From b871eabaf65322e54507c7c8e3aae1db3aa9aa66 Mon Sep 17 00:00:00 2001 From: Debugger022 Date: Wed, 13 Sep 2023 13:47:10 +0530 Subject: [PATCH 01/33] feat: ven-1930 force liquidation --- contracts/Comptroller.sol | 23 ++++++++++- contracts/ComptrollerStorage.sol | 5 ++- .../Comptroller/liquidateAccountTest.ts | 38 ++++++++++++++++++- 3 files changed, 63 insertions(+), 3 deletions(-) diff --git a/contracts/Comptroller.sol b/contracts/Comptroller.sol index 9d2de5830..75d88f7db 100644 --- a/contracts/Comptroller.sol +++ b/contracts/Comptroller.sol @@ -91,6 +91,9 @@ contract Comptroller is /// @notice Emitted when a market is supported event MarketSupported(VToken vToken); + /// @notice Emitted when forced liquidation is enabled or disabled for a market + event IsForcedLiquidationEnabledUpdated(address indexed vToken, bool enable); + /// @notice Thrown when collateral factor exceeds the upper bound error InvalidCollateralFactor(); @@ -475,7 +478,7 @@ contract Comptroller is uint256 borrowBalance = VToken(vTokenBorrowed).borrowBalanceStored(borrower); /* Allow accounts to be liquidated if the market is deprecated or it is a forced liquidation */ - if (skipLiquidityCheck || isDeprecated(VToken(vTokenBorrowed))) { + if (skipLiquidityCheck || isDeprecated(VToken(vTokenBorrowed)) || isForcedLiquidationEnabled[vTokenBorrowed]) { if (repayAmount > borrowBalance) { revert TooMuchRepay(); } @@ -1004,6 +1007,24 @@ contract Comptroller is _setMaxLoopsLimit(limit); } + /** + * @notice Enables forced liquidations for a market. If forced liquidation is enabled, + * borrows in the market may be liquidated regardless of the account liquidity + * @param vTokenBorrowed Borrowed vToken + * @param enable Whether to enable forced liquidations + */ + function setForcedLiquidation(address vTokenBorrowed, bool enable) external { + _checkAccessAllowed("setForcedLiquidation(address,bool)"); + ensureNonzeroAddress(vTokenBorrowed); + + if (!markets[vTokenBorrowed].isListed) { + revert MarketNotListed(vTokenBorrowed); + } + + isForcedLiquidationEnabled[address(vTokenBorrowed)] = enable; + emit IsForcedLiquidationEnabledUpdated(vTokenBorrowed, enable); + } + /** * @notice Determine the current account liquidity with respect to liquidation threshold requirements * @dev The interface of this function is intentionally kept compatible with Compound and Venus Core diff --git a/contracts/ComptrollerStorage.sol b/contracts/ComptrollerStorage.sol index b710ca4a4..af90d8d23 100644 --- a/contracts/ComptrollerStorage.sol +++ b/contracts/ComptrollerStorage.sol @@ -118,10 +118,13 @@ contract ComptrollerStorage { // No collateralFactorMantissa may exceed this value uint256 internal constant MAX_COLLATERAL_FACTOR_MANTISSA = 0.9e18; // 0.9 + /// @notice Flag indicating whether forced liquidation enabled for a market + mapping(address => bool) public isForcedLiquidationEnabled; + /** * @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[50] private __gap; + uint256[49] private __gap; } diff --git a/tests/hardhat/Comptroller/liquidateAccountTest.ts b/tests/hardhat/Comptroller/liquidateAccountTest.ts index 5c32ff465..cdaf06a81 100644 --- a/tests/hardhat/Comptroller/liquidateAccountTest.ts +++ b/tests/hardhat/Comptroller/liquidateAccountTest.ts @@ -53,6 +53,7 @@ describe("liquidateAccount", () => { let OMG: FakeContract; let ZRX: FakeContract; let BAT: FakeContract; + let accessControl: FakeContract; const maxLoopsLimit = 150; type LiquidateAccountFixture = { @@ -113,7 +114,7 @@ describe("liquidateAccount", () => { [, liquidator, user] = await ethers.getSigners(); const contracts = await loadFixture(liquidateAccountFixture); configure(contracts); - ({ comptroller, OMG, ZRX, BAT } = contracts); + ({ comptroller, OMG, ZRX, BAT, accessControl } = contracts); }); describe("collateral to borrows ratio requirements", async () => { @@ -342,4 +343,39 @@ describe("liquidateAccount", () => { ); }); }); + + describe("setForcedLiquidation", async () => { + it("fails if asset is not listed", async () => { + const someVToken = await smock.fake("VToken"); + await expect(comptroller.setForcedLiquidation(someVToken.address, true)).to.be.revertedWithCustomError( + comptroller, + "MarketNotListed", + ); + }); + + it("fails if ACM does not allow the call", async () => { + accessControl.isAllowedToCall.returns(false); + await expect(comptroller.setForcedLiquidation(OMG.address, true)).to.be.revertedWithCustomError( + comptroller, + "Unauthorized", + ); + accessControl.isAllowedToCall.returns(true); + }); + + it("sets forced liquidation", async () => { + await comptroller.setForcedLiquidation(OMG.address, true); + expect(await comptroller.isForcedLiquidationEnabled(OMG.address)).to.be.true; + + await comptroller.setForcedLiquidation(OMG.address, false); + expect(await comptroller.isForcedLiquidationEnabled(OMG.address)).to.be.false; + }); + + it("emits IsForcedLiquidationEnabledUpdated event", async () => { + const tx1 = await comptroller.setForcedLiquidation(OMG.address, true); + await expect(tx1).to.emit(comptroller, "IsForcedLiquidationEnabledUpdated").withArgs(OMG.address, true); + + const tx2 = await comptroller.setForcedLiquidation(OMG.address, false); + await expect(tx2).to.emit(comptroller, "IsForcedLiquidationEnabledUpdated").withArgs(OMG.address, false); + }); + }); }); From e062119483c18ddea4e0a3ab399179867a89188a Mon Sep 17 00:00:00 2001 From: Debugger022 Date: Wed, 13 Sep 2023 16:50:59 +0530 Subject: [PATCH 02/33] tests: pre liquidate hook --- .../Comptroller/liquidateAccountTest.ts | 90 +++++++++++++++++++ 1 file changed, 90 insertions(+) diff --git a/tests/hardhat/Comptroller/liquidateAccountTest.ts b/tests/hardhat/Comptroller/liquidateAccountTest.ts index cdaf06a81..e5b006e14 100644 --- a/tests/hardhat/Comptroller/liquidateAccountTest.ts +++ b/tests/hardhat/Comptroller/liquidateAccountTest.ts @@ -378,4 +378,94 @@ describe("liquidateAccount", () => { await expect(tx2).to.emit(comptroller, "IsForcedLiquidationEnabledUpdated").withArgs(OMG.address, false); }); }); + + describe("preLiquidateHook", async () => { + let accounts: SignerWithAddress[]; + + before(async () => { + accounts = await ethers.getSigners(); + }); + const generalTests = () => { + it("reverts if borrowed market is not listed", async () => { + const someVToken = await smock.fake("VToken"); + await expect( + comptroller.preLiquidateHook( + someVToken.address, + OMG.address, + accounts[0].address, + parseUnits("1", 18), + false, + ), + ).to.be.revertedWithCustomError(comptroller, "MarketNotListed"); + }); + + it("reverts if collateral market is not listed", async () => { + const someVToken = await smock.fake("VToken"); + await expect( + comptroller.preLiquidateHook( + OMG.address, + someVToken.address, + accounts[0].address, + parseUnits("1", 18), + false, + ), + ).to.be.revertedWithCustomError(comptroller, "MarketNotListed"); + }); + }; + + describe("isForcedLiquidationEnabled == true", async () => { + beforeEach(async () => { + await comptroller.setForcedLiquidation(OMG.address, true); + }); + + generalTests(); + + it("allows liquidations without shortfall", async () => { + OMG.borrowBalanceStored.returns(parseUnits("100", 18)); + await comptroller.callStatic.preLiquidateHook( + OMG.address, + OMG.address, + accounts[0].address, + parseUnits("1", 18), + true, + ); + }); + + it("allows to repay 100% of the borrow", async () => { + OMG.borrowBalanceStored.returns(parseUnits("1", 18)); + await comptroller.callStatic.preLiquidateHook( + OMG.address, + OMG.address, + accounts[0].address, + parseUnits("1", 18), + false, + ); + }); + + it("fails with TOO_MUCH_REPAY if trying to repay > borrowed amount", async () => { + OMG.borrowBalanceStored.returns(parseUnits("0.99", 18)); + const tx = comptroller.callStatic.preLiquidateHook( + OMG.address, + OMG.address, + accounts[0].address, + parseUnits("1", 18), + false, + ); + await expect(tx).to.be.revertedWithCustomError(comptroller, "TooMuchRepay"); + }); + + it("checks the shortfall if isForcedLiquidationEnabled is set back to false", async () => { + await comptroller.setForcedLiquidation(OMG.address, false); + OMG.borrowBalanceStored.returns(parseUnits("100", 18)); + const tx = comptroller.callStatic.preLiquidateHook( + OMG.address, + OMG.address, + accounts[0].address, + parseUnits("1", 18), + false, + ); + await expect(tx).to.be.revertedWithCustomError(comptroller, "MinimalCollateralViolated"); + }); + }); + }); }); From cbd9b18a99c4e1f92bf9404e88fceb8ebc36d55f Mon Sep 17 00:00:00 2001 From: Debugger022 Date: Fri, 15 Sep 2023 16:58:20 +0530 Subject: [PATCH 03/33] fix: pr comments --- contracts/Comptroller.sol | 15 +- contracts/ComptrollerStorage.sol | 6 +- .../Comptroller/liquidateAccountTest.ts | 132 ++++++++---------- 3 files changed, 60 insertions(+), 93 deletions(-) diff --git a/contracts/Comptroller.sol b/contracts/Comptroller.sol index 75d88f7db..33a4fe45c 100644 --- a/contracts/Comptroller.sol +++ b/contracts/Comptroller.sol @@ -478,7 +478,7 @@ contract Comptroller is uint256 borrowBalance = VToken(vTokenBorrowed).borrowBalanceStored(borrower); /* Allow accounts to be liquidated if the market is deprecated or it is a forced liquidation */ - if (skipLiquidityCheck || isDeprecated(VToken(vTokenBorrowed)) || isForcedLiquidationEnabled[vTokenBorrowed]) { + if (skipLiquidityCheck || isForcedLiquidationEnabled[vTokenBorrowed]) { if (repayAmount > borrowBalance) { revert TooMuchRepay(); } @@ -1244,19 +1244,6 @@ contract Comptroller is return _actionPaused[market][action]; } - /** - * @notice Check if a vToken market has been deprecated - * @dev All borrows in a deprecated vToken market can be immediately liquidated - * @param vToken The market to check if deprecated - * @return deprecated True if the given vToken market has been deprecated - */ - function isDeprecated(VToken vToken) public view returns (bool) { - return - markets[address(vToken)].collateralFactorMantissa == 0 && - actionPaused(address(vToken), Action.BORROW) && - vToken.reserveFactorMantissa() == MANTISSA_ONE; - } - /** * @notice Add the market to the borrower's "assets in" for liquidity calculations * @param vToken The market to enter diff --git a/contracts/ComptrollerStorage.sol b/contracts/ComptrollerStorage.sol index af90d8d23..6732a6349 100644 --- a/contracts/ComptrollerStorage.sol +++ b/contracts/ComptrollerStorage.sol @@ -107,6 +107,9 @@ contract ComptrollerStorage { // Used to check if rewards distributor is added mapping(address => bool) internal rewardsDistributorExists; + /// @notice Flag indicating whether forced liquidation enabled for a market + mapping(address => bool) public isForcedLiquidationEnabled; + uint256 internal constant NO_ERROR = 0; // closeFactorMantissa must be strictly greater than this value @@ -118,9 +121,6 @@ contract ComptrollerStorage { // No collateralFactorMantissa may exceed this value uint256 internal constant MAX_COLLATERAL_FACTOR_MANTISSA = 0.9e18; // 0.9 - /// @notice Flag indicating whether forced liquidation enabled for a market - mapping(address => bool) public isForcedLiquidationEnabled; - /** * @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. diff --git a/tests/hardhat/Comptroller/liquidateAccountTest.ts b/tests/hardhat/Comptroller/liquidateAccountTest.ts index e5b006e14..75fbd4f06 100644 --- a/tests/hardhat/Comptroller/liquidateAccountTest.ts +++ b/tests/hardhat/Comptroller/liquidateAccountTest.ts @@ -382,90 +382,70 @@ describe("liquidateAccount", () => { describe("preLiquidateHook", async () => { let accounts: SignerWithAddress[]; - before(async () => { + beforeEach(async () => { accounts = await ethers.getSigners(); + await comptroller.setForcedLiquidation(OMG.address, true); }); - const generalTests = () => { - it("reverts if borrowed market is not listed", async () => { - const someVToken = await smock.fake("VToken"); - await expect( - comptroller.preLiquidateHook( - someVToken.address, - OMG.address, - accounts[0].address, - parseUnits("1", 18), - false, - ), - ).to.be.revertedWithCustomError(comptroller, "MarketNotListed"); - }); - it("reverts if collateral market is not listed", async () => { - const someVToken = await smock.fake("VToken"); - await expect( - comptroller.preLiquidateHook( - OMG.address, - someVToken.address, - accounts[0].address, - parseUnits("1", 18), - false, - ), - ).to.be.revertedWithCustomError(comptroller, "MarketNotListed"); - }); - }; + it("reverts if borrowed market is not listed", async () => { + const someVToken = await smock.fake("VToken"); + await expect( + comptroller.preLiquidateHook(someVToken.address, OMG.address, accounts[0].address, parseUnits("1", 18), false), + ).to.be.revertedWithCustomError(comptroller, "MarketNotListed"); + }); - describe("isForcedLiquidationEnabled == true", async () => { - beforeEach(async () => { - await comptroller.setForcedLiquidation(OMG.address, true); - }); + it("reverts if collateral market is not listed", async () => { + const someVToken = await smock.fake("VToken"); + await expect( + comptroller.preLiquidateHook(OMG.address, someVToken.address, accounts[0].address, parseUnits("1", 18), false), + ).to.be.revertedWithCustomError(comptroller, "MarketNotListed"); + }); - generalTests(); - - it("allows liquidations without shortfall", async () => { - OMG.borrowBalanceStored.returns(parseUnits("100", 18)); - await comptroller.callStatic.preLiquidateHook( - OMG.address, - OMG.address, - accounts[0].address, - parseUnits("1", 18), - true, - ); - }); + it("allows liquidations without shortfall", async () => { + OMG.borrowBalanceStored.returns(parseUnits("100", 18)); + await comptroller.callStatic.preLiquidateHook( + OMG.address, + OMG.address, + accounts[0].address, + parseUnits("1", 18), + true, + ); + }); - it("allows to repay 100% of the borrow", async () => { - OMG.borrowBalanceStored.returns(parseUnits("1", 18)); - await comptroller.callStatic.preLiquidateHook( - OMG.address, - OMG.address, - accounts[0].address, - parseUnits("1", 18), - false, - ); - }); + it("allows to repay 100% of the borrow", async () => { + OMG.borrowBalanceStored.returns(parseUnits("1", 18)); + await comptroller.callStatic.preLiquidateHook( + OMG.address, + OMG.address, + accounts[0].address, + parseUnits("1", 18), + false, + ); + }); - it("fails with TOO_MUCH_REPAY if trying to repay > borrowed amount", async () => { - OMG.borrowBalanceStored.returns(parseUnits("0.99", 18)); - const tx = comptroller.callStatic.preLiquidateHook( - OMG.address, - OMG.address, - accounts[0].address, - parseUnits("1", 18), - false, - ); - await expect(tx).to.be.revertedWithCustomError(comptroller, "TooMuchRepay"); - }); + it("fails with TOO_MUCH_REPAY if trying to repay > borrowed amount", async () => { + OMG.borrowBalanceStored.returns(parseUnits("0.99", 18)); + const tx = comptroller.callStatic.preLiquidateHook( + OMG.address, + OMG.address, + accounts[0].address, + parseUnits("1", 18), + false, + ); + await expect(tx).to.be.revertedWithCustomError(comptroller, "TooMuchRepay"); + }); - it("checks the shortfall if isForcedLiquidationEnabled is set back to false", async () => { - await comptroller.setForcedLiquidation(OMG.address, false); - OMG.borrowBalanceStored.returns(parseUnits("100", 18)); - const tx = comptroller.callStatic.preLiquidateHook( - OMG.address, - OMG.address, - accounts[0].address, - parseUnits("1", 18), - false, - ); - await expect(tx).to.be.revertedWithCustomError(comptroller, "MinimalCollateralViolated"); - }); + it("checks the shortfall if isForcedLiquidationEnabled is set back to false", async () => { + await comptroller.setForcedLiquidation(OMG.address, false); + OMG.borrowBalanceStored.returns(parseUnits("100", 18)); + const tx = comptroller.callStatic.preLiquidateHook( + OMG.address, + OMG.address, + accounts[0].address, + parseUnits("1", 18), + false, + ); + await expect(tx).to.be.revertedWithCustomError(comptroller, "MinimalCollateralViolated"); }); }); }); From c713dd7decd36d87d4ad03cbb04d9419996aacc6 Mon Sep 17 00:00:00 2001 From: Kirill Kuvshinov Date: Thu, 21 Sep 2023 13:49:23 +0300 Subject: [PATCH 04/33] refactor: remove Compound's scenario tests Problem: We've inherited a scenario test suite from Compound that was useful in initial phases of development. However, these tests are hard to maintain due to outdated toolset and a custom DSL used in these tests. Scenario tests were not maintained, a separate set of integration tests were implemented instead. There is no reason to keep this folder in the repo. Solution: Remove scenario tests. --- scenario/Grammar.pegjs | 318 - scenario/SCENARIO.md | 219 - scenario/package.json | 34 - scenario/script/generate_parser | 13 - scenario/script/repl | 59 - scenario/script/tsc | 43 - scenario/script/webpack | 18 - scenario/src/Accounts.ts | 49 - scenario/src/Action.ts | 15 - scenario/src/Assert.ts | 19 - scenario/src/Builder/CTokenBuilder.ts | 408 - scenario/src/Builder/CTokenDelegateBuilder.ts | 156 - scenario/src/Builder/CompBuilder.ts | 110 - .../src/Builder/ComptrollerImplBuilder.ts | 367 - scenario/src/Builder/Erc20Builder.ts | 271 - .../src/Builder/InterestRateModelBuilder.ts | 219 - scenario/src/Builder/PriceOracleBuilder.ts | 165 - .../src/Builder/PriceOracleProxyBuilder.ts | 77 - scenario/src/Builder/UnitrollerBuilder.ts | 58 - scenario/src/Command.ts | 248 - scenario/src/Completer.ts | 36 - scenario/src/Contract.ts | 207 - scenario/src/Contract/AnchoredView.ts | 10 - scenario/src/Contract/CErc20Delegate.ts | 23 - scenario/src/Contract/CErc20Delegator.ts | 28 - scenario/src/Contract/CToken.ts | 66 - scenario/src/Contract/Comp.ts | 41 - scenario/src/Contract/Comptroller.ts | 81 - scenario/src/Contract/ComptrollerImpl.ts | 24 - scenario/src/Contract/Counter.ts | 12 - scenario/src/Contract/Erc20.ts | 25 - scenario/src/Contract/InterestRateModel.ts | 12 - scenario/src/Contract/Pot.ts | 19 - scenario/src/Contract/PriceOracle.ts | 30 - scenario/src/Contract/PriceOracleProxy.ts | 13 - scenario/src/Contract/Reservoir.ts | 17 - scenario/src/Contract/Timelock.ts | 43 - scenario/src/Contract/Unitroller.ts | 16 - scenario/src/Contract/Vat.ts | 14 - scenario/src/Contract/builder.js | 63 - scenario/src/ContractLookup.ts | 224 - scenario/src/CoreEvent.ts | 826 -- scenario/src/CoreValue.ts | 977 -- scenario/src/Encoding.ts | 18 - scenario/src/ErrorReporter.ts | 121 - scenario/src/ErrorReporterConstants.ts | 243 - scenario/src/Event.ts | 7 - scenario/src/Event/AssertionEvent.ts | 509 - scenario/src/Event/CTokenDelegateEvent.ts | 86 - scenario/src/Event/CTokenEvent.ts | 934 -- scenario/src/Event/CompEvent.ts | 270 - scenario/src/Event/ComptrollerEvent.ts | 926 -- scenario/src/Event/ComptrollerImplEvent.ts | 493 - scenario/src/Event/Erc20Event.ts | 282 - scenario/src/Event/ExpectationEvent.ts | 70 - scenario/src/Event/InterestRateModelEvent.ts | 84 - scenario/src/Event/InvariantEvent.ts | 83 - scenario/src/Event/PriceOracleEvent.ts | 146 - scenario/src/Event/PriceOracleProxyEvent.ts | 104 - scenario/src/Event/TrxEvent.ts | 56 - scenario/src/Event/UnitrollerEvent.ts | 152 - scenario/src/EventBuilder.ts | 310 - scenario/src/Expectation.ts | 4 - .../src/Expectation/ChangesExpectation.ts | 52 - .../src/Expectation/RemainsExpectation.ts | 32 - scenario/src/File.ts | 39 - scenario/src/Formatter.ts | 25 - scenario/src/Help.ts | 64 - scenario/src/HistoricReadline.ts | 35 - scenario/src/Hypothetical.ts | 36 - scenario/src/Invariant.ts | 5 - scenario/src/Invariant/RemainsInvariant.ts | 33 - scenario/src/Invariant/StaticInvariant.ts | 33 - scenario/src/Invariant/SuccessInvariant.ts | 21 - scenario/src/Invokation.ts | 320 - scenario/src/Macro.ts | 98 - scenario/src/Networks.ts | 202 - scenario/src/Parser.ts | 3210 ---- scenario/src/Printer.ts | 120 - scenario/src/Repl.d.ts | 9 - scenario/src/Repl.ts | 188 - scenario/src/Runner.ts | 20 - scenario/src/Settings.ts | 85 - scenario/src/Utils.ts | 133 - scenario/src/Value.ts | 424 - scenario/src/Value/AnchoredViewValue.ts | 36 - scenario/src/Value/CTokenDelegateValue.ts | 51 - scenario/src/Value/CTokenValue.ts | 395 - scenario/src/Value/CompValue.ts | 202 - scenario/src/Value/ComptrollerImplValue.ts | 35 - scenario/src/Value/ComptrollerValue.ts | 652 - scenario/src/Value/Erc20Value.ts | 160 - scenario/src/Value/InterestRateModelValue.ts | 60 - scenario/src/Value/MCDValue.ts | 65 - scenario/src/Value/PriceOracleProxyValue.ts | 67 - scenario/src/Value/PriceOracleValue.ts | 52 - scenario/src/Value/UnitrollerValue.ts | 89 - scenario/src/Value/UserValue.ts | 36 - scenario/src/Verify.ts | 157 - scenario/src/Web.ts | 87 - scenario/src/World.ts | 356 - scenario/tsconfig.json | 63 - scenario/webpack.config.js | 28 - scenario/yarn.lock | 12154 ---------------- spec/scenario/AddReserves.scen | 138 - spec/scenario/Borrow.scen | 116 - spec/scenario/BorrowBalance.scen | 88 - spec/scenario/BorrowCap.scen | 182 - spec/scenario/BorrowEth.scen | 52 - spec/scenario/BorrowWBTC.scen | 71 - spec/scenario/BreakLiquidate.scen | 84 - spec/scenario/CTokenAdmin.scen | 43 - spec/scenario/ChangeDelegate.scen | 12 - spec/scenario/Comp/Comp.scen | 300 - spec/scenario/CoreMacros | 258 - spec/scenario/EnterExitMarkets.scen | 142 - spec/scenario/ExchangeRate.scen | 76 - spec/scenario/Fee.scen | 102 - .../HypotheticalAccountLiquidity.scen | 53 - spec/scenario/InKindLiquidation.scen | 443 - spec/scenario/MCDai.scen | 168 - spec/scenario/Mint.scen | 114 - spec/scenario/MintEth.scen | 72 - spec/scenario/MintWBTC.scen | 101 - spec/scenario/PriceOracleProxy.scen | 53 - spec/scenario/ReEntry.scen | 13 - spec/scenario/Redeem.scen | 239 - spec/scenario/RedeemEth.scen | 164 - spec/scenario/RedeemUnderlying.scen | 191 - spec/scenario/RedeemUnderlyingEth.scen | 179 - spec/scenario/RedeemUnderlyingWBTC.scen | 192 - spec/scenario/RedeemWBTC.scen | 238 - spec/scenario/ReduceReserves.scen | 140 - spec/scenario/RepayBorrow.scen | 175 - spec/scenario/RepayBorrowEth.scen | 135 - spec/scenario/RepayBorrowWBTC.scen | 193 - spec/scenario/Seize.scen | 59 - spec/scenario/SetComptroller.scen | 29 - spec/scenario/SweepToken.scen | 32 - spec/scenario/TokenTransfer.scen | 115 - spec/scenario/Unitroller.scen | 277 - 141 files changed, 35539 deletions(-) delete mode 100644 scenario/Grammar.pegjs delete mode 100644 scenario/SCENARIO.md delete mode 100644 scenario/package.json delete mode 100755 scenario/script/generate_parser delete mode 100755 scenario/script/repl delete mode 100755 scenario/script/tsc delete mode 100755 scenario/script/webpack delete mode 100644 scenario/src/Accounts.ts delete mode 100644 scenario/src/Action.ts delete mode 100644 scenario/src/Assert.ts delete mode 100644 scenario/src/Builder/CTokenBuilder.ts delete mode 100644 scenario/src/Builder/CTokenDelegateBuilder.ts delete mode 100644 scenario/src/Builder/CompBuilder.ts delete mode 100644 scenario/src/Builder/ComptrollerImplBuilder.ts delete mode 100644 scenario/src/Builder/Erc20Builder.ts delete mode 100644 scenario/src/Builder/InterestRateModelBuilder.ts delete mode 100644 scenario/src/Builder/PriceOracleBuilder.ts delete mode 100644 scenario/src/Builder/PriceOracleProxyBuilder.ts delete mode 100644 scenario/src/Builder/UnitrollerBuilder.ts delete mode 100644 scenario/src/Command.ts delete mode 100644 scenario/src/Completer.ts delete mode 100644 scenario/src/Contract.ts delete mode 100644 scenario/src/Contract/AnchoredView.ts delete mode 100644 scenario/src/Contract/CErc20Delegate.ts delete mode 100644 scenario/src/Contract/CErc20Delegator.ts delete mode 100644 scenario/src/Contract/CToken.ts delete mode 100644 scenario/src/Contract/Comp.ts delete mode 100644 scenario/src/Contract/Comptroller.ts delete mode 100644 scenario/src/Contract/ComptrollerImpl.ts delete mode 100644 scenario/src/Contract/Counter.ts delete mode 100644 scenario/src/Contract/Erc20.ts delete mode 100644 scenario/src/Contract/InterestRateModel.ts delete mode 100644 scenario/src/Contract/Pot.ts delete mode 100644 scenario/src/Contract/PriceOracle.ts delete mode 100644 scenario/src/Contract/PriceOracleProxy.ts delete mode 100644 scenario/src/Contract/Reservoir.ts delete mode 100644 scenario/src/Contract/Timelock.ts delete mode 100644 scenario/src/Contract/Unitroller.ts delete mode 100644 scenario/src/Contract/Vat.ts delete mode 100644 scenario/src/Contract/builder.js delete mode 100644 scenario/src/ContractLookup.ts delete mode 100644 scenario/src/CoreEvent.ts delete mode 100644 scenario/src/CoreValue.ts delete mode 100644 scenario/src/Encoding.ts delete mode 100644 scenario/src/ErrorReporter.ts delete mode 100644 scenario/src/ErrorReporterConstants.ts delete mode 100644 scenario/src/Event.ts delete mode 100644 scenario/src/Event/AssertionEvent.ts delete mode 100644 scenario/src/Event/CTokenDelegateEvent.ts delete mode 100644 scenario/src/Event/CTokenEvent.ts delete mode 100644 scenario/src/Event/CompEvent.ts delete mode 100644 scenario/src/Event/ComptrollerEvent.ts delete mode 100644 scenario/src/Event/ComptrollerImplEvent.ts delete mode 100644 scenario/src/Event/Erc20Event.ts delete mode 100644 scenario/src/Event/ExpectationEvent.ts delete mode 100644 scenario/src/Event/InterestRateModelEvent.ts delete mode 100644 scenario/src/Event/InvariantEvent.ts delete mode 100644 scenario/src/Event/PriceOracleEvent.ts delete mode 100644 scenario/src/Event/PriceOracleProxyEvent.ts delete mode 100644 scenario/src/Event/TrxEvent.ts delete mode 100644 scenario/src/Event/UnitrollerEvent.ts delete mode 100644 scenario/src/EventBuilder.ts delete mode 100644 scenario/src/Expectation.ts delete mode 100644 scenario/src/Expectation/ChangesExpectation.ts delete mode 100644 scenario/src/Expectation/RemainsExpectation.ts delete mode 100644 scenario/src/File.ts delete mode 100644 scenario/src/Formatter.ts delete mode 100644 scenario/src/Help.ts delete mode 100644 scenario/src/HistoricReadline.ts delete mode 100644 scenario/src/Hypothetical.ts delete mode 100644 scenario/src/Invariant.ts delete mode 100644 scenario/src/Invariant/RemainsInvariant.ts delete mode 100644 scenario/src/Invariant/StaticInvariant.ts delete mode 100644 scenario/src/Invariant/SuccessInvariant.ts delete mode 100644 scenario/src/Invokation.ts delete mode 100644 scenario/src/Macro.ts delete mode 100644 scenario/src/Networks.ts delete mode 100644 scenario/src/Parser.ts delete mode 100644 scenario/src/Printer.ts delete mode 100644 scenario/src/Repl.d.ts delete mode 100644 scenario/src/Repl.ts delete mode 100644 scenario/src/Runner.ts delete mode 100644 scenario/src/Settings.ts delete mode 100644 scenario/src/Utils.ts delete mode 100644 scenario/src/Value.ts delete mode 100644 scenario/src/Value/AnchoredViewValue.ts delete mode 100644 scenario/src/Value/CTokenDelegateValue.ts delete mode 100644 scenario/src/Value/CTokenValue.ts delete mode 100644 scenario/src/Value/CompValue.ts delete mode 100644 scenario/src/Value/ComptrollerImplValue.ts delete mode 100644 scenario/src/Value/ComptrollerValue.ts delete mode 100644 scenario/src/Value/Erc20Value.ts delete mode 100644 scenario/src/Value/InterestRateModelValue.ts delete mode 100644 scenario/src/Value/MCDValue.ts delete mode 100644 scenario/src/Value/PriceOracleProxyValue.ts delete mode 100644 scenario/src/Value/PriceOracleValue.ts delete mode 100644 scenario/src/Value/UnitrollerValue.ts delete mode 100644 scenario/src/Value/UserValue.ts delete mode 100644 scenario/src/Verify.ts delete mode 100644 scenario/src/Web.ts delete mode 100644 scenario/src/World.ts delete mode 100644 scenario/tsconfig.json delete mode 100644 scenario/webpack.config.js delete mode 100644 scenario/yarn.lock delete mode 100644 spec/scenario/AddReserves.scen delete mode 100644 spec/scenario/Borrow.scen delete mode 100644 spec/scenario/BorrowBalance.scen delete mode 100644 spec/scenario/BorrowCap.scen delete mode 100644 spec/scenario/BorrowEth.scen delete mode 100644 spec/scenario/BorrowWBTC.scen delete mode 100644 spec/scenario/BreakLiquidate.scen delete mode 100644 spec/scenario/CTokenAdmin.scen delete mode 100644 spec/scenario/ChangeDelegate.scen delete mode 100644 spec/scenario/Comp/Comp.scen delete mode 100644 spec/scenario/CoreMacros delete mode 100644 spec/scenario/EnterExitMarkets.scen delete mode 100644 spec/scenario/ExchangeRate.scen delete mode 100644 spec/scenario/Fee.scen delete mode 100644 spec/scenario/HypotheticalAccountLiquidity.scen delete mode 100644 spec/scenario/InKindLiquidation.scen delete mode 100644 spec/scenario/MCDai.scen delete mode 100644 spec/scenario/Mint.scen delete mode 100644 spec/scenario/MintEth.scen delete mode 100644 spec/scenario/MintWBTC.scen delete mode 100644 spec/scenario/PriceOracleProxy.scen delete mode 100644 spec/scenario/ReEntry.scen delete mode 100644 spec/scenario/Redeem.scen delete mode 100644 spec/scenario/RedeemEth.scen delete mode 100644 spec/scenario/RedeemUnderlying.scen delete mode 100644 spec/scenario/RedeemUnderlyingEth.scen delete mode 100644 spec/scenario/RedeemUnderlyingWBTC.scen delete mode 100644 spec/scenario/RedeemWBTC.scen delete mode 100644 spec/scenario/ReduceReserves.scen delete mode 100644 spec/scenario/RepayBorrow.scen delete mode 100644 spec/scenario/RepayBorrowEth.scen delete mode 100644 spec/scenario/RepayBorrowWBTC.scen delete mode 100644 spec/scenario/Seize.scen delete mode 100644 spec/scenario/SetComptroller.scen delete mode 100644 spec/scenario/SweepToken.scen delete mode 100644 spec/scenario/TokenTransfer.scen delete mode 100644 spec/scenario/Unitroller.scen diff --git a/scenario/Grammar.pegjs b/scenario/Grammar.pegjs deleted file mode 100644 index 30bb16dbd..000000000 --- a/scenario/Grammar.pegjs +++ /dev/null @@ -1,318 +0,0 @@ -// See: https://pegjs.org/online - -// Scenario Grammar - -{ - if (!Array.prototype.flat) { - Object.defineProperty(Array.prototype, 'flat', { - configurable: true, - value: function flat (x) { - var depth = isNaN(arguments[0]) ? 1 : Number(arguments[0]); - - return depth ? Array.prototype.reduce.call(this, function (acc, cur) { - if (Array.isArray(cur)) { - acc.push.apply(acc, flat.call(cur, depth - 1)); - } else { - acc.push(cur); - } - - return acc; - }, []) : Array.prototype.slice.call(this); - }, - writable: true - }); - } - - function getString(str) { - let val; - if (Array.isArray(str)) { - if (str.length !== 2 || str[0] !== 'String') { - throw new Error(`Expected string, got ${str}`); - } - - val = str[1]; - } else { - val = str; - } - - if (typeof val !== 'string') { - throw new Error(`Expected string, got ${val} (${typeof val})`); - } - - return val; - } - - function expandEvent(macros, step) { - const [eventName, ...eventArgs] = step; - - if (macros[eventName]) { - let expanded = expandMacro(macros[eventName], eventArgs); - - // Recursively expand steps - return expanded.map(event => expandEvent(macros, event)).flat(); - } else { - return [step]; - } - } - - function getArgValues(eventArgs, macroArgs) { - const eventArgNameMap = {}; - const eventArgIndexed = new Array(); - const argValues = {}; - let usedNamedArg = false; - let usedSplat = false; - - eventArgs.forEach((eventArg) => { - if (eventArg.argName) { - const {argName, argValue} = eventArg; - - eventArgNameMap[argName] = argValue; - usedNamedArg = true; - } else { - if (usedNamedArg) { - throw new Error(`Cannot use positional arg after named arg in macro invokation ${JSON.stringify(eventArgs)} looking at ${eventArg.toString()}`); - } - - eventArgIndexed.push(eventArg); - } - }); - - macroArgs.forEach(({arg, def, splat}, argIndex) => { - if (usedSplat) { - throw new Error("Cannot have arg after splat arg"); - } - - let val; - if (eventArgNameMap[arg] !== undefined) { - val = eventArgNameMap[arg]; - } else if (splat) { - val = eventArgIndexed.slice(argIndex); // Clear out any remaining args - usedSplat = true; - } else if (eventArgIndexed[argIndex] !== undefined) { - val = eventArgIndexed[argIndex]; - } else if (def !== undefined) { - val = def; - } else { - throw new Error("Macro cannot find arg value for " + arg); - } - argValues[arg] = val; - }); - - return argValues; - } - - function expandMacro(macro, eventArgs) { - const argValues = getArgValues(eventArgs, macro.args); - - function expandStep(step) { - return step.map((token) => { - if (argValues[token] !== undefined) { - return argValues[token]; - } else { - if (Array.isArray(token)) { - return expandStep(token); - } else { - return token; - } - } - }); - }; - - return macro.steps.map(expandStep); - } - - function addTopLevelEl(state, el) { - const macros = state.macros; - const tests = state.tests; - const pending = state.pending; - - switch (el.type) { - case 'macro': - const macro = {[el.name]: {args: el.args, steps: el.steps}}; - - return { - tests: tests, - macros: ({...macros, ...macro}) - }; - case 'test': - const steps = el.steps; - const expandedSteps = steps.map((step) => { - return expandEvent(macros, step) - }).flat(); - - const test = {[el.test]: expandedSteps}; - - return { - tests: {...tests, ...test}, - macros: macros - } - } - } -} - -tests - = values:( - head:top_level_el - tail:(line_separator t:top_level_el { return t; })* - { return tail.reduce((acc, el) => addTopLevelEl(acc, el), addTopLevelEl({macros: {}, tests: {}}, head)); } - )? - full_ws - { return values !== null ? values.tests : {}; } - -macros - = values:( - head:top_level_el - tail:(line_separator t:top_level_el { return t; })* - { return tail.reduce((acc, el) => addTopLevelEl(acc, el), addTopLevelEl({macros: {}, tests: {}}, head)); } - )? - full_ws - { return values !== null ? values.macros : {}; } - -top_level_el - = test - / macro - / gastest - / pending - / only - / skip - -test - = full_ws? "Test" ws name:string ws line_separator steps:steps? { return {type: 'test', test: getString(name), steps: steps}; } - -gastest - = full_ws? "GasTest" ws name:string ws line_separator steps:steps? { return {type: 'test', test: getString(name), steps: ["Gas"].concat(steps)}; } - -pending - = full_ws? "Pending" ws name:string ws line_separator steps:steps? { return {type: 'test', test: getString(name), steps: ["Pending"].concat(steps)}; } - -only - = full_ws? "Only" ws name:string ws line_separator steps:steps? { return {type: 'test', test: getString(name), steps: ["Only"].concat(steps)}; } - -skip - = full_ws? "Skip" ws name:string ws line_separator steps:steps? { return {type: 'test', test: getString(name), steps: ["Skip"].concat(steps)}; } - -macro - = full_ws? "Macro" ws name:token ws args:args? line_separator steps:steps { return {type: 'macro', name: getString(name), args: args || [], steps: steps}; } - -args - = args:( - head:arg - tail:(ws t:args { return t; })* - { return [head].concat(tail).filter((x) => !!x); } - ) - { return args !== null ? args.flat() : []; } - -arg - = splat:("..."?) arg:token def:(ws? "=" t:token ws? { return t; })? { return { arg, def, splat }; } - -token_set - = tokens:( - head:token - tail:(ws t:token_set { return t; })* - { return [head].concat(tail).filter((x) => !!x); } - ) - { return tokens !== null ? tokens.flat() : []; } - -steps - = steps:( - head:full_expr - tail:(line_separator step:full_expr { return step; })* - { return [head].concat(tail).filter((x) => !!x); } - )? - { return steps !== null ? steps : []; } - -full_expr - = tab_separator step:step { return step; } - / comment { return null; } - / tab_separator ws { return null; } - -step - = val:expr comment? { return val; } - / comment { return null; } - / tab_separator? ws { return null; } - -expr - = ( - head:token - tail:(ws continuation? value:expr { return value })* - { return [head].concat(tail.flat(1)); } - ) - / begin_compound inner:expr end_compound { return [inner]; } - / begin_list inner:list_inner? end_list { return [["List"].concat((inner || []).flat())] }; - -comment - = ws "--" [^\n]* { return null; } - / ws "#" [^\n]* { return null; } - -token = - token1:simple_token ":" token2:simple_token { return {argName: token1, argValue: token2} } - / simple_token - -simple_token = - hex - / number - / ( t:([A-Za-z0-9_]+) { return t.join("") } ) - / string - -hex = hex:("0x" [0-9a-fA-F]+) { return ["Hex", hex.flat().flat().join("")] } -number = - n:(("-" / "+")? [0-9]+ ("." [0-9]+)? ("e" "-"? [0-9]+)?) { return ["Exactly", n.flat().flat().join("")] } - -list_inner - = ( - head:expr - tail:(ws? value:list_inner { return value })* - { return [head].concat(tail.flat()); } - ) - -begin_compound = ws "(" ws -end_compound = ws ")" ws - -begin_list = ws "[" ws -end_list = ws "]" ws - -line_separator = "\r"?"\n" -tab_separator = "\t" - / " " - -continuation = "\\" line_separator tab_separator tab_separator - -ws "whitespace" = [ \t]* -full_ws = comment full_ws - / [ \t\r\n] full_ws? - -string "string" - = quotation_mark chars:char* quotation_mark { return ["String", chars.join("")]; } - -char - = unescaped - / escape - sequence:( - '"' - / "\\" - / "/" - / "b" { return "\b"; } - / "f" { return "\f"; } - / "n" { return "\n"; } - / "r" { return "\r"; } - / "t" { return "\t"; } - / "u" digits:$(HEXDIG HEXDIG HEXDIG HEXDIG) { - return String.fromCharCode(parseInt(digits, 16)); - } - ) - { return sequence; } - -escape - = "\\" - -quotation_mark - = '"' - -unescaped - = [^\0-\x1F\x22\x5C] - -// ----- Core ABNF Rules ----- - -// See RFC 4234, Appendix B (http://tools.ietf.org/html/rfc4234). -DIGIT = [0-9] -HEXDIG = [0-9a-f]i \ No newline at end of file diff --git a/scenario/SCENARIO.md b/scenario/SCENARIO.md deleted file mode 100644 index 3ca472798..000000000 --- a/scenario/SCENARIO.md +++ /dev/null @@ -1,219 +0,0 @@ - -# Types -* `name:` - Helper to describe arguments with names, not actually input this way -* `` - `True` or `False` -* `` - A standard number (e.g. `5` or `6.0` or `10.0e18`) -* `` - The local name for a given cToken when created, e.g. `cZRX` -* `` - One of: `Admin, Bank, Geoff, Torrey, Robert, Coburn, Jared` -* `` - A string, may be quoted but does not have to be if a single-word (e.g. `"Mint"` or `Mint`) -* `
` - TODO -* `` - See assertions below. - -# Events - -## Core Events - -* "History n:=5" - Prints history of actions - * E.g. "History" - * E.g. "History 10" -* `Read ...` - Reads given value and prints result - * E.g. `Read CToken cBAT ExchangeRateStored` - Returns exchange rate of cBAT -* `Assert ` - Validates given assertion, raising an exception if assertion fails - * E.g. `Assert Equal (Erc20 BAT TokenBalance Geoff) (Exactly 5.0)` - Returns exchange rate of cBAT -* `FastForward n: Blocks` - For `CTokenScenario`, moves the block number forward n blocks. Note: in `CTokenScenario` the current block number is mocked (starting at 100000). Thus, this is the only way for the protocol to see a higher block number (for accruing interest). - * E.g. `FastForward 5 Blocks` - Move block number forward 5 blocks. -* `Inspect` - Prints debugging information about the world -* `Debug message:` - Same as inspect but prepends with a string -* `From ` - Runs event as the given user - * E.g. `From Geoff (CToken cZRX Mint 5e18)` -* `Invariant ` - Adds a new invariant to the world which is checked after each transaction - * E.g. `Invariant Static (CToken cZRX TotalSupply)` -* `WipeInvariants` - Removes all invariants. -* `Comptroller ` - Runs given Comptroller event - * E.g. `Comptroller _setReserveFactor 0.5` -* `CToken ` - Runs given CToken event - * E.g. `CToken cZRX Mint 5e18` -* `Erc20 ` - Runs given Erc20 event - * E.g. `Erc20 ZRX Facuet Geoff 5e18` -* `InterestRateModel ...event` - Runs given interest rate model event - * E.g. `InterestRateModel Deployed (Fixed 0.5)` -* `PriceOracle ` - Runs given Price Oracle event - * E.g. `PriceOracle SetPrice cZRX 1.5` - -## Comptroller Events - -* "Comptroller Deploy ...comptrollerParams" - Generates a new Comptroller - * E.g. "Comptroller Deploy Scenario (PriceOracle Address) 0.1 10" -* `Comptroller SetPaused action: paused:` - Pauses or unpaused given cToken function (e.g. Mint) - * E.g. `Comptroller SetPaused Mint True` -* `Comptroller SupportMarket ` - Adds support in the Comptroller for the given cToken - * E.g. `Comptroller SupportMarket cZRX` -* `Comptroller EnterMarkets ...` - User enters the given markets - * E.g. `Comptroller EnterMarkets Geoff cZRX cETH` -* `Comptroller SetMaxAssets ` - Sets (or resets) the max allowed asset count - * E.g. `Comptroller SetMaxAssets 4` -* `CToken SetOracle oracle:` - Sets the oracle - * E.g. `Comptroller SetOracle (Fixed 1.5)` -* `Comptroller SetCollateralFactor ` - Sets the collateral factor for given cToken to number - * E.g. `Comptroller SetCollateralFactor cZRX 0.1` -* `FastForward n: Blocks` - Moves the block number forward `n` blocks. Note: in `CTokenScenario` and `ComptrollerScenario` the current block number is mocked (starting at 100000). This is the only way for the protocol to see a higher block number (for accruing interest). - * E.g. `Comptroller FastForward 5 Blocks` - Move block number forward 5 blocks. - -## cToken Events - -* `CToken Deploy name: underlying: comptroller: interestRateModel: initialExchangeRate: decimals: admin:
` - Generates a new comptroller and sets to world global - * E.g. `CToken Deploy cZRX (Erc20 ZRX Address) (Comptroller Address) (InterestRateModel Address) 1.0 18` -* `CToken AccrueInterest` - Accrues interest for given token - * E.g. `CToken cZRX AccrueInterest` -* `CToken Mint amount:` - Mints the given amount of cToken as specified user - * E.g. `CToken cZRX Mint Geoff 1.0` -* `CToken Redeem amount:` - Redeems the given amount of cToken as specified user - * E.g. `CToken cZRX Redeem Geoff 1.0e18` -* `CToken Borrow amount:` - Borrows the given amount of this cToken as specified user - * E.g. `CToken cZRX Borrow Geoff 1.0e18` -* `CToken ReduceReserves amount:` - Reduces the reserves of the cToken - * E.g. `CToken cZRX ReduceReserves 1.0e18` -* `CToken SetReserveFactor amount:` - Sets the reserve factor for the cToken - * E.g. `CToken cZRX SetReserveFactor 0.1` -* `CToken SetInterestRateModel interestRateModel:` - Sets the interest rate model for the given cToken - * E.g. `CToken cZRX SetInterestRateModel (Fixed 1.5)` -* `CToken SetComptroller comptroller:` - Sets the comptroller for the given cToken - * E.g. `CToken cZRX SetComptroller Comptroller` -* `CToken Mock variable: value:` - Mocks a given value on cToken. Note: value must be a supported mock and this will only work on a CTokenScenario contract. - * E.g. `CToken cZRX Mock totalBorrows 5.0e18` - * E.g. `CToken cZRX Mock totalReserves 0.5e18` - -## Erc-20 Events - -* `Erc20 Deploy name:` - Generates a new ERC-20 token by name - * E.g. `Erc20 Deploy ZRX` -* `Erc20 Approve
` - Adds an allowance between user and address - * E.g. `Erc20 ZRX Approve Geoff cZRX 1.0e18` -* `Erc20 Faucet
` - Adds an arbitrary balance to given user - * E.g. `Erc20 ZRX Facuet Geoff 1.0e18` - -## Price Oracle Events - -* `Deploy` - Generates a new price oracle (note: defaults to (Fixed 1.0)) - * E.g. `PriceOracle Deploy (Fixed 1.0)` - * E.g. `PriceOracle Deploy Simple` - * E.g. `PriceOracle Deploy NotPriceOracle` -* `SetPrice ` - Sets the per-ether price for the given cToken - * E.g. `PriceOracle SetPrice cZRX 1.0` - -## Interest Rate Model Events - -## Deploy - -* `Deploy params:` - Generates a new interest rate model (note: defaults to (Fixed 0.25)) - * E.g. `InterestRateModel Deploy (Fixed 0.5)` - * E.g. `InterestRateModel Deploy Whitepaper` - -# Values - -## Core Values - -* `True` - Returns true -* `False` - Returns false -* `Zero` - Returns 0 -* `Some` - Returns 100e18 -* `Little` - Returns 100e10 -* `Exactly ` - Returns a strict numerical value - * E.g. `Exactly 5.0` -* `Exp ` - Returns the mantissa for a given exp - * E.g. `Exp 5.5` -* `Precisely ` - Matches a number to given number of significant figures - * E.g. `Exactly 5.1000` - Matches to 5 sig figs -* `Anything` - Matches anything -* `Nothing` - Matches nothing -* `Default value: default:` - Returns value if truthy, otherwise default. Note: this does short-circuit -* `LastContract` - Returns the address of last constructed contract -* `User <...>` - Returns User value (see below) -* `Comptroller <...>` - Returns Comptroller value (see below) -* `CToken <...>` - Returns CToken value (see below) -* `Erc20 <...>` - Returns Erc20 value (see below) -* `InterestRateModel <...>` - Returns InterestRateModel value (see below) -* `PriceOracle <...>` - Returns PriceOracle value (see below) - -## User Values - -* `User Address` - Returns address of user - * E.g. `User Geoff Address` - Returns Geoff's address - -## Comptroller Values - -* `Comptroller Liquidity ` - Returns a given user's trued up liquidity - * E.g. `Comptroller Liquidity Geoff` -* `Comptroller MembershipLength ` - Returns a given user's length of membership - * E.g. `Comptroller MembershipLength Geoff` -* `Comptroller CheckMembership ` - Returns one if user is in asset, zero otherwise. - * E.g. `Comptroller CheckMembership Geoff cZRX` -* "Comptroller CheckListed " - Returns true if market is listed, false otherwise. - * E.g. "Comptroller CheckListed cZRX" - -## CToken Values -* `CToken UnderlyingBalance ` - Returns a user's underlying balance (based on given exchange rate) - * E.g. `CToken cZRX UnderlyingBalance Geoff` -* `CToken BorrowBalance ` - Returns a user's borrow balance (including interest) - * E.g. `CToken cZRX BorrowBalance Geoff` -* `CToken TotalBorrowBalance` - Returns the cToken's total borrow balance - * E.g. `CToken cZRX TotalBorrowBalance` -* `CToken Reserves` - Returns the cToken's total reserves - * E.g. `CToken cZRX Reserves` -* `CToken Comptroller` - Returns the cToken's comptroller - * E.g. `CToken cZRX Comptroller` -* `CToken PriceOracle` - Returns the cToken's price oracle - * E.g. `CToken cZRX PriceOracle` -* `CToken ExchangeRateStored` - Returns the cToken's exchange rate (based on balances stored) - * E.g. `CToken cZRX ExchangeRateStored` -* `CToken ExchangeRate` - Returns the cToken's current exchange rate - * E.g. `CToken cZRX ExchangeRate` - -## Erc-20 Values - -* `Erc20 Address` - Returns address of ERC-20 contract - * E.g. `Erc20 ZRX Address` - Returns ZRX's address -* `Erc20 Name` - Returns name of ERC-20 contract - * E.g. `Erc20 ZRX Address` - Returns ZRX's name -* `Erc20 Symbol` - Returns symbol of ERC-20 contract - * E.g. `Erc20 ZRX Symbol` - Returns ZRX's symbol -* `Erc20 Decimals` - Returns number of decimals in ERC-20 contract - * E.g. `Erc20 ZRX Decimals` - Returns ZRX's decimals -* `Erc20 TotalSupply` - Returns the ERC-20 token's total supply - * E.g. `Erc20 ZRX TotalSupply` - * E.g. `Erc20 cZRX TotalSupply` -* `Erc20 TokenBalance
` - Returns the ERC-20 token balance of a given address - * E.g. `Erc20 ZRX TokenBalance Geoff` - Returns a user's ZRX balance - * E.g. `Erc20 cZRX TokenBalance Geoff` - Returns a user's cZRX balance - * E.g. `Erc20 ZRX TokenBalance cZRX` - Returns cZRX's ZRX balance -* `Erc20 Allowance owner:
spender:
` - Returns the ERC-20 allowance from owner to spender - * E.g. `Erc20 ZRX Allowance Geoff Torrey` - Returns the ZRX allowance of Geoff to Torrey - * E.g. `Erc20 cZRX Allowance Geoff Coburn` - Returns the cZRX allowance of Geoff to Coburn - * E.g. `Erc20 ZRX Allowance Geoff cZRX` - Returns the ZRX allowance of Geoff to the cZRX cToken - -## PriceOracle Values - -* `Address` - Gets the address of the global price oracle -* `Price asset:
` - Gets the price of the given asset - -## Interest Rate Model Values - -* `Address` - Gets the address of the global interest rate model - -# Assertions - -* `Equal given: expected:` - Asserts that given matches expected. - * E.g. `Assert Equal (Exactly 0) Zero` - * E.g. `Assert Equal (CToken cZRX TotalSupply) (Exactly 55)` - * E.g. `Assert Equal (CToken cZRX Comptroller) (Comptroller Address)` -* `True given:` - Asserts that given is true. - * E.g. `Assert True (Comptroller CheckMembership Geoff cETH)` -* `False given:` - Asserts that given is false. - * E.g. `Assert False (Comptroller CheckMembership Geoff cETH)` -* `Failure error: info: detail:` - Asserts that last transaction had a graceful failure with given error, info and detail. - * E.g. `Assert Failure UNAUTHORIZED SUPPORT_MARKET_OWNER_CHECK` - * E.g. `Assert Failure MATH_ERROR MINT_CALCULATE_BALANCE 5` -* `Revert` - Asserts that the last transaction reverted. -* `Success` - Asserts that the last transaction completed successfully (that is, did not revert nor emit graceful failure). -* `Log name: ((key: value:) ...)` - Asserts that last transaction emitted log with given name and key-value pairs. - * E.g. `Assert Log Minted (("account" (User Geoff address)) ("amount" (Exactly 55)))` diff --git a/scenario/package.json b/scenario/package.json deleted file mode 100644 index dbd88aa8d..000000000 --- a/scenario/package.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "name": "compound-protocol-alpha", - "version": "0.2.1", - "description": "The Compound Money Market", - "main": "index.js", - "scripts": { - "build": "./script/webpack" - }, - "repository": "git@github.com:compound-finance/money-market.git", - "author": "Compound Finance", - "license": "UNLICENSED", - "devDependencies": { - "request": "^2.88.2", - "solparse": "^2.2.8", - "ts-loader": "^8.0.3", - "ts-pegjs": "^0.2.7", - "typescript": "^4.0.2", - "webpack": "^4.44.1", - "webpack-bundle-analyzer": "^3.8.0", - "webpack-cli": "^3.3.12" - }, - "dependencies": { - "bignumber.js": "9.0.0", - "eth-saddle": "^0.1.25", - "ethers": "^5.0.8", - "immutable": "^4.0.0-rc.12", - "truffle-flattener": "^1.4.4", - "web3": "^1.2.11" - }, - "resolutions": { - "scrypt.js": "https://registry.npmjs.org/@compound-finance/ethereumjs-wallet/-/ethereumjs-wallet-0.6.3.tgz", - "**/ganache-core": "github:compound-finance/ganache-core.git#jflatow/unbreak-fork" - } -} diff --git a/scenario/script/generate_parser b/scenario/script/generate_parser deleted file mode 100755 index 27ad43705..000000000 --- a/scenario/script/generate_parser +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/bash - -set -eo pipefail - -dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" -scenario_dir="$(cd $dir/.. && pwd)" - -"$scenario_dir/node_modules/.bin/pegjs" \ - --plugin "$scenario_dir/node_modules/ts-pegjs" \ - -o "$scenario_dir/src/Parser.ts" \ - --cache \ - --allowed-start-rules tests,step,macros \ - "$scenario_dir/Grammar.pegjs" diff --git a/scenario/script/repl b/scenario/script/repl deleted file mode 100755 index ad0ec5ba1..000000000 --- a/scenario/script/repl +++ /dev/null @@ -1,59 +0,0 @@ -#!/bin/bash - -set -eo pipefail - -dir=`dirname $0` -tsc_root="$dir/.." -proj_root="$dir/../.." -networks_root="$dir/../../networks" -network=${NETWORK:-development} -script=() -verbose="$VERBOSE" -dry_run="$DRY_RUN" -no_tsc="$NO_TSC" - -[ -n "$SCRIPT" ] && script+=("$SCRIPT") - -usage() { echo "$0 usage:" && grep ".)\ #" $0; exit 0; } -while getopts ":hdn:e:s:vt" arg; do - case $arg in - c) # Don't compile - no_compile="true" - ;; - d) # Dry run - dry_run="true" - ;; - h) # Hypothetical - hypothetical="true" - ;; - e) # Add variables for script (key=value,key2=value2) - env_vars="$OPTARG" - ;; - n) # Specify network - network=$OPTARG - ;; - s) # Specify a script to run - [ ! -f "$OPTARG" ] \ - && echo "Cannot find script $OPTARG" \ - && exit 1 - script+=("$OPTARG") - ;; - t) # Don't build TSC - no_tsc="true" - ;; - - v) # Verbose - verbose="true" - ;; - - h | *) # Display help. - usage - exit 0 - ;; - esac -done - -[[ -z $no_tsc ]] && "$dir/tsc" -[[ -z $no_compile ]] && "$proj_root/script/compile" - -proj_root="$proj_root" env_vars="$env_vars" dry_run="$dry_run" script="$(IFS=, ; echo "${script[*]}")" network="$network" verbose="$verbose" node "$tsc_root/.tsbuilt/Repl.js" diff --git a/scenario/script/tsc b/scenario/script/tsc deleted file mode 100755 index cdf02b20e..000000000 --- a/scenario/script/tsc +++ /dev/null @@ -1,43 +0,0 @@ -#!/bin/bash - -set -eo pipefail - -dir=`dirname $0` -scenario_dir="$(cd $dir/.. && pwd)" -parent_dir="$(cd $dir/../.. && pwd)" -cache_file="$scenario_dir/.tscache" -shasumVersion="$(shasum -v)" -inflectionVersion="6.01" - -if [ "$(printf '%s\n' "$inflectionVersion" "$shasumVersion" | sort -V | head -n1)" = "$inflectionVersion" ]; then - checksum="$(echo $scenario_dir/src/{*,**/}*.* | xargs shasum -U | shasum -U | cut -d' ' -f 1)" -else - checksum="$(echo $scenario_dir/src/{*,**/}*.* | xargs shasum -p | shasum -p | cut -d' ' -f 1)" -fi - -if [ ! -d "$scenario_dir/node_modules" ]; then - echo "Getting scenario packages..." - cd "$scenario_dir" && yarn -fi - -trap cleanup EXIT - -cleanup() { - mv "$parent_dir/node_modules_tmp" "$parent_dir/node_modules" -} - -mv "$parent_dir/node_modules" "$parent_dir/node_modules_tmp" - -if [ -z "$rebuild" -a -f "$cache_file" ]; then - cached="$(cat $cache_file)" - - if [ "$cached" == "$checksum" ]; then - echo "Skipping Scenario Rebuild (set rebuild=true to force)" - exit 0 - fi -fi - -echo "Building Scenario Runner..." -cd "$scenario_dir" && node "$scenario_dir/node_modules/.bin/tsc" ${TSC_ARGS-"--skipLibCheck"} - -echo "$checksum" > "$cache_file" diff --git a/scenario/script/webpack b/scenario/script/webpack deleted file mode 100755 index 450947799..000000000 --- a/scenario/script/webpack +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/bash - -set -eo pipefail - -dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" -scenario_dir="$(cd $dir/.. && pwd)" - -cd "$scenario_dir" && - mkdir -p ./build && - ./node_modules/.bin/webpack \ - --mode production \ - --config ./webpack.config.js \ - --entry ./src/Web.ts \ - --module-bind 'ts=ts-loader' \ - --module-bind 'exports-loader?parse' \ - --resolve-extensions ".ts,.js" \ - --output-library-target window \ - --output ./build/scenario.js diff --git a/scenario/src/Accounts.ts b/scenario/src/Accounts.ts deleted file mode 100644 index 63070f7f6..000000000 --- a/scenario/src/Accounts.ts +++ /dev/null @@ -1,49 +0,0 @@ -import {World} from './World'; -import {Map} from 'immutable'; - -export const accountMap = { - "default": 0, - "root": 0, - "admin": 0, - "first": 0, - - "bank": 1, - "second": 1, - - "geoff": 2, - "third": 2, - "guardian": 2, - - "torrey": 3, - "fourth": 3, - - "robert": 4, - "fifth": 4, - - "coburn": 5, - "sixth": 5, - - "jared": 6, - "seventh": 6 -}; - -export interface Account { - name: string - address: string -} - -export type Accounts = Map - -export function accountAliases(index: number): string[] { - return Object.entries(accountMap).filter(([k,v]) => v === index).map(([k,v]) => k); -} - -export function loadAccounts(accounts: string[]): Accounts { - return Object.entries(accountMap).reduce((acc, [name, index]) => { - if (accounts[index]) { - return acc.set(name, { name: name, address: accounts[index] }); - } else { - return acc; - } - }, >Map({})); -} diff --git a/scenario/src/Action.ts b/scenario/src/Action.ts deleted file mode 100644 index 81eaabc11..000000000 --- a/scenario/src/Action.ts +++ /dev/null @@ -1,15 +0,0 @@ -import {Invokation} from './Invokation'; - -export class Action { - log: string; - invokation: Invokation; - - constructor(log: string, invokation: Invokation) { - this.log = log; - this.invokation = invokation; - } - - toString() { - return `Action: log=${this.log}, result=${this.invokation.toString()}`; - } -} diff --git a/scenario/src/Assert.ts b/scenario/src/Assert.ts deleted file mode 100644 index f34637929..000000000 --- a/scenario/src/Assert.ts +++ /dev/null @@ -1,19 +0,0 @@ -export type Expect = (actual: any) => { - toEqual: (expected: any) => any - fail: (message: string) => any -} - -export const throwExpect: Expect = (x) => { - return { - toEqual: (y) => { - let xEnc = JSON.stringify(x); - let yEnc = JSON.stringify(y); - if (xEnc !== yEnc) { - throw new Error(`expected ${x} to equal ${y}`); - } - }, - fail: (reason) => { - throw new Error(reason) - } - } -}; diff --git a/scenario/src/Builder/CTokenBuilder.ts b/scenario/src/Builder/CTokenBuilder.ts deleted file mode 100644 index f998d3e0b..000000000 --- a/scenario/src/Builder/CTokenBuilder.ts +++ /dev/null @@ -1,408 +0,0 @@ -import { Event } from '../Event'; -import { World } from '../World'; -import { CErc20Delegator, CErc20DelegatorScenario } from '../Contract/CErc20Delegator'; -import { CToken } from '../Contract/CToken'; -import { Invokation, invoke } from '../Invokation'; -import { getAddressV, getExpNumberV, getNumberV, getStringV } from '../CoreValue'; -import { AddressV, NumberV, StringV } from '../Value'; -import { Arg, Fetcher, getFetcherValue } from '../Command'; -import { storeAndSaveContract } from '../Networks'; -import { getContract, getTestContract } from '../Contract'; - -const CErc20Contract = getContract('CErc20Immutable'); -const CErc20Delegator = getContract('CErc20Delegator'); -const CErc20DelegatorScenario = getTestContract('CErc20DelegatorScenario'); -const CEtherContract = getContract('CEther'); -const CErc20ScenarioContract = getTestContract('CErc20Scenario'); -const CEtherScenarioContract = getTestContract('CEtherScenario'); -const CEvilContract = getTestContract('CEvil'); - -export interface TokenData { - invokation: Invokation; - name: string; - symbol: string; - decimals?: number; - underlying?: string; - address?: string; - contract: string; - initial_exchange_rate_mantissa?: string; - admin?: string; -} - -export async function buildCToken( - world: World, - from: string, - params: Event -): Promise<{ world: World; cToken: CToken; tokenData: TokenData }> { - const fetchers = [ - new Fetcher< - { - symbol: StringV; - name: StringV; - decimals: NumberV; - underlying: AddressV; - comptroller: AddressV; - interestRateModel: AddressV; - initialExchangeRate: NumberV; - admin: AddressV; - implementation: AddressV; - becomeImplementationData: StringV; - }, - TokenData - >( - ` - #### CErc20Delegator - - * "CErc20Delegator symbol: name: underlying:
comptroller:
interestRateModel:
initialExchangeRate: decimals: admin:
implementation:
becomeImplementationData:" - The real deal CToken - * E.g. "CToken Deploy CErc20Delegator cDAI \"Compound DAI\" (Erc20 DAI Address) (Comptroller Address) (InterestRateModel Address) 1.0 8 Geoff (CToken CDaiDelegate Address) "0x0123434anyByTes314535q" " - `, - 'CErc20Delegator', - [ - new Arg('symbol', getStringV), - new Arg('name', getStringV), - new Arg('underlying', getAddressV), - new Arg('comptroller', getAddressV), - new Arg('interestRateModel', getAddressV), - new Arg('initialExchangeRate', getExpNumberV), - new Arg('decimals', getNumberV), - new Arg('admin', getAddressV), - new Arg('implementation', getAddressV), - new Arg('becomeImplementationData', getStringV) - ], - async ( - world, - { - symbol, - name, - underlying, - comptroller, - interestRateModel, - initialExchangeRate, - decimals, - admin, - implementation, - becomeImplementationData - } - ) => { - return { - invokation: await CErc20Delegator.deploy(world, from, [ - underlying.val, - comptroller.val, - interestRateModel.val, - initialExchangeRate.val, - name.val, - symbol.val, - decimals.val, - admin.val, - implementation.val, - becomeImplementationData.val - ]), - name: name.val, - symbol: symbol.val, - decimals: decimals.toNumber(), - underlying: underlying.val, - contract: 'CErc20Delegator', - initial_exchange_rate_mantissa: initialExchangeRate.encode().toString(), - admin: admin.val - }; - } - ), - - new Fetcher< - { - symbol: StringV; - name: StringV; - decimals: NumberV; - underlying: AddressV; - comptroller: AddressV; - interestRateModel: AddressV; - initialExchangeRate: NumberV; - admin: AddressV; - implementation: AddressV; - becomeImplementationData: StringV; - }, - TokenData - >( - ` - #### CErc20DelegatorScenario - - * "CErc20DelegatorScenario symbol: name: underlying:
comptroller:
interestRateModel:
initialExchangeRate: decimals: admin:
implementation:
becomeImplementationData:" - A CToken Scenario for local testing - * E.g. "CToken Deploy CErc20DelegatorScenario cDAI \"Compound DAI\" (Erc20 DAI Address) (Comptroller Address) (InterestRateModel Address) 1.0 8 Geoff (CToken CDaiDelegate Address) "0x0123434anyByTes314535q" " - `, - 'CErc20DelegatorScenario', - [ - new Arg('symbol', getStringV), - new Arg('name', getStringV), - new Arg('underlying', getAddressV), - new Arg('comptroller', getAddressV), - new Arg('interestRateModel', getAddressV), - new Arg('initialExchangeRate', getExpNumberV), - new Arg('decimals', getNumberV), - new Arg('admin', getAddressV), - new Arg('implementation', getAddressV), - new Arg('becomeImplementationData', getStringV) - ], - async ( - world, - { - symbol, - name, - underlying, - comptroller, - interestRateModel, - initialExchangeRate, - decimals, - admin, - implementation, - becomeImplementationData - } - ) => { - return { - invokation: await CErc20DelegatorScenario.deploy(world, from, [ - underlying.val, - comptroller.val, - interestRateModel.val, - initialExchangeRate.val, - name.val, - symbol.val, - decimals.val, - admin.val, - implementation.val, - becomeImplementationData.val - ]), - name: name.val, - symbol: symbol.val, - decimals: decimals.toNumber(), - underlying: underlying.val, - contract: 'CErc20DelegatorScenario', - initial_exchange_rate_mantissa: initialExchangeRate.encode().toString(), - admin: admin.val - }; - } - ), - - new Fetcher<{symbol: StringV, name: StringV, decimals: NumberV, underlying: AddressV, comptroller: AddressV, interestRateModel: AddressV, initialExchangeRate: NumberV, admin: AddressV}, TokenData>(` - #### Scenario - - * "Scenario symbol: name: underlying:
comptroller:
interestRateModel:
initialExchangeRate: decimals: admin:
" - A CToken Scenario for local testing - * E.g. "CToken Deploy Scenario cZRX \"Compound ZRX\" (Erc20 ZRX Address) (Comptroller Address) (InterestRateModel Address) 1.0 8" - `, - "Scenario", - [ - new Arg("symbol", getStringV), - new Arg("name", getStringV), - new Arg("underlying", getAddressV), - new Arg("comptroller", getAddressV), - new Arg("interestRateModel", getAddressV), - new Arg("initialExchangeRate", getExpNumberV), - new Arg("decimals", getNumberV), - new Arg("admin", getAddressV) - ], - async (world, {symbol, name, underlying, comptroller, interestRateModel, initialExchangeRate, decimals, admin}) => { - return { - invokation: await CErc20ScenarioContract.deploy(world, from, [underlying.val, comptroller.val, interestRateModel.val, initialExchangeRate.val, name.val, symbol.val, decimals.val, admin.val]), - name: name.val, - symbol: symbol.val, - decimals: decimals.toNumber(), - underlying: underlying.val, - contract: 'CErc20Scenario', - initial_exchange_rate_mantissa: initialExchangeRate.encode().toString(), - admin: admin.val - }; - } - ), - - new Fetcher<{symbol: StringV, name: StringV, decimals: NumberV, admin: AddressV, comptroller: AddressV, interestRateModel: AddressV, initialExchangeRate: NumberV}, TokenData>(` - #### CEtherScenario - - * "CEtherScenario symbol: name: comptroller:
interestRateModel:
initialExchangeRate: decimals: admin:
" - A CToken Scenario for local testing - * E.g. "CToken Deploy CEtherScenario cETH \"Compound Ether\" (Comptroller Address) (InterestRateModel Address) 1.0 8" - `, - "CEtherScenario", - [ - new Arg("symbol", getStringV), - new Arg("name", getStringV), - new Arg("comptroller", getAddressV), - new Arg("interestRateModel", getAddressV), - new Arg("initialExchangeRate", getExpNumberV), - new Arg("decimals", getNumberV), - new Arg("admin", getAddressV) - ], - async (world, {symbol, name, comptroller, interestRateModel, initialExchangeRate, decimals, admin}) => { - return { - invokation: await CEtherScenarioContract.deploy(world, from, [name.val, symbol.val, decimals.val, admin.val, comptroller.val, interestRateModel.val, initialExchangeRate.val]), - name: name.val, - symbol: symbol.val, - decimals: decimals.toNumber(), - underlying: "", - contract: 'CEtherScenario', - initial_exchange_rate_mantissa: initialExchangeRate.encode().toString(), - admin: admin.val - }; - } - ), - - new Fetcher<{symbol: StringV, name: StringV, decimals: NumberV, admin: AddressV, comptroller: AddressV, interestRateModel: AddressV, initialExchangeRate: NumberV}, TokenData>(` - #### CEther - - * "CEther symbol: name: comptroller:
interestRateModel:
initialExchangeRate: decimals: admin:
" - A CToken Scenario for local testing - * E.g. "CToken Deploy CEther cETH \"Compound Ether\" (Comptroller Address) (InterestRateModel Address) 1.0 8" - `, - "CEther", - [ - new Arg("symbol", getStringV), - new Arg("name", getStringV), - new Arg("comptroller", getAddressV), - new Arg("interestRateModel", getAddressV), - new Arg("initialExchangeRate", getExpNumberV), - new Arg("decimals", getNumberV), - new Arg("admin", getAddressV) - ], - async (world, {symbol, name, comptroller, interestRateModel, initialExchangeRate, decimals, admin}) => { - return { - invokation: await CEtherContract.deploy(world, from, [comptroller.val, interestRateModel.val, initialExchangeRate.val, name.val, symbol.val, decimals.val, admin.val]), - name: name.val, - symbol: symbol.val, - decimals: decimals.toNumber(), - underlying: "", - contract: 'CEther', - initial_exchange_rate_mantissa: initialExchangeRate.encode().toString(), - admin: admin.val - }; - } - ), - - new Fetcher<{symbol: StringV, name: StringV, decimals: NumberV, admin: AddressV, underlying: AddressV, comptroller: AddressV, interestRateModel: AddressV, initialExchangeRate: NumberV}, TokenData>(` - #### CErc20 - - * "CErc20 symbol: name: underlying:
comptroller:
interestRateModel:
initialExchangeRate: decimals: admin:
" - A official CToken contract - * E.g. "CToken Deploy CErc20 cZRX \"Compound ZRX\" (Erc20 ZRX Address) (Comptroller Address) (InterestRateModel Address) 1.0 8" - `, - "CErc20", - [ - new Arg("symbol", getStringV), - new Arg("name", getStringV), - new Arg("underlying", getAddressV), - new Arg("comptroller", getAddressV), - new Arg("interestRateModel", getAddressV), - new Arg("initialExchangeRate", getExpNumberV), - new Arg("decimals", getNumberV), - new Arg("admin", getAddressV) - ], - async (world, {symbol, name, underlying, comptroller, interestRateModel, initialExchangeRate, decimals, admin}) => { - - return { - invokation: await CErc20Contract.deploy(world, from, [underlying.val, comptroller.val, interestRateModel.val, initialExchangeRate.val, name.val, symbol.val, decimals.val, admin.val]), - name: name.val, - symbol: symbol.val, - decimals: decimals.toNumber(), - underlying: underlying.val, - contract: 'CErc20', - initial_exchange_rate_mantissa: initialExchangeRate.encode().toString(), - admin: admin.val - }; - } - ), - - new Fetcher<{symbol: StringV, name: StringV, decimals: NumberV, admin: AddressV, underlying: AddressV, comptroller: AddressV, interestRateModel: AddressV, initialExchangeRate: NumberV}, TokenData>(` - #### CEvil - - * "CEvil symbol: name: underlying:
comptroller:
interestRateModel:
initialExchangeRate: decimals: admin:
" - A malicious CToken contract - * E.g. "CToken Deploy CEvil cEVL \"Compound EVL\" (Erc20 ZRX Address) (Comptroller Address) (InterestRateModel Address) 1.0 8" - `, - "CEvil", - [ - new Arg("symbol", getStringV), - new Arg("name", getStringV), - new Arg("underlying", getAddressV), - new Arg("comptroller", getAddressV), - new Arg("interestRateModel", getAddressV), - new Arg("initialExchangeRate", getExpNumberV), - new Arg("decimals", getNumberV), - new Arg("admin", getAddressV) - ], - async (world, {symbol, name, underlying, comptroller, interestRateModel, initialExchangeRate, decimals, admin}) => { - return { - invokation: await CEvilContract.deploy(world, from, [underlying.val, comptroller.val, interestRateModel.val, initialExchangeRate.val, name.val, symbol.val, decimals.val, admin.val]), - name: name.val, - symbol: symbol.val, - decimals: decimals.toNumber(), - underlying: underlying.val, - contract: 'CEvil', - initial_exchange_rate_mantissa: initialExchangeRate.encode().toString(), - admin: admin.val - }; - } - ), - - new Fetcher<{symbol: StringV, name: StringV, decimals: NumberV, admin: AddressV, underlying: AddressV, comptroller: AddressV, interestRateModel: AddressV, initialExchangeRate: NumberV}, TokenData>(` - #### Standard - - * "symbol: name: underlying:
comptroller:
interestRateModel:
initialExchangeRate: decimals: admin:
" - A official CToken contract - * E.g. "CToken Deploy Standard cZRX \"Compound ZRX\" (Erc20 ZRX Address) (Comptroller Address) (InterestRateModel Address) 1.0 8" - `, - "Standard", - [ - new Arg("symbol", getStringV), - new Arg("name", getStringV), - new Arg("underlying", getAddressV), - new Arg("comptroller", getAddressV), - new Arg("interestRateModel", getAddressV), - new Arg("initialExchangeRate", getExpNumberV), - new Arg("decimals", getNumberV), - new Arg("admin", getAddressV) - ], - async (world, {symbol, name, underlying, comptroller, interestRateModel, initialExchangeRate, decimals, admin}) => { - // Note: we're going to use the scenario contract as the standard deployment on local networks - if (world.isLocalNetwork()) { - return { - invokation: await CErc20ScenarioContract.deploy(world, from, [underlying.val, comptroller.val, interestRateModel.val, initialExchangeRate.val, name.val, symbol.val, decimals.val, admin.val]), - name: name.val, - symbol: symbol.val, - decimals: decimals.toNumber(), - underlying: underlying.val, - contract: 'CErc20Scenario', - initial_exchange_rate_mantissa: initialExchangeRate.encode().toString(), - admin: admin.val - }; - } else { - return { - invokation: await CErc20Contract.deploy(world, from, [underlying.val, comptroller.val, interestRateModel.val, initialExchangeRate.val, name.val, symbol.val, decimals.val, admin.val]), - name: name.val, - symbol: symbol.val, - decimals: decimals.toNumber(), - underlying: underlying.val, - contract: 'CErc20Immutable', - initial_exchange_rate_mantissa: initialExchangeRate.encode().toString(), - admin: admin.val - }; - } - }, - {catchall: true} - ) - ]; - - let tokenData = await getFetcherValue("DeployCToken", fetchers, world, params); - let invokation = tokenData.invokation; - delete tokenData.invokation; - - if (invokation.error) { - throw invokation.error; - } - - const cToken = invokation.value!; - tokenData.address = cToken._address; - - world = await storeAndSaveContract( - world, - cToken, - tokenData.symbol, - invokation, - [ - { index: ['cTokens', tokenData.symbol], data: tokenData }, - { index: ['Tokens', tokenData.symbol], data: tokenData } - ] - ); - - return {world, cToken, tokenData}; -} diff --git a/scenario/src/Builder/CTokenDelegateBuilder.ts b/scenario/src/Builder/CTokenDelegateBuilder.ts deleted file mode 100644 index f19477abd..000000000 --- a/scenario/src/Builder/CTokenDelegateBuilder.ts +++ /dev/null @@ -1,156 +0,0 @@ -import { Event } from '../Event'; -import { World } from '../World'; -import { CErc20Delegate, CErc20DelegateScenario } from '../Contract/CErc20Delegate'; -import { CToken } from '../Contract/CToken'; -import { Invokation } from '../Invokation'; -import { getStringV } from '../CoreValue'; -import { AddressV, NumberV, StringV } from '../Value'; -import { Arg, Fetcher, getFetcherValue } from '../Command'; -import { storeAndSaveContract } from '../Networks'; -import { getContract, getTestContract } from '../Contract'; - -const CDaiDelegateContract = getContract('CDaiDelegate'); -const CDaiDelegateScenarioContract = getTestContract('CDaiDelegateScenario'); -const CErc20DelegateContract = getContract('CErc20Delegate'); -const CErc20DelegateScenarioContract = getTestContract('CErc20DelegateScenario'); - - -export interface CTokenDelegateData { - invokation: Invokation; - name: string; - contract: string; - description?: string; -} - -export async function buildCTokenDelegate( - world: World, - from: string, - params: Event -): Promise<{ world: World; cTokenDelegate: CErc20Delegate; delegateData: CTokenDelegateData }> { - const fetchers = [ - new Fetcher<{ name: StringV; }, CTokenDelegateData>( - ` - #### CDaiDelegate - - * "CDaiDelegate name:" - * E.g. "CTokenDelegate Deploy CDaiDelegate cDAIDelegate" - `, - 'CDaiDelegate', - [ - new Arg('name', getStringV) - ], - async ( - world, - { name } - ) => { - return { - invokation: await CDaiDelegateContract.deploy(world, from, []), - name: name.val, - contract: 'CDaiDelegate', - description: 'Standard CDai Delegate' - }; - } - ), - - new Fetcher<{ name: StringV; }, CTokenDelegateData>( - ` - #### CDaiDelegateScenario - - * "CDaiDelegateScenario name:" - A CDaiDelegate Scenario for local testing - * E.g. "CTokenDelegate Deploy CDaiDelegateScenario cDAIDelegate" - `, - 'CDaiDelegateScenario', - [ - new Arg('name', getStringV) - ], - async ( - world, - { name } - ) => { - return { - invokation: await CDaiDelegateScenarioContract.deploy(world, from, []), - name: name.val, - contract: 'CDaiDelegateScenario', - description: 'Scenario CDai Delegate' - }; - } - ), - - new Fetcher<{ name: StringV; }, CTokenDelegateData>( - ` - #### CErc20Delegate - - * "CErc20Delegate name:" - * E.g. "CTokenDelegate Deploy CErc20Delegate cDAIDelegate" - `, - 'CErc20Delegate', - [ - new Arg('name', getStringV) - ], - async ( - world, - { name } - ) => { - return { - invokation: await CErc20DelegateContract.deploy(world, from, []), - name: name.val, - contract: 'CErc20Delegate', - description: 'Standard CErc20 Delegate' - }; - } - ), - - new Fetcher<{ name: StringV; }, CTokenDelegateData>( - ` - #### CErc20DelegateScenario - - * "CErc20DelegateScenario name:" - A CErc20Delegate Scenario for local testing - * E.g. "CTokenDelegate Deploy CErc20DelegateScenario cDAIDelegate" - `, - 'CErc20DelegateScenario', - [ - new Arg('name', getStringV), - ], - async ( - world, - { name } - ) => { - return { - invokation: await CErc20DelegateScenarioContract.deploy(world, from, []), - name: name.val, - contract: 'CErc20DelegateScenario', - description: 'Scenario CErc20 Delegate' - }; - } - ) - ]; - - let delegateData = await getFetcherValue("DeployCToken", fetchers, world, params); - let invokation = delegateData.invokation; - delete delegateData.invokation; - - if (invokation.error) { - throw invokation.error; - } - - const cTokenDelegate = invokation.value!; - - world = await storeAndSaveContract( - world, - cTokenDelegate, - delegateData.name, - invokation, - [ - { - index: ['CTokenDelegate', delegateData.name], - data: { - address: cTokenDelegate._address, - contract: delegateData.contract, - description: delegateData.description - } - } - ] - ); - - return { world, cTokenDelegate, delegateData }; -} diff --git a/scenario/src/Builder/CompBuilder.ts b/scenario/src/Builder/CompBuilder.ts deleted file mode 100644 index 0d23cf5d1..000000000 --- a/scenario/src/Builder/CompBuilder.ts +++ /dev/null @@ -1,110 +0,0 @@ -import { Event } from '../Event'; -import { World, addAction } from '../World'; -import { Comp, CompScenario } from '../Contract/Comp'; -import { Invokation } from '../Invokation'; -import { getAddressV } from '../CoreValue'; -import { StringV, AddressV } from '../Value'; -import { Arg, Fetcher, getFetcherValue } from '../Command'; -import { storeAndSaveContract } from '../Networks'; -import { getContract } from '../Contract'; - -const CompContract = getContract('Comp'); -const CompScenarioContract = getContract('CompScenario'); - -export interface TokenData { - invokation: Invokation; - contract: string; - address?: string; - symbol: string; - name: string; - decimals?: number; -} - -export async function buildComp( - world: World, - from: string, - params: Event -): Promise<{ world: World; comp: Comp; tokenData: TokenData }> { - const fetchers = [ - new Fetcher<{ account: AddressV }, TokenData>( - ` - #### Scenario - - * "Comp Deploy Scenario account:
" - Deploys Scenario Comp Token - * E.g. "Comp Deploy Scenario Geoff" - `, - 'Scenario', - [ - new Arg("account", getAddressV), - ], - async (world, { account }) => { - return { - invokation: await CompScenarioContract.deploy(world, from, [account.val]), - contract: 'CompScenario', - symbol: 'COMP', - name: 'Compound Governance Token', - decimals: 18 - }; - } - ), - - new Fetcher<{ account: AddressV }, TokenData>( - ` - #### Comp - - * "Comp Deploy account:
" - Deploys Comp Token - * E.g. "Comp Deploy Geoff" - `, - 'Comp', - [ - new Arg("account", getAddressV), - ], - async (world, { account }) => { - if (world.isLocalNetwork()) { - return { - invokation: await CompScenarioContract.deploy(world, from, [account.val]), - contract: 'CompScenario', - symbol: 'COMP', - name: 'Compound Governance Token', - decimals: 18 - }; - } else { - return { - invokation: await CompContract.deploy(world, from, [account.val]), - contract: 'Comp', - symbol: 'COMP', - name: 'Compound Governance Token', - decimals: 18 - }; - } - }, - { catchall: true } - ) - ]; - - let tokenData = await getFetcherValue("DeployComp", fetchers, world, params); - let invokation = tokenData.invokation; - delete tokenData.invokation; - - if (invokation.error) { - throw invokation.error; - } - - const comp = invokation.value!; - tokenData.address = comp._address; - - world = await storeAndSaveContract( - world, - comp, - 'Comp', - invokation, - [ - { index: ['Comp'], data: tokenData }, - { index: ['Tokens', tokenData.symbol], data: tokenData } - ] - ); - - tokenData.invokation = invokation; - - return { world, comp, tokenData }; -} diff --git a/scenario/src/Builder/ComptrollerImplBuilder.ts b/scenario/src/Builder/ComptrollerImplBuilder.ts deleted file mode 100644 index f01b4d233..000000000 --- a/scenario/src/Builder/ComptrollerImplBuilder.ts +++ /dev/null @@ -1,367 +0,0 @@ -import { Event } from '../Event'; -import { addAction, World } from '../World'; -import { ComptrollerImpl } from '../Contract/ComptrollerImpl'; -import { Invokation, invoke } from '../Invokation'; -import { getAddressV, getExpNumberV, getNumberV, getStringV } from '../CoreValue'; -import { AddressV, NumberV, StringV } from '../Value'; -import { Arg, Fetcher, getFetcherValue } from '../Command'; -import { storeAndSaveContract } from '../Networks'; -import { getContract, getTestContract } from '../Contract'; - -const ComptrollerG1Contract = getContract('ComptrollerG1'); -const ComptrollerScenarioG1Contract = getTestContract('ComptrollerScenarioG1'); - -const ComptrollerG2Contract = getContract('ComptrollerG2'); -const ComptrollerScenarioG2Contract = getContract('ComptrollerScenarioG2'); - -const ComptrollerG3Contract = getContract('ComptrollerG3'); -const ComptrollerScenarioG3Contract = getContract('ComptrollerScenarioG3'); - -const ComptrollerG4Contract = getContract('ComptrollerG4'); -const ComptrollerScenarioG4Contract = getContract('ComptrollerScenarioG4'); - -const ComptrollerG5Contract = getContract('ComptrollerG5'); -const ComptrollerScenarioG5Contract = getContract('ComptrollerScenarioG5'); - -const ComptrollerG6Contract = getContract('ComptrollerG6'); -const ComptrollerScenarioG6Contract = getContract('ComptrollerScenarioG6'); - -const ComptrollerScenarioContract = getTestContract('ComptrollerScenario'); -const ComptrollerContract = getContract('Comptroller'); - -const ComptrollerBorkedContract = getTestContract('ComptrollerBorked'); - -export interface ComptrollerImplData { - invokation: Invokation; - name: string; - contract: string; - description: string; -} - -export async function buildComptrollerImpl( - world: World, - from: string, - event: Event -): Promise<{ world: World; comptrollerImpl: ComptrollerImpl; comptrollerImplData: ComptrollerImplData }> { - const fetchers = [ - new Fetcher<{ name: StringV }, ComptrollerImplData>( - ` - #### ScenarioG1 - - * "ScenarioG1 name:" - The Comptroller Scenario for local testing (G1) - * E.g. "ComptrollerImpl Deploy ScenarioG1 MyScen" - `, - 'ScenarioG1', - [new Arg('name', getStringV)], - async (world, { name }) => ({ - invokation: await ComptrollerScenarioG1Contract.deploy(world, from, []), - name: name.val, - contract: 'ComptrollerScenarioG1', - description: 'ScenarioG1 Comptroller Impl' - }) - ), - - new Fetcher<{ name: StringV }, ComptrollerImplData>( - ` - #### ScenarioG2 - - * "ScenarioG2 name:" - The Comptroller Scenario for local testing (G2) - * E.g. "ComptrollerImpl Deploy ScenarioG2 MyScen" - `, - 'ScenarioG2', - [new Arg('name', getStringV)], - async (world, { name }) => ({ - invokation: await ComptrollerScenarioG2Contract.deploy(world, from, []), - name: name.val, - contract: 'ComptrollerScenarioG2Contract', - description: 'ScenarioG2 Comptroller Impl' - }) - ), - - new Fetcher<{ name: StringV }, ComptrollerImplData>( - ` - #### ScenarioG3 - - * "ScenarioG3 name:" - The Comptroller Scenario for local testing (G3) - * E.g. "ComptrollerImpl Deploy ScenarioG3 MyScen" - `, - 'ScenarioG3', - [new Arg('name', getStringV)], - async (world, { name }) => ({ - invokation: await ComptrollerScenarioG3Contract.deploy(world, from, []), - name: name.val, - contract: 'ComptrollerScenarioG3Contract', - description: 'ScenarioG3 Comptroller Impl' - }) - ), - - new Fetcher<{ name: StringV }, ComptrollerImplData>( - ` - #### ScenarioG4 - * "ScenarioG4 name:" - The Comptroller Scenario for local testing (G4) - * E.g. "ComptrollerImpl Deploy ScenarioG4 MyScen" - `, - 'ScenarioG4', - [new Arg('name', getStringV)], - async (world, { name }) => ({ - invokation: await ComptrollerScenarioG4Contract.deploy(world, from, []), - name: name.val, - contract: 'ComptrollerScenarioG4Contract', - description: 'ScenarioG4 Comptroller Impl' - }) - ), - - new Fetcher<{ name: StringV }, ComptrollerImplData>( - ` - #### ScenarioG5 - * "ScenarioG5 name:" - The Comptroller Scenario for local testing (G5) - * E.g. "ComptrollerImpl Deploy ScenarioG5 MyScen" - `, - 'ScenarioG5', - [new Arg('name', getStringV)], - async (world, { name }) => ({ - invokation: await ComptrollerScenarioG5Contract.deploy(world, from, []), - name: name.val, - contract: 'ComptrollerScenarioG5Contract', - description: 'ScenarioG5 Comptroller Impl' - }) - ), - - new Fetcher<{ name: StringV }, ComptrollerImplData>( - ` - #### ScenarioG6 - * "ScenarioG6 name:" - The Comptroller Scenario for local testing (G6) - * E.g. "ComptrollerImpl Deploy ScenarioG6 MyScen" - `, - 'ScenarioG6', - [new Arg('name', getStringV)], - async (world, { name }) => ({ - invokation: await ComptrollerScenarioG6Contract.deploy(world, from, []), - name: name.val, - contract: 'ComptrollerScenarioG6Contract', - description: 'ScenarioG6 Comptroller Impl' - }) - ), - - new Fetcher<{ name: StringV }, ComptrollerImplData>( - ` - #### Scenario - - * "Scenario name:" - The Comptroller Scenario for local testing - * E.g. "ComptrollerImpl Deploy Scenario MyScen" - `, - 'Scenario', - [new Arg('name', getStringV)], - async (world, { name }) => ({ - invokation: await ComptrollerScenarioContract.deploy(world, from, []), - name: name.val, - contract: 'ComptrollerScenario', - description: 'Scenario Comptroller Impl' - }) - ), - - new Fetcher<{ name: StringV }, ComptrollerImplData>( - ` - #### StandardG1 - - * "StandardG1 name:" - The standard generation 1 Comptroller contract - * E.g. "Comptroller Deploy StandardG1 MyStandard" - `, - 'StandardG1', - [new Arg('name', getStringV)], - async (world, { name }) => { - return { - invokation: await ComptrollerG1Contract.deploy(world, from, []), - name: name.val, - contract: 'ComptrollerG1', - description: 'StandardG1 Comptroller Impl' - }; - } - ), - - new Fetcher<{ name: StringV }, ComptrollerImplData>( - ` - #### StandardG2 - - * "StandardG2 name:" - The standard generation 2 Comptroller contract - * E.g. "Comptroller Deploy StandardG2 MyStandard" - `, - 'StandardG2', - [new Arg('name', getStringV)], - async (world, { name }) => { - return { - invokation: await ComptrollerG2Contract.deploy(world, from, []), - name: name.val, - contract: 'ComptrollerG2', - description: 'StandardG2 Comptroller Impl' - }; - } - ), - - new Fetcher<{ name: StringV }, ComptrollerImplData>( - ` - #### StandardG3 - - * "StandardG3 name:" - The standard generation 3 Comptroller contract - * E.g. "Comptroller Deploy StandardG3 MyStandard" - `, - 'StandardG3', - [new Arg('name', getStringV)], - async (world, { name }) => { - return { - invokation: await ComptrollerG3Contract.deploy(world, from, []), - name: name.val, - contract: 'ComptrollerG3', - description: 'StandardG3 Comptroller Impl' - }; - } - ), - - new Fetcher<{ name: StringV }, ComptrollerImplData>( - ` - #### StandardG4 - - * "StandardG4 name:" - The standard generation 4 Comptroller contract - * E.g. "Comptroller Deploy StandardG4 MyStandard" - `, - 'StandardG4', - [new Arg('name', getStringV)], - async (world, { name }) => { - return { - invokation: await ComptrollerG4Contract.deploy(world, from, []), - name: name.val, - contract: 'ComptrollerG4', - description: 'StandardG4 Comptroller Impl' - }; - } - ), - - new Fetcher<{ name: StringV }, ComptrollerImplData>( - ` - #### StandardG5 - * "StandardG5 name:" - The standard generation 5 Comptroller contract - * E.g. "Comptroller Deploy StandardG5 MyStandard" - `, - 'StandardG5', - [new Arg('name', getStringV)], - async (world, { name }) => { - return { - invokation: await ComptrollerG5Contract.deploy(world, from, []), - name: name.val, - contract: 'ComptrollerG5', - description: 'StandardG5 Comptroller Impl' - }; - } - ), - - new Fetcher<{ name: StringV }, ComptrollerImplData>( - ` - #### StandardG6 - * "StandardG6 name:" - The standard generation 6 Comptroller contract - * E.g. "Comptroller Deploy StandardG6 MyStandard" - `, - 'StandardG6', - [new Arg('name', getStringV)], - async (world, { name }) => { - return { - invokation: await ComptrollerG6Contract.deploy(world, from, []), - name: name.val, - contract: 'ComptrollerG6', - description: 'StandardG6 Comptroller Impl' - }; - } - ), - - new Fetcher<{ name: StringV }, ComptrollerImplData>( - ` - #### Standard - - * "Standard name:" - The standard Comptroller contract - * E.g. "Comptroller Deploy Standard MyStandard" - `, - 'Standard', - [new Arg('name', getStringV)], - async (world, { name }) => { - return { - invokation: await ComptrollerContract.deploy(world, from, []), - name: name.val, - contract: 'Comptroller', - description: 'Standard Comptroller Impl' - }; - } - ), - - new Fetcher<{ name: StringV }, ComptrollerImplData>( - ` - #### Borked - - * "Borked name:" - A Borked Comptroller for testing - * E.g. "ComptrollerImpl Deploy Borked MyBork" - `, - 'Borked', - [new Arg('name', getStringV)], - async (world, { name }) => ({ - invokation: await ComptrollerBorkedContract.deploy(world, from, []), - name: name.val, - contract: 'ComptrollerBorked', - description: 'Borked Comptroller Impl' - }) - ), - new Fetcher<{ name: StringV }, ComptrollerImplData>( - ` - #### Default - - * "name:" - The standard Comptroller contract - * E.g. "ComptrollerImpl Deploy MyDefault" - `, - 'Default', - [new Arg('name', getStringV)], - async (world, { name }) => { - if (world.isLocalNetwork()) { - // Note: we're going to use the scenario contract as the standard deployment on local networks - return { - invokation: await ComptrollerScenarioContract.deploy(world, from, []), - name: name.val, - contract: 'ComptrollerScenario', - description: 'Scenario Comptroller Impl' - }; - } else { - return { - invokation: await ComptrollerContract.deploy(world, from, []), - name: name.val, - contract: 'Comptroller', - description: 'Standard Comptroller Impl' - }; - } - }, - { catchall: true } - ) - ]; - - let comptrollerImplData = await getFetcherValue( - 'DeployComptrollerImpl', - fetchers, - world, - event - ); - let invokation = comptrollerImplData.invokation; - delete comptrollerImplData.invokation; - - if (invokation.error) { - throw invokation.error; - } - const comptrollerImpl = invokation.value!; - - world = await storeAndSaveContract(world, comptrollerImpl, comptrollerImplData.name, invokation, [ - { - index: ['Comptroller', comptrollerImplData.name], - data: { - address: comptrollerImpl._address, - contract: comptrollerImplData.contract, - description: comptrollerImplData.description - } - } - ]); - - return { world, comptrollerImpl, comptrollerImplData }; -} diff --git a/scenario/src/Builder/Erc20Builder.ts b/scenario/src/Builder/Erc20Builder.ts deleted file mode 100644 index 4ccfad1ae..000000000 --- a/scenario/src/Builder/Erc20Builder.ts +++ /dev/null @@ -1,271 +0,0 @@ - -import {Event} from '../Event'; -import {addAction, World} from '../World'; -import {Erc20} from '../Contract/Erc20'; -import {Invokation, invoke} from '../Invokation'; -import { - getAddressV, - getCoreValue, - getNumberV, - getStringV -} from '../CoreValue'; -import { - AddressV, - NumberV, - StringV, - Value -} from '../Value'; -import {Arg, Fetcher, getFetcherValue} from '../Command'; -import {storeAndSaveContract} from '../Networks'; -import {getContract, getTestContract} from '../Contract'; -import {encodeABI} from '../Utils'; - -const ExistingToken = getContract("EIP20Interface"); -const TetherInterface = getContract("TetherInterface"); - -const FaucetTokenHarness = getContract("FaucetToken"); -const FaucetTokenNonStandardHarness = getContract("FaucetNonStandardToken"); -const FaucetTokenReEntrantHarness = getContract("FaucetTokenReEntrantHarness"); -const EvilTokenHarness = getContract("EvilToken"); -const WBTCTokenHarness = getContract("WBTCToken"); -const FeeTokenHarness = getContract("FeeToken"); - -export interface TokenData { - invokation: Invokation, - description: string, - name: string, - symbol: string, - decimals?: number, - address?: string, - contract: string -} - -export async function buildErc20(world: World, from: string, event: Event): Promise<{ world: World, erc20: Erc20, tokenData: TokenData }> { - const fetchers = [ - new Fetcher<{ symbol: StringV, address: AddressV, name: StringV }, TokenData>(` - #### Existing - - * "Existing symbol: address:
name:" - Wrap an existing Erc20 token - * E.g. "Erc20 Deploy Existing DAI 0x123... - `, - "Existing", - [ - new Arg("symbol", getStringV), - new Arg("address", getAddressV), - new Arg("name", getStringV, { default: undefined }), - ], - async (world, { symbol, name, address }) => { - const existingToken = await ExistingToken.at(world, address.val); - const tokenName = name.val === undefined ? symbol.val : name.val; - const decimals = await existingToken.methods.decimals().call(); - - return { - invokation: new Invokation(existingToken, null, null, null), - description: "Existing", - decimals: Number(decimals), - name: tokenName, - symbol: symbol.val, - contract: 'ExistingToken' - }; - } - ), - - new Fetcher<{symbol: StringV, address: AddressV}, TokenData>(` - #### ExistingTether - - * "Existing symbol: address:
" - Wrap an existing Erc20 token - * E.g. "Erc20 Deploy ExistingTether USDT 0x123... - `, - "ExistingTether", - [ - new Arg("symbol", getStringV), - new Arg("address", getAddressV) - ], - async (world, {symbol, address}) => { - return { - invokation: new Invokation(await TetherInterface.at(world, address.val), null, null, null), - description: "ExistingTether", - name: symbol.val, - symbol: symbol.val, - contract: 'TetherInterface' - }; - } - ), - - new Fetcher<{symbol: StringV, name: StringV, decimals: NumberV}, TokenData>(` - #### NonStandard - - * "NonStandard symbol: name: decimals:" - A non-standard token, like BAT - * E.g. "Erc20 Deploy NonStandard BAT \"Basic Attention Token\" 18" - `, - "NonStandard", - [ - new Arg("symbol", getStringV), - new Arg("name", getStringV), - new Arg("decimals", getNumberV, {default: new NumberV(18)}), - ], - async (world, {symbol, name, decimals}) => { - return { - invokation: await FaucetTokenNonStandardHarness.deploy(world, from, [0, name.val, decimals.val, symbol.val]), - description: "NonStandard", - name: name.val, - symbol: symbol.val, - decimals: decimals.toNumber(), - contract: 'FaucetNonStandardToken' - }; - } - ), - - new Fetcher<{symbol: StringV, name: StringV, fun:StringV, reEntryFunSig: StringV, reEntryFunArgs: StringV[]}, TokenData>(` - #### ReEntrant - - * "ReEntrant symbol: name:string fun: funSig: ...funArgs:" - A token that loves to call back to spook its caller - * E.g. "Erc20 Deploy ReEntrant PHREAK PHREAK "transfer" "mint(uint256)" 0 - A token that will call back to a CToken's mint function - - Note: valid functions: totalSupply, balanceOf, transfer, transferFrom, approve, allowance - `, - "ReEntrant", - [ - new Arg("symbol", getStringV), - new Arg("name", getStringV), - new Arg("fun", getStringV), - new Arg("reEntryFunSig", getStringV), - new Arg("reEntryFunArgs", getStringV, {variadic: true, mapped: true}) - ], - async (world, {symbol, name, fun, reEntryFunSig, reEntryFunArgs}) => { - const fnData = encodeABI(world, reEntryFunSig.val, reEntryFunArgs.map((a) => a.val)); - - return { - invokation: await FaucetTokenReEntrantHarness.deploy(world, from, [0, name.val, 18, symbol.val, fnData, fun.val]), - description: "ReEntrant", - name: name.val, - symbol: symbol.val, - decimals: 18, - contract: 'FaucetTokenReEntrantHarness' - }; - } - ), - - new Fetcher<{symbol: StringV, name: StringV, decimals: NumberV}, TokenData>(` - #### Evil - - * "Evil symbol: name: decimals:" - A less vanilla ERC-20 contract that fails transfers - * E.g. "Erc20 Deploy Evil BAT \"Basic Attention Token\" 18" - `, - "Evil", - [ - new Arg("symbol", getStringV), - new Arg("name", getStringV), - new Arg("decimals", getNumberV, {default: new NumberV(18)}) - ], - async (world, {symbol, name, decimals}) => { - return { - invokation: await EvilTokenHarness.deploy(world, from, [0, name.val, decimals.val, symbol.val]), - description: "Evil", - name: name.val, - symbol: symbol.val, - decimals: decimals.toNumber(), - contract: 'EvilToken' - }; - } - ), - - new Fetcher<{symbol: StringV, name: StringV, decimals: NumberV}, TokenData>(` - #### Standard - - * "Standard symbol: name: decimals:" - A vanilla ERC-20 contract - * E.g. "Erc20 Deploy Standard BAT \"Basic Attention Token\" 18" - `, - "Standard", - [ - new Arg("symbol", getStringV), - new Arg("name", getStringV), - new Arg("decimals", getNumberV, {default: new NumberV(18)}) - ], - async (world, {symbol, name, decimals}) => { - return { - invokation: await FaucetTokenHarness.deploy(world, from, [0, name.val, decimals.val, symbol.val]), - description: "Standard", - name: name.val, - symbol: symbol.val, - decimals: decimals.toNumber(), - contract: 'FaucetToken' - }; - } - ), - - new Fetcher<{symbol: StringV, name: StringV}, TokenData>(` - #### WBTC - - * "WBTC symbol: name:" - The WBTC contract - * E.g. "Erc20 Deploy WBTC WBTC \"Wrapped Bitcoin\"" - `, - "WBTC", - [ - new Arg("symbol", getStringV, {default: new StringV("WBTC")}), - new Arg("name", getStringV, {default: new StringV("Wrapped Bitcoin")}) - ], - async (world, {symbol, name}) => { - let decimals = 8; - - return { - invokation: await WBTCTokenHarness.deploy(world, from, []), - description: "WBTC", - name: name.val, - symbol: symbol.val, - decimals: decimals, - contract: 'WBTCToken' - }; - } - ), - - new Fetcher<{symbol: StringV, name: StringV, decimals: NumberV, basisPointFee: NumberV, owner: AddressV}, TokenData>(` - #### Fee - - * "Fee symbol: name: decimals: basisPointFee: owner:
" - An ERC20 whose owner takes a fee on transfers. Used for mocking USDT. - * E.g. "Erc20 Deploy Fee USDT USDT 100 Root" - `, - "Fee", - [ - new Arg("symbol", getStringV), - new Arg("name", getStringV), - new Arg("decimals", getNumberV), - new Arg("basisPointFee", getNumberV), - new Arg("owner", getAddressV) - ], - async (world, {symbol, name, decimals, basisPointFee, owner}) => { - return { - invokation: await FeeTokenHarness.deploy(world, from, [0, name.val, decimals.val, symbol.val, basisPointFee.val, owner.val]), - description: "Fee", - name: name.val, - symbol: symbol.val, - decimals: decimals.toNumber(), - owner: owner.val, - contract: 'FeeToken' - }; - } - ), - ]; - - let tokenData = await getFetcherValue("DeployErc20", fetchers, world, event); - let invokation = tokenData.invokation; - delete tokenData.invokation; - - if (invokation.error) { - throw invokation.error; - } - const erc20 = invokation.value!; - tokenData.address = erc20._address; - - world = await storeAndSaveContract( - world, - erc20, - tokenData.symbol, - invokation, - [ - { index: ['Tokens', tokenData.symbol], data: tokenData } - ] - ); - - return {world, erc20, tokenData}; -} diff --git a/scenario/src/Builder/InterestRateModelBuilder.ts b/scenario/src/Builder/InterestRateModelBuilder.ts deleted file mode 100644 index a1663fd49..000000000 --- a/scenario/src/Builder/InterestRateModelBuilder.ts +++ /dev/null @@ -1,219 +0,0 @@ -import {Event} from '../Event'; -import {addAction, World} from '../World'; -import {InterestRateModel} from '../Contract/InterestRateModel'; -import {Invokation, invoke} from '../Invokation'; -import { - getAddressV, - getExpNumberV, - getNumberV, - getPercentV, - getStringV, -} from '../CoreValue'; -import { - AddressV, - EventV, - NumberV, - StringV, -} from '../Value'; -import {Arg, Fetcher, getFetcherValue} from '../Command'; -import {storeAndSaveContract} from '../Networks'; -import {getContract, getTestContract} from '../Contract'; - -const FixedInterestRateModel = getTestContract('InterestRateModelHarness'); -const WhitePaperInterestRateModel = getContract('WhitePaperInterestRateModel'); -const JumpRateModel = getContract('JumpRateModel'); -const DAIInterestRateModel = getContract('DAIInterestRateModelV3'); -const JumpRateModelV2 = getContract('JumpRateModelV2'); -const LegacyJumpRateModelV2 = getContract('LegacyJumpRateModelV2'); - -export interface InterestRateModelData { - invokation: Invokation - address?: string - name: string - contract: string - description: string - base?: string - slope?: string - kink?: string - jump?: string -} - -export async function buildInterestRateModel(world: World, from: string, event: Event): Promise<{world: World, interestRateModel: InterestRateModel, interestRateModelData: InterestRateModelData}> { - const fetchers = [ - new Fetcher<{name: StringV, rate: NumberV}, InterestRateModelData>(` - #### Fixed - - * "Fixed name: rate:" - Fixed interest **per-block** rate - * E.g. "InterestRateModel Deploy Fixed MyInterestRateModel 0.5" - `, - "Fixed", - [ - new Arg("name", getStringV), - new Arg("rate", getPercentV), - ], - async (world, {name, rate}) => ({ - invokation: await FixedInterestRateModel.deploy(world, from, [rate.encode()]), - name: name.val, - contract: "InterestRateModelHarness", - description: `Fixed rate ${rate.show()} per block` - }) - ), - - new Fetcher<{name: StringV, baseRate: NumberV, multiplier: NumberV}, InterestRateModelData>(` - #### WhitePaper - - * "WhitePaper name: baseRate: multiplier:" - The WhitePaper interest rate - * E.g. "InterestRateModel Deploy WhitePaper MyInterestRateModel 0.05 0.2" - 5% base rate and 20% utilization multiplier - `, - "WhitePaper", - [ - new Arg("name", getStringV), - new Arg("baseRate", getExpNumberV), - new Arg("multiplier", getExpNumberV) - ], - async (world, {name, baseRate, multiplier}) => ({ - invokation: await WhitePaperInterestRateModel.deploy(world, from, [baseRate.encode(), multiplier.encode()]), - name: name.val, - contract: "WhitePaperInterestRateModel", - description: `WhitePaper baseRate=${baseRate.encode().toString()} multiplier=${multiplier.encode().toString()}`, - base: baseRate.encode().toString(), - slope: multiplier.encode().toString() - }) - ), - - new Fetcher<{name: StringV, baseRate: NumberV, multiplier: NumberV, jump: NumberV, kink: NumberV}, InterestRateModelData>(` - #### JumpRateModel - - * "JumpRateModel name: baseRate: multiplier: jump: kink:" - The Jump interest rate - * E.g. "InterestRateModel Deploy JumpRateModel MyInterestRateModel 0.05 0.2 2 0.90" - 5% base rate and 20% utilization multiplier and 200% multiplier at 90% utilization - `, - "JumpRateModel", - [ - new Arg("name", getStringV), - new Arg("baseRate", getExpNumberV), - new Arg("multiplier", getExpNumberV), - new Arg("jump", getExpNumberV), - new Arg("kink", getExpNumberV) - ], - async (world, {name, baseRate, multiplier, jump, kink}) => ({ - invokation: await JumpRateModel.deploy(world, from, [baseRate.encode(), multiplier.encode(), jump.encode(), kink.val]), - name: name.val, - contract: "JumpRateModel", - description: `JumpRateModel baseRate=${baseRate.encode().toString()} multiplier=${multiplier.encode().toString()} jump=${jump.encode().toString()} kink=${kink.encode().toString()}`, - base: baseRate.encode().toString(), - slope: multiplier.encode().toString(), - jump: jump.encode().toString(), - kink: kink.encode().toString() - }) - ), - - new Fetcher<{name: StringV, baseRate: NumberV, multiplier: NumberV, jump: NumberV, kink: NumberV, owner: AddressV}, InterestRateModelData>(` - #### JumpRateModelV2 - - * "JumpRateModelV2 name: baseRate: multiplier: jump: kink: owner:
" - The v2 Jump interest rate model - * E.g. "InterestRateModel Deploy JumpRateModelV2 MyInterestRateModel 0.05 0.2 2 0.90 (Address Timelock)" - 5% base rate and 20% + 5% interest at kink and 200% multiplier starting at the kink of 90% utilization - `, - "JumpRateModelV2", - [ - new Arg("name", getStringV), - new Arg("baseRate", getExpNumberV), - new Arg("multiplier", getExpNumberV), - new Arg("jump", getExpNumberV), - new Arg("kink", getExpNumberV), - new Arg("owner", getAddressV), - ], - async (world, {name, baseRate, multiplier, jump, kink, owner}) => ({ - invokation: await JumpRateModelV2.deploy(world, from, [baseRate.encode(), multiplier.encode(), jump.encode(), kink.encode(), owner.val]), - name: name.val, - contract: "JumpRateModelV2", - description: `JumpRateModelV2 baseRate=${baseRate.encode().toString()} multiplier=${multiplier.encode().toString()} jump=${jump.encode().toString()} kink=${kink.encode().toString()}`, - base: baseRate.encode().toString(), - slope: multiplier.encode().toString(), - jump: jump.encode().toString(), - kink: kink.encode().toString(), - owner: owner.val, - }) - ), - - new Fetcher<{name: StringV, baseRate: NumberV, multiplier: NumberV, jump: NumberV, kink: NumberV, owner: AddressV}, InterestRateModelData>(` - #### LegacyJumpRateModelV2 - - * "LegacyJumpRateModelV2 name: baseRate: multiplier: jump: kink: owner:
" - The legacy v2 Jump interest rate model - * E.g. "InterestRateModel Deploy LegacyJumpRateModelV2 MyInterestRateModel 0.05 0.2 2 0.90 (Address Timelock)" - 5% base rate and 20% + 5% interest at kink and 200% multiplier starting at the kink of 90% utilization - `, - "LegacyJumpRateModelV2", - [ - new Arg("name", getStringV), - new Arg("baseRate", getExpNumberV), - new Arg("multiplier", getExpNumberV), - new Arg("jump", getExpNumberV), - new Arg("kink", getExpNumberV), - new Arg("owner", getAddressV), - ], - async (world, {name, baseRate, multiplier, jump, kink, owner}) => ({ - invokation: await LegacyJumpRateModelV2.deploy(world, from, [baseRate.encode(), multiplier.encode(), jump.encode(), kink.encode(), owner.val]), - name: name.val, - contract: "LegacyJumpRateModelV2", - description: `LegacyJumpRateModelV2 baseRate=${baseRate.encode().toString()} multiplier=${multiplier.encode().toString()} jump=${jump.encode().toString()} kink=${kink.encode().toString()}`, - base: baseRate.encode().toString(), - slope: multiplier.encode().toString(), - jump: jump.encode().toString(), - kink: kink.encode().toString(), - owner: owner.val, - }) - ), - - new Fetcher<{name: StringV, jump: NumberV, kink: NumberV, pot: AddressV, jug: AddressV, owner: AddressV}, InterestRateModelData>(` - #### DAIInterestRateModel - - * "DAIInterestRateModel name: jump: kink: pot:
jug:
owner:
" - The DAI interest rate model - * E.g. "InterestRateModel Deploy DAIInterestRateModel MyInterestRateModel (Exp 2) (Exp 0.9) PotAddress JugAddress" Timelock - 200% multiplier at 90% utilization - `, - "DAIInterestRateModel", - [ - new Arg("name", getStringV), - new Arg("jump", getExpNumberV), - new Arg("kink", getExpNumberV), - new Arg("pot", getAddressV), - new Arg("jug", getAddressV), - new Arg("owner", getAddressV), - ], - async (world, {name, jump, kink, pot, jug, owner}) => ({ - invokation: await DAIInterestRateModel.deploy(world, from, [jump.encode(), kink.encode(), pot.val, jug.val, owner.val]), - name: name.val, - contract: "DAIInterestRateModel", - description: `DAIInterestRateModel jump=${jump.encode().toString()} kink=${kink.encode().toString()} pot=${pot.val} jug=${jug.val} owner=${owner.val}`, - jump: jump.encode().toString(), - kink: kink.encode().toString(), - pot: pot.val, - jug: jug.val, - owner: owner.val - }) - ) - ]; - - let interestRateModelData = await getFetcherValue("DeployInterestRateModel", fetchers, world, event); - let invokation = interestRateModelData.invokation; - delete interestRateModelData.invokation; - - if (invokation.error) { - throw invokation.error; - } - const interestRateModel = invokation.value!; - interestRateModelData.address = interestRateModel._address; - - world = await storeAndSaveContract( - world, - interestRateModel, - interestRateModelData.name, - invokation, - [ - { - index: ['InterestRateModel', interestRateModelData.name], - data: interestRateModelData - } - ] - ); - - return {world, interestRateModel, interestRateModelData}; -} diff --git a/scenario/src/Builder/PriceOracleBuilder.ts b/scenario/src/Builder/PriceOracleBuilder.ts deleted file mode 100644 index 5888bd623..000000000 --- a/scenario/src/Builder/PriceOracleBuilder.ts +++ /dev/null @@ -1,165 +0,0 @@ -import {Event} from '../Event'; -import {addAction, World} from '../World'; -import {PriceOracle} from '../Contract/PriceOracle'; -import {Invokation, invoke} from '../Invokation'; -import { - getAddressV, - getExpNumberV, - getStringV -} from '../CoreValue'; -import { - AddressV, - EventV, - NothingV, - NumberV, - StringV -} from '../Value'; -import {Arg, Fetcher, getFetcherValue} from '../Command'; -import {storeAndSaveContract} from '../Networks'; -import {getContract, getTestContract} from '../Contract'; - -const FixedPriceOracle = getTestContract('FixedPriceOracle'); -const SimplePriceOracle = getContract('SimplePriceOracle'); -const AnchorPriceOracle = getContract('AnchorPriceOracle'); -const NotPriceOracle = getTestContract('NotPriceOracle'); -const PriceOracleInterface = getTestContract('PriceOracle'); - -export interface PriceOracleData { - invokation?: Invokation, - contract?: PriceOracle, - description: string, - address?: string -} - -export async function buildPriceOracle(world: World, from: string, event: Event): Promise<{world: World, priceOracle: PriceOracle, priceOracleData: PriceOracleData}> { - const fetchers = [ - new Fetcher<{price: NumberV}, PriceOracleData>(` - #### Fixed - - * "Fixed price:" - Fixed price - * E.g. "PriceOracle Deploy (Fixed 20.0)" - `, - "Fixed", - [ - new Arg("price", getExpNumberV), - ], - async (world, {price}) => { - return { - invokation: await FixedPriceOracle.deploy(world, from, [price.val]), - description: "Fixed Price Oracle" - }; - } - ), - new Fetcher<{}, PriceOracleData>(` - #### Simple - - * "Simple" - The a simple price oracle that has a harness price setter - * E.g. "PriceOracle Deploy Simple" - `, - "Simple", - [], - async (world, {}) => { - return { - invokation: await SimplePriceOracle.deploy(world, from, []), - description: "Simple Price Oracle" - }; - } - ), - new Fetcher<{poster: AddressV}, PriceOracleData>(` - #### Anchor - - * "Anchor " - The anchor price oracle that caps price movements to anchors - * E.g. "PriceOracle Deploy Anchor 0x..." - `, - "Anchor", - [ - new Arg("poster", getAddressV) - ], - async (world, {poster}) => { - return { - invokation: await AnchorPriceOracle.deploy(world, from, [poster.val]), - description: "Anchor Price Oracle", - poster: poster.val - }; - } - ), - new Fetcher<{}, PriceOracleData>(` - #### NotPriceOracle - - * "NotPriceOracle" - Not actually a price oracle - * E.g. "PriceOracle Deploy NotPriceOracle" - `, - "NotPriceOracle", - [], - async (world, {}) => { - return { - invokation: await NotPriceOracle.deploy(world, from, []), - description: "Not a Price Oracle" - }; - } - ) - ]; - - let priceOracleData = await getFetcherValue("DeployPriceOracle", fetchers, world, event); - let invokation = priceOracleData.invokation!; - delete priceOracleData.invokation; - - if (invokation.error) { - throw invokation.error; - } - const priceOracle = invokation.value!; - priceOracleData.address = priceOracle._address; - - world = await storeAndSaveContract( - world, - priceOracle, - 'PriceOracle', - invokation, - [ - { index: ['PriceOracle'], data: priceOracleData } - ] - ); - - return {world, priceOracle, priceOracleData}; -} - -export async function setPriceOracle(world: World, event: Event): Promise<{world: World, priceOracle: PriceOracle, priceOracleData: PriceOracleData}> { - const fetchers = [ - new Fetcher<{address: AddressV, description: StringV}, PriceOracleData>(` - #### Standard - - * "Standard" - The standard price oracle - * E.g. "PriceOracle Set Standard \"0x...\" \"Standard Price Oracle\"" - `, - "Standard", - [ - new Arg("address", getAddressV), - new Arg("description", getStringV), - ], - async (world, {address, description}) => { - return { - contract: await PriceOracleInterface.at(world, address.val), - description: description.val - }; - } - ) - ]; - - let priceOracleData = await getFetcherValue("SetPriceOracle", fetchers, world, event); - let priceOracle = priceOracleData.contract!; - delete priceOracleData.contract; - - priceOracleData.address = priceOracle._address; - - world = await storeAndSaveContract( - world, - priceOracle, - 'PriceOracle', - null, - [ - { index: ['PriceOracle'], data: priceOracleData } - ] - ); - - return {world, priceOracle, priceOracleData}; -} diff --git a/scenario/src/Builder/PriceOracleProxyBuilder.ts b/scenario/src/Builder/PriceOracleProxyBuilder.ts deleted file mode 100644 index 5807371ba..000000000 --- a/scenario/src/Builder/PriceOracleProxyBuilder.ts +++ /dev/null @@ -1,77 +0,0 @@ -import {Event} from '../Event'; -import {addAction, World} from '../World'; -import {PriceOracleProxy} from '../Contract/PriceOracleProxy'; -import {Invokation} from '../Invokation'; -import {Arg, Fetcher, getFetcherValue} from '../Command'; -import {storeAndSaveContract} from '../Networks'; -import {getContract} from '../Contract'; -import {getAddressV} from '../CoreValue'; -import {AddressV} from '../Value'; - -const PriceOracleProxyContract = getContract("PriceOracleProxy"); - -export interface PriceOracleProxyData { - invokation?: Invokation, - contract?: PriceOracleProxy, - description: string, - address?: string, - cETH: string, - cUSDC: string, - cDAI: string -} - -export async function buildPriceOracleProxy(world: World, from: string, event: Event): Promise<{world: World, priceOracleProxy: PriceOracleProxy, invokation: Invokation}> { - const fetchers = [ - new Fetcher<{guardian: AddressV, priceOracle: AddressV, cETH: AddressV, cUSDC: AddressV, cSAI: AddressV, cDAI: AddressV, cUSDT: AddressV}, PriceOracleProxyData>(` - #### Price Oracle Proxy - - * "Deploy " - The Price Oracle which proxies to a backing oracle - * E.g. "PriceOracleProxy Deploy Admin (PriceOracle Address) cETH cUSDC cSAI cDAI cUSDT" - `, - "PriceOracleProxy", - [ - new Arg("guardian", getAddressV), - new Arg("priceOracle", getAddressV), - new Arg("cETH", getAddressV), - new Arg("cUSDC", getAddressV), - new Arg("cSAI", getAddressV), - new Arg("cDAI", getAddressV), - new Arg("cUSDT", getAddressV) - ], - async (world, {guardian, priceOracle, cETH, cUSDC, cSAI, cDAI, cUSDT}) => { - return { - invokation: await PriceOracleProxyContract.deploy(world, from, [guardian.val, priceOracle.val, cETH.val, cUSDC.val, cSAI.val, cDAI.val, cUSDT.val]), - description: "Price Oracle Proxy", - cETH: cETH.val, - cUSDC: cUSDC.val, - cSAI: cSAI.val, - cDAI: cDAI.val, - cUSDT: cUSDT.val - }; - }, - {catchall: true} - ) - ]; - - let priceOracleProxyData = await getFetcherValue("DeployPriceOracleProxy", fetchers, world, event); - let invokation = priceOracleProxyData.invokation!; - delete priceOracleProxyData.invokation; - - if (invokation.error) { - throw invokation.error; - } - const priceOracleProxy = invokation.value!; - priceOracleProxyData.address = priceOracleProxy._address; - - world = await storeAndSaveContract( - world, - priceOracleProxy, - 'PriceOracleProxy', - invokation, - [ - { index: ['PriceOracleProxy'], data: priceOracleProxyData } - ] - ); - - return {world, priceOracleProxy, invokation}; -} diff --git a/scenario/src/Builder/UnitrollerBuilder.ts b/scenario/src/Builder/UnitrollerBuilder.ts deleted file mode 100644 index d934dec9f..000000000 --- a/scenario/src/Builder/UnitrollerBuilder.ts +++ /dev/null @@ -1,58 +0,0 @@ -import {Event} from '../Event'; -import {addAction, World} from '../World'; -import {Unitroller} from '../Contract/Unitroller'; -import {Invokation} from '../Invokation'; -import {Arg, Fetcher, getFetcherValue} from '../Command'; -import {storeAndSaveContract} from '../Networks'; -import {getContract} from '../Contract'; - -const UnitrollerContract = getContract("Unitroller"); - -export interface UnitrollerData { - invokation: Invokation, - description: string, - address?: string -} - -export async function buildUnitroller(world: World, from: string, event: Event): Promise<{world: World, unitroller: Unitroller, unitrollerData: UnitrollerData}> { - const fetchers = [ - new Fetcher<{}, UnitrollerData>(` - #### Unitroller - - * "" - The Upgradable Comptroller - * E.g. "Unitroller Deploy" - `, - "Unitroller", - [], - async (world, {}) => { - return { - invokation: await UnitrollerContract.deploy(world, from, []), - description: "Unitroller" - }; - }, - {catchall: true} - ) - ]; - - let unitrollerData = await getFetcherValue("DeployUnitroller", fetchers, world, event); - let invokation = unitrollerData.invokation; - delete unitrollerData.invokation; - - if (invokation.error) { - throw invokation.error; - } - const unitroller = invokation.value!; - unitrollerData.address = unitroller._address; - - world = await storeAndSaveContract( - world, - unitroller, - 'Unitroller', - invokation, - [ - { index: ['Unitroller'], data: unitrollerData } - ] - ); - - return {world, unitroller, unitrollerData}; -} diff --git a/scenario/src/Command.ts b/scenario/src/Command.ts deleted file mode 100644 index 56206c40b..000000000 --- a/scenario/src/Command.ts +++ /dev/null @@ -1,248 +0,0 @@ -import {Event} from './Event'; -import {World} from './World'; -import {mustArray} from './Utils'; -import {NothingV} from './Value'; - -interface ArgOpts { - default?: T | T[] - implicit?: boolean - variadic?: boolean - mapped?: boolean - nullable?: boolean - rescue?: T -} - -export class Arg { - name: string - type: any - getter: (World, Event?) => Promise - defaultValue: T | T[] | undefined - implicit: boolean - variadic: boolean - mapped: boolean - nullable: boolean - rescue: T | undefined - - constructor(name: string, getter: (World, Event?) => Promise, opts = >{}) { - this.name = name; - this.getter = getter; - this.defaultValue = opts.default; - this.implicit = !!opts.implicit; - this.variadic = !!opts.variadic; - this.mapped = !!opts.mapped; - this.nullable = !!opts.nullable; - this.rescue = opts.rescue; - } -} - -interface ExpressionOpts { - namePos?: number - catchall?: boolean - subExpressions?: Expression[] -} - -export abstract class Expression { - doc: string - name: string - args: Arg[] - namePos: number - catchall: boolean - subExpressions: Expression[] - - constructor(doc: string, name: string, args: Arg[], opts: ExpressionOpts={}) { - this.doc = Command.cleanDoc(doc); - this.name = name; - this.args = args; - this.namePos = opts.namePos || 0; - this.catchall = opts.catchall || false; - this.subExpressions = opts.subExpressions || []; - } - - getNameArgs(event: Event): [string | null, Event] { - // Unwrap double-wrapped expressions e.g. [[Exactly, "1.0"]] -> ["Exactly", "1.0"] - if (Array.isArray(event) && event.length === 1 && Array.isArray(event[0])) { - const [eventInner] = event; - - return this.getNameArgs(eventInner); - } - - // Let's allow single-length complex expressions to be passed without parens e.g. "True" -> ["True"] - if (!Array.isArray(event)) { - event = [event]; - } - - if (this.catchall) { - return [this.name, event]; - } else { - let args = event.slice(); - let [name] = args.splice(this.namePos, 1); - - if (Array.isArray(name)) { - return [null, event]; - } - - return [name, args]; - } - } - - matches(event: Event): boolean { - if (this.catchall) { - return true; - } - - const [name, _args] = this.getNameArgs(event); - - return !!name && name.toLowerCase().trim() === this.name.toLowerCase().trim(); - } - - async getArgs(world: World, event: Event): Promise { - const [_name, eventArgs] = this.getNameArgs(event); - - let initialAcc = <{currArgs: Args, currEvents: Event}>{currArgs: {}, currEvents: eventArgs}; - - const {currArgs: args, currEvents: restEvent} = await this.args.reduce(async (acc, arg) => { - let {currArgs, currEvents} = await acc; - let val: any; - let restEventArgs: Event; - - if (arg.nullable && currEvents.length === 0) { // Note this is zero-length string or zero-length array - val = new NothingV(); - restEventArgs = currEvents; - } else if (arg.variadic) { - if (arg.mapped) { - // If mapped, mapped the function over each event arg - val = await Promise.all(currEvents.map((event) => arg.getter(world, event))); - } else { - val = await arg.getter(world, currEvents); - } - restEventArgs = []; - } else if (arg.implicit) { - val = await arg.getter(world); - restEventArgs = currEvents; - } else { - let eventArg; - - [eventArg, ...restEventArgs] = currEvents; - - if (eventArg === undefined) { - if (arg.defaultValue !== undefined) { - val = arg.defaultValue; - } else { - throw new Error(`Missing argument ${arg.name} when processing ${this.name}`); - } - } else { - try { - if (arg.mapped) { - val = await await Promise.all(mustArray(eventArg).map((el) => arg.getter(world, el))); - } else { - val = await arg.getter(world, eventArg); - } - } catch (err) { - if (arg.rescue) { - // Rescue is meant to allow Gate to work for checks that - // fail due to the missing components, e.g.: - // `Gate (CToken Eth Address) (... deploy cToken)` - // could be used to deploy a cToken if it doesn't exist, but - // since there is no CToken, that check would raise (when we'd - // hope it just returns null). So here, we allow our code to rescue - // errors and recover, but we need to be smarter about catching specific - // errors instead of all errors. For now, to assist debugging, we may print - // any error that comes up, even if it was intended. - // world.printer.printError(err); - - val = arg.rescue; - } else { - throw err; - } - } - } - } - - let newArgs = { - ...currArgs, - [arg.name]: val - }; - - return { - currArgs: newArgs, - currEvents: restEventArgs - }; - }, Promise.resolve(initialAcc)); - - if (restEvent.length !== 0) { - throw new Error(`Found extra args: ${restEvent.toString()} when processing ${this.name}`); - } - - return args; - } - - static cleanDoc(doc: string): string { - return doc.replace(/^\s+/mg, '').replace(/"/g, '`'); - } -} - -export class Command extends Expression { - processor: (world: World, from: string, args: Args) => Promise - requireFrom: boolean = true; - - constructor(doc: string, name: string, args: Arg[], processor: (world: World, from: string, args: Args) => Promise, opts: ExpressionOpts={}) { - super(doc, name, args, opts); - - this.processor = processor; - } - - async process(world: World, from: string | null, event: Event): Promise { - let args = await this.getArgs(world, event); - if (this.requireFrom) { - if (!from) { - throw new Error(`From required but not given for ${this.name}. Please set a default alias or open unlocked account`); - } - - return await this.processor(world, from, args); - } else { - return await this.processor(world, null, args); - } - } -} - -export class View extends Command { - constructor(doc: string, name: string, args: Arg[], processor: (world: World, args: Args) => Promise, opts: ExpressionOpts={}) { - super(doc, name, args, (world, from, args) => processor(world, args), opts); - this.requireFrom = false; - } -} - -export class Fetcher extends Expression { - fetcher: (world: World, args: Args) => Promise - - constructor(doc: string, name: string, args: Arg[], fetcher: (world: World, args: Args) => Promise, opts: ExpressionOpts={}) { - super(doc, name, args, opts); - - this.fetcher = fetcher; - } - - async fetch(world: World, event: Event): Promise { - let args = await this.getArgs(world, event); - return await this.fetcher(world, args); - } -} - -export async function processCommandEvent(type: string, commands: Command[], world: World, event: Event, from: string | null): Promise { - let matchingCommand = commands.find((command) => command.matches(event)); - - if (!matchingCommand) { - throw new Error(`Found unknown ${type} event type ${event.toString()}`); - } - - return matchingCommand.process(world, from, event); -} - -export async function getFetcherValue(type: string, fetchers: Fetcher[], world: World, event: Event): Promise { - let matchingFetcher = fetchers.find((fetcher) => fetcher.matches(event)); - - if (!matchingFetcher) { - throw new Error(`Found unknown ${type} value type ${JSON.stringify(event)}`); - } - - return matchingFetcher.fetch(world, event); -} diff --git a/scenario/src/Completer.ts b/scenario/src/Completer.ts deleted file mode 100644 index 35f90782b..000000000 --- a/scenario/src/Completer.ts +++ /dev/null @@ -1,36 +0,0 @@ -import {World} from './World'; -import {Macros} from './Macro'; - -// TODO: Get smarter about storing actions as data -const actions: string[] = [ - "Read", - "Assert", - "FastForward", - "Inspect", - "Debug", - "From", - "Invariant", - "Comptroller", - "cToken", - "Erc20", -]; - -function caseInsensitiveSort(a: string, b: string): number { - let A = a.toUpperCase(); - let B = b.toUpperCase(); - - if (A < B) { - return -1; - } else if (A > B) { - return 1; - } else { - return 0; - } -} - -export function complete(world: World, macros: Macros, line: string) { - let allActions = actions.concat(Object.keys(macros)).sort(caseInsensitiveSort); - const hits = allActions.filter((c) => c.toLowerCase().startsWith(line.toLowerCase())); - - return [hits, line]; -} diff --git a/scenario/src/Contract.ts b/scenario/src/Contract.ts deleted file mode 100644 index 03b4ba14a..000000000 --- a/scenario/src/Contract.ts +++ /dev/null @@ -1,207 +0,0 @@ -import * as path from 'path'; -import * as crypto from 'crypto'; -import { World } from './World'; -import { Invokation } from './Invokation'; -import { readFile } from './File'; -import { AbiItem } from 'web3-utils'; - -export interface Raw { - data: string - topics: string[] -} - -export interface Event { - event: string - signature: string | null - address: string - returnValues: object - logIndex: number - transactionIndex: number - blockHash: string - blockNumber: number - raw: Raw -} - -export interface Contract { - address: string - _address: string - name: string - methods: any - _jsonInterface: AbiItem[] - constructorAbi?: string - getPastEvents: (event: string, options: { filter: object, fromBlock: number, toBlock: number | string }) => Event[] -} - -function randomAddress(): string { - return crypto.randomBytes(20).toString('hex'); -} - -class ContractStub { - name: string; - test: boolean - - constructor(name: string, test: boolean) { - this.name = name; - this.test = test; - } - - async deploy(world: World, from: string, args: any[]): Promise> { - // XXXS Consider opts - // ( world.web3.currentProvider && typeof(world.web3.currentProvider) !== 'string' && world.web3.currentProvider.opts ) || - const opts = { from: from }; - - let invokationOpts = world.getInvokationOpts(opts); - - const networkContractABI = await world.saddle.abi(this.name); - const constructorAbi = networkContractABI.find((x) => x.type === 'constructor'); - let inputs; - - if (constructorAbi) { - inputs = constructorAbi.inputs; - } else { - inputs = []; - } - - try { - let contract; - let receipt; - - if (world.dryRun) { - let addr = randomAddress(); - console.log(`Dry run: Deploying ${this.name} at fake address ${addr}`); - contract = new world.web3.eth.Contract(networkContractABI, addr) - receipt = { - blockNumber: -1, - transactionHash: "0x", - events: {} - }; - } else { - ({ contract, receipt } = await world.saddle.deployFull(this.name, args, invokationOpts, world.web3)); - contract.constructorAbi = world.web3.eth.abi.encodeParameters(inputs, args);; - } - - return new Invokation(contract, receipt, null, null); - } catch (err) { - return new Invokation(null, null, err, null); - } - } - - async at(world: World, address: string): Promise { - const networkContractABI = await world.saddle.abi(this.name); - - // XXXS unknown? - return (new world.web3.eth.Contract(networkContractABI, address)); - } -} - -export function getContract(name: string): ContractStub { - return new ContractStub(name, false); -} - -export function getTestContract(name: string): ContractStub { - return new ContractStub(name, true); -} - -export function setContractName(name: string, contract: Contract): Contract { - contract.name = name; - - return contract; -} - -export async function getPastEvents(world: World, contract: Contract, name: string, event: string, filter: object = {}): Promise { - const block = world.getIn(['contractData', 'Blocks', name]); - if (!block) { - throw new Error(`Cannot get events when missing deploy block for ${name}`); - } - - return await contract.getPastEvents(event, { filter: filter, fromBlock: block, toBlock: 'latest' }); -} - -export async function decodeCall(world: World, contract: Contract, input: string): Promise { - if (input.slice(0, 2) === '0x') { - input = input.slice(2); - } - - let functionSignature = input.slice(0, 8); - let argsEncoded = input.slice(8); - - let funsMapped = contract._jsonInterface.reduce((acc, fun) => { - if (fun.type === 'function') { - let functionAbi = `${fun.name}(${(fun.inputs || []).map((i) => i.type).join(',')})`; - let sig = world.web3.utils.sha3(functionAbi).slice(2, 10); - - return { - ...acc, - [sig]: fun - }; - } else { - return acc; - } - }, {}); - - let abi = funsMapped[functionSignature]; - - if (!abi) { - throw new Error(`Cannot find function matching signature ${functionSignature}`); - } - - let decoded = world.web3.eth.abi.decodeParameters(abi.inputs, argsEncoded); - - const args = abi.inputs.map((input) => { - return `${input.name}=${decoded[input.name]}`; - }); - world.printer.printLine(`\n${contract.name}.${abi.name}(\n\t${args.join("\n\t")}\n)`); - - return world; -} - -// XXXS Handle -async function getNetworkContract(world: World, name: string): Promise<{ abi: any[], bin: string }> { - let basePath = world.basePath || "" - let network = world.network || "" - - let pizath = (name, ext) => path.join(basePath, '.build', `contracts.json`); - let abi, bin; - if (network == 'coverage') { - let json = await readFile(world, pizath(name, 'json'), null, JSON.parse); - abi = json.abi; - bin = json.bytecode.substr(2); - } else { - let { networkContracts } = await getNetworkContracts(world); - let networkContract = networkContracts[name]; - abi = JSON.parse(networkContract.abi); - bin = networkContract.bin; - } - if (!bin) { - throw new Error(`no bin for contract ${name} ${network}`) - } - return { - abi: abi, - bin: bin - } -} - -export async function getNetworkContracts(world: World): Promise<{ networkContracts: object, version: string }> { - let basePath = world.basePath || "" - let network = world.network || "" - - let contractsPath = path.join(basePath, '.build', `contracts.json`) - let fullContracts = await readFile(world, contractsPath, null, JSON.parse); - let version = fullContracts.version; - let networkContracts = Object.entries(fullContracts.contracts).reduce((acc, [k, v]) => { - let [path, contractName] = k.split(':'); - - return { - ...acc, - [contractName]: { - ...v, /// XXXS TODO - path: path - } - }; - }, {}); - - return { - networkContracts, - version - }; -} diff --git a/scenario/src/Contract/AnchoredView.ts b/scenario/src/Contract/AnchoredView.ts deleted file mode 100644 index 84bdf44b9..000000000 --- a/scenario/src/Contract/AnchoredView.ts +++ /dev/null @@ -1,10 +0,0 @@ -import {Contract} from '../Contract'; -import {Callable} from '../Invokation'; - -interface AnchoredViewMethods { - getUnderlyingPrice(asset: string): Callable -} - -export interface AnchoredView extends Contract { - methods: AnchoredViewMethods -} diff --git a/scenario/src/Contract/CErc20Delegate.ts b/scenario/src/Contract/CErc20Delegate.ts deleted file mode 100644 index a805103f9..000000000 --- a/scenario/src/Contract/CErc20Delegate.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { Contract } from '../Contract'; -import { Sendable } from '../Invokation'; -import { CTokenMethods, CTokenScenarioMethods } from './CToken'; - -interface CErc20DelegateMethods extends CTokenMethods { - _becomeImplementation(data: string): Sendable; - _resignImplementation(): Sendable; -} - -interface CErc20DelegateScenarioMethods extends CTokenScenarioMethods { - _becomeImplementation(data: string): Sendable; - _resignImplementation(): Sendable; -} - -export interface CErc20Delegate extends Contract { - methods: CErc20DelegateMethods; - name: string; -} - -export interface CErc20DelegateScenario extends Contract { - methods: CErc20DelegateScenarioMethods; - name: string; -} diff --git a/scenario/src/Contract/CErc20Delegator.ts b/scenario/src/Contract/CErc20Delegator.ts deleted file mode 100644 index 8787c414e..000000000 --- a/scenario/src/Contract/CErc20Delegator.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { Contract } from '../Contract'; -import { Callable, Sendable } from '../Invokation'; -import { CTokenMethods } from './CToken'; -import { encodedNumber } from '../Encoding'; - -interface CErc20DelegatorMethods extends CTokenMethods { - implementation(): Callable; - _setImplementation( - implementation_: string, - allowResign: boolean, - becomImplementationData: string - ): Sendable; -} - -interface CErc20DelegatorScenarioMethods extends CErc20DelegatorMethods { - setTotalBorrows(amount: encodedNumber): Sendable; - setTotalReserves(amount: encodedNumber): Sendable; -} - -export interface CErc20Delegator extends Contract { - methods: CErc20DelegatorMethods; - name: string; -} - -export interface CErc20DelegatorScenario extends Contract { - methods: CErc20DelegatorMethods; - name: string; -} diff --git a/scenario/src/Contract/CToken.ts b/scenario/src/Contract/CToken.ts deleted file mode 100644 index f21086a2c..000000000 --- a/scenario/src/Contract/CToken.ts +++ /dev/null @@ -1,66 +0,0 @@ -import { Contract } from '../Contract'; -import { Callable, Sendable } from '../Invokation'; -import { encodedNumber } from '../Encoding'; - -export interface CTokenMethods { - _resignImplementation(): Sendable; - balanceOfUnderlying(address: string): Callable; - borrowBalanceCurrent(address: string): Callable; - borrowBalanceStored(address: string): Callable; - totalBorrows(): Callable; - totalBorrowsCurrent(): Callable; - totalReserves(): Callable; - reserveFactorMantissa(): Callable; - comptroller(): Callable; - exchangeRateStored(): Sendable; - exchangeRateCurrent(): Callable; - getCash(): Callable; - accrueInterest(): Sendable; - mint(): Sendable; - mint(amount: encodedNumber): Sendable; - redeem(amount: encodedNumber): Sendable; - redeemUnderlying(amount: encodedNumber): Sendable; - borrow(amount: encodedNumber): Sendable; - repayBorrow(): Sendable; - repayBorrow(amount: encodedNumber): Sendable; - repayBorrowBehalf(amount: string): Sendable; - repayBorrowBehalf(address: string, amount: encodedNumber): Sendable; - liquidateBorrow(borrower: string, cTokenCollateral: string): Sendable; - liquidateBorrow(borrower: string, repayAmount: encodedNumber, cTokenCollateral: string): Sendable; - seize(liquidator: string, borrower: string, seizeTokens: encodedNumber): Sendable; - evilSeize( - treasure: string, - liquidator: string, - borrower: string, - seizeTokens: encodedNumber - ): Sendable; - _addReserves(amount: encodedNumber): Sendable; - _reduceReserves(amount: encodedNumber): Sendable; - _setReserveFactor(reserveFactor: encodedNumber): Sendable; - _setInterestRateModel(address: string): Sendable; - _setComptroller(address: string): Sendable; - underlying(): Callable; - interestRateModel(): Callable; - borrowRatePerBlock(): Callable; - donate(): Sendable; - admin(): Callable; - pendingAdmin(): Callable; - _setPendingAdmin(address: string): Sendable; - _acceptAdmin(): Sendable; - sweepToken(token: string): Sendable; -} - -export interface CTokenScenarioMethods extends CTokenMethods { - setTotalBorrows(amount: encodedNumber): Sendable; - setTotalReserves(amount: encodedNumber): Sendable; -} - -export interface CToken extends Contract { - methods: CTokenMethods; - name: string; -} - -export interface CTokenScenario extends Contract { - methods: CTokenScenarioMethods; - name: string; -} diff --git a/scenario/src/Contract/Comp.ts b/scenario/src/Contract/Comp.ts deleted file mode 100644 index 53e1692a3..000000000 --- a/scenario/src/Contract/Comp.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { Contract } from '../Contract'; -import { encodedNumber } from '../Encoding'; -import { Callable, Sendable } from '../Invokation'; - -interface Checkpoint { - fromBlock: number; - votes: number; -} - -export interface CompMethods { - name(): Callable; - symbol(): Callable; - decimals(): Callable; - totalSupply(): Callable; - balanceOf(address: string): Callable; - allowance(owner: string, spender: string): Callable; - approve(address: string, amount: encodedNumber): Sendable; - transfer(address: string, amount: encodedNumber): Sendable; - transferFrom(owner: string, spender: string, amount: encodedNumber): Sendable; - checkpoints(account: string, index: number): Callable; - numCheckpoints(account: string): Callable; - delegate(account: string): Sendable; - getCurrentVotes(account: string): Callable; - getPriorVotes(account: string, blockNumber: encodedNumber): Callable; - setBlockNumber(blockNumber: encodedNumber): Sendable; -} - -export interface CompScenarioMethods extends CompMethods { - transferScenario(destinations: string[], amount: encodedNumber): Sendable; - transferFromScenario(froms: string[], amount: encodedNumber): Sendable; -} - -export interface Comp extends Contract { - methods: CompMethods; - name: string; -} - -export interface CompScenario extends Contract { - methods: CompScenarioMethods; - name: string; -} diff --git a/scenario/src/Contract/Comptroller.ts b/scenario/src/Contract/Comptroller.ts deleted file mode 100644 index 287127287..000000000 --- a/scenario/src/Contract/Comptroller.ts +++ /dev/null @@ -1,81 +0,0 @@ -import {Contract} from '../Contract'; -import {Callable, Sendable} from '../Invokation'; -import {encodedNumber} from '../Encoding'; - -interface ComptrollerMethods { - getAccountLiquidity(string): Callable<{0: number, 1: number, 2: number}> - getHypotheticalAccountLiquidity(account: string, asset: string, redeemTokens: encodedNumber, borrowAmount: encodedNumber): Callable<{0: number, 1: number, 2: number}> - membershipLength(string): Callable - checkMembership(user: string, cToken: string): Callable - getAssetsIn(string): Callable - admin(): Callable - oracle(): Callable - maxAssets(): Callable - liquidationIncentiveMantissa(): Callable - closeFactorMantissa(): Callable - getBlockNumber(): Callable - collateralFactor(string): Callable - markets(string): Callable<{0: boolean, 1: number, 2?: boolean}> - _setMintPaused(bool): Sendable - _setMaxAssets(encodedNumber): Sendable - _setLiquidationIncentive(encodedNumber): Sendable - _supportMarket(string): Sendable - _setPriceOracle(string): Sendable - _setCollateralFactor(string, encodedNumber): Sendable - _setCloseFactor(encodedNumber): Sendable - enterMarkets(markets: string[]): Sendable - exitMarket(market: string): Sendable - fastForward(encodedNumber): Sendable - _setPendingImplementation(string): Sendable - comptrollerImplementation(): Callable - unlist(string): Sendable - admin(): Callable - pendingAdmin(): Callable - _setPendingAdmin(string): Sendable - _acceptAdmin(): Sendable - _setPauseGuardian(string): Sendable - pauseGuardian(): Callable - _setMintPaused(market: string, string): Sendable - _setBorrowPaused(market: string, string): Sendable - _setTransferPaused(string): Sendable - _setSeizePaused(string): Sendable - _mintGuardianPaused(): Callable - _borrowGuardianPaused(): Callable - transferGuardianPaused(): Callable - seizeGuardianPaused(): Callable - mintGuardianPaused(market: string): Callable - borrowGuardianPaused(market: string): Callable - _addCompMarkets(markets: string[]): Sendable - _dropCompMarket(market: string): Sendable - getCompMarkets(): Callable - refreshCompSpeeds(): Sendable - compRate(): Callable - compSupplyState(string): Callable - compBorrowState(string): Callable - compAccrued(string): Callable - compReceivable(string): Callable - compSupplierIndex(market: string, account: string): Callable - compBorrowerIndex(market: string, account: string): Callable - compSpeeds(string): Callable - compSupplySpeeds(string): Callable - compBorrowSpeeds(string): Callable - claimComp(holder: string): Sendable - claimComp(holder: string, cTokens: string[]): Sendable - updateContributorRewards(account: string): Sendable - _grantComp(account: string, encodedNumber): Sendable - _setCompRate(encodedNumber): Sendable - _setCompSpeed(cTokens: string, encodedNumber): Sendable - _setCompSpeeds(cTokens: string[], supplySpeeds: encodedNumber[], borrowSpeeds: encodedNumber[]): Sendable - _setContributorCompSpeed(account: string, encodedNumber): Sendable - _setMarketBorrowCaps(cTokens:string[], borrowCaps:encodedNumber[]): Sendable - _setBorrowCapGuardian(string): Sendable - borrowCapGuardian(): Callable - borrowCaps(string): Callable - isDeprecated(cToken: string): Callable - _setMarketSupplyCaps(cTokens:string[], supplyCaps:encodedNumber[]): Sendable - supplyCaps(string): Callable -} - -export interface Comptroller extends Contract { - methods: ComptrollerMethods -} diff --git a/scenario/src/Contract/ComptrollerImpl.ts b/scenario/src/Contract/ComptrollerImpl.ts deleted file mode 100644 index af4b29224..000000000 --- a/scenario/src/Contract/ComptrollerImpl.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { Contract } from '../Contract'; -import { Callable, Sendable } from '../Invokation'; -import { encodedNumber } from '../Encoding'; - -interface ComptrollerImplMethods { - _become( - comptroller: string, - priceOracle?: string, - maxAssets?: encodedNumber, - closeFactor?: encodedNumber, - reinitializing?: boolean - ): Sendable; - - _become( - comptroller: string, - compRate: encodedNumber, - compMarkets: string[], - otherMarkets: string[] - ): Sendable; -} - -export interface ComptrollerImpl extends Contract { - methods: ComptrollerImplMethods; -} diff --git a/scenario/src/Contract/Counter.ts b/scenario/src/Contract/Counter.ts deleted file mode 100644 index 81f553d14..000000000 --- a/scenario/src/Contract/Counter.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { Contract } from '../Contract'; -import { encodedNumber } from '../Encoding'; -import { Callable, Sendable } from '../Invokation'; - -export interface CounterMethods { - increment(by: encodedNumber): Sendable; -} - -export interface Counter extends Contract { - methods: CounterMethods; - name: string; -} diff --git a/scenario/src/Contract/Erc20.ts b/scenario/src/Contract/Erc20.ts deleted file mode 100644 index 914cd408a..000000000 --- a/scenario/src/Contract/Erc20.ts +++ /dev/null @@ -1,25 +0,0 @@ -import {Contract} from '../Contract'; -import {Callable, Sendable} from '../Invokation'; -import {encodedNumber} from '../Encoding'; - -interface Erc20Methods { - name(): Callable - symbol(): Callable - decimals(): Callable - totalSupply(): Callable - balanceOf(string): Callable - allowance(owner: string, spender: string): Callable - approve(address: string, amount: encodedNumber): Sendable - allocateTo(address: string, amount: encodedNumber): Sendable - transfer(address: string, amount: encodedNumber): Sendable - transferFrom(owner: string, spender: string, amount: encodedNumber): Sendable - setFail(fail: boolean): Sendable - pause(): Sendable - unpause(): Sendable - setParams(newBasisPoints: encodedNumber, maxFee: encodedNumber): Sendable -} - -export interface Erc20 extends Contract { - methods: Erc20Methods - name: string -} diff --git a/scenario/src/Contract/InterestRateModel.ts b/scenario/src/Contract/InterestRateModel.ts deleted file mode 100644 index afb6f2db3..000000000 --- a/scenario/src/Contract/InterestRateModel.ts +++ /dev/null @@ -1,12 +0,0 @@ -import {Contract} from '../Contract'; -import {Callable, Sendable} from '../Invokation'; -import {encodedNumber} from '../Encoding'; - -interface InterestRateModelMethods { - getBorrowRate(cash: encodedNumber, borrows: encodedNumber, reserves: encodedNumber): Callable -} - -export interface InterestRateModel extends Contract { - methods: InterestRateModelMethods - name: string -} diff --git a/scenario/src/Contract/Pot.ts b/scenario/src/Contract/Pot.ts deleted file mode 100644 index 3f0f70106..000000000 --- a/scenario/src/Contract/Pot.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { Contract } from '../Contract'; -import { Callable, Sendable } from '../Invokation'; -import { encodedNumber } from '../Encoding'; - -interface PotMethods { - chi(): Callable; - dsr(): Callable; - rho(): Callable; - pie(address: string): Callable; - drip(): Sendable; - file(what: string, data: encodedNumber): Sendable; - join(amount: encodedNumber): Sendable; - exit(amount: encodedNumber): Sendable; -} - -export interface Pot extends Contract { - methods: PotMethods; - name: string; -} diff --git a/scenario/src/Contract/PriceOracle.ts b/scenario/src/Contract/PriceOracle.ts deleted file mode 100644 index 04d283668..000000000 --- a/scenario/src/Contract/PriceOracle.ts +++ /dev/null @@ -1,30 +0,0 @@ -import {Contract} from '../Contract'; -import {Callable, Sendable} from '../Invokation'; -import {encodedNumber} from '../Encoding'; - -interface PriceOracleMethods { - assetPrices(asset: string): Callable - setUnderlyingPrice(cToken: string, amount: encodedNumber): Sendable - setDirectPrice(address: string, amount: encodedNumber): Sendable - - // Anchor Price Oracle - getPrice(asset: string): Callable - readers(asset: string): Callable - anchorAdmin(): Callable - pendingAnchorAdmin(): Callable - poster(): Callable - maxSwing(): Callable - anchors(asset: string): Callable<{0: number, 1: number}> - pendingAnchors(asset: string): Callable - _setPendingAnchor(asset: string, price: encodedNumber): Sendable - _setPaused(paused: boolean): Sendable - _setPendingAnchorAdmin(string): Sendable - _acceptAnchorAdmin(): Sendable - setPrice(asset: string, price: encodedNumber): Sendable - setPrices(assets: string[], prices: encodedNumber[]): Sendable -} - -export interface PriceOracle extends Contract { - methods: PriceOracleMethods - name: string -} diff --git a/scenario/src/Contract/PriceOracleProxy.ts b/scenario/src/Contract/PriceOracleProxy.ts deleted file mode 100644 index 69bd08a99..000000000 --- a/scenario/src/Contract/PriceOracleProxy.ts +++ /dev/null @@ -1,13 +0,0 @@ -import {Contract} from '../Contract'; -import {Callable, Sendable} from '../Invokation'; -import {encodedNumber} from '../Encoding'; - -interface PriceOracleProxyMethods { - getUnderlyingPrice(asset: string): Callable - v1PriceOracle(): Callable; - setSaiPrice(amount: encodedNumber): Sendable -} - -export interface PriceOracleProxy extends Contract { - methods: PriceOracleProxyMethods -} diff --git a/scenario/src/Contract/Reservoir.ts b/scenario/src/Contract/Reservoir.ts deleted file mode 100644 index 1bfae9013..000000000 --- a/scenario/src/Contract/Reservoir.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { Contract } from '../Contract'; -import { encodedNumber } from '../Encoding'; -import { Callable, Sendable } from '../Invokation'; - -export interface ReservoirMethods { - drip(): Sendable; - dripped(): Callable; - dripStart(): Callable; - dripRate(): Callable; - token(): Callable; - target(): Callable; -} - -export interface Reservoir extends Contract { - methods: ReservoirMethods; - name: string; -} diff --git a/scenario/src/Contract/Timelock.ts b/scenario/src/Contract/Timelock.ts deleted file mode 100644 index 3ea7a284c..000000000 --- a/scenario/src/Contract/Timelock.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { Contract } from '../Contract'; -import { Callable, Sendable } from '../Invokation'; -import { encodedNumber } from '../Encoding'; - -interface TimelockMethods { - admin(): Callable; - pendingAdmin(): Callable; - delay(): Callable; - queuedTransactions(txHash: string): Callable; - setDelay(delay: encodedNumber): Sendable; - acceptAdmin(): Sendable; - setPendingAdmin(admin: string): Sendable; - queueTransaction( - target: string, - value: encodedNumber, - signature: string, - data: string, - eta: encodedNumber - ): Sendable; - cancelTransaction( - target: string, - value: encodedNumber, - signature: string, - data: string, - eta: encodedNumber - ): Sendable; - executeTransaction( - target: string, - value: encodedNumber, - signature: string, - data: string, - eta: encodedNumber - ): Sendable; - - blockTimestamp(): Callable; - harnessFastForward(seconds: encodedNumber): Sendable; - harnessSetBlockTimestamp(seconds: encodedNumber): Sendable; - harnessSetAdmin(admin: string): Sendable; -} - -export interface Timelock extends Contract { - methods: TimelockMethods; -} diff --git a/scenario/src/Contract/Unitroller.ts b/scenario/src/Contract/Unitroller.ts deleted file mode 100644 index 484f11b89..000000000 --- a/scenario/src/Contract/Unitroller.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { Contract } from '../Contract'; -import { Callable, Sendable } from '../Invokation'; - -interface UnitrollerMethods { - admin(): Callable; - pendingAdmin(): Callable; - _acceptAdmin(): Sendable; - _setPendingAdmin(pendingAdmin: string): Sendable; - _setPendingImplementation(pendingImpl: string): Sendable; - comptrollerImplementation(): Callable; - pendingComptrollerImplementation(): Callable; -} - -export interface Unitroller extends Contract { - methods: UnitrollerMethods; -} diff --git a/scenario/src/Contract/Vat.ts b/scenario/src/Contract/Vat.ts deleted file mode 100644 index 0a0a9a76e..000000000 --- a/scenario/src/Contract/Vat.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { Contract } from '../Contract'; -import { Callable, Sendable } from '../Invokation'; -import { encodedNumber } from '../Encoding'; - -interface VatMethods { - dai(address: string): Callable; - hope(address: string): Sendable; - move(src: string, dst: string, amount: encodedNumber): Sendable; -} - -export interface Vat extends Contract { - methods: VatMethods; - name: string; -} diff --git a/scenario/src/Contract/builder.js b/scenario/src/Contract/builder.js deleted file mode 100644 index f6c11270d..000000000 --- a/scenario/src/Contract/builder.js +++ /dev/null @@ -1,63 +0,0 @@ -const fs = require('fs'); -const path = require('path'); - -let [_, _f, buildFile, contract] = process.argv; - -if (!buildFile || !contract) { - throw new Error(`builder.js `); -} -if (!fs.existsSync(buildFile)) { - throw new Error(`build_file: file not found`); -} -let buildRaw = fs.readFileSync(buildFile, 'utf8'); -let build; - -try { - build = JSON.parse(buildRaw); -} catch (e) { - throw new Error(`Error parsing build file: ${e.toString()}`); -} -if (!build.contracts) { - throw new Error(`Invalid build file, missing contracts`); -} -let contractInfo = Object.entries(build.contracts).find(([k,v]) => k.split(':')[1] === contract); -if (!contractInfo) { - throw new Error(`Build file does not contain info for ${contract}`); -} -let contractABI = JSON.parse(contractInfo[1].abi); - -console.log(`export interface ${contract}Methods {`); -contractABI.forEach(abi => { - if (abi.type === 'function') { - function mapped(io) { - let typeMap = { - 'address': 'string', - 'address[]': 'string[]', - 'uint256': 'number', - 'bool': 'boolean' - }; - return typeMap[io.type] || io.type; - }; - let name = abi.name; - let args = abi.inputs.map((input) => { - return `${input.name}: ${mapped(input)}`; - }).join(', '); - let returnType = abi.outputs.map((output) => { - if (output.type == 'tuple' || output.type == 'tuple[]') { - let res = output.components.map((c) => { - return mapped(c); - }).join(','); - if (output.type == 'tuple[]') { - return `[${res}][]`; - } else { - return `[${res}]`; - } - } else { - return mapped(output); - } - }).join(','); - let able = abi.constant ? 'Callable' : 'Sendable'; - console.log(` ${name}(${args}): ${able}<${returnType}>;`); - } -}); -console.log("}"); diff --git a/scenario/src/ContractLookup.ts b/scenario/src/ContractLookup.ts deleted file mode 100644 index 655f799a0..000000000 --- a/scenario/src/ContractLookup.ts +++ /dev/null @@ -1,224 +0,0 @@ -import { Map } from 'immutable'; - -import { Event } from './Event'; -import { World } from './World'; -import { Contract } from './Contract'; -import { mustString } from './Utils'; - -import { CErc20Delegate } from './Contract/CErc20Delegate'; -import { Comp } from './Contract/Comp'; -import { Comptroller } from './Contract/Comptroller'; -import { ComptrollerImpl } from './Contract/ComptrollerImpl'; -import { CToken } from './Contract/CToken'; -import { Erc20 } from './Contract/Erc20'; -import { InterestRateModel } from './Contract/InterestRateModel'; -import { PriceOracle } from './Contract/PriceOracle'; -import { AnchoredView } from './Contract/AnchoredView'; - -type ContractDataEl = string | Map | undefined; - -function getContractData(world: World, indices: string[][]): ContractDataEl { - return indices.reduce((value: ContractDataEl, index) => { - if (value) { - return value; - } else { - return index.reduce((data: ContractDataEl, el) => { - let lowerEl = el.toLowerCase(); - - if (!data) { - return; - } else if (typeof data === 'string') { - return data; - } else { - return (data as Map).find((_v, key) => key.toLowerCase().trim() === lowerEl.trim()); - } - }, world.contractData); - } - }, undefined); -} - -function getContractDataString(world: World, indices: string[][]): string { - const value: ContractDataEl = getContractData(world, indices); - - if (!value || typeof value !== 'string') { - throw new Error( - `Failed to find string value by index (got ${value}): ${JSON.stringify( - indices - )}, index contains: ${JSON.stringify(world.contractData.toJSON())}` - ); - } - - return value; -} - -export function getWorldContract(world: World, indices: string[][]): T { - const address = getContractDataString(world, indices); - - return getWorldContractByAddress(world, address); -} - -export function getWorldContractByAddress(world: World, address: string): T { - const contract = world.contractIndex[address.toLowerCase()]; - - if (!contract) { - throw new Error( - `Failed to find world contract by address: ${address}, index contains: ${JSON.stringify( - Object.keys(world.contractIndex) - )}` - ); - } - - return (contract); -} - -export async function getUnitroller(world: World): Promise { - return getWorldContract(world, [['Contracts', 'Unitroller']]); -} - -export async function getMaximillion(world: World): Promise { - return getWorldContract(world, [['Contracts', 'Maximillion']]); -} - -export async function getComptroller(world: World): Promise { - return getWorldContract(world, [['Contracts', 'Comptroller']]); -} - -export async function getComptrollerImpl(world: World, comptrollerImplArg: Event): Promise { - return getWorldContract(world, [['Comptroller', mustString(comptrollerImplArg), 'address']]); -} - -export function getCTokenAddress(world: World, cTokenArg: string): string { - return getContractDataString(world, [['cTokens', cTokenArg, 'address']]); -} - -export function getCTokenDelegateAddress(world: World, cTokenDelegateArg: string): string { - return getContractDataString(world, [['CTokenDelegate', cTokenDelegateArg, 'address']]); -} - -export function getErc20Address(world: World, erc20Arg: string): string { - return getContractDataString(world, [['Tokens', erc20Arg, 'address']]); -} - -export function getGovernorAddress(world: World, governorArg: string): string { - return getContractDataString(world, [['Contracts', governorArg]]); -} - -export async function getPriceOracleProxy(world: World): Promise { - return getWorldContract(world, [['Contracts', 'PriceOracleProxy']]); -} - -export async function getAnchoredView(world: World): Promise { - return getWorldContract(world, [['Contracts', 'AnchoredView']]); -} - -export async function getPriceOracle(world: World): Promise { - return getWorldContract(world, [['Contracts', 'PriceOracle']]); -} - -export async function getComp( - world: World, - compArg: Event -): Promise { - return getWorldContract(world, [['COMP', 'address']]); -} - -export async function getCompData( - world: World, - compArg: string -): Promise<[Comp, string, Map]> { - let contract = await getComp(world, (compArg)); - let data = getContractData(world, [['Comp', compArg]]); - - return [contract, compArg, >(data)]; -} - -export async function getInterestRateModel( - world: World, - interestRateModelArg: Event -): Promise { - return getWorldContract(world, [['InterestRateModel', mustString(interestRateModelArg), 'address']]); -} - -export async function getInterestRateModelData( - world: World, - interestRateModelArg: string -): Promise<[InterestRateModel, string, Map]> { - let contract = await getInterestRateModel(world, (interestRateModelArg)); - let data = getContractData(world, [['InterestRateModel', interestRateModelArg]]); - - return [contract, interestRateModelArg, >(data)]; -} - -export async function getErc20Data( - world: World, - erc20Arg: string -): Promise<[Erc20, string, Map]> { - let contract = getWorldContract(world, [['Tokens', erc20Arg, 'address']]); - let data = getContractData(world, [['Tokens', erc20Arg]]); - - return [contract, erc20Arg, >(data)]; -} - -export async function getCTokenData( - world: World, - cTokenArg: string -): Promise<[CToken, string, Map]> { - let contract = getWorldContract(world, [['cTokens', cTokenArg, 'address']]); - let data = getContractData(world, [['CTokens', cTokenArg]]); - - return [contract, cTokenArg, >(data)]; -} - -export async function getCTokenDelegateData( - world: World, - cTokenDelegateArg: string -): Promise<[CErc20Delegate, string, Map]> { - let contract = getWorldContract(world, [['CTokenDelegate', cTokenDelegateArg, 'address']]); - let data = getContractData(world, [['CTokenDelegate', cTokenDelegateArg]]); - - return [contract, cTokenDelegateArg, >(data)]; -} - -export async function getComptrollerImplData( - world: World, - comptrollerImplArg: string -): Promise<[ComptrollerImpl, string, Map]> { - let contract = await getComptrollerImpl(world, (comptrollerImplArg)); - let data = getContractData(world, [['Comptroller', comptrollerImplArg]]); - - return [contract, comptrollerImplArg, >(data)]; -} - -export function getAddress(world: World, addressArg: string): string { - if (addressArg.toLowerCase() === 'zero') { - return '0x0000000000000000000000000000000000000000'; - } - - if (addressArg.startsWith('0x')) { - return addressArg; - } - - let alias = Object.entries(world.settings.aliases).find( - ([alias, addr]) => alias.toLowerCase() === addressArg.toLowerCase() - ); - if (alias) { - return alias[1]; - } - - let account = world.accounts.find(account => account.name.toLowerCase() === addressArg.toLowerCase()); - if (account) { - return account.address; - } - - return getContractDataString(world, [ - ['Contracts', addressArg], - ['cTokens', addressArg, 'address'], - ['CTokenDelegate', addressArg, 'address'], - ['Tokens', addressArg, 'address'], - ['Comptroller', addressArg, 'address'] - ]); -} - -export function getContractByName(world: World, name: string): Contract { - return getWorldContract(world, [['Contracts', name]]); -} diff --git a/scenario/src/CoreEvent.ts b/scenario/src/CoreEvent.ts deleted file mode 100644 index 40cee5c4d..000000000 --- a/scenario/src/CoreEvent.ts +++ /dev/null @@ -1,826 +0,0 @@ -import { - addAction, - checkExpectations, - checkInvariants, - clearInvariants, - holdInvariants, - setEvent, - World -} from './World'; -import { Event } from './Event'; -import { getAddressV, getEventV, getNumberV, getStringV } from './CoreValue'; -import { AddressV, EventV, NothingV, NumberV, StringV, Value } from './Value'; -import { Arg, Command, processCommandEvent, View } from './Command'; -import { assertionCommands, processAssertionEvent } from './Event/AssertionEvent'; -import { comptrollerCommands, processComptrollerEvent } from './Event/ComptrollerEvent'; -import { processUnitrollerEvent, unitrollerCommands } from './Event/UnitrollerEvent'; -import { comptrollerImplCommands, processComptrollerImplEvent } from './Event/ComptrollerImplEvent'; -import { cTokenCommands, processCTokenEvent } from './Event/CTokenEvent'; -import { cTokenDelegateCommands, processCTokenDelegateEvent } from './Event/CTokenDelegateEvent'; -import { erc20Commands, processErc20Event } from './Event/Erc20Event'; -import { interestRateModelCommands, processInterestRateModelEvent } from './Event/InterestRateModelEvent'; -import { priceOracleCommands, processPriceOracleEvent } from './Event/PriceOracleEvent'; -import { priceOracleProxyCommands, processPriceOracleProxyEvent } from './Event/PriceOracleProxyEvent'; -import { invariantCommands, processInvariantEvent } from './Event/InvariantEvent'; -import { expectationCommands, processExpectationEvent } from './Event/ExpectationEvent'; -import { compCommands, processCompEvent } from './Event/CompEvent'; -import { processTrxEvent, trxCommands } from './Event/TrxEvent'; -import { getFetchers, getCoreValue } from './CoreValue'; -import { formatEvent } from './Formatter'; -import { fallback } from './Invokation'; -import { getCurrentBlockNumber, getCurrentTimestamp, sendRPC, sleep } from './Utils'; -import { Map } from 'immutable'; -import { encodedNumber } from './Encoding'; -import { printHelp } from './Help'; -import { loadContracts } from './Networks'; -import { fork } from './Hypothetical'; -import { buildContractEvent } from './EventBuilder'; -import { Counter } from './Contract/Counter'; -import { Reservoir } from './Contract/Reservoir'; -import Web3 from 'web3'; - -export class EventProcessingError extends Error { - error: Error; - event: Event; - - constructor(error: Error, event: Event) { - super(error.message); - - this.error = error; - this.event = event; - this.message = `Error: \`${this.error.toString()}\` when processing \`${formatEvent(this.event)}\``; - this.stack = error.stack; - } -} - -export async function processEvents(originalWorld: World, events: Event[]): Promise { - return events.reduce(async (pWorld: Promise, event: Event): Promise => { - let world = await pWorld; - - try { - world = await processCoreEvent(setEvent(world, event), event, world.defaultFrom()); - } catch (err) { - if (world.verbose) { - console.error(err); - } - throw new EventProcessingError(err, event); - } - - // Next, check any unchecked invariants - world = await checkInvariants(world); - - // Check any expectations - world = await checkExpectations(world); - - // Also clear trx related fields - world = world.set('trxInvokationOpts', Map({})); - world = world.set('newInvokation', false); - - if (!world) { - throw new Error(`Encountered null world result when processing event ${event[0]}: ${world}`); - } else if (!(world instanceof World)) { - throw new Error( - `Encountered world result which was not isWorld when processing event ${event[0]}: ${world}` - ); - } - - return world; - }, Promise.resolve(originalWorld)); -} - -async function print(world: World, message: string): Promise { - world.printer.printLine(message); - - return world; -} - -async function inspect(world: World, string: string | null): Promise { - if (string !== null) { - console.log(['Inspect', string, world.toJS()]); - } else { - console.log(['Inspect', world.toJS()]); - } - - return world; -} - -async function sendEther(world: World, from: string, to: string, amount: encodedNumber): Promise { - let invokation = await fallback(world, from, to, amount); - - world = addAction(world, `Send ${amount} from ${from} to ${to}`, invokation); - - return world; -} - -export const commands: (View | ((world: World) => Promise>))[] = [ - new View<{ n: NumberV }>( - ` - #### History - - * "History n:=5" - Prints history of actions - * E.g. "History" - * E.g. "History 10" - `, - 'History', - [new Arg('n', getNumberV, { default: new NumberV(5) })], - async (world, { n }) => { - world.actions.slice(0, Number(n.val)).forEach(action => { - world.printer.printLine(action.toString()); - }); - - return world; - } - ), - new View<{ seconds: NumberV }>( - ` - #### SleepSeconds - - * "SleepSeconds s:" - Sleeps for given amount of time. - * E.g. "SleepSeconds 1" - Sleeps for one second - `, - 'SleepSeconds', - [new Arg('seconds', getNumberV)], - async (world, { seconds }) => { - await sleep(seconds.toNumber() * 1000); - return world; - } - ), - new View<{ timestamp: NumberV }>( - ` - #### SleepUntilTimestamp - - * "SleepUntil timestamp:" - Sleeps until the given timestamp - * E.g. "SleepUntil 1579123423" - Sleeps from now until 1579123423 - `, - 'SleepUntilTimestamp', - [new Arg('timestamp', getNumberV)], - async (world, { timestamp }) => { - const delay = timestamp.toNumber() - getCurrentTimestamp(); - if (delay > 0) { - await sleep(delay * 1000); - } - return world; - } - ), - new View<{ blocks: NumberV }>( - ` - #### SleepBlocks - - * "SleepForBlocks blocks:" - Sleeps for a given number of blocks - * E.g. "SleepBlocks 20" - Sleeps for 20 blocks - `, - 'SleepBlocks', - [new Arg('blocks', getNumberV)], - async (world, { blocks }) => { - const targetBlockNumber = blocks.toNumber() + await getCurrentBlockNumber(world); - while (await getCurrentBlockNumber(world) < targetBlockNumber) { - await sleep(1000); - } - return world; - } - ), - new View<{ blockNumber: NumberV }>( - ` - #### SleepUntilBlock - - * "SleepUntilBlock blockNumber:" - Sleeps until the given blockNumber - * E.g. "SleepUntilBlock 2006868" - Sleeps from now until block 2006868. - `, - 'SleepUntilBlock', - [new Arg('blockNumber', getNumberV)], - async (world, { blockNumber }) => { - const delay = blockNumber.toNumber() - await getCurrentBlockNumber(world); - while (blockNumber.toNumber() > await getCurrentBlockNumber(world)) { - await sleep(1000); - } - return world; - } - ), - new View<{ errMsg: StringV }>( - ` - #### Throw - - * "Throw errMsg:" - Throws given error - * E.g. "Throw \"my error message\"" - `, - 'Throw', - [new Arg('errMsg', getStringV)], - async (world, { errMsg }) => { - throw new Error(errMsg.val); - - return world; - } - ), - async (world: World) => - new View<{ res: Value }>( - ` - #### Read - - * "Read ..." - Reads given value and prints result - * E.g. "Read CToken cBAT ExchangeRateStored" - Returns exchange rate of cBAT - `, - 'Read', - [new Arg('res', getCoreValue, { variadic: true })], - async (world, { res }) => { - world.printer.printValue(res); - - return world; - }, - { subExpressions: (await getFetchers(world)).fetchers } - ), - new View<{ message: StringV }>( - ` - #### Print - - * "Print ..." - Prints given string - * E.g. "Print \"Hello there\"" - `, - 'Print', - [new Arg('message', getStringV)], - async (world, { message }) => print(world, message.val) - ), - new View<{ num: NumberV }>( - ` - #### PrintNumber - - * "Print ..." - Prints given number - * E.g. "Print \"Hello there\"" - `, - 'PrintNumber', - [new Arg('num', getNumberV)], - async (world, { num }) => print(world, num.toString()) - ), - new View<{}>( - ` - #### PrintTransactionLogs - - * "PrintTransactionLogs" - Prints logs from all transacions - `, - 'PrintTransactionLogs', - [], - async (world, { }) => { - return await world.updateSettings(async settings => { - settings.printTxLogs = true; - - return settings; - }); - } - ), - new View<{ url: StringV; unlockedAccounts: AddressV[] }>( - ` - #### Web3Fork - - * "Web3Fork url: unlockedAccounts:[]" - Creates an in-memory ganache - * E.g. "Web3Fork \"https://mainnet.infura.io/v3/e1a5d4d2c06a4e81945fca56d0d5d8ea\" (\"0x8b8592e9570e96166336603a1b4bd1e8db20fa20\")" - `, - 'Web3Fork', - [ - new Arg('url', getStringV), - new Arg('unlockedAccounts', getAddressV, { default: [], mapped: true }) - ], - async (world, { url, unlockedAccounts }) => fork(world, url.val, unlockedAccounts.map(v => v.val)) - ), - - new View<{ networkVal: StringV; }>( - ` - #### UseConfigs - - * "UseConfigs networkVal:" - Updates world to use the configs for specified network - * E.g. "UseConfigs mainnet" - `, - 'UseConfigs', - [new Arg('networkVal', getStringV)], - async (world, { networkVal }) => { - const network = networkVal.val; - if (world.basePath && (network === 'mainnet' || network === 'kovan' || network === 'goerli' || network === 'rinkeby' || network == 'ropsten')) { - let newWorld = world.set('network', network); - let contractInfo; - [newWorld, contractInfo] = await loadContracts(newWorld); - if (contractInfo.length > 0) { - world.printer.printLine(`Contracts:`); - contractInfo.forEach((info) => world.printer.printLine(`\t${info}`)); - } - - return newWorld; - } - - return world; - } - ), - - new View<{ address: AddressV }>( - ` - #### MyAddress - - * "MyAddress address:" - Sets default from address (same as "Alias Me ") - * E.g. "MyAddress \"0x9C1856636d78C051deAd6CAB9c5699e4E25549e9\"" - `, - 'MyAddress', - [new Arg('address', getAddressV)], - async (world, { address }) => { - return await world.updateSettings(async settings => { - settings.aliases['Me'] = address.val; - - return settings; - }); - } - ), - new View<{ name: StringV; address: AddressV }>( - ` - #### Alias - - * "Alias name: address:" - Stores an alias between name and address - * E.g. "Alias Me \"0x9C1856636d78C051deAd6CAB9c5699e4E25549e9\"" - `, - 'Alias', - [new Arg('name', getStringV), new Arg('address', getAddressV)], - async (world, { name, address }) => { - return await world.updateSettings(async settings => { - settings.aliases[name.val] = address.val; - - return settings; - }); - } - ), - - new View<{ name: StringV; address: AddressV }>( - ` - #### Aliases - - * "Aliases - Prints all aliases - `, - 'Aliases', - [], - async (world, { name, address }) => { - world.printer.printLine('Aliases:'); - Object.entries(world.settings.aliases).forEach(([name, address]) => { - world.printer.printLine(`\t${name}: ${address}`); - }); - - return world; - } - ), - - new View<{ seconds: NumberV }>( - ` - #### IncreaseTime - - * "IncreaseTime seconds:" - Increase Ganache evm time by a number of seconds - * E.g. "IncreaseTime 60" - `, - 'IncreaseTime', - [new Arg('seconds', getNumberV)], - async (world, { seconds }) => { - await sendRPC(world, 'evm_increaseTime', [Number(seconds.val)]); - await sendRPC(world, 'evm_mine', []); - return world; - } - ), - - new View<{ timestamp: NumberV }>( - ` - #### SetTime - - * "SetTime timestamp:" - Increase Ganache evm time to specific timestamp - * E.g. "SetTime 1573597400" - `, - 'SetTime', - [new Arg('timestamp', getNumberV)], - async (world, { timestamp }) => { - await sendRPC(world, 'evm_mine', [timestamp.val]); - return world; - } - ), - - new View<{ timestamp: NumberV }>( - ` - #### FreezeTime - - * "FreezeTime timestamp:" - Freeze Ganache evm time to specific timestamp - * E.g. "FreezeTime 1573597400" - `, - 'FreezeTime', - [new Arg('timestamp', getNumberV)], - async (world, { timestamp }) => { - await sendRPC(world, 'evm_freezeTime', [timestamp.val]); - return world; - } - ), - - new View<{}>( - ` - #### MineBlock - - * "MineBlock" - Increase Ganache evm block number - * E.g. "MineBlock" - `, - 'MineBlock', - [], - async (world, { }) => { - await sendRPC(world, 'evm_mine', []); - return world; - } - ), - - new Command<{ blockNumber: NumberV }>( - ` - #### SetBlockNumber - - * "SetBlockNumber 10" - Increase Ganache evm block number - * E.g. "SetBlockNumber 10" - `, - 'SetBlockNumber', - [new Arg('blockNumber', getNumberV)], - async (world, from, { blockNumber }) => { - await sendRPC(world, 'evm_mineBlockNumber', [blockNumber.toNumber() - 1]) - return world; - } - ), - - new Command<{ blockNumber: NumberV, event: EventV }>( - ` - #### Block - - * "Block 10 (...event)" - Set block to block N and run event - * E.g. "Block 10 (Comp Deploy Admin)" - `, - 'Block', - [ - new Arg('blockNumber', getNumberV), - new Arg('event', getEventV) - ], - async (world, from, { blockNumber, event }) => { - await sendRPC(world, 'evm_mineBlockNumber', [blockNumber.toNumber() - 2]) - return await processCoreEvent(world, event.val, from); - } - ), - - new Command<{ blockNumber: NumberV }>( - ` - #### AdvanceBlocks - - * "AdvanceBlocks 10" - Increase Ganache latest + block number - * E.g. "AdvanceBlocks 10" - `, - 'AdvanceBlocks', - [new Arg('blockNumber', getNumberV)], - async (world, from, { blockNumber }) => { - const currentBlockNumber = await getCurrentBlockNumber(world); - await sendRPC(world, 'evm_mineBlockNumber', [Number(blockNumber.val) + currentBlockNumber]); - return world; - } - ), - - new View<{}>( - ` - #### Inspect - - * "Inspect" - Prints debugging information about the world - `, - 'Inspect', - [], - async (world, { }) => inspect(world, null) - ), - - new View<{ message: StringV }>( - ` - #### Debug - - * "Debug message:" - Same as inspect but prepends with a string - `, - 'Debug', - [new Arg('message', getStringV)], - async (world, { message }) => inspect(world, message.val) - ), - - new View<{ num: NumberV }>( - ` - #### DebugNumber - - * "Debug num:" - Same as inspect but prepends with a number - `, - 'DebugNumber', - [new Arg('num', getNumberV)], - async (world, { num }) => inspect(world, num.toString()) - ), - - new View<{ account: AddressV; event: EventV }>( - ` - #### From - - * "From " - Runs event as the given user - * E.g. "From Geoff (CToken cZRX Mint 5e18)" - `, - 'From', - [new Arg('account', getAddressV), new Arg('event', getEventV)], - async (world, { account, event }) => processCoreEvent(world, event.val, account.val) - ), - - new Command<{ event: EventV }>( - ` - #### Trx - - * "Trx ...trxEvent" - Handles event to set details of next transaction - * E.g. "Trx Value 1.0e18 (CToken cEth Mint 1.0e18)" - `, - 'Trx', - [new Arg('event', getEventV, { variadic: true })], - async (world, from, { event }) => processTrxEvent(world, event.val, from), - { subExpressions: trxCommands() } - ), - - new Command<{ event: EventV }>( - ` - #### Invariant - - * "Invariant ...invariant" - Adds a new invariant to the world which is checked after each transaction - * E.g. "Invariant Static (CToken cZRX TotalSupply)" - `, - 'Invariant', - [new Arg('event', getEventV, { variadic: true })], - async (world, from, { event }) => processInvariantEvent(world, event.val, from), - { subExpressions: invariantCommands() } - ), - - new Command<{ event: EventV }>( - ` - #### Expect - - * "Expect ...expectation" - Adds an expectation to hold after the next transaction - * E.g. "Expect Changes (CToken cZRX TotalSupply) +10.0e18" - `, - 'Expect', - [new Arg('event', getEventV, { variadic: true })], - async (world, from, { event }) => processExpectationEvent(world, event.val, from), - { subExpressions: expectationCommands() } - ), - - new View<{ type: StringV }>( - ` - #### HoldInvariants - - * "HoldInvariants type:" - Skips checking invariants on next command. - * E.g. "HoldInvariants" - Skips all invariants - * E.g. "HoldInvariants All" - Skips all invariants - * E.g. "HoldInvariants Success" - Skips "success" invariants - * E.g. "HoldInvariants Remains" - Skips "remains" invariants - * E.g. "HoldInvariants Static" - Skips "static" invariants - `, - 'HoldInvariants', - [new Arg('type', getStringV, { default: new StringV('All') })], - async (world, { type }) => holdInvariants(world, type.val) - ), - - new View<{ type: StringV }>( - ` - #### ClearInvariants - - * "ClearInvariants type:" - Removes all invariants. - * E.g. "ClearInvariants" - Removes all invariants - * E.g. "ClearInvariants All" - Removes all invariants - * E.g. "ClearInvariants Success" - Removes "success" invariants - * E.g. "ClearInvariants Remains" - Removes "remains" invariants - * E.g. "ClearInvariants Static" - Removes "static" invariants - `, - 'ClearInvariants', - [new Arg('type', getStringV, { default: new StringV('All') })], - async (world, { type }) => clearInvariants(world, type.val) - ), - - new Command<{ event: EventV }>( - ` - #### Assert - - * "Assert ...event" - Validates given assertion, raising an exception if assertion fails - * E.g. "Assert Equal (Erc20 BAT TokenBalance Geoff) (Exactly 5.0)" - `, - 'Assert', - [new Arg('event', getEventV, { variadic: true })], - async (world, from, { event }) => processAssertionEvent(world, event.val, from), - { subExpressions: assertionCommands() } - ), - - new Command<{ gate: Value; event: EventV }>( - ` - #### Gate - - * "Gate value event" - Runs event only if value is falsey. Thus, gate can be used to build idempotency. - * E.g. "Gate (Erc20 ZRX Address) (Erc20 Deploy BAT)" - `, - 'Gate', - [new Arg('gate', getCoreValue, { rescue: new NothingV() }), new Arg('event', getEventV)], - async (world, from, { gate, event }) => { - if (gate.truthy()) { - return world; - } else { - return processCoreEvent(world, event.val, from); - } - } - ), - - new Command<{ given: Value; event: EventV }>( - ` - #### Given - - * "Given value event" - Runs event only if value is truthy. Thus, given can be used to build existence checks. - * E.g. "Given ($var) (PriceOracle SetPrice cBAT $var)" - `, - 'Given', - [new Arg('given', getCoreValue, { rescue: new NothingV() }), new Arg('event', getEventV)], - async (world, from, { given, event }) => { - if (given.truthy()) { - return processCoreEvent(world, event.val, from); - } else { - return world; - } - } - ), - - new Command<{ address: AddressV; amount: NumberV }>( - ` - #### Send - - * "Send
" - Sends a given amount of eth to given address - * E.g. "Send cETH 0.5e18" - `, - 'Send', - [new Arg('address', getAddressV), new Arg('amount', getNumberV)], - (world, from, { address, amount }) => sendEther(world, from, address.val, amount.encode()) - ), - - new Command<{ event: EventV }>( - ` - #### Unitroller - - * "Unitroller ...event" - Runs given Unitroller event - * E.g. "Unitroller SetPendingImpl MyComptrollerImpl" - `, - 'Unitroller', - [new Arg('event', getEventV, { variadic: true })], - (world, from, { event }) => processUnitrollerEvent(world, event.val, from), - { subExpressions: unitrollerCommands() } - ), - - new Command<{ event: EventV }>( - ` - #### Comptroller - - * "Comptroller ...event" - Runs given Comptroller event - * E.g. "Comptroller _setReserveFactor 0.5" - `, - 'Comptroller', - [new Arg('event', getEventV, { variadic: true })], - (world, from, { event }) => processComptrollerEvent(world, event.val, from), - { subExpressions: comptrollerCommands() } - ), - - new Command<{ event: EventV }>( - ` - #### ComptrollerImpl - - * "ComptrollerImpl ...event" - Runs given ComptrollerImpl event - * E.g. "ComptrollerImpl MyImpl Become" - `, - 'ComptrollerImpl', - [new Arg('event', getEventV, { variadic: true })], - (world, from, { event }) => processComptrollerImplEvent(world, event.val, from), - { subExpressions: comptrollerImplCommands() } - ), - - new Command<{ event: EventV }>( - ` - #### CToken - - * "CToken ...event" - Runs given CToken event - * E.g. "CToken cZRX Mint 5e18" - `, - 'CToken', - [new Arg('event', getEventV, { variadic: true })], - (world, from, { event }) => processCTokenEvent(world, event.val, from), - { subExpressions: cTokenCommands() } - ), - - new Command<{ event: EventV }>( - ` - #### CTokenDelegate - - * "CTokenDelegate ...event" - Runs given CTokenDelegate event - * E.g. "CTokenDelegate Deploy CDaiDelegate cDaiDelegate" - `, - 'CTokenDelegate', - [new Arg('event', getEventV, { variadic: true })], - (world, from, { event }) => processCTokenDelegateEvent(world, event.val, from), - { subExpressions: cTokenDelegateCommands() } - ), - - new Command<{ event: EventV }>( - ` - #### Erc20 - - * "Erc20 ...event" - Runs given Erc20 event - * E.g. "Erc20 ZRX Facuet Geoff 5e18" - `, - 'Erc20', - [new Arg('event', getEventV, { variadic: true })], - (world, from, { event }) => processErc20Event(world, event.val, from), - { subExpressions: erc20Commands() } - ), - - new Command<{ event: EventV }>( - ` - #### InterestRateModel - - * "InterestRateModel ...event" - Runs given interest rate model event - * E.g. "InterestRateModel Deploy Fixed StdRate 0.5" - `, - 'InterestRateModel', - [new Arg('event', getEventV, { variadic: true })], - (world, from, { event }) => processInterestRateModelEvent(world, event.val, from), - { subExpressions: interestRateModelCommands() } - ), - - new Command<{ event: EventV }>( - ` - #### PriceOracle - - * "PriceOracle ...event" - Runs given Price Oracle event - * E.g. "PriceOracle SetPrice cZRX 1.5" - `, - 'PriceOracle', - [new Arg('event', getEventV, { variadic: true })], - (world, from, { event }) => processPriceOracleEvent(world, event.val, from), - { subExpressions: priceOracleCommands() } - ), - - new Command<{ event: EventV }>( - ` - #### PriceOracleProxy - - * "PriceOracleProxy ...event" - Runs given Price Oracle event - * E.g. "PriceOracleProxy Deploy (Unitroller Address) (PriceOracle Address) (CToken cETH Address)" - `, - 'PriceOracleProxy', - [new Arg('event', getEventV, { variadic: true })], - (world, from, { event }) => { - return processPriceOracleProxyEvent(world, event.val, from); - }, - { subExpressions: priceOracleProxyCommands() } - ), - - new Command<{ event: EventV }>( - ` - #### Comp - - * "Comp ...event" - Runs given comp event - * E.g. "Comp Deploy" - `, - 'Comp', - [new Arg('event', getEventV, { variadic: true })], - (world, from, { event }) => { - return processCompEvent(world, event.val, from); - }, - { subExpressions: compCommands() } - ), - - buildContractEvent("Counter", false), - buildContractEvent("Reservoir", true), - - new View<{ event: EventV }>( - ` - #### Help - - * "Help ...event" - Prints help for given command - * E.g. "Help From" - `, - 'Help', - [new Arg('event', getEventV, { variadic: true })], - async (world, { event }) => { - world.printer.printLine(''); - let { commands } = await getCommands(world); - printHelp(world.printer, event.val, commands); - - return world; - } - ) -]; - -async function getCommands(world: World) { - if (world.commands) { - return { world, commands: world.commands }; - } - - let allCommands = await Promise.all(commands.map((command) => { - if (typeof (command) === 'function') { - return command(world); - } else { - return Promise.resolve(command); - } - })); - - return { world: world.set('commands', allCommands), commands: allCommands }; -} - -export async function processCoreEvent(world: World, event: Event, from: string | null): Promise { - let { world: nextWorld, commands } = await getCommands(world); - return await processCommandEvent('Core', commands, nextWorld, event, from); -} diff --git a/scenario/src/CoreValue.ts b/scenario/src/CoreValue.ts deleted file mode 100644 index e66a5a8f5..000000000 --- a/scenario/src/CoreValue.ts +++ /dev/null @@ -1,977 +0,0 @@ -import { Event } from './Event'; -import { World } from './World'; -import { - AddressV, - AnythingV, - ArrayV, - BoolV, - EventV, - ExpNumberV, - ListV, - MapV, - NothingV, - NumberV, - PercentV, - PreciseV, - StringV, - Value -} from './Value'; -import { Arg, Fetcher, getFetcherValue } from './Command'; -import { getUserValue, userFetchers } from './Value/UserValue'; -import { comptrollerFetchers, getComptrollerValue } from './Value/ComptrollerValue'; -import { comptrollerImplFetchers, getComptrollerImplValue } from './Value/ComptrollerImplValue'; -import { getUnitrollerValue, unitrollerFetchers } from './Value/UnitrollerValue'; -import { cTokenFetchers, getCTokenValue } from './Value/CTokenValue'; -import { cTokenDelegateFetchers, getCTokenDelegateValue } from './Value/CTokenDelegateValue'; -import { erc20Fetchers, getErc20Value } from './Value/Erc20Value'; -import { mcdFetchers, getMCDValue } from './Value/MCDValue'; -import { getInterestRateModelValue, interestRateModelFetchers } from './Value/InterestRateModelValue'; -import { getPriceOracleValue, priceOracleFetchers } from './Value/PriceOracleValue'; -import { getPriceOracleProxyValue, priceOracleProxyFetchers } from './Value/PriceOracleProxyValue'; -import { getAnchoredViewValue, anchoredViewFetchers } from './Value/AnchoredViewValue'; -import { getCompValue, compFetchers } from './Value/CompValue'; -import { getAddress } from './ContractLookup'; -import { getCurrentBlockNumber, getCurrentTimestamp, mustArray, sendRPC } from './Utils'; -import { toEncodableNum } from './Encoding'; -import { BigNumber } from 'bignumber.js'; -import { buildContractFetcher } from './EventBuilder'; - -import { - padLeft, - sha3, - toBN, - toDecimal, - toHex -} from 'web3-utils'; - -const expMantissa = new BigNumber('1000000000000000000'); - -function getSigFigs(value) { - let str = value.toString(); - - str = str.replace(/e\d+/, ''); // Remove e01 - str = str.replace(/\./, ''); // Remove decimal point - - return str.length; -} - -export async function getEventV(world: World, event: Event): Promise { - return new EventV(event); -} - -// TODO: We may want to handle simple values -> complex values at the parser level -// This is currently trying to parse simple values as simple or complex values, -// and this is because items like `Some` could work either way. -export async function mapValue( - world: World, - event: Event, - simple: (string) => T, - complex: (World, Event) => Promise, - type: any -): Promise { - let simpleErr; - let val; - - if (typeof event === 'string') { - try { - return simple(event); - } catch (err) { - // Collect the error, but fallback to a complex expression - simpleErr = err; - } - } - - try { - val = await complex(world, event); - } catch (complexErr) { - // If we had an error before and this was the fallback, now throw that one - if (simpleErr) { - throw simpleErr; - } else { - throw complexErr; - } - } - - if (!(val instanceof type)) { - throw new Error(`Expected "${type.name}" from event "${event.toString()}", was: "${val.toString()}"`); - } - - // We just did a typecheck above... - return (val); -} - -export async function getBoolV(world: World, event: Event): Promise { - return mapValue( - world, - event, - str => { - const lower = str.trim().toLowerCase(); - - if (lower == 'true' || lower == 't' || lower == '1') { - return new BoolV(true); - } else { - return new BoolV(false); - } - }, - getCoreValue, - BoolV - ); -} - -export async function getAddressV(world: World, event: Event): Promise { - return mapValue( - world, - event, - str => new AddressV(getAddress(world, str)), - async (currWorld, val) => { - const coreVal = await getCoreValue(currWorld, val); - - if (coreVal instanceof StringV) { - return new AddressV(coreVal.val); - } else { - return coreVal; - } - }, - AddressV - ); -} - -function strToNumberV(str: string): NumberV { - if (isNaN(Number(str))) { - throw 'not a number'; - } - - return new NumberV(str); -} - -function strToExpNumberV(str: string): NumberV { - const r = new BigNumber(str); - - return new NumberV(r.multipliedBy(expMantissa).toFixed()); -} - -export async function getNumberV(world: World, event: Event): Promise { - return mapValue(world, event, strToNumberV, getCoreValue, NumberV); -} - -export async function getExpNumberV(world: World, event: Event): Promise { - let res = await mapValue(world, event, strToNumberV, getCoreValue, NumberV); - - const r = new BigNumber(res.val); - - return new ExpNumberV(r.multipliedBy(expMantissa).toFixed()); -} - -export async function getPercentV(world: World, event: Event): Promise { - let res = await getExpNumberV(world, event); - - return new PercentV(res.val); -} - -// Note: MapV does not currently parse its contents -export async function getMapV(world: World, event: Event): Promise { - const res: object = {}; - - await Promise.all( - mustArray(event).map(async e => { - if (Array.isArray(e) && e.length === 2 && typeof e[0] === 'string') { - const [key, valueEvent] = e; - let value; - if (typeof valueEvent === 'string') { - value = new StringV(valueEvent); - } else { - value = await getCoreValue(world, valueEvent); - } - - res[key] = value; - } else { - throw new Error(`Expected all string pairs for MapV from ${event.toString()}, got: ${e.toString()}`); - } - }) - ); - - return new MapV(res); -} - -export function getArrayV(fetcher: (World, Event) => Promise): (World, Event) => Promise> { - return async (world: World, event: Event): Promise> => { - const res = await Promise.all( - mustArray(event).filter((x) => x !== 'List').map(e => fetcher(world, e)) - ); - return new ArrayV(res); - } -} - -export async function getStringV(world: World, event: Event): Promise { - return mapValue(world, event, str => new StringV(str), getCoreValue, StringV); -} - -async function getEtherBalance(world: World, address: string): Promise { - let balance = await world.web3.eth.getBalance(address); - - return new NumberV(balance); -} - -const fetchers = [ - new Fetcher<{}, BoolV>( - ` - #### True - - * "True" - Returns true - `, - 'True', - [], - async (world, {}) => new BoolV(true) - ), - - new Fetcher<{}, BoolV>( - ` - #### False - - * "False" - Returns false - `, - 'False', - [], - async (world, {}) => new BoolV(false) - ), - - new Fetcher<{}, NumberV>( - ` - #### Zero - - * "Zero" - Returns 0 - `, - 'Zero', - [], - async (world, {}) => strToNumberV('0') - ), - - new Fetcher<{}, NumberV>( - ` - #### UInt96Max - - * "UInt96Max" - Returns 2^96 - 1 - `, - 'UInt96Max', - [], - async (world, {}) => - new NumberV('79228162514264337593543950335') - ), - - new Fetcher<{}, NumberV>( - ` - #### UInt256Max - - * "UInt256Max" - Returns 2^256 - 1 - `, - 'UInt256Max', - [], - async (world, {}) => - new NumberV('115792089237316195423570985008687907853269984665640564039457584007913129639935') - ), - - new Fetcher<{}, NumberV>( - ` - #### Some - - * "Some" - Returns 100e18 - `, - 'Some', - [], - async (world, {}) => strToNumberV('100e18') - ), - - new Fetcher<{}, NumberV>( - ` - #### Little - - * "Little" - Returns 100e10 - `, - 'Little', - [], - async (world, {}) => strToNumberV('100e10') - ), - - new Fetcher<{ amt: EventV }, NumberV>( - ` - #### Exactly - - * "Exactly " - Returns a strict numerical value - * E.g. "Exactly 5.0" - `, - 'Exactly', - [new Arg('amt', getEventV)], - async (world, { amt }) => getNumberV(world, amt.val) - ), - - new Fetcher<{ hexVal: EventV }, StringV>( - ` - #### Hex - - * "Hex " - Returns a byte string with given hex value - * E.g. "Hex \"0xffff\"" - `, - 'Hex', - [new Arg('hexVal', getEventV)], - async (world, { hexVal }) => getStringV(world, hexVal.val) - ), - - new Fetcher<{ str: EventV }, StringV>( - ` - #### String - - * "String " - Returns a string literal - * E.g. "String MyString" - `, - 'String', - [new Arg('str', getEventV)], - async (world, { str }) => getStringV(world, str.val) - ), - - new Fetcher<{ amt: EventV }, NumberV>( - ` - #### Exp - - * "Exp " - Returns the mantissa for a given exp - * E.g. "Exp 5.5" - `, - 'Exp', - [new Arg('amt', getEventV)], - async (world, { amt }) => getExpNumberV(world, amt.val) - ), - - new Fetcher<{ amt: EventV }, NumberV>( - ` - #### Neg - - * "Neg " - Returns the amount subtracted from zero - * E.g. "Neg amount" - `, - 'Neg', - [new Arg('amt', getEventV)], - async (world, { amt }) => new NumberV(0).sub(await getNumberV(world, amt.val)) - ), - - new Fetcher<{ amt: StringV }, PreciseV>( - ` - #### Precisely - - * "Precisely " - Matches a number to given number of significant figures - * E.g. "Precisely 5.1000" - Matches to 5 sig figs - `, - 'Precisely', - [new Arg('amt', getStringV)], - async (world, { amt }) => new PreciseV(toEncodableNum(amt.val), getSigFigs(amt.val)) - ), - - new Fetcher<{}, AnythingV>( - ` - #### Anything - - * "Anything" - Matches any value for assertions - `, - 'Anything', - [], - async (world, {}) => new AnythingV() - ), - - new Fetcher<{}, NothingV>( - ` - #### Nothing - - * "Nothing" - Matches no values and is nothing. - `, - 'Nothing', - [], - async (world, {}) => new NothingV() - ), - - new Fetcher<{ addr: AddressV }, AddressV>( - ` - #### Address - - * "Address arg:
" - Returns an address - `, - 'Address', - [new Arg('addr', getAddressV)], - async (world, { addr }) => addr - ), - - new Fetcher<{ num: NumberV }, NumberV>( - ` - #### Number - - * "Number arg:" - Returns a number - `, - 'Number', - [new Arg('num', getNumberV)], - async (world, { num }) => num - ), - - new Fetcher< - { addr: AddressV; slot: NumberV; start: NumberV; valType: StringV }, - BoolV | AddressV | ExpNumberV | NothingV - >( - ` - #### StorageAt - - * "StorageAt addr:
slot: start:, valType:" - Returns bytes at storage slot - `, - 'StorageAt', - [ - new Arg('addr', getAddressV), - new Arg('slot', getNumberV), - new Arg('start', getNumberV), - new Arg('valType', getStringV) - ], - async (world, { addr, slot, start, valType }) => { - const startVal = start.toNumber() - const reverse = s => s.split('').reverse().join(''); - const storage = await world.web3.eth.getStorageAt(addr.val, slot.toNumber()); - const stored = reverse(storage.slice(2)); // drop leading 0x and reverse since items are packed from the back of the slot - - // Don't forget to re-reverse - switch (valType.val) { - case 'bool': - return new BoolV(!!reverse(stored.slice(startVal, startVal + 2))); - case 'address': - return new AddressV('0x' + padLeft(reverse(stored.slice(startVal, startVal + 40)), 40)); - case 'number': - return new NumberV(toBN('0x' + reverse(stored)).toString()); - default: - return new NothingV(); - } - } - ), - - new Fetcher< - { addr: AddressV; slot: NumberV; key: AddressV; nestedKey: AddressV; valType: StringV }, - ListV | NothingV - >( - ` - #### StorageAtNestedMapping - - * "StorageAtNestedMapping addr:
slot:, key:
, nestedKey:
, valType:" - Returns bytes at storage slot - `, - 'StorageAtNestedMapping', - [ - new Arg('addr', getAddressV), - new Arg('slot', getNumberV), - new Arg('key', getAddressV), - new Arg('nestedKey', getAddressV), - new Arg('valType', getStringV) - ], - async (world, { addr, slot, key, nestedKey, valType }) => { - const areEqual = (v, x) => toBN(v).eq(toBN(x)); - let paddedSlot = slot.toNumber().toString(16).padStart(64, '0'); - let paddedKey = padLeft(key.val, 64); - let newKey = sha3(paddedKey + paddedSlot); - let val = await world.web3.eth.getStorageAt(addr.val, newKey); - - switch (valType.val) { - case 'marketStruct': - let isListed = areEqual(val, 1); - let collateralFactorKey = '0x' + toBN(newKey).add(toBN(1)).toString(16); - let collateralFactorStr = await world.web3.eth.getStorageAt(addr.val, collateralFactorKey); - let collateralFactor = toBN(collateralFactorStr); - let userMarketBaseKey = padLeft(toBN(newKey).add(toBN(2)).toString(16), 64); - let paddedSlot = padLeft(userMarketBaseKey, 64); - let paddedKey = padLeft(nestedKey.val, 64); - let newKeyTwo = sha3(paddedKey + paddedSlot); - let userInMarket = await world.web3.eth.getStorageAt(addr.val, newKeyTwo); - - let isCompKey = '0x' + toBN(newKey).add(toBN(3)).toString(16); - let isCompStr = await world.web3.eth.getStorageAt(addr.val, isCompKey); - - return new ListV([ - new BoolV(isListed), - new ExpNumberV(collateralFactor.toString(), 1e18), - new BoolV(areEqual(userInMarket, 1)), - new BoolV(areEqual(isCompStr, 1)) - ]); - default: - return new NothingV(); - } - } - ), - - new Fetcher< - { addr: AddressV; slot: NumberV; key: AddressV; valType: StringV }, - AddressV | BoolV | ExpNumberV | ListV | NothingV - >( - ` - #### StorageAtMapping - - * "StorageAtMapping addr:
slot:, key:
, valType:" - Returns bytes at storage slot - `, - 'StorageAtMapping', - [ - new Arg('addr', getAddressV), - new Arg('slot', getNumberV), - new Arg('key', getAddressV), - new Arg('valType', getStringV) - ], - async (world, { addr, slot, key, valType }) => { - let paddedSlot = slot.toNumber().toString(16).padStart(64, '0'); - let paddedKey = padLeft(key.val, 64); - let newKey = sha3(paddedKey + paddedSlot); - let val = await world.web3.eth.getStorageAt(addr.val, newKey); - - switch (valType.val) { - case 'list(address)': - let p = new Array(toDecimal(val)).fill(undefined).map(async (_v, index) => { - let newKeySha = sha3(newKey); - let itemKey = toBN(newKeySha).add(toBN(index)); - let address = await world.web3.eth.getStorageAt(addr.val, padLeft(toHex(itemKey), 40)); - return new AddressV(address); - }); - - let all = await Promise.all(p); - return new ListV(all); - - case 'bool': - return new BoolV(val != '0x' && val != '0x0'); - case 'address': - return new AddressV(val); - case 'number': - return new NumberV(toBN(val).toString()); - default: - return new NothingV(); - } - } - ), - - new Fetcher<{}, NumberV>( - ` - #### BlockNumber - * BlockNumber - `, - 'BlockNumber', - [], - async (world, {}) => { - return new NumberV(await getCurrentBlockNumber(world)); - } - ), - - new Fetcher<{}, NumberV>( - ` - #### GasCounter - * GasCounter - `, - 'GasCounter', - [], - async (world, {}) => new NumberV(world.gasCounter.value) - ), - - new Fetcher<{}, AddressV>( - ` - #### LastContract - - * "LastContract" - The address of last constructed contract - `, - 'LastContract', - [], - async (world, { }) => new AddressV(world.get('lastContract')) - ), - - new Fetcher<{}, NumberV>( - ` - #### LastBlock - - * "LastBlock" - The block of the last transaction - `, - 'LastBlock', - [], - async (world, { }) => { - let invokation = world.get('lastInvokation'); - if (!invokation) { - throw new Error(`Expected last invokation for "lastBlock" but none found.`); - } - - if (!invokation.receipt) { - throw new Error(`Expected last invokation to have receipt for "lastBlock" but none found.`); - } - - return new NumberV(invokation.receipt.blockNumber); - } - ), - - new Fetcher<{}, NumberV>( - ` - #### LastGas - - * "LastGas" - The gas consumed by the last transaction - `, - 'LastGas', - [], - async (world, {}) => { - let invokation = world.get('lastInvokation'); - if (!invokation) { - throw new Error(`Expected last invokation for "lastGas" but none found.`); - } - - if (!invokation.receipt) { - throw new Error(`Expected last invokation to have receipt for "lastGas" but none found.`); - } - - return new NumberV(invokation.receipt.gasUsed); - } - ), - - new Fetcher<{ els: Value[] }, AnythingV>( - ` - #### List - - * "List ..." - Returns a list of given elements - `, - 'List', - [new Arg('els', getCoreValue, { variadic: true, mapped: true })], - async (world, { els }) => new ListV(els) - ), - new Fetcher<{ val: Value; def: EventV }, Value>( - ` - #### Default - - * "Default val: def:" - Returns value if truthy, otherwise default. Note: this **does** short circuit. - `, - 'Default', - [new Arg('val', getCoreValue), new Arg('def', getEventV)], - async (world, { val, def }) => { - if (val.truthy()) { - return val; - } else { - return await getCoreValue(world, def.val); - } - } - ), - new Fetcher<{ minutes: NumberV }, NumberV>( - ` - #### Minutes - - * "Minutes minutes:" - Returns number of minutes in seconds - `, - 'Minutes', - [new Arg('minutes', getNumberV)], - async (world, { minutes }) => { - const minutesBn = new BigNumber(minutes.val); - return new NumberV(minutesBn.times(60).toFixed(0)); - } - ), - new Fetcher<{ hours: NumberV }, NumberV>( - ` - #### Hours - - * "Hours hours:" - Returns number of hours in seconds - `, - 'Hours', - [new Arg('hours', getNumberV)], - async (world, { hours }) => { - const hoursBn = new BigNumber(hours.val); - return new NumberV(hoursBn.times(3600).toFixed(0)); - } - ), - new Fetcher<{ days: NumberV }, NumberV>( - ` - #### Days - - * "Days days:" - Returns number of days in seconds - `, - 'Days', - [new Arg('days', getNumberV)], - async (world, { days }) => { - const daysBn = new BigNumber(days.val); - return new NumberV(daysBn.times(86400).toFixed(0)); - } - ), - new Fetcher<{ weeks: NumberV }, NumberV>( - ` - #### Weeks - - * "Weeks weeks:" - Returns number of weeks in seconds - `, - 'Weeks', - [new Arg('weeks', getNumberV)], - async (world, { weeks }) => { - const weeksBn = new BigNumber(weeks.val); - return new NumberV(weeksBn.times(604800).toFixed(0)); - } - ), - new Fetcher<{ years: NumberV }, NumberV>( - ` - #### Years - - * "Years years:" - Returns number of years in seconds - `, - 'Years', - [new Arg('years', getNumberV)], - async (world, { years }) => { - const yearsBn = new BigNumber(years.val); - return new NumberV(yearsBn.times(31536000).toFixed(0)); - } - ), - new Fetcher<{ seconds: NumberV }, NumberV>( - ` - #### FromNow - - * "FromNow seconds:" - Returns future timestamp of given seconds from now - `, - 'FromNow', - [new Arg('seconds', getNumberV)], - async (world, { seconds }) => { - const secondsBn = new BigNumber(seconds.val); - return new NumberV(secondsBn.plus(getCurrentTimestamp()).toFixed(0)); - } - ), - new Fetcher<{}, NumberV>( - ` - #### Now - - * "Now seconds:" - Returns current timestamp - `, - 'Now', - [], - async (world, {}) => { - return new NumberV(getCurrentTimestamp()); - } - ), - new Fetcher<{}, NumberV>( - ` - #### BlockTimestamp - - * "BlockTimestamp" - Returns the current block's timestamp - * E.g. "BlockTimestamp" - `, - 'BlockTimestamp', - [], - async (world, {}) => { - const {result: blockNumber}: any = await sendRPC(world, 'eth_blockNumber', []); - const {result: block}: any = await sendRPC(world, 'eth_getBlockByNumber', [blockNumber, false]); - return new NumberV(parseInt(block.timestamp, 16)); - } - ), - new Fetcher<{}, StringV>( - ` - #### Network - - * "Network" - Returns the current Network - `, - 'Network', - [], - async world => new StringV(world.network) - ), - new Fetcher<{ res: Value }, Value>( - ` - #### User - - * "User ...userArgs" - Returns user value - `, - 'User', - [new Arg('res', getUserValue, { variadic: true })], - async (world, { res }) => res, - { subExpressions: userFetchers() } - ), - new Fetcher<{ address: AddressV }, Value>( - ` - #### EtherBalance - - * "EtherBalance
" - Returns given address' ether balance. - `, - 'EtherBalance', - [new Arg('address', getAddressV)], - (world, { address }) => getEtherBalance(world, address.val) - ), - new Fetcher<{ given: Value; expected: Value }, BoolV>( - ` - #### Equal - - * "Equal given: expected:" - Returns true if given values are equal - * E.g. "Equal (Exactly 0) Zero" - * E.g. "Equal (CToken cZRX TotalSupply) (Exactly 55)" - * E.g. "Equal (CToken cZRX Comptroller) (Comptroller Address)" - `, - 'Equal', - [new Arg('given', getCoreValue), new Arg('expected', getCoreValue)], - async (world, { given, expected }) => new BoolV(expected.compareTo(world, given)) - ), - new Fetcher< - { - argTypes: StringV[]; - args: StringV[]; - }, - StringV - >( - ` - #### EncodeParameters - - * "EncodeParameters (...argTypes:) (...args:) - * E.g. "EncodeParameters (\"address\" \"address\") (\"0xabc\" \"0x123\") - `, - 'EncodeParameters', - [ - new Arg('argTypes', getStringV, { mapped: true }), - new Arg('args', getStringV, { mapped: true }) - ], - async (world, { argTypes, args }) => { - const realArgs = args.map((a, i) => { - if (argTypes[i].val == 'address') - return getAddress(world, a.val); - return a.val; - }); - return new StringV(world.web3.eth.abi.encodeParameters(argTypes.map(t => t.val), realArgs)); - } - ), - new Fetcher<{ res: Value }, Value>( - ` - #### Unitroller - - * "Unitroller ...unitrollerArgs" - Returns unitroller value - `, - 'Unitroller', - [new Arg('res', getUnitrollerValue, { variadic: true })], - async (world, { res }) => res, - { subExpressions: unitrollerFetchers() } - ), - new Fetcher<{ res: Value }, Value>( - ` - #### Comptroller - - * "Comptroller ...comptrollerArgs" - Returns comptroller value - `, - 'Comptroller', - [new Arg('res', getComptrollerValue, { variadic: true })], - async (world, { res }) => res, - { subExpressions: comptrollerFetchers() } - ), - new Fetcher<{ res: Value }, Value>( - ` - #### ComptrollerImpl - - * "ComptrollerImpl ...comptrollerImplArgs" - Returns comptroller implementation value - `, - 'ComptrollerImpl', - [new Arg('res', getComptrollerImplValue, { variadic: true })], - async (world, { res }) => res, - { subExpressions: comptrollerImplFetchers() } - ), - new Fetcher<{ res: Value }, Value>( - ` - #### CToken - - * "CToken ...cTokenArgs" - Returns cToken value - `, - 'CToken', - [new Arg('res', getCTokenValue, { variadic: true })], - async (world, { res }) => res, - { subExpressions: cTokenFetchers() } - ), - new Fetcher<{ res: Value }, Value>( - ` - #### CTokenDelegate - - * "CTokenDelegate ...cTokenDelegateArgs" - Returns cToken delegate value - `, - 'CTokenDelegate', - [new Arg('res', getCTokenDelegateValue, { variadic: true })], - async (world, { res }) => res, - { subExpressions: cTokenDelegateFetchers() } - ), - new Fetcher<{ res: Value }, Value>( - ` - #### Erc20 - - * "Erc20 ...erc20Args" - Returns Erc20 value - `, - 'Erc20', - [new Arg('res', getErc20Value, { variadic: true })], - async (world, { res }) => res, - { subExpressions: erc20Fetchers() } - ), - new Fetcher<{ res: Value }, Value>( - ` - #### InterestRateModel - - * "InterestRateModel ...interestRateModelArgs" - Returns InterestRateModel value - `, - 'InterestRateModel', - [new Arg('res', getInterestRateModelValue, { variadic: true })], - async (world, { res }) => res, - { subExpressions: interestRateModelFetchers() } - ), - new Fetcher<{ res: Value }, Value>( - ` - #### PriceOracle - - * "PriceOracle ...priceOracleArgs" - Returns PriceOracle value - `, - 'PriceOracle', - [new Arg('res', getPriceOracleValue, { variadic: true })], - async (world, { res }) => res, - { subExpressions: priceOracleFetchers() } - ), - new Fetcher<{ res: Value }, Value>( - ` - #### PriceOracleProxy - - * "PriceOracleProxy ...priceOracleProxyArgs" - Returns PriceOracleProxy value - `, - 'PriceOracleProxy', - [new Arg('res', getPriceOracleProxyValue, { variadic: true })], - async (world, { res }) => res, - { subExpressions: priceOracleProxyFetchers() } - ), - new Fetcher<{ res: Value }, Value>( - ` - #### AnchoredView - - * "AnchoredView ...anchoredViewArgs" - Returns AnchoredView value - `, - 'AnchoredView', - [new Arg('res', getAnchoredViewValue, { variadic: true })], - async (world, { res }) => res, - { subExpressions: anchoredViewFetchers() } - ), - new Fetcher<{ res: Value }, Value>( - ` - #### MCD - - * "MCD ...mcdArgs" - Returns MCD value - `, - 'MCD', - [new Arg('res', getMCDValue, { variadic: true })], - async (world, { res }) => res, - { subExpressions: mcdFetchers() } - ), - new Fetcher<{ res: Value }, Value>( - ` - #### Comp - - * "Comp ...compArgs" - Returns Comp value - `, - 'Comp', - [new Arg('res', getCompValue, { variadic: true })], - async (world, { res }) => res, - { subExpressions: compFetchers() } - ), -]; - -let contractFetchers = [ - { contract: "Counter", implicit: false }, - { contract: "Reservoir", implicit: true } -]; - -export async function getFetchers(world: World) { - if (world.fetchers) { - return { world, fetchers: world.fetchers }; - } - - let allFetchers = fetchers.concat(await Promise.all(contractFetchers.map(({contract, implicit}) => { - return buildContractFetcher(world, contract, implicit); - }))); - - return { world: world.set('fetchers', allFetchers), fetchers: allFetchers }; -} - -export async function getCoreValue(world: World, event: Event): Promise { - let {world: nextWorld, fetchers} = await getFetchers(world); - return await getFetcherValue('Core', fetchers, nextWorld, event); -} diff --git a/scenario/src/Encoding.ts b/scenario/src/Encoding.ts deleted file mode 100644 index 22a2b0a54..000000000 --- a/scenario/src/Encoding.ts +++ /dev/null @@ -1,18 +0,0 @@ -import BigNumber from 'bignumber.js'; - -const smallEnoughNumber = new BigNumber('100000000'); - -export type encodedNumber = number | BigNumber; - -// Returns the mantissa of an Exp with given floating value -export function getExpMantissa(float: number): encodedNumber { - // Workaround from https://github.com/ethereum/web3.js/issues/1920 - const str = Math.floor(float * 1.0e18).toString(); - - return toEncodableNum(str); -} - -export function toEncodableNum(amountArgRaw: string | encodedNumber): encodedNumber { - const bigNumber = new BigNumber(amountArgRaw); - return bigNumber.lt(smallEnoughNumber) ? bigNumber.toNumber() : bigNumber; -} diff --git a/scenario/src/ErrorReporter.ts b/scenario/src/ErrorReporter.ts deleted file mode 100644 index 8fd7367a6..000000000 --- a/scenario/src/ErrorReporter.ts +++ /dev/null @@ -1,121 +0,0 @@ - -import { utils } from 'ethers'; -import {ComptrollerErr, TokenErr} from './ErrorReporterConstants'; - -export interface ErrorReporter { - getError(error: any): string | null - getInfo(info: any): string | null - getDetail(error: any, detail: number): string - getEncodedCustomError(errorName: string, args: unknown[]): string | null -} - -class NoErrorReporterType implements ErrorReporter { - getError(error: any): string | null { - return null; - } - - getInfo(info: any): string | null { - return null; - } - - getDetail(error: any, detail: number): string { - return detail.toString(); - } - - getEncodedCustomError(errorName: string, args: unknown[]): string | null { - return null - } -} - -class CTokenErrorReporterType implements ErrorReporter { - getError(error: any): string | null { - if (error === null) { - return null; - } else { - return TokenErr.ErrorInv[Number(error)]; - } - } - - getInfo(info: any): string | null { - if (info === null) { - return null; - } else { - return TokenErr.FailureInfoInv[Number(info)]; - } - } - - getDetail(error: any, detail: number): string { - // Little hack to let us use proper names for cross-contract errors - if (this.getError(error) === "COMPTROLLER_REJECTION") { - let comptrollerError = ComptrollerErrorReporter.getError(detail); - - if (comptrollerError) { - return comptrollerError; - } - } - - return detail.toString(); - } - - getEncodedCustomError(errorName: string, args: unknown[]): string | null { - try { - return TokenErr.CustomErrors.encodeErrorResult(errorName, args) - } catch (err) { - return null - } - } -} - -class ComptrollerErrorReporterType implements ErrorReporter { - getError(error: any): string | null { - if (error === null) { - return null; - } else { - // TODO: This probably isn't right... - return ComptrollerErr.ErrorInv[Number(error)]; - } - } - - getInfo(info: any): string | null { - if (info === null) { - return null; - } else { - // TODO: This probably isn't right... - return ComptrollerErr.FailureInfoInv[Number(info)]; - } - } - - getDetail(error: any, detail: number): string { - if (this.getError(error) === "REJECTION") { - let comptrollerError = ComptrollerErrorReporter.getError(detail); - - if (comptrollerError) { - return comptrollerError; - } - } - - return detail.toString(); - } - - getEncodedCustomError(errorName: string, args: unknown[]): string | null { - try { - return ComptrollerErr.CustomErrors.encodeErrorResult(errorName, args) - } catch (err) { - return null - } - } -} - -export function formatResult(errorReporter: ErrorReporter, result: any): string { - const errorStr = errorReporter.getError(result); - if (errorStr !== null) { - return `Error=${errorStr}` - } else { - return `Result=${result}`; - } -} - -// Singleton instances -export const NoErrorReporter = new NoErrorReporterType(); -export const CTokenErrorReporter = new CTokenErrorReporterType(); -export const ComptrollerErrorReporter = new ComptrollerErrorReporterType(); diff --git a/scenario/src/ErrorReporterConstants.ts b/scenario/src/ErrorReporterConstants.ts deleted file mode 100644 index fa4e13d7e..000000000 --- a/scenario/src/ErrorReporterConstants.ts +++ /dev/null @@ -1,243 +0,0 @@ -import * as ethers from 'ethers' -interface ErrorReporterEnum { - Error: string[] - FailureInfo: string[] - CustomErrors?: string[] -} - -interface ErrorTypes { - Error: {[name: string]: number} - FailureInfo: {[name: string]: number} - ErrorInv: {[code: number]: string} - FailureInfoInv: {[code: number]: string} - CustomErrors: ethers.utils.Interface -} - -const ComptrollerErrorReporter = { - Error: [ - 'NO_ERROR', - 'UNAUTHORIZED', - 'COMPTROLLER_MISMATCH', - 'INSUFFICIENT_SHORTFALL', - 'INSUFFICIENT_LIQUIDITY', - 'INVALID_CLOSE_FACTOR', - 'INVALID_COLLATERAL_FACTOR', - 'INVALID_LIQUIDATION_INCENTIVE', - 'MARKET_NOT_ENTERED', - 'MARKET_NOT_LISTED', - 'MARKET_ALREADY_LISTED', - 'MATH_ERROR', - 'NONZERO_BORROW_BALANCE', - 'PRICE_ERROR', - 'REJECTION', - 'SNAPSHOT_ERROR', - 'TOO_MANY_ASSETS', - 'TOO_MUCH_REPAY' - ], - - FailureInfo: [ - 'ACCEPT_ADMIN_PENDING_ADMIN_CHECK', - 'ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK', - 'EXIT_MARKET_BALANCE_OWED', - 'EXIT_MARKET_REJECTION', - 'SET_CLOSE_FACTOR_OWNER_CHECK', - 'SET_CLOSE_FACTOR_VALIDATION', - 'SET_COLLATERAL_FACTOR_OWNER_CHECK', - 'SET_COLLATERAL_FACTOR_NO_EXISTS', - 'SET_COLLATERAL_FACTOR_VALIDATION', - 'SET_COLLATERAL_FACTOR_WITHOUT_PRICE', - 'SET_IMPLEMENTATION_OWNER_CHECK', - 'SET_LIQUIDATION_INCENTIVE_OWNER_CHECK', - 'SET_LIQUIDATION_INCENTIVE_VALIDATION', - 'SET_MAX_ASSETS_OWNER_CHECK', - 'SET_PENDING_ADMIN_OWNER_CHECK', - 'SET_PENDING_IMPLEMENTATION_OWNER_CHECK', - 'SET_PRICE_ORACLE_OWNER_CHECK', - 'SUPPORT_MARKET_EXISTS', - 'SUPPORT_MARKET_OWNER_CHECK', - 'SET_PAUSE_GUARDIAN_OWNER_CHECK', - ] -}; - -const TokenErrorReporter = { - Error: [ - 'NO_ERROR', - 'UNAUTHORIZED', - 'BAD_INPUT', - 'COMPTROLLER_REJECTION', - 'COMPTROLLER_CALCULATION_ERROR', - 'INTEREST_RATE_MODEL_ERROR', - 'INVALID_ACCOUNT_PAIR', - 'INVALID_CLOSE_AMOUNT_REQUESTED', - 'INVALID_COLLATERAL_FACTOR', - 'MATH_ERROR', - 'MARKET_NOT_FRESH', - 'MARKET_NOT_LISTED', - 'TOKEN_INSUFFICIENT_ALLOWANCE', - 'TOKEN_INSUFFICIENT_BALANCE', - 'TOKEN_INSUFFICIENT_CASH', - 'TOKEN_TRANSFER_IN_FAILED', - 'TOKEN_TRANSFER_OUT_FAILED' - ], - - FailureInfo: [ - 'ACCEPT_ADMIN_PENDING_ADMIN_CHECK', - 'ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED', - 'ACCRUE_INTEREST_BORROW_RATE_CALCULATION_FAILED', - 'ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED', - 'ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED', - 'ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED', - 'ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED', - 'BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED', - 'BORROW_ACCRUE_INTEREST_FAILED', - 'BORROW_CASH_NOT_AVAILABLE', - 'BORROW_FRESHNESS_CHECK', - 'BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED', - 'BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED', - 'BORROW_MARKET_NOT_LISTED', - 'BORROW_COMPTROLLER_REJECTION', - 'LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED', - 'LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED', - 'LIQUIDATE_COLLATERAL_FRESHNESS_CHECK', - 'LIQUIDATE_COMPTROLLER_REJECTION', - 'LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED', - 'LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX', - 'LIQUIDATE_CLOSE_AMOUNT_IS_ZERO', - 'LIQUIDATE_FRESHNESS_CHECK', - 'LIQUIDATE_LIQUIDATOR_IS_BORROWER', - 'LIQUIDATE_REPAY_BORROW_FRESH_FAILED', - 'LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED', - 'LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED', - 'LIQUIDATE_SEIZE_COMPTROLLER_REJECTION', - 'LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER', - 'LIQUIDATE_SEIZE_TOO_MUCH', - 'MINT_ACCRUE_INTEREST_FAILED', - 'MINT_COMPTROLLER_REJECTION', - 'MINT_EXCHANGE_CALCULATION_FAILED', - 'MINT_EXCHANGE_RATE_READ_FAILED', - 'MINT_FRESHNESS_CHECK', - 'MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED', - 'MINT_NEW_TOTAL_SUPPLY_CALCULATION_FAILED', - 'MINT_TRANSFER_IN_FAILED', - 'MINT_TRANSFER_IN_NOT_POSSIBLE', - 'REDEEM_ACCRUE_INTEREST_FAILED', - 'REDEEM_COMPTROLLER_REJECTION', - 'REDEEM_EXCHANGE_TOKENS_CALCULATION_FAILED', - 'REDEEM_EXCHANGE_AMOUNT_CALCULATION_FAILED', - 'REDEEM_EXCHANGE_RATE_READ_FAILED', - 'REDEEM_FRESHNESS_CHECK', - 'REDEEM_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED', - 'REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED', - 'REDEEM_TRANSFER_OUT_NOT_POSSIBLE', - 'REDUCE_RESERVES_ACCRUE_INTEREST_FAILED', - 'REDUCE_RESERVES_ADMIN_CHECK', - 'REDUCE_RESERVES_CASH_NOT_AVAILABLE', - 'REDUCE_RESERVES_FRESH_CHECK', - 'REDUCE_RESERVES_VALIDATION', - 'REPAY_BEHALF_ACCRUE_INTEREST_FAILED', - 'REPAY_BORROW_ACCRUE_INTEREST_FAILED', - 'REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED', - 'REPAY_BORROW_COMPTROLLER_REJECTION', - 'REPAY_BORROW_FRESHNESS_CHECK', - 'REPAY_BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED', - 'REPAY_BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED', - 'REPAY_BORROW_TRANSFER_IN_NOT_POSSIBLE', - 'SET_COLLATERAL_FACTOR_OWNER_CHECK', - 'SET_COLLATERAL_FACTOR_VALIDATION', - 'SET_COMPTROLLER_OWNER_CHECK', - 'SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED', - 'SET_INTEREST_RATE_MODEL_FRESH_CHECK', - 'SET_INTEREST_RATE_MODEL_OWNER_CHECK', - 'SET_MAX_ASSETS_OWNER_CHECK', - 'SET_ORACLE_MARKET_NOT_LISTED', - 'SET_PENDING_ADMIN_OWNER_CHECK', - 'SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED', - 'SET_RESERVE_FACTOR_ADMIN_CHECK', - 'SET_RESERVE_FACTOR_FRESH_CHECK', - 'SET_RESERVE_FACTOR_BOUNDS_CHECK', - 'TRANSFER_COMPTROLLER_REJECTION', - 'TRANSFER_NOT_ALLOWED', - 'TRANSFER_NOT_ENOUGH', - 'TRANSFER_TOO_MUCH', - 'ADD_RESERVES_ACCRUE_INTEREST_FAILED', - 'ADD_RESERVES_FRESH_CHECK', - 'ADD_RESERVES_TRANSFER_IN_NOT_POSSIBLE' - ], - - CustomErrors: [ - "error TransferComptrollerRejection(uint256 errorCode)", - "error TransferNotAllowed()", - "error TransferNotEnough()", - "error TransferTooMuch()", - - "error MintComptrollerRejection(uint256 errorCode)", - "error MintFreshnessCheck()", - - "error RedeemComptrollerRejection(uint256 errorCode)", - "error RedeemFreshnessCheck()", - "error RedeemTransferOutNotPossible()", - - "error BorrowComptrollerRejection(uint256 errorCode)", - "error BorrowFreshnessCheck()", - "error BorrowCashNotAvailable()", - - "error RepayBorrowComptrollerRejection(uint256 errorCode)", - "error RepayBorrowFreshnessCheck()", - - "error LiquidateComptrollerRejection(uint256 errorCode)", - "error LiquidateFreshnessCheck()", - "error LiquidateCollateralFreshnessCheck()", - "error LiquidateAccrueBorrowInterestFailed(uint256 errorCode)", - "error LiquidateAccrueCollateralInterestFailed(uint256 errorCode)", - "error LiquidateLiquidatorIsBorrower()", - "error LiquidateCloseAmountIsZero()", - "error LiquidateCloseAmountIsUintMax()", - "error LiquidateRepayBorrowFreshFailed(uint256 errorCode)", - - "error LiquidateSeizeComptrollerRejection(uint256 errorCode)", - "error LiquidateSeizeLiquidatorIsBorrower()", - - "error AcceptAdminPendingAdminCheck()", - - "error SetComptrollerOwnerCheck()", - "error SetPendingAdminOwnerCheck()", - - "error SetReserveFactorAdminCheck()", - "error SetReserveFactorFreshCheck()", - "error SetReserveFactorBoundsCheck()", - - "error AddReservesFactorFreshCheck(uint256 actualAddAmount)", - - "error ReduceReservesAdminCheck()", - "error ReduceReservesFreshCheck()", - "error ReduceReservesCashNotAvailable()", - "error ReduceReservesCashValidation()", - - "error SetInterestRateModelOwnerCheck()", - "error SetInterestRateModelFreshCheck();", - ] -}; - -function parseEnum(reporterEnum: ErrorReporterEnum): ErrorTypes { - const Error: {[name: string]: number} = {}; - const ErrorInv: {[code: number]: string} = {}; - const FailureInfo: {[name: string]: number} = {}; - const FailureInfoInv: {[code: number]: string} = {}; - - reporterEnum.Error.forEach((entry, i) => { - Error[entry] = i; - ErrorInv[i] = entry; - }); - - reporterEnum.FailureInfo.forEach((entry, i) => { - FailureInfo[entry] = i; - FailureInfoInv[i] = entry; - }); - - const CustomErrors = new ethers.utils.Interface(reporterEnum.CustomErrors || []) - - return {Error, ErrorInv, FailureInfo, FailureInfoInv, CustomErrors}; -} - -export const ComptrollerErr = parseEnum(ComptrollerErrorReporter); -export const TokenErr = parseEnum(TokenErrorReporter); diff --git a/scenario/src/Event.ts b/scenario/src/Event.ts deleted file mode 100644 index b5eb6e373..000000000 --- a/scenario/src/Event.ts +++ /dev/null @@ -1,7 +0,0 @@ - -type ScalarEvent = string; -interface EventArray extends Array { - [index: number]: ScalarEvent | EventArray; -} - -export type Event = EventArray; diff --git a/scenario/src/Event/AssertionEvent.ts b/scenario/src/Event/AssertionEvent.ts deleted file mode 100644 index c660ec7f3..000000000 --- a/scenario/src/Event/AssertionEvent.ts +++ /dev/null @@ -1,509 +0,0 @@ -import { Event } from '../Event'; -import { fail, World } from '../World'; -import { getCoreValue } from '../CoreValue'; -import { Failure, InvokationRevertCustomError, InvokationRevertFailure } from '../Invokation'; -import { - getEventV, - getMapV, - getNumberV, - getStringV -} from '../CoreValue'; -import { - AddressV, - BoolV, - EventV, - ListV, - MapV, - NumberV, - Order, - StringV, - Value -} from '../Value'; -import { Arg, View, processCommandEvent } from '../Command'; -import { rawValues } from '../Utils'; - -async function assertApprox(world: World, given: NumberV, expected: NumberV, tolerance: NumberV): Promise { - if (Math.abs(Number(expected.sub(given).div(expected).val)) > Number(tolerance.val)) { - return fail(world, `Expected ${given.toString()} to approximately equal ${expected.toString()} within ${tolerance.toString()}`); - } - - return world; -} - -async function assertEqual(world: World, given: Value, expected: Value): Promise { - if (!expected.compareTo(world, given)) { - return fail(world, `Expected ${given.toString()} to equal ${expected.toString()}`); - } - - return world; -} - -async function assertLessThan(world: World, given: Value, expected: Value): Promise { - if (given.compareOrder(world, expected) !== Order.LESS_THAN) { - return fail(world, `Expected ${given.toString()} to be less than ${expected.toString()}`); - } - - return world; -} - -async function assertGreaterThan(world: World, given: Value, expected: Value): Promise { - if (given.compareOrder(world, expected) !== Order.GREATER_THAN) { - return fail(world, `Expected ${given.toString()} to be greater than ${expected.toString()}`); - } - - return world; -} - -async function assertFailure(world: World, failure: Failure): Promise { - if (!world.lastInvokation) { - return fail(world, `Expected ${failure.toString()}, but missing any invokations.`); - } - - if (world.lastInvokation.success()) { - return fail(world, `Expected ${failure.toString()}, but last invokation was successful with result ${JSON.stringify(world.lastInvokation.value)}.`); - } - - if (world.lastInvokation.error) { - return fail(world, `Expected ${failure.toString()}, but last invokation threw error ${world.lastInvokation.error}.`); - } - - if (world.lastInvokation.failures.length === 0) { - throw new Error(`Invokation requires success, failure or error, got: ${world.lastInvokation.toString()}`); - } - - if (world.lastInvokation.failures.find((f) => f.equals(failure)) === undefined) { - return fail(world, `Expected ${failure.toString()}, but got ${world.lastInvokation.failures.toString()}.`); - } - - return world; -} - -// coverage tests don't currently support checking full message given with a revert -function coverageSafeRevertMessage(world: World, message: string): string { - if (world.network === 'coverage') { - return "revert"; - } else { - return message; - } -} - -async function assertRevertFailure(world: World, err: string, message: string): Promise { - if (world.network === 'coverage') { // coverage doesn't have detailed message, thus no revert failures - return await assertRevert(world, message); - } - - if (!world.lastInvokation) { - return fail(world, `Expected revert failure, but missing any invokations.`); - } - - if (world.lastInvokation.success()) { - return fail(world, `Expected revert failure, but last invokation was successful with result ${JSON.stringify(world.lastInvokation.value)}.`); - } - - if (world.lastInvokation.failures.length > 0) { - return fail(world, `Expected revert failure, but got ${world.lastInvokation.failures.toString()}.`); - } - - if (!world.lastInvokation.error) { - throw new Error(`Invokation requires success, failure or error, got: ${world.lastInvokation.toString()}`); - } - - if (!(world.lastInvokation.error instanceof InvokationRevertFailure)) { - throw new Error(`Invokation error mismatch, expected revert failure: "${err}, ${message}", got: "${world.lastInvokation.error.toString()}"`); - } - - const expectedMessage = `VM Exception while processing transaction: ${coverageSafeRevertMessage(world, message)}`; - - if (world.lastInvokation.error.error !== err || world.lastInvokation.error.errMessage !== expectedMessage) { - throw new Error(`Invokation error mismatch, expected revert failure: err=${err}, message="${expectedMessage}", got: "${world.lastInvokation.error.toString()}"`); - } - - return world; -} - -async function assertRevertCustomError(world: World, err: string, args: unknown[]): Promise { - if (world.network === 'coverage') { // coverage doesn't have detailed message, thus no revert failures - return await assertRevert(world, "revert"); - } - - if (!world.lastInvokation) { - return fail(world, `Expected revert failure, but missing any invokations.`); - } - - if (world.lastInvokation.success()) { - return fail(world, `Expected revert failure, but last invokation was successful with result ${JSON.stringify(world.lastInvokation.value)}.`); - } - - if (world.lastInvokation.failures.length > 0) { - return fail(world, `Expected revert failure, but got ${world.lastInvokation.failures.toString()}.`); - } - - if (!world.lastInvokation.error) { - throw new Error(`Invokation requires success, failure or error, got: ${world.lastInvokation.toString()}`); - } - - if (!(world.lastInvokation.error instanceof InvokationRevertCustomError)) { - throw new Error(`Invokation error mismatch, expected revert custom error: "${err}", got: "${world.lastInvokation.error.toString()}"`); - } - - const expectedResult = world.lastInvokation.errorReporter.getEncodedCustomError(err, args); - - if (!expectedResult) { - throw new Error(`Expected revert with custom error, but custom error ${err} not found`) - } - - if (Object.values(world.lastInvokation.error.errorResults).findIndex(v => v.error === 'revert' && v.return === expectedResult) < 0) { - throw new Error(`Invokation error mismatch, expected revert custom error: err=${err}, args="${args.join(',')}", got: "${world.lastInvokation.error.toString()}"`); - } - - return world; -} - -async function assertError(world: World, message: string): Promise { - if (!world.lastInvokation) { - return fail(world, `Expected revert, but missing any invokations.`); - } - - if (world.lastInvokation.success()) { - return fail(world, `Expected revert, but last invokation was successful with result ${JSON.stringify(world.lastInvokation.value)}.`); - } - - if (world.lastInvokation.failures.length > 0) { - return fail(world, `Expected revert, but got ${world.lastInvokation.failures.toString()}.`); - } - - if (!world.lastInvokation.error) { - throw new Error(`Invokation requires success, failure or error, got: ${world.lastInvokation.toString()}`); - } - - if (!world.lastInvokation.error.message.startsWith(message)) { - throw new Error(`Invokation error mismatch, expected: "${message}", got: "${world.lastInvokation.error.message}"`); - } - - return world; -} - -function buildRevertMessage(world: World, message: string): string { - return `VM Exception while processing transaction: ${coverageSafeRevertMessage(world, message)}` -} - -async function assertRevert(world: World, message: string): Promise { - return await assertError(world, buildRevertMessage(world, message)); -} - -async function assertSuccess(world: World): Promise { - if (!world.lastInvokation || world.lastInvokation.success()) { - return world; - } else { - return fail(world, `Expected success, but got ${world.lastInvokation.toString()}.`); - } -} - -async function assertReadError(world: World, event: Event, message: string, isRevert: boolean): Promise { - try { - let value = await getCoreValue(world, event); - - throw new Error(`Expected read revert, instead got value \`${value}\``); - } catch (err) { - let expectedMessage; - if (isRevert) { - expectedMessage = buildRevertMessage(world, message); - } else { - expectedMessage = message; - } - - world.expect(expectedMessage).toEqual(err.message); // XXXS "expected read revert" - } - - return world; -} - -function getLogValue(value: any): Value { - if (typeof value === 'number' || (typeof value === 'string' && value.match(/^[0-9]+$/))) { - return new NumberV(Number(value)); - } else if (typeof value === 'string') { - return new StringV(value); - } else if (typeof value === 'boolean') { - return new BoolV(value); - } else if (Array.isArray(value)) { - return new ListV(value.map(getLogValue)); - } else { - throw new Error('Unknown type of log parameter: ${value}'); - } -} - -async function assertLog(world: World, event: string, keyValues: MapV): Promise { - if (!world.lastInvokation) { - return fail(world, `Expected log message "${event}" from contract execution, but world missing any invokations.`); - } else if (!world.lastInvokation.receipt) { - return fail(world, `Expected log message "${event}" from contract execution, but world invokation transaction.`); - } else { - const log = world.lastInvokation.receipt.events && world.lastInvokation.receipt.events[event]; - - if (!log) { - const events = Object.keys(world.lastInvokation.receipt.events || {}).join(', '); - return fail(world, `Expected log with event \`${event}\`, found logs with events: [${events}]`); - } - - if (Array.isArray(log)) { - const found = log.find(_log => { - return Object.entries(keyValues.val).reduce((previousValue, currentValue) => { - const [key, value] = currentValue; - if (previousValue) { - if (_log.returnValues[key] === undefined) { - return false; - } else { - let logValue = getLogValue(_log.returnValues[key]); - - if (!logValue.compareTo(world, value)) { - return false; - } - - return true; - } - } - return previousValue; - }, true as boolean); - }); - - if (!found) { - const eventExpected = Object.entries(keyValues.val).join(', '); - const eventDetailsFound = log.map(_log => { - return Object.entries(_log.returnValues); - }); - return fail(world, `Expected log with event \`${eventExpected}\`, found logs for this event with: [${eventDetailsFound}]`); - } - - } else { - Object.entries(keyValues.val).forEach(([key, value]) => { - if (log.returnValues[key] === undefined) { - fail(world, `Expected log to have param for \`${key}\``); - } else { - let logValue = getLogValue(log.returnValues[key]); - - if (!logValue.compareTo(world, value)) { - fail(world, `Expected log to have param \`${key}\` to match ${value.toString()}, but got ${logValue.toString()}`); - } - } - }); - } - - return world; - } -} - -export function assertionCommands() { - return [ - new View<{ given: NumberV, expected: NumberV, tolerance: NumberV }>(` - #### Approx - - * "Approx given: expected: tolerance:" - Asserts that given approximately matches expected. - * E.g. "Assert Approx (Exactly 0) Zero " - * E.g. "Assert Approx (CToken cZRX TotalSupply) (Exactly 55) 1e-18" - * E.g. "Assert Approx (CToken cZRX Comptroller) (Comptroller Address) 1" - `, - "Approx", - [ - new Arg("given", getNumberV), - new Arg("expected", getNumberV), - new Arg("tolerance", getNumberV, { default: new NumberV(0.001) }) - ], - (world, { given, expected, tolerance }) => assertApprox(world, given, expected, tolerance) - ), - - new View<{ given: Value, expected: Value }>(` - #### Equal - - * "Equal given: expected:" - Asserts that given matches expected. - * E.g. "Assert Equal (Exactly 0) Zero" - * E.g. "Assert Equal (CToken cZRX TotalSupply) (Exactly 55)" - * E.g. "Assert Equal (CToken cZRX Comptroller) (Comptroller Address)" - `, - "Equal", - [ - new Arg("given", getCoreValue), - new Arg("expected", getCoreValue) - ], - (world, { given, expected }) => assertEqual(world, given, expected) - ), - - new View<{ given: Value, expected: Value }>(` - #### LessThan - - * "given: LessThan expected:" - Asserts that given is less than expected. - * E.g. "Assert (Exactly 0) LessThan (Exactly 1)" - `, - "LessThan", - [ - new Arg("given", getCoreValue), - new Arg("expected", getCoreValue) - ], - (world, { given, expected }) => assertLessThan(world, given, expected), - { namePos: 1 } - ), - - new View<{ given: Value, expected: Value }>(` - #### GreaterThan - - * "given: GreaterThan expected:" - Asserts that given is greater than the expected. - * E.g. "Assert (Exactly 0) GreaterThan (Exactly 1)" - `, - "GreaterThan", - [ - new Arg("given", getCoreValue), - new Arg("expected", getCoreValue) - ], - (world, { given, expected }) => assertGreaterThan(world, given, expected), - { namePos: 1 } - ), - - new View<{ given: Value }>(` - #### True - - * "True given:" - Asserts that given is true. - * E.g. "Assert True (Comptroller CheckMembership Geoff cETH)" - `, - "True", - [ - new Arg("given", getCoreValue) - ], - (world, { given }) => assertEqual(world, given, new BoolV(true)) - ), - - new View<{ given: Value }>(` - #### False - - * "False given:" - Asserts that given is false. - * E.g. "Assert False (Comptroller CheckMembership Geoff cETH)" - `, - "False", - [ - new Arg("given", getCoreValue) - ], - (world, { given }) => assertEqual(world, given, new BoolV(false)) - ), - new View<{ event: EventV, message: StringV }>(` - #### ReadRevert - - * "ReadRevert event: message:" - Asserts that reading the given value reverts with given message. - * E.g. "Assert ReadRevert (Comptroller CheckMembership Geoff cETH) \"revert\"" - `, - "ReadRevert", - [ - new Arg("event", getEventV), - new Arg("message", getStringV) - ], - (world, { event, message }) => assertReadError(world, event.val, message.val, true) - ), - - new View<{ event: EventV, message: StringV }>(` - #### ReadError - - * "ReadError event: message:" - Asserts that reading the given value throws given error - * E.g. "Assert ReadError (Comptroller Bad Address) \"cannot find comptroller\"" - `, - "ReadError", - [ - new Arg("event", getEventV), - new Arg("message", getStringV) - ], - (world, { event, message }) => assertReadError(world, event.val, message.val, false) - ), - - new View<{ error: StringV, info: StringV, detail: StringV }>(` - #### Failure - - * "Failure error: info: detail:" - Asserts that last transaction had a graceful failure with given error, info and detail. - * E.g. "Assert Failure UNAUTHORIZED SUPPORT_MARKET_OWNER_CHECK" - * E.g. "Assert Failure MATH_ERROR MINT_CALCULATE_BALANCE 5" - `, - "Failure", - [ - new Arg("error", getStringV), - new Arg("info", getStringV), - new Arg("detail", getStringV, { default: new StringV("0") }), - ], - (world, { error, info, detail }) => assertFailure(world, new Failure(error.val, info.val, detail.val)) - ), - - new View<{ error: StringV, message: StringV }>(` - #### RevertFailure - - * "RevertFailure error: message:" - Assert last transaction reverted with a message beginning with an error code - * E.g. "Assert RevertFailure UNAUTHORIZED \"set reserves failed\"" - `, - "RevertFailure", - [ - new Arg("error", getStringV), - new Arg("message", getStringV), - ], - (world, { error, message }) => assertRevertFailure(world, error.val, message.val) - ), - - new View<{ error: StringV, args: StringV[] }>(` - #### RevertCustomError - - * "RevertCustomError error: args:<[]Value>" - Assert last transaction reverted with a message beginning with an error code - * E.g. "Assert RevertFailure UNAUTHORIZED \"set reserves failed\"" - `, - "RevertCustomError", - [ - new Arg("error", getStringV), - new Arg("args", getCoreValue, {variadic: true, mapped: true, default: []}), - ], - (world, { error, args }) => assertRevertCustomError(world, error.val, rawValues(args)) - ), - - new View<{ message: StringV }>(` - #### Revert - - * "Revert message:" - Asserts that the last transaction reverted. - `, - "Revert", - [ - new Arg("message", getStringV, { default: new StringV("revert") }), - ], - (world, { message }) => assertRevert(world, message.val) - ), - - new View<{ message: StringV }>(` - #### Error - - * "Error message:" - Asserts that the last transaction had the given error. - `, - "Error", - [ - new Arg("message", getStringV), - ], - (world, { message }) => assertError(world, message.val) - ), - - new View<{ given: Value }>(` - #### Success - - * "Success" - Asserts that the last transaction completed successfully (that is, did not revert nor emit graceful failure). - `, - "Success", - [], - (world, { given }) => assertSuccess(world) - ), - - new View<{ name: StringV, params: MapV }>(` - #### Log - - * "Log name: (key: value:) ..." - Asserts that last transaction emitted log with given name and key-value pairs. - * E.g. "Assert Log Minted ("account" (User Geoff address)) ("amount" (Exactly 55))" - `, - "Log", - [ - new Arg("name", getStringV), - new Arg("params", getMapV, { variadic: true }), - ], - (world, { name, params }) => assertLog(world, name.val, params) - ) - ]; -} - -export async function processAssertionEvent(world: World, event: Event, from: string | null): Promise { - return await processCommandEvent("Assertion", assertionCommands(), world, event, from); -} diff --git a/scenario/src/Event/CTokenDelegateEvent.ts b/scenario/src/Event/CTokenDelegateEvent.ts deleted file mode 100644 index 30f6ec966..000000000 --- a/scenario/src/Event/CTokenDelegateEvent.ts +++ /dev/null @@ -1,86 +0,0 @@ -import { Event } from '../Event'; -import { addAction, describeUser, World } from '../World'; -import { decodeCall, getPastEvents } from '../Contract'; -import { CToken, CTokenScenario } from '../Contract/CToken'; -import { CErc20Delegate } from '../Contract/CErc20Delegate' -import { invoke, Sendable } from '../Invokation'; -import { - getAddressV, - getEventV, - getExpNumberV, - getNumberV, - getStringV, - getBoolV -} from '../CoreValue'; -import { - AddressV, - BoolV, - EventV, - NothingV, - NumberV, - StringV -} from '../Value'; -import { Arg, Command, View, processCommandEvent } from '../Command'; -import { getCTokenDelegateData } from '../ContractLookup'; -import { buildCTokenDelegate } from '../Builder/CTokenDelegateBuilder'; -import { verify } from '../Verify'; - -async function genCTokenDelegate(world: World, from: string, event: Event): Promise { - let { world: nextWorld, cTokenDelegate, delegateData } = await buildCTokenDelegate(world, from, event); - world = nextWorld; - - world = addAction( - world, - `Added cToken ${delegateData.name} (${delegateData.contract}) at address ${cTokenDelegate._address}`, - delegateData.invokation - ); - - return world; -} - -async function verifyCTokenDelegate(world: World, cTokenDelegate: CErc20Delegate, name: string, contract: string, apiKey: string): Promise { - if (world.isLocalNetwork()) { - world.printer.printLine(`Politely declining to verify on local network: ${world.network}.`); - } else { - await verify(world, apiKey, name, contract, cTokenDelegate._address); - } - - return world; -} - -export function cTokenDelegateCommands() { - return [ - new Command<{ cTokenDelegateParams: EventV }>(` - #### Deploy - - * "CTokenDelegate Deploy ...cTokenDelegateParams" - Generates a new CTokenDelegate - * E.g. "CTokenDelegate Deploy CDaiDelegate cDAIDelegate" - `, - "Deploy", - [new Arg("cTokenDelegateParams", getEventV, { variadic: true })], - (world, from, { cTokenDelegateParams }) => genCTokenDelegate(world, from, cTokenDelegateParams.val) - ), - new View<{ cTokenDelegateArg: StringV, apiKey: StringV }>(` - #### Verify - - * "CTokenDelegate Verify apiKey:" - Verifies CTokenDelegate in Etherscan - * E.g. "CTokenDelegate cDaiDelegate Verify "myApiKey" - `, - "Verify", - [ - new Arg("cTokenDelegateArg", getStringV), - new Arg("apiKey", getStringV) - ], - async (world, { cTokenDelegateArg, apiKey }) => { - let [cToken, name, data] = await getCTokenDelegateData(world, cTokenDelegateArg.val); - - return await verifyCTokenDelegate(world, cToken, name, data.get('contract')!, apiKey.val); - }, - { namePos: 1 } - ), - ]; -} - -export async function processCTokenDelegateEvent(world: World, event: Event, from: string | null): Promise { - return await processCommandEvent("CTokenDelegate", cTokenDelegateCommands(), world, event, from); -} diff --git a/scenario/src/Event/CTokenEvent.ts b/scenario/src/Event/CTokenEvent.ts deleted file mode 100644 index bb0df3ba3..000000000 --- a/scenario/src/Event/CTokenEvent.ts +++ /dev/null @@ -1,934 +0,0 @@ -import { Event } from '../Event'; -import { addAction, describeUser, World } from '../World'; -import { decodeCall, getPastEvents } from '../Contract'; -import { CToken, CTokenScenario } from '../Contract/CToken'; -import { CErc20Delegate } from '../Contract/CErc20Delegate' -import { CErc20Delegator } from '../Contract/CErc20Delegator' -import { invoke, Sendable } from '../Invokation'; -import { - getAddressV, - getEventV, - getExpNumberV, - getNumberV, - getStringV, - getBoolV -} from '../CoreValue'; -import { - AddressV, - BoolV, - EventV, - NothingV, - NumberV, - StringV -} from '../Value'; -import { getContract } from '../Contract'; -import { Arg, Command, View, processCommandEvent } from '../Command'; -import { CTokenErrorReporter } from '../ErrorReporter'; -import { getComptroller, getCTokenData } from '../ContractLookup'; -import { getExpMantissa } from '../Encoding'; -import { buildCToken } from '../Builder/CTokenBuilder'; -import { verify } from '../Verify'; -import { getLiquidity } from '../Value/ComptrollerValue'; -import { encodedNumber } from '../Encoding'; -import { getCTokenV, getCErc20DelegatorV } from '../Value/CTokenValue'; - -function showTrxValue(world: World): string { - return new NumberV(world.trxInvokationOpts.get('value')).show(); -} - -async function genCToken(world: World, from: string, event: Event): Promise { - let { world: nextWorld, cToken, tokenData } = await buildCToken(world, from, event); - world = nextWorld; - - world = addAction( - world, - `Added cToken ${tokenData.name} (${tokenData.contract}) at address ${cToken._address}`, - tokenData.invokation - ); - - return world; -} - -async function accrueInterest(world: World, from: string, cToken: CToken): Promise { - let invokation = await invoke(world, cToken.methods.accrueInterest(), from, CTokenErrorReporter); - - world = addAction( - world, - `CToken ${cToken.name}: Interest accrued`, - invokation - ); - - return world; -} - -async function mint(world: World, from: string, cToken: CToken, amount: NumberV | NothingV): Promise { - let invokation; - let showAmount; - - if (amount instanceof NumberV) { - showAmount = amount.show(); - invokation = await invoke(world, cToken.methods.mint(amount.encode()), from, CTokenErrorReporter); - } else { - showAmount = showTrxValue(world); - invokation = await invoke(world, cToken.methods.mint(), from, CTokenErrorReporter); - } - - world = addAction( - world, - `CToken ${cToken.name}: ${describeUser(world, from)} mints ${showAmount}`, - invokation - ); - - return world; -} - -async function redeem(world: World, from: string, cToken: CToken, tokens: NumberV): Promise { - let invokation = await invoke(world, cToken.methods.redeem(tokens.encode()), from, CTokenErrorReporter); - - world = addAction( - world, - `CToken ${cToken.name}: ${describeUser(world, from)} redeems ${tokens.show()} tokens`, - invokation - ); - - return world; -} - -async function redeemUnderlying(world: World, from: string, cToken: CToken, amount: NumberV): Promise { - let invokation = await invoke(world, cToken.methods.redeemUnderlying(amount.encode()), from, CTokenErrorReporter); - - world = addAction( - world, - `CToken ${cToken.name}: ${describeUser(world, from)} redeems ${amount.show()} underlying`, - invokation - ); - - return world; -} - -async function borrow(world: World, from: string, cToken: CToken, amount: NumberV): Promise { - let invokation = await invoke(world, cToken.methods.borrow(amount.encode()), from, CTokenErrorReporter); - - world = addAction( - world, - `CToken ${cToken.name}: ${describeUser(world, from)} borrows ${amount.show()}`, - invokation - ); - - return world; -} - -async function repayBorrow(world: World, from: string, cToken: CToken, amount: NumberV | NothingV): Promise { - let invokation; - let showAmount; - - if (amount instanceof NumberV) { - showAmount = amount.show(); - invokation = await invoke(world, cToken.methods.repayBorrow(amount.encode()), from, CTokenErrorReporter); - } else { - showAmount = showTrxValue(world); - invokation = await invoke(world, cToken.methods.repayBorrow(), from, CTokenErrorReporter); - } - - world = addAction( - world, - `CToken ${cToken.name}: ${describeUser(world, from)} repays ${showAmount} of borrow`, - invokation - ); - - return world; -} - -async function repayBorrowBehalf(world: World, from: string, behalf: string, cToken: CToken, amount: NumberV | NothingV): Promise { - let invokation; - let showAmount; - - if (amount instanceof NumberV) { - showAmount = amount.show(); - invokation = await invoke(world, cToken.methods.repayBorrowBehalf(behalf, amount.encode()), from, CTokenErrorReporter); - } else { - showAmount = showTrxValue(world); - invokation = await invoke(world, cToken.methods.repayBorrowBehalf(behalf), from, CTokenErrorReporter); - } - - world = addAction( - world, - `CToken ${cToken.name}: ${describeUser(world, from)} repays ${showAmount} of borrow on behalf of ${describeUser(world, behalf)}`, - invokation - ); - - return world; -} - -async function liquidateBorrow(world: World, from: string, cToken: CToken, borrower: string, collateral: CToken, repayAmount: NumberV | NothingV): Promise { - let invokation; - let showAmount; - - if (repayAmount instanceof NumberV) { - showAmount = repayAmount.show(); - invokation = await invoke(world, cToken.methods.liquidateBorrow(borrower, repayAmount.encode(), collateral._address), from, CTokenErrorReporter); - } else { - showAmount = showTrxValue(world); - invokation = await invoke(world, cToken.methods.liquidateBorrow(borrower, collateral._address), from, CTokenErrorReporter); - } - - world = addAction( - world, - `CToken ${cToken.name}: ${describeUser(world, from)} liquidates ${showAmount} from of ${describeUser(world, borrower)}, seizing ${collateral.name}.`, - invokation - ); - - return world; -} - -async function seize(world: World, from: string, cToken: CToken, liquidator: string, borrower: string, seizeTokens: NumberV): Promise { - let invokation = await invoke(world, cToken.methods.seize(liquidator, borrower, seizeTokens.encode()), from, CTokenErrorReporter); - - world = addAction( - world, - `CToken ${cToken.name}: ${describeUser(world, from)} initiates seizing ${seizeTokens.show()} to ${describeUser(world, liquidator)} from ${describeUser(world, borrower)}.`, - invokation - ); - - return world; -} - -async function evilSeize(world: World, from: string, cToken: CToken, treasure: CToken, liquidator: string, borrower: string, seizeTokens: NumberV): Promise { - let invokation = await invoke(world, cToken.methods.evilSeize(treasure._address, liquidator, borrower, seizeTokens.encode()), from, CTokenErrorReporter); - - world = addAction( - world, - `CToken ${cToken.name}: ${describeUser(world, from)} initiates illegal seizing ${seizeTokens.show()} to ${describeUser(world, liquidator)} from ${describeUser(world, borrower)}.`, - invokation - ); - - return world; -} - -async function setPendingAdmin(world: World, from: string, cToken: CToken, newPendingAdmin: string): Promise { - let invokation = await invoke(world, cToken.methods._setPendingAdmin(newPendingAdmin), from, CTokenErrorReporter); - - world = addAction( - world, - `CToken ${cToken.name}: ${describeUser(world, from)} sets pending admin to ${newPendingAdmin}`, - invokation - ); - - return world; -} - -async function acceptAdmin(world: World, from: string, cToken: CToken): Promise { - let invokation = await invoke(world, cToken.methods._acceptAdmin(), from, CTokenErrorReporter); - - world = addAction( - world, - `CToken ${cToken.name}: ${describeUser(world, from)} accepts admin`, - invokation - ); - - return world; -} - -async function addReserves(world: World, from: string, cToken: CToken, amount: NumberV): Promise { - let invokation = await invoke(world, cToken.methods._addReserves(amount.encode()), from, CTokenErrorReporter); - - world = addAction( - world, - `CToken ${cToken.name}: ${describeUser(world, from)} adds to reserves by ${amount.show()}`, - invokation - ); - - return world; -} - -async function reduceReserves(world: World, from: string, cToken: CToken, amount: NumberV): Promise { - let invokation = await invoke(world, cToken.methods._reduceReserves(amount.encode()), from, CTokenErrorReporter); - - world = addAction( - world, - `CToken ${cToken.name}: ${describeUser(world, from)} reduces reserves by ${amount.show()}`, - invokation - ); - - return world; -} - -async function setReserveFactor(world: World, from: string, cToken: CToken, reserveFactor: NumberV): Promise { - let invokation = await invoke(world, cToken.methods._setReserveFactor(reserveFactor.encode()), from, CTokenErrorReporter); - - world = addAction( - world, - `CToken ${cToken.name}: ${describeUser(world, from)} sets reserve factor to ${reserveFactor.show()}`, - invokation - ); - - return world; -} - -async function setInterestRateModel(world: World, from: string, cToken: CToken, interestRateModel: string): Promise { - let invokation = await invoke(world, cToken.methods._setInterestRateModel(interestRateModel), from, CTokenErrorReporter); - - world = addAction( - world, - `Set interest rate for ${cToken.name} to ${interestRateModel} as ${describeUser(world, from)}`, - invokation - ); - - return world; -} - -async function setComptroller(world: World, from: string, cToken: CToken, comptroller: string): Promise { - let invokation = await invoke(world, cToken.methods._setComptroller(comptroller), from, CTokenErrorReporter); - - world = addAction( - world, - `Set comptroller for ${cToken.name} to ${comptroller} as ${describeUser(world, from)}`, - invokation - ); - - return world; -} - -async function sweepToken(world: World, from: string, cToken: CToken, token: string): Promise { - let invokation = await invoke(world, cToken.methods.sweepToken(token), from, CTokenErrorReporter); - - world = addAction( - world, - `Swept ERC-20 at ${token} to admin`, - invokation - ); - - return world; -} - -async function becomeImplementation( - world: World, - from: string, - cToken: CToken, - becomeImplementationData: string -): Promise { - - const cErc20Delegate = getContract('CErc20Delegate'); - const cErc20DelegateContract = await cErc20Delegate.at(world, cToken._address); - - let invokation = await invoke( - world, - cErc20DelegateContract.methods._becomeImplementation(becomeImplementationData), - from, - CTokenErrorReporter - ); - - world = addAction( - world, - `CToken ${cToken.name}: ${describeUser( - world, - from - )} initiates _becomeImplementation with data:${becomeImplementationData}.`, - invokation - ); - - return world; -} - -async function resignImplementation( - world: World, - from: string, - cToken: CToken, -): Promise { - - const cErc20Delegate = getContract('CErc20Delegate'); - const cErc20DelegateContract = await cErc20Delegate.at(world, cToken._address); - - let invokation = await invoke( - world, - cErc20DelegateContract.methods._resignImplementation(), - from, - CTokenErrorReporter - ); - - world = addAction( - world, - `CToken ${cToken.name}: ${describeUser( - world, - from - )} initiates _resignImplementation.`, - invokation - ); - - return world; -} - -async function setImplementation( - world: World, - from: string, - cToken: CErc20Delegator, - implementation: string, - allowResign: boolean, - becomeImplementationData: string -): Promise { - let invokation = await invoke( - world, - cToken.methods._setImplementation( - implementation, - allowResign, - becomeImplementationData - ), - from, - CTokenErrorReporter - ); - - world = addAction( - world, - `CToken ${cToken.name}: ${describeUser( - world, - from - )} initiates setImplementation with implementation:${implementation} allowResign:${allowResign} data:${becomeImplementationData}.`, - invokation - ); - - return world; -} - -async function donate(world: World, from: string, cToken: CToken): Promise { - let invokation = await invoke(world, cToken.methods.donate(), from, CTokenErrorReporter); - - world = addAction( - world, - `Donate for ${cToken.name} as ${describeUser(world, from)} with value ${showTrxValue(world)}`, - invokation - ); - - return world; -} - -async function setCTokenMock(world: World, from: string, cToken: CTokenScenario, mock: string, value: NumberV): Promise { - let mockMethod: (number) => Sendable; - - switch (mock.toLowerCase()) { - case "totalborrows": - mockMethod = cToken.methods.setTotalBorrows; - break; - case "totalreserves": - mockMethod = cToken.methods.setTotalReserves; - break; - default: - throw new Error(`Mock "${mock}" not defined for cToken`); - } - - let invokation = await invoke(world, mockMethod(value.encode()), from); - - world = addAction( - world, - `Mocked ${mock}=${value.show()} for ${cToken.name}`, - invokation - ); - - return world; -} - -async function verifyCToken(world: World, cToken: CToken, name: string, contract: string, apiKey: string): Promise { - if (world.isLocalNetwork()) { - world.printer.printLine(`Politely declining to verify on local network: ${world.network}.`); - } else { - await verify(world, apiKey, name, contract, cToken._address); - } - - return world; -} - -async function printMinters(world: World, cToken: CToken): Promise { - let events = await getPastEvents(world, cToken, cToken.name, 'Mint'); - let addresses = events.map((event) => event.returnValues['minter']); - let uniq = [...new Set(addresses)]; - - world.printer.printLine("Minters:") - - uniq.forEach((address) => { - world.printer.printLine(`\t${address}`) - }); - - return world; -} - -async function printBorrowers(world: World, cToken: CToken): Promise { - let events = await getPastEvents(world, cToken, cToken.name, 'Borrow'); - let addresses = events.map((event) => event.returnValues['borrower']); - let uniq = [...new Set(addresses)]; - - world.printer.printLine("Borrowers:") - - uniq.forEach((address) => { - world.printer.printLine(`\t${address}`) - }); - - return world; -} - -async function printLiquidity(world: World, cToken: CToken): Promise { - let mintEvents = await getPastEvents(world, cToken, cToken.name, 'Mint'); - let mintAddresses = mintEvents.map((event) => event.returnValues['minter']); - let borrowEvents = await getPastEvents(world, cToken, cToken.name, 'Borrow'); - let borrowAddresses = borrowEvents.map((event) => event.returnValues['borrower']); - let uniq = [...new Set(mintAddresses.concat(borrowAddresses))]; - let comptroller = await getComptroller(world); - - world.printer.printLine("Liquidity:") - - const liquidityMap = await Promise.all(uniq.map(async (address) => { - let userLiquidity = await getLiquidity(world, comptroller, address); - - return [address, userLiquidity.val]; - })); - - liquidityMap.forEach(([address, liquidity]) => { - world.printer.printLine(`\t${world.settings.lookupAlias(address)}: ${liquidity / 1e18}e18`) - }); - - return world; -} - -export function cTokenCommands() { - return [ - new Command<{ cTokenParams: EventV }>(` - #### Deploy - - * "CToken Deploy ...cTokenParams" - Generates a new CToken - * E.g. "CToken cZRX Deploy" - `, - "Deploy", - [new Arg("cTokenParams", getEventV, { variadic: true })], - (world, from, { cTokenParams }) => genCToken(world, from, cTokenParams.val) - ), - new View<{ cTokenArg: StringV, apiKey: StringV }>(` - #### Verify - - * "CToken Verify apiKey:" - Verifies CToken in Etherscan - * E.g. "CToken cZRX Verify "myApiKey" - `, - "Verify", - [ - new Arg("cTokenArg", getStringV), - new Arg("apiKey", getStringV) - ], - async (world, { cTokenArg, apiKey }) => { - let [cToken, name, data] = await getCTokenData(world, cTokenArg.val); - - return await verifyCToken(world, cToken, name, data.get('contract')!, apiKey.val); - }, - { namePos: 1 } - ), - new Command<{ cToken: CToken }>(` - #### AccrueInterest - - * "CToken AccrueInterest" - Accrues interest for given token - * E.g. "CToken cZRX AccrueInterest" - `, - "AccrueInterest", - [ - new Arg("cToken", getCTokenV) - ], - (world, from, { cToken }) => accrueInterest(world, from, cToken), - { namePos: 1 } - ), - new Command<{ cToken: CToken, amount: NumberV | NothingV }>(` - #### Mint - - * "CToken Mint amount:" - Mints the given amount of cToken as specified user - * E.g. "CToken cZRX Mint 1.0e18" - `, - "Mint", - [ - new Arg("cToken", getCTokenV), - new Arg("amount", getNumberV, { nullable: true }) - ], - (world, from, { cToken, amount }) => mint(world, from, cToken, amount), - { namePos: 1 } - ), - new Command<{ cToken: CToken, tokens: NumberV }>(` - #### Redeem - - * "CToken Redeem tokens:" - Redeems the given amount of cTokens as specified user - * E.g. "CToken cZRX Redeem 1.0e9" - `, - "Redeem", - [ - new Arg("cToken", getCTokenV), - new Arg("tokens", getNumberV) - ], - (world, from, { cToken, tokens }) => redeem(world, from, cToken, tokens), - { namePos: 1 } - ), - new Command<{ cToken: CToken, amount: NumberV }>(` - #### RedeemUnderlying - - * "CToken RedeemUnderlying amount:" - Redeems the given amount of underlying as specified user - * E.g. "CToken cZRX RedeemUnderlying 1.0e18" - `, - "RedeemUnderlying", - [ - new Arg("cToken", getCTokenV), - new Arg("amount", getNumberV) - ], - (world, from, { cToken, amount }) => redeemUnderlying(world, from, cToken, amount), - { namePos: 1 } - ), - new Command<{ cToken: CToken, amount: NumberV }>(` - #### Borrow - - * "CToken Borrow amount:" - Borrows the given amount of this cToken as specified user - * E.g. "CToken cZRX Borrow 1.0e18" - `, - "Borrow", - [ - new Arg("cToken", getCTokenV), - new Arg("amount", getNumberV) - ], - // Note: we override from - (world, from, { cToken, amount }) => borrow(world, from, cToken, amount), - { namePos: 1 } - ), - new Command<{ cToken: CToken, amount: NumberV | NothingV }>(` - #### RepayBorrow - - * "CToken RepayBorrow underlyingAmount:" - Repays borrow in the given underlying amount as specified user - * E.g. "CToken cZRX RepayBorrow 1.0e18" - `, - "RepayBorrow", - [ - new Arg("cToken", getCTokenV), - new Arg("amount", getNumberV, { nullable: true }) - ], - (world, from, { cToken, amount }) => repayBorrow(world, from, cToken, amount), - { namePos: 1 } - ), - new Command<{ cToken: CToken, behalf: AddressV, amount: NumberV | NothingV }>(` - #### RepayBorrowBehalf - - * "CToken RepayBorrowBehalf behalf: underlyingAmount:" - Repays borrow in the given underlying amount on behalf of another user - * E.g. "CToken cZRX RepayBorrowBehalf Geoff 1.0e18" - `, - "RepayBorrowBehalf", - [ - new Arg("cToken", getCTokenV), - new Arg("behalf", getAddressV), - new Arg("amount", getNumberV, { nullable: true }) - ], - (world, from, { cToken, behalf, amount }) => repayBorrowBehalf(world, from, behalf.val, cToken, amount), - { namePos: 1 } - ), - new Command<{ borrower: AddressV, cToken: CToken, collateral: CToken, repayAmount: NumberV | NothingV }>(` - #### Liquidate - - * "CToken Liquidate borrower: cTokenCollateral:
repayAmount:" - Liquidates repayAmount of given token seizing collateral token - * E.g. "CToken cZRX Liquidate Geoff cBAT 1.0e18" - `, - "Liquidate", - [ - new Arg("cToken", getCTokenV), - new Arg("borrower", getAddressV), - new Arg("collateral", getCTokenV), - new Arg("repayAmount", getNumberV, { nullable: true }) - ], - (world, from, { borrower, cToken, collateral, repayAmount }) => liquidateBorrow(world, from, cToken, borrower.val, collateral, repayAmount), - { namePos: 1 } - ), - new Command<{ cToken: CToken, liquidator: AddressV, borrower: AddressV, seizeTokens: NumberV }>(` - #### Seize - - * "CToken Seize liquidator: borrower: seizeTokens:" - Seizes a given number of tokens from a user (to be called from other CToken) - * E.g. "CToken cZRX Seize Geoff Torrey 1.0e18" - `, - "Seize", - [ - new Arg("cToken", getCTokenV), - new Arg("liquidator", getAddressV), - new Arg("borrower", getAddressV), - new Arg("seizeTokens", getNumberV) - ], - (world, from, { cToken, liquidator, borrower, seizeTokens }) => seize(world, from, cToken, liquidator.val, borrower.val, seizeTokens), - { namePos: 1 } - ), - new Command<{ cToken: CToken, treasure: CToken, liquidator: AddressV, borrower: AddressV, seizeTokens: NumberV }>(` - #### EvilSeize - - * "CToken EvilSeize treasure: liquidator: borrower: seizeTokens:" - Improperly seizes a given number of tokens from a user - * E.g. "CToken cEVL EvilSeize cZRX Geoff Torrey 1.0e18" - `, - "EvilSeize", - [ - new Arg("cToken", getCTokenV), - new Arg("treasure", getCTokenV), - new Arg("liquidator", getAddressV), - new Arg("borrower", getAddressV), - new Arg("seizeTokens", getNumberV) - ], - (world, from, { cToken, treasure, liquidator, borrower, seizeTokens }) => evilSeize(world, from, cToken, treasure, liquidator.val, borrower.val, seizeTokens), - { namePos: 1 } - ), - new Command<{ cToken: CToken, amount: NumberV }>(` - #### ReduceReserves - - * "CToken ReduceReserves amount:" - Reduces the reserves of the cToken - * E.g. "CToken cZRX ReduceReserves 1.0e18" - `, - "ReduceReserves", - [ - new Arg("cToken", getCTokenV), - new Arg("amount", getNumberV) - ], - (world, from, { cToken, amount }) => reduceReserves(world, from, cToken, amount), - { namePos: 1 } - ), - new Command<{ cToken: CToken, amount: NumberV }>(` - #### AddReserves - - * "CToken AddReserves amount:" - Adds reserves to the cToken - * E.g. "CToken cZRX AddReserves 1.0e18" - `, - "AddReserves", - [ - new Arg("cToken", getCTokenV), - new Arg("amount", getNumberV) - ], - (world, from, { cToken, amount }) => addReserves(world, from, cToken, amount), - { namePos: 1 } - ), - new Command<{ cToken: CToken, newPendingAdmin: AddressV }>(` - #### SetPendingAdmin - - * "CToken SetPendingAdmin newPendingAdmin:
" - Sets the pending admin for the cToken - * E.g. "CToken cZRX SetPendingAdmin Geoff" - `, - "SetPendingAdmin", - [ - new Arg("cToken", getCTokenV), - new Arg("newPendingAdmin", getAddressV) - ], - (world, from, { cToken, newPendingAdmin }) => setPendingAdmin(world, from, cToken, newPendingAdmin.val), - { namePos: 1 } - ), - new Command<{ cToken: CToken }>(` - #### AcceptAdmin - - * "CToken AcceptAdmin" - Accepts admin for the cToken - * E.g. "From Geoff (CToken cZRX AcceptAdmin)" - `, - "AcceptAdmin", - [ - new Arg("cToken", getCTokenV) - ], - (world, from, { cToken }) => acceptAdmin(world, from, cToken), - { namePos: 1 } - ), - new Command<{ cToken: CToken, reserveFactor: NumberV }>(` - #### SetReserveFactor - - * "CToken SetReserveFactor reserveFactor:" - Sets the reserve factor for the cToken - * E.g. "CToken cZRX SetReserveFactor 0.1" - `, - "SetReserveFactor", - [ - new Arg("cToken", getCTokenV), - new Arg("reserveFactor", getExpNumberV) - ], - (world, from, { cToken, reserveFactor }) => setReserveFactor(world, from, cToken, reserveFactor), - { namePos: 1 } - ), - new Command<{ cToken: CToken, interestRateModel: AddressV }>(` - #### SetInterestRateModel - - * "CToken SetInterestRateModel interestRateModel:" - Sets the interest rate model for the given cToken - * E.g. "CToken cZRX SetInterestRateModel (FixedRate 1.5)" - `, - "SetInterestRateModel", - [ - new Arg("cToken", getCTokenV), - new Arg("interestRateModel", getAddressV) - ], - (world, from, { cToken, interestRateModel }) => setInterestRateModel(world, from, cToken, interestRateModel.val), - { namePos: 1 } - ), - new Command<{ cToken: CToken, token: AddressV }>(` - #### SweepToken - - * "CToken SweepToken erc20Token:" - Sweeps the given erc-20 token from the contract - * E.g. "CToken cZRX SweepToken BAT" - `, - "SweepToken", - [ - new Arg("cToken", getCTokenV), - new Arg("token", getAddressV) - ], - (world, from, { cToken, token }) => sweepToken(world, from, cToken, token.val), - { namePos: 1 } - ), - new Command<{ cToken: CToken, comptroller: AddressV }>(` - #### SetComptroller - - * "CToken SetComptroller comptroller:" - Sets the comptroller for the given cToken - * E.g. "CToken cZRX SetComptroller Comptroller" - `, - "SetComptroller", - [ - new Arg("cToken", getCTokenV), - new Arg("comptroller", getAddressV) - ], - (world, from, { cToken, comptroller }) => setComptroller(world, from, cToken, comptroller.val), - { namePos: 1 } - ), - new Command<{ - cToken: CToken; - becomeImplementationData: StringV; - }>( - ` - #### BecomeImplementation - - * "CToken BecomeImplementation becomeImplementationData:" - * E.g. "CToken cDAI BecomeImplementation "0x01234anyByTeS56789"" - `, - 'BecomeImplementation', - [ - new Arg('cToken', getCTokenV), - new Arg('becomeImplementationData', getStringV) - ], - (world, from, { cToken, becomeImplementationData }) => - becomeImplementation( - world, - from, - cToken, - becomeImplementationData.val - ), - { namePos: 1 } - ), - new Command<{cToken: CToken;}>( - ` - #### ResignImplementation - - * "CToken ResignImplementation" - * E.g. "CToken cDAI ResignImplementation" - `, - 'ResignImplementation', - [new Arg('cToken', getCTokenV)], - (world, from, { cToken }) => - resignImplementation( - world, - from, - cToken - ), - { namePos: 1 } - ), - new Command<{ - cToken: CErc20Delegator; - implementation: AddressV; - allowResign: BoolV; - becomeImplementationData: StringV; - }>( - ` - #### SetImplementation - - * "CToken SetImplementation implementation:
allowResign: becomeImplementationData:" - * E.g. "CToken cDAI SetImplementation (CToken cDAIDelegate Address) True "0x01234anyByTeS56789" - `, - 'SetImplementation', - [ - new Arg('cToken', getCErc20DelegatorV), - new Arg('implementation', getAddressV), - new Arg('allowResign', getBoolV), - new Arg('becomeImplementationData', getStringV) - ], - (world, from, { cToken, implementation, allowResign, becomeImplementationData }) => - setImplementation( - world, - from, - cToken, - implementation.val, - allowResign.val, - becomeImplementationData.val - ), - { namePos: 1 } - ), - new Command<{ cToken: CToken }>(` - #### Donate - - * "CToken Donate" - Calls the donate (payable no-op) function - * E.g. "(Trx Value 5.0e18 (CToken cETH Donate))" - `, - "Donate", - [ - new Arg("cToken", getCTokenV) - ], - (world, from, { cToken }) => donate(world, from, cToken), - { namePos: 1 } - ), - new Command<{ cToken: CToken, variable: StringV, value: NumberV }>(` - #### Mock - - * "CToken Mock variable: value:" - Mocks a given value on cToken. Note: value must be a supported mock and this will only work on a "CTokenScenario" contract. - * E.g. "CToken cZRX Mock totalBorrows 5.0e18" - * E.g. "CToken cZRX Mock totalReserves 0.5e18" - `, - "Mock", - [ - new Arg("cToken", getCTokenV), - new Arg("variable", getStringV), - new Arg("value", getNumberV), - ], - (world, from, { cToken, variable, value }) => setCTokenMock(world, from, cToken, variable.val, value), - { namePos: 1 } - ), - new View<{ cToken: CToken }>(` - #### Minters - - * "CToken Minters" - Print address of all minters - `, - "Minters", - [ - new Arg("cToken", getCTokenV) - ], - (world, { cToken }) => printMinters(world, cToken), - { namePos: 1 } - ), - new View<{ cToken: CToken }>(` - #### Borrowers - - * "CToken Borrowers" - Print address of all borrowers - `, - "Borrowers", - [ - new Arg("cToken", getCTokenV) - ], - (world, { cToken }) => printBorrowers(world, cToken), - { namePos: 1 } - ), - new View<{ cToken: CToken }>(` - #### Liquidity - - * "CToken Liquidity" - Prints liquidity of all minters or borrowers - `, - "Liquidity", - [ - new Arg("cToken", getCTokenV) - ], - (world, { cToken }) => printLiquidity(world, cToken), - { namePos: 1 } - ), - new View<{ cToken: CToken, input: StringV }>(` - #### Decode - - * "Decode input:" - Prints information about a call to a cToken contract - `, - "Decode", - [ - new Arg("cToken", getCTokenV), - new Arg("input", getStringV) - - ], - (world, { cToken, input }) => decodeCall(world, cToken, input.val), - { namePos: 1 } - ) - ]; -} - -export async function processCTokenEvent(world: World, event: Event, from: string | null): Promise { - return await processCommandEvent("CToken", cTokenCommands(), world, event, from); -} diff --git a/scenario/src/Event/CompEvent.ts b/scenario/src/Event/CompEvent.ts deleted file mode 100644 index 1f420131f..000000000 --- a/scenario/src/Event/CompEvent.ts +++ /dev/null @@ -1,270 +0,0 @@ -import { Event } from '../Event'; -import { addAction, World, describeUser } from '../World'; -import { Comp, CompScenario } from '../Contract/Comp'; -import { buildComp } from '../Builder/CompBuilder'; -import { invoke } from '../Invokation'; -import { - getAddressV, - getEventV, - getNumberV, - getStringV, -} from '../CoreValue'; -import { - AddressV, - EventV, - NumberV, - StringV -} from '../Value'; -import { Arg, Command, processCommandEvent, View } from '../Command'; -import { getComp } from '../ContractLookup'; -import { NoErrorReporter } from '../ErrorReporter'; -import { verify } from '../Verify'; -import { encodedNumber } from '../Encoding'; - -async function genComp(world: World, from: string, params: Event): Promise { - let { world: nextWorld, comp, tokenData } = await buildComp(world, from, params); - world = nextWorld; - - world = addAction( - world, - `Deployed Comp (${comp.name}) to address ${comp._address}`, - tokenData.invokation - ); - - return world; -} - -async function verifyComp(world: World, comp: Comp, apiKey: string, modelName: string, contractName: string): Promise { - if (world.isLocalNetwork()) { - world.printer.printLine(`Politely declining to verify on local network: ${world.network}.`); - } else { - await verify(world, apiKey, modelName, contractName, comp._address); - } - - return world; -} - -async function approve(world: World, from: string, comp: Comp, address: string, amount: NumberV): Promise { - let invokation = await invoke(world, comp.methods.approve(address, amount.encode()), from, NoErrorReporter); - - world = addAction( - world, - `Approved Comp token for ${from} of ${amount.show()}`, - invokation - ); - - return world; -} - -async function transfer(world: World, from: string, comp: Comp, address: string, amount: NumberV): Promise { - let invokation = await invoke(world, comp.methods.transfer(address, amount.encode()), from, NoErrorReporter); - - world = addAction( - world, - `Transferred ${amount.show()} Comp tokens from ${from} to ${address}`, - invokation - ); - - return world; -} - -async function transferFrom(world: World, from: string, comp: Comp, owner: string, spender: string, amount: NumberV): Promise { - let invokation = await invoke(world, comp.methods.transferFrom(owner, spender, amount.encode()), from, NoErrorReporter); - - world = addAction( - world, - `"Transferred from" ${amount.show()} Comp tokens from ${owner} to ${spender}`, - invokation - ); - - return world; -} - -async function transferScenario(world: World, from: string, comp: CompScenario, addresses: string[], amount: NumberV): Promise { - let invokation = await invoke(world, comp.methods.transferScenario(addresses, amount.encode()), from, NoErrorReporter); - - world = addAction( - world, - `Transferred ${amount.show()} Comp tokens from ${from} to ${addresses}`, - invokation - ); - - return world; -} - -async function transferFromScenario(world: World, from: string, comp: CompScenario, addresses: string[], amount: NumberV): Promise { - let invokation = await invoke(world, comp.methods.transferFromScenario(addresses, amount.encode()), from, NoErrorReporter); - - world = addAction( - world, - `Transferred ${amount.show()} Comp tokens from ${addresses} to ${from}`, - invokation - ); - - return world; -} - -async function delegate(world: World, from: string, comp: Comp, account: string): Promise { - let invokation = await invoke(world, comp.methods.delegate(account), from, NoErrorReporter); - - world = addAction( - world, - `"Delegated from" ${from} to ${account}`, - invokation - ); - - return world; -} - -async function setBlockNumber( - world: World, - from: string, - comp: Comp, - blockNumber: NumberV -): Promise { - return addAction( - world, - `Set Comp blockNumber to ${blockNumber.show()}`, - await invoke(world, comp.methods.setBlockNumber(blockNumber.encode()), from) - ); -} - -export function compCommands() { - return [ - new Command<{ params: EventV }>(` - #### Deploy - - * "Deploy ...params" - Generates a new Comp token - * E.g. "Comp Deploy" - `, - "Deploy", - [ - new Arg("params", getEventV, { variadic: true }) - ], - (world, from, { params }) => genComp(world, from, params.val) - ), - - new View<{ comp: Comp, apiKey: StringV, contractName: StringV }>(` - #### Verify - - * " Verify apiKey: contractName:=Comp" - Verifies Comp token in Etherscan - * E.g. "Comp Verify "myApiKey" - `, - "Verify", - [ - new Arg("comp", getComp, { implicit: true }), - new Arg("apiKey", getStringV), - new Arg("contractName", getStringV, { default: new StringV("Comp") }) - ], - async (world, { comp, apiKey, contractName }) => { - return await verifyComp(world, comp, apiKey.val, comp.name, contractName.val) - } - ), - - new Command<{ comp: Comp, spender: AddressV, amount: NumberV }>(` - #### Approve - - * "Comp Approve spender:
" - Adds an allowance between user and address - * E.g. "Comp Approve Geoff 1.0e18" - `, - "Approve", - [ - new Arg("comp", getComp, { implicit: true }), - new Arg("spender", getAddressV), - new Arg("amount", getNumberV) - ], - (world, from, { comp, spender, amount }) => { - return approve(world, from, comp, spender.val, amount) - } - ), - - new Command<{ comp: Comp, recipient: AddressV, amount: NumberV }>(` - #### Transfer - - * "Comp Transfer recipient: " - Transfers a number of tokens via "transfer" as given user to recipient (this does not depend on allowance) - * E.g. "Comp Transfer Torrey 1.0e18" - `, - "Transfer", - [ - new Arg("comp", getComp, { implicit: true }), - new Arg("recipient", getAddressV), - new Arg("amount", getNumberV) - ], - (world, from, { comp, recipient, amount }) => transfer(world, from, comp, recipient.val, amount) - ), - - new Command<{ comp: Comp, owner: AddressV, spender: AddressV, amount: NumberV }>(` - #### TransferFrom - - * "Comp TransferFrom owner: spender: " - Transfers a number of tokens via "transfeFrom" to recipient (this depends on allowances) - * E.g. "Comp TransferFrom Geoff Torrey 1.0e18" - `, - "TransferFrom", - [ - new Arg("comp", getComp, { implicit: true }), - new Arg("owner", getAddressV), - new Arg("spender", getAddressV), - new Arg("amount", getNumberV) - ], - (world, from, { comp, owner, spender, amount }) => transferFrom(world, from, comp, owner.val, spender.val, amount) - ), - - new Command<{ comp: CompScenario, recipients: AddressV[], amount: NumberV }>(` - #### TransferScenario - - * "Comp TransferScenario recipients: " - Transfers a number of tokens via "transfer" to the given recipients (this does not depend on allowance) - * E.g. "Comp TransferScenario (Jared Torrey) 10" - `, - "TransferScenario", - [ - new Arg("comp", getComp, { implicit: true }), - new Arg("recipients", getAddressV, { mapped: true }), - new Arg("amount", getNumberV) - ], - (world, from, { comp, recipients, amount }) => transferScenario(world, from, comp, recipients.map(recipient => recipient.val), amount) - ), - - new Command<{ comp: CompScenario, froms: AddressV[], amount: NumberV }>(` - #### TransferFromScenario - - * "Comp TransferFromScenario froms: " - Transfers a number of tokens via "transferFrom" from the given users to msg.sender (this depends on allowance) - * E.g. "Comp TransferFromScenario (Jared Torrey) 10" - `, - "TransferFromScenario", - [ - new Arg("comp", getComp, { implicit: true }), - new Arg("froms", getAddressV, { mapped: true }), - new Arg("amount", getNumberV) - ], - (world, from, { comp, froms, amount }) => transferFromScenario(world, from, comp, froms.map(_from => _from.val), amount) - ), - - new Command<{ comp: Comp, account: AddressV }>(` - #### Delegate - - * "Comp Delegate account:
" - Delegates votes to a given account - * E.g. "Comp Delegate Torrey" - `, - "Delegate", - [ - new Arg("comp", getComp, { implicit: true }), - new Arg("account", getAddressV), - ], - (world, from, { comp, account }) => delegate(world, from, comp, account.val) - ), - new Command<{ comp: Comp, blockNumber: NumberV }>(` - #### SetBlockNumber - - * "SetBlockNumber " - Sets the blockTimestamp of the Comp Harness - * E.g. "Comp SetBlockNumber 500" - `, - 'SetBlockNumber', - [new Arg('comp', getComp, { implicit: true }), new Arg('blockNumber', getNumberV)], - (world, from, { comp, blockNumber }) => setBlockNumber(world, from, comp, blockNumber) - ) - ]; -} - -export async function processCompEvent(world: World, event: Event, from: string | null): Promise { - return await processCommandEvent("Comp", compCommands(), world, event, from); -} diff --git a/scenario/src/Event/ComptrollerEvent.ts b/scenario/src/Event/ComptrollerEvent.ts deleted file mode 100644 index 88b3ee497..000000000 --- a/scenario/src/Event/ComptrollerEvent.ts +++ /dev/null @@ -1,926 +0,0 @@ -import {Event} from '../Event'; -import {addAction, describeUser, World} from '../World'; -import {decodeCall, getPastEvents} from '../Contract'; -import {Comptroller} from '../Contract/Comptroller'; -import {ComptrollerImpl} from '../Contract/ComptrollerImpl'; -import {CToken} from '../Contract/CToken'; -import {invoke} from '../Invokation'; -import { - getAddressV, - getBoolV, - getEventV, - getExpNumberV, - getNumberV, - getPercentV, - getStringV, - getCoreValue -} from '../CoreValue'; -import { - AddressV, - BoolV, - EventV, - NumberV, - StringV -} from '../Value'; -import {Arg, Command, View, processCommandEvent} from '../Command'; -import {buildComptrollerImpl} from '../Builder/ComptrollerImplBuilder'; -import {ComptrollerErrorReporter} from '../ErrorReporter'; -import {getComptroller, getComptrollerImpl} from '../ContractLookup'; -import {getLiquidity} from '../Value/ComptrollerValue'; -import {getCTokenV} from '../Value/CTokenValue'; -import {encodedNumber} from '../Encoding'; -import {encodeABI, rawValues} from "../Utils"; - -async function genComptroller(world: World, from: string, params: Event): Promise { - let {world: nextWorld, comptrollerImpl: comptroller, comptrollerImplData: comptrollerData} = await buildComptrollerImpl(world, from, params); - world = nextWorld; - - world = addAction( - world, - `Added Comptroller (${comptrollerData.description}) at address ${comptroller._address}`, - comptrollerData.invokation - ); - - return world; -}; - -async function setPaused(world: World, from: string, comptroller: Comptroller, actionName: string, isPaused: boolean): Promise { - const pauseMap = { - "Mint": comptroller.methods._setMintPaused - }; - - if (!pauseMap[actionName]) { - throw `Cannot find pause function for action "${actionName}"`; - } - - let invokation = await invoke(world, comptroller[actionName]([isPaused]), from, ComptrollerErrorReporter); - - world = addAction( - world, - `Comptroller: set paused for ${actionName} to ${isPaused}`, - invokation - ); - - return world; -} - -async function setMaxAssets(world: World, from: string, comptroller: Comptroller, numberOfAssets: NumberV): Promise { - let invokation = await invoke(world, comptroller.methods._setMaxAssets(numberOfAssets.encode()), from, ComptrollerErrorReporter); - - world = addAction( - world, - `Set max assets to ${numberOfAssets.show()}`, - invokation - ); - - return world; -} - -async function setLiquidationIncentive(world: World, from: string, comptroller: Comptroller, liquidationIncentive: NumberV): Promise { - let invokation = await invoke(world, comptroller.methods._setLiquidationIncentive(liquidationIncentive.encode()), from, ComptrollerErrorReporter); - - world = addAction( - world, - `Set liquidation incentive to ${liquidationIncentive.show()}`, - invokation - ); - - return world; -} - -async function supportMarket(world: World, from: string, comptroller: Comptroller, cToken: CToken): Promise { - if (world.dryRun) { - // Skip this specifically on dry runs since it's likely to crash due to a number of reasons - world.printer.printLine(`Dry run: Supporting market \`${cToken._address}\``); - return world; - } - - let invokation = await invoke(world, comptroller.methods._supportMarket(cToken._address), from, ComptrollerErrorReporter); - - world = addAction( - world, - `Supported market ${cToken.name}`, - invokation - ); - - return world; -} - -async function unlistMarket(world: World, from: string, comptroller: Comptroller, cToken: CToken): Promise { - let invokation = await invoke(world, comptroller.methods.unlist(cToken._address), from, ComptrollerErrorReporter); - - world = addAction( - world, - `Unlisted market ${cToken.name}`, - invokation - ); - - return world; -} - -async function enterMarkets(world: World, from: string, comptroller: Comptroller, assets: string[]): Promise { - let invokation = await invoke(world, comptroller.methods.enterMarkets(assets), from, ComptrollerErrorReporter); - - world = addAction( - world, - `Called enter assets ${assets} as ${describeUser(world, from)}`, - invokation - ); - - return world; -} - -async function exitMarket(world: World, from: string, comptroller: Comptroller, asset: string): Promise { - let invokation = await invoke(world, comptroller.methods.exitMarket(asset), from, ComptrollerErrorReporter); - - world = addAction( - world, - `Called exit market ${asset} as ${describeUser(world, from)}`, - invokation - ); - - return world; -} - -async function setPriceOracle(world: World, from: string, comptroller: Comptroller, priceOracleAddr: string): Promise { - let invokation = await invoke(world, comptroller.methods._setPriceOracle(priceOracleAddr), from, ComptrollerErrorReporter); - - world = addAction( - world, - `Set price oracle for to ${priceOracleAddr} as ${describeUser(world, from)}`, - invokation - ); - - return world; -} - -async function setCollateralFactor(world: World, from: string, comptroller: Comptroller, cToken: CToken, collateralFactor: NumberV): Promise { - let invokation = await invoke(world, comptroller.methods._setCollateralFactor(cToken._address, collateralFactor.encode()), from, ComptrollerErrorReporter); - - world = addAction( - world, - `Set collateral factor for ${cToken.name} to ${collateralFactor.show()}`, - invokation - ); - - return world; -} - -async function setCloseFactor(world: World, from: string, comptroller: Comptroller, closeFactor: NumberV): Promise { - let invokation = await invoke(world, comptroller.methods._setCloseFactor(closeFactor.encode()), from, ComptrollerErrorReporter); - - world = addAction( - world, - `Set close factor to ${closeFactor.show()}`, - invokation - ); - - return world; -} - -async function fastForward(world: World, from: string, comptroller: Comptroller, blocks: NumberV): Promise { - let invokation = await invoke(world, comptroller.methods.fastForward(blocks.encode()), from, ComptrollerErrorReporter); - - world = addAction( - world, - `Fast forward ${blocks.show()} blocks to #${invokation.value}`, - invokation - ); - - return world; -} - -async function sendAny(world: World, from:string, comptroller: Comptroller, signature: string, callArgs: string[]): Promise { - const fnData = encodeABI(world, signature, callArgs); - await world.web3.eth.sendTransaction({ - to: comptroller._address, - data: fnData, - from: from - }) - return world; -} - -async function addCompMarkets(world: World, from: string, comptroller: Comptroller, cTokens: CToken[]): Promise { - let invokation = await invoke(world, comptroller.methods._addCompMarkets(cTokens.map(c => c._address)), from, ComptrollerErrorReporter); - - world = addAction( - world, - `Added COMP markets ${cTokens.map(c => c.name)}`, - invokation - ); - - return world; -} - -async function dropCompMarket(world: World, from: string, comptroller: Comptroller, cToken: CToken): Promise { - let invokation = await invoke(world, comptroller.methods._dropCompMarket(cToken._address), from, ComptrollerErrorReporter); - - world = addAction( - world, - `Drop COMP market ${cToken.name}`, - invokation - ); - - return world; -} - -async function refreshCompSpeeds(world: World, from: string, comptroller: Comptroller): Promise { - let invokation = await invoke(world, comptroller.methods.refreshCompSpeeds(), from, ComptrollerErrorReporter); - - world = addAction( - world, - `Refreshed COMP speeds`, - invokation - ); - - return world; -} - -async function claimComp(world: World, from: string, comptroller: Comptroller, holder: string): Promise { - let invokation = await invoke(world, comptroller.methods.claimComp(holder), from, ComptrollerErrorReporter); - - world = addAction( - world, - `Comp claimed by ${holder}`, - invokation - ); - - return world; -} - -async function claimCompInMarkets(world: World, from: string, comptroller: Comptroller, holder: string, cTokens: CToken[]): Promise { - let invokation = await invoke(world, comptroller.methods.claimComp(holder, cTokens.map(c => c._address)), from, ComptrollerErrorReporter); - - world = addAction( - world, - `Comp claimed by ${holder} in markets ${cTokens.map(c => c.name)}`, - invokation - ); - - return world; -} - -async function updateContributorRewards(world: World, from: string, comptroller: Comptroller, contributor: string): Promise { - let invokation = await invoke(world, comptroller.methods.updateContributorRewards(contributor), from, ComptrollerErrorReporter); - - world = addAction( - world, - `Contributor rewards updated for ${contributor}`, - invokation - ); - - return world; -} - -async function grantComp(world: World, from: string, comptroller: Comptroller, recipient: string, amount: NumberV): Promise { - let invokation = await invoke(world, comptroller.methods._grantComp(recipient, amount.encode()), from, ComptrollerErrorReporter); - - world = addAction( - world, - `${amount.show()} comp granted to ${recipient}`, - invokation - ); - - return world; -} - -async function setCompRate(world: World, from: string, comptroller: Comptroller, rate: NumberV): Promise { - let invokation = await invoke(world, comptroller.methods._setCompRate(rate.encode()), from, ComptrollerErrorReporter); - - world = addAction( - world, - `Comp rate set to ${rate.show()}`, - invokation - ); - - return world; -} - -async function setCompSpeed(world: World, from: string, comptroller: Comptroller, cToken: CToken, speed: NumberV): Promise { - let invokation = await invoke(world, comptroller.methods._setCompSpeed(cToken._address, speed.encode()), from, ComptrollerErrorReporter); - - world = addAction( - world, - `Comp speed for market ${cToken._address} set to ${speed.show()}`, - invokation - ); - - return world; -} - -async function setCompSpeeds(world: World, from: string, comptroller: Comptroller, cTokens: CToken[], supplySpeeds: NumberV[], borrowSpeeds: NumberV[]): Promise { - let invokation = await invoke(world, comptroller.methods._setCompSpeeds(cTokens.map(c => c._address), supplySpeeds.map(speed => speed.encode()), borrowSpeeds.map(speed => speed.encode())), from, ComptrollerErrorReporter); - - world = addAction( - world, - `Comp speed for markets [${cTokens.map(c => c._address)}] set to supplySpeeds=[${supplySpeeds.map(speed => speed.show())}, borrowSpeeds=[${borrowSpeeds.map(speed => speed.show())}]`, - invokation - ); - - return world; -} - -async function setContributorCompSpeed(world: World, from: string, comptroller: Comptroller, contributor: string, speed: NumberV): Promise { - let invokation = await invoke(world, comptroller.methods._setContributorCompSpeed(contributor, speed.encode()), from, ComptrollerErrorReporter); - - world = addAction( - world, - `Comp speed for contributor ${contributor} set to ${speed.show()}`, - invokation - ); - - return world; -} - -async function printLiquidity(world: World, comptroller: Comptroller): Promise { - let enterEvents = await getPastEvents(world, comptroller, 'StdComptroller', 'MarketEntered'); - let addresses = enterEvents.map((event) => event.returnValues['account']); - let uniq = [...new Set(addresses)]; - - world.printer.printLine("Liquidity:") - - const liquidityMap = await Promise.all(uniq.map(async (address) => { - let userLiquidity = await getLiquidity(world, comptroller, address); - - return [address, userLiquidity.val]; - })); - - liquidityMap.forEach(([address, liquidity]) => { - world.printer.printLine(`\t${world.settings.lookupAlias(address)}: ${liquidity / 1e18}e18`) - }); - - return world; -} - -async function setPendingAdmin(world: World, from: string, comptroller: Comptroller, newPendingAdmin: string): Promise { - let invokation = await invoke(world, comptroller.methods._setPendingAdmin(newPendingAdmin), from, ComptrollerErrorReporter); - - world = addAction( - world, - `Comptroller: ${describeUser(world, from)} sets pending admin to ${newPendingAdmin}`, - invokation - ); - - return world; -} - -async function acceptAdmin(world: World, from: string, comptroller: Comptroller): Promise { - let invokation = await invoke(world, comptroller.methods._acceptAdmin(), from, ComptrollerErrorReporter); - - world = addAction( - world, - `Comptroller: ${describeUser(world, from)} accepts admin`, - invokation - ); - - return world; -} - -async function setPauseGuardian(world: World, from: string, comptroller: Comptroller, newPauseGuardian: string): Promise { - let invokation = await invoke(world, comptroller.methods._setPauseGuardian(newPauseGuardian), from, ComptrollerErrorReporter); - - world = addAction( - world, - `Comptroller: ${describeUser(world, from)} sets pause guardian to ${newPauseGuardian}`, - invokation - ); - - return world; -} - -async function setGuardianPaused(world: World, from: string, comptroller: Comptroller, action: string, state: boolean): Promise { - let fun; - switch(action){ - case "Transfer": - fun = comptroller.methods._setTransferPaused - break; - case "Seize": - fun = comptroller.methods._setSeizePaused - break; - } - let invokation = await invoke(world, fun(state), from, ComptrollerErrorReporter); - - world = addAction( - world, - `Comptroller: ${describeUser(world, from)} sets ${action} paused`, - invokation - ); - - return world; -} - -async function setGuardianMarketPaused(world: World, from: string, comptroller: Comptroller, cToken: CToken, action: string, state: boolean): Promise { - let fun; - switch(action){ - case "Mint": - fun = comptroller.methods._setMintPaused - break; - case "Borrow": - fun = comptroller.methods._setBorrowPaused - break; - } - let invokation = await invoke(world, fun(cToken._address, state), from, ComptrollerErrorReporter); - - world = addAction( - world, - `Comptroller: ${describeUser(world, from)} sets ${action} paused`, - invokation - ); - - return world; -} - -async function setMarketBorrowCaps(world: World, from: string, comptroller: Comptroller, cTokens: CToken[], borrowCaps: NumberV[]): Promise { - let invokation = await invoke(world, comptroller.methods._setMarketBorrowCaps(cTokens.map(c => c._address), borrowCaps.map(c => c.encode())), from, ComptrollerErrorReporter); - - world = addAction( - world, - `Borrow caps on ${cTokens} set to ${borrowCaps}`, - invokation - ); - - return world; -} - -async function setBorrowCapGuardian(world: World, from: string, comptroller: Comptroller, newBorrowCapGuardian: string): Promise { - let invokation = await invoke(world, comptroller.methods._setBorrowCapGuardian(newBorrowCapGuardian), from, ComptrollerErrorReporter); - - world = addAction( - world, - `Comptroller: ${describeUser(world, from)} sets borrow cap guardian to ${newBorrowCapGuardian}`, - invokation - ); - - return world; -} - -async function setMarketSupplyCaps(world: World, from: string, comptroller: Comptroller, vTokens: VToken[], supplyCaps: NumberV[]): Promise { - let invokation = await invoke(world, comptroller.methods._setMarketSupplyCaps(vTokens.map(c => c._address), supplyCaps.map(c => c.encode())), from, ComptrollerErrorReporter); - - world = addAction( - world, - `Supply caps on ${vTokens} set to ${supplyCaps}`, - invokation - ); - - return world; -} - -export function comptrollerCommands() { - return [ - new Command<{comptrollerParams: EventV}>(` - #### Deploy - - * "Comptroller Deploy ...comptrollerParams" - Generates a new Comptroller (not as Impl) - * E.g. "Comptroller Deploy YesNo" - `, - "Deploy", - [new Arg("comptrollerParams", getEventV, {variadic: true})], - (world, from, {comptrollerParams}) => genComptroller(world, from, comptrollerParams.val) - ), - new Command<{comptroller: Comptroller, action: StringV, isPaused: BoolV}>(` - #### SetPaused - - * "Comptroller SetPaused " - Pauses or unpaused given cToken function - * E.g. "Comptroller SetPaused "Mint" True" - `, - "SetPaused", - [ - new Arg("comptroller", getComptroller, {implicit: true}), - new Arg("action", getStringV), - new Arg("isPaused", getBoolV) - ], - (world, from, {comptroller, action, isPaused}) => setPaused(world, from, comptroller, action.val, isPaused.val) - ), - new Command<{comptroller: Comptroller, cToken: CToken}>(` - #### SupportMarket - - * "Comptroller SupportMarket " - Adds support in the Comptroller for the given cToken - * E.g. "Comptroller SupportMarket cZRX" - `, - "SupportMarket", - [ - new Arg("comptroller", getComptroller, {implicit: true}), - new Arg("cToken", getCTokenV) - ], - (world, from, {comptroller, cToken}) => supportMarket(world, from, comptroller, cToken) - ), - new Command<{comptroller: Comptroller, cToken: CToken}>(` - #### UnList - - * "Comptroller UnList " - Mock unlists a given market in tests - * E.g. "Comptroller UnList cZRX" - `, - "UnList", - [ - new Arg("comptroller", getComptroller, {implicit: true}), - new Arg("cToken", getCTokenV) - ], - (world, from, {comptroller, cToken}) => unlistMarket(world, from, comptroller, cToken) - ), - new Command<{comptroller: Comptroller, cTokens: CToken[]}>(` - #### EnterMarkets - - * "Comptroller EnterMarkets ( ...)" - User enters the given markets - * E.g. "Comptroller EnterMarkets (cZRX cETH)" - `, - "EnterMarkets", - [ - new Arg("comptroller", getComptroller, {implicit: true}), - new Arg("cTokens", getCTokenV, {mapped: true}) - ], - (world, from, {comptroller, cTokens}) => enterMarkets(world, from, comptroller, cTokens.map((c) => c._address)) - ), - new Command<{comptroller: Comptroller, cToken: CToken}>(` - #### ExitMarket - - * "Comptroller ExitMarket " - User exits the given markets - * E.g. "Comptroller ExitMarket cZRX" - `, - "ExitMarket", - [ - new Arg("comptroller", getComptroller, {implicit: true}), - new Arg("cToken", getCTokenV) - ], - (world, from, {comptroller, cToken}) => exitMarket(world, from, comptroller, cToken._address) - ), - new Command<{comptroller: Comptroller, maxAssets: NumberV}>(` - #### SetMaxAssets - - * "Comptroller SetMaxAssets " - Sets (or resets) the max allowed asset count - * E.g. "Comptroller SetMaxAssets 4" - `, - "SetMaxAssets", - [ - new Arg("comptroller", getComptroller, {implicit: true}), - new Arg("maxAssets", getNumberV) - ], - (world, from, {comptroller, maxAssets}) => setMaxAssets(world, from, comptroller, maxAssets) - ), - new Command<{comptroller: Comptroller, liquidationIncentive: NumberV}>(` - #### LiquidationIncentive - - * "Comptroller LiquidationIncentive " - Sets the liquidation incentive - * E.g. "Comptroller LiquidationIncentive 1.1" - `, - "LiquidationIncentive", - [ - new Arg("comptroller", getComptroller, {implicit: true}), - new Arg("liquidationIncentive", getExpNumberV) - ], - (world, from, {comptroller, liquidationIncentive}) => setLiquidationIncentive(world, from, comptroller, liquidationIncentive) - ), - new Command<{comptroller: Comptroller, priceOracle: AddressV}>(` - #### SetPriceOracle - - * "Comptroller SetPriceOracle oracle:
" - Sets the price oracle address - * E.g. "Comptroller SetPriceOracle 0x..." - `, - "SetPriceOracle", - [ - new Arg("comptroller", getComptroller, {implicit: true}), - new Arg("priceOracle", getAddressV) - ], - (world, from, {comptroller, priceOracle}) => setPriceOracle(world, from, comptroller, priceOracle.val) - ), - new Command<{comptroller: Comptroller, cToken: CToken, collateralFactor: NumberV}>(` - #### SetCollateralFactor - - * "Comptroller SetCollateralFactor " - Sets the collateral factor for given cToken to number - * E.g. "Comptroller SetCollateralFactor cZRX 0.1" - `, - "SetCollateralFactor", - [ - new Arg("comptroller", getComptroller, {implicit: true}), - new Arg("cToken", getCTokenV), - new Arg("collateralFactor", getExpNumberV) - ], - (world, from, {comptroller, cToken, collateralFactor}) => setCollateralFactor(world, from, comptroller, cToken, collateralFactor) - ), - new Command<{comptroller: Comptroller, closeFactor: NumberV}>(` - #### SetCloseFactor - - * "Comptroller SetCloseFactor " - Sets the close factor to given percentage - * E.g. "Comptroller SetCloseFactor 0.2" - `, - "SetCloseFactor", - [ - new Arg("comptroller", getComptroller, {implicit: true}), - new Arg("closeFactor", getPercentV) - ], - (world, from, {comptroller, closeFactor}) => setCloseFactor(world, from, comptroller, closeFactor) - ), - new Command<{comptroller: Comptroller, newPendingAdmin: AddressV}>(` - #### SetPendingAdmin - - * "Comptroller SetPendingAdmin newPendingAdmin:
" - Sets the pending admin for the Comptroller - * E.g. "Comptroller SetPendingAdmin Geoff" - `, - "SetPendingAdmin", - [ - new Arg("comptroller", getComptroller, {implicit: true}), - new Arg("newPendingAdmin", getAddressV) - ], - (world, from, {comptroller, newPendingAdmin}) => setPendingAdmin(world, from, comptroller, newPendingAdmin.val) - ), - new Command<{comptroller: Comptroller}>(` - #### AcceptAdmin - - * "Comptroller AcceptAdmin" - Accepts admin for the Comptroller - * E.g. "From Geoff (Comptroller AcceptAdmin)" - `, - "AcceptAdmin", - [ - new Arg("comptroller", getComptroller, {implicit: true}), - ], - (world, from, {comptroller}) => acceptAdmin(world, from, comptroller) - ), - new Command<{comptroller: Comptroller, newPauseGuardian: AddressV}>(` - #### SetPauseGuardian - - * "Comptroller SetPauseGuardian newPauseGuardian:
" - Sets the PauseGuardian for the Comptroller - * E.g. "Comptroller SetPauseGuardian Geoff" - `, - "SetPauseGuardian", - [ - new Arg("comptroller", getComptroller, {implicit: true}), - new Arg("newPauseGuardian", getAddressV) - ], - (world, from, {comptroller, newPauseGuardian}) => setPauseGuardian(world, from, comptroller, newPauseGuardian.val) - ), - - new Command<{comptroller: Comptroller, action: StringV, isPaused: BoolV}>(` - #### SetGuardianPaused - - * "Comptroller SetGuardianPaused " - Pauses or unpaused given cToken function - * E.g. "Comptroller SetGuardianPaused "Transfer" True" - `, - "SetGuardianPaused", - [ - new Arg("comptroller", getComptroller, {implicit: true}), - new Arg("action", getStringV), - new Arg("isPaused", getBoolV) - ], - (world, from, {comptroller, action, isPaused}) => setGuardianPaused(world, from, comptroller, action.val, isPaused.val) - ), - - new Command<{comptroller: Comptroller, cToken: CToken, action: StringV, isPaused: BoolV}>(` - #### SetGuardianMarketPaused - - * "Comptroller SetGuardianMarketPaused " - Pauses or unpaused given cToken function - * E.g. "Comptroller SetGuardianMarketPaused cREP "Mint" True" - `, - "SetGuardianMarketPaused", - [ - new Arg("comptroller", getComptroller, {implicit: true}), - new Arg("cToken", getCTokenV), - new Arg("action", getStringV), - new Arg("isPaused", getBoolV) - ], - (world, from, {comptroller, cToken, action, isPaused}) => setGuardianMarketPaused(world, from, comptroller, cToken, action.val, isPaused.val) - ), - - new Command<{comptroller: Comptroller, blocks: NumberV, _keyword: StringV}>(` - #### FastForward - - * "FastForward n: Blocks" - Moves the block number forward "n" blocks. Note: in "CTokenScenario" and "ComptrollerScenario" the current block number is mocked (starting at 100000). This is the only way for the protocol to see a higher block number (for accruing interest). - * E.g. "Comptroller FastForward 5 Blocks" - Move block number forward 5 blocks. - `, - "FastForward", - [ - new Arg("comptroller", getComptroller, {implicit: true}), - new Arg("blocks", getNumberV), - new Arg("_keyword", getStringV) - ], - (world, from, {comptroller, blocks}) => fastForward(world, from, comptroller, blocks) - ), - new View<{comptroller: Comptroller}>(` - #### Liquidity - - * "Comptroller Liquidity" - Prints liquidity of all minters or borrowers - `, - "Liquidity", - [ - new Arg("comptroller", getComptroller, {implicit: true}), - ], - (world, {comptroller}) => printLiquidity(world, comptroller) - ), - new View<{comptroller: Comptroller, input: StringV}>(` - #### Decode - - * "Decode input:" - Prints information about a call to a Comptroller contract - `, - "Decode", - [ - new Arg("comptroller", getComptroller, {implicit: true}), - new Arg("input", getStringV) - - ], - (world, {comptroller, input}) => decodeCall(world, comptroller, input.val) - ), - - new Command<{comptroller: Comptroller, signature: StringV, callArgs: StringV[]}>(` - #### Send - * Comptroller Send functionSignature: callArgs[] - Sends any transaction to comptroller - * E.g: Comptroller Send "setCompAddress(address)" (Address COMP) - `, - "Send", - [ - new Arg("comptroller", getComptroller, {implicit: true}), - new Arg("signature", getStringV), - new Arg("callArgs", getCoreValue, {variadic: true, mapped: true}) - ], - (world, from, {comptroller, signature, callArgs}) => sendAny(world, from, comptroller, signature.val, rawValues(callArgs)) - ), - new Command<{comptroller: Comptroller, cTokens: CToken[]}>(` - #### AddCompMarkets - - * "Comptroller AddCompMarkets (
...)" - Makes a market COMP-enabled - * E.g. "Comptroller AddCompMarkets (cZRX cBAT) - `, - "AddCompMarkets", - [ - new Arg("comptroller", getComptroller, {implicit: true}), - new Arg("cTokens", getCTokenV, {mapped: true}) - ], - (world, from, {comptroller, cTokens}) => addCompMarkets(world, from, comptroller, cTokens) - ), - new Command<{comptroller: Comptroller, cToken: CToken}>(` - #### DropCompMarket - - * "Comptroller DropCompMarket
" - Makes a market COMP - * E.g. "Comptroller DropCompMarket cZRX - `, - "DropCompMarket", - [ - new Arg("comptroller", getComptroller, {implicit: true}), - new Arg("cToken", getCTokenV) - ], - (world, from, {comptroller, cToken}) => dropCompMarket(world, from, comptroller, cToken) - ), - - new Command<{comptroller: Comptroller}>(` - #### RefreshCompSpeeds - - * "Comptroller RefreshCompSpeeds" - Recalculates all the COMP market speeds - * E.g. "Comptroller RefreshCompSpeeds - `, - "RefreshCompSpeeds", - [ - new Arg("comptroller", getComptroller, {implicit: true}) - ], - (world, from, {comptroller}) => refreshCompSpeeds(world, from, comptroller) - ), - new Command<{comptroller: Comptroller, holder: AddressV}>(` - #### ClaimComp - - * "Comptroller ClaimComp " - Claims comp - * E.g. "Comptroller ClaimComp Geoff - `, - "ClaimComp", - [ - new Arg("comptroller", getComptroller, {implicit: true}), - new Arg("holder", getAddressV) - ], - (world, from, {comptroller, holder}) => claimComp(world, from, comptroller, holder.val) - ), - new Command<{comptroller: Comptroller, holder: AddressV, cTokens: CToken[]}>(` - #### ClaimCompInMarkets - - * "Comptroller ClaimComp ( ...)" - Claims comp - * E.g. "Comptroller ClaimCompInMarkets Geoff (cDAI cBAT) - `, - "ClaimCompInMarkets", - [ - new Arg("comptroller", getComptroller, {implicit: true}), - new Arg("holder", getAddressV), - new Arg("cTokens", getCTokenV, {mapped: true}) - ], - (world, from, {comptroller, holder, cTokens}) => claimCompInMarkets(world, from, comptroller, holder.val, cTokens) - ), - new Command<{comptroller: Comptroller, contributor: AddressV}>(` - #### UpdateContributorRewards - - * "Comptroller UpdateContributorRewards " - Updates rewards for a contributor - * E.g. "Comptroller UpdateContributorRewards Geoff - `, - "UpdateContributorRewards", - [ - new Arg("comptroller", getComptroller, {implicit: true}), - new Arg("contributor", getAddressV) - ], - (world, from, {comptroller, contributor}) => updateContributorRewards(world, from, comptroller, contributor.val) - ), - new Command<{comptroller: Comptroller, recipient: AddressV, amount: NumberV}>(` - #### GrantComp - - * "Comptroller GrantComp " - Grants COMP to a recipient - * E.g. "Comptroller GrantComp Geoff 1e18 - `, - "GrantComp", - [ - new Arg("comptroller", getComptroller, {implicit: true}), - new Arg("recipient", getAddressV), - new Arg("amount", getNumberV) - ], - (world, from, {comptroller, recipient, amount}) => grantComp(world, from, comptroller, recipient.val, amount) - ), - new Command<{comptroller: Comptroller, rate: NumberV}>(` - #### SetCompRate - - * "Comptroller SetCompRate " - Sets COMP rate - * E.g. "Comptroller SetCompRate 1e18 - `, - "SetCompRate", - [ - new Arg("comptroller", getComptroller, {implicit: true}), - new Arg("rate", getNumberV) - ], - (world, from, {comptroller, rate}) => setCompRate(world, from, comptroller, rate) - ), - new Command<{comptroller: Comptroller, cToken: CToken, speed: NumberV}>(` - #### SetCompSpeed (deprecated) - * "Comptroller SetCompSpeed " - Sets COMP speed for market - * E.g. "Comptroller SetCompSpeed cToken 1000 - `, - "SetCompSpeed", - [ - new Arg("comptroller", getComptroller, {implicit: true}), - new Arg("cToken", getCTokenV), - new Arg("speed", getNumberV) - ], - (world, from, {comptroller, cToken, speed}) => setCompSpeed(world, from, comptroller, cToken, speed) - ), - new Command<{comptroller: Comptroller, cTokens: CToken[], supplySpeeds: NumberV[], borrowSpeeds: NumberV[]}>(` - #### SetCompSpeeds - * "Comptroller SetCompSpeeds ( ...) ( ...) ( ...)" - Sets COMP speeds for markets - * E.g. "Comptroller SetCompSpeeds (cZRX cBAT) (1000 0) (1000 2000) - `, - "SetCompSpeeds", - [ - new Arg("comptroller", getComptroller, {implicit: true}), - new Arg("cTokens", getCTokenV, {mapped: true}), - new Arg("supplySpeeds", getNumberV, {mapped: true}), - new Arg("borrowSpeeds", getNumberV, {mapped: true}) - ], - (world, from, {comptroller, cTokens, supplySpeeds, borrowSpeeds}) => setCompSpeeds(world, from, comptroller, cTokens, supplySpeeds, borrowSpeeds) - ), - new Command<{comptroller: Comptroller, contributor: AddressV, speed: NumberV}>(` - #### SetContributorCompSpeed - * "Comptroller SetContributorCompSpeed " - Sets COMP speed for contributor - * E.g. "Comptroller SetContributorCompSpeed contributor 1000 - `, - "SetContributorCompSpeed", - [ - new Arg("comptroller", getComptroller, {implicit: true}), - new Arg("contributor", getAddressV), - new Arg("speed", getNumberV) - ], - (world, from, {comptroller, contributor, speed}) => setContributorCompSpeed(world, from, comptroller, contributor.val, speed) - ), - new Command<{comptroller: Comptroller, cTokens: CToken[], borrowCaps: NumberV[]}>(` - #### SetMarketBorrowCaps - - * "Comptroller SetMarketBorrowCaps ( ...) ( ...)" - Sets Market Borrow Caps - * E.g "Comptroller SetMarketBorrowCaps (cZRX cUSDC) (10000.0e18, 1000.0e6) - `, - "SetMarketBorrowCaps", - [ - new Arg("comptroller", getComptroller, {implicit: true}), - new Arg("cTokens", getCTokenV, {mapped: true}), - new Arg("borrowCaps", getNumberV, {mapped: true}) - ], - (world, from, {comptroller,cTokens,borrowCaps}) => setMarketBorrowCaps(world, from, comptroller, cTokens, borrowCaps) - ), - new Command<{comptroller: Comptroller, newBorrowCapGuardian: AddressV}>(` - #### SetBorrowCapGuardian - - * "Comptroller SetBorrowCapGuardian newBorrowCapGuardian:
" - Sets the Borrow Cap Guardian for the Comptroller - * E.g. "Comptroller SetBorrowCapGuardian Geoff" - `, - "SetBorrowCapGuardian", - [ - new Arg("comptroller", getComptroller, {implicit: true}), - new Arg("newBorrowCapGuardian", getAddressV) - ], - (world, from, {comptroller, newBorrowCapGuardian}) => setBorrowCapGuardian(world, from, comptroller, newBorrowCapGuardian.val) - ), - new Command<{ comptroller: Comptroller, cTokens: CToken[], supplyCaps: NumberV[] }>(` - #### SetMarketSupplyCaps - * "Comptroller SetMarketSupplyCaps ( ...) ( ...)" - Sets Market Supply Caps - * E.g "Comptroller SetMarketSupplyCaps (vZRX vUSDC) (10000.0e18, 1000.0e6) - `, - "SetMarketSupplyCaps", - [ - new Arg("comptroller", getComptroller, { implicit: true }), - new Arg("vTokens", getCTokenV, { mapped: true }), - new Arg("supplyCaps", getNumberV, { mapped: true }) - ], - (world, from, { comptroller, cTokens, supplyCaps }) => setMarketSupplyCaps(world, from, comptroller, cTokens, supplyCaps) - ) - ]; -} - -export async function processComptrollerEvent(world: World, event: Event, from: string | null): Promise { - return await processCommandEvent("Comptroller", comptrollerCommands(), world, event, from); -} diff --git a/scenario/src/Event/ComptrollerImplEvent.ts b/scenario/src/Event/ComptrollerImplEvent.ts deleted file mode 100644 index 9ca9c49a5..000000000 --- a/scenario/src/Event/ComptrollerImplEvent.ts +++ /dev/null @@ -1,493 +0,0 @@ -import { Event } from '../Event'; -import { addAction, describeUser, World } from '../World'; -import { ComptrollerImpl } from '../Contract/ComptrollerImpl'; -import { Unitroller } from '../Contract/Unitroller'; -import { invoke } from '../Invokation'; -import { getAddressV, getArrayV, getEventV, getExpNumberV, getNumberV, getStringV, getCoreValue } from '../CoreValue'; -import { ArrayV, AddressV, EventV, NumberV, StringV } from '../Value'; -import { Arg, Command, View, processCommandEvent } from '../Command'; -import { buildComptrollerImpl } from '../Builder/ComptrollerImplBuilder'; -import { ComptrollerErrorReporter } from '../ErrorReporter'; -import { getComptrollerImpl, getComptrollerImplData, getUnitroller } from '../ContractLookup'; -import { verify } from '../Verify'; -import { mergeContractABI } from '../Networks'; -import { encodedNumber } from '../Encoding'; -import { encodeABI } from '../Utils'; - -async function genComptrollerImpl(world: World, from: string, params: Event): Promise { - let { world: nextWorld, comptrollerImpl, comptrollerImplData } = await buildComptrollerImpl( - world, - from, - params - ); - world = nextWorld; - - world = addAction( - world, - `Added Comptroller Implementation (${comptrollerImplData.description}) at address ${comptrollerImpl._address}`, - comptrollerImplData.invokation - ); - - return world; -} - -async function mergeABI( - world: World, - from: string, - comptrollerImpl: ComptrollerImpl, - unitroller: Unitroller -): Promise { - if (!world.dryRun) { - // Skip this specifically on dry runs since it's likely to crash due to a number of reasons - world = await mergeContractABI(world, 'Comptroller', unitroller, unitroller.name, comptrollerImpl.name); - } - - return world; -} - -async function becomeG1( - world: World, - from: string, - comptrollerImpl: ComptrollerImpl, - unitroller: Unitroller, - priceOracleAddr: string, - closeFactor: encodedNumber, - maxAssets: encodedNumber -): Promise { - let invokation = await invoke( - world, - comptrollerImpl.methods._become(unitroller._address, priceOracleAddr, closeFactor, maxAssets, false), - from, - ComptrollerErrorReporter - ); - if (!world.dryRun) { - // Skip this specifically on dry runs since it's likely to crash due to a number of reasons - world = await mergeContractABI(world, 'Comptroller', unitroller, unitroller.name, comptrollerImpl.name); - } - - world = addAction( - world, - `Become ${unitroller._address}'s Comptroller Impl with priceOracle=${priceOracleAddr},closeFactor=${closeFactor},maxAssets=${maxAssets}`, - invokation - ); - - return world; -} - -// Recome calls `become` on the G1 Comptroller, but passes a flag to not modify any of the initialization variables. -async function recome( - world: World, - from: string, - comptrollerImpl: ComptrollerImpl, - unitroller: Unitroller -): Promise { - let invokation = await invoke( - world, - comptrollerImpl.methods._become( - unitroller._address, - '0x0000000000000000000000000000000000000000', - 0, - 0, - true - ), - from, - ComptrollerErrorReporter - ); - - world = await mergeContractABI(world, 'Comptroller', unitroller, unitroller.name, comptrollerImpl.name); - - world = addAction(world, `Recome ${unitroller._address}'s Comptroller Impl`, invokation); - - return world; -} - -async function becomeG2( - world: World, - from: string, - comptrollerImpl: ComptrollerImpl, - unitroller: Unitroller -): Promise { - let invokation = await invoke( - world, - comptrollerImpl.methods._become(unitroller._address), - from, - ComptrollerErrorReporter - ); - - if (!world.dryRun) { - // Skip this specifically on dry runs since it's likely to crash due to a number of reasons - world = await mergeContractABI(world, 'Comptroller', unitroller, unitroller.name, comptrollerImpl.name); - } - - world = addAction(world, `Become ${unitroller._address}'s Comptroller Impl`, invokation); - - return world; -} - -async function becomeG3( - world: World, - from: string, - comptrollerImpl: ComptrollerImpl, - unitroller: Unitroller, - compRate: encodedNumber, - compMarkets: string[], - otherMarkets: string[] -): Promise { - let invokation = await invoke( - world, - comptrollerImpl.methods._become(unitroller._address, compRate, compMarkets, otherMarkets), - from, - ComptrollerErrorReporter - ); - - if (!world.dryRun) { - // Skip this specifically on dry runs since it's likely to crash due to a number of reasons - world = await mergeContractABI(world, 'Comptroller', unitroller, unitroller.name, comptrollerImpl.name); - } - - world = addAction(world, `Become ${unitroller._address}'s Comptroller Impl`, invokation); - - return world; -} - -async function becomeG4( - world: World, - from: string, - comptrollerImpl: ComptrollerImpl, - unitroller: Unitroller -): Promise { - let invokation = await invoke( - world, - comptrollerImpl.methods._become(unitroller._address), - from, - ComptrollerErrorReporter - ); - - if (!world.dryRun) { - // Skip this specifically on dry runs since it's likely to crash due to a number of reasons - world = await mergeContractABI(world, 'Comptroller', unitroller, unitroller.name, comptrollerImpl.name); - } - - world = addAction(world, `Become ${unitroller._address}'s Comptroller Impl`, invokation); - - return world; -} - -async function becomeG5( - world: World, - from: string, - comptrollerImpl: ComptrollerImpl, - unitroller: Unitroller -): Promise { - let invokation = await invoke( - world, - comptrollerImpl.methods._become(unitroller._address), - from, - ComptrollerErrorReporter - ); - - if (!world.dryRun) { - // Skip this specifically on dry runs since it's likely to crash due to a number of reasons - world = await mergeContractABI(world, 'Comptroller', unitroller, unitroller.name, comptrollerImpl.name); - } - - world = addAction(world, `Become ${unitroller._address}'s Comptroller Impl`, invokation); - - return world; -} - -async function becomeG6( - world: World, - from: string, - comptrollerImpl: ComptrollerImpl, - unitroller: Unitroller -): Promise { - let invokation = await invoke( - world, - comptrollerImpl.methods._become(unitroller._address), - from, - ComptrollerErrorReporter - ); - - if (!world.dryRun) { - // Skip this specifically on dry runs since it's likely to crash due to a number of reasons - world = await mergeContractABI(world, 'Comptroller', unitroller, unitroller.name, comptrollerImpl.name); - } - - world = addAction(world, `Become ${unitroller._address}'s Comptroller Impl`, invokation); - - return world; -} - -async function become( - world: World, - from: string, - comptrollerImpl: ComptrollerImpl, - unitroller: Unitroller -): Promise { - let invokation = await invoke( - world, - comptrollerImpl.methods._become(unitroller._address), - from, - ComptrollerErrorReporter - ); - - if (!world.dryRun) { - // Skip this specifically on dry runs since it's likely to crash due to a number of reasons - world = await mergeContractABI(world, 'Comptroller', unitroller, unitroller.name, comptrollerImpl.name); - } - - world = addAction(world, `Become ${unitroller._address}'s Comptroller Impl`, invokation); - - return world; -} - -async function verifyComptrollerImpl( - world: World, - comptrollerImpl: ComptrollerImpl, - name: string, - contract: string, - apiKey: string -): Promise { - if (world.isLocalNetwork()) { - world.printer.printLine(`Politely declining to verify on local network: ${world.network}.`); - } else { - await verify(world, apiKey, name, contract, comptrollerImpl._address); - } - - return world; -} - -export function comptrollerImplCommands() { - return [ - new Command<{ comptrollerImplParams: EventV }>( - ` - #### Deploy - - * "ComptrollerImpl Deploy ...comptrollerImplParams" - Generates a new Comptroller Implementation - * E.g. "ComptrollerImpl Deploy MyScen Scenario" - `, - 'Deploy', - [new Arg('comptrollerImplParams', getEventV, { variadic: true })], - (world, from, { comptrollerImplParams }) => genComptrollerImpl(world, from, comptrollerImplParams.val) - ), - new View<{ comptrollerImplArg: StringV; apiKey: StringV }>( - ` - #### Verify - - * "ComptrollerImpl Verify apiKey:" - Verifies Comptroller Implemetation in Etherscan - * E.g. "ComptrollerImpl Verify "myApiKey" - `, - 'Verify', - [new Arg('comptrollerImplArg', getStringV), new Arg('apiKey', getStringV)], - async (world, { comptrollerImplArg, apiKey }) => { - let [comptrollerImpl, name, data] = await getComptrollerImplData(world, comptrollerImplArg.val); - - return await verifyComptrollerImpl(world, comptrollerImpl, name, data.get('contract')!, apiKey.val); - }, - { namePos: 1 } - ), - new Command<{ - unitroller: Unitroller; - comptrollerImpl: ComptrollerImpl; - priceOracle: AddressV; - closeFactor: NumberV; - maxAssets: NumberV; - }>( - ` - #### BecomeG1 - - * "ComptrollerImpl BecomeG1 priceOracle: closeFactor: maxAssets:" - Become the comptroller, if possible. - * E.g. "ComptrollerImpl MyImpl BecomeG1 - `, - 'BecomeG1', - [ - new Arg('unitroller', getUnitroller, { implicit: true }), - new Arg('comptrollerImpl', getComptrollerImpl), - new Arg('priceOracle', getAddressV), - new Arg('closeFactor', getExpNumberV), - new Arg('maxAssets', getNumberV) - ], - (world, from, { unitroller, comptrollerImpl, priceOracle, closeFactor, maxAssets }) => - becomeG1( - world, - from, - comptrollerImpl, - unitroller, - priceOracle.val, - closeFactor.encode(), - maxAssets.encode() - ), - { namePos: 1 } - ), - - new Command<{ - unitroller: Unitroller; - comptrollerImpl: ComptrollerImpl; - }>( - ` - #### BecomeG2 - - * "ComptrollerImpl BecomeG2" - Become the comptroller, if possible. - * E.g. "ComptrollerImpl MyImpl BecomeG2 - `, - 'BecomeG2', - [ - new Arg('unitroller', getUnitroller, { implicit: true }), - new Arg('comptrollerImpl', getComptrollerImpl) - ], - (world, from, { unitroller, comptrollerImpl }) => becomeG2(world, from, comptrollerImpl, unitroller), - { namePos: 1 } - ), - - new Command<{ - unitroller: Unitroller; - comptrollerImpl: ComptrollerImpl; - compRate: NumberV; - compMarkets: ArrayV; - otherMarkets: ArrayV; - }>( - ` - #### BecomeG3 - - * "ComptrollerImpl BecomeG3 " - Become the comptroller, if possible. - * E.g. "ComptrollerImpl MyImpl BecomeG3 0.1e18 [cDAI, cETH, cUSDC] - `, - 'BecomeG3', - [ - new Arg('unitroller', getUnitroller, { implicit: true }), - new Arg('comptrollerImpl', getComptrollerImpl), - new Arg('compRate', getNumberV, { default: new NumberV(1e18) }), - new Arg('compMarkets', getArrayV(getAddressV), {default: new ArrayV([]) }), - new Arg('otherMarkets', getArrayV(getAddressV), { default: new ArrayV([]) }) - ], - (world, from, { unitroller, comptrollerImpl, compRate, compMarkets, otherMarkets }) => { - return becomeG3(world, from, comptrollerImpl, unitroller, compRate.encode(), compMarkets.val.map(a => a.val), otherMarkets.val.map(a => a.val)) - }, - { namePos: 1 } - ), - - new Command<{ - unitroller: Unitroller; - comptrollerImpl: ComptrollerImpl; - }>( - ` - #### BecomeG4 - * "ComptrollerImpl BecomeG4" - Become the comptroller, if possible. - * E.g. "ComptrollerImpl MyImpl BecomeG4 - `, - 'BecomeG4', - [ - new Arg('unitroller', getUnitroller, { implicit: true }), - new Arg('comptrollerImpl', getComptrollerImpl) - ], - (world, from, { unitroller, comptrollerImpl }) => { - return becomeG4(world, from, comptrollerImpl, unitroller) - }, - { namePos: 1 } - ), - - new Command<{ - unitroller: Unitroller; - comptrollerImpl: ComptrollerImpl; - }>( - ` - #### BecomeG5 - * "ComptrollerImpl BecomeG5" - Become the comptroller, if possible. - * E.g. "ComptrollerImpl MyImpl BecomeG5 - `, - 'BecomeG5', - [ - new Arg('unitroller', getUnitroller, { implicit: true }), - new Arg('comptrollerImpl', getComptrollerImpl) - ], - (world, from, { unitroller, comptrollerImpl }) => { - return becomeG5(world, from, comptrollerImpl, unitroller) - }, - { namePos: 1 } - ), - - new Command<{ - unitroller: Unitroller; - comptrollerImpl: ComptrollerImpl; - }>( - ` - #### BecomeG6 - * "ComptrollerImpl BecomeG6" - Become the comptroller, if possible. - * E.g. "ComptrollerImpl MyImpl BecomeG6 - `, - 'BecomeG6', - [ - new Arg('unitroller', getUnitroller, { implicit: true }), - new Arg('comptrollerImpl', getComptrollerImpl) - ], - (world, from, { unitroller, comptrollerImpl }) => { - return becomeG6(world, from, comptrollerImpl, unitroller) - }, - { namePos: 1 } - ), - - new Command<{ - unitroller: Unitroller; - comptrollerImpl: ComptrollerImpl; - }>( - ` - #### Become - - * "ComptrollerImpl Become " - Become the comptroller, if possible. - * E.g. "ComptrollerImpl MyImpl Become 0.1e18 [cDAI, cETH, cUSDC] - `, - 'Become', - [ - new Arg('unitroller', getUnitroller, { implicit: true }), - new Arg('comptrollerImpl', getComptrollerImpl) - ], - (world, from, { unitroller, comptrollerImpl }) => { - return become(world, from, comptrollerImpl, unitroller) - }, - { namePos: 1 } - ), - - new Command<{ - unitroller: Unitroller; - comptrollerImpl: ComptrollerImpl; - }>( - ` - #### MergeABI - - * "ComptrollerImpl MergeABI" - Merges the ABI, as if it was a become. - * E.g. "ComptrollerImpl MyImpl MergeABI - `, - 'MergeABI', - [ - new Arg('unitroller', getUnitroller, { implicit: true }), - new Arg('comptrollerImpl', getComptrollerImpl) - ], - (world, from, { unitroller, comptrollerImpl }) => mergeABI(world, from, comptrollerImpl, unitroller), - { namePos: 1 } - ), - new Command<{ unitroller: Unitroller; comptrollerImpl: ComptrollerImpl }>( - ` - #### Recome - - * "ComptrollerImpl Recome" - Recome the comptroller - * E.g. "ComptrollerImpl MyImpl Recome - `, - 'Recome', - [ - new Arg('unitroller', getUnitroller, { implicit: true }), - new Arg('comptrollerImpl', getComptrollerImpl) - ], - (world, from, { unitroller, comptrollerImpl }) => recome(world, from, comptrollerImpl, unitroller), - { namePos: 1 } - ) - ]; -} - -export async function processComptrollerImplEvent( - world: World, - event: Event, - from: string | null -): Promise { - return await processCommandEvent('ComptrollerImpl', comptrollerImplCommands(), world, event, from); -} diff --git a/scenario/src/Event/Erc20Event.ts b/scenario/src/Event/Erc20Event.ts deleted file mode 100644 index c3ccb99d5..000000000 --- a/scenario/src/Event/Erc20Event.ts +++ /dev/null @@ -1,282 +0,0 @@ -import {Event} from '../Event'; -import {addAction, World} from '../World'; -import {Erc20} from '../Contract/Erc20'; -import {invoke} from '../Invokation'; -import {buildErc20} from '../Builder/Erc20Builder'; -import { - getAddressV, - getBoolV, - getEventV, - getNumberV, - getStringV -} from '../CoreValue'; -import { - AddressV, - BoolV, - EventV, - NumberV, - StringV} from '../Value'; -import {getErc20V} from '../Value/Erc20Value'; -import {verify} from '../Verify'; -import {Arg, Command, View, processCommandEvent} from '../Command'; -import {CTokenErrorReporter} from '../ErrorReporter'; -import {encodedNumber} from '../Encoding'; -import {getErc20Data} from '../ContractLookup'; - -async function genToken(world: World, from: string, params: Event): Promise { - let {world: newWorld, erc20, tokenData} = await buildErc20(world, from, params); - world = newWorld; - - world = addAction( - world, - `Added ERC-20 token ${tokenData.symbol} (${tokenData.description}) at address ${erc20._address}`, - tokenData.invokation - ); - - return world; -} - -async function verifyErc20(world: World, erc20: Erc20, name: string, contract: string, apiKey: string): Promise { - if (world.isLocalNetwork()) { - world.printer.printLine(`Politely declining to verify on local network: ${world.network}.`); - } else { - await verify(world, apiKey, name, contract, erc20._address); - } - - return world; -} - -async function approve(world: World, from: string, erc20: Erc20, address: string, amount: NumberV): Promise { - let invokation = await invoke(world, erc20.methods.approve(address, amount.encode()), from, CTokenErrorReporter); - - world = addAction( - world, - `Approved ${erc20.name} ERC-20 token for ${from} of ${amount.show()}`, - invokation - ); - - return world; -} - -async function faucet(world: World, from: string, erc20: Erc20, address: string, amount: NumberV): Promise { - let invokation = await invoke(world, erc20.methods.allocateTo(address, amount.encode()), from, CTokenErrorReporter); - - world = addAction( - world, - `Fauceted ${amount.show()} ERC-20 tokens to ${address}`, - invokation - ); - - return world; -} - -async function transfer(world: World, from: string, erc20: Erc20, address: string, amount: NumberV): Promise { - let invokation = await invoke(world, erc20.methods.transfer(address, amount.encode()), from, CTokenErrorReporter); - - world = addAction( - world, - `Transferred ${amount.show()} ERC-20 tokens from ${from} to ${address}`, - invokation - ); - - return world; -} - -async function transferFrom(world: World, from: string, erc20: Erc20, owner: string, spender: string, amount: NumberV): Promise { - let invokation = await invoke(world, erc20.methods.transferFrom(owner, spender, amount.encode()), from, CTokenErrorReporter); - - world = addAction( - world, - `"Transferred from" ${amount.show()} ERC-20 tokens from ${owner} to ${spender}`, - invokation - ); - - return world; -} - -async function setFail(world: World, from: string, erc20: Erc20, fail: boolean): Promise { - let invokation = await invoke(world, erc20.methods.setFail(fail), from, CTokenErrorReporter); - - world = addAction( - world, - `Set fail for ${erc20.name} to ${fail}`, - invokation - ); - - return world; -} - -async function setPaused(world: World, from: string, erc20: Erc20, pause: boolean): Promise { - let method = pause ? erc20.methods.pause() : erc20.methods.unpause(); - let invokation = await invoke(world, method, from); - - world = addAction( - world, - `Set ${erc20.name} ${pause ? 'paused' : 'unpaused'}`, - invokation - ); - - return world; -} - -async function setFee(world: World, from: string, erc20: Erc20, basisPointFee: NumberV, maxFee: NumberV): Promise { - let invokation = await invoke(world, erc20.methods.setParams(basisPointFee.encode(), maxFee.encode()), from); - - world = addAction( - world, - `Set fee on ${erc20.name} to ${basisPointFee} with a max of ${maxFee}`, - invokation - ); - - return world; -} - -export function erc20Commands() { - return [ - new Command<{erc20Params: EventV}>(` - #### Deploy - - * "Erc20 Deploy ...erc20Params" - Generates a new ERC-20 token by name - * E.g. "Erc20 Deploy ZRX ..." - `, - "Deploy", - [new Arg("erc20Params", getEventV, {variadic: true})], - (world, from, {erc20Params}) => genToken(world, from, erc20Params.val) - ), - - new View<{erc20Arg: StringV, apiKey: StringV}>(` - #### Verify - - * "Erc20 Verify apiKey:" - Verifies Erc20 in Etherscan - * E.g. "Erc20 ZRX Verify "myApiKey" - `, - "Verify", - [ - new Arg("erc20Arg", getStringV), - new Arg("apiKey", getStringV) - ], - async (world, {erc20Arg, apiKey}) => { - let [erc20, name, data] = await getErc20Data(world, erc20Arg.val); - - return await verifyErc20(world, erc20, name, data.get('contract')!, apiKey.val); - }, - {namePos: 1} - ), - - new Command<{erc20: Erc20, spender: AddressV, amount: NumberV}>(` - #### Approve - - * "Erc20 Approve spender:
" - Adds an allowance between user and address - * E.g. "Erc20 ZRX Approve cZRX 1.0e18" - `, - "Approve", - [ - new Arg("erc20", getErc20V), - new Arg("spender", getAddressV), - new Arg("amount", getNumberV) - ], - (world, from, {erc20, spender, amount}) => { - return approve(world, from, erc20, spender.val, amount) - }, - {namePos: 1} - ), - - new Command<{erc20: Erc20, recipient: AddressV, amount: NumberV}>(` - #### Faucet - - * "Erc20 Faucet recipient: " - Adds an arbitrary balance to given user - * E.g. "Erc20 ZRX Faucet Geoff 1.0e18" - `, - "Faucet", - [ - new Arg("erc20", getErc20V), - new Arg("recipient", getAddressV), - new Arg("amount", getNumberV) - ], - (world, from, {erc20, recipient, amount}) => { - return faucet(world, from, erc20, recipient.val, amount) - }, - {namePos: 1} - ), - new Command<{erc20: Erc20, recipient: AddressV, amount: NumberV}>(` - #### Transfer - - * "Erc20 Transfer recipient: " - Transfers a number of tokens via "transfer" as given user to recipient (this does not depend on allowance) - * E.g. "Erc20 ZRX Transfer Torrey 1.0e18" - `, - "Transfer", - [ - new Arg("erc20", getErc20V), - new Arg("recipient", getAddressV), - new Arg("amount", getNumberV) - ], - (world, from, {erc20, recipient, amount}) => transfer(world, from, erc20, recipient.val, amount), - {namePos: 1} - ), - new Command<{erc20: Erc20, owner: AddressV, spender: AddressV, amount: NumberV}>(` - #### TransferFrom - - * "Erc20 TransferFrom owner: spender: " - Transfers a number of tokens via "transfeFrom" to recipient (this depends on allowances) - * E.g. "Erc20 ZRX TransferFrom Geoff Torrey 1.0e18" - `, - "TransferFrom", - [ - new Arg("erc20", getErc20V), - new Arg("owner", getAddressV), - new Arg("spender", getAddressV), - new Arg("amount", getNumberV) - ], - (world, from, {erc20, owner, spender, amount}) => transferFrom(world, from, erc20, owner.val, spender.val, amount), - {namePos: 1} - ), - new Command<{erc20: Erc20, fail: BoolV}>(` - #### SetFail - - * "Erc20 SetFail fail:" - Sets failure on or off for an EvilToken - * E.g. "Erc20 EVL SetFail False" - `, - "SetFail", - [ - new Arg("erc20", getErc20V), - new Arg("fail", getBoolV) - ], - (world, from, {erc20, fail}) => setFail(world, from, erc20, fail.val), - {namePos: 1} - ), - new Command<{erc20: Erc20, paused: BoolV}>(` - #### Pause - - * "Erc20 Pause paused:" - Sets paused on or off for WBTC - * E.g. "Erc20 WBTC Pause" - * E.g. "Erc20 WBTC Pause False" - `, - "Pause", - [ - new Arg("erc20", getErc20V), - new Arg("paused", getBoolV, {default: new BoolV(true)}) - ], - (world, from, {erc20, paused}) => setPaused(world, from, erc20, paused.val), - {namePos: 1} - ), - new Command<{erc20: Erc20, basisPointFee: NumberV, maxFee: NumberV}>(` - #### SetFee - - * "Erc20 SetFee basisPointFee: maxFee:" - Sets the current fee and max fee on Tether. Current - * Current fee (basisPointFee) has a max of 20 basis points, while maxFee is capped at 50 Tether (a max absolute fee of 50 * 10 ^ decimals) - * E.g. "Erc20 USDT SetFee 10 10" - `, - "SetFee", - [ - new Arg("erc20", getErc20V), - new Arg("basisPointFee", getNumberV), - new Arg("maxFee", getNumberV) - ], - (world, from, {erc20, basisPointFee, maxFee}) => setFee(world, from, erc20, basisPointFee, maxFee), - {namePos: 1} - ) - ]; -} - -export async function processErc20Event(world: World, event: Event, from: string | null): Promise { - return await processCommandEvent("Erc20", erc20Commands(), world, event, from); -} diff --git a/scenario/src/Event/ExpectationEvent.ts b/scenario/src/Event/ExpectationEvent.ts deleted file mode 100644 index 82429d348..000000000 --- a/scenario/src/Event/ExpectationEvent.ts +++ /dev/null @@ -1,70 +0,0 @@ -import {Event} from '../Event'; -import {addExpectation, World} from '../World'; -import { - EventV, - NumberV, - Value -} from '../Value'; -import { - getCoreValue, - getEventV, - getNumberV -} from '../CoreValue'; -import {Invariant} from '../Invariant'; -import {ChangesExpectation} from '../Expectation/ChangesExpectation'; -import {RemainsExpectation} from '../Expectation/RemainsExpectation'; -import {formatEvent} from '../Formatter'; -import {Arg, View, processCommandEvent} from '../Command'; - -async function changesExpectation(world: World, condition: Event, delta: NumberV, tolerance: NumberV): Promise { - const value = await getCoreValue(world, condition); - const expectation = new ChangesExpectation(condition, value, delta, tolerance); - - return addExpectation(world, expectation); -} - -async function remainsExpectation(world: World, condition: Event, value: Value): Promise { - const expectation = new RemainsExpectation(condition, value); - - // Immediately check value matches - await expectation.checker(world, true); - - return addExpectation(world, expectation); -} - -export function expectationCommands() { - return [ - new View<{condition: EventV, delta: NumberV, tolerance: NumberV}>(` - #### Changes - - * "Changes amount: tolerance:" - Expects that given value changes by amount - * E.g ."Expect Changes (CToken cZRX UnderlyingBalance Geoff) +10e18" - `, - "Changes", - [ - new Arg("condition", getEventV), - new Arg("delta", getNumberV), - new Arg("tolerance", getNumberV, {default: new NumberV(0)}) - ], - (world, {condition, delta, tolerance}) => changesExpectation(world, condition.val, delta, tolerance) - ), - - new View<{condition: EventV, value: Value}>(` - #### Remains - - * "Expect Remains " - Ensures that the given condition starts at and remains a given value - * E.g ."Expect Remains (CToken cZRX UnderlyingBalance Geoff) (Exactly 0)" - `, - "Remains", - [ - new Arg("condition", getEventV), - new Arg("value", getCoreValue) - ], - (world, {condition, value}) => remainsExpectation(world, condition.val, value) - ) - ]; -} - -export async function processExpectationEvent(world: World, event: Event, from: string | null): Promise { - return await processCommandEvent("Expectation", expectationCommands(), world, event, from); -} diff --git a/scenario/src/Event/InterestRateModelEvent.ts b/scenario/src/Event/InterestRateModelEvent.ts deleted file mode 100644 index 7276c06f5..000000000 --- a/scenario/src/Event/InterestRateModelEvent.ts +++ /dev/null @@ -1,84 +0,0 @@ -import {Event} from '../Event'; -import {addAction, World} from '../World'; -import {InterestRateModel} from '../Contract/InterestRateModel'; -import {buildInterestRateModel} from '../Builder/InterestRateModelBuilder'; -import {invoke} from '../Invokation'; -import { - getAddressV, - getEventV, - getNumberV, - getStringV, -} from '../CoreValue'; -import { - AddressV, - EventV, - NumberV, - StringV -} from '../Value'; -import {Arg, Command, processCommandEvent, View} from '../Command'; -import {getInterestRateModelData} from '../ContractLookup'; -import {verify} from '../Verify'; - -async function genInterestRateModel(world: World, from: string, params: Event): Promise { - let {world: nextWorld, interestRateModel, interestRateModelData} = await buildInterestRateModel(world, from, params); - world = nextWorld; - - world = addAction( - world, - `Deployed interest rate model (${interestRateModelData.description}) to address ${interestRateModel._address}`, - interestRateModelData.invokation - ); - - return world; -} - -async function verifyInterestRateModel(world: World, interestRateModel: InterestRateModel, apiKey: string, modelName: string, contractName: string): Promise { - if (world.isLocalNetwork()) { - world.printer.printLine(`Politely declining to verify on local network: ${world.network}.`); - } else { - await verify(world, apiKey, modelName, contractName, interestRateModel._address); - } - - return world; -} - -export function interestRateModelCommands() { - return [ - new Command<{params: EventV}>(` - #### Deploy - - * "Deploy ...params" - Generates a new interest rate model - * E.g. "InterestRateModel Deploy Fixed MyInterestRateModel 0.5" - * E.g. "InterestRateModel Deploy Whitepaper MyInterestRateModel 0.05 0.45" - * E.g. "InterestRateModel Deploy Standard MyInterestRateModel" - `, - "Deploy", - [ - new Arg("params", getEventV, {variadic: true}) - ], - (world, from, {params}) => genInterestRateModel(world, from, params.val) - ), - new View<{interestRateModelArg: StringV, apiKey: StringV}>(` - #### Verify - - * " Verify apiKey:" - Verifies InterestRateModel in Etherscan - * E.g. "InterestRateModel MyInterestRateModel Verify "myApiKey" - `, - "Verify", - [ - new Arg("interestRateModelArg", getStringV), - new Arg("apiKey", getStringV) - ], - async (world, {interestRateModelArg, apiKey}) => { - let [interestRateModel, name, data] = await getInterestRateModelData(world, interestRateModelArg.val); - - return await verifyInterestRateModel(world, interestRateModel, apiKey.val, name, data.get('contract')!) - }, - {namePos: 1} - ) - ]; -} - -export async function processInterestRateModelEvent(world: World, event: Event, from: string | null): Promise { - return await processCommandEvent("InterestRateModel", interestRateModelCommands(), world, event, from); -} diff --git a/scenario/src/Event/InvariantEvent.ts b/scenario/src/Event/InvariantEvent.ts deleted file mode 100644 index 9a94b9c8c..000000000 --- a/scenario/src/Event/InvariantEvent.ts +++ /dev/null @@ -1,83 +0,0 @@ -import {Event} from '../Event'; -import {addInvariant, World} from '../World'; -import { - EventV, - Value -} from '../Value'; -import { - getCoreValue, - getEventV, -} from '../CoreValue'; -import {Invariant} from '../Invariant'; -import {StaticInvariant} from '../Invariant/StaticInvariant'; -import {RemainsInvariant} from '../Invariant/RemainsInvariant'; -import {SuccessInvariant} from '../Invariant/SuccessInvariant'; -import {formatEvent} from '../Formatter'; -import {Arg, View, processCommandEvent} from '../Command'; - - -async function staticInvariant(world: World, condition): Promise { - const currentValue = await getCoreValue(world, condition); - const invariant = new StaticInvariant(condition, currentValue); - - return addInvariant(world, invariant); -} - -async function remainsInvariant(world: World, condition: Event, value: Value): Promise { - const invariant = new RemainsInvariant(condition, value); - - // Immediately check value matches - await invariant.checker(world, true); - - return addInvariant(world, invariant); -} - -async function successInvariant(world: World): Promise { - const invariant = new SuccessInvariant(); - - return addInvariant(world, invariant); -} - -export function invariantCommands() { - return [ - new View<{condition: EventV}>(` - #### Static - - * "Static " - Ensures that the given condition retains a consistent value - * E.g ."Invariant Static (CToken cZRX UnderlyingBalance Geoff)" - `, - "Static", - [ - new Arg("condition", getEventV) - ], - (world, {condition}) => staticInvariant(world, condition.val) - ), - new View<{condition: EventV, value: Value}>(` - #### Remains - - * "Invariant Remains " - Ensures that the given condition starts at and remains a given value - * E.g ."Invariant Remains (CToken cZRX UnderlyingBalance Geoff) (Exactly 0)" - `, - "Remains", - [ - new Arg("condition", getEventV), - new Arg("value", getCoreValue) - ], - (world, {condition, value}) => remainsInvariant(world, condition.val, value) - ), - new View<{}>(` - #### Success - - * "Invariant Success" - Ensures that each transaction completes successfully - * E.g ."Invariant Success" - `, - "Success", - [], - (world, {}) => successInvariant(world) - ) - ]; -} - -export async function processInvariantEvent(world: World, event: Event, from: string | null): Promise { - return await processCommandEvent("Invariant", invariantCommands(), world, event, from); -} diff --git a/scenario/src/Event/PriceOracleEvent.ts b/scenario/src/Event/PriceOracleEvent.ts deleted file mode 100644 index fadbd9dca..000000000 --- a/scenario/src/Event/PriceOracleEvent.ts +++ /dev/null @@ -1,146 +0,0 @@ -import {Event} from '../Event'; -import {addAction, World} from '../World'; -import {PriceOracle} from '../Contract/PriceOracle'; -import {buildPriceOracle, setPriceOracle} from '../Builder/PriceOracleBuilder'; -import {invoke} from '../Invokation'; -import { - getAddressV, - getEventV, - getExpNumberV, - getStringV -} from '../CoreValue'; -import { - AddressV, - EventV, - NumberV, - StringV -} from '../Value'; -import {Arg, Command, processCommandEvent, View} from '../Command'; -import {getPriceOracle} from '../ContractLookup'; -import {verify} from '../Verify'; -import {encodedNumber} from '../Encoding'; - -async function genPriceOracle(world: World, from: string, params: Event): Promise { - let {world: nextWorld, priceOracle, priceOracleData} = await buildPriceOracle(world, from, params); - world = nextWorld; - - world = addAction( - world, - `Deployed PriceOracle (${priceOracleData.description}) to address ${priceOracle._address}`, - priceOracleData.invokation! - ); - - return world; -} - -async function setPriceOracleFn(world: World, params: Event): Promise { - let {world: nextWorld, priceOracle, priceOracleData} = await setPriceOracle(world, params); - - return nextWorld; -} - -async function setPrice(world: World, from: string, priceOracle: PriceOracle, cToken: string, amount: NumberV): Promise { - return addAction( - world, - `Set price oracle price for ${cToken} to ${amount.show()}`, - await invoke(world, priceOracle.methods.setUnderlyingPrice(cToken, amount.encode()), from) - ); -} - -async function setDirectPrice(world: World, from: string, priceOracle: PriceOracle, address: string, amount: NumberV): Promise { - return addAction( - world, - `Set price oracle price for ${address} to ${amount.show()}`, - await invoke(world, priceOracle.methods.setDirectPrice(address, amount.encode()), from) - ); -} - -async function verifyPriceOracle(world: World, priceOracle: PriceOracle, apiKey: string, contractName: string): Promise { - if (world.isLocalNetwork()) { - world.printer.printLine(`Politely declining to verify on local network: ${world.network}.`); - } else { - await verify(world, apiKey, "PriceOracle", contractName, priceOracle._address); - } - - return world; -} - -export function priceOracleCommands() { - return [ - new Command<{params: EventV}>(` - #### Deploy - - * "Deploy ...params" - Generates a new price oracle - * E.g. "PriceOracle Deploy Fixed 1.0" - * E.g. "PriceOracle Deploy Simple" - * E.g. "PriceOracle Deploy NotPriceOracle" - `, - "Deploy", - [ - new Arg("params", getEventV, {variadic: true}) - ], - (world, from, {params}) => genPriceOracle(world, from, params.val) - ), - new Command<{params: EventV}>(` - #### Set - - * "Set ...params" - Sets the price oracle to given deployed contract - * E.g. "PriceOracle Set Standard \"0x...\" \"My Already Deployed Oracle\"" - `, - "Set", - [ - new Arg("params", getEventV, {variadic: true}) - ], - (world, from, {params}) => setPriceOracleFn(world, params.val) - ), - - new Command<{priceOracle: PriceOracle, cToken: AddressV, amount: NumberV}>(` - #### SetPrice - - * "SetPrice " - Sets the per-ether price for the given cToken - * E.g. "PriceOracle SetPrice cZRX 1.0" - `, - "SetPrice", - [ - new Arg("priceOracle", getPriceOracle, {implicit: true}), - new Arg("cToken", getAddressV), - new Arg("amount", getExpNumberV) - ], - (world, from, {priceOracle, cToken, amount}) => setPrice(world, from, priceOracle, cToken.val, amount) - ), - - new Command<{priceOracle: PriceOracle, address: AddressV, amount: NumberV}>(` - #### SetDirectPrice - - * "SetDirectPrice
" - Sets the per-ether price for the given cToken - * E.g. "PriceOracle SetDirectPrice (Address Zero) 1.0" - `, - "SetDirectPrice", - [ - new Arg("priceOracle", getPriceOracle, {implicit: true}), - new Arg("address", getAddressV), - new Arg("amount", getExpNumberV) - ], - (world, from, {priceOracle, address, amount}) => setDirectPrice(world, from, priceOracle, address.val, amount) - ), - - new View<{priceOracle: PriceOracle, apiKey: StringV, contractName: StringV}>(` - #### Verify - - * "Verify apiKey: contractName:=PriceOracle" - Verifies PriceOracle in Etherscan - * E.g. "PriceOracle Verify "myApiKey" - `, - "Verify", - [ - new Arg("priceOracle", getPriceOracle, {implicit: true}), - new Arg("apiKey", getStringV), - new Arg("contractName", getStringV, {default: new StringV("PriceOracle")}) - ], - (world, {priceOracle, apiKey, contractName}) => verifyPriceOracle(world, priceOracle, apiKey.val, contractName.val) - ) - ]; -} - -export async function processPriceOracleEvent(world: World, event: Event, from: string | null): Promise { - return await processCommandEvent("PriceOracle", priceOracleCommands(), world, event, from); -} diff --git a/scenario/src/Event/PriceOracleProxyEvent.ts b/scenario/src/Event/PriceOracleProxyEvent.ts deleted file mode 100644 index a75af5b8b..000000000 --- a/scenario/src/Event/PriceOracleProxyEvent.ts +++ /dev/null @@ -1,104 +0,0 @@ -import {Event} from '../Event'; -import {addAction, World} from '../World'; -import {PriceOracleProxy} from '../Contract/PriceOracleProxy'; -import {buildPriceOracleProxy} from '../Builder/PriceOracleProxyBuilder'; -import {invoke} from '../Invokation'; -import { - getAddressV, - getEventV, - getExpNumberV, - getStringV -} from '../CoreValue'; -import { - AddressV, - EventV, - NumberV, - StringV -} from '../Value'; -import {Arg, Command, processCommandEvent, View} from '../Command'; -import {getPriceOracleProxy} from '../ContractLookup'; -import {verify} from '../Verify'; -import {encodedNumber} from '../Encoding'; - -async function genPriceOracleProxy(world: World, from: string, params: Event): Promise { - let priceOracleProxy; - let invokation; - - ({world, priceOracleProxy, invokation} = await buildPriceOracleProxy(world, from, params)); - - world = addAction( - world, - `Deployed PriceOracleProxy to address ${priceOracleProxy._address}`, - invokation - ); - - return world; -} - -async function verifyPriceOracleProxy(world: World, priceOracleProxy: PriceOracleProxy, apiKey: string, contractName: string): Promise { - if (world.isLocalNetwork()) { - world.printer.printLine(`Politely declining to verify on local network: ${world.network}.`); - } else { - await verify(world, apiKey, "PriceOracleProxy", contractName, priceOracleProxy._address); - } - - return world; -} - -async function setSaiPrice(world: World, from: string, priceOracleProxy: PriceOracleProxy, amount: NumberV): Promise { - return addAction( - world, - `Set price oracle SAI price to ${amount.show()}`, - await invoke(world, priceOracleProxy.methods.setSaiPrice(amount.encode()), from) - ); -} - -export function priceOracleProxyCommands() { - return [ - new Command<{params: EventV}>(` - #### Deploy - - * "Deploy ...params" - Generates a new price oracle proxy - * E.g. "PriceOracleProxy Deploy (Unitroller Address) (PriceOracle Address) (cEther Address)" - `, - "Deploy", - [ - new Arg("params", getEventV, {variadic: true}) - ], - (world, from, {params}) => genPriceOracleProxy(world, from, params.val) - ), - - new View<{priceOracleProxy: PriceOracleProxy, apiKey: StringV, contractName: StringV}>(` - #### Verify - - * "Verify apiKey: contractName:=PriceOracleProxy" - Verifies PriceOracleProxy in Etherscan - * E.g. "PriceOracleProxy Verify "myApiKey" - `, - "Verify", - [ - new Arg("priceOracleProxy", getPriceOracleProxy, {implicit: true}), - new Arg("apiKey", getStringV), - new Arg("contractName", getStringV, {default: new StringV("PriceOracleProxy")}) - ], - (world, {priceOracleProxy, apiKey, contractName}) => verifyPriceOracleProxy(world, priceOracleProxy, apiKey.val, contractName.val) - ), - - new Command<{priceOracleProxy: PriceOracleProxy, amount: NumberV}>(` - #### SetSaiPrice - - * "SetSaiPrice " - Sets the per-ether price for SAI - * E.g. "PriceOracleProxy SetSaiPrice 1.0" - `, - "SetSaiPrice", - [ - new Arg("priceOracleProxy", getPriceOracleProxy, {implicit: true}), - new Arg("amount", getExpNumberV) - ], - (world, from, {priceOracleProxy, amount}) => setSaiPrice(world, from, priceOracleProxy, amount) - ) - ]; -} - -export async function processPriceOracleProxyEvent(world: World, event: Event, from: string | null): Promise { - return await processCommandEvent("PriceOracleProxy", priceOracleProxyCommands(), world, event, from); -} diff --git a/scenario/src/Event/TrxEvent.ts b/scenario/src/Event/TrxEvent.ts deleted file mode 100644 index ae8285298..000000000 --- a/scenario/src/Event/TrxEvent.ts +++ /dev/null @@ -1,56 +0,0 @@ -import {World} from '../World'; -import {Event} from '../Event'; -import {processCoreEvent} from '../CoreEvent'; -import { - EventV, - NumberV -} from '../Value'; -import { - getEventV, - getNumberV -} from '../CoreValue'; -import {Arg, Command, processCommandEvent} from '../Command'; -import {encodedNumber} from '../Encoding'; - -async function setTrxValue(world: World, value: encodedNumber): Promise { - return world.update('trxInvokationOpts', (t) => t.set('value', value.toString())); -} - -async function setTrxGasPrice(world: World, gasPrice: encodedNumber): Promise { - return world.update('trxInvokationOpts', (t) => t.set('gasPrice', gasPrice.toString()));; -} - -export function trxCommands() { - return [ - new Command<{amount: NumberV, event: EventV}>(` - #### Value - - * "Value " - Runs event with a set amount for any transactions - * E.g. "Value 1.0e18 (CToken cEth Mint 1.0e18)" - `, - "Value", - [ - new Arg("amount", getNumberV), - new Arg("event", getEventV) - ], - async (world, from, {amount, event}) => processCoreEvent(await setTrxValue(world, amount.encode()), event.val, from) - ), - new Command<{gasPrice: NumberV, event: EventV}>(` - #### GasPrice - - * "GasPrice " - Runs event with a given gas price - * E.g. "GasPrice 0 (CToken cEth Mint 1.0e18)" - `, - "GasPrice", - [ - new Arg("gasPrice", getNumberV), - new Arg("event", getEventV) - ], - async (world, from, {gasPrice, event}) => processCoreEvent(await setTrxGasPrice(world, gasPrice.encode()), event.val, from) - ) - ]; -} - -export async function processTrxEvent(world: World, event: Event, from: string | null): Promise { - return await processCommandEvent("Trx", trxCommands(), world, event, from); -} diff --git a/scenario/src/Event/UnitrollerEvent.ts b/scenario/src/Event/UnitrollerEvent.ts deleted file mode 100644 index 6adc46133..000000000 --- a/scenario/src/Event/UnitrollerEvent.ts +++ /dev/null @@ -1,152 +0,0 @@ -import { Event } from '../Event'; -import { addAction, describeUser, World } from '../World'; -import { Unitroller } from '../Contract/Unitroller'; -import { ComptrollerImpl } from '../Contract/ComptrollerImpl'; -import { invoke } from '../Invokation'; -import { getEventV, getStringV, getAddressV } from '../CoreValue'; -import { EventV, StringV, AddressV } from '../Value'; -import { Arg, Command, View, processCommandEvent } from '../Command'; -import { ComptrollerErrorReporter } from '../ErrorReporter'; -import { buildUnitroller } from '../Builder/UnitrollerBuilder'; -import { getComptrollerImpl, getUnitroller } from '../ContractLookup'; -import { verify } from '../Verify'; - -async function genUnitroller(world: World, from: string, params: Event): Promise { - let { world: nextWorld, unitroller, unitrollerData } = await buildUnitroller(world, from, params); - world = nextWorld; - - world = addAction( - world, - `Added Unitroller (${unitrollerData.description}) at address ${unitroller._address}`, - unitrollerData.invokation - ); - - return world; -} - -async function verifyUnitroller(world: World, unitroller: Unitroller, apiKey: string): Promise { - if (world.isLocalNetwork()) { - world.printer.printLine(`Politely declining to verify on local network: ${world.network}.`); - } else { - await verify(world, apiKey, 'Unitroller', 'Unitroller', unitroller._address); - } - - return world; -} - -async function acceptAdmin(world: World, from: string, unitroller: Unitroller): Promise { - let invokation = await invoke(world, unitroller.methods._acceptAdmin(), from, ComptrollerErrorReporter); - - world = addAction(world, `Accept admin as ${from}`, invokation); - - return world; -} - -async function setPendingAdmin( - world: World, - from: string, - unitroller: Unitroller, - pendingAdmin: string -): Promise { - let invokation = await invoke( - world, - unitroller.methods._setPendingAdmin(pendingAdmin), - from, - ComptrollerErrorReporter - ); - - world = addAction(world, `Set pending admin to ${pendingAdmin}`, invokation); - - return world; -} - -async function setPendingImpl( - world: World, - from: string, - unitroller: Unitroller, - comptrollerImpl: ComptrollerImpl -): Promise { - let invokation = await invoke( - world, - unitroller.methods._setPendingImplementation(comptrollerImpl._address), - from, - ComptrollerErrorReporter - ); - - world = addAction(world, `Set pending comptroller impl to ${comptrollerImpl.name}`, invokation); - - return world; -} - -export function unitrollerCommands() { - return [ - new Command<{ unitrollerParams: EventV }>( - ` - #### Deploy - - * "Unitroller Deploy ...unitrollerParams" - Generates a new Unitroller - * E.g. "Unitroller Deploy" - `, - 'Deploy', - [new Arg('unitrollerParams', getEventV, { variadic: true })], - (world, from, { unitrollerParams }) => genUnitroller(world, from, unitrollerParams.val) - ), - new View<{ unitroller: Unitroller; apiKey: StringV }>( - ` - #### Verify - - * "Unitroller Verify apiKey:" - Verifies Unitroller in Etherscan - * E.g. "Unitroller Verify "myApiKey" - `, - 'Verify', - [new Arg('unitroller', getUnitroller, { implicit: true }), new Arg('apiKey', getStringV)], - (world, { unitroller, apiKey }) => verifyUnitroller(world, unitroller, apiKey.val) - ), - new Command<{ unitroller: Unitroller; pendingAdmin: AddressV }>( - ` - #### AcceptAdmin - - * "AcceptAdmin" - Accept admin for this unitroller - * E.g. "Unitroller AcceptAdmin" - `, - 'AcceptAdmin', - [new Arg('unitroller', getUnitroller, { implicit: true })], - (world, from, { unitroller }) => acceptAdmin(world, from, unitroller) - ), - new Command<{ unitroller: Unitroller; pendingAdmin: AddressV }>( - ` - #### SetPendingAdmin - - * "SetPendingAdmin admin:" - Sets the pending admin for this unitroller - * E.g. "Unitroller SetPendingAdmin Jared" - `, - 'SetPendingAdmin', - [new Arg('unitroller', getUnitroller, { implicit: true }), new Arg('pendingAdmin', getAddressV)], - (world, from, { unitroller, pendingAdmin }) => - setPendingAdmin(world, from, unitroller, pendingAdmin.val) - ), - new Command<{ unitroller: Unitroller; comptrollerImpl: ComptrollerImpl }>( - ` - #### SetPendingImpl - - * "SetPendingImpl impl:" - Sets the pending comptroller implementation for this unitroller - * E.g. "Unitroller SetPendingImpl MyScenImpl" - Sets the current comptroller implementation to MyScenImpl - `, - 'SetPendingImpl', - [ - new Arg('unitroller', getUnitroller, { implicit: true }), - new Arg('comptrollerImpl', getComptrollerImpl) - ], - (world, from, { unitroller, comptrollerImpl }) => - setPendingImpl(world, from, unitroller, comptrollerImpl) - ) - ]; -} - -export async function processUnitrollerEvent( - world: World, - event: Event, - from: string | null -): Promise { - return await processCommandEvent('Unitroller', unitrollerCommands(), world, event, from); -} diff --git a/scenario/src/EventBuilder.ts b/scenario/src/EventBuilder.ts deleted file mode 100644 index 54d7a9d0e..000000000 --- a/scenario/src/EventBuilder.ts +++ /dev/null @@ -1,310 +0,0 @@ -import { Event } from './Event'; -import { addAction, World } from './World'; -import { Invokation } from './Invokation'; -import { Arg, Command, Fetcher, getFetcherValue, processCommandEvent, View } from './Command'; -import { storeAndSaveContract } from './Networks'; -import { Contract, getContract } from './Contract'; -import { getWorldContract } from './ContractLookup'; -import { mustString } from './Utils'; -import { Callable, Sendable, invoke } from './Invokation'; -import { - AddressV, - ArrayV, - EventV, - NumberV, - StringV, - Value -} from './Value'; -import { - getAddressV, - getArrayV, - getEventV, - getNumberV, - getStringV, -} from './CoreValue'; -import { AbiItem, AbiInput } from 'web3-utils'; - -export interface ContractData { - invokation: Invokation; - name: string; - contract: string; - address?: string; -} - -const typeMappings = () => ({ - address: { - builder: (x) => new AddressV(x), - getter: getAddressV - }, - 'address[]': { - builder: (x) => new ArrayV(x), - getter: (x) => getArrayV(x), - }, - string: { - builder: (x) => new StringV(x), - getter: getStringV - }, - uint256: { - builder: (x) => new NumberV(x), - getter: getNumberV - }, - 'uint256[]': { - builder: (x) => new ArrayV(x), - getter: (x) => getArrayV(x), - }, - 'uint32[]': { - builder: (x) => new ArrayV(x), - getter: (x) => getArrayV(x), - }, - 'uint96[]': { - builder: (x) => new ArrayV(x), - getter: (x) => getArrayV(x), - } -}); - -function buildArg(contractName: string, name: string, input: AbiInput): Arg { - let { getter } = typeMappings()[input.type] || {}; - - if (!getter) { - throw new Error(`Unknown ABI Input Type: ${input.type} of \`${name}\` in ${contractName}`); - } - - return new Arg(name, getter); -} - -function getEventName(s) { - return s.charAt(0).toUpperCase() + s.slice(1); -} - -function getContractObjectFn(contractName, implicit) { - if (implicit) { - return async function getContractObject(world: World): Promise { - return getWorldContract(world, [['Contracts', contractName]]); - } - } else { - return async function getContractObject(world: World, event: Event): Promise { - return getWorldContract(world, [['Contracts', mustString(event)]]); - } - } -} -export function buildContractEvent(contractName: string, implicit) { - - - return async (world) => { - let contractDeployer = getContract(contractName); - let abis: AbiItem[] = await world.saddle.abi(contractName); - - async function build( - world: World, - from: string, - params: Event - ): Promise<{ world: World; contract: T; data: ContractData }> { - let constructors = abis.filter(({type}) => type === 'constructor'); - if (constructors.length === 0) { - constructors.push({ - constant: false, - inputs: [], - outputs: [], - payable: true, - stateMutability: "payable", - type: 'constructor' - }); - } - - const fetchers = constructors.map((abi: any) => { - let nameArg = implicit ? [] : [ - new Arg('name', getStringV, { default: new StringV(contractName) }) - ]; - let nameArgDesc = implicit ? `` : `name:=${contractName}" ` - let inputNames = abi.inputs.map((input) => getEventName(input.name)); - let args = abi.inputs.map((input) => buildArg(contractName, input.name, input)); - return new Fetcher>( - ` - #### ${contractName} - - * "${contractName} ${nameArgDesc}${inputNames.join(" ")} - Build ${contractName} - * E.g. "${contractName} Deploy" - } - `, - contractName, - nameArg.concat(args), - async (world, paramValues) => { - let name = implicit ? contractName : paramValues['name'].val; - let params = args.map((arg) => paramValues[arg.name]); // TODO: This is just a guess - let paramsEncoded = params.map((param) => typeof(param['encode']) === 'function' ? param.encode() : param.val); - - return { - invokation: await contractDeployer.deploy(world, from, paramsEncoded), - name: name, - contract: contractName - }; - }, - { catchall: true } - ) - }); - - let data = await getFetcherValue>(`Deploy${contractName}`, fetchers, world, params); - let invokation = data.invokation; - delete data.invokation; - - if (invokation.error) { - throw invokation.error; - } - - const contract = invokation.value!; - contract.address = contract._address; - const index = contractName == data.name ? [contractName] : [contractName, data.name]; - - world = await storeAndSaveContract( - world, - contract, - data.name, - invokation, - [ - { index: index, data: data } - ] - ); - - return { world, contract, data }; - } - - async function deploy(world: World, from: string, params: Event) { - let { world: nextWorld, contract, data } = await build(world, from, params); - world = nextWorld; - - world = addAction( - world, - `Deployed ${contractName} ${data.contract} to address ${contract._address}`, - data.invokation - ); - - return world; - } - - function commands() { - async function buildOutput(world: World, from: string, fn: string, inputs: object, output: AbiItem): Promise { - const sendable = >(inputs['contract'].methods[fn](...Object.values(inputs).slice(1))); - let invokation = await invoke(world, sendable, from); - - world = addAction( - world, - `Invokation of ${fn} with inputs ${inputs}`, - invokation - ); - - return world; - } - - let abiCommands = abis.filter(({type}) => type === 'function').map((abi: any) => { - let eventName = getEventName(abi.name); - let inputNames = abi.inputs.map((input) => getEventName(input.name)); - let args = [ - new Arg("contract", getContractObjectFn(contractName, implicit), implicit ? { implicit: true } : {}) - ].concat(abi.inputs.map((input) => buildArg(contractName, abi.name, input))); - - return new Command(` - #### ${eventName} - - * "${eventName} ${inputNames.join(" ")}" - Executes \`${abi.name}\` function - `, - eventName, - args, - (world, from, inputs) => buildOutput(world, from, abi.name, inputs, abi.outputs[0]), - { namePos: implicit ? 0 : 1 } - ) - }); - - return [ - ...abiCommands, - new Command<{ params: EventV }>(` - #### ${contractName} - - * "${contractName} Deploy" - Deploy ${contractName} - * E.g. "Counter Deploy" - `, - "Deploy", - [ - new Arg("params", getEventV, { variadic: true }) - ], - (world, from, { params }) => deploy(world, from, params.val) - ) - ]; - } - - async function processEvent(world: World, event: Event, from: string | null): Promise { - return await processCommandEvent(contractName, commands(), world, event, from); - } - - let command = new Command<{ event: EventV }>( - ` - #### ${contractName} - - * "${contractName} ...event" - Runs given ${contractName} event - * E.g. "${contractName} Deploy" - `, - contractName, - [new Arg('event', getEventV, { variadic: true })], - (world, from, { event }) => { - return processEvent(world, event.val, from); - }, - { subExpressions: commands() } - ); - - return command; - } -} - -export async function buildContractFetcher(world: World, contractName: string, implicit: boolean) { - - let abis: AbiItem[] = await world.saddle.abi(contractName); - - function fetchers() { - async function buildOutput(world: World, fn: string, inputs: object, output: AbiItem): Promise { - const callable = >(inputs['contract'].methods[fn](...Object.values(inputs).slice(1))); - let value = await callable.call(); - let { builder } = typeMappings()[output.type] || {}; - - if (!builder) { - throw new Error(`Unknown ABI Output Type: ${output.type} of \`${fn}\` in ${contractName}`); - } - - return builder(value); - } - - return abis.filter(({name}) => !!name).map((abi: any) => { - let eventName = getEventName(abi.name); - let inputNames = abi.inputs.map((input) => getEventName(input.name)); - let args = [ - new Arg("contract", getContractObjectFn(contractName, implicit), implicit ? { implicit: true } : {}) - ].concat(abi.inputs.map((input) => buildArg(contractName, abi.name, input))); - return new Fetcher(` - #### ${eventName} - - * "${eventName} ${inputNames.join(" ")}" - Returns the result of \`${abi.name}\` function - `, - eventName, - args, - (world, inputs) => buildOutput(world, abi.name, inputs, abi.outputs[0]), - { namePos: implicit ? 0 : 1 } - ) - }); - } - - async function getValue(world: World, event: Event): Promise { - return await getFetcherValue(contractName, fetchers(), world, event); - } - - let fetcher = new Fetcher<{ res: Value }, Value>( - ` - #### ${contractName} - - * "${contractName} ...args" - Returns ${contractName} value - `, - contractName, - [new Arg('res', getValue, { variadic: true })], - async (world, { res }) => res, - { subExpressions: fetchers() } - ) - - return fetcher; -} diff --git a/scenario/src/Expectation.ts b/scenario/src/Expectation.ts deleted file mode 100644 index 7823f87fd..000000000 --- a/scenario/src/Expectation.ts +++ /dev/null @@ -1,4 +0,0 @@ - -export interface Expectation { - checker: (world: any) => Promise; -} diff --git a/scenario/src/Expectation/ChangesExpectation.ts b/scenario/src/Expectation/ChangesExpectation.ts deleted file mode 100644 index 91acee86e..000000000 --- a/scenario/src/Expectation/ChangesExpectation.ts +++ /dev/null @@ -1,52 +0,0 @@ -import {Expectation} from '../Expectation'; -import {fail, World} from '../World'; -import {getCoreValue} from '../CoreValue'; -import {Value, NumberV} from '../Value'; -import {Event} from '../Event'; -import {formatEvent} from '../Formatter'; -import {BigNumber} from 'bignumber.js'; - -function asNumberV(v: Value): NumberV { - if (v instanceof NumberV) { - return v; - } else { - throw new Error(`Expected NumberV for ChangesExpectation, got ${v.toString()}`); - } -} - -export class ChangesExpectation implements Expectation { - condition: Event; - originalValue: NumberV; - delta: NumberV; - tolerance: NumberV; - expected: NumberV; - - constructor(condition: Event, originalValue: Value, delta: NumberV, tolerance: NumberV) { - this.condition = condition; - this.originalValue = asNumberV(originalValue); - this.delta = delta; - this.tolerance = tolerance; - this.expected = this.originalValue.add(this.delta); - } - - async getCurrentValue(world: World): Promise { - return await getCoreValue(world, this.condition); - }; - - async checker(world: World, initialCheck: boolean=false): Promise { - const currentValue = asNumberV(await this.getCurrentValue(world)); - const trueDelta = currentValue.sub(this.originalValue); - - if (this.tolerance.val != 0) { - if (Math.abs(Number(trueDelta.sub(this.delta).div(this.originalValue).val)) > Number(this.tolerance.val)) { - fail(world, `Expected ${trueDelta.toString()} to approximately equal ${this.delta.toString()} within ${this.tolerance.toString()}`); - } - } else if (!currentValue.compareTo(world, this.expected)) { - fail(world, `${this.toString()} instead had value \`${currentValue.toString()}\` (true delta: ${trueDelta.toString()})`); - } - } - - toString() { - return `ChangesExpectation: condition=${formatEvent(this.condition)}, originalValue=${this.originalValue.toString()}, delta=${this.delta.toString()}, expected=${this.expected.toString()}`; - } -} diff --git a/scenario/src/Expectation/RemainsExpectation.ts b/scenario/src/Expectation/RemainsExpectation.ts deleted file mode 100644 index 9506cc473..000000000 --- a/scenario/src/Expectation/RemainsExpectation.ts +++ /dev/null @@ -1,32 +0,0 @@ -import {Expectation} from '../Expectation'; -import {fail, World} from '../World'; -import {getCoreValue} from '../CoreValue'; -import {Value} from '../Value'; -import {Event} from '../Event'; -import {formatEvent} from '../Formatter'; - -export class RemainsExpectation implements Expectation { - condition: Event; - value: Value; - - constructor(condition: Event, value: Value) { - this.condition = condition; - this.value = value; - } - - async getCurrentValue(world: World): Promise { - return await getCoreValue(world, this.condition); - }; - - async checker(world: World, initialCheck: boolean=false): Promise { - const currentValue = await this.getCurrentValue(world); - - if (!this.value.compareTo(world, currentValue)) { - fail(world, `${this.toString()} failed as value ${initialCheck ? 'started as' : 'became'} \`${currentValue.toString()}\``); - } - } - - toString() { - return `RemainsExpectation: condition=${formatEvent(this.condition)}, value=${this.value.toString()}`; - } -} diff --git a/scenario/src/File.ts b/scenario/src/File.ts deleted file mode 100644 index 1452e66a7..000000000 --- a/scenario/src/File.ts +++ /dev/null @@ -1,39 +0,0 @@ -import * as fs from 'fs'; -import * as path from 'path'; -import { World } from './World'; - -export function getNetworkPath(basePath: string | null, network: string, name: string, extension: string | null='json'): string { - return path.join(basePath || '', 'networks', `${network}${name}${extension ? `.${extension}` : ''}`); -} - -export async function readFile(world: World | null, file: string, def: T, fn: (data: string) => T): Promise { - if (world && world.fs) { - let data = world.fs[file]; - return Promise.resolve(data ? fn(data) : def); - } else { - return new Promise((resolve, reject) => { - fs.access(file, fs.constants.F_OK, (err) => { - if (err) { - resolve(def); - } else { - fs.readFile(file, 'utf8', (err, data) => { - return err ? reject(err) : resolve(fn(data)); - }); - } - }); - }); - } -} - -export async function writeFile(world: World | null, file: string, data: string): Promise { - if (world && world.fs) { - world = world.setIn(['fs', file], data); - return Promise.resolve(world); - } else { - return new Promise((resolve, reject) => { - fs.writeFile(file, data, (err) => { - return err ? reject(err) : resolve(world!); // XXXS `!` - }); - }); - } -} diff --git a/scenario/src/Formatter.ts b/scenario/src/Formatter.ts deleted file mode 100644 index 55e2d4806..000000000 --- a/scenario/src/Formatter.ts +++ /dev/null @@ -1,25 +0,0 @@ -import {Event} from './Event'; - -// Effectively the opposite of parse -export function formatEvent(event: Event, outter=true): string { - if (Array.isArray(event)) { - if (event.length === 2 && typeof event[0] === "string" && (event[0]).toLowerCase() === "exactly") { - return event[1].toString(); - } - - let mapped = event.map(e => formatEvent(e, false)); - let joined = mapped.join(' '); - - if (outter) { - return joined; - } else { - return `(${joined})`; - } - } else { - return event; - } -} - -export function formatError(err: any) { - return JSON.stringify(err); // yeah... for now -} diff --git a/scenario/src/Help.ts b/scenario/src/Help.ts deleted file mode 100644 index c67d53170..000000000 --- a/scenario/src/Help.ts +++ /dev/null @@ -1,64 +0,0 @@ -import {Event} from './Event'; -import {Expression} from './Command'; -import {mustString} from './Utils'; -import {Printer} from './Printer'; - -export function printHelp(printer: Printer, event: Event, expressions: Expression[], path: string[]=[]) { - if (event.length === 0) { - let banner; - - if (path.length === 0) { - banner = ( -` -## Compound Command Runner - -The Compound Command Runner makes it easy to interact with Compound. You can input simple commands -and it will construct Web3 calls to pull data or generate transactions. A list of available commands -is included below. To dig further into a command run \`Help \`, such as \`Help From\` or for -sub-commands run \`Help CToken\` or \`Help CToken Mint\`. -`).trim(); - } else { - if (expressions.length > 0) { - banner = `### ${path.join(" ")} Sub-Commands`; - } - } - - if (!!banner) { - printer.printMarkdown(banner); - } - - expressions.forEach((expression) => { - printer.printMarkdown(`\n${expression.doc}`); - if (expression.subExpressions.length > 0) { - printer.printMarkdown(`For more information, run: \`Help ${path} ${expression.name}\``); - } - }); - } else { - const [first, ...rest] = event; - const expressionName = mustString(first); - - let expression = expressions.find((expression) => expression.name.toLowerCase() === expressionName.toLowerCase()); - - if (expression) { - if (rest.length === 0) { - printer.printMarkdown(`${expression.doc}`); - } - - printHelp(printer, rest, expression.subExpressions, path.concat(expression.name)); - } else { - let matchingExpressions = expressions.filter((expression) => expression.name.toLowerCase().startsWith(expressionName.toLowerCase())); - - if (matchingExpressions.length === 0) { - printer.printLine(`\nError: cannot find help docs for ${path.concat(first).join(" ")}`); - } else { - if (rest.length === 0) { - matchingExpressions.forEach((expression) => { - printer.printMarkdown(`${expression.doc}`); - }); - } else { - printer.printLine(`\nError: cannot find help docs for ${path.concat(event).join(" ")}`); - } - } - } - } -} diff --git a/scenario/src/HistoricReadline.ts b/scenario/src/HistoricReadline.ts deleted file mode 100644 index 21dbc87c8..000000000 --- a/scenario/src/HistoricReadline.ts +++ /dev/null @@ -1,35 +0,0 @@ -import * as readline from 'readline'; -import * as fs from 'fs'; -import {readFile} from './File'; - -let readlineAny = readline; - -export async function createInterface(options): Promise { - let history: string[] = await readFile(null, options['path'], [], (x) => x.split("\n")); - let cleanHistory = history.filter((x) => !!x).reverse(); - - readlineAny.kHistorySize = Math.max(readlineAny.kHistorySize, options['maxLength']); - - let rl = readline.createInterface(options); - let rlAny = rl; - - let oldAddHistory = rlAny._addHistory; - - rlAny._addHistory = function() { - let last = rlAny.history[0]; - let line = oldAddHistory.call(rl); - - // TODO: Should this be sync? - if (line.length > 0 && line != last) { - fs.appendFileSync(options['path'], `${line}\n`); - } - - // TODO: Truncate file? - - return line; - } - - rlAny.history.push.apply(rlAny.history, cleanHistory); - - return rl; -} diff --git a/scenario/src/Hypothetical.ts b/scenario/src/Hypothetical.ts deleted file mode 100644 index 497ea3def..000000000 --- a/scenario/src/Hypothetical.ts +++ /dev/null @@ -1,36 +0,0 @@ -import {Accounts, loadAccounts} from './Accounts'; -import { - addAction, - checkExpectations, - checkInvariants, - clearInvariants, - describeUser, - holdInvariants, - setEvent, - World -} from './World'; -import {Ganache} from 'eth-saddle/dist/config'; -import Web3 from 'web3'; - -export async function forkWeb3(web3: Web3, url: string, accounts: string[]): Promise { - let lastBlock = await web3.eth.getBlock("latest") - return new Web3( - Ganache.provider({ - allowUnlimitedContractSize: true, - fork: url, - gasLimit: lastBlock.gasLimit, // maintain configured gas limit - gasPrice: '20000', - port: 8546, - unlocked_accounts: accounts - }) - ); -} - -export async function fork(world: World, url: string, accounts: string[]): Promise { - let newWeb3 = await forkWeb3(world.web3, url, accounts); - const newAccounts = loadAccounts(await newWeb3.eth.getAccounts()); - - return world - .set('web3', newWeb3) - .set('accounts', newAccounts); -} diff --git a/scenario/src/Invariant.ts b/scenario/src/Invariant.ts deleted file mode 100644 index fc5211c0a..000000000 --- a/scenario/src/Invariant.ts +++ /dev/null @@ -1,5 +0,0 @@ - -export interface Invariant { - held: boolean - checker: (world: any) => Promise; -} diff --git a/scenario/src/Invariant/RemainsInvariant.ts b/scenario/src/Invariant/RemainsInvariant.ts deleted file mode 100644 index b98a4c635..000000000 --- a/scenario/src/Invariant/RemainsInvariant.ts +++ /dev/null @@ -1,33 +0,0 @@ -import {Invariant} from '../Invariant'; -import {fail, World} from '../World'; -import {getCoreValue} from '../CoreValue'; -import {Value} from '../Value'; -import {Event} from '../Event'; -import {formatEvent} from '../Formatter'; - -export class RemainsInvariant implements Invariant { - condition: Event; - value: Value; - held = false; - - constructor(condition: Event, value: Value) { - this.condition = condition; - this.value = value; - } - - async getCurrentValue(world: World): Promise { - return await getCoreValue(world, this.condition); - }; - - async checker(world: World, initialCheck: boolean=false): Promise { - const currentValue = await this.getCurrentValue(world); - - if (!this.value.compareTo(world, currentValue)) { - fail(world, `Static invariant broken! Expected ${this.toString()} to remain static value \`${this.value}\` but ${initialCheck ? 'started as' : 'became'} \`${currentValue}\``); - } - } - - toString() { - return `RemainsInvariant: condition=${formatEvent(this.condition)}, value=${this.value.toString()}`; - } -} diff --git a/scenario/src/Invariant/StaticInvariant.ts b/scenario/src/Invariant/StaticInvariant.ts deleted file mode 100644 index 7a464c310..000000000 --- a/scenario/src/Invariant/StaticInvariant.ts +++ /dev/null @@ -1,33 +0,0 @@ -import {Invariant} from '../Invariant'; -import {fail, World} from '../World'; -import {getCoreValue} from '../CoreValue'; -import {Value} from '../Value'; -import {Event} from '../Event'; -import {formatEvent} from '../Formatter'; - -export class StaticInvariant implements Invariant { - condition: Event; - value: Value; - held = false; - - constructor(condition: Event, value: Value) { - this.condition = condition; - this.value = value; - } - - async getCurrentValue(world: World): Promise { - return await getCoreValue(world, this.condition); - }; - - async checker(world: World): Promise { - const currentValue = await this.getCurrentValue(world); - - if (!this.value.compareTo(world, currentValue)) { - fail(world, `Static invariant broken! Expected ${this.toString()} to remain static value \`${this.value}\` but became \`${currentValue}\``); - } - } - - toString() { - return `StaticInvariant: condition=${formatEvent(this.condition)}, value=${this.value.toString()}`; - } -} diff --git a/scenario/src/Invariant/SuccessInvariant.ts b/scenario/src/Invariant/SuccessInvariant.ts deleted file mode 100644 index 9abd2b49e..000000000 --- a/scenario/src/Invariant/SuccessInvariant.ts +++ /dev/null @@ -1,21 +0,0 @@ -import {Invariant} from '../Invariant'; -import {fail, World} from '../World'; -import {getCoreValue} from '../CoreValue'; -import {Value} from '../Value'; -import {Event} from '../Event'; - -export class SuccessInvariant implements Invariant { - held = false; - - constructor() {} - - async checker(world: World): Promise { - if (world.lastInvokation && !world.lastInvokation.success()) { - fail(world, `Success invariant broken! Expected successful execution, but had error ${world.lastInvokation.toString()}`); - } - } - - toString() { - return `SuccessInvariant`; - } -} diff --git a/scenario/src/Invokation.ts b/scenario/src/Invokation.ts deleted file mode 100644 index 0c7dd6ff8..000000000 --- a/scenario/src/Invokation.ts +++ /dev/null @@ -1,320 +0,0 @@ -import { ErrorReporter, NoErrorReporter, ComptrollerErrorReporter } from './ErrorReporter'; -import { mustArray } from './Utils'; -import { World } from './World'; -import { encodedNumber } from './Encoding'; -import { TransactionReceipt } from 'web3-eth'; - -const errorRegex = /^(.*) \((\d+)\)$/ - -function getErrorCode(revertMessage: string): [string, number] | null { - let res = errorRegex.exec(revertMessage); - - if (res) { - return [res[1], Number(res[2])]; - } else { - return null; - } -} - -export interface InvokationOpts { - from?: string, - gas?: number, - gasPrice?: number -} - -export class InvokationError extends Error { - err: Error - // function : string - // arguments : {[]} - - constructor(err: Error) { - super(err.message); - this.err = err; - } - - toString() { - return `InvokationError`; - } -} - -export class InvokationRevertFailure extends InvokationError { - errCode: number - error: string | null - errMessage: string - - constructor(err: Error, errMessage: string, errCode: number, error: string | null) { - super(err); - - this.errMessage = errMessage; - this.errCode = errCode; - this.error = error; - } - - toString() { - return `InvokationRevertError`; - } -} - -interface CustomErrorResult { - return: string - error: string -} - -export class InvokationRevertCustomError extends InvokationError { - errCode: number - errorResults: {[address: string]: CustomErrorResult} - - constructor(err: Error, errorResults: {[address: string]: CustomErrorResult}) { - super(err); - - this.errorResults = errorResults; - } - - toString() { - return `InvokationRevertCustomError`; - } -} - -interface Argument { - name: string - type: string -} - -interface Method { - name: string - inputs: Argument[] -} - -export interface Callable { - estimateGas: (InvokationOpts?) => Promise - call: (InvokationOpts?) => Promise - _method: Method - arguments: any[] -} - -export interface Sendable extends Callable { - send: (InvokationOpts) => Promise -} - -export class Failure { - error: string - info: string - detail: string - - constructor(error: string, info: string, detail: string) { - this.error = error; - this.info = info; - this.detail = detail; - } - - toString(): string { - return `Failure`; - } - - equals(other: Failure): boolean { - return ( - this.error === other.error && - this.info === other.info && - this.detail === other.detail - ); - } -} - -export class Invokation { - value: T | null - receipt: TransactionReceipt | null - error: Error | null - failures: Failure[] - method: string | null - args: { arg: string, val: any }[] - errorReporter: ErrorReporter - - constructor(value: T | null, receipt: TransactionReceipt | null, error: Error | null, fn: Callable | null, errorReporter: ErrorReporter=NoErrorReporter) { - this.value = value; - this.receipt = receipt; - this.error = error; - this.errorReporter = errorReporter; - - if (fn !== null) { - this.method = fn._method.name; - this.args = fn.arguments.map((argument, i) => ({ arg: fn._method.inputs[i].name, val: argument })); - } else { - this.method = null; - this.args = []; - } - - if (receipt !== null && receipt.events && receipt.events["Failure"]) { - const failures = mustArray(receipt.events["Failure"]); - - this.failures = failures.map((failure) => { - const { 'error': errorVal, 'info': infoVal, 'detail': detailVal } = failure.returnValues; - - return new Failure( - errorReporter.getError(errorVal) || `unknown error=${errorVal}`, - errorReporter.getInfo(infoVal) || `unknown info=${infoVal}`, - errorReporter.getDetail(errorVal, detailVal) - ); - }); - } else { - this.failures = []; - } - } - - success(): boolean { - return ( - this.error === null && this.failures.length === 0 - ); - } - - invokation(): string { - if (this.method) { - let argStr = this.args.map(({ arg, val }) => `${arg}=${val.toString()}`).join(','); - return `"${this.method}(${argStr})"`; - } else { - return `unknown method`; - } - } - - toString(): string { - return `Invokation<${this.invokation()}, tx=${this.receipt ? this.receipt.transactionHash : ''}, value=${this.value ? (this.value).toString() : ''}, error=${this.error}, failures=${this.failures.toString()}>`; - } -} - -export async function fallback(world: World, from: string, to: string, value: encodedNumber): Promise> { - let trxObj = { - from: from, - to: to, - value: value.toString() - }; - - let estimateGas = async (opts: InvokationOpts) => { - let trxObjMerged = { - ...trxObj, - ...opts - }; - - return await world.web3.eth.estimateGas(trxObjMerged); - }; - - let call = async (opts: InvokationOpts) => { - let trxObjMerged = { - ...trxObj, - ...opts - }; - - return await world.web3.eth.call(trxObjMerged); - }; - - let send = async (opts: InvokationOpts) => { - let trxObjMerged = { - ...trxObj, - ...opts - }; - - let receipt = await world.web3.eth.sendTransaction(trxObjMerged); - receipt.events = {}; - - return receipt; - } - - let fn: Sendable = { - estimateGas: estimateGas, - call: call, - send: send, - _method: { - name: "fallback", - inputs: [] - }, - arguments: [] - } - - return invoke(world, fn, from, NoErrorReporter); -} - -export async function invoke(world: World, fn: Sendable, from: string, errorReporter: ErrorReporter = NoErrorReporter): Promise> { - let value: T | null = null; - let result: TransactionReceipt | null = null; - let worldInvokationOpts = world.getInvokationOpts({from: from}); - let trxInvokationOpts = world.trxInvokationOpts.toJS(); - - let invokationOpts = { - ...worldInvokationOpts, - ...trxInvokationOpts - }; - - if (world.totalGas) { - invokationOpts = { - ...invokationOpts, - gas: world.totalGas - } - } else { - try { - const gas = await fn.estimateGas({ ...invokationOpts }); - invokationOpts = { - ...invokationOpts, - gas: gas * 2 - }; - } catch (e) { - invokationOpts = { - ...invokationOpts, - gas: 2000000 - }; - } - } - - try { - let error: null | Error = null; - - try { - value = await fn.call({ ...invokationOpts }); - } catch (err) { - error = new InvokationError(err); - } - - if (world.dryRun) { - world.printer.printLine(`Dry run: invoking \`${fn._method.name}\``); - // XXXS - result = { - blockNumber: -1, - transactionHash: '0x', - gasUsed: 0, - events: {} - }; - } else { - result = await fn.send({ ...invokationOpts }); - world.gasCounter.value += result.gasUsed; - } - - if (world.settings.printTxLogs) { - const eventLogs = Object.values(result && result.events || {}).map((event: any) => { - const eventLog = event.raw; - if (eventLog) { - const eventDecoder = world.eventDecoder[eventLog.topics[0]]; - if (eventDecoder) { - return eventDecoder(eventLog); - } else { - return eventLog; - } - } - }); - console.log('EMITTED EVENTS: ', eventLogs); - } - - return new Invokation(value, result, null, fn, errorReporter); - } catch (err) { - if (errorReporter) { - let decoded = getErrorCode(err.message); - - if (decoded) { - let [errMessage, errCode] = decoded; - - return new Invokation(value, result, new InvokationRevertFailure(err, errMessage, errCode, errorReporter.getError(errCode)), fn, errorReporter); - } - if (err.results) { - return new Invokation(value, result, new InvokationRevertCustomError(err, err.results), fn, errorReporter); - } - } - - return new Invokation(value, result, new InvokationError(err), fn, errorReporter); - } -} diff --git a/scenario/src/Macro.ts b/scenario/src/Macro.ts deleted file mode 100644 index a0a686733..000000000 --- a/scenario/src/Macro.ts +++ /dev/null @@ -1,98 +0,0 @@ -import {Event} from './Event'; - -interface Arg { - arg: any - def: any - splat: any -} - -interface Macro { - args: Arg[] - steps: Event -} - -type ArgMap = {[arg: string]: Event}; -type NamedArg = { argName: string, argValue: Event }; -type ArgValue = Event | NamedArg; - -export type Macros = {[eventName: string]: Macro}; - -export function expandEvent(macros: Macros, event: Event): Event[] { - const [eventName, ...eventArgs] = event; - - if (macros[eventName]) { - let expanded = expandMacro(macros[eventName], eventArgs); - - // Recursively expand steps - return expanded.map(event => expandEvent(macros, event)).flat(); - } else { - return [event]; - } -} - -function getArgValues(eventArgs: ArgValue[], macroArgs: Arg[]): ArgMap { - const eventArgNameMap: ArgMap = {}; - const eventArgIndexed: Event[] = []; - const argValues: ArgMap = {}; - let usedNamedArg: boolean = false; - let usedSplat: boolean = false; - - eventArgs.forEach((eventArg) => { - if (eventArg.hasOwnProperty('argName')) { - const {argName, argValue} = eventArg; - - eventArgNameMap[argName] = argValue; - usedNamedArg = true; - } else { - if (usedNamedArg) { - throw new Error("Cannot use positional arg after named arg in macro invokation."); - } - - eventArgIndexed.push(eventArg); - } - }); - - macroArgs.forEach(({arg, def, splat}, argIndex) => { - let val; - - if (usedSplat) { - throw new Error("Cannot have arg after splat arg"); - } - - if (eventArgNameMap[arg] !== undefined) { - val = eventArgNameMap[arg]; - } else if (splat) { - val = eventArgIndexed.slice(argIndex); - usedSplat = true; - } else if (eventArgIndexed[argIndex] !== undefined) { - val = eventArgIndexed[argIndex]; - } else if (def !== undefined) { - val = def; - } else { - throw new Error("Macro cannot find arg value for " + arg); - } - argValues[arg] = val; - }); - - return argValues; -} - -export function expandMacro(macro: Macro, event: Event): Event[] { - const argValues = getArgValues(event, macro.args); - - function expandStep(step) { - return step.map((token) => { - if (argValues[token] !== undefined) { - return argValues[token]; - } else { - if (Array.isArray(token)) { - return expandStep(token); - } else { - return token; - } - } - }); - }; - - return macro.steps.map(expandStep); -} diff --git a/scenario/src/Networks.ts b/scenario/src/Networks.ts deleted file mode 100644 index b241fc870..000000000 --- a/scenario/src/Networks.ts +++ /dev/null @@ -1,202 +0,0 @@ -import { fromJS, Map } from 'immutable'; -import { World } from './World'; -import { Invokation } from './Invokation'; -import { Contract, setContractName } from './Contract'; -import { getNetworkPath, readFile, writeFile } from './File'; -import { AbiItem } from 'web3-utils'; - -type Networks = Map; - -interface ExtraData { - index: string[]; - data: object | string | number; -} - -export function parseNetworkFile(data: string | object): Networks { - return fromJS(typeof data === 'string' ? JSON.parse(data) : data); -} - -function serializeNetworkFile(networks: Networks): string { - return JSON.stringify(networks.toJSON(), null, 4); -} - -function readNetworkFile(world: World, isABI: boolean): Promise { - return readFile( - world, - getNetworkPath(world.basePath, world.network, isABI ? '-abi' : ''), - Map({}), - parseNetworkFile - ); -} - -function writeNetworkFile(world: World, networks: Networks, isABI: boolean): Promise { - return writeFile( - world, - getNetworkPath(world.basePath, world.network, isABI ? '-abi' : ''), - serializeNetworkFile(networks) - ); -} - -export function storeContract(world: World, contract: Contract, name: string, extraData: ExtraData[]): World { - contract = setContractName(name, contract); - - world = world.set('lastContract', contract); - world = world.setIn(['contractIndex', contract._address.toLowerCase()], contract); - world = updateEventDecoder(world, contract); - - world = world.update('contractData', contractData => { - return extraData.reduce((acc, { index, data }) => { - if (typeof data !== 'string' && typeof data !== 'number') { - // Store extra data as an immutable - data = Map(data); - } - - return acc.setIn(index, data); - }, contractData); - }); - - return world; -} - -export async function saveContract( - world: World, - contract: Contract, - name: string, - extraData: ExtraData[] -): Promise { - let networks = await readNetworkFile(world, false); - let networksABI = await readNetworkFile(world, true); - - networks = extraData.reduce((acc, { index, data }) => acc.setIn(index, data), networks); - networksABI = networksABI.set(name, contract._jsonInterface); - - // Don't write during a dry-run - if (!world.dryRun) { - world = await writeNetworkFile(world, networks, false); - world = await writeNetworkFile(world, networksABI, true); - } - - return world; -} - -// Merges a contract into another, which is important for delegation -export async function mergeContractABI( - world: World, - targetName: string, - contractTarget: Contract, - a: string, - b: string -): Promise { - let networks = await readNetworkFile(world, false); - let networksABI = await readNetworkFile(world, true); - let aABI = networksABI.get(a); - let bABI = networksABI.get(b); - - if (!aABI) { - throw new Error(`Missing contract ABI for ${a}`); - } - - if (!bABI) { - throw new Error(`Missing contract ABI for ${b}`); - } - - const itemBySig: { [key: string]: AbiItem } = {}; - for (let item of aABI.toJS().concat(bABI.toJS())) { - itemBySig[item.signature] = item; - } - const fullABI = Object.values(itemBySig); - - // Store Comptroller address - networks = networks.setIn(['Contracts', targetName], contractTarget._address); - world = world.setIn(['contractData', 'Contracts', targetName], contractTarget._address); - - networksABI = networksABI.set(targetName, fullABI); - - let mergedContract = new world.web3.eth.Contract(fullABI, contractTarget._address, {}); - - /// XXXS - world = world.setIn( - ['contractIndex', contractTarget._address.toLowerCase()], - setContractName(targetName, mergedContract) - ); - - // Don't write during a dry-run - if (!world.dryRun) { - world = await writeNetworkFile(world, networks, false); - world = await writeNetworkFile(world, networksABI, true); - } - - return world; -} - -export async function loadContracts(world: World): Promise<[World, string[]]> { - let networks = await readNetworkFile(world, false); - let networksABI = await readNetworkFile(world, true); - - return loadContractData(world, networks, networksABI); -} - -function updateEventDecoder(world: World, contract: any) { - const updatedEventDecoder = contract._jsonInterface - .filter(i => i.type == 'event') - .reduce((accum, event) => { - const { anonymous, inputs, signature } = event; - return { - ...accum, - [signature]: log => { - let argTopics = anonymous ? log.topics : log.topics.slice(1); - return world.web3.eth.abi.decodeLog(inputs, log.data, argTopics); - } - }; - }, world.eventDecoder); - - return world.set('eventDecoder', updatedEventDecoder) -} - -export async function loadContractData( - world: World, - networks: Networks, - networksABI: Networks -): Promise<[World, string[]]> { - // Pull off contracts value and the rest is "extra" - let contractInfo: string[] = []; - let contracts = networks.get('Contracts') || Map({}); - - world = contracts.reduce((world: World, address: string, name: string) => { - let abi: AbiItem[] = networksABI.has(name) ? networksABI.get(name).toJS() : []; - let contract = new world.web3.eth.Contract(abi, address, {}); - - world = updateEventDecoder(world, contract); - - contractInfo.push(`${name}: ${address}`); - - // Store the contract - // XXXS - return world.setIn(['contractIndex', (contract)._address.toLowerCase()], setContractName(name, contract)); - }, world); - - world = world.update('contractData', contractData => contractData.mergeDeep(networks)); - - return [world, contractInfo]; -} - -export async function storeAndSaveContract( - world: World, - contract: Contract, - name: string, - invokation: Invokation | null, - extraData: ExtraData[] -): Promise { - extraData.push({ index: ['Contracts', name], data: contract._address }); - if (contract.constructorAbi) { - extraData.push({ index: ['Constructors', name], data: contract.constructorAbi }); - } - if (invokation && invokation.receipt) { - extraData.push({ index: ['Blocks', name], data: invokation.receipt.blockNumber }); - } - - world = storeContract(world, contract, name, extraData); - world = await saveContract(world, contract, name, extraData); - - return world; -} diff --git a/scenario/src/Parser.ts b/scenario/src/Parser.ts deleted file mode 100644 index 1a8deab3a..000000000 --- a/scenario/src/Parser.ts +++ /dev/null @@ -1,3210 +0,0 @@ -// tslint:disable:only-arrow-functions -// tslint:disable:object-literal-shorthand -// tslint:disable:trailing-comma -// tslint:disable:object-literal-sort-keys -// tslint:disable:one-variable-per-declaration -// tslint:disable:max-line-length -// tslint:disable:no-consecutive-blank-lines -// tslint:disable:align - - -// Generated by PEG.js v. 0.10.0 (ts-pegjs plugin v. 0.2.2 ) -// -// https://pegjs.org/ https://github.com/metadevpro/ts-pegjs - -"use strict"; - -export interface IFilePosition { - offset: number; - line: number; - column: number; -} - -export interface IFileRange { - start: IFilePosition; - end: IFilePosition; -} - -export interface ILiteralExpectation { - type: "literal"; - text: string; - ignoreCase: boolean; -} - -export interface IClassParts extends Array {} - -export interface IClassExpectation { - type: "class"; - parts: IClassParts; - inverted: boolean; - ignoreCase: boolean; -} - -export interface IAnyExpectation { - type: "any"; -} - -export interface IEndExpectation { - type: "end"; -} - -export interface IOtherExpectation { - type: "other"; - description: string; -} - -export type Expectation = ILiteralExpectation | IClassExpectation | IAnyExpectation | IEndExpectation | IOtherExpectation; - -export class SyntaxError extends Error { - public static buildMessage(expected: Expectation[], found: string | null) { - function hex(ch: string): string { - return ch.charCodeAt(0).toString(16).toUpperCase(); - } - - function literalEscape(s: string): string { - return s - .replace(/\\/g, "\\\\") - .replace(/"/g, "\\\"") - .replace(/\0/g, "\\0") - .replace(/\t/g, "\\t") - .replace(/\n/g, "\\n") - .replace(/\r/g, "\\r") - .replace(/[\x00-\x0F]/g, (ch) => "\\x0" + hex(ch) ) - .replace(/[\x10-\x1F\x7F-\x9F]/g, (ch) => "\\x" + hex(ch) ); - } - - function classEscape(s: string): string { - return s - .replace(/\\/g, "\\\\") - .replace(/\]/g, "\\]") - .replace(/\^/g, "\\^") - .replace(/-/g, "\\-") - .replace(/\0/g, "\\0") - .replace(/\t/g, "\\t") - .replace(/\n/g, "\\n") - .replace(/\r/g, "\\r") - .replace(/[\x00-\x0F]/g, (ch) => "\\x0" + hex(ch) ) - .replace(/[\x10-\x1F\x7F-\x9F]/g, (ch) => "\\x" + hex(ch) ); - } - - function describeExpectation(expectation: Expectation) { - switch (expectation.type) { - case "literal": - return "\"" + literalEscape(expectation.text) + "\""; - case "class": - const escapedParts = expectation.parts.map((part) => { - return Array.isArray(part) - ? classEscape(part[0] as string) + "-" + classEscape(part[1] as string) - : classEscape(part); - }); - - return "[" + (expectation.inverted ? "^" : "") + escapedParts + "]"; - case "any": - return "any character"; - case "end": - return "end of input"; - case "other": - return expectation.description; - } - } - - function describeExpected(expected1: Expectation[]) { - const descriptions = expected1.map(describeExpectation); - let i; - let j; - - descriptions.sort(); - - if (descriptions.length > 0) { - for (i = 1, j = 1; i < descriptions.length; i++) { - if (descriptions[i - 1] !== descriptions[i]) { - descriptions[j] = descriptions[i]; - j++; - } - } - descriptions.length = j; - } - - switch (descriptions.length) { - case 1: - return descriptions[0]; - - case 2: - return descriptions[0] + " or " + descriptions[1]; - - default: - return descriptions.slice(0, -1).join(", ") - + ", or " - + descriptions[descriptions.length - 1]; - } - } - - function describeFound(found1: string | null) { - return found1 ? "\"" + literalEscape(found1) + "\"" : "end of input"; - } - - return "Expected " + describeExpected(expected) + " but " + describeFound(found) + " found."; - } - - public message: string; - public expected: Expectation[]; - public found: string | null; - public location: IFileRange; - public name: string; - - constructor(message: string, expected: Expectation[], found: string | null, location: IFileRange) { - super(); - this.message = message; - this.expected = expected; - this.found = found; - this.location = location; - this.name = "SyntaxError"; - - if (typeof (Error as any).captureStackTrace === "function") { - (Error as any).captureStackTrace(this, SyntaxError); - } - } -} - -export interface ICached { - nextPos: number; - result: any; -} - -function peg$parse(input: string, options?: IParseOptions) { - options = options !== undefined ? options : {}; - - const peg$FAILED = {}; - - const peg$startRuleFunctions: {[id: string]: any} = { tests: peg$parsetests, step: peg$parsestep, macros: peg$parsemacros }; - let peg$startRuleFunction: () => any = peg$parsetests; - - const peg$c0 = function(head: any, t: any) { return t; }; - const peg$c1 = function(head: any, tail: any) { return tail.reduce((acc, el) => addTopLevelEl(acc, el), addTopLevelEl({macros: {}, tests: {}}, head)); }; - const peg$c2 = function(values: any) { return values !== null ? values.tests : {}; }; - const peg$c3 = function(values: any) { return values !== null ? values.macros : {}; }; - const peg$c4 = "Test"; - const peg$c5 = peg$literalExpectation("Test", false); - const peg$c6 = function(name: any, steps: any) { return {type: 'test', test: getString(name), steps: steps}; }; - const peg$c7 = "GasTest"; - const peg$c8 = peg$literalExpectation("GasTest", false); - const peg$c9 = function(name: any, steps: any) { return {type: 'test', test: getString(name), steps: ["Gas"].concat(steps)}; }; - const peg$c10 = "Pending"; - const peg$c11 = peg$literalExpectation("Pending", false); - const peg$c12 = function(name: any, steps: any) { return {type: 'test', test: getString(name), steps: ["Pending"].concat(steps)}; }; - const peg$c13 = "Only"; - const peg$c14 = peg$literalExpectation("Only", false); - const peg$c15 = function(name: any, steps: any) { return {type: 'test', test: getString(name), steps: ["Only"].concat(steps)}; }; - const peg$c16 = "Skip"; - const peg$c17 = peg$literalExpectation("Skip", false); - const peg$c18 = function(name: any, steps: any) { return {type: 'test', test: getString(name), steps: ["Skip"].concat(steps)}; }; - const peg$c19 = "Macro"; - const peg$c20 = peg$literalExpectation("Macro", false); - const peg$c21 = function(name: any, args: any, steps: any) { return {type: 'macro', name: getString(name), args: args || [], steps: steps}; }; - const peg$c22 = function(head: any, tail: any) { return [head].concat(tail).filter((x) => !!x); }; - const peg$c23 = function(args: any) { return args !== null ? args.flat() : []; }; - const peg$c24 = "..."; - const peg$c25 = peg$literalExpectation("...", false); - const peg$c26 = "="; - const peg$c27 = peg$literalExpectation("=", false); - const peg$c28 = function(splat: any, arg: any, t: any) { return t; }; - const peg$c29 = function(splat: any, arg: any, def: any) { return { arg, def, splat }; }; - const peg$c30 = function(tokens: any) { return tokens !== null ? tokens.flat() : []; }; - const peg$c31 = function(head: any, step: any) { return step; }; - const peg$c32 = function(steps: any) { return steps !== null ? steps : []; }; - const peg$c33 = function(step: any) { return step; }; - const peg$c34 = function() { return null; }; - const peg$c35 = function(val: any) { return val; }; - const peg$c36 = function(head: any, value: any) { return value }; - const peg$c37 = function(head: any, tail: any) { return [head].concat(tail.flat(1)); }; - const peg$c38 = function(inner: any) { return [inner]; }; - const peg$c39 = function(inner: any) { return [["List"].concat((inner || []).flat())] }; - const peg$c40 = "--"; - const peg$c41 = peg$literalExpectation("--", false); - const peg$c42 = /^[^\n]/; - const peg$c43 = peg$classExpectation(["\n"], true, false); - const peg$c44 = "#"; - const peg$c45 = peg$literalExpectation("#", false); - const peg$c46 = ":"; - const peg$c47 = peg$literalExpectation(":", false); - const peg$c48 = function(token1: any, token2: any) { return {argName: token1, argValue: token2} }; - const peg$c49 = /^[A-Za-z0-9_]/; - const peg$c50 = peg$classExpectation([["A", "Z"], ["a", "z"], ["0", "9"], "_"], false, false); - const peg$c51 = function(t: any) { return t.join("") }; - const peg$c52 = "0x"; - const peg$c53 = peg$literalExpectation("0x", false); - const peg$c54 = /^[0-9a-fA-F]/; - const peg$c55 = peg$classExpectation([["0", "9"], ["a", "f"], ["A", "F"]], false, false); - const peg$c56 = function(hex: any) { return ["Hex", hex.flat().flat().join("")] }; - const peg$c57 = "-"; - const peg$c58 = peg$literalExpectation("-", false); - const peg$c59 = "+"; - const peg$c60 = peg$literalExpectation("+", false); - const peg$c61 = /^[0-9]/; - const peg$c62 = peg$classExpectation([["0", "9"]], false, false); - const peg$c63 = "."; - const peg$c64 = peg$literalExpectation(".", false); - const peg$c65 = "e"; - const peg$c66 = peg$literalExpectation("e", false); - const peg$c67 = function(n: any) { return ["Exactly", n.flat().flat().join("")] }; - const peg$c68 = function(head: any, tail: any) { return [head].concat(tail.flat()); }; - const peg$c69 = "("; - const peg$c70 = peg$literalExpectation("(", false); - const peg$c71 = ")"; - const peg$c72 = peg$literalExpectation(")", false); - const peg$c73 = "["; - const peg$c74 = peg$literalExpectation("[", false); - const peg$c75 = "]"; - const peg$c76 = peg$literalExpectation("]", false); - const peg$c77 = "\r"; - const peg$c78 = peg$literalExpectation("\r", false); - const peg$c79 = "\n"; - const peg$c80 = peg$literalExpectation("\n", false); - const peg$c81 = "\t"; - const peg$c82 = peg$literalExpectation("\t", false); - const peg$c83 = " "; - const peg$c84 = peg$literalExpectation(" ", false); - const peg$c85 = "\\"; - const peg$c86 = peg$literalExpectation("\\", false); - const peg$c87 = peg$otherExpectation("whitespace"); - const peg$c88 = /^[ \t]/; - const peg$c89 = peg$classExpectation([" ", "\t"], false, false); - const peg$c90 = /^[ \t\r\n]/; - const peg$c91 = peg$classExpectation([" ", "\t", "\r", "\n"], false, false); - const peg$c92 = peg$otherExpectation("string"); - const peg$c93 = function(chars: any) { return ["String", chars.join("")]; }; - const peg$c94 = "\""; - const peg$c95 = peg$literalExpectation("\"", false); - const peg$c96 = "/"; - const peg$c97 = peg$literalExpectation("/", false); - const peg$c98 = "b"; - const peg$c99 = peg$literalExpectation("b", false); - const peg$c100 = function() { return "\b"; }; - const peg$c101 = "f"; - const peg$c102 = peg$literalExpectation("f", false); - const peg$c103 = function() { return "\f"; }; - const peg$c104 = "n"; - const peg$c105 = peg$literalExpectation("n", false); - const peg$c106 = function() { return "\n"; }; - const peg$c107 = "r"; - const peg$c108 = peg$literalExpectation("r", false); - const peg$c109 = function() { return "\r"; }; - const peg$c110 = "t"; - const peg$c111 = peg$literalExpectation("t", false); - const peg$c112 = function() { return "\t"; }; - const peg$c113 = "u"; - const peg$c114 = peg$literalExpectation("u", false); - const peg$c115 = function(digits: any) { - return String.fromCharCode(parseInt(digits, 16)); - }; - const peg$c116 = function(sequence: any) { return sequence; }; - const peg$c117 = /^[^\0-\x1F"\\]/; - const peg$c118 = peg$classExpectation([["\0", "\x1F"], "\"", "\\"], true, false); - const peg$c119 = /^[0-9a-f]/i; - const peg$c120 = peg$classExpectation([["0", "9"], ["a", "f"]], false, true); - - let peg$currPos = 0; - let peg$savedPos = 0; - const peg$posDetailsCache = [{ line: 1, column: 1 }]; - let peg$maxFailPos = 0; - let peg$maxFailExpected: any[] = []; - let peg$silentFails = 0; - - const peg$resultsCache: {[id: number]: ICached} = {}; - - let peg$result; - - if (options.startRule !== undefined) { - if (!(options.startRule in peg$startRuleFunctions)) { - throw new Error("Can't start parsing from rule \"" + options.startRule + "\"."); - } - - peg$startRuleFunction = peg$startRuleFunctions[options.startRule]; - } - - function text(): string { - return input.substring(peg$savedPos, peg$currPos); - } - - function location(): IFileRange { - return peg$computeLocation(peg$savedPos, peg$currPos); - } - - function expected(description: string, location1?: IFileRange) { - location1 = location1 !== undefined - ? location1 - : peg$computeLocation(peg$savedPos, peg$currPos); - - throw peg$buildStructuredError( - [peg$otherExpectation(description)], - input.substring(peg$savedPos, peg$currPos), - location1 - ); - } - - function error(message: string, location1?: IFileRange) { - location1 = location1 !== undefined - ? location1 - : peg$computeLocation(peg$savedPos, peg$currPos); - - throw peg$buildSimpleError(message, location1); - } - - function peg$literalExpectation(text1: string, ignoreCase: boolean): ILiteralExpectation { - return { type: "literal", text: text1, ignoreCase: ignoreCase }; - } - - function peg$classExpectation(parts: IClassParts, inverted: boolean, ignoreCase: boolean): IClassExpectation { - return { type: "class", parts: parts, inverted: inverted, ignoreCase: ignoreCase }; - } - - function peg$anyExpectation(): IAnyExpectation { - return { type: "any" }; - } - - function peg$endExpectation(): IEndExpectation { - return { type: "end" }; - } - - function peg$otherExpectation(description: string): IOtherExpectation { - return { type: "other", description: description }; - } - - function peg$computePosDetails(pos: number) { - let details = peg$posDetailsCache[pos]; - let p; - - if (details) { - return details; - } else { - p = pos - 1; - while (!peg$posDetailsCache[p]) { - p--; - } - - details = peg$posDetailsCache[p]; - details = { - line: details.line, - column: details.column - }; - - while (p < pos) { - if (input.charCodeAt(p) === 10) { - details.line++; - details.column = 1; - } else { - details.column++; - } - - p++; - } - - peg$posDetailsCache[pos] = details; - - return details; - } - } - - function peg$computeLocation(startPos: number, endPos: number): IFileRange { - const startPosDetails = peg$computePosDetails(startPos); - const endPosDetails = peg$computePosDetails(endPos); - - return { - start: { - offset: startPos, - line: startPosDetails.line, - column: startPosDetails.column - }, - end: { - offset: endPos, - line: endPosDetails.line, - column: endPosDetails.column - } - }; - } - - function peg$fail(expected1: Expectation) { - if (peg$currPos < peg$maxFailPos) { return; } - - if (peg$currPos > peg$maxFailPos) { - peg$maxFailPos = peg$currPos; - peg$maxFailExpected = []; - } - - peg$maxFailExpected.push(expected1); - } - - function peg$buildSimpleError(message: string, location1: IFileRange) { - return new SyntaxError(message, [], "", location1); - } - - function peg$buildStructuredError(expected1: Expectation[], found: string | null, location1: IFileRange) { - return new SyntaxError( - SyntaxError.buildMessage(expected1, found), - expected1, - found, - location1 - ); - } - - function peg$parsetests(): any { - let s0, s1, s2, s3, s4, s5, s6; - - const key = peg$currPos * 38 + 0; - const cached: ICached = peg$resultsCache[key]; - - if (cached) { - peg$currPos = cached.nextPos; - - return cached.result; - } - - s0 = peg$currPos; - s1 = peg$currPos; - s2 = peg$parsetop_level_el(); - if (s2 !== peg$FAILED) { - s3 = []; - s4 = peg$currPos; - s5 = peg$parseline_separator(); - if (s5 !== peg$FAILED) { - s6 = peg$parsetop_level_el(); - if (s6 !== peg$FAILED) { - peg$savedPos = s4; - s5 = peg$c0(s2, s6); - s4 = s5; - } else { - peg$currPos = s4; - s4 = peg$FAILED; - } - } else { - peg$currPos = s4; - s4 = peg$FAILED; - } - while (s4 !== peg$FAILED) { - s3.push(s4); - s4 = peg$currPos; - s5 = peg$parseline_separator(); - if (s5 !== peg$FAILED) { - s6 = peg$parsetop_level_el(); - if (s6 !== peg$FAILED) { - peg$savedPos = s4; - s5 = peg$c0(s2, s6); - s4 = s5; - } else { - peg$currPos = s4; - s4 = peg$FAILED; - } - } else { - peg$currPos = s4; - s4 = peg$FAILED; - } - } - if (s3 !== peg$FAILED) { - peg$savedPos = s1; - s2 = peg$c1(s2, s3); - s1 = s2; - } else { - peg$currPos = s1; - s1 = peg$FAILED; - } - } else { - peg$currPos = s1; - s1 = peg$FAILED; - } - if (s1 === peg$FAILED) { - s1 = null; - } - if (s1 !== peg$FAILED) { - s2 = peg$parsefull_ws(); - if (s2 !== peg$FAILED) { - peg$savedPos = s0; - s1 = peg$c2(s1); - s0 = s1; - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - - peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; - - return s0; - } - - function peg$parsemacros(): any { - let s0, s1, s2, s3, s4, s5, s6; - - const key = peg$currPos * 38 + 1; - const cached: ICached = peg$resultsCache[key]; - - if (cached) { - peg$currPos = cached.nextPos; - - return cached.result; - } - - s0 = peg$currPos; - s1 = peg$currPos; - s2 = peg$parsetop_level_el(); - if (s2 !== peg$FAILED) { - s3 = []; - s4 = peg$currPos; - s5 = peg$parseline_separator(); - if (s5 !== peg$FAILED) { - s6 = peg$parsetop_level_el(); - if (s6 !== peg$FAILED) { - peg$savedPos = s4; - s5 = peg$c0(s2, s6); - s4 = s5; - } else { - peg$currPos = s4; - s4 = peg$FAILED; - } - } else { - peg$currPos = s4; - s4 = peg$FAILED; - } - while (s4 !== peg$FAILED) { - s3.push(s4); - s4 = peg$currPos; - s5 = peg$parseline_separator(); - if (s5 !== peg$FAILED) { - s6 = peg$parsetop_level_el(); - if (s6 !== peg$FAILED) { - peg$savedPos = s4; - s5 = peg$c0(s2, s6); - s4 = s5; - } else { - peg$currPos = s4; - s4 = peg$FAILED; - } - } else { - peg$currPos = s4; - s4 = peg$FAILED; - } - } - if (s3 !== peg$FAILED) { - peg$savedPos = s1; - s2 = peg$c1(s2, s3); - s1 = s2; - } else { - peg$currPos = s1; - s1 = peg$FAILED; - } - } else { - peg$currPos = s1; - s1 = peg$FAILED; - } - if (s1 === peg$FAILED) { - s1 = null; - } - if (s1 !== peg$FAILED) { - s2 = peg$parsefull_ws(); - if (s2 !== peg$FAILED) { - peg$savedPos = s0; - s1 = peg$c3(s1); - s0 = s1; - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - - peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; - - return s0; - } - - function peg$parsetop_level_el(): any { - let s0; - - const key = peg$currPos * 38 + 2; - const cached: ICached = peg$resultsCache[key]; - - if (cached) { - peg$currPos = cached.nextPos; - - return cached.result; - } - - s0 = peg$parsetest(); - if (s0 === peg$FAILED) { - s0 = peg$parsemacro(); - if (s0 === peg$FAILED) { - s0 = peg$parsegastest(); - if (s0 === peg$FAILED) { - s0 = peg$parsepending(); - if (s0 === peg$FAILED) { - s0 = peg$parseonly(); - if (s0 === peg$FAILED) { - s0 = peg$parseskip(); - } - } - } - } - } - - peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; - - return s0; - } - - function peg$parsetest(): any { - let s0, s1, s2, s3, s4, s5, s6, s7; - - const key = peg$currPos * 38 + 3; - const cached: ICached = peg$resultsCache[key]; - - if (cached) { - peg$currPos = cached.nextPos; - - return cached.result; - } - - s0 = peg$currPos; - s1 = peg$parsefull_ws(); - if (s1 === peg$FAILED) { - s1 = null; - } - if (s1 !== peg$FAILED) { - if (input.substr(peg$currPos, 4) === peg$c4) { - s2 = peg$c4; - peg$currPos += 4; - } else { - s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c5); } - } - if (s2 !== peg$FAILED) { - s3 = peg$parsews(); - if (s3 !== peg$FAILED) { - s4 = peg$parsestring(); - if (s4 !== peg$FAILED) { - s5 = peg$parsews(); - if (s5 !== peg$FAILED) { - s6 = peg$parseline_separator(); - if (s6 !== peg$FAILED) { - s7 = peg$parsesteps(); - if (s7 === peg$FAILED) { - s7 = null; - } - if (s7 !== peg$FAILED) { - peg$savedPos = s0; - s1 = peg$c6(s4, s7); - s0 = s1; - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - - peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; - - return s0; - } - - function peg$parsegastest(): any { - let s0, s1, s2, s3, s4, s5, s6, s7; - - const key = peg$currPos * 38 + 4; - const cached: ICached = peg$resultsCache[key]; - - if (cached) { - peg$currPos = cached.nextPos; - - return cached.result; - } - - s0 = peg$currPos; - s1 = peg$parsefull_ws(); - if (s1 === peg$FAILED) { - s1 = null; - } - if (s1 !== peg$FAILED) { - if (input.substr(peg$currPos, 7) === peg$c7) { - s2 = peg$c7; - peg$currPos += 7; - } else { - s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c8); } - } - if (s2 !== peg$FAILED) { - s3 = peg$parsews(); - if (s3 !== peg$FAILED) { - s4 = peg$parsestring(); - if (s4 !== peg$FAILED) { - s5 = peg$parsews(); - if (s5 !== peg$FAILED) { - s6 = peg$parseline_separator(); - if (s6 !== peg$FAILED) { - s7 = peg$parsesteps(); - if (s7 === peg$FAILED) { - s7 = null; - } - if (s7 !== peg$FAILED) { - peg$savedPos = s0; - s1 = peg$c9(s4, s7); - s0 = s1; - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - - peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; - - return s0; - } - - function peg$parsepending(): any { - let s0, s1, s2, s3, s4, s5, s6, s7; - - const key = peg$currPos * 38 + 5; - const cached: ICached = peg$resultsCache[key]; - - if (cached) { - peg$currPos = cached.nextPos; - - return cached.result; - } - - s0 = peg$currPos; - s1 = peg$parsefull_ws(); - if (s1 === peg$FAILED) { - s1 = null; - } - if (s1 !== peg$FAILED) { - if (input.substr(peg$currPos, 7) === peg$c10) { - s2 = peg$c10; - peg$currPos += 7; - } else { - s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c11); } - } - if (s2 !== peg$FAILED) { - s3 = peg$parsews(); - if (s3 !== peg$FAILED) { - s4 = peg$parsestring(); - if (s4 !== peg$FAILED) { - s5 = peg$parsews(); - if (s5 !== peg$FAILED) { - s6 = peg$parseline_separator(); - if (s6 !== peg$FAILED) { - s7 = peg$parsesteps(); - if (s7 === peg$FAILED) { - s7 = null; - } - if (s7 !== peg$FAILED) { - peg$savedPos = s0; - s1 = peg$c12(s4, s7); - s0 = s1; - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - - peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; - - return s0; - } - - function peg$parseonly(): any { - let s0, s1, s2, s3, s4, s5, s6, s7; - - const key = peg$currPos * 38 + 6; - const cached: ICached = peg$resultsCache[key]; - - if (cached) { - peg$currPos = cached.nextPos; - - return cached.result; - } - - s0 = peg$currPos; - s1 = peg$parsefull_ws(); - if (s1 === peg$FAILED) { - s1 = null; - } - if (s1 !== peg$FAILED) { - if (input.substr(peg$currPos, 4) === peg$c13) { - s2 = peg$c13; - peg$currPos += 4; - } else { - s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c14); } - } - if (s2 !== peg$FAILED) { - s3 = peg$parsews(); - if (s3 !== peg$FAILED) { - s4 = peg$parsestring(); - if (s4 !== peg$FAILED) { - s5 = peg$parsews(); - if (s5 !== peg$FAILED) { - s6 = peg$parseline_separator(); - if (s6 !== peg$FAILED) { - s7 = peg$parsesteps(); - if (s7 === peg$FAILED) { - s7 = null; - } - if (s7 !== peg$FAILED) { - peg$savedPos = s0; - s1 = peg$c15(s4, s7); - s0 = s1; - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - - peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; - - return s0; - } - - function peg$parseskip(): any { - let s0, s1, s2, s3, s4, s5, s6, s7; - - const key = peg$currPos * 38 + 7; - const cached: ICached = peg$resultsCache[key]; - - if (cached) { - peg$currPos = cached.nextPos; - - return cached.result; - } - - s0 = peg$currPos; - s1 = peg$parsefull_ws(); - if (s1 === peg$FAILED) { - s1 = null; - } - if (s1 !== peg$FAILED) { - if (input.substr(peg$currPos, 4) === peg$c16) { - s2 = peg$c16; - peg$currPos += 4; - } else { - s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c17); } - } - if (s2 !== peg$FAILED) { - s3 = peg$parsews(); - if (s3 !== peg$FAILED) { - s4 = peg$parsestring(); - if (s4 !== peg$FAILED) { - s5 = peg$parsews(); - if (s5 !== peg$FAILED) { - s6 = peg$parseline_separator(); - if (s6 !== peg$FAILED) { - s7 = peg$parsesteps(); - if (s7 === peg$FAILED) { - s7 = null; - } - if (s7 !== peg$FAILED) { - peg$savedPos = s0; - s1 = peg$c18(s4, s7); - s0 = s1; - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - - peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; - - return s0; - } - - function peg$parsemacro(): any { - let s0, s1, s2, s3, s4, s5, s6, s7, s8; - - const key = peg$currPos * 38 + 8; - const cached: ICached = peg$resultsCache[key]; - - if (cached) { - peg$currPos = cached.nextPos; - - return cached.result; - } - - s0 = peg$currPos; - s1 = peg$parsefull_ws(); - if (s1 === peg$FAILED) { - s1 = null; - } - if (s1 !== peg$FAILED) { - if (input.substr(peg$currPos, 5) === peg$c19) { - s2 = peg$c19; - peg$currPos += 5; - } else { - s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c20); } - } - if (s2 !== peg$FAILED) { - s3 = peg$parsews(); - if (s3 !== peg$FAILED) { - s4 = peg$parsetoken(); - if (s4 !== peg$FAILED) { - s5 = peg$parsews(); - if (s5 !== peg$FAILED) { - s6 = peg$parseargs(); - if (s6 === peg$FAILED) { - s6 = null; - } - if (s6 !== peg$FAILED) { - s7 = peg$parseline_separator(); - if (s7 !== peg$FAILED) { - s8 = peg$parsesteps(); - if (s8 !== peg$FAILED) { - peg$savedPos = s0; - s1 = peg$c21(s4, s6, s8); - s0 = s1; - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - - peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; - - return s0; - } - - function peg$parseargs(): any { - let s0, s1, s2, s3, s4, s5, s6; - - const key = peg$currPos * 38 + 9; - const cached: ICached = peg$resultsCache[key]; - - if (cached) { - peg$currPos = cached.nextPos; - - return cached.result; - } - - s0 = peg$currPos; - s1 = peg$currPos; - s2 = peg$parsearg(); - if (s2 !== peg$FAILED) { - s3 = []; - s4 = peg$currPos; - s5 = peg$parsews(); - if (s5 !== peg$FAILED) { - s6 = peg$parseargs(); - if (s6 !== peg$FAILED) { - peg$savedPos = s4; - s5 = peg$c0(s2, s6); - s4 = s5; - } else { - peg$currPos = s4; - s4 = peg$FAILED; - } - } else { - peg$currPos = s4; - s4 = peg$FAILED; - } - while (s4 !== peg$FAILED) { - s3.push(s4); - s4 = peg$currPos; - s5 = peg$parsews(); - if (s5 !== peg$FAILED) { - s6 = peg$parseargs(); - if (s6 !== peg$FAILED) { - peg$savedPos = s4; - s5 = peg$c0(s2, s6); - s4 = s5; - } else { - peg$currPos = s4; - s4 = peg$FAILED; - } - } else { - peg$currPos = s4; - s4 = peg$FAILED; - } - } - if (s3 !== peg$FAILED) { - peg$savedPos = s1; - s2 = peg$c22(s2, s3); - s1 = s2; - } else { - peg$currPos = s1; - s1 = peg$FAILED; - } - } else { - peg$currPos = s1; - s1 = peg$FAILED; - } - if (s1 !== peg$FAILED) { - peg$savedPos = s0; - s1 = peg$c23(s1); - } - s0 = s1; - - peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; - - return s0; - } - - function peg$parsearg(): any { - let s0, s1, s2, s3, s4, s5, s6, s7; - - const key = peg$currPos * 38 + 10; - const cached: ICached = peg$resultsCache[key]; - - if (cached) { - peg$currPos = cached.nextPos; - - return cached.result; - } - - s0 = peg$currPos; - if (input.substr(peg$currPos, 3) === peg$c24) { - s1 = peg$c24; - peg$currPos += 3; - } else { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c25); } - } - if (s1 === peg$FAILED) { - s1 = null; - } - if (s1 !== peg$FAILED) { - s2 = peg$parsetoken(); - if (s2 !== peg$FAILED) { - s3 = peg$currPos; - s4 = peg$parsews(); - if (s4 === peg$FAILED) { - s4 = null; - } - if (s4 !== peg$FAILED) { - if (input.charCodeAt(peg$currPos) === 61) { - s5 = peg$c26; - peg$currPos++; - } else { - s5 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c27); } - } - if (s5 !== peg$FAILED) { - s6 = peg$parsetoken(); - if (s6 !== peg$FAILED) { - s7 = peg$parsews(); - if (s7 === peg$FAILED) { - s7 = null; - } - if (s7 !== peg$FAILED) { - peg$savedPos = s3; - s4 = peg$c28(s1, s2, s6); - s3 = s4; - } else { - peg$currPos = s3; - s3 = peg$FAILED; - } - } else { - peg$currPos = s3; - s3 = peg$FAILED; - } - } else { - peg$currPos = s3; - s3 = peg$FAILED; - } - } else { - peg$currPos = s3; - s3 = peg$FAILED; - } - if (s3 === peg$FAILED) { - s3 = null; - } - if (s3 !== peg$FAILED) { - peg$savedPos = s0; - s1 = peg$c29(s1, s2, s3); - s0 = s1; - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - - peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; - - return s0; - } - - function peg$parsetoken_set(): any { - let s0, s1, s2, s3, s4, s5, s6; - - const key = peg$currPos * 38 + 11; - const cached: ICached = peg$resultsCache[key]; - - if (cached) { - peg$currPos = cached.nextPos; - - return cached.result; - } - - s0 = peg$currPos; - s1 = peg$currPos; - s2 = peg$parsetoken(); - if (s2 !== peg$FAILED) { - s3 = []; - s4 = peg$currPos; - s5 = peg$parsews(); - if (s5 !== peg$FAILED) { - s6 = peg$parsetoken_set(); - if (s6 !== peg$FAILED) { - peg$savedPos = s4; - s5 = peg$c0(s2, s6); - s4 = s5; - } else { - peg$currPos = s4; - s4 = peg$FAILED; - } - } else { - peg$currPos = s4; - s4 = peg$FAILED; - } - while (s4 !== peg$FAILED) { - s3.push(s4); - s4 = peg$currPos; - s5 = peg$parsews(); - if (s5 !== peg$FAILED) { - s6 = peg$parsetoken_set(); - if (s6 !== peg$FAILED) { - peg$savedPos = s4; - s5 = peg$c0(s2, s6); - s4 = s5; - } else { - peg$currPos = s4; - s4 = peg$FAILED; - } - } else { - peg$currPos = s4; - s4 = peg$FAILED; - } - } - if (s3 !== peg$FAILED) { - peg$savedPos = s1; - s2 = peg$c22(s2, s3); - s1 = s2; - } else { - peg$currPos = s1; - s1 = peg$FAILED; - } - } else { - peg$currPos = s1; - s1 = peg$FAILED; - } - if (s1 !== peg$FAILED) { - peg$savedPos = s0; - s1 = peg$c30(s1); - } - s0 = s1; - - peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; - - return s0; - } - - function peg$parsesteps(): any { - let s0, s1, s2, s3, s4, s5, s6; - - const key = peg$currPos * 38 + 12; - const cached: ICached = peg$resultsCache[key]; - - if (cached) { - peg$currPos = cached.nextPos; - - return cached.result; - } - - s0 = peg$currPos; - s1 = peg$currPos; - s2 = peg$parsefull_expr(); - if (s2 !== peg$FAILED) { - s3 = []; - s4 = peg$currPos; - s5 = peg$parseline_separator(); - if (s5 !== peg$FAILED) { - s6 = peg$parsefull_expr(); - if (s6 !== peg$FAILED) { - peg$savedPos = s4; - s5 = peg$c31(s2, s6); - s4 = s5; - } else { - peg$currPos = s4; - s4 = peg$FAILED; - } - } else { - peg$currPos = s4; - s4 = peg$FAILED; - } - while (s4 !== peg$FAILED) { - s3.push(s4); - s4 = peg$currPos; - s5 = peg$parseline_separator(); - if (s5 !== peg$FAILED) { - s6 = peg$parsefull_expr(); - if (s6 !== peg$FAILED) { - peg$savedPos = s4; - s5 = peg$c31(s2, s6); - s4 = s5; - } else { - peg$currPos = s4; - s4 = peg$FAILED; - } - } else { - peg$currPos = s4; - s4 = peg$FAILED; - } - } - if (s3 !== peg$FAILED) { - peg$savedPos = s1; - s2 = peg$c22(s2, s3); - s1 = s2; - } else { - peg$currPos = s1; - s1 = peg$FAILED; - } - } else { - peg$currPos = s1; - s1 = peg$FAILED; - } - if (s1 === peg$FAILED) { - s1 = null; - } - if (s1 !== peg$FAILED) { - peg$savedPos = s0; - s1 = peg$c32(s1); - } - s0 = s1; - - peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; - - return s0; - } - - function peg$parsefull_expr(): any { - let s0, s1, s2; - - const key = peg$currPos * 38 + 13; - const cached: ICached = peg$resultsCache[key]; - - if (cached) { - peg$currPos = cached.nextPos; - - return cached.result; - } - - s0 = peg$currPos; - s1 = peg$parsetab_separator(); - if (s1 !== peg$FAILED) { - s2 = peg$parsestep(); - if (s2 !== peg$FAILED) { - peg$savedPos = s0; - s1 = peg$c33(s2); - s0 = s1; - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - if (s0 === peg$FAILED) { - s0 = peg$currPos; - s1 = peg$parsecomment(); - if (s1 !== peg$FAILED) { - peg$savedPos = s0; - s1 = peg$c34(); - } - s0 = s1; - if (s0 === peg$FAILED) { - s0 = peg$currPos; - s1 = peg$parsetab_separator(); - if (s1 !== peg$FAILED) { - s2 = peg$parsews(); - if (s2 !== peg$FAILED) { - peg$savedPos = s0; - s1 = peg$c34(); - s0 = s1; - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } - } - - peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; - - return s0; - } - - function peg$parsestep(): any { - let s0, s1, s2; - - const key = peg$currPos * 38 + 14; - const cached: ICached = peg$resultsCache[key]; - - if (cached) { - peg$currPos = cached.nextPos; - - return cached.result; - } - - s0 = peg$currPos; - s1 = peg$parseexpr(); - if (s1 !== peg$FAILED) { - s2 = peg$parsecomment(); - if (s2 === peg$FAILED) { - s2 = null; - } - if (s2 !== peg$FAILED) { - peg$savedPos = s0; - s1 = peg$c35(s1); - s0 = s1; - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - if (s0 === peg$FAILED) { - s0 = peg$currPos; - s1 = peg$parsecomment(); - if (s1 !== peg$FAILED) { - peg$savedPos = s0; - s1 = peg$c34(); - } - s0 = s1; - if (s0 === peg$FAILED) { - s0 = peg$currPos; - s1 = peg$parsetab_separator(); - if (s1 === peg$FAILED) { - s1 = null; - } - if (s1 !== peg$FAILED) { - s2 = peg$parsews(); - if (s2 !== peg$FAILED) { - peg$savedPos = s0; - s1 = peg$c34(); - s0 = s1; - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } - } - - peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; - - return s0; - } - - function peg$parseexpr(): any { - let s0, s1, s2, s3, s4, s5, s6; - - const key = peg$currPos * 38 + 15; - const cached: ICached = peg$resultsCache[key]; - - if (cached) { - peg$currPos = cached.nextPos; - - return cached.result; - } - - s0 = peg$currPos; - s1 = peg$parsetoken(); - if (s1 !== peg$FAILED) { - s2 = []; - s3 = peg$currPos; - s4 = peg$parsews(); - if (s4 !== peg$FAILED) { - s5 = peg$parsecontinuation(); - if (s5 === peg$FAILED) { - s5 = null; - } - if (s5 !== peg$FAILED) { - s6 = peg$parseexpr(); - if (s6 !== peg$FAILED) { - peg$savedPos = s3; - s4 = peg$c36(s1, s6); - s3 = s4; - } else { - peg$currPos = s3; - s3 = peg$FAILED; - } - } else { - peg$currPos = s3; - s3 = peg$FAILED; - } - } else { - peg$currPos = s3; - s3 = peg$FAILED; - } - while (s3 !== peg$FAILED) { - s2.push(s3); - s3 = peg$currPos; - s4 = peg$parsews(); - if (s4 !== peg$FAILED) { - s5 = peg$parsecontinuation(); - if (s5 === peg$FAILED) { - s5 = null; - } - if (s5 !== peg$FAILED) { - s6 = peg$parseexpr(); - if (s6 !== peg$FAILED) { - peg$savedPos = s3; - s4 = peg$c36(s1, s6); - s3 = s4; - } else { - peg$currPos = s3; - s3 = peg$FAILED; - } - } else { - peg$currPos = s3; - s3 = peg$FAILED; - } - } else { - peg$currPos = s3; - s3 = peg$FAILED; - } - } - if (s2 !== peg$FAILED) { - peg$savedPos = s0; - s1 = peg$c37(s1, s2); - s0 = s1; - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - if (s0 === peg$FAILED) { - s0 = peg$currPos; - s1 = peg$parsebegin_compound(); - if (s1 !== peg$FAILED) { - s2 = peg$parseexpr(); - if (s2 !== peg$FAILED) { - s3 = peg$parseend_compound(); - if (s3 !== peg$FAILED) { - peg$savedPos = s0; - s1 = peg$c38(s2); - s0 = s1; - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - if (s0 === peg$FAILED) { - s0 = peg$currPos; - s1 = peg$parsebegin_list(); - if (s1 !== peg$FAILED) { - s2 = peg$parselist_inner(); - if (s2 === peg$FAILED) { - s2 = null; - } - if (s2 !== peg$FAILED) { - s3 = peg$parseend_list(); - if (s3 !== peg$FAILED) { - peg$savedPos = s0; - s1 = peg$c39(s2); - s0 = s1; - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } - } - - peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; - - return s0; - } - - function peg$parsecomment(): any { - let s0, s1, s2, s3, s4; - - const key = peg$currPos * 38 + 16; - const cached: ICached = peg$resultsCache[key]; - - if (cached) { - peg$currPos = cached.nextPos; - - return cached.result; - } - - s0 = peg$currPos; - s1 = peg$parsews(); - if (s1 !== peg$FAILED) { - if (input.substr(peg$currPos, 2) === peg$c40) { - s2 = peg$c40; - peg$currPos += 2; - } else { - s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c41); } - } - if (s2 !== peg$FAILED) { - s3 = []; - if (peg$c42.test(input.charAt(peg$currPos))) { - s4 = input.charAt(peg$currPos); - peg$currPos++; - } else { - s4 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c43); } - } - while (s4 !== peg$FAILED) { - s3.push(s4); - if (peg$c42.test(input.charAt(peg$currPos))) { - s4 = input.charAt(peg$currPos); - peg$currPos++; - } else { - s4 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c43); } - } - } - if (s3 !== peg$FAILED) { - peg$savedPos = s0; - s1 = peg$c34(); - s0 = s1; - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - if (s0 === peg$FAILED) { - s0 = peg$currPos; - s1 = peg$parsews(); - if (s1 !== peg$FAILED) { - if (input.charCodeAt(peg$currPos) === 35) { - s2 = peg$c44; - peg$currPos++; - } else { - s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c45); } - } - if (s2 !== peg$FAILED) { - s3 = []; - if (peg$c42.test(input.charAt(peg$currPos))) { - s4 = input.charAt(peg$currPos); - peg$currPos++; - } else { - s4 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c43); } - } - while (s4 !== peg$FAILED) { - s3.push(s4); - if (peg$c42.test(input.charAt(peg$currPos))) { - s4 = input.charAt(peg$currPos); - peg$currPos++; - } else { - s4 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c43); } - } - } - if (s3 !== peg$FAILED) { - peg$savedPos = s0; - s1 = peg$c34(); - s0 = s1; - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } - - peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; - - return s0; - } - - function peg$parsetoken(): any { - let s0, s1, s2, s3; - - const key = peg$currPos * 38 + 17; - const cached: ICached = peg$resultsCache[key]; - - if (cached) { - peg$currPos = cached.nextPos; - - return cached.result; - } - - s0 = peg$currPos; - s1 = peg$parsesimple_token(); - if (s1 !== peg$FAILED) { - if (input.charCodeAt(peg$currPos) === 58) { - s2 = peg$c46; - peg$currPos++; - } else { - s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c47); } - } - if (s2 !== peg$FAILED) { - s3 = peg$parsesimple_token(); - if (s3 !== peg$FAILED) { - peg$savedPos = s0; - s1 = peg$c48(s1, s3); - s0 = s1; - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - if (s0 === peg$FAILED) { - s0 = peg$parsesimple_token(); - } - - peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; - - return s0; - } - - function peg$parsesimple_token(): any { - let s0, s1, s2; - - const key = peg$currPos * 38 + 18; - const cached: ICached = peg$resultsCache[key]; - - if (cached) { - peg$currPos = cached.nextPos; - - return cached.result; - } - - s0 = peg$parsehex(); - if (s0 === peg$FAILED) { - s0 = peg$parsenumber(); - if (s0 === peg$FAILED) { - s0 = peg$currPos; - s1 = []; - if (peg$c49.test(input.charAt(peg$currPos))) { - s2 = input.charAt(peg$currPos); - peg$currPos++; - } else { - s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c50); } - } - if (s2 !== peg$FAILED) { - while (s2 !== peg$FAILED) { - s1.push(s2); - if (peg$c49.test(input.charAt(peg$currPos))) { - s2 = input.charAt(peg$currPos); - peg$currPos++; - } else { - s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c50); } - } - } - } else { - s1 = peg$FAILED; - } - if (s1 !== peg$FAILED) { - peg$savedPos = s0; - s1 = peg$c51(s1); - } - s0 = s1; - if (s0 === peg$FAILED) { - s0 = peg$parsestring(); - } - } - } - - peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; - - return s0; - } - - function peg$parsehex(): any { - let s0, s1, s2, s3, s4; - - const key = peg$currPos * 38 + 19; - const cached: ICached = peg$resultsCache[key]; - - if (cached) { - peg$currPos = cached.nextPos; - - return cached.result; - } - - s0 = peg$currPos; - s1 = peg$currPos; - if (input.substr(peg$currPos, 2) === peg$c52) { - s2 = peg$c52; - peg$currPos += 2; - } else { - s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c53); } - } - if (s2 !== peg$FAILED) { - s3 = []; - if (peg$c54.test(input.charAt(peg$currPos))) { - s4 = input.charAt(peg$currPos); - peg$currPos++; - } else { - s4 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c55); } - } - if (s4 !== peg$FAILED) { - while (s4 !== peg$FAILED) { - s3.push(s4); - if (peg$c54.test(input.charAt(peg$currPos))) { - s4 = input.charAt(peg$currPos); - peg$currPos++; - } else { - s4 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c55); } - } - } - } else { - s3 = peg$FAILED; - } - if (s3 !== peg$FAILED) { - s2 = [s2, s3]; - s1 = s2; - } else { - peg$currPos = s1; - s1 = peg$FAILED; - } - } else { - peg$currPos = s1; - s1 = peg$FAILED; - } - if (s1 !== peg$FAILED) { - peg$savedPos = s0; - s1 = peg$c56(s1); - } - s0 = s1; - - peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; - - return s0; - } - - function peg$parsenumber(): any { - let s0, s1, s2, s3, s4, s5, s6, s7, s8, s9; - - const key = peg$currPos * 38 + 20; - const cached: ICached = peg$resultsCache[key]; - - if (cached) { - peg$currPos = cached.nextPos; - - return cached.result; - } - - s0 = peg$currPos; - s1 = peg$currPos; - if (input.charCodeAt(peg$currPos) === 45) { - s2 = peg$c57; - peg$currPos++; - } else { - s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c58); } - } - if (s2 === peg$FAILED) { - if (input.charCodeAt(peg$currPos) === 43) { - s2 = peg$c59; - peg$currPos++; - } else { - s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c60); } - } - } - if (s2 === peg$FAILED) { - s2 = null; - } - if (s2 !== peg$FAILED) { - s3 = []; - if (peg$c61.test(input.charAt(peg$currPos))) { - s4 = input.charAt(peg$currPos); - peg$currPos++; - } else { - s4 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c62); } - } - if (s4 !== peg$FAILED) { - while (s4 !== peg$FAILED) { - s3.push(s4); - if (peg$c61.test(input.charAt(peg$currPos))) { - s4 = input.charAt(peg$currPos); - peg$currPos++; - } else { - s4 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c62); } - } - } - } else { - s3 = peg$FAILED; - } - if (s3 !== peg$FAILED) { - s4 = peg$currPos; - if (input.charCodeAt(peg$currPos) === 46) { - s5 = peg$c63; - peg$currPos++; - } else { - s5 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c64); } - } - if (s5 !== peg$FAILED) { - s6 = []; - if (peg$c61.test(input.charAt(peg$currPos))) { - s7 = input.charAt(peg$currPos); - peg$currPos++; - } else { - s7 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c62); } - } - if (s7 !== peg$FAILED) { - while (s7 !== peg$FAILED) { - s6.push(s7); - if (peg$c61.test(input.charAt(peg$currPos))) { - s7 = input.charAt(peg$currPos); - peg$currPos++; - } else { - s7 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c62); } - } - } - } else { - s6 = peg$FAILED; - } - if (s6 !== peg$FAILED) { - s5 = [s5, s6]; - s4 = s5; - } else { - peg$currPos = s4; - s4 = peg$FAILED; - } - } else { - peg$currPos = s4; - s4 = peg$FAILED; - } - if (s4 === peg$FAILED) { - s4 = null; - } - if (s4 !== peg$FAILED) { - s5 = peg$currPos; - if (input.charCodeAt(peg$currPos) === 101) { - s6 = peg$c65; - peg$currPos++; - } else { - s6 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c66); } - } - if (s6 !== peg$FAILED) { - if (input.charCodeAt(peg$currPos) === 45) { - s7 = peg$c57; - peg$currPos++; - } else { - s7 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c58); } - } - if (s7 === peg$FAILED) { - s7 = null; - } - if (s7 !== peg$FAILED) { - s8 = []; - if (peg$c61.test(input.charAt(peg$currPos))) { - s9 = input.charAt(peg$currPos); - peg$currPos++; - } else { - s9 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c62); } - } - if (s9 !== peg$FAILED) { - while (s9 !== peg$FAILED) { - s8.push(s9); - if (peg$c61.test(input.charAt(peg$currPos))) { - s9 = input.charAt(peg$currPos); - peg$currPos++; - } else { - s9 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c62); } - } - } - } else { - s8 = peg$FAILED; - } - if (s8 !== peg$FAILED) { - s6 = [s6, s7, s8]; - s5 = s6; - } else { - peg$currPos = s5; - s5 = peg$FAILED; - } - } else { - peg$currPos = s5; - s5 = peg$FAILED; - } - } else { - peg$currPos = s5; - s5 = peg$FAILED; - } - if (s5 === peg$FAILED) { - s5 = null; - } - if (s5 !== peg$FAILED) { - s2 = [s2, s3, s4, s5]; - s1 = s2; - } else { - peg$currPos = s1; - s1 = peg$FAILED; - } - } else { - peg$currPos = s1; - s1 = peg$FAILED; - } - } else { - peg$currPos = s1; - s1 = peg$FAILED; - } - } else { - peg$currPos = s1; - s1 = peg$FAILED; - } - if (s1 !== peg$FAILED) { - peg$savedPos = s0; - s1 = peg$c67(s1); - } - s0 = s1; - - peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; - - return s0; - } - - function peg$parselist_inner(): any { - let s0, s1, s2, s3, s4, s5; - - const key = peg$currPos * 38 + 21; - const cached: ICached = peg$resultsCache[key]; - - if (cached) { - peg$currPos = cached.nextPos; - - return cached.result; - } - - s0 = peg$currPos; - s1 = peg$parseexpr(); - if (s1 !== peg$FAILED) { - s2 = []; - s3 = peg$currPos; - s4 = peg$parsews(); - if (s4 === peg$FAILED) { - s4 = null; - } - if (s4 !== peg$FAILED) { - s5 = peg$parselist_inner(); - if (s5 !== peg$FAILED) { - peg$savedPos = s3; - s4 = peg$c36(s1, s5); - s3 = s4; - } else { - peg$currPos = s3; - s3 = peg$FAILED; - } - } else { - peg$currPos = s3; - s3 = peg$FAILED; - } - while (s3 !== peg$FAILED) { - s2.push(s3); - s3 = peg$currPos; - s4 = peg$parsews(); - if (s4 === peg$FAILED) { - s4 = null; - } - if (s4 !== peg$FAILED) { - s5 = peg$parselist_inner(); - if (s5 !== peg$FAILED) { - peg$savedPos = s3; - s4 = peg$c36(s1, s5); - s3 = s4; - } else { - peg$currPos = s3; - s3 = peg$FAILED; - } - } else { - peg$currPos = s3; - s3 = peg$FAILED; - } - } - if (s2 !== peg$FAILED) { - peg$savedPos = s0; - s1 = peg$c68(s1, s2); - s0 = s1; - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - - peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; - - return s0; - } - - function peg$parsebegin_compound(): any { - let s0, s1, s2, s3; - - const key = peg$currPos * 38 + 22; - const cached: ICached = peg$resultsCache[key]; - - if (cached) { - peg$currPos = cached.nextPos; - - return cached.result; - } - - s0 = peg$currPos; - s1 = peg$parsews(); - if (s1 !== peg$FAILED) { - if (input.charCodeAt(peg$currPos) === 40) { - s2 = peg$c69; - peg$currPos++; - } else { - s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c70); } - } - if (s2 !== peg$FAILED) { - s3 = peg$parsews(); - if (s3 !== peg$FAILED) { - s1 = [s1, s2, s3]; - s0 = s1; - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - - peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; - - return s0; - } - - function peg$parseend_compound(): any { - let s0, s1, s2, s3; - - const key = peg$currPos * 38 + 23; - const cached: ICached = peg$resultsCache[key]; - - if (cached) { - peg$currPos = cached.nextPos; - - return cached.result; - } - - s0 = peg$currPos; - s1 = peg$parsews(); - if (s1 !== peg$FAILED) { - if (input.charCodeAt(peg$currPos) === 41) { - s2 = peg$c71; - peg$currPos++; - } else { - s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c72); } - } - if (s2 !== peg$FAILED) { - s3 = peg$parsews(); - if (s3 !== peg$FAILED) { - s1 = [s1, s2, s3]; - s0 = s1; - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - - peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; - - return s0; - } - - function peg$parsebegin_list(): any { - let s0, s1, s2, s3; - - const key = peg$currPos * 38 + 24; - const cached: ICached = peg$resultsCache[key]; - - if (cached) { - peg$currPos = cached.nextPos; - - return cached.result; - } - - s0 = peg$currPos; - s1 = peg$parsews(); - if (s1 !== peg$FAILED) { - if (input.charCodeAt(peg$currPos) === 91) { - s2 = peg$c73; - peg$currPos++; - } else { - s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c74); } - } - if (s2 !== peg$FAILED) { - s3 = peg$parsews(); - if (s3 !== peg$FAILED) { - s1 = [s1, s2, s3]; - s0 = s1; - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - - peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; - - return s0; - } - - function peg$parseend_list(): any { - let s0, s1, s2, s3; - - const key = peg$currPos * 38 + 25; - const cached: ICached = peg$resultsCache[key]; - - if (cached) { - peg$currPos = cached.nextPos; - - return cached.result; - } - - s0 = peg$currPos; - s1 = peg$parsews(); - if (s1 !== peg$FAILED) { - if (input.charCodeAt(peg$currPos) === 93) { - s2 = peg$c75; - peg$currPos++; - } else { - s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c76); } - } - if (s2 !== peg$FAILED) { - s3 = peg$parsews(); - if (s3 !== peg$FAILED) { - s1 = [s1, s2, s3]; - s0 = s1; - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - - peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; - - return s0; - } - - function peg$parseline_separator(): any { - let s0, s1, s2; - - const key = peg$currPos * 38 + 26; - const cached: ICached = peg$resultsCache[key]; - - if (cached) { - peg$currPos = cached.nextPos; - - return cached.result; - } - - s0 = peg$currPos; - if (input.charCodeAt(peg$currPos) === 13) { - s1 = peg$c77; - peg$currPos++; - } else { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c78); } - } - if (s1 === peg$FAILED) { - s1 = null; - } - if (s1 !== peg$FAILED) { - if (input.charCodeAt(peg$currPos) === 10) { - s2 = peg$c79; - peg$currPos++; - } else { - s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c80); } - } - if (s2 !== peg$FAILED) { - s1 = [s1, s2]; - s0 = s1; - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - - peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; - - return s0; - } - - function peg$parsetab_separator(): any { - let s0; - - const key = peg$currPos * 38 + 27; - const cached: ICached = peg$resultsCache[key]; - - if (cached) { - peg$currPos = cached.nextPos; - - return cached.result; - } - - if (input.charCodeAt(peg$currPos) === 9) { - s0 = peg$c81; - peg$currPos++; - } else { - s0 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c82); } - } - if (s0 === peg$FAILED) { - if (input.substr(peg$currPos, 4) === peg$c83) { - s0 = peg$c83; - peg$currPos += 4; - } else { - s0 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c84); } - } - } - - peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; - - return s0; - } - - function peg$parsecontinuation(): any { - let s0, s1, s2, s3, s4; - - const key = peg$currPos * 38 + 28; - const cached: ICached = peg$resultsCache[key]; - - if (cached) { - peg$currPos = cached.nextPos; - - return cached.result; - } - - s0 = peg$currPos; - if (input.charCodeAt(peg$currPos) === 92) { - s1 = peg$c85; - peg$currPos++; - } else { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c86); } - } - if (s1 !== peg$FAILED) { - s2 = peg$parseline_separator(); - if (s2 !== peg$FAILED) { - s3 = peg$parsetab_separator(); - if (s3 !== peg$FAILED) { - s4 = peg$parsetab_separator(); - if (s4 !== peg$FAILED) { - s1 = [s1, s2, s3, s4]; - s0 = s1; - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - - peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; - - return s0; - } - - function peg$parsews(): any { - let s0, s1; - - const key = peg$currPos * 38 + 29; - const cached: ICached = peg$resultsCache[key]; - - if (cached) { - peg$currPos = cached.nextPos; - - return cached.result; - } - - peg$silentFails++; - s0 = []; - if (peg$c88.test(input.charAt(peg$currPos))) { - s1 = input.charAt(peg$currPos); - peg$currPos++; - } else { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c89); } - } - while (s1 !== peg$FAILED) { - s0.push(s1); - if (peg$c88.test(input.charAt(peg$currPos))) { - s1 = input.charAt(peg$currPos); - peg$currPos++; - } else { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c89); } - } - } - peg$silentFails--; - if (s0 === peg$FAILED) { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c87); } - } - - peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; - - return s0; - } - - function peg$parsefull_ws(): any { - let s0, s1, s2; - - const key = peg$currPos * 38 + 30; - const cached: ICached = peg$resultsCache[key]; - - if (cached) { - peg$currPos = cached.nextPos; - - return cached.result; - } - - s0 = peg$currPos; - s1 = peg$parsecomment(); - if (s1 !== peg$FAILED) { - s2 = peg$parsefull_ws(); - if (s2 !== peg$FAILED) { - s1 = [s1, s2]; - s0 = s1; - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - if (s0 === peg$FAILED) { - s0 = peg$currPos; - if (peg$c90.test(input.charAt(peg$currPos))) { - s1 = input.charAt(peg$currPos); - peg$currPos++; - } else { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c91); } - } - if (s1 !== peg$FAILED) { - s2 = peg$parsefull_ws(); - if (s2 === peg$FAILED) { - s2 = null; - } - if (s2 !== peg$FAILED) { - s1 = [s1, s2]; - s0 = s1; - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } - - peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; - - return s0; - } - - function peg$parsestring(): any { - let s0, s1, s2, s3; - - const key = peg$currPos * 38 + 31; - const cached: ICached = peg$resultsCache[key]; - - if (cached) { - peg$currPos = cached.nextPos; - - return cached.result; - } - - peg$silentFails++; - s0 = peg$currPos; - s1 = peg$parsequotation_mark(); - if (s1 !== peg$FAILED) { - s2 = []; - s3 = peg$parsechar(); - while (s3 !== peg$FAILED) { - s2.push(s3); - s3 = peg$parsechar(); - } - if (s2 !== peg$FAILED) { - s3 = peg$parsequotation_mark(); - if (s3 !== peg$FAILED) { - peg$savedPos = s0; - s1 = peg$c93(s2); - s0 = s1; - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - peg$silentFails--; - if (s0 === peg$FAILED) { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c92); } - } - - peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; - - return s0; - } - - function peg$parsechar(): any { - let s0, s1, s2, s3, s4, s5, s6, s7, s8, s9; - - const key = peg$currPos * 38 + 32; - const cached: ICached = peg$resultsCache[key]; - - if (cached) { - peg$currPos = cached.nextPos; - - return cached.result; - } - - s0 = peg$parseunescaped(); - if (s0 === peg$FAILED) { - s0 = peg$currPos; - s1 = peg$parseescape(); - if (s1 !== peg$FAILED) { - if (input.charCodeAt(peg$currPos) === 34) { - s2 = peg$c94; - peg$currPos++; - } else { - s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c95); } - } - if (s2 === peg$FAILED) { - if (input.charCodeAt(peg$currPos) === 92) { - s2 = peg$c85; - peg$currPos++; - } else { - s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c86); } - } - if (s2 === peg$FAILED) { - if (input.charCodeAt(peg$currPos) === 47) { - s2 = peg$c96; - peg$currPos++; - } else { - s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c97); } - } - if (s2 === peg$FAILED) { - s2 = peg$currPos; - if (input.charCodeAt(peg$currPos) === 98) { - s3 = peg$c98; - peg$currPos++; - } else { - s3 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c99); } - } - if (s3 !== peg$FAILED) { - peg$savedPos = s2; - s3 = peg$c100(); - } - s2 = s3; - if (s2 === peg$FAILED) { - s2 = peg$currPos; - if (input.charCodeAt(peg$currPos) === 102) { - s3 = peg$c101; - peg$currPos++; - } else { - s3 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c102); } - } - if (s3 !== peg$FAILED) { - peg$savedPos = s2; - s3 = peg$c103(); - } - s2 = s3; - if (s2 === peg$FAILED) { - s2 = peg$currPos; - if (input.charCodeAt(peg$currPos) === 110) { - s3 = peg$c104; - peg$currPos++; - } else { - s3 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c105); } - } - if (s3 !== peg$FAILED) { - peg$savedPos = s2; - s3 = peg$c106(); - } - s2 = s3; - if (s2 === peg$FAILED) { - s2 = peg$currPos; - if (input.charCodeAt(peg$currPos) === 114) { - s3 = peg$c107; - peg$currPos++; - } else { - s3 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c108); } - } - if (s3 !== peg$FAILED) { - peg$savedPos = s2; - s3 = peg$c109(); - } - s2 = s3; - if (s2 === peg$FAILED) { - s2 = peg$currPos; - if (input.charCodeAt(peg$currPos) === 116) { - s3 = peg$c110; - peg$currPos++; - } else { - s3 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c111); } - } - if (s3 !== peg$FAILED) { - peg$savedPos = s2; - s3 = peg$c112(); - } - s2 = s3; - if (s2 === peg$FAILED) { - s2 = peg$currPos; - if (input.charCodeAt(peg$currPos) === 117) { - s3 = peg$c113; - peg$currPos++; - } else { - s3 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c114); } - } - if (s3 !== peg$FAILED) { - s4 = peg$currPos; - s5 = peg$currPos; - s6 = peg$parseHEXDIG(); - if (s6 !== peg$FAILED) { - s7 = peg$parseHEXDIG(); - if (s7 !== peg$FAILED) { - s8 = peg$parseHEXDIG(); - if (s8 !== peg$FAILED) { - s9 = peg$parseHEXDIG(); - if (s9 !== peg$FAILED) { - s6 = [s6, s7, s8, s9]; - s5 = s6; - } else { - peg$currPos = s5; - s5 = peg$FAILED; - } - } else { - peg$currPos = s5; - s5 = peg$FAILED; - } - } else { - peg$currPos = s5; - s5 = peg$FAILED; - } - } else { - peg$currPos = s5; - s5 = peg$FAILED; - } - if (s5 !== peg$FAILED) { - s4 = input.substring(s4, peg$currPos); - } else { - s4 = s5; - } - if (s4 !== peg$FAILED) { - peg$savedPos = s2; - s3 = peg$c115(s4); - s2 = s3; - } else { - peg$currPos = s2; - s2 = peg$FAILED; - } - } else { - peg$currPos = s2; - s2 = peg$FAILED; - } - } - } - } - } - } - } - } - } - if (s2 !== peg$FAILED) { - peg$savedPos = s0; - s1 = peg$c116(s2); - s0 = s1; - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } - } - - peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; - - return s0; - } - - function peg$parseescape(): any { - let s0; - - const key = peg$currPos * 38 + 33; - const cached: ICached = peg$resultsCache[key]; - - if (cached) { - peg$currPos = cached.nextPos; - - return cached.result; - } - - if (input.charCodeAt(peg$currPos) === 92) { - s0 = peg$c85; - peg$currPos++; - } else { - s0 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c86); } - } - - peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; - - return s0; - } - - function peg$parsequotation_mark(): any { - let s0; - - const key = peg$currPos * 38 + 34; - const cached: ICached = peg$resultsCache[key]; - - if (cached) { - peg$currPos = cached.nextPos; - - return cached.result; - } - - if (input.charCodeAt(peg$currPos) === 34) { - s0 = peg$c94; - peg$currPos++; - } else { - s0 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c95); } - } - - peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; - - return s0; - } - - function peg$parseunescaped(): any { - let s0; - - const key = peg$currPos * 38 + 35; - const cached: ICached = peg$resultsCache[key]; - - if (cached) { - peg$currPos = cached.nextPos; - - return cached.result; - } - - if (peg$c117.test(input.charAt(peg$currPos))) { - s0 = input.charAt(peg$currPos); - peg$currPos++; - } else { - s0 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c118); } - } - - peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; - - return s0; - } - - function peg$parseDIGIT(): any { - let s0; - - const key = peg$currPos * 38 + 36; - const cached: ICached = peg$resultsCache[key]; - - if (cached) { - peg$currPos = cached.nextPos; - - return cached.result; - } - - if (peg$c61.test(input.charAt(peg$currPos))) { - s0 = input.charAt(peg$currPos); - peg$currPos++; - } else { - s0 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c62); } - } - - peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; - - return s0; - } - - function peg$parseHEXDIG(): any { - let s0; - - const key = peg$currPos * 38 + 37; - const cached: ICached = peg$resultsCache[key]; - - if (cached) { - peg$currPos = cached.nextPos; - - return cached.result; - } - - if (peg$c119.test(input.charAt(peg$currPos))) { - s0 = input.charAt(peg$currPos); - peg$currPos++; - } else { - s0 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c120); } - } - - peg$resultsCache[key] = { nextPos: peg$currPos, result: s0 }; - - return s0; - } - - - if (!Array.prototype.flat) { - Object.defineProperty(Array.prototype, 'flat', { - configurable: true, - value: function flat (x) { - var depth = isNaN(arguments[0]) ? 1 : Number(arguments[0]); - - return depth ? Array.prototype.reduce.call(this, function (acc, cur) { - if (Array.isArray(cur)) { - (acc).push.apply(acc, flat.call(cur, depth - 1)); - } else { - (acc).push(cur); - } - - return acc; - }, []) : Array.prototype.slice.call(this); - }, - writable: true - }); - } - - function getString(str) { - let val; - if (Array.isArray(str)) { - if (str.length !== 2 || str[0] !== 'String') { - throw new Error(`Expected string, got ${str}`); - } - - val = str[1]; - } else { - val = str; - } - - if (typeof val !== 'string') { - throw new Error(`Expected string, got ${val} (${typeof val})`); - } - - return val; - } - - function expandEvent(macros, step) { - const [eventName, ...eventArgs] = step; - - if (macros[eventName]) { - let expanded = expandMacro(macros[eventName], eventArgs); - - // Recursively expand steps - return expanded.map(event => expandEvent(macros, event)).flat(); - } else { - return [step]; - } - } - - function getArgValues(eventArgs, macroArgs) { - const eventArgNameMap = {}; - const eventArgIndexed = new Array(); - const argValues = {}; - let usedNamedArg = false; - let usedSplat = false; - - eventArgs.forEach((eventArg) => { - if (eventArg.argName) { - const {argName, argValue} = eventArg; - - eventArgNameMap[argName] = argValue; - usedNamedArg = true; - } else { - if (usedNamedArg) { - throw new Error(`Cannot use positional arg after named arg in macro invokation ${JSON.stringify(eventArgs)} looking at ${eventArg.toString()}`); - } - - eventArgIndexed.push(eventArg); - } - }); - - macroArgs.forEach(({arg, def, splat}, argIndex) => { - if (usedSplat) { - throw new Error("Cannot have arg after splat arg"); - } - - let val; - if (eventArgNameMap[arg] !== undefined) { - val = eventArgNameMap[arg]; - } else if (splat) { - val = eventArgIndexed.slice(argIndex); // Clear out any remaining args - usedSplat = true; - } else if (eventArgIndexed[argIndex] !== undefined) { - val = eventArgIndexed[argIndex]; - } else if (def !== undefined) { - val = def; - } else { - throw new Error("Macro cannot find arg value for " + arg); - } - argValues[arg] = val; - }); - - return argValues; - } - - function expandMacro(macro, eventArgs) { - const argValues = getArgValues(eventArgs, macro.args); - - function expandStep(step) { - return step.map((token) => { - if (argValues[token] !== undefined) { - return argValues[token]; - } else { - if (Array.isArray(token)) { - return expandStep(token); - } else { - return token; - } - } - }); - }; - - return macro.steps.map(expandStep); - } - - function addTopLevelEl(state, el) { - const macros = state.macros; - const tests = state.tests; - const pending = state.pending; - - switch (el.type) { - case 'macro': - const macro = {[el.name]: {args: el.args, steps: el.steps}}; - - return { - tests: tests, - macros: ({...macros, ...macro}) - }; - case 'test': - const steps = el.steps; - const expandedSteps = steps.map((step) => { - return expandEvent(macros, step) - }).flat(); - - const test = {[el.test]: expandedSteps}; - - return { - tests: {...tests, ...test}, - macros: macros - } - } - } - - - peg$result = peg$startRuleFunction(); - - if (peg$result !== peg$FAILED && peg$currPos === input.length) { - return peg$result; - } else { - if (peg$result !== peg$FAILED && peg$currPos < input.length) { - peg$fail(peg$endExpectation()); - } - - throw peg$buildStructuredError( - peg$maxFailExpected, - peg$maxFailPos < input.length ? input.charAt(peg$maxFailPos) : null, - peg$maxFailPos < input.length - ? peg$computeLocation(peg$maxFailPos, peg$maxFailPos + 1) - : peg$computeLocation(peg$maxFailPos, peg$maxFailPos) - ); - } -} - -export interface IParseOptions { - filename?: string; - startRule?: string; - tracer?: any; - [key: string]: any; -} -export type ParseFunction = (input: string, options?: IParseOptions) => any; -export const parse: ParseFunction = peg$parse; - diff --git a/scenario/src/Printer.ts b/scenario/src/Printer.ts deleted file mode 100644 index 478bbfc69..000000000 --- a/scenario/src/Printer.ts +++ /dev/null @@ -1,120 +0,0 @@ -import {Value} from './Value'; -import {Action} from './Action'; -import {EventProcessingError} from './CoreEvent' -import {formatEvent} from './Formatter'; - -import * as readline from 'readline'; - -export interface Printer { - printLine(str: string): void - printMarkdown(str: string): void - printValue(val: Value): void - printError(err: Error): void - printAction(action: Action): void -} - -export class CallbackPrinter implements Printer { - callback: (message: any, format: object) => void - - constructor(callback: (message: string) => void) { - this.callback = callback; - } - - printLine(str: string): void { - this.callback(str, {}); - } - - printMarkdown(str: string): void { - this.callback(str, {markdown: true}); - } - - printValue(val: Value): void { - this.callback(val.toString(), {value: true}); - } - - printError(err: Error): void { - if (process.env['verbose']) { - this.callback(err, {error: true}); - } - - this.callback(`Error: ${err.toString()}`, {error: true}); - } - - printAction(action: Action): void { - // Do nothing - } -} - -export class ConsolePrinter implements Printer { - verbose: boolean - - constructor(verbose: boolean) { - this.verbose = verbose; - } - - printLine(str: string): void { - console.log(str); - } - - printMarkdown(str: string): void { - console.log(str); - } - - printValue(val: Value): void { - console.log(val.toString()); - } - - printError(err: Error): void { - if (this.verbose) { - console.log(err); - } - - console.log(`Error: ${err.toString()}`); - } - - printAction(action: Action): void { - if (this.verbose) { - console.log(`Action: ${action.log}`); - } - } -} - -export class ReplPrinter implements Printer { - rl : readline.Interface; - verbose : boolean - - constructor(rl: readline.Interface, verbose: boolean) { - this.rl = rl; - this.verbose = verbose; - } - - printLine(str: string): void { - console.log(`${str}`); - } - - printMarkdown(str: string): void { - console.log(`${str}`); - } - - printValue(val: Value): void { - console.log(val.toString()); - } - - printError(err: Error): void { - if (this.verbose) { - console.log(err); - } - - if (err instanceof EventProcessingError) { - console.log(`Event Processing Error:`); - console.log(`\t${err.error.toString()}`); - console.log(`\twhen processing event \`${formatEvent(err.event)}\``); - } else { - console.log(`Error: ${err.toString()}`); - } - } - - printAction(action: Action): void { - console.log(`Action: ${action.log}`); - } -} diff --git a/scenario/src/Repl.d.ts b/scenario/src/Repl.d.ts deleted file mode 100644 index a4a22f456..000000000 --- a/scenario/src/Repl.d.ts +++ /dev/null @@ -1,9 +0,0 @@ -import {Artifacts} from './Artifact'; -import {Web3} from './Web3'; - -declare namespace NodeJS { - interface Global { - Web3: Web3 - Artifacts: Artifacts - } -} diff --git a/scenario/src/Repl.ts b/scenario/src/Repl.ts deleted file mode 100644 index 2752ee017..000000000 --- a/scenario/src/Repl.ts +++ /dev/null @@ -1,188 +0,0 @@ -import {ReplPrinter} from './Printer'; -import { - addInvariant, - initWorld, - loadInvokationOpts, - loadDryRun, - loadSettings, - loadVerbose, - World -} from './World'; -import {throwExpect} from './Assert'; -import {Macros} from './Macro'; -import {formatEvent} from './Formatter'; -import {complete} from './Completer'; -import {loadContracts} from './Networks'; -import {accountAliases, loadAccounts} from './Accounts'; -import {getNetworkPath, readFile} from './File'; -import {SuccessInvariant} from './Invariant/SuccessInvariant'; -import {createInterface} from './HistoricReadline'; -import {runCommand} from './Runner'; -import {parse} from './Parser'; -import {forkWeb3} from './Hypothetical'; -import {getSaddle} from 'eth-saddle'; -import Web3 from 'web3'; - -import * as fs from 'fs'; -import * as path from 'path'; - -const basePath = process.env.proj_root || process.cwd(); -const baseScenarioPath = path.join(basePath, 'spec', 'scenario'); -const baseNetworksPath = path.join(basePath, 'networks'); - -const TOTAL_GAS = 8000000; - -function questionPromise(rl): Promise { - return new Promise((resolve, reject) => { - rl.question(" > ", (command) => { - resolve(command); - }); - }); -} - -async function loop(world, rl, macros): Promise { - let command = await questionPromise(rl); - - try { - let newWorld = await runCommand(world, command, macros); - - return await loop(newWorld, rl, macros); - } catch (err) { - world.printer.printError(err); - return await loop(world, rl, macros); - } -} - -function loadEnvVars(): object { - return (process.env['env_vars'] || '').split(',').reduce((acc, keyValue) => { - if (keyValue.length === 0) { - return acc; - } else { - const [key, value] = keyValue.split('='); - - return { - ...acc, - [key]: value - }; - } - }, {}); -} - -async function repl(): Promise { - // Uck, we need to load core macros :( - const coreMacros = fs.readFileSync(path.join(baseScenarioPath, 'CoreMacros'), 'utf8'); - - const macros = parse(coreMacros, {startRule: 'macros'}); - - let script = process.env['script']; - - let network = process.env['network']; - - if (!network) { - throw new Error(`Missing required "network" env argument`); - } - - let world; - - let rl = await createInterface({ - input: process.stdin, - output: process.stdout, - completer: (line) => complete(world, macros, line), - path: getNetworkPath(basePath, network, '-history', null) - }); - - const verbose: boolean = !!process.env['verbose']; - const hypothetical: boolean = !!process.env['hypothetical']; - - let printer = new ReplPrinter(rl, verbose); - let contractInfo: string[]; - - let saddle = await getSaddle(network); - let accounts: string[] = saddle.wallet_accounts.concat(saddle.accounts).filter((x) => !!x); - - world = await initWorld(throwExpect, printer, saddle.web3, saddle, network, accounts, basePath, TOTAL_GAS); - [world, contractInfo] = await loadContracts(world); - world = loadInvokationOpts(world); - world = loadVerbose(world); - world = loadDryRun(world); - world = await loadSettings(world); - - printer.printLine(`Network: ${network}`); - - if (hypothetical) { - const forkJsonPath = path.join(baseNetworksPath, `${network}-fork.json`); - let forkJson; - - try { - let forkJsonString = fs.readFileSync(forkJsonPath, 'utf8'); - forkJson = JSON.parse(forkJsonString); - } catch (err) { - throw new Error(`Cannot read fork configuration from \`${forkJsonPath}\`, ${err}`); - } - if (!forkJson['url']) { - throw new Error(`Missing url in fork json`); - } - if (!forkJson['unlocked'] || !Array.isArray(forkJson.unlocked)) { - throw new Error(`Missing unlocked in fork json`); - } - - saddle.web3 = await forkWeb3(saddle.web3, forkJson.url, forkJson.unlocked); - saddle.accounts = forkJson.unlocked; - console.log(`Running on fork ${forkJson.url} with unlocked accounts ${forkJson.unlocked.join(', ')}`) - } - - if (accounts.length > 0) { - printer.printLine(`Accounts:`); - accounts.forEach((account, i) => { - let aliases = world.settings.lookupAliases(account); - aliases = aliases.concat(accountAliases(i)); - - printer.printLine(`\t${account} (${aliases.join(',')})`) - }); - } - - if (contractInfo.length > 0) { - world.printer.printLine(`Contracts:`); - contractInfo.forEach((info) => world.printer.printLine(`\t${info}`)); - } - - printer.printLine(`Available macros: ${Object.keys(macros).toString()}`); - printer.printLine(``); - - if (script) { - const combined = script.split(',').reduce((acc, script) => { - printer.printLine(`Running script: ${script}...`); - const envVars = loadEnvVars(); - if (hypothetical) { - envVars['hypo'] = true; - } - const scriptData: string = fs.readFileSync(script).toString(); - - if (Object.keys(envVars).length > 0) { - printer.printLine(`Env Vars:`); - } - - const replacedScript = Object.entries(envVars).reduce((data, [key, val]) => { - printer.printLine(`\t${key}: ${val}`); - - return data.split(`$${key}`).join(val); - }, scriptData); - - const finalScript = replacedScript.replace(new RegExp(/\$[\w_]+/, 'g'), 'Nothing'); - - return [...acc, ...finalScript.split("\n")]; - }, []); - - return await combined.reduce(async (acc, command) => { - return await runCommand(await acc, command, macros); - }, Promise.resolve(world)); - printer.printLine(`Script complete.`); - } else { - await loop(world, rl, macros); - } -} - -repl().catch((error) => { - console.error(error); - process.exit(1); -}); diff --git a/scenario/src/Runner.ts b/scenario/src/Runner.ts deleted file mode 100644 index e5aac37e6..000000000 --- a/scenario/src/Runner.ts +++ /dev/null @@ -1,20 +0,0 @@ -import {World} from './World'; -import {parse} from './Parser'; -import {expandEvent, Macros} from './Macro'; -import {processEvents} from './CoreEvent' - -export async function runCommand(world: World, command: string, macros: Macros): Promise { - const trimmedCommand = command.trim(); - - const event = parse(trimmedCommand, {startRule: 'step'}); - - if (event === null) { - return world; - } else { - world.printer.printLine(`Command: ${trimmedCommand}`); - - let expanded = expandEvent(macros, event); - - return processEvents(world, expanded); - } -} diff --git a/scenario/src/Settings.ts b/scenario/src/Settings.ts deleted file mode 100644 index ba2ea5898..000000000 --- a/scenario/src/Settings.ts +++ /dev/null @@ -1,85 +0,0 @@ -import { getNetworkPath, readFile, writeFile } from './File'; - -export class Settings { - basePath: string | null; - network: string | null; - aliases: { [name: string]: string }; - from: string | undefined; - printTxLogs: boolean = false; - - constructor( - basePath: string | null, - network: string | null, - aliases: { [name: string]: string }, - from?: string - ) { - this.basePath = basePath; - this.network = network; - this.aliases = aliases; - this.from = from; - } - - static deserialize(basePath: string, network: string, data: string): Settings { - const { aliases } = JSON.parse(data); - - return new Settings(basePath, network, aliases); - } - - serialize(): string { - return JSON.stringify({ - aliases: this.aliases - }); - } - - static default(basePath: string | null, network: string | null): Settings { - return new Settings(basePath, network, {}); - } - - static getFilePath(basePath: string | null, network: string): string { - return getNetworkPath(basePath, network, '-settings'); - } - - static load(basePath: string, network: string): Promise { - return readFile(null, Settings.getFilePath(basePath, network), Settings.default(basePath, network), data => - Settings.deserialize(basePath, network, data) - ); - } - - async save(): Promise { - if (this.network) { - await writeFile(null, Settings.getFilePath(this.basePath, this.network), this.serialize()); - } - } - - lookupAlias(address: string): string { - let entry = Object.entries(this.aliases).find(([key, value]) => { - return value === address; - }); - - if (entry) { - return entry[0]; - } else { - return address; - } - } - - lookupAliases(address: string): string[] { - let entries = Object.entries(this.aliases).filter(([key, value]) => { - return value === address; - }); - - return entries.map(([key, _value]) => key); - } - - findAlias(name: string): string | null { - const alias = Object.entries(this.aliases).find( - ([alias, addr]) => alias.toLowerCase() === name.toLowerCase() - ); - - if (alias) { - return alias[1]; - } else { - return null; - } - } -} diff --git a/scenario/src/Utils.ts b/scenario/src/Utils.ts deleted file mode 100644 index 3820335e0..000000000 --- a/scenario/src/Utils.ts +++ /dev/null @@ -1,133 +0,0 @@ -import { Event } from './Event'; -import { World } from './World'; -import { AbiItem } from 'web3-utils'; - -// Wraps the element in an array, if it was not already an array -// If array is null or undefined, return the empty array -export function mustArray(arg: T[] | T): T[] { - if (Array.isArray(arg)) { - return arg; - } else { - if (arg === null || arg === undefined) { - return []; - } else { - return [arg]; - } - } -} - -// Asserts that the array must be given length and if so returns it, otherwise -// it will raise an error -export function mustLen(arg: any[] | any, len: number, maxLen?: number): any[] { - if (!Array.isArray(arg)) { - throw `Expected array of length ${len}, got ${arg}`; - } else if (maxLen === undefined && arg.length !== len) { - throw `Expected array of length ${len}, got length ${arg.length} (${arg})`; - } else if (maxLen !== undefined && (arg.length < len || arg.length > maxLen)) { - throw `Expected array of length ${len}-${maxLen}, got length ${arg.length} (${arg})`; - } else { - return arg; - } -} - -export function mustString(arg: Event): string { - if (typeof arg === 'string') { - return arg; - } - - throw new Error(`Expected string argument, got ${arg.toString()}`); -} - -export function rawValues(args) { - if (Array.isArray(args)) - return args.map(rawValues); - if (Array.isArray(args.val)) - return args.val.map(rawValues); - return args.val; -} - -// Web3 doesn't have a function ABI parser.. not sure why.. but we build a simple encoder -// that accepts "fun(uint256,uint256)" and params and returns the encoded value. -export function encodeABI(world: World, fnABI: string, fnParams: string[]): string { - if (fnParams.length == 0) { - return world.web3.eth.abi.encodeFunctionSignature(fnABI); - } else { - const regex = /(\w+)\(([\w,\[\]]+)\)/; - const res = regex.exec(fnABI); - if (!res) { - throw new Error(`Expected ABI signature, got: ${fnABI}`); - } - const [_, fnName, fnInputs] = <[string, string, string]>(res); - const jsonInterface = { - name: fnName, - inputs: fnInputs.split(',').map(i => ({ name: '', type: i })) - }; - // XXXS - return world.web3.eth.abi.encodeFunctionCall(jsonInterface, fnParams); - } -} - -export function encodeParameters(world: World, fnABI: string, fnParams: string[]): string { - const regex = /(\w+)\(([\w,\[\]]+)\)/; - const res = regex.exec(fnABI); - if (!res) { - return '0x0'; - } - const [_, __, fnInputs] = <[string, string, string]>(res); - return world.web3.eth.abi.encodeParameters(fnInputs.split(','), fnParams); -} - -export function decodeParameters(world: World, fnABI: string, data: string): string[] { - const regex = /(\w+)\(([\w,\[\]]+)\)/; - const res = regex.exec(fnABI); - if (!res) { - return []; - } - const [_, __, fnInputs] = <[string, string, string]>(res); - const inputTypes = fnInputs.split(','); - const parameters = world.web3.eth.abi.decodeParameters(inputTypes, data); - - return inputTypes.map((_, index) => parameters[index]); -} - -export async function getCurrentBlockNumber(world: World): Promise { - const { result: currentBlockNumber }: any = await sendRPC(world, 'eth_blockNumber', []); - return parseInt(currentBlockNumber); -} - -export function getCurrentTimestamp(): number { - return Math.floor(Date.now() / 1000); -} - - -export function sleep(timeout: number): Promise { - return new Promise((resolve, reject) => { - setTimeout(() => { - resolve(); - }, timeout); - }); -} - -export function sendRPC(world: World, method: string, params: any[]) { - return new Promise((resolve, reject) => { - if (!world.web3.currentProvider || typeof (world.web3.currentProvider) === 'string') { - return reject(`cannot send from currentProvider=${world.web3.currentProvider}`); - } - - world.web3.currentProvider.send( - { - jsonrpc: '2.0', - method: method, - params: params, - id: new Date().getTime() // Id of the request; anything works, really - }, - (err, response) => { - if (err) { - reject(err); - } else { - resolve(response); - } - } - ); - }); -} diff --git a/scenario/src/Value.ts b/scenario/src/Value.ts deleted file mode 100644 index 25c8c0a4c..000000000 --- a/scenario/src/Value.ts +++ /dev/null @@ -1,424 +0,0 @@ -import {World} from './World'; -import {Event} from './Event'; -import BigNumber from 'bignumber.js'; -import {toEncodableNum} from './Encoding'; -import {formatEvent} from './Formatter'; - -BigNumber.config({ ROUNDING_MODE: 3 }); -const mantissaOne = new BigNumber('1.0e18'); - -export enum Order { - EQUAL, - LESS_THAN, - GREATER_THAN -} - -export interface Value { - compareTo(world: World, given: Value): boolean - compareOrder(world: World, given: Value): Order - toString(): string - truthy(): boolean -} - -function compareInt(a: number, b: number): Order { - if (a === b) { - return Order.EQUAL; - } else if (a > b) { - return Order.GREATER_THAN; - } else { - return Order.LESS_THAN; - } -} - -export class EventV implements Value { - val: Event - - constructor(val) { - this.val = val; - } - - compareTo(world: World, given: Value): boolean { - if (given instanceof EventV) { - return JSON.stringify(this.val) === JSON.stringify(given.val); - } else { - throw new Error(`Cannot compare ${typeof this} to ${typeof given} (${this.toString()}, ${given.toString()})`); - } - } - - compareOrder(world: World, given: Value): Order { - throw new Error(`Cannot compare order of ${typeof this} to ${typeof given} (${this.toString()}, ${given.toString()})`); - } - - toString() { - return `EventV`; - } - - truthy() { - // This check applies to strings or arrays :) - return this.val.length > 0; - } -} - -export class AnythingV implements Value { - compareTo(world: World, given: Value): boolean { - // Everything is awesome. - return true; - } - - compareOrder(world: World, given: Value): Order { - throw new Error(`Cannot compare order of ${typeof this} to ${typeof given} (${this.toString()}, ${given.toString()})`); - } - - toString() { - return `AnythingV<>`; - } - - truthy() { - return true; - } -} - -export class NothingV implements Value { - val: null - - constructor() { - this.val = null; - } - - compareTo(world: World, given: Value): boolean { - // Everything is not awesome. - return false; - } - - compareOrder(world: World, given: Value): Order { - throw new Error(`Cannot compare order of ${typeof this} to ${typeof given} (${this.toString()}, ${given.toString()})`); - } - - encode() { - return null; - } - - toString() { - return `NothingV<>`; - } - - truthy() { - return false; - } -} - -export class BoolV implements Value { - val: boolean - - constructor(val) { - this.val = val; - } - - compareTo(world: World, given: Value): boolean { - if (given instanceof BoolV) { - return this.val === given.val; - } else if (given instanceof NumberV) { - return this.compareTo(world, given.toBoolV()); - } else if (given instanceof StringV && ( given.val === 'true' || given.val === 'false' )) { - return this.val || given.val !== 'true'; - } else { - throw new Error(`Cannot compare ${typeof this} to ${typeof given} (${this.toString()}, ${given.toString()})`); - } - } - - compareOrder(world: World, given: Value): Order { - throw new Error(`Cannot compare order of ${typeof this} to ${typeof given} (${this.toString()}, ${given.toString()})`); - } - - toString() { - return `BoolV`; - } - - truthy() { - return this.val; - } -} - -export class StringV implements Value { - val: string - - constructor(val) { - this.val = val; - } - - compareTo(world: World, given: Value): boolean { - if (given instanceof StringV) { - return this.val === given.val; - } else if ( given instanceof AddressV) { - return world.web3.utils.toChecksumAddress(this.val) === world.web3.utils.toChecksumAddress(given.val); - } else { - throw new Error(`Cannot compare ${typeof this} to ${typeof given} (${this.toString()}, ${given.toString()})`); - } - } - - compareOrder(world: World, given: Value): Order { - throw new Error(`Cannot compare order of ${typeof this} to ${typeof given} (${this.toString()}, ${given.toString()})`); - } - - toString() { - return `StringV`; - } - - truthy() { - return this.val.length > 0; - } -} - -export class MapV implements Value { - val: object - - constructor(val) { - this.val = val; - } - - compareTo(world: World, given: Value): boolean { - if (given instanceof MapV) { - return JSON.stringify(this.val) === JSON.stringify(given.val); - } else { - throw new Error(`Cannot compare ${typeof this} to ${typeof given} (${this.toString()}, ${given.toString()})`); - } - } - - compareOrder(world: World, given: Value): Order { - throw new Error(`Cannot compare order of ${typeof this} to ${typeof given} (${this.toString()}, ${given.toString()})`); - } - - toString() { - return `MapV`; - } - - truthy() { - return Object.keys(this.val).length > 0; - } -} - -export class AddressV implements Value { - val: string - - constructor(val) { - this.val = val; - } - - compareTo(world: World, given: Value): boolean { - if (given instanceof AddressV || given instanceof StringV) { - return world.web3.utils.toChecksumAddress(this.val) === world.web3.utils.toChecksumAddress(given.val); - } else { - throw new Error(`Cannot compare ${typeof this} to ${typeof given} (${this.toString()}, ${given.toString()})`); - } - } - - compareOrder(world: World, given: Value): Order { - throw new Error(`Cannot compare order of ${typeof this} to ${typeof given} (${this.toString()}, ${given.toString()})`); - } - - toString() { - return `AddressV`; - } - - truthy() { - return this.val !== "0x0000000000000000000000000000000000000000"; - } -} - -export class NumberV implements Value { - val : number | string - - constructor(val: number | string, denom?: number | undefined) { - if (denom) { - this.val = Number(val) / denom; - } else { - this.val = val; - } - } - - toNumber(): number { - return Number(this.val); - } - - encode() { - return toEncodableNum(this.val); - } - - compareTo(world: World, given: Value): boolean { - if (given instanceof NumberV) { - const thisBig = new BigNumber(this.val).toFixed(); - const givenBig = new BigNumber(given.val).toFixed(); - - return thisBig === givenBig; - } else if (given instanceof PreciseV) { - return this.compareTo(world, given.toNumberV()); - } else if (given instanceof StringV) { - return this.compareTo(world, new NumberV(Number(given.val))); - } else { - throw new Error(`Cannot compare ${typeof this} to ${typeof given} (${this.toString()}, ${given.toString()})`); - } - } - - compareOrder(world: World, given: Value): Order { - if (given instanceof NumberV) { - const thisBig = new BigNumber(this.val).toNumber(); - const givenBig = new BigNumber(given.val).toNumber(); - - return compareInt(thisBig, givenBig); - } else if (given instanceof PreciseV) { - return this.compareOrder(world, given.toNumberV()); - } else { - throw new Error(`Cannot compare ${typeof this} to ${typeof given} (${this.toString()}, ${given.toString()})`); - } - } - - toBoolV(): BoolV { - if (this.val === 0) { - return new BoolV(true) - } else if (this.val === 1) { - return new BoolV(false); - } - - throw new Error(`Cannot convert number ${this.val} into bool`) - } - - asExp(denom=undefined): string { - return new BigNumber(this.val).toExponential(); - } - - show(): string { - return new BigNumber(this.val).toExponential(); - } - - toString() { - return `NumberV`; - } - - truthy() { - return this.val != 0; - } - - add(b: NumberV): NumberV { - return new NumberV(new BigNumber(this.val).plus(new BigNumber(b.val)).toFixed()); - } - - div(b: NumberV): NumberV { - return new NumberV(new BigNumber(this.val).div(new BigNumber(b.val)).toFixed()); - } - - mul(b: NumberV): NumberV { - return new NumberV(new BigNumber(this.val).times(new BigNumber(b.val)).toFixed()); - } - - sub(b: NumberV): NumberV { - return new NumberV(new BigNumber(this.val).minus(new BigNumber(b.val)).toFixed()); - } -} - -export class ExpNumberV extends NumberV { - show() { - return new BigNumber(this.val).dividedBy(mantissaOne).toNumber().toString(); - } -} - -export class PercentV extends NumberV { - show() { - return new BigNumber(this.val).dividedBy(mantissaOne).multipliedBy(new BigNumber(100)).toNumber().toString() + '%'; - } -} - -export class PreciseV implements Value { - val: number - precision: number - - constructor(val, precision) { - this.val = val; - this.precision = precision; - } - - compareTo(world: World, given: Value): boolean { - if (given instanceof NumberV) { - const thisBig = new BigNumber(this.val.toString()).toPrecision(this.precision); - const givenBig = new BigNumber(given.val.toString()).toPrecision(this.precision); - - return thisBig === givenBig; - } else if (given instanceof PreciseV) { - // TODO: Is this okay? - return this.compareTo(world, given.toNumberV()); - } else { - throw new Error(`Cannot compare ${typeof this} to ${typeof given} (${this.toString()}, ${given.toString()})`); - } - } - - compareOrder(world: World, given: Value): Order { - throw new Error(`Cannot compare order of ${typeof this} to ${typeof given} (${this.toString()}, ${given.toString()})`); - } - - toNumberV(): NumberV { - return new NumberV(this.val); - } - - toString() { - return `PreciseV`; - } - - truthy() { - return this.val != 0; - } -} - -export class ListV implements Value { - val: Value[] - - constructor(els) { - this.val = els; - } - - compareTo(world: World, given: Value): boolean { - if (given instanceof ListV || given instanceof ArrayV) { - return this.val.every((el, i) => el.compareTo(world, given.val[i] || new NothingV())); - } else { - throw new Error(`Cannot compare ${typeof this} to ${typeof given} (${this.toString()}, ${given.toString()})`); - } - } - - compareOrder(world: World, given: Value): Order { - throw new Error(`Cannot compare order of ${typeof this} to ${typeof given} (${this.toString()}, ${given.toString()})`); - } - - toString() { - return `ListV el.toString()).join(',')}>`; - } - - truthy() { - return this.val.length > 0; - } -} - -export class ArrayV implements Value { - val: T[] - - constructor(els) { - this.val = els; - } - - compareTo(world: World, given: Value): boolean { - if (given instanceof ListV || given instanceof ArrayV) { - return this.val.every((el, i) => el.compareTo(world, given.val[i] || new NothingV())); - } else { - throw new Error(`Cannot compare ${typeof this} to ${typeof given} (${this.toString()}, ${given.toString()})`); - } - } - - compareOrder(world: World, given: Value): Order { - throw new Error(`Cannot compare order of ${typeof this} to ${typeof given} (${this.toString()}, ${given.toString()})`); - } - - toString() { - return `ArrayV el.toString()).join(',')}>`; - } - - truthy() { - return this.val.length > 0; - } -} diff --git a/scenario/src/Value/AnchoredViewValue.ts b/scenario/src/Value/AnchoredViewValue.ts deleted file mode 100644 index a63da77c7..000000000 --- a/scenario/src/Value/AnchoredViewValue.ts +++ /dev/null @@ -1,36 +0,0 @@ -import {Event} from '../Event'; -import {World} from '../World'; -import {AnchoredView} from '../Contract/AnchoredView'; -import {getAddressV} from '../CoreValue'; -import {AddressV, NumberV, Value} from '../Value'; -import {Arg, Fetcher, getFetcherValue} from '../Command'; -import {getAnchoredView} from '../ContractLookup'; - -export async function getAnchoredViewAddress(_: World, anchoredView: AnchoredView): Promise { - return new AddressV(anchoredView._address); -} - -async function getUnderlyingPrice(_: World, anchoredView: AnchoredView, asset: string): Promise { - return new NumberV(await anchoredView.methods.getUnderlyingPrice(asset).call()); -} - -export function anchoredViewFetchers() { - return [ - new Fetcher<{anchoredView: AnchoredView, asset: AddressV}, NumberV>(` - #### UnderlyingPrice - - * "UnderlyingPrice asset:
" - Gets the price of the given asset - `, - "UnderlyingPrice", - [ - new Arg("anchoredView", getAnchoredView, {implicit: true}), - new Arg("asset", getAddressV) - ], - (world, {anchoredView, asset}) => getUnderlyingPrice(world, anchoredView, asset.val) - ) - ]; -} - -export async function getAnchoredViewValue(world: World, event: Event): Promise { - return await getFetcherValue("AnchoredView", anchoredViewFetchers(), world, event); -} diff --git a/scenario/src/Value/CTokenDelegateValue.ts b/scenario/src/Value/CTokenDelegateValue.ts deleted file mode 100644 index b368552a5..000000000 --- a/scenario/src/Value/CTokenDelegateValue.ts +++ /dev/null @@ -1,51 +0,0 @@ -import { Event } from '../Event'; -import { World } from '../World'; -import { CErc20Delegate } from '../Contract/CErc20Delegate'; -import { - getCoreValue, - mapValue -} from '../CoreValue'; -import { Arg, Fetcher, getFetcherValue } from '../Command'; -import { - AddressV, - Value, -} from '../Value'; -import { getWorldContractByAddress, getCTokenDelegateAddress } from '../ContractLookup'; - -export async function getCTokenDelegateV(world: World, event: Event): Promise { - const address = await mapValue( - world, - event, - (str) => new AddressV(getCTokenDelegateAddress(world, str)), - getCoreValue, - AddressV - ); - - return getWorldContractByAddress(world, address.val); -} - -async function cTokenDelegateAddress(world: World, cTokenDelegate: CErc20Delegate): Promise { - return new AddressV(cTokenDelegate._address); -} - -export function cTokenDelegateFetchers() { - return [ - new Fetcher<{ cTokenDelegate: CErc20Delegate }, AddressV>(` - #### Address - - * "CTokenDelegate Address" - Returns address of CTokenDelegate contract - * E.g. "CTokenDelegate cDaiDelegate Address" - Returns cDaiDelegate's address - `, - "Address", - [ - new Arg("cTokenDelegate", getCTokenDelegateV) - ], - (world, { cTokenDelegate }) => cTokenDelegateAddress(world, cTokenDelegate), - { namePos: 1 } - ), - ]; -} - -export async function getCTokenDelegateValue(world: World, event: Event): Promise { - return await getFetcherValue("CTokenDelegate", cTokenDelegateFetchers(), world, event); -} diff --git a/scenario/src/Value/CTokenValue.ts b/scenario/src/Value/CTokenValue.ts deleted file mode 100644 index f0cd18342..000000000 --- a/scenario/src/Value/CTokenValue.ts +++ /dev/null @@ -1,395 +0,0 @@ -import { Event } from '../Event'; -import { World } from '../World'; -import { CToken } from '../Contract/CToken'; -import { CErc20Delegator } from '../Contract/CErc20Delegator'; -import { Erc20 } from '../Contract/Erc20'; -import { - getAddressV, - getCoreValue, - getStringV, - mapValue -} from '../CoreValue'; -import { Arg, Fetcher, getFetcherValue } from '../Command'; -import { - AddressV, - NumberV, - Value, - StringV -} from '../Value'; -import { getWorldContractByAddress, getCTokenAddress } from '../ContractLookup'; - -export async function getCTokenV(world: World, event: Event): Promise { - const address = await mapValue( - world, - event, - (str) => new AddressV(getCTokenAddress(world, str)), - getCoreValue, - AddressV - ); - - return getWorldContractByAddress(world, address.val); -} - -export async function getCErc20DelegatorV(world: World, event: Event): Promise { - const address = await mapValue( - world, - event, - (str) => new AddressV(getCTokenAddress(world, str)), - getCoreValue, - AddressV - ); - - return getWorldContractByAddress(world, address.val); -} - -async function getInterestRateModel(world: World, cToken: CToken): Promise { - return new AddressV(await cToken.methods.interestRateModel().call()); -} - -async function cTokenAddress(world: World, cToken: CToken): Promise { - return new AddressV(cToken._address); -} - -async function getCTokenAdmin(world: World, cToken: CToken): Promise { - return new AddressV(await cToken.methods.admin().call()); -} - -async function getCTokenPendingAdmin(world: World, cToken: CToken): Promise { - return new AddressV(await cToken.methods.pendingAdmin().call()); -} - -async function balanceOfUnderlying(world: World, cToken: CToken, user: string): Promise { - return new NumberV(await cToken.methods.balanceOfUnderlying(user).call()); -} - -async function getBorrowBalance(world: World, cToken: CToken, user): Promise { - return new NumberV(await cToken.methods.borrowBalanceCurrent(user).call()); -} - -async function getBorrowBalanceStored(world: World, cToken: CToken, user): Promise { - return new NumberV(await cToken.methods.borrowBalanceStored(user).call()); -} - -async function getTotalBorrows(world: World, cToken: CToken): Promise { - return new NumberV(await cToken.methods.totalBorrows().call()); -} - -async function getTotalBorrowsCurrent(world: World, cToken: CToken): Promise { - return new NumberV(await cToken.methods.totalBorrowsCurrent().call()); -} - -async function getReserveFactor(world: World, cToken: CToken): Promise { - return new NumberV(await cToken.methods.reserveFactorMantissa().call(), 1.0e18); -} - -async function getTotalReserves(world: World, cToken: CToken): Promise { - return new NumberV(await cToken.methods.totalReserves().call()); -} - -async function getComptroller(world: World, cToken: CToken): Promise { - return new AddressV(await cToken.methods.comptroller().call()); -} - -async function getExchangeRateStored(world: World, cToken: CToken): Promise { - return new NumberV(await cToken.methods.exchangeRateStored().call()); -} - -async function getExchangeRate(world: World, cToken: CToken): Promise { - return new NumberV(await cToken.methods.exchangeRateCurrent().call(), 1e18); -} - -async function getCash(world: World, cToken: CToken): Promise { - return new NumberV(await cToken.methods.getCash().call()); -} - -async function getInterestRate(world: World, cToken: CToken): Promise { - return new NumberV(await cToken.methods.borrowRatePerBlock().call(), 1.0e18 / 2102400); -} - -async function getImplementation(world: World, cToken: CToken): Promise { - return new AddressV(await (cToken as CErc20Delegator).methods.implementation().call()); -} - -export function cTokenFetchers() { - return [ - new Fetcher<{ cToken: CToken }, AddressV>(` - #### Address - - * "CToken Address" - Returns address of CToken contract - * E.g. "CToken cZRX Address" - Returns cZRX's address - `, - "Address", - [ - new Arg("cToken", getCTokenV) - ], - (world, { cToken }) => cTokenAddress(world, cToken), - { namePos: 1 } - ), - - new Fetcher<{ cToken: CToken }, AddressV>(` - #### InterestRateModel - - * "CToken InterestRateModel" - Returns the interest rate model of CToken contract - * E.g. "CToken cZRX InterestRateModel" - Returns cZRX's interest rate model - `, - "InterestRateModel", - [ - new Arg("cToken", getCTokenV) - ], - (world, { cToken }) => getInterestRateModel(world, cToken), - { namePos: 1 } - ), - - new Fetcher<{ cToken: CToken }, AddressV>(` - #### Admin - - * "CToken Admin" - Returns the admin of CToken contract - * E.g. "CToken cZRX Admin" - Returns cZRX's admin - `, - "Admin", - [ - new Arg("cToken", getCTokenV) - ], - (world, { cToken }) => getCTokenAdmin(world, cToken), - { namePos: 1 } - ), - - new Fetcher<{ cToken: CToken }, AddressV>(` - #### PendingAdmin - - * "CToken PendingAdmin" - Returns the pending admin of CToken contract - * E.g. "CToken cZRX PendingAdmin" - Returns cZRX's pending admin - `, - "PendingAdmin", - [ - new Arg("cToken", getCTokenV) - ], - (world, { cToken }) => getCTokenPendingAdmin(world, cToken), - { namePos: 1 } - ), - - new Fetcher<{ cToken: CToken }, AddressV>(` - #### Underlying - - * "CToken Underlying" - Returns the underlying asset (if applicable) - * E.g. "CToken cZRX Underlying" - `, - "Underlying", - [ - new Arg("cToken", getCTokenV) - ], - async (world, { cToken }) => new AddressV(await cToken.methods.underlying().call()), - { namePos: 1 } - ), - - new Fetcher<{ cToken: CToken, address: AddressV }, NumberV>(` - #### UnderlyingBalance - - * "CToken UnderlyingBalance " - Returns a user's underlying balance (based on given exchange rate) - * E.g. "CToken cZRX UnderlyingBalance Geoff" - `, - "UnderlyingBalance", - [ - new Arg("cToken", getCTokenV), - new Arg("address", getAddressV) - ], - (world, { cToken, address }) => balanceOfUnderlying(world, cToken, address.val), - { namePos: 1 } - ), - - new Fetcher<{ cToken: CToken, address: AddressV }, NumberV>(` - #### BorrowBalance - - * "CToken BorrowBalance " - Returns a user's borrow balance (including interest) - * E.g. "CToken cZRX BorrowBalance Geoff" - `, - "BorrowBalance", - [ - new Arg("cToken", getCTokenV), - new Arg("address", getAddressV) - ], - (world, { cToken, address }) => getBorrowBalance(world, cToken, address.val), - { namePos: 1 } - ), - - new Fetcher<{ cToken: CToken, address: AddressV }, NumberV>(` - #### BorrowBalanceStored - - * "CToken BorrowBalanceStored " - Returns a user's borrow balance (without specifically re-accruing interest) - * E.g. "CToken cZRX BorrowBalanceStored Geoff" - `, - "BorrowBalanceStored", - [ - new Arg("cToken", getCTokenV), - new Arg("address", getAddressV) - ], - (world, { cToken, address }) => getBorrowBalanceStored(world, cToken, address.val), - { namePos: 1 } - ), - - new Fetcher<{ cToken: CToken }, NumberV>(` - #### TotalBorrows - - * "CToken TotalBorrows" - Returns the cToken's total borrow balance - * E.g. "CToken cZRX TotalBorrows" - `, - "TotalBorrows", - [ - new Arg("cToken", getCTokenV) - ], - (world, { cToken }) => getTotalBorrows(world, cToken), - { namePos: 1 } - ), - - new Fetcher<{ cToken: CToken }, NumberV>(` - #### TotalBorrowsCurrent - - * "CToken TotalBorrowsCurrent" - Returns the cToken's total borrow balance with interest - * E.g. "CToken cZRX TotalBorrowsCurrent" - `, - "TotalBorrowsCurrent", - [ - new Arg("cToken", getCTokenV) - ], - (world, { cToken }) => getTotalBorrowsCurrent(world, cToken), - { namePos: 1 } - ), - - new Fetcher<{ cToken: CToken }, NumberV>(` - #### Reserves - - * "CToken Reserves" - Returns the cToken's total reserves - * E.g. "CToken cZRX Reserves" - `, - "Reserves", - [ - new Arg("cToken", getCTokenV) - ], - (world, { cToken }) => getTotalReserves(world, cToken), - { namePos: 1 } - ), - - new Fetcher<{ cToken: CToken }, NumberV>(` - #### ReserveFactor - - * "CToken ReserveFactor" - Returns reserve factor of CToken contract - * E.g. "CToken cZRX ReserveFactor" - Returns cZRX's reserve factor - `, - "ReserveFactor", - [ - new Arg("cToken", getCTokenV) - ], - (world, { cToken }) => getReserveFactor(world, cToken), - { namePos: 1 } - ), - - new Fetcher<{ cToken: CToken }, AddressV>(` - #### Comptroller - - * "CToken Comptroller" - Returns the cToken's comptroller - * E.g. "CToken cZRX Comptroller" - `, - "Comptroller", - [ - new Arg("cToken", getCTokenV) - ], - (world, { cToken }) => getComptroller(world, cToken), - { namePos: 1 } - ), - - new Fetcher<{ cToken: CToken }, NumberV>(` - #### ExchangeRateStored - - * "CToken ExchangeRateStored" - Returns the cToken's exchange rate (based on balances stored) - * E.g. "CToken cZRX ExchangeRateStored" - `, - "ExchangeRateStored", - [ - new Arg("cToken", getCTokenV) - ], - (world, { cToken }) => getExchangeRateStored(world, cToken), - { namePos: 1 } - ), - - new Fetcher<{ cToken: CToken }, NumberV>(` - #### ExchangeRate - - * "CToken ExchangeRate" - Returns the cToken's current exchange rate - * E.g. "CToken cZRX ExchangeRate" - `, - "ExchangeRate", - [ - new Arg("cToken", getCTokenV) - ], - (world, { cToken }) => getExchangeRate(world, cToken), - { namePos: 1 } - ), - - new Fetcher<{ cToken: CToken }, NumberV>(` - #### Cash - - * "CToken Cash" - Returns the cToken's current cash - * E.g. "CToken cZRX Cash" - `, - "Cash", - [ - new Arg("cToken", getCTokenV) - ], - (world, { cToken }) => getCash(world, cToken), - { namePos: 1 } - ), - - new Fetcher<{ cToken: CToken }, NumberV>(` - #### InterestRate - - * "CToken InterestRate" - Returns the cToken's current interest rate - * E.g. "CToken cZRX InterestRate" - `, - "InterestRate", - [ - new Arg("cToken", getCTokenV) - ], - (world, {cToken}) => getInterestRate(world, cToken), - {namePos: 1} - ), - new Fetcher<{cToken: CToken, signature: StringV}, NumberV>(` - #### CallNum - - * "CToken Call " - Simple direct call method, for now with no parameters - * E.g. "CToken cZRX Call \"borrowIndex()\"" - `, - "CallNum", - [ - new Arg("cToken", getCTokenV), - new Arg("signature", getStringV), - ], - async (world, {cToken, signature}) => { - const res = await world.web3.eth.call({ - to: cToken._address, - data: world.web3.eth.abi.encodeFunctionSignature(signature.val) - }) - const resNum : any = world.web3.eth.abi.decodeParameter('uint256',res); - return new NumberV(resNum); - } - , - {namePos: 1} - ), - new Fetcher<{ cToken: CToken }, AddressV>(` - #### Implementation - - * "CToken Implementation" - Returns the cToken's current implementation - * E.g. "CToken cDAI Implementation" - `, - "Implementation", - [ - new Arg("cToken", getCTokenV) - ], - (world, { cToken }) => getImplementation(world, cToken), - { namePos: 1 } - ) - ]; -} - -export async function getCTokenValue(world: World, event: Event): Promise { - return await getFetcherValue("cToken", cTokenFetchers(), world, event); -} diff --git a/scenario/src/Value/CompValue.ts b/scenario/src/Value/CompValue.ts deleted file mode 100644 index d95672434..000000000 --- a/scenario/src/Value/CompValue.ts +++ /dev/null @@ -1,202 +0,0 @@ -import { Event } from '../Event'; -import { World } from '../World'; -import { Comp } from '../Contract/Comp'; -import { - getAddressV, - getNumberV -} from '../CoreValue'; -import { - AddressV, - ListV, - NumberV, - StringV, - Value -} from '../Value'; -import { Arg, Fetcher, getFetcherValue } from '../Command'; -import { getComp } from '../ContractLookup'; - -export function compFetchers() { - return [ - new Fetcher<{ comp: Comp }, AddressV>(` - #### Address - - * " Address" - Returns the address of Comp token - * E.g. "Comp Address" - `, - "Address", - [ - new Arg("comp", getComp, { implicit: true }) - ], - async (world, { comp }) => new AddressV(comp._address) - ), - - new Fetcher<{ comp: Comp }, StringV>(` - #### Name - - * " Name" - Returns the name of the Comp token - * E.g. "Comp Name" - `, - "Name", - [ - new Arg("comp", getComp, { implicit: true }) - ], - async (world, { comp }) => new StringV(await comp.methods.name().call()) - ), - - new Fetcher<{ comp: Comp }, StringV>(` - #### Symbol - - * " Symbol" - Returns the symbol of the Comp token - * E.g. "Comp Symbol" - `, - "Symbol", - [ - new Arg("comp", getComp, { implicit: true }) - ], - async (world, { comp }) => new StringV(await comp.methods.symbol().call()) - ), - - new Fetcher<{ comp: Comp }, NumberV>(` - #### Decimals - - * " Decimals" - Returns the number of decimals of the Comp token - * E.g. "Comp Decimals" - `, - "Decimals", - [ - new Arg("comp", getComp, { implicit: true }) - ], - async (world, { comp }) => new NumberV(await comp.methods.decimals().call()) - ), - - new Fetcher<{ comp: Comp }, NumberV>(` - #### TotalSupply - - * "Comp TotalSupply" - Returns Comp token's total supply - `, - "TotalSupply", - [ - new Arg("comp", getComp, { implicit: true }) - ], - async (world, { comp }) => new NumberV(await comp.methods.totalSupply().call()) - ), - - new Fetcher<{ comp: Comp, address: AddressV }, NumberV>(` - #### TokenBalance - - * "Comp TokenBalance
" - Returns the Comp token balance of a given address - * E.g. "Comp TokenBalance Geoff" - Returns Geoff's Comp balance - `, - "TokenBalance", - [ - new Arg("comp", getComp, { implicit: true }), - new Arg("address", getAddressV) - ], - async (world, { comp, address }) => new NumberV(await comp.methods.balanceOf(address.val).call()) - ), - - new Fetcher<{ comp: Comp, owner: AddressV, spender: AddressV }, NumberV>(` - #### Allowance - - * "Comp Allowance owner:
spender:
" - Returns the Comp allowance from owner to spender - * E.g. "Comp Allowance Geoff Torrey" - Returns the Comp allowance of Geoff to Torrey - `, - "Allowance", - [ - new Arg("comp", getComp, { implicit: true }), - new Arg("owner", getAddressV), - new Arg("spender", getAddressV) - ], - async (world, { comp, owner, spender }) => new NumberV(await comp.methods.allowance(owner.val, spender.val).call()) - ), - - new Fetcher<{ comp: Comp, account: AddressV }, NumberV>(` - #### GetCurrentVotes - - * "Comp GetCurrentVotes account:
" - Returns the current Comp votes balance for an account - * E.g. "Comp GetCurrentVotes Geoff" - Returns the current Comp vote balance of Geoff - `, - "GetCurrentVotes", - [ - new Arg("comp", getComp, { implicit: true }), - new Arg("account", getAddressV), - ], - async (world, { comp, account }) => new NumberV(await comp.methods.getCurrentVotes(account.val).call()) - ), - - new Fetcher<{ comp: Comp, account: AddressV, blockNumber: NumberV }, NumberV>(` - #### GetPriorVotes - - * "Comp GetPriorVotes account:
blockBumber:" - Returns the current Comp votes balance at given block - * E.g. "Comp GetPriorVotes Geoff 5" - Returns the Comp vote balance for Geoff at block 5 - `, - "GetPriorVotes", - [ - new Arg("comp", getComp, { implicit: true }), - new Arg("account", getAddressV), - new Arg("blockNumber", getNumberV), - ], - async (world, { comp, account, blockNumber }) => new NumberV(await comp.methods.getPriorVotes(account.val, blockNumber.encode()).call()) - ), - - new Fetcher<{ comp: Comp, account: AddressV }, NumberV>(` - #### GetCurrentVotesBlock - - * "Comp GetCurrentVotesBlock account:
" - Returns the current Comp votes checkpoint block for an account - * E.g. "Comp GetCurrentVotesBlock Geoff" - Returns the current Comp votes checkpoint block for Geoff - `, - "GetCurrentVotesBlock", - [ - new Arg("comp", getComp, { implicit: true }), - new Arg("account", getAddressV), - ], - async (world, { comp, account }) => { - const numCheckpoints = Number(await comp.methods.numCheckpoints(account.val).call()); - const checkpoint = await comp.methods.checkpoints(account.val, numCheckpoints - 1).call(); - - return new NumberV(checkpoint.fromBlock); - } - ), - - new Fetcher<{ comp: Comp, account: AddressV }, NumberV>(` - #### VotesLength - - * "Comp VotesLength account:
" - Returns the Comp vote checkpoint array length - * E.g. "Comp VotesLength Geoff" - Returns the Comp vote checkpoint array length of Geoff - `, - "VotesLength", - [ - new Arg("comp", getComp, { implicit: true }), - new Arg("account", getAddressV), - ], - async (world, { comp, account }) => new NumberV(await comp.methods.numCheckpoints(account.val).call()) - ), - - new Fetcher<{ comp: Comp, account: AddressV }, ListV>(` - #### AllVotes - - * "Comp AllVotes account:
" - Returns information about all votes an account has had - * E.g. "Comp AllVotes Geoff" - Returns the Comp vote checkpoint array - `, - "AllVotes", - [ - new Arg("comp", getComp, { implicit: true }), - new Arg("account", getAddressV), - ], - async (world, { comp, account }) => { - const numCheckpoints = Number(await comp.methods.numCheckpoints(account.val).call()); - const checkpoints = await Promise.all(new Array(numCheckpoints).fill(undefined).map(async (_, i) => { - const {fromBlock, votes} = await comp.methods.checkpoints(account.val, i).call(); - - return new StringV(`Block ${fromBlock}: ${votes} vote${votes !== 1 ? "s" : ""}`); - })); - - return new ListV(checkpoints); - } - ) - ]; -} - -export async function getCompValue(world: World, event: Event): Promise { - return await getFetcherValue("Comp", compFetchers(), world, event); -} diff --git a/scenario/src/Value/ComptrollerImplValue.ts b/scenario/src/Value/ComptrollerImplValue.ts deleted file mode 100644 index a7678b969..000000000 --- a/scenario/src/Value/ComptrollerImplValue.ts +++ /dev/null @@ -1,35 +0,0 @@ -import {Event} from '../Event'; -import {World} from '../World'; -import {ComptrollerImpl} from '../Contract/ComptrollerImpl'; -import { - getAddressV -} from '../CoreValue'; -import { - AddressV, - Value -} from '../Value'; -import {Arg, Fetcher, getFetcherValue} from '../Command'; -import {getComptrollerImpl} from '../ContractLookup'; - -export async function getComptrollerImplAddress(world: World, comptrollerImpl: ComptrollerImpl): Promise { - return new AddressV(comptrollerImpl._address); -} - -export function comptrollerImplFetchers() { - return [ - new Fetcher<{comptrollerImpl: ComptrollerImpl}, AddressV>(` - #### Address - - * "ComptrollerImpl Address" - Returns address of comptroller implementation - `, - "Address", - [new Arg("comptrollerImpl", getComptrollerImpl)], - (world, {comptrollerImpl}) => getComptrollerImplAddress(world, comptrollerImpl), - {namePos: 1} - ) - ]; -} - -export async function getComptrollerImplValue(world: World, event: Event): Promise { - return await getFetcherValue("ComptrollerImpl", comptrollerImplFetchers(), world, event); -} diff --git a/scenario/src/Value/ComptrollerValue.ts b/scenario/src/Value/ComptrollerValue.ts deleted file mode 100644 index d60b29509..000000000 --- a/scenario/src/Value/ComptrollerValue.ts +++ /dev/null @@ -1,652 +0,0 @@ -import {Event} from '../Event'; -import {World} from '../World'; -import {Comptroller} from '../Contract/Comptroller'; -import {CToken} from '../Contract/CToken'; -import { - getAddressV, - getCoreValue, - getStringV, - getNumberV -} from '../CoreValue'; -import { - AddressV, - BoolV, - ListV, - NumberV, - StringV, - Value -} from '../Value'; -import {Arg, Fetcher, getFetcherValue} from '../Command'; -import {getComptroller} from '../ContractLookup'; -import {encodedNumber} from '../Encoding'; -import {getCTokenV} from '../Value/CTokenValue'; -import { encodeParameters, encodeABI } from '../Utils'; - -export async function getComptrollerAddress(world: World, comptroller: Comptroller): Promise { - return new AddressV(comptroller._address); -} - -export async function getLiquidity(world: World, comptroller: Comptroller, user: string): Promise { - let {0: error, 1: liquidity, 2: shortfall} = await comptroller.methods.getAccountLiquidity(user).call(); - if (Number(error) != 0) { - throw new Error(`Failed to compute account liquidity: error code = ${error}`); - } - return new NumberV(Number(liquidity) - Number(shortfall)); -} - -export async function getHypotheticalLiquidity(world: World, comptroller: Comptroller, account: string, asset: string, redeemTokens: encodedNumber, borrowAmount: encodedNumber): Promise { - let {0: error, 1: liquidity, 2: shortfall} = await comptroller.methods.getHypotheticalAccountLiquidity(account, asset, redeemTokens, borrowAmount).call(); - if (Number(error) != 0) { - throw new Error(`Failed to compute account hypothetical liquidity: error code = ${error}`); - } - return new NumberV(Number(liquidity) - Number(shortfall)); -} - -async function getPriceOracle(world: World, comptroller: Comptroller): Promise { - return new AddressV(await comptroller.methods.oracle().call()); -} - -async function getCloseFactor(world: World, comptroller: Comptroller): Promise { - return new NumberV(await comptroller.methods.closeFactorMantissa().call(), 1e18); -} - -async function getMaxAssets(world: World, comptroller: Comptroller): Promise { - return new NumberV(await comptroller.methods.maxAssets().call()); -} - -async function getLiquidationIncentive(world: World, comptroller: Comptroller): Promise { - return new NumberV(await comptroller.methods.liquidationIncentiveMantissa().call(), 1e18); -} - -async function getImplementation(world: World, comptroller: Comptroller): Promise { - return new AddressV(await comptroller.methods.comptrollerImplementation().call()); -} - -async function getBlockNumber(world: World, comptroller: Comptroller): Promise { - return new NumberV(await comptroller.methods.getBlockNumber().call()); -} - -async function getAdmin(world: World, comptroller: Comptroller): Promise { - return new AddressV(await comptroller.methods.admin().call()); -} - -async function getPendingAdmin(world: World, comptroller: Comptroller): Promise { - return new AddressV(await comptroller.methods.pendingAdmin().call()); -} - -async function getCollateralFactor(world: World, comptroller: Comptroller, cToken: CToken): Promise { - let {0: _isListed, 1: collateralFactorMantissa} = await comptroller.methods.markets(cToken._address).call(); - return new NumberV(collateralFactorMantissa, 1e18); -} - -async function membershipLength(world: World, comptroller: Comptroller, user: string): Promise { - return new NumberV(await comptroller.methods.membershipLength(user).call()); -} - -async function checkMembership(world: World, comptroller: Comptroller, user: string, cToken: CToken): Promise { - return new BoolV(await comptroller.methods.checkMembership(user, cToken._address).call()); -} - -async function getAssetsIn(world: World, comptroller: Comptroller, user: string): Promise { - let assetsList = await comptroller.methods.getAssetsIn(user).call(); - - return new ListV(assetsList.map((a) => new AddressV(a))); -} - -async function getCompMarkets(world: World, comptroller: Comptroller): Promise { - let mkts = await comptroller.methods.getCompMarkets().call(); - - return new ListV(mkts.map((a) => new AddressV(a))); -} - -async function checkListed(world: World, comptroller: Comptroller, cToken: CToken): Promise { - let {0: isListed, 1: _collateralFactorMantissa} = await comptroller.methods.markets(cToken._address).call(); - - return new BoolV(isListed); -} - -async function checkIsComped(world: World, comptroller: Comptroller, cToken: CToken): Promise { - let {0: isListed, 1: _collateralFactorMantissa, 2: isComped} = await comptroller.methods.markets(cToken._address).call(); - return new BoolV(isComped); -} - - -export function comptrollerFetchers() { - return [ - new Fetcher<{comptroller: Comptroller}, AddressV>(` - #### Address - - * "Comptroller Address" - Returns address of comptroller - `, - "Address", - [new Arg("comptroller", getComptroller, {implicit: true})], - (world, {comptroller}) => getComptrollerAddress(world, comptroller) - ), - new Fetcher<{comptroller: Comptroller, account: AddressV}, NumberV>(` - #### Liquidity - - * "Comptroller Liquidity " - Returns a given user's trued up liquidity - * E.g. "Comptroller Liquidity Geoff" - `, - "Liquidity", - [ - new Arg("comptroller", getComptroller, {implicit: true}), - new Arg("account", getAddressV) - ], - (world, {comptroller, account}) => getLiquidity(world, comptroller, account.val) - ), - new Fetcher<{comptroller: Comptroller, account: AddressV, action: StringV, amount: NumberV, cToken: CToken}, NumberV>(` - #### Hypothetical - - * "Comptroller Hypothetical " - Returns a given user's trued up liquidity given a hypothetical change in asset with redeeming a certain number of tokens and/or borrowing a given amount. - * E.g. "Comptroller Hypothetical Geoff Redeems 6.0 cZRX" - * E.g. "Comptroller Hypothetical Geoff Borrows 5.0 cZRX" - `, - "Hypothetical", - [ - new Arg("comptroller", getComptroller, {implicit: true}), - new Arg("account", getAddressV), - new Arg("action", getStringV), - new Arg("amount", getNumberV), - new Arg("cToken", getCTokenV) - ], - async (world, {comptroller, account, action, cToken, amount}) => { - let redeemTokens: NumberV; - let borrowAmount: NumberV; - - switch (action.val.toLowerCase()) { - case "borrows": - redeemTokens = new NumberV(0); - borrowAmount = amount; - break; - case "redeems": - redeemTokens = amount; - borrowAmount = new NumberV(0); - break; - default: - throw new Error(`Unknown hypothetical: ${action.val}`); - } - - return await getHypotheticalLiquidity(world, comptroller, account.val, cToken._address, redeemTokens.encode(), borrowAmount.encode()); - } - ), - new Fetcher<{comptroller: Comptroller}, AddressV>(` - #### Admin - - * "Comptroller Admin" - Returns the Comptrollers's admin - * E.g. "Comptroller Admin" - `, - "Admin", - [new Arg("comptroller", getComptroller, {implicit: true})], - (world, {comptroller}) => getAdmin(world, comptroller) - ), - new Fetcher<{comptroller: Comptroller}, AddressV>(` - #### PendingAdmin - - * "Comptroller PendingAdmin" - Returns the pending admin of the Comptroller - * E.g. "Comptroller PendingAdmin" - Returns Comptroller's pending admin - `, - "PendingAdmin", - [ - new Arg("comptroller", getComptroller, {implicit: true}), - ], - (world, {comptroller}) => getPendingAdmin(world, comptroller) - ), - new Fetcher<{comptroller: Comptroller}, AddressV>(` - #### PriceOracle - - * "Comptroller PriceOracle" - Returns the Comptrollers's price oracle - * E.g. "Comptroller PriceOracle" - `, - "PriceOracle", - [new Arg("comptroller", getComptroller, {implicit: true})], - (world, {comptroller}) => getPriceOracle(world, comptroller) - ), - new Fetcher<{comptroller: Comptroller}, NumberV>(` - #### CloseFactor - - * "Comptroller CloseFactor" - Returns the Comptrollers's close factor - * E.g. "Comptroller CloseFactor" - `, - "CloseFactor", - [new Arg("comptroller", getComptroller, {implicit: true})], - (world, {comptroller}) => getCloseFactor(world, comptroller) - ), - new Fetcher<{comptroller: Comptroller}, NumberV>(` - #### MaxAssets - - * "Comptroller MaxAssets" - Returns the Comptrollers's max assets - * E.g. "Comptroller MaxAssets" - `, - "MaxAssets", - [new Arg("comptroller", getComptroller, {implicit: true})], - (world, {comptroller}) => getMaxAssets(world, comptroller) - ), - new Fetcher<{comptroller: Comptroller}, NumberV>(` - #### LiquidationIncentive - - * "Comptroller LiquidationIncentive" - Returns the Comptrollers's liquidation incentive - * E.g. "Comptroller LiquidationIncentive" - `, - "LiquidationIncentive", - [new Arg("comptroller", getComptroller, {implicit: true})], - (world, {comptroller}) => getLiquidationIncentive(world, comptroller) - ), - new Fetcher<{comptroller: Comptroller}, AddressV>(` - #### Implementation - - * "Comptroller Implementation" - Returns the Comptrollers's implementation - * E.g. "Comptroller Implementation" - `, - "Implementation", - [new Arg("comptroller", getComptroller, {implicit: true})], - (world, {comptroller}) => getImplementation(world, comptroller) - ), - new Fetcher<{comptroller: Comptroller}, NumberV>(` - #### BlockNumber - - * "Comptroller BlockNumber" - Returns the Comptrollers's mocked block number (for scenario runner) - * E.g. "Comptroller BlockNumber" - `, - "BlockNumber", - [new Arg("comptroller", getComptroller, {implicit: true})], - (world, {comptroller}) => getBlockNumber(world, comptroller) - ), - new Fetcher<{comptroller: Comptroller, cToken: CToken}, NumberV>(` - #### CollateralFactor - - * "Comptroller CollateralFactor " - Returns the collateralFactor associated with a given asset - * E.g. "Comptroller CollateralFactor cZRX" - `, - "CollateralFactor", - [ - new Arg("comptroller", getComptroller, {implicit: true}), - new Arg("cToken", getCTokenV) - ], - (world, {comptroller, cToken}) => getCollateralFactor(world, comptroller, cToken) - ), - new Fetcher<{comptroller: Comptroller, account: AddressV}, NumberV>(` - #### MembershipLength - - * "Comptroller MembershipLength " - Returns a given user's length of membership - * E.g. "Comptroller MembershipLength Geoff" - `, - "MembershipLength", - [ - new Arg("comptroller", getComptroller, {implicit: true}), - new Arg("account", getAddressV) - ], - (world, {comptroller, account}) => membershipLength(world, comptroller, account.val) - ), - new Fetcher<{comptroller: Comptroller, account: AddressV, cToken: CToken}, BoolV>(` - #### CheckMembership - - * "Comptroller CheckMembership " - Returns one if user is in asset, zero otherwise. - * E.g. "Comptroller CheckMembership Geoff cZRX" - `, - "CheckMembership", - [ - new Arg("comptroller", getComptroller, {implicit: true}), - new Arg("account", getAddressV), - new Arg("cToken", getCTokenV) - ], - (world, {comptroller, account, cToken}) => checkMembership(world, comptroller, account.val, cToken) - ), - new Fetcher<{comptroller: Comptroller, account: AddressV}, ListV>(` - #### AssetsIn - - * "Comptroller AssetsIn " - Returns the assets a user is in - * E.g. "Comptroller AssetsIn Geoff" - `, - "AssetsIn", - [ - new Arg("comptroller", getComptroller, {implicit: true}), - new Arg("account", getAddressV) - ], - (world, {comptroller, account}) => getAssetsIn(world, comptroller, account.val) - ), - new Fetcher<{comptroller: Comptroller, cToken: CToken}, BoolV>(` - #### CheckListed - - * "Comptroller CheckListed " - Returns true if market is listed, false otherwise. - * E.g. "Comptroller CheckListed cZRX" - `, - "CheckListed", - [ - new Arg("comptroller", getComptroller, {implicit: true}), - new Arg("cToken", getCTokenV) - ], - (world, {comptroller, cToken}) => checkListed(world, comptroller, cToken) - ), - new Fetcher<{comptroller: Comptroller, cToken: CToken}, BoolV>(` - #### CheckIsComped - - * "Comptroller CheckIsComped " - Returns true if market is listed, false otherwise. - * E.g. "Comptroller CheckIsComped cZRX" - `, - "CheckIsComped", - [ - new Arg("comptroller", getComptroller, {implicit: true}), - new Arg("cToken", getCTokenV) - ], - (world, {comptroller, cToken}) => checkIsComped(world, comptroller, cToken) - ), - new Fetcher<{comptroller: Comptroller}, AddressV>(` - #### PauseGuardian - - * "PauseGuardian" - Returns the Comptrollers's PauseGuardian - * E.g. "Comptroller PauseGuardian" - `, - "PauseGuardian", - [ - new Arg("comptroller", getComptroller, {implicit: true}) - ], - async (world, {comptroller}) => new AddressV(await comptroller.methods.pauseGuardian().call()) - ), - - new Fetcher<{comptroller: Comptroller}, BoolV>(` - #### _MintGuardianPaused - - * "_MintGuardianPaused" - Returns the Comptrollers's original global Mint paused status - * E.g. "Comptroller _MintGuardianPaused" - `, - "_MintGuardianPaused", - [new Arg("comptroller", getComptroller, {implicit: true})], - async (world, {comptroller}) => new BoolV(await comptroller.methods._mintGuardianPaused().call()) - ), - new Fetcher<{comptroller: Comptroller}, BoolV>(` - #### _BorrowGuardianPaused - - * "_BorrowGuardianPaused" - Returns the Comptrollers's original global Borrow paused status - * E.g. "Comptroller _BorrowGuardianPaused" - `, - "_BorrowGuardianPaused", - [new Arg("comptroller", getComptroller, {implicit: true})], - async (world, {comptroller}) => new BoolV(await comptroller.methods._borrowGuardianPaused().call()) - ), - - new Fetcher<{comptroller: Comptroller}, BoolV>(` - #### TransferGuardianPaused - - * "TransferGuardianPaused" - Returns the Comptrollers's Transfer paused status - * E.g. "Comptroller TransferGuardianPaused" - `, - "TransferGuardianPaused", - [new Arg("comptroller", getComptroller, {implicit: true})], - async (world, {comptroller}) => new BoolV(await comptroller.methods.transferGuardianPaused().call()) - ), - new Fetcher<{comptroller: Comptroller}, BoolV>(` - #### SeizeGuardianPaused - - * "SeizeGuardianPaused" - Returns the Comptrollers's Seize paused status - * E.g. "Comptroller SeizeGuardianPaused" - `, - "SeizeGuardianPaused", - [new Arg("comptroller", getComptroller, {implicit: true})], - async (world, {comptroller}) => new BoolV(await comptroller.methods.seizeGuardianPaused().call()) - ), - - new Fetcher<{comptroller: Comptroller, cToken: CToken}, BoolV>(` - #### MintGuardianMarketPaused - - * "MintGuardianMarketPaused" - Returns the Comptrollers's Mint paused status in market - * E.g. "Comptroller MintGuardianMarketPaused cREP" - `, - "MintGuardianMarketPaused", - [ - new Arg("comptroller", getComptroller, {implicit: true}), - new Arg("cToken", getCTokenV) - ], - async (world, {comptroller, cToken}) => new BoolV(await comptroller.methods.mintGuardianPaused(cToken._address).call()) - ), - new Fetcher<{comptroller: Comptroller, cToken: CToken}, BoolV>(` - #### BorrowGuardianMarketPaused - - * "BorrowGuardianMarketPaused" - Returns the Comptrollers's Borrow paused status in market - * E.g. "Comptroller BorrowGuardianMarketPaused cREP" - `, - "BorrowGuardianMarketPaused", - [ - new Arg("comptroller", getComptroller, {implicit: true}), - new Arg("cToken", getCTokenV) - ], - async (world, {comptroller, cToken}) => new BoolV(await comptroller.methods.borrowGuardianPaused(cToken._address).call()) - ), - - new Fetcher<{comptroller: Comptroller}, ListV>(` - #### GetCompMarkets - - * "GetCompMarkets" - Returns an array of the currently enabled Comp markets. To use the auto-gen array getter compMarkets(uint), use CompMarkets - * E.g. "Comptroller GetCompMarkets" - `, - "GetCompMarkets", - [new Arg("comptroller", getComptroller, {implicit: true})], - async(world, {comptroller}) => await getCompMarkets(world, comptroller) - ), - - new Fetcher<{comptroller: Comptroller}, NumberV>(` - #### CompRate - - * "CompRate" - Returns the current comp rate. - * E.g. "Comptroller CompRate" - `, - "CompRate", - [new Arg("comptroller", getComptroller, {implicit: true})], - async(world, {comptroller}) => new NumberV(await comptroller.methods.compRate().call()) - ), - - new Fetcher<{comptroller: Comptroller, signature: StringV, callArgs: StringV[]}, NumberV>(` - #### CallNum - - * "CallNum signature: ...callArgs" - Simple direct call method - * E.g. "Comptroller CallNum \"compSpeeds(address)\" (Address Coburn)" - `, - "CallNum", - [ - new Arg("comptroller", getComptroller, {implicit: true}), - new Arg("signature", getStringV), - new Arg("callArgs", getCoreValue, {variadic: true, mapped: true}) - ], - async (world, {comptroller, signature, callArgs}) => { - const fnData = encodeABI(world, signature.val, callArgs.map(a => a.val)); - const res = await world.web3.eth.call({ - to: comptroller._address, - data: fnData - }) - const resNum : any = world.web3.eth.abi.decodeParameter('uint256',res); - return new NumberV(resNum); - } - ), - new Fetcher<{comptroller: Comptroller, CToken: CToken, key: StringV}, NumberV>(` - #### CompSupplyState(address) - - * "Comptroller CompBorrowState cZRX "index" - `, - "CompSupplyState", - [ - new Arg("comptroller", getComptroller, {implicit: true}), - new Arg("CToken", getCTokenV), - new Arg("key", getStringV), - ], - async (world, {comptroller, CToken, key}) => { - const result = await comptroller.methods.compSupplyState(CToken._address).call(); - return new NumberV(result[key.val]); - } - ), - new Fetcher<{comptroller: Comptroller, CToken: CToken, key: StringV}, NumberV>(` - #### CompBorrowState(address) - - * "Comptroller CompBorrowState cZRX "index" - `, - "CompBorrowState", - [ - new Arg("comptroller", getComptroller, {implicit: true}), - new Arg("CToken", getCTokenV), - new Arg("key", getStringV), - ], - async (world, {comptroller, CToken, key}) => { - const result = await comptroller.methods.compBorrowState(CToken._address).call(); - return new NumberV(result[key.val]); - } - ), - new Fetcher<{comptroller: Comptroller, account: AddressV, key: StringV}, NumberV>(` - #### CompAccrued(address) - - * "Comptroller CompAccrued Coburn - `, - "CompAccrued", - [ - new Arg("comptroller", getComptroller, {implicit: true}), - new Arg("account", getAddressV), - ], - async (world, {comptroller,account}) => { - const result = await comptroller.methods.compAccrued(account.val).call(); - return new NumberV(result); - } - ), - new Fetcher<{comptroller: Comptroller, account: AddressV, key: StringV}, NumberV>(` - #### CompReceivable(address) - - * "Comptroller CompReceivable Coburn - `, - "CompReceivable", - [ - new Arg("comptroller", getComptroller, {implicit: true}), - new Arg("account", getAddressV), - ], - async (world, {comptroller,account}) => { - const result = await comptroller.methods.compReceivable(account.val).call(); - return new NumberV(result); - } - ), - new Fetcher<{comptroller: Comptroller, CToken: CToken, account: AddressV}, NumberV>(` - #### compSupplierIndex - - * "Comptroller CompSupplierIndex cZRX Coburn - `, - "CompSupplierIndex", - [ - new Arg("comptroller", getComptroller, {implicit: true}), - new Arg("CToken", getCTokenV), - new Arg("account", getAddressV), - ], - async (world, {comptroller, CToken, account}) => { - return new NumberV(await comptroller.methods.compSupplierIndex(CToken._address, account.val).call()); - } - ), - new Fetcher<{comptroller: Comptroller, CToken: CToken, account: AddressV}, NumberV>(` - #### CompBorrowerIndex - - * "Comptroller CompBorrowerIndex cZRX Coburn - `, - "CompBorrowerIndex", - [ - new Arg("comptroller", getComptroller, {implicit: true}), - new Arg("CToken", getCTokenV), - new Arg("account", getAddressV), - ], - async (world, {comptroller, CToken, account}) => { - return new NumberV(await comptroller.methods.compBorrowerIndex(CToken._address, account.val).call()); - } - ), - new Fetcher<{comptroller: Comptroller, CToken: CToken}, NumberV>(` - #### CompSpeed - - * "Comptroller CompSpeed cZRX - `, - "CompSpeed", - [ - new Arg("comptroller", getComptroller, {implicit: true}), - new Arg("CToken", getCTokenV), - ], - async (world, {comptroller, CToken}) => { - return new NumberV(await comptroller.methods.compSpeeds(CToken._address).call()); - } - ), - new Fetcher<{comptroller: Comptroller, CToken: CToken}, NumberV>(` - #### CompSupplySpeed - - * "Comptroller CompSupplySpeed cZRX - `, - "CompSupplySpeed", - [ - new Arg("comptroller", getComptroller, {implicit: true}), - new Arg("CToken", getCTokenV), - ], - async (world, {comptroller, CToken}) => { - return new NumberV(await comptroller.methods.compSupplySpeeds(CToken._address).call()); - } - ), - new Fetcher<{comptroller: Comptroller, CToken: CToken}, NumberV>(` - #### CompBorrowSpeed - - * "Comptroller CompBorrowSpeed cZRX - `, - "CompBorrowSpeed", - [ - new Arg("comptroller", getComptroller, {implicit: true}), - new Arg("CToken", getCTokenV), - ], - async (world, {comptroller, CToken}) => { - return new NumberV(await comptroller.methods.compBorrowSpeeds(CToken._address).call()); - } - ), - new Fetcher<{comptroller: Comptroller}, AddressV>(` - #### BorrowCapGuardian - - * "BorrowCapGuardian" - Returns the Comptrollers's BorrowCapGuardian - * E.g. "Comptroller BorrowCapGuardian" - `, - "BorrowCapGuardian", - [ - new Arg("comptroller", getComptroller, {implicit: true}) - ], - async (world, {comptroller}) => new AddressV(await comptroller.methods.borrowCapGuardian().call()) - ), - new Fetcher<{comptroller: Comptroller, CToken: CToken}, NumberV>(` - #### BorrowCaps - - * "Comptroller BorrowCaps cZRX - `, - "BorrowCaps", - [ - new Arg("comptroller", getComptroller, {implicit: true}), - new Arg("CToken", getCTokenV), - ], - async (world, {comptroller, CToken}) => { - return new NumberV(await comptroller.methods.borrowCaps(CToken._address).call()); - } - ), - new Fetcher<{comptroller: Comptroller, CToken: CToken}, NumberV>(` - #### IsDeprecated - - * "Comptroller IsDeprecated cZRX - `, - "IsDeprecated", - [ - new Arg("comptroller", getComptroller, {implicit: true}), - new Arg("CToken", getCTokenV), - ], - async (world, {comptroller, CToken}) => { - return new NumberV(await comptroller.methods.isDeprecated(CToken._address).call()); - } - ), - new Fetcher<{ comptroller: Comptroller, cToken: CToken }, NumberV>(` - #### SupplyCaps - * "Comptroller SupplyCaps vZRX - `, - "SupplyCaps", - [ - new Arg("comptroller", getComptroller, { implicit: true }), - new Arg("VToken", getCTokenV), - ], - async (world, { comptroller, cToken }) => { - return new NumberV(await comptroller.methods.supplyCaps(cToken._address).call()); - } - ) - ]; -} - -export async function getComptrollerValue(world: World, event: Event): Promise { - return await getFetcherValue("Comptroller", comptrollerFetchers(), world, event); -} diff --git a/scenario/src/Value/Erc20Value.ts b/scenario/src/Value/Erc20Value.ts deleted file mode 100644 index 8f31716b0..000000000 --- a/scenario/src/Value/Erc20Value.ts +++ /dev/null @@ -1,160 +0,0 @@ -import {Event} from '../Event'; -import {World} from '../World'; -import {Erc20} from '../Contract/Erc20'; -import {getErc20Address, getWorldContractByAddress} from '../ContractLookup'; -import { - getAddressV, - getCoreValue, - mapValue, -} from '../CoreValue'; -import {Arg, Fetcher, getFetcherValue} from '../Command'; -import { - AddressV, - NumberV, - Value, - StringV -} from '../Value'; - -export async function getErc20Name(world: World, erc20: Erc20): Promise { - return new StringV(await erc20.methods.name().call()); -} - -export async function getErc20Symbol(world: World, erc20: Erc20): Promise { - return new StringV(await erc20.methods.symbol().call()); -} - -export async function getErc20Decimals(world: World, erc20: Erc20): Promise { - return new NumberV(await erc20.methods.decimals().call()); -} - -async function getTotalSupply(world: World, erc20: Erc20): Promise { - return new NumberV(await erc20.methods.totalSupply().call()); -} - -async function getTokenBalance(world: World, erc20: Erc20, address: string): Promise { - return new NumberV(await erc20.methods.balanceOf(address).call()); -} - -async function getAllowance(world: World, erc20: Erc20, owner: string, spender: string): Promise { - return new NumberV(await erc20.methods.allowance(owner, spender).call()); -} - -export async function getErc20V(world: World, event: Event): Promise { - const address = await mapValue( - world, - event, - (str) => new AddressV(getErc20Address(world, str)), - getCoreValue, - AddressV - ); - - return getWorldContractByAddress(world, address.val); -} - -export function erc20Fetchers() { - return [ - new Fetcher<{erc20: Erc20}, AddressV>(` - #### Address - - * "Erc20 Address" - Returns address of ERC-20 contract - * E.g. "Erc20 ZRX Address" - Returns ZRX's address - `, - "Address", - [ - new Arg("erc20", getErc20V) - ], - async (world, {erc20}) => new AddressV(erc20._address), - {namePos: 1} - ), - new Fetcher<{erc20: Erc20}, StringV>(` - #### Name - - * "Erc20 Name" - Returns name of ERC-20 contract - * E.g. "Erc20 ZRX Name" - Returns ZRX's name - `, - "Name", - [ - new Arg("erc20", getErc20V) - ], - (world, {erc20}) => getErc20Name(world, erc20), - {namePos: 1} - ), - new Fetcher<{erc20: Erc20}, StringV>(` - #### Symbol - - * "Erc20 Symbol" - Returns symbol of ERC-20 contract - * E.g. "Erc20 ZRX Symbol" - Returns ZRX's symbol - `, - "Symbol", - [ - new Arg("erc20", getErc20V) - ], - (world, {erc20}) => getErc20Symbol(world, erc20), - {namePos: 1} - ), - new Fetcher<{erc20: Erc20}, NumberV>(` - #### Decimals - - * "Erc20 Decimals" - Returns number of decimals in ERC-20 contract - * E.g. "Erc20 ZRX Decimals" - Returns ZRX's decimals - `, - "Decimals", - [ - new Arg("erc20", getErc20V) - ], - (world, {erc20}) => getErc20Decimals(world, erc20), - {namePos: 1} - ), - new Fetcher<{erc20: Erc20}, NumberV>(` - #### TotalSupply - - * "Erc20 TotalSupply" - Returns the ERC-20 token's total supply - * E.g. "Erc20 ZRX TotalSupply" - * E.g. "Erc20 cZRX TotalSupply" - `, - "TotalSupply", - [ - new Arg("erc20", getErc20V) - ], - (world, {erc20}) => getTotalSupply(world, erc20), - {namePos: 1} - ), - new Fetcher<{erc20: Erc20, address: AddressV}, NumberV>(` - #### TokenBalance - - * "Erc20 TokenBalance
" - Returns the ERC-20 token balance of a given address - * E.g. "Erc20 ZRX TokenBalance Geoff" - Returns a user's ZRX balance - * E.g. "Erc20 cZRX TokenBalance Geoff" - Returns a user's cZRX balance - * E.g. "Erc20 ZRX TokenBalance cZRX" - Returns cZRX's ZRX balance - `, - "TokenBalance", - [ - new Arg("erc20", getErc20V), - new Arg("address", getAddressV) - ], - (world, {erc20, address}) => getTokenBalance(world, erc20, address.val), - {namePos: 1} - ), - new Fetcher<{erc20: Erc20, owner: AddressV, spender: AddressV}, NumberV>(` - #### Allowance - - * "Erc20 Allowance owner:
spender:
" - Returns the ERC-20 allowance from owner to spender - * E.g. "Erc20 ZRX Allowance Geoff Torrey" - Returns the ZRX allowance of Geoff to Torrey - * E.g. "Erc20 cZRX Allowance Geoff Coburn" - Returns the cZRX allowance of Geoff to Coburn - * E.g. "Erc20 ZRX Allowance Geoff cZRX" - Returns the ZRX allowance of Geoff to the cZRX cToken - `, - "Allowance", - [ - new Arg("erc20", getErc20V), - new Arg("owner", getAddressV), - new Arg("spender", getAddressV) - ], - (world, {erc20, owner, spender}) => getAllowance(world, erc20, owner.val, spender.val), - {namePos: 1} - ) - ]; -} - -export async function getErc20Value(world: World, event: Event): Promise { - return await getFetcherValue("Erc20", erc20Fetchers(), world, event); -} diff --git a/scenario/src/Value/InterestRateModelValue.ts b/scenario/src/Value/InterestRateModelValue.ts deleted file mode 100644 index e4361d27b..000000000 --- a/scenario/src/Value/InterestRateModelValue.ts +++ /dev/null @@ -1,60 +0,0 @@ -import {Event} from '../Event'; -import {World} from '../World'; -import {InterestRateModel} from '../Contract/InterestRateModel'; -import { - getAddressV, - getNumberV -} from '../CoreValue'; -import { - AddressV, - NumberV, - Value} from '../Value'; -import {Arg, Fetcher, getFetcherValue} from '../Command'; -import {getInterestRateModel} from '../ContractLookup'; - -export async function getInterestRateModelAddress(world: World, interestRateModel: InterestRateModel): Promise { - return new AddressV(interestRateModel._address); -} - -export async function getBorrowRate(world: World, interestRateModel: InterestRateModel, cash: NumberV, borrows: NumberV, reserves: NumberV): Promise { - return new NumberV(await interestRateModel.methods.getBorrowRate(cash.encode(), borrows.encode(), reserves.encode()).call(), 1.0e18 / 2102400); -} - -export function interestRateModelFetchers() { - return [ - new Fetcher<{interestRateModel: InterestRateModel}, AddressV>(` - #### Address - - * " Address" - Gets the address of the interest rate model - * E.g. "InterestRateModel MyInterestRateModel Address" - `, - "Address", - [ - new Arg("interestRateModel", getInterestRateModel) - ], - (world, {interestRateModel}) => getInterestRateModelAddress(world, interestRateModel), - {namePos: 1} - ), - - new Fetcher<{interestRateModel: InterestRateModel, cash: NumberV, borrows: NumberV, reserves: NumberV}, NumberV>(` - #### BorrowRate - - * " BorrowRate" - Gets the borrow rate of the interest rate model - * E.g. "InterestRateModel MyInterestRateModel BorrowRate 0 10 0" - `, - "BorrowRate", - [ - new Arg("interestRateModel", getInterestRateModel), - new Arg("cash", getNumberV), - new Arg("borrows", getNumberV), - new Arg("reserves", getNumberV) - ], - (world, {interestRateModel, cash, borrows, reserves}) => getBorrowRate(world, interestRateModel, cash, borrows, reserves), - {namePos: 1} - ) - ]; -} - -export async function getInterestRateModelValue(world: World, event: Event): Promise { - return await getFetcherValue("InterestRateModel", interestRateModelFetchers(), world, event); -} diff --git a/scenario/src/Value/MCDValue.ts b/scenario/src/Value/MCDValue.ts deleted file mode 100644 index e970226c6..000000000 --- a/scenario/src/Value/MCDValue.ts +++ /dev/null @@ -1,65 +0,0 @@ -import { Event } from '../Event'; -import { World } from '../World'; -import { getContract } from '../Contract'; -import { Pot } from '../Contract/Pot'; -import { Vat } from '../Contract/Vat'; -import { - getAddressV, - getCoreValue, - getStringV -} from '../CoreValue'; -import { Arg, Fetcher, getFetcherValue } from '../Command'; -import { - AddressV, - NumberV, - Value, - StringV -} from '../Value'; - -export function mcdFetchers() { - return [ - new Fetcher<{ potAddress: AddressV, method: StringV, args: StringV[] }, Value>(` - #### PotAt - - * "MCD PotAt " - * E.g. "MCD PotAt "0xPotAddress" "pie" (CToken cDai Address)" - `, - "PotAt", - [ - new Arg("potAddress", getAddressV), - new Arg("method", getStringV), - new Arg('args', getCoreValue, { variadic: true, mapped: true }) - ], - async (world, { potAddress, method, args }) => { - const PotContract = getContract('PotLike'); - const pot = await PotContract.at(world, potAddress.val); - const argStrings = args.map(arg => arg.val); - return new NumberV(await pot.methods[method.val](...argStrings).call()) - } - ), - - new Fetcher<{ vatAddress: AddressV, method: StringV, args: StringV[] }, Value>(` - #### VatAt - - * "MCD VatAt " - * E.g. "MCD VatAt "0xVatAddress" "dai" (CToken cDai Address)" - `, - "VatAt", - [ - new Arg("vatAddress", getAddressV), - new Arg("method", getStringV), - new Arg('args', getCoreValue, { variadic: true, mapped: true }) - ], - async (world, { vatAddress, method, args }) => { - const VatContract = getContract('VatLike'); - const vat = await VatContract.at(world, vatAddress.val); - const argStrings = args.map(arg => arg.val); - return new NumberV(await vat.methods[method.val](...argStrings).call()) - } - ) - ]; -} - -export async function getMCDValue(world: World, event: Event): Promise { - return await getFetcherValue("MCD", mcdFetchers(), world, event); -} diff --git a/scenario/src/Value/PriceOracleProxyValue.ts b/scenario/src/Value/PriceOracleProxyValue.ts deleted file mode 100644 index cb1143806..000000000 --- a/scenario/src/Value/PriceOracleProxyValue.ts +++ /dev/null @@ -1,67 +0,0 @@ -import {Event} from '../Event'; -import {World} from '../World'; -import {PriceOracleProxy} from '../Contract/PriceOracleProxy'; -import { - getAddressV -} from '../CoreValue'; -import { - AddressV, - NumberV, - Value} from '../Value'; -import {Arg, Fetcher, getFetcherValue} from '../Command'; -import {getPriceOracleProxy} from '../ContractLookup'; - -export async function getPriceOracleProxyAddress(world: World, priceOracleProxy: PriceOracleProxy): Promise { - return new AddressV(priceOracleProxy._address); -} - -export async function getV1PriceOracle(world: World, priceOracleProxy: PriceOracleProxy): Promise { - return new AddressV(await priceOracleProxy.methods.v1PriceOracle().call()); -} - -async function getPrice(world: World, priceOracleProxy: PriceOracleProxy, asset: string): Promise { - return new NumberV(await priceOracleProxy.methods.getUnderlyingPrice(asset).call()); -} - -export function priceOracleProxyFetchers() { - return [ - new Fetcher<{priceOracleProxy: PriceOracleProxy}, AddressV>(` - #### V1PriceOracle - - * "V1PriceOracle" - Gets the address of the v1 Price - `, - "V1PriceOracle", - [ - new Arg("priceOracleProxy", getPriceOracleProxy, {implicit: true}) - ], - (world, {priceOracleProxy}) => getV1PriceOracle(world, priceOracleProxy) - ), - new Fetcher<{priceOracleProxy: PriceOracleProxy}, AddressV>(` - #### Address - - * "Address" - Gets the address of the global price oracle - `, - "Address", - [ - new Arg("priceOracleProxy", getPriceOracleProxy, {implicit: true}) - ], - (world, {priceOracleProxy}) => getPriceOracleProxyAddress(world, priceOracleProxy) - ), - new Fetcher<{priceOracle: PriceOracleProxy, asset: AddressV}, NumberV>(` - #### Price - - * "Price asset:
" - Gets the price of the given asset - `, - "Price", - [ - new Arg("priceOracle", getPriceOracleProxy, {implicit: true}), - new Arg("asset", getAddressV) - ], - (world, {priceOracle, asset}) => getPrice(world, priceOracle, asset.val) - ) - ]; -} - -export async function getPriceOracleProxyValue(world: World, event: Event): Promise { - return await getFetcherValue("PriceOracle", priceOracleProxyFetchers(), world, event); -} diff --git a/scenario/src/Value/PriceOracleValue.ts b/scenario/src/Value/PriceOracleValue.ts deleted file mode 100644 index f954bec9d..000000000 --- a/scenario/src/Value/PriceOracleValue.ts +++ /dev/null @@ -1,52 +0,0 @@ -import {Event} from '../Event'; -import {World} from '../World'; -import {PriceOracle} from '../Contract/PriceOracle'; -import { - getAddressV -} from '../CoreValue'; -import { - AddressV, - NumberV, - Value} from '../Value'; -import {Arg, Fetcher, getFetcherValue} from '../Command'; -import {getPriceOracle} from '../ContractLookup'; - -async function getPrice(world: World, priceOracle: PriceOracle, asset: string): Promise { - return new NumberV(await priceOracle.methods.assetPrices(asset).call()); -} - -export async function getPriceOracleAddress(world: World, priceOracle: PriceOracle): Promise { - return new AddressV(priceOracle._address); -} - -export function priceOracleFetchers() { - return [ - new Fetcher<{priceOracle: PriceOracle}, AddressV>(` - #### Address - - * "Address" - Gets the address of the global price oracle - `, - "Address", - [ - new Arg("priceOracle", getPriceOracle, {implicit: true}) - ], - (world, {priceOracle}) => getPriceOracleAddress(world, priceOracle) - ), - new Fetcher<{priceOracle: PriceOracle, asset: AddressV}, NumberV>(` - #### Price - - * "Price asset:
" - Gets the price of the given asset - `, - "Price", - [ - new Arg("priceOracle", getPriceOracle, {implicit: true}), - new Arg("asset", getAddressV,) - ], - (world, {priceOracle, asset}) => getPrice(world, priceOracle, asset.val) - ) - ]; -} - -export async function getPriceOracleValue(world: World, event: Event): Promise { - return await getFetcherValue("PriceOracle", priceOracleFetchers(), world, event); -} diff --git a/scenario/src/Value/UnitrollerValue.ts b/scenario/src/Value/UnitrollerValue.ts deleted file mode 100644 index e57c3887e..000000000 --- a/scenario/src/Value/UnitrollerValue.ts +++ /dev/null @@ -1,89 +0,0 @@ -import { Event } from '../Event'; -import { World } from '../World'; -import { Unitroller } from '../Contract/Unitroller'; -import { AddressV, Value } from '../Value'; -import { Arg, Fetcher, getFetcherValue } from '../Command'; -import { getUnitroller } from '../ContractLookup'; - -export async function getUnitrollerAddress(world: World, unitroller: Unitroller): Promise { - return new AddressV(unitroller._address); -} - -async function getUnitrollerAdmin(world: World, unitroller: Unitroller): Promise { - return new AddressV(await unitroller.methods.admin().call()); -} - -async function getUnitrollerPendingAdmin(world: World, unitroller: Unitroller): Promise { - return new AddressV(await unitroller.methods.pendingAdmin().call()); -} - -async function getComptrollerImplementation(world: World, unitroller: Unitroller): Promise { - return new AddressV(await unitroller.methods.comptrollerImplementation().call()); -} - -async function getPendingComptrollerImplementation(world: World, unitroller: Unitroller): Promise { - return new AddressV(await unitroller.methods.pendingComptrollerImplementation().call()); -} - -export function unitrollerFetchers() { - return [ - new Fetcher<{ unitroller: Unitroller }, AddressV>( - ` - #### Address - - * "Unitroller Address" - Returns address of unitroller - `, - 'Address', - [new Arg('unitroller', getUnitroller, { implicit: true })], - (world, { unitroller }) => getUnitrollerAddress(world, unitroller) - ), - new Fetcher<{ unitroller: Unitroller }, AddressV>( - ` - #### Admin - - * "Unitroller Admin" - Returns the admin of Unitroller contract - * E.g. "Unitroller Admin" - Returns address of admin - `, - 'Admin', - [new Arg('unitroller', getUnitroller, { implicit: true })], - (world, { unitroller }) => getUnitrollerAdmin(world, unitroller) - ), - new Fetcher<{ unitroller: Unitroller }, AddressV>( - ` - #### PendingAdmin - - * "Unitroller PendingAdmin" - Returns the pending admin of Unitroller contract - * E.g. "Unitroller PendingAdmin" - Returns address of pendingAdmin - `, - 'PendingAdmin', - [new Arg('unitroller', getUnitroller, { implicit: true })], - (world, { unitroller }) => getUnitrollerPendingAdmin(world, unitroller) - ), - new Fetcher<{ unitroller: Unitroller }, AddressV>( - ` - #### Implementation - - * "Unitroller Implementation" - Returns the Implementation of Unitroller contract - * E.g. "Unitroller Implementation" - Returns address of comptrollerImplentation - `, - 'Implementation', - [new Arg('unitroller', getUnitroller, { implicit: true })], - (world, { unitroller }) => getComptrollerImplementation(world, unitroller) - ), - new Fetcher<{ unitroller: Unitroller }, AddressV>( - ` - #### PendingImplementation - - * "Unitroller PendingImplementation" - Returns the pending implementation of Unitroller contract - * E.g. "Unitroller PendingImplementation" - Returns address of pendingComptrollerImplementation - `, - 'PendingImplementation', - [new Arg('unitroller', getUnitroller, { implicit: true })], - (world, { unitroller }) => getPendingComptrollerImplementation(world, unitroller) - ) - ]; -} - -export async function getUnitrollerValue(world: World, event: Event): Promise { - return await getFetcherValue('Unitroller', unitrollerFetchers(), world, event); -} diff --git a/scenario/src/Value/UserValue.ts b/scenario/src/Value/UserValue.ts deleted file mode 100644 index df183ccf1..000000000 --- a/scenario/src/Value/UserValue.ts +++ /dev/null @@ -1,36 +0,0 @@ -import {Event} from '../Event'; -import {World} from '../World'; -import { - getAddressV -} from '../CoreValue'; -import {Arg, Fetcher, getFetcherValue} from '../Command'; -import { - AddressV, - Value -} from '../Value'; - -async function getUserAddress(world: World, user: string): Promise { - return new AddressV(user); -} - -export function userFetchers() { - return [ - new Fetcher<{account: AddressV}, AddressV>(` - #### Address - - * "User Address" - Returns address of user - * E.g. "User Geoff Address" - Returns Geoff's address - `, - "Address", - [ - new Arg("account", getAddressV) - ], - async (world, {account}) => account, - {namePos: 1} - ) - ]; -} - -export async function getUserValue(world: World, event: Event): Promise { - return await getFetcherValue("User", userFetchers(), world, event); -} diff --git a/scenario/src/Verify.ts b/scenario/src/Verify.ts deleted file mode 100644 index 03b41c10e..000000000 --- a/scenario/src/Verify.ts +++ /dev/null @@ -1,157 +0,0 @@ -import {World} from './World'; -import {readFile} from './File'; -import request from 'request'; -import * as path from 'path'; -import truffleFlattener from 'truffle-flattener'; -import {getNetworkContracts} from './Contract'; - -interface DevDoc { - author: string - methods: object - title: string -} - -interface UserDoc { - methods: object - notice: string -} - -function getUrl(network: string): string { - let host = { - kovan: 'api-kovan.etherscan.io', - rinkeby: 'api-rinkeby.etherscan.io', - ropsten: 'api-ropsten.etherscan.io', - goerli: 'api-goerli.etherscan.io', - mainnet: 'api.etherscan.io' - }[network]; - - if (!host) { - throw new Error(`Unknown etherscan API host for network ${network}`); - } - - return `https://${host}/api`; -} - -function getConstructorABI(world: World, contractName: string): string { - let constructorAbi = world.getIn(['contractData', 'Constructors', contractName]); - - if (!constructorAbi) { - throw new Error(`Unknown Constructor ABI for ${contractName} on ${world.network}. Try deploying again?`); - } - - return constructorAbi; -} - -function post(url, data): Promise { - return new Promise((resolve, reject) => { - request.post(url, {form: data}, (err, httpResponse, body) => { - if (err) { - reject(err); - } else { - resolve(JSON.parse(body)); - } - }); - }); -} - -function get(url, data): Promise { - return new Promise((resolve, reject) => { - request.get(url, {form: data}, (err, httpResponse, body) => { - if (err) { - reject(err); - } else { - resolve(JSON.parse(body)); - } - }); - }); -} - -interface Result { - status: string - message: string - result: string -} - -async function sleep(timeout): Promise { - return new Promise((resolve, _reject) => { - setTimeout(() => resolve(), timeout); - }) -} - -async function checkStatus(world: World, url: string, token: string): Promise { - world.printer.printLine(`Checking status of ${token}...`); - - // Potential results: - // { status: '0', message: 'NOTOK', result: 'Fail - Unable to verify' } - // { status: '0', message: 'NOTOK', result: 'Pending in queue' } - // { status: '1', message: 'OK', result: 'Pass - Verified' } - - let result: Result = await get(url, { - guid: token, - module: "contract", - action: "checkverifystatus" - }); - - if (world.verbose) { - console.log(result); - } - - if (result.result === "Pending in queue") { - await sleep(5000); - return await checkStatus(world, url, token); - } - - if (result.result.startsWith('Fail')) { - throw new Error(`Etherscan failed to verify contract: ${result.message} "${result.result}"`) - } - - if (Number(result.status) !== 1) { - throw new Error(`Etherscan Error: ${result.message} "${result.result}"`) - } - - world.printer.printLine(`Verification result ${result.result}...`); -} - -export async function verify(world: World, apiKey: string, contractName: string, buildInfoName: string, address: string): Promise { - let contractAddress: string = address; - let {networkContracts, version} = await getNetworkContracts(world); - let networkContract = networkContracts[buildInfoName]; - if (!networkContract) { - throw new Error(`Cannot find contract ${buildInfoName}, found: ${Object.keys(networkContracts)}`) - } - let sourceCode: string = await truffleFlattener([networkContract.path]); - let compilerVersion: string = version.replace(/(\.Emscripten)|(\.clang)|(\.Darwin)|(\.appleclang)/gi, ''); - let constructorAbi = getConstructorABI(world, contractName); - let url = getUrl(world.network); - - const verifyData: object = { - apikey: apiKey, - module: 'contract', - action: 'verifysourcecode', - contractaddress: contractAddress, - sourceCode: sourceCode, - contractname: buildInfoName, - compilerversion: `v${compilerVersion}`, - optimizationUsed: '1', - runs: '200', - constructorArguements: constructorAbi.slice(2) - }; - - world.printer.printLine(`Verifying ${contractName} at ${address} with compiler version ${compilerVersion}...`); - - // Potential results - // {"status":"0","message":"NOTOK","result":"Invalid constructor arguments provided. Please verify that they are in ABI-encoded format"} - // {"status":"1","message":"OK","result":"usjpiyvmxtgwyee59wnycyiet7m3dba4ccdi6acdp8eddlzdde"} - - let result: Result = await post(url, verifyData); - - if (Number(result.status) === 0 || result.message !== "OK") { - if (result.result.includes('Contract source code already verified')) { - world.printer.printLine(`Contract already verified`); - } else { - throw new Error(`Etherscan Error: ${result.message}: ${result.result}`) - } - } else { - return await checkStatus(world, url, result.result); - } -} diff --git a/scenario/src/Web.ts b/scenario/src/Web.ts deleted file mode 100644 index 8d0b3bf23..000000000 --- a/scenario/src/Web.ts +++ /dev/null @@ -1,87 +0,0 @@ -import { parse } from './Parser'; -import { World, initWorld } from './World'; -import { throwExpect } from './Assert'; -import { CallbackPrinter } from './Printer'; -import { runCommand } from './Runner'; -import { loadContractData, parseNetworkFile } from './Networks'; -import Web3 from 'web3'; -import { Saddle } from 'eth-saddle'; - -function networkFromId(id: number) { - switch (id) { - case 0: - return 'olympic'; - - case 1: - return 'mainnet'; - - case 2: - return 'morden'; - - case 3: - return 'ropsten'; - - case 4: - return 'rinkeby'; - - case 5: - return 'goerli'; - - case 8: - return 'ubiq'; - - case 42: - return 'kovan'; - - case 77: - return 'sokol'; - - case 99: - return 'core'; - - case 999: - return 'development'; - - default: - return ''; - } -} - -export async function webWorld( - web3: Web3, - networksData: string, - networksABIData: string, - printerCallback: (message: any) => void -): Promise { - let printer = new CallbackPrinter(printerCallback); - let accounts; - if (web3.currentProvider && typeof(web3.currentProvider) !== 'string') { - // XXXS - accounts = [(web3.currentProvider).address]; - } - - const networkId = await (web3 as any).net.getId(); - const network: string = networkFromId(networkId); - - // XXXS - const saddle = { - web3: web3 - }; - - let world = await initWorld(throwExpect, printer, web3, saddle, network, accounts, null, null); - - let networks = parseNetworkFile(networksData); - let networksABI = parseNetworkFile(networksABIData); - - [world] = await loadContractData(world, networks, networksABI); - // world = loadInvokationOpts(world); - // world = loadVerbose(world); - // world = loadDryRun(world); - // world = await loadSettings(world); - - return world; -} - -export async function webParse(world: World, line: string): Promise { - return runCommand(world, line, {}); -} diff --git a/scenario/src/World.ts b/scenario/src/World.ts deleted file mode 100644 index 6a556e564..000000000 --- a/scenario/src/World.ts +++ /dev/null @@ -1,356 +0,0 @@ -import { Expect, throwExpect } from './Assert'; -import { Action } from './Action'; -import { Contract } from './Contract'; -import { Record } from 'immutable'; -import { Printer } from './Printer'; -import { Invariant } from './Invariant'; -import { SuccessInvariant } from './Invariant/SuccessInvariant'; -import { RemainsInvariant } from './Invariant/RemainsInvariant'; -import { StaticInvariant } from './Invariant/StaticInvariant'; -import { Expectation } from './Expectation'; -import { formatResult } from './ErrorReporter'; -import { Invokation, InvokationOpts } from './Invokation'; -import { Event } from './Event'; -import { formatEvent } from './Formatter'; -import { Map } from 'immutable'; -import { Settings } from './Settings'; -import { Accounts, loadAccounts } from './Accounts'; -import Web3 from 'web3'; -import { Saddle } from 'eth-saddle'; -import { Command, Fetcher } from './Command'; -import { Value} from './Value'; - -const startingBlockNumber = 1000; - -type ContractIndex = { [address: string]: Contract }; -type Counter = { value: number }; -type EventDecoder = { [eventSignature: string]: (log: any) => any }; - -export interface WorldProps { - actions: Action[]; - event: Event | null; - lastInvokation: Invokation | null; - newInvokation: boolean; - blockNumber: number; - gasCounter: Counter; - lastContract: Contract | null; - invariants: Invariant[]; - expectations: Expectation[]; - contractIndex: ContractIndex; - contractData: Map; - expect: Expect; - web3: Web3 | null; - saddle: Saddle | null; - printer: Printer | null; - network: string | null; - dryRun: boolean; - verbose: boolean; - settings: Settings; - accounts: Accounts | null; - invokationOpts: InvokationOpts; - trxInvokationOpts: Map; - basePath: string | null; - totalGas: number | null; - eventDecoder: EventDecoder; - fs: object | null; - commands: Command[] | undefined; - fetchers: Fetcher[] | undefined; -} - -const defaultWorldProps: WorldProps = { - actions: []>[], - event: null, - lastInvokation: null, - newInvokation: false, - blockNumber: 0, - gasCounter: {value: 0}, - lastContract: null, - invariants: [], - expectations: [], - contractIndex: {}, - contractData: Map({}), - expect: throwExpect, - web3: null, - saddle: null, - printer: null, - network: null, - dryRun: false, - verbose: false, - settings: Settings.default(null, null), - accounts: null, - invokationOpts: {}, - trxInvokationOpts: Map({}), - basePath: null, - totalGas: null, - eventDecoder: {}, - fs: null, - commands: undefined, - fetchers: undefined, -}; - -export class World extends Record(defaultWorldProps) { - public readonly actions!: Action[]; - public readonly event!: Event | null; - public readonly value!: number | null; - public readonly lastInvokation!: Invokation | null; - public readonly newInvokation!: boolean; - public readonly blockNumber!: number; - public readonly gasCounter!: Counter; - public readonly lastContract!: Contract | null; - public readonly invariants!: Invariant[]; - public readonly expectations!: Expectation[]; - public readonly contractIndex!: ContractIndex; - public readonly contractData!: Map; - public readonly expect!: Expect; - public readonly web3!: Web3; - public readonly saddle!: Saddle; - public readonly printer!: Printer; - public readonly network!: string; - public readonly dryRun!: boolean; - public readonly verbose!: boolean; - public readonly settings!: Settings; - public readonly accounts!: Accounts; - public readonly invokationOpts!: InvokationOpts; - public readonly trxInvokationOpts!: Map; - public readonly basePath!: string | null; - - public constructor(values?: Partial) { - values ? super(values) : super(); - } - - getInvokationOpts(baseOpts: InvokationOpts): InvokationOpts { - return { - ...baseOpts, - ...this.invokationOpts, - ...this.value ? {value: this.value.toString()} : {} - }; - } - - isLocalNetwork(): boolean { - return this.network === 'test' || this.network === 'development' || this.network === 'coverage'; - } - - async updateSettings(fn: (settings: Settings) => Promise): Promise { - // TODO: Should we do an immutable update? - const newSettings = await fn(this.settings); - - // TODO: Should we await or just let it clobber? - await newSettings.save(); - - return this.set('settings', newSettings); - } - - defaultFrom(): string | null { - let settingsFrom = this.settings.findAlias('Me'); - if (settingsFrom) { - return settingsFrom; - } - - let accountsDefault = this.accounts.get('default'); - if (accountsDefault) { - return accountsDefault.address; - } - - return null; - } -} - -export function loadInvokationOpts(world: World): World { - let networkOpts = {}; - const networkOptsStr = process.env[`${world.network}_opts`]; - if (networkOptsStr) { - networkOpts = JSON.parse(networkOptsStr); - } - - return world.set('invokationOpts', networkOpts); -} - -export function loadVerbose(world: World): World { - return world.set('verbose', !!process.env['verbose']); -} - -export function loadDryRun(world: World): World { - return world.set('dryRun', !!process.env['dry_run']); -} - -export async function loadSettings(world: World): Promise { - if (world.basePath) { - return world.set('settings', await Settings.load(world.basePath, world.network)); - } else { - return world; - } -} - -export async function initWorld( - expect: Expect, - printer: Printer, - iweb3: Web3, - saddle: Saddle, - network: string, - accounts: string[], - basePath: string | null, - totalGas: number | null -): Promise { - return new World({ - actions: [], - event: null, - lastInvokation: null, - newInvokation: true, - blockNumber: startingBlockNumber, - gasCounter: {value: 0}, - lastContract: null, - invariants: [new SuccessInvariant()], // Start with invariant success, - expectations: [], - contractIndex: {}, - contractData: Map({}), - expect: expect, - web3: iweb3, - saddle: saddle, - printer: printer, - network: network, - settings: Settings.default(basePath, null), - accounts: loadAccounts(accounts), - trxInvokationOpts: Map({}), - basePath: basePath, - totalGas: totalGas ? totalGas : null, - eventDecoder: {}, - fs: network === 'test' ? {} : null - }); -} - -export function setEvent(world: World, event: Event): World { - return world.set('event', event); -} - -export function addAction(world: World, log: string, invokation: Invokation): World { - const action = new Action(log, invokation); - - world = world.update('actions', actions => actions.concat([action])); - - // Print the action via the printer - world.printer.printAction(action); - - return world.merge(world, { - lastInvokation: invokation, - newInvokation: true - }); -} - -export function addInvariant(world: World, invariant: Invariant): World { - return world.update('invariants', invariants => invariants.concat([invariant])); -} - -export function addExpectation(world: World, expectation: Expectation): World { - return world.update('expectations', expectations => expectations.concat([expectation])); -} - -function getInvariantFilter(type: string) { - let filters: { [filter: string]: (invariant: Invariant) => boolean } = { - all: _invariant => true, - success: invariant => !(invariant instanceof SuccessInvariant), - remains: invariant => !(invariant instanceof RemainsInvariant), - static: invariant => !(invariant instanceof StaticInvariant) - }; - - let filter = filters[type.toLowerCase()]; - - if (!filter) { - throw new Error(`Unknown invariant type \`${type}\` when wiping invariants.`); - } - - return filter; -} - -export function clearInvariants(world: World, type: string): World { - let filter = getInvariantFilter(type); - - return world.update('invariants', invariants => world.invariants.filter(filter)); -} - -export function holdInvariants(world: World, type: string): World { - let filter = getInvariantFilter(type); - - return world.update('invariants', invariants => { - return world.invariants.map(invariant => { - if (filter(invariant)) { - invariant.held = true; - } - - return invariant; - }); - }); -} - -export async function checkExpectations(world: World): Promise { - if (!world.get('newInvokation')) { - return world; - } else { - // Lastly, check invariants each hold - await Promise.all( - world.get('expectations').map(expectation => { - // Check the expectation holds - return expectation.checker(world); - }) - ); - - return world.set('expectations', []); - } -} - -export async function checkInvariants(world: World): Promise { - if (!world.get('newInvokation')) { - return world; - } else { - // Lastly, check invariants each hold - await Promise.all( - world.get('invariants').map(invariant => { - // Check the invariant still holds - if (!invariant.held) { - return invariant.checker(world); - } - }) - ); - - // Remove holds - return world.update('invariants', invariants => { - return invariants.map(invariant => { - invariant.held = false; - - return invariant; - }); - }); - } -} - -export function describeUser(world: World, address: string): string { - // Look up by alias - let alias = Object.entries(world.settings.aliases).find(([name, aliasAddr]) => aliasAddr === address); - if (alias) { - return `${alias[0]} (${address.slice(0,6)}...)`; - } - - // Look up by `from` - if (world.settings.from === address) { - return `root (${address.slice(0,6)}...)`; - } - - // Look up by unlocked accounts - let account = world.accounts.find(account => account.address === address); - if (account) { - return `${account.name} (${address.slice(0,6)}...)`; - } - - // Otherwise, just return the address itself - return address; -} - -// Fails an assertion with reason -export function fail(world: World, reason: string): World { - if (world.event) { - world.expect(undefined).fail(`${reason} processing ${formatEvent(world.event)}`); - } else { - world.expect(undefined).fail(reason); - } - - return world; -} diff --git a/scenario/tsconfig.json b/scenario/tsconfig.json deleted file mode 100644 index 164399432..000000000 --- a/scenario/tsconfig.json +++ /dev/null @@ -1,63 +0,0 @@ -{ - "compilerOptions": { - /* Basic Options */ - "target": "es2018", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */ - "module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */ - "lib": ["esnext"], /* Specify library files to be included in the compilation. */ - // "allowJs": true, /* Allow javascript files to be compiled. */ - // "checkJs": true, /* Report errors in .js files. */ - // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ - // "declaration": true, /* Generates corresponding '.d.ts' file. */ - // "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */ - // "sourceMap": true, /* Generates corresponding '.map' file. */ - // "outFile": "./", /* Concatenate and emit output to single file. */ - "outDir": "./.tsbuilt", /* Redirect output structure to the directory. */ - // "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ - // "composite": true, /* Enable project compilation */ - // "removeComments": true, /* Do not emit comments to output. */ - // "noEmit": true, /* Do not emit outputs. */ - // "importHelpers": true, /* Import emit helpers from 'tslib'. */ - // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ - // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ - - /* Strict Type-Checking Options */ - "strict": false, /* Enable all strict type-checking options. */ - "noImplicitAny": false, /* Raise error on expressions and declarations with an implied 'any' type. */ - // "strictNullChecks": true, /* Enable strict null checks. */ - // "strictFunctionTypes": true, /* Enable strict checking of function types. */ - // "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */ - // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ - // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ - // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ - - /* Additional Checks */ - // "noUnusedLocals": true, /* Report errors on unused locals. */ - // "noUnusedParameters": true, /* Report errors on unused parameters. */ - // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ - // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ - - /* Module Resolution Options */ - // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ - // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ - // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ - // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ - // "typeRoots": [], /* List of folders to include type definitions from. */ - // "types": [], /* Type declaration files to be included in compilation. */ - // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ - "esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ - // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ - - /* Source Map Options */ - // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ - // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ - "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ - "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ - - /* Experimental Options */ - // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ - // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ - }, - "include": [ - "./src/**/*" - ] -} diff --git a/scenario/webpack.config.js b/scenario/webpack.config.js deleted file mode 100644 index e25a1fbae..000000000 --- a/scenario/webpack.config.js +++ /dev/null @@ -1,28 +0,0 @@ -'use strict' -const webpack = require('webpack'); - -module.exports = { - stats: 'verbose', - devtool: 'source-map', - externals: { - file: '{}', - fs: '{}', - tls: '{}', - net: '{}', - xmlhttprequest: '{}', - 'truffle-flattener': '{}', - 'request': '{}' - }, - optimization: { - minimize: true - }, - plugins: [ - new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/), - new webpack.DefinePlugin({ - 'process.env': { - // This has effect on the react lib size - 'NODE_ENV': JSON.stringify('production'), - } - }) - ] -} diff --git a/scenario/yarn.lock b/scenario/yarn.lock deleted file mode 100644 index 405b4491a..000000000 --- a/scenario/yarn.lock +++ /dev/null @@ -1,12154 +0,0 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. -# yarn lockfile v1 - - -"@0x/assert@^3.0.0": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@0x/assert/-/assert-3.0.0.tgz#a5fa5defd6638431c76309968fed175ddab5956a" - integrity sha512-SiU9pWEtHzDsmFx80/uBGZScpVwN4EhMlqcqt3fGa3u4e3iK6rtqLCD9qvlN9OgEljbvyuq6pzI8bGr27xspkw== - dependencies: - "@0x/json-schemas" "^5.0.0" - "@0x/typescript-typings" "^5.0.0" - "@0x/utils" "^5.0.0" - lodash "^4.17.11" - valid-url "^1.0.9" - -"@0x/assert@^3.0.9": - version "3.0.9" - resolved "https://registry.yarnpkg.com/@0x/assert/-/assert-3.0.9.tgz#4bc750b786c1f02ea0b7ceb701ebe2e46d30c113" - integrity sha512-ywQuG8feXtIpRn/3tekPZeXLjKfDJPooA5QJEDxHDv1E5ZjSrKSK6B3wdkVW6NJvNPECw0eKjM50uF2784tbfA== - dependencies: - "@0x/json-schemas" "^5.1.0" - "@0x/typescript-typings" "^5.1.1" - "@0x/utils" "^5.5.1" - lodash "^4.17.11" - valid-url "^1.0.9" - -"@0x/dev-utils@^3.3.0": - version "3.3.0" - resolved "https://registry.yarnpkg.com/@0x/dev-utils/-/dev-utils-3.3.0.tgz#ff56021d13b9630bb7f42d102e30a18f2b9aa7ff" - integrity sha512-/SPF/dVrGeYgZMo4vhHjG/YPxEsbnSi3sKA3+R6hySF7AKOH0u+78cUZ1NwrVOhGHToNWmehhci1Ic2BOXxQ9g== - dependencies: - "@0x/subproviders" "^6.1.1" - "@0x/types" "^3.2.0" - "@0x/typescript-typings" "^5.1.1" - "@0x/utils" "^5.5.1" - "@0x/web3-wrapper" "^7.2.0" - "@types/web3-provider-engine" "^14.0.0" - chai "^4.0.1" - chai-as-promised "^7.1.0" - chai-bignumber "^3.0.0" - dirty-chai "^2.0.1" - ethereum-types "^3.2.0" - lodash "^4.17.11" - web3-provider-engine "14.0.6" - -"@0x/json-schemas@^5.0.0": - version "5.0.0" - resolved "https://registry.yarnpkg.com/@0x/json-schemas/-/json-schemas-5.0.0.tgz#95c29fb7977adb19b9f0127122ec90efb38651ec" - integrity sha512-+OlJ5UBdX1MpXA/wD3j3GCD51IQmgp9zTvFriWbUIBn35imZe1gUETdn7tpeqxbTMOm4kHzwcSDrf5bdx6ztLA== - dependencies: - "@0x/typescript-typings" "^5.0.0" - "@types/node" "*" - jsonschema "^1.2.0" - lodash.values "^4.3.0" - -"@0x/json-schemas@^5.1.0": - version "5.1.0" - resolved "https://registry.yarnpkg.com/@0x/json-schemas/-/json-schemas-5.1.0.tgz#3f30529049ea5aa4cfc4aed2c2124c7482d632f1" - integrity sha512-qDiCz94AR140puQ0MHT6XyDbmDrvWjw+Zyysmf4tD9PfM8sD+MOhF9dfvaYPNlS51M1CIlOTWZYqo5OUCIBEXQ== - dependencies: - "@0x/typescript-typings" "^5.1.1" - "@types/node" "*" - jsonschema "^1.2.0" - lodash.values "^4.3.0" - -"@0x/sol-compiler@^4.1.1": - version "4.1.1" - resolved "https://registry.yarnpkg.com/@0x/sol-compiler/-/sol-compiler-4.1.1.tgz#dfab22e2370c03ef8dcfd910d66ced0d46ef5579" - integrity sha512-ktcTBz1m0cRn34t1ZkCn1BzssgLEI3ZLB6+aLq1OZzb3hGha9RW/yzl8UC7K/G/GPAK0rb3ip4t3TYHzIH/3lg== - dependencies: - "@0x/assert" "^3.0.9" - "@0x/json-schemas" "^5.1.0" - "@0x/sol-resolver" "^3.1.0" - "@0x/types" "^3.2.0" - "@0x/typescript-typings" "^5.1.1" - "@0x/utils" "^5.5.1" - "@0x/web3-wrapper" "^7.2.0" - "@types/yargs" "^11.0.0" - chalk "^2.3.0" - chokidar "^3.0.2" - ethereum-types "^3.2.0" - ethereumjs-util "^5.1.1" - lodash "^4.17.11" - mkdirp "^0.5.1" - pluralize "^7.0.0" - require-from-string "^2.0.1" - semver "5.5.0" - solc "^0.5.5" - source-map-support "^0.5.0" - web3-eth-abi "^1.0.0-beta.24" - yargs "^10.0.3" - -"@0x/sol-resolver@^3.1.0": - version "3.1.0" - resolved "https://registry.yarnpkg.com/@0x/sol-resolver/-/sol-resolver-3.1.0.tgz#86dbbc6641011df446f5a0e4545cd3360a3af52b" - integrity sha512-fyOngwc1qzN/rH+lrsGAACnXd8UuTVHkzj423+s3p5I2qhjDrQcxTfJpxQ1Yuc74fb9R0cXFRQto3A9LevjKxA== - dependencies: - "@0x/types" "^3.2.0" - "@0x/typescript-typings" "^5.1.1" - lodash "^4.17.11" - -"@0x/subproviders@=6.0.0": - version "6.0.0" - resolved "https://registry.yarnpkg.com/@0x/subproviders/-/subproviders-6.0.0.tgz#9d4b32e22c9e71f450b0f6d00978ca6b1129c0b3" - integrity sha512-5u0JpSGz6RtU0YKckV9FQeJAWkuESG6oR94GQujvkdxg1i1b/QGe9Njq+9VdPq6jhFwl7Hzr8K0JJYTXPlIo5A== - dependencies: - "@0x/assert" "^3.0.0" - "@0x/types" "^3.0.0" - "@0x/typescript-typings" "^5.0.0" - "@0x/utils" "^5.0.0" - "@0x/web3-wrapper" "^7.0.0" - "@ledgerhq/hw-app-eth" "^4.3.0" - "@ledgerhq/hw-transport-u2f" "4.24.0" - "@types/hdkey" "^0.7.0" - "@types/web3-provider-engine" "^14.0.0" - bip39 "^2.5.0" - bn.js "^4.11.8" - ethereum-types "^3.0.0" - ethereumjs-tx "^1.3.5" - ethereumjs-util "^5.1.1" - ganache-core "^2.6.0" - hdkey "^0.7.1" - json-rpc-error "2.0.0" - lodash "^4.17.11" - semaphore-async-await "^1.5.1" - web3-provider-engine "14.0.6" - optionalDependencies: - "@ledgerhq/hw-transport-node-hid" "^4.3.0" - -"@0x/subproviders@^6.1.1": - version "6.1.1" - resolved "https://registry.yarnpkg.com/@0x/subproviders/-/subproviders-6.1.1.tgz#f0d523055cb889652a7e53263cbe0b9d93bb1d4b" - integrity sha512-5rXmQbokPAlq6Am+O/C2QV6VlxKJGREncJ50ymLp0z8Bsyjt864Mgb1sB1ym19Qg6EJEhamQiJzVrrkN4ApbTQ== - dependencies: - "@0x/assert" "^3.0.9" - "@0x/types" "^3.2.0" - "@0x/typescript-typings" "^5.1.1" - "@0x/utils" "^5.5.1" - "@0x/web3-wrapper" "^7.2.0" - "@ledgerhq/hw-app-eth" "^4.3.0" - "@ledgerhq/hw-transport-u2f" "4.24.0" - "@types/hdkey" "^0.7.0" - "@types/web3-provider-engine" "^14.0.0" - bip39 "^2.5.0" - bn.js "^4.11.8" - ethereum-types "^3.2.0" - ethereumjs-tx "^1.3.5" - ethereumjs-util "^5.1.1" - ganache-core "^2.10.2" - hdkey "^0.7.1" - json-rpc-error "2.0.0" - lodash "^4.17.11" - semaphore-async-await "^1.5.1" - web3-provider-engine "14.0.6" - optionalDependencies: - "@ledgerhq/hw-transport-node-hid" "^4.3.0" - -"@0x/types@^3.0.0": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@0x/types/-/types-3.0.0.tgz#3cc815094fb9b73d3bc6bbe29735af982a0f519c" - integrity sha512-q+XRLgd/I7UbT73w0SRKLs9ZHe1FpIc5JZO1sLI3asNj+bb9FrFjuHiDJvZV33MjMI8u3IajN534YjVCMTBefg== - dependencies: - "@types/node" "*" - bignumber.js "~9.0.0" - ethereum-types "^3.0.0" - -"@0x/types@^3.2.0": - version "3.2.0" - resolved "https://registry.yarnpkg.com/@0x/types/-/types-3.2.0.tgz#490627e9440c3ff4e4660b0c10960ccd02d7105f" - integrity sha512-HcYXmz7gYtibJmZQjrQCnzV2FjRoo5b/Ul1QoTeQFAZ2M2ggt1wHspQ7vOkEAZEK/7TE4TKA4MlRwRLa4isL1Q== - dependencies: - "@types/node" "*" - bignumber.js "~9.0.0" - ethereum-types "^3.2.0" - -"@0x/typescript-typings@^5.0.0": - version "5.0.0" - resolved "https://registry.yarnpkg.com/@0x/typescript-typings/-/typescript-typings-5.0.0.tgz#54bb89fe78216cd9a1a737dead329ad1cb05bd94" - integrity sha512-4ZgHGY5OniFC8giOMF4W2l6YuOccIt7L0a52BKbJvBGpPeaDIlKWGuqxhp9nXDd212SlkYxALyoXlJd/We2kew== - dependencies: - "@types/bn.js" "^4.11.0" - "@types/react" "*" - bignumber.js "~9.0.0" - ethereum-types "^3.0.0" - popper.js "1.14.3" - -"@0x/typescript-typings@^5.1.1": - version "5.1.1" - resolved "https://registry.yarnpkg.com/@0x/typescript-typings/-/typescript-typings-5.1.1.tgz#e5216f33e5859d48cd441a059da9c56c2b6df36a" - integrity sha512-a8/uKPNStHORFQzI/DDEq4ixb4IricPogAJ3P17YnNYr/yF3HwXEu6+cFxs4qi1fr0zGoPe7D3XtqtR+dX/ajQ== - dependencies: - "@types/bn.js" "^4.11.0" - "@types/react" "*" - bignumber.js "~9.0.0" - ethereum-types "^3.2.0" - popper.js "1.14.3" - -"@0x/utils@^5.0.0": - version "5.0.0" - resolved "https://registry.yarnpkg.com/@0x/utils/-/utils-5.0.0.tgz#4b0acff872c9b158c9293849f8bd2bb62f17b8c5" - integrity sha512-Nsa8VHdSo4jhWmsEuuIAJIBG55swbtDn5vb4/Kh+pXWRoOhkCuJyE6E0OIikL0wmgasIISD+xaOnpgqCY1N/mQ== - dependencies: - "@0x/types" "^3.0.0" - "@0x/typescript-typings" "^5.0.0" - "@types/node" "*" - abortcontroller-polyfill "^1.1.9" - bignumber.js "~9.0.0" - chalk "^2.3.0" - detect-node "2.0.3" - ethereum-types "^3.0.0" - ethereumjs-util "^5.1.1" - ethers "~4.0.4" - isomorphic-fetch "2.2.1" - js-sha3 "^0.7.0" - lodash "^4.17.11" - -"@0x/utils@^5.5.1": - version "5.5.1" - resolved "https://registry.yarnpkg.com/@0x/utils/-/utils-5.5.1.tgz#5f131755e1692e7c7b74d03d224d94808d475dd7" - integrity sha512-UreVm7R/qEv1v4dVccb4Y6Oz13o8ko2vB10sdNrPAGbstqx3NfdEBkylNxD7I8Bkta/BIwHrLbtCN3jni8CSeg== - dependencies: - "@0x/types" "^3.2.0" - "@0x/typescript-typings" "^5.1.1" - "@types/node" "*" - abortcontroller-polyfill "^1.1.9" - bignumber.js "~9.0.0" - chalk "^2.3.0" - detect-node "2.0.3" - ethereum-types "^3.2.0" - ethereumjs-util "^5.1.1" - ethers "~4.0.4" - isomorphic-fetch "2.2.1" - js-sha3 "^0.7.0" - lodash "^4.17.11" - -"@0x/web3-wrapper@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@0x/web3-wrapper/-/web3-wrapper-7.0.0.tgz#323e7931f067f7f9ed88cca30bd1ed1f7505fc48" - integrity sha512-Cyd4/LIP69XDRkLA+OCRjFxx3mba0M+gG5zoXcc69HFTvZXV/mB36ibsQBvBI/CNVxUkxkrOQA/lG4+/zl3Dcg== - dependencies: - "@0x/assert" "^3.0.0" - "@0x/json-schemas" "^5.0.0" - "@0x/typescript-typings" "^5.0.0" - "@0x/utils" "^5.0.0" - ethereum-types "^3.0.0" - ethereumjs-util "^5.1.1" - ethers "~4.0.4" - lodash "^4.17.11" - -"@0x/web3-wrapper@^7.2.0": - version "7.2.0" - resolved "https://registry.yarnpkg.com/@0x/web3-wrapper/-/web3-wrapper-7.2.0.tgz#079f59276a7ea4e2920881645c51f71b1c0251e3" - integrity sha512-5jRr5Xl/co5VZB2sCFiokuRwuPc2BENeSVuXll/+YNmytP5+C+7oDvVt6GrGP3j5921GIr4EhusZMbvOFw1oKQ== - dependencies: - "@0x/assert" "^3.0.9" - "@0x/json-schemas" "^5.1.0" - "@0x/typescript-typings" "^5.1.1" - "@0x/utils" "^5.5.1" - ethereum-types "^3.2.0" - ethereumjs-util "^5.1.1" - ethers "~4.0.4" - lodash "^4.17.11" - -"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.5.5": - version "7.5.5" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.5.5.tgz#bc0782f6d69f7b7d49531219699b988f669a8f9d" - integrity sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw== - dependencies: - "@babel/highlight" "^7.0.0" - -"@babel/core@^7.1.0": - version "7.7.7" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.7.7.tgz#ee155d2e12300bcc0cff6a8ad46f2af5063803e9" - integrity sha512-jlSjuj/7z138NLZALxVgrx13AOtqip42ATZP7+kYl53GvDV6+4dCek1mVUo8z8c8Xnw/mx2q3d9HWh3griuesQ== - dependencies: - "@babel/code-frame" "^7.5.5" - "@babel/generator" "^7.7.7" - "@babel/helpers" "^7.7.4" - "@babel/parser" "^7.7.7" - "@babel/template" "^7.7.4" - "@babel/traverse" "^7.7.4" - "@babel/types" "^7.7.4" - convert-source-map "^1.7.0" - debug "^4.1.0" - json5 "^2.1.0" - lodash "^4.17.13" - resolve "^1.3.2" - semver "^5.4.1" - source-map "^0.5.0" - -"@babel/generator@^7.4.0", "@babel/generator@^7.7.4", "@babel/generator@^7.7.7": - version "7.7.7" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.7.7.tgz#859ac733c44c74148e1a72980a64ec84b85f4f45" - integrity sha512-/AOIBpHh/JU1l0ZFS4kiRCBnLi6OTHzh0RPk3h9isBxkkqELtQNFi1Vr/tiG9p1yfoUdKVwISuXWQR+hwwM4VQ== - dependencies: - "@babel/types" "^7.7.4" - jsesc "^2.5.1" - lodash "^4.17.13" - source-map "^0.5.0" - -"@babel/helper-function-name@^7.7.4": - version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.7.4.tgz#ab6e041e7135d436d8f0a3eca15de5b67a341a2e" - integrity sha512-AnkGIdiBhEuiwdoMnKm7jfPfqItZhgRaZfMg1XX3bS25INOnLPjPG1Ppnajh8eqgt5kPJnfqrRHqFqmjKDZLzQ== - dependencies: - "@babel/helper-get-function-arity" "^7.7.4" - "@babel/template" "^7.7.4" - "@babel/types" "^7.7.4" - -"@babel/helper-get-function-arity@^7.7.4": - version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.7.4.tgz#cb46348d2f8808e632f0ab048172130e636005f0" - integrity sha512-QTGKEdCkjgzgfJ3bAyRwF4yyT3pg+vDgan8DSivq1eS0gwi+KGKE5x8kRcbeFTb/673mkO5SN1IZfmCfA5o+EA== - dependencies: - "@babel/types" "^7.7.4" - -"@babel/helper-module-imports@^7.7.4": - version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.7.4.tgz#e5a92529f8888bf319a6376abfbd1cebc491ad91" - integrity sha512-dGcrX6K9l8258WFjyDLJwuVKxR4XZfU0/vTUgOQYWEnRD8mgr+p4d6fCUMq/ys0h4CCt/S5JhbvtyErjWouAUQ== - dependencies: - "@babel/types" "^7.7.4" - -"@babel/helper-plugin-utils@^7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.0.0.tgz#bbb3fbee98661c569034237cc03967ba99b4f250" - integrity sha512-CYAOUCARwExnEixLdB6sDm2dIJ/YgEAKDM1MOeMeZu9Ld/bDgVo8aiWrXwcY7OBh+1Ea2uUcVRcxKk0GJvW7QA== - -"@babel/helper-split-export-declaration@^7.7.4": - version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.7.4.tgz#57292af60443c4a3622cf74040ddc28e68336fd8" - integrity sha512-guAg1SXFcVr04Guk9eq0S4/rWS++sbmyqosJzVs8+1fH5NI+ZcmkaSkc7dmtAFbHFva6yRJnjW3yAcGxjueDug== - dependencies: - "@babel/types" "^7.7.4" - -"@babel/helpers@^7.7.4": - version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.7.4.tgz#62c215b9e6c712dadc15a9a0dcab76c92a940302" - integrity sha512-ak5NGZGJ6LV85Q1Zc9gn2n+ayXOizryhjSUBTdu5ih1tlVCJeuQENzc4ItyCVhINVXvIT/ZQ4mheGIsfBkpskg== - dependencies: - "@babel/template" "^7.7.4" - "@babel/traverse" "^7.7.4" - "@babel/types" "^7.7.4" - -"@babel/highlight@^7.0.0": - version "7.5.0" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.5.0.tgz#56d11312bd9248fa619591d02472be6e8cb32540" - integrity sha512-7dV4eu9gBxoM0dAnj/BCFDW9LFU0zvTrkq0ugM7pnHEgguOEeOz1so2ZghEdzviYzQEED0r4EAgpsBChKy1TRQ== - dependencies: - chalk "^2.0.0" - esutils "^2.0.2" - js-tokens "^4.0.0" - -"@babel/parser@^7.1.0", "@babel/parser@^7.4.3", "@babel/parser@^7.7.4", "@babel/parser@^7.7.7": - version "7.7.7" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.7.7.tgz#1b886595419cf92d811316d5b715a53ff38b4937" - integrity sha512-WtTZMZAZLbeymhkd/sEaPD8IQyGAhmuTuvTzLiCFM7iXiVdY0gc0IaI+cW0fh1BnSMbJSzXX6/fHllgHKwHhXw== - -"@babel/plugin-syntax-object-rest-spread@^7.0.0": - version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.7.4.tgz#47cf220d19d6d0d7b154304701f468fc1cc6ff46" - integrity sha512-mObR+r+KZq0XhRVS2BrBKBpr5jqrqzlPvS9C9vuOf5ilSwzloAl7RPWLrgKdWS6IreaVrjHxTjtyqFiOisaCwg== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - -"@babel/plugin-transform-runtime@^7.5.5": - version "7.7.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.7.6.tgz#4f2b548c88922fb98ec1c242afd4733ee3e12f61" - integrity sha512-tajQY+YmXR7JjTwRvwL4HePqoL3DYxpYXIHKVvrOIvJmeHe2y1w4tz5qz9ObUDC9m76rCzIMPyn4eERuwA4a4A== - dependencies: - "@babel/helper-module-imports" "^7.7.4" - "@babel/helper-plugin-utils" "^7.0.0" - resolve "^1.8.1" - semver "^5.5.1" - -"@babel/runtime@^7.5.5": - version "7.7.6" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.7.6.tgz#d18c511121aff1b4f2cd1d452f1bac9601dd830f" - integrity sha512-BWAJxpNVa0QlE5gZdWjSxXtemZyZ9RmrmVozxt3NUXeZhVIJ5ANyqmMc0JDrivBZyxUuQvFxlvH4OWWOogGfUw== - dependencies: - regenerator-runtime "^0.13.2" - -"@babel/template@^7.4.0", "@babel/template@^7.7.4": - version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.7.4.tgz#428a7d9eecffe27deac0a98e23bf8e3675d2a77b" - integrity sha512-qUzihgVPguAzXCK7WXw8pqs6cEwi54s3E+HrejlkuWO6ivMKx9hZl3Y2fSXp9i5HgyWmj7RKP+ulaYnKM4yYxw== - dependencies: - "@babel/code-frame" "^7.0.0" - "@babel/parser" "^7.7.4" - "@babel/types" "^7.7.4" - -"@babel/traverse@^7.1.0", "@babel/traverse@^7.4.3", "@babel/traverse@^7.7.4": - version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.7.4.tgz#9c1e7c60fb679fe4fcfaa42500833333c2058558" - integrity sha512-P1L58hQyupn8+ezVA2z5KBm4/Zr4lCC8dwKCMYzsa5jFMDMQAzaBNy9W5VjB+KAmBjb40U7a/H6ao+Xo+9saIw== - dependencies: - "@babel/code-frame" "^7.5.5" - "@babel/generator" "^7.7.4" - "@babel/helper-function-name" "^7.7.4" - "@babel/helper-split-export-declaration" "^7.7.4" - "@babel/parser" "^7.7.4" - "@babel/types" "^7.7.4" - debug "^4.1.0" - globals "^11.1.0" - lodash "^4.17.13" - -"@babel/types@^7.0.0", "@babel/types@^7.3.0", "@babel/types@^7.4.0", "@babel/types@^7.7.4": - version "7.7.4" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.7.4.tgz#516570d539e44ddf308c07569c258ff94fde9193" - integrity sha512-cz5Ji23KCi4T+YIE/BolWosrJuSmoZeN1EFnRtBwF+KKLi8GG/Z2c2hOJJeCXPk4mwk4QFvTmwIodJowXgttRA== - dependencies: - esutils "^2.0.2" - lodash "^4.17.13" - to-fast-properties "^2.0.0" - -"@cnakazawa/watch@^1.0.3": - version "1.0.3" - resolved "https://registry.yarnpkg.com/@cnakazawa/watch/-/watch-1.0.3.tgz#099139eaec7ebf07a27c1786a3ff64f39464d2ef" - integrity sha512-r5160ogAvGyHsal38Kux7YYtodEKOj89RGb28ht1jh3SJb08VwRwAKKJL0bGb04Zd/3r9FL3BFIc3bBidYffCA== - dependencies: - exec-sh "^0.3.2" - minimist "^1.2.0" - -"@compound-finance/sol-coverage@=4.0.10-alpha.7": - version "4.0.10-alpha.7" - resolved "https://registry.yarnpkg.com/@compound-finance/sol-coverage/-/sol-coverage-4.0.10-alpha.7.tgz#7459f23a9934f987e865bc1717a33da137dae696" - integrity sha512-UtBAc50sdv2KEnG3y5d2Vm/WvN5UvnhhZZ73BSYut67DNu4l22kOvlgivgO+Gd4cfTHRNhoy7cy0mZuUBomDfQ== - dependencies: - "@0x/subproviders" "^6.1.1" - "@0x/typescript-typings" "^5.1.1" - "@compound-finance/sol-tracing-utils" "^7.1.0-alpha.7" - "@types/minimatch" "^3.0.3" - ethereum-types "^3.2.0" - lodash "^4.17.11" - minimatch "^3.0.4" - web3-provider-engine "14.0.6" - -"@compound-finance/sol-tracing-utils@=7.1.0-alpha.7", "@compound-finance/sol-tracing-utils@^7.1.0-alpha.7": - version "7.1.0-alpha.7" - resolved "https://registry.yarnpkg.com/@compound-finance/sol-tracing-utils/-/sol-tracing-utils-7.1.0-alpha.7.tgz#ad4b06320fb2db115d3266ca8fdfdd68e6d57080" - integrity sha512-7yrJsjg7U6zwrDu09FTRN2ziQAv140dBZnQEasiXGy2UPhv17hToKow/bXtrR233ULQ3xHNR9hlpm2jatE5xVQ== - dependencies: - "@0x/dev-utils" "^3.3.0" - "@0x/sol-compiler" "^4.1.1" - "@0x/sol-resolver" "^3.1.0" - "@0x/subproviders" "^6.1.1" - "@0x/typescript-typings" "^5.1.1" - "@0x/utils" "^5.5.1" - "@0x/web3-wrapper" "^7.2.0" - "@types/solidity-parser-antlr" "^0.2.3" - chalk "^2.3.0" - ethereum-types "^3.2.0" - ethereumjs-util "^5.1.1" - ethers "~4.0.4" - glob "^7.1.2" - istanbul "^0.4.5" - lodash "^4.17.11" - loglevel "^1.6.1" - mkdirp "^0.5.1" - rimraf "^2.6.2" - semaphore-async-await "^1.5.1" - solc "^0.5.5" - solidity-parser-antlr "https://github.com/solidity-parser/parser" - -"@ethersproject/abi@5.0.0-beta.153": - version "5.0.0-beta.153" - resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.0.0-beta.153.tgz#43a37172b33794e4562999f6e2d555b7599a8eee" - integrity sha512-aXweZ1Z7vMNzJdLpR1CZUAIgnwjrZeUSvN9syCwlBaEBUFJmFY+HHnfuTI5vIhVs/mRkfJVrbEyl51JZQqyjAg== - dependencies: - "@ethersproject/address" ">=5.0.0-beta.128" - "@ethersproject/bignumber" ">=5.0.0-beta.130" - "@ethersproject/bytes" ">=5.0.0-beta.129" - "@ethersproject/constants" ">=5.0.0-beta.128" - "@ethersproject/hash" ">=5.0.0-beta.128" - "@ethersproject/keccak256" ">=5.0.0-beta.127" - "@ethersproject/logger" ">=5.0.0-beta.129" - "@ethersproject/properties" ">=5.0.0-beta.131" - "@ethersproject/strings" ">=5.0.0-beta.130" - -"@ethersproject/abi@5.4.1", "@ethersproject/abi@^5.4.0": - version "5.4.1" - resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.4.1.tgz#6ac28fafc9ef6f5a7a37e30356a2eb31fa05d39b" - integrity sha512-9mhbjUk76BiSluiiW4BaYyI58KSbDMMQpCLdsAR+RsT2GyATiNYxVv+pGWRrekmsIdY3I+hOqsYQSTkc8L/mcg== - dependencies: - "@ethersproject/address" "^5.4.0" - "@ethersproject/bignumber" "^5.4.0" - "@ethersproject/bytes" "^5.4.0" - "@ethersproject/constants" "^5.4.0" - "@ethersproject/hash" "^5.4.0" - "@ethersproject/keccak256" "^5.4.0" - "@ethersproject/logger" "^5.4.0" - "@ethersproject/properties" "^5.4.0" - "@ethersproject/strings" "^5.4.0" - -"@ethersproject/abstract-provider@5.4.1", "@ethersproject/abstract-provider@^5.4.0": - version "5.4.1" - resolved "https://registry.yarnpkg.com/@ethersproject/abstract-provider/-/abstract-provider-5.4.1.tgz#e404309a29f771bd4d28dbafadcaa184668c2a6e" - integrity sha512-3EedfKI3LVpjSKgAxoUaI+gB27frKsxzm+r21w9G60Ugk+3wVLQwhi1LsEJAKNV7WoZc8CIpNrATlL1QFABjtQ== - dependencies: - "@ethersproject/bignumber" "^5.4.0" - "@ethersproject/bytes" "^5.4.0" - "@ethersproject/logger" "^5.4.0" - "@ethersproject/networks" "^5.4.0" - "@ethersproject/properties" "^5.4.0" - "@ethersproject/transactions" "^5.4.0" - "@ethersproject/web" "^5.4.0" - -"@ethersproject/abstract-signer@5.4.1", "@ethersproject/abstract-signer@^5.4.0": - version "5.4.1" - resolved "https://registry.yarnpkg.com/@ethersproject/abstract-signer/-/abstract-signer-5.4.1.tgz#e4e9abcf4dd4f1ba0db7dff9746a5f78f355ea81" - integrity sha512-SkkFL5HVq1k4/25dM+NWP9MILgohJCgGv5xT5AcRruGz4ILpfHeBtO/y6j+Z3UN/PAjDeb4P7E51Yh8wcGNLGA== - dependencies: - "@ethersproject/abstract-provider" "^5.4.0" - "@ethersproject/bignumber" "^5.4.0" - "@ethersproject/bytes" "^5.4.0" - "@ethersproject/logger" "^5.4.0" - "@ethersproject/properties" "^5.4.0" - -"@ethersproject/address@5.4.0", "@ethersproject/address@^5.0.0", "@ethersproject/address@^5.4.0": - version "5.4.0" - resolved "https://registry.yarnpkg.com/@ethersproject/address/-/address-5.4.0.tgz#ba2d00a0f8c4c0854933b963b9a3a9f6eb4a37a3" - integrity sha512-SD0VgOEkcACEG/C6xavlU1Hy3m5DGSXW3CUHkaaEHbAPPsgi0coP5oNPsxau8eTlZOk/bpa/hKeCNoK5IzVI2Q== - dependencies: - "@ethersproject/bignumber" "^5.4.0" - "@ethersproject/bytes" "^5.4.0" - "@ethersproject/keccak256" "^5.4.0" - "@ethersproject/logger" "^5.4.0" - "@ethersproject/rlp" "^5.4.0" - -"@ethersproject/address@>=5.0.0-beta.128": - version "5.0.2" - resolved "https://registry.yarnpkg.com/@ethersproject/address/-/address-5.0.2.tgz#80d0ddfb7d4bd0d32657747fa4bdd2defef2e00a" - integrity sha512-+rz26RKj7ujGfQynys4V9VJRbR+wpC6eL8F22q3raWMH3152Ha31GwJPWzxE/bEA+43M/zTNVwY0R53gn53L2Q== - dependencies: - "@ethersproject/bignumber" "^5.0.0" - "@ethersproject/bytes" "^5.0.0" - "@ethersproject/keccak256" "^5.0.0" - "@ethersproject/logger" "^5.0.0" - "@ethersproject/rlp" "^5.0.0" - bn.js "^4.4.0" - -"@ethersproject/base64@5.4.0", "@ethersproject/base64@^5.4.0": - version "5.4.0" - resolved "https://registry.yarnpkg.com/@ethersproject/base64/-/base64-5.4.0.tgz#7252bf65295954c9048c7ca5f43e5c86441b2a9a" - integrity sha512-CjQw6E17QDSSC5jiM9YpF7N1aSCHmYGMt9bWD8PWv6YPMxjsys2/Q8xLrROKI3IWJ7sFfZ8B3flKDTM5wlWuZQ== - dependencies: - "@ethersproject/bytes" "^5.4.0" - -"@ethersproject/basex@5.4.0", "@ethersproject/basex@^5.4.0": - version "5.4.0" - resolved "https://registry.yarnpkg.com/@ethersproject/basex/-/basex-5.4.0.tgz#0a2da0f4e76c504a94f2b21d3161ed9438c7f8a6" - integrity sha512-J07+QCVJ7np2bcpxydFVf/CuYo9mZ7T73Pe7KQY4c1lRlrixMeblauMxHXD0MPwFmUHZIILDNViVkykFBZylbg== - dependencies: - "@ethersproject/bytes" "^5.4.0" - "@ethersproject/properties" "^5.4.0" - -"@ethersproject/bignumber@5.4.1", "@ethersproject/bignumber@^5.0.0", "@ethersproject/bignumber@^5.4.0": - version "5.4.1" - resolved "https://registry.yarnpkg.com/@ethersproject/bignumber/-/bignumber-5.4.1.tgz#64399d3b9ae80aa83d483e550ba57ea062c1042d" - integrity sha512-fJhdxqoQNuDOk6epfM7yD6J8Pol4NUCy1vkaGAkuujZm0+lNow//MKu1hLhRiYV4BsOHyBv5/lsTjF+7hWwhJg== - dependencies: - "@ethersproject/bytes" "^5.4.0" - "@ethersproject/logger" "^5.4.0" - bn.js "^4.11.9" - -"@ethersproject/bignumber@>=5.0.0-beta.130": - version "5.0.5" - resolved "https://registry.yarnpkg.com/@ethersproject/bignumber/-/bignumber-5.0.5.tgz#31bd7e75aad46ace345fae69b1f5bb120906af1b" - integrity sha512-24ln7PV0g8ZzjcVZiLW9Wod0i+XCmK6zKkAaxw5enraTIT1p7gVOcSXFSzNQ9WYAwtiFQPvvA+TIO2oEITZNJA== - dependencies: - "@ethersproject/bytes" "^5.0.0" - "@ethersproject/logger" "^5.0.0" - bn.js "^4.4.0" - -"@ethersproject/bytes@5.4.0", "@ethersproject/bytes@^5.0.0", "@ethersproject/bytes@^5.4.0": - version "5.4.0" - resolved "https://registry.yarnpkg.com/@ethersproject/bytes/-/bytes-5.4.0.tgz#56fa32ce3bf67153756dbaefda921d1d4774404e" - integrity sha512-H60ceqgTHbhzOj4uRc/83SCN9d+BSUnOkrr2intevqdtEMO1JFVZ1XL84OEZV+QjV36OaZYxtnt4lGmxcGsPfA== - dependencies: - "@ethersproject/logger" "^5.4.0" - -"@ethersproject/bytes@>=5.0.0-beta.129": - version "5.0.3" - resolved "https://registry.yarnpkg.com/@ethersproject/bytes/-/bytes-5.0.3.tgz#b3769963ae0188a35713d343890a903bda20af9c" - integrity sha512-AyPMAlY+Amaw4Zfp8OAivm1xYPI8mqiUYmEnSUk1CnS2NrQGHEMmFJFiOJdS3gDDpgSOFhWIjZwxKq2VZpqNTA== - dependencies: - "@ethersproject/logger" "^5.0.0" - -"@ethersproject/constants@5.4.0", "@ethersproject/constants@^5.0.0", "@ethersproject/constants@^5.4.0": - version "5.4.0" - resolved "https://registry.yarnpkg.com/@ethersproject/constants/-/constants-5.4.0.tgz#ee0bdcb30bf1b532d2353c977bf2ef1ee117958a" - integrity sha512-tzjn6S7sj9+DIIeKTJLjK9WGN2Tj0P++Z8ONEIlZjyoTkBuODN+0VfhAyYksKi43l1Sx9tX2VlFfzjfmr5Wl3Q== - dependencies: - "@ethersproject/bignumber" "^5.4.0" - -"@ethersproject/constants@>=5.0.0-beta.128": - version "5.0.2" - resolved "https://registry.yarnpkg.com/@ethersproject/constants/-/constants-5.0.2.tgz#f7ac0b320e2bbec1a5950da075015f8bc4e8fed1" - integrity sha512-nNoVlNP6bgpog7pQ2EyD1xjlaXcy1Cl4kK5v1KoskHj58EtB6TK8M8AFGi3GgHTdMldfT4eN3OsoQ/CdOTVNFA== - dependencies: - "@ethersproject/bignumber" "^5.0.0" - -"@ethersproject/contracts@5.4.1": - version "5.4.1" - resolved "https://registry.yarnpkg.com/@ethersproject/contracts/-/contracts-5.4.1.tgz#3eb4f35b7fe60a962a75804ada2746494df3e470" - integrity sha512-m+z2ZgPy4pyR15Je//dUaymRUZq5MtDajF6GwFbGAVmKz/RF+DNIPwF0k5qEcL3wPGVqUjFg2/krlCRVTU4T5w== - dependencies: - "@ethersproject/abi" "^5.4.0" - "@ethersproject/abstract-provider" "^5.4.0" - "@ethersproject/abstract-signer" "^5.4.0" - "@ethersproject/address" "^5.4.0" - "@ethersproject/bignumber" "^5.4.0" - "@ethersproject/bytes" "^5.4.0" - "@ethersproject/constants" "^5.4.0" - "@ethersproject/logger" "^5.4.0" - "@ethersproject/properties" "^5.4.0" - "@ethersproject/transactions" "^5.4.0" - -"@ethersproject/hash@5.4.0", "@ethersproject/hash@^5.4.0": - version "5.4.0" - resolved "https://registry.yarnpkg.com/@ethersproject/hash/-/hash-5.4.0.tgz#d18a8e927e828e22860a011f39e429d388344ae0" - integrity sha512-xymAM9tmikKgbktOCjW60Z5sdouiIIurkZUr9oW5NOex5uwxrbsYG09kb5bMcNjlVeJD3yPivTNzViIs1GCbqA== - dependencies: - "@ethersproject/abstract-signer" "^5.4.0" - "@ethersproject/address" "^5.4.0" - "@ethersproject/bignumber" "^5.4.0" - "@ethersproject/bytes" "^5.4.0" - "@ethersproject/keccak256" "^5.4.0" - "@ethersproject/logger" "^5.4.0" - "@ethersproject/properties" "^5.4.0" - "@ethersproject/strings" "^5.4.0" - -"@ethersproject/hash@>=5.0.0-beta.128": - version "5.0.2" - resolved "https://registry.yarnpkg.com/@ethersproject/hash/-/hash-5.0.2.tgz#6d69558786961836d530b8b4a8714eac5388aec7" - integrity sha512-dWGvNwmVRX2bxoQQ3ciMw46Vzl1nqfL+5R8+2ZxsRXD3Cjgw1dL2mdjJF7xMMWPvPdrlhKXWSK0gb8VLwHZ8Cw== - dependencies: - "@ethersproject/bytes" "^5.0.0" - "@ethersproject/keccak256" "^5.0.0" - "@ethersproject/logger" "^5.0.0" - "@ethersproject/strings" "^5.0.0" - -"@ethersproject/hdnode@5.4.0", "@ethersproject/hdnode@^5.4.0": - version "5.4.0" - resolved "https://registry.yarnpkg.com/@ethersproject/hdnode/-/hdnode-5.4.0.tgz#4bc9999b9a12eb5ce80c5faa83114a57e4107cac" - integrity sha512-pKxdS0KAaeVGfZPp1KOiDLB0jba11tG6OP1u11QnYfb7pXn6IZx0xceqWRr6ygke8+Kw74IpOoSi7/DwANhy8Q== - dependencies: - "@ethersproject/abstract-signer" "^5.4.0" - "@ethersproject/basex" "^5.4.0" - "@ethersproject/bignumber" "^5.4.0" - "@ethersproject/bytes" "^5.4.0" - "@ethersproject/logger" "^5.4.0" - "@ethersproject/pbkdf2" "^5.4.0" - "@ethersproject/properties" "^5.4.0" - "@ethersproject/sha2" "^5.4.0" - "@ethersproject/signing-key" "^5.4.0" - "@ethersproject/strings" "^5.4.0" - "@ethersproject/transactions" "^5.4.0" - "@ethersproject/wordlists" "^5.4.0" - -"@ethersproject/json-wallets@5.4.0", "@ethersproject/json-wallets@^5.4.0": - version "5.4.0" - resolved "https://registry.yarnpkg.com/@ethersproject/json-wallets/-/json-wallets-5.4.0.tgz#2583341cfe313fc9856642e8ace3080154145e95" - integrity sha512-igWcu3fx4aiczrzEHwG1xJZo9l1cFfQOWzTqwRw/xcvxTk58q4f9M7cjh51EKphMHvrJtcezJ1gf1q1AUOfEQQ== - dependencies: - "@ethersproject/abstract-signer" "^5.4.0" - "@ethersproject/address" "^5.4.0" - "@ethersproject/bytes" "^5.4.0" - "@ethersproject/hdnode" "^5.4.0" - "@ethersproject/keccak256" "^5.4.0" - "@ethersproject/logger" "^5.4.0" - "@ethersproject/pbkdf2" "^5.4.0" - "@ethersproject/properties" "^5.4.0" - "@ethersproject/random" "^5.4.0" - "@ethersproject/strings" "^5.4.0" - "@ethersproject/transactions" "^5.4.0" - aes-js "3.0.0" - scrypt-js "3.0.1" - -"@ethersproject/keccak256@5.4.0", "@ethersproject/keccak256@^5.0.0", "@ethersproject/keccak256@^5.4.0": - version "5.4.0" - resolved "https://registry.yarnpkg.com/@ethersproject/keccak256/-/keccak256-5.4.0.tgz#7143b8eea4976080241d2bd92e3b1f1bf7025318" - integrity sha512-FBI1plWet+dPUvAzPAeHzRKiPpETQzqSUWR1wXJGHVWi4i8bOSrpC3NwpkPjgeXG7MnugVc1B42VbfnQikyC/A== - dependencies: - "@ethersproject/bytes" "^5.4.0" - js-sha3 "0.5.7" - -"@ethersproject/keccak256@>=5.0.0-beta.127": - version "5.0.2" - resolved "https://registry.yarnpkg.com/@ethersproject/keccak256/-/keccak256-5.0.2.tgz#7ed4a95bb45ee502cf4532223833740a83602797" - integrity sha512-MbroXutc0gPNYIrUjS4Aw0lDuXabdzI7+l7elRWr1G6G+W0v00e/3gbikWkCReGtt2Jnt4lQSgnflhDwQGcIhA== - dependencies: - "@ethersproject/bytes" "^5.0.0" - js-sha3 "0.5.7" - -"@ethersproject/logger@5.4.1", "@ethersproject/logger@^5.0.0", "@ethersproject/logger@^5.4.0": - version "5.4.1" - resolved "https://registry.yarnpkg.com/@ethersproject/logger/-/logger-5.4.1.tgz#503bd33683538b923c578c07d1c2c0dd18672054" - integrity sha512-DZ+bRinnYLPw1yAC64oRl0QyVZj43QeHIhVKfD/+YwSz4wsv1pfwb5SOFjz+r710YEWzU6LrhuSjpSO+6PeE4A== - -"@ethersproject/logger@>=5.0.0-beta.129": - version "5.0.4" - resolved "https://registry.yarnpkg.com/@ethersproject/logger/-/logger-5.0.4.tgz#09fa4765b5691233e3afb6617cb38a700f9dd2e4" - integrity sha512-alA2LiAy1LdQ/L1SA9ajUC7MvGAEQLsICEfKK4erX5qhkXE1LwLSPIzobtOWFsMHf2yrXGKBLnnpuVHprI3sAw== - -"@ethersproject/networks@5.4.2", "@ethersproject/networks@^5.4.0": - version "5.4.2" - resolved "https://registry.yarnpkg.com/@ethersproject/networks/-/networks-5.4.2.tgz#2247d977626e97e2c3b8ee73cd2457babde0ce35" - integrity sha512-eekOhvJyBnuibfJnhtK46b8HimBc5+4gqpvd1/H9LEl7Q7/qhsIhM81dI9Fcnjpk3jB1aTy6bj0hz3cifhNeYw== - dependencies: - "@ethersproject/logger" "^5.4.0" - -"@ethersproject/pbkdf2@5.4.0", "@ethersproject/pbkdf2@^5.4.0": - version "5.4.0" - resolved "https://registry.yarnpkg.com/@ethersproject/pbkdf2/-/pbkdf2-5.4.0.tgz#ed88782a67fda1594c22d60d0ca911a9d669641c" - integrity sha512-x94aIv6tiA04g6BnazZSLoRXqyusawRyZWlUhKip2jvoLpzJuLb//KtMM6PEovE47pMbW+Qe1uw+68ameJjB7g== - dependencies: - "@ethersproject/bytes" "^5.4.0" - "@ethersproject/sha2" "^5.4.0" - -"@ethersproject/properties@5.4.1", "@ethersproject/properties@^5.0.0", "@ethersproject/properties@^5.4.0": - version "5.4.1" - resolved "https://registry.yarnpkg.com/@ethersproject/properties/-/properties-5.4.1.tgz#9f051f976ce790142c6261ccb7b826eaae1f2f36" - integrity sha512-cyCGlF8wWlIZyizsj2PpbJ9I7rIlUAfnHYwy/T90pdkSn/NFTa5YWZx2wTJBe9V7dD65dcrrEMisCRUJiq6n3w== - dependencies: - "@ethersproject/logger" "^5.4.0" - -"@ethersproject/properties@>=5.0.0-beta.131": - version "5.0.2" - resolved "https://registry.yarnpkg.com/@ethersproject/properties/-/properties-5.0.2.tgz#2facb62d2f2d968c7b3d0befa5bcc884cc565d3b" - integrity sha512-FxAisPGAOACQjMJzewl9OJG6lsGCPTm5vpUMtfeoxzAlAb2lv+kHzQPUh9h4jfAILzE8AR1jgXMzRmlhwyra1Q== - dependencies: - "@ethersproject/logger" "^5.0.0" - -"@ethersproject/providers@5.4.5": - version "5.4.5" - resolved "https://registry.yarnpkg.com/@ethersproject/providers/-/providers-5.4.5.tgz#eb2ea2a743a8115f79604a8157233a3a2c832928" - integrity sha512-1GkrvkiAw3Fj28cwi1Sqm8ED1RtERtpdXmRfwIBGmqBSN5MoeRUHuwHPppMtbPayPgpFcvD7/Gdc9doO5fGYgw== - dependencies: - "@ethersproject/abstract-provider" "^5.4.0" - "@ethersproject/abstract-signer" "^5.4.0" - "@ethersproject/address" "^5.4.0" - "@ethersproject/basex" "^5.4.0" - "@ethersproject/bignumber" "^5.4.0" - "@ethersproject/bytes" "^5.4.0" - "@ethersproject/constants" "^5.4.0" - "@ethersproject/hash" "^5.4.0" - "@ethersproject/logger" "^5.4.0" - "@ethersproject/networks" "^5.4.0" - "@ethersproject/properties" "^5.4.0" - "@ethersproject/random" "^5.4.0" - "@ethersproject/rlp" "^5.4.0" - "@ethersproject/sha2" "^5.4.0" - "@ethersproject/strings" "^5.4.0" - "@ethersproject/transactions" "^5.4.0" - "@ethersproject/web" "^5.4.0" - bech32 "1.1.4" - ws "7.4.6" - -"@ethersproject/random@5.4.0", "@ethersproject/random@^5.4.0": - version "5.4.0" - resolved "https://registry.yarnpkg.com/@ethersproject/random/-/random-5.4.0.tgz#9cdde60e160d024be39cc16f8de3b9ce39191e16" - integrity sha512-pnpWNQlf0VAZDEOVp1rsYQosmv2o0ITS/PecNw+mS2/btF8eYdspkN0vIXrCMtkX09EAh9bdk8GoXmFXM1eAKw== - dependencies: - "@ethersproject/bytes" "^5.4.0" - "@ethersproject/logger" "^5.4.0" - -"@ethersproject/rlp@5.4.0", "@ethersproject/rlp@^5.0.0", "@ethersproject/rlp@^5.4.0": - version "5.4.0" - resolved "https://registry.yarnpkg.com/@ethersproject/rlp/-/rlp-5.4.0.tgz#de61afda5ff979454e76d3b3310a6c32ad060931" - integrity sha512-0I7MZKfi+T5+G8atId9QaQKHRvvasM/kqLyAH4XxBCBchAooH2EX5rL9kYZWwcm3awYV+XC7VF6nLhfeQFKVPg== - dependencies: - "@ethersproject/bytes" "^5.4.0" - "@ethersproject/logger" "^5.4.0" - -"@ethersproject/sha2@5.4.0", "@ethersproject/sha2@^5.4.0": - version "5.4.0" - resolved "https://registry.yarnpkg.com/@ethersproject/sha2/-/sha2-5.4.0.tgz#c9a8db1037014cbc4e9482bd662f86c090440371" - integrity sha512-siheo36r1WD7Cy+bDdE1BJ8y0bDtqXCOxRMzPa4bV1TGt/eTUUt03BHoJNB6reWJD8A30E/pdJ8WFkq+/uz4Gg== - dependencies: - "@ethersproject/bytes" "^5.4.0" - "@ethersproject/logger" "^5.4.0" - hash.js "1.1.7" - -"@ethersproject/signing-key@5.4.0", "@ethersproject/signing-key@^5.0.0", "@ethersproject/signing-key@^5.4.0": - version "5.4.0" - resolved "https://registry.yarnpkg.com/@ethersproject/signing-key/-/signing-key-5.4.0.tgz#2f05120984e81cf89a3d5f6dec5c68ee0894fbec" - integrity sha512-q8POUeywx6AKg2/jX9qBYZIAmKSB4ubGXdQ88l40hmATj29JnG5pp331nAWwwxPn2Qao4JpWHNZsQN+bPiSW9A== - dependencies: - "@ethersproject/bytes" "^5.4.0" - "@ethersproject/logger" "^5.4.0" - "@ethersproject/properties" "^5.4.0" - bn.js "^4.11.9" - elliptic "6.5.4" - hash.js "1.1.7" - -"@ethersproject/solidity@5.4.0": - version "5.4.0" - resolved "https://registry.yarnpkg.com/@ethersproject/solidity/-/solidity-5.4.0.tgz#1305e058ea02dc4891df18b33232b11a14ece9ec" - integrity sha512-XFQTZ7wFSHOhHcV1DpcWj7VXECEiSrBuv7JErJvB9Uo+KfCdc3QtUZV+Vjh/AAaYgezUEKbCtE6Khjm44seevQ== - dependencies: - "@ethersproject/bignumber" "^5.4.0" - "@ethersproject/bytes" "^5.4.0" - "@ethersproject/keccak256" "^5.4.0" - "@ethersproject/sha2" "^5.4.0" - "@ethersproject/strings" "^5.4.0" - -"@ethersproject/strings@5.4.0", "@ethersproject/strings@^5.0.0", "@ethersproject/strings@^5.4.0": - version "5.4.0" - resolved "https://registry.yarnpkg.com/@ethersproject/strings/-/strings-5.4.0.tgz#fb12270132dd84b02906a8d895ae7e7fa3d07d9a" - integrity sha512-k/9DkH5UGDhv7aReXLluFG5ExurwtIpUfnDNhQA29w896Dw3i4uDTz01Quaptbks1Uj9kI8wo9tmW73wcIEaWA== - dependencies: - "@ethersproject/bytes" "^5.4.0" - "@ethersproject/constants" "^5.4.0" - "@ethersproject/logger" "^5.4.0" - -"@ethersproject/strings@>=5.0.0-beta.130": - version "5.0.2" - resolved "https://registry.yarnpkg.com/@ethersproject/strings/-/strings-5.0.2.tgz#1753408c3c889813fd0992abd76393e3e47a2619" - integrity sha512-oNa+xvSqsFU96ndzog0IBTtsRFGOqGpzrXJ7shXLBT7juVeSEyZA/sYs0DMZB5mJ9FEjHdZKxR/rTyBY91vuXg== - dependencies: - "@ethersproject/bytes" "^5.0.0" - "@ethersproject/constants" "^5.0.0" - "@ethersproject/logger" "^5.0.0" - -"@ethersproject/transactions@5.4.0", "@ethersproject/transactions@^5.4.0": - version "5.4.0" - resolved "https://registry.yarnpkg.com/@ethersproject/transactions/-/transactions-5.4.0.tgz#a159d035179334bd92f340ce0f77e83e9e1522e0" - integrity sha512-s3EjZZt7xa4BkLknJZ98QGoIza94rVjaEed0rzZ/jB9WrIuu/1+tjvYCWzVrystXtDswy7TPBeIepyXwSYa4WQ== - dependencies: - "@ethersproject/address" "^5.4.0" - "@ethersproject/bignumber" "^5.4.0" - "@ethersproject/bytes" "^5.4.0" - "@ethersproject/constants" "^5.4.0" - "@ethersproject/keccak256" "^5.4.0" - "@ethersproject/logger" "^5.4.0" - "@ethersproject/properties" "^5.4.0" - "@ethersproject/rlp" "^5.4.0" - "@ethersproject/signing-key" "^5.4.0" - -"@ethersproject/transactions@^5.0.0-beta.135": - version "5.0.2" - resolved "https://registry.yarnpkg.com/@ethersproject/transactions/-/transactions-5.0.2.tgz#590ede71fc87b45be7bd46002e18ae52246a2347" - integrity sha512-jZp0ZbbJlq4JLZY6qoMzNtp2HQsX6USQposi3ns0MPUdn3OdZJBDtrcO15r/2VS5t/K1e1GE5MI1HmMKlcTbbQ== - dependencies: - "@ethersproject/address" "^5.0.0" - "@ethersproject/bignumber" "^5.0.0" - "@ethersproject/bytes" "^5.0.0" - "@ethersproject/constants" "^5.0.0" - "@ethersproject/keccak256" "^5.0.0" - "@ethersproject/logger" "^5.0.0" - "@ethersproject/properties" "^5.0.0" - "@ethersproject/rlp" "^5.0.0" - "@ethersproject/signing-key" "^5.0.0" - -"@ethersproject/units@5.4.0": - version "5.4.0" - resolved "https://registry.yarnpkg.com/@ethersproject/units/-/units-5.4.0.tgz#d57477a4498b14b88b10396062c8cbbaf20c79fe" - integrity sha512-Z88krX40KCp+JqPCP5oPv5p750g+uU6gopDYRTBGcDvOASh6qhiEYCRatuM/suC4S2XW9Zz90QI35MfSrTIaFg== - dependencies: - "@ethersproject/bignumber" "^5.4.0" - "@ethersproject/constants" "^5.4.0" - "@ethersproject/logger" "^5.4.0" - -"@ethersproject/wallet@5.4.0": - version "5.4.0" - resolved "https://registry.yarnpkg.com/@ethersproject/wallet/-/wallet-5.4.0.tgz#fa5b59830b42e9be56eadd45a16a2e0933ad9353" - integrity sha512-wU29majLjM6AjCjpat21mPPviG+EpK7wY1+jzKD0fg3ui5fgedf2zEu1RDgpfIMsfn8fJHJuzM4zXZ2+hSHaSQ== - dependencies: - "@ethersproject/abstract-provider" "^5.4.0" - "@ethersproject/abstract-signer" "^5.4.0" - "@ethersproject/address" "^5.4.0" - "@ethersproject/bignumber" "^5.4.0" - "@ethersproject/bytes" "^5.4.0" - "@ethersproject/hash" "^5.4.0" - "@ethersproject/hdnode" "^5.4.0" - "@ethersproject/json-wallets" "^5.4.0" - "@ethersproject/keccak256" "^5.4.0" - "@ethersproject/logger" "^5.4.0" - "@ethersproject/properties" "^5.4.0" - "@ethersproject/random" "^5.4.0" - "@ethersproject/signing-key" "^5.4.0" - "@ethersproject/transactions" "^5.4.0" - "@ethersproject/wordlists" "^5.4.0" - -"@ethersproject/web@5.4.0", "@ethersproject/web@^5.4.0": - version "5.4.0" - resolved "https://registry.yarnpkg.com/@ethersproject/web/-/web-5.4.0.tgz#49fac173b96992334ed36a175538ba07a7413d1f" - integrity sha512-1bUusGmcoRLYgMn6c1BLk1tOKUIFuTg8j+6N8lYlbMpDesnle+i3pGSagGNvwjaiLo4Y5gBibwctpPRmjrh4Og== - dependencies: - "@ethersproject/base64" "^5.4.0" - "@ethersproject/bytes" "^5.4.0" - "@ethersproject/logger" "^5.4.0" - "@ethersproject/properties" "^5.4.0" - "@ethersproject/strings" "^5.4.0" - -"@ethersproject/wordlists@5.4.0", "@ethersproject/wordlists@^5.4.0": - version "5.4.0" - resolved "https://registry.yarnpkg.com/@ethersproject/wordlists/-/wordlists-5.4.0.tgz#f34205ec3bbc9e2c49cadaee774cf0b07e7573d7" - integrity sha512-FemEkf6a+EBKEPxlzeVgUaVSodU7G0Na89jqKjmWMlDB0tomoU8RlEMgUvXyqtrg8N4cwpLh8nyRnm1Nay1isA== - dependencies: - "@ethersproject/bytes" "^5.4.0" - "@ethersproject/hash" "^5.4.0" - "@ethersproject/logger" "^5.4.0" - "@ethersproject/properties" "^5.4.0" - "@ethersproject/strings" "^5.4.0" - -"@jest/console@^24.7.1", "@jest/console@^24.9.0": - version "24.9.0" - resolved "https://registry.yarnpkg.com/@jest/console/-/console-24.9.0.tgz#79b1bc06fb74a8cfb01cbdedf945584b1b9707f0" - integrity sha512-Zuj6b8TnKXi3q4ymac8EQfc3ea/uhLeCGThFqXeC8H9/raaH8ARPUTdId+XyGd03Z4In0/VjD2OYFcBF09fNLQ== - dependencies: - "@jest/source-map" "^24.9.0" - chalk "^2.0.1" - slash "^2.0.0" - -"@jest/core@^24.9.0": - version "24.9.0" - resolved "https://registry.yarnpkg.com/@jest/core/-/core-24.9.0.tgz#2ceccd0b93181f9c4850e74f2a9ad43d351369c4" - integrity sha512-Fogg3s4wlAr1VX7q+rhV9RVnUv5tD7VuWfYy1+whMiWUrvl7U3QJSJyWcDio9Lq2prqYsZaeTv2Rz24pWGkJ2A== - dependencies: - "@jest/console" "^24.7.1" - "@jest/reporters" "^24.9.0" - "@jest/test-result" "^24.9.0" - "@jest/transform" "^24.9.0" - "@jest/types" "^24.9.0" - ansi-escapes "^3.0.0" - chalk "^2.0.1" - exit "^0.1.2" - graceful-fs "^4.1.15" - jest-changed-files "^24.9.0" - jest-config "^24.9.0" - jest-haste-map "^24.9.0" - jest-message-util "^24.9.0" - jest-regex-util "^24.3.0" - jest-resolve "^24.9.0" - jest-resolve-dependencies "^24.9.0" - jest-runner "^24.9.0" - jest-runtime "^24.9.0" - jest-snapshot "^24.9.0" - jest-util "^24.9.0" - jest-validate "^24.9.0" - jest-watcher "^24.9.0" - micromatch "^3.1.10" - p-each-series "^1.0.0" - realpath-native "^1.1.0" - rimraf "^2.5.4" - slash "^2.0.0" - strip-ansi "^5.0.0" - -"@jest/environment@^24.9.0": - version "24.9.0" - resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-24.9.0.tgz#21e3afa2d65c0586cbd6cbefe208bafade44ab18" - integrity sha512-5A1QluTPhvdIPFYnO3sZC3smkNeXPVELz7ikPbhUj0bQjB07EoE9qtLrem14ZUYWdVayYbsjVwIiL4WBIMV4aQ== - dependencies: - "@jest/fake-timers" "^24.9.0" - "@jest/transform" "^24.9.0" - "@jest/types" "^24.9.0" - jest-mock "^24.9.0" - -"@jest/fake-timers@^24.9.0": - version "24.9.0" - resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-24.9.0.tgz#ba3e6bf0eecd09a636049896434d306636540c93" - integrity sha512-eWQcNa2YSwzXWIMC5KufBh3oWRIijrQFROsIqt6v/NS9Io/gknw1jsAC9c+ih/RQX4A3O7SeWAhQeN0goKhT9A== - dependencies: - "@jest/types" "^24.9.0" - jest-message-util "^24.9.0" - jest-mock "^24.9.0" - -"@jest/reporters@^24.9.0": - version "24.9.0" - resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-24.9.0.tgz#86660eff8e2b9661d042a8e98a028b8d631a5b43" - integrity sha512-mu4X0yjaHrffOsWmVLzitKmmmWSQ3GGuefgNscUSWNiUNcEOSEQk9k3pERKEQVBb0Cnn88+UESIsZEMH3o88Gw== - dependencies: - "@jest/environment" "^24.9.0" - "@jest/test-result" "^24.9.0" - "@jest/transform" "^24.9.0" - "@jest/types" "^24.9.0" - chalk "^2.0.1" - exit "^0.1.2" - glob "^7.1.2" - istanbul-lib-coverage "^2.0.2" - istanbul-lib-instrument "^3.0.1" - istanbul-lib-report "^2.0.4" - istanbul-lib-source-maps "^3.0.1" - istanbul-reports "^2.2.6" - jest-haste-map "^24.9.0" - jest-resolve "^24.9.0" - jest-runtime "^24.9.0" - jest-util "^24.9.0" - jest-worker "^24.6.0" - node-notifier "^5.4.2" - slash "^2.0.0" - source-map "^0.6.0" - string-length "^2.0.0" - -"@jest/source-map@^24.3.0", "@jest/source-map@^24.9.0": - version "24.9.0" - resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-24.9.0.tgz#0e263a94430be4b41da683ccc1e6bffe2a191714" - integrity sha512-/Xw7xGlsZb4MJzNDgB7PW5crou5JqWiBQaz6xyPd3ArOg2nfn/PunV8+olXbbEZzNl591o5rWKE9BRDaFAuIBg== - dependencies: - callsites "^3.0.0" - graceful-fs "^4.1.15" - source-map "^0.6.0" - -"@jest/test-result@^24.9.0": - version "24.9.0" - resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-24.9.0.tgz#11796e8aa9dbf88ea025757b3152595ad06ba0ca" - integrity sha512-XEFrHbBonBJ8dGp2JmF8kP/nQI/ImPpygKHwQ/SY+es59Z3L5PI4Qb9TQQMAEeYsThG1xF0k6tmG0tIKATNiiA== - dependencies: - "@jest/console" "^24.9.0" - "@jest/types" "^24.9.0" - "@types/istanbul-lib-coverage" "^2.0.0" - -"@jest/test-sequencer@^24.9.0": - version "24.9.0" - resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-24.9.0.tgz#f8f334f35b625a4f2f355f2fe7e6036dad2e6b31" - integrity sha512-6qqsU4o0kW1dvA95qfNog8v8gkRN9ph6Lz7r96IvZpHdNipP2cBcb07J1Z45mz/VIS01OHJ3pY8T5fUY38tg4A== - dependencies: - "@jest/test-result" "^24.9.0" - jest-haste-map "^24.9.0" - jest-runner "^24.9.0" - jest-runtime "^24.9.0" - -"@jest/transform@^24.9.0": - version "24.9.0" - resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-24.9.0.tgz#4ae2768b296553fadab09e9ec119543c90b16c56" - integrity sha512-TcQUmyNRxV94S0QpMOnZl0++6RMiqpbH/ZMccFB/amku6Uwvyb1cjYX7xkp5nGNkbX4QPH/FcB6q1HBTHynLmQ== - dependencies: - "@babel/core" "^7.1.0" - "@jest/types" "^24.9.0" - babel-plugin-istanbul "^5.1.0" - chalk "^2.0.1" - convert-source-map "^1.4.0" - fast-json-stable-stringify "^2.0.0" - graceful-fs "^4.1.15" - jest-haste-map "^24.9.0" - jest-regex-util "^24.9.0" - jest-util "^24.9.0" - micromatch "^3.1.10" - pirates "^4.0.1" - realpath-native "^1.1.0" - slash "^2.0.0" - source-map "^0.6.1" - write-file-atomic "2.4.1" - -"@jest/types@^24.9.0": - version "24.9.0" - resolved "https://registry.yarnpkg.com/@jest/types/-/types-24.9.0.tgz#63cb26cb7500d069e5a389441a7c6ab5e909fc59" - integrity sha512-XKK7ze1apu5JWQ5eZjHITP66AX+QsLlbaJRBGYr8pNzwcAE2JVkwnf0yqjHTsDRcjR0mujy/NmZMXw5kl+kGBw== - dependencies: - "@types/istanbul-lib-coverage" "^2.0.0" - "@types/istanbul-reports" "^1.1.1" - "@types/yargs" "^13.0.0" - -"@jest/types@^25.3.0": - version "25.3.0" - resolved "https://registry.yarnpkg.com/@jest/types/-/types-25.3.0.tgz#88f94b277a1d028fd7117bc1f74451e0fc2131e7" - integrity sha512-UkaDNewdqXAmCDbN2GlUM6amDKS78eCqiw/UmF5nE0mmLTd6moJkiZJML/X52Ke3LH7Swhw883IRXq8o9nWjVw== - dependencies: - "@types/istanbul-lib-coverage" "^2.0.0" - "@types/istanbul-reports" "^1.1.1" - "@types/yargs" "^15.0.0" - chalk "^3.0.0" - -"@ledgerhq/devices@^4.78.0": - version "4.78.0" - resolved "https://registry.yarnpkg.com/@ledgerhq/devices/-/devices-4.78.0.tgz#149b572f0616096e2bd5eb14ce14d0061c432be6" - integrity sha512-tWKS5WM/UU82czihnVjRwz9SXNTQzWjGJ/7+j/xZ70O86nlnGJ1aaFbs5/WTzfrVKpOKgj1ZoZkAswX67i/JTw== - dependencies: - "@ledgerhq/errors" "^4.78.0" - "@ledgerhq/logs" "^4.72.0" - rxjs "^6.5.3" - -"@ledgerhq/errors@^4.78.0": - version "4.78.0" - resolved "https://registry.yarnpkg.com/@ledgerhq/errors/-/errors-4.78.0.tgz#23daf3af54d03b1bda3e616002b555da1bdb705a" - integrity sha512-FX6zHZeiNtegBvXabK6M5dJ+8OV8kQGGaGtuXDeK/Ss5EmG4Ltxc6Lnhe8hiHpm9pCHtktOsnUVL7IFBdHhYUg== - -"@ledgerhq/hw-app-eth@^4.3.0": - version "4.78.0" - resolved "https://registry.yarnpkg.com/@ledgerhq/hw-app-eth/-/hw-app-eth-4.78.0.tgz#fbd7ffe7f371d0c32a53f38c5149ab8d13514297" - integrity sha512-m4s4Zhy4lwYJjZB3xPeGV/8mxQcnoui+Eu1KDEl6atsquZHUpbtern/0hZl88+OlFUz0XrX34W3I9cqj61Y6KA== - dependencies: - "@ledgerhq/errors" "^4.78.0" - "@ledgerhq/hw-transport" "^4.78.0" - -"@ledgerhq/hw-transport-node-hid-noevents@^4.78.0": - version "4.78.0" - resolved "https://registry.yarnpkg.com/@ledgerhq/hw-transport-node-hid-noevents/-/hw-transport-node-hid-noevents-4.78.0.tgz#6f0dbe1bbfad6516b42ad2d6b6b34a8b07e4cd46" - integrity sha512-CJPVR4wksq+apiXH2GnsttguBxmj9zdM2HjqZ3dHZN8SFW/9Xj3k+baS+pYoUISkECVxDrdfaW3Bd5dWv+jPUg== - dependencies: - "@ledgerhq/devices" "^4.78.0" - "@ledgerhq/errors" "^4.78.0" - "@ledgerhq/hw-transport" "^4.78.0" - "@ledgerhq/logs" "^4.72.0" - node-hid "^0.7.9" - -"@ledgerhq/hw-transport-node-hid@^4.3.0": - version "4.78.0" - resolved "https://registry.yarnpkg.com/@ledgerhq/hw-transport-node-hid/-/hw-transport-node-hid-4.78.0.tgz#abd99e0f918b810a61c035e5ab8c2bd8807aff55" - integrity sha512-OMrY2ecfQ1XjMAuuHqu3n3agMPR06HN1s0ENrKc+Twbb5A17jujpv07WzjxfTN2V1G7vgeZpRqrg2ulhowWbdg== - dependencies: - "@ledgerhq/devices" "^4.78.0" - "@ledgerhq/errors" "^4.78.0" - "@ledgerhq/hw-transport" "^4.78.0" - "@ledgerhq/hw-transport-node-hid-noevents" "^4.78.0" - "@ledgerhq/logs" "^4.72.0" - lodash "^4.17.15" - node-hid "^0.7.9" - usb "^1.6.0" - -"@ledgerhq/hw-transport-u2f@4.24.0": - version "4.24.0" - resolved "https://registry.yarnpkg.com/@ledgerhq/hw-transport-u2f/-/hw-transport-u2f-4.24.0.tgz#d67cfc4abf6d9a900ed45f2e2df7fe06dfdff5c7" - integrity sha512-/gFjhkM0sJfZ7iUf8HoIkGufAWgPacrbb1LW0TvWnZwvsATVJ1BZJBtrr90Wo401PKsjVwYtFt3Ce4gOAUv9jQ== - dependencies: - "@ledgerhq/hw-transport" "^4.24.0" - u2f-api "0.2.7" - -"@ledgerhq/hw-transport@^4.24.0", "@ledgerhq/hw-transport@^4.78.0": - version "4.78.0" - resolved "https://registry.yarnpkg.com/@ledgerhq/hw-transport/-/hw-transport-4.78.0.tgz#714786658e1f2fbc0569e06e2abf8d15d310d931" - integrity sha512-xQu16OMPQjFYLjqCysij+8sXtdWv2YLxPrB6FoLvEWGTlQ7yL1nUBRQyzyQtWIYqZd4THQowQmzm1VjxuN6SZw== - dependencies: - "@ledgerhq/devices" "^4.78.0" - "@ledgerhq/errors" "^4.78.0" - events "^3.0.0" - -"@ledgerhq/logs@^4.72.0": - version "4.72.0" - resolved "https://registry.yarnpkg.com/@ledgerhq/logs/-/logs-4.72.0.tgz#43df23af013ad1135407e5cf33ca6e4c4c7708d5" - integrity sha512-o+TYF8vBcyySRsb2kqBDv/KMeme8a2nwWoG+lAWzbDmWfb2/MrVWYCVYDYvjXdSoI/Cujqy1i0gIDrkdxa9chA== - -"@nodelib/fs.scandir@2.1.3": - version "2.1.3" - resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.3.tgz#3a582bdb53804c6ba6d146579c46e52130cf4a3b" - integrity sha512-eGmwYQn3gxo4r7jdQnkrrN6bY478C3P+a/y72IJukF8LjB6ZHeB3c+Ehacj3sYeSmUXGlnA67/PmbM9CVwL7Dw== - dependencies: - "@nodelib/fs.stat" "2.0.3" - run-parallel "^1.1.9" - -"@nodelib/fs.stat@2.0.3", "@nodelib/fs.stat@^2.0.2": - version "2.0.3" - resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.3.tgz#34dc5f4cabbc720f4e60f75a747e7ecd6c175bd3" - integrity sha512-bQBFruR2TAwoevBEd/NWMoAAtNGzTRgdrqnYCc7dhzfoNvqPzLyqlEQnzZ3kVnNrSp25iyxE00/3h2fqGAGArA== - -"@nodelib/fs.walk@^1.2.3": - version "1.2.4" - resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.4.tgz#011b9202a70a6366e436ca5c065844528ab04976" - integrity sha512-1V9XOY4rDW0rehzbrcqAmHnz8e7SKvX27gh8Gt2WgB0+pdzdiLV83p72kZPU+jvMbS1qU5mauP2iOvO8rhmurQ== - dependencies: - "@nodelib/fs.scandir" "2.1.3" - fastq "^1.6.0" - -"@resolver-engine/core@^0.2.1": - version "0.2.1" - resolved "https://registry.yarnpkg.com/@resolver-engine/core/-/core-0.2.1.tgz#0d71803f6d3b8cb2e9ed481a1bf0ca5f5256d0c0" - integrity sha512-nsLQHmPJ77QuifqsIvqjaF5B9aHnDzJjp73Q1z6apY3e9nqYrx4Dtowhpsf7Jwftg/XzVDEMQC+OzUBNTS+S1A== - dependencies: - debug "^3.1.0" - request "^2.85.0" - -"@resolver-engine/fs@^0.2.1": - version "0.2.1" - resolved "https://registry.yarnpkg.com/@resolver-engine/fs/-/fs-0.2.1.tgz#f98a308d77568cc02651d03636f46536b941b241" - integrity sha512-7kJInM1Qo2LJcKyDhuYzh9ZWd+mal/fynfL9BNjWOiTcOpX+jNfqb/UmGUqros5pceBITlWGqS4lU709yHFUbg== - dependencies: - "@resolver-engine/core" "^0.2.1" - debug "^3.1.0" - -"@resolver-engine/imports-fs@^0.2.2": - version "0.2.2" - resolved "https://registry.yarnpkg.com/@resolver-engine/imports-fs/-/imports-fs-0.2.2.tgz#5a81ef3285dbf0411ab3b15205080a1ad7622d9e" - integrity sha512-gFCgMvCwyppjwq0UzIjde/WI+yDs3oatJhozG9xdjJdewwtd7LiF0T5i9lrHAUtqrQbqoFE4E+ZMRVHWpWHpKQ== - dependencies: - "@resolver-engine/fs" "^0.2.1" - "@resolver-engine/imports" "^0.2.2" - debug "^3.1.0" - -"@resolver-engine/imports@^0.2.2": - version "0.2.2" - resolved "https://registry.yarnpkg.com/@resolver-engine/imports/-/imports-0.2.2.tgz#d3de55a1bb5f3beb7703fdde743298f321175843" - integrity sha512-u5/HUkvo8q34AA+hnxxqqXGfby5swnH0Myw91o3Sm2TETJlNKXibFGSKBavAH+wvWdBi4Z5gS2Odu0PowgVOUg== - dependencies: - "@resolver-engine/core" "^0.2.1" - debug "^3.1.0" - hosted-git-info "^2.6.0" - -"@sindresorhus/is@^0.14.0": - version "0.14.0" - resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.14.0.tgz#9fb3a3cf3132328151f353de4632e01e52102bea" - integrity sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ== - -"@solidity-parser/parser@^0.6.0": - version "0.6.2" - resolved "https://registry.yarnpkg.com/@solidity-parser/parser/-/parser-0.6.2.tgz#49707fc4e06649d39d6b25bdab2e9093d372ce50" - integrity sha512-kUVUvrqttndeprLoXjI5arWHeiP3uh4XODAKbG+ZaWHCVQeelxCbnXBeWxZ2BPHdXgH0xR9dU1b916JhDhbgAA== - -"@szmarczak/http-timer@^1.1.2": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-1.1.2.tgz#b1665e2c461a2cd92f4c1bbf50d5454de0d4b421" - integrity sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA== - dependencies: - defer-to-connect "^1.0.1" - -"@types/babel__core@^7.1.0": - version "7.1.3" - resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.3.tgz#e441ea7df63cd080dfcd02ab199e6d16a735fc30" - integrity sha512-8fBo0UR2CcwWxeX7WIIgJ7lXjasFxoYgRnFHUj+hRvKkpiBJbxhdAPTCY6/ZKM0uxANFVzt4yObSLuTiTnazDA== - dependencies: - "@babel/parser" "^7.1.0" - "@babel/types" "^7.0.0" - "@types/babel__generator" "*" - "@types/babel__template" "*" - "@types/babel__traverse" "*" - -"@types/babel__generator@*": - version "7.6.1" - resolved "https://registry.yarnpkg.com/@types/babel__generator/-/babel__generator-7.6.1.tgz#4901767b397e8711aeb99df8d396d7ba7b7f0e04" - integrity sha512-bBKm+2VPJcMRVwNhxKu8W+5/zT7pwNEqeokFOmbvVSqGzFneNxYcEBro9Ac7/N9tlsaPYnZLK8J1LWKkMsLAew== - dependencies: - "@babel/types" "^7.0.0" - -"@types/babel__template@*": - version "7.0.2" - resolved "https://registry.yarnpkg.com/@types/babel__template/-/babel__template-7.0.2.tgz#4ff63d6b52eddac1de7b975a5223ed32ecea9307" - integrity sha512-/K6zCpeW7Imzgab2bLkLEbz0+1JlFSrUMdw7KoIIu+IUdu51GWaBZpd3y1VXGVXzynvGa4DaIaxNZHiON3GXUg== - dependencies: - "@babel/parser" "^7.1.0" - "@babel/types" "^7.0.0" - -"@types/babel__traverse@*", "@types/babel__traverse@^7.0.6": - version "7.0.8" - resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.0.8.tgz#479a4ee3e291a403a1096106013ec22cf9b64012" - integrity sha512-yGeB2dHEdvxjP0y4UbRtQaSkXJ9649fYCmIdRoul5kfAoGCwxuCbMhag0k3RPfnuh9kPGm8x89btcfDEXdVWGw== - dependencies: - "@babel/types" "^7.3.0" - -"@types/bignumber.js@^5.0.0": - version "5.0.0" - resolved "https://registry.yarnpkg.com/@types/bignumber.js/-/bignumber.js-5.0.0.tgz#d9f1a378509f3010a3255e9cc822ad0eeb4ab969" - integrity sha512-0DH7aPGCClywOFaxxjE6UwpN2kQYe9LwuDQMv+zYA97j5GkOMo8e66LYT+a8JYU7jfmUFRZLa9KycxHDsKXJCA== - dependencies: - bignumber.js "*" - -"@types/bn.js@^4.11.0", "@types/bn.js@^4.11.3", "@types/bn.js@^4.11.4": - version "4.11.5" - resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-4.11.5.tgz#40e36197433f78f807524ec623afcf0169ac81dc" - integrity sha512-AEAZcIZga0JgVMHNtl1CprA/hXX7/wPt79AgR4XqaDt7jyj3QWYw6LPoOiznPtugDmlubUnAahMs2PFxGcQrng== - dependencies: - "@types/node" "*" - -"@types/bn.js@^4.11.5": - version "4.11.6" - resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-4.11.6.tgz#c306c70d9358aaea33cd4eda092a742b9505967c" - integrity sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg== - dependencies: - "@types/node" "*" - -"@types/color-name@^1.1.1": - version "1.1.1" - resolved "https://registry.yarnpkg.com/@types/color-name/-/color-name-1.1.1.tgz#1c1261bbeaa10a8055bbc5d8ab84b7b2afc846a0" - integrity sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ== - -"@types/ethereum-protocol@*": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@types/ethereum-protocol/-/ethereum-protocol-1.0.0.tgz#416e3827d5fdfa4658b0045b35a008747871b271" - integrity sha512-3DiI3Zxf81CgX+VhxNNFJBv/sfr1BFBKQK2sQ85hU9FwWJJMWV5gRDV79OUNShiwj3tYYIezU94qpucsb3dThQ== - dependencies: - bignumber.js "7.2.1" - -"@types/hdkey@^0.7.0": - version "0.7.1" - resolved "https://registry.yarnpkg.com/@types/hdkey/-/hdkey-0.7.1.tgz#9bc63ebbe96b107b277b65ea7a95442a677d0d61" - integrity sha512-4Kkr06hq+R8a9EzVNqXGOY2x1xA7dhY6qlp6OvaZ+IJy1BCca1Cv126RD9X7CMJoXoLo8WvAizy8gQHpqW6K0Q== - dependencies: - "@types/node" "*" - -"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0": - version "2.0.1" - resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.1.tgz#42995b446db9a48a11a07ec083499a860e9138ff" - integrity sha512-hRJD2ahnnpLgsj6KWMYSrmXkM3rm2Dl1qkx6IOFD5FnuNPXJIG5L0dhgKXCYTRMGzU4n0wImQ/xfmRc4POUFlg== - -"@types/istanbul-lib-report@*": - version "1.1.1" - resolved "https://registry.yarnpkg.com/@types/istanbul-lib-report/-/istanbul-lib-report-1.1.1.tgz#e5471e7fa33c61358dd38426189c037a58433b8c" - integrity sha512-3BUTyMzbZa2DtDI2BkERNC6jJw2Mr2Y0oGI7mRxYNBPxppbtEK1F66u3bKwU2g+wxwWI7PAoRpJnOY1grJqzHg== - dependencies: - "@types/istanbul-lib-coverage" "*" - -"@types/istanbul-reports@^1.1.1": - version "1.1.1" - resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-1.1.1.tgz#7a8cbf6a406f36c8add871625b278eaf0b0d255a" - integrity sha512-UpYjBi8xefVChsCoBpKShdxTllC9pwISirfoZsUa2AAdQg/Jd2KQGtSbw+ya7GPo7x/wAPlH6JBhKhAsXUEZNA== - dependencies: - "@types/istanbul-lib-coverage" "*" - "@types/istanbul-lib-report" "*" - -"@types/jest@^24.0.15": - version "24.0.25" - resolved "https://registry.yarnpkg.com/@types/jest/-/jest-24.0.25.tgz#2aba377824ce040114aa906ad2cac2c85351360f" - integrity sha512-hnP1WpjN4KbGEK4dLayul6lgtys6FPz0UfxMeMQCv0M+sTnzN3ConfiO72jHgLxl119guHgI8gLqDOrRLsyp2g== - dependencies: - jest-diff "^24.3.0" - -"@types/minimatch@^3.0.3": - version "3.0.3" - resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d" - integrity sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA== - -"@types/node@*": - version "12.12.14" - resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.14.tgz#1c1d6e3c75dba466e0326948d56e8bd72a1903d2" - integrity sha512-u/SJDyXwuihpwjXy7hOOghagLEV1KdAST6syfnOk6QZAMzZuWZqXy5aYYZbh8Jdpd4escVFP0MvftHNDb9pruA== - -"@types/node@^10.12.18": - version "10.17.11" - resolved "https://registry.yarnpkg.com/@types/node/-/node-10.17.11.tgz#46ba035fb917b31c948280dbea22ab8838f386a4" - integrity sha512-dNd2pp8qTzzNLAs3O8nH3iU9DG9866KHq9L3ISPB7DOGERZN81nW/5/g/KzMJpCU8jrbCiMRBzV9/sCEdRosig== - -"@types/node@^10.3.2": - version "10.14.4" - resolved "https://registry.yarnpkg.com/@types/node/-/node-10.14.4.tgz#1c586b991457cbb58fef51bc4e0cfcfa347714b5" - integrity sha512-DT25xX/YgyPKiHFOpNuANIQIVvYEwCWXgK2jYYwqgaMrYE6+tq+DtmMwlD3drl6DJbUwtlIDnn0d7tIn/EbXBg== - -"@types/node@^12.12.6": - version "12.12.54" - resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.54.tgz#a4b58d8df3a4677b6c08bfbc94b7ad7a7a5f82d1" - integrity sha512-ge4xZ3vSBornVYlDnk7yZ0gK6ChHf/CHB7Gl1I0Jhah8DDnEQqBzgohYG4FX4p81TNirSETOiSyn+y1r9/IR6w== - -"@types/node@^12.6.1": - version "12.12.21" - resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.21.tgz#aa44a6363291c7037111c47e4661ad210aded23f" - integrity sha512-8sRGhbpU+ck1n0PGAUgVrWrWdjSW2aqNeyC15W88GRsMpSwzv6RJGlLhE7s2RhVSOdyDmxbqlWSeThq4/7xqlA== - -"@types/prop-types@*": - version "15.7.3" - resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.3.tgz#2ab0d5da2e5815f94b0b9d4b95d1e5f243ab2ca7" - integrity sha512-KfRL3PuHmqQLOG+2tGpRO26Ctg+Cq1E01D2DMriKEATHgWLfeNDmq9e29Q9WIky0dQ3NPkd1mzYH8Lm936Z9qw== - -"@types/react@*": - version "16.9.15" - resolved "https://registry.yarnpkg.com/@types/react/-/react-16.9.15.tgz#aeabb7a50f96c9e31a16079ada20ede9ed602977" - integrity sha512-WsmM1b6xQn1tG3X2Hx4F3bZwc2E82pJXt5OPs2YJgg71IzvUoKOSSSYOvLXYCg1ttipM+UuA4Lj3sfvqjVxyZw== - dependencies: - "@types/prop-types" "*" - csstype "^2.2.0" - -"@types/solidity-parser-antlr@^0.2.3": - version "0.2.3" - resolved "https://registry.yarnpkg.com/@types/solidity-parser-antlr/-/solidity-parser-antlr-0.2.3.tgz#bb2d9c6511bf483afe4fc3e2714da8a924e59e3f" - integrity sha512-FoSyZT+1TTaofbEtGW1oC9wHND1YshvVeHerME/Jh6gIdHbBAWFW8A97YYqO/dpHcFjIwEPEepX0Efl2ckJgwA== - -"@types/stack-utils@^1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-1.0.1.tgz#0a851d3bd96498fa25c33ab7278ed3bd65f06c3e" - integrity sha512-l42BggppR6zLmpfU6fq9HEa2oGPEI8yrSPL3GITjfRInppYFahObbIQOQK3UGxEnyQpltZLaPe75046NOZQikw== - -"@types/web3-provider-engine@^14.0.0": - version "14.0.0" - resolved "https://registry.yarnpkg.com/@types/web3-provider-engine/-/web3-provider-engine-14.0.0.tgz#43adc3b39dc9812b82aef8cd2d66577665ad59b0" - integrity sha512-yHr8mX2SoX3JNyfqdLXdO1UobsGhfiwSgtekbVxKLQrzD7vtpPkKbkIVsPFOhvekvNbPsCmDyeDCLkpeI9gSmA== - dependencies: - "@types/ethereum-protocol" "*" - -"@types/yargs-parser@*": - version "13.1.0" - resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-13.1.0.tgz#c563aa192f39350a1d18da36c5a8da382bbd8228" - integrity sha512-gCubfBUZ6KxzoibJ+SCUc/57Ms1jz5NjHe4+dI2krNmU5zCPAphyLJYyTOg06ueIyfj+SaCUqmzun7ImlxDcKg== - -"@types/yargs@^11.0.0": - version "11.1.3" - resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-11.1.3.tgz#33c8ebf05f78f1edeb249c1cde1a42ae57f5664e" - integrity sha512-moBUF6X8JsK5MbLZGP3vCfG/TVHZHsaePj3EimlLKp8+ESUjGjpXalxyn90a2L9fTM2ZGtW4swb6Am1DvVRNGA== - -"@types/yargs@^13.0.0": - version "13.0.4" - resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-13.0.4.tgz#53d231cebe1a540e7e13727fc1f0d13ad4a9ba3b" - integrity sha512-Ke1WmBbIkVM8bpvsNEcGgQM70XcEh/nbpxQhW7FhrsbCsXSY9BmLB1+LHtD7r9zrsOcFlLiF+a/UeJsdfw3C5A== - dependencies: - "@types/yargs-parser" "*" - -"@types/yargs@^15.0.0": - version "15.0.4" - resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-15.0.4.tgz#7e5d0f8ca25e9d5849f2ea443cf7c402decd8299" - integrity sha512-9T1auFmbPZoxHz0enUFlUuKRy3it01R+hlggyVUMtnCTQRunsQYifnSGb8hET4Xo8yiC0o0r1paW3ud5+rbURg== - dependencies: - "@types/yargs-parser" "*" - -"@web3-js/scrypt-shim@^0.1.0": - version "0.1.0" - resolved "https://registry.yarnpkg.com/@web3-js/scrypt-shim/-/scrypt-shim-0.1.0.tgz#0bf7529ab6788311d3e07586f7d89107c3bea2cc" - integrity sha512-ZtZeWCc/s0nMcdx/+rZwY1EcuRdemOK9ag21ty9UsHkFxsNb/AaoucUz0iPuyGe0Ku+PFuRmWZG7Z7462p9xPw== - dependencies: - scryptsy "^2.1.0" - semver "^6.3.0" - -"@web3-js/websocket@^1.0.29": - version "1.0.30" - resolved "https://registry.yarnpkg.com/@web3-js/websocket/-/websocket-1.0.30.tgz#9ea15b7b582cf3bf3e8bc1f4d3d54c0731a87f87" - integrity sha512-fDwrD47MiDrzcJdSeTLF75aCcxVVt8B1N74rA+vh2XCAvFy4tEWJjtnUtj2QG7/zlQ6g9cQ88bZFBxwd9/FmtA== - dependencies: - debug "^2.2.0" - es5-ext "^0.10.50" - nan "^2.14.0" - typedarray-to-buffer "^3.1.5" - yaeti "^0.0.6" - -"@webassemblyjs/ast@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.9.0.tgz#bd850604b4042459a5a41cd7d338cbed695ed964" - integrity sha512-C6wW5L+b7ogSDVqymbkkvuW9kruN//YisMED04xzeBBqjHa2FYnmvOlS6Xj68xWQRgWvI9cIglsjFowH/RJyEA== - dependencies: - "@webassemblyjs/helper-module-context" "1.9.0" - "@webassemblyjs/helper-wasm-bytecode" "1.9.0" - "@webassemblyjs/wast-parser" "1.9.0" - -"@webassemblyjs/floating-point-hex-parser@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.9.0.tgz#3c3d3b271bddfc84deb00f71344438311d52ffb4" - integrity sha512-TG5qcFsS8QB4g4MhrxK5TqfdNe7Ey/7YL/xN+36rRjl/BlGE/NcBvJcqsRgCP6Z92mRE+7N50pRIi8SmKUbcQA== - -"@webassemblyjs/helper-api-error@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.9.0.tgz#203f676e333b96c9da2eeab3ccef33c45928b6a2" - integrity sha512-NcMLjoFMXpsASZFxJ5h2HZRcEhDkvnNFOAKneP5RbKRzaWJN36NC4jqQHKwStIhGXu5mUWlUUk7ygdtrO8lbmw== - -"@webassemblyjs/helper-buffer@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.9.0.tgz#a1442d269c5feb23fcbc9ef759dac3547f29de00" - integrity sha512-qZol43oqhq6yBPx7YM3m9Bv7WMV9Eevj6kMi6InKOuZxhw+q9hOkvq5e/PpKSiLfyetpaBnogSbNCfBwyB00CA== - -"@webassemblyjs/helper-code-frame@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.9.0.tgz#647f8892cd2043a82ac0c8c5e75c36f1d9159f27" - integrity sha512-ERCYdJBkD9Vu4vtjUYe8LZruWuNIToYq/ME22igL+2vj2dQ2OOujIZr3MEFvfEaqKoVqpsFKAGsRdBSBjrIvZA== - dependencies: - "@webassemblyjs/wast-printer" "1.9.0" - -"@webassemblyjs/helper-fsm@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-fsm/-/helper-fsm-1.9.0.tgz#c05256b71244214671f4b08ec108ad63b70eddb8" - integrity sha512-OPRowhGbshCb5PxJ8LocpdX9Kl0uB4XsAjl6jH/dWKlk/mzsANvhwbiULsaiqT5GZGT9qinTICdj6PLuM5gslw== - -"@webassemblyjs/helper-module-context@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-module-context/-/helper-module-context-1.9.0.tgz#25d8884b76839871a08a6c6f806c3979ef712f07" - integrity sha512-MJCW8iGC08tMk2enck1aPW+BE5Cw8/7ph/VGZxwyvGbJwjktKkDK7vy7gAmMDx88D7mhDTCNKAW5tED+gZ0W8g== - dependencies: - "@webassemblyjs/ast" "1.9.0" - -"@webassemblyjs/helper-wasm-bytecode@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.9.0.tgz#4fed8beac9b8c14f8c58b70d124d549dd1fe5790" - integrity sha512-R7FStIzyNcd7xKxCZH5lE0Bqy+hGTwS3LJjuv1ZVxd9O7eHCedSdrId/hMOd20I+v8wDXEn+bjfKDLzTepoaUw== - -"@webassemblyjs/helper-wasm-section@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.9.0.tgz#5a4138d5a6292ba18b04c5ae49717e4167965346" - integrity sha512-XnMB8l3ek4tvrKUUku+IVaXNHz2YsJyOOmz+MMkZvh8h1uSJpSen6vYnw3IoQ7WwEuAhL8Efjms1ZWjqh2agvw== - dependencies: - "@webassemblyjs/ast" "1.9.0" - "@webassemblyjs/helper-buffer" "1.9.0" - "@webassemblyjs/helper-wasm-bytecode" "1.9.0" - "@webassemblyjs/wasm-gen" "1.9.0" - -"@webassemblyjs/ieee754@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.9.0.tgz#15c7a0fbaae83fb26143bbacf6d6df1702ad39e4" - integrity sha512-dcX8JuYU/gvymzIHc9DgxTzUUTLexWwt8uCTWP3otys596io0L5aW02Gb1RjYpx2+0Jus1h4ZFqjla7umFniTg== - dependencies: - "@xtuc/ieee754" "^1.2.0" - -"@webassemblyjs/leb128@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.9.0.tgz#f19ca0b76a6dc55623a09cffa769e838fa1e1c95" - integrity sha512-ENVzM5VwV1ojs9jam6vPys97B/S65YQtv/aanqnU7D8aSoHFX8GyhGg0CMfyKNIHBuAVjy3tlzd5QMMINa7wpw== - dependencies: - "@xtuc/long" "4.2.2" - -"@webassemblyjs/utf8@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.9.0.tgz#04d33b636f78e6a6813227e82402f7637b6229ab" - integrity sha512-GZbQlWtopBTP0u7cHrEx+73yZKrQoBMpwkGEIqlacljhXCkVM1kMQge/Mf+csMJAjEdSwhOyLAS0AoR3AG5P8w== - -"@webassemblyjs/wasm-edit@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.9.0.tgz#3fe6d79d3f0f922183aa86002c42dd256cfee9cf" - integrity sha512-FgHzBm80uwz5M8WKnMTn6j/sVbqilPdQXTWraSjBwFXSYGirpkSWE2R9Qvz9tNiTKQvoKILpCuTjBKzOIm0nxw== - dependencies: - "@webassemblyjs/ast" "1.9.0" - "@webassemblyjs/helper-buffer" "1.9.0" - "@webassemblyjs/helper-wasm-bytecode" "1.9.0" - "@webassemblyjs/helper-wasm-section" "1.9.0" - "@webassemblyjs/wasm-gen" "1.9.0" - "@webassemblyjs/wasm-opt" "1.9.0" - "@webassemblyjs/wasm-parser" "1.9.0" - "@webassemblyjs/wast-printer" "1.9.0" - -"@webassemblyjs/wasm-gen@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.9.0.tgz#50bc70ec68ded8e2763b01a1418bf43491a7a49c" - integrity sha512-cPE3o44YzOOHvlsb4+E9qSqjc9Qf9Na1OO/BHFy4OI91XDE14MjFN4lTMezzaIWdPqHnsTodGGNP+iRSYfGkjA== - dependencies: - "@webassemblyjs/ast" "1.9.0" - "@webassemblyjs/helper-wasm-bytecode" "1.9.0" - "@webassemblyjs/ieee754" "1.9.0" - "@webassemblyjs/leb128" "1.9.0" - "@webassemblyjs/utf8" "1.9.0" - -"@webassemblyjs/wasm-opt@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.9.0.tgz#2211181e5b31326443cc8112eb9f0b9028721a61" - integrity sha512-Qkjgm6Anhm+OMbIL0iokO7meajkzQD71ioelnfPEj6r4eOFuqm4YC3VBPqXjFyyNwowzbMD+hizmprP/Fwkl2A== - dependencies: - "@webassemblyjs/ast" "1.9.0" - "@webassemblyjs/helper-buffer" "1.9.0" - "@webassemblyjs/wasm-gen" "1.9.0" - "@webassemblyjs/wasm-parser" "1.9.0" - -"@webassemblyjs/wasm-parser@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.9.0.tgz#9d48e44826df4a6598294aa6c87469d642fff65e" - integrity sha512-9+wkMowR2AmdSWQzsPEjFU7njh8HTO5MqO8vjwEHuM+AMHioNqSBONRdr0NQQ3dVQrzp0s8lTcYqzUdb7YgELA== - dependencies: - "@webassemblyjs/ast" "1.9.0" - "@webassemblyjs/helper-api-error" "1.9.0" - "@webassemblyjs/helper-wasm-bytecode" "1.9.0" - "@webassemblyjs/ieee754" "1.9.0" - "@webassemblyjs/leb128" "1.9.0" - "@webassemblyjs/utf8" "1.9.0" - -"@webassemblyjs/wast-parser@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-parser/-/wast-parser-1.9.0.tgz#3031115d79ac5bd261556cecc3fa90a3ef451914" - integrity sha512-qsqSAP3QQ3LyZjNC/0jBJ/ToSxfYJ8kYyuiGvtn/8MK89VrNEfwj7BPQzJVHi0jGTRK2dGdJ5PRqhtjzoww+bw== - dependencies: - "@webassemblyjs/ast" "1.9.0" - "@webassemblyjs/floating-point-hex-parser" "1.9.0" - "@webassemblyjs/helper-api-error" "1.9.0" - "@webassemblyjs/helper-code-frame" "1.9.0" - "@webassemblyjs/helper-fsm" "1.9.0" - "@xtuc/long" "4.2.2" - -"@webassemblyjs/wast-printer@1.9.0": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.9.0.tgz#4935d54c85fef637b00ce9f52377451d00d47899" - integrity sha512-2J0nE95rHXHyQ24cWjMKJ1tqB/ds8z/cyeOZxJhcb+rW+SQASVjuznUSmdz5GpVJTzU8JkhYut0D3siFDD6wsA== - dependencies: - "@webassemblyjs/ast" "1.9.0" - "@webassemblyjs/wast-parser" "1.9.0" - "@xtuc/long" "4.2.2" - -"@xtuc/ieee754@^1.2.0": - version "1.2.0" - resolved "https://registry.yarnpkg.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790" - integrity sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA== - -"@xtuc/long@4.2.2": - version "4.2.2" - resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d" - integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ== - -abab@^2.0.0: - version "2.0.3" - resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.3.tgz#623e2075e02eb2d3f2475e49f99c91846467907a" - integrity sha512-tsFzPpcttalNjFBCFMqsKYQcWxxen1pgJR56by//QwvJc4/OUS3kPOOttx2tSIfjsylB0pYu7f5D3K1RCxUnUg== - -abbrev@1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" - integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== - -abbrev@1.0.x: - version "1.0.9" - resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.0.9.tgz#91b4792588a7738c25f35dd6f63752a2f8776135" - integrity sha1-kbR5JYinc4wl813W9jdSovh3YTU= - -abortcontroller-polyfill@^1.1.9: - version "1.4.0" - resolved "https://registry.yarnpkg.com/abortcontroller-polyfill/-/abortcontroller-polyfill-1.4.0.tgz#0d5eb58e522a461774af8086414f68e1dda7a6c4" - integrity sha512-3ZFfCRfDzx3GFjO6RAkYx81lPGpUS20ISxux9gLxuKnqafNcFQo59+IoZqpO2WvQlyc287B62HDnDdNYRmlvWA== - -abstract-leveldown@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/abstract-leveldown/-/abstract-leveldown-3.0.0.tgz#5cb89f958a44f526779d740d1440e743e0c30a57" - integrity sha512-KUWx9UWGQD12zsmLNj64/pndaz4iJh/Pj7nopgkfDG6RlCcbMZvT6+9l7dchK4idog2Is8VdC/PvNbFuFmalIQ== - dependencies: - xtend "~4.0.0" - -abstract-leveldown@^2.4.1, abstract-leveldown@~2.7.1: - version "2.7.2" - resolved "https://registry.yarnpkg.com/abstract-leveldown/-/abstract-leveldown-2.7.2.tgz#87a44d7ebebc341d59665204834c8b7e0932cc93" - integrity sha512-+OVvxH2rHVEhWLdbudP6p0+dNMXu8JA1CbhP19T8paTYAcX7oJ4OVjT+ZUVpv7mITxXHqDMej+GdqXBmXkw09w== - dependencies: - xtend "~4.0.0" - -abstract-leveldown@^5.0.0, abstract-leveldown@~5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/abstract-leveldown/-/abstract-leveldown-5.0.0.tgz#f7128e1f86ccabf7d2893077ce5d06d798e386c6" - integrity sha512-5mU5P1gXtsMIXg65/rsYGsi93+MlogXZ9FA8JnwKurHQg64bfXwGYVdVdijNTVNOlAsuIiOwHdvFFD5JqCJQ7A== - dependencies: - xtend "~4.0.0" - -abstract-leveldown@~2.6.0: - version "2.6.3" - resolved "https://registry.yarnpkg.com/abstract-leveldown/-/abstract-leveldown-2.6.3.tgz#1c5e8c6a5ef965ae8c35dfb3a8770c476b82c4b8" - integrity sha512-2++wDf/DYqkPR3o5tbfdhF96EfMApo1GpPfzOsR/ZYXdkSmELlvOOEAl9iKkRsktMPHdGjO4rtkBpf2I7TiTeA== - dependencies: - xtend "~4.0.0" - -accepts@~1.3.7: - version "1.3.7" - resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.7.tgz#531bc726517a3b2b41f850021c6cc15eaab507cd" - integrity sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA== - dependencies: - mime-types "~2.1.24" - negotiator "0.6.2" - -acorn-globals@^4.1.0: - version "4.3.4" - resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-4.3.4.tgz#9fa1926addc11c97308c4e66d7add0d40c3272e7" - integrity sha512-clfQEh21R+D0leSbUdWf3OcfqyaCSAQ8Ryq00bofSekfr9W8u1jyYZo6ir0xu9Gtcf7BjcHJpnbZH7JOCpP60A== - dependencies: - acorn "^6.0.1" - acorn-walk "^6.0.1" - -acorn-walk@^6.0.1: - version "6.2.0" - resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-6.2.0.tgz#123cb8f3b84c2171f1f7fb252615b1c78a6b1a8c" - integrity sha512-7evsyfH1cLOCdAzZAd43Cic04yKydNx0cF+7tiA19p1XnLLPU4dpCQOqpjqwokFe//vS0QqfqqjCS2JkiIs0cA== - -acorn-walk@^7.1.1: - version "7.2.0" - resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-7.2.0.tgz#0de889a601203909b0fbe07b8938dc21d2e967bc" - integrity sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA== - -acorn@^5.5.3: - version "5.7.3" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.3.tgz#67aa231bf8812974b85235a96771eb6bd07ea279" - integrity sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw== - -acorn@^6.0.1: - version "6.4.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.0.tgz#b659d2ffbafa24baf5db1cdbb2c94a983ecd2784" - integrity sha512-gac8OEcQ2Li1dxIEWGZzsp2BitJxwkwcOm0zHAJLcPJaVvm58FRnk6RkuLRpU1EujipU2ZFODv2P9DLMfnV8mw== - -acorn@^6.4.1: - version "6.4.1" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.1.tgz#531e58ba3f51b9dacb9a6646ca4debf5b14ca474" - integrity sha512-ZVA9k326Nwrj3Cj9jlh3wGFutC2ZornPNARZwsNYqQYgN0EsV2d53w5RN/co65Ohn4sUAUtb1rSUAOD6XN9idA== - -acorn@^7.1.1: - version "7.4.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.0.tgz#e1ad486e6c54501634c6c397c5c121daa383607c" - integrity sha512-+G7P8jJmCHr+S+cLfQxygbWhXy+8YTVGzAkpEbcLo2mLoL7tij/VG41QSHACSf5QgYRhMZYHuNc6drJaO0Da+w== - -aes-js@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.0.0.tgz#e21df10ad6c2053295bcbb8dab40b09dbea87e4d" - integrity sha1-4h3xCtbCBTKVvLuNq0Cwnb6ofk0= - -aes-js@^3.1.1: - version "3.1.2" - resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.1.2.tgz#db9aabde85d5caabbfc0d4f2a4446960f627146a" - integrity sha512-e5pEa2kBnBOgR4Y/p20pskXI74UEz7de8ZGVo58asOtvSVG5YAbJeELPZxOmt+Bnz3rX753YKhfIn4X4l1PPRQ== - -ajv-errors@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/ajv-errors/-/ajv-errors-1.0.1.tgz#f35986aceb91afadec4102fbd85014950cefa64d" - integrity sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ== - -ajv-keywords@^3.1.0, ajv-keywords@^3.4.1: - version "3.4.1" - resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.4.1.tgz#ef916e271c64ac12171fd8384eaae6b2345854da" - integrity sha512-RO1ibKvd27e6FEShVFfPALuHI3WjSVNeK5FIsmme/LYRNxjKuNj+Dt7bucLa6NdSv3JcVTyMlm9kGR84z1XpaQ== - -ajv@^6.1.0, ajv@^6.10.2, ajv@^6.5.5: - version "6.10.2" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.10.2.tgz#d3cea04d6b017b2894ad69040fec8b623eb4bd52" - integrity sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw== - dependencies: - fast-deep-equal "^2.0.1" - fast-json-stable-stringify "^2.0.0" - json-schema-traverse "^0.4.1" - uri-js "^4.2.2" - -ajv@^6.12.3: - version "6.12.4" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.4.tgz#0614facc4522127fa713445c6bfd3ebd376e2234" - integrity sha512-eienB2c9qVQs2KWexhkrdMLVDoIQCz5KSeLxwg9Lzk4DOfBtIK9PQwwufcsn1jjGuf9WZmqPMbGxOzfcuphJCQ== - dependencies: - fast-deep-equal "^3.1.1" - fast-json-stable-stringify "^2.0.0" - json-schema-traverse "^0.4.1" - uri-js "^4.2.2" - -amdefine@>=0.0.4: - version "1.0.1" - resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" - integrity sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU= - -ansi-colors@^1.0.1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-1.1.0.tgz#6374b4dd5d4718ff3ce27a671a3b1cad077132a9" - integrity sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA== - dependencies: - ansi-wrap "^0.1.0" - -ansi-escapes@^3.0.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.2.0.tgz#8780b98ff9dbf5638152d1f1fe5c1d7b4442976b" - integrity sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ== - -ansi-gray@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/ansi-gray/-/ansi-gray-0.1.1.tgz#2962cf54ec9792c48510a3deb524436861ef7251" - integrity sha1-KWLPVOyXksSFEKPetSRDaGHvclE= - dependencies: - ansi-wrap "0.1.0" - -ansi-regex@^2.0.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" - integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8= - -ansi-regex@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" - integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg= - -ansi-regex@^4.0.0, ansi-regex@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997" - integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg== - -ansi-regex@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.0.tgz#388539f55179bf39339c81af30a654d69f87cb75" - integrity sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg== - -ansi-styles@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" - integrity sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4= - -ansi-styles@^3.2.0, ansi-styles@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" - integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== - dependencies: - color-convert "^1.9.0" - -ansi-styles@^4.0.0, ansi-styles@^4.1.0: - version "4.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.2.1.tgz#90ae75c424d008d2624c5bf29ead3177ebfcf359" - integrity sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA== - dependencies: - "@types/color-name" "^1.1.1" - color-convert "^2.0.1" - -ansi-wrap@0.1.0, ansi-wrap@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/ansi-wrap/-/ansi-wrap-0.1.0.tgz#a82250ddb0015e9a27ca82e82ea603bbfa45efaf" - integrity sha1-qCJQ3bABXponyoLoLqYDu/pF768= - -any-promise@1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f" - integrity sha1-q8av7tzqUugJzcA3au0845Y10X8= - -anymatch@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-2.0.0.tgz#bcb24b4f37934d9aa7ac17b4adaf89e7c76ef2eb" - integrity sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw== - dependencies: - micromatch "^3.1.4" - normalize-path "^2.1.1" - -anymatch@~3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.1.tgz#c55ecf02185e2469259399310c173ce31233b142" - integrity sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg== - dependencies: - normalize-path "^3.0.0" - picomatch "^2.0.4" - -append-buffer@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/append-buffer/-/append-buffer-1.0.2.tgz#d8220cf466081525efea50614f3de6514dfa58f1" - integrity sha1-2CIM9GYIFSXv6lBhTz3mUU36WPE= - dependencies: - buffer-equal "^1.0.0" - -aproba@^1.0.3, aproba@^1.1.1: - version "1.2.0" - resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" - integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw== - -archy@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/archy/-/archy-1.0.0.tgz#f9c8c13757cc1dd7bc379ac77b2c62a5c2868c40" - integrity sha1-+cjBN1fMHde8N5rHeyxipcKGjEA= - -are-we-there-yet@~1.1.2: - version "1.1.5" - resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz#4b35c2944f062a8bfcda66410760350fe9ddfc21" - integrity sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w== - dependencies: - delegates "^1.0.0" - readable-stream "^2.0.6" - -argparse@^1.0.7: - version "1.0.10" - resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" - integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== - dependencies: - sprintf-js "~1.0.2" - -arr-diff@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" - integrity sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA= - -arr-filter@^1.1.1: - version "1.1.2" - resolved "https://registry.yarnpkg.com/arr-filter/-/arr-filter-1.1.2.tgz#43fdddd091e8ef11aa4c45d9cdc18e2dff1711ee" - integrity sha1-Q/3d0JHo7xGqTEXZzcGOLf8XEe4= - dependencies: - make-iterator "^1.0.0" - -arr-flatten@^1.0.1, arr-flatten@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" - integrity sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg== - -arr-map@^2.0.0, arr-map@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/arr-map/-/arr-map-2.0.2.tgz#3a77345ffc1cf35e2a91825601f9e58f2e24cac4" - integrity sha1-Onc0X/wc814qkYJWAfnljy4kysQ= - dependencies: - make-iterator "^1.0.0" - -arr-union@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" - integrity sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ= - -array-each@^1.0.0, array-each@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/array-each/-/array-each-1.0.1.tgz#a794af0c05ab1752846ee753a1f211a05ba0c44f" - integrity sha1-p5SvDAWrF1KEbudTofIRoFugxE8= - -array-equal@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/array-equal/-/array-equal-1.0.0.tgz#8c2a5ef2472fd9ea742b04c77a75093ba2757c93" - integrity sha1-jCpe8kcv2ep0KwTHenUJO6J1fJM= - -array-flatten@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" - integrity sha1-ml9pkFGx5wczKPKgCJaLZOopVdI= - -array-initial@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/array-initial/-/array-initial-1.1.0.tgz#2fa74b26739371c3947bd7a7adc73be334b3d795" - integrity sha1-L6dLJnOTccOUe9enrcc74zSz15U= - dependencies: - array-slice "^1.0.0" - is-number "^4.0.0" - -array-last@^1.1.1: - version "1.3.0" - resolved "https://registry.yarnpkg.com/array-last/-/array-last-1.3.0.tgz#7aa77073fec565ddab2493f5f88185f404a9d336" - integrity sha512-eOCut5rXlI6aCOS7Z7kCplKRKyiFQ6dHFBem4PwlwKeNFk2/XxTrhRh5T9PyaEWGy/NHTZWbY+nsZlNFJu9rYg== - dependencies: - is-number "^4.0.0" - -array-slice@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/array-slice/-/array-slice-1.1.0.tgz#e368ea15f89bc7069f7ffb89aec3a6c7d4ac22d4" - integrity sha512-B1qMD3RBP7O8o0H2KbrXDyB0IccejMF15+87Lvlor12ONPRHP6gTjXMNkt/d3ZuOGbAe66hFmaCfECI24Ufp6w== - -array-sort@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/array-sort/-/array-sort-1.0.0.tgz#e4c05356453f56f53512a7d1d6123f2c54c0a88a" - integrity sha512-ihLeJkonmdiAsD7vpgN3CRcx2J2S0TiYW+IS/5zHBI7mKUq3ySvBdzzBfD236ubDBQFiiyG3SWCPc+msQ9KoYg== - dependencies: - default-compare "^1.0.0" - get-value "^2.0.6" - kind-of "^5.0.2" - -array-unique@^0.3.2: - version "0.3.2" - resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" - integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg= - -asn1.js@^4.0.0: - version "4.10.1" - resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-4.10.1.tgz#b9c2bf5805f1e64aadeed6df3a2bfafb5a73f5a0" - integrity sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw== - dependencies: - bn.js "^4.0.0" - inherits "^2.0.1" - minimalistic-assert "^1.0.0" - -asn1@~0.2.3: - version "0.2.4" - resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136" - integrity sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg== - dependencies: - safer-buffer "~2.1.0" - -assert-plus@1.0.0, assert-plus@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" - integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU= - -assert@^1.1.1: - version "1.5.0" - resolved "https://registry.yarnpkg.com/assert/-/assert-1.5.0.tgz#55c109aaf6e0aefdb3dc4b71240c70bf574b18eb" - integrity sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA== - dependencies: - object-assign "^4.1.1" - util "0.10.3" - -assertion-error@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.1.0.tgz#e60b6b0e8f301bd97e5375215bda406c85118c0b" - integrity sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw== - -assign-symbols@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" - integrity sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c= - -astral-regex@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9" - integrity sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg== - -async-done@^1.2.0, async-done@^1.2.2: - version "1.3.2" - resolved "https://registry.yarnpkg.com/async-done/-/async-done-1.3.2.tgz#5e15aa729962a4b07414f528a88cdf18e0b290a2" - integrity sha512-uYkTP8dw2og1tu1nmza1n1CMW0qb8gWWlwqMmLb7MhBVs4BXrFziT6HXUd+/RlRA/i4H9AkofYloUbs1fwMqlw== - dependencies: - end-of-stream "^1.1.0" - once "^1.3.2" - process-nextick-args "^2.0.0" - stream-exhaust "^1.0.1" - -async-each@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.3.tgz#b727dbf87d7651602f06f4d4ac387f47d91b0cbf" - integrity sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ== - -async-eventemitter@^0.2.2: - version "0.2.4" - resolved "https://registry.yarnpkg.com/async-eventemitter/-/async-eventemitter-0.2.4.tgz#f5e7c8ca7d3e46aab9ec40a292baf686a0bafaca" - integrity sha512-pd20BwL7Yt1zwDFy+8MX8F1+WCT8aQeKj0kQnTrH9WaeRETlRamVhD0JtRPmrV4GfOJ2F9CvdQkZeZhnh2TuHw== - dependencies: - async "^2.4.0" - -async-limiter@~1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.1.tgz#dd379e94f0db8310b08291f9d64c3209766617fd" - integrity sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ== - -async-settle@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/async-settle/-/async-settle-1.0.0.tgz#1d0a914bb02575bec8a8f3a74e5080f72b2c0c6b" - integrity sha1-HQqRS7Aldb7IqPOnTlCA9yssDGs= - dependencies: - async-done "^1.2.2" - -async@1.x, async@^1.4.2: - version "1.5.2" - resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" - integrity sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo= - -async@2.6.2: - version "2.6.2" - resolved "https://registry.yarnpkg.com/async/-/async-2.6.2.tgz#18330ea7e6e313887f5d2f2a904bac6fe4dd5381" - integrity sha512-H1qVYh1MYhEEFLsP97cVKqCGo7KfCyTt6uEWqsTBr9SO84oK9Uwbyd/yCW+6rKJLHksBNUVWZDAjfS+Ccx0Bbg== - dependencies: - lodash "^4.17.11" - -async@^2.0.1, async@^2.1.2, async@^2.4.0, async@^2.5.0, async@^2.6.1: - version "2.6.3" - resolved "https://registry.yarnpkg.com/async/-/async-2.6.3.tgz#d72625e2344a3656e3a3ad4fa749fa83299d82ff" - integrity sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg== - dependencies: - lodash "^4.17.14" - -asynckit@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" - integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= - -atob@^2.1.1: - version "2.1.2" - resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" - integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== - -await-semaphore@^0.1.3: - version "0.1.3" - resolved "https://registry.yarnpkg.com/await-semaphore/-/await-semaphore-0.1.3.tgz#2b88018cc8c28e06167ae1cdff02504f1f9688d3" - integrity sha512-d1W2aNSYcz/sxYO4pMGX9vq65qOTu0P800epMud+6cYYX0QcT7zyqcxec3VWzpgvdXo57UWmVbZpLMjX2m1I7Q== - -aws-sign2@~0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" - integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg= - -aws4@^1.8.0: - version "1.9.0" - resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.9.0.tgz#24390e6ad61386b0a747265754d2a17219de862c" - integrity sha512-Uvq6hVe90D0B2WEnUqtdgY1bATGz3mw33nH9Y+dmA+w5DHvUmBgkr5rM/KCHpCsiFNRUfokW/szpPPgMK2hm4A== - -babel-code-frame@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b" - integrity sha1-Y/1D99weO7fONZR9uP42mj9Yx0s= - dependencies: - chalk "^1.1.3" - esutils "^2.0.2" - js-tokens "^3.0.2" - -babel-core@^6.0.14, babel-core@^6.26.0: - version "6.26.3" - resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.26.3.tgz#b2e2f09e342d0f0c88e2f02e067794125e75c207" - integrity sha512-6jyFLuDmeidKmUEb3NM+/yawG0M2bDZ9Z1qbZP59cyHLz8kYGKYwpJP0UwUKKUiTRNvxfLesJnTedqczP7cTDA== - dependencies: - babel-code-frame "^6.26.0" - babel-generator "^6.26.0" - babel-helpers "^6.24.1" - babel-messages "^6.23.0" - babel-register "^6.26.0" - babel-runtime "^6.26.0" - babel-template "^6.26.0" - babel-traverse "^6.26.0" - babel-types "^6.26.0" - babylon "^6.18.0" - convert-source-map "^1.5.1" - debug "^2.6.9" - json5 "^0.5.1" - lodash "^4.17.4" - minimatch "^3.0.4" - path-is-absolute "^1.0.1" - private "^0.1.8" - slash "^1.0.0" - source-map "^0.5.7" - -babel-generator@^6.26.0: - version "6.26.1" - resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.26.1.tgz#1844408d3b8f0d35a404ea7ac180f087a601bd90" - integrity sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA== - dependencies: - babel-messages "^6.23.0" - babel-runtime "^6.26.0" - babel-types "^6.26.0" - detect-indent "^4.0.0" - jsesc "^1.3.0" - lodash "^4.17.4" - source-map "^0.5.7" - trim-right "^1.0.1" - -babel-helper-builder-binary-assignment-operator-visitor@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz#cce4517ada356f4220bcae8a02c2b346f9a56664" - integrity sha1-zORReto1b0IgvK6KAsKzRvmlZmQ= - dependencies: - babel-helper-explode-assignable-expression "^6.24.1" - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-helper-call-delegate@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz#ece6aacddc76e41c3461f88bfc575bd0daa2df8d" - integrity sha1-7Oaqzdx25Bw0YfiL/Fdb0Nqi340= - dependencies: - babel-helper-hoist-variables "^6.24.1" - babel-runtime "^6.22.0" - babel-traverse "^6.24.1" - babel-types "^6.24.1" - -babel-helper-define-map@^6.24.1: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz#a5f56dab41a25f97ecb498c7ebaca9819f95be5f" - integrity sha1-pfVtq0GiX5fstJjH66ypgZ+Vvl8= - dependencies: - babel-helper-function-name "^6.24.1" - babel-runtime "^6.26.0" - babel-types "^6.26.0" - lodash "^4.17.4" - -babel-helper-explode-assignable-expression@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz#f25b82cf7dc10433c55f70592d5746400ac22caa" - integrity sha1-8luCz33BBDPFX3BZLVdGQArCLKo= - dependencies: - babel-runtime "^6.22.0" - babel-traverse "^6.24.1" - babel-types "^6.24.1" - -babel-helper-function-name@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz#d3475b8c03ed98242a25b48351ab18399d3580a9" - integrity sha1-00dbjAPtmCQqJbSDUasYOZ01gKk= - dependencies: - babel-helper-get-function-arity "^6.24.1" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - babel-traverse "^6.24.1" - babel-types "^6.24.1" - -babel-helper-get-function-arity@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz#8f7782aa93407c41d3aa50908f89b031b1b6853d" - integrity sha1-j3eCqpNAfEHTqlCQj4mwMbG2hT0= - dependencies: - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-helper-hoist-variables@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz#1ecb27689c9d25513eadbc9914a73f5408be7a76" - integrity sha1-HssnaJydJVE+rbyZFKc/VAi+enY= - dependencies: - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-helper-optimise-call-expression@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz#f7a13427ba9f73f8f4fa993c54a97882d1244257" - integrity sha1-96E0J7qfc/j0+pk8VKl4gtEkQlc= - dependencies: - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-helper-regex@^6.24.1: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz#325c59f902f82f24b74faceed0363954f6495e72" - integrity sha1-MlxZ+QL4LyS3T6zu0DY5VPZJXnI= - dependencies: - babel-runtime "^6.26.0" - babel-types "^6.26.0" - lodash "^4.17.4" - -babel-helper-remap-async-to-generator@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz#5ec581827ad723fecdd381f1c928390676e4551b" - integrity sha1-XsWBgnrXI/7N04HxySg5BnbkVRs= - dependencies: - babel-helper-function-name "^6.24.1" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - babel-traverse "^6.24.1" - babel-types "^6.24.1" - -babel-helper-replace-supers@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz#bf6dbfe43938d17369a213ca8a8bf74b6a90ab1a" - integrity sha1-v22/5Dk40XNpohPKiov3S2qQqxo= - dependencies: - babel-helper-optimise-call-expression "^6.24.1" - babel-messages "^6.23.0" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - babel-traverse "^6.24.1" - babel-types "^6.24.1" - -babel-helpers@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helpers/-/babel-helpers-6.24.1.tgz#3471de9caec388e5c850e597e58a26ddf37602b2" - integrity sha1-NHHenK7DiOXIUOWX5Yom3fN2ArI= - dependencies: - babel-runtime "^6.22.0" - babel-template "^6.24.1" - -babel-jest@^24.9.0: - version "24.9.0" - resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-24.9.0.tgz#3fc327cb8467b89d14d7bc70e315104a783ccd54" - integrity sha512-ntuddfyiN+EhMw58PTNL1ph4C9rECiQXjI4nMMBKBaNjXvqLdkXpPRcMSr4iyBrJg/+wz9brFUD6RhOAT6r4Iw== - dependencies: - "@jest/transform" "^24.9.0" - "@jest/types" "^24.9.0" - "@types/babel__core" "^7.1.0" - babel-plugin-istanbul "^5.1.0" - babel-preset-jest "^24.9.0" - chalk "^2.4.2" - slash "^2.0.0" - -babel-messages@^6.23.0: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel-messages/-/babel-messages-6.23.0.tgz#f3cdf4703858035b2a2951c6ec5edf6c62f2630e" - integrity sha1-8830cDhYA1sqKVHG7F7fbGLyYw4= - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-check-es2015-constants@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz#35157b101426fd2ffd3da3f75c7d1e91835bbf8a" - integrity sha1-NRV7EBQm/S/9PaP3XH0ekYNbv4o= - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-istanbul@^5.1.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-5.2.0.tgz#df4ade83d897a92df069c4d9a25cf2671293c854" - integrity sha512-5LphC0USA8t4i1zCtjbbNb6jJj/9+X6P37Qfirc/70EQ34xKlMW+a1RHGwxGI+SwWpNwZ27HqvzAobeqaXwiZw== - dependencies: - "@babel/helper-plugin-utils" "^7.0.0" - find-up "^3.0.0" - istanbul-lib-instrument "^3.3.0" - test-exclude "^5.2.3" - -babel-plugin-jest-hoist@^24.9.0: - version "24.9.0" - resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-24.9.0.tgz#4f837091eb407e01447c8843cbec546d0002d756" - integrity sha512-2EMA2P8Vp7lG0RAzr4HXqtYwacfMErOuv1U3wrvxHX6rD1sV6xS3WXG3r8TRQ2r6w8OhvSdWt+z41hQNwNm3Xw== - dependencies: - "@types/babel__traverse" "^7.0.6" - -babel-plugin-syntax-async-functions@^6.8.0: - version "6.13.0" - resolved "https://registry.yarnpkg.com/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz#cad9cad1191b5ad634bf30ae0872391e0647be95" - integrity sha1-ytnK0RkbWtY0vzCuCHI5HgZHvpU= - -babel-plugin-syntax-exponentiation-operator@^6.8.0: - version "6.13.0" - resolved "https://registry.yarnpkg.com/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz#9ee7e8337290da95288201a6a57f4170317830de" - integrity sha1-nufoM3KQ2pUoggGmpX9BcDF4MN4= - -babel-plugin-syntax-trailing-function-commas@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz#ba0360937f8d06e40180a43fe0d5616fff532cf3" - integrity sha1-ugNgk3+NBuQBgKQ/4NVhb/9TLPM= - -babel-plugin-transform-async-to-generator@^6.22.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz#6536e378aff6cb1d5517ac0e40eb3e9fc8d08761" - integrity sha1-ZTbjeK/2yx1VF6wOQOs+n8jQh2E= - dependencies: - babel-helper-remap-async-to-generator "^6.24.1" - babel-plugin-syntax-async-functions "^6.8.0" - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-arrow-functions@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz#452692cb711d5f79dc7f85e440ce41b9f244d221" - integrity sha1-RSaSy3EdX3ncf4XkQM5BufJE0iE= - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-block-scoped-functions@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz#bbc51b49f964d70cb8d8e0b94e820246ce3a6141" - integrity sha1-u8UbSflk1wy42OC5ToICRs46YUE= - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-block-scoping@^6.23.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz#d70f5299c1308d05c12f463813b0a09e73b1895f" - integrity sha1-1w9SmcEwjQXBL0Y4E7CgnnOxiV8= - dependencies: - babel-runtime "^6.26.0" - babel-template "^6.26.0" - babel-traverse "^6.26.0" - babel-types "^6.26.0" - lodash "^4.17.4" - -babel-plugin-transform-es2015-classes@^6.23.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz#5a4c58a50c9c9461e564b4b2a3bfabc97a2584db" - integrity sha1-WkxYpQyclGHlZLSyo7+ryXolhNs= - dependencies: - babel-helper-define-map "^6.24.1" - babel-helper-function-name "^6.24.1" - babel-helper-optimise-call-expression "^6.24.1" - babel-helper-replace-supers "^6.24.1" - babel-messages "^6.23.0" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - babel-traverse "^6.24.1" - babel-types "^6.24.1" - -babel-plugin-transform-es2015-computed-properties@^6.22.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz#6fe2a8d16895d5634f4cd999b6d3480a308159b3" - integrity sha1-b+Ko0WiV1WNPTNmZttNICjCBWbM= - dependencies: - babel-runtime "^6.22.0" - babel-template "^6.24.1" - -babel-plugin-transform-es2015-destructuring@^6.23.0: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz#997bb1f1ab967f682d2b0876fe358d60e765c56d" - integrity sha1-mXux8auWf2gtKwh2/jWNYOdlxW0= - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-duplicate-keys@^6.22.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz#73eb3d310ca969e3ef9ec91c53741a6f1576423e" - integrity sha1-c+s9MQypaePvnskcU3QabxV2Qj4= - dependencies: - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-plugin-transform-es2015-for-of@^6.23.0: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz#f47c95b2b613df1d3ecc2fdb7573623c75248691" - integrity sha1-9HyVsrYT3x0+zC/bdXNiPHUkhpE= - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-function-name@^6.22.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz#834c89853bc36b1af0f3a4c5dbaa94fd8eacaa8b" - integrity sha1-g0yJhTvDaxrw86TF26qU/Y6sqos= - dependencies: - babel-helper-function-name "^6.24.1" - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-plugin-transform-es2015-literals@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz#4f54a02d6cd66cf915280019a31d31925377ca2e" - integrity sha1-T1SgLWzWbPkVKAAZox0xklN3yi4= - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-modules-amd@^6.22.0, babel-plugin-transform-es2015-modules-amd@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz#3b3e54017239842d6d19c3011c4bd2f00a00d154" - integrity sha1-Oz5UAXI5hC1tGcMBHEvS8AoA0VQ= - dependencies: - babel-plugin-transform-es2015-modules-commonjs "^6.24.1" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - -babel-plugin-transform-es2015-modules-commonjs@^6.23.0, babel-plugin-transform-es2015-modules-commonjs@^6.24.1: - version "6.26.2" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.2.tgz#58a793863a9e7ca870bdc5a881117ffac27db6f3" - integrity sha512-CV9ROOHEdrjcwhIaJNBGMBCodN+1cfkwtM1SbUHmvyy35KGT7fohbpOxkE2uLz1o6odKK2Ck/tz47z+VqQfi9Q== - dependencies: - babel-plugin-transform-strict-mode "^6.24.1" - babel-runtime "^6.26.0" - babel-template "^6.26.0" - babel-types "^6.26.0" - -babel-plugin-transform-es2015-modules-systemjs@^6.23.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz#ff89a142b9119a906195f5f106ecf305d9407d23" - integrity sha1-/4mhQrkRmpBhlfXxBuzzBdlAfSM= - dependencies: - babel-helper-hoist-variables "^6.24.1" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - -babel-plugin-transform-es2015-modules-umd@^6.23.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz#ac997e6285cd18ed6176adb607d602344ad38468" - integrity sha1-rJl+YoXNGO1hdq22B9YCNErThGg= - dependencies: - babel-plugin-transform-es2015-modules-amd "^6.24.1" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - -babel-plugin-transform-es2015-object-super@^6.22.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz#24cef69ae21cb83a7f8603dad021f572eb278f8d" - integrity sha1-JM72muIcuDp/hgPa0CH1cusnj40= - dependencies: - babel-helper-replace-supers "^6.24.1" - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-parameters@^6.23.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz#57ac351ab49caf14a97cd13b09f66fdf0a625f2b" - integrity sha1-V6w1GrScrxSpfNE7CfZv3wpiXys= - dependencies: - babel-helper-call-delegate "^6.24.1" - babel-helper-get-function-arity "^6.24.1" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - babel-traverse "^6.24.1" - babel-types "^6.24.1" - -babel-plugin-transform-es2015-shorthand-properties@^6.22.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz#24f875d6721c87661bbd99a4622e51f14de38aa0" - integrity sha1-JPh11nIch2YbvZmkYi5R8U3jiqA= - dependencies: - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-plugin-transform-es2015-spread@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz#d6d68a99f89aedc4536c81a542e8dd9f1746f8d1" - integrity sha1-1taKmfia7cRTbIGlQujdnxdG+NE= - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-sticky-regex@^6.22.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz#00c1cdb1aca71112cdf0cf6126c2ed6b457ccdbc" - integrity sha1-AMHNsaynERLN8M9hJsLta0V8zbw= - dependencies: - babel-helper-regex "^6.24.1" - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-plugin-transform-es2015-template-literals@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz#a84b3450f7e9f8f1f6839d6d687da84bb1236d8d" - integrity sha1-qEs0UPfp+PH2g51taH2oS7EjbY0= - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-typeof-symbol@^6.23.0: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz#dec09f1cddff94b52ac73d505c84df59dcceb372" - integrity sha1-3sCfHN3/lLUqxz1QXITfWdzOs3I= - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-unicode-regex@^6.22.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz#d38b12f42ea7323f729387f18a7c5ae1faeb35e9" - integrity sha1-04sS9C6nMj9yk4fxinxa4frrNek= - dependencies: - babel-helper-regex "^6.24.1" - babel-runtime "^6.22.0" - regexpu-core "^2.0.0" - -babel-plugin-transform-exponentiation-operator@^6.22.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz#2ab0c9c7f3098fa48907772bb813fe41e8de3a0e" - integrity sha1-KrDJx/MJj6SJB3cruBP+QejeOg4= - dependencies: - babel-helper-builder-binary-assignment-operator-visitor "^6.24.1" - babel-plugin-syntax-exponentiation-operator "^6.8.0" - babel-runtime "^6.22.0" - -babel-plugin-transform-regenerator@^6.22.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz#e0703696fbde27f0a3efcacf8b4dca2f7b3a8f2f" - integrity sha1-4HA2lvveJ/Cj78rPi03KL3s6jy8= - dependencies: - regenerator-transform "^0.10.0" - -babel-plugin-transform-strict-mode@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz#d5faf7aa578a65bbe591cf5edae04a0c67020758" - integrity sha1-1fr3qleKZbvlkc9e2uBKDGcCB1g= - dependencies: - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-preset-env@^1.7.0: - version "1.7.0" - resolved "https://registry.yarnpkg.com/babel-preset-env/-/babel-preset-env-1.7.0.tgz#dea79fa4ebeb883cd35dab07e260c1c9c04df77a" - integrity sha512-9OR2afuKDneX2/q2EurSftUYM0xGu4O2D9adAhVfADDhrYDaxXV0rBbevVYoY9n6nyX1PmQW/0jtpJvUNr9CHg== - dependencies: - babel-plugin-check-es2015-constants "^6.22.0" - babel-plugin-syntax-trailing-function-commas "^6.22.0" - babel-plugin-transform-async-to-generator "^6.22.0" - babel-plugin-transform-es2015-arrow-functions "^6.22.0" - babel-plugin-transform-es2015-block-scoped-functions "^6.22.0" - babel-plugin-transform-es2015-block-scoping "^6.23.0" - babel-plugin-transform-es2015-classes "^6.23.0" - babel-plugin-transform-es2015-computed-properties "^6.22.0" - babel-plugin-transform-es2015-destructuring "^6.23.0" - babel-plugin-transform-es2015-duplicate-keys "^6.22.0" - babel-plugin-transform-es2015-for-of "^6.23.0" - babel-plugin-transform-es2015-function-name "^6.22.0" - babel-plugin-transform-es2015-literals "^6.22.0" - babel-plugin-transform-es2015-modules-amd "^6.22.0" - babel-plugin-transform-es2015-modules-commonjs "^6.23.0" - babel-plugin-transform-es2015-modules-systemjs "^6.23.0" - babel-plugin-transform-es2015-modules-umd "^6.23.0" - babel-plugin-transform-es2015-object-super "^6.22.0" - babel-plugin-transform-es2015-parameters "^6.23.0" - babel-plugin-transform-es2015-shorthand-properties "^6.22.0" - babel-plugin-transform-es2015-spread "^6.22.0" - babel-plugin-transform-es2015-sticky-regex "^6.22.0" - babel-plugin-transform-es2015-template-literals "^6.22.0" - babel-plugin-transform-es2015-typeof-symbol "^6.23.0" - babel-plugin-transform-es2015-unicode-regex "^6.22.0" - babel-plugin-transform-exponentiation-operator "^6.22.0" - babel-plugin-transform-regenerator "^6.22.0" - browserslist "^3.2.6" - invariant "^2.2.2" - semver "^5.3.0" - -babel-preset-jest@^24.9.0: - version "24.9.0" - resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-24.9.0.tgz#192b521e2217fb1d1f67cf73f70c336650ad3cdc" - integrity sha512-izTUuhE4TMfTRPF92fFwD2QfdXaZW08qvWTFCI51V8rW5x00UuPgc3ajRoWofXOuxjfcOM5zzSYsQS3H8KGCAg== - dependencies: - "@babel/plugin-syntax-object-rest-spread" "^7.0.0" - babel-plugin-jest-hoist "^24.9.0" - -babel-register@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-register/-/babel-register-6.26.0.tgz#6ed021173e2fcb486d7acb45c6009a856f647071" - integrity sha1-btAhFz4vy0htestFxgCahW9kcHE= - dependencies: - babel-core "^6.26.0" - babel-runtime "^6.26.0" - core-js "^2.5.0" - home-or-tmp "^2.0.0" - lodash "^4.17.4" - mkdirp "^0.5.1" - source-map-support "^0.4.15" - -babel-runtime@^6.18.0, babel-runtime@^6.22.0, babel-runtime@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe" - integrity sha1-llxwWGaOgrVde/4E/yM3vItWR/4= - dependencies: - core-js "^2.4.0" - regenerator-runtime "^0.11.0" - -babel-template@^6.24.1, babel-template@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-template/-/babel-template-6.26.0.tgz#de03e2d16396b069f46dd9fff8521fb1a0e35e02" - integrity sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI= - dependencies: - babel-runtime "^6.26.0" - babel-traverse "^6.26.0" - babel-types "^6.26.0" - babylon "^6.18.0" - lodash "^4.17.4" - -babel-traverse@^6.24.1, babel-traverse@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.26.0.tgz#46a9cbd7edcc62c8e5c064e2d2d8d0f4035766ee" - integrity sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4= - dependencies: - babel-code-frame "^6.26.0" - babel-messages "^6.23.0" - babel-runtime "^6.26.0" - babel-types "^6.26.0" - babylon "^6.18.0" - debug "^2.6.8" - globals "^9.18.0" - invariant "^2.2.2" - lodash "^4.17.4" - -babel-types@^6.19.0, babel-types@^6.24.1, babel-types@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.26.0.tgz#a3b073f94ab49eb6fa55cd65227a334380632497" - integrity sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc= - dependencies: - babel-runtime "^6.26.0" - esutils "^2.0.2" - lodash "^4.17.4" - to-fast-properties "^1.0.3" - -babelify@^7.3.0: - version "7.3.0" - resolved "https://registry.yarnpkg.com/babelify/-/babelify-7.3.0.tgz#aa56aede7067fd7bd549666ee16dc285087e88e5" - integrity sha1-qlau3nBn/XvVSWZu4W3ChQh+iOU= - dependencies: - babel-core "^6.0.14" - object-assign "^4.0.0" - -babylon@^6.18.0: - version "6.18.0" - resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3" - integrity sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ== - -bach@^1.0.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/bach/-/bach-1.2.0.tgz#4b3ce96bf27134f79a1b414a51c14e34c3bd9880" - integrity sha1-Szzpa/JxNPeaG0FKUcFONMO9mIA= - dependencies: - arr-filter "^1.1.1" - arr-flatten "^1.0.1" - arr-map "^2.0.0" - array-each "^1.0.0" - array-initial "^1.0.0" - array-last "^1.1.1" - async-done "^1.2.2" - async-settle "^1.0.0" - now-and-later "^2.0.0" - -backoff@^2.5.0: - version "2.5.0" - resolved "https://registry.yarnpkg.com/backoff/-/backoff-2.5.0.tgz#f616eda9d3e4b66b8ca7fca79f695722c5f8e26f" - integrity sha1-9hbtqdPktmuMp/ynn2lXIsX44m8= - dependencies: - precond "0.2" - -balanced-match@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" - integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= - -base-x@^3.0.2: - version "3.0.7" - resolved "https://registry.yarnpkg.com/base-x/-/base-x-3.0.7.tgz#1c5a7fafe8f66b4114063e8da102799d4e7c408f" - integrity sha512-zAKJGuQPihXW22fkrfOclUUZXM2g92z5GzlSMHxhO6r6Qj+Nm0ccaGNBzDZojzwOMkpjAv4J0fOv1U4go+a4iw== - dependencies: - safe-buffer "^5.0.1" - -base-x@^3.0.8: - version "3.0.8" - resolved "https://registry.yarnpkg.com/base-x/-/base-x-3.0.8.tgz#1e1106c2537f0162e8b52474a557ebb09000018d" - integrity sha512-Rl/1AWP4J/zRrk54hhlxH4drNxPJXYUaKffODVI53/dAsV4t9fBxyxYKAVPU1XBHxYwOWP9h9H0hM2MVw4YfJA== - dependencies: - safe-buffer "^5.0.1" - -base64-js@^1.0.2: - version "1.3.1" - resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.3.1.tgz#58ece8cb75dd07e71ed08c736abc5fac4dbf8df1" - integrity sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g== - -base@^0.11.1: - version "0.11.2" - resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f" - integrity sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg== - dependencies: - cache-base "^1.0.1" - class-utils "^0.3.5" - component-emitter "^1.2.1" - define-property "^1.0.0" - isobject "^3.0.1" - mixin-deep "^1.2.0" - pascalcase "^0.1.1" - -bcrypt-pbkdf@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" - integrity sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4= - dependencies: - tweetnacl "^0.14.3" - -bech32@1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/bech32/-/bech32-1.1.4.tgz#e38c9f37bf179b8eb16ae3a772b40c356d4832e9" - integrity sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ== - -bfj@^6.1.1: - version "6.1.2" - resolved "https://registry.yarnpkg.com/bfj/-/bfj-6.1.2.tgz#325c861a822bcb358a41c78a33b8e6e2086dde7f" - integrity sha512-BmBJa4Lip6BPRINSZ0BPEIfB1wUY/9rwbwvIHQA1KjX9om29B6id0wnWXq7m3bn5JrUVjeOTnVuhPT1FiHwPGw== - dependencies: - bluebird "^3.5.5" - check-types "^8.0.3" - hoopy "^0.1.4" - tryer "^1.0.1" - -big.js@^5.2.2: - version "5.2.2" - resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328" - integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ== - -bignumber.js@*, bignumber.js@9.0.0, bignumber.js@^9.0.0, bignumber.js@~9.0.0: - version "9.0.0" - resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-9.0.0.tgz#805880f84a329b5eac6e7cb6f8274b6d82bdf075" - integrity sha512-t/OYhhJ2SD+YGBQcjY8GzzDHEk9f3nerxjtfa6tlMXfe7frs/WozhvCNoGvpM0P3bNf3Gq5ZRMlGr5f3r4/N8A== - -bignumber.js@7.2.1: - version "7.2.1" - resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-7.2.1.tgz#80c048759d826800807c4bfd521e50edbba57a5f" - integrity sha512-S4XzBk5sMB+Rcb/LNcpzXr57VRTxgAvaAEDAl1AwRx27j00hT84O6OkteE7u8UB3NuaaygCRrEpqox4uDOrbdQ== - -binary-extensions@^1.0.0: - version "1.13.1" - resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.13.1.tgz#598afe54755b2868a5330d2aff9d4ebb53209b65" - integrity sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw== - -binary-extensions@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.0.0.tgz#23c0df14f6a88077f5f986c0d167ec03c3d5537c" - integrity sha512-Phlt0plgpIIBOGTT/ehfFnbNlfsDEiqmzE2KRXoX1bLIlir4X/MR+zSyBEkL05ffWgnRSf/DXv+WrUAVr93/ow== - -bindings@^1.2.1, bindings@^1.4.0, bindings@^1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.5.0.tgz#10353c9e945334bc0511a6d90b38fbc7c9c504df" - integrity sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ== - dependencies: - file-uri-to-path "1.0.0" - -bip39@2.5.0: - version "2.5.0" - resolved "https://registry.yarnpkg.com/bip39/-/bip39-2.5.0.tgz#51cbd5179460504a63ea3c000db3f787ca051235" - integrity sha512-xwIx/8JKoT2+IPJpFEfXoWdYwP7UVAoUxxLNfGCfVowaJE7yg1Y5B1BVPqlUNsBq5/nGwmFkwRJ8xDW4sX8OdA== - dependencies: - create-hash "^1.1.0" - pbkdf2 "^3.0.9" - randombytes "^2.0.1" - safe-buffer "^5.0.1" - unorm "^1.3.3" - -bip39@^2.5.0: - version "2.6.0" - resolved "https://registry.yarnpkg.com/bip39/-/bip39-2.6.0.tgz#9e3a720b42ec8b3fbe4038f1e445317b6a99321c" - integrity sha512-RrnQRG2EgEoqO24ea+Q/fftuPUZLmrEM3qNhhGsA3PbaXaCW791LTzPuVyx/VprXQcTbPJ3K3UeTna8ZnVl2sg== - dependencies: - create-hash "^1.1.0" - pbkdf2 "^3.0.9" - randombytes "^2.0.1" - safe-buffer "^5.0.1" - unorm "^1.3.3" - -bip66@^1.1.5: - version "1.1.5" - resolved "https://registry.yarnpkg.com/bip66/-/bip66-1.1.5.tgz#01fa8748785ca70955d5011217d1b3139969ca22" - integrity sha1-AfqHSHhcpwlV1QESF9GzE5lpyiI= - dependencies: - safe-buffer "^5.0.1" - -bl@^1.0.0: - version "1.2.2" - resolved "https://registry.yarnpkg.com/bl/-/bl-1.2.2.tgz#a160911717103c07410cef63ef51b397c025af9c" - integrity sha512-e8tQYnZodmebYDWGH7KMRvtzKXaJHx3BbilrgZCfvyLUYdKpK1t5PSPmpkny/SgiTSCnjfLW7v5rlONXVFkQEA== - dependencies: - readable-stream "^2.3.5" - safe-buffer "^5.1.1" - -bl@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/bl/-/bl-3.0.0.tgz#3611ec00579fd18561754360b21e9f784500ff88" - integrity sha512-EUAyP5UHU5hxF8BPT0LKW8gjYLhq1DQIcneOX/pL/m2Alo+OYDQAJlHq+yseMP50Os2nHXOSic6Ss3vSQeyf4A== - dependencies: - readable-stream "^3.0.1" - -bluebird@^3.5.0, bluebird@^3.5.5: - version "3.7.2" - resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" - integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== - -bn.js@4.11.6: - version "4.11.6" - resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.6.tgz#53344adb14617a13f6e8dd2ce28905d1c0ba3215" - integrity sha1-UzRK2xRhehP26N0s4okF0cC6MhU= - -bn.js@4.11.8, bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.10.0, bn.js@^4.11.0, bn.js@^4.11.1, bn.js@^4.11.6, bn.js@^4.11.8, bn.js@^4.8.0: - version "4.11.8" - resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.8.tgz#2cde09eb5ee341f484746bb0309b3253b1b1442f" - integrity sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA== - -bn.js@^4.11.9: - version "4.11.9" - resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.9.tgz#26d556829458f9d1e81fc48952493d0ba3507828" - integrity sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw== - -bn.js@^4.4.0: - version "4.12.0" - resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.12.0.tgz#775b3f278efbb9718eec7361f483fb36fbbfea88" - integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA== - -body-parser@1.19.0, body-parser@^1.16.0: - version "1.19.0" - resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.0.tgz#96b2709e57c9c4e09a6fd66a8fd979844f69f08a" - integrity sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw== - dependencies: - bytes "3.1.0" - content-type "~1.0.4" - debug "2.6.9" - depd "~1.1.2" - http-errors "1.7.2" - iconv-lite "0.4.24" - on-finished "~2.3.0" - qs "6.7.0" - raw-body "2.4.0" - type-is "~1.6.17" - -brace-expansion@^1.1.7: - version "1.1.11" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" - integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== - dependencies: - balanced-match "^1.0.0" - concat-map "0.0.1" - -braces@^2.3.1, braces@^2.3.2: - version "2.3.2" - resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729" - integrity sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w== - dependencies: - arr-flatten "^1.1.0" - array-unique "^0.3.2" - extend-shallow "^2.0.1" - fill-range "^4.0.0" - isobject "^3.0.1" - repeat-element "^1.1.2" - snapdragon "^0.8.1" - snapdragon-node "^2.0.1" - split-string "^3.0.2" - to-regex "^3.0.1" - -braces@^3.0.1, braces@~3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" - integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== - dependencies: - fill-range "^7.0.1" - -brorand@^1.0.1, brorand@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" - integrity sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8= - -browser-process-hrtime@^0.1.2: - version "0.1.3" - resolved "https://registry.yarnpkg.com/browser-process-hrtime/-/browser-process-hrtime-0.1.3.tgz#616f00faef1df7ec1b5bf9cfe2bdc3170f26c7b4" - integrity sha512-bRFnI4NnjO6cnyLmOV/7PVoDEMJChlcfN0z4s1YMBY989/SvlfMI1lgCnkFUs53e9gQF+w7qu7XdllSTiSl8Aw== - -browser-resolve@^1.11.3: - version "1.11.3" - resolved "https://registry.yarnpkg.com/browser-resolve/-/browser-resolve-1.11.3.tgz#9b7cbb3d0f510e4cb86bdbd796124d28b5890af6" - integrity sha512-exDi1BYWB/6raKHmDTCicQfTkqwN5fioMFV4j8BsfMU4R2DK/QfZfK7kOVkmWCNANf0snkBzqGqAJBao9gZMdQ== - dependencies: - resolve "1.1.7" - -browser-stdout@1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.0.tgz#f351d32969d32fa5d7a5567154263d928ae3bd1f" - integrity sha1-81HTKWnTL6XXpVZxVCY9korjvR8= - -browserify-aes@^1.0.0, browserify-aes@^1.0.4, browserify-aes@^1.0.6: - version "1.2.0" - resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48" - integrity sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA== - dependencies: - buffer-xor "^1.0.3" - cipher-base "^1.0.0" - create-hash "^1.1.0" - evp_bytestokey "^1.0.3" - inherits "^2.0.1" - safe-buffer "^5.0.1" - -browserify-cipher@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/browserify-cipher/-/browserify-cipher-1.0.1.tgz#8d6474c1b870bfdabcd3bcfcc1934a10e94f15f0" - integrity sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w== - dependencies: - browserify-aes "^1.0.4" - browserify-des "^1.0.0" - evp_bytestokey "^1.0.0" - -browserify-des@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/browserify-des/-/browserify-des-1.0.2.tgz#3af4f1f59839403572f1c66204375f7a7f703e9c" - integrity sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A== - dependencies: - cipher-base "^1.0.1" - des.js "^1.0.0" - inherits "^2.0.1" - safe-buffer "^5.1.2" - -browserify-rsa@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/browserify-rsa/-/browserify-rsa-4.0.1.tgz#21e0abfaf6f2029cf2fafb133567a701d4135524" - integrity sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ= - dependencies: - bn.js "^4.1.0" - randombytes "^2.0.1" - -browserify-sha3@^0.0.4: - version "0.0.4" - resolved "https://registry.yarnpkg.com/browserify-sha3/-/browserify-sha3-0.0.4.tgz#086c47b8c82316c9d47022c26185954576dd8e26" - integrity sha1-CGxHuMgjFsnUcCLCYYWVRXbdjiY= - dependencies: - js-sha3 "^0.6.1" - safe-buffer "^5.1.1" - -browserify-sign@^4.0.0: - version "4.0.4" - resolved "https://registry.yarnpkg.com/browserify-sign/-/browserify-sign-4.0.4.tgz#aa4eb68e5d7b658baa6bf6a57e630cbd7a93d298" - integrity sha1-qk62jl17ZYuqa/alfmMMvXqT0pg= - dependencies: - bn.js "^4.1.1" - browserify-rsa "^4.0.0" - create-hash "^1.1.0" - create-hmac "^1.1.2" - elliptic "^6.0.0" - inherits "^2.0.1" - parse-asn1 "^5.0.0" - -browserify-zlib@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/browserify-zlib/-/browserify-zlib-0.2.0.tgz#2869459d9aa3be245fe8fe2ca1f46e2e7f54d73f" - integrity sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA== - dependencies: - pako "~1.0.5" - -browserslist@^3.2.6: - version "3.2.8" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-3.2.8.tgz#b0005361d6471f0f5952797a76fc985f1f978fc6" - integrity sha512-WHVocJYavUwVgVViC0ORikPHQquXwVh939TaelZ4WDqpWgTX/FsGhl/+P4qBUAGcRvtOgDgC+xftNWWp2RUTAQ== - dependencies: - caniuse-lite "^1.0.30000844" - electron-to-chromium "^1.3.47" - -bs-logger@0.x: - version "0.2.6" - resolved "https://registry.yarnpkg.com/bs-logger/-/bs-logger-0.2.6.tgz#eb7d365307a72cf974cc6cda76b68354ad336bd8" - integrity sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog== - dependencies: - fast-json-stable-stringify "2.x" - -bs58@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/bs58/-/bs58-2.0.1.tgz#55908d58f1982aba2008fa1bed8f91998a29bf8d" - integrity sha1-VZCNWPGYKrogCPob7Y+RmYopv40= - -bs58@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/bs58/-/bs58-4.0.1.tgz#be161e76c354f6f788ae4071f63f34e8c4f0a42a" - integrity sha1-vhYedsNU9veIrkBx9j806MTwpCo= - dependencies: - base-x "^3.0.2" - -bs58check@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/bs58check/-/bs58check-2.1.2.tgz#53b018291228d82a5aa08e7d796fdafda54aebfc" - integrity sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA== - dependencies: - bs58 "^4.0.0" - create-hash "^1.1.0" - safe-buffer "^5.1.2" - -bser@2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/bser/-/bser-2.1.1.tgz#e6787da20ece9d07998533cfd9de6f5c38f4bc05" - integrity sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ== - dependencies: - node-int64 "^0.4.0" - -btoa@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/btoa/-/btoa-1.2.1.tgz#01a9909f8b2c93f6bf680ba26131eb30f7fa3d73" - integrity sha512-SB4/MIGlsiVkMcHmT+pSmIPoNDoHg+7cMzmt3Uxt628MTz2487DKSqK/fuhFBrkuqrYv5UCEnACpF4dTFNKc/g== - -buffer-alloc-unsafe@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz#bd7dc26ae2972d0eda253be061dba992349c19f0" - integrity sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg== - -buffer-alloc@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/buffer-alloc/-/buffer-alloc-1.2.0.tgz#890dd90d923a873e08e10e5fd51a57e5b7cce0ec" - integrity sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow== - dependencies: - buffer-alloc-unsafe "^1.1.0" - buffer-fill "^1.0.0" - -buffer-crc32@~0.2.3: - version "0.2.13" - resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242" - integrity sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI= - -buffer-equal@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/buffer-equal/-/buffer-equal-1.0.0.tgz#59616b498304d556abd466966b22eeda3eca5fbe" - integrity sha1-WWFrSYME1Var1GaWayLu2j7KX74= - -buffer-fill@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/buffer-fill/-/buffer-fill-1.0.0.tgz#f8f78b76789888ef39f205cd637f68e702122b2c" - integrity sha1-+PeLdniYiO858gXNY39o5wISKyw= - -buffer-from@1.x, buffer-from@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" - integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A== - -buffer-to-arraybuffer@^0.0.5: - version "0.0.5" - resolved "https://registry.yarnpkg.com/buffer-to-arraybuffer/-/buffer-to-arraybuffer-0.0.5.tgz#6064a40fa76eb43c723aba9ef8f6e1216d10511a" - integrity sha1-YGSkD6dutDxyOrqe+PbhIW0QURo= - -buffer-xor@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" - integrity sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk= - -buffer@^4.3.0: - version "4.9.2" - resolved "https://registry.yarnpkg.com/buffer/-/buffer-4.9.2.tgz#230ead344002988644841ab0244af8c44bbe3ef8" - integrity sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg== - dependencies: - base64-js "^1.0.2" - ieee754 "^1.1.4" - isarray "^1.0.0" - -buffer@^5.0.5, buffer@^5.2.1: - version "5.4.3" - resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.4.3.tgz#3fbc9c69eb713d323e3fc1a895eee0710c072115" - integrity sha512-zvj65TkFeIt3i6aj5bIvJDzjjQQGs4o/sNoezg1F1kYap9Nu2jcUdpwzRSJTHMMzG0H7bZkn4rNQpImhuxWX2A== - dependencies: - base64-js "^1.0.2" - ieee754 "^1.1.4" - -buffer@^5.5.0, buffer@^5.6.0: - version "5.6.0" - resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.6.0.tgz#a31749dc7d81d84db08abf937b6b8c4033f62786" - integrity sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw== - dependencies: - base64-js "^1.0.2" - ieee754 "^1.1.4" - -builtin-status-codes@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8" - integrity sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug= - -bytes@3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6" - integrity sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg== - -bytewise-core@^1.2.2: - version "1.2.3" - resolved "https://registry.yarnpkg.com/bytewise-core/-/bytewise-core-1.2.3.tgz#3fb410c7e91558eb1ab22a82834577aa6bd61d42" - integrity sha1-P7QQx+kVWOsasiqCg0V3qmvWHUI= - dependencies: - typewise-core "^1.2" - -bytewise@~1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/bytewise/-/bytewise-1.1.0.tgz#1d13cbff717ae7158094aa881b35d081b387253e" - integrity sha1-HRPL/3F65xWAlKqIGzXQgbOHJT4= - dependencies: - bytewise-core "^1.2.2" - typewise "^1.0.3" - -cacache@^12.0.2: - version "12.0.3" - resolved "https://registry.yarnpkg.com/cacache/-/cacache-12.0.3.tgz#be99abba4e1bf5df461cd5a2c1071fc432573390" - integrity sha512-kqdmfXEGFepesTuROHMs3MpFLWrPkSSpRqOw80RCflZXy/khxaArvFrQ7uJxSUduzAufc6G0g1VUCOZXxWavPw== - dependencies: - bluebird "^3.5.5" - chownr "^1.1.1" - figgy-pudding "^3.5.1" - glob "^7.1.4" - graceful-fs "^4.1.15" - infer-owner "^1.0.3" - lru-cache "^5.1.1" - mississippi "^3.0.0" - mkdirp "^0.5.1" - move-concurrently "^1.0.1" - promise-inflight "^1.0.1" - rimraf "^2.6.3" - ssri "^6.0.1" - unique-filename "^1.1.1" - y18n "^4.0.0" - -cache-base@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2" - integrity sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ== - dependencies: - collection-visit "^1.0.0" - component-emitter "^1.2.1" - get-value "^2.0.6" - has-value "^1.0.0" - isobject "^3.0.1" - set-value "^2.0.0" - to-object-path "^0.3.0" - union-value "^1.0.0" - unset-value "^1.0.0" - -cacheable-request@^6.0.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-6.1.0.tgz#20ffb8bd162ba4be11e9567d823db651052ca912" - integrity sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg== - dependencies: - clone-response "^1.0.2" - get-stream "^5.1.0" - http-cache-semantics "^4.0.0" - keyv "^3.0.0" - lowercase-keys "^2.0.0" - normalize-url "^4.1.0" - responselike "^1.0.2" - -cachedown@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/cachedown/-/cachedown-1.0.0.tgz#d43f036e4510696b31246d7db31ebf0f7ac32d15" - integrity sha1-1D8DbkUQaWsxJG19sx6/D3rDLRU= - dependencies: - abstract-leveldown "^2.4.1" - lru-cache "^3.2.0" - -callsites@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" - integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== - -camelcase@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-3.0.0.tgz#32fc4b9fcdaf845fcdf7e73bb97cac2261f0ab0a" - integrity sha1-MvxLn82vhF/N9+c7uXysImHwqwo= - -camelcase@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd" - integrity sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0= - -camelcase@^5.0.0, camelcase@^5.3.1: - version "5.3.1" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" - integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== - -caniuse-lite@^1.0.30000844: - version "1.0.30001015" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001015.tgz#15a7ddf66aba786a71d99626bc8f2b91c6f0f5f0" - integrity sha512-/xL2AbW/XWHNu1gnIrO8UitBGoFthcsDgU9VLK1/dpsoxbaD5LscHozKze05R6WLsBvLhqv78dAPozMFQBYLbQ== - -capture-exit@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/capture-exit/-/capture-exit-2.0.0.tgz#fb953bfaebeb781f62898239dabb426d08a509a4" - integrity sha512-PiT/hQmTonHhl/HFGN+Lx3JJUznrVYJ3+AQsnthneZbvW7x+f08Tk7yLJTLEOUvBTbduLeeBkxEaYXUOUrRq6g== - dependencies: - rsvp "^4.8.4" - -caseless@~0.12.0: - version "0.12.0" - resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" - integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= - -chai-as-promised@^7.1.0: - version "7.1.1" - resolved "https://registry.yarnpkg.com/chai-as-promised/-/chai-as-promised-7.1.1.tgz#08645d825deb8696ee61725dbf590c012eb00ca0" - integrity sha512-azL6xMoi+uxu6z4rhWQ1jbdUhOMhis2PvscD/xjLqNMkv3BPPp2JyyuTHOrf9BOosGpNQ11v6BKv/g57RXbiaA== - dependencies: - check-error "^1.0.2" - -chai-bignumber@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/chai-bignumber/-/chai-bignumber-3.0.0.tgz#e90cf1f468355bbb11a9acd051222586cd2648a9" - integrity sha512-SubOtaSI2AILWTWe2j0c6i2yFT/f9J6UBjeVGDuwDiPLkF/U5+/eTWUE3sbCZ1KgcPF6UJsDVYbIxaYA097MQA== - -chai@^4.0.1: - version "4.2.0" - resolved "https://registry.yarnpkg.com/chai/-/chai-4.2.0.tgz#760aa72cf20e3795e84b12877ce0e83737aa29e5" - integrity sha512-XQU3bhBukrOsQCuwZndwGcCVQHyZi53fQ6Ys1Fym7E4olpIqqZZhhoFJoaKVvV17lWQoXYwgWN2nF5crA8J2jw== - dependencies: - assertion-error "^1.1.0" - check-error "^1.0.2" - deep-eql "^3.0.1" - get-func-name "^2.0.0" - pathval "^1.1.0" - type-detect "^4.0.5" - -chalk@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" - integrity sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg= - dependencies: - ansi-styles "^2.2.1" - escape-string-regexp "^1.0.2" - has-ansi "^2.0.0" - strip-ansi "^3.0.0" - supports-color "^2.0.0" - -chalk@^2.0.0, chalk@^2.0.1, chalk@^2.3.0, chalk@^2.4.1, chalk@^2.4.2: - version "2.4.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" - integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== - dependencies: - ansi-styles "^3.2.1" - escape-string-regexp "^1.0.5" - supports-color "^5.3.0" - -chalk@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-3.0.0.tgz#3f73c2bf526591f574cc492c51e2456349f844e4" - integrity sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg== - dependencies: - ansi-styles "^4.1.0" - supports-color "^7.1.0" - -check-error@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.2.tgz#574d312edd88bb5dd8912e9286dd6c0aed4aac82" - integrity sha1-V00xLt2Iu13YkS6Sht1sCu1KrII= - -check-types@^8.0.3: - version "8.0.3" - resolved "https://registry.yarnpkg.com/check-types/-/check-types-8.0.3.tgz#3356cca19c889544f2d7a95ed49ce508a0ecf552" - integrity sha512-YpeKZngUmG65rLudJ4taU7VLkOCTMhNl/u4ctNC56LQS/zJTyNH0Lrtwm1tfTsbLlwvlfsA2d1c8vCf/Kh2KwQ== - -checkpoint-store@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/checkpoint-store/-/checkpoint-store-1.1.0.tgz#04e4cb516b91433893581e6d4601a78e9552ea06" - integrity sha1-BOTLUWuRQziTWB5tRgGnjpVS6gY= - dependencies: - functional-red-black-tree "^1.0.1" - -chokidar@^2.0.0, chokidar@^2.1.8: - version "2.1.8" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.1.8.tgz#804b3a7b6a99358c3c5c61e71d8728f041cff917" - integrity sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg== - dependencies: - anymatch "^2.0.0" - async-each "^1.0.1" - braces "^2.3.2" - glob-parent "^3.1.0" - inherits "^2.0.3" - is-binary-path "^1.0.0" - is-glob "^4.0.0" - normalize-path "^3.0.0" - path-is-absolute "^1.0.0" - readdirp "^2.2.1" - upath "^1.1.1" - optionalDependencies: - fsevents "^1.2.7" - -chokidar@^3.0.2: - version "3.3.0" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.3.0.tgz#12c0714668c55800f659e262d4962a97faf554a6" - integrity sha512-dGmKLDdT3Gdl7fBUe8XK+gAtGmzy5Fn0XkkWQuYxGIgWVPPse2CxFA5mtrlD0TOHaHjEUqkWNyP1XdHoJES/4A== - dependencies: - anymatch "~3.1.1" - braces "~3.0.2" - glob-parent "~5.1.0" - is-binary-path "~2.1.0" - is-glob "~4.0.1" - normalize-path "~3.0.0" - readdirp "~3.2.0" - optionalDependencies: - fsevents "~2.1.1" - -chokidar@^3.4.1: - version "3.4.2" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.4.2.tgz#38dc8e658dec3809741eb3ef7bb0a47fe424232d" - integrity sha512-IZHaDeBeI+sZJRX7lGcXsdzgvZqKv6sECqsbErJA4mHWfpRrD8B97kSFN4cQz6nGBGiuFia1MKR4d6c1o8Cv7A== - dependencies: - anymatch "~3.1.1" - braces "~3.0.2" - glob-parent "~5.1.0" - is-binary-path "~2.1.0" - is-glob "~4.0.1" - normalize-path "~3.0.0" - readdirp "~3.4.0" - optionalDependencies: - fsevents "~2.1.2" - -chownr@^1.1.1: - version "1.1.3" - resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.3.tgz#42d837d5239688d55f303003a508230fa6727142" - integrity sha512-i70fVHhmV3DtTl6nqvZOnIjbY0Pe4kAUjwHj8z0zAdgBtYrJyYwLKCCuRBQ5ppkyL0AkN7HKRnETdmdp1zqNXw== - -chrome-trace-event@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz#234090ee97c7d4ad1a2c4beae27505deffc608a4" - integrity sha512-9e/zx1jw7B4CO+c/RXoCsfg/x1AfUBioy4owYH0bJprEYAx5hRFLRhWBqHAG57D0ZM4H7vxbP7bPe0VwhQRYDQ== - dependencies: - tslib "^1.9.0" - -ci-info@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46" - integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ== - -cids@^0.7.1: - version "0.7.5" - resolved "https://registry.yarnpkg.com/cids/-/cids-0.7.5.tgz#60a08138a99bfb69b6be4ceb63bfef7a396b28b2" - integrity sha512-zT7mPeghoWAu+ppn8+BS1tQ5qGmbMfB4AregnQjA/qHY3GC1m1ptI9GkWNlgeu38r7CuRdXB47uY2XgAYt6QVA== - dependencies: - buffer "^5.5.0" - class-is "^1.1.0" - multibase "~0.6.0" - multicodec "^1.0.0" - multihashes "~0.4.15" - -cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de" - integrity sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q== - dependencies: - inherits "^2.0.1" - safe-buffer "^5.0.1" - -class-is@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/class-is/-/class-is-1.1.0.tgz#9d3c0fba0440d211d843cec3dedfa48055005825" - integrity sha512-rhjH9AG1fvabIDoGRVH587413LPjTZgmDF9fOFCbFJQV4yuocX1mHxxvXI4g3cGwbVY9wAYIoKlg1N79frJKQw== - -class-utils@^0.3.5: - version "0.3.6" - resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463" - integrity sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg== - dependencies: - arr-union "^3.1.0" - define-property "^0.2.5" - isobject "^3.0.0" - static-extend "^0.1.1" - -cliui@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-3.2.0.tgz#120601537a916d29940f934da3b48d585a39213d" - integrity sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0= - dependencies: - string-width "^1.0.1" - strip-ansi "^3.0.1" - wrap-ansi "^2.0.0" - -cliui@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-4.1.0.tgz#348422dbe82d800b3022eef4f6ac10bf2e4d1b49" - integrity sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ== - dependencies: - string-width "^2.1.1" - strip-ansi "^4.0.0" - wrap-ansi "^2.0.0" - -cliui@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-5.0.0.tgz#deefcfdb2e800784aa34f46fa08e06851c7bbbc5" - integrity sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA== - dependencies: - string-width "^3.1.0" - strip-ansi "^5.2.0" - wrap-ansi "^5.1.0" - -clone-buffer@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/clone-buffer/-/clone-buffer-1.0.0.tgz#e3e25b207ac4e701af721e2cb5a16792cac3dc58" - integrity sha1-4+JbIHrE5wGvch4staFnksrD3Fg= - -clone-response@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/clone-response/-/clone-response-1.0.2.tgz#d1dc973920314df67fbeb94223b4ee350239e96b" - integrity sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws= - dependencies: - mimic-response "^1.0.0" - -clone-stats@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/clone-stats/-/clone-stats-1.0.0.tgz#b3782dff8bb5474e18b9b6bf0fdfe782f8777680" - integrity sha1-s3gt/4u1R04Yuba/D9/ngvh3doA= - -clone@2.1.2, clone@^2.0.0, clone@^2.1.1: - version "2.1.2" - resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.2.tgz#1b7f4b9f591f1e8f83670401600345a02887435f" - integrity sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18= - -cloneable-readable@^1.0.0: - version "1.1.3" - resolved "https://registry.yarnpkg.com/cloneable-readable/-/cloneable-readable-1.1.3.tgz#120a00cb053bfb63a222e709f9683ea2e11d8cec" - integrity sha512-2EF8zTQOxYq70Y4XKtorQupqF0m49MBz2/yf5Bj+MHjvpG3Hy7sImifnqD6UA+TKYxeSV+u6qqQPawN5UvnpKQ== - dependencies: - inherits "^2.0.1" - process-nextick-args "^2.0.0" - readable-stream "^2.3.5" - -co@^4.6.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" - integrity sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ= - -code-point-at@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" - integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c= - -coinstring@^2.0.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/coinstring/-/coinstring-2.3.0.tgz#cdb63363a961502404a25afb82c2e26d5ff627a4" - integrity sha1-zbYzY6lhUCQEolr7gsLibV/2J6Q= - dependencies: - bs58 "^2.0.1" - create-hash "^1.1.1" - -collection-map@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/collection-map/-/collection-map-1.0.0.tgz#aea0f06f8d26c780c2b75494385544b2255af18c" - integrity sha1-rqDwb40mx4DCt1SUOFVEsiVa8Yw= - dependencies: - arr-map "^2.0.2" - for-own "^1.0.0" - make-iterator "^1.0.0" - -collection-visit@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0" - integrity sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA= - dependencies: - map-visit "^1.0.0" - object-visit "^1.0.0" - -color-convert@^1.9.0: - version "1.9.3" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" - integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== - dependencies: - color-name "1.1.3" - -color-convert@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" - integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== - dependencies: - color-name "~1.1.4" - -color-name@1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" - integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= - -color-name@~1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" - integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== - -color-support@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/color-support/-/color-support-1.1.3.tgz#93834379a1cc9a0c61f82f52f0d04322251bd5a2" - integrity sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg== - -combined-stream@^1.0.6, combined-stream@~1.0.6: - version "1.0.8" - resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" - integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== - dependencies: - delayed-stream "~1.0.0" - -command-exists@^1.2.8: - version "1.2.8" - resolved "https://registry.yarnpkg.com/command-exists/-/command-exists-1.2.8.tgz#715acefdd1223b9c9b37110a149c6392c2852291" - integrity sha512-PM54PkseWbiiD/mMsbvW351/u+dafwTJ0ye2qB60G1aGQP9j3xK2gmMDc+R34L3nDtx4qMCitXT75mkbkGJDLw== - -commander@2.11.0: - version "2.11.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.11.0.tgz#157152fd1e7a6c8d98a5b715cf376df928004563" - integrity sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ== - -commander@3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/commander/-/commander-3.0.2.tgz#6837c3fb677ad9933d1cfba42dd14d5117d6b39e" - integrity sha512-Gar0ASD4BDyKC4hl4DwHqDrmvjoxWKZigVnAbn5H1owvm4CxCPdb0HQDehwNYMJpla5+M2tPmPARzhtYuwpHow== - -commander@^2.18.0, commander@^2.20.0, commander@~2.20.3: - version "2.20.3" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" - integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== - -commander@~2.8.1: - version "2.8.1" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.8.1.tgz#06be367febfda0c330aa1e2a072d3dc9762425d4" - integrity sha1-Br42f+v9oMMwqh4qBy09yXYkJdQ= - dependencies: - graceful-readlink ">= 1.0.0" - -commondir@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" - integrity sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs= - -component-emitter@^1.2.1: - version "1.3.0" - resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0" - integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg== - -concat-map@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" - integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= - -concat-stream@^1.5.0, concat-stream@^1.5.1, concat-stream@^1.6.0: - version "1.6.2" - resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" - integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw== - dependencies: - buffer-from "^1.0.0" - inherits "^2.0.3" - readable-stream "^2.2.2" - typedarray "^0.0.6" - -console-browserify@^1.1.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.2.0.tgz#67063cef57ceb6cf4993a2ab3a55840ae8c49336" - integrity sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA== - -console-control-strings@^1.0.0, console-control-strings@~1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" - integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4= - -constants-browserify@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75" - integrity sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U= - -content-disposition@0.5.3: - version "0.5.3" - resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.3.tgz#e130caf7e7279087c5616c2007d0485698984fbd" - integrity sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g== - dependencies: - safe-buffer "5.1.2" - -content-hash@^2.5.2: - version "2.5.2" - resolved "https://registry.yarnpkg.com/content-hash/-/content-hash-2.5.2.tgz#bbc2655e7c21f14fd3bfc7b7d4bfe6e454c9e211" - integrity sha512-FvIQKy0S1JaWV10sMsA7TRx8bpU+pqPkhbsfvOJAdjRXvYxEckAwQWGwtRjiaJfh+E0DvcWUGqcdjwMGFjsSdw== - dependencies: - cids "^0.7.1" - multicodec "^0.5.5" - multihashes "^0.4.15" - -content-type@~1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" - integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA== - -convert-source-map@^1.4.0, convert-source-map@^1.5.0, convert-source-map@^1.5.1, convert-source-map@^1.7.0: - version "1.7.0" - resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.7.0.tgz#17a2cb882d7f77d3490585e2ce6c524424a3a442" - integrity sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA== - dependencies: - safe-buffer "~5.1.1" - -cookie-signature@1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" - integrity sha1-4wOogrNCzD7oylE6eZmXNNqzriw= - -cookie@0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.0.tgz#beb437e7022b3b6d49019d088665303ebe9c14ba" - integrity sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg== - -cookiejar@^2.1.1: - version "2.1.2" - resolved "https://registry.yarnpkg.com/cookiejar/-/cookiejar-2.1.2.tgz#dd8a235530752f988f9a0844f3fc589e3111125c" - integrity sha512-Mw+adcfzPxcPeI+0WlvRrr/3lGVO0bD75SxX6811cxSh1Wbxx7xZBGK1eVtDf6si8rg2lhnUjsVLMFMfbRIuwA== - -copy-concurrently@^1.0.0: - version "1.0.5" - resolved "https://registry.yarnpkg.com/copy-concurrently/-/copy-concurrently-1.0.5.tgz#92297398cae34937fcafd6ec8139c18051f0b5e0" - integrity sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A== - dependencies: - aproba "^1.1.1" - fs-write-stream-atomic "^1.0.8" - iferr "^0.1.5" - mkdirp "^0.5.1" - rimraf "^2.5.4" - run-queue "^1.0.0" - -copy-descriptor@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" - integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= - -copy-props@^2.0.1: - version "2.0.4" - resolved "https://registry.yarnpkg.com/copy-props/-/copy-props-2.0.4.tgz#93bb1cadfafd31da5bb8a9d4b41f471ec3a72dfe" - integrity sha512-7cjuUME+p+S3HZlbllgsn2CDwS+5eCCX16qBgNC4jgSTf49qR1VKy/Zhl400m0IQXl/bPGEVqncgUUMjrr4s8A== - dependencies: - each-props "^1.3.0" - is-plain-object "^2.0.1" - -core-js-pure@^3.0.1: - version "3.6.2" - resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.6.2.tgz#81f08059134d1c7318838024e1b8e866bcb1ddb3" - integrity sha512-PRasaCPjjCB65au2dMBPtxuIR6LM8MVNdbIbN57KxcDV1FAYQWlF0pqje/HC2sM6nm/s9KqSTkMTU75pozaghA== - -core-js@^2.4.0, core-js@^2.5.0: - version "2.6.10" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.10.tgz#8a5b8391f8cc7013da703411ce5b585706300d7f" - integrity sha512-I39t74+4t+zau64EN1fE5v2W31Adtc/REhzWN+gWRRXg6WH5qAsZm62DHpQ1+Yhe4047T55jvzz7MUqF/dBBlA== - -core-util-is@1.0.2, core-util-is@~1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" - integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= - -cors@^2.8.1: - version "2.8.5" - resolved "https://registry.yarnpkg.com/cors/-/cors-2.8.5.tgz#eac11da51592dd86b9f06f6e7ac293b3df875d29" - integrity sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g== - dependencies: - object-assign "^4" - vary "^1" - -create-ecdh@^4.0.0: - version "4.0.3" - resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.3.tgz#c9111b6f33045c4697f144787f9254cdc77c45ff" - integrity sha512-GbEHQPMOswGpKXM9kCWVrremUcBmjteUaQ01T9rkKCPDXfUHX0IoP9LpHYo2NPFampa4e+/pFDc3jQdxrxQLaw== - dependencies: - bn.js "^4.1.0" - elliptic "^6.0.0" - -create-hash@^1.1.0, create-hash@^1.1.1, create-hash@^1.1.2, create-hash@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196" - integrity sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg== - dependencies: - cipher-base "^1.0.1" - inherits "^2.0.1" - md5.js "^1.3.4" - ripemd160 "^2.0.1" - sha.js "^2.4.0" - -create-hmac@^1.1.0, create-hmac@^1.1.2, create-hmac@^1.1.4: - version "1.1.7" - resolved "https://registry.yarnpkg.com/create-hmac/-/create-hmac-1.1.7.tgz#69170c78b3ab957147b2b8b04572e47ead2243ff" - integrity sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg== - dependencies: - cipher-base "^1.0.3" - create-hash "^1.1.0" - inherits "^2.0.1" - ripemd160 "^2.0.0" - safe-buffer "^5.0.1" - sha.js "^2.4.8" - -cross-fetch@^2.1.0, cross-fetch@^2.1.1: - version "2.2.3" - resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-2.2.3.tgz#e8a0b3c54598136e037f8650f8e823ccdfac198e" - integrity sha512-PrWWNH3yL2NYIb/7WF/5vFG3DCQiXDOVf8k3ijatbrtnwNuhMWLC7YF7uqf53tbTFDzHIUD8oITw4Bxt8ST3Nw== - dependencies: - node-fetch "2.1.2" - whatwg-fetch "2.0.4" - -cross-spawn@^5.0.1: - version "5.1.0" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449" - integrity sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk= - dependencies: - lru-cache "^4.0.1" - shebang-command "^1.2.0" - which "^1.2.9" - -cross-spawn@^6.0.0, cross-spawn@^6.0.5: - version "6.0.5" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" - integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ== - dependencies: - nice-try "^1.0.4" - path-key "^2.0.1" - semver "^5.5.0" - shebang-command "^1.2.0" - which "^1.2.9" - -crypto-browserify@3.12.0, crypto-browserify@^3.11.0: - version "3.12.0" - resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec" - integrity sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg== - dependencies: - browserify-cipher "^1.0.0" - browserify-sign "^4.0.0" - create-ecdh "^4.0.0" - create-hash "^1.1.0" - create-hmac "^1.1.0" - diffie-hellman "^5.0.0" - inherits "^2.0.1" - pbkdf2 "^3.0.3" - public-encrypt "^4.0.0" - randombytes "^2.0.0" - randomfill "^1.0.3" - -cssom@0.3.x, "cssom@>= 0.3.2 < 0.4.0": - version "0.3.8" - resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.3.8.tgz#9f1276f5b2b463f2114d3f2c75250af8c1a36f4a" - integrity sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg== - -cssstyle@^1.0.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/cssstyle/-/cssstyle-1.4.0.tgz#9d31328229d3c565c61e586b02041a28fccdccf1" - integrity sha512-GBrLZYZ4X4x6/QEoBnIrqb8B/f5l4+8me2dkom/j1Gtbxy0kBv6OGzKuAsGM75bkGwGAFkt56Iwg28S3XTZgSA== - dependencies: - cssom "0.3.x" - -csstype@^2.2.0: - version "2.6.7" - resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.7.tgz#20b0024c20b6718f4eda3853a1f5a1cce7f5e4a5" - integrity sha512-9Mcn9sFbGBAdmimWb2gLVDtFJzeKtDGIr76TUqmjZrw9LFXBMSU70lcs+C0/7fyCd6iBDqmksUcCOUIkisPHsQ== - -cyclist@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-1.0.1.tgz#596e9698fd0c80e12038c2b82d6eb1b35b6224d9" - integrity sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk= - -d@1, d@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/d/-/d-1.0.1.tgz#8698095372d58dbee346ffd0c7093f99f8f9eb5a" - integrity sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA== - dependencies: - es5-ext "^0.10.50" - type "^1.0.1" - -dashdash@^1.12.0: - version "1.14.1" - resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" - integrity sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA= - dependencies: - assert-plus "^1.0.0" - -data-urls@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-1.1.0.tgz#15ee0582baa5e22bb59c77140da8f9c76963bbfe" - integrity sha512-YTWYI9se1P55u58gL5GkQHW4P6VJBJ5iBT+B5a7i2Tjadhv52paJG0qHX4A0OR6/t52odI64KP2YvFpkDOi3eQ== - dependencies: - abab "^2.0.0" - whatwg-mimetype "^2.2.0" - whatwg-url "^7.0.0" - -debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.8, debug@^2.6.9: - version "2.6.9" - resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" - integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== - dependencies: - ms "2.0.0" - -debug@3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" - integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g== - dependencies: - ms "2.0.0" - -debug@3.2.6, debug@^3.1.0, debug@^3.2.6: - version "3.2.6" - resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" - integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== - dependencies: - ms "^2.1.1" - -debug@^4.1.0, debug@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791" - integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw== - dependencies: - ms "^2.1.1" - -decamelize@^1.1.1, decamelize@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" - integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= - -decode-uri-component@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" - integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU= - -decompress-response@^3.2.0, decompress-response@^3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-3.3.0.tgz#80a4dd323748384bfa248083622aedec982adff3" - integrity sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M= - dependencies: - mimic-response "^1.0.0" - -decompress-response@^4.2.0: - version "4.2.1" - resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-4.2.1.tgz#414023cc7a302da25ce2ec82d0d5238ccafd8986" - integrity sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw== - dependencies: - mimic-response "^2.0.0" - -decompress-tar@^4.0.0, decompress-tar@^4.1.0, decompress-tar@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/decompress-tar/-/decompress-tar-4.1.1.tgz#718cbd3fcb16209716e70a26b84e7ba4592e5af1" - integrity sha512-JdJMaCrGpB5fESVyxwpCx4Jdj2AagLmv3y58Qy4GE6HMVjWz1FeVQk1Ct4Kye7PftcdOo/7U7UKzYBJgqnGeUQ== - dependencies: - file-type "^5.2.0" - is-stream "^1.1.0" - tar-stream "^1.5.2" - -decompress-tarbz2@^4.0.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/decompress-tarbz2/-/decompress-tarbz2-4.1.1.tgz#3082a5b880ea4043816349f378b56c516be1a39b" - integrity sha512-s88xLzf1r81ICXLAVQVzaN6ZmX4A6U4z2nMbOwobxkLoIIfjVMBg7TeguTUXkKeXni795B6y5rnvDw7rxhAq9A== - dependencies: - decompress-tar "^4.1.0" - file-type "^6.1.0" - is-stream "^1.1.0" - seek-bzip "^1.0.5" - unbzip2-stream "^1.0.9" - -decompress-targz@^4.0.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/decompress-targz/-/decompress-targz-4.1.1.tgz#c09bc35c4d11f3de09f2d2da53e9de23e7ce1eee" - integrity sha512-4z81Znfr6chWnRDNfFNqLwPvm4db3WuZkqV+UgXQzSngG3CEKdBkw5jrv3axjjL96glyiiKjsxJG3X6WBZwX3w== - dependencies: - decompress-tar "^4.1.1" - file-type "^5.2.0" - is-stream "^1.1.0" - -decompress-unzip@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/decompress-unzip/-/decompress-unzip-4.0.1.tgz#deaaccdfd14aeaf85578f733ae8210f9b4848f69" - integrity sha1-3qrM39FK6vhVePczroIQ+bSEj2k= - dependencies: - file-type "^3.8.0" - get-stream "^2.2.0" - pify "^2.3.0" - yauzl "^2.4.2" - -decompress@^4.0.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/decompress/-/decompress-4.2.0.tgz#7aedd85427e5a92dacfe55674a7c505e96d01f9d" - integrity sha1-eu3YVCflqS2s/lVnSnxQXpbQH50= - dependencies: - decompress-tar "^4.0.0" - decompress-tarbz2 "^4.0.0" - decompress-targz "^4.0.0" - decompress-unzip "^4.0.1" - graceful-fs "^4.1.10" - make-dir "^1.0.0" - pify "^2.3.0" - strip-dirs "^2.0.0" - -deep-eql@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-3.0.1.tgz#dfc9404400ad1c8fe023e7da1df1c147c4b444df" - integrity sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw== - dependencies: - type-detect "^4.0.0" - -deep-equal@~1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.0.1.tgz#f5d260292b660e084eff4cdbc9f08ad3247448b5" - integrity sha1-9dJgKStmDghO/0zbyfCK0yR0SLU= - -deep-extend@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" - integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== - -deep-is@~0.1.3: - version "0.1.3" - resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" - integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ= - -default-compare@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/default-compare/-/default-compare-1.0.0.tgz#cb61131844ad84d84788fb68fd01681ca7781a2f" - integrity sha512-QWfXlM0EkAbqOCbD/6HjdwT19j7WCkMyiRhWilc4H9/5h/RzTF9gv5LYh1+CmDV5d1rki6KAWLtQale0xt20eQ== - dependencies: - kind-of "^5.0.2" - -default-resolution@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/default-resolution/-/default-resolution-2.0.0.tgz#bcb82baa72ad79b426a76732f1a81ad6df26d684" - integrity sha1-vLgrqnKtebQmp2cy8aga1t8m1oQ= - -defer-to-connect@^1.0.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-1.1.1.tgz#88ae694b93f67b81815a2c8c769aef6574ac8f2f" - integrity sha512-J7thop4u3mRTkYRQ+Vpfwy2G5Ehoy82I14+14W4YMDLKdWloI9gSzRbV30s/NckQGVJtPkWNcW4oMAUigTdqiQ== - -deferred-leveldown@~1.2.1: - version "1.2.2" - resolved "https://registry.yarnpkg.com/deferred-leveldown/-/deferred-leveldown-1.2.2.tgz#3acd2e0b75d1669924bc0a4b642851131173e1eb" - integrity sha512-uukrWD2bguRtXilKt6cAWKyoXrTSMo5m7crUdLfWQmu8kIm88w3QZoUL+6nhpfKVmhHANER6Re3sKoNoZ3IKMA== - dependencies: - abstract-leveldown "~2.6.0" - -deferred-leveldown@~4.0.0: - version "4.0.2" - resolved "https://registry.yarnpkg.com/deferred-leveldown/-/deferred-leveldown-4.0.2.tgz#0b0570087827bf480a23494b398f04c128c19a20" - integrity sha512-5fMC8ek8alH16QiV0lTCis610D1Zt1+LA4MS4d63JgS32lrCjTFDUFz2ao09/j2I4Bqb5jL4FZYwu7Jz0XO1ww== - dependencies: - abstract-leveldown "~5.0.0" - inherits "^2.0.3" - -define-properties@^1.1.2, define-properties@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" - integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ== - dependencies: - object-keys "^1.0.12" - -define-property@^0.2.5: - version "0.2.5" - resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116" - integrity sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY= - dependencies: - is-descriptor "^0.1.0" - -define-property@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/define-property/-/define-property-1.0.0.tgz#769ebaaf3f4a63aad3af9e8d304c9bbe79bfb0e6" - integrity sha1-dp66rz9KY6rTr56NMEybvnm/sOY= - dependencies: - is-descriptor "^1.0.0" - -define-property@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/define-property/-/define-property-2.0.2.tgz#d459689e8d654ba77e02a817f8710d702cb16e9d" - integrity sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ== - dependencies: - is-descriptor "^1.0.2" - isobject "^3.0.1" - -defined@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/defined/-/defined-1.0.0.tgz#c98d9bcef75674188e110969151199e39b1fa693" - integrity sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM= - -delayed-stream@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" - integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= - -delegates@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" - integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o= - -depd@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" - integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak= - -des.js@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.0.1.tgz#5382142e1bdc53f85d86d53e5f4aa7deb91e0843" - integrity sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA== - dependencies: - inherits "^2.0.1" - minimalistic-assert "^1.0.0" - -destroy@~1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" - integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA= - -detect-file@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/detect-file/-/detect-file-1.0.0.tgz#f0d66d03672a825cb1b73bdb3fe62310c8e552b7" - integrity sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc= - -detect-indent@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-4.0.0.tgz#f76d064352cdf43a1cb6ce619c4ee3a9475de208" - integrity sha1-920GQ1LN9Docts5hnE7jqUdd4gg= - dependencies: - repeating "^2.0.0" - -detect-libc@^1.0.2, detect-libc@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" - integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups= - -detect-newline@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-2.1.0.tgz#f41f1c10be4b00e87b5f13da680759f2c5bfd3e2" - integrity sha1-9B8cEL5LAOh7XxPaaAdZ8sW/0+I= - -detect-node@2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.0.3.tgz#a2033c09cc8e158d37748fbde7507832bd6ce127" - integrity sha1-ogM8CcyOFY03dI+951B4Mr1s4Sc= - -diff-sequences@^24.9.0: - version "24.9.0" - resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-24.9.0.tgz#5715d6244e2aa65f48bba0bc972db0b0b11e95b5" - integrity sha512-Dj6Wk3tWyTE+Fo1rW8v0Xhwk80um6yFYKbuAxc9c3EZxIHFDYwbi34Uk42u1CdnIiVorvt4RmlSDjIPyzGC2ew== - -diff-sequences@^25.2.6: - version "25.2.6" - resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-25.2.6.tgz#5f467c00edd35352b7bca46d7927d60e687a76dd" - integrity sha512-Hq8o7+6GaZeoFjtpgvRBUknSXNeJiCx7V9Fr94ZMljNiCr9n9L8H8aJqgWOQiDDGdyn29fRNcDdRVJ5fdyihfg== - -diff@3.3.1: - version "3.3.1" - resolved "https://registry.yarnpkg.com/diff/-/diff-3.3.1.tgz#aa8567a6eed03c531fc89d3f711cd0e5259dec75" - integrity sha512-MKPHZDMB0o6yHyDryUOScqZibp914ksXwAMYMTHj6KO8UeKsRYNJD3oNCKjTqZon+V488P7N/HzXF8t7ZR95ww== - -diffie-hellman@^5.0.0: - version "5.0.3" - resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875" - integrity sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg== - dependencies: - bn.js "^4.1.0" - miller-rabin "^4.0.0" - randombytes "^2.0.0" - -dirty-chai@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/dirty-chai/-/dirty-chai-2.0.1.tgz#6b2162ef17f7943589da840abc96e75bda01aff3" - integrity sha512-ys79pWKvDMowIDEPC6Fig8d5THiC0DJ2gmTeGzVAoEH18J8OzLud0Jh7I9IWg3NSk8x2UocznUuFmfHCXYZx9w== - -dom-walk@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/dom-walk/-/dom-walk-0.1.1.tgz#672226dc74c8f799ad35307df936aba11acd6018" - integrity sha1-ZyIm3HTI95mtNTB9+TaroRrNYBg= - -domain-browser@^1.1.1: - version "1.2.0" - resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.2.0.tgz#3d31f50191a6749dd1375a7f522e823d42e54eda" - integrity sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA== - -domexception@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/domexception/-/domexception-1.0.1.tgz#937442644ca6a31261ef36e3ec677fe805582c90" - integrity sha512-raigMkn7CJNNo6Ihro1fzG7wr3fHuYVytzquZKX5n0yizGsTcYgzdIUwj1X9pK0VvjeihV+XiclP+DjwbsSKug== - dependencies: - webidl-conversions "^4.0.2" - -drbg.js@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/drbg.js/-/drbg.js-1.0.1.tgz#3e36b6c42b37043823cdbc332d58f31e2445480b" - integrity sha1-Pja2xCs3BDgjzbwzLVjzHiRFSAs= - dependencies: - browserify-aes "^1.0.6" - create-hash "^1.1.2" - create-hmac "^1.1.4" - -duplexer3@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2" - integrity sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI= - -duplexer@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.1.tgz#ace6ff808c1ce66b57d1ebf97977acb02334cfc1" - integrity sha1-rOb/gIwc5mtX0ev5eXessCM0z8E= - -duplexify@^3.4.2, duplexify@^3.6.0: - version "3.7.1" - resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.7.1.tgz#2a4df5317f6ccfd91f86d6fd25d8d8a103b88309" - integrity sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g== - dependencies: - end-of-stream "^1.0.0" - inherits "^2.0.1" - readable-stream "^2.0.0" - stream-shift "^1.0.0" - -each-props@^1.3.0: - version "1.3.2" - resolved "https://registry.yarnpkg.com/each-props/-/each-props-1.3.2.tgz#ea45a414d16dd5cfa419b1a81720d5ca06892333" - integrity sha512-vV0Hem3zAGkJAyU7JSjixeU66rwdynTAa1vofCrSA5fEln+m67Az9CcnkVD776/fsN/UjIWmBDoNRS6t6G9RfA== - dependencies: - is-plain-object "^2.0.1" - object.defaults "^1.1.0" - -ecc-jsbn@~0.1.1: - version "0.1.2" - resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" - integrity sha1-OoOpBOVDUyh4dMVkt1SThoSamMk= - dependencies: - jsbn "~0.1.0" - safer-buffer "^2.1.0" - -ee-first@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" - integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= - -ejs@^2.6.1: - version "2.7.4" - resolved "https://registry.yarnpkg.com/ejs/-/ejs-2.7.4.tgz#48661287573dcc53e366c7a1ae52c3a120eec9ba" - integrity sha512-7vmuyh5+kuUyJKePhQfRQBhXV5Ce+RnaeeQArKu1EAMpL3WbgMt5WG6uQZpEVvYSSsxMXRKOewtDk9RaTKXRlA== - -electron-to-chromium@^1.3.47: - version "1.3.322" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.322.tgz#a6f7e1c79025c2b05838e8e344f6e89eb83213a8" - integrity sha512-Tc8JQEfGQ1MzfSzI/bTlSr7btJv/FFO7Yh6tanqVmIWOuNCu6/D1MilIEgLtmWqIrsv+o4IjpLAhgMBr/ncNAA== - -elliptic@6.3.3: - version "6.3.3" - resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.3.3.tgz#5482d9646d54bcb89fd7d994fc9e2e9568876e3f" - integrity sha1-VILZZG1UvLif19mU/J4ulWiHbj8= - dependencies: - bn.js "^4.4.0" - brorand "^1.0.1" - hash.js "^1.0.0" - inherits "^2.0.1" - -elliptic@6.5.2, elliptic@^6.0.0, elliptic@^6.4.0, elliptic@^6.4.1: - version "6.5.2" - resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.2.tgz#05c5678d7173c049d8ca433552224a495d0e3762" - integrity sha512-f4x70okzZbIQl/NSRLkI/+tteV/9WqL98zx+SQ69KbXxmVrmjwsNUPn/gYJJ0sHvEak24cZgHIPegRePAtA/xw== - dependencies: - bn.js "^4.4.0" - brorand "^1.0.1" - hash.js "^1.0.0" - hmac-drbg "^1.0.0" - inherits "^2.0.1" - minimalistic-assert "^1.0.0" - minimalistic-crypto-utils "^1.0.0" - -elliptic@6.5.4: - version "6.5.4" - resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.4.tgz#da37cebd31e79a1367e941b592ed1fbebd58abbb" - integrity sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ== - dependencies: - bn.js "^4.11.9" - brorand "^1.1.0" - hash.js "^1.0.0" - hmac-drbg "^1.0.1" - inherits "^2.0.4" - minimalistic-assert "^1.0.1" - minimalistic-crypto-utils "^1.0.1" - -emoji-regex@^7.0.1: - version "7.0.3" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" - integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA== - -emojis-list@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-2.1.0.tgz#4daa4d9db00f9819880c79fa457ae5b09a1fd389" - integrity sha1-TapNnbAPmBmIDHn6RXrlsJof04k= - -emojis-list@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-3.0.0.tgz#5570662046ad29e2e916e71aae260abdff4f6a78" - integrity sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q== - -encodeurl@~1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" - integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= - -encoding-down@5.0.4, encoding-down@~5.0.0: - version "5.0.4" - resolved "https://registry.yarnpkg.com/encoding-down/-/encoding-down-5.0.4.tgz#1e477da8e9e9d0f7c8293d320044f8b2cd8e9614" - integrity sha512-8CIZLDcSKxgzT+zX8ZVfgNbu8Md2wq/iqa1Y7zyVR18QBEAc0Nmzuvj/N5ykSKpfGzjM8qxbaFntLPwnVoUhZw== - dependencies: - abstract-leveldown "^5.0.0" - inherits "^2.0.3" - level-codec "^9.0.0" - level-errors "^2.0.0" - xtend "^4.0.1" - -encoding@^0.1.11: - version "0.1.12" - resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.12.tgz#538b66f3ee62cd1ab51ec323829d1f9480c74beb" - integrity sha1-U4tm8+5izRq1HsMjgp0flIDHS+s= - dependencies: - iconv-lite "~0.4.13" - -end-of-stream@^1.0.0, end-of-stream@^1.1.0, end-of-stream@^1.4.1: - version "1.4.4" - resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" - integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== - dependencies: - once "^1.4.0" - -enhanced-resolve@^4.0.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-4.1.1.tgz#2937e2b8066cd0fe7ce0990a98f0d71a35189f66" - integrity sha512-98p2zE+rL7/g/DzMHMTF4zZlCgeVdJ7yr6xzEpJRYwFYrGi9ANdn5DnJURg6RpBkyk60XYDnWIv51VfIhfNGuA== - dependencies: - graceful-fs "^4.1.2" - memory-fs "^0.5.0" - tapable "^1.0.0" - -enhanced-resolve@^4.1.1, enhanced-resolve@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-4.3.0.tgz#3b806f3bfafc1ec7de69551ef93cca46c1704126" - integrity sha512-3e87LvavsdxyoCfGusJnrZ5G8SLPOFeHSNpZI/ATL9a5leXo2k0w6MKnbqhdBad9qTobSfB20Ld7UmgoNbAZkQ== - dependencies: - graceful-fs "^4.1.2" - memory-fs "^0.5.0" - tapable "^1.0.0" - -errno@^0.1.3, errno@~0.1.1, errno@~0.1.7: - version "0.1.7" - resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.7.tgz#4684d71779ad39af177e3f007996f7c67c852618" - integrity sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg== - dependencies: - prr "~1.0.1" - -error-ex@^1.2.0, error-ex@^1.3.1: - version "1.3.2" - resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" - integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== - dependencies: - is-arrayish "^0.2.1" - -es-abstract@^1.17.0-next.1: - version "1.17.0" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.17.0.tgz#f42a517d0036a5591dbb2c463591dc8bb50309b1" - integrity sha512-yYkE07YF+6SIBmg1MsJ9dlub5L48Ek7X0qz+c/CPCHS9EBXfESorzng4cJQjJW5/pB6vDF41u7F8vUhLVDqIug== - dependencies: - es-to-primitive "^1.2.1" - function-bind "^1.1.1" - has "^1.0.3" - has-symbols "^1.0.1" - is-callable "^1.1.5" - is-regex "^1.0.5" - object-inspect "^1.7.0" - object-keys "^1.1.1" - object.assign "^4.1.0" - string.prototype.trimleft "^2.1.1" - string.prototype.trimright "^2.1.1" - -es-abstract@^1.5.0: - version "1.16.3" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.16.3.tgz#52490d978f96ff9f89ec15b5cf244304a5bca161" - integrity sha512-WtY7Fx5LiOnSYgF5eg/1T+GONaGmpvpPdCpSnYij+U2gDTL0UPfWrhDw7b2IYb+9NQJsYpCA0wOQvZfsd6YwRw== - dependencies: - es-to-primitive "^1.2.1" - function-bind "^1.1.1" - has "^1.0.3" - has-symbols "^1.0.1" - is-callable "^1.1.4" - is-regex "^1.0.4" - object-inspect "^1.7.0" - object-keys "^1.1.1" - string.prototype.trimleft "^2.1.0" - string.prototype.trimright "^2.1.0" - -es-to-primitive@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" - integrity sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA== - dependencies: - is-callable "^1.1.4" - is-date-object "^1.0.1" - is-symbol "^1.0.2" - -es5-ext@^0.10.35, es5-ext@^0.10.46, es5-ext@^0.10.50: - version "0.10.53" - resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.53.tgz#93c5a3acfdbef275220ad72644ad02ee18368de1" - integrity sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q== - dependencies: - es6-iterator "~2.0.3" - es6-symbol "~3.1.3" - next-tick "~1.0.0" - -es6-iterator@^2.0.1, es6-iterator@^2.0.3, es6-iterator@~2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.3.tgz#a7de889141a05a94b0854403b2d0a0fbfa98f3b7" - integrity sha1-p96IkUGgWpSwhUQDstCg+/qY87c= - dependencies: - d "1" - es5-ext "^0.10.35" - es6-symbol "^3.1.1" - -es6-symbol@^3.1.1, es6-symbol@~3.1.3: - version "3.1.3" - resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.3.tgz#bad5d3c1bcdac28269f4cb331e431c78ac705d18" - integrity sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA== - dependencies: - d "^1.0.1" - ext "^1.1.2" - -es6-weak-map@^2.0.1: - version "2.0.3" - resolved "https://registry.yarnpkg.com/es6-weak-map/-/es6-weak-map-2.0.3.tgz#b6da1f16cc2cc0d9be43e6bdbfc5e7dfcdf31d53" - integrity sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA== - dependencies: - d "1" - es5-ext "^0.10.46" - es6-iterator "^2.0.3" - es6-symbol "^3.1.1" - -escape-html@~1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" - integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg= - -escape-string-regexp@1.0.5, escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" - integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= - -escodegen@1.8.x: - version "1.8.1" - resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.8.1.tgz#5a5b53af4693110bebb0867aa3430dd3b70a1018" - integrity sha1-WltTr0aTEQvrsIZ6o0MN07cKEBg= - dependencies: - esprima "^2.7.1" - estraverse "^1.9.1" - esutils "^2.0.2" - optionator "^0.8.1" - optionalDependencies: - source-map "~0.2.0" - -escodegen@^1.9.1: - version "1.12.1" - resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.12.1.tgz#08770602a74ac34c7a90ca9229e7d51e379abc76" - integrity sha512-Q8t2YZ+0e0pc7NRVj3B4tSQ9rim1oi4Fh46k2xhJ2qOiEwhQfdjyEQddWdj7ZFaKmU+5104vn1qrcjEPWq+bgQ== - dependencies: - esprima "^3.1.3" - estraverse "^4.2.0" - esutils "^2.0.2" - optionator "^0.8.1" - optionalDependencies: - source-map "~0.6.1" - -eslint-scope@^4.0.3: - version "4.0.3" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-4.0.3.tgz#ca03833310f6889a3264781aa82e63eb9cfe7848" - integrity sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg== - dependencies: - esrecurse "^4.1.0" - estraverse "^4.1.1" - -esprima@2.7.x, esprima@^2.7.1: - version "2.7.3" - resolved "https://registry.yarnpkg.com/esprima/-/esprima-2.7.3.tgz#96e3b70d5779f6ad49cd032673d1c312767ba581" - integrity sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE= - -esprima@^3.1.3: - version "3.1.3" - resolved "https://registry.yarnpkg.com/esprima/-/esprima-3.1.3.tgz#fdca51cee6133895e3c88d535ce49dbff62a4633" - integrity sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM= - -esprima@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" - integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== - -esrecurse@^4.1.0: - version "4.2.1" - resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.2.1.tgz#007a3b9fdbc2b3bb87e4879ea19c92fdbd3942cf" - integrity sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ== - dependencies: - estraverse "^4.1.0" - -estraverse@^1.9.1: - version "1.9.3" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-1.9.3.tgz#af67f2dc922582415950926091a4005d29c9bb44" - integrity sha1-r2fy3JIlgkFZUJJgkaQAXSnJu0Q= - -estraverse@^4.1.0, estraverse@^4.1.1, estraverse@^4.2.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" - integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== - -esutils@^2.0.2: - version "2.0.3" - resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" - integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== - -etag@~1.8.1: - version "1.8.1" - resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" - integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc= - -eth-block-tracker@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/eth-block-tracker/-/eth-block-tracker-3.0.1.tgz#95cd5e763c7293e0b1b2790a2a39ac2ac188a5e1" - integrity sha512-WUVxWLuhMmsfenfZvFO5sbl1qFY2IqUlw/FPVmjjdElpqLsZtSG+wPe9Dz7W/sB6e80HgFKknOmKk2eNlznHug== - dependencies: - eth-query "^2.1.0" - ethereumjs-tx "^1.3.3" - ethereumjs-util "^5.1.3" - ethjs-util "^0.1.3" - json-rpc-engine "^3.6.0" - pify "^2.3.0" - tape "^4.6.3" - -eth-block-tracker@^4.4.2: - version "4.4.3" - resolved "https://registry.yarnpkg.com/eth-block-tracker/-/eth-block-tracker-4.4.3.tgz#766a0a0eb4a52c867a28328e9ae21353812cf626" - integrity sha512-A8tG4Z4iNg4mw5tP1Vung9N9IjgMNqpiMoJ/FouSFwNCGHv2X0mmOYwtQOJzki6XN7r7Tyo01S29p7b224I4jw== - dependencies: - "@babel/plugin-transform-runtime" "^7.5.5" - "@babel/runtime" "^7.5.5" - eth-query "^2.1.0" - json-rpc-random-id "^1.0.1" - pify "^3.0.0" - safe-event-emitter "^1.0.1" - -eth-ens-namehash@2.0.8: - version "2.0.8" - resolved "https://registry.yarnpkg.com/eth-ens-namehash/-/eth-ens-namehash-2.0.8.tgz#229ac46eca86d52e0c991e7cb2aef83ff0f68bcf" - integrity sha1-IprEbsqG1S4MmR58sq74P/D2i88= - dependencies: - idna-uts46-hx "^2.3.1" - js-sha3 "^0.5.7" - -eth-json-rpc-errors@^1.0.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/eth-json-rpc-errors/-/eth-json-rpc-errors-1.1.1.tgz#148377ef55155585981c21ff574a8937f9d6991f" - integrity sha512-WT5shJ5KfNqHi9jOZD+ID8I1kuYWNrigtZat7GOQkvwo99f8SzAVaEcWhJUv656WiZOAg3P1RiJQANtUmDmbIg== - dependencies: - fast-safe-stringify "^2.0.6" - -eth-json-rpc-errors@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/eth-json-rpc-errors/-/eth-json-rpc-errors-2.0.0.tgz#bdc19df8b80a820844709193372f0d75fb74fed8" - integrity sha512-casdSTVOxbC3ptfUdclJRvU0Sgmdm/QtezLku8l4iVR5wNFe+KF+tfnlm2I84xxpx7mkyyHeeUxmRkcB5Os6mw== - dependencies: - fast-safe-stringify "^2.0.6" - -eth-json-rpc-filters@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/eth-json-rpc-filters/-/eth-json-rpc-filters-4.1.1.tgz#15277c66790236d85f798f4d7dc6bab99a798cd2" - integrity sha512-GkXb2h6STznD+AmMzblwXgm1JMvjdK9PTIXG7BvIkTlXQ9g0QOxuU1iQRYHoslF9S30BYBSoLSisAYPdLggW+A== - dependencies: - await-semaphore "^0.1.3" - eth-json-rpc-middleware "^4.1.4" - eth-query "^2.1.2" - json-rpc-engine "^5.1.3" - lodash.flatmap "^4.5.0" - safe-event-emitter "^1.0.1" - -eth-json-rpc-infura@^3.1.0: - version "3.2.1" - resolved "https://registry.yarnpkg.com/eth-json-rpc-infura/-/eth-json-rpc-infura-3.2.1.tgz#26702a821067862b72d979c016fd611502c6057f" - integrity sha512-W7zR4DZvyTn23Bxc0EWsq4XGDdD63+XPUCEhV2zQvQGavDVC4ZpFDK4k99qN7bd7/fjj37+rxmuBOBeIqCA5Mw== - dependencies: - cross-fetch "^2.1.1" - eth-json-rpc-middleware "^1.5.0" - json-rpc-engine "^3.4.0" - json-rpc-error "^2.0.0" - -eth-json-rpc-infura@^4.0.1: - version "4.0.2" - resolved "https://registry.yarnpkg.com/eth-json-rpc-infura/-/eth-json-rpc-infura-4.0.2.tgz#8af1a1a2e9a0a82aaa302bbc96fb1a4c15d69b83" - integrity sha512-dvgOrci9lZqpjpp0hoC3Zfedhg3aIpLFVDH0TdlKxRlkhR75hTrKTwxghDrQwE0bn3eKrC8RsN1m/JdnIWltpw== - dependencies: - cross-fetch "^2.1.1" - eth-json-rpc-errors "^1.0.1" - eth-json-rpc-middleware "^4.1.4" - json-rpc-engine "^5.1.3" - -eth-json-rpc-middleware@^1.5.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/eth-json-rpc-middleware/-/eth-json-rpc-middleware-1.6.0.tgz#5c9d4c28f745ccb01630f0300ba945f4bef9593f" - integrity sha512-tDVCTlrUvdqHKqivYMjtFZsdD7TtpNLBCfKAcOpaVs7orBMS/A8HWro6dIzNtTZIR05FAbJ3bioFOnZpuCew9Q== - dependencies: - async "^2.5.0" - eth-query "^2.1.2" - eth-tx-summary "^3.1.2" - ethereumjs-block "^1.6.0" - ethereumjs-tx "^1.3.3" - ethereumjs-util "^5.1.2" - ethereumjs-vm "^2.1.0" - fetch-ponyfill "^4.0.0" - json-rpc-engine "^3.6.0" - json-rpc-error "^2.0.0" - json-stable-stringify "^1.0.1" - promise-to-callback "^1.0.0" - tape "^4.6.3" - -eth-json-rpc-middleware@^4.1.4, eth-json-rpc-middleware@^4.1.5: - version "4.3.0" - resolved "https://registry.yarnpkg.com/eth-json-rpc-middleware/-/eth-json-rpc-middleware-4.3.0.tgz#d3e72efb60b6f601f022ce01384481eaed552b6b" - integrity sha512-Acr+FaIHB0oIV0nWrCvepQghgA3FzYFvnMDXdTUeHQvAX/G6ioMbw1exGJs+6HirRjJ+MmkZqaArphx+PTrRNQ== - dependencies: - btoa "^1.2.1" - clone "^2.1.1" - eth-json-rpc-errors "^1.0.1" - eth-query "^2.1.2" - eth-sig-util "^1.4.2" - ethereumjs-block "^1.6.0" - ethereumjs-tx "^1.3.7" - ethereumjs-util "^5.1.2" - ethereumjs-vm "^2.6.0" - fetch-ponyfill "^4.0.0" - json-rpc-engine "^5.1.3" - json-stable-stringify "^1.0.1" - pify "^3.0.0" - safe-event-emitter "^1.0.1" - -eth-lib@0.2.7: - version "0.2.7" - resolved "https://registry.yarnpkg.com/eth-lib/-/eth-lib-0.2.7.tgz#2f93f17b1e23aec3759cd4a3fe20c1286a3fc1ca" - integrity sha1-L5Pxex4jrsN1nNSj/iDBKGo/wco= - dependencies: - bn.js "^4.11.6" - elliptic "^6.4.0" - xhr-request-promise "^0.1.2" - -eth-lib@0.2.8: - version "0.2.8" - resolved "https://registry.yarnpkg.com/eth-lib/-/eth-lib-0.2.8.tgz#b194058bef4b220ad12ea497431d6cb6aa0623c8" - integrity sha512-ArJ7x1WcWOlSpzdoTBX8vkwlkSQ85CjjifSZtV4co64vWxSV8geWfPI9x4SVYu3DSxnX4yWFVTtGL+j9DUFLNw== - dependencies: - bn.js "^4.11.6" - elliptic "^6.4.0" - xhr-request-promise "^0.1.2" - -eth-lib@^0.1.26: - version "0.1.29" - resolved "https://registry.yarnpkg.com/eth-lib/-/eth-lib-0.1.29.tgz#0c11f5060d42da9f931eab6199084734f4dbd1d9" - integrity sha512-bfttrr3/7gG4E02HoWTDUcDDslN003OlOoBxk9virpAZQ1ja/jDgwkWB8QfJF7ojuEowrqy+lzp9VcJG7/k5bQ== - dependencies: - bn.js "^4.11.6" - elliptic "^6.4.0" - nano-json-stream-parser "^0.1.2" - servify "^0.1.12" - ws "^3.0.0" - xhr-request-promise "^0.1.2" - -eth-query@^2.0.2, eth-query@^2.1.0, eth-query@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/eth-query/-/eth-query-2.1.2.tgz#d6741d9000106b51510c72db92d6365456a6da5e" - integrity sha1-1nQdkAAQa1FRDHLbktY2VFam2l4= - dependencies: - json-rpc-random-id "^1.0.0" - xtend "^4.0.1" - -eth-saddle@^0.1.25: - version "0.1.25" - resolved "https://registry.yarnpkg.com/eth-saddle/-/eth-saddle-0.1.25.tgz#8bbfefa6eabcdaca0c88e838fa60213e9fff9d8b" - integrity sha512-BUames0/ap3Cm7bJVjp0sFfTxKUv+xK+zbwZLYQghky9KrfowlURqBZgJHPxF3w9HyCh95UQBY5QsIeed1Ppqw== - dependencies: - "@0x/subproviders" "=6.0.0" - "@compound-finance/sol-coverage" "=4.0.10-alpha.7" - "@compound-finance/sol-tracing-utils" "=7.1.0-alpha.7" - "@types/jest" "^24.0.15" - ethereumjs-tx "2.1.2" - ethereumjs-util "5.2.0" - fast-glob "^3.2.2" - ganache-core "^2.13.2" - jest "^24.9.0" - jest-cli "^24.9.0" - jest-diff "^25.3.0" - jest-junit "^6.4.0" - ts-jest "^24.0.2" - typescript "^3.5.1" - web3 "^1.2.11" - web3-provider-engine "^15.0.4" - yargs "^13.2.4" - -eth-sig-util@2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/eth-sig-util/-/eth-sig-util-2.3.0.tgz#c54a6ac8e8796f7e25f59cf436982a930e645231" - integrity sha512-ugD1AvaggvKaZDgnS19W5qOfepjGc7qHrt7TrAaL54gJw9SHvgIXJ3r2xOMW30RWJZNP+1GlTOy5oye7yXA4xA== - dependencies: - buffer "^5.2.1" - elliptic "^6.4.0" - ethereumjs-abi "0.6.5" - ethereumjs-util "^5.1.1" - tweetnacl "^1.0.0" - tweetnacl-util "^0.15.0" - -eth-sig-util@^1.4.2: - version "1.4.2" - resolved "https://registry.yarnpkg.com/eth-sig-util/-/eth-sig-util-1.4.2.tgz#8d958202c7edbaae839707fba6f09ff327606210" - integrity sha1-jZWCAsftuq6Dlwf7pvCf8ydgYhA= - dependencies: - ethereumjs-abi "git+https://github.com/ethereumjs/ethereumjs-abi.git" - ethereumjs-util "^5.1.1" - -eth-tx-summary@^3.1.2: - version "3.2.4" - resolved "https://registry.yarnpkg.com/eth-tx-summary/-/eth-tx-summary-3.2.4.tgz#e10eb95eb57cdfe549bf29f97f1e4f1db679035c" - integrity sha512-NtlDnaVZah146Rm8HMRUNMgIwG/ED4jiqk0TME9zFheMl1jOp6jL1m0NKGjJwehXQ6ZKCPr16MTr+qspKpEXNg== - dependencies: - async "^2.1.2" - clone "^2.0.0" - concat-stream "^1.5.1" - end-of-stream "^1.1.0" - eth-query "^2.0.2" - ethereumjs-block "^1.4.1" - ethereumjs-tx "^1.1.1" - ethereumjs-util "^5.0.1" - ethereumjs-vm "^2.6.0" - through2 "^2.0.3" - -ethashjs@~0.0.7: - version "0.0.7" - resolved "https://registry.yarnpkg.com/ethashjs/-/ethashjs-0.0.7.tgz#30bfe4196726690a0c59d3b8272e70d4d0c34bae" - integrity sha1-ML/kGWcmaQoMWdO4Jy5w1NDDS64= - dependencies: - async "^1.4.2" - buffer-xor "^1.0.3" - ethereumjs-util "^4.0.1" - miller-rabin "^4.0.0" - -ethereum-bloom-filters@^1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/ethereum-bloom-filters/-/ethereum-bloom-filters-1.0.6.tgz#9cdebb3ec20de96ec4a434c6bad6ea5a513037aa" - integrity sha512-dE9CGNzgOOsdh7msZirvv8qjHtnHpvBlKe2647kM8v+yeF71IRso55jpojemvHV+jMjr48irPWxMRaHuOWzAFA== - dependencies: - js-sha3 "^0.8.0" - -ethereum-common@0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/ethereum-common/-/ethereum-common-0.2.0.tgz#13bf966131cce1eeade62a1b434249bb4cb120ca" - integrity sha512-XOnAR/3rntJgbCdGhqdaLIxDLWKLmsZOGhHdBKadEr6gEnJLH52k93Ou+TUdFaPN3hJc3isBZBal3U/XZ15abA== - -ethereum-common@^0.0.18: - version "0.0.18" - resolved "https://registry.yarnpkg.com/ethereum-common/-/ethereum-common-0.0.18.tgz#2fdc3576f232903358976eb39da783213ff9523f" - integrity sha1-L9w1dvIykDNYl26znaeDIT/5Uj8= - -ethereum-types@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/ethereum-types/-/ethereum-types-3.0.0.tgz#9fa3a98b8b9b64a0fab1864de7bc7fd7b1699fcd" - integrity sha512-jRSsiua+e4/89r7M3mqPcP1M2f3TgXxpVmWysy+7pEg2H4lwEQRWarbYfIpWp81NtxrcMQv5bMK+yR1MN4sDpg== - dependencies: - "@types/node" "*" - bignumber.js "~9.0.0" - -ethereum-types@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/ethereum-types/-/ethereum-types-3.2.0.tgz#5bd27cadc3c1b3c2e2bf94654fa2bc3618a4520f" - integrity sha512-osxikvWF2CuHauo2jiBpGalLXbCj5xWm2WcNr+Z4sNTk7z6DArPNXwsgANu2bA+aAsqSSF4NgsNx8JS1d3xdOQ== - dependencies: - "@types/node" "*" - bignumber.js "~9.0.0" - -ethereumjs-abi@0.6.5: - version "0.6.5" - resolved "https://registry.yarnpkg.com/ethereumjs-abi/-/ethereumjs-abi-0.6.5.tgz#5a637ef16ab43473fa72a29ad90871405b3f5241" - integrity sha1-WmN+8Wq0NHP6cqKa2QhxQFs/UkE= - dependencies: - bn.js "^4.10.0" - ethereumjs-util "^4.3.0" - -ethereumjs-abi@0.6.7: - version "0.6.7" - resolved "https://registry.yarnpkg.com/ethereumjs-abi/-/ethereumjs-abi-0.6.7.tgz#d1d1c5cdb8d910a7d97645ba9e93be5d153bba2e" - integrity sha512-EMLOA8ICO5yAaXDhjVEfYjsJIXYutY8ufTE93eEKwsVtp2usQreKwsDTJ9zvam3omYqNuffr8IONIqb2uUslGQ== - dependencies: - bn.js "^4.11.8" - ethereumjs-util "^6.0.0" - -"ethereumjs-abi@git+https://github.com/ethereumjs/ethereumjs-abi.git": - version "0.6.8" - resolved "git+https://github.com/ethereumjs/ethereumjs-abi.git#1cfbb13862f90f0b391d8a699544d5fe4dfb8c7b" - dependencies: - bn.js "^4.11.8" - ethereumjs-util "^6.0.0" - -ethereumjs-account@3.0.0, ethereumjs-account@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/ethereumjs-account/-/ethereumjs-account-3.0.0.tgz#728f060c8e0c6e87f1e987f751d3da25422570a9" - integrity sha512-WP6BdscjiiPkQfF9PVfMcwx/rDvfZTjFKY0Uwc09zSQr9JfIVH87dYIJu0gNhBhpmovV4yq295fdllS925fnBA== - dependencies: - ethereumjs-util "^6.0.0" - rlp "^2.2.1" - safe-buffer "^5.1.1" - -ethereumjs-account@^2.0.3: - version "2.0.5" - resolved "https://registry.yarnpkg.com/ethereumjs-account/-/ethereumjs-account-2.0.5.tgz#eeafc62de544cb07b0ee44b10f572c9c49e00a84" - integrity sha512-bgDojnXGjhMwo6eXQC0bY6UK2liSFUSMwwylOmQvZbSl/D7NXQ3+vrGO46ZeOgjGfxXmgIeVNDIiHw7fNZM4VA== - dependencies: - ethereumjs-util "^5.0.0" - rlp "^2.0.0" - safe-buffer "^5.1.1" - -ethereumjs-block@2.2.2, ethereumjs-block@^2.2.2, ethereumjs-block@~2.2.2: - version "2.2.2" - resolved "https://registry.yarnpkg.com/ethereumjs-block/-/ethereumjs-block-2.2.2.tgz#c7654be7e22df489fda206139ecd63e2e9c04965" - integrity sha512-2p49ifhek3h2zeg/+da6XpdFR3GlqY3BIEiqxGF8j9aSRIgkb7M1Ky+yULBKJOu8PAZxfhsYA+HxUk2aCQp3vg== - dependencies: - async "^2.0.1" - ethereumjs-common "^1.5.0" - ethereumjs-tx "^2.1.1" - ethereumjs-util "^5.0.0" - merkle-patricia-tree "^2.1.2" - -ethereumjs-block@^1.2.2, ethereumjs-block@^1.4.1, ethereumjs-block@^1.6.0: - version "1.7.1" - resolved "https://registry.yarnpkg.com/ethereumjs-block/-/ethereumjs-block-1.7.1.tgz#78b88e6cc56de29a6b4884ee75379b6860333c3f" - integrity sha512-B+sSdtqm78fmKkBq78/QLKJbu/4Ts4P2KFISdgcuZUPDm9x+N7qgBPIIFUGbaakQh8bzuquiRVbdmvPKqbILRg== - dependencies: - async "^2.0.1" - ethereum-common "0.2.0" - ethereumjs-tx "^1.2.2" - ethereumjs-util "^5.0.0" - merkle-patricia-tree "^2.1.2" - -ethereumjs-block@~2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/ethereumjs-block/-/ethereumjs-block-2.2.0.tgz#8c6c3ab4a5eff0a16d9785fbeedbe643f4dbcbef" - integrity sha512-Ye+uG/L2wrp364Zihdlr/GfC3ft+zG8PdHcRtsBFNNH1CkOhxOwdB8friBU85n89uRZ9eIMAywCq0F4CwT1wAw== - dependencies: - async "^2.0.1" - ethereumjs-common "^1.1.0" - ethereumjs-tx "^1.2.2" - ethereumjs-util "^5.0.0" - merkle-patricia-tree "^2.1.2" - -ethereumjs-blockchain@^4.0.3: - version "4.0.3" - resolved "https://registry.yarnpkg.com/ethereumjs-blockchain/-/ethereumjs-blockchain-4.0.3.tgz#e013034633a30ad2006728e8e2b21956b267b773" - integrity sha512-0nJWbyA+Gu0ZKZr/cywMtB/77aS/4lOVsIKbgUN2sFQYscXO5rPbUfrEe7G2Zhjp86/a0VqLllemDSTHvx3vZA== - dependencies: - async "^2.6.1" - ethashjs "~0.0.7" - ethereumjs-block "~2.2.2" - ethereumjs-common "^1.5.0" - ethereumjs-util "~6.1.0" - flow-stoplight "^1.0.0" - level-mem "^3.0.1" - lru-cache "^5.1.1" - rlp "^2.2.2" - semaphore "^1.1.0" - -ethereumjs-common@1.5.0, ethereumjs-common@^1.3.1, ethereumjs-common@^1.3.2, ethereumjs-common@^1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/ethereumjs-common/-/ethereumjs-common-1.5.0.tgz#d3e82fc7c47c0cef95047f431a99485abc9bb1cd" - integrity sha512-SZOjgK1356hIY7MRj3/ma5qtfr/4B5BL+G4rP/XSMYr2z1H5el4RX5GReYCKmQmYI/nSBmRnwrZ17IfHuG0viQ== - -ethereumjs-common@^1.1.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/ethereumjs-common/-/ethereumjs-common-1.4.0.tgz#a940685f88f3c2587e4061630fe720b089c965b8" - integrity sha512-ser2SAplX/YI5W2AnzU8wmSjKRy4KQd4uxInJ36BzjS3m18E/B9QedPUIresZN1CSEQb/RgNQ2gN7C/XbpTafA== - -ethereumjs-tx@2.1.2, ethereumjs-tx@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/ethereumjs-tx/-/ethereumjs-tx-2.1.2.tgz#5dfe7688bf177b45c9a23f86cf9104d47ea35fed" - integrity sha512-zZEK1onCeiORb0wyCXUvg94Ve5It/K6GD1K+26KfFKodiBiS6d9lfCXlUKGBBdQ+bv7Day+JK0tj1K+BeNFRAw== - dependencies: - ethereumjs-common "^1.5.0" - ethereumjs-util "^6.0.0" - -ethereumjs-tx@^1.1.1, ethereumjs-tx@^1.2.0, ethereumjs-tx@^1.2.2, ethereumjs-tx@^1.3.3, ethereumjs-tx@^1.3.5, ethereumjs-tx@^1.3.7: - version "1.3.7" - resolved "https://registry.yarnpkg.com/ethereumjs-tx/-/ethereumjs-tx-1.3.7.tgz#88323a2d875b10549b8347e09f4862b546f3d89a" - integrity sha512-wvLMxzt1RPhAQ9Yi3/HKZTn0FZYpnsmQdbKYfUUpi4j1SEIcbkd9tndVjcPrufY3V7j2IebOpC00Zp2P/Ay2kA== - dependencies: - ethereum-common "^0.0.18" - ethereumjs-util "^5.0.0" - -ethereumjs-tx@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/ethereumjs-tx/-/ethereumjs-tx-2.1.1.tgz#7d204e2b319156c9bc6cec67e9529424a26e8ccc" - integrity sha512-QtVriNqowCFA19X9BCRPMgdVNJ0/gMBS91TQb1DfrhsbR748g4STwxZptFAwfqehMyrF8rDwB23w87PQwru0wA== - dependencies: - ethereumjs-common "^1.3.1" - ethereumjs-util "^6.0.0" - -ethereumjs-util@5.2.0, ethereumjs-util@^5.0.0, ethereumjs-util@^5.0.1, ethereumjs-util@^5.1.1, ethereumjs-util@^5.1.2, ethereumjs-util@^5.1.3, ethereumjs-util@^5.1.5: - version "5.2.0" - resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-5.2.0.tgz#3e0c0d1741471acf1036052d048623dee54ad642" - integrity sha512-CJAKdI0wgMbQFLlLRtZKGcy/L6pzVRgelIZqRqNbuVFM3K9VEnyfbcvz0ncWMRNCe4kaHWjwRYQcYMucmwsnWA== - dependencies: - bn.js "^4.11.0" - create-hash "^1.1.2" - ethjs-util "^0.1.3" - keccak "^1.0.2" - rlp "^2.0.0" - safe-buffer "^5.1.1" - secp256k1 "^3.0.1" - -ethereumjs-util@6.2.0, ethereumjs-util@^6.0.0, ethereumjs-util@^6.2.0: - version "6.2.0" - resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-6.2.0.tgz#23ec79b2488a7d041242f01e25f24e5ad0357960" - integrity sha512-vb0XN9J2QGdZGIEKG2vXM+kUdEivUfU6Wmi5y0cg+LRhDYKnXIZ/Lz7XjFbHRR9VIKq2lVGLzGBkA++y2nOdOQ== - dependencies: - "@types/bn.js" "^4.11.3" - bn.js "^4.11.0" - create-hash "^1.1.2" - ethjs-util "0.1.6" - keccak "^2.0.0" - rlp "^2.2.3" - secp256k1 "^3.0.1" - -ethereumjs-util@^4.0.1, ethereumjs-util@^4.3.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-4.5.0.tgz#3e9428b317eebda3d7260d854fddda954b1f1bc6" - integrity sha1-PpQosxfuvaPXJg2FT93alUsfG8Y= - dependencies: - bn.js "^4.8.0" - create-hash "^1.1.2" - keccakjs "^0.2.0" - rlp "^2.0.0" - secp256k1 "^3.0.1" - -ethereumjs-util@~6.1.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-6.1.0.tgz#e9c51e5549e8ebd757a339cc00f5380507e799c8" - integrity sha512-URESKMFbDeJxnAxPppnk2fN6Y3BIatn9fwn76Lm8bQlt+s52TpG8dN9M66MLPuRAiAOIqL3dfwqWJf0sd0fL0Q== - dependencies: - bn.js "^4.11.0" - create-hash "^1.1.2" - ethjs-util "0.1.6" - keccak "^1.0.2" - rlp "^2.0.0" - safe-buffer "^5.1.1" - secp256k1 "^3.0.1" - -ethereumjs-vm@4.1.3: - version "4.1.3" - resolved "https://registry.yarnpkg.com/ethereumjs-vm/-/ethereumjs-vm-4.1.3.tgz#dc8eb45f47d775da9f0b2437d5e20896fdf66f37" - integrity sha512-RTrD0y7My4O6Qr1P2ZIsMfD6RzL6kU/RhBZ0a5XrPzAeR61crBS7or66ohDrvxDI/rDBxMi+6SnsELih6fzalw== - dependencies: - async "^2.1.2" - async-eventemitter "^0.2.2" - core-js-pure "^3.0.1" - ethereumjs-account "^3.0.0" - ethereumjs-block "^2.2.2" - ethereumjs-blockchain "^4.0.3" - ethereumjs-common "^1.5.0" - ethereumjs-tx "^2.1.2" - ethereumjs-util "^6.2.0" - fake-merkle-patricia-tree "^1.0.1" - functional-red-black-tree "^1.0.1" - merkle-patricia-tree "^2.3.2" - rustbn.js "~0.2.0" - safe-buffer "^5.1.1" - util.promisify "^1.0.0" - -ethereumjs-vm@^2.1.0, ethereumjs-vm@^2.3.4, ethereumjs-vm@^2.6.0: - version "2.6.0" - resolved "https://registry.yarnpkg.com/ethereumjs-vm/-/ethereumjs-vm-2.6.0.tgz#76243ed8de031b408793ac33907fb3407fe400c6" - integrity sha512-r/XIUik/ynGbxS3y+mvGnbOKnuLo40V5Mj1J25+HEO63aWYREIqvWeRO/hnROlMBE5WoniQmPmhiaN0ctiHaXw== - dependencies: - async "^2.1.2" - async-eventemitter "^0.2.2" - ethereumjs-account "^2.0.3" - ethereumjs-block "~2.2.0" - ethereumjs-common "^1.1.0" - ethereumjs-util "^6.0.0" - fake-merkle-patricia-tree "^1.0.1" - functional-red-black-tree "^1.0.1" - merkle-patricia-tree "^2.3.2" - rustbn.js "~0.2.0" - safe-buffer "^5.1.1" - -ethereumjs-wallet@0.6.3: - version "0.6.3" - resolved "https://registry.yarnpkg.com/ethereumjs-wallet/-/ethereumjs-wallet-0.6.3.tgz#b0eae6f327637c2aeb9ccb9047b982ac542e6ab1" - integrity sha512-qiXPiZOsStem+Dj/CQHbn5qex+FVkuPmGH7SvSnA9F3tdRDt8dLMyvIj3+U05QzVZNPYh4HXEdnzoYI4dZkr9w== - dependencies: - aes-js "^3.1.1" - bs58check "^2.1.2" - ethereumjs-util "^6.0.0" - hdkey "^1.1.0" - randombytes "^2.0.6" - safe-buffer "^5.1.2" - scrypt.js "^0.3.0" - utf8 "^3.0.0" - uuid "^3.3.2" - -ethers@4.0.0-beta.3: - version "4.0.0-beta.3" - resolved "https://registry.yarnpkg.com/ethers/-/ethers-4.0.0-beta.3.tgz#15bef14e57e94ecbeb7f9b39dd0a4bd435bc9066" - integrity sha512-YYPogooSknTwvHg3+Mv71gM/3Wcrx+ZpCzarBj3mqs9njjRkrOo2/eufzhHloOCo3JSoNI4TQJJ6yU5ABm3Uog== - dependencies: - "@types/node" "^10.3.2" - aes-js "3.0.0" - bn.js "^4.4.0" - elliptic "6.3.3" - hash.js "1.1.3" - js-sha3 "0.5.7" - scrypt-js "2.0.3" - setimmediate "1.0.4" - uuid "2.0.1" - xmlhttprequest "1.8.0" - -ethers@^5.0.8: - version "5.4.6" - resolved "https://registry.yarnpkg.com/ethers/-/ethers-5.4.6.tgz#fe0a023956b5502c947f58e82fbcf9a73e5e75b6" - integrity sha512-F7LXARyB/Px3AQC6/QKedWZ8eqCkgOLORqL4B/F0Mag/K+qJSFGqsR36EaOZ6fKg3ZonI+pdbhb4A8Knt/43jQ== - dependencies: - "@ethersproject/abi" "5.4.1" - "@ethersproject/abstract-provider" "5.4.1" - "@ethersproject/abstract-signer" "5.4.1" - "@ethersproject/address" "5.4.0" - "@ethersproject/base64" "5.4.0" - "@ethersproject/basex" "5.4.0" - "@ethersproject/bignumber" "5.4.1" - "@ethersproject/bytes" "5.4.0" - "@ethersproject/constants" "5.4.0" - "@ethersproject/contracts" "5.4.1" - "@ethersproject/hash" "5.4.0" - "@ethersproject/hdnode" "5.4.0" - "@ethersproject/json-wallets" "5.4.0" - "@ethersproject/keccak256" "5.4.0" - "@ethersproject/logger" "5.4.1" - "@ethersproject/networks" "5.4.2" - "@ethersproject/pbkdf2" "5.4.0" - "@ethersproject/properties" "5.4.1" - "@ethersproject/providers" "5.4.5" - "@ethersproject/random" "5.4.0" - "@ethersproject/rlp" "5.4.0" - "@ethersproject/sha2" "5.4.0" - "@ethersproject/signing-key" "5.4.0" - "@ethersproject/solidity" "5.4.0" - "@ethersproject/strings" "5.4.0" - "@ethersproject/transactions" "5.4.0" - "@ethersproject/units" "5.4.0" - "@ethersproject/wallet" "5.4.0" - "@ethersproject/web" "5.4.0" - "@ethersproject/wordlists" "5.4.0" - -ethers@~4.0.4: - version "4.0.40" - resolved "https://registry.yarnpkg.com/ethers/-/ethers-4.0.40.tgz#6e1963d10b5d336a13cd81b519c230cc17624653" - integrity sha512-MC9BtV7Hpq4dgFONEfanx9aU9GhhoWU270F+/wegHZXA7FR+2KXFdt36YIQYLmVY5ykUWswDxd+f9EVkIa7JOA== - dependencies: - aes-js "3.0.0" - bn.js "^4.4.0" - elliptic "6.5.2" - hash.js "1.1.3" - js-sha3 "0.5.7" - scrypt-js "2.0.4" - setimmediate "1.0.4" - uuid "2.0.1" - xmlhttprequest "1.8.0" - -ethjs-unit@0.1.6: - version "0.1.6" - resolved "https://registry.yarnpkg.com/ethjs-unit/-/ethjs-unit-0.1.6.tgz#c665921e476e87bce2a9d588a6fe0405b2c41699" - integrity sha1-xmWSHkduh7ziqdWIpv4EBbLEFpk= - dependencies: - bn.js "4.11.6" - number-to-bn "1.7.0" - -ethjs-util@0.1.6, ethjs-util@^0.1.3: - version "0.1.6" - resolved "https://registry.yarnpkg.com/ethjs-util/-/ethjs-util-0.1.6.tgz#f308b62f185f9fe6237132fb2a9818866a5cd536" - integrity sha512-CUnVOQq7gSpDHZVVrQW8ExxUETWrnrvXYvYz55wOU8Uj4VCgw56XC2B/fVqQN+f7gmrnRHSLVnFAwsCuNwji8w== - dependencies: - is-hex-prefixed "1.0.0" - strip-hex-prefix "1.0.0" - -eventemitter3@3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-3.1.2.tgz#2d3d48f9c346698fce83a85d7d664e98535df6e7" - integrity sha512-tvtQIeLVHjDkJYnzf2dgVMxfuSGJeM/7UCG17TT4EumTfNtF+0nebF/4zWOIkCreAbtNqhGEboB6BWrwqNaw4Q== - -eventemitter3@4.0.4: - version "4.0.4" - resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.4.tgz#b5463ace635a083d018bdc7c917b4c5f10a85384" - integrity sha512-rlaVLnVxtxvoyLsQQFBx53YmXHDxRIzzTLbdfxqi4yocpSjAxXwkU0cScM5JgSKMqEhrZpnvQ2D9gjylR0AimQ== - -events@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/events/-/events-3.0.0.tgz#9a0a0dfaf62893d92b875b8f2698ca4114973e88" - integrity sha512-Dc381HFWJzEOhQ+d8pkNon++bk9h6cdAoAj4iE6Q4y6xgTzySWXlKn05/TVNpjnfRqi/X0EpJEJohPjNI3zpVA== - -evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz#7fcbdb198dc71959432efe13842684e0525acb02" - integrity sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA== - dependencies: - md5.js "^1.3.4" - safe-buffer "^5.1.1" - -exec-sh@^0.3.2: - version "0.3.4" - resolved "https://registry.yarnpkg.com/exec-sh/-/exec-sh-0.3.4.tgz#3a018ceb526cc6f6df2bb504b2bfe8e3a4934ec5" - integrity sha512-sEFIkc61v75sWeOe72qyrqg2Qg0OuLESziUDk/O/z2qgS15y2gWVFrI6f2Qn/qw/0/NCfCEsmNA4zOjkwEZT1A== - -execa@^0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/execa/-/execa-0.7.0.tgz#944becd34cc41ee32a63a9faf27ad5a65fc59777" - integrity sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c= - dependencies: - cross-spawn "^5.0.1" - get-stream "^3.0.0" - is-stream "^1.1.0" - npm-run-path "^2.0.0" - p-finally "^1.0.0" - signal-exit "^3.0.0" - strip-eof "^1.0.0" - -execa@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/execa/-/execa-1.0.0.tgz#c6236a5bb4df6d6f15e88e7f017798216749ddd8" - integrity sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA== - dependencies: - cross-spawn "^6.0.0" - get-stream "^4.0.0" - is-stream "^1.1.0" - npm-run-path "^2.0.0" - p-finally "^1.0.0" - signal-exit "^3.0.0" - strip-eof "^1.0.0" - -exit@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" - integrity sha1-BjJjj42HfMghB9MKD/8aF8uhzQw= - -expand-brackets@^2.1.4: - version "2.1.4" - resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622" - integrity sha1-t3c14xXOMPa27/D4OwQVGiJEliI= - dependencies: - debug "^2.3.3" - define-property "^0.2.5" - extend-shallow "^2.0.1" - posix-character-classes "^0.1.0" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.1" - -expand-template@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/expand-template/-/expand-template-2.0.3.tgz#6e14b3fcee0f3a6340ecb57d2e8918692052a47c" - integrity sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg== - -expand-tilde@^2.0.0, expand-tilde@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/expand-tilde/-/expand-tilde-2.0.2.tgz#97e801aa052df02454de46b02bf621642cdc8502" - integrity sha1-l+gBqgUt8CRU3kawK/YhZCzchQI= - dependencies: - homedir-polyfill "^1.0.1" - -expect@^24.9.0: - version "24.9.0" - resolved "https://registry.yarnpkg.com/expect/-/expect-24.9.0.tgz#b75165b4817074fa4a157794f46fe9f1ba15b6ca" - integrity sha512-wvVAx8XIol3Z5m9zvZXiyZOQ+sRJqNTIm6sGjdWlaZIeupQGO3WbYI+15D/AmEwZywL6wtJkbAbJtzkOfBuR0Q== - dependencies: - "@jest/types" "^24.9.0" - ansi-styles "^3.2.0" - jest-get-type "^24.9.0" - jest-matcher-utils "^24.9.0" - jest-message-util "^24.9.0" - jest-regex-util "^24.9.0" - -express@^4.14.0, express@^4.16.3: - version "4.17.1" - resolved "https://registry.yarnpkg.com/express/-/express-4.17.1.tgz#4491fc38605cf51f8629d39c2b5d026f98a4c134" - integrity sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g== - dependencies: - accepts "~1.3.7" - array-flatten "1.1.1" - body-parser "1.19.0" - content-disposition "0.5.3" - content-type "~1.0.4" - cookie "0.4.0" - cookie-signature "1.0.6" - debug "2.6.9" - depd "~1.1.2" - encodeurl "~1.0.2" - escape-html "~1.0.3" - etag "~1.8.1" - finalhandler "~1.1.2" - fresh "0.5.2" - merge-descriptors "1.0.1" - methods "~1.1.2" - on-finished "~2.3.0" - parseurl "~1.3.3" - path-to-regexp "0.1.7" - proxy-addr "~2.0.5" - qs "6.7.0" - range-parser "~1.2.1" - safe-buffer "5.1.2" - send "0.17.1" - serve-static "1.14.1" - setprototypeof "1.1.1" - statuses "~1.5.0" - type-is "~1.6.18" - utils-merge "1.0.1" - vary "~1.1.2" - -ext@^1.1.2: - version "1.4.0" - resolved "https://registry.yarnpkg.com/ext/-/ext-1.4.0.tgz#89ae7a07158f79d35517882904324077e4379244" - integrity sha512-Key5NIsUxdqKg3vIsdw9dSuXpPCQ297y6wBjL30edxwPgt2E44WcWBZey/ZvUc6sERLTxKdyCu4gZFmUbk1Q7A== - dependencies: - type "^2.0.0" - -extend-shallow@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" - integrity sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8= - dependencies: - is-extendable "^0.1.0" - -extend-shallow@^3.0.0, extend-shallow@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-3.0.2.tgz#26a71aaf073b39fb2127172746131c2704028db8" - integrity sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg= - dependencies: - assign-symbols "^1.0.0" - is-extendable "^1.0.1" - -extend@^3.0.0, extend@~3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" - integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== - -extglob@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543" - integrity sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw== - dependencies: - array-unique "^0.3.2" - define-property "^1.0.0" - expand-brackets "^2.1.4" - extend-shallow "^2.0.1" - fragment-cache "^0.2.1" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.1" - -extsprintf@1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" - integrity sha1-lpGEQOMEGnpBT4xS48V06zw+HgU= - -extsprintf@^1.2.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f" - integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8= - -fake-merkle-patricia-tree@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/fake-merkle-patricia-tree/-/fake-merkle-patricia-tree-1.0.1.tgz#4b8c3acfb520afadf9860b1f14cd8ce3402cddd3" - integrity sha1-S4w6z7Ugr635hgsfFM2M40As3dM= - dependencies: - checkpoint-store "^1.1.0" - -fancy-log@^1.3.2: - version "1.3.3" - resolved "https://registry.yarnpkg.com/fancy-log/-/fancy-log-1.3.3.tgz#dbc19154f558690150a23953a0adbd035be45fc7" - integrity sha512-k9oEhlyc0FrVh25qYuSELjr8oxsCoc4/LEZfg2iJJrfEk/tZL9bCoJE47gqAvI2m/AUjluCS4+3I0eTx8n3AEw== - dependencies: - ansi-gray "^0.1.1" - color-support "^1.1.3" - parse-node-version "^1.0.0" - time-stamp "^1.0.0" - -fast-deep-equal@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49" - integrity sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk= - -fast-deep-equal@^3.1.1: - version "3.1.3" - resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" - integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== - -fast-glob@^3.2.2: - version "3.2.2" - resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.2.tgz#ade1a9d91148965d4bf7c51f72e1ca662d32e63d" - integrity sha512-UDV82o4uQyljznxwMxyVRJgZZt3O5wENYojjzbaGEGZgeOxkLFf+V4cnUD+krzb2F72E18RhamkMZ7AdeggF7A== - dependencies: - "@nodelib/fs.stat" "^2.0.2" - "@nodelib/fs.walk" "^1.2.3" - glob-parent "^5.1.0" - merge2 "^1.3.0" - micromatch "^4.0.2" - picomatch "^2.2.1" - -fast-json-stable-stringify@2.x: - version "2.1.0" - resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" - integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== - -fast-json-stable-stringify@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2" - integrity sha1-1RQsDK7msRifh9OnYREGT4bIu/I= - -fast-levenshtein@~2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" - integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= - -fast-safe-stringify@^2.0.6: - version "2.0.7" - resolved "https://registry.yarnpkg.com/fast-safe-stringify/-/fast-safe-stringify-2.0.7.tgz#124aa885899261f68aedb42a7c080de9da608743" - integrity sha512-Utm6CdzT+6xsDk2m8S6uL8VHxNwI6Jub+e9NYTcAms28T84pTa25GJQV9j0CY0N1rM8hK4x6grpF2BQf+2qwVA== - -fastq@^1.6.0: - version "1.7.0" - resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.7.0.tgz#fcd79a08c5bd7ec5b55cd3f5c4720db551929801" - integrity sha512-YOadQRnHd5q6PogvAR/x62BGituF2ufiEA6s8aavQANw5YKHERI4AREboX6KotzP8oX2klxYF2wcV/7bn1clfQ== - dependencies: - reusify "^1.0.4" - -fb-watchman@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.1.tgz#fc84fb39d2709cf3ff6d743706157bb5708a8a85" - integrity sha512-DkPJKQeY6kKwmuMretBhr7G6Vodr7bFwDYTXIkfG1gjvNpaxBTQV3PbXg6bR1c1UP4jPOX0jHUbbHANL9vRjVg== - dependencies: - bser "2.1.1" - -fd-slicer@~1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.1.0.tgz#25c7c89cb1f9077f8891bbe61d8f390eae256f1e" - integrity sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4= - dependencies: - pend "~1.2.0" - -fetch-ponyfill@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/fetch-ponyfill/-/fetch-ponyfill-4.1.0.tgz#ae3ce5f732c645eab87e4ae8793414709b239893" - integrity sha1-rjzl9zLGReq4fkroeTQUcJsjmJM= - dependencies: - node-fetch "~1.7.1" - -figgy-pudding@^3.5.1: - version "3.5.1" - resolved "https://registry.yarnpkg.com/figgy-pudding/-/figgy-pudding-3.5.1.tgz#862470112901c727a0e495a80744bd5baa1d6790" - integrity sha512-vNKxJHTEKNThjfrdJwHc7brvM6eVevuO5nTj6ez8ZQ1qbXTvGthucRF7S4vf2cr71QVnT70V34v0S1DyQsti0w== - -file-type@^3.8.0: - version "3.9.0" - resolved "https://registry.yarnpkg.com/file-type/-/file-type-3.9.0.tgz#257a078384d1db8087bc449d107d52a52672b9e9" - integrity sha1-JXoHg4TR24CHvESdEH1SpSZyuek= - -file-type@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/file-type/-/file-type-5.2.0.tgz#2ddbea7c73ffe36368dfae49dc338c058c2b8ad6" - integrity sha1-LdvqfHP/42No365J3DOMBYwritY= - -file-type@^6.1.0: - version "6.2.0" - resolved "https://registry.yarnpkg.com/file-type/-/file-type-6.2.0.tgz#e50cd75d356ffed4e306dc4f5bcf52a79903a919" - integrity sha512-YPcTBDV+2Tm0VqjybVd32MHdlEGAtuxS3VAYsumFokDSMG+ROT5wawGlnHDoz7bfMcMDt9hxuXvXwoKUx2fkOg== - -file-uri-to-path@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd" - integrity sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw== - -filesize@^3.6.1: - version "3.6.1" - resolved "https://registry.yarnpkg.com/filesize/-/filesize-3.6.1.tgz#090bb3ee01b6f801a8a8be99d31710b3422bb317" - integrity sha512-7KjR1vv6qnicaPMi1iiTcI85CyYwRO/PSFCu6SvqL8jN2Wjt/NIYQTFtFs7fSDCYOstUkEWIQGFUg5YZQfjlcg== - -fill-range@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" - integrity sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc= - dependencies: - extend-shallow "^2.0.1" - is-number "^3.0.0" - repeat-string "^1.6.1" - to-regex-range "^2.1.0" - -fill-range@^7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" - integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== - dependencies: - to-regex-range "^5.0.1" - -finalhandler@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.2.tgz#b7e7d000ffd11938d0fdb053506f6ebabe9f587d" - integrity sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA== - dependencies: - debug "2.6.9" - encodeurl "~1.0.2" - escape-html "~1.0.3" - on-finished "~2.3.0" - parseurl "~1.3.3" - statuses "~1.5.0" - unpipe "~1.0.0" - -find-cache-dir@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-2.1.0.tgz#8d0f94cd13fe43c6c7c261a0d86115ca918c05f7" - integrity sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ== - dependencies: - commondir "^1.0.1" - make-dir "^2.0.0" - pkg-dir "^3.0.0" - -find-up@^1.0.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f" - integrity sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8= - dependencies: - path-exists "^2.0.0" - pinkie-promise "^2.0.0" - -find-up@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" - integrity sha1-RdG35QbHF93UgndaK3eSCjwMV6c= - dependencies: - locate-path "^2.0.0" - -find-up@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" - integrity sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg== - dependencies: - locate-path "^3.0.0" - -findup-sync@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/findup-sync/-/findup-sync-2.0.0.tgz#9326b1488c22d1a6088650a86901b2d9a90a2cbc" - integrity sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw= - dependencies: - detect-file "^1.0.0" - is-glob "^3.1.0" - micromatch "^3.0.4" - resolve-dir "^1.0.1" - -findup-sync@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/findup-sync/-/findup-sync-3.0.0.tgz#17b108f9ee512dfb7a5c7f3c8b27ea9e1a9c08d1" - integrity sha512-YbffarhcicEhOrm4CtrwdKBdCuz576RLdhJDsIfvNtxUuhdRet1qZcsMjqbePtAseKdAnDyM/IyXbu7PRPRLYg== - dependencies: - detect-file "^1.0.0" - is-glob "^4.0.0" - micromatch "^3.0.4" - resolve-dir "^1.0.1" - -fined@^1.0.1: - version "1.2.0" - resolved "https://registry.yarnpkg.com/fined/-/fined-1.2.0.tgz#d00beccf1aa2b475d16d423b0238b713a2c4a37b" - integrity sha512-ZYDqPLGxDkDhDZBjZBb+oD1+j0rA4E0pXY50eplAAOPg2N/gUBSSk5IM1/QhPfyVo19lJ+CvXpqfvk+b2p/8Ng== - dependencies: - expand-tilde "^2.0.2" - is-plain-object "^2.0.3" - object.defaults "^1.1.0" - object.pick "^1.2.0" - parse-filepath "^1.0.1" - -flagged-respawn@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/flagged-respawn/-/flagged-respawn-1.0.1.tgz#e7de6f1279ddd9ca9aac8a5971d618606b3aab41" - integrity sha512-lNaHNVymajmk0OJMBn8fVUAU1BtDeKIqKoVhk4xAALB57aALg6b4W0MfJ/cUE0g9YBXy5XhSlPIpYIJ7HaY/3Q== - -flow-stoplight@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/flow-stoplight/-/flow-stoplight-1.0.0.tgz#4a292c5bcff8b39fa6cc0cb1a853d86f27eeff7b" - integrity sha1-SiksW8/4s5+mzAyxqFPYbyfu/3s= - -flush-write-stream@^1.0.0, flush-write-stream@^1.0.2: - version "1.1.1" - resolved "https://registry.yarnpkg.com/flush-write-stream/-/flush-write-stream-1.1.1.tgz#8dd7d873a1babc207d94ead0c2e0e44276ebf2e8" - integrity sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w== - dependencies: - inherits "^2.0.3" - readable-stream "^2.3.6" - -for-each@~0.3.3: - version "0.3.3" - resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e" - integrity sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw== - dependencies: - is-callable "^1.1.3" - -for-in@^1.0.1, for-in@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" - integrity sha1-gQaNKVqBQuwKxybG4iAMMPttXoA= - -for-own@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/for-own/-/for-own-1.0.0.tgz#c63332f415cedc4b04dbfe70cf836494c53cb44b" - integrity sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs= - dependencies: - for-in "^1.0.1" - -forever-agent@~0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" - integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE= - -form-data@~2.3.2: - version "2.3.3" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6" - integrity sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ== - dependencies: - asynckit "^0.4.0" - combined-stream "^1.0.6" - mime-types "^2.1.12" - -forwarded@~0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.2.tgz#98c23dab1175657b8c0573e8ceccd91b0ff18c84" - integrity sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ= - -fragment-cache@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19" - integrity sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk= - dependencies: - map-cache "^0.2.2" - -fresh@0.5.2: - version "0.5.2" - resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" - integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac= - -from2@^2.1.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/from2/-/from2-2.3.0.tgz#8bfb5502bde4a4d36cfdeea007fcca21d7e382af" - integrity sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8= - dependencies: - inherits "^2.0.1" - readable-stream "^2.0.0" - -fs-constants@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad" - integrity sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow== - -fs-extra@^0.30.0: - version "0.30.0" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-0.30.0.tgz#f233ffcc08d4da7d432daa449776989db1df93f0" - integrity sha1-8jP/zAjU2n1DLapEl3aYnbHfk/A= - dependencies: - graceful-fs "^4.1.2" - jsonfile "^2.1.0" - klaw "^1.0.0" - path-is-absolute "^1.0.0" - rimraf "^2.2.8" - -fs-extra@^4.0.2: - version "4.0.3" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-4.0.3.tgz#0d852122e5bc5beb453fb028e9c0c9bf36340c94" - integrity sha512-q6rbdDd1o2mAnQreO7YADIxf/Whx4AHBiRf6d+/cVT8h44ss+lHgxf1FemcqDnQt9X3ct4McHr+JMGlYSsK7Cg== - dependencies: - graceful-fs "^4.1.2" - jsonfile "^4.0.0" - universalify "^0.1.0" - -fs-minipass@^1.2.5: - version "1.2.7" - resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.7.tgz#ccff8570841e7fe4265693da88936c55aed7f7c7" - integrity sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA== - dependencies: - minipass "^2.6.0" - -fs-mkdirp-stream@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/fs-mkdirp-stream/-/fs-mkdirp-stream-1.0.0.tgz#0b7815fc3201c6a69e14db98ce098c16935259eb" - integrity sha1-C3gV/DIBxqaeFNuYzgmMFpNSWes= - dependencies: - graceful-fs "^4.1.11" - through2 "^2.0.3" - -fs-write-stream-atomic@^1.0.8: - version "1.0.10" - resolved "https://registry.yarnpkg.com/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz#b47df53493ef911df75731e70a9ded0189db40c9" - integrity sha1-tH31NJPvkR33VzHnCp3tAYnbQMk= - dependencies: - graceful-fs "^4.1.2" - iferr "^0.1.5" - imurmurhash "^0.1.4" - readable-stream "1 || 2" - -fs.realpath@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" - integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= - -fsevents@^1.2.7: - version "1.2.9" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.9.tgz#3f5ed66583ccd6f400b5a00db6f7e861363e388f" - integrity sha512-oeyj2H3EjjonWcFjD5NvZNE9Rqe4UW+nQBU2HNeKw0koVLEFIhtyETyAakeAM3de7Z/SW5kcA+fZUait9EApnw== - dependencies: - nan "^2.12.1" - node-pre-gyp "^0.12.0" - -fsevents@~2.1.1: - version "2.1.2" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.1.2.tgz#4c0a1fb34bc68e543b4b82a9ec392bfbda840805" - integrity sha512-R4wDiBwZ0KzpgOWetKDug1FZcYhqYnUYKtfZYt4mD5SBz76q0KR4Q9o7GIPamsVPGmW3EYPPJ0dOOjvx32ldZA== - -fsevents@~2.1.2: - version "2.1.3" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.1.3.tgz#fb738703ae8d2f9fe900c33836ddebee8b97f23e" - integrity sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ== - -function-bind@^1.0.2, function-bind@^1.1.1, function-bind@~1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" - integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== - -functional-red-black-tree@^1.0.1, functional-red-black-tree@~1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" - integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= - -ganache-core@^2.10.2, ganache-core@^2.13.2, ganache-core@^2.6.0, "ganache-core@github:compound-finance/ganache-core.git#jflatow/unbreak-fork": - version "2.10.2" - resolved "https://codeload.github.com/compound-finance/ganache-core/tar.gz/4c7e063f6d423e1b3850f4cb328029e819670a64" - dependencies: - abstract-leveldown "3.0.0" - async "2.6.2" - bip39 "2.5.0" - cachedown "1.0.0" - clone "2.1.2" - debug "3.2.6" - encoding-down "5.0.4" - eth-sig-util "2.3.0" - ethereumjs-abi "0.6.7" - ethereumjs-account "3.0.0" - ethereumjs-block "2.2.2" - ethereumjs-common "1.5.0" - ethereumjs-tx "2.1.2" - ethereumjs-util "6.2.0" - ethereumjs-vm "4.1.3" - heap "0.2.6" - level-sublevel "6.6.4" - levelup "3.1.1" - lodash "4.17.14" - merkle-patricia-tree "2.3.2" - seedrandom "3.0.1" - source-map-support "0.5.12" - tmp "0.1.0" - web3-provider-engine "14.2.1" - websocket "1.0.29" - optionalDependencies: - ethereumjs-wallet "0.6.3" - web3 "1.2.4" - -gauge@~2.7.3: - version "2.7.4" - resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" - integrity sha1-LANAXHU4w51+s3sxcCLjJfsBi/c= - dependencies: - aproba "^1.0.3" - console-control-strings "^1.0.0" - has-unicode "^2.0.0" - object-assign "^4.1.0" - signal-exit "^3.0.0" - string-width "^1.0.1" - strip-ansi "^3.0.1" - wide-align "^1.1.0" - -get-caller-file@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.3.tgz#f978fa4c90d1dfe7ff2d6beda2a515e713bdcf4a" - integrity sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w== - -get-caller-file@^2.0.1: - version "2.0.5" - resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" - integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== - -get-func-name@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.0.tgz#ead774abee72e20409433a066366023dd6887a41" - integrity sha1-6td0q+5y4gQJQzoGY2YCPdaIekE= - -get-stream@^2.2.0: - version "2.3.1" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-2.3.1.tgz#5f38f93f346009666ee0150a054167f91bdd95de" - integrity sha1-Xzj5PzRgCWZu4BUKBUFn+Rvdld4= - dependencies: - object-assign "^4.0.1" - pinkie-promise "^2.0.0" - -get-stream@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" - integrity sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ= - -get-stream@^4.0.0, get-stream@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" - integrity sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w== - dependencies: - pump "^3.0.0" - -get-stream@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.1.0.tgz#01203cdc92597f9b909067c3e656cc1f4d3c4dc9" - integrity sha512-EXr1FOzrzTfGeL0gQdeFEvOMm2mzMOglyiOXSTpPC+iAjAKftbr3jpCMWynogwYnM+eSj9sHGc6wjIcDvYiygw== - dependencies: - pump "^3.0.0" - -get-value@^2.0.3, get-value@^2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" - integrity sha1-3BXKHGcjh8p2vTesCjlbogQqLCg= - -getpass@^0.1.1: - version "0.1.7" - resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" - integrity sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo= - dependencies: - assert-plus "^1.0.0" - -github-from-package@0.0.0: - version "0.0.0" - resolved "https://registry.yarnpkg.com/github-from-package/-/github-from-package-0.0.0.tgz#97fb5d96bfde8973313f20e8288ef9a167fa64ce" - integrity sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4= - -glob-parent@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae" - integrity sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4= - dependencies: - is-glob "^3.1.0" - path-dirname "^1.0.0" - -glob-parent@^5.1.0: - version "5.1.1" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.1.tgz#b6c1ef417c4e5663ea498f1c45afac6916bbc229" - integrity sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ== - dependencies: - is-glob "^4.0.1" - -glob-parent@~5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.0.tgz#5f4c1d1e748d30cd73ad2944b3577a81b081e8c2" - integrity sha512-qjtRgnIVmOfnKUE3NJAQEdk+lKrxfw8t5ke7SXtfMTHcjsBfOfWXCQfdb30zfDoZQ2IRSIiidmjtbHZPZ++Ihw== - dependencies: - is-glob "^4.0.1" - -glob-stream@^6.1.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/glob-stream/-/glob-stream-6.1.0.tgz#7045c99413b3eb94888d83ab46d0b404cc7bdde4" - integrity sha1-cEXJlBOz65SIjYOrRtC0BMx73eQ= - dependencies: - extend "^3.0.0" - glob "^7.1.1" - glob-parent "^3.1.0" - is-negated-glob "^1.0.0" - ordered-read-streams "^1.0.0" - pumpify "^1.3.5" - readable-stream "^2.1.5" - remove-trailing-separator "^1.0.1" - to-absolute-glob "^2.0.0" - unique-stream "^2.0.2" - -glob-watcher@^5.0.3: - version "5.0.3" - resolved "https://registry.yarnpkg.com/glob-watcher/-/glob-watcher-5.0.3.tgz#88a8abf1c4d131eb93928994bc4a593c2e5dd626" - integrity sha512-8tWsULNEPHKQ2MR4zXuzSmqbdyV5PtwwCaWSGQ1WwHsJ07ilNeN1JB8ntxhckbnpSHaf9dXFUHzIWvm1I13dsg== - dependencies: - anymatch "^2.0.0" - async-done "^1.2.0" - chokidar "^2.0.0" - is-negated-glob "^1.0.0" - just-debounce "^1.0.0" - object.defaults "^1.1.0" - -glob@7.1.2: - version "7.1.2" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" - integrity sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.4" - once "^1.3.0" - path-is-absolute "^1.0.0" - -glob@^5.0.15: - version "5.0.15" - resolved "https://registry.yarnpkg.com/glob/-/glob-5.0.15.tgz#1bc936b9e02f4a603fcc222ecf7633d30b8b93b1" - integrity sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E= - dependencies: - inflight "^1.0.4" - inherits "2" - minimatch "2 || 3" - once "^1.3.0" - path-is-absolute "^1.0.0" - -glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@~7.1.4: - version "7.1.6" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" - integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.4" - once "^1.3.0" - path-is-absolute "^1.0.0" - -global-modules@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-1.0.0.tgz#6d770f0eb523ac78164d72b5e71a8877265cc3ea" - integrity sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg== - dependencies: - global-prefix "^1.0.1" - is-windows "^1.0.1" - resolve-dir "^1.0.0" - -global-modules@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-2.0.0.tgz#997605ad2345f27f51539bea26574421215c7780" - integrity sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A== - dependencies: - global-prefix "^3.0.0" - -global-prefix@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/global-prefix/-/global-prefix-1.0.2.tgz#dbf743c6c14992593c655568cb66ed32c0122ebe" - integrity sha1-2/dDxsFJklk8ZVVoy2btMsASLr4= - dependencies: - expand-tilde "^2.0.2" - homedir-polyfill "^1.0.1" - ini "^1.3.4" - is-windows "^1.0.1" - which "^1.2.14" - -global-prefix@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/global-prefix/-/global-prefix-3.0.0.tgz#fc85f73064df69f50421f47f883fe5b913ba9b97" - integrity sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg== - dependencies: - ini "^1.3.5" - kind-of "^6.0.2" - which "^1.3.1" - -global@~4.3.0: - version "4.3.2" - resolved "https://registry.yarnpkg.com/global/-/global-4.3.2.tgz#e76989268a6c74c38908b1305b10fc0e394e9d0f" - integrity sha1-52mJJopsdMOJCLEwWxD8DjlOnQ8= - dependencies: - min-document "^2.19.0" - process "~0.5.1" - -globals@^11.1.0: - version "11.12.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" - integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== - -globals@^9.18.0: - version "9.18.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a" - integrity sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ== - -glogg@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/glogg/-/glogg-1.0.2.tgz#2d7dd702beda22eb3bffadf880696da6d846313f" - integrity sha512-5mwUoSuBk44Y4EshyiqcH95ZntbDdTQqA3QYSrxmzj28Ai0vXBGMH1ApSANH14j2sIRtqCEyg6PfsuP7ElOEDA== - dependencies: - sparkles "^1.0.0" - -got@9.6.0: - version "9.6.0" - resolved "https://registry.yarnpkg.com/got/-/got-9.6.0.tgz#edf45e7d67f99545705de1f7bbeeeb121765ed85" - integrity sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q== - dependencies: - "@sindresorhus/is" "^0.14.0" - "@szmarczak/http-timer" "^1.1.2" - cacheable-request "^6.0.0" - decompress-response "^3.3.0" - duplexer3 "^0.1.4" - get-stream "^4.1.0" - lowercase-keys "^1.0.1" - mimic-response "^1.0.1" - p-cancelable "^1.0.0" - to-readable-stream "^1.0.0" - url-parse-lax "^3.0.0" - -got@^7.1.0: - version "7.1.0" - resolved "https://registry.yarnpkg.com/got/-/got-7.1.0.tgz#05450fd84094e6bbea56f451a43a9c289166385a" - integrity sha512-Y5WMo7xKKq1muPsxD+KmrR8DH5auG7fBdDVueZwETwV6VytKyU9OX/ddpq2/1hp1vIPvVb4T81dKQz3BivkNLw== - dependencies: - decompress-response "^3.2.0" - duplexer3 "^0.1.4" - get-stream "^3.0.0" - is-plain-obj "^1.1.0" - is-retry-allowed "^1.0.0" - is-stream "^1.0.0" - isurl "^1.0.0-alpha5" - lowercase-keys "^1.0.0" - p-cancelable "^0.3.0" - p-timeout "^1.1.1" - safe-buffer "^5.0.1" - timed-out "^4.0.0" - url-parse-lax "^1.0.0" - url-to-options "^1.0.1" - -graceful-fs@^4.0.0, graceful-fs@^4.1.10, graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9: - version "4.2.3" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.3.tgz#4a12ff1b60376ef09862c2093edd908328be8423" - integrity sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ== - -"graceful-readlink@>= 1.0.0": - version "1.0.1" - resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725" - integrity sha1-TK+tdrxi8C+gObL5Tpo906ORpyU= - -growl@1.10.3: - version "1.10.3" - resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.3.tgz#1926ba90cf3edfe2adb4927f5880bc22c66c790f" - integrity sha512-hKlsbA5Vu3xsh1Cg3J7jSmX/WaW6A5oBeqzM88oNbCRQFz+zUaXm6yxS4RVytp1scBoJzSYl4YAEOQIt6O8V1Q== - -growly@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/growly/-/growly-1.3.0.tgz#f10748cbe76af964b7c96c93c6bcc28af120c081" - integrity sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE= - -gulp-cli@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/gulp-cli/-/gulp-cli-2.2.0.tgz#5533126eeb7fe415a7e3e84a297d334d5cf70ebc" - integrity sha512-rGs3bVYHdyJpLqR0TUBnlcZ1O5O++Zs4bA0ajm+zr3WFCfiSLjGwoCBqFs18wzN+ZxahT9DkOK5nDf26iDsWjA== - dependencies: - ansi-colors "^1.0.1" - archy "^1.0.0" - array-sort "^1.0.0" - color-support "^1.1.3" - concat-stream "^1.6.0" - copy-props "^2.0.1" - fancy-log "^1.3.2" - gulplog "^1.0.0" - interpret "^1.1.0" - isobject "^3.0.1" - liftoff "^3.1.0" - matchdep "^2.0.0" - mute-stdout "^1.0.0" - pretty-hrtime "^1.0.0" - replace-homedir "^1.0.0" - semver-greatest-satisfied-range "^1.1.0" - v8flags "^3.0.1" - yargs "^7.1.0" - -gulp@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/gulp/-/gulp-4.0.2.tgz#543651070fd0f6ab0a0650c6a3e6ff5a7cb09caa" - integrity sha512-dvEs27SCZt2ibF29xYgmnwwCYZxdxhQ/+LFWlbAW8y7jt68L/65402Lz3+CKy0Ov4rOs+NERmDq7YlZaDqUIfA== - dependencies: - glob-watcher "^5.0.3" - gulp-cli "^2.2.0" - undertaker "^1.2.1" - vinyl-fs "^3.0.0" - -gulplog@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/gulplog/-/gulplog-1.0.0.tgz#e28c4d45d05ecbbed818363ce8f9c5926229ffe5" - integrity sha1-4oxNRdBey77YGDY86PnFkmIp/+U= - dependencies: - glogg "^1.0.0" - -gzip-size@^5.0.0: - version "5.1.1" - resolved "https://registry.yarnpkg.com/gzip-size/-/gzip-size-5.1.1.tgz#cb9bee692f87c0612b232840a873904e4c135274" - integrity sha512-FNHi6mmoHvs1mxZAds4PpdCS6QG8B4C1krxJsMutgxl5t3+GlRTzzI3NEkifXx2pVsOvJdOGSmIgDhQ55FwdPA== - dependencies: - duplexer "^0.1.1" - pify "^4.0.1" - -handlebars@^4.0.1, handlebars@^4.1.2: - version "4.5.3" - resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.5.3.tgz#5cf75bd8714f7605713511a56be7c349becb0482" - integrity sha512-3yPecJoJHK/4c6aZhSvxOyG4vJKDshV36VHp0iVCDVh7o9w2vwi3NSnL2MMPj3YdduqaBcu7cGbggJQM0br9xA== - dependencies: - neo-async "^2.6.0" - optimist "^0.6.1" - source-map "^0.6.1" - optionalDependencies: - uglify-js "^3.1.4" - -har-schema@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" - integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI= - -har-validator@~5.1.0: - version "5.1.3" - resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.3.tgz#1ef89ebd3e4996557675eed9893110dc350fa080" - integrity sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g== - dependencies: - ajv "^6.5.5" - har-schema "^2.0.0" - -har-validator@~5.1.3: - version "5.1.5" - resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.5.tgz#1f0803b9f8cb20c0fa13822df1ecddb36bde1efd" - integrity sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w== - dependencies: - ajv "^6.12.3" - har-schema "^2.0.0" - -has-ansi@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" - integrity sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE= - dependencies: - ansi-regex "^2.0.0" - -has-flag@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa" - integrity sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo= - -has-flag@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-2.0.0.tgz#e8207af1cc7b30d446cc70b734b5e8be18f88d51" - integrity sha1-6CB68cx7MNRGzHC3NLXovhj4jVE= - -has-flag@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" - integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= - -has-flag@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" - integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== - -has-symbol-support-x@^1.4.1: - version "1.4.2" - resolved "https://registry.yarnpkg.com/has-symbol-support-x/-/has-symbol-support-x-1.4.2.tgz#1409f98bc00247da45da67cee0a36f282ff26455" - integrity sha512-3ToOva++HaW+eCpgqZrCfN51IPB+7bJNVT6CUATzueB5Heb8o6Nam0V3HG5dlDvZU1Gn5QLcbahiKw/XVk5JJw== - -has-symbols@^1.0.0, has-symbols@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.1.tgz#9f5214758a44196c406d9bd76cebf81ec2dd31e8" - integrity sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg== - -has-to-string-tag-x@^1.2.0: - version "1.4.1" - resolved "https://registry.yarnpkg.com/has-to-string-tag-x/-/has-to-string-tag-x-1.4.1.tgz#a045ab383d7b4b2012a00148ab0aa5f290044d4d" - integrity sha512-vdbKfmw+3LoOYVr+mtxHaX5a96+0f3DljYd8JOqvOLsf5mw2Otda2qCDT9qRqLAhrjyQ0h7ual5nOiASpsGNFw== - dependencies: - has-symbol-support-x "^1.4.1" - -has-unicode@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" - integrity sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk= - -has-value@^0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" - integrity sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8= - dependencies: - get-value "^2.0.3" - has-values "^0.1.4" - isobject "^2.0.0" - -has-value@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-value/-/has-value-1.0.0.tgz#18b281da585b1c5c51def24c930ed29a0be6b177" - integrity sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc= - dependencies: - get-value "^2.0.6" - has-values "^1.0.0" - isobject "^3.0.0" - -has-values@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/has-values/-/has-values-0.1.4.tgz#6d61de95d91dfca9b9a02089ad384bff8f62b771" - integrity sha1-bWHeldkd/Km5oCCJrThL/49it3E= - -has-values@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-values/-/has-values-1.0.0.tgz#95b0b63fec2146619a6fe57fe75628d5a39efe4f" - integrity sha1-lbC2P+whRmGab+V/51Yo1aOe/k8= - dependencies: - is-number "^3.0.0" - kind-of "^4.0.0" - -has@^1.0.1, has@^1.0.3, has@~1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" - integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== - dependencies: - function-bind "^1.1.1" - -hash-base@^3.0.0: - version "3.0.4" - resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.0.4.tgz#5fc8686847ecd73499403319a6b0a3f3f6ae4918" - integrity sha1-X8hoaEfs1zSZQDMZprCj8/auSRg= - dependencies: - inherits "^2.0.1" - safe-buffer "^5.0.1" - -hash.js@1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.3.tgz#340dedbe6290187151c1ea1d777a3448935df846" - integrity sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA== - dependencies: - inherits "^2.0.3" - minimalistic-assert "^1.0.0" - -hash.js@1.1.7, hash.js@^1.0.0, hash.js@^1.0.3: - version "1.1.7" - resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42" - integrity sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA== - dependencies: - inherits "^2.0.3" - minimalistic-assert "^1.0.1" - -hdkey@^0.7.1: - version "0.7.1" - resolved "https://registry.yarnpkg.com/hdkey/-/hdkey-0.7.1.tgz#caee4be81aa77921e909b8d228dd0f29acaee632" - integrity sha1-yu5L6BqneSHpCbjSKN0PKayu5jI= - dependencies: - coinstring "^2.0.0" - secp256k1 "^3.0.1" - -hdkey@^1.1.0, hdkey@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/hdkey/-/hdkey-1.1.1.tgz#c2b3bfd5883ff9529b72f2f08b28be0972a9f64a" - integrity sha512-DvHZ5OuavsfWs5yfVJZestsnc3wzPvLWNk6c2nRUfo6X+OtxypGt20vDDf7Ba+MJzjL3KS1og2nw2eBbLCOUTA== - dependencies: - coinstring "^2.0.0" - safe-buffer "^5.1.1" - secp256k1 "^3.0.1" - -he@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd" - integrity sha1-k0EP0hsAlzUVH4howvJx80J+I/0= - -heap@0.2.6: - version "0.2.6" - resolved "https://registry.yarnpkg.com/heap/-/heap-0.2.6.tgz#087e1f10b046932fc8594dd9e6d378afc9d1e5ac" - integrity sha1-CH4fELBGky/IWU3Z5tN4r8nR5aw= - -hmac-drbg@^1.0.0, hmac-drbg@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" - integrity sha1-0nRXAQJabHdabFRXk+1QL8DGSaE= - dependencies: - hash.js "^1.0.3" - minimalistic-assert "^1.0.0" - minimalistic-crypto-utils "^1.0.1" - -home-or-tmp@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/home-or-tmp/-/home-or-tmp-2.0.0.tgz#e36c3f2d2cae7d746a857e38d18d5f32a7882db8" - integrity sha1-42w/LSyufXRqhX440Y1fMqeILbg= - dependencies: - os-homedir "^1.0.0" - os-tmpdir "^1.0.1" - -homedir-polyfill@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz#743298cef4e5af3e194161fbadcc2151d3a058e8" - integrity sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA== - dependencies: - parse-passwd "^1.0.0" - -hoopy@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/hoopy/-/hoopy-0.1.4.tgz#609207d661100033a9a9402ad3dea677381c1b1d" - integrity sha512-HRcs+2mr52W0K+x8RzcLzuPPmVIKMSv97RGHy0Ea9y/mpcaK+xTrjICA04KAHi4GRzxliNqNJEFYWHghy3rSfQ== - -hosted-git-info@^2.1.4, hosted-git-info@^2.6.0: - version "2.8.5" - resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.5.tgz#759cfcf2c4d156ade59b0b2dfabddc42a6b9c70c" - integrity sha512-kssjab8CvdXfcXMXVcvsXum4Hwdq9XGtRD3TteMEvEbq0LXyiNQr6AprqKqfeaDXze7SxWvRxdpwE6ku7ikLkg== - -html-encoding-sniffer@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/html-encoding-sniffer/-/html-encoding-sniffer-1.0.2.tgz#e70d84b94da53aa375e11fe3a351be6642ca46f8" - integrity sha512-71lZziiDnsuabfdYiUeWdCVyKuqwWi23L8YeIgV9jSSZHCtb6wB1BKWooH7L3tn4/FuZJMVWyNaIDr4RGmaSYw== - dependencies: - whatwg-encoding "^1.0.1" - -http-cache-semantics@^4.0.0: - version "4.0.3" - resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.0.3.tgz#495704773277eeef6e43f9ab2c2c7d259dda25c5" - integrity sha512-TcIMG3qeVLgDr1TEd2XvHaTnMPwYQUQMIBLy+5pLSDKYFc7UIqj39w8EGzZkaxoLv/l2K8HaI0t5AVA+YYgUew== - -http-errors@1.7.2: - version "1.7.2" - resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.2.tgz#4f5029cf13239f31036e5b2e55292bcfbcc85c8f" - integrity sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg== - dependencies: - depd "~1.1.2" - inherits "2.0.3" - setprototypeof "1.1.1" - statuses ">= 1.5.0 < 2" - toidentifier "1.0.0" - -http-errors@~1.7.2: - version "1.7.3" - resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.3.tgz#6c619e4f9c60308c38519498c14fbb10aacebb06" - integrity sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw== - dependencies: - depd "~1.1.2" - inherits "2.0.4" - setprototypeof "1.1.1" - statuses ">= 1.5.0 < 2" - toidentifier "1.0.0" - -http-https@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/http-https/-/http-https-1.0.0.tgz#2f908dd5f1db4068c058cd6e6d4ce392c913389b" - integrity sha1-L5CN1fHbQGjAWM1ubUzjkskTOJs= - -http-signature@~1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" - integrity sha1-muzZJRFHcvPZW2WmCruPfBj7rOE= - dependencies: - assert-plus "^1.0.0" - jsprim "^1.2.2" - sshpk "^1.7.0" - -https-browserify@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73" - integrity sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM= - -iconv-lite@0.4.24, iconv-lite@^0.4.4, iconv-lite@~0.4.13: - version "0.4.24" - resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" - integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== - dependencies: - safer-buffer ">= 2.1.2 < 3" - -idna-uts46-hx@^2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/idna-uts46-hx/-/idna-uts46-hx-2.3.1.tgz#a1dc5c4df37eee522bf66d969cc980e00e8711f9" - integrity sha512-PWoF9Keq6laYdIRwwCdhTPl60xRqAloYNMQLiyUnG42VjT53oW07BXIRM+NK7eQjzXjAk2gUvX9caRxlnF9TAA== - dependencies: - punycode "2.1.0" - -ieee754@^1.1.4: - version "1.1.13" - resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.13.tgz#ec168558e95aa181fd87d37f55c32bbcb6708b84" - integrity sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg== - -iferr@^0.1.5: - version "0.1.5" - resolved "https://registry.yarnpkg.com/iferr/-/iferr-0.1.5.tgz#c60eed69e6d8fdb6b3104a1fcbca1c192dc5b501" - integrity sha1-xg7taebY/bazEEofy8ocGS3FtQE= - -ignore-walk@^3.0.1: - version "3.0.3" - resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-3.0.3.tgz#017e2447184bfeade7c238e4aefdd1e8f95b1e37" - integrity sha512-m7o6xuOaT1aqheYHKf8W6J5pYH85ZI9w077erOzLje3JsB1gkafkAhHHY19dqjulgIZHFm32Cp5uNZgcQqdJKw== - dependencies: - minimatch "^3.0.4" - -immediate@^3.2.3, immediate@~3.2.3: - version "3.2.3" - resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.2.3.tgz#d140fa8f614659bd6541233097ddaac25cdd991c" - integrity sha1-0UD6j2FGWb1lQSMwl92qwlzdmRw= - -immutable@^4.0.0-rc.12: - version "4.0.0-rc.12" - resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.0.0-rc.12.tgz#ca59a7e4c19ae8d9bf74a97bdf0f6e2f2a5d0217" - integrity sha512-0M2XxkZLx/mi3t8NVwIm1g8nHoEmM9p9UBl/G9k4+hm0kBgOVdMV/B3CY5dQ8qG8qc80NN4gDV4HQv6FTJ5q7A== - -import-local@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/import-local/-/import-local-2.0.0.tgz#55070be38a5993cf18ef6db7e961f5bee5c5a09d" - integrity sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ== - dependencies: - pkg-dir "^3.0.0" - resolve-cwd "^2.0.0" - -imurmurhash@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" - integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= - -infer-owner@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/infer-owner/-/infer-owner-1.0.4.tgz#c4cefcaa8e51051c2a40ba2ce8a3d27295af9467" - integrity sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A== - -inflight@^1.0.4: - version "1.0.6" - resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" - integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= - dependencies: - once "^1.3.0" - wrappy "1" - -inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.1, inherits@~2.0.3, inherits@~2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" - integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== - -inherits@2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.1.tgz#b17d08d326b4423e568eff719f91b0b1cbdf69f1" - integrity sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE= - -inherits@2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" - integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= - -ini@^1.3.4, ini@^1.3.5, ini@~1.3.0: - version "1.3.5" - resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" - integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw== - -interpret@^1.1.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.2.0.tgz#d5061a6224be58e8083985f5014d844359576296" - integrity sha512-mT34yGKMNceBQUoVn7iCDKDntA7SC6gycMAWzGx1z/CMCTV7b2AAtXlo3nRyHZ1FelRkQbQjprHSYGwzLtkVbw== - -interpret@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.4.0.tgz#665ab8bc4da27a774a40584e812e3e0fa45b1a1e" - integrity sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA== - -invariant@^2.2.2, invariant@^2.2.4: - version "2.2.4" - resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" - integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA== - dependencies: - loose-envify "^1.0.0" - -invert-kv@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6" - integrity sha1-EEqOSqym09jNFXqO+L+rLXo//bY= - -ipaddr.js@1.9.0: - version "1.9.0" - resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.0.tgz#37df74e430a0e47550fe54a2defe30d8acd95f65" - integrity sha512-M4Sjn6N/+O6/IXSJseKqHoFc+5FdGJ22sXqnjTpdZweHK64MzEPAyQZyEU3R/KRv2GLoa7nNtg/C2Ev6m7z+eA== - -is-absolute@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-absolute/-/is-absolute-1.0.0.tgz#395e1ae84b11f26ad1795e73c17378e48a301576" - integrity sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA== - dependencies: - is-relative "^1.0.0" - is-windows "^1.0.1" - -is-accessor-descriptor@^0.1.6: - version "0.1.6" - resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6" - integrity sha1-qeEss66Nh2cn7u84Q/igiXtcmNY= - dependencies: - kind-of "^3.0.2" - -is-accessor-descriptor@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz#169c2f6d3df1f992618072365c9b0ea1f6878656" - integrity sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ== - dependencies: - kind-of "^6.0.0" - -is-arrayish@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" - integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= - -is-binary-path@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898" - integrity sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg= - dependencies: - binary-extensions "^1.0.0" - -is-binary-path@~2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" - integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== - dependencies: - binary-extensions "^2.0.0" - -is-buffer@^1.1.5: - version "1.1.6" - resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" - integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== - -is-callable@^1.1.3, is-callable@^1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.4.tgz#1e1adf219e1eeb684d691f9d6a05ff0d30a24d75" - integrity sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA== - -is-callable@^1.1.5: - version "1.1.5" - resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.5.tgz#f7e46b596890456db74e7f6e976cb3273d06faab" - integrity sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q== - -is-ci@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-2.0.0.tgz#6bc6334181810e04b5c22b3d589fdca55026404c" - integrity sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w== - dependencies: - ci-info "^2.0.0" - -is-data-descriptor@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" - integrity sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y= - dependencies: - kind-of "^3.0.2" - -is-data-descriptor@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz#d84876321d0e7add03990406abbbbd36ba9268c7" - integrity sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ== - dependencies: - kind-of "^6.0.0" - -is-date-object@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.1.tgz#9aa20eb6aeebbff77fbd33e74ca01b33581d3a16" - integrity sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY= - -is-descriptor@^0.1.0: - version "0.1.6" - resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca" - integrity sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg== - dependencies: - is-accessor-descriptor "^0.1.6" - is-data-descriptor "^0.1.4" - kind-of "^5.0.0" - -is-descriptor@^1.0.0, is-descriptor@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-1.0.2.tgz#3b159746a66604b04f8c81524ba365c5f14d86ec" - integrity sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg== - dependencies: - is-accessor-descriptor "^1.0.0" - is-data-descriptor "^1.0.0" - kind-of "^6.0.2" - -is-extendable@^0.1.0, is-extendable@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" - integrity sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik= - -is-extendable@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-1.0.1.tgz#a7470f9e426733d81bd81e1155264e3a3507cab4" - integrity sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA== - dependencies: - is-plain-object "^2.0.4" - -is-extglob@^2.1.0, is-extglob@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" - integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= - -is-finite@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.0.2.tgz#cc6677695602be550ef11e8b4aa6305342b6d0aa" - integrity sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko= - dependencies: - number-is-nan "^1.0.0" - -is-fn@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-fn/-/is-fn-1.0.0.tgz#9543d5de7bcf5b08a22ec8a20bae6e286d510d8c" - integrity sha1-lUPV3nvPWwiiLsiiC65uKG1RDYw= - -is-fullwidth-code-point@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" - integrity sha1-754xOG8DGn8NZDr4L95QxFfvAMs= - dependencies: - number-is-nan "^1.0.0" - -is-fullwidth-code-point@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" - integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= - -is-function@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-function/-/is-function-1.0.1.tgz#12cfb98b65b57dd3d193a3121f5f6e2f437602b5" - integrity sha1-Es+5i2W1fdPRk6MSH19uL0N2ArU= - -is-generator-fn@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-2.1.0.tgz#7d140adc389aaf3011a8f2a2a4cfa6faadffb118" - integrity sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ== - -is-glob@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a" - integrity sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo= - dependencies: - is-extglob "^2.1.0" - -is-glob@^4.0.0, is-glob@^4.0.1, is-glob@~4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc" - integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg== - dependencies: - is-extglob "^2.1.1" - -is-hex-prefixed@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz#7d8d37e6ad77e5d127148913c573e082d777f554" - integrity sha1-fY035q135dEnFIkTxXPggtd39VQ= - -is-natural-number@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/is-natural-number/-/is-natural-number-4.0.1.tgz#ab9d76e1db4ced51e35de0c72ebecf09f734cde8" - integrity sha1-q5124dtM7VHjXeDHLr7PCfc0zeg= - -is-negated-glob@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-negated-glob/-/is-negated-glob-1.0.0.tgz#6910bca5da8c95e784b5751b976cf5a10fee36d2" - integrity sha1-aRC8pdqMleeEtXUbl2z1oQ/uNtI= - -is-number@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" - integrity sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU= - dependencies: - kind-of "^3.0.2" - -is-number@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-4.0.0.tgz#0026e37f5454d73e356dfe6564699867c6a7f0ff" - integrity sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ== - -is-number@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" - integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== - -is-object@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-object/-/is-object-1.0.1.tgz#8952688c5ec2ffd6b03ecc85e769e02903083470" - integrity sha1-iVJojF7C/9awPsyF52ngKQMINHA= - -is-plain-obj@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" - integrity sha1-caUMhCnfync8kqOQpKA7OfzVHT4= - -is-plain-object@^2.0.1, is-plain-object@^2.0.3, is-plain-object@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" - integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== - dependencies: - isobject "^3.0.1" - -is-regex@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.4.tgz#5517489b547091b0930e095654ced25ee97e9491" - integrity sha1-VRdIm1RwkbCTDglWVM7SXul+lJE= - dependencies: - has "^1.0.1" - -is-regex@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.5.tgz#39d589a358bf18967f726967120b8fc1aed74eae" - integrity sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ== - dependencies: - has "^1.0.3" - -is-relative@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-relative/-/is-relative-1.0.0.tgz#a1bb6935ce8c5dba1e8b9754b9b2dcc020e2260d" - integrity sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA== - dependencies: - is-unc-path "^1.0.0" - -is-retry-allowed@^1.0.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/is-retry-allowed/-/is-retry-allowed-1.2.0.tgz#d778488bd0a4666a3be8a1482b9f2baafedea8b4" - integrity sha512-RUbUeKwvm3XG2VYamhJL1xFktgjvPzL0Hq8C+6yrWIswDy3BIXGqCxhxkc30N9jqK311gVU137K8Ei55/zVJRg== - -is-stream@^1.0.0, is-stream@^1.0.1, is-stream@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" - integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ= - -is-symbol@^1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.3.tgz#38e1014b9e6329be0de9d24a414fd7441ec61937" - integrity sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ== - dependencies: - has-symbols "^1.0.1" - -is-typedarray@^1.0.0, is-typedarray@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" - integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= - -is-unc-path@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-unc-path/-/is-unc-path-1.0.0.tgz#d731e8898ed090a12c352ad2eaed5095ad322c9d" - integrity sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ== - dependencies: - unc-path-regex "^0.1.2" - -is-utf8@^0.2.0, is-utf8@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" - integrity sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI= - -is-valid-glob@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-valid-glob/-/is-valid-glob-1.0.0.tgz#29bf3eff701be2d4d315dbacc39bc39fe8f601aa" - integrity sha1-Kb8+/3Ab4tTTFdusw5vDn+j2Aao= - -is-windows@^1.0.1, is-windows@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" - integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== - -is-wsl@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-1.1.0.tgz#1f16e4aa22b04d1336b66188a66af3c600c3a66d" - integrity sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0= - -isarray@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" - integrity sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8= - -isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" - integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= - -isexe@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" - integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= - -isobject@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" - integrity sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk= - dependencies: - isarray "1.0.0" - -isobject@^3.0.0, isobject@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" - integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8= - -isomorphic-fetch@2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz#611ae1acf14f5e81f729507472819fe9733558a9" - integrity sha1-YRrhrPFPXoH3KVB0coGf6XM1WKk= - dependencies: - node-fetch "^1.0.1" - whatwg-fetch ">=0.10.0" - -isstream@~0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" - integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo= - -istanbul-lib-coverage@^2.0.2, istanbul-lib-coverage@^2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.5.tgz#675f0ab69503fad4b1d849f736baaca803344f49" - integrity sha512-8aXznuEPCJvGnMSRft4udDRDtb1V3pkQkMMI5LI+6HuQz5oQ4J2UFn1H82raA3qJtyOLkkwVqICBQkjnGtn5mA== - -istanbul-lib-instrument@^3.0.1, istanbul-lib-instrument@^3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-3.3.0.tgz#a5f63d91f0bbc0c3e479ef4c5de027335ec6d630" - integrity sha512-5nnIN4vo5xQZHdXno/YDXJ0G+I3dAm4XgzfSVTPLQpj/zAV2dV6Juy0yaf10/zrJOJeHoN3fraFe+XRq2bFVZA== - dependencies: - "@babel/generator" "^7.4.0" - "@babel/parser" "^7.4.3" - "@babel/template" "^7.4.0" - "@babel/traverse" "^7.4.3" - "@babel/types" "^7.4.0" - istanbul-lib-coverage "^2.0.5" - semver "^6.0.0" - -istanbul-lib-report@^2.0.4: - version "2.0.8" - resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-2.0.8.tgz#5a8113cd746d43c4889eba36ab10e7d50c9b4f33" - integrity sha512-fHBeG573EIihhAblwgxrSenp0Dby6tJMFR/HvlerBsrCTD5bkUuoNtn3gVh29ZCS824cGGBPn7Sg7cNk+2xUsQ== - dependencies: - istanbul-lib-coverage "^2.0.5" - make-dir "^2.1.0" - supports-color "^6.1.0" - -istanbul-lib-source-maps@^3.0.1: - version "3.0.6" - resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-3.0.6.tgz#284997c48211752ec486253da97e3879defba8c8" - integrity sha512-R47KzMtDJH6X4/YW9XTx+jrLnZnscW4VpNN+1PViSYTejLVPWv7oov+Duf8YQSPyVRUvueQqz1TcsC6mooZTXw== - dependencies: - debug "^4.1.1" - istanbul-lib-coverage "^2.0.5" - make-dir "^2.1.0" - rimraf "^2.6.3" - source-map "^0.6.1" - -istanbul-reports@^2.2.6: - version "2.2.6" - resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-2.2.6.tgz#7b4f2660d82b29303a8fe6091f8ca4bf058da1af" - integrity sha512-SKi4rnMyLBKe0Jy2uUdx28h8oG7ph2PPuQPvIAh31d+Ci+lSiEu4C+h3oBPuJ9+mPKhOyW0M8gY4U5NM1WLeXA== - dependencies: - handlebars "^4.1.2" - -istanbul@^0.4.5: - version "0.4.5" - resolved "https://registry.yarnpkg.com/istanbul/-/istanbul-0.4.5.tgz#65c7d73d4c4da84d4f3ac310b918fb0b8033733b" - integrity sha1-ZcfXPUxNqE1POsMQuRj7C4Azczs= - dependencies: - abbrev "1.0.x" - async "1.x" - escodegen "1.8.x" - esprima "2.7.x" - glob "^5.0.15" - handlebars "^4.0.1" - js-yaml "3.x" - mkdirp "0.5.x" - nopt "3.x" - once "1.x" - resolve "1.1.x" - supports-color "^3.1.0" - which "^1.1.1" - wordwrap "^1.0.0" - -isurl@^1.0.0-alpha5: - version "1.0.0" - resolved "https://registry.yarnpkg.com/isurl/-/isurl-1.0.0.tgz#b27f4f49f3cdaa3ea44a0a5b7f3462e6edc39d67" - integrity sha512-1P/yWsxPlDtn7QeRD+ULKQPaIaN6yF368GZ2vDfv0AL0NwpStafjWCDDdn0k8wgFMWpVAqG7oJhxHnlud42i9w== - dependencies: - has-to-string-tag-x "^1.2.0" - is-object "^1.0.1" - -jest-changed-files@^24.9.0: - version "24.9.0" - resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-24.9.0.tgz#08d8c15eb79a7fa3fc98269bc14b451ee82f8039" - integrity sha512-6aTWpe2mHF0DhL28WjdkO8LyGjs3zItPET4bMSeXU6T3ub4FPMw+mcOcbdGXQOAfmLcxofD23/5Bl9Z4AkFwqg== - dependencies: - "@jest/types" "^24.9.0" - execa "^1.0.0" - throat "^4.0.0" - -jest-cli@^24.9.0: - version "24.9.0" - resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-24.9.0.tgz#ad2de62d07472d419c6abc301fc432b98b10d2af" - integrity sha512-+VLRKyitT3BWoMeSUIHRxV/2g8y9gw91Jh5z2UmXZzkZKpbC08CSehVxgHUwTpy+HwGcns/tqafQDJW7imYvGg== - dependencies: - "@jest/core" "^24.9.0" - "@jest/test-result" "^24.9.0" - "@jest/types" "^24.9.0" - chalk "^2.0.1" - exit "^0.1.2" - import-local "^2.0.0" - is-ci "^2.0.0" - jest-config "^24.9.0" - jest-util "^24.9.0" - jest-validate "^24.9.0" - prompts "^2.0.1" - realpath-native "^1.1.0" - yargs "^13.3.0" - -jest-config@^24.9.0: - version "24.9.0" - resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-24.9.0.tgz#fb1bbc60c73a46af03590719efa4825e6e4dd1b5" - integrity sha512-RATtQJtVYQrp7fvWg6f5y3pEFj9I+H8sWw4aKxnDZ96mob5i5SD6ZEGWgMLXQ4LE8UurrjbdlLWdUeo+28QpfQ== - dependencies: - "@babel/core" "^7.1.0" - "@jest/test-sequencer" "^24.9.0" - "@jest/types" "^24.9.0" - babel-jest "^24.9.0" - chalk "^2.0.1" - glob "^7.1.1" - jest-environment-jsdom "^24.9.0" - jest-environment-node "^24.9.0" - jest-get-type "^24.9.0" - jest-jasmine2 "^24.9.0" - jest-regex-util "^24.3.0" - jest-resolve "^24.9.0" - jest-util "^24.9.0" - jest-validate "^24.9.0" - micromatch "^3.1.10" - pretty-format "^24.9.0" - realpath-native "^1.1.0" - -jest-diff@^24.3.0, jest-diff@^24.9.0: - version "24.9.0" - resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-24.9.0.tgz#931b7d0d5778a1baf7452cb816e325e3724055da" - integrity sha512-qMfrTs8AdJE2iqrTp0hzh7kTd2PQWrsFyj9tORoKmu32xjPjeE4NyjVRDz8ybYwqS2ik8N4hsIpiVTyFeo2lBQ== - dependencies: - chalk "^2.0.1" - diff-sequences "^24.9.0" - jest-get-type "^24.9.0" - pretty-format "^24.9.0" - -jest-diff@^25.3.0: - version "25.3.0" - resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-25.3.0.tgz#0d7d6f5d6171e5dacde9e05be47b3615e147c26f" - integrity sha512-vyvs6RPoVdiwARwY4kqFWd4PirPLm2dmmkNzKqo38uZOzJvLee87yzDjIZLmY1SjM3XR5DwsUH+cdQ12vgqi1w== - dependencies: - chalk "^3.0.0" - diff-sequences "^25.2.6" - jest-get-type "^25.2.6" - pretty-format "^25.3.0" - -jest-docblock@^24.3.0: - version "24.9.0" - resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-24.9.0.tgz#7970201802ba560e1c4092cc25cbedf5af5a8ce2" - integrity sha512-F1DjdpDMJMA1cN6He0FNYNZlo3yYmOtRUnktrT9Q37njYzC5WEaDdmbynIgy0L/IvXvvgsG8OsqhLPXTpfmZAA== - dependencies: - detect-newline "^2.1.0" - -jest-each@^24.9.0: - version "24.9.0" - resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-24.9.0.tgz#eb2da602e2a610898dbc5f1f6df3ba86b55f8b05" - integrity sha512-ONi0R4BvW45cw8s2Lrx8YgbeXL1oCQ/wIDwmsM3CqM/nlblNCPmnC3IPQlMbRFZu3wKdQ2U8BqM6lh3LJ5Bsog== - dependencies: - "@jest/types" "^24.9.0" - chalk "^2.0.1" - jest-get-type "^24.9.0" - jest-util "^24.9.0" - pretty-format "^24.9.0" - -jest-environment-jsdom@^24.9.0: - version "24.9.0" - resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-24.9.0.tgz#4b0806c7fc94f95edb369a69cc2778eec2b7375b" - integrity sha512-Zv9FV9NBRzLuALXjvRijO2351DRQeLYXtpD4xNvfoVFw21IOKNhZAEUKcbiEtjTkm2GsJ3boMVgkaR7rN8qetA== - dependencies: - "@jest/environment" "^24.9.0" - "@jest/fake-timers" "^24.9.0" - "@jest/types" "^24.9.0" - jest-mock "^24.9.0" - jest-util "^24.9.0" - jsdom "^11.5.1" - -jest-environment-node@^24.9.0: - version "24.9.0" - resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-24.9.0.tgz#333d2d2796f9687f2aeebf0742b519f33c1cbfd3" - integrity sha512-6d4V2f4nxzIzwendo27Tr0aFm+IXWa0XEUnaH6nU0FMaozxovt+sfRvh4J47wL1OvF83I3SSTu0XK+i4Bqe7uA== - dependencies: - "@jest/environment" "^24.9.0" - "@jest/fake-timers" "^24.9.0" - "@jest/types" "^24.9.0" - jest-mock "^24.9.0" - jest-util "^24.9.0" - -jest-get-type@^24.9.0: - version "24.9.0" - resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-24.9.0.tgz#1684a0c8a50f2e4901b6644ae861f579eed2ef0e" - integrity sha512-lUseMzAley4LhIcpSP9Jf+fTrQ4a1yHQwLNeeVa2cEmbCGeoZAtYPOIv8JaxLD/sUpKxetKGP+gsHl8f8TSj8Q== - -jest-get-type@^25.2.6: - version "25.2.6" - resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-25.2.6.tgz#0b0a32fab8908b44d508be81681487dbabb8d877" - integrity sha512-DxjtyzOHjObRM+sM1knti6or+eOgcGU4xVSb2HNP1TqO4ahsT+rqZg+nyqHWJSvWgKC5cG3QjGFBqxLghiF/Ig== - -jest-haste-map@^24.9.0: - version "24.9.0" - resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-24.9.0.tgz#b38a5d64274934e21fa417ae9a9fbeb77ceaac7d" - integrity sha512-kfVFmsuWui2Sj1Rp1AJ4D9HqJwE4uwTlS/vO+eRUaMmd54BFpli2XhMQnPC2k4cHFVbB2Q2C+jtI1AGLgEnCjQ== - dependencies: - "@jest/types" "^24.9.0" - anymatch "^2.0.0" - fb-watchman "^2.0.0" - graceful-fs "^4.1.15" - invariant "^2.2.4" - jest-serializer "^24.9.0" - jest-util "^24.9.0" - jest-worker "^24.9.0" - micromatch "^3.1.10" - sane "^4.0.3" - walker "^1.0.7" - optionalDependencies: - fsevents "^1.2.7" - -jest-jasmine2@^24.9.0: - version "24.9.0" - resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-24.9.0.tgz#1f7b1bd3242c1774e62acabb3646d96afc3be6a0" - integrity sha512-Cq7vkAgaYKp+PsX+2/JbTarrk0DmNhsEtqBXNwUHkdlbrTBLtMJINADf2mf5FkowNsq8evbPc07/qFO0AdKTzw== - dependencies: - "@babel/traverse" "^7.1.0" - "@jest/environment" "^24.9.0" - "@jest/test-result" "^24.9.0" - "@jest/types" "^24.9.0" - chalk "^2.0.1" - co "^4.6.0" - expect "^24.9.0" - is-generator-fn "^2.0.0" - jest-each "^24.9.0" - jest-matcher-utils "^24.9.0" - jest-message-util "^24.9.0" - jest-runtime "^24.9.0" - jest-snapshot "^24.9.0" - jest-util "^24.9.0" - pretty-format "^24.9.0" - throat "^4.0.0" - -jest-junit@^6.4.0: - version "6.4.0" - resolved "https://registry.yarnpkg.com/jest-junit/-/jest-junit-6.4.0.tgz#23e15c979fa6338afde46f2d2ac2a6b7e8cf0d9e" - integrity sha512-GXEZA5WBeUich94BARoEUccJumhCgCerg7mXDFLxWwI2P7wL3Z7sGWk+53x343YdBLjiMR9aD/gYMVKO+0pE4Q== - dependencies: - jest-validate "^24.0.0" - mkdirp "^0.5.1" - strip-ansi "^4.0.0" - xml "^1.0.1" - -jest-leak-detector@^24.9.0: - version "24.9.0" - resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-24.9.0.tgz#b665dea7c77100c5c4f7dfcb153b65cf07dcf96a" - integrity sha512-tYkFIDsiKTGwb2FG1w8hX9V0aUb2ot8zY/2nFg087dUageonw1zrLMP4W6zsRO59dPkTSKie+D4rhMuP9nRmrA== - dependencies: - jest-get-type "^24.9.0" - pretty-format "^24.9.0" - -jest-matcher-utils@^24.9.0: - version "24.9.0" - resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-24.9.0.tgz#f5b3661d5e628dffe6dd65251dfdae0e87c3a073" - integrity sha512-OZz2IXsu6eaiMAwe67c1T+5tUAtQyQx27/EMEkbFAGiw52tB9em+uGbzpcgYVpA8wl0hlxKPZxrly4CXU/GjHA== - dependencies: - chalk "^2.0.1" - jest-diff "^24.9.0" - jest-get-type "^24.9.0" - pretty-format "^24.9.0" - -jest-message-util@^24.9.0: - version "24.9.0" - resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-24.9.0.tgz#527f54a1e380f5e202a8d1149b0ec872f43119e3" - integrity sha512-oCj8FiZ3U0hTP4aSui87P4L4jC37BtQwUMqk+zk/b11FR19BJDeZsZAvIHutWnmtw7r85UmR3CEWZ0HWU2mAlw== - dependencies: - "@babel/code-frame" "^7.0.0" - "@jest/test-result" "^24.9.0" - "@jest/types" "^24.9.0" - "@types/stack-utils" "^1.0.1" - chalk "^2.0.1" - micromatch "^3.1.10" - slash "^2.0.0" - stack-utils "^1.0.1" - -jest-mock@^24.9.0: - version "24.9.0" - resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-24.9.0.tgz#c22835541ee379b908673ad51087a2185c13f1c6" - integrity sha512-3BEYN5WbSq9wd+SyLDES7AHnjH9A/ROBwmz7l2y+ol+NtSFO8DYiEBzoO1CeFc9a8DYy10EO4dDFVv/wN3zl1w== - dependencies: - "@jest/types" "^24.9.0" - -jest-pnp-resolver@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/jest-pnp-resolver/-/jest-pnp-resolver-1.2.1.tgz#ecdae604c077a7fbc70defb6d517c3c1c898923a" - integrity sha512-pgFw2tm54fzgYvc/OHrnysABEObZCUNFnhjoRjaVOCN8NYc032/gVjPaHD4Aq6ApkSieWtfKAFQtmDKAmhupnQ== - -jest-regex-util@^24.3.0, jest-regex-util@^24.9.0: - version "24.9.0" - resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-24.9.0.tgz#c13fb3380bde22bf6575432c493ea8fe37965636" - integrity sha512-05Cmb6CuxaA+Ys6fjr3PhvV3bGQmO+2p2La4hFbU+W5uOc479f7FdLXUWXw4pYMAhhSZIuKHwSXSu6CsSBAXQA== - -jest-resolve-dependencies@^24.9.0: - version "24.9.0" - resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-24.9.0.tgz#ad055198959c4cfba8a4f066c673a3f0786507ab" - integrity sha512-Fm7b6AlWnYhT0BXy4hXpactHIqER7erNgIsIozDXWl5dVm+k8XdGVe1oTg1JyaFnOxarMEbax3wyRJqGP2Pq+g== - dependencies: - "@jest/types" "^24.9.0" - jest-regex-util "^24.3.0" - jest-snapshot "^24.9.0" - -jest-resolve@^24.9.0: - version "24.9.0" - resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-24.9.0.tgz#dff04c7687af34c4dd7e524892d9cf77e5d17321" - integrity sha512-TaLeLVL1l08YFZAt3zaPtjiVvyy4oSA6CRe+0AFPPVX3Q/VI0giIWWoAvoS5L96vj9Dqxj4fB5p2qrHCmTU/MQ== - dependencies: - "@jest/types" "^24.9.0" - browser-resolve "^1.11.3" - chalk "^2.0.1" - jest-pnp-resolver "^1.2.1" - realpath-native "^1.1.0" - -jest-runner@^24.9.0: - version "24.9.0" - resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-24.9.0.tgz#574fafdbd54455c2b34b4bdf4365a23857fcdf42" - integrity sha512-KksJQyI3/0mhcfspnxxEOBueGrd5E4vV7ADQLT9ESaCzz02WnbdbKWIf5Mkaucoaj7obQckYPVX6JJhgUcoWWg== - dependencies: - "@jest/console" "^24.7.1" - "@jest/environment" "^24.9.0" - "@jest/test-result" "^24.9.0" - "@jest/types" "^24.9.0" - chalk "^2.4.2" - exit "^0.1.2" - graceful-fs "^4.1.15" - jest-config "^24.9.0" - jest-docblock "^24.3.0" - jest-haste-map "^24.9.0" - jest-jasmine2 "^24.9.0" - jest-leak-detector "^24.9.0" - jest-message-util "^24.9.0" - jest-resolve "^24.9.0" - jest-runtime "^24.9.0" - jest-util "^24.9.0" - jest-worker "^24.6.0" - source-map-support "^0.5.6" - throat "^4.0.0" - -jest-runtime@^24.9.0: - version "24.9.0" - resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-24.9.0.tgz#9f14583af6a4f7314a6a9d9f0226e1a781c8e4ac" - integrity sha512-8oNqgnmF3v2J6PVRM2Jfuj8oX3syKmaynlDMMKQ4iyzbQzIG6th5ub/lM2bCMTmoTKM3ykcUYI2Pw9xwNtjMnw== - dependencies: - "@jest/console" "^24.7.1" - "@jest/environment" "^24.9.0" - "@jest/source-map" "^24.3.0" - "@jest/transform" "^24.9.0" - "@jest/types" "^24.9.0" - "@types/yargs" "^13.0.0" - chalk "^2.0.1" - exit "^0.1.2" - glob "^7.1.3" - graceful-fs "^4.1.15" - jest-config "^24.9.0" - jest-haste-map "^24.9.0" - jest-message-util "^24.9.0" - jest-mock "^24.9.0" - jest-regex-util "^24.3.0" - jest-resolve "^24.9.0" - jest-snapshot "^24.9.0" - jest-util "^24.9.0" - jest-validate "^24.9.0" - realpath-native "^1.1.0" - slash "^2.0.0" - strip-bom "^3.0.0" - yargs "^13.3.0" - -jest-serializer@^24.9.0: - version "24.9.0" - resolved "https://registry.yarnpkg.com/jest-serializer/-/jest-serializer-24.9.0.tgz#e6d7d7ef96d31e8b9079a714754c5d5c58288e73" - integrity sha512-DxYipDr8OvfrKH3Kel6NdED3OXxjvxXZ1uIY2I9OFbGg+vUkkg7AGvi65qbhbWNPvDckXmzMPbK3u3HaDO49bQ== - -jest-snapshot@^24.9.0: - version "24.9.0" - resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-24.9.0.tgz#ec8e9ca4f2ec0c5c87ae8f925cf97497b0e951ba" - integrity sha512-uI/rszGSs73xCM0l+up7O7a40o90cnrk429LOiK3aeTvfC0HHmldbd81/B7Ix81KSFe1lwkbl7GnBGG4UfuDew== - dependencies: - "@babel/types" "^7.0.0" - "@jest/types" "^24.9.0" - chalk "^2.0.1" - expect "^24.9.0" - jest-diff "^24.9.0" - jest-get-type "^24.9.0" - jest-matcher-utils "^24.9.0" - jest-message-util "^24.9.0" - jest-resolve "^24.9.0" - mkdirp "^0.5.1" - natural-compare "^1.4.0" - pretty-format "^24.9.0" - semver "^6.2.0" - -jest-util@^24.9.0: - version "24.9.0" - resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-24.9.0.tgz#7396814e48536d2e85a37de3e4c431d7cb140162" - integrity sha512-x+cZU8VRmOJxbA1K5oDBdxQmdq0OIdADarLxk0Mq+3XS4jgvhG/oKGWcIDCtPG0HgjxOYvF+ilPJQsAyXfbNOg== - dependencies: - "@jest/console" "^24.9.0" - "@jest/fake-timers" "^24.9.0" - "@jest/source-map" "^24.9.0" - "@jest/test-result" "^24.9.0" - "@jest/types" "^24.9.0" - callsites "^3.0.0" - chalk "^2.0.1" - graceful-fs "^4.1.15" - is-ci "^2.0.0" - mkdirp "^0.5.1" - slash "^2.0.0" - source-map "^0.6.0" - -jest-validate@^24.0.0, jest-validate@^24.9.0: - version "24.9.0" - resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-24.9.0.tgz#0775c55360d173cd854e40180756d4ff52def8ab" - integrity sha512-HPIt6C5ACwiqSiwi+OfSSHbK8sG7akG8eATl+IPKaeIjtPOeBUd/g3J7DghugzxrGjI93qS/+RPKe1H6PqvhRQ== - dependencies: - "@jest/types" "^24.9.0" - camelcase "^5.3.1" - chalk "^2.0.1" - jest-get-type "^24.9.0" - leven "^3.1.0" - pretty-format "^24.9.0" - -jest-watcher@^24.9.0: - version "24.9.0" - resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-24.9.0.tgz#4b56e5d1ceff005f5b88e528dc9afc8dd4ed2b3b" - integrity sha512-+/fLOfKPXXYJDYlks62/4R4GoT+GU1tYZed99JSCOsmzkkF7727RqKrjNAxtfO4YpGv11wybgRvCjR73lK2GZw== - dependencies: - "@jest/test-result" "^24.9.0" - "@jest/types" "^24.9.0" - "@types/yargs" "^13.0.0" - ansi-escapes "^3.0.0" - chalk "^2.0.1" - jest-util "^24.9.0" - string-length "^2.0.0" - -jest-worker@^24.6.0, jest-worker@^24.9.0: - version "24.9.0" - resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-24.9.0.tgz#5dbfdb5b2d322e98567898238a9697bcce67b3e5" - integrity sha512-51PE4haMSXcHohnSMdM42anbvZANYTqMrr52tVKPqqsPJMzoP6FYYDVqahX/HrAoKEKz3uUPzSvKs9A3qR4iVw== - dependencies: - merge-stream "^2.0.0" - supports-color "^6.1.0" - -jest@^24.9.0: - version "24.9.0" - resolved "https://registry.yarnpkg.com/jest/-/jest-24.9.0.tgz#987d290c05a08b52c56188c1002e368edb007171" - integrity sha512-YvkBL1Zm7d2B1+h5fHEOdyjCG+sGMz4f8D86/0HiqJ6MB4MnDc8FgP5vdWsGnemOQro7lnYo8UakZ3+5A0jxGw== - dependencies: - import-local "^2.0.0" - jest-cli "^24.9.0" - -js-sha3@0.5.7, js-sha3@^0.5.7: - version "0.5.7" - resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.5.7.tgz#0d4ffd8002d5333aabaf4a23eed2f6374c9f28e7" - integrity sha1-DU/9gALVMzqrr0oj7tL2N0yfKOc= - -js-sha3@0.8.0, js-sha3@^0.8.0: - version "0.8.0" - resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.8.0.tgz#b9b7a5da73afad7dedd0f8c463954cbde6818840" - integrity sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q== - -js-sha3@^0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.6.1.tgz#5b89f77a7477679877f58c4a075240934b1f95c0" - integrity sha1-W4n3enR3Z5h39YxKB1JAk0sflcA= - -js-sha3@^0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.7.0.tgz#0a5c57b36f79882573b2d84051f8bb85dd1bd63a" - integrity sha512-Wpks3yBDm0UcL5qlVhwW9Jr9n9i4FfeWBFOOXP5puDS/SiudJGhw7DPyBqn3487qD4F0lsC0q3zxink37f7zeA== - -"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" - integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== - -js-tokens@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" - integrity sha1-mGbfOVECEw449/mWvOtlRDIJwls= - -js-yaml@3.x: - version "3.13.1" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847" - integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw== - dependencies: - argparse "^1.0.7" - esprima "^4.0.0" - -jsbn@~0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" - integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM= - -jsdom@^11.5.1: - version "11.12.0" - resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-11.12.0.tgz#1a80d40ddd378a1de59656e9e6dc5a3ba8657bc8" - integrity sha512-y8Px43oyiBM13Zc1z780FrfNLJCXTL40EWlty/LXUtcjykRBNgLlCjWXpfSPBl2iv+N7koQN+dvqszHZgT/Fjw== - dependencies: - abab "^2.0.0" - acorn "^5.5.3" - acorn-globals "^4.1.0" - array-equal "^1.0.0" - cssom ">= 0.3.2 < 0.4.0" - cssstyle "^1.0.0" - data-urls "^1.0.0" - domexception "^1.0.1" - escodegen "^1.9.1" - html-encoding-sniffer "^1.0.2" - left-pad "^1.3.0" - nwsapi "^2.0.7" - parse5 "4.0.0" - pn "^1.1.0" - request "^2.87.0" - request-promise-native "^1.0.5" - sax "^1.2.4" - symbol-tree "^3.2.2" - tough-cookie "^2.3.4" - w3c-hr-time "^1.0.1" - webidl-conversions "^4.0.2" - whatwg-encoding "^1.0.3" - whatwg-mimetype "^2.1.0" - whatwg-url "^6.4.1" - ws "^5.2.0" - xml-name-validator "^3.0.0" - -jsesc@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-1.3.0.tgz#46c3fec8c1892b12b0833db9bc7622176dbab34b" - integrity sha1-RsP+yMGJKxKwgz25vHYiF226s0s= - -jsesc@^2.5.1: - version "2.5.2" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" - integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== - -jsesc@~0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" - integrity sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0= - -json-buffer@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.0.tgz#5b1f397afc75d677bde8bcfc0e47e1f9a3d9a898" - integrity sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg= - -json-parse-better-errors@^1.0.1, json-parse-better-errors@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" - integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw== - -json-rpc-engine@^3.4.0, json-rpc-engine@^3.6.0: - version "3.8.0" - resolved "https://registry.yarnpkg.com/json-rpc-engine/-/json-rpc-engine-3.8.0.tgz#9d4ff447241792e1d0a232f6ef927302bb0c62a9" - integrity sha512-6QNcvm2gFuuK4TKU1uwfH0Qd/cOSb9c1lls0gbnIhciktIUQJwz6NQNAW4B1KiGPenv7IKu97V222Yo1bNhGuA== - dependencies: - async "^2.0.1" - babel-preset-env "^1.7.0" - babelify "^7.3.0" - json-rpc-error "^2.0.0" - promise-to-callback "^1.0.0" - safe-event-emitter "^1.0.1" - -json-rpc-engine@^5.1.3: - version "5.1.5" - resolved "https://registry.yarnpkg.com/json-rpc-engine/-/json-rpc-engine-5.1.5.tgz#a5f9915356ea916d5305716354080723c63dede7" - integrity sha512-HTT9HixG4j8vHYrmJIckgbISW9Q8tCkySv7x7Q8zjMpcw10wSe/dZSQ0w08VkDm3y195K4074UlvD3hxaznvlw== - dependencies: - async "^2.0.1" - eth-json-rpc-errors "^2.0.0" - promise-to-callback "^1.0.0" - safe-event-emitter "^1.0.1" - -json-rpc-error@2.0.0, json-rpc-error@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/json-rpc-error/-/json-rpc-error-2.0.0.tgz#a7af9c202838b5e905c7250e547f1aff77258a02" - integrity sha1-p6+cICg4tekFxyUOVH8a/3cligI= - dependencies: - inherits "^2.0.1" - -json-rpc-random-id@^1.0.0, json-rpc-random-id@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/json-rpc-random-id/-/json-rpc-random-id-1.0.1.tgz#ba49d96aded1444dbb8da3d203748acbbcdec8c8" - integrity sha1-uknZat7RRE27jaPSA3SKy7zeyMg= - -json-schema-traverse@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" - integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== - -json-schema@0.2.3: - version "0.2.3" - resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" - integrity sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM= - -json-stable-stringify-without-jsonify@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" - integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE= - -json-stable-stringify@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz#9a759d39c5f2ff503fd5300646ed445f88c4f9af" - integrity sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8= - dependencies: - jsonify "~0.0.0" - -json-stringify-safe@~5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" - integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= - -json5@2.x, json5@^2.1.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/json5/-/json5-2.1.1.tgz#81b6cb04e9ba496f1c7005d07b4368a2638f90b6" - integrity sha512-l+3HXD0GEI3huGq1njuqtzYK8OYJyXMkOLtQ53pjWh89tvWS2h6l+1zMkYWqlb57+SiQodKZyvMEFb2X+KrFhQ== - dependencies: - minimist "^1.2.0" - -json5@^0.5.1: - version "0.5.1" - resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821" - integrity sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE= - -json5@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe" - integrity sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow== - dependencies: - minimist "^1.2.0" - -jsonfile@^2.1.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-2.4.0.tgz#3736a2b428b87bbda0cc83b53fa3d633a35c2ae8" - integrity sha1-NzaitCi4e72gzIO1P6PWM6NcKug= - optionalDependencies: - graceful-fs "^4.1.6" - -jsonfile@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" - integrity sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss= - optionalDependencies: - graceful-fs "^4.1.6" - -jsonify@~0.0.0: - version "0.0.0" - resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73" - integrity sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM= - -jsonschema@^1.2.0: - version "1.2.5" - resolved "https://registry.yarnpkg.com/jsonschema/-/jsonschema-1.2.5.tgz#bab69d97fa28946aec0a56a9cc266d23fe80ae61" - integrity sha512-kVTF+08x25PQ0CjuVc0gRM9EUPb0Fe9Ln/utFOgcdxEIOHuU7ooBk/UPTd7t1M91pP35m0MU1T8M5P7vP1bRRw== - -jsprim@^1.2.2: - version "1.4.1" - resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2" - integrity sha1-MT5mvB5cwG5Di8G3SZwuXFastqI= - dependencies: - assert-plus "1.0.0" - extsprintf "1.3.0" - json-schema "0.2.3" - verror "1.10.0" - -just-debounce@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/just-debounce/-/just-debounce-1.0.0.tgz#87fccfaeffc0b68cd19d55f6722943f929ea35ea" - integrity sha1-h/zPrv/AtozRnVX2cilD+SnqNeo= - -keccak@^1.0.2: - version "1.4.0" - resolved "https://registry.yarnpkg.com/keccak/-/keccak-1.4.0.tgz#572f8a6dbee8e7b3aa421550f9e6408ca2186f80" - integrity sha512-eZVaCpblK5formjPjeTBik7TAg+pqnDrMHIffSvi9Lh7PQgM1+hSzakUeZFCk9DVVG0dacZJuaz2ntwlzZUIBw== - dependencies: - bindings "^1.2.1" - inherits "^2.0.3" - nan "^2.2.1" - safe-buffer "^5.1.0" - -keccak@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/keccak/-/keccak-2.1.0.tgz#734ea53f2edcfd0f42cdb8d5f4c358fef052752b" - integrity sha512-m1wbJRTo+gWbctZWay9i26v5fFnYkOn7D5PCxJ3fZUGUEb49dE1Pm4BREUYCt/aoO6di7jeoGmhvqN9Nzylm3Q== - dependencies: - bindings "^1.5.0" - inherits "^2.0.4" - nan "^2.14.0" - safe-buffer "^5.2.0" - -keccakjs@^0.2.0: - version "0.2.3" - resolved "https://registry.yarnpkg.com/keccakjs/-/keccakjs-0.2.3.tgz#5e4e969ce39689a3861f445d7752ee3477f9fe72" - integrity sha512-BjLkNDcfaZ6l8HBG9tH0tpmDv3sS2mA7FNQxFHpCdzP3Gb2MVruXBSuoM66SnVxKJpAr5dKGdkHD+bDokt8fTg== - dependencies: - browserify-sha3 "^0.0.4" - sha3 "^1.2.2" - -keyv@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/keyv/-/keyv-3.1.0.tgz#ecc228486f69991e49e9476485a5be1e8fc5c4d9" - integrity sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA== - dependencies: - json-buffer "3.0.0" - -kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: - version "3.2.2" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" - integrity sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ= - dependencies: - is-buffer "^1.1.5" - -kind-of@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57" - integrity sha1-IIE989cSkosgc3hpGkUGb65y3Vc= - dependencies: - is-buffer "^1.1.5" - -kind-of@^5.0.0, kind-of@^5.0.2: - version "5.1.0" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-5.1.0.tgz#729c91e2d857b7a419a1f9aa65685c4c33f5845d" - integrity sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw== - -kind-of@^6.0.0, kind-of@^6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.2.tgz#01146b36a6218e64e58f3a8d66de5d7fc6f6d051" - integrity sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA== - -klaw@^1.0.0: - version "1.3.1" - resolved "https://registry.yarnpkg.com/klaw/-/klaw-1.3.1.tgz#4088433b46b3b1ba259d78785d8e96f73ba02439" - integrity sha1-QIhDO0azsbolnXh4XY6W9zugJDk= - optionalDependencies: - graceful-fs "^4.1.9" - -kleur@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e" - integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w== - -last-run@^1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/last-run/-/last-run-1.1.1.tgz#45b96942c17b1c79c772198259ba943bebf8ca5b" - integrity sha1-RblpQsF7HHnHchmCWbqUO+v4yls= - dependencies: - default-resolution "^2.0.0" - es6-weak-map "^2.0.1" - -lazystream@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/lazystream/-/lazystream-1.0.0.tgz#f6995fe0f820392f61396be89462407bb77168e4" - integrity sha1-9plf4PggOS9hOWvolGJAe7dxaOQ= - dependencies: - readable-stream "^2.0.5" - -lcid@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835" - integrity sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU= - dependencies: - invert-kv "^1.0.0" - -lead@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/lead/-/lead-1.0.0.tgz#6f14f99a37be3a9dd784f5495690e5903466ee42" - integrity sha1-bxT5mje+Op3XhPVJVpDlkDRm7kI= - dependencies: - flush-write-stream "^1.0.2" - -left-pad@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/left-pad/-/left-pad-1.3.0.tgz#5b8a3a7765dfe001261dde915589e782f8c94d1e" - integrity sha512-XI5MPzVNApjAyhQzphX8BkmKsKUxD4LdyK24iZeQGinBN9yTQT3bFlCBy/aVx2HrNcqQGsdot8ghrjyrvMCoEA== - -level-codec@^9.0.0: - version "9.0.1" - resolved "https://registry.yarnpkg.com/level-codec/-/level-codec-9.0.1.tgz#042f4aa85e56d4328ace368c950811ba802b7247" - integrity sha512-ajFP0kJ+nyq4i6kptSM+mAvJKLOg1X5FiFPtLG9M5gCEZyBmgDi3FkDrvlMkEzrUn1cWxtvVmrvoS4ASyO/q+Q== - -level-codec@~7.0.0: - version "7.0.1" - resolved "https://registry.yarnpkg.com/level-codec/-/level-codec-7.0.1.tgz#341f22f907ce0f16763f24bddd681e395a0fb8a7" - integrity sha512-Ua/R9B9r3RasXdRmOtd+t9TCOEIIlts+TN/7XTT2unhDaL6sJn83S3rUyljbr6lVtw49N3/yA0HHjpV6Kzb2aQ== - -level-errors@^1.0.3: - version "1.1.2" - resolved "https://registry.yarnpkg.com/level-errors/-/level-errors-1.1.2.tgz#4399c2f3d3ab87d0625f7e3676e2d807deff404d" - integrity sha512-Sw/IJwWbPKF5Ai4Wz60B52yj0zYeqzObLh8k1Tk88jVmD51cJSKWSYpRyhVIvFzZdvsPqlH5wfhp/yxdsaQH4w== - dependencies: - errno "~0.1.1" - -level-errors@^2.0.0, level-errors@~2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/level-errors/-/level-errors-2.0.1.tgz#2132a677bf4e679ce029f517c2f17432800c05c8" - integrity sha512-UVprBJXite4gPS+3VznfgDSU8PTRuVX0NXwoWW50KLxd2yw4Y1t2JUR5In1itQnudZqRMT9DlAM3Q//9NCjCFw== - dependencies: - errno "~0.1.1" - -level-errors@~1.0.3: - version "1.0.5" - resolved "https://registry.yarnpkg.com/level-errors/-/level-errors-1.0.5.tgz#83dbfb12f0b8a2516bdc9a31c4876038e227b859" - integrity sha512-/cLUpQduF6bNrWuAC4pwtUKA5t669pCsCi2XbmojG2tFeOr9j6ShtdDCtFFQO1DRt+EVZhx9gPzP9G2bUaG4ig== - dependencies: - errno "~0.1.1" - -level-iterator-stream@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/level-iterator-stream/-/level-iterator-stream-2.0.3.tgz#ccfff7c046dcf47955ae9a86f46dfa06a31688b4" - integrity sha512-I6Heg70nfF+e5Y3/qfthJFexhRw/Gi3bIymCoXAlijZdAcLaPuWSJs3KXyTYf23ID6g0o2QF62Yh+grOXY3Rig== - dependencies: - inherits "^2.0.1" - readable-stream "^2.0.5" - xtend "^4.0.0" - -level-iterator-stream@~1.3.0: - version "1.3.1" - resolved "https://registry.yarnpkg.com/level-iterator-stream/-/level-iterator-stream-1.3.1.tgz#e43b78b1a8143e6fa97a4f485eb8ea530352f2ed" - integrity sha1-5Dt4sagUPm+pek9IXrjqUwNS8u0= - dependencies: - inherits "^2.0.1" - level-errors "^1.0.3" - readable-stream "^1.0.33" - xtend "^4.0.0" - -level-iterator-stream@~3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/level-iterator-stream/-/level-iterator-stream-3.0.1.tgz#2c98a4f8820d87cdacab3132506815419077c730" - integrity sha512-nEIQvxEED9yRThxvOrq8Aqziy4EGzrxSZK+QzEFAVuJvQ8glfyZ96GB6BoI4sBbLfjMXm2w4vu3Tkcm9obcY0g== - dependencies: - inherits "^2.0.1" - readable-stream "^2.3.6" - xtend "^4.0.0" - -level-mem@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/level-mem/-/level-mem-3.0.1.tgz#7ce8cf256eac40f716eb6489654726247f5a89e5" - integrity sha512-LbtfK9+3Ug1UmvvhR2DqLqXiPW1OJ5jEh0a3m9ZgAipiwpSxGj/qaVVy54RG5vAQN1nCuXqjvprCuKSCxcJHBg== - dependencies: - level-packager "~4.0.0" - memdown "~3.0.0" - -level-packager@~4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/level-packager/-/level-packager-4.0.1.tgz#7e7d3016af005be0869bc5fa8de93d2a7f56ffe6" - integrity sha512-svCRKfYLn9/4CoFfi+d8krOtrp6RoX8+xm0Na5cgXMqSyRru0AnDYdLl+YI8u1FyS6gGZ94ILLZDE5dh2but3Q== - dependencies: - encoding-down "~5.0.0" - levelup "^3.0.0" - -level-post@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/level-post/-/level-post-1.0.7.tgz#19ccca9441a7cc527879a0635000f06d5e8f27d0" - integrity sha512-PWYqG4Q00asOrLhX7BejSajByB4EmG2GaKHfj3h5UmmZ2duciXLPGYWIjBzLECFWUGOZWlm5B20h/n3Gs3HKew== - dependencies: - ltgt "^2.1.2" - -level-sublevel@6.6.4: - version "6.6.4" - resolved "https://registry.yarnpkg.com/level-sublevel/-/level-sublevel-6.6.4.tgz#f7844ae893919cd9d69ae19d7159499afd5352ba" - integrity sha512-pcCrTUOiO48+Kp6F1+UAzF/OtWqLcQVTVF39HLdZ3RO8XBoXt+XVPKZO1vVr1aUoxHZA9OtD2e1v7G+3S5KFDA== - dependencies: - bytewise "~1.1.0" - level-codec "^9.0.0" - level-errors "^2.0.0" - level-iterator-stream "^2.0.3" - ltgt "~2.1.1" - pull-defer "^0.2.2" - pull-level "^2.0.3" - pull-stream "^3.6.8" - typewiselite "~1.0.0" - xtend "~4.0.0" - -level-ws@0.0.0: - version "0.0.0" - resolved "https://registry.yarnpkg.com/level-ws/-/level-ws-0.0.0.tgz#372e512177924a00424b0b43aef2bb42496d228b" - integrity sha1-Ny5RIXeSSgBCSwtDrvK7QkltIos= - dependencies: - readable-stream "~1.0.15" - xtend "~2.1.1" - -levelup@3.1.1, levelup@^3.0.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/levelup/-/levelup-3.1.1.tgz#c2c0b3be2b4dc316647c53b42e2f559e232d2189" - integrity sha512-9N10xRkUU4dShSRRFTBdNaBxofz+PGaIZO962ckboJZiNmLuhVT6FZ6ZKAsICKfUBO76ySaYU6fJWX/jnj3Lcg== - dependencies: - deferred-leveldown "~4.0.0" - level-errors "~2.0.0" - level-iterator-stream "~3.0.0" - xtend "~4.0.0" - -levelup@^1.2.1: - version "1.3.9" - resolved "https://registry.yarnpkg.com/levelup/-/levelup-1.3.9.tgz#2dbcae845b2bb2b6bea84df334c475533bbd82ab" - integrity sha512-VVGHfKIlmw8w1XqpGOAGwq6sZm2WwWLmlDcULkKWQXEA5EopA8OBNJ2Ck2v6bdk8HeEZSbCSEgzXadyQFm76sQ== - dependencies: - deferred-leveldown "~1.2.1" - level-codec "~7.0.0" - level-errors "~1.0.3" - level-iterator-stream "~1.3.0" - prr "~1.0.1" - semver "~5.4.1" - xtend "~4.0.0" - -leven@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" - integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A== - -levn@~0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" - integrity sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4= - dependencies: - prelude-ls "~1.1.2" - type-check "~0.3.2" - -liftoff@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/liftoff/-/liftoff-3.1.0.tgz#c9ba6081f908670607ee79062d700df062c52ed3" - integrity sha512-DlIPlJUkCV0Ips2zf2pJP0unEoT1kwYhiiPUGF3s/jtxTCjziNLoiVVh+jqWOWeFi6mmwQ5fNxvAUyPad4Dfog== - dependencies: - extend "^3.0.0" - findup-sync "^3.0.0" - fined "^1.0.1" - flagged-respawn "^1.0.0" - is-plain-object "^2.0.4" - object.map "^1.0.0" - rechoir "^0.6.2" - resolve "^1.1.7" - -load-json-file@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0" - integrity sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA= - dependencies: - graceful-fs "^4.1.2" - parse-json "^2.2.0" - pify "^2.0.0" - pinkie-promise "^2.0.0" - strip-bom "^2.0.0" - -load-json-file@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-4.0.0.tgz#2f5f45ab91e33216234fd53adab668eb4ec0993b" - integrity sha1-L19Fq5HjMhYjT9U62rZo607AmTs= - dependencies: - graceful-fs "^4.1.2" - parse-json "^4.0.0" - pify "^3.0.0" - strip-bom "^3.0.0" - -loader-runner@^2.4.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-2.4.0.tgz#ed47066bfe534d7e84c4c7b9998c2a75607d9357" - integrity sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw== - -loader-utils@^1.0.2, loader-utils@^1.2.3: - version "1.2.3" - resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.2.3.tgz#1ff5dc6911c9f0a062531a4c04b609406108c2c7" - integrity sha512-fkpz8ejdnEMG3s37wGL07iSBDg99O9D5yflE9RGNH3hRdx9SOwYfnGYdZOUIZitN8E+E2vkq3MUMYMvPYl5ZZA== - dependencies: - big.js "^5.2.2" - emojis-list "^2.0.0" - json5 "^1.0.1" - -loader-utils@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.4.0.tgz#c579b5e34cb34b1a74edc6c1fb36bfa371d5a613" - integrity sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA== - dependencies: - big.js "^5.2.2" - emojis-list "^3.0.0" - json5 "^1.0.1" - -locate-path@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" - integrity sha1-K1aLJl7slExtnA3pw9u7ygNUzY4= - dependencies: - p-locate "^2.0.0" - path-exists "^3.0.0" - -locate-path@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e" - integrity sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A== - dependencies: - p-locate "^3.0.0" - path-exists "^3.0.0" - -lodash.flatmap@^4.5.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/lodash.flatmap/-/lodash.flatmap-4.5.0.tgz#ef8cbf408f6e48268663345305c6acc0b778702e" - integrity sha1-74y/QI9uSCaGYzRTBcaswLd4cC4= - -lodash.memoize@4.x: - version "4.1.2" - resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" - integrity sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4= - -lodash.sortby@^4.7.0: - version "4.7.0" - resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438" - integrity sha1-7dFMgk4sycHgsKG0K7UhBRakJDg= - -lodash.values@^4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/lodash.values/-/lodash.values-4.3.0.tgz#a3a6c2b0ebecc5c2cba1c17e6e620fe81b53d347" - integrity sha1-o6bCsOvsxcLLocF+bmIP6BtT00c= - -lodash@4.17.14: - version "4.17.14" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.14.tgz#9ce487ae66c96254fe20b599f21b6816028078ba" - integrity sha512-mmKYbW3GLuJeX+iGP+Y7Gp1AiGHGbXHCOh/jZmrawMmsE7MS4znI3RL2FsjbqOyMayHInjOeykW7PEajUk1/xw== - -lodash@^4.17.11, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.4: - version "4.17.15" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" - integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== - -loglevel@^1.6.1: - version "1.6.6" - resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.6.6.tgz#0ee6300cc058db6b3551fa1c4bf73b83bb771312" - integrity sha512-Sgr5lbboAUBo3eXCSPL4/KoVz3ROKquOjcctxmHIt+vol2DrqTQe3SwkKKuYhEiWB5kYa13YyopJ69deJ1irzQ== - -looper@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/looper/-/looper-2.0.0.tgz#66cd0c774af3d4fedac53794f742db56da8f09ec" - integrity sha1-Zs0Md0rz1P7axTeU90LbVtqPCew= - -looper@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/looper/-/looper-3.0.0.tgz#2efa54c3b1cbaba9b94aee2e5914b0be57fbb749" - integrity sha1-LvpUw7HLq6m5Su4uWRSwvlf7t0k= - -loose-envify@^1.0.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" - integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== - dependencies: - js-tokens "^3.0.0 || ^4.0.0" - -lowercase-keys@^1.0.0, lowercase-keys@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f" - integrity sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA== - -lowercase-keys@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-2.0.0.tgz#2603e78b7b4b0006cbca2fbcc8a3202558ac9479" - integrity sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA== - -lru-cache@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-3.2.0.tgz#71789b3b7f5399bec8565dda38aa30d2a097efee" - integrity sha1-cXibO39Tmb7IVl3aOKow0qCX7+4= - dependencies: - pseudomap "^1.0.1" - -lru-cache@^4.0.1: - version "4.1.5" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd" - integrity sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g== - dependencies: - pseudomap "^1.0.2" - yallist "^2.1.2" - -lru-cache@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" - integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w== - dependencies: - yallist "^3.0.2" - -ltgt@^2.1.2, ltgt@~2.2.0: - version "2.2.1" - resolved "https://registry.yarnpkg.com/ltgt/-/ltgt-2.2.1.tgz#f35ca91c493f7b73da0e07495304f17b31f87ee5" - integrity sha1-81ypHEk/e3PaDgdJUwTxezH4fuU= - -ltgt@~2.1.1: - version "2.1.3" - resolved "https://registry.yarnpkg.com/ltgt/-/ltgt-2.1.3.tgz#10851a06d9964b971178441c23c9e52698eece34" - integrity sha1-EIUaBtmWS5cReEQcI8nlJpjuzjQ= - -make-dir@^1.0.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.3.0.tgz#79c1033b80515bd6d24ec9933e860ca75ee27f0c" - integrity sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ== - dependencies: - pify "^3.0.0" - -make-dir@^2.0.0, make-dir@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-2.1.0.tgz#5f0310e18b8be898cc07009295a30ae41e91e6f5" - integrity sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA== - dependencies: - pify "^4.0.1" - semver "^5.6.0" - -make-error@1.x: - version "1.3.5" - resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.5.tgz#efe4e81f6db28cadd605c70f29c831b58ef776c8" - integrity sha512-c3sIjNUow0+8swNwVpqoH4YCShKNFkMaw6oH1mNS2haDZQqkeZFlHS3dhoeEbKKmJB4vXpJucU6oH75aDYeE9g== - -make-iterator@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/make-iterator/-/make-iterator-1.0.1.tgz#29b33f312aa8f547c4a5e490f56afcec99133ad6" - integrity sha512-pxiuXh0iVEq7VM7KMIhs5gxsfxCux2URptUQaXo4iZZJxBAzTPOLE2BumO5dbfVYq/hBJFBR/a1mFDmOx5AGmw== - dependencies: - kind-of "^6.0.2" - -makeerror@1.0.x: - version "1.0.11" - resolved "https://registry.yarnpkg.com/makeerror/-/makeerror-1.0.11.tgz#e01a5c9109f2af79660e4e8b9587790184f5a96c" - integrity sha1-4BpckQnyr3lmDk6LlYd5AYT1qWw= - dependencies: - tmpl "1.0.x" - -map-cache@^0.2.0, map-cache@^0.2.2: - version "0.2.2" - resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" - integrity sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8= - -map-visit@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f" - integrity sha1-7Nyo8TFE5mDxtb1B8S80edmN+48= - dependencies: - object-visit "^1.0.0" - -matchdep@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/matchdep/-/matchdep-2.0.0.tgz#c6f34834a0d8dbc3b37c27ee8bbcb27c7775582e" - integrity sha1-xvNINKDY28OzfCfui7yyfHd1WC4= - dependencies: - findup-sync "^2.0.0" - micromatch "^3.0.4" - resolve "^1.4.0" - stack-trace "0.0.10" - -md5.js@^1.3.4: - version "1.3.5" - resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f" - integrity sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg== - dependencies: - hash-base "^3.0.0" - inherits "^2.0.1" - safe-buffer "^5.1.2" - -media-typer@0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" - integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g= - -mem@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/mem/-/mem-1.1.0.tgz#5edd52b485ca1d900fe64895505399a0dfa45f76" - integrity sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y= - dependencies: - mimic-fn "^1.0.0" - -memdown@^1.0.0: - version "1.4.1" - resolved "https://registry.yarnpkg.com/memdown/-/memdown-1.4.1.tgz#b4e4e192174664ffbae41361aa500f3119efe215" - integrity sha1-tOThkhdGZP+65BNhqlAPMRnv4hU= - dependencies: - abstract-leveldown "~2.7.1" - functional-red-black-tree "^1.0.1" - immediate "^3.2.3" - inherits "~2.0.1" - ltgt "~2.2.0" - safe-buffer "~5.1.1" - -memdown@~3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/memdown/-/memdown-3.0.0.tgz#93aca055d743b20efc37492e9e399784f2958309" - integrity sha512-tbV02LfZMWLcHcq4tw++NuqMO+FZX8tNJEiD2aNRm48ZZusVg5N8NART+dmBkepJVye986oixErf7jfXboMGMA== - dependencies: - abstract-leveldown "~5.0.0" - functional-red-black-tree "~1.0.1" - immediate "~3.2.3" - inherits "~2.0.1" - ltgt "~2.2.0" - safe-buffer "~5.1.1" - -memory-fs@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.4.1.tgz#3a9a20b8462523e447cfbc7e8bb80ed667bfc552" - integrity sha1-OpoguEYlI+RHz7x+i7gO1me/xVI= - dependencies: - errno "^0.1.3" - readable-stream "^2.0.1" - -memory-fs@^0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.5.0.tgz#324c01288b88652966d161db77838720845a8e3c" - integrity sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA== - dependencies: - errno "^0.1.3" - readable-stream "^2.0.1" - -memorystream@^0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/memorystream/-/memorystream-0.3.1.tgz#86d7090b30ce455d63fbae12dda51a47ddcaf9b2" - integrity sha1-htcJCzDORV1j+64S3aUaR93K+bI= - -merge-descriptors@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" - integrity sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E= - -merge-stream@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" - integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== - -merge2@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.3.0.tgz#5b366ee83b2f1582c48f87e47cf1a9352103ca81" - integrity sha512-2j4DAdlBOkiSZIsaXk4mTE3sRS02yBHAtfy127xRV3bQUFqXkjHCHLW6Scv7DwNRbIWNHH8zpnz9zMaKXIdvYw== - -merkle-patricia-tree@2.3.2, merkle-patricia-tree@^2.1.2, merkle-patricia-tree@^2.3.2: - version "2.3.2" - resolved "https://registry.yarnpkg.com/merkle-patricia-tree/-/merkle-patricia-tree-2.3.2.tgz#982ca1b5a0fde00eed2f6aeed1f9152860b8208a" - integrity sha512-81PW5m8oz/pz3GvsAwbauj7Y00rqm81Tzad77tHBwU7pIAtN+TJnMSOJhxBKflSVYhptMMb9RskhqHqrSm1V+g== - dependencies: - async "^1.4.2" - ethereumjs-util "^5.0.0" - level-ws "0.0.0" - levelup "^1.2.1" - memdown "^1.0.0" - readable-stream "^2.0.0" - rlp "^2.0.0" - semaphore ">=1.0.1" - -methods@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" - integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4= - -micromatch@^3.0.4, micromatch@^3.1.10, micromatch@^3.1.4: - version "3.1.10" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" - integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg== - dependencies: - arr-diff "^4.0.0" - array-unique "^0.3.2" - braces "^2.3.1" - define-property "^2.0.2" - extend-shallow "^3.0.2" - extglob "^2.0.4" - fragment-cache "^0.2.1" - kind-of "^6.0.2" - nanomatch "^1.2.9" - object.pick "^1.3.0" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.2" - -micromatch@^4.0.0, micromatch@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.2.tgz#4fcb0999bf9fbc2fcbdd212f6d629b9a56c39259" - integrity sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q== - dependencies: - braces "^3.0.1" - picomatch "^2.0.5" - -miller-rabin@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/miller-rabin/-/miller-rabin-4.0.1.tgz#f080351c865b0dc562a8462966daa53543c78a4d" - integrity sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA== - dependencies: - bn.js "^4.0.0" - brorand "^1.0.1" - -mime-db@1.42.0: - version "1.42.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.42.0.tgz#3e252907b4c7adb906597b4b65636272cf9e7bac" - integrity sha512-UbfJCR4UAVRNgMpfImz05smAXK7+c+ZntjaA26ANtkXLlOe947Aag5zdIcKQULAiF9Cq4WxBi9jUs5zkA84bYQ== - -mime-types@^2.1.12, mime-types@^2.1.16, mime-types@~2.1.19, mime-types@~2.1.24: - version "2.1.25" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.25.tgz#39772d46621f93e2a80a856c53b86a62156a6437" - integrity sha512-5KhStqB5xpTAeGqKBAMgwaYMnQik7teQN4IAzC7npDv6kzeU6prfkR67bc87J1kWMPGkoaZSq1npmexMgkmEVg== - dependencies: - mime-db "1.42.0" - -mime@1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" - integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== - -mimic-fn@^1.0.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022" - integrity sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ== - -mimic-response@^1.0.0, mimic-response@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b" - integrity sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ== - -mimic-response@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-2.0.0.tgz#996a51c60adf12cb8a87d7fb8ef24c2f3d5ebb46" - integrity sha512-8ilDoEapqA4uQ3TwS0jakGONKXVJqpy+RpM+3b7pLdOjghCrEiGp9SRkFbUHAmZW9vdnrENWHjaweIoTIJExSQ== - -min-document@^2.19.0: - version "2.19.0" - resolved "https://registry.yarnpkg.com/min-document/-/min-document-2.19.0.tgz#7bd282e3f5842ed295bb748cdd9f1ffa2c824685" - integrity sha1-e9KC4/WELtKVu3SM3Z8f+iyCRoU= - dependencies: - dom-walk "^0.1.0" - -minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" - integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== - -minimalistic-crypto-utils@^1.0.0, minimalistic-crypto-utils@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" - integrity sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo= - -"minimatch@2 || 3", minimatch@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" - integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== - dependencies: - brace-expansion "^1.1.7" - -minimist@0.0.8: - version "0.0.8" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" - integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0= - -minimist@^1.1.1, minimist@^1.2.0, minimist@~1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" - integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ= - -minimist@^1.2.5: - version "1.2.5" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" - integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== - -minimist@~0.0.1: - version "0.0.10" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf" - integrity sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8= - -minipass@^2.6.0, minipass@^2.8.6, minipass@^2.9.0: - version "2.9.0" - resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.9.0.tgz#e713762e7d3e32fed803115cf93e04bca9fcc9a6" - integrity sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg== - dependencies: - safe-buffer "^5.1.2" - yallist "^3.0.0" - -minizlib@^1.2.1: - version "1.3.3" - resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.3.3.tgz#2290de96818a34c29551c8a8d301216bd65a861d" - integrity sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q== - dependencies: - minipass "^2.9.0" - -mississippi@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/mississippi/-/mississippi-3.0.0.tgz#ea0a3291f97e0b5e8776b363d5f0a12d94c67022" - integrity sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA== - dependencies: - concat-stream "^1.5.0" - duplexify "^3.4.2" - end-of-stream "^1.1.0" - flush-write-stream "^1.0.0" - from2 "^2.1.0" - parallel-transform "^1.1.0" - pump "^3.0.0" - pumpify "^1.3.3" - stream-each "^1.1.0" - through2 "^2.0.0" - -mixin-deep@^1.2.0: - version "1.3.2" - resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.2.tgz#1120b43dc359a785dce65b55b82e257ccf479566" - integrity sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA== - dependencies: - for-in "^1.0.2" - is-extendable "^1.0.1" - -mkdirp-promise@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/mkdirp-promise/-/mkdirp-promise-5.0.1.tgz#e9b8f68e552c68a9c1713b84883f7a1dd039b8a1" - integrity sha1-6bj2jlUsaKnBcTuEiD96HdA5uKE= - dependencies: - mkdirp "*" - -mkdirp@*, mkdirp@0.5.1, mkdirp@0.5.x, mkdirp@0.x, mkdirp@^0.5.0, mkdirp@^0.5.1: - version "0.5.1" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" - integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM= - dependencies: - minimist "0.0.8" - -mkdirp@^0.5.3: - version "0.5.5" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" - integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ== - dependencies: - minimist "^1.2.5" - -mkdirp@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" - integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== - -mocha@^4.0.1: - version "4.1.0" - resolved "https://registry.yarnpkg.com/mocha/-/mocha-4.1.0.tgz#7d86cfbcf35cb829e2754c32e17355ec05338794" - integrity sha512-0RVnjg1HJsXY2YFDoTNzcc1NKhYuXKRrBAG2gDygmJJA136Cs2QlRliZG1mA0ap7cuaT30mw16luAeln+4RiNA== - dependencies: - browser-stdout "1.3.0" - commander "2.11.0" - debug "3.1.0" - diff "3.3.1" - escape-string-regexp "1.0.5" - glob "7.1.2" - growl "1.10.3" - he "1.1.1" - mkdirp "0.5.1" - supports-color "4.4.0" - -mock-fs@^4.1.0: - version "4.10.4" - resolved "https://registry.yarnpkg.com/mock-fs/-/mock-fs-4.10.4.tgz#4eaa3d6f7da2f44e1f3dd6b462cbbcb7b082e3d4" - integrity sha512-gDfZDLaPIvtOusbusLinfx6YSe2YpQsDT8qdP41P47dQ/NQggtkHukz7hwqgt8QvMBmAv+Z6DGmXPyb5BWX2nQ== - -move-concurrently@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/move-concurrently/-/move-concurrently-1.0.1.tgz#be2c005fda32e0b29af1f05d7c4b33214c701f92" - integrity sha1-viwAX9oy4LKa8fBdfEszIUxwH5I= - dependencies: - aproba "^1.1.1" - copy-concurrently "^1.0.0" - fs-write-stream-atomic "^1.0.8" - mkdirp "^0.5.1" - rimraf "^2.5.4" - run-queue "^1.0.3" - -ms@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" - integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= - -ms@2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" - integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg== - -ms@^2.1.1: - version "2.1.2" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" - integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== - -multibase@^0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/multibase/-/multibase-0.7.0.tgz#1adfc1c50abe05eefeb5091ac0c2728d6b84581b" - integrity sha512-TW8q03O0f6PNFTQDvh3xxH03c8CjGaaYrjkl9UQPG6rz53TQzzxJVCIWVjzcbN/Q5Y53Zd0IBQBMVktVgNx4Fg== - dependencies: - base-x "^3.0.8" - buffer "^5.5.0" - -multibase@~0.6.0: - version "0.6.1" - resolved "https://registry.yarnpkg.com/multibase/-/multibase-0.6.1.tgz#b76df6298536cc17b9f6a6db53ec88f85f8cc12b" - integrity sha512-pFfAwyTjbbQgNc3G7D48JkJxWtoJoBMaR4xQUOuB8RnCgRqaYmWNFeJTTvrJ2w51bjLq2zTby6Rqj9TQ9elSUw== - dependencies: - base-x "^3.0.8" - buffer "^5.5.0" - -multicodec@^0.5.5: - version "0.5.7" - resolved "https://registry.yarnpkg.com/multicodec/-/multicodec-0.5.7.tgz#1fb3f9dd866a10a55d226e194abba2dcc1ee9ffd" - integrity sha512-PscoRxm3f+88fAtELwUnZxGDkduE2HD9Q6GHUOywQLjOGT/HAdhjLDYNZ1e7VR0s0TP0EwZ16LNUTFpoBGivOA== - dependencies: - varint "^5.0.0" - -multicodec@^1.0.0: - version "1.0.4" - resolved "https://registry.yarnpkg.com/multicodec/-/multicodec-1.0.4.tgz#46ac064657c40380c28367c90304d8ed175a714f" - integrity sha512-NDd7FeS3QamVtbgfvu5h7fd1IlbaC4EQ0/pgU4zqE2vdHCmBGsUa0TiM8/TdSeG6BMPC92OOCf8F1ocE/Wkrrg== - dependencies: - buffer "^5.6.0" - varint "^5.0.0" - -multihashes@^0.4.15, multihashes@~0.4.15: - version "0.4.21" - resolved "https://registry.yarnpkg.com/multihashes/-/multihashes-0.4.21.tgz#dc02d525579f334a7909ade8a122dabb58ccfcb5" - integrity sha512-uVSvmeCWf36pU2nB4/1kzYZjsXD9vofZKpgudqkceYY5g2aZZXJ5r9lxuzoRLl1OAp28XljXsEJ/X/85ZsKmKw== - dependencies: - buffer "^5.5.0" - multibase "^0.7.0" - varint "^5.0.0" - -mute-stdout@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/mute-stdout/-/mute-stdout-1.0.1.tgz#acb0300eb4de23a7ddeec014e3e96044b3472331" - integrity sha512-kDcwXR4PS7caBpuRYYBUz9iVixUk3anO3f5OYFiIPwK/20vCzKCHyKoulbiDY1S53zD2bxUpxN/IJ+TnXjfvxg== - -nan@2.13.2: - version "2.13.2" - resolved "https://registry.yarnpkg.com/nan/-/nan-2.13.2.tgz#f51dc7ae66ba7d5d55e1e6d4d8092e802c9aefe7" - integrity sha512-TghvYc72wlMGMVMluVo9WRJc0mB8KxxF/gZ4YYFy7V2ZQX9l7rgbPg7vjS9mt6U5HXODVFVI2bOduCzwOMv/lw== - -nan@^2.11.0, nan@^2.12.1, nan@^2.13.2, nan@^2.14.0, nan@^2.2.1: - version "2.14.0" - resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.0.tgz#7818f722027b2459a86f0295d434d1fc2336c52c" - integrity sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg== - -nano-json-stream-parser@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/nano-json-stream-parser/-/nano-json-stream-parser-0.1.2.tgz#0cc8f6d0e2b622b479c40d499c46d64b755c6f5f" - integrity sha1-DMj20OK2IrR5xA1JnEbWS3Vcb18= - -nanomatch@^1.2.9: - version "1.2.13" - resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" - integrity sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA== - dependencies: - arr-diff "^4.0.0" - array-unique "^0.3.2" - define-property "^2.0.2" - extend-shallow "^3.0.2" - fragment-cache "^0.2.1" - is-windows "^1.0.2" - kind-of "^6.0.2" - object.pick "^1.3.0" - regex-not "^1.0.0" - snapdragon "^0.8.1" - to-regex "^3.0.1" - -napi-build-utils@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/napi-build-utils/-/napi-build-utils-1.0.1.tgz#1381a0f92c39d66bf19852e7873432fc2123e508" - integrity sha512-boQj1WFgQH3v4clhu3mTNfP+vOBxorDlE8EKiMjUlLG3C4qAESnn9AxIOkFgTR2c9LtzNjPrjS60cT27ZKBhaA== - -natural-compare@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" - integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= - -needle@^2.2.1: - version "2.4.0" - resolved "https://registry.yarnpkg.com/needle/-/needle-2.4.0.tgz#6833e74975c444642590e15a750288c5f939b57c" - integrity sha512-4Hnwzr3mi5L97hMYeNl8wRW/Onhy4nUKR/lVemJ8gJedxxUyBLm9kkrDColJvoSfwi0jCNhD+xCdOtiGDQiRZg== - dependencies: - debug "^3.2.6" - iconv-lite "^0.4.4" - sax "^1.2.4" - -negotiator@0.6.2: - version "0.6.2" - resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb" - integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw== - -neo-async@^2.5.0, neo-async@^2.6.0, neo-async@^2.6.1: - version "2.6.1" - resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.1.tgz#ac27ada66167fa8849a6addd837f6b189ad2081c" - integrity sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw== - -next-tick@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.0.0.tgz#ca86d1fe8828169b0120208e3dc8424b9db8342c" - integrity sha1-yobR/ogoFpsBICCOPchCS524NCw= - -nice-try@^1.0.4: - version "1.0.5" - resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" - integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== - -node-abi@^2.7.0: - version "2.13.0" - resolved "https://registry.yarnpkg.com/node-abi/-/node-abi-2.13.0.tgz#e2f2ec444d0aca3ea1b3874b6de41d1665828f63" - integrity sha512-9HrZGFVTR5SOu3PZAnAY2hLO36aW1wmA+FDsVkr85BTST32TLCA1H/AEcatVRAsWLyXS3bqUDYCAjq5/QGuSTA== - dependencies: - semver "^5.4.1" - -node-fetch@2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.1.2.tgz#ab884e8e7e57e38a944753cec706f788d1768bb5" - integrity sha1-q4hOjn5X44qUR1POxwb3iNF2i7U= - -node-fetch@^1.0.1, node-fetch@~1.7.1: - version "1.7.3" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.7.3.tgz#980f6f72d85211a5347c6b2bc18c5b84c3eb47ef" - integrity sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ== - dependencies: - encoding "^0.1.11" - is-stream "^1.0.1" - -node-hid@^0.7.9: - version "0.7.9" - resolved "https://registry.yarnpkg.com/node-hid/-/node-hid-0.7.9.tgz#cc0cdf1418a286a7667f0b63642b5eeb544ccd05" - integrity sha512-vJnonTqmq3frCyTumJqG4g2IZcny3ynkfmbfDfQ90P3ZhRzcWYS/Um1ux6HFmAxmkaQnrZqIYHcGpL7kdqY8jA== - dependencies: - bindings "^1.5.0" - nan "^2.13.2" - prebuild-install "^5.3.0" - -node-int64@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" - integrity sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs= - -node-libs-browser@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/node-libs-browser/-/node-libs-browser-2.2.1.tgz#b64f513d18338625f90346d27b0d235e631f6425" - integrity sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q== - dependencies: - assert "^1.1.1" - browserify-zlib "^0.2.0" - buffer "^4.3.0" - console-browserify "^1.1.0" - constants-browserify "^1.0.0" - crypto-browserify "^3.11.0" - domain-browser "^1.1.1" - events "^3.0.0" - https-browserify "^1.0.0" - os-browserify "^0.3.0" - path-browserify "0.0.1" - process "^0.11.10" - punycode "^1.2.4" - querystring-es3 "^0.2.0" - readable-stream "^2.3.3" - stream-browserify "^2.0.1" - stream-http "^2.7.2" - string_decoder "^1.0.0" - timers-browserify "^2.0.4" - tty-browserify "0.0.0" - url "^0.11.0" - util "^0.11.0" - vm-browserify "^1.0.1" - -node-modules-regexp@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/node-modules-regexp/-/node-modules-regexp-1.0.0.tgz#8d9dbe28964a4ac5712e9131642107c71e90ec40" - integrity sha1-jZ2+KJZKSsVxLpExZCEHxx6Q7EA= - -node-notifier@^5.4.2: - version "5.4.3" - resolved "https://registry.yarnpkg.com/node-notifier/-/node-notifier-5.4.3.tgz#cb72daf94c93904098e28b9c590fd866e464bd50" - integrity sha512-M4UBGcs4jeOK9CjTsYwkvH6/MzuUmGCyTW+kCY7uO+1ZVr0+FHGdPdIf5CCLqAaxnRrWidyoQlNkMIIVwbKB8Q== - dependencies: - growly "^1.3.0" - is-wsl "^1.1.0" - semver "^5.5.0" - shellwords "^0.1.1" - which "^1.3.0" - -node-pre-gyp@^0.12.0: - version "0.12.0" - resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.12.0.tgz#39ba4bb1439da030295f899e3b520b7785766149" - integrity sha512-4KghwV8vH5k+g2ylT+sLTjy5wmUOb9vPhnM8NHvRf9dHmnW/CndrFXy2aRPaPST6dugXSdHXfeaHQm77PIz/1A== - dependencies: - detect-libc "^1.0.2" - mkdirp "^0.5.1" - needle "^2.2.1" - nopt "^4.0.1" - npm-packlist "^1.1.6" - npmlog "^4.0.2" - rc "^1.2.7" - rimraf "^2.6.1" - semver "^5.3.0" - tar "^4" - -noop-logger@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/noop-logger/-/noop-logger-0.1.1.tgz#94a2b1633c4f1317553007d8966fd0e841b6a4c2" - integrity sha1-lKKxYzxPExdVMAfYlm/Q6EG2pMI= - -nopt@3.x: - version "3.0.6" - resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9" - integrity sha1-xkZdvwirzU2zWTF/eaxopkayj/k= - dependencies: - abbrev "1" - -nopt@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.1.tgz#d0d4685afd5415193c8c7505602d0d17cd64474d" - integrity sha1-0NRoWv1UFRk8jHUFYC0NF81kR00= - dependencies: - abbrev "1" - osenv "^0.1.4" - -normalize-package-data@^2.3.2: - version "2.5.0" - resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" - integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA== - dependencies: - hosted-git-info "^2.1.4" - resolve "^1.10.0" - semver "2 || 3 || 4 || 5" - validate-npm-package-license "^3.0.1" - -normalize-path@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" - integrity sha1-GrKLVW4Zg2Oowab35vogE3/mrtk= - dependencies: - remove-trailing-separator "^1.0.1" - -normalize-path@^3.0.0, normalize-path@~3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" - integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== - -normalize-url@^4.1.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-4.5.0.tgz#453354087e6ca96957bd8f5baf753f5982142129" - integrity sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ== - -now-and-later@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/now-and-later/-/now-and-later-2.0.1.tgz#8e579c8685764a7cc02cb680380e94f43ccb1f7c" - integrity sha512-KGvQ0cB70AQfg107Xvs/Fbu+dGmZoTRJp2TaPwcwQm3/7PteUyN2BCgk8KBMPGBUXZdVwyWS8fDCGFygBm19UQ== - dependencies: - once "^1.3.2" - -npm-bundled@^1.0.1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.1.0.tgz#2e8fdb7e69eff2df963937b696243316537c284b" - integrity sha512-ez6dcKBFNo4FvlMqscBEFUum6M2FTLW5grqm3DyBKB5XOyKVCeeWvAuoZtbmW/5Cv8EM2bQUOA6ufxa/TKVN0g== - -npm-packlist@^1.1.6: - version "1.4.6" - resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.4.6.tgz#53ba3ed11f8523079f1457376dd379ee4ea42ff4" - integrity sha512-u65uQdb+qwtGvEJh/DgQgW1Xg7sqeNbmxYyrvlNznaVTjV3E5P6F/EFjM+BVHXl7JJlsdG8A64M0XI8FI/IOlg== - dependencies: - ignore-walk "^3.0.1" - npm-bundled "^1.0.1" - -npm-run-path@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f" - integrity sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8= - dependencies: - path-key "^2.0.0" - -npmlog@^4.0.1, npmlog@^4.0.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" - integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg== - dependencies: - are-we-there-yet "~1.1.2" - console-control-strings "~1.1.0" - gauge "~2.7.3" - set-blocking "~2.0.0" - -number-is-nan@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" - integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0= - -number-to-bn@1.7.0: - version "1.7.0" - resolved "https://registry.yarnpkg.com/number-to-bn/-/number-to-bn-1.7.0.tgz#bb3623592f7e5f9e0030b1977bd41a0c53fe1ea0" - integrity sha1-uzYjWS9+X54AMLGXe9QaDFP+HqA= - dependencies: - bn.js "4.11.6" - strip-hex-prefix "1.0.0" - -nwsapi@^2.0.7: - version "2.2.0" - resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.0.tgz#204879a9e3d068ff2a55139c2c772780681a38b7" - integrity sha512-h2AatdwYH+JHiZpv7pt/gSX1XoRGb7L/qSIeuqA6GwYoF9w1vP1cw42TO0aI2pNyshRK5893hNSl+1//vHK7hQ== - -oauth-sign@~0.9.0: - version "0.9.0" - resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" - integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== - -object-assign@^4, object-assign@^4.0.0, object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" - integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= - -object-copy@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c" - integrity sha1-fn2Fi3gb18mRpBupde04EnVOmYw= - dependencies: - copy-descriptor "^0.1.0" - define-property "^0.2.5" - kind-of "^3.0.3" - -object-inspect@^1.7.0: - version "1.7.0" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.7.0.tgz#f4f6bd181ad77f006b5ece60bd0b6f398ff74a67" - integrity sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw== - -object-inspect@~1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.6.0.tgz#c70b6cbf72f274aab4c34c0c82f5167bf82cf15b" - integrity sha512-GJzfBZ6DgDAmnuaM3104jR4s1Myxr3Y3zfIyN4z3UdqN69oSRacNK8UhnobDdC+7J2AHCjGwxQubNJfE70SXXQ== - -object-keys@^1.0.11, object-keys@^1.0.12, object-keys@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" - integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== - -object-keys@~0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-0.4.0.tgz#28a6aae7428dd2c3a92f3d95f21335dd204e0336" - integrity sha1-KKaq50KN0sOpLz2V8hM13SBOAzY= - -object-visit@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb" - integrity sha1-95xEk68MU3e1n+OdOV5BBC3QRbs= - dependencies: - isobject "^3.0.0" - -object.assign@^4.0.4, object.assign@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.0.tgz#968bf1100d7956bb3ca086f006f846b3bc4008da" - integrity sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w== - dependencies: - define-properties "^1.1.2" - function-bind "^1.1.1" - has-symbols "^1.0.0" - object-keys "^1.0.11" - -object.defaults@^1.0.0, object.defaults@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/object.defaults/-/object.defaults-1.1.0.tgz#3a7f868334b407dea06da16d88d5cd29e435fecf" - integrity sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8= - dependencies: - array-each "^1.0.1" - array-slice "^1.0.0" - for-own "^1.0.0" - isobject "^3.0.0" - -object.getownpropertydescriptors@^2.0.3: - version "2.1.0" - resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.0.tgz#369bf1f9592d8ab89d712dced5cb81c7c5352649" - integrity sha512-Z53Oah9A3TdLoblT7VKJaTDdXdT+lQO+cNpKVnya5JDe9uLvzu1YyY1yFDFrcxrlRgWrEFH0jJtD/IbuwjcEVg== - dependencies: - define-properties "^1.1.3" - es-abstract "^1.17.0-next.1" - -object.map@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/object.map/-/object.map-1.0.1.tgz#cf83e59dc8fcc0ad5f4250e1f78b3b81bd801d37" - integrity sha1-z4Plncj8wK1fQlDh94s7gb2AHTc= - dependencies: - for-own "^1.0.0" - make-iterator "^1.0.0" - -object.pick@^1.2.0, object.pick@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" - integrity sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c= - dependencies: - isobject "^3.0.1" - -object.reduce@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/object.reduce/-/object.reduce-1.0.1.tgz#6fe348f2ac7fa0f95ca621226599096825bb03ad" - integrity sha1-b+NI8qx/oPlcpiEiZZkJaCW7A60= - dependencies: - for-own "^1.0.0" - make-iterator "^1.0.0" - -oboe@2.1.4: - version "2.1.4" - resolved "https://registry.yarnpkg.com/oboe/-/oboe-2.1.4.tgz#20c88cdb0c15371bb04119257d4fdd34b0aa49f6" - integrity sha1-IMiM2wwVNxuwQRklfU/dNLCqSfY= - dependencies: - http-https "^1.0.0" - -on-finished@~2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" - integrity sha1-IPEzZIGwg811M3mSoWlxqi2QaUc= - dependencies: - ee-first "1.1.1" - -once@1.x, once@^1.3.0, once@^1.3.1, once@^1.3.2, once@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" - integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= - dependencies: - wrappy "1" - -opener@^1.5.1: - version "1.5.1" - resolved "https://registry.yarnpkg.com/opener/-/opener-1.5.1.tgz#6d2f0e77f1a0af0032aca716c2c1fbb8e7e8abed" - integrity sha512-goYSy5c2UXE4Ra1xixabeVh1guIX/ZV/YokJksb6q2lubWu6UbvPQ20p542/sFIll1nl8JnCyK9oBaOcCWXwvA== - -optimist@^0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686" - integrity sha1-2j6nRob6IaGaERwybpDrFaAZZoY= - dependencies: - minimist "~0.0.1" - wordwrap "~0.0.2" - -optionator@^0.8.1: - version "0.8.3" - resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495" - integrity sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA== - dependencies: - deep-is "~0.1.3" - fast-levenshtein "~2.0.6" - levn "~0.3.0" - prelude-ls "~1.1.2" - type-check "~0.3.2" - word-wrap "~1.2.3" - -ordered-read-streams@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/ordered-read-streams/-/ordered-read-streams-1.0.1.tgz#77c0cb37c41525d64166d990ffad7ec6a0e1363e" - integrity sha1-d8DLN8QVJdZBZtmQ/61+xqDhNj4= - dependencies: - readable-stream "^2.0.1" - -os-browserify@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.3.0.tgz#854373c7f5c2315914fc9bfc6bd8238fdda1ec27" - integrity sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc= - -os-homedir@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" - integrity sha1-/7xJiDNuDoM94MFox+8VISGqf7M= - -os-locale@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-1.4.0.tgz#20f9f17ae29ed345e8bde583b13d2009803c14d9" - integrity sha1-IPnxeuKe00XoveWDsT0gCYA8FNk= - dependencies: - lcid "^1.0.0" - -os-locale@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-2.1.0.tgz#42bc2900a6b5b8bd17376c8e882b65afccf24bf2" - integrity sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA== - dependencies: - execa "^0.7.0" - lcid "^1.0.0" - mem "^1.1.0" - -os-tmpdir@^1.0.0, os-tmpdir@^1.0.1, os-tmpdir@~1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" - integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ= - -osenv@^0.1.4: - version "0.1.5" - resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.5.tgz#85cdfafaeb28e8677f416e287592b5f3f49ea410" - integrity sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g== - dependencies: - os-homedir "^1.0.0" - os-tmpdir "^1.0.0" - -p-cancelable@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-0.3.0.tgz#b9e123800bcebb7ac13a479be195b507b98d30fa" - integrity sha512-RVbZPLso8+jFeq1MfNvgXtCRED2raz/dKpacfTNxsx6pLEpEomM7gah6VeHSYV3+vo0OAi4MkArtQcWWXuQoyw== - -p-cancelable@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-1.1.0.tgz#d078d15a3af409220c886f1d9a0ca2e441ab26cc" - integrity sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw== - -p-each-series@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/p-each-series/-/p-each-series-1.0.0.tgz#930f3d12dd1f50e7434457a22cd6f04ac6ad7f71" - integrity sha1-kw89Et0fUOdDRFeiLNbwSsatf3E= - dependencies: - p-reduce "^1.0.0" - -p-finally@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" - integrity sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4= - -p-limit@^1.1.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8" - integrity sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q== - dependencies: - p-try "^1.0.0" - -p-limit@^2.0.0: - version "2.2.1" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.2.1.tgz#aa07a788cc3151c939b5131f63570f0dd2009537" - integrity sha512-85Tk+90UCVWvbDavCLKPOLC9vvY8OwEX/RtKF+/1OADJMVlFfEHOiMTPVyxg7mk/dKa+ipdHm0OUkTvCpMTuwg== - dependencies: - p-try "^2.0.0" - -p-locate@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" - integrity sha1-IKAQOyIqcMj9OcwuWAaA893l7EM= - dependencies: - p-limit "^1.1.0" - -p-locate@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4" - integrity sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ== - dependencies: - p-limit "^2.0.0" - -p-reduce@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/p-reduce/-/p-reduce-1.0.0.tgz#18c2b0dd936a4690a529f8231f58a0fdb6a47dfa" - integrity sha1-GMKw3ZNqRpClKfgjH1ig/bakffo= - -p-timeout@^1.1.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/p-timeout/-/p-timeout-1.2.1.tgz#5eb3b353b7fce99f101a1038880bb054ebbea386" - integrity sha1-XrOzU7f86Z8QGhA4iAuwVOu+o4Y= - dependencies: - p-finally "^1.0.0" - -p-try@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" - integrity sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M= - -p-try@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" - integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== - -pako@~1.0.5: - version "1.0.10" - resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.10.tgz#4328badb5086a426aa90f541977d4955da5c9732" - integrity sha512-0DTvPVU3ed8+HNXOu5Bs+o//Mbdj9VNQMUOe9oKCwh8l0GNwpTDMKCWbRjgtD291AWnkAgkqA/LOnQS8AmS1tw== - -parallel-transform@^1.1.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/parallel-transform/-/parallel-transform-1.2.0.tgz#9049ca37d6cb2182c3b1d2c720be94d14a5814fc" - integrity sha512-P2vSmIu38uIlvdcU7fDkyrxj33gTUy/ABO5ZUbGowxNCopBq/OoD42bP4UmMrJoPyk4Uqf0mu3mtWBhHCZD8yg== - dependencies: - cyclist "^1.0.1" - inherits "^2.0.3" - readable-stream "^2.1.5" - -parse-asn1@^5.0.0: - version "5.1.5" - resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.5.tgz#003271343da58dc94cace494faef3d2147ecea0e" - integrity sha512-jkMYn1dcJqF6d5CpU689bq7w/b5ALS9ROVSpQDPrZsqqesUJii9qutvoT5ltGedNXMO2e16YUWIghG9KxaViTQ== - dependencies: - asn1.js "^4.0.0" - browserify-aes "^1.0.0" - create-hash "^1.1.0" - evp_bytestokey "^1.0.0" - pbkdf2 "^3.0.3" - safe-buffer "^5.1.1" - -parse-filepath@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/parse-filepath/-/parse-filepath-1.0.2.tgz#a632127f53aaf3d15876f5872f3ffac763d6c891" - integrity sha1-pjISf1Oq89FYdvWHLz/6x2PWyJE= - dependencies: - is-absolute "^1.0.0" - map-cache "^0.2.0" - path-root "^0.1.1" - -parse-headers@^2.0.0: - version "2.0.3" - resolved "https://registry.yarnpkg.com/parse-headers/-/parse-headers-2.0.3.tgz#5e8e7512383d140ba02f0c7aa9f49b4399c92515" - integrity sha512-QhhZ+DCCit2Coi2vmAKbq5RGTRcQUOE2+REgv8vdyu7MnYx2eZztegqtTx99TZ86GTIwqiy3+4nQTWZ2tgmdCA== - -parse-json@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9" - integrity sha1-9ID0BDTvgHQfhGkJn43qGPVaTck= - dependencies: - error-ex "^1.2.0" - -parse-json@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0" - integrity sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA= - dependencies: - error-ex "^1.3.1" - json-parse-better-errors "^1.0.1" - -parse-node-version@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/parse-node-version/-/parse-node-version-1.0.1.tgz#e2b5dbede00e7fa9bc363607f53327e8b073189b" - integrity sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA== - -parse-passwd@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/parse-passwd/-/parse-passwd-1.0.0.tgz#6d5b934a456993b23d37f40a382d6f1666a8e5c6" - integrity sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY= - -parse5@4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/parse5/-/parse5-4.0.0.tgz#6d78656e3da8d78b4ec0b906f7c08ef1dfe3f608" - integrity sha512-VrZ7eOd3T1Fk4XWNXMgiGBK/z0MG48BWG2uQNU4I72fkQuKUTZpl+u9k+CxEG0twMVzSmXEEz12z5Fnw1jIQFA== - -parseurl@~1.3.3: - version "1.3.3" - resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" - integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== - -pascalcase@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" - integrity sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ= - -path-browserify@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-0.0.1.tgz#e6c4ddd7ed3aa27c68a20cc4e50e1a4ee83bbc4a" - integrity sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ== - -path-dirname@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0" - integrity sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA= - -path-exists@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b" - integrity sha1-D+tsZPD8UY2adU3V77YscCJ2H0s= - dependencies: - pinkie-promise "^2.0.0" - -path-exists@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" - integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU= - -path-is-absolute@^1.0.0, path-is-absolute@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" - integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= - -path-key@^2.0.0, path-key@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" - integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A= - -path-parse@^1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c" - integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw== - -path-root-regex@^0.1.0: - version "0.1.2" - resolved "https://registry.yarnpkg.com/path-root-regex/-/path-root-regex-0.1.2.tgz#bfccdc8df5b12dc52c8b43ec38d18d72c04ba96d" - integrity sha1-v8zcjfWxLcUsi0PsONGNcsBLqW0= - -path-root@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/path-root/-/path-root-0.1.1.tgz#9a4a6814cac1c0cd73360a95f32083c8ea4745b7" - integrity sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc= - dependencies: - path-root-regex "^0.1.0" - -path-to-regexp@0.1.7: - version "0.1.7" - resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" - integrity sha1-32BBeABfUi8V60SQ5yR6G/qmf4w= - -path-type@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441" - integrity sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE= - dependencies: - graceful-fs "^4.1.2" - pify "^2.0.0" - pinkie-promise "^2.0.0" - -path-type@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/path-type/-/path-type-3.0.0.tgz#cef31dc8e0a1a3bb0d105c0cd97cf3bf47f4e36f" - integrity sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg== - dependencies: - pify "^3.0.0" - -pathval@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.0.tgz#b942e6d4bde653005ef6b71361def8727d0645e0" - integrity sha1-uULm1L3mUwBe9rcTYd74cn0GReA= - -pbkdf2@^3.0.3, pbkdf2@^3.0.9: - version "3.0.17" - resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.0.17.tgz#976c206530617b14ebb32114239f7b09336e93a6" - integrity sha512-U/il5MsrZp7mGg3mSQfn742na2T+1/vHDCG5/iTI3X9MKUuYUZVLQhyRsg06mCgDBTd57TxzgZt7P+fYfjRLtA== - dependencies: - create-hash "^1.1.2" - create-hmac "^1.1.4" - ripemd160 "^2.0.1" - safe-buffer "^5.0.1" - sha.js "^2.4.8" - -pegjs@^0.10.0: - version "0.10.0" - resolved "https://registry.yarnpkg.com/pegjs/-/pegjs-0.10.0.tgz#cf8bafae6eddff4b5a7efb185269eaaf4610ddbd" - integrity sha1-z4uvrm7d/0tafvsYUmnqr0YQ3b0= - -pend@~1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50" - integrity sha1-elfrVQpng/kRUzH89GY9XI4AelA= - -performance-now@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" - integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= - -picomatch@^2.0.4: - version "2.1.1" - resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.1.1.tgz#ecdfbea7704adb5fe6fb47f9866c4c0e15e905c5" - integrity sha512-OYMyqkKzK7blWO/+XZYP6w8hH0LDvkBvdvKukti+7kqYFCiEAk+gI3DWnryapc0Dau05ugGTy0foQ6mqn4AHYA== - -picomatch@^2.0.5, picomatch@^2.2.1: - version "2.2.2" - resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.2.tgz#21f333e9b6b8eaff02468f5146ea406d345f4dad" - integrity sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg== - -pify@^2.0.0, pify@^2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" - integrity sha1-7RQaasBDqEnqWISY59yosVMw6Qw= - -pify@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176" - integrity sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY= - -pify@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231" - integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g== - -pinkie-promise@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" - integrity sha1-ITXW36ejWMBprJsXh3YogihFD/o= - dependencies: - pinkie "^2.0.0" - -pinkie@^2.0.0: - version "2.0.4" - resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" - integrity sha1-clVrgM+g1IqXToDnckjoDtT3+HA= - -pirates@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.1.tgz#643a92caf894566f91b2b986d2c66950a8e2fb87" - integrity sha512-WuNqLTbMI3tmfef2TKxlQmAiLHKtFhlsCZnPIpuv2Ow0RDVO8lfy1Opf4NUzlMXLjPl+Men7AuVdX6TA+s+uGA== - dependencies: - node-modules-regexp "^1.0.0" - -pkg-dir@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-3.0.0.tgz#2749020f239ed990881b1f71210d51eb6523bea3" - integrity sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw== - dependencies: - find-up "^3.0.0" - -pluralize@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-7.0.0.tgz#298b89df8b93b0221dbf421ad2b1b1ea23fc6777" - integrity sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow== - -pn@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/pn/-/pn-1.1.0.tgz#e2f4cef0e219f463c179ab37463e4e1ecdccbafb" - integrity sha512-2qHaIQr2VLRFoxe2nASzsV6ef4yOOH+Fi9FBOVH6cqeSgUnoyySPZkxzLuzd+RYOQTRpROA0ztTMqxROKSb/nA== - -popper.js@1.14.3: - version "1.14.3" - resolved "https://registry.yarnpkg.com/popper.js/-/popper.js-1.14.3.tgz#1438f98d046acf7b4d78cd502bf418ac64d4f095" - integrity sha1-FDj5jQRqz3tNeM1QK/QYrGTU8JU= - -posix-character-classes@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" - integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs= - -prebuild-install@^5.3.0, prebuild-install@^5.3.3: - version "5.3.3" - resolved "https://registry.yarnpkg.com/prebuild-install/-/prebuild-install-5.3.3.tgz#ef4052baac60d465f5ba6bf003c9c1de79b9da8e" - integrity sha512-GV+nsUXuPW2p8Zy7SarF/2W/oiK8bFQgJcncoJ0d7kRpekEA0ftChjfEaF9/Y+QJEc/wFR7RAEa8lYByuUIe2g== - dependencies: - detect-libc "^1.0.3" - expand-template "^2.0.3" - github-from-package "0.0.0" - minimist "^1.2.0" - mkdirp "^0.5.1" - napi-build-utils "^1.0.1" - node-abi "^2.7.0" - noop-logger "^0.1.1" - npmlog "^4.0.1" - pump "^3.0.0" - rc "^1.2.7" - simple-get "^3.0.3" - tar-fs "^2.0.0" - tunnel-agent "^0.6.0" - which-pm-runs "^1.0.0" - -precond@0.2: - version "0.2.3" - resolved "https://registry.yarnpkg.com/precond/-/precond-0.2.3.tgz#aa9591bcaa24923f1e0f4849d240f47efc1075ac" - integrity sha1-qpWRvKokkj8eD0hJ0kD0fvwQdaw= - -prelude-ls@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" - integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ= - -prepend-http@^1.0.1: - version "1.0.4" - resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc" - integrity sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw= - -prepend-http@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-2.0.0.tgz#e92434bfa5ea8c19f41cdfd401d741a3c819d897" - integrity sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc= - -pretty-format@^24.9.0: - version "24.9.0" - resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-24.9.0.tgz#12fac31b37019a4eea3c11aa9a959eb7628aa7c9" - integrity sha512-00ZMZUiHaJrNfk33guavqgvfJS30sLYf0f8+Srklv0AMPodGGHcoHgksZ3OThYnIvOd+8yMCn0YiEOogjlgsnA== - dependencies: - "@jest/types" "^24.9.0" - ansi-regex "^4.0.0" - ansi-styles "^3.2.0" - react-is "^16.8.4" - -pretty-format@^25.3.0: - version "25.3.0" - resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-25.3.0.tgz#d0a4f988ff4a6cd350342fdabbb809aeb4d49ad5" - integrity sha512-wToHwF8bkQknIcFkBqNfKu4+UZqnrLn/Vr+wwKQwwvPzkBfDDKp/qIabFqdgtoi5PEnM8LFByVsOrHoa3SpTVA== - dependencies: - "@jest/types" "^25.3.0" - ansi-regex "^5.0.0" - ansi-styles "^4.0.0" - react-is "^16.12.0" - -pretty-hrtime@^1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz#b7e3ea42435a4c9b2759d99e0f201eb195802ee1" - integrity sha1-t+PqQkNaTJsnWdmeDyAesZWALuE= - -private@^0.1.6, private@^0.1.8: - version "0.1.8" - resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff" - integrity sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg== - -process-nextick-args@^2.0.0, process-nextick-args@~2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" - integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== - -process@^0.11.10: - version "0.11.10" - resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" - integrity sha1-czIwDoQBYb2j5podHZGn1LwW8YI= - -process@~0.5.1: - version "0.5.2" - resolved "https://registry.yarnpkg.com/process/-/process-0.5.2.tgz#1638d8a8e34c2f440a91db95ab9aeb677fc185cf" - integrity sha1-FjjYqONML0QKkduVq5rrZ3/Bhc8= - -promise-inflight@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3" - integrity sha1-mEcocL8igTL8vdhoEputEsPAKeM= - -promise-to-callback@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/promise-to-callback/-/promise-to-callback-1.0.0.tgz#5d2a749010bfb67d963598fcd3960746a68feef7" - integrity sha1-XSp0kBC/tn2WNZj805YHRqaP7vc= - dependencies: - is-fn "^1.0.0" - set-immediate-shim "^1.0.1" - -prompts@^2.0.1: - version "2.3.0" - resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.3.0.tgz#a444e968fa4cc7e86689a74050685ac8006c4cc4" - integrity sha512-NfbbPPg/74fT7wk2XYQ7hAIp9zJyZp5Fu19iRbORqqy1BhtrkZ0fPafBU+7bmn8ie69DpT0R6QpJIN2oisYjJg== - dependencies: - kleur "^3.0.3" - sisteransi "^1.0.3" - -proxy-addr@~2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.5.tgz#34cbd64a2d81f4b1fd21e76f9f06c8a45299ee34" - integrity sha512-t/7RxHXPH6cJtP0pRG6smSr9QJidhB+3kXu0KgXnbGYMgzEnUxRQ4/LDdfOwZEMyIh3/xHb8PX3t+lfL9z+YVQ== - dependencies: - forwarded "~0.1.2" - ipaddr.js "1.9.0" - -prr@~1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476" - integrity sha1-0/wRS6BplaRexok/SEzrHXj19HY= - -pseudomap@^1.0.1, pseudomap@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" - integrity sha1-8FKijacOYYkX7wqKw0wa5aaChrM= - -psl@^1.1.24: - version "1.6.0" - resolved "https://registry.yarnpkg.com/psl/-/psl-1.6.0.tgz#60557582ee23b6c43719d9890fb4170ecd91e110" - integrity sha512-SYKKmVel98NCOYXpkwUqZqh0ahZeeKfmisiLIcEZdsb+WbLv02g/dI5BUmZnIyOe7RzZtLax81nnb2HbvC2tzA== - -psl@^1.1.28: - version "1.7.0" - resolved "https://registry.yarnpkg.com/psl/-/psl-1.7.0.tgz#f1c4c47a8ef97167dea5d6bbf4816d736e884a3c" - integrity sha512-5NsSEDv8zY70ScRnOTn7bK7eanl2MvFrOrS/R6x+dBt5g1ghnj9Zv90kO8GwT8gxcu2ANyFprnFYB85IogIJOQ== - -public-encrypt@^4.0.0: - version "4.0.3" - resolved "https://registry.yarnpkg.com/public-encrypt/-/public-encrypt-4.0.3.tgz#4fcc9d77a07e48ba7527e7cbe0de33d0701331e0" - integrity sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q== - dependencies: - bn.js "^4.1.0" - browserify-rsa "^4.0.0" - create-hash "^1.1.0" - parse-asn1 "^5.0.0" - randombytes "^2.0.1" - safe-buffer "^5.1.2" - -pull-cat@^1.1.9: - version "1.1.11" - resolved "https://registry.yarnpkg.com/pull-cat/-/pull-cat-1.1.11.tgz#b642dd1255da376a706b6db4fa962f5fdb74c31b" - integrity sha1-tkLdElXaN2pwa220+pYvX9t0wxs= - -pull-defer@^0.2.2: - version "0.2.3" - resolved "https://registry.yarnpkg.com/pull-defer/-/pull-defer-0.2.3.tgz#4ee09c6d9e227bede9938db80391c3dac489d113" - integrity sha512-/An3KE7mVjZCqNhZsr22k1Tx8MACnUnHZZNPSJ0S62td8JtYr/AiRG42Vz7Syu31SoTLUzVIe61jtT/pNdjVYA== - -pull-level@^2.0.3: - version "2.0.4" - resolved "https://registry.yarnpkg.com/pull-level/-/pull-level-2.0.4.tgz#4822e61757c10bdcc7cf4a03af04c92734c9afac" - integrity sha512-fW6pljDeUThpq5KXwKbRG3X7Ogk3vc75d5OQU/TvXXui65ykm+Bn+fiktg+MOx2jJ85cd+sheufPL+rw9QSVZg== - dependencies: - level-post "^1.0.7" - pull-cat "^1.1.9" - pull-live "^1.0.1" - pull-pushable "^2.0.0" - pull-stream "^3.4.0" - pull-window "^2.1.4" - stream-to-pull-stream "^1.7.1" - -pull-live@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/pull-live/-/pull-live-1.0.1.tgz#a4ecee01e330155e9124bbbcf4761f21b38f51f5" - integrity sha1-pOzuAeMwFV6RJLu89HYfIbOPUfU= - dependencies: - pull-cat "^1.1.9" - pull-stream "^3.4.0" - -pull-pushable@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/pull-pushable/-/pull-pushable-2.2.0.tgz#5f2f3aed47ad86919f01b12a2e99d6f1bd776581" - integrity sha1-Xy867UethpGfAbEqLpnW8b13ZYE= - -pull-stream@^3.2.3, pull-stream@^3.4.0, pull-stream@^3.6.8: - version "3.6.14" - resolved "https://registry.yarnpkg.com/pull-stream/-/pull-stream-3.6.14.tgz#529dbd5b86131f4a5ed636fdf7f6af00781357ee" - integrity sha512-KIqdvpqHHaTUA2mCYcLG1ibEbu/LCKoJZsBWyv9lSYtPkJPBq8m3Hxa103xHi6D2thj5YXa0TqK3L3GUkwgnew== - -pull-window@^2.1.4: - version "2.1.4" - resolved "https://registry.yarnpkg.com/pull-window/-/pull-window-2.1.4.tgz#fc3b86feebd1920c7ae297691e23f705f88552f0" - integrity sha1-/DuG/uvRkgx64pdpHiP3BfiFUvA= - dependencies: - looper "^2.0.0" - -pump@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/pump/-/pump-2.0.1.tgz#12399add6e4cf7526d973cbc8b5ce2e2908b3909" - integrity sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA== - dependencies: - end-of-stream "^1.1.0" - once "^1.3.1" - -pump@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" - integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww== - dependencies: - end-of-stream "^1.1.0" - once "^1.3.1" - -pumpify@^1.3.3, pumpify@^1.3.5: - version "1.5.1" - resolved "https://registry.yarnpkg.com/pumpify/-/pumpify-1.5.1.tgz#36513be246ab27570b1a374a5ce278bfd74370ce" - integrity sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ== - dependencies: - duplexify "^3.6.0" - inherits "^2.0.3" - pump "^2.0.0" - -punycode@1.3.2: - version "1.3.2" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" - integrity sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0= - -punycode@2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.0.tgz#5f863edc89b96db09074bad7947bf09056ca4e7d" - integrity sha1-X4Y+3Im5bbCQdLrXlHvwkFbKTn0= - -punycode@^1.2.4, punycode@^1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" - integrity sha1-wNWmOycYgArY4esPpSachN1BhF4= - -punycode@^2.1.0, punycode@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" - integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== - -qs@6.7.0: - version "6.7.0" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc" - integrity sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ== - -qs@~6.5.2: - version "6.5.2" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" - integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA== - -query-string@^5.0.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/query-string/-/query-string-5.1.1.tgz#a78c012b71c17e05f2e3fa2319dd330682efb3cb" - integrity sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw== - dependencies: - decode-uri-component "^0.2.0" - object-assign "^4.1.0" - strict-uri-encode "^1.0.0" - -querystring-es3@^0.2.0: - version "0.2.1" - resolved "https://registry.yarnpkg.com/querystring-es3/-/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73" - integrity sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM= - -querystring@0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" - integrity sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA= - -randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5, randombytes@^2.0.6, randombytes@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" - integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== - dependencies: - safe-buffer "^5.1.0" - -randomfill@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/randomfill/-/randomfill-1.0.4.tgz#c92196fc86ab42be983f1bf31778224931d61458" - integrity sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw== - dependencies: - randombytes "^2.0.5" - safe-buffer "^5.1.0" - -range-parser@~1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" - integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== - -raw-body@2.4.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.4.0.tgz#a1ce6fb9c9bc356ca52e89256ab59059e13d0332" - integrity sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q== - dependencies: - bytes "3.1.0" - http-errors "1.7.2" - iconv-lite "0.4.24" - unpipe "1.0.0" - -rc@^1.2.7: - version "1.2.8" - resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" - integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== - dependencies: - deep-extend "^0.6.0" - ini "~1.3.0" - minimist "^1.2.0" - strip-json-comments "~2.0.1" - -react-is@^16.12.0: - version "16.13.1" - resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" - integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== - -react-is@^16.8.4: - version "16.12.0" - resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.12.0.tgz#2cc0fe0fba742d97fd527c42a13bec4eeb06241c" - integrity sha512-rPCkf/mWBtKc97aLL9/txD8DZdemK0vkA3JMLShjlJB3Pj3s+lpf1KaBzMfQrAmhMQB0n1cU/SUGgKKBCe837Q== - -read-pkg-up@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02" - integrity sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI= - dependencies: - find-up "^1.0.0" - read-pkg "^1.0.0" - -read-pkg-up@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-4.0.0.tgz#1b221c6088ba7799601c808f91161c66e58f8978" - integrity sha512-6etQSH7nJGsK0RbG/2TeDzZFa8shjQ1um+SwQQ5cwKy0dhSXdOncEhb1CPpvQG4h7FyOV6EB6YlV0yJvZQNAkA== - dependencies: - find-up "^3.0.0" - read-pkg "^3.0.0" - -read-pkg@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-1.1.0.tgz#f5ffaa5ecd29cb31c0474bca7d756b6bb29e3f28" - integrity sha1-9f+qXs0pyzHAR0vKfXVra7KePyg= - dependencies: - load-json-file "^1.0.0" - normalize-package-data "^2.3.2" - path-type "^1.0.0" - -read-pkg@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-3.0.0.tgz#9cbc686978fee65d16c00e2b19c237fcf6e38389" - integrity sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k= - dependencies: - load-json-file "^4.0.0" - normalize-package-data "^2.3.2" - path-type "^3.0.0" - -"readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.5, readable-stream@^2.0.6, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.2.9, readable-stream@^2.3.0, readable-stream@^2.3.3, readable-stream@^2.3.5, readable-stream@^2.3.6, readable-stream@~2.3.6: - version "2.3.6" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" - integrity sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw== - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.3" - isarray "~1.0.0" - process-nextick-args "~2.0.0" - safe-buffer "~5.1.1" - string_decoder "~1.1.1" - util-deprecate "~1.0.1" - -readable-stream@^1.0.33: - version "1.1.14" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9" - integrity sha1-fPTFTvZI44EwhMY23SB54WbAgdk= - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.1" - isarray "0.0.1" - string_decoder "~0.10.x" - -readable-stream@^3.0.1, readable-stream@^3.1.1: - version "3.4.0" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.4.0.tgz#a51c26754658e0a3c21dbf59163bd45ba6f447fc" - integrity sha512-jItXPLmrSR8jmTRmRWJXCnGJsfy85mB3Wd/uINMXA65yrnFo0cPClFIUWzo2najVNSl+mx7/4W8ttlLWJe99pQ== - dependencies: - inherits "^2.0.3" - string_decoder "^1.1.1" - util-deprecate "^1.0.1" - -readable-stream@~1.0.15: - version "1.0.34" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c" - integrity sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw= - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.1" - isarray "0.0.1" - string_decoder "~0.10.x" - -readdirp@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.2.1.tgz#0e87622a3325aa33e892285caf8b4e846529a525" - integrity sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ== - dependencies: - graceful-fs "^4.1.11" - micromatch "^3.1.10" - readable-stream "^2.0.2" - -readdirp@~3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.2.0.tgz#c30c33352b12c96dfb4b895421a49fd5a9593839" - integrity sha512-crk4Qu3pmXwgxdSgGhgA/eXiJAPQiX4GMOZZMXnqKxHX7TaoL+3gQVo/WeuAiogr07DpnfjIMpXXa+PAIvwPGQ== - dependencies: - picomatch "^2.0.4" - -readdirp@~3.4.0: - version "3.4.0" - resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.4.0.tgz#9fdccdf9e9155805449221ac645e8303ab5b9ada" - integrity sha512-0xe001vZBnJEK+uKcj8qOhyAKPzIT+gStxWr3LCB0DwcXR5NZJ3IaC+yGnHCYzB/S7ov3m3EEbZI2zeNvX+hGQ== - dependencies: - picomatch "^2.2.1" - -realpath-native@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/realpath-native/-/realpath-native-1.1.0.tgz#2003294fea23fb0672f2476ebe22fcf498a2d65c" - integrity sha512-wlgPA6cCIIg9gKz0fgAPjnzh4yR/LnXovwuo9hvyGvx3h8nX4+/iLZplfUWasXpqD8BdnGnP5njOFjkUwPzvjA== - dependencies: - util.promisify "^1.0.0" - -rechoir@^0.6.2: - version "0.6.2" - resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384" - integrity sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q= - dependencies: - resolve "^1.1.6" - -regenerate@^1.2.1: - version "1.4.0" - resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.0.tgz#4a856ec4b56e4077c557589cae85e7a4c8869a11" - integrity sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg== - -regenerator-runtime@^0.11.0: - version "0.11.1" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9" - integrity sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg== - -regenerator-runtime@^0.13.2: - version "0.13.3" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.3.tgz#7cf6a77d8f5c6f60eb73c5fc1955b2ceb01e6bf5" - integrity sha512-naKIZz2GQ8JWh///G7L3X6LaQUAMp2lvb1rvwwsURe/VXwD6VMfr+/1NuNw3ag8v2kY1aQ/go5SNn79O9JU7yw== - -regenerator-transform@^0.10.0: - version "0.10.1" - resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.10.1.tgz#1e4996837231da8b7f3cf4114d71b5691a0680dd" - integrity sha512-PJepbvDbuK1xgIgnau7Y90cwaAmO/LCLMI2mPvaXq2heGMR3aWW5/BQvYrhJ8jgmQjXewXvBjzfqKcVOmhjZ6Q== - dependencies: - babel-runtime "^6.18.0" - babel-types "^6.19.0" - private "^0.1.6" - -regex-not@^1.0.0, regex-not@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c" - integrity sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A== - dependencies: - extend-shallow "^3.0.2" - safe-regex "^1.1.0" - -regexpu-core@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-2.0.0.tgz#49d038837b8dcf8bfa5b9a42139938e6ea2ae240" - integrity sha1-SdA4g3uNz4v6W5pCE5k45uoq4kA= - dependencies: - regenerate "^1.2.1" - regjsgen "^0.2.0" - regjsparser "^0.1.4" - -regjsgen@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.2.0.tgz#6c016adeac554f75823fe37ac05b92d5a4edb1f7" - integrity sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc= - -regjsparser@^0.1.4: - version "0.1.5" - resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.1.5.tgz#7ee8f84dc6fa792d3fd0ae228d24bd949ead205c" - integrity sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw= - dependencies: - jsesc "~0.5.0" - -remove-bom-buffer@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/remove-bom-buffer/-/remove-bom-buffer-3.0.0.tgz#c2bf1e377520d324f623892e33c10cac2c252b53" - integrity sha512-8v2rWhaakv18qcvNeli2mZ/TMTL2nEyAKRvzo1WtnZBl15SHyEhrCu2/xKlJyUFKHiHgfXIyuY6g2dObJJycXQ== - dependencies: - is-buffer "^1.1.5" - is-utf8 "^0.2.1" - -remove-bom-stream@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/remove-bom-stream/-/remove-bom-stream-1.2.0.tgz#05f1a593f16e42e1fb90ebf59de8e569525f9523" - integrity sha1-BfGlk/FuQuH7kOv1nejlaVJflSM= - dependencies: - remove-bom-buffer "^3.0.0" - safe-buffer "^5.1.0" - through2 "^2.0.3" - -remove-trailing-separator@^1.0.1, remove-trailing-separator@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" - integrity sha1-wkvOKig62tW8P1jg1IJJuSN52O8= - -repeat-element@^1.1.2: - version "1.1.3" - resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.3.tgz#782e0d825c0c5a3bb39731f84efee6b742e6b1ce" - integrity sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g== - -repeat-string@^1.6.1: - version "1.6.1" - resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" - integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc= - -repeating@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/repeating/-/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda" - integrity sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo= - dependencies: - is-finite "^1.0.0" - -replace-ext@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/replace-ext/-/replace-ext-1.0.0.tgz#de63128373fcbf7c3ccfa4de5a480c45a67958eb" - integrity sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs= - -replace-homedir@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/replace-homedir/-/replace-homedir-1.0.0.tgz#e87f6d513b928dde808260c12be7fec6ff6e798c" - integrity sha1-6H9tUTuSjd6AgmDBK+f+xv9ueYw= - dependencies: - homedir-polyfill "^1.0.1" - is-absolute "^1.0.0" - remove-trailing-separator "^1.1.0" - -request-promise-core@1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/request-promise-core/-/request-promise-core-1.1.3.tgz#e9a3c081b51380dfea677336061fea879a829ee9" - integrity sha512-QIs2+ArIGQVp5ZYbWD5ZLCY29D5CfWizP8eWnm8FoGD1TX61veauETVQbrV60662V0oFBkrDOuaBI8XgtuyYAQ== - dependencies: - lodash "^4.17.15" - -request-promise-native@^1.0.5: - version "1.0.8" - resolved "https://registry.yarnpkg.com/request-promise-native/-/request-promise-native-1.0.8.tgz#a455b960b826e44e2bf8999af64dff2bfe58cb36" - integrity sha512-dapwLGqkHtwL5AEbfenuzjTYg35Jd6KPytsC2/TLkVMz8rm+tNt72MGUWT1RP/aYawMpN6HqbNGBQaRcBtjQMQ== - dependencies: - request-promise-core "1.1.3" - stealthy-require "^1.1.1" - tough-cookie "^2.3.3" - -request@^2.67.0, request@^2.79.0, request@^2.85.0, request@^2.87.0: - version "2.88.0" - resolved "https://registry.yarnpkg.com/request/-/request-2.88.0.tgz#9c2fca4f7d35b592efe57c7f0a55e81052124fef" - integrity sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg== - dependencies: - aws-sign2 "~0.7.0" - aws4 "^1.8.0" - caseless "~0.12.0" - combined-stream "~1.0.6" - extend "~3.0.2" - forever-agent "~0.6.1" - form-data "~2.3.2" - har-validator "~5.1.0" - http-signature "~1.2.0" - is-typedarray "~1.0.0" - isstream "~0.1.2" - json-stringify-safe "~5.0.1" - mime-types "~2.1.19" - oauth-sign "~0.9.0" - performance-now "^2.1.0" - qs "~6.5.2" - safe-buffer "^5.1.2" - tough-cookie "~2.4.3" - tunnel-agent "^0.6.0" - uuid "^3.3.2" - -request@^2.88.2: - version "2.88.2" - resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3" - integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw== - dependencies: - aws-sign2 "~0.7.0" - aws4 "^1.8.0" - caseless "~0.12.0" - combined-stream "~1.0.6" - extend "~3.0.2" - forever-agent "~0.6.1" - form-data "~2.3.2" - har-validator "~5.1.3" - http-signature "~1.2.0" - is-typedarray "~1.0.0" - isstream "~0.1.2" - json-stringify-safe "~5.0.1" - mime-types "~2.1.19" - oauth-sign "~0.9.0" - performance-now "^2.1.0" - qs "~6.5.2" - safe-buffer "^5.1.2" - tough-cookie "~2.5.0" - tunnel-agent "^0.6.0" - uuid "^3.3.2" - -require-directory@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" - integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= - -require-from-string@^2.0.0, require-from-string@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" - integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== - -require-main-filename@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1" - integrity sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE= - -require-main-filename@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" - integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg== - -resolve-cwd@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-2.0.0.tgz#00a9f7387556e27038eae232caa372a6a59b665a" - integrity sha1-AKn3OHVW4nA46uIyyqNypqWbZlo= - dependencies: - resolve-from "^3.0.0" - -resolve-dir@^1.0.0, resolve-dir@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/resolve-dir/-/resolve-dir-1.0.1.tgz#79a40644c362be82f26effe739c9bb5382046f43" - integrity sha1-eaQGRMNivoLybv/nOcm7U4IEb0M= - dependencies: - expand-tilde "^2.0.0" - global-modules "^1.0.0" - -resolve-from@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748" - integrity sha1-six699nWiBvItuZTM17rywoYh0g= - -resolve-options@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/resolve-options/-/resolve-options-1.1.0.tgz#32bb9e39c06d67338dc9378c0d6d6074566ad131" - integrity sha1-MrueOcBtZzONyTeMDW1gdFZq0TE= - dependencies: - value-or-function "^3.0.0" - -resolve-url@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" - integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= - -resolve@1.1.7, resolve@1.1.x: - version "1.1.7" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" - integrity sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs= - -resolve@1.x, resolve@^1.3.2: - version "1.14.2" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.14.2.tgz#dbf31d0fa98b1f29aa5169783b9c290cb865fea2" - integrity sha512-EjlOBLBO1kxsUxsKjLt7TAECyKW6fOh1VRkykQkKGzcBbjjPIxBqGh0jf7GJ3k/f5mxMqW3htMD3WdTUVtW8HQ== - dependencies: - path-parse "^1.0.6" - -resolve@^1.1.6, resolve@^1.1.7, resolve@^1.10.0, resolve@^1.4.0, resolve@^1.8.1: - version "1.13.1" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.13.1.tgz#be0aa4c06acd53083505abb35f4d66932ab35d16" - integrity sha512-CxqObCX8K8YtAhOBRg+lrcdn+LK+WYOS8tSjqSFbjtrI5PnS63QPhZl4+yKfrU9tdsbMu9Anr/amegT87M9Z6w== - dependencies: - path-parse "^1.0.6" - -resolve@~1.11.1: - version "1.11.1" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.11.1.tgz#ea10d8110376982fef578df8fc30b9ac30a07a3e" - integrity sha512-vIpgF6wfuJOZI7KKKSP+HmiKggadPQAdsp5HiC1mvqnfp0gF1vdwgBWZIdrVft9pgqoMFQN+R7BSWZiBxx+BBw== - dependencies: - path-parse "^1.0.6" - -responselike@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/responselike/-/responselike-1.0.2.tgz#918720ef3b631c5642be068f15ade5a46f4ba1e7" - integrity sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec= - dependencies: - lowercase-keys "^1.0.0" - -resumer@~0.0.0: - version "0.0.0" - resolved "https://registry.yarnpkg.com/resumer/-/resumer-0.0.0.tgz#f1e8f461e4064ba39e82af3cdc2a8c893d076759" - integrity sha1-8ej0YeQGS6Oegq883CqMiT0HZ1k= - dependencies: - through "~2.3.4" - -ret@~0.1.10: - version "0.1.15" - resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" - integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg== - -reusify@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" - integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== - -rimraf@^2.2.8, rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.2, rimraf@^2.6.3: - version "2.7.1" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" - integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== - dependencies: - glob "^7.1.3" - -ripemd160@^2.0.0, ripemd160@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c" - integrity sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA== - dependencies: - hash-base "^3.0.0" - inherits "^2.0.1" - -rlp@^2.0.0, rlp@^2.2.1, rlp@^2.2.2, rlp@^2.2.3: - version "2.2.4" - resolved "https://registry.yarnpkg.com/rlp/-/rlp-2.2.4.tgz#d6b0e1659e9285fc509a5d169a9bd06f704951c1" - integrity sha512-fdq2yYCWpAQBhwkZv+Z8o/Z4sPmYm1CUq6P7n6lVTOdb949CnqA0sndXal5C1NleSVSZm6q5F3iEbauyVln/iw== - dependencies: - bn.js "^4.11.1" - -rsvp@^4.8.4: - version "4.8.5" - resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-4.8.5.tgz#c8f155311d167f68f21e168df71ec5b083113734" - integrity sha512-nfMOlASu9OnRJo1mbEk2cz0D56a1MBNrJ7orjRZQG10XDyuvwksKbuXNp6qa+kbn839HwjwhBzhFmdsaEAfauA== - -run-parallel@^1.1.9: - version "1.1.9" - resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.1.9.tgz#c9dd3a7cf9f4b2c4b6244e173a6ed866e61dd679" - integrity sha512-DEqnSRTDw/Tc3FXf49zedI638Z9onwUotBMiUFKmrO2sdFKIbXamXGQ3Axd4qgphxKB4kw/qP1w5kTxnfU1B9Q== - -run-queue@^1.0.0, run-queue@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/run-queue/-/run-queue-1.0.3.tgz#e848396f057d223f24386924618e25694161ec47" - integrity sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec= - dependencies: - aproba "^1.1.1" - -rustbn.js@~0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/rustbn.js/-/rustbn.js-0.2.0.tgz#8082cb886e707155fd1cb6f23bd591ab8d55d0ca" - integrity sha512-4VlvkRUuCJvr2J6Y0ImW7NvTCriMi7ErOAqWk1y69vAdoNIzCF3yPmgeNzx+RQTLEDFq5sHfscn1MwHxP9hNfA== - -rxjs@^6.5.3: - version "6.5.3" - resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.5.3.tgz#510e26317f4db91a7eb1de77d9dd9ba0a4899a3a" - integrity sha512-wuYsAYYFdWTAnAaPoKGNhfpWwKZbJW+HgAJ+mImp+Epl7BG8oNWBCTyRM8gba9k4lk8BgWdoYm21Mo/RYhhbgA== - dependencies: - tslib "^1.9.0" - -safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: - version "5.1.2" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" - integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== - -safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@~5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.0.tgz#b74daec49b1148f88c64b68d49b1e815c1f2f519" - integrity sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg== - -safe-event-emitter@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/safe-event-emitter/-/safe-event-emitter-1.0.1.tgz#5b692ef22329ed8f69fdce607e50ca734f6f20af" - integrity sha512-e1wFe99A91XYYxoQbcq2ZJUWurxEyP8vfz7A7vuUe1s95q8r5ebraVaA1BukYJcpM6V16ugWoD9vngi8Ccu5fg== - dependencies: - events "^3.0.0" - -safe-regex@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e" - integrity sha1-QKNmnzsHfR6UPURinhV91IAjvy4= - dependencies: - ret "~0.1.10" - -"safer-buffer@>= 2.1.2 < 3", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: - version "2.1.2" - resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" - integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== - -sane@^4.0.3: - version "4.1.0" - resolved "https://registry.yarnpkg.com/sane/-/sane-4.1.0.tgz#ed881fd922733a6c461bc189dc2b6c006f3ffded" - integrity sha512-hhbzAgTIX8O7SHfp2c8/kREfEn4qO/9q8C9beyY6+tvZ87EpoZ3i1RIEvp27YBswnNbY9mWd6paKVmKbAgLfZA== - dependencies: - "@cnakazawa/watch" "^1.0.3" - anymatch "^2.0.0" - capture-exit "^2.0.0" - exec-sh "^0.3.2" - execa "^1.0.0" - fb-watchman "^2.0.0" - micromatch "^3.1.4" - minimist "^1.1.1" - walker "~1.0.5" - -sax@^1.2.4: - version "1.2.4" - resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" - integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== - -schema-utils@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-1.0.0.tgz#0b79a93204d7b600d4b2850d1f66c2a34951c770" - integrity sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g== - dependencies: - ajv "^6.1.0" - ajv-errors "^1.0.0" - ajv-keywords "^3.1.0" - -scrypt-js@2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/scrypt-js/-/scrypt-js-2.0.3.tgz#bb0040be03043da9a012a2cea9fc9f852cfc87d4" - integrity sha1-uwBAvgMEPamgEqLOqfyfhSz8h9Q= - -scrypt-js@2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/scrypt-js/-/scrypt-js-2.0.4.tgz#32f8c5149f0797672e551c07e230f834b6af5f16" - integrity sha512-4KsaGcPnuhtCZQCxFxN3GVYIhKFPTdLd8PLC552XwbMndtD0cjRFAhDuuydXQ0h08ZfPgzqe6EKHozpuH74iDw== - -scrypt-js@3.0.1, scrypt-js@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/scrypt-js/-/scrypt-js-3.0.1.tgz#d314a57c2aef69d1ad98a138a21fe9eafa9ee312" - integrity sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA== - -scrypt.js@^0.3.0, "scrypt.js@https://registry.npmjs.org/@compound-finance/ethereumjs-wallet/-/ethereumjs-wallet-0.6.3.tgz": - version "0.6.3" - resolved "https://registry.npmjs.org/@compound-finance/ethereumjs-wallet/-/ethereumjs-wallet-0.6.3.tgz#707128975a68333df615f4098b51f82d983f7416" - dependencies: - aes-js "^3.1.1" - bs58check "^2.1.2" - ethereumjs-util "^6.0.0" - hdkey "^1.1.1" - randombytes "^2.0.6" - safe-buffer "^5.1.2" - utf8 "^3.0.0" - uuid "^3.3.2" - -scryptsy@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/scryptsy/-/scryptsy-2.1.0.tgz#8d1e8d0c025b58fdd25b6fa9a0dc905ee8faa790" - integrity sha512-1CdSqHQowJBnMAFyPEBRfqag/YP9OF394FV+4YREIJX4ljD7OxvQRDayyoyyCk+senRjSkP6VnUNQmVQqB6g7w== - -secp256k1@^3.0.1: - version "3.7.1" - resolved "https://registry.yarnpkg.com/secp256k1/-/secp256k1-3.7.1.tgz#12e473e0e9a7c2f2d4d4818e722ad0e14cc1e2f1" - integrity sha512-1cf8sbnRreXrQFdH6qsg2H71Xw91fCCS9Yp021GnUNJzWJS/py96fS4lHbnTnouLp08Xj6jBoBB6V78Tdbdu5g== - dependencies: - bindings "^1.5.0" - bip66 "^1.1.5" - bn.js "^4.11.8" - create-hash "^1.2.0" - drbg.js "^1.0.1" - elliptic "^6.4.1" - nan "^2.14.0" - safe-buffer "^5.1.2" - -seedrandom@3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/seedrandom/-/seedrandom-3.0.1.tgz#eb3dde015bcf55df05a233514e5df44ef9dce083" - integrity sha512-1/02Y/rUeU1CJBAGLebiC5Lbo5FnB22gQbIFFYTLkwvp1xdABZJH1sn4ZT1MzXmPpzv+Rf/Lu2NcsLJiK4rcDg== - -seek-bzip@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/seek-bzip/-/seek-bzip-1.0.5.tgz#cfe917cb3d274bcffac792758af53173eb1fabdc" - integrity sha1-z+kXyz0nS8/6x5J1ivUxc+sfq9w= - dependencies: - commander "~2.8.1" - -semaphore-async-await@^1.5.1: - version "1.5.1" - resolved "https://registry.yarnpkg.com/semaphore-async-await/-/semaphore-async-await-1.5.1.tgz#857bef5e3644601ca4b9570b87e9df5ca12974fa" - integrity sha1-hXvvXjZEYBykuVcLh+nfXKEpdPo= - -semaphore@>=1.0.1, semaphore@^1.0.3, semaphore@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/semaphore/-/semaphore-1.1.0.tgz#aaad8b86b20fe8e9b32b16dc2ee682a8cd26a8aa" - integrity sha512-O4OZEaNtkMd/K0i6js9SL+gqy0ZCBMgUvlSqHKi4IBdjhe7wB8pwztUk1BbZ1fmrvpwFrPbHzqd2w5pTcJH6LA== - -semver-greatest-satisfied-range@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/semver-greatest-satisfied-range/-/semver-greatest-satisfied-range-1.1.0.tgz#13e8c2658ab9691cb0cd71093240280d36f77a5b" - integrity sha1-E+jCZYq5aRywzXEJMkAoDTb3els= - dependencies: - sver-compat "^1.5.0" - -"semver@2 || 3 || 4 || 5", semver@^5.3.0, semver@^5.4.1, semver@^5.5, semver@^5.5.0, semver@^5.5.1, semver@^5.6.0: - version "5.7.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" - integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== - -semver@5.5.0: - version "5.5.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab" - integrity sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA== - -semver@^6.0.0, semver@^6.2.0, semver@^6.3.0: - version "6.3.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" - integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== - -semver@~5.4.1: - version "5.4.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.4.1.tgz#e059c09d8571f0540823733433505d3a2f00b18e" - integrity sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg== - -send@0.17.1: - version "0.17.1" - resolved "https://registry.yarnpkg.com/send/-/send-0.17.1.tgz#c1d8b059f7900f7466dd4938bdc44e11ddb376c8" - integrity sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg== - dependencies: - debug "2.6.9" - depd "~1.1.2" - destroy "~1.0.4" - encodeurl "~1.0.2" - escape-html "~1.0.3" - etag "~1.8.1" - fresh "0.5.2" - http-errors "~1.7.2" - mime "1.6.0" - ms "2.1.1" - on-finished "~2.3.0" - range-parser "~1.2.1" - statuses "~1.5.0" - -serialize-javascript@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-4.0.0.tgz#b525e1238489a5ecfc42afacc3fe99e666f4b1aa" - integrity sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw== - dependencies: - randombytes "^2.1.0" - -serve-static@1.14.1: - version "1.14.1" - resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.14.1.tgz#666e636dc4f010f7ef29970a88a674320898b2f9" - integrity sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg== - dependencies: - encodeurl "~1.0.2" - escape-html "~1.0.3" - parseurl "~1.3.3" - send "0.17.1" - -servify@^0.1.12: - version "0.1.12" - resolved "https://registry.yarnpkg.com/servify/-/servify-0.1.12.tgz#142ab7bee1f1d033b66d0707086085b17c06db95" - integrity sha512-/xE6GvsKKqyo1BAY+KxOWXcLpPsUUyji7Qg3bVD7hh1eRze5bR1uYiuDA/k3Gof1s9BTzQZEJK8sNcNGFIzeWw== - dependencies: - body-parser "^1.16.0" - cors "^2.8.1" - express "^4.14.0" - request "^2.79.0" - xhr "^2.3.3" - -set-blocking@^2.0.0, set-blocking@~2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" - integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= - -set-immediate-shim@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz#4b2b1b27eb808a9f8dcc481a58e5e56f599f3f61" - integrity sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E= - -set-value@^2.0.0, set-value@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.1.tgz#a18d40530e6f07de4228c7defe4227af8cad005b" - integrity sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw== - dependencies: - extend-shallow "^2.0.1" - is-extendable "^0.1.1" - is-plain-object "^2.0.3" - split-string "^3.0.1" - -setimmediate@1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.4.tgz#20e81de622d4a02588ce0c8da8973cbcf1d3138f" - integrity sha1-IOgd5iLUoCWIzgyNqJc8vPHTE48= - -setimmediate@^1.0.4, setimmediate@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" - integrity sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU= - -setprototypeof@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.1.tgz#7e95acb24aa92f5885e0abef5ba131330d4ae683" - integrity sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw== - -sha.js@^2.4.0, sha.js@^2.4.8: - version "2.4.11" - resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7" - integrity sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ== - dependencies: - inherits "^2.0.1" - safe-buffer "^5.0.1" - -sha3@^1.2.2: - version "1.2.6" - resolved "https://registry.yarnpkg.com/sha3/-/sha3-1.2.6.tgz#102aa3e47dc793e2357902c3cce8760822f9e905" - integrity sha512-KgLGmJGrmNB4JWVsAV11Yk6KbvsAiygWJc7t5IebWva/0NukNrjJqhtKhzy3Eiv2AKuGvhZZt7dt1mDo7HkoiQ== - dependencies: - nan "2.13.2" - -shebang-command@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" - integrity sha1-RKrGW2lbAzmJaMOfNj/uXer98eo= - dependencies: - shebang-regex "^1.0.0" - -shebang-regex@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" - integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM= - -shellwords@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/shellwords/-/shellwords-0.1.1.tgz#d6b9181c1a48d397324c84871efbcfc73fc0654b" - integrity sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww== - -signal-exit@^3.0.0, signal-exit@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" - integrity sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0= - -simple-concat@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/simple-concat/-/simple-concat-1.0.0.tgz#7344cbb8b6e26fb27d66b2fc86f9f6d5997521c6" - integrity sha1-c0TLuLbib7J9ZrL8hvn21Zl1IcY= - -simple-get@^2.7.0: - version "2.8.1" - resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-2.8.1.tgz#0e22e91d4575d87620620bc91308d57a77f44b5d" - integrity sha512-lSSHRSw3mQNUGPAYRqo7xy9dhKmxFXIjLjp4KHpf99GEH2VH7C3AM+Qfx6du6jhfUi6Vm7XnbEVEf7Wb6N8jRw== - dependencies: - decompress-response "^3.3.0" - once "^1.3.1" - simple-concat "^1.0.0" - -simple-get@^3.0.3: - version "3.1.0" - resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-3.1.0.tgz#b45be062435e50d159540b576202ceec40b9c6b3" - integrity sha512-bCR6cP+aTdScaQCnQKbPKtJOKDp/hj9EDLJo3Nw4y1QksqaovlW/bnptB6/c1e+qmNIDHRK+oXFDdEqBT8WzUA== - dependencies: - decompress-response "^4.2.0" - once "^1.3.1" - simple-concat "^1.0.0" - -sisteransi@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.4.tgz#386713f1ef688c7c0304dc4c0632898941cad2e3" - integrity sha512-/ekMoM4NJ59ivGSfKapeG+FWtrmWvA1p6FBZwXrqojw90vJu8lBmrTxCMuBCydKtkaUe2zt4PlxeTKpjwMbyig== - -slash@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55" - integrity sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU= - -slash@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/slash/-/slash-2.0.0.tgz#de552851a1759df3a8f206535442f5ec4ddeab44" - integrity sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A== - -snapdragon-node@^2.0.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b" - integrity sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw== - dependencies: - define-property "^1.0.0" - isobject "^3.0.0" - snapdragon-util "^3.0.1" - -snapdragon-util@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/snapdragon-util/-/snapdragon-util-3.0.1.tgz#f956479486f2acd79700693f6f7b805e45ab56e2" - integrity sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ== - dependencies: - kind-of "^3.2.0" - -snapdragon@^0.8.1: - version "0.8.2" - resolved "https://registry.yarnpkg.com/snapdragon/-/snapdragon-0.8.2.tgz#64922e7c565b0e14204ba1aa7d6964278d25182d" - integrity sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg== - dependencies: - base "^0.11.1" - debug "^2.2.0" - define-property "^0.2.5" - extend-shallow "^2.0.1" - map-cache "^0.2.2" - source-map "^0.5.6" - source-map-resolve "^0.5.0" - use "^3.1.0" - -solc@^0.5.5: - version "0.5.13" - resolved "https://registry.yarnpkg.com/solc/-/solc-0.5.13.tgz#2a5ba2b7681898c6293759441e0a768fb6955def" - integrity sha512-osybDVPGjAqcmSKLU3vh5iHuxbhGlJjQI5ZvI7nRDR0fgblQqYte4MGvNjbew8DPvCrmoH0ZBiz/KBBLlPxfMg== - dependencies: - command-exists "^1.2.8" - commander "3.0.2" - fs-extra "^0.30.0" - js-sha3 "0.8.0" - memorystream "^0.3.1" - require-from-string "^2.0.0" - semver "^5.5.0" - tmp "0.0.33" - -"solidity-parser-antlr@https://github.com/solidity-parser/parser": - version "0.7.0" - resolved "https://github.com/solidity-parser/parser#013764c850294460d51c6f227cc150c152a01338" - -solparse@^2.2.8: - version "2.2.8" - resolved "https://registry.yarnpkg.com/solparse/-/solparse-2.2.8.tgz#d13e42dbed95ce32f43894f5ec53f00d14cf9f11" - integrity sha512-Tm6hdfG72DOxD40SD+T5ddbekWglNWjzDRSNq7ZDIOHVsyaJSeeunUuWNj4DE7uDrJK3tGQuX0ZTDZWNYsGPMA== - dependencies: - mocha "^4.0.1" - pegjs "^0.10.0" - yargs "^10.0.3" - -source-list-map@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.1.tgz#3993bd873bfc48479cca9ea3a547835c7c154b34" - integrity sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw== - -source-map-resolve@^0.5.0: - version "0.5.2" - resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.2.tgz#72e2cc34095543e43b2c62b2c4c10d4a9054f259" - integrity sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA== - dependencies: - atob "^2.1.1" - decode-uri-component "^0.2.0" - resolve-url "^0.2.1" - source-map-url "^0.4.0" - urix "^0.1.0" - -source-map-support@0.5.12: - version "0.5.12" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.12.tgz#b4f3b10d51857a5af0138d3ce8003b201613d599" - integrity sha512-4h2Pbvyy15EE02G+JOZpUCmqWJuqrs+sEkzewTm++BPi7Hvn/HwcqLAcNxYAyI0x13CpPPn+kMjl+hplXMHITQ== - dependencies: - buffer-from "^1.0.0" - source-map "^0.6.0" - -source-map-support@^0.4.15: - version "0.4.18" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.18.tgz#0286a6de8be42641338594e97ccea75f0a2c585f" - integrity sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA== - dependencies: - source-map "^0.5.6" - -source-map-support@^0.5.0, source-map-support@^0.5.6, source-map-support@~0.5.12: - version "0.5.16" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.16.tgz#0ae069e7fe3ba7538c64c98515e35339eac5a042" - integrity sha512-efyLRJDr68D9hBBNIPWFjhpFzURh+KJykQwvMyW5UiZzYwoF6l4YMMDIJJEyFWxWCqfyxLzz6tSfUFR+kXXsVQ== - dependencies: - buffer-from "^1.0.0" - source-map "^0.6.0" - -source-map-url@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3" - integrity sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM= - -source-map@^0.5.0, source-map@^0.5.6, source-map@^0.5.7: - version "0.5.7" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" - integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= - -source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" - integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== - -source-map@~0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.2.0.tgz#dab73fbcfc2ba819b4de03bd6f6eaa48164b3f9d" - integrity sha1-2rc/vPwrqBm03gO9b26qSBZLP50= - dependencies: - amdefine ">=0.0.4" - -sparkles@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/sparkles/-/sparkles-1.0.1.tgz#008db65edce6c50eec0c5e228e1945061dd0437c" - integrity sha512-dSO0DDYUahUt/0/pD/Is3VIm5TGJjludZ0HVymmhYF6eNA53PVLhnUk0znSYbH8IYBuJdCE+1luR22jNLMaQdw== - -spdx-correct@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.0.tgz#fb83e504445268f154b074e218c87c003cd31df4" - integrity sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q== - dependencies: - spdx-expression-parse "^3.0.0" - spdx-license-ids "^3.0.0" - -spdx-exceptions@^2.1.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz#2ea450aee74f2a89bfb94519c07fcd6f41322977" - integrity sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA== - -spdx-expression-parse@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz#99e119b7a5da00e05491c9fa338b7904823b41d0" - integrity sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg== - dependencies: - spdx-exceptions "^2.1.0" - spdx-license-ids "^3.0.0" - -spdx-license-ids@^3.0.0: - version "3.0.5" - resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz#3694b5804567a458d3c8045842a6358632f62654" - integrity sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q== - -split-string@^3.0.1, split-string@^3.0.2: - version "3.1.0" - resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2" - integrity sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw== - dependencies: - extend-shallow "^3.0.0" - -sprintf-js@~1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" - integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= - -sshpk@^1.7.0: - version "1.16.1" - resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.16.1.tgz#fb661c0bef29b39db40769ee39fa70093d6f6877" - integrity sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg== - dependencies: - asn1 "~0.2.3" - assert-plus "^1.0.0" - bcrypt-pbkdf "^1.0.0" - dashdash "^1.12.0" - ecc-jsbn "~0.1.1" - getpass "^0.1.1" - jsbn "~0.1.0" - safer-buffer "^2.0.2" - tweetnacl "~0.14.0" - -ssri@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/ssri/-/ssri-6.0.1.tgz#2a3c41b28dd45b62b63676ecb74001265ae9edd8" - integrity sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA== - dependencies: - figgy-pudding "^3.5.1" - -stack-trace@0.0.10: - version "0.0.10" - resolved "https://registry.yarnpkg.com/stack-trace/-/stack-trace-0.0.10.tgz#547c70b347e8d32b4e108ea1a2a159e5fdde19c0" - integrity sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA= - -stack-utils@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-1.0.2.tgz#33eba3897788558bebfc2db059dc158ec36cebb8" - integrity sha512-MTX+MeG5U994cazkjd/9KNAapsHnibjMLnfXodlkXw76JEea0UiNzrqidzo1emMwk7w5Qhc9jd4Bn9TBb1MFwA== - -static-extend@^0.1.1: - version "0.1.2" - resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" - integrity sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY= - dependencies: - define-property "^0.2.5" - object-copy "^0.1.0" - -"statuses@>= 1.5.0 < 2", statuses@~1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" - integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow= - -stealthy-require@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/stealthy-require/-/stealthy-require-1.1.1.tgz#35b09875b4ff49f26a777e509b3090a3226bf24b" - integrity sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks= - -stream-browserify@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-2.0.2.tgz#87521d38a44aa7ee91ce1cd2a47df0cb49dd660b" - integrity sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg== - dependencies: - inherits "~2.0.1" - readable-stream "^2.0.2" - -stream-each@^1.1.0: - version "1.2.3" - resolved "https://registry.yarnpkg.com/stream-each/-/stream-each-1.2.3.tgz#ebe27a0c389b04fbcc233642952e10731afa9bae" - integrity sha512-vlMC2f8I2u/bZGqkdfLQW/13Zihpej/7PmSiMQsbYddxuTsJp8vRe2x2FvVExZg7FaOds43ROAuFJwPR4MTZLw== - dependencies: - end-of-stream "^1.1.0" - stream-shift "^1.0.0" - -stream-exhaust@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/stream-exhaust/-/stream-exhaust-1.0.2.tgz#acdac8da59ef2bc1e17a2c0ccf6c320d120e555d" - integrity sha512-b/qaq/GlBK5xaq1yrK9/zFcyRSTNxmcZwFLGSTG0mXgZl/4Z6GgiyYOXOvY7N3eEvFRAG1bkDRz5EPGSvPYQlw== - -stream-http@^2.7.2: - version "2.8.3" - resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-2.8.3.tgz#b2d242469288a5a27ec4fe8933acf623de6514fc" - integrity sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw== - dependencies: - builtin-status-codes "^3.0.0" - inherits "^2.0.1" - readable-stream "^2.3.6" - to-arraybuffer "^1.0.0" - xtend "^4.0.0" - -stream-shift@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.0.tgz#d5c752825e5367e786f78e18e445ea223a155952" - integrity sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI= - -stream-to-pull-stream@^1.7.1: - version "1.7.3" - resolved "https://registry.yarnpkg.com/stream-to-pull-stream/-/stream-to-pull-stream-1.7.3.tgz#4161aa2d2eb9964de60bfa1af7feaf917e874ece" - integrity sha512-6sNyqJpr5dIOQdgNy/xcDWwDuzAsAwVzhzrWlAPAQ7Lkjx/rv0wgvxEyKwTq6FmNd5rjTrELt/CLmaSw7crMGg== - dependencies: - looper "^3.0.0" - pull-stream "^3.2.3" - -strict-uri-encode@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713" - integrity sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM= - -string-length@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/string-length/-/string-length-2.0.0.tgz#d40dbb686a3ace960c1cffca562bf2c45f8363ed" - integrity sha1-1A27aGo6zpYMHP/KVivyxF+DY+0= - dependencies: - astral-regex "^1.0.0" - strip-ansi "^4.0.0" - -string-width@^1.0.1, string-width@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" - integrity sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M= - dependencies: - code-point-at "^1.0.0" - is-fullwidth-code-point "^1.0.0" - strip-ansi "^3.0.0" - -"string-width@^1.0.2 || 2", string-width@^2.0.0, string-width@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" - integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== - dependencies: - is-fullwidth-code-point "^2.0.0" - strip-ansi "^4.0.0" - -string-width@^3.0.0, string-width@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961" - integrity sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w== - dependencies: - emoji-regex "^7.0.1" - is-fullwidth-code-point "^2.0.0" - strip-ansi "^5.1.0" - -string.prototype.trim@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.1.2.tgz#d04de2c89e137f4d7d206f086b5ed2fae6be8cea" - integrity sha1-0E3iyJ4Tf019IG8Ia17S+ua+jOo= - dependencies: - define-properties "^1.1.2" - es-abstract "^1.5.0" - function-bind "^1.0.2" - -string.prototype.trimleft@^2.1.0, string.prototype.trimleft@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/string.prototype.trimleft/-/string.prototype.trimleft-2.1.1.tgz#9bdb8ac6abd6d602b17a4ed321870d2f8dcefc74" - integrity sha512-iu2AGd3PuP5Rp7x2kEZCrB2Nf41ehzh+goo8TV7z8/XDBbsvc6HQIlUl9RjkZ4oyrW1XM5UwlGl1oVEaDjg6Ag== - dependencies: - define-properties "^1.1.3" - function-bind "^1.1.1" - -string.prototype.trimright@^2.1.0, string.prototype.trimright@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/string.prototype.trimright/-/string.prototype.trimright-2.1.1.tgz#440314b15996c866ce8a0341894d45186200c5d9" - integrity sha512-qFvWL3/+QIgZXVmJBfpHmxLB7xsUXz6HsUmP8+5dRaC3Q7oKUv9Vo6aMCRZC1smrtyECFsIT30PqBJ1gTjAs+g== - dependencies: - define-properties "^1.1.3" - function-bind "^1.1.1" - -string_decoder@^1.0.0, string_decoder@^1.1.1: - version "1.3.0" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" - integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== - dependencies: - safe-buffer "~5.2.0" - -string_decoder@~0.10.x: - version "0.10.31" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" - integrity sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ= - -string_decoder@~1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" - integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== - dependencies: - safe-buffer "~5.1.0" - -strip-ansi@^3.0.0, strip-ansi@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" - integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8= - dependencies: - ansi-regex "^2.0.0" - -strip-ansi@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" - integrity sha1-qEeQIusaw2iocTibY1JixQXuNo8= - dependencies: - ansi-regex "^3.0.0" - -strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" - integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA== - dependencies: - ansi-regex "^4.1.0" - -strip-bom@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e" - integrity sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4= - dependencies: - is-utf8 "^0.2.0" - -strip-bom@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" - integrity sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM= - -strip-dirs@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/strip-dirs/-/strip-dirs-2.1.0.tgz#4987736264fc344cf20f6c34aca9d13d1d4ed6c5" - integrity sha512-JOCxOeKLm2CAS73y/U4ZeZPTkE+gNVCzKt7Eox84Iej1LT/2pTWYpZKJuxwQpvX1LiZb1xokNR7RLfuBAa7T3g== - dependencies: - is-natural-number "^4.0.1" - -strip-eof@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" - integrity sha1-u0P/VZim6wXYm1n80SnJgzE2Br8= - -strip-hex-prefix@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/strip-hex-prefix/-/strip-hex-prefix-1.0.0.tgz#0c5f155fef1151373377de9dbb588da05500e36f" - integrity sha1-DF8VX+8RUTczd96du1iNoFUA428= - dependencies: - is-hex-prefixed "1.0.0" - -strip-json-comments@~2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" - integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= - -supports-color@4.4.0: - version "4.4.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-4.4.0.tgz#883f7ddabc165142b2a61427f3352ded195d1a3e" - integrity sha512-rKC3+DyXWgK0ZLKwmRsrkyHVZAjNkfzeehuFWdGGcqGDTZFH73+RH6S/RDAAxl9GusSjZSUWYLmT9N5pzXFOXQ== - dependencies: - has-flag "^2.0.0" - -supports-color@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" - integrity sha1-U10EXOa2Nj+kARcIRimZXp3zJMc= - -supports-color@^3.1.0: - version "3.2.3" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.2.3.tgz#65ac0504b3954171d8a64946b2ae3cbb8a5f54f6" - integrity sha1-ZawFBLOVQXHYpklGsq48u4pfVPY= - dependencies: - has-flag "^1.0.0" - -supports-color@^5.3.0: - version "5.5.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" - integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== - dependencies: - has-flag "^3.0.0" - -supports-color@^6.1.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.1.0.tgz#0764abc69c63d5ac842dd4867e8d025e880df8f3" - integrity sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ== - dependencies: - has-flag "^3.0.0" - -supports-color@^7.1.0: - version "7.1.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.1.0.tgz#68e32591df73e25ad1c4b49108a2ec507962bfd1" - integrity sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g== - dependencies: - has-flag "^4.0.0" - -sver-compat@^1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/sver-compat/-/sver-compat-1.5.0.tgz#3cf87dfeb4d07b4a3f14827bc186b3fd0c645cd8" - integrity sha1-PPh9/rTQe0o/FIJ7wYaz/QxkXNg= - dependencies: - es6-iterator "^2.0.1" - es6-symbol "^3.1.1" - -swarm-js@0.1.39: - version "0.1.39" - resolved "https://registry.yarnpkg.com/swarm-js/-/swarm-js-0.1.39.tgz#79becb07f291d4b2a178c50fee7aa6e10342c0e8" - integrity sha512-QLMqL2rzF6n5s50BptyD6Oi0R1aWlJC5Y17SRIVXRj6OR1DRIPM7nepvrxxkjA1zNzFz6mUOMjfeqeDaWB7OOg== - dependencies: - bluebird "^3.5.0" - buffer "^5.0.5" - decompress "^4.0.0" - eth-lib "^0.1.26" - fs-extra "^4.0.2" - got "^7.1.0" - mime-types "^2.1.16" - mkdirp-promise "^5.0.1" - mock-fs "^4.1.0" - setimmediate "^1.0.5" - tar "^4.0.2" - xhr-request-promise "^0.1.2" - -swarm-js@^0.1.40: - version "0.1.40" - resolved "https://registry.yarnpkg.com/swarm-js/-/swarm-js-0.1.40.tgz#b1bc7b6dcc76061f6c772203e004c11997e06b99" - integrity sha512-yqiOCEoA4/IShXkY3WKwP5PvZhmoOOD8clsKA7EEcRILMkTEYHCQ21HDCAcVpmIxZq4LyZvWeRJ6quIyHk1caA== - dependencies: - bluebird "^3.5.0" - buffer "^5.0.5" - eth-lib "^0.1.26" - fs-extra "^4.0.2" - got "^7.1.0" - mime-types "^2.1.16" - mkdirp-promise "^5.0.1" - mock-fs "^4.1.0" - setimmediate "^1.0.5" - tar "^4.0.2" - xhr-request "^1.0.1" - -symbol-tree@^3.2.2: - version "3.2.4" - resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2" - integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw== - -tapable@^1.0.0, tapable@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.3.tgz#a1fccc06b58db61fd7a45da2da44f5f3a3e67ba2" - integrity sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA== - -tape@^4.4.0, tape@^4.6.3: - version "4.11.0" - resolved "https://registry.yarnpkg.com/tape/-/tape-4.11.0.tgz#63d41accd95e45a23a874473051c57fdbc58edc1" - integrity sha512-yixvDMX7q7JIs/omJSzSZrqulOV51EC9dK8dM0TzImTIkHWfe2/kFyL5v+d9C+SrCMaICk59ujsqFAVidDqDaA== - dependencies: - deep-equal "~1.0.1" - defined "~1.0.0" - for-each "~0.3.3" - function-bind "~1.1.1" - glob "~7.1.4" - has "~1.0.3" - inherits "~2.0.4" - minimist "~1.2.0" - object-inspect "~1.6.0" - resolve "~1.11.1" - resumer "~0.0.0" - string.prototype.trim "~1.1.2" - through "~2.3.8" - -tar-fs@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-2.0.0.tgz#677700fc0c8b337a78bee3623fdc235f21d7afad" - integrity sha512-vaY0obB6Om/fso8a8vakQBzwholQ7v5+uy+tF3Ozvxv1KNezmVQAiWtcNmMHFSFPqL3dJA8ha6gdtFbfX9mcxA== - dependencies: - chownr "^1.1.1" - mkdirp "^0.5.1" - pump "^3.0.0" - tar-stream "^2.0.0" - -tar-stream@^1.5.2: - version "1.6.2" - resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-1.6.2.tgz#8ea55dab37972253d9a9af90fdcd559ae435c555" - integrity sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A== - dependencies: - bl "^1.0.0" - buffer-alloc "^1.2.0" - end-of-stream "^1.0.0" - fs-constants "^1.0.0" - readable-stream "^2.3.0" - to-buffer "^1.1.1" - xtend "^4.0.0" - -tar-stream@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-2.1.0.tgz#d1aaa3661f05b38b5acc9b7020efdca5179a2cc3" - integrity sha512-+DAn4Nb4+gz6WZigRzKEZl1QuJVOLtAwwF+WUxy1fJ6X63CaGaUAxJRD2KEn1OMfcbCjySTYpNC6WmfQoIEOdw== - dependencies: - bl "^3.0.0" - end-of-stream "^1.4.1" - fs-constants "^1.0.0" - inherits "^2.0.3" - readable-stream "^3.1.1" - -tar@^4, tar@^4.0.2: - version "4.4.13" - resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.13.tgz#43b364bc52888d555298637b10d60790254ab525" - integrity sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA== - dependencies: - chownr "^1.1.1" - fs-minipass "^1.2.5" - minipass "^2.8.6" - minizlib "^1.2.1" - mkdirp "^0.5.0" - safe-buffer "^5.1.2" - yallist "^3.0.3" - -terser-webpack-plugin@^1.4.3: - version "1.4.5" - resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-1.4.5.tgz#a217aefaea330e734ffacb6120ec1fa312d6040b" - integrity sha512-04Rfe496lN8EYruwi6oPQkG0vo8C+HT49X687FZnpPF0qMAIHONI6HEXYPKDOE8e5HjXTyKfqRd/agHtH0kOtw== - dependencies: - cacache "^12.0.2" - find-cache-dir "^2.1.0" - is-wsl "^1.1.0" - schema-utils "^1.0.0" - serialize-javascript "^4.0.0" - source-map "^0.6.1" - terser "^4.1.2" - webpack-sources "^1.4.0" - worker-farm "^1.7.0" - -terser@^4.1.2: - version "4.4.2" - resolved "https://registry.yarnpkg.com/terser/-/terser-4.4.2.tgz#448fffad0245f4c8a277ce89788b458bfd7706e8" - integrity sha512-Uufrsvhj9O1ikwgITGsZ5EZS6qPokUOkCegS7fYOdGTv+OA90vndUbU6PEjr5ePqHfNUbGyMO7xyIZv2MhsALQ== - dependencies: - commander "^2.20.0" - source-map "~0.6.1" - source-map-support "~0.5.12" - -test-exclude@^5.2.3: - version "5.2.3" - resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-5.2.3.tgz#c3d3e1e311eb7ee405e092dac10aefd09091eac0" - integrity sha512-M+oxtseCFO3EDtAaGH7iiej3CBkzXqFMbzqYAACdzKui4eZA+pq3tZEwChvOdNfa7xxy8BfbmgJSIr43cC/+2g== - dependencies: - glob "^7.1.3" - minimatch "^3.0.4" - read-pkg-up "^4.0.0" - require-main-filename "^2.0.0" - -throat@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/throat/-/throat-4.1.0.tgz#89037cbc92c56ab18926e6ba4cbb200e15672a6a" - integrity sha1-iQN8vJLFarGJJua6TLsgDhVnKmo= - -through2-filter@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/through2-filter/-/through2-filter-3.0.0.tgz#700e786df2367c2c88cd8aa5be4cf9c1e7831254" - integrity sha512-jaRjI2WxN3W1V8/FMZ9HKIBXixtiqs3SQSX4/YGIiP3gL6djW48VoZq9tDqeCWs3MT8YY5wb/zli8VW8snY1CA== - dependencies: - through2 "~2.0.0" - xtend "~4.0.0" - -through2@^2.0.0, through2@^2.0.3, through2@~2.0.0: - version "2.0.5" - resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd" - integrity sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ== - dependencies: - readable-stream "~2.3.6" - xtend "~4.0.1" - -through@^2.3.8, through@~2.3.4, through@~2.3.8: - version "2.3.8" - resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" - integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= - -time-stamp@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/time-stamp/-/time-stamp-1.1.0.tgz#764a5a11af50561921b133f3b44e618687e0f5c3" - integrity sha1-dkpaEa9QVhkhsTPztE5hhofg9cM= - -timed-out@^4.0.0, timed-out@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/timed-out/-/timed-out-4.0.1.tgz#f32eacac5a175bea25d7fab565ab3ed8741ef56f" - integrity sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8= - -timers-browserify@^2.0.4: - version "2.0.11" - resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-2.0.11.tgz#800b1f3eee272e5bc53ee465a04d0e804c31211f" - integrity sha512-60aV6sgJ5YEbzUdn9c8kYGIqOubPoUdqQCul3SBAsRCZ40s6Y5cMcrW4dt3/k/EsbLVJNl9n6Vz3fTc+k2GeKQ== - dependencies: - setimmediate "^1.0.4" - -tmp@0.0.33: - version "0.0.33" - resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" - integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw== - dependencies: - os-tmpdir "~1.0.2" - -tmp@0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.1.0.tgz#ee434a4e22543082e294ba6201dcc6eafefa2877" - integrity sha512-J7Z2K08jbGcdA1kkQpJSqLF6T0tdQqpR2pnSUXsIchbPdTI9v3e85cLW0d6WDhwuAleOV71j2xWs8qMPfK7nKw== - dependencies: - rimraf "^2.6.3" - -tmpl@1.0.x: - version "1.0.4" - resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.4.tgz#23640dd7b42d00433911140820e5cf440e521dd1" - integrity sha1-I2QN17QtAEM5ERQIIOXPRA5SHdE= - -to-absolute-glob@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/to-absolute-glob/-/to-absolute-glob-2.0.2.tgz#1865f43d9e74b0822db9f145b78cff7d0f7c849b" - integrity sha1-GGX0PZ50sIItufFFt4z/fQ98hJs= - dependencies: - is-absolute "^1.0.0" - is-negated-glob "^1.0.0" - -to-arraybuffer@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43" - integrity sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M= - -to-buffer@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/to-buffer/-/to-buffer-1.1.1.tgz#493bd48f62d7c43fcded313a03dcadb2e1213a80" - integrity sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg== - -to-fast-properties@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47" - integrity sha1-uDVx+k2MJbguIxsG46MFXeTKGkc= - -to-fast-properties@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" - integrity sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4= - -to-object-path@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af" - integrity sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68= - dependencies: - kind-of "^3.0.2" - -to-readable-stream@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/to-readable-stream/-/to-readable-stream-1.0.0.tgz#ce0aa0c2f3df6adf852efb404a783e77c0475771" - integrity sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q== - -to-regex-range@^2.1.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38" - integrity sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg= - dependencies: - is-number "^3.0.0" - repeat-string "^1.6.1" - -to-regex-range@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" - integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== - dependencies: - is-number "^7.0.0" - -to-regex@^3.0.1, to-regex@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce" - integrity sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw== - dependencies: - define-property "^2.0.2" - extend-shallow "^3.0.2" - regex-not "^1.0.2" - safe-regex "^1.1.0" - -to-through@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/to-through/-/to-through-2.0.0.tgz#fc92adaba072647bc0b67d6b03664aa195093af6" - integrity sha1-/JKtq6ByZHvAtn1rA2ZKoZUJOvY= - dependencies: - through2 "^2.0.3" - -toidentifier@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553" - integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw== - -tough-cookie@^2.3.3, tough-cookie@^2.3.4, tough-cookie@~2.5.0: - version "2.5.0" - resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2" - integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g== - dependencies: - psl "^1.1.28" - punycode "^2.1.1" - -tough-cookie@~2.4.3: - version "2.4.3" - resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.4.3.tgz#53f36da3f47783b0925afa06ff9f3b165280f781" - integrity sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ== - dependencies: - psl "^1.1.24" - punycode "^1.4.1" - -tr46@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/tr46/-/tr46-1.0.1.tgz#a8b13fd6bfd2489519674ccde55ba3693b706d09" - integrity sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk= - dependencies: - punycode "^2.1.0" - -trim-right@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003" - integrity sha1-yy4SAwZ+DI3h9hQJS5/kVwTqYAM= - -truffle-flattener@^1.4.4: - version "1.4.4" - resolved "https://registry.yarnpkg.com/truffle-flattener/-/truffle-flattener-1.4.4.tgz#747a99204001f7d6dce43ea92771e1ff6ac3eafb" - integrity sha512-S/WmvubzlUj1mn56wEI6yo1bmPpKDNdEe5rtyVC1C5iNfZWobD/V69pAYI15IBDJrDqUyh+iXgpTkzov50zpQw== - dependencies: - "@resolver-engine/imports-fs" "^0.2.2" - "@solidity-parser/parser" "^0.6.0" - find-up "^2.1.0" - mkdirp "^1.0.4" - tsort "0.0.1" - -tryer@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/tryer/-/tryer-1.0.1.tgz#f2c85406800b9b0f74c9f7465b81eaad241252f8" - integrity sha512-c3zayb8/kWWpycWYg87P71E1S1ZL6b6IJxfb5fvsUgsf0S2MVGaDhDXXjDMpdCpfWXqptc+4mXwmiy1ypXqRAA== - -ts-jest@^24.0.2: - version "24.3.0" - resolved "https://registry.yarnpkg.com/ts-jest/-/ts-jest-24.3.0.tgz#b97814e3eab359ea840a1ac112deae68aa440869" - integrity sha512-Hb94C/+QRIgjVZlJyiWwouYUF+siNJHJHknyspaOcZ+OQAIdFG/UrdQVXw/0B8Z3No34xkUXZJpOTy9alOWdVQ== - dependencies: - bs-logger "0.x" - buffer-from "1.x" - fast-json-stable-stringify "2.x" - json5 "2.x" - lodash.memoize "4.x" - make-error "1.x" - mkdirp "0.x" - resolve "1.x" - semver "^5.5" - yargs-parser "10.x" - -ts-loader@^8.0.3: - version "8.0.3" - resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-8.0.3.tgz#56858f4296edf1ed55e01f8520552984d3f0911c" - integrity sha512-wsqfnVdB7xQiqhqbz2ZPLGHLPZbHVV5Qn/MNFZkCFxRU1miDyxKORucDGxKtsQJ63Rfza0udiUxWF5nHY6bpdQ== - dependencies: - chalk "^2.3.0" - enhanced-resolve "^4.0.0" - loader-utils "^1.0.2" - micromatch "^4.0.0" - semver "^6.0.0" - -ts-pegjs@^0.2.7: - version "0.2.7" - resolved "https://registry.yarnpkg.com/ts-pegjs/-/ts-pegjs-0.2.7.tgz#2b97bbf65898d7296ae59ebc53e68436b5752826" - integrity sha512-pB+lqVyPWEUDy8w4E53Yu8V6w20No75J6lHUD+sFzogGW/Qn/QtkdR+vYYfMVEsDpz7LEKUOU5Rqf6dgVA3qsQ== - dependencies: - pegjs "^0.10.0" - -tslib@^1.9.0: - version "1.10.0" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.10.0.tgz#c3c19f95973fb0a62973fb09d90d961ee43e5c8a" - integrity sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ== - -tsort@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/tsort/-/tsort-0.0.1.tgz#e2280f5e817f8bf4275657fd0f9aebd44f5a2786" - integrity sha1-4igPXoF/i/QnVlf9D5rr1E9aJ4Y= - -tty-browserify@0.0.0: - version "0.0.0" - resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6" - integrity sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY= - -tunnel-agent@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" - integrity sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0= - dependencies: - safe-buffer "^5.0.1" - -tweetnacl-util@^0.15.0: - version "0.15.0" - resolved "https://registry.yarnpkg.com/tweetnacl-util/-/tweetnacl-util-0.15.0.tgz#4576c1cee5e2d63d207fee52f1ba02819480bc75" - integrity sha1-RXbBzuXi1j0gf+5S8boCgZSAvHU= - -tweetnacl@^0.14.3, tweetnacl@~0.14.0: - version "0.14.5" - resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" - integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= - -tweetnacl@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-1.0.1.tgz#2594d42da73cd036bd0d2a54683dd35a6b55ca17" - integrity sha512-kcoMoKTPYnoeS50tzoqjPY3Uv9axeuuFAZY9M/9zFnhoVvRfxz9K29IMPD7jGmt2c8SW7i3gT9WqDl2+nV7p4A== - -type-check@~0.3.2: - version "0.3.2" - resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" - integrity sha1-WITKtRLPHTVeP7eE8wgEsrUg23I= - dependencies: - prelude-ls "~1.1.2" - -type-detect@^4.0.0, type-detect@^4.0.5: - version "4.0.8" - resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" - integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== - -type-is@~1.6.17, type-is@~1.6.18: - version "1.6.18" - resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" - integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== - dependencies: - media-typer "0.3.0" - mime-types "~2.1.24" - -type@^1.0.1: - version "1.2.0" - resolved "https://registry.yarnpkg.com/type/-/type-1.2.0.tgz#848dd7698dafa3e54a6c479e759c4bc3f18847a0" - integrity sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg== - -type@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/type/-/type-2.0.0.tgz#5f16ff6ef2eb44f260494dae271033b29c09a9c3" - integrity sha512-KBt58xCHry4Cejnc2ISQAF7QY+ORngsWfxezO68+12hKV6lQY8P/psIkcbjeHWn7MqcgciWJyCCevFMJdIXpow== - -typedarray-to-buffer@^3.1.5: - version "3.1.5" - resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" - integrity sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q== - dependencies: - is-typedarray "^1.0.0" - -typedarray@^0.0.6: - version "0.0.6" - resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" - integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= - -typescript@^3.5.1: - version "3.7.4" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.7.4.tgz#1743a5ec5fef6a1fa9f3e4708e33c81c73876c19" - integrity sha512-A25xv5XCtarLwXpcDNZzCGvW2D1S3/bACratYBx2sax8PefsFhlYmkQicKHvpYflFS8if4zne5zT5kpJ7pzuvw== - -typescript@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.0.2.tgz#7ea7c88777c723c681e33bf7988be5d008d05ac2" - integrity sha512-e4ERvRV2wb+rRZ/IQeb3jm2VxBsirQLpQhdxplZ2MEzGvDkkMmPglecnNDfSUBivMjP93vRbngYYDQqQ/78bcQ== - -typewise-core@^1.2, typewise-core@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/typewise-core/-/typewise-core-1.2.0.tgz#97eb91805c7f55d2f941748fa50d315d991ef195" - integrity sha1-l+uRgFx/VdL5QXSPpQ0xXZke8ZU= - -typewise@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/typewise/-/typewise-1.0.3.tgz#1067936540af97937cc5dcf9922486e9fa284651" - integrity sha1-EGeTZUCvl5N8xdz5kiSG6fooRlE= - dependencies: - typewise-core "^1.2.0" - -typewiselite@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/typewiselite/-/typewiselite-1.0.0.tgz#c8882fa1bb1092c06005a97f34ef5c8508e3664e" - integrity sha1-yIgvobsQksBgBal/NO9chQjjZk4= - -u2f-api@0.2.7: - version "0.2.7" - resolved "https://registry.yarnpkg.com/u2f-api/-/u2f-api-0.2.7.tgz#17bf196b242f6bf72353d9858e6a7566cc192720" - integrity sha512-fqLNg8vpvLOD5J/z4B6wpPg4Lvowz1nJ9xdHcCzdUPKcFE/qNCceV2gNZxSJd5vhAZemHr/K/hbzVA0zxB5mkg== - -uglify-js@^3.1.4: - version "3.7.1" - resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.7.1.tgz#35c7de17971a4aa7689cd2eae0a5b39bb838c0c5" - integrity sha512-pnOF7jY82wdIhATVn87uUY/FHU+MDUdPLkmGFvGoclQmeu229eTkbG5gjGGBi3R7UuYYSEeYXY/TTY5j2aym2g== - dependencies: - commander "~2.20.3" - source-map "~0.6.1" - -ultron@~1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/ultron/-/ultron-1.1.1.tgz#9fe1536a10a664a65266a1e3ccf85fd36302bc9c" - integrity sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og== - -unbzip2-stream@^1.0.9: - version "1.3.3" - resolved "https://registry.yarnpkg.com/unbzip2-stream/-/unbzip2-stream-1.3.3.tgz#d156d205e670d8d8c393e1c02ebd506422873f6a" - integrity sha512-fUlAF7U9Ah1Q6EieQ4x4zLNejrRvDWUYmxXUpN3uziFYCHapjWFaCAnreY9bGgxzaMCFAPPpYNng57CypwJVhg== - dependencies: - buffer "^5.2.1" - through "^2.3.8" - -unc-path-regex@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/unc-path-regex/-/unc-path-regex-0.1.2.tgz#e73dd3d7b0d7c5ed86fbac6b0ae7d8c6a69d50fa" - integrity sha1-5z3T17DXxe2G+6xrCufYxqadUPo= - -underscore@1.9.1: - version "1.9.1" - resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.9.1.tgz#06dce34a0e68a7babc29b365b8e74b8925203961" - integrity sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg== - -undertaker-registry@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/undertaker-registry/-/undertaker-registry-1.0.1.tgz#5e4bda308e4a8a2ae584f9b9a4359a499825cc50" - integrity sha1-XkvaMI5KiirlhPm5pDWaSZglzFA= - -undertaker@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/undertaker/-/undertaker-1.2.1.tgz#701662ff8ce358715324dfd492a4f036055dfe4b" - integrity sha512-71WxIzDkgYk9ZS+spIB8iZXchFhAdEo2YU8xYqBYJ39DIUIqziK78ftm26eecoIY49X0J2MLhG4hr18Yp6/CMA== - dependencies: - arr-flatten "^1.0.1" - arr-map "^2.0.0" - bach "^1.0.0" - collection-map "^1.0.0" - es6-weak-map "^2.0.1" - last-run "^1.1.0" - object.defaults "^1.0.0" - object.reduce "^1.0.0" - undertaker-registry "^1.0.0" - -union-value@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.1.tgz#0b6fe7b835aecda61c6ea4d4f02c14221e109847" - integrity sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg== - dependencies: - arr-union "^3.1.0" - get-value "^2.0.6" - is-extendable "^0.1.1" - set-value "^2.0.1" - -unique-filename@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/unique-filename/-/unique-filename-1.1.1.tgz#1d69769369ada0583103a1e6ae87681b56573230" - integrity sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ== - dependencies: - unique-slug "^2.0.0" - -unique-slug@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/unique-slug/-/unique-slug-2.0.2.tgz#baabce91083fc64e945b0f3ad613e264f7cd4e6c" - integrity sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w== - dependencies: - imurmurhash "^0.1.4" - -unique-stream@^2.0.2: - version "2.3.1" - resolved "https://registry.yarnpkg.com/unique-stream/-/unique-stream-2.3.1.tgz#c65d110e9a4adf9a6c5948b28053d9a8d04cbeac" - integrity sha512-2nY4TnBE70yoxHkDli7DMazpWiP7xMdCYqU2nBRO0UB+ZpEkGsSija7MvmvnZFUeC+mrgiUfcHSr3LmRFIg4+A== - dependencies: - json-stable-stringify-without-jsonify "^1.0.1" - through2-filter "^3.0.0" - -universalify@^0.1.0: - version "0.1.2" - resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" - integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== - -unorm@^1.3.3: - version "1.6.0" - resolved "https://registry.yarnpkg.com/unorm/-/unorm-1.6.0.tgz#029b289661fba714f1a9af439eb51d9b16c205af" - integrity sha512-b2/KCUlYZUeA7JFUuRJZPUtr4gZvBh7tavtv4fvk4+KV9pfGiR6CQAQAWl49ZpR3ts2dk4FYkP7EIgDJoiOLDA== - -unpipe@1.0.0, unpipe@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" - integrity sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw= - -unset-value@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559" - integrity sha1-g3aHP30jNRef+x5vw6jtDfyKtVk= - dependencies: - has-value "^0.3.1" - isobject "^3.0.0" - -upath@^1.1.1: - version "1.2.0" - resolved "https://registry.yarnpkg.com/upath/-/upath-1.2.0.tgz#8f66dbcd55a883acdae4408af8b035a5044c1894" - integrity sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg== - -uri-js@^4.2.2: - version "4.2.2" - resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0" - integrity sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ== - dependencies: - punycode "^2.1.0" - -urix@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" - integrity sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI= - -url-parse-lax@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-1.0.0.tgz#7af8f303645e9bd79a272e7a14ac68bc0609da73" - integrity sha1-evjzA2Rem9eaJy56FKxovAYJ2nM= - dependencies: - prepend-http "^1.0.1" - -url-parse-lax@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-3.0.0.tgz#16b5cafc07dbe3676c1b1999177823d6503acb0c" - integrity sha1-FrXK/Afb42dsGxmZF3gj1lA6yww= - dependencies: - prepend-http "^2.0.0" - -url-set-query@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/url-set-query/-/url-set-query-1.0.0.tgz#016e8cfd7c20ee05cafe7795e892bd0702faa339" - integrity sha1-AW6M/Xwg7gXK/neV6JK9BwL6ozk= - -url-to-options@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/url-to-options/-/url-to-options-1.0.1.tgz#1505a03a289a48cbd7a434efbaeec5055f5633a9" - integrity sha1-FQWgOiiaSMvXpDTvuu7FBV9WM6k= - -url@^0.11.0: - version "0.11.0" - resolved "https://registry.yarnpkg.com/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1" - integrity sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE= - dependencies: - punycode "1.3.2" - querystring "0.2.0" - -usb@^1.6.0: - version "1.6.2" - resolved "https://registry.yarnpkg.com/usb/-/usb-1.6.2.tgz#4ed7f0d8631c70192b33635f6a4e700d9e6bfe62" - integrity sha512-KcovLXRQuH63iEtnqXyDQGOi5dXHpLM5lZBIUsqSJQToua8nL2sVCieQTkzQBfLe5mCuvk40MgKciI61lgevWw== - dependencies: - bindings "^1.4.0" - nan "2.13.2" - prebuild-install "^5.3.3" - -use@^3.1.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" - integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ== - -utf8@3.0.0, utf8@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/utf8/-/utf8-3.0.0.tgz#f052eed1364d696e769ef058b183df88c87f69d1" - integrity sha512-E8VjFIQ/TyQgp+TZfS6l8yp/xWppSAHzidGiRrqe4bK4XP9pTRyKFgGJpO3SN7zdX4DeomTrwaseCHovfpFcqQ== - -util-deprecate@^1.0.1, util-deprecate@~1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" - integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= - -util.promisify@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/util.promisify/-/util.promisify-1.0.0.tgz#440f7165a459c9a16dc145eb8e72f35687097030" - integrity sha512-i+6qA2MPhvoKLuxnJNpXAGhg7HphQOSUq2LKMZD0m15EiskXUkMvKdF4Uui0WYeCUGea+o2cw/ZuwehtfsrNkA== - dependencies: - define-properties "^1.1.2" - object.getownpropertydescriptors "^2.0.3" - -util@0.10.3: - version "0.10.3" - resolved "https://registry.yarnpkg.com/util/-/util-0.10.3.tgz#7afb1afe50805246489e3db7fe0ed379336ac0f9" - integrity sha1-evsa/lCAUkZInj23/g7TeTNqwPk= - dependencies: - inherits "2.0.1" - -util@^0.11.0: - version "0.11.1" - resolved "https://registry.yarnpkg.com/util/-/util-0.11.1.tgz#3236733720ec64bb27f6e26f421aaa2e1b588d61" - integrity sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ== - dependencies: - inherits "2.0.3" - -utils-merge@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" - integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM= - -uuid@2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-2.0.1.tgz#c2a30dedb3e535d72ccf82e343941a50ba8533ac" - integrity sha1-wqMN7bPlNdcsz4LjQ5QaULqFM6w= - -uuid@3.3.2: - version "3.3.2" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131" - integrity sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA== - -uuid@^3.3.2: - version "3.3.3" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.3.tgz#4568f0216e78760ee1dbf3a4d2cf53e224112866" - integrity sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ== - -v8-compile-cache@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.1.1.tgz#54bc3cdd43317bca91e35dcaf305b1a7237de745" - integrity sha512-8OQ9CL+VWyt3JStj7HX7/ciTL2V3Rl1Wf5OL+SNTm0yK1KvtReVulksyeRnCANHHuUxHlQig+JJDlUhBt1NQDQ== - -v8flags@^3.0.1: - version "3.1.3" - resolved "https://registry.yarnpkg.com/v8flags/-/v8flags-3.1.3.tgz#fc9dc23521ca20c5433f81cc4eb9b3033bb105d8" - integrity sha512-amh9CCg3ZxkzQ48Mhcb8iX7xpAfYJgePHxWMQCBWECpOSqJUXgY26ncA61UTV0BkPqfhcy6mzwCIoP4ygxpW8w== - dependencies: - homedir-polyfill "^1.0.1" - -valid-url@^1.0.9: - version "1.0.9" - resolved "https://registry.yarnpkg.com/valid-url/-/valid-url-1.0.9.tgz#1c14479b40f1397a75782f115e4086447433a200" - integrity sha1-HBRHm0DxOXp1eC8RXkCGRHQzogA= - -validate-npm-package-license@^3.0.1: - version "3.0.4" - resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" - integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew== - dependencies: - spdx-correct "^3.0.0" - spdx-expression-parse "^3.0.0" - -value-or-function@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/value-or-function/-/value-or-function-3.0.0.tgz#1c243a50b595c1be54a754bfece8563b9ff8d813" - integrity sha1-HCQ6ULWVwb5Up1S/7OhWO5/42BM= - -varint@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/varint/-/varint-5.0.0.tgz#d826b89f7490732fabc0c0ed693ed475dcb29ebf" - integrity sha1-2Ca4n3SQcy+rwMDtaT7Uddyynr8= - -vary@^1, vary@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" - integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw= - -verror@1.10.0: - version "1.10.0" - resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" - integrity sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA= - dependencies: - assert-plus "^1.0.0" - core-util-is "1.0.2" - extsprintf "^1.2.0" - -vinyl-fs@^3.0.0: - version "3.0.3" - resolved "https://registry.yarnpkg.com/vinyl-fs/-/vinyl-fs-3.0.3.tgz#c85849405f67428feabbbd5c5dbdd64f47d31bc7" - integrity sha512-vIu34EkyNyJxmP0jscNzWBSygh7VWhqun6RmqVfXePrOwi9lhvRs//dOaGOTRUQr4tx7/zd26Tk5WeSVZitgng== - dependencies: - fs-mkdirp-stream "^1.0.0" - glob-stream "^6.1.0" - graceful-fs "^4.0.0" - is-valid-glob "^1.0.0" - lazystream "^1.0.0" - lead "^1.0.0" - object.assign "^4.0.4" - pumpify "^1.3.5" - readable-stream "^2.3.3" - remove-bom-buffer "^3.0.0" - remove-bom-stream "^1.2.0" - resolve-options "^1.1.0" - through2 "^2.0.0" - to-through "^2.0.0" - value-or-function "^3.0.0" - vinyl "^2.0.0" - vinyl-sourcemap "^1.1.0" - -vinyl-sourcemap@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/vinyl-sourcemap/-/vinyl-sourcemap-1.1.0.tgz#92a800593a38703a8cdb11d8b300ad4be63b3e16" - integrity sha1-kqgAWTo4cDqM2xHYswCtS+Y7PhY= - dependencies: - append-buffer "^1.0.2" - convert-source-map "^1.5.0" - graceful-fs "^4.1.6" - normalize-path "^2.1.1" - now-and-later "^2.0.0" - remove-bom-buffer "^3.0.0" - vinyl "^2.0.0" - -vinyl@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-2.2.0.tgz#d85b07da96e458d25b2ffe19fece9f2caa13ed86" - integrity sha512-MBH+yP0kC/GQ5GwBqrTPTzEfiiLjta7hTtvQtbxBgTeSXsmKQRQecjibMbxIXzVT3Y9KJK+drOz1/k+vsu8Nkg== - dependencies: - clone "^2.1.1" - clone-buffer "^1.0.0" - clone-stats "^1.0.0" - cloneable-readable "^1.0.0" - remove-trailing-separator "^1.0.1" - replace-ext "^1.0.0" - -vm-browserify@^1.0.1: - version "1.1.2" - resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-1.1.2.tgz#78641c488b8e6ca91a75f511e7a3b32a86e5dda0" - integrity sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ== - -w3c-hr-time@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/w3c-hr-time/-/w3c-hr-time-1.0.1.tgz#82ac2bff63d950ea9e3189a58a65625fedf19045" - integrity sha1-gqwr/2PZUOqeMYmlimViX+3xkEU= - dependencies: - browser-process-hrtime "^0.1.2" - -walker@^1.0.7, walker@~1.0.5: - version "1.0.7" - resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.7.tgz#2f7f9b8fd10d677262b18a884e28d19618e028fb" - integrity sha1-L3+bj9ENZ3JisYqITijRlhjgKPs= - dependencies: - makeerror "1.0.x" - -watchpack-chokidar2@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/watchpack-chokidar2/-/watchpack-chokidar2-2.0.0.tgz#9948a1866cbbd6cb824dea13a7ed691f6c8ddff0" - integrity sha512-9TyfOyN/zLUbA288wZ8IsMZ+6cbzvsNyEzSBp6e/zkifi6xxbl8SmQ/CxQq32k8NNqrdVEVUVSEf56L4rQ/ZxA== - dependencies: - chokidar "^2.1.8" - -watchpack@^1.7.4: - version "1.7.4" - resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.7.4.tgz#6e9da53b3c80bb2d6508188f5b200410866cd30b" - integrity sha512-aWAgTW4MoSJzZPAicljkO1hsi1oKj/RRq/OJQh2PKI2UKL04c2Bs+MBOB+BBABHTXJpf9mCwHN7ANCvYsvY2sg== - dependencies: - graceful-fs "^4.1.2" - neo-async "^2.5.0" - optionalDependencies: - chokidar "^3.4.1" - watchpack-chokidar2 "^2.0.0" - -web3-bzz@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-bzz/-/web3-bzz-1.2.11.tgz#41bc19a77444bd5365744596d778b811880f707f" - integrity sha512-XGpWUEElGypBjeFyUhTkiPXFbDVD6Nr/S5jznE3t8cWUA0FxRf1n3n/NuIZeb0H9RkN2Ctd/jNma/k8XGa3YKg== - dependencies: - "@types/node" "^12.12.6" - got "9.6.0" - swarm-js "^0.1.40" - underscore "1.9.1" - -web3-bzz@1.2.4: - version "1.2.4" - resolved "https://registry.yarnpkg.com/web3-bzz/-/web3-bzz-1.2.4.tgz#a4adb7a8cba3d260de649bdb1f14ed359bfb3821" - integrity sha512-MqhAo/+0iQSMBtt3/QI1rU83uvF08sYq8r25+OUZ+4VtihnYsmkkca+rdU0QbRyrXY2/yGIpI46PFdh0khD53A== - dependencies: - "@types/node" "^10.12.18" - got "9.6.0" - swarm-js "0.1.39" - underscore "1.9.1" - -web3-core-helpers@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-core-helpers/-/web3-core-helpers-1.2.11.tgz#84c681ed0b942c0203f3b324a245a127e8c67a99" - integrity sha512-PEPoAoZd5ME7UfbnCZBdzIerpe74GEvlwT4AjOmHeCVZoIFk7EqvOZDejJHt+feJA6kMVTdd0xzRNN295UhC1A== - dependencies: - underscore "1.9.1" - web3-eth-iban "1.2.11" - web3-utils "1.2.11" - -web3-core-helpers@1.2.4: - version "1.2.4" - resolved "https://registry.yarnpkg.com/web3-core-helpers/-/web3-core-helpers-1.2.4.tgz#ffd425861f4d66b3f38df032afdb39ea0971fc0f" - integrity sha512-U7wbsK8IbZvF3B7S+QMSNP0tni/6VipnJkB0tZVEpHEIV2WWeBHYmZDnULWcsS/x/jn9yKhJlXIxWGsEAMkjiw== - dependencies: - underscore "1.9.1" - web3-eth-iban "1.2.4" - web3-utils "1.2.4" - -web3-core-method@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-core-method/-/web3-core-method-1.2.11.tgz#f880137d1507a0124912bf052534f168b8d8fbb6" - integrity sha512-ff0q76Cde94HAxLDZ6DbdmKniYCQVtvuaYh+rtOUMB6kssa5FX0q3vPmixi7NPooFnbKmmZCM6NvXg4IreTPIw== - dependencies: - "@ethersproject/transactions" "^5.0.0-beta.135" - underscore "1.9.1" - web3-core-helpers "1.2.11" - web3-core-promievent "1.2.11" - web3-core-subscriptions "1.2.11" - web3-utils "1.2.11" - -web3-core-method@1.2.4: - version "1.2.4" - resolved "https://registry.yarnpkg.com/web3-core-method/-/web3-core-method-1.2.4.tgz#a0fbc50b8ff5fd214021435cc2c6d1e115807aed" - integrity sha512-8p9kpL7di2qOVPWgcM08kb+yKom0rxRCMv6m/K+H+yLSxev9TgMbCgMSbPWAHlyiF3SJHw7APFKahK5Z+8XT5A== - dependencies: - underscore "1.9.1" - web3-core-helpers "1.2.4" - web3-core-promievent "1.2.4" - web3-core-subscriptions "1.2.4" - web3-utils "1.2.4" - -web3-core-promievent@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-core-promievent/-/web3-core-promievent-1.2.11.tgz#51fe97ca0ddec2f99bf8c3306a7a8e4b094ea3cf" - integrity sha512-il4McoDa/Ox9Agh4kyfQ8Ak/9ABYpnF8poBLL33R/EnxLsJOGQG2nZhkJa3I067hocrPSjEdlPt/0bHXsln4qA== - dependencies: - eventemitter3 "4.0.4" - -web3-core-promievent@1.2.4: - version "1.2.4" - resolved "https://registry.yarnpkg.com/web3-core-promievent/-/web3-core-promievent-1.2.4.tgz#75e5c0f2940028722cdd21ba503ebd65272df6cb" - integrity sha512-gEUlm27DewUsfUgC3T8AxkKi8Ecx+e+ZCaunB7X4Qk3i9F4C+5PSMGguolrShZ7Zb6717k79Y86f3A00O0VAZw== - dependencies: - any-promise "1.3.0" - eventemitter3 "3.1.2" - -web3-core-requestmanager@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-core-requestmanager/-/web3-core-requestmanager-1.2.11.tgz#fe6eb603fbaee18530293a91f8cf26d8ae28c45a" - integrity sha512-oFhBtLfOiIbmfl6T6gYjjj9igOvtyxJ+fjS+byRxiwFJyJ5BQOz4/9/17gWR1Cq74paTlI7vDGxYfuvfE/mKvA== - dependencies: - underscore "1.9.1" - web3-core-helpers "1.2.11" - web3-providers-http "1.2.11" - web3-providers-ipc "1.2.11" - web3-providers-ws "1.2.11" - -web3-core-requestmanager@1.2.4: - version "1.2.4" - resolved "https://registry.yarnpkg.com/web3-core-requestmanager/-/web3-core-requestmanager-1.2.4.tgz#0a7020a23fb91c6913c611dfd3d8c398d1e4b4a8" - integrity sha512-eZJDjyNTDtmSmzd3S488nR/SMJtNnn/GuwxnMh3AzYCqG3ZMfOylqTad2eYJPvc2PM5/Gj1wAMQcRpwOjjLuPg== - dependencies: - underscore "1.9.1" - web3-core-helpers "1.2.4" - web3-providers-http "1.2.4" - web3-providers-ipc "1.2.4" - web3-providers-ws "1.2.4" - -web3-core-subscriptions@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-core-subscriptions/-/web3-core-subscriptions-1.2.11.tgz#beca908fbfcb050c16f45f3f0f4c205e8505accd" - integrity sha512-qEF/OVqkCvQ7MPs1JylIZCZkin0aKK9lDxpAtQ1F8niEDGFqn7DT8E/vzbIa0GsOjL2fZjDhWJsaW+BSoAW1gg== - dependencies: - eventemitter3 "4.0.4" - underscore "1.9.1" - web3-core-helpers "1.2.11" - -web3-core-subscriptions@1.2.4: - version "1.2.4" - resolved "https://registry.yarnpkg.com/web3-core-subscriptions/-/web3-core-subscriptions-1.2.4.tgz#0dc095b5cfd82baa527a39796e3515a846b21b99" - integrity sha512-3D607J2M8ymY9V+/WZq4MLlBulwCkwEjjC2U+cXqgVO1rCyVqbxZNCmHyNYHjDDCxSEbks9Ju5xqJxDSxnyXEw== - dependencies: - eventemitter3 "3.1.2" - underscore "1.9.1" - web3-core-helpers "1.2.4" - -web3-core@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-core/-/web3-core-1.2.11.tgz#1043cacc1becb80638453cc5b2a14be9050288a7" - integrity sha512-CN7MEYOY5ryo5iVleIWRE3a3cZqVaLlIbIzDPsvQRUfzYnvzZQRZBm9Mq+ttDi2STOOzc1MKylspz/o3yq/LjQ== - dependencies: - "@types/bn.js" "^4.11.5" - "@types/node" "^12.12.6" - bignumber.js "^9.0.0" - web3-core-helpers "1.2.11" - web3-core-method "1.2.11" - web3-core-requestmanager "1.2.11" - web3-utils "1.2.11" - -web3-core@1.2.4: - version "1.2.4" - resolved "https://registry.yarnpkg.com/web3-core/-/web3-core-1.2.4.tgz#2df13b978dcfc59c2abaa887d27f88f21ad9a9d6" - integrity sha512-CHc27sMuET2cs1IKrkz7xzmTdMfZpYswe7f0HcuyneTwS1yTlTnHyqjAaTy0ZygAb/x4iaVox+Gvr4oSAqSI+A== - dependencies: - "@types/bignumber.js" "^5.0.0" - "@types/bn.js" "^4.11.4" - "@types/node" "^12.6.1" - web3-core-helpers "1.2.4" - web3-core-method "1.2.4" - web3-core-requestmanager "1.2.4" - web3-utils "1.2.4" - -web3-eth-abi@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-eth-abi/-/web3-eth-abi-1.2.11.tgz#a887494e5d447c2926d557a3834edd66e17af9b0" - integrity sha512-PkRYc0+MjuLSgg03QVWqWlQivJqRwKItKtEpRUaxUAeLE7i/uU39gmzm2keHGcQXo3POXAbOnMqkDvOep89Crg== - dependencies: - "@ethersproject/abi" "5.0.0-beta.153" - underscore "1.9.1" - web3-utils "1.2.11" - -web3-eth-abi@1.2.4, web3-eth-abi@^1.0.0-beta.24: - version "1.2.4" - resolved "https://registry.yarnpkg.com/web3-eth-abi/-/web3-eth-abi-1.2.4.tgz#5b73e5ef70b03999227066d5d1310b168845e2b8" - integrity sha512-8eLIY4xZKoU3DSVu1pORluAw9Ru0/v4CGdw5so31nn+7fR8zgHMgwbFe0aOqWQ5VU42PzMMXeIJwt4AEi2buFg== - dependencies: - ethers "4.0.0-beta.3" - underscore "1.9.1" - web3-utils "1.2.4" - -web3-eth-accounts@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-eth-accounts/-/web3-eth-accounts-1.2.11.tgz#a9e3044da442d31903a7ce035a86d8fa33f90520" - integrity sha512-6FwPqEpCfKIh3nSSGeo3uBm2iFSnFJDfwL3oS9pyegRBXNsGRVpgiW63yhNzL0796StsvjHWwQnQHsZNxWAkGw== - dependencies: - crypto-browserify "3.12.0" - eth-lib "0.2.8" - ethereumjs-common "^1.3.2" - ethereumjs-tx "^2.1.1" - scrypt-js "^3.0.1" - underscore "1.9.1" - uuid "3.3.2" - web3-core "1.2.11" - web3-core-helpers "1.2.11" - web3-core-method "1.2.11" - web3-utils "1.2.11" - -web3-eth-accounts@1.2.4: - version "1.2.4" - resolved "https://registry.yarnpkg.com/web3-eth-accounts/-/web3-eth-accounts-1.2.4.tgz#ada6edc49542354328a85cafab067acd7f88c288" - integrity sha512-04LzT/UtWmRFmi4hHRewP5Zz43fWhuHiK5XimP86sUQodk/ByOkXQ3RoXyGXFMNoRxdcAeRNxSfA2DpIBc9xUw== - dependencies: - "@web3-js/scrypt-shim" "^0.1.0" - any-promise "1.3.0" - crypto-browserify "3.12.0" - eth-lib "0.2.7" - ethereumjs-common "^1.3.2" - ethereumjs-tx "^2.1.1" - underscore "1.9.1" - uuid "3.3.2" - web3-core "1.2.4" - web3-core-helpers "1.2.4" - web3-core-method "1.2.4" - web3-utils "1.2.4" - -web3-eth-contract@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-eth-contract/-/web3-eth-contract-1.2.11.tgz#917065902bc27ce89da9a1da26e62ef663663b90" - integrity sha512-MzYuI/Rq2o6gn7vCGcnQgco63isPNK5lMAan2E51AJLknjSLnOxwNY3gM8BcKoy4Z+v5Dv00a03Xuk78JowFow== - dependencies: - "@types/bn.js" "^4.11.5" - underscore "1.9.1" - web3-core "1.2.11" - web3-core-helpers "1.2.11" - web3-core-method "1.2.11" - web3-core-promievent "1.2.11" - web3-core-subscriptions "1.2.11" - web3-eth-abi "1.2.11" - web3-utils "1.2.11" - -web3-eth-contract@1.2.4: - version "1.2.4" - resolved "https://registry.yarnpkg.com/web3-eth-contract/-/web3-eth-contract-1.2.4.tgz#68ef7cc633232779b0a2c506a810fbe903575886" - integrity sha512-b/9zC0qjVetEYnzRA1oZ8gF1OSSUkwSYi5LGr4GeckLkzXP7osEnp9lkO/AQcE4GpG+l+STnKPnASXJGZPgBRQ== - dependencies: - "@types/bn.js" "^4.11.4" - underscore "1.9.1" - web3-core "1.2.4" - web3-core-helpers "1.2.4" - web3-core-method "1.2.4" - web3-core-promievent "1.2.4" - web3-core-subscriptions "1.2.4" - web3-eth-abi "1.2.4" - web3-utils "1.2.4" - -web3-eth-ens@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-eth-ens/-/web3-eth-ens-1.2.11.tgz#26d4d7f16d6cbcfff918e39832b939edc3162532" - integrity sha512-dbW7dXP6HqT1EAPvnniZVnmw6TmQEKF6/1KgAxbo8iBBYrVTMDGFQUUnZ+C4VETGrwwaqtX4L9d/FrQhZ6SUiA== - dependencies: - content-hash "^2.5.2" - eth-ens-namehash "2.0.8" - underscore "1.9.1" - web3-core "1.2.11" - web3-core-helpers "1.2.11" - web3-core-promievent "1.2.11" - web3-eth-abi "1.2.11" - web3-eth-contract "1.2.11" - web3-utils "1.2.11" - -web3-eth-ens@1.2.4: - version "1.2.4" - resolved "https://registry.yarnpkg.com/web3-eth-ens/-/web3-eth-ens-1.2.4.tgz#b95b3aa99fb1e35c802b9e02a44c3046a3fa065e" - integrity sha512-g8+JxnZlhdsCzCS38Zm6R/ngXhXzvc3h7bXlxgKU4coTzLLoMpgOAEz71GxyIJinWTFbLXk/WjNY0dazi9NwVw== - dependencies: - eth-ens-namehash "2.0.8" - underscore "1.9.1" - web3-core "1.2.4" - web3-core-helpers "1.2.4" - web3-core-promievent "1.2.4" - web3-eth-abi "1.2.4" - web3-eth-contract "1.2.4" - web3-utils "1.2.4" - -web3-eth-iban@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-eth-iban/-/web3-eth-iban-1.2.11.tgz#f5f73298305bc7392e2f188bf38a7362b42144ef" - integrity sha512-ozuVlZ5jwFC2hJY4+fH9pIcuH1xP0HEFhtWsR69u9uDIANHLPQQtWYmdj7xQ3p2YT4bQLq/axKhZi7EZVetmxQ== - dependencies: - bn.js "^4.11.9" - web3-utils "1.2.11" - -web3-eth-iban@1.2.4: - version "1.2.4" - resolved "https://registry.yarnpkg.com/web3-eth-iban/-/web3-eth-iban-1.2.4.tgz#8e0550fd3fd8e47a39357d87fe27dee9483ee476" - integrity sha512-D9HIyctru/FLRpXakRwmwdjb5bWU2O6UE/3AXvRm6DCOf2e+7Ve11qQrPtaubHfpdW3KWjDKvlxV9iaFv/oTMQ== - dependencies: - bn.js "4.11.8" - web3-utils "1.2.4" - -web3-eth-personal@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-eth-personal/-/web3-eth-personal-1.2.11.tgz#a38b3942a1d87a62070ce0622a941553c3d5aa70" - integrity sha512-42IzUtKq9iHZ8K9VN0vAI50iSU9tOA1V7XU2BhF/tb7We2iKBVdkley2fg26TxlOcKNEHm7o6HRtiiFsVK4Ifw== - dependencies: - "@types/node" "^12.12.6" - web3-core "1.2.11" - web3-core-helpers "1.2.11" - web3-core-method "1.2.11" - web3-net "1.2.11" - web3-utils "1.2.11" - -web3-eth-personal@1.2.4: - version "1.2.4" - resolved "https://registry.yarnpkg.com/web3-eth-personal/-/web3-eth-personal-1.2.4.tgz#3224cca6851c96347d9799b12c1b67b2a6eb232b" - integrity sha512-5Russ7ZECwHaZXcN3DLuLS7390Vzgrzepl4D87SD6Sn1DHsCZtvfdPIYwoTmKNp69LG3mORl7U23Ga5YxqkICw== - dependencies: - "@types/node" "^12.6.1" - web3-core "1.2.4" - web3-core-helpers "1.2.4" - web3-core-method "1.2.4" - web3-net "1.2.4" - web3-utils "1.2.4" - -web3-eth@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-eth/-/web3-eth-1.2.11.tgz#4c81fcb6285b8caf544058fba3ae802968fdc793" - integrity sha512-REvxW1wJ58AgHPcXPJOL49d1K/dPmuw4LjPLBPStOVkQjzDTVmJEIsiLwn2YeuNDd4pfakBwT8L3bz1G1/wVsQ== - dependencies: - underscore "1.9.1" - web3-core "1.2.11" - web3-core-helpers "1.2.11" - web3-core-method "1.2.11" - web3-core-subscriptions "1.2.11" - web3-eth-abi "1.2.11" - web3-eth-accounts "1.2.11" - web3-eth-contract "1.2.11" - web3-eth-ens "1.2.11" - web3-eth-iban "1.2.11" - web3-eth-personal "1.2.11" - web3-net "1.2.11" - web3-utils "1.2.11" - -web3-eth@1.2.4: - version "1.2.4" - resolved "https://registry.yarnpkg.com/web3-eth/-/web3-eth-1.2.4.tgz#24c3b1f1ac79351bbfb808b2ab5c585fa57cdd00" - integrity sha512-+j+kbfmZsbc3+KJpvHM16j1xRFHe2jBAniMo1BHKc3lho6A8Sn9Buyut6odubguX2AxoRArCdIDCkT9hjUERpA== - dependencies: - underscore "1.9.1" - web3-core "1.2.4" - web3-core-helpers "1.2.4" - web3-core-method "1.2.4" - web3-core-subscriptions "1.2.4" - web3-eth-abi "1.2.4" - web3-eth-accounts "1.2.4" - web3-eth-contract "1.2.4" - web3-eth-ens "1.2.4" - web3-eth-iban "1.2.4" - web3-eth-personal "1.2.4" - web3-net "1.2.4" - web3-utils "1.2.4" - -web3-net@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-net/-/web3-net-1.2.11.tgz#eda68ef25e5cdb64c96c39085cdb74669aabbe1b" - integrity sha512-sjrSDj0pTfZouR5BSTItCuZ5K/oZPVdVciPQ6981PPPIwJJkCMeVjD7I4zO3qDPCnBjBSbWvVnLdwqUBPtHxyg== - dependencies: - web3-core "1.2.11" - web3-core-method "1.2.11" - web3-utils "1.2.11" - -web3-net@1.2.4: - version "1.2.4" - resolved "https://registry.yarnpkg.com/web3-net/-/web3-net-1.2.4.tgz#1d246406d3aaffbf39c030e4e98bce0ca5f25458" - integrity sha512-wKOsqhyXWPSYTGbp7ofVvni17yfRptpqoUdp3SC8RAhDmGkX6irsiT9pON79m6b3HUHfLoBilFQyt/fTUZOf7A== - dependencies: - web3-core "1.2.4" - web3-core-method "1.2.4" - web3-utils "1.2.4" - -web3-provider-engine@14.0.6: - version "14.0.6" - resolved "https://registry.yarnpkg.com/web3-provider-engine/-/web3-provider-engine-14.0.6.tgz#cbdd66fe20c0136a3a495cbe40d18b6c4160d5f0" - integrity sha512-tr5cGSyxfSC/JqiUpBlJtfZpwQf1yAA8L/zy1C6fDFm0ntR974pobJ4v4676atpZne4Ze5VFy3kPPahHe9gQiQ== - dependencies: - async "^2.5.0" - backoff "^2.5.0" - clone "^2.0.0" - cross-fetch "^2.1.0" - eth-block-tracker "^3.0.0" - eth-json-rpc-infura "^3.1.0" - eth-sig-util "^1.4.2" - ethereumjs-block "^1.2.2" - ethereumjs-tx "^1.2.0" - ethereumjs-util "^5.1.5" - ethereumjs-vm "^2.3.4" - json-rpc-error "^2.0.0" - json-stable-stringify "^1.0.1" - promise-to-callback "^1.0.0" - readable-stream "^2.2.9" - request "^2.67.0" - semaphore "^1.0.3" - tape "^4.4.0" - ws "^5.1.1" - xhr "^2.2.0" - xtend "^4.0.1" - -web3-provider-engine@14.2.1: - version "14.2.1" - resolved "https://registry.yarnpkg.com/web3-provider-engine/-/web3-provider-engine-14.2.1.tgz#ef351578797bf170e08d529cb5b02f8751329b95" - integrity sha512-iSv31h2qXkr9vrL6UZDm4leZMc32SjWJFGOp/D92JXfcEboCqraZyuExDkpxKw8ziTufXieNM7LSXNHzszYdJw== - dependencies: - async "^2.5.0" - backoff "^2.5.0" - clone "^2.0.0" - cross-fetch "^2.1.0" - eth-block-tracker "^3.0.0" - eth-json-rpc-infura "^3.1.0" - eth-sig-util "^1.4.2" - ethereumjs-block "^1.2.2" - ethereumjs-tx "^1.2.0" - ethereumjs-util "^5.1.5" - ethereumjs-vm "^2.3.4" - json-rpc-error "^2.0.0" - json-stable-stringify "^1.0.1" - promise-to-callback "^1.0.0" - readable-stream "^2.2.9" - request "^2.85.0" - semaphore "^1.0.3" - ws "^5.1.1" - xhr "^2.2.0" - xtend "^4.0.1" - -web3-provider-engine@^15.0.4: - version "15.0.4" - resolved "https://registry.yarnpkg.com/web3-provider-engine/-/web3-provider-engine-15.0.4.tgz#5c336bcad2274dff5218bc8db003fa4e9e464c24" - integrity sha512-Ob9oK0TUZfVC7NXkB7CQSWAiCdCD/Xnlh2zTnV8NdJR8LCrMAy2i6JedU70JHaxw59y7mM4GnsYOTTGkquFnNQ== - dependencies: - async "^2.5.0" - backoff "^2.5.0" - clone "^2.0.0" - cross-fetch "^2.1.0" - eth-block-tracker "^4.4.2" - eth-json-rpc-errors "^1.0.1" - eth-json-rpc-filters "^4.1.1" - eth-json-rpc-infura "^4.0.1" - eth-json-rpc-middleware "^4.1.5" - eth-sig-util "^1.4.2" - ethereumjs-block "^1.2.2" - ethereumjs-tx "^1.2.0" - ethereumjs-util "^5.1.5" - ethereumjs-vm "^2.3.4" - json-stable-stringify "^1.0.1" - promise-to-callback "^1.0.0" - readable-stream "^2.2.9" - request "^2.85.0" - semaphore "^1.0.3" - ws "^5.1.1" - xhr "^2.2.0" - xtend "^4.0.1" - -web3-providers-http@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-providers-http/-/web3-providers-http-1.2.11.tgz#1cd03442c61670572d40e4dcdf1faff8bd91e7c6" - integrity sha512-psh4hYGb1+ijWywfwpB2cvvOIMISlR44F/rJtYkRmQ5jMvG4FOCPlQJPiHQZo+2cc3HbktvvSJzIhkWQJdmvrA== - dependencies: - web3-core-helpers "1.2.11" - xhr2-cookies "1.1.0" - -web3-providers-http@1.2.4: - version "1.2.4" - resolved "https://registry.yarnpkg.com/web3-providers-http/-/web3-providers-http-1.2.4.tgz#514fcad71ae77832c2c15574296282fbbc5f4a67" - integrity sha512-dzVCkRrR/cqlIrcrWNiPt9gyt0AZTE0J+MfAu9rR6CyIgtnm1wFUVVGaxYRxuTGQRO4Dlo49gtoGwaGcyxqiTw== - dependencies: - web3-core-helpers "1.2.4" - xhr2-cookies "1.1.0" - -web3-providers-ipc@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-providers-ipc/-/web3-providers-ipc-1.2.11.tgz#d16d6c9be1be6e0b4f4536c4acc16b0f4f27ef21" - integrity sha512-yhc7Y/k8hBV/KlELxynWjJDzmgDEDjIjBzXK+e0rHBsYEhdCNdIH5Psa456c+l0qTEU2YzycF8VAjYpWfPnBpQ== - dependencies: - oboe "2.1.4" - underscore "1.9.1" - web3-core-helpers "1.2.11" - -web3-providers-ipc@1.2.4: - version "1.2.4" - resolved "https://registry.yarnpkg.com/web3-providers-ipc/-/web3-providers-ipc-1.2.4.tgz#9d6659f8d44943fb369b739f48df09092be459bd" - integrity sha512-8J3Dguffin51gckTaNrO3oMBo7g+j0UNk6hXmdmQMMNEtrYqw4ctT6t06YOf9GgtOMjSAc1YEh3LPrvgIsR7og== - dependencies: - oboe "2.1.4" - underscore "1.9.1" - web3-core-helpers "1.2.4" - -web3-providers-ws@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-providers-ws/-/web3-providers-ws-1.2.11.tgz#a1dfd6d9778d840561d9ec13dd453046451a96bb" - integrity sha512-ZxnjIY1Er8Ty+cE4migzr43zA/+72AF1myzsLaU5eVgdsfV7Jqx7Dix1hbevNZDKFlSoEyq/3j/jYalh3So1Zg== - dependencies: - eventemitter3 "4.0.4" - underscore "1.9.1" - web3-core-helpers "1.2.11" - websocket "^1.0.31" - -web3-providers-ws@1.2.4: - version "1.2.4" - resolved "https://registry.yarnpkg.com/web3-providers-ws/-/web3-providers-ws-1.2.4.tgz#099ee271ee03f6ea4f5df9cfe969e83f4ce0e36f" - integrity sha512-F/vQpDzeK+++oeeNROl1IVTufFCwCR2hpWe5yRXN0ApLwHqXrMI7UwQNdJ9iyibcWjJf/ECbauEEQ8CHgE+MYQ== - dependencies: - "@web3-js/websocket" "^1.0.29" - underscore "1.9.1" - web3-core-helpers "1.2.4" - -web3-shh@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-shh/-/web3-shh-1.2.11.tgz#f5d086f9621c9a47e98d438010385b5f059fd88f" - integrity sha512-B3OrO3oG1L+bv3E1sTwCx66injW1A8hhwpknDUbV+sw3fehFazA06z9SGXUefuFI1kVs4q2vRi0n4oCcI4dZDg== - dependencies: - web3-core "1.2.11" - web3-core-method "1.2.11" - web3-core-subscriptions "1.2.11" - web3-net "1.2.11" - -web3-shh@1.2.4: - version "1.2.4" - resolved "https://registry.yarnpkg.com/web3-shh/-/web3-shh-1.2.4.tgz#5c8ff5ab624a3b14f08af0d24d2b16c10e9f70dd" - integrity sha512-z+9SCw0dE+69Z/Hv8809XDbLj7lTfEv9Sgu8eKEIdGntZf4v7ewj5rzN5bZZSz8aCvfK7Y6ovz1PBAu4QzS4IQ== - dependencies: - web3-core "1.2.4" - web3-core-method "1.2.4" - web3-core-subscriptions "1.2.4" - web3-net "1.2.4" - -web3-utils@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-utils/-/web3-utils-1.2.11.tgz#af1942aead3fb166ae851a985bed8ef2c2d95a82" - integrity sha512-3Tq09izhD+ThqHEaWYX4VOT7dNPdZiO+c/1QMA0s5X2lDFKK/xHJb7cyTRRVzN2LvlHbR7baS1tmQhSua51TcQ== - dependencies: - bn.js "^4.11.9" - eth-lib "0.2.8" - ethereum-bloom-filters "^1.0.6" - ethjs-unit "0.1.6" - number-to-bn "1.7.0" - randombytes "^2.1.0" - underscore "1.9.1" - utf8 "3.0.0" - -web3-utils@1.2.4: - version "1.2.4" - resolved "https://registry.yarnpkg.com/web3-utils/-/web3-utils-1.2.4.tgz#96832a39a66b05bf8862a5b0bdad2799d709d951" - integrity sha512-+S86Ip+jqfIPQWvw2N/xBQq5JNqCO0dyvukGdJm8fEWHZbckT4WxSpHbx+9KLEWY4H4x9pUwnoRkK87pYyHfgQ== - dependencies: - bn.js "4.11.8" - eth-lib "0.2.7" - ethereum-bloom-filters "^1.0.6" - ethjs-unit "0.1.6" - number-to-bn "1.7.0" - randombytes "^2.1.0" - underscore "1.9.1" - utf8 "3.0.0" - -web3@1.2.4: - version "1.2.4" - resolved "https://registry.yarnpkg.com/web3/-/web3-1.2.4.tgz#6e7ab799eefc9b4648c2dab63003f704a1d5e7d9" - integrity sha512-xPXGe+w0x0t88Wj+s/dmAdASr3O9wmA9mpZRtixGZxmBexAF0MjfqYM+MS4tVl5s11hMTN3AZb8cDD4VLfC57A== - dependencies: - "@types/node" "^12.6.1" - web3-bzz "1.2.4" - web3-core "1.2.4" - web3-eth "1.2.4" - web3-eth-personal "1.2.4" - web3-net "1.2.4" - web3-shh "1.2.4" - web3-utils "1.2.4" - -web3@^1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3/-/web3-1.2.11.tgz#50f458b2e8b11aa37302071c170ed61cff332975" - integrity sha512-mjQ8HeU41G6hgOYm1pmeH0mRAeNKJGnJEUzDMoerkpw7QUQT4exVREgF1MYPvL/z6vAshOXei25LE/t/Bxl8yQ== - dependencies: - web3-bzz "1.2.11" - web3-core "1.2.11" - web3-eth "1.2.11" - web3-eth-personal "1.2.11" - web3-net "1.2.11" - web3-shh "1.2.11" - web3-utils "1.2.11" - -webidl-conversions@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad" - integrity sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg== - -webpack-bundle-analyzer@^3.8.0: - version "3.8.0" - resolved "https://registry.yarnpkg.com/webpack-bundle-analyzer/-/webpack-bundle-analyzer-3.8.0.tgz#ce6b3f908daf069fd1f7266f692cbb3bded9ba16" - integrity sha512-PODQhAYVEourCcOuU+NiYI7WdR8QyELZGgPvB1y2tjbUpbmcQOt5Q7jEK+ttd5se0KSBKD9SXHCEozS++Wllmw== - dependencies: - acorn "^7.1.1" - acorn-walk "^7.1.1" - bfj "^6.1.1" - chalk "^2.4.1" - commander "^2.18.0" - ejs "^2.6.1" - express "^4.16.3" - filesize "^3.6.1" - gzip-size "^5.0.0" - lodash "^4.17.15" - mkdirp "^0.5.1" - opener "^1.5.1" - ws "^6.0.0" - -webpack-cli@^3.3.12: - version "3.3.12" - resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-3.3.12.tgz#94e9ada081453cd0aa609c99e500012fd3ad2d4a" - integrity sha512-NVWBaz9k839ZH/sinurM+HcDvJOTXwSjYp1ku+5XKeOC03z8v5QitnK/x+lAxGXFyhdayoIf/GOpv85z3/xPag== - dependencies: - chalk "^2.4.2" - cross-spawn "^6.0.5" - enhanced-resolve "^4.1.1" - findup-sync "^3.0.0" - global-modules "^2.0.0" - import-local "^2.0.0" - interpret "^1.4.0" - loader-utils "^1.4.0" - supports-color "^6.1.0" - v8-compile-cache "^2.1.1" - yargs "^13.3.2" - -webpack-sources@^1.4.0, webpack-sources@^1.4.1: - version "1.4.3" - resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-1.4.3.tgz#eedd8ec0b928fbf1cbfe994e22d2d890f330a933" - integrity sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ== - dependencies: - source-list-map "^2.0.0" - source-map "~0.6.1" - -webpack@^4.44.1: - version "4.44.1" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.44.1.tgz#17e69fff9f321b8f117d1fda714edfc0b939cc21" - integrity sha512-4UOGAohv/VGUNQJstzEywwNxqX417FnjZgZJpJQegddzPmTvph37eBIRbRTfdySXzVtJXLJfbMN3mMYhM6GdmQ== - dependencies: - "@webassemblyjs/ast" "1.9.0" - "@webassemblyjs/helper-module-context" "1.9.0" - "@webassemblyjs/wasm-edit" "1.9.0" - "@webassemblyjs/wasm-parser" "1.9.0" - acorn "^6.4.1" - ajv "^6.10.2" - ajv-keywords "^3.4.1" - chrome-trace-event "^1.0.2" - enhanced-resolve "^4.3.0" - eslint-scope "^4.0.3" - json-parse-better-errors "^1.0.2" - loader-runner "^2.4.0" - loader-utils "^1.2.3" - memory-fs "^0.4.1" - micromatch "^3.1.10" - mkdirp "^0.5.3" - neo-async "^2.6.1" - node-libs-browser "^2.2.1" - schema-utils "^1.0.0" - tapable "^1.1.3" - terser-webpack-plugin "^1.4.3" - watchpack "^1.7.4" - webpack-sources "^1.4.1" - -websocket@1.0.29: - version "1.0.29" - resolved "https://registry.yarnpkg.com/websocket/-/websocket-1.0.29.tgz#3f83e49d3279657c58b02a22d90749c806101b98" - integrity sha512-WhU8jKXC8sTh6ocLSqpZRlOKMNYGwUvjA5+XcIgIk/G3JCaDfkZUr0zA19sVSxJ0TEvm0i5IBzr54RZC4vzW7g== - dependencies: - debug "^2.2.0" - gulp "^4.0.2" - nan "^2.11.0" - typedarray-to-buffer "^3.1.5" - yaeti "^0.0.6" - -websocket@^1.0.31: - version "1.0.31" - resolved "https://registry.yarnpkg.com/websocket/-/websocket-1.0.31.tgz#e5d0f16c3340ed87670e489ecae6144c79358730" - integrity sha512-VAouplvGKPiKFDTeCCO65vYHsyay8DqoBSlzIO3fayrfOgU94lQN5a1uWVnFrMLceTJw/+fQXR5PGbUVRaHshQ== - dependencies: - debug "^2.2.0" - es5-ext "^0.10.50" - nan "^2.14.0" - typedarray-to-buffer "^3.1.5" - yaeti "^0.0.6" - -whatwg-encoding@^1.0.1, whatwg-encoding@^1.0.3: - version "1.0.5" - resolved "https://registry.yarnpkg.com/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz#5abacf777c32166a51d085d6b4f3e7d27113ddb0" - integrity sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw== - dependencies: - iconv-lite "0.4.24" - -whatwg-fetch@2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-2.0.4.tgz#dde6a5df315f9d39991aa17621853d720b85566f" - integrity sha512-dcQ1GWpOD/eEQ97k66aiEVpNnapVj90/+R+SXTPYGHpYBBypfKJEQjLrvMZ7YXbKm21gXd4NcuxUTjiv1YtLng== - -whatwg-fetch@>=0.10.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.0.0.tgz#fc804e458cc460009b1a2b966bc8817d2578aefb" - integrity sha512-9GSJUgz1D4MfyKU7KRqwOjXCXTqWdFNvEr7eUBYchQiVc744mqK/MzXPNR2WsPkmkOa4ywfg8C2n8h+13Bey1Q== - -whatwg-mimetype@^2.1.0, whatwg-mimetype@^2.2.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz#3d4b1e0312d2079879f826aff18dbeeca5960fbf" - integrity sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g== - -whatwg-url@^6.4.1: - version "6.5.0" - resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-6.5.0.tgz#f2df02bff176fd65070df74ad5ccbb5a199965a8" - integrity sha512-rhRZRqx/TLJQWUpQ6bmrt2UV4f0HCQ463yQuONJqC6fO2VoEb1pTYddbe59SkYq87aoM5A3bdhMZiUiVws+fzQ== - dependencies: - lodash.sortby "^4.7.0" - tr46 "^1.0.1" - webidl-conversions "^4.0.2" - -whatwg-url@^7.0.0: - version "7.1.0" - resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-7.1.0.tgz#c2c492f1eca612988efd3d2266be1b9fc6170d06" - integrity sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg== - dependencies: - lodash.sortby "^4.7.0" - tr46 "^1.0.1" - webidl-conversions "^4.0.2" - -which-module@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/which-module/-/which-module-1.0.0.tgz#bba63ca861948994ff307736089e3b96026c2a4f" - integrity sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8= - -which-module@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" - integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= - -which-pm-runs@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/which-pm-runs/-/which-pm-runs-1.0.0.tgz#670b3afbc552e0b55df6b7780ca74615f23ad1cb" - integrity sha1-Zws6+8VS4LVd9rd4DKdGFfI60cs= - -which@^1.1.1, which@^1.2.14, which@^1.2.9, which@^1.3.0, which@^1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" - integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== - dependencies: - isexe "^2.0.0" - -wide-align@^1.1.0: - version "1.1.3" - resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" - integrity sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA== - dependencies: - string-width "^1.0.2 || 2" - -word-wrap@~1.2.3: - version "1.2.3" - resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" - integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== - -wordwrap@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" - integrity sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus= - -wordwrap@~0.0.2: - version "0.0.3" - resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107" - integrity sha1-o9XabNXAvAAI03I0u68b7WMFkQc= - -worker-farm@^1.7.0: - version "1.7.0" - resolved "https://registry.yarnpkg.com/worker-farm/-/worker-farm-1.7.0.tgz#26a94c5391bbca926152002f69b84a4bf772e5a8" - integrity sha512-rvw3QTZc8lAxyVrqcSGVm5yP/IJ2UcB3U0graE3LCFoZ0Yn2x4EoVSqJKdB/T5M+FLcRPjz4TDacRf3OCfNUzw== - dependencies: - errno "~0.1.7" - -wrap-ansi@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85" - integrity sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU= - dependencies: - string-width "^1.0.1" - strip-ansi "^3.0.1" - -wrap-ansi@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-5.1.0.tgz#1fd1f67235d5b6d0fee781056001bfb694c03b09" - integrity sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q== - dependencies: - ansi-styles "^3.2.0" - string-width "^3.0.0" - strip-ansi "^5.0.0" - -wrappy@1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" - integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= - -write-file-atomic@2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-2.4.1.tgz#d0b05463c188ae804396fd5ab2a370062af87529" - integrity sha512-TGHFeZEZMnv+gBFRfjAcxL5bPHrsGKtnb4qsFAws7/vlh+QfwAaySIw4AXP9ZskTTh5GWu3FLuJhsWVdiJPGvg== - dependencies: - graceful-fs "^4.1.11" - imurmurhash "^0.1.4" - signal-exit "^3.0.2" - -ws@7.4.6: - version "7.4.6" - resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.6.tgz#5654ca8ecdeee47c33a9a4bf6d28e2be2980377c" - integrity sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A== - -ws@^3.0.0: - version "3.3.3" - resolved "https://registry.yarnpkg.com/ws/-/ws-3.3.3.tgz#f1cf84fe2d5e901ebce94efaece785f187a228f2" - integrity sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA== - dependencies: - async-limiter "~1.0.0" - safe-buffer "~5.1.0" - ultron "~1.1.0" - -ws@^5.1.1, ws@^5.2.0: - version "5.2.2" - resolved "https://registry.yarnpkg.com/ws/-/ws-5.2.2.tgz#dffef14866b8e8dc9133582514d1befaf96e980f" - integrity sha512-jaHFD6PFv6UgoIVda6qZllptQsMlDEJkTQcybzzXDYM1XO9Y8em691FGMPmM46WGyLU4z9KMgQN+qrux/nhlHA== - dependencies: - async-limiter "~1.0.0" - -ws@^6.0.0: - version "6.2.1" - resolved "https://registry.yarnpkg.com/ws/-/ws-6.2.1.tgz#442fdf0a47ed64f59b6a5d8ff130f4748ed524fb" - integrity sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA== - dependencies: - async-limiter "~1.0.0" - -xhr-request-promise@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/xhr-request-promise/-/xhr-request-promise-0.1.2.tgz#343c44d1ee7726b8648069682d0f840c83b4261d" - integrity sha1-NDxE0e53JrhkgGloLQ+EDIO0Jh0= - dependencies: - xhr-request "^1.0.1" - -xhr-request@^1.0.1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/xhr-request/-/xhr-request-1.1.0.tgz#f4a7c1868b9f198723444d82dcae317643f2e2ed" - integrity sha512-Y7qzEaR3FDtL3fP30k9wO/e+FBnBByZeybKOhASsGP30NIkRAAkKD/sCnLvgEfAIEC1rcmK7YG8f4oEnIrrWzA== - dependencies: - buffer-to-arraybuffer "^0.0.5" - object-assign "^4.1.1" - query-string "^5.0.1" - simple-get "^2.7.0" - timed-out "^4.0.1" - url-set-query "^1.0.0" - xhr "^2.0.4" - -xhr2-cookies@1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/xhr2-cookies/-/xhr2-cookies-1.1.0.tgz#7d77449d0999197f155cb73b23df72505ed89d48" - integrity sha1-fXdEnQmZGX8VXLc7I99yUF7YnUg= - dependencies: - cookiejar "^2.1.1" - -xhr@^2.0.4, xhr@^2.2.0, xhr@^2.3.3: - version "2.5.0" - resolved "https://registry.yarnpkg.com/xhr/-/xhr-2.5.0.tgz#bed8d1676d5ca36108667692b74b316c496e49dd" - integrity sha512-4nlO/14t3BNUZRXIXfXe+3N6w3s1KoxcJUUURctd64BLRe67E4gRwp4PjywtDY72fXpZ1y6Ch0VZQRY/gMPzzQ== - dependencies: - global "~4.3.0" - is-function "^1.0.1" - parse-headers "^2.0.0" - xtend "^4.0.0" - -xml-name-validator@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-3.0.0.tgz#6ae73e06de4d8c6e47f9fb181f78d648ad457c6a" - integrity sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw== - -xml@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/xml/-/xml-1.0.1.tgz#78ba72020029c5bc87b8a81a3cfcd74b4a2fc1e5" - integrity sha1-eLpyAgApxbyHuKgaPPzXS0ovweU= - -xmlhttprequest@1.8.0: - version "1.8.0" - resolved "https://registry.yarnpkg.com/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz#67fe075c5c24fef39f9d65f5f7b7fe75171968fc" - integrity sha1-Z/4HXFwk/vOfnWX197f+dRcZaPw= - -xtend@^4.0.0, xtend@^4.0.1, xtend@~4.0.0, xtend@~4.0.1: - version "4.0.2" - resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" - integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== - -xtend@~2.1.1: - version "2.1.2" - resolved "https://registry.yarnpkg.com/xtend/-/xtend-2.1.2.tgz#6efecc2a4dad8e6962c4901b337ce7ba87b5d28b" - integrity sha1-bv7MKk2tjmlixJAbM3znuoe10os= - dependencies: - object-keys "~0.4.0" - -y18n@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.1.tgz#6d15fba884c08679c0d77e88e7759e811e07fa41" - integrity sha1-bRX7qITAhnnA136I53WegR4H+kE= - -y18n@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b" - integrity sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w== - -yaeti@^0.0.6: - version "0.0.6" - resolved "https://registry.yarnpkg.com/yaeti/-/yaeti-0.0.6.tgz#f26f484d72684cf42bedfb76970aa1608fbf9577" - integrity sha1-8m9ITXJoTPQr7ft2lwqhYI+/lXc= - -yallist@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" - integrity sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI= - -yallist@^3.0.0, yallist@^3.0.2, yallist@^3.0.3: - version "3.1.1" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" - integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== - -yargs-parser@10.x: - version "10.1.0" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-10.1.0.tgz#7202265b89f7e9e9f2e5765e0fe735a905edbaa8" - integrity sha512-VCIyR1wJoEBZUqk5PA+oOBF6ypbwh5aNB3I50guxAL/quggdfs4TtNHQrSazFA3fYZ+tEqfs0zIGlv0c/rgjbQ== - dependencies: - camelcase "^4.1.0" - -yargs-parser@^13.1.1: - version "13.1.1" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.1.tgz#d26058532aa06d365fe091f6a1fc06b2f7e5eca0" - integrity sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ== - dependencies: - camelcase "^5.0.0" - decamelize "^1.2.0" - -yargs-parser@^13.1.2: - version "13.1.2" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.2.tgz#130f09702ebaeef2650d54ce6e3e5706f7a4fb38" - integrity sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg== - dependencies: - camelcase "^5.0.0" - decamelize "^1.2.0" - -yargs-parser@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-5.0.0.tgz#275ecf0d7ffe05c77e64e7c86e4cd94bf0e1228a" - integrity sha1-J17PDX/+Bcd+ZOfIbkzZS/DhIoo= - dependencies: - camelcase "^3.0.0" - -yargs-parser@^8.1.0: - version "8.1.0" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-8.1.0.tgz#f1376a33b6629a5d063782944da732631e966950" - integrity sha512-yP+6QqN8BmrgW2ggLtTbdrOyBNSI7zBa4IykmiV5R1wl1JWNxQvWhMfMdmzIYtKU7oP3OOInY/tl2ov3BDjnJQ== - dependencies: - camelcase "^4.1.0" - -yargs@^10.0.3: - version "10.1.2" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-10.1.2.tgz#454d074c2b16a51a43e2fb7807e4f9de69ccb5c5" - integrity sha512-ivSoxqBGYOqQVruxD35+EyCFDYNEFL/Uo6FcOnz+9xZdZzK0Zzw4r4KhbrME1Oo2gOggwJod2MnsdamSG7H9ig== - dependencies: - cliui "^4.0.0" - decamelize "^1.1.1" - find-up "^2.1.0" - get-caller-file "^1.0.1" - os-locale "^2.0.0" - require-directory "^2.1.1" - require-main-filename "^1.0.1" - set-blocking "^2.0.0" - string-width "^2.0.0" - which-module "^2.0.0" - y18n "^3.2.1" - yargs-parser "^8.1.0" - -yargs@^13.2.4, yargs@^13.3.0: - version "13.3.0" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.3.0.tgz#4c657a55e07e5f2cf947f8a366567c04a0dedc83" - integrity sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA== - dependencies: - cliui "^5.0.0" - find-up "^3.0.0" - get-caller-file "^2.0.1" - require-directory "^2.1.1" - require-main-filename "^2.0.0" - set-blocking "^2.0.0" - string-width "^3.0.0" - which-module "^2.0.0" - y18n "^4.0.0" - yargs-parser "^13.1.1" - -yargs@^13.3.2: - version "13.3.2" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.3.2.tgz#ad7ffefec1aa59565ac915f82dccb38a9c31a2dd" - integrity sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw== - dependencies: - cliui "^5.0.0" - find-up "^3.0.0" - get-caller-file "^2.0.1" - require-directory "^2.1.1" - require-main-filename "^2.0.0" - set-blocking "^2.0.0" - string-width "^3.0.0" - which-module "^2.0.0" - y18n "^4.0.0" - yargs-parser "^13.1.2" - -yargs@^7.1.0: - version "7.1.0" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-7.1.0.tgz#6ba318eb16961727f5d284f8ea003e8d6154d0c8" - integrity sha1-a6MY6xaWFyf10oT46gA+jWFU0Mg= - dependencies: - camelcase "^3.0.0" - cliui "^3.2.0" - decamelize "^1.1.1" - get-caller-file "^1.0.1" - os-locale "^1.4.0" - read-pkg-up "^1.0.1" - require-directory "^2.1.1" - require-main-filename "^1.0.1" - set-blocking "^2.0.0" - string-width "^1.0.2" - which-module "^1.0.0" - y18n "^3.2.1" - yargs-parser "^5.0.0" - -yauzl@^2.4.2: - version "2.10.0" - resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9" - integrity sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk= - dependencies: - buffer-crc32 "~0.2.3" - fd-slicer "~1.1.0" diff --git a/spec/scenario/AddReserves.scen b/spec/scenario/AddReserves.scen deleted file mode 100644 index fee870fa0..000000000 --- a/spec/scenario/AddReserves.scen +++ /dev/null @@ -1,138 +0,0 @@ -Test "Add all reserves and verify effects" - NewComptroller - ListedCToken ZRX cZRX initialExchangeRate:1e9 - Comptroller SetMarketSupplyCaps (cZRX) (2e30) - Prep Geoff 50e18 ZRX cZRX - Mint Geoff 50e18 cZRX - Assert Equal (Erc20 cZRX TokenBalance Geoff) (Exactly 500e8) -- 50e18 / 1e9 - Assert Equal (CToken cZRX UnderlyingBalance Geoff) (Exactly 50e18) - Assert Equal (CToken cZRX ExchangeRate) (Exactly 1e9) - -- Get some brah to borrow then repay - BorrowAndRepayWithInterest ZRX cZRX 10e18 5e18 interestRate:0.000001 blocks:500000 reserveRate:0.2 - -- We've accrued .0001% interest for 500000 blocks, or 50% of the principal (10e18), - -- thus, we should have accrued 5e18 of interest for the protocol - -- The reserves should get 20% of this, or 1e18, and the rest - -- is due pro-rata to all suppliers. We just have one, so - -- let's check that account is given correct new balance. - Assert Equal (Erc20 ZRX TokenBalance cZRX) (Exactly 55e18) - Assert Equal (Erc20 ZRX TokenBalance Root) (Exactly 0e18) - Assert Equal (Erc20 cZRX TokenBalance Geoff) (Exactly 500e8) - Assert Equal (CToken cZRX Reserves) (Exactly 1e18) - Assert Equal (CToken cZRX UnderlyingBalance Geoff) (Exactly 54e18) - -- (55.0e18+0.0e18-1.0e18)/500.0e8 - Assert Equal (CToken cZRX ExchangeRate) (Exactly 1.08e9) - -- Now, let's pull out add some our reserves (1e18) - Erc20 ZRX Faucet Root 3e18 - From Root (Erc20 ZRX Approve cZRX 6e18) - AddReserves 1e18 cZRX - Assert Equal (Erc20 ZRX TokenBalance cZRX) (Exactly 56e18) - Assert Equal (Erc20 ZRX TokenBalance Root) (Exactly 2e18) - Assert Equal (Erc20 cZRX TokenBalance Geoff) (Exactly 500e8) - Assert Equal (CToken cZRX Reserves) (Exactly 2e18) - Assert Equal (CToken cZRX UnderlyingBalance Geoff) (Exactly 54e18) - -- (54.0e18+0.0e18-0.0e18)/500.0e8 - -- unchanged - Assert Equal (CToken cZRX ExchangeRate) (Exactly 1.08e9) - -Test "Remove and re add reserves and remove again" - NewComptroller - ListedCToken ZRX cZRX initialExchangeRate:1e9 - Comptroller SetMarketSupplyCaps (cZRX) (2e30) - Prep Geoff 50e18 ZRX cZRX - Mint Geoff 50e18 cZRX - Assert Equal (Erc20 cZRX TokenBalance Geoff) (Exactly 500e8) - Assert Equal (CToken cZRX UnderlyingBalance Geoff) (Exactly 50e18) - Assert Equal (CToken cZRX ExchangeRate) (Exactly 1e9) - -- Get some brah to borrow then repay - BorrowAndRepayWithInterest ZRX cZRX 10e18 5e18 interestRate:0.000001 blocks:500000 reserveRate:0.2 - -- We've accrued .0001% interest for 500000 blocks, or 50% of the principal (10e18), - -- thus, we should have accrued 5e18 of interest for the protocol - -- The reserves should get 20% of this, or 1e18, and the rest - -- is due pro-rata to all suppliers. We just have one, so - -- let's check that account is given correct new balance. - Assert Equal (Erc20 ZRX TokenBalance cZRX) (Exactly 55e18) - Assert Equal (Erc20 ZRX TokenBalance Root) (Exactly 0e18) - Assert Equal (Erc20 cZRX TokenBalance Geoff) (Exactly 500e8) - Assert Equal (CToken cZRX Reserves) (Exactly 1e18) - Assert Equal (CToken cZRX UnderlyingBalance Geoff) (Exactly 54e18) - -- (55.0e18+0.0e18-1.0e18)/500.0e8 - Assert Equal (CToken cZRX ExchangeRate) (Exactly 1.08e9) - -- Now, let's pull out half of reserves (0.5e18) - ReduceReserves 0.5e18 cZRX - Assert Equal (Erc20 ZRX TokenBalance cZRX) (Exactly 54.5e18) - Assert Equal (Erc20 ZRX TokenBalance Root) (Exactly 0.5e18) - Assert Equal (Erc20 cZRX TokenBalance Geoff) (Exactly 500e8) - Assert Equal (CToken cZRX Reserves) (Exactly 0.5e18) - Assert Equal (CToken cZRX UnderlyingBalance Geoff) (Exactly 54e18) - -- (54.5e18+0.5e18-0.0e18)/500.0e8 - Assert Equal (CToken cZRX ExchangeRate) (Exactly 1.08e9) - -- Now, let's put back reserves (1e18) - From Root (Erc20 ZRX Approve cZRX 6e18) - AddReserves 0.5e18 cZRX - Assert Equal (Erc20 ZRX TokenBalance cZRX) (Exactly 55e18) - Assert Equal (Erc20 ZRX TokenBalance Root) (Exactly 0e18) - Assert Equal (Erc20 cZRX TokenBalance Geoff) (Exactly 500e8) - Assert Equal (CToken cZRX Reserves) (Exactly 1e18) - Assert Equal (CToken cZRX UnderlyingBalance Geoff) (Exactly 54e18) - -- (54.5e18+0.5e18-0.0e18)/500.0e8 - Assert Equal (CToken cZRX ExchangeRate) (Exactly 1.08e9) - -Test "add reserves to empty contract" - NewComptroller - ListedCToken ZRX cZRX initialExchangeRate:1e9 - Comptroller SetMarketSupplyCaps (cZRX) (2e30) - Assert Equal (CToken cZRX ExchangeRate) (Exactly 1e9) - Erc20 ZRX Faucet Root 3e18 - From Root (Erc20 ZRX Approve cZRX 6e18) - AddReserves 2e18 cZRX - Assert Equal (Erc20 ZRX TokenBalance cZRX) (Exactly 2e18) - Assert Equal (Erc20 ZRX TokenBalance Root) (Exactly 1e18) - Assert Equal (CToken cZRX Reserves) (Exactly 2e18) - -- unchanged - Assert Equal (CToken cZRX ExchangeRate) (Exactly 1e9) - -Test "add reserves failures" - NewComptroller - ListedCToken ZRX cZRX initialExchangeRate:1e9 - Comptroller SetMarketSupplyCaps (cZRX) (1000000e18) - Assert Equal (CToken cZRX ExchangeRate) (Exactly 1e9) - Assert Equal (CToken cZRX Reserves) (Exactly 0e18) - Erc20 ZRX Faucet Root 2e18 - AllowFailures - AddReserves 2e18 cZRX - Assert Revert "revert Insufficient allowance" - Assert Equal (Erc20 ZRX TokenBalance cZRX) (Exactly 0e18) - Assert Equal (Erc20 ZRX TokenBalance Root) (Exactly 2e18) - Assert Equal (CToken cZRX Reserves) (Exactly 0e18) - -- unchanged - Assert Equal (CToken cZRX ExchangeRate) (Exactly 1e9) - -Test "Add reserves WBTC when paused" - NewComptroller - ListedCToken WBTC cWBTC initialExchangeRate:1e9 tokenType:WBTC - Comptroller SetMarketSupplyCaps (cWBTC) (2e30) - Prep Geoff 50e18 WBTC cWBTC - Mint Geoff 50e18 cWBTC - Assert Equal (Erc20 cWBTC TokenBalance Geoff) (Exactly 500e8) - Assert Equal (CToken cWBTC UnderlyingBalance Geoff) (Exactly 50e18) - Assert Equal (CToken cWBTC ExchangeRate) (Exactly 1e9) - -- Get some brah to borrow then repay - BorrowAndRepayWithInterest WBTC cWBTC 10e18 5e18 interestRate:0.000001 blocks:500000 reserveRate:0.2 - -- We've accrued .0001% interest for 500000 blocks, or 50% of the principal (10e18), - -- thus, we should have accrued 5e18 of interest for the protocol - -- The reserves should get 20% of this, or 1e18, and the rest - -- is due pro-rata to all suppliers. We just have one, so - -- let's check that account is given correct new balance. - Erc20 WBTC Faucet Root 3e18 - Invariant Remains (Erc20 WBTC TokenBalance cWBTC) (Exactly 55e18) - Invariant Remains (Erc20 WBTC TokenBalance Root) (Exactly 3e18) - Invariant Remains (Erc20 cWBTC TokenBalance Geoff) (Exactly 500e8) - Invariant Remains (CToken cWBTC Reserves) (Exactly 1e18) - Invariant Remains (CToken cWBTC UnderlyingBalance Geoff) (Exactly 54e18) - -- (55.0e18+0.0e18-1.0e18)/500.0e8 - Invariant Remains (CToken cWBTC ExchangeRate) (Exactly 1.08e9) - From Root (Erc20 WBTC Approve cWBTC 6e18) - Erc20 WBTC Pause - AllowFailures - AddReserves 1e18 cWBTC - Assert Revert diff --git a/spec/scenario/Borrow.scen b/spec/scenario/Borrow.scen deleted file mode 100644 index d6d18c88d..000000000 --- a/spec/scenario/Borrow.scen +++ /dev/null @@ -1,116 +0,0 @@ - -Test "Borrow some BAT and enters BAT if BAT not entered" - NewComptroller price:1.0 - NewCToken ZRX cZRX - NewCToken BAT cBAT - Comptroller SetMarketSupplyCaps (cZRX) (1000e18) - Comptroller SetMarketSupplyCaps (cZRX) (1000e18) - Give cBAT 10e18 BAT -- Faucet some bat to borrow - Support cZRX collateralFactor:0.5 - Support cBAT collateralFactor:0.5 - Prep Geoff Some ZRX cZRX - Mint Geoff 100e18 cZRX - EnterMarkets Geoff cZRX - Borrow Geoff 1e18 cBAT - Assert Equal (cToken cBAT BorrowBalance Geoff) (Exactly 1e18) - Assert Equal (Erc20 BAT TokenBalance Geoff) (Exactly 1e18) - Assert Equal (Erc20 BAT TokenBalance cBAT) (Exactly 9e18) - Assert Equal (Comptroller MembershipLength Geoff) (Exactly 2) - Assert True (Comptroller CheckMembership Geoff cZRX) - Assert True (Comptroller CheckMembership Geoff cBAT) - --- Now that we revert instead of returning failures, the user does not get marked as entered -Test "Borrow some BAT fails, user not entered" - NewComptroller price:1.0 - NewCToken ZRX cZRX - NewCToken BAT cBAT - Comptroller SetMarketSupplyCaps (cBAT) (1000e18) - Comptroller SetMarketSupplyCaps (cZRX) (1000e18) - Support cZRX collateralFactor:0.5 - Support cBAT collateralFactor:0.5 - Prep Geoff Some ZRX cZRX - Mint Geoff 100e18 cZRX - EnterMarkets Geoff cZRX - Invariant Static (Erc20 BAT TokenBalance Geoff) - Invariant Static (Erc20 BAT TokenBalance cBAT) - AllowFailures - Borrow Geoff 1e18 cBAT - Assert RevertCustomError BorrowCashNotAvailable - Assert Equal (Comptroller MembershipLength Geoff) (Exactly 1) - Assert True (Comptroller CheckMembership Geoff cZRX) - Assert False (Comptroller CheckMembership Geoff cBAT) - -Test "Borrow some BAT fails when no BAT available" - NewComptroller price:1.0 - NewCToken ZRX cZRX - NewCToken BAT cBAT - Comptroller SetMarketSupplyCaps (cBAT) (1000e18) - Comptroller SetMarketSupplyCaps (cZRX) (1000e18) - Support cZRX collateralFactor:0.5 - Support cBAT collateralFactor:0.5 - Prep Geoff Some ZRX cZRX - Mint Geoff 100e18 cZRX - EnterMarkets Geoff cZRX cBAT - Invariant Static (CToken cZRX ExchangeRateStored) - AllowFailures - Borrow Geoff 1e18 cBAT - Assert RevertCustomError BorrowCashNotAvailable - -Test "Borrow fails if market not listed" - NewComptroller price:1.0 - NewCToken ZRX cZRX - NewCToken BAT cBAT - Comptroller SetMarketSupplyCaps (cBAT) (1000e18) - Comptroller SetMarketSupplyCaps (cZRX) (1000e18) - Give cBAT 10e18 BAT -- Faucet some bat to borrow - Support cZRX collateralFactor:0.5 - Prep Geoff Some ZRX cZRX - Mint Geoff 100e18 cZRX - EnterMarkets Geoff cZRX - AllowFailures - Borrow Geoff 1e18 cBAT - Assert RevertCustomError BorrowComptrollerRejection 9 - -Test "Borrow some BAT from Excess Cash" - Invariant Success - NewComptroller price:1.0 - NewCToken ZRX cZRX - NewCToken BAT cBAT - Comptroller SetMarketSupplyCaps (cBAT) (1000e18) - Comptroller SetMarketSupplyCaps (cZRX) (1000e18) - Give cBAT 10e18 BAT -- Faucet some bat to borrow - Support cZRX collateralFactor:0.5 - Support cBAT collateralFactor:0.5 - Prep Geoff Some ZRX cZRX - Mint Geoff 100e18 cZRX - EnterMarkets Geoff cZRX cBAT - Borrow Geoff 1e18 cBAT - Assert Equal (cToken cBAT BorrowBalance Geoff) (Exactly 1e18) - Assert Equal (Erc20 BAT TokenBalance Geoff) (Exactly 1e18) - Assert Equal (Erc20 BAT TokenBalance cBAT) (Exactly 9e18) - -Test "Borrow some BAT reverts if borrow is paused" - NewComptroller price:1.0 - Comptroller SetPauseGuardian Coburn - NewCToken ZRX cZRX - NewCToken BAT cBAT - Comptroller SetMarketSupplyCaps (cBAT) (1000e18) - Comptroller SetMarketSupplyCaps (cZRX) (1000e18) - Give cBAT 10e18 BAT -- Faucet some bat to borrow - Support cZRX collateralFactor:0.5 - Support cBAT collateralFactor:0.5 - Prep Geoff Some ZRX cZRX - Mint Geoff 100e18 cZRX - EnterMarkets Geoff cZRX cBAT - From Coburn (Comptroller SetGuardianMarketPaused cBAT "Borrow" True) - AllowFailures - Borrow Geoff 1e18 cBAT - Assert Revert "revert borrow is paused" - Assert Equal (cToken cBAT BorrowBalance Geoff) 0 - Assert Equal (Erc20 BAT TokenBalance Geoff) 0 - Assert Equal (Erc20 BAT TokenBalance cBAT) (Exactly 10e18) - Comptroller SetGuardianMarketPaused cBAT "Borrow" False - Borrow Geoff 1e18 cBAT - Assert Equal (cToken cBAT BorrowBalance Geoff) (Exactly 1e18) - Assert Equal (Erc20 BAT TokenBalance Geoff) (Exactly 1e18) - Assert Equal (Erc20 BAT TokenBalance cBAT) (Exactly 9e18) diff --git a/spec/scenario/BorrowBalance.scen b/spec/scenario/BorrowBalance.scen deleted file mode 100644 index 530a1b173..000000000 --- a/spec/scenario/BorrowBalance.scen +++ /dev/null @@ -1,88 +0,0 @@ --- Tests for the current borrow balance in a number of scenarios - -Macro NewBorrow borrowAmount borrowRate user=Geoff - NewComptroller price:1.0 -- TODO: This should really be a price for a specific asset - NewCToken ZRX cZRX - NewCToken BAT cBAT borrowRate -- note: cannot use macros with named args right now - Comptroller SetMarketSupplyCaps (vBAT) (1000e18) - Comptroller SetMarketSupplyCaps (vZRX) (1000e18) - Give cBAT 10e18 BAT -- Faucet some bat to borrow - Support cZRX collateralFactor:0.5 - Support cBAT collateralFactor:0.5 - SimpleBorrow user borrowAmount - -Macro SimpleBorrow user borrowAmount - Prep user Some ZRX cZRX - Mint user 100e18 cZRX - EnterMarkets user cZRX cBAT - Borrow user borrowAmount cBAT - -Test "Borrow Balance after 300000 blocks" - NewBorrow borrowAmount:1e18 borrowRate:0.000005 - Assert Equal (cToken cBAT BorrowBalance Geoff) (Exactly 1e18) - Assert Equal (cToken cBAT TotalBorrowsCurrent) (Exactly 1e18) - Assert Equal (Erc20 BAT TokenBalance Geoff) (Exactly 1e18) - Assert Equal (Erc20 BAT TokenBalance cBAT) (Exactly 9e18) - -- Now let's add some blocks and see what happs - FastForward 300000 Blocks -- 1e18 * (1 + 300000 * 0.000005) - Assert Equal (cToken cBAT BorrowBalance Geoff) (Exactly 2.5e18) - Assert Equal (cToken cBAT TotalBorrowsCurrent) (Exactly 2.5e18) - -Test "Borrow Balance after 300000 blocks and then 600000 blocks" - NewBorrow borrowAmount:1e18 borrowRate:0.000005 - Assert Equal (cToken cBAT BorrowBalance Geoff) (Exactly 1e18) - Assert Equal (cToken cBAT TotalBorrowsCurrent) (Exactly 1e18) - Assert Equal (Erc20 BAT TokenBalance Geoff) (Exactly 1e18) - Assert Equal (Erc20 BAT TokenBalance cBAT) (Exactly 9e18) - -- Now let's add some blocks and see what happs - FastForward 300000 Blocks -- 1e18 * (1 + 300000 * 0.000005) - AccrueInterest cBAT - Assert Equal (cToken cBAT BorrowBalance Geoff) (Exactly 2.5e18) - Assert Equal (cToken cBAT TotalBorrowsCurrent) (Exactly 2.5e18) - FastForward 600000 Blocks -- 1e18 * (1 + 300000 * 0.000005) * (1 + 600000 * 0.000005) - Assert Equal (cToken cBAT BorrowBalance Geoff) (Exactly 10e18) - Assert Equal (cToken cBAT TotalBorrowsCurrent) (Exactly 10e18) - -Test "Borrow Balance after accrual then changed interest rate" - NewBorrow borrowAmount:1e18 borrowRate:0.000005 - Assert Equal (cToken cBAT BorrowBalance Geoff) (Exactly 1e18) - Assert Equal (cToken cBAT TotalBorrowsCurrent) (Exactly 1e18) - Assert Equal (Erc20 BAT TokenBalance Geoff) (Exactly 1e18) - Assert Equal (Erc20 BAT TokenBalance cBAT) (Exactly 9e18) - -- Now let's add some blocks and see what happs - FastForward 300000 Blocks -- Current: 1e18 * (1 + 300000 * 0.000005) - -- Note: this should accrue interest - InterestRateModel Deploy Fixed Std 0.000004 - CToken cBAT SetInterestRateModel (InterestRateModel Std Address) - Comptroller SetMarketSupplyCaps (cBAT) (1000e18) - -- Check borrow balance still based on old figure (with previous interest accrual) - Assert Equal (cToken cBAT BorrowBalance Geoff) (Exactly 2.5e18) - Assert Equal (cToken cBAT TotalBorrowsCurrent) (Exactly 2.5e18) - -- Now accrue with new rate - FastForward 800000 Blocks -- 1e18 * (1 + 300000 * 0.000005) * (1 + 800000 * 0.000004) - Assert Equal (cToken cBAT BorrowBalance Geoff) (Exactly 10.5e18) - Assert Equal (cToken cBAT TotalBorrowsCurrent) (Exactly 10.5e18) - -Test "Total Borrow Balance with Two Borrowers" - NewBorrow borrowAmount:1e18 borrowRate:0.000005 user:Geoff - FastForward 300000 Blocks - InterestRateModel Deploy Fixed Std 0.000004 - CToken cBAT SetInterestRateModel (InterestRateModel Std Address) - Comptroller SetMarketSupplyCaps (cBAT) (1000e18) - -- Check borrow balance still based on old figure (with previous interest accrual) - Assert Equal (cToken cBAT BorrowBalance Geoff) (Exactly 2.5e18) - Assert Equal (cToken cBAT TotalBorrowsCurrent) (Exactly 2.5e18) - SimpleBorrow user:Torrey borrowAmount:5e18 - -- Now accrue with new rate - FastForward 800000 Blocks - -- Geoff: 1e18 * (1 + 300000 * 0.000005) * (1 + 800000 * 0.000004) - Assert Equal (cToken cBAT BorrowBalance Geoff) (Exactly 10.5e18) - -- Torrey: 5e18 * (1 + 800000 * 0.000004) - Assert Equal (cToken cBAT BorrowBalance Torrey) (Exactly 21e18) - Assert Equal (cToken cBAT TotalBorrowsCurrent) (Exactly 31.5e18) - -- And test some repayment - From Torrey (Erc20 BAT Approve cBAT 2.0e18) - RepayBorrow Torrey 2.0e18 cBAT - Assert Equal (cToken cBAT BorrowBalance Geoff) (Exactly 10.5e18) - Assert Equal (cToken cBAT BorrowBalance Torrey) (Exactly 19e18) - Assert Equal (cToken cBAT TotalBorrowsCurrent) (Exactly 29.5e18) diff --git a/spec/scenario/BorrowCap.scen b/spec/scenario/BorrowCap.scen deleted file mode 100644 index 4501b7527..000000000 --- a/spec/scenario/BorrowCap.scen +++ /dev/null @@ -1,182 +0,0 @@ - -Test "Attempt to borrow over set cap ERC20" - NewComptroller price:1.0 - NewCToken ZRX cZRX - NewCToken BAT cBAT - Comptroller SetMarketSupplyCaps (vBAT) (1000e18) - Comptroller SetMarketSupplyCaps (vZRX) (1000e18) - Comptroller SetMarketBorrowCaps (cBAT) (0.5e18) - Assert Equal (Comptroller BorrowCaps cBAT) (Exactly 0.5e18) - Give cBAT 10e18 BAT -- Faucet some bat to borrow - Support cZRX collateralFactor:0.5 - Support cBAT collateralFactor:0.5 - Prep Geoff Some ZRX cZRX - Mint Geoff 100e18 cZRX - EnterMarkets Geoff cZRX - AllowFailures - Borrow Geoff 1e18 cBAT - Assert Revert - Assert Equal (cToken cBAT BorrowBalance Geoff) (Exactly 0) - Assert Equal (Erc20 BAT TokenBalance Geoff) (Exactly 0) - Assert Equal (Erc20 BAT TokenBalance cBAT) (Exactly 10e18) - -Test "Attempt to borrow at set cap ERC20" - NewComptroller price:1.0 - NewCToken ZRX cZRX - NewCToken BAT cBAT - Comptroller SetMarketSupplyCaps (cBAT) (1000e18) - Comptroller SetMarketSupplyCaps (cZRX) (1000e18) - Comptroller SetMarketBorrowCaps (cBAT) (1000000000000000001) - Give cBAT 10e18 BAT -- Faucet some bat to borrow - Support cZRX collateralFactor:0.5 - Support cBAT collateralFactor:0.5 - Prep Geoff Some ZRX cZRX - Mint Geoff 100e18 cZRX - EnterMarkets Geoff cZRX - Borrow Geoff 1e18 cBAT - Assert Equal (cToken cBAT BorrowBalance Geoff) (Exactly 1e18) - Assert Equal (Erc20 BAT TokenBalance Geoff) (Exactly 1e18) - Assert Equal (Erc20 BAT TokenBalance cBAT) (Exactly 9e18) - Assert Equal (Comptroller MembershipLength Geoff) (Exactly 2) - Assert True (Comptroller CheckMembership Geoff cZRX) - Assert True (Comptroller CheckMembership Geoff cBAT) - -Test "Attempt to borrow below set cap ERC20" - NewComptroller price:1.0 - NewCToken ZRX cZRX - NewCToken BAT cBAT - Comptroller SetMarketSupplyCaps (cBAT) (1000e18) - Comptroller SetMarketSupplyCaps (cZRX) (1000e18) - Comptroller SetMarketBorrowCaps (cBAT) (10e18) - Give cBAT 10e18 BAT -- Faucet some bat to borrow - Support cZRX collateralFactor:0.5 - Support cBAT collateralFactor:0.5 - Prep Geoff Some ZRX cZRX - Mint Geoff 100e18 cZRX - EnterMarkets Geoff cZRX - Borrow Geoff 1e18 cBAT - Assert Equal (cToken cBAT BorrowBalance Geoff) (Exactly 1e18) - Assert Equal (Erc20 BAT TokenBalance Geoff) (Exactly 1e18) - Assert Equal (Erc20 BAT TokenBalance cBAT) (Exactly 9e18) - Assert Equal (Comptroller MembershipLength Geoff) (Exactly 2) - Assert True (Comptroller CheckMembership Geoff cZRX) - Assert True (Comptroller CheckMembership Geoff cBAT) - -Test "Borrow some Eth over cap" - NewComptroller price:1.0 - ListedCToken ZRX cZRX - ListedEtherToken cETH initialExchangeRate:0.005e9 - SetCollateralFactor cZRX collateralFactor:0.5 - SetCollateralFactor cETH collateralFactor:0.5 - Comptroller SetMarketSupplyCaps (cZRX) (1000e18) - Comptroller SetMarketSupplyCaps (cETH) (0.01e18) - Comptroller SetMarketBorrowCaps (cETH) (0.0001e18) - Donate cETH 0.003e18 - Prep Geoff Some ZRX cZRX - Mint Geoff 1e18 cZRX - EnterMarkets Geoff cZRX - AllowFailures - BorrowEth Geoff 0.001e18 cETH - Assert Revert - Assert Equal (EtherBalance cETH) 0.003e18 - -Test "Borrow some Eth enters Eth and succeeds when Eth not entered. At borrow cap" - NewComptroller price:1.0 - ListedCToken ZRX cZRX - ListedEtherToken cETH initialExchangeRate:0.005e9 - SetCollateralFactor cZRX collateralFactor:0.5 - SetCollateralFactor cETH collateralFactor:0.5 - Comptroller SetMarketBorrowCaps (cETH) (1000000000000001) - Donate cETH 0.003e18 - Prep Geoff Some ZRX cZRX - Mint Geoff 1e18 cZRX - EnterMarkets Geoff cZRX - Expect Changes (EtherBalance Geoff) +0.001e18 - BorrowEth Geoff 0.001e18 cETH - Assert Equal (EtherBalance cETH) 0.002e18 - Assert Equal (Comptroller Liquidity Geoff) 4.99e17 - Assert Equal (Comptroller MembershipLength Geoff) (Exactly 2) - Assert True (Comptroller CheckMembership Geoff cETH) - -Test "Borrow some Eth enters Eth and succeeds when Eth not entered. At under borrow cap" - NewComptroller price:1.0 - ListedCToken ZRX cZRX - ListedEtherToken cETH initialExchangeRate:0.005e9 - SetCollateralFactor cZRX collateralFactor:0.5 - SetCollateralFactor cETH collateralFactor:0.5 - Comptroller SetMarketSupplyCaps (cZRX) (1000e18) - Comptroller SetMarketBorrowCaps (cETH) (0.01e18) - Comptroller SetMarketSupplyCaps (cETH) (1000e18) - Donate cETH 0.003e18 - Prep Geoff Some ZRX cZRX - Mint Geoff 1e18 cZRX - EnterMarkets Geoff cZRX - Expect Changes (EtherBalance Geoff) +0.001e18 - BorrowEth Geoff 0.001e18 cETH - Assert Equal (EtherBalance cETH) 0.002e18 - Assert Equal (Comptroller Liquidity Geoff) 4.99e17 - Assert Equal (Comptroller MembershipLength Geoff) (Exactly 2) - Assert True (Comptroller CheckMembership Geoff cETH) - -Test "Setting borrow cap restricted to admin" - NewComptroller price:1.0 - ListedCToken ZRX cZRX - ListedEtherToken cETH initialExchangeRate:0.005e9 - SetCollateralFactor cZRX collateralFactor:0.5 - SetCollateralFactor cETH collateralFactor:0.5 - AllowFailures - From Robert (Comptroller SetMarketBorrowCaps (cETH) (0.01e18)) - Assert Revert - -Test "Borrow cap guardian can set borrow caps" - NewComptroller price:1.0 - ListedCToken ZRX cZRX - ListedEtherToken cETH initialExchangeRate:0.005e9 - SetCollateralFactor cZRX collateralFactor:0.5 - SetCollateralFactor cETH collateralFactor:0.5 - Comptroller SetBorrowCapGuardian Geoff - From Geoff (Comptroller SetMarketBorrowCaps (cZRX) (0.5e18)) - AllowFailures - From Robert (Comptroller SetMarketBorrowCaps (cZRX) (0.01e18)) -- Robert still can't... - Assert Revert - From Robert (Comptroller SetMarketBorrowCaps (cZRX) (0.01e18)) - Assert Revert - Assert Equal (Comptroller BorrowCaps cZRX) (Exactly 0.5e18) - Assert Equal (Comptroller BorrowCapGuardian) (User Geoff Address) - -Test "Only admin can set Borrow Cap Guardian" - NewComptroller price:1.0 - AllowFailures - From Robert (Comptroller SetBorrowCapGuardian Robert) -- Robert has really gone rogue - Assert Revert - -Test "SetBorrowCaps works correctly too" - NewComptroller price:1.0 - NewCToken ZRX cZRX - NewCToken BAT cBAT - Comptroller SetMarketSupplyCaps (cBAT) (1000e18) - Comptroller SetMarketSupplyCaps (cZRX) (1000e18) - NewCToken USDC cUSDC - Comptroller SetMarketBorrowCaps (cBAT cUSDC) (0.5e18 1000001) - Assert Equal (Comptroller BorrowCaps cBAT) (Exactly 0.5e18) - Assert Equal (Comptroller BorrowCaps cUSDC) (Exactly 1000001) - Give cBAT 10e18 BAT -- Faucet some bat to borrow - Give cUSDC 20e6 USDC - Support cZRX collateralFactor:0.5 - Support cBAT collateralFactor:0.5 - Support cUSDC collateralFactor:0.5 - Prep Geoff Some ZRX cZRX - Mint Geoff 100e18 cZRX - EnterMarkets Geoff cZRX - AllowFailures - Borrow Geoff 1e18 cBAT - Assert Revert - Borrow Geoff 2e6 cUSDC - Assert Revert - Successfully - Borrow Geoff 1e6 cUSDC - Assert Equal (cToken cBAT BorrowBalance Geoff) (Exactly 0) - Assert Equal (Erc20 BAT TokenBalance Geoff) (Exactly 0) - Assert Equal (Erc20 BAT TokenBalance cBAT) (Exactly 10e18) - Assert Equal (Erc20 USDC TokenBalance Geoff) (Exactly 1e6) - diff --git a/spec/scenario/BorrowEth.scen b/spec/scenario/BorrowEth.scen deleted file mode 100644 index 64a36663b..000000000 --- a/spec/scenario/BorrowEth.scen +++ /dev/null @@ -1,52 +0,0 @@ - -Test "Borrow some Eth enters Eth and succeeds when Eth not entered" - NewComptroller price:1.0 - ListedCToken ZRX cZRX - Comptroller SetMarketSupplyCaps (cZRX) (1000e18) - ListedEtherToken cETH initialExchangeRate:0.005e9 - SetCollateralFactor cZRX collateralFactor:0.5 - SetCollateralFactor cETH collateralFactor:0.5 - Donate cETH 0.003e18 - Prep Geoff Some ZRX cZRX - Mint Geoff 1e18 cZRX - EnterMarkets Geoff cZRX - Expect Changes (EtherBalance Geoff) +0.001e18 - BorrowEth Geoff 0.001e18 cETH - Assert Equal (EtherBalance cETH) 0.002e18 - Assert Equal (Comptroller Liquidity Geoff) 4.99e17 - Assert Equal (Comptroller MembershipLength Geoff) (Exactly 2) - Assert True (Comptroller CheckMembership Geoff cETH) - -Test "Borrow some ETH fails when no ETH available" - NewComptroller price:1.0 - ListedCToken ZRX cZRX - Comptroller SetMarketSupplyCaps (cZRX) (1000e18) - ListedEtherToken cETH initialExchangeRate:0.005e9 - SetCollateralFactor cZRX collateralFactor:0.5 - SetCollateralFactor cETH collateralFactor:0.5 - Prep Geoff Some ZRX cZRX - Mint Geoff 100e18 cZRX - EnterMarkets Geoff cZRX cETH - AllowFailures - Invariant Static (CToken cZRX ExchangeRateStored) - Invariant Static (CToken cETH ExchangeRateStored) - Invariant Static (Comptroller Liquidity Geoff) - Invariant Static (EtherBalance Geoff) - BorrowEth Geoff 1e18 cETH - Assert RevertCustomError BorrowCashNotAvailable - -Test "Borrow some ETH from excess cash" - NewComptroller price:1.0 - ListedCToken ZRX cZRX - Comptroller SetMarketSupplyCaps (cZRX) (1000e18) - ListedEtherToken cETH initialExchangeRate:0.005e9 - SetCollateralFactor cZRX collateralFactor:0.5 - SetCollateralFactor cETH collateralFactor:0.5 - Donate cETH 0.003e18 - Prep Geoff Some ZRX cZRX - Mint Geoff 1e18 cZRX - EnterMarkets Geoff cZRX cETH - Expect Changes (EtherBalance Geoff) +0.001e18 - BorrowEth Geoff 0.001e18 cETH - Assert Equal (EtherBalance cETH) 0.002e18 - Assert Equal (Comptroller Liquidity Geoff) 4.99e17 diff --git a/spec/scenario/BorrowWBTC.scen b/spec/scenario/BorrowWBTC.scen deleted file mode 100644 index 8a67c9914..000000000 --- a/spec/scenario/BorrowWBTC.scen +++ /dev/null @@ -1,71 +0,0 @@ - -Test "Borrow some WBTC enters WBTC and succeeds when not entered" - Invariant Success - NewComptroller price:1.0 - NewCToken ZRX cZRX - NewCToken WBTC cWBTC tokenType:WBTC - Comptroller SetMarketSupplyCaps (cWBTC) (1000e18) - Comptroller SetMarketSupplyCaps (cZRX) (1000e18) - Give cWBTC 10e8 WBTC -- Faucet some WBTC to borrow - Support cZRX collateralFactor:0.5 - Support cWBTC collateralFactor:0.5 - Prep Geoff Some ZRX cZRX - Mint Geoff 100e18 cZRX - EnterMarkets Geoff cZRX - Borrow Geoff 1e8 cWBTC - Assert Equal (cToken cWBTC BorrowBalance Geoff) (Exactly 1e8) - Assert Equal (Erc20 WBTC TokenBalance Geoff) (Exactly 1e8) - Assert Equal (Erc20 WBTC TokenBalance cWBTC) (Exactly 9e8) - -Test "Borrow some WBTC fails when no WBTC available" - NewComptroller price:1.0 - NewCToken ZRX cZRX - NewCToken WBTC cWBTC tokenType:WBTC - Comptroller SetMarketSupplyCaps (cZRX) (1000e18) - Comptroller SetMarketSupplyCaps (cWBTC) (1000e18) - Support cZRX collateralFactor:0.5 - Support cWBTC collateralFactor:0.5 - Prep Geoff Some ZRX cZRX - Mint Geoff 100e18 cZRX - EnterMarkets Geoff cZRX cWBTC - Invariant Static (CToken cZRX ExchangeRateStored) - AllowFailures - Borrow Geoff 1e8 cWBTC - Assert RevertCustomError BorrowCashNotAvailable - -Test "Borrow some WBTC fails when WBTC paused" - NewComptroller price:1.0 - NewCToken ZRX cZRX - NewCToken WBTC cWBTC tokenType:WBTC - Comptroller SetMarketSupplyCaps (vWBTC) (1000e18) - Comptroller SetMarketSupplyCaps (vZRX) (1000e18) - Give cWBTC 10e8 WBTC -- Faucet some WBTC to borrow - Support cZRX collateralFactor:0.5 - Support cWBTC collateralFactor:0.5 - Prep Geoff Some ZRX cZRX - Mint Geoff 100e18 cZRX - EnterMarkets Geoff cZRX cWBTC - Invariant Static (CToken cZRX ExchangeRateStored) - Erc20 WBTC Pause - AllowFailures - Borrow Geoff 1e8 cWBTC - Assert Revert - -Test "Borrow some WBTC from Excess Cash" - Invariant Success - NewComptroller price:1.0 - NewCToken ZRX cZRX - NewCToken WBTC cWBTC tokenType:WBTC - Comptroller SetMarketSupplyCaps (vWBTC) (1000e18) - Comptroller SetMarketSupplyCaps (vZRX) (1000e18) - Give cWBTC 10e8 WBTC -- Faucet some WBTC to borrow - Support cZRX collateralFactor:0.5 - Support cWBTC collateralFactor:0.5 - Prep Geoff Some ZRX cZRX - Mint Geoff 100e18 cZRX - EnterMarkets Geoff cZRX cWBTC - Borrow Geoff 1e8 cWBTC - EnterMarkets Geoff cZRX cWBTC - Assert Equal (cToken cWBTC BorrowBalance Geoff) (Exactly 1e8) - Assert Equal (Erc20 WBTC TokenBalance Geoff) (Exactly 1e8) - Assert Equal (Erc20 WBTC TokenBalance cWBTC) (Exactly 9e8) diff --git a/spec/scenario/BreakLiquidate.scen b/spec/scenario/BreakLiquidate.scen deleted file mode 100644 index 75d2ed3f8..000000000 --- a/spec/scenario/BreakLiquidate.scen +++ /dev/null @@ -1,84 +0,0 @@ - -Macro NewBorrow borrowAmount mintAmount borrowRate=0.000005 user=Geoff collateralPrice=1.0 borrowPrice=1.0 liquidationIncentive=1.1 - PricedComptroller closeFactor:0.9 -- Set the close factor high to reduce number of steps to demonstrate - Comptroller LiquidationIncentive liquidationIncentive - NewCToken ZRX cZRX - NewCToken BAT cBAT borrowRate - Comptroller SetMarketSupplyCaps (cBAT) (1000e18) - Comptroller SetMarketSupplyCaps (cZRX) (1000e18) - Give cBAT 10e18 BAT -- Faucet some bat to borrow - PriceOracle SetPrice cZRX collateralPrice - Support cZRX collateralFactor:0.7 - PriceOracle SetPrice cBAT borrowPrice - Support cBAT collateralFactor:0 - SimpleBorrow user borrowAmount mintAmount - -Macro SimpleBorrow user borrowAmount mintAmount - Prep user mintAmount ZRX cZRX - Mint user mintAmount cZRX - EnterMarkets user cZRX cBAT - Borrow user borrowAmount cBAT - -Test "When account goes further underwater than the liquidation incentive and cannot pay down debt fully" - -- Happens whenever collateral ratio > liquidation discount (i.e. 1 / liquidation incentive) - -- - -- Start right around the liquidity threshold - NewBorrow borrowAmount:1e18 mintAmount:1.43e18 liquidationIncentive:1.1 - -- - -- Verify that the borrow results in the correct state - Assert Equal (CToken cBAT BorrowBalance Geoff) 1e18 - Assert Equal (CToken cZRX UnderlyingBalance Geoff) 1.43e18 - -- - -- Put the account underwater s.t. 0.91 < Borrow/Supply - -- i.e. (1 / liquidationIncentive) < Borrow/Supply - PriceOracle SetPrice cZRX 0.76 - -- - -- Pay back a bunch of debt by liquidating - Prep Jared 10e18 BAT cBAT - Liquidate Jared "->" Geoff 0.9e18 cBAT "Seizing" cZRX - Assert Equal (CToken cBAT BorrowBalance Geoff) 0.1e18 - Assert Equal (CToken cZRX UnderlyingBalance Geoff) 0.127368422e18 - -- Do it again, and note that the collateral is gone but borrows remain - -- if we had set the close factor lower, it would just take more steps - Liquidate Jared "->" Geoff 0.0880000008e18 cBAT "Seizing" cZRX - Assert Equal (CToken cBAT BorrowBalance Geoff) 0.0119999992e18 - Assert Equal (CToken cZRX UnderlyingBalance Geoff) 0 - -Test "When liquidation incentive is too high to be effective" - -- Happens whenever liquidation discount < collateral factor - -- - -- Start right around the liquidity threshold - NewBorrow borrowAmount:1e18 mintAmount:1.43e18 liquidationIncentive:1.5 - -- - -- Verify that the borrow results in the correct state - Assert Equal (CToken cBAT BorrowBalance Geoff) 1e18 - Assert Equal (CToken cZRX UnderlyingBalance Geoff) 1.43e18 - -- - -- Put the account underwater s.t. 0.7 < Borrow/Supply - -- i.e. collateral factor < Borrow/Supply - PriceOracle SetPrice cZRX 0.87 - -- - -- Now any amount of debt that we pay back by liquidating will make liquidity worse - -- - -- First, prepare to liquidate - Prep Jared 10e18 BAT cBAT - Expect Changes (Comptroller Liquidity Geoff) -0.024999999076e18 - -- Note that the account collateral ratio will become worse than before - -- although shortfall decreases in absolute terms - -- had Supply/Borrow = 1.430000000 * 0.87 / 1.0 = 1.244100000 - -- now Supply/Borrow = 0.567931036 * 0.87 / 0.5 = 1.135862072 - -- - -- Now perform the liquidation - Liquidate Jared "->" Geoff 0.5e18 cBAT "Seizing" cZRX - -- - -- Verify that the liquidation went through - Assert Equal (CToken cBAT BorrowBalance Geoff) 0.5e18 - Assert Equal (CToken cZRX UnderlyingBalance Geoff) 0.567931036e18 - -- - -- Test succeeded which means our expectation was correct - -- liquidity went down after a liquidation! - -- - -- Now lets see that lowering the incentive and liquidating improves the situation - Comptroller LiquidationIncentive 1.2 - Expect Changes (Comptroller Liquidity Geoff) 0.016000000294e18 - Liquidate Jared "->" Geoff 0.1e18 cBAT "Seizing" cZRX diff --git a/spec/scenario/CTokenAdmin.scen b/spec/scenario/CTokenAdmin.scen deleted file mode 100644 index 807725a97..000000000 --- a/spec/scenario/CTokenAdmin.scen +++ /dev/null @@ -1,43 +0,0 @@ - -Test "Set admin" - NewComptroller - NewCToken ZRX cZRX - Assert Equal (CToken cZRX Admin) (Address Root) - Assert Equal (CToken cZRX PendingAdmin) (Address Zero) - From Root (CToken cZRX SetPendingAdmin Geoff) - Assert Equal (CToken cZRX Admin) (Address Root) - Assert Equal (CToken cZRX PendingAdmin) (Address Geoff) - From Geoff (CToken cZRX AcceptAdmin) - Assert Equal (CToken cZRX Admin) (Address Geoff) - Assert Equal (CToken cZRX PendingAdmin) (Address Zero) - -Test "Set admin to contructor argument" - NewComptroller - NewCToken ZRX cZRX admin:Torrey - Assert Equal (CToken cZRX Admin) (Address Torrey) - Assert Equal (CToken cZRX PendingAdmin) (Address Zero) - From Torrey (CToken cZRX SetPendingAdmin Geoff) - Assert Equal (CToken cZRX Admin) (Address Torrey) - Assert Equal (CToken cZRX PendingAdmin) (Address Geoff) - From Geoff (CToken cZRX AcceptAdmin) - Assert Equal (CToken cZRX Admin) (Address Geoff) - Assert Equal (CToken cZRX PendingAdmin) (Address Zero) - - -Test "Fail to set pending admin" - NewComptroller - NewCToken ZRX cZRX - Invariant Remains (CToken cZRX Admin) (Address Root) - Invariant Remains (CToken cZRX PendingAdmin) (Address Zero) - AllowFailures - From Geoff (CToken cZRX SetPendingAdmin Geoff) - Assert RevertCustomError SetPendingAdminOwnerCheck - -Test "Fail to accept admin" - NewComptroller - NewCToken ZRX cZRX - Invariant Remains (CToken cZRX Admin) (Address Root) - Invariant Remains (CToken cZRX PendingAdmin) (Address Zero) - AllowFailures - From Geoff (CToken cZRX AcceptAdmin) - Assert RevertCustomError AcceptAdminPendingAdminCheck diff --git a/spec/scenario/ChangeDelegate.scen b/spec/scenario/ChangeDelegate.scen deleted file mode 100644 index 0921de4e2..000000000 --- a/spec/scenario/ChangeDelegate.scen +++ /dev/null @@ -1,12 +0,0 @@ --- Delegate upgrade tests - -Test "Change the delegate" - NewComptroller - NewCToken DEL cDEL - Comptroller SetMarketSupplyCaps (cDEL) (1000e18) - Support cDEL collateralFactor:0.5 - Prep Jared Some DEL cDEL - Mint Jared 100e18 cDEL - CTokenDelegate Deploy CErc20Delegate cErc20Delegate2 - CToken cDEL SetImplementation (CTokenDelegate cErc20Delegate2 Address) True "0x0" - Redeem Jared 50e9 cDEL diff --git a/spec/scenario/Comp/Comp.scen b/spec/scenario/Comp/Comp.scen deleted file mode 100644 index db51ee9f1..000000000 --- a/spec/scenario/Comp/Comp.scen +++ /dev/null @@ -1,300 +0,0 @@ - -Test "Check Name" - Comp Deploy Geoff - Assert Equal (Comp Name) "Compound" - -Test "Check Symbol" - Comp Deploy Geoff - Assert Equal (Comp Symbol) "COMP" - -Test "Check Decimals" - Comp Deploy Geoff - Assert Equal (Comp Decimals) 18 - -Test "Check Total Supply" - Comp Deploy Geoff - Assert Equal (Comp TotalSupply) 10000000e18 - -Test "Check account receives Total Supply after deploy and emits Transfer event" - Comp Deploy Geoff - Assert Equal (Comp TokenBalance Geoff) 10000000e18 - Assert Log Transfer (from (Address Zero)) (to (Address Geoff)) (amount "10000000000000000000000000") - -Test "Check approve sets correct approval and emits Approval event" - Comp Deploy Geoff - From Geoff (Comp Approve Jared 10) - Assert Equal (Comp Allowance Geoff Jared) 10 - Assert Log Approval (owner (Address Geoff)) (spender (Address Jared)) (amount "10") - -Test "Check approve with bad allowance reverts" - Comp Deploy Geoff - AllowFailures - From Geoff (Comp Approve Jared 1e70) - Assert Revert "revert Comp::approve: amount exceeds 96 bits" - -Test "Check transfer updates balances correctly, emits Transfer event, and returns true" - Comp Deploy Geoff - From Geoff (Comp Transfer Jared 10) - Assert Equal (Comp TokenBalance Geoff) 9999999999999999999999990 - Assert Equal (Comp TokenBalance Jared) 10 - Assert Log Transfer (from (Address Geoff)) (to (Address Jared)) (amount "10") - -Test "Check self-transfer updates balances correctly, emits Transfer event, and returns true" - Comp Deploy Geoff - Expect Changes (Comp VotesLength Geoff) Zero - Expect Changes (Comp TokenBalance Geoff) Zero - From Geoff (Comp Transfer Geoff 10) - Assert Log Transfer (from (Address Geoff)) (to (Address Geoff)) (amount "10") - Expect Changes (Comp VotesLength Geoff) Zero - Expect Changes (Comp TokenBalance Geoff) Zero - From Geoff (Comp Transfer Geoff 0) - Assert Log Transfer (from (Address Geoff)) (to (Address Geoff)) (amount "0") - -Test "Check transferFrom with unlimited allowance updates balances correctly, emits Transfer event, and returns true" - Comp Deploy Geoff - From Geoff (Comp Approve Jared UInt256Max) - From Jared (Comp TransferFrom Geoff Jared 10) - Assert Equal (Comp TokenBalance Geoff) 9999999999999999999999990 - Assert Equal (Comp TokenBalance Jared) 10 - Assert Equal (Comp Allowance Geoff Jared) UInt96Max - Assert Log Transfer (from (Address Geoff)) (to (Address Jared)) (amount "10") - -Test "Check transferFrom with unlimited allowance updates balances correctly, emits Transfer event, and returns true" - Comp Deploy Geoff - From Geoff (Comp Approve Jared UInt96Max) - From Jared (Comp TransferFrom Geoff Jared 10) - Assert Equal (Comp TokenBalance Geoff) 9999999999999999999999990 - Assert Equal (Comp TokenBalance Jared) 10 - Assert Equal (Comp Allowance Geoff Jared) UInt96Max - Assert Log Transfer (from (Address Geoff)) (to (Address Jared)) (amount "10") - -Test "Check transferFrom with allowance updates balances correctly, emits Transfer event, and returns true" - Comp Deploy Geoff - From Geoff (Comp Approve Jared 10) - From Jared (Comp TransferFrom Geoff Jared 9) - Assert Equal (Comp TokenBalance Geoff) 9999999999999999999999991 - Assert Equal (Comp TokenBalance Jared) 9 - Assert Equal (Comp Allowance Geoff Jared) 1 - Assert Log Transfer (from (Address Geoff)) (to (Address Jared)) (amount "9") - Assert Log Approval (owner (Address Geoff)) (spender (Address Jared)) (amount "1") - -Test "Check transferFrom reverts with not sufficient allowance" - Comp Deploy Geoff - From Geoff (Comp Approve Jared 10) - AllowFailures - From Jared (Comp TransferFrom Geoff Jared 11) - Assert Revert "revert Comp::transferFrom: transfer amount exceeds spender allowance" - -Test "Check transfer reverts when transferring too much" - Comp Deploy Geoff - AllowFailures - From Geoff (Comp Transfer Jared 10000001e18) - Assert Revert "revert Comp::_transferTokens: transfer amount exceeds balance" - -Test "Check transfer reverts when transferring to address 0" - Comp Deploy Geoff - AllowFailures - From Geoff (Comp Transfer (Address Zero) 10000000e18) - Assert Revert "revert Comp::_transferTokens: cannot transfer to the zero address" - -Test "Delegate with zero balance doesn't change votes checkpoints" - Comp Deploy Geoff - Assert Equal (Comp VotesLength Geoff) 0 - From Jared (Comp Delegate Geoff) - Assert Equal (Comp VotesLength Geoff) 0 - Assert Log DelegateChanged (delegator (Address Jared)) (fromDelegate (Address Zero)) (toDelegate (Address Geoff)) - -Test "Delegate from address(0) to account with zero checkpoints" - Comp Deploy Geoff - From Geoff (Comp Transfer Jared 10) - Assert Equal (Comp VotesLength Geoff) 0 - From Jared (Comp Delegate Geoff) - Assert Equal (Comp VotesLength Geoff) 1 - Assert Equal (Comp GetCurrentVotes Geoff) 10 - Assert Equal (Comp GetCurrentVotesBlock Geoff) LastBlock - Assert Equal (Comp VotesLength Zero) 0 - Assert Log DelegateChanged (delegator (Address Jared)) (fromDelegate (Address Zero)) (toDelegate (Address Geoff)) - Assert Log DelegateVotesChanged (delegate (Address Geoff)) (previousBalance "0") (newBalance "10") - -Test "Delegate from address(0) to account with existing checkpoints" - Comp Deploy Geoff - From Geoff (Comp Transfer Jared 10) - From Geoff (Comp Transfer Torrey 14) - Assert Equal (Comp VotesLength Geoff) 0 - From Jared (Comp Delegate Geoff) - Assert Equal (Comp VotesLength Geoff) 1 - Assert Equal (Comp GetCurrentVotes Geoff) 10 - Assert Equal (Comp GetCurrentVotesBlock Geoff) LastBlock - Assert Log DelegateChanged (delegator (Address Jared)) (fromDelegate (Address Zero)) (toDelegate (Address Geoff)) - Assert Log DelegateVotesChanged (delegate (Address Geoff)) (previousBalance "0") (newBalance "10") - From Torrey (Comp Delegate Geoff) - Assert Equal (Comp VotesLength Geoff) 2 - Assert Equal (Comp GetCurrentVotes Geoff) 24 - Assert Equal (Comp GetCurrentVotesBlock Geoff) LastBlock - Assert Equal (Comp VotesLength Zero) 0 - Assert Log DelegateChanged (delegator (Address Torrey)) (fromDelegate (Address Zero)) (toDelegate (Address Geoff)) - Assert Log DelegateVotesChanged (delegate (Address Geoff)) (previousBalance "10") (newBalance "24") - -Test "Delegate to address(0)" - Comp Deploy Geoff - From Geoff (Comp Transfer Jared 10) - From Geoff (Comp Transfer Torrey 14) - Assert Equal (Comp VotesLength Geoff) 0 - From Jared (Comp Delegate Geoff) - Assert Equal (Comp VotesLength Geoff) 1 - Assert Equal (Comp GetCurrentVotes Geoff) 10 - Assert Equal (Comp GetCurrentVotesBlock Geoff) LastBlock - Assert Log DelegateChanged (delegator (Address Jared)) (fromDelegate (Address Zero)) (toDelegate (Address Geoff)) - Assert Log DelegateVotesChanged (delegate (Address Geoff)) (previousBalance "0") (newBalance "10") - From Torrey (Comp Delegate Geoff) - Assert Equal (Comp VotesLength Geoff) 2 - Assert Equal (Comp GetCurrentVotes Geoff) 24 - Assert Equal (Comp GetCurrentVotesBlock Geoff) LastBlock - Assert Log DelegateChanged (delegator (Address Torrey)) (fromDelegate (Address Zero)) (toDelegate (Address Geoff)) - Assert Log DelegateVotesChanged (delegate (Address Geoff)) (previousBalance "10") (newBalance "24") - From Torrey (Comp Delegate Zero) - Assert Equal (Comp VotesLength Geoff) 3 - Assert Equal (Comp GetCurrentVotes Geoff) 10 - Assert Equal (Comp GetCurrentVotesBlock Geoff) LastBlock - Assert Log DelegateChanged (delegator (Address Torrey)) (fromDelegate (Address Geoff)) (toDelegate (Address Zero)) - Assert Log DelegateVotesChanged (delegate (Address Geoff)) (previousBalance "24") (newBalance "10") - Assert Equal (Comp VotesLength Zero) 0 - -Test "Delegate from one account to another account with zero checkpoints" - Comp Deploy Geoff - From Geoff (Comp Transfer Jared 10) - From Geoff (Comp Transfer Torrey 14) - Assert Equal (Comp VotesLength Geoff) 0 - From Jared (Comp Delegate Geoff) - Assert Equal (Comp VotesLength Geoff) 1 - Assert Equal (Comp GetCurrentVotes Geoff) 10 - Assert Equal (Comp GetCurrentVotesBlock Geoff) LastBlock - Assert Log DelegateChanged (delegator (Address Jared)) (fromDelegate (Address Zero)) (toDelegate (Address Geoff)) - Assert Log DelegateVotesChanged (delegate (Address Geoff)) (previousBalance "0") (newBalance "10") - From Torrey (Comp Delegate Geoff) - Assert Equal (Comp VotesLength Geoff) 2 - Assert Equal (Comp GetCurrentVotes Geoff) 24 - Assert Equal (Comp GetCurrentVotesBlock Geoff) LastBlock - Assert Equal (Comp VotesLength Coburn) 0 - Assert Log DelegateChanged (delegator (Address Torrey)) (fromDelegate (Address Zero)) (toDelegate (Address Geoff)) - Assert Log DelegateVotesChanged (delegate (Address Geoff)) (previousBalance "10") (newBalance "24") - From Torrey (Comp Delegate Coburn) - Assert Equal (Comp VotesLength Coburn) 1 - Assert Equal (Comp GetCurrentVotes Coburn) 14 - Assert Equal (Comp GetCurrentVotesBlock Coburn) LastBlock - Assert Equal (Comp VotesLength Geoff) 3 - Assert Equal (Comp GetCurrentVotes Geoff) 10 - Assert Equal (Comp GetCurrentVotesBlock Geoff) LastBlock - Assert Log DelegateChanged (delegator (Address Torrey)) (fromDelegate (Address Geoff)) (toDelegate (Address Coburn)) - Assert Log DelegateVotesChanged (delegate (Address Geoff)) (previousBalance "24") (newBalance "10") - Assert Log DelegateVotesChanged (delegate (Address Coburn)) (previousBalance "0") (newBalance "14") - -Test "Delegate from one account to another account with multiple checkpoints" - Comp Deploy Geoff - From Geoff (Comp Transfer Jared 10) - From Geoff (Comp Transfer Torrey 14) - From Geoff (Comp Transfer Coburn 2) - Assert Equal (Comp VotesLength Geoff) 0 - From Jared (Comp Delegate Geoff) - Assert Equal (Comp VotesLength Geoff) 1 - Assert Equal (Comp GetCurrentVotes Geoff) 10 - Assert Equal (Comp GetCurrentVotesBlock Geoff) LastBlock - Assert Log DelegateChanged (delegator (Address Jared)) (fromDelegate (Address Zero)) (toDelegate (Address Geoff)) - Assert Log DelegateVotesChanged (delegate (Address Geoff)) (previousBalance "0") (newBalance "10") - From Torrey (Comp Delegate Geoff) - Assert Equal (Comp VotesLength Geoff) 2 - Assert Equal (Comp GetCurrentVotes Geoff) 24 - Assert Equal (Comp GetCurrentVotesBlock Geoff) LastBlock - Assert Equal (Comp VotesLength Coburn) 0 - Assert Log DelegateChanged (delegator (Address Torrey)) (fromDelegate (Address Zero)) (toDelegate (Address Geoff)) - Assert Log DelegateVotesChanged (delegate (Address Geoff)) (previousBalance "10") (newBalance "24") - From Coburn (Comp Delegate Coburn) - Assert Equal (Comp VotesLength Coburn) 1 - Assert Equal (Comp GetCurrentVotes Coburn) 2 - Assert Equal (Comp GetCurrentVotesBlock Coburn) LastBlock - Assert Log DelegateChanged (delegator (Address Coburn)) (fromDelegate (Address Zero)) (toDelegate (Address Coburn)) - Assert Log DelegateVotesChanged (delegate (Address Coburn)) (previousBalance "0") (newBalance "2") - From Torrey (Comp Delegate Coburn) - Assert Equal (Comp VotesLength Coburn) 2 - Assert Equal (Comp GetCurrentVotes Coburn) 16 - Assert Equal (Comp GetCurrentVotesBlock Coburn) LastBlock - Assert Equal (Comp VotesLength Geoff) 3 - Assert Equal (Comp GetCurrentVotes Geoff) 10 - Assert Equal (Comp GetCurrentVotesBlock Geoff) LastBlock - Assert Log DelegateChanged (delegator (Address Torrey)) (fromDelegate (Address Geoff)) (toDelegate (Address Coburn)) - Assert Log DelegateVotesChanged (delegate (Address Geoff)) (previousBalance "24") (newBalance "10") - Assert Log DelegateVotesChanged (delegate (Address Coburn)) (previousBalance "2") (newBalance "16") - -Test "Vote checkpoints don't change on transfer when to and from accounts delegate to same account" - Comp Deploy Geoff - From Geoff (Comp Transfer Jared 10) - From Geoff (Comp Transfer Torrey 14) - Assert Equal (Comp VotesLength Geoff) 0 - From Jared (Comp Delegate Geoff) - Assert Equal (Comp VotesLength Geoff) 1 - Assert Equal (Comp GetCurrentVotes Geoff) 10 - Assert Equal (Comp GetCurrentVotesBlock Geoff) LastBlock - Assert Log DelegateChanged (delegator (Address Jared)) (fromDelegate (Address Zero)) (toDelegate (Address Geoff)) - Assert Log DelegateVotesChanged (delegate (Address Geoff)) (previousBalance "0") (newBalance "10") - From Torrey (Comp Delegate Geoff) - Assert Equal (Comp VotesLength Geoff) 2 - Assert Equal (Comp GetCurrentVotes Geoff) 24 - Assert Equal (Comp GetCurrentVotesBlock Geoff) LastBlock - Assert Log DelegateChanged (delegator (Address Torrey)) (fromDelegate (Address Zero)) (toDelegate (Address Geoff)) - Assert Log DelegateVotesChanged (delegate (Address Geoff)) (previousBalance "10") (newBalance "24") - Invariant Static (Comp VotesLength Geoff) - Invariant Static (Comp GetCurrentVotes Geoff) - Invariant Static (Comp GetCurrentVotesBlock Geoff) - From Torrey (Comp Transfer Jared 14) - -Test "Only one checkpoint is added per block for multiple increased balance updates" - Comp Deploy Scenario Geoff - Assert Equal (Comp VotesLength Geoff) 0 - Assert Equal (Comp GetCurrentVotes Geoff) 0 - From Jared (Comp Delegate Geoff) - Assert Log DelegateChanged (delegator (Address Jared)) (fromDelegate (Address Zero)) (toDelegate (Address Geoff)) - From Torrey (Comp Delegate Geoff) - Assert Log DelegateChanged (delegator (Address Torrey)) (fromDelegate (Address Zero)) (toDelegate (Address Geoff)) - From Geoff (Comp TransferScenario (Jared Torrey) 10) - Assert Equal (Comp VotesLength Geoff) 1 - Assert Equal (Comp GetCurrentVotes Geoff) 20 - Assert Equal (Comp GetCurrentVotesBlock Geoff) LastBlock - Assert Equal (Comp VotesLength Zero) 0 - Assert Log DelegateVotesChanged (delegate (Address Geoff)) (previousBalance "0") (newBalance "10") - Assert Log DelegateVotesChanged (delegate (Address Geoff)) (previousBalance "10") (newBalance "20") - -Test "Only one checkpoint is added per block for multiple decreased balance updates" - Comp Deploy Scenario Geoff - From Geoff (Comp Transfer Jared 10) - From Geoff (Comp Transfer Torrey 10) - Assert Equal (Comp VotesLength Geoff) 0 - Assert Equal (Comp GetCurrentVotes Geoff) 0 - From Jared (Comp Delegate Geoff) - Assert Equal (Comp VotesLength Geoff) 1 - Assert Equal (Comp GetCurrentVotes Geoff) 10 - Assert Equal (Comp GetCurrentVotesBlock Geoff) LastBlock - Assert Log DelegateChanged (delegator (Address Jared)) (fromDelegate (Address Zero)) (toDelegate (Address Geoff)) - Assert Log DelegateVotesChanged (delegate (Address Geoff)) (previousBalance "0") (newBalance "10") - From Torrey (Comp Delegate Geoff) - Assert Equal (Comp VotesLength Geoff) 2 - Assert Equal (Comp GetCurrentVotes Geoff) 20 - Assert Equal (Comp GetCurrentVotesBlock Geoff) LastBlock - Assert Log DelegateChanged (delegator (Address Torrey)) (fromDelegate (Address Zero)) (toDelegate (Address Geoff)) - Assert Log DelegateVotesChanged (delegate (Address Geoff)) (previousBalance "10") (newBalance "20") - From Jared (Comp Approve Geoff 10) - From Torrey (Comp Approve Geoff 10) - From Geoff (Comp TransferFromScenario (Jared Torrey) 10) - Assert Equal (Comp VotesLength Geoff) 3 - Assert Equal (Comp GetCurrentVotes Geoff) 0 - Assert Equal (Comp GetCurrentVotesBlock Geoff) LastBlock - Assert Equal (Comp VotesLength Zero) 0 - Assert Log DelegateVotesChanged (delegate (Address Geoff)) (previousBalance "20") (newBalance "10") - Assert Log DelegateVotesChanged (delegate (Address Geoff)) (previousBalance "10") (newBalance "0") - -Test "Check transfer reverts when block number exceeds 32 bits" - Comp Deploy Geoff - From Jared (Comp Delegate Geoff) - AllowFailures - SetBlockNumber 5000000000 - From Geoff (Comp Transfer Jared 10000000e18) - Assert Revert "revert Comp::_writeCheckpoint: block number exceeds 32 bits" diff --git a/spec/scenario/CoreMacros b/spec/scenario/CoreMacros deleted file mode 100644 index cc5238c8d..000000000 --- a/spec/scenario/CoreMacros +++ /dev/null @@ -1,258 +0,0 @@ --- These are included in each scenario - -Macro Successfully - Invariant Success - -Macro AllowFailures - ClearInvariants Success - -Macro PricedComptroller closeFactor=0.1 maxAssets=20 - Unitroller Deploy - PriceOracle Deploy Simple - ComptrollerImpl Deploy ScenarioG1 ScenComptrollerG1 - Unitroller SetPendingImpl ScenComptrollerG1 - PriceOracleProxy Deploy Admin (PriceOracle Address) (Address Zero) (Address Zero) (Address Zero) (Address Zero) (Address Zero) -- if listing cEther use ListedEtherToken to replace proxy - ComptrollerImpl ScenComptrollerG1 BecomeG1 (PriceOracleProxy Address) closeFactor maxAssets - ComptrollerImpl Deploy Scenario ScenComptroller - Unitroller SetPendingImpl ScenComptroller - ComptrollerImpl ScenComptroller Become - -Macro NewComptroller price=1.0 closeFactor=0.1 maxAssets=20 - --g1 - Unitroller Deploy - PriceOracle Deploy Fixed price - ComptrollerImpl Deploy ScenarioG1 ScenComptrollerG1 - Unitroller SetPendingImpl ScenComptrollerG1 - PriceOracleProxy Deploy Admin (PriceOracle Address) (Address Zero) (Address Zero) (Address Zero) (Address Zero) (Address Zero) -- if listing cEther use ListedEtherToken to replace proxy - ComptrollerImpl ScenComptrollerG1 BecomeG1 (PriceOracleProxy Address) closeFactor maxAssets - --g2 - ComptrollerImpl Deploy StandardG2 ComptrollerG2 - Unitroller SetPendingImpl ComptrollerG2 - ComptrollerImpl ComptrollerG2 BecomeG2 - --g3 - ComptrollerImpl Deploy StandardG3 ComptrollerG3 - Unitroller SetPendingImpl ComptrollerG3 - ComptrollerImpl ComptrollerG3 BecomeG3 1e18 [] - --g4 - ComptrollerImpl Deploy StandardG4 ComptrollerG4 - Unitroller SetPendingImpl ComptrollerG4 - ComptrollerImpl ComptrollerG4 BecomeG4 - --g5 - ComptrollerImpl Deploy ScenarioG5 ComptrollerG5 - Unitroller SetPendingImpl ComptrollerG5 - ComptrollerImpl ComptrollerG5 BecomeG5 - --g6 - ComptrollerImpl Deploy ScenarioG6 ComptrollerG6 - Unitroller SetPendingImpl ComptrollerG6 - ComptrollerImpl ComptrollerG6 BecomeG6 - --current - ComptrollerImpl Deploy Scenario ComptrollerScen - Unitroller SetPendingImpl ComptrollerScen - ComptrollerImpl ComptrollerScen Become - -Macro NewCToken erc20 cToken borrowRate=0.000005 initialExchangeRate=2e9 decimals=8 tokenType=Standard delegatorType=CErc20DelegatorScenario cTokenType=CErc20DelegateScenario admin=Admin becomeImplementationData="0x0" - Erc20 Deploy tokenType erc20 erc20 - InterestRateModel Deploy Fixed StdInterest borrowRate -- Note: interest rate model probably shouldn't be global - CTokenDelegate Deploy cTokenType cErc20Delegate - CToken Deploy delegatorType cToken cToken (Erc20 erc20 Address) (Comptroller Address) (InterestRateModel StdInterest Address) initialExchangeRate decimals admin (CTokenDelegate cErc20Delegate Address) becomeImplementationData - --- Same as NewCToken but does not deploy an ERC20. Used for special ERC20s that are initialized differently -Macro NewCTokenBringERC20 erc20 cToken borrowRate=0.000005 initialExchangeRate=2e9 decimals=8 delegatorType=CErc20DelegatorScenario cTokenType=CErc20DelegateScenario admin=Admin becomeImplementationData="0x0" - InterestRateModel Deploy Fixed StdInterest borrowRate -- Note: interest rate model probably shouldn't be global - CTokenDelegate Deploy cTokenType cErc20Delegate - CToken Deploy delegatorType cToken cToken (Erc20 erc20 Address) (Comptroller Address) (InterestRateModel StdInterest Address) initialExchangeRate decimals admin (CTokenDelegate cErc20Delegate Address) becomeImplementationData - Comptroller SetMarketSupplyCaps (cToken) (2000e18) - -Macro NewCTokenImmutable erc20 cToken borrowRate=0.000005 initialExchangeRate=2e9 decimals=8 tokenType=Standard cTokenType=Scenario admin=Admin - Erc20 Deploy tokenType erc20 erc20 - InterestRateModel Deploy Fixed StdInterest borrowRate -- Note: interest rate model probably shouldn't be global - CToken Deploy cTokenType cToken cToken (Erc20 erc20 Address) (Comptroller Address) (InterestRateModel StdInterest Address) initialExchangeRate decimals admin - -Macro NewEtherToken cToken borrowRate=0.000005 initialExchangeRate=2e9 decimals=8 admin=Admin - InterestRateModel Deploy Fixed StdInterest borrowRate -- Note: interest rate model probably shouldn't be global - CToken Deploy CEtherScenario cToken cToken (Comptroller Address) (InterestRateModel StdInterest Address) initialExchangeRate decimals admin - -Macro ListedCToken erc20 cToken borrowRate=0.000005 initialExchangeRate=2e9 decimals=8 tokenType=Standard delegatorType=CErc20DelegatorScenario cTokenType=CErc20DelegateScenario admin=Admin - NewCToken erc20 cToken borrowRate initialExchangeRate decimals tokenType delegatorType cTokenType admin - Comptroller SupportMarket cToken - Comptroller SetMarketSupplyCaps (cToken) (2000e18) - -Macro ListedCTokenImmutable erc20 cToken borrowRate=0.000005 initialExchangeRate=2e9 decimals=8 tokenType=Standard cTokenType=Scenario admin=Admin - NewCTokenImmutable erc20 cToken borrowRate initialExchangeRate decimals tokenType cTokenType admin - Comptroller SupportMarket cToken - -Macro ListedEtherToken cToken borrowRate=0.000005 initialExchangeRate=2e9 decimals=8 admin=Admin - NewEtherToken cToken borrowRate initialExchangeRate decimals admin - Comptroller SupportMarket cToken - PriceOracleProxy Deploy Admin (PriceOracle Address) (Address cETH) (Address Zero) (Address Zero) (Address Zero) (Address Zero) - Comptroller SetPriceOracle (PriceOracleProxy Address) - -Macro ListedEtherTokenMinted cToken borrowRate=0.000005 initialExchangeRate=2e9 decimals=8 admin=Admin - NewEtherToken cToken borrowRate initialExchangeRate decimals admin - Comptroller SupportMarket cToken - Comptroller SetMarketSupplyCaps (cToken) (2000e18) - CallMintEth Root 1e18 cToken - -Macro SetPriceCF cToken price collateralFactor - PriceOracle SetPrice cToken price - Comptroller SetCollateralFactor cToken collateralFactor - Comptroller SetMarketSupplyCaps (cToken) (2e30) - -Macro Give user amount erc20 - Erc20 erc20 Faucet user amount - -Macro Donate token amount - (Trx Value amount (CToken token Donate)) - -Macro Prep user amount erc20 token allowanceAmount=Nothing - Erc20 erc20 Faucet user amount - From user (Erc20 erc20 Approve token (Default allowanceAmount amount)) - -Macro Allow user token - From user (Erc20 (CToken token Underlying) Approve token UInt256Max) - -Macro AccrueInterest token - CToken token AccrueInterest - -Macro Mint user amount token - From user (CToken token Mint amount) - -Macro SendMintEth user amount token - From user (Trx GasPrice 0 (Trx Value amount (Send token amount))) - -Macro CallMintEth user amount token - From user (Trx GasPrice 0 (Trx Value amount (CToken token Mint))) - -Macro Redeem user amount token - From user (CToken token Redeem amount) - -Macro RedeemEth user amount token - Trx GasPrice 0 (From user (CToken token Redeem amount)) - -Macro RedeemUnderlying user amount token - From user (CToken token RedeemUnderlying amount) - -Macro RedeemUnderlyingEth user amount token - Trx GasPrice 0 (From user (CToken token RedeemUnderlying amount)) - -Macro BorrowEth user amount token - Trx GasPrice 0 (From user (CToken token Borrow amount)) - -Macro Borrow user amount token - From user (CToken token Borrow amount) - -Macro RepayBorrow user amount token - From user (CToken token RepayBorrow amount) - -Macro RepayBorrowEth user amount token - From user (Trx GasPrice 0 (Trx Value amount (CToken token RepayBorrow))) - -Macro RepayBorrowBehalf user behalf amount token - From user (CToken token RepayBorrowBehalf behalf amount) - -Macro RepayBorrowEthBehalf user behalf amount token - From user (Trx GasPrice 0 (Trx Value amount (CToken token RepayBorrowBehalf behalf))) - -Macro Liquidate liquidator _ borrower amount token _ collateral - From liquidator (CToken token Liquidate borrower collateral amount) - -Macro LiquidateEthColl liquidator _ borrower amount token _ collateral - From liquidator (Trx GasPrice 0 (CToken token Liquidate borrower collateral amount)) - -Macro LiquidateEthBorrow liquidator _ borrower amount token _ collateral - From liquidator (Trx GasPrice 0 (Trx Value amount (CToken token Liquidate borrower collateral))) - -Macro Seize amount token caller liquidator borrower - From caller (CToken token Seize liquidator borrower amount) - -Macro EvilSeize token amount treasure seizer seizee - CToken token EvilSeize treasure seizer seizee amount - -Macro Support cToken collateralFactor=0.5 - Comptroller SupportMarket cToken - Comptroller SetCollateralFactor cToken collateralFactor - -Macro SetCollateralFactor cToken collateralFactor=0.5 - Comptroller SetCollateralFactor cToken collateralFactor - -Macro AddReserves amount token user=Root - From user (CToken token AddReserves amount) - -Macro ReduceReserves amount token - CToken token ReduceReserves amount - -Macro FastForward n blocks - Comptroller FastForward n blocks - -Macro EnterMarkets user ...markets - From user (Comptroller EnterMarkets markets) - -Macro ExitMarket user market - From user (Comptroller ExitMarket market) - -Macro Transfer from to amount token - From from (Erc20 token Transfer to amount) - -Macro Cash cToken - Read Erc20 (CToken cToken Underlying) TokenBalance cToken - -Macro QuickMint amount cToken from=Me - Give from amount (CToken cToken Underlying) - Allow from cToken - From from (CToken cToken Mint amount) - -Macro QuickBorrow amount cToken ...collateral - From Me (Comptroller EnterMarkets collateral) - From Me (Comptroller EnterMarkets (cToken)) - From Me (CToken cToken Borrow amount) - --- Macro for performing a borrow with the sole --- purpose of adding interest to the erc20 market -Macro BorrowAndRepayWithInterest erc20 cToken amount interestAmount interestRate blocks reserveRate=0 - -- TODO: Make invariant success for these? - -- TODO: Named args as macros - InterestRateModel Deploy Fixed Std interestRate - CToken cToken SetInterestRateModel (InterestRateModel Std Address) - CToken cToken SetReserveFactor reserveRate - ListedCToken COLLAT cCOLLAT - Comptroller SetCollateralFactor cCOLLAT 0.9 - Comptroller SetMarketSupplyCaps (cCOLLAT) (2e30) - Prep Torrey 1e30 COLLAT cCOLLAT - Mint Torrey 1e30 cCOLLAT - EnterMarkets Torrey cCOLLAT cToken - Assert True (Comptroller CheckMembership Torrey cCOLLAT) - Assert True (Comptroller CheckMembership Torrey cToken) - Borrow Torrey amount cToken - -- Cool, we've borrowed, now let's accrue interest then repay all - FastForward blocks Blocks - -- RepayBorrow Torrey (CToken BorrowBalance Torrey) cToken - From Torrey (Erc20 erc20 Approve cToken amount) - RepayBorrow Torrey amount cToken - From Torrey (Erc20 erc20 Approve cToken interestAmount) - Give Torrey interestAmount erc20 - RepayBorrow Torrey interestAmount cToken - Assert Equal (CToken cToken BorrowBalance Torrey) Zero - --- Macro for performing a borrow with the sole --- purpose of adding interest to the ether market -Macro BorrowAndRepayEthWithInterest cEther amount interestAmount interestRate blocks reserveRate=0 - -- TODO: Make invariant success for these? - -- TODO: Named args as macros - InterestRateModel Deploy Fixed Std interestRate - CToken cEther SetInterestRateModel (InterestRateModel Std Address) - CToken cEther SetReserveFactor reserveRate - ListedCToken COLLAT cCOLLAT - Comptroller SetCollateralFactor cCOLLAT 0.9 - Comptroller SetMarketSupplyCaps (cCOLLAT) (2e30) - Prep Torrey 1e30 COLLAT cCOLLAT - Mint Torrey 1e30 cCOLLAT - EnterMarkets Torrey cCOLLAT cEther - Assert True (Comptroller CheckMembership Torrey cCOLLAT) - Assert True (Comptroller CheckMembership Torrey cEther) - Borrow Torrey amount cEther - -- Cool, we've borrowed, now let's accrue interest then repay all - FastForward blocks Blocks - -- RepayBorrow Torrey (CToken BorrowBalance Torrey) cEther - RepayBorrowEth Torrey amount cEther - RepayBorrowEth Torrey interestAmount cEther - Assert Equal (CToken cEther BorrowBalance Torrey) Zero diff --git a/spec/scenario/EnterExitMarkets.scen b/spec/scenario/EnterExitMarkets.scen deleted file mode 100644 index 3fbb608e1..000000000 --- a/spec/scenario/EnterExitMarkets.scen +++ /dev/null @@ -1,142 +0,0 @@ --- Enter and Exit Markets Tests - -Test "Enter Markets Idempotent" - NewComptroller - Assert Equal (Comptroller MembershipLength Geoff) Zero - Assert Equal (Comptroller AssetsIn Geoff) [] - ListedCToken ZRX cZRX - EnterMarkets Geoff cZRX - Assert Log MarketEntered (cToken (Address cZRX)) (account (Address Geoff)) - Assert Equal (Comptroller MembershipLength Geoff) (Exactly 1) - Assert True (Comptroller CheckMembership Geoff cZRX) - ListedCToken OMG cOMG - EnterMarkets Geoff cZRX cOMG - Assert Equal (Comptroller MembershipLength Geoff) (Exactly 2) - Assert True (Comptroller CheckMembership Geoff cZRX) - Assert True (Comptroller CheckMembership Geoff cOMG) - Assert Equal (Comptroller AssetsIn Geoff) [(Address cZRX) (Address cOMG)] - -Test "Entered Market Must Be Supported" - NewComptroller - Assert Equal (Comptroller MembershipLength Geoff) Zero - ListedCToken ZRX cZRX - EnterMarkets Geoff cZRX - Assert Equal (Comptroller MembershipLength Geoff) (Exactly 1) - NewCToken OMG cOMG - EnterMarkets Geoff cZRX cOMG - Assert Equal (Comptroller MembershipLength Geoff) (Exactly 1) - Assert True (Comptroller CheckMembership Geoff cZRX) - Assert False (Comptroller CheckMembership Geoff cOMG) - Support cOMG - EnterMarkets Geoff cZRX cOMG - Assert Equal (Comptroller MembershipLength Geoff) (Exactly 2) - Assert True (Comptroller CheckMembership Geoff cZRX) - Assert True (Comptroller CheckMembership Geoff cOMG) - -Test "Exit single market" - NewComptroller - ListedCToken ZRX cZRX - EnterMarkets Geoff cZRX - Assert Equal (Comptroller AssetsIn Geoff) [(Address cZRX)] - ExitMarket Geoff cZRX - Assert Equal (Comptroller AssetsIn Geoff) [] - -Test "Exit non-entered market" - NewComptroller - ListedCToken ZRX cZRX - ExitMarket Geoff cZRX - Assert Equal (Comptroller AssetsIn Geoff) [] - -Test "Exit one of two market from the front" - NewComptroller - ListedCToken ZRX cZRX - ListedCToken OMG cOMG - EnterMarkets Geoff cZRX cOMG - Assert Equal (Comptroller AssetsIn Geoff) [(Address cZRX) (Address cOMG)] - ExitMarket Geoff cZRX - Assert Equal (Comptroller AssetsIn Geoff) [(Address cOMG)] - -Test "Exit one of two market from the back" - NewComptroller - ListedCToken ZRX cZRX - ListedCToken OMG cOMG - EnterMarkets Geoff cZRX cOMG - Assert Equal (Comptroller AssetsIn Geoff) [(Address cZRX) (Address cOMG)] - ExitMarket Geoff cOMG - Assert Equal (Comptroller AssetsIn Geoff) [(Address cZRX)] - -Test "Exit multiple markets" - NewComptroller - ListedCToken ZRX cZRX - ListedCToken OMG cOMG - ListedCToken BAT cBAT - ListedCToken REP cREP - ListedCToken DAI cDAI - EnterMarkets Geoff cZRX cOMG cBAT cREP cDAI - Assert Equal (Comptroller AssetsIn Geoff) [(Address cZRX) (Address cOMG) (Address cBAT) (Address cREP) (Address cDAI)] - ExitMarket Geoff cZRX - Assert Equal (Comptroller AssetsIn Geoff) [(Address cDAI) (Address cOMG) (Address cBAT) (Address cREP)] - ExitMarket Geoff cREP - Assert Equal (Comptroller AssetsIn Geoff) [(Address cDAI) (Address cOMG) (Address cBAT)] - ExitMarket Geoff cOMG - Assert Equal (Comptroller AssetsIn Geoff) [(Address cDAI) (Address cBAT)] - ExitMarket Geoff cDAI - Assert Equal (Comptroller AssetsIn Geoff) [(Address cBAT)] - ExitMarket Geoff cBAT - Assert Equal (Comptroller AssetsIn Geoff) [] - -Test "Realistic Market Scenario" - PricedComptroller - ListedCToken ZRX cZRX - SetPriceCF cZRX 0.002 0.4 - ListedEtherToken cETH - Comptroller SetCollateralFactor cEth 0.8 - ListedCToken BAT cBAT - SetPriceCF cBAT 0.0015 0.3 - Comptroller SetMarketSupplyCaps (cZRX) (2000e18) - Comptroller SetMarketSupplyCaps (cETH) (2000e18) - -- Mint some cZRX and cETH - Prep Geoff 1250e18 ZRX cZRX - Mint Geoff 1250e18 cZRX -- Liquidity -> 0.4 * 0.002 * 1250e18 = 1.0e18 - SendMintEth Geoff 2.5e18 cETH -- Liqiuidity -> 0.8 * 1.0 * 2.5e18 = 2.0e18 - -- Check liquidity is zero when not in any markets - Assert Equal (Comptroller Liquidity Geoff) Zero - -- Enter ZRX and check liquidity - EnterMarkets Geoff cZRX - Assert Equal (Comptroller Liquidity Geoff) 1.0e18 - -- Fail to borrow BAT due to liquidity - Give cBAT 1000e18 BAT - HoldInvariants - Borrow Geoff 1000e18 cBAT -- 1000e18 * 0.0015 = 1.5e18 required liquidity - -- But since we're only in ZRX, we only have 1.0e18 liquidity - Assert RevertCustomError BorrowComptrollerRejection 4 - -- Enter cETH and check liquidity - EnterMarkets Geoff cETH - Assert Equal (Comptroller Liquidity Geoff) 3.0e18 -- Sum of cETH and cZRX liquidity from above - -- Borrow previous BAT amount given liquidity - Borrow Geoff 1000e18 cBAT - Assert Equal (Comptroller Liquidity Geoff) 1.5e18 -- Less the borrow amount's toll - -- Try to exit a eth market but fail due to given borrow requiring eth as collateral - HoldInvariants - ExitMarket Geoff cETH - Assert Failure REJECTION EXIT_MARKET_REJECTION INSUFFICIENT_LIQUIDITY -- Liquidity check fails - Assert Equal (Comptroller AssetsIn Geoff) [(Address cZRX) (Address cETH) (Address cBAT)] - -- Repay some borrow and exit market OMG - Allow Geoff cBAT - RepayBorrow Geoff 500e18 cBAT - Assert Equal (Comptroller Liquidity Geoff) 2.25e18 -- With 0.75e18 repaid - ExitMarket Geoff cETH - Assert Equal (Comptroller AssetsIn Geoff) [(Address cZRX) (Address cBAT)] - Assert Equal (Comptroller Liquidity Geoff) 0.25e18 -- Less Eth's 2.0e18 collateral weight - -- Try and exit cBAT (firist without, then after, repaying) - HoldInvariants - ExitMarket Geoff cBAT - Assert Failure NONZERO_BORROW_BALANCE EXIT_MARKET_BALANCE_OWED - RepayBorrow Geoff UInt256Max cBAT - ExitMarket Geoff cBAT - Assert Equal (Comptroller AssetsIn Geoff) [(Address cZRX)] - Assert Equal (Comptroller Liquidity Geoff) 1.0e18 -- Back to just cZRX - -- Exit cZRX - ExitMarket Geoff cZRX - Assert Equal (Comptroller AssetsIn Geoff) [] - Assert Equal (Comptroller Liquidity Geoff) 0e18 -- Back to nothing diff --git a/spec/scenario/ExchangeRate.scen b/spec/scenario/ExchangeRate.scen deleted file mode 100644 index 5299e55f4..000000000 --- a/spec/scenario/ExchangeRate.scen +++ /dev/null @@ -1,76 +0,0 @@ - -Test "Initial Exchange Rate" - NewComptroller - NewCToken ZRX cZRX initialExchangeRate:2e9 - Assert Equal (CToken cZRX ExchangeRateStored) (Exp 2e9) - -Test "Initial Exchange Rate with Mint" - NewComptroller - ListedCToken ZRX cZRX initialExchangeRate:5e9 - Comptroller SetMarketSupplyCaps (cZRX) (2000e18) - -- Check initial exchange holds - Invariant Remains (CToken cZRX ExchangeRateStored) (Exp 5e9) - -- Mint some tokens and verify invariant still holds - Prep Geoff Some ZRX cZRX - Mint Geoff 50e18 cZRX - -- Also, verify token was minted at given exchange rate - Assert Equal (Erc20 cZRX TotalSupply) (Exactly 10e9) - Assert Equal (Erc20 cZRX TokenBalance Geoff) (Exactly 10e9) - -- Let's mint again and verify it's still good. - Prep Torrey Some ZRX cZRX - Mint Torrey 50e18 cZRX - -- Also, verify token was minted at given exchange rate - Assert Equal (Erc20 cZRX TotalSupply) (Exactly 20e9) - Assert Equal (Erc20 cZRX TokenBalance Torrey) (Exactly 10e9) - -Test "ZRX: Exch. Rate:2e9, Cash(51e18) + Borrows(2.0e18) - Reserves(0.5e18) / Tokens(2.5e10)" - NewComptroller - -- Decimals You=18, Decimals Us=8 -> 2e9 Exchange Rate - ListedCToken ZRX cZRX initialExchangeRate:2e9 decimals:8 - Comptroller SetMarketSupplyCaps (cZRX) (2000e18) - Assert Equal (CToken cZRX ExchangeRateStored) (Exp 2e9) - -- Mint 50.0 ZRX at given exchange rate - Prep Geoff Some ZRX cZRX - Assert Equal (Erc20 cZRX TotalSupply) Zero - Mint Geoff 50e18 cZRX - -- 50e18 / 2e9 = 2.5e10 - Assert Equal (Erc20 cZRX TotalSupply) (Exactly 2.5e10) - Assert Equal (Erc20 cZRX TokenBalance Geoff) (Exactly 2.5e10) - -- Set cash - Erc20 ZRX Faucet cZRX 1.0e18 - Assert Equal (Erc20 ZRX TokenBalance cZRX) (Exactly 51.0e18) - -- Mock total borrows - CToken cZRX Mock totalBorrows 2.0e18 - Assert Equal (CToken cZRX TotalBorrows) (Exactly 2.0e18) - -- Mock total reserves - CToken cZRX Mock totalReserves 0.5e18 - Assert Equal (CToken cZRX Reserves) (Exactly 0.5e18) - -- Okay, we're all set, let's check the exchange rate - -- (51+2-0.5)e18/2.5e10 = 52.5e18/2.5e10 = 21e8 -> 21e26 (Exp) - Assert Equal (CToken cZRX ExchangeRateStored) (Exp 2.1e9) - -Test "USDC: Exch. Rate:2e-3, Cash(51e18) + Borrows(2.0e18) - Reserves(0.5e18) / Tokens(2.5e10)" - NewComptroller - -- Decimals You=6, Decimals Us=8 -> 2e-3 Exchange Rate - ListedCToken USDC cUSDC initialExchangeRate:2e-3 decimals:8 - Comptroller SetMarketSupplyCaps (cUSDC) (2000e18) - Assert Equal (CToken cUSDC ExchangeRateStored) (Exp 2e-3) - -- Mint 50.0 USDC at given exchange rate - Prep Geoff Little USDC cUSDC - Assert Equal (Erc20 cUSDC TotalSupply) (Exactly 0.0) - Mint Geoff 50e6 cUSDC - -- 5.0e7 / 2e-3 = 2.5e10 - Assert Equal (Erc20 cUSDC TotalSupply) (Exactly 2.5e10) - Assert Equal (Erc20 cUSDC TokenBalance Geoff) (Exactly 2.5e10) - -- Set cash - Erc20 USDC Faucet cUSDC 2.0e6 - Assert Equal (Erc20 USDC TokenBalance cUSDC) (Exactly 52.0e6) - -- Mock total borrows - CToken cUSDC Mock totalBorrows 5.0e6 - Assert Equal (CToken cUSDC TotalBorrows) (Exactly 5.0e6) - -- Mock total reserves - CToken cUSDC Mock totalReserves 1.5e6 - Assert Equal (CToken cUSDC Reserves) (Exactly 1.5e6) - -- Okay, we're all set, let's check the exchange rate - -- (52+5-1.5)e6/2.5e10 = 55.5e6/2.5e10 = 2.22e-3 -> 2.22e15 (Exp) - Assert Equal (CToken cUSDC ExchangeRateStored) (Exp 2.22e-3) diff --git a/spec/scenario/Fee.scen b/spec/scenario/Fee.scen deleted file mode 100644 index b4005a289..000000000 --- a/spec/scenario/Fee.scen +++ /dev/null @@ -1,102 +0,0 @@ - -Test "Transfer fee goes to admin" - Erc20 Deploy Fee USDT USDT 18 100 Admin - Give Torrey 1e18 USDT - From Torrey (Erc20 USDT Transfer Coburn 1e18) - Assert Equal (ERC20 USDT TokenBalance Torrey) 0e18 - Assert Equal (ERC20 USDT TokenBalance Coburn) 0.99e18 - Assert Equal (ERC20 USDT TokenBalance Admin) 0.01e18 - -Test "Mint should work and not change exchange rate" - NewComptroller price:1.0 - Erc20 Deploy Fee USDT USDT 18 100 Admin - NewCTokenBringERC20 USDT cUSDT - Support cUSDT collateralFactor:0.5 - Invariant Static (CToken cUSDT ExchangeRate) - Prep Torrey 1e18 USDT cUSDT - Mint Torrey 1e18 cUSDT - Assert Equal (ERC20 USDT TokenBalance cUSDT) 0.99e18 - -Test "Repay borrow should work and not change exchange rate" - PricedComptroller - Erc20 Deploy Fee USDT USDT 18 100 Admin - NewCTokenBringERC20 USDT cUSDT - NewCToken ZRX cZRX 0.000005 2e9 8 Standard - Comptroller SetMarketSupplyCaps (cUSDT) (2000e18) - Comptroller SetMarketSupplyCaps (cZRX) (2000e18) - PriceOracle SetPrice cZRX 1.0 - PriceOracle SetPrice cUSDT 1.0 - Support cZRX 0.5 - Support cUSDT 0.5 - Give cUSDT 10e18 USDT -- Faucet some Tether to borrow - Invariant Static (CToken cUSDT ExchangeRate) - Prep Torrey 100e18 ZRX cZRX - Mint Torrey 100e18 cZRX - EnterMarkets Torrey cUSDT - EnterMarkets Torrey cZRX - Borrow Torrey 1e18 cUSDT -- we only received 0.99 tether bc of fee - Assert Equal (ERC20 USDT TokenBalance Torrey) 0.99e18 - FastForward 196000 Blocks -- 1e18 * 196000 * 0.000005 = 0.98e18 interest accrued - Assert Equal (CToken cUSDT TotalBorrowsCurrent) 1.98e18 - Prep Torrey 1.01e18 USDT cUSDT 2e18 -- so give 2 - 0.99 = 1.01, and approve 2e18 - RepayBorrow Torrey 2e18 cUSDT -- repay more than we owe to account for fee - Assert Equal (CToken cUSDT BorrowBalance Torrey) 0 - Assert Equal (CToken cUSDT TotalBorrowsCurrent) 0 - Assert Equal (ERC20 USDT TokenBalance Torrey) 0 - -Test "Should be able to liquidate fee token borrow" - PricedComptroller - Comptroller LiquidationIncentive 1.1 - Erc20 Deploy Fee USDT USDT 18 100 Admin - NewCTokenBringERC20 USDT cUSDT - Comptroller SetMarketSupplyCaps (cUSDT) (2000e18) - NewCToken ZRX cZRX 0.000005 2e9 8 Standard - Comptroller SetMarketSupplyCaps (cZRX) (2000e18) - PriceOracle SetPrice cZRX 1.0 - PriceOracle SetPrice cUSDT 1.0 - Support cZRX 0.5 - Support cUSDT 0.5 - Give cUSDT 10e18 USDT -- Faucet some Tether to borrow - Invariant Static (CToken cUSDT ExchangeRate) - Invariant Static (CToken cZRX ExchangeRate) - Prep Torrey 2e18 ZRX cZRX - Mint Torrey 2e18 cZRX - EnterMarkets Torrey cUSDT - EnterMarkets Torrey cZRX - Borrow Torrey 1e18 cUSDT -- we only received 0.99 tether bc of fee - Assert Equal (ERC20 USDT TokenBalance Torrey) 0.99e18 - FastForward 196000 Blocks -- 1e18 * 196000 * 0.000005 = 0.98e18 interest accrued - Assert Equal (CToken cUSDT TotalBorrowsCurrent) 1.98e18 - -- OK! should be ready to liquidate, so lets do that - Prep Coburn 2e18 USDT cUSDT - Liquidate Coburn "->" Torrey 0.1e18 cUSDT "Seizing" cZRX - -- effective liquidation incentive after deducting protocolSeizeShare is 1.1 * (1-.028) = 1.0692 - -- 5.29254e7 = 0.1e18 (amount liquidated) * 1.0692 (liq discount) * .99 (fee) / 2e9 (exchange rate) - Assert Equal (Erc20 cZRX TokenBalance Coburn) 5.29254e7 - Assert Equal (CToken cUSDT BorrowBalance Torrey) 1.881e18 -- 1.98 - (0.1 * .99) was liquidated - Assert Equal (Erc20 USDT TokenBalance Coburn) 1.9e18 - -Test "Should be able to redeem a fee CToken, exchange Rate should not change" - NewComptroller price:1.0 - Erc20 Deploy Fee USDT USDT 18 100 Admin - NewCTokenBringERC20 USDT cUSDT - Comptroller SetMarketSupplyCaps (cUSDT) (2000e18) - Support cUSDT collateralFactor:0.5 - Invariant Static (CToken cUSDT ExchangeRate) - Prep Torrey 1e18 USDT cUSDT - Mint Torrey 1e18 cUSDT - Redeem Torrey (Erc20 cUSDT TokenBalance Torrey) cUSDT - -Test "Order of redeems should not matter if no interest accrued" - NewComptroller price:1.0 - Erc20 Deploy Fee USDT USDT 18 100 Admin - NewCTokenBringERC20 USDT cUSDT - Comptroller SetMarketSupplyCaps (cUSDT) (2000e18) - Support cUSDT collateralFactor:0.5 - Invariant Static (CToken cUSDT ExchangeRate) - Prep Torrey 1e18 USDT cUSDT - Mint Torrey 1e18 cUSDT - Prep Coburn 1e18 USDT cUSDT - Mint Coburn 1e18 cUSDT - Redeem Torrey (Erc20 cUSDT TokenBalance Torrey) cUSDT - Redeem Coburn (Erc20 cUSDT TokenBalance Coburn) cUSDT diff --git a/spec/scenario/HypotheticalAccountLiquidity.scen b/spec/scenario/HypotheticalAccountLiquidity.scen deleted file mode 100644 index f8bb148c6..000000000 --- a/spec/scenario/HypotheticalAccountLiquidity.scen +++ /dev/null @@ -1,53 +0,0 @@ - -Test "Calculates hypothetical account liquidity" - -- Note, this comes a bit from `EnterExitMarkets` Scenario - PricedComptroller - ListedCToken ZRX cZRX initialExchangeRate:1e9 - Comptroller SetMarketSupplyCaps (cZRX) (2000e18) - SetPriceCF cZRX 0.002 0.4 - ListedEtherToken cETH initialExchangeRate:1e9 - Comptroller SetMarketSupplyCaps (cETH) (2000e18) - Comptroller SetCollateralFactor cEth 0.8 - ListedCToken BAT cBAT initialExchangeRate:1e9 - Comptroller SetMarketSupplyCaps (cOMG) (2000e18) - SetPriceCF cBAT 0.0015 0.3 - ListedCToken OMG cOMG initialExchangeRate:1e9 - NewCToken REP cREP - -- Mint some cZRX and cETH - Prep Geoff 1250e18 ZRX cZRX - Comptroller SetMarketSupplyCaps (cREP) (2000e18) - Mint Geoff 1250e18 cZRX -- Liquidity -> 0.4 * 0.002 * 1250e18 = 1.0e18 - SendMintEth Geoff 2.5e18 cETH -- Liqiuidity -> 0.8 * 1.0 * 2.5e18 = 2.0e18 - -- Check liquidity is zero when not in any markets - Assert Equal (Comptroller Liquidity Geoff) Zero - -- Enter ZRX and check liquidity - EnterMarkets Geoff cZRX - Assert Equal (Comptroller Liquidity Geoff) 1.0e18 - -- Now let's look at some hypotheticals - Assert Equal (Comptroller Hypothetical Geoff Redeems 1000e9 cZRX) 0.2e18 -- 0.4 * 0.002 * -1000e18 = -0.8e18 - Assert Equal (Comptroller Hypothetical Geoff Borrows 1000e18 cZRX) -1e18 -- 0.002 * -1000e18 = -2e18 - -- Note, if you're not in an asset, this function returns no effect - Assert Equal (Comptroller Hypothetical Geoff Redeems 0.002e9 cETH) 1.0e18 -- 0.8 * 1000.0 * -0.002e18 = -1.6e18 - Assert Equal (Comptroller Hypothetical Geoff Borrows 0.002e18 cETH) 1.0e18 -- 1000.0 * -0.002e18 = -2e18 - EnterMarkets Geoff cETH - Assert Equal (Comptroller Liquidity Geoff) 3.0e18 - Assert Equal (Comptroller Hypothetical Geoff Redeems 1000e9 cZRX) 2.2e18 -- 0.4 * 0.002 * -1000e18 = -0.8e18 - Assert Equal (Comptroller Hypothetical Geoff Borrows 1000e18 cZRX) 1e18 -- 0.002 * -1000e18 = -2e18 - Assert Equal (Comptroller Hypothetical Geoff Redeems 2e9 cETH) 1.4e18 -- 0.8 * 1.0 * -2e18 = -1.6e18 - Assert Equal (Comptroller Hypothetical Geoff Borrows 2e18 cETH) 1.0e18 -- 1.0 * -2e18 = -2e18 - EnterMarkets Geoff cBAT - Assert Equal (Comptroller Hypothetical Geoff Redeems 1000e9 cBAT) 2.55e18 -- 0.3 * 0.0015 * -1000e18 = -0.45e18e18 - Assert Equal (Comptroller Hypothetical Geoff Borrows 1000e18 cBAT) 1.5e18 -- 0.0015 * -1000e18 = -1.5e18 - EnterMarkets Geoff cOMG - -- Fails if the given asset doesn't have a price - Assert ReadError (Comptroller Hypothetical Geoff Redeems 1e20 cOMG) "Failed to compute account hypothetical liquidity: error code = 13" - Assert ReadError (Comptroller Hypothetical Geoff Borrows 1e20 cOMG) "Failed to compute account hypothetical liquidity: error code = 13" - PriceOracle SetPrice cOMG 0.01 - -- Has a price and now is listed - Assert Equal (Comptroller Hypothetical Geoff Redeems 100e9 cOMG) 3.0e18 -- No collateral factor - Assert Equal (Comptroller Hypothetical Geoff Borrows 100e18 cOMG) 2.0e18 -- 0.01 * -100e18 = -1e18 - -- For a token has no price and isn't listed - -- Note: we can't actually enter the unlisted market without some harness function - -- we could consider testing this, but it would be out of the scope of scenarios - Assert Equal (Comptroller Hypothetical Geoff Redeems 100e18 cREP) 3.0e18 -- No effect - Assert Equal (Comptroller Hypothetical Geoff Borrows 100e18 cREP) 3.0e18 -- No effect diff --git a/spec/scenario/InKindLiquidation.scen b/spec/scenario/InKindLiquidation.scen deleted file mode 100644 index 6ef95a521..000000000 --- a/spec/scenario/InKindLiquidation.scen +++ /dev/null @@ -1,443 +0,0 @@ - -Macro InKindBorrow borrowAmount borrowRate user=Geoff borrowPrice=1.0 mintAmount=100e18 giveAmount=0e18 borrowTokenType=Standard - PricedComptroller - Comptroller LiquidationIncentive 1.1 - NewCToken BAT cBAT borrowRate 2e9 8 borrowTokenType -- note: cannot use macros with named args right now - Comptroller SetMarketSupplyCaps (cBAT) (2000e18) - Give cBAT giveAmount BAT -- Faucet some bat - PriceOracle SetPrice cBAT borrowPrice - Support cBAT collateralFactor:0.5 - Prep user mintAmount BAT cBAT - Mint user mintAmount cBAT - EnterMarkets user cBAT - Borrow user borrowAmount cBAT - -Test "Insufficient in-kind shortfall" - InKindBorrow borrowAmount:1e18 borrowRate:0.000005 - Assert Equal (CToken cBAT BorrowBalance Geoff) 1e18 - Assert Equal (CToken cBAT TotalBorrows) 1e18 - Comptroller SetMarketSupplyCaps (cBAT) (2000e18) - Assert Equal (Erc20 BAT TokenBalance Geoff) 1e18 - Assert Equal (Erc20 BAT TokenBalance cBAT) 99e18 - Assert Equal (Comptroller Liquidity Geoff) 49e18 -- ( ( 1.0 * 100e18 * 0.5 ) - ( 1.0 * 51e18 ) ) / 1e18 - -- Prices are 1:1 (in-kind) and collateral factor is 0.5, - -- thus supplying 100e18 cBAT gives the user 50e18 - -- capacity of BAT. User only borrowed 1BAT, but after - -- a lot blocks at a 0.0005% interest rate, he'll be - -- underwater. Note: with a reserve rate of zero, that - -- interest will be paid back to himself as supply - -- but that will be discounted by 50% by the collateral factor. - -- Thus, we will need to accumulate for twice as many blocks - -- to end up where we'd usually be underwater - FastForward 19600000 Blocks -- 1e18 * (1 + 19600000 * 0.000005) - AccrueInterest cBAT -- Note: we have to accrue interest - -- since it's not automatic for liquidity - Assert Equal (CToken cBAT BorrowBalanceStored Geoff) 99e18 - Assert Equal (CToken cBAT TotalBorrows) 99e18 - -- Check user liquidity and verify equals 0 - Assert Equal (Comptroller Liquidity Geoff) 0e18 -- ( ( 1.0 * ( 100e18 + 98e18 ) * 0.5 ) - ( ( 98 + 1 ) * 1e18 ) ) / 1e18 - -- At exactly zero, should not be able to liquidate - Prep Torrey 10e18 BAT cBAT - AllowFailures - Liquidate Torrey "->" Geoff 10e18 cBAT "Seizing" cBAT - Assert RevertCustomError LiquidateComptrollerRejection 3 - -Test "Cannot self-in-kind-liquidate" - InKindBorrow borrowAmount:1e18 borrowRate:0.000005 - Assert Equal (CToken cBAT BorrowBalance Geoff) 1e18 - Assert Equal (CToken cBAT TotalBorrows) 1e18 - Assert Equal (Erc20 BAT TokenBalance Geoff) 1e18 - Assert Equal (Erc20 BAT TokenBalance cBAT) 99e18 - Assert Equal (Comptroller Liquidity Geoff) 49e18 -- ( ( 1.0 * 100e18 * 0.5 ) - ( 1.0 * 51e18 ) ) / 1e18 - -- Prices are 1:1 (in-kind) and collateral factor is 0.5, - -- thus supplying 100e18 cBAT gives the user 50e18 - -- capacity of BAT. User only borrowed 1BAT, but after - -- a lot blocks at a 0.0005% interest rate, he'll be - -- underwater. Note: with a reserve rate of zero, that - -- interest will be paid back to himself as supply - -- but that will be discounted by 50% by the collateral factor. - -- Thus, we will need to accumulate for twice as many blocks - -- to end up where we'd usually be underwater - FastForward 20000000 Blocks -- 1e18 * (1 + 20000000 * 0.000005) - AccrueInterest cBAT -- Note: we have to accrue interest - -- since it's not automatic for liquidity - Assert Equal (CToken cBAT BorrowBalanceStored Geoff) 101e18 - Assert Equal (CToken cBAT TotalBorrows) 101e18 - -- Check user liquidity and verify < 0 - Assert Equal (Comptroller Liquidity Geoff) -1e18 - -- Okay, so we should be able to liquidate, so let's do that. - Prep Geoff 10e18 BAT cBAT - AllowFailures - Liquidate Geoff "->" Geoff 2e18 cBAT "Seizing" cBAT - Assert RevertCustomError LiquidateLiquidatorIsBorrower - -Test "Liqidate in-kind beyond max close" - InKindBorrow borrowAmount:1e18 borrowRate:0.000005 - Assert Equal (CToken cBAT BorrowBalance Geoff) 1e18 - Assert Equal (CToken cBAT TotalBorrows) 1e18 - Assert Equal (Erc20 BAT TokenBalance Geoff) 1e18 - Assert Equal (Erc20 BAT TokenBalance cBAT) 99e18 - Assert Equal (Comptroller Liquidity Geoff) 49e18 -- ( ( 1.0 * 100e18 * 0.5 ) - ( 1.0 * 51e18 ) ) / 1e18 - -- Prices are 1:1 (in-kind) and collateral factor is 0.5, - -- thus supplying 100e18 cBAT gives the user 50e18 - -- capacity of BAT. User only borrowed 1BAT, but after - -- a lot blocks at a 0.0005% interest rate, he'll be - -- underwater. Note: with a reserve rate of zero, that - -- interest will be paid back to himself as supply - -- but that will be discounted by 50% by the collateral factor. - -- Thus, we will need to accumulate for twice as many blocks - -- to end up where we'd usually be underwater - FastForward 20000000 Blocks -- 1e18 * (1 + 20000000 * 0.000005) - AccrueInterest cBAT -- Note: we have to accrue interest - -- since it's not automatic for liquidity - Assert Equal (CToken cBAT BorrowBalanceStored Geoff) 101e18 - Assert Equal (CToken cBAT TotalBorrows) 101e18 - -- Check user liquidity and verify < 0 - Assert Equal (Comptroller Liquidity Geoff) -1e18 - -- Okay, so we should be able to liquidate, so let's do that. - Prep Torrey 20e18 BAT cBAT - AllowFailures - Liquidate Torrey "->" Geoff 20e18 cBAT "Seizing" cBAT - Assert RevertCustomError LiquidateComptrollerRejection 17 - -Test "Proper In-Kind Liquidation" - InKindBorrow borrowAmount:1e18 borrowRate:0.000005 - Assert Equal (CToken cBAT BorrowBalance Geoff) 1e18 - Assert Equal (CToken cBAT TotalBorrows) 1e18 - Assert Equal (Erc20 BAT TokenBalance Geoff) 1e18 - Assert Equal (Erc20 BAT TokenBalance cBAT) 99e18 - Assert Equal (Comptroller Liquidity Geoff) 49e18 -- ( ( 1.0 * 100e18 * 0.5 ) - ( 1.0 * 1e18 ) ) / 1e18 - -- Prices are 1:1 (in-kind) and collateral factor is 0.5, - -- thus supplying 100e18 cBAT gives the user 50e18 - -- capacity of BAT. User only borrowed 1BAT, but after - -- a lot blocks at a 0.0005% interest rate, he'll be - -- underwater. Note: with a reserve rate of zero, that - -- interest will be paid back to himself as supply - -- but that will be discounted by 50% by the collateral factor. - -- Thus, we will need to accumulate for twice as many blocks - -- to end up where we'd usually be underwater - FastForward 20000000 Blocks -- 1e18 * (1 + 20000000 * 0.000005) - AccrueInterest cBAT -- Note: we have to accrue interest - -- since it's not automatic for liquidity - Assert Equal (CToken cBAT BorrowBalanceStored Geoff) 101e18 - Assert Equal (CToken cBAT TotalBorrows) 101e18 - -- Check user liquidity and verify < 0 - Assert Equal (Comptroller Liquidity Geoff) -1e18 -- ( ( 1.0 * ( 100e18 + 100e18 ) * 0.5 ) - ( 101 * 1e18 ) ) / 1e18 - -- Okay, so we should be able to liquidate, so let's do that. - Prep Torrey 2e18 BAT cBAT - -- - -- Let's check how values start before liquidation - -- Note: we're going to be some-what exhausive in what we check - Invariant Remains (Erc20 BAT TokenBalance Geoff) 1e18 -- all was minted, this is what was borrowed - Assert Equal (Erc20 BAT TokenBalance Torrey) 2e18 -- from prep above - Assert Equal (Erc20 BAT TokenBalance cBAT) 99e18 -- from minting minus 1e18 lent to geoff - Assert Equal (Erc20 cBAT TokenBalance Geoff) 50e9 -- from minting - Assert Equal (Erc20 cBAT TokenBalance Torrey) 0e9 -- never had any - Invariant Remains (Erc20 BAT TokenBalance Geoff) 1e18 -- original amount borrowed - Assert Equal (CToken cBAT BorrowBalanceStored Geoff) 101e18 -- all that interest - Assert Equal (CToken cBAT TotalBorrows) 101e18 -- all those borrowers - Assert Equal (CToken cBAT ExchangeRate) 4e9 --- XXX: Verify this - -- Do the liquidation - Liquidate Torrey "->" Geoff 2e18 cBAT "Seizing" cBAT -- should now take twice as much collateral - -- - -- And see what they are now - Assert Equal (CToken cBAT ExchangeRate) 4e9 --- XXX: Verify this - -- effective liquidation incentive after deducting protocolSeizeShare is 1.1 * (1-.028) = 1.0692 - Assert Equal (Erc20 cBAT TokenBalance Geoff) 49.45e9 -- 1:1 -> 1 x 2e18 x 1.0692 ÷ 4e9 [exchange rate] = 0.55e9 -> Torrey - Assert Equal (Erc20 cBAT TokenBalance Torrey) 0.5346e9 -- didn't have any beforehand XXX - Assert Equal (Erc20 BAT TokenBalance Torrey) 0e18 -- repaid - Assert Equal (Erc20 BAT TokenBalance cBAT) 101e18 -- had 100e18, lent 1e18 to geoff, repaid 2 - Assert Equal (CToken cBAT BorrowBalanceStored Geoff) 99e18 -- less closed amount - Assert Equal (CToken cBAT TotalBorrows) 99e18 -- - -- Prices are 1:1 and collateral factor is 0.5 - -- User now has 49.45e9 outstanding supply (yielding 98.9 borrowing capacity due - -- to the collateral factor (0.5) and exchange rate (4e9)). - -- The user also has a 99e18 borrow outstanding which is weighted 1:1. - -- Thus the liquidity is (98.9-99)e18 or -0.1e18. - Assert Equal (Comptroller Liquidity Geoff) -0.1e18 - -Test "Liquidate exactly zero" - InKindBorrow borrowAmount:1e18 borrowRate:0.000005 - Assert Equal (CToken cBAT BorrowBalance Geoff) 1e18 - Assert Equal (CToken cBAT TotalBorrows) 1e18 - Assert Equal (Erc20 BAT TokenBalance Geoff) 1e18 - Assert Equal (Erc20 BAT TokenBalance cBAT) 99e18 - Assert Equal (Comptroller Liquidity Geoff) 49e18 -- ( ( 1.0 * 100e18 * 0.5 ) - ( 1.0 * 1e18 ) ) / 1e18 - -- Prices are 1:1 (in-kind) and collateral factor is 0.5, - -- thus supplying 100e18 cBAT gives the user 50e18 - -- capacity of BAT. User only borrowed 1BAT, but after - -- a lot blocks at a 0.0005% interest rate, he'll be - -- underwater. Note: with a reserve rate of zero, that - -- interest will be paid back to himself as supply - -- but that will be discounted by 50% by the collateral factor. - -- Thus, we will need to accumulate for twice as many blocks - -- to end up where we'd usually be underwater - FastForward 20000000 Blocks -- 1e18 * (1 + 20000000 * 0.000005) - AccrueInterest cBAT -- Note: we have to accrue interest - -- since it's not automatic for liquidity - Invariant Remains (CToken cBAT BorrowBalanceStored Geoff) 101e18 - Invariant Remains (CToken cBAT TotalBorrows) 101e18 - -- Check user liquidity and verify < 0 - Invariant Remains (Comptroller Liquidity Geoff) -1e18 - -- Okay, so we should be able to liquidate, so let's do that. - Prep Torrey 10e18 BAT cBAT - AllowFailures - Liquidate Torrey "->" Geoff 0e18 cBAT "Seizing" cBAT - Assert RevertCustomError LiquidateCloseAmountIsZero - -Test "When price oracle for collateral token is zero" - InKindBorrow borrowAmount:1e18 borrowRate:0.000005 - Assert Equal (CToken cBAT BorrowBalance Geoff) 1e18 - Assert Equal (CToken cBAT TotalBorrows) 1e18 - Assert Equal (Erc20 BAT TokenBalance Geoff) 1e18 - Assert Equal (Erc20 BAT TokenBalance cBAT) 99e18 - Assert Equal (Comptroller Liquidity Geoff) 49e18 -- ( ( 1.0 * 100e18 * 0.5 ) - ( 1.0 * 1e18 ) ) / 1e18 - -- Prices are 1:1 (in-kind) and collateral factor is 0.5, - -- thus supplying 100e18 cBAT gives the user 50e18 - -- capacity of BAT. User only borrowed 1BAT, but after - -- a lot blocks at a 0.0005% interest rate, he'll be - -- underwater. Note: with a reserve rate of zero, that - -- interest will be paid back to himself as supply - -- but that will be discounted by 50% by the collateral factor. - -- Thus, we will need to accumulate for twice as many blocks - -- to end up where we'd usually be underwater - FastForward 20000000 Blocks -- 1e18 * (1 + 20000000 * 0.000005) - AccrueInterest cBAT -- Note: we have to accrue interest - -- since it's not automatic for liquidity - Invariant Remains (CToken cBAT BorrowBalanceStored Geoff) 101e18 - Invariant Remains (CToken cBAT TotalBorrows) 101e18 - -- Check user liquidity and verify < 0 - Assert Equal (Comptroller Liquidity Geoff) -1e18 - -- Okay, so we should be able to liquidate, so let's do that. - Prep Torrey 10e18 BAT cBAT - PriceOracle SetPrice cBAT 0 - AllowFailures - Liquidate Torrey "->" Geoff 2e18 cBAT "Seizing" cBAT - Assert RevertCustomError LiquidateComptrollerRejection 13 - -Test "When price oracle for collateral token is whack" - InKindBorrow borrowAmount:1e18 borrowRate:0.000005 - Assert Equal (CToken cBAT BorrowBalance Geoff) 1e18 - Assert Equal (CToken cBAT TotalBorrows) 1e18 - Assert Equal (Erc20 BAT TokenBalance Geoff) 1e18 - Assert Equal (Erc20 BAT TokenBalance cBAT) 99e18 - Assert Equal (Comptroller Liquidity Geoff) 49e18 -- ( ( 1.0 * 100e18 * 0.5 ) - ( 1.0 * 1e18 ) ) / 1e18 - -- Prices are 1:1 (in-kind) and collateral factor is 0.5, - -- thus supplying 100e18 cBAT gives the user 50e18 - -- capacity of BAT. User only borrowed 1BAT, but after - -- a lot blocks at a 0.0005% interest rate, he'll be - -- underwater. Note: with a reserve rate of zero, that - -- interest will be paid back to himself as supply - -- but that will be discounted by 50% by the collateral factor. - -- Thus, we will need to accumulate for twice as many blocks - -- to end up where we'd usually be underwater - FastForward 20000000 Blocks -- 1e18 * (1 + 20000000 * 0.000005) - AccrueInterest cBAT -- Note: we have to accrue interest - -- since it's not automatic for liquidity - Invariant Remains (CToken cBAT BorrowBalanceStored Geoff) 101e18 - Invariant Remains (CToken cBAT TotalBorrows) 101e18 - -- Check user liquidity and verify < 0 - Assert Equal (Comptroller Liquidity Geoff) -1e18 - -- Okay, so we should be able to liquidate, so let's do that. - Prep Torrey 10e18 BAT cBAT - PriceOracle SetPrice cBAT 1.15792e59 - AllowFailures - Liquidate Torrey "->" Geoff 2e18 cBAT "Seizing" cBAT - Assert Revert -- Multiplication Overflow - -Test "When repay borrow fails" - InKindBorrow borrowAmount:1e18 borrowRate:0.000005 - Assert Equal (CToken cBAT BorrowBalance Geoff) 1e18 - Assert Equal (CToken cBAT TotalBorrows) 1e18 - Assert Equal (Erc20 BAT TokenBalance Geoff) 1e18 - Assert Equal (Erc20 BAT TokenBalance cBAT) 99e18 - Assert Equal (Comptroller Liquidity Geoff) 49e18 -- ( ( 1.0 * 100e18 * 0.5 ) - ( 1.0 * 1e18 ) ) / 1e18 - -- Prices are 1:1 (in-kind) and collateral factor is 0.5, - -- thus supplying 100e18 cBAT gives the user 50e18 - -- capacity of BAT. User only borrowed 1BAT, but after - -- a lot blocks at a 0.0005% interest rate, he'll be - -- underwater. Note: with a reserve rate of zero, that - -- interest will be paid back to himself as supply - -- but that will be discounted by 50% by the collateral factor. - -- Thus, we will need to accumulate for twice as many blocks - -- to end up where we'd usually be underwater - FastForward 20000000 Blocks -- 1e18 * (1 + 20000000 * 0.000005) - AccrueInterest cBAT -- Note: we have to accrue interest - -- since it's not automatic for liquidity - Invariant Remains (CToken cBAT BorrowBalanceStored Geoff) 101e18 - Invariant Remains (CToken cBAT TotalBorrows) 101e18 - -- Check user liquidity and verify < 0 - Invariant Remains (Comptroller Liquidity Geoff) -1e18 - -- Okay, so we should be able to liquidate, so let's do that. - Prep Torrey 10e18 BAT cBAT allowanceAmount:0.1e18 - AllowFailures - Liquidate Torrey "->" Geoff 2e18 cBAT "Seizing" cBAT - Assert Revert "revert Insufficient allowance" - -Test "Proper liquidation of paused WBTC as collateral" - InKindBorrow borrowAmount:1e18 borrowRate:0.000005 borrowTokenType:WBTC - Assert Equal (CToken cBAT BorrowBalance Geoff) 1e18 - Assert Equal (CToken cBAT TotalBorrows) 1e18 - Assert Equal (Erc20 BAT TokenBalance Geoff) 1e18 - Assert Equal (Erc20 BAT TokenBalance cBAT) 99e18 - Assert Equal (Comptroller Liquidity Geoff) 49e18 -- ( ( 1.0 * 100e18 * 0.5 ) - ( 1.0 * 1e18 ) ) / 1e18 - -- Prices are 1:1 (in-kind) and collateral factor is 0.5, - -- thus supplying 100e18 cBAT gives the user 50e18 - -- capacity of BAT. User only borrowed 1BAT, but after - -- a lot blocks at a 0.0005% interest rate, he'll be - -- underwater. Note: with a reserve rate of zero, that - -- interest will be paid back to himself as supply - -- but that will be discounted by 50% by the collateral factor. - -- Thus, we will need to accumulate for twice as many blocks - -- to end up where we'd usually be underwater - FastForward 20000000 Blocks -- 1e18 * (1 + 20000000 * 0.000005) - AccrueInterest cBAT -- Note: we have to accrue interest - -- since it's not automatic for liquidity - Assert Equal (CToken cBAT BorrowBalanceStored Geoff) 101e18 - Assert Equal (CToken cBAT TotalBorrows) 101e18 - -- Check user liquidity and verify < 0 - Assert Equal (Comptroller Liquidity Geoff) -1e18 -- recheck - -- Okay, so we should be able to liquidate, so let's do that. - Prep Torrey 2e18 BAT cBAT - -- - -- Let's check how values start before liquidation - -- Note: we're going to be some-what exhausive in what we check - Invariant Remains (Erc20 BAT TokenBalance Geoff) 1e18 -- all was minted, this is what was borrowed - Assert Equal (Erc20 BAT TokenBalance Torrey) 2e18 -- from prep above - Assert Equal (Erc20 BAT TokenBalance cBAT) 99e18 -- from minting minus 1e18 lent to geoff - Assert Equal (Erc20 cBAT TokenBalance Geoff) 50e9 -- from minting - Assert Equal (Erc20 cBAT TokenBalance Torrey) 0e9 -- never had any - Invariant Remains (Erc20 BAT TokenBalance Geoff) 1e18 -- original amount borrowed - Assert Equal (CToken cBAT BorrowBalanceStored Geoff) 101e18 -- all that interest - Assert Equal (CToken cBAT TotalBorrows) 101e18 -- all those borrowers - Assert Equal (CToken cBAT ExchangeRate) 4e9 --- XXX: Verify this - -- - -- Pause "WBTC" - Erc20 BAT Pause -- Actually a WBTC token - -- Do the liquidation - AllowFailures - Liquidate Torrey "->" Geoff 2e18 cBAT "Seizing" cBAT -- should now take twice as much collateral - Assert Revert -- Reverts since we can't transfer the BAT in due to pause - -Test "When seize not allowed due to unlisted collateral" - InKindBorrow borrowAmount:1e18 borrowRate:0.000005 - Assert Equal (CToken cBAT BorrowBalance Geoff) 1e18 - Assert Equal (CToken cBAT TotalBorrows) 1e18 - Assert Equal (Erc20 BAT TokenBalance Geoff) 1e18 - Assert Equal (Erc20 BAT TokenBalance cBAT) 99e18 - Assert Equal (Comptroller Liquidity Geoff) 49e18 -- ( ( 1.0 * 100e18 * 0.5 ) - ( 1.0 * 1e18 ) ) / 1e18 - -- Prices are 1:1 (in-kind) and collateral factor is 0.5, - -- thus supplying 100e18 cBAT gives the user 50e18 - -- capacity of BAT. User only borrowed 1BAT, but after - -- a lot blocks at a 0.0005% interest rate, he'll be - -- underwater. Note: with a reserve rate of zero, that - -- interest will be paid back to himself as supply - -- but that will be discounted by 50% by the collateral factor. - -- Thus, we will need to accumulate for twice as many blocks - -- to end up where we'd usually be underwater - FastForward 20000000 Blocks -- 1e18 * (1 + 20000000 * 0.000005) - AccrueInterest cBAT -- Note: we have to accrue interest - -- since it's not automatic for liquidity - Invariant Remains (CToken cBAT BorrowBalanceStored Geoff) 101e18 - Invariant Remains (CToken cBAT TotalBorrows) 101e18 - -- Okay, so we should be able to liquidate, so let's do that. - Prep Torrey 10e18 BAT cBAT - Comptroller UnList cBAT -- Mock unlist collateral - AllowFailures - Liquidate Torrey "->" Geoff 2e18 cBAT "Seizing" cBAT - Assert RevertCustomError LiquidateComptrollerRejection 9 - -Test "When seize not allowed due to unlisted borrow" - InKindBorrow borrowAmount:1e18 borrowRate:0.000005 - Assert Equal (CToken cBAT BorrowBalance Geoff) 1e18 - Assert Equal (CToken cBAT TotalBorrows) 1e18 - Assert Equal (Erc20 BAT TokenBalance Geoff) 1e18 - Assert Equal (Erc20 BAT TokenBalance cBAT) 99e18 - Assert Equal (Comptroller Liquidity Geoff) 49e18 -- ( ( 1.0 * 100e18 * 0.5 ) - ( 1.0 * 1e18 ) ) / 1e18 - -- Prices are 1:1 (in-kind) and collateral factor is 0.5, - -- thus supplying 100e18 cBAT gives the user 50e18 - -- capacity of BAT. User only borrowed 1BAT, but after - -- a lot blocks at a 0.0005% interest rate, he'll be - -- underwater. Note: with a reserve rate of zero, that - -- interest will be paid back to himself as supply - -- but that will be discounted by 50% by the collateral factor. - -- Thus, we will need to accumulate for twice as many blocks - -- to end up where we'd usually be underwater - FastForward 20000000 Blocks -- 1e18 * (1 + 20000000 * 0.000005) - AccrueInterest cBAT -- Note: we have to accrue interest - -- since it's not automatic for liquidity - Invariant Remains (CToken cBAT BorrowBalanceStored Geoff) 101e18 - Invariant Remains (CToken cBAT TotalBorrows) 101e18 - -- Okay, so we should be able to liquidate, so let's do that. - Prep Torrey 10e18 BAT cBAT - Comptroller UnList cBAT -- Mock unlist borrow - AllowFailures - Liquidate Torrey "->" Geoff 2e18 cBAT "Seizing" cBAT - Assert RevertCustomError LiquidateComptrollerRejection 9 - -Test "When there's insufficient collateral" - InKindBorrow borrowAmount:1e18 borrowRate:0.000005 - Comptroller SetCloseFactor 0.9 - Comptroller LiquidationIncentive 1.5 - Assert Equal (CToken cBAT BorrowBalance Geoff) 1e18 - Assert Equal (CToken cBAT TotalBorrows) 1e18 - Assert Equal (Erc20 BAT TokenBalance Geoff) 1e18 - Assert Equal (Erc20 BAT TokenBalance cBAT) 99e18 - Assert Equal (Comptroller Liquidity Geoff) 49e18 -- ( ( 1.0 * 100e18 * 0.5 ) - ( 1.0 * 1e18 ) ) / 1e18 - -- Prices are 1:1 (in-kind) and collateral factor is 0.5, - -- thus supplying 100e18 cBAT gives the user 50e18 - -- capacity of BAT. User only borrowed 1BAT, but after - -- a lot blocks at a 0.0005% interest rate, he'll be - -- underwater. Note: with a reserve rate of zero, that - -- interest will be paid back to himself as supply - -- but that will be discounted by 50% by the collateral factor. - -- Thus, we will need to accumulate for twice as many blocks - -- to end up where we'd usually be underwater - FastForward 200000000 Blocks -- 1e18 * (1 + 200000000 * 0.000005) - AccrueInterest cBAT -- Note: we have to accrue interest - -- since it's not automatic for liquidity - Invariant Remains (CToken cBAT BorrowBalanceStored Geoff) 1001e18 - Invariant Remains (CToken cBAT TotalBorrows) 1001e18 - Comptroller SetCollateralFactor cBAT 0 - -- Check user liquidity and verify < 0 - Invariant Remains (Comptroller Liquidity Geoff) -1001e18 - -- Okay, so we should be able to liquidate, so let's do that. - Prep Torrey 900e18 BAT cBAT - AllowFailures - Liquidate Torrey "->" Geoff 900e18 cBAT "Seizing" cBAT - Assert Revert "revert LIQUIDATE_SEIZE_TOO_MUCH" - -Test "when seize is paused" - InKindBorrow borrowAmount:1e18 borrowRate:0.000005 - Assert Equal (CToken cBAT BorrowBalance Geoff) 1e18 - Assert Equal (CToken cBAT TotalBorrows) 1e18 - Assert Equal (Erc20 BAT TokenBalance Geoff) 1e18 - Assert Equal (Erc20 BAT TokenBalance cBAT) 99e18 - Assert Equal (Comptroller Liquidity Geoff) 49e18 -- ( ( 1.0 * 100e18 * 0.5 ) - ( 1.0 * 1e18 ) ) / 1e18 - -- Prices are 1:1 (in-kind) and collateral factor is 0.5, - -- thus supplying 100e18 cBAT gives the user 50e18 - -- capacity of BAT. User only borrowed 1BAT, but after - -- a lot blocks at a 0.0005% interest rate, he'll be - -- underwater. Note: with a reserve rate of zero, that - -- interest will be paid back to himself as supply - -- but that will be discounted by 50% by the collateral factor. - -- Thus, we will need to accumulate for twice as many blocks - -- to end up where we'd usually be underwater - FastForward 20000000 Blocks -- 1e18 * (1 + 20000000 * 0.000005) - AccrueInterest cBAT -- Note: we have to accrue interest - -- since it's not automatic for liquidity - Assert Equal (CToken cBAT BorrowBalanceStored Geoff) 101e18 - Assert Equal (CToken cBAT TotalBorrows) 101e18 - -- Check user liquidity and verify < 0 - Assert Equal (Comptroller Liquidity Geoff) -1e18 - -- Okay, so we should be able to liquidate, so let's do that. - Prep Torrey 2e18 BAT cBAT - Comptroller SetPauseGuardian Coburn - From Coburn (Comptroller SetGuardianPaused "Seize" True) - AllowFailures - Liquidate Torrey "->" Geoff 2e18 cBAT "Seizing" cBAT - Assert Revert "revert seize is paused" - -- unpause and check correct values - Invariant Success - Comptroller SetGuardianPaused "Seize" False - Liquidate Torrey "->" Geoff 2e18 cBAT "Seizing" cBAT diff --git a/spec/scenario/MCDai.scen b/spec/scenario/MCDai.scen deleted file mode 100644 index 2a97cb535..000000000 --- a/spec/scenario/MCDai.scen +++ /dev/null @@ -1,168 +0,0 @@ --- Multi-collateral DAI tests --- These fork tests are very slow and highly dependent on ganache version, so we mark them pending - -Macro ForkMCD - -- Uses MakerDAO 0.2.16 Release https://changelog.makerdao.com/releases/kovan/0.2.16/index.html - Alias CTokenAdmin "0x9C1856636d78C051deAd6CAB9c5699e4E25549e9" - Alias DaiHolder "0x9Bffd1579bd6760a186fFf1A720f2a5dB35dE0f4" - Alias DaiAddress "0xc27a24e60a89a03bd2f1ffb4ea59076fd8385fe6" - Alias DaiJoinAddress "0x3a3cc501d46b84f310067ef7c5df4ae1f05810ea" - Alias PotAddress "0x1c11810b1f8551d543f33a48ba88dcb0e8002b0f" - Alias VatAddress "0x2d9fad7795f0658f5931b75845d14250aecc81ee" - Web3Fork "https://kovan.infura.io/v3/e1a5d4d2c06a4e81945fca56d0d5d8ea@14760012" (CTokenAdmin DaiHolder) - Erc20 Deploy Existing DAI DaiAddress DAI - Assert Equal (EtherBalance CTokenAdmin) 1.680448935e18 -- Ensure the fork works as expected - -Macro ForkMCD101 - -- Uses MakerDAO 1.0.1 Release https://changelog.makerdao.com/releases/kovan/1.0.1/index.html - Alias CTokenAdmin "0xA776184Fd6F545DAe5f51361dBcC9018549a9749" - Alias DaiHolder "0x72776bb917751225d24c07d0663b3780b2ada67c" - Alias DaiJoinAddress "0x5aa71a3ae1c0bd6ac27a1f28e1415fffb6f15b8c" - Alias PotAddress "0xea190dbdc7adf265260ec4da6e9675fd4f5a78bb" - Alias VatAddress "0xba987bdb501d131f766fee8180da5d81b34b69d9" - Alias JugAddress "0xcbb7718c9f39d05aeede1c472ca8bf804b2f1ead" - Web3Fork "https://kovan.infura.io/v3/e1a5d4d2c06a4e81945fca56d0d5d8ea@15090204" (CTokenAdmin DaiHolder) - -Macro DeployCDAIWithDSR - ForkMCD - NewComptroller - InterestRateModel Deploy Fixed StdInterest 0.000005 - CTokenDelegate Deploy CDaiDelegate cDaiDelegate - From CTokenAdmin (CToken Deploy CErc20Delegator cDAI cDAI (Erc20 DAI Address) (Comptroller Address) (InterestRateModel StdInterest Address) 1e9 8 CTokenAdmin (CTokenDelegate cDaiDelegate Address) (EncodeParameters ("address" "address") (DaiJoinAddress PotAddress))) - Comptroller SupportMarket cDAI - -Macro DeployCDAI - ForkMCD - NewComptroller - InterestRateModel Deploy Fixed StdInterest 0.000005 - CTokenDelegate Deploy CErc20Delegate cErc20Delegate - From CTokenAdmin (CToken Deploy CErc20Delegator cDAI cDAI (Erc20 DAI Address) (Comptroller Address) (InterestRateModel StdInterest Address) 1e9 8 CTokenAdmin (CTokenDelegate cErc20Delegate Address) "0x0") - Comptroller SupportMarket cDAI - -Macro UpgradeToDSR - CTokenDelegate Deploy CDaiDelegate cDaiDelegate - From CTokenAdmin (CToken cDAI SetImplementation (CTokenDelegate cDaiDelegate Address) True (EncodeParameters ("address" "address") (DaiJoinAddress PotAddress))) - -Macro CheckBasicMintRedeem - From DaiHolder (Erc20 DAI Transfer Jared 2e18) - From Jared (Erc20 DAI Approve (CToken cDAI Address) 2e18) - Mint Jared 1e18 cDAI - Assert Equal (Erc20 cDAI TokenBalance Jared) (Exactly 1e9) - Expect Changes (Erc20 cDAI TokenBalance Jared) -1e9 - Redeem Jared 1e9 cDAI - -Macro CheckBasicMintRedeemWithDSR - -- Note: we cannot tightly control time for evm calls in ganache, so we approximate time-based values - -- Approve and mint cDAI from DAI - From DaiHolder (Erc20 DAI Approve (CToken cDAI Address) 1e30) - Mint DaiHolder 1e18 cDAI - Assert Equal (Erc20 cDAI TokenBalance DaiHolder) (Exactly 1e9) - -- Sanity check the DSR - Assert Equal (MCD PotAt PotAddress "dsr") (Exactly 1000000000627937192491029810) - -- Check that the funds are in the pot and not the vat - Assert Approx (MCD PotAt PotAddress "pie" (CToken cDAI Address)) 999784970332262855 -- pot is a wad (1e18), check for ~ 1 DAI - Assert (MCD VatAt VatAddress "dai" (CToken cDAI Address)) LessThan 1e27 -- vat is a rad (1e45), check for ~ dust - -- Time passes - IncreaseTime 100000 - -- Check that holder earns the DSR on 1 DAI after redeeming (1 DAI * (dsr ** seconds)) - Expect Changes (Erc20 DAI TokenBalance DaiHolder) 1000006279390070400 0.0001 - Redeem DaiHolder 1e9 cDAI - -- Check that the funds are not in the pot nor the vat - -- Note: we always move a little too much into vat on transfer out, so it might be extra dusty - Assert Equal (MCD PotAt PotAddress "pie" (CToken cDAI Address)) 0 -- pot is a wad (1e18), check for ~ dust - Assert (MCD VatAt VatAddress "dai" (CToken cDAI Address)) LessThan 2e27 -- vat is a rad (1e45), check for ~ dust - -Macro CheckBasicBorrowRepayWithDSR repayAmount=1000015000000000000 - -- Note: we cannot tightly control time for evm calls in ganache, so we approximate time-based values - NewCToken BAT cBAT - Support cBAT collateralFactor:0.5 - -- Add some DAI to borrow - From DaiHolder (Erc20 DAI Approve (CToken cDAI Address) 1e30) - Mint DaiHolder 1e18 cDAI - -- Get some collateral and borrow - EnterMarkets Geoff cBAT - Prep Geoff Some BAT cBAT - Mint Geoff 100e18 cBAT - Expect Changes (Erc20 DAI TokenBalance Geoff) (Exactly 1e18) - Borrow Geoff 1e18 cDAI - -- Check that the funds are not in the pot nor the vat - -- Note: we always move a little too much into vat on transfer out, so it might be extra dusty - Assert (MCD PotAt PotAddress "pie" (CToken cDAI Address)) LessThan 5e10 -- pot is a wad (1e18), check for ~ dust + DSR - Assert (MCD VatAt VatAddress "dai" (CToken cDAI Address)) LessThan 2e27 -- vat is a rad (1e45), check for ~ dust - -- Repay the principal + interest after 3 blocks (i.e. 3 transactions since) - From DaiHolder (Erc20 DAI Transfer Geoff 1e18) - From Geoff (Erc20 DAI Approve (CToken cDAI Address) 1e30) - RepayBorrow Geoff repayAmount cDAI - Assert Equal (cToken cDAI BorrowBalance Geoff) 0 - -- Check that the funds are in the pot and not the vat - -- Note: we always move a little too much into vat on transfer out, so it might be extra dusty - Assert Approx (MCD PotAt PotAddress "pie" (CToken cDAI Address)) repayAmount -- pot is a wad (1e18), check for ~ 1 DAI + interest - Assert (MCD VatAt VatAddress "dai" (CToken cDAI Address)) LessThan 2e27 -- vat is a rad (1e45), check for ~ dust - -Pending "Basic mint and redeem cDAI2 (directly to swept DSR)" - DeployCDAIWithDSR - CheckBasicMintRedeemWithDSR - -Pending "Basic borrow and repay cDAI2 (directly to swept DSR)" - DeployCDAIWithDSR - CheckBasicBorrowRepayWithDSR - -Pending "Basic mint and redeem cDAI2 (upgrade to swept DSR)" - DeployCDAI - CheckBasicMintRedeem - UpgradeToDSR - CheckBasicMintRedeemWithDSR - -Pending "Basic borrow and repay cDAI2 (upgrade to swept DSR)" - DeployCDAI - CheckBasicMintRedeem - UpgradeToDSR - CheckBasicBorrowRepayWithDSR repayAmount:1000014999999999999 -- real block numbers can get nasty - -Pending "Mint, upgrade to DSR and then downgrade to vanilla delegate" - DeployCDAI - From DaiHolder (Erc20 DAI Approve (CToken cDAI Address) 1e18) - Mint DaiHolder 1e18 cDAI - Assert Equal (Erc20 DAI TokenBalance cDAI) 1e18 - Assert Equal (CToken cDAI Cash) 1e18 - -- Upgrade - UpgradeToDSR - Assert Equal (Erc20 DAI TokenBalance cDAI) 0 - Assert Approx (CToken cDAI Cash) 1e18 - Assert Approx (MCD PotAt PotAddress "pie" (CToken cDAI Address)) 1e18 - -- Downgrade - From CTokenAdmin (CToken cDAI SetImplementation (CTokenDelegate cErc20Delegate Address) True "0x0") - Assert Approx (Erc20 DAI TokenBalance cDAI) 1e18 - Assert Approx (CToken cDAI Cash) 1e18 - -Pending "Mint, upgrade to DSR, mint, and then reupgrade to a new cdai delegate" - DeployCDAI - From DaiHolder (Erc20 DAI Approve (CToken cDAI Address) 2e18) - Mint DaiHolder 1e18 cDAI - Assert Equal (Erc20 DAI TokenBalance cDAI) 1e18 - Assert Equal (CToken cDAI Cash) 1e18 - -- Upgrade - UpgradeToDSR - Mint DaiHolder 1e18 cDAI - Assert Equal (Erc20 DAI TokenBalance cDAI) 0 - Assert Approx (CToken cDAI Cash) 2e18 - Assert Approx (MCD PotAt PotAddress "pie" (CToken cDAI Address)) 2e18 - -- Reupgrade to a new cDaiDelegate - CTokenDelegate Deploy CDaiDelegate cDaiDelegate2 - From CTokenAdmin (CToken cDAI SetImplementation (CTokenDelegate cDaiDelegate2 Address) True (EncodeParameters ("address" "address") (DaiJoinAddress PotAddress))) - Assert Equal (Erc20 DAI TokenBalance cDAI) 0 - Assert Approx (CToken cDAI Cash) 2e18 - Assert Approx (MCD PotAt PotAddress "pie" (CToken cDAI Address)) 2e18 - -Pending "Test resigning implementation" - ForkMCD101 - UseConfigs kovan - Assert Approx (Erc20 DAI TokenBalance cDAI) 0 - Assert Equal (MCD PotAt PotAddress "pie" (CToken cDAI Address)) 137889496810499277888 - From CTokenAdmin (CToken cDAI ResignImplementation) - Assert Approx (Erc20 DAI TokenBalance cDAI) 137889496810499277888 - Assert Approx (MCD PotAt PotAddress "pie" (CToken cDAI Address)) 0 - -Pending "DAI interest rate model" - ForkMCD101 - InterestRateModel Deploy DAIInterestRateModel DSR_Kink_9000bps_Jump_12000bps_AssumedRF_500bps 120e16 90e16 PotAddress JugAddress CTokenAdmin diff --git a/spec/scenario/Mint.scen b/spec/scenario/Mint.scen deleted file mode 100644 index 3149da121..000000000 --- a/spec/scenario/Mint.scen +++ /dev/null @@ -1,114 +0,0 @@ --- Mint Tests - -Test "Mint 1 cZRX" - NewComptroller - ListedCToken ZRX cZRX initialExchangeRate:1e9 - Comptroller SetMarketSupplyCaps (cZRX) (2000e18) - Prep Geoff Some ZRX cZRX - Mint Geoff 50e18 cZRX - Assert Equal (Erc20 cZRX TokenBalance Geoff) (Exactly 50e9) - -- Assert Equal (CToken cZRX UnderlyingBalance Geoff) (Exactly 1.0e18) - -Test "Mint with insufficient allowance" - NewComptroller - ListedCToken ZRX cZRX initialExchangeRate:1e9 - Comptroller SetMarketSupplyCaps (cZRX) (2000e18) - Prep Geoff 50e18 ZRX cZRX allowanceAmount:49e18 - AllowFailures - Mint Geoff 50e18 cZRX - Assert Revert "revert Insufficient allowance" - Assert Equal (Erc20 cZRX TokenBalance Geoff) (Exactly 0e9) - -Test "Mint with insufficient balance" - NewComptroller - ListedCToken ZRX cZRX initialExchangeRate:1e9 - Comptroller SetMarketSupplyCaps (cZRX) (2000e18) - Prep Geoff 49e18 ZRX cZRX allowanceAmount:50e18 - AllowFailures - Mint Geoff 50e18 cZRX - Assert Revert "revert Insufficient balance" - Assert Equal (Erc20 cZRX TokenBalance Geoff) (Exactly 0e9) - -Test "Mint two ZRX after minting two ZRX, and then I mint two more" - NewComptroller - ListedCToken ZRX cZRX initialExchangeRate:1e9 - Comptroller SetMarketSupplyCaps (cZRX) (2000e18) - Prep Geoff Some ZRX cZRX - Mint Geoff 2e18 cZRX - Assert Equal (Erc20 cZRX TokenBalance Geoff) (Exactly 2e9) - Assert Equal (Erc20 cZRX TotalSupply) (Exactly 2e9) - Mint Geoff 2e18 cZRX - Assert Equal (Erc20 cZRX TokenBalance Geoff) (Exactly 4e9) - Assert Equal (Erc20 cZRX TotalSupply) (Exactly 4e9) - Mint Geoff 2e18 cZRX - Assert Equal (Erc20 cZRX TokenBalance Geoff) (Exactly 6e9) - Assert Equal (Erc20 cZRX TotalSupply) (Exactly 6e9) - -Test "Two users Mint" - NewComptroller - ListedCToken ZRX cZRX initialExchangeRate:1e9 - Comptroller SetMarketSupplyCaps (cZRX) (2000e18) - Prep Geoff Some ZRX cZRX - Prep Torrey Some ZRX cZRX - Mint Geoff 2e18 cZRX - Assert Equal (Erc20 cZRX TokenBalance Geoff) (Exactly 2e9) - Assert Equal (Erc20 cZRX TotalSupply) (Exactly 2e9) - Mint Torrey 2e18 cZRX - Assert Equal (Erc20 cZRX TokenBalance Geoff) (Exactly 2e9) - Assert Equal (Erc20 cZRX TokenBalance Torrey) (Exactly 2e9) - Assert Equal (Erc20 cZRX TotalSupply) (Exactly 4e9) - -Test "Mint accrues no interest without borrows" - NewComptroller - ListedCToken ZRX cZRX initialExchangeRate:1e9 - Comptroller SetMarketSupplyCaps (cZRX) (2000e18) - Prep Geoff Some ZRX cZRX - Prep Torrey Some ZRX cZRX - Mint Geoff 2e18 cZRX - Assert Equal (Erc20 cZRX TokenBalance Geoff) (Exactly 2e9) - Assert Equal (Erc20 cZRX TotalSupply) (Exactly 2e9) - FastForward 1000 Blocks - Assert Equal (Erc20 cZRX TokenBalance Geoff) (Exactly 2e9) - Assert Equal (Erc20 cZRX TotalSupply) (Exactly 2e9) - -Test "Mint transfer in fails" - NewComptroller - ListedCToken EVL cEVL tokenType:Evil - Comptroller SetMarketSupplyCaps (cEVL) (2000e18) - Prep Geoff Some EVL cEVL - Prep Torrey Some EVL cEVL - Invariant Static (Erc20 cEVL TokenBalance Geoff) - Invariant Static (Erc20 cEVL TotalSupply) - Invariant Static (Erc20 EVL TotalSupply) - AllowFailures - Mint Geoff 2e18 cEVL - Assert Revert "revert TOKEN_TRANSFER_IN_FAILED" - -Test "Denied by comptroller because unlisted" - NewComptroller - NewCToken ZRX cZRX - Comptroller SetMarketSupplyCaps (cZRX) (2000e18) - Prep Geoff Some ZRX cZRX - Prep Torrey Some ZRX cZRX - Invariant Static (Erc20 cZRX TokenBalance Geoff) - Invariant Static (Erc20 cZRX TotalSupply) - Invariant Static (Erc20 ZRX TotalSupply) - AllowFailures - Mint Geoff 2e18 cZRX - Assert RevertCustomError MintComptrollerRejection 9 - -Test "mint reverts if mint is paused" - NewComptroller - ListedCToken ZRX cZRX - Comptroller SetMarketSupplyCaps (cZRX) (2000e18) - Prep Geoff Some ZRX cZRX - Prep Torrey Some ZRX cZRX - Invariant Static (Erc20 cZRX TokenBalance Geoff) - Invariant Static (Erc20 cZRX TotalSupply) - Invariant Static (Erc20 ZRX TotalSupply) - Comptroller SetPauseGuardian Coburn - From Coburn (Comptroller SetGuardianMarketPaused cZRX "Mint" True) - AllowFailures - Mint Geoff 2e18 cZRX - Assert Revert "revert mint is paused" - Comptroller SetGuardianMarketPaused cZRX "Mint" False diff --git a/spec/scenario/MintEth.scen b/spec/scenario/MintEth.scen deleted file mode 100644 index 2039c053a..000000000 --- a/spec/scenario/MintEth.scen +++ /dev/null @@ -1,72 +0,0 @@ --- Mint Tests - -GasTest "Send Mint 1 cETH" - NewComptroller - ListedEtherTokenMinted cETH initialExchangeRate:0.005e9 - Comptroller SetMarketSupplyCaps (cETH) (2000e18) - Expect Changes (EtherBalance Geoff) -0.005e18 - Expect Changes (CToken cETH UnderlyingBalance Geoff) +0.005e18 - SendMintEth Geoff 0.005e18 cETH - Assert Equal (Erc20 cETH TokenBalance Geoff) 10e8 - Assert LastGas LessThan 1.2e5 - -GasTest "Call Mint 1 cETH" - NewComptroller - ListedEtherTokenMinted cETH initialExchangeRate:0.005e9 - Comptroller SetMarketSupplyCaps (cETH) (2000e18) - Expect Changes (EtherBalance Geoff) -0.005e18 - Expect Changes (CToken cETH UnderlyingBalance Geoff) +0.005e18 - CallMintEth Geoff 0.005e18 cETH - Assert Equal (Erc20 cETH TokenBalance Geoff) 10e8 - Assert LastGas LessThan 1.2e5 - -Test "Mint with insufficient eth balance" - NewComptroller - ListedEtherTokenMinted cETH initialExchangeRate:0.005e9 - Comptroller SetMarketSupplyCaps (cETH) (2000e18) - AllowFailures - Invariant Remains (CToken cETH UnderlyingBalance Geoff) 0e18 - Invariant Remains (Erc20 cETH TokenBalance Geoff) 0e8 - Invariant Static (EtherBalance Geoff) - CallMintEth Geoff 1e20 cETH - Assert Error "sender doesn't have enough funds to send tx. The upfront cost is" - -Test "Mint two Eth after minting two Eth, and then I mint two more" - NewComptroller - ListedEtherToken cETH initialExchangeRate:0.005e9 - Comptroller SetMarketSupplyCaps (cETH) (2000e18) - Expect Changes (EtherBalance Geoff) -0.002e18 - CallMintEth Geoff 0.002e18 cETH - Assert Equal (Erc20 cETH TokenBalance Geoff) 4e8 - Assert Equal (Erc20 cETH TotalSupply) 4e8 - Expect Changes (EtherBalance Geoff) -0.002e18 - SendMintEth Geoff 0.002e18 cETH - Assert Equal (Erc20 cETH TokenBalance Geoff) 8e8 - Assert Equal (Erc20 cETH TotalSupply) 8e8 - Expect Changes (EtherBalance Geoff) -0.002e18 - CallMintEth Geoff 0.002e18 cETH - Assert Equal (Erc20 cETH TokenBalance Geoff) 12e8 - Assert Equal (Erc20 cETH TotalSupply) 12e8 - -Test "Two users Mint" - NewComptroller - ListedEtherToken cETH initialExchangeRate:0.005e9 - Comptroller SetMarketSupplyCaps (cETH) (2000e18) - CallMintEth Geoff 0.002e18 cETH - Assert Equal (Erc20 cETH TokenBalance Geoff) 4e8 - Assert Equal (Erc20 cETH TotalSupply) 4e8 - CallMintEth Torrey 0.004e18 cETH - Assert Equal (Erc20 cETH TokenBalance Geoff) 4e8 - Assert Equal (Erc20 cETH TokenBalance Torrey) 8e8 - Assert Equal (Erc20 cETH TotalSupply) 12e8 - -Test "Mint accrues no interest without borrows" - NewComptroller - ListedEtherToken cETH initialExchangeRate:0.005e9 - Comptroller SetMarketSupplyCaps (cETH) (2000e18) - CallMintEth Geoff 0.002e18 cETH - Assert Equal (Erc20 cETH TokenBalance Geoff) 4e8 - Assert Equal (Erc20 cETH TotalSupply) 4e8 - FastForward 1000 Blocks - Assert Equal (Erc20 cETH TokenBalance Geoff) 4e8 - Assert Equal (Erc20 cETH TotalSupply) 4e8 diff --git a/spec/scenario/MintWBTC.scen b/spec/scenario/MintWBTC.scen deleted file mode 100644 index 4279889b9..000000000 --- a/spec/scenario/MintWBTC.scen +++ /dev/null @@ -1,101 +0,0 @@ --- Mint Tests - -Test "Mint 1 cWBTC" - NewComptroller - ListedCToken WBTC cWBTC initialExchangeRate:0.2 tokenType:WBTC - Comptroller SetMarketSupplyCaps (cWBTC) (2000e18) - Prep Geoff Some WBTC cWBTC - Mint Geoff 10e8 cWBTC - Assert Equal (Erc20 cWBTC TokenBalance Geoff) (Exactly 50e8) - Assert Equal (CToken cWBTC UnderlyingBalance Geoff) (Exactly 10e8) - -Test "Mint WBTC with insufficient allowance" - NewComptroller - ListedCToken WBTC cWBTC initialExchangeRate:0.2 tokenType:WBTC - Comptroller SetMarketSupplyCaps (cWBTC) (2000e18) - Prep Geoff 5e8 WBTC cWBTC allowanceAmount:4.9e8 - AllowFailures - Mint Geoff 5e8 cWBTC - --wbtc does not revert with reason in transfer from - Assert Revert "revert" - Assert Equal (Erc20 cWBTC TokenBalance Geoff) (Exactly 0e8) - -Test "Mint WBTC with insufficient balance" - NewComptroller - ListedCToken WBTC cWBTC initialExchangeRate:0.2 tokenType:WBTC - Comptroller SetMarketSupplyCaps (cWBTC) (2000e18) - Prep Geoff 4.9e8 WBTC cWBTC allowanceAmount:5e8 - AllowFailures - Mint Geoff 5e8 cWBTC - --wbtc does not revert with reason in transfer from - Assert Revert "revert" - Assert Equal (Erc20 cWBTC TokenBalance Geoff) (Exactly 0e8) - -Test "Mint two WBTC after minting two WBTC, and then I mint two more" - NewComptroller - ListedCToken WBTC cWBTC initialExchangeRate:0.2 tokenType:WBTC - Comptroller SetMarketSupplyCaps (cWBTC) (2000e18) - Prep Geoff Some WBTC cWBTC - Mint Geoff 2e8 cWBTC - Assert Equal (Erc20 cWBTC TokenBalance Geoff) (Exactly 10e8) - Assert Equal (Erc20 cWBTC TotalSupply) (Exactly 10e8) - Mint Geoff 2e8 cWBTC - Assert Equal (Erc20 cWBTC TokenBalance Geoff) (Exactly 20e8) - Assert Equal (Erc20 cWBTC TotalSupply) (Exactly 20e8) - Mint Geoff 2e8 cWBTC - Assert Equal (Erc20 cWBTC TokenBalance Geoff) (Exactly 30e8) - Assert Equal (Erc20 cWBTC TotalSupply) (Exactly 30e8) - -Test "Two users Mint WBTC" - NewComptroller - ListedCToken WBTC cWBTC initialExchangeRate:0.2 tokenType:WBTC - Comptroller SetMarketSupplyCaps (cWBTC) (2000e18) - Prep Geoff Some WBTC cWBTC - Prep Torrey Some WBTC cWBTC - Mint Geoff 2e8 cWBTC - Assert Equal (Erc20 cWBTC TokenBalance Geoff) (Exactly 10e8) - Assert Equal (Erc20 cWBTC TotalSupply) (Exactly 10e8) - Mint Torrey 2e8 cWBTC - Assert Equal (Erc20 cWBTC TokenBalance Geoff) (Exactly 10e8) - Assert Equal (Erc20 cWBTC TokenBalance Torrey) (Exactly 10e8) - Assert Equal (Erc20 cWBTC TotalSupply) (Exactly 20e8) - -Test "Mint WBTC accrues no interest without borrows" - NewComptroller - ListedCToken WBTC cWBTC initialExchangeRate:0.2 tokenType:WBTC - Comptroller SetMarketSupplyCaps (cWBTC) (2000e18) - Prep Geoff Some WBTC cWBTC - Prep Torrey Some WBTC cWBTC - Mint Geoff 2e8 cWBTC - Assert Equal (Erc20 cWBTC TokenBalance Geoff) (Exactly 10e8) - Assert Equal (Erc20 cWBTC TotalSupply) (Exactly 10e8) - FastForward 1000 Blocks - Assert Equal (Erc20 cWBTC TokenBalance Geoff) (Exactly 10e8) - Assert Equal (Erc20 cWBTC TotalSupply) (Exactly 10e8) - -Test "Mint WBTC transfer in fails due to paused" - NewComptroller - ListedCToken WBTC cWBTC initialExchangeRate:0.2 tokenType:WBTC - Comptroller SetMarketSupplyCaps (cWBTC) (2000e18) - Prep Geoff Some WBTC cWBTC - Prep Torrey Some WBTC cWBTC - Invariant Static (Erc20 cWBTC TokenBalance Geoff) - Invariant Static (Erc20 cWBTC TotalSupply) - Invariant Static (Erc20 WBTC TotalSupply) - Erc20 WBTC Pause - AllowFailures - Mint Geoff 2e8 cWBTC - Assert Revert - -Test "Denied by comptroller because WBTC unlisted" - NewComptroller - NewCToken WBTC cWBTC tokenType:WBTC - Comptroller SetMarketSupplyCaps (cWBTC) (2000e18) - Prep Geoff Some WBTC cWBTC - Prep Torrey Some WBTC cWBTC - Invariant Static (Erc20 cWBTC TokenBalance Geoff) - Invariant Static (Erc20 cWBTC TotalSupply) - Invariant Static (Erc20 WBTC TotalSupply) - AllowFailures - Mint Geoff 2e8 cWBTC - Assert RevertCustomError MintComptrollerRejection 9 diff --git a/spec/scenario/PriceOracleProxy.scen b/spec/scenario/PriceOracleProxy.scen deleted file mode 100644 index 600d0536a..000000000 --- a/spec/scenario/PriceOracleProxy.scen +++ /dev/null @@ -1,53 +0,0 @@ -Macro SetupPriceOracleProxy - Unitroller Deploy - PriceOracle Deploy Simple - -- Update to G1 - ComptrollerImpl Deploy ScenarioG1 ScenComptrollerG1 - Unitroller SetPendingImpl ScenComptrollerG1 - PriceOracleProxy Deploy Admin (PriceOracle Address) (Address Zero) (Address Zero) (Address Zero) (Address Zero) (Address Zero) - ComptrollerImpl ScenComptrollerG1 BecomeG1 (PriceOracleProxy Address) 0.1 20 - -- Update to G2 - ComptrollerImpl Deploy StandardG2 ComptrollerG2 - Unitroller SetPendingImpl ComptrollerG2 - ComptrollerImpl ComptrollerG2 BecomeG2 - -- Update to G3 - ComptrollerImpl Deploy StandardG3 ComptrollerG3 - Unitroller SetPendingImpl ComptrollerG3 - ComptrollerImpl ComptrollerG3 BecomeG3 1e18 [] - -- Update to G* - ComptrollerImpl Deploy Scenario ScenComptroller - Unitroller SetPendingImpl ScenComptroller - ComptrollerImpl ScenComptroller Become - NewEtherToken cETH - NewCToken USDC cUSDC - NewCToken SAI cSAI - NewCToken DAI cDAI - NewCToken USDT cUSDT - Comptroller SupportMarket cETH - Comptroller SupportMarket cUSDC - Comptroller SupportMarket cSAI - Comptroller SupportMarket cDAI - Comptroller SupportMarket cUSDT - PriceOracleProxy Deploy Admin (PriceOracle Address) (Address cETH) (Address cUSDC) (Address cSAI) (Address cDAI) (Address cUSDT) - Comptroller SetPriceOracle (PriceOracleProxy Address) - -Test "uses address(2) for dai and address(1) for usdc" - SetupPriceOracleProxy - PriceOracle SetDirectPrice (Address 0x0000000000000000000000000000000000000001) 5740564708.572881 - PriceOracle SetDirectPrice (Address 0x0000000000000000000000000000000000000002) 0.005842307360923634 - Assert Equal (PriceOracleProxy Price cUSDC) 5740564708572881000000000000 - Assert Equal (PriceOracleProxy Price cDAI) 5842307360923634 - -Test "sai price is dai price until set" - SetupPriceOracleProxy - PriceOracle SetDirectPrice (Address 0x0000000000000000000000000000000000000002) 0.005842307360923634 - Assert Equal (PriceOracleProxy Price cSAI) 5842307360923634 - PriceOracleProxy SetSaiPrice 0.006842307360923634 - Assert Equal (PriceOracleProxy Price cSAI) 6842307360923634 - -Test "gets tether and usdc prices" - SetupPriceOracleProxy - PriceOracle SetDirectPrice (Address 0x0000000000000000000000000000000000000001) 5740564708.572881 - -- scaled to 1e30 bc both tokens have 6 decimals - Assert Equal (PriceOracleProxy Price cUSDT) 5740564708572881000000000000 - Assert Equal (PriceOracleProxy Price cUSDC) 5740564708572881000000000000 diff --git a/spec/scenario/ReEntry.scen b/spec/scenario/ReEntry.scen deleted file mode 100644 index 5aab1c41c..000000000 --- a/spec/scenario/ReEntry.scen +++ /dev/null @@ -1,13 +0,0 @@ - -Test "ReEntry Mint @no-cov" - NewComptroller - Erc20 Deploy ReEntrant PHREAK PHREAK "transferFrom" "mint(uint256)" "0" - InterestRateModel Deploy Fixed Std 0.000001 - CToken Deploy Scenario cPHREAK cPHREAK (Erc20 PHREAK Address) (Comptroller Address) (InterestRateModel Std Address) 1e9 8 Admin - Comptroller SetMarketSupplyCaps (cPHREAK) (2e30) - Comptroller SupportMarket cPHREAK - Prep Geoff Some PHREAK cPHREAK - AllowFailures - Mint Geoff 50e18 cPHREAK - Assert Revert "revert re-entered" - Assert Equal (Erc20 cPHREAK TokenBalance Geoff) Zero diff --git a/spec/scenario/Redeem.scen b/spec/scenario/Redeem.scen deleted file mode 100644 index 3f74e680d..000000000 --- a/spec/scenario/Redeem.scen +++ /dev/null @@ -1,239 +0,0 @@ --- Redeem Tests - -Test "Mint then Redeem All" - NewComptroller - ListedCToken ZRX cZRX initialExchangeRate:1e9 - Comptroller SetMarketSupplyCaps (cZRX) (2000e18) - Prep Geoff 70e18 ZRX cZRX - Mint Geoff 50e18 cZRX - -- Check current affairs - Assert Equal (Erc20 cZRX TokenBalance Geoff) 500e8 - Assert Equal (Erc20 ZRX TokenBalance Geoff) 20e18 - -- Any other good invariants? - Invariant Static (CToken cZRX ExchangeRateStored) - -- Now redeem after some time - FastForward 2 Blocks - Redeem Geoff 500e8 cZRX - Assert Equal (Erc20 cZRX TokenBalance Geoff) Zero - Assert Equal (Erc20 ZRX TokenBalance Geoff) 70e18 - -Test "Mint, Enter and then Redeem All" - NewComptroller - ListedCToken ZRX cZRX initialExchangeRate:1e9 - Comptroller SetMarketSupplyCaps (cZRX) (2000e18) - Prep Geoff 70e18 ZRX cZRX - Mint Geoff 50e18 cZRX - -- Check current affairs - Assert Equal (Erc20 cZRX TokenBalance Geoff) 500e8 - Assert Equal (Erc20 ZRX TokenBalance Geoff) 20e18 - -- Any other good invariants? - Invariant Static (CToken cZRX ExchangeRateStored) - -- Now redeem after some time - FastForward 2 Blocks - EnterMarkets Geoff cZRX - Redeem Geoff 500e8 cZRX - Assert Equal (Erc20 cZRX TokenBalance Geoff) Zero - Assert Equal (Erc20 ZRX TokenBalance Geoff) 70e18 - -Test "Mint then Redeem Part" - NewComptroller - ListedCToken ZRX cZRX initialExchangeRate:1e9 - Comptroller SetMarketSupplyCaps (cZRX) (2000e18) - Prep Geoff 70e18 ZRX cZRX - Mint Geoff 50e18 cZRX - -- Check current affairs - Assert Equal (Erc20 cZRX TokenBalance Geoff) 500e8 - Assert Equal (Erc20 ZRX TokenBalance Geoff) 20e18 - -- Any other good invariants? - Invariant Static (CToken cZRX ExchangeRateStored) - -- Now redeem after some time - FastForward 2 Blocks - Redeem Geoff 250e8 cZRX - Assert Equal (Erc20 cZRX TokenBalance Geoff) 250e8 - Assert Equal (Erc20 ZRX TokenBalance Geoff) 45e18 - -Test "Mint then Redeem Too Much" - NewComptroller - ListedCToken ZRX cZRX initialExchangeRate:1e9 - Comptroller SetMarketSupplyCaps (cZRX) (2000e18) - Prep Geoff 70e18 ZRX cZRX - Mint Geoff 50e18 cZRX - -- Check and hold static - Invariant Static (CToken cZRX ExchangeRateStored) - Invariant Remains (Erc20 cZRX TokenBalance Geoff) 500e8 - Invariant Remains (Erc20 ZRX TokenBalance Geoff) 20e18 - -- Now redeem after some time - FastForward 2 Blocks - AllowFailures - Redeem Geoff 501e8 cZRX - Assert Revert - -Test "Mint then Redeem Zero" - NewComptroller - ListedCToken ZRX cZRX initialExchangeRate:1e9 - Comptroller SetMarketSupplyCaps (cZRX) (2000e18) - Prep Geoff 70e18 ZRX cZRX - Mint Geoff 50e18 cZRX - -- Check current affairs - Assert Equal (Erc20 cZRX TokenBalance Geoff) 500e8 - Assert Equal (Erc20 ZRX TokenBalance Geoff) 20e18 - -- Any other good invariants? - Invariant Static (CToken cZRX ExchangeRateStored) - -- Now redeem after some time - FastForward 2 Blocks - Redeem Geoff 0e18 cZRX - Assert Equal (Erc20 cZRX TokenBalance Geoff) 500e8 - Assert Equal (Erc20 ZRX TokenBalance Geoff) 20e18 - -Test "Mint then redeem with interest - no reserves" - NewComptroller - ListedCToken ZRX cZRX initialExchangeRate:1e9 - Comptroller SetMarketSupplyCaps (cZRX) (2000e18) - Invariant Remains (CToken cZRX Reserves) Zero - Prep Geoff 50e18 ZRX cZRX - Mint Geoff 50e18 cZRX - Assert Equal (Erc20 cZRX TokenBalance Geoff) 500e8 - Assert Equal (CToken cZRX UnderlyingBalance Geoff) 50e18 - Assert Equal (CToken cZRX ExchangeRate) 1e9 - -- Get some brah to borrow then repay - BorrowAndRepayWithInterest ZRX cZRX 10e18 5e18 interestRate:0.000001 blocks:500000 - -- We've accrued .001% interest for 500000 blocks, or 50% of the principal, - -- thus, we should have accrued 5e18 of interest for the protocol - -- This is due pro-rata to all suppliers, but we just have one, so - -- let's check that account is given correct new balance. - Assert Equal (Erc20 cZRX TokenBalance Geoff) 500e8 - Assert Equal (CToken cZRX UnderlyingBalance Geoff) 55e18 - Assert Equal (CToken cZRX ExchangeRate) 1.1e9 - -- Now redeem all with interest - Redeem Geoff 500e8 cZRX - Assert Equal (Erc20 ZRX TokenBalance Geoff) 55e18 - Assert Equal (Erc20 ZRX TokenBalance cZRX) 0e18 - Assert Equal (Erc20 cZRX TokenBalance Geoff) 0e8 - Assert Equal (CToken cZRX UnderlyingBalance Geoff) 0e18 - Assert Equal (CToken cZRX ExchangeRate) 1e9 - -Test "Mint then redeem part with interest - no reserves" - NewComptroller - ListedCToken ZRX cZRX initialExchangeRate:1e9 - Comptroller SetMarketSupplyCaps (cZRX) (2000e18) - Invariant Remains (CToken cZRX Reserves) Zero - Prep Geoff 50e18 ZRX cZRX - Mint Geoff 50e18 cZRX - Assert Equal (Erc20 cZRX TokenBalance Geoff) 500e8 - Assert Equal (CToken cZRX UnderlyingBalance Geoff) 50e18 - Assert Equal (CToken cZRX ExchangeRate) 1e9 - -- Get some brah to borrow then repay - BorrowAndRepayWithInterest ZRX cZRX 10e18 5e18 interestRate:0.000001 blocks:500000 - -- We've accrued .001% interest for 500000 blocks, or 50% of the principal, - -- thus, we should have accrued 5e18 of interest for the protocol - -- This is due pro-rata to all suppliers, but we just have one, so - -- let's check that account is given correct new balance. - Assert Equal (Erc20 cZRX TokenBalance Geoff) 500e8 - Assert Equal (CToken cZRX UnderlyingBalance Geoff) 55e18 - Assert Equal (CToken cZRX ExchangeRate) 1.1e9 - -- Now redeem all with interest - Redeem Geoff 499e8 cZRX - Assert Equal (Erc20 cZRX TokenBalance Geoff) 1e8 - Assert Equal (CToken cZRX UnderlyingBalance Geoff) 0.11e18 - Assert Equal (CToken cZRX ExchangeRate) 1.1e9 - -Test "Mint then redeem with reserves and interest" - NewComptroller - ListedCToken ZRX cZRX initialExchangeRate:1e9 - Comptroller SetMarketSupplyCaps (cZRX) (2000e18) - Prep Geoff 50e18 ZRX cZRX - Mint Geoff 50e18 cZRX - Assert Equal (Erc20 cZRX TokenBalance Geoff) 500e8 - Assert Equal (CToken cZRX UnderlyingBalance Geoff) 50e18 - Assert Equal (CToken cZRX ExchangeRate) 1e9 - -- Get some brah to borrow then repay - BorrowAndRepayWithInterest ZRX cZRX 10e18 5e18 interestRate:0.000001 blocks:500000 reserveRate:0.2 - -- We've accrued .001% interest for 500000 blocks, or 50% of the principal, - -- thus, we should have accrued 5e18 of interest for the protocol - -- The reserves should get 20% of this, or 1e18, and the rest - -- is due pro-rata to all holders. We just have one, so - -- let's check that account is given correct new balance. - Assert Equal (Erc20 cZRX TokenBalance Geoff) 500e8 - Assert Equal (CToken cZRX Reserves) 1e18 - Assert Equal (CToken cZRX UnderlyingBalance Geoff) 54e18 - -- 55e18 + 0e18 - 1e18 / 500 - Assert Equal (CToken cZRX ExchangeRate) 1.08e9 - -- Now redeem all with interest - Redeem Geoff 500e8 cZRX - Assert Equal (Erc20 ZRX TokenBalance Geoff) 54e18 - Assert Equal (Erc20 ZRX TokenBalance cZRX) 1e18 - Assert Equal (Erc20 cZRX TokenBalance Geoff) 0e8 - Assert Equal (CToken cZRX Reserves) 1e18 - Assert Equal (CToken cZRX UnderlyingBalance Geoff) 0e18 - Assert Equal (CToken cZRX ExchangeRate) 1e9 - -Test "Two users Mint, one redeems" - NewComptroller - ListedCToken ZRX cZRX initialExchangeRate:1e9 - Comptroller SetMarketSupplyCaps (cZRX) (2000e18) - Prep Geoff Some ZRX cZRX - Prep Torrey Some ZRX cZRX - Mint Geoff 2e18 cZRX - Assert Equal (Erc20 cZRX TokenBalance Geoff) 20e8 - Assert Equal (Erc20 cZRX TotalSupply) 20e8 - Mint Torrey 2e18 cZRX - Assert Equal (Erc20 cZRX TokenBalance Geoff) 20e8 - Assert Equal (Erc20 cZRX TokenBalance Torrey) 20e8 - Assert Equal (Erc20 cZRX TotalSupply) 40e8 - Redeem Torrey 10e8 cZRX - Assert Equal (Erc20 cZRX TokenBalance Geoff) 20e8 - Assert Equal (Erc20 cZRX TokenBalance Torrey) 10e8 - Assert Equal (Erc20 cZRX TotalSupply) 30e8 - -Test "Redeem transfer out fails" - NewComptroller - ListedCToken EVL cEVL initialExchangeRate:1e9 tokenType:Evil - Comptroller SetMarketSupplyCaps (cEVL) (2000e18) - Erc20 EVL SetFail False - Prep Geoff 70e18 EVL cEVL - Mint Geoff 50e18 cEVL - -- Check current affairs - Invariant Remains (Erc20 cEVL TokenBalance Geoff) 500e8 - Invariant Remains (Erc20 EVL TokenBalance Geoff) 20e18 - Invariant Static (CToken cEVL ExchangeRateStored) - -- Now redeem after some time - FastForward 2 Blocks - Erc20 EVL SetFail True - AllowFailures - Redeem Geoff 500e8 cEVL - Assert Revert "revert TOKEN_TRANSFER_OUT_FAILED" - -Test "Mint, Enter, then Redeem Too Much (collateral factor: 0)" - NewComptroller - ListedCToken ZRX cZRX initialExchangeRate:1e9 - Comptroller SetMarketSupplyCaps (cZRX) (2000e18) - Prep Geoff 70e18 ZRX cZRX - Mint Geoff 50e18 cZRX - -- Check and hold static - Invariant Static (CToken cZRX ExchangeRateStored) - Invariant Remains (Erc20 cZRX TokenBalance Geoff) 500e8 - Invariant Remains (Erc20 ZRX TokenBalance Geoff) 20e18 - -- Now redeem after some time - FastForward 2 Blocks - EnterMarkets Geoff cZRX - AllowFailures - Redeem Geoff 501e8 cZRX - Assert Revert - -Test "Mint, Enter, then Redeem Too Much (collateral factor: 0.1)" - NewComptroller - ListedCToken ZRX cZRX initialExchangeRate:1e9 - Comptroller SetMarketSupplyCaps (cZRX) (2000e18) - Comptroller SetCollateralFactor cZRX 0.1 - Prep Geoff 70e18 ZRX cZRX - Mint Geoff 50e18 cZRX - -- Check and hold static - Invariant Static (CToken cZRX ExchangeRateStored) - Invariant Remains (Erc20 cZRX TokenBalance Geoff) 500e8 - Invariant Remains (Erc20 ZRX TokenBalance Geoff) 20e18 - -- Now redeem after some time - FastForward 2 Blocks - EnterMarkets Geoff cZRX - AllowFailures - Redeem Geoff 501e8 cZRX - Assert RevertCustomError RedeemComptrollerRejection 4 diff --git a/spec/scenario/RedeemEth.scen b/spec/scenario/RedeemEth.scen deleted file mode 100644 index 49bbd9f6a..000000000 --- a/spec/scenario/RedeemEth.scen +++ /dev/null @@ -1,164 +0,0 @@ --- Redeem Tests - -Test "Mint then Redeem All" - NewComptroller - ListedEtherToken cETH initialExchangeRate:0.005e9 - Comptroller SetMarketSupplyCaps (cETH) (2000e18) - CallMintEth Geoff 0.005e18 cETH - -- Check current affairs - Assert Equal (Erc20 cETH TokenBalance Geoff) 10e8 - Assert Equal (CToken cETH UnderlyingBalance Geoff) 0.005e18 - Invariant Static (CToken cETH ExchangeRateStored) - -- Now redeem after some time - FastForward 2 Blocks - Expect Changes (EtherBalance Geoff) +0.005e18 - RedeemEth Geoff 10e8 cETH - Assert Equal (Erc20 cETH TokenBalance Geoff) Zero - Assert Equal (CToken cETH UnderlyingBalance Geoff) Zero - -Test "Mint then Redeem Part" - NewComptroller - ListedEtherToken cETH initialExchangeRate:0.005e9 - Comptroller SetMarketSupplyCaps (cETH) (2000e18) - CallMintEth Geoff 0.005e18 cETH - -- Check current affairs - Assert Equal (Erc20 cETH TokenBalance Geoff) 10e8 - Assert Equal (CToken cETH UnderlyingBalance Geoff) 0.005e18 - Invariant Static (CToken cETH ExchangeRateStored) - -- Now redeem after some time - FastForward 2 Blocks - Expect Changes (EtherBalance Geoff) +0.001e18 - RedeemEth Geoff 2e8 cETH - Assert Equal (Erc20 cETH TokenBalance Geoff) 8e8 - Assert Equal (CToken cETH UnderlyingBalance Geoff) 0.004e18 - -Test "Mint then Redeem Too Much" - NewComptroller - ListedEtherToken cETH initialExchangeRate:0.005e9 - Comptroller SetMarketSupplyCaps (cETH) (2000e18) - CallMintEth Geoff 0.005e18 cETH - AllowFailures - -- Check and hold static - Invariant Static (CToken cETH ExchangeRateStored) - Invariant Remains (Erc20 cETH TokenBalance Geoff) 10e8 - Invariant Static (EtherBalance Geoff) - -- Now redeem after some time - FastForward 2 Blocks - RedeemEth Geoff 11e8 cETH - -- TODO: This should really be REDEEM_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED, but based on - -- the order of subtractions, total supply comes before account supply. - Assert Revert - -Test "Mint then Redeem Zero" - NewComptroller - ListedEtherToken cETH initialExchangeRate:0.005e9 - Comptroller SetMarketSupplyCaps (cETH) (2000e18) - CallMintEth Geoff 0.005e18 cETH - -- Check and hold static - Invariant Static (CToken cETH ExchangeRateStored) - Invariant Remains (Erc20 cETH TokenBalance Geoff) 10e8 - Invariant Static (EtherBalance Geoff) - -- Now redeem after some time - FastForward 2 Blocks - RedeemEth Geoff 0e9 cETH - -Pending "Mint then redeem with interest - no reserves" - Invariant Success - NewComptroller - ListedCToken ZRX cETH initialExchangeRate:1e9 - Comptroller SetMarketSupplyCaps (cETH) (2000e18) - Invariant Remains (CToken cETH Reserves) Zero - Prep Geoff 50e18 ZRX cETH - Mint Geoff 50e18 cETH - Assert Equal (Erc20 cETH TokenBalance Geoff) 500e8 - Assert Equal (CToken cETH UnderlyingBalance Geoff) 50e18 - Assert Equal (CToken cETH ExchangeRate) 1e9 - -- Get some brah to borrow then repay - BorrowAndRepayWithInterest ZRX cETH 10e18 5e18 interestRate:0.0001 blocks:5000 - -- We've accrued 10% interest for 5 blocks, or 50% of the amount, - -- thus, we should have accrued 5e18 of interest for the protocol - -- This is due pro-rata to all holders, but we just have one, so - -- let's check that account is given correct new balance. - Assert Equal (Erc20 cETH TokenBalance Geoff) 500e8 - Assert Equal (CToken cETH UnderlyingBalance Geoff) 55e18 - Assert Equal (CToken cETH ExchangeRate) 1.1e9 - -- Now redeem all with interest - Redeem Geoff 500e8 cETH - Assert Equal (Erc20 ZRX TokenBalance Geoff) 55e18 - Assert Equal (Erc20 ZRX TokenBalance cETH) 0e18 - Assert Equal (Erc20 cETH TokenBalance Geoff) 0e8 - Assert Equal (CToken cETH UnderlyingBalance Geoff) 0e18 - Assert Equal (CToken cETH ExchangeRate) 1e9 - -Pending "Mint then redeem part with interest - no reserves" - Invariant Success - NewComptroller - ListedCToken ZRX cETH initialExchangeRate:1e9 - Comptroller SetMarketSupplyCaps (cETH) (2000e18) - Invariant Remains (CToken cETH Reserves) Zero - Prep Geoff 50e18 ZRX cETH - Mint Geoff 50e18 cETH - Assert Equal (Erc20 cETH TokenBalance Geoff) 500e8 - Assert Equal (CToken cETH UnderlyingBalance Geoff) 50e18 - Assert Equal (CToken cETH ExchangeRate) 1e9 - -- Get some brah to borrow then repay - BorrowAndRepayWithInterest ZRX cETH 10e18 5e18 interestRate:0.0001 blocks:5000 - -- We've accrued 10% interest for 5 blocks, or 50% of the amount, - -- thus, we should have accrued 5e18 of interest for the protocol - -- This is due pro-rata to all holders, but we just have one, so - -- let's check that account is given correct new balance. - Assert Equal (Erc20 cETH TokenBalance Geoff) 500e8 - Assert Equal (CToken cETH UnderlyingBalance Geoff) 55e18 - Assert Equal (CToken cETH ExchangeRate) 1.1e9 - -- Now redeem all with interest - Redeem Geoff 499e8 cETH - Assert Equal (Erc20 cETH TokenBalance Geoff) 1e8 - Assert Equal (CToken cETH UnderlyingBalance Geoff) 0.11e18 - Assert Equal (CToken cETH ExchangeRate) 1.1e9 - -Pending "Mint then redeem with reserves and interest" - Invariant Success - NewComptroller - ListedCToken ZRX cETH initialExchangeRate:1e9 - Comptroller SetMarketSupplyCaps (cETH) (2000e18) - Prep Geoff 50e18 ZRX cETH - Mint Geoff 50e18 cETH - Assert Equal (Erc20 cETH TokenBalance Geoff) 500e8 - Assert Equal (CToken cETH UnderlyingBalance Geoff) 50e18 - Assert Equal (CToken cETH ExchangeRate) 1e9 - -- Get some brah to borrow then repay - BorrowAndRepayWithInterest ZRX cETH 10e18 5e18 interestRate:0.0001 blocks:5000 reserveRate:0.2 - -- We've accrued 10% interest for 5 blocks, or 50% of the amount, - -- thus, we should have accrued 5e18 of interest for the protocol - -- The reserves should get 20% of this, or 1e18, and the rest - -- is due pro-rata to all holders. We just have one, so - -- let's check that account is given correct new balance. - Assert Equal (Erc20 cETH TokenBalance Geoff) 500e8 - Assert Equal (CToken cETH Reserves) 1e18 - Assert Equal (CToken cETH UnderlyingBalance Geoff) 54e18 - -- 55e18 + 0e18 - 1e18 / 500 - Assert Equal (CToken cETH ExchangeRate) 1.08e9 - -- Now redeem all with interest - Redeem Geoff 500e8 cETH - Assert Equal (Erc20 ZRX TokenBalance Geoff) 54e18 - Assert Equal (Erc20 ZRX TokenBalance cETH) 1e18 - Assert Equal (Erc20 cETH TokenBalance Geoff) 0e8 - Assert Equal (CToken cETH Reserves) 1e18 - Assert Equal (CToken cETH UnderlyingBalance Geoff) 0e18 - Assert Equal (CToken cETH ExchangeRate) 1e9 - -Test "Two users Mint, one redeems" - NewComptroller - ListedEtherToken cETH initialExchangeRate:0.005e9 - Comptroller SetMarketSupplyCaps (cETH) (2000e18) - CallMintEth Geoff 0.002e18 cETH - Assert Equal (Erc20 cETH TokenBalance Geoff) 4e8 - Assert Equal (Erc20 cETH TotalSupply) 4e8 - CallMintEth Torrey 0.004e18 cETH - Assert Equal (Erc20 cETH TokenBalance Geoff) 4e8 - Assert Equal (Erc20 cETH TokenBalance Torrey) 8e8 - Assert Equal (Erc20 cETH TotalSupply) 12e8 - RedeemEth Torrey 3e8 cETH - Assert Equal (Erc20 cETH TokenBalance Geoff) 4e8 - Assert Equal (Erc20 cETH TokenBalance Torrey) 5e8 - Assert Equal (Erc20 cETH TotalSupply) 9e8 diff --git a/spec/scenario/RedeemUnderlying.scen b/spec/scenario/RedeemUnderlying.scen deleted file mode 100644 index 028e162bf..000000000 --- a/spec/scenario/RedeemUnderlying.scen +++ /dev/null @@ -1,191 +0,0 @@ --- Redeem Tests - -Test "Mint then Redeem All" - NewComptroller - ListedCToken ZRX cZRX initialExchangeRate:1e9 - Comptroller SetMarketSupplyCaps (cZRX) (2000e18) - Prep Geoff 70e18 ZRX cZRX - Mint Geoff 50e18 cZRX - -- Check current affairs - Assert Equal (Erc20 cZRX TokenBalance Geoff) 500e8 - Assert Equal (Erc20 ZRX TokenBalance Geoff) 20e18 - -- Any other good invariants? - Invariant Static (CToken cZRX ExchangeRateStored) - -- Now redeem after some time - FastForward 2 Blocks - RedeemUnderlying Geoff 50e18 cZRX - Assert Equal (Erc20 cZRX TokenBalance Geoff) Zero - Assert Equal (Erc20 ZRX TokenBalance Geoff) 70e18 - -Test "Mint then Redeem Part" - NewComptroller - ListedCToken ZRX cZRX initialExchangeRate:1e9 - Comptroller SetMarketSupplyCaps (cZRX) (2000e18) - Prep Geoff 70e18 ZRX cZRX - Mint Geoff 50e18 cZRX - -- Check current affairs - Assert Equal (Erc20 cZRX TokenBalance Geoff) 500e8 - Assert Equal (Erc20 ZRX TokenBalance Geoff) 20e18 - -- Any other good invariants? - Invariant Static (CToken cZRX ExchangeRateStored) - -- Now redeem after some time - FastForward 2 Blocks - RedeemUnderlying Geoff 25e18 cZRX - Assert Equal (Erc20 cZRX TokenBalance Geoff) 250e8 - Assert Equal (Erc20 ZRX TokenBalance Geoff) 45e18 - -Test "Mint then Redeem Too Much" - NewComptroller - ListedCToken ZRX cZRX initialExchangeRate:1e9 - Comptroller SetMarketSupplyCaps (cZRX) (2000e18) - Prep Geoff 70e18 ZRX cZRX - Mint Geoff 50e18 cZRX - -- Check and hold static - Invariant Static (CToken cZRX ExchangeRateStored) - Invariant Remains (Erc20 cZRX TokenBalance Geoff) 500e8 - Invariant Remains (Erc20 ZRX TokenBalance Geoff) 20e18 - -- Now redeem after some time - FastForward 2 Blocks - AllowFailures - RedeemUnderlying Geoff 50.1e18 cZRX - Assert Revert - -Test "Mint then Redeem Zero" - NewComptroller - ListedCToken ZRX cZRX initialExchangeRate:1e9 - Comptroller SetMarketSupplyCaps (cZRX) (2000e18) - Prep Geoff 70e18 ZRX cZRX - Mint Geoff 50e18 cZRX - -- Check current affairs - Assert Equal (Erc20 cZRX TokenBalance Geoff) 500e8 - Assert Equal (Erc20 ZRX TokenBalance Geoff) 20e18 - -- Any other good invariants? - Invariant Static (CToken cZRX ExchangeRateStored) - -- Now redeem after some time - FastForward 2 Blocks - RedeemUnderlying Geoff 0e18 cZRX - Assert Equal (Erc20 cZRX TokenBalance Geoff) 500e8 - Assert Equal (Erc20 ZRX TokenBalance Geoff) 20e18 - -Test "Mint then redeem with interest - no reserves" - NewComptroller - ListedCToken ZRX cZRX initialExchangeRate:1e9 - Comptroller SetMarketSupplyCaps (cZRX) (2000e18) - Invariant Remains (CToken cZRX Reserves) Zero - Prep Geoff 50e18 ZRX cZRX - Mint Geoff 50e18 cZRX - Assert Equal (Erc20 cZRX TokenBalance Geoff) 500e8 - Assert Equal (CToken cZRX UnderlyingBalance Geoff) 50e18 - Assert Equal (CToken cZRX ExchangeRate) 1e9 - -- Get some brah to borrow then repay - BorrowAndRepayWithInterest ZRX cZRX 10e18 5e18 interestRate:0.000001 blocks:500000 - -- We've accrued .001% interest for 500000 blocks, or 50% of the principal, - -- thus, we should have accrued 5e18 of interest for the protocol - -- This is due pro-rata to all suppliers, but we just have one, so - -- let's check that account is given correct new balance. - Assert Equal (Erc20 cZRX TokenBalance Geoff) 500e8 - Assert Equal (CToken cZRX UnderlyingBalance Geoff) 55e18 - Assert Equal (CToken cZRX ExchangeRate) 1.1e9 - -- Now redeem all with interest - -- Exchange rate is now 55e18 ÷ 50e9 = 1.1e9 - -- 500e9 * 1.1e9 = 55e18 - RedeemUnderlying Geoff 55e18 cZRX - Assert Equal (Erc20 ZRX TokenBalance Geoff) 55e18 - Assert Equal (Erc20 ZRX TokenBalance cZRX) 0e18 - Assert Equal (Erc20 cZRX TokenBalance Geoff) 0e8 - Assert Equal (CToken cZRX UnderlyingBalance Geoff) 0e18 - Assert Equal (CToken cZRX ExchangeRate) 1e9 - -Test "Mint then redeem part with interest - no reserves" - NewComptroller - ListedCToken ZRX cZRX initialExchangeRate:1e9 - Comptroller SetMarketSupplyCaps (cZRX) (2000e18) - Invariant Remains (CToken cZRX Reserves) Zero - Prep Geoff 50e18 ZRX cZRX - Mint Geoff 50e18 cZRX - Assert Equal (Erc20 cZRX TokenBalance Geoff) 500e8 - Assert Equal (CToken cZRX UnderlyingBalance Geoff) 50e18 - Assert Equal (CToken cZRX ExchangeRate) 1e9 - -- Get some brah to borrow then repay - BorrowAndRepayWithInterest ZRX cZRX 10e18 5e18 interestRate:0.000001 blocks:500000 - -- We've accrued .001% interest for 500000 blocks, or 50% of the principal, - -- thus, we should have accrued 5e18 of interest for the protocol - -- This is due pro-rata to all suppliers, but we just have one, so - -- let's check that account is given correct new balance. - Assert Equal (Erc20 cZRX TokenBalance Geoff) 500e8 - Assert Equal (CToken cZRX UnderlyingBalance Geoff) 55e18 - Assert Equal (CToken cZRX ExchangeRate) 1.1e9 - -- Now redeem all with interest - -- Exchange rate is now 55e18 ÷ 50e9 = 1.1e9 - -- 499e9 * 1.1e9 = 54.89e18 - RedeemUnderlying Geoff 54.89e18 cZRX - Assert Equal (Erc20 cZRX TokenBalance Geoff) 1e8 - Assert Equal (CToken cZRX UnderlyingBalance Geoff) 0.11e18 - Assert Equal (CToken cZRX ExchangeRate) 1.1e9 - -Test "Mint then redeem with reserves and interest" - NewComptroller - ListedCToken ZRX cZRX initialExchangeRate:1e9 - Comptroller SetMarketSupplyCaps (cZRX) (2000e18) - Prep Geoff 50e18 ZRX cZRX - Mint Geoff 50e18 cZRX - Assert Equal (Erc20 cZRX TokenBalance Geoff) 500e8 - Assert Equal (CToken cZRX UnderlyingBalance Geoff) 50e18 - Assert Equal (CToken cZRX ExchangeRate) 1e9 - -- Get some brah to borrow then repay - BorrowAndRepayWithInterest ZRX cZRX 10e18 5e18 interestRate:0.000001 blocks:500000 reserveRate:0.2 - -- We've accrued .001% interest for 500000 blocks, or 50% of the principal, - -- thus, we should have accrued 5e18 of interest for the protocol - -- The reserves should get 20% of this, or 1e18, and the rest - -- is due pro-rata to all suppliers. We just have one, so - -- let's check that account is given correct new balance. - Assert Equal (Erc20 cZRX TokenBalance Geoff) 500e8 - Assert Equal (CToken cZRX Reserves) 1e18 - Assert Equal (CToken cZRX UnderlyingBalance Geoff) 54e18 - -- 55e18 + 0e18 - 1e18 / 500 - Assert Equal (CToken cZRX ExchangeRate) 1.08e9 - -- Now redeem all with interest - -- Exchange rate is 1.08e9 - -- 500e8 * 1.08e9 = 54e18 - RedeemUnderlying Geoff 54e18 cZRX - Assert Equal (Erc20 ZRX TokenBalance Geoff) 54e18 - Assert Equal (Erc20 ZRX TokenBalance cZRX) 1e18 - Assert Equal (Erc20 cZRX TokenBalance Geoff) 0e8 - Assert Equal (CToken cZRX Reserves) 1e18 - Assert Equal (CToken cZRX UnderlyingBalance Geoff) 0e18 - Assert Equal (CToken cZRX ExchangeRate) 1e9 - -Test "Two users Mint, one redeems" - NewComptroller - ListedCToken ZRX cZRX initialExchangeRate:1e9 - Comptroller SetMarketSupplyCaps (cZRX) (2000e18) - Prep Geoff Some ZRX cZRX - Prep Torrey Some ZRX cZRX - Mint Geoff 2e18 cZRX - Assert Equal (Erc20 cZRX TokenBalance Geoff) 20e8 - Assert Equal (Erc20 cZRX TotalSupply) 20e8 - Mint Torrey 2e18 cZRX - Assert Equal (Erc20 cZRX TokenBalance Geoff) 20e8 - Assert Equal (Erc20 cZRX TokenBalance Torrey) 20e8 - Assert Equal (Erc20 cZRX TotalSupply) 40e8 - RedeemUnderlying Torrey 1e18 cZRX - Assert Equal (Erc20 cZRX TokenBalance Geoff) 20e8 - Assert Equal (Erc20 cZRX TokenBalance Torrey) 10e8 - Assert Equal (Erc20 cZRX TotalSupply) 30e8 - -Test "Mint then Redeem 1 wei of underlying" - NewComptroller - ListedCToken ZRX cZRX initialExchangeRate:1e9 - Comptroller SetMarketSupplyCaps (cZRX) (2000e18) - Prep Geoff 70e18 ZRX cZRX - Mint Geoff 50e18 cZRX - AllowFailures - -- Check current affairs - Invariant Remains (Erc20 cZRX TokenBalance Geoff) 500e8 - Invariant Remains (Erc20 ZRX TokenBalance Geoff) 20e18 - -- Any other good invariants? - Invariant Static (CToken cZRX ExchangeRateStored) - -- Now redeem after some time - FastForward 2 Blocks - RedeemUnderlying Geoff 1 cZRX - Assert Revert "revert redeemTokens zero" diff --git a/spec/scenario/RedeemUnderlyingEth.scen b/spec/scenario/RedeemUnderlyingEth.scen deleted file mode 100644 index 260ac3640..000000000 --- a/spec/scenario/RedeemUnderlyingEth.scen +++ /dev/null @@ -1,179 +0,0 @@ --- Redeem Tests - -Test "Mint then Redeem All" - NewComptroller - ListedEtherToken cETH initialExchangeRate:0.005e9 - Comptroller SetMarketSupplyCaps (cETH) (2000e18) - CallMintEth Geoff 0.005e18 cETH - -- Check current affairs - Assert Equal (Erc20 cETH TokenBalance Geoff) 10e8 - Assert Equal (CToken cETH UnderlyingBalance Geoff) 0.005e18 - Invariant Static (CToken cETH ExchangeRateStored) - -- Now redeem after some time - FastForward 2 Blocks - Expect Changes (EtherBalance Geoff) +0.005e18 - RedeemUnderlyingEth Geoff 0.005e18 cETH - Assert Equal (Erc20 cETH TokenBalance Geoff) Zero - Assert Equal (CToken cETH UnderlyingBalance Geoff) Zero - -Test "Mint then Redeem Part" - NewComptroller - ListedEtherToken cETH initialExchangeRate:0.005e9 - Comptroller SetMarketSupplyCaps (cETH) (2000e18) - CallMintEth Geoff 0.005e18 cETH - -- Check current affairs - Assert Equal (Erc20 cETH TokenBalance Geoff) 10e8 - Assert Equal (CToken cETH UnderlyingBalance Geoff) 0.005e18 - Invariant Static (CToken cETH ExchangeRateStored) - -- Now redeem after some time - FastForward 2 Blocks - Expect Changes (EtherBalance Geoff) +0.001e18 - RedeemUnderlyingEth Geoff 0.001e18 cETH - Assert Equal (Erc20 cETH TokenBalance Geoff) 8e8 - Assert Equal (CToken cETH UnderlyingBalance Geoff) 0.004e18 - -Test "Mint then Redeem Too Much" - NewComptroller - ListedEtherToken cETH initialExchangeRate:0.005e9 - Comptroller SetMarketSupplyCaps (cETH) (2000e18) - CallMintEth Geoff 0.005e18 cETH - AllowFailures - -- Check and hold static - Invariant Static (CToken cETH ExchangeRateStored) - Invariant Remains (Erc20 cETH TokenBalance Geoff) 10e8 - Invariant Static (EtherBalance Geoff) - -- Now redeem after some time - FastForward 2 Blocks - RedeemUnderlyingEth Geoff 0.0055e18 cETH - -- TODO: This should really be REDEEM_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED, but based on - -- the order of subtractions, total supply comes before account supply. - Assert Revert - -Test "Mint then Redeem Zero" - NewComptroller - ListedEtherToken cETH initialExchangeRate:0.005e9 - Comptroller SetMarketSupplyCaps (cETH) (2000e18) - CallMintEth Geoff 0.005e18 cETH - -- Check and hold static - Invariant Static (CToken cETH ExchangeRateStored) - Invariant Remains (Erc20 cETH TokenBalance Geoff) 10e8 - Invariant Static (EtherBalance Geoff) - -- Now redeem after some time - FastForward 2 Blocks - RedeemUnderlyingEth Geoff 0e18 cETH - -Test "Mint then redeem with interest - no reserves" - Invariant Success - NewComptroller - ListedEtherToken cETH initialExchangeRate:1e9 - Comptroller SetMarketSupplyCaps (cETH) (2000e18) - Invariant Remains (CToken cETH Reserves) Zero - CallMintEth Geoff 50e18 cETH - Assert Equal (Erc20 cETH TokenBalance Geoff) 500e8 - Assert Equal (CToken cETH UnderlyingBalance Geoff) 50e18 - Assert Equal (CToken cETH ExchangeRate) 1e9 - -- Get some brah to borrow then repay - BorrowAndRepayEthWithInterest cETH 10e18 5e18 interestRate:0.000001 blocks:500000 - -- We've accrued 10% interest for 5 blocks, or 50% of the amount, - -- thus, we should have accrued 5e18 of interest for the protocol - -- This is due pro-rata to all holders, but we just have one, so - -- let's check that account is given correct new balance. - Assert Equal (Erc20 cETH TokenBalance Geoff) 500e8 - Assert Equal (CToken cETH UnderlyingBalance Geoff) 55e18 - Assert Equal (CToken cETH ExchangeRate) 1.1e9 - -- Now redeem all with interest - Expect Changes (EtherBalance Geoff) 55e18 - RedeemUnderlyingEth Geoff 55e18 cETH - Assert Equal (EtherBalance cETH) 0e18 - Assert Equal (Erc20 cETH TokenBalance Geoff) 0e8 - Assert Equal (CToken cETH UnderlyingBalance Geoff) 0e18 - Assert Equal (CToken cETH ExchangeRate) 1e9 - -Pending "Mint then redeem part with interest - no reserves" - Invariant Success - NewComptroller - ListedCToken ZRX cETH initialExchangeRate:1e9 - Comptroller SetMarketSupplyCaps (cETH) (2000e18) - Invariant Remains (CToken cETH Reserves) Zero - Prep Geoff 50e18 ZRX cETH - Mint Geoff 50e18 cETH - Assert Equal (Erc20 cETH TokenBalance Geoff) 500e8 - Assert Equal (CToken cETH UnderlyingBalance Geoff) 50e18 - Assert Equal (CToken cETH ExchangeRate) 1e9 - -- Get some brah to borrow then repay - BorrowAndRepayWithInterest ZRX cETH 10e18 5e18 interestRate:0.000001 blocks:500000 - -- We've accrued 10% interest for 5 blocks, or 50% of the amount, - -- thus, we should have accrued 5e18 of interest for the protocol - -- This is due pro-rata to all holders, but we just have one, so - -- let's check that account is given correct new balance. - Assert Equal (Erc20 cETH TokenBalance Geoff) 500e8 - Assert Equal (CToken cETH UnderlyingBalance Geoff) 55e18 - Assert Equal (CToken cETH ExchangeRate) 1.1e9 - -- Now redeem all with interest - Redeem Geoff 499e8 cETH - Assert Equal (Erc20 cETH TokenBalance Geoff) 1e8 - Assert Equal (CToken cETH UnderlyingBalance Geoff) 0.11e18 - Assert Equal (CToken cETH ExchangeRate) 1.1e9 - -Pending "Mint then redeem with reserves and interest" - Invariant Success - NewComptroller - ListedCToken ZRX cETH initialExchangeRate:1e9 - Comptroller SetMarketSupplyCaps (cETH) (2000e18) - Prep Geoff 50e18 ZRX cETH - Mint Geoff 50e18 cETH - Assert Equal (Erc20 cETH TokenBalance Geoff) 500e8 - Assert Equal (CToken cETH UnderlyingBalance Geoff) 50e18 - Assert Equal (CToken cETH ExchangeRate) 1e9 - -- Get some brah to borrow then repay - BorrowAndRepayWithInterest ZRX cETH 10e18 5e18 interestRate:0.000001 blocks:500000 reserveRate:0.2 - -- We've accrued 10% interest for 5 blocks, or 50% of the amount, - -- thus, we should have accrued 5e18 of interest for the protocol - -- The reserves should get 20% of this, or 1e18, and the rest - -- is due pro-rata to all holders. We just have one, so - -- let's check that account is given correct new balance. - Assert Equal (Erc20 cETH TokenBalance Geoff) 500e8 - Assert Equal (CToken cETH Reserves) 1e18 - Assert Equal (CToken cETH UnderlyingBalance Geoff) 54e18 - -- 55e18 + 0e18 - 1e18 / 500 - Assert Equal (CToken cETH ExchangeRate) 1.08e9 - -- Now redeem all with interest - Redeem Geoff 500e8 cETH - Assert Equal (Erc20 ZRX TokenBalance Geoff) 54e18 - Assert Equal (Erc20 ZRX TokenBalance cETH) 1e18 - Assert Equal (Erc20 cETH TokenBalance Geoff) 0e8 - Assert Equal (CToken cETH Reserves) 1e18 - Assert Equal (CToken cETH UnderlyingBalance Geoff) 0e18 - Assert Equal (CToken cETH ExchangeRate) 1e9 - -Test "Two users Mint, one redeems" - NewComptroller - ListedEtherToken cETH initialExchangeRate:0.005e9 - Comptroller SetMarketSupplyCaps (cETH) (2000e18) - CallMintEth Geoff 0.002e18 cETH - Assert Equal (Erc20 cETH TokenBalance Geoff) 4e8 - Assert Equal (Erc20 cETH TotalSupply) 4e8 - CallMintEth Torrey 0.004e18 cETH - Assert Equal (Erc20 cETH TokenBalance Geoff) 4e8 - Assert Equal (Erc20 cETH TokenBalance Torrey) 8e8 - Assert Equal (Erc20 cETH TotalSupply) 12e8 - RedeemUnderlyingEth Torrey 0.0015e18 cETH - Assert Equal (Erc20 cETH TokenBalance Geoff) 4e8 - Assert Equal (Erc20 cETH TokenBalance Torrey) 5e8 - Assert Equal (Erc20 cETH TotalSupply) 9e8 - -Test "Mint then redeem 1 wei" - NewComptroller - ListedEtherToken cETH initialExchangeRate:0.005e9 - Comptroller SetMarketSupplyCaps (cETH) (2000e18) - CallMintEth Geoff 0.005e18 cETH - AllowFailures - -- Check current affairs - Assert Equal (Erc20 cETH TokenBalance Geoff) 10e8 - Assert Equal (CToken cETH UnderlyingBalance Geoff) 0.005e18 - Invariant Static (CToken cETH ExchangeRateStored) - Invariant Static (EtherBalance Geoff) - -- Now redeem after some time - FastForward 2 Blocks - RedeemUnderlyingEth Geoff 1 cETH - Assert Revert "revert redeemTokens zero" diff --git a/spec/scenario/RedeemUnderlyingWBTC.scen b/spec/scenario/RedeemUnderlyingWBTC.scen deleted file mode 100644 index f1f275721..000000000 --- a/spec/scenario/RedeemUnderlyingWBTC.scen +++ /dev/null @@ -1,192 +0,0 @@ --- Redeem Tests - -Test "Mint then Redeem All" - NewComptroller - ListedCToken WBTC cWBTC initialExchangeRate:0.1 tokenType:WBTC - Comptroller SetMarketSupplyCaps (cWBTC) (2e30) - Prep Geoff 70e8 WBTC cWBTC - Mint Geoff 50e8 cWBTC - -- Check current affairs - Assert Equal (Erc20 cWBTC TokenBalance Geoff) 500e8 - Assert Equal (Erc20 WBTC TokenBalance Geoff) 20e8 - -- Any other good invariants? - Invariant Static (CToken cWBTC ExchangeRateStored) - -- Now redeem after some time - FastForward 2 Blocks - RedeemUnderlying Geoff 50e8 cWBTC - Assert Equal (Erc20 cWBTC TokenBalance Geoff) Zero - Assert Equal (Erc20 WBTC TokenBalance Geoff) 70e8 - -Test "Mint then Redeem Part" - NewComptroller - ListedCToken WBTC cWBTC initialExchangeRate:0.1 tokenType:WBTC - Comptroller SetMarketSupplyCaps (cWBTC) (2e30) - Prep Geoff 70e8 WBTC cWBTC - Mint Geoff 50e8 cWBTC - -- Check current affairs - Assert Equal (Erc20 cWBTC TokenBalance Geoff) 500e8 - Assert Equal (Erc20 WBTC TokenBalance Geoff) 20e8 - -- Any other good invariants? - Invariant Static (CToken cWBTC ExchangeRateStored) - -- Now redeem after some time - FastForward 2 Blocks - RedeemUnderlying Geoff 25e8 cWBTC - Assert Equal (Erc20 cWBTC TokenBalance Geoff) 250e8 - Assert Equal (Erc20 WBTC TokenBalance Geoff) 45e8 - -Test "Mint then Redeem Too Much" - NewComptroller - ListedCToken WBTC cWBTC initialExchangeRate:0.1 tokenType:WBTC - Comptroller SetMarketSupplyCaps (cWBTC) (2e30) - Prep Geoff 70e8 WBTC cWBTC - Mint Geoff 50e8 cWBTC - -- Check and hold static - Invariant Static (CToken cWBTC ExchangeRateStored) - Invariant Remains (Erc20 cWBTC TokenBalance Geoff) 500e8 - Invariant Remains (Erc20 WBTC TokenBalance Geoff) 20e8 - -- Now redeem after some time - FastForward 2 Blocks - AllowFailures - RedeemUnderlying Geoff 50.1e8 cWBTC - Assert Revert - -Test "Mint then Redeem Zero" - NewComptroller - ListedCToken WBTC cWBTC initialExchangeRate:0.1 tokenType:WBTC - Comptroller SetMarketSupplyCaps (cWBTC) (2e30) - Prep Geoff 70e8 WBTC cWBTC - Mint Geoff 50e8 cWBTC - -- Check current affairs - Assert Equal (Erc20 cWBTC TokenBalance Geoff) 500e8 - Assert Equal (Erc20 WBTC TokenBalance Geoff) 20e8 - -- Any other good invariants? - Invariant Static (CToken cWBTC ExchangeRateStored) - -- Now redeem after some time - FastForward 2 Blocks - RedeemUnderlying Geoff 0e8 cWBTC - Assert Equal (Erc20 cWBTC TokenBalance Geoff) 500e8 - Assert Equal (Erc20 WBTC TokenBalance Geoff) 20e8 - -Test "Mint then redeem with interest - no reserves" - NewComptroller - ListedCToken WBTC cWBTC initialExchangeRate:0.1 tokenType:WBTC - Comptroller SetMarketSupplyCaps (cWBTC) (2e30) - Invariant Remains (CToken cWBTC Reserves) Zero - Prep Geoff 50e8 WBTC cWBTC - Mint Geoff 50e8 cWBTC - Assert Equal (Erc20 cWBTC TokenBalance Geoff) 500e8 - Assert Equal (CToken cWBTC UnderlyingBalance Geoff) 50e8 - Assert Equal (CToken cWBTC ExchangeRate) 0.1 - -- Get some brah to borrow then repay - BorrowAndRepayWithInterest WBTC cWBTC 10e8 5e8 interestRate:0.000001 blocks:500000 - -- We've accrued .001% interest for 500000 blocks, or 50% of the principal, - -- thus, we should have accrued 5e8 of interest for the protocol - -- This is due pro-rata to all suppliers, but we just have one, so - -- let's check that account is given correct new balance. - Assert Equal (Erc20 cWBTC TokenBalance Geoff) 500e8 - Assert Equal (CToken cWBTC UnderlyingBalance Geoff) 55e8 - Assert Equal (CToken cWBTC ExchangeRate) 0.11 - -- Now redeem all with interest - -- Exchange rate is now 55e8 ÷ 50e-1 = 1.1e-1 - -- 500e-1 * 1.1e-1 = 55e8 - RedeemUnderlying Geoff 55e8 cWBTC - Assert Equal (Erc20 WBTC TokenBalance Geoff) 55e8 - Assert Equal (Erc20 WBTC TokenBalance cWBTC) 0e8 - Assert Equal (Erc20 cWBTC TokenBalance Geoff) 0e8 - Assert Equal (CToken cWBTC UnderlyingBalance Geoff) 0e8 - Assert Equal (CToken cWBTC ExchangeRate) 0.1 - -Test "Mint then redeem part with interest - no reserves" - NewComptroller - ListedCToken WBTC cWBTC initialExchangeRate:0.1 tokenType:WBTC - Comptroller SetMarketSupplyCaps (cWBTC) (2e30) - Invariant Remains (CToken cWBTC Reserves) Zero - Prep Geoff 50e8 WBTC cWBTC - Mint Geoff 50e8 cWBTC - Assert Equal (Erc20 cWBTC TokenBalance Geoff) 500e8 - Assert Equal (CToken cWBTC UnderlyingBalance Geoff) 50e8 - Assert Equal (CToken cWBTC ExchangeRate) 0.1 - -- Get some brah to borrow then repay - BorrowAndRepayWithInterest WBTC cWBTC 10e8 5e8 interestRate:0.000001 blocks:500000 - -- We've accrued .001% interest for 500000 blocks, or 50% of the principal, - -- thus, we should have accrued 5e8 of interest for the protocol - -- This is due pro-rata to all suppliers, but we just have one, so - -- let's check that account is given correct new balance. - Assert Equal (Erc20 cWBTC TokenBalance Geoff) 500e8 - Assert Equal (CToken cWBTC UnderlyingBalance Geoff) 55e8 - Assert Equal (CToken cWBTC ExchangeRate) 0.11 - -- Now redeem all with interest - -- Exchange rate is now 55e8 ÷ 50e-1 = 1.1e-1 - -- 499e-1 * 1.1e-1 = 54.89e8 - RedeemUnderlying Geoff 54.89e8 cWBTC - Assert Equal (Erc20 cWBTC TokenBalance Geoff) 1e8 - Assert Equal (CToken cWBTC UnderlyingBalance Geoff) 0.11e8 - Assert Equal (CToken cWBTC ExchangeRate) 0.11 - -Test "Mint then redeem with reserves and interest" - NewComptroller - ListedCToken WBTC cWBTC initialExchangeRate:0.1 tokenType:WBTC - Comptroller SetMarketSupplyCaps (cWBTC) (2e30) - Prep Geoff 50e8 WBTC cWBTC - Mint Geoff 50e8 cWBTC - Assert Equal (Erc20 cWBTC TokenBalance Geoff) 500e8 - Assert Equal (CToken cWBTC UnderlyingBalance Geoff) 50e8 - Assert Equal (CToken cWBTC ExchangeRate) 0.1 - -- Get some brah to borrow then repay - BorrowAndRepayWithInterest WBTC cWBTC 10e8 5e8 interestRate:0.000001 blocks:500000 reserveRate:0.2 - -- We've accrued .001% interest for 500000 blocks, or 50% of the principal, - -- thus, we should have accrued 5e8 of interest for the protocol - -- The reserves should get 20% of this, or 1e8, and the rest - -- is due pro-rata to all suppliers. We just have one, so - -- let's check that account is given correct new balance. - Assert Equal (Erc20 cWBTC TokenBalance Geoff) 500e8 - Assert Equal (CToken cWBTC Reserves) 1e8 - Assert Equal (CToken cWBTC UnderlyingBalance Geoff) 54e8 - -- 55e8 + 0e8 - 1e8 / 500 - Assert Equal (CToken cWBTC ExchangeRate) 0.108 - -- Now redeem all with interest - -- Exchange rate is 1.08e-1 - -- 500e8 * 1.08e-1 = 54e8 - RedeemUnderlying Geoff 54e8 cWBTC - Assert Equal (Erc20 WBTC TokenBalance Geoff) 54e8 - Assert Equal (Erc20 WBTC TokenBalance cWBTC) 1e8 - Assert Equal (Erc20 cWBTC TokenBalance Geoff) 0e8 - Assert Equal (CToken cWBTC Reserves) 1e8 - Assert Equal (CToken cWBTC UnderlyingBalance Geoff) 0e8 - Assert Equal (CToken cWBTC ExchangeRate) 0.1 - -Test "Two users Mint, one redeems" - NewComptroller - ListedCToken WBTC cWBTC initialExchangeRate:0.1 tokenType:WBTC - Comptroller SetMarketSupplyCaps (cWBTC) (2e30) - Prep Geoff Some WBTC cWBTC - Prep Torrey Some WBTC cWBTC - Mint Geoff 2e8 cWBTC - Assert Equal (Erc20 cWBTC TokenBalance Geoff) 20e8 - Assert Equal (Erc20 cWBTC TotalSupply) 20e8 - Mint Torrey 2e8 cWBTC - Assert Equal (Erc20 cWBTC TokenBalance Geoff) 20e8 - Assert Equal (Erc20 cWBTC TokenBalance Torrey) 20e8 - Assert Equal (Erc20 cWBTC TotalSupply) 40e8 - RedeemUnderlying Torrey 1e8 cWBTC - Assert Equal (Erc20 cWBTC TokenBalance Geoff) 20e8 - Assert Equal (Erc20 cWBTC TokenBalance Torrey) 10e8 - Assert Equal (Erc20 cWBTC TotalSupply) 30e8 - -Test "Mint then Redeem 1 wei of underlying is allowed for 1:1 assets" - NewComptroller - ListedCToken WBTC cWBTC initialExchangeRate:0.1 tokenType:WBTC - Comptroller SetMarketSupplyCaps (cWBTC) (2e30) - Prep Geoff 70e8 WBTC cWBTC - Mint Geoff 50e8 cWBTC - -- Check current affairs - Assert Equal (Erc20 cWBTC TokenBalance Geoff) 500e8 - Assert Equal (Erc20 WBTC TokenBalance Geoff) 20e8 - -- Any other good invariants? - Invariant Static (CToken cWBTC ExchangeRateStored) - -- Now redeem after some time - FastForward 2 Blocks - RedeemUnderlying Geoff 1 cWBTC - -- After affairs - Assert Equal (Erc20 cWBTC TokenBalance Geoff) 49999999990 - Assert Equal (Erc20 WBTC TokenBalance Geoff) 2000000001 diff --git a/spec/scenario/RedeemWBTC.scen b/spec/scenario/RedeemWBTC.scen deleted file mode 100644 index 6884ef733..000000000 --- a/spec/scenario/RedeemWBTC.scen +++ /dev/null @@ -1,238 +0,0 @@ --- Redeem Tests - -Test "Mint WBTC then Redeem All" - NewComptroller - ListedCToken WBTC cWBTC initialExchangeRate:0.1 tokenType:WBTC - Comptroller SetMarketSupplyCaps (cWBTC) (2e30) - Prep Geoff 70e8 WBTC cWBTC - Mint Geoff 50e8 cWBTC - -- Check current affairs - Assert Equal (Erc20 cWBTC TokenBalance Geoff) 500e8 - Assert Equal (Erc20 WBTC TokenBalance Geoff) 20e8 - -- Any other good invariants? - Invariant Static (CToken cWBTC ExchangeRateStored) - -- Now redeem after some time - FastForward 2 Blocks - Redeem Geoff 500e8 cWBTC - Assert Equal (Erc20 cWBTC TokenBalance Geoff) Zero - Assert Equal (Erc20 WBTC TokenBalance Geoff) 70e8 - -Test "Mint WBTC, Enter and then Redeem All" - NewComptroller - ListedCToken WBTC cWBTC initialExchangeRate:0.1 tokenType:WBTC - Comptroller SetMarketSupplyCaps (cWBTC) (2e30) - Prep Geoff 70e8 WBTC cWBTC - Mint Geoff 50e8 cWBTC - -- Check current affairs - Assert Equal (Erc20 cWBTC TokenBalance Geoff) 500e8 - Assert Equal (Erc20 WBTC TokenBalance Geoff) 20e8 - -- Any other good invariants? - Invariant Static (CToken cWBTC ExchangeRateStored) - -- Now redeem after some time - FastForward 2 Blocks - EnterMarkets Geoff cWBTC - Redeem Geoff 500e8 cWBTC - Assert Equal (Erc20 cWBTC TokenBalance Geoff) Zero - Assert Equal (Erc20 WBTC TokenBalance Geoff) 70e8 - -Test "Mint WBTC then Redeem Part" - NewComptroller - ListedCToken WBTC cWBTC initialExchangeRate:0.1 tokenType:WBTC - Comptroller SetMarketSupplyCaps (cWBTC) (2e30) - Prep Geoff 70e8 WBTC cWBTC - Mint Geoff 50e8 cWBTC - -- Check current affairs - Assert Equal (Erc20 cWBTC TokenBalance Geoff) 500e8 - Assert Equal (Erc20 WBTC TokenBalance Geoff) 20e8 - -- Any other good invariants? - Invariant Static (CToken cWBTC ExchangeRateStored) - -- Now redeem after some time - FastForward 2 Blocks - Redeem Geoff 250e8 cWBTC - Assert Equal (Erc20 cWBTC TokenBalance Geoff) 250e8 - Assert Equal (Erc20 WBTC TokenBalance Geoff) 45e8 - -Test "Mint WBTC then Redeem Too Much" - NewComptroller - ListedCToken WBTC cWBTC initialExchangeRate:0.1 tokenType:WBTC - Comptroller SetMarketSupplyCaps (cWBTC) (2e30) - Prep Geoff 70e8 WBTC cWBTC - Mint Geoff 50e8 cWBTC - -- Check and hold static - Invariant Static (CToken cWBTC ExchangeRateStored) - Invariant Remains (Erc20 cWBTC TokenBalance Geoff) 500e8 - Invariant Remains (Erc20 WBTC TokenBalance Geoff) 20e8 - -- Now redeem after some time - FastForward 2 Blocks - AllowFailures - Redeem Geoff 501e8 cWBTC - Assert Revert - -Test "Mint WBTC then Redeem Zero" - NewComptroller - ListedCToken WBTC cWBTC initialExchangeRate:0.1 tokenType:WBTC - Comptroller SetMarketSupplyCaps (cWBTC) (2e30) - Prep Geoff 70e8 WBTC cWBTC - Mint Geoff 50e8 cWBTC - -- Check current affairs - Assert Equal (Erc20 cWBTC TokenBalance Geoff) 500e8 - Assert Equal (Erc20 WBTC TokenBalance Geoff) 20e8 - -- Any other good invariants? - Invariant Static (CToken cWBTC ExchangeRateStored) - -- Now redeem after some time - FastForward 2 Blocks - Redeem Geoff 0e8 cWBTC - Assert Equal (Erc20 cWBTC TokenBalance Geoff) 500e8 - Assert Equal (Erc20 WBTC TokenBalance Geoff) 20e8 - -Test "Mint WBTC then redeem with interest - no reserves" - NewComptroller - ListedCToken WBTC cWBTC initialExchangeRate:0.1 tokenType:WBTC - Comptroller SetMarketSupplyCaps (cWBTC) (2e30) - Invariant Remains (CToken cWBTC Reserves) Zero - Prep Geoff 50e8 WBTC cWBTC - Mint Geoff 50e8 cWBTC - Assert Equal (Erc20 cWBTC TokenBalance Geoff) 500e8 - Assert Equal (CToken cWBTC UnderlyingBalance Geoff) 50e8 - Assert Equal (CToken cWBTC ExchangeRate) 0.1 - -- Get some brah to borrow then repay - BorrowAndRepayWithInterest WBTC cWBTC 10e8 5e8 interestRate:0.000001 blocks:500000 - -- We've accrued .001% interest for 500000 blocks, or 50% of the principal, - -- thus, we should have accrued 5e8 of interest for the protocol - -- This is due pro-rata to all suppliers, but we just have one, so - -- let's check that account is given correct new balance. - Assert Equal (Erc20 cWBTC TokenBalance Geoff) 500e8 - Assert Equal (CToken cWBTC UnderlyingBalance Geoff) 55e8 - Assert Equal (CToken cWBTC ExchangeRate) 0.11 - -- Now redeem all with interest - Redeem Geoff 500e8 cWBTC - Assert Equal (Erc20 WBTC TokenBalance Geoff) 55e8 - Assert Equal (Erc20 WBTC TokenBalance cWBTC) 0e8 - Assert Equal (Erc20 cWBTC TokenBalance Geoff) 0e8 - Assert Equal (CToken cWBTC UnderlyingBalance Geoff) 0e8 - Assert Equal (CToken cWBTC ExchangeRate) 0.1 - -Test "Mint WBTC then redeem part with interest - no reserves" - NewComptroller - ListedCToken WBTC cWBTC initialExchangeRate:0.1 tokenType:WBTC - Comptroller SetMarketSupplyCaps (cWBTC) (2e30) - Invariant Remains (CToken cWBTC Reserves) Zero - Prep Geoff 50e8 WBTC cWBTC - Mint Geoff 50e8 cWBTC - Assert Equal (Erc20 cWBTC TokenBalance Geoff) 500e8 - Assert Equal (CToken cWBTC UnderlyingBalance Geoff) 50e8 - Assert Equal (CToken cWBTC ExchangeRate) 0.1 - -- Get some brah to borrow then repay - BorrowAndRepayWithInterest WBTC cWBTC 10e8 5e8 interestRate:0.000001 blocks:500000 - -- We've accrued .001% interest for 500000 blocks, or 50% of the principal, - -- thus, we should have accrued 5e8 of interest for the protocol - -- This is due pro-rata to all suppliers, but we just have one, so - -- let's check that account is given correct new balance. - Assert Equal (Erc20 cWBTC TokenBalance Geoff) 500e8 - Assert Equal (CToken cWBTC UnderlyingBalance Geoff) 55e8 - Assert Equal (CToken cWBTC ExchangeRate) 0.11 - -- Now redeem all with interest - Redeem Geoff 499e8 cWBTC - Assert Equal (Erc20 cWBTC TokenBalance Geoff) 1e8 - Assert Equal (CToken cWBTC UnderlyingBalance Geoff) 0.11e8 - Assert Equal (CToken cWBTC ExchangeRate) 0.11 - -Test "Mint WBTC then redeem with reserves and interest" - NewComptroller - ListedCToken WBTC cWBTC initialExchangeRate:0.1 tokenType:WBTC - Comptroller SetMarketSupplyCaps (cWBTC) (2e30) - Prep Geoff 50e8 WBTC cWBTC - Mint Geoff 50e8 cWBTC - Assert Equal (Erc20 cWBTC TokenBalance Geoff) 500e8 - Assert Equal (CToken cWBTC UnderlyingBalance Geoff) 50e8 - Assert Equal (CToken cWBTC ExchangeRate) 0.1 - -- Get some brah to borrow then repay - BorrowAndRepayWithInterest WBTC cWBTC 10e8 5e8 interestRate:0.000001 blocks:500000 reserveRate:0.2 - -- We've accrued .001% interest for 500000 blocks, or 50% of the principal, - -- thus, we should have accrued 5e8 of interest for the protocol - -- The reserves should get 20% of this, or 1e8, and the rest - -- is due pro-rata to all suppliers. We just have one, so - -- let's check that account is given correct new balance. - Assert Equal (Erc20 cWBTC TokenBalance Geoff) 500e8 - Assert Equal (CToken cWBTC Reserves) 1e8 - Assert Equal (CToken cWBTC UnderlyingBalance Geoff) 54e8 - -- 55e8 + 0e8 - 1e8 / 500 - Assert Equal (CToken cWBTC ExchangeRate) 0.108 - -- Now redeem all with interest - Redeem Geoff 500e8 cWBTC - Assert Equal (Erc20 WBTC TokenBalance Geoff) 54e8 - Assert Equal (Erc20 WBTC TokenBalance cWBTC) 1e8 - Assert Equal (Erc20 cWBTC TokenBalance Geoff) 0e8 - Assert Equal (CToken cWBTC Reserves) 1e8 - Assert Equal (CToken cWBTC UnderlyingBalance Geoff) 0e8 - Assert Equal (CToken cWBTC ExchangeRate) 0.1 - -Test "Two users Mint WBTC, one redeems" - NewComptroller - ListedCToken WBTC cWBTC initialExchangeRate:0.1 tokenType:WBTC - Comptroller SetMarketSupplyCaps (cWBTC) (2e30) - Prep Geoff Some WBTC cWBTC - Prep Torrey Some WBTC cWBTC - Mint Geoff 2e8 cWBTC - Assert Equal (Erc20 cWBTC TokenBalance Geoff) 20e8 - Assert Equal (Erc20 cWBTC TotalSupply) 20e8 - Mint Torrey 2e8 cWBTC - Assert Equal (Erc20 cWBTC TokenBalance Geoff) 20e8 - Assert Equal (Erc20 cWBTC TokenBalance Torrey) 20e8 - Assert Equal (Erc20 cWBTC TotalSupply) 40e8 - Redeem Torrey 10e8 cWBTC - Assert Equal (Erc20 cWBTC TokenBalance Geoff) 20e8 - Assert Equal (Erc20 cWBTC TokenBalance Torrey) 10e8 - Assert Equal (Erc20 cWBTC TotalSupply) 30e8 - -Test "Redeem WBTC transfer out fails" - NewComptroller - ListedCToken WBTC cWBTC initialExchangeRate:0.1 tokenType:WBTC - Comptroller SetMarketSupplyCaps (cWBTC) (2e30) - Prep Geoff 70e8 WBTC cWBTC - Mint Geoff 50e8 cWBTC - -- Check current affairs - Invariant Remains (Erc20 cWBTC TokenBalance Geoff) 500e8 - Invariant Remains (Erc20 WBTC TokenBalance Geoff) 20e8 - Invariant Static (CToken cWBTC ExchangeRateStored) - -- Now redeem after some time - FastForward 2 Blocks - Erc20 WBTC Pause - AllowFailures - Redeem Geoff 500e8 cWBTC - Assert Revert - -Test "Mint WBTC, Enter, then Redeem Too Much (collateral factor: 0)" - NewComptroller - ListedCToken WBTC cWBTC initialExchangeRate:0.1 tokenType:WBTC - Comptroller SetMarketSupplyCaps (cWBTC) (2e30) - Prep Geoff 70e8 WBTC cWBTC - Mint Geoff 50e8 cWBTC - -- Check and hold static - Invariant Static (CToken cWBTC ExchangeRateStored) - Invariant Remains (Erc20 cWBTC TokenBalance Geoff) 500e8 - Invariant Remains (Erc20 WBTC TokenBalance Geoff) 20e8 - -- Now redeem after some time - FastForward 2 Blocks - EnterMarkets Geoff cWBTC - AllowFailures - Redeem Geoff 501e8 cWBTC - Assert Revert - -Test "Mint WBTC, Enter, then Redeem Too Much (collateral factor: 0.1)" - NewComptroller - ListedCToken WBTC cWBTC initialExchangeRate:0.1 tokenType:WBTC - Comptroller SetMarketSupplyCaps (cWBTC) (2e30) - Comptroller SetCollateralFactor cWBTC 0.1 - Prep Geoff 70e8 WBTC cWBTC - Mint Geoff 50e8 cWBTC - -- Check and hold static - Invariant Static (CToken cWBTC ExchangeRateStored) - Invariant Remains (Erc20 cWBTC TokenBalance Geoff) 500e8 - Invariant Remains (Erc20 WBTC TokenBalance Geoff) 20e8 - -- Now redeem after some time - FastForward 2 Blocks - EnterMarkets Geoff cWBTC - AllowFailures - Redeem Geoff 501e8 cWBTC - Assert RevertCustomError RedeemComptrollerRejection 4 diff --git a/spec/scenario/ReduceReserves.scen b/spec/scenario/ReduceReserves.scen deleted file mode 100644 index e2d598f26..000000000 --- a/spec/scenario/ReduceReserves.scen +++ /dev/null @@ -1,140 +0,0 @@ - -Test "Reduce all reserves and verify effects" - NewComptroller - ListedCToken ZRX cZRX initialExchangeRate:1e9 - Comptroller SetMarketSupplyCaps (cZRX) (2e30) - Prep Geoff 50e18 ZRX cZRX - Mint Geoff 50e18 cZRX - Assert Equal (Erc20 cZRX TokenBalance Geoff) (Exactly 500e8) -- 50e18 / 1e9 - Assert Equal (CToken cZRX UnderlyingBalance Geoff) (Exactly 50e18) - Assert Equal (CToken cZRX ExchangeRate) (Exactly 1e9) - -- Get some brah to borrow then repay - BorrowAndRepayWithInterest ZRX cZRX 10e18 5e18 interestRate:0.000001 blocks:500000 reserveRate:0.2 - -- We've accrued .0001% interest for 500000 blocks, or 50% of the principal (10e18), - -- thus, we should have accrued 5e18 of interest for the protocol - -- The reserves should get 20% of this, or 1e18, and the rest - -- is due pro-rata to all suppliers. We just have one, so - -- let's check that account is given correct new balance. - Assert Equal (Erc20 ZRX TokenBalance cZRX) (Exactly 55e18) - Assert Equal (Erc20 ZRX TokenBalance Root) (Exactly 0e18) - Assert Equal (Erc20 cZRX TokenBalance Geoff) (Exactly 500e8) - Assert Equal (CToken cZRX Reserves) (Exactly 1e18) - Assert Equal (CToken cZRX UnderlyingBalance Geoff) (Exactly 54e18) - -- (55.0e18+0.0e18-1.0e18)/500.0e8 - Assert Equal (CToken cZRX ExchangeRate) (Exactly 1.08e9) - -- Now, let's pull out all of our reserves (1e18) - ReduceReserves 1e18 cZRX - Assert Equal (Erc20 ZRX TokenBalance cZRX) (Exactly 54e18) - Assert Equal (Erc20 ZRX TokenBalance Root) (Exactly 1e18) - Assert Equal (Erc20 cZRX TokenBalance Geoff) (Exactly 500e8) - Assert Equal (CToken cZRX Reserves) (Exactly 0e18) - Assert Equal (CToken cZRX UnderlyingBalance Geoff) (Exactly 54e18) - -- (54.0e18+0.0e18-0.0e18)/500.0e8 - Assert Equal (CToken cZRX ExchangeRate) (Exactly 1.08e9) - -Test "Reduce partial reserves and verify effects" - NewComptroller - ListedCToken ZRX cZRX initialExchangeRate:1e9 - Comptroller SetMarketSupplyCaps (cZRX) (2e30) - Prep Geoff 50e18 ZRX cZRX - Mint Geoff 50e18 cZRX - Assert Equal (Erc20 cZRX TokenBalance Geoff) (Exactly 500e8) - Assert Equal (CToken cZRX UnderlyingBalance Geoff) (Exactly 50e18) - Assert Equal (CToken cZRX ExchangeRate) (Exactly 1e9) - -- Get some brah to borrow then repay - BorrowAndRepayWithInterest ZRX cZRX 10e18 5e18 interestRate:0.000001 blocks:500000 reserveRate:0.2 - -- We've accrued .0001% interest for 500000 blocks, or 50% of the principal (10e18), - -- thus, we should have accrued 5e18 of interest for the protocol - -- The reserves should get 20% of this, or 1e18, and the rest - -- is due pro-rata to all suppliers. We just have one, so - -- let's check that account is given correct new balance. - Assert Equal (Erc20 ZRX TokenBalance cZRX) (Exactly 55e18) - Assert Equal (Erc20 ZRX TokenBalance Root) (Exactly 0e18) - Assert Equal (Erc20 cZRX TokenBalance Geoff) (Exactly 500e8) - Assert Equal (CToken cZRX Reserves) (Exactly 1e18) - Assert Equal (CToken cZRX UnderlyingBalance Geoff) (Exactly 54e18) - -- (55.0e18+0.0e18-1.0e18)/500.0e8 - Assert Equal (CToken cZRX ExchangeRate) (Exactly 1.08e9) - -- Now, let's pull out all of our reserves (1e18) - ReduceReserves 0.5e18 cZRX - Assert Equal (Erc20 ZRX TokenBalance cZRX) (Exactly 54.5e18) - Assert Equal (Erc20 ZRX TokenBalance Root) (Exactly 0.5e18) - Assert Equal (Erc20 cZRX TokenBalance Geoff) (Exactly 500e8) - Assert Equal (CToken cZRX Reserves) (Exactly 0.5e18) - Assert Equal (CToken cZRX UnderlyingBalance Geoff) (Exactly 54e18) - -- (54.5e18+0.5e18-0.0e18)/500.0e8 - Assert Equal (CToken cZRX ExchangeRate) (Exactly 1.08e9) - -Test "Redeem all and then reduce all reserves" - NewComptroller - ListedCToken ZRX cZRX initialExchangeRate:1e9 - Comptroller SetMarketSupplyCaps (cZRX) (2e30) - Prep Geoff 50e18 ZRX cZRX - Mint Geoff 50e18 cZRX - Assert Equal (Erc20 cZRX TokenBalance Geoff) (Exactly 500e8) - Assert Equal (CToken cZRX UnderlyingBalance Geoff) (Exactly 50e18) - Assert Equal (CToken cZRX ExchangeRate) (Exactly 1e9) - -- Get some brah to borrow then repay - BorrowAndRepayWithInterest ZRX cZRX 10e18 5e18 interestRate:0.000001 blocks:500000 reserveRate:0.2 - -- We've accrued .0001% interest for 500000 blocks, or 50% of the principal (10e18), - -- thus, we should have accrued 5e18 of interest for the protocol - -- The reserves should get 20% of this, or 1e18, and the rest - -- is due pro-rata to all suppliers. We just have one, so - -- let's check that account is given correct new balance. - Assert Equal (Erc20 ZRX TokenBalance cZRX) (Exactly 55e18) - Assert Equal (Erc20 ZRX TokenBalance Root) (Exactly 0e18) - Assert Equal (Erc20 cZRX TokenBalance Geoff) (Exactly 500e8) - Assert Equal (CToken cZRX Reserves) (Exactly 1e18) - Assert Equal (CToken cZRX UnderlyingBalance Geoff) (Exactly 54e18) - -- (55.0e18+0.0e18-1.0e18)/500.0e8 - Assert Equal (CToken cZRX ExchangeRate) (Exactly 1.08e9) - -- Now let's redeem all - Redeem Geoff 500e8 cZRX - -- Check our values - Assert Equal (Erc20 ZRX TokenBalance Geoff) (Exactly 54e18) - Assert Equal (Erc20 ZRX TokenBalance cZRX) (Exactly 1e18) - Assert Equal (Erc20 ZRX TokenBalance Root) (Exactly 0e18) - Assert Equal (Erc20 cZRX TokenBalance Geoff) (Exactly 0e8) - Assert Equal (CToken cZRX Reserves) (Exactly 1e18) - Assert Equal (CToken cZRX UnderlyingBalance Geoff) (Exactly 0e18) - -- 0 tokens implies initial exchange rate - Assert Equal (CToken cZRX ExchangeRate) (Exactly 1e9) - -- Then now, let's pull out all of our reserves (1e18) - ReduceReserves 1e18 cZRX - Assert Equal (Erc20 ZRX TokenBalance Geoff) (Exactly 54e18) - Assert Equal (Erc20 ZRX TokenBalance cZRX) (Exactly 0e18) - Assert Equal (Erc20 ZRX TokenBalance Root) (Exactly 1e18) - Assert Equal (Erc20 cZRX TokenBalance Geoff) (Exactly 0e8) - Assert Equal (CToken cZRX Reserves) (Exactly 0e18) - Assert Equal (CToken cZRX UnderlyingBalance Geoff) (Exactly 0e18) - -- 0 tokens implies initial exchange rate - Assert Equal (CToken cZRX ExchangeRate) (Exactly 1e9) - -Test "Reduce reserves WBTC when paused" - NewComptroller - ListedCToken WBTC cWBTC initialExchangeRate:1e9 tokenType:WBTC - Comptroller SetMarketSupplyCaps (cWBTC) (2e30) - Prep Geoff 50e18 WBTC cWBTC - Mint Geoff 50e18 cWBTC - Assert Equal (Erc20 cWBTC TokenBalance Geoff) (Exactly 500e8) - Assert Equal (CToken cWBTC UnderlyingBalance Geoff) (Exactly 50e18) - Assert Equal (CToken cWBTC ExchangeRate) (Exactly 1e9) - -- Get some brah to borrow then repay - BorrowAndRepayWithInterest WBTC cWBTC 10e18 5e18 interestRate:0.000001 blocks:500000 reserveRate:0.2 - -- We've accrued .0001% interest for 500000 blocks, or 50% of the principal (10e18), - -- thus, we should have accrued 5e18 of interest for the protocol - -- The reserves should get 20% of this, or 1e18, and the rest - -- is due pro-rata to all suppliers. We just have one, so - -- let's check that account is given correct new balance. - Invariant Remains (Erc20 WBTC TokenBalance cWBTC) (Exactly 55e18) - Invariant Remains (Erc20 WBTC TokenBalance Root) (Exactly 0e18) - Invariant Remains (Erc20 cWBTC TokenBalance Geoff) (Exactly 500e8) - Invariant Remains (CToken cWBTC Reserves) (Exactly 1e18) - Invariant Remains (CToken cWBTC UnderlyingBalance Geoff) (Exactly 54e18) - -- (55.0e18+0.0e18-1.0e18)/500.0e8 - Invariant Remains (CToken cWBTC ExchangeRate) (Exactly 1.08e9) - -- Now, let's pull out all of our reserves (1e18) - Erc20 WBTC Pause - AllowFailures - ReduceReserves 1e18 cWBTC - Assert Revert diff --git a/spec/scenario/RepayBorrow.scen b/spec/scenario/RepayBorrow.scen deleted file mode 100644 index 4504740ad..000000000 --- a/spec/scenario/RepayBorrow.scen +++ /dev/null @@ -1,175 +0,0 @@ --- Tests for repaying borrows - -Macro NewBorrow borrowAmount borrowRate - NewComptroller price:1.0 -- TODO: This should really be a price for a specific asset - NewCToken ZRX cZRX - Comptroller SetMarketSupplyCaps (cZRX) (2e30) - NewCToken BAT cBAT borrowRate -- note: cannot use macros with named args right now - Comptroller SetMarketSupplyCaps (cBAT) (2e30) - Give cBAT 10e18 BAT -- Faucet some bat to borrow - Support cZRX collateralFactor:0.5 - Support cBAT collateralFactor:0.5 - Prep Geoff Some ZRX cZRX - Mint Geoff 100e18 cZRX - EnterMarkets Geoff cZRX cBAT - Borrow Geoff borrowAmount cBAT - -Test "Borrow, hold a few blocks, and repay part" - NewBorrow borrowAmount:1e18 borrowRate:0.000005 - Assert Equal (CToken cBAT BorrowBalance Geoff) 1e18 - Assert Equal (CToken cBAT TotalBorrowsCurrent) 1e18 - Assert Equal (Erc20 BAT TokenBalance Geoff) 1e18 - Assert Equal (Erc20 BAT TokenBalance cBAT) 9e18 - -- Now let's add some blocks and see what happs - FastForward 300000 Blocks -- 1e18 * (1 + 300000 * 0.000005) - Assert Equal (CToken cBAT BorrowBalance Geoff) 2.5e18 - -- Now let's repay one full token - From Geoff (Erc20 BAT Approve cBAT 1.0e18) - RepayBorrow Geoff 1.0e18 cBAT - Assert Equal (CToken cBAT BorrowBalance Geoff) 1.5e18 - -- Let's check the overall numbers - Assert Equal (Erc20 BAT TokenBalance Geoff) Zero - Assert Equal (Erc20 BAT TokenBalance cBAT) 10e18 - Assert Equal (CToken cBAT TotalBorrowsCurrent) 1.5e18 - FastForward 200000 Blocks -- 1.5e18 * (1 + 200000 * 0.000005) - Assert Equal (CToken cBAT BorrowBalance Geoff) 3e18 - Assert Equal (CToken cBAT TotalBorrowsCurrent) 3e18 - -Test "Borrow, hold a few blocks, and repay full" - NewBorrow borrowAmount:1e18 borrowRate:0.000005 - Assert Equal (CToken cBAT BorrowBalance Geoff) 1e18 - Assert Equal (CToken cBAT TotalBorrowsCurrent) 1e18 - Assert Equal (Erc20 BAT TokenBalance Geoff) 1e18 - Assert Equal (Erc20 BAT TokenBalance cBAT) 9e18 - -- Now let's add some blocks and see what happs - FastForward 300000 Blocks -- 1e18 * (1 + 300000 * 0.000005) - Assert Equal (CToken cBAT BorrowBalance Geoff) 2.5e18 - -- Now let's repay fully - Give Geoff 1.5e18 BAT -- Geoff had the 1.0e18 borrowed BAT - From Geoff (Erc20 BAT Approve cBAT 2.5e18) - RepayBorrow Geoff 2.5e18 cBAT - Assert Equal (CToken cBAT BorrowBalance Geoff) 0e18 - -- Let's check the overall numbers - Assert Equal (Erc20 BAT TokenBalance Geoff) 0e18 - Assert Equal (Erc20 BAT TokenBalance cBAT) 11.5e18 - Assert Equal (CToken cBAT TotalBorrowsCurrent) 0e18 - FastForward 200000 Blocks -- 0e18 * (1 + 200000 * 0.000005) - Assert Equal (CToken cBAT BorrowBalance Geoff) 0e18 - Assert Equal (CToken cBAT TotalBorrowsCurrent) 0e18 - -Test "Borrow, hold a few blocks, and repay too much" - NewBorrow borrowAmount:1e18 borrowRate:0.000005 - Assert Equal (CToken cBAT BorrowBalance Geoff) 1e18 - Assert Equal (CToken cBAT TotalBorrowsCurrent) 1e18 - -- Now let's add some blocks and see what happs - FastForward 300000 Blocks -- 0.001e18 * (1 + 300000 * 0.000005) - Assert Equal (CToken cBAT BorrowBalance Geoff) 2.5e18 - -- Now let's repay fully - AllowFailures - Prep Geoff 10e18 BAT cBAT - Expect Changes (Erc20 BAT TokenBalance Geoff) Zero - Expect Changes (Erc20 BAT TokenBalance cBAT) Zero - RepayBorrow Geoff 10e18 cBAT - Assert Revert - -- Let's check the overall numbers - Assert Equal (CToken cBAT BorrowBalance Geoff) 2.5e18 - Assert Equal (CToken cBAT TotalBorrowsCurrent) 2.5e18 - -Test "Borrow, and get a negative total cash situation" - Invariant Success - NewBorrow borrowAmount:1e18 borrowRate:0.000005 - Assert Equal (CToken cBAT BorrowBalance Geoff) 1e18 - Assert Equal (CToken cBAT TotalBorrowsCurrent) 1e18 - Assert Equal (Erc20 BAT TokenBalance Geoff) 1e18 - Assert Equal (Erc20 BAT TokenBalance cBAT) 9e18 - -- Let's zoom way forward into the future - FastForward 9800000 Blocks -- 1e18 * (1 + 9800000 * 0.000005) - Assert Equal (CToken cBAT BorrowBalance Geoff) 50e18 - Assert Equal (CToken cBAT TotalBorrowsCurrent) 50e18 - -- Now let's repay one full token - From Geoff (Erc20 BAT Approve cBAT 1.0e18) - RepayBorrow Geoff 1.0e18 cBAT - Assert Equal (CToken cBAT BorrowBalance Geoff) 49e18 - Assert Equal (CToken cBAT TotalBorrowsCurrent) 49e18 - Assert Equal (Erc20 BAT TokenBalance Geoff) 0e18 - Assert Equal (Erc20 BAT TokenBalance cBAT) 10e18 - -Test "Borrow, hold a few blocks, and repay behalf part" - Invariant Success - NewBorrow borrowAmount:1e18 borrowRate:0.000005 - Assert Equal (CToken cBAT BorrowBalance Geoff) 1e18 - Assert Equal (CToken cBAT TotalBorrowsCurrent) 1e18 - Assert Equal (Erc20 BAT TokenBalance Geoff) 1e18 - Assert Equal (Erc20 BAT TokenBalance cBAT) 9e18 - -- Now let's add some blocks and see what happs - FastForward 300000 Blocks -- 1e18 * (1 + 300000 * 0.000005) - Assert Equal (CToken cBAT BorrowBalance Geoff) 2.5e18 - -- Now let's repay one full token from another user - Prep Torrey 1.0e18 BAT cBAT - RepayBorrowBehalf Torrey Geoff 1.0e18 cBAT - Assert Equal (CToken cBAT BorrowBalance Torrey) Zero - Assert Equal (CToken cBAT BorrowBalance Geoff) 1.5e18 - -- Let's check the overall numbers - Assert Equal (Erc20 BAT TokenBalance Torrey) 0e18 - Assert Equal (Erc20 BAT TokenBalance Geoff) 1e18 - Assert Equal (Erc20 BAT TokenBalance cBAT) 10e18 - Assert Equal (CToken cBAT TotalBorrowsCurrent) 1.5e18 - FastForward 200000 Blocks -- 1.5e18 * (1 + 200000 * 0.000005) - Assert Equal (CToken cBAT BorrowBalance Torrey) Zero - Assert Equal (CToken cBAT BorrowBalance Geoff) 3e18 - Assert Equal (CToken cBAT TotalBorrowsCurrent) 3e18 - -Test "Prohibit repay by comptroller rejection due to mock unlist" - NewBorrow borrowAmount:1e18 borrowRate:0.000005 - Assert Equal (CToken cBAT BorrowBalance Geoff) 1e18 - Assert Equal (CToken cBAT TotalBorrowsCurrent) 1e18 - -- Now let's add some blocks and see what happs - FastForward 300000 Blocks -- 1e18 * (1 + 300000 * 0.000005) - Assert Equal (CToken cBAT BorrowBalance Geoff) 2.5e18 - -- Now let's repay fully - AllowFailures - Prep Geoff 10e18 BAT cBAT - Expect Changes (Erc20 BAT TokenBalance Geoff) Zero - Expect Changes (Erc20 BAT TokenBalance cBAT) Zero - Comptroller UnList cZRX -- Mock unlist ZRX - RepayBorrow Geoff 2.5e18 cZRX - Assert RevertCustomError RepayBorrowComptrollerRejection 9 - -- Let's check the overall numbers - Assert Equal (CToken cBAT BorrowBalance Geoff) 2.5e18 - Assert Equal (CToken cBAT TotalBorrowsCurrent) 2.5e18 - -Test "Repay fails with insufficient allowance" - NewBorrow borrowAmount:1e18 borrowRate:0.000005 - Assert Equal (CToken cBAT BorrowBalance Geoff) 1e18 - Assert Equal (CToken cBAT TotalBorrowsCurrent) 1e18 - -- Now let's add some blocks and see what happs - FastForward 300000 Blocks -- 1e18 * (1 + 300000 * 0.000005) - Assert Equal (CToken cBAT BorrowBalance Geoff) 2.5e18 - -- Now let's repay fully - AllowFailures - Prep Geoff 100e18 BAT cBAT allowanceAmount:1.5e18 - Expect Changes (Erc20 BAT TokenBalance Geoff) Zero - Expect Changes (Erc20 BAT TokenBalance cBAT) Zero - RepayBorrow Geoff 2.5e18 cBAT - Assert Revert "revert Insufficient allowance" - -- Let's check the overall numbers - Assert Equal (CToken cBAT BorrowBalance Geoff) 2.5e18 - Assert Equal (CToken cBAT TotalBorrowsCurrent) 2.5e18 - -Test "Repay fails with insufficient balance" - NewBorrow borrowAmount:1e18 borrowRate:0.000005 - Assert Equal (CToken cBAT BorrowBalance Geoff) 1e18 - Assert Equal (CToken cBAT TotalBorrowsCurrent) 1e18 - -- Now let's add some blocks and see what happs - FastForward 300000 Blocks -- 1e18 * (1 + 300000 * 0.000005) - Assert Equal (CToken cBAT BorrowBalance Geoff) 2.5e18 - -- Now let's repay fully - AllowFailures - Prep Geoff 0e18 BAT cBAT allowanceAmount:2.5e18 - Expect Changes (Erc20 BAT TokenBalance Geoff) Zero - Expect Changes (Erc20 BAT TokenBalance cBAT) Zero - RepayBorrow Geoff 2.5e18 cBAT - Assert Revert "revert Insufficient balance" - -- Let's check the overall numbers - Assert Equal (CToken cBAT BorrowBalance Geoff) 2.5e18 - Assert Equal (CToken cBAT TotalBorrowsCurrent) 2.5e18 diff --git a/spec/scenario/RepayBorrowEth.scen b/spec/scenario/RepayBorrowEth.scen deleted file mode 100644 index 7e2b69168..000000000 --- a/spec/scenario/RepayBorrowEth.scen +++ /dev/null @@ -1,135 +0,0 @@ --- Tests for repaying borrows - -Macro SetupBorrow borrowRate - NewComptroller price:1.0 -- TODO: This should really be a price for a specific asset - ListedCToken ZRX cZRX borrowRate - Comptroller SetMarketSupplyCaps (cZRX) (2e30) - ListedEtherToken cETH borrowRate 0.005e9 - Comptroller SetMarketSupplyCaps (cETH) (2e30) - SetCollateralFactor cZRX collateralFactor:0.5 - SetCollateralFactor cETH collateralFactor:0.5 - Donate cETH 0.003e18 - Prep Geoff Some ZRX cZRX - Mint Geoff 100e18 cZRX - EnterMarkets Geoff cZRX cETH - -Macro NewBorrowEth borrowAmount borrowRate - SetupBorrow borrowRate - Borrow Geoff borrowAmount cETH - -Test "Borrow, hold a few blocks, and repay part" - NewBorrowEth borrowAmount:0.001e18 borrowRate:0.000005 - Assert Equal (CToken cETH BorrowBalance Geoff) 0.001e18 - Assert Equal (CToken cETH TotalBorrowsCurrent) 0.001e18 - -- Now let's add some blocks and see what happs - FastForward 300000 Blocks -- 0.001e18 * (1 + 300000 * 0.000005) - Assert Equal (CToken cETH BorrowBalance Geoff) 0.0025e18 - -- Now let's repay one full token - Expect Changes (EtherBalance Geoff) -0.001e18 - Expect Changes (EtherBalance cETH) +0.001e18 - RepayBorrowEth Geoff 0.001e18 cETH - ---- Let's check the overall numbers - Assert Equal (CToken cETH BorrowBalance Geoff) 0.0015e18 - Assert Equal (CToken cETH TotalBorrowsCurrent) 0.0015e18 - FastForward 200000 Blocks -- 0.0015e18 * (1 + 2000 * 0.000005) - Assert Equal (CToken cETH BorrowBalance Geoff) 0.003e18 - Assert Equal (CToken cETH TotalBorrowsCurrent) 0.003e18 - -Test "Don't borrow and then do repay" - SetupBorrow borrowRate:0.000005 - Assert Equal (CToken cETH BorrowBalance Geoff) Zero - Assert Equal (CToken cETH TotalBorrowsCurrent) Zero - -- Now let's add some blocks and see what happs - FastForward 300000 Blocks -- 0 * (1 + 300000 * 0.000005) - Assert Equal (CToken cETH BorrowBalance Geoff) Zero - -- Now let's repay one full token - Expect Changes (EtherBalance Geoff) Zero - Expect Changes (EtherBalance cETH) Zero - RepayBorrowEth Geoff 0 cETH - ---- Let's check the overall numbers - Assert Equal (CToken cETH BorrowBalance Geoff) Zero - Assert Equal (CToken cETH TotalBorrowsCurrent) Zero - -Test "Borrow, hold a few blocks, and repay full" - NewBorrowEth borrowAmount:0.001e18 borrowRate:0.000005 - Assert Equal (CToken cETH BorrowBalance Geoff) 0.001e18 - Assert Equal (CToken cETH TotalBorrowsCurrent) 0.001e18 - -- Now let's add some blocks and see what happs - FastForward 300000 Blocks -- 0.001e18 * (1 + 300000 * 0.000005) - Assert Equal (CToken cETH BorrowBalance Geoff) 0.0025e18 - -- Now let's repay fully - Expect Changes (EtherBalance Geoff) -0.0025e18 - Expect Changes (EtherBalance cETH) +0.0025e18 - RepayBorrowEth Geoff 0.0025e18 cETH - -- Let's check the overall numbers - Assert Equal (CToken cETH BorrowBalance Geoff) Zero - Assert Equal (CToken cETH TotalBorrowsCurrent) Zero - FastForward 200000 Blocks -- 0e18 * (1 + 200000 * 0.000005) - Assert Equal (CToken cETH BorrowBalance Geoff) Zero - Assert Equal (CToken cETH TotalBorrowsCurrent) Zero - -Test "Borrow, hold a few blocks, and repay too much" - NewBorrowEth borrowAmount:0.001e18 borrowRate:0.000005 - Assert Equal (CToken cETH BorrowBalance Geoff) 0.001e18 - Assert Equal (CToken cETH TotalBorrowsCurrent) 0.001e18 - -- Now let's add some blocks and see what happs - FastForward 300000 Blocks -- 0.001e18 * (1 + 300000 * 0.000005) - Assert Equal (CToken cETH BorrowBalance Geoff) 0.0025e18 - -- Now let's repay fully - Expect Changes (EtherBalance Geoff) Zero - Expect Changes (EtherBalance cETH) Zero - -- TODO: This currently drains the sent-eth - AllowFailures - RepayBorrowEth Geoff 1.0e18 cETH - Assert Revert - -- Let's check the overall numbers - Assert Equal (CToken cETH BorrowBalance Geoff) 0.0025e18 - Assert Equal (CToken cETH TotalBorrowsCurrent) 0.0025e18 - -Test "Borrow, and get a negative total cash situation" - NewBorrowEth borrowAmount:0.001e18 borrowRate:0.000005 - Assert Equal (CToken cETH BorrowBalance Geoff) 0.001e18 - Assert Equal (CToken cETH TotalBorrowsCurrent) 0.001e18 - -- Let's zoom way forward into the future - FastForward 9800000 Blocks -- 0.001e18 * (1 + 9800000 * 0.000005) - Assert Equal (CToken cETH BorrowBalance Geoff) 0.05e18 - Assert Equal (CToken cETH TotalBorrowsCurrent) 0.05e18 - -- Now let's repay one bit - RepayBorrowEth Geoff 0.001e18 cETH - Assert Equal (CToken cETH BorrowBalance Geoff) 0.049e18 - Assert Equal (CToken cETH TotalBorrowsCurrent) 0.049e18 - -Test "Borrow, hold a few blocks, and repay behalf part" - NewBorrowEth borrowAmount:0.001e18 borrowRate:0.000005 - Assert Equal (CToken cETH BorrowBalance Geoff) 0.001e18 - Assert Equal (CToken cETH TotalBorrowsCurrent) 0.001e18 - -- Now let's add some blocks and see what happs - FastForward 300000 Blocks -- 0.001e18 * (1 + 300000 * 0.000005) - Assert Equal (CToken cETH BorrowBalance Geoff) 0.0025e18 - -- Now let's repay one full token from another user - RepayBorrowEthBehalf Torrey Geoff 0.001e18 cETH - Assert Equal (CToken cETH BorrowBalance Torrey) Zero - Assert Equal (CToken cETH BorrowBalance Geoff) 0.0015e18 - Assert Equal (CToken cETH TotalBorrowsCurrent) 0.0015e18 - FastForward 200000 Blocks -- 0.0015e18 * (1 + 200000 * 0.000005) - Assert Equal (CToken cETH BorrowBalance Torrey) Zero - Assert Equal (CToken cETH BorrowBalance Geoff) 0.003e18 - Assert Equal (CToken cETH TotalBorrowsCurrent) 0.003e18 - -Test "Prohibit repay by comptroller hook" - NewBorrowEth borrowAmount:0.001e18 borrowRate:0.000005 - Assert Equal (CToken cETH BorrowBalance Geoff) 0.001e18 - Assert Equal (CToken cETH TotalBorrowsCurrent) 0.001e18 - -- Now let's add some blocks and see what happs - FastForward 300000 Blocks -- 0.001e18 * (1 + 300000 * 0.000005) - Assert Equal (CToken cETH BorrowBalance Geoff) 0.0025e18 - -- Now let's repay one full token - Expect Changes (EtherBalance Geoff) Zero - Expect Changes (EtherBalance cETH) Zero - Comptroller UnList cETH -- Mock unlist cETH - AllowFailures - RepayBorrowEth Geoff 0.001e18 cETH - Assert RevertCustomError RepayBorrowComptrollerRejection 9 - ---- Let's check the overall numbers - Assert Equal (CToken cETH BorrowBalance Geoff) 0.0025e18 - Assert Equal (CToken cETH TotalBorrowsCurrent) 0.0025e18 diff --git a/spec/scenario/RepayBorrowWBTC.scen b/spec/scenario/RepayBorrowWBTC.scen deleted file mode 100644 index d0f019bc9..000000000 --- a/spec/scenario/RepayBorrowWBTC.scen +++ /dev/null @@ -1,193 +0,0 @@ --- Tests for repaying borrows - -Macro NewBorrow borrowAmount borrowRate - NewComptroller price:1.0 -- TODO: This should really be a price for a specific asset - NewCToken ZRX cZRX - Comptroller SetMarketSupplyCaps (cZRX) (2e30) - NewCToken WBTC cWBTC borrowRate 0.1 8 WBTC -- note: cannot use macros with named args right now - Comptroller SetMarketSupplyCaps (cWBTC) (2e30) - Give cWBTC 10e8 WBTC -- Faucet some WBTC to borrow - Support cZRX collateralFactor:0.5 - Support cWBTC collateralFactor:0.5 - Prep Geoff Some ZRX cZRX - Mint Geoff 100e18 cZRX - EnterMarkets Geoff cZRX cWBTC - Borrow Geoff borrowAmount cWBTC - -Test "Borrow WBTC, hold a few blocks, and repay part" - NewBorrow borrowAmount:1e8 borrowRate:0.000005 - Assert Equal (CToken cWBTC BorrowBalance Geoff) 1e8 - Assert Equal (CToken cWBTC TotalBorrowsCurrent) 1e8 - Assert Equal (Erc20 WBTC TokenBalance Geoff) 1e8 - Assert Equal (Erc20 WBTC TokenBalance cWBTC) 9e8 - -- Now let's add some blocks and see what happs - FastForward 300000 Blocks -- 1e18 * (1 + 300000 * 0.000005) - Assert Equal (CToken cWBTC BorrowBalance Geoff) 2.5e8 - -- Now let's repay one full token - From Geoff (Erc20 WBTC Approve cWBTC 1.0e8) - RepayBorrow Geoff 1e8 cWBTC - Assert Equal (CToken cWBTC BorrowBalance Geoff) 1.5e8 - -- Let's check the overall numbers - Assert Equal (Erc20 WBTC TokenBalance Geoff) Zero - Assert Equal (Erc20 WBTC TokenBalance cWBTC) 10e8 - Assert Equal (CToken cWBTC TotalBorrowsCurrent) 1.5e8 - FastForward 200000 Blocks -- 1.5e8 * (1 + 200000 * 0.000005) - Assert Equal (CToken cWBTC BorrowBalance Geoff) 3e8 - Assert Equal (CToken cWBTC TotalBorrowsCurrent) 3e8 - -Test "Borrow, hold a few blocks, and repay full" - NewBorrow borrowAmount:1e8 borrowRate:0.000005 - Assert Equal (CToken cWBTC BorrowBalance Geoff) 1e8 - Assert Equal (CToken cWBTC TotalBorrowsCurrent) 1e8 - Assert Equal (Erc20 WBTC TokenBalance Geoff) 1e8 - Assert Equal (Erc20 WBTC TokenBalance cWBTC) 9e8 - -- Now let's add some blocks and see what happs - FastForward 300000 Blocks -- 1e8 * (1 + 300000 * 0.000005) - Assert Equal (CToken cWBTC BorrowBalance Geoff) 2.5e8 - -- Now let's repay fully - Give Geoff 1.5e8 WBTC -- Geoff had the 1.0e8 borrowed WBTC - From Geoff (Erc20 WBTC Approve cWBTC 2.5e8) - RepayBorrow Geoff 2.5e8 cWBTC - Assert Equal (CToken cWBTC BorrowBalance Geoff) 0e8 - -- Let's check the overall numbers - Assert Equal (Erc20 WBTC TokenBalance Geoff) 0e8 - Assert Equal (Erc20 WBTC TokenBalance cWBTC) 11.5e8 - Assert Equal (CToken cWBTC TotalBorrowsCurrent) 0e8 - FastForward 200000 Blocks -- 0e8 * (1 + 200000 * 0.000005) - Assert Equal (CToken cWBTC BorrowBalance Geoff) 0e8 - Assert Equal (CToken cWBTC TotalBorrowsCurrent) 0e8 - -Test "Borrow, hold a few blocks, and repay too much" - NewBorrow borrowAmount:1e8 borrowRate:0.000005 - Assert Equal (CToken cWBTC BorrowBalance Geoff) 1e8 - Assert Equal (CToken cWBTC TotalBorrowsCurrent) 1e8 - -- Now let's add some blocks and see what happs - FastForward 300000 Blocks -- 1e8 * (1 + 300000 * 0.000005) - Assert Equal (CToken cWBTC BorrowBalance Geoff) 2.5e8 - -- Now let's repay fully - AllowFailures - Prep Geoff 10e8 WBTC cWBTC - Expect Changes (Erc20 WBTC TokenBalance Geoff) Zero - Expect Changes (Erc20 WBTC TokenBalance cWBTC) Zero - RepayBorrow Geoff 10e8 cWBTC - Assert Revert - -- Let's check the overall numbers - Assert Equal (CToken cWBTC BorrowBalance Geoff) 2.5e8 - Assert Equal (CToken cWBTC TotalBorrowsCurrent) 2.5e8 - -Test "Borrow, and get a negative total cash situation" - Invariant Success - NewBorrow borrowAmount:1e8 borrowRate:0.000005 - Assert Equal (CToken cWBTC BorrowBalance Geoff) 1e8 - Assert Equal (CToken cWBTC TotalBorrowsCurrent) 1e8 - Assert Equal (Erc20 WBTC TokenBalance Geoff) 1e8 - Assert Equal (Erc20 WBTC TokenBalance cWBTC) 9e8 - -- Let's zoom way forward into the future - FastForward 9800000 Blocks -- 1e8 * (1 + 9800000 * 0.000005) - Assert Equal (CToken cWBTC BorrowBalance Geoff) 50e8 - Assert Equal (CToken cWBTC TotalBorrowsCurrent) 50e8 - -- Now let's repay one full token - From Geoff (Erc20 WBTC Approve cWBTC 1.0e8) - RepayBorrow Geoff 1.0e8 cWBTC - Assert Equal (CToken cWBTC BorrowBalance Geoff) 49e8 - Assert Equal (CToken cWBTC TotalBorrowsCurrent) 49e8 - Assert Equal (Erc20 WBTC TokenBalance Geoff) 0e8 - Assert Equal (Erc20 WBTC TokenBalance cWBTC) 10e8 - -Test "Borrow, hold a few blocks, and repay behalf part" - Invariant Success - NewBorrow borrowAmount:1e8 borrowRate:0.000005 - Assert Equal (CToken cWBTC BorrowBalance Geoff) 1e8 - Assert Equal (CToken cWBTC TotalBorrowsCurrent) 1e8 - Assert Equal (Erc20 WBTC TokenBalance Geoff) 1e8 - Assert Equal (Erc20 WBTC TokenBalance cWBTC) 9e8 - -- Now let's add some blocks and see what happs - FastForward 300000 Blocks -- 1e8 * (1 + 300000 * 0.000005) - Assert Equal (CToken cWBTC BorrowBalance Geoff) 2.5e8 - -- Now let's repay one full token from another user - Prep Torrey 1.0e8 WBTC cWBTC - RepayBorrowBehalf Torrey Geoff 1.0e8 cWBTC - Assert Equal (CToken cWBTC BorrowBalance Torrey) Zero - Assert Equal (CToken cWBTC BorrowBalance Geoff) 1.5e8 - -- Let's check the overall numbers - Assert Equal (Erc20 WBTC TokenBalance Torrey) 0e8 - Assert Equal (Erc20 WBTC TokenBalance Geoff) 1e8 - Assert Equal (Erc20 WBTC TokenBalance cWBTC) 10e8 - Assert Equal (CToken cWBTC TotalBorrowsCurrent) 1.5e8 - FastForward 200000 Blocks -- 1.5e8 * (1 + 200000 * 0.000005) - Assert Equal (CToken cWBTC BorrowBalance Torrey) Zero - Assert Equal (CToken cWBTC BorrowBalance Geoff) 3e8 - Assert Equal (CToken cWBTC TotalBorrowsCurrent) 3e8 - -Test "Prohibit repay by comptroller rejection due to mock unlist" - NewBorrow borrowAmount:1e8 borrowRate:0.000005 - Assert Equal (CToken cWBTC BorrowBalance Geoff) 1e8 - Assert Equal (CToken cWBTC TotalBorrowsCurrent) 1e8 - -- Now let's add some blocks and see what happs - FastForward 300000 Blocks -- 0.001e8 * (1 + 300000 * 0.000005) - Assert Equal (CToken cWBTC BorrowBalance Geoff) 2.5e8 - -- Now let's repay fully - AllowFailures - Prep Geoff 10e8 WBTC cWBTC - Expect Changes (Erc20 WBTC TokenBalance Geoff) Zero - Expect Changes (Erc20 WBTC TokenBalance cWBTC) Zero - Comptroller UnList cZRX -- Mock unlist ZRX - RepayBorrow Geoff 2.5e8 cZRX - Assert RevertCustomError RepayBorrowComptrollerRejection 9 - -- Let's check the overall numbers - Assert Equal (CToken cWBTC BorrowBalance Geoff) 2.5e8 - Assert Equal (CToken cWBTC TotalBorrowsCurrent) 2.5e8 - -Test "Borrow WBTC, can't repay when paused" - NewBorrow borrowAmount:1e8 borrowRate:0.000005 - Assert Equal (CToken cWBTC BorrowBalance Geoff) 1e8 - Assert Equal (CToken cWBTC TotalBorrowsCurrent) 1e8 - Assert Equal (Erc20 WBTC TokenBalance Geoff) 1e8 - Assert Equal (Erc20 WBTC TokenBalance cWBTC) 9e8 - -- Now let's add some blocks and see what happs - FastForward 300000 Blocks -- 1e18 * (1 + 300000 * 0.000005) - Invariant Remains (CToken cWBTC BorrowBalance Geoff) 2.5e8 - -- Now let's repay one full token - From Geoff (Erc20 WBTC Approve cWBTC 1.0e8) - Erc20 WBTC Pause - AllowFailures - RepayBorrow Geoff 1e8 cWBTC - Assert Revert - -Test "Repay fails with insufficient allowance" - NewBorrow borrowAmount:1e8 borrowRate:0.000005 - Assert Equal (CToken cWBTC BorrowBalance Geoff) 1e8 - Assert Equal (CToken cWBTC TotalBorrowsCurrent) 1e8 - -- Now let's add some blocks and see what happs - FastForward 300000 Blocks -- 1e8 * (1 + 300000 * 0.000005) - Assert Equal (CToken cWBTC BorrowBalance Geoff) 2.5e8 - -- Now let's repay fully - AllowFailures - Prep Geoff 100e8 WBTC cWBTC allowanceAmount:1.5e8 - Expect Changes (Erc20 WBTC TokenBalance Geoff) Zero - Expect Changes (Erc20 WBTC TokenBalance cWBTC) Zero - RepayBorrow Geoff 2.5e8 cWBTC - --wbtc does not revert with reason in transfer from - Assert Revert "revert" - -- Let's check the overall numbers - Assert Equal (CToken cWBTC BorrowBalance Geoff) 2.5e8 - Assert Equal (CToken cWBTC TotalBorrowsCurrent) 2.5e8 - -Test "Repay fails with insufficient balance" - NewBorrow borrowAmount:1e8 borrowRate:0.000005 - Assert Equal (CToken cWBTC BorrowBalance Geoff) 1e8 - Assert Equal (CToken cWBTC TotalBorrowsCurrent) 1e8 - -- Now let's add some blocks and see what happs - FastForward 300000 Blocks -- 1e8 * (1 + 300000 * 0.000005) - Assert Equal (CToken cWBTC BorrowBalance Geoff) 2.5e8 - -- Now let's repay fully - AllowFailures - Prep Geoff 0e8 WBTC cWBTC allowanceAmount:2.5e8 - Expect Changes (Erc20 WBTC TokenBalance Geoff) Zero - Expect Changes (Erc20 WBTC TokenBalance cWBTC) Zero - RepayBorrow Geoff 2.5e8 cWBTC - --wbtc does not revert with reason in transfer from - Assert Revert "revert" - -- Let's check the overall numbers - Assert Equal (CToken cWBTC BorrowBalance Geoff) 2.5e8 - Assert Equal (CToken cWBTC TotalBorrowsCurrent) 2.5e8 diff --git a/spec/scenario/Seize.scen b/spec/scenario/Seize.scen deleted file mode 100644 index bdcbe17d5..000000000 --- a/spec/scenario/Seize.scen +++ /dev/null @@ -1,59 +0,0 @@ - -Test "Fail to seize calling directly" - NewComptroller - ListedCToken ZRX cZRX initialExchangeRate:1e9 - Comptroller SetMarketSupplyCaps (cZRX) (2e30) - ListedCToken BAT cBAT initialExchangeRate:1e9 - Comptroller SetMarketSupplyCaps (cBAT) (2e30) - Prep Geoff Some ZRX cZRX - Mint Geoff 50e18 cZRX - Invariant Remains (Erc20 cZRX TokenBalance Geoff) 50e9 - AllowFailures - Seize 1e9 cZRX caller:Geoff liquidator:Geoff borrower:Torrey - -- The caller must be from another cToken market, thus this fails - Assert RevertCustomError LiquidateSeizeComptrollerRejection 9 - -Test "Seize tokens with a paused WBTC cToken-- like normal" - NewComptroller - ListedCToken ZRX cZRX initialExchangeRate:1e9 - Comptroller SetMarketSupplyCaps (cZRX) (2e30) - ListedCToken WBTC cWBTC initialExchangeRate:0.1 tokenType:WBTC - Comptroller SetMarketSupplyCaps (cWBTC) (2e30) - Prep Geoff Some ZRX cZRX - Mint Geoff 50e18 cZRX - Erc20 WBTC Pause - Invariant Remains (Erc20 cZRX TokenBalance Geoff) 50e9 - AllowFailures - Seize 1e9 cWBTC caller:Geoff liquidator:Geoff borrower:Torrey - -- The caller must be from another cToken market, thus this fails - Assert RevertCustomError LiquidateSeizeComptrollerRejection 9 - -Test "Not able to seize tokens with a malicious unlisted cToken" - NewComptroller - ListedCToken ZRX cZRX initialExchangeRate:1e9 - Comptroller SetMarketSupplyCaps (cZRX) (2e30) - NewCTokenImmutable EVL cEVL initialExchangeRate:1e9 cTokenType:CEvil - Comptroller SetMarketSupplyCaps (cEVL) (2e30) - Prep Geoff Some ZRX cZRX - Mint Geoff 50e18 cZRX - Invariant Remains (Erc20 cZRX TokenBalance Geoff) 50e9 - Invariant Static (Erc20 cZRX TokenBalance Geoff) - Invariant Static (Erc20 cZRX TokenBalance Torrey) - AllowFailures - EvilSeize cEVL 1e9 cZRX seizer:Geoff seizee:Torrey - -- The caller must be from another cToken market, thus this fails - Assert RevertCustomError LiquidateSeizeComptrollerRejection 9 - -Test "Able to seize tokens with a malicious listed cToken" - NewComptroller - ListedCToken ZRX cZRX initialExchangeRate:1e9 - Comptroller SetMarketSupplyCaps (cZRX) (2e30) - ListedCTokenImmutable EVL cEVL initialExchangeRate:1e9 cTokenType:CEvil - Comptroller SetMarketSupplyCaps (cEVL) (2e30) - Prep Geoff Some ZRX cZRX - Mint Geoff 50e18 cZRX - Assert Equal (Erc20 cZRX TokenBalance Geoff) 50e9 - Expect Changes (Erc20 cZRX TokenBalance Geoff) -1e9 - -- effective liquidation reward is 1-.028 = 0.972 after protocolSeizeShare (liq incentive = 1) - Expect Changes (Erc20 cZRX TokenBalance Torrey) +0.972e9 - EvilSeize cEVL 1e9 cZRX seizer:Torrey seizee:Geoff diff --git a/spec/scenario/SetComptroller.scen b/spec/scenario/SetComptroller.scen deleted file mode 100644 index 36b4560e3..000000000 --- a/spec/scenario/SetComptroller.scen +++ /dev/null @@ -1,29 +0,0 @@ --- Sets for `_setComptroller` Admin Function - -Test "Set Comptroller" - NewComptroller - NewCToken ZRX cZRX - Comptroller SetMarketSupplyCaps (cZRX) (2e30) - Assert Equal (CToken cZRX Comptroller) (Unitroller Address) - ComptrollerImpl Deploy Scenario NewComptroller - From Root (CToken cZRX SetComptroller (ComptrollerImpl NewComptroller Address)) - -- TODO: Fix log assertion - -- Assert Log "NewComptroller" ("oldComptroller" (Unitroller Address)) ("newComptroller" (ComptrollerImpl NewComptroller Address)) - Assert Equal (CToken cZRX Comptroller) (ComptrollerImpl NewComptroller Address) - -Test "Fail when is not a comptroller" - NewComptroller - NewCToken ZRX cZRX - Comptroller SetMarketSupplyCaps (cZRX) (2e30) - Invariant Remains (CToken cZRX Comptroller) (Unitroller Address) - AllowFailures - From Root (CToken cZRX SetComptroller (PriceOracle Address)) - Assert Revert - -Test "Fail to set comptroller as not admin" - NewComptroller - NewCToken ZRX cZRX - Comptroller SetMarketSupplyCaps (cZRX) (2e30) - AllowFailures - From Geoff (CToken cZRX SetComptroller (PriceOracle Address)) - Assert RevertCustomError SetComptrollerOwnerCheck diff --git a/spec/scenario/SweepToken.scen b/spec/scenario/SweepToken.scen deleted file mode 100644 index 584df1318..000000000 --- a/spec/scenario/SweepToken.scen +++ /dev/null @@ -1,32 +0,0 @@ - -Test "Attempt to sweep underlying token" - NewComptroller price:1.0 - NewCToken ZRX cZRX - Comptroller SetMarketSupplyCaps (cZRX) (2e30) - NewCToken BAT cBAT - Give cBAT 10e18 BAT -- Faucet some bat to sweep - Support cZRX collateralFactor:0.5 - Support cBAT collateralFactor:0.5 - AllowFailures - cToken cBAT SweepToken BAT - Assert Revert "revert CErc20::sweepToken: can not sweep underlying token" - -Test "Succesfully Sweep standard non-underlying token from CErc20" - NewComptroller price:1.0 - Erc20 Deploy Standard ZRX "ZRX" 18 - NewCToken BAT cBAT - Comptroller SetMarketSupplyCaps (cBAT) (2e30) - Give cBAT 10e18 ZRX -- Faucet some ZRX to sweep - Support cBAT collateralFactor:0.5 - cToken cBAT SweepToken ZRX - Assert Equal (Erc20 ZRX TokenBalance Admin) (10e18) - -Test "Succesfully Sweep non-standard non-underlying token from CErc20" - NewComptroller price:1.0 - Erc20 Deploy NonStandard USDT "USDT" 18 - NewCToken BAT cBAT - Comptroller SetMarketSupplyCaps (cBAT) (2e30) - Give cBAT 10e18 USDT -- Faucet some USDT to sweep - Support cBAT collateralFactor:0.5 - cToken cBAT SweepToken USDT - Assert Equal (Erc20 USDT TokenBalance Admin) (10e18) diff --git a/spec/scenario/TokenTransfer.scen b/spec/scenario/TokenTransfer.scen deleted file mode 100644 index f5feda9ad..000000000 --- a/spec/scenario/TokenTransfer.scen +++ /dev/null @@ -1,115 +0,0 @@ - -Test "Simple cToken Transfer" - NewComptroller - ListedCToken ZRX cZRX initialExchangeRate:1e9 - Comptroller SetMarketSupplyCaps (cZRX) (2e30) - Prep Geoff Some ZRX cZRX - Mint Geoff 50e18 cZRX - -- Just to be sure, check initial balances - Assert Equal (Erc20 cZRX TokenBalance Geoff) (Exactly 50e9) - Assert Equal (Erc20 cZRX TokenBalance Torrey) Zero - -- Just transfer - Transfer Geoff Torrey 10e9 cZRX - Assert Equal (Erc20 cZRX TokenBalance Geoff) (Exactly 40e9) - Assert Equal (Erc20 cZRX TokenBalance Torrey) (Exactly 10e9) - -Test "Simple cToken Transfer When Underlying Paused" - NewComptroller - ListedCToken WBTC cWBTC initialExchangeRate:0.1 tokenType:WBTC - Comptroller SetMarketSupplyCaps (cWBTC) (2e30) - Prep Geoff Some WBTC cWBTC - Mint Geoff 50e8 cWBTC - -- Just to be sure, check initial balances - Assert Equal (Erc20 cWBTC TokenBalance Geoff) (Exactly 50e9) - Assert Equal (Erc20 cWBTC TokenBalance Torrey) Zero - -- Just transfer - Erc20 WBTC Pause - Transfer Geoff Torrey 10e9 cWBTC - Assert Equal (Erc20 cWBTC TokenBalance Geoff) (Exactly 40e9) - Assert Equal (Erc20 cWBTC TokenBalance Torrey) (Exactly 10e9) - -Test "Simple cToken Transfer 1:1 Rate" - NewComptroller - ListedCToken ZRX cZRX initialExchangeRate:1e0 - Comptroller SetMarketSupplyCaps (cZRX) (2e30) - Prep Geoff Some ZRX cZRX - Mint Geoff 50e18 cZRX - -- Just to be sure, check initial balances - Assert Equal (Erc20 cZRX TokenBalance Geoff) (Exactly 50e18) - Assert Equal (Erc20 cZRX TokenBalance Torrey) Zero - -- Just transfer - Transfer Geoff Torrey 10e18 cZRX - Assert Equal (Erc20 cZRX TokenBalance Geoff) (Exactly 40e18) - Assert Equal (Erc20 cZRX TokenBalance Torrey) (Exactly 10e18) - -Test "Simple cToken Transfer Not Allowed by Comptroller" - NewComptroller - ListedCToken ZRX cZRX initialExchangeRate:1e0 - Comptroller SetMarketSupplyCaps (cZRX) (2e30) - Comptroller SetCollateralFactor cZRX 0.1 - EnterMarkets Geoff cZRX - Prep Geoff Some ZRX cZRX - Mint Geoff 50e18 cZRX - -- Just to be sure, check initial balances - Invariant Remains (Erc20 cZRX TokenBalance Geoff) (Exactly 50e18) - Invariant Remains (Erc20 cZRX TokenBalance Torrey) Zero - -- Just transfer - AllowFailures - Transfer Geoff Torrey 60e18 cZRX - Assert RevertCustomError TransferComptrollerRejection 4 - -Test "Simple cToken Transfer From" - NewComptroller - ListedCToken ZRX cZRX initialExchangeRate:1e9 - Comptroller SetMarketSupplyCaps (cZRX) (2e30) - Prep Geoff Some ZRX cZRX - Mint Geoff 50e18 cZRX - -- Just to be sure, check initial balances - Invariant Remains (Erc20 cZRX TokenBalance Torrey) Zero - Assert Equal (Erc20 cZRX TokenBalance Geoff) (Exactly 50e9) - Assert Equal (Erc20 cZRX TokenBalance Coburn) Zero - -- Add approval - From Geoff (Erc20 cZRX Approve Torrey 25e9) - Assert Equal (Erc20 cZRX Allowance Geoff Torrey) (Exactly 25e9) - -- Perform transfer from - From Torrey (Erc20 cZRX TransferFrom Geoff Coburn 10e9) - Assert Equal (Erc20 cZRX TokenBalance Geoff) (Exactly 40e9) - Assert Equal (Erc20 cZRX TokenBalance Coburn) (Exactly 10e9) - Assert Equal (Erc20 cZRX Allowance Geoff Torrey) (Exactly 15e9) - -Test "cToken Transfer From Not Allowed" - NewComptroller - ListedCToken ZRX cZRX initialExchangeRate:1e9 - Comptroller SetMarketSupplyCaps (cZRX) (2e30) - Prep Geoff Some ZRX cZRX - Mint Geoff 50e18 cZRX - -- - Invariant Remains (Erc20 cZRX TokenBalance Geoff) (Exactly 50e9) - Invariant Remains (Erc20 cZRX TokenBalance Torrey) (Exactly 0e9) - AllowFailures - Erc20 cZRX TransferFrom Geoff Torrey 10e9 - Assert Revert - -Test "cToken Transfer paused" - NewComptroller - ListedCToken ZRX cZRX initialExchangeRate:1e9 - Comptroller SetMarketSupplyCaps (cZRX) (2e30) - Prep Geoff Some ZRX cZRX - Mint Geoff 50e18 cZRX - -- Just to be sure, check initial balances - Assert Equal (Erc20 cZRX TokenBalance Geoff) (Exactly 50e9) - Assert Equal (Erc20 cZRX TokenBalance Coburn) Zero - -- Pause and attempt transfer - Comptroller SetPauseGuardian Coburn - From Coburn (Comptroller SetGuardianPaused "Transfer" True) - AllowFailures - Transfer Geoff Torrey 10e9 cZRX - Assert Revert "revert transfer is paused" - Assert Equal (Erc20 cZRX TokenBalance Geoff) (Exactly 50e9) - Assert Equal (Erc20 cZRX TokenBalance Coburn) Zero - -- unPause and complete transfer - Invariant Success - Comptroller SetGuardianPaused "Transfer" False - Transfer Geoff Coburn 10e9 cZRX - Assert Equal (Erc20 cZRX TokenBalance Geoff) (Exactly 40e9) - Assert Equal (Erc20 cZRX TokenBalance Coburn) (Exactly 10e9) diff --git a/spec/scenario/Unitroller.scen b/spec/scenario/Unitroller.scen deleted file mode 100644 index dc9576d22..000000000 --- a/spec/scenario/Unitroller.scen +++ /dev/null @@ -1,277 +0,0 @@ - -Test "Standard Upgrade" - Unitroller Deploy - PriceOracle Deploy Fixed 1.0 - -- Upgrade to G1 - ComptrollerImpl Deploy ScenarioG1 ScenComptrollerG1 - Unitroller SetPendingImpl ScenComptrollerG1 - ComptrollerImpl ScenComptrollerG1 BecomeG1 (PriceOracle Address) 0.2 20 - Assert Equal (Comptroller CloseFactor) 0.2 - Assert Equal (Comptroller MaxAssets) 20 - Assert Equal (Comptroller Implementation) (Address ScenComptrollerG1) - ListedCToken ZRX cZRX - Comptroller SetMarketSupplyCaps (cZRX) (2e30) - ListedCToken DAI cDAI - Comptroller SetMarketSupplyCaps (cDAI) (2e30) - -- Upgrade to G2 - ComptrollerImpl Deploy StandardG2 StandardComptrollerG2 - Unitroller SetPendingImpl StandardComptrollerG2 - ComptrollerImpl StandardComptrollerG2 BecomeG2 - Assert Equal (Comptroller CloseFactor) 0.2 - Assert Equal (Comptroller MaxAssets) 20 - Assert Equal (Comptroller Implementation) (Address StandardComptrollerG2) - -- Upgrade to G3 - ComptrollerImpl Deploy ScenarioG3 ScenComptrollerG3 - Unitroller SetPendingImpl ScenComptrollerG3 - ComptrollerImpl ScenComptrollerG3 BecomeG3 1e18 [cZRX cDAI] - Assert Equal (Comptroller CloseFactor) 0.2 - Assert Equal (Comptroller MaxAssets) 20 - Assert Equal (Comptroller Implementation) (Address ScenComptrollerG3) - -Test "Standard Upgrade, then downgrade then upgrade again" - Unitroller Deploy - PriceOracle Deploy Fixed 1.0 - -- Upgrade to G1 - ComptrollerImpl Deploy ScenarioG1 ScenComptrollerG1 - Unitroller SetPendingImpl ScenComptrollerG1 - ComptrollerImpl ScenComptrollerG1 BecomeG1 (PriceOracle Address) 0.2 20 - Assert Equal (Comptroller CloseFactor) 0.2 - Assert Equal (Comptroller MaxAssets) 20 - Assert Equal (Comptroller Implementation) (Address ScenComptrollerG1) - ListedCToken ZRX cZRX - ListedCToken DAI cDAI - -- Upgrade to G2 - ComptrollerImpl Deploy StandardG2 ComptrollerG2 - Unitroller SetPendingImpl ComptrollerG2 - ComptrollerImpl ComptrollerG2 BecomeG2 - Comptroller SetPauseGuardian Coburn - Assert Equal (Comptroller PauseGuardian) (Address Coburn) - Assert Equal (Comptroller CloseFactor) 0.2 - Assert Equal (Comptroller MaxAssets) 20 - Assert Equal (Comptroller Implementation) (Address ComptrollerG2) - -- Upgrade to G3 - ComptrollerImpl Deploy ScenarioG3 ScenComptrollerG3 - Unitroller SetPendingImpl ScenComptrollerG3 - ComptrollerImpl ScenComptrollerG3 BecomeG3 1e18 [cZRX cDAI] - Assert Equal (Comptroller PauseGuardian) (Address Coburn) - Assert Equal (Comptroller CloseFactor) 0.2 - Assert Equal (Comptroller MaxAssets) 20 - Assert Equal (Comptroller Implementation) (Address ScenComptrollerG3) - -- Downgrade to G2 - Unitroller SetPendingImpl ComptrollerG2 - ComptrollerImpl ComptrollerG2 BecomeG2 - Assert Equal (Comptroller CloseFactor) 0.2 - Assert Equal (Comptroller MaxAssets) 20 - Assert Equal (Comptroller Implementation) (Address ComptrollerG2) - -- Upgrade to G3 again - Unitroller SetPendingImpl ScenComptrollerG3 - ComptrollerImpl ScenComptrollerG3 BecomeG3 1e18 [] - Assert Equal (Comptroller GetCompMarkets) [(Address cZRX) (Address cDAI)] - Assert Equal (Comptroller PauseGuardian) (Address Coburn) - Assert Equal (Comptroller CloseFactor) 0.2 - Assert Equal (Comptroller MaxAssets) 20 - Assert Equal (Comptroller Implementation) (Address ScenComptrollerG3) - -Test "Once become, can become again" - -- TODO: See why ABI is broken here - Unitroller Deploy - PriceOracle Deploy Fixed 1.0 - ComptrollerImpl Deploy ScenarioG1 ScenComptrollerG1 - Unitroller SetPendingImpl ScenComptrollerG1 - ComptrollerImpl ScenComptrollerG1 BecomeG1 (PriceOracle Address) 0.2 20 - Assert Equal (Comptroller CloseFactor) 0.2 - Assert Equal (Comptroller MaxAssets) 20 - Assert Equal (Comptroller Implementation) (Address ScenComptrollerG1) - ComptrollerImpl Deploy ScenarioG1 ScenComptrollerG1_2 - Unitroller SetPendingImpl ScenComptrollerG1_2 - ComptrollerImpl ScenComptrollerG1_2 BecomeG1 (PriceOracle Address) 0.4 40 - Assert Equal (Comptroller CloseFactor) 0.4 - Assert Equal (Comptroller MaxAssets) 40 - Assert Equal (Comptroller Implementation) (Address ScenComptrollerG1_2) - ---G1 recome -Test "Recome has default values" - Unitroller Deploy - PriceOracle Deploy Fixed 1.0 - ComptrollerImpl Deploy ScenarioG1 ScenComptrollerG1 - Unitroller SetPendingImpl ScenComptrollerG1 - ComptrollerImpl ScenComptrollerG1 Recome - Assert Equal (Comptroller CloseFactor) 0.0 - Assert Equal (Comptroller MaxAssets) 0 - Assert Equal (Comptroller Implementation) (Address ScenComptrollerG1) - ---G1 bork -Test "Bork and unbork" - Unitroller Deploy - PriceOracle Deploy Fixed 1.0 - ComptrollerImpl Deploy ScenarioG1 ScenComptrollerG1 - -- Set a normal impl - Unitroller SetPendingImpl ScenComptrollerG1 - ComptrollerImpl ScenComptrollerG1 BecomeG1 (PriceOracle Address) 0.2 20 - Assert Equal (Comptroller CloseFactor) 0.2 - Assert Equal (Comptroller MaxAssets) 20 - Assert Equal (Comptroller Implementation) (Address ScenComptrollerG1) - -- Now move to a borked one that's bad - ComptrollerImpl Deploy Borked MyBork - Unitroller SetPendingImpl MyBork - ComptrollerImpl MyBork BecomeG1 (PriceOracle Address) 0.4 40 - Assert ReadRevert (Comptroller CloseFactor) "revert" - Assert Equal (Comptroller Implementation) (Address MyBork) - -- Now change back to the first good one - Unitroller SetPendingImpl ScenComptrollerG1 - ComptrollerImpl ScenComptrollerG1 Recome - Assert Equal (Comptroller CloseFactor) 0.2 - Assert Equal (Comptroller MaxAssets) 20 - Assert Equal (Comptroller Implementation) (Address ScenComptrollerG1) - -Macro CheckUnitrollerStorage implementation - -- Admin; 0 - Assert Equal (Comptroller Admin) (Address Root) - Assert Equal (StorageAt Comptroller 0 0 "address") (Address Root) - -- PendingAdmin; 1 - Assert Equal (Comptroller PendingAdmin) (Address Coburn) - Assert Equal (StorageAt Comptroller 1 0 "address") (Address Coburn) - -- ComptrollerImplementation; 2 - Assert Equal (Unitroller Implementation) implementation - Assert Equal (StorageAt Comptroller 2 0 "address") implementation - -- PendingComptrollerImplementation; 3 - -- check as number since casting address 0 is not defined - Assert Equal (StorageAt Comptroller 3 0 "number") 0 - -Macro CheckV1Storage - -- Oracle; 4 - Assert Equal (Comptroller PriceOracle) (Address PriceOracle) - Assert Equal (StorageAt Comptroller 4 0 "address") (Address PriceOracle) - -- CloseFactorMantissa; 5 - Assert Equal (Comptroller CloseFactor) 0.2 - Assert Equal (StorageAt Comptroller 5 0 "number") 0.2e18 - -- LiquidationIncentiveMantissa; 6 - Assert Equal (Comptroller LiquidationIncentive) 1 - Assert Equal (StorageAt Comptroller 6 0 "number") 1e18 - -- MaxAssets; 7 - Assert Equal (Comptroller MaxAssets) 20 - Assert Equal (StorageAt Comptroller 7 0 "number") 20 - -- AccountAssets; 8 * - Assert Equal (StorageAt Comptroller 8 0 "number") 0 - Assert Equal (StorageAtMapping Comptroller 8 (Address Geoff) "number") 2 - Assert Equal (StorageAtMapping Comptroller 8 (Address Geoff) "list(address)") [(Address cZRX) (Address cBAT)] - Assert Equal (Comptroller AssetsIn Geoff) [(Address cZRX) (Address cBAT)] - -- Markets; 9 * - Assert Equal (StorageAt Comptroller 9 0 "number") 0 - Assert Equal (StorageAtNestedMapping Comptroller 9 (Address cZRX) Geoff "marketStruct") [True 0.5 True] - Assert Equal (StorageAtNestedMapping Comptroller 9 (Address cBAT) Geoff "marketStruct") [True 0.4 True] - Assert Equal (StorageAtNestedMapping Comptroller 9 (Address cBAT) Coburn "marketStruct") [True 0.4 False] - Assert Equal (Comptroller CollateralFactor cZRX) 0.5 - Assert Equal (Comptroller CollateralFactor cBAT) 0.4 - Assert Equal (Comptroller CheckMembership Geoff cZRX) True - Assert Equal (Comptroller CheckMembership Geoff cBAT) True - -Macro CheckV2Storage - -- PauseGuardian; 10 - Assert Equal (Comptroller PauseGuardian) (Address Coburn) - Assert Equal (StorageAt Comptroller 10 0 "address") (Address Coburn) - -- MintGuardianPaused; 11 - Assert Equal (StorageAt Comptroller 10 40 "bool") False - Assert Equal (Comptroller _MintGuardianPaused) False - -- BorrowGuardianPaused; 12 - Assert Equal (StorageAt Comptroller 10 42 "bool") False - Assert Equal (Comptroller _BorrowGuardianPaused) False - -- TransferGuardianPaused; 13 - Assert Equal (StorageAt Comptroller 10 44 "bool") False - From Coburn (Comptroller SetGuardianPaused "Transfer" True) - Assert Equal (Comptroller TransferGuardianPaused) True - Assert Equal (StorageAt Comptroller 10 44 "bool") True - Comptroller SetGuardianPaused "Transfer" False - -- SeizeGuardianPaused; 14 - Assert Equal (StorageAt Comptroller 10 46 "bool") False - From Coburn (Comptroller SetGuardianPaused "Seize" True) - Assert Equal (Comptroller SeizeGuardianPaused) True - Assert Equal (StorageAt Comptroller 10 46 "bool") True - Comptroller SetGuardianPaused "Seize" False - -- - -- Pause by market storage - -- - -- MintGuardianPaused; 15 - Assert Equal (StorageAtMapping Comptroller 11 (Address cZRX) "bool") False - From Coburn (Comptroller SetGuardianMarketPaused cZRX "Mint" True) - Assert Equal (Comptroller MintGuardianMarketPaused cZRX) True - Assert Equal (StorageAtMapping Comptroller 11 (Address cZRX) "bool") True - Comptroller SetGuardianMarketPaused cZRX "Mint" False - -- BorrowGuardianPaused; 16 - Assert Equal (StorageAtMapping Comptroller 12 (Address cZRX) "bool") False - From Coburn (Comptroller SetGuardianMarketPaused cZRX "Borrow" True) - Assert Equal (Comptroller BorrowGuardianMarketPaused cZRX) True - Assert Equal (StorageAtMapping Comptroller 12 (Address cZRX) "bool") True - Comptroller SetGuardianMarketPaused cZRX "Borrow" False - -Macro CheckV3Storage - -- AllMarkets; 17 - Assert Equal (StorageAt Comptroller 13 0 "number") 2 - -- TODO: StorageAtArray Comptroller 13? - -- CompRate; 18 - Assert Equal (StorageAt Comptroller 14 0 "number") 1e18 - -- CompSpeeds; 19 - Assert Equal (StorageAt Comptroller 15 0 "number") 0 - -- CompSupplyState; 20 - Assert Equal (StorageAt Comptroller 16 0 "number") 0 - -- CompBorrowState; 21 - Assert Equal (StorageAt Comptroller 17 0 "number") 0 - -- CompSupplierIndex; 22 - Assert Equal (StorageAt Comptroller 18 0 "number") 0 - -- CompBorrowerIndex; 23 - Assert Equal (StorageAt Comptroller 19 0 "number") 0 - -- CompAccrued; 24 - Assert Equal (StorageAt Comptroller 20 0 "number") 0 - --- Times out coverage, disable for now - ideally set flag to not run in coverage -Pending "Keeps all storage" - Unitroller Deploy - PriceOracle Deploy Fixed 1.0 - ComptrollerImpl Deploy StandardG1 ComptrollerG1 - Unitroller SetPendingImpl ComptrollerG1 - ComptrollerImpl ComptrollerG1 BecomeG1 (PriceOracle Address) 0.2 20 - Comptroller SetPendingAdmin Coburn - --- - NewCToken ZRX cZRX delegatorType:CErc20Delegator cTokenType:CErc20Delegate - NewCToken BAT cBAT delegatorType:CErc20Delegator cTokenType:CErc20Delegate - Comptroller SetMarketSupplyCaps (cZRX) (2e30) - Comptroller SetMarketSupplyCaps (cBAT) (2e30) - Give cBAT 10e18 BAT -- Faucet some bat to borrow - Support cZRX collateralFactor:0.5 - Support cBAT collateralFactor:0.4 - Prep Geoff Some ZRX cZRX - Mint Geoff 100e18 cZRX - EnterMarkets Geoff cZRX cBAT - Borrow Geoff 1e18 cBAT - -- - CheckUnitrollerStorage (Address ComptrollerG1) - CheckV1Storage - -- - ComptrollerImpl Deploy StandardG2 ComptrollerG2 - Unitroller SetPendingImpl ComptrollerG2 - Assert Equal (Unitroller PendingImplementation) (Address ComptrollerG2) - Assert Equal (StorageAt Comptroller 3 0 "address") (Address ComptrollerG2) - ComptrollerImpl ComptrollerG2 BecomeG2 - Comptroller SetPauseGuardian Coburn - -- - CheckUnitrollerStorage (Address ComptrollerG2) - CheckV1Storage - CheckV2Storage - -- - ComptrollerImpl Deploy StandardG3 ComptrollerG3 - Unitroller SetPendingImpl ComptrollerG3 - ComptrollerImpl ComptrollerG3 BecomeG3 1e18 [cZRX cBAT] - -- - CheckUnitrollerStorage (Address ComptrollerG3) - CheckV1Storage - CheckV2Storage - CheckV3Storage - -- - ComptrollerImpl Deploy Standard ComptrollerG4 - Unitroller SetPendingImpl ComptrollerG4 - ComptrollerImpl ComptrollerG4 Become - -- - CheckUnitrollerStorage (Address ComptrollerG4) - CheckV1Storage - CheckV2Storage - CheckV3Storage From 6355810b28203dddc93c670682d0438cf11391ba Mon Sep 17 00:00:00 2001 From: Kirill Kuvshinov Date: Thu, 21 Sep 2023 13:52:55 +0300 Subject: [PATCH 05/33] refactor: remove Compound's governance simulations * Governance simulations in Venus are done via a separate simulations framework located at https://github.com/VenusProtocol/vips * This commit removes legacy Compound simulations in favor of using the new framework --- .../0001-comp-distribution-patch/deploy.scen | 8 - .../hypothetical_upgrade.scen | 176 ------------ .../hypothetical_upgrade_post_deploy.scen | 172 ----------- .../hypothetical_upgrade_post_propose.scen | 169 ----------- .../kovan/execute.scen | 8 - .../kovan/queue.scen | 8 - .../ropsten/execute.scen | 8 - .../ropsten/queue.scen | 8 - .../0002-dai-irm-v3/hypothetical_upgrade.scen | 52 ---- spec/sim/0003-borrow-caps-patch/deploy.scen | 8 - .../hypothetical_upgrade.scen | 48 ---- .../hypothetical_upgrade_post_deploy.scen | 46 --- .../hypothetical_upgrade_post_propose.scen | 32 --- .../hypothetical_upgrade.scen | 30 -- spec/sim/0005-grants/deploy.scen | 8 - .../sim/0005-grants/hypothetical_upgrade.scen | 98 ------- .../hypothetical_upgrade_multiple_speed.scen | 86 ------ .../hypothetical_upgrade_post_propose.scen | 31 -- .../0006-setspeed-manual-claims/deploy.scen | 8 - .../hypothetical_upgrade.scen | 102 ------- .../hypothetical_upgrade_borrower.scen | 53 ---- .../hypothetical_upgrade_post_deploy.scen | 95 ------- .../hypothetical_upgrade_post_propose.scen | 86 ------ .../hypothetical_migration.scen | 44 --- .../hypothetical_migration_post_propose.scen | 47 --- .../hypothetical_migration.scen | 42 --- .../hypothetical_migration_post_deploy.scen | 42 --- .../hypothetical_migration_post_propose.scen | 48 ---- .../0009-gov-bravo/hypothetical_upgrade.scen | 43 --- .../hypothetical_upgrade_post_deploy.scen | 42 --- .../hypothetical_upgrade_post_propose.scen | 48 ---- .../kovan/hypothetical_upgrade_kovan.scen | 41 --- .../hypothetical-ctoken-upgrade.scen | 39 --- .../hypothetical_mainnet_upgrade.scen | 269 ------------------ .../hypothetical_upgrade.scen | 40 --- .../hypothetical_upgrade_post_deploy.scen | 48 ---- .../hypothetical_upgrade_post_propose.scen | 47 --- .../hypothetical_mainnet_upgrade.scen | 109 ------- .../hypothetical_mainnet_upgrade.scen | 97 ------- .../mainnet_upgrade.scen | 89 ------ .../post_deploy.scen | 52 ---- .../pre_deploy.scen | 51 ---- 42 files changed, 2578 deletions(-) delete mode 100755 spec/sim/0001-comp-distribution-patch/deploy.scen delete mode 100755 spec/sim/0001-comp-distribution-patch/hypothetical_upgrade.scen delete mode 100755 spec/sim/0001-comp-distribution-patch/hypothetical_upgrade_post_deploy.scen delete mode 100755 spec/sim/0001-comp-distribution-patch/hypothetical_upgrade_post_propose.scen delete mode 100755 spec/sim/0001-comp-distribution-patch/kovan/execute.scen delete mode 100755 spec/sim/0001-comp-distribution-patch/kovan/queue.scen delete mode 100755 spec/sim/0001-comp-distribution-patch/ropsten/execute.scen delete mode 100755 spec/sim/0001-comp-distribution-patch/ropsten/queue.scen delete mode 100755 spec/sim/0002-dai-irm-v3/hypothetical_upgrade.scen delete mode 100755 spec/sim/0003-borrow-caps-patch/deploy.scen delete mode 100755 spec/sim/0003-borrow-caps-patch/hypothetical_upgrade.scen delete mode 100755 spec/sim/0003-borrow-caps-patch/hypothetical_upgrade_post_deploy.scen delete mode 100755 spec/sim/0003-borrow-caps-patch/hypothetical_upgrade_post_propose.scen delete mode 100755 spec/sim/0004-cusdc-irm-update/hypothetical_upgrade.scen delete mode 100755 spec/sim/0005-grants/deploy.scen delete mode 100755 spec/sim/0005-grants/hypothetical_upgrade.scen delete mode 100755 spec/sim/0005-grants/hypothetical_upgrade_multiple_speed.scen delete mode 100755 spec/sim/0005-grants/hypothetical_upgrade_post_propose.scen delete mode 100755 spec/sim/0006-setspeed-manual-claims/deploy.scen delete mode 100755 spec/sim/0006-setspeed-manual-claims/hypothetical_upgrade.scen delete mode 100755 spec/sim/0006-setspeed-manual-claims/hypothetical_upgrade_borrower.scen delete mode 100755 spec/sim/0006-setspeed-manual-claims/hypothetical_upgrade_post_deploy.scen delete mode 100755 spec/sim/0006-setspeed-manual-claims/hypothetical_upgrade_post_propose.scen delete mode 100755 spec/sim/0007-cdai-impl-migration/hypothetical_migration.scen delete mode 100755 spec/sim/0007-cdai-impl-migration/hypothetical_migration_post_propose.scen delete mode 100755 spec/sim/0008-sweep-token/hypothetical_migration.scen delete mode 100755 spec/sim/0008-sweep-token/hypothetical_migration_post_deploy.scen delete mode 100755 spec/sim/0008-sweep-token/hypothetical_migration_post_propose.scen delete mode 100755 spec/sim/0009-gov-bravo/hypothetical_upgrade.scen delete mode 100755 spec/sim/0009-gov-bravo/hypothetical_upgrade_post_deploy.scen delete mode 100755 spec/sim/0009-gov-bravo/hypothetical_upgrade_post_propose.scen delete mode 100755 spec/sim/0009-gov-bravo/kovan/hypothetical_upgrade_kovan.scen delete mode 100755 spec/sim/0010-liq-incentive/hypothetical-ctoken-upgrade.scen delete mode 100755 spec/sim/0011-split-comp-rewards/hypothetical_mainnet_upgrade.scen delete mode 100755 spec/sim/0011-whitelist-accounts/hypothetical_upgrade.scen delete mode 100755 spec/sim/0011-whitelist-accounts/hypothetical_upgrade_post_deploy.scen delete mode 100755 spec/sim/0011-whitelist-accounts/hypothetical_upgrade_post_propose.scen delete mode 100755 spec/sim/0064-fix-comp-accruals/hypothetical_mainnet_upgrade.scen delete mode 100755 spec/sim/0065-correct-bad-comp-accruals/hypothetical_mainnet_upgrade.scen delete mode 100755 spec/sim/0065-correct-bad-comp-accruals/mainnet_upgrade.scen delete mode 100755 spec/sim/0089-lower-proposal-threshold-v2/post_deploy.scen delete mode 100755 spec/sim/0089-lower-proposal-threshold-v2/pre_deploy.scen diff --git a/spec/sim/0001-comp-distribution-patch/deploy.scen b/spec/sim/0001-comp-distribution-patch/deploy.scen deleted file mode 100755 index d7729b6f6..000000000 --- a/spec/sim/0001-comp-distribution-patch/deploy.scen +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/env yarn repl -n mainnet -s - -PrintTransactionLogs - --- Deploy the flywheel impl -ComptrollerImpl Deploy Standard StdComptrollerG4 - -Print "Deployed OK!" diff --git a/spec/sim/0001-comp-distribution-patch/hypothetical_upgrade.scen b/spec/sim/0001-comp-distribution-patch/hypothetical_upgrade.scen deleted file mode 100755 index c65586c0b..000000000 --- a/spec/sim/0001-comp-distribution-patch/hypothetical_upgrade.scen +++ /dev/null @@ -1,176 +0,0 @@ -#!/usr/bin/env yarn repl -s - -PrintTransactionLogs -Alias CompHolder "0x19bc62ff7cd9ffd6bdced9802ff718f09f7259f1" -Alias USDCWhale "0x92d7796c04ee34d1d16c57fab92fc2bccf434468" -Alias cBATBorrower "0xe5f3dbcc3dcf75a6946822aae7df5160505d3069" -Web3Fork "https://mainnet-eth.compound.finance/@10331520" (CompHolder USDCWhale cBATBorrower) -UseConfigs mainnet - --- Deploy the flywheel impl - -ComptrollerImpl Deploy Standard ComptrollerG4 - --- Propose to apply the patch - -From CompHolder (Comp Delegate CompHolder) -From CompHolder (Governor GovernorAlpha Propose "COMP Distribution Patch" [(Address Unitroller) (Address ComptrollerG4)] [0 0] ["_setPendingImplementation(address)" "_become(address)"] [[(Address ComptrollerG4)] [(Address Unitroller)]]) - --- Vote for, queue, and execute the proposal - -MineBlock -From CompHolder (Governor GovernorAlpha Proposal LastProposal Vote For) -AdvanceBlocks 20000 -Governor GovernorAlpha Proposal LastProposal Queue -IncreaseTime 604910 -Governor GovernorAlpha Proposal LastProposal Execute - --- Sanity check the upgrade - -Assert Equal (Comptroller CompRate) 0.25e18 -Assert Equal (Comptroller CheckIsComped cBAT) True -Assert Equal (Comptroller CheckIsComped cDAI) True -Assert Equal (Comptroller CheckIsComped cETH) True -Assert Equal (Comptroller CheckIsComped cREP) True -Assert Equal (Comptroller CheckIsComped cSAI) False -Assert Equal (Comptroller CheckIsComped cUSDC) True -Assert Equal (Comptroller CheckIsComped cUSDT) True -Assert Equal (Comptroller CheckisComped cWBTC) True -Assert Equal (Comptroller CheckIsComped cZRX) True - --- Sanity check the speeds - -Assert Equal (Comptroller CompSpeed cBAT) 0.211801939788283286e18 -Assert Equal (Comptroller CompSpeed cDAI) 0.001175763573454607e18 -Assert Equal (Comptroller CompSpeed cETH) 0.000020887685831991e18 -Assert Equal (Comptroller CompSpeed cREP) 0.000007175802675015e18 -Assert Equal (Comptroller CompSpeed cSAI) 0 -Assert Equal (Comptroller CompSpeed cUSDC) 0.000884273506888560e18 -Assert Equal (Comptroller CompSpeed cUSDT) 0.020341204032904166e18 -Assert Equal (Comptroller CompSpeed cWBTC) 0.005869479211613005e18 -Assert Equal (Comptroller CompSpeed cZRX) 0.009899276398349366e18 - --- Check the market borrows - -Assert Equal (CToken cBAT TotalBorrows) 816167647101108360363936140 -Assert Equal (CToken cDAI TotalBorrows) 23521775646627969501566436 -Assert Equal (CToken cETH TotalBorrows) 1260824767124865834187 -Assert Equal (CToken cREP TotalBorrows) 5305791273320090270164 -Assert Equal (CToken cSAI TotalBorrows) 87120566019791136455808 -Assert Equal (CToken cUSDC TotalBorrows) 9369602511430 -Assert Equal (CToken cUSDT TotalBorrows) 51344064688134 -Assert Equal (CToken cWBTC TotalBorrows) 134858882039 -Assert Equal (CToken cZRX TotalBorrows) 54734120640511560139309871 - --- Check the market prices - -Assert Equal (PriceOracleProxy Price cBAT) 1057982500000000 -Assert Equal (PriceOracleProxy Price cDAI) 4296489354886929 -Assert Equal (PriceOracleProxy Price cETH) 1000000000000000000 -Assert Equal (PriceOracleProxy Price cREP) 71436527500000010 -Assert Equal (PriceOracleProxy Price cSAI) 5285551943761727 -Assert Equal (PriceOracleProxy Price cUSDC) 4261783149807061700000000000 -Assert Equal (PriceOracleProxy Price cUSDT) 4261783149807061700000000000 -Assert Equal (PriceOracleProxy Price cWBTC) 397626172108253540000000000000 -Assert Equal (PriceOracleProxy Price cZRX) 1464966666666666 - --- Refresh speeds - -Comptroller RefreshCompSpeeds - --- Check the new speeds match utility metric --- Total Utility = --- 816167647101108360363936140 * 1057982500000000 + --- 23521775646627969501566436 * 4296489354886929 + --- 1260824767124865834187 * 1000000000000000000 + --- 5305791273320090270164 * 71436527500000010 + --- 87120566019791136455808 * 5285551943761727 * 0 (cSAI not comped) + --- 9369602511430 * 4261783149807061700000000000 + --- 51344064688134 * 4261783149807061700000000000 + --- 134858882039 * 397626172108253540000000000000 + --- 54734120640511560139309871 * 1464966666666666 --- = 1358747565585977723277660096116431304676770 - --- .25e18 * 816167647101108360363936140 * 1057982500000000 / 1358747565585977723277660096116431304676770 --- = 158876289748264717 -Assert Equal (Comptroller CompSpeed cBAT) 158876289748264702 - --- .25e18 * 23521775646627969501566436 * 4296489354886929 / 1358747565585977723277660096116431304676770 --- = 18594524331344760 -Assert Equal (Comptroller CompSpeed cDAI) 18594524331344758 - --- .25e18 * 1260824767124865834187 * 1000000000000000000 / 1358747565585977723277660096116431304676770 --- = 231982893485648 -Assert Equal (Comptroller CompSpeed cETH) 231982893485648 - --- .25e18 * 5305791273320090270164 * 71436527500000010 / 1358747565585977723277660096116431304676770 --- = 69738359391711 -Assert Equal (Comptroller CompSpeed cREP) 69738359391711 - --- not comped -Assert Equal (Comptroller CompSpeed cSAI) 0 - --- .25e18 * 9369602511430 * 4261783149807061700000000000 / 1358747565585977723277660096116431304676770 --- = 7347062676498972 -Assert Equal (Comptroller CompSpeed cUSDC) 7347062676498971 - --- .25e18 * 51344064688134 * 4261783149807061700000000000 / 1358747565585977723277660096116431304676770 --- = 40260839333339567 -Assert Equal (Comptroller CompSpeed cUSDT) 40260839333339565 - --- .25e18 * 134858882039 * 397626172108253540000000000000 / 1358747565585977723277660096116431304676770 --- = 9866332495845221 -Assert Equal (Comptroller CompSpeed cWBTC) 9866332495845221 - --- .25e18 * 54734120640511560139309871 * 1464966666666666 / 1358747565585977723277660096116431304676770 --- = 14753230161829421 -Assert Equal (Comptroller CompSpeed cZRX) 14753230161829420 - --- Now sanity check that we can continue to use the market as usual - --- First check the USDC Whale, mint - -Assert Equal (Erc20 cUSDC TokenBalance USDCWhale) 0 - -From USDCWhale (Trx GasPrice 0 (Erc20 USDC Approve cUSDC UInt256Max)) -From USDCWhale (Trx GasPrice 0 (CToken cUSDC Mint 10000e6)) - -Assert Equal (Erc20 cUSDC TokenBalance USDCWhale) 47481980579468 -Assert Equal (Erc20 cUSDC TotalSupply) 927050045835492296 - --- Next check the BAT borrower, borrow a little more - -Assert Equal (Erc20 cETH TokenBalance cBATBorrower) 384765976900 -Assert Equal (Erc20 cETH TotalSupply) 4585405574577755 - -Assert Equal (CToken cBAT BorrowBalance cBATBorrower) 37550980777226218529804 -Assert Equal (CToken cBAT TotalBorrows) 816167647101108360363936140 - -Expect Changes (CToken cBAT BorrowBalance cBATBorrower) 6666005042256047300989 -From cBATBorrower (CToken cBAT Borrow 6666000000000000000000) - -Assert Equal (CToken cBAT BorrowBalance cBATBorrower) 44216985819482265830793 -Assert Equal (CToken cBAT TotalBorrows) 818374059192055804747435060 - --- Claim comp to true up their balances - -Comptroller ClaimComp USDCWhale -Comptroller ClaimComp cBATBorrower - --- Now move the clock forward - -AdvanceBlocks 1000000 - --- And check that they receive the right amount of COMP when claimed - --- cUSDC: 47481980579468 / 927050045835492296 * 7347062676498971 * 1e6 = 376304482038247230 -Expect Changes (Erc20 Comp TokenBalance USDCWhale) 0.376305610951693392e18 -Comptroller ClaimComp USDCWhale - --- cETH: 384765976900 / 4585405574577755 * 231982893485648 * 1e6 = 19465917067611490 --- cBAT: 44216985819482265830793 / 818374059192055804747435060 * 158876289748264702 * 1e6 = 8584131635094196000 --- = 0.01946591706761149 + 8.584131635094196000 = 8.603597552161807 -Expect Changes (Erc20 Comp TokenBalance cBATBorrower) 8.603623362954463581e18 -Comptroller ClaimComp cBATBorrower - -Print "COMP distribution patch OK!" diff --git a/spec/sim/0001-comp-distribution-patch/hypothetical_upgrade_post_deploy.scen b/spec/sim/0001-comp-distribution-patch/hypothetical_upgrade_post_deploy.scen deleted file mode 100755 index 2be610004..000000000 --- a/spec/sim/0001-comp-distribution-patch/hypothetical_upgrade_post_deploy.scen +++ /dev/null @@ -1,172 +0,0 @@ -#!/usr/bin/env yarn repl -s - -PrintTransactionLogs -Alias CompHolder "0x19bc62ff7cd9ffd6bdced9802ff718f09f7259f1" -Alias USDCWhale "0x92d7796c04ee34d1d16c57fab92fc2bccf434468" -Alias cBATBorrower "0xe5f3dbcc3dcf75a6946822aae7df5160505d3069" -Web3Fork "https://mainnet-eth.compound.finance/@10348955" (CompHolder USDCWhale cBATBorrower) -UseConfigs mainnet - --- Propose to apply the patch - -From CompHolder (Comp Delegate CompHolder) -From CompHolder (Governor GovernorAlpha Propose "COMP Distribution Patch" [(Address Unitroller) (Address StdComptrollerG4)] [0 0] ["_setPendingImplementation(address)" "_become(address)"] [[(Address StdComptrollerG4)] [(Address Unitroller)]]) - --- Vote for, queue, and execute the proposal - -MineBlock -From CompHolder (Governor GovernorAlpha Proposal LastProposal Vote For) -AdvanceBlocks 20000 -Governor GovernorAlpha Proposal LastProposal Queue -IncreaseTime 604910 -Governor GovernorAlpha Proposal LastProposal Execute - --- Sanity check the upgrade - -Assert Equal (Comptroller CompRate) 0.22e18 -Assert Equal (Comptroller CheckIsComped cBAT) True -Assert Equal (Comptroller CheckIsComped cDAI) True -Assert Equal (Comptroller CheckIsComped cETH) True -Assert Equal (Comptroller CheckIsComped cREP) True -Assert Equal (Comptroller CheckIsComped cSAI) False -Assert Equal (Comptroller CheckIsComped cUSDC) True -Assert Equal (Comptroller CheckIsComped cUSDT) True -Assert Equal (Comptroller CheckisComped cWBTC) True -Assert Equal (Comptroller CheckIsComped cZRX) True - --- Sanity check the speeds - -Assert Equal (Comptroller CompSpeed cBAT) 0.203121569295974918e18 -Assert Equal (Comptroller CompSpeed cDAI) 0.001103447907469680e18 -Assert Equal (Comptroller CompSpeed cETH) 0.000017970643503360e18 -Assert Equal (Comptroller CompSpeed cREP) 0.000127756157903774e18 -Assert Equal (Comptroller CompSpeed cSAI) 0 -Assert Equal (Comptroller CompSpeed cUSDC) 0.000940109498639776e18 -Assert Equal (Comptroller CompSpeed cUSDT) 0.008447487333746899e18 -Assert Equal (Comptroller CompSpeed cWBTC) 0.004841175362144006e18 -Assert Equal (Comptroller CompSpeed cZRX) 0.001400483800617582e18 - --- Check the market borrows - -Assert Equal (CToken cBAT TotalBorrows) 933675278927019769365181653 -Assert Equal (CToken cDAI TotalBorrows) 28288631632222856320436141 -Assert Equal (CToken cETH TotalBorrows) 1489418340783050403890 -Assert Equal (CToken cREP TotalBorrows) 83744752724324161827907 -Assert Equal (CToken cSAI TotalBorrows) 85694017918878755539524 -Assert Equal (CToken cUSDC TotalBorrows) 13559619925496 -Assert Equal (CToken cUSDT TotalBorrows) 34881672655224 -Assert Equal (CToken cWBTC TotalBorrows) 148448436871 -Assert Equal (CToken cZRX TotalBorrows) 17678865043142504899157201 - --- Check the market prices - -Assert Equal (PriceOracleProxy Price cBAT) 1241500000000000 -Assert Equal (PriceOracleProxy Price cDAI) 4429377994656539 -Assert Equal (PriceOracleProxy Price cETH) 1000000000000000000 -Assert Equal (PriceOracleProxy Price cREP) 73035785000000000 -Assert Equal (PriceOracleProxy Price cSAI) 5285551943761727 -Assert Equal (PriceOracleProxy Price cUSDC) 4442302859110025000000000000 -Assert Equal (PriceOracleProxy Price cUSDT) 4442302859110025000000000000 -Assert Equal (PriceOracleProxy Price cWBTC) 401937357611677730000000000000 -Assert Equal (PriceOracleProxy Price cZRX) 1506198333333333 - --- Refresh speeds - -Comptroller RefreshCompSpeeds - --- Check the new speeds match utility metric --- Total Utility = --- 933675278927019769365181653 * 1241500000000000 + --- 28288631632222856320436141 * 4429377994656539 + --- 1489418340783050403890 * 1000000000000000000 + --- 83744752724324161827907 * 73035785000000000 + --- 85694017918878755539524 * 5285551943761727 * 0 (cSAI not comped) + --- 13559619925496 * 4442302859110025000000000000 + --- 34881672655224 * 4442302859110025000000000000 + --- 148448436871 * 401937357611677730000000000000 + --- 17678865043142504899157201 * 1506198333333333 --- = 1593550425385280362248038892811635677856932 - --- .22e18 * 933675278927019769365181653 * 1241500000000000 / 1593550425385280362248038892811635677856932 --- = 160029281076361760 -Assert Equal (Comptroller CompSpeed cBAT) 0.160029281076361778e18 - --- .22e18 * 28288631632222856320436141 * 4429377994656539 / 1593550425385280362248038892811635677856932 --- = 17298623815115230 -Assert Equal (Comptroller CompSpeed cDAI) 0.017298623815115231e18 - --- .22e18 * 1489418340783050403890 * 1000000000000000000 / 1593550425385280362248038892811635677856932 --- = 205623888489784 -Assert Equal (Comptroller CompSpeed cETH) 0.000205623888489784e18 - --- .22e18 * 83744752724324161827907 * 73035785000000000 / 1593550425385280362248038892811635677856932 --- = 844403794590991 -Assert Equal (Comptroller CompSpeed cREP) 0.000844403794590990e18 - --- not comped -Assert Equal (Comptroller CompSpeed cSAI) 0 - --- .22e18 * 13559619925496 * 4442302859110025000000000000 / 1593550425385280362248038892811635677856932 --- = 8315963040053016 -Assert Equal (Comptroller CompSpeed cUSDC) 0.008315963040053015e18 - --- .22e18 * 34881672655224 * 4442302859110025000000000000 / 1593550425385280362248038892811635677856932 --- = 21392539183981588 -Assert Equal (Comptroller CompSpeed cUSDT) 0.021392539183981590e18 - --- .22e18 * 148448436871 * 401937357611677730000000000000 / 1593550425385280362248038892811635677856932 --- = 8237413596422151 -Assert Equal (Comptroller CompSpeed cWBTC) 0.008237413596422151e18 - --- .22e18 * 17678865043142504899157201 * 1506198333333333 / 1593550425385280362248038892811635677856932 --- = 3676151604985456 -Assert Equal (Comptroller CompSpeed cZRX) 0.003676151604985456e18 - --- Now sanity check that we can continue to use the market as usual - --- First check the USDC Whale, mint - -Assert Equal (Erc20 cUSDC TokenBalance USDCWhale) 0 - -From USDCWhale (Trx GasPrice 0 (Erc20 USDC Approve cUSDC UInt256Max)) -From USDCWhale (Trx GasPrice 0 (CToken cUSDC Mint 10000e6)) - -Assert Equal (Erc20 cUSDC TokenBalance USDCWhale) 47481175626857 -Assert Equal (Erc20 cUSDC TotalSupply) 1067945787269646173 - --- Next check the BAT borrower, borrow a little more - -Assert Equal (Erc20 cETH TokenBalance cBATBorrower) 1034370824418 -Assert Equal (Erc20 cETH TotalSupply) 5163948275203265 - -Assert Equal (CToken cBAT BorrowBalance cBATBorrower) 123004206941461188039104 -Assert Equal (CToken cBAT TotalBorrows) 933675278927019769365181653 - -Expect Changes (CToken cBAT BorrowBalance cBATBorrower) 6666016377088188607420 -From cBATBorrower (CToken cBAT Borrow 6666000000000000000000) - -Assert Equal (CToken cBAT BorrowBalance cBATBorrower) 129670223318549376646524 -Assert Equal (CToken cBAT TotalBorrows) 936176444748237020604963003 - --- Claim comp to true up their balances - -Comptroller ClaimComp USDCWhale -Comptroller ClaimComp cBATBorrower - --- Now move the clock forward - -AdvanceBlocks 1000000 - --- And check that they receive the right amount of COMP when claimed - --- cUSDC: 47481175626857 / 1067945787269646173 * 8315963040053015 * 1e6 = 369730098960081900 -Expect Changes (Erc20 Comp TokenBalance USDCWhale) 0.369731208150378785e18 -Comptroller ClaimComp USDCWhale - --- cETH: 1034370824418 / 5163948275203265 * 205623888489784 * 1e6 = 41187738474944500 --- cBAT: 123004206941461188039104 / 933675278927019769365181653 * 160029281076361778 * 1e6 = 21082570408023708000 --- = 0.041187738474944495 + 21.082570408023706 = 21.123758146498652 -Expect Changes (Erc20 Comp TokenBalance cBATBorrower) 22.576722556314661630e18 -Comptroller ClaimComp cBATBorrower - -Print "COMP distribution patch OK!" diff --git a/spec/sim/0001-comp-distribution-patch/hypothetical_upgrade_post_propose.scen b/spec/sim/0001-comp-distribution-patch/hypothetical_upgrade_post_propose.scen deleted file mode 100755 index fe6d33b18..000000000 --- a/spec/sim/0001-comp-distribution-patch/hypothetical_upgrade_post_propose.scen +++ /dev/null @@ -1,169 +0,0 @@ -#!/usr/bin/env yarn repl -s - -PrintTransactionLogs -Alias CompVoter1 "0xf25f26a42adcb153b1966a4bf5df6d0c9e27197f" -Alias CompVoter2 "0xed409c9ff60f3020abf9012bcd45fc294f5608ff" -Alias USDCWhale "0x92d7796c04ee34d1d16c57fab92fc2bccf434468" -Alias cBATBorrower "0xe5f3dbcc3dcf75a6946822aae7df5160505d3069" -Web3Fork "https://mainnet-eth.compound.finance/@10351502" (CompVoter1 CompVoter2 USDCWhale cBATBorrower) -UseConfigs mainnet - --- Vote for, queue, and execute the proposal - -MineBlock -From CompVoter1 (Governor GovernorAlpha Proposal 11 Vote For) -From CompVoter2 (Governor GovernorAlpha Proposal 11 Vote For) -AdvanceBlocks 20000 -Governor GovernorAlpha Proposal 11 Queue -IncreaseTime 604910 -Governor GovernorAlpha Proposal 11 Execute - --- Sanity check the upgrade - -Assert Equal (Comptroller CompRate) 0.22e18 -Assert Equal (Comptroller CheckIsComped cBAT) True -Assert Equal (Comptroller CheckIsComped cDAI) True -Assert Equal (Comptroller CheckIsComped cETH) True -Assert Equal (Comptroller CheckIsComped cREP) True -Assert Equal (Comptroller CheckIsComped cSAI) False -Assert Equal (Comptroller CheckIsComped cUSDC) True -Assert Equal (Comptroller CheckIsComped cUSDT) True -Assert Equal (Comptroller CheckisComped cWBTC) True -Assert Equal (Comptroller CheckIsComped cZRX) True - --- Sanity check the speeds - -Assert Equal (Comptroller CompSpeed cBAT) 0.203121569295974918e18 -Assert Equal (Comptroller CompSpeed cDAI) 0.001103447907469680e18 -Assert Equal (Comptroller CompSpeed cETH) 0.000017970643503360e18 -Assert Equal (Comptroller CompSpeed cREP) 0.000127756157903774e18 -Assert Equal (Comptroller CompSpeed cSAI) 0 -Assert Equal (Comptroller CompSpeed cUSDC) 0.000940109498639776e18 -Assert Equal (Comptroller CompSpeed cUSDT) 0.008447487333746899e18 -Assert Equal (Comptroller CompSpeed cWBTC) 0.004841175362144006e18 -Assert Equal (Comptroller CompSpeed cZRX) 0.001400483800617582e18 - --- Check the market borrows - -Assert Equal (CToken cBAT TotalBorrows) 994790805782510516637146235 -Assert Equal (CToken cDAI TotalBorrows) 28733415458831908292748520 -Assert Equal (CToken cETH TotalBorrows) 1423195009215949475714 -Assert Equal (CToken cREP TotalBorrows) 11741036506536325005938 -Assert Equal (CToken cSAI TotalBorrows) 85702639018129680274971 -Assert Equal (CToken cUSDC TotalBorrows) 13194641271913 -Assert Equal (CToken cUSDT TotalBorrows) 33842222695086 -Assert Equal (CToken cWBTC TotalBorrows) 166281366345 -Assert Equal (CToken cZRX TotalBorrows) 14602818278789368467659480 - --- Check the market prices - -Assert Equal (PriceOracleProxy Price cBAT) 1189627500000000 -Assert Equal (PriceOracleProxy Price cDAI) 4579024512369984 -Assert Equal (PriceOracleProxy Price cETH) 1000000000000000000 -Assert Equal (PriceOracleProxy Price cREP) 71700617500000010 -Assert Equal (PriceOracleProxy Price cSAI) 5285551943761727 -Assert Equal (PriceOracleProxy Price cUSDC) 4554587056912220000000000000 -Assert Equal (PriceOracleProxy Price cUSDT) 4554587056912220000000000000 -Assert Equal (PriceOracleProxy Price cWBTC) 410378476771980800000000000000 -Assert Equal (PriceOracleProxy Price cZRX) 1465310000000000 - --- Refresh speeds - -Comptroller RefreshCompSpeeds - --- Check the new speeds match utility metric --- Total Utility = --- 994790805782510516637146235 * 1189627500000000 + --- 28733415458831908292748520 * 4579024512369984 + --- 1423195009215949475714 * 1000000000000000000 + --- 11741036506536325005938 * 71700617500000010 + --- 85702639018129680274971 * 5285551943761727 * 0 (cSAI not comped) + --- 13194641271913 * 4554587056912220000000000000 + --- 33842222695086 * 4554587056912220000000000000 + --- 166281366345 * 410378476771980800000000000000 + --- 14602818278789368467659480 * 1465310000000000 --- = 1621135988903112202016711619617847258483060 - --- .22e18 * 994790805782510516637146235 * 1189627500000000 / 1621135988903112202016711619617847258483060 --- = 160600166568066720 -Assert Equal (Comptroller CompSpeed cBAT) 0.160600166568066716e18 - --- .22e18 * 28733415458831908292748520 * 4579024512369984 / 1621135988903112202016711619617847258483060 --- = 17855148003843600 -Assert Equal (Comptroller CompSpeed cDAI) 0.017855148003843601e18 - --- .22e18 * 1423195009215949475714 * 1000000000000000000 / 1621135988903112202016711619617847258483060 --- = 193137962620495 -Assert Equal (Comptroller CompSpeed cETH) 0.000193137962620495e18 - --- .22e18 * 11741036506536325005938 * 71700617500000010 / 1621135988903112202016711619617847258483060 --- = 114243780991640 -Assert Equal (Comptroller CompSpeed cREP) 0.000114243780991640e18 - --- not comped -Assert Equal (Comptroller CompSpeed cSAI) 0 - --- .22e18 * 13194641271913 * 4554587056912220000000000000 / 1621135988903112202016711619617847258483060 --- = 8155485665104318 -Assert Equal (Comptroller CompSpeed cUSDC) 0.008155485665104317e18 - --- .22e18 * 33842222695086 * 4554587056912220000000000000 / 1621135988903112202016711619617847258483060 --- = 20917564667146620 -Assert Equal (Comptroller CompSpeed cUSDT) 0.020917564667146617e18 - --- .22e18 * 166281366345 * 410378476771980800000000000000 / 1621135988903112202016711619617847258483060 --- = 9260435118787978 -Assert Equal (Comptroller CompSpeed cWBTC) 0.009260435118787978e18 - --- .22e18 * 14602818278789368467659480 * 1465310000000000 / 1621135988903112202016711619617847258483060 --- = 2903818233438633 -Assert Equal (Comptroller CompSpeed cZRX) 0.002903818233438633e18 - --- Now sanity check that we can continue to use the market as usual - --- First check the USDC Whale, mint - -Assert Equal (Erc20 cUSDC TokenBalance USDCWhale) 0 - -From USDCWhale (Trx GasPrice 0 (Erc20 USDC Approve cUSDC UInt256Max)) -From USDCWhale (Trx GasPrice 0 (CToken cUSDC Mint 10000e6)) - -Assert Equal (Erc20 cUSDC TokenBalance USDCWhale) 47481122314530 -Assert Equal (Erc20 cUSDC TotalSupply) 1080141236963466282 - --- Next check the BAT borrower, borrow a little more - -Assert Equal (Erc20 cETH TokenBalance cBATBorrower) 1034370824418 -Assert Equal (Erc20 cETH TotalSupply) 5134544277187300 - -Assert Equal (CToken cBAT BorrowBalance cBATBorrower) 123048404201235973562497 -Assert Equal (CToken cBAT TotalBorrows) 994790805782510516637146235 - -Expect Changes (CToken cBAT BorrowBalance cBATBorrower) 6666016503078751208324 -From cBATBorrower (CToken cBAT Borrow 6666000000000000000000) - -Assert Equal (CToken cBAT BorrowBalance cBATBorrower) 129714420704314724770821 -Assert Equal (CToken cBAT TotalBorrows) 997475461661266096431316572 - --- Claim comp to true up their balances - -Comptroller ClaimComp USDCWhale -Comptroller ClaimComp cBATBorrower - --- Now move the clock forward - -AdvanceBlocks 1000000 - --- And check that they receive the right amount of COMP when claimed - --- cUSDC: 47481122314530 / 1080141236963466282 * 8155485665104318 * 1e6 = 358500906314635600 -Expect Changes (Erc20 Comp TokenBalance USDCWhale) 0.358501981817354439e18 -Comptroller ClaimComp USDCWhale - --- cETH: 1034370824418 / 5134544277187300 * 193137962620495 * 1e6 = 38908277509608240 --- cBAT: 129714420704314724770821 / 997475461661266096431316572 * 160600166568066720 * 1e6 = 20884882257351856000 --- = 0.358500906314635600 + 20.884882257351856000 = 21.24338316366649 -Expect Changes (Erc20 Comp TokenBalance cBATBorrower) 21.282364219697601761e18 -Comptroller ClaimComp cBATBorrower - -Print "COMP distribution patch OK!" diff --git a/spec/sim/0001-comp-distribution-patch/kovan/execute.scen b/spec/sim/0001-comp-distribution-patch/kovan/execute.scen deleted file mode 100755 index b1e213489..000000000 --- a/spec/sim/0001-comp-distribution-patch/kovan/execute.scen +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/env yarn repl -n kovan -s - -PrintTransactionLogs - --- Execute the proposal -Governor GovernorAlpha Proposal 8 Execute - -Print "Executed OK!" \ No newline at end of file diff --git a/spec/sim/0001-comp-distribution-patch/kovan/queue.scen b/spec/sim/0001-comp-distribution-patch/kovan/queue.scen deleted file mode 100755 index 8adb34035..000000000 --- a/spec/sim/0001-comp-distribution-patch/kovan/queue.scen +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/env yarn repl -n queue -s - -PrintTransactionLogs - --- Queue the proposal -Governor GovernorAlpha Proposal 8 Queue - -Print "Queued OK!" \ No newline at end of file diff --git a/spec/sim/0001-comp-distribution-patch/ropsten/execute.scen b/spec/sim/0001-comp-distribution-patch/ropsten/execute.scen deleted file mode 100755 index b1ff668d6..000000000 --- a/spec/sim/0001-comp-distribution-patch/ropsten/execute.scen +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/env yarn repl -n ropsten -s - -PrintTransactionLogs - --- Execute the proposal -Governor GovernorAlpha Proposal 9 Execute - -Print "Executed OK!" \ No newline at end of file diff --git a/spec/sim/0001-comp-distribution-patch/ropsten/queue.scen b/spec/sim/0001-comp-distribution-patch/ropsten/queue.scen deleted file mode 100755 index c6f856db5..000000000 --- a/spec/sim/0001-comp-distribution-patch/ropsten/queue.scen +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/env yarn repl -n ropsten -s - -PrintTransactionLogs - --- Queue the proposal -Governor GovernorAlpha Proposal 9 Queue - -Print "Queued OK!" \ No newline at end of file diff --git a/spec/sim/0002-dai-irm-v3/hypothetical_upgrade.scen b/spec/sim/0002-dai-irm-v3/hypothetical_upgrade.scen deleted file mode 100755 index df4d45825..000000000 --- a/spec/sim/0002-dai-irm-v3/hypothetical_upgrade.scen +++ /dev/null @@ -1,52 +0,0 @@ -#!/usr/bin/env yarn repl -s - -PrintTransactionLogs - --- verify at https://changelog.makerdao.com/releases/mainnet/1.0.8/contracts.json -Alias PotAddress "0x197E90f9FAD81970bA7976f33CbD77088E5D7cf7" -Alias JugAddress "0x19c0976f590D67707E62397C87829d896Dc0f1F1" -Alias CompHolder "0x19bc62ff7cd9ffd6bdced9802ff718f09f7259f1" -Web3Fork "https://mainnet-eth.compound.finance/@10473211" (CompHolder) -UseConfigs mainnet - --- Deploy IRM contract -InterestRateModel Deploy DAIInterestRateModel UpdateableDaiInterestRateModel (Exp 1.09) (Exp 0.8) PotAddress JugAddress (Address Timelock) - --- Propose to apply the patch -From CompHolder (Comp Delegate CompHolder) -From CompHolder (Governor GovernorAlpha Propose "DAI IRM v3" [(Address cDAI)] [0] ["_setInterestRateModel(address)"] [[(InterestRateModel UpdateableDaiInterestRateModel Address)]]) - --- Vote for, queue, and execute the proposal -MineBlock -From CompHolder (Governor GovernorAlpha Proposal LastProposal Vote For) -AdvanceBlocks 20000 -Governor GovernorAlpha Proposal LastProposal Queue -IncreaseTime 604910 -Governor GovernorAlpha Proposal LastProposal Execute - --- Check model -Assert Equal (CToken cDAI InterestRateModel) (InterestRateModel UpdateableDaiInterestRateModel Address) - --- Propose to apply the update -From CompHolder (Governor GovernorAlpha Propose "DAI IRM v3 update" [(Address UpdateableDaiInterestRateModel)] [0] ["updateJumpRateModel(uint256,uint256,uint256,uint256)"] [[0 (Exp 0.4) (Exp 1.1) (Exp 0.7)]]) - --- Vote for, queue, and execute the proposal to update -MineBlock -From CompHolder (Governor GovernorAlpha Proposal LastProposal Vote For) -AdvanceBlocks 20000 -Governor GovernorAlpha Proposal LastProposal Queue -IncreaseTime 604910 - --- NOTE: checking the interest rate before the update currently returns 0, needs to be investigated! -Assert Equal (InterestRateModel UpdateableDaiInterestRateModel BorrowRate 1 10 1) (Zero) - -Governor GovernorAlpha Proposal LastProposal Execute - -Assert Equal (InterestRateModel UpdateableDaiInterestRateModel BorrowRate 1 10 1) (0.7299999999953279) - --- TODO: --- * additional tests that new cDAI interest rate matches expectations --- * no one else can propose rate update --- * get a non-zero initial interest rate! - -Print "Looking good!" diff --git a/spec/sim/0003-borrow-caps-patch/deploy.scen b/spec/sim/0003-borrow-caps-patch/deploy.scen deleted file mode 100755 index c9d62969f..000000000 --- a/spec/sim/0003-borrow-caps-patch/deploy.scen +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/env yarn repl -n mainnet -s - -PrintTransactionLogs - --- Deploy the flywheel impl -ComptrollerImpl Deploy Standard StdComptrollerG5 - -Print "Deployed OK!" diff --git a/spec/sim/0003-borrow-caps-patch/hypothetical_upgrade.scen b/spec/sim/0003-borrow-caps-patch/hypothetical_upgrade.scen deleted file mode 100755 index 4d11a281a..000000000 --- a/spec/sim/0003-borrow-caps-patch/hypothetical_upgrade.scen +++ /dev/null @@ -1,48 +0,0 @@ -#!/usr/bin/env yarn repl -s - -PrintTransactionLogs -Alias CompHolder "0x19bc62ff7cd9ffd6bdced9802ff718f09f7259f1" -Alias USDCWhale "0x3dfd23a6c5e8bbcfc9581d2e864a68feb6a076d3" -Alias Arr00 "0x2b384212edc04ae8bb41738d05ba20e33277bf33" -Web3Fork "https://mainnet-eth.compound.finance/@10706095" (CompHolder USDCWhale) -UseConfigs mainnet - --- Deploy the flywheel impl - -ComptrollerImpl Deploy Standard ComptrollerG5 - --- Propose to apply the patch - -From CompHolder (Comp Delegate CompHolder) -From CompHolder (Governor GovernorAlpha Propose "Borrow Cap Comptroller Patch" [(Address Unitroller) (Address ComptrollerG5) (Address Unitroller) (Address cSAI) (Address SAI)] [0 0 0 0 0] ["_setPendingImplementation(address)" "_become(address)" "_setBorrowCapGuardian(address)" "_reduceReserves(uint256)" "transfer(address,uint256)"] [[(Address ComptrollerG5)] [(Address Unitroller)] [(Address CompHolder)] [2360000000000000000000] [(Address Arr00) 2360000000000000000000]]) - --- Vote for, queue, and execute the proposal - -MineBlock -From CompHolder (Governor GovernorAlpha Proposal LastProposal Vote For) -AdvanceBlocks 20000 -Governor GovernorAlpha Proposal LastProposal Queue -IncreaseTime 604910 -Governor GovernorAlpha Proposal LastProposal Execute -ComptrollerImpl ComptrollerG5 MergeABI - -Assert Equal (Address (Unitroller Implementation)) (Address ComptrollerG5) -Assert Equal (Erc20 SAI TokenBalance (Address Arr00)) (2360000000000000000000) - -From USDCWhale (Trx GasPrice 0 (Erc20 USDC Approve cUSDC UInt256Max)) -From USDCWhale (Trx GasPrice 0 (CToken cUSDC Mint 214000000e6)) -From USDCWhale (Trx GasPrice 0 (CToken cUSDC Borrow 1000000e6)) - -From CompHolder (Comptroller SetMarketBorrowCaps (cUSDC) (83000000e6)) - -AllowFailures -From USDCWhale (Trx GasPrice 0 (CToken cUSDC Borrow 1000000e6)) -Assert Revert - -Successfully -From USDCWhale (Trx GasPrice 0 (CToken cUSDC RepayBorrow 1000000e6)) -From USDCWhale (Trx GasPrice 0 (CToken cUSDC Borrow 10e6)) - - - -Print "Borrow Cap Comptroller Patch OK!" \ No newline at end of file diff --git a/spec/sim/0003-borrow-caps-patch/hypothetical_upgrade_post_deploy.scen b/spec/sim/0003-borrow-caps-patch/hypothetical_upgrade_post_deploy.scen deleted file mode 100755 index 679ec0261..000000000 --- a/spec/sim/0003-borrow-caps-patch/hypothetical_upgrade_post_deploy.scen +++ /dev/null @@ -1,46 +0,0 @@ -#!/usr/bin/env yarn repl -s - -PrintTransactionLogs -Alias CompHolder "0x19bc62ff7cd9ffd6bdced9802ff718f09f7259f1" -Alias USDCWhale "0x3dfd23a6c5e8bbcfc9581d2e864a68feb6a076d3" -Alias Arr00 "0x2b384212edc04ae8bb41738d05ba20e33277bf33" -Web3Fork "https://mainnet-eth.compound.finance/@10809638" (CompHolder USDCWhale) -UseConfigs mainnet - - --- Propose to apply the patch - -From CompHolder (Comp Delegate CompHolder) -From CompHolder (Governor GovernorAlpha Propose "Borrow Limit Comptroller Patch" [(Address Unitroller) (Address StdComptrollerG5) (Address Unitroller) (Address cSAI) (Address SAI)] [0 0 0 0 0] ["_setPendingImplementation(address)" "_become(address)" "_setBorrowCapGuardian(address)" "_reduceReserves(uint256)" "transfer(address,uint256)"] [[(Address StdComptrollerG5)] [(Address Unitroller)] [(Address CompHolder)] [2360000000000000000000] [(Address Arr00) 2360000000000000000000]]) - --- Vote for, queue, and execute the proposal - -MineBlock -From CompHolder (Governor GovernorAlpha Proposal LastProposal Vote For) -AdvanceBlocks 20000 -Governor GovernorAlpha Proposal LastProposal Queue -IncreaseTime 604910 -Governor GovernorAlpha Proposal LastProposal Execute -ComptrollerImpl StdComptrollerG5 MergeABI - -Assert Equal (Address (Unitroller Implementation)) (Address StdComptrollerG5) -Assert Equal (Erc20 SAI TokenBalance (Address Arr00)) (2360000000000000000000) - -From USDCWhale (Trx GasPrice 0 (Erc20 USDC Approve cUSDC UInt256Max)) -From USDCWhale (Trx GasPrice 0 (CToken cUSDC Mint 100000000e6)) -From USDCWhale (Trx GasPrice 0 (CToken cUSDC Borrow 1000000e6)) - --- Market borrows were just under 81M at this block -From CompHolder (Comptroller SetMarketBorrowCaps (cUSDC) (68000000e6)) - -AllowFailures -From USDCWhale (Trx GasPrice 0 (CToken cUSDC Borrow 1000000e6)) -Assert Revert - -Successfully -From USDCWhale (Trx GasPrice 0 (CToken cUSDC RepayBorrow 1000000e6)) -From USDCWhale (Trx GasPrice 0 (CToken cUSDC Borrow 10e6)) - - - -Print "Borrow Limit Comptroller Patch OK!" \ No newline at end of file diff --git a/spec/sim/0003-borrow-caps-patch/hypothetical_upgrade_post_propose.scen b/spec/sim/0003-borrow-caps-patch/hypothetical_upgrade_post_propose.scen deleted file mode 100755 index 5d777dfaa..000000000 --- a/spec/sim/0003-borrow-caps-patch/hypothetical_upgrade_post_propose.scen +++ /dev/null @@ -1,32 +0,0 @@ -#!/usr/bin/env yarn repl -s - -PrintTransactionLogs -Alias CompVoter1 "0x9aa835bc7b8ce13b9b0c9764a52fbf71ac62ccf1" -Alias CompVoter2 "0xed409c9ff60f3020abf9012bcd45fc294f5608ff" -Alias USDCWhale "0x3dfd23a6c5e8bbcfc9581d2e864a68feb6a076d3" -Alias Arr00 "0x2b384212edc04ae8bb41738d05ba20e33277bf33" -Web3Fork "https://mainnet-eth.compound.finance/@10823813" (USDCWhale CompVoter1 CompVoter2) -UseConfigs mainnet - - - --- Vote for, queue, and execute the proposal - -MineBlock -From CompVoter1 (Governor GovernorAlpha Proposal LastProposal Vote For) -From CompVoter2 (Governor GovernorAlpha Proposal LastProposal Vote For) -AdvanceBlocks 20000 -Governor GovernorAlpha Proposal LastProposal Queue -IncreaseTime 604910 -Governor GovernorAlpha Proposal LastProposal Execute -ComptrollerImpl StdComptrollerG5 MergeABI - -Assert Equal (Address (Unitroller Implementation)) (Address StdComptrollerG5) -Assert Equal (Erc20 SAI TokenBalance (Address Arr00)) (2800000000000000000000) - -From USDCWhale (Trx GasPrice 0 (Erc20 USDC Approve cUSDC UInt256Max)) -From USDCWhale (Trx GasPrice 0 (CToken cUSDC Mint 100000000e6)) -From USDCWhale (Trx GasPrice 0 (CToken cUSDC Borrow 1000000e6)) - - -Print "Borrow Limit Comptroller Patch OK!" \ No newline at end of file diff --git a/spec/sim/0004-cusdc-irm-update/hypothetical_upgrade.scen b/spec/sim/0004-cusdc-irm-update/hypothetical_upgrade.scen deleted file mode 100755 index bc0a53e5d..000000000 --- a/spec/sim/0004-cusdc-irm-update/hypothetical_upgrade.scen +++ /dev/null @@ -1,30 +0,0 @@ -#!/usr/bin/env yarn repl -s - -PrintTransactionLogs -Alias CompHolder "0x19bc62ff7cd9ffd6bdced9802ff718f09f7259f1" -Web3Fork "https://mainnet-eth.compound.finance/@10796407" (CompHolder) -UseConfigs mainnet - --- Deploy new interest rate model -InterestRateModel Deploy LegacyJumpRateModelV2 MyInterestRateModel 0 0.04 1.09 0.8 (Address Timelock) - --- Propose to apply the patch - -From CompHolder (Comp Delegate CompHolder) -From CompHolder (Governor GovernorAlpha Propose "Update cUSDC interest rate model" [(Address cUSDC)] [0] ["_setInterestRateModel(address)"] [[(Address MyInterestRateModel)]]) - --- Vote for, queue, and execute the proposal - -MineBlock -From CompHolder (Governor GovernorAlpha Proposal LastProposal Vote For) -AdvanceBlocks 20000 -Governor GovernorAlpha Proposal LastProposal Queue -IncreaseTime 604910 -Governor GovernorAlpha Proposal LastProposal Execute - - -Assert Equal (Address (CToken cUSDC InterestRateModel)) (Address MyInterestRateModel) -CToken cUSDC AccrueInterest - - -Print "cUSDC interest rate model upgrade ok" \ No newline at end of file diff --git a/spec/sim/0005-grants/deploy.scen b/spec/sim/0005-grants/deploy.scen deleted file mode 100755 index fec91042d..000000000 --- a/spec/sim/0005-grants/deploy.scen +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/env yarn repl -n mainnet -s - -PrintTransactionLogs - --- Deploy the flywheel impl -ComptrollerImpl Deploy Standard StdComptrollerG6 - -Print "Deployed OK!" diff --git a/spec/sim/0005-grants/hypothetical_upgrade.scen b/spec/sim/0005-grants/hypothetical_upgrade.scen deleted file mode 100755 index 3c028a39b..000000000 --- a/spec/sim/0005-grants/hypothetical_upgrade.scen +++ /dev/null @@ -1,98 +0,0 @@ -#!/usr/bin/env yarn repl -s - --- This script tests a hypothetical upgrade with one time and streaming grants - -PrintTransactionLogs -Alias CompHolder "0x19bc62ff7cd9ffd6bdced9802ff718f09f7259f1" -Alias USDCWhale "0x3dfd23a6c5e8bbcfc9581d2e864a68feb6a076d3" -Alias Tarun "0x6626593c237f530d15ae9980a95ef938ac15c35c" -Web3Fork "https://mainnet-eth.compound.finance/@10706095" (CompHolder USDCWhale Tarun) -UseConfigs mainnet - --- Deploy the flywheel impl - -ComptrollerImpl Deploy Standard ComptrollerG6 - --- Propose to apply the patch - -Assert Equal (Erc20 COMP TokenBalance (Address Tarun)) (0) - -From CompHolder (Comp Delegate CompHolder) -From CompHolder (Governor GovernorAlpha Propose "Grants Comptroller Patch and both types of grants issued" [(Address Unitroller) (Address ComptrollerG6) (Address Unitroller) (Address Unitroller)] [0 0 0 0] ["_setPendingImplementation(address)" "_become(address)" "_grantComp(address,uint256)" "_setContributorCompSpeed(address,uint256)"] [[(Address ComptrollerG6)] [(Address Unitroller)] [(Address Tarun) 10000000] [(Address Tarun) 15]]) - --- Vote for, queue, and execute the proposal - -MineBlock -From CompHolder (Governor GovernorAlpha Proposal LastProposal Vote For) -AdvanceBlocks 20000 -Governor GovernorAlpha Proposal LastProposal Queue -IncreaseTime 604910 -Governor GovernorAlpha Proposal LastProposal Execute -ComptrollerImpl ComptrollerG6 MergeABI - --- Check initial grant amount was apportioned -Assert Equal (Address (Unitroller Implementation)) (Address ComptrollerG6) -Assert Equal (Erc20 COMP TokenBalance (Address Tarun)) (10e6) - --- Check contributor claim does not work without update -AdvanceBlocks 997 -From Tarun (Comptroller ClaimComp Tarun) -Assert Equal (Erc20 COMP TokenBalance (Address Tarun)) (10e6) - --- Check contributor claim amount is added -From Tarun (Comptroller UpdateContributorRewards Tarun) -From Tarun (Comptroller ClaimComp Tarun) -Assert Equal (Erc20 COMP TokenBalance (Address Tarun)) (10015000) - - --- Prepare second proposal -From CompHolder (Governor GovernorAlpha Propose "Contributor speed reduction and second grant" [(Address Unitroller) (Address ComptrollerG6) (Address Unitroller) (Address Unitroller)] [0 0 0 0] ["_setPendingImplementation(address)" "_become(address)" "_grantComp(address,uint256)" "_setContributorCompSpeed(address,uint256)"] [[(Address ComptrollerG6)] [(Address Unitroller)] [(Address Tarun) 20000000] [(Address Tarun) 5]]) - --- Vote for, queue, and execute the second proposal - -MineBlock -From CompHolder (Governor GovernorAlpha Proposal LastProposal Vote For) -AdvanceBlocks 20000 -Governor GovernorAlpha Proposal LastProposal Queue -IncreaseTime 604910 -Governor GovernorAlpha Proposal LastProposal Execute - -AdvanceBlocks 1000 - --- Check contributor claim amount is added -From Tarun (Comptroller UpdateContributorRewards Tarun) -From Tarun (Comptroller ClaimComp Tarun) - --- Initial value 10015000 = 10000000 grant + (997+3)*15 --- Second grant 20000000 --- Second proposal mining 300000 = 20000*15 --- Extra blocks 5000 = 1000*5 --- Extra proposal mining 130 --- Total = 30330130 -Assert Equal (Erc20 COMP TokenBalance (Address Tarun)) (30320130) - --- Prepare final proposal -From CompHolder (Governor GovernorAlpha Propose "Contributor speed elimination Patch" [(Address Unitroller)] [0] ["_setContributorCompSpeed(address,uint256)"] [[(Address Tarun) 0]]) - --- Vote for, queue, and execute the final proposal - -MineBlock -From CompHolder (Governor GovernorAlpha Proposal LastProposal Vote For) -AdvanceBlocks 20000 -Governor GovernorAlpha Proposal LastProposal Queue -IncreaseTime 604910 -Governor GovernorAlpha Proposal LastProposal Execute - -AdvanceBlocks 10000 - --- Check no more COMP was allocated -From Tarun (Comptroller UpdateContributorRewards Tarun) -From Tarun (Comptroller ClaimComp Tarun) --- Initial value 30320130 --- Third proposal mining 100000 = 20000*5 --- Extra blocks 0 = 1000*0 --- Extra proposal mining 40 --- Total = 30420170 -Assert Equal (Erc20 COMP TokenBalance (Address Tarun)) (30420170) - -Print "Upgrade OK!" diff --git a/spec/sim/0005-grants/hypothetical_upgrade_multiple_speed.scen b/spec/sim/0005-grants/hypothetical_upgrade_multiple_speed.scen deleted file mode 100755 index 92fa506d4..000000000 --- a/spec/sim/0005-grants/hypothetical_upgrade_multiple_speed.scen +++ /dev/null @@ -1,86 +0,0 @@ -#!/usr/bin/env yarn repl -s - --- This script tests a hypothetical upgrade with multiple speeds and has been subsumed in hypothetical_upgrade.scen --- It is left here as a faster test for development - -PrintTransactionLogs -Alias CompHolder "0x19bc62ff7cd9ffd6bdced9802ff718f09f7259f1" -Alias USDCWhale "0x3dfd23a6c5e8bbcfc9581d2e864a68feb6a076d3" -Alias Tarun "0x6626593c237f530d15ae9980a95ef938ac15c35c" -Web3Fork "https://mainnet-eth.compound.finance/@10706095" (CompHolder USDCWhale Tarun) -UseConfigs mainnet - --- Deploy the flywheel impl - -ComptrollerImpl Deploy Standard ComptrollerG6 - --- Propose to apply the patch - -Assert Equal (Erc20 COMP TokenBalance (Address Tarun)) (0) - -From CompHolder (Comp Delegate CompHolder) -From CompHolder (Governor GovernorAlpha Propose "Grants Comptroller Patch" [(Address Unitroller) (Address ComptrollerG6) (Address Unitroller)] [0 0 0] ["_setPendingImplementation(address)" "_become(address)" "_setContributorCompSpeed(address,uint256)"] [[(Address ComptrollerG6)] [(Address Unitroller)] [(Address Tarun) 15]]) - --- Vote for, queue, and execute the proposal - -MineBlock -From CompHolder (Governor GovernorAlpha Proposal LastProposal Vote For) -AdvanceBlocks 20000 -Governor GovernorAlpha Proposal LastProposal Queue -IncreaseTime 604910 -Governor GovernorAlpha Proposal LastProposal Execute -ComptrollerImpl ComptrollerG6 MergeABI - --- Round out blocks to 1000 before next patch -AdvanceBlocks 997 - --- Prepare second proposal -From CompHolder (Governor GovernorAlpha Propose "Contributor speed reduction Patch" [(Address Unitroller)] [0] ["_setContributorCompSpeed(address,uint256)"] [[(Address Tarun) 5]]) - --- Vote for, queue, and execute the second proposal - -MineBlock -From CompHolder (Governor GovernorAlpha Proposal LastProposal Vote For) -AdvanceBlocks 20000 -Governor GovernorAlpha Proposal LastProposal Queue -IncreaseTime 604910 -Governor GovernorAlpha Proposal LastProposal Execute - -AdvanceBlocks 1000 - --- Check contributor claim amount is added -From Tarun (Comptroller UpdateContributorRewards Tarun) -From Tarun (Comptroller ClaimComp Tarun) - --- Initial run 15000 = (997+3)*15 --- Second proposal mining 300000 = 20000*15 --- Extra blocks 5000 = 1000*5 --- Extra proposal mining 85 --- Total = 330080 -Assert Equal (Erc20 COMP TokenBalance (Address Tarun)) (320085) - --- Prepare final proposal -From CompHolder (Governor GovernorAlpha Propose "Contributor speed elimination Patch" [(Address Unitroller)] [0] ["_setContributorCompSpeed(address,uint256)"] [[(Address Tarun) 0]]) - --- Vote for, queue, and execute the final proposal - -MineBlock -From CompHolder (Governor GovernorAlpha Proposal LastProposal Vote For) -AdvanceBlocks 20000 -Governor GovernorAlpha Proposal LastProposal Queue -IncreaseTime 604910 -Governor GovernorAlpha Proposal LastProposal Execute - -AdvanceBlocks 10000 - --- Check no more COMP was allocated -From Tarun (Comptroller UpdateContributorRewards Tarun) -From Tarun (Comptroller ClaimComp Tarun) --- Initial value 320085 --- Third proposal mining 100000 = 20000*5 --- Extra blocks 0 = 1000*0 --- Extra proposal mining 40 --- Total = 420125 -Assert Equal (Erc20 COMP TokenBalance (Address Tarun)) (420125) - -Print "Upgrade OK!" diff --git a/spec/sim/0005-grants/hypothetical_upgrade_post_propose.scen b/spec/sim/0005-grants/hypothetical_upgrade_post_propose.scen deleted file mode 100755 index 0c7fb2e81..000000000 --- a/spec/sim/0005-grants/hypothetical_upgrade_post_propose.scen +++ /dev/null @@ -1,31 +0,0 @@ -#!/usr/bin/env yarn repl -s - --- This script tests a hypothetical upgrade with one time and streaming grants - -PrintTransactionLogs -Alias CompHolder "0x19bc62ff7cd9ffd6bdced9802ff718f09f7259f1" -Alias CompVoter1 "0x9aa835bc7b8ce13b9b0c9764a52fbf71ac62ccf1" -Alias CompVoter2 "0xed409c9ff60f3020abf9012bcd45fc294f5608ff" -Alias USDCWhale "0x3dfd23a6c5e8bbcfc9581d2e864a68feb6a076d3" -Alias Tarun "0x6626593c237f530d15ae9980a95ef938ac15c35c" -Web3Fork "https://mainnet-eth.compound.finance/@11395519" (CompHolder USDCWhale Tarun CompVoter1 CompVoter2) -UseConfigs mainnet - -Assert Equal (Erc20 COMP TokenBalance (Address Tarun)) (2e18) - --- Vote for, queue, and execute the proposal - -MineBlock -From CompVoter1 (Governor GovernorAlpha Proposal LastProposal Vote For) -From CompVoter2 (Governor GovernorAlpha Proposal LastProposal Vote For) -From CompHolder (Governor GovernorAlpha Proposal LastProposal Vote For) -AdvanceBlocks 20000 -Governor GovernorAlpha Proposal LastProposal Queue -IncreaseTime 604910 -Governor GovernorAlpha Proposal LastProposal Execute -ComptrollerImpl ComptrollerG6 MergeABI - --- Check grant amount was apportioned -Assert Equal (Erc20 COMP TokenBalance (Address Tarun)) (1002e18) - -Print "Upgrade OK!" diff --git a/spec/sim/0006-setspeed-manual-claims/deploy.scen b/spec/sim/0006-setspeed-manual-claims/deploy.scen deleted file mode 100755 index 46518d956..000000000 --- a/spec/sim/0006-setspeed-manual-claims/deploy.scen +++ /dev/null @@ -1,8 +0,0 @@ -#!/usr/bin/env yarn repl -n mainnet -s - -PrintTransactionLogs - --- Deploy the flywheel impl -ComptrollerImpl Deploy Standard StdComptrollerG7 - -Print "Deployed OK!" diff --git a/spec/sim/0006-setspeed-manual-claims/hypothetical_upgrade.scen b/spec/sim/0006-setspeed-manual-claims/hypothetical_upgrade.scen deleted file mode 100755 index 780ccee14..000000000 --- a/spec/sim/0006-setspeed-manual-claims/hypothetical_upgrade.scen +++ /dev/null @@ -1,102 +0,0 @@ -#!/usr/bin/env yarn repl -s - --- This script tests a hypothetical upgrade with manual COMP claims and manual COMP speed setting - -PrintTransactionLogs -Alias CompHolder "0xC89b6f0146642688bb254bF93C28fcCF1E182C81" -Alias USDCWhale "0x3dfd23a6c5e8bbcfc9581d2e864a68feb6a076d3" -Alias DAIWhale "0x47ac0Fb4F2D84898e4D9E7b4DaB3C24507a6D503" -Web3Fork "https://mainnet-eth.compound.finance/@11458477" (CompHolder USDCWhale DAIWhale) -UseConfigs mainnet - --- Deploy the flywheel impl -ComptrollerImpl Deploy Standard ComptrollerG7 - --- Baseline USDC comp speed before the patch -Assert Equal (Comptroller CompSpeed cUSDC) 5.3786477206671197e16 - --- Mint tokens -From DAIWhale (Trx GasPrice 0 (Erc20 DAI Approve cDAI UInt256Max)) -From DAIWhale (Trx GasPrice 0 (CToken cDAI Mint 10000e6)) -From USDCWhale (Trx GasPrice 0 (Erc20 USDC Approve cUSDC UInt256Max)) -From USDCWhale (Trx GasPrice 0 (CToken cUSDC Mint 10000e6)) - --- Baseline COMP claim speed -Assert Equal (Comptroller CheckIsComped cDAI) True - -Comptroller ClaimComp DAIWhale -AdvanceBlocks 1000 -Expect Changes (Erc20 Comp TokenBalance DAIWhale) 7.77e2 -Comptroller ClaimComp DAIWhale - --- Propose to apply the patch - -From CompHolder (Comp Delegate CompHolder) -From CompHolder (Governor GovernorAlpha Propose "Disable automatic comp speed refresh and automatic claims and change comp speed" [(Address Unitroller) (Address ComptrollerG7) (Address Unitroller)] [0 0 0] ["_setPendingImplementation(address)" "_become(address)" "_setCompSpeed(address,uint256)"] [[(Address ComptrollerG7)] [(Address Unitroller)] [(Address cUSDC) 30000000000000000]]) - --- Vote for, queue, and execute the proposal - -MineBlock -From CompHolder (Governor GovernorAlpha Proposal LastProposal Vote For) -AdvanceBlocks 20000 -Governor GovernorAlpha Proposal LastProposal Queue -IncreaseTime 604910 -Governor GovernorAlpha Proposal LastProposal Execute -ComptrollerImpl ComptrollerG7 MergeABI - --- Check that speed has changed -Assert Equal (Comptroller CompSpeed cUSDC) 3.0e16 - --- Check that COMP is still accruing at the same speed -Comptroller ClaimComp DAIWhale -AdvanceBlocks 1000 -Expect Changes (Erc20 Comp TokenBalance DAIWhale) 7.77e2 -Comptroller ClaimComp DAIWhale - --- Check that minting some USDC wont result in any automatic claims -AdvanceBlocks 1000000 -From USDCWhale (Trx GasPrice 0 (Erc20 USDC Approve cUSDC UInt256Max)) -Expect Changes (Erc20 Comp TokenBalance USDCWhale) 0 -From USDCWhale (Trx GasPrice 0 (CToken cUSDC Mint 10000e6)) - --- Prepare second proposal -From CompHolder (Governor GovernorAlpha Propose "Remove USDC market by setting comp speed to 0" [(Address Unitroller)] [0] ["_setCompSpeed(address,uint256)"] [[(Address cUSDC) 0]]) - --- Vote for, queue, and execute the second proposal - -MineBlock -From CompHolder (Governor GovernorAlpha Proposal LastProposal Vote For) -AdvanceBlocks 20000 -Governor GovernorAlpha Proposal LastProposal Queue -IncreaseTime 604910 -Governor GovernorAlpha Proposal LastProposal Execute - -AdvanceBlocks 1000 - --- Check speed is now 0 -Assert Equal (Comptroller CompSpeed cUSDC) 0 - --- True up balances -Comptroller ClaimComp USDCWhale - --- Check no more comp accrued -AdvanceBlocks 1000000 -Expect Changes (Erc20 Comp TokenBalance USDCWhale) 0 -Comptroller ClaimComp USDCWhale - --- Prepare final proposal -From CompHolder (Governor GovernorAlpha Propose "Reset USDC comp speed" [(Address Unitroller)] [0] ["_setCompSpeed(address,uint256)"] [[(Address cUSDC) 27000000000000000]]) - --- Vote for, queue, and execute the final proposal - -MineBlock -From CompHolder (Governor GovernorAlpha Proposal LastProposal Vote For) -AdvanceBlocks 20000 -Governor GovernorAlpha Proposal LastProposal Queue -IncreaseTime 604910 -Governor GovernorAlpha Proposal LastProposal Execute - --- Check new speed -Assert Equal (Comptroller CompSpeed cUSDC) 2.7e16 - -Print "Upgrade OK!" diff --git a/spec/sim/0006-setspeed-manual-claims/hypothetical_upgrade_borrower.scen b/spec/sim/0006-setspeed-manual-claims/hypothetical_upgrade_borrower.scen deleted file mode 100755 index 3dfa682b6..000000000 --- a/spec/sim/0006-setspeed-manual-claims/hypothetical_upgrade_borrower.scen +++ /dev/null @@ -1,53 +0,0 @@ -#!/usr/bin/env yarn repl -s - --- This script tests a hypothetical upgrade with manual COMP claims and manual COMP speed setting - -PrintTransactionLogs -Alias CompHolder "0xC89b6f0146642688bb254bF93C28fcCF1E182C81" -Alias USDCWhale "0x3dfd23a6c5e8bbcfc9581d2e864a68feb6a076d3" -Alias DAIWhale "0x47ac0Fb4F2D84898e4D9E7b4DaB3C24507a6D503" -Alias BigBorrower "0x847956f7f7ff49714fb2d70a0d0cd44a6376990f" -Web3Fork "https://mainnet-eth.compound.finance/@11458477" (CompHolder USDCWhale DAIWhale) -UseConfigs mainnet - --- Deploy the flywheel impl -ComptrollerImpl Deploy Standard ComptrollerG7 - --- Baseline USDC comp speed before the patch -Assert Equal (Comptroller CompSpeed cUSDC) 5.3786477206671197e16 - --- Mint tokens -From DAIWhale (Trx GasPrice 0 (Erc20 DAI Approve cDAI UInt256Max)) -From DAIWhale (Trx GasPrice 0 (CToken cDAI Mint 10000e6)) -From USDCWhale (Trx GasPrice 0 (Erc20 USDC Approve cUSDC UInt256Max)) -From USDCWhale (Trx GasPrice 0 (CToken cUSDC Mint 10000e6)) - --- Baseline COMP claim speed -Assert Equal (Comptroller CheckIsComped cDAI) True - -Comptroller ClaimComp BigBorrower -AdvanceBlocks 1000 -Expect Changes (Erc20 Comp TokenBalance BigBorrower) 2.893496802261224189e18 -Comptroller ClaimComp BigBorrower - --- Propose to apply the patch - -From CompHolder (Comp Delegate CompHolder) -From CompHolder (Governor GovernorAlpha Propose "Disable automatic comp speed refresh and automatic claims and change comp speed" [(Address Unitroller) (Address ComptrollerG7) (Address Unitroller)] [0 0 0] ["_setPendingImplementation(address)" "_become(address)" "_setCompSpeed(address,uint256)"] [[(Address ComptrollerG7)] [(Address Unitroller)] [(Address cUSDC) 30000000000000000]]) - --- Vote for, queue, and execute the proposal - -MineBlock -From CompHolder (Governor GovernorAlpha Proposal LastProposal Vote For) -AdvanceBlocks 20000 -Governor GovernorAlpha Proposal LastProposal Queue -IncreaseTime 604910 -Governor GovernorAlpha Proposal LastProposal Execute -ComptrollerImpl ComptrollerG7 MergeABI - -Comptroller ClaimComp BigBorrower -AdvanceBlocks 1000 -Expect Changes (Erc20 Comp TokenBalance BigBorrower) 2.893496802261224189e18 -Comptroller ClaimComp BigBorrower - -Print "Upgrade OK!" diff --git a/spec/sim/0006-setspeed-manual-claims/hypothetical_upgrade_post_deploy.scen b/spec/sim/0006-setspeed-manual-claims/hypothetical_upgrade_post_deploy.scen deleted file mode 100755 index f63b7a7a8..000000000 --- a/spec/sim/0006-setspeed-manual-claims/hypothetical_upgrade_post_deploy.scen +++ /dev/null @@ -1,95 +0,0 @@ -#!/usr/bin/env yarn repl -s - --- This script tests a hypothetical upgrade with manual COMP claims and manual COMP speed setting - -PrintTransactionLogs -Alias CompHolder "0xC89b6f0146642688bb254bF93C28fcCF1E182C81" -Alias USDCWhale "0x3dfd23a6c5e8bbcfc9581d2e864a68feb6a076d3" -Alias DAIWhale "0x47ac0Fb4F2D84898e4D9E7b4DaB3C24507a6D503" -Alias NewComptroller "0xbe7616B06f71e363A310Aa8CE8aD99654401ead7" -Web3Fork "https://mainnet-eth.compound.finance/@11499182" (CompHolder USDCWhale DAIWhale) -UseConfigs mainnet - --- Mint tokens -From DAIWhale (Trx GasPrice 0 (Erc20 DAI Approve cDAI UInt256Max)) -From DAIWhale (Trx GasPrice 0 (CToken cDAI Mint 10000e6)) -From USDCWhale (Trx GasPrice 0 (Erc20 USDC Approve cUSDC UInt256Max)) -From USDCWhale (Trx GasPrice 0 (CToken cUSDC Mint 10000e6)) - --- Baseline COMP claim speed -Assert Equal (Comptroller CheckIsComped cDAI) True - -Comptroller ClaimComp DAIWhale -AdvanceBlocks 1000 -Comptroller ClaimComp DAIWhale - --- Propose to apply the patch - -From CompHolder (Comp Delegate CompHolder) -From CompHolder (Governor GovernorAlpha Propose "Disable automatic comp speed refresh and automatic claims and change comp speed" [(Address Unitroller) (Address NewComptroller) (Address Unitroller)] [0 0 0] ["_setPendingImplementation(address)" "_become(address)" "_setCompSpeed(address,uint256)"] [[(Address NewComptroller)] [(Address Unitroller)] [(Address cUSDC) 30000000000000000]]) - --- Vote for, queue, and execute the proposal - -MineBlock -From CompHolder (Governor GovernorAlpha Proposal LastProposal Vote For) -AdvanceBlocks 20000 -Governor GovernorAlpha Proposal LastProposal Queue -IncreaseTime 604910 -Governor GovernorAlpha Proposal LastProposal Execute -ComptrollerImpl ComptrollerG7 MergeABI - --- Check that speed has changed -Assert Equal (Comptroller CompSpeed cUSDC) 3.0e16 - --- Check that COMP is still accruing at the same speed -Comptroller ClaimComp DAIWhale -AdvanceBlocks 1000 -Comptroller ClaimComp DAIWhale - --- Check that minting some USDC wont result in any automatic claims -AdvanceBlocks 1000000 -From USDCWhale (Trx GasPrice 0 (Erc20 USDC Approve cUSDC UInt256Max)) -Expect Changes (Erc20 Comp TokenBalance USDCWhale) 0 -From USDCWhale (Trx GasPrice 0 (CToken cUSDC Mint 10000e6)) - --- Prepare second proposal -From CompHolder (Governor GovernorAlpha Propose "Remove USDC market by setting comp speed to 0" [(Address Unitroller)] [0] ["_setCompSpeed(address,uint256)"] [[(Address cUSDC) 0]]) - --- Vote for, queue, and execute the second proposal - -MineBlock -From CompHolder (Governor GovernorAlpha Proposal LastProposal Vote For) -AdvanceBlocks 20000 -Governor GovernorAlpha Proposal LastProposal Queue -IncreaseTime 604910 -Governor GovernorAlpha Proposal LastProposal Execute - -AdvanceBlocks 1000 - --- Check speed is now 0 -Assert Equal (Comptroller CompSpeed cUSDC) 0 - --- True up balances -Comptroller ClaimComp USDCWhale - --- Check no more comp accrued -AdvanceBlocks 1000000 -Expect Changes (Erc20 Comp TokenBalance USDCWhale) 0 -Comptroller ClaimComp USDCWhale - --- Prepare final proposal -From CompHolder (Governor GovernorAlpha Propose "Reset USDC comp speed" [(Address Unitroller)] [0] ["_setCompSpeed(address,uint256)"] [[(Address cUSDC) 27000000000000000]]) - --- Vote for, queue, and execute the final proposal - -MineBlock -From CompHolder (Governor GovernorAlpha Proposal LastProposal Vote For) -AdvanceBlocks 20000 -Governor GovernorAlpha Proposal LastProposal Queue -IncreaseTime 604910 -Governor GovernorAlpha Proposal LastProposal Execute - --- Check new speed -Assert Equal (Comptroller CompSpeed cUSDC) 2.7e16 - -Print "Upgrade OK!" diff --git a/spec/sim/0006-setspeed-manual-claims/hypothetical_upgrade_post_propose.scen b/spec/sim/0006-setspeed-manual-claims/hypothetical_upgrade_post_propose.scen deleted file mode 100755 index 49b33c92a..000000000 --- a/spec/sim/0006-setspeed-manual-claims/hypothetical_upgrade_post_propose.scen +++ /dev/null @@ -1,86 +0,0 @@ -#!/usr/bin/env yarn repl -s - --- This script tests a hypothetical upgrade with manual COMP claims and manual COMP speed setting - -PrintTransactionLogs -Alias CompHolder1 "0xC89b6f0146642688bb254bF93C28fcCF1E182C81" -Alias CompHolder2 "0xed409c9ff60f3020abf9012bcd45fc294f5608ff" -Alias CompHolder3 "0x6626593c237f530d15ae9980a95ef938ac15c35c" -Alias USDCWhale "0x3dfd23a6c5e8bbcfc9581d2e864a68feb6a076d3" -Alias DAIWhale "0x47ac0Fb4F2D84898e4D9E7b4DaB3C24507a6D503" -Alias NewComptroller "0xbe7616B06f71e363A310Aa8CE8aD99654401ead7" -Web3Fork "https://mainnet-eth.compound.finance/@11499432" (CompHolder1 CompHolder2 CompHolder3 USDCWhale DAIWhale) -UseConfigs mainnet - --- Baseline the speed -Assert Equal (Comptroller CompSpeed cUSDC) 6.5604507401004006e16 - -MineBlock -From CompHolder1 (Governor GovernorAlpha Proposal LastProposal Vote For) -From CompHolder2 (Governor GovernorAlpha Proposal LastProposal Vote For) -From CompHolder3 (Governor GovernorAlpha Proposal LastProposal Vote For) -AdvanceBlocks 20000 -Governor GovernorAlpha Proposal LastProposal Queue -IncreaseTime 604910 -Governor GovernorAlpha Proposal LastProposal Execute -ComptrollerImpl ComptrollerG7 MergeABI - --- Check that speed has not changed -Assert Equal (Comptroller CompSpeed cUSDC) 6.5604507401004006e16 - --- Check that COMP is still accruing at the same speed -Comptroller ClaimComp DAIWhale -AdvanceBlocks 1000 -Comptroller ClaimComp DAIWhale - --- Check that minting some USDC wont result in any automatic claims -AdvanceBlocks 1000000 -From USDCWhale (Trx GasPrice 0 (Erc20 USDC Approve cUSDC UInt256Max)) -Expect Changes (Erc20 Comp TokenBalance USDCWhale) 0 -From USDCWhale (Trx GasPrice 0 (CToken cUSDC Mint 10000e6)) - --- Prepare second proposal -From CompHolder3 (Governor GovernorAlpha Propose "Remove USDC market by setting comp speed to 0" [(Address Unitroller)] [0] ["_setCompSpeed(address,uint256)"] [[(Address cUSDC) 0]]) - --- Vote for, queue, and execute the second proposal - -MineBlock -From CompHolder1 (Governor GovernorAlpha Proposal LastProposal Vote For) -From CompHolder2 (Governor GovernorAlpha Proposal LastProposal Vote For) -From CompHolder3 (Governor GovernorAlpha Proposal LastProposal Vote For) -AdvanceBlocks 20000 -Governor GovernorAlpha Proposal LastProposal Queue -IncreaseTime 604910 -Governor GovernorAlpha Proposal LastProposal Execute - -AdvanceBlocks 1000 - --- Check speed is now 0 -Assert Equal (Comptroller CompSpeed cUSDC) 0 - --- True up balances -Comptroller ClaimComp USDCWhale - --- Check no more comp accrued -AdvanceBlocks 1000000 -Expect Changes (Erc20 Comp TokenBalance USDCWhale) 0 -Comptroller ClaimComp USDCWhale - --- Prepare final proposal -From CompHolder3 (Governor GovernorAlpha Propose "Reset USDC comp speed" [(Address Unitroller)] [0] ["_setCompSpeed(address,uint256)"] [[(Address cUSDC) 27000000000000000]]) - --- Vote for, queue, and execute the final proposal - -MineBlock -From CompHolder1 (Governor GovernorAlpha Proposal LastProposal Vote For) -From CompHolder2 (Governor GovernorAlpha Proposal LastProposal Vote For) -From CompHolder3 (Governor GovernorAlpha Proposal LastProposal Vote For) -AdvanceBlocks 20000 -Governor GovernorAlpha Proposal LastProposal Queue -IncreaseTime 604910 -Governor GovernorAlpha Proposal LastProposal Execute - --- Check new speed -Assert Equal (Comptroller CompSpeed cUSDC) 2.7e16 - -Print "Upgrade OK!" diff --git a/spec/sim/0007-cdai-impl-migration/hypothetical_migration.scen b/spec/sim/0007-cdai-impl-migration/hypothetical_migration.scen deleted file mode 100755 index 9b5f9e9c1..000000000 --- a/spec/sim/0007-cdai-impl-migration/hypothetical_migration.scen +++ /dev/null @@ -1,44 +0,0 @@ -#!/usr/bin/env yarn repl -s - -PrintTransactionLogs -Alias CompHolder "0xC89b6f0146642688bb254bF93C28fcCF1E182C81" -Alias DaiHolder "0xf977814e90da44bfa03b6295a0616a897441acec" -Alias CUSDCHolder "0x5e34bc93a7506ecc8562ade4d5c8b090247a6349" -Alias CUsdtImplementation "0x976aa93ca5aaa569109f4267589c619a097f001d" -Alias CUsdtIRM "0xFB564da37B41b2F6B6EDcc3e56FbF523bD9F2012" -Web3Fork "https://mainnet-eth.compound.finance/@11447815" (CompHolder DaiHolder CUSDCHolder) -UseConfigs mainnet - - --- Delegate and propose update -From CompHolder (Comp Delegate CompHolder) -From CompHolder (Governor GovernorAlpha Propose "Update cDai implementation" [(Address cDai) (Address cDai)] [0 0] ["_setImplementation(address,bool,bytes)" "_setInterestRateModel(address)"] [[(address CUsdtImplementation) true "0x"] [(address CUsdtIRM)]]) - --- Fast forward, vote, queue, execute -MineBlock -From CompHolder (Governor GovernorAlpha Proposal LastProposal Vote For) -AdvanceBlocks 20000 -Governor GovernorAlpha Proposal LastProposal Queue -IncreaseTime 604910 -Governor GovernorAlpha Proposal LastProposal Execute - --- Assert Dai retrieved from DSR -Assert Equal (Erc20 Dai TokenBalance cDai) (284058478303890709049107567) - --- IRM changed correctly -Assert Equal (CToken cDai InterestRateModel) (Address CUsdtIRM) - --- Ensure accrue interest works -CToken cDai AccrueInterest - --- Mint Test -From DaiHolder (Erc20 Dai Approve (Address cDai) 10000000) -From DaiHolder (CToken cDai Mint 10000000) -Assert Equal (Erc20 Dai TokenBalance cDai) (284058478303890709059107567) - --- Borrow Test -From CUSDCHolder (CToken cDai Borrow 10000000) -Assert Equal (Erc20 Dai TokenBalance CUSDCHolder) (4235678125976069) -Assert Equal (Erc20 Dai TokenBalance cDai) (284058478303890709049107567) - -Print "cDai implementation migration ok" \ No newline at end of file diff --git a/spec/sim/0007-cdai-impl-migration/hypothetical_migration_post_propose.scen b/spec/sim/0007-cdai-impl-migration/hypothetical_migration_post_propose.scen deleted file mode 100755 index 242534611..000000000 --- a/spec/sim/0007-cdai-impl-migration/hypothetical_migration_post_propose.scen +++ /dev/null @@ -1,47 +0,0 @@ -#!/usr/bin/env yarn repl -s - -PrintTransactionLogs -Alias CompHolder "0xed409c9ff60f3020abf9012bcd45fc294f5608ff" -Alias CompHolder2 "0x6626593c237f530d15ae9980a95ef938ac15c35c" -Alias DaiHolder "0xf977814e90da44bfa03b6295a0616a897441acec" -Alias CUSDCHolder "0x5e34bc93a7506ecc8562ade4d5c8b090247a6349" -Alias CUsdtImplementation "0x976aa93ca5aaa569109f4267589c619a097f001d" -Alias CUsdtIRM "0xFB564da37B41b2F6B6EDcc3e56FbF523bD9F2012" -Web3Fork "https://mainnet-eth.compound.finance/@11499832" (CompHolder CompHolder2 DaiHolder CUSDCHolder) -UseConfigs mainnet - - - - --- Fast forward, vote, queue, execute -MineBlock -From CompHolder (Governor GovernorAlpha Proposal LastProposal Vote For) -From CompHolder2 (Governor GovernorAlpha Proposal LastProposal Vote For) -AdvanceBlocks 20000 -Governor GovernorAlpha Proposal LastProposal Queue -IncreaseTime 604910 -Governor GovernorAlpha Proposal LastProposal Execute - --- Assert Dai retrieved from DSR -Assert Equal (Erc20 Dai TokenBalance cDai) (247764889541500427246579984) - --- Assert Impl Changed Correctly -Assert Equal (CToken cDai Implementation) (Address CUsdtImplementation) - --- IRM changed correctly -Assert Equal (CToken cDai InterestRateModel) (Address CUsdtIRM) - --- Ensure accrue interest works -CToken cDai AccrueInterest - --- Mint Test -From DaiHolder (Erc20 Dai Approve (Address cDai) 10000000) -From DaiHolder (CToken cDai Mint 10000000) -Assert Equal (Erc20 Dai TokenBalance cDai) (247764889541500427256579984) - --- Borrow Test -From CUSDCHolder (CToken cDai Borrow 10000000) -Assert Equal (Erc20 Dai TokenBalance CUSDCHolder) (4235678125976069) -Assert Equal (Erc20 Dai TokenBalance cDai) (247764889541500427246579984) - -Print "cDai implementation migration ok" \ No newline at end of file diff --git a/spec/sim/0008-sweep-token/hypothetical_migration.scen b/spec/sim/0008-sweep-token/hypothetical_migration.scen deleted file mode 100755 index bfb35dac3..000000000 --- a/spec/sim/0008-sweep-token/hypothetical_migration.scen +++ /dev/null @@ -1,42 +0,0 @@ -#!/usr/bin/env yarn repl -s - -PrintTransactionLogs -Alias CompHolder "0xC89b6f0146642688bb254bF93C28fcCF1E182C81" -Alias cUNISender "0xf22c2e3475e4a066f4e9f44567c950dd36112d05" -Alias UniHolder "0x5518C31f4A22782E5a7046711FACF985985530c7" -Alias CUSDCHolder "0x926e78b8DF67e129011750Dd7b975f8E50D3d7Ad" -Web3Fork "https://mainnet-eth.compound.finance/@11746553" (CompHolder CUSDCHolder UniHolder) -UseConfigs mainnet - - --- Delegate and propose update -CTokenDelegate Deploy CErc20Delegate newCUNIImpl - -From CompHolder (Comp Delegate CompHolder) -From CompHolder (Governor GovernorAlpha Propose "Update cUNI implementation" [(Address cUNI) (Address cUNI) (Address cUNI)] [0 0 0] ["_setImplementation(address,bool,bytes)" "sweepToken(address)" "transfer(address,uint256)"] [[(address newCUNIImpl) false "0x"] [(address cUNI)] [(address cUNISender) 1]]) - --- Fast forward, vote, queue, execute -MineBlock -From CompHolder (Governor GovernorAlpha Proposal LastProposal Vote For) -AdvanceBlocks 20000 -Governor GovernorAlpha Proposal LastProposal Queue -IncreaseTime 604910 -Governor GovernorAlpha Proposal LastProposal Execute - -Assert Equal (Erc20 (Address cUNI) TokenBalance cUNISender) (1) -Assert Equal (Erc20 (Address cUNI) TokenBalance Timelock) (179874258721489) - --- Ensure accrue interest works -CToken cUNI AccrueInterest - --- Mint Test -Assert Equal (Erc20 Uni TokenBalance cUNI) (8841949597201167092831625) -From UniHolder (Erc20 Uni Approve cUNI 10000000) -From UniHolder (CToken cUNI Mint 10000000) -Assert Equal (Erc20 Uni TokenBalance cUNI) (8841949597201167102831625) - --- Borrow Test -From CUSDCHolder (CToken cUNI Borrow 10000000) -Assert Equal (Erc20 Uni TokenBalance CUSDCHolder) (10000000) - -Print "cUNI implementation migration ok" diff --git a/spec/sim/0008-sweep-token/hypothetical_migration_post_deploy.scen b/spec/sim/0008-sweep-token/hypothetical_migration_post_deploy.scen deleted file mode 100755 index 3d2619074..000000000 --- a/spec/sim/0008-sweep-token/hypothetical_migration_post_deploy.scen +++ /dev/null @@ -1,42 +0,0 @@ -#!/usr/bin/env yarn repl -s - -PrintTransactionLogs -Alias CompHolder "0xC89b6f0146642688bb254bF93C28fcCF1E182C81" -Alias cUNISender "0xf22c2e3475e4a066f4e9f44567c950dd36112d05" -Alias UniHolder "0x5518C31f4A22782E5a7046711FACF985985530c7" -Alias CUSDCHolder "0x926e78b8DF67e129011750Dd7b975f8E50D3d7Ad" -Alias NewcUNIImplementation "0xa1849880593E96d2f7dF77D0D38a7f2372aE10E0" -Web3Fork "https://mainnet-eth.compound.finance/@11805759" (CompHolder CUSDCHolder UniHolder) -UseConfigs mainnet - - - -From CompHolder (Comp Delegate CompHolder) -From CompHolder (Governor GovernorAlpha Propose "Update cUNI implementation" [(Address cUNI) (Address cUNI) (Address cUNI)] [0 0 0] ["_setImplementation(address,bool,bytes)" "sweepToken(address)" "transfer(address,uint256)"] [[(address NewcUNIImplementation) false "0x"] [(address cUNI)] [(address cUNISender) 1]]) - --- Fast forward, vote, queue, execute -MineBlock -From CompHolder (Governor GovernorAlpha Proposal LastProposal Vote For) -AdvanceBlocks 20000 -Governor GovernorAlpha Proposal LastProposal Queue -IncreaseTime 604910 -Governor GovernorAlpha Proposal LastProposal Execute - -Assert Equal (Erc20 (Address cUNI) TokenBalance cUNISender) (1) -Assert Equal (Erc20 (Address cUNI) TokenBalance Timelock) (179874258721489) - --- Ensure accrue interest works -MineBlock -CToken cUNI AccrueInterest - --- Mint Test -Assert Equal (Erc20 Uni TokenBalance cUNI) (9213234645306032140780326) -From UniHolder (Erc20 Uni Approve cUNI 10000000) -From UniHolder (CToken cUNI Mint 10000000) -Assert Equal (Erc20 Uni TokenBalance cUNI) (9213234645306032150780326) - --- Borrow Test -From CUSDCHolder (CToken cUNI Borrow 10000000) -Assert Equal (Erc20 Uni TokenBalance CUSDCHolder) (10000000) - -Print "cUNI implementation migration ok" diff --git a/spec/sim/0008-sweep-token/hypothetical_migration_post_propose.scen b/spec/sim/0008-sweep-token/hypothetical_migration_post_propose.scen deleted file mode 100755 index 7a20b0d9d..000000000 --- a/spec/sim/0008-sweep-token/hypothetical_migration_post_propose.scen +++ /dev/null @@ -1,48 +0,0 @@ -#!/usr/bin/env yarn repl -s - -PrintTransactionLogs -Alias CompVoter1 "0x6626593C237f530D15aE9980A95ef938Ac15c35c" -Alias CompVoter2 "0xA1b61405791170833070C0eA61eD28728A840241" -Alias CompVoter3 "0xAC5720d6EE2d7872b88914C9c5Fa9BF38e72FaF6" -Alias CompVoter4 "0x8169522c2C57883E8EF80C498aAB7820dA539806" -Alias Arr00 "0x2B384212EDc04Ae8bB41738D05BA20E33277bf33" -Alias NewcUNIImplementation "0xa1849880593E96d2f7dF77D0D38a7f2372aE10E0" -Alias UniHolder "0x5518C31f4A22782E5a7046711FACF985985530c7" -Alias CUSDCHolder "0x926e78b8DF67e129011750Dd7b975f8E50D3d7Ad" -Alias cUNISender "0xf22c2e3475e4a066f4e9f44567c950dd36112d05" -Web3Fork "https://mainnet-eth.compound.finance/@11820163" (CompVoter1 CompVoter2 CompVoter3 CompVoter4 UniHolder CUSDCHolder) -UseConfigs mainnet - - --- Vote for, queue, and execute the proposal -MineBlock -From CompVoter1 (Governor GovernorAlpha Proposal LastProposal Vote For) -From CompVoter2 (Governor GovernorAlpha Proposal LastProposal Vote For) -From CompVoter3 (Governor GovernorAlpha Proposal LastProposal Vote For) -From CompVoter4 (Governor GovernorAlpha Proposal LastProposal Vote For) -AdvanceBlocks 20000 -Governor GovernorAlpha Proposal LastProposal Queue -IncreaseTime 604910 -Governor GovernorAlpha Proposal LastProposal Execute - --- Check expected values -Assert Equal (CToken cUNI Implementation) (Address NewcUNIImplementation) -Assert Equal (Erc20 (Address cUNI) TokenBalance (Address Timelock)) (17987425872149) -Assert Equal (Erc20 (Address cUNI) TokenBalance cUNISender) (161886832849341) -Assert Equal (Erc20 (Address COMP) TokenBalance (Address Arr00)) (30040000000000000000) - --- Ensure accrue interest works -MineBlock -CToken cUNI AccrueInterest - --- Mint Test -Assert Equal (Erc20 Uni TokenBalance cUNI) (8974517540659969962306996) -From UniHolder (Erc20 Uni Approve cUNI 10000000) -From UniHolder (CToken cUNI Mint 10000000) -Assert Equal (Erc20 Uni TokenBalance cUNI) (8974517540659969972306996) - --- Borrow Test -From CUSDCHolder (CToken cUNI Borrow 10000000) -Assert Equal (Erc20 Uni TokenBalance CUSDCHolder) (10000000) - -Print "cUNI implementation migration ok" \ No newline at end of file diff --git a/spec/sim/0009-gov-bravo/hypothetical_upgrade.scen b/spec/sim/0009-gov-bravo/hypothetical_upgrade.scen deleted file mode 100755 index ca4a3d5d8..000000000 --- a/spec/sim/0009-gov-bravo/hypothetical_upgrade.scen +++ /dev/null @@ -1,43 +0,0 @@ -#!/usr/bin/env yarn repl -s - -PrintTransactionLogs - -Alias Arr00 "0x2B384212EDc04Ae8bB41738D05BA20E33277bf33" -Alias CompHolder "0xC89b6f0146642688bb254bF93C28fcCF1E182C81" - -Web3Fork "https://mainnet-eth.compound.finance/@11635311" (CompHolder) -UseConfigs mainnet - -GovernorBravo Deploy BravoDelegate BravoDelegate2 -GovernorBravo Deploy BravoDelegator BravoDelegator2 (Address Timelock) (Address Comp) (Address Timelock) (Address BravoDelegate2) 17280 1 100000e18 - -From CompHolder (Comp Delegate CompHolder) -From CompHolder (Governor GovernorAlpha Propose "Governor Bravo" [(Address Timelock) (Address BravoDelegator2)] [0 0] ["setPendingAdmin(address)" "_initiate(address)"] [[(Address BravoDelegator2)] [(Address GovernorAlpha)]]) - --- Vote for, queue, and execute the proposal -MineBlock -From CompHolder (Governor GovernorAlpha Proposal LastProposal Vote For) -AdvanceBlocks 20000 -Governor GovernorAlpha Proposal LastProposal Queue -IncreaseTime 604910 -Governor GovernorAlpha Proposal LastProposal Execute -GovernorBravo BravoDelegator2 MergeABI BravoDelegate2 - -From CompHolder (GovernorBravo BravoDelegator2 Propose "Grant Comp" [(Address Comptroller)] [0] ["_grantComp(address,uint256)"] [[(Address Arr00) 2]]) - --- Vote for, queue, and execute the proposal -MineBlock -From CompHolder (GovernorBravo BravoDelegator2 Proposal LastProposal Vote For) -AdvanceBlocks 20000 -GovernorBravo BravoDelegator2 Proposal LastProposal Queue -IncreaseTime 604910 -GovernorBravo BravoDelegator2 Proposal LastProposal Execute - -Assert Equal (50000000000000002) (Erc20 Comp TokenBalance (Address Arr00)) - --- Continuous proposal id count -Assert Equal (GovernorBravo BravoDelegator2 Proposal LastProposal Id) 37 - - -Print "Migration to GovernorBravo Ok!" - diff --git a/spec/sim/0009-gov-bravo/hypothetical_upgrade_post_deploy.scen b/spec/sim/0009-gov-bravo/hypothetical_upgrade_post_deploy.scen deleted file mode 100755 index d6d0596e4..000000000 --- a/spec/sim/0009-gov-bravo/hypothetical_upgrade_post_deploy.scen +++ /dev/null @@ -1,42 +0,0 @@ -#!/usr/bin/env yarn repl -s - -PrintTransactionLogs - -Alias Arr00 "0x2B384212EDc04Ae8bB41738D05BA20E33277bf33" -Alias CompHolder "0xC89b6f0146642688bb254bF93C28fcCF1E182C81" - -Web3Fork "https://mainnet-eth.compound.finance/@12006351" (CompHolder) -UseConfigs mainnet - -From CompHolder (Comp Delegate CompHolder) -From CompHolder (Governor GovernorAlpha Propose "Governor Bravo" [(Address Comptroller) (Address Timelock) (Address GovernorBravo)] [0 0 0] ["_grantComp(address,uint256)" "setPendingAdmin(address)" "_initiate(address)"] [[(Address Arr00) 2] [(Address GovernorBravo)] [(Address GovernorAlpha)]]) - --- Vote for, queue, and execute the proposal -MineBlock -From CompHolder (Governor GovernorAlpha Proposal LastProposal Vote For) -AdvanceBlocks 20000 -Governor GovernorAlpha Proposal LastProposal Queue -IncreaseTime 604910 -Governor GovernorAlpha Proposal LastProposal Execute - -Assert Equal (2) (Erc20 Comp TokenBalance (Address Arr00)) -Assert Equal (Timelock Admin) (Address GovernorBravo) - -From CompHolder (GovernorBravo GovernorBravo Propose "Grant Comp" [(Address Comptroller)] [0] ["_grantComp(address,uint256)"] [[(Address Arr00) 2]]) - --- Vote for, queue, and execute the proposal -MineBlock -From CompHolder (GovernorBravo GovernorBravo Proposal LastProposal Vote For) -AdvanceBlocks 20000 -GovernorBravo GovernorBravo Proposal LastProposal Queue -IncreaseTime 604910 -GovernorBravo GovernorBravo Proposal LastProposal Execute - -Assert Equal (4) (Erc20 Comp TokenBalance (Address Arr00)) - --- Continuous proposal id count -Assert Equal (GovernorBravo GovernorBravo Proposal LastProposal Id) 41 - - -Print "Migration to GovernorBravo Ok!" - diff --git a/spec/sim/0009-gov-bravo/hypothetical_upgrade_post_propose.scen b/spec/sim/0009-gov-bravo/hypothetical_upgrade_post_propose.scen deleted file mode 100755 index 9f3d42717..000000000 --- a/spec/sim/0009-gov-bravo/hypothetical_upgrade_post_propose.scen +++ /dev/null @@ -1,48 +0,0 @@ -#!/usr/bin/env yarn repl -s - -PrintTransactionLogs -Alias CompVoter1 "0x6626593C237f530D15aE9980A95ef938Ac15c35c" -Alias CompVoter2 "0xA1b61405791170833070C0eA61eD28728A840241" -Alias CompVoter3 "0xAC5720d6EE2d7872b88914C9c5Fa9BF38e72FaF6" -Alias CompVoter4 "0x8169522c2C57883E8EF80C498aAB7820dA539806" - -Alias Arr00 "0x2b384212edc04ae8bb41738d05ba20e33277bf33" -Web3Fork "https://mainnet-eth.compound.finance/@12109064" (CompVoter1 CompVoter2 CompVoter3 CompVoter4) -UseConfigs mainnet - - - --- Vote for, queue, and execute the proposal - -MineBlock -From CompVoter1 (Governor GovernorAlpha Proposal LastProposal Vote For) -From CompVoter2 (Governor GovernorAlpha Proposal LastProposal Vote For) -From CompVoter3 (Governor GovernorAlpha Proposal LastProposal Vote For) -AdvanceBlocks 20000 -Governor GovernorAlpha Proposal LastProposal Queue -IncreaseTime 604910 -Governor GovernorAlpha Proposal LastProposal Execute - -Assert Equal (Erc20 COMP TokenBalance (Address Arr00)) (160000000000000000000) -Assert Equal (Timelock Admin) (Address GovernorBravo) - -From CompVoter1 (GovernorBravo GovernorBravo Propose "Grant Comp" [(Address Comptroller)] [0] ["_grantComp(address,uint256)"] [[(Address Arr00) 2]]) - --- Vote for, queue, and execute the proposal -MineBlock -From CompVoter1 (GovernorBravo GovernorBravo Proposal LastProposal Vote For) -From CompVoter2 (GovernorBravo GovernorBravo Proposal LastProposal Vote For) -From CompVoter3 (GovernorBravo GovernorBravo Proposal LastProposal Vote For) -From CompVoter4 (GovernorBravo GovernorBravo Proposal LastProposal Vote For) -AdvanceBlocks 20000 -GovernorBravo GovernorBravo Proposal LastProposal Queue -IncreaseTime 604910 -GovernorBravo GovernorBravo Proposal LastProposal Execute - -Assert Equal (160000000000000000002) (Erc20 Comp TokenBalance (Address Arr00)) - --- Continuous proposal id count -Assert Equal (GovernorBravo GovernorBravo Proposal LastProposal Id) 43 - - -Print "Migration to GovernorBravo Ok!" \ No newline at end of file diff --git a/spec/sim/0009-gov-bravo/kovan/hypothetical_upgrade_kovan.scen b/spec/sim/0009-gov-bravo/kovan/hypothetical_upgrade_kovan.scen deleted file mode 100755 index a690a8756..000000000 --- a/spec/sim/0009-gov-bravo/kovan/hypothetical_upgrade_kovan.scen +++ /dev/null @@ -1,41 +0,0 @@ -#!/usr/bin/env yarn repl -s - -PrintTransactionLogs - -Alias Arr00 "0x2B384212EDc04Ae8bB41738D05BA20E33277bf33" - -Web3Fork "https://kovan-eth.compound.finance/@23053022" (Arr00) -UseConfigs kovan - -GovernorBravo Deploy BravoDelegate BravoDelegate2 -GovernorBravo Deploy BravoDelegator BravoDelegator2 (Address Timelock) (Address Comp) (Address Timelock) (Address BravoDelegate2) 17280 1 100000e18 - -From Arr00 (Governor GovernorAlpha Propose "Governor Bravo" [(Address Timelock) (Address BravoDelegator2)] [0 0] ["setPendingAdmin(address)" "_initiate(address)"] [[(Address BravoDelegator2)] [(Address GovernorAlpha)]]) - --- Vote for, queue, and execute the proposal -MineBlock -From Arr00 (Governor GovernorAlpha Proposal LastProposal Vote For) -AdvanceBlocks 20000 -Governor GovernorAlpha Proposal LastProposal Queue -IncreaseTime 604910 -Governor GovernorAlpha Proposal LastProposal Execute -GovernorBravo BravoDelegator2 MergeABI BravoDelegate2 - -From Arr00 (GovernorBravo BravoDelegator2 Propose "Grant Comp" [("0x5eAe89DC1C671724A672ff0630122ee834098657")] [0] ["_grantComp(address,uint256)"] [[(Address Arr00) 2]]) - --- Vote for, queue, and execute the proposal -MineBlock -From Arr00 (GovernorBravo BravoDelegator2 Proposal LastProposal Vote For) -AdvanceBlocks 20000 -GovernorBravo BravoDelegator2 Proposal LastProposal Queue -IncreaseTime 604910 -GovernorBravo BravoDelegator2 Proposal LastProposal Execute - -Assert Equal (2) (Erc20 Comp TokenBalance (Address Arr00)) - --- Continuous proposal id count -Assert Equal (GovernorBravo BravoDelegator2 Proposal LastProposal Id) 52 - - -Print "Migration to GovernorBravo on kovan Ok!" - diff --git a/spec/sim/0010-liq-incentive/hypothetical-ctoken-upgrade.scen b/spec/sim/0010-liq-incentive/hypothetical-ctoken-upgrade.scen deleted file mode 100755 index d28e70c9e..000000000 --- a/spec/sim/0010-liq-incentive/hypothetical-ctoken-upgrade.scen +++ /dev/null @@ -1,39 +0,0 @@ -#!/usr/bin/env yarn repl -s - -Alias CompHolder "0x7587cAefc8096f5F40ACB83A09Df031a018C66ec" -Alias Liquidator "0x7d6149ad9a573a6e2ca6ebf7d4897c1b766841b4" -Alias UniHolder "0x767ecb395def19ab8d1b2fcc89b3ddfbed28fd6b" -Web3Fork "https://mainnet-eth.compound.finance/@12466889" (CompHolder UniHolder Liquidator) -UseConfigs mainnet - -From CompHolder (Comp Delegate CompHolder) -From CompHolder (Governor GovernorBravo Propose "Update cERC20 Implementation" [(Address cCOMP) (Address cDAI) (Address cUNI) (Address cUSDT) (Address cWBTC2)] [0 0 0 0 0] ["_setImplementation(address,bool,bytes)" "_setImplementation(address,bool,bytes)" "_setImplementation(address,bool,bytes)" "_setImplementation(address,bool,bytes)" "_setImplementation(address,bool,bytes)"] [[(address cErc20ImplG2) false "0x"] [(address cErc20ImplG2) false "0x"][(address cErc20ImplG2) false "0x"][(address cErc20ImplG2) false "0x"][(address cErc20ImplG2) false "0x"]]) - --- upgrade to mainnet cerc20delegate deployment -From CompHolder (Governor GovernorBravo Propose "Update cERC20 Implementation" [(Address cDAI)] [0] ["_setImplementation(address,bool,bytes)"] [[(address cErc20ImplG2) false "0x"]]) - -AdvanceBlocks 13140 -From CompHolder (GovernorBravo GovernorBravo Proposal LastProposal Vote For) -AdvanceBlocks 20000 -Governor GovernorBravo Proposal LastProposal Queue -IncreaseTime 604910 -Governor GovernorBravo Proposal LastProposal Execute - --- Test basic actions -From Liquidator (CToken cDAI RedeemUnderlying 20000e18) -From UniHolder (CToken cUSDC Borrow 8e13) - -Print "Migration to reserve delegate is ok" - -From CompHolder (GovernorBravo GovernorBravo Propose "Update Comptroller implementation" [(Address Unitroller) (Address ComptrollerG8)] [0 0] ["_setPendingImplementation(address)" "_become(address)"] [[(Address ComptrollerG8)] [(Address Unitroller)]]) - -AdvanceBlocks 13140 -From CompHolder (GovernorBravo GovernorBravo Proposal LastProposal Vote For) -AdvanceBlocks 20000 -Governor GovernorBravo Proposal LastProposal Queue -IncreaseTime 604910 -Governor GovernorBravo Proposal LastProposal Execute - -From Root (Comptroller ClaimComp Root) - -Print "Migration to new comptroller ok" \ No newline at end of file diff --git a/spec/sim/0011-split-comp-rewards/hypothetical_mainnet_upgrade.scen b/spec/sim/0011-split-comp-rewards/hypothetical_mainnet_upgrade.scen deleted file mode 100755 index c2ee4cf98..000000000 --- a/spec/sim/0011-split-comp-rewards/hypothetical_mainnet_upgrade.scen +++ /dev/null @@ -1,269 +0,0 @@ -#!/usr/bin/env -S yarn repl -s - -PrintTransactionLogs - --- Token holder addresses for mocking -Alias CompHolder "0x7587caefc8096f5f40acb83a09df031a018c66ec" -Alias TokenHolder "0x05e793ce0c6027323ac150f6d45c2344d28b6019" -Alias CUSDCHolder "0x5e34bc93a7506ecc8562ade4d5c8b090247a6349" - -Web3Fork "https://mainnet-eth.compound.finance/@13057957" (CompHolder TokenHolder CUSDCHolder) -UseConfigs mainnet - --- Verify current borrow state indices -Assert Equal (Comptroller CompBorrowState cETH "index") (271900236502310314207275303654594550) -Assert Equal (Comptroller CompBorrowState cUSDC "index") (374249356944686866589343968372424802182093834) -Assert Equal (Comptroller CompBorrowState cDAI "index") (304681283805461047990696432440416) -Assert Equal (Comptroller CompBorrowState cWBTC "index") (57091242808581665886978349924495532483402440045) -Assert Equal (Comptroller CompBorrowState cWBTC2 "index") (4737883459778580214958447506665029825205802627436) -Assert Equal (Comptroller CompBorrowState cUSDT "index") (423043052052409576153627131768953764641085770) -Assert Equal (Comptroller CompBorrowState cCOMP "index") (1090703374692561421496444039421391844) -Assert Equal (Comptroller CompBorrowState cUNI "index") (1003224738961829505932781071832714863) -Assert Equal (Comptroller CompBorrowState cLINK "index") (1021334963447383149197229014847138287) -Assert Equal (Comptroller CompBorrowState cZRX "index") (276469710290458744488056479123899) -Assert Equal (Comptroller CompBorrowState cTUSD "index") (0) -Assert Equal (Comptroller CompBorrowState cBAT "index") (233011432934823645559082204456702) -Assert Equal (Comptroller CompBorrowState cAAVE "index") (0) -Assert Equal (Comptroller CompBorrowState cSAI "index") (0) -Assert Equal (Comptroller CompBorrowState cSUSHI "index") (0) -Assert Equal (Comptroller CompBorrowState cMKR "index") (0) -Assert Equal (Comptroller CompBorrowState cREP "index") (2887409755927065791842943220324690) -Assert Equal (Comptroller CompBorrowState cYFI "index") (0) - --- Verify current supply state indices -Assert Equal (Comptroller CompSupplyState cETH "index") (3266868720475524419878033121250905466535312) -Assert Equal (Comptroller CompSupplyState cUSDC "index") (32567188278514519540286631350261809001131) -Assert Equal (Comptroller CompSupplyState cDAI "index") (48523828872606782857477338624275950203274) -Assert Equal (Comptroller CompSupplyState cWBTC "index") (98873610159998754418561608689329824102859175) -Assert Equal (Comptroller CompSupplyState cWBTC2 "index") (551089483977648654874859795061443575084844994561) -Assert Equal (Comptroller CompSupplyState cUSDT "index") (50534796386054496931306603320108731513487) -Assert Equal (Comptroller CompSupplyState cCOMP "index") (3836027216477076374142846684153643830549513) -Assert Equal (Comptroller CompSupplyState cUNI "index") (57432610740828790697901777052414007754599) -Assert Equal (Comptroller CompSupplyState cLINK "index") (852011526290128056285332840775220381888746) -Assert Equal (Comptroller CompSupplyState cZRX "index") (11697528643270194078002497271204681811028) -Assert Equal (Comptroller CompSupplyState cTUSD "index") (0) -Assert Equal (Comptroller CompSupplyState cBAT "index") (9278159415477864616059533796790401482787) -Assert Equal (Comptroller CompSupplyState cAAVE "index") (0) -Assert Equal (Comptroller CompSupplyState cSAI "index") (0) -Assert Equal (Comptroller CompSupplyState cSUSHI "index") (0) -Assert Equal (Comptroller CompSupplyState cMKR "index") (0) -Assert Equal (Comptroller CompSupplyState cREP "index") (10822464444875983176893501598723703991037) -Assert Equal (Comptroller CompSupplyState cYFI "index") (0) - --- Verify current supply speeds -Assert Equal (Comptroller CompSpeed cETH) (10750000000000000) -Assert Equal (Comptroller CompSpeed cUSDC) (67000000000000000) -Assert Equal (Comptroller CompSpeed cDAI) (67000000000000000) -Assert Equal (Comptroller CompSpeed cWBTC) (0) -Assert Equal (Comptroller CompSpeed cWBTC2) (10750000000000000) -Assert Equal (Comptroller CompSpeed cUSDT) (9650000000000000) -Assert Equal (Comptroller CompSpeed cCOMP) (5000000000000000) -Assert Equal (Comptroller CompSpeed cUNI) (1462500000000000) -Assert Equal (Comptroller CompSpeed cLINK) (1462500000000000) -Assert Equal (Comptroller CompSpeed cZRX) (1462500000000000) -Assert Equal (Comptroller CompSpeed cTUSD) (0) -Assert Equal (Comptroller CompSpeed cBAT) (1462500000000000) -Assert Equal (Comptroller CompSpeed cAAVE) (0) -Assert Equal (Comptroller CompSpeed cSAI) (0) -Assert Equal (Comptroller CompSpeed cSUSHI) (0) -Assert Equal (Comptroller CompSpeed cMKR) (0) -Assert Equal (Comptroller CompSpeed cREP) (0) -Assert Equal (Comptroller CompSpeed cYFI) (0) - --- Deploy latest Comptroller -ComptrollerImpl Deploy Standard ComptrollerSplitCompRewards - --- Delegate and propose update -From CompHolder (Comp Delegate CompHolder) -From CompHolder (GovernorBravo GovernorBravo Propose "Upgrade Comptroller" [(Address Unitroller) (Address ComptrollerSplitCompRewards)] [0 0] ["_setPendingImplementation(address)" "_become(address)"] [[(Address ComptrollerSplitCompRewards)] [(Address Unitroller)]]) - --- Fast forward, vote, queue, execute -MineBlock -AdvanceBlocks 14000 -From CompHolder (GovernorBravo GovernorBravo Proposal LastProposal Vote For) -AdvanceBlocks 20000 -GovernorBravo GovernorBravo Proposal LastProposal Queue -IncreaseTime 604910 -GovernorBravo GovernorBravo Proposal LastProposal Execute -MineBlock - --- Merge ABIs so that we can call the newly introduced functions without an error -ComptrollerImpl ComptrollerSplitCompRewards MergeABI - --- Verify new borrow state indices -Assert Equal (Comptroller CompBorrowState cETH "index") (271900236502310314207275303654594550) -Assert Equal (Comptroller CompBorrowState cUSDC "index") (374249356944686866589343968372424802182093834) -Assert Equal (Comptroller CompBorrowState cDAI "index") (304681283805461047990696432440416) -Assert Equal (Comptroller CompBorrowState cWBTC "index") (57091242808581665886978349924495532483402440045) -Assert Equal (Comptroller CompBorrowState cWBTC2 "index") (4737883459778580214958447506665029825205802627436) -Assert Equal (Comptroller CompBorrowState cUSDT "index") (423043052052409576153627131768953764641085770) -Assert Equal (Comptroller CompBorrowState cCOMP "index") (1090703374692561421496444039421391844) -Assert Equal (Comptroller CompBorrowState cUNI "index") (1003224738961829505932781071832714863) -Assert Equal (Comptroller CompBorrowState cLINK "index") (1021334963447383149197229014847138287) -Assert Equal (Comptroller CompBorrowState cZRX "index") (276469710290458744488056479123899) -Assert Equal (Comptroller CompBorrowState cTUSD "index") (1e36) -Assert Equal (Comptroller CompBorrowState cBAT "index") (233011432934823645559082204456702) -Assert Equal (Comptroller CompBorrowState cAAVE "index") (1e36) -Assert Equal (Comptroller CompBorrowState cSAI "index") (1e36) -Assert Equal (Comptroller CompBorrowState cSUSHI "index") (1e36) -Assert Equal (Comptroller CompBorrowState cMKR "index") (1e36) -Assert Equal (Comptroller CompBorrowState cREP "index") (2887409755927065791842943220324690) -Assert Equal (Comptroller CompBorrowState cYFI "index") (1e36) - --- Verify new supply state indices -Assert Equal (Comptroller CompSupplyState cETH "index") (3266868720475524419878033121250905466535312) -Assert Equal (Comptroller CompSupplyState cUSDC "index") (32567188278514519540286631350261809001131) -Assert Equal (Comptroller CompSupplyState cDAI "index") (48523828872606782857477338624275950203274) -Assert Equal (Comptroller CompSupplyState cWBTC "index") (98873610159998754418561608689329824102859175) -Assert Equal (Comptroller CompSupplyState cWBTC2 "index") (551089483977648654874859795061443575084844994561) -Assert Equal (Comptroller CompSupplyState cUSDT "index") (50534796386054496931306603320108731513487) -Assert Equal (Comptroller CompSupplyState cCOMP "index") (3836027216477076374142846684153643830549513) -Assert Equal (Comptroller CompSupplyState cUNI "index") (57432610740828790697901777052414007754599) -Assert Equal (Comptroller CompSupplyState cLINK "index") (852011526290128056285332840775220381888746) -Assert Equal (Comptroller CompSupplyState cZRX "index") (11697528643270194078002497271204681811028) -Assert Equal (Comptroller CompSupplyState cTUSD "index") (1e36) -Assert Equal (Comptroller CompSupplyState cBAT "index") (9278159415477864616059533796790401482787) -Assert Equal (Comptroller CompSupplyState cAAVE "index") (1e36) -Assert Equal (Comptroller CompSupplyState cSAI "index") (1e36) -Assert Equal (Comptroller CompSupplyState cSUSHI "index") (1e36) -Assert Equal (Comptroller CompSupplyState cMKR "index") (1e36) -Assert Equal (Comptroller CompSupplyState cREP "index") (10822464444875983176893501598723703991037) -Assert Equal (Comptroller CompSupplyState cYFI "index") (1e36) - --- Verify old COMP speed storage deleted -Assert Equal (Comptroller CompSpeed cETH) (0) -Assert Equal (Comptroller CompSpeed cUSDC) (0) -Assert Equal (Comptroller CompSpeed cDAI) (0) -Assert Equal (Comptroller CompSpeed cWBTC) (0) -Assert Equal (Comptroller CompSpeed cWBTC2) (0) -Assert Equal (Comptroller CompSpeed cUSDT) (0) -Assert Equal (Comptroller CompSpeed cCOMP) (0) -Assert Equal (Comptroller CompSpeed cUNI) (0) -Assert Equal (Comptroller CompSpeed cLINK) (0) -Assert Equal (Comptroller CompSpeed cZRX) (0) -Assert Equal (Comptroller CompSpeed cTUSD) (0) -Assert Equal (Comptroller CompSpeed cBAT) (0) -Assert Equal (Comptroller CompSpeed cAAVE) (0) -Assert Equal (Comptroller CompSpeed cSAI) (0) -Assert Equal (Comptroller CompSpeed cSUSHI) (0) -Assert Equal (Comptroller CompSpeed cMKR) (0) -Assert Equal (Comptroller CompSpeed cREP) (0) -Assert Equal (Comptroller CompSpeed cYFI) (0) - --- Verify COMP supply speeds equal the previous speeds -Assert Equal (Comptroller CompSupplySpeed cETH) (10750000000000000) -Assert Equal (Comptroller CompSupplySpeed cUSDC) (67000000000000000) -Assert Equal (Comptroller CompSupplySpeed cDAI) (67000000000000000) -Assert Equal (Comptroller CompSupplySpeed cWBTC) (0) -Assert Equal (Comptroller CompSupplySpeed cWBTC2) (10750000000000000) -Assert Equal (Comptroller CompSupplySpeed cUSDT) (9650000000000000) -Assert Equal (Comptroller CompSupplySpeed cCOMP) (5000000000000000) -Assert Equal (Comptroller CompSupplySpeed cUNI) (1462500000000000) -Assert Equal (Comptroller CompSupplySpeed cLINK) (1462500000000000) -Assert Equal (Comptroller CompSupplySpeed cZRX) (1462500000000000) -Assert Equal (Comptroller CompSupplySpeed cTUSD) (0) -Assert Equal (Comptroller CompSupplySpeed cBAT) (1462500000000000) -Assert Equal (Comptroller CompSupplySpeed cAAVE) (0) -Assert Equal (Comptroller CompSupplySpeed cSAI) (0) -Assert Equal (Comptroller CompSupplySpeed cSUSHI) (0) -Assert Equal (Comptroller CompSupplySpeed cMKR) (0) -Assert Equal (Comptroller CompSupplySpeed cREP) (0) -Assert Equal (Comptroller CompSupplySpeed cYFI) (0) - --- Verify COMP borrow speeds equal the previous speeds -Assert Equal (Comptroller CompBorrowSpeed cETH) (10750000000000000) -Assert Equal (Comptroller CompBorrowSpeed cUSDC) (67000000000000000) -Assert Equal (Comptroller CompBorrowSpeed cDAI) (67000000000000000) -Assert Equal (Comptroller CompBorrowSpeed cWBTC) (0) -Assert Equal (Comptroller CompBorrowSpeed cWBTC2) (10750000000000000) -Assert Equal (Comptroller CompBorrowSpeed cUSDT) (9650000000000000) -Assert Equal (Comptroller CompBorrowSpeed cCOMP) (5000000000000000) -Assert Equal (Comptroller CompBorrowSpeed cUNI) (1462500000000000) -Assert Equal (Comptroller CompBorrowSpeed cLINK) (1462500000000000) -Assert Equal (Comptroller CompBorrowSpeed cZRX) (1462500000000000) -Assert Equal (Comptroller CompBorrowSpeed cTUSD) (0) -Assert Equal (Comptroller CompBorrowSpeed cBAT) (1462500000000000) -Assert Equal (Comptroller CompBorrowSpeed cAAVE) (0) -Assert Equal (Comptroller CompBorrowSpeed cSAI) (0) -Assert Equal (Comptroller CompBorrowSpeed cSUSHI) (0) -Assert Equal (Comptroller CompBorrowSpeed cMKR) (0) -Assert Equal (Comptroller CompBorrowSpeed cREP) (0) -Assert Equal (Comptroller CompBorrowSpeed cYFI) (0) - -Print "Upgrade ok" -Print "Verifying exploits/bugs are patched" - --- Mint test -From TokenHolder (Erc20 MKR Approve (Address cMKR) 1000e18) -From TokenHolder (CToken cMKR Mint 1000e18) - -Comptroller ClaimComp TokenHolder -Assert Equal (Erc20 COMP TokenBalance TokenHolder) (0) - --- Fast forward to make us accrue a ton of interest (1 year) -MineBlock -AdvanceBlocks 2354250 - --- Propose COMP speed update -From CompHolder (GovernorBravo GovernorBravo Propose "Exploit rewards bug 1" [(Address Comptroller)] [0] ["_setCompSpeeds(address[],uint256[],uint256[])"] [[[(address cMKR)] [1] [1]]]) - --- Fast forward, vote, queue, execute -MineBlock -AdvanceBlocks 14000 -From CompHolder (GovernorBravo GovernorBravo Proposal LastProposal Vote For) -AdvanceBlocks 20000 -GovernorBravo GovernorBravo Proposal LastProposal Queue -IncreaseTime 604910 -GovernorBravo GovernorBravo Proposal LastProposal Execute - --- Ensure accrue interest -CToken cMKR AccrueInterest - -From TokenHolder (Erc20 MKR Approve (Address cMKR) 1000e18) -From TokenHolder (CToken cMKR Mint 1000e18) - -Comptroller ClaimComp TokenHolder -Assert Equal (Erc20 COMP TokenBalance TokenHolder) (2) - --- Propose COMP speed update -From CompHolder (GovernorBravo GovernorBravo Propose "Exploit rewards bug 2" [(Address Comptroller)] [0] ["_setCompSpeeds(address[],uint256[],uint256[])"] [[[(address cMKR)] [0] [0]]]) - --- Fast forward, vote, queue, execute -MineBlock -AdvanceBlocks 14000 -From CompHolder (GovernorBravo GovernorBravo Proposal LastProposal Vote For) -AdvanceBlocks 20000 -GovernorBravo GovernorBravo Proposal LastProposal Queue -IncreaseTime 604910 -GovernorBravo GovernorBravo Proposal LastProposal Execute - -CToken cMKR AccrueInterest -Comptroller ClaimComp TokenHolder -Assert Equal (Erc20 COMP TokenBalance TokenHolder) (32056) - --- Fast forward to make us accrue a ton of interest - we shouldn't as the rate is 0 (1 year) -MineBlock -AdvanceBlocks 2354250 - --- Propose COMP speed update -From CompHolder (GovernorBravo GovernorBravo Propose "Exploit rewards bug 3" [(Address Comptroller)] [0] ["_setCompSpeeds(address[],uint256[],uint256[])"] [[[(address cMKR)] [1] [1]]]) - --- Fast forward, vote, queue, execute -MineBlock -AdvanceBlocks 14000 -From CompHolder (GovernorBravo GovernorBravo Proposal LastProposal Vote For) -AdvanceBlocks 20000 -GovernorBravo GovernorBravo Proposal LastProposal Queue -IncreaseTime 604910 -GovernorBravo GovernorBravo Proposal LastProposal Execute - --- Ensure accrue interest -CToken cMKR AccrueInterest - -From TokenHolder (Erc20 MKR Approve (Address cMKR) 1000e18) -From TokenHolder (CToken cMKR Mint 1000e18) - -Comptroller ClaimComp TokenHolder -Assert Equal (Erc20 COMP TokenBalance TokenHolder) (32058) - -Print "COMP rewards bug fix passed" \ No newline at end of file diff --git a/spec/sim/0011-whitelist-accounts/hypothetical_upgrade.scen b/spec/sim/0011-whitelist-accounts/hypothetical_upgrade.scen deleted file mode 100755 index 349a7e155..000000000 --- a/spec/sim/0011-whitelist-accounts/hypothetical_upgrade.scen +++ /dev/null @@ -1,40 +0,0 @@ -#!/usr/bin/env yarn repl -s - -PrintTransactionLogs - -Alias Arr00 "0x2B384212EDc04Ae8bB41738D05BA20E33277bf33" -Alias CompHolder "0x7587cAefc8096f5F40ACB83A09Df031a018C66ec" -Alias CommunityMultisig "0xbbf3f1421D886E9b2c5D716B5192aC998af2012c" - -Web3Fork "https://mainnet-eth.compound.finance/@12835588" (CompHolder Arr00 CommunityMultisig) -UseConfigs mainnet - -GovernorBravo Deploy BravoDelegate BravoDelegate2 - -From CompHolder (Comp Delegate CompHolder) -From CompHolder (GovernorBravo GovernorBravoDelegator Propose "Whitelist Accounts" [(Address GovernorBravoDelegator) (Address GovernorBravoDelegator) (Address GovernorBravoDelegator)] [0 0 0] ["_setImplementation(address)" "_setWhitelistAccountExpiration(address,uint256)" "_setWhitelistGuardian(address)"] [[(Address BravoDelegate2)] [(Address Arr00) (FromNow 604911)] [(Address CommunityMultisig)]]) - --- Vote for, queue, and execute the proposal -MineBlock -AdvanceBlocks 13140 -From CompHolder (GovernorBravo GovernorBravoDelegator Proposal LastProposal Vote For) -AdvanceBlocks 20000 -GovernorBravo GovernorBravoDelegator Proposal LastProposal Queue -IncreaseTime 604910 -GovernorBravo GovernorBravoDelegator Proposal LastProposal Execute -GovernorBravo GovernorBravoDelegator MergeABI BravoDelegate2 - -From Arr00 (GovernorBravo GovernorBravoDelegator Propose "Test Proposal" [(Address GovernorBravoDelegator)] [0] ["_setImplementation(address)"] [[(Address BravoDelegate2)]]) - -Send CommunityMultisig 1e18 - --- Use community multisig -From CommunityMultisig (GovernorBravo GovernorBravoDelegator Proposal LastProposal Cancel) -From CommunityMultisig (GovernorBravo GovernorBravoDelegator SetWhitelistAccountExpiration (Address Arr00) 0) - -AllowFailures -From Arr00 (GovernorBravo GovernorBravoDelegator Propose "Test Proposal" [(Address GovernorBravoDelegator)] [0] ["_setImplementation(address)"] [[(Address BravoDelegate2)]]) -Assert Revert "revert GovernorBravo::propose: proposer votes below proposal threshold" - - -Print "Setup whitelisted accounts ok!" diff --git a/spec/sim/0011-whitelist-accounts/hypothetical_upgrade_post_deploy.scen b/spec/sim/0011-whitelist-accounts/hypothetical_upgrade_post_deploy.scen deleted file mode 100755 index 7800b5bb8..000000000 --- a/spec/sim/0011-whitelist-accounts/hypothetical_upgrade_post_deploy.scen +++ /dev/null @@ -1,48 +0,0 @@ -#!/usr/bin/env yarn repl -s - -PrintTransactionLogs - -Alias Arr00 "0x2B384212EDc04Ae8bB41738D05BA20E33277bf33" -Alias CompHolder "0x7587cAefc8096f5F40ACB83A09Df031a018C66ec" -Alias CommunityMultisig "0xbbf3f1421D886E9b2c5D716B5192aC998af2012c" -Alias NewBravoDelegate "0x563a63d650a5d259abae9248dddc6867813d3f87" - -Web3Fork "https://mainnet-eth.compound.finance/@13170219" (CompHolder Arr00 CommunityMultisig) -UseConfigs mainnet - -GovernorBravo Deploy BravoDelegate BravoDelegate2 -- Just used to merge abi - -From CompHolder (Comp Delegate CompHolder) -From CompHolder (GovernorBravo GovernorBravoDelegator Propose "Whitelist Accounts" [(Address GovernorBravoDelegator) (Address GovernorBravoDelegator)] [0 0] ["_setImplementation(address)" "_setWhitelistGuardian(address)"] [[(Address NewBravoDelegate)] [(Address CommunityMultisig)]]) - --- Vote for, queue, and execute the proposal -MineBlock -AdvanceBlocks 13140 -From CompHolder (GovernorBravo GovernorBravoDelegator Proposal LastProposal Vote For) -AdvanceBlocks 20000 -GovernorBravo GovernorBravoDelegator Proposal LastProposal Queue -IncreaseTime 604910 -GovernorBravo GovernorBravoDelegator Proposal LastProposal Execute - -GovernorBravo GovernorBravoDelegator MergeABI BravoDelegate2 - -AllowFailures -From Arr00 (GovernorBravo GovernorBravoDelegator Propose "Test Proposal" [(Address GovernorBravoDelegator)] [0] ["_setImplementation(address)"] [[(Address NewBravoDelegate)]]) -Assert Revert "revert GovernorBravo::propose: proposer votes below proposal threshold" - -Successfully - -Send CommunityMultisig 1e18 --- Use community multisig -Assert False (GovernorBravo GovernorBravoDelegator IsWhitelisted (Address Arr00)) -SetTime 1 -From CommunityMultisig (GovernorBravo GovernorBravoDelegator SetWhitelistAccountExpiration (Address Arr00) 1000) -Assert True (GovernorBravo GovernorBravoDelegator IsWhitelisted (Address Arr00)) - -From Arr00 (GovernorBravo GovernorBravoDelegator Propose "Test Proposal" [(Address GovernorBravoDelegator)] [0] ["_setImplementation(address)"] [[(Address NewBravoDelegate)]]) - -From CommunityMultisig (GovernorBravo GovernorBravoDelegator Proposal LastProposal Cancel) -Assert Equal ("Canceled") (GovernorBravo GovernorBravoDelegator Proposal LastProposal State) - - -Print "Setup whitelisted accounts ok!" diff --git a/spec/sim/0011-whitelist-accounts/hypothetical_upgrade_post_propose.scen b/spec/sim/0011-whitelist-accounts/hypothetical_upgrade_post_propose.scen deleted file mode 100755 index 42bf5dd87..000000000 --- a/spec/sim/0011-whitelist-accounts/hypothetical_upgrade_post_propose.scen +++ /dev/null @@ -1,47 +0,0 @@ -#!/usr/bin/env yarn repl -s - -PrintTransactionLogs - -Alias Arr00 "0x2B384212EDc04Ae8bB41738D05BA20E33277bf33" -Alias CompHolder "0xd5447a7aa223268398cf7c38c2c580622cc98772" -Alias CompHolder2 "0x6626593c237f530d15ae9980a95ef938ac15c35c" -Alias CommunityMultisig "0xbbf3f1421D886E9b2c5D716B5192aC998af2012c" -Alias NewBravoDelegate "0x563a63d650a5d259abae9248dddc6867813d3f87" - -Web3Fork "https://mainnet-eth.compound.finance/@13201186" (CompHolder CompHolder2 Arr00 CommunityMultisig) -UseConfigs mainnet - -GovernorBravo Deploy BravoDelegate BravoDelegate2 -- Just used to merge abi - --- Vote for, queue, and execute the proposal -MineBlock -AdvanceBlocks 13140 -From CompHolder (GovernorBravo GovernorBravoDelegator Proposal LastProposal Vote For) -From CompHolder2 (GovernorBravo GovernorBravoDelegator Proposal LastProposal Vote For) -AdvanceBlocks 20000 -GovernorBravo GovernorBravoDelegator Proposal LastProposal Queue -IncreaseTime 604910 -GovernorBravo GovernorBravoDelegator Proposal LastProposal Execute - -GovernorBravo GovernorBravoDelegator MergeABI BravoDelegate2 - -AllowFailures -From Arr00 (GovernorBravo GovernorBravoDelegator Propose "Test Proposal" [(Address GovernorBravoDelegator)] [0] ["_setImplementation(address)"] [[(Address NewBravoDelegate)]]) -Assert Revert "revert GovernorBravo::propose: proposer votes below proposal threshold" - -Successfully - -Send CommunityMultisig 1e18 --- Use community multisig -Assert False (GovernorBravo GovernorBravoDelegator IsWhitelisted (Address Arr00)) -SetTime 1 -From CommunityMultisig (GovernorBravo GovernorBravoDelegator SetWhitelistAccountExpiration (Address Arr00) 1000) -Assert True (GovernorBravo GovernorBravoDelegator IsWhitelisted (Address Arr00)) - -From Arr00 (GovernorBravo GovernorBravoDelegator Propose "Test Proposal" [(Address GovernorBravoDelegator)] [0] ["_setImplementation(address)"] [[(Address NewBravoDelegate)]]) - -From CommunityMultisig (GovernorBravo GovernorBravoDelegator Proposal LastProposal Cancel) -Assert Equal ("Canceled") (GovernorBravo GovernorBravoDelegator Proposal LastProposal State) - - -Print "Setup whitelisted accounts ok!" diff --git a/spec/sim/0064-fix-comp-accruals/hypothetical_mainnet_upgrade.scen b/spec/sim/0064-fix-comp-accruals/hypothetical_mainnet_upgrade.scen deleted file mode 100755 index 64d6797ae..000000000 --- a/spec/sim/0064-fix-comp-accruals/hypothetical_mainnet_upgrade.scen +++ /dev/null @@ -1,109 +0,0 @@ -#!/usr/bin/env -S yarn repl -s - -PrintTransactionLogs - --- Token holder addresses for mocking -Alias CompHolder "0x7587caefc8096f5f40acb83a09df031a018c66ec" -Alias CUSDCHolder "0xF977814e90dA44bFA03b6295A0616a897441aceC" -- Binance 8 -Alias DaiHolder "0x5f65f7b609678448494De4C87521CdF6cEf1e932" -- Gemini 4 - -Alias Timelock "0x6d903f6003cca6255D85CcA4D3B5E5146dC33925" - --- Fork the block prior to proposal 62 executing -Web3Fork "https://mainnet-eth.compound.finance/@13322797" (CompHolder CUSDCHolder DaiHolder Timelock) -UseConfigs mainnet - --- Disable USDC COMP rewards so that these rewards won't mess with our results -Send Timelock 1e18 -From Timelock (Comptroller SetCompSpeed cUSDC 0) - --- Send USDC from CUSDCHolder to other accounts -From CUSDCHolder (Erc20 USDC Transfer Geoff 1000000e6) -From CUSDCHolder (Erc20 USDC Transfer Torrey 1000000e6) -From CUSDCHolder (Erc20 USDC Transfer Coburn 1000000e6) -From CUSDCHolder (Erc20 USDC Transfer Jared 1000000e6) - --- Send DAI from DaiHolder to other accounts -From DaiHolder (Erc20 DAI Transfer Coburn 1000000e18) -From DaiHolder (Erc20 DAI Transfer Jared 1000000e18) - --- Pre Proposal 62: Deposit collateral and borrow SUSHI -From Geoff (Erc20 USDC Approve (Address cUSDC) 1000000e6) -From Geoff (CToken cUSDC Mint 1000000e6) -From Geoff (Comptroller EnterMarkets (cUSDC)) -From Geoff (CToken cSUSHI Borrow 1000e18) - -From Torrey (Erc20 USDC Approve (Address cUSDC) 1000000e6) -From Torrey (CToken cUSDC Mint 1000000e6) -From Torrey (Comptroller EnterMarkets (cUSDC)) -From Torrey (CToken cSUSHI Borrow 1000e18) - --- Execute proposal 62 -GovernorBravo GovernorBravo Proposal LastProposal Execute -MineBlock - --- Claim COMP for Geoff -Comptroller ClaimComp Geoff - --- Check Geoff COMP rewards - invalid accrual & COMP sent -Assert Equal (Erc20 COMP TokenBalance Geoff) (988792275103122749560) -- Huge amount (988 COMP) -> Bug -Assert Equal (Comptroller CompAccrued Geoff) (0) - --- Cause Torrey to accrue COMP without claiming -From Torrey (CToken cSUSHI Borrow 1e18) -- Causes COMP to be distributed but not claimed - --- Deploy latest Comptroller -ComptrollerImpl Deploy Standard NewComptroller - --- Delegate and propose update (containing bug fix) -From CompHolder (Comp Delegate CompHolder) -From CompHolder (GovernorBravo GovernorBravo Propose "Upgrade Comptroller" [(Address Unitroller) (Address NewComptroller)] [0 0] ["_setPendingImplementation(address)" "_become(address)"] [[(Address NewComptroller)] [(Address Unitroller)]]) - --- Fast forward, vote, queue, execute -MineBlock -AdvanceBlocks 14000 -From CompHolder (GovernorBravo GovernorBravo Proposal LastProposal Vote For) -AdvanceBlocks 20000 -GovernorBravo GovernorBravo Proposal LastProposal Queue -IncreaseTime 604910 -GovernorBravo GovernorBravo Proposal LastProposal Execute -MineBlock - --- Claim COMP for Torrey -Comptroller ClaimComp Torrey - --- Check Torrey COMP balance changes - invalid accrual & COMP not sent -Assert Equal (Erc20 COMP TokenBalance Torrey) (0) -Assert Equal (Comptroller CompAccrued Torrey) (988792086947769887785) -- Huge amount (988 COMP) -> Bug - --- Post bug fix: Deposit collateral (DAI) and borrow SUSHI - block COMP sending -From Coburn (Erc20 DAI Approve (Address cDAI) 1000000e18) -From Coburn (CToken cDAI Mint 1000000e18) -From Coburn (Comptroller EnterMarkets (cDAI)) -From Coburn (CToken cSUSHI Borrow 1000e18) - --- Post bug fix: Deposit collateral (DAI) and borrow BAT - don't block COMP sending -From Jared (Erc20 DAI Approve (Address cDAI) 1000000e18) -From Jared (CToken cDAI Mint 1000000e18) -From Jared (Comptroller EnterMarkets (cDAI)) -From Jared (CToken cBAT Borrow 1000e18) - --- Accrue rewards (if any) -MineBlock -AdvanceBlocks 14000 - --- Claim COMP for Coburn -Comptroller ClaimCompInMarkets Coburn (cDAI cSUSHI) - --- Claim COMP for Jared -Comptroller ClaimCompInMarkets Jared (cDAI cBAT) - --- Check Coburn COMP balance changes - valid accrual & COMP not sent (claim in affected market) -Assert Equal (Erc20 COMP TokenBalance Coburn) (0) -Assert Equal (Comptroller CompAccrued Coburn) (211455443766873733) -- 0.21 COMP accrued - --- Check Jared COMP balance changes - valid accrual & COMP sent (no claim in affected market) -Assert Equal (Erc20 COMP TokenBalance Jared) (212379370589809042) -- 0.21 COMP claimed -Assert Equal (Comptroller CompAccrued Jared) (0) - -Print "Done" \ No newline at end of file diff --git a/spec/sim/0065-correct-bad-comp-accruals/hypothetical_mainnet_upgrade.scen b/spec/sim/0065-correct-bad-comp-accruals/hypothetical_mainnet_upgrade.scen deleted file mode 100755 index 4c85729e2..000000000 --- a/spec/sim/0065-correct-bad-comp-accruals/hypothetical_mainnet_upgrade.scen +++ /dev/null @@ -1,97 +0,0 @@ -#!/usr/bin/env -S yarn repl -s - -PrintTransactionLogs - --- Token holder addresses for mocking -Alias CompHolder "0x7587caefc8096f5f40acb83a09df031a018c66ec" - -Alias AffectedUser1 "0xb3bd459e0598dde1fe84b1d0a1430be175b5d5be" -Alias AffectedUser2 "0xc5119db28adde44a8e1453e733381025a2910f7d" -Alias AffectedUser3 "0x309d413391e975b553b7b8d19bc11f8a6c2eb889" -Alias AffectedUser4 "0x261fe0fc430c4ce4158ebe9258e7f9c646fea448" -Alias AffectedUser54 "0xb265ac5bc12a97bc359b0ca0870f8b1cec6369e9" -Alias AffectedUser74 "0xde122ae193f46d67c239ae0c7dae644f9931a772" -- The last affected user - -Web3Fork "https://mainnet-eth.compound.finance/@13380217" (CompHolder) -UseConfigs mainnet - --- Execute proposal 64 -IncreaseTime 604910 -GovernorBravo GovernorBravo Proposal LastProposal Execute - --- Verify compAccrued for select affected users -Assert Equal (Comptroller CompAccrued AffectedUser1) (70026235599882059838229769) -Assert Equal (Comptroller CompAccrued AffectedUser2) (99436286923591330401865) -Assert Equal (Comptroller CompAccrued AffectedUser3) (0343336911491348169) -Assert Equal (Comptroller CompAccrued AffectedUser4) (0) -Assert Equal (Comptroller CompAccrued AffectedUser54) (4989881308103) -Assert Equal (Comptroller CompAccrued AffectedUser74) (934955697489397386) - --- Deploy latest Comptroller -ComptrollerImpl Deploy Standard NewComptroller - --- Delegate and propose - proposal 65 -From CompHolder (Comp Delegate CompHolder) -From CompHolder (GovernorBravo GovernorBravo Propose "Upgrade Comptroller" [(Address Unitroller) (Address NewComptroller) (Address Unitroller)] [0 0 0] ["_setPendingImplementation(address)" "_become(address)" "fixBadAccruals(address[],uint256[])"] [[(Address NewComptroller)] [(Address Unitroller)] [[0xb3bd459e0598dde1fe84b1d0a1430be175b5d5be 0xc5119db28adde44a8e1453e733381025a2910f7d 0x309d413391e975b553b7b8d19bc11f8a6c2eb889 0x261fe0fc430c4ce4158ebe9258e7f9c646fea448 0xdf6fada48f5963a8977ec2bcd7b264434ce294f6 0x2e4ae4d3bd0af45040b4f17e0bb7e6dc548626b1 0x3af015f6e3ac79d217198f00ef36af099d223e29 0xab5a193a11f779fe105e8edf9815a0b514b013ca 0xf3f5c252e8acd60671f92c7f72cf33661221ef42 0x01b037084eba7e4519dbfc9ba026ae696746e033 0x9657bd100802434797d0fb21c356b0871c24485b 0x712d0f306956a6a4b4f9319ad9b9de48c5345996 0x98d105874052ddef7150afb661190df5f8c3a719 0xf946cdaecf5a15440e500e61a0c1d179a93652ad 0x8e9c0ea7e72531ba2f7014f3b39783ac4a26e34a 0xa7b95d2a2d10028cc4450e453151181cbcac74fc 0x3b3f3ea865293f004e01c35b9e8ba80daabc8a72 0x0246c1e74ee54af89c50bfeffdddbad0f0d63da2 0xe68176a9d8a4323ea3fab649b30e00d0a6a87d15 0xfa24de5410581625ca749d615191bd33e0366a8f 0x75e4c0ffb05c07798e22605b607e2c8717a1e885 0x26a6dc267e276fded7b40251c8fc08b1b40df367 0x621ec0b18317049583ac828461cdb4031ad2a76a 0x8f4138b15a1eb898380d29b677b417dcafd2bbfe 0x34bbc9a46b09283698ba7aa1c273e8b4e9f7bcc3 0x25b651a210f0cd42d1540f885489cae8c9ff0fcc 0xff628b747c4e70825af24e3d59748bac477dcbf6 0x5d6dc617d38655254ea718044d37451e75144357 0x10bf1dcb5ab7860bab1c3320163c6dddf8dcc0e4 0x60a71287353f3ac632f3e75fd1be532850aa5f4d 0x53f79a391c638d03e9ed0823df82e1e72e5f616a 0x90f7fe74192f18e0020eb04de550cb2bdbc7cd4f 0x093599e111a14aaefef98573f26a7aa2cc58ebff 0xa5d223c176daab154a3134369d1c0478c5e6fecf 0x6c9eda0c8ce90ccaf6f88c0fb7511447fb92b3fe 0x7f9d39de53a3036463146e91e921cc9fbfcb2de4 0x8fd2515a5b29e61220ee080d484d1f2ea4c46e6b 0xb35e71b6a5aebb07dfc3aa705968411ebdbc003f 0x107e78d87005a76b1dc787c2e3dd7986bb47568b 0x94aaf5ceb457057ac4d1588257988d487272984f 0x3ddfa8ec3052539b6c9549f12cea2c295cff5296 0xe03ffe4cce71b39ae1a8580aa94aa40ba611c820 0x11690b00fef3091f37dd0f88e36c838cd344547f 0x7d6149ad9a573a6e2ca6ebf7d4897c1b766841b4 0xf6c3c3621f42ec1f1cd1207bb1571d93646ab29a 0xd19b7946621fe75ba15ce23ed90d0af8c962e6d8 0x8de962fdc6521a426389aad89e1c067c8f816004 0x212d3c9ad48926ed3e7ef538caaddb5d10e8eb9e 0xa92766340b0742d4af8c065443640efdfd18a9a3 0x6ddca709e0d29fdd03be35553c77c08f81a3f9e1 0x83b8987b2f48b6b7220ffc6e83fa0f129b9d5149 0x9c84be7ba23a5034c56d0289eefb6c083e96dd94 0xd2e7d58850d058668ee67fad262760e5b05ed2a4 0xb265ac5bc12a97bc359b0ca0870f8b1cec6369e9 0xba2ef5189b762bd4c9e7f0b50fbbab65193935e8 0xe095de809090531d343d046b2fd3abf28419d3d0 0x99265b66461539efd0334901dbb5a2d7f082687a 0x86bbc49a00bde4d64cde650f6ca8cc0f138fd344 0x87279585d52f534a2d2e453518cd7890c5762d19 0x2ecdc1191514b7e1ed44587822dffaf7c670d6ae 0x138f85de34ec8057ec206788a064f842cd64ce9e 0xc63fc0ae83555e2553762edd887433573f77cfc2 0x2b3b15cb2304223d1a8ca28c17258775bd5b0826 0x8c1a4c98c470900567fb9e764243c89cda79400c 0xf8d9ecfb5ddd99a6e0ccabc54a440205cd40e448 0x728e7f512e01e7811037985ddfb15f9bfef517a8 0x6e13be05021e83318fae9f29f2f57cacaccb62a3 0x124e1fafcadc2c017a17b4bbbbfff3867b7dee35 0x0006e4548aed4502ec8c844567840ce6ef1013f5 0x82a726178ab68d446e079901f2ca95f83dde37d4 0x339b00277f32265b5a46599ad30495b0e921eb6f 0xebe5c14f6ac0ce53640cebfe6d213674dc08d440 0x0730fd7d15fa9a40a6c7b2bbb4b8ce9ee6e6d08b 0xde122ae193f46d67c239ae0c7dae644f9931a772] [70024581827215461300286636 99434542520051820798713 91168628321892518528194 65253893519524513427603 37504914534703867310656 29991222921414803034064 29664092163099163866723 22995425435193061317525 18977306140567618322762 16153770461869763337554 14995552017332537907240 11518530074563941561647 9499196713099819935841 7212224879583644596449 7038803948830987770903 4465995783400342603801 3476860522368145404076 2999525712631519714571 2976977462986329769345 1881718446191311189927 1699235799386422007751 1577018231157018115140 1499788428567608763699 1278642977639309919583 1247907251007203364606 998601466881096599093 791579317801755286963 773933487859775608904 762430378814137892973 505305506641181113258 499866820508711159523 491351929276724469475 187011763377256292965 95880194615183341505 35906565779719826718 34940732225857751281 25099485956367649889 19778101924102624863 19505161319578397635 2968804004067920724 432423944715881797 100905201500492779 99856604811161355 49962015092674176 9951593329323840 6757459496349902 5597019815253533 476759772220656 200024507662316 33277774577726 14611468777911 5014905724070 4997677706137 4989881308103 2419923659650 1486146270087 496946680063 349870854800 152196995332 147008249887 104317366337 99993707875 47972588242 44234730265 12031544568 10541282903 8594826060 5000000000 1617031777 1324963912 751720862 293454410 171168761 1549831]]]) -PrintNumber LastGas - --- Fast forward, vote, queue, execute -MineBlock -AdvanceBlocks 14000 -From CompHolder (GovernorBravo GovernorBravo Proposal LastProposal Vote For) -AdvanceBlocks 20000 -GovernorBravo GovernorBravo Proposal LastProposal Queue -IncreaseTime 604910 -GovernorBravo GovernorBravo Proposal LastProposal Execute -PrintNumber LastGas -MineBlock - --- Merge ABIs so that we can call the newly compReceivable without an error -ComptrollerImpl NewComptroller MergeABI - --- Inflection points to test: --- compOverAccrued < compAccrued -- AffectedUser1, AffectedUser2, AffectedUser74 --- compOverAccrued > compAccrued -- AffectedUser3, AffectedUser4 --- compAccrued == 0 -- AffectedUser4 --- compAccrued == compOverAccrued -- AffectedUser54 --- first affected user -- AffectedUser1 --- last affected user -- AffectedUser74 - -Assert Equal (Comptroller CompAccrued AffectedUser1) (1653772666598537943133) -- 70026235599882059838229769 - 70024581827215461300286636 -Assert Equal (Comptroller CompReceivable AffectedUser1) (0) -- compAccrued > compOverAccrued => compReceivable = 0 - -Assert Equal (Comptroller CompAccrued AffectedUser2) (1744403539509603152) -- 99436286923591330401865 - 99434542520051820798713 -Assert Equal (Comptroller CompReceivable AffectedUser2) (0) -- compAccrued > compOverAccrued => compReceivable = 0 - -Assert Equal (Comptroller CompAccrued AffectedUser3) (0) -- compOverAccrued > compAccrued => compAccrued = 0 -Assert Equal (Comptroller CompReceivable AffectedUser3) (91168284984981027180025) -- 91168628321892518528194 - 343336911491348169 - -Assert Equal (Comptroller CompAccrued AffectedUser4) (0) -- compOverAccrued > compAccrued => compAccrued = 0 -Assert Equal (Comptroller CompReceivable AffectedUser4) (65253893519524513427603) -- 65253893519524513427603 - 0 - -Assert Equal (Comptroller CompAccrued AffectedUser54) (0) -- compOverAccrued == compAccrued => compAccrued = 0 -Assert Equal (Comptroller CompReceivable AffectedUser54) (0) -- compOverAccrued == compAccrued => compReceivable = 0 - -Assert Equal (Comptroller CompAccrued AffectedUser74) (934955697487847555) -- 934955697489397386 - 1549831 -Assert Equal (Comptroller CompReceivable AffectedUser74) (0) -- compAccrued > compOverAccrued => compReceivable = 0 - --- Ensure that claimComp functionality has been restored and works as expected --- From 70M COMP accrued to 1955 - looks good -Expect Changes (Erc20 Comp TokenBalance AffectedUser1) +1955396565201585496359 -- 1653772666598537943133 + newly accrued COMP -Comptroller ClaimComp AffectedUser1 -Assert Equal (Comptroller CompAccrued AffectedUser1) (0) - --- Ensure calling fixBadAccruals again reverts -From CompHolder (GovernorBravo GovernorBravo Propose "Call fixBadAccruals for a second time" [(Address Unitroller)] [0] ["fixBadAccruals(address[],uint256[])"] [[[0xb3bd459e0598dde1fe84b1d0a1430be175b5d5be 0xc5119db28adde44a8e1453e733381025a2910f7d 0x309d413391e975b553b7b8d19bc11f8a6c2eb889 0x261fe0fc430c4ce4158ebe9258e7f9c646fea448 0xdf6fada48f5963a8977ec2bcd7b264434ce294f6 0x2e4ae4d3bd0af45040b4f17e0bb7e6dc548626b1 0x3af015f6e3ac79d217198f00ef36af099d223e29 0xab5a193a11f779fe105e8edf9815a0b514b013ca 0xf3f5c252e8acd60671f92c7f72cf33661221ef42 0x01b037084eba7e4519dbfc9ba026ae696746e033 0x9657bd100802434797d0fb21c356b0871c24485b 0x712d0f306956a6a4b4f9319ad9b9de48c5345996 0x98d105874052ddef7150afb661190df5f8c3a719 0xf946cdaecf5a15440e500e61a0c1d179a93652ad 0x8e9c0ea7e72531ba2f7014f3b39783ac4a26e34a 0xa7b95d2a2d10028cc4450e453151181cbcac74fc 0x3b3f3ea865293f004e01c35b9e8ba80daabc8a72 0x0246c1e74ee54af89c50bfeffdddbad0f0d63da2 0xe68176a9d8a4323ea3fab649b30e00d0a6a87d15 0xfa24de5410581625ca749d615191bd33e0366a8f 0x75e4c0ffb05c07798e22605b607e2c8717a1e885 0x26a6dc267e276fded7b40251c8fc08b1b40df367 0x621ec0b18317049583ac828461cdb4031ad2a76a 0x8f4138b15a1eb898380d29b677b417dcafd2bbfe 0x34bbc9a46b09283698ba7aa1c273e8b4e9f7bcc3 0x25b651a210f0cd42d1540f885489cae8c9ff0fcc 0xff628b747c4e70825af24e3d59748bac477dcbf6 0x5d6dc617d38655254ea718044d37451e75144357 0x10bf1dcb5ab7860bab1c3320163c6dddf8dcc0e4 0x60a71287353f3ac632f3e75fd1be532850aa5f4d 0x53f79a391c638d03e9ed0823df82e1e72e5f616a 0x90f7fe74192f18e0020eb04de550cb2bdbc7cd4f 0x093599e111a14aaefef98573f26a7aa2cc58ebff 0xa5d223c176daab154a3134369d1c0478c5e6fecf 0x6c9eda0c8ce90ccaf6f88c0fb7511447fb92b3fe 0x7f9d39de53a3036463146e91e921cc9fbfcb2de4 0x8fd2515a5b29e61220ee080d484d1f2ea4c46e6b 0xb35e71b6a5aebb07dfc3aa705968411ebdbc003f 0x107e78d87005a76b1dc787c2e3dd7986bb47568b 0x94aaf5ceb457057ac4d1588257988d487272984f 0x3ddfa8ec3052539b6c9549f12cea2c295cff5296 0xe03ffe4cce71b39ae1a8580aa94aa40ba611c820 0x11690b00fef3091f37dd0f88e36c838cd344547f 0x7d6149ad9a573a6e2ca6ebf7d4897c1b766841b4 0xf6c3c3621f42ec1f1cd1207bb1571d93646ab29a 0xd19b7946621fe75ba15ce23ed90d0af8c962e6d8 0x8de962fdc6521a426389aad89e1c067c8f816004 0x212d3c9ad48926ed3e7ef538caaddb5d10e8eb9e 0xa92766340b0742d4af8c065443640efdfd18a9a3 0x6ddca709e0d29fdd03be35553c77c08f81a3f9e1 0x83b8987b2f48b6b7220ffc6e83fa0f129b9d5149 0x9c84be7ba23a5034c56d0289eefb6c083e96dd94 0xd2e7d58850d058668ee67fad262760e5b05ed2a4 0xb265ac5bc12a97bc359b0ca0870f8b1cec6369e9 0xba2ef5189b762bd4c9e7f0b50fbbab65193935e8 0xe095de809090531d343d046b2fd3abf28419d3d0 0x99265b66461539efd0334901dbb5a2d7f082687a 0x86bbc49a00bde4d64cde650f6ca8cc0f138fd344 0x87279585d52f534a2d2e453518cd7890c5762d19 0x2ecdc1191514b7e1ed44587822dffaf7c670d6ae 0x138f85de34ec8057ec206788a064f842cd64ce9e 0xc63fc0ae83555e2553762edd887433573f77cfc2 0x2b3b15cb2304223d1a8ca28c17258775bd5b0826 0x8c1a4c98c470900567fb9e764243c89cda79400c 0xf8d9ecfb5ddd99a6e0ccabc54a440205cd40e448 0x728e7f512e01e7811037985ddfb15f9bfef517a8 0x6e13be05021e83318fae9f29f2f57cacaccb62a3 0x124e1fafcadc2c017a17b4bbbbfff3867b7dee35 0x0006e4548aed4502ec8c844567840ce6ef1013f5 0x82a726178ab68d446e079901f2ca95f83dde37d4 0x339b00277f32265b5a46599ad30495b0e921eb6f 0xebe5c14f6ac0ce53640cebfe6d213674dc08d440 0x0730fd7d15fa9a40a6c7b2bbb4b8ce9ee6e6d08b 0xde122ae193f46d67c239ae0c7dae644f9931a772] [70024581827215461300286636 99434542520051820798713 91168628321892518528194 65253893519524513427603 37504914534703867310656 29991222921414803034064 29664092163099163866723 22995425435193061317525 18977306140567618322762 16153770461869763337554 14995552017332537907240 11518530074563941561647 9499196713099819935841 7212224879583644596449 7038803948830987770903 4465995783400342603801 3476860522368145404076 2999525712631519714571 2976977462986329769345 1881718446191311189927 1699235799386422007751 1577018231157018115140 1499788428567608763699 1278642977639309919583 1247907251007203364606 998601466881096599093 791579317801755286963 773933487859775608904 762430378814137892973 505305506641181113258 499866820508711159523 491351929276724469475 187011763377256292965 95880194615183341505 35906565779719826718 34940732225857751281 25099485956367649889 19778101924102624863 19505161319578397635 2968804004067920724 432423944715881797 100905201500492779 99856604811161355 49962015092674176 9951593329323840 6757459496349902 5597019815253533 476759772220656 200024507662316 33277774577726 14611468777911 5014905724070 4997677706137 4989881308103 2419923659650 1486146270087 496946680063 349870854800 152196995332 147008249887 104317366337 99993707875 47972588242 44234730265 12031544568 10541282903 8594826060 5000000000 1617031777 1324963912 751720862 293454410 171168761 1549831]]]) -MineBlock -AdvanceBlocks 14000 -From CompHolder (GovernorBravo GovernorBravo Proposal LastProposal Vote For) -AdvanceBlocks 20000 -GovernorBravo GovernorBravo Proposal LastProposal Queue -IncreaseTime 604910 -AllowFailures -GovernorBravo GovernorBravo Proposal LastProposal Execute -Assert Revert -Successfully - -Print "Done" \ No newline at end of file diff --git a/spec/sim/0065-correct-bad-comp-accruals/mainnet_upgrade.scen b/spec/sim/0065-correct-bad-comp-accruals/mainnet_upgrade.scen deleted file mode 100755 index 65908f3eb..000000000 --- a/spec/sim/0065-correct-bad-comp-accruals/mainnet_upgrade.scen +++ /dev/null @@ -1,89 +0,0 @@ -#!/usr/bin/env -S yarn repl -s - -PrintTransactionLogs - --- Token holder addresses for mocking -Alias CompHolder "0x7587caefc8096f5f40acb83a09df031a018c66ec" - -Alias AffectedUser1 "0xb3bd459e0598dde1fe84b1d0a1430be175b5d5be" -Alias AffectedUser2 "0xc5119db28adde44a8e1453e733381025a2910f7d" -Alias AffectedUser3 "0x309d413391e975b553b7b8d19bc11f8a6c2eb889" -Alias AffectedUser4 "0x261fe0fc430c4ce4158ebe9258e7f9c646fea448" -Alias AffectedUser54 "0xb265ac5bc12a97bc359b0ca0870f8b1cec6369e9" -Alias AffectedUser74 "0xde122ae193f46d67c239ae0c7dae644f9931a772" -- The last affected user - -Web3Fork "https://mainnet-eth.compound.finance/@13400300" (CompHolder) -UseConfigs mainnet - --- Deploy latest Comptroller (needed for ABI merge) -ComptrollerImpl Deploy Standard NewComptroller - --- Merge ABIs so that we can call the newly compReceivable without an error -ComptrollerImpl NewComptroller MergeABI - --- Verify compAccrued for select affected users -Assert Equal (Comptroller CompAccrued AffectedUser1) (70026235599882059838229769) -Assert Equal (Comptroller CompAccrued AffectedUser2) (99436286923591330401865) -Assert Equal (Comptroller CompAccrued AffectedUser3) (0343336911491348169) -Assert Equal (Comptroller CompAccrued AffectedUser4) (0) -Assert Equal (Comptroller CompAccrued AffectedUser54) (4989881308103) -Assert Equal (Comptroller CompAccrued AffectedUser74) (934955697489397386) - --- Delegate and execute proposal 65 -From CompHolder (Comp Delegate CompHolder) -MineBlock -AdvanceBlocks 14000 -From CompHolder (GovernorBravo GovernorBravo Proposal LastProposal Vote For) -AdvanceBlocks 20000 -GovernorBravo GovernorBravo Proposal LastProposal Queue -IncreaseTime 604910 -GovernorBravo GovernorBravo Proposal LastProposal Execute -PrintNumber LastGas -MineBlock - --- Inflection points to test: --- compOverAccrued < compAccrued -- AffectedUser1, AffectedUser2, AffectedUser74 --- compOverAccrued > compAccrued -- AffectedUser3, AffectedUser4 --- compAccrued == 0 -- AffectedUser4 --- compAccrued == compOverAccrued -- AffectedUser54 --- first affected user -- AffectedUser1 --- last affected user -- AffectedUser74 - -Assert Equal (Comptroller CompAccrued AffectedUser1) (1653772666598537943133) -- 70026235599882059838229769 - 70024581827215461300286636 -Assert Equal (Comptroller CompReceivable AffectedUser1) (0) -- compAccrued > compOverAccrued => compReceivable = 0 - -Assert Equal (Comptroller CompAccrued AffectedUser2) (1744403539509603152) -- 99436286923591330401865 - 99434542520051820798713 -Assert Equal (Comptroller CompReceivable AffectedUser2) (0) -- compAccrued > compOverAccrued => compReceivable = 0 - -Assert Equal (Comptroller CompAccrued AffectedUser3) (0) -- compOverAccrued > compAccrued => compAccrued = 0 -Assert Equal (Comptroller CompReceivable AffectedUser3) (91168284984981027180025) -- 91168628321892518528194 - 343336911491348169 - -Assert Equal (Comptroller CompAccrued AffectedUser4) (0) -- compOverAccrued > compAccrued => compAccrued = 0 -Assert Equal (Comptroller CompReceivable AffectedUser4) (65253893519524513427603) -- 65253893519524513427603 - 0 - -Assert Equal (Comptroller CompAccrued AffectedUser54) (0) -- compOverAccrued == compAccrued => compAccrued = 0 -Assert Equal (Comptroller CompReceivable AffectedUser54) (0) -- compOverAccrued == compAccrued => compReceivable = 0 - -Assert Equal (Comptroller CompAccrued AffectedUser74) (934955697487847555) -- 934955697489397386 - 1549831 -Assert Equal (Comptroller CompReceivable AffectedUser74) (0) -- compAccrued > compOverAccrued => compReceivable = 0 - --- Ensure that claimComp functionality has been restored and works as expected --- From 70M COMP accrued to 2055 - looks good -Expect Changes (Erc20 Comp TokenBalance AffectedUser1) +2055078988438040858099 -- 1653772666598537943133 + newly accrued COMP -Comptroller ClaimComp AffectedUser1 -Assert Equal (Comptroller CompAccrued AffectedUser1) (0) - --- Ensure calling fixBadAccruals again reverts -From CompHolder (GovernorBravo GovernorBravo Propose "Call fixBadAccruals for a second time" [(Address Unitroller)] [0] ["fixBadAccruals(address[],uint256[])"] [[[0xb3bd459e0598dde1fe84b1d0a1430be175b5d5be 0xc5119db28adde44a8e1453e733381025a2910f7d 0x309d413391e975b553b7b8d19bc11f8a6c2eb889 0x261fe0fc430c4ce4158ebe9258e7f9c646fea448 0xdf6fada48f5963a8977ec2bcd7b264434ce294f6 0x2e4ae4d3bd0af45040b4f17e0bb7e6dc548626b1 0x3af015f6e3ac79d217198f00ef36af099d223e29 0xab5a193a11f779fe105e8edf9815a0b514b013ca 0xf3f5c252e8acd60671f92c7f72cf33661221ef42 0x01b037084eba7e4519dbfc9ba026ae696746e033 0x9657bd100802434797d0fb21c356b0871c24485b 0x712d0f306956a6a4b4f9319ad9b9de48c5345996 0x98d105874052ddef7150afb661190df5f8c3a719 0xf946cdaecf5a15440e500e61a0c1d179a93652ad 0x8e9c0ea7e72531ba2f7014f3b39783ac4a26e34a 0xa7b95d2a2d10028cc4450e453151181cbcac74fc 0x3b3f3ea865293f004e01c35b9e8ba80daabc8a72 0x0246c1e74ee54af89c50bfeffdddbad0f0d63da2 0xe68176a9d8a4323ea3fab649b30e00d0a6a87d15 0xfa24de5410581625ca749d615191bd33e0366a8f 0x75e4c0ffb05c07798e22605b607e2c8717a1e885 0x26a6dc267e276fded7b40251c8fc08b1b40df367 0x621ec0b18317049583ac828461cdb4031ad2a76a 0x8f4138b15a1eb898380d29b677b417dcafd2bbfe 0x34bbc9a46b09283698ba7aa1c273e8b4e9f7bcc3 0x25b651a210f0cd42d1540f885489cae8c9ff0fcc 0xff628b747c4e70825af24e3d59748bac477dcbf6 0x5d6dc617d38655254ea718044d37451e75144357 0x10bf1dcb5ab7860bab1c3320163c6dddf8dcc0e4 0x60a71287353f3ac632f3e75fd1be532850aa5f4d 0x53f79a391c638d03e9ed0823df82e1e72e5f616a 0x90f7fe74192f18e0020eb04de550cb2bdbc7cd4f 0x093599e111a14aaefef98573f26a7aa2cc58ebff 0xa5d223c176daab154a3134369d1c0478c5e6fecf 0x6c9eda0c8ce90ccaf6f88c0fb7511447fb92b3fe 0x7f9d39de53a3036463146e91e921cc9fbfcb2de4 0x8fd2515a5b29e61220ee080d484d1f2ea4c46e6b 0xb35e71b6a5aebb07dfc3aa705968411ebdbc003f 0x107e78d87005a76b1dc787c2e3dd7986bb47568b 0x94aaf5ceb457057ac4d1588257988d487272984f 0x3ddfa8ec3052539b6c9549f12cea2c295cff5296 0xe03ffe4cce71b39ae1a8580aa94aa40ba611c820 0x11690b00fef3091f37dd0f88e36c838cd344547f 0x7d6149ad9a573a6e2ca6ebf7d4897c1b766841b4 0xf6c3c3621f42ec1f1cd1207bb1571d93646ab29a 0xd19b7946621fe75ba15ce23ed90d0af8c962e6d8 0x8de962fdc6521a426389aad89e1c067c8f816004 0x212d3c9ad48926ed3e7ef538caaddb5d10e8eb9e 0xa92766340b0742d4af8c065443640efdfd18a9a3 0x6ddca709e0d29fdd03be35553c77c08f81a3f9e1 0x83b8987b2f48b6b7220ffc6e83fa0f129b9d5149 0x9c84be7ba23a5034c56d0289eefb6c083e96dd94 0xd2e7d58850d058668ee67fad262760e5b05ed2a4 0xb265ac5bc12a97bc359b0ca0870f8b1cec6369e9 0xba2ef5189b762bd4c9e7f0b50fbbab65193935e8 0xe095de809090531d343d046b2fd3abf28419d3d0 0x99265b66461539efd0334901dbb5a2d7f082687a 0x86bbc49a00bde4d64cde650f6ca8cc0f138fd344 0x87279585d52f534a2d2e453518cd7890c5762d19 0x2ecdc1191514b7e1ed44587822dffaf7c670d6ae 0x138f85de34ec8057ec206788a064f842cd64ce9e 0xc63fc0ae83555e2553762edd887433573f77cfc2 0x2b3b15cb2304223d1a8ca28c17258775bd5b0826 0x8c1a4c98c470900567fb9e764243c89cda79400c 0xf8d9ecfb5ddd99a6e0ccabc54a440205cd40e448 0x728e7f512e01e7811037985ddfb15f9bfef517a8 0x6e13be05021e83318fae9f29f2f57cacaccb62a3 0x124e1fafcadc2c017a17b4bbbbfff3867b7dee35 0x0006e4548aed4502ec8c844567840ce6ef1013f5 0x82a726178ab68d446e079901f2ca95f83dde37d4 0x339b00277f32265b5a46599ad30495b0e921eb6f 0xebe5c14f6ac0ce53640cebfe6d213674dc08d440 0x0730fd7d15fa9a40a6c7b2bbb4b8ce9ee6e6d08b 0xde122ae193f46d67c239ae0c7dae644f9931a772] [70024581827215461300286636 99434542520051820798713 91168628321892518528194 65253893519524513427603 37504914534703867310656 29991222921414803034064 29664092163099163866723 22995425435193061317525 18977306140567618322762 16153770461869763337554 14995552017332537907240 11518530074563941561647 9499196713099819935841 7212224879583644596449 7038803948830987770903 4465995783400342603801 3476860522368145404076 2999525712631519714571 2976977462986329769345 1881718446191311189927 1699235799386422007751 1577018231157018115140 1499788428567608763699 1278642977639309919583 1247907251007203364606 998601466881096599093 791579317801755286963 773933487859775608904 762430378814137892973 505305506641181113258 499866820508711159523 491351929276724469475 187011763377256292965 95880194615183341505 35906565779719826718 34940732225857751281 25099485956367649889 19778101924102624863 19505161319578397635 2968804004067920724 432423944715881797 100905201500492779 99856604811161355 49962015092674176 9951593329323840 6757459496349902 5597019815253533 476759772220656 200024507662316 33277774577726 14611468777911 5014905724070 4997677706137 4989881308103 2419923659650 1486146270087 496946680063 349870854800 152196995332 147008249887 104317366337 99993707875 47972588242 44234730265 12031544568 10541282903 8594826060 5000000000 1617031777 1324963912 751720862 293454410 171168761 1549831]]]) -MineBlock -AdvanceBlocks 14000 -From CompHolder (GovernorBravo GovernorBravo Proposal LastProposal Vote For) -AdvanceBlocks 20000 -GovernorBravo GovernorBravo Proposal LastProposal Queue -IncreaseTime 604910 -AllowFailures -GovernorBravo GovernorBravo Proposal LastProposal Execute -Assert Revert -Successfully - -Print "Done" \ No newline at end of file diff --git a/spec/sim/0089-lower-proposal-threshold-v2/post_deploy.scen b/spec/sim/0089-lower-proposal-threshold-v2/post_deploy.scen deleted file mode 100755 index 1db68d32c..000000000 --- a/spec/sim/0089-lower-proposal-threshold-v2/post_deploy.scen +++ /dev/null @@ -1,52 +0,0 @@ -#!/usr/bin/env yarn repl -s - -PrintTransactionLogs - -Alias CompHolder "0x7587caefc8096f5f40acb83a09df031a018c66ec" -- Compound Team 2 -Alias CompHolder2 "0x5608169973d639649196A84EE4085a708bcBf397" -- Compound Team 3 -Alias CompProposer "0x18c8f1222083997405f2e482338a4650ac02e1d6" -- Compound Holder ~27K -Alias NewBravoDelegate "0x30065B703DE5d473975A2db5bBB790A23FD6EFbD" -- New Bravo Delegate Contract -Alias Ratan "0xcf0Ef02C51438C821246f2e6ADe50e0F1CB0f385" -- Ratan Kaliani ETH address - - -Web3Fork "https://mainnet-eth.compound.finance/@14261479" (CompHolder CompHolder2 CompProposer NewBravoDelegate) -UseConfigs mainnet - -GovernorBravo Deploy BravoDelegate BravoDelegate2 - -From CompHolder (Comp Delegate CompHolder) -From CompHolder2 (Comp Delegate CompHolder) -From CompProposer (Comp Delegate CompProposer) - --- Test that CompProposer proposing fails -AllowFailures -From CompProposer (GovernorBravo GovernorBravoDelegator Propose "Test Proposal" [(Address GovernorBravoDelegator)] [0] ["_setProposalThreshold(uint256)"] [[25000000000000000000000]]) -Successfully -Assert Revert "revert GovernorBravo::propose: proposer votes below proposal threshold" - --- Update Delegate Impl, Reduce Threshold & Allocate 5 COMP to Ratan for completing proposal -From CompHolder (GovernorBravo GovernorBravoDelegator Propose "Reduce Proposal Threshold" [(Address GovernorBravoDelegator) (Address GovernorBravoDelegator) (Address Comptroller)] [0 0 0] ["_setImplementation(address)" "_setProposalThreshold(uint256)" "_grantComp(address,uint256)"] [[(Address NewBravoDelegate)] [25000000000000000000000] [(Address Ratan) 5000000000000000000]]) --- Vote for, queue, and execute the proposal -MineBlock -AdvanceBlocks 13140 -From CompHolder (GovernorBravo GovernorBravoDelegator Proposal LastProposal Vote For) -AdvanceBlocks 20000 -GovernorBravo GovernorBravoDelegator Proposal LastProposal Queue -IncreaseTime 604910 -GovernorBravo GovernorBravoDelegator Proposal LastProposal Execute - --- Check if grant to Ratan was successful -Assert Equal (6977000000000000000) (Erc20 Comp TokenBalance (Address Ratan)) - --- Testing a proposer 10K < x < 65K -From CompProposer (GovernorBravo GovernorBravoDelegator Propose "Test Proposal" [(Address GovernorBravoDelegator)] [0] ["_setProposalThreshold(uint256)"] [[25000000000000000000000]]) --- Vote for, queue, and execute the proposal -MineBlock -AdvanceBlocks 13140 -From CompHolder (GovernorBravo GovernorBravoDelegator Proposal LastProposal Vote For) -AdvanceBlocks 20000 -GovernorBravo GovernorBravoDelegator Proposal LastProposal Queue -IncreaseTime 604910 -GovernorBravo GovernorBravoDelegator Proposal LastProposal Execute - -Print "Lower proposal threshold v2 ok!" diff --git a/spec/sim/0089-lower-proposal-threshold-v2/pre_deploy.scen b/spec/sim/0089-lower-proposal-threshold-v2/pre_deploy.scen deleted file mode 100755 index 076591c9b..000000000 --- a/spec/sim/0089-lower-proposal-threshold-v2/pre_deploy.scen +++ /dev/null @@ -1,51 +0,0 @@ -#!/usr/bin/env yarn repl -s - -PrintTransactionLogs - -Alias CompHolder "0x7587caefc8096f5f40acb83a09df031a018c66ec" -- Compound Team 2 -Alias CompHolder2 "0x5608169973d639649196A84EE4085a708bcBf397" -- Compound Team 3 -Alias CompProposer "0xb326843982c5872768ea8E24dCe34D18b73f0B44" -- Compound Holder ~15K -Alias CalBlockchain "0x7AE109A63ff4DC852e063a673b40BED85D22E585" -Alias Ratan "0xcf0Ef02C51438C821246f2e6ADe50e0F1CB0f385" -- Ratan Kaliani ETH address - -Web3Fork "https://mainnet-eth.compound.finance/@14251015" (CompHolder CompHolder2 CompProposer CalBlockchain) -UseConfigs mainnet - -GovernorBravo Deploy BravoDelegate BravoDelegate2 - -From CompHolder (Comp Delegate CompHolder) -From CompHolder2 (Comp Delegate CompHolder) -From CompProposer (Comp Delegate CompProposer) - --- Test that CompProposer proposing fails -AllowFailures -From CompProposer (GovernorBravo GovernorBravoDelegator Propose "Test Proposal" [(Address GovernorBravoDelegator)] [0] ["_setProposalThreshold(uint256)"] [[10000000000000000000000]]) -Successfully -Assert Revert "revert GovernorBravo::propose: proposer votes below proposal threshold" - --- Allocate 5 COMP to Ratan for completing proposal -From CompHolder (GovernorBravo GovernorBravoDelegator Propose "Reduce Proposal Threshold" [(Address GovernorBravoDelegator) (Address GovernorBravoDelegator) (Address Comptroller)] [0 0 0] ["_setImplementation(address)" "_setProposalThreshold(uint256)" "_grantComp(address,uint256)"] [[(Address BravoDelegate2)] [10000000000000000000000] [(Address Ratan) 5000000000000000000]]) --- Vote for, queue, and execute the proposal -MineBlock -AdvanceBlocks 13140 -From CompHolder (GovernorBravo GovernorBravoDelegator Proposal LastProposal Vote For) -AdvanceBlocks 20000 -GovernorBravo GovernorBravoDelegator Proposal LastProposal Queue -IncreaseTime 604910 -GovernorBravo GovernorBravoDelegator Proposal LastProposal Execute - --- Check if grant to Ratan was successful -Assert Equal (6977000000000000000) (Erc20 Comp TokenBalance (Address Ratan)) - --- Testing a proposer 10K < x < 65K -From CompProposer (GovernorBravo GovernorBravoDelegator Propose "Test Proposal" [(Address GovernorBravoDelegator)] [0] ["_setProposalThreshold(uint256)"] [[10000000000000000000000]]) --- Vote for, queue, and execute the proposal -MineBlock -AdvanceBlocks 13140 -From CompHolder (GovernorBravo GovernorBravoDelegator Proposal LastProposal Vote For) -AdvanceBlocks 20000 -GovernorBravo GovernorBravoDelegator Proposal LastProposal Queue -IncreaseTime 604910 -GovernorBravo GovernorBravoDelegator Proposal LastProposal Execute - -Print "Lower proposal threshold v2 ok!" From b384429e71978c85fbe4b24aa6f088b64b9b8c26 Mon Sep 17 00:00:00 2001 From: Kirill Kuvshinov Date: Thu, 21 Sep 2023 13:54:43 +0300 Subject: [PATCH 06/33] refactor: remove unused Certora rules * Certora ruleset has not been maintained for Venus IL, so some of the invariants may no longer hold. The interface of Venus IL contracts is also not always compatible with Compound. * This commit removes outdated Certora rules in favor of using a new ruleset in future once it's developed. --- spec/certora/CErc20/accrueInterest.cvl | 66 ---- spec/certora/CErc20/admin.cvl | 101 ------ spec/certora/CErc20/borrowAndRepayFresh.cvl | 238 ------------- spec/certora/CErc20/eip20.cvl | 137 -------- spec/certora/CErc20/exchangeRate.cvl | 53 --- spec/certora/CErc20/frame.cvl | 257 -------------- spec/certora/CErc20/liquidateFresh.cvl | 315 ------------------ spec/certora/CErc20/mintAndRedeemFresh.cvl | 244 -------------- spec/certora/CErc20/rounding.cvl | 29 -- spec/certora/CErc20Delegator | 1 - spec/certora/Comp/search.cvl | 23 -- spec/certora/Comp/transfer.cvl | 44 --- spec/certora/Comptroller/comptroller.cvl | 157 --------- spec/certora/Governor/alpha.cvl | 123 ------- spec/certora/Governor/state.cvl | 118 ------- spec/certora/Governor/votes.cvl | 43 --- spec/certora/Math/int.cvl | 24 -- spec/certora/Maximillion/maximillion.cvl | 26 -- spec/certora/Timelock/timelock.cvl | 91 ----- spec/certora/cDAI/mcd.cvl | 14 - .../certora/contracts/CDaiDelegateCertora.sol | 9 - .../contracts/CErc20DelegateCertora.sol | 41 --- .../contracts/CErc20DelegatorCertora.sol | 133 -------- .../contracts/CErc20ImmutableCertora.sol | 104 ------ spec/certora/contracts/CEtherCertora.sol | 18 - spec/certora/contracts/CTokenCollateral.sol | 33 -- spec/certora/contracts/CompCertora.sol | 36 -- spec/certora/contracts/ComptrollerCertora.sol | 21 -- .../contracts/GovernorAlphaCertora.sol | 63 ---- .../contracts/InterestRateModelModel.sol | 29 -- spec/certora/contracts/MathCertora.sol | 3 - spec/certora/contracts/MaximillionCertora.sol | 19 -- spec/certora/contracts/PriceOracleModel.sol | 15 - .../certora/contracts/SimulationInterface.sol | 5 - spec/certora/contracts/TimelockCertora.sol | 23 -- .../contracts/UnderlyingModelNonStandard.sol | 50 --- .../contracts/UnderlyingModelWithFee.sol | 55 --- spec/certora/contracts/mcd/Dai.sol | 158 --------- spec/certora/contracts/mcd/Lib.sol | 45 --- spec/certora/contracts/mcd/Pot.sol | 198 ----------- spec/certora/contracts/mcd/Vat.sol | 304 ----------------- spec/certora/contracts/mcd/join.sol | 209 ------------ 42 files changed, 3675 deletions(-) delete mode 100644 spec/certora/CErc20/accrueInterest.cvl delete mode 100644 spec/certora/CErc20/admin.cvl delete mode 100644 spec/certora/CErc20/borrowAndRepayFresh.cvl delete mode 100644 spec/certora/CErc20/eip20.cvl delete mode 100644 spec/certora/CErc20/exchangeRate.cvl delete mode 100644 spec/certora/CErc20/frame.cvl delete mode 100644 spec/certora/CErc20/liquidateFresh.cvl delete mode 100644 spec/certora/CErc20/mintAndRedeemFresh.cvl delete mode 100644 spec/certora/CErc20/rounding.cvl delete mode 120000 spec/certora/CErc20Delegator delete mode 100644 spec/certora/Comp/search.cvl delete mode 100644 spec/certora/Comp/transfer.cvl delete mode 100644 spec/certora/Comptroller/comptroller.cvl delete mode 100644 spec/certora/Governor/alpha.cvl delete mode 100644 spec/certora/Governor/state.cvl delete mode 100644 spec/certora/Governor/votes.cvl delete mode 100644 spec/certora/Math/int.cvl delete mode 100644 spec/certora/Maximillion/maximillion.cvl delete mode 100644 spec/certora/Timelock/timelock.cvl delete mode 100644 spec/certora/cDAI/mcd.cvl delete mode 100644 spec/certora/contracts/CDaiDelegateCertora.sol delete mode 100644 spec/certora/contracts/CErc20DelegateCertora.sol delete mode 100644 spec/certora/contracts/CErc20DelegatorCertora.sol delete mode 100644 spec/certora/contracts/CErc20ImmutableCertora.sol delete mode 100644 spec/certora/contracts/CEtherCertora.sol delete mode 100644 spec/certora/contracts/CTokenCollateral.sol delete mode 100644 spec/certora/contracts/CompCertora.sol delete mode 100644 spec/certora/contracts/ComptrollerCertora.sol delete mode 100644 spec/certora/contracts/GovernorAlphaCertora.sol delete mode 100644 spec/certora/contracts/InterestRateModelModel.sol delete mode 100644 spec/certora/contracts/MathCertora.sol delete mode 100644 spec/certora/contracts/MaximillionCertora.sol delete mode 100644 spec/certora/contracts/PriceOracleModel.sol delete mode 100644 spec/certora/contracts/SimulationInterface.sol delete mode 100644 spec/certora/contracts/TimelockCertora.sol delete mode 100644 spec/certora/contracts/UnderlyingModelNonStandard.sol delete mode 100644 spec/certora/contracts/UnderlyingModelWithFee.sol delete mode 100644 spec/certora/contracts/mcd/Dai.sol delete mode 100644 spec/certora/contracts/mcd/Lib.sol delete mode 100644 spec/certora/contracts/mcd/Pot.sol delete mode 100644 spec/certora/contracts/mcd/Vat.sol delete mode 100644 spec/certora/contracts/mcd/join.sol diff --git a/spec/certora/CErc20/accrueInterest.cvl b/spec/certora/CErc20/accrueInterest.cvl deleted file mode 100644 index 7ab1517b5..000000000 --- a/spec/certora/CErc20/accrueInterest.cvl +++ /dev/null @@ -1,66 +0,0 @@ - -accrueInterest(uint result) -description "Break accrueInterest with result=$result, block delta is $delta" { - // Pre/action/post environments - env e0; - env e1; - - require e1.block.number >= e0.block.number; - - // fetch pre - uint256 cTokenCashPre = sinvoke getCash(e0); - - uint256 borrowRateMaxMantissa = 5000000000000; - uint256 borrowRateMantissaPre = sinvoke borrowRatePerBlock(e0); - bool interestRateModelReverted = lastReverted; - - uint256 accrualBlockNumberPre = sinvoke accrualBlockNumber(e0); - uint256 borrowIndexPre = sinvoke borrowIndex(e0); - uint256 totalBorrowsPre = sinvoke totalBorrows(e0); - uint256 totalReservesPre = sinvoke totalReserves(e0); - uint256 reserveFactorPre = sinvoke reserveFactorMantissa(e0); - - // internal computations - uint256 delta = e0.block.number - accrualBlockNumberPre; - require delta >= 0; - - uint256 simpleInterestFactor = delta * borrowRateMantissaPre; - uint256 interestAccumulated = (totalBorrowsPre * simpleInterestFactor) / 1000000000000000000; - - // post expected - uint256 borrowIndexPostExpected = borrowIndexPre + (borrowIndexPre*simpleInterestFactor) / 1000000000000000000; - uint256 totalBorrowsPostExpected = totalBorrowsPre + interestAccumulated; - uint256 totalReservesPostExpected = totalReservesPre + (interestAccumulated*reserveFactorPre) / 1000000000000000000; - - // Action! - require result == invoke accrueInterest(e0); - bool accrueInterestReverted = lastReverted; - - // fetch post - uint256 accrualBlockNumberPost = sinvoke accrualBlockNumber(e1); - uint256 borrowIndexPostActual = sinvoke borrowIndex(e1); - uint256 totalBorrowsPostActual = sinvoke totalBorrows(e1); - uint256 totalReservesPostActual = sinvoke totalReserves(e1); - - uint256 NO_ERROR = 0; - uint256 MATH_ERROR = 9; - - // Guarantee return values - assert (accrueInterestReverted <=> (interestRateModelReverted || borrowRateMantissaPre > borrowRateMaxMantissa)), "Reverted for unexpected reason"; - - assert (!accrueInterestReverted) => (result == NO_ERROR || result == MATH_ERROR), "Got unexpected error code"; - - assert (!accrueInterestReverted => - ((result != 0 || delta == 0) <=> - (accrualBlockNumberPost == accrualBlockNumberPre && - borrowIndexPostActual == borrowIndexPre && - totalBorrowsPostActual == totalBorrowsPre && - totalReservesPostActual == totalReservesPre))), "Mismatch in static case"; - - assert (!accrueInterestReverted => - ((result == 0) <=> - (accrualBlockNumberPost == e0.block.number && - borrowIndexPostActual == borrowIndexPostExpected && - totalBorrowsPostActual == totalBorrowsPostExpected && - totalReservesPostActual == totalReservesPostExpected))), "Mismatch in no error case"; -} diff --git a/spec/certora/CErc20/admin.cvl b/spec/certora/CErc20/admin.cvl deleted file mode 100644 index 404ec3461..000000000 --- a/spec/certora/CErc20/admin.cvl +++ /dev/null @@ -1,101 +0,0 @@ -_setPendingAdmin(address currentAdmin, address currentPendingAdmin, address newPendingAdmin) -description "Failed to set new pending admin $currentPendingAdmin to $newPendingAdmin (admin=$currentAdmin)" -{ - // Free Variables - env e0; - env e1; - env e2; - - require currentAdmin == sinvoke admin(e0); - require currentPendingAdmin == sinvoke pendingAdmin(e0); - - // Invoke set new pending admin - uint256 result = sinvoke _setPendingAdmin(e1, newPendingAdmin); - - // pendingAdmin changes <=> msg.sender == currentAdmin - assert ( - ( - e1.msg.sender == currentAdmin && - result == 0 && - sinvoke pendingAdmin(e2) == newPendingAdmin - ) - || - ( - e1.msg.sender != currentAdmin && - result != 0 && - sinvoke pendingAdmin(e2) == currentPendingAdmin - ) - ); -} - -_acceptAdmin(address currentAdmin, address currentPendingAdmin, address newAdmin, address newPendingAdmin) -description "Failed to accept pending admin currentAdmin=$currentAdmin, currentPendingAdmin=$currentPendingAdmin, newPendingAdmin=$newPendingAdmin, newAdmin=$newAdmin" -{ - // Free Variables - env e0; - env e1; - env e2; - - require currentAdmin == sinvoke admin(e0); - require currentPendingAdmin == sinvoke pendingAdmin(e0); - - // Invoke accept admin - uint256 result = sinvoke _acceptAdmin(e1); - - require newAdmin == sinvoke admin(e2); - require newPendingAdmin == sinvoke pendingAdmin(e2); - - // admin == pendingAdmin <=> msg.sender == pendingAdmin - assert ( - ( - e1.msg.sender == currentPendingAdmin && - currentPendingAdmin != 0 && - result == 0 && - newAdmin == currentPendingAdmin && - newPendingAdmin == 0 - ) - || - ( - ( - e1.msg.sender != currentPendingAdmin || - currentPendingAdmin == 0 - ) && - result != 0 && - newAdmin == currentAdmin && - newPendingAdmin == currentPendingAdmin - ) - ); -} - -// Invariant: To change admin or currentPendingAdmin, must come from current admin -invariantRequireAdminToChangeAdmin(address caller, address currentAdmin, address currentPendingAdmin, address desiredAdmin, address newAdmin, address newPendingAdmin) - description "Failed to prove that required to be admin to change admin (caller=$caller, currentAdmin=$currentAdmin, currentPendingAdmin=$currentPendingAdmin, desiredAdmin=$desiredAdmin, newAdmin=$newAdmin, newPendingAdmin=$newPendingAdmin)" -{ - // Free Variables - env e0; - env e1; - env e2; - env e3; - - require currentAdmin == sinvoke admin(e0); - require currentPendingAdmin == sinvoke pendingAdmin(e0); - - // Start with a zero admin - require currentPendingAdmin == 0; - - require caller == e1.msg.sender; - - // Invoke set new pending admin - uint256 result0 = sinvoke _setPendingAdmin(e1, desiredAdmin); - uint256 result1 = sinvoke _acceptAdmin(e2); - - require newAdmin == sinvoke admin(e3); - require newPendingAdmin == sinvoke pendingAdmin(e3); - - assert (e1.msg.sender == currentAdmin || - ( - newAdmin == currentAdmin && - newPendingAdmin == currentPendingAdmin - ) - ); -} diff --git a/spec/certora/CErc20/borrowAndRepayFresh.cvl b/spec/certora/CErc20/borrowAndRepayFresh.cvl deleted file mode 100644 index ddaf89f7c..000000000 --- a/spec/certora/CErc20/borrowAndRepayFresh.cvl +++ /dev/null @@ -1,238 +0,0 @@ - -borrowFresh(uint result, address borrower, uint256 borrowAmount) -description "Break borrow with result=$result borrower=$borrower borrowAmount=$borrowAmount" { - // Pre/action/post environments - env e0; - env e1; - env e2; - - require e1.block.number >= e0.block.number; - require e2.block.number >= e1.block.number; - - // Any other account - address other; - require other != borrower && other != currentContract; - - /* - - exchange rate should not change - - errors should have no effect - - no *other* storage should change - XXX can we specify this? - - |----------+--------+----------+-------| - | | CToken | Borrower | Other | - |----------+--------+----------+-------| - | cash | -A | +A | 0 | - | borrows | +A | +A | 0 | - | tokens | 0 | 0 | 0 | - | reserves | 0 | | | - |----------+--------+----------+-------| - */ - - /* Pre */ - - uint256 exchangeRatePre = sinvoke exchangeRateStored(e0); - - uint256 cTokenCashPre = sinvoke getCash(e0); - uint256 borrowerCashPre = sinvoke getCashOf(e0, borrower); - uint256 otherCashPre = sinvoke getCashOf(e0, other); - - uint256 cTokenBorrowsPre = sinvoke totalBorrows(e0); - uint256 borrowerBorrowsPre = sinvoke borrowBalanceStored(e0, borrower); - uint256 otherBorrowsPre = sinvoke borrowBalanceStored(e0, other); - - uint256 cTokenTokensPre = sinvoke totalSupply(e0); - uint256 borrowerTokensPre = sinvoke balanceOf(e0, borrower); - uint256 otherTokensPre = sinvoke balanceOf(e0, other); - - uint256 cTokenReservesPre = sinvoke totalReserves(e0); - - // Just Do It - require result == invoke borrowFreshPub(e1, borrower, borrowAmount); - bool borrowFreshReverted = lastReverted; - - /* Post */ - - uint256 exchangeRatePost = sinvoke exchangeRateStored(e2); - - uint256 cTokenCashPost = sinvoke getCash(e2); - uint256 borrowerCashPost = sinvoke getCashOf(e2, borrower); - uint256 otherCashPost = sinvoke getCashOf(e2, other); - - uint256 cTokenBorrowsPost = sinvoke totalBorrows(e2); - uint256 borrowerBorrowsPost = sinvoke borrowBalanceStored(e2, borrower); - uint256 otherBorrowsPost = sinvoke borrowBalanceStored(e2, other); - - uint256 cTokenTokensPost = sinvoke totalSupply(e2); - uint256 borrowerTokensPost = sinvoke balanceOf(e2, borrower); - uint256 otherTokensPost = sinvoke balanceOf(e2, other); - - uint256 cTokenReservesPost = sinvoke totalReserves(e2); - - // Measure - bool staticBalance = - (exchangeRatePost == exchangeRatePre) && - (cTokenCashPost == cTokenCashPre) && - (cTokenBorrowsPost == cTokenBorrowsPre) && - (cTokenTokensPost == cTokenTokensPre) && - (cTokenReservesPost == cTokenReservesPre) && - (borrowerCashPost == borrowerCashPre) && - (borrowerBorrowsPost == borrowerBorrowsPre) && - (borrowerTokensPost == borrowerTokensPre) && - (otherCashPost == otherCashPre) && - (otherBorrowsPost == otherBorrowsPre) && - (otherTokensPost == otherTokensPre); - - bool dynamicBalance = - (borrowAmount != 0) && - (exchangeRatePost == exchangeRatePre) && - (cTokenCashPost == cTokenCashPre - borrowAmount) && - (cTokenBorrowsPost == cTokenBorrowsPre + borrowAmount) && - (cTokenTokensPost == cTokenTokensPre) && - (cTokenReservesPost == cTokenReservesPre) && - (borrowerCashPost == borrowerCashPre + borrowAmount) && - (borrowerBorrowsPost == borrowerBorrowsPre + borrowAmount) && - (borrowerTokensPost == borrowerTokensPre) && - (otherCashPost == otherCashPre) && - (otherBorrowsPost == otherBorrowsPre) && - (otherTokensPost == otherTokensPre); - - assert (!borrowFreshReverted => - ((result != 0 || borrowAmount == 0) <=> staticBalance)), "Mismatch in static case"; - assert (!borrowFreshReverted => - ((result == 0 && borrowAmount != 0 && borrower != currentContract) <=> dynamicBalance)), "Mismatch in dynamic case"; -} - -repayBorrowFresh(uint result, address payer, address borrower, uint256 repayAmount) -description "Break repay borrow with realRepayAmount=$realRepayAmount borrowerBorrowsPre=$borrowerBorrowsPre" { - // Pre/action/post environments - env e0; - env e1; - env e2; - - require e1.block.number >= e0.block.number; - require e2.block.number >= e1.block.number; - - // Any other account - address other; - require other != payer && other != borrower && other != currentContract; - - // We assume this cannot happen - // OQ: should we enforce in the code such that it need not be assumed? - require borrower != currentContract; - require payer != currentContract; - - /* - |----------+--------+-------+----------+-------| - | | CToken | Payer | Borrower | Other | - |----------+--------+-------+----------+-------| - | cash | +A | -A | -A/0 | 0 | - | borrows | -A | -A/0 | -A | 0 | - | tokens | 0 | 0 | 0 | 0 | - | reserves | 0 | | | | - |----------+--------+-------+----------+-------| - */ - - /* Pre */ - - uint256 exchangeRatePre = sinvoke exchangeRateStored(e0); - - uint256 cTokenCashPre = sinvoke getCash(e0); - uint256 payerCashPre = sinvoke getCashOf(e0, payer); - uint256 borrowerCashPre = sinvoke getCashOf(e0, borrower); - uint256 otherCashPre = sinvoke getCashOf(e0, other); - - uint256 cTokenBorrowsPre = sinvoke totalBorrows(e0); - uint256 payerBorrowsPre = sinvoke borrowBalanceStored(e0, payer); - uint256 borrowerBorrowsPre = sinvoke borrowBalanceStored(e0, borrower); - uint256 otherBorrowsPre = sinvoke borrowBalanceStored(e0, other); - - uint256 cTokenTokensPre = sinvoke totalSupply(e0); - uint256 payerTokensPre = sinvoke balanceOf(e0, payer); - uint256 borrowerTokensPre = sinvoke balanceOf(e0, borrower); - uint256 otherTokensPre = sinvoke balanceOf(e0, other); - - uint256 cTokenReservesPre = sinvoke totalReserves(e0); - - // Just Do It - require result == invoke repayBorrowFreshPub(e1, payer, borrower, repayAmount); - bool repayBorrowFreshReverted = lastReverted; - - /* Post */ - - uint256 exchangeRatePost = sinvoke exchangeRateStored(e2); - - uint256 cTokenCashPost = sinvoke getCash(e2); - uint256 payerCashPost = sinvoke getCashOf(e2, payer); - uint256 borrowerCashPost = sinvoke getCashOf(e2, borrower); - uint256 otherCashPost = sinvoke getCashOf(e2, other); - - uint256 cTokenBorrowsPost = sinvoke totalBorrows(e2); - uint256 payerBorrowsPost = sinvoke borrowBalanceStored(e2, payer); - uint256 borrowerBorrowsPost = sinvoke borrowBalanceStored(e2, borrower); - uint256 otherBorrowsPost = sinvoke borrowBalanceStored(e2, other); - - uint256 cTokenTokensPost = sinvoke totalSupply(e2); - uint256 payerTokensPost = sinvoke balanceOf(e2, payer); - uint256 borrowerTokensPost = sinvoke balanceOf(e2, borrower); - uint256 otherTokensPost = sinvoke balanceOf(e2, other); - - uint256 cTokenReservesPost = sinvoke totalReserves(e2); - - // Measure - bool staticBalance = - (exchangeRatePost == exchangeRatePre) && - (cTokenCashPost == cTokenCashPre) && - (cTokenBorrowsPost == cTokenBorrowsPre) && - (cTokenTokensPost == cTokenTokensPre) && - (cTokenReservesPost == cTokenReservesPre) && - (payerCashPost == payerCashPre) && - (payerBorrowsPost == payerBorrowsPre) && - (payerTokensPost == payerTokensPre) && - (borrowerCashPost == borrowerCashPre) && - (borrowerBorrowsPost == borrowerBorrowsPre) && - (borrowerTokensPost == borrowerTokensPre) && - (otherCashPost == otherCashPre) && - (otherBorrowsPost == otherBorrowsPre) && - (otherTokensPost == otherTokensPre); - - // XXX more convenient way to represent uint max? - uint256 UINT_MAX = 115792089237316195423570985008687907853269984665640564039457584007913129639935; - uint256 realRepayAmount; - require - ((repayAmount == UINT_MAX) => - (realRepayAmount == borrowerBorrowsPre)) && - ((repayAmount != UINT_MAX) => - (realRepayAmount == repayAmount)); - - uint256 payerBorrowsExpected; - uint256 borrowerCashExpected; - require - ((payer == borrower) => - (payerBorrowsExpected == payerBorrowsPre - realRepayAmount) && - (borrowerCashExpected == borrowerCashPre - realRepayAmount)) && - ((payer != borrower) => - (payerBorrowsExpected == payerBorrowsPre) && - (borrowerCashExpected == borrowerCashPre)); - - bool dynamicBalance = - (realRepayAmount != 0) && - (exchangeRatePost == exchangeRatePre) && - (cTokenCashPost == cTokenCashPre + realRepayAmount) && - (cTokenBorrowsPost == cTokenBorrowsPre - realRepayAmount) && - (cTokenTokensPost == cTokenTokensPre) && - (cTokenReservesPost == cTokenReservesPre) && - (payerCashPost == payerCashPre - realRepayAmount) && - (payerBorrowsPost == payerBorrowsExpected) && - (payerTokensPost == payerTokensPre) && - (borrowerCashPost == borrowerCashExpected) && - (borrowerBorrowsPost == borrowerBorrowsPre - realRepayAmount) && - (borrowerTokensPost == borrowerTokensPre) && - (otherCashPost == otherCashPre) && - (otherBorrowsPost == otherBorrowsPre) && - (otherTokensPost == otherTokensPre); - - assert (!repayBorrowFreshReverted => - ((result != 0 || realRepayAmount == 0) <=> staticBalance)), "Mismatch in static case"; - assert (!repayBorrowFreshReverted => - ((result == 0 && realRepayAmount != 0 && payer != currentContract) <=> dynamicBalance)), "Mismatch in dynamic case"; -} diff --git a/spec/certora/CErc20/eip20.cvl b/spec/certora/CErc20/eip20.cvl deleted file mode 100644 index 385098816..000000000 --- a/spec/certora/CErc20/eip20.cvl +++ /dev/null @@ -1,137 +0,0 @@ -transferFrom(bool success, address src, address dst, uint256 amount) -description "Break transferFrom" { - // Pre/action/post environments - env e0; - env e1a; - env e1b; - env e2; - - require e1a.block.number >= e0.block.number; - require e1b.block.number >= e1a.block.number; - require e2.block.number >= e1b.block.number; - - // Any other account - address other; - require other != src && other != dst; - - /* - - no effect on exchange rate - - no more than approved - |----------+--------+-----+-----+-------| - | | CToken | Src | Dst | Other | - |----------+--------+-----+-----+-------| - | cash | 0 | 0 | 0 | 0 | - | borrows | 0 | 0 | 0 | 0 | - | tokens | 0 | -T | +T | 0 | - | reserves | 0 | | | | - |----------+--------+-----+-----+-------| - */ - - /* Pre */ - - uint256 exchangeRatePre = sinvoke exchangeRateStored(e0); - - uint256 cTokenCashPre = sinvoke getCash(e0); - uint256 srcCashPre = sinvoke getCashOf(e0, src); - uint256 dstCashPre = sinvoke getCashOf(e0, dst); - uint256 otherCashPre = sinvoke getCashOf(e0, other); - - uint256 cTokenBorrowsPre = sinvoke totalBorrows(e0); - uint256 srcBorrowsPre = sinvoke borrowBalanceStored(e0, src); - uint256 dstBorrowsPre = sinvoke borrowBalanceStored(e0, dst); - uint256 otherBorrowsPre = sinvoke borrowBalanceStored(e0, other); - - uint256 cTokenSupplyPre = sinvoke totalSupply(e0); - uint256 srcTokensPre = sinvoke balanceOf(e0, src); - uint256 dstTokensPre = sinvoke balanceOf(e0, dst); - uint256 otherTokensPre = sinvoke balanceOf(e0, other); - - uint256 cTokenReservesPre = sinvoke totalReserves(e0); - - // Approve - bool doApprove; - uint256 approvedAmount; - if (doApprove) { - require e1a.msg.sender == src; - sinvoke approve(e1a, e1b.msg.sender, approvedAmount); - } else {} - - uint256 allowancePre = sinvoke allowance(e1a, src, e1b.msg.sender); - - // Just Do It - require success == invoke transferFrom(e1b, src, dst, amount); - bool transferReverted = lastReverted; - - /* Post */ - - uint256 exchangeRatePost = sinvoke exchangeRateStored(e2); - - uint256 cTokenCashPost = sinvoke getCash(e2); - uint256 srcCashPost = sinvoke getCashOf(e2, src); - uint256 dstCashPost = sinvoke getCashOf(e2, dst); - uint256 otherCashPost = sinvoke getCashOf(e2, other); - - uint256 cTokenBorrowsPost = sinvoke totalBorrows(e2); - uint256 srcBorrowsPost = sinvoke borrowBalanceStored(e2, src); - uint256 dstBorrowsPost = sinvoke borrowBalanceStored(e2, dst); - uint256 otherBorrowsPost = sinvoke borrowBalanceStored(e2, other); - - uint256 cTokenSupplyPost = sinvoke totalSupply(e2); - uint256 srcTokensPost = sinvoke balanceOf(e2, src); - uint256 dstTokensPost = sinvoke balanceOf(e2, dst); - uint256 otherTokensPost = sinvoke balanceOf(e2, other); - - uint256 cTokenReservesPost = sinvoke totalReserves(e2); - - uint256 allowancePost = sinvoke allowance(e2, src, e1b.msg.sender); - - // Measure - bool staticBalance = - (exchangeRatePost == exchangeRatePre) && - (cTokenCashPost == cTokenCashPre) && - (cTokenBorrowsPost == cTokenBorrowsPre) && - (cTokenSupplyPost == cTokenSupplyPre) && - (cTokenReservesPost == cTokenReservesPre) && - (srcCashPost == srcCashPre) && - (srcBorrowsPost == srcBorrowsPre) && - (srcTokensPost == srcTokensPre) && - (dstCashPost == dstCashPre) && - (dstBorrowsPost == dstBorrowsPre) && - (dstTokensPost == dstTokensPre) && - (otherCashPost == otherCashPre) && - (otherBorrowsPost == otherBorrowsPre) && - (otherTokensPost == otherTokensPre); - - bool dynamicBalance = - (amount != 0) && - (exchangeRatePost == exchangeRatePre) && - (cTokenCashPost == cTokenCashPre) && - (cTokenBorrowsPost == cTokenBorrowsPre) && - (cTokenSupplyPost == cTokenSupplyPre) && - (cTokenReservesPost == cTokenReservesPre) && - (srcCashPost == srcCashPre) && - (srcBorrowsPost == srcBorrowsPre) && - (srcTokensPost == srcTokensPre - amount) && - (dstCashPost == dstCashPre) && - (dstBorrowsPost == dstBorrowsPre) && - (dstTokensPost == dstTokensPre + amount) && - (otherCashPost == otherCashPre) && - (otherBorrowsPost == otherBorrowsPre) && - (otherTokensPost == otherTokensPre); - - // XXX better way to write uint max? - uint256 UINT_MAX = 115792089237316195423570985008687907853269984665640564039457584007913129639935; - - assert (!transferReverted => - ((!success || amount == 0 || src == dst) <=> staticBalance)), "Mismatch in static case"; - assert (!transferReverted => - ((success && amount != 0) <=> dynamicBalance)), "Mismatch in dynamic case"; - assert (!transferReverted && success => - (amount > allowancePre => e1b.msg.sender == src)), "Only owner can transfer > allowance"; - assert (!transferReverted && success => - (doApprove => allowancePre >= approvedAmount)), "Approval must increase the allowance"; - assert (!transferReverted && success => - (allowancePre == UINT_MAX || e1b.msg.sender == src || amount == 0) <=> allowancePost == allowancePre), "Mismatch not touching allowance"; - assert (!transferReverted && success && e1b.msg.sender != src && amount != 0 => - (allowancePre != UINT_MAX <=> allowancePost == allowancePre - amount)), "Spender transfer uses allowance"; -} \ No newline at end of file diff --git a/spec/certora/CErc20/exchangeRate.cvl b/spec/certora/CErc20/exchangeRate.cvl deleted file mode 100644 index 4860d8d5e..000000000 --- a/spec/certora/CErc20/exchangeRate.cvl +++ /dev/null @@ -1,53 +0,0 @@ - -exchangeRateDecreases(uint result, address minter, uint256 mintAmount, uint256 mintTokens) { - // Pre/action/post environments - env e0; - env e1; - env e2; - - require e1.block.number >= e0.block.number; - require e2.block.number >= e1.block.number; - - // Any other account - address other; - require other != minter && other != currentContract; - require minter != currentContract; - - uint256 exchangeRatePre = sinvoke exchangeRateCurrent(e0); - - uint256 cTokenCashPre = sinvoke getCash(e0); - uint256 cTokenBorrowsPre = sinvoke totalBorrows(e0); - uint256 cTokenTokensPre = sinvoke totalSupply(e0); - uint256 cTokenReservesPre = sinvoke totalReserves(e0); - uint256 cTokenSupplyPre = cTokenCashPre + cTokenBorrowsPre - cTokenReservesPre; - - // Simplifying assumptions to analyze the vulnerability - require cTokenBorrowsPre == 0; // XXX not necessary, simplifies analysis - require cTokenSupplyPre >= 0; // XXX not necessary, should underflow - require cTokenTokensPre > 0; // XXX not necessary - require exchangeRatePre * cTokenTokensPre == cTokenSupplyPre * 1000000000000000000; // XXX - - // XXX why does this have to be after require? - uint256 implicitExchangeRatePre = cTokenSupplyPre * 1000000000000000000 / cTokenTokensPre; - - require result == invoke mintFreshPub(e1, minter, mintAmount); - bool mintFreshReverted = lastReverted; - - uint256 exchangeRatePost = sinvoke exchangeRateCurrent(e2); - - uint256 cTokenCashPost = sinvoke getCash(e2); - uint256 cTokenBorrowsPost = sinvoke totalBorrows(e2); - uint256 cTokenTokensPost = sinvoke totalSupply(e2); - uint256 cTokenReservesPost = sinvoke totalReserves(e2); - uint256 cTokenSupplyPost = cTokenCashPost + cTokenBorrowsPost - cTokenReservesPost; - - require mintTokens == cTokenTokensPost - cTokenTokensPre; - require exchangeRatePre * mintTokens == mintAmount * 1000000000000000000; // XXX why would this need to be assumed? should be proven - - uint256 implicitExchangeRatePost = cTokenSupplyPost * 1000000000000000000 / cTokenTokensPost; - - assert (!mintFreshReverted => - ((result != 0) => (exchangeRatePost == exchangeRatePre))), "Mismatch in failure case"; - assert (!mintFreshReverted => (exchangeRatePost >= exchangeRatePre)), "Exchange rate decreased"; - assert (!mintFreshReverted => (implicitExchangeRatePost >= implicitExchangeRatePre)), "Implicit exchange rate decreased"; -} diff --git a/spec/certora/CErc20/frame.cvl b/spec/certora/CErc20/frame.cvl deleted file mode 100644 index 10605b923..000000000 --- a/spec/certora/CErc20/frame.cvl +++ /dev/null @@ -1,257 +0,0 @@ - -frame_balanceOf(address a, method f) -description "$f may change value of balanceOf($a)" -{ - env e0; - env e1; - env e2; - require e1.block.number >= e0.block.number; - require e2.block.number >= e1.block.number; - - uint256 old = sinvoke balanceOf(e0, a); - calldataarg arg; - invoke f(e1, arg); - uint256 new = sinvoke balanceOf(e2, a); - - assert old == new; -} - -frame_borrowBalanceStored(address a, method f) -description "$f may change value of borrowBalanceStored($a)" -{ - env e0; - env e1; - env e2; - require e1.block.number >= e0.block.number; - require e2.block.number >= e1.block.number; - - uint256 old = sinvoke borrowBalanceStored(e0, a); - calldataarg arg; - invoke f(e1, arg); - uint256 new = sinvoke borrowBalanceStored(e2, a); - - assert old == new; -} - -frame_borrowIndex(method f) -description "$f may change value of borrowIndex()" -{ - env e0; - env e1; - env e2; - require e1.block.number >= e0.block.number; - require e2.block.number >= e1.block.number; - - uint256 old = sinvoke borrowIndex(e0); - calldataarg arg; - invoke f(e1, arg); - uint256 new = sinvoke borrowIndex(e2); - - assert old == new; -} - -frame_borrowRatePerBlock(method f) -description "$f may change value of borrowRatePerBlock()" -{ - env e0; - env e1; - env e2; - require e1.block.number >= e0.block.number; - require e2.block.number >= e1.block.number; - - uint256 old = sinvoke borrowRatePerBlock(e0); - calldataarg arg; - invoke f(e1, arg); - uint256 new = sinvoke borrowRatePerBlock(e2); - - assert old == new; -} - -frame_comptroller(method f) -description "$f may change value of comptroller()" -{ - env e0; - env e1; - env e2; - require e1.block.number >= e0.block.number; - require e2.block.number >= e1.block.number; - - address old = sinvoke comptroller(e0); - calldataarg arg; - invoke f(e1, arg); - address new = sinvoke comptroller(e2); - - assert old == new; -} - -frame_exchangeRateStored(address a, method f) -description "$f may change value of exchangeRateStored()" -{ - env e0; - env e1; - env e2; - require e1.block.number >= e0.block.number; - require e2.block.number >= e1.block.number; - - uint256 old = sinvoke exchangeRateStored(e0); - calldataarg arg; - invoke f(e1, arg); - uint256 new = sinvoke exchangeRateStored(e2); - - assert old == new; -} - -frame_getAccountSnapshot(address a, method f) -description "$f may change value of getAccountSnapshot($a)" -{ - env e0; - env e1; - env e2; - require e1.block.number >= e0.block.number; - require e2.block.number >= e1.block.number; - - uint256 old1; uint256 old2; uint256 old3; uint256 old4; - old1,old2,old3,old4 = sinvoke getAccountSnapshot(e0, a); - calldataarg arg; - invoke f(e1, arg); - uint256 new1; uint256 new2; uint256 new3; uint256 new4; - new1,new2,new3,new4 = sinvoke getAccountSnapshot(e2, a); - - assert old1 == new1 && old2 == new2 && old3 == new3 && old4 == new4; -} - -frame_getCash(method f) -description "$f may change value of getCash()" -{ - env e0; - env e1; - env e2; - require e1.block.number >= e0.block.number; - require e2.block.number >= e1.block.number; - - uint256 old = sinvoke getCash(e0); - calldataarg arg; - invoke f(e1, arg); - uint256 new = sinvoke getCash(e2); - - assert old == new; -} - -frame_interestRateModel(method f) -description "$f may change value of interestRateModel()" -{ - env e0; - env e1; - env e2; - require e1.block.number >= e0.block.number; - require e2.block.number >= e1.block.number; - - address old = sinvoke interestRateModel(e0); - calldataarg arg; - invoke f(e1, arg); - address new = sinvoke interestRateModel(e2); - - assert old == new; -} - -frame_pendingAdmin(method f) -description "$f may change value of pendingAdmin()" -{ - env e0; - env e1; - env e2; - require e1.block.number >= e0.block.number; - require e2.block.number >= e1.block.number; - - address old = sinvoke pendingAdmin(e0); - calldataarg arg; - invoke f(e1, arg); - address new = sinvoke pendingAdmin(e2); - - assert old == new; -} - -frame_reserveFactorMantissa(method f) -description "$f may change value of reserveFactorMantissa()" -{ - env e0; - env e1; - env e2; - require e1.block.number >= e0.block.number; - require e2.block.number >= e1.block.number; - - uint256 old = sinvoke reserveFactorMantissa(e0); - calldataarg arg; - invoke f(e1, arg); - uint256 new = sinvoke reserveFactorMantissa(e2); - - assert old == new; -} - -frame_supplyRatePerBlock(method f) -description "$f may change value of supplyRatePerBlock()" -{ - env e0; - env e1; - env e2; - require e1.block.number >= e0.block.number; - require e2.block.number >= e1.block.number; - - uint256 old = sinvoke supplyRatePerBlock(e0); - calldataarg arg; - invoke f(e1, arg); - uint256 new = sinvoke supplyRatePerBlock(e2); - - assert old == new; -} - -frame_totalBorrows(method f) -description "$f may change value of totalBorrows()" -{ - env e0; - env e1; - env e2; - require e1.block.number >= e0.block.number; - require e2.block.number >= e1.block.number; - - uint256 old = sinvoke totalBorrows(e0); - calldataarg arg; - invoke f(e1, arg); - uint256 new = sinvoke totalBorrows(e2); - - assert old == new; -} - -frame_totalReserves(address a, method f) -description "$f may change value of totalReserves()" -{ - env e0; - env e1; - env e2; - require e1.block.number >= e0.block.number; - require e2.block.number >= e1.block.number; - - uint256 old = sinvoke totalReserves(e0); - calldataarg arg; - invoke f(e1, arg); - uint256 new = sinvoke totalReserves(e2); - - assert old == new; -} - -frame_totalSupply(method f) -description "$f may change value of totalSupply()" -{ - env e0; - env e1; - env e2; - require e1.block.number >= e0.block.number; - require e2.block.number >= e1.block.number; - - uint256 old = sinvoke totalSupply(e0); - calldataarg arg; - invoke f(e1, arg); - uint256 new = sinvoke totalSupply(e2); - - assert old == new; -} \ No newline at end of file diff --git a/spec/certora/CErc20/liquidateFresh.cvl b/spec/certora/CErc20/liquidateFresh.cvl deleted file mode 100644 index 6565b67b6..000000000 --- a/spec/certora/CErc20/liquidateFresh.cvl +++ /dev/null @@ -1,315 +0,0 @@ - -liquidateBorrowFresh(uint result, address liquidator, address borrower, uint256 repayAmount) -description "Break liquidate" { - // Pre/action/post environments - env e0; - env e1; - env e2; - - require e1.block.number >= e0.block.number; - require e2.block.number >= e1.block.number; - - // Any other account - address other; - require other != liquidator && other != borrower && other != currentContract; - - // We assume this cannot happen - // OQ: should we enforce in the code such that it need not be assumed? - require borrower != currentContract; - require liquidator != currentContract; - require borrower != sinvoke otherToken(e0); - require liquidator != sinvoke otherToken(e0); - - // We check if the borrowed token and the collateral token have the same underlying - // which affects whether or not collateral cash should have changed or not - bool borrowCashIsCollateralCash = sinvoke underlying(e0) == sinvoke underlyingInOther(e0); - - /* - - no effect on exchange rate - - self-liquidate has no effect - |---------------------+--------+------------+----------+-------| - | | CToken | Liquidator | Borrower | Other | - |---------------------+--------+------------+----------+-------| - | cash | +A | -A | 0 | 0 | - | borrows | -A | 0 | -A | 0 | - | tokens | 0 | 0 | 0 | 0 | - | reserves | 0 | | | | - | collateral cash | 0 | -A/0 | 0 | 0 | - | collateral borrows | 0 | 0 | 0 | 0 | - | collateral tokens | 0 | +T | -T | 0 | - | collateral reserves | 0 | | | | - |---------------------+--------+------------+----------+-------| - */ - - /* Pre */ - - // borrowed - uint256 exchangeRatePre = sinvoke exchangeRateStored(e0); - - uint256 cTokenCashPre = sinvoke getCash(e0); - uint256 liquidatorCashPre = sinvoke getCashOf(e0, liquidator); - uint256 borrowerCashPre = sinvoke getCashOf(e0, borrower); - uint256 otherCashPre = sinvoke getCashOf(e0, other); - - uint256 cTokenBorrowsPre = sinvoke totalBorrows(e0); - uint256 liquidatorBorrowsPre = sinvoke borrowBalanceStored(e0, liquidator); - uint256 borrowerBorrowsPre = sinvoke borrowBalanceStored(e0, borrower); - uint256 otherBorrowsPre = sinvoke borrowBalanceStored(e0, other); - - uint256 cTokenTokensPre = sinvoke totalSupply(e0); - uint256 liquidatorTokensPre = sinvoke balanceOf(e0, liquidator); - uint256 borrowerTokensPre = sinvoke balanceOf(e0, borrower); - uint256 otherTokensPre = sinvoke balanceOf(e0, other); - - uint256 cTokenReservesPre = sinvoke totalReserves(e0); - - // collateral - uint256 collateralExchangeRatePre = sinvoke exchangeRateStoredInOther(e0); - - uint256 collateralCashPre = sinvoke getCashInOther(e0); - uint256 liquidatorCollateralCashPre = sinvoke getCashOfInOther(e0, liquidator); - uint256 borrowerCollateralCashPre = sinvoke getCashOfInOther(e0, borrower); - uint256 otherCollateralCashPre = sinvoke getCashOfInOther(e0, other); - - uint256 collateralBorrowsPre = sinvoke totalBorrowsInOther(e0); - uint256 liquidatorCollateralBorrowsPre = sinvoke borrowBalanceStoredInOther(e0, liquidator); - uint256 borrowerCollateralBorrowsPre = sinvoke borrowBalanceStoredInOther(e0, borrower); - uint256 otherCollateralBorrowsPre = sinvoke borrowBalanceStoredInOther(e0, other); - - uint256 collateralTokensPre = sinvoke totalSupplyInOther(e0); - uint256 liquidatorCollateralTokensPre = sinvoke balanceOfInOther(e0, liquidator); - uint256 borrowerCollateralTokensPre = sinvoke balanceOfInOther(e0, borrower); - uint256 otherCollateralTokensPre = sinvoke balanceOfInOther(e0, other); - - uint256 collateralReservesPre = sinvoke totalReservesInOther(e0); - - // Just Do It - // Note: cTokenCollateral is linked via Compound.spclnk in order to support checking its balances - // not perfect since it only proves the balance sheet is safe for a particular token configuration - require result == invoke liquidateBorrowFreshPub(e1, liquidator, borrower, repayAmount); - bool liquidateBorrowFreshReverted = lastReverted; - - /* Post */ - - // borrowed - uint256 exchangeRatePost = sinvoke exchangeRateStored(e2); - - uint256 cTokenCashPost = sinvoke getCash(e2); - uint256 liquidatorCashPost = sinvoke getCashOf(e2, liquidator); - uint256 borrowerCashPost = sinvoke getCashOf(e2, borrower); - uint256 otherCashPost = sinvoke getCashOf(e2, other); - - uint256 cTokenBorrowsPost = sinvoke totalBorrows(e2); - uint256 liquidatorBorrowsPost = sinvoke borrowBalanceStored(e2, liquidator); - uint256 borrowerBorrowsPost = sinvoke borrowBalanceStored(e2, borrower); - uint256 otherBorrowsPost = sinvoke borrowBalanceStored(e2, other); - - uint256 cTokenTokensPost = sinvoke totalSupply(e2); - uint256 liquidatorTokensPost = sinvoke balanceOf(e2, liquidator); - uint256 borrowerTokensPost = sinvoke balanceOf(e2, borrower); - uint256 otherTokensPost = sinvoke balanceOf(e2, other); - - uint256 cTokenReservesPost = sinvoke totalReserves(e2); - - // collateral - uint256 collateralExchangeRatePost = sinvoke exchangeRateStoredInOther(e2); - - uint256 collateralCashPost = sinvoke getCashInOther(e2); - uint256 liquidatorCollateralCashPost = sinvoke getCashOfInOther(e2, liquidator); - uint256 borrowerCollateralCashPost = sinvoke getCashOfInOther(e2, borrower); - uint256 otherCollateralCashPost = sinvoke getCashOfInOther(e2, other); - - uint256 collateralBorrowsPost = sinvoke totalBorrowsInOther(e2); - uint256 liquidatorCollateralBorrowsPost = sinvoke borrowBalanceStoredInOther(e2, liquidator); - uint256 borrowerCollateralBorrowsPost = sinvoke borrowBalanceStoredInOther(e2, borrower); - uint256 otherCollateralBorrowsPost = sinvoke borrowBalanceStoredInOther(e2, other); - - uint256 collateralTokensPost = sinvoke totalSupplyInOther(e2); - uint256 liquidatorCollateralTokensPost = sinvoke balanceOfInOther(e2, liquidator); - uint256 borrowerCollateralTokensPost = sinvoke balanceOfInOther(e2, borrower); - uint256 otherCollateralTokensPost = sinvoke balanceOfInOther(e2, other); - - uint256 collateralReservesPost = sinvoke totalReservesInOther(e2); - - // Measure - bool staticBalance = - (exchangeRatePost == exchangeRatePre) && - (cTokenCashPost == cTokenCashPre) && - (cTokenBorrowsPost == cTokenBorrowsPre) && - (cTokenTokensPost == cTokenTokensPre) && - (cTokenReservesPost == cTokenReservesPre) && - (liquidatorCashPost == liquidatorCashPre) && - (liquidatorBorrowsPost == liquidatorBorrowsPre) && - (liquidatorTokensPost == liquidatorTokensPre) && - (borrowerCashPost == borrowerCashPre) && - (borrowerBorrowsPost == borrowerBorrowsPre) && - (borrowerTokensPost == borrowerTokensPre) && - (otherCashPost == otherCashPre) && - (otherBorrowsPost == otherBorrowsPre) && - (otherTokensPost == otherTokensPre) && - - (collateralExchangeRatePost == collateralExchangeRatePre) && - (collateralCashPost == collateralCashPre) && - (collateralBorrowsPost == collateralBorrowsPre) && - (collateralTokensPost == collateralTokensPre) && - (collateralReservesPost == collateralReservesPre) && - (liquidatorCollateralCashPost == liquidatorCollateralCashPre) && - (liquidatorCollateralBorrowsPost == liquidatorCollateralBorrowsPre) && - (liquidatorCollateralTokensPost == liquidatorCollateralTokensPre) && - (borrowerCollateralCashPost == borrowerCollateralCashPre) && - (borrowerCollateralBorrowsPost == borrowerCollateralBorrowsPre) && - (borrowerCollateralTokensPost == borrowerCollateralTokensPre) && - (otherCollateralCashPost == otherCollateralCashPre) && - (otherCollateralBorrowsPost == otherCollateralBorrowsPre) && - (otherCollateralTokensPost == otherCollateralTokensPre); - - bool dynamicBalance = - (repayAmount != 0) && - (exchangeRatePost == exchangeRatePre) && - (cTokenCashPost == cTokenCashPre + repayAmount) && - (cTokenBorrowsPost == cTokenBorrowsPre - repayAmount) && - (cTokenTokensPost == cTokenTokensPre) && - (cTokenReservesPost == cTokenReservesPre) && - (liquidatorCashPost == liquidatorCashPre - repayAmount) && - (liquidatorBorrowsPost == liquidatorBorrowsPre) && - (liquidatorTokensPost == liquidatorTokensPre) && - (borrowerCashPost == borrowerCashPre) && - (borrowerBorrowsPost == borrowerBorrowsPre - repayAmount) && - (borrowerTokensPost == borrowerTokensPre) && - (otherCashPost == otherCashPre) && - (otherBorrowsPost == otherBorrowsPre) && - (otherTokensPost == otherTokensPre) && - (borrowerCollateralCashPost == borrowerCollateralCashPre) && - - (collateralExchangeRatePost == collateralExchangeRatePre) && - (collateralCashPost == collateralCashPre) && - (collateralBorrowsPost == collateralBorrowsPre) && - (collateralTokensPost == collateralTokensPre) && - (collateralReservesPost == collateralReservesPre) && - (liquidatorCollateralCashPost == liquidatorCollateralCashPre || (borrowCashIsCollateralCash && liquidatorCollateralCashPost == liquidatorCollateralCashPre - repayAmount)) && - (liquidatorCollateralBorrowsPost == liquidatorCollateralBorrowsPre) && - (liquidatorCollateralTokensPost - liquidatorCollateralTokensPre == borrowerCollateralTokensPre - borrowerCollateralTokensPost) && - (borrowerCollateralCashPost == borrowerCollateralCashPre) && - (borrowerCollateralBorrowsPost == borrowerCollateralBorrowsPre) && - (otherCollateralCashPost == otherCollateralCashPre) && - (otherCollateralBorrowsPost == otherCollateralBorrowsPre) && - (otherCollateralTokensPost == otherCollateralTokensPre); - - - assert (!liquidateBorrowFreshReverted => - ((result != 0 || repayAmount == 0 || liquidator == borrower) <=> staticBalance)), "Mismatch in static case"; - assert (!liquidateBorrowFreshReverted => - ((result == 0 && repayAmount != 0 && liquidator != currentContract) <=> dynamicBalance)), "Mismatch in dynamic case"; -} - -seize(uint result, address liquidator, address borrower, uint256 seizeTokens) -description "Break seize" { - // Pre/action/post environments - env e0; - env e1; - env e2; - - require e1.block.number >= e0.block.number; - require e2.block.number >= e1.block.number; - - // Any other account - address other; - require other != liquidator && other != borrower && other != currentContract; - - /* - - no effect on exchange rate - |----------+--------+------------+----------+-------| - | | CToken | Liquidator | Borrower | Other | - |----------+--------+------------+----------+-------| - | cash | 0 | 0 | 0 | 0 | - | borrows | 0 | 0 | 0 | 0 | - | tokens | 0 | +T | -T | 0 | - | reserves | 0 | | | | - |----------+--------+------------+----------+-------| - */ - - /* Pre */ - - uint256 exchangeRatePre = sinvoke exchangeRateStored(e0); - - uint256 cTokenCashPre = sinvoke getCash(e0); - uint256 liquidatorCashPre = sinvoke getCashOf(e0, liquidator); - uint256 borrowerCashPre = sinvoke getCashOf(e0, borrower); - uint256 otherCashPre = sinvoke getCashOf(e0, other); - - uint256 cTokenBorrowsPre = sinvoke totalBorrows(e0); - uint256 liquidatorBorrowsPre = sinvoke borrowBalanceStored(e0, liquidator); - uint256 borrowerBorrowsPre = sinvoke borrowBalanceStored(e0, borrower); - uint256 otherBorrowsPre = sinvoke borrowBalanceStored(e0, other); - - uint256 cTokenTokensPre = sinvoke totalSupply(e0); - uint256 liquidatorTokensPre = sinvoke balanceOf(e0, liquidator); - uint256 borrowerTokensPre = sinvoke balanceOf(e0, borrower); - uint256 otherTokensPre = sinvoke balanceOf(e0, other); - - uint256 cTokenReservesPre = sinvoke totalReserves(e0); - - // Just Do It - require result == invoke seize(e1, liquidator, borrower, seizeTokens); - bool seizeReverted = lastReverted; - - /* Post */ - - uint256 exchangeRatePost = sinvoke exchangeRateStored(e2); - - uint256 cTokenCashPost = sinvoke getCash(e2); - uint256 liquidatorCashPost = sinvoke getCashOf(e2, liquidator); - uint256 borrowerCashPost = sinvoke getCashOf(e2, borrower); - uint256 otherCashPost = sinvoke getCashOf(e2, other); - - uint256 cTokenBorrowsPost = sinvoke totalBorrows(e2); - uint256 liquidatorBorrowsPost = sinvoke borrowBalanceStored(e2, liquidator); - uint256 borrowerBorrowsPost = sinvoke borrowBalanceStored(e2, borrower); - uint256 otherBorrowsPost = sinvoke borrowBalanceStored(e2, other); - - uint256 cTokenTokensPost = sinvoke totalSupply(e2); - uint256 liquidatorTokensPost = sinvoke balanceOf(e2, liquidator); - uint256 borrowerTokensPost = sinvoke balanceOf(e2, borrower); - uint256 otherTokensPost = sinvoke balanceOf(e2, other); - - uint256 cTokenReservesPost = sinvoke totalReserves(e2); - - // Measure - bool staticBalance = - (exchangeRatePost == exchangeRatePre) && - (cTokenCashPost == cTokenCashPre) && - (cTokenBorrowsPost == cTokenBorrowsPre) && - (cTokenTokensPost == cTokenTokensPre) && - (cTokenReservesPost == cTokenReservesPre) && - (liquidatorCashPost == liquidatorCashPre) && - (liquidatorBorrowsPost == liquidatorBorrowsPre) && - (liquidatorTokensPost == liquidatorTokensPre) && - (borrowerCashPost == borrowerCashPre) && - (borrowerBorrowsPost == borrowerBorrowsPre) && - (borrowerTokensPost == borrowerTokensPre) && - (otherCashPost == otherCashPre) && - (otherBorrowsPost == otherBorrowsPre) && - (otherTokensPost == otherTokensPre); - - bool dynamicBalance = - (seizeTokens != 0) && - (exchangeRatePost == exchangeRatePre) && - (cTokenCashPost == cTokenCashPre) && - (cTokenBorrowsPost == cTokenBorrowsPre) && - (cTokenTokensPost == cTokenTokensPre) && - (cTokenReservesPost == cTokenReservesPre) && - (liquidatorCashPost == liquidatorCashPre) && - (liquidatorBorrowsPost == liquidatorBorrowsPre) && - (liquidatorTokensPost == liquidatorTokensPre + seizeTokens) && - (borrowerCashPost == borrowerCashPre) && - (borrowerBorrowsPost == borrowerBorrowsPre) && - (borrowerTokensPost == borrowerTokensPre - seizeTokens) && - (otherCashPost == otherCashPre) && - (otherBorrowsPost == otherBorrowsPre) && - (otherTokensPost == otherTokensPre); - - assert (!seizeReverted => - ((result != 0 || seizeTokens == 0 || liquidator == borrower) <=> staticBalance)), "Mismatch in static case"; - assert (!seizeReverted => - ((result == 0 && seizeTokens != 0) <=> dynamicBalance)), "Mismatch in dynamic case"; -} \ No newline at end of file diff --git a/spec/certora/CErc20/mintAndRedeemFresh.cvl b/spec/certora/CErc20/mintAndRedeemFresh.cvl deleted file mode 100644 index 0cb927711..000000000 --- a/spec/certora/CErc20/mintAndRedeemFresh.cvl +++ /dev/null @@ -1,244 +0,0 @@ - -mintFresh(uint result, address minter, uint256 mintAmount, uint256 mintTokens) -description "Break mint with result=$result minter=$minter mintAmount=$mintAmount" { - // Pre/action/post environments - env e0; - env e1; - env e2; - - require e1.block.number >= e0.block.number; - require e2.block.number >= e1.block.number; - - // Any other account - address other; - require other != minter && other != currentContract; - require minter != currentContract; - - /* - - exchange rate should not change - - errors should have no effect - - no *other* storage should change - XXX can we specify this? - - |----------+--------+--------+-------| - | | CToken | Minter | Other | - |----------+--------+--------+-------| - | cash | +A | -A | 0 | - | borrows | 0 | 0 | 0 | - | tokens | +T | +T | 0 | - | reserves | 0 | | | - |----------+--------+--------+-------| - */ - - /* Pre */ - - uint256 exchangeRatePre = sinvoke exchangeRateStored(e0); - - uint256 cTokenCashPre = sinvoke getCash(e0); - uint256 minterCashPre = sinvoke getCashOf(e0, minter); - uint256 otherCashPre = sinvoke getCashOf(e0, other); - - uint256 cTokenBorrowsPre = sinvoke totalBorrows(e0); - uint256 minterBorrowsPre = sinvoke borrowBalanceStored(e0, minter); - uint256 otherBorrowsPre = sinvoke borrowBalanceStored(e0, other); - - uint256 cTokenTokensPre = sinvoke totalSupply(e0); - uint256 minterTokensPre = sinvoke balanceOf(e0, minter); - uint256 otherTokensPre = sinvoke balanceOf(e0, other); - - uint256 cTokenReservesPre = sinvoke totalReserves(e0); - - uint256 cTokenSupplyPre = cTokenCashPre + cTokenBorrowsPre - cTokenReservesPre; // XXX - - // A few constraints - /* require cTokenBorrowsPre == 0; // XXX */ - /* require cTokenSupplyPre >= 0; // XXX shouldn't be necessary, should underflow */ - /* require cTokenTokensPre > 0; // XXX shouldn't be necessary */ - //require exchangeRatePre == 2000000000000000000; // XXX - /* require exchangeRatePre * cTokenTokensPre == cTokenSupplyPre; // XXX */ - require minterTokensPre + otherTokensPre <= cTokenTokensPre; // XXX shouldn't be necessary, though weird - /* require mintAmount == mintTokens * exchangeRatePre; */ - - // Just do it - require result == invoke mintFreshPub(e1, minter, mintAmount); - bool mintFreshReverted = lastReverted; - - /* Post */ - - uint256 exchangeRatePost = sinvoke exchangeRateStored(e2); - - uint256 cTokenCashPost = sinvoke getCash(e2); - uint256 minterCashPost = sinvoke getCashOf(e2, minter); - uint256 otherCashPost = sinvoke getCashOf(e2, other); - - uint256 cTokenBorrowsPost = sinvoke totalBorrows(e2); - uint256 minterBorrowsPost = sinvoke borrowBalanceStored(e2, minter); - uint256 otherBorrowsPost = sinvoke borrowBalanceStored(e2, other); - - uint256 cTokenTokensPost = sinvoke totalSupply(e2); - uint256 minterTokensPost = sinvoke balanceOf(e2, minter); - uint256 otherTokensPost = sinvoke balanceOf(e2, other); - - uint256 cTokenReservesPost = sinvoke totalReserves(e2); - - // Measure - bool staticBalance = - /* (exchangeRatePost == exchangeRatePre) && */ - (cTokenCashPost == cTokenCashPre) && - (cTokenBorrowsPost == cTokenBorrowsPre) && - (cTokenTokensPost == cTokenTokensPre) && - (cTokenReservesPost == cTokenReservesPre) && - (minterCashPost == minterCashPre) && - (minterBorrowsPost == minterBorrowsPre) && - (minterTokensPost == minterTokensPre) && - (otherCashPost == otherCashPre) && - (otherBorrowsPost == otherBorrowsPre) && - (otherTokensPost == otherTokensPre); - - bool dynamicBalance = - (mintAmount != 0) && - /* (exchangeRatePost >= exchangeRatePre) && // XXX ugh */ - (cTokenCashPost == cTokenCashPre + mintAmount) && - (cTokenBorrowsPost == cTokenBorrowsPre) && - //XXX(cTokenTokensPost == cTokenTokensPre + mintTokens) && - (cTokenReservesPost == cTokenReservesPre) && - (minterCashPost == minterCashPre - mintAmount) && - (minterBorrowsPost == minterBorrowsPre) && - //XXX(minterTokensPost == minterTokensPre + mintTokens) && - (otherCashPost == otherCashPre) && - (otherBorrowsPost == otherBorrowsPre) && - (otherTokensPost == otherTokensPre); - - assert (!mintFreshReverted => - ((result != 0 || mintAmount == 0) <=> staticBalance)), "Mismatch in static case"; - assert (!mintFreshReverted => - ((result == 0 && mintAmount != 0) <=> dynamicBalance)), "Mismatch in dynamic case"; -} - -redeemFresh(uint result, address redeemer, uint256 redeemAmount, uint256 redeemTokens) -description "Break redeem with result=$result redeemer=$redeemer redeemAmount=$redeemAmount" { - // Pre/action/post environments - env e0; - env e1; - env e2; - - require e1.block.number >= e0.block.number; - require e2.block.number >= e1.block.number; - - // Any other account - address other; - require other != redeemer && other != currentContract; - require redeemer != currentContract; - - /* - - exchange rate should not change - - errors should have no effect - - no *other* storage should change - XXX can we specify this? - - |----------+--------+----------+-------| - | | CToken | Redeemer | Other | - |----------+--------+----------+-------| - | cash | -A | +A | 0 | - | borrows | 0 | 0 | 0 | - | tokens | -T | -T | 0 | - | reserves | 0 | | | - |----------+--------+----------+-------| - */ - - /* Pre */ - - uint256 exchangeRatePre = sinvoke exchangeRateStored(e0); - - uint256 cTokenCashPre = sinvoke getCash(e0); - uint256 redeemerCashPre = sinvoke getCashOf(e0, redeemer); - uint256 otherCashPre = sinvoke getCashOf(e0, other); - - uint256 cTokenBorrowsPre = sinvoke totalBorrows(e0); - uint256 redeemerBorrowsPre = sinvoke borrowBalanceStored(e0, redeemer); - uint256 otherBorrowsPre = sinvoke borrowBalanceStored(e0, other); - - uint256 cTokenTokensPre = sinvoke totalSupply(e0); - uint256 redeemerTokensPre = sinvoke balanceOf(e0, redeemer); - uint256 otherTokensPre = sinvoke balanceOf(e0, other); - - uint256 cTokenReservesPre = sinvoke totalReserves(e0); - - uint256 cTokenSupplyPre = cTokenCashPre + cTokenBorrowsPre - cTokenReservesPre; // XXX - - // Just do it - require result == invoke redeemFreshPub(e1, redeemer, 0, redeemAmount); - bool redeemFreshReverted = lastReverted; - - /* Post */ - - uint256 exchangeRatePost = sinvoke exchangeRateStored(e2); - - uint256 cTokenCashPost = sinvoke getCash(e2); - uint256 redeemerCashPost = sinvoke getCashOf(e2, redeemer); - uint256 otherCashPost = sinvoke getCashOf(e2, other); - - uint256 cTokenBorrowsPost = sinvoke totalBorrows(e2); - uint256 redeemerBorrowsPost = sinvoke borrowBalanceStored(e2, redeemer); - uint256 otherBorrowsPost = sinvoke borrowBalanceStored(e2, other); - - uint256 cTokenTokensPost = sinvoke totalSupply(e2); - uint256 redeemerTokensPost = sinvoke balanceOf(e2, redeemer); - uint256 otherTokensPost = sinvoke balanceOf(e2, other); - - uint256 cTokenReservesPost = sinvoke totalReserves(e2); - - // Measure - bool staticBalance = - /* (exchangeRatePost == exchangeRatePre) && */ - (cTokenCashPost == cTokenCashPre) && - (cTokenBorrowsPost == cTokenBorrowsPre) && - (cTokenTokensPost == cTokenTokensPre) && - (cTokenReservesPost == cTokenReservesPre) && - (redeemerCashPost == redeemerCashPre) && - (redeemerBorrowsPost == redeemerBorrowsPre) && - (redeemerTokensPost == redeemerTokensPre) && - (otherCashPost == otherCashPre) && - (otherBorrowsPost == otherBorrowsPre) && - (otherTokensPost == otherTokensPre); - - bool dynamicBalance = - (redeemAmount != 0) && - /* (exchangeRatePost >= exchangeRatePre) && // XXX ugh */ - (cTokenCashPost == cTokenCashPre - redeemAmount) && - (cTokenBorrowsPost == cTokenBorrowsPre) && - //XXX(cTokenTokensPost == cTokenTokensPre - redeemTokens) && - (cTokenReservesPost == cTokenReservesPre) && - (redeemerCashPost == redeemerCashPre + redeemAmount) && - (redeemerBorrowsPost == redeemerBorrowsPre) && - //XXX(redeemerTokensPost == redeemerTokensPre - redeemTokens) && - (otherCashPost == otherCashPre) && - (otherBorrowsPost == otherBorrowsPre) && - (otherTokensPost == otherTokensPre); - - assert (!redeemFreshReverted => - ((result != 0 || redeemAmount == 0) <=> staticBalance)), "Mismatch in static case"; - assert (!redeemFreshReverted => - ((result == 0 && redeemAmount != 0) <=> dynamicBalance)), "Mismatch in dynamic case"; -} - -mintThenRedeem(address account, uint256 amountUnderlying) -description "Mint and redeem are not inverses for account $account, amount $amountUnderlying" -{ - env e0; - - uint origCash = sinvoke getCash(e0); - - // both calls are "fresh" - uint mintResult = invoke mintFreshPub(e0, account, amountUnderlying); - bool mintReverted = lastReverted; - - uint redeemResult = invoke redeemFreshPub(e0, account, 0, amountUnderlying); - bool redeemReverted = lastReverted; - - uint newCash = sinvoke getCash(e0); - - assert (mintResult == 0 && !mintReverted && redeemResult == 0 && !redeemReverted) => newCash == origCash; - - // check that exchange rate is the same, check all the 4 variables that affect the exchange rate are retained. - // check that accounts balances are the same. - // the only thing that changes is the interest index. rounding errors. -} diff --git a/spec/certora/CErc20/rounding.cvl b/spec/certora/CErc20/rounding.cvl deleted file mode 100644 index 180ea78ef..000000000 --- a/spec/certora/CErc20/rounding.cvl +++ /dev/null @@ -1,29 +0,0 @@ - -rule redeemRounding(uint256 redeemTokensIn, uint256 redeemAmountIn) -description "Redeemer can withdraw tokens for free" { - env e0; - env e1; - require e1.block.number >= e0.block.number; - - uint256 exchangeRate = sinvoke exchangeRateStored(e0); - require exchangeRate > 0; - uint256 redeemTokens = redeemAmountIn / exchangeRate / 1000000000000000000; - uint256 redeemAmount = redeemTokensIn * exchangeRate / 1000000000000000000; - bool tokensTruncated = redeemAmountIn > 0 && redeemTokens == 0; - bool amountTruncated = redeemTokensIn > 0 && redeemAmount == 0; - - address redeemer = e0.msg.sender; - - uint256 preTokens = sinvoke balanceOf(e0, redeemer); - uint256 preCash = sinvoke getCash(e0); - - uint256 error = sinvoke redeemFreshPub(e0, redeemer, redeemTokensIn, redeemAmountIn); - bool redeemReverted = lastReverted; - bool redeemSucceeded = !redeemReverted && error == 0; - - uint256 postTokens = sinvoke balanceOf(e1, redeemer); - uint256 postCash = sinvoke getCash(e1); - - assert (redeemSucceeded => (!tokensTruncated <=> (postCash < preCash => postTokens < preTokens))), "Cash decreased but redeemer tokens did not"; - assert (redeemSucceeded => (!amountTruncated <=> (postTokens < preTokens => postCash < preCash))), "Redeemer tokens decreased but cash did not"; -} \ No newline at end of file diff --git a/spec/certora/CErc20Delegator b/spec/certora/CErc20Delegator deleted file mode 120000 index 639e88c87..000000000 --- a/spec/certora/CErc20Delegator +++ /dev/null @@ -1 +0,0 @@ -CErc20 \ No newline at end of file diff --git a/spec/certora/Comp/search.cvl b/spec/certora/Comp/search.cvl deleted file mode 100644 index a3b43bded..000000000 --- a/spec/certora/Comp/search.cvl +++ /dev/null @@ -1,23 +0,0 @@ -binarySearch(address account, uint blockNumber, uint futureBlock) { - env e0; - require e0.msg.value == 0; - require blockNumber < e0.block.number; - require futureBlock >= e0.block.number; - - uint nCheckpoints; - require nCheckpoints <= 4; - require invoke numCheckpoints(e0, account) == nCheckpoints; - - require invoke certoraOrdered(e0, account); - - invoke getPriorVotes(e0, account, futureBlock); - assert lastReverted, "Must revert for future blocks"; - - uint votesLinear = invoke certoraScan(e0, account, blockNumber); - assert !lastReverted, "Linear scan should not revert for any valid block number"; - - uint votesBinary = invoke getPriorVotes(e0, account, blockNumber); - assert !lastReverted, "Query should not revert for any valid block number"; - - assert votesLinear == votesBinary, "Linear search and binary search disagree"; -} diff --git a/spec/certora/Comp/transfer.cvl b/spec/certora/Comp/transfer.cvl deleted file mode 100644 index 0cb38fd95..000000000 --- a/spec/certora/Comp/transfer.cvl +++ /dev/null @@ -1,44 +0,0 @@ -transferDelegates(address src, address dst, uint amount) { - env e0; - env e1; - require e1.block.number > e0.block.number; - - address srcRep = sinvoke delegates(e0, src); - address dstRep = sinvoke delegates(e0, dst); - - uint srcBalancePrior = sinvoke balanceOf(e0, src); - uint dstBalancePrior = sinvoke balanceOf(e0, dst); - - uint srcVotesPrior = sinvoke getCurrentVotes(e0, srcRep); - uint dstVotesPrior = sinvoke getCurrentVotes(e0, dstRep); - - // Bound the number of checkpoints to prevent solver timeout / unwinding assertion violation - uint32 nCheckpoints; - require nCheckpoints == 1; // XXX - require invoke numCheckpoints(e0, srcRep) == nCheckpoints && invoke numCheckpoints(e0, dstRep) == nCheckpoints; - - // Ensure the checkpoints are sane - require sinvoke certoraOrdered(e0, src); - require sinvoke certoraOrdered(e0, dst); - require srcVotesPrior >= srcBalancePrior; - require dstVotesPrior >= dstBalancePrior; - - require amount <= 79228162514264337593543950335; // UInt96 Max - bool didTransfer = invoke transferFrom(e0, src, dst, amount); - bool transferReverted = lastReverted; - assert didTransfer || transferReverted, "Transfer either succeeds or reverts"; - - uint srcBalancePost = sinvoke balanceOf(e1, src); - uint dstBalancePost = sinvoke balanceOf(e1, dst); - assert !transferReverted => ( - (src != dst) => ((dstBalancePost == dstBalancePrior + amount) && (srcBalancePost == srcBalancePrior - amount)) && - (src == dst) => ((dstBalancePost == dstBalancePrior) && (srcBalancePost == srcBalancePrior)) - ), "Transfers right amount"; - - uint srcVotesPost = sinvoke getCurrentVotes(e1, srcRep); - uint dstVotesPost = sinvoke getCurrentVotes(e1, dstRep); - - assert (srcRep == 0 && dstRep != 0 && !transferReverted) => (dstVotesPost == dstVotesPrior + amount), "Votes are created from the abyss"; - assert (srcRep != 0 && dstRep == 0 && !transferReverted) => (srcVotesPost + amount == srcVotesPrior), "Votes are destroyed into the abyss"; - assert (srcRep != 0 && dstRep != 0) => (srcVotesPrior + dstVotesPrior == srcVotesPost + dstVotesPost), "Votes are neither created nor destroyed"; -} \ No newline at end of file diff --git a/spec/certora/Comptroller/comptroller.cvl b/spec/certora/Comptroller/comptroller.cvl deleted file mode 100644 index f1c0befd0..000000000 --- a/spec/certora/Comptroller/comptroller.cvl +++ /dev/null @@ -1,157 +0,0 @@ -_setPendingAdmin(address currentAdmin, address currentPendingAdmin, address newPendingAdmin) -description "Failed to set new pending admin $currentPendingAdmin to $newPendingAdmin (admin=$currentAdmin)" -{ - // Free Variables - env e0; - env e1; - env e2; - - require currentAdmin == sinvoke admin(e0); - require currentPendingAdmin == sinvoke pendingAdmin(e0); - - // Invoke set new pending admin - uint256 result = sinvoke _setPendingAdmin(e1, newPendingAdmin); - - // pendingAdmin changes <=> msg.sender == currentAdmin - assert ( - ( - e1.msg.sender == currentAdmin && - result == 0 && - sinvoke pendingAdmin(e2) == newPendingAdmin - ) - || - ( - e1.msg.sender != currentAdmin && - result != 0 && - sinvoke pendingAdmin(e2) == currentPendingAdmin - ) - ); -} - -_acceptAdmin(address currentAdmin, address currentPendingAdmin, address newAdmin, address newPendingAdmin) -description "Failed to accept pending admin currentAdmin=$currentAdmin, currentPendingAdmin=$currentPendingAdmin, newPendingAdmin=$newPendingAdmin, newAdmin=$newAdmin" -{ - // Free Variables - env e0; - env e1; - env e2; - - require currentAdmin == sinvoke admin(e0); - require currentPendingAdmin == sinvoke pendingAdmin(e0); - - // Invoke accept admin - uint256 result = sinvoke _acceptAdmin(e1); - - require newAdmin == sinvoke admin(e2); - require newPendingAdmin == sinvoke pendingAdmin(e2); - - // admin == pendingAdmin <=> msg.sender == pendingAdmin - assert ( - ( - e1.msg.sender == currentPendingAdmin && - currentPendingAdmin != 0 && - result == 0 && - newAdmin == currentPendingAdmin && - newPendingAdmin == 0 - ) - || - ( - ( - e1.msg.sender != currentPendingAdmin || - currentPendingAdmin == 0 - ) && - result != 0 && - newAdmin == currentAdmin && - newPendingAdmin == currentPendingAdmin - ) - ); -} - -// Invariant: To change admin or currentPendingAdmin, must come from current admin -invariantRequireAdminToChangeAdmin(address caller, address currentAdmin, address currentPendingAdmin, address desiredAdmin, address newAdmin, address newPendingAdmin) - description "Failed to prove that required to be admin to change admin (caller=$caller, currentAdmin=$currentAdmin, currentPendingAdmin=$currentPendingAdmin, desiredAdmin=$desiredAdmin, newAdmin=$newAdmin, newPendingAdmin=$newPendingAdmin)" -{ - // Free Variables - env e0; - env e1; - env e2; - env e3; - - require currentAdmin == sinvoke admin(e0); - require currentPendingAdmin == sinvoke pendingAdmin(e0); - - // Start with a zero admin - require currentPendingAdmin == 0; - - require caller == e1.msg.sender; - - // Invoke set new pending admin - uint256 result0 = sinvoke _setPendingAdmin(e1, desiredAdmin); - uint256 result1 = sinvoke _acceptAdmin(e2); - - require newAdmin == sinvoke admin(e3); - require newPendingAdmin == sinvoke pendingAdmin(e3); - - assert ( - e1.msg.sender == currentAdmin || - ( - newAdmin == currentAdmin && - newPendingAdmin == currentPendingAdmin - ) - ); -} - -_setComptroller(address desiredComptroller) -description "Failed to set comptroller: result=$result (currAdmin=$currAdmin, currComptroller=$currComptroller, desiredComptroller=$desiredComptroller, nextComptroller=$nextComptroller)" { - - // Free Variables - env e0; - env e_set; - env e1; - env e_accept; - env e2; - - address currAdmin = sinvoke admin(e0); - address currComptroller = sinvoke comptrollerImplementation(e0); - - // Step 1: Invoke set new pending comptroller - uint256 result_set = sinvoke _setPendingImplementation(e1,desiredComptroller); - - // Results and checks: - address updated_pending = sinvoke pendingComptrollerImplementation(e1); - assert (result_set == 0 <=> (e1.msg.sender == currAdmin && desiredComptroller == updated_pending)), "Mismatch in success case: result of setting pending implementation ${result_set}. Sent by ${e1.msg.sender}, current admin ${currAdmin}, wanted to set to ${desiredComptroller} with updated pending comptroller implementation is ${updated_pending}."; - assert (result_set == 1 <=> e1.msg.sender != currAdmin), "Mismatch in unauthorized case: result is ${result_set} and sender is ${e1.msg.sender} when current admin is ${currAdmin}."; - - // Step 2: Invoke accept new comptroller - uint256 result_accept = sinvoke _acceptImplementation(e_accept, desiredComptroller); - - // Results and checks: - address nextComptroller = sinvoke comptrollerImplementation(e2); - address finalPendingComptroller = sinvoke pendingComptrollerImplementation(e2); - - // if succeeded setting: nextComptroller == desiredComptroller <=> msg.sender == desiredComptroller - assert result_set == 0 => - (result_accept == 0 <=> - (e_accept.msg.sender == desiredComptroller && - nextComptroller == desiredComptroller && - nextComptroller != 0 && // Cannot set new comptroller to 0 - finalPendingComptroller == 0)), - "If setting pending implementation succeeded, accept will succeed (got ${result_accept}) only if desired comptroller $desiredComptroller sent the request (sent by ${e_accept.msg.sender}, and set next comptroller as ${nextComptroller}"; - assert result_set == 0 => - (result_accept == 1 <=> - ((e_accept.msg.sender != desiredComptroller || desiredComptroller == 0) && // fails if bad sender, or trying to effectively erase desired comptroller - nextComptroller == currComptroller && - finalPendingComptroller == desiredComptroller)), - "If setting pending implementation succeeded, will fail with unauthorized (got ${result_accept}) only if different implementation tried to accept on behalf of ${desiredComptroller} (sent by ${e_accept.msg.sender}) and did not change the next comptroller: ${nextComptroller} from current one ${currComptroller}."; -} - -rule mustEnterMarkets(address cToken, address borrower, uint256 borrowAmount) { - env e0; - - bool inMarketPre = sinvoke checkMembership(e0, borrower, cToken); - bool canBorrow = sinvoke borrowAllowed(e0, cToken, borrower, borrowAmount) == 0; - bool inMarketPost = sinvoke checkMembership(e0, borrower, cToken); - // We used to require you to be in the market to borrow, now trying to borrow will enter - // assert canBorrow => inMarketPre, "Must be in market before being allowed to borrow"; - assert canBorrow => inMarketPost, "Must be in market if allowed to borrow"; - } diff --git a/spec/certora/Governor/alpha.cvl b/spec/certora/Governor/alpha.cvl deleted file mode 100644 index cc87171d5..000000000 --- a/spec/certora/Governor/alpha.cvl +++ /dev/null @@ -1,123 +0,0 @@ -validStatesAndTransitions(env e0, env e1) { - // Possible states - uint PENDING = 0; - uint ACTIVE = 1; - uint CANCELED = 2; - uint DEFEATED = 3; - uint SUCCEEDED = 4; - uint QUEUED = 5; - uint EXPIRED = 6; - uint EXECUTED = 7; - - uint proposalId = sinvoke certoraPropose(e0); - - uint startBlock = invoke certoraProposalStart(e0, proposalId); - uint endBlock = invoke certoraProposalEnd(e0, proposalId); - uint state = invoke certoraProposalState(e0, proposalId); - - // XXX simulate calling any other (sequence of?) functions in between? - // do more specific paths of transitions based on this sequence? - - uint startBlockNext = invoke certoraProposalStart(e1, proposalId); - uint endBlockNext = invoke certoraProposalEnd(e1, proposalId); - uint stateNext = invoke certoraProposalState(e1, proposalId); - - require e1.block.number == e0.block.number + 1; - assert startBlockNext == startBlock, "Start block may not change"; - assert endBlockNext == endBlock, "End block may not change"; - - // Possibilities based on time - - assert (e0.block.number <= startBlock) => ( - state == CANCELED || - state == PENDING - ), "Prior to voting, may only be pending or canceled"; - - assert (e0.block.number > startBlock && e0.block.number <= endBlock) => ( - state == CANCELED || - state == ACTIVE - ), "During voting, may only be active or canceled"; - - assert (e0.block.number > endBlock) => ( - state == CANCELED || - state == DEFEATED || - state == SUCCEEDED || - state == QUEUED || - state == EXPIRED || - state == EXECUTED - ), "After voting, must be in a viable state"; - - // Allowed transitions - - assert (state == PENDING) => ( - (stateNext == CANCELED) || - (stateNext == ACTIVE && e1.block.number > startBlock) || - (stateNext == PENDING) - ), "From pending, must either become canceled, active, or remain pending"; - - assert (state == ACTIVE) => ( - (stateNext == CANCELED) || - (( - stateNext == DEFEATED || - stateNext == SUCCEEDED || - stateNext == QUEUED || - stateNext == EXPIRED || - stateNext == EXECUTED - ) && e1.block.number > endBlock) || - (stateNext == ACTIVE) - ), "From active, must either become canceled, a viable next statem or remain active"; - - assert (state == CANCELED) => (stateNext == CANCELED), "Once canceled, always canceled"; - - assert (state == DEFEATED) => ( - stateNext == CANCELED || - stateNext == DEFEATED - ), "From defeated, must either become canceled, or remain defeated"; - - assert (state == SUCCEEDED) => ( - stateNext == CANCELED || - stateNext == QUEUED || - stateNext == SUCCEEDED - ), "From succeeded, must either become canceled, queued, or remain expired"; - - assert (state == QUEUED) => ( - stateNext == CANCELED || - stateNext == EXPIRED || - stateNext == EXECUTED || - stateNext == QUEUED - ), "From queued, must either become canceled, expired, executed, or remain queued"; - - assert (state == EXPIRED) => ( - stateNext == CANCELED || - stateNext == EXPIRED - ), "From expired, must either become canceled, or remain expired"; - - assert (state == EXECUTED) => (stateNext == EXECUTED), "Once executed, always executed"; -} - -voteOnce(uint proposalId, bool support) { - env e0; - env e1; - require e0.msg.sender == e1.msg.sender; - - invoke castVote(e0, proposalId, support); - bool firstVoteReverted = lastReverted; - - invoke castVote(e1, proposalId, support); - bool secondVoteReverted = lastReverted; - - assert !firstVoteReverted => secondVoteReverted, "Second vote succeeded after first"; -} - -votesSum(uint proposalId, bool support, address voterA, address voterB) { - // XXX I guess we can't really havoc proposalId? - env e0; - env e1; - require e0.msg.sender == voterA; - require e1.msg.sender == voterB; - - sinvoke castVote(e0, proposalId, support); - sinvoke castVote(e1, proposalId, support); - - assert true; // XXX Shh -} \ No newline at end of file diff --git a/spec/certora/Governor/state.cvl b/spec/certora/Governor/state.cvl deleted file mode 100644 index 59417e194..000000000 --- a/spec/certora/Governor/state.cvl +++ /dev/null @@ -1,118 +0,0 @@ -validStatesAndTransitions() { - // Possible states - uint PENDING = 0; - uint ACTIVE = 1; - uint CANCELED = 2; - uint DEFEATED = 3; - uint SUCCEEDED = 4; - uint QUEUED = 5; - uint EXPIRED = 6; - uint EXECUTED = 7; - - env e0; - env e1; - require e1.block.number == e0.block.number + 1; - require e1.block.timestamp > e0.block.timestamp; - require e1.block.timestamp - e0.block.timestamp < sinvoke certoraTimelockGracePeriod(e0); - require sinvoke certoraTimelockDelay(e0) > 0; - - // XXX cannot propose - /* uint proposalId = sinvoke certoraPropose(e0); */ - /* require invoke certoraProposalLength(e0, proposalId) <= 5; */ - uint proposalId; - uint nProposals = sinvoke proposalCount(e0); - require proposalId < nProposals; - - // Ensure the executed flag is not (arbitrarily) set if eta has not been set yet - require sinvoke certoraProposalEta(e0, proposalId) == 0 => !sinvoke certoraProposalExecuted(e0, proposalId); - - uint startBlock = sinvoke certoraProposalStart(e0, proposalId); - uint endBlock = sinvoke certoraProposalEnd(e0, proposalId); - uint stateNow = sinvoke certoraProposalState(e0, proposalId); - require startBlock < endBlock; // i.e. votingPeriod > 0 - - // Do something - method fun1; calldataarg arg1; - invoke fun1(e0, arg1); - - // Do something else - // XXX takes days to run, but catches violations in queue-execute - // but also thinks timelock delay = 0 according to output report - /* method fun2; calldataarg arg2; */ - /* invoke fun2(e0, arg2); */ - - uint startBlockNext = sinvoke certoraProposalStart(e1, proposalId); - uint endBlockNext = sinvoke certoraProposalEnd(e1, proposalId); - uint stateNext = sinvoke certoraProposalState(e1, proposalId); - - assert startBlockNext == startBlock, "Start block may not change"; - assert endBlockNext == endBlock, "End block may not change"; - - // Possibilities based on time - - assert (e0.block.number <= startBlock) => ( - stateNow == CANCELED || - stateNow == PENDING - ), "Prior to voting, may only be pending or canceled"; - - assert (e0.block.number > startBlock && e0.block.number <= endBlock) => ( - stateNow == CANCELED || - stateNow == ACTIVE - ), "During voting, may only be active or canceled"; - - assert (e0.block.number > endBlock) => ( - stateNow == CANCELED || - stateNow == DEFEATED || - stateNow == SUCCEEDED || - stateNow == QUEUED || - stateNow == EXPIRED || - stateNow == EXECUTED - ), "After voting, must be in a viable state"; - - /* // Allowed transitions */ - - assert (stateNow == PENDING) => ( - (stateNext == CANCELED) || - (stateNext == ACTIVE && e1.block.number > startBlock) || - (stateNext == PENDING) - ), "From pending, must either become canceled, active, or remain pending"; - - assert (stateNow == ACTIVE) => ( - (stateNext == CANCELED) || - (( - stateNext == DEFEATED || - stateNext == SUCCEEDED || - stateNext == QUEUED || - stateNext == EXPIRED || - stateNext == EXECUTED - ) && e1.block.number > endBlock) || - (stateNext == ACTIVE) - ), "From active, must either become canceled, a viable next statem or remain active"; - - assert (stateNow == CANCELED) => (stateNext == CANCELED), "Once canceled, always canceled"; - - assert (stateNow == DEFEATED) => ( - stateNext == CANCELED || - stateNext == DEFEATED - ), "From defeated, must either become canceled, or remain defeated"; - - assert (stateNow == SUCCEEDED) => ( - stateNext == CANCELED || - stateNext == QUEUED || - stateNext == SUCCEEDED - ), "From succeeded, must either become canceled, queued, or remain succeeded"; - - assert (stateNow == QUEUED) => ( - stateNext == CANCELED || - stateNext == EXPIRED || - stateNext == EXECUTED || - stateNext == QUEUED - ), "From queued, must either become canceled, expired, executed, or remain queued"; - - assert (stateNow == EXPIRED) => ( - stateNext == CANCELED || - stateNext == EXPIRED - ), "From expired, must either become canceled, or remain expired"; - - assert (stateNow == EXECUTED) => (stateNext == EXECUTED), "Once executed, always executed"; -} diff --git a/spec/certora/Governor/votes.cvl b/spec/certora/Governor/votes.cvl deleted file mode 100644 index 937ccc578..000000000 --- a/spec/certora/Governor/votes.cvl +++ /dev/null @@ -1,43 +0,0 @@ -voteOnce(uint proposalId, bool support) { - env e0; - env e1; - require e0.msg.sender == e1.msg.sender; - - uint nProposals = sinvoke proposalCount(e0); - require proposalId < nProposals; - - invoke castVote(e0, proposalId, support); - bool firstVoteReverted = lastReverted; - - invoke castVote(e1, proposalId, support); - bool secondVoteReverted = lastReverted; - - assert !firstVoteReverted => secondVoteReverted, "Second vote succeeded after first"; -} - -votesSum(uint proposalId, bool support, address voterA, address voterB) { - env e0; - env e1; - require e0.msg.sender == voterA; - require e1.msg.sender == voterB; - - uint nProposals = sinvoke proposalCount(e0); - require proposalId < nProposals; - - uint preVotesFor = sinvoke certoraProposalVotesFor(e0, proposalId); - uint preVotesAgainst = sinvoke certoraProposalVotesAgainst(e0, proposalId); - - sinvoke castVote(e0, proposalId, support); - sinvoke castVote(e1, proposalId, support); - - uint postVotesFor = sinvoke certoraProposalVotesFor(e1, proposalId); - uint postVotesAgainst = sinvoke certoraProposalVotesAgainst(e1, proposalId); - - uint voterAVotes = sinvoke certoraVoterVotes(e1, proposalId, voterA); - uint voterBVotes = sinvoke certoraVoterVotes(e1, proposalId, voterB); - - // XXX violates? - assert postVotesFor >= preVotesFor, "Cannot reduce votes for"; - assert postVotesAgainst >= preVotesAgainst, "Cannot reduce votes against"; - assert postVotesFor - preVotesFor + postVotesAgainst - preVotesAgainst == voterAVotes + voterBVotes, "Delta votes equals voter votes"; -} diff --git a/spec/certora/Math/int.cvl b/spec/certora/Math/int.cvl deleted file mode 100644 index 05c8265d3..000000000 --- a/spec/certora/Math/int.cvl +++ /dev/null @@ -1,24 +0,0 @@ - -basicDiv(uint a, uint b) { - require b > 0; - - uint c = a + 1; - uint d = a / b; - uint e = c / b; - - assert c >= a, "Failed to prove ${c} >= ${a}"; - assert e >= d, "Failed to prove: ${e} >= ${d}"; -} - -atLeastEnough(uint256 chi, uint256 amount) { - uint256 WAD = 1000000000000000000; - uint256 RAY = 1000000000000000000000000000; - uint256 MAX = 115792089237316195423570985008687907853269984665640564039457584007913129639935; - - require chi >= RAY; - require amount <= MAX; - - assert (amount + 1) >= amount, "Failed (${amount} + 1) >= ${amount}"; - assert (amount + 1) / chi >= amount / chi, "Failed: (${amount} + 1) / ${chi} >= ${amount} / ${chi}"; - assert ((((amount + 1) * RAY) / chi) * chi / RAY) >= amount, "Not enough DAI"; -} \ No newline at end of file diff --git a/spec/certora/Maximillion/maximillion.cvl b/spec/certora/Maximillion/maximillion.cvl deleted file mode 100644 index 3160e3927..000000000 --- a/spec/certora/Maximillion/maximillion.cvl +++ /dev/null @@ -1,26 +0,0 @@ -repayBehalf(uint256 repayAmount, address borrower) -description "Break repayBehalf" { - env e0; - env e1; - env e2; - - require e1.block.number == e0.block.number; - require e2.block.number == e1.block.number; - - require e0.msg.value == 0; - uint256 borrowed = sinvoke borrowBalance(e0, borrower); - - require repayAmount == e1.msg.value; - invoke repayBehalf(e1, borrower); - bool repayReverted = lastReverted; - - require e2.msg.value == 0; - uint256 borrows = sinvoke borrowBalance(e2, borrower); - uint256 balance = sinvoke etherBalance(e2, e1.msg.sender); - - assert (!repayReverted => - ((repayAmount >= borrowed) => (balance >= repayAmount - borrowed))), "Mismatch in refund"; - assert (!repayReverted => - ((repayAmount >= borrowed) => (borrows == 0)) && - ((repayAmount < borrowed) => (borrows == borrowed - repayAmount))), "Mismatch in borrows repaid"; -} \ No newline at end of file diff --git a/spec/certora/Timelock/timelock.cvl b/spec/certora/Timelock/timelock.cvl deleted file mode 100644 index 1c5be4fbe..000000000 --- a/spec/certora/Timelock/timelock.cvl +++ /dev/null @@ -1,91 +0,0 @@ - -rule queueTransaction(address target, uint256 value, uint256 eta) { - env e0; - - address admin_ = sinvoke admin(e0); - uint256 delay_ = sinvoke delay(e0); - - bytes32 txHash = invoke queueTransactionStatic(e0, target, value, eta); - bool queueReverted = lastReverted; - bool queued = sinvoke queuedTransactions(e0, txHash); - - assert (!queueReverted => queued), "Did not revert but not queued"; - assert ((eta < (e0.block.timestamp + delay_)) => queueReverted), "ETA too soon but did not revert"; - assert (!queueReverted => (queued <=> ((eta >= e0.block.timestamp + delay_) && admin_ == e0.msg.sender))), "Bad queue"; -} - -rule cancelTransaction(address target, uint256 value, uint256 eta) { - env e0; - env e1; - env e2; - - bytes32 txHash = sinvoke queueTransactionStatic(e0, target, value, eta); - bool queuedPre = sinvoke queuedTransactions(e0, txHash); - assert queuedPre, "Queue did not revert, but not queued"; - - sinvoke cancelTransactionStatic(e1, target, value, eta); - bool queuedPost = sinvoke queuedTransactions(e1, txHash); - assert !queuedPost, "Cancel did not revert, but queued"; - - invoke executeTransactionStatic(e1, target, value, eta); - bool executeReverted = lastReverted; - assert executeReverted, "Transaction was canceled, must not be able to execute"; -} - -rule executeTransaction(address target, uint256 value, uint256 eta) { - env e0; - env e1; - - uint256 deltaT = e1.block.timestamp - e0.block.timestamp; - require deltaT >= 0; // Certora does not infer this from block number - - address admin_ = sinvoke admin(e0); - uint256 delay_ = sinvoke delay(e0); - uint256 grace_ = sinvoke grace(e0); - - bytes32 txHash = sinvoke queueTransactionStatic(e0, target, value, eta); - bool queuedPre = sinvoke queuedTransactions(e0, txHash); - assert queuedPre, "Queue did not revert, but not queued"; - - invoke executeTransactionStatic(e1, target, value, eta); - bool executeReverted = lastReverted; - bool queuedPost = sinvoke queuedTransactions(e1, txHash); - - assert (!executeReverted => !queuedPost), "Did not revert, should no longer be queued"; - assert (!executeReverted => deltaT >= delay_), "Did not revert, must not execute before Timelock minimum delay"; - assert (!executeReverted => - (deltaT >= eta - e0.block.timestamp && - deltaT <= eta - e0.block.timestamp + grace_)), - "Did not revert, should only execute within grace period of eta"; - assert ((e1.msg.sender != admin_) => executeReverted), "Must revert if not admin"; -} - -rule cannotExecuteTransaction(address target, uint256 value, uint256 eta) { - env e0; - env e1; - - bytes32 txHash = sinvoke queueTransactionStatic(e0, target, value, eta); - bool queuedPre = sinvoke queuedTransactions(e0, txHash); - assert queuedPre, "Queue did not revert, but not queued"; - - address target_; - require target_ != target; - - uint256 value_; - require value_ != value; - - uint256 eta_; - require eta_ != eta; - - invoke executeTransactionStatic(e1, target_, value, eta); - assert lastReverted, "Executed tx with different target"; - - invoke executeTransactionStatic(e1, target, value_, eta); - assert lastReverted, "Executed tx with different value"; - - invoke executeTransactionStatic(e1, target, value, eta_); - assert lastReverted, "Executed tx with different eta"; - - bool queuedPost = sinvoke queuedTransactions(e1, txHash); - assert queuedPost, "Dequeued the transaction, but not canceled or executed"; -} \ No newline at end of file diff --git a/spec/certora/cDAI/mcd.cvl b/spec/certora/cDAI/mcd.cvl deleted file mode 100644 index 839a81cf6..000000000 --- a/spec/certora/cDAI/mcd.cvl +++ /dev/null @@ -1,14 +0,0 @@ - -rule alwaysHasDai(uint256 amount) { - env e0; - - require amount == sinvoke getCashOf(e0, e0.msg.sender); - uint256 mintError = sinvoke mint(e0, amount); - uint256 redeemError = invoke redeemUnderlying(e0, amount); - bool redeemReverted = lastReverted; - uint256 redeemedAmount = sinvoke getCashOf(e0, e0.msg.sender); - - // XXX what if it reverts? cannot fix until specs can run again - assert !redeemReverted, "Redeem reverted"; - assert !redeemReverted => redeemedAmount == amount, "Redeemed amount other than specified"; -} \ No newline at end of file diff --git a/spec/certora/contracts/CDaiDelegateCertora.sol b/spec/certora/contracts/CDaiDelegateCertora.sol deleted file mode 100644 index 637805fdf..000000000 --- a/spec/certora/contracts/CDaiDelegateCertora.sol +++ /dev/null @@ -1,9 +0,0 @@ -pragma solidity ^0.8.10; - -import "../../../contracts/CDaiDelegate.sol"; - -contract CDaiDelegateCertora is CDaiDelegate { - function getCashOf(address account) public view returns (uint256) { - return EIP20Interface(underlying).balanceOf(account); - } -} diff --git a/spec/certora/contracts/CErc20DelegateCertora.sol b/spec/certora/contracts/CErc20DelegateCertora.sol deleted file mode 100644 index 11ac936e9..000000000 --- a/spec/certora/contracts/CErc20DelegateCertora.sol +++ /dev/null @@ -1,41 +0,0 @@ -pragma solidity ^0.8.10; - -import "../../../contracts/VBep20Delegate.sol"; -import "../../../contracts/EIP20Interface.sol"; - -import "./VTokenCollateral.sol"; - -contract VBep20DelegateCertora is VBep20Delegate { - VTokenCollateral public otherToken; - - function mintFreshPub(address minter, uint256 mintAmount) public returns (uint256) { - (uint256 error, ) = mintFresh(minter, mintAmount); - return error; - } - - function redeemFreshPub( - address payable redeemer, - uint256 redeemTokens, - uint256 redeemUnderlying - ) public returns (uint256) { - return redeemFresh(redeemer, redeemTokens, redeemUnderlying); - } - - function borrowFreshPub(address payable borrower, uint256 borrowAmount) public returns (uint256) { - return borrowFresh(borrower, borrowAmount); - } - - function repayBorrowFreshPub(address payer, address borrower, uint256 repayAmount) public returns (uint256) { - (uint256 error, ) = repayBorrowFresh(payer, borrower, repayAmount); - return error; - } - - function liquidateBorrowFreshPub( - address liquidator, - address borrower, - uint256 repayAmount - ) public returns (uint256) { - (uint256 error, ) = liquidateBorrowFresh(liquidator, borrower, repayAmount, otherToken); - return error; - } -} diff --git a/spec/certora/contracts/CErc20DelegatorCertora.sol b/spec/certora/contracts/CErc20DelegatorCertora.sol deleted file mode 100644 index dccde1712..000000000 --- a/spec/certora/contracts/CErc20DelegatorCertora.sol +++ /dev/null @@ -1,133 +0,0 @@ -pragma solidity ^0.8.10; - -import "../../../contracts/VBep20Delegator.sol"; -import "../../../contracts/EIP20Interface.sol"; - -import "./VTokenCollateral.sol"; - -contract VBep20DelegatorCertora is VBep20Delegator { - VTokenCollateral public otherToken; - - constructor( - address underlying_, - ComptrollerInterface comptroller_, - InterestRateModel interestRateModel_, - uint256 initialExchangeRateMantissa_, - string memory name_, - string memory symbol_, - uint8 decimals_, - address payable admin_, - address implementation_, - bytes memory becomeImplementationData - ) - public - VBep20Delegator( - underlying_, - comptroller_, - interestRateModel_, - initialExchangeRateMantissa_, - name_, - symbol_, - decimals_, - admin_, - implementation_, - becomeImplementationData - ) - { - comptroller; // touch for Certora slot deduction - interestRateModel; // touch for Certora slot deduction - } - - function balanceOfInOther(address account) public view returns (uint256) { - return otherToken.balanceOf(account); - } - - function borrowBalanceStoredInOther(address account) public view returns (uint256) { - return otherToken.borrowBalanceStored(account); - } - - function exchangeRateStoredInOther() public view returns (uint256) { - return otherToken.exchangeRateStored(); - } - - function getCashInOther() public view returns (uint256) { - return otherToken.getCash(); - } - - function getCashOf(address account) public view returns (uint256) { - return EIP20Interface(underlying).balanceOf(account); - } - - function getCashOfInOther(address account) public view returns (uint256) { - return otherToken.getCashOf(account); - } - - function totalSupplyInOther() public view returns (uint256) { - return otherToken.totalSupply(); - } - - function totalBorrowsInOther() public view returns (uint256) { - return otherToken.totalBorrows(); - } - - function totalReservesInOther() public view returns (uint256) { - return otherToken.totalReserves(); - } - - function underlyingInOther() public view returns (address) { - return otherToken.underlying(); - } - - function mintFreshPub(address minter, uint256 mintAmount) public returns (uint256) { - bytes memory data = delegateToImplementation( - abi.encodeWithSignature("_mintFreshPub(address,uint256)", minter, mintAmount) - ); - return abi.decode(data, (uint256)); - } - - function redeemFreshPub( - address payable redeemer, - uint256 redeemTokens, - uint256 redeemUnderlying - ) public returns (uint256) { - bytes memory data = delegateToImplementation( - abi.encodeWithSignature( - "_redeemFreshPub(address,uint256,uint256)", - redeemer, - redeemTokens, - redeemUnderlying - ) - ); - return abi.decode(data, (uint256)); - } - - function borrowFreshPub(address payable borrower, uint256 borrowAmount) public returns (uint256) { - bytes memory data = delegateToImplementation( - abi.encodeWithSignature("_borrowFreshPub(address,uint256)", borrower, borrowAmount) - ); - return abi.decode(data, (uint256)); - } - - function repayBorrowFreshPub(address payer, address borrower, uint256 repayAmount) public returns (uint256) { - bytes memory data = delegateToImplementation( - abi.encodeWithSignature("_repayBorrowFreshPub(address,address,uint256)", payer, borrower, repayAmount) - ); - return abi.decode(data, (uint256)); - } - - function liquidateBorrowFreshPub( - address liquidator, - address borrower, - uint256 repayAmount - ) public returns (uint256) { - bytes memory data = delegateToImplementation( - abi.encodeWithSignature( - "_liquidateBorrowFreshPub(address,address,uint256)", - liquidator, - borrower, - repayAmount - ) - ); - return abi.decode(data, (uint256)); - } -} diff --git a/spec/certora/contracts/CErc20ImmutableCertora.sol b/spec/certora/contracts/CErc20ImmutableCertora.sol deleted file mode 100644 index 7136a5a94..000000000 --- a/spec/certora/contracts/CErc20ImmutableCertora.sol +++ /dev/null @@ -1,104 +0,0 @@ -pragma solidity ^0.8.10; - -import "../../../contracts/VBep20Immutable.sol"; -import "../../../contracts/EIP20Interface.sol"; - -import "./VTokenCollateral.sol"; - -contract VBep20ImmutableCertora is VBep20Immutable { - VTokenCollateral public otherToken; - - constructor( - address underlying_, - ComptrollerInterface comptroller_, - InterestRateModel interestRateModel_, - uint256 initialExchangeRateMantissa_, - string memory name_, - string memory symbol_, - uint8 decimals_, - address payable admin_ - ) - public - VBep20Immutable( - underlying_, - comptroller_, - interestRateModel_, - initialExchangeRateMantissa_, - name_, - symbol_, - decimals_, - admin_ - ) - {} - - function balanceOfInOther(address account) public view returns (uint256) { - return otherToken.balanceOf(account); - } - - function borrowBalanceStoredInOther(address account) public view returns (uint256) { - return otherToken.borrowBalanceStored(account); - } - - function exchangeRateStoredInOther() public view returns (uint256) { - return otherToken.exchangeRateStored(); - } - - function getCashInOther() public view returns (uint256) { - return otherToken.getCash(); - } - - function getCashOf(address account) public view returns (uint256) { - return EIP20Interface(underlying).balanceOf(account); - } - - function getCashOfInOther(address account) public view returns (uint256) { - return otherToken.getCashOf(account); - } - - function totalSupplyInOther() public view returns (uint256) { - return otherToken.totalSupply(); - } - - function totalBorrowsInOther() public view returns (uint256) { - return otherToken.totalBorrows(); - } - - function totalReservesInOther() public view returns (uint256) { - return otherToken.totalReserves(); - } - - function underlyingInOther() public view returns (address) { - return otherToken.underlying(); - } - - function mintFreshPub(address minter, uint256 mintAmount) public returns (uint256) { - (uint256 error, ) = mintFresh(minter, mintAmount); - return error; - } - - function redeemFreshPub( - address payable redeemer, - uint256 redeemTokens, - uint256 redeemUnderlying - ) public returns (uint256) { - return redeemFresh(redeemer, redeemTokens, redeemUnderlying); - } - - function borrowFreshPub(address payable borrower, uint256 borrowAmount) public returns (uint256) { - return borrowFresh(borrower, borrowAmount); - } - - function repayBorrowFreshPub(address payer, address borrower, uint256 repayAmount) public returns (uint256) { - (uint256 error, ) = repayBorrowFresh(payer, borrower, repayAmount); - return error; - } - - function liquidateBorrowFreshPub( - address liquidator, - address borrower, - uint256 repayAmount - ) public returns (uint256) { - (uint256 error, ) = liquidateBorrowFresh(liquidator, borrower, repayAmount, otherToken); - return error; - } -} diff --git a/spec/certora/contracts/CEtherCertora.sol b/spec/certora/contracts/CEtherCertora.sol deleted file mode 100644 index bac88f5aa..000000000 --- a/spec/certora/contracts/CEtherCertora.sol +++ /dev/null @@ -1,18 +0,0 @@ -pragma solidity ^0.8.10; - -import "../../../contracts/CEther.sol"; - -contract CEtherCertora is CEther { - constructor( - ComptrollerInterface comptroller_, - InterestRateModel interestRateModel_, - uint256 initialExchangeRateMantissa_, - string memory name_, - string memory symbol_, - uint8 decimals_, - address payable admin_ - ) - public - CEther(comptroller_, interestRateModel_, initialExchangeRateMantissa_, name_, symbol_, decimals_, admin_) - {} -} diff --git a/spec/certora/contracts/CTokenCollateral.sol b/spec/certora/contracts/CTokenCollateral.sol deleted file mode 100644 index 5fc655830..000000000 --- a/spec/certora/contracts/CTokenCollateral.sol +++ /dev/null @@ -1,33 +0,0 @@ -pragma solidity ^0.8.10; - -import "../../../contracts/VBep20Immutable.sol"; -import "../../../contracts/EIP20Interface.sol"; - -contract VTokenCollateral is VBep20Immutable { - constructor( - address underlying_, - ComptrollerInterface comptroller_, - InterestRateModel interestRateModel_, - uint256 initialExchangeRateMantissa_, - string memory name_, - string memory symbol_, - uint8 decimals_, - address payable admin_ - ) - public - VBep20Immutable( - underlying_, - comptroller_, - interestRateModel_, - initialExchangeRateMantissa_, - name_, - symbol_, - decimals_, - admin_ - ) - {} - - function getCashOf(address account) public view returns (uint256) { - return EIP20Interface(underlying).balanceOf(account); - } -} diff --git a/spec/certora/contracts/CompCertora.sol b/spec/certora/contracts/CompCertora.sol deleted file mode 100644 index f56dabf52..000000000 --- a/spec/certora/contracts/CompCertora.sol +++ /dev/null @@ -1,36 +0,0 @@ -pragma solidity ^0.8.10; - -import "../../../contracts/Governance/Comp.sol"; - -contract CompCertora is Comp { - constructor(address grantor) public Comp(grantor) {} - - function certoraOrdered(address account) external view returns (bool) { - uint32 nCheckpoints = numCheckpoints[account]; - for (uint32 i = 1; i < nCheckpoints; i++) { - if (checkpoints[account][i - 1].fromBlock >= checkpoints[account][i].fromBlock) { - return false; - } - } - - // make sure the checkpoints are also all before the current block - if (nCheckpoints > 0 && checkpoints[account][nCheckpoints - 1].fromBlock > block.number) { - return false; - } - - return true; - } - - function certoraScan(address account, uint256 blockNumber) external view returns (uint256) { - // find most recent checkpoint from before blockNumber - for (uint32 i = numCheckpoints[account]; i != 0; i--) { - Checkpoint memory cp = checkpoints[account][i - 1]; - if (cp.fromBlock <= blockNumber) { - return cp.votes; - } - } - - // blockNumber is from before first checkpoint (or list is empty) - return 0; - } -} diff --git a/spec/certora/contracts/ComptrollerCertora.sol b/spec/certora/contracts/ComptrollerCertora.sol deleted file mode 100644 index 498fc2836..000000000 --- a/spec/certora/contracts/ComptrollerCertora.sol +++ /dev/null @@ -1,21 +0,0 @@ -pragma solidity ^0.8.10; - -import "../../../contracts/Comptroller.sol"; - -contract ComptrollerCertora is Comptroller { - uint8 switcher; - uint256 liquidityOrShortfall; - - function getHypotheticalAccountLiquidityInternal( - address account, - VToken vTokenModify, - uint256 redeemTokens, - uint256 borrowAmount - ) internal view override returns (Error, uint256, uint256) { - if (switcher == 0) return (Error.NO_ERROR, liquidityOrShortfall, 0); - if (switcher == 1) return (Error.NO_ERROR, 0, liquidityOrShortfall); - if (switcher == 2) return (Error.SNAPSHOT_ERROR, 0, 0); - if (switcher == 3) return (Error.PRICE_ERROR, 0, 0); - return (Error.MATH_ERROR, 0, 0); - } -} diff --git a/spec/certora/contracts/GovernorAlphaCertora.sol b/spec/certora/contracts/GovernorAlphaCertora.sol deleted file mode 100644 index 436ea17bc..000000000 --- a/spec/certora/contracts/GovernorAlphaCertora.sol +++ /dev/null @@ -1,63 +0,0 @@ -pragma solidity ^0.8.10; -pragma experimental ABIEncoderV2; - -import "../../../contracts/Governance/GovernorAlpha.sol"; - -contract GovernorAlphaCertora is GovernorAlpha { - Proposal proposal; - - constructor( - address timelock_, - address comp_, - address guardian_ - ) public GovernorAlpha(timelock_, comp_, guardian_) {} - - // XXX breaks solver - /* function certoraPropose() public returns (uint) { */ - /* return propose(proposal.targets, proposal.values, proposal.signatures, proposal.calldatas, "Motion to do something"); */ - /* } */ - - /* function certoraProposalLength(uint proposalId) public returns (uint) { */ - /* return proposals[proposalId].targets.length; */ - /* } */ - - function certoraProposalStart(uint256 proposalId) public returns (uint256) { - return proposals[proposalId].startBlock; - } - - function certoraProposalEnd(uint256 proposalId) public returns (uint256) { - return proposals[proposalId].endBlock; - } - - function certoraProposalEta(uint256 proposalId) public returns (uint256) { - return proposals[proposalId].eta; - } - - function certoraProposalExecuted(uint256 proposalId) public returns (bool) { - return proposals[proposalId].executed; - } - - function certoraProposalState(uint256 proposalId) public returns (uint256) { - return uint256(state(proposalId)); - } - - function certoraProposalVotesFor(uint256 proposalId) public returns (uint256) { - return proposals[proposalId].forVotes; - } - - function certoraProposalVotesAgainst(uint256 proposalId) public returns (uint256) { - return proposals[proposalId].againstVotes; - } - - function certoraVoterVotes(uint256 proposalId, address voter) public returns (uint256) { - return proposals[proposalId].receipts[voter].votes; - } - - function certoraTimelockDelay() public returns (uint256) { - return timelock.delay(); - } - - function certoraTimelockGracePeriod() public returns (uint256) { - return timelock.GRACE_PERIOD(); - } -} diff --git a/spec/certora/contracts/InterestRateModelModel.sol b/spec/certora/contracts/InterestRateModelModel.sol deleted file mode 100644 index 042e5aae6..000000000 --- a/spec/certora/contracts/InterestRateModelModel.sol +++ /dev/null @@ -1,29 +0,0 @@ -pragma solidity ^0.8.10; - -import "../../../contracts/InterestRateModel.sol"; - -contract InterestRateModelModel is InterestRateModel { - uint256 borrowDummy; - uint256 supplyDummy; - - function isInterestRateModel() external pure override returns (bool) { - return true; - } - - function getBorrowRate( - uint256 _cash, - uint256 _borrows, - uint256 _reserves - ) external view override returns (uint256) { - return borrowDummy; - } - - function getSupplyRate( - uint256 _cash, - uint256 _borrows, - uint256 _reserves, - uint256 _reserveFactorMantissa - ) external view override returns (uint256) { - return supplyDummy; - } -} diff --git a/spec/certora/contracts/MathCertora.sol b/spec/certora/contracts/MathCertora.sol deleted file mode 100644 index a3f250c9f..000000000 --- a/spec/certora/contracts/MathCertora.sol +++ /dev/null @@ -1,3 +0,0 @@ -pragma solidity ^0.8.10; - -contract MathCertora {} diff --git a/spec/certora/contracts/MaximillionCertora.sol b/spec/certora/contracts/MaximillionCertora.sol deleted file mode 100644 index 923f4ebea..000000000 --- a/spec/certora/contracts/MaximillionCertora.sol +++ /dev/null @@ -1,19 +0,0 @@ -pragma solidity ^0.8.10; - -import "../../../contracts/Maximillion.sol"; - -contract MaximillionCertora is Maximillion { - constructor(CEther cEther_) public Maximillion(cEther_) {} - - function borrowBalance(address account) external returns (uint256) { - return cEther.borrowBalanceCurrent(account); - } - - function etherBalance(address account) external returns (uint256) { - return account.balance; - } - - function repayBehalf(address borrower) public payable override { - return super.repayBehalf(borrower); - } -} diff --git a/spec/certora/contracts/PriceOracleModel.sol b/spec/certora/contracts/PriceOracleModel.sol deleted file mode 100644 index 071d2f006..000000000 --- a/spec/certora/contracts/PriceOracleModel.sol +++ /dev/null @@ -1,15 +0,0 @@ -pragma solidity ^0.8.10; - -import "@venusprotocol/oracle/contracts/PriceOracle.sol"; - -contract PriceOracleModel is PriceOracle { - uint256 dummy; - - function isPriceOracle() external pure override returns (bool) { - return true; - } - - function getUnderlyingPrice(VToken vToken) external view override returns (uint256) { - return dummy; - } -} diff --git a/spec/certora/contracts/SimulationInterface.sol b/spec/certora/contracts/SimulationInterface.sol deleted file mode 100644 index 034ea2e55..000000000 --- a/spec/certora/contracts/SimulationInterface.sol +++ /dev/null @@ -1,5 +0,0 @@ -pragma solidity ^0.8.10; - -interface SimulationInterface { - function dummy() external; -} diff --git a/spec/certora/contracts/TimelockCertora.sol b/spec/certora/contracts/TimelockCertora.sol deleted file mode 100644 index dafb2429f..000000000 --- a/spec/certora/contracts/TimelockCertora.sol +++ /dev/null @@ -1,23 +0,0 @@ -pragma solidity ^0.8.10; - -import "../../../contracts/Timelock.sol"; - -contract TimelockCertora is Timelock { - constructor(address admin_, uint256 delay_) public Timelock(admin_, delay_) {} - - function grace() public pure returns (uint256) { - return GRACE_PERIOD; - } - - function queueTransactionStatic(address target, uint256 value, uint256 eta) public returns (bytes32) { - return queueTransaction(target, value, "setCounter()", "", eta); - } - - function cancelTransactionStatic(address target, uint256 value, uint256 eta) public { - return cancelTransaction(target, value, "setCounter()", "", eta); - } - - function executeTransactionStatic(address target, uint256 value, uint256 eta) public { - executeTransaction(target, value, "setCounter()", "", eta); // NB: cannot return dynamic types (will hang solver) - } -} diff --git a/spec/certora/contracts/UnderlyingModelNonStandard.sol b/spec/certora/contracts/UnderlyingModelNonStandard.sol deleted file mode 100644 index 827fe0601..000000000 --- a/spec/certora/contracts/UnderlyingModelNonStandard.sol +++ /dev/null @@ -1,50 +0,0 @@ -pragma solidity ^0.8.10; - -import "../../../contracts/EIP20NonStandardInterface.sol"; - -import "./SimulationInterface.sol"; - -contract UnderlyingModelNonStandard is EIP20NonStandardInterface, SimulationInterface { - uint256 _totalSupply; - mapping(address => uint256) balances; - mapping(address => mapping(address => uint256)) allowances; - - function totalSupply() external view override returns (uint256) { - return _totalSupply; - } - - function balanceOf(address owner) external view override returns (uint256 balance) { - balance = balances[owner]; - } - - function transfer(address dst, uint256 amount) external override { - address src = msg.sender; - require(balances[src] >= amount); - require(balances[dst] + amount >= balances[dst]); - - balances[src] -= amount; - balances[dst] += amount; - } - - function transferFrom(address src, address dst, uint256 amount) external override { - require(allowances[src][msg.sender] >= amount); - require(balances[src] >= amount); - require(balances[dst] + amount >= balances[dst]); - - allowances[src][msg.sender] -= amount; - balances[src] -= amount; - balances[dst] += amount; - } - - function approve(address spender, uint256 amount) external override returns (bool success) { - allowances[msg.sender][spender] = amount; - } - - function allowance(address owner, address spender) external view override returns (uint256 remaining) { - remaining = allowances[owner][spender]; - } - - function dummy() external override { - return; - } -} diff --git a/spec/certora/contracts/UnderlyingModelWithFee.sol b/spec/certora/contracts/UnderlyingModelWithFee.sol deleted file mode 100644 index ec70e632f..000000000 --- a/spec/certora/contracts/UnderlyingModelWithFee.sol +++ /dev/null @@ -1,55 +0,0 @@ -pragma solidity ^0.8.10; - -import "../../../contracts/EIP20NonStandardInterface.sol"; - -import "./SimulationInterface.sol"; - -contract UnderlyingModelWithFee is EIP20NonStandardInterface, SimulationInterface { - uint256 _totalSupply; - uint256 fee; - mapping(address => uint256) balances; - mapping(address => mapping(address => uint256)) allowances; - - function totalSupply() external view override returns (uint256) { - return _totalSupply; - } - - function balanceOf(address owner) external view override returns (uint256 balance) { - balance = balances[owner]; - } - - function transfer(address dst, uint256 amount) external override { - address src = msg.sender; - uint256 actualAmount = amount + fee; - require(actualAmount >= amount); - require(balances[src] >= actualAmount); - require(balances[dst] + actualAmount >= balances[dst]); - - balances[src] -= actualAmount; - balances[dst] += actualAmount; - } - - function transferFrom(address src, address dst, uint256 amount) external override { - uint256 actualAmount = amount + fee; - require(actualAmount > fee); - require(allowances[src][msg.sender] >= actualAmount); - require(balances[src] >= actualAmount); - require(balances[dst] + actualAmount >= balances[dst]); - - allowances[src][msg.sender] -= actualAmount; - balances[src] -= actualAmount; - balances[dst] += actualAmount; - } - - function approve(address spender, uint256 amount) external override returns (bool success) { - allowances[msg.sender][spender] = amount; - } - - function allowance(address owner, address spender) external view override returns (uint256 remaining) { - remaining = allowances[owner][spender]; - } - - function dummy() external override { - return; - } -} diff --git a/spec/certora/contracts/mcd/Dai.sol b/spec/certora/contracts/mcd/Dai.sol deleted file mode 100644 index 7708645af..000000000 --- a/spec/certora/contracts/mcd/Dai.sol +++ /dev/null @@ -1,158 +0,0 @@ -// Copyright (C) 2017, 2018, 2019 dbrock, rain, mrchico - -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -pragma solidity ^0.8.10; - -import "./lib.sol"; - -contract Dai is LibNote { - // --- Auth --- - mapping(address => uint256) public wards; - - function rely(address guy) external note auth { - wards[guy] = 1; - } - - function deny(address guy) external note auth { - wards[guy] = 0; - } - - modifier auth() { - require(wards[msg.sender] == 1, "Dai/not-authorized"); - _; - } - - // --- ERC20 Data --- - string public constant name = "Dai Stablecoin"; - string public constant symbol = "DAI"; - string public constant version = "1"; - uint8 public constant decimals = 18; - uint256 public totalSupply; - - mapping(address => uint256) public balanceOf; - mapping(address => mapping(address => uint256)) public allowance; - mapping(address => uint256) public nonces; - - event Approval(address indexed src, address indexed guy, uint256 wad); - event Transfer(address indexed src, address indexed dst, uint256 wad); - - // --- Math --- - function add(uint256 x, uint256 y) internal pure returns (uint256 z) { - require((z = x + y) >= x); - } - - function sub(uint256 x, uint256 y) internal pure returns (uint256 z) { - require((z = x - y) <= x); - } - - // --- EIP712 niceties --- - bytes32 public DOMAIN_SEPARATOR; - // bytes32 public constant PERMIT_TYPEHASH = keccak256("Permit(address holder,address spender,uint256 nonce,uint256 expiry,bool allowed)"); - bytes32 public constant PERMIT_TYPEHASH = 0xea2aa0a1be11a07ed86d755c93467f4f82362b452371d1ba94d1715123511acb; - - constructor(uint256 chainId_) public { - wards[msg.sender] = 1; - DOMAIN_SEPARATOR = keccak256( - abi.encode( - keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"), - keccak256(bytes(name)), - keccak256(bytes(version)), - chainId_, - address(this) - ) - ); - } - - // --- Token --- - function transfer(address dst, uint256 wad) external returns (bool) { - return transferFrom(msg.sender, dst, wad); - } - - function transferFrom(address src, address dst, uint256 wad) public returns (bool) { - require(balanceOf[src] >= wad, "Dai/insufficient-balance"); - if (src != msg.sender && allowance[src][msg.sender] != uint256(-1)) { - require(allowance[src][msg.sender] >= wad, "Dai/insufficient-allowance"); - allowance[src][msg.sender] = sub(allowance[src][msg.sender], wad); - } - balanceOf[src] = sub(balanceOf[src], wad); - balanceOf[dst] = add(balanceOf[dst], wad); - emit Transfer(src, dst, wad); - return true; - } - - function mint(address usr, uint256 wad) external auth { - balanceOf[usr] = add(balanceOf[usr], wad); - totalSupply = add(totalSupply, wad); - emit Transfer(address(0), usr, wad); - } - - function burn(address usr, uint256 wad) external { - require(balanceOf[usr] >= wad, "Dai/insufficient-balance"); - if (usr != msg.sender && allowance[usr][msg.sender] != uint256(-1)) { - require(allowance[usr][msg.sender] >= wad, "Dai/insufficient-allowance"); - allowance[usr][msg.sender] = sub(allowance[usr][msg.sender], wad); - } - balanceOf[usr] = sub(balanceOf[usr], wad); - totalSupply = sub(totalSupply, wad); - emit Transfer(usr, address(0), wad); - } - - function approve(address usr, uint256 wad) external returns (bool) { - allowance[msg.sender][usr] = wad; - emit Approval(msg.sender, usr, wad); - return true; - } - - // --- Alias --- - function push(address usr, uint256 wad) external { - transferFrom(msg.sender, usr, wad); - } - - function pull(address usr, uint256 wad) external { - transferFrom(usr, msg.sender, wad); - } - - function move(address src, address dst, uint256 wad) external { - transferFrom(src, dst, wad); - } - - // --- Approve by signature --- - function permit( - address holder, - address spender, - uint256 nonce, - uint256 expiry, - bool allowed, - uint8 v, - bytes32 r, - bytes32 s - ) external { - bytes32 digest = keccak256( - abi.encodePacked( - "\x19\x01", - DOMAIN_SEPARATOR, - keccak256(abi.encode(PERMIT_TYPEHASH, holder, spender, nonce, expiry, allowed)) - ) - ); - - require(holder != address(0), "Dai/invalid-address-0"); - require(holder == ecrecover(digest, v, r, s), "Dai/invalid-permit"); - require(expiry == 0 || now <= expiry, "Dai/permit-expired"); - require(nonce == nonces[holder]++, "Dai/invalid-nonce"); - uint256 wad = allowed ? uint256(-1) : 0; - allowance[holder][spender] = wad; - emit Approval(holder, spender, wad); - } -} diff --git a/spec/certora/contracts/mcd/Lib.sol b/spec/certora/contracts/mcd/Lib.sol deleted file mode 100644 index 3f67782db..000000000 --- a/spec/certora/contracts/mcd/Lib.sol +++ /dev/null @@ -1,45 +0,0 @@ -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. - -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . - -pragma solidity ^0.8.10; - -contract LibNote { - event LogNote( - bytes4 indexed sig, - address indexed usr, - bytes32 indexed arg1, - bytes32 indexed arg2, - bytes data - ) anonymous; - - modifier note() { - _; - assembly { - // log an 'anonymous' event with a constant 6 words of calldata - // and four indexed topics: selector, caller, arg1 and arg2 - let mark := msize // end of memory ensures zero - mstore(0x40, add(mark, 288)) // update free memory pointer - mstore(mark, 0x20) // bytes type data offset - mstore(add(mark, 0x20), 224) // bytes size (padded) - calldatacopy(add(mark, 0x40), 0, 224) // bytes payload - log4( - mark, - 288, // calldata - shl(224, shr(224, calldataload(0))), // msg.sig - caller, // msg.sender - calldataload(4), // arg1 - calldataload(36) // arg2 - ) - } - } -} diff --git a/spec/certora/contracts/mcd/Pot.sol b/spec/certora/contracts/mcd/Pot.sol deleted file mode 100644 index 9d1663c26..000000000 --- a/spec/certora/contracts/mcd/Pot.sol +++ /dev/null @@ -1,198 +0,0 @@ -/// pot.sol -- Dai Savings Rate - -// Copyright (C) 2018 Rain -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -pragma solidity ^0.8.10; - -import "./lib.sol"; - -/* - "Savings Dai" is obtained when Dai is deposited into - this contract. Each "Savings Dai" accrues Dai interest - at the "Dai Savings Rate". - - This contract does not implement a user tradeable token - and is intended to be used with adapters. - - --- `save` your `dai` in the `pot` --- - - - `dsr`: the Dai Savings Rate - - `pie`: user balance of Savings Dai - - - `join`: start saving some dai - - `exit`: remove some dai - - `drip`: perform rate collection - -*/ - -contract VatLike { - function move(address, address, uint256) external; - - function suck(address, address, uint256) external; -} - -contract Pot is LibNote { - // --- Auth --- - mapping(address => uint256) public wards; - - function rely(address guy) external note auth { - wards[guy] = 1; - } - - function deny(address guy) external note auth { - wards[guy] = 0; - } - - modifier auth() { - require(wards[msg.sender] == 1, "Pot/not-authorized"); - _; - } - - // --- Data --- - mapping(address => uint256) public pie; // user Savings Dai - - uint256 public Pie; // total Savings Dai - uint256 public dsr; // the Dai Savings Rate - uint256 public chi; // the Rate Accumulator - - VatLike public vat; // CDP engine - address public vow; // debt engine - uint256 public rho; // time of last drip - - uint256 public live; // Access Flag - - // --- Init --- - constructor(address vat_) public { - wards[msg.sender] = 1; - vat = VatLike(vat_); - dsr = ONE; - chi = ONE; - rho = now; - live = 1; - } - - // --- Math --- - uint256 constant ONE = 10 ** 27; - - function rpow(uint256 x, uint256 n, uint256 base) internal pure returns (uint256 z) { - assembly { - switch x - case 0 { - switch n - case 0 { - z := base - } - default { - z := 0 - } - } - default { - switch mod(n, 2) - case 0 { - z := base - } - default { - z := x - } - let half := div(base, 2) // for rounding. - for { - n := div(n, 2) - } n { - n := div(n, 2) - } { - let xx := mul(x, x) - if iszero(eq(div(xx, x), x)) { - revert(0, 0) - } - let xxRound := add(xx, half) - if lt(xxRound, xx) { - revert(0, 0) - } - x := div(xxRound, base) - if mod(n, 2) { - let zx := mul(z, x) - if and(iszero(iszero(x)), iszero(eq(div(zx, x), z))) { - revert(0, 0) - } - let zxRound := add(zx, half) - if lt(zxRound, zx) { - revert(0, 0) - } - z := div(zxRound, base) - } - } - } - } - } - - function rmul(uint256 x, uint256 y) internal pure returns (uint256 z) { - z = mul(x, y) / ONE; - } - - function add(uint256 x, uint256 y) internal pure returns (uint256 z) { - require((z = x + y) >= x); - } - - function sub(uint256 x, uint256 y) internal pure returns (uint256 z) { - require((z = x - y) <= x); - } - - function mul(uint256 x, uint256 y) internal pure returns (uint256 z) { - require(y == 0 || (z = x * y) / y == x); - } - - // --- Administration --- - function file(bytes32 what, uint256 data) external note auth { - require(live == 1, "Pot/not-live"); - require(now == rho, "Pot/rho-not-updated"); - if (what == "dsr") dsr = data; - else revert("Pot/file-unrecognized-param"); - } - - function file(bytes32 what, address addr) external note auth { - if (what == "vow") vow = addr; - else revert("Pot/file-unrecognized-param"); - } - - function cage() external note auth { - live = 0; - dsr = ONE; - } - - // --- Savings Rate Accumulation --- - function drip() external note returns (uint256 tmp) { - require(now >= rho, "Pot/invalid-now"); - tmp = rmul(rpow(dsr, now - rho, ONE), chi); - uint256 chi_ = sub(tmp, chi); - chi = tmp; - rho = now; - vat.suck(address(vow), address(this), mul(Pie, chi_)); - } - - // --- Savings Dai Management --- - function join(uint256 wad) external note { - require(now == rho, "Pot/rho-not-updated"); - pie[msg.sender] = add(pie[msg.sender], wad); - Pie = add(Pie, wad); - vat.move(msg.sender, address(this), mul(chi, wad)); - } - - function exit(uint256 wad) external note { - pie[msg.sender] = sub(pie[msg.sender], wad); - Pie = sub(Pie, wad); - vat.move(address(this), msg.sender, mul(chi, wad)); - } -} diff --git a/spec/certora/contracts/mcd/Vat.sol b/spec/certora/contracts/mcd/Vat.sol deleted file mode 100644 index 28616e205..000000000 --- a/spec/certora/contracts/mcd/Vat.sol +++ /dev/null @@ -1,304 +0,0 @@ -/// vat.sol -- Dai CDP database - -// Copyright (C) 2018 Rain -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -pragma solidity ^0.8.10; - -contract Vat { - // --- Auth --- - mapping(address => uint256) public wards; - - function rely(address usr) external note auth { - require(live == 1, "Vat/not-live"); - wards[usr] = 1; - } - - function deny(address usr) external note auth { - require(live == 1, "Vat/not-live"); - wards[usr] = 0; - } - - modifier auth() { - require(wards[msg.sender] == 1, "Vat/not-authorized"); - _; - } - - mapping(address => mapping(address => uint256)) public can; - - function hope(address usr) external note { - can[msg.sender][usr] = 1; - } - - function nope(address usr) external note { - can[msg.sender][usr] = 0; - } - - function wish(address bit, address usr) internal view returns (bool) { - return either(bit == usr, can[bit][usr] == 1); - } - - // --- Data --- - struct Ilk { - uint256 Art; // Total Normalised Debt [wad] - uint256 rate; // Accumulated Rates [ray] - uint256 spot; // Price with Safety Margin [ray] - uint256 line; // Debt Ceiling [rad] - uint256 dust; // Urn Debt Floor [rad] - } - struct Urn { - uint256 ink; // Locked Collateral [wad] - uint256 art; // Normalised Debt [wad] - } - - mapping(bytes32 => Ilk) public ilks; - mapping(bytes32 => mapping(address => Urn)) public urns; - mapping(bytes32 => mapping(address => uint256)) public gem; // [wad] - mapping(address => uint256) public dai; // [rad] - mapping(address => uint256) public sin; // [rad] - - uint256 public debt; // Total Dai Issued [rad] - uint256 public vice; // Total Unbacked Dai [rad] - uint256 public Line; // Total Debt Ceiling [rad] - uint256 public live; // Access Flag - - // --- Logs --- - event LogNote( - bytes4 indexed sig, - bytes32 indexed arg1, - bytes32 indexed arg2, - bytes32 indexed arg3, - bytes data - ) anonymous; - - modifier note() { - _; - assembly { - // log an 'anonymous' event with a constant 6 words of calldata - // and four indexed topics: the selector and the first three args - let mark := msize // end of memory ensures zero - mstore(0x40, add(mark, 288)) // update free memory pointer - mstore(mark, 0x20) // bytes type data offset - mstore(add(mark, 0x20), 224) // bytes size (padded) - calldatacopy(add(mark, 0x40), 0, 224) // bytes payload - log4( - mark, - 288, // calldata - shl(224, shr(224, calldataload(0))), // msg.sig - calldataload(4), // arg1 - calldataload(36), // arg2 - calldataload(68) // arg3 - ) - } - } - - // --- Init --- - constructor() public { - wards[msg.sender] = 1; - live = 1; - } - - // --- Math --- - function add(uint256 x, int256 y) internal pure returns (uint256 z) { - z = x + uint256(y); - require(y >= 0 || z <= x); - require(y <= 0 || z >= x); - } - - function sub(uint256 x, int256 y) internal pure returns (uint256 z) { - z = x - uint256(y); - require(y <= 0 || z <= x); - require(y >= 0 || z >= x); - } - - function mul(uint256 x, int256 y) internal pure returns (int256 z) { - z = int256(x) * y; - require(int256(x) >= 0); - require(y == 0 || z / y == int256(x)); - } - - function add(uint256 x, uint256 y) internal pure returns (uint256 z) { - require((z = x + y) >= x); - } - - function sub(uint256 x, uint256 y) internal pure returns (uint256 z) { - require((z = x - y) <= x); - } - - function mul(uint256 x, uint256 y) internal pure returns (uint256 z) { - require(y == 0 || (z = x * y) / y == x); - } - - // --- Administration --- - function init(bytes32 ilk) external note auth { - require(ilks[ilk].rate == 0, "Vat/ilk-already-init"); - ilks[ilk].rate = 10 ** 27; - } - - function file(bytes32 what, uint256 data) external note auth { - require(live == 1, "Vat/not-live"); - if (what == "Line") Line = data; - else revert("Vat/file-unrecognized-param"); - } - - function file(bytes32 ilk, bytes32 what, uint256 data) external note auth { - require(live == 1, "Vat/not-live"); - if (what == "spot") ilks[ilk].spot = data; - else if (what == "line") ilks[ilk].line = data; - else if (what == "dust") ilks[ilk].dust = data; - else revert("Vat/file-unrecognized-param"); - } - - function cage() external note auth { - live = 0; - } - - // --- Fungibility --- - function slip(bytes32 ilk, address usr, int256 wad) external note auth { - gem[ilk][usr] = add(gem[ilk][usr], wad); - } - - function flux(bytes32 ilk, address src, address dst, uint256 wad) external note { - require(wish(src, msg.sender), "Vat/not-allowed"); - gem[ilk][src] = sub(gem[ilk][src], wad); - gem[ilk][dst] = add(gem[ilk][dst], wad); - } - - function move(address src, address dst, uint256 rad) external note { - require(wish(src, msg.sender), "Vat/not-allowed"); - dai[src] = sub(dai[src], rad); - dai[dst] = add(dai[dst], rad); - } - - function either(bool x, bool y) internal pure returns (bool z) { - assembly { - z := or(x, y) - } - } - - function both(bool x, bool y) internal pure returns (bool z) { - assembly { - z := and(x, y) - } - } - - // --- CDP Manipulation --- - function frob(bytes32 i, address u, address v, address w, int256 dink, int256 dart) external note { - // system is live - require(live == 1, "Vat/not-live"); - - Urn memory urn = urns[i][u]; - Ilk memory ilk = ilks[i]; - // ilk has been initialised - require(ilk.rate != 0, "Vat/ilk-not-init"); - - urn.ink = add(urn.ink, dink); - urn.art = add(urn.art, dart); - ilk.Art = add(ilk.Art, dart); - - int256 dtab = mul(ilk.rate, dart); - uint256 tab = mul(ilk.rate, urn.art); - debt = add(debt, dtab); - - // either debt has decreased, or debt ceilings are not exceeded - require(either(dart <= 0, both(mul(ilk.Art, ilk.rate) <= ilk.line, debt <= Line)), "Vat/ceiling-exceeded"); - // urn is either less risky than before, or it is safe - require(either(both(dart <= 0, dink >= 0), tab <= mul(urn.ink, ilk.spot)), "Vat/not-safe"); - - // urn is either more safe, or the owner consents - require(either(both(dart <= 0, dink >= 0), wish(u, msg.sender)), "Vat/not-allowed-u"); - // collateral src consents - require(either(dink <= 0, wish(v, msg.sender)), "Vat/not-allowed-v"); - // debt dst consents - require(either(dart >= 0, wish(w, msg.sender)), "Vat/not-allowed-w"); - - // urn has no debt, or a non-dusty amount - require(either(urn.art == 0, tab >= ilk.dust), "Vat/dust"); - - gem[i][v] = sub(gem[i][v], dink); - dai[w] = add(dai[w], dtab); - - urns[i][u] = urn; - ilks[i] = ilk; - } - - // --- CDP Fungibility --- - function fork(bytes32 ilk, address src, address dst, int256 dink, int256 dart) external note { - Urn storage u = urns[ilk][src]; - Urn storage v = urns[ilk][dst]; - Ilk storage i = ilks[ilk]; - - u.ink = sub(u.ink, dink); - u.art = sub(u.art, dart); - v.ink = add(v.ink, dink); - v.art = add(v.art, dart); - - uint256 utab = mul(u.art, i.rate); - uint256 vtab = mul(v.art, i.rate); - - // both sides consent - require(both(wish(src, msg.sender), wish(dst, msg.sender)), "Vat/not-allowed"); - - // both sides safe - require(utab <= mul(u.ink, i.spot), "Vat/not-safe-src"); - require(vtab <= mul(v.ink, i.spot), "Vat/not-safe-dst"); - - // both sides non-dusty - require(either(utab >= i.dust, u.art == 0), "Vat/dust-src"); - require(either(vtab >= i.dust, v.art == 0), "Vat/dust-dst"); - } - - // --- CDP Confiscation --- - function grab(bytes32 i, address u, address v, address w, int256 dink, int256 dart) external note auth { - Urn storage urn = urns[i][u]; - Ilk storage ilk = ilks[i]; - - urn.ink = add(urn.ink, dink); - urn.art = add(urn.art, dart); - ilk.Art = add(ilk.Art, dart); - - int256 dtab = mul(ilk.rate, dart); - - gem[i][v] = sub(gem[i][v], dink); - sin[w] = sub(sin[w], dtab); - vice = sub(vice, dtab); - } - - // --- Settlement --- - function heal(uint256 rad) external note { - address u = msg.sender; - sin[u] = sub(sin[u], rad); - dai[u] = sub(dai[u], rad); - vice = sub(vice, rad); - debt = sub(debt, rad); - } - - function suck(address u, address v, uint256 rad) external note auth { - sin[u] = add(sin[u], rad); - dai[v] = add(dai[v], rad); - vice = add(vice, rad); - debt = add(debt, rad); - } - - // --- Rates --- - function fold(bytes32 i, address u, int256 rate) external note auth { - require(live == 1, "Vat/not-live"); - Ilk storage ilk = ilks[i]; - ilk.rate = add(ilk.rate, rate); - int256 rad = mul(ilk.Art, rate); - dai[u] = add(dai[u], rad); - debt = add(debt, rad); - } -} diff --git a/spec/certora/contracts/mcd/join.sol b/spec/certora/contracts/mcd/join.sol deleted file mode 100644 index ff443970e..000000000 --- a/spec/certora/contracts/mcd/join.sol +++ /dev/null @@ -1,209 +0,0 @@ -/// join.sol -- Basic token adapters - -// Copyright (C) 2018 Rain -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU Affero General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Affero General Public License for more details. -// -// You should have received a copy of the GNU Affero General Public License -// along with this program. If not, see . - -pragma solidity ^0.8.10; - -import "./lib.sol"; - -contract GemLike { - function decimals() public view returns (uint256); - - function transfer(address, uint256) external returns (bool); - - function transferFrom(address, address, uint256) external returns (bool); -} - -contract DSTokenLike { - function mint(address, uint256) external; - - function burn(address, uint256) external; -} - -contract VatLike { - function slip(bytes32, address, int256) external; - - function move(address, address, uint256) external; -} - -/* - Here we provide *adapters* to connect the Vat to arbitrary external - token implementations, creating a bounded context for the Vat. The - adapters here are provided as working examples: - - - `GemJoin`: For well behaved ERC20 tokens, with simple transfer - semantics. - - - `ETHJoin`: For native Ether. - - - `DaiJoin`: For connecting internal Dai balances to an external - `DSToken` implementation. - - In practice, adapter implementations will be varied and specific to - individual collateral types, accounting for different transfer - semantics and token standards. - - Adapters need to implement two basic methods: - - - `join`: enter collateral into the system - - `exit`: remove collateral from the system - -*/ - -contract GemJoin is LibNote { - // --- Auth --- - mapping(address => uint256) public wards; - - function rely(address usr) external note auth { - wards[usr] = 1; - } - - function deny(address usr) external note auth { - wards[usr] = 0; - } - - modifier auth() { - require(wards[msg.sender] == 1, "GemJoin/not-authorized"); - _; - } - - VatLike public vat; - bytes32 public ilk; - GemLike public gem; - uint256 public dec; - uint256 public live; // Access Flag - - constructor(address vat_, bytes32 ilk_, address gem_) public { - wards[msg.sender] = 1; - live = 1; - vat = VatLike(vat_); - ilk = ilk_; - gem = GemLike(gem_); - dec = gem.decimals(); - } - - function cage() external note auth { - live = 0; - } - - function join(address usr, uint256 wad) external note { - require(live == 1, "GemJoin/not-live"); - require(int256(wad) >= 0, "GemJoin/overflow"); - vat.slip(ilk, usr, int256(wad)); - require(gem.transferFrom(msg.sender, address(this), wad), "GemJoin/failed-transfer"); - } - - function exit(address usr, uint256 wad) external note { - require(wad <= 2 ** 255, "GemJoin/overflow"); - vat.slip(ilk, msg.sender, -int256(wad)); - require(gem.transfer(usr, wad), "GemJoin/failed-transfer"); - } -} - -contract ETHJoin is LibNote { - // --- Auth --- - mapping(address => uint256) public wards; - - function rely(address usr) external note auth { - wards[usr] = 1; - } - - function deny(address usr) external note auth { - wards[usr] = 0; - } - - modifier auth() { - require(wards[msg.sender] == 1, "ETHJoin/not-authorized"); - _; - } - - VatLike public vat; - bytes32 public ilk; - uint256 public live; // Access Flag - - constructor(address vat_, bytes32 ilk_) public { - wards[msg.sender] = 1; - live = 1; - vat = VatLike(vat_); - ilk = ilk_; - } - - function cage() external note auth { - live = 0; - } - - function join(address usr) external payable note { - require(live == 1, "ETHJoin/not-live"); - require(int256(msg.value) >= 0, "ETHJoin/overflow"); - vat.slip(ilk, usr, int256(msg.value)); - } - - function exit(address payable usr, uint256 wad) external note { - require(int256(wad) >= 0, "ETHJoin/overflow"); - vat.slip(ilk, msg.sender, -int256(wad)); - usr.transfer(wad); - } -} - -contract DaiJoin is LibNote { - // --- Auth --- - mapping(address => uint256) public wards; - - function rely(address usr) external note auth { - wards[usr] = 1; - } - - function deny(address usr) external note auth { - wards[usr] = 0; - } - - modifier auth() { - require(wards[msg.sender] == 1, "DaiJoin/not-authorized"); - _; - } - - VatLike public vat; - DSTokenLike public dai; - uint256 public live; // Access Flag - - constructor(address vat_, address dai_) public { - wards[msg.sender] = 1; - live = 1; - vat = VatLike(vat_); - dai = DSTokenLike(dai_); - } - - function cage() external note auth { - live = 0; - } - - uint256 constant ONE = 10 ** 27; - - function mul(uint256 x, uint256 y) internal pure returns (uint256 z) { - require(y == 0 || (z = x * y) / y == x); - } - - function join(address usr, uint256 wad) external note { - vat.move(address(this), usr, mul(ONE, wad)); - dai.burn(msg.sender, wad); - } - - function exit(address usr, uint256 wad) external note { - require(live == 1, "DaiJoin/not-live"); - vat.move(msg.sender, address(this), mul(ONE, wad)); - dai.mint(usr, wad); - } -} From 0d47567d45b382cfe4927fd2a0a2195fcc66040b Mon Sep 17 00:00:00 2001 From: Kirill Kuvshinov Date: Thu, 21 Sep 2023 14:11:07 +0300 Subject: [PATCH 07/33] refactor: remove unused files and scripts --- Makefile | 139 ---------------------------- gasCosts.json | 204 ----------------------------------------- jest.config.js | 185 ------------------------------------- reporterConfig.json | 3 - script/README.md | 1 - script/comptroller-abi | 33 ------- 6 files changed, 565 deletions(-) delete mode 100644 Makefile delete mode 100644 gasCosts.json delete mode 100644 jest.config.js delete mode 100644 reporterConfig.json delete mode 100644 script/README.md delete mode 100755 script/comptroller-abi diff --git a/Makefile b/Makefile deleted file mode 100644 index d65554780..000000000 --- a/Makefile +++ /dev/null @@ -1,139 +0,0 @@ - -# Run a single cvl e.g.: -# make -B spec/certora/CErc20/borrowAndRepayFresh.cvl - -# TODO: -# - mintAndRedeemFresh.cvl in progress and is failing due to issues with tool proving how the exchange rate can change -# hoping for better division modelling - currently fails to prove (a + 1) / b >= a / b -# - CErc20Delegator/*.cvl cannot yet be run with the tool -# - cDAI proofs are WIP, require using the delegate and the new revert message assertions - -.PHONY: certora-clean - -CERTORA_BIN = $(abspath script/certora) -CERTORA_RUN = $(CERTORA_BIN)/run.py -CERTORA_CLI = $(CERTORA_BIN)/cli.jar -CERTORA_EMV = $(CERTORA_BIN)/emv.jar - -export CERTORA = $(CERTORA_BIN) -export CERTORA_DISABLE_POPUP = 1 - -spec/certora/Math/%.cvl: - $(CERTORA_RUN) \ - spec/certora/contracts/MathCertora.sol \ - --verify \ - MathCertora:$@ - -spec/certora/Comp/search.cvl: - $(CERTORA_RUN) \ - spec/certora/contracts/CompCertora.sol \ - --settings -b=4,-graphDrawLimit=0,-assumeUnwindCond,-depth=100 \ - --solc_args "'--evm-version istanbul'" \ - --verify \ - CompCertora:$@ - -spec/certora/Comp/transfer.cvl: - $(CERTORA_RUN) \ - spec/certora/contracts/CompCertora.sol \ - --settings -graphDrawLimit=0,-assumeUnwindCond,-depth=100 \ - --solc_args "'--evm-version istanbul'" \ - --verify \ - CompCertora:$@ - -spec/certora/Governor/%.cvl: - $(CERTORA_RUN) \ - spec/certora/contracts/GovernorAlphaCertora.sol \ - spec/certora/contracts/TimelockCertora.sol \ - spec/certora/contracts/CompCertora.sol \ - --settings -assumeUnwindCond,-enableWildcardInlining=false \ - --solc_args "'--evm-version istanbul'" \ - --link \ - GovernorAlphaCertora:timelock=TimelockCertora \ - GovernorAlphaCertora:comp=CompCertora \ - --verify \ - GovernorAlphaCertora:$@ - -spec/certora/Comptroller/%.cvl: - $(CERTORA_RUN) \ - spec/certora/contracts/ComptrollerCertora.sol \ - spec/certora/contracts/PriceOracleModel.sol \ - --link \ - ComptrollerCertora:oracle=PriceOracleModel \ - --verify \ - ComptrollerCertora:$@ - -spec/certora/cDAI/%.cvl: - $(CERTORA_RUN) \ - spec/certora/contracts/CDaiDelegateCertora.sol \ - spec/certora/contracts/UnderlyingModelNonStandard.sol \ - spec/certora/contracts/mcd/dai.sol:Dai \ - spec/certora/contracts/mcd/pot.sol:Pot \ - spec/certora/contracts/mcd/vat.sol:Vat \ - spec/certora/contracts/mcd/join.sol:DaiJoin \ - tests/Contracts/BoolComptroller.sol \ - --link \ - CDaiDelegateCertora:comptroller=BoolComptroller \ - CDaiDelegateCertora:underlying=Dai \ - CDaiDelegateCertora:potAddress=Pot \ - CDaiDelegateCertora:vatAddress=Vat \ - CDaiDelegateCertora:daiJoinAddress=DaiJoin \ - --verify \ - CDaiDelegateCertora:$@ \ - --settings -cache=certora-run-cdai - -spec/certora/CErc20/%.cvl: - $(CERTORA_RUN) \ - spec/certora/contracts/CErc20ImmutableCertora.sol \ - spec/certora/contracts/CTokenCollateral.sol \ - spec/certora/contracts/ComptrollerCertora.sol \ - spec/certora/contracts/InterestRateModelModel.sol \ - spec/certora/contracts/UnderlyingModelNonStandard.sol \ - --link \ - CErc20ImmutableCertora:otherToken=CTokenCollateral \ - CErc20ImmutableCertora:comptroller=ComptrollerCertora \ - CErc20ImmutableCertora:underlying=UnderlyingModelNonStandard \ - CErc20ImmutableCertora:interestRateModel=InterestRateModelModel \ - CTokenCollateral:comptroller=ComptrollerCertora \ - CTokenCollateral:underlying=UnderlyingModelNonStandard \ - --verify \ - CErc20ImmutableCertora:$@ \ - --settings -cache=certora-run-cerc20-immutable - -spec/certora/CErc20Delegator/%.cvl: - $(CERTORA_RUN) \ - spec/certora/contracts/CErc20DelegatorCertora.sol \ - spec/certora/contracts/CErc20DelegateCertora.sol \ - spec/certora/contracts/CTokenCollateral.sol \ - spec/certora/contracts/ComptrollerCertora.sol \ - spec/certora/contracts/InterestRateModelModel.sol \ - spec/certora/contracts/UnderlyingModelNonStandard.sol \ - --link \ - CErc20DelegatorCertora:implementation=CErc20DelegateCertora \ - CErc20DelegatorCertora:otherToken=CTokenCollateral \ - CErc20DelegatorCertora:comptroller=ComptrollerCertora \ - CErc20DelegatorCertora:underlying=UnderlyingModelNonStandard \ - CErc20DelegatorCertora:interestRateModel=InterestRateModelModel \ - CTokenCollateral:comptroller=ComptrollerCertora \ - CTokenCollateral:underlying=UnderlyingModelNonStandard \ - --verify \ - CErc20DelegatorCertora:$@ \ - --settings -assumeUnwindCond \ - --settings -cache=certora-run-cerc20-delegator - -spec/certora/Maximillion/%.cvl: - $(CERTORA_RUN) \ - spec/certora/contracts/MaximillionCertora.sol \ - spec/certora/contracts/CEtherCertora.sol \ - --link \ - MaximillionCertora:cEther=CEtherCertora \ - --verify \ - MaximillionCertora:$@ - -spec/certora/Timelock/%.cvl: - $(CERTORA_RUN) \ - spec/certora/contracts/TimelockCertora.sol \ - --verify \ - TimelockCertora:$@ - -certora-clean: - rm -rf .certora_build.json .certora_config certora_verify.json emv-* diff --git a/gasCosts.json b/gasCosts.json deleted file mode 100644 index 6c1dc43ca..000000000 --- a/gasCosts.json +++ /dev/null @@ -1,204 +0,0 @@ -{ - "first mint": { - "fee": 124570, - "opcodes": {} - }, - "second mint": { - "fee": 84516, - "opcodes": { - "PUSH1 @ 3": 287, - "MSTORE @ 3": 126, - "PUSH1 @ 12": 1, - "CALLDATASIZE @ 3": 18, - "LT @ 2": 9, - "PUSH2 @ 3": 302, - "JUMPI @ 3": 137, - "PUSH1 @ 10": 12, - "CALLDATALOAD @ 3": 22, - "SHR @ 3": 9, - "DUP1 @ 3": 107, - "PUSH4 @ 3": 48, - "GT @ 3": 40, - "DUP1 @ 10": 12, - "JUMPDEST @ 10": 110, - "DUP1 @ 1": 23, - "EQ @ 3": 24, - "CALLVALUE @ 1": 1, - "DUP1 @ 2": 16, - "ISZERO @ 3": 88, - "POP @ 1": 66, - "PUSH2 @ 2": 7, - "PUSH1 @ 2": 58, - "JUMP @ 3": 145, - "JUMPDEST @ 8": 203, - "PUSH1 @ 1": 128, - "DUP3 @ 3": 105, - "DUP5 @ 3": 53, - "SUB @ 3": 67, - "SLT @ 3": 16, - "CALLDATALOAD @ 2": 2, - "SWAP2 @ 3": 86, - "SWAP1 @ 3": 195, - "POP @ 3": 106, - "JUMP @ 2": 57, - "PUSH2 @ 1": 25, - "DUP4 @ 3": 30, - "MLOAD @ 3": 82, - "ADD @ 3": 102, - "DUP2 @ 3": 118, - "PUSH1 @ 15": 1, - "NOT @ 3": 24, - "SHL @ 3": 40, - "AND @ 3": 53, - "OR @ 3": 2, - "SLOAD @ 3": 27, - "PUSH1 @ 800": 22, - "DUP8 @ 3": 10, - "JUMPDEST @ 3": 4, - "DUP4 @ 1": 5, - "LT @ 3": 9, - "DUP2 @ 10": 2, - "PUSH1 @ 6": 17, - "POP @ 2": 133, - "SWAP2 @ 1": 14, - "SWAP3 @ 3": 26, - "DUP6 @ 3": 33, - "GAS @ 3": 1, - "DELEGATECALL @ 2": 1, - "PUSH1 @ 312831": 1, - "CALLVALUE @ 12": 8, - "SSTORE @ 3": 11, - "PUSH2 @ 5000": 1, - "SWAP1 @ 800": 2, - "ADDRESS @ 9": 1, - "DUP7 @ 3": 17, - "EXTCODESIZE @ 3": 7, - "ISZERO @ 700": 7, - "GAS @ 2": 7, - "STATICCALL @ 2": 5, - "PUSH1 @ 307782": 1, - "SWAP4 @ 1": 17, - "SHA3 @ 3": 15, - "SLOAD @ 42": 9, - "DUP2 @ 800": 5, - "PUSH1 @ 9": 6, - "RETURN @ 3": 9, - "ISZERO @ -307082": 1, - "RETURNDATASIZE @ 3": 10, - "DUP2 @ 2": 7, - "MLOAD @ 2": 7, - "SWAP1 @ 2": 7, - "SWAP5 @ 6": 1, - "SWAP6 @ 3": 3, - "SWAP3 @ 2": 7, - "SWAP4 @ 3": 13, - "PUSH1 @ 307684": 1, - "POP @ 10": 1, - "SWAP1 @ 1": 25, - "PUSH8 @ 800": 1, - "DUP4 @ 800": 2, - "DIV @ 3": 7, - "DUP4 @ 5": 7, - "MUL @ 2": 7, - "SWAP1 @ 5": 13, - "DIV @ 2": 6, - "ADD @ 2": 8, - "JUMPDEST @ 2": 2, - "ISZERO @ -306984": 1, - "PUSH6 @ 2": 1, - "DUP10 @ 3": 3, - "SUB @ 2": 5, - "DUP4 @ 2": 2, - "DUP9 @ 3": 5, - "SWAP4 @ 6": 4, - "PUSH8 @ 3": 5, - "SWAP3 @ 1": 6, - "SWAP5 @ 1": 3, - "POP @ 6": 1, - "DUP5 @ 2": 2, - "DUP11 @ 3": 2, - "DUP5 @ 1": 2, - "SWAP6 @ 1": 4, - "SWAP5 @ 3": 6, - "DUP15 @ 3": 1, - "PUSH1 @ 5000": 2, - "DUP14 @ 3": 1, - "SWAP1 @ 6": 2, - "PUSH32 @ 2": 1, - "LOG1 @ 3": 2, - "PUSH1 @ 1774": 1, - "SWAP14 @ 3": 1, - "CALLER @ 3": 1, - "ADDRESS @ 3": 5, - "CALL @ 2": 2, - "PUSH1 @ 307417": 1, - "JUMPDEST @ 800": 1, - "ISZERO @ -306717": 1, - "EQ @ 800": 1, - "PUSH1 @ 307290": 1, - "ISZERO @ -306590": 1, - "ADDRESS @ 6": 1, - "PUSH1 @ 307200": 1, - "ISZERO @ -306500": 1, - "SWAP2 @ 7": 1, - "PUSH1 @ 307152": 1, - "PUSH22 @ 9": 1, - "CALLER @ 42": 2, - "DUP3 @ 2": 2, - "PUSH2 @ 800": 5, - "SWAP5 @ 42": 1, - "DUP4 @ 5000": 1, - "PUSH20 @ 6": 1, - "SWAP3 @ 6": 1, - "SWAP6 @ 42": 1, - "DUP5 @ 5000": 1, - "PUSH16 @ 6": 1, - "SWAP5 @ 2": 1, - "SWAP4 @ 42": 1, - "SWAP2 @ 5000": 1, - "PUSH32 @ 3": 2, - "LOG3 @ 3": 2, - "POP @ 1756": 2, - "ISZERO @ -306452": 1, - "RETURNDATACOPY @ 3": 2, - "PUSH1 @ 306770": 1, - "ISZERO @ -306070": 1, - "SWAP8 @ 1": 1, - "SWAP7 @ 3": 1, - "SWAP2 @ 42": 1, - "MLOAD @ 5000": 1, - "PUSH1 @ 1518": 1, - "CODECOPY @ 3": 1, - "DUP2 @ 6": 1, - "JUMP @ 800": 1, - "SWAP2 @ -312131": 1, - "RETURNDATASIZE @ 2": 1, - "PUSH2 @ 6": 1, - "SWAP2 @ 2": 2 - } - }, - "second mint, no interest accrued": { - "fee": 61306, - "opcodes": {} - }, - "redeem": { - "fee": 95058, - "opcodes": {} - }, - "unitroller-g6 second mint with comp accrued": { - "fee": 138680, - "opcodes": {} - }, - "unitroller-g6 claim comp": { - "fee": 142459, - "opcodes": {} - }, - "unitroller second mint with comp accrued": { - "fee": 116271, - "opcodes": {} - }, - "unitroller claim comp": { - "fee": 155422, - "opcodes": {} - } -} diff --git a/jest.config.js b/jest.config.js deleted file mode 100644 index 2863ba90d..000000000 --- a/jest.config.js +++ /dev/null @@ -1,185 +0,0 @@ -// For a detailed explanation regarding each configuration property, visit: -// https://jestjs.io/docs/en/configuration.html - -module.exports = { - // All imported modules in your tests should be mocked automatically - // automock: false, - - // Stop running tests after `n` failures - // bail: 0, - - // Respect "browser" field in package.json when resolving modules - // browser: false, - - // The directory where Jest should store its cached dependency information - // cacheDirectory: "/private/var/folders/jz/z56b1n2902584b4zplqztm3m0000gn/T/jest_dx", - - // Automatically clear mock calls and instances between every test - // clearMocks: false, - - // Indicates whether the coverage information should be collected while executing the test - // collectCoverage: false, - - // An array of glob patterns indicating a set of files for which coverage information should be collected - // collectCoverageFrom: null, - - // The directory where Jest should output its coverage files - // coverageDirectory: null, - - // An array of regexp pattern strings used to skip coverage collection - // coveragePathIgnorePatterns: [ - // "/node_modules/" - // ], - - // A list of reporter names that Jest uses when writing coverage reports - // coverageReporters: [ - // "json", - // "text", - // "lcov", - // "clover" - // ], - - // An object that configures minimum threshold enforcement for coverage results - // coverageThreshold: null, - - // A path to a custom dependency extractor - // dependencyExtractor: null, - - // Make calling deprecated APIs throw helpful error messages - // errorOnDeprecated: false, - - // Force coverage collection from ignored files using an array of glob patterns - // forceCoverageMatch: [], - - // A path to a module which exports an async function that is triggered once before all test suites - // globalSetup: null, - - // A path to a module which exports an async function that is triggered once after all test suites - // globalTeardown: null, - - // A set of global variables that need to be available in all test environments - // globals: {}, - - // An array of directory names to be searched recursively up from the requiring module's location - // moduleDirectories: [ - // "node_modules" - // ], - - // An array of file extensions your modules use - // moduleFileExtensions: [ - // "js", - // "json", - // "jsx", - // "ts", - // "tsx", - // "node" - // ], - - // A map from regular expressions to module names that allow to stub out resources with a single module - // moduleNameMapper: {}, - - // An array of regexp pattern strings, matched against all module paths before considered 'visible' to the module loader - // modulePathIgnorePatterns: [], - - // Activates notifications for test results - // notify: false, - - // An enum that specifies notification mode. Requires { notify: true } - // notifyMode: "failure-change", - - // A preset that is used as a base for Jest's configuration - // preset: null, - - // Run tests from one or more projects - // projects: null, - - // Use this configuration option to add custom reporters to Jest - reporters: ["default", "jest-junit"], - - // Automatically reset mock state between every test - // resetMocks: false, - - // Reset the module registry before running each individual test - // resetModules: false, - - // A path to a custom resolver - // resolver: null, - - // Automatically restore mock state between every test - // restoreMocks: false, - - // The root directory that Jest should scan for tests and modules within - // rootDir: null, - - // A list of paths to directories that Jest should use to search for files in - // roots: [ - // "" - // ], - - // Allows you to use a custom runner instead of Jest's default test runner - // runner: "jest-runner", - - // The paths to modules that run some code to configure or set up the testing environment before each test - // setupFiles: [], - - // A list of paths to modules that run some code to configure or set up the testing framework before each test - setupFilesAfterEnv: ["/tests/Matchers.js", "/tests/Jest.js"], - - // A list of paths to snapshot serializer modules Jest should use for snapshot testing - // snapshotSerializers: [], - - // The test environment that will be used for testing - testEnvironment: "node", - - // Options that will be passed to the testEnvironment - // testEnvironmentOptions: {}, - - // Adds a location field to test results - // testLocationInResults: false, - - // The glob patterns Jest uses to detect test files - // testMatch: [ - // "**/__tests__/**/*.[jt]s?(x)", - // "**/?(*.)+(spec|test).[tj]s?(x)" - // ], - - // An array of regexp pattern strings that are matched against all test paths, matched tests are skipped - // testPathIgnorePatterns: [ - // "/node_modules/" - // ], - - // The regexp pattern or array of patterns that Jest uses to detect test files - // testRegex: [], - - // This option allows the use of a custom results processor - // testResultsProcessor: null, - - // This option allows use of a custom test runner - // testRunner: "jasmine2", - - // This option sets the URL for the jsdom environment. It is reflected in properties such as location.href - // testURL: "http://localhost", - - // Setting this value to "fake" allows the use of fake timers for functions such as "setTimeout" - // timers: "real", - - // A map from regular expressions to paths to transformers - // transform: null, - - // An array of regexp pattern strings that are matched against all source file paths, matched files will skip transformation - // transformIgnorePatterns: [ - // "/node_modules/" - // ], - - // An array of regexp pattern strings that are matched against all modules before the module loader will automatically return a mock for them - // unmockedModulePathPatterns: undefined, - - // Indicates whether each individual test should be reported during the run - // verbose: null, - - // An array of regexp patterns that are matched against all source file paths before re-running tests in watch mode - // watchPathIgnorePatterns: [], - - // Whether to use watchman for file crawling - // watchman: true, -}; diff --git a/reporterConfig.json b/reporterConfig.json deleted file mode 100644 index 8facae3fe..000000000 --- a/reporterConfig.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "reporterEnabled": "spec, mocha-junit-reporter" -} diff --git a/script/README.md b/script/README.md deleted file mode 100644 index 01c920da1..000000000 --- a/script/README.md +++ /dev/null @@ -1 +0,0 @@ -Scripts to make common developer tasks easy to type. diff --git a/script/comptroller-abi b/script/comptroller-abi deleted file mode 100755 index 436bf7b99..000000000 --- a/script/comptroller-abi +++ /dev/null @@ -1,33 +0,0 @@ -#!/usr/bin/env node - -const fs = require('fs') - -function mergeInterface(into, from) { - const key = (item) => item.inputs ? `${item.name}/${item.inputs.length}` : item.name; - const existing = into.reduce((acc, item) => { - acc[key(item)] = true; - return acc; - }, {}); - const extended = from.reduce((acc, item) => { - if (!(key(item) in existing)) - acc.push(item) - return acc; - }, into.slice()); - return into.concat(from) -} - -function mergeComptroller(abi) { - abi.Comptroller = mergeInterface(abi.Unitroller, abi[`Comptroller`]) - return abi; -} - -function format(abi) { - return JSON.stringify(abi, null, 4).replace(/^( {4}".*?)$/mg, '\n$1') -} - -function main(path) { - const abi = JSON.parse(fs.readFileSync(path)) - fs.writeFileSync(path, format(mergeComptroller(abi))) -} - -main('networks/mainnet-abi.json') From add695693f9e835835e8e53a83dce81aaddfe29e Mon Sep 17 00:00:00 2001 From: GitGuru7 <128375421+GitGuru7@users.noreply.github.com> Date: Tue, 26 Sep 2023 15:04:21 +0530 Subject: [PATCH 08/33] feat: add SnBNB market deployments --- .../RewardsDistributor_LiquidStakedBNB_4.json | 1270 +++++++++++++++++ ...dsDistributor_LiquidStakedBNB_4_Proxy.json | 277 ++++ .../VToken_vSnBNB_LiquidStakedBNB.json | 246 ++++ .../6d4db51b84097a74598623a15df3d6fb.json | 285 ++++ deployments/bsctestnet/MockSnBNB.json | 450 ++++++ .../RewardsDistributor_LiquidStakedBNB_4.json | 1270 +++++++++++++++++ ...dsDistributor_LiquidStakedBNB_4_Proxy.json | 277 ++++ .../VToken_vSnBNB_LiquidStakedBNB.json | 246 ++++ .../6d4db51b84097a74598623a15df3d6fb.json | 285 ++++ helpers/deploymentConfig.ts | 60 + 10 files changed, 4666 insertions(+) create mode 100644 deployments/bscmainnet/RewardsDistributor_LiquidStakedBNB_4.json create mode 100644 deployments/bscmainnet/RewardsDistributor_LiquidStakedBNB_4_Proxy.json create mode 100644 deployments/bscmainnet/VToken_vSnBNB_LiquidStakedBNB.json create mode 100644 deployments/bscmainnet/solcInputs/6d4db51b84097a74598623a15df3d6fb.json create mode 100644 deployments/bsctestnet/MockSnBNB.json create mode 100644 deployments/bsctestnet/RewardsDistributor_LiquidStakedBNB_4.json create mode 100644 deployments/bsctestnet/RewardsDistributor_LiquidStakedBNB_4_Proxy.json create mode 100644 deployments/bsctestnet/VToken_vSnBNB_LiquidStakedBNB.json create mode 100644 deployments/bsctestnet/solcInputs/6d4db51b84097a74598623a15df3d6fb.json diff --git a/deployments/bscmainnet/RewardsDistributor_LiquidStakedBNB_4.json b/deployments/bscmainnet/RewardsDistributor_LiquidStakedBNB_4.json new file mode 100644 index 000000000..b2ed33ed3 --- /dev/null +++ b/deployments/bscmainnet/RewardsDistributor_LiquidStakedBNB_4.json @@ -0,0 +1,1270 @@ +{ + "address": "0x888E317606b4c590BBAD88653863e8B345702633", + "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": "0x0adee9dd4ed4c9d28a6efa7e441e287050e94bad78b9524f5d3646a777aa7633", + "receipt": { + "to": null, + "from": "0x12Bdf8Ae9fE2047809080412d7341044b910ef10", + "contractAddress": "0x888E317606b4c590BBAD88653863e8B345702633", + "transactionIndex": 82, + "gasUsed": "865817", + "logsBloom": "0x00000000000000000000000000000000400000000000000000808000000000000000000000000000000000000000000000000000000000000000000000008000000000000000100000000000000002000001000000000000000000000000000000000000020000000000000000000800000000800000000000000000000000400000000000000000000010000000000000000000000084040000000000800000000000000000000000002000000400000000000000800000000000000000000000000020000000000000000001040000000200000400080000000000000220000000000200000000000000000000000000040800000000000000000000000000", + "blockHash": "0x3e223d8a6345efdb153c31646108023aefa1356fbfd53d96e05a93fb7668775b", + "transactionHash": "0x0adee9dd4ed4c9d28a6efa7e441e287050e94bad78b9524f5d3646a777aa7633", + "logs": [ + { + "transactionIndex": 82, + "blockNumber": 32073468, + "transactionHash": "0x0adee9dd4ed4c9d28a6efa7e441e287050e94bad78b9524f5d3646a777aa7633", + "address": "0x888E317606b4c590BBAD88653863e8B345702633", + "topics": [ + "0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b", + "0x00000000000000000000000001251d4ef6bb9f56c8bef7d3a201f00f4c122589" + ], + "data": "0x", + "logIndex": 182, + "blockHash": "0x3e223d8a6345efdb153c31646108023aefa1356fbfd53d96e05a93fb7668775b" + }, + { + "transactionIndex": 82, + "blockNumber": 32073468, + "transactionHash": "0x0adee9dd4ed4c9d28a6efa7e441e287050e94bad78b9524f5d3646a777aa7633", + "address": "0x888E317606b4c590BBAD88653863e8B345702633", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x00000000000000000000000012bdf8ae9fe2047809080412d7341044b910ef10" + ], + "data": "0x", + "logIndex": 183, + "blockHash": "0x3e223d8a6345efdb153c31646108023aefa1356fbfd53d96e05a93fb7668775b" + }, + { + "transactionIndex": 82, + "blockNumber": 32073468, + "transactionHash": "0x0adee9dd4ed4c9d28a6efa7e441e287050e94bad78b9524f5d3646a777aa7633", + "address": "0x888E317606b4c590BBAD88653863e8B345702633", + "topics": ["0x66fd58e82f7b31a2a5c30e0888f3093efe4e111b00cd2b0c31fe014601293aa0"], + "data": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000004788629abc6cfca10f9f969efdeaa1cf70c23555", + "logIndex": 184, + "blockHash": "0x3e223d8a6345efdb153c31646108023aefa1356fbfd53d96e05a93fb7668775b" + }, + { + "transactionIndex": 82, + "blockNumber": 32073468, + "transactionHash": "0x0adee9dd4ed4c9d28a6efa7e441e287050e94bad78b9524f5d3646a777aa7633", + "address": "0x888E317606b4c590BBAD88653863e8B345702633", + "topics": ["0xc2d09fef144f7c8a86f71ea459f8fc17f675768eb1ae369cbd77fb31d467aafa"], + "data": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000064", + "logIndex": 185, + "blockHash": "0x3e223d8a6345efdb153c31646108023aefa1356fbfd53d96e05a93fb7668775b" + }, + { + "transactionIndex": 82, + "blockNumber": 32073468, + "transactionHash": "0x0adee9dd4ed4c9d28a6efa7e441e287050e94bad78b9524f5d3646a777aa7633", + "address": "0x888E317606b4c590BBAD88653863e8B345702633", + "topics": ["0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498"], + "data": "0x0000000000000000000000000000000000000000000000000000000000000001", + "logIndex": 186, + "blockHash": "0x3e223d8a6345efdb153c31646108023aefa1356fbfd53d96e05a93fb7668775b" + }, + { + "transactionIndex": 82, + "blockNumber": 32073468, + "transactionHash": "0x0adee9dd4ed4c9d28a6efa7e441e287050e94bad78b9524f5d3646a777aa7633", + "address": "0x888E317606b4c590BBAD88653863e8B345702633", + "topics": ["0x7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f"], + "data": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000006beb6d2695b67feb73ad4f172e8e2975497187e4", + "logIndex": 187, + "blockHash": "0x3e223d8a6345efdb153c31646108023aefa1356fbfd53d96e05a93fb7668775b" + } + ], + "blockNumber": 32073468, + "cumulativeGasUsed": "10321529", + "status": 1, + "byzantium": true + }, + "args": [ + "0x01251D4eF6bb9f56C8Bef7D3A201f00f4C122589", + "0x6beb6D2695B67FEb73ad4f172E8E2975497187e4", + "0xbe203094000000000000000000000000d933909a4a2b7a4638903028f44d1d38ce27c3520000000000000000000000000782b6d8c4551b9760e74c0545a9bcd90bdc41e500000000000000000000000000000000000000000000000000000000000000640000000000000000000000004788629abc6cfca10f9f969efdeaa1cf70c23555" + ], + "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": [ + "0xd933909A4a2b7A4638903028f44D1d38ce27c352", + "0x0782b6d8c4551B9760e74c0545a9bCD90bdc41E5", + 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/RewardsDistributor_LiquidStakedBNB_4_Proxy.json b/deployments/bscmainnet/RewardsDistributor_LiquidStakedBNB_4_Proxy.json new file mode 100644 index 000000000..f55dbafae --- /dev/null +++ b/deployments/bscmainnet/RewardsDistributor_LiquidStakedBNB_4_Proxy.json @@ -0,0 +1,277 @@ +{ + "address": "0x888E317606b4c590BBAD88653863e8B345702633", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_logic", + "type": "address" + }, + { + "internalType": "address", + "name": "admin_", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "stateMutability": "payable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "previousAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beacon", + "type": "address" + } + ], + "name": "BeaconUpgraded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "admin_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "changeAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "implementation_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "upgradeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "upgradeToAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "transactionHash": "0x0adee9dd4ed4c9d28a6efa7e441e287050e94bad78b9524f5d3646a777aa7633", + "receipt": { + "to": null, + "from": "0x12Bdf8Ae9fE2047809080412d7341044b910ef10", + "contractAddress": "0x888E317606b4c590BBAD88653863e8B345702633", + "transactionIndex": 82, + "gasUsed": "865817", + "logsBloom": "0x00000000000000000000000000000000400000000000000000808000000000000000000000000000000000000000000000000000000000000000000000008000000000000000100000000000000002000001000000000000000000000000000000000000020000000000000000000800000000800000000000000000000000400000000000000000000010000000000000000000000084040000000000800000000000000000000000002000000400000000000000800000000000000000000000000020000000000000000001040000000200000400080000000000000220000000000200000000000000000000000000040800000000000000000000000000", + "blockHash": "0x3e223d8a6345efdb153c31646108023aefa1356fbfd53d96e05a93fb7668775b", + "transactionHash": "0x0adee9dd4ed4c9d28a6efa7e441e287050e94bad78b9524f5d3646a777aa7633", + "logs": [ + { + "transactionIndex": 82, + "blockNumber": 32073468, + "transactionHash": "0x0adee9dd4ed4c9d28a6efa7e441e287050e94bad78b9524f5d3646a777aa7633", + "address": "0x888E317606b4c590BBAD88653863e8B345702633", + "topics": [ + "0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b", + "0x00000000000000000000000001251d4ef6bb9f56c8bef7d3a201f00f4c122589" + ], + "data": "0x", + "logIndex": 182, + "blockHash": "0x3e223d8a6345efdb153c31646108023aefa1356fbfd53d96e05a93fb7668775b" + }, + { + "transactionIndex": 82, + "blockNumber": 32073468, + "transactionHash": "0x0adee9dd4ed4c9d28a6efa7e441e287050e94bad78b9524f5d3646a777aa7633", + "address": "0x888E317606b4c590BBAD88653863e8B345702633", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x00000000000000000000000012bdf8ae9fe2047809080412d7341044b910ef10" + ], + "data": "0x", + "logIndex": 183, + "blockHash": "0x3e223d8a6345efdb153c31646108023aefa1356fbfd53d96e05a93fb7668775b" + }, + { + "transactionIndex": 82, + "blockNumber": 32073468, + "transactionHash": "0x0adee9dd4ed4c9d28a6efa7e441e287050e94bad78b9524f5d3646a777aa7633", + "address": "0x888E317606b4c590BBAD88653863e8B345702633", + "topics": ["0x66fd58e82f7b31a2a5c30e0888f3093efe4e111b00cd2b0c31fe014601293aa0"], + "data": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000004788629abc6cfca10f9f969efdeaa1cf70c23555", + "logIndex": 184, + "blockHash": "0x3e223d8a6345efdb153c31646108023aefa1356fbfd53d96e05a93fb7668775b" + }, + { + "transactionIndex": 82, + "blockNumber": 32073468, + "transactionHash": "0x0adee9dd4ed4c9d28a6efa7e441e287050e94bad78b9524f5d3646a777aa7633", + "address": "0x888E317606b4c590BBAD88653863e8B345702633", + "topics": ["0xc2d09fef144f7c8a86f71ea459f8fc17f675768eb1ae369cbd77fb31d467aafa"], + "data": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000064", + "logIndex": 185, + "blockHash": "0x3e223d8a6345efdb153c31646108023aefa1356fbfd53d96e05a93fb7668775b" + }, + { + "transactionIndex": 82, + "blockNumber": 32073468, + "transactionHash": "0x0adee9dd4ed4c9d28a6efa7e441e287050e94bad78b9524f5d3646a777aa7633", + "address": "0x888E317606b4c590BBAD88653863e8B345702633", + "topics": ["0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498"], + "data": "0x0000000000000000000000000000000000000000000000000000000000000001", + "logIndex": 186, + "blockHash": "0x3e223d8a6345efdb153c31646108023aefa1356fbfd53d96e05a93fb7668775b" + }, + { + "transactionIndex": 82, + "blockNumber": 32073468, + "transactionHash": "0x0adee9dd4ed4c9d28a6efa7e441e287050e94bad78b9524f5d3646a777aa7633", + "address": "0x888E317606b4c590BBAD88653863e8B345702633", + "topics": ["0x7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f"], + "data": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000006beb6d2695b67feb73ad4f172e8e2975497187e4", + "logIndex": 187, + "blockHash": "0x3e223d8a6345efdb153c31646108023aefa1356fbfd53d96e05a93fb7668775b" + } + ], + "blockNumber": 32073468, + "cumulativeGasUsed": "10321529", + "status": 1, + "byzantium": true + }, + "args": [ + "0x01251D4eF6bb9f56C8Bef7D3A201f00f4C122589", + "0x6beb6D2695B67FEb73ad4f172E8E2975497187e4", + "0xbe203094000000000000000000000000d933909a4a2b7a4638903028f44d1d38ce27c3520000000000000000000000000782b6d8c4551b9760e74c0545a9bcd90bdc41e500000000000000000000000000000000000000000000000000000000000000640000000000000000000000004788629abc6cfca10f9f969efdeaa1cf70c23555" + ], + "numDeployments": 1, + "solcInputHash": "0e89febeebc7444140de8e67c9067d2c", + "metadata": "{\"compiler\":{\"version\":\"0.8.10+commit.fc410830\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_logic\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"admin_\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"previousAdmin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\"}],\"name\":\"AdminChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"beacon\",\"type\":\"address\"}],\"name\":\"BeaconUpgraded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"implementation\",\"type\":\"address\"}],\"name\":\"Upgraded\",\"type\":\"event\"},{\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"inputs\":[],\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"admin_\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\"}],\"name\":\"changeAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"implementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"implementation_\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newImplementation\",\"type\":\"address\"}],\"name\":\"upgradeTo\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newImplementation\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"upgradeToAndCall\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"details\":\"This contract implements a proxy that is upgradeable by an admin. To avoid https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector clashing], which can potentially be used in an attack, this contract uses the https://blog.openzeppelin.com/the-transparent-proxy-pattern/[transparent proxy pattern]. This pattern implies two things that go hand in hand: 1. If any account other than the admin calls the proxy, the call will be forwarded to the implementation, even if that call matches one of the admin functions exposed by the proxy itself. 2. If the admin calls the proxy, it can access the admin functions, but its calls will never be forwarded to the implementation. If the admin tries to call a function on the implementation it will fail with an error that says \\\"admin cannot fallback to proxy target\\\". These properties mean that the admin account can only be used for admin actions like upgrading the proxy or changing the admin, so it's best if it's a dedicated account that is not used for anything else. This will avoid headaches due to sudden errors when trying to call a function from the proxy implementation. Our recommendation is for the dedicated account to be an instance of the {ProxyAdmin} contract. If set up this way, you should think of the `ProxyAdmin` instance as the real administrative interface of your proxy.\",\"kind\":\"dev\",\"methods\":{\"admin()\":{\"details\":\"Returns the current admin. NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyAdmin}. TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call. `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`\"},\"changeAdmin(address)\":{\"details\":\"Changes the admin of the proxy. Emits an {AdminChanged} event. NOTE: Only the admin can call this function. See {ProxyAdmin-changeProxyAdmin}.\"},\"constructor\":{\"details\":\"Initializes an upgradeable proxy managed by `_admin`, backed by the implementation at `_logic`, and optionally initialized with `_data` as explained in {ERC1967Proxy-constructor}.\"},\"implementation()\":{\"details\":\"Returns the current implementation. NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyImplementation}. TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call. `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc`\"},\"upgradeTo(address)\":{\"details\":\"Upgrade the implementation of the proxy. NOTE: Only the admin can call this function. See {ProxyAdmin-upgrade}.\"},\"upgradeToAndCall(address,bytes)\":{\"details\":\"Upgrade the implementation of the proxy, and then call a function from the new implementation as specified by `data`, which should be an encoded function call. This is useful to initialize new storage variables in the proxied contract. NOTE: Only the admin can call this function. See {ProxyAdmin-upgradeAndCall}.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solc_0.8/openzeppelin/proxy/transparent/TransparentUpgradeableProxy.sol\":\"TransparentUpgradeableProxy\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":999999},\"remappings\":[]},\"sources\":{\"solc_0.8/openzeppelin/interfaces/draft-IERC1822.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (interfaces/draft-IERC1822.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified\\n * proxy whose upgrades are fully controlled by the current implementation.\\n */\\ninterface IERC1822Proxiable {\\n /**\\n * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation\\n * address.\\n *\\n * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks\\n * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this\\n * function revert if invoked through a proxy.\\n */\\n function proxiableUUID() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0x93b4e21c931252739a1ec13ea31d3d35a5c068be3163ccab83e4d70c40355f03\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/proxy/ERC1967/ERC1967Proxy.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (proxy/ERC1967/ERC1967Proxy.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../Proxy.sol\\\";\\nimport \\\"./ERC1967Upgrade.sol\\\";\\n\\n/**\\n * @dev This contract implements an upgradeable proxy. It is upgradeable because calls are delegated to an\\n * implementation address that can be changed. This address is stored in storage in the location specified by\\n * https://eips.ethereum.org/EIPS/eip-1967[EIP1967], so that it doesn't conflict with the storage layout of the\\n * implementation behind the proxy.\\n */\\ncontract ERC1967Proxy is Proxy, ERC1967Upgrade {\\n /**\\n * @dev Initializes the upgradeable proxy with an initial implementation specified by `_logic`.\\n *\\n * If `_data` is nonempty, it's used as data in a delegate call to `_logic`. This will typically be an encoded\\n * function call, and allows initializating the storage of the proxy like a Solidity constructor.\\n */\\n constructor(address _logic, bytes memory _data) payable {\\n assert(_IMPLEMENTATION_SLOT == bytes32(uint256(keccak256(\\\"eip1967.proxy.implementation\\\")) - 1));\\n _upgradeToAndCall(_logic, _data, false);\\n }\\n\\n /**\\n * @dev Returns the current implementation address.\\n */\\n function _implementation() internal view virtual override returns (address impl) {\\n return ERC1967Upgrade._getImplementation();\\n }\\n}\\n\",\"keccak256\":\"0x6309f9f39dc6f4f45a24f296543867aa358e32946cd6b2874627a996d606b3a0\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/proxy/ERC1967/ERC1967Upgrade.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (proxy/ERC1967/ERC1967Upgrade.sol)\\n\\npragma solidity ^0.8.2;\\n\\nimport \\\"../beacon/IBeacon.sol\\\";\\nimport \\\"../../interfaces/draft-IERC1822.sol\\\";\\nimport \\\"../../utils/Address.sol\\\";\\nimport \\\"../../utils/StorageSlot.sol\\\";\\n\\n/**\\n * @dev This abstract contract provides getters and event emitting update functions for\\n * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots.\\n *\\n * _Available since v4.1._\\n *\\n * @custom:oz-upgrades-unsafe-allow delegatecall\\n */\\nabstract contract ERC1967Upgrade {\\n // This is the keccak-256 hash of \\\"eip1967.proxy.rollback\\\" subtracted by 1\\n bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143;\\n\\n /**\\n * @dev Storage slot with the address of the current implementation.\\n * This is the keccak-256 hash of \\\"eip1967.proxy.implementation\\\" subtracted by 1, and is\\n * validated in the constructor.\\n */\\n bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\\n\\n /**\\n * @dev Emitted when the implementation is upgraded.\\n */\\n event Upgraded(address indexed implementation);\\n\\n /**\\n * @dev Returns the current implementation address.\\n */\\n function _getImplementation() internal view returns (address) {\\n return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\\n }\\n\\n /**\\n * @dev Stores a new address in the EIP1967 implementation slot.\\n */\\n function _setImplementation(address newImplementation) private {\\n require(Address.isContract(newImplementation), \\\"ERC1967: new implementation is not a contract\\\");\\n StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\\n }\\n\\n /**\\n * @dev Perform implementation upgrade\\n *\\n * Emits an {Upgraded} event.\\n */\\n function _upgradeTo(address newImplementation) internal {\\n _setImplementation(newImplementation);\\n emit Upgraded(newImplementation);\\n }\\n\\n /**\\n * @dev Perform implementation upgrade with additional setup call.\\n *\\n * Emits an {Upgraded} event.\\n */\\n function _upgradeToAndCall(\\n address newImplementation,\\n bytes memory data,\\n bool forceCall\\n ) internal {\\n _upgradeTo(newImplementation);\\n if (data.length > 0 || forceCall) {\\n Address.functionDelegateCall(newImplementation, data);\\n }\\n }\\n\\n /**\\n * @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call.\\n *\\n * Emits an {Upgraded} event.\\n */\\n function _upgradeToAndCallUUPS(\\n address newImplementation,\\n bytes memory data,\\n bool forceCall\\n ) internal {\\n // Upgrades from old implementations will perform a rollback test. This test requires the new\\n // implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing\\n // this special case will break upgrade paths from old UUPS implementation to new ones.\\n if (StorageSlot.getBooleanSlot(_ROLLBACK_SLOT).value) {\\n _setImplementation(newImplementation);\\n } else {\\n try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) {\\n require(slot == _IMPLEMENTATION_SLOT, \\\"ERC1967Upgrade: unsupported proxiableUUID\\\");\\n } catch {\\n revert(\\\"ERC1967Upgrade: new implementation is not UUPS\\\");\\n }\\n _upgradeToAndCall(newImplementation, data, forceCall);\\n }\\n }\\n\\n /**\\n * @dev Storage slot with the admin of the contract.\\n * This is the keccak-256 hash of \\\"eip1967.proxy.admin\\\" subtracted by 1, and is\\n * validated in the constructor.\\n */\\n bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;\\n\\n /**\\n * @dev Emitted when the admin account has changed.\\n */\\n event AdminChanged(address previousAdmin, address newAdmin);\\n\\n /**\\n * @dev Returns the current admin.\\n */\\n function _getAdmin() internal view virtual returns (address) {\\n return StorageSlot.getAddressSlot(_ADMIN_SLOT).value;\\n }\\n\\n /**\\n * @dev Stores a new address in the EIP1967 admin slot.\\n */\\n function _setAdmin(address newAdmin) private {\\n require(newAdmin != address(0), \\\"ERC1967: new admin is the zero address\\\");\\n StorageSlot.getAddressSlot(_ADMIN_SLOT).value = newAdmin;\\n }\\n\\n /**\\n * @dev Changes the admin of the proxy.\\n *\\n * Emits an {AdminChanged} event.\\n */\\n function _changeAdmin(address newAdmin) internal {\\n emit AdminChanged(_getAdmin(), newAdmin);\\n _setAdmin(newAdmin);\\n }\\n\\n /**\\n * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.\\n * This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor.\\n */\\n bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;\\n\\n /**\\n * @dev Emitted when the beacon is upgraded.\\n */\\n event BeaconUpgraded(address indexed beacon);\\n\\n /**\\n * @dev Returns the current beacon.\\n */\\n function _getBeacon() internal view returns (address) {\\n return StorageSlot.getAddressSlot(_BEACON_SLOT).value;\\n }\\n\\n /**\\n * @dev Stores a new beacon in the EIP1967 beacon slot.\\n */\\n function _setBeacon(address newBeacon) private {\\n require(Address.isContract(newBeacon), \\\"ERC1967: new beacon is not a contract\\\");\\n require(Address.isContract(IBeacon(newBeacon).implementation()), \\\"ERC1967: beacon implementation is not a contract\\\");\\n StorageSlot.getAddressSlot(_BEACON_SLOT).value = newBeacon;\\n }\\n\\n /**\\n * @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does\\n * not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that).\\n *\\n * Emits a {BeaconUpgraded} event.\\n */\\n function _upgradeBeaconToAndCall(\\n address newBeacon,\\n bytes memory data,\\n bool forceCall\\n ) internal {\\n _setBeacon(newBeacon);\\n emit BeaconUpgraded(newBeacon);\\n if (data.length > 0 || forceCall) {\\n Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x17668652127feebed0ce8d9431ef95ccc8c4292f03e3b8cf06c6ca16af396633\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/proxy/Proxy.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (proxy/Proxy.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM\\n * instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to\\n * be specified by overriding the virtual {_implementation} function.\\n *\\n * Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a\\n * different contract through the {_delegate} function.\\n *\\n * The success and return data of the delegated call will be returned back to the caller of the proxy.\\n */\\nabstract contract Proxy {\\n /**\\n * @dev Delegates the current call to `implementation`.\\n *\\n * This function does not return to its internal call site, it will return directly to the external caller.\\n */\\n function _delegate(address implementation) internal virtual {\\n assembly {\\n // Copy msg.data. We take full control of memory in this inline assembly\\n // block because it will not return to Solidity code. We overwrite the\\n // Solidity scratch pad at memory position 0.\\n calldatacopy(0, 0, calldatasize())\\n\\n // Call the implementation.\\n // out and outsize are 0 because we don't know the size yet.\\n let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)\\n\\n // Copy the returned data.\\n returndatacopy(0, 0, returndatasize())\\n\\n switch result\\n // delegatecall returns 0 on error.\\n case 0 {\\n revert(0, returndatasize())\\n }\\n default {\\n return(0, returndatasize())\\n }\\n }\\n }\\n\\n /**\\n * @dev This is a virtual function that should be overriden so it returns the address to which the fallback function\\n * and {_fallback} should delegate.\\n */\\n function _implementation() internal view virtual returns (address);\\n\\n /**\\n * @dev Delegates the current call to the address returned by `_implementation()`.\\n *\\n * This function does not return to its internall call site, it will return directly to the external caller.\\n */\\n function _fallback() internal virtual {\\n _beforeFallback();\\n _delegate(_implementation());\\n }\\n\\n /**\\n * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other\\n * function in the contract matches the call data.\\n */\\n fallback() external payable virtual {\\n _fallback();\\n }\\n\\n /**\\n * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if call data\\n * is empty.\\n */\\n receive() external payable virtual {\\n _fallback();\\n }\\n\\n /**\\n * @dev Hook that is called before falling back to the implementation. Can happen as part of a manual `_fallback`\\n * call, or as part of the Solidity `fallback` or `receive` functions.\\n *\\n * If overriden should call `super._beforeFallback()`.\\n */\\n function _beforeFallback() internal virtual {}\\n}\\n\",\"keccak256\":\"0xd5d1fd16e9faff7fcb3a52e02a8d49156f42a38a03f07b5f1810c21c2149a8ab\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/proxy/beacon/IBeacon.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev This is the interface that {BeaconProxy} expects of its beacon.\\n */\\ninterface IBeacon {\\n /**\\n * @dev Must return an address that can be used as a delegate call target.\\n *\\n * {BeaconProxy} will check that this address is a contract.\\n */\\n function implementation() external view returns (address);\\n}\\n\",\"keccak256\":\"0xd50a3421ac379ccb1be435fa646d66a65c986b4924f0849839f08692f39dde61\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/proxy/transparent/TransparentUpgradeableProxy.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (proxy/transparent/TransparentUpgradeableProxy.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../ERC1967/ERC1967Proxy.sol\\\";\\n\\n/**\\n * @dev This contract implements a proxy that is upgradeable by an admin.\\n *\\n * To avoid https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector\\n * clashing], which can potentially be used in an attack, this contract uses the\\n * https://blog.openzeppelin.com/the-transparent-proxy-pattern/[transparent proxy pattern]. This pattern implies two\\n * things that go hand in hand:\\n *\\n * 1. If any account other than the admin calls the proxy, the call will be forwarded to the implementation, even if\\n * that call matches one of the admin functions exposed by the proxy itself.\\n * 2. If the admin calls the proxy, it can access the admin functions, but its calls will never be forwarded to the\\n * implementation. If the admin tries to call a function on the implementation it will fail with an error that says\\n * \\\"admin cannot fallback to proxy target\\\".\\n *\\n * These properties mean that the admin account can only be used for admin actions like upgrading the proxy or changing\\n * the admin, so it's best if it's a dedicated account that is not used for anything else. This will avoid headaches due\\n * to sudden errors when trying to call a function from the proxy implementation.\\n *\\n * Our recommendation is for the dedicated account to be an instance of the {ProxyAdmin} contract. If set up this way,\\n * you should think of the `ProxyAdmin` instance as the real administrative interface of your proxy.\\n */\\ncontract TransparentUpgradeableProxy is ERC1967Proxy {\\n /**\\n * @dev Initializes an upgradeable proxy managed by `_admin`, backed by the implementation at `_logic`, and\\n * optionally initialized with `_data` as explained in {ERC1967Proxy-constructor}.\\n */\\n constructor(\\n address _logic,\\n address admin_,\\n bytes memory _data\\n ) payable ERC1967Proxy(_logic, _data) {\\n assert(_ADMIN_SLOT == bytes32(uint256(keccak256(\\\"eip1967.proxy.admin\\\")) - 1));\\n _changeAdmin(admin_);\\n }\\n\\n /**\\n * @dev Modifier used internally that will delegate the call to the implementation unless the sender is the admin.\\n */\\n modifier ifAdmin() {\\n if (msg.sender == _getAdmin()) {\\n _;\\n } else {\\n _fallback();\\n }\\n }\\n\\n /**\\n * @dev Returns the current admin.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyAdmin}.\\n *\\n * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the\\n * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.\\n * `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`\\n */\\n function admin() external ifAdmin returns (address admin_) {\\n admin_ = _getAdmin();\\n }\\n\\n /**\\n * @dev Returns the current implementation.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyImplementation}.\\n *\\n * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the\\n * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.\\n * `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc`\\n */\\n function implementation() external ifAdmin returns (address implementation_) {\\n implementation_ = _implementation();\\n }\\n\\n /**\\n * @dev Changes the admin of the proxy.\\n *\\n * Emits an {AdminChanged} event.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-changeProxyAdmin}.\\n */\\n function changeAdmin(address newAdmin) external virtual ifAdmin {\\n _changeAdmin(newAdmin);\\n }\\n\\n /**\\n * @dev Upgrade the implementation of the proxy.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-upgrade}.\\n */\\n function upgradeTo(address newImplementation) external ifAdmin {\\n _upgradeToAndCall(newImplementation, bytes(\\\"\\\"), false);\\n }\\n\\n /**\\n * @dev Upgrade the implementation of the proxy, and then call a function from the new implementation as specified\\n * by `data`, which should be an encoded function call. This is useful to initialize new storage variables in the\\n * proxied contract.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-upgradeAndCall}.\\n */\\n function upgradeToAndCall(address newImplementation, bytes calldata data) external payable ifAdmin {\\n _upgradeToAndCall(newImplementation, data, true);\\n }\\n\\n /**\\n * @dev Returns the current admin.\\n */\\n function _admin() internal view virtual returns (address) {\\n return _getAdmin();\\n }\\n\\n /**\\n * @dev Makes sure the admin cannot access the fallback function. See {Proxy-_beforeFallback}.\\n */\\n function _beforeFallback() internal virtual override {\\n require(msg.sender != _getAdmin(), \\\"TransparentUpgradeableProxy: admin cannot fallback to proxy target\\\");\\n super._beforeFallback();\\n }\\n}\\n\",\"keccak256\":\"0x140055a64cf579d622e04f5a198595832bf2cb193cd0005f4f2d4d61ca906253\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x3777e696b62134e6177440dbe6e6601c0c156a443f57167194b67e75527439de\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/utils/StorageSlot.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/StorageSlot.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Library for reading and writing primitive types to specific storage slots.\\n *\\n * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.\\n * This library helps with reading and writing to such slots without the need for inline assembly.\\n *\\n * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.\\n *\\n * Example usage to set ERC1967 implementation slot:\\n * ```\\n * contract ERC1967 {\\n * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\\n *\\n * function _getImplementation() internal view returns (address) {\\n * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\\n * }\\n *\\n * function _setImplementation(address newImplementation) internal {\\n * require(Address.isContract(newImplementation), \\\"ERC1967: new implementation is not a contract\\\");\\n * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\\n * }\\n * }\\n * ```\\n *\\n * _Available since v4.1 for `address`, `bool`, `bytes32`, and `uint256`._\\n */\\nlibrary StorageSlot {\\n struct AddressSlot {\\n address value;\\n }\\n\\n struct BooleanSlot {\\n bool value;\\n }\\n\\n struct Bytes32Slot {\\n bytes32 value;\\n }\\n\\n struct Uint256Slot {\\n uint256 value;\\n }\\n\\n /**\\n * @dev Returns an `AddressSlot` with member `value` located at `slot`.\\n */\\n function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {\\n assembly {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `BooleanSlot` with member `value` located at `slot`.\\n */\\n function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {\\n assembly {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `Bytes32Slot` with member `value` located at `slot`.\\n */\\n function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {\\n assembly {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `Uint256Slot` with member `value` located at `slot`.\\n */\\n function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {\\n assembly {\\n r.slot := slot\\n }\\n }\\n}\\n\",\"keccak256\":\"0xfe1b7a9aa2a530a9e705b220e26cd584e2fbdc9602a3a1066032b12816b46aca\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x6080604052604051620011b2380380620011b2833981016040819052620000269162000519565b82816200005560017f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbd620005f9565b6000805160206200116b833981519152146200007557620000756200061f565b6200008382826000620000e7565b50620000b3905060017fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6104620005f9565b6000805160206200114b83398151915214620000d357620000d36200061f565b620000de8262000124565b50505062000688565b620000f2836200017f565b600082511180620001005750805b156200011f576200011d8383620001c160201b620002ff1760201c565b505b505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6200014f620001f0565b604080516001600160a01b03928316815291841660208301520160405180910390a16200017c8162000229565b50565b6200018a81620002de565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b6060620001e983836040518060600160405280602781526020016200118b6027913962000381565b9392505050565b60006200021a6000805160206200114b83398151915260001b6200046760201b620002731760201c565b546001600160a01b0316919050565b6001600160a01b038116620002945760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b60648201526084015b60405180910390fd5b80620002bd6000805160206200114b83398151915260001b6200046760201b620002731760201c565b80546001600160a01b0319166001600160a01b039290921691909117905550565b620002f4816200046a60201b6200032b1760201c565b620003585760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b60648201526084016200028b565b80620002bd6000805160206200116b83398151915260001b6200046760201b620002731760201c565b60606001600160a01b0384163b620003eb5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f6044820152651b9d1c9858dd60d21b60648201526084016200028b565b600080856001600160a01b03168560405162000408919062000635565b600060405180830381855af49150503d806000811462000445576040519150601f19603f3d011682016040523d82523d6000602084013e6200044a565b606091505b5090925090506200045d82828662000479565b9695505050505050565b90565b6001600160a01b03163b151590565b606083156200048a575081620001e9565b8251156200049b5782518084602001fd5b8160405162461bcd60e51b81526004016200028b919062000653565b80516001600160a01b0381168114620004cf57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60005b8381101562000507578181015183820152602001620004ed565b838111156200011d5750506000910152565b6000806000606084860312156200052f57600080fd5b6200053a84620004b7565b92506200054a60208501620004b7565b60408501519092506001600160401b03808211156200056857600080fd5b818601915086601f8301126200057d57600080fd5b815181811115620005925762000592620004d4565b604051601f8201601f19908116603f01168101908382118183101715620005bd57620005bd620004d4565b81604052828152896020848701011115620005d757600080fd5b620005ea836020830160208801620004ea565b80955050505050509250925092565b6000828210156200061a57634e487b7160e01b600052601160045260246000fd5b500390565b634e487b7160e01b600052600160045260246000fd5b6000825162000649818460208701620004ea565b9190910192915050565b602081526000825180602084015262000674816040850160208701620004ea565b601f01601f19169190910160400192915050565b610ab380620006986000396000f3fe60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100a85780638f283970146100e6578063f851a440146101065761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61011b565b005b61006b61011b565b34801561008157600080fd5b5061006b61009036600461091f565b610135565b61006b6100a336600461093a565b610196565b3480156100b457600080fd5b506100bd610221565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b3480156100f257600080fd5b5061006b61010136600461091f565b610276565b34801561011257600080fd5b506100bd6102ba565b610123610347565b61013361012e610435565b61043f565b565b61013d610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561018e5761018b816040518060200160405280600081525060006104a3565b50565b61018b61011b565b61019e610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415610219576102148383838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250600192506104a3915050565b505050565b61021461011b565b600061022b610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561026b57610266610435565b905090565b61027361011b565b90565b61027e610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561018e5761018b816104ce565b60006102c4610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561026b57610266610463565b60606103248383604051806060016040528060278152602001610a576027913961052f565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b61034f610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415610133576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f7879207461726760648201527f6574000000000000000000000000000000000000000000000000000000000000608482015260a4015b60405180910390fd5b6000610266610657565b3660008037600080366000845af43d6000803e80801561045e573d6000f35b3d6000fd5b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b5473ffffffffffffffffffffffffffffffffffffffff16919050565b6104ac8361067f565b6000825111806104b95750805b15610214576104c883836102ff565b50505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6104f7610463565b6040805173ffffffffffffffffffffffffffffffffffffffff928316815291841660208301520160405180910390a161018b816106cc565b606073ffffffffffffffffffffffffffffffffffffffff84163b6105d5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f60448201527f6e74726163740000000000000000000000000000000000000000000000000000606482015260840161042c565b6000808573ffffffffffffffffffffffffffffffffffffffff16856040516105fd91906109e9565b600060405180830381855af49150503d8060008114610638576040519150601f19603f3d011682016040523d82523d6000602084013e61063d565b606091505b509150915061064d8282866107d8565b9695505050505050565b60007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc610487565b6106888161082b565b60405173ffffffffffffffffffffffffffffffffffffffff8216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b73ffffffffffffffffffffffffffffffffffffffff811661076f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201527f6464726573730000000000000000000000000000000000000000000000000000606482015260840161042c565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9290921691909117905550565b606083156107e7575081610324565b8251156107f75782518084602001fd5b816040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161042c9190610a05565b73ffffffffffffffffffffffffffffffffffffffff81163b6108cf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201527f6f74206120636f6e747261637400000000000000000000000000000000000000606482015260840161042c565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc610792565b803573ffffffffffffffffffffffffffffffffffffffff8116811461091a57600080fd5b919050565b60006020828403121561093157600080fd5b610324826108f6565b60008060006040848603121561094f57600080fd5b610958846108f6565b9250602084013567ffffffffffffffff8082111561097557600080fd5b818601915086601f83011261098957600080fd5b81358181111561099857600080fd5b8760208285010111156109aa57600080fd5b6020830194508093505050509250925092565b60005b838110156109d85781810151838201526020016109c0565b838111156104c85750506000910152565b600082516109fb8184602087016109bd565b9190910192915050565b6020815260008251806020840152610a248160408501602087016109bd565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220b29caa54336b3ee836679675e9732ec5e526fb3f803cca2fe336cc3555aba62264736f6c634300080a0033b53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564", + "deployedBytecode": "0x60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100a85780638f283970146100e6578063f851a440146101065761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61011b565b005b61006b61011b565b34801561008157600080fd5b5061006b61009036600461091f565b610135565b61006b6100a336600461093a565b610196565b3480156100b457600080fd5b506100bd610221565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b3480156100f257600080fd5b5061006b61010136600461091f565b610276565b34801561011257600080fd5b506100bd6102ba565b610123610347565b61013361012e610435565b61043f565b565b61013d610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561018e5761018b816040518060200160405280600081525060006104a3565b50565b61018b61011b565b61019e610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415610219576102148383838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250600192506104a3915050565b505050565b61021461011b565b600061022b610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561026b57610266610435565b905090565b61027361011b565b90565b61027e610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561018e5761018b816104ce565b60006102c4610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561026b57610266610463565b60606103248383604051806060016040528060278152602001610a576027913961052f565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b61034f610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415610133576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f7879207461726760648201527f6574000000000000000000000000000000000000000000000000000000000000608482015260a4015b60405180910390fd5b6000610266610657565b3660008037600080366000845af43d6000803e80801561045e573d6000f35b3d6000fd5b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b5473ffffffffffffffffffffffffffffffffffffffff16919050565b6104ac8361067f565b6000825111806104b95750805b15610214576104c883836102ff565b50505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6104f7610463565b6040805173ffffffffffffffffffffffffffffffffffffffff928316815291841660208301520160405180910390a161018b816106cc565b606073ffffffffffffffffffffffffffffffffffffffff84163b6105d5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f60448201527f6e74726163740000000000000000000000000000000000000000000000000000606482015260840161042c565b6000808573ffffffffffffffffffffffffffffffffffffffff16856040516105fd91906109e9565b600060405180830381855af49150503d8060008114610638576040519150601f19603f3d011682016040523d82523d6000602084013e61063d565b606091505b509150915061064d8282866107d8565b9695505050505050565b60007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc610487565b6106888161082b565b60405173ffffffffffffffffffffffffffffffffffffffff8216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b73ffffffffffffffffffffffffffffffffffffffff811661076f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201527f6464726573730000000000000000000000000000000000000000000000000000606482015260840161042c565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9290921691909117905550565b606083156107e7575081610324565b8251156107f75782518084602001fd5b816040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161042c9190610a05565b73ffffffffffffffffffffffffffffffffffffffff81163b6108cf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201527f6f74206120636f6e747261637400000000000000000000000000000000000000606482015260840161042c565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc610792565b803573ffffffffffffffffffffffffffffffffffffffff8116811461091a57600080fd5b919050565b60006020828403121561093157600080fd5b610324826108f6565b60008060006040848603121561094f57600080fd5b610958846108f6565b9250602084013567ffffffffffffffff8082111561097557600080fd5b818601915086601f83011261098957600080fd5b81358181111561099857600080fd5b8760208285010111156109aa57600080fd5b6020830194508093505050509250925092565b60005b838110156109d85781810151838201526020016109c0565b838111156104c85750506000910152565b600082516109fb8184602087016109bd565b9190910192915050565b6020815260008251806020840152610a248160408501602087016109bd565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220b29caa54336b3ee836679675e9732ec5e526fb3f803cca2fe336cc3555aba62264736f6c634300080a0033", + "devdoc": { + "details": "This contract implements a proxy that is upgradeable by an admin. To avoid https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector clashing], which can potentially be used in an attack, this contract uses the https://blog.openzeppelin.com/the-transparent-proxy-pattern/[transparent proxy pattern]. This pattern implies two things that go hand in hand: 1. If any account other than the admin calls the proxy, the call will be forwarded to the implementation, even if that call matches one of the admin functions exposed by the proxy itself. 2. If the admin calls the proxy, it can access the admin functions, but its calls will never be forwarded to the implementation. If the admin tries to call a function on the implementation it will fail with an error that says \"admin cannot fallback to proxy target\". These properties mean that the admin account can only be used for admin actions like upgrading the proxy or changing the admin, so it's best if it's a dedicated account that is not used for anything else. This will avoid headaches due to sudden errors when trying to call a function from the proxy implementation. Our recommendation is for the dedicated account to be an instance of the {ProxyAdmin} contract. If set up this way, you should think of the `ProxyAdmin` instance as the real administrative interface of your proxy.", + "kind": "dev", + "methods": { + "admin()": { + "details": "Returns the current admin. NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyAdmin}. TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call. `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`" + }, + "changeAdmin(address)": { + "details": "Changes the admin of the proxy. Emits an {AdminChanged} event. NOTE: Only the admin can call this function. See {ProxyAdmin-changeProxyAdmin}." + }, + "constructor": { + "details": "Initializes an upgradeable proxy managed by `_admin`, backed by the implementation at `_logic`, and optionally initialized with `_data` as explained in {ERC1967Proxy-constructor}." + }, + "implementation()": { + "details": "Returns the current implementation. NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyImplementation}. TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call. `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc`" + }, + "upgradeTo(address)": { + "details": "Upgrade the implementation of the proxy. NOTE: Only the admin can call this function. See {ProxyAdmin-upgrade}." + }, + "upgradeToAndCall(address,bytes)": { + "details": "Upgrade the implementation of the proxy, and then call a function from the new implementation as specified by `data`, which should be an encoded function call. This is useful to initialize new storage variables in the proxied contract. NOTE: Only the admin can call this function. See {ProxyAdmin-upgradeAndCall}." + } + }, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [], + "types": null + } +} diff --git a/deployments/bscmainnet/VToken_vSnBNB_LiquidStakedBNB.json b/deployments/bscmainnet/VToken_vSnBNB_LiquidStakedBNB.json new file mode 100644 index 000000000..00a156923 --- /dev/null +++ b/deployments/bscmainnet/VToken_vSnBNB_LiquidStakedBNB.json @@ -0,0 +1,246 @@ +{ + "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" + } + ], + "transactionHash": "0x00268d6b9779fbd0de29fdbdde4026c8ec3f0c4cb060386522e16122123ea5d8", + "receipt": { + "to": null, + "from": "0x12Bdf8Ae9fE2047809080412d7341044b910ef10", + "contractAddress": "0xd3CC9d8f3689B83c91b7B59cAB4946B063EB894A", + "transactionIndex": 99, + "gasUsed": "683433", + "logsBloom": "0x00000000000400000000001000000000000001000000000000808000000000200000000000000040000400420000000001000000000000000000000840048000001000000000000000000000001000000801000042040000000000080000082000000000020000000080000000000800000002000000000000000000000000400000000000000000000000000000080000000000080080140000000000000000000000000000000100000000000400000000000000800000000000000000004000000004000000000002000000040000000000000000080000840000000460100040000000000000000000800000000400000800000000000000000000010000", + "blockHash": "0xfb8d253bb5b47b8711d4482430a94ca1207fe4e2f2a591d56e9cf348d70894e5", + "transactionHash": "0x00268d6b9779fbd0de29fdbdde4026c8ec3f0c4cb060386522e16122123ea5d8", + "logs": [ + { + "transactionIndex": 99, + "blockNumber": 32073458, + "transactionHash": "0x00268d6b9779fbd0de29fdbdde4026c8ec3f0c4cb060386522e16122123ea5d8", + "address": "0xd3CC9d8f3689B83c91b7B59cAB4946B063EB894A", + "topics": [ + "0x1cf3b03a6cf19fa2baba4df148e9dcabedea7f8a5c07840e207e5c089be95d3e", + "0x0000000000000000000000002b8a1c539abac89cbf7e2bc6987a0a38a5e660d4" + ], + "data": "0x", + "logIndex": 210, + "blockHash": "0xfb8d253bb5b47b8711d4482430a94ca1207fe4e2f2a591d56e9cf348d70894e5" + }, + { + "transactionIndex": 99, + "blockNumber": 32073458, + "transactionHash": "0x00268d6b9779fbd0de29fdbdde4026c8ec3f0c4cb060386522e16122123ea5d8", + "address": "0xd3CC9d8f3689B83c91b7B59cAB4946B063EB894A", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x00000000000000000000000012bdf8ae9fe2047809080412d7341044b910ef10" + ], + "data": "0x", + "logIndex": 211, + "blockHash": "0xfb8d253bb5b47b8711d4482430a94ca1207fe4e2f2a591d56e9cf348d70894e5" + }, + { + "transactionIndex": 99, + "blockNumber": 32073458, + "transactionHash": "0x00268d6b9779fbd0de29fdbdde4026c8ec3f0c4cb060386522e16122123ea5d8", + "address": "0xd3CC9d8f3689B83c91b7B59cAB4946B063EB894A", + "topics": ["0x66fd58e82f7b31a2a5c30e0888f3093efe4e111b00cd2b0c31fe014601293aa0"], + "data": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000004788629abc6cfca10f9f969efdeaa1cf70c23555", + "logIndex": 212, + "blockHash": "0xfb8d253bb5b47b8711d4482430a94ca1207fe4e2f2a591d56e9cf348d70894e5" + }, + { + "transactionIndex": 99, + "blockNumber": 32073458, + "transactionHash": "0x00268d6b9779fbd0de29fdbdde4026c8ec3f0c4cb060386522e16122123ea5d8", + "address": "0xd3CC9d8f3689B83c91b7B59cAB4946B063EB894A", + "topics": [ + "0x7ac369dbd14fa5ea3f473ed67cc9d598964a77501540ba6751eb0b3decf5870d", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000d933909a4a2b7a4638903028f44d1d38ce27c352" + ], + "data": "0x", + "logIndex": 213, + "blockHash": "0xfb8d253bb5b47b8711d4482430a94ca1207fe4e2f2a591d56e9cf348d70894e5" + }, + { + "transactionIndex": 99, + "blockNumber": 32073458, + "transactionHash": "0x00268d6b9779fbd0de29fdbdde4026c8ec3f0c4cb060386522e16122123ea5d8", + "address": "0xd3CC9d8f3689B83c91b7B59cAB4946B063EB894A", + "topics": [ + "0xedffc32e068c7c95dfd4bdfd5c4d939a084d6b11c4199eac8436ed234d72f926", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x00000000000000000000000035dacdbfa83369d9edac586c65ff4aba850f1dba" + ], + "data": "0x", + "logIndex": 214, + "blockHash": "0xfb8d253bb5b47b8711d4482430a94ca1207fe4e2f2a591d56e9cf348d70894e5" + }, + { + "transactionIndex": 99, + "blockNumber": 32073458, + "transactionHash": "0x00268d6b9779fbd0de29fdbdde4026c8ec3f0c4cb060386522e16122123ea5d8", + "address": "0xd3CC9d8f3689B83c91b7B59cAB4946B063EB894A", + "topics": ["0xaaa68312e2ea9d50e16af5068410ab56e1a1fd06037b1a35664812c30f821460"], + "data": "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003782dace9d90000", + "logIndex": 215, + "blockHash": "0xfb8d253bb5b47b8711d4482430a94ca1207fe4e2f2a591d56e9cf348d70894e5" + }, + { + "transactionIndex": 99, + "blockNumber": 32073458, + "transactionHash": "0x00268d6b9779fbd0de29fdbdde4026c8ec3f0c4cb060386522e16122123ea5d8", + "address": "0xd3CC9d8f3689B83c91b7B59cAB4946B063EB894A", + "topics": [ + "0x6dbf1ff28f860de5edafa4c6505e37c0aba213288cc4166c5352b6d3776c79ef", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000001" + ], + "data": "0x", + "logIndex": 216, + "blockHash": "0xfb8d253bb5b47b8711d4482430a94ca1207fe4e2f2a591d56e9cf348d70894e5" + }, + { + "transactionIndex": 99, + "blockNumber": 32073458, + "transactionHash": "0x00268d6b9779fbd0de29fdbdde4026c8ec3f0c4cb060386522e16122123ea5d8", + "address": "0xd3CC9d8f3689B83c91b7B59cAB4946B063EB894A", + "topics": [ + "0xafec95c8612496c3ecf5dddc71e393528fe29bd145fbaf9c6b496d78d7e2d79b", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000f322942f644a996a617bd29c16bd7d231d9f35e9" + ], + "data": "0x", + "logIndex": 217, + "blockHash": "0xfb8d253bb5b47b8711d4482430a94ca1207fe4e2f2a591d56e9cf348d70894e5" + }, + { + "transactionIndex": 99, + "blockNumber": 32073458, + "transactionHash": "0x00268d6b9779fbd0de29fdbdde4026c8ec3f0c4cb060386522e16122123ea5d8", + "address": "0xd3CC9d8f3689B83c91b7B59cAB4946B063EB894A", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x00000000000000000000000012bdf8ae9fe2047809080412d7341044b910ef10", + "0x000000000000000000000000939bd8d64c0a9583a7dcea9933f7b21697ab6396" + ], + "data": "0x", + "logIndex": 218, + "blockHash": "0xfb8d253bb5b47b8711d4482430a94ca1207fe4e2f2a591d56e9cf348d70894e5" + }, + { + "transactionIndex": 99, + "blockNumber": 32073458, + "transactionHash": "0x00268d6b9779fbd0de29fdbdde4026c8ec3f0c4cb060386522e16122123ea5d8", + "address": "0xd3CC9d8f3689B83c91b7B59cAB4946B063EB894A", + "topics": ["0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498"], + "data": "0x0000000000000000000000000000000000000000000000000000000000000001", + "logIndex": 219, + "blockHash": "0xfb8d253bb5b47b8711d4482430a94ca1207fe4e2f2a591d56e9cf348d70894e5" + } + ], + "blockNumber": 32073458, + "cumulativeGasUsed": "9034087", + "status": 1, + "byzantium": true + }, + "args": [ + "0x2b8A1C539ABaC89CbF7E2Bc6987A0A38A5e660D4", + "0x8a42c319000000000000000000000000b0b84d294e0c75a6abe60171b70edeb2efd14a1b000000000000000000000000d933909a4a2b7a4638903028f44d1d38ce27c35200000000000000000000000035dacdbfa83369d9edac586c65ff4aba850f1dba0000000000000000000000000000000000000000204fce5e3e25026110000000000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000001c00000000000000000000000000000000000000000000000000000000000000008000000000000000000000000939bd8d64c0a9583a7dcea9933f7b21697ab63960000000000000000000000004788629abc6cfca10f9f969efdeaa1cf70c235550000000000000000000000000000000000000000000000000000000000000001000000000000000000000000f322942f644a996a617bd29c16bd7d231d9f35e900000000000000000000000000000000000000000000000003782dace9d90000000000000000000000000000000000000000000000000000000000000000001f56656e757320536e424e4220284c6971756964205374616b656420424e422900000000000000000000000000000000000000000000000000000000000000001676536e424e425f4c69717569645374616b6564424e4200000000000000000000" + ], + "numDeployments": 1, + "solcInputHash": "6d4db51b84097a74598623a15df3d6fb", + "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/bscmainnet/solcInputs/6d4db51b84097a74598623a15df3d6fb.json b/deployments/bscmainnet/solcInputs/6d4db51b84097a74598623a15df3d6fb.json new file mode 100644 index 000000000..b8f55c44b --- /dev/null +++ b/deployments/bscmainnet/solcInputs/6d4db51b84097a74598623a15df3d6fb.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 { 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 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 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/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 { 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/bsctestnet/MockSnBNB.json b/deployments/bsctestnet/MockSnBNB.json new file mode 100644 index 000000000..3d37cbdf9 --- /dev/null +++ b/deployments/bsctestnet/MockSnBNB.json @@ -0,0 +1,450 @@ +{ + "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" + } + ], + "transactionHash": "0x9c7339970b202a670322fff4634e4075faf0849a0ea33b143ac627e8c5a42c00", + "receipt": { + "to": null, + "from": "0x9cc6F5f16498fCEEf4D00A350Bd8F8921D304Dc9", + "contractAddress": "0xd2aF6A916Bc77764dc63742BC30f71AF4cF423F4", + "transactionIndex": 1, + "gasUsed": "636136", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x3f406e936dff209256fac973e5cf9b0d1144431776a68c08a4274edc62313c58", + "transactionHash": "0x9c7339970b202a670322fff4634e4075faf0849a0ea33b143ac627e8c5a42c00", + "logs": [], + "blockNumber": 33673019, + "cumulativeGasUsed": "667377", + "status": 1, + "byzantium": true + }, + "args": ["Synclub Staked BNB", "SnBNB", 18], + "numDeployments": 1, + "solcInputHash": "6d4db51b84097a74598623a15df3d6fb", + "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/RewardsDistributor_LiquidStakedBNB_4.json b/deployments/bsctestnet/RewardsDistributor_LiquidStakedBNB_4.json new file mode 100644 index 000000000..2ad1d37cf --- /dev/null +++ b/deployments/bsctestnet/RewardsDistributor_LiquidStakedBNB_4.json @@ -0,0 +1,1270 @@ +{ + "address": "0xc1Ea6292C49D6B6E952baAC6673dE64701bB88cB", + "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": "0x1ab70c2c69f1148c8aaee1aaa4d3aa411b2f20a8aababf20e6596f2a906c4c98", + "receipt": { + "to": null, + "from": "0x9cc6F5f16498fCEEf4D00A350Bd8F8921D304Dc9", + "contractAddress": "0xc1Ea6292C49D6B6E952baAC6673dE64701bB88cB", + "transactionIndex": 2, + "gasUsed": "865817", + "logsBloom": "0x00000000000000000000000010020000400000000000000000800000000800000000000000000000000000000000000000020000000000000000000000008000000000000000000000000000000002000001000000000000000000400000000000000000020000000000000020000800000800800000000040000000000000400000000000000000000000000000000000000000000080000000000000800000000000000000000000002000000400000000000000800000000000000000000000000020000000000000000001040000000000000400000000000000000020000000000200000000000800000000000000000800000000000000000000000000", + "blockHash": "0x5d69ca41e0b06a0ec1ad0d0869e32d92f3ad52e0443e80bf5a1638e546601f16", + "transactionHash": "0x1ab70c2c69f1148c8aaee1aaa4d3aa411b2f20a8aababf20e6596f2a906c4c98", + "logs": [ + { + "transactionIndex": 2, + "blockNumber": 33673411, + "transactionHash": "0x1ab70c2c69f1148c8aaee1aaa4d3aa411b2f20a8aababf20e6596f2a906c4c98", + "address": "0xc1Ea6292C49D6B6E952baAC6673dE64701bB88cB", + "topics": [ + "0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b", + "0x0000000000000000000000003f0a9e2e605e5ebf01e0e28ed6f7ebb67b51691f" + ], + "data": "0x", + "logIndex": 5, + "blockHash": "0x5d69ca41e0b06a0ec1ad0d0869e32d92f3ad52e0443e80bf5a1638e546601f16" + }, + { + "transactionIndex": 2, + "blockNumber": 33673411, + "transactionHash": "0x1ab70c2c69f1148c8aaee1aaa4d3aa411b2f20a8aababf20e6596f2a906c4c98", + "address": "0xc1Ea6292C49D6B6E952baAC6673dE64701bB88cB", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000009cc6f5f16498fceef4d00a350bd8f8921d304dc9" + ], + "data": "0x", + "logIndex": 6, + "blockHash": "0x5d69ca41e0b06a0ec1ad0d0869e32d92f3ad52e0443e80bf5a1638e546601f16" + }, + { + "transactionIndex": 2, + "blockNumber": 33673411, + "transactionHash": "0x1ab70c2c69f1148c8aaee1aaa4d3aa411b2f20a8aababf20e6596f2a906c4c98", + "address": "0xc1Ea6292C49D6B6E952baAC6673dE64701bB88cB", + "topics": ["0x66fd58e82f7b31a2a5c30e0888f3093efe4e111b00cd2b0c31fe014601293aa0"], + "data": "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000045f8a08f534f34a97187626e05d4b6648eeaa9aa", + "logIndex": 7, + "blockHash": "0x5d69ca41e0b06a0ec1ad0d0869e32d92f3ad52e0443e80bf5a1638e546601f16" + }, + { + "transactionIndex": 2, + "blockNumber": 33673411, + "transactionHash": "0x1ab70c2c69f1148c8aaee1aaa4d3aa411b2f20a8aababf20e6596f2a906c4c98", + "address": "0xc1Ea6292C49D6B6E952baAC6673dE64701bB88cB", + "topics": ["0xc2d09fef144f7c8a86f71ea459f8fc17f675768eb1ae369cbd77fb31d467aafa"], + "data": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000064", + "logIndex": 8, + "blockHash": "0x5d69ca41e0b06a0ec1ad0d0869e32d92f3ad52e0443e80bf5a1638e546601f16" + }, + { + "transactionIndex": 2, + "blockNumber": 33673411, + "transactionHash": "0x1ab70c2c69f1148c8aaee1aaa4d3aa411b2f20a8aababf20e6596f2a906c4c98", + "address": "0xc1Ea6292C49D6B6E952baAC6673dE64701bB88cB", + "topics": ["0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498"], + "data": "0x0000000000000000000000000000000000000000000000000000000000000001", + "logIndex": 9, + "blockHash": "0x5d69ca41e0b06a0ec1ad0d0869e32d92f3ad52e0443e80bf5a1638e546601f16" + }, + { + "transactionIndex": 2, + "blockNumber": 33673411, + "transactionHash": "0x1ab70c2c69f1148c8aaee1aaa4d3aa411b2f20a8aababf20e6596f2a906c4c98", + "address": "0xc1Ea6292C49D6B6E952baAC6673dE64701bB88cB", + "topics": ["0x7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f"], + "data": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000007877ffd62649b6a1557b55d4c20fcbab17344c91", + "logIndex": 10, + "blockHash": "0x5d69ca41e0b06a0ec1ad0d0869e32d92f3ad52e0443e80bf5a1638e546601f16" + } + ], + "blockNumber": 33673411, + "cumulativeGasUsed": "1144110", + "status": 1, + "byzantium": true + }, + "args": [ + "0x3F0a9e2E605E5EbF01e0e28ED6f7EBB67b51691f", + "0x7877fFd62649b6A1557B55D4c20fcBaB17344C91", + "0xbe203094000000000000000000000000596b11acaacf03217287939f88d63b51d3771704000000000000000000000000e73774dfcd551bf75650772dc2cc56a2b6323453000000000000000000000000000000000000000000000000000000000000006400000000000000000000000045f8a08f534f34a97187626e05d4b6648eeaa9aa" + ], + "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": [ + "0x596B11acAACF03217287939f88d63b51d3771704", + "0xe73774DfCD551BF75650772dC2cC56a2B6323453", + 100, + "0x45f8a08F534f34A97187626E05d4b6648Eeaa9AA" + ] + }, + "implementation": "0x3F0a9e2E605E5EbF01e0e28ED6f7EBB67b51691f", + "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/RewardsDistributor_LiquidStakedBNB_4_Proxy.json b/deployments/bsctestnet/RewardsDistributor_LiquidStakedBNB_4_Proxy.json new file mode 100644 index 000000000..f4b404494 --- /dev/null +++ b/deployments/bsctestnet/RewardsDistributor_LiquidStakedBNB_4_Proxy.json @@ -0,0 +1,277 @@ +{ + "address": "0xc1Ea6292C49D6B6E952baAC6673dE64701bB88cB", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_logic", + "type": "address" + }, + { + "internalType": "address", + "name": "admin_", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "stateMutability": "payable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "previousAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beacon", + "type": "address" + } + ], + "name": "BeaconUpgraded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "admin_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "changeAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "implementation_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "upgradeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "upgradeToAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "transactionHash": "0x1ab70c2c69f1148c8aaee1aaa4d3aa411b2f20a8aababf20e6596f2a906c4c98", + "receipt": { + "to": null, + "from": "0x9cc6F5f16498fCEEf4D00A350Bd8F8921D304Dc9", + "contractAddress": "0xc1Ea6292C49D6B6E952baAC6673dE64701bB88cB", + "transactionIndex": 2, + "gasUsed": "865817", + "logsBloom": "0x00000000000000000000000010020000400000000000000000800000000800000000000000000000000000000000000000020000000000000000000000008000000000000000000000000000000002000001000000000000000000400000000000000000020000000000000020000800000800800000000040000000000000400000000000000000000000000000000000000000000080000000000000800000000000000000000000002000000400000000000000800000000000000000000000000020000000000000000001040000000000000400000000000000000020000000000200000000000800000000000000000800000000000000000000000000", + "blockHash": "0x5d69ca41e0b06a0ec1ad0d0869e32d92f3ad52e0443e80bf5a1638e546601f16", + "transactionHash": "0x1ab70c2c69f1148c8aaee1aaa4d3aa411b2f20a8aababf20e6596f2a906c4c98", + "logs": [ + { + "transactionIndex": 2, + "blockNumber": 33673411, + "transactionHash": "0x1ab70c2c69f1148c8aaee1aaa4d3aa411b2f20a8aababf20e6596f2a906c4c98", + "address": "0xc1Ea6292C49D6B6E952baAC6673dE64701bB88cB", + "topics": [ + "0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b", + "0x0000000000000000000000003f0a9e2e605e5ebf01e0e28ed6f7ebb67b51691f" + ], + "data": "0x", + "logIndex": 5, + "blockHash": "0x5d69ca41e0b06a0ec1ad0d0869e32d92f3ad52e0443e80bf5a1638e546601f16" + }, + { + "transactionIndex": 2, + "blockNumber": 33673411, + "transactionHash": "0x1ab70c2c69f1148c8aaee1aaa4d3aa411b2f20a8aababf20e6596f2a906c4c98", + "address": "0xc1Ea6292C49D6B6E952baAC6673dE64701bB88cB", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000009cc6f5f16498fceef4d00a350bd8f8921d304dc9" + ], + "data": "0x", + "logIndex": 6, + "blockHash": "0x5d69ca41e0b06a0ec1ad0d0869e32d92f3ad52e0443e80bf5a1638e546601f16" + }, + { + "transactionIndex": 2, + "blockNumber": 33673411, + "transactionHash": "0x1ab70c2c69f1148c8aaee1aaa4d3aa411b2f20a8aababf20e6596f2a906c4c98", + "address": "0xc1Ea6292C49D6B6E952baAC6673dE64701bB88cB", + "topics": ["0x66fd58e82f7b31a2a5c30e0888f3093efe4e111b00cd2b0c31fe014601293aa0"], + "data": "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000045f8a08f534f34a97187626e05d4b6648eeaa9aa", + "logIndex": 7, + "blockHash": "0x5d69ca41e0b06a0ec1ad0d0869e32d92f3ad52e0443e80bf5a1638e546601f16" + }, + { + "transactionIndex": 2, + "blockNumber": 33673411, + "transactionHash": "0x1ab70c2c69f1148c8aaee1aaa4d3aa411b2f20a8aababf20e6596f2a906c4c98", + "address": "0xc1Ea6292C49D6B6E952baAC6673dE64701bB88cB", + "topics": ["0xc2d09fef144f7c8a86f71ea459f8fc17f675768eb1ae369cbd77fb31d467aafa"], + "data": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000064", + "logIndex": 8, + "blockHash": "0x5d69ca41e0b06a0ec1ad0d0869e32d92f3ad52e0443e80bf5a1638e546601f16" + }, + { + "transactionIndex": 2, + "blockNumber": 33673411, + "transactionHash": "0x1ab70c2c69f1148c8aaee1aaa4d3aa411b2f20a8aababf20e6596f2a906c4c98", + "address": "0xc1Ea6292C49D6B6E952baAC6673dE64701bB88cB", + "topics": ["0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498"], + "data": "0x0000000000000000000000000000000000000000000000000000000000000001", + "logIndex": 9, + "blockHash": "0x5d69ca41e0b06a0ec1ad0d0869e32d92f3ad52e0443e80bf5a1638e546601f16" + }, + { + "transactionIndex": 2, + "blockNumber": 33673411, + "transactionHash": "0x1ab70c2c69f1148c8aaee1aaa4d3aa411b2f20a8aababf20e6596f2a906c4c98", + "address": "0xc1Ea6292C49D6B6E952baAC6673dE64701bB88cB", + "topics": ["0x7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f"], + "data": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000007877ffd62649b6a1557b55d4c20fcbab17344c91", + "logIndex": 10, + "blockHash": "0x5d69ca41e0b06a0ec1ad0d0869e32d92f3ad52e0443e80bf5a1638e546601f16" + } + ], + "blockNumber": 33673411, + "cumulativeGasUsed": "1144110", + "status": 1, + "byzantium": true + }, + "args": [ + "0x3F0a9e2E605E5EbF01e0e28ED6f7EBB67b51691f", + "0x7877fFd62649b6A1557B55D4c20fcBaB17344C91", + "0xbe203094000000000000000000000000596b11acaacf03217287939f88d63b51d3771704000000000000000000000000e73774dfcd551bf75650772dc2cc56a2b6323453000000000000000000000000000000000000000000000000000000000000006400000000000000000000000045f8a08f534f34a97187626e05d4b6648eeaa9aa" + ], + "numDeployments": 1, + "solcInputHash": "0e89febeebc7444140de8e67c9067d2c", + "metadata": "{\"compiler\":{\"version\":\"0.8.10+commit.fc410830\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_logic\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"admin_\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"previousAdmin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\"}],\"name\":\"AdminChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"beacon\",\"type\":\"address\"}],\"name\":\"BeaconUpgraded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"implementation\",\"type\":\"address\"}],\"name\":\"Upgraded\",\"type\":\"event\"},{\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"inputs\":[],\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"admin_\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\"}],\"name\":\"changeAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"implementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"implementation_\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newImplementation\",\"type\":\"address\"}],\"name\":\"upgradeTo\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newImplementation\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"upgradeToAndCall\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"details\":\"This contract implements a proxy that is upgradeable by an admin. To avoid https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector clashing], which can potentially be used in an attack, this contract uses the https://blog.openzeppelin.com/the-transparent-proxy-pattern/[transparent proxy pattern]. This pattern implies two things that go hand in hand: 1. If any account other than the admin calls the proxy, the call will be forwarded to the implementation, even if that call matches one of the admin functions exposed by the proxy itself. 2. If the admin calls the proxy, it can access the admin functions, but its calls will never be forwarded to the implementation. If the admin tries to call a function on the implementation it will fail with an error that says \\\"admin cannot fallback to proxy target\\\". These properties mean that the admin account can only be used for admin actions like upgrading the proxy or changing the admin, so it's best if it's a dedicated account that is not used for anything else. This will avoid headaches due to sudden errors when trying to call a function from the proxy implementation. Our recommendation is for the dedicated account to be an instance of the {ProxyAdmin} contract. If set up this way, you should think of the `ProxyAdmin` instance as the real administrative interface of your proxy.\",\"kind\":\"dev\",\"methods\":{\"admin()\":{\"details\":\"Returns the current admin. NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyAdmin}. TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call. `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`\"},\"changeAdmin(address)\":{\"details\":\"Changes the admin of the proxy. Emits an {AdminChanged} event. NOTE: Only the admin can call this function. See {ProxyAdmin-changeProxyAdmin}.\"},\"constructor\":{\"details\":\"Initializes an upgradeable proxy managed by `_admin`, backed by the implementation at `_logic`, and optionally initialized with `_data` as explained in {ERC1967Proxy-constructor}.\"},\"implementation()\":{\"details\":\"Returns the current implementation. NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyImplementation}. TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call. `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc`\"},\"upgradeTo(address)\":{\"details\":\"Upgrade the implementation of the proxy. NOTE: Only the admin can call this function. See {ProxyAdmin-upgrade}.\"},\"upgradeToAndCall(address,bytes)\":{\"details\":\"Upgrade the implementation of the proxy, and then call a function from the new implementation as specified by `data`, which should be an encoded function call. This is useful to initialize new storage variables in the proxied contract. NOTE: Only the admin can call this function. See {ProxyAdmin-upgradeAndCall}.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solc_0.8/openzeppelin/proxy/transparent/TransparentUpgradeableProxy.sol\":\"TransparentUpgradeableProxy\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":999999},\"remappings\":[]},\"sources\":{\"solc_0.8/openzeppelin/interfaces/draft-IERC1822.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (interfaces/draft-IERC1822.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified\\n * proxy whose upgrades are fully controlled by the current implementation.\\n */\\ninterface IERC1822Proxiable {\\n /**\\n * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation\\n * address.\\n *\\n * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks\\n * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this\\n * function revert if invoked through a proxy.\\n */\\n function proxiableUUID() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0x93b4e21c931252739a1ec13ea31d3d35a5c068be3163ccab83e4d70c40355f03\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/proxy/ERC1967/ERC1967Proxy.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (proxy/ERC1967/ERC1967Proxy.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../Proxy.sol\\\";\\nimport \\\"./ERC1967Upgrade.sol\\\";\\n\\n/**\\n * @dev This contract implements an upgradeable proxy. It is upgradeable because calls are delegated to an\\n * implementation address that can be changed. This address is stored in storage in the location specified by\\n * https://eips.ethereum.org/EIPS/eip-1967[EIP1967], so that it doesn't conflict with the storage layout of the\\n * implementation behind the proxy.\\n */\\ncontract ERC1967Proxy is Proxy, ERC1967Upgrade {\\n /**\\n * @dev Initializes the upgradeable proxy with an initial implementation specified by `_logic`.\\n *\\n * If `_data` is nonempty, it's used as data in a delegate call to `_logic`. This will typically be an encoded\\n * function call, and allows initializating the storage of the proxy like a Solidity constructor.\\n */\\n constructor(address _logic, bytes memory _data) payable {\\n assert(_IMPLEMENTATION_SLOT == bytes32(uint256(keccak256(\\\"eip1967.proxy.implementation\\\")) - 1));\\n _upgradeToAndCall(_logic, _data, false);\\n }\\n\\n /**\\n * @dev Returns the current implementation address.\\n */\\n function _implementation() internal view virtual override returns (address impl) {\\n return ERC1967Upgrade._getImplementation();\\n }\\n}\\n\",\"keccak256\":\"0x6309f9f39dc6f4f45a24f296543867aa358e32946cd6b2874627a996d606b3a0\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/proxy/ERC1967/ERC1967Upgrade.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (proxy/ERC1967/ERC1967Upgrade.sol)\\n\\npragma solidity ^0.8.2;\\n\\nimport \\\"../beacon/IBeacon.sol\\\";\\nimport \\\"../../interfaces/draft-IERC1822.sol\\\";\\nimport \\\"../../utils/Address.sol\\\";\\nimport \\\"../../utils/StorageSlot.sol\\\";\\n\\n/**\\n * @dev This abstract contract provides getters and event emitting update functions for\\n * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots.\\n *\\n * _Available since v4.1._\\n *\\n * @custom:oz-upgrades-unsafe-allow delegatecall\\n */\\nabstract contract ERC1967Upgrade {\\n // This is the keccak-256 hash of \\\"eip1967.proxy.rollback\\\" subtracted by 1\\n bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143;\\n\\n /**\\n * @dev Storage slot with the address of the current implementation.\\n * This is the keccak-256 hash of \\\"eip1967.proxy.implementation\\\" subtracted by 1, and is\\n * validated in the constructor.\\n */\\n bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\\n\\n /**\\n * @dev Emitted when the implementation is upgraded.\\n */\\n event Upgraded(address indexed implementation);\\n\\n /**\\n * @dev Returns the current implementation address.\\n */\\n function _getImplementation() internal view returns (address) {\\n return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\\n }\\n\\n /**\\n * @dev Stores a new address in the EIP1967 implementation slot.\\n */\\n function _setImplementation(address newImplementation) private {\\n require(Address.isContract(newImplementation), \\\"ERC1967: new implementation is not a contract\\\");\\n StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\\n }\\n\\n /**\\n * @dev Perform implementation upgrade\\n *\\n * Emits an {Upgraded} event.\\n */\\n function _upgradeTo(address newImplementation) internal {\\n _setImplementation(newImplementation);\\n emit Upgraded(newImplementation);\\n }\\n\\n /**\\n * @dev Perform implementation upgrade with additional setup call.\\n *\\n * Emits an {Upgraded} event.\\n */\\n function _upgradeToAndCall(\\n address newImplementation,\\n bytes memory data,\\n bool forceCall\\n ) internal {\\n _upgradeTo(newImplementation);\\n if (data.length > 0 || forceCall) {\\n Address.functionDelegateCall(newImplementation, data);\\n }\\n }\\n\\n /**\\n * @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call.\\n *\\n * Emits an {Upgraded} event.\\n */\\n function _upgradeToAndCallUUPS(\\n address newImplementation,\\n bytes memory data,\\n bool forceCall\\n ) internal {\\n // Upgrades from old implementations will perform a rollback test. This test requires the new\\n // implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing\\n // this special case will break upgrade paths from old UUPS implementation to new ones.\\n if (StorageSlot.getBooleanSlot(_ROLLBACK_SLOT).value) {\\n _setImplementation(newImplementation);\\n } else {\\n try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) {\\n require(slot == _IMPLEMENTATION_SLOT, \\\"ERC1967Upgrade: unsupported proxiableUUID\\\");\\n } catch {\\n revert(\\\"ERC1967Upgrade: new implementation is not UUPS\\\");\\n }\\n _upgradeToAndCall(newImplementation, data, forceCall);\\n }\\n }\\n\\n /**\\n * @dev Storage slot with the admin of the contract.\\n * This is the keccak-256 hash of \\\"eip1967.proxy.admin\\\" subtracted by 1, and is\\n * validated in the constructor.\\n */\\n bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;\\n\\n /**\\n * @dev Emitted when the admin account has changed.\\n */\\n event AdminChanged(address previousAdmin, address newAdmin);\\n\\n /**\\n * @dev Returns the current admin.\\n */\\n function _getAdmin() internal view virtual returns (address) {\\n return StorageSlot.getAddressSlot(_ADMIN_SLOT).value;\\n }\\n\\n /**\\n * @dev Stores a new address in the EIP1967 admin slot.\\n */\\n function _setAdmin(address newAdmin) private {\\n require(newAdmin != address(0), \\\"ERC1967: new admin is the zero address\\\");\\n StorageSlot.getAddressSlot(_ADMIN_SLOT).value = newAdmin;\\n }\\n\\n /**\\n * @dev Changes the admin of the proxy.\\n *\\n * Emits an {AdminChanged} event.\\n */\\n function _changeAdmin(address newAdmin) internal {\\n emit AdminChanged(_getAdmin(), newAdmin);\\n _setAdmin(newAdmin);\\n }\\n\\n /**\\n * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.\\n * This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor.\\n */\\n bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;\\n\\n /**\\n * @dev Emitted when the beacon is upgraded.\\n */\\n event BeaconUpgraded(address indexed beacon);\\n\\n /**\\n * @dev Returns the current beacon.\\n */\\n function _getBeacon() internal view returns (address) {\\n return StorageSlot.getAddressSlot(_BEACON_SLOT).value;\\n }\\n\\n /**\\n * @dev Stores a new beacon in the EIP1967 beacon slot.\\n */\\n function _setBeacon(address newBeacon) private {\\n require(Address.isContract(newBeacon), \\\"ERC1967: new beacon is not a contract\\\");\\n require(Address.isContract(IBeacon(newBeacon).implementation()), \\\"ERC1967: beacon implementation is not a contract\\\");\\n StorageSlot.getAddressSlot(_BEACON_SLOT).value = newBeacon;\\n }\\n\\n /**\\n * @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does\\n * not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that).\\n *\\n * Emits a {BeaconUpgraded} event.\\n */\\n function _upgradeBeaconToAndCall(\\n address newBeacon,\\n bytes memory data,\\n bool forceCall\\n ) internal {\\n _setBeacon(newBeacon);\\n emit BeaconUpgraded(newBeacon);\\n if (data.length > 0 || forceCall) {\\n Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x17668652127feebed0ce8d9431ef95ccc8c4292f03e3b8cf06c6ca16af396633\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/proxy/Proxy.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (proxy/Proxy.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM\\n * instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to\\n * be specified by overriding the virtual {_implementation} function.\\n *\\n * Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a\\n * different contract through the {_delegate} function.\\n *\\n * The success and return data of the delegated call will be returned back to the caller of the proxy.\\n */\\nabstract contract Proxy {\\n /**\\n * @dev Delegates the current call to `implementation`.\\n *\\n * This function does not return to its internal call site, it will return directly to the external caller.\\n */\\n function _delegate(address implementation) internal virtual {\\n assembly {\\n // Copy msg.data. We take full control of memory in this inline assembly\\n // block because it will not return to Solidity code. We overwrite the\\n // Solidity scratch pad at memory position 0.\\n calldatacopy(0, 0, calldatasize())\\n\\n // Call the implementation.\\n // out and outsize are 0 because we don't know the size yet.\\n let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)\\n\\n // Copy the returned data.\\n returndatacopy(0, 0, returndatasize())\\n\\n switch result\\n // delegatecall returns 0 on error.\\n case 0 {\\n revert(0, returndatasize())\\n }\\n default {\\n return(0, returndatasize())\\n }\\n }\\n }\\n\\n /**\\n * @dev This is a virtual function that should be overriden so it returns the address to which the fallback function\\n * and {_fallback} should delegate.\\n */\\n function _implementation() internal view virtual returns (address);\\n\\n /**\\n * @dev Delegates the current call to the address returned by `_implementation()`.\\n *\\n * This function does not return to its internall call site, it will return directly to the external caller.\\n */\\n function _fallback() internal virtual {\\n _beforeFallback();\\n _delegate(_implementation());\\n }\\n\\n /**\\n * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other\\n * function in the contract matches the call data.\\n */\\n fallback() external payable virtual {\\n _fallback();\\n }\\n\\n /**\\n * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if call data\\n * is empty.\\n */\\n receive() external payable virtual {\\n _fallback();\\n }\\n\\n /**\\n * @dev Hook that is called before falling back to the implementation. Can happen as part of a manual `_fallback`\\n * call, or as part of the Solidity `fallback` or `receive` functions.\\n *\\n * If overriden should call `super._beforeFallback()`.\\n */\\n function _beforeFallback() internal virtual {}\\n}\\n\",\"keccak256\":\"0xd5d1fd16e9faff7fcb3a52e02a8d49156f42a38a03f07b5f1810c21c2149a8ab\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/proxy/beacon/IBeacon.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev This is the interface that {BeaconProxy} expects of its beacon.\\n */\\ninterface IBeacon {\\n /**\\n * @dev Must return an address that can be used as a delegate call target.\\n *\\n * {BeaconProxy} will check that this address is a contract.\\n */\\n function implementation() external view returns (address);\\n}\\n\",\"keccak256\":\"0xd50a3421ac379ccb1be435fa646d66a65c986b4924f0849839f08692f39dde61\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/proxy/transparent/TransparentUpgradeableProxy.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (proxy/transparent/TransparentUpgradeableProxy.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../ERC1967/ERC1967Proxy.sol\\\";\\n\\n/**\\n * @dev This contract implements a proxy that is upgradeable by an admin.\\n *\\n * To avoid https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector\\n * clashing], which can potentially be used in an attack, this contract uses the\\n * https://blog.openzeppelin.com/the-transparent-proxy-pattern/[transparent proxy pattern]. This pattern implies two\\n * things that go hand in hand:\\n *\\n * 1. If any account other than the admin calls the proxy, the call will be forwarded to the implementation, even if\\n * that call matches one of the admin functions exposed by the proxy itself.\\n * 2. If the admin calls the proxy, it can access the admin functions, but its calls will never be forwarded to the\\n * implementation. If the admin tries to call a function on the implementation it will fail with an error that says\\n * \\\"admin cannot fallback to proxy target\\\".\\n *\\n * These properties mean that the admin account can only be used for admin actions like upgrading the proxy or changing\\n * the admin, so it's best if it's a dedicated account that is not used for anything else. This will avoid headaches due\\n * to sudden errors when trying to call a function from the proxy implementation.\\n *\\n * Our recommendation is for the dedicated account to be an instance of the {ProxyAdmin} contract. If set up this way,\\n * you should think of the `ProxyAdmin` instance as the real administrative interface of your proxy.\\n */\\ncontract TransparentUpgradeableProxy is ERC1967Proxy {\\n /**\\n * @dev Initializes an upgradeable proxy managed by `_admin`, backed by the implementation at `_logic`, and\\n * optionally initialized with `_data` as explained in {ERC1967Proxy-constructor}.\\n */\\n constructor(\\n address _logic,\\n address admin_,\\n bytes memory _data\\n ) payable ERC1967Proxy(_logic, _data) {\\n assert(_ADMIN_SLOT == bytes32(uint256(keccak256(\\\"eip1967.proxy.admin\\\")) - 1));\\n _changeAdmin(admin_);\\n }\\n\\n /**\\n * @dev Modifier used internally that will delegate the call to the implementation unless the sender is the admin.\\n */\\n modifier ifAdmin() {\\n if (msg.sender == _getAdmin()) {\\n _;\\n } else {\\n _fallback();\\n }\\n }\\n\\n /**\\n * @dev Returns the current admin.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyAdmin}.\\n *\\n * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the\\n * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.\\n * `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`\\n */\\n function admin() external ifAdmin returns (address admin_) {\\n admin_ = _getAdmin();\\n }\\n\\n /**\\n * @dev Returns the current implementation.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyImplementation}.\\n *\\n * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the\\n * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.\\n * `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc`\\n */\\n function implementation() external ifAdmin returns (address implementation_) {\\n implementation_ = _implementation();\\n }\\n\\n /**\\n * @dev Changes the admin of the proxy.\\n *\\n * Emits an {AdminChanged} event.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-changeProxyAdmin}.\\n */\\n function changeAdmin(address newAdmin) external virtual ifAdmin {\\n _changeAdmin(newAdmin);\\n }\\n\\n /**\\n * @dev Upgrade the implementation of the proxy.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-upgrade}.\\n */\\n function upgradeTo(address newImplementation) external ifAdmin {\\n _upgradeToAndCall(newImplementation, bytes(\\\"\\\"), false);\\n }\\n\\n /**\\n * @dev Upgrade the implementation of the proxy, and then call a function from the new implementation as specified\\n * by `data`, which should be an encoded function call. This is useful to initialize new storage variables in the\\n * proxied contract.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-upgradeAndCall}.\\n */\\n function upgradeToAndCall(address newImplementation, bytes calldata data) external payable ifAdmin {\\n _upgradeToAndCall(newImplementation, data, true);\\n }\\n\\n /**\\n * @dev Returns the current admin.\\n */\\n function _admin() internal view virtual returns (address) {\\n return _getAdmin();\\n }\\n\\n /**\\n * @dev Makes sure the admin cannot access the fallback function. See {Proxy-_beforeFallback}.\\n */\\n function _beforeFallback() internal virtual override {\\n require(msg.sender != _getAdmin(), \\\"TransparentUpgradeableProxy: admin cannot fallback to proxy target\\\");\\n super._beforeFallback();\\n }\\n}\\n\",\"keccak256\":\"0x140055a64cf579d622e04f5a198595832bf2cb193cd0005f4f2d4d61ca906253\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x3777e696b62134e6177440dbe6e6601c0c156a443f57167194b67e75527439de\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/utils/StorageSlot.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/StorageSlot.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Library for reading and writing primitive types to specific storage slots.\\n *\\n * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.\\n * This library helps with reading and writing to such slots without the need for inline assembly.\\n *\\n * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.\\n *\\n * Example usage to set ERC1967 implementation slot:\\n * ```\\n * contract ERC1967 {\\n * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\\n *\\n * function _getImplementation() internal view returns (address) {\\n * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\\n * }\\n *\\n * function _setImplementation(address newImplementation) internal {\\n * require(Address.isContract(newImplementation), \\\"ERC1967: new implementation is not a contract\\\");\\n * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\\n * }\\n * }\\n * ```\\n *\\n * _Available since v4.1 for `address`, `bool`, `bytes32`, and `uint256`._\\n */\\nlibrary StorageSlot {\\n struct AddressSlot {\\n address value;\\n }\\n\\n struct BooleanSlot {\\n bool value;\\n }\\n\\n struct Bytes32Slot {\\n bytes32 value;\\n }\\n\\n struct Uint256Slot {\\n uint256 value;\\n }\\n\\n /**\\n * @dev Returns an `AddressSlot` with member `value` located at `slot`.\\n */\\n function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {\\n assembly {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `BooleanSlot` with member `value` located at `slot`.\\n */\\n function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {\\n assembly {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `Bytes32Slot` with member `value` located at `slot`.\\n */\\n function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {\\n assembly {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `Uint256Slot` with member `value` located at `slot`.\\n */\\n function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {\\n assembly {\\n r.slot := slot\\n }\\n }\\n}\\n\",\"keccak256\":\"0xfe1b7a9aa2a530a9e705b220e26cd584e2fbdc9602a3a1066032b12816b46aca\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x6080604052604051620011b2380380620011b2833981016040819052620000269162000519565b82816200005560017f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbd620005f9565b6000805160206200116b833981519152146200007557620000756200061f565b6200008382826000620000e7565b50620000b3905060017fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6104620005f9565b6000805160206200114b83398151915214620000d357620000d36200061f565b620000de8262000124565b50505062000688565b620000f2836200017f565b600082511180620001005750805b156200011f576200011d8383620001c160201b620002ff1760201c565b505b505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6200014f620001f0565b604080516001600160a01b03928316815291841660208301520160405180910390a16200017c8162000229565b50565b6200018a81620002de565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b6060620001e983836040518060600160405280602781526020016200118b6027913962000381565b9392505050565b60006200021a6000805160206200114b83398151915260001b6200046760201b620002731760201c565b546001600160a01b0316919050565b6001600160a01b038116620002945760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b60648201526084015b60405180910390fd5b80620002bd6000805160206200114b83398151915260001b6200046760201b620002731760201c565b80546001600160a01b0319166001600160a01b039290921691909117905550565b620002f4816200046a60201b6200032b1760201c565b620003585760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b60648201526084016200028b565b80620002bd6000805160206200116b83398151915260001b6200046760201b620002731760201c565b60606001600160a01b0384163b620003eb5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f6044820152651b9d1c9858dd60d21b60648201526084016200028b565b600080856001600160a01b03168560405162000408919062000635565b600060405180830381855af49150503d806000811462000445576040519150601f19603f3d011682016040523d82523d6000602084013e6200044a565b606091505b5090925090506200045d82828662000479565b9695505050505050565b90565b6001600160a01b03163b151590565b606083156200048a575081620001e9565b8251156200049b5782518084602001fd5b8160405162461bcd60e51b81526004016200028b919062000653565b80516001600160a01b0381168114620004cf57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60005b8381101562000507578181015183820152602001620004ed565b838111156200011d5750506000910152565b6000806000606084860312156200052f57600080fd5b6200053a84620004b7565b92506200054a60208501620004b7565b60408501519092506001600160401b03808211156200056857600080fd5b818601915086601f8301126200057d57600080fd5b815181811115620005925762000592620004d4565b604051601f8201601f19908116603f01168101908382118183101715620005bd57620005bd620004d4565b81604052828152896020848701011115620005d757600080fd5b620005ea836020830160208801620004ea565b80955050505050509250925092565b6000828210156200061a57634e487b7160e01b600052601160045260246000fd5b500390565b634e487b7160e01b600052600160045260246000fd5b6000825162000649818460208701620004ea565b9190910192915050565b602081526000825180602084015262000674816040850160208701620004ea565b601f01601f19169190910160400192915050565b610ab380620006986000396000f3fe60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100a85780638f283970146100e6578063f851a440146101065761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61011b565b005b61006b61011b565b34801561008157600080fd5b5061006b61009036600461091f565b610135565b61006b6100a336600461093a565b610196565b3480156100b457600080fd5b506100bd610221565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b3480156100f257600080fd5b5061006b61010136600461091f565b610276565b34801561011257600080fd5b506100bd6102ba565b610123610347565b61013361012e610435565b61043f565b565b61013d610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561018e5761018b816040518060200160405280600081525060006104a3565b50565b61018b61011b565b61019e610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415610219576102148383838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250600192506104a3915050565b505050565b61021461011b565b600061022b610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561026b57610266610435565b905090565b61027361011b565b90565b61027e610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561018e5761018b816104ce565b60006102c4610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561026b57610266610463565b60606103248383604051806060016040528060278152602001610a576027913961052f565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b61034f610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415610133576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f7879207461726760648201527f6574000000000000000000000000000000000000000000000000000000000000608482015260a4015b60405180910390fd5b6000610266610657565b3660008037600080366000845af43d6000803e80801561045e573d6000f35b3d6000fd5b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b5473ffffffffffffffffffffffffffffffffffffffff16919050565b6104ac8361067f565b6000825111806104b95750805b15610214576104c883836102ff565b50505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6104f7610463565b6040805173ffffffffffffffffffffffffffffffffffffffff928316815291841660208301520160405180910390a161018b816106cc565b606073ffffffffffffffffffffffffffffffffffffffff84163b6105d5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f60448201527f6e74726163740000000000000000000000000000000000000000000000000000606482015260840161042c565b6000808573ffffffffffffffffffffffffffffffffffffffff16856040516105fd91906109e9565b600060405180830381855af49150503d8060008114610638576040519150601f19603f3d011682016040523d82523d6000602084013e61063d565b606091505b509150915061064d8282866107d8565b9695505050505050565b60007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc610487565b6106888161082b565b60405173ffffffffffffffffffffffffffffffffffffffff8216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b73ffffffffffffffffffffffffffffffffffffffff811661076f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201527f6464726573730000000000000000000000000000000000000000000000000000606482015260840161042c565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9290921691909117905550565b606083156107e7575081610324565b8251156107f75782518084602001fd5b816040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161042c9190610a05565b73ffffffffffffffffffffffffffffffffffffffff81163b6108cf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201527f6f74206120636f6e747261637400000000000000000000000000000000000000606482015260840161042c565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc610792565b803573ffffffffffffffffffffffffffffffffffffffff8116811461091a57600080fd5b919050565b60006020828403121561093157600080fd5b610324826108f6565b60008060006040848603121561094f57600080fd5b610958846108f6565b9250602084013567ffffffffffffffff8082111561097557600080fd5b818601915086601f83011261098957600080fd5b81358181111561099857600080fd5b8760208285010111156109aa57600080fd5b6020830194508093505050509250925092565b60005b838110156109d85781810151838201526020016109c0565b838111156104c85750506000910152565b600082516109fb8184602087016109bd565b9190910192915050565b6020815260008251806020840152610a248160408501602087016109bd565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220b29caa54336b3ee836679675e9732ec5e526fb3f803cca2fe336cc3555aba62264736f6c634300080a0033b53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564", + "deployedBytecode": "0x60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100a85780638f283970146100e6578063f851a440146101065761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61011b565b005b61006b61011b565b34801561008157600080fd5b5061006b61009036600461091f565b610135565b61006b6100a336600461093a565b610196565b3480156100b457600080fd5b506100bd610221565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b3480156100f257600080fd5b5061006b61010136600461091f565b610276565b34801561011257600080fd5b506100bd6102ba565b610123610347565b61013361012e610435565b61043f565b565b61013d610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561018e5761018b816040518060200160405280600081525060006104a3565b50565b61018b61011b565b61019e610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415610219576102148383838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250600192506104a3915050565b505050565b61021461011b565b600061022b610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561026b57610266610435565b905090565b61027361011b565b90565b61027e610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561018e5761018b816104ce565b60006102c4610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561026b57610266610463565b60606103248383604051806060016040528060278152602001610a576027913961052f565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b61034f610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415610133576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f7879207461726760648201527f6574000000000000000000000000000000000000000000000000000000000000608482015260a4015b60405180910390fd5b6000610266610657565b3660008037600080366000845af43d6000803e80801561045e573d6000f35b3d6000fd5b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b5473ffffffffffffffffffffffffffffffffffffffff16919050565b6104ac8361067f565b6000825111806104b95750805b15610214576104c883836102ff565b50505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6104f7610463565b6040805173ffffffffffffffffffffffffffffffffffffffff928316815291841660208301520160405180910390a161018b816106cc565b606073ffffffffffffffffffffffffffffffffffffffff84163b6105d5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f60448201527f6e74726163740000000000000000000000000000000000000000000000000000606482015260840161042c565b6000808573ffffffffffffffffffffffffffffffffffffffff16856040516105fd91906109e9565b600060405180830381855af49150503d8060008114610638576040519150601f19603f3d011682016040523d82523d6000602084013e61063d565b606091505b509150915061064d8282866107d8565b9695505050505050565b60007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc610487565b6106888161082b565b60405173ffffffffffffffffffffffffffffffffffffffff8216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b73ffffffffffffffffffffffffffffffffffffffff811661076f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201527f6464726573730000000000000000000000000000000000000000000000000000606482015260840161042c565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9290921691909117905550565b606083156107e7575081610324565b8251156107f75782518084602001fd5b816040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161042c9190610a05565b73ffffffffffffffffffffffffffffffffffffffff81163b6108cf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201527f6f74206120636f6e747261637400000000000000000000000000000000000000606482015260840161042c565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc610792565b803573ffffffffffffffffffffffffffffffffffffffff8116811461091a57600080fd5b919050565b60006020828403121561093157600080fd5b610324826108f6565b60008060006040848603121561094f57600080fd5b610958846108f6565b9250602084013567ffffffffffffffff8082111561097557600080fd5b818601915086601f83011261098957600080fd5b81358181111561099857600080fd5b8760208285010111156109aa57600080fd5b6020830194508093505050509250925092565b60005b838110156109d85781810151838201526020016109c0565b838111156104c85750506000910152565b600082516109fb8184602087016109bd565b9190910192915050565b6020815260008251806020840152610a248160408501602087016109bd565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220b29caa54336b3ee836679675e9732ec5e526fb3f803cca2fe336cc3555aba62264736f6c634300080a0033", + "devdoc": { + "details": "This contract implements a proxy that is upgradeable by an admin. To avoid https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector clashing], which can potentially be used in an attack, this contract uses the https://blog.openzeppelin.com/the-transparent-proxy-pattern/[transparent proxy pattern]. This pattern implies two things that go hand in hand: 1. If any account other than the admin calls the proxy, the call will be forwarded to the implementation, even if that call matches one of the admin functions exposed by the proxy itself. 2. If the admin calls the proxy, it can access the admin functions, but its calls will never be forwarded to the implementation. If the admin tries to call a function on the implementation it will fail with an error that says \"admin cannot fallback to proxy target\". These properties mean that the admin account can only be used for admin actions like upgrading the proxy or changing the admin, so it's best if it's a dedicated account that is not used for anything else. This will avoid headaches due to sudden errors when trying to call a function from the proxy implementation. Our recommendation is for the dedicated account to be an instance of the {ProxyAdmin} contract. If set up this way, you should think of the `ProxyAdmin` instance as the real administrative interface of your proxy.", + "kind": "dev", + "methods": { + "admin()": { + "details": "Returns the current admin. NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyAdmin}. TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call. `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`" + }, + "changeAdmin(address)": { + "details": "Changes the admin of the proxy. Emits an {AdminChanged} event. NOTE: Only the admin can call this function. See {ProxyAdmin-changeProxyAdmin}." + }, + "constructor": { + "details": "Initializes an upgradeable proxy managed by `_admin`, backed by the implementation at `_logic`, and optionally initialized with `_data` as explained in {ERC1967Proxy-constructor}." + }, + "implementation()": { + "details": "Returns the current implementation. NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyImplementation}. TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call. `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc`" + }, + "upgradeTo(address)": { + "details": "Upgrade the implementation of the proxy. NOTE: Only the admin can call this function. See {ProxyAdmin-upgrade}." + }, + "upgradeToAndCall(address,bytes)": { + "details": "Upgrade the implementation of the proxy, and then call a function from the new implementation as specified by `data`, which should be an encoded function call. This is useful to initialize new storage variables in the proxied contract. NOTE: Only the admin can call this function. See {ProxyAdmin-upgradeAndCall}." + } + }, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [], + "types": null + } +} diff --git a/deployments/bsctestnet/VToken_vSnBNB_LiquidStakedBNB.json b/deployments/bsctestnet/VToken_vSnBNB_LiquidStakedBNB.json new file mode 100644 index 000000000..68fd3f419 --- /dev/null +++ b/deployments/bsctestnet/VToken_vSnBNB_LiquidStakedBNB.json @@ -0,0 +1,246 @@ +{ + "address": "0xeffE7874C345aE877c1D893cd5160DDD359b24dA", + "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": "0xb74dd8de42258df7a7751664743d99fe354e1d37ccc5d12c5e9f7f10ac234ca6", + "receipt": { + "to": null, + "from": "0x9cc6F5f16498fCEEf4D00A350Bd8F8921D304Dc9", + "contractAddress": "0xeffE7874C345aE877c1D893cd5160DDD359b24dA", + "transactionIndex": 1, + "gasUsed": "676026", + "logsBloom": "0x00000000400400000000000000020000000004000000000000800000000804000000000000000040000000020000000000000000000000100040000800048040001000000000000000000000001000004001000000040000800000000000002000000000020000000080000000000800000800000000000000000000000000400000000000000000000000000000080000000000000080100000000000000000000000040000000100000002000400000000000010880000000001000000004000000024000000000002000000040000000000000000100000800000000060000000000000000000000000800000040400000800000004000000004000010000", + "blockHash": "0x712ca9f2ff743cb2d596489acfa787d1c16fbb2bf7faed002a192222a1a18c47", + "transactionHash": "0xb74dd8de42258df7a7751664743d99fe354e1d37ccc5d12c5e9f7f10ac234ca6", + "logs": [ + { + "transactionIndex": 1, + "blockNumber": 33673404, + "transactionHash": "0xb74dd8de42258df7a7751664743d99fe354e1d37ccc5d12c5e9f7f10ac234ca6", + "address": "0xeffE7874C345aE877c1D893cd5160DDD359b24dA", + "topics": [ + "0x1cf3b03a6cf19fa2baba4df148e9dcabedea7f8a5c07840e207e5c089be95d3e", + "0x0000000000000000000000001103bec24eb194d69ae116d62dd9559412e7c23a" + ], + "data": "0x", + "logIndex": 0, + "blockHash": "0x712ca9f2ff743cb2d596489acfa787d1c16fbb2bf7faed002a192222a1a18c47" + }, + { + "transactionIndex": 1, + "blockNumber": 33673404, + "transactionHash": "0xb74dd8de42258df7a7751664743d99fe354e1d37ccc5d12c5e9f7f10ac234ca6", + "address": "0xeffE7874C345aE877c1D893cd5160DDD359b24dA", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000009cc6f5f16498fceef4d00a350bd8f8921d304dc9" + ], + "data": "0x", + "logIndex": 1, + "blockHash": "0x712ca9f2ff743cb2d596489acfa787d1c16fbb2bf7faed002a192222a1a18c47" + }, + { + "transactionIndex": 1, + "blockNumber": 33673404, + "transactionHash": "0xb74dd8de42258df7a7751664743d99fe354e1d37ccc5d12c5e9f7f10ac234ca6", + "address": "0xeffE7874C345aE877c1D893cd5160DDD359b24dA", + "topics": ["0x66fd58e82f7b31a2a5c30e0888f3093efe4e111b00cd2b0c31fe014601293aa0"], + "data": "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000045f8a08f534f34a97187626e05d4b6648eeaa9aa", + "logIndex": 2, + "blockHash": "0x712ca9f2ff743cb2d596489acfa787d1c16fbb2bf7faed002a192222a1a18c47" + }, + { + "transactionIndex": 1, + "blockNumber": 33673404, + "transactionHash": "0xb74dd8de42258df7a7751664743d99fe354e1d37ccc5d12c5e9f7f10ac234ca6", + "address": "0xeffE7874C345aE877c1D893cd5160DDD359b24dA", + "topics": [ + "0x7ac369dbd14fa5ea3f473ed67cc9d598964a77501540ba6751eb0b3decf5870d", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000596b11acaacf03217287939f88d63b51d3771704" + ], + "data": "0x", + "logIndex": 3, + "blockHash": "0x712ca9f2ff743cb2d596489acfa787d1c16fbb2bf7faed002a192222a1a18c47" + }, + { + "transactionIndex": 1, + "blockNumber": 33673404, + "transactionHash": "0xb74dd8de42258df7a7751664743d99fe354e1d37ccc5d12c5e9f7f10ac234ca6", + "address": "0xeffE7874C345aE877c1D893cd5160DDD359b24dA", + "topics": [ + "0xedffc32e068c7c95dfd4bdfd5c4d939a084d6b11c4199eac8436ed234d72f926", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000009d812a63a5e33f2fc54810f71466fed862a5ef28" + ], + "data": "0x", + "logIndex": 4, + "blockHash": "0x712ca9f2ff743cb2d596489acfa787d1c16fbb2bf7faed002a192222a1a18c47" + }, + { + "transactionIndex": 1, + "blockNumber": 33673404, + "transactionHash": "0xb74dd8de42258df7a7751664743d99fe354e1d37ccc5d12c5e9f7f10ac234ca6", + "address": "0xeffE7874C345aE877c1D893cd5160DDD359b24dA", + "topics": ["0xaaa68312e2ea9d50e16af5068410ab56e1a1fd06037b1a35664812c30f821460"], + "data": "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003782dace9d90000", + "logIndex": 5, + "blockHash": "0x712ca9f2ff743cb2d596489acfa787d1c16fbb2bf7faed002a192222a1a18c47" + }, + { + "transactionIndex": 1, + "blockNumber": 33673404, + "transactionHash": "0xb74dd8de42258df7a7751664743d99fe354e1d37ccc5d12c5e9f7f10ac234ca6", + "address": "0xeffE7874C345aE877c1D893cd5160DDD359b24dA", + "topics": [ + "0x6dbf1ff28f860de5edafa4c6505e37c0aba213288cc4166c5352b6d3776c79ef", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000001" + ], + "data": "0x", + "logIndex": 6, + "blockHash": "0x712ca9f2ff743cb2d596489acfa787d1c16fbb2bf7faed002a192222a1a18c47" + }, + { + "transactionIndex": 1, + "blockNumber": 33673404, + "transactionHash": "0xb74dd8de42258df7a7751664743d99fe354e1d37ccc5d12c5e9f7f10ac234ca6", + "address": "0xeffE7874C345aE877c1D893cd5160DDD359b24dA", + "topics": [ + "0xafec95c8612496c3ecf5dddc71e393528fe29bd145fbaf9c6b496d78d7e2d79b", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000008b293600c50d6fbdc6ed4251cc75ece29880276f" + ], + "data": "0x", + "logIndex": 7, + "blockHash": "0x712ca9f2ff743cb2d596489acfa787d1c16fbb2bf7faed002a192222a1a18c47" + }, + { + "transactionIndex": 1, + "blockNumber": 33673404, + "transactionHash": "0xb74dd8de42258df7a7751664743d99fe354e1d37ccc5d12c5e9f7f10ac234ca6", + "address": "0xeffE7874C345aE877c1D893cd5160DDD359b24dA", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000009cc6f5f16498fceef4d00a350bd8f8921d304dc9", + "0x000000000000000000000000ce10739590001705f7ff231611ba4a48b2820327" + ], + "data": "0x", + "logIndex": 8, + "blockHash": "0x712ca9f2ff743cb2d596489acfa787d1c16fbb2bf7faed002a192222a1a18c47" + }, + { + "transactionIndex": 1, + "blockNumber": 33673404, + "transactionHash": "0xb74dd8de42258df7a7751664743d99fe354e1d37ccc5d12c5e9f7f10ac234ca6", + "address": "0xeffE7874C345aE877c1D893cd5160DDD359b24dA", + "topics": ["0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498"], + "data": "0x0000000000000000000000000000000000000000000000000000000000000001", + "logIndex": 9, + "blockHash": "0x712ca9f2ff743cb2d596489acfa787d1c16fbb2bf7faed002a192222a1a18c47" + } + ], + "blockNumber": 33673404, + "cumulativeGasUsed": "707267", + "status": 1, + "byzantium": true + }, + "args": [ + "0x1103Bec24Eb194d69ae116d62DD9559412E7C23A", + "0x8a42c319000000000000000000000000d2af6a916bc77764dc63742bc30f71af4cf423f4000000000000000000000000596b11acaacf03217287939f88d63b51d37717040000000000000000000000009d812a63a5e33f2fc54810f71466fed862a5ef280000000000000000000000000000000000000000204fce5e3e25026110000000000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000001c00000000000000000000000000000000000000000000000000000000000000008000000000000000000000000ce10739590001705f7ff231611ba4a48b282032700000000000000000000000045f8a08f534f34a97187626e05d4b6648eeaa9aa00000000000000000000000000000000000000000000000000000000000000010000000000000000000000008b293600c50d6fbdc6ed4251cc75ece29880276f00000000000000000000000000000000000000000000000003782dace9d90000000000000000000000000000000000000000000000000000000000000000001f56656e757320536e424e4220284c6971756964205374616b656420424e422900000000000000000000000000000000000000000000000000000000000000001676536e424e425f4c69717569645374616b6564424e4200000000000000000000" + ], + "numDeployments": 1, + "solcInputHash": "6d4db51b84097a74598623a15df3d6fb", + "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/6d4db51b84097a74598623a15df3d6fb.json b/deployments/bsctestnet/solcInputs/6d4db51b84097a74598623a15df3d6fb.json new file mode 100644 index 000000000..b8f55c44b --- /dev/null +++ b/deployments/bsctestnet/solcInputs/6d4db51b84097a74598623a15df3d6fb.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 { 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 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 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/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 { 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/helpers/deploymentConfig.ts b/helpers/deploymentConfig.ts index 63c80a843..63c5605a8 100644 --- a/helpers/deploymentConfig.ts +++ b/helpers/deploymentConfig.ts @@ -660,6 +660,13 @@ export const globalConfig: NetworkConfig = { decimals: 18, tokenAddress: ethers.constants.AddressZero, }, + { + isMock: false, + name: "Synclub Staked BNB", + symbol: "SnBNB", + decimals: 18, + tokenAddress: "0xd2aF6A916Bc77764dc63742BC30f71AF4cF423F4", + }, ], poolConfig: [ { @@ -1061,6 +1068,23 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit("1600000", 18), vTokenReceiver: "0x3DdfA8eC3052539b6C9549F12cEA2C295cfF5296", }, + { + name: "Venus SnBNB (Liquid Staked BNB)", + asset: "SnBNB", + symbol: "vSnBNB_LiquidStakedBNB", + rateModel: InterestRateModels.JumpRate.toString(), + baseRatePerYear: convertToUnit("0.02", 18), + multiplierPerYear: convertToUnit("0.2", 18), + jumpMultiplierPerYear: convertToUnit("3", 18), + kink_: convertToUnit("0.5", 18), + collateralFactor: convertToUnit("0.87", 18), + liquidationThreshold: convertToUnit("0.9", 18), + reserveFactor: convertToUnit("0.25", 18), + initialSupply: convertToUnit("47", 18), + supplyCap: convertToUnit("1000", 18), + borrowCap: convertToUnit("100", 18), + vTokenReceiver: "0xDC2D855A95Ee70d7282BebD35c96f905CDE31f55", + }, ], rewards: [ { @@ -1087,6 +1111,12 @@ export const globalConfig: NetworkConfig = { supplySpeeds: ["1157407407407407"], // 1000 SD over 30 days (864000 blocks) borrowSpeeds: ["1157407407407407"], // 1000 SD over 30 days (864000 blocks) }, + { + asset: "HAY", + markets: ["SnBNB"], + supplySpeeds: ["930059523809523"], // 1500 HAY over 56 days (1612800 blocks) + borrowSpeeds: ["930059523809523"], // 1500 HAY over 56 days (1612800 blocks) + }, ], }, { @@ -1363,6 +1393,13 @@ export const globalConfig: NetworkConfig = { decimals: 18, tokenAddress: "0x3BC5AC0dFdC871B365d159f728dd1B9A0B5481E8", }, + { + isMock: false, + name: "Synclub Staked BNB", + symbol: "SnBNB", + decimals: 18, + tokenAddress: "0xB0b84D294e0C75A6abe60171b70edEb2EFd14A1B", + }, ], poolConfig: [ { @@ -1766,6 +1803,23 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit("1600000", 18), vTokenReceiver: "0x3DdfA8eC3052539b6C9549F12cEA2C295cfF5296", }, + { + name: "Venus SnBNB (Liquid Staked BNB)", + asset: "SnBNB", + symbol: "vSnBNB_LiquidStakedBNB", + rateModel: InterestRateModels.JumpRate.toString(), + baseRatePerYear: convertToUnit("0.02", 18), + multiplierPerYear: convertToUnit("0.2", 18), + jumpMultiplierPerYear: convertToUnit("3", 18), + kink_: convertToUnit("0.5", 18), + collateralFactor: convertToUnit("0.87", 18), + liquidationThreshold: convertToUnit("0.9", 18), + reserveFactor: convertToUnit("0.25", 18), + initialSupply: convertToUnit("47", 18), + supplyCap: convertToUnit("1000", 18), + borrowCap: convertToUnit("100", 18), + vTokenReceiver: "0xDC2D855A95Ee70d7282BebD35c96f905CDE31f55", + }, ], rewards: [ { @@ -1792,6 +1846,12 @@ export const globalConfig: NetworkConfig = { supplySpeeds: ["1157407407407407"], // 1000 SD over 30 days (864000 blocks) borrowSpeeds: ["1157407407407407"], // 1000 SD over 30 days (864000 blocks) }, + { + asset: "HAY", + markets: ["SnBNB"], + supplySpeeds: ["930059523809523"], // 1500 HAY over 56 days (1612800 blocks) + borrowSpeeds: ["930059523809523"], // 1500 HAY over 56 days (1612800 blocks) + }, ], }, { From 667ac5feeedf0a7337258389f16110df864948cb Mon Sep 17 00:00:00 2001 From: GitGuru7 <128375421+GitGuru7@users.noreply.github.com> Date: Thu, 28 Sep 2023 12:50:41 +0530 Subject: [PATCH 09/33] feat: add deployments of agEUR market --- deployments/bscmainnet.json | 375 +++++++ ...slope1000bps_jump25000bps_kink5000bps.json | 497 +++++++++ .../bscmainnet/VToken_vagEUR_Stablecoins.json | 246 +++++ .../6d4db51b84097a74598623a15df3d6fb.json | 285 +++++ deployments/bsctestnet.json | 986 +++++++++++++++--- ...slope1000bps_jump25000bps_kink5000bps.json | 497 +++++++++ deployments/bsctestnet/MockagEUR.json | 450 ++++++++ .../bsctestnet/VToken_vagEUR_Stablecoins.json | 246 +++++ .../6d4db51b84097a74598623a15df3d6fb.json | 285 +++++ helpers/deploymentConfig.ts | 48 + 10 files changed, 3764 insertions(+), 151 deletions(-) create mode 100644 deployments/bscmainnet/JumpRateModelV2_base200bps_slope1000bps_jump25000bps_kink5000bps.json create mode 100644 deployments/bscmainnet/VToken_vagEUR_Stablecoins.json create mode 100644 deployments/bscmainnet/solcInputs/6d4db51b84097a74598623a15df3d6fb.json create mode 100644 deployments/bsctestnet/JumpRateModelV2_base200bps_slope1000bps_jump25000bps_kink5000bps.json create mode 100644 deployments/bsctestnet/MockagEUR.json create mode 100644 deployments/bsctestnet/VToken_vagEUR_Stablecoins.json create mode 100644 deployments/bsctestnet/solcInputs/6d4db51b84097a74598623a15df3d6fb.json diff --git a/deployments/bscmainnet.json b/deployments/bscmainnet.json index 32cff70ff..76a93e531 100644 --- a/deployments/bscmainnet.json +++ b/deployments/bscmainnet.json @@ -2311,6 +2311,307 @@ } ] }, + "JumpRateModelV2_base200bps_slope1000bps_jump25000bps_kink5000bps": { + "address": "0x0820d5DA817Ac2eAf3757829B255B56354188bd1", + "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_slope1000bps_jump30000bps_kink8000bps": { "address": "0x4021Da92B4e64126Cd5A2d6B305FB0e9e4ed2024", "abi": [ @@ -42573,6 +42874,80 @@ } ] }, + "VToken_vagEUR_Stablecoins": { + "address": "0x1a9D2862028F6f5E6C299A7AC3C285508942b15E", + "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_vankrBNB_DeFi": { "address": "0x53728FD51060a85ac41974C6C3Eb1DaE42776723", "abi": [ diff --git a/deployments/bscmainnet/JumpRateModelV2_base200bps_slope1000bps_jump25000bps_kink5000bps.json b/deployments/bscmainnet/JumpRateModelV2_base200bps_slope1000bps_jump25000bps_kink5000bps.json new file mode 100644 index 000000000..1eff07166 --- /dev/null +++ b/deployments/bscmainnet/JumpRateModelV2_base200bps_slope1000bps_jump25000bps_kink5000bps.json @@ -0,0 +1,497 @@ +{ + "address": "0x0820d5DA817Ac2eAf3757829B255B56354188bd1", + "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": "0x86c21b946ffe7c3a105ed56cff0557172bf7ee5829301496ab8af938574e0b94", + "receipt": { + "to": null, + "from": "0x12Bdf8Ae9fE2047809080412d7341044b910ef10", + "contractAddress": "0x0820d5DA817Ac2eAf3757829B255B56354188bd1", + "transactionIndex": 61, + "gasUsed": "554524", + "logsBloom": "0x00000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000004004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000080000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x8a2f483d3543ca79998209faebe1fc11d7fb608d0e35dad40536b266226bba4b", + "transactionHash": "0x86c21b946ffe7c3a105ed56cff0557172bf7ee5829301496ab8af938574e0b94", + "logs": [ + { + "transactionIndex": 61, + "blockNumber": 32129380, + "transactionHash": "0x86c21b946ffe7c3a105ed56cff0557172bf7ee5829301496ab8af938574e0b94", + "address": "0x0820d5DA817Ac2eAf3757829B255B56354188bd1", + "topics": ["0x6960ab234c7ef4b0c9197100f5393cfcde7c453ac910a27bd2000aa1dd4c068d"], + "data": "0x0000000000000000000000000000000000000000000000000000000071672e7f000000000000000000000000000000000000000000000000000000023703e87b000000000000000000000000000000000000000000000000000000375f61b40600000000000000000000000000000000000000000000000006f05b59d3b20000", + "logIndex": 180, + "blockHash": "0x8a2f483d3543ca79998209faebe1fc11d7fb608d0e35dad40536b266226bba4b" + } + ], + "blockNumber": 32129380, + "cumulativeGasUsed": "16037261", + "status": 1, + "byzantium": true + }, + "args": [ + "20000000000000000", + "100000000000000000", + "2500000000000000000", + "500000000000000000", + "0x4788629ABc6cFCA10F9f969efdEAa1cF70c23555" + ], + "numDeployments": 1, + "solcInputHash": "6d4db51b84097a74598623a15df3d6fb", + "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": 6106, + "contract": "contracts/JumpRateModelV2.sol:JumpRateModelV2", + "label": "accessControlManager", + "offset": 0, + "slot": "0", + "type": "t_contract(IAccessControlManagerV8)5203" + }, + { + "astId": 6109, + "contract": "contracts/JumpRateModelV2.sol:JumpRateModelV2", + "label": "multiplierPerBlock", + "offset": 0, + "slot": "1", + "type": "t_uint256" + }, + { + "astId": 6112, + "contract": "contracts/JumpRateModelV2.sol:JumpRateModelV2", + "label": "baseRatePerBlock", + "offset": 0, + "slot": "2", + "type": "t_uint256" + }, + { + "astId": 6115, + "contract": "contracts/JumpRateModelV2.sol:JumpRateModelV2", + "label": "jumpMultiplierPerBlock", + "offset": 0, + "slot": "3", + "type": "t_uint256" + }, + { + "astId": 6118, + "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/VToken_vagEUR_Stablecoins.json b/deployments/bscmainnet/VToken_vagEUR_Stablecoins.json new file mode 100644 index 000000000..97b93bb71 --- /dev/null +++ b/deployments/bscmainnet/VToken_vagEUR_Stablecoins.json @@ -0,0 +1,246 @@ +{ + "address": "0x1a9D2862028F6f5E6C299A7AC3C285508942b15E", + "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": "0x6feefa919796851a92bad7a4628b1d13966480210b1f203fa97c8daa0b025aa2", + "receipt": { + "to": null, + "from": "0x12Bdf8Ae9fE2047809080412d7341044b910ef10", + "contractAddress": "0x1a9D2862028F6f5E6C299A7AC3C285508942b15E", + "transactionIndex": 81, + "gasUsed": "683212", + "logsBloom": "0x00000000400400000000001000000000000001000000000000808000000000000000000000000040000840020000000000400000000000000000000840048000001000000000000000000000001000800001000002040000000000080000002000000000020000000080000000000800000002080000000000000000000000400000000000000008000000000000080000000000080080140000000000000000000000000000000100000000000400000000000000800000000000000000004000000004000000000002000000040000000000000000080000840000000060000040000000000002000000800000000400000800000000000000000800010000", + "blockHash": "0xcd5322bb8023a14559b40450baa607e4380fc265810776182b1c51cdd9df73ba", + "transactionHash": "0x6feefa919796851a92bad7a4628b1d13966480210b1f203fa97c8daa0b025aa2", + "logs": [ + { + "transactionIndex": 81, + "blockNumber": 32129384, + "transactionHash": "0x6feefa919796851a92bad7a4628b1d13966480210b1f203fa97c8daa0b025aa2", + "address": "0x1a9D2862028F6f5E6C299A7AC3C285508942b15E", + "topics": [ + "0x1cf3b03a6cf19fa2baba4df148e9dcabedea7f8a5c07840e207e5c089be95d3e", + "0x0000000000000000000000002b8a1c539abac89cbf7e2bc6987a0a38a5e660d4" + ], + "data": "0x", + "logIndex": 137, + "blockHash": "0xcd5322bb8023a14559b40450baa607e4380fc265810776182b1c51cdd9df73ba" + }, + { + "transactionIndex": 81, + "blockNumber": 32129384, + "transactionHash": "0x6feefa919796851a92bad7a4628b1d13966480210b1f203fa97c8daa0b025aa2", + "address": "0x1a9D2862028F6f5E6C299A7AC3C285508942b15E", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x00000000000000000000000012bdf8ae9fe2047809080412d7341044b910ef10" + ], + "data": "0x", + "logIndex": 138, + "blockHash": "0xcd5322bb8023a14559b40450baa607e4380fc265810776182b1c51cdd9df73ba" + }, + { + "transactionIndex": 81, + "blockNumber": 32129384, + "transactionHash": "0x6feefa919796851a92bad7a4628b1d13966480210b1f203fa97c8daa0b025aa2", + "address": "0x1a9D2862028F6f5E6C299A7AC3C285508942b15E", + "topics": ["0x66fd58e82f7b31a2a5c30e0888f3093efe4e111b00cd2b0c31fe014601293aa0"], + "data": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000004788629abc6cfca10f9f969efdeaa1cf70c23555", + "logIndex": 139, + "blockHash": "0xcd5322bb8023a14559b40450baa607e4380fc265810776182b1c51cdd9df73ba" + }, + { + "transactionIndex": 81, + "blockNumber": 32129384, + "transactionHash": "0x6feefa919796851a92bad7a4628b1d13966480210b1f203fa97c8daa0b025aa2", + "address": "0x1a9D2862028F6f5E6C299A7AC3C285508942b15E", + "topics": [ + "0x7ac369dbd14fa5ea3f473ed67cc9d598964a77501540ba6751eb0b3decf5870d", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x00000000000000000000000094c1495cd4c557f1560cbd68eab0d197e6291571" + ], + "data": "0x", + "logIndex": 140, + "blockHash": "0xcd5322bb8023a14559b40450baa607e4380fc265810776182b1c51cdd9df73ba" + }, + { + "transactionIndex": 81, + "blockNumber": 32129384, + "transactionHash": "0x6feefa919796851a92bad7a4628b1d13966480210b1f203fa97c8daa0b025aa2", + "address": "0x1a9D2862028F6f5E6C299A7AC3C285508942b15E", + "topics": [ + "0xedffc32e068c7c95dfd4bdfd5c4d939a084d6b11c4199eac8436ed234d72f926", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000820d5da817ac2eaf3757829b255b56354188bd1" + ], + "data": "0x", + "logIndex": 141, + "blockHash": "0xcd5322bb8023a14559b40450baa607e4380fc265810776182b1c51cdd9df73ba" + }, + { + "transactionIndex": 81, + "blockNumber": 32129384, + "transactionHash": "0x6feefa919796851a92bad7a4628b1d13966480210b1f203fa97c8daa0b025aa2", + "address": "0x1a9D2862028F6f5E6C299A7AC3C285508942b15E", + "topics": ["0xaaa68312e2ea9d50e16af5068410ab56e1a1fd06037b1a35664812c30f821460"], + "data": "0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016345785d8a0000", + "logIndex": 142, + "blockHash": "0xcd5322bb8023a14559b40450baa607e4380fc265810776182b1c51cdd9df73ba" + }, + { + "transactionIndex": 81, + "blockNumber": 32129384, + "transactionHash": "0x6feefa919796851a92bad7a4628b1d13966480210b1f203fa97c8daa0b025aa2", + "address": "0x1a9D2862028F6f5E6C299A7AC3C285508942b15E", + "topics": [ + "0x6dbf1ff28f860de5edafa4c6505e37c0aba213288cc4166c5352b6d3776c79ef", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000001" + ], + "data": "0x", + "logIndex": 143, + "blockHash": "0xcd5322bb8023a14559b40450baa607e4380fc265810776182b1c51cdd9df73ba" + }, + { + "transactionIndex": 81, + "blockNumber": 32129384, + "transactionHash": "0x6feefa919796851a92bad7a4628b1d13966480210b1f203fa97c8daa0b025aa2", + "address": "0x1a9D2862028F6f5E6C299A7AC3C285508942b15E", + "topics": [ + "0xafec95c8612496c3ecf5dddc71e393528fe29bd145fbaf9c6b496d78d7e2d79b", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000f322942f644a996a617bd29c16bd7d231d9f35e9" + ], + "data": "0x", + "logIndex": 144, + "blockHash": "0xcd5322bb8023a14559b40450baa607e4380fc265810776182b1c51cdd9df73ba" + }, + { + "transactionIndex": 81, + "blockNumber": 32129384, + "transactionHash": "0x6feefa919796851a92bad7a4628b1d13966480210b1f203fa97c8daa0b025aa2", + "address": "0x1a9D2862028F6f5E6C299A7AC3C285508942b15E", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x00000000000000000000000012bdf8ae9fe2047809080412d7341044b910ef10", + "0x000000000000000000000000939bd8d64c0a9583a7dcea9933f7b21697ab6396" + ], + "data": "0x", + "logIndex": 145, + "blockHash": "0xcd5322bb8023a14559b40450baa607e4380fc265810776182b1c51cdd9df73ba" + }, + { + "transactionIndex": 81, + "blockNumber": 32129384, + "transactionHash": "0x6feefa919796851a92bad7a4628b1d13966480210b1f203fa97c8daa0b025aa2", + "address": "0x1a9D2862028F6f5E6C299A7AC3C285508942b15E", + "topics": ["0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498"], + "data": "0x0000000000000000000000000000000000000000000000000000000000000001", + "logIndex": 146, + "blockHash": "0xcd5322bb8023a14559b40450baa607e4380fc265810776182b1c51cdd9df73ba" + } + ], + "blockNumber": 32129384, + "cumulativeGasUsed": "8387324", + "status": 1, + "byzantium": true + }, + "args": [ + "0x2b8A1C539ABaC89CbF7E2Bc6987A0A38A5e660D4", + "0x8a42c31900000000000000000000000012f31b73d812c6bb0d735a218c086d44d5fe5f8900000000000000000000000094c1495cd4c557f1560cbd68eab0d197e62915710000000000000000000000000820d5da817ac2eaf3757829b255b56354188bd10000000000000000000000000000000000000000204fce5e3e25026110000000000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000001c00000000000000000000000000000000000000000000000000000000000000008000000000000000000000000939bd8d64c0a9583a7dcea9933f7b21697ab63960000000000000000000000004788629abc6cfca10f9f969efdeaa1cf70c235550000000000000000000000000000000000000000000000000000000000000001000000000000000000000000f322942f644a996a617bd29c16bd7d231d9f35e9000000000000000000000000000000000000000000000000016345785d8a0000000000000000000000000000000000000000000000000000000000000000001956656e75732061674555522028537461626c65636f696e73290000000000000000000000000000000000000000000000000000000000000000000000000000127661674555525f537461626c65636f696e730000000000000000000000000000" + ], + "numDeployments": 1, + "solcInputHash": "6d4db51b84097a74598623a15df3d6fb", + "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/bscmainnet/solcInputs/6d4db51b84097a74598623a15df3d6fb.json b/deployments/bscmainnet/solcInputs/6d4db51b84097a74598623a15df3d6fb.json new file mode 100644 index 000000000..b8f55c44b --- /dev/null +++ b/deployments/bscmainnet/solcInputs/6d4db51b84097a74598623a15df3d6fb.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 { 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 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 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/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 { 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/bsctestnet.json b/deployments/bsctestnet.json index fb97820ff..8fe165941 100644 --- a/deployments/bsctestnet.json +++ b/deployments/bsctestnet.json @@ -2140,8 +2140,8 @@ } ] }, - "JumpRateModelV2_base200bps_slope1000bps_jump30000bps_kink8000bps": { - "address": "0x42D9AFb65d2C89fB8bFF6Fe88eFC55922Ec3bD44", + "JumpRateModelV2_base200bps_slope1000bps_jump25000bps_kink5000bps": { + "address": "0x6Ba592934fD60d7A180d65cdb1C9BF561FeAD3D4", "abi": [ { "inputs": [ @@ -2441,8 +2441,8 @@ } ] }, - "JumpRateModelV2_base200bps_slope2000bps_jump30000bps_kink5000bps": { - "address": "0x9d812A63A5e33f2fC54810f71466FeD862A5eF28", + "JumpRateModelV2_base200bps_slope1000bps_jump30000bps_kink8000bps": { + "address": "0x42D9AFb65d2C89fB8bFF6Fe88eFC55922Ec3bD44", "abi": [ { "inputs": [ @@ -2742,8 +2742,8 @@ } ] }, - "JumpRateModelV2_base200bps_slope500bps_jump25000bps_kink6000bps": { - "address": "0x870BF9ba9b371297F4637f0686468E9a60cF5F12", + "JumpRateModelV2_base200bps_slope2000bps_jump30000bps_kink5000bps": { + "address": "0x9d812A63A5e33f2fC54810f71466FeD862A5eF28", "abi": [ { "inputs": [ @@ -3043,8 +3043,8 @@ } ] }, - "JumpRateModelV2_base300bps_slope1000bps_jump25000bps_kink6000bps": { - "address": "0x94d2E7Afb4ACe29D50f12BdfD35858D888e5fEA1", + "JumpRateModelV2_base200bps_slope500bps_jump25000bps_kink6000bps": { + "address": "0x870BF9ba9b371297F4637f0686468E9a60cF5F12", "abi": [ { "inputs": [ @@ -3344,8 +3344,8 @@ } ] }, - "JumpRateModelV2_base350bps_slope1000bps_jump30000bps_kink8000bps": { - "address": "0xC59C757D88c38F9d6B15FDae8D7026D694d1c4E5", + "JumpRateModelV2_base300bps_slope1000bps_jump25000bps_kink6000bps": { + "address": "0x94d2E7Afb4ACe29D50f12BdfD35858D888e5fEA1", "abi": [ { "inputs": [ @@ -3645,94 +3645,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", @@ -3746,54 +3760,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", @@ -3802,54 +3794,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", @@ -3857,17 +3840,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", @@ -3875,12 +3858,12 @@ }, { "inputs": [], - "name": "symbol", + "name": "kink", "outputs": [ { - "internalType": "string", + "internalType": "uint256", "name": "", - "type": "string" + "type": "uint256" } ], "stateMutability": "view", @@ -3888,7 +3871,7 @@ }, { "inputs": [], - "name": "totalSupply", + "name": "multiplierPerBlock", "outputs": [ { "internalType": "uint256", @@ -3902,60 +3885,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" } ] }, - "MockANKR": { - "address": "0xe4a90EB942CF2DA7238e8F6cC9EF510c49FC8B4B", + "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" + } + ] + }, + "MockANKR": { + "address": "0xe4a90EB942CF2DA7238e8F6cC9EF510c49FC8B4B", "abi": [ { "inputs": [ @@ -8280,6 +8581,315 @@ } ] }, + "MockagEUR": { + "address": "0x63061de4A25f24279AAab80400040684F92Ee319", + "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" + } + ] + }, "MockankrBNB": { "address": "0x167F1F9EF531b3576201aa3146b13c57dbEda514", "abi": [ @@ -47655,6 +48265,80 @@ } ] }, + "VToken_vagEUR_Stablecoins": { + "address": "0xa0571e758a00C586DbD53fb431d0f48eff9d0F15", + "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_vankrBNB_DeFi": { "address": "0xe507B30C41E9e375BCe05197c1e09fc9ee40c0f6", "abi": [ diff --git a/deployments/bsctestnet/JumpRateModelV2_base200bps_slope1000bps_jump25000bps_kink5000bps.json b/deployments/bsctestnet/JumpRateModelV2_base200bps_slope1000bps_jump25000bps_kink5000bps.json new file mode 100644 index 000000000..973f2a4e3 --- /dev/null +++ b/deployments/bsctestnet/JumpRateModelV2_base200bps_slope1000bps_jump25000bps_kink5000bps.json @@ -0,0 +1,497 @@ +{ + "address": "0x6Ba592934fD60d7A180d65cdb1C9BF561FeAD3D4", + "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": "0x6392f1aa73c5df56fcd7d844e9f0dc37b069d1d60f4ee63840c01ee86c913163", + "receipt": { + "to": null, + "from": "0xcd2a514f04241b7c9A0d5d54441e92E4611929CF", + "contractAddress": "0x6Ba592934fD60d7A180d65cdb1C9BF561FeAD3D4", + "transactionIndex": 0, + "gasUsed": "554524", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000020000000000000000080000000000000004000000000000000000000000080000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x8b9d09bc2c07da0f8c25add56055d864afbe6d100a828ac6e7b1806316491f55", + "transactionHash": "0x6392f1aa73c5df56fcd7d844e9f0dc37b069d1d60f4ee63840c01ee86c913163", + "logs": [ + { + "transactionIndex": 0, + "blockNumber": 33727990, + "transactionHash": "0x6392f1aa73c5df56fcd7d844e9f0dc37b069d1d60f4ee63840c01ee86c913163", + "address": "0x6Ba592934fD60d7A180d65cdb1C9BF561FeAD3D4", + "topics": ["0x6960ab234c7ef4b0c9197100f5393cfcde7c453ac910a27bd2000aa1dd4c068d"], + "data": "0x0000000000000000000000000000000000000000000000000000000071672e7f000000000000000000000000000000000000000000000000000000023703e87b000000000000000000000000000000000000000000000000000000375f61b40600000000000000000000000000000000000000000000000006f05b59d3b20000", + "logIndex": 0, + "blockHash": "0x8b9d09bc2c07da0f8c25add56055d864afbe6d100a828ac6e7b1806316491f55" + } + ], + "blockNumber": 33727990, + "cumulativeGasUsed": "554524", + "status": 1, + "byzantium": true + }, + "args": [ + "20000000000000000", + "100000000000000000", + "2500000000000000000", + "500000000000000000", + "0x45f8a08F534f34A97187626E05d4b6648Eeaa9AA" + ], + "numDeployments": 1, + "solcInputHash": "6d4db51b84097a74598623a15df3d6fb", + "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": 6106, + "contract": "contracts/JumpRateModelV2.sol:JumpRateModelV2", + "label": "accessControlManager", + "offset": 0, + "slot": "0", + "type": "t_contract(IAccessControlManagerV8)5203" + }, + { + "astId": 6109, + "contract": "contracts/JumpRateModelV2.sol:JumpRateModelV2", + "label": "multiplierPerBlock", + "offset": 0, + "slot": "1", + "type": "t_uint256" + }, + { + "astId": 6112, + "contract": "contracts/JumpRateModelV2.sol:JumpRateModelV2", + "label": "baseRatePerBlock", + "offset": 0, + "slot": "2", + "type": "t_uint256" + }, + { + "astId": 6115, + "contract": "contracts/JumpRateModelV2.sol:JumpRateModelV2", + "label": "jumpMultiplierPerBlock", + "offset": 0, + "slot": "3", + "type": "t_uint256" + }, + { + "astId": 6118, + "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/MockagEUR.json b/deployments/bsctestnet/MockagEUR.json new file mode 100644 index 000000000..06198e772 --- /dev/null +++ b/deployments/bsctestnet/MockagEUR.json @@ -0,0 +1,450 @@ +{ + "address": "0x63061de4A25f24279AAab80400040684F92Ee319", + "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": "0xd95693fb9659210edaa82ffe1adc66273c980d20f1f308678629af7281344154", + "receipt": { + "to": null, + "from": "0xcd2a514f04241b7c9A0d5d54441e92E4611929CF", + "contractAddress": "0x63061de4A25f24279AAab80400040684F92Ee319", + "transactionIndex": 0, + "gasUsed": "635980", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x7aae162d20ba9d6ba739bd764bb0a3266f422b2efc14544e44de572bf362cd09", + "transactionHash": "0xd95693fb9659210edaa82ffe1adc66273c980d20f1f308678629af7281344154", + "logs": [], + "blockNumber": 33727876, + "cumulativeGasUsed": "635980", + "status": 1, + "byzantium": true + }, + "args": ["agEUR", "agEUR", 18], + "numDeployments": 1, + "solcInputHash": "6d4db51b84097a74598623a15df3d6fb", + "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/VToken_vagEUR_Stablecoins.json b/deployments/bsctestnet/VToken_vagEUR_Stablecoins.json new file mode 100644 index 000000000..f13348ef3 --- /dev/null +++ b/deployments/bsctestnet/VToken_vagEUR_Stablecoins.json @@ -0,0 +1,246 @@ +{ + "address": "0xa0571e758a00C586DbD53fb431d0f48eff9d0F15", + "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": "0x16949b420db4e6e6db37a7f953eb0fd22e36f76b74fa5e26afdfa10bad9027a5", + "receipt": { + "to": null, + "from": "0xcd2a514f04241b7c9A0d5d54441e92E4611929CF", + "contractAddress": "0xa0571e758a00C586DbD53fb431d0f48eff9d0F15", + "transactionIndex": 1, + "gasUsed": "675894", + "logsBloom": "0x00000000000400000000000000000000000000000000000000800000000000000000000000800040000000020000000000000000000000000000000800048000021000000000000000000000001000000001000000040000800000000000002000000000021000000080000010080810000000000040000000000000040000400000100000000000000000000000080000000000000080100000000000000000000000040000000100000000000400000000000010800000000000000010004000000004000000000002200000040000000000000000100000800000000060000000040000000000000000800000040402010800000004000000004000010000", + "blockHash": "0x890ed17c6062fbbf0555dc1eb7e115f8554adbf0d123d288ab5d21ddf54f456e", + "transactionHash": "0x16949b420db4e6e6db37a7f953eb0fd22e36f76b74fa5e26afdfa10bad9027a5", + "logs": [ + { + "transactionIndex": 1, + "blockNumber": 33727995, + "transactionHash": "0x16949b420db4e6e6db37a7f953eb0fd22e36f76b74fa5e26afdfa10bad9027a5", + "address": "0xa0571e758a00C586DbD53fb431d0f48eff9d0F15", + "topics": [ + "0x1cf3b03a6cf19fa2baba4df148e9dcabedea7f8a5c07840e207e5c089be95d3e", + "0x000000000000000000000000bf85a90673e61956f8c79b9150bab7893b791bdd" + ], + "data": "0x", + "logIndex": 0, + "blockHash": "0x890ed17c6062fbbf0555dc1eb7e115f8554adbf0d123d288ab5d21ddf54f456e" + }, + { + "transactionIndex": 1, + "blockNumber": 33727995, + "transactionHash": "0x16949b420db4e6e6db37a7f953eb0fd22e36f76b74fa5e26afdfa10bad9027a5", + "address": "0xa0571e758a00C586DbD53fb431d0f48eff9d0F15", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000cd2a514f04241b7c9a0d5d54441e92e4611929cf" + ], + "data": "0x", + "logIndex": 1, + "blockHash": "0x890ed17c6062fbbf0555dc1eb7e115f8554adbf0d123d288ab5d21ddf54f456e" + }, + { + "transactionIndex": 1, + "blockNumber": 33727995, + "transactionHash": "0x16949b420db4e6e6db37a7f953eb0fd22e36f76b74fa5e26afdfa10bad9027a5", + "address": "0xa0571e758a00C586DbD53fb431d0f48eff9d0F15", + "topics": ["0x66fd58e82f7b31a2a5c30e0888f3093efe4e111b00cd2b0c31fe014601293aa0"], + "data": "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000045f8a08f534f34a97187626e05d4b6648eeaa9aa", + "logIndex": 2, + "blockHash": "0x890ed17c6062fbbf0555dc1eb7e115f8554adbf0d123d288ab5d21ddf54f456e" + }, + { + "transactionIndex": 1, + "blockNumber": 33727995, + "transactionHash": "0x16949b420db4e6e6db37a7f953eb0fd22e36f76b74fa5e26afdfa10bad9027a5", + "address": "0xa0571e758a00C586DbD53fb431d0f48eff9d0F15", + "topics": [ + "0x7ac369dbd14fa5ea3f473ed67cc9d598964a77501540ba6751eb0b3decf5870d", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x00000000000000000000000010b57706ad2345e590c2ea4dc02faef0d9f5b08b" + ], + "data": "0x", + "logIndex": 3, + "blockHash": "0x890ed17c6062fbbf0555dc1eb7e115f8554adbf0d123d288ab5d21ddf54f456e" + }, + { + "transactionIndex": 1, + "blockNumber": 33727995, + "transactionHash": "0x16949b420db4e6e6db37a7f953eb0fd22e36f76b74fa5e26afdfa10bad9027a5", + "address": "0xa0571e758a00C586DbD53fb431d0f48eff9d0F15", + "topics": [ + "0xedffc32e068c7c95dfd4bdfd5c4d939a084d6b11c4199eac8436ed234d72f926", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000006ba592934fd60d7a180d65cdb1c9bf561fead3d4" + ], + "data": "0x", + "logIndex": 4, + "blockHash": "0x890ed17c6062fbbf0555dc1eb7e115f8554adbf0d123d288ab5d21ddf54f456e" + }, + { + "transactionIndex": 1, + "blockNumber": 33727995, + "transactionHash": "0x16949b420db4e6e6db37a7f953eb0fd22e36f76b74fa5e26afdfa10bad9027a5", + "address": "0xa0571e758a00C586DbD53fb431d0f48eff9d0F15", + "topics": ["0xaaa68312e2ea9d50e16af5068410ab56e1a1fd06037b1a35664812c30f821460"], + "data": "0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016345785d8a0000", + "logIndex": 5, + "blockHash": "0x890ed17c6062fbbf0555dc1eb7e115f8554adbf0d123d288ab5d21ddf54f456e" + }, + { + "transactionIndex": 1, + "blockNumber": 33727995, + "transactionHash": "0x16949b420db4e6e6db37a7f953eb0fd22e36f76b74fa5e26afdfa10bad9027a5", + "address": "0xa0571e758a00C586DbD53fb431d0f48eff9d0F15", + "topics": [ + "0x6dbf1ff28f860de5edafa4c6505e37c0aba213288cc4166c5352b6d3776c79ef", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000000000000000000000000000000000000000000001" + ], + "data": "0x", + "logIndex": 6, + "blockHash": "0x890ed17c6062fbbf0555dc1eb7e115f8554adbf0d123d288ab5d21ddf54f456e" + }, + { + "transactionIndex": 1, + "blockNumber": 33727995, + "transactionHash": "0x16949b420db4e6e6db37a7f953eb0fd22e36f76b74fa5e26afdfa10bad9027a5", + "address": "0xa0571e758a00C586DbD53fb431d0f48eff9d0F15", + "topics": [ + "0xafec95c8612496c3ecf5dddc71e393528fe29bd145fbaf9c6b496d78d7e2d79b", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x0000000000000000000000008b293600c50d6fbdc6ed4251cc75ece29880276f" + ], + "data": "0x", + "logIndex": 7, + "blockHash": "0x890ed17c6062fbbf0555dc1eb7e115f8554adbf0d123d288ab5d21ddf54f456e" + }, + { + "transactionIndex": 1, + "blockNumber": 33727995, + "transactionHash": "0x16949b420db4e6e6db37a7f953eb0fd22e36f76b74fa5e26afdfa10bad9027a5", + "address": "0xa0571e758a00C586DbD53fb431d0f48eff9d0F15", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x000000000000000000000000cd2a514f04241b7c9a0d5d54441e92e4611929cf", + "0x000000000000000000000000ce10739590001705f7ff231611ba4a48b2820327" + ], + "data": "0x", + "logIndex": 8, + "blockHash": "0x890ed17c6062fbbf0555dc1eb7e115f8554adbf0d123d288ab5d21ddf54f456e" + }, + { + "transactionIndex": 1, + "blockNumber": 33727995, + "transactionHash": "0x16949b420db4e6e6db37a7f953eb0fd22e36f76b74fa5e26afdfa10bad9027a5", + "address": "0xa0571e758a00C586DbD53fb431d0f48eff9d0F15", + "topics": ["0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498"], + "data": "0x0000000000000000000000000000000000000000000000000000000000000001", + "logIndex": 9, + "blockHash": "0x890ed17c6062fbbf0555dc1eb7e115f8554adbf0d123d288ab5d21ddf54f456e" + } + ], + "blockNumber": 33727995, + "cumulativeGasUsed": "696894", + "status": 1, + "byzantium": true + }, + "args": [ + "0xBF85A90673E61956f8c79b9150BAB7893b791bDd", + "0x8a42c31900000000000000000000000063061de4a25f24279aaab80400040684f92ee31900000000000000000000000010b57706ad2345e590c2ea4dc02faef0d9f5b08b0000000000000000000000006ba592934fd60d7a180d65cdb1c9bf561fead3d40000000000000000000000000000000000000000204fce5e3e25026110000000000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000001c00000000000000000000000000000000000000000000000000000000000000008000000000000000000000000ce10739590001705f7ff231611ba4a48b282032700000000000000000000000045f8a08f534f34a97187626e05d4b6648eeaa9aa00000000000000000000000000000000000000000000000000000000000000010000000000000000000000008b293600c50d6fbdc6ed4251cc75ece29880276f000000000000000000000000000000000000000000000000016345785d8a0000000000000000000000000000000000000000000000000000000000000000001956656e75732061674555522028537461626c65636f696e73290000000000000000000000000000000000000000000000000000000000000000000000000000127661674555525f537461626c65636f696e730000000000000000000000000000" + ], + "numDeployments": 1, + "solcInputHash": "6d4db51b84097a74598623a15df3d6fb", + "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/6d4db51b84097a74598623a15df3d6fb.json b/deployments/bsctestnet/solcInputs/6d4db51b84097a74598623a15df3d6fb.json new file mode 100644 index 000000000..b8f55c44b --- /dev/null +++ b/deployments/bsctestnet/solcInputs/6d4db51b84097a74598623a15df3d6fb.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 { 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 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 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/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 { 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/helpers/deploymentConfig.ts b/helpers/deploymentConfig.ts index 63c80a843..53f7c052e 100644 --- a/helpers/deploymentConfig.ts +++ b/helpers/deploymentConfig.ts @@ -660,6 +660,13 @@ export const globalConfig: NetworkConfig = { decimals: 18, tokenAddress: ethers.constants.AddressZero, }, + { + isMock: false, + name: "agEUR", + symbol: "agEUR", + decimals: 18, + tokenAddress: "0x63061de4A25f24279AAab80400040684F92Ee319", + }, ], poolConfig: [ { @@ -720,6 +727,23 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(400_000, 18), vTokenReceiver: "0x3DdfA8eC3052539b6C9549F12cEA2C295cfF5296", }, + { + name: "Venus agEUR (Stablecoins)", + asset: "agEUR", + symbol: "vagEUR_Stablecoins", + rateModel: InterestRateModels.JumpRate.toString(), + baseRatePerYear: convertToUnit("0.02", 18), + multiplierPerYear: convertToUnit("0.1", 18), + jumpMultiplierPerYear: convertToUnit("2.5", 18), + kink_: convertToUnit("0.5", 18), + collateralFactor: convertToUnit("0.75", 18), + liquidationThreshold: convertToUnit("0.8", 18), + reserveFactor: convertToUnit("0.1", 18), + initialSupply: convertToUnit(10000, 18), + supplyCap: convertToUnit(100000, 18), + borrowCap: convertToUnit(50000, 18), + vTokenReceiver: "0x3DdfA8eC3052539b6C9549F12cEA2C295cfF5296", + }, ], rewards: [ { @@ -1363,6 +1387,13 @@ export const globalConfig: NetworkConfig = { decimals: 18, tokenAddress: "0x3BC5AC0dFdC871B365d159f728dd1B9A0B5481E8", }, + { + isMock: false, + name: "agEUR", + symbol: "agEUR", + decimals: 18, + tokenAddress: "0x12f31b73d812c6bb0d735a218c086d44d5fe5f89", + }, ], poolConfig: [ { @@ -1423,6 +1454,23 @@ export const globalConfig: NetworkConfig = { borrowCap: convertToUnit(400_000, 18), vTokenReceiver: "0x3DdfA8eC3052539b6C9549F12cEA2C295cfF5296", }, + { + name: "Venus agEUR (Stablecoins)", + asset: "agEUR", + symbol: "vagEUR_Stablecoins", + rateModel: InterestRateModels.JumpRate.toString(), + baseRatePerYear: convertToUnit("0.02", 18), + multiplierPerYear: convertToUnit("0.1", 18), + jumpMultiplierPerYear: convertToUnit("2.5", 18), + kink_: convertToUnit("0.5", 18), + collateralFactor: convertToUnit("0.75", 18), + liquidationThreshold: convertToUnit("0.8", 18), + reserveFactor: convertToUnit("0.1", 18), + initialSupply: convertToUnit(10000, 18), + supplyCap: convertToUnit(100000, 18), + borrowCap: convertToUnit(50000, 18), + vTokenReceiver: "0x3DdfA8eC3052539b6C9549F12cEA2C295cfF5296", + }, ], rewards: [ { From e9eb707e871cea81a6c2c5be57510ec4fb5c49d8 Mon Sep 17 00:00:00 2001 From: GitGuru7 <128375421+GitGuru7@users.noreply.github.com> Date: Thu, 28 Sep 2023 14:28:08 +0530 Subject: [PATCH 10/33] chore: update inital supply and receiver --- helpers/deploymentConfig.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/helpers/deploymentConfig.ts b/helpers/deploymentConfig.ts index 53f7c052e..a189a3120 100644 --- a/helpers/deploymentConfig.ts +++ b/helpers/deploymentConfig.ts @@ -739,10 +739,10 @@ export const globalConfig: NetworkConfig = { collateralFactor: convertToUnit("0.75", 18), liquidationThreshold: convertToUnit("0.8", 18), reserveFactor: convertToUnit("0.1", 18), - initialSupply: convertToUnit(10000, 18), + initialSupply: convertToUnit(9000, 18), supplyCap: convertToUnit(100000, 18), borrowCap: convertToUnit(50000, 18), - vTokenReceiver: "0x3DdfA8eC3052539b6C9549F12cEA2C295cfF5296", + vTokenReceiver: "0xc444949e0054a23c44fc45789738bdf64aed2391", }, ], rewards: [ @@ -1466,10 +1466,10 @@ export const globalConfig: NetworkConfig = { collateralFactor: convertToUnit("0.75", 18), liquidationThreshold: convertToUnit("0.8", 18), reserveFactor: convertToUnit("0.1", 18), - initialSupply: convertToUnit(10000, 18), + initialSupply: convertToUnit(9000, 18), supplyCap: convertToUnit(100000, 18), borrowCap: convertToUnit(50000, 18), - vTokenReceiver: "0x3DdfA8eC3052539b6C9549F12cEA2C295cfF5296", + vTokenReceiver: "0xc444949e0054a23c44fc45789738bdf64aed2391", }, ], rewards: [ From 072714ded3dc712e9ed99748ff6a2da2adb94a02 Mon Sep 17 00:00:00 2001 From: GitGuru7 <128375421+GitGuru7@users.noreply.github.com> Date: Thu, 28 Sep 2023 17:24:33 +0530 Subject: [PATCH 11/33] feat: add reward distributor in agEUR market --- deployments/bscmainnet.json | 1281 ++++ .../RewardsDistributor_Stablecoins_2.json | 1270 ++++ ...ewardsDistributor_Stablecoins_2_Proxy.json | 277 + deployments/bsctestnet.json | 5748 +++++++++++------ deployments/bsctestnet/MockANGLE.json | 450 ++ .../RewardsDistributor_StableCoins_2.json | 1270 ++++ ...ewardsDistributor_StableCoins_2_Proxy.json | 277 + helpers/deploymentConfig.ts | 26 + 8 files changed, 8520 insertions(+), 2079 deletions(-) create mode 100644 deployments/bscmainnet/RewardsDistributor_Stablecoins_2.json create mode 100644 deployments/bscmainnet/RewardsDistributor_Stablecoins_2_Proxy.json create mode 100644 deployments/bsctestnet/MockANGLE.json create mode 100644 deployments/bsctestnet/RewardsDistributor_StableCoins_2.json create mode 100644 deployments/bsctestnet/RewardsDistributor_StableCoins_2_Proxy.json diff --git a/deployments/bscmainnet.json b/deployments/bscmainnet.json index 76a93e531..b307aba94 100644 --- a/deployments/bscmainnet.json +++ b/deployments/bscmainnet.json @@ -21725,6 +21725,1287 @@ } ] }, + "RewardsDistributor_Stablecoins_2": { + "address": "0x177ED4625F57cEa2804EA3A396c8Ff78f314F1CA", + "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" + } + ] + }, + "RewardsDistributor_Stablecoins_2_Proxy": { + "address": "0x177ED4625F57cEa2804EA3A396c8Ff78f314F1CA", + "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_Tron_0": { "address": "0x804F3893d3c1C3EFFDf778eDDa7C199129235882", "abi": [ diff --git a/deployments/bscmainnet/RewardsDistributor_Stablecoins_2.json b/deployments/bscmainnet/RewardsDistributor_Stablecoins_2.json new file mode 100644 index 000000000..738c1ac12 --- /dev/null +++ b/deployments/bscmainnet/RewardsDistributor_Stablecoins_2.json @@ -0,0 +1,1270 @@ +{ + "address": "0x177ED4625F57cEa2804EA3A396c8Ff78f314F1CA", + "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": "0x4c308d6e97f08b11a47d49104f4642e697b723c3a1cbee7107cc6d8b657c618d", + "receipt": { + "to": null, + "from": "0x12Bdf8Ae9fE2047809080412d7341044b910ef10", + "contractAddress": "0x177ED4625F57cEa2804EA3A396c8Ff78f314F1CA", + "transactionIndex": 96, + "gasUsed": "865817", + "logsBloom": "0x00000000000000000000000000000000400000000000000000808000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000010000000002000001000000000000000000000000000000000000020000000000000000000800000000800000000000000000000000400000000000000000000010000000000000000000000084040000000000800000000000000000000000002000000400000000000000800010000000000000000000000020000000000000000001040000000200000400080000000000000020000000000200000000000000000000000000000800000000000000000000000000", + "blockHash": "0xc5bfe0a327be3b446a7e0bc82ebd51062aef6897d4bc91e56b4103e2f36daa32", + "transactionHash": "0x4c308d6e97f08b11a47d49104f4642e697b723c3a1cbee7107cc6d8b657c618d", + "logs": [ + { + "transactionIndex": 96, + "blockNumber": 32136194, + "transactionHash": "0x4c308d6e97f08b11a47d49104f4642e697b723c3a1cbee7107cc6d8b657c618d", + "address": "0x177ED4625F57cEa2804EA3A396c8Ff78f314F1CA", + "topics": [ + "0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b", + "0x00000000000000000000000001251d4ef6bb9f56c8bef7d3a201f00f4c122589" + ], + "data": "0x", + "logIndex": 222, + "blockHash": "0xc5bfe0a327be3b446a7e0bc82ebd51062aef6897d4bc91e56b4103e2f36daa32" + }, + { + "transactionIndex": 96, + "blockNumber": 32136194, + "transactionHash": "0x4c308d6e97f08b11a47d49104f4642e697b723c3a1cbee7107cc6d8b657c618d", + "address": "0x177ED4625F57cEa2804EA3A396c8Ff78f314F1CA", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x00000000000000000000000012bdf8ae9fe2047809080412d7341044b910ef10" + ], + "data": "0x", + "logIndex": 223, + "blockHash": "0xc5bfe0a327be3b446a7e0bc82ebd51062aef6897d4bc91e56b4103e2f36daa32" + }, + { + "transactionIndex": 96, + "blockNumber": 32136194, + "transactionHash": "0x4c308d6e97f08b11a47d49104f4642e697b723c3a1cbee7107cc6d8b657c618d", + "address": "0x177ED4625F57cEa2804EA3A396c8Ff78f314F1CA", + "topics": ["0x66fd58e82f7b31a2a5c30e0888f3093efe4e111b00cd2b0c31fe014601293aa0"], + "data": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000004788629abc6cfca10f9f969efdeaa1cf70c23555", + "logIndex": 224, + "blockHash": "0xc5bfe0a327be3b446a7e0bc82ebd51062aef6897d4bc91e56b4103e2f36daa32" + }, + { + "transactionIndex": 96, + "blockNumber": 32136194, + "transactionHash": "0x4c308d6e97f08b11a47d49104f4642e697b723c3a1cbee7107cc6d8b657c618d", + "address": "0x177ED4625F57cEa2804EA3A396c8Ff78f314F1CA", + "topics": ["0xc2d09fef144f7c8a86f71ea459f8fc17f675768eb1ae369cbd77fb31d467aafa"], + "data": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000064", + "logIndex": 225, + "blockHash": "0xc5bfe0a327be3b446a7e0bc82ebd51062aef6897d4bc91e56b4103e2f36daa32" + }, + { + "transactionIndex": 96, + "blockNumber": 32136194, + "transactionHash": "0x4c308d6e97f08b11a47d49104f4642e697b723c3a1cbee7107cc6d8b657c618d", + "address": "0x177ED4625F57cEa2804EA3A396c8Ff78f314F1CA", + "topics": ["0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498"], + "data": "0x0000000000000000000000000000000000000000000000000000000000000001", + "logIndex": 226, + "blockHash": "0xc5bfe0a327be3b446a7e0bc82ebd51062aef6897d4bc91e56b4103e2f36daa32" + }, + { + "transactionIndex": 96, + "blockNumber": 32136194, + "transactionHash": "0x4c308d6e97f08b11a47d49104f4642e697b723c3a1cbee7107cc6d8b657c618d", + "address": "0x177ED4625F57cEa2804EA3A396c8Ff78f314F1CA", + "topics": ["0x7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f"], + "data": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000006beb6d2695b67feb73ad4f172e8e2975497187e4", + "logIndex": 227, + "blockHash": "0xc5bfe0a327be3b446a7e0bc82ebd51062aef6897d4bc91e56b4103e2f36daa32" + } + ], + "blockNumber": 32136194, + "cumulativeGasUsed": "10164928", + "status": 1, + "byzantium": true + }, + "args": [ + "0x01251D4eF6bb9f56C8Bef7D3A201f00f4C122589", + "0x6beb6D2695B67FEb73ad4f172E8E2975497187e4", + "0xbe20309400000000000000000000000094c1495cd4c557f1560cbd68eab0d197e629157100000000000000000000000097b6897aad7aba3861c04c0e6388fc02af1f227f00000000000000000000000000000000000000000000000000000000000000640000000000000000000000004788629abc6cfca10f9f969efdeaa1cf70c23555" + ], + "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": [ + "0x94c1495cD4c557f1560Cbd68EAB0d197e6291571", + "0x97B6897AAd7aBa3861c04C0e6388Fc02AF1F227f", + 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/RewardsDistributor_Stablecoins_2_Proxy.json b/deployments/bscmainnet/RewardsDistributor_Stablecoins_2_Proxy.json new file mode 100644 index 000000000..07d6ec9db --- /dev/null +++ b/deployments/bscmainnet/RewardsDistributor_Stablecoins_2_Proxy.json @@ -0,0 +1,277 @@ +{ + "address": "0x177ED4625F57cEa2804EA3A396c8Ff78f314F1CA", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_logic", + "type": "address" + }, + { + "internalType": "address", + "name": "admin_", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "stateMutability": "payable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "previousAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beacon", + "type": "address" + } + ], + "name": "BeaconUpgraded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "admin_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "changeAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "implementation_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "upgradeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "upgradeToAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "transactionHash": "0x4c308d6e97f08b11a47d49104f4642e697b723c3a1cbee7107cc6d8b657c618d", + "receipt": { + "to": null, + "from": "0x12Bdf8Ae9fE2047809080412d7341044b910ef10", + "contractAddress": "0x177ED4625F57cEa2804EA3A396c8Ff78f314F1CA", + "transactionIndex": 96, + "gasUsed": "865817", + "logsBloom": "0x00000000000000000000000000000000400000000000000000808000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000010000000002000001000000000000000000000000000000000000020000000000000000000800000000800000000000000000000000400000000000000000000010000000000000000000000084040000000000800000000000000000000000002000000400000000000000800010000000000000000000000020000000000000000001040000000200000400080000000000000020000000000200000000000000000000000000000800000000000000000000000000", + "blockHash": "0xc5bfe0a327be3b446a7e0bc82ebd51062aef6897d4bc91e56b4103e2f36daa32", + "transactionHash": "0x4c308d6e97f08b11a47d49104f4642e697b723c3a1cbee7107cc6d8b657c618d", + "logs": [ + { + "transactionIndex": 96, + "blockNumber": 32136194, + "transactionHash": "0x4c308d6e97f08b11a47d49104f4642e697b723c3a1cbee7107cc6d8b657c618d", + "address": "0x177ED4625F57cEa2804EA3A396c8Ff78f314F1CA", + "topics": [ + "0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b", + "0x00000000000000000000000001251d4ef6bb9f56c8bef7d3a201f00f4c122589" + ], + "data": "0x", + "logIndex": 222, + "blockHash": "0xc5bfe0a327be3b446a7e0bc82ebd51062aef6897d4bc91e56b4103e2f36daa32" + }, + { + "transactionIndex": 96, + "blockNumber": 32136194, + "transactionHash": "0x4c308d6e97f08b11a47d49104f4642e697b723c3a1cbee7107cc6d8b657c618d", + "address": "0x177ED4625F57cEa2804EA3A396c8Ff78f314F1CA", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x00000000000000000000000012bdf8ae9fe2047809080412d7341044b910ef10" + ], + "data": "0x", + "logIndex": 223, + "blockHash": "0xc5bfe0a327be3b446a7e0bc82ebd51062aef6897d4bc91e56b4103e2f36daa32" + }, + { + "transactionIndex": 96, + "blockNumber": 32136194, + "transactionHash": "0x4c308d6e97f08b11a47d49104f4642e697b723c3a1cbee7107cc6d8b657c618d", + "address": "0x177ED4625F57cEa2804EA3A396c8Ff78f314F1CA", + "topics": ["0x66fd58e82f7b31a2a5c30e0888f3093efe4e111b00cd2b0c31fe014601293aa0"], + "data": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000004788629abc6cfca10f9f969efdeaa1cf70c23555", + "logIndex": 224, + "blockHash": "0xc5bfe0a327be3b446a7e0bc82ebd51062aef6897d4bc91e56b4103e2f36daa32" + }, + { + "transactionIndex": 96, + "blockNumber": 32136194, + "transactionHash": "0x4c308d6e97f08b11a47d49104f4642e697b723c3a1cbee7107cc6d8b657c618d", + "address": "0x177ED4625F57cEa2804EA3A396c8Ff78f314F1CA", + "topics": ["0xc2d09fef144f7c8a86f71ea459f8fc17f675768eb1ae369cbd77fb31d467aafa"], + "data": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000064", + "logIndex": 225, + "blockHash": "0xc5bfe0a327be3b446a7e0bc82ebd51062aef6897d4bc91e56b4103e2f36daa32" + }, + { + "transactionIndex": 96, + "blockNumber": 32136194, + "transactionHash": "0x4c308d6e97f08b11a47d49104f4642e697b723c3a1cbee7107cc6d8b657c618d", + "address": "0x177ED4625F57cEa2804EA3A396c8Ff78f314F1CA", + "topics": ["0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498"], + "data": "0x0000000000000000000000000000000000000000000000000000000000000001", + "logIndex": 226, + "blockHash": "0xc5bfe0a327be3b446a7e0bc82ebd51062aef6897d4bc91e56b4103e2f36daa32" + }, + { + "transactionIndex": 96, + "blockNumber": 32136194, + "transactionHash": "0x4c308d6e97f08b11a47d49104f4642e697b723c3a1cbee7107cc6d8b657c618d", + "address": "0x177ED4625F57cEa2804EA3A396c8Ff78f314F1CA", + "topics": ["0x7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f"], + "data": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000006beb6d2695b67feb73ad4f172e8e2975497187e4", + "logIndex": 227, + "blockHash": "0xc5bfe0a327be3b446a7e0bc82ebd51062aef6897d4bc91e56b4103e2f36daa32" + } + ], + "blockNumber": 32136194, + "cumulativeGasUsed": "10164928", + "status": 1, + "byzantium": true + }, + "args": [ + "0x01251D4eF6bb9f56C8Bef7D3A201f00f4C122589", + "0x6beb6D2695B67FEb73ad4f172E8E2975497187e4", + "0xbe20309400000000000000000000000094c1495cd4c557f1560cbd68eab0d197e629157100000000000000000000000097b6897aad7aba3861c04c0e6388fc02af1f227f00000000000000000000000000000000000000000000000000000000000000640000000000000000000000004788629abc6cfca10f9f969efdeaa1cf70c23555" + ], + "numDeployments": 1, + "solcInputHash": "0e89febeebc7444140de8e67c9067d2c", + "metadata": "{\"compiler\":{\"version\":\"0.8.10+commit.fc410830\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_logic\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"admin_\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"previousAdmin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\"}],\"name\":\"AdminChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"beacon\",\"type\":\"address\"}],\"name\":\"BeaconUpgraded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"implementation\",\"type\":\"address\"}],\"name\":\"Upgraded\",\"type\":\"event\"},{\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"inputs\":[],\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"admin_\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\"}],\"name\":\"changeAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"implementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"implementation_\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newImplementation\",\"type\":\"address\"}],\"name\":\"upgradeTo\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newImplementation\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"upgradeToAndCall\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"details\":\"This contract implements a proxy that is upgradeable by an admin. To avoid https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector clashing], which can potentially be used in an attack, this contract uses the https://blog.openzeppelin.com/the-transparent-proxy-pattern/[transparent proxy pattern]. This pattern implies two things that go hand in hand: 1. If any account other than the admin calls the proxy, the call will be forwarded to the implementation, even if that call matches one of the admin functions exposed by the proxy itself. 2. If the admin calls the proxy, it can access the admin functions, but its calls will never be forwarded to the implementation. If the admin tries to call a function on the implementation it will fail with an error that says \\\"admin cannot fallback to proxy target\\\". These properties mean that the admin account can only be used for admin actions like upgrading the proxy or changing the admin, so it's best if it's a dedicated account that is not used for anything else. This will avoid headaches due to sudden errors when trying to call a function from the proxy implementation. Our recommendation is for the dedicated account to be an instance of the {ProxyAdmin} contract. If set up this way, you should think of the `ProxyAdmin` instance as the real administrative interface of your proxy.\",\"kind\":\"dev\",\"methods\":{\"admin()\":{\"details\":\"Returns the current admin. NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyAdmin}. TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call. `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`\"},\"changeAdmin(address)\":{\"details\":\"Changes the admin of the proxy. Emits an {AdminChanged} event. NOTE: Only the admin can call this function. See {ProxyAdmin-changeProxyAdmin}.\"},\"constructor\":{\"details\":\"Initializes an upgradeable proxy managed by `_admin`, backed by the implementation at `_logic`, and optionally initialized with `_data` as explained in {ERC1967Proxy-constructor}.\"},\"implementation()\":{\"details\":\"Returns the current implementation. NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyImplementation}. TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call. `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc`\"},\"upgradeTo(address)\":{\"details\":\"Upgrade the implementation of the proxy. NOTE: Only the admin can call this function. See {ProxyAdmin-upgrade}.\"},\"upgradeToAndCall(address,bytes)\":{\"details\":\"Upgrade the implementation of the proxy, and then call a function from the new implementation as specified by `data`, which should be an encoded function call. This is useful to initialize new storage variables in the proxied contract. NOTE: Only the admin can call this function. See {ProxyAdmin-upgradeAndCall}.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solc_0.8/openzeppelin/proxy/transparent/TransparentUpgradeableProxy.sol\":\"TransparentUpgradeableProxy\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":999999},\"remappings\":[]},\"sources\":{\"solc_0.8/openzeppelin/interfaces/draft-IERC1822.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (interfaces/draft-IERC1822.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified\\n * proxy whose upgrades are fully controlled by the current implementation.\\n */\\ninterface IERC1822Proxiable {\\n /**\\n * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation\\n * address.\\n *\\n * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks\\n * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this\\n * function revert if invoked through a proxy.\\n */\\n function proxiableUUID() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0x93b4e21c931252739a1ec13ea31d3d35a5c068be3163ccab83e4d70c40355f03\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/proxy/ERC1967/ERC1967Proxy.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (proxy/ERC1967/ERC1967Proxy.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../Proxy.sol\\\";\\nimport \\\"./ERC1967Upgrade.sol\\\";\\n\\n/**\\n * @dev This contract implements an upgradeable proxy. It is upgradeable because calls are delegated to an\\n * implementation address that can be changed. This address is stored in storage in the location specified by\\n * https://eips.ethereum.org/EIPS/eip-1967[EIP1967], so that it doesn't conflict with the storage layout of the\\n * implementation behind the proxy.\\n */\\ncontract ERC1967Proxy is Proxy, ERC1967Upgrade {\\n /**\\n * @dev Initializes the upgradeable proxy with an initial implementation specified by `_logic`.\\n *\\n * If `_data` is nonempty, it's used as data in a delegate call to `_logic`. This will typically be an encoded\\n * function call, and allows initializating the storage of the proxy like a Solidity constructor.\\n */\\n constructor(address _logic, bytes memory _data) payable {\\n assert(_IMPLEMENTATION_SLOT == bytes32(uint256(keccak256(\\\"eip1967.proxy.implementation\\\")) - 1));\\n _upgradeToAndCall(_logic, _data, false);\\n }\\n\\n /**\\n * @dev Returns the current implementation address.\\n */\\n function _implementation() internal view virtual override returns (address impl) {\\n return ERC1967Upgrade._getImplementation();\\n }\\n}\\n\",\"keccak256\":\"0x6309f9f39dc6f4f45a24f296543867aa358e32946cd6b2874627a996d606b3a0\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/proxy/ERC1967/ERC1967Upgrade.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (proxy/ERC1967/ERC1967Upgrade.sol)\\n\\npragma solidity ^0.8.2;\\n\\nimport \\\"../beacon/IBeacon.sol\\\";\\nimport \\\"../../interfaces/draft-IERC1822.sol\\\";\\nimport \\\"../../utils/Address.sol\\\";\\nimport \\\"../../utils/StorageSlot.sol\\\";\\n\\n/**\\n * @dev This abstract contract provides getters and event emitting update functions for\\n * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots.\\n *\\n * _Available since v4.1._\\n *\\n * @custom:oz-upgrades-unsafe-allow delegatecall\\n */\\nabstract contract ERC1967Upgrade {\\n // This is the keccak-256 hash of \\\"eip1967.proxy.rollback\\\" subtracted by 1\\n bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143;\\n\\n /**\\n * @dev Storage slot with the address of the current implementation.\\n * This is the keccak-256 hash of \\\"eip1967.proxy.implementation\\\" subtracted by 1, and is\\n * validated in the constructor.\\n */\\n bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\\n\\n /**\\n * @dev Emitted when the implementation is upgraded.\\n */\\n event Upgraded(address indexed implementation);\\n\\n /**\\n * @dev Returns the current implementation address.\\n */\\n function _getImplementation() internal view returns (address) {\\n return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\\n }\\n\\n /**\\n * @dev Stores a new address in the EIP1967 implementation slot.\\n */\\n function _setImplementation(address newImplementation) private {\\n require(Address.isContract(newImplementation), \\\"ERC1967: new implementation is not a contract\\\");\\n StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\\n }\\n\\n /**\\n * @dev Perform implementation upgrade\\n *\\n * Emits an {Upgraded} event.\\n */\\n function _upgradeTo(address newImplementation) internal {\\n _setImplementation(newImplementation);\\n emit Upgraded(newImplementation);\\n }\\n\\n /**\\n * @dev Perform implementation upgrade with additional setup call.\\n *\\n * Emits an {Upgraded} event.\\n */\\n function _upgradeToAndCall(\\n address newImplementation,\\n bytes memory data,\\n bool forceCall\\n ) internal {\\n _upgradeTo(newImplementation);\\n if (data.length > 0 || forceCall) {\\n Address.functionDelegateCall(newImplementation, data);\\n }\\n }\\n\\n /**\\n * @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call.\\n *\\n * Emits an {Upgraded} event.\\n */\\n function _upgradeToAndCallUUPS(\\n address newImplementation,\\n bytes memory data,\\n bool forceCall\\n ) internal {\\n // Upgrades from old implementations will perform a rollback test. This test requires the new\\n // implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing\\n // this special case will break upgrade paths from old UUPS implementation to new ones.\\n if (StorageSlot.getBooleanSlot(_ROLLBACK_SLOT).value) {\\n _setImplementation(newImplementation);\\n } else {\\n try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) {\\n require(slot == _IMPLEMENTATION_SLOT, \\\"ERC1967Upgrade: unsupported proxiableUUID\\\");\\n } catch {\\n revert(\\\"ERC1967Upgrade: new implementation is not UUPS\\\");\\n }\\n _upgradeToAndCall(newImplementation, data, forceCall);\\n }\\n }\\n\\n /**\\n * @dev Storage slot with the admin of the contract.\\n * This is the keccak-256 hash of \\\"eip1967.proxy.admin\\\" subtracted by 1, and is\\n * validated in the constructor.\\n */\\n bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;\\n\\n /**\\n * @dev Emitted when the admin account has changed.\\n */\\n event AdminChanged(address previousAdmin, address newAdmin);\\n\\n /**\\n * @dev Returns the current admin.\\n */\\n function _getAdmin() internal view virtual returns (address) {\\n return StorageSlot.getAddressSlot(_ADMIN_SLOT).value;\\n }\\n\\n /**\\n * @dev Stores a new address in the EIP1967 admin slot.\\n */\\n function _setAdmin(address newAdmin) private {\\n require(newAdmin != address(0), \\\"ERC1967: new admin is the zero address\\\");\\n StorageSlot.getAddressSlot(_ADMIN_SLOT).value = newAdmin;\\n }\\n\\n /**\\n * @dev Changes the admin of the proxy.\\n *\\n * Emits an {AdminChanged} event.\\n */\\n function _changeAdmin(address newAdmin) internal {\\n emit AdminChanged(_getAdmin(), newAdmin);\\n _setAdmin(newAdmin);\\n }\\n\\n /**\\n * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.\\n * This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor.\\n */\\n bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;\\n\\n /**\\n * @dev Emitted when the beacon is upgraded.\\n */\\n event BeaconUpgraded(address indexed beacon);\\n\\n /**\\n * @dev Returns the current beacon.\\n */\\n function _getBeacon() internal view returns (address) {\\n return StorageSlot.getAddressSlot(_BEACON_SLOT).value;\\n }\\n\\n /**\\n * @dev Stores a new beacon in the EIP1967 beacon slot.\\n */\\n function _setBeacon(address newBeacon) private {\\n require(Address.isContract(newBeacon), \\\"ERC1967: new beacon is not a contract\\\");\\n require(Address.isContract(IBeacon(newBeacon).implementation()), \\\"ERC1967: beacon implementation is not a contract\\\");\\n StorageSlot.getAddressSlot(_BEACON_SLOT).value = newBeacon;\\n }\\n\\n /**\\n * @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does\\n * not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that).\\n *\\n * Emits a {BeaconUpgraded} event.\\n */\\n function _upgradeBeaconToAndCall(\\n address newBeacon,\\n bytes memory data,\\n bool forceCall\\n ) internal {\\n _setBeacon(newBeacon);\\n emit BeaconUpgraded(newBeacon);\\n if (data.length > 0 || forceCall) {\\n Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x17668652127feebed0ce8d9431ef95ccc8c4292f03e3b8cf06c6ca16af396633\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/proxy/Proxy.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (proxy/Proxy.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM\\n * instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to\\n * be specified by overriding the virtual {_implementation} function.\\n *\\n * Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a\\n * different contract through the {_delegate} function.\\n *\\n * The success and return data of the delegated call will be returned back to the caller of the proxy.\\n */\\nabstract contract Proxy {\\n /**\\n * @dev Delegates the current call to `implementation`.\\n *\\n * This function does not return to its internal call site, it will return directly to the external caller.\\n */\\n function _delegate(address implementation) internal virtual {\\n assembly {\\n // Copy msg.data. We take full control of memory in this inline assembly\\n // block because it will not return to Solidity code. We overwrite the\\n // Solidity scratch pad at memory position 0.\\n calldatacopy(0, 0, calldatasize())\\n\\n // Call the implementation.\\n // out and outsize are 0 because we don't know the size yet.\\n let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)\\n\\n // Copy the returned data.\\n returndatacopy(0, 0, returndatasize())\\n\\n switch result\\n // delegatecall returns 0 on error.\\n case 0 {\\n revert(0, returndatasize())\\n }\\n default {\\n return(0, returndatasize())\\n }\\n }\\n }\\n\\n /**\\n * @dev This is a virtual function that should be overriden so it returns the address to which the fallback function\\n * and {_fallback} should delegate.\\n */\\n function _implementation() internal view virtual returns (address);\\n\\n /**\\n * @dev Delegates the current call to the address returned by `_implementation()`.\\n *\\n * This function does not return to its internall call site, it will return directly to the external caller.\\n */\\n function _fallback() internal virtual {\\n _beforeFallback();\\n _delegate(_implementation());\\n }\\n\\n /**\\n * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other\\n * function in the contract matches the call data.\\n */\\n fallback() external payable virtual {\\n _fallback();\\n }\\n\\n /**\\n * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if call data\\n * is empty.\\n */\\n receive() external payable virtual {\\n _fallback();\\n }\\n\\n /**\\n * @dev Hook that is called before falling back to the implementation. Can happen as part of a manual `_fallback`\\n * call, or as part of the Solidity `fallback` or `receive` functions.\\n *\\n * If overriden should call `super._beforeFallback()`.\\n */\\n function _beforeFallback() internal virtual {}\\n}\\n\",\"keccak256\":\"0xd5d1fd16e9faff7fcb3a52e02a8d49156f42a38a03f07b5f1810c21c2149a8ab\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/proxy/beacon/IBeacon.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev This is the interface that {BeaconProxy} expects of its beacon.\\n */\\ninterface IBeacon {\\n /**\\n * @dev Must return an address that can be used as a delegate call target.\\n *\\n * {BeaconProxy} will check that this address is a contract.\\n */\\n function implementation() external view returns (address);\\n}\\n\",\"keccak256\":\"0xd50a3421ac379ccb1be435fa646d66a65c986b4924f0849839f08692f39dde61\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/proxy/transparent/TransparentUpgradeableProxy.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (proxy/transparent/TransparentUpgradeableProxy.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../ERC1967/ERC1967Proxy.sol\\\";\\n\\n/**\\n * @dev This contract implements a proxy that is upgradeable by an admin.\\n *\\n * To avoid https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector\\n * clashing], which can potentially be used in an attack, this contract uses the\\n * https://blog.openzeppelin.com/the-transparent-proxy-pattern/[transparent proxy pattern]. This pattern implies two\\n * things that go hand in hand:\\n *\\n * 1. If any account other than the admin calls the proxy, the call will be forwarded to the implementation, even if\\n * that call matches one of the admin functions exposed by the proxy itself.\\n * 2. If the admin calls the proxy, it can access the admin functions, but its calls will never be forwarded to the\\n * implementation. If the admin tries to call a function on the implementation it will fail with an error that says\\n * \\\"admin cannot fallback to proxy target\\\".\\n *\\n * These properties mean that the admin account can only be used for admin actions like upgrading the proxy or changing\\n * the admin, so it's best if it's a dedicated account that is not used for anything else. This will avoid headaches due\\n * to sudden errors when trying to call a function from the proxy implementation.\\n *\\n * Our recommendation is for the dedicated account to be an instance of the {ProxyAdmin} contract. If set up this way,\\n * you should think of the `ProxyAdmin` instance as the real administrative interface of your proxy.\\n */\\ncontract TransparentUpgradeableProxy is ERC1967Proxy {\\n /**\\n * @dev Initializes an upgradeable proxy managed by `_admin`, backed by the implementation at `_logic`, and\\n * optionally initialized with `_data` as explained in {ERC1967Proxy-constructor}.\\n */\\n constructor(\\n address _logic,\\n address admin_,\\n bytes memory _data\\n ) payable ERC1967Proxy(_logic, _data) {\\n assert(_ADMIN_SLOT == bytes32(uint256(keccak256(\\\"eip1967.proxy.admin\\\")) - 1));\\n _changeAdmin(admin_);\\n }\\n\\n /**\\n * @dev Modifier used internally that will delegate the call to the implementation unless the sender is the admin.\\n */\\n modifier ifAdmin() {\\n if (msg.sender == _getAdmin()) {\\n _;\\n } else {\\n _fallback();\\n }\\n }\\n\\n /**\\n * @dev Returns the current admin.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyAdmin}.\\n *\\n * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the\\n * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.\\n * `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`\\n */\\n function admin() external ifAdmin returns (address admin_) {\\n admin_ = _getAdmin();\\n }\\n\\n /**\\n * @dev Returns the current implementation.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyImplementation}.\\n *\\n * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the\\n * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.\\n * `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc`\\n */\\n function implementation() external ifAdmin returns (address implementation_) {\\n implementation_ = _implementation();\\n }\\n\\n /**\\n * @dev Changes the admin of the proxy.\\n *\\n * Emits an {AdminChanged} event.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-changeProxyAdmin}.\\n */\\n function changeAdmin(address newAdmin) external virtual ifAdmin {\\n _changeAdmin(newAdmin);\\n }\\n\\n /**\\n * @dev Upgrade the implementation of the proxy.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-upgrade}.\\n */\\n function upgradeTo(address newImplementation) external ifAdmin {\\n _upgradeToAndCall(newImplementation, bytes(\\\"\\\"), false);\\n }\\n\\n /**\\n * @dev Upgrade the implementation of the proxy, and then call a function from the new implementation as specified\\n * by `data`, which should be an encoded function call. This is useful to initialize new storage variables in the\\n * proxied contract.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-upgradeAndCall}.\\n */\\n function upgradeToAndCall(address newImplementation, bytes calldata data) external payable ifAdmin {\\n _upgradeToAndCall(newImplementation, data, true);\\n }\\n\\n /**\\n * @dev Returns the current admin.\\n */\\n function _admin() internal view virtual returns (address) {\\n return _getAdmin();\\n }\\n\\n /**\\n * @dev Makes sure the admin cannot access the fallback function. See {Proxy-_beforeFallback}.\\n */\\n function _beforeFallback() internal virtual override {\\n require(msg.sender != _getAdmin(), \\\"TransparentUpgradeableProxy: admin cannot fallback to proxy target\\\");\\n super._beforeFallback();\\n }\\n}\\n\",\"keccak256\":\"0x140055a64cf579d622e04f5a198595832bf2cb193cd0005f4f2d4d61ca906253\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x3777e696b62134e6177440dbe6e6601c0c156a443f57167194b67e75527439de\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/utils/StorageSlot.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/StorageSlot.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Library for reading and writing primitive types to specific storage slots.\\n *\\n * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.\\n * This library helps with reading and writing to such slots without the need for inline assembly.\\n *\\n * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.\\n *\\n * Example usage to set ERC1967 implementation slot:\\n * ```\\n * contract ERC1967 {\\n * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\\n *\\n * function _getImplementation() internal view returns (address) {\\n * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\\n * }\\n *\\n * function _setImplementation(address newImplementation) internal {\\n * require(Address.isContract(newImplementation), \\\"ERC1967: new implementation is not a contract\\\");\\n * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\\n * }\\n * }\\n * ```\\n *\\n * _Available since v4.1 for `address`, `bool`, `bytes32`, and `uint256`._\\n */\\nlibrary StorageSlot {\\n struct AddressSlot {\\n address value;\\n }\\n\\n struct BooleanSlot {\\n bool value;\\n }\\n\\n struct Bytes32Slot {\\n bytes32 value;\\n }\\n\\n struct Uint256Slot {\\n uint256 value;\\n }\\n\\n /**\\n * @dev Returns an `AddressSlot` with member `value` located at `slot`.\\n */\\n function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {\\n assembly {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `BooleanSlot` with member `value` located at `slot`.\\n */\\n function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {\\n assembly {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `Bytes32Slot` with member `value` located at `slot`.\\n */\\n function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {\\n assembly {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `Uint256Slot` with member `value` located at `slot`.\\n */\\n function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {\\n assembly {\\n r.slot := slot\\n }\\n }\\n}\\n\",\"keccak256\":\"0xfe1b7a9aa2a530a9e705b220e26cd584e2fbdc9602a3a1066032b12816b46aca\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x6080604052604051620011b2380380620011b2833981016040819052620000269162000519565b82816200005560017f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbd620005f9565b6000805160206200116b833981519152146200007557620000756200061f565b6200008382826000620000e7565b50620000b3905060017fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6104620005f9565b6000805160206200114b83398151915214620000d357620000d36200061f565b620000de8262000124565b50505062000688565b620000f2836200017f565b600082511180620001005750805b156200011f576200011d8383620001c160201b620002ff1760201c565b505b505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6200014f620001f0565b604080516001600160a01b03928316815291841660208301520160405180910390a16200017c8162000229565b50565b6200018a81620002de565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b6060620001e983836040518060600160405280602781526020016200118b6027913962000381565b9392505050565b60006200021a6000805160206200114b83398151915260001b6200046760201b620002731760201c565b546001600160a01b0316919050565b6001600160a01b038116620002945760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b60648201526084015b60405180910390fd5b80620002bd6000805160206200114b83398151915260001b6200046760201b620002731760201c565b80546001600160a01b0319166001600160a01b039290921691909117905550565b620002f4816200046a60201b6200032b1760201c565b620003585760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b60648201526084016200028b565b80620002bd6000805160206200116b83398151915260001b6200046760201b620002731760201c565b60606001600160a01b0384163b620003eb5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f6044820152651b9d1c9858dd60d21b60648201526084016200028b565b600080856001600160a01b03168560405162000408919062000635565b600060405180830381855af49150503d806000811462000445576040519150601f19603f3d011682016040523d82523d6000602084013e6200044a565b606091505b5090925090506200045d82828662000479565b9695505050505050565b90565b6001600160a01b03163b151590565b606083156200048a575081620001e9565b8251156200049b5782518084602001fd5b8160405162461bcd60e51b81526004016200028b919062000653565b80516001600160a01b0381168114620004cf57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60005b8381101562000507578181015183820152602001620004ed565b838111156200011d5750506000910152565b6000806000606084860312156200052f57600080fd5b6200053a84620004b7565b92506200054a60208501620004b7565b60408501519092506001600160401b03808211156200056857600080fd5b818601915086601f8301126200057d57600080fd5b815181811115620005925762000592620004d4565b604051601f8201601f19908116603f01168101908382118183101715620005bd57620005bd620004d4565b81604052828152896020848701011115620005d757600080fd5b620005ea836020830160208801620004ea565b80955050505050509250925092565b6000828210156200061a57634e487b7160e01b600052601160045260246000fd5b500390565b634e487b7160e01b600052600160045260246000fd5b6000825162000649818460208701620004ea565b9190910192915050565b602081526000825180602084015262000674816040850160208701620004ea565b601f01601f19169190910160400192915050565b610ab380620006986000396000f3fe60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100a85780638f283970146100e6578063f851a440146101065761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61011b565b005b61006b61011b565b34801561008157600080fd5b5061006b61009036600461091f565b610135565b61006b6100a336600461093a565b610196565b3480156100b457600080fd5b506100bd610221565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b3480156100f257600080fd5b5061006b61010136600461091f565b610276565b34801561011257600080fd5b506100bd6102ba565b610123610347565b61013361012e610435565b61043f565b565b61013d610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561018e5761018b816040518060200160405280600081525060006104a3565b50565b61018b61011b565b61019e610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415610219576102148383838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250600192506104a3915050565b505050565b61021461011b565b600061022b610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561026b57610266610435565b905090565b61027361011b565b90565b61027e610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561018e5761018b816104ce565b60006102c4610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561026b57610266610463565b60606103248383604051806060016040528060278152602001610a576027913961052f565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b61034f610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415610133576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f7879207461726760648201527f6574000000000000000000000000000000000000000000000000000000000000608482015260a4015b60405180910390fd5b6000610266610657565b3660008037600080366000845af43d6000803e80801561045e573d6000f35b3d6000fd5b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b5473ffffffffffffffffffffffffffffffffffffffff16919050565b6104ac8361067f565b6000825111806104b95750805b15610214576104c883836102ff565b50505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6104f7610463565b6040805173ffffffffffffffffffffffffffffffffffffffff928316815291841660208301520160405180910390a161018b816106cc565b606073ffffffffffffffffffffffffffffffffffffffff84163b6105d5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f60448201527f6e74726163740000000000000000000000000000000000000000000000000000606482015260840161042c565b6000808573ffffffffffffffffffffffffffffffffffffffff16856040516105fd91906109e9565b600060405180830381855af49150503d8060008114610638576040519150601f19603f3d011682016040523d82523d6000602084013e61063d565b606091505b509150915061064d8282866107d8565b9695505050505050565b60007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc610487565b6106888161082b565b60405173ffffffffffffffffffffffffffffffffffffffff8216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b73ffffffffffffffffffffffffffffffffffffffff811661076f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201527f6464726573730000000000000000000000000000000000000000000000000000606482015260840161042c565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9290921691909117905550565b606083156107e7575081610324565b8251156107f75782518084602001fd5b816040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161042c9190610a05565b73ffffffffffffffffffffffffffffffffffffffff81163b6108cf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201527f6f74206120636f6e747261637400000000000000000000000000000000000000606482015260840161042c565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc610792565b803573ffffffffffffffffffffffffffffffffffffffff8116811461091a57600080fd5b919050565b60006020828403121561093157600080fd5b610324826108f6565b60008060006040848603121561094f57600080fd5b610958846108f6565b9250602084013567ffffffffffffffff8082111561097557600080fd5b818601915086601f83011261098957600080fd5b81358181111561099857600080fd5b8760208285010111156109aa57600080fd5b6020830194508093505050509250925092565b60005b838110156109d85781810151838201526020016109c0565b838111156104c85750506000910152565b600082516109fb8184602087016109bd565b9190910192915050565b6020815260008251806020840152610a248160408501602087016109bd565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220b29caa54336b3ee836679675e9732ec5e526fb3f803cca2fe336cc3555aba62264736f6c634300080a0033b53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564", + "deployedBytecode": "0x60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100a85780638f283970146100e6578063f851a440146101065761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61011b565b005b61006b61011b565b34801561008157600080fd5b5061006b61009036600461091f565b610135565b61006b6100a336600461093a565b610196565b3480156100b457600080fd5b506100bd610221565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b3480156100f257600080fd5b5061006b61010136600461091f565b610276565b34801561011257600080fd5b506100bd6102ba565b610123610347565b61013361012e610435565b61043f565b565b61013d610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561018e5761018b816040518060200160405280600081525060006104a3565b50565b61018b61011b565b61019e610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415610219576102148383838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250600192506104a3915050565b505050565b61021461011b565b600061022b610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561026b57610266610435565b905090565b61027361011b565b90565b61027e610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561018e5761018b816104ce565b60006102c4610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561026b57610266610463565b60606103248383604051806060016040528060278152602001610a576027913961052f565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b61034f610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415610133576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f7879207461726760648201527f6574000000000000000000000000000000000000000000000000000000000000608482015260a4015b60405180910390fd5b6000610266610657565b3660008037600080366000845af43d6000803e80801561045e573d6000f35b3d6000fd5b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b5473ffffffffffffffffffffffffffffffffffffffff16919050565b6104ac8361067f565b6000825111806104b95750805b15610214576104c883836102ff565b50505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6104f7610463565b6040805173ffffffffffffffffffffffffffffffffffffffff928316815291841660208301520160405180910390a161018b816106cc565b606073ffffffffffffffffffffffffffffffffffffffff84163b6105d5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f60448201527f6e74726163740000000000000000000000000000000000000000000000000000606482015260840161042c565b6000808573ffffffffffffffffffffffffffffffffffffffff16856040516105fd91906109e9565b600060405180830381855af49150503d8060008114610638576040519150601f19603f3d011682016040523d82523d6000602084013e61063d565b606091505b509150915061064d8282866107d8565b9695505050505050565b60007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc610487565b6106888161082b565b60405173ffffffffffffffffffffffffffffffffffffffff8216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b73ffffffffffffffffffffffffffffffffffffffff811661076f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201527f6464726573730000000000000000000000000000000000000000000000000000606482015260840161042c565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9290921691909117905550565b606083156107e7575081610324565b8251156107f75782518084602001fd5b816040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161042c9190610a05565b73ffffffffffffffffffffffffffffffffffffffff81163b6108cf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201527f6f74206120636f6e747261637400000000000000000000000000000000000000606482015260840161042c565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc610792565b803573ffffffffffffffffffffffffffffffffffffffff8116811461091a57600080fd5b919050565b60006020828403121561093157600080fd5b610324826108f6565b60008060006040848603121561094f57600080fd5b610958846108f6565b9250602084013567ffffffffffffffff8082111561097557600080fd5b818601915086601f83011261098957600080fd5b81358181111561099857600080fd5b8760208285010111156109aa57600080fd5b6020830194508093505050509250925092565b60005b838110156109d85781810151838201526020016109c0565b838111156104c85750506000910152565b600082516109fb8184602087016109bd565b9190910192915050565b6020815260008251806020840152610a248160408501602087016109bd565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220b29caa54336b3ee836679675e9732ec5e526fb3f803cca2fe336cc3555aba62264736f6c634300080a0033", + "devdoc": { + "details": "This contract implements a proxy that is upgradeable by an admin. To avoid https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector clashing], which can potentially be used in an attack, this contract uses the https://blog.openzeppelin.com/the-transparent-proxy-pattern/[transparent proxy pattern]. This pattern implies two things that go hand in hand: 1. If any account other than the admin calls the proxy, the call will be forwarded to the implementation, even if that call matches one of the admin functions exposed by the proxy itself. 2. If the admin calls the proxy, it can access the admin functions, but its calls will never be forwarded to the implementation. If the admin tries to call a function on the implementation it will fail with an error that says \"admin cannot fallback to proxy target\". These properties mean that the admin account can only be used for admin actions like upgrading the proxy or changing the admin, so it's best if it's a dedicated account that is not used for anything else. This will avoid headaches due to sudden errors when trying to call a function from the proxy implementation. Our recommendation is for the dedicated account to be an instance of the {ProxyAdmin} contract. If set up this way, you should think of the `ProxyAdmin` instance as the real administrative interface of your proxy.", + "kind": "dev", + "methods": { + "admin()": { + "details": "Returns the current admin. NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyAdmin}. TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call. `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`" + }, + "changeAdmin(address)": { + "details": "Changes the admin of the proxy. Emits an {AdminChanged} event. NOTE: Only the admin can call this function. See {ProxyAdmin-changeProxyAdmin}." + }, + "constructor": { + "details": "Initializes an upgradeable proxy managed by `_admin`, backed by the implementation at `_logic`, and optionally initialized with `_data` as explained in {ERC1967Proxy-constructor}." + }, + "implementation()": { + "details": "Returns the current implementation. NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyImplementation}. TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call. `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc`" + }, + "upgradeTo(address)": { + "details": "Upgrade the implementation of the proxy. NOTE: Only the admin can call this function. See {ProxyAdmin-upgrade}." + }, + "upgradeToAndCall(address,bytes)": { + "details": "Upgrade the implementation of the proxy, and then call a function from the new implementation as specified by `data`, which should be an encoded function call. This is useful to initialize new storage variables in the proxied contract. NOTE: Only the admin can call this function. See {ProxyAdmin-upgradeAndCall}." + } + }, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [], + "types": null + } +} diff --git a/deployments/bsctestnet.json b/deployments/bsctestnet.json index 8fe165941..dccaaeace 100644 --- a/deployments/bsctestnet.json +++ b/deployments/bsctestnet.json @@ -4255,8 +4255,8 @@ } ] }, - "MockANKR": { - "address": "0xe4a90EB942CF2DA7238e8F6cC9EF510c49FC8B4B", + "MockANGLE": { + "address": "0xD1Bc731d188ACc3f52a6226B328a89056B0Ec71a", "abi": [ { "inputs": [ @@ -4564,8 +4564,8 @@ } ] }, - "MockBNBx": { - "address": "0x327d6E6FAC0228070884e913263CFF9eFed4a2C8", + "MockANKR": { + "address": "0xe4a90EB942CF2DA7238e8F6cC9EF510c49FC8B4B", "abi": [ { "inputs": [ @@ -4873,8 +4873,8 @@ } ] }, - "MockBNX": { - "address": "0xa8062D2bd49D1D2C6376B444bde19402B38938d0", + "MockBNBx": { + "address": "0x327d6E6FAC0228070884e913263CFF9eFed4a2C8", "abi": [ { "inputs": [ @@ -5182,8 +5182,8 @@ } ] }, - "MockBSW": { - "address": "0x7FCC76fc1F573d8Eb445c236Cc282246bC562bCE", + "MockBNX": { + "address": "0xa8062D2bd49D1D2C6376B444bde19402B38938d0", "abi": [ { "inputs": [ @@ -5491,8 +5491,8 @@ } ] }, - "MockBTT": { - "address": "0xE98344A7c691B200EF47c9b8829110087D832C64", + "MockBSW": { + "address": "0x7FCC76fc1F573d8Eb445c236Cc282246bC562bCE", "abi": [ { "inputs": [ @@ -5800,8 +5800,8 @@ } ] }, - "MockFLOKI": { - "address": "0xb22cF15FBc089d470f8e532aeAd2baB76bE87c88", + "MockBTT": { + "address": "0xE98344A7c691B200EF47c9b8829110087D832C64", "abi": [ { "inputs": [ @@ -6109,8 +6109,8 @@ } ] }, - "MockHAY": { - "address": "0xe73774DfCD551BF75650772dC2cC56a2B6323453", + "MockFLOKI": { + "address": "0xb22cF15FBc089d470f8e532aeAd2baB76bE87c88", "abi": [ { "inputs": [ @@ -6418,8 +6418,8 @@ } ] }, - "MockMBOX": { - "address": "0x523027fFdf9B18Aa652dBcd6B92f885009153dA3", + "MockHAY": { + "address": "0xe73774DfCD551BF75650772dC2cC56a2B6323453", "abi": [ { "inputs": [ @@ -6727,8 +6727,8 @@ } ] }, - "MockNFT": { - "address": "0xc440e4F21AFc2C3bDBA1Af7D0E338ED35d3e25bA", + "MockMBOX": { + "address": "0x523027fFdf9B18Aa652dBcd6B92f885009153dA3", "abi": [ { "inputs": [ @@ -7036,8 +7036,8 @@ } ] }, - "MockRACA": { - "address": "0xD60cC803d888A3e743F21D0bdE4bF2cAfdEA1F26", + "MockNFT": { + "address": "0xc440e4F21AFc2C3bDBA1Af7D0E338ED35d3e25bA", "abi": [ { "inputs": [ @@ -7345,8 +7345,8 @@ } ] }, - "MockSD": { - "address": "0xac7D6B77EBD1DB8C5a9f0896e5eB5d485CB677b3", + "MockRACA": { + "address": "0xD60cC803d888A3e743F21D0bdE4bF2cAfdEA1F26", "abi": [ { "inputs": [ @@ -7654,8 +7654,8 @@ } ] }, - "MockUSDD": { - "address": "0x2E2466e22FcbE0732Be385ee2FBb9C59a1098382", + "MockSD": { + "address": "0xac7D6B77EBD1DB8C5a9f0896e5eB5d485CB677b3", "abi": [ { "inputs": [ @@ -7963,8 +7963,8 @@ } ] }, - "MockWIN": { - "address": "0x2E6Af3f3F059F43D764060968658c9F3c8f9479D", + "MockUSDD": { + "address": "0x2E2466e22FcbE0732Be385ee2FBb9C59a1098382", "abi": [ { "inputs": [ @@ -8272,8 +8272,8 @@ } ] }, - "MockWOO": { - "address": "0x65B849A4Fc306AF413E341D44dF8482F963fBB91", + "MockWIN": { + "address": "0x2E6Af3f3F059F43D764060968658c9F3c8f9479D", "abi": [ { "inputs": [ @@ -8581,8 +8581,8 @@ } ] }, - "MockagEUR": { - "address": "0x63061de4A25f24279AAab80400040684F92Ee319", + "MockWOO": { + "address": "0x65B849A4Fc306AF413E341D44dF8482F963fBB91", "abi": [ { "inputs": [ @@ -8890,8 +8890,8 @@ } ] }, - "MockankrBNB": { - "address": "0x167F1F9EF531b3576201aa3146b13c57dbEda514", + "MockagEUR": { + "address": "0x63061de4A25f24279AAab80400040684F92Ee319", "abi": [ { "inputs": [ @@ -9199,8 +9199,8 @@ } ] }, - "MockstkBNB": { - "address": "0x2999C176eBf66ecda3a646E70CeB5FF4d5fCFb8C", + "MockankrBNB": { + "address": "0x167F1F9EF531b3576201aa3146b13c57dbEda514", "abi": [ { "inputs": [ @@ -9508,298 +9508,1730 @@ } ] }, - "PoolLens": { - "address": "0x6492dF28A9478230205c940A245Ffb114EaEb9d1", + "MockstkBNB": { + "address": "0x2999C176eBf66ecda3a646E70CeB5FF4d5fCFb8C", "abi": [ { "inputs": [ { - "internalType": "address", - "name": "poolRegistryAddress", - "type": "address" - } - ], - "name": "getAllPools", - "outputs": [ + "internalType": "string", + "name": "name_", + "type": "string" + }, { - "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[]" + "internalType": "string", + "name": "symbol_", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals_", + "type": "uint8" } ], - "stateMutability": "view", - "type": "function" + "stateMutability": "nonpayable", + "type": "constructor" }, { + "anonymous": false, "inputs": [ { + "indexed": true, "internalType": "address", - "name": "account", + "name": "owner", "type": "address" }, { + "indexed": true, "internalType": "address", - "name": "comptrollerAddress", + "name": "spender", "type": "address" - } - ], - "name": "getPendingRewards", - "outputs": [ + }, + { + "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": "0x6492dF28A9478230205c940A245Ffb114EaEb9d1", + "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": "distributorAddress", + "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": "rewardTokenAddress", + "name": "underlyingAssetAddress", "type": "address" }, { "internalType": "uint256", - "name": "totalRewards", + "name": "vTokenDecimals", "type": "uint256" }, { - "components": [ - { - "internalType": "address", - "name": "vTokenAddress", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "internalType": "struct PoolLens.PendingReward[]", - "name": "pendingRewards", - "type": "tuple[]" + "internalType": "uint256", + "name": "underlyingDecimals", + "type": "uint256" } ], - "internalType": "struct PoolLens.RewardSummary[]", + "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", + "stateMutability": "view", + "type": "function" + } + ] + }, + "PoolRegistry": { + "address": "0xC85491616Fa949E048F3aAc39fbf5b0703800667", + "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": "comptrollerAddress", + "name": "newAdmin", "type": "address" } ], - "name": "getPoolBadDebt", + "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": "address", - "name": "comptroller", - "type": "address" + "internalType": "string", + "name": "category", + "type": "string" }, { - "internalType": "uint256", - "name": "totalBadDebtUsd", - "type": "uint256" + "internalType": "string", + "name": "logoURL", + "type": "string" }, { - "components": [ - { - "internalType": "address", - "name": "vTokenAddress", - "type": "address" - }, - { - "internalType": "uint256", - "name": "badDebtUsd", - "type": "uint256" - } - ], - "internalType": "struct PoolLens.BadDebt[]", - "name": "badDebts", - "type": "tuple[]" + "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" } ], - "internalType": "struct PoolLens.BadDebtSummary", - "name": "", + "indexed": false, + "internalType": "struct PoolRegistryInterface.VenusPoolMetaData", + "name": "newMetadata", "type": "tuple" } ], - "stateMutability": "view", - "type": "function" + "name": "PoolMetadataUpdated", + "type": "event" }, { + "anonymous": false, "inputs": [ { + "indexed": true, "internalType": "address", - "name": "poolRegistryAddress", + "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" - } - ], - "name": "getPoolByComptroller", - "outputs": [ + }, { "components": [ { @@ -9826,145 +11258,130 @@ "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": "string", - "name": "category", - "type": "string" + "internalType": "uint256", + "name": "collateralFactor", + "type": "uint256" }, { - "internalType": "string", - "name": "logoURL", - "type": "string" + "internalType": "uint256", + "name": "liquidationThreshold", + "type": "uint256" }, { - "internalType": "string", - "name": "description", - "type": "string" + "internalType": "uint256", + "name": "initialSupply", + "type": "uint256" }, { "internalType": "address", - "name": "priceOracle", + "name": "vTokenReceiver", "type": "address" }, { "internalType": "uint256", - "name": "closeFactor", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "liquidationIncentive", + "name": "supplyCap", "type": "uint256" }, { "internalType": "uint256", - "name": "minLiquidatableCollateral", + "name": "borrowCap", "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": "", + "internalType": "struct PoolRegistry.AddMarketInput", + "name": "input", "type": "tuple" } ], - "stateMutability": "view", + "name": "addMarket", + "outputs": [], + "stateMutability": "nonpayable", "type": "function" }, { "inputs": [ { - "internalType": "address", - "name": "poolRegistryAddress", + "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": [ { @@ -9993,12 +11410,23 @@ "type": "uint256" } ], - "internalType": "struct PoolRegistryInterface.VenusPool", - "name": "venusPool", - "type": "tuple" + "internalType": "struct PoolRegistryInterface.VenusPool[]", + "name": "", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "comptroller", + "type": "address" } ], - "name": "getPoolDataFromVenusPool", + "name": "getPoolByComptroller", "outputs": [ { "components": [ @@ -10026,7 +11454,223 @@ "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", @@ -10041,483 +11685,436 @@ "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": "", + "internalType": "struct PoolRegistryInterface.VenusPoolMetaData", + "name": "metadata_", "type": "tuple" } ], - "stateMutability": "view", + "name": "updatePoolMetadata", + "outputs": [], + "stateMutability": "nonpayable", "type": "function" }, { "inputs": [ { "internalType": "address", - "name": "poolRegistryAddress", + "name": "_logic", "type": "address" }, { "internalType": "address", - "name": "asset", + "name": "admin_", "type": "address" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" } ], - "name": "getPoolsSupportedByAsset", - "outputs": [ + "stateMutability": "payable", + "type": "constructor" + } + ] + }, + "PoolRegistry_Implementation": { + "address": "0xed659A02c5f63f299C28F6A246143326b922e3d9", + "abi": [ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ { - "internalType": "address[]", - "name": "", - "type": "address[]" + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "calledContract", + "type": "address" + }, + { + "internalType": "string", + "name": "methodSignature", + "type": "string" } ], - "stateMutability": "view", - "type": "function" + "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": "poolRegistryAddress", + "name": "comptroller", "type": "address" }, { + "indexed": true, "internalType": "address", - "name": "comptroller", + "name": "vTokenAddress", + "type": "address" + } + ], + "name": "MarketAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAccessControlManager", "type": "address" }, { + "indexed": false, "internalType": "address", - "name": "asset", + "name": "newAccessControlManager", "type": "address" } ], - "name": "getVTokenForAsset", - "outputs": [ + "name": "NewAccessControlManager", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ { + "indexed": true, "internalType": "address", - "name": "", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", "type": "address" } ], - "stateMutability": "view", - "type": "function" + "name": "OwnershipTransferStarted", + "type": "event" }, { + "anonymous": false, "inputs": [ { - "internalType": "contract VToken", - "name": "vToken", + "indexed": true, + "internalType": "address", + "name": "previousOwner", "type": "address" }, { + "indexed": true, "internalType": "address", - "name": "account", + "name": "newOwner", "type": "address" } ], - "name": "vTokenBalances", - "outputs": [ + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "comptroller", + "type": "address" + }, { "components": [ { - "internalType": "address", - "name": "vToken", - "type": "address" + "internalType": "string", + "name": "category", + "type": "string" }, { - "internalType": "uint256", - "name": "balanceOf", - "type": "uint256" + "internalType": "string", + "name": "logoURL", + "type": "string" }, { - "internalType": "uint256", - "name": "borrowBalanceCurrent", - "type": "uint256" - }, + "internalType": "string", + "name": "description", + "type": "string" + } + ], + "indexed": false, + "internalType": "struct PoolRegistryInterface.VenusPoolMetaData", + "name": "oldMetadata", + "type": "tuple" + }, + { + "components": [ { - "internalType": "uint256", - "name": "balanceOfUnderlying", - "type": "uint256" + "internalType": "string", + "name": "category", + "type": "string" }, { - "internalType": "uint256", - "name": "tokenBalance", - "type": "uint256" + "internalType": "string", + "name": "logoURL", + "type": "string" }, { - "internalType": "uint256", - "name": "tokenAllowance", - "type": "uint256" + "internalType": "string", + "name": "description", + "type": "string" } ], - "internalType": "struct PoolLens.VTokenBalances", - "name": "", + "indexed": false, + "internalType": "struct PoolRegistryInterface.VenusPoolMetaData", + "name": "newMetadata", "type": "tuple" } ], - "stateMutability": "nonpayable", - "type": "function" + "name": "PoolMetadataUpdated", + "type": "event" }, { + "anonymous": false, "inputs": [ { - "internalType": "contract VToken[]", - "name": "vTokens", - "type": "address[]" - }, - { + "indexed": true, "internalType": "address", - "name": "account", + "name": "comptroller", "type": "address" + }, + { + "indexed": false, + "internalType": "string", + "name": "oldName", + "type": "string" + }, + { + "indexed": false, + "internalType": "string", + "name": "newName", + "type": "string" } ], - "name": "vTokenBalancesAll", - "outputs": [ + "name": "PoolNameSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "comptroller", + "type": "address" + }, { "components": [ { - "internalType": "address", - "name": "vToken", - "type": "address" - }, - { - "internalType": "uint256", - "name": "balanceOf", - "type": "uint256" + "internalType": "string", + "name": "name", + "type": "string" }, { - "internalType": "uint256", - "name": "borrowBalanceCurrent", - "type": "uint256" + "internalType": "address", + "name": "creator", + "type": "address" }, { - "internalType": "uint256", - "name": "balanceOfUnderlying", - "type": "uint256" + "internalType": "address", + "name": "comptroller", + "type": "address" }, { "internalType": "uint256", - "name": "tokenBalance", + "name": "blockPosted", "type": "uint256" }, { "internalType": "uint256", - "name": "tokenAllowance", + "name": "timestampPosted", "type": "uint256" } ], - "internalType": "struct PoolLens.VTokenBalances[]", - "name": "", - "type": "tuple[]" + "indexed": false, + "internalType": "struct PoolRegistryInterface.VenusPool", + "name": "pool", + "type": "tuple" } ], + "name": "PoolRegistered", + "type": "event" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { - "inputs": [ + "inputs": [], + "name": "accessControlManager", + "outputs": [ { - "internalType": "contract VToken", - "name": "vToken", + "internalType": "contract IAccessControlManagerV8", + "name": "", "type": "address" } ], - "name": "vTokenMetadata", - "outputs": [ + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ { "components": [ { - "internalType": "address", + "internalType": "contract VToken", "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", + "name": "collateralFactor", "type": "uint256" }, { "internalType": "uint256", - "name": "totalCash", + "name": "liquidationThreshold", "type": "uint256" }, - { - "internalType": "bool", - "name": "isListed", - "type": "bool" - }, { "internalType": "uint256", - "name": "collateralFactorMantissa", + "name": "initialSupply", "type": "uint256" }, { "internalType": "address", - "name": "underlyingAssetAddress", + "name": "vTokenReceiver", "type": "address" }, { "internalType": "uint256", - "name": "vTokenDecimals", + "name": "supplyCap", "type": "uint256" }, { "internalType": "uint256", - "name": "underlyingDecimals", + "name": "borrowCap", "type": "uint256" } ], - "internalType": "struct PoolLens.VTokenMetadata", - "name": "", + "internalType": "struct PoolRegistry.AddMarketInput", + "name": "input", "type": "tuple" } ], - "stateMutability": "view", + "name": "addMarket", + "outputs": [], + "stateMutability": "nonpayable", "type": "function" }, { "inputs": [ { - "internalType": "contract VToken[]", - "name": "vTokens", - "type": "address[]" + "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": "vTokenMetadataAll", + "name": "addPool", "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": "uint256", + "name": "index", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getAllPools", + "outputs": [ + { + "components": [ { - "internalType": "bool", - "name": "isListed", - "type": "bool" + "internalType": "string", + "name": "name", + "type": "string" }, { - "internalType": "uint256", - "name": "collateralFactorMantissa", - "type": "uint256" + "internalType": "address", + "name": "creator", + "type": "address" }, { "internalType": "address", - "name": "underlyingAssetAddress", + "name": "comptroller", "type": "address" }, { "internalType": "uint256", - "name": "vTokenDecimals", + "name": "blockPosted", "type": "uint256" }, { "internalType": "uint256", - "name": "underlyingDecimals", + "name": "timestampPosted", "type": "uint256" } ], - "internalType": "struct PoolLens.VTokenMetadata[]", + "internalType": "struct PoolRegistryInterface.VenusPool[]", "name": "", "type": "tuple[]" } @@ -10528,27 +12125,42 @@ { "inputs": [ { - "internalType": "contract VToken", - "name": "vToken", + "internalType": "address", + "name": "comptroller", "type": "address" } ], - "name": "vTokenUnderlyingPrice", + "name": "getPoolByComptroller", "outputs": [ { "components": [ + { + "internalType": "string", + "name": "name", + "type": "string" + }, { "internalType": "address", - "name": "vToken", + "name": "creator", + "type": "address" + }, + { + "internalType": "address", + "name": "comptroller", "type": "address" }, { "internalType": "uint256", - "name": "underlyingPrice", + "name": "blockPosted", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "timestampPosted", "type": "uint256" } ], - "internalType": "struct PoolLens.VTokenUnderlyingPrice", + "internalType": "struct PoolRegistryInterface.VenusPool", "name": "", "type": "tuple" } @@ -10559,136 +12171,91 @@ { "inputs": [ { - "internalType": "contract VToken[]", - "name": "vTokens", - "type": "address[]" + "internalType": "address", + "name": "asset", + "type": "address" } ], - "name": "vTokenUnderlyingPriceAll", + "name": "getPoolsSupportedByAsset", "outputs": [ { - "components": [ - { - "internalType": "address", - "name": "vToken", - "type": "address" - }, - { - "internalType": "uint256", - "name": "underlyingPrice", - "type": "uint256" - } - ], - "internalType": "struct PoolLens.VTokenUnderlyingPrice[]", + "internalType": "address[]", "name": "", - "type": "tuple[]" + "type": "address[]" } ], "stateMutability": "view", "type": "function" - } - ] - }, - "PoolRegistry": { - "address": "0xC85491616Fa949E048F3aAc39fbf5b0703800667", - "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", + "name": "comptroller", "type": "address" - } - ], - "name": "BeaconUpgraded", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ + }, { - "indexed": true, "internalType": "address", - "name": "implementation", + "name": "asset", "type": "address" } ], - "name": "Upgraded", - "type": "event" - }, - { - "stateMutability": "payable", - "type": "fallback" - }, - { - "inputs": [], - "name": "admin", + "name": "getVTokenForAsset", "outputs": [ { "internalType": "address", - "name": "admin_", + "name": "", "type": "address" } ], - "stateMutability": "nonpayable", + "stateMutability": "view", "type": "function" }, { "inputs": [ { "internalType": "address", - "name": "newAdmin", + "name": "comptroller", "type": "address" } ], - "name": "changeAdmin", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "implementation", + "name": "getVenusPoolMetadata", "outputs": [ { - "internalType": "address", - "name": "implementation_", - "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": "", + "type": "tuple" } ], - "stateMutability": "nonpayable", + "stateMutability": "view", "type": "function" }, { "inputs": [ { "internalType": "address", - "name": "newImplementation", + "name": "accessControlManager_", "type": "address" } ], - "name": "upgradeTo", + "name": "initialize", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -10697,144 +12264,111 @@ "inputs": [ { "internalType": "address", - "name": "newImplementation", + "name": "", "type": "address" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" } ], - "name": "upgradeToAndCall", - "outputs": [], - "stateMutability": "payable", - "type": "function" - }, - { - "stateMutability": "payable", - "type": "receive" - }, - { - "inputs": [ + "name": "metadata", + "outputs": [ { - "internalType": "address", - "name": "sender", - "type": "address" + "internalType": "string", + "name": "category", + "type": "string" }, { - "internalType": "address", - "name": "calledContract", - "type": "address" + "internalType": "string", + "name": "logoURL", + "type": "string" }, { "internalType": "string", - "name": "methodSignature", + "name": "description", "type": "string" } ], - "name": "Unauthorized", - "type": "error" + "stateMutability": "view", + "type": "function" }, { "inputs": [], - "name": "ZeroAddressNotAllowed", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ + "name": "owner", + "outputs": [ { - "indexed": false, - "internalType": "uint8", - "name": "version", - "type": "uint8" + "internalType": "address", + "name": "", + "type": "address" } ], - "name": "Initialized", - "type": "event" + "stateMutability": "view", + "type": "function" }, { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "comptroller", - "type": "address" - }, + "inputs": [], + "name": "pendingOwner", + "outputs": [ { - "indexed": true, "internalType": "address", - "name": "vTokenAddress", + "name": "", "type": "address" } ], - "name": "MarketAdded", - "type": "event" + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" }, { - "anonymous": false, "inputs": [ { - "indexed": false, - "internalType": "address", - "name": "oldAccessControlManager", - "type": "address" - }, - { - "indexed": false, "internalType": "address", - "name": "newAccessControlManager", + "name": "accessControlManager_", "type": "address" } ], - "name": "NewAccessControlManager", - "type": "event" + "name": "setAccessControlManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" }, { - "anonymous": false, "inputs": [ { - "indexed": true, "internalType": "address", - "name": "previousOwner", + "name": "comptroller", "type": "address" }, { - "indexed": true, - "internalType": "address", - "name": "newOwner", - "type": "address" + "internalType": "string", + "name": "name", + "type": "string" } ], - "name": "OwnershipTransferStarted", - "type": "event" + "name": "setPoolName", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" }, { - "anonymous": false, "inputs": [ { - "indexed": true, - "internalType": "address", - "name": "previousOwner", - "type": "address" - }, - { - "indexed": true, "internalType": "address", "name": "newOwner", "type": "address" } ], - "name": "OwnershipTransferred", - "type": "event" + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" }, { - "anonymous": false, "inputs": [ { - "indexed": true, "internalType": "address", "name": "comptroller", "type": "address" @@ -10857,498 +12391,446 @@ "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", + "name": "metadata_", "type": "tuple" } ], - "name": "PoolMetadataUpdated", - "type": "event" - }, + "name": "updatePoolMetadata", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ] + }, + "PoolRegistry_Proxy": { + "address": "0xC85491616Fa949E048F3aAc39fbf5b0703800667", + "abi": [ { - "anonymous": false, "inputs": [ { - "indexed": true, "internalType": "address", - "name": "comptroller", + "name": "_logic", "type": "address" }, { - "indexed": false, - "internalType": "string", - "name": "oldName", - "type": "string" + "internalType": "address", + "name": "admin_", + "type": "address" }, { - "indexed": false, - "internalType": "string", - "name": "newName", - "type": "string" + "internalType": "bytes", + "name": "_data", + "type": "bytes" } ], - "name": "PoolNameSet", - "type": "event" + "stateMutability": "payable", + "type": "constructor" }, { "anonymous": false, "inputs": [ { - "indexed": true, + "indexed": false, "internalType": "address", - "name": "comptroller", + "name": "previousAdmin", "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" + "internalType": "address", + "name": "newAdmin", + "type": "address" } ], - "name": "PoolRegistered", + "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" }, { + "anonymous": false, "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" + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" } ], - "name": "addMarket", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" + "name": "Upgraded", + "type": "event" }, { - "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" - }, + "stateMutability": "payable", + "type": "fallback" + }, + { + "inputs": [], + "name": "admin", + "outputs": [ { - "internalType": "uint256", - "name": "minLiquidatableCollateral", - "type": "uint256" + "internalType": "address", + "name": "admin_", + "type": "address" } ], - "name": "addPool", - "outputs": [ + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ { - "internalType": "uint256", - "name": "index", - "type": "uint256" + "internalType": "address", + "name": "newAdmin", + "type": "address" } ], + "name": "changeAdmin", + "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [], - "name": "getAllPools", + "name": "implementation", "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[]" + "internalType": "address", + "name": "implementation_", + "type": "address" } ], - "stateMutability": "view", + "stateMutability": "nonpayable", "type": "function" }, { "inputs": [ { "internalType": "address", - "name": "comptroller", + "name": "newImplementation", "type": "address" } ], - "name": "getPoolByComptroller", - "outputs": [ + "name": "upgradeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ { - "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" + "internalType": "address", + "name": "newImplementation", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" } ], - "stateMutability": "view", + "name": "upgradeToAndCall", + "outputs": [], + "stateMutability": "payable", "type": "function" }, { + "stateMutability": "payable", + "type": "receive" + } + ] + }, + "ProtocolShareReserve": { + "address": "0xc987a03ab6C2A5891Fc0919f021cc693B5E55278", + "abi": [ + { + "anonymous": false, "inputs": [ { + "indexed": false, "internalType": "address", - "name": "asset", + "name": "previousAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", "type": "address" } ], - "name": "getPoolsSupportedByAsset", - "outputs": [ + "name": "AdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ { - "internalType": "address[]", - "name": "", - "type": "address[]" + "indexed": true, + "internalType": "address", + "name": "beacon", + "type": "address" } ], - "stateMutability": "view", - "type": "function" + "name": "BeaconUpgraded", + "type": "event" }, { + "anonymous": false, "inputs": [ { + "indexed": true, "internalType": "address", - "name": "comptroller", + "name": "implementation", "type": "address" - }, + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "inputs": [], + "name": "admin", + "outputs": [ { "internalType": "address", - "name": "asset", + "name": "admin_", "type": "address" } ], - "name": "getVTokenForAsset", + "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": "", + "name": "implementation_", "type": "address" } ], - "stateMutability": "view", + "stateMutability": "nonpayable", "type": "function" }, { "inputs": [ { "internalType": "address", - "name": "comptroller", + "name": "newImplementation", "type": "address" } ], - "name": "getVenusPoolMetadata", - "outputs": [ + "name": "upgradeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ { - "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" + "internalType": "address", + "name": "newImplementation", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" } ], - "stateMutability": "view", + "name": "upgradeToAndCall", + "outputs": [], + "stateMutability": "payable", "type": "function" }, { + "stateMutability": "payable", + "type": "receive" + }, + { + "inputs": [], + "name": "ZeroAddressNotAllowed", + "type": "error" + }, + { + "anonymous": false, "inputs": [ { + "indexed": true, "internalType": "address", - "name": "accessControlManager_", + "name": "comptroller", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "asset", "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" } ], - "name": "initialize", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" + "name": "AssetsReservesUpdated", + "type": "event" }, { + "anonymous": false, "inputs": [ { + "indexed": true, "internalType": "address", - "name": "", + "name": "comptroller", "type": "address" - } - ], - "name": "metadata", - "outputs": [ - { - "internalType": "string", - "name": "category", - "type": "string" }, { - "internalType": "string", - "name": "logoURL", - "type": "string" + "indexed": true, + "internalType": "address", + "name": "asset", + "type": "address" }, { - "internalType": "string", - "name": "description", - "type": "string" + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" } ], - "stateMutability": "view", - "type": "function" + "name": "FundsReleased", + "type": "event" }, { - "inputs": [], - "name": "owner", - "outputs": [ + "anonymous": false, + "inputs": [ { - "internalType": "address", - "name": "", - "type": "address" + "indexed": false, + "internalType": "uint8", + "name": "version", + "type": "uint8" } ], - "stateMutability": "view", - "type": "function" + "name": "Initialized", + "type": "event" }, { - "inputs": [], - "name": "pendingOwner", - "outputs": [ + "anonymous": false, + "inputs": [ { + "indexed": true, "internalType": "address", - "name": "", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", "type": "address" } ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "renounceOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" + "name": "OwnershipTransferStarted", + "type": "event" }, { + "anonymous": false, "inputs": [ { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, "internalType": "address", - "name": "accessControlManager_", + "name": "newOwner", "type": "address" } ], - "name": "setAccessControlManager", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" + "name": "OwnershipTransferred", + "type": "event" }, { + "anonymous": false, "inputs": [ { + "indexed": true, "internalType": "address", - "name": "comptroller", + "name": "oldPoolRegistry", "type": "address" }, { - "internalType": "string", - "name": "name", - "type": "string" + "indexed": true, + "internalType": "address", + "name": "newPoolRegistry", + "type": "address" } ], - "name": "setPoolName", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" + "name": "PoolRegistryUpdated", + "type": "event" }, { + "anonymous": false, "inputs": [ { + "indexed": true, "internalType": "address", - "name": "newOwner", + "name": "token", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" } ], - "name": "transferOwnership", + "name": "SweepToken", + "type": "event" + }, + { + "inputs": [], + "name": "acceptOwnership", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -11357,548 +12839,430 @@ "inputs": [ { "internalType": "address", - "name": "comptroller", + "name": "", "type": "address" - }, + } + ], + "name": "assetsReserves", + "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": "metadata_", - "type": "tuple" + "internalType": "uint256", + "name": "", + "type": "uint256" } ], - "name": "updatePoolMetadata", - "outputs": [], - "stateMutability": "nonpayable", + "stateMutability": "view", "type": "function" }, { "inputs": [ { "internalType": "address", - "name": "_logic", + "name": "comptroller", "type": "address" }, { "internalType": "address", - "name": "admin_", + "name": "asset", "type": "address" - }, + } + ], + "name": "getPoolAssetReserve", + "outputs": [ { - "internalType": "bytes", - "name": "_data", - "type": "bytes" + "internalType": "uint256", + "name": "", + "type": "uint256" } ], - "stateMutability": "payable", - "type": "constructor" - } - ] - }, - "PoolRegistry_Implementation": { - "address": "0xed659A02c5f63f299C28F6A246143326b922e3d9", - "abi": [ - { - "inputs": [], - "stateMutability": "nonpayable", - "type": "constructor" + "stateMutability": "view", + "type": "function" }, { "inputs": [ { "internalType": "address", - "name": "sender", + "name": "protocolIncome_", "type": "address" }, { "internalType": "address", - "name": "calledContract", + "name": "riskFund_", "type": "address" - }, - { - "internalType": "string", - "name": "methodSignature", - "type": "string" } ], - "name": "Unauthorized", - "type": "error" + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" }, { "inputs": [], - "name": "ZeroAddressNotAllowed", - "type": "error" + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" }, { - "anonymous": false, - "inputs": [ + "inputs": [], + "name": "pendingOwner", + "outputs": [ { - "indexed": false, - "internalType": "uint8", - "name": "version", - "type": "uint8" + "internalType": "address", + "name": "", + "type": "address" } ], - "name": "Initialized", - "type": "event" + "stateMutability": "view", + "type": "function" }, { - "anonymous": false, - "inputs": [ + "inputs": [], + "name": "poolRegistry", + "outputs": [ { - "indexed": true, "internalType": "address", - "name": "comptroller", + "name": "", "type": "address" - }, + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "protocolIncome", + "outputs": [ { - "indexed": true, "internalType": "address", - "name": "vTokenAddress", + "name": "", "type": "address" } ], - "name": "MarketAdded", - "type": "event" + "stateMutability": "view", + "type": "function" }, { - "anonymous": false, "inputs": [ { - "indexed": false, "internalType": "address", - "name": "oldAccessControlManager", + "name": "comptroller", "type": "address" }, { - "indexed": false, "internalType": "address", - "name": "newAccessControlManager", + "name": "asset", "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" } ], - "name": "NewAccessControlManager", - "type": "event" + "name": "releaseFunds", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" }, { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "previousOwner", - "type": "address" - }, + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "riskFund", + "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" - }, - { - "indexed": true, "internalType": "address", - "name": "newOwner", + "name": "poolRegistry_", "type": "address" } ], - "name": "OwnershipTransferred", - "type": "event" + "name": "setPoolRegistry", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" }, { - "anonymous": false, "inputs": [ { - "indexed": true, "internalType": "address", - "name": "comptroller", + "name": "_token", "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" + "internalType": "address", + "name": "_to", + "type": "address" } ], - "name": "PoolMetadataUpdated", - "type": "event" + "name": "sweepToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" }, { - "anonymous": false, "inputs": [ { - "indexed": true, "internalType": "address", - "name": "comptroller", + "name": "newOwner", "type": "address" - }, - { - "indexed": false, - "internalType": "string", - "name": "oldName", - "type": "string" - }, - { - "indexed": false, - "internalType": "string", - "name": "newName", - "type": "string" } ], - "name": "PoolNameSet", - "type": "event" + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" }, { - "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" + "internalType": "address", + "name": "asset", + "type": "address" } ], - "name": "PoolRegistered", - "type": "event" - }, - { - "inputs": [], - "name": "acceptOwnership", + "name": "updateAssetsState", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { - "inputs": [], - "name": "accessControlManager", - "outputs": [ + "inputs": [ { - "internalType": "contract IAccessControlManagerV8", - "name": "", + "internalType": "address", + "name": "_logic", "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" + "internalType": "address", + "name": "admin_", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" } ], - "name": "addMarket", - "outputs": [], + "stateMutability": "payable", + "type": "constructor" + } + ] + }, + "ProtocolShareReserve_Implementation": { + "address": "0x0Bbea4B14f475bF5eb60Fc2b0Ca90d3d089Ef833", + "abi": [ + { + "inputs": [], "stateMutability": "nonpayable", - "type": "function" + "type": "constructor" + }, + { + "inputs": [], + "name": "ZeroAddressNotAllowed", + "type": "error" }, { + "anonymous": false, "inputs": [ { - "internalType": "string", - "name": "name", - "type": "string" + "indexed": true, + "internalType": "address", + "name": "comptroller", + "type": "address" }, { - "internalType": "contract Comptroller", - "name": "comptroller", + "indexed": true, + "internalType": "address", + "name": "asset", "type": "address" }, { + "indexed": false, "internalType": "uint256", - "name": "closeFactor", + "name": "amount", "type": "uint256" + } + ], + "name": "AssetsReservesUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "comptroller", + "type": "address" }, { - "internalType": "uint256", - "name": "liquidationIncentive", - "type": "uint256" + "indexed": true, + "internalType": "address", + "name": "asset", + "type": "address" }, { + "indexed": false, "internalType": "uint256", - "name": "minLiquidatableCollateral", + "name": "amount", "type": "uint256" } ], - "name": "addPool", - "outputs": [ + "name": "FundsReleased", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ { - "internalType": "uint256", - "name": "index", - "type": "uint256" + "indexed": false, + "internalType": "uint8", + "name": "version", + "type": "uint8" } ], - "stateMutability": "nonpayable", - "type": "function" + "name": "Initialized", + "type": "event" }, { - "inputs": [], - "name": "getAllPools", - "outputs": [ + "anonymous": false, + "inputs": [ { - "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[]" + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" } ], - "stateMutability": "view", - "type": "function" + "name": "OwnershipTransferStarted", + "type": "event" }, { + "anonymous": false, "inputs": [ { + "indexed": true, "internalType": "address", - "name": "comptroller", + "name": "previousOwner", "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" + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" } ], - "stateMutability": "view", - "type": "function" + "name": "OwnershipTransferred", + "type": "event" }, { + "anonymous": false, "inputs": [ { + "indexed": true, "internalType": "address", - "name": "asset", + "name": "oldPoolRegistry", "type": "address" - } - ], - "name": "getPoolsSupportedByAsset", - "outputs": [ + }, { - "internalType": "address[]", - "name": "", - "type": "address[]" + "indexed": true, + "internalType": "address", + "name": "newPoolRegistry", + "type": "address" } ], - "stateMutability": "view", - "type": "function" + "name": "PoolRegistryUpdated", + "type": "event" }, { + "anonymous": false, "inputs": [ { + "indexed": true, "internalType": "address", - "name": "comptroller", + "name": "token", "type": "address" }, { + "indexed": true, "internalType": "address", - "name": "asset", + "name": "to", "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" } ], - "name": "getVTokenForAsset", - "outputs": [ + "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" }, @@ -11907,32 +13271,20 @@ { "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", + "type": "address" + }, + { + "internalType": "address", + "name": "asset", + "type": "address" + } + ], + "name": "getPoolAssetReserve", + "outputs": [ + { + "internalType": "uint256", "name": "", - "type": "tuple" + "type": "uint256" } ], "stateMutability": "view", @@ -11942,7 +13294,12 @@ "inputs": [ { "internalType": "address", - "name": "accessControlManager_", + "name": "protocolIncome_", + "type": "address" + }, + { + "internalType": "address", + "name": "riskFund_", "type": "address" } ], @@ -11952,29 +13309,26 @@ "type": "function" }, { - "inputs": [ + "inputs": [], + "name": "owner", + "outputs": [ { "internalType": "address", "name": "", "type": "address" } ], - "name": "metadata", + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pendingOwner", "outputs": [ { - "internalType": "string", - "name": "category", - "type": "string" - }, - { - "internalType": "string", - "name": "logoURL", - "type": "string" - }, - { - "internalType": "string", - "name": "description", - "type": "string" + "internalType": "address", + "name": "", + "type": "address" } ], "stateMutability": "view", @@ -11982,7 +13336,7 @@ }, { "inputs": [], - "name": "owner", + "name": "poolRegistry", "outputs": [ { "internalType": "address", @@ -11995,7 +13349,7 @@ }, { "inputs": [], - "name": "pendingOwner", + "name": "protocolIncome", "outputs": [ { "internalType": "address", @@ -12006,6 +13360,35 @@ "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", @@ -12013,15 +13396,28 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [], + "name": "riskFund", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [ { "internalType": "address", - "name": "accessControlManager_", + "name": "poolRegistry_", "type": "address" } ], - "name": "setAccessControlManager", + "name": "setPoolRegistry", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -12030,16 +13426,16 @@ "inputs": [ { "internalType": "address", - "name": "comptroller", + "name": "_token", "type": "address" }, { - "internalType": "string", - "name": "name", - "type": "string" + "internalType": "address", + "name": "_to", + "type": "address" } ], - "name": "setPoolName", + "name": "sweepToken", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -12065,37 +13461,20 @@ "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" + "internalType": "address", + "name": "asset", + "type": "address" } ], - "name": "updatePoolMetadata", + "name": "updateAssetsState", "outputs": [], "stateMutability": "nonpayable", "type": "function" } ] }, - "PoolRegistry_Proxy": { - "address": "0xC85491616Fa949E048F3aAc39fbf5b0703800667", + "ProtocolShareReserve_Proxy": { + "address": "0xc987a03ab6C2A5891Fc0919f021cc693B5E55278", "abi": [ { "inputs": [ @@ -12243,160 +13622,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" }, { @@ -12404,24 +13766,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" }, { @@ -12443,36 +13817,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": true, - "internalType": "address", - "name": "newOwner", - "type": "address" + "indexed": false, + "internalType": "uint256", + "name": "newmaxLoopsLimit", + "type": "uint256" } ], - "name": "OwnershipTransferStarted", + "name": "MaxLoopsLimitUpdated", "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": "OwnershipTransferred", + "name": "NewAccessControlManager", "type": "event" }, { @@ -12481,17 +13868,17 @@ { "indexed": true, "internalType": "address", - "name": "oldPoolRegistry", + "name": "previousOwner", "type": "address" }, { "indexed": true, "internalType": "address", - "name": "newPoolRegistry", + "name": "newOwner", "type": "address" } ], - "name": "PoolRegistryUpdated", + "name": "OwnershipTransferStarted", "type": "event" }, { @@ -12500,187 +13887,160 @@ { "indexed": true, "internalType": "address", - "name": "token", + "name": "previousOwner", "type": "address" }, { "indexed": true, "internalType": "address", - "name": "to", + "name": "newOwner", "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" } ], - "name": "SweepToken", + "name": "OwnershipTransferred", "type": "event" }, { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { + "anonymous": false, "inputs": [ { + "indexed": true, "internalType": "address", - "name": "", + "name": "vToken", "type": "address" - } - ], - "name": "assetsReserves", - "outputs": [ + }, { - "internalType": "uint256", - "name": "", - "type": "uint256" + "components": [ + { + "internalType": "uint256", + "name": "mantissa", + "type": "uint256" + } + ], + "indexed": false, + "internalType": "struct ExponentialNoError.Exp", + "name": "marketBorrowIndex", + "type": "tuple" } ], - "stateMutability": "view", - "type": "function" + "name": "RewardTokenBorrowIndexUpdated", + "type": "event" }, { + "anonymous": false, "inputs": [ { - "internalType": "address", - "name": "comptroller", + "indexed": true, + "internalType": "contract VToken", + "name": "vToken", "type": "address" }, { - "internalType": "address", - "name": "asset", - "type": "address" - } - ], - "name": "getPoolAssetReserve", - "outputs": [ - { + "indexed": false, "internalType": "uint256", - "name": "", + "name": "newSpeed", "type": "uint256" } ], - "stateMutability": "view", - "type": "function" + "name": "RewardTokenBorrowSpeedUpdated", + "type": "event" }, { + "anonymous": false, "inputs": [ { + "indexed": true, "internalType": "address", - "name": "protocolIncome_", + "name": "recipient", "type": "address" }, { - "internalType": "address", - "name": "riskFund_", - "type": "address" - } - ], - "name": "initialize", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" } ], - "stateMutability": "view", - "type": "function" + "name": "RewardTokenGranted", + "type": "event" }, { - "inputs": [], - "name": "pendingOwner", - "outputs": [ + "anonymous": false, + "inputs": [ { + "indexed": true, "internalType": "address", - "name": "", + "name": "vToken", "type": "address" } ], - "stateMutability": "view", - "type": "function" + "name": "RewardTokenSupplyIndexUpdated", + "type": "event" }, { - "inputs": [], - "name": "poolRegistry", - "outputs": [ + "anonymous": false, + "inputs": [ { - "internalType": "address", - "name": "", + "indexed": true, + "internalType": "contract VToken", + "name": "vToken", "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "protocolIncome", - "outputs": [ + }, { - "internalType": "address", - "name": "", - "type": "address" + "indexed": false, + "internalType": "uint256", + "name": "newSpeed", + "type": "uint256" } ], - "stateMutability": "view", - "type": "function" + "name": "RewardTokenSupplySpeedUpdated", + "type": "event" }, { + "anonymous": false, "inputs": [ { + "indexed": true, "internalType": "address", - "name": "comptroller", - "type": "address" - }, - { - "internalType": "address", - "name": "asset", + "name": "vToken", "type": "address" }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" + { + "indexed": false, + "internalType": "uint32", + "name": "newBlock", + "type": "uint32" } ], - "name": "releaseFunds", + "name": "SupplyLastRewardingBlockUpdated", + "type": "event" + }, + { + "inputs": [], + "name": "INITIAL_INDEX", "outputs": [ { - "internalType": "uint256", + "internalType": "uint224", "name": "", - "type": "uint256" + "type": "uint224" } ], - "stateMutability": "nonpayable", + "stateMutability": "view", "type": "function" }, { "inputs": [], - "name": "renounceOwnership", + "name": "acceptOwnership", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [], - "name": "riskFund", + "name": "accessControlManager", "outputs": [ { - "internalType": "address", + "internalType": "contract IAccessControlManagerV8", "name": "", "type": "address" } @@ -12692,11 +14052,16 @@ "inputs": [ { "internalType": "address", - "name": "poolRegistry_", + "name": "holder", "type": "address" + }, + { + "internalType": "contract VToken[]", + "name": "vTokens", + "type": "address[]" } ], - "name": "setPoolRegistry", + "name": "claimRewardToken", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -12705,16 +14070,11 @@ "inputs": [ { "internalType": "address", - "name": "_token", - "type": "address" - }, - { - "internalType": "address", - "name": "_to", + "name": "holder", "type": "address" } ], - "name": "sweepToken", + "name": "claimRewardToken", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -12723,11 +14083,28 @@ "inputs": [ { "internalType": "address", - "name": "newOwner", + "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": "transferOwnership", + "name": "distributeBorrowerRewardToken", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -12736,206 +14113,259 @@ "inputs": [ { "internalType": "address", - "name": "comptroller", + "name": "vToken", "type": "address" }, { "internalType": "address", - "name": "asset", + "name": "supplier", "type": "address" } ], - "name": "updateAssetsState", + "name": "distributeSupplierRewardToken", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { - "inputs": [ + "inputs": [], + "name": "getBlockNumber", + "outputs": [ { - "internalType": "address", - "name": "_logic", - "type": "address" - }, + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ { "internalType": "address", - "name": "admin_", + "name": "recipient", "type": "address" }, { - "internalType": "bytes", - "name": "_data", - "type": "bytes" + "internalType": "uint256", + "name": "amount", + "type": "uint256" } ], - "stateMutability": "payable", - "type": "constructor" - } - ] - }, - "ProtocolShareReserve_Implementation": { - "address": "0x0Bbea4B14f475bF5eb60Fc2b0Ca90d3d089Ef833", - "abi": [ - { - "inputs": [], + "name": "grantRewardToken", + "outputs": [], "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "ZeroAddressNotAllowed", - "type": "error" + "type": "function" }, { - "anonymous": false, "inputs": [ { - "indexed": true, - "internalType": "address", - "name": "comptroller", + "internalType": "contract Comptroller", + "name": "comptroller_", "type": "address" }, { - "indexed": true, - "internalType": "address", - "name": "asset", + "internalType": "contract IERC20Upgradeable", + "name": "rewardToken_", "type": "address" }, { - "indexed": false, "internalType": "uint256", - "name": "amount", + "name": "loopsLimit_", "type": "uint256" + }, + { + "internalType": "address", + "name": "accessControlManager_", + "type": "address" } ], - "name": "AssetsReservesUpdated", - "type": "event" + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" }, { - "anonymous": false, "inputs": [ { - "indexed": true, "internalType": "address", - "name": "comptroller", + "name": "vToken", "type": "address" - }, + } + ], + "name": "initializeMarket", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ { - "indexed": true, "internalType": "address", - "name": "asset", + "name": "", "type": "address" - }, + } + ], + "name": "lastContributorBlock", + "outputs": [ { - "indexed": false, "internalType": "uint256", - "name": "amount", + "name": "", "type": "uint256" } ], - "name": "FundsReleased", - "type": "event" + "stateMutability": "view", + "type": "function" }, { - "anonymous": false, - "inputs": [ + "inputs": [], + "name": "maxLoopsLimit", + "outputs": [ { - "indexed": false, - "internalType": "uint8", - "name": "version", - "type": "uint8" + "internalType": "uint256", + "name": "", + "type": "uint256" } ], - "name": "Initialized", - "type": "event" + "stateMutability": "view", + "type": "function" }, { - "anonymous": false, - "inputs": [ + "inputs": [], + "name": "owner", + "outputs": [ { - "indexed": true, "internalType": "address", - "name": "previousOwner", + "name": "", "type": "address" - }, + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pendingOwner", + "outputs": [ { - "indexed": true, "internalType": "address", - "name": "newOwner", + "name": "", "type": "address" } ], - "name": "OwnershipTransferStarted", - "type": "event" + "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" }, { - "anonymous": false, "inputs": [ { - "indexed": true, "internalType": "address", - "name": "previousOwner", + "name": "", "type": "address" - }, + } + ], + "name": "rewardTokenAccrued", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ { - "indexed": true, "internalType": "address", - "name": "newOwner", + "name": "", "type": "address" } ], - "name": "OwnershipTransferred", - "type": "event" + "name": "rewardTokenBorrowSpeeds", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "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" }, { @@ -12946,7 +14376,7 @@ "type": "address" } ], - "name": "assetsReserves", + "name": "rewardTokenContributorSpeeds", "outputs": [ { "internalType": "uint256", @@ -12961,16 +14391,16 @@ "inputs": [ { "internalType": "address", - "name": "comptroller", + "name": "", "type": "address" }, { "internalType": "address", - "name": "asset", + "name": "", "type": "address" } ], - "name": "getPoolAssetReserve", + "name": "rewardTokenSupplierIndex", "outputs": [ { "internalType": "uint256", @@ -12985,130 +14415,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" @@ -13116,17 +14529,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" @@ -13148,46 +14566,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": [ @@ -13310,16 +14740,6 @@ { "stateMutability": "payable", "type": "receive" - } - ] - }, - "RewardsDistributorImpl": { - "address": "0xfAE44cf6309598c2557Bb265BF0401D594db97DA", - "abi": [ - { - "inputs": [], - "stateMutability": "nonpayable", - "type": "constructor" }, { "inputs": [ @@ -14303,11 +15723,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, @@ -15438,8 +17028,8 @@ } ] }, - "RewardsDistributor_DeFi_0_Proxy": { - "address": "0x2b67Cfaf28a1aBbBf71fb814Ad384d0C5a98e0F9", + "RewardsDistributor_DeFi_1_Proxy": { + "address": "0x4be90041D1e082EfE3613099aA3b987D9045d718", "abi": [ { "inputs": [ @@ -15587,8 +17177,8 @@ } ] }, - "RewardsDistributor_DeFi_1": { - "address": "0x4be90041D1e082EfE3613099aA3b987D9045d718", + "RewardsDistributor_GameFi_0": { + "address": "0x5651866bcC4650d6fe5178E5ED7a8Be2cf3F70D0", "abi": [ { "anonymous": false, @@ -16719,8 +18309,8 @@ } ] }, - "RewardsDistributor_DeFi_1_Proxy": { - "address": "0x4be90041D1e082EfE3613099aA3b987D9045d718", + "RewardsDistributor_GameFi_0_Proxy": { + "address": "0x5651866bcC4650d6fe5178E5ED7a8Be2cf3F70D0", "abi": [ { "inputs": [ @@ -16868,8 +18458,8 @@ } ] }, - "RewardsDistributor_GameFi_0": { - "address": "0x5651866bcC4650d6fe5178E5ED7a8Be2cf3F70D0", + "RewardsDistributor_GameFi_1": { + "address": "0x66E213a4b8ba1c8D62cAa4649C7177E29321E262", "abi": [ { "anonymous": false, @@ -18000,8 +19590,8 @@ } ] }, - "RewardsDistributor_GameFi_0_Proxy": { - "address": "0x5651866bcC4650d6fe5178E5ED7a8Be2cf3F70D0", + "RewardsDistributor_GameFi_1_Proxy": { + "address": "0x66E213a4b8ba1c8D62cAa4649C7177E29321E262", "abi": [ { "inputs": [ @@ -18149,8 +19739,8 @@ } ] }, - "RewardsDistributor_GameFi_1": { - "address": "0x66E213a4b8ba1c8D62cAa4649C7177E29321E262", + "RewardsDistributor_LiquidStakedBNB_0": { + "address": "0x7df11563c6b6b8027aE619FD9644A647dED5893B", "abi": [ { "anonymous": false, @@ -19281,8 +20871,8 @@ } ] }, - "RewardsDistributor_GameFi_1_Proxy": { - "address": "0x66E213a4b8ba1c8D62cAa4649C7177E29321E262", + "RewardsDistributor_LiquidStakedBNB_0_Proxy": { + "address": "0x7df11563c6b6b8027aE619FD9644A647dED5893B", "abi": [ { "inputs": [ @@ -19430,8 +21020,8 @@ } ] }, - "RewardsDistributor_LiquidStakedBNB_0": { - "address": "0x7df11563c6b6b8027aE619FD9644A647dED5893B", + "RewardsDistributor_LiquidStakedBNB_1": { + "address": "0x72c770A1E73Ad9ccD5249fC5536346f95345Fe2c", "abi": [ { "anonymous": false, @@ -20562,8 +22152,8 @@ } ] }, - "RewardsDistributor_LiquidStakedBNB_0_Proxy": { - "address": "0x7df11563c6b6b8027aE619FD9644A647dED5893B", + "RewardsDistributor_LiquidStakedBNB_1_Proxy": { + "address": "0x72c770A1E73Ad9ccD5249fC5536346f95345Fe2c", "abi": [ { "inputs": [ @@ -20711,8 +22301,8 @@ } ] }, - "RewardsDistributor_LiquidStakedBNB_1": { - "address": "0x72c770A1E73Ad9ccD5249fC5536346f95345Fe2c", + "RewardsDistributor_LiquidStakedBNB_2": { + "address": "0x8Ad2Ad29e4e2C0606644Be51c853A7A4a3078F85", "abi": [ { "anonymous": false, @@ -21843,8 +23433,8 @@ } ] }, - "RewardsDistributor_LiquidStakedBNB_1_Proxy": { - "address": "0x72c770A1E73Ad9ccD5249fC5536346f95345Fe2c", + "RewardsDistributor_LiquidStakedBNB_2_Proxy": { + "address": "0x8Ad2Ad29e4e2C0606644Be51c853A7A4a3078F85", "abi": [ { "inputs": [ @@ -21992,8 +23582,8 @@ } ] }, - "RewardsDistributor_LiquidStakedBNB_2": { - "address": "0x8Ad2Ad29e4e2C0606644Be51c853A7A4a3078F85", + "RewardsDistributor_LiquidStakedBNB_3": { + "address": "0x37fA1e5613455223F09e179DFAEBba61d7505C97", "abi": [ { "anonymous": false, @@ -23124,8 +24714,8 @@ } ] }, - "RewardsDistributor_LiquidStakedBNB_2_Proxy": { - "address": "0x8Ad2Ad29e4e2C0606644Be51c853A7A4a3078F85", + "RewardsDistributor_LiquidStakedBNB_3_Proxy": { + "address": "0x37fA1e5613455223F09e179DFAEBba61d7505C97", "abi": [ { "inputs": [ @@ -23273,8 +24863,8 @@ } ] }, - "RewardsDistributor_LiquidStakedBNB_3": { - "address": "0x37fA1e5613455223F09e179DFAEBba61d7505C97", + "RewardsDistributor_StableCoins_0": { + "address": "0xb0269d68CfdCc30Cb7Cd2E0b52b08Fa7Ffd3079b", "abi": [ { "anonymous": false, @@ -24405,8 +25995,8 @@ } ] }, - "RewardsDistributor_LiquidStakedBNB_3_Proxy": { - "address": "0x37fA1e5613455223F09e179DFAEBba61d7505C97", + "RewardsDistributor_StableCoins_0_Proxy": { + "address": "0xb0269d68CfdCc30Cb7Cd2E0b52b08Fa7Ffd3079b", "abi": [ { "inputs": [ @@ -24554,8 +26144,8 @@ } ] }, - "RewardsDistributor_StableCoins_0": { - "address": "0xb0269d68CfdCc30Cb7Cd2E0b52b08Fa7Ffd3079b", + "RewardsDistributor_StableCoins_1": { + "address": "0x2aBEf3602B688493fe698EF11D27DCa43a0CE4BE", "abi": [ { "anonymous": false, @@ -25686,8 +27276,8 @@ } ] }, - "RewardsDistributor_StableCoins_0_Proxy": { - "address": "0xb0269d68CfdCc30Cb7Cd2E0b52b08Fa7Ffd3079b", + "RewardsDistributor_StableCoins_1_Proxy": { + "address": "0x2aBEf3602B688493fe698EF11D27DCa43a0CE4BE", "abi": [ { "inputs": [ @@ -25835,8 +27425,8 @@ } ] }, - "RewardsDistributor_StableCoins_1": { - "address": "0x2aBEf3602B688493fe698EF11D27DCa43a0CE4BE", + "RewardsDistributor_StableCoins_2": { + "address": "0x78d32FC46e5025c29e3BA03Fcf2840323351F26a", "abi": [ { "anonymous": false, @@ -26967,8 +28557,8 @@ } ] }, - "RewardsDistributor_StableCoins_1_Proxy": { - "address": "0x2aBEf3602B688493fe698EF11D27DCa43a0CE4BE", + "RewardsDistributor_StableCoins_2_Proxy": { + "address": "0x78d32FC46e5025c29e3BA03Fcf2840323351F26a", "abi": [ { "inputs": [ diff --git a/deployments/bsctestnet/MockANGLE.json b/deployments/bsctestnet/MockANGLE.json new file mode 100644 index 000000000..be260bbc8 --- /dev/null +++ b/deployments/bsctestnet/MockANGLE.json @@ -0,0 +1,450 @@ +{ + "address": "0xD1Bc731d188ACc3f52a6226B328a89056B0Ec71a", + "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": "0xef1d6446bb3fc31ffce33922492eb0b5cc7085b7be3bd31ef62ba47708f1488c", + "receipt": { + "to": null, + "from": "0xcd2a514f04241b7c9A0d5d54441e92E4611929CF", + "contractAddress": "0xD1Bc731d188ACc3f52a6226B328a89056B0Ec71a", + "transactionIndex": 5, + "gasUsed": "636028", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x1cb8e9577181668d9d0a8ff1df3f31e52d97725c269e67f8aaf11a1deff98f22", + "transactionHash": "0xef1d6446bb3fc31ffce33922492eb0b5cc7085b7be3bd31ef62ba47708f1488c", + "logs": [], + "blockNumber": 33734400, + "cumulativeGasUsed": "1698490", + "status": 1, + "byzantium": true + }, + "args": ["ANGLE_bsc", "ANGLE", 18], + "numDeployments": 1, + "solcInputHash": "6d4db51b84097a74598623a15df3d6fb", + "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/RewardsDistributor_StableCoins_2.json b/deployments/bsctestnet/RewardsDistributor_StableCoins_2.json new file mode 100644 index 000000000..883c9a322 --- /dev/null +++ b/deployments/bsctestnet/RewardsDistributor_StableCoins_2.json @@ -0,0 +1,1270 @@ +{ + "address": "0x78d32FC46e5025c29e3BA03Fcf2840323351F26a", + "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": "0x3c03493f8c9b7245174379cc256cb00018bdc24ff7881aaecccc5d668a43d5dd", + "receipt": { + "to": null, + "from": "0xcd2a514f04241b7c9A0d5d54441e92E4611929CF", + "contractAddress": "0x78d32FC46e5025c29e3BA03Fcf2840323351F26a", + "transactionIndex": 2, + "gasUsed": "865817", + "logsBloom": "0x00000000000000000000000000000000400000000000000000800000000000000400000000800008000000000000000000000000000000000000000000008000000000000000000000000000000002000001010000000000000000000000000000000000021000000000000000000800000000800000000000000000000000400000000000000000000000000000000000000000000080000000000000800000000000000000000002002000000400000000000000800000000000000000000000000020000000000000000001040000000000000400000000000000000020000000000200000000000000000000000000010800000000000000000000800001", + "blockHash": "0x3998e4031ed97101f7172284cfcd40c39c54690302b791704921299d71367e7f", + "transactionHash": "0x3c03493f8c9b7245174379cc256cb00018bdc24ff7881aaecccc5d668a43d5dd", + "logs": [ + { + "transactionIndex": 2, + "blockNumber": 33734416, + "transactionHash": "0x3c03493f8c9b7245174379cc256cb00018bdc24ff7881aaecccc5d668a43d5dd", + "address": "0x78d32FC46e5025c29e3BA03Fcf2840323351F26a", + "topics": [ + "0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b", + "0x000000000000000000000000fae44cf6309598c2557bb265bf0401d594db97da" + ], + "data": "0x", + "logIndex": 0, + "blockHash": "0x3998e4031ed97101f7172284cfcd40c39c54690302b791704921299d71367e7f" + }, + { + "transactionIndex": 2, + "blockNumber": 33734416, + "transactionHash": "0x3c03493f8c9b7245174379cc256cb00018bdc24ff7881aaecccc5d668a43d5dd", + "address": "0x78d32FC46e5025c29e3BA03Fcf2840323351F26a", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000cd2a514f04241b7c9a0d5d54441e92e4611929cf" + ], + "data": "0x", + "logIndex": 1, + "blockHash": "0x3998e4031ed97101f7172284cfcd40c39c54690302b791704921299d71367e7f" + }, + { + "transactionIndex": 2, + "blockNumber": 33734416, + "transactionHash": "0x3c03493f8c9b7245174379cc256cb00018bdc24ff7881aaecccc5d668a43d5dd", + "address": "0x78d32FC46e5025c29e3BA03Fcf2840323351F26a", + "topics": ["0x66fd58e82f7b31a2a5c30e0888f3093efe4e111b00cd2b0c31fe014601293aa0"], + "data": "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000045f8a08f534f34a97187626e05d4b6648eeaa9aa", + "logIndex": 2, + "blockHash": "0x3998e4031ed97101f7172284cfcd40c39c54690302b791704921299d71367e7f" + }, + { + "transactionIndex": 2, + "blockNumber": 33734416, + "transactionHash": "0x3c03493f8c9b7245174379cc256cb00018bdc24ff7881aaecccc5d668a43d5dd", + "address": "0x78d32FC46e5025c29e3BA03Fcf2840323351F26a", + "topics": ["0xc2d09fef144f7c8a86f71ea459f8fc17f675768eb1ae369cbd77fb31d467aafa"], + "data": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000064", + "logIndex": 3, + "blockHash": "0x3998e4031ed97101f7172284cfcd40c39c54690302b791704921299d71367e7f" + }, + { + "transactionIndex": 2, + "blockNumber": 33734416, + "transactionHash": "0x3c03493f8c9b7245174379cc256cb00018bdc24ff7881aaecccc5d668a43d5dd", + "address": "0x78d32FC46e5025c29e3BA03Fcf2840323351F26a", + "topics": ["0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498"], + "data": "0x0000000000000000000000000000000000000000000000000000000000000001", + "logIndex": 4, + "blockHash": "0x3998e4031ed97101f7172284cfcd40c39c54690302b791704921299d71367e7f" + }, + { + "transactionIndex": 2, + "blockNumber": 33734416, + "transactionHash": "0x3c03493f8c9b7245174379cc256cb00018bdc24ff7881aaecccc5d668a43d5dd", + "address": "0x78d32FC46e5025c29e3BA03Fcf2840323351F26a", + "topics": ["0x7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f"], + "data": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000007877ffd62649b6a1557b55d4c20fcbab17344c91", + "logIndex": 5, + "blockHash": "0x3998e4031ed97101f7172284cfcd40c39c54690302b791704921299d71367e7f" + } + ], + "blockNumber": 33734416, + "cumulativeGasUsed": "942484", + "status": 1, + "byzantium": true + }, + "args": [ + "0xfAE44cf6309598c2557Bb265BF0401D594db97DA", + "0x7877fFd62649b6A1557B55D4c20fcBaB17344C91", + "0xbe20309400000000000000000000000010b57706ad2345e590c2ea4dc02faef0d9f5b08b000000000000000000000000d1bc731d188acc3f52a6226b328a89056b0ec71a000000000000000000000000000000000000000000000000000000000000006400000000000000000000000045f8a08f534f34a97187626e05d4b6648eeaa9aa" + ], + "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": [ + "0x10b57706AD2345e590c2eA4DC02faef0d9f5b08B", + "0xD1Bc731d188ACc3f52a6226B328a89056B0Ec71a", + 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/RewardsDistributor_StableCoins_2_Proxy.json b/deployments/bsctestnet/RewardsDistributor_StableCoins_2_Proxy.json new file mode 100644 index 000000000..b2cca2e70 --- /dev/null +++ b/deployments/bsctestnet/RewardsDistributor_StableCoins_2_Proxy.json @@ -0,0 +1,277 @@ +{ + "address": "0x78d32FC46e5025c29e3BA03Fcf2840323351F26a", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_logic", + "type": "address" + }, + { + "internalType": "address", + "name": "admin_", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "stateMutability": "payable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "previousAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beacon", + "type": "address" + } + ], + "name": "BeaconUpgraded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "admin_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "changeAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "implementation_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "upgradeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "upgradeToAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + } + ], + "transactionHash": "0x3c03493f8c9b7245174379cc256cb00018bdc24ff7881aaecccc5d668a43d5dd", + "receipt": { + "to": null, + "from": "0xcd2a514f04241b7c9A0d5d54441e92E4611929CF", + "contractAddress": "0x78d32FC46e5025c29e3BA03Fcf2840323351F26a", + "transactionIndex": 2, + "gasUsed": "865817", + "logsBloom": "0x00000000000000000000000000000000400000000000000000800000000000000400000000800008000000000000000000000000000000000000000000008000000000000000000000000000000002000001010000000000000000000000000000000000021000000000000000000800000000800000000000000000000000400000000000000000000000000000000000000000000080000000000000800000000000000000000002002000000400000000000000800000000000000000000000000020000000000000000001040000000000000400000000000000000020000000000200000000000000000000000000010800000000000000000000800001", + "blockHash": "0x3998e4031ed97101f7172284cfcd40c39c54690302b791704921299d71367e7f", + "transactionHash": "0x3c03493f8c9b7245174379cc256cb00018bdc24ff7881aaecccc5d668a43d5dd", + "logs": [ + { + "transactionIndex": 2, + "blockNumber": 33734416, + "transactionHash": "0x3c03493f8c9b7245174379cc256cb00018bdc24ff7881aaecccc5d668a43d5dd", + "address": "0x78d32FC46e5025c29e3BA03Fcf2840323351F26a", + "topics": [ + "0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b", + "0x000000000000000000000000fae44cf6309598c2557bb265bf0401d594db97da" + ], + "data": "0x", + "logIndex": 0, + "blockHash": "0x3998e4031ed97101f7172284cfcd40c39c54690302b791704921299d71367e7f" + }, + { + "transactionIndex": 2, + "blockNumber": 33734416, + "transactionHash": "0x3c03493f8c9b7245174379cc256cb00018bdc24ff7881aaecccc5d668a43d5dd", + "address": "0x78d32FC46e5025c29e3BA03Fcf2840323351F26a", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000cd2a514f04241b7c9a0d5d54441e92e4611929cf" + ], + "data": "0x", + "logIndex": 1, + "blockHash": "0x3998e4031ed97101f7172284cfcd40c39c54690302b791704921299d71367e7f" + }, + { + "transactionIndex": 2, + "blockNumber": 33734416, + "transactionHash": "0x3c03493f8c9b7245174379cc256cb00018bdc24ff7881aaecccc5d668a43d5dd", + "address": "0x78d32FC46e5025c29e3BA03Fcf2840323351F26a", + "topics": ["0x66fd58e82f7b31a2a5c30e0888f3093efe4e111b00cd2b0c31fe014601293aa0"], + "data": "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000045f8a08f534f34a97187626e05d4b6648eeaa9aa", + "logIndex": 2, + "blockHash": "0x3998e4031ed97101f7172284cfcd40c39c54690302b791704921299d71367e7f" + }, + { + "transactionIndex": 2, + "blockNumber": 33734416, + "transactionHash": "0x3c03493f8c9b7245174379cc256cb00018bdc24ff7881aaecccc5d668a43d5dd", + "address": "0x78d32FC46e5025c29e3BA03Fcf2840323351F26a", + "topics": ["0xc2d09fef144f7c8a86f71ea459f8fc17f675768eb1ae369cbd77fb31d467aafa"], + "data": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000064", + "logIndex": 3, + "blockHash": "0x3998e4031ed97101f7172284cfcd40c39c54690302b791704921299d71367e7f" + }, + { + "transactionIndex": 2, + "blockNumber": 33734416, + "transactionHash": "0x3c03493f8c9b7245174379cc256cb00018bdc24ff7881aaecccc5d668a43d5dd", + "address": "0x78d32FC46e5025c29e3BA03Fcf2840323351F26a", + "topics": ["0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498"], + "data": "0x0000000000000000000000000000000000000000000000000000000000000001", + "logIndex": 4, + "blockHash": "0x3998e4031ed97101f7172284cfcd40c39c54690302b791704921299d71367e7f" + }, + { + "transactionIndex": 2, + "blockNumber": 33734416, + "transactionHash": "0x3c03493f8c9b7245174379cc256cb00018bdc24ff7881aaecccc5d668a43d5dd", + "address": "0x78d32FC46e5025c29e3BA03Fcf2840323351F26a", + "topics": ["0x7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f"], + "data": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000007877ffd62649b6a1557b55d4c20fcbab17344c91", + "logIndex": 5, + "blockHash": "0x3998e4031ed97101f7172284cfcd40c39c54690302b791704921299d71367e7f" + } + ], + "blockNumber": 33734416, + "cumulativeGasUsed": "942484", + "status": 1, + "byzantium": true + }, + "args": [ + "0xfAE44cf6309598c2557Bb265BF0401D594db97DA", + "0x7877fFd62649b6A1557B55D4c20fcBaB17344C91", + "0xbe20309400000000000000000000000010b57706ad2345e590c2ea4dc02faef0d9f5b08b000000000000000000000000d1bc731d188acc3f52a6226b328a89056b0ec71a000000000000000000000000000000000000000000000000000000000000006400000000000000000000000045f8a08f534f34a97187626e05d4b6648eeaa9aa" + ], + "numDeployments": 1, + "solcInputHash": "0e89febeebc7444140de8e67c9067d2c", + "metadata": "{\"compiler\":{\"version\":\"0.8.10+commit.fc410830\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_logic\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"admin_\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"stateMutability\":\"payable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"previousAdmin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\"}],\"name\":\"AdminChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"beacon\",\"type\":\"address\"}],\"name\":\"BeaconUpgraded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"implementation\",\"type\":\"address\"}],\"name\":\"Upgraded\",\"type\":\"event\"},{\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"inputs\":[],\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"admin_\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\"}],\"name\":\"changeAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"implementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"implementation_\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newImplementation\",\"type\":\"address\"}],\"name\":\"upgradeTo\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newImplementation\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"upgradeToAndCall\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}],\"devdoc\":{\"details\":\"This contract implements a proxy that is upgradeable by an admin. To avoid https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector clashing], which can potentially be used in an attack, this contract uses the https://blog.openzeppelin.com/the-transparent-proxy-pattern/[transparent proxy pattern]. This pattern implies two things that go hand in hand: 1. If any account other than the admin calls the proxy, the call will be forwarded to the implementation, even if that call matches one of the admin functions exposed by the proxy itself. 2. If the admin calls the proxy, it can access the admin functions, but its calls will never be forwarded to the implementation. If the admin tries to call a function on the implementation it will fail with an error that says \\\"admin cannot fallback to proxy target\\\". These properties mean that the admin account can only be used for admin actions like upgrading the proxy or changing the admin, so it's best if it's a dedicated account that is not used for anything else. This will avoid headaches due to sudden errors when trying to call a function from the proxy implementation. Our recommendation is for the dedicated account to be an instance of the {ProxyAdmin} contract. If set up this way, you should think of the `ProxyAdmin` instance as the real administrative interface of your proxy.\",\"kind\":\"dev\",\"methods\":{\"admin()\":{\"details\":\"Returns the current admin. NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyAdmin}. TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call. `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`\"},\"changeAdmin(address)\":{\"details\":\"Changes the admin of the proxy. Emits an {AdminChanged} event. NOTE: Only the admin can call this function. See {ProxyAdmin-changeProxyAdmin}.\"},\"constructor\":{\"details\":\"Initializes an upgradeable proxy managed by `_admin`, backed by the implementation at `_logic`, and optionally initialized with `_data` as explained in {ERC1967Proxy-constructor}.\"},\"implementation()\":{\"details\":\"Returns the current implementation. NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyImplementation}. TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call. `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc`\"},\"upgradeTo(address)\":{\"details\":\"Upgrade the implementation of the proxy. NOTE: Only the admin can call this function. See {ProxyAdmin-upgrade}.\"},\"upgradeToAndCall(address,bytes)\":{\"details\":\"Upgrade the implementation of the proxy, and then call a function from the new implementation as specified by `data`, which should be an encoded function call. This is useful to initialize new storage variables in the proxied contract. NOTE: Only the admin can call this function. See {ProxyAdmin-upgradeAndCall}.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"solc_0.8/openzeppelin/proxy/transparent/TransparentUpgradeableProxy.sol\":\"TransparentUpgradeableProxy\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":999999},\"remappings\":[]},\"sources\":{\"solc_0.8/openzeppelin/interfaces/draft-IERC1822.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (interfaces/draft-IERC1822.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified\\n * proxy whose upgrades are fully controlled by the current implementation.\\n */\\ninterface IERC1822Proxiable {\\n /**\\n * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation\\n * address.\\n *\\n * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks\\n * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this\\n * function revert if invoked through a proxy.\\n */\\n function proxiableUUID() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0x93b4e21c931252739a1ec13ea31d3d35a5c068be3163ccab83e4d70c40355f03\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/proxy/ERC1967/ERC1967Proxy.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (proxy/ERC1967/ERC1967Proxy.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../Proxy.sol\\\";\\nimport \\\"./ERC1967Upgrade.sol\\\";\\n\\n/**\\n * @dev This contract implements an upgradeable proxy. It is upgradeable because calls are delegated to an\\n * implementation address that can be changed. This address is stored in storage in the location specified by\\n * https://eips.ethereum.org/EIPS/eip-1967[EIP1967], so that it doesn't conflict with the storage layout of the\\n * implementation behind the proxy.\\n */\\ncontract ERC1967Proxy is Proxy, ERC1967Upgrade {\\n /**\\n * @dev Initializes the upgradeable proxy with an initial implementation specified by `_logic`.\\n *\\n * If `_data` is nonempty, it's used as data in a delegate call to `_logic`. This will typically be an encoded\\n * function call, and allows initializating the storage of the proxy like a Solidity constructor.\\n */\\n constructor(address _logic, bytes memory _data) payable {\\n assert(_IMPLEMENTATION_SLOT == bytes32(uint256(keccak256(\\\"eip1967.proxy.implementation\\\")) - 1));\\n _upgradeToAndCall(_logic, _data, false);\\n }\\n\\n /**\\n * @dev Returns the current implementation address.\\n */\\n function _implementation() internal view virtual override returns (address impl) {\\n return ERC1967Upgrade._getImplementation();\\n }\\n}\\n\",\"keccak256\":\"0x6309f9f39dc6f4f45a24f296543867aa358e32946cd6b2874627a996d606b3a0\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/proxy/ERC1967/ERC1967Upgrade.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (proxy/ERC1967/ERC1967Upgrade.sol)\\n\\npragma solidity ^0.8.2;\\n\\nimport \\\"../beacon/IBeacon.sol\\\";\\nimport \\\"../../interfaces/draft-IERC1822.sol\\\";\\nimport \\\"../../utils/Address.sol\\\";\\nimport \\\"../../utils/StorageSlot.sol\\\";\\n\\n/**\\n * @dev This abstract contract provides getters and event emitting update functions for\\n * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots.\\n *\\n * _Available since v4.1._\\n *\\n * @custom:oz-upgrades-unsafe-allow delegatecall\\n */\\nabstract contract ERC1967Upgrade {\\n // This is the keccak-256 hash of \\\"eip1967.proxy.rollback\\\" subtracted by 1\\n bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143;\\n\\n /**\\n * @dev Storage slot with the address of the current implementation.\\n * This is the keccak-256 hash of \\\"eip1967.proxy.implementation\\\" subtracted by 1, and is\\n * validated in the constructor.\\n */\\n bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\\n\\n /**\\n * @dev Emitted when the implementation is upgraded.\\n */\\n event Upgraded(address indexed implementation);\\n\\n /**\\n * @dev Returns the current implementation address.\\n */\\n function _getImplementation() internal view returns (address) {\\n return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\\n }\\n\\n /**\\n * @dev Stores a new address in the EIP1967 implementation slot.\\n */\\n function _setImplementation(address newImplementation) private {\\n require(Address.isContract(newImplementation), \\\"ERC1967: new implementation is not a contract\\\");\\n StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\\n }\\n\\n /**\\n * @dev Perform implementation upgrade\\n *\\n * Emits an {Upgraded} event.\\n */\\n function _upgradeTo(address newImplementation) internal {\\n _setImplementation(newImplementation);\\n emit Upgraded(newImplementation);\\n }\\n\\n /**\\n * @dev Perform implementation upgrade with additional setup call.\\n *\\n * Emits an {Upgraded} event.\\n */\\n function _upgradeToAndCall(\\n address newImplementation,\\n bytes memory data,\\n bool forceCall\\n ) internal {\\n _upgradeTo(newImplementation);\\n if (data.length > 0 || forceCall) {\\n Address.functionDelegateCall(newImplementation, data);\\n }\\n }\\n\\n /**\\n * @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call.\\n *\\n * Emits an {Upgraded} event.\\n */\\n function _upgradeToAndCallUUPS(\\n address newImplementation,\\n bytes memory data,\\n bool forceCall\\n ) internal {\\n // Upgrades from old implementations will perform a rollback test. This test requires the new\\n // implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing\\n // this special case will break upgrade paths from old UUPS implementation to new ones.\\n if (StorageSlot.getBooleanSlot(_ROLLBACK_SLOT).value) {\\n _setImplementation(newImplementation);\\n } else {\\n try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) {\\n require(slot == _IMPLEMENTATION_SLOT, \\\"ERC1967Upgrade: unsupported proxiableUUID\\\");\\n } catch {\\n revert(\\\"ERC1967Upgrade: new implementation is not UUPS\\\");\\n }\\n _upgradeToAndCall(newImplementation, data, forceCall);\\n }\\n }\\n\\n /**\\n * @dev Storage slot with the admin of the contract.\\n * This is the keccak-256 hash of \\\"eip1967.proxy.admin\\\" subtracted by 1, and is\\n * validated in the constructor.\\n */\\n bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;\\n\\n /**\\n * @dev Emitted when the admin account has changed.\\n */\\n event AdminChanged(address previousAdmin, address newAdmin);\\n\\n /**\\n * @dev Returns the current admin.\\n */\\n function _getAdmin() internal view virtual returns (address) {\\n return StorageSlot.getAddressSlot(_ADMIN_SLOT).value;\\n }\\n\\n /**\\n * @dev Stores a new address in the EIP1967 admin slot.\\n */\\n function _setAdmin(address newAdmin) private {\\n require(newAdmin != address(0), \\\"ERC1967: new admin is the zero address\\\");\\n StorageSlot.getAddressSlot(_ADMIN_SLOT).value = newAdmin;\\n }\\n\\n /**\\n * @dev Changes the admin of the proxy.\\n *\\n * Emits an {AdminChanged} event.\\n */\\n function _changeAdmin(address newAdmin) internal {\\n emit AdminChanged(_getAdmin(), newAdmin);\\n _setAdmin(newAdmin);\\n }\\n\\n /**\\n * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.\\n * This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor.\\n */\\n bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;\\n\\n /**\\n * @dev Emitted when the beacon is upgraded.\\n */\\n event BeaconUpgraded(address indexed beacon);\\n\\n /**\\n * @dev Returns the current beacon.\\n */\\n function _getBeacon() internal view returns (address) {\\n return StorageSlot.getAddressSlot(_BEACON_SLOT).value;\\n }\\n\\n /**\\n * @dev Stores a new beacon in the EIP1967 beacon slot.\\n */\\n function _setBeacon(address newBeacon) private {\\n require(Address.isContract(newBeacon), \\\"ERC1967: new beacon is not a contract\\\");\\n require(Address.isContract(IBeacon(newBeacon).implementation()), \\\"ERC1967: beacon implementation is not a contract\\\");\\n StorageSlot.getAddressSlot(_BEACON_SLOT).value = newBeacon;\\n }\\n\\n /**\\n * @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does\\n * not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that).\\n *\\n * Emits a {BeaconUpgraded} event.\\n */\\n function _upgradeBeaconToAndCall(\\n address newBeacon,\\n bytes memory data,\\n bool forceCall\\n ) internal {\\n _setBeacon(newBeacon);\\n emit BeaconUpgraded(newBeacon);\\n if (data.length > 0 || forceCall) {\\n Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x17668652127feebed0ce8d9431ef95ccc8c4292f03e3b8cf06c6ca16af396633\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/proxy/Proxy.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (proxy/Proxy.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM\\n * instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to\\n * be specified by overriding the virtual {_implementation} function.\\n *\\n * Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a\\n * different contract through the {_delegate} function.\\n *\\n * The success and return data of the delegated call will be returned back to the caller of the proxy.\\n */\\nabstract contract Proxy {\\n /**\\n * @dev Delegates the current call to `implementation`.\\n *\\n * This function does not return to its internal call site, it will return directly to the external caller.\\n */\\n function _delegate(address implementation) internal virtual {\\n assembly {\\n // Copy msg.data. We take full control of memory in this inline assembly\\n // block because it will not return to Solidity code. We overwrite the\\n // Solidity scratch pad at memory position 0.\\n calldatacopy(0, 0, calldatasize())\\n\\n // Call the implementation.\\n // out and outsize are 0 because we don't know the size yet.\\n let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)\\n\\n // Copy the returned data.\\n returndatacopy(0, 0, returndatasize())\\n\\n switch result\\n // delegatecall returns 0 on error.\\n case 0 {\\n revert(0, returndatasize())\\n }\\n default {\\n return(0, returndatasize())\\n }\\n }\\n }\\n\\n /**\\n * @dev This is a virtual function that should be overriden so it returns the address to which the fallback function\\n * and {_fallback} should delegate.\\n */\\n function _implementation() internal view virtual returns (address);\\n\\n /**\\n * @dev Delegates the current call to the address returned by `_implementation()`.\\n *\\n * This function does not return to its internall call site, it will return directly to the external caller.\\n */\\n function _fallback() internal virtual {\\n _beforeFallback();\\n _delegate(_implementation());\\n }\\n\\n /**\\n * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other\\n * function in the contract matches the call data.\\n */\\n fallback() external payable virtual {\\n _fallback();\\n }\\n\\n /**\\n * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if call data\\n * is empty.\\n */\\n receive() external payable virtual {\\n _fallback();\\n }\\n\\n /**\\n * @dev Hook that is called before falling back to the implementation. Can happen as part of a manual `_fallback`\\n * call, or as part of the Solidity `fallback` or `receive` functions.\\n *\\n * If overriden should call `super._beforeFallback()`.\\n */\\n function _beforeFallback() internal virtual {}\\n}\\n\",\"keccak256\":\"0xd5d1fd16e9faff7fcb3a52e02a8d49156f42a38a03f07b5f1810c21c2149a8ab\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/proxy/beacon/IBeacon.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev This is the interface that {BeaconProxy} expects of its beacon.\\n */\\ninterface IBeacon {\\n /**\\n * @dev Must return an address that can be used as a delegate call target.\\n *\\n * {BeaconProxy} will check that this address is a contract.\\n */\\n function implementation() external view returns (address);\\n}\\n\",\"keccak256\":\"0xd50a3421ac379ccb1be435fa646d66a65c986b4924f0849839f08692f39dde61\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/proxy/transparent/TransparentUpgradeableProxy.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (proxy/transparent/TransparentUpgradeableProxy.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../ERC1967/ERC1967Proxy.sol\\\";\\n\\n/**\\n * @dev This contract implements a proxy that is upgradeable by an admin.\\n *\\n * To avoid https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector\\n * clashing], which can potentially be used in an attack, this contract uses the\\n * https://blog.openzeppelin.com/the-transparent-proxy-pattern/[transparent proxy pattern]. This pattern implies two\\n * things that go hand in hand:\\n *\\n * 1. If any account other than the admin calls the proxy, the call will be forwarded to the implementation, even if\\n * that call matches one of the admin functions exposed by the proxy itself.\\n * 2. If the admin calls the proxy, it can access the admin functions, but its calls will never be forwarded to the\\n * implementation. If the admin tries to call a function on the implementation it will fail with an error that says\\n * \\\"admin cannot fallback to proxy target\\\".\\n *\\n * These properties mean that the admin account can only be used for admin actions like upgrading the proxy or changing\\n * the admin, so it's best if it's a dedicated account that is not used for anything else. This will avoid headaches due\\n * to sudden errors when trying to call a function from the proxy implementation.\\n *\\n * Our recommendation is for the dedicated account to be an instance of the {ProxyAdmin} contract. If set up this way,\\n * you should think of the `ProxyAdmin` instance as the real administrative interface of your proxy.\\n */\\ncontract TransparentUpgradeableProxy is ERC1967Proxy {\\n /**\\n * @dev Initializes an upgradeable proxy managed by `_admin`, backed by the implementation at `_logic`, and\\n * optionally initialized with `_data` as explained in {ERC1967Proxy-constructor}.\\n */\\n constructor(\\n address _logic,\\n address admin_,\\n bytes memory _data\\n ) payable ERC1967Proxy(_logic, _data) {\\n assert(_ADMIN_SLOT == bytes32(uint256(keccak256(\\\"eip1967.proxy.admin\\\")) - 1));\\n _changeAdmin(admin_);\\n }\\n\\n /**\\n * @dev Modifier used internally that will delegate the call to the implementation unless the sender is the admin.\\n */\\n modifier ifAdmin() {\\n if (msg.sender == _getAdmin()) {\\n _;\\n } else {\\n _fallback();\\n }\\n }\\n\\n /**\\n * @dev Returns the current admin.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyAdmin}.\\n *\\n * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the\\n * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.\\n * `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`\\n */\\n function admin() external ifAdmin returns (address admin_) {\\n admin_ = _getAdmin();\\n }\\n\\n /**\\n * @dev Returns the current implementation.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyImplementation}.\\n *\\n * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the\\n * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.\\n * `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc`\\n */\\n function implementation() external ifAdmin returns (address implementation_) {\\n implementation_ = _implementation();\\n }\\n\\n /**\\n * @dev Changes the admin of the proxy.\\n *\\n * Emits an {AdminChanged} event.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-changeProxyAdmin}.\\n */\\n function changeAdmin(address newAdmin) external virtual ifAdmin {\\n _changeAdmin(newAdmin);\\n }\\n\\n /**\\n * @dev Upgrade the implementation of the proxy.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-upgrade}.\\n */\\n function upgradeTo(address newImplementation) external ifAdmin {\\n _upgradeToAndCall(newImplementation, bytes(\\\"\\\"), false);\\n }\\n\\n /**\\n * @dev Upgrade the implementation of the proxy, and then call a function from the new implementation as specified\\n * by `data`, which should be an encoded function call. This is useful to initialize new storage variables in the\\n * proxied contract.\\n *\\n * NOTE: Only the admin can call this function. See {ProxyAdmin-upgradeAndCall}.\\n */\\n function upgradeToAndCall(address newImplementation, bytes calldata data) external payable ifAdmin {\\n _upgradeToAndCall(newImplementation, data, true);\\n }\\n\\n /**\\n * @dev Returns the current admin.\\n */\\n function _admin() internal view virtual returns (address) {\\n return _getAdmin();\\n }\\n\\n /**\\n * @dev Makes sure the admin cannot access the fallback function. See {Proxy-_beforeFallback}.\\n */\\n function _beforeFallback() internal virtual override {\\n require(msg.sender != _getAdmin(), \\\"TransparentUpgradeableProxy: admin cannot fallback to proxy target\\\");\\n super._beforeFallback();\\n }\\n}\\n\",\"keccak256\":\"0x140055a64cf579d622e04f5a198595832bf2cb193cd0005f4f2d4d61ca906253\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x3777e696b62134e6177440dbe6e6601c0c156a443f57167194b67e75527439de\",\"license\":\"MIT\"},\"solc_0.8/openzeppelin/utils/StorageSlot.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/StorageSlot.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Library for reading and writing primitive types to specific storage slots.\\n *\\n * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.\\n * This library helps with reading and writing to such slots without the need for inline assembly.\\n *\\n * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.\\n *\\n * Example usage to set ERC1967 implementation slot:\\n * ```\\n * contract ERC1967 {\\n * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\\n *\\n * function _getImplementation() internal view returns (address) {\\n * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\\n * }\\n *\\n * function _setImplementation(address newImplementation) internal {\\n * require(Address.isContract(newImplementation), \\\"ERC1967: new implementation is not a contract\\\");\\n * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\\n * }\\n * }\\n * ```\\n *\\n * _Available since v4.1 for `address`, `bool`, `bytes32`, and `uint256`._\\n */\\nlibrary StorageSlot {\\n struct AddressSlot {\\n address value;\\n }\\n\\n struct BooleanSlot {\\n bool value;\\n }\\n\\n struct Bytes32Slot {\\n bytes32 value;\\n }\\n\\n struct Uint256Slot {\\n uint256 value;\\n }\\n\\n /**\\n * @dev Returns an `AddressSlot` with member `value` located at `slot`.\\n */\\n function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {\\n assembly {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `BooleanSlot` with member `value` located at `slot`.\\n */\\n function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {\\n assembly {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `Bytes32Slot` with member `value` located at `slot`.\\n */\\n function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {\\n assembly {\\n r.slot := slot\\n }\\n }\\n\\n /**\\n * @dev Returns an `Uint256Slot` with member `value` located at `slot`.\\n */\\n function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {\\n assembly {\\n r.slot := slot\\n }\\n }\\n}\\n\",\"keccak256\":\"0xfe1b7a9aa2a530a9e705b220e26cd584e2fbdc9602a3a1066032b12816b46aca\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x6080604052604051620011b2380380620011b2833981016040819052620000269162000519565b82816200005560017f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbd620005f9565b6000805160206200116b833981519152146200007557620000756200061f565b6200008382826000620000e7565b50620000b3905060017fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6104620005f9565b6000805160206200114b83398151915214620000d357620000d36200061f565b620000de8262000124565b50505062000688565b620000f2836200017f565b600082511180620001005750805b156200011f576200011d8383620001c160201b620002ff1760201c565b505b505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6200014f620001f0565b604080516001600160a01b03928316815291841660208301520160405180910390a16200017c8162000229565b50565b6200018a81620002de565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b6060620001e983836040518060600160405280602781526020016200118b6027913962000381565b9392505050565b60006200021a6000805160206200114b83398151915260001b6200046760201b620002731760201c565b546001600160a01b0316919050565b6001600160a01b038116620002945760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b60648201526084015b60405180910390fd5b80620002bd6000805160206200114b83398151915260001b6200046760201b620002731760201c565b80546001600160a01b0319166001600160a01b039290921691909117905550565b620002f4816200046a60201b6200032b1760201c565b620003585760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b60648201526084016200028b565b80620002bd6000805160206200116b83398151915260001b6200046760201b620002731760201c565b60606001600160a01b0384163b620003eb5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f6044820152651b9d1c9858dd60d21b60648201526084016200028b565b600080856001600160a01b03168560405162000408919062000635565b600060405180830381855af49150503d806000811462000445576040519150601f19603f3d011682016040523d82523d6000602084013e6200044a565b606091505b5090925090506200045d82828662000479565b9695505050505050565b90565b6001600160a01b03163b151590565b606083156200048a575081620001e9565b8251156200049b5782518084602001fd5b8160405162461bcd60e51b81526004016200028b919062000653565b80516001600160a01b0381168114620004cf57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60005b8381101562000507578181015183820152602001620004ed565b838111156200011d5750506000910152565b6000806000606084860312156200052f57600080fd5b6200053a84620004b7565b92506200054a60208501620004b7565b60408501519092506001600160401b03808211156200056857600080fd5b818601915086601f8301126200057d57600080fd5b815181811115620005925762000592620004d4565b604051601f8201601f19908116603f01168101908382118183101715620005bd57620005bd620004d4565b81604052828152896020848701011115620005d757600080fd5b620005ea836020830160208801620004ea565b80955050505050509250925092565b6000828210156200061a57634e487b7160e01b600052601160045260246000fd5b500390565b634e487b7160e01b600052600160045260246000fd5b6000825162000649818460208701620004ea565b9190910192915050565b602081526000825180602084015262000674816040850160208701620004ea565b601f01601f19169190910160400192915050565b610ab380620006986000396000f3fe60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100a85780638f283970146100e6578063f851a440146101065761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61011b565b005b61006b61011b565b34801561008157600080fd5b5061006b61009036600461091f565b610135565b61006b6100a336600461093a565b610196565b3480156100b457600080fd5b506100bd610221565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b3480156100f257600080fd5b5061006b61010136600461091f565b610276565b34801561011257600080fd5b506100bd6102ba565b610123610347565b61013361012e610435565b61043f565b565b61013d610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561018e5761018b816040518060200160405280600081525060006104a3565b50565b61018b61011b565b61019e610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415610219576102148383838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250600192506104a3915050565b505050565b61021461011b565b600061022b610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561026b57610266610435565b905090565b61027361011b565b90565b61027e610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561018e5761018b816104ce565b60006102c4610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561026b57610266610463565b60606103248383604051806060016040528060278152602001610a576027913961052f565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b61034f610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415610133576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f7879207461726760648201527f6574000000000000000000000000000000000000000000000000000000000000608482015260a4015b60405180910390fd5b6000610266610657565b3660008037600080366000845af43d6000803e80801561045e573d6000f35b3d6000fd5b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b5473ffffffffffffffffffffffffffffffffffffffff16919050565b6104ac8361067f565b6000825111806104b95750805b15610214576104c883836102ff565b50505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6104f7610463565b6040805173ffffffffffffffffffffffffffffffffffffffff928316815291841660208301520160405180910390a161018b816106cc565b606073ffffffffffffffffffffffffffffffffffffffff84163b6105d5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f60448201527f6e74726163740000000000000000000000000000000000000000000000000000606482015260840161042c565b6000808573ffffffffffffffffffffffffffffffffffffffff16856040516105fd91906109e9565b600060405180830381855af49150503d8060008114610638576040519150601f19603f3d011682016040523d82523d6000602084013e61063d565b606091505b509150915061064d8282866107d8565b9695505050505050565b60007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc610487565b6106888161082b565b60405173ffffffffffffffffffffffffffffffffffffffff8216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b73ffffffffffffffffffffffffffffffffffffffff811661076f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201527f6464726573730000000000000000000000000000000000000000000000000000606482015260840161042c565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9290921691909117905550565b606083156107e7575081610324565b8251156107f75782518084602001fd5b816040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161042c9190610a05565b73ffffffffffffffffffffffffffffffffffffffff81163b6108cf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201527f6f74206120636f6e747261637400000000000000000000000000000000000000606482015260840161042c565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc610792565b803573ffffffffffffffffffffffffffffffffffffffff8116811461091a57600080fd5b919050565b60006020828403121561093157600080fd5b610324826108f6565b60008060006040848603121561094f57600080fd5b610958846108f6565b9250602084013567ffffffffffffffff8082111561097557600080fd5b818601915086601f83011261098957600080fd5b81358181111561099857600080fd5b8760208285010111156109aa57600080fd5b6020830194508093505050509250925092565b60005b838110156109d85781810151838201526020016109c0565b838111156104c85750506000910152565b600082516109fb8184602087016109bd565b9190910192915050565b6020815260008251806020840152610a248160408501602087016109bd565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220b29caa54336b3ee836679675e9732ec5e526fb3f803cca2fe336cc3555aba62264736f6c634300080a0033b53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564", + "deployedBytecode": "0x60806040526004361061005e5760003560e01c80635c60da1b116100435780635c60da1b146100a85780638f283970146100e6578063f851a440146101065761006d565b80633659cfe6146100755780634f1ef286146100955761006d565b3661006d5761006b61011b565b005b61006b61011b565b34801561008157600080fd5b5061006b61009036600461091f565b610135565b61006b6100a336600461093a565b610196565b3480156100b457600080fd5b506100bd610221565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b3480156100f257600080fd5b5061006b61010136600461091f565b610276565b34801561011257600080fd5b506100bd6102ba565b610123610347565b61013361012e610435565b61043f565b565b61013d610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561018e5761018b816040518060200160405280600081525060006104a3565b50565b61018b61011b565b61019e610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415610219576102148383838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250600192506104a3915050565b505050565b61021461011b565b600061022b610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561026b57610266610435565b905090565b61027361011b565b90565b61027e610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561018e5761018b816104ce565b60006102c4610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141561026b57610266610463565b60606103248383604051806060016040528060278152602001610a576027913961052f565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff163b151590565b61034f610463565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415610133576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f7879207461726760648201527f6574000000000000000000000000000000000000000000000000000000000000608482015260a4015b60405180910390fd5b6000610266610657565b3660008037600080366000845af43d6000803e80801561045e573d6000f35b3d6000fd5b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b5473ffffffffffffffffffffffffffffffffffffffff16919050565b6104ac8361067f565b6000825111806104b95750805b15610214576104c883836102ff565b50505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6104f7610463565b6040805173ffffffffffffffffffffffffffffffffffffffff928316815291841660208301520160405180910390a161018b816106cc565b606073ffffffffffffffffffffffffffffffffffffffff84163b6105d5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f60448201527f6e74726163740000000000000000000000000000000000000000000000000000606482015260840161042c565b6000808573ffffffffffffffffffffffffffffffffffffffff16856040516105fd91906109e9565b600060405180830381855af49150503d8060008114610638576040519150601f19603f3d011682016040523d82523d6000602084013e61063d565b606091505b509150915061064d8282866107d8565b9695505050505050565b60007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc610487565b6106888161082b565b60405173ffffffffffffffffffffffffffffffffffffffff8216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b73ffffffffffffffffffffffffffffffffffffffff811661076f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201527f6464726573730000000000000000000000000000000000000000000000000000606482015260840161042c565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9290921691909117905550565b606083156107e7575081610324565b8251156107f75782518084602001fd5b816040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161042c9190610a05565b73ffffffffffffffffffffffffffffffffffffffff81163b6108cf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201527f6f74206120636f6e747261637400000000000000000000000000000000000000606482015260840161042c565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc610792565b803573ffffffffffffffffffffffffffffffffffffffff8116811461091a57600080fd5b919050565b60006020828403121561093157600080fd5b610324826108f6565b60008060006040848603121561094f57600080fd5b610958846108f6565b9250602084013567ffffffffffffffff8082111561097557600080fd5b818601915086601f83011261098957600080fd5b81358181111561099857600080fd5b8760208285010111156109aa57600080fd5b6020830194508093505050509250925092565b60005b838110156109d85781810151838201526020016109c0565b838111156104c85750506000910152565b600082516109fb8184602087016109bd565b9190910192915050565b6020815260008251806020840152610a248160408501602087016109bd565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a2646970667358221220b29caa54336b3ee836679675e9732ec5e526fb3f803cca2fe336cc3555aba62264736f6c634300080a0033", + "devdoc": { + "details": "This contract implements a proxy that is upgradeable by an admin. To avoid https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector clashing], which can potentially be used in an attack, this contract uses the https://blog.openzeppelin.com/the-transparent-proxy-pattern/[transparent proxy pattern]. This pattern implies two things that go hand in hand: 1. If any account other than the admin calls the proxy, the call will be forwarded to the implementation, even if that call matches one of the admin functions exposed by the proxy itself. 2. If the admin calls the proxy, it can access the admin functions, but its calls will never be forwarded to the implementation. If the admin tries to call a function on the implementation it will fail with an error that says \"admin cannot fallback to proxy target\". These properties mean that the admin account can only be used for admin actions like upgrading the proxy or changing the admin, so it's best if it's a dedicated account that is not used for anything else. This will avoid headaches due to sudden errors when trying to call a function from the proxy implementation. Our recommendation is for the dedicated account to be an instance of the {ProxyAdmin} contract. If set up this way, you should think of the `ProxyAdmin` instance as the real administrative interface of your proxy.", + "kind": "dev", + "methods": { + "admin()": { + "details": "Returns the current admin. NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyAdmin}. TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call. `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`" + }, + "changeAdmin(address)": { + "details": "Changes the admin of the proxy. Emits an {AdminChanged} event. NOTE: Only the admin can call this function. See {ProxyAdmin-changeProxyAdmin}." + }, + "constructor": { + "details": "Initializes an upgradeable proxy managed by `_admin`, backed by the implementation at `_logic`, and optionally initialized with `_data` as explained in {ERC1967Proxy-constructor}." + }, + "implementation()": { + "details": "Returns the current implementation. NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyImplementation}. TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call. `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc`" + }, + "upgradeTo(address)": { + "details": "Upgrade the implementation of the proxy. NOTE: Only the admin can call this function. See {ProxyAdmin-upgrade}." + }, + "upgradeToAndCall(address,bytes)": { + "details": "Upgrade the implementation of the proxy, and then call a function from the new implementation as specified by `data`, which should be an encoded function call. This is useful to initialize new storage variables in the proxied contract. NOTE: Only the admin can call this function. See {ProxyAdmin-upgradeAndCall}." + } + }, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [], + "types": null + } +} diff --git a/helpers/deploymentConfig.ts b/helpers/deploymentConfig.ts index a189a3120..65e6ef3b2 100644 --- a/helpers/deploymentConfig.ts +++ b/helpers/deploymentConfig.ts @@ -667,6 +667,13 @@ export const globalConfig: NetworkConfig = { decimals: 18, tokenAddress: "0x63061de4A25f24279AAab80400040684F92Ee319", }, + { + isMock: false, + name: "ANGLE_bsc", + symbol: "ANGLE", + decimals: 18, + tokenAddress: "0xD1Bc731d188ACc3f52a6226B328a89056B0Ec71a", + }, ], poolConfig: [ { @@ -758,6 +765,12 @@ export const globalConfig: NetworkConfig = { supplySpeeds: ["1240079365079365"], // 1000 HAY over 28 days (806400 blocks) borrowSpeeds: ["1240079365079365"], // 1000 HAY over 28 days (806400 blocks) }, + { + asset: "ANGLE", + markets: ["agEUR"], + supplySpeeds: ["0"], + borrowSpeeds: ["87549603174603174"], // 17650 ANGLE over 7 days (201600 blocks) + }, ], }, { @@ -1394,6 +1407,13 @@ export const globalConfig: NetworkConfig = { decimals: 18, tokenAddress: "0x12f31b73d812c6bb0d735a218c086d44d5fe5f89", }, + { + isMock: false, + name: "ANGLE_bsc", + symbol: "ANGLE", + decimals: 18, + tokenAddress: "0x97B6897AAd7aBa3861c04C0e6388Fc02AF1F227f", + }, ], poolConfig: [ { @@ -1485,6 +1505,12 @@ export const globalConfig: NetworkConfig = { supplySpeeds: ["1240079365079365"], // 1000 HAY over 28 days (806400 blocks) borrowSpeeds: ["1240079365079365"], // 1000 HAY over 28 days (806400 blocks) }, + { + asset: "ANGLE", + markets: ["agEUR"], + supplySpeeds: ["0"], + borrowSpeeds: ["87549603174603174"], // 17650 ANGLE over 7 days (201600 blocks) + }, ], }, { From 9463b74bc05dbe884303e6087785c167ac09a8e6 Mon Sep 17 00:00:00 2001 From: GitGuru7 <128375421+GitGuru7@users.noreply.github.com> Date: Thu, 28 Sep 2023 19:43:32 +0530 Subject: [PATCH 12/33] chore: update risk management addresses --- deployments/bscmainnet.json | 2 +- .../bscmainnet/VToken_vagEUR_Stablecoins.json | 146 +++++++++--------- deployments/bsctestnet.json | 2 +- .../bsctestnet/VToken_vagEUR_Stablecoins.json | 126 +++++++-------- helpers/deploymentConfig.ts | 4 + 5 files changed, 142 insertions(+), 138 deletions(-) diff --git a/deployments/bscmainnet.json b/deployments/bscmainnet.json index b307aba94..6b4f19163 100644 --- a/deployments/bscmainnet.json +++ b/deployments/bscmainnet.json @@ -44156,7 +44156,7 @@ ] }, "VToken_vagEUR_Stablecoins": { - "address": "0x1a9D2862028F6f5E6C299A7AC3C285508942b15E", + "address": "0x795DE779Be00Ea46eA97a28BDD38d9ED570BCF0F", "abi": [ { "inputs": [ diff --git a/deployments/bscmainnet/VToken_vagEUR_Stablecoins.json b/deployments/bscmainnet/VToken_vagEUR_Stablecoins.json index 97b93bb71..d440e9ed7 100644 --- a/deployments/bscmainnet/VToken_vagEUR_Stablecoins.json +++ b/deployments/bscmainnet/VToken_vagEUR_Stablecoins.json @@ -1,5 +1,5 @@ { - "address": "0x1a9D2862028F6f5E6C299A7AC3C285508942b15E", + "address": "0x795DE779Be00Ea46eA97a28BDD38d9ED570BCF0F", "abi": [ { "inputs": [ @@ -71,153 +71,153 @@ "type": "receive" } ], - "transactionHash": "0x6feefa919796851a92bad7a4628b1d13966480210b1f203fa97c8daa0b025aa2", + "transactionHash": "0x94c2c6065182423ebaa2818078939f9c92e2bffef62ac180dd283bf2c9e97c74", "receipt": { "to": null, "from": "0x12Bdf8Ae9fE2047809080412d7341044b910ef10", - "contractAddress": "0x1a9D2862028F6f5E6C299A7AC3C285508942b15E", - "transactionIndex": 81, - "gasUsed": "683212", - "logsBloom": "0x00000000400400000000001000000000000001000000000000808000000000000000000000000040000840020000000000400000000000000000000840048000001000000000000000000000001000800001000002040000000000080000002000000000020000000080000000000800000002080000000000000000000000400000000000000008000000000000080000000000080080140000000000000000000000000000000100000000000400000000000000800000000000000000004000000004000000000002000000040000000000000000080000840000000060000040000000000002000000800000000400000800000000000000000800010000", - "blockHash": "0xcd5322bb8023a14559b40450baa607e4380fc265810776182b1c51cdd9df73ba", - "transactionHash": "0x6feefa919796851a92bad7a4628b1d13966480210b1f203fa97c8daa0b025aa2", + "contractAddress": "0x795DE779Be00Ea46eA97a28BDD38d9ED570BCF0F", + "transactionIndex": 83, + "gasUsed": "683440", + "logsBloom": "0x000000004004000000000010000000000000010010000000008080000000000000000000000000400008400202000000000000000000000000000008400080000010000000000000000000000010000000010000000000000000000000000020000000000200000000800000000008000000020000000000000000000000004080a0000000000018000000000000080000000010080080140000000000000000000000000000000100000000000400000000000000800000000000000000004000000004000000000002000000040000000000000000080000a00000000020000040000000000002000000800000000400000800000000000040000800010000", + "blockHash": "0xd2ab0c26930f96425b92857f30d578f17bea22e0eefd4ef3a9ab281831b97cd4", + "transactionHash": "0x94c2c6065182423ebaa2818078939f9c92e2bffef62ac180dd283bf2c9e97c74", "logs": [ { - "transactionIndex": 81, - "blockNumber": 32129384, - "transactionHash": "0x6feefa919796851a92bad7a4628b1d13966480210b1f203fa97c8daa0b025aa2", - "address": "0x1a9D2862028F6f5E6C299A7AC3C285508942b15E", + "transactionIndex": 83, + "blockNumber": 32138981, + "transactionHash": "0x94c2c6065182423ebaa2818078939f9c92e2bffef62ac180dd283bf2c9e97c74", + "address": "0x795DE779Be00Ea46eA97a28BDD38d9ED570BCF0F", "topics": [ "0x1cf3b03a6cf19fa2baba4df148e9dcabedea7f8a5c07840e207e5c089be95d3e", "0x0000000000000000000000002b8a1c539abac89cbf7e2bc6987a0a38a5e660d4" ], "data": "0x", - "logIndex": 137, - "blockHash": "0xcd5322bb8023a14559b40450baa607e4380fc265810776182b1c51cdd9df73ba" + "logIndex": 217, + "blockHash": "0xd2ab0c26930f96425b92857f30d578f17bea22e0eefd4ef3a9ab281831b97cd4" }, { - "transactionIndex": 81, - "blockNumber": 32129384, - "transactionHash": "0x6feefa919796851a92bad7a4628b1d13966480210b1f203fa97c8daa0b025aa2", - "address": "0x1a9D2862028F6f5E6C299A7AC3C285508942b15E", + "transactionIndex": 83, + "blockNumber": 32138981, + "transactionHash": "0x94c2c6065182423ebaa2818078939f9c92e2bffef62ac180dd283bf2c9e97c74", + "address": "0x795DE779Be00Ea46eA97a28BDD38d9ED570BCF0F", "topics": [ "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x00000000000000000000000012bdf8ae9fe2047809080412d7341044b910ef10" ], "data": "0x", - "logIndex": 138, - "blockHash": "0xcd5322bb8023a14559b40450baa607e4380fc265810776182b1c51cdd9df73ba" + "logIndex": 218, + "blockHash": "0xd2ab0c26930f96425b92857f30d578f17bea22e0eefd4ef3a9ab281831b97cd4" }, { - "transactionIndex": 81, - "blockNumber": 32129384, - "transactionHash": "0x6feefa919796851a92bad7a4628b1d13966480210b1f203fa97c8daa0b025aa2", - "address": "0x1a9D2862028F6f5E6C299A7AC3C285508942b15E", + "transactionIndex": 83, + "blockNumber": 32138981, + "transactionHash": "0x94c2c6065182423ebaa2818078939f9c92e2bffef62ac180dd283bf2c9e97c74", + "address": "0x795DE779Be00Ea46eA97a28BDD38d9ED570BCF0F", "topics": ["0x66fd58e82f7b31a2a5c30e0888f3093efe4e111b00cd2b0c31fe014601293aa0"], "data": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000004788629abc6cfca10f9f969efdeaa1cf70c23555", - "logIndex": 139, - "blockHash": "0xcd5322bb8023a14559b40450baa607e4380fc265810776182b1c51cdd9df73ba" + "logIndex": 219, + "blockHash": "0xd2ab0c26930f96425b92857f30d578f17bea22e0eefd4ef3a9ab281831b97cd4" }, { - "transactionIndex": 81, - "blockNumber": 32129384, - "transactionHash": "0x6feefa919796851a92bad7a4628b1d13966480210b1f203fa97c8daa0b025aa2", - "address": "0x1a9D2862028F6f5E6C299A7AC3C285508942b15E", + "transactionIndex": 83, + "blockNumber": 32138981, + "transactionHash": "0x94c2c6065182423ebaa2818078939f9c92e2bffef62ac180dd283bf2c9e97c74", + "address": "0x795DE779Be00Ea46eA97a28BDD38d9ED570BCF0F", "topics": [ "0x7ac369dbd14fa5ea3f473ed67cc9d598964a77501540ba6751eb0b3decf5870d", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x00000000000000000000000094c1495cd4c557f1560cbd68eab0d197e6291571" ], "data": "0x", - "logIndex": 140, - "blockHash": "0xcd5322bb8023a14559b40450baa607e4380fc265810776182b1c51cdd9df73ba" + "logIndex": 220, + "blockHash": "0xd2ab0c26930f96425b92857f30d578f17bea22e0eefd4ef3a9ab281831b97cd4" }, { - "transactionIndex": 81, - "blockNumber": 32129384, - "transactionHash": "0x6feefa919796851a92bad7a4628b1d13966480210b1f203fa97c8daa0b025aa2", - "address": "0x1a9D2862028F6f5E6C299A7AC3C285508942b15E", + "transactionIndex": 83, + "blockNumber": 32138981, + "transactionHash": "0x94c2c6065182423ebaa2818078939f9c92e2bffef62ac180dd283bf2c9e97c74", + "address": "0x795DE779Be00Ea46eA97a28BDD38d9ED570BCF0F", "topics": [ "0xedffc32e068c7c95dfd4bdfd5c4d939a084d6b11c4199eac8436ed234d72f926", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000820d5da817ac2eaf3757829b255b56354188bd1" ], "data": "0x", - "logIndex": 141, - "blockHash": "0xcd5322bb8023a14559b40450baa607e4380fc265810776182b1c51cdd9df73ba" + "logIndex": 221, + "blockHash": "0xd2ab0c26930f96425b92857f30d578f17bea22e0eefd4ef3a9ab281831b97cd4" }, { - "transactionIndex": 81, - "blockNumber": 32129384, - "transactionHash": "0x6feefa919796851a92bad7a4628b1d13966480210b1f203fa97c8daa0b025aa2", - "address": "0x1a9D2862028F6f5E6C299A7AC3C285508942b15E", + "transactionIndex": 83, + "blockNumber": 32138981, + "transactionHash": "0x94c2c6065182423ebaa2818078939f9c92e2bffef62ac180dd283bf2c9e97c74", + "address": "0x795DE779Be00Ea46eA97a28BDD38d9ED570BCF0F", "topics": ["0xaaa68312e2ea9d50e16af5068410ab56e1a1fd06037b1a35664812c30f821460"], "data": "0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016345785d8a0000", - "logIndex": 142, - "blockHash": "0xcd5322bb8023a14559b40450baa607e4380fc265810776182b1c51cdd9df73ba" + "logIndex": 222, + "blockHash": "0xd2ab0c26930f96425b92857f30d578f17bea22e0eefd4ef3a9ab281831b97cd4" }, { - "transactionIndex": 81, - "blockNumber": 32129384, - "transactionHash": "0x6feefa919796851a92bad7a4628b1d13966480210b1f203fa97c8daa0b025aa2", - "address": "0x1a9D2862028F6f5E6C299A7AC3C285508942b15E", + "transactionIndex": 83, + "blockNumber": 32138981, + "transactionHash": "0x94c2c6065182423ebaa2818078939f9c92e2bffef62ac180dd283bf2c9e97c74", + "address": "0x795DE779Be00Ea46eA97a28BDD38d9ED570BCF0F", "topics": [ "0x6dbf1ff28f860de5edafa4c6505e37c0aba213288cc4166c5352b6d3776c79ef", "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000001" + "0x000000000000000000000000f37530a8a810fcb501aa0ecd0b0699388f0f2209" ], "data": "0x", - "logIndex": 143, - "blockHash": "0xcd5322bb8023a14559b40450baa607e4380fc265810776182b1c51cdd9df73ba" + "logIndex": 223, + "blockHash": "0xd2ab0c26930f96425b92857f30d578f17bea22e0eefd4ef3a9ab281831b97cd4" }, { - "transactionIndex": 81, - "blockNumber": 32129384, - "transactionHash": "0x6feefa919796851a92bad7a4628b1d13966480210b1f203fa97c8daa0b025aa2", - "address": "0x1a9D2862028F6f5E6C299A7AC3C285508942b15E", + "transactionIndex": 83, + "blockNumber": 32138981, + "transactionHash": "0x94c2c6065182423ebaa2818078939f9c92e2bffef62ac180dd283bf2c9e97c74", + "address": "0x795DE779Be00Ea46eA97a28BDD38d9ED570BCF0F", "topics": [ "0xafec95c8612496c3ecf5dddc71e393528fe29bd145fbaf9c6b496d78d7e2d79b", "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x000000000000000000000000f322942f644a996a617bd29c16bd7d231d9f35e9" + "0x000000000000000000000000fb5be09a1fa6cfda075ab1e69fe83ce8324682e4" ], "data": "0x", - "logIndex": 144, - "blockHash": "0xcd5322bb8023a14559b40450baa607e4380fc265810776182b1c51cdd9df73ba" + "logIndex": 224, + "blockHash": "0xd2ab0c26930f96425b92857f30d578f17bea22e0eefd4ef3a9ab281831b97cd4" }, { - "transactionIndex": 81, - "blockNumber": 32129384, - "transactionHash": "0x6feefa919796851a92bad7a4628b1d13966480210b1f203fa97c8daa0b025aa2", - "address": "0x1a9D2862028F6f5E6C299A7AC3C285508942b15E", + "transactionIndex": 83, + "blockNumber": 32138981, + "transactionHash": "0x94c2c6065182423ebaa2818078939f9c92e2bffef62ac180dd283bf2c9e97c74", + "address": "0x795DE779Be00Ea46eA97a28BDD38d9ED570BCF0F", "topics": [ "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", "0x00000000000000000000000012bdf8ae9fe2047809080412d7341044b910ef10", "0x000000000000000000000000939bd8d64c0a9583a7dcea9933f7b21697ab6396" ], "data": "0x", - "logIndex": 145, - "blockHash": "0xcd5322bb8023a14559b40450baa607e4380fc265810776182b1c51cdd9df73ba" + "logIndex": 225, + "blockHash": "0xd2ab0c26930f96425b92857f30d578f17bea22e0eefd4ef3a9ab281831b97cd4" }, { - "transactionIndex": 81, - "blockNumber": 32129384, - "transactionHash": "0x6feefa919796851a92bad7a4628b1d13966480210b1f203fa97c8daa0b025aa2", - "address": "0x1a9D2862028F6f5E6C299A7AC3C285508942b15E", + "transactionIndex": 83, + "blockNumber": 32138981, + "transactionHash": "0x94c2c6065182423ebaa2818078939f9c92e2bffef62ac180dd283bf2c9e97c74", + "address": "0x795DE779Be00Ea46eA97a28BDD38d9ED570BCF0F", "topics": ["0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498"], "data": "0x0000000000000000000000000000000000000000000000000000000000000001", - "logIndex": 146, - "blockHash": "0xcd5322bb8023a14559b40450baa607e4380fc265810776182b1c51cdd9df73ba" + "logIndex": 226, + "blockHash": "0xd2ab0c26930f96425b92857f30d578f17bea22e0eefd4ef3a9ab281831b97cd4" } ], - "blockNumber": 32129384, - "cumulativeGasUsed": "8387324", + "blockNumber": 32138981, + "cumulativeGasUsed": "9242988", "status": 1, "byzantium": true }, "args": [ "0x2b8A1C539ABaC89CbF7E2Bc6987A0A38A5e660D4", - "0x8a42c31900000000000000000000000012f31b73d812c6bb0d735a218c086d44d5fe5f8900000000000000000000000094c1495cd4c557f1560cbd68eab0d197e62915710000000000000000000000000820d5da817ac2eaf3757829b255b56354188bd10000000000000000000000000000000000000000204fce5e3e25026110000000000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000001c00000000000000000000000000000000000000000000000000000000000000008000000000000000000000000939bd8d64c0a9583a7dcea9933f7b21697ab63960000000000000000000000004788629abc6cfca10f9f969efdeaa1cf70c235550000000000000000000000000000000000000000000000000000000000000001000000000000000000000000f322942f644a996a617bd29c16bd7d231d9f35e9000000000000000000000000000000000000000000000000016345785d8a0000000000000000000000000000000000000000000000000000000000000000001956656e75732061674555522028537461626c65636f696e73290000000000000000000000000000000000000000000000000000000000000000000000000000127661674555525f537461626c65636f696e730000000000000000000000000000" + "0x8a42c31900000000000000000000000012f31b73d812c6bb0d735a218c086d44d5fe5f8900000000000000000000000094c1495cd4c557f1560cbd68eab0d197e62915710000000000000000000000000820d5da817ac2eaf3757829b255b56354188bd10000000000000000000000000000000000000000204fce5e3e25026110000000000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000001c00000000000000000000000000000000000000000000000000000000000000008000000000000000000000000939bd8d64c0a9583a7dcea9933f7b21697ab63960000000000000000000000004788629abc6cfca10f9f969efdeaa1cf70c23555000000000000000000000000f37530a8a810fcb501aa0ecd0b0699388f0f2209000000000000000000000000fb5be09a1fa6cfda075ab1e69fe83ce8324682e4000000000000000000000000000000000000000000000000016345785d8a0000000000000000000000000000000000000000000000000000000000000000001956656e75732061674555522028537461626c65636f696e73290000000000000000000000000000000000000000000000000000000000000000000000000000127661674555525f537461626c65636f696e730000000000000000000000000000" ], "numDeployments": 1, "solcInputHash": "6d4db51b84097a74598623a15df3d6fb", diff --git a/deployments/bsctestnet.json b/deployments/bsctestnet.json index dccaaeace..83eb8845a 100644 --- a/deployments/bsctestnet.json +++ b/deployments/bsctestnet.json @@ -49856,7 +49856,7 @@ ] }, "VToken_vagEUR_Stablecoins": { - "address": "0xa0571e758a00C586DbD53fb431d0f48eff9d0F15", + "address": "0x4E1D35166776825402d50AfE4286c500027211D1", "abi": [ { "inputs": [ diff --git a/deployments/bsctestnet/VToken_vagEUR_Stablecoins.json b/deployments/bsctestnet/VToken_vagEUR_Stablecoins.json index f13348ef3..6d1b0741d 100644 --- a/deployments/bsctestnet/VToken_vagEUR_Stablecoins.json +++ b/deployments/bsctestnet/VToken_vagEUR_Stablecoins.json @@ -1,5 +1,5 @@ { - "address": "0xa0571e758a00C586DbD53fb431d0f48eff9d0F15", + "address": "0x4E1D35166776825402d50AfE4286c500027211D1", "abi": [ { "inputs": [ @@ -71,35 +71,35 @@ "type": "receive" } ], - "transactionHash": "0x16949b420db4e6e6db37a7f953eb0fd22e36f76b74fa5e26afdfa10bad9027a5", + "transactionHash": "0x74f8b739a28f747ecf0e6df8bbb44d664d6fd5e162bd985175c1339abf2e4b90", "receipt": { "to": null, "from": "0xcd2a514f04241b7c9A0d5d54441e92E4611929CF", - "contractAddress": "0xa0571e758a00C586DbD53fb431d0f48eff9d0F15", - "transactionIndex": 1, - "gasUsed": "675894", - "logsBloom": "0x00000000000400000000000000000000000000000000000000800000000000000000000000800040000000020000000000000000000000000000000800048000021000000000000000000000001000000001000000040000800000000000002000000000021000000080000010080810000000000040000000000000040000400000100000000000000000000000080000000000000080100000000000000000000000040000000100000000000400000000000010800000000000000010004000000004000000000002200000040000000000000000100000800000000060000000040000000000000000800000040402010800000004000000004000010000", - "blockHash": "0x890ed17c6062fbbf0555dc1eb7e115f8554adbf0d123d288ab5d21ddf54f456e", - "transactionHash": "0x16949b420db4e6e6db37a7f953eb0fd22e36f76b74fa5e26afdfa10bad9027a5", + "contractAddress": "0x4E1D35166776825402d50AfE4286c500027211D1", + "transactionIndex": 0, + "gasUsed": "676134", + "logsBloom": "0x00000000000400000000000000000000000000000000000000800000000000000000008000800040000000020000000000000000000000000000000800008000021000000000040000000000001000000001000000000000800000000000002000000000021000000080000010000810000000000040000000000000000000400000000000000000800000000000080000000000000080100008000000000000000000000000100100000000000500000000000000800000000000000010004000000004000000800002200000040040000000000000120000800000000020000000040000000000000000800000040402010800000000000000004000010000", + "blockHash": "0x6139aa8da7872f861c7f29dbead5804573799f15206c94951d4d27182f659cbf", + "transactionHash": "0x74f8b739a28f747ecf0e6df8bbb44d664d6fd5e162bd985175c1339abf2e4b90", "logs": [ { - "transactionIndex": 1, - "blockNumber": 33727995, - "transactionHash": "0x16949b420db4e6e6db37a7f953eb0fd22e36f76b74fa5e26afdfa10bad9027a5", - "address": "0xa0571e758a00C586DbD53fb431d0f48eff9d0F15", + "transactionIndex": 0, + "blockNumber": 33737725, + "transactionHash": "0x74f8b739a28f747ecf0e6df8bbb44d664d6fd5e162bd985175c1339abf2e4b90", + "address": "0x4E1D35166776825402d50AfE4286c500027211D1", "topics": [ "0x1cf3b03a6cf19fa2baba4df148e9dcabedea7f8a5c07840e207e5c089be95d3e", "0x000000000000000000000000bf85a90673e61956f8c79b9150bab7893b791bdd" ], "data": "0x", "logIndex": 0, - "blockHash": "0x890ed17c6062fbbf0555dc1eb7e115f8554adbf0d123d288ab5d21ddf54f456e" + "blockHash": "0x6139aa8da7872f861c7f29dbead5804573799f15206c94951d4d27182f659cbf" }, { - "transactionIndex": 1, - "blockNumber": 33727995, - "transactionHash": "0x16949b420db4e6e6db37a7f953eb0fd22e36f76b74fa5e26afdfa10bad9027a5", - "address": "0xa0571e758a00C586DbD53fb431d0f48eff9d0F15", + "transactionIndex": 0, + "blockNumber": 33737725, + "transactionHash": "0x74f8b739a28f747ecf0e6df8bbb44d664d6fd5e162bd985175c1339abf2e4b90", + "address": "0x4E1D35166776825402d50AfE4286c500027211D1", "topics": [ "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", "0x0000000000000000000000000000000000000000000000000000000000000000", @@ -107,23 +107,23 @@ ], "data": "0x", "logIndex": 1, - "blockHash": "0x890ed17c6062fbbf0555dc1eb7e115f8554adbf0d123d288ab5d21ddf54f456e" + "blockHash": "0x6139aa8da7872f861c7f29dbead5804573799f15206c94951d4d27182f659cbf" }, { - "transactionIndex": 1, - "blockNumber": 33727995, - "transactionHash": "0x16949b420db4e6e6db37a7f953eb0fd22e36f76b74fa5e26afdfa10bad9027a5", - "address": "0xa0571e758a00C586DbD53fb431d0f48eff9d0F15", + "transactionIndex": 0, + "blockNumber": 33737725, + "transactionHash": "0x74f8b739a28f747ecf0e6df8bbb44d664d6fd5e162bd985175c1339abf2e4b90", + "address": "0x4E1D35166776825402d50AfE4286c500027211D1", "topics": ["0x66fd58e82f7b31a2a5c30e0888f3093efe4e111b00cd2b0c31fe014601293aa0"], "data": "0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000045f8a08f534f34a97187626e05d4b6648eeaa9aa", "logIndex": 2, - "blockHash": "0x890ed17c6062fbbf0555dc1eb7e115f8554adbf0d123d288ab5d21ddf54f456e" + "blockHash": "0x6139aa8da7872f861c7f29dbead5804573799f15206c94951d4d27182f659cbf" }, { - "transactionIndex": 1, - "blockNumber": 33727995, - "transactionHash": "0x16949b420db4e6e6db37a7f953eb0fd22e36f76b74fa5e26afdfa10bad9027a5", - "address": "0xa0571e758a00C586DbD53fb431d0f48eff9d0F15", + "transactionIndex": 0, + "blockNumber": 33737725, + "transactionHash": "0x74f8b739a28f747ecf0e6df8bbb44d664d6fd5e162bd985175c1339abf2e4b90", + "address": "0x4E1D35166776825402d50AfE4286c500027211D1", "topics": [ "0x7ac369dbd14fa5ea3f473ed67cc9d598964a77501540ba6751eb0b3decf5870d", "0x0000000000000000000000000000000000000000000000000000000000000000", @@ -131,13 +131,13 @@ ], "data": "0x", "logIndex": 3, - "blockHash": "0x890ed17c6062fbbf0555dc1eb7e115f8554adbf0d123d288ab5d21ddf54f456e" + "blockHash": "0x6139aa8da7872f861c7f29dbead5804573799f15206c94951d4d27182f659cbf" }, { - "transactionIndex": 1, - "blockNumber": 33727995, - "transactionHash": "0x16949b420db4e6e6db37a7f953eb0fd22e36f76b74fa5e26afdfa10bad9027a5", - "address": "0xa0571e758a00C586DbD53fb431d0f48eff9d0F15", + "transactionIndex": 0, + "blockNumber": 33737725, + "transactionHash": "0x74f8b739a28f747ecf0e6df8bbb44d664d6fd5e162bd985175c1339abf2e4b90", + "address": "0x4E1D35166776825402d50AfE4286c500027211D1", "topics": [ "0xedffc32e068c7c95dfd4bdfd5c4d939a084d6b11c4199eac8436ed234d72f926", "0x0000000000000000000000000000000000000000000000000000000000000000", @@ -145,51 +145,51 @@ ], "data": "0x", "logIndex": 4, - "blockHash": "0x890ed17c6062fbbf0555dc1eb7e115f8554adbf0d123d288ab5d21ddf54f456e" + "blockHash": "0x6139aa8da7872f861c7f29dbead5804573799f15206c94951d4d27182f659cbf" }, { - "transactionIndex": 1, - "blockNumber": 33727995, - "transactionHash": "0x16949b420db4e6e6db37a7f953eb0fd22e36f76b74fa5e26afdfa10bad9027a5", - "address": "0xa0571e758a00C586DbD53fb431d0f48eff9d0F15", + "transactionIndex": 0, + "blockNumber": 33737725, + "transactionHash": "0x74f8b739a28f747ecf0e6df8bbb44d664d6fd5e162bd985175c1339abf2e4b90", + "address": "0x4E1D35166776825402d50AfE4286c500027211D1", "topics": ["0xaaa68312e2ea9d50e16af5068410ab56e1a1fd06037b1a35664812c30f821460"], "data": "0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016345785d8a0000", "logIndex": 5, - "blockHash": "0x890ed17c6062fbbf0555dc1eb7e115f8554adbf0d123d288ab5d21ddf54f456e" + "blockHash": "0x6139aa8da7872f861c7f29dbead5804573799f15206c94951d4d27182f659cbf" }, { - "transactionIndex": 1, - "blockNumber": 33727995, - "transactionHash": "0x16949b420db4e6e6db37a7f953eb0fd22e36f76b74fa5e26afdfa10bad9027a5", - "address": "0xa0571e758a00C586DbD53fb431d0f48eff9d0F15", + "transactionIndex": 0, + "blockNumber": 33737725, + "transactionHash": "0x74f8b739a28f747ecf0e6df8bbb44d664d6fd5e162bd985175c1339abf2e4b90", + "address": "0x4E1D35166776825402d50AfE4286c500027211D1", "topics": [ "0x6dbf1ff28f860de5edafa4c6505e37c0aba213288cc4166c5352b6d3776c79ef", "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000001" + "0x000000000000000000000000503574a82fe2a9f968d355c8aac1ba0481859369" ], "data": "0x", "logIndex": 6, - "blockHash": "0x890ed17c6062fbbf0555dc1eb7e115f8554adbf0d123d288ab5d21ddf54f456e" + "blockHash": "0x6139aa8da7872f861c7f29dbead5804573799f15206c94951d4d27182f659cbf" }, { - "transactionIndex": 1, - "blockNumber": 33727995, - "transactionHash": "0x16949b420db4e6e6db37a7f953eb0fd22e36f76b74fa5e26afdfa10bad9027a5", - "address": "0xa0571e758a00C586DbD53fb431d0f48eff9d0F15", + "transactionIndex": 0, + "blockNumber": 33737725, + "transactionHash": "0x74f8b739a28f747ecf0e6df8bbb44d664d6fd5e162bd985175c1339abf2e4b90", + "address": "0x4E1D35166776825402d50AfE4286c500027211D1", "topics": [ "0xafec95c8612496c3ecf5dddc71e393528fe29bd145fbaf9c6b496d78d7e2d79b", "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000008b293600c50d6fbdc6ed4251cc75ece29880276f" + "0x000000000000000000000000c987a03ab6c2a5891fc0919f021cc693b5e55278" ], "data": "0x", "logIndex": 7, - "blockHash": "0x890ed17c6062fbbf0555dc1eb7e115f8554adbf0d123d288ab5d21ddf54f456e" + "blockHash": "0x6139aa8da7872f861c7f29dbead5804573799f15206c94951d4d27182f659cbf" }, { - "transactionIndex": 1, - "blockNumber": 33727995, - "transactionHash": "0x16949b420db4e6e6db37a7f953eb0fd22e36f76b74fa5e26afdfa10bad9027a5", - "address": "0xa0571e758a00C586DbD53fb431d0f48eff9d0F15", + "transactionIndex": 0, + "blockNumber": 33737725, + "transactionHash": "0x74f8b739a28f747ecf0e6df8bbb44d664d6fd5e162bd985175c1339abf2e4b90", + "address": "0x4E1D35166776825402d50AfE4286c500027211D1", "topics": [ "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", "0x000000000000000000000000cd2a514f04241b7c9a0d5d54441e92e4611929cf", @@ -197,27 +197,27 @@ ], "data": "0x", "logIndex": 8, - "blockHash": "0x890ed17c6062fbbf0555dc1eb7e115f8554adbf0d123d288ab5d21ddf54f456e" + "blockHash": "0x6139aa8da7872f861c7f29dbead5804573799f15206c94951d4d27182f659cbf" }, { - "transactionIndex": 1, - "blockNumber": 33727995, - "transactionHash": "0x16949b420db4e6e6db37a7f953eb0fd22e36f76b74fa5e26afdfa10bad9027a5", - "address": "0xa0571e758a00C586DbD53fb431d0f48eff9d0F15", + "transactionIndex": 0, + "blockNumber": 33737725, + "transactionHash": "0x74f8b739a28f747ecf0e6df8bbb44d664d6fd5e162bd985175c1339abf2e4b90", + "address": "0x4E1D35166776825402d50AfE4286c500027211D1", "topics": ["0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498"], "data": "0x0000000000000000000000000000000000000000000000000000000000000001", "logIndex": 9, - "blockHash": "0x890ed17c6062fbbf0555dc1eb7e115f8554adbf0d123d288ab5d21ddf54f456e" + "blockHash": "0x6139aa8da7872f861c7f29dbead5804573799f15206c94951d4d27182f659cbf" } ], - "blockNumber": 33727995, - "cumulativeGasUsed": "696894", + "blockNumber": 33737725, + "cumulativeGasUsed": "676134", "status": 1, "byzantium": true }, "args": [ "0xBF85A90673E61956f8c79b9150BAB7893b791bDd", - "0x8a42c31900000000000000000000000063061de4a25f24279aaab80400040684f92ee31900000000000000000000000010b57706ad2345e590c2ea4dc02faef0d9f5b08b0000000000000000000000006ba592934fd60d7a180d65cdb1c9bf561fead3d40000000000000000000000000000000000000000204fce5e3e25026110000000000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000001c00000000000000000000000000000000000000000000000000000000000000008000000000000000000000000ce10739590001705f7ff231611ba4a48b282032700000000000000000000000045f8a08f534f34a97187626e05d4b6648eeaa9aa00000000000000000000000000000000000000000000000000000000000000010000000000000000000000008b293600c50d6fbdc6ed4251cc75ece29880276f000000000000000000000000000000000000000000000000016345785d8a0000000000000000000000000000000000000000000000000000000000000000001956656e75732061674555522028537461626c65636f696e73290000000000000000000000000000000000000000000000000000000000000000000000000000127661674555525f537461626c65636f696e730000000000000000000000000000" + "0x8a42c31900000000000000000000000063061de4a25f24279aaab80400040684f92ee31900000000000000000000000010b57706ad2345e590c2ea4dc02faef0d9f5b08b0000000000000000000000006ba592934fd60d7a180d65cdb1c9bf561fead3d40000000000000000000000000000000000000000204fce5e3e25026110000000000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000001c00000000000000000000000000000000000000000000000000000000000000008000000000000000000000000ce10739590001705f7ff231611ba4a48b282032700000000000000000000000045f8a08f534f34a97187626e05d4b6648eeaa9aa000000000000000000000000503574a82fe2a9f968d355c8aac1ba0481859369000000000000000000000000c987a03ab6c2a5891fc0919f021cc693b5e55278000000000000000000000000000000000000000000000000016345785d8a0000000000000000000000000000000000000000000000000000000000000000001956656e75732061674555522028537461626c65636f696e73290000000000000000000000000000000000000000000000000000000000000000000000000000127661674555525f537461626c65636f696e730000000000000000000000000000" ], "numDeployments": 1, "solcInputHash": "6d4db51b84097a74598623a15df3d6fb", diff --git a/helpers/deploymentConfig.ts b/helpers/deploymentConfig.ts index 65e6ef3b2..e6a657180 100644 --- a/helpers/deploymentConfig.ts +++ b/helpers/deploymentConfig.ts @@ -96,6 +96,8 @@ const preconfiguredAddresses = { WBNB: "0xae13d989daC2f0dEbFf460aC112a837C89BAa7cd", VBNB_CorePool: "0x2E7222e51c0f6e98610A1543Aa3836E092CDe62c", SwapRouter_CorePool: "0x83edf1deE1B730b7e8e13C00ba76027D63a51ac0", + ProtocolShareReserve: "0xc987a03ab6C2A5891Fc0919f021cc693B5E55278", + Shortfall: "0x503574a82fE2A9f968d355C8AAc1Ba0481859369", }, bscmainnet: { VTreasury: "0xF322942f644A996A617BD29c16bd7d231d9F35E9", @@ -108,6 +110,8 @@ const preconfiguredAddresses = { WBNB: "0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c", VBNB_CorePool: "0xA07c5b74C9B40447a954e1466938b865b6BBea36", SwapRouter_CorePool: "0x8938E6dA30b59c1E27d5f70a94688A89F7c815a4", + ProtocolShareReserve: "0xfB5bE09a1FA6CFDA075aB1E69FE83ce8324682e4", + Shortfall: "0xf37530A8a810Fcb501AA0Ecd0B0699388F0F2209", }, }; From 3df706dd560e32589cec8387b5d3f2466332ffdb Mon Sep 17 00:00:00 2001 From: GitGuru7 <128375421+GitGuru7@users.noreply.github.com> Date: Fri, 29 Sep 2023 09:26:07 +0530 Subject: [PATCH 13/33] chore: update script to set risk management addresses --- deploy/009-deploy-vtokens.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/deploy/009-deploy-vtokens.ts b/deploy/009-deploy-vtokens.ts index 96907417f..ebe95e4ef 100644 --- a/deploy/009-deploy-vtokens.ts +++ b/deploy/009-deploy-vtokens.ts @@ -114,7 +114,10 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { vTokenDecimals, preconfiguredAddresses.NormalTimelock || deployer, // admin accessControlManagerAddress, - [ADDRESS_ONE, treasuryAddress], + [ + preconfiguredAddresses.Shortfall || ADDRESS_ONE, + preconfiguredAddresses.ProtocolShareReserve || treasuryAddress, + ], reserveFactor, ]; await deploy(`VToken_${symbol}`, { From 4d376c815e63f167b6be79e17035a2060c2a39ab Mon Sep 17 00:00:00 2001 From: Venus Tools Date: Fri, 29 Sep 2023 10:02:45 +0000 Subject: [PATCH 14/33] chore(release): 2.1.0-dev.3 [skip ci] ## [2.1.0-dev.3](https://github.com/VenusProtocol/isolated-pools/compare/v2.1.0-dev.2...v2.1.0-dev.3) (2023-09-29) ### Features * add SnBNB market deployments ([add6956](https://github.com/VenusProtocol/isolated-pools/commit/add695693f9e835835e8e53a83dce81aaddfe29e)) --- CHANGELOG.md | 7 +++++++ package.json | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0344a7aef..4776749a0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [2.1.0-dev.3](https://github.com/VenusProtocol/isolated-pools/compare/v2.1.0-dev.2...v2.1.0-dev.3) (2023-09-29) + + +### Features + +* add SnBNB market deployments ([add6956](https://github.com/VenusProtocol/isolated-pools/commit/add695693f9e835835e8e53a83dce81aaddfe29e)) + ## [2.1.0-dev.2](https://github.com/VenusProtocol/isolated-pools/compare/v2.1.0-dev.1...v2.1.0-dev.2) (2023-09-18) ## [2.1.0-dev.1](https://github.com/VenusProtocol/isolated-pools/compare/v2.0.1-dev.1...v2.1.0-dev.1) (2023-09-15) diff --git a/package.json b/package.json index 6f1bc24ee..06992c70c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@venusprotocol/isolated-pools", - "version": "2.1.0-dev.2", + "version": "2.1.0-dev.3", "description": "", "files": [ "artifacts", From e1614383fe6a24b098c98ff509ce2f7e84e4e2bc Mon Sep 17 00:00:00 2001 From: Narayan Prusty Date: Mon, 9 Oct 2023 15:56:36 +0100 Subject: [PATCH 15/33] fix: added support for core pool assets in risk fund --- contracts/RiskFund/ProtocolShareReserve.sol | 8 +-- contracts/RiskFund/ReserveHelpers.sol | 55 +++++++++++++++++++-- contracts/RiskFund/RiskFund.sol | 6 ++- deploy/014-riskfund-protocolshare.ts | 14 ++++++ helpers/deploymentConfig.ts | 2 + tests/hardhat/Fork/RiskFund.ts | 27 ++++++++-- tests/hardhat/Fork/RiskFundSwap.ts | 18 ++++++- tests/hardhat/ProtocolShareReserve.ts | 10 +++- tests/integration/index.ts | 2 +- 9 files changed, 127 insertions(+), 15 deletions(-) diff --git a/contracts/RiskFund/ProtocolShareReserve.sol b/contracts/RiskFund/ProtocolShareReserve.sol index bc4733c99..0e1b3439b 100644 --- a/contracts/RiskFund/ProtocolShareReserve.sol +++ b/contracts/RiskFund/ProtocolShareReserve.sol @@ -26,9 +26,11 @@ contract ProtocolShareReserve is ExponentialNoError, ReserveHelpers, IProtocolSh event PoolRegistryUpdated(address indexed oldPoolRegistry, address indexed newPoolRegistry); /// @custom:oz-upgrades-unsafe-allow constructor - constructor() { - // Note that the contract is upgradeable. Use initialize() or reinitializers - // to set the state variables. + constructor( + address corePoolComptroller_, + address vbnb_, + address nativeWrapped_ + ) ReserveHelpers(corePoolComptroller_, vbnb_, nativeWrapped_) { _disableInitializers(); } diff --git a/contracts/RiskFund/ReserveHelpers.sol b/contracts/RiskFund/ReserveHelpers.sol index bca55a25f..cdd1f9ed2 100644 --- a/contracts/RiskFund/ReserveHelpers.sol +++ b/contracts/RiskFund/ReserveHelpers.sol @@ -8,6 +8,8 @@ import { SafeERC20Upgradeable } from "@openzeppelin/contracts-upgradeable/token/ import { ensureNonzeroAddress } from "../lib/validators.sol"; import { ComptrollerInterface } from "../ComptrollerInterface.sol"; import { PoolRegistryInterface } from "../Pool/PoolRegistryInterface.sol"; +import { VToken } from "../VToken.sol"; +import { PoolRegistry } from "../Pool/PoolRegistry.sol"; contract ReserveHelpers is Ownable2StepUpgradeable { using SafeERC20Upgradeable for IERC20Upgradeable; @@ -16,6 +18,18 @@ contract ReserveHelpers is Ownable2StepUpgradeable { uint256 private constant ENTERED = 2; + // Address of the core pool's comptroller + /// @custom:oz-upgrades-unsafe-allow state-variable-immutable + address public immutable CORE_POOL_COMPTROLLER; + + // Address of the VBNB + /// @custom:oz-upgrades-unsafe-allow state-variable-immutable + address public immutable VBNB; + + // Address of the native wrapped token + /// @custom:oz-upgrades-unsafe-allow state-variable-immutable + address public immutable NATIVE_WRAPPED; + // Store the previous state for the asset transferred to ProtocolShareReserve combined(for all pools). mapping(address => uint256) public assetsReserves; @@ -56,6 +70,17 @@ contract ReserveHelpers is Ownable2StepUpgradeable { status = NOT_ENTERED; } + /// @custom:oz-upgrades-unsafe-allow constructor + constructor( + address corePoolComptroller_, + address vbnb_, + address nativeWrapped_ + ) { + CORE_POOL_COMPTROLLER = corePoolComptroller_; + VBNB = vbnb_; + NATIVE_WRAPPED = nativeWrapped_; + } + /** * @notice A public function to sweep accidental BEP-20 transfers to this contract. Tokens are sent to the address `to`, provided in input * @param _token The address of the BEP-20 token to sweep @@ -90,6 +115,31 @@ contract ReserveHelpers is Ownable2StepUpgradeable { return _poolsAssetsReserves[comptroller][asset]; } + function isAssetListedInCore(address tokenAddress) internal view returns (bool isAssetListed) { + VToken[] memory coreMarkets = ComptrollerInterface(CORE_POOL_COMPTROLLER).getAllMarkets(); + + for (uint256 i; i < coreMarkets.length; ++i) { + isAssetListed = (VBNB == address(coreMarkets[i])) + ? (tokenAddress == NATIVE_WRAPPED) + : (coreMarkets[i].underlying() == tokenAddress); + + if (isAssetListed) { + break; + } + } + } + + /// @notice This function checks for the given asset is listed or not + /// @param comptroller Address of the comptroller + /// @param asset Address of the asset + function ensureAssetListed(address comptroller, address asset) internal view returns (bool) { + if (comptroller == CORE_POOL_COMPTROLLER) { + return isAssetListedInCore(asset); + } + + return PoolRegistry(poolRegistry).getVTokenForAsset(comptroller, asset) != address(0); + } + /** * @notice Update the reserve of the asset for the specific pool after transferring to risk fund * and transferring funds to the protocol share reserve @@ -102,10 +152,7 @@ contract ReserveHelpers is Ownable2StepUpgradeable { require(ComptrollerInterface(comptroller).isComptroller(), "ReserveHelpers: Comptroller address invalid"); address poolRegistry_ = poolRegistry; require(poolRegistry_ != address(0), "ReserveHelpers: Pool Registry address is not set"); - require( - PoolRegistryInterface(poolRegistry_).getVTokenForAsset(comptroller, asset) != address(0), - "ReserveHelpers: The pool doesn't support the asset" - ); + require(ensureAssetListed(comptroller, asset), "ReserveHelpers: The pool doesn't support the asset"); uint256 currentBalance = IERC20Upgradeable(asset).balanceOf(address(this)); uint256 assetReserve = assetsReserves[asset]; diff --git a/contracts/RiskFund/RiskFund.sol b/contracts/RiskFund/RiskFund.sol index 3c9bf21dd..91495ada7 100644 --- a/contracts/RiskFund/RiskFund.sol +++ b/contracts/RiskFund/RiskFund.sol @@ -57,7 +57,11 @@ contract RiskFund is AccessControlledV8, ExponentialNoError, ReserveHelpers, Max /// @dev Note that the contract is upgradeable. Use initialize() or reinitializers /// to set the state variables. /// @custom:oz-upgrades-unsafe-allow constructor - constructor() { + constructor( + address corePoolComptroller_, + address vbnb_, + address nativeWrapped_ + ) ReserveHelpers(corePoolComptroller_, vbnb_, nativeWrapped_) { _disableInitializers(); } diff --git a/deploy/014-riskfund-protocolshare.ts b/deploy/014-riskfund-protocolshare.ts index 0efb88b05..d4acc54e4 100644 --- a/deploy/014-riskfund-protocolshare.ts +++ b/deploy/014-riskfund-protocolshare.ts @@ -1,10 +1,12 @@ import { ethers } from "hardhat"; import { DeployFunction } from "hardhat-deploy/types"; import { HardhatRuntimeEnvironment } from "hardhat/types"; +import { smock } from "@defi-wonderland/smock"; import { getConfig } from "../helpers/deploymentConfig"; import { getUnderlyingToken, toAddress } from "../helpers/deploymentUtils"; import { convertToUnit } from "../helpers/utils"; +import { Comptroller } from "../typechain"; const MIN_AMOUNT_TO_CONVERT = convertToUnit(10, 18); const MIN_POOL_BAD_DEBT = convertToUnit(1000, 18); @@ -27,6 +29,8 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const proxyAdmin = await ethers.getContract("DefaultProxyAdmin"); const owner = await proxyAdmin.owner(); + const fakeCorePoolComptroller = await smock.fake("Comptroller"); + await deploy("RiskFund", { from: deployer, contract: "RiskFund", @@ -41,6 +45,11 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { }, autoMine: true, log: true, + args: [ + preconfiguredAddresses.Unitroller || fakeCorePoolComptroller.address, + preconfiguredAddresses.VBNB_CorePool || ethers.constants.AddressZero, + preconfiguredAddresses.WBNB || ethers.constants.AddressZero, + ], }); const riskFund = await ethers.getContract("RiskFund"); @@ -89,6 +98,11 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { }, autoMine: true, log: true, + args: [ + preconfiguredAddresses.Unitroller || fakeCorePoolComptroller.address, + preconfiguredAddresses.VBNB_CorePool || ethers.constants.AddressZero, + preconfiguredAddresses.WBNB || ethers.constants.AddressZero, + ], }); for (const contractName of ["ProtocolShareReserve", "RiskFund"]) { diff --git a/helpers/deploymentConfig.ts b/helpers/deploymentConfig.ts index 63c5605a8..1437c2845 100644 --- a/helpers/deploymentConfig.ts +++ b/helpers/deploymentConfig.ts @@ -96,6 +96,7 @@ const preconfiguredAddresses = { WBNB: "0xae13d989daC2f0dEbFf460aC112a837C89BAa7cd", VBNB_CorePool: "0x2E7222e51c0f6e98610A1543Aa3836E092CDe62c", SwapRouter_CorePool: "0x83edf1deE1B730b7e8e13C00ba76027D63a51ac0", + Unitroller: "0x94d1820b2D1c7c7452A163983Dc888CEC546b77D" }, bscmainnet: { VTreasury: "0xF322942f644A996A617BD29c16bd7d231d9F35E9", @@ -108,6 +109,7 @@ const preconfiguredAddresses = { WBNB: "0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c", VBNB_CorePool: "0xA07c5b74C9B40447a954e1466938b865b6BBea36", SwapRouter_CorePool: "0x8938E6dA30b59c1E27d5f70a94688A89F7c815a4", + Unitroller: "0xfD36E2c2a6789Db23113685031d7F16329158384", }, }; diff --git a/tests/hardhat/Fork/RiskFund.ts b/tests/hardhat/Fork/RiskFund.ts index e7eeec0d0..ba20e1bbb 100644 --- a/tests/hardhat/Fork/RiskFund.ts +++ b/tests/hardhat/Fork/RiskFund.ts @@ -128,6 +128,8 @@ const riskFundFixture = async (): Promise => { value: ethers.utils.parseEther("1"), // 1 ether }); + const fakeCorePoolComptroller = await smock.fake("Comptroller"); + const RiskFund = await ethers.getContractFactory("RiskFund"); riskFund = (await upgrades.deployProxy(RiskFund, [ pancakeSwapRouter.address, @@ -135,7 +137,13 @@ const riskFundFixture = async (): Promise => { BUSD.address, accessControlManager.address, 150, - ])) as RiskFund; + ], { + constructorArgs: [ + fakeCorePoolComptroller.address, + ethers.constants.AddressZero, + ethers.constants.AddressZero, + ], + })) as RiskFund; await riskFund.setShortfallContractAddress(shortfall.address); const fakeProtocolIncome = await smock.fake("RiskFund"); @@ -143,7 +151,13 @@ const riskFundFixture = async (): Promise => { protocolShareReserve = (await upgrades.deployProxy(ProtocolShareReserve, [ fakeProtocolIncome.address, riskFund.address, - ])) as ProtocolShareReserve; + ], { + constructorArgs: [ + fakeCorePoolComptroller.address, + ethers.constants.AddressZero, + ethers.constants.AddressZero, + ], + })) as ProtocolShareReserve; const PoolRegistry = await ethers.getContractFactory("PoolRegistry"); poolRegistry = (await upgrades.deployProxy(PoolRegistry, [accessControlManager.address])) as PoolRegistry; @@ -516,13 +530,20 @@ describe("Risk Fund: Tests", function () { it("fails if pool registry is not configured", async function () { const [admin] = await ethers.getSigners(); const RiskFund = await ethers.getContractFactory("RiskFund"); + const fakeCorePoolComptroller = await smock.fake("Comptroller"); const misconfiguredRiskFund = await upgrades.deployProxy(RiskFund, [ pancakeSwapRouter.address, convertToUnit(10, 18), BUSD.address, accessControlManager.address, 150, - ]); + ], { + constructorArgs: [ + fakeCorePoolComptroller.address, + ethers.constants.AddressZero, + ethers.constants.AddressZero, + ] + }); await accessControlManager.giveCallPermission( misconfiguredRiskFund.address, "swapPoolsAssets(address[],uint256[],address[][],uint256)", diff --git a/tests/hardhat/Fork/RiskFundSwap.ts b/tests/hardhat/Fork/RiskFundSwap.ts index a3a883220..ff1cbdb95 100644 --- a/tests/hardhat/Fork/RiskFundSwap.ts +++ b/tests/hardhat/Fork/RiskFundSwap.ts @@ -111,6 +111,8 @@ const riskFundFixture = async (): Promise => { fakeAccessControlManager.address, ]); + const fakeCorePoolComptroller = await smock.fake("Comptroller"); + const RiskFund = await ethers.getContractFactory("RiskFund"); riskFund = (await upgrades.deployProxy(RiskFund, [ pancakeSwapRouter.address, @@ -118,7 +120,13 @@ const riskFundFixture = async (): Promise => { BUSD.address, fakeAccessControlManager.address, maxLoopsLimit, - ])) as RiskFund; + ], { + constructorArgs: [ + fakeCorePoolComptroller.address, + ethers.constants.AddressZero, + ethers.constants.AddressZero, + ], + })) as RiskFund; await riskFund.setShortfallContractAddress(shortfall.address); @@ -127,7 +135,13 @@ const riskFundFixture = async (): Promise => { protocolShareReserve = (await upgrades.deployProxy(ProtocolShareReserve, [ fakeProtocolIncome.address, riskFund.address, - ])) as ProtocolShareReserve; + ], { + constructorArgs: [ + fakeCorePoolComptroller.address, + ethers.constants.AddressZero, + ethers.constants.AddressZero, + ], + })) as ProtocolShareReserve; const PoolRegistry = await ethers.getContractFactory("PoolRegistry"); poolRegistry = (await upgrades.deployProxy(PoolRegistry, [fakeAccessControlManager.address])) as PoolRegistry; diff --git a/tests/hardhat/ProtocolShareReserve.ts b/tests/hardhat/ProtocolShareReserve.ts index c52f83693..65786b337 100644 --- a/tests/hardhat/ProtocolShareReserve.ts +++ b/tests/hardhat/ProtocolShareReserve.ts @@ -14,6 +14,7 @@ let poolRegistry: FakeContract; let fakeProtocolIncome: FakeContract; let fakeComptroller: FakeContract; let protocolShareReserve: ProtocolShareReserve; +let fakeCorePoolComptroller: FakeContract; const fixture = async (): Promise => { const MockDAI = await ethers.getContractFactory("MockToken"); @@ -29,13 +30,20 @@ const fixture = async (): Promise => { fakeProtocolIncome = await smock.fake("RiskFund"); fakeComptroller = await smock.fake("Comptroller"); + fakeCorePoolComptroller = await smock.fake("Comptroller"); // ProtocolShareReserve contract deployment const ProtocolShareReserve = await ethers.getContractFactory("ProtocolShareReserve"); protocolShareReserve = await upgrades.deployProxy(ProtocolShareReserve, [ fakeProtocolIncome.address, fakeRiskFund.address, - ]); + ], { + constructorArgs: [ + fakeCorePoolComptroller.address, + ethers.constants.AddressZero, + ethers.constants.AddressZero, + ], + }); await protocolShareReserve.setPoolRegistry(poolRegistry.address); }; diff --git a/tests/integration/index.ts b/tests/integration/index.ts index ef2573e35..e8d78e17d 100644 --- a/tests/integration/index.ts +++ b/tests/integration/index.ts @@ -163,7 +163,7 @@ describe("Positive Cases", function () { ); }); - it("PoolRegistry has the required permissions ", async function () { + it.only("PoolRegistry has the required permissions ", async function () { let canCall = await AccessControlManager.connect(Comptroller.address).isAllowedToCall( PoolRegistry.address, "setCollateralFactor(address,uint256,uint256)", From b874469cdfa3f62771ebc354ecb3726c7d9a9370 Mon Sep 17 00:00:00 2001 From: Narayan Prusty Date: Mon, 9 Oct 2023 16:14:30 +0100 Subject: [PATCH 16/33] chore: fixed lint --- contracts/RiskFund/ReserveHelpers.sol | 56 ++++++++++++------------ deploy/014-riskfund-protocolshare.ts | 2 +- helpers/deploymentConfig.ts | 2 +- tests/hardhat/Fork/RiskFund.ts | 61 +++++++++++---------------- tests/hardhat/Fork/RiskFundSwap.ts | 37 ++++++---------- tests/hardhat/ProtocolShareReserve.ts | 17 +++----- 6 files changed, 74 insertions(+), 101 deletions(-) diff --git a/contracts/RiskFund/ReserveHelpers.sol b/contracts/RiskFund/ReserveHelpers.sol index cdd1f9ed2..3bb5cea7d 100644 --- a/contracts/RiskFund/ReserveHelpers.sol +++ b/contracts/RiskFund/ReserveHelpers.sol @@ -71,11 +71,7 @@ contract ReserveHelpers is Ownable2StepUpgradeable { } /// @custom:oz-upgrades-unsafe-allow constructor - constructor( - address corePoolComptroller_, - address vbnb_, - address nativeWrapped_ - ) { + constructor(address corePoolComptroller_, address vbnb_, address nativeWrapped_) { CORE_POOL_COMPTROLLER = corePoolComptroller_; VBNB = vbnb_; NATIVE_WRAPPED = nativeWrapped_; @@ -115,31 +111,6 @@ contract ReserveHelpers is Ownable2StepUpgradeable { return _poolsAssetsReserves[comptroller][asset]; } - function isAssetListedInCore(address tokenAddress) internal view returns (bool isAssetListed) { - VToken[] memory coreMarkets = ComptrollerInterface(CORE_POOL_COMPTROLLER).getAllMarkets(); - - for (uint256 i; i < coreMarkets.length; ++i) { - isAssetListed = (VBNB == address(coreMarkets[i])) - ? (tokenAddress == NATIVE_WRAPPED) - : (coreMarkets[i].underlying() == tokenAddress); - - if (isAssetListed) { - break; - } - } - } - - /// @notice This function checks for the given asset is listed or not - /// @param comptroller Address of the comptroller - /// @param asset Address of the asset - function ensureAssetListed(address comptroller, address asset) internal view returns (bool) { - if (comptroller == CORE_POOL_COMPTROLLER) { - return isAssetListedInCore(asset); - } - - return PoolRegistry(poolRegistry).getVTokenForAsset(comptroller, asset) != address(0); - } - /** * @notice Update the reserve of the asset for the specific pool after transferring to risk fund * and transferring funds to the protocol share reserve @@ -166,4 +137,29 @@ contract ReserveHelpers is Ownable2StepUpgradeable { emit AssetsReservesUpdated(comptroller, asset, balanceDifference); } } + + function isAssetListedInCore(address tokenAddress) internal view returns (bool isAssetListed) { + VToken[] memory coreMarkets = ComptrollerInterface(CORE_POOL_COMPTROLLER).getAllMarkets(); + + for (uint256 i; i < coreMarkets.length; ++i) { + isAssetListed = (VBNB == address(coreMarkets[i])) + ? (tokenAddress == NATIVE_WRAPPED) + : (coreMarkets[i].underlying() == tokenAddress); + + if (isAssetListed) { + break; + } + } + } + + /// @notice This function checks for the given asset is listed or not + /// @param comptroller Address of the comptroller + /// @param asset Address of the asset + function ensureAssetListed(address comptroller, address asset) internal view returns (bool) { + if (comptroller == CORE_POOL_COMPTROLLER) { + return isAssetListedInCore(asset); + } + + return PoolRegistry(poolRegistry).getVTokenForAsset(comptroller, asset) != address(0); + } } diff --git a/deploy/014-riskfund-protocolshare.ts b/deploy/014-riskfund-protocolshare.ts index d4acc54e4..b2a38fa4f 100644 --- a/deploy/014-riskfund-protocolshare.ts +++ b/deploy/014-riskfund-protocolshare.ts @@ -1,7 +1,7 @@ +import { smock } from "@defi-wonderland/smock"; import { ethers } from "hardhat"; import { DeployFunction } from "hardhat-deploy/types"; import { HardhatRuntimeEnvironment } from "hardhat/types"; -import { smock } from "@defi-wonderland/smock"; import { getConfig } from "../helpers/deploymentConfig"; import { getUnderlyingToken, toAddress } from "../helpers/deploymentUtils"; diff --git a/helpers/deploymentConfig.ts b/helpers/deploymentConfig.ts index 1437c2845..a16868136 100644 --- a/helpers/deploymentConfig.ts +++ b/helpers/deploymentConfig.ts @@ -96,7 +96,7 @@ const preconfiguredAddresses = { WBNB: "0xae13d989daC2f0dEbFf460aC112a837C89BAa7cd", VBNB_CorePool: "0x2E7222e51c0f6e98610A1543Aa3836E092CDe62c", SwapRouter_CorePool: "0x83edf1deE1B730b7e8e13C00ba76027D63a51ac0", - Unitroller: "0x94d1820b2D1c7c7452A163983Dc888CEC546b77D" + Unitroller: "0x94d1820b2D1c7c7452A163983Dc888CEC546b77D", }, bscmainnet: { VTreasury: "0xF322942f644A996A617BD29c16bd7d231d9F35E9", diff --git a/tests/hardhat/Fork/RiskFund.ts b/tests/hardhat/Fork/RiskFund.ts index ba20e1bbb..0d812378d 100644 --- a/tests/hardhat/Fork/RiskFund.ts +++ b/tests/hardhat/Fork/RiskFund.ts @@ -131,33 +131,24 @@ const riskFundFixture = async (): Promise => { const fakeCorePoolComptroller = await smock.fake("Comptroller"); const RiskFund = await ethers.getContractFactory("RiskFund"); - riskFund = (await upgrades.deployProxy(RiskFund, [ - pancakeSwapRouter.address, - convertToUnit(10, 18), - BUSD.address, - accessControlManager.address, - 150, - ], { - constructorArgs: [ - fakeCorePoolComptroller.address, - ethers.constants.AddressZero, - ethers.constants.AddressZero, - ], - })) as RiskFund; + riskFund = (await upgrades.deployProxy( + RiskFund, + [pancakeSwapRouter.address, convertToUnit(10, 18), BUSD.address, accessControlManager.address, 150], + { + constructorArgs: [fakeCorePoolComptroller.address, ethers.constants.AddressZero, ethers.constants.AddressZero], + }, + )) as RiskFund; await riskFund.setShortfallContractAddress(shortfall.address); const fakeProtocolIncome = await smock.fake("RiskFund"); const ProtocolShareReserve = await ethers.getContractFactory("ProtocolShareReserve"); - protocolShareReserve = (await upgrades.deployProxy(ProtocolShareReserve, [ - fakeProtocolIncome.address, - riskFund.address, - ], { - constructorArgs: [ - fakeCorePoolComptroller.address, - ethers.constants.AddressZero, - ethers.constants.AddressZero, - ], - })) as ProtocolShareReserve; + protocolShareReserve = (await upgrades.deployProxy( + ProtocolShareReserve, + [fakeProtocolIncome.address, riskFund.address], + { + constructorArgs: [fakeCorePoolComptroller.address, ethers.constants.AddressZero, ethers.constants.AddressZero], + }, + )) as ProtocolShareReserve; const PoolRegistry = await ethers.getContractFactory("PoolRegistry"); poolRegistry = (await upgrades.deployProxy(PoolRegistry, [accessControlManager.address])) as PoolRegistry; @@ -531,19 +522,17 @@ describe("Risk Fund: Tests", function () { const [admin] = await ethers.getSigners(); const RiskFund = await ethers.getContractFactory("RiskFund"); const fakeCorePoolComptroller = await smock.fake("Comptroller"); - const misconfiguredRiskFund = await upgrades.deployProxy(RiskFund, [ - pancakeSwapRouter.address, - convertToUnit(10, 18), - BUSD.address, - accessControlManager.address, - 150, - ], { - constructorArgs: [ - fakeCorePoolComptroller.address, - ethers.constants.AddressZero, - ethers.constants.AddressZero, - ] - }); + const misconfiguredRiskFund = await upgrades.deployProxy( + RiskFund, + [pancakeSwapRouter.address, convertToUnit(10, 18), BUSD.address, accessControlManager.address, 150], + { + constructorArgs: [ + fakeCorePoolComptroller.address, + ethers.constants.AddressZero, + ethers.constants.AddressZero, + ], + }, + ); await accessControlManager.giveCallPermission( misconfiguredRiskFund.address, "swapPoolsAssets(address[],uint256[],address[][],uint256)", diff --git a/tests/hardhat/Fork/RiskFundSwap.ts b/tests/hardhat/Fork/RiskFundSwap.ts index ff1cbdb95..66a0a1b9d 100644 --- a/tests/hardhat/Fork/RiskFundSwap.ts +++ b/tests/hardhat/Fork/RiskFundSwap.ts @@ -114,34 +114,25 @@ const riskFundFixture = async (): Promise => { const fakeCorePoolComptroller = await smock.fake("Comptroller"); const RiskFund = await ethers.getContractFactory("RiskFund"); - riskFund = (await upgrades.deployProxy(RiskFund, [ - pancakeSwapRouter.address, - parseUnits("10", 18), - BUSD.address, - fakeAccessControlManager.address, - maxLoopsLimit, - ], { - constructorArgs: [ - fakeCorePoolComptroller.address, - ethers.constants.AddressZero, - ethers.constants.AddressZero, - ], - })) as RiskFund; + riskFund = (await upgrades.deployProxy( + RiskFund, + [pancakeSwapRouter.address, parseUnits("10", 18), BUSD.address, fakeAccessControlManager.address, maxLoopsLimit], + { + constructorArgs: [fakeCorePoolComptroller.address, ethers.constants.AddressZero, ethers.constants.AddressZero], + }, + )) as RiskFund; await riskFund.setShortfallContractAddress(shortfall.address); const fakeProtocolIncome = await smock.fake("RiskFund"); const ProtocolShareReserve = await ethers.getContractFactory("ProtocolShareReserve"); - protocolShareReserve = (await upgrades.deployProxy(ProtocolShareReserve, [ - fakeProtocolIncome.address, - riskFund.address, - ], { - constructorArgs: [ - fakeCorePoolComptroller.address, - ethers.constants.AddressZero, - ethers.constants.AddressZero, - ], - })) as ProtocolShareReserve; + protocolShareReserve = (await upgrades.deployProxy( + ProtocolShareReserve, + [fakeProtocolIncome.address, riskFund.address], + { + constructorArgs: [fakeCorePoolComptroller.address, ethers.constants.AddressZero, ethers.constants.AddressZero], + }, + )) as ProtocolShareReserve; const PoolRegistry = await ethers.getContractFactory("PoolRegistry"); poolRegistry = (await upgrades.deployProxy(PoolRegistry, [fakeAccessControlManager.address])) as PoolRegistry; diff --git a/tests/hardhat/ProtocolShareReserve.ts b/tests/hardhat/ProtocolShareReserve.ts index 65786b337..164326ee7 100644 --- a/tests/hardhat/ProtocolShareReserve.ts +++ b/tests/hardhat/ProtocolShareReserve.ts @@ -34,16 +34,13 @@ const fixture = async (): Promise => { // ProtocolShareReserve contract deployment const ProtocolShareReserve = await ethers.getContractFactory("ProtocolShareReserve"); - protocolShareReserve = await upgrades.deployProxy(ProtocolShareReserve, [ - fakeProtocolIncome.address, - fakeRiskFund.address, - ], { - constructorArgs: [ - fakeCorePoolComptroller.address, - ethers.constants.AddressZero, - ethers.constants.AddressZero, - ], - }); + protocolShareReserve = await upgrades.deployProxy( + ProtocolShareReserve, + [fakeProtocolIncome.address, fakeRiskFund.address], + { + constructorArgs: [fakeCorePoolComptroller.address, ethers.constants.AddressZero, ethers.constants.AddressZero], + }, + ); await protocolShareReserve.setPoolRegistry(poolRegistry.address); }; From 635e2062bb972e5fa1949b2879d657d715b412d5 Mon Sep 17 00:00:00 2001 From: Narayan Prusty Date: Mon, 9 Oct 2023 17:20:11 +0100 Subject: [PATCH 17/33] fix: fixed tests --- deploy/014-riskfund-protocolshare.ts | 9 +- .../bsctestnet/RiskFund_Implementation.json | 155 ++++++++++++------ .../0c597ac2b90fc7d0b2be179fa6482d23.json | 134 +++++++++++++++ hardhat.config.ts | 9 +- tests/integration/index.ts | 2 +- 5 files changed, 256 insertions(+), 53 deletions(-) create mode 100644 deployments/bsctestnet/solcInputs/0c597ac2b90fc7d0b2be179fa6482d23.json diff --git a/deploy/014-riskfund-protocolshare.ts b/deploy/014-riskfund-protocolshare.ts index b2a38fa4f..b28ccde9b 100644 --- a/deploy/014-riskfund-protocolshare.ts +++ b/deploy/014-riskfund-protocolshare.ts @@ -29,7 +29,10 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { const proxyAdmin = await ethers.getContract("DefaultProxyAdmin"); const owner = await proxyAdmin.owner(); - const fakeCorePoolComptroller = await smock.fake("Comptroller"); + let corePoolComptrollerAddress = preconfiguredAddresses.Unitroller; + if (!hre.network.live) { + corePoolComptrollerAddress = (await smock.fake("Comptroller")).address; + } await deploy("RiskFund", { from: deployer, @@ -46,7 +49,7 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { autoMine: true, log: true, args: [ - preconfiguredAddresses.Unitroller || fakeCorePoolComptroller.address, + corePoolComptrollerAddress, preconfiguredAddresses.VBNB_CorePool || ethers.constants.AddressZero, preconfiguredAddresses.WBNB || ethers.constants.AddressZero, ], @@ -99,7 +102,7 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { autoMine: true, log: true, args: [ - preconfiguredAddresses.Unitroller || fakeCorePoolComptroller.address, + corePoolComptrollerAddress, preconfiguredAddresses.VBNB_CorePool || ethers.constants.AddressZero, preconfiguredAddresses.WBNB || ethers.constants.AddressZero, ], diff --git a/deployments/bsctestnet/RiskFund_Implementation.json b/deployments/bsctestnet/RiskFund_Implementation.json index f8d81b0fb..21f515098 100644 --- a/deployments/bsctestnet/RiskFund_Implementation.json +++ b/deployments/bsctestnet/RiskFund_Implementation.json @@ -1,8 +1,24 @@ { - "address": "0x665085EcC7bc1B59c9872d030f2Bd6c724739709", + "address": "0x4A4Aabf30A3b8F2a262c9e49A343e728Ff07e7F4", "abi": [ { - "inputs": [], + "inputs": [ + { + "internalType": "address", + "name": "corePoolComptroller_", + "type": "address" + }, + { + "internalType": "address", + "name": "vbnb_", + "type": "address" + }, + { + "internalType": "address", + "name": "nativeWrapped_", + "type": "address" + } + ], "stateMutability": "nonpayable", "type": "constructor" }, @@ -331,6 +347,45 @@ "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", @@ -756,39 +811,45 @@ "type": "function" } ], - "transactionHash": "0x955a0c232779cfb36d81d2cc7109fca5904681646f40d398cc1102cfc4fbd8da", + "transactionHash": "0x70250bc04c612fb8c897e5e608ff19ca7e2f52e4249b8ab90da4c87238537d29", "receipt": { "to": null, - "from": "0x2Ce1d0ffD7E869D9DF33e28552b12DdDed326706", - "contractAddress": "0x665085EcC7bc1B59c9872d030f2Bd6c724739709", - "transactionIndex": 3, - "gasUsed": "2577667", - "logsBloom": "0x00000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000400000200000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x0bfdfcabefa0274c2074eb92a0b32ca60efd5db3ae2823d5f14ef82b0bf71782", - "transactionHash": "0x955a0c232779cfb36d81d2cc7109fca5904681646f40d398cc1102cfc4fbd8da", + "from": "0x8BDA9f9E1fEF0DFd404Fef338D9fE4c543d172e1", + "contractAddress": "0x4A4Aabf30A3b8F2a262c9e49A343e728Ff07e7F4", + "transactionIndex": 0, + "gasUsed": "2768629", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xe52bf6228183cde78b49303b2135228dfe5d4b5eac197ed598d9828a140a268a", + "transactionHash": "0x70250bc04c612fb8c897e5e608ff19ca7e2f52e4249b8ab90da4c87238537d29", "logs": [ { - "transactionIndex": 3, - "blockNumber": 33267908, - "transactionHash": "0x955a0c232779cfb36d81d2cc7109fca5904681646f40d398cc1102cfc4fbd8da", - "address": "0x665085EcC7bc1B59c9872d030f2Bd6c724739709", - "topics": ["0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498"], + "transactionIndex": 0, + "blockNumber": 34056841, + "transactionHash": "0x70250bc04c612fb8c897e5e608ff19ca7e2f52e4249b8ab90da4c87238537d29", + "address": "0x4A4Aabf30A3b8F2a262c9e49A343e728Ff07e7F4", + "topics": [ + "0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498" + ], "data": "0x00000000000000000000000000000000000000000000000000000000000000ff", - "logIndex": 1, - "blockHash": "0x0bfdfcabefa0274c2074eb92a0b32ca60efd5db3ae2823d5f14ef82b0bf71782" + "logIndex": 0, + "blockHash": "0xe52bf6228183cde78b49303b2135228dfe5d4b5eac197ed598d9828a140a268a" } ], - "blockNumber": 33267908, - "cumulativeGasUsed": "5977795", + "blockNumber": 34056841, + "cumulativeGasUsed": "2768629", "status": 1, "byzantium": true }, - "args": [], + "args": [ + "0x94d1820b2D1c7c7452A163983Dc888CEC546b77D", + "0x2E7222e51c0f6e98610A1543Aa3836E092CDe62c", + "0xae13d989daC2f0dEbFf460aC112a837C89BAa7cd" + ], "numDeployments": 1, - "solcInputHash": "394b060e0e484d4aa39aea929deecf07", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"ApproveFailed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"loopsLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requiredLoops\",\"type\":\"uint256\"}],\"name\":\"MaxLoopsLimitExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"calledContract\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"methodSignature\",\"type\":\"string\"}],\"name\":\"Unauthorized\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"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\":\"oldConvertibleBaseAsset\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newConvertibleBaseAsset\",\"type\":\"address\"}],\"name\":\"ConvertibleBaseAssetUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldMaxLoopsLimit\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newmaxLoopsLimit\",\"type\":\"uint256\"}],\"name\":\"MaxLoopsLimitUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldMinAmountToConvert\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newMinAmountToConvert\",\"type\":\"uint256\"}],\"name\":\"MinAmountToConvertUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldAccessControlManager\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newAccessControlManager\",\"type\":\"address\"}],\"name\":\"NewAccessControlManager\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferStarted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"oldPancakeSwapRouter\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newPancakeSwapRouter\",\"type\":\"address\"}],\"name\":\"PancakeSwapRouterUpdated\",\"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\":\"oldShortfallContract\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"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\":\"totalAmount\",\"type\":\"uint256\"}],\"name\":\"SwappedPoolsAssets\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"SweepToken\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"TransferredReserveForAuction\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"accessControlManager\",\"outputs\":[{\"internalType\":\"contract IAccessControlManagerV8\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"assetsReserves\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"convertibleBaseAsset\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"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\":\"comptroller\",\"type\":\"address\"}],\"name\":\"getPoolsBaseAssetReserves\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"pancakeSwapRouter_\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmountToConvert_\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"convertibleBaseAsset_\",\"type\":\"address\"},{\"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\":\"minAmountToConvert\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pancakeSwapRouter\",\"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\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"accessControlManager_\",\"type\":\"address\"}],\"name\":\"setAccessControlManager\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_convertibleBaseAsset\",\"type\":\"address\"}],\"name\":\"setConvertibleBaseAsset\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"limit\",\"type\":\"uint256\"}],\"name\":\"setMaxLoopsLimit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minAmountToConvert_\",\"type\":\"uint256\"}],\"name\":\"setMinAmountToConvert\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"pancakeSwapRouter_\",\"type\":\"address\"}],\"name\":\"setPancakeSwapRouter\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"poolRegistry_\",\"type\":\"address\"}],\"name\":\"setPoolRegistry\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"shortfallContractAddress_\",\"type\":\"address\"}],\"name\":\"setShortfallContractAddress\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"shortfall\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"markets\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"amountsOutMin\",\"type\":\"uint256[]\"},{\"internalType\":\"address[][]\",\"name\":\"paths\",\"type\":\"address[][]\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"swapPoolsAssets\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"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\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transferReserveForAuction\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"}],\"name\":\"updateAssetsState\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Venus\",\"details\":\"This contract does not support BNB.\",\"kind\":\"dev\",\"methods\":{\"acceptOwnership()\":{\"details\":\"The new owner accepts the ownership transfer.\"},\"constructor\":{\"custom:oz-upgrades-unsafe-allow\":\"constructor\",\"details\":\"Note that the contract is upgradeable. Use initialize() or reinitializers to set the state variables.\"},\"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.\"}},\"getPoolsBaseAssetReserves(address)\":{\"params\":{\"comptroller\":\"Comptroller address(pool).\"},\"returns\":{\"_0\":\"Base Asset's reserve in risk fund.\"}},\"initialize(address,uint256,address,address,uint256)\":{\"custom:error\":\"ZeroAddressNotAllowed is thrown when PCS router address is zeroZeroAddressNotAllowed is thrown when convertible base asset address is zero\",\"params\":{\"accessControlManager_\":\"Address of the access control contract\",\"convertibleBaseAsset_\":\"Address of the base asset\",\"loopsLimit_\":\"Limit for the loops in the contract to avoid DOS\",\"minAmountToConvert_\":\"Minimum amount assets must be worth to convert into base asset\",\"pancakeSwapRouter_\":\"Address of the PancakeSwap router\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"pendingOwner()\":{\"details\":\"Returns the address of the pending owner.\"},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner.\"},\"setAccessControlManager(address)\":{\"custom:access\":\"Only Governance\",\"custom:event\":\"Emits NewAccessControlManager event\",\"details\":\"Admin function to set address of AccessControlManager\",\"params\":{\"accessControlManager_\":\"The new address of the AccessControlManager\"}},\"setConvertibleBaseAsset(address)\":{\"params\":{\"_convertibleBaseAsset\":\"Address for new convertible base asset.\"}},\"setMaxLoopsLimit(uint256)\":{\"params\":{\"limit\":\"Limit for the max loops can execute at a time\"}},\"setMinAmountToConvert(uint256)\":{\"params\":{\"minAmountToConvert_\":\"Min amount to convert.\"}},\"setPancakeSwapRouter(address)\":{\"custom:error\":\"ZeroAddressNotAllowed is thrown when PCS router address is zero\",\"params\":{\"pancakeSwapRouter_\":\"Address of the PancakeSwap router\"}},\"setPoolRegistry(address)\":{\"custom:error\":\"ZeroAddressNotAllowed is thrown when pool registry address is zero\",\"params\":{\"poolRegistry_\":\"Address of the pool registry\"}},\"setShortfallContractAddress(address)\":{\"custom:error\":\"ZeroAddressNotAllowed is thrown when shortfall contract address is zero\",\"params\":{\"shortfallContractAddress_\":\"Address of the auction contract\"}},\"swapPoolsAssets(address[],uint256[],address[][],uint256)\":{\"custom:error\":\"ZeroAddressNotAllowed is thrown if PoolRegistry contract address is not configured\",\"params\":{\"amountsOutMin\":\"Minimum amount to receive for swap\",\"deadline\":\"Deadline for the swap\",\"markets\":\"Array of vTokens whose assets to swap for base asset\",\"paths\":\"A path consisting of PCS token pairs for each swap\"},\"returns\":{\"_0\":\"Number of swapped tokens\"}},\"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.\"},\"transferReserveForAuction(address,uint256)\":{\"params\":{\"amount\":\"Amount to be transferred to auction contract.\",\"comptroller\":\"Comptroller of the pool.\"},\"returns\":{\"_0\":\"Number reserved tokens.\"}},\"updateAssetsState(address,address)\":{\"params\":{\"asset\":\"Asset address.\",\"comptroller\":\"Comptroller address(pool).\"}}},\"title\":\"RiskFund\",\"version\":1},\"userdoc\":{\"errors\":{\"ApproveFailed()\":[{\"notice\":\"Thrown if a contract is unable to approve a transfer\"}],\"MaxLoopsLimitExceeded(uint256,uint256)\":[{\"notice\":\"Thrown an error on maxLoopsLimit exceeds for any loop\"}],\"Unauthorized(address,address,string)\":[{\"notice\":\"Thrown when the action is prohibited by AccessControlManager\"}],\"ZeroAddressNotAllowed()\":[{\"notice\":\"Thrown if the supplied address is a zero address where it is not allowed\"}]},\"events\":{\"AssetsReservesUpdated(address,address,uint256)\":{\"notice\":\"Event emitted after the update of the assets reserves.\"},\"ConvertibleBaseAssetUpdated(address,address)\":{\"notice\":\"Emitted when convertible base asset is updated\"},\"MaxLoopsLimitUpdated(uint256,uint256)\":{\"notice\":\"Emitted when max loops limit is set\"},\"MinAmountToConvertUpdated(uint256,uint256)\":{\"notice\":\"Emitted when minimum amount to convert is updated\"},\"NewAccessControlManager(address,address)\":{\"notice\":\"Emitted when access control manager contract address is changed\"},\"PancakeSwapRouterUpdated(address,address)\":{\"notice\":\"Emitted when PancakeSwap router contract address is updated\"},\"PoolRegistryUpdated(address,address)\":{\"notice\":\"Emitted when pool registry address is updated\"},\"ShortfallContractUpdated(address,address)\":{\"notice\":\"Emitted when shortfall contract address is updated\"},\"SwappedPoolsAssets(address[],uint256[],uint256)\":{\"notice\":\"Emitted when pools assets are swapped\"},\"SweepToken(address,address,uint256)\":{\"notice\":\"event emitted on sweep token success\"},\"TransferredReserveForAuction(address,uint256)\":{\"notice\":\"Emitted when reserves are transferred for auction\"}},\"kind\":\"user\",\"methods\":{\"accessControlManager()\":{\"notice\":\"Returns the address of the access control manager contract\"},\"getPoolAssetReserve(address,address)\":{\"notice\":\"Get the Amount of the asset in the risk fund for the specific pool.\"},\"getPoolsBaseAssetReserves(address)\":{\"notice\":\"Get the Amount of the Base asset in the risk fund for the specific pool.\"},\"initialize(address,uint256,address,address,uint256)\":{\"notice\":\"Initializes the deployer to owner.\"},\"setAccessControlManager(address)\":{\"notice\":\"Sets the address of AccessControlManager\"},\"setConvertibleBaseAsset(address)\":{\"notice\":\"Sets a new convertible base asset\"},\"setMaxLoopsLimit(uint256)\":{\"notice\":\"Set the limit for the loops can iterate to avoid the DOS\"},\"setMinAmountToConvert(uint256)\":{\"notice\":\"Min amount to convert setter\"},\"setPancakeSwapRouter(address)\":{\"notice\":\"PancakeSwap router address setter\"},\"setPoolRegistry(address)\":{\"notice\":\"Pool registry setter\"},\"setShortfallContractAddress(address)\":{\"notice\":\"Shortfall contract address setter\"},\"swapPoolsAssets(address[],uint256[],address[][],uint256)\":{\"notice\":\"Swap array of pool assets into base asset's tokens of at least a minimum amount\"},\"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\"},\"transferReserveForAuction(address,uint256)\":{\"notice\":\"Transfer tokens for auction.\"},\"updateAssetsState(address,address)\":{\"notice\":\"Update the reserve of the asset for the specific pool after transferring to risk fund.\"}},\"notice\":\"Contract with basic features to track/hold different assets for different Comptrollers.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/RiskFund/RiskFund.sol\":\"RiskFund\"},\"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/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\",\"keccak256\":\"0x7e4d140bd2a5671389ad7a3975b65d05a4f750daf6a61c16139d123d9782b96e\",\"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(\\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\",\"keccak256\":\"0x6b903c298c9e2c3aaed29b4a1f76ace9fc24e50a48db22111bfc190a1a25c499\",\"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/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/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\",\"keccak256\":\"0xb16c27419547f251890c508ee9244b6515f9fd3c35c8ba82f1b485f50dc854c4\",\"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/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\",\"keccak256\":\"0x60505497b334ce53f01cdaeedcee4cfc9dfd153b69e9ceecd165282c9bd2c031\",\"license\":\"MIT\"},\"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": "0x60806040523480156200001157600080fd5b506200001c62000022565b620000e3565b600054610100900460ff16156200008f5760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b60005460ff90811614620000e1576000805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b612d2d80620000f36000396000f3fe608060405234801561001057600080fd5b50600436106101a95760003560e01c806377d4937f116100f9578063afcff50f11610097578063c8ecc0d311610071578063c8ecc0d31461037b578063e30c39781461038f578063f2fde38b146103a0578063fe3da984146103b357600080fd5b8063afcff50f1461034e578063b4a0bdf314610361578063be26317e1461037257600080fd5b806380d45a2d116100d357806380d45a2d146103045780638da5cb5b14610317578063a69bd19e14610328578063aac59a751461033b57600080fd5b806377d4937f146102d657806379ba5097146102e95780637b77cd6a146102f157600080fd5b80632e688141116101665780635f30e37b116101405780635f30e37b146102955780636fb05275146102a8578063715018a6146102bb578063746460a9146102c357600080fd5b80632e6881411461024f578063439b5517146102625780634dd9584a1461028257600080fd5b80630a9837c5146101ae5780630e32cb86146101d457806319b1faef146101e95780632455899514610215578063258836fe146102295780632a1d05471461023c575b600080fd5b6101c16101bc3660046124a8565b6103bd565b6040519081526020015b60405180910390f35b6101e76101e23660046124d4565b61058c565b005b61012e546101fd906001600160a01b031681565b6040516001600160a01b0390911681526020016101cb565b61012f546101fd906001600160a01b031681565b6101e76102373660046124f1565b6105a0565b6101e761024a36600461252a565b610731565b6101e761025d3660046124d4565b610922565b6101c16102703660046124d4565b60c96020526000908152604090205481565b6101e76102903660046124d4565b610a27565b6101c16102a33660046125d1565b610a8b565b6101c16102b63660046124f1565b610fdf565b6101e7611093565b6101e76102d1366004612674565b6110a7565b6101e76102e43660046124d4565b61114c565b6101e76111b0565b6101e76102ff3660046124d4565b611227565b6101e7610312366004612674565b61128a565b6033546001600160a01b03166101fd565b6101c16103363660046124d4565b61129b565b6101e76103493660046124f1565b611387565b60cb546101fd906001600160a01b031681565b6097546001600160a01b03166101fd565b6101c160fb5481565b61012d546101fd906001600160a01b031681565b6065546001600160a01b03166101fd565b6101e76103ae3660046124d4565b611395565b6101c16101305481565b6000600260cc54036103ea5760405162461bcd60e51b81526004016103e19061268d565b60405180910390fd5b600260cc5561012e546001600160a01b03163381146104625760405162461bcd60e51b815260206004820152602e60248201527f5269736b2066756e643a204f6e6c792063616c6c61626c652062792053686f7260448201526d1d19985b1b0818dbdb9d1c9858dd60921b60648201526084016103e1565b6001600160a01b03808516600090815260ca6020908152604080832061012d54909416835292905220548311156104e95760405162461bcd60e51b815260206004820152602560248201527f5269736b2046756e643a20496e73756666696369656e7420706f6f6c2072657360448201526432b93b329760d91b60648201526084016103e1565b6001600160a01b03808516600081815260ca6020908152604080832061012d80548716855290835281842080548a9003905554909416825260c990528290208054869003905590517fc8d0a37ed16dfaa43514df00e18f478b60d5cc7b4bfc687103948b9020f737fd906105609086815260200190565b60405180910390a261012d54610580906001600160a01b03168285611406565b5050600160cc55919050565b61059461145d565b61059d816114b7565b50565b6105a861145d565b600260cc54036105ca5760405162461bcd60e51b81526004016103e19061268d565b600260cc556105d881611575565b6040516370a0823160e01b815230600482015260009081906001600160a01b038516906370a0823190602401602060405180830381865afa158015610621573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061064591906126b1565b6001600160a01b038516600090815260c9602052604090205490915081116106bb5760405162461bcd60e51b815260206004820152602360248201527f5265736572766548656c706572733a205a65726f20737572706c757320746f6b604482015262656e7360e81b60648201526084016103e1565b6001600160a01b03848116600081815260c960209081526040918290205491519185038083529550928616927f6d25be279134f4ecaa4770aff0c3d916d9e7c5ef37b65ed95dbdba411f5d54d5910160405180910390a36107266001600160a01b0385168484611406565b5050600160cc555050565b600054610100900460ff16158080156107515750600054600160ff909116105b8061076b5750303b15801561076b575060005460ff166001145b6107ce5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084016103e1565b6000805460ff1916600117905580156107f1576000805461ff0019166101001790555b6107fa86611575565b61080384611575565b600085116108235760405162461bcd60e51b81526004016103e1906126ca565b600082116108825760405162461bcd60e51b815260206004820152602660248201527f5269736b2046756e643a204c6f6f7073206c696d69742063616e206e6f74206260448201526565207a65726f60d01b60648201526084016103e1565b61088a61159c565b610893836115cb565b61012f80546001600160a01b038089166001600160a01b03199283161790925561013087905561012d8054928716929091169190911790556108d4826115f2565b801561091a576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050565b6109606040518060400160405280602081526020017f736574436f6e7665727469626c6542617365417373657428616464726573732981525061168c565b6001600160a01b0381166109d45760405162461bcd60e51b815260206004820152603560248201527f5269736b2046756e643a206e657720636f6e7665727469626c65206261736520604482015274185cdcd95d081859191c995cdcc81a5b9d985b1a59605a1b60648201526084016103e1565b61012d80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f5fa61583da12070720613fefdd68cc6c0e464a71e009742526bd2b2e0ac62cd290600090a35050565b610a2f61145d565b610a3881611575565b61012f80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907fd37b9d138f53ea58d7e50292588239a46efa8f523966febf4066da96defc77fd90600090a35050565b6000600260cc5403610aaf5760405162461bcd60e51b81526004016103e19061268d565b600260cc81905550610ad8604051806060016040528060388152602001612cc06038913961168c565b42821015610b285760405162461bcd60e51b815260206004820152601a60248201527f5269736b2066756e643a20646561646c696e652070617373656400000000000060448201526064016103e1565b60cb546001600160a01b0316610b3d81611575565b878614610bb25760405162461bcd60e51b815260206004820152603860248201527f5269736b2066756e643a206d61726b65747320616e6420616d6f756e74734f7560448201527f744d696e2061726520756e657175616c206c656e67746873000000000000000060648201526084016103e1565b878414610c1a5760405162461bcd60e51b815260206004820152603060248201527f5269736b2066756e643a206d61726b65747320616e642070617468732061726560448201526f20756e657175616c206c656e6774687360801b60648201526084016103e1565b600088610c2681611726565b60005b81811015610f8c5760008c8c83818110610c4557610c45612712565b9050602002016020810190610c5a91906124d4565b6001600160a01b0316635fe3b5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c97573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cbb9190612728565b604051637aee632d60e01b81526001600160a01b038083166004830152919250600091871690637aee632d90602401600060405180830381865afa158015610d07573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610d2f91908101906127f5565b9050816001600160a01b031681604001516001600160a01b031614610da65760405162461bcd60e51b815260206004820152602760248201527f636f6d7074726f6c6c657220646f65736e277420657869737420706f6f6c20726044820152666567697374727960c81b60648201526084016103e1565b816001600160a01b0316633d98a1e58f8f86818110610dc757610dc7612712565b9050602002016020810190610ddc91906124d4565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa158015610e20573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e4491906128eb565b610e875760405162461bcd60e51b81526020600482015260146024820152731b585c9ad95d081a5cc81b9bdd081b1a5cdd195960621b60448201526064016103e1565b6000610ef68f8f86818110610e9e57610e9e612712565b9050602002016020810190610eb391906124d4565b848f8f88818110610ec657610ec6612712565b905060200201358e8e89818110610edf57610edf612712565b9050602002810190610ef1919061290d565b611757565b6001600160a01b03808516600090815260ca6020908152604080832061012d54909416835292905290812080549293508392909190610f3690849061296d565b909155505061012d546001600160a01b0316600090815260c9602052604081208054839290610f6690849061296d565b90915550610f769050818761296d565b955050505080610f8590612985565b9050610c29565b507fb17530966b045b50d4975e7f05048ca00d7335780c24f1c465165a4b94b2d37d8b8b8b8b86604051610fc49594939291906129e7565b60405180910390a150600160cc559998505050505050505050565b6000610fea82611575565b826001600160a01b0316627e3dd26040518163ffffffff1660e01b8152600401602060405180830381865afa158015611027573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061104b91906128eb565b6110675760405162461bcd60e51b81526004016103e190612a42565b506001600160a01b03918216600090815260ca6020908152604080832093909416825291909152205490565b61109b61145d565b6110a56000611cfa565b565b6110e56040518060400160405280601e81526020017f7365744d696e416d6f756e74546f436f6e766572742875696e7432353629000081525061168c565b600081116111055760405162461bcd60e51b81526004016103e1906126ca565b61013080549082905560408051828152602081018490527fada67d0d38fa20c8ae6a5c17cb9d60b0fe7f2d4e4f27ac9ee55e54ac88de9d8d91015b60405180910390a15050565b61115461145d565b61115d81611575565b61012e80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907fb6e5fcf02f7fbb8acfbaa3bac4fd5abf9ff51e3f2e8884b5498927179b211b2890600090a35050565b60655433906001600160a01b0316811461121e5760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b60648201526084016103e1565b61059d81611cfa565b61122f61145d565b61123881611575565b60cb80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907fa87b964d321035d2165e484ff4b722dd6eae30606c0b98887d2ed1a34e594bfe90600090a35050565b61129261145d565b61059d816115f2565b6000816001600160a01b0316627e3dd26040518163ffffffff1660e01b8152600401602060405180830381865afa1580156112da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112fe91906128eb565b6113595760405162461bcd60e51b815260206004820152602660248201527f5269736b2046756e643a20436f6d7074726f6c6c6572206164647265737320696044820152651b9d985b1a5960d21b60648201526084016103e1565b506001600160a01b03908116600090815260ca6020908152604080832061012d549094168352929052205490565b6113918282611d13565b5050565b61139d61145d565b606580546001600160a01b0383166001600160a01b031990911681179091556113ce6033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b179052611458908490612046565b505050565b6033546001600160a01b031633146110a55760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016103e1565b6001600160a01b03811661151b5760405162461bcd60e51b815260206004820152602560248201527f696e76616c696420616365737320636f6e74726f6c206d616e61676572206164604482015264647265737360d81b60648201526084016103e1565b609780546001600160a01b038381166001600160a01b031983168117909355604080519190921680825260208201939093527f66fd58e82f7b31a2a5c30e0888f3093efe4e111b00cd2b0c31fe014601293aa09101611140565b6001600160a01b03811661059d576040516342bcdf7f60e11b815260040160405180910390fd5b600054610100900460ff166115c35760405162461bcd60e51b81526004016103e190612a8d565b6110a561211b565b600054610100900460ff166105945760405162461bcd60e51b81526004016103e190612a8d565b60fb54811161164e5760405162461bcd60e51b815260206004820152602260248201527f436f6d7074726f6c6c65723a20496e76616c6964206d61784c6f6f70734c696d6044820152611a5d60f21b60648201526084016103e1565b60fb80549082905560408051828152602081018490527fc2d09fef144f7c8a86f71ea459f8fc17f675768eb1ae369cbd77fb31d467aafa9101611140565b6097546040516318c5e8ab60e01b81526000916001600160a01b0316906318c5e8ab906116bf9033908690600401612b04565b602060405180830381865afa1580156116dc573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061170091906128eb565b90508061139157333083604051634a3fa29360e01b81526004016103e193929190612b28565b60fb5481111561059d5760fb5460405163792bfb1b60e11b81526004810191909152602481018290526044016103e1565b6000836000036117cf5760405162461bcd60e51b815260206004820152603c60248201527f5269736b46756e643a20616d6f756e744f75744d696e206d757374206265206760448201527f726561746572207468616e203020746f20737761702076546f6b656e0000000060648201526084016103e1565b600080876001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa158015611810573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118349190612728565b61012d546001600160a01b03898116600090815260ca6020908152604080832084871684529091528120549394509116919081900361187a576000945050505050611cf1565b6000896001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa1580156118ba573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118de9190612728565b60405163b62cad6960e01b81526001600160a01b0385811660048301529192509082169063b62cad6990602401600060405180830381600087803b15801561192557600080fd5b505af1158015611939573d6000803e3d6000fd5b50506040805160208101918290526341976e0960e01b9091526001600160a01b03868116602483015260009350909150819084166341976e0960448301602060405180830381865afa158015611993573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119b791906126b1565b9052905060006119c7828c61214b565b905061013054811015611a2a5760405162461bcd60e51b815260206004820152602560248201527f5269736b46756e643a206d696e416d6f756e74546f436f6e766572742076696f6044820152641b185d195960da1b60648201526084016103e1565b6001600160a01b038616600090815260c9602052604081208054869290611a52908490612b54565b90915550506001600160a01b03808d16600090815260ca60209081526040808320938a1683529290529081208054869290611a8e908490612b54565b90915550506001600160a01b0386811690861614611ce357856001600160a01b03168a8a6000818110611ac357611ac3612712565b9050602002016020810190611ad891906124d4565b6001600160a01b031614611b545760405162461bcd60e51b815260206004820152603860248201527f5269736b46756e643a20737761702070617468206d757374207374617274207760448201527f6974682074686520756e6465726c79696e67206173736574000000000000000060648201526084016103e1565b6001600160a01b0385168a8a611b6b600182612b54565b818110611b7a57611b7a612712565b9050602002016020810190611b8f91906124d4565b6001600160a01b031614611c035760405162461bcd60e51b815260206004820152603560248201527f5269736b46756e643a2066696e616c6c792070617468206d75737420626520636044820152741bdb9d995c9d1a589b194818985cd948185cdcd95d605a1b60648201526084016103e1565b61012f546001600160a01b0390811690611c2190881682600061216b565b611c356001600160a01b038816828761216b565b6000816001600160a01b03166338ed1739878f8f8f30426040518763ffffffff1660e01b8152600401611c6d96959493929190612b6b565b6000604051808303816000875af1158015611c8c573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611cb49190810190612ba9565b905080611cc260018d612b54565b81518110611cd257611cd2612712565b602002602001015198505050611ce7565b8396505b5094955050505050505b95945050505050565b606580546001600160a01b031916905561059d81612257565b611d1c81611575565b816001600160a01b0316627e3dd26040518163ffffffff1660e01b8152600401602060405180830381865afa158015611d59573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d7d91906128eb565b611d995760405162461bcd60e51b81526004016103e190612a42565b60cb546001600160a01b031680611e0b5760405162461bcd60e51b815260206004820152603060248201527f5265736572766548656c706572733a20506f6f6c20526567697374727920616460448201526f191c995cdcc81a5cc81b9bdd081cd95d60821b60648201526084016103e1565b60405163266e0a7f60e01b81526001600160a01b03848116600483015283811660248301526000919083169063266e0a7f90604401602060405180830381865afa158015611e5d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e819190612728565b6001600160a01b031603611ef25760405162461bcd60e51b815260206004820152603260248201527f5265736572766548656c706572733a2054686520706f6f6c20646f65736e2774604482015271081cdd5c1c1bdc9d081d1a1948185cdcd95d60721b60648201526084016103e1565b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa158015611f39573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f5d91906126b1565b6001600160a01b038416600090815260c960205260409020549091508082111561203f576001600160a01b038416600090815260c960205260408120805483850392839291611fad90849061296d565b90915550506001600160a01b03808716600090815260ca6020908152604080832093891683529290529081208054839290611fe990849061296d565b92505081905550846001600160a01b0316866001600160a01b03167fc39e3e80c0219fde334a8cb5d8468b628482e23388b6e809c90cb00c63c8ce388360405161203591815260200190565b60405180910390a3505b5050505050565b600061209b826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166122a99092919063ffffffff16565b90508051600014806120bc5750808060200190518101906120bc91906128eb565b6114585760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b60648201526084016103e1565b600054610100900460ff166121425760405162461bcd60e51b81526004016103e190612a8d565b6110a533611cfa565b60008061215884846122b8565b9050612163816122e9565b949350505050565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663095ea7b360e01b1790529151909160009182918716906121c9908590612c4f565b6000604051808303816000865af19150503d8060008114612206576040519150601f19603f3d011682016040523d82523d6000602084013e61220b565b606091505b5091509150811580612239575080511580159061223957508080602001905181019061223791906128eb565b155b1561091a57604051633e3f8f7360e01b815260040160405180910390fd5b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60606121638484600085612307565b60408051602081019091526000815260405180602001604052806122e08560000151856123e2565b90529392505050565b805160009061230190670de0b6b3a764000090612c6b565b92915050565b6060824710156123685760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b60648201526084016103e1565b600080866001600160a01b031685876040516123849190612c4f565b60006040518083038185875af1925050503d80600081146123c1576040519150601f19603f3d011682016040523d82523d6000602084013e6123c6565b606091505b50915091506123d7878383876123f5565b979650505050505050565b60006123ee8284612c8d565b9392505050565b6060831561246457825160000361245d576001600160a01b0385163b61245d5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016103e1565b5081612163565b61216383838151156124795781518083602001fd5b8060405162461bcd60e51b81526004016103e19190612cac565b6001600160a01b038116811461059d57600080fd5b600080604083850312156124bb57600080fd5b82356124c681612493565b946020939093013593505050565b6000602082840312156124e657600080fd5b81356123ee81612493565b6000806040838503121561250457600080fd5b823561250f81612493565b9150602083013561251f81612493565b809150509250929050565b600080600080600060a0868803121561254257600080fd5b853561254d81612493565b945060208601359350604086013561256481612493565b9250606086013561257481612493565b949793965091946080013592915050565b60008083601f84011261259757600080fd5b50813567ffffffffffffffff8111156125af57600080fd5b6020830191508360208260051b85010111156125ca57600080fd5b9250929050565b60008060008060008060006080888a0312156125ec57600080fd5b873567ffffffffffffffff8082111561260457600080fd5b6126108b838c01612585565b909950975060208a013591508082111561262957600080fd5b6126358b838c01612585565b909750955060408a013591508082111561264e57600080fd5b5061265b8a828b01612585565b989b979a50959894979596606090950135949350505050565b60006020828403121561268657600080fd5b5035919050565b6020808252600a90820152691c994b595b9d195c995960b21b604082015260600190565b6000602082840312156126c357600080fd5b5051919050565b60208082526028908201527f5269736b2046756e643a20496e76616c6964206d696e20616d6f756e7420746f6040820152670818dbdb9d995c9d60c21b606082015260800190565b634e487b7160e01b600052603260045260246000fd5b60006020828403121561273a57600080fd5b81516123ee81612493565b634e487b7160e01b600052604160045260246000fd5b60405160a0810167ffffffffffffffff8111828210171561277e5761277e612745565b60405290565b604051601f8201601f1916810167ffffffffffffffff811182821017156127ad576127ad612745565b604052919050565b60005b838110156127d05781810151838201526020016127b8565b838111156127df576000848401525b50505050565b80516127f081612493565b919050565b6000602080838503121561280857600080fd5b825167ffffffffffffffff8082111561282057600080fd5b9084019060a0828703121561283457600080fd5b61283c61275b565b82518281111561284b57600080fd5b8301601f8101881361285c57600080fd5b80518381111561286e5761286e612745565b612880601f8201601f19168701612784565b9350808452888682840101111561289657600080fd5b6128a5818786018885016127b5565b50508181526128b58484016127e5565b848201526128c5604084016127e5565b604082015260608301516060820152608083015160808201528094505050505092915050565b6000602082840312156128fd57600080fd5b815180151581146123ee57600080fd5b6000808335601e1984360301811261292457600080fd5b83018035915067ffffffffffffffff82111561293f57600080fd5b6020019150600581901b36038213156125ca57600080fd5b634e487b7160e01b600052601160045260246000fd5b6000821982111561298057612980612957565b500190565b60006001820161299757612997612957565b5060010190565b8183526000602080850194508260005b858110156129dc5781356129c181612493565b6001600160a01b0316875295820195908201906001016129ae565b509495945050505050565b6060815260006129fb60608301878961299e565b82810360208401528481526001600160fb1b03851115612a1a57600080fd5b8460051b80876020840137600091016020019081526040929092019290925295945050505050565b6020808252602b908201527f5265736572766548656c706572733a20436f6d7074726f6c6c6572206164647260408201526a195cdcc81a5b9d985b1a5960aa1b606082015260800190565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b60008151808452612af08160208601602086016127b5565b601f01601f19169290920160200192915050565b6001600160a01b038316815260406020820181905260009061216390830184612ad8565b6001600160a01b03848116825283166020820152606060408201819052600090611cf190830184612ad8565b600082821015612b6657612b66612957565b500390565b86815285602082015260a060408201526000612b8b60a08301868861299e565b6001600160a01b039490941660608301525060800152949350505050565b60006020808385031215612bbc57600080fd5b825167ffffffffffffffff80821115612bd457600080fd5b818501915085601f830112612be857600080fd5b815181811115612bfa57612bfa612745565b8060051b9150612c0b848301612784565b8181529183018401918481019088841115612c2557600080fd5b938501935b83851015612c4357845182529385019390850190612c2a565b98975050505050505050565b60008251612c618184602087016127b5565b9190910192915050565b600082612c8857634e487b7160e01b600052601260045260246000fd5b500490565b6000816000190483118215151615612ca757612ca7612957565b500290565b6020815260006123ee6020830184612ad856fe73776170506f6f6c7341737365747328616464726573735b5d2c75696e743235365b5d2c616464726573735b5d5b5d2c75696e7432353629a26469706673582212200df4784c551e6f296a40813ffbdb6c465608d0b9582f5f659a9257b405a4147e64736f6c634300080d0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101a95760003560e01c806377d4937f116100f9578063afcff50f11610097578063c8ecc0d311610071578063c8ecc0d31461037b578063e30c39781461038f578063f2fde38b146103a0578063fe3da984146103b357600080fd5b8063afcff50f1461034e578063b4a0bdf314610361578063be26317e1461037257600080fd5b806380d45a2d116100d357806380d45a2d146103045780638da5cb5b14610317578063a69bd19e14610328578063aac59a751461033b57600080fd5b806377d4937f146102d657806379ba5097146102e95780637b77cd6a146102f157600080fd5b80632e688141116101665780635f30e37b116101405780635f30e37b146102955780636fb05275146102a8578063715018a6146102bb578063746460a9146102c357600080fd5b80632e6881411461024f578063439b5517146102625780634dd9584a1461028257600080fd5b80630a9837c5146101ae5780630e32cb86146101d457806319b1faef146101e95780632455899514610215578063258836fe146102295780632a1d05471461023c575b600080fd5b6101c16101bc3660046124a8565b6103bd565b6040519081526020015b60405180910390f35b6101e76101e23660046124d4565b61058c565b005b61012e546101fd906001600160a01b031681565b6040516001600160a01b0390911681526020016101cb565b61012f546101fd906001600160a01b031681565b6101e76102373660046124f1565b6105a0565b6101e761024a36600461252a565b610731565b6101e761025d3660046124d4565b610922565b6101c16102703660046124d4565b60c96020526000908152604090205481565b6101e76102903660046124d4565b610a27565b6101c16102a33660046125d1565b610a8b565b6101c16102b63660046124f1565b610fdf565b6101e7611093565b6101e76102d1366004612674565b6110a7565b6101e76102e43660046124d4565b61114c565b6101e76111b0565b6101e76102ff3660046124d4565b611227565b6101e7610312366004612674565b61128a565b6033546001600160a01b03166101fd565b6101c16103363660046124d4565b61129b565b6101e76103493660046124f1565b611387565b60cb546101fd906001600160a01b031681565b6097546001600160a01b03166101fd565b6101c160fb5481565b61012d546101fd906001600160a01b031681565b6065546001600160a01b03166101fd565b6101e76103ae3660046124d4565b611395565b6101c16101305481565b6000600260cc54036103ea5760405162461bcd60e51b81526004016103e19061268d565b60405180910390fd5b600260cc5561012e546001600160a01b03163381146104625760405162461bcd60e51b815260206004820152602e60248201527f5269736b2066756e643a204f6e6c792063616c6c61626c652062792053686f7260448201526d1d19985b1b0818dbdb9d1c9858dd60921b60648201526084016103e1565b6001600160a01b03808516600090815260ca6020908152604080832061012d54909416835292905220548311156104e95760405162461bcd60e51b815260206004820152602560248201527f5269736b2046756e643a20496e73756666696369656e7420706f6f6c2072657360448201526432b93b329760d91b60648201526084016103e1565b6001600160a01b03808516600081815260ca6020908152604080832061012d80548716855290835281842080548a9003905554909416825260c990528290208054869003905590517fc8d0a37ed16dfaa43514df00e18f478b60d5cc7b4bfc687103948b9020f737fd906105609086815260200190565b60405180910390a261012d54610580906001600160a01b03168285611406565b5050600160cc55919050565b61059461145d565b61059d816114b7565b50565b6105a861145d565b600260cc54036105ca5760405162461bcd60e51b81526004016103e19061268d565b600260cc556105d881611575565b6040516370a0823160e01b815230600482015260009081906001600160a01b038516906370a0823190602401602060405180830381865afa158015610621573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061064591906126b1565b6001600160a01b038516600090815260c9602052604090205490915081116106bb5760405162461bcd60e51b815260206004820152602360248201527f5265736572766548656c706572733a205a65726f20737572706c757320746f6b604482015262656e7360e81b60648201526084016103e1565b6001600160a01b03848116600081815260c960209081526040918290205491519185038083529550928616927f6d25be279134f4ecaa4770aff0c3d916d9e7c5ef37b65ed95dbdba411f5d54d5910160405180910390a36107266001600160a01b0385168484611406565b5050600160cc555050565b600054610100900460ff16158080156107515750600054600160ff909116105b8061076b5750303b15801561076b575060005460ff166001145b6107ce5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084016103e1565b6000805460ff1916600117905580156107f1576000805461ff0019166101001790555b6107fa86611575565b61080384611575565b600085116108235760405162461bcd60e51b81526004016103e1906126ca565b600082116108825760405162461bcd60e51b815260206004820152602660248201527f5269736b2046756e643a204c6f6f7073206c696d69742063616e206e6f74206260448201526565207a65726f60d01b60648201526084016103e1565b61088a61159c565b610893836115cb565b61012f80546001600160a01b038089166001600160a01b03199283161790925561013087905561012d8054928716929091169190911790556108d4826115f2565b801561091a576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050565b6109606040518060400160405280602081526020017f736574436f6e7665727469626c6542617365417373657428616464726573732981525061168c565b6001600160a01b0381166109d45760405162461bcd60e51b815260206004820152603560248201527f5269736b2046756e643a206e657720636f6e7665727469626c65206261736520604482015274185cdcd95d081859191c995cdcc81a5b9d985b1a59605a1b60648201526084016103e1565b61012d80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f5fa61583da12070720613fefdd68cc6c0e464a71e009742526bd2b2e0ac62cd290600090a35050565b610a2f61145d565b610a3881611575565b61012f80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907fd37b9d138f53ea58d7e50292588239a46efa8f523966febf4066da96defc77fd90600090a35050565b6000600260cc5403610aaf5760405162461bcd60e51b81526004016103e19061268d565b600260cc81905550610ad8604051806060016040528060388152602001612cc06038913961168c565b42821015610b285760405162461bcd60e51b815260206004820152601a60248201527f5269736b2066756e643a20646561646c696e652070617373656400000000000060448201526064016103e1565b60cb546001600160a01b0316610b3d81611575565b878614610bb25760405162461bcd60e51b815260206004820152603860248201527f5269736b2066756e643a206d61726b65747320616e6420616d6f756e74734f7560448201527f744d696e2061726520756e657175616c206c656e67746873000000000000000060648201526084016103e1565b878414610c1a5760405162461bcd60e51b815260206004820152603060248201527f5269736b2066756e643a206d61726b65747320616e642070617468732061726560448201526f20756e657175616c206c656e6774687360801b60648201526084016103e1565b600088610c2681611726565b60005b81811015610f8c5760008c8c83818110610c4557610c45612712565b9050602002016020810190610c5a91906124d4565b6001600160a01b0316635fe3b5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c97573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cbb9190612728565b604051637aee632d60e01b81526001600160a01b038083166004830152919250600091871690637aee632d90602401600060405180830381865afa158015610d07573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610d2f91908101906127f5565b9050816001600160a01b031681604001516001600160a01b031614610da65760405162461bcd60e51b815260206004820152602760248201527f636f6d7074726f6c6c657220646f65736e277420657869737420706f6f6c20726044820152666567697374727960c81b60648201526084016103e1565b816001600160a01b0316633d98a1e58f8f86818110610dc757610dc7612712565b9050602002016020810190610ddc91906124d4565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa158015610e20573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e4491906128eb565b610e875760405162461bcd60e51b81526020600482015260146024820152731b585c9ad95d081a5cc81b9bdd081b1a5cdd195960621b60448201526064016103e1565b6000610ef68f8f86818110610e9e57610e9e612712565b9050602002016020810190610eb391906124d4565b848f8f88818110610ec657610ec6612712565b905060200201358e8e89818110610edf57610edf612712565b9050602002810190610ef1919061290d565b611757565b6001600160a01b03808516600090815260ca6020908152604080832061012d54909416835292905290812080549293508392909190610f3690849061296d565b909155505061012d546001600160a01b0316600090815260c9602052604081208054839290610f6690849061296d565b90915550610f769050818761296d565b955050505080610f8590612985565b9050610c29565b507fb17530966b045b50d4975e7f05048ca00d7335780c24f1c465165a4b94b2d37d8b8b8b8b86604051610fc49594939291906129e7565b60405180910390a150600160cc559998505050505050505050565b6000610fea82611575565b826001600160a01b0316627e3dd26040518163ffffffff1660e01b8152600401602060405180830381865afa158015611027573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061104b91906128eb565b6110675760405162461bcd60e51b81526004016103e190612a42565b506001600160a01b03918216600090815260ca6020908152604080832093909416825291909152205490565b61109b61145d565b6110a56000611cfa565b565b6110e56040518060400160405280601e81526020017f7365744d696e416d6f756e74546f436f6e766572742875696e7432353629000081525061168c565b600081116111055760405162461bcd60e51b81526004016103e1906126ca565b61013080549082905560408051828152602081018490527fada67d0d38fa20c8ae6a5c17cb9d60b0fe7f2d4e4f27ac9ee55e54ac88de9d8d91015b60405180910390a15050565b61115461145d565b61115d81611575565b61012e80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907fb6e5fcf02f7fbb8acfbaa3bac4fd5abf9ff51e3f2e8884b5498927179b211b2890600090a35050565b60655433906001600160a01b0316811461121e5760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b60648201526084016103e1565b61059d81611cfa565b61122f61145d565b61123881611575565b60cb80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907fa87b964d321035d2165e484ff4b722dd6eae30606c0b98887d2ed1a34e594bfe90600090a35050565b61129261145d565b61059d816115f2565b6000816001600160a01b0316627e3dd26040518163ffffffff1660e01b8152600401602060405180830381865afa1580156112da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112fe91906128eb565b6113595760405162461bcd60e51b815260206004820152602660248201527f5269736b2046756e643a20436f6d7074726f6c6c6572206164647265737320696044820152651b9d985b1a5960d21b60648201526084016103e1565b506001600160a01b03908116600090815260ca6020908152604080832061012d549094168352929052205490565b6113918282611d13565b5050565b61139d61145d565b606580546001600160a01b0383166001600160a01b031990911681179091556113ce6033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b179052611458908490612046565b505050565b6033546001600160a01b031633146110a55760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016103e1565b6001600160a01b03811661151b5760405162461bcd60e51b815260206004820152602560248201527f696e76616c696420616365737320636f6e74726f6c206d616e61676572206164604482015264647265737360d81b60648201526084016103e1565b609780546001600160a01b038381166001600160a01b031983168117909355604080519190921680825260208201939093527f66fd58e82f7b31a2a5c30e0888f3093efe4e111b00cd2b0c31fe014601293aa09101611140565b6001600160a01b03811661059d576040516342bcdf7f60e11b815260040160405180910390fd5b600054610100900460ff166115c35760405162461bcd60e51b81526004016103e190612a8d565b6110a561211b565b600054610100900460ff166105945760405162461bcd60e51b81526004016103e190612a8d565b60fb54811161164e5760405162461bcd60e51b815260206004820152602260248201527f436f6d7074726f6c6c65723a20496e76616c6964206d61784c6f6f70734c696d6044820152611a5d60f21b60648201526084016103e1565b60fb80549082905560408051828152602081018490527fc2d09fef144f7c8a86f71ea459f8fc17f675768eb1ae369cbd77fb31d467aafa9101611140565b6097546040516318c5e8ab60e01b81526000916001600160a01b0316906318c5e8ab906116bf9033908690600401612b04565b602060405180830381865afa1580156116dc573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061170091906128eb565b90508061139157333083604051634a3fa29360e01b81526004016103e193929190612b28565b60fb5481111561059d5760fb5460405163792bfb1b60e11b81526004810191909152602481018290526044016103e1565b6000836000036117cf5760405162461bcd60e51b815260206004820152603c60248201527f5269736b46756e643a20616d6f756e744f75744d696e206d757374206265206760448201527f726561746572207468616e203020746f20737761702076546f6b656e0000000060648201526084016103e1565b600080876001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa158015611810573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118349190612728565b61012d546001600160a01b03898116600090815260ca6020908152604080832084871684529091528120549394509116919081900361187a576000945050505050611cf1565b6000896001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa1580156118ba573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118de9190612728565b60405163b62cad6960e01b81526001600160a01b0385811660048301529192509082169063b62cad6990602401600060405180830381600087803b15801561192557600080fd5b505af1158015611939573d6000803e3d6000fd5b50506040805160208101918290526341976e0960e01b9091526001600160a01b03868116602483015260009350909150819084166341976e0960448301602060405180830381865afa158015611993573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119b791906126b1565b9052905060006119c7828c61214b565b905061013054811015611a2a5760405162461bcd60e51b815260206004820152602560248201527f5269736b46756e643a206d696e416d6f756e74546f436f6e766572742076696f6044820152641b185d195960da1b60648201526084016103e1565b6001600160a01b038616600090815260c9602052604081208054869290611a52908490612b54565b90915550506001600160a01b03808d16600090815260ca60209081526040808320938a1683529290529081208054869290611a8e908490612b54565b90915550506001600160a01b0386811690861614611ce357856001600160a01b03168a8a6000818110611ac357611ac3612712565b9050602002016020810190611ad891906124d4565b6001600160a01b031614611b545760405162461bcd60e51b815260206004820152603860248201527f5269736b46756e643a20737761702070617468206d757374207374617274207760448201527f6974682074686520756e6465726c79696e67206173736574000000000000000060648201526084016103e1565b6001600160a01b0385168a8a611b6b600182612b54565b818110611b7a57611b7a612712565b9050602002016020810190611b8f91906124d4565b6001600160a01b031614611c035760405162461bcd60e51b815260206004820152603560248201527f5269736b46756e643a2066696e616c6c792070617468206d75737420626520636044820152741bdb9d995c9d1a589b194818985cd948185cdcd95d605a1b60648201526084016103e1565b61012f546001600160a01b0390811690611c2190881682600061216b565b611c356001600160a01b038816828761216b565b6000816001600160a01b03166338ed1739878f8f8f30426040518763ffffffff1660e01b8152600401611c6d96959493929190612b6b565b6000604051808303816000875af1158015611c8c573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611cb49190810190612ba9565b905080611cc260018d612b54565b81518110611cd257611cd2612712565b602002602001015198505050611ce7565b8396505b5094955050505050505b95945050505050565b606580546001600160a01b031916905561059d81612257565b611d1c81611575565b816001600160a01b0316627e3dd26040518163ffffffff1660e01b8152600401602060405180830381865afa158015611d59573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d7d91906128eb565b611d995760405162461bcd60e51b81526004016103e190612a42565b60cb546001600160a01b031680611e0b5760405162461bcd60e51b815260206004820152603060248201527f5265736572766548656c706572733a20506f6f6c20526567697374727920616460448201526f191c995cdcc81a5cc81b9bdd081cd95d60821b60648201526084016103e1565b60405163266e0a7f60e01b81526001600160a01b03848116600483015283811660248301526000919083169063266e0a7f90604401602060405180830381865afa158015611e5d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e819190612728565b6001600160a01b031603611ef25760405162461bcd60e51b815260206004820152603260248201527f5265736572766548656c706572733a2054686520706f6f6c20646f65736e2774604482015271081cdd5c1c1bdc9d081d1a1948185cdcd95d60721b60648201526084016103e1565b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa158015611f39573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f5d91906126b1565b6001600160a01b038416600090815260c960205260409020549091508082111561203f576001600160a01b038416600090815260c960205260408120805483850392839291611fad90849061296d565b90915550506001600160a01b03808716600090815260ca6020908152604080832093891683529290529081208054839290611fe990849061296d565b92505081905550846001600160a01b0316866001600160a01b03167fc39e3e80c0219fde334a8cb5d8468b628482e23388b6e809c90cb00c63c8ce388360405161203591815260200190565b60405180910390a3505b5050505050565b600061209b826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166122a99092919063ffffffff16565b90508051600014806120bc5750808060200190518101906120bc91906128eb565b6114585760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b60648201526084016103e1565b600054610100900460ff166121425760405162461bcd60e51b81526004016103e190612a8d565b6110a533611cfa565b60008061215884846122b8565b9050612163816122e9565b949350505050565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663095ea7b360e01b1790529151909160009182918716906121c9908590612c4f565b6000604051808303816000865af19150503d8060008114612206576040519150601f19603f3d011682016040523d82523d6000602084013e61220b565b606091505b5091509150811580612239575080511580159061223957508080602001905181019061223791906128eb565b155b1561091a57604051633e3f8f7360e01b815260040160405180910390fd5b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60606121638484600085612307565b60408051602081019091526000815260405180602001604052806122e08560000151856123e2565b90529392505050565b805160009061230190670de0b6b3a764000090612c6b565b92915050565b6060824710156123685760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b60648201526084016103e1565b600080866001600160a01b031685876040516123849190612c4f565b60006040518083038185875af1925050503d80600081146123c1576040519150601f19603f3d011682016040523d82523d6000602084013e6123c6565b606091505b50915091506123d7878383876123f5565b979650505050505050565b60006123ee8284612c8d565b9392505050565b6060831561246457825160000361245d576001600160a01b0385163b61245d5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016103e1565b5081612163565b61216383838151156124795781518083602001fd5b8060405162461bcd60e51b81526004016103e19190612cac565b6001600160a01b038116811461059d57600080fd5b600080604083850312156124bb57600080fd5b82356124c681612493565b946020939093013593505050565b6000602082840312156124e657600080fd5b81356123ee81612493565b6000806040838503121561250457600080fd5b823561250f81612493565b9150602083013561251f81612493565b809150509250929050565b600080600080600060a0868803121561254257600080fd5b853561254d81612493565b945060208601359350604086013561256481612493565b9250606086013561257481612493565b949793965091946080013592915050565b60008083601f84011261259757600080fd5b50813567ffffffffffffffff8111156125af57600080fd5b6020830191508360208260051b85010111156125ca57600080fd5b9250929050565b60008060008060008060006080888a0312156125ec57600080fd5b873567ffffffffffffffff8082111561260457600080fd5b6126108b838c01612585565b909950975060208a013591508082111561262957600080fd5b6126358b838c01612585565b909750955060408a013591508082111561264e57600080fd5b5061265b8a828b01612585565b989b979a50959894979596606090950135949350505050565b60006020828403121561268657600080fd5b5035919050565b6020808252600a90820152691c994b595b9d195c995960b21b604082015260600190565b6000602082840312156126c357600080fd5b5051919050565b60208082526028908201527f5269736b2046756e643a20496e76616c6964206d696e20616d6f756e7420746f6040820152670818dbdb9d995c9d60c21b606082015260800190565b634e487b7160e01b600052603260045260246000fd5b60006020828403121561273a57600080fd5b81516123ee81612493565b634e487b7160e01b600052604160045260246000fd5b60405160a0810167ffffffffffffffff8111828210171561277e5761277e612745565b60405290565b604051601f8201601f1916810167ffffffffffffffff811182821017156127ad576127ad612745565b604052919050565b60005b838110156127d05781810151838201526020016127b8565b838111156127df576000848401525b50505050565b80516127f081612493565b919050565b6000602080838503121561280857600080fd5b825167ffffffffffffffff8082111561282057600080fd5b9084019060a0828703121561283457600080fd5b61283c61275b565b82518281111561284b57600080fd5b8301601f8101881361285c57600080fd5b80518381111561286e5761286e612745565b612880601f8201601f19168701612784565b9350808452888682840101111561289657600080fd5b6128a5818786018885016127b5565b50508181526128b58484016127e5565b848201526128c5604084016127e5565b604082015260608301516060820152608083015160808201528094505050505092915050565b6000602082840312156128fd57600080fd5b815180151581146123ee57600080fd5b6000808335601e1984360301811261292457600080fd5b83018035915067ffffffffffffffff82111561293f57600080fd5b6020019150600581901b36038213156125ca57600080fd5b634e487b7160e01b600052601160045260246000fd5b6000821982111561298057612980612957565b500190565b60006001820161299757612997612957565b5060010190565b8183526000602080850194508260005b858110156129dc5781356129c181612493565b6001600160a01b0316875295820195908201906001016129ae565b509495945050505050565b6060815260006129fb60608301878961299e565b82810360208401528481526001600160fb1b03851115612a1a57600080fd5b8460051b80876020840137600091016020019081526040929092019290925295945050505050565b6020808252602b908201527f5265736572766548656c706572733a20436f6d7074726f6c6c6572206164647260408201526a195cdcc81a5b9d985b1a5960aa1b606082015260800190565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b60008151808452612af08160208601602086016127b5565b601f01601f19169290920160200192915050565b6001600160a01b038316815260406020820181905260009061216390830184612ad8565b6001600160a01b03848116825283166020820152606060408201819052600090611cf190830184612ad8565b600082821015612b6657612b66612957565b500390565b86815285602082015260a060408201526000612b8b60a08301868861299e565b6001600160a01b039490941660608301525060800152949350505050565b60006020808385031215612bbc57600080fd5b825167ffffffffffffffff80821115612bd457600080fd5b818501915085601f830112612be857600080fd5b815181811115612bfa57612bfa612745565b8060051b9150612c0b848301612784565b8181529183018401918481019088841115612c2557600080fd5b938501935b83851015612c4357845182529385019390850190612c2a565b98975050505050505050565b60008251612c618184602087016127b5565b9190910192915050565b600082612c8857634e487b7160e01b600052601260045260246000fd5b500490565b6000816000190483118215151615612ca757612ca7612957565b500290565b6020815260006123ee6020830184612ad856fe73776170506f6f6c7341737365747328616464726573735b5d2c75696e743235365b5d2c616464726573735b5d5b5d2c75696e7432353629a26469706673582212200df4784c551e6f296a40813ffbdb6c465608d0b9582f5f659a9257b405a4147e64736f6c634300080d0033", + "solcInputHash": "0c597ac2b90fc7d0b2be179fa6482d23", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"corePoolComptroller_\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"vbnb_\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nativeWrapped_\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"ApproveFailed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"loopsLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requiredLoops\",\"type\":\"uint256\"}],\"name\":\"MaxLoopsLimitExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"calledContract\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"methodSignature\",\"type\":\"string\"}],\"name\":\"Unauthorized\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"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\":\"oldConvertibleBaseAsset\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newConvertibleBaseAsset\",\"type\":\"address\"}],\"name\":\"ConvertibleBaseAssetUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldMaxLoopsLimit\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newmaxLoopsLimit\",\"type\":\"uint256\"}],\"name\":\"MaxLoopsLimitUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldMinAmountToConvert\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newMinAmountToConvert\",\"type\":\"uint256\"}],\"name\":\"MinAmountToConvertUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldAccessControlManager\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newAccessControlManager\",\"type\":\"address\"}],\"name\":\"NewAccessControlManager\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferStarted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"oldPancakeSwapRouter\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newPancakeSwapRouter\",\"type\":\"address\"}],\"name\":\"PancakeSwapRouterUpdated\",\"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\":\"oldShortfallContract\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"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\":\"totalAmount\",\"type\":\"uint256\"}],\"name\":\"SwappedPoolsAssets\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"SweepToken\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"TransferredReserveForAuction\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"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\",\"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\"}],\"name\":\"assetsReserves\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"convertibleBaseAsset\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"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\":\"comptroller\",\"type\":\"address\"}],\"name\":\"getPoolsBaseAssetReserves\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"pancakeSwapRouter_\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmountToConvert_\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"convertibleBaseAsset_\",\"type\":\"address\"},{\"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\":\"minAmountToConvert\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pancakeSwapRouter\",\"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\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"accessControlManager_\",\"type\":\"address\"}],\"name\":\"setAccessControlManager\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_convertibleBaseAsset\",\"type\":\"address\"}],\"name\":\"setConvertibleBaseAsset\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"limit\",\"type\":\"uint256\"}],\"name\":\"setMaxLoopsLimit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minAmountToConvert_\",\"type\":\"uint256\"}],\"name\":\"setMinAmountToConvert\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"pancakeSwapRouter_\",\"type\":\"address\"}],\"name\":\"setPancakeSwapRouter\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"poolRegistry_\",\"type\":\"address\"}],\"name\":\"setPoolRegistry\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"shortfallContractAddress_\",\"type\":\"address\"}],\"name\":\"setShortfallContractAddress\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"shortfall\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"markets\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"amountsOutMin\",\"type\":\"uint256[]\"},{\"internalType\":\"address[][]\",\"name\":\"paths\",\"type\":\"address[][]\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"swapPoolsAssets\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"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\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transferReserveForAuction\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"}],\"name\":\"updateAssetsState\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Venus\",\"details\":\"This contract does not support BNB.\",\"kind\":\"dev\",\"methods\":{\"acceptOwnership()\":{\"details\":\"The new owner accepts the ownership transfer.\"},\"constructor\":{\"custom:oz-upgrades-unsafe-allow\":\"constructor\",\"details\":\"Note that the contract is upgradeable. Use initialize() or reinitializers to set the state variables.\"},\"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.\"}},\"getPoolsBaseAssetReserves(address)\":{\"params\":{\"comptroller\":\"Comptroller address(pool).\"},\"returns\":{\"_0\":\"Base Asset's reserve in risk fund.\"}},\"initialize(address,uint256,address,address,uint256)\":{\"custom:error\":\"ZeroAddressNotAllowed is thrown when PCS router address is zeroZeroAddressNotAllowed is thrown when convertible base asset address is zero\",\"params\":{\"accessControlManager_\":\"Address of the access control contract\",\"convertibleBaseAsset_\":\"Address of the base asset\",\"loopsLimit_\":\"Limit for the loops in the contract to avoid DOS\",\"minAmountToConvert_\":\"Minimum amount assets must be worth to convert into base asset\",\"pancakeSwapRouter_\":\"Address of the PancakeSwap router\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"pendingOwner()\":{\"details\":\"Returns the address of the pending owner.\"},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner.\"},\"setAccessControlManager(address)\":{\"custom:access\":\"Only Governance\",\"custom:event\":\"Emits NewAccessControlManager event\",\"details\":\"Admin function to set address of AccessControlManager\",\"params\":{\"accessControlManager_\":\"The new address of the AccessControlManager\"}},\"setConvertibleBaseAsset(address)\":{\"params\":{\"_convertibleBaseAsset\":\"Address for new convertible base asset.\"}},\"setMaxLoopsLimit(uint256)\":{\"params\":{\"limit\":\"Limit for the max loops can execute at a time\"}},\"setMinAmountToConvert(uint256)\":{\"params\":{\"minAmountToConvert_\":\"Min amount to convert.\"}},\"setPancakeSwapRouter(address)\":{\"custom:error\":\"ZeroAddressNotAllowed is thrown when PCS router address is zero\",\"params\":{\"pancakeSwapRouter_\":\"Address of the PancakeSwap router\"}},\"setPoolRegistry(address)\":{\"custom:error\":\"ZeroAddressNotAllowed is thrown when pool registry address is zero\",\"params\":{\"poolRegistry_\":\"Address of the pool registry\"}},\"setShortfallContractAddress(address)\":{\"custom:error\":\"ZeroAddressNotAllowed is thrown when shortfall contract address is zero\",\"params\":{\"shortfallContractAddress_\":\"Address of the auction contract\"}},\"swapPoolsAssets(address[],uint256[],address[][],uint256)\":{\"custom:error\":\"ZeroAddressNotAllowed is thrown if PoolRegistry contract address is not configured\",\"params\":{\"amountsOutMin\":\"Minimum amount to receive for swap\",\"deadline\":\"Deadline for the swap\",\"markets\":\"Array of vTokens whose assets to swap for base asset\",\"paths\":\"A path consisting of PCS token pairs for each swap\"},\"returns\":{\"_0\":\"Number of swapped tokens\"}},\"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.\"},\"transferReserveForAuction(address,uint256)\":{\"params\":{\"amount\":\"Amount to be transferred to auction contract.\",\"comptroller\":\"Comptroller of the pool.\"},\"returns\":{\"_0\":\"Number reserved tokens.\"}},\"updateAssetsState(address,address)\":{\"params\":{\"asset\":\"Asset address.\",\"comptroller\":\"Comptroller address(pool).\"}}},\"title\":\"RiskFund\",\"version\":1},\"userdoc\":{\"errors\":{\"ApproveFailed()\":[{\"notice\":\"Thrown if a contract is unable to approve a transfer\"}],\"MaxLoopsLimitExceeded(uint256,uint256)\":[{\"notice\":\"Thrown an error on maxLoopsLimit exceeds for any loop\"}],\"Unauthorized(address,address,string)\":[{\"notice\":\"Thrown when the action is prohibited by AccessControlManager\"}],\"ZeroAddressNotAllowed()\":[{\"notice\":\"Thrown if the supplied address is a zero address where it is not allowed\"}]},\"events\":{\"AssetsReservesUpdated(address,address,uint256)\":{\"notice\":\"Event emitted after the update of the assets reserves.\"},\"ConvertibleBaseAssetUpdated(address,address)\":{\"notice\":\"Emitted when convertible base asset is updated\"},\"MaxLoopsLimitUpdated(uint256,uint256)\":{\"notice\":\"Emitted when max loops limit is set\"},\"MinAmountToConvertUpdated(uint256,uint256)\":{\"notice\":\"Emitted when minimum amount to convert is updated\"},\"NewAccessControlManager(address,address)\":{\"notice\":\"Emitted when access control manager contract address is changed\"},\"PancakeSwapRouterUpdated(address,address)\":{\"notice\":\"Emitted when PancakeSwap router contract address is updated\"},\"PoolRegistryUpdated(address,address)\":{\"notice\":\"Emitted when pool registry address is updated\"},\"ShortfallContractUpdated(address,address)\":{\"notice\":\"Emitted when shortfall contract address is updated\"},\"SwappedPoolsAssets(address[],uint256[],uint256)\":{\"notice\":\"Emitted when pools assets are swapped\"},\"SweepToken(address,address,uint256)\":{\"notice\":\"event emitted on sweep token success\"},\"TransferredReserveForAuction(address,uint256)\":{\"notice\":\"Emitted when reserves are transferred for auction\"}},\"kind\":\"user\",\"methods\":{\"accessControlManager()\":{\"notice\":\"Returns the address of the access control manager contract\"},\"getPoolAssetReserve(address,address)\":{\"notice\":\"Get the Amount of the asset in the risk fund for the specific pool.\"},\"getPoolsBaseAssetReserves(address)\":{\"notice\":\"Get the Amount of the Base asset in the risk fund for the specific pool.\"},\"initialize(address,uint256,address,address,uint256)\":{\"notice\":\"Initializes the deployer to owner.\"},\"setAccessControlManager(address)\":{\"notice\":\"Sets the address of AccessControlManager\"},\"setConvertibleBaseAsset(address)\":{\"notice\":\"Sets a new convertible base asset\"},\"setMaxLoopsLimit(uint256)\":{\"notice\":\"Set the limit for the loops can iterate to avoid the DOS\"},\"setMinAmountToConvert(uint256)\":{\"notice\":\"Min amount to convert setter\"},\"setPancakeSwapRouter(address)\":{\"notice\":\"PancakeSwap router address setter\"},\"setPoolRegistry(address)\":{\"notice\":\"Pool registry setter\"},\"setShortfallContractAddress(address)\":{\"notice\":\"Shortfall contract address setter\"},\"swapPoolsAssets(address[],uint256[],address[][],uint256)\":{\"notice\":\"Swap array of pool assets into base asset's tokens of at least a minimum amount\"},\"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\"},\"transferReserveForAuction(address,uint256)\":{\"notice\":\"Transfer tokens for auction.\"},\"updateAssetsState(address,address)\":{\"notice\":\"Update the reserve of the asset for the specific pool after transferring to risk fund.\"}},\"notice\":\"Contract with basic features to track/hold different assets for different Comptrollers.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/RiskFund/RiskFund.sol\":\"RiskFund\"},\"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(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 \\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\":\"0xef1ca0adc3ce1ff540279d424953087771b4a07470caac99777fafd2ceea38a9\",\"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 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(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/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\",\"keccak256\":\"0x7e4d140bd2a5671389ad7a3975b65d05a4f750daf6a61c16139d123d9782b96e\",\"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/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/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\\\";\\nimport { PoolRegistry } from \\\"../Pool/PoolRegistry.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 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 PoolRegistry(poolRegistry).getVTokenForAsset(comptroller, asset) != address(0);\\n }\\n}\\n\",\"keccak256\":\"0xb66ce634fdff1b2cf4f52b2e2a2d1232108c74068f2a4129d0f421ed19362211\",\"license\":\"BSD-3-Clause\"},\"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\",\"keccak256\":\"0x918526b067c834935f5dd0788139e1a73c64cbf6f8b7d6fd43242eaa93aa7f37\",\"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(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 \\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 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 \\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(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\",\"keccak256\":\"0xcda9eb71f6ceb8a4c3bfbc1c42d72e2f0523d30f6d3252fbd90819e953640fe5\",\"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(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\":\"0x2947e95eb97a3a45f90ec36d4fd5a4cbb9409319f6ad000e950550055a3f2324\",\"license\":\"BSD-3-Clause\"},\"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\",\"keccak256\":\"0x9bbc31c80a4c537ddfd06cbd03a412ba64842a708381fbc4bf2e33ef56c92b4d\",\"license\":\"MIT\"},\"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": "0x60e06040523480156200001157600080fd5b506040516200326a3803806200326a83398101604081905262000034916200013e565b6001600160a01b0380841660805280831660a052811660c0526200005762000060565b50505062000188565b600054610100900460ff1615620000cd5760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b60005460ff908116146200011f576000805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b80516001600160a01b03811681146200013957600080fd5b919050565b6000806000606084860312156200015457600080fd5b6200015f8462000121565b92506200016f6020850162000121565b91506200017f6040850162000121565b90509250925092565b60805160a05160c051613096620001d4600039600081816102bf015261258601526000818161029801526124c3015260008181610437015281816122df015261240c01526130966000f3fe608060405234801561001057600080fd5b50600436106101da5760003560e01c806377d4937f11610104578063afcff50f116100a2578063e30c397811610071578063e30c39781461040e578063f2fde38b1461041f578063fa7b81a014610432578063fe3da9841461045957600080fd5b8063afcff50f146103cd578063b4a0bdf3146103e0578063be26317e146103f1578063c8ecc0d3146103fa57600080fd5b806380d45a2d116100de57806380d45a2d146103835780638da5cb5b14610396578063a69bd19e146103a7578063aac59a75146103ba57600080fd5b806377d4937f1461035557806379ba5097146103685780637b77cd6a1461037057600080fd5b80633421fc521161017c5780635f30e37b1161014b5780635f30e37b146103145780636fb0527514610327578063715018a61461033a578063746460a91461034257600080fd5b80633421fc5214610293578063362b6795146102ba578063439b5517146102e15780634dd9584a1461030157600080fd5b806324558995116101b85780632455899514610246578063258836fe1461025a5780632a1d05471461026d5780632e6881411461028057600080fd5b80630a9837c5146101df5780630e32cb861461020557806319b1faef1461021a575b600080fd5b6101f26101ed366004612779565b610463565b6040519081526020015b60405180910390f35b6102186102133660046127a5565b610632565b005b61012e5461022e906001600160a01b031681565b6040516001600160a01b0390911681526020016101fc565b61012f5461022e906001600160a01b031681565b6102186102683660046127c2565b610646565b61021861027b3660046127fb565b6107d7565b61021861028e3660046127a5565b6109c8565b61022e7f000000000000000000000000000000000000000000000000000000000000000081565b61022e7f000000000000000000000000000000000000000000000000000000000000000081565b6101f26102ef3660046127a5565b60c96020526000908152604090205481565b61021861030f3660046127a5565b610acd565b6101f26103223660046128a2565b610b31565b6101f26103353660046127c2565b611085565b61021861113b565b610218610350366004612945565b61114f565b6102186103633660046127a5565b6111f4565b610218611258565b61021861037e3660046127a5565b6112cf565b610218610391366004612945565b611332565b6033546001600160a01b031661022e565b6101f26103b53660046127a5565b611343565b6102186103c83660046127c2565b61142f565b60cb5461022e906001600160a01b031681565b6097546001600160a01b031661022e565b6101f260fb5481565b61012d5461022e906001600160a01b031681565b6065546001600160a01b031661022e565b61021861042d3660046127a5565b61143d565b61022e7f000000000000000000000000000000000000000000000000000000000000000081565b6101f26101305481565b6000600260cc54036104905760405162461bcd60e51b81526004016104879061295e565b60405180910390fd5b600260cc5561012e546001600160a01b03163381146105085760405162461bcd60e51b815260206004820152602e60248201527f5269736b2066756e643a204f6e6c792063616c6c61626c652062792053686f7260448201526d1d19985b1b0818dbdb9d1c9858dd60921b6064820152608401610487565b6001600160a01b03808516600090815260ca6020908152604080832061012d549094168352929052205483111561058f5760405162461bcd60e51b815260206004820152602560248201527f5269736b2046756e643a20496e73756666696369656e7420706f6f6c2072657360448201526432b93b329760d91b6064820152608401610487565b6001600160a01b03808516600081815260ca6020908152604080832061012d80548716855290835281842080548a9003905554909416825260c990528290208054869003905590517fc8d0a37ed16dfaa43514df00e18f478b60d5cc7b4bfc687103948b9020f737fd906106069086815260200190565b60405180910390a261012d54610626906001600160a01b031682856114ae565b5050600160cc55919050565b61063a611505565b6106438161155f565b50565b61064e611505565b600260cc54036106705760405162461bcd60e51b81526004016104879061295e565b600260cc5561067e8161161d565b6040516370a0823160e01b815230600482015260009081906001600160a01b038516906370a0823190602401602060405180830381865afa1580156106c7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106eb9190612982565b6001600160a01b038516600090815260c9602052604090205490915081116107615760405162461bcd60e51b815260206004820152602360248201527f5265736572766548656c706572733a205a65726f20737572706c757320746f6b604482015262656e7360e81b6064820152608401610487565b6001600160a01b03848116600081815260c960209081526040918290205491519185038083529550928616927f6d25be279134f4ecaa4770aff0c3d916d9e7c5ef37b65ed95dbdba411f5d54d5910160405180910390a36107cc6001600160a01b03851684846114ae565b5050600160cc555050565b600054610100900460ff16158080156107f75750600054600160ff909116105b806108115750303b158015610811575060005460ff166001145b6108745760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610487565b6000805460ff191660011790558015610897576000805461ff0019166101001790555b6108a08661161d565b6108a98461161d565b600085116108c95760405162461bcd60e51b81526004016104879061299b565b600082116109285760405162461bcd60e51b815260206004820152602660248201527f5269736b2046756e643a204c6f6f7073206c696d69742063616e206e6f74206260448201526565207a65726f60d01b6064820152608401610487565b610930611644565b61093983611673565b61012f80546001600160a01b038089166001600160a01b03199283161790925561013087905561012d80549287169290911691909117905561097a8261169a565b80156109c0576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050565b610a066040518060400160405280602081526020017f736574436f6e7665727469626c65426173654173736574286164647265737329815250611734565b6001600160a01b038116610a7a5760405162461bcd60e51b815260206004820152603560248201527f5269736b2046756e643a206e657720636f6e7665727469626c65206261736520604482015274185cdcd95d081859191c995cdcc81a5b9d985b1a59605a1b6064820152608401610487565b61012d80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f5fa61583da12070720613fefdd68cc6c0e464a71e009742526bd2b2e0ac62cd290600090a35050565b610ad5611505565b610ade8161161d565b61012f80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907fd37b9d138f53ea58d7e50292588239a46efa8f523966febf4066da96defc77fd90600090a35050565b6000600260cc5403610b555760405162461bcd60e51b81526004016104879061295e565b600260cc81905550610b7e60405180606001604052806038815260200161302960389139611734565b42821015610bce5760405162461bcd60e51b815260206004820152601a60248201527f5269736b2066756e643a20646561646c696e65207061737365640000000000006044820152606401610487565b60cb546001600160a01b0316610be38161161d565b878614610c585760405162461bcd60e51b815260206004820152603860248201527f5269736b2066756e643a206d61726b65747320616e6420616d6f756e74734f7560448201527f744d696e2061726520756e657175616c206c656e6774687300000000000000006064820152608401610487565b878414610cc05760405162461bcd60e51b815260206004820152603060248201527f5269736b2066756e643a206d61726b65747320616e642070617468732061726560448201526f20756e657175616c206c656e6774687360801b6064820152608401610487565b600088610ccc816117ce565b60005b818110156110325760008c8c83818110610ceb57610ceb6129e3565b9050602002016020810190610d0091906127a5565b6001600160a01b0316635fe3b5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d3d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d6191906129f9565b604051637aee632d60e01b81526001600160a01b038083166004830152919250600091871690637aee632d90602401600060405180830381865afa158015610dad573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610dd59190810190612ac6565b9050816001600160a01b031681604001516001600160a01b031614610e4c5760405162461bcd60e51b815260206004820152602760248201527f636f6d7074726f6c6c657220646f65736e277420657869737420706f6f6c20726044820152666567697374727960c81b6064820152608401610487565b816001600160a01b0316633d98a1e58f8f86818110610e6d57610e6d6129e3565b9050602002016020810190610e8291906127a5565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa158015610ec6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610eea9190612bbc565b610f2d5760405162461bcd60e51b81526020600482015260146024820152731b585c9ad95d081a5cc81b9bdd081b1a5cdd195960621b6044820152606401610487565b6000610f9c8f8f86818110610f4457610f446129e3565b9050602002016020810190610f5991906127a5565b848f8f88818110610f6c57610f6c6129e3565b905060200201358e8e89818110610f8557610f856129e3565b9050602002810190610f979190612bde565b6117ff565b6001600160a01b03808516600090815260ca6020908152604080832061012d54909416835292905290812080549293508392909190610fdc908490612c3e565b909155505061012d546001600160a01b0316600090815260c960205260408120805483929061100c908490612c3e565b9091555061101c90508187612c3e565b95505050508061102b90612c56565b9050610ccf565b507fb17530966b045b50d4975e7f05048ca00d7335780c24f1c465165a4b94b2d37d8b8b8b8b8660405161106a959493929190612cb8565b60405180910390a150600160cc559998505050505050505050565b60006110908261161d565b826001600160a01b0316627e3dd26040518163ffffffff1660e01b8152600401602060405180830381865afa1580156110cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110f19190612bbc565b61110d5760405162461bcd60e51b815260040161048790612d13565b506001600160a01b03808316600090815260ca60209081526040808320938516835292905220545b92915050565b611143611505565b61114d6000611da2565b565b61118d6040518060400160405280601e81526020017f7365744d696e416d6f756e74546f436f6e766572742875696e74323536290000815250611734565b600081116111ad5760405162461bcd60e51b81526004016104879061299b565b61013080549082905560408051828152602081018490527fada67d0d38fa20c8ae6a5c17cb9d60b0fe7f2d4e4f27ac9ee55e54ac88de9d8d91015b60405180910390a15050565b6111fc611505565b6112058161161d565b61012e80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907fb6e5fcf02f7fbb8acfbaa3bac4fd5abf9ff51e3f2e8884b5498927179b211b2890600090a35050565b60655433906001600160a01b031681146112c65760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b6064820152608401610487565b61064381611da2565b6112d7611505565b6112e08161161d565b60cb80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907fa87b964d321035d2165e484ff4b722dd6eae30606c0b98887d2ed1a34e594bfe90600090a35050565b61133a611505565b6106438161169a565b6000816001600160a01b0316627e3dd26040518163ffffffff1660e01b8152600401602060405180830381865afa158015611382573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113a69190612bbc565b6114015760405162461bcd60e51b815260206004820152602660248201527f5269736b2046756e643a20436f6d7074726f6c6c6572206164647265737320696044820152651b9d985b1a5960d21b6064820152608401610487565b506001600160a01b03908116600090815260ca6020908152604080832061012d549094168352929052205490565b6114398282611dbb565b5050565b611445611505565b606580546001600160a01b0383166001600160a01b031990911681179091556114766033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b179052611500908490612078565b505050565b6033546001600160a01b0316331461114d5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610487565b6001600160a01b0381166115c35760405162461bcd60e51b815260206004820152602560248201527f696e76616c696420616365737320636f6e74726f6c206d616e61676572206164604482015264647265737360d81b6064820152608401610487565b609780546001600160a01b038381166001600160a01b031983168117909355604080519190921680825260208201939093527f66fd58e82f7b31a2a5c30e0888f3093efe4e111b00cd2b0c31fe014601293aa091016111e8565b6001600160a01b038116610643576040516342bcdf7f60e11b815260040160405180910390fd5b600054610100900460ff1661166b5760405162461bcd60e51b815260040161048790612d5e565b61114d61214d565b600054610100900460ff1661063a5760405162461bcd60e51b815260040161048790612d5e565b60fb5481116116f65760405162461bcd60e51b815260206004820152602260248201527f436f6d7074726f6c6c65723a20496e76616c6964206d61784c6f6f70734c696d6044820152611a5d60f21b6064820152608401610487565b60fb80549082905560408051828152602081018490527fc2d09fef144f7c8a86f71ea459f8fc17f675768eb1ae369cbd77fb31d467aafa91016111e8565b6097546040516318c5e8ab60e01b81526000916001600160a01b0316906318c5e8ab906117679033908690600401612dd5565b602060405180830381865afa158015611784573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117a89190612bbc565b90508061143957333083604051634a3fa29360e01b815260040161048793929190612df9565b60fb548111156106435760fb5460405163792bfb1b60e11b8152600481019190915260248101829052604401610487565b6000836000036118775760405162461bcd60e51b815260206004820152603c60248201527f5269736b46756e643a20616d6f756e744f75744d696e206d757374206265206760448201527f726561746572207468616e203020746f20737761702076546f6b656e000000006064820152608401610487565b600080876001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa1580156118b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118dc91906129f9565b61012d546001600160a01b03898116600090815260ca60209081526040808320848716845290915281205493945091169190819003611922576000945050505050611d99565b6000896001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa158015611962573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061198691906129f9565b60405163b62cad6960e01b81526001600160a01b0385811660048301529192509082169063b62cad6990602401600060405180830381600087803b1580156119cd57600080fd5b505af11580156119e1573d6000803e3d6000fd5b50506040805160208101918290526341976e0960e01b9091526001600160a01b03868116602483015260009350909150819084166341976e0960448301602060405180830381865afa158015611a3b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a5f9190612982565b905290506000611a6f828c61217d565b905061013054811015611ad25760405162461bcd60e51b815260206004820152602560248201527f5269736b46756e643a206d696e416d6f756e74546f436f6e766572742076696f6044820152641b185d195960da1b6064820152608401610487565b6001600160a01b038616600090815260c9602052604081208054869290611afa908490612e25565b90915550506001600160a01b03808d16600090815260ca60209081526040808320938a1683529290529081208054869290611b36908490612e25565b90915550506001600160a01b0386811690861614611d8b57856001600160a01b03168a8a6000818110611b6b57611b6b6129e3565b9050602002016020810190611b8091906127a5565b6001600160a01b031614611bfc5760405162461bcd60e51b815260206004820152603860248201527f5269736b46756e643a20737761702070617468206d757374207374617274207760448201527f6974682074686520756e6465726c79696e6720617373657400000000000000006064820152608401610487565b6001600160a01b0385168a8a611c13600182612e25565b818110611c2257611c226129e3565b9050602002016020810190611c3791906127a5565b6001600160a01b031614611cab5760405162461bcd60e51b815260206004820152603560248201527f5269736b46756e643a2066696e616c6c792070617468206d75737420626520636044820152741bdb9d995c9d1a589b194818985cd948185cdcd95d605a1b6064820152608401610487565b61012f546001600160a01b0390811690611cc990881682600061219d565b611cdd6001600160a01b038816828761219d565b6000816001600160a01b03166338ed1739878f8f8f30426040518763ffffffff1660e01b8152600401611d1596959493929190612e3c565b6000604051808303816000875af1158015611d34573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611d5c9190810190612e9e565b905080611d6a60018d612e25565b81518110611d7a57611d7a6129e3565b602002602001015198505050611d8f565b8396505b5094955050505050505b95945050505050565b606580546001600160a01b031916905561064381612289565b611dc48161161d565b816001600160a01b0316627e3dd26040518163ffffffff1660e01b8152600401602060405180830381865afa158015611e01573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e259190612bbc565b611e415760405162461bcd60e51b815260040161048790612d13565b60cb546001600160a01b031680611eb35760405162461bcd60e51b815260206004820152603060248201527f5265736572766548656c706572733a20506f6f6c20526567697374727920616460448201526f191c995cdcc81a5cc81b9bdd081cd95d60821b6064820152608401610487565b611ebd83836122db565b611f245760405162461bcd60e51b815260206004820152603260248201527f5265736572766548656c706572733a2054686520706f6f6c20646f65736e2774604482015271081cdd5c1c1bdc9d081d1a1948185cdcd95d60721b6064820152608401610487565b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa158015611f6b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f8f9190612982565b6001600160a01b038416600090815260c9602052604090205490915080821115612071576001600160a01b038416600090815260c960205260408120805483850392839291611fdf908490612c3e565b90915550506001600160a01b03808716600090815260ca602090815260408083209389168352929052908120805483929061201b908490612c3e565b92505081905550846001600160a01b0316866001600160a01b03167fc39e3e80c0219fde334a8cb5d8468b628482e23388b6e809c90cb00c63c8ce388360405161206791815260200190565b60405180910390a3505b5050505050565b60006120cd826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166123af9092919063ffffffff16565b90508051600014806120ee5750808060200190518101906120ee9190612bbc565b6115005760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610487565b600054610100900460ff166121745760405162461bcd60e51b815260040161048790612d5e565b61114d33611da2565b60008061218a84846123be565b9050612195816123ef565b949350505050565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663095ea7b360e01b1790529151909160009182918716906121fb908590612f29565b6000604051808303816000865af19150503d8060008114612238576040519150601f19603f3d011682016040523d82523d6000602084013e61223d565b606091505b509150915081158061226b575080511580159061226b5750808060200190518101906122699190612bbc565b155b156109c057604051633e3f8f7360e01b815260040160405180910390fd5b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316836001600160a01b0316036123265761231f82612407565b9050611135565b60cb5460405163266e0a7f60e01b81526001600160a01b0385811660048301528481166024830152600092169063266e0a7f90604401602060405180830381865afa158015612379573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061239d91906129f9565b6001600160a01b031614159392505050565b606061219584846000856125d8565b60408051602081019091526000815260405180602001604052806123e68560000151856126b3565b90529392505050565b805160009061113590670de0b6b3a764000090612f45565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b0772d0b6040518163ffffffff1660e01b8152600401600060405180830381865afa158015612468573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526124909190810190612f67565b905060005b81518110156125d1578181815181106124b0576124b06129e3565b60200260200101516001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03161461258457836001600160a01b031682828151811061250c5761250c6129e3565b60200260200101516001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa158015612551573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061257591906129f9565b6001600160a01b0316146125ba565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316846001600160a01b0316145b9250826125d1576125ca81612c56565b9050612495565b5050919050565b6060824710156126395760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610487565b600080866001600160a01b031685876040516126559190612f29565b60006040518083038185875af1925050503d8060008114612692576040519150601f19603f3d011682016040523d82523d6000602084013e612697565b606091505b50915091506126a8878383876126c6565b979650505050505050565b60006126bf8284612ff6565b9392505050565b6060831561273557825160000361272e576001600160a01b0385163b61272e5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610487565b5081612195565b612195838381511561274a5781518083602001fd5b8060405162461bcd60e51b81526004016104879190613015565b6001600160a01b038116811461064357600080fd5b6000806040838503121561278c57600080fd5b823561279781612764565b946020939093013593505050565b6000602082840312156127b757600080fd5b81356126bf81612764565b600080604083850312156127d557600080fd5b82356127e081612764565b915060208301356127f081612764565b809150509250929050565b600080600080600060a0868803121561281357600080fd5b853561281e81612764565b945060208601359350604086013561283581612764565b9250606086013561284581612764565b949793965091946080013592915050565b60008083601f84011261286857600080fd5b50813567ffffffffffffffff81111561288057600080fd5b6020830191508360208260051b850101111561289b57600080fd5b9250929050565b60008060008060008060006080888a0312156128bd57600080fd5b873567ffffffffffffffff808211156128d557600080fd5b6128e18b838c01612856565b909950975060208a01359150808211156128fa57600080fd5b6129068b838c01612856565b909750955060408a013591508082111561291f57600080fd5b5061292c8a828b01612856565b989b979a50959894979596606090950135949350505050565b60006020828403121561295757600080fd5b5035919050565b6020808252600a90820152691c994b595b9d195c995960b21b604082015260600190565b60006020828403121561299457600080fd5b5051919050565b60208082526028908201527f5269736b2046756e643a20496e76616c6964206d696e20616d6f756e7420746f6040820152670818dbdb9d995c9d60c21b606082015260800190565b634e487b7160e01b600052603260045260246000fd5b600060208284031215612a0b57600080fd5b81516126bf81612764565b634e487b7160e01b600052604160045260246000fd5b60405160a0810167ffffffffffffffff81118282101715612a4f57612a4f612a16565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715612a7e57612a7e612a16565b604052919050565b60005b83811015612aa1578181015183820152602001612a89565b83811115612ab0576000848401525b50505050565b8051612ac181612764565b919050565b60006020808385031215612ad957600080fd5b825167ffffffffffffffff80821115612af157600080fd5b9084019060a08287031215612b0557600080fd5b612b0d612a2c565b825182811115612b1c57600080fd5b8301601f81018813612b2d57600080fd5b805183811115612b3f57612b3f612a16565b612b51601f8201601f19168701612a55565b93508084528886828401011115612b6757600080fd5b612b7681878601888501612a86565b5050818152612b86848401612ab6565b84820152612b9660408401612ab6565b604082015260608301516060820152608083015160808201528094505050505092915050565b600060208284031215612bce57600080fd5b815180151581146126bf57600080fd5b6000808335601e19843603018112612bf557600080fd5b83018035915067ffffffffffffffff821115612c1057600080fd5b6020019150600581901b360382131561289b57600080fd5b634e487b7160e01b600052601160045260246000fd5b60008219821115612c5157612c51612c28565b500190565b600060018201612c6857612c68612c28565b5060010190565b8183526000602080850194508260005b85811015612cad578135612c9281612764565b6001600160a01b031687529582019590820190600101612c7f565b509495945050505050565b606081526000612ccc606083018789612c6f565b82810360208401528481526001600160fb1b03851115612ceb57600080fd5b8460051b80876020840137600091016020019081526040929092019290925295945050505050565b6020808252602b908201527f5265736572766548656c706572733a20436f6d7074726f6c6c6572206164647260408201526a195cdcc81a5b9d985b1a5960aa1b606082015260800190565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b60008151808452612dc1816020860160208601612a86565b601f01601f19169290920160200192915050565b6001600160a01b038316815260406020820181905260009061219590830184612da9565b6001600160a01b03848116825283166020820152606060408201819052600090611d9990830184612da9565b600082821015612e3757612e37612c28565b500390565b86815285602082015260a060408201526000612e5c60a083018688612c6f565b6001600160a01b039490941660608301525060800152949350505050565b600067ffffffffffffffff821115612e9457612e94612a16565b5060051b60200190565b60006020808385031215612eb157600080fd5b825167ffffffffffffffff811115612ec857600080fd5b8301601f81018513612ed957600080fd5b8051612eec612ee782612e7a565b612a55565b81815260059190911b82018301908381019087831115612f0b57600080fd5b928401925b828410156126a857835182529284019290840190612f10565b60008251612f3b818460208701612a86565b9190910192915050565b600082612f6257634e487b7160e01b600052601260045260246000fd5b500490565b60006020808385031215612f7a57600080fd5b825167ffffffffffffffff811115612f9157600080fd5b8301601f81018513612fa257600080fd5b8051612fb0612ee782612e7a565b81815260059190911b82018301908381019087831115612fcf57600080fd5b928401925b828410156126a8578351612fe781612764565b82529284019290840190612fd4565b600081600019048311821515161561301057613010612c28565b500290565b6020815260006126bf6020830184612da956fe73776170506f6f6c7341737365747328616464726573735b5d2c75696e743235365b5d2c616464726573735b5d5b5d2c75696e7432353629a2646970667358221220a76e180bdb2a013eae9260adc61d71f42f8a3f14fc1a73b29ba29c31a1106f4964736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101da5760003560e01c806377d4937f11610104578063afcff50f116100a2578063e30c397811610071578063e30c39781461040e578063f2fde38b1461041f578063fa7b81a014610432578063fe3da9841461045957600080fd5b8063afcff50f146103cd578063b4a0bdf3146103e0578063be26317e146103f1578063c8ecc0d3146103fa57600080fd5b806380d45a2d116100de57806380d45a2d146103835780638da5cb5b14610396578063a69bd19e146103a7578063aac59a75146103ba57600080fd5b806377d4937f1461035557806379ba5097146103685780637b77cd6a1461037057600080fd5b80633421fc521161017c5780635f30e37b1161014b5780635f30e37b146103145780636fb0527514610327578063715018a61461033a578063746460a91461034257600080fd5b80633421fc5214610293578063362b6795146102ba578063439b5517146102e15780634dd9584a1461030157600080fd5b806324558995116101b85780632455899514610246578063258836fe1461025a5780632a1d05471461026d5780632e6881411461028057600080fd5b80630a9837c5146101df5780630e32cb861461020557806319b1faef1461021a575b600080fd5b6101f26101ed366004612779565b610463565b6040519081526020015b60405180910390f35b6102186102133660046127a5565b610632565b005b61012e5461022e906001600160a01b031681565b6040516001600160a01b0390911681526020016101fc565b61012f5461022e906001600160a01b031681565b6102186102683660046127c2565b610646565b61021861027b3660046127fb565b6107d7565b61021861028e3660046127a5565b6109c8565b61022e7f000000000000000000000000000000000000000000000000000000000000000081565b61022e7f000000000000000000000000000000000000000000000000000000000000000081565b6101f26102ef3660046127a5565b60c96020526000908152604090205481565b61021861030f3660046127a5565b610acd565b6101f26103223660046128a2565b610b31565b6101f26103353660046127c2565b611085565b61021861113b565b610218610350366004612945565b61114f565b6102186103633660046127a5565b6111f4565b610218611258565b61021861037e3660046127a5565b6112cf565b610218610391366004612945565b611332565b6033546001600160a01b031661022e565b6101f26103b53660046127a5565b611343565b6102186103c83660046127c2565b61142f565b60cb5461022e906001600160a01b031681565b6097546001600160a01b031661022e565b6101f260fb5481565b61012d5461022e906001600160a01b031681565b6065546001600160a01b031661022e565b61021861042d3660046127a5565b61143d565b61022e7f000000000000000000000000000000000000000000000000000000000000000081565b6101f26101305481565b6000600260cc54036104905760405162461bcd60e51b81526004016104879061295e565b60405180910390fd5b600260cc5561012e546001600160a01b03163381146105085760405162461bcd60e51b815260206004820152602e60248201527f5269736b2066756e643a204f6e6c792063616c6c61626c652062792053686f7260448201526d1d19985b1b0818dbdb9d1c9858dd60921b6064820152608401610487565b6001600160a01b03808516600090815260ca6020908152604080832061012d549094168352929052205483111561058f5760405162461bcd60e51b815260206004820152602560248201527f5269736b2046756e643a20496e73756666696369656e7420706f6f6c2072657360448201526432b93b329760d91b6064820152608401610487565b6001600160a01b03808516600081815260ca6020908152604080832061012d80548716855290835281842080548a9003905554909416825260c990528290208054869003905590517fc8d0a37ed16dfaa43514df00e18f478b60d5cc7b4bfc687103948b9020f737fd906106069086815260200190565b60405180910390a261012d54610626906001600160a01b031682856114ae565b5050600160cc55919050565b61063a611505565b6106438161155f565b50565b61064e611505565b600260cc54036106705760405162461bcd60e51b81526004016104879061295e565b600260cc5561067e8161161d565b6040516370a0823160e01b815230600482015260009081906001600160a01b038516906370a0823190602401602060405180830381865afa1580156106c7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106eb9190612982565b6001600160a01b038516600090815260c9602052604090205490915081116107615760405162461bcd60e51b815260206004820152602360248201527f5265736572766548656c706572733a205a65726f20737572706c757320746f6b604482015262656e7360e81b6064820152608401610487565b6001600160a01b03848116600081815260c960209081526040918290205491519185038083529550928616927f6d25be279134f4ecaa4770aff0c3d916d9e7c5ef37b65ed95dbdba411f5d54d5910160405180910390a36107cc6001600160a01b03851684846114ae565b5050600160cc555050565b600054610100900460ff16158080156107f75750600054600160ff909116105b806108115750303b158015610811575060005460ff166001145b6108745760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610487565b6000805460ff191660011790558015610897576000805461ff0019166101001790555b6108a08661161d565b6108a98461161d565b600085116108c95760405162461bcd60e51b81526004016104879061299b565b600082116109285760405162461bcd60e51b815260206004820152602660248201527f5269736b2046756e643a204c6f6f7073206c696d69742063616e206e6f74206260448201526565207a65726f60d01b6064820152608401610487565b610930611644565b61093983611673565b61012f80546001600160a01b038089166001600160a01b03199283161790925561013087905561012d80549287169290911691909117905561097a8261169a565b80156109c0576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050565b610a066040518060400160405280602081526020017f736574436f6e7665727469626c65426173654173736574286164647265737329815250611734565b6001600160a01b038116610a7a5760405162461bcd60e51b815260206004820152603560248201527f5269736b2046756e643a206e657720636f6e7665727469626c65206261736520604482015274185cdcd95d081859191c995cdcc81a5b9d985b1a59605a1b6064820152608401610487565b61012d80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f5fa61583da12070720613fefdd68cc6c0e464a71e009742526bd2b2e0ac62cd290600090a35050565b610ad5611505565b610ade8161161d565b61012f80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907fd37b9d138f53ea58d7e50292588239a46efa8f523966febf4066da96defc77fd90600090a35050565b6000600260cc5403610b555760405162461bcd60e51b81526004016104879061295e565b600260cc81905550610b7e60405180606001604052806038815260200161302960389139611734565b42821015610bce5760405162461bcd60e51b815260206004820152601a60248201527f5269736b2066756e643a20646561646c696e65207061737365640000000000006044820152606401610487565b60cb546001600160a01b0316610be38161161d565b878614610c585760405162461bcd60e51b815260206004820152603860248201527f5269736b2066756e643a206d61726b65747320616e6420616d6f756e74734f7560448201527f744d696e2061726520756e657175616c206c656e6774687300000000000000006064820152608401610487565b878414610cc05760405162461bcd60e51b815260206004820152603060248201527f5269736b2066756e643a206d61726b65747320616e642070617468732061726560448201526f20756e657175616c206c656e6774687360801b6064820152608401610487565b600088610ccc816117ce565b60005b818110156110325760008c8c83818110610ceb57610ceb6129e3565b9050602002016020810190610d0091906127a5565b6001600160a01b0316635fe3b5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d3d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d6191906129f9565b604051637aee632d60e01b81526001600160a01b038083166004830152919250600091871690637aee632d90602401600060405180830381865afa158015610dad573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610dd59190810190612ac6565b9050816001600160a01b031681604001516001600160a01b031614610e4c5760405162461bcd60e51b815260206004820152602760248201527f636f6d7074726f6c6c657220646f65736e277420657869737420706f6f6c20726044820152666567697374727960c81b6064820152608401610487565b816001600160a01b0316633d98a1e58f8f86818110610e6d57610e6d6129e3565b9050602002016020810190610e8291906127a5565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa158015610ec6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610eea9190612bbc565b610f2d5760405162461bcd60e51b81526020600482015260146024820152731b585c9ad95d081a5cc81b9bdd081b1a5cdd195960621b6044820152606401610487565b6000610f9c8f8f86818110610f4457610f446129e3565b9050602002016020810190610f5991906127a5565b848f8f88818110610f6c57610f6c6129e3565b905060200201358e8e89818110610f8557610f856129e3565b9050602002810190610f979190612bde565b6117ff565b6001600160a01b03808516600090815260ca6020908152604080832061012d54909416835292905290812080549293508392909190610fdc908490612c3e565b909155505061012d546001600160a01b0316600090815260c960205260408120805483929061100c908490612c3e565b9091555061101c90508187612c3e565b95505050508061102b90612c56565b9050610ccf565b507fb17530966b045b50d4975e7f05048ca00d7335780c24f1c465165a4b94b2d37d8b8b8b8b8660405161106a959493929190612cb8565b60405180910390a150600160cc559998505050505050505050565b60006110908261161d565b826001600160a01b0316627e3dd26040518163ffffffff1660e01b8152600401602060405180830381865afa1580156110cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110f19190612bbc565b61110d5760405162461bcd60e51b815260040161048790612d13565b506001600160a01b03808316600090815260ca60209081526040808320938516835292905220545b92915050565b611143611505565b61114d6000611da2565b565b61118d6040518060400160405280601e81526020017f7365744d696e416d6f756e74546f436f6e766572742875696e74323536290000815250611734565b600081116111ad5760405162461bcd60e51b81526004016104879061299b565b61013080549082905560408051828152602081018490527fada67d0d38fa20c8ae6a5c17cb9d60b0fe7f2d4e4f27ac9ee55e54ac88de9d8d91015b60405180910390a15050565b6111fc611505565b6112058161161d565b61012e80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907fb6e5fcf02f7fbb8acfbaa3bac4fd5abf9ff51e3f2e8884b5498927179b211b2890600090a35050565b60655433906001600160a01b031681146112c65760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b6064820152608401610487565b61064381611da2565b6112d7611505565b6112e08161161d565b60cb80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907fa87b964d321035d2165e484ff4b722dd6eae30606c0b98887d2ed1a34e594bfe90600090a35050565b61133a611505565b6106438161169a565b6000816001600160a01b0316627e3dd26040518163ffffffff1660e01b8152600401602060405180830381865afa158015611382573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113a69190612bbc565b6114015760405162461bcd60e51b815260206004820152602660248201527f5269736b2046756e643a20436f6d7074726f6c6c6572206164647265737320696044820152651b9d985b1a5960d21b6064820152608401610487565b506001600160a01b03908116600090815260ca6020908152604080832061012d549094168352929052205490565b6114398282611dbb565b5050565b611445611505565b606580546001600160a01b0383166001600160a01b031990911681179091556114766033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b179052611500908490612078565b505050565b6033546001600160a01b0316331461114d5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610487565b6001600160a01b0381166115c35760405162461bcd60e51b815260206004820152602560248201527f696e76616c696420616365737320636f6e74726f6c206d616e61676572206164604482015264647265737360d81b6064820152608401610487565b609780546001600160a01b038381166001600160a01b031983168117909355604080519190921680825260208201939093527f66fd58e82f7b31a2a5c30e0888f3093efe4e111b00cd2b0c31fe014601293aa091016111e8565b6001600160a01b038116610643576040516342bcdf7f60e11b815260040160405180910390fd5b600054610100900460ff1661166b5760405162461bcd60e51b815260040161048790612d5e565b61114d61214d565b600054610100900460ff1661063a5760405162461bcd60e51b815260040161048790612d5e565b60fb5481116116f65760405162461bcd60e51b815260206004820152602260248201527f436f6d7074726f6c6c65723a20496e76616c6964206d61784c6f6f70734c696d6044820152611a5d60f21b6064820152608401610487565b60fb80549082905560408051828152602081018490527fc2d09fef144f7c8a86f71ea459f8fc17f675768eb1ae369cbd77fb31d467aafa91016111e8565b6097546040516318c5e8ab60e01b81526000916001600160a01b0316906318c5e8ab906117679033908690600401612dd5565b602060405180830381865afa158015611784573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117a89190612bbc565b90508061143957333083604051634a3fa29360e01b815260040161048793929190612df9565b60fb548111156106435760fb5460405163792bfb1b60e11b8152600481019190915260248101829052604401610487565b6000836000036118775760405162461bcd60e51b815260206004820152603c60248201527f5269736b46756e643a20616d6f756e744f75744d696e206d757374206265206760448201527f726561746572207468616e203020746f20737761702076546f6b656e000000006064820152608401610487565b600080876001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa1580156118b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118dc91906129f9565b61012d546001600160a01b03898116600090815260ca60209081526040808320848716845290915281205493945091169190819003611922576000945050505050611d99565b6000896001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa158015611962573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061198691906129f9565b60405163b62cad6960e01b81526001600160a01b0385811660048301529192509082169063b62cad6990602401600060405180830381600087803b1580156119cd57600080fd5b505af11580156119e1573d6000803e3d6000fd5b50506040805160208101918290526341976e0960e01b9091526001600160a01b03868116602483015260009350909150819084166341976e0960448301602060405180830381865afa158015611a3b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a5f9190612982565b905290506000611a6f828c61217d565b905061013054811015611ad25760405162461bcd60e51b815260206004820152602560248201527f5269736b46756e643a206d696e416d6f756e74546f436f6e766572742076696f6044820152641b185d195960da1b6064820152608401610487565b6001600160a01b038616600090815260c9602052604081208054869290611afa908490612e25565b90915550506001600160a01b03808d16600090815260ca60209081526040808320938a1683529290529081208054869290611b36908490612e25565b90915550506001600160a01b0386811690861614611d8b57856001600160a01b03168a8a6000818110611b6b57611b6b6129e3565b9050602002016020810190611b8091906127a5565b6001600160a01b031614611bfc5760405162461bcd60e51b815260206004820152603860248201527f5269736b46756e643a20737761702070617468206d757374207374617274207760448201527f6974682074686520756e6465726c79696e6720617373657400000000000000006064820152608401610487565b6001600160a01b0385168a8a611c13600182612e25565b818110611c2257611c226129e3565b9050602002016020810190611c3791906127a5565b6001600160a01b031614611cab5760405162461bcd60e51b815260206004820152603560248201527f5269736b46756e643a2066696e616c6c792070617468206d75737420626520636044820152741bdb9d995c9d1a589b194818985cd948185cdcd95d605a1b6064820152608401610487565b61012f546001600160a01b0390811690611cc990881682600061219d565b611cdd6001600160a01b038816828761219d565b6000816001600160a01b03166338ed1739878f8f8f30426040518763ffffffff1660e01b8152600401611d1596959493929190612e3c565b6000604051808303816000875af1158015611d34573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611d5c9190810190612e9e565b905080611d6a60018d612e25565b81518110611d7a57611d7a6129e3565b602002602001015198505050611d8f565b8396505b5094955050505050505b95945050505050565b606580546001600160a01b031916905561064381612289565b611dc48161161d565b816001600160a01b0316627e3dd26040518163ffffffff1660e01b8152600401602060405180830381865afa158015611e01573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e259190612bbc565b611e415760405162461bcd60e51b815260040161048790612d13565b60cb546001600160a01b031680611eb35760405162461bcd60e51b815260206004820152603060248201527f5265736572766548656c706572733a20506f6f6c20526567697374727920616460448201526f191c995cdcc81a5cc81b9bdd081cd95d60821b6064820152608401610487565b611ebd83836122db565b611f245760405162461bcd60e51b815260206004820152603260248201527f5265736572766548656c706572733a2054686520706f6f6c20646f65736e2774604482015271081cdd5c1c1bdc9d081d1a1948185cdcd95d60721b6064820152608401610487565b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa158015611f6b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f8f9190612982565b6001600160a01b038416600090815260c9602052604090205490915080821115612071576001600160a01b038416600090815260c960205260408120805483850392839291611fdf908490612c3e565b90915550506001600160a01b03808716600090815260ca602090815260408083209389168352929052908120805483929061201b908490612c3e565b92505081905550846001600160a01b0316866001600160a01b03167fc39e3e80c0219fde334a8cb5d8468b628482e23388b6e809c90cb00c63c8ce388360405161206791815260200190565b60405180910390a3505b5050505050565b60006120cd826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166123af9092919063ffffffff16565b90508051600014806120ee5750808060200190518101906120ee9190612bbc565b6115005760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610487565b600054610100900460ff166121745760405162461bcd60e51b815260040161048790612d5e565b61114d33611da2565b60008061218a84846123be565b9050612195816123ef565b949350505050565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663095ea7b360e01b1790529151909160009182918716906121fb908590612f29565b6000604051808303816000865af19150503d8060008114612238576040519150601f19603f3d011682016040523d82523d6000602084013e61223d565b606091505b509150915081158061226b575080511580159061226b5750808060200190518101906122699190612bbc565b155b156109c057604051633e3f8f7360e01b815260040160405180910390fd5b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316836001600160a01b0316036123265761231f82612407565b9050611135565b60cb5460405163266e0a7f60e01b81526001600160a01b0385811660048301528481166024830152600092169063266e0a7f90604401602060405180830381865afa158015612379573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061239d91906129f9565b6001600160a01b031614159392505050565b606061219584846000856125d8565b60408051602081019091526000815260405180602001604052806123e68560000151856126b3565b90529392505050565b805160009061113590670de0b6b3a764000090612f45565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b0772d0b6040518163ffffffff1660e01b8152600401600060405180830381865afa158015612468573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526124909190810190612f67565b905060005b81518110156125d1578181815181106124b0576124b06129e3565b60200260200101516001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03161461258457836001600160a01b031682828151811061250c5761250c6129e3565b60200260200101516001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa158015612551573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061257591906129f9565b6001600160a01b0316146125ba565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316846001600160a01b0316145b9250826125d1576125ca81612c56565b9050612495565b5050919050565b6060824710156126395760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610487565b600080866001600160a01b031685876040516126559190612f29565b60006040518083038185875af1925050503d8060008114612692576040519150601f19603f3d011682016040523d82523d6000602084013e612697565b606091505b50915091506126a8878383876126c6565b979650505050505050565b60006126bf8284612ff6565b9392505050565b6060831561273557825160000361272e576001600160a01b0385163b61272e5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610487565b5081612195565b612195838381511561274a5781518083602001fd5b8060405162461bcd60e51b81526004016104879190613015565b6001600160a01b038116811461064357600080fd5b6000806040838503121561278c57600080fd5b823561279781612764565b946020939093013593505050565b6000602082840312156127b757600080fd5b81356126bf81612764565b600080604083850312156127d557600080fd5b82356127e081612764565b915060208301356127f081612764565b809150509250929050565b600080600080600060a0868803121561281357600080fd5b853561281e81612764565b945060208601359350604086013561283581612764565b9250606086013561284581612764565b949793965091946080013592915050565b60008083601f84011261286857600080fd5b50813567ffffffffffffffff81111561288057600080fd5b6020830191508360208260051b850101111561289b57600080fd5b9250929050565b60008060008060008060006080888a0312156128bd57600080fd5b873567ffffffffffffffff808211156128d557600080fd5b6128e18b838c01612856565b909950975060208a01359150808211156128fa57600080fd5b6129068b838c01612856565b909750955060408a013591508082111561291f57600080fd5b5061292c8a828b01612856565b989b979a50959894979596606090950135949350505050565b60006020828403121561295757600080fd5b5035919050565b6020808252600a90820152691c994b595b9d195c995960b21b604082015260600190565b60006020828403121561299457600080fd5b5051919050565b60208082526028908201527f5269736b2046756e643a20496e76616c6964206d696e20616d6f756e7420746f6040820152670818dbdb9d995c9d60c21b606082015260800190565b634e487b7160e01b600052603260045260246000fd5b600060208284031215612a0b57600080fd5b81516126bf81612764565b634e487b7160e01b600052604160045260246000fd5b60405160a0810167ffffffffffffffff81118282101715612a4f57612a4f612a16565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715612a7e57612a7e612a16565b604052919050565b60005b83811015612aa1578181015183820152602001612a89565b83811115612ab0576000848401525b50505050565b8051612ac181612764565b919050565b60006020808385031215612ad957600080fd5b825167ffffffffffffffff80821115612af157600080fd5b9084019060a08287031215612b0557600080fd5b612b0d612a2c565b825182811115612b1c57600080fd5b8301601f81018813612b2d57600080fd5b805183811115612b3f57612b3f612a16565b612b51601f8201601f19168701612a55565b93508084528886828401011115612b6757600080fd5b612b7681878601888501612a86565b5050818152612b86848401612ab6565b84820152612b9660408401612ab6565b604082015260608301516060820152608083015160808201528094505050505092915050565b600060208284031215612bce57600080fd5b815180151581146126bf57600080fd5b6000808335601e19843603018112612bf557600080fd5b83018035915067ffffffffffffffff821115612c1057600080fd5b6020019150600581901b360382131561289b57600080fd5b634e487b7160e01b600052601160045260246000fd5b60008219821115612c5157612c51612c28565b500190565b600060018201612c6857612c68612c28565b5060010190565b8183526000602080850194508260005b85811015612cad578135612c9281612764565b6001600160a01b031687529582019590820190600101612c7f565b509495945050505050565b606081526000612ccc606083018789612c6f565b82810360208401528481526001600160fb1b03851115612ceb57600080fd5b8460051b80876020840137600091016020019081526040929092019290925295945050505050565b6020808252602b908201527f5265736572766548656c706572733a20436f6d7074726f6c6c6572206164647260408201526a195cdcc81a5b9d985b1a5960aa1b606082015260800190565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b60008151808452612dc1816020860160208601612a86565b601f01601f19169290920160200192915050565b6001600160a01b038316815260406020820181905260009061219590830184612da9565b6001600160a01b03848116825283166020820152606060408201819052600090611d9990830184612da9565b600082821015612e3757612e37612c28565b500390565b86815285602082015260a060408201526000612e5c60a083018688612c6f565b6001600160a01b039490941660608301525060800152949350505050565b600067ffffffffffffffff821115612e9457612e94612a16565b5060051b60200190565b60006020808385031215612eb157600080fd5b825167ffffffffffffffff811115612ec857600080fd5b8301601f81018513612ed957600080fd5b8051612eec612ee782612e7a565b612a55565b81815260059190911b82018301908381019087831115612f0b57600080fd5b928401925b828410156126a857835182529284019290840190612f10565b60008251612f3b818460208701612a86565b9190910192915050565b600082612f6257634e487b7160e01b600052601260045260246000fd5b500490565b60006020808385031215612f7a57600080fd5b825167ffffffffffffffff811115612f9157600080fd5b8301601f81018513612fa257600080fd5b8051612fb0612ee782612e7a565b81815260059190911b82018301908381019087831115612fcf57600080fd5b928401925b828410156126a8578351612fe781612764565b82529284019290840190612fd4565b600081600019048311821515161561301057613010612c28565b500290565b6020815260006126bf6020830184612da956fe73776170506f6f6c7341737365747328616464726573735b5d2c75696e743235365b5d2c616464726573735b5d5b5d2c75696e7432353629a2646970667358221220a76e180bdb2a013eae9260adc61d71f42f8a3f14fc1a73b29ba29c31a1106f4964736f6c634300080d0033", "devdoc": { "author": "Venus", "details": "This contract does not support BNB.", @@ -1033,7 +1094,7 @@ "storageLayout": { "storage": [ { - "astId": 290, + "astId": 244, "contract": "contracts/RiskFund/RiskFund.sol:RiskFund", "label": "_initialized", "offset": 0, @@ -1041,7 +1102,7 @@ "type": "t_uint8" }, { - "astId": 293, + "astId": 247, "contract": "contracts/RiskFund/RiskFund.sol:RiskFund", "label": "_initializing", "offset": 1, @@ -1049,7 +1110,7 @@ "type": "t_bool" }, { - "astId": 1397, + "astId": 1267, "contract": "contracts/RiskFund/RiskFund.sol:RiskFund", "label": "__gap", "offset": 0, @@ -1057,7 +1118,7 @@ "type": "t_array(t_uint256)50_storage" }, { - "astId": 162, + "astId": 116, "contract": "contracts/RiskFund/RiskFund.sol:RiskFund", "label": "_owner", "offset": 0, @@ -1065,7 +1126,7 @@ "type": "t_address" }, { - "astId": 282, + "astId": 236, "contract": "contracts/RiskFund/RiskFund.sol:RiskFund", "label": "__gap", "offset": 0, @@ -1073,7 +1134,7 @@ "type": "t_array(t_uint256)49_storage" }, { - "astId": 71, + "astId": 25, "contract": "contracts/RiskFund/RiskFund.sol:RiskFund", "label": "_pendingOwner", "offset": 0, @@ -1081,7 +1142,7 @@ "type": "t_address" }, { - "astId": 150, + "astId": 104, "contract": "contracts/RiskFund/RiskFund.sol:RiskFund", "label": "__gap", "offset": 0, @@ -1089,15 +1150,15 @@ "type": "t_array(t_uint256)49_storage" }, { - "astId": 3341, + "astId": 1355, "contract": "contracts/RiskFund/RiskFund.sol:RiskFund", "label": "_accessControlManager", "offset": 0, "slot": "151", - "type": "t_contract(IAccessControlManagerV8)3525" + "type": "t_contract(IAccessControlManagerV8)1539" }, { - "astId": 3346, + "astId": 1360, "contract": "contracts/RiskFund/RiskFund.sol:RiskFund", "label": "__gap", "offset": 0, @@ -1105,7 +1166,7 @@ "type": "t_array(t_uint256)49_storage" }, { - "astId": 13338, + "astId": 8855, "contract": "contracts/RiskFund/RiskFund.sol:RiskFund", "label": "assetsReserves", "offset": 0, @@ -1113,7 +1174,7 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 13344, + "astId": 8861, "contract": "contracts/RiskFund/RiskFund.sol:RiskFund", "label": "_poolsAssetsReserves", "offset": 0, @@ -1121,7 +1182,7 @@ "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))" }, { - "astId": 13346, + "astId": 8863, "contract": "contracts/RiskFund/RiskFund.sol:RiskFund", "label": "poolRegistry", "offset": 0, @@ -1129,7 +1190,7 @@ "type": "t_address" }, { - "astId": 13349, + "astId": 8866, "contract": "contracts/RiskFund/RiskFund.sol:RiskFund", "label": "status", "offset": 0, @@ -1137,7 +1198,7 @@ "type": "t_uint256" }, { - "astId": 13354, + "astId": 8871, "contract": "contracts/RiskFund/RiskFund.sol:RiskFund", "label": "__gap", "offset": 0, @@ -1145,7 +1206,7 @@ "type": "t_array(t_uint256)46_storage" }, { - "astId": 10571, + "astId": 6064, "contract": "contracts/RiskFund/RiskFund.sol:RiskFund", "label": "maxLoopsLimit", "offset": 0, @@ -1153,7 +1214,7 @@ "type": "t_uint256" }, { - "astId": 10576, + "astId": 6069, "contract": "contracts/RiskFund/RiskFund.sol:RiskFund", "label": "__gap", "offset": 0, @@ -1161,7 +1222,7 @@ "type": "t_array(t_uint256)49_storage" }, { - "astId": 13647, + "astId": 9272, "contract": "contracts/RiskFund/RiskFund.sol:RiskFund", "label": "convertibleBaseAsset", "offset": 0, @@ -1169,7 +1230,7 @@ "type": "t_address" }, { - "astId": 13649, + "astId": 9274, "contract": "contracts/RiskFund/RiskFund.sol:RiskFund", "label": "shortfall", "offset": 0, @@ -1177,7 +1238,7 @@ "type": "t_address" }, { - "astId": 13651, + "astId": 9276, "contract": "contracts/RiskFund/RiskFund.sol:RiskFund", "label": "pancakeSwapRouter", "offset": 0, @@ -1185,7 +1246,7 @@ "type": "t_address" }, { - "astId": 13653, + "astId": 9278, "contract": "contracts/RiskFund/RiskFund.sol:RiskFund", "label": "minAmountToConvert", "offset": 0, @@ -1222,7 +1283,7 @@ "label": "bool", "numberOfBytes": "1" }, - "t_contract(IAccessControlManagerV8)3525": { + "t_contract(IAccessControlManagerV8)1539": { "encoding": "inplace", "label": "contract IAccessControlManagerV8", "numberOfBytes": "20" @@ -1253,4 +1314,4 @@ } } } -} +} \ No newline at end of file diff --git a/deployments/bsctestnet/solcInputs/0c597ac2b90fc7d0b2be179fa6482d23.json b/deployments/bsctestnet/solcInputs/0c597ac2b90fc7d0b2be179fa6482d23.json new file mode 100644 index 000000000..354fcbd3c --- /dev/null +++ b/deployments/bsctestnet/solcInputs/0c597ac2b90fc7d0b2be179fa6482d23.json @@ -0,0 +1,134 @@ +{ + "language": "Solidity", + "sources": { + "@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable2Step.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./OwnableUpgradeable.sol\";\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module which provides access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership} and {acceptOwnership}.\n *\n * This module is used through inheritance. It will make available all functions\n * from parent (Ownable).\n */\nabstract contract Ownable2StepUpgradeable is Initializable, OwnableUpgradeable {\n function __Ownable2Step_init() internal onlyInitializing {\n __Ownable_init_unchained();\n }\n\n function __Ownable2Step_init_unchained() internal onlyInitializing {\n }\n address private _pendingOwner;\n\n event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Returns the address of the pending owner.\n */\n function pendingOwner() public view virtual returns (address) {\n return _pendingOwner;\n }\n\n /**\n * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual override onlyOwner {\n _pendingOwner = newOwner;\n emit OwnershipTransferStarted(owner(), newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual override {\n delete _pendingOwner;\n super._transferOwnership(newOwner);\n }\n\n /**\n * @dev The new owner accepts the ownership transfer.\n */\n function acceptOwnership() public virtual {\n address sender = _msgSender();\n require(pendingOwner() == sender, \"Ownable2Step: caller is not the new owner\");\n _transferOwnership(sender);\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/ContextUpgradeable.sol\";\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n function __Ownable_init() internal onlyInitializing {\n __Ownable_init_unchained();\n }\n\n function __Ownable_init_unchained() internal onlyInitializing {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n _checkOwner();\n _;\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if the sender is not the owner.\n */\n function _checkOwner() internal view virtual {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby disabling any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)\n\npragma solidity ^0.8.2;\n\nimport \"../../utils/AddressUpgradeable.sol\";\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```solidity\n * contract MyToken is ERC20Upgradeable {\n * function initialize() initializer public {\n * __ERC20_init(\"MyToken\", \"MTK\");\n * }\n * }\n *\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n * function initializeV2() reinitializer(2) public {\n * __ERC20Permit_init(\"MyToken\");\n * }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n * _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n /**\n * @dev Indicates that the contract has been initialized.\n * @custom:oz-retyped-from bool\n */\n uint8 private _initialized;\n\n /**\n * @dev Indicates that the contract is in the process of being initialized.\n */\n bool private _initializing;\n\n /**\n * @dev Triggered when the contract has been initialized or reinitialized.\n */\n event Initialized(uint8 version);\n\n /**\n * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n * `onlyInitializing` functions can be used to initialize parent contracts.\n *\n * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a\n * constructor.\n *\n * Emits an {Initialized} event.\n */\n modifier initializer() {\n bool isTopLevelCall = !_initializing;\n require(\n (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),\n \"Initializable: contract is already initialized\"\n );\n _initialized = 1;\n if (isTopLevelCall) {\n _initializing = true;\n }\n _;\n if (isTopLevelCall) {\n _initializing = false;\n emit Initialized(1);\n }\n }\n\n /**\n * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n * used to initialize parent contracts.\n *\n * A reinitializer may be used after the original initialization step. This is essential to configure modules that\n * are added through upgrades and that require initialization.\n *\n * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\n * cannot be nested. If one is invoked in the context of another, execution will revert.\n *\n * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n * a contract, executing them in the right order is up to the developer or operator.\n *\n * WARNING: setting the version to 255 will prevent any future reinitialization.\n *\n * Emits an {Initialized} event.\n */\n modifier reinitializer(uint8 version) {\n require(!_initializing && _initialized < version, \"Initializable: contract is already initialized\");\n _initialized = version;\n _initializing = true;\n _;\n _initializing = false;\n emit Initialized(version);\n }\n\n /**\n * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n * {initializer} and {reinitializer} modifiers, directly or indirectly.\n */\n modifier onlyInitializing() {\n require(_initializing, \"Initializable: contract is not initializing\");\n _;\n }\n\n /**\n * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n * through proxies.\n *\n * Emits an {Initialized} event the first time it is successfully executed.\n */\n function _disableInitializers() internal virtual {\n require(!_initializing, \"Initializable: contract is initializing\");\n if (_initialized != type(uint8).max) {\n _initialized = type(uint8).max;\n emit Initialized(type(uint8).max);\n }\n }\n\n /**\n * @dev Returns the highest version that has been initialized. See {reinitializer}.\n */\n function _getInitializedVersion() internal view returns (uint8) {\n return _initialized;\n }\n\n /**\n * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\n */\n function _isInitializing() internal view returns (bool) {\n return _initializing;\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/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/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" + }, + "@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/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/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" + }, + "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/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/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 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 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\";\nimport { VToken } from \"../VToken.sol\";\nimport { PoolRegistry } from \"../Pool/PoolRegistry.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 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 PoolRegistry(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/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" + } + }, + "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 + } + } +} \ No newline at end of file diff --git a/hardhat.config.ts b/hardhat.config.ts index 295f3e671..d310b470e 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -162,12 +162,17 @@ const config: HardhatUserConfig = { chainId: 97, live: true, gasPrice: 20000000000, - accounts: process.env.TESTNET_PRIVATE_KEY ? [process.env.TESTNET_PRIVATE_KEY] : [], + accounts: { + mnemonic: process.env.MNEMONIC || "", + }, }, bscmainnet: { - url: "http://127.0.0.1:1248", + url: "https://bsc-dataseed.binance.org/", chainId: 56, timeout: 1200000, + accounts: { + mnemonic: process.env.MNEMONIC || "", + }, }, }, gasReporter: { diff --git a/tests/integration/index.ts b/tests/integration/index.ts index e8d78e17d..ef2573e35 100644 --- a/tests/integration/index.ts +++ b/tests/integration/index.ts @@ -163,7 +163,7 @@ describe("Positive Cases", function () { ); }); - it.only("PoolRegistry has the required permissions ", async function () { + it("PoolRegistry has the required permissions ", async function () { let canCall = await AccessControlManager.connect(Comptroller.address).isAllowedToCall( PoolRegistry.address, "setCollateralFactor(address,uint256,uint256)", From 31a4c449a1386f8bb222a3263cc0b39aeec4b85a Mon Sep 17 00:00:00 2001 From: Narayan Prusty Date: Mon, 9 Oct 2023 17:36:00 +0100 Subject: [PATCH 18/33] fix: fixed integration tests --- contracts/RiskFund/ReserveHelpers.sol | 4 ++++ deploy/014-riskfund-protocolshare.ts | 8 ++++---- tests/hardhat/Fork/RiskFund.ts | 8 ++++---- tests/hardhat/Fork/RiskFundSwap.ts | 4 ++-- tests/hardhat/ProtocolShareReserve.ts | 2 +- tests/integration/index.ts | 2 +- 6 files changed, 16 insertions(+), 12 deletions(-) diff --git a/contracts/RiskFund/ReserveHelpers.sol b/contracts/RiskFund/ReserveHelpers.sol index 3bb5cea7d..24603af9f 100644 --- a/contracts/RiskFund/ReserveHelpers.sol +++ b/contracts/RiskFund/ReserveHelpers.sol @@ -72,6 +72,10 @@ contract ReserveHelpers is Ownable2StepUpgradeable { /// @custom:oz-upgrades-unsafe-allow constructor constructor(address corePoolComptroller_, address vbnb_, address nativeWrapped_) { + ensureNonzeroAddress(corePoolComptroller_); + ensureNonzeroAddress(vbnb_); + ensureNonzeroAddress(nativeWrapped_); + CORE_POOL_COMPTROLLER = corePoolComptroller_; VBNB = vbnb_; NATIVE_WRAPPED = nativeWrapped_; diff --git a/deploy/014-riskfund-protocolshare.ts b/deploy/014-riskfund-protocolshare.ts index b28ccde9b..2ae113fd0 100644 --- a/deploy/014-riskfund-protocolshare.ts +++ b/deploy/014-riskfund-protocolshare.ts @@ -50,8 +50,8 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { log: true, args: [ corePoolComptrollerAddress, - preconfiguredAddresses.VBNB_CorePool || ethers.constants.AddressZero, - preconfiguredAddresses.WBNB || ethers.constants.AddressZero, + preconfiguredAddresses.VBNB_CorePool || "0x0000000000000000000000000000000000000001", + preconfiguredAddresses.WBNB || "0x0000000000000000000000000000000000000002", ], }); @@ -103,8 +103,8 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { log: true, args: [ corePoolComptrollerAddress, - preconfiguredAddresses.VBNB_CorePool || ethers.constants.AddressZero, - preconfiguredAddresses.WBNB || ethers.constants.AddressZero, + preconfiguredAddresses.VBNB_CorePool || "0x0000000000000000000000000000000000000001", + preconfiguredAddresses.WBNB || "0x0000000000000000000000000000000000000002", ], }); diff --git a/tests/hardhat/Fork/RiskFund.ts b/tests/hardhat/Fork/RiskFund.ts index 0d812378d..c5a2861af 100644 --- a/tests/hardhat/Fork/RiskFund.ts +++ b/tests/hardhat/Fork/RiskFund.ts @@ -135,7 +135,7 @@ const riskFundFixture = async (): Promise => { RiskFund, [pancakeSwapRouter.address, convertToUnit(10, 18), BUSD.address, accessControlManager.address, 150], { - constructorArgs: [fakeCorePoolComptroller.address, ethers.constants.AddressZero, ethers.constants.AddressZero], + constructorArgs: [fakeCorePoolComptroller.address, "0x0000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000002"], }, )) as RiskFund; await riskFund.setShortfallContractAddress(shortfall.address); @@ -146,7 +146,7 @@ const riskFundFixture = async (): Promise => { ProtocolShareReserve, [fakeProtocolIncome.address, riskFund.address], { - constructorArgs: [fakeCorePoolComptroller.address, ethers.constants.AddressZero, ethers.constants.AddressZero], + constructorArgs: [fakeCorePoolComptroller.address, "0x0000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000002"], }, )) as ProtocolShareReserve; @@ -528,8 +528,8 @@ describe("Risk Fund: Tests", function () { { constructorArgs: [ fakeCorePoolComptroller.address, - ethers.constants.AddressZero, - ethers.constants.AddressZero, + "0x0000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000002", ], }, ); diff --git a/tests/hardhat/Fork/RiskFundSwap.ts b/tests/hardhat/Fork/RiskFundSwap.ts index 66a0a1b9d..4074b9d01 100644 --- a/tests/hardhat/Fork/RiskFundSwap.ts +++ b/tests/hardhat/Fork/RiskFundSwap.ts @@ -118,7 +118,7 @@ const riskFundFixture = async (): Promise => { RiskFund, [pancakeSwapRouter.address, parseUnits("10", 18), BUSD.address, fakeAccessControlManager.address, maxLoopsLimit], { - constructorArgs: [fakeCorePoolComptroller.address, ethers.constants.AddressZero, ethers.constants.AddressZero], + constructorArgs: [fakeCorePoolComptroller.address, "0x0000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000002"], }, )) as RiskFund; @@ -130,7 +130,7 @@ const riskFundFixture = async (): Promise => { ProtocolShareReserve, [fakeProtocolIncome.address, riskFund.address], { - constructorArgs: [fakeCorePoolComptroller.address, ethers.constants.AddressZero, ethers.constants.AddressZero], + constructorArgs: [fakeCorePoolComptroller.address, "0x0000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000002"], }, )) as ProtocolShareReserve; diff --git a/tests/hardhat/ProtocolShareReserve.ts b/tests/hardhat/ProtocolShareReserve.ts index 164326ee7..110665d53 100644 --- a/tests/hardhat/ProtocolShareReserve.ts +++ b/tests/hardhat/ProtocolShareReserve.ts @@ -38,7 +38,7 @@ const fixture = async (): Promise => { ProtocolShareReserve, [fakeProtocolIncome.address, fakeRiskFund.address], { - constructorArgs: [fakeCorePoolComptroller.address, ethers.constants.AddressZero, ethers.constants.AddressZero], + constructorArgs: [fakeCorePoolComptroller.address, "0x0000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000002"], }, ); diff --git a/tests/integration/index.ts b/tests/integration/index.ts index ef2573e35..f68c80245 100644 --- a/tests/integration/index.ts +++ b/tests/integration/index.ts @@ -157,7 +157,7 @@ describe("Positive Cases", function () { } = fixture); }); describe("Setup", () => { - it("PoolRegistry should be initialized properly", async function () { + it.only("PoolRegistry should be initialized properly", async function () { await expect(PoolRegistry.initialize(ethers.constants.AddressZero)).to.be.revertedWith( "Initializable: contract is already initialized", ); From d72e82debb4eb905871b778eab9409a2ee59c186 Mon Sep 17 00:00:00 2001 From: Narayan Prusty Date: Mon, 9 Oct 2023 17:47:52 +0100 Subject: [PATCH 19/33] chore: fixed lint --- contracts/RiskFund/ReserveHelpers.sol | 2 +- .../bscmainnet/RiskFund_Implementation.json | 149 ++++++++++++------ .../f237ea044837d6f4ff4c08abcdd27558.json | 132 ++++++++++++++++ .../bsctestnet/RiskFund_Implementation.json | 52 +++--- .../0c597ac2b90fc7d0b2be179fa6482d23.json | 6 +- .../f237ea044837d6f4ff4c08abcdd27558.json | 132 ++++++++++++++++ tests/hardhat/Fork/RiskFund.ts | 12 +- tests/hardhat/Fork/RiskFundSwap.ts | 12 +- tests/hardhat/ProtocolShareReserve.ts | 6 +- 9 files changed, 421 insertions(+), 82 deletions(-) create mode 100644 deployments/bscmainnet/solcInputs/f237ea044837d6f4ff4c08abcdd27558.json create mode 100644 deployments/bsctestnet/solcInputs/f237ea044837d6f4ff4c08abcdd27558.json diff --git a/contracts/RiskFund/ReserveHelpers.sol b/contracts/RiskFund/ReserveHelpers.sol index 24603af9f..622bdc66c 100644 --- a/contracts/RiskFund/ReserveHelpers.sol +++ b/contracts/RiskFund/ReserveHelpers.sol @@ -75,7 +75,7 @@ contract ReserveHelpers is Ownable2StepUpgradeable { ensureNonzeroAddress(corePoolComptroller_); ensureNonzeroAddress(vbnb_); ensureNonzeroAddress(nativeWrapped_); - + CORE_POOL_COMPTROLLER = corePoolComptroller_; VBNB = vbnb_; NATIVE_WRAPPED = nativeWrapped_; diff --git a/deployments/bscmainnet/RiskFund_Implementation.json b/deployments/bscmainnet/RiskFund_Implementation.json index 735e68cb8..3f1f4aeac 100644 --- a/deployments/bscmainnet/RiskFund_Implementation.json +++ b/deployments/bscmainnet/RiskFund_Implementation.json @@ -1,8 +1,24 @@ { - "address": "0x87ac8dD81Ec00D2183a04D22884e7FC67f6ce0C8", + "address": "0x470443271a416214841a617cbFB8b2f060dDb830", "abi": [ { - "inputs": [], + "inputs": [ + { + "internalType": "address", + "name": "corePoolComptroller_", + "type": "address" + }, + { + "internalType": "address", + "name": "vbnb_", + "type": "address" + }, + { + "internalType": "address", + "name": "nativeWrapped_", + "type": "address" + } + ], "stateMutability": "nonpayable", "type": "constructor" }, @@ -331,6 +347,45 @@ "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", @@ -756,39 +811,43 @@ "type": "function" } ], - "transactionHash": "0xf82fe32de3f970194e6fb1845418d41601b6275718eef7f5aee07d470fa44800", + "transactionHash": "0xf1bb734413dee3f943e457c8734e4b66e3dd8dd9783329b88c273f4780e95ef6", "receipt": { "to": null, - "from": "0x55A9f5374Af30E3045FB491f1da3C2E8a74d168D", - "contractAddress": "0x87ac8dD81Ec00D2183a04D22884e7FC67f6ce0C8", - "transactionIndex": 85, - "gasUsed": "2577667", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000400000000000000000000000080000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xc4f776e64231aec8f09c564b9d4007e6583fe79370c927b73600dab2c81997bb", - "transactionHash": "0xf82fe32de3f970194e6fb1845418d41601b6275718eef7f5aee07d470fa44800", + "from": "0x8BDA9f9E1fEF0DFd404Fef338D9fE4c543d172e1", + "contractAddress": "0x470443271a416214841a617cbFB8b2f060dDb830", + "transactionIndex": 46, + "gasUsed": "2769907", + "logsBloom": "0x00000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000080000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x5265158486084e468ed2c2e0d3ff83459eb807e24726f2936f01c910a19c6af7", + "transactionHash": "0xf1bb734413dee3f943e457c8734e4b66e3dd8dd9783329b88c273f4780e95ef6", "logs": [ { - "transactionIndex": 85, - "blockNumber": 31670879, - "transactionHash": "0xf82fe32de3f970194e6fb1845418d41601b6275718eef7f5aee07d470fa44800", - "address": "0x87ac8dD81Ec00D2183a04D22884e7FC67f6ce0C8", + "transactionIndex": 46, + "blockNumber": 32457691, + "transactionHash": "0xf1bb734413dee3f943e457c8734e4b66e3dd8dd9783329b88c273f4780e95ef6", + "address": "0x470443271a416214841a617cbFB8b2f060dDb830", "topics": ["0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498"], "data": "0x00000000000000000000000000000000000000000000000000000000000000ff", - "logIndex": 110, - "blockHash": "0xc4f776e64231aec8f09c564b9d4007e6583fe79370c927b73600dab2c81997bb" + "logIndex": 220, + "blockHash": "0x5265158486084e468ed2c2e0d3ff83459eb807e24726f2936f01c910a19c6af7" } ], - "blockNumber": 31670879, - "cumulativeGasUsed": "7246673", + "blockNumber": 32457691, + "cumulativeGasUsed": "11147413", "status": 1, "byzantium": true }, - "args": [], + "args": [ + "0xfD36E2c2a6789Db23113685031d7F16329158384", + "0xA07c5b74C9B40447a954e1466938b865b6BBea36", + "0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c" + ], "numDeployments": 1, - "solcInputHash": "394b060e0e484d4aa39aea929deecf07", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"ApproveFailed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"loopsLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requiredLoops\",\"type\":\"uint256\"}],\"name\":\"MaxLoopsLimitExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"calledContract\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"methodSignature\",\"type\":\"string\"}],\"name\":\"Unauthorized\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"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\":\"oldConvertibleBaseAsset\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newConvertibleBaseAsset\",\"type\":\"address\"}],\"name\":\"ConvertibleBaseAssetUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldMaxLoopsLimit\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newmaxLoopsLimit\",\"type\":\"uint256\"}],\"name\":\"MaxLoopsLimitUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldMinAmountToConvert\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newMinAmountToConvert\",\"type\":\"uint256\"}],\"name\":\"MinAmountToConvertUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldAccessControlManager\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newAccessControlManager\",\"type\":\"address\"}],\"name\":\"NewAccessControlManager\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferStarted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"oldPancakeSwapRouter\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newPancakeSwapRouter\",\"type\":\"address\"}],\"name\":\"PancakeSwapRouterUpdated\",\"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\":\"oldShortfallContract\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"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\":\"totalAmount\",\"type\":\"uint256\"}],\"name\":\"SwappedPoolsAssets\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"SweepToken\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"TransferredReserveForAuction\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"accessControlManager\",\"outputs\":[{\"internalType\":\"contract IAccessControlManagerV8\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"assetsReserves\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"convertibleBaseAsset\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"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\":\"comptroller\",\"type\":\"address\"}],\"name\":\"getPoolsBaseAssetReserves\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"pancakeSwapRouter_\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmountToConvert_\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"convertibleBaseAsset_\",\"type\":\"address\"},{\"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\":\"minAmountToConvert\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pancakeSwapRouter\",\"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\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"accessControlManager_\",\"type\":\"address\"}],\"name\":\"setAccessControlManager\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_convertibleBaseAsset\",\"type\":\"address\"}],\"name\":\"setConvertibleBaseAsset\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"limit\",\"type\":\"uint256\"}],\"name\":\"setMaxLoopsLimit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minAmountToConvert_\",\"type\":\"uint256\"}],\"name\":\"setMinAmountToConvert\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"pancakeSwapRouter_\",\"type\":\"address\"}],\"name\":\"setPancakeSwapRouter\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"poolRegistry_\",\"type\":\"address\"}],\"name\":\"setPoolRegistry\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"shortfallContractAddress_\",\"type\":\"address\"}],\"name\":\"setShortfallContractAddress\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"shortfall\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"markets\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"amountsOutMin\",\"type\":\"uint256[]\"},{\"internalType\":\"address[][]\",\"name\":\"paths\",\"type\":\"address[][]\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"swapPoolsAssets\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"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\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transferReserveForAuction\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"}],\"name\":\"updateAssetsState\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Venus\",\"details\":\"This contract does not support BNB.\",\"kind\":\"dev\",\"methods\":{\"acceptOwnership()\":{\"details\":\"The new owner accepts the ownership transfer.\"},\"constructor\":{\"custom:oz-upgrades-unsafe-allow\":\"constructor\",\"details\":\"Note that the contract is upgradeable. Use initialize() or reinitializers to set the state variables.\"},\"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.\"}},\"getPoolsBaseAssetReserves(address)\":{\"params\":{\"comptroller\":\"Comptroller address(pool).\"},\"returns\":{\"_0\":\"Base Asset's reserve in risk fund.\"}},\"initialize(address,uint256,address,address,uint256)\":{\"custom:error\":\"ZeroAddressNotAllowed is thrown when PCS router address is zeroZeroAddressNotAllowed is thrown when convertible base asset address is zero\",\"params\":{\"accessControlManager_\":\"Address of the access control contract\",\"convertibleBaseAsset_\":\"Address of the base asset\",\"loopsLimit_\":\"Limit for the loops in the contract to avoid DOS\",\"minAmountToConvert_\":\"Minimum amount assets must be worth to convert into base asset\",\"pancakeSwapRouter_\":\"Address of the PancakeSwap router\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"pendingOwner()\":{\"details\":\"Returns the address of the pending owner.\"},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner.\"},\"setAccessControlManager(address)\":{\"custom:access\":\"Only Governance\",\"custom:event\":\"Emits NewAccessControlManager event\",\"details\":\"Admin function to set address of AccessControlManager\",\"params\":{\"accessControlManager_\":\"The new address of the AccessControlManager\"}},\"setConvertibleBaseAsset(address)\":{\"params\":{\"_convertibleBaseAsset\":\"Address for new convertible base asset.\"}},\"setMaxLoopsLimit(uint256)\":{\"params\":{\"limit\":\"Limit for the max loops can execute at a time\"}},\"setMinAmountToConvert(uint256)\":{\"params\":{\"minAmountToConvert_\":\"Min amount to convert.\"}},\"setPancakeSwapRouter(address)\":{\"custom:error\":\"ZeroAddressNotAllowed is thrown when PCS router address is zero\",\"params\":{\"pancakeSwapRouter_\":\"Address of the PancakeSwap router\"}},\"setPoolRegistry(address)\":{\"custom:error\":\"ZeroAddressNotAllowed is thrown when pool registry address is zero\",\"params\":{\"poolRegistry_\":\"Address of the pool registry\"}},\"setShortfallContractAddress(address)\":{\"custom:error\":\"ZeroAddressNotAllowed is thrown when shortfall contract address is zero\",\"params\":{\"shortfallContractAddress_\":\"Address of the auction contract\"}},\"swapPoolsAssets(address[],uint256[],address[][],uint256)\":{\"custom:error\":\"ZeroAddressNotAllowed is thrown if PoolRegistry contract address is not configured\",\"params\":{\"amountsOutMin\":\"Minimum amount to receive for swap\",\"deadline\":\"Deadline for the swap\",\"markets\":\"Array of vTokens whose assets to swap for base asset\",\"paths\":\"A path consisting of PCS token pairs for each swap\"},\"returns\":{\"_0\":\"Number of swapped tokens\"}},\"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.\"},\"transferReserveForAuction(address,uint256)\":{\"params\":{\"amount\":\"Amount to be transferred to auction contract.\",\"comptroller\":\"Comptroller of the pool.\"},\"returns\":{\"_0\":\"Number reserved tokens.\"}},\"updateAssetsState(address,address)\":{\"params\":{\"asset\":\"Asset address.\",\"comptroller\":\"Comptroller address(pool).\"}}},\"title\":\"RiskFund\",\"version\":1},\"userdoc\":{\"errors\":{\"ApproveFailed()\":[{\"notice\":\"Thrown if a contract is unable to approve a transfer\"}],\"MaxLoopsLimitExceeded(uint256,uint256)\":[{\"notice\":\"Thrown an error on maxLoopsLimit exceeds for any loop\"}],\"Unauthorized(address,address,string)\":[{\"notice\":\"Thrown when the action is prohibited by AccessControlManager\"}],\"ZeroAddressNotAllowed()\":[{\"notice\":\"Thrown if the supplied address is a zero address where it is not allowed\"}]},\"events\":{\"AssetsReservesUpdated(address,address,uint256)\":{\"notice\":\"Event emitted after the update of the assets reserves.\"},\"ConvertibleBaseAssetUpdated(address,address)\":{\"notice\":\"Emitted when convertible base asset is updated\"},\"MaxLoopsLimitUpdated(uint256,uint256)\":{\"notice\":\"Emitted when max loops limit is set\"},\"MinAmountToConvertUpdated(uint256,uint256)\":{\"notice\":\"Emitted when minimum amount to convert is updated\"},\"NewAccessControlManager(address,address)\":{\"notice\":\"Emitted when access control manager contract address is changed\"},\"PancakeSwapRouterUpdated(address,address)\":{\"notice\":\"Emitted when PancakeSwap router contract address is updated\"},\"PoolRegistryUpdated(address,address)\":{\"notice\":\"Emitted when pool registry address is updated\"},\"ShortfallContractUpdated(address,address)\":{\"notice\":\"Emitted when shortfall contract address is updated\"},\"SwappedPoolsAssets(address[],uint256[],uint256)\":{\"notice\":\"Emitted when pools assets are swapped\"},\"SweepToken(address,address,uint256)\":{\"notice\":\"event emitted on sweep token success\"},\"TransferredReserveForAuction(address,uint256)\":{\"notice\":\"Emitted when reserves are transferred for auction\"}},\"kind\":\"user\",\"methods\":{\"accessControlManager()\":{\"notice\":\"Returns the address of the access control manager contract\"},\"getPoolAssetReserve(address,address)\":{\"notice\":\"Get the Amount of the asset in the risk fund for the specific pool.\"},\"getPoolsBaseAssetReserves(address)\":{\"notice\":\"Get the Amount of the Base asset in the risk fund for the specific pool.\"},\"initialize(address,uint256,address,address,uint256)\":{\"notice\":\"Initializes the deployer to owner.\"},\"setAccessControlManager(address)\":{\"notice\":\"Sets the address of AccessControlManager\"},\"setConvertibleBaseAsset(address)\":{\"notice\":\"Sets a new convertible base asset\"},\"setMaxLoopsLimit(uint256)\":{\"notice\":\"Set the limit for the loops can iterate to avoid the DOS\"},\"setMinAmountToConvert(uint256)\":{\"notice\":\"Min amount to convert setter\"},\"setPancakeSwapRouter(address)\":{\"notice\":\"PancakeSwap router address setter\"},\"setPoolRegistry(address)\":{\"notice\":\"Pool registry setter\"},\"setShortfallContractAddress(address)\":{\"notice\":\"Shortfall contract address setter\"},\"swapPoolsAssets(address[],uint256[],address[][],uint256)\":{\"notice\":\"Swap array of pool assets into base asset's tokens of at least a minimum amount\"},\"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\"},\"transferReserveForAuction(address,uint256)\":{\"notice\":\"Transfer tokens for auction.\"},\"updateAssetsState(address,address)\":{\"notice\":\"Update the reserve of the asset for the specific pool after transferring to risk fund.\"}},\"notice\":\"Contract with basic features to track/hold different assets for different Comptrollers.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/RiskFund/RiskFund.sol\":\"RiskFund\"},\"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/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\",\"keccak256\":\"0x7e4d140bd2a5671389ad7a3975b65d05a4f750daf6a61c16139d123d9782b96e\",\"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(\\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\",\"keccak256\":\"0x6b903c298c9e2c3aaed29b4a1f76ace9fc24e50a48db22111bfc190a1a25c499\",\"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/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/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\",\"keccak256\":\"0xb16c27419547f251890c508ee9244b6515f9fd3c35c8ba82f1b485f50dc854c4\",\"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/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\",\"keccak256\":\"0x60505497b334ce53f01cdaeedcee4cfc9dfd153b69e9ceecd165282c9bd2c031\",\"license\":\"MIT\"},\"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": "0x60806040523480156200001157600080fd5b506200001c62000022565b620000e3565b600054610100900460ff16156200008f5760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b60005460ff90811614620000e1576000805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b612d2d80620000f36000396000f3fe608060405234801561001057600080fd5b50600436106101a95760003560e01c806377d4937f116100f9578063afcff50f11610097578063c8ecc0d311610071578063c8ecc0d31461037b578063e30c39781461038f578063f2fde38b146103a0578063fe3da984146103b357600080fd5b8063afcff50f1461034e578063b4a0bdf314610361578063be26317e1461037257600080fd5b806380d45a2d116100d357806380d45a2d146103045780638da5cb5b14610317578063a69bd19e14610328578063aac59a751461033b57600080fd5b806377d4937f146102d657806379ba5097146102e95780637b77cd6a146102f157600080fd5b80632e688141116101665780635f30e37b116101405780635f30e37b146102955780636fb05275146102a8578063715018a6146102bb578063746460a9146102c357600080fd5b80632e6881411461024f578063439b5517146102625780634dd9584a1461028257600080fd5b80630a9837c5146101ae5780630e32cb86146101d457806319b1faef146101e95780632455899514610215578063258836fe146102295780632a1d05471461023c575b600080fd5b6101c16101bc3660046124a8565b6103bd565b6040519081526020015b60405180910390f35b6101e76101e23660046124d4565b61058c565b005b61012e546101fd906001600160a01b031681565b6040516001600160a01b0390911681526020016101cb565b61012f546101fd906001600160a01b031681565b6101e76102373660046124f1565b6105a0565b6101e761024a36600461252a565b610731565b6101e761025d3660046124d4565b610922565b6101c16102703660046124d4565b60c96020526000908152604090205481565b6101e76102903660046124d4565b610a27565b6101c16102a33660046125d1565b610a8b565b6101c16102b63660046124f1565b610fdf565b6101e7611093565b6101e76102d1366004612674565b6110a7565b6101e76102e43660046124d4565b61114c565b6101e76111b0565b6101e76102ff3660046124d4565b611227565b6101e7610312366004612674565b61128a565b6033546001600160a01b03166101fd565b6101c16103363660046124d4565b61129b565b6101e76103493660046124f1565b611387565b60cb546101fd906001600160a01b031681565b6097546001600160a01b03166101fd565b6101c160fb5481565b61012d546101fd906001600160a01b031681565b6065546001600160a01b03166101fd565b6101e76103ae3660046124d4565b611395565b6101c16101305481565b6000600260cc54036103ea5760405162461bcd60e51b81526004016103e19061268d565b60405180910390fd5b600260cc5561012e546001600160a01b03163381146104625760405162461bcd60e51b815260206004820152602e60248201527f5269736b2066756e643a204f6e6c792063616c6c61626c652062792053686f7260448201526d1d19985b1b0818dbdb9d1c9858dd60921b60648201526084016103e1565b6001600160a01b03808516600090815260ca6020908152604080832061012d54909416835292905220548311156104e95760405162461bcd60e51b815260206004820152602560248201527f5269736b2046756e643a20496e73756666696369656e7420706f6f6c2072657360448201526432b93b329760d91b60648201526084016103e1565b6001600160a01b03808516600081815260ca6020908152604080832061012d80548716855290835281842080548a9003905554909416825260c990528290208054869003905590517fc8d0a37ed16dfaa43514df00e18f478b60d5cc7b4bfc687103948b9020f737fd906105609086815260200190565b60405180910390a261012d54610580906001600160a01b03168285611406565b5050600160cc55919050565b61059461145d565b61059d816114b7565b50565b6105a861145d565b600260cc54036105ca5760405162461bcd60e51b81526004016103e19061268d565b600260cc556105d881611575565b6040516370a0823160e01b815230600482015260009081906001600160a01b038516906370a0823190602401602060405180830381865afa158015610621573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061064591906126b1565b6001600160a01b038516600090815260c9602052604090205490915081116106bb5760405162461bcd60e51b815260206004820152602360248201527f5265736572766548656c706572733a205a65726f20737572706c757320746f6b604482015262656e7360e81b60648201526084016103e1565b6001600160a01b03848116600081815260c960209081526040918290205491519185038083529550928616927f6d25be279134f4ecaa4770aff0c3d916d9e7c5ef37b65ed95dbdba411f5d54d5910160405180910390a36107266001600160a01b0385168484611406565b5050600160cc555050565b600054610100900460ff16158080156107515750600054600160ff909116105b8061076b5750303b15801561076b575060005460ff166001145b6107ce5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084016103e1565b6000805460ff1916600117905580156107f1576000805461ff0019166101001790555b6107fa86611575565b61080384611575565b600085116108235760405162461bcd60e51b81526004016103e1906126ca565b600082116108825760405162461bcd60e51b815260206004820152602660248201527f5269736b2046756e643a204c6f6f7073206c696d69742063616e206e6f74206260448201526565207a65726f60d01b60648201526084016103e1565b61088a61159c565b610893836115cb565b61012f80546001600160a01b038089166001600160a01b03199283161790925561013087905561012d8054928716929091169190911790556108d4826115f2565b801561091a576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050565b6109606040518060400160405280602081526020017f736574436f6e7665727469626c6542617365417373657428616464726573732981525061168c565b6001600160a01b0381166109d45760405162461bcd60e51b815260206004820152603560248201527f5269736b2046756e643a206e657720636f6e7665727469626c65206261736520604482015274185cdcd95d081859191c995cdcc81a5b9d985b1a59605a1b60648201526084016103e1565b61012d80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f5fa61583da12070720613fefdd68cc6c0e464a71e009742526bd2b2e0ac62cd290600090a35050565b610a2f61145d565b610a3881611575565b61012f80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907fd37b9d138f53ea58d7e50292588239a46efa8f523966febf4066da96defc77fd90600090a35050565b6000600260cc5403610aaf5760405162461bcd60e51b81526004016103e19061268d565b600260cc81905550610ad8604051806060016040528060388152602001612cc06038913961168c565b42821015610b285760405162461bcd60e51b815260206004820152601a60248201527f5269736b2066756e643a20646561646c696e652070617373656400000000000060448201526064016103e1565b60cb546001600160a01b0316610b3d81611575565b878614610bb25760405162461bcd60e51b815260206004820152603860248201527f5269736b2066756e643a206d61726b65747320616e6420616d6f756e74734f7560448201527f744d696e2061726520756e657175616c206c656e67746873000000000000000060648201526084016103e1565b878414610c1a5760405162461bcd60e51b815260206004820152603060248201527f5269736b2066756e643a206d61726b65747320616e642070617468732061726560448201526f20756e657175616c206c656e6774687360801b60648201526084016103e1565b600088610c2681611726565b60005b81811015610f8c5760008c8c83818110610c4557610c45612712565b9050602002016020810190610c5a91906124d4565b6001600160a01b0316635fe3b5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c97573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cbb9190612728565b604051637aee632d60e01b81526001600160a01b038083166004830152919250600091871690637aee632d90602401600060405180830381865afa158015610d07573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610d2f91908101906127f5565b9050816001600160a01b031681604001516001600160a01b031614610da65760405162461bcd60e51b815260206004820152602760248201527f636f6d7074726f6c6c657220646f65736e277420657869737420706f6f6c20726044820152666567697374727960c81b60648201526084016103e1565b816001600160a01b0316633d98a1e58f8f86818110610dc757610dc7612712565b9050602002016020810190610ddc91906124d4565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa158015610e20573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e4491906128eb565b610e875760405162461bcd60e51b81526020600482015260146024820152731b585c9ad95d081a5cc81b9bdd081b1a5cdd195960621b60448201526064016103e1565b6000610ef68f8f86818110610e9e57610e9e612712565b9050602002016020810190610eb391906124d4565b848f8f88818110610ec657610ec6612712565b905060200201358e8e89818110610edf57610edf612712565b9050602002810190610ef1919061290d565b611757565b6001600160a01b03808516600090815260ca6020908152604080832061012d54909416835292905290812080549293508392909190610f3690849061296d565b909155505061012d546001600160a01b0316600090815260c9602052604081208054839290610f6690849061296d565b90915550610f769050818761296d565b955050505080610f8590612985565b9050610c29565b507fb17530966b045b50d4975e7f05048ca00d7335780c24f1c465165a4b94b2d37d8b8b8b8b86604051610fc49594939291906129e7565b60405180910390a150600160cc559998505050505050505050565b6000610fea82611575565b826001600160a01b0316627e3dd26040518163ffffffff1660e01b8152600401602060405180830381865afa158015611027573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061104b91906128eb565b6110675760405162461bcd60e51b81526004016103e190612a42565b506001600160a01b03918216600090815260ca6020908152604080832093909416825291909152205490565b61109b61145d565b6110a56000611cfa565b565b6110e56040518060400160405280601e81526020017f7365744d696e416d6f756e74546f436f6e766572742875696e7432353629000081525061168c565b600081116111055760405162461bcd60e51b81526004016103e1906126ca565b61013080549082905560408051828152602081018490527fada67d0d38fa20c8ae6a5c17cb9d60b0fe7f2d4e4f27ac9ee55e54ac88de9d8d91015b60405180910390a15050565b61115461145d565b61115d81611575565b61012e80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907fb6e5fcf02f7fbb8acfbaa3bac4fd5abf9ff51e3f2e8884b5498927179b211b2890600090a35050565b60655433906001600160a01b0316811461121e5760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b60648201526084016103e1565b61059d81611cfa565b61122f61145d565b61123881611575565b60cb80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907fa87b964d321035d2165e484ff4b722dd6eae30606c0b98887d2ed1a34e594bfe90600090a35050565b61129261145d565b61059d816115f2565b6000816001600160a01b0316627e3dd26040518163ffffffff1660e01b8152600401602060405180830381865afa1580156112da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112fe91906128eb565b6113595760405162461bcd60e51b815260206004820152602660248201527f5269736b2046756e643a20436f6d7074726f6c6c6572206164647265737320696044820152651b9d985b1a5960d21b60648201526084016103e1565b506001600160a01b03908116600090815260ca6020908152604080832061012d549094168352929052205490565b6113918282611d13565b5050565b61139d61145d565b606580546001600160a01b0383166001600160a01b031990911681179091556113ce6033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b179052611458908490612046565b505050565b6033546001600160a01b031633146110a55760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016103e1565b6001600160a01b03811661151b5760405162461bcd60e51b815260206004820152602560248201527f696e76616c696420616365737320636f6e74726f6c206d616e61676572206164604482015264647265737360d81b60648201526084016103e1565b609780546001600160a01b038381166001600160a01b031983168117909355604080519190921680825260208201939093527f66fd58e82f7b31a2a5c30e0888f3093efe4e111b00cd2b0c31fe014601293aa09101611140565b6001600160a01b03811661059d576040516342bcdf7f60e11b815260040160405180910390fd5b600054610100900460ff166115c35760405162461bcd60e51b81526004016103e190612a8d565b6110a561211b565b600054610100900460ff166105945760405162461bcd60e51b81526004016103e190612a8d565b60fb54811161164e5760405162461bcd60e51b815260206004820152602260248201527f436f6d7074726f6c6c65723a20496e76616c6964206d61784c6f6f70734c696d6044820152611a5d60f21b60648201526084016103e1565b60fb80549082905560408051828152602081018490527fc2d09fef144f7c8a86f71ea459f8fc17f675768eb1ae369cbd77fb31d467aafa9101611140565b6097546040516318c5e8ab60e01b81526000916001600160a01b0316906318c5e8ab906116bf9033908690600401612b04565b602060405180830381865afa1580156116dc573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061170091906128eb565b90508061139157333083604051634a3fa29360e01b81526004016103e193929190612b28565b60fb5481111561059d5760fb5460405163792bfb1b60e11b81526004810191909152602481018290526044016103e1565b6000836000036117cf5760405162461bcd60e51b815260206004820152603c60248201527f5269736b46756e643a20616d6f756e744f75744d696e206d757374206265206760448201527f726561746572207468616e203020746f20737761702076546f6b656e0000000060648201526084016103e1565b600080876001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa158015611810573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118349190612728565b61012d546001600160a01b03898116600090815260ca6020908152604080832084871684529091528120549394509116919081900361187a576000945050505050611cf1565b6000896001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa1580156118ba573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118de9190612728565b60405163b62cad6960e01b81526001600160a01b0385811660048301529192509082169063b62cad6990602401600060405180830381600087803b15801561192557600080fd5b505af1158015611939573d6000803e3d6000fd5b50506040805160208101918290526341976e0960e01b9091526001600160a01b03868116602483015260009350909150819084166341976e0960448301602060405180830381865afa158015611993573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119b791906126b1565b9052905060006119c7828c61214b565b905061013054811015611a2a5760405162461bcd60e51b815260206004820152602560248201527f5269736b46756e643a206d696e416d6f756e74546f436f6e766572742076696f6044820152641b185d195960da1b60648201526084016103e1565b6001600160a01b038616600090815260c9602052604081208054869290611a52908490612b54565b90915550506001600160a01b03808d16600090815260ca60209081526040808320938a1683529290529081208054869290611a8e908490612b54565b90915550506001600160a01b0386811690861614611ce357856001600160a01b03168a8a6000818110611ac357611ac3612712565b9050602002016020810190611ad891906124d4565b6001600160a01b031614611b545760405162461bcd60e51b815260206004820152603860248201527f5269736b46756e643a20737761702070617468206d757374207374617274207760448201527f6974682074686520756e6465726c79696e67206173736574000000000000000060648201526084016103e1565b6001600160a01b0385168a8a611b6b600182612b54565b818110611b7a57611b7a612712565b9050602002016020810190611b8f91906124d4565b6001600160a01b031614611c035760405162461bcd60e51b815260206004820152603560248201527f5269736b46756e643a2066696e616c6c792070617468206d75737420626520636044820152741bdb9d995c9d1a589b194818985cd948185cdcd95d605a1b60648201526084016103e1565b61012f546001600160a01b0390811690611c2190881682600061216b565b611c356001600160a01b038816828761216b565b6000816001600160a01b03166338ed1739878f8f8f30426040518763ffffffff1660e01b8152600401611c6d96959493929190612b6b565b6000604051808303816000875af1158015611c8c573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611cb49190810190612ba9565b905080611cc260018d612b54565b81518110611cd257611cd2612712565b602002602001015198505050611ce7565b8396505b5094955050505050505b95945050505050565b606580546001600160a01b031916905561059d81612257565b611d1c81611575565b816001600160a01b0316627e3dd26040518163ffffffff1660e01b8152600401602060405180830381865afa158015611d59573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d7d91906128eb565b611d995760405162461bcd60e51b81526004016103e190612a42565b60cb546001600160a01b031680611e0b5760405162461bcd60e51b815260206004820152603060248201527f5265736572766548656c706572733a20506f6f6c20526567697374727920616460448201526f191c995cdcc81a5cc81b9bdd081cd95d60821b60648201526084016103e1565b60405163266e0a7f60e01b81526001600160a01b03848116600483015283811660248301526000919083169063266e0a7f90604401602060405180830381865afa158015611e5d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e819190612728565b6001600160a01b031603611ef25760405162461bcd60e51b815260206004820152603260248201527f5265736572766548656c706572733a2054686520706f6f6c20646f65736e2774604482015271081cdd5c1c1bdc9d081d1a1948185cdcd95d60721b60648201526084016103e1565b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa158015611f39573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f5d91906126b1565b6001600160a01b038416600090815260c960205260409020549091508082111561203f576001600160a01b038416600090815260c960205260408120805483850392839291611fad90849061296d565b90915550506001600160a01b03808716600090815260ca6020908152604080832093891683529290529081208054839290611fe990849061296d565b92505081905550846001600160a01b0316866001600160a01b03167fc39e3e80c0219fde334a8cb5d8468b628482e23388b6e809c90cb00c63c8ce388360405161203591815260200190565b60405180910390a3505b5050505050565b600061209b826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166122a99092919063ffffffff16565b90508051600014806120bc5750808060200190518101906120bc91906128eb565b6114585760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b60648201526084016103e1565b600054610100900460ff166121425760405162461bcd60e51b81526004016103e190612a8d565b6110a533611cfa565b60008061215884846122b8565b9050612163816122e9565b949350505050565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663095ea7b360e01b1790529151909160009182918716906121c9908590612c4f565b6000604051808303816000865af19150503d8060008114612206576040519150601f19603f3d011682016040523d82523d6000602084013e61220b565b606091505b5091509150811580612239575080511580159061223957508080602001905181019061223791906128eb565b155b1561091a57604051633e3f8f7360e01b815260040160405180910390fd5b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60606121638484600085612307565b60408051602081019091526000815260405180602001604052806122e08560000151856123e2565b90529392505050565b805160009061230190670de0b6b3a764000090612c6b565b92915050565b6060824710156123685760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b60648201526084016103e1565b600080866001600160a01b031685876040516123849190612c4f565b60006040518083038185875af1925050503d80600081146123c1576040519150601f19603f3d011682016040523d82523d6000602084013e6123c6565b606091505b50915091506123d7878383876123f5565b979650505050505050565b60006123ee8284612c8d565b9392505050565b6060831561246457825160000361245d576001600160a01b0385163b61245d5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016103e1565b5081612163565b61216383838151156124795781518083602001fd5b8060405162461bcd60e51b81526004016103e19190612cac565b6001600160a01b038116811461059d57600080fd5b600080604083850312156124bb57600080fd5b82356124c681612493565b946020939093013593505050565b6000602082840312156124e657600080fd5b81356123ee81612493565b6000806040838503121561250457600080fd5b823561250f81612493565b9150602083013561251f81612493565b809150509250929050565b600080600080600060a0868803121561254257600080fd5b853561254d81612493565b945060208601359350604086013561256481612493565b9250606086013561257481612493565b949793965091946080013592915050565b60008083601f84011261259757600080fd5b50813567ffffffffffffffff8111156125af57600080fd5b6020830191508360208260051b85010111156125ca57600080fd5b9250929050565b60008060008060008060006080888a0312156125ec57600080fd5b873567ffffffffffffffff8082111561260457600080fd5b6126108b838c01612585565b909950975060208a013591508082111561262957600080fd5b6126358b838c01612585565b909750955060408a013591508082111561264e57600080fd5b5061265b8a828b01612585565b989b979a50959894979596606090950135949350505050565b60006020828403121561268657600080fd5b5035919050565b6020808252600a90820152691c994b595b9d195c995960b21b604082015260600190565b6000602082840312156126c357600080fd5b5051919050565b60208082526028908201527f5269736b2046756e643a20496e76616c6964206d696e20616d6f756e7420746f6040820152670818dbdb9d995c9d60c21b606082015260800190565b634e487b7160e01b600052603260045260246000fd5b60006020828403121561273a57600080fd5b81516123ee81612493565b634e487b7160e01b600052604160045260246000fd5b60405160a0810167ffffffffffffffff8111828210171561277e5761277e612745565b60405290565b604051601f8201601f1916810167ffffffffffffffff811182821017156127ad576127ad612745565b604052919050565b60005b838110156127d05781810151838201526020016127b8565b838111156127df576000848401525b50505050565b80516127f081612493565b919050565b6000602080838503121561280857600080fd5b825167ffffffffffffffff8082111561282057600080fd5b9084019060a0828703121561283457600080fd5b61283c61275b565b82518281111561284b57600080fd5b8301601f8101881361285c57600080fd5b80518381111561286e5761286e612745565b612880601f8201601f19168701612784565b9350808452888682840101111561289657600080fd5b6128a5818786018885016127b5565b50508181526128b58484016127e5565b848201526128c5604084016127e5565b604082015260608301516060820152608083015160808201528094505050505092915050565b6000602082840312156128fd57600080fd5b815180151581146123ee57600080fd5b6000808335601e1984360301811261292457600080fd5b83018035915067ffffffffffffffff82111561293f57600080fd5b6020019150600581901b36038213156125ca57600080fd5b634e487b7160e01b600052601160045260246000fd5b6000821982111561298057612980612957565b500190565b60006001820161299757612997612957565b5060010190565b8183526000602080850194508260005b858110156129dc5781356129c181612493565b6001600160a01b0316875295820195908201906001016129ae565b509495945050505050565b6060815260006129fb60608301878961299e565b82810360208401528481526001600160fb1b03851115612a1a57600080fd5b8460051b80876020840137600091016020019081526040929092019290925295945050505050565b6020808252602b908201527f5265736572766548656c706572733a20436f6d7074726f6c6c6572206164647260408201526a195cdcc81a5b9d985b1a5960aa1b606082015260800190565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b60008151808452612af08160208601602086016127b5565b601f01601f19169290920160200192915050565b6001600160a01b038316815260406020820181905260009061216390830184612ad8565b6001600160a01b03848116825283166020820152606060408201819052600090611cf190830184612ad8565b600082821015612b6657612b66612957565b500390565b86815285602082015260a060408201526000612b8b60a08301868861299e565b6001600160a01b039490941660608301525060800152949350505050565b60006020808385031215612bbc57600080fd5b825167ffffffffffffffff80821115612bd457600080fd5b818501915085601f830112612be857600080fd5b815181811115612bfa57612bfa612745565b8060051b9150612c0b848301612784565b8181529183018401918481019088841115612c2557600080fd5b938501935b83851015612c4357845182529385019390850190612c2a565b98975050505050505050565b60008251612c618184602087016127b5565b9190910192915050565b600082612c8857634e487b7160e01b600052601260045260246000fd5b500490565b6000816000190483118215151615612ca757612ca7612957565b500290565b6020815260006123ee6020830184612ad856fe73776170506f6f6c7341737365747328616464726573735b5d2c75696e743235365b5d2c616464726573735b5d5b5d2c75696e7432353629a26469706673582212200df4784c551e6f296a40813ffbdb6c465608d0b9582f5f659a9257b405a4147e64736f6c634300080d0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101a95760003560e01c806377d4937f116100f9578063afcff50f11610097578063c8ecc0d311610071578063c8ecc0d31461037b578063e30c39781461038f578063f2fde38b146103a0578063fe3da984146103b357600080fd5b8063afcff50f1461034e578063b4a0bdf314610361578063be26317e1461037257600080fd5b806380d45a2d116100d357806380d45a2d146103045780638da5cb5b14610317578063a69bd19e14610328578063aac59a751461033b57600080fd5b806377d4937f146102d657806379ba5097146102e95780637b77cd6a146102f157600080fd5b80632e688141116101665780635f30e37b116101405780635f30e37b146102955780636fb05275146102a8578063715018a6146102bb578063746460a9146102c357600080fd5b80632e6881411461024f578063439b5517146102625780634dd9584a1461028257600080fd5b80630a9837c5146101ae5780630e32cb86146101d457806319b1faef146101e95780632455899514610215578063258836fe146102295780632a1d05471461023c575b600080fd5b6101c16101bc3660046124a8565b6103bd565b6040519081526020015b60405180910390f35b6101e76101e23660046124d4565b61058c565b005b61012e546101fd906001600160a01b031681565b6040516001600160a01b0390911681526020016101cb565b61012f546101fd906001600160a01b031681565b6101e76102373660046124f1565b6105a0565b6101e761024a36600461252a565b610731565b6101e761025d3660046124d4565b610922565b6101c16102703660046124d4565b60c96020526000908152604090205481565b6101e76102903660046124d4565b610a27565b6101c16102a33660046125d1565b610a8b565b6101c16102b63660046124f1565b610fdf565b6101e7611093565b6101e76102d1366004612674565b6110a7565b6101e76102e43660046124d4565b61114c565b6101e76111b0565b6101e76102ff3660046124d4565b611227565b6101e7610312366004612674565b61128a565b6033546001600160a01b03166101fd565b6101c16103363660046124d4565b61129b565b6101e76103493660046124f1565b611387565b60cb546101fd906001600160a01b031681565b6097546001600160a01b03166101fd565b6101c160fb5481565b61012d546101fd906001600160a01b031681565b6065546001600160a01b03166101fd565b6101e76103ae3660046124d4565b611395565b6101c16101305481565b6000600260cc54036103ea5760405162461bcd60e51b81526004016103e19061268d565b60405180910390fd5b600260cc5561012e546001600160a01b03163381146104625760405162461bcd60e51b815260206004820152602e60248201527f5269736b2066756e643a204f6e6c792063616c6c61626c652062792053686f7260448201526d1d19985b1b0818dbdb9d1c9858dd60921b60648201526084016103e1565b6001600160a01b03808516600090815260ca6020908152604080832061012d54909416835292905220548311156104e95760405162461bcd60e51b815260206004820152602560248201527f5269736b2046756e643a20496e73756666696369656e7420706f6f6c2072657360448201526432b93b329760d91b60648201526084016103e1565b6001600160a01b03808516600081815260ca6020908152604080832061012d80548716855290835281842080548a9003905554909416825260c990528290208054869003905590517fc8d0a37ed16dfaa43514df00e18f478b60d5cc7b4bfc687103948b9020f737fd906105609086815260200190565b60405180910390a261012d54610580906001600160a01b03168285611406565b5050600160cc55919050565b61059461145d565b61059d816114b7565b50565b6105a861145d565b600260cc54036105ca5760405162461bcd60e51b81526004016103e19061268d565b600260cc556105d881611575565b6040516370a0823160e01b815230600482015260009081906001600160a01b038516906370a0823190602401602060405180830381865afa158015610621573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061064591906126b1565b6001600160a01b038516600090815260c9602052604090205490915081116106bb5760405162461bcd60e51b815260206004820152602360248201527f5265736572766548656c706572733a205a65726f20737572706c757320746f6b604482015262656e7360e81b60648201526084016103e1565b6001600160a01b03848116600081815260c960209081526040918290205491519185038083529550928616927f6d25be279134f4ecaa4770aff0c3d916d9e7c5ef37b65ed95dbdba411f5d54d5910160405180910390a36107266001600160a01b0385168484611406565b5050600160cc555050565b600054610100900460ff16158080156107515750600054600160ff909116105b8061076b5750303b15801561076b575060005460ff166001145b6107ce5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084016103e1565b6000805460ff1916600117905580156107f1576000805461ff0019166101001790555b6107fa86611575565b61080384611575565b600085116108235760405162461bcd60e51b81526004016103e1906126ca565b600082116108825760405162461bcd60e51b815260206004820152602660248201527f5269736b2046756e643a204c6f6f7073206c696d69742063616e206e6f74206260448201526565207a65726f60d01b60648201526084016103e1565b61088a61159c565b610893836115cb565b61012f80546001600160a01b038089166001600160a01b03199283161790925561013087905561012d8054928716929091169190911790556108d4826115f2565b801561091a576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050565b6109606040518060400160405280602081526020017f736574436f6e7665727469626c6542617365417373657428616464726573732981525061168c565b6001600160a01b0381166109d45760405162461bcd60e51b815260206004820152603560248201527f5269736b2046756e643a206e657720636f6e7665727469626c65206261736520604482015274185cdcd95d081859191c995cdcc81a5b9d985b1a59605a1b60648201526084016103e1565b61012d80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f5fa61583da12070720613fefdd68cc6c0e464a71e009742526bd2b2e0ac62cd290600090a35050565b610a2f61145d565b610a3881611575565b61012f80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907fd37b9d138f53ea58d7e50292588239a46efa8f523966febf4066da96defc77fd90600090a35050565b6000600260cc5403610aaf5760405162461bcd60e51b81526004016103e19061268d565b600260cc81905550610ad8604051806060016040528060388152602001612cc06038913961168c565b42821015610b285760405162461bcd60e51b815260206004820152601a60248201527f5269736b2066756e643a20646561646c696e652070617373656400000000000060448201526064016103e1565b60cb546001600160a01b0316610b3d81611575565b878614610bb25760405162461bcd60e51b815260206004820152603860248201527f5269736b2066756e643a206d61726b65747320616e6420616d6f756e74734f7560448201527f744d696e2061726520756e657175616c206c656e67746873000000000000000060648201526084016103e1565b878414610c1a5760405162461bcd60e51b815260206004820152603060248201527f5269736b2066756e643a206d61726b65747320616e642070617468732061726560448201526f20756e657175616c206c656e6774687360801b60648201526084016103e1565b600088610c2681611726565b60005b81811015610f8c5760008c8c83818110610c4557610c45612712565b9050602002016020810190610c5a91906124d4565b6001600160a01b0316635fe3b5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c97573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cbb9190612728565b604051637aee632d60e01b81526001600160a01b038083166004830152919250600091871690637aee632d90602401600060405180830381865afa158015610d07573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610d2f91908101906127f5565b9050816001600160a01b031681604001516001600160a01b031614610da65760405162461bcd60e51b815260206004820152602760248201527f636f6d7074726f6c6c657220646f65736e277420657869737420706f6f6c20726044820152666567697374727960c81b60648201526084016103e1565b816001600160a01b0316633d98a1e58f8f86818110610dc757610dc7612712565b9050602002016020810190610ddc91906124d4565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa158015610e20573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e4491906128eb565b610e875760405162461bcd60e51b81526020600482015260146024820152731b585c9ad95d081a5cc81b9bdd081b1a5cdd195960621b60448201526064016103e1565b6000610ef68f8f86818110610e9e57610e9e612712565b9050602002016020810190610eb391906124d4565b848f8f88818110610ec657610ec6612712565b905060200201358e8e89818110610edf57610edf612712565b9050602002810190610ef1919061290d565b611757565b6001600160a01b03808516600090815260ca6020908152604080832061012d54909416835292905290812080549293508392909190610f3690849061296d565b909155505061012d546001600160a01b0316600090815260c9602052604081208054839290610f6690849061296d565b90915550610f769050818761296d565b955050505080610f8590612985565b9050610c29565b507fb17530966b045b50d4975e7f05048ca00d7335780c24f1c465165a4b94b2d37d8b8b8b8b86604051610fc49594939291906129e7565b60405180910390a150600160cc559998505050505050505050565b6000610fea82611575565b826001600160a01b0316627e3dd26040518163ffffffff1660e01b8152600401602060405180830381865afa158015611027573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061104b91906128eb565b6110675760405162461bcd60e51b81526004016103e190612a42565b506001600160a01b03918216600090815260ca6020908152604080832093909416825291909152205490565b61109b61145d565b6110a56000611cfa565b565b6110e56040518060400160405280601e81526020017f7365744d696e416d6f756e74546f436f6e766572742875696e7432353629000081525061168c565b600081116111055760405162461bcd60e51b81526004016103e1906126ca565b61013080549082905560408051828152602081018490527fada67d0d38fa20c8ae6a5c17cb9d60b0fe7f2d4e4f27ac9ee55e54ac88de9d8d91015b60405180910390a15050565b61115461145d565b61115d81611575565b61012e80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907fb6e5fcf02f7fbb8acfbaa3bac4fd5abf9ff51e3f2e8884b5498927179b211b2890600090a35050565b60655433906001600160a01b0316811461121e5760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b60648201526084016103e1565b61059d81611cfa565b61122f61145d565b61123881611575565b60cb80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907fa87b964d321035d2165e484ff4b722dd6eae30606c0b98887d2ed1a34e594bfe90600090a35050565b61129261145d565b61059d816115f2565b6000816001600160a01b0316627e3dd26040518163ffffffff1660e01b8152600401602060405180830381865afa1580156112da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112fe91906128eb565b6113595760405162461bcd60e51b815260206004820152602660248201527f5269736b2046756e643a20436f6d7074726f6c6c6572206164647265737320696044820152651b9d985b1a5960d21b60648201526084016103e1565b506001600160a01b03908116600090815260ca6020908152604080832061012d549094168352929052205490565b6113918282611d13565b5050565b61139d61145d565b606580546001600160a01b0383166001600160a01b031990911681179091556113ce6033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b179052611458908490612046565b505050565b6033546001600160a01b031633146110a55760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016103e1565b6001600160a01b03811661151b5760405162461bcd60e51b815260206004820152602560248201527f696e76616c696420616365737320636f6e74726f6c206d616e61676572206164604482015264647265737360d81b60648201526084016103e1565b609780546001600160a01b038381166001600160a01b031983168117909355604080519190921680825260208201939093527f66fd58e82f7b31a2a5c30e0888f3093efe4e111b00cd2b0c31fe014601293aa09101611140565b6001600160a01b03811661059d576040516342bcdf7f60e11b815260040160405180910390fd5b600054610100900460ff166115c35760405162461bcd60e51b81526004016103e190612a8d565b6110a561211b565b600054610100900460ff166105945760405162461bcd60e51b81526004016103e190612a8d565b60fb54811161164e5760405162461bcd60e51b815260206004820152602260248201527f436f6d7074726f6c6c65723a20496e76616c6964206d61784c6f6f70734c696d6044820152611a5d60f21b60648201526084016103e1565b60fb80549082905560408051828152602081018490527fc2d09fef144f7c8a86f71ea459f8fc17f675768eb1ae369cbd77fb31d467aafa9101611140565b6097546040516318c5e8ab60e01b81526000916001600160a01b0316906318c5e8ab906116bf9033908690600401612b04565b602060405180830381865afa1580156116dc573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061170091906128eb565b90508061139157333083604051634a3fa29360e01b81526004016103e193929190612b28565b60fb5481111561059d5760fb5460405163792bfb1b60e11b81526004810191909152602481018290526044016103e1565b6000836000036117cf5760405162461bcd60e51b815260206004820152603c60248201527f5269736b46756e643a20616d6f756e744f75744d696e206d757374206265206760448201527f726561746572207468616e203020746f20737761702076546f6b656e0000000060648201526084016103e1565b600080876001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa158015611810573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118349190612728565b61012d546001600160a01b03898116600090815260ca6020908152604080832084871684529091528120549394509116919081900361187a576000945050505050611cf1565b6000896001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa1580156118ba573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118de9190612728565b60405163b62cad6960e01b81526001600160a01b0385811660048301529192509082169063b62cad6990602401600060405180830381600087803b15801561192557600080fd5b505af1158015611939573d6000803e3d6000fd5b50506040805160208101918290526341976e0960e01b9091526001600160a01b03868116602483015260009350909150819084166341976e0960448301602060405180830381865afa158015611993573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119b791906126b1565b9052905060006119c7828c61214b565b905061013054811015611a2a5760405162461bcd60e51b815260206004820152602560248201527f5269736b46756e643a206d696e416d6f756e74546f436f6e766572742076696f6044820152641b185d195960da1b60648201526084016103e1565b6001600160a01b038616600090815260c9602052604081208054869290611a52908490612b54565b90915550506001600160a01b03808d16600090815260ca60209081526040808320938a1683529290529081208054869290611a8e908490612b54565b90915550506001600160a01b0386811690861614611ce357856001600160a01b03168a8a6000818110611ac357611ac3612712565b9050602002016020810190611ad891906124d4565b6001600160a01b031614611b545760405162461bcd60e51b815260206004820152603860248201527f5269736b46756e643a20737761702070617468206d757374207374617274207760448201527f6974682074686520756e6465726c79696e67206173736574000000000000000060648201526084016103e1565b6001600160a01b0385168a8a611b6b600182612b54565b818110611b7a57611b7a612712565b9050602002016020810190611b8f91906124d4565b6001600160a01b031614611c035760405162461bcd60e51b815260206004820152603560248201527f5269736b46756e643a2066696e616c6c792070617468206d75737420626520636044820152741bdb9d995c9d1a589b194818985cd948185cdcd95d605a1b60648201526084016103e1565b61012f546001600160a01b0390811690611c2190881682600061216b565b611c356001600160a01b038816828761216b565b6000816001600160a01b03166338ed1739878f8f8f30426040518763ffffffff1660e01b8152600401611c6d96959493929190612b6b565b6000604051808303816000875af1158015611c8c573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611cb49190810190612ba9565b905080611cc260018d612b54565b81518110611cd257611cd2612712565b602002602001015198505050611ce7565b8396505b5094955050505050505b95945050505050565b606580546001600160a01b031916905561059d81612257565b611d1c81611575565b816001600160a01b0316627e3dd26040518163ffffffff1660e01b8152600401602060405180830381865afa158015611d59573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d7d91906128eb565b611d995760405162461bcd60e51b81526004016103e190612a42565b60cb546001600160a01b031680611e0b5760405162461bcd60e51b815260206004820152603060248201527f5265736572766548656c706572733a20506f6f6c20526567697374727920616460448201526f191c995cdcc81a5cc81b9bdd081cd95d60821b60648201526084016103e1565b60405163266e0a7f60e01b81526001600160a01b03848116600483015283811660248301526000919083169063266e0a7f90604401602060405180830381865afa158015611e5d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e819190612728565b6001600160a01b031603611ef25760405162461bcd60e51b815260206004820152603260248201527f5265736572766548656c706572733a2054686520706f6f6c20646f65736e2774604482015271081cdd5c1c1bdc9d081d1a1948185cdcd95d60721b60648201526084016103e1565b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa158015611f39573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f5d91906126b1565b6001600160a01b038416600090815260c960205260409020549091508082111561203f576001600160a01b038416600090815260c960205260408120805483850392839291611fad90849061296d565b90915550506001600160a01b03808716600090815260ca6020908152604080832093891683529290529081208054839290611fe990849061296d565b92505081905550846001600160a01b0316866001600160a01b03167fc39e3e80c0219fde334a8cb5d8468b628482e23388b6e809c90cb00c63c8ce388360405161203591815260200190565b60405180910390a3505b5050505050565b600061209b826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166122a99092919063ffffffff16565b90508051600014806120bc5750808060200190518101906120bc91906128eb565b6114585760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b60648201526084016103e1565b600054610100900460ff166121425760405162461bcd60e51b81526004016103e190612a8d565b6110a533611cfa565b60008061215884846122b8565b9050612163816122e9565b949350505050565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663095ea7b360e01b1790529151909160009182918716906121c9908590612c4f565b6000604051808303816000865af19150503d8060008114612206576040519150601f19603f3d011682016040523d82523d6000602084013e61220b565b606091505b5091509150811580612239575080511580159061223957508080602001905181019061223791906128eb565b155b1561091a57604051633e3f8f7360e01b815260040160405180910390fd5b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60606121638484600085612307565b60408051602081019091526000815260405180602001604052806122e08560000151856123e2565b90529392505050565b805160009061230190670de0b6b3a764000090612c6b565b92915050565b6060824710156123685760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b60648201526084016103e1565b600080866001600160a01b031685876040516123849190612c4f565b60006040518083038185875af1925050503d80600081146123c1576040519150601f19603f3d011682016040523d82523d6000602084013e6123c6565b606091505b50915091506123d7878383876123f5565b979650505050505050565b60006123ee8284612c8d565b9392505050565b6060831561246457825160000361245d576001600160a01b0385163b61245d5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016103e1565b5081612163565b61216383838151156124795781518083602001fd5b8060405162461bcd60e51b81526004016103e19190612cac565b6001600160a01b038116811461059d57600080fd5b600080604083850312156124bb57600080fd5b82356124c681612493565b946020939093013593505050565b6000602082840312156124e657600080fd5b81356123ee81612493565b6000806040838503121561250457600080fd5b823561250f81612493565b9150602083013561251f81612493565b809150509250929050565b600080600080600060a0868803121561254257600080fd5b853561254d81612493565b945060208601359350604086013561256481612493565b9250606086013561257481612493565b949793965091946080013592915050565b60008083601f84011261259757600080fd5b50813567ffffffffffffffff8111156125af57600080fd5b6020830191508360208260051b85010111156125ca57600080fd5b9250929050565b60008060008060008060006080888a0312156125ec57600080fd5b873567ffffffffffffffff8082111561260457600080fd5b6126108b838c01612585565b909950975060208a013591508082111561262957600080fd5b6126358b838c01612585565b909750955060408a013591508082111561264e57600080fd5b5061265b8a828b01612585565b989b979a50959894979596606090950135949350505050565b60006020828403121561268657600080fd5b5035919050565b6020808252600a90820152691c994b595b9d195c995960b21b604082015260600190565b6000602082840312156126c357600080fd5b5051919050565b60208082526028908201527f5269736b2046756e643a20496e76616c6964206d696e20616d6f756e7420746f6040820152670818dbdb9d995c9d60c21b606082015260800190565b634e487b7160e01b600052603260045260246000fd5b60006020828403121561273a57600080fd5b81516123ee81612493565b634e487b7160e01b600052604160045260246000fd5b60405160a0810167ffffffffffffffff8111828210171561277e5761277e612745565b60405290565b604051601f8201601f1916810167ffffffffffffffff811182821017156127ad576127ad612745565b604052919050565b60005b838110156127d05781810151838201526020016127b8565b838111156127df576000848401525b50505050565b80516127f081612493565b919050565b6000602080838503121561280857600080fd5b825167ffffffffffffffff8082111561282057600080fd5b9084019060a0828703121561283457600080fd5b61283c61275b565b82518281111561284b57600080fd5b8301601f8101881361285c57600080fd5b80518381111561286e5761286e612745565b612880601f8201601f19168701612784565b9350808452888682840101111561289657600080fd5b6128a5818786018885016127b5565b50508181526128b58484016127e5565b848201526128c5604084016127e5565b604082015260608301516060820152608083015160808201528094505050505092915050565b6000602082840312156128fd57600080fd5b815180151581146123ee57600080fd5b6000808335601e1984360301811261292457600080fd5b83018035915067ffffffffffffffff82111561293f57600080fd5b6020019150600581901b36038213156125ca57600080fd5b634e487b7160e01b600052601160045260246000fd5b6000821982111561298057612980612957565b500190565b60006001820161299757612997612957565b5060010190565b8183526000602080850194508260005b858110156129dc5781356129c181612493565b6001600160a01b0316875295820195908201906001016129ae565b509495945050505050565b6060815260006129fb60608301878961299e565b82810360208401528481526001600160fb1b03851115612a1a57600080fd5b8460051b80876020840137600091016020019081526040929092019290925295945050505050565b6020808252602b908201527f5265736572766548656c706572733a20436f6d7074726f6c6c6572206164647260408201526a195cdcc81a5b9d985b1a5960aa1b606082015260800190565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b60008151808452612af08160208601602086016127b5565b601f01601f19169290920160200192915050565b6001600160a01b038316815260406020820181905260009061216390830184612ad8565b6001600160a01b03848116825283166020820152606060408201819052600090611cf190830184612ad8565b600082821015612b6657612b66612957565b500390565b86815285602082015260a060408201526000612b8b60a08301868861299e565b6001600160a01b039490941660608301525060800152949350505050565b60006020808385031215612bbc57600080fd5b825167ffffffffffffffff80821115612bd457600080fd5b818501915085601f830112612be857600080fd5b815181811115612bfa57612bfa612745565b8060051b9150612c0b848301612784565b8181529183018401918481019088841115612c2557600080fd5b938501935b83851015612c4357845182529385019390850190612c2a565b98975050505050505050565b60008251612c618184602087016127b5565b9190910192915050565b600082612c8857634e487b7160e01b600052601260045260246000fd5b500490565b6000816000190483118215151615612ca757612ca7612957565b500290565b6020815260006123ee6020830184612ad856fe73776170506f6f6c7341737365747328616464726573735b5d2c75696e743235365b5d2c616464726573735b5d5b5d2c75696e7432353629a26469706673582212200df4784c551e6f296a40813ffbdb6c465608d0b9582f5f659a9257b405a4147e64736f6c634300080d0033", + "solcInputHash": "f237ea044837d6f4ff4c08abcdd27558", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"corePoolComptroller_\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"vbnb_\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nativeWrapped_\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"ApproveFailed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"loopsLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requiredLoops\",\"type\":\"uint256\"}],\"name\":\"MaxLoopsLimitExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"calledContract\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"methodSignature\",\"type\":\"string\"}],\"name\":\"Unauthorized\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"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\":\"oldConvertibleBaseAsset\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newConvertibleBaseAsset\",\"type\":\"address\"}],\"name\":\"ConvertibleBaseAssetUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldMaxLoopsLimit\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newmaxLoopsLimit\",\"type\":\"uint256\"}],\"name\":\"MaxLoopsLimitUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldMinAmountToConvert\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newMinAmountToConvert\",\"type\":\"uint256\"}],\"name\":\"MinAmountToConvertUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldAccessControlManager\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newAccessControlManager\",\"type\":\"address\"}],\"name\":\"NewAccessControlManager\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferStarted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"oldPancakeSwapRouter\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newPancakeSwapRouter\",\"type\":\"address\"}],\"name\":\"PancakeSwapRouterUpdated\",\"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\":\"oldShortfallContract\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"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\":\"totalAmount\",\"type\":\"uint256\"}],\"name\":\"SwappedPoolsAssets\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"SweepToken\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"TransferredReserveForAuction\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"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\",\"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\"}],\"name\":\"assetsReserves\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"convertibleBaseAsset\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"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\":\"comptroller\",\"type\":\"address\"}],\"name\":\"getPoolsBaseAssetReserves\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"pancakeSwapRouter_\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmountToConvert_\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"convertibleBaseAsset_\",\"type\":\"address\"},{\"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\":\"minAmountToConvert\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pancakeSwapRouter\",\"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\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"accessControlManager_\",\"type\":\"address\"}],\"name\":\"setAccessControlManager\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_convertibleBaseAsset\",\"type\":\"address\"}],\"name\":\"setConvertibleBaseAsset\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"limit\",\"type\":\"uint256\"}],\"name\":\"setMaxLoopsLimit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minAmountToConvert_\",\"type\":\"uint256\"}],\"name\":\"setMinAmountToConvert\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"pancakeSwapRouter_\",\"type\":\"address\"}],\"name\":\"setPancakeSwapRouter\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"poolRegistry_\",\"type\":\"address\"}],\"name\":\"setPoolRegistry\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"shortfallContractAddress_\",\"type\":\"address\"}],\"name\":\"setShortfallContractAddress\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"shortfall\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"markets\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"amountsOutMin\",\"type\":\"uint256[]\"},{\"internalType\":\"address[][]\",\"name\":\"paths\",\"type\":\"address[][]\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"swapPoolsAssets\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"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\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transferReserveForAuction\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"}],\"name\":\"updateAssetsState\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Venus\",\"details\":\"This contract does not support BNB.\",\"kind\":\"dev\",\"methods\":{\"acceptOwnership()\":{\"details\":\"The new owner accepts the ownership transfer.\"},\"constructor\":{\"custom:oz-upgrades-unsafe-allow\":\"constructor\",\"details\":\"Note that the contract is upgradeable. Use initialize() or reinitializers to set the state variables.\"},\"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.\"}},\"getPoolsBaseAssetReserves(address)\":{\"params\":{\"comptroller\":\"Comptroller address(pool).\"},\"returns\":{\"_0\":\"Base Asset's reserve in risk fund.\"}},\"initialize(address,uint256,address,address,uint256)\":{\"custom:error\":\"ZeroAddressNotAllowed is thrown when PCS router address is zeroZeroAddressNotAllowed is thrown when convertible base asset address is zero\",\"params\":{\"accessControlManager_\":\"Address of the access control contract\",\"convertibleBaseAsset_\":\"Address of the base asset\",\"loopsLimit_\":\"Limit for the loops in the contract to avoid DOS\",\"minAmountToConvert_\":\"Minimum amount assets must be worth to convert into base asset\",\"pancakeSwapRouter_\":\"Address of the PancakeSwap router\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"pendingOwner()\":{\"details\":\"Returns the address of the pending owner.\"},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner.\"},\"setAccessControlManager(address)\":{\"custom:access\":\"Only Governance\",\"custom:event\":\"Emits NewAccessControlManager event\",\"details\":\"Admin function to set address of AccessControlManager\",\"params\":{\"accessControlManager_\":\"The new address of the AccessControlManager\"}},\"setConvertibleBaseAsset(address)\":{\"params\":{\"_convertibleBaseAsset\":\"Address for new convertible base asset.\"}},\"setMaxLoopsLimit(uint256)\":{\"params\":{\"limit\":\"Limit for the max loops can execute at a time\"}},\"setMinAmountToConvert(uint256)\":{\"params\":{\"minAmountToConvert_\":\"Min amount to convert.\"}},\"setPancakeSwapRouter(address)\":{\"custom:error\":\"ZeroAddressNotAllowed is thrown when PCS router address is zero\",\"params\":{\"pancakeSwapRouter_\":\"Address of the PancakeSwap router\"}},\"setPoolRegistry(address)\":{\"custom:error\":\"ZeroAddressNotAllowed is thrown when pool registry address is zero\",\"params\":{\"poolRegistry_\":\"Address of the pool registry\"}},\"setShortfallContractAddress(address)\":{\"custom:error\":\"ZeroAddressNotAllowed is thrown when shortfall contract address is zero\",\"params\":{\"shortfallContractAddress_\":\"Address of the auction contract\"}},\"swapPoolsAssets(address[],uint256[],address[][],uint256)\":{\"custom:error\":\"ZeroAddressNotAllowed is thrown if PoolRegistry contract address is not configured\",\"params\":{\"amountsOutMin\":\"Minimum amount to receive for swap\",\"deadline\":\"Deadline for the swap\",\"markets\":\"Array of vTokens whose assets to swap for base asset\",\"paths\":\"A path consisting of PCS token pairs for each swap\"},\"returns\":{\"_0\":\"Number of swapped tokens\"}},\"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.\"},\"transferReserveForAuction(address,uint256)\":{\"params\":{\"amount\":\"Amount to be transferred to auction contract.\",\"comptroller\":\"Comptroller of the pool.\"},\"returns\":{\"_0\":\"Number reserved tokens.\"}},\"updateAssetsState(address,address)\":{\"params\":{\"asset\":\"Asset address.\",\"comptroller\":\"Comptroller address(pool).\"}}},\"title\":\"RiskFund\",\"version\":1},\"userdoc\":{\"errors\":{\"ApproveFailed()\":[{\"notice\":\"Thrown if a contract is unable to approve a transfer\"}],\"MaxLoopsLimitExceeded(uint256,uint256)\":[{\"notice\":\"Thrown an error on maxLoopsLimit exceeds for any loop\"}],\"Unauthorized(address,address,string)\":[{\"notice\":\"Thrown when the action is prohibited by AccessControlManager\"}],\"ZeroAddressNotAllowed()\":[{\"notice\":\"Thrown if the supplied address is a zero address where it is not allowed\"}]},\"events\":{\"AssetsReservesUpdated(address,address,uint256)\":{\"notice\":\"Event emitted after the update of the assets reserves.\"},\"ConvertibleBaseAssetUpdated(address,address)\":{\"notice\":\"Emitted when convertible base asset is updated\"},\"MaxLoopsLimitUpdated(uint256,uint256)\":{\"notice\":\"Emitted when max loops limit is set\"},\"MinAmountToConvertUpdated(uint256,uint256)\":{\"notice\":\"Emitted when minimum amount to convert is updated\"},\"NewAccessControlManager(address,address)\":{\"notice\":\"Emitted when access control manager contract address is changed\"},\"PancakeSwapRouterUpdated(address,address)\":{\"notice\":\"Emitted when PancakeSwap router contract address is updated\"},\"PoolRegistryUpdated(address,address)\":{\"notice\":\"Emitted when pool registry address is updated\"},\"ShortfallContractUpdated(address,address)\":{\"notice\":\"Emitted when shortfall contract address is updated\"},\"SwappedPoolsAssets(address[],uint256[],uint256)\":{\"notice\":\"Emitted when pools assets are swapped\"},\"SweepToken(address,address,uint256)\":{\"notice\":\"event emitted on sweep token success\"},\"TransferredReserveForAuction(address,uint256)\":{\"notice\":\"Emitted when reserves are transferred for auction\"}},\"kind\":\"user\",\"methods\":{\"accessControlManager()\":{\"notice\":\"Returns the address of the access control manager contract\"},\"getPoolAssetReserve(address,address)\":{\"notice\":\"Get the Amount of the asset in the risk fund for the specific pool.\"},\"getPoolsBaseAssetReserves(address)\":{\"notice\":\"Get the Amount of the Base asset in the risk fund for the specific pool.\"},\"initialize(address,uint256,address,address,uint256)\":{\"notice\":\"Initializes the deployer to owner.\"},\"setAccessControlManager(address)\":{\"notice\":\"Sets the address of AccessControlManager\"},\"setConvertibleBaseAsset(address)\":{\"notice\":\"Sets a new convertible base asset\"},\"setMaxLoopsLimit(uint256)\":{\"notice\":\"Set the limit for the loops can iterate to avoid the DOS\"},\"setMinAmountToConvert(uint256)\":{\"notice\":\"Min amount to convert setter\"},\"setPancakeSwapRouter(address)\":{\"notice\":\"PancakeSwap router address setter\"},\"setPoolRegistry(address)\":{\"notice\":\"Pool registry setter\"},\"setShortfallContractAddress(address)\":{\"notice\":\"Shortfall contract address setter\"},\"swapPoolsAssets(address[],uint256[],address[][],uint256)\":{\"notice\":\"Swap array of pool assets into base asset's tokens of at least a minimum amount\"},\"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\"},\"transferReserveForAuction(address,uint256)\":{\"notice\":\"Transfer tokens for auction.\"},\"updateAssetsState(address,address)\":{\"notice\":\"Update the reserve of the asset for the specific pool after transferring to risk fund.\"}},\"notice\":\"Contract with basic features to track/hold different assets for different Comptrollers.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/RiskFund/RiskFund.sol\":\"RiskFund\"},\"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(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 \\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\":\"0xef1ca0adc3ce1ff540279d424953087771b4a07470caac99777fafd2ceea38a9\",\"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 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(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/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\",\"keccak256\":\"0x7e4d140bd2a5671389ad7a3975b65d05a4f750daf6a61c16139d123d9782b96e\",\"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/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/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\\\";\\nimport { PoolRegistry } from \\\"../Pool/PoolRegistry.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 PoolRegistry(poolRegistry).getVTokenForAsset(comptroller, asset) != address(0);\\n }\\n}\\n\",\"keccak256\":\"0xf30155bbbb7251eb8445c7d282427ed0040d015fe34efcb5ec61bc92a289b0cc\",\"license\":\"BSD-3-Clause\"},\"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\",\"keccak256\":\"0x918526b067c834935f5dd0788139e1a73c64cbf6f8b7d6fd43242eaa93aa7f37\",\"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(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 \\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 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 \\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(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\",\"keccak256\":\"0xcda9eb71f6ceb8a4c3bfbc1c42d72e2f0523d30f6d3252fbd90819e953640fe5\",\"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(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\":\"0x2947e95eb97a3a45f90ec36d4fd5a4cbb9409319f6ad000e950550055a3f2324\",\"license\":\"BSD-3-Clause\"},\"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\",\"keccak256\":\"0x9bbc31c80a4c537ddfd06cbd03a412ba64842a708381fbc4bf2e33ef56c92b4d\",\"license\":\"MIT\"},\"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": "0x60e06040523480156200001157600080fd5b50604051620032b8380380620032b883398101604081905262000034916200018c565b828282620000428362000083565b6200004d8262000083565b620000588162000083565b6001600160a01b0392831660805290821660a0521660c0526200007a620000ae565b505050620001d6565b6001600160a01b038116620000ab576040516342bcdf7f60e11b815260040160405180910390fd5b50565b600054610100900460ff16156200011b5760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b60005460ff908116146200016d576000805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b80516001600160a01b03811681146200018757600080fd5b919050565b600080600060608486031215620001a257600080fd5b620001ad846200016f565b9250620001bd602085016200016f565b9150620001cd604085016200016f565b90509250925092565b60805160a05160c05161309662000222600039600081816102bf015261258601526000818161029801526124c3015260008181610437015281816122df015261240c01526130966000f3fe608060405234801561001057600080fd5b50600436106101da5760003560e01c806377d4937f11610104578063afcff50f116100a2578063e30c397811610071578063e30c39781461040e578063f2fde38b1461041f578063fa7b81a014610432578063fe3da9841461045957600080fd5b8063afcff50f146103cd578063b4a0bdf3146103e0578063be26317e146103f1578063c8ecc0d3146103fa57600080fd5b806380d45a2d116100de57806380d45a2d146103835780638da5cb5b14610396578063a69bd19e146103a7578063aac59a75146103ba57600080fd5b806377d4937f1461035557806379ba5097146103685780637b77cd6a1461037057600080fd5b80633421fc521161017c5780635f30e37b1161014b5780635f30e37b146103145780636fb0527514610327578063715018a61461033a578063746460a91461034257600080fd5b80633421fc5214610293578063362b6795146102ba578063439b5517146102e15780634dd9584a1461030157600080fd5b806324558995116101b85780632455899514610246578063258836fe1461025a5780632a1d05471461026d5780632e6881411461028057600080fd5b80630a9837c5146101df5780630e32cb861461020557806319b1faef1461021a575b600080fd5b6101f26101ed366004612779565b610463565b6040519081526020015b60405180910390f35b6102186102133660046127a5565b610632565b005b61012e5461022e906001600160a01b031681565b6040516001600160a01b0390911681526020016101fc565b61012f5461022e906001600160a01b031681565b6102186102683660046127c2565b610646565b61021861027b3660046127fb565b6107d7565b61021861028e3660046127a5565b6109c8565b61022e7f000000000000000000000000000000000000000000000000000000000000000081565b61022e7f000000000000000000000000000000000000000000000000000000000000000081565b6101f26102ef3660046127a5565b60c96020526000908152604090205481565b61021861030f3660046127a5565b610acd565b6101f26103223660046128a2565b610b31565b6101f26103353660046127c2565b611085565b61021861113b565b610218610350366004612945565b61114f565b6102186103633660046127a5565b6111f4565b610218611258565b61021861037e3660046127a5565b6112cf565b610218610391366004612945565b611332565b6033546001600160a01b031661022e565b6101f26103b53660046127a5565b611343565b6102186103c83660046127c2565b61142f565b60cb5461022e906001600160a01b031681565b6097546001600160a01b031661022e565b6101f260fb5481565b61012d5461022e906001600160a01b031681565b6065546001600160a01b031661022e565b61021861042d3660046127a5565b61143d565b61022e7f000000000000000000000000000000000000000000000000000000000000000081565b6101f26101305481565b6000600260cc54036104905760405162461bcd60e51b81526004016104879061295e565b60405180910390fd5b600260cc5561012e546001600160a01b03163381146105085760405162461bcd60e51b815260206004820152602e60248201527f5269736b2066756e643a204f6e6c792063616c6c61626c652062792053686f7260448201526d1d19985b1b0818dbdb9d1c9858dd60921b6064820152608401610487565b6001600160a01b03808516600090815260ca6020908152604080832061012d549094168352929052205483111561058f5760405162461bcd60e51b815260206004820152602560248201527f5269736b2046756e643a20496e73756666696369656e7420706f6f6c2072657360448201526432b93b329760d91b6064820152608401610487565b6001600160a01b03808516600081815260ca6020908152604080832061012d80548716855290835281842080548a9003905554909416825260c990528290208054869003905590517fc8d0a37ed16dfaa43514df00e18f478b60d5cc7b4bfc687103948b9020f737fd906106069086815260200190565b60405180910390a261012d54610626906001600160a01b031682856114ae565b5050600160cc55919050565b61063a611505565b6106438161155f565b50565b61064e611505565b600260cc54036106705760405162461bcd60e51b81526004016104879061295e565b600260cc5561067e8161161d565b6040516370a0823160e01b815230600482015260009081906001600160a01b038516906370a0823190602401602060405180830381865afa1580156106c7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106eb9190612982565b6001600160a01b038516600090815260c9602052604090205490915081116107615760405162461bcd60e51b815260206004820152602360248201527f5265736572766548656c706572733a205a65726f20737572706c757320746f6b604482015262656e7360e81b6064820152608401610487565b6001600160a01b03848116600081815260c960209081526040918290205491519185038083529550928616927f6d25be279134f4ecaa4770aff0c3d916d9e7c5ef37b65ed95dbdba411f5d54d5910160405180910390a36107cc6001600160a01b03851684846114ae565b5050600160cc555050565b600054610100900460ff16158080156107f75750600054600160ff909116105b806108115750303b158015610811575060005460ff166001145b6108745760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610487565b6000805460ff191660011790558015610897576000805461ff0019166101001790555b6108a08661161d565b6108a98461161d565b600085116108c95760405162461bcd60e51b81526004016104879061299b565b600082116109285760405162461bcd60e51b815260206004820152602660248201527f5269736b2046756e643a204c6f6f7073206c696d69742063616e206e6f74206260448201526565207a65726f60d01b6064820152608401610487565b610930611644565b61093983611673565b61012f80546001600160a01b038089166001600160a01b03199283161790925561013087905561012d80549287169290911691909117905561097a8261169a565b80156109c0576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050565b610a066040518060400160405280602081526020017f736574436f6e7665727469626c65426173654173736574286164647265737329815250611734565b6001600160a01b038116610a7a5760405162461bcd60e51b815260206004820152603560248201527f5269736b2046756e643a206e657720636f6e7665727469626c65206261736520604482015274185cdcd95d081859191c995cdcc81a5b9d985b1a59605a1b6064820152608401610487565b61012d80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f5fa61583da12070720613fefdd68cc6c0e464a71e009742526bd2b2e0ac62cd290600090a35050565b610ad5611505565b610ade8161161d565b61012f80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907fd37b9d138f53ea58d7e50292588239a46efa8f523966febf4066da96defc77fd90600090a35050565b6000600260cc5403610b555760405162461bcd60e51b81526004016104879061295e565b600260cc81905550610b7e60405180606001604052806038815260200161302960389139611734565b42821015610bce5760405162461bcd60e51b815260206004820152601a60248201527f5269736b2066756e643a20646561646c696e65207061737365640000000000006044820152606401610487565b60cb546001600160a01b0316610be38161161d565b878614610c585760405162461bcd60e51b815260206004820152603860248201527f5269736b2066756e643a206d61726b65747320616e6420616d6f756e74734f7560448201527f744d696e2061726520756e657175616c206c656e6774687300000000000000006064820152608401610487565b878414610cc05760405162461bcd60e51b815260206004820152603060248201527f5269736b2066756e643a206d61726b65747320616e642070617468732061726560448201526f20756e657175616c206c656e6774687360801b6064820152608401610487565b600088610ccc816117ce565b60005b818110156110325760008c8c83818110610ceb57610ceb6129e3565b9050602002016020810190610d0091906127a5565b6001600160a01b0316635fe3b5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d3d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d6191906129f9565b604051637aee632d60e01b81526001600160a01b038083166004830152919250600091871690637aee632d90602401600060405180830381865afa158015610dad573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610dd59190810190612ac6565b9050816001600160a01b031681604001516001600160a01b031614610e4c5760405162461bcd60e51b815260206004820152602760248201527f636f6d7074726f6c6c657220646f65736e277420657869737420706f6f6c20726044820152666567697374727960c81b6064820152608401610487565b816001600160a01b0316633d98a1e58f8f86818110610e6d57610e6d6129e3565b9050602002016020810190610e8291906127a5565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa158015610ec6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610eea9190612bbc565b610f2d5760405162461bcd60e51b81526020600482015260146024820152731b585c9ad95d081a5cc81b9bdd081b1a5cdd195960621b6044820152606401610487565b6000610f9c8f8f86818110610f4457610f446129e3565b9050602002016020810190610f5991906127a5565b848f8f88818110610f6c57610f6c6129e3565b905060200201358e8e89818110610f8557610f856129e3565b9050602002810190610f979190612bde565b6117ff565b6001600160a01b03808516600090815260ca6020908152604080832061012d54909416835292905290812080549293508392909190610fdc908490612c3e565b909155505061012d546001600160a01b0316600090815260c960205260408120805483929061100c908490612c3e565b9091555061101c90508187612c3e565b95505050508061102b90612c56565b9050610ccf565b507fb17530966b045b50d4975e7f05048ca00d7335780c24f1c465165a4b94b2d37d8b8b8b8b8660405161106a959493929190612cb8565b60405180910390a150600160cc559998505050505050505050565b60006110908261161d565b826001600160a01b0316627e3dd26040518163ffffffff1660e01b8152600401602060405180830381865afa1580156110cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110f19190612bbc565b61110d5760405162461bcd60e51b815260040161048790612d13565b506001600160a01b03808316600090815260ca60209081526040808320938516835292905220545b92915050565b611143611505565b61114d6000611da2565b565b61118d6040518060400160405280601e81526020017f7365744d696e416d6f756e74546f436f6e766572742875696e74323536290000815250611734565b600081116111ad5760405162461bcd60e51b81526004016104879061299b565b61013080549082905560408051828152602081018490527fada67d0d38fa20c8ae6a5c17cb9d60b0fe7f2d4e4f27ac9ee55e54ac88de9d8d91015b60405180910390a15050565b6111fc611505565b6112058161161d565b61012e80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907fb6e5fcf02f7fbb8acfbaa3bac4fd5abf9ff51e3f2e8884b5498927179b211b2890600090a35050565b60655433906001600160a01b031681146112c65760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b6064820152608401610487565b61064381611da2565b6112d7611505565b6112e08161161d565b60cb80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907fa87b964d321035d2165e484ff4b722dd6eae30606c0b98887d2ed1a34e594bfe90600090a35050565b61133a611505565b6106438161169a565b6000816001600160a01b0316627e3dd26040518163ffffffff1660e01b8152600401602060405180830381865afa158015611382573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113a69190612bbc565b6114015760405162461bcd60e51b815260206004820152602660248201527f5269736b2046756e643a20436f6d7074726f6c6c6572206164647265737320696044820152651b9d985b1a5960d21b6064820152608401610487565b506001600160a01b03908116600090815260ca6020908152604080832061012d549094168352929052205490565b6114398282611dbb565b5050565b611445611505565b606580546001600160a01b0383166001600160a01b031990911681179091556114766033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b179052611500908490612078565b505050565b6033546001600160a01b0316331461114d5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610487565b6001600160a01b0381166115c35760405162461bcd60e51b815260206004820152602560248201527f696e76616c696420616365737320636f6e74726f6c206d616e61676572206164604482015264647265737360d81b6064820152608401610487565b609780546001600160a01b038381166001600160a01b031983168117909355604080519190921680825260208201939093527f66fd58e82f7b31a2a5c30e0888f3093efe4e111b00cd2b0c31fe014601293aa091016111e8565b6001600160a01b038116610643576040516342bcdf7f60e11b815260040160405180910390fd5b600054610100900460ff1661166b5760405162461bcd60e51b815260040161048790612d5e565b61114d61214d565b600054610100900460ff1661063a5760405162461bcd60e51b815260040161048790612d5e565b60fb5481116116f65760405162461bcd60e51b815260206004820152602260248201527f436f6d7074726f6c6c65723a20496e76616c6964206d61784c6f6f70734c696d6044820152611a5d60f21b6064820152608401610487565b60fb80549082905560408051828152602081018490527fc2d09fef144f7c8a86f71ea459f8fc17f675768eb1ae369cbd77fb31d467aafa91016111e8565b6097546040516318c5e8ab60e01b81526000916001600160a01b0316906318c5e8ab906117679033908690600401612dd5565b602060405180830381865afa158015611784573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117a89190612bbc565b90508061143957333083604051634a3fa29360e01b815260040161048793929190612df9565b60fb548111156106435760fb5460405163792bfb1b60e11b8152600481019190915260248101829052604401610487565b6000836000036118775760405162461bcd60e51b815260206004820152603c60248201527f5269736b46756e643a20616d6f756e744f75744d696e206d757374206265206760448201527f726561746572207468616e203020746f20737761702076546f6b656e000000006064820152608401610487565b600080876001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa1580156118b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118dc91906129f9565b61012d546001600160a01b03898116600090815260ca60209081526040808320848716845290915281205493945091169190819003611922576000945050505050611d99565b6000896001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa158015611962573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061198691906129f9565b60405163b62cad6960e01b81526001600160a01b0385811660048301529192509082169063b62cad6990602401600060405180830381600087803b1580156119cd57600080fd5b505af11580156119e1573d6000803e3d6000fd5b50506040805160208101918290526341976e0960e01b9091526001600160a01b03868116602483015260009350909150819084166341976e0960448301602060405180830381865afa158015611a3b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a5f9190612982565b905290506000611a6f828c61217d565b905061013054811015611ad25760405162461bcd60e51b815260206004820152602560248201527f5269736b46756e643a206d696e416d6f756e74546f436f6e766572742076696f6044820152641b185d195960da1b6064820152608401610487565b6001600160a01b038616600090815260c9602052604081208054869290611afa908490612e25565b90915550506001600160a01b03808d16600090815260ca60209081526040808320938a1683529290529081208054869290611b36908490612e25565b90915550506001600160a01b0386811690861614611d8b57856001600160a01b03168a8a6000818110611b6b57611b6b6129e3565b9050602002016020810190611b8091906127a5565b6001600160a01b031614611bfc5760405162461bcd60e51b815260206004820152603860248201527f5269736b46756e643a20737761702070617468206d757374207374617274207760448201527f6974682074686520756e6465726c79696e6720617373657400000000000000006064820152608401610487565b6001600160a01b0385168a8a611c13600182612e25565b818110611c2257611c226129e3565b9050602002016020810190611c3791906127a5565b6001600160a01b031614611cab5760405162461bcd60e51b815260206004820152603560248201527f5269736b46756e643a2066696e616c6c792070617468206d75737420626520636044820152741bdb9d995c9d1a589b194818985cd948185cdcd95d605a1b6064820152608401610487565b61012f546001600160a01b0390811690611cc990881682600061219d565b611cdd6001600160a01b038816828761219d565b6000816001600160a01b03166338ed1739878f8f8f30426040518763ffffffff1660e01b8152600401611d1596959493929190612e3c565b6000604051808303816000875af1158015611d34573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611d5c9190810190612e9e565b905080611d6a60018d612e25565b81518110611d7a57611d7a6129e3565b602002602001015198505050611d8f565b8396505b5094955050505050505b95945050505050565b606580546001600160a01b031916905561064381612289565b611dc48161161d565b816001600160a01b0316627e3dd26040518163ffffffff1660e01b8152600401602060405180830381865afa158015611e01573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e259190612bbc565b611e415760405162461bcd60e51b815260040161048790612d13565b60cb546001600160a01b031680611eb35760405162461bcd60e51b815260206004820152603060248201527f5265736572766548656c706572733a20506f6f6c20526567697374727920616460448201526f191c995cdcc81a5cc81b9bdd081cd95d60821b6064820152608401610487565b611ebd83836122db565b611f245760405162461bcd60e51b815260206004820152603260248201527f5265736572766548656c706572733a2054686520706f6f6c20646f65736e2774604482015271081cdd5c1c1bdc9d081d1a1948185cdcd95d60721b6064820152608401610487565b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa158015611f6b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f8f9190612982565b6001600160a01b038416600090815260c9602052604090205490915080821115612071576001600160a01b038416600090815260c960205260408120805483850392839291611fdf908490612c3e565b90915550506001600160a01b03808716600090815260ca602090815260408083209389168352929052908120805483929061201b908490612c3e565b92505081905550846001600160a01b0316866001600160a01b03167fc39e3e80c0219fde334a8cb5d8468b628482e23388b6e809c90cb00c63c8ce388360405161206791815260200190565b60405180910390a3505b5050505050565b60006120cd826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166123af9092919063ffffffff16565b90508051600014806120ee5750808060200190518101906120ee9190612bbc565b6115005760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610487565b600054610100900460ff166121745760405162461bcd60e51b815260040161048790612d5e565b61114d33611da2565b60008061218a84846123be565b9050612195816123ef565b949350505050565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663095ea7b360e01b1790529151909160009182918716906121fb908590612f29565b6000604051808303816000865af19150503d8060008114612238576040519150601f19603f3d011682016040523d82523d6000602084013e61223d565b606091505b509150915081158061226b575080511580159061226b5750808060200190518101906122699190612bbc565b155b156109c057604051633e3f8f7360e01b815260040160405180910390fd5b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316836001600160a01b0316036123265761231f82612407565b9050611135565b60cb5460405163266e0a7f60e01b81526001600160a01b0385811660048301528481166024830152600092169063266e0a7f90604401602060405180830381865afa158015612379573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061239d91906129f9565b6001600160a01b031614159392505050565b606061219584846000856125d8565b60408051602081019091526000815260405180602001604052806123e68560000151856126b3565b90529392505050565b805160009061113590670de0b6b3a764000090612f45565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b0772d0b6040518163ffffffff1660e01b8152600401600060405180830381865afa158015612468573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526124909190810190612f67565b905060005b81518110156125d1578181815181106124b0576124b06129e3565b60200260200101516001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03161461258457836001600160a01b031682828151811061250c5761250c6129e3565b60200260200101516001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa158015612551573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061257591906129f9565b6001600160a01b0316146125ba565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316846001600160a01b0316145b9250826125d1576125ca81612c56565b9050612495565b5050919050565b6060824710156126395760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610487565b600080866001600160a01b031685876040516126559190612f29565b60006040518083038185875af1925050503d8060008114612692576040519150601f19603f3d011682016040523d82523d6000602084013e612697565b606091505b50915091506126a8878383876126c6565b979650505050505050565b60006126bf8284612ff6565b9392505050565b6060831561273557825160000361272e576001600160a01b0385163b61272e5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610487565b5081612195565b612195838381511561274a5781518083602001fd5b8060405162461bcd60e51b81526004016104879190613015565b6001600160a01b038116811461064357600080fd5b6000806040838503121561278c57600080fd5b823561279781612764565b946020939093013593505050565b6000602082840312156127b757600080fd5b81356126bf81612764565b600080604083850312156127d557600080fd5b82356127e081612764565b915060208301356127f081612764565b809150509250929050565b600080600080600060a0868803121561281357600080fd5b853561281e81612764565b945060208601359350604086013561283581612764565b9250606086013561284581612764565b949793965091946080013592915050565b60008083601f84011261286857600080fd5b50813567ffffffffffffffff81111561288057600080fd5b6020830191508360208260051b850101111561289b57600080fd5b9250929050565b60008060008060008060006080888a0312156128bd57600080fd5b873567ffffffffffffffff808211156128d557600080fd5b6128e18b838c01612856565b909950975060208a01359150808211156128fa57600080fd5b6129068b838c01612856565b909750955060408a013591508082111561291f57600080fd5b5061292c8a828b01612856565b989b979a50959894979596606090950135949350505050565b60006020828403121561295757600080fd5b5035919050565b6020808252600a90820152691c994b595b9d195c995960b21b604082015260600190565b60006020828403121561299457600080fd5b5051919050565b60208082526028908201527f5269736b2046756e643a20496e76616c6964206d696e20616d6f756e7420746f6040820152670818dbdb9d995c9d60c21b606082015260800190565b634e487b7160e01b600052603260045260246000fd5b600060208284031215612a0b57600080fd5b81516126bf81612764565b634e487b7160e01b600052604160045260246000fd5b60405160a0810167ffffffffffffffff81118282101715612a4f57612a4f612a16565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715612a7e57612a7e612a16565b604052919050565b60005b83811015612aa1578181015183820152602001612a89565b83811115612ab0576000848401525b50505050565b8051612ac181612764565b919050565b60006020808385031215612ad957600080fd5b825167ffffffffffffffff80821115612af157600080fd5b9084019060a08287031215612b0557600080fd5b612b0d612a2c565b825182811115612b1c57600080fd5b8301601f81018813612b2d57600080fd5b805183811115612b3f57612b3f612a16565b612b51601f8201601f19168701612a55565b93508084528886828401011115612b6757600080fd5b612b7681878601888501612a86565b5050818152612b86848401612ab6565b84820152612b9660408401612ab6565b604082015260608301516060820152608083015160808201528094505050505092915050565b600060208284031215612bce57600080fd5b815180151581146126bf57600080fd5b6000808335601e19843603018112612bf557600080fd5b83018035915067ffffffffffffffff821115612c1057600080fd5b6020019150600581901b360382131561289b57600080fd5b634e487b7160e01b600052601160045260246000fd5b60008219821115612c5157612c51612c28565b500190565b600060018201612c6857612c68612c28565b5060010190565b8183526000602080850194508260005b85811015612cad578135612c9281612764565b6001600160a01b031687529582019590820190600101612c7f565b509495945050505050565b606081526000612ccc606083018789612c6f565b82810360208401528481526001600160fb1b03851115612ceb57600080fd5b8460051b80876020840137600091016020019081526040929092019290925295945050505050565b6020808252602b908201527f5265736572766548656c706572733a20436f6d7074726f6c6c6572206164647260408201526a195cdcc81a5b9d985b1a5960aa1b606082015260800190565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b60008151808452612dc1816020860160208601612a86565b601f01601f19169290920160200192915050565b6001600160a01b038316815260406020820181905260009061219590830184612da9565b6001600160a01b03848116825283166020820152606060408201819052600090611d9990830184612da9565b600082821015612e3757612e37612c28565b500390565b86815285602082015260a060408201526000612e5c60a083018688612c6f565b6001600160a01b039490941660608301525060800152949350505050565b600067ffffffffffffffff821115612e9457612e94612a16565b5060051b60200190565b60006020808385031215612eb157600080fd5b825167ffffffffffffffff811115612ec857600080fd5b8301601f81018513612ed957600080fd5b8051612eec612ee782612e7a565b612a55565b81815260059190911b82018301908381019087831115612f0b57600080fd5b928401925b828410156126a857835182529284019290840190612f10565b60008251612f3b818460208701612a86565b9190910192915050565b600082612f6257634e487b7160e01b600052601260045260246000fd5b500490565b60006020808385031215612f7a57600080fd5b825167ffffffffffffffff811115612f9157600080fd5b8301601f81018513612fa257600080fd5b8051612fb0612ee782612e7a565b81815260059190911b82018301908381019087831115612fcf57600080fd5b928401925b828410156126a8578351612fe781612764565b82529284019290840190612fd4565b600081600019048311821515161561301057613010612c28565b500290565b6020815260006126bf6020830184612da956fe73776170506f6f6c7341737365747328616464726573735b5d2c75696e743235365b5d2c616464726573735b5d5b5d2c75696e7432353629a2646970667358221220c967afe4ee07c007702bfe8b40ad090042c372456a0a152775ad412949fc6bc564736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101da5760003560e01c806377d4937f11610104578063afcff50f116100a2578063e30c397811610071578063e30c39781461040e578063f2fde38b1461041f578063fa7b81a014610432578063fe3da9841461045957600080fd5b8063afcff50f146103cd578063b4a0bdf3146103e0578063be26317e146103f1578063c8ecc0d3146103fa57600080fd5b806380d45a2d116100de57806380d45a2d146103835780638da5cb5b14610396578063a69bd19e146103a7578063aac59a75146103ba57600080fd5b806377d4937f1461035557806379ba5097146103685780637b77cd6a1461037057600080fd5b80633421fc521161017c5780635f30e37b1161014b5780635f30e37b146103145780636fb0527514610327578063715018a61461033a578063746460a91461034257600080fd5b80633421fc5214610293578063362b6795146102ba578063439b5517146102e15780634dd9584a1461030157600080fd5b806324558995116101b85780632455899514610246578063258836fe1461025a5780632a1d05471461026d5780632e6881411461028057600080fd5b80630a9837c5146101df5780630e32cb861461020557806319b1faef1461021a575b600080fd5b6101f26101ed366004612779565b610463565b6040519081526020015b60405180910390f35b6102186102133660046127a5565b610632565b005b61012e5461022e906001600160a01b031681565b6040516001600160a01b0390911681526020016101fc565b61012f5461022e906001600160a01b031681565b6102186102683660046127c2565b610646565b61021861027b3660046127fb565b6107d7565b61021861028e3660046127a5565b6109c8565b61022e7f000000000000000000000000000000000000000000000000000000000000000081565b61022e7f000000000000000000000000000000000000000000000000000000000000000081565b6101f26102ef3660046127a5565b60c96020526000908152604090205481565b61021861030f3660046127a5565b610acd565b6101f26103223660046128a2565b610b31565b6101f26103353660046127c2565b611085565b61021861113b565b610218610350366004612945565b61114f565b6102186103633660046127a5565b6111f4565b610218611258565b61021861037e3660046127a5565b6112cf565b610218610391366004612945565b611332565b6033546001600160a01b031661022e565b6101f26103b53660046127a5565b611343565b6102186103c83660046127c2565b61142f565b60cb5461022e906001600160a01b031681565b6097546001600160a01b031661022e565b6101f260fb5481565b61012d5461022e906001600160a01b031681565b6065546001600160a01b031661022e565b61021861042d3660046127a5565b61143d565b61022e7f000000000000000000000000000000000000000000000000000000000000000081565b6101f26101305481565b6000600260cc54036104905760405162461bcd60e51b81526004016104879061295e565b60405180910390fd5b600260cc5561012e546001600160a01b03163381146105085760405162461bcd60e51b815260206004820152602e60248201527f5269736b2066756e643a204f6e6c792063616c6c61626c652062792053686f7260448201526d1d19985b1b0818dbdb9d1c9858dd60921b6064820152608401610487565b6001600160a01b03808516600090815260ca6020908152604080832061012d549094168352929052205483111561058f5760405162461bcd60e51b815260206004820152602560248201527f5269736b2046756e643a20496e73756666696369656e7420706f6f6c2072657360448201526432b93b329760d91b6064820152608401610487565b6001600160a01b03808516600081815260ca6020908152604080832061012d80548716855290835281842080548a9003905554909416825260c990528290208054869003905590517fc8d0a37ed16dfaa43514df00e18f478b60d5cc7b4bfc687103948b9020f737fd906106069086815260200190565b60405180910390a261012d54610626906001600160a01b031682856114ae565b5050600160cc55919050565b61063a611505565b6106438161155f565b50565b61064e611505565b600260cc54036106705760405162461bcd60e51b81526004016104879061295e565b600260cc5561067e8161161d565b6040516370a0823160e01b815230600482015260009081906001600160a01b038516906370a0823190602401602060405180830381865afa1580156106c7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106eb9190612982565b6001600160a01b038516600090815260c9602052604090205490915081116107615760405162461bcd60e51b815260206004820152602360248201527f5265736572766548656c706572733a205a65726f20737572706c757320746f6b604482015262656e7360e81b6064820152608401610487565b6001600160a01b03848116600081815260c960209081526040918290205491519185038083529550928616927f6d25be279134f4ecaa4770aff0c3d916d9e7c5ef37b65ed95dbdba411f5d54d5910160405180910390a36107cc6001600160a01b03851684846114ae565b5050600160cc555050565b600054610100900460ff16158080156107f75750600054600160ff909116105b806108115750303b158015610811575060005460ff166001145b6108745760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610487565b6000805460ff191660011790558015610897576000805461ff0019166101001790555b6108a08661161d565b6108a98461161d565b600085116108c95760405162461bcd60e51b81526004016104879061299b565b600082116109285760405162461bcd60e51b815260206004820152602660248201527f5269736b2046756e643a204c6f6f7073206c696d69742063616e206e6f74206260448201526565207a65726f60d01b6064820152608401610487565b610930611644565b61093983611673565b61012f80546001600160a01b038089166001600160a01b03199283161790925561013087905561012d80549287169290911691909117905561097a8261169a565b80156109c0576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050565b610a066040518060400160405280602081526020017f736574436f6e7665727469626c65426173654173736574286164647265737329815250611734565b6001600160a01b038116610a7a5760405162461bcd60e51b815260206004820152603560248201527f5269736b2046756e643a206e657720636f6e7665727469626c65206261736520604482015274185cdcd95d081859191c995cdcc81a5b9d985b1a59605a1b6064820152608401610487565b61012d80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f5fa61583da12070720613fefdd68cc6c0e464a71e009742526bd2b2e0ac62cd290600090a35050565b610ad5611505565b610ade8161161d565b61012f80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907fd37b9d138f53ea58d7e50292588239a46efa8f523966febf4066da96defc77fd90600090a35050565b6000600260cc5403610b555760405162461bcd60e51b81526004016104879061295e565b600260cc81905550610b7e60405180606001604052806038815260200161302960389139611734565b42821015610bce5760405162461bcd60e51b815260206004820152601a60248201527f5269736b2066756e643a20646561646c696e65207061737365640000000000006044820152606401610487565b60cb546001600160a01b0316610be38161161d565b878614610c585760405162461bcd60e51b815260206004820152603860248201527f5269736b2066756e643a206d61726b65747320616e6420616d6f756e74734f7560448201527f744d696e2061726520756e657175616c206c656e6774687300000000000000006064820152608401610487565b878414610cc05760405162461bcd60e51b815260206004820152603060248201527f5269736b2066756e643a206d61726b65747320616e642070617468732061726560448201526f20756e657175616c206c656e6774687360801b6064820152608401610487565b600088610ccc816117ce565b60005b818110156110325760008c8c83818110610ceb57610ceb6129e3565b9050602002016020810190610d0091906127a5565b6001600160a01b0316635fe3b5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d3d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d6191906129f9565b604051637aee632d60e01b81526001600160a01b038083166004830152919250600091871690637aee632d90602401600060405180830381865afa158015610dad573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610dd59190810190612ac6565b9050816001600160a01b031681604001516001600160a01b031614610e4c5760405162461bcd60e51b815260206004820152602760248201527f636f6d7074726f6c6c657220646f65736e277420657869737420706f6f6c20726044820152666567697374727960c81b6064820152608401610487565b816001600160a01b0316633d98a1e58f8f86818110610e6d57610e6d6129e3565b9050602002016020810190610e8291906127a5565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa158015610ec6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610eea9190612bbc565b610f2d5760405162461bcd60e51b81526020600482015260146024820152731b585c9ad95d081a5cc81b9bdd081b1a5cdd195960621b6044820152606401610487565b6000610f9c8f8f86818110610f4457610f446129e3565b9050602002016020810190610f5991906127a5565b848f8f88818110610f6c57610f6c6129e3565b905060200201358e8e89818110610f8557610f856129e3565b9050602002810190610f979190612bde565b6117ff565b6001600160a01b03808516600090815260ca6020908152604080832061012d54909416835292905290812080549293508392909190610fdc908490612c3e565b909155505061012d546001600160a01b0316600090815260c960205260408120805483929061100c908490612c3e565b9091555061101c90508187612c3e565b95505050508061102b90612c56565b9050610ccf565b507fb17530966b045b50d4975e7f05048ca00d7335780c24f1c465165a4b94b2d37d8b8b8b8b8660405161106a959493929190612cb8565b60405180910390a150600160cc559998505050505050505050565b60006110908261161d565b826001600160a01b0316627e3dd26040518163ffffffff1660e01b8152600401602060405180830381865afa1580156110cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110f19190612bbc565b61110d5760405162461bcd60e51b815260040161048790612d13565b506001600160a01b03808316600090815260ca60209081526040808320938516835292905220545b92915050565b611143611505565b61114d6000611da2565b565b61118d6040518060400160405280601e81526020017f7365744d696e416d6f756e74546f436f6e766572742875696e74323536290000815250611734565b600081116111ad5760405162461bcd60e51b81526004016104879061299b565b61013080549082905560408051828152602081018490527fada67d0d38fa20c8ae6a5c17cb9d60b0fe7f2d4e4f27ac9ee55e54ac88de9d8d91015b60405180910390a15050565b6111fc611505565b6112058161161d565b61012e80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907fb6e5fcf02f7fbb8acfbaa3bac4fd5abf9ff51e3f2e8884b5498927179b211b2890600090a35050565b60655433906001600160a01b031681146112c65760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b6064820152608401610487565b61064381611da2565b6112d7611505565b6112e08161161d565b60cb80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907fa87b964d321035d2165e484ff4b722dd6eae30606c0b98887d2ed1a34e594bfe90600090a35050565b61133a611505565b6106438161169a565b6000816001600160a01b0316627e3dd26040518163ffffffff1660e01b8152600401602060405180830381865afa158015611382573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113a69190612bbc565b6114015760405162461bcd60e51b815260206004820152602660248201527f5269736b2046756e643a20436f6d7074726f6c6c6572206164647265737320696044820152651b9d985b1a5960d21b6064820152608401610487565b506001600160a01b03908116600090815260ca6020908152604080832061012d549094168352929052205490565b6114398282611dbb565b5050565b611445611505565b606580546001600160a01b0383166001600160a01b031990911681179091556114766033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b179052611500908490612078565b505050565b6033546001600160a01b0316331461114d5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610487565b6001600160a01b0381166115c35760405162461bcd60e51b815260206004820152602560248201527f696e76616c696420616365737320636f6e74726f6c206d616e61676572206164604482015264647265737360d81b6064820152608401610487565b609780546001600160a01b038381166001600160a01b031983168117909355604080519190921680825260208201939093527f66fd58e82f7b31a2a5c30e0888f3093efe4e111b00cd2b0c31fe014601293aa091016111e8565b6001600160a01b038116610643576040516342bcdf7f60e11b815260040160405180910390fd5b600054610100900460ff1661166b5760405162461bcd60e51b815260040161048790612d5e565b61114d61214d565b600054610100900460ff1661063a5760405162461bcd60e51b815260040161048790612d5e565b60fb5481116116f65760405162461bcd60e51b815260206004820152602260248201527f436f6d7074726f6c6c65723a20496e76616c6964206d61784c6f6f70734c696d6044820152611a5d60f21b6064820152608401610487565b60fb80549082905560408051828152602081018490527fc2d09fef144f7c8a86f71ea459f8fc17f675768eb1ae369cbd77fb31d467aafa91016111e8565b6097546040516318c5e8ab60e01b81526000916001600160a01b0316906318c5e8ab906117679033908690600401612dd5565b602060405180830381865afa158015611784573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117a89190612bbc565b90508061143957333083604051634a3fa29360e01b815260040161048793929190612df9565b60fb548111156106435760fb5460405163792bfb1b60e11b8152600481019190915260248101829052604401610487565b6000836000036118775760405162461bcd60e51b815260206004820152603c60248201527f5269736b46756e643a20616d6f756e744f75744d696e206d757374206265206760448201527f726561746572207468616e203020746f20737761702076546f6b656e000000006064820152608401610487565b600080876001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa1580156118b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118dc91906129f9565b61012d546001600160a01b03898116600090815260ca60209081526040808320848716845290915281205493945091169190819003611922576000945050505050611d99565b6000896001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa158015611962573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061198691906129f9565b60405163b62cad6960e01b81526001600160a01b0385811660048301529192509082169063b62cad6990602401600060405180830381600087803b1580156119cd57600080fd5b505af11580156119e1573d6000803e3d6000fd5b50506040805160208101918290526341976e0960e01b9091526001600160a01b03868116602483015260009350909150819084166341976e0960448301602060405180830381865afa158015611a3b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a5f9190612982565b905290506000611a6f828c61217d565b905061013054811015611ad25760405162461bcd60e51b815260206004820152602560248201527f5269736b46756e643a206d696e416d6f756e74546f436f6e766572742076696f6044820152641b185d195960da1b6064820152608401610487565b6001600160a01b038616600090815260c9602052604081208054869290611afa908490612e25565b90915550506001600160a01b03808d16600090815260ca60209081526040808320938a1683529290529081208054869290611b36908490612e25565b90915550506001600160a01b0386811690861614611d8b57856001600160a01b03168a8a6000818110611b6b57611b6b6129e3565b9050602002016020810190611b8091906127a5565b6001600160a01b031614611bfc5760405162461bcd60e51b815260206004820152603860248201527f5269736b46756e643a20737761702070617468206d757374207374617274207760448201527f6974682074686520756e6465726c79696e6720617373657400000000000000006064820152608401610487565b6001600160a01b0385168a8a611c13600182612e25565b818110611c2257611c226129e3565b9050602002016020810190611c3791906127a5565b6001600160a01b031614611cab5760405162461bcd60e51b815260206004820152603560248201527f5269736b46756e643a2066696e616c6c792070617468206d75737420626520636044820152741bdb9d995c9d1a589b194818985cd948185cdcd95d605a1b6064820152608401610487565b61012f546001600160a01b0390811690611cc990881682600061219d565b611cdd6001600160a01b038816828761219d565b6000816001600160a01b03166338ed1739878f8f8f30426040518763ffffffff1660e01b8152600401611d1596959493929190612e3c565b6000604051808303816000875af1158015611d34573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611d5c9190810190612e9e565b905080611d6a60018d612e25565b81518110611d7a57611d7a6129e3565b602002602001015198505050611d8f565b8396505b5094955050505050505b95945050505050565b606580546001600160a01b031916905561064381612289565b611dc48161161d565b816001600160a01b0316627e3dd26040518163ffffffff1660e01b8152600401602060405180830381865afa158015611e01573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e259190612bbc565b611e415760405162461bcd60e51b815260040161048790612d13565b60cb546001600160a01b031680611eb35760405162461bcd60e51b815260206004820152603060248201527f5265736572766548656c706572733a20506f6f6c20526567697374727920616460448201526f191c995cdcc81a5cc81b9bdd081cd95d60821b6064820152608401610487565b611ebd83836122db565b611f245760405162461bcd60e51b815260206004820152603260248201527f5265736572766548656c706572733a2054686520706f6f6c20646f65736e2774604482015271081cdd5c1c1bdc9d081d1a1948185cdcd95d60721b6064820152608401610487565b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa158015611f6b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f8f9190612982565b6001600160a01b038416600090815260c9602052604090205490915080821115612071576001600160a01b038416600090815260c960205260408120805483850392839291611fdf908490612c3e565b90915550506001600160a01b03808716600090815260ca602090815260408083209389168352929052908120805483929061201b908490612c3e565b92505081905550846001600160a01b0316866001600160a01b03167fc39e3e80c0219fde334a8cb5d8468b628482e23388b6e809c90cb00c63c8ce388360405161206791815260200190565b60405180910390a3505b5050505050565b60006120cd826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166123af9092919063ffffffff16565b90508051600014806120ee5750808060200190518101906120ee9190612bbc565b6115005760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610487565b600054610100900460ff166121745760405162461bcd60e51b815260040161048790612d5e565b61114d33611da2565b60008061218a84846123be565b9050612195816123ef565b949350505050565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663095ea7b360e01b1790529151909160009182918716906121fb908590612f29565b6000604051808303816000865af19150503d8060008114612238576040519150601f19603f3d011682016040523d82523d6000602084013e61223d565b606091505b509150915081158061226b575080511580159061226b5750808060200190518101906122699190612bbc565b155b156109c057604051633e3f8f7360e01b815260040160405180910390fd5b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316836001600160a01b0316036123265761231f82612407565b9050611135565b60cb5460405163266e0a7f60e01b81526001600160a01b0385811660048301528481166024830152600092169063266e0a7f90604401602060405180830381865afa158015612379573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061239d91906129f9565b6001600160a01b031614159392505050565b606061219584846000856125d8565b60408051602081019091526000815260405180602001604052806123e68560000151856126b3565b90529392505050565b805160009061113590670de0b6b3a764000090612f45565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b0772d0b6040518163ffffffff1660e01b8152600401600060405180830381865afa158015612468573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526124909190810190612f67565b905060005b81518110156125d1578181815181106124b0576124b06129e3565b60200260200101516001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03161461258457836001600160a01b031682828151811061250c5761250c6129e3565b60200260200101516001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa158015612551573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061257591906129f9565b6001600160a01b0316146125ba565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316846001600160a01b0316145b9250826125d1576125ca81612c56565b9050612495565b5050919050565b6060824710156126395760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610487565b600080866001600160a01b031685876040516126559190612f29565b60006040518083038185875af1925050503d8060008114612692576040519150601f19603f3d011682016040523d82523d6000602084013e612697565b606091505b50915091506126a8878383876126c6565b979650505050505050565b60006126bf8284612ff6565b9392505050565b6060831561273557825160000361272e576001600160a01b0385163b61272e5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610487565b5081612195565b612195838381511561274a5781518083602001fd5b8060405162461bcd60e51b81526004016104879190613015565b6001600160a01b038116811461064357600080fd5b6000806040838503121561278c57600080fd5b823561279781612764565b946020939093013593505050565b6000602082840312156127b757600080fd5b81356126bf81612764565b600080604083850312156127d557600080fd5b82356127e081612764565b915060208301356127f081612764565b809150509250929050565b600080600080600060a0868803121561281357600080fd5b853561281e81612764565b945060208601359350604086013561283581612764565b9250606086013561284581612764565b949793965091946080013592915050565b60008083601f84011261286857600080fd5b50813567ffffffffffffffff81111561288057600080fd5b6020830191508360208260051b850101111561289b57600080fd5b9250929050565b60008060008060008060006080888a0312156128bd57600080fd5b873567ffffffffffffffff808211156128d557600080fd5b6128e18b838c01612856565b909950975060208a01359150808211156128fa57600080fd5b6129068b838c01612856565b909750955060408a013591508082111561291f57600080fd5b5061292c8a828b01612856565b989b979a50959894979596606090950135949350505050565b60006020828403121561295757600080fd5b5035919050565b6020808252600a90820152691c994b595b9d195c995960b21b604082015260600190565b60006020828403121561299457600080fd5b5051919050565b60208082526028908201527f5269736b2046756e643a20496e76616c6964206d696e20616d6f756e7420746f6040820152670818dbdb9d995c9d60c21b606082015260800190565b634e487b7160e01b600052603260045260246000fd5b600060208284031215612a0b57600080fd5b81516126bf81612764565b634e487b7160e01b600052604160045260246000fd5b60405160a0810167ffffffffffffffff81118282101715612a4f57612a4f612a16565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715612a7e57612a7e612a16565b604052919050565b60005b83811015612aa1578181015183820152602001612a89565b83811115612ab0576000848401525b50505050565b8051612ac181612764565b919050565b60006020808385031215612ad957600080fd5b825167ffffffffffffffff80821115612af157600080fd5b9084019060a08287031215612b0557600080fd5b612b0d612a2c565b825182811115612b1c57600080fd5b8301601f81018813612b2d57600080fd5b805183811115612b3f57612b3f612a16565b612b51601f8201601f19168701612a55565b93508084528886828401011115612b6757600080fd5b612b7681878601888501612a86565b5050818152612b86848401612ab6565b84820152612b9660408401612ab6565b604082015260608301516060820152608083015160808201528094505050505092915050565b600060208284031215612bce57600080fd5b815180151581146126bf57600080fd5b6000808335601e19843603018112612bf557600080fd5b83018035915067ffffffffffffffff821115612c1057600080fd5b6020019150600581901b360382131561289b57600080fd5b634e487b7160e01b600052601160045260246000fd5b60008219821115612c5157612c51612c28565b500190565b600060018201612c6857612c68612c28565b5060010190565b8183526000602080850194508260005b85811015612cad578135612c9281612764565b6001600160a01b031687529582019590820190600101612c7f565b509495945050505050565b606081526000612ccc606083018789612c6f565b82810360208401528481526001600160fb1b03851115612ceb57600080fd5b8460051b80876020840137600091016020019081526040929092019290925295945050505050565b6020808252602b908201527f5265736572766548656c706572733a20436f6d7074726f6c6c6572206164647260408201526a195cdcc81a5b9d985b1a5960aa1b606082015260800190565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b60008151808452612dc1816020860160208601612a86565b601f01601f19169290920160200192915050565b6001600160a01b038316815260406020820181905260009061219590830184612da9565b6001600160a01b03848116825283166020820152606060408201819052600090611d9990830184612da9565b600082821015612e3757612e37612c28565b500390565b86815285602082015260a060408201526000612e5c60a083018688612c6f565b6001600160a01b039490941660608301525060800152949350505050565b600067ffffffffffffffff821115612e9457612e94612a16565b5060051b60200190565b60006020808385031215612eb157600080fd5b825167ffffffffffffffff811115612ec857600080fd5b8301601f81018513612ed957600080fd5b8051612eec612ee782612e7a565b612a55565b81815260059190911b82018301908381019087831115612f0b57600080fd5b928401925b828410156126a857835182529284019290840190612f10565b60008251612f3b818460208701612a86565b9190910192915050565b600082612f6257634e487b7160e01b600052601260045260246000fd5b500490565b60006020808385031215612f7a57600080fd5b825167ffffffffffffffff811115612f9157600080fd5b8301601f81018513612fa257600080fd5b8051612fb0612ee782612e7a565b81815260059190911b82018301908381019087831115612fcf57600080fd5b928401925b828410156126a8578351612fe781612764565b82529284019290840190612fd4565b600081600019048311821515161561301057613010612c28565b500290565b6020815260006126bf6020830184612da956fe73776170506f6f6c7341737365747328616464726573735b5d2c75696e743235365b5d2c616464726573735b5d5b5d2c75696e7432353629a2646970667358221220c967afe4ee07c007702bfe8b40ad090042c372456a0a152775ad412949fc6bc564736f6c634300080d0033", "devdoc": { "author": "Venus", "details": "This contract does not support BNB.", @@ -1033,7 +1092,7 @@ "storageLayout": { "storage": [ { - "astId": 290, + "astId": 244, "contract": "contracts/RiskFund/RiskFund.sol:RiskFund", "label": "_initialized", "offset": 0, @@ -1041,7 +1100,7 @@ "type": "t_uint8" }, { - "astId": 293, + "astId": 247, "contract": "contracts/RiskFund/RiskFund.sol:RiskFund", "label": "_initializing", "offset": 1, @@ -1049,7 +1108,7 @@ "type": "t_bool" }, { - "astId": 1397, + "astId": 1267, "contract": "contracts/RiskFund/RiskFund.sol:RiskFund", "label": "__gap", "offset": 0, @@ -1057,7 +1116,7 @@ "type": "t_array(t_uint256)50_storage" }, { - "astId": 162, + "astId": 116, "contract": "contracts/RiskFund/RiskFund.sol:RiskFund", "label": "_owner", "offset": 0, @@ -1065,7 +1124,7 @@ "type": "t_address" }, { - "astId": 282, + "astId": 236, "contract": "contracts/RiskFund/RiskFund.sol:RiskFund", "label": "__gap", "offset": 0, @@ -1073,7 +1132,7 @@ "type": "t_array(t_uint256)49_storage" }, { - "astId": 71, + "astId": 25, "contract": "contracts/RiskFund/RiskFund.sol:RiskFund", "label": "_pendingOwner", "offset": 0, @@ -1081,7 +1140,7 @@ "type": "t_address" }, { - "astId": 150, + "astId": 104, "contract": "contracts/RiskFund/RiskFund.sol:RiskFund", "label": "__gap", "offset": 0, @@ -1089,15 +1148,15 @@ "type": "t_array(t_uint256)49_storage" }, { - "astId": 3341, + "astId": 1355, "contract": "contracts/RiskFund/RiskFund.sol:RiskFund", "label": "_accessControlManager", "offset": 0, "slot": "151", - "type": "t_contract(IAccessControlManagerV8)3525" + "type": "t_contract(IAccessControlManagerV8)1539" }, { - "astId": 3346, + "astId": 1360, "contract": "contracts/RiskFund/RiskFund.sol:RiskFund", "label": "__gap", "offset": 0, @@ -1105,7 +1164,7 @@ "type": "t_array(t_uint256)49_storage" }, { - "astId": 13338, + "astId": 8855, "contract": "contracts/RiskFund/RiskFund.sol:RiskFund", "label": "assetsReserves", "offset": 0, @@ -1113,7 +1172,7 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 13344, + "astId": 8861, "contract": "contracts/RiskFund/RiskFund.sol:RiskFund", "label": "_poolsAssetsReserves", "offset": 0, @@ -1121,7 +1180,7 @@ "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))" }, { - "astId": 13346, + "astId": 8863, "contract": "contracts/RiskFund/RiskFund.sol:RiskFund", "label": "poolRegistry", "offset": 0, @@ -1129,7 +1188,7 @@ "type": "t_address" }, { - "astId": 13349, + "astId": 8866, "contract": "contracts/RiskFund/RiskFund.sol:RiskFund", "label": "status", "offset": 0, @@ -1137,7 +1196,7 @@ "type": "t_uint256" }, { - "astId": 13354, + "astId": 8871, "contract": "contracts/RiskFund/RiskFund.sol:RiskFund", "label": "__gap", "offset": 0, @@ -1145,7 +1204,7 @@ "type": "t_array(t_uint256)46_storage" }, { - "astId": 10571, + "astId": 6064, "contract": "contracts/RiskFund/RiskFund.sol:RiskFund", "label": "maxLoopsLimit", "offset": 0, @@ -1153,7 +1212,7 @@ "type": "t_uint256" }, { - "astId": 10576, + "astId": 6069, "contract": "contracts/RiskFund/RiskFund.sol:RiskFund", "label": "__gap", "offset": 0, @@ -1161,7 +1220,7 @@ "type": "t_array(t_uint256)49_storage" }, { - "astId": 13647, + "astId": 9284, "contract": "contracts/RiskFund/RiskFund.sol:RiskFund", "label": "convertibleBaseAsset", "offset": 0, @@ -1169,7 +1228,7 @@ "type": "t_address" }, { - "astId": 13649, + "astId": 9286, "contract": "contracts/RiskFund/RiskFund.sol:RiskFund", "label": "shortfall", "offset": 0, @@ -1177,7 +1236,7 @@ "type": "t_address" }, { - "astId": 13651, + "astId": 9288, "contract": "contracts/RiskFund/RiskFund.sol:RiskFund", "label": "pancakeSwapRouter", "offset": 0, @@ -1185,7 +1244,7 @@ "type": "t_address" }, { - "astId": 13653, + "astId": 9290, "contract": "contracts/RiskFund/RiskFund.sol:RiskFund", "label": "minAmountToConvert", "offset": 0, @@ -1222,7 +1281,7 @@ "label": "bool", "numberOfBytes": "1" }, - "t_contract(IAccessControlManagerV8)3525": { + "t_contract(IAccessControlManagerV8)1539": { "encoding": "inplace", "label": "contract IAccessControlManagerV8", "numberOfBytes": "20" diff --git a/deployments/bscmainnet/solcInputs/f237ea044837d6f4ff4c08abcdd27558.json b/deployments/bscmainnet/solcInputs/f237ea044837d6f4ff4c08abcdd27558.json new file mode 100644 index 000000000..49193e297 --- /dev/null +++ b/deployments/bscmainnet/solcInputs/f237ea044837d6f4ff4c08abcdd27558.json @@ -0,0 +1,132 @@ +{ + "language": "Solidity", + "sources": { + "@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable2Step.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./OwnableUpgradeable.sol\";\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module which provides access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership} and {acceptOwnership}.\n *\n * This module is used through inheritance. It will make available all functions\n * from parent (Ownable).\n */\nabstract contract Ownable2StepUpgradeable is Initializable, OwnableUpgradeable {\n function __Ownable2Step_init() internal onlyInitializing {\n __Ownable_init_unchained();\n }\n\n function __Ownable2Step_init_unchained() internal onlyInitializing {\n }\n address private _pendingOwner;\n\n event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Returns the address of the pending owner.\n */\n function pendingOwner() public view virtual returns (address) {\n return _pendingOwner;\n }\n\n /**\n * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual override onlyOwner {\n _pendingOwner = newOwner;\n emit OwnershipTransferStarted(owner(), newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual override {\n delete _pendingOwner;\n super._transferOwnership(newOwner);\n }\n\n /**\n * @dev The new owner accepts the ownership transfer.\n */\n function acceptOwnership() public virtual {\n address sender = _msgSender();\n require(pendingOwner() == sender, \"Ownable2Step: caller is not the new owner\");\n _transferOwnership(sender);\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/ContextUpgradeable.sol\";\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n function __Ownable_init() internal onlyInitializing {\n __Ownable_init_unchained();\n }\n\n function __Ownable_init_unchained() internal onlyInitializing {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n _checkOwner();\n _;\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if the sender is not the owner.\n */\n function _checkOwner() internal view virtual {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby disabling any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)\n\npragma solidity ^0.8.2;\n\nimport \"../../utils/AddressUpgradeable.sol\";\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```solidity\n * contract MyToken is ERC20Upgradeable {\n * function initialize() initializer public {\n * __ERC20_init(\"MyToken\", \"MTK\");\n * }\n * }\n *\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n * function initializeV2() reinitializer(2) public {\n * __ERC20Permit_init(\"MyToken\");\n * }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n * _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n /**\n * @dev Indicates that the contract has been initialized.\n * @custom:oz-retyped-from bool\n */\n uint8 private _initialized;\n\n /**\n * @dev Indicates that the contract is in the process of being initialized.\n */\n bool private _initializing;\n\n /**\n * @dev Triggered when the contract has been initialized or reinitialized.\n */\n event Initialized(uint8 version);\n\n /**\n * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n * `onlyInitializing` functions can be used to initialize parent contracts.\n *\n * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a\n * constructor.\n *\n * Emits an {Initialized} event.\n */\n modifier initializer() {\n bool isTopLevelCall = !_initializing;\n require(\n (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),\n \"Initializable: contract is already initialized\"\n );\n _initialized = 1;\n if (isTopLevelCall) {\n _initializing = true;\n }\n _;\n if (isTopLevelCall) {\n _initializing = false;\n emit Initialized(1);\n }\n }\n\n /**\n * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n * used to initialize parent contracts.\n *\n * A reinitializer may be used after the original initialization step. This is essential to configure modules that\n * are added through upgrades and that require initialization.\n *\n * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\n * cannot be nested. If one is invoked in the context of another, execution will revert.\n *\n * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n * a contract, executing them in the right order is up to the developer or operator.\n *\n * WARNING: setting the version to 255 will prevent any future reinitialization.\n *\n * Emits an {Initialized} event.\n */\n modifier reinitializer(uint8 version) {\n require(!_initializing && _initialized < version, \"Initializable: contract is already initialized\");\n _initialized = version;\n _initializing = true;\n _;\n _initializing = false;\n emit Initialized(version);\n }\n\n /**\n * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n * {initializer} and {reinitializer} modifiers, directly or indirectly.\n */\n modifier onlyInitializing() {\n require(_initializing, \"Initializable: contract is not initializing\");\n _;\n }\n\n /**\n * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n * through proxies.\n *\n * Emits an {Initialized} event the first time it is successfully executed.\n */\n function _disableInitializers() internal virtual {\n require(!_initializing, \"Initializable: contract is initializing\");\n if (_initialized != type(uint8).max) {\n _initialized = type(uint8).max;\n emit Initialized(type(uint8).max);\n }\n }\n\n /**\n * @dev Returns the highest version that has been initialized. See {reinitializer}.\n */\n function _getInitializedVersion() internal view returns (uint8) {\n return _initialized;\n }\n\n /**\n * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\n */\n function _isInitializing() internal view returns (bool) {\n return _initializing;\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/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/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" + }, + "@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/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/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" + }, + "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/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/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 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 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\";\nimport { VToken } from \"../VToken.sol\";\nimport { PoolRegistry } from \"../Pool/PoolRegistry.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 PoolRegistry(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/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" + } + }, + "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/bsctestnet/RiskFund_Implementation.json b/deployments/bsctestnet/RiskFund_Implementation.json index 21f515098..ea2c6b26f 100644 --- a/deployments/bsctestnet/RiskFund_Implementation.json +++ b/deployments/bsctestnet/RiskFund_Implementation.json @@ -1,5 +1,5 @@ { - "address": "0x4A4Aabf30A3b8F2a262c9e49A343e728Ff07e7F4", + "address": "0x50B26c741Db8F45b24498575C203c862Fe70d934", "abi": [ { "inputs": [ @@ -811,32 +811,30 @@ "type": "function" } ], - "transactionHash": "0x70250bc04c612fb8c897e5e608ff19ca7e2f52e4249b8ab90da4c87238537d29", + "transactionHash": "0x510331028fd96d747253dc318dfe753c619a984f00bb506ae0d2c8412f0f1a97", "receipt": { "to": null, "from": "0x8BDA9f9E1fEF0DFd404Fef338D9fE4c543d172e1", - "contractAddress": "0x4A4Aabf30A3b8F2a262c9e49A343e728Ff07e7F4", - "transactionIndex": 0, - "gasUsed": "2768629", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xe52bf6228183cde78b49303b2135228dfe5d4b5eac197ed598d9828a140a268a", - "transactionHash": "0x70250bc04c612fb8c897e5e608ff19ca7e2f52e4249b8ab90da4c87238537d29", + "contractAddress": "0x50B26c741Db8F45b24498575C203c862Fe70d934", + "transactionIndex": 1, + "gasUsed": "2769907", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000080000000000000000000000001000000000000000000000400000000000000000000000000000000000000000000000000000000000000040000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x40bb0a783e69d9664ac6d5f47534a224f64b75c190858f0fba51d114e51cfd08", + "transactionHash": "0x510331028fd96d747253dc318dfe753c619a984f00bb506ae0d2c8412f0f1a97", "logs": [ { - "transactionIndex": 0, - "blockNumber": 34056841, - "transactionHash": "0x70250bc04c612fb8c897e5e608ff19ca7e2f52e4249b8ab90da4c87238537d29", - "address": "0x4A4Aabf30A3b8F2a262c9e49A343e728Ff07e7F4", - "topics": [ - "0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498" - ], + "transactionIndex": 1, + "blockNumber": 34057466, + "transactionHash": "0x510331028fd96d747253dc318dfe753c619a984f00bb506ae0d2c8412f0f1a97", + "address": "0x50B26c741Db8F45b24498575C203c862Fe70d934", + "topics": ["0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498"], "data": "0x00000000000000000000000000000000000000000000000000000000000000ff", "logIndex": 0, - "blockHash": "0xe52bf6228183cde78b49303b2135228dfe5d4b5eac197ed598d9828a140a268a" + "blockHash": "0x40bb0a783e69d9664ac6d5f47534a224f64b75c190858f0fba51d114e51cfd08" } ], - "blockNumber": 34056841, - "cumulativeGasUsed": "2768629", + "blockNumber": 34057466, + "cumulativeGasUsed": "2801148", "status": 1, "byzantium": true }, @@ -846,10 +844,10 @@ "0xae13d989daC2f0dEbFf460aC112a837C89BAa7cd" ], "numDeployments": 1, - "solcInputHash": "0c597ac2b90fc7d0b2be179fa6482d23", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"corePoolComptroller_\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"vbnb_\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nativeWrapped_\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"ApproveFailed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"loopsLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requiredLoops\",\"type\":\"uint256\"}],\"name\":\"MaxLoopsLimitExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"calledContract\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"methodSignature\",\"type\":\"string\"}],\"name\":\"Unauthorized\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"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\":\"oldConvertibleBaseAsset\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newConvertibleBaseAsset\",\"type\":\"address\"}],\"name\":\"ConvertibleBaseAssetUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldMaxLoopsLimit\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newmaxLoopsLimit\",\"type\":\"uint256\"}],\"name\":\"MaxLoopsLimitUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldMinAmountToConvert\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newMinAmountToConvert\",\"type\":\"uint256\"}],\"name\":\"MinAmountToConvertUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldAccessControlManager\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newAccessControlManager\",\"type\":\"address\"}],\"name\":\"NewAccessControlManager\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferStarted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"oldPancakeSwapRouter\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newPancakeSwapRouter\",\"type\":\"address\"}],\"name\":\"PancakeSwapRouterUpdated\",\"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\":\"oldShortfallContract\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"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\":\"totalAmount\",\"type\":\"uint256\"}],\"name\":\"SwappedPoolsAssets\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"SweepToken\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"TransferredReserveForAuction\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"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\",\"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\"}],\"name\":\"assetsReserves\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"convertibleBaseAsset\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"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\":\"comptroller\",\"type\":\"address\"}],\"name\":\"getPoolsBaseAssetReserves\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"pancakeSwapRouter_\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmountToConvert_\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"convertibleBaseAsset_\",\"type\":\"address\"},{\"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\":\"minAmountToConvert\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pancakeSwapRouter\",\"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\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"accessControlManager_\",\"type\":\"address\"}],\"name\":\"setAccessControlManager\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_convertibleBaseAsset\",\"type\":\"address\"}],\"name\":\"setConvertibleBaseAsset\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"limit\",\"type\":\"uint256\"}],\"name\":\"setMaxLoopsLimit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minAmountToConvert_\",\"type\":\"uint256\"}],\"name\":\"setMinAmountToConvert\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"pancakeSwapRouter_\",\"type\":\"address\"}],\"name\":\"setPancakeSwapRouter\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"poolRegistry_\",\"type\":\"address\"}],\"name\":\"setPoolRegistry\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"shortfallContractAddress_\",\"type\":\"address\"}],\"name\":\"setShortfallContractAddress\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"shortfall\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"markets\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"amountsOutMin\",\"type\":\"uint256[]\"},{\"internalType\":\"address[][]\",\"name\":\"paths\",\"type\":\"address[][]\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"swapPoolsAssets\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"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\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transferReserveForAuction\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"}],\"name\":\"updateAssetsState\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Venus\",\"details\":\"This contract does not support BNB.\",\"kind\":\"dev\",\"methods\":{\"acceptOwnership()\":{\"details\":\"The new owner accepts the ownership transfer.\"},\"constructor\":{\"custom:oz-upgrades-unsafe-allow\":\"constructor\",\"details\":\"Note that the contract is upgradeable. Use initialize() or reinitializers to set the state variables.\"},\"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.\"}},\"getPoolsBaseAssetReserves(address)\":{\"params\":{\"comptroller\":\"Comptroller address(pool).\"},\"returns\":{\"_0\":\"Base Asset's reserve in risk fund.\"}},\"initialize(address,uint256,address,address,uint256)\":{\"custom:error\":\"ZeroAddressNotAllowed is thrown when PCS router address is zeroZeroAddressNotAllowed is thrown when convertible base asset address is zero\",\"params\":{\"accessControlManager_\":\"Address of the access control contract\",\"convertibleBaseAsset_\":\"Address of the base asset\",\"loopsLimit_\":\"Limit for the loops in the contract to avoid DOS\",\"minAmountToConvert_\":\"Minimum amount assets must be worth to convert into base asset\",\"pancakeSwapRouter_\":\"Address of the PancakeSwap router\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"pendingOwner()\":{\"details\":\"Returns the address of the pending owner.\"},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner.\"},\"setAccessControlManager(address)\":{\"custom:access\":\"Only Governance\",\"custom:event\":\"Emits NewAccessControlManager event\",\"details\":\"Admin function to set address of AccessControlManager\",\"params\":{\"accessControlManager_\":\"The new address of the AccessControlManager\"}},\"setConvertibleBaseAsset(address)\":{\"params\":{\"_convertibleBaseAsset\":\"Address for new convertible base asset.\"}},\"setMaxLoopsLimit(uint256)\":{\"params\":{\"limit\":\"Limit for the max loops can execute at a time\"}},\"setMinAmountToConvert(uint256)\":{\"params\":{\"minAmountToConvert_\":\"Min amount to convert.\"}},\"setPancakeSwapRouter(address)\":{\"custom:error\":\"ZeroAddressNotAllowed is thrown when PCS router address is zero\",\"params\":{\"pancakeSwapRouter_\":\"Address of the PancakeSwap router\"}},\"setPoolRegistry(address)\":{\"custom:error\":\"ZeroAddressNotAllowed is thrown when pool registry address is zero\",\"params\":{\"poolRegistry_\":\"Address of the pool registry\"}},\"setShortfallContractAddress(address)\":{\"custom:error\":\"ZeroAddressNotAllowed is thrown when shortfall contract address is zero\",\"params\":{\"shortfallContractAddress_\":\"Address of the auction contract\"}},\"swapPoolsAssets(address[],uint256[],address[][],uint256)\":{\"custom:error\":\"ZeroAddressNotAllowed is thrown if PoolRegistry contract address is not configured\",\"params\":{\"amountsOutMin\":\"Minimum amount to receive for swap\",\"deadline\":\"Deadline for the swap\",\"markets\":\"Array of vTokens whose assets to swap for base asset\",\"paths\":\"A path consisting of PCS token pairs for each swap\"},\"returns\":{\"_0\":\"Number of swapped tokens\"}},\"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.\"},\"transferReserveForAuction(address,uint256)\":{\"params\":{\"amount\":\"Amount to be transferred to auction contract.\",\"comptroller\":\"Comptroller of the pool.\"},\"returns\":{\"_0\":\"Number reserved tokens.\"}},\"updateAssetsState(address,address)\":{\"params\":{\"asset\":\"Asset address.\",\"comptroller\":\"Comptroller address(pool).\"}}},\"title\":\"RiskFund\",\"version\":1},\"userdoc\":{\"errors\":{\"ApproveFailed()\":[{\"notice\":\"Thrown if a contract is unable to approve a transfer\"}],\"MaxLoopsLimitExceeded(uint256,uint256)\":[{\"notice\":\"Thrown an error on maxLoopsLimit exceeds for any loop\"}],\"Unauthorized(address,address,string)\":[{\"notice\":\"Thrown when the action is prohibited by AccessControlManager\"}],\"ZeroAddressNotAllowed()\":[{\"notice\":\"Thrown if the supplied address is a zero address where it is not allowed\"}]},\"events\":{\"AssetsReservesUpdated(address,address,uint256)\":{\"notice\":\"Event emitted after the update of the assets reserves.\"},\"ConvertibleBaseAssetUpdated(address,address)\":{\"notice\":\"Emitted when convertible base asset is updated\"},\"MaxLoopsLimitUpdated(uint256,uint256)\":{\"notice\":\"Emitted when max loops limit is set\"},\"MinAmountToConvertUpdated(uint256,uint256)\":{\"notice\":\"Emitted when minimum amount to convert is updated\"},\"NewAccessControlManager(address,address)\":{\"notice\":\"Emitted when access control manager contract address is changed\"},\"PancakeSwapRouterUpdated(address,address)\":{\"notice\":\"Emitted when PancakeSwap router contract address is updated\"},\"PoolRegistryUpdated(address,address)\":{\"notice\":\"Emitted when pool registry address is updated\"},\"ShortfallContractUpdated(address,address)\":{\"notice\":\"Emitted when shortfall contract address is updated\"},\"SwappedPoolsAssets(address[],uint256[],uint256)\":{\"notice\":\"Emitted when pools assets are swapped\"},\"SweepToken(address,address,uint256)\":{\"notice\":\"event emitted on sweep token success\"},\"TransferredReserveForAuction(address,uint256)\":{\"notice\":\"Emitted when reserves are transferred for auction\"}},\"kind\":\"user\",\"methods\":{\"accessControlManager()\":{\"notice\":\"Returns the address of the access control manager contract\"},\"getPoolAssetReserve(address,address)\":{\"notice\":\"Get the Amount of the asset in the risk fund for the specific pool.\"},\"getPoolsBaseAssetReserves(address)\":{\"notice\":\"Get the Amount of the Base asset in the risk fund for the specific pool.\"},\"initialize(address,uint256,address,address,uint256)\":{\"notice\":\"Initializes the deployer to owner.\"},\"setAccessControlManager(address)\":{\"notice\":\"Sets the address of AccessControlManager\"},\"setConvertibleBaseAsset(address)\":{\"notice\":\"Sets a new convertible base asset\"},\"setMaxLoopsLimit(uint256)\":{\"notice\":\"Set the limit for the loops can iterate to avoid the DOS\"},\"setMinAmountToConvert(uint256)\":{\"notice\":\"Min amount to convert setter\"},\"setPancakeSwapRouter(address)\":{\"notice\":\"PancakeSwap router address setter\"},\"setPoolRegistry(address)\":{\"notice\":\"Pool registry setter\"},\"setShortfallContractAddress(address)\":{\"notice\":\"Shortfall contract address setter\"},\"swapPoolsAssets(address[],uint256[],address[][],uint256)\":{\"notice\":\"Swap array of pool assets into base asset's tokens of at least a minimum amount\"},\"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\"},\"transferReserveForAuction(address,uint256)\":{\"notice\":\"Transfer tokens for auction.\"},\"updateAssetsState(address,address)\":{\"notice\":\"Update the reserve of the asset for the specific pool after transferring to risk fund.\"}},\"notice\":\"Contract with basic features to track/hold different assets for different Comptrollers.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/RiskFund/RiskFund.sol\":\"RiskFund\"},\"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(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 \\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\":\"0xef1ca0adc3ce1ff540279d424953087771b4a07470caac99777fafd2ceea38a9\",\"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 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(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/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\",\"keccak256\":\"0x7e4d140bd2a5671389ad7a3975b65d05a4f750daf6a61c16139d123d9782b96e\",\"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/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/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\\\";\\nimport { PoolRegistry } from \\\"../Pool/PoolRegistry.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 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 PoolRegistry(poolRegistry).getVTokenForAsset(comptroller, asset) != address(0);\\n }\\n}\\n\",\"keccak256\":\"0xb66ce634fdff1b2cf4f52b2e2a2d1232108c74068f2a4129d0f421ed19362211\",\"license\":\"BSD-3-Clause\"},\"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\",\"keccak256\":\"0x918526b067c834935f5dd0788139e1a73c64cbf6f8b7d6fd43242eaa93aa7f37\",\"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(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 \\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 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 \\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(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\",\"keccak256\":\"0xcda9eb71f6ceb8a4c3bfbc1c42d72e2f0523d30f6d3252fbd90819e953640fe5\",\"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(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\":\"0x2947e95eb97a3a45f90ec36d4fd5a4cbb9409319f6ad000e950550055a3f2324\",\"license\":\"BSD-3-Clause\"},\"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\",\"keccak256\":\"0x9bbc31c80a4c537ddfd06cbd03a412ba64842a708381fbc4bf2e33ef56c92b4d\",\"license\":\"MIT\"},\"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": "0x60e06040523480156200001157600080fd5b506040516200326a3803806200326a83398101604081905262000034916200013e565b6001600160a01b0380841660805280831660a052811660c0526200005762000060565b50505062000188565b600054610100900460ff1615620000cd5760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b60005460ff908116146200011f576000805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b80516001600160a01b03811681146200013957600080fd5b919050565b6000806000606084860312156200015457600080fd5b6200015f8462000121565b92506200016f6020850162000121565b91506200017f6040850162000121565b90509250925092565b60805160a05160c051613096620001d4600039600081816102bf015261258601526000818161029801526124c3015260008181610437015281816122df015261240c01526130966000f3fe608060405234801561001057600080fd5b50600436106101da5760003560e01c806377d4937f11610104578063afcff50f116100a2578063e30c397811610071578063e30c39781461040e578063f2fde38b1461041f578063fa7b81a014610432578063fe3da9841461045957600080fd5b8063afcff50f146103cd578063b4a0bdf3146103e0578063be26317e146103f1578063c8ecc0d3146103fa57600080fd5b806380d45a2d116100de57806380d45a2d146103835780638da5cb5b14610396578063a69bd19e146103a7578063aac59a75146103ba57600080fd5b806377d4937f1461035557806379ba5097146103685780637b77cd6a1461037057600080fd5b80633421fc521161017c5780635f30e37b1161014b5780635f30e37b146103145780636fb0527514610327578063715018a61461033a578063746460a91461034257600080fd5b80633421fc5214610293578063362b6795146102ba578063439b5517146102e15780634dd9584a1461030157600080fd5b806324558995116101b85780632455899514610246578063258836fe1461025a5780632a1d05471461026d5780632e6881411461028057600080fd5b80630a9837c5146101df5780630e32cb861461020557806319b1faef1461021a575b600080fd5b6101f26101ed366004612779565b610463565b6040519081526020015b60405180910390f35b6102186102133660046127a5565b610632565b005b61012e5461022e906001600160a01b031681565b6040516001600160a01b0390911681526020016101fc565b61012f5461022e906001600160a01b031681565b6102186102683660046127c2565b610646565b61021861027b3660046127fb565b6107d7565b61021861028e3660046127a5565b6109c8565b61022e7f000000000000000000000000000000000000000000000000000000000000000081565b61022e7f000000000000000000000000000000000000000000000000000000000000000081565b6101f26102ef3660046127a5565b60c96020526000908152604090205481565b61021861030f3660046127a5565b610acd565b6101f26103223660046128a2565b610b31565b6101f26103353660046127c2565b611085565b61021861113b565b610218610350366004612945565b61114f565b6102186103633660046127a5565b6111f4565b610218611258565b61021861037e3660046127a5565b6112cf565b610218610391366004612945565b611332565b6033546001600160a01b031661022e565b6101f26103b53660046127a5565b611343565b6102186103c83660046127c2565b61142f565b60cb5461022e906001600160a01b031681565b6097546001600160a01b031661022e565b6101f260fb5481565b61012d5461022e906001600160a01b031681565b6065546001600160a01b031661022e565b61021861042d3660046127a5565b61143d565b61022e7f000000000000000000000000000000000000000000000000000000000000000081565b6101f26101305481565b6000600260cc54036104905760405162461bcd60e51b81526004016104879061295e565b60405180910390fd5b600260cc5561012e546001600160a01b03163381146105085760405162461bcd60e51b815260206004820152602e60248201527f5269736b2066756e643a204f6e6c792063616c6c61626c652062792053686f7260448201526d1d19985b1b0818dbdb9d1c9858dd60921b6064820152608401610487565b6001600160a01b03808516600090815260ca6020908152604080832061012d549094168352929052205483111561058f5760405162461bcd60e51b815260206004820152602560248201527f5269736b2046756e643a20496e73756666696369656e7420706f6f6c2072657360448201526432b93b329760d91b6064820152608401610487565b6001600160a01b03808516600081815260ca6020908152604080832061012d80548716855290835281842080548a9003905554909416825260c990528290208054869003905590517fc8d0a37ed16dfaa43514df00e18f478b60d5cc7b4bfc687103948b9020f737fd906106069086815260200190565b60405180910390a261012d54610626906001600160a01b031682856114ae565b5050600160cc55919050565b61063a611505565b6106438161155f565b50565b61064e611505565b600260cc54036106705760405162461bcd60e51b81526004016104879061295e565b600260cc5561067e8161161d565b6040516370a0823160e01b815230600482015260009081906001600160a01b038516906370a0823190602401602060405180830381865afa1580156106c7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106eb9190612982565b6001600160a01b038516600090815260c9602052604090205490915081116107615760405162461bcd60e51b815260206004820152602360248201527f5265736572766548656c706572733a205a65726f20737572706c757320746f6b604482015262656e7360e81b6064820152608401610487565b6001600160a01b03848116600081815260c960209081526040918290205491519185038083529550928616927f6d25be279134f4ecaa4770aff0c3d916d9e7c5ef37b65ed95dbdba411f5d54d5910160405180910390a36107cc6001600160a01b03851684846114ae565b5050600160cc555050565b600054610100900460ff16158080156107f75750600054600160ff909116105b806108115750303b158015610811575060005460ff166001145b6108745760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610487565b6000805460ff191660011790558015610897576000805461ff0019166101001790555b6108a08661161d565b6108a98461161d565b600085116108c95760405162461bcd60e51b81526004016104879061299b565b600082116109285760405162461bcd60e51b815260206004820152602660248201527f5269736b2046756e643a204c6f6f7073206c696d69742063616e206e6f74206260448201526565207a65726f60d01b6064820152608401610487565b610930611644565b61093983611673565b61012f80546001600160a01b038089166001600160a01b03199283161790925561013087905561012d80549287169290911691909117905561097a8261169a565b80156109c0576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050565b610a066040518060400160405280602081526020017f736574436f6e7665727469626c65426173654173736574286164647265737329815250611734565b6001600160a01b038116610a7a5760405162461bcd60e51b815260206004820152603560248201527f5269736b2046756e643a206e657720636f6e7665727469626c65206261736520604482015274185cdcd95d081859191c995cdcc81a5b9d985b1a59605a1b6064820152608401610487565b61012d80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f5fa61583da12070720613fefdd68cc6c0e464a71e009742526bd2b2e0ac62cd290600090a35050565b610ad5611505565b610ade8161161d565b61012f80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907fd37b9d138f53ea58d7e50292588239a46efa8f523966febf4066da96defc77fd90600090a35050565b6000600260cc5403610b555760405162461bcd60e51b81526004016104879061295e565b600260cc81905550610b7e60405180606001604052806038815260200161302960389139611734565b42821015610bce5760405162461bcd60e51b815260206004820152601a60248201527f5269736b2066756e643a20646561646c696e65207061737365640000000000006044820152606401610487565b60cb546001600160a01b0316610be38161161d565b878614610c585760405162461bcd60e51b815260206004820152603860248201527f5269736b2066756e643a206d61726b65747320616e6420616d6f756e74734f7560448201527f744d696e2061726520756e657175616c206c656e6774687300000000000000006064820152608401610487565b878414610cc05760405162461bcd60e51b815260206004820152603060248201527f5269736b2066756e643a206d61726b65747320616e642070617468732061726560448201526f20756e657175616c206c656e6774687360801b6064820152608401610487565b600088610ccc816117ce565b60005b818110156110325760008c8c83818110610ceb57610ceb6129e3565b9050602002016020810190610d0091906127a5565b6001600160a01b0316635fe3b5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d3d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d6191906129f9565b604051637aee632d60e01b81526001600160a01b038083166004830152919250600091871690637aee632d90602401600060405180830381865afa158015610dad573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610dd59190810190612ac6565b9050816001600160a01b031681604001516001600160a01b031614610e4c5760405162461bcd60e51b815260206004820152602760248201527f636f6d7074726f6c6c657220646f65736e277420657869737420706f6f6c20726044820152666567697374727960c81b6064820152608401610487565b816001600160a01b0316633d98a1e58f8f86818110610e6d57610e6d6129e3565b9050602002016020810190610e8291906127a5565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa158015610ec6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610eea9190612bbc565b610f2d5760405162461bcd60e51b81526020600482015260146024820152731b585c9ad95d081a5cc81b9bdd081b1a5cdd195960621b6044820152606401610487565b6000610f9c8f8f86818110610f4457610f446129e3565b9050602002016020810190610f5991906127a5565b848f8f88818110610f6c57610f6c6129e3565b905060200201358e8e89818110610f8557610f856129e3565b9050602002810190610f979190612bde565b6117ff565b6001600160a01b03808516600090815260ca6020908152604080832061012d54909416835292905290812080549293508392909190610fdc908490612c3e565b909155505061012d546001600160a01b0316600090815260c960205260408120805483929061100c908490612c3e565b9091555061101c90508187612c3e565b95505050508061102b90612c56565b9050610ccf565b507fb17530966b045b50d4975e7f05048ca00d7335780c24f1c465165a4b94b2d37d8b8b8b8b8660405161106a959493929190612cb8565b60405180910390a150600160cc559998505050505050505050565b60006110908261161d565b826001600160a01b0316627e3dd26040518163ffffffff1660e01b8152600401602060405180830381865afa1580156110cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110f19190612bbc565b61110d5760405162461bcd60e51b815260040161048790612d13565b506001600160a01b03808316600090815260ca60209081526040808320938516835292905220545b92915050565b611143611505565b61114d6000611da2565b565b61118d6040518060400160405280601e81526020017f7365744d696e416d6f756e74546f436f6e766572742875696e74323536290000815250611734565b600081116111ad5760405162461bcd60e51b81526004016104879061299b565b61013080549082905560408051828152602081018490527fada67d0d38fa20c8ae6a5c17cb9d60b0fe7f2d4e4f27ac9ee55e54ac88de9d8d91015b60405180910390a15050565b6111fc611505565b6112058161161d565b61012e80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907fb6e5fcf02f7fbb8acfbaa3bac4fd5abf9ff51e3f2e8884b5498927179b211b2890600090a35050565b60655433906001600160a01b031681146112c65760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b6064820152608401610487565b61064381611da2565b6112d7611505565b6112e08161161d565b60cb80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907fa87b964d321035d2165e484ff4b722dd6eae30606c0b98887d2ed1a34e594bfe90600090a35050565b61133a611505565b6106438161169a565b6000816001600160a01b0316627e3dd26040518163ffffffff1660e01b8152600401602060405180830381865afa158015611382573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113a69190612bbc565b6114015760405162461bcd60e51b815260206004820152602660248201527f5269736b2046756e643a20436f6d7074726f6c6c6572206164647265737320696044820152651b9d985b1a5960d21b6064820152608401610487565b506001600160a01b03908116600090815260ca6020908152604080832061012d549094168352929052205490565b6114398282611dbb565b5050565b611445611505565b606580546001600160a01b0383166001600160a01b031990911681179091556114766033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b179052611500908490612078565b505050565b6033546001600160a01b0316331461114d5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610487565b6001600160a01b0381166115c35760405162461bcd60e51b815260206004820152602560248201527f696e76616c696420616365737320636f6e74726f6c206d616e61676572206164604482015264647265737360d81b6064820152608401610487565b609780546001600160a01b038381166001600160a01b031983168117909355604080519190921680825260208201939093527f66fd58e82f7b31a2a5c30e0888f3093efe4e111b00cd2b0c31fe014601293aa091016111e8565b6001600160a01b038116610643576040516342bcdf7f60e11b815260040160405180910390fd5b600054610100900460ff1661166b5760405162461bcd60e51b815260040161048790612d5e565b61114d61214d565b600054610100900460ff1661063a5760405162461bcd60e51b815260040161048790612d5e565b60fb5481116116f65760405162461bcd60e51b815260206004820152602260248201527f436f6d7074726f6c6c65723a20496e76616c6964206d61784c6f6f70734c696d6044820152611a5d60f21b6064820152608401610487565b60fb80549082905560408051828152602081018490527fc2d09fef144f7c8a86f71ea459f8fc17f675768eb1ae369cbd77fb31d467aafa91016111e8565b6097546040516318c5e8ab60e01b81526000916001600160a01b0316906318c5e8ab906117679033908690600401612dd5565b602060405180830381865afa158015611784573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117a89190612bbc565b90508061143957333083604051634a3fa29360e01b815260040161048793929190612df9565b60fb548111156106435760fb5460405163792bfb1b60e11b8152600481019190915260248101829052604401610487565b6000836000036118775760405162461bcd60e51b815260206004820152603c60248201527f5269736b46756e643a20616d6f756e744f75744d696e206d757374206265206760448201527f726561746572207468616e203020746f20737761702076546f6b656e000000006064820152608401610487565b600080876001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa1580156118b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118dc91906129f9565b61012d546001600160a01b03898116600090815260ca60209081526040808320848716845290915281205493945091169190819003611922576000945050505050611d99565b6000896001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa158015611962573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061198691906129f9565b60405163b62cad6960e01b81526001600160a01b0385811660048301529192509082169063b62cad6990602401600060405180830381600087803b1580156119cd57600080fd5b505af11580156119e1573d6000803e3d6000fd5b50506040805160208101918290526341976e0960e01b9091526001600160a01b03868116602483015260009350909150819084166341976e0960448301602060405180830381865afa158015611a3b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a5f9190612982565b905290506000611a6f828c61217d565b905061013054811015611ad25760405162461bcd60e51b815260206004820152602560248201527f5269736b46756e643a206d696e416d6f756e74546f436f6e766572742076696f6044820152641b185d195960da1b6064820152608401610487565b6001600160a01b038616600090815260c9602052604081208054869290611afa908490612e25565b90915550506001600160a01b03808d16600090815260ca60209081526040808320938a1683529290529081208054869290611b36908490612e25565b90915550506001600160a01b0386811690861614611d8b57856001600160a01b03168a8a6000818110611b6b57611b6b6129e3565b9050602002016020810190611b8091906127a5565b6001600160a01b031614611bfc5760405162461bcd60e51b815260206004820152603860248201527f5269736b46756e643a20737761702070617468206d757374207374617274207760448201527f6974682074686520756e6465726c79696e6720617373657400000000000000006064820152608401610487565b6001600160a01b0385168a8a611c13600182612e25565b818110611c2257611c226129e3565b9050602002016020810190611c3791906127a5565b6001600160a01b031614611cab5760405162461bcd60e51b815260206004820152603560248201527f5269736b46756e643a2066696e616c6c792070617468206d75737420626520636044820152741bdb9d995c9d1a589b194818985cd948185cdcd95d605a1b6064820152608401610487565b61012f546001600160a01b0390811690611cc990881682600061219d565b611cdd6001600160a01b038816828761219d565b6000816001600160a01b03166338ed1739878f8f8f30426040518763ffffffff1660e01b8152600401611d1596959493929190612e3c565b6000604051808303816000875af1158015611d34573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611d5c9190810190612e9e565b905080611d6a60018d612e25565b81518110611d7a57611d7a6129e3565b602002602001015198505050611d8f565b8396505b5094955050505050505b95945050505050565b606580546001600160a01b031916905561064381612289565b611dc48161161d565b816001600160a01b0316627e3dd26040518163ffffffff1660e01b8152600401602060405180830381865afa158015611e01573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e259190612bbc565b611e415760405162461bcd60e51b815260040161048790612d13565b60cb546001600160a01b031680611eb35760405162461bcd60e51b815260206004820152603060248201527f5265736572766548656c706572733a20506f6f6c20526567697374727920616460448201526f191c995cdcc81a5cc81b9bdd081cd95d60821b6064820152608401610487565b611ebd83836122db565b611f245760405162461bcd60e51b815260206004820152603260248201527f5265736572766548656c706572733a2054686520706f6f6c20646f65736e2774604482015271081cdd5c1c1bdc9d081d1a1948185cdcd95d60721b6064820152608401610487565b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa158015611f6b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f8f9190612982565b6001600160a01b038416600090815260c9602052604090205490915080821115612071576001600160a01b038416600090815260c960205260408120805483850392839291611fdf908490612c3e565b90915550506001600160a01b03808716600090815260ca602090815260408083209389168352929052908120805483929061201b908490612c3e565b92505081905550846001600160a01b0316866001600160a01b03167fc39e3e80c0219fde334a8cb5d8468b628482e23388b6e809c90cb00c63c8ce388360405161206791815260200190565b60405180910390a3505b5050505050565b60006120cd826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166123af9092919063ffffffff16565b90508051600014806120ee5750808060200190518101906120ee9190612bbc565b6115005760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610487565b600054610100900460ff166121745760405162461bcd60e51b815260040161048790612d5e565b61114d33611da2565b60008061218a84846123be565b9050612195816123ef565b949350505050565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663095ea7b360e01b1790529151909160009182918716906121fb908590612f29565b6000604051808303816000865af19150503d8060008114612238576040519150601f19603f3d011682016040523d82523d6000602084013e61223d565b606091505b509150915081158061226b575080511580159061226b5750808060200190518101906122699190612bbc565b155b156109c057604051633e3f8f7360e01b815260040160405180910390fd5b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316836001600160a01b0316036123265761231f82612407565b9050611135565b60cb5460405163266e0a7f60e01b81526001600160a01b0385811660048301528481166024830152600092169063266e0a7f90604401602060405180830381865afa158015612379573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061239d91906129f9565b6001600160a01b031614159392505050565b606061219584846000856125d8565b60408051602081019091526000815260405180602001604052806123e68560000151856126b3565b90529392505050565b805160009061113590670de0b6b3a764000090612f45565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b0772d0b6040518163ffffffff1660e01b8152600401600060405180830381865afa158015612468573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526124909190810190612f67565b905060005b81518110156125d1578181815181106124b0576124b06129e3565b60200260200101516001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03161461258457836001600160a01b031682828151811061250c5761250c6129e3565b60200260200101516001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa158015612551573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061257591906129f9565b6001600160a01b0316146125ba565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316846001600160a01b0316145b9250826125d1576125ca81612c56565b9050612495565b5050919050565b6060824710156126395760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610487565b600080866001600160a01b031685876040516126559190612f29565b60006040518083038185875af1925050503d8060008114612692576040519150601f19603f3d011682016040523d82523d6000602084013e612697565b606091505b50915091506126a8878383876126c6565b979650505050505050565b60006126bf8284612ff6565b9392505050565b6060831561273557825160000361272e576001600160a01b0385163b61272e5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610487565b5081612195565b612195838381511561274a5781518083602001fd5b8060405162461bcd60e51b81526004016104879190613015565b6001600160a01b038116811461064357600080fd5b6000806040838503121561278c57600080fd5b823561279781612764565b946020939093013593505050565b6000602082840312156127b757600080fd5b81356126bf81612764565b600080604083850312156127d557600080fd5b82356127e081612764565b915060208301356127f081612764565b809150509250929050565b600080600080600060a0868803121561281357600080fd5b853561281e81612764565b945060208601359350604086013561283581612764565b9250606086013561284581612764565b949793965091946080013592915050565b60008083601f84011261286857600080fd5b50813567ffffffffffffffff81111561288057600080fd5b6020830191508360208260051b850101111561289b57600080fd5b9250929050565b60008060008060008060006080888a0312156128bd57600080fd5b873567ffffffffffffffff808211156128d557600080fd5b6128e18b838c01612856565b909950975060208a01359150808211156128fa57600080fd5b6129068b838c01612856565b909750955060408a013591508082111561291f57600080fd5b5061292c8a828b01612856565b989b979a50959894979596606090950135949350505050565b60006020828403121561295757600080fd5b5035919050565b6020808252600a90820152691c994b595b9d195c995960b21b604082015260600190565b60006020828403121561299457600080fd5b5051919050565b60208082526028908201527f5269736b2046756e643a20496e76616c6964206d696e20616d6f756e7420746f6040820152670818dbdb9d995c9d60c21b606082015260800190565b634e487b7160e01b600052603260045260246000fd5b600060208284031215612a0b57600080fd5b81516126bf81612764565b634e487b7160e01b600052604160045260246000fd5b60405160a0810167ffffffffffffffff81118282101715612a4f57612a4f612a16565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715612a7e57612a7e612a16565b604052919050565b60005b83811015612aa1578181015183820152602001612a89565b83811115612ab0576000848401525b50505050565b8051612ac181612764565b919050565b60006020808385031215612ad957600080fd5b825167ffffffffffffffff80821115612af157600080fd5b9084019060a08287031215612b0557600080fd5b612b0d612a2c565b825182811115612b1c57600080fd5b8301601f81018813612b2d57600080fd5b805183811115612b3f57612b3f612a16565b612b51601f8201601f19168701612a55565b93508084528886828401011115612b6757600080fd5b612b7681878601888501612a86565b5050818152612b86848401612ab6565b84820152612b9660408401612ab6565b604082015260608301516060820152608083015160808201528094505050505092915050565b600060208284031215612bce57600080fd5b815180151581146126bf57600080fd5b6000808335601e19843603018112612bf557600080fd5b83018035915067ffffffffffffffff821115612c1057600080fd5b6020019150600581901b360382131561289b57600080fd5b634e487b7160e01b600052601160045260246000fd5b60008219821115612c5157612c51612c28565b500190565b600060018201612c6857612c68612c28565b5060010190565b8183526000602080850194508260005b85811015612cad578135612c9281612764565b6001600160a01b031687529582019590820190600101612c7f565b509495945050505050565b606081526000612ccc606083018789612c6f565b82810360208401528481526001600160fb1b03851115612ceb57600080fd5b8460051b80876020840137600091016020019081526040929092019290925295945050505050565b6020808252602b908201527f5265736572766548656c706572733a20436f6d7074726f6c6c6572206164647260408201526a195cdcc81a5b9d985b1a5960aa1b606082015260800190565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b60008151808452612dc1816020860160208601612a86565b601f01601f19169290920160200192915050565b6001600160a01b038316815260406020820181905260009061219590830184612da9565b6001600160a01b03848116825283166020820152606060408201819052600090611d9990830184612da9565b600082821015612e3757612e37612c28565b500390565b86815285602082015260a060408201526000612e5c60a083018688612c6f565b6001600160a01b039490941660608301525060800152949350505050565b600067ffffffffffffffff821115612e9457612e94612a16565b5060051b60200190565b60006020808385031215612eb157600080fd5b825167ffffffffffffffff811115612ec857600080fd5b8301601f81018513612ed957600080fd5b8051612eec612ee782612e7a565b612a55565b81815260059190911b82018301908381019087831115612f0b57600080fd5b928401925b828410156126a857835182529284019290840190612f10565b60008251612f3b818460208701612a86565b9190910192915050565b600082612f6257634e487b7160e01b600052601260045260246000fd5b500490565b60006020808385031215612f7a57600080fd5b825167ffffffffffffffff811115612f9157600080fd5b8301601f81018513612fa257600080fd5b8051612fb0612ee782612e7a565b81815260059190911b82018301908381019087831115612fcf57600080fd5b928401925b828410156126a8578351612fe781612764565b82529284019290840190612fd4565b600081600019048311821515161561301057613010612c28565b500290565b6020815260006126bf6020830184612da956fe73776170506f6f6c7341737365747328616464726573735b5d2c75696e743235365b5d2c616464726573735b5d5b5d2c75696e7432353629a2646970667358221220a76e180bdb2a013eae9260adc61d71f42f8a3f14fc1a73b29ba29c31a1106f4964736f6c634300080d0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101da5760003560e01c806377d4937f11610104578063afcff50f116100a2578063e30c397811610071578063e30c39781461040e578063f2fde38b1461041f578063fa7b81a014610432578063fe3da9841461045957600080fd5b8063afcff50f146103cd578063b4a0bdf3146103e0578063be26317e146103f1578063c8ecc0d3146103fa57600080fd5b806380d45a2d116100de57806380d45a2d146103835780638da5cb5b14610396578063a69bd19e146103a7578063aac59a75146103ba57600080fd5b806377d4937f1461035557806379ba5097146103685780637b77cd6a1461037057600080fd5b80633421fc521161017c5780635f30e37b1161014b5780635f30e37b146103145780636fb0527514610327578063715018a61461033a578063746460a91461034257600080fd5b80633421fc5214610293578063362b6795146102ba578063439b5517146102e15780634dd9584a1461030157600080fd5b806324558995116101b85780632455899514610246578063258836fe1461025a5780632a1d05471461026d5780632e6881411461028057600080fd5b80630a9837c5146101df5780630e32cb861461020557806319b1faef1461021a575b600080fd5b6101f26101ed366004612779565b610463565b6040519081526020015b60405180910390f35b6102186102133660046127a5565b610632565b005b61012e5461022e906001600160a01b031681565b6040516001600160a01b0390911681526020016101fc565b61012f5461022e906001600160a01b031681565b6102186102683660046127c2565b610646565b61021861027b3660046127fb565b6107d7565b61021861028e3660046127a5565b6109c8565b61022e7f000000000000000000000000000000000000000000000000000000000000000081565b61022e7f000000000000000000000000000000000000000000000000000000000000000081565b6101f26102ef3660046127a5565b60c96020526000908152604090205481565b61021861030f3660046127a5565b610acd565b6101f26103223660046128a2565b610b31565b6101f26103353660046127c2565b611085565b61021861113b565b610218610350366004612945565b61114f565b6102186103633660046127a5565b6111f4565b610218611258565b61021861037e3660046127a5565b6112cf565b610218610391366004612945565b611332565b6033546001600160a01b031661022e565b6101f26103b53660046127a5565b611343565b6102186103c83660046127c2565b61142f565b60cb5461022e906001600160a01b031681565b6097546001600160a01b031661022e565b6101f260fb5481565b61012d5461022e906001600160a01b031681565b6065546001600160a01b031661022e565b61021861042d3660046127a5565b61143d565b61022e7f000000000000000000000000000000000000000000000000000000000000000081565b6101f26101305481565b6000600260cc54036104905760405162461bcd60e51b81526004016104879061295e565b60405180910390fd5b600260cc5561012e546001600160a01b03163381146105085760405162461bcd60e51b815260206004820152602e60248201527f5269736b2066756e643a204f6e6c792063616c6c61626c652062792053686f7260448201526d1d19985b1b0818dbdb9d1c9858dd60921b6064820152608401610487565b6001600160a01b03808516600090815260ca6020908152604080832061012d549094168352929052205483111561058f5760405162461bcd60e51b815260206004820152602560248201527f5269736b2046756e643a20496e73756666696369656e7420706f6f6c2072657360448201526432b93b329760d91b6064820152608401610487565b6001600160a01b03808516600081815260ca6020908152604080832061012d80548716855290835281842080548a9003905554909416825260c990528290208054869003905590517fc8d0a37ed16dfaa43514df00e18f478b60d5cc7b4bfc687103948b9020f737fd906106069086815260200190565b60405180910390a261012d54610626906001600160a01b031682856114ae565b5050600160cc55919050565b61063a611505565b6106438161155f565b50565b61064e611505565b600260cc54036106705760405162461bcd60e51b81526004016104879061295e565b600260cc5561067e8161161d565b6040516370a0823160e01b815230600482015260009081906001600160a01b038516906370a0823190602401602060405180830381865afa1580156106c7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106eb9190612982565b6001600160a01b038516600090815260c9602052604090205490915081116107615760405162461bcd60e51b815260206004820152602360248201527f5265736572766548656c706572733a205a65726f20737572706c757320746f6b604482015262656e7360e81b6064820152608401610487565b6001600160a01b03848116600081815260c960209081526040918290205491519185038083529550928616927f6d25be279134f4ecaa4770aff0c3d916d9e7c5ef37b65ed95dbdba411f5d54d5910160405180910390a36107cc6001600160a01b03851684846114ae565b5050600160cc555050565b600054610100900460ff16158080156107f75750600054600160ff909116105b806108115750303b158015610811575060005460ff166001145b6108745760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610487565b6000805460ff191660011790558015610897576000805461ff0019166101001790555b6108a08661161d565b6108a98461161d565b600085116108c95760405162461bcd60e51b81526004016104879061299b565b600082116109285760405162461bcd60e51b815260206004820152602660248201527f5269736b2046756e643a204c6f6f7073206c696d69742063616e206e6f74206260448201526565207a65726f60d01b6064820152608401610487565b610930611644565b61093983611673565b61012f80546001600160a01b038089166001600160a01b03199283161790925561013087905561012d80549287169290911691909117905561097a8261169a565b80156109c0576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050565b610a066040518060400160405280602081526020017f736574436f6e7665727469626c65426173654173736574286164647265737329815250611734565b6001600160a01b038116610a7a5760405162461bcd60e51b815260206004820152603560248201527f5269736b2046756e643a206e657720636f6e7665727469626c65206261736520604482015274185cdcd95d081859191c995cdcc81a5b9d985b1a59605a1b6064820152608401610487565b61012d80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f5fa61583da12070720613fefdd68cc6c0e464a71e009742526bd2b2e0ac62cd290600090a35050565b610ad5611505565b610ade8161161d565b61012f80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907fd37b9d138f53ea58d7e50292588239a46efa8f523966febf4066da96defc77fd90600090a35050565b6000600260cc5403610b555760405162461bcd60e51b81526004016104879061295e565b600260cc81905550610b7e60405180606001604052806038815260200161302960389139611734565b42821015610bce5760405162461bcd60e51b815260206004820152601a60248201527f5269736b2066756e643a20646561646c696e65207061737365640000000000006044820152606401610487565b60cb546001600160a01b0316610be38161161d565b878614610c585760405162461bcd60e51b815260206004820152603860248201527f5269736b2066756e643a206d61726b65747320616e6420616d6f756e74734f7560448201527f744d696e2061726520756e657175616c206c656e6774687300000000000000006064820152608401610487565b878414610cc05760405162461bcd60e51b815260206004820152603060248201527f5269736b2066756e643a206d61726b65747320616e642070617468732061726560448201526f20756e657175616c206c656e6774687360801b6064820152608401610487565b600088610ccc816117ce565b60005b818110156110325760008c8c83818110610ceb57610ceb6129e3565b9050602002016020810190610d0091906127a5565b6001600160a01b0316635fe3b5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d3d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d6191906129f9565b604051637aee632d60e01b81526001600160a01b038083166004830152919250600091871690637aee632d90602401600060405180830381865afa158015610dad573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610dd59190810190612ac6565b9050816001600160a01b031681604001516001600160a01b031614610e4c5760405162461bcd60e51b815260206004820152602760248201527f636f6d7074726f6c6c657220646f65736e277420657869737420706f6f6c20726044820152666567697374727960c81b6064820152608401610487565b816001600160a01b0316633d98a1e58f8f86818110610e6d57610e6d6129e3565b9050602002016020810190610e8291906127a5565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa158015610ec6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610eea9190612bbc565b610f2d5760405162461bcd60e51b81526020600482015260146024820152731b585c9ad95d081a5cc81b9bdd081b1a5cdd195960621b6044820152606401610487565b6000610f9c8f8f86818110610f4457610f446129e3565b9050602002016020810190610f5991906127a5565b848f8f88818110610f6c57610f6c6129e3565b905060200201358e8e89818110610f8557610f856129e3565b9050602002810190610f979190612bde565b6117ff565b6001600160a01b03808516600090815260ca6020908152604080832061012d54909416835292905290812080549293508392909190610fdc908490612c3e565b909155505061012d546001600160a01b0316600090815260c960205260408120805483929061100c908490612c3e565b9091555061101c90508187612c3e565b95505050508061102b90612c56565b9050610ccf565b507fb17530966b045b50d4975e7f05048ca00d7335780c24f1c465165a4b94b2d37d8b8b8b8b8660405161106a959493929190612cb8565b60405180910390a150600160cc559998505050505050505050565b60006110908261161d565b826001600160a01b0316627e3dd26040518163ffffffff1660e01b8152600401602060405180830381865afa1580156110cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110f19190612bbc565b61110d5760405162461bcd60e51b815260040161048790612d13565b506001600160a01b03808316600090815260ca60209081526040808320938516835292905220545b92915050565b611143611505565b61114d6000611da2565b565b61118d6040518060400160405280601e81526020017f7365744d696e416d6f756e74546f436f6e766572742875696e74323536290000815250611734565b600081116111ad5760405162461bcd60e51b81526004016104879061299b565b61013080549082905560408051828152602081018490527fada67d0d38fa20c8ae6a5c17cb9d60b0fe7f2d4e4f27ac9ee55e54ac88de9d8d91015b60405180910390a15050565b6111fc611505565b6112058161161d565b61012e80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907fb6e5fcf02f7fbb8acfbaa3bac4fd5abf9ff51e3f2e8884b5498927179b211b2890600090a35050565b60655433906001600160a01b031681146112c65760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b6064820152608401610487565b61064381611da2565b6112d7611505565b6112e08161161d565b60cb80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907fa87b964d321035d2165e484ff4b722dd6eae30606c0b98887d2ed1a34e594bfe90600090a35050565b61133a611505565b6106438161169a565b6000816001600160a01b0316627e3dd26040518163ffffffff1660e01b8152600401602060405180830381865afa158015611382573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113a69190612bbc565b6114015760405162461bcd60e51b815260206004820152602660248201527f5269736b2046756e643a20436f6d7074726f6c6c6572206164647265737320696044820152651b9d985b1a5960d21b6064820152608401610487565b506001600160a01b03908116600090815260ca6020908152604080832061012d549094168352929052205490565b6114398282611dbb565b5050565b611445611505565b606580546001600160a01b0383166001600160a01b031990911681179091556114766033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b179052611500908490612078565b505050565b6033546001600160a01b0316331461114d5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610487565b6001600160a01b0381166115c35760405162461bcd60e51b815260206004820152602560248201527f696e76616c696420616365737320636f6e74726f6c206d616e61676572206164604482015264647265737360d81b6064820152608401610487565b609780546001600160a01b038381166001600160a01b031983168117909355604080519190921680825260208201939093527f66fd58e82f7b31a2a5c30e0888f3093efe4e111b00cd2b0c31fe014601293aa091016111e8565b6001600160a01b038116610643576040516342bcdf7f60e11b815260040160405180910390fd5b600054610100900460ff1661166b5760405162461bcd60e51b815260040161048790612d5e565b61114d61214d565b600054610100900460ff1661063a5760405162461bcd60e51b815260040161048790612d5e565b60fb5481116116f65760405162461bcd60e51b815260206004820152602260248201527f436f6d7074726f6c6c65723a20496e76616c6964206d61784c6f6f70734c696d6044820152611a5d60f21b6064820152608401610487565b60fb80549082905560408051828152602081018490527fc2d09fef144f7c8a86f71ea459f8fc17f675768eb1ae369cbd77fb31d467aafa91016111e8565b6097546040516318c5e8ab60e01b81526000916001600160a01b0316906318c5e8ab906117679033908690600401612dd5565b602060405180830381865afa158015611784573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117a89190612bbc565b90508061143957333083604051634a3fa29360e01b815260040161048793929190612df9565b60fb548111156106435760fb5460405163792bfb1b60e11b8152600481019190915260248101829052604401610487565b6000836000036118775760405162461bcd60e51b815260206004820152603c60248201527f5269736b46756e643a20616d6f756e744f75744d696e206d757374206265206760448201527f726561746572207468616e203020746f20737761702076546f6b656e000000006064820152608401610487565b600080876001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa1580156118b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118dc91906129f9565b61012d546001600160a01b03898116600090815260ca60209081526040808320848716845290915281205493945091169190819003611922576000945050505050611d99565b6000896001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa158015611962573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061198691906129f9565b60405163b62cad6960e01b81526001600160a01b0385811660048301529192509082169063b62cad6990602401600060405180830381600087803b1580156119cd57600080fd5b505af11580156119e1573d6000803e3d6000fd5b50506040805160208101918290526341976e0960e01b9091526001600160a01b03868116602483015260009350909150819084166341976e0960448301602060405180830381865afa158015611a3b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a5f9190612982565b905290506000611a6f828c61217d565b905061013054811015611ad25760405162461bcd60e51b815260206004820152602560248201527f5269736b46756e643a206d696e416d6f756e74546f436f6e766572742076696f6044820152641b185d195960da1b6064820152608401610487565b6001600160a01b038616600090815260c9602052604081208054869290611afa908490612e25565b90915550506001600160a01b03808d16600090815260ca60209081526040808320938a1683529290529081208054869290611b36908490612e25565b90915550506001600160a01b0386811690861614611d8b57856001600160a01b03168a8a6000818110611b6b57611b6b6129e3565b9050602002016020810190611b8091906127a5565b6001600160a01b031614611bfc5760405162461bcd60e51b815260206004820152603860248201527f5269736b46756e643a20737761702070617468206d757374207374617274207760448201527f6974682074686520756e6465726c79696e6720617373657400000000000000006064820152608401610487565b6001600160a01b0385168a8a611c13600182612e25565b818110611c2257611c226129e3565b9050602002016020810190611c3791906127a5565b6001600160a01b031614611cab5760405162461bcd60e51b815260206004820152603560248201527f5269736b46756e643a2066696e616c6c792070617468206d75737420626520636044820152741bdb9d995c9d1a589b194818985cd948185cdcd95d605a1b6064820152608401610487565b61012f546001600160a01b0390811690611cc990881682600061219d565b611cdd6001600160a01b038816828761219d565b6000816001600160a01b03166338ed1739878f8f8f30426040518763ffffffff1660e01b8152600401611d1596959493929190612e3c565b6000604051808303816000875af1158015611d34573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611d5c9190810190612e9e565b905080611d6a60018d612e25565b81518110611d7a57611d7a6129e3565b602002602001015198505050611d8f565b8396505b5094955050505050505b95945050505050565b606580546001600160a01b031916905561064381612289565b611dc48161161d565b816001600160a01b0316627e3dd26040518163ffffffff1660e01b8152600401602060405180830381865afa158015611e01573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e259190612bbc565b611e415760405162461bcd60e51b815260040161048790612d13565b60cb546001600160a01b031680611eb35760405162461bcd60e51b815260206004820152603060248201527f5265736572766548656c706572733a20506f6f6c20526567697374727920616460448201526f191c995cdcc81a5cc81b9bdd081cd95d60821b6064820152608401610487565b611ebd83836122db565b611f245760405162461bcd60e51b815260206004820152603260248201527f5265736572766548656c706572733a2054686520706f6f6c20646f65736e2774604482015271081cdd5c1c1bdc9d081d1a1948185cdcd95d60721b6064820152608401610487565b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa158015611f6b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f8f9190612982565b6001600160a01b038416600090815260c9602052604090205490915080821115612071576001600160a01b038416600090815260c960205260408120805483850392839291611fdf908490612c3e565b90915550506001600160a01b03808716600090815260ca602090815260408083209389168352929052908120805483929061201b908490612c3e565b92505081905550846001600160a01b0316866001600160a01b03167fc39e3e80c0219fde334a8cb5d8468b628482e23388b6e809c90cb00c63c8ce388360405161206791815260200190565b60405180910390a3505b5050505050565b60006120cd826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166123af9092919063ffffffff16565b90508051600014806120ee5750808060200190518101906120ee9190612bbc565b6115005760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610487565b600054610100900460ff166121745760405162461bcd60e51b815260040161048790612d5e565b61114d33611da2565b60008061218a84846123be565b9050612195816123ef565b949350505050565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663095ea7b360e01b1790529151909160009182918716906121fb908590612f29565b6000604051808303816000865af19150503d8060008114612238576040519150601f19603f3d011682016040523d82523d6000602084013e61223d565b606091505b509150915081158061226b575080511580159061226b5750808060200190518101906122699190612bbc565b155b156109c057604051633e3f8f7360e01b815260040160405180910390fd5b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316836001600160a01b0316036123265761231f82612407565b9050611135565b60cb5460405163266e0a7f60e01b81526001600160a01b0385811660048301528481166024830152600092169063266e0a7f90604401602060405180830381865afa158015612379573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061239d91906129f9565b6001600160a01b031614159392505050565b606061219584846000856125d8565b60408051602081019091526000815260405180602001604052806123e68560000151856126b3565b90529392505050565b805160009061113590670de0b6b3a764000090612f45565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b0772d0b6040518163ffffffff1660e01b8152600401600060405180830381865afa158015612468573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526124909190810190612f67565b905060005b81518110156125d1578181815181106124b0576124b06129e3565b60200260200101516001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03161461258457836001600160a01b031682828151811061250c5761250c6129e3565b60200260200101516001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa158015612551573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061257591906129f9565b6001600160a01b0316146125ba565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316846001600160a01b0316145b9250826125d1576125ca81612c56565b9050612495565b5050919050565b6060824710156126395760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610487565b600080866001600160a01b031685876040516126559190612f29565b60006040518083038185875af1925050503d8060008114612692576040519150601f19603f3d011682016040523d82523d6000602084013e612697565b606091505b50915091506126a8878383876126c6565b979650505050505050565b60006126bf8284612ff6565b9392505050565b6060831561273557825160000361272e576001600160a01b0385163b61272e5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610487565b5081612195565b612195838381511561274a5781518083602001fd5b8060405162461bcd60e51b81526004016104879190613015565b6001600160a01b038116811461064357600080fd5b6000806040838503121561278c57600080fd5b823561279781612764565b946020939093013593505050565b6000602082840312156127b757600080fd5b81356126bf81612764565b600080604083850312156127d557600080fd5b82356127e081612764565b915060208301356127f081612764565b809150509250929050565b600080600080600060a0868803121561281357600080fd5b853561281e81612764565b945060208601359350604086013561283581612764565b9250606086013561284581612764565b949793965091946080013592915050565b60008083601f84011261286857600080fd5b50813567ffffffffffffffff81111561288057600080fd5b6020830191508360208260051b850101111561289b57600080fd5b9250929050565b60008060008060008060006080888a0312156128bd57600080fd5b873567ffffffffffffffff808211156128d557600080fd5b6128e18b838c01612856565b909950975060208a01359150808211156128fa57600080fd5b6129068b838c01612856565b909750955060408a013591508082111561291f57600080fd5b5061292c8a828b01612856565b989b979a50959894979596606090950135949350505050565b60006020828403121561295757600080fd5b5035919050565b6020808252600a90820152691c994b595b9d195c995960b21b604082015260600190565b60006020828403121561299457600080fd5b5051919050565b60208082526028908201527f5269736b2046756e643a20496e76616c6964206d696e20616d6f756e7420746f6040820152670818dbdb9d995c9d60c21b606082015260800190565b634e487b7160e01b600052603260045260246000fd5b600060208284031215612a0b57600080fd5b81516126bf81612764565b634e487b7160e01b600052604160045260246000fd5b60405160a0810167ffffffffffffffff81118282101715612a4f57612a4f612a16565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715612a7e57612a7e612a16565b604052919050565b60005b83811015612aa1578181015183820152602001612a89565b83811115612ab0576000848401525b50505050565b8051612ac181612764565b919050565b60006020808385031215612ad957600080fd5b825167ffffffffffffffff80821115612af157600080fd5b9084019060a08287031215612b0557600080fd5b612b0d612a2c565b825182811115612b1c57600080fd5b8301601f81018813612b2d57600080fd5b805183811115612b3f57612b3f612a16565b612b51601f8201601f19168701612a55565b93508084528886828401011115612b6757600080fd5b612b7681878601888501612a86565b5050818152612b86848401612ab6565b84820152612b9660408401612ab6565b604082015260608301516060820152608083015160808201528094505050505092915050565b600060208284031215612bce57600080fd5b815180151581146126bf57600080fd5b6000808335601e19843603018112612bf557600080fd5b83018035915067ffffffffffffffff821115612c1057600080fd5b6020019150600581901b360382131561289b57600080fd5b634e487b7160e01b600052601160045260246000fd5b60008219821115612c5157612c51612c28565b500190565b600060018201612c6857612c68612c28565b5060010190565b8183526000602080850194508260005b85811015612cad578135612c9281612764565b6001600160a01b031687529582019590820190600101612c7f565b509495945050505050565b606081526000612ccc606083018789612c6f565b82810360208401528481526001600160fb1b03851115612ceb57600080fd5b8460051b80876020840137600091016020019081526040929092019290925295945050505050565b6020808252602b908201527f5265736572766548656c706572733a20436f6d7074726f6c6c6572206164647260408201526a195cdcc81a5b9d985b1a5960aa1b606082015260800190565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b60008151808452612dc1816020860160208601612a86565b601f01601f19169290920160200192915050565b6001600160a01b038316815260406020820181905260009061219590830184612da9565b6001600160a01b03848116825283166020820152606060408201819052600090611d9990830184612da9565b600082821015612e3757612e37612c28565b500390565b86815285602082015260a060408201526000612e5c60a083018688612c6f565b6001600160a01b039490941660608301525060800152949350505050565b600067ffffffffffffffff821115612e9457612e94612a16565b5060051b60200190565b60006020808385031215612eb157600080fd5b825167ffffffffffffffff811115612ec857600080fd5b8301601f81018513612ed957600080fd5b8051612eec612ee782612e7a565b612a55565b81815260059190911b82018301908381019087831115612f0b57600080fd5b928401925b828410156126a857835182529284019290840190612f10565b60008251612f3b818460208701612a86565b9190910192915050565b600082612f6257634e487b7160e01b600052601260045260246000fd5b500490565b60006020808385031215612f7a57600080fd5b825167ffffffffffffffff811115612f9157600080fd5b8301601f81018513612fa257600080fd5b8051612fb0612ee782612e7a565b81815260059190911b82018301908381019087831115612fcf57600080fd5b928401925b828410156126a8578351612fe781612764565b82529284019290840190612fd4565b600081600019048311821515161561301057613010612c28565b500290565b6020815260006126bf6020830184612da956fe73776170506f6f6c7341737365747328616464726573735b5d2c75696e743235365b5d2c616464726573735b5d5b5d2c75696e7432353629a2646970667358221220a76e180bdb2a013eae9260adc61d71f42f8a3f14fc1a73b29ba29c31a1106f4964736f6c634300080d0033", + "solcInputHash": "f237ea044837d6f4ff4c08abcdd27558", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"corePoolComptroller_\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"vbnb_\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nativeWrapped_\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"ApproveFailed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"loopsLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requiredLoops\",\"type\":\"uint256\"}],\"name\":\"MaxLoopsLimitExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"calledContract\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"methodSignature\",\"type\":\"string\"}],\"name\":\"Unauthorized\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"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\":\"oldConvertibleBaseAsset\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newConvertibleBaseAsset\",\"type\":\"address\"}],\"name\":\"ConvertibleBaseAssetUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldMaxLoopsLimit\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newmaxLoopsLimit\",\"type\":\"uint256\"}],\"name\":\"MaxLoopsLimitUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldMinAmountToConvert\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newMinAmountToConvert\",\"type\":\"uint256\"}],\"name\":\"MinAmountToConvertUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldAccessControlManager\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newAccessControlManager\",\"type\":\"address\"}],\"name\":\"NewAccessControlManager\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferStarted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"oldPancakeSwapRouter\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newPancakeSwapRouter\",\"type\":\"address\"}],\"name\":\"PancakeSwapRouterUpdated\",\"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\":\"oldShortfallContract\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"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\":\"totalAmount\",\"type\":\"uint256\"}],\"name\":\"SwappedPoolsAssets\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"SweepToken\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"TransferredReserveForAuction\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"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\",\"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\"}],\"name\":\"assetsReserves\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"convertibleBaseAsset\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"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\":\"comptroller\",\"type\":\"address\"}],\"name\":\"getPoolsBaseAssetReserves\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"pancakeSwapRouter_\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmountToConvert_\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"convertibleBaseAsset_\",\"type\":\"address\"},{\"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\":\"minAmountToConvert\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pancakeSwapRouter\",\"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\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"accessControlManager_\",\"type\":\"address\"}],\"name\":\"setAccessControlManager\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_convertibleBaseAsset\",\"type\":\"address\"}],\"name\":\"setConvertibleBaseAsset\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"limit\",\"type\":\"uint256\"}],\"name\":\"setMaxLoopsLimit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minAmountToConvert_\",\"type\":\"uint256\"}],\"name\":\"setMinAmountToConvert\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"pancakeSwapRouter_\",\"type\":\"address\"}],\"name\":\"setPancakeSwapRouter\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"poolRegistry_\",\"type\":\"address\"}],\"name\":\"setPoolRegistry\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"shortfallContractAddress_\",\"type\":\"address\"}],\"name\":\"setShortfallContractAddress\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"shortfall\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"markets\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"amountsOutMin\",\"type\":\"uint256[]\"},{\"internalType\":\"address[][]\",\"name\":\"paths\",\"type\":\"address[][]\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"swapPoolsAssets\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"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\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transferReserveForAuction\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"}],\"name\":\"updateAssetsState\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Venus\",\"details\":\"This contract does not support BNB.\",\"kind\":\"dev\",\"methods\":{\"acceptOwnership()\":{\"details\":\"The new owner accepts the ownership transfer.\"},\"constructor\":{\"custom:oz-upgrades-unsafe-allow\":\"constructor\",\"details\":\"Note that the contract is upgradeable. Use initialize() or reinitializers to set the state variables.\"},\"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.\"}},\"getPoolsBaseAssetReserves(address)\":{\"params\":{\"comptroller\":\"Comptroller address(pool).\"},\"returns\":{\"_0\":\"Base Asset's reserve in risk fund.\"}},\"initialize(address,uint256,address,address,uint256)\":{\"custom:error\":\"ZeroAddressNotAllowed is thrown when PCS router address is zeroZeroAddressNotAllowed is thrown when convertible base asset address is zero\",\"params\":{\"accessControlManager_\":\"Address of the access control contract\",\"convertibleBaseAsset_\":\"Address of the base asset\",\"loopsLimit_\":\"Limit for the loops in the contract to avoid DOS\",\"minAmountToConvert_\":\"Minimum amount assets must be worth to convert into base asset\",\"pancakeSwapRouter_\":\"Address of the PancakeSwap router\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"pendingOwner()\":{\"details\":\"Returns the address of the pending owner.\"},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner.\"},\"setAccessControlManager(address)\":{\"custom:access\":\"Only Governance\",\"custom:event\":\"Emits NewAccessControlManager event\",\"details\":\"Admin function to set address of AccessControlManager\",\"params\":{\"accessControlManager_\":\"The new address of the AccessControlManager\"}},\"setConvertibleBaseAsset(address)\":{\"params\":{\"_convertibleBaseAsset\":\"Address for new convertible base asset.\"}},\"setMaxLoopsLimit(uint256)\":{\"params\":{\"limit\":\"Limit for the max loops can execute at a time\"}},\"setMinAmountToConvert(uint256)\":{\"params\":{\"minAmountToConvert_\":\"Min amount to convert.\"}},\"setPancakeSwapRouter(address)\":{\"custom:error\":\"ZeroAddressNotAllowed is thrown when PCS router address is zero\",\"params\":{\"pancakeSwapRouter_\":\"Address of the PancakeSwap router\"}},\"setPoolRegistry(address)\":{\"custom:error\":\"ZeroAddressNotAllowed is thrown when pool registry address is zero\",\"params\":{\"poolRegistry_\":\"Address of the pool registry\"}},\"setShortfallContractAddress(address)\":{\"custom:error\":\"ZeroAddressNotAllowed is thrown when shortfall contract address is zero\",\"params\":{\"shortfallContractAddress_\":\"Address of the auction contract\"}},\"swapPoolsAssets(address[],uint256[],address[][],uint256)\":{\"custom:error\":\"ZeroAddressNotAllowed is thrown if PoolRegistry contract address is not configured\",\"params\":{\"amountsOutMin\":\"Minimum amount to receive for swap\",\"deadline\":\"Deadline for the swap\",\"markets\":\"Array of vTokens whose assets to swap for base asset\",\"paths\":\"A path consisting of PCS token pairs for each swap\"},\"returns\":{\"_0\":\"Number of swapped tokens\"}},\"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.\"},\"transferReserveForAuction(address,uint256)\":{\"params\":{\"amount\":\"Amount to be transferred to auction contract.\",\"comptroller\":\"Comptroller of the pool.\"},\"returns\":{\"_0\":\"Number reserved tokens.\"}},\"updateAssetsState(address,address)\":{\"params\":{\"asset\":\"Asset address.\",\"comptroller\":\"Comptroller address(pool).\"}}},\"title\":\"RiskFund\",\"version\":1},\"userdoc\":{\"errors\":{\"ApproveFailed()\":[{\"notice\":\"Thrown if a contract is unable to approve a transfer\"}],\"MaxLoopsLimitExceeded(uint256,uint256)\":[{\"notice\":\"Thrown an error on maxLoopsLimit exceeds for any loop\"}],\"Unauthorized(address,address,string)\":[{\"notice\":\"Thrown when the action is prohibited by AccessControlManager\"}],\"ZeroAddressNotAllowed()\":[{\"notice\":\"Thrown if the supplied address is a zero address where it is not allowed\"}]},\"events\":{\"AssetsReservesUpdated(address,address,uint256)\":{\"notice\":\"Event emitted after the update of the assets reserves.\"},\"ConvertibleBaseAssetUpdated(address,address)\":{\"notice\":\"Emitted when convertible base asset is updated\"},\"MaxLoopsLimitUpdated(uint256,uint256)\":{\"notice\":\"Emitted when max loops limit is set\"},\"MinAmountToConvertUpdated(uint256,uint256)\":{\"notice\":\"Emitted when minimum amount to convert is updated\"},\"NewAccessControlManager(address,address)\":{\"notice\":\"Emitted when access control manager contract address is changed\"},\"PancakeSwapRouterUpdated(address,address)\":{\"notice\":\"Emitted when PancakeSwap router contract address is updated\"},\"PoolRegistryUpdated(address,address)\":{\"notice\":\"Emitted when pool registry address is updated\"},\"ShortfallContractUpdated(address,address)\":{\"notice\":\"Emitted when shortfall contract address is updated\"},\"SwappedPoolsAssets(address[],uint256[],uint256)\":{\"notice\":\"Emitted when pools assets are swapped\"},\"SweepToken(address,address,uint256)\":{\"notice\":\"event emitted on sweep token success\"},\"TransferredReserveForAuction(address,uint256)\":{\"notice\":\"Emitted when reserves are transferred for auction\"}},\"kind\":\"user\",\"methods\":{\"accessControlManager()\":{\"notice\":\"Returns the address of the access control manager contract\"},\"getPoolAssetReserve(address,address)\":{\"notice\":\"Get the Amount of the asset in the risk fund for the specific pool.\"},\"getPoolsBaseAssetReserves(address)\":{\"notice\":\"Get the Amount of the Base asset in the risk fund for the specific pool.\"},\"initialize(address,uint256,address,address,uint256)\":{\"notice\":\"Initializes the deployer to owner.\"},\"setAccessControlManager(address)\":{\"notice\":\"Sets the address of AccessControlManager\"},\"setConvertibleBaseAsset(address)\":{\"notice\":\"Sets a new convertible base asset\"},\"setMaxLoopsLimit(uint256)\":{\"notice\":\"Set the limit for the loops can iterate to avoid the DOS\"},\"setMinAmountToConvert(uint256)\":{\"notice\":\"Min amount to convert setter\"},\"setPancakeSwapRouter(address)\":{\"notice\":\"PancakeSwap router address setter\"},\"setPoolRegistry(address)\":{\"notice\":\"Pool registry setter\"},\"setShortfallContractAddress(address)\":{\"notice\":\"Shortfall contract address setter\"},\"swapPoolsAssets(address[],uint256[],address[][],uint256)\":{\"notice\":\"Swap array of pool assets into base asset's tokens of at least a minimum amount\"},\"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\"},\"transferReserveForAuction(address,uint256)\":{\"notice\":\"Transfer tokens for auction.\"},\"updateAssetsState(address,address)\":{\"notice\":\"Update the reserve of the asset for the specific pool after transferring to risk fund.\"}},\"notice\":\"Contract with basic features to track/hold different assets for different Comptrollers.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/RiskFund/RiskFund.sol\":\"RiskFund\"},\"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(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 \\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\":\"0xef1ca0adc3ce1ff540279d424953087771b4a07470caac99777fafd2ceea38a9\",\"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 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(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/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\",\"keccak256\":\"0x7e4d140bd2a5671389ad7a3975b65d05a4f750daf6a61c16139d123d9782b96e\",\"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/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/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\\\";\\nimport { PoolRegistry } from \\\"../Pool/PoolRegistry.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 PoolRegistry(poolRegistry).getVTokenForAsset(comptroller, asset) != address(0);\\n }\\n}\\n\",\"keccak256\":\"0xf30155bbbb7251eb8445c7d282427ed0040d015fe34efcb5ec61bc92a289b0cc\",\"license\":\"BSD-3-Clause\"},\"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\",\"keccak256\":\"0x918526b067c834935f5dd0788139e1a73c64cbf6f8b7d6fd43242eaa93aa7f37\",\"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(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 \\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 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 \\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(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\",\"keccak256\":\"0xcda9eb71f6ceb8a4c3bfbc1c42d72e2f0523d30f6d3252fbd90819e953640fe5\",\"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(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\":\"0x2947e95eb97a3a45f90ec36d4fd5a4cbb9409319f6ad000e950550055a3f2324\",\"license\":\"BSD-3-Clause\"},\"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\",\"keccak256\":\"0x9bbc31c80a4c537ddfd06cbd03a412ba64842a708381fbc4bf2e33ef56c92b4d\",\"license\":\"MIT\"},\"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": "0x60e06040523480156200001157600080fd5b50604051620032b8380380620032b883398101604081905262000034916200018c565b828282620000428362000083565b6200004d8262000083565b620000588162000083565b6001600160a01b0392831660805290821660a0521660c0526200007a620000ae565b505050620001d6565b6001600160a01b038116620000ab576040516342bcdf7f60e11b815260040160405180910390fd5b50565b600054610100900460ff16156200011b5760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b60005460ff908116146200016d576000805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b80516001600160a01b03811681146200018757600080fd5b919050565b600080600060608486031215620001a257600080fd5b620001ad846200016f565b9250620001bd602085016200016f565b9150620001cd604085016200016f565b90509250925092565b60805160a05160c05161309662000222600039600081816102bf015261258601526000818161029801526124c3015260008181610437015281816122df015261240c01526130966000f3fe608060405234801561001057600080fd5b50600436106101da5760003560e01c806377d4937f11610104578063afcff50f116100a2578063e30c397811610071578063e30c39781461040e578063f2fde38b1461041f578063fa7b81a014610432578063fe3da9841461045957600080fd5b8063afcff50f146103cd578063b4a0bdf3146103e0578063be26317e146103f1578063c8ecc0d3146103fa57600080fd5b806380d45a2d116100de57806380d45a2d146103835780638da5cb5b14610396578063a69bd19e146103a7578063aac59a75146103ba57600080fd5b806377d4937f1461035557806379ba5097146103685780637b77cd6a1461037057600080fd5b80633421fc521161017c5780635f30e37b1161014b5780635f30e37b146103145780636fb0527514610327578063715018a61461033a578063746460a91461034257600080fd5b80633421fc5214610293578063362b6795146102ba578063439b5517146102e15780634dd9584a1461030157600080fd5b806324558995116101b85780632455899514610246578063258836fe1461025a5780632a1d05471461026d5780632e6881411461028057600080fd5b80630a9837c5146101df5780630e32cb861461020557806319b1faef1461021a575b600080fd5b6101f26101ed366004612779565b610463565b6040519081526020015b60405180910390f35b6102186102133660046127a5565b610632565b005b61012e5461022e906001600160a01b031681565b6040516001600160a01b0390911681526020016101fc565b61012f5461022e906001600160a01b031681565b6102186102683660046127c2565b610646565b61021861027b3660046127fb565b6107d7565b61021861028e3660046127a5565b6109c8565b61022e7f000000000000000000000000000000000000000000000000000000000000000081565b61022e7f000000000000000000000000000000000000000000000000000000000000000081565b6101f26102ef3660046127a5565b60c96020526000908152604090205481565b61021861030f3660046127a5565b610acd565b6101f26103223660046128a2565b610b31565b6101f26103353660046127c2565b611085565b61021861113b565b610218610350366004612945565b61114f565b6102186103633660046127a5565b6111f4565b610218611258565b61021861037e3660046127a5565b6112cf565b610218610391366004612945565b611332565b6033546001600160a01b031661022e565b6101f26103b53660046127a5565b611343565b6102186103c83660046127c2565b61142f565b60cb5461022e906001600160a01b031681565b6097546001600160a01b031661022e565b6101f260fb5481565b61012d5461022e906001600160a01b031681565b6065546001600160a01b031661022e565b61021861042d3660046127a5565b61143d565b61022e7f000000000000000000000000000000000000000000000000000000000000000081565b6101f26101305481565b6000600260cc54036104905760405162461bcd60e51b81526004016104879061295e565b60405180910390fd5b600260cc5561012e546001600160a01b03163381146105085760405162461bcd60e51b815260206004820152602e60248201527f5269736b2066756e643a204f6e6c792063616c6c61626c652062792053686f7260448201526d1d19985b1b0818dbdb9d1c9858dd60921b6064820152608401610487565b6001600160a01b03808516600090815260ca6020908152604080832061012d549094168352929052205483111561058f5760405162461bcd60e51b815260206004820152602560248201527f5269736b2046756e643a20496e73756666696369656e7420706f6f6c2072657360448201526432b93b329760d91b6064820152608401610487565b6001600160a01b03808516600081815260ca6020908152604080832061012d80548716855290835281842080548a9003905554909416825260c990528290208054869003905590517fc8d0a37ed16dfaa43514df00e18f478b60d5cc7b4bfc687103948b9020f737fd906106069086815260200190565b60405180910390a261012d54610626906001600160a01b031682856114ae565b5050600160cc55919050565b61063a611505565b6106438161155f565b50565b61064e611505565b600260cc54036106705760405162461bcd60e51b81526004016104879061295e565b600260cc5561067e8161161d565b6040516370a0823160e01b815230600482015260009081906001600160a01b038516906370a0823190602401602060405180830381865afa1580156106c7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106eb9190612982565b6001600160a01b038516600090815260c9602052604090205490915081116107615760405162461bcd60e51b815260206004820152602360248201527f5265736572766548656c706572733a205a65726f20737572706c757320746f6b604482015262656e7360e81b6064820152608401610487565b6001600160a01b03848116600081815260c960209081526040918290205491519185038083529550928616927f6d25be279134f4ecaa4770aff0c3d916d9e7c5ef37b65ed95dbdba411f5d54d5910160405180910390a36107cc6001600160a01b03851684846114ae565b5050600160cc555050565b600054610100900460ff16158080156107f75750600054600160ff909116105b806108115750303b158015610811575060005460ff166001145b6108745760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610487565b6000805460ff191660011790558015610897576000805461ff0019166101001790555b6108a08661161d565b6108a98461161d565b600085116108c95760405162461bcd60e51b81526004016104879061299b565b600082116109285760405162461bcd60e51b815260206004820152602660248201527f5269736b2046756e643a204c6f6f7073206c696d69742063616e206e6f74206260448201526565207a65726f60d01b6064820152608401610487565b610930611644565b61093983611673565b61012f80546001600160a01b038089166001600160a01b03199283161790925561013087905561012d80549287169290911691909117905561097a8261169a565b80156109c0576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050565b610a066040518060400160405280602081526020017f736574436f6e7665727469626c65426173654173736574286164647265737329815250611734565b6001600160a01b038116610a7a5760405162461bcd60e51b815260206004820152603560248201527f5269736b2046756e643a206e657720636f6e7665727469626c65206261736520604482015274185cdcd95d081859191c995cdcc81a5b9d985b1a59605a1b6064820152608401610487565b61012d80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f5fa61583da12070720613fefdd68cc6c0e464a71e009742526bd2b2e0ac62cd290600090a35050565b610ad5611505565b610ade8161161d565b61012f80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907fd37b9d138f53ea58d7e50292588239a46efa8f523966febf4066da96defc77fd90600090a35050565b6000600260cc5403610b555760405162461bcd60e51b81526004016104879061295e565b600260cc81905550610b7e60405180606001604052806038815260200161302960389139611734565b42821015610bce5760405162461bcd60e51b815260206004820152601a60248201527f5269736b2066756e643a20646561646c696e65207061737365640000000000006044820152606401610487565b60cb546001600160a01b0316610be38161161d565b878614610c585760405162461bcd60e51b815260206004820152603860248201527f5269736b2066756e643a206d61726b65747320616e6420616d6f756e74734f7560448201527f744d696e2061726520756e657175616c206c656e6774687300000000000000006064820152608401610487565b878414610cc05760405162461bcd60e51b815260206004820152603060248201527f5269736b2066756e643a206d61726b65747320616e642070617468732061726560448201526f20756e657175616c206c656e6774687360801b6064820152608401610487565b600088610ccc816117ce565b60005b818110156110325760008c8c83818110610ceb57610ceb6129e3565b9050602002016020810190610d0091906127a5565b6001600160a01b0316635fe3b5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d3d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d6191906129f9565b604051637aee632d60e01b81526001600160a01b038083166004830152919250600091871690637aee632d90602401600060405180830381865afa158015610dad573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610dd59190810190612ac6565b9050816001600160a01b031681604001516001600160a01b031614610e4c5760405162461bcd60e51b815260206004820152602760248201527f636f6d7074726f6c6c657220646f65736e277420657869737420706f6f6c20726044820152666567697374727960c81b6064820152608401610487565b816001600160a01b0316633d98a1e58f8f86818110610e6d57610e6d6129e3565b9050602002016020810190610e8291906127a5565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa158015610ec6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610eea9190612bbc565b610f2d5760405162461bcd60e51b81526020600482015260146024820152731b585c9ad95d081a5cc81b9bdd081b1a5cdd195960621b6044820152606401610487565b6000610f9c8f8f86818110610f4457610f446129e3565b9050602002016020810190610f5991906127a5565b848f8f88818110610f6c57610f6c6129e3565b905060200201358e8e89818110610f8557610f856129e3565b9050602002810190610f979190612bde565b6117ff565b6001600160a01b03808516600090815260ca6020908152604080832061012d54909416835292905290812080549293508392909190610fdc908490612c3e565b909155505061012d546001600160a01b0316600090815260c960205260408120805483929061100c908490612c3e565b9091555061101c90508187612c3e565b95505050508061102b90612c56565b9050610ccf565b507fb17530966b045b50d4975e7f05048ca00d7335780c24f1c465165a4b94b2d37d8b8b8b8b8660405161106a959493929190612cb8565b60405180910390a150600160cc559998505050505050505050565b60006110908261161d565b826001600160a01b0316627e3dd26040518163ffffffff1660e01b8152600401602060405180830381865afa1580156110cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110f19190612bbc565b61110d5760405162461bcd60e51b815260040161048790612d13565b506001600160a01b03808316600090815260ca60209081526040808320938516835292905220545b92915050565b611143611505565b61114d6000611da2565b565b61118d6040518060400160405280601e81526020017f7365744d696e416d6f756e74546f436f6e766572742875696e74323536290000815250611734565b600081116111ad5760405162461bcd60e51b81526004016104879061299b565b61013080549082905560408051828152602081018490527fada67d0d38fa20c8ae6a5c17cb9d60b0fe7f2d4e4f27ac9ee55e54ac88de9d8d91015b60405180910390a15050565b6111fc611505565b6112058161161d565b61012e80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907fb6e5fcf02f7fbb8acfbaa3bac4fd5abf9ff51e3f2e8884b5498927179b211b2890600090a35050565b60655433906001600160a01b031681146112c65760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b6064820152608401610487565b61064381611da2565b6112d7611505565b6112e08161161d565b60cb80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907fa87b964d321035d2165e484ff4b722dd6eae30606c0b98887d2ed1a34e594bfe90600090a35050565b61133a611505565b6106438161169a565b6000816001600160a01b0316627e3dd26040518163ffffffff1660e01b8152600401602060405180830381865afa158015611382573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113a69190612bbc565b6114015760405162461bcd60e51b815260206004820152602660248201527f5269736b2046756e643a20436f6d7074726f6c6c6572206164647265737320696044820152651b9d985b1a5960d21b6064820152608401610487565b506001600160a01b03908116600090815260ca6020908152604080832061012d549094168352929052205490565b6114398282611dbb565b5050565b611445611505565b606580546001600160a01b0383166001600160a01b031990911681179091556114766033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b179052611500908490612078565b505050565b6033546001600160a01b0316331461114d5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610487565b6001600160a01b0381166115c35760405162461bcd60e51b815260206004820152602560248201527f696e76616c696420616365737320636f6e74726f6c206d616e61676572206164604482015264647265737360d81b6064820152608401610487565b609780546001600160a01b038381166001600160a01b031983168117909355604080519190921680825260208201939093527f66fd58e82f7b31a2a5c30e0888f3093efe4e111b00cd2b0c31fe014601293aa091016111e8565b6001600160a01b038116610643576040516342bcdf7f60e11b815260040160405180910390fd5b600054610100900460ff1661166b5760405162461bcd60e51b815260040161048790612d5e565b61114d61214d565b600054610100900460ff1661063a5760405162461bcd60e51b815260040161048790612d5e565b60fb5481116116f65760405162461bcd60e51b815260206004820152602260248201527f436f6d7074726f6c6c65723a20496e76616c6964206d61784c6f6f70734c696d6044820152611a5d60f21b6064820152608401610487565b60fb80549082905560408051828152602081018490527fc2d09fef144f7c8a86f71ea459f8fc17f675768eb1ae369cbd77fb31d467aafa91016111e8565b6097546040516318c5e8ab60e01b81526000916001600160a01b0316906318c5e8ab906117679033908690600401612dd5565b602060405180830381865afa158015611784573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117a89190612bbc565b90508061143957333083604051634a3fa29360e01b815260040161048793929190612df9565b60fb548111156106435760fb5460405163792bfb1b60e11b8152600481019190915260248101829052604401610487565b6000836000036118775760405162461bcd60e51b815260206004820152603c60248201527f5269736b46756e643a20616d6f756e744f75744d696e206d757374206265206760448201527f726561746572207468616e203020746f20737761702076546f6b656e000000006064820152608401610487565b600080876001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa1580156118b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118dc91906129f9565b61012d546001600160a01b03898116600090815260ca60209081526040808320848716845290915281205493945091169190819003611922576000945050505050611d99565b6000896001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa158015611962573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061198691906129f9565b60405163b62cad6960e01b81526001600160a01b0385811660048301529192509082169063b62cad6990602401600060405180830381600087803b1580156119cd57600080fd5b505af11580156119e1573d6000803e3d6000fd5b50506040805160208101918290526341976e0960e01b9091526001600160a01b03868116602483015260009350909150819084166341976e0960448301602060405180830381865afa158015611a3b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a5f9190612982565b905290506000611a6f828c61217d565b905061013054811015611ad25760405162461bcd60e51b815260206004820152602560248201527f5269736b46756e643a206d696e416d6f756e74546f436f6e766572742076696f6044820152641b185d195960da1b6064820152608401610487565b6001600160a01b038616600090815260c9602052604081208054869290611afa908490612e25565b90915550506001600160a01b03808d16600090815260ca60209081526040808320938a1683529290529081208054869290611b36908490612e25565b90915550506001600160a01b0386811690861614611d8b57856001600160a01b03168a8a6000818110611b6b57611b6b6129e3565b9050602002016020810190611b8091906127a5565b6001600160a01b031614611bfc5760405162461bcd60e51b815260206004820152603860248201527f5269736b46756e643a20737761702070617468206d757374207374617274207760448201527f6974682074686520756e6465726c79696e6720617373657400000000000000006064820152608401610487565b6001600160a01b0385168a8a611c13600182612e25565b818110611c2257611c226129e3565b9050602002016020810190611c3791906127a5565b6001600160a01b031614611cab5760405162461bcd60e51b815260206004820152603560248201527f5269736b46756e643a2066696e616c6c792070617468206d75737420626520636044820152741bdb9d995c9d1a589b194818985cd948185cdcd95d605a1b6064820152608401610487565b61012f546001600160a01b0390811690611cc990881682600061219d565b611cdd6001600160a01b038816828761219d565b6000816001600160a01b03166338ed1739878f8f8f30426040518763ffffffff1660e01b8152600401611d1596959493929190612e3c565b6000604051808303816000875af1158015611d34573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611d5c9190810190612e9e565b905080611d6a60018d612e25565b81518110611d7a57611d7a6129e3565b602002602001015198505050611d8f565b8396505b5094955050505050505b95945050505050565b606580546001600160a01b031916905561064381612289565b611dc48161161d565b816001600160a01b0316627e3dd26040518163ffffffff1660e01b8152600401602060405180830381865afa158015611e01573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e259190612bbc565b611e415760405162461bcd60e51b815260040161048790612d13565b60cb546001600160a01b031680611eb35760405162461bcd60e51b815260206004820152603060248201527f5265736572766548656c706572733a20506f6f6c20526567697374727920616460448201526f191c995cdcc81a5cc81b9bdd081cd95d60821b6064820152608401610487565b611ebd83836122db565b611f245760405162461bcd60e51b815260206004820152603260248201527f5265736572766548656c706572733a2054686520706f6f6c20646f65736e2774604482015271081cdd5c1c1bdc9d081d1a1948185cdcd95d60721b6064820152608401610487565b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa158015611f6b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f8f9190612982565b6001600160a01b038416600090815260c9602052604090205490915080821115612071576001600160a01b038416600090815260c960205260408120805483850392839291611fdf908490612c3e565b90915550506001600160a01b03808716600090815260ca602090815260408083209389168352929052908120805483929061201b908490612c3e565b92505081905550846001600160a01b0316866001600160a01b03167fc39e3e80c0219fde334a8cb5d8468b628482e23388b6e809c90cb00c63c8ce388360405161206791815260200190565b60405180910390a3505b5050505050565b60006120cd826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166123af9092919063ffffffff16565b90508051600014806120ee5750808060200190518101906120ee9190612bbc565b6115005760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610487565b600054610100900460ff166121745760405162461bcd60e51b815260040161048790612d5e565b61114d33611da2565b60008061218a84846123be565b9050612195816123ef565b949350505050565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663095ea7b360e01b1790529151909160009182918716906121fb908590612f29565b6000604051808303816000865af19150503d8060008114612238576040519150601f19603f3d011682016040523d82523d6000602084013e61223d565b606091505b509150915081158061226b575080511580159061226b5750808060200190518101906122699190612bbc565b155b156109c057604051633e3f8f7360e01b815260040160405180910390fd5b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316836001600160a01b0316036123265761231f82612407565b9050611135565b60cb5460405163266e0a7f60e01b81526001600160a01b0385811660048301528481166024830152600092169063266e0a7f90604401602060405180830381865afa158015612379573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061239d91906129f9565b6001600160a01b031614159392505050565b606061219584846000856125d8565b60408051602081019091526000815260405180602001604052806123e68560000151856126b3565b90529392505050565b805160009061113590670de0b6b3a764000090612f45565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b0772d0b6040518163ffffffff1660e01b8152600401600060405180830381865afa158015612468573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526124909190810190612f67565b905060005b81518110156125d1578181815181106124b0576124b06129e3565b60200260200101516001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03161461258457836001600160a01b031682828151811061250c5761250c6129e3565b60200260200101516001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa158015612551573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061257591906129f9565b6001600160a01b0316146125ba565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316846001600160a01b0316145b9250826125d1576125ca81612c56565b9050612495565b5050919050565b6060824710156126395760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610487565b600080866001600160a01b031685876040516126559190612f29565b60006040518083038185875af1925050503d8060008114612692576040519150601f19603f3d011682016040523d82523d6000602084013e612697565b606091505b50915091506126a8878383876126c6565b979650505050505050565b60006126bf8284612ff6565b9392505050565b6060831561273557825160000361272e576001600160a01b0385163b61272e5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610487565b5081612195565b612195838381511561274a5781518083602001fd5b8060405162461bcd60e51b81526004016104879190613015565b6001600160a01b038116811461064357600080fd5b6000806040838503121561278c57600080fd5b823561279781612764565b946020939093013593505050565b6000602082840312156127b757600080fd5b81356126bf81612764565b600080604083850312156127d557600080fd5b82356127e081612764565b915060208301356127f081612764565b809150509250929050565b600080600080600060a0868803121561281357600080fd5b853561281e81612764565b945060208601359350604086013561283581612764565b9250606086013561284581612764565b949793965091946080013592915050565b60008083601f84011261286857600080fd5b50813567ffffffffffffffff81111561288057600080fd5b6020830191508360208260051b850101111561289b57600080fd5b9250929050565b60008060008060008060006080888a0312156128bd57600080fd5b873567ffffffffffffffff808211156128d557600080fd5b6128e18b838c01612856565b909950975060208a01359150808211156128fa57600080fd5b6129068b838c01612856565b909750955060408a013591508082111561291f57600080fd5b5061292c8a828b01612856565b989b979a50959894979596606090950135949350505050565b60006020828403121561295757600080fd5b5035919050565b6020808252600a90820152691c994b595b9d195c995960b21b604082015260600190565b60006020828403121561299457600080fd5b5051919050565b60208082526028908201527f5269736b2046756e643a20496e76616c6964206d696e20616d6f756e7420746f6040820152670818dbdb9d995c9d60c21b606082015260800190565b634e487b7160e01b600052603260045260246000fd5b600060208284031215612a0b57600080fd5b81516126bf81612764565b634e487b7160e01b600052604160045260246000fd5b60405160a0810167ffffffffffffffff81118282101715612a4f57612a4f612a16565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715612a7e57612a7e612a16565b604052919050565b60005b83811015612aa1578181015183820152602001612a89565b83811115612ab0576000848401525b50505050565b8051612ac181612764565b919050565b60006020808385031215612ad957600080fd5b825167ffffffffffffffff80821115612af157600080fd5b9084019060a08287031215612b0557600080fd5b612b0d612a2c565b825182811115612b1c57600080fd5b8301601f81018813612b2d57600080fd5b805183811115612b3f57612b3f612a16565b612b51601f8201601f19168701612a55565b93508084528886828401011115612b6757600080fd5b612b7681878601888501612a86565b5050818152612b86848401612ab6565b84820152612b9660408401612ab6565b604082015260608301516060820152608083015160808201528094505050505092915050565b600060208284031215612bce57600080fd5b815180151581146126bf57600080fd5b6000808335601e19843603018112612bf557600080fd5b83018035915067ffffffffffffffff821115612c1057600080fd5b6020019150600581901b360382131561289b57600080fd5b634e487b7160e01b600052601160045260246000fd5b60008219821115612c5157612c51612c28565b500190565b600060018201612c6857612c68612c28565b5060010190565b8183526000602080850194508260005b85811015612cad578135612c9281612764565b6001600160a01b031687529582019590820190600101612c7f565b509495945050505050565b606081526000612ccc606083018789612c6f565b82810360208401528481526001600160fb1b03851115612ceb57600080fd5b8460051b80876020840137600091016020019081526040929092019290925295945050505050565b6020808252602b908201527f5265736572766548656c706572733a20436f6d7074726f6c6c6572206164647260408201526a195cdcc81a5b9d985b1a5960aa1b606082015260800190565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b60008151808452612dc1816020860160208601612a86565b601f01601f19169290920160200192915050565b6001600160a01b038316815260406020820181905260009061219590830184612da9565b6001600160a01b03848116825283166020820152606060408201819052600090611d9990830184612da9565b600082821015612e3757612e37612c28565b500390565b86815285602082015260a060408201526000612e5c60a083018688612c6f565b6001600160a01b039490941660608301525060800152949350505050565b600067ffffffffffffffff821115612e9457612e94612a16565b5060051b60200190565b60006020808385031215612eb157600080fd5b825167ffffffffffffffff811115612ec857600080fd5b8301601f81018513612ed957600080fd5b8051612eec612ee782612e7a565b612a55565b81815260059190911b82018301908381019087831115612f0b57600080fd5b928401925b828410156126a857835182529284019290840190612f10565b60008251612f3b818460208701612a86565b9190910192915050565b600082612f6257634e487b7160e01b600052601260045260246000fd5b500490565b60006020808385031215612f7a57600080fd5b825167ffffffffffffffff811115612f9157600080fd5b8301601f81018513612fa257600080fd5b8051612fb0612ee782612e7a565b81815260059190911b82018301908381019087831115612fcf57600080fd5b928401925b828410156126a8578351612fe781612764565b82529284019290840190612fd4565b600081600019048311821515161561301057613010612c28565b500290565b6020815260006126bf6020830184612da956fe73776170506f6f6c7341737365747328616464726573735b5d2c75696e743235365b5d2c616464726573735b5d5b5d2c75696e7432353629a2646970667358221220c967afe4ee07c007702bfe8b40ad090042c372456a0a152775ad412949fc6bc564736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101da5760003560e01c806377d4937f11610104578063afcff50f116100a2578063e30c397811610071578063e30c39781461040e578063f2fde38b1461041f578063fa7b81a014610432578063fe3da9841461045957600080fd5b8063afcff50f146103cd578063b4a0bdf3146103e0578063be26317e146103f1578063c8ecc0d3146103fa57600080fd5b806380d45a2d116100de57806380d45a2d146103835780638da5cb5b14610396578063a69bd19e146103a7578063aac59a75146103ba57600080fd5b806377d4937f1461035557806379ba5097146103685780637b77cd6a1461037057600080fd5b80633421fc521161017c5780635f30e37b1161014b5780635f30e37b146103145780636fb0527514610327578063715018a61461033a578063746460a91461034257600080fd5b80633421fc5214610293578063362b6795146102ba578063439b5517146102e15780634dd9584a1461030157600080fd5b806324558995116101b85780632455899514610246578063258836fe1461025a5780632a1d05471461026d5780632e6881411461028057600080fd5b80630a9837c5146101df5780630e32cb861461020557806319b1faef1461021a575b600080fd5b6101f26101ed366004612779565b610463565b6040519081526020015b60405180910390f35b6102186102133660046127a5565b610632565b005b61012e5461022e906001600160a01b031681565b6040516001600160a01b0390911681526020016101fc565b61012f5461022e906001600160a01b031681565b6102186102683660046127c2565b610646565b61021861027b3660046127fb565b6107d7565b61021861028e3660046127a5565b6109c8565b61022e7f000000000000000000000000000000000000000000000000000000000000000081565b61022e7f000000000000000000000000000000000000000000000000000000000000000081565b6101f26102ef3660046127a5565b60c96020526000908152604090205481565b61021861030f3660046127a5565b610acd565b6101f26103223660046128a2565b610b31565b6101f26103353660046127c2565b611085565b61021861113b565b610218610350366004612945565b61114f565b6102186103633660046127a5565b6111f4565b610218611258565b61021861037e3660046127a5565b6112cf565b610218610391366004612945565b611332565b6033546001600160a01b031661022e565b6101f26103b53660046127a5565b611343565b6102186103c83660046127c2565b61142f565b60cb5461022e906001600160a01b031681565b6097546001600160a01b031661022e565b6101f260fb5481565b61012d5461022e906001600160a01b031681565b6065546001600160a01b031661022e565b61021861042d3660046127a5565b61143d565b61022e7f000000000000000000000000000000000000000000000000000000000000000081565b6101f26101305481565b6000600260cc54036104905760405162461bcd60e51b81526004016104879061295e565b60405180910390fd5b600260cc5561012e546001600160a01b03163381146105085760405162461bcd60e51b815260206004820152602e60248201527f5269736b2066756e643a204f6e6c792063616c6c61626c652062792053686f7260448201526d1d19985b1b0818dbdb9d1c9858dd60921b6064820152608401610487565b6001600160a01b03808516600090815260ca6020908152604080832061012d549094168352929052205483111561058f5760405162461bcd60e51b815260206004820152602560248201527f5269736b2046756e643a20496e73756666696369656e7420706f6f6c2072657360448201526432b93b329760d91b6064820152608401610487565b6001600160a01b03808516600081815260ca6020908152604080832061012d80548716855290835281842080548a9003905554909416825260c990528290208054869003905590517fc8d0a37ed16dfaa43514df00e18f478b60d5cc7b4bfc687103948b9020f737fd906106069086815260200190565b60405180910390a261012d54610626906001600160a01b031682856114ae565b5050600160cc55919050565b61063a611505565b6106438161155f565b50565b61064e611505565b600260cc54036106705760405162461bcd60e51b81526004016104879061295e565b600260cc5561067e8161161d565b6040516370a0823160e01b815230600482015260009081906001600160a01b038516906370a0823190602401602060405180830381865afa1580156106c7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106eb9190612982565b6001600160a01b038516600090815260c9602052604090205490915081116107615760405162461bcd60e51b815260206004820152602360248201527f5265736572766548656c706572733a205a65726f20737572706c757320746f6b604482015262656e7360e81b6064820152608401610487565b6001600160a01b03848116600081815260c960209081526040918290205491519185038083529550928616927f6d25be279134f4ecaa4770aff0c3d916d9e7c5ef37b65ed95dbdba411f5d54d5910160405180910390a36107cc6001600160a01b03851684846114ae565b5050600160cc555050565b600054610100900460ff16158080156107f75750600054600160ff909116105b806108115750303b158015610811575060005460ff166001145b6108745760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610487565b6000805460ff191660011790558015610897576000805461ff0019166101001790555b6108a08661161d565b6108a98461161d565b600085116108c95760405162461bcd60e51b81526004016104879061299b565b600082116109285760405162461bcd60e51b815260206004820152602660248201527f5269736b2046756e643a204c6f6f7073206c696d69742063616e206e6f74206260448201526565207a65726f60d01b6064820152608401610487565b610930611644565b61093983611673565b61012f80546001600160a01b038089166001600160a01b03199283161790925561013087905561012d80549287169290911691909117905561097a8261169a565b80156109c0576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050565b610a066040518060400160405280602081526020017f736574436f6e7665727469626c65426173654173736574286164647265737329815250611734565b6001600160a01b038116610a7a5760405162461bcd60e51b815260206004820152603560248201527f5269736b2046756e643a206e657720636f6e7665727469626c65206261736520604482015274185cdcd95d081859191c995cdcc81a5b9d985b1a59605a1b6064820152608401610487565b61012d80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f5fa61583da12070720613fefdd68cc6c0e464a71e009742526bd2b2e0ac62cd290600090a35050565b610ad5611505565b610ade8161161d565b61012f80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907fd37b9d138f53ea58d7e50292588239a46efa8f523966febf4066da96defc77fd90600090a35050565b6000600260cc5403610b555760405162461bcd60e51b81526004016104879061295e565b600260cc81905550610b7e60405180606001604052806038815260200161302960389139611734565b42821015610bce5760405162461bcd60e51b815260206004820152601a60248201527f5269736b2066756e643a20646561646c696e65207061737365640000000000006044820152606401610487565b60cb546001600160a01b0316610be38161161d565b878614610c585760405162461bcd60e51b815260206004820152603860248201527f5269736b2066756e643a206d61726b65747320616e6420616d6f756e74734f7560448201527f744d696e2061726520756e657175616c206c656e6774687300000000000000006064820152608401610487565b878414610cc05760405162461bcd60e51b815260206004820152603060248201527f5269736b2066756e643a206d61726b65747320616e642070617468732061726560448201526f20756e657175616c206c656e6774687360801b6064820152608401610487565b600088610ccc816117ce565b60005b818110156110325760008c8c83818110610ceb57610ceb6129e3565b9050602002016020810190610d0091906127a5565b6001600160a01b0316635fe3b5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d3d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d6191906129f9565b604051637aee632d60e01b81526001600160a01b038083166004830152919250600091871690637aee632d90602401600060405180830381865afa158015610dad573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610dd59190810190612ac6565b9050816001600160a01b031681604001516001600160a01b031614610e4c5760405162461bcd60e51b815260206004820152602760248201527f636f6d7074726f6c6c657220646f65736e277420657869737420706f6f6c20726044820152666567697374727960c81b6064820152608401610487565b816001600160a01b0316633d98a1e58f8f86818110610e6d57610e6d6129e3565b9050602002016020810190610e8291906127a5565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa158015610ec6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610eea9190612bbc565b610f2d5760405162461bcd60e51b81526020600482015260146024820152731b585c9ad95d081a5cc81b9bdd081b1a5cdd195960621b6044820152606401610487565b6000610f9c8f8f86818110610f4457610f446129e3565b9050602002016020810190610f5991906127a5565b848f8f88818110610f6c57610f6c6129e3565b905060200201358e8e89818110610f8557610f856129e3565b9050602002810190610f979190612bde565b6117ff565b6001600160a01b03808516600090815260ca6020908152604080832061012d54909416835292905290812080549293508392909190610fdc908490612c3e565b909155505061012d546001600160a01b0316600090815260c960205260408120805483929061100c908490612c3e565b9091555061101c90508187612c3e565b95505050508061102b90612c56565b9050610ccf565b507fb17530966b045b50d4975e7f05048ca00d7335780c24f1c465165a4b94b2d37d8b8b8b8b8660405161106a959493929190612cb8565b60405180910390a150600160cc559998505050505050505050565b60006110908261161d565b826001600160a01b0316627e3dd26040518163ffffffff1660e01b8152600401602060405180830381865afa1580156110cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110f19190612bbc565b61110d5760405162461bcd60e51b815260040161048790612d13565b506001600160a01b03808316600090815260ca60209081526040808320938516835292905220545b92915050565b611143611505565b61114d6000611da2565b565b61118d6040518060400160405280601e81526020017f7365744d696e416d6f756e74546f436f6e766572742875696e74323536290000815250611734565b600081116111ad5760405162461bcd60e51b81526004016104879061299b565b61013080549082905560408051828152602081018490527fada67d0d38fa20c8ae6a5c17cb9d60b0fe7f2d4e4f27ac9ee55e54ac88de9d8d91015b60405180910390a15050565b6111fc611505565b6112058161161d565b61012e80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907fb6e5fcf02f7fbb8acfbaa3bac4fd5abf9ff51e3f2e8884b5498927179b211b2890600090a35050565b60655433906001600160a01b031681146112c65760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b6064820152608401610487565b61064381611da2565b6112d7611505565b6112e08161161d565b60cb80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907fa87b964d321035d2165e484ff4b722dd6eae30606c0b98887d2ed1a34e594bfe90600090a35050565b61133a611505565b6106438161169a565b6000816001600160a01b0316627e3dd26040518163ffffffff1660e01b8152600401602060405180830381865afa158015611382573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113a69190612bbc565b6114015760405162461bcd60e51b815260206004820152602660248201527f5269736b2046756e643a20436f6d7074726f6c6c6572206164647265737320696044820152651b9d985b1a5960d21b6064820152608401610487565b506001600160a01b03908116600090815260ca6020908152604080832061012d549094168352929052205490565b6114398282611dbb565b5050565b611445611505565b606580546001600160a01b0383166001600160a01b031990911681179091556114766033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b179052611500908490612078565b505050565b6033546001600160a01b0316331461114d5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610487565b6001600160a01b0381166115c35760405162461bcd60e51b815260206004820152602560248201527f696e76616c696420616365737320636f6e74726f6c206d616e61676572206164604482015264647265737360d81b6064820152608401610487565b609780546001600160a01b038381166001600160a01b031983168117909355604080519190921680825260208201939093527f66fd58e82f7b31a2a5c30e0888f3093efe4e111b00cd2b0c31fe014601293aa091016111e8565b6001600160a01b038116610643576040516342bcdf7f60e11b815260040160405180910390fd5b600054610100900460ff1661166b5760405162461bcd60e51b815260040161048790612d5e565b61114d61214d565b600054610100900460ff1661063a5760405162461bcd60e51b815260040161048790612d5e565b60fb5481116116f65760405162461bcd60e51b815260206004820152602260248201527f436f6d7074726f6c6c65723a20496e76616c6964206d61784c6f6f70734c696d6044820152611a5d60f21b6064820152608401610487565b60fb80549082905560408051828152602081018490527fc2d09fef144f7c8a86f71ea459f8fc17f675768eb1ae369cbd77fb31d467aafa91016111e8565b6097546040516318c5e8ab60e01b81526000916001600160a01b0316906318c5e8ab906117679033908690600401612dd5565b602060405180830381865afa158015611784573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117a89190612bbc565b90508061143957333083604051634a3fa29360e01b815260040161048793929190612df9565b60fb548111156106435760fb5460405163792bfb1b60e11b8152600481019190915260248101829052604401610487565b6000836000036118775760405162461bcd60e51b815260206004820152603c60248201527f5269736b46756e643a20616d6f756e744f75744d696e206d757374206265206760448201527f726561746572207468616e203020746f20737761702076546f6b656e000000006064820152608401610487565b600080876001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa1580156118b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118dc91906129f9565b61012d546001600160a01b03898116600090815260ca60209081526040808320848716845290915281205493945091169190819003611922576000945050505050611d99565b6000896001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa158015611962573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061198691906129f9565b60405163b62cad6960e01b81526001600160a01b0385811660048301529192509082169063b62cad6990602401600060405180830381600087803b1580156119cd57600080fd5b505af11580156119e1573d6000803e3d6000fd5b50506040805160208101918290526341976e0960e01b9091526001600160a01b03868116602483015260009350909150819084166341976e0960448301602060405180830381865afa158015611a3b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a5f9190612982565b905290506000611a6f828c61217d565b905061013054811015611ad25760405162461bcd60e51b815260206004820152602560248201527f5269736b46756e643a206d696e416d6f756e74546f436f6e766572742076696f6044820152641b185d195960da1b6064820152608401610487565b6001600160a01b038616600090815260c9602052604081208054869290611afa908490612e25565b90915550506001600160a01b03808d16600090815260ca60209081526040808320938a1683529290529081208054869290611b36908490612e25565b90915550506001600160a01b0386811690861614611d8b57856001600160a01b03168a8a6000818110611b6b57611b6b6129e3565b9050602002016020810190611b8091906127a5565b6001600160a01b031614611bfc5760405162461bcd60e51b815260206004820152603860248201527f5269736b46756e643a20737761702070617468206d757374207374617274207760448201527f6974682074686520756e6465726c79696e6720617373657400000000000000006064820152608401610487565b6001600160a01b0385168a8a611c13600182612e25565b818110611c2257611c226129e3565b9050602002016020810190611c3791906127a5565b6001600160a01b031614611cab5760405162461bcd60e51b815260206004820152603560248201527f5269736b46756e643a2066696e616c6c792070617468206d75737420626520636044820152741bdb9d995c9d1a589b194818985cd948185cdcd95d605a1b6064820152608401610487565b61012f546001600160a01b0390811690611cc990881682600061219d565b611cdd6001600160a01b038816828761219d565b6000816001600160a01b03166338ed1739878f8f8f30426040518763ffffffff1660e01b8152600401611d1596959493929190612e3c565b6000604051808303816000875af1158015611d34573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611d5c9190810190612e9e565b905080611d6a60018d612e25565b81518110611d7a57611d7a6129e3565b602002602001015198505050611d8f565b8396505b5094955050505050505b95945050505050565b606580546001600160a01b031916905561064381612289565b611dc48161161d565b816001600160a01b0316627e3dd26040518163ffffffff1660e01b8152600401602060405180830381865afa158015611e01573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e259190612bbc565b611e415760405162461bcd60e51b815260040161048790612d13565b60cb546001600160a01b031680611eb35760405162461bcd60e51b815260206004820152603060248201527f5265736572766548656c706572733a20506f6f6c20526567697374727920616460448201526f191c995cdcc81a5cc81b9bdd081cd95d60821b6064820152608401610487565b611ebd83836122db565b611f245760405162461bcd60e51b815260206004820152603260248201527f5265736572766548656c706572733a2054686520706f6f6c20646f65736e2774604482015271081cdd5c1c1bdc9d081d1a1948185cdcd95d60721b6064820152608401610487565b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa158015611f6b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f8f9190612982565b6001600160a01b038416600090815260c9602052604090205490915080821115612071576001600160a01b038416600090815260c960205260408120805483850392839291611fdf908490612c3e565b90915550506001600160a01b03808716600090815260ca602090815260408083209389168352929052908120805483929061201b908490612c3e565b92505081905550846001600160a01b0316866001600160a01b03167fc39e3e80c0219fde334a8cb5d8468b628482e23388b6e809c90cb00c63c8ce388360405161206791815260200190565b60405180910390a3505b5050505050565b60006120cd826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166123af9092919063ffffffff16565b90508051600014806120ee5750808060200190518101906120ee9190612bbc565b6115005760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610487565b600054610100900460ff166121745760405162461bcd60e51b815260040161048790612d5e565b61114d33611da2565b60008061218a84846123be565b9050612195816123ef565b949350505050565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663095ea7b360e01b1790529151909160009182918716906121fb908590612f29565b6000604051808303816000865af19150503d8060008114612238576040519150601f19603f3d011682016040523d82523d6000602084013e61223d565b606091505b509150915081158061226b575080511580159061226b5750808060200190518101906122699190612bbc565b155b156109c057604051633e3f8f7360e01b815260040160405180910390fd5b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316836001600160a01b0316036123265761231f82612407565b9050611135565b60cb5460405163266e0a7f60e01b81526001600160a01b0385811660048301528481166024830152600092169063266e0a7f90604401602060405180830381865afa158015612379573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061239d91906129f9565b6001600160a01b031614159392505050565b606061219584846000856125d8565b60408051602081019091526000815260405180602001604052806123e68560000151856126b3565b90529392505050565b805160009061113590670de0b6b3a764000090612f45565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b0772d0b6040518163ffffffff1660e01b8152600401600060405180830381865afa158015612468573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526124909190810190612f67565b905060005b81518110156125d1578181815181106124b0576124b06129e3565b60200260200101516001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03161461258457836001600160a01b031682828151811061250c5761250c6129e3565b60200260200101516001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa158015612551573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061257591906129f9565b6001600160a01b0316146125ba565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316846001600160a01b0316145b9250826125d1576125ca81612c56565b9050612495565b5050919050565b6060824710156126395760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610487565b600080866001600160a01b031685876040516126559190612f29565b60006040518083038185875af1925050503d8060008114612692576040519150601f19603f3d011682016040523d82523d6000602084013e612697565b606091505b50915091506126a8878383876126c6565b979650505050505050565b60006126bf8284612ff6565b9392505050565b6060831561273557825160000361272e576001600160a01b0385163b61272e5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610487565b5081612195565b612195838381511561274a5781518083602001fd5b8060405162461bcd60e51b81526004016104879190613015565b6001600160a01b038116811461064357600080fd5b6000806040838503121561278c57600080fd5b823561279781612764565b946020939093013593505050565b6000602082840312156127b757600080fd5b81356126bf81612764565b600080604083850312156127d557600080fd5b82356127e081612764565b915060208301356127f081612764565b809150509250929050565b600080600080600060a0868803121561281357600080fd5b853561281e81612764565b945060208601359350604086013561283581612764565b9250606086013561284581612764565b949793965091946080013592915050565b60008083601f84011261286857600080fd5b50813567ffffffffffffffff81111561288057600080fd5b6020830191508360208260051b850101111561289b57600080fd5b9250929050565b60008060008060008060006080888a0312156128bd57600080fd5b873567ffffffffffffffff808211156128d557600080fd5b6128e18b838c01612856565b909950975060208a01359150808211156128fa57600080fd5b6129068b838c01612856565b909750955060408a013591508082111561291f57600080fd5b5061292c8a828b01612856565b989b979a50959894979596606090950135949350505050565b60006020828403121561295757600080fd5b5035919050565b6020808252600a90820152691c994b595b9d195c995960b21b604082015260600190565b60006020828403121561299457600080fd5b5051919050565b60208082526028908201527f5269736b2046756e643a20496e76616c6964206d696e20616d6f756e7420746f6040820152670818dbdb9d995c9d60c21b606082015260800190565b634e487b7160e01b600052603260045260246000fd5b600060208284031215612a0b57600080fd5b81516126bf81612764565b634e487b7160e01b600052604160045260246000fd5b60405160a0810167ffffffffffffffff81118282101715612a4f57612a4f612a16565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715612a7e57612a7e612a16565b604052919050565b60005b83811015612aa1578181015183820152602001612a89565b83811115612ab0576000848401525b50505050565b8051612ac181612764565b919050565b60006020808385031215612ad957600080fd5b825167ffffffffffffffff80821115612af157600080fd5b9084019060a08287031215612b0557600080fd5b612b0d612a2c565b825182811115612b1c57600080fd5b8301601f81018813612b2d57600080fd5b805183811115612b3f57612b3f612a16565b612b51601f8201601f19168701612a55565b93508084528886828401011115612b6757600080fd5b612b7681878601888501612a86565b5050818152612b86848401612ab6565b84820152612b9660408401612ab6565b604082015260608301516060820152608083015160808201528094505050505092915050565b600060208284031215612bce57600080fd5b815180151581146126bf57600080fd5b6000808335601e19843603018112612bf557600080fd5b83018035915067ffffffffffffffff821115612c1057600080fd5b6020019150600581901b360382131561289b57600080fd5b634e487b7160e01b600052601160045260246000fd5b60008219821115612c5157612c51612c28565b500190565b600060018201612c6857612c68612c28565b5060010190565b8183526000602080850194508260005b85811015612cad578135612c9281612764565b6001600160a01b031687529582019590820190600101612c7f565b509495945050505050565b606081526000612ccc606083018789612c6f565b82810360208401528481526001600160fb1b03851115612ceb57600080fd5b8460051b80876020840137600091016020019081526040929092019290925295945050505050565b6020808252602b908201527f5265736572766548656c706572733a20436f6d7074726f6c6c6572206164647260408201526a195cdcc81a5b9d985b1a5960aa1b606082015260800190565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b60008151808452612dc1816020860160208601612a86565b601f01601f19169290920160200192915050565b6001600160a01b038316815260406020820181905260009061219590830184612da9565b6001600160a01b03848116825283166020820152606060408201819052600090611d9990830184612da9565b600082821015612e3757612e37612c28565b500390565b86815285602082015260a060408201526000612e5c60a083018688612c6f565b6001600160a01b039490941660608301525060800152949350505050565b600067ffffffffffffffff821115612e9457612e94612a16565b5060051b60200190565b60006020808385031215612eb157600080fd5b825167ffffffffffffffff811115612ec857600080fd5b8301601f81018513612ed957600080fd5b8051612eec612ee782612e7a565b612a55565b81815260059190911b82018301908381019087831115612f0b57600080fd5b928401925b828410156126a857835182529284019290840190612f10565b60008251612f3b818460208701612a86565b9190910192915050565b600082612f6257634e487b7160e01b600052601260045260246000fd5b500490565b60006020808385031215612f7a57600080fd5b825167ffffffffffffffff811115612f9157600080fd5b8301601f81018513612fa257600080fd5b8051612fb0612ee782612e7a565b81815260059190911b82018301908381019087831115612fcf57600080fd5b928401925b828410156126a8578351612fe781612764565b82529284019290840190612fd4565b600081600019048311821515161561301057613010612c28565b500290565b6020815260006126bf6020830184612da956fe73776170506f6f6c7341737365747328616464726573735b5d2c75696e743235365b5d2c616464726573735b5d5b5d2c75696e7432353629a2646970667358221220c967afe4ee07c007702bfe8b40ad090042c372456a0a152775ad412949fc6bc564736f6c634300080d0033", "devdoc": { "author": "Venus", "details": "This contract does not support BNB.", @@ -1222,7 +1220,7 @@ "type": "t_array(t_uint256)49_storage" }, { - "astId": 9272, + "astId": 9284, "contract": "contracts/RiskFund/RiskFund.sol:RiskFund", "label": "convertibleBaseAsset", "offset": 0, @@ -1230,7 +1228,7 @@ "type": "t_address" }, { - "astId": 9274, + "astId": 9286, "contract": "contracts/RiskFund/RiskFund.sol:RiskFund", "label": "shortfall", "offset": 0, @@ -1238,7 +1236,7 @@ "type": "t_address" }, { - "astId": 9276, + "astId": 9288, "contract": "contracts/RiskFund/RiskFund.sol:RiskFund", "label": "pancakeSwapRouter", "offset": 0, @@ -1246,7 +1244,7 @@ "type": "t_address" }, { - "astId": 9278, + "astId": 9290, "contract": "contracts/RiskFund/RiskFund.sol:RiskFund", "label": "minAmountToConvert", "offset": 0, @@ -1314,4 +1312,4 @@ } } } -} \ No newline at end of file +} diff --git a/deployments/bsctestnet/solcInputs/0c597ac2b90fc7d0b2be179fa6482d23.json b/deployments/bsctestnet/solcInputs/0c597ac2b90fc7d0b2be179fa6482d23.json index 354fcbd3c..798b0c95d 100644 --- a/deployments/bsctestnet/solcInputs/0c597ac2b90fc7d0b2be179fa6482d23.json +++ b/deployments/bsctestnet/solcInputs/0c597ac2b90fc7d0b2be179fa6482d23.json @@ -122,13 +122,11 @@ "userdoc", "evm.gasEstimates" ], - "": [ - "ast" - ] + "": ["ast"] } }, "metadata": { "useLiteralContent": true } } -} \ No newline at end of file +} diff --git a/deployments/bsctestnet/solcInputs/f237ea044837d6f4ff4c08abcdd27558.json b/deployments/bsctestnet/solcInputs/f237ea044837d6f4ff4c08abcdd27558.json new file mode 100644 index 000000000..49193e297 --- /dev/null +++ b/deployments/bsctestnet/solcInputs/f237ea044837d6f4ff4c08abcdd27558.json @@ -0,0 +1,132 @@ +{ + "language": "Solidity", + "sources": { + "@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable2Step.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./OwnableUpgradeable.sol\";\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module which provides access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership} and {acceptOwnership}.\n *\n * This module is used through inheritance. It will make available all functions\n * from parent (Ownable).\n */\nabstract contract Ownable2StepUpgradeable is Initializable, OwnableUpgradeable {\n function __Ownable2Step_init() internal onlyInitializing {\n __Ownable_init_unchained();\n }\n\n function __Ownable2Step_init_unchained() internal onlyInitializing {\n }\n address private _pendingOwner;\n\n event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Returns the address of the pending owner.\n */\n function pendingOwner() public view virtual returns (address) {\n return _pendingOwner;\n }\n\n /**\n * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual override onlyOwner {\n _pendingOwner = newOwner;\n emit OwnershipTransferStarted(owner(), newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual override {\n delete _pendingOwner;\n super._transferOwnership(newOwner);\n }\n\n /**\n * @dev The new owner accepts the ownership transfer.\n */\n function acceptOwnership() public virtual {\n address sender = _msgSender();\n require(pendingOwner() == sender, \"Ownable2Step: caller is not the new owner\");\n _transferOwnership(sender);\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/ContextUpgradeable.sol\";\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n function __Ownable_init() internal onlyInitializing {\n __Ownable_init_unchained();\n }\n\n function __Ownable_init_unchained() internal onlyInitializing {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n _checkOwner();\n _;\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if the sender is not the owner.\n */\n function _checkOwner() internal view virtual {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby disabling any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)\n\npragma solidity ^0.8.2;\n\nimport \"../../utils/AddressUpgradeable.sol\";\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```solidity\n * contract MyToken is ERC20Upgradeable {\n * function initialize() initializer public {\n * __ERC20_init(\"MyToken\", \"MTK\");\n * }\n * }\n *\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n * function initializeV2() reinitializer(2) public {\n * __ERC20Permit_init(\"MyToken\");\n * }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n * _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n /**\n * @dev Indicates that the contract has been initialized.\n * @custom:oz-retyped-from bool\n */\n uint8 private _initialized;\n\n /**\n * @dev Indicates that the contract is in the process of being initialized.\n */\n bool private _initializing;\n\n /**\n * @dev Triggered when the contract has been initialized or reinitialized.\n */\n event Initialized(uint8 version);\n\n /**\n * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n * `onlyInitializing` functions can be used to initialize parent contracts.\n *\n * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a\n * constructor.\n *\n * Emits an {Initialized} event.\n */\n modifier initializer() {\n bool isTopLevelCall = !_initializing;\n require(\n (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),\n \"Initializable: contract is already initialized\"\n );\n _initialized = 1;\n if (isTopLevelCall) {\n _initializing = true;\n }\n _;\n if (isTopLevelCall) {\n _initializing = false;\n emit Initialized(1);\n }\n }\n\n /**\n * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n * used to initialize parent contracts.\n *\n * A reinitializer may be used after the original initialization step. This is essential to configure modules that\n * are added through upgrades and that require initialization.\n *\n * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\n * cannot be nested. If one is invoked in the context of another, execution will revert.\n *\n * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n * a contract, executing them in the right order is up to the developer or operator.\n *\n * WARNING: setting the version to 255 will prevent any future reinitialization.\n *\n * Emits an {Initialized} event.\n */\n modifier reinitializer(uint8 version) {\n require(!_initializing && _initialized < version, \"Initializable: contract is already initialized\");\n _initialized = version;\n _initializing = true;\n _;\n _initializing = false;\n emit Initialized(version);\n }\n\n /**\n * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n * {initializer} and {reinitializer} modifiers, directly or indirectly.\n */\n modifier onlyInitializing() {\n require(_initializing, \"Initializable: contract is not initializing\");\n _;\n }\n\n /**\n * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n * through proxies.\n *\n * Emits an {Initialized} event the first time it is successfully executed.\n */\n function _disableInitializers() internal virtual {\n require(!_initializing, \"Initializable: contract is initializing\");\n if (_initialized != type(uint8).max) {\n _initialized = type(uint8).max;\n emit Initialized(type(uint8).max);\n }\n }\n\n /**\n * @dev Returns the highest version that has been initialized. See {reinitializer}.\n */\n function _getInitializedVersion() internal view returns (uint8) {\n return _initialized;\n }\n\n /**\n * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\n */\n function _isInitializing() internal view returns (bool) {\n return _initializing;\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/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/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" + }, + "@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/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/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" + }, + "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/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/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 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 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\";\nimport { VToken } from \"../VToken.sol\";\nimport { PoolRegistry } from \"../Pool/PoolRegistry.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 PoolRegistry(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/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" + } + }, + "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/tests/hardhat/Fork/RiskFund.ts b/tests/hardhat/Fork/RiskFund.ts index c5a2861af..617ba35fa 100644 --- a/tests/hardhat/Fork/RiskFund.ts +++ b/tests/hardhat/Fork/RiskFund.ts @@ -135,7 +135,11 @@ const riskFundFixture = async (): Promise => { RiskFund, [pancakeSwapRouter.address, convertToUnit(10, 18), BUSD.address, accessControlManager.address, 150], { - constructorArgs: [fakeCorePoolComptroller.address, "0x0000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000002"], + constructorArgs: [ + fakeCorePoolComptroller.address, + "0x0000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000002", + ], }, )) as RiskFund; await riskFund.setShortfallContractAddress(shortfall.address); @@ -146,7 +150,11 @@ const riskFundFixture = async (): Promise => { ProtocolShareReserve, [fakeProtocolIncome.address, riskFund.address], { - constructorArgs: [fakeCorePoolComptroller.address, "0x0000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000002"], + constructorArgs: [ + fakeCorePoolComptroller.address, + "0x0000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000002", + ], }, )) as ProtocolShareReserve; diff --git a/tests/hardhat/Fork/RiskFundSwap.ts b/tests/hardhat/Fork/RiskFundSwap.ts index 4074b9d01..3e8a50c50 100644 --- a/tests/hardhat/Fork/RiskFundSwap.ts +++ b/tests/hardhat/Fork/RiskFundSwap.ts @@ -118,7 +118,11 @@ const riskFundFixture = async (): Promise => { RiskFund, [pancakeSwapRouter.address, parseUnits("10", 18), BUSD.address, fakeAccessControlManager.address, maxLoopsLimit], { - constructorArgs: [fakeCorePoolComptroller.address, "0x0000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000002"], + constructorArgs: [ + fakeCorePoolComptroller.address, + "0x0000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000002", + ], }, )) as RiskFund; @@ -130,7 +134,11 @@ const riskFundFixture = async (): Promise => { ProtocolShareReserve, [fakeProtocolIncome.address, riskFund.address], { - constructorArgs: [fakeCorePoolComptroller.address, "0x0000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000002"], + constructorArgs: [ + fakeCorePoolComptroller.address, + "0x0000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000002", + ], }, )) as ProtocolShareReserve; diff --git a/tests/hardhat/ProtocolShareReserve.ts b/tests/hardhat/ProtocolShareReserve.ts index 110665d53..f3b888ae2 100644 --- a/tests/hardhat/ProtocolShareReserve.ts +++ b/tests/hardhat/ProtocolShareReserve.ts @@ -38,7 +38,11 @@ const fixture = async (): Promise => { ProtocolShareReserve, [fakeProtocolIncome.address, fakeRiskFund.address], { - constructorArgs: [fakeCorePoolComptroller.address, "0x0000000000000000000000000000000000000001", "0x0000000000000000000000000000000000000002"], + constructorArgs: [ + fakeCorePoolComptroller.address, + "0x0000000000000000000000000000000000000001", + "0x0000000000000000000000000000000000000002", + ], }, ); From 761b0e1386ea27db1a410c29be7ad2bc3e5109aa Mon Sep 17 00:00:00 2001 From: Narayan Prusty Date: Mon, 9 Oct 2023 18:54:09 +0100 Subject: [PATCH 20/33] fix: use PoolRegistry interface --- contracts/RiskFund/ReserveHelpers.sol | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/contracts/RiskFund/ReserveHelpers.sol b/contracts/RiskFund/ReserveHelpers.sol index 622bdc66c..a9dbde5d6 100644 --- a/contracts/RiskFund/ReserveHelpers.sol +++ b/contracts/RiskFund/ReserveHelpers.sol @@ -9,7 +9,6 @@ import { ensureNonzeroAddress } from "../lib/validators.sol"; import { ComptrollerInterface } from "../ComptrollerInterface.sol"; import { PoolRegistryInterface } from "../Pool/PoolRegistryInterface.sol"; import { VToken } from "../VToken.sol"; -import { PoolRegistry } from "../Pool/PoolRegistry.sol"; contract ReserveHelpers is Ownable2StepUpgradeable { using SafeERC20Upgradeable for IERC20Upgradeable; @@ -164,6 +163,6 @@ contract ReserveHelpers is Ownable2StepUpgradeable { return isAssetListedInCore(asset); } - return PoolRegistry(poolRegistry).getVTokenForAsset(comptroller, asset) != address(0); + return PoolRegistryInterface(poolRegistry).getVTokenForAsset(comptroller, asset) != address(0); } } From 650180c5ebfd365e076dced9a1fd3d2d4a8b776f Mon Sep 17 00:00:00 2001 From: Venus Tools Date: Tue, 10 Oct 2023 10:30:03 +0000 Subject: [PATCH 21/33] chore(release): 2.1.0-dev.4 [skip ci] ## [2.1.0-dev.4](https://github.com/VenusProtocol/isolated-pools/compare/v2.1.0-dev.3...v2.1.0-dev.4) (2023-10-10) ### Features * add deployments of agEUR market ([667ac5f](https://github.com/VenusProtocol/isolated-pools/commit/667ac5feeedf0a7337258389f16110df864948cb)) * add reward distributor in agEUR market ([072714d](https://github.com/VenusProtocol/isolated-pools/commit/072714ded3dc712e9ed99748ff6a2da2adb94a02)) --- CHANGELOG.md | 8 ++++++++ package.json | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4776749a0..5d747825a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,11 @@ +## [2.1.0-dev.4](https://github.com/VenusProtocol/isolated-pools/compare/v2.1.0-dev.3...v2.1.0-dev.4) (2023-10-10) + + +### Features + +* add deployments of agEUR market ([667ac5f](https://github.com/VenusProtocol/isolated-pools/commit/667ac5feeedf0a7337258389f16110df864948cb)) +* add reward distributor in agEUR market ([072714d](https://github.com/VenusProtocol/isolated-pools/commit/072714ded3dc712e9ed99748ff6a2da2adb94a02)) + ## [2.1.0-dev.3](https://github.com/VenusProtocol/isolated-pools/compare/v2.1.0-dev.2...v2.1.0-dev.3) (2023-09-29) diff --git a/package.json b/package.json index 06992c70c..2b0fd086b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@venusprotocol/isolated-pools", - "version": "2.1.0-dev.3", + "version": "2.1.0-dev.4", "description": "", "files": [ "artifacts", From 35d7139b1de2c29815f5d4c691cb316b3a1a7c0c Mon Sep 17 00:00:00 2001 From: Narayan Prusty Date: Tue, 10 Oct 2023 14:19:12 +0100 Subject: [PATCH 22/33] fix: redeployed risk fund implementation --- .../bscmainnet/RiskFund_Implementation.json | 58 ++++---- .../09e209110f36e8c9fe7ecc1925064673.json | 132 ++++++++++++++++++ .../bsctestnet/RiskFund_Implementation.json | 52 +++---- .../09e209110f36e8c9fe7ecc1925064673.json | 132 ++++++++++++++++++ 4 files changed, 319 insertions(+), 55 deletions(-) create mode 100644 deployments/bscmainnet/solcInputs/09e209110f36e8c9fe7ecc1925064673.json create mode 100644 deployments/bsctestnet/solcInputs/09e209110f36e8c9fe7ecc1925064673.json diff --git a/deployments/bscmainnet/RiskFund_Implementation.json b/deployments/bscmainnet/RiskFund_Implementation.json index 3f1f4aeac..9105e0eba 100644 --- a/deployments/bscmainnet/RiskFund_Implementation.json +++ b/deployments/bscmainnet/RiskFund_Implementation.json @@ -1,5 +1,5 @@ { - "address": "0x470443271a416214841a617cbFB8b2f060dDb830", + "address": "0x0E8Ef0EC1e0C109c5B5249CcefB703A414835eaC", "abi": [ { "inputs": [ @@ -811,30 +811,30 @@ "type": "function" } ], - "transactionHash": "0xf1bb734413dee3f943e457c8734e4b66e3dd8dd9783329b88c273f4780e95ef6", + "transactionHash": "0xd9867d6013bc06e223fd5dd18d00fd3ed5df66e5af4fe5333bd262dfc5f274a4", "receipt": { "to": null, "from": "0x8BDA9f9E1fEF0DFd404Fef338D9fE4c543d172e1", - "contractAddress": "0x470443271a416214841a617cbFB8b2f060dDb830", - "transactionIndex": 46, - "gasUsed": "2769907", - "logsBloom": "0x00000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000080000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x5265158486084e468ed2c2e0d3ff83459eb807e24726f2936f01c910a19c6af7", - "transactionHash": "0xf1bb734413dee3f943e457c8734e4b66e3dd8dd9783329b88c273f4780e95ef6", + "contractAddress": "0x0E8Ef0EC1e0C109c5B5249CcefB703A414835eaC", + "transactionIndex": 27, + "gasUsed": "2769919", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000040000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x5d616ed035cdd9a3c75af48af68ca2407ea78cf0ff10636938fecb57d95b9037", + "transactionHash": "0xd9867d6013bc06e223fd5dd18d00fd3ed5df66e5af4fe5333bd262dfc5f274a4", "logs": [ { - "transactionIndex": 46, - "blockNumber": 32457691, - "transactionHash": "0xf1bb734413dee3f943e457c8734e4b66e3dd8dd9783329b88c273f4780e95ef6", - "address": "0x470443271a416214841a617cbFB8b2f060dDb830", + "transactionIndex": 27, + "blockNumber": 32482245, + "transactionHash": "0xd9867d6013bc06e223fd5dd18d00fd3ed5df66e5af4fe5333bd262dfc5f274a4", + "address": "0x0E8Ef0EC1e0C109c5B5249CcefB703A414835eaC", "topics": ["0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498"], "data": "0x00000000000000000000000000000000000000000000000000000000000000ff", - "logIndex": 220, - "blockHash": "0x5265158486084e468ed2c2e0d3ff83459eb807e24726f2936f01c910a19c6af7" + "logIndex": 154, + "blockHash": "0x5d616ed035cdd9a3c75af48af68ca2407ea78cf0ff10636938fecb57d95b9037" } ], - "blockNumber": 32457691, - "cumulativeGasUsed": "11147413", + "blockNumber": 32482245, + "cumulativeGasUsed": "6439831", "status": 1, "byzantium": true }, @@ -844,10 +844,10 @@ "0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c" ], "numDeployments": 1, - "solcInputHash": "f237ea044837d6f4ff4c08abcdd27558", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"corePoolComptroller_\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"vbnb_\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nativeWrapped_\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"ApproveFailed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"loopsLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requiredLoops\",\"type\":\"uint256\"}],\"name\":\"MaxLoopsLimitExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"calledContract\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"methodSignature\",\"type\":\"string\"}],\"name\":\"Unauthorized\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"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\":\"oldConvertibleBaseAsset\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newConvertibleBaseAsset\",\"type\":\"address\"}],\"name\":\"ConvertibleBaseAssetUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldMaxLoopsLimit\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newmaxLoopsLimit\",\"type\":\"uint256\"}],\"name\":\"MaxLoopsLimitUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldMinAmountToConvert\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newMinAmountToConvert\",\"type\":\"uint256\"}],\"name\":\"MinAmountToConvertUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldAccessControlManager\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newAccessControlManager\",\"type\":\"address\"}],\"name\":\"NewAccessControlManager\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferStarted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"oldPancakeSwapRouter\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newPancakeSwapRouter\",\"type\":\"address\"}],\"name\":\"PancakeSwapRouterUpdated\",\"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\":\"oldShortfallContract\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"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\":\"totalAmount\",\"type\":\"uint256\"}],\"name\":\"SwappedPoolsAssets\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"SweepToken\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"TransferredReserveForAuction\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"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\",\"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\"}],\"name\":\"assetsReserves\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"convertibleBaseAsset\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"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\":\"comptroller\",\"type\":\"address\"}],\"name\":\"getPoolsBaseAssetReserves\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"pancakeSwapRouter_\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmountToConvert_\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"convertibleBaseAsset_\",\"type\":\"address\"},{\"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\":\"minAmountToConvert\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pancakeSwapRouter\",\"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\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"accessControlManager_\",\"type\":\"address\"}],\"name\":\"setAccessControlManager\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_convertibleBaseAsset\",\"type\":\"address\"}],\"name\":\"setConvertibleBaseAsset\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"limit\",\"type\":\"uint256\"}],\"name\":\"setMaxLoopsLimit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minAmountToConvert_\",\"type\":\"uint256\"}],\"name\":\"setMinAmountToConvert\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"pancakeSwapRouter_\",\"type\":\"address\"}],\"name\":\"setPancakeSwapRouter\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"poolRegistry_\",\"type\":\"address\"}],\"name\":\"setPoolRegistry\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"shortfallContractAddress_\",\"type\":\"address\"}],\"name\":\"setShortfallContractAddress\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"shortfall\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"markets\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"amountsOutMin\",\"type\":\"uint256[]\"},{\"internalType\":\"address[][]\",\"name\":\"paths\",\"type\":\"address[][]\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"swapPoolsAssets\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"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\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transferReserveForAuction\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"}],\"name\":\"updateAssetsState\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Venus\",\"details\":\"This contract does not support BNB.\",\"kind\":\"dev\",\"methods\":{\"acceptOwnership()\":{\"details\":\"The new owner accepts the ownership transfer.\"},\"constructor\":{\"custom:oz-upgrades-unsafe-allow\":\"constructor\",\"details\":\"Note that the contract is upgradeable. Use initialize() or reinitializers to set the state variables.\"},\"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.\"}},\"getPoolsBaseAssetReserves(address)\":{\"params\":{\"comptroller\":\"Comptroller address(pool).\"},\"returns\":{\"_0\":\"Base Asset's reserve in risk fund.\"}},\"initialize(address,uint256,address,address,uint256)\":{\"custom:error\":\"ZeroAddressNotAllowed is thrown when PCS router address is zeroZeroAddressNotAllowed is thrown when convertible base asset address is zero\",\"params\":{\"accessControlManager_\":\"Address of the access control contract\",\"convertibleBaseAsset_\":\"Address of the base asset\",\"loopsLimit_\":\"Limit for the loops in the contract to avoid DOS\",\"minAmountToConvert_\":\"Minimum amount assets must be worth to convert into base asset\",\"pancakeSwapRouter_\":\"Address of the PancakeSwap router\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"pendingOwner()\":{\"details\":\"Returns the address of the pending owner.\"},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner.\"},\"setAccessControlManager(address)\":{\"custom:access\":\"Only Governance\",\"custom:event\":\"Emits NewAccessControlManager event\",\"details\":\"Admin function to set address of AccessControlManager\",\"params\":{\"accessControlManager_\":\"The new address of the AccessControlManager\"}},\"setConvertibleBaseAsset(address)\":{\"params\":{\"_convertibleBaseAsset\":\"Address for new convertible base asset.\"}},\"setMaxLoopsLimit(uint256)\":{\"params\":{\"limit\":\"Limit for the max loops can execute at a time\"}},\"setMinAmountToConvert(uint256)\":{\"params\":{\"minAmountToConvert_\":\"Min amount to convert.\"}},\"setPancakeSwapRouter(address)\":{\"custom:error\":\"ZeroAddressNotAllowed is thrown when PCS router address is zero\",\"params\":{\"pancakeSwapRouter_\":\"Address of the PancakeSwap router\"}},\"setPoolRegistry(address)\":{\"custom:error\":\"ZeroAddressNotAllowed is thrown when pool registry address is zero\",\"params\":{\"poolRegistry_\":\"Address of the pool registry\"}},\"setShortfallContractAddress(address)\":{\"custom:error\":\"ZeroAddressNotAllowed is thrown when shortfall contract address is zero\",\"params\":{\"shortfallContractAddress_\":\"Address of the auction contract\"}},\"swapPoolsAssets(address[],uint256[],address[][],uint256)\":{\"custom:error\":\"ZeroAddressNotAllowed is thrown if PoolRegistry contract address is not configured\",\"params\":{\"amountsOutMin\":\"Minimum amount to receive for swap\",\"deadline\":\"Deadline for the swap\",\"markets\":\"Array of vTokens whose assets to swap for base asset\",\"paths\":\"A path consisting of PCS token pairs for each swap\"},\"returns\":{\"_0\":\"Number of swapped tokens\"}},\"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.\"},\"transferReserveForAuction(address,uint256)\":{\"params\":{\"amount\":\"Amount to be transferred to auction contract.\",\"comptroller\":\"Comptroller of the pool.\"},\"returns\":{\"_0\":\"Number reserved tokens.\"}},\"updateAssetsState(address,address)\":{\"params\":{\"asset\":\"Asset address.\",\"comptroller\":\"Comptroller address(pool).\"}}},\"title\":\"RiskFund\",\"version\":1},\"userdoc\":{\"errors\":{\"ApproveFailed()\":[{\"notice\":\"Thrown if a contract is unable to approve a transfer\"}],\"MaxLoopsLimitExceeded(uint256,uint256)\":[{\"notice\":\"Thrown an error on maxLoopsLimit exceeds for any loop\"}],\"Unauthorized(address,address,string)\":[{\"notice\":\"Thrown when the action is prohibited by AccessControlManager\"}],\"ZeroAddressNotAllowed()\":[{\"notice\":\"Thrown if the supplied address is a zero address where it is not allowed\"}]},\"events\":{\"AssetsReservesUpdated(address,address,uint256)\":{\"notice\":\"Event emitted after the update of the assets reserves.\"},\"ConvertibleBaseAssetUpdated(address,address)\":{\"notice\":\"Emitted when convertible base asset is updated\"},\"MaxLoopsLimitUpdated(uint256,uint256)\":{\"notice\":\"Emitted when max loops limit is set\"},\"MinAmountToConvertUpdated(uint256,uint256)\":{\"notice\":\"Emitted when minimum amount to convert is updated\"},\"NewAccessControlManager(address,address)\":{\"notice\":\"Emitted when access control manager contract address is changed\"},\"PancakeSwapRouterUpdated(address,address)\":{\"notice\":\"Emitted when PancakeSwap router contract address is updated\"},\"PoolRegistryUpdated(address,address)\":{\"notice\":\"Emitted when pool registry address is updated\"},\"ShortfallContractUpdated(address,address)\":{\"notice\":\"Emitted when shortfall contract address is updated\"},\"SwappedPoolsAssets(address[],uint256[],uint256)\":{\"notice\":\"Emitted when pools assets are swapped\"},\"SweepToken(address,address,uint256)\":{\"notice\":\"event emitted on sweep token success\"},\"TransferredReserveForAuction(address,uint256)\":{\"notice\":\"Emitted when reserves are transferred for auction\"}},\"kind\":\"user\",\"methods\":{\"accessControlManager()\":{\"notice\":\"Returns the address of the access control manager contract\"},\"getPoolAssetReserve(address,address)\":{\"notice\":\"Get the Amount of the asset in the risk fund for the specific pool.\"},\"getPoolsBaseAssetReserves(address)\":{\"notice\":\"Get the Amount of the Base asset in the risk fund for the specific pool.\"},\"initialize(address,uint256,address,address,uint256)\":{\"notice\":\"Initializes the deployer to owner.\"},\"setAccessControlManager(address)\":{\"notice\":\"Sets the address of AccessControlManager\"},\"setConvertibleBaseAsset(address)\":{\"notice\":\"Sets a new convertible base asset\"},\"setMaxLoopsLimit(uint256)\":{\"notice\":\"Set the limit for the loops can iterate to avoid the DOS\"},\"setMinAmountToConvert(uint256)\":{\"notice\":\"Min amount to convert setter\"},\"setPancakeSwapRouter(address)\":{\"notice\":\"PancakeSwap router address setter\"},\"setPoolRegistry(address)\":{\"notice\":\"Pool registry setter\"},\"setShortfallContractAddress(address)\":{\"notice\":\"Shortfall contract address setter\"},\"swapPoolsAssets(address[],uint256[],address[][],uint256)\":{\"notice\":\"Swap array of pool assets into base asset's tokens of at least a minimum amount\"},\"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\"},\"transferReserveForAuction(address,uint256)\":{\"notice\":\"Transfer tokens for auction.\"},\"updateAssetsState(address,address)\":{\"notice\":\"Update the reserve of the asset for the specific pool after transferring to risk fund.\"}},\"notice\":\"Contract with basic features to track/hold different assets for different Comptrollers.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/RiskFund/RiskFund.sol\":\"RiskFund\"},\"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(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 \\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\":\"0xef1ca0adc3ce1ff540279d424953087771b4a07470caac99777fafd2ceea38a9\",\"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 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(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/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\",\"keccak256\":\"0x7e4d140bd2a5671389ad7a3975b65d05a4f750daf6a61c16139d123d9782b96e\",\"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/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/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\\\";\\nimport { PoolRegistry } from \\\"../Pool/PoolRegistry.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 PoolRegistry(poolRegistry).getVTokenForAsset(comptroller, asset) != address(0);\\n }\\n}\\n\",\"keccak256\":\"0xf30155bbbb7251eb8445c7d282427ed0040d015fe34efcb5ec61bc92a289b0cc\",\"license\":\"BSD-3-Clause\"},\"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\",\"keccak256\":\"0x918526b067c834935f5dd0788139e1a73c64cbf6f8b7d6fd43242eaa93aa7f37\",\"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(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 \\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 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 \\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(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\",\"keccak256\":\"0xcda9eb71f6ceb8a4c3bfbc1c42d72e2f0523d30f6d3252fbd90819e953640fe5\",\"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(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\":\"0x2947e95eb97a3a45f90ec36d4fd5a4cbb9409319f6ad000e950550055a3f2324\",\"license\":\"BSD-3-Clause\"},\"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\",\"keccak256\":\"0x9bbc31c80a4c537ddfd06cbd03a412ba64842a708381fbc4bf2e33ef56c92b4d\",\"license\":\"MIT\"},\"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": "0x60e06040523480156200001157600080fd5b50604051620032b8380380620032b883398101604081905262000034916200018c565b828282620000428362000083565b6200004d8262000083565b620000588162000083565b6001600160a01b0392831660805290821660a0521660c0526200007a620000ae565b505050620001d6565b6001600160a01b038116620000ab576040516342bcdf7f60e11b815260040160405180910390fd5b50565b600054610100900460ff16156200011b5760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b60005460ff908116146200016d576000805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b80516001600160a01b03811681146200018757600080fd5b919050565b600080600060608486031215620001a257600080fd5b620001ad846200016f565b9250620001bd602085016200016f565b9150620001cd604085016200016f565b90509250925092565b60805160a05160c05161309662000222600039600081816102bf015261258601526000818161029801526124c3015260008181610437015281816122df015261240c01526130966000f3fe608060405234801561001057600080fd5b50600436106101da5760003560e01c806377d4937f11610104578063afcff50f116100a2578063e30c397811610071578063e30c39781461040e578063f2fde38b1461041f578063fa7b81a014610432578063fe3da9841461045957600080fd5b8063afcff50f146103cd578063b4a0bdf3146103e0578063be26317e146103f1578063c8ecc0d3146103fa57600080fd5b806380d45a2d116100de57806380d45a2d146103835780638da5cb5b14610396578063a69bd19e146103a7578063aac59a75146103ba57600080fd5b806377d4937f1461035557806379ba5097146103685780637b77cd6a1461037057600080fd5b80633421fc521161017c5780635f30e37b1161014b5780635f30e37b146103145780636fb0527514610327578063715018a61461033a578063746460a91461034257600080fd5b80633421fc5214610293578063362b6795146102ba578063439b5517146102e15780634dd9584a1461030157600080fd5b806324558995116101b85780632455899514610246578063258836fe1461025a5780632a1d05471461026d5780632e6881411461028057600080fd5b80630a9837c5146101df5780630e32cb861461020557806319b1faef1461021a575b600080fd5b6101f26101ed366004612779565b610463565b6040519081526020015b60405180910390f35b6102186102133660046127a5565b610632565b005b61012e5461022e906001600160a01b031681565b6040516001600160a01b0390911681526020016101fc565b61012f5461022e906001600160a01b031681565b6102186102683660046127c2565b610646565b61021861027b3660046127fb565b6107d7565b61021861028e3660046127a5565b6109c8565b61022e7f000000000000000000000000000000000000000000000000000000000000000081565b61022e7f000000000000000000000000000000000000000000000000000000000000000081565b6101f26102ef3660046127a5565b60c96020526000908152604090205481565b61021861030f3660046127a5565b610acd565b6101f26103223660046128a2565b610b31565b6101f26103353660046127c2565b611085565b61021861113b565b610218610350366004612945565b61114f565b6102186103633660046127a5565b6111f4565b610218611258565b61021861037e3660046127a5565b6112cf565b610218610391366004612945565b611332565b6033546001600160a01b031661022e565b6101f26103b53660046127a5565b611343565b6102186103c83660046127c2565b61142f565b60cb5461022e906001600160a01b031681565b6097546001600160a01b031661022e565b6101f260fb5481565b61012d5461022e906001600160a01b031681565b6065546001600160a01b031661022e565b61021861042d3660046127a5565b61143d565b61022e7f000000000000000000000000000000000000000000000000000000000000000081565b6101f26101305481565b6000600260cc54036104905760405162461bcd60e51b81526004016104879061295e565b60405180910390fd5b600260cc5561012e546001600160a01b03163381146105085760405162461bcd60e51b815260206004820152602e60248201527f5269736b2066756e643a204f6e6c792063616c6c61626c652062792053686f7260448201526d1d19985b1b0818dbdb9d1c9858dd60921b6064820152608401610487565b6001600160a01b03808516600090815260ca6020908152604080832061012d549094168352929052205483111561058f5760405162461bcd60e51b815260206004820152602560248201527f5269736b2046756e643a20496e73756666696369656e7420706f6f6c2072657360448201526432b93b329760d91b6064820152608401610487565b6001600160a01b03808516600081815260ca6020908152604080832061012d80548716855290835281842080548a9003905554909416825260c990528290208054869003905590517fc8d0a37ed16dfaa43514df00e18f478b60d5cc7b4bfc687103948b9020f737fd906106069086815260200190565b60405180910390a261012d54610626906001600160a01b031682856114ae565b5050600160cc55919050565b61063a611505565b6106438161155f565b50565b61064e611505565b600260cc54036106705760405162461bcd60e51b81526004016104879061295e565b600260cc5561067e8161161d565b6040516370a0823160e01b815230600482015260009081906001600160a01b038516906370a0823190602401602060405180830381865afa1580156106c7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106eb9190612982565b6001600160a01b038516600090815260c9602052604090205490915081116107615760405162461bcd60e51b815260206004820152602360248201527f5265736572766548656c706572733a205a65726f20737572706c757320746f6b604482015262656e7360e81b6064820152608401610487565b6001600160a01b03848116600081815260c960209081526040918290205491519185038083529550928616927f6d25be279134f4ecaa4770aff0c3d916d9e7c5ef37b65ed95dbdba411f5d54d5910160405180910390a36107cc6001600160a01b03851684846114ae565b5050600160cc555050565b600054610100900460ff16158080156107f75750600054600160ff909116105b806108115750303b158015610811575060005460ff166001145b6108745760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610487565b6000805460ff191660011790558015610897576000805461ff0019166101001790555b6108a08661161d565b6108a98461161d565b600085116108c95760405162461bcd60e51b81526004016104879061299b565b600082116109285760405162461bcd60e51b815260206004820152602660248201527f5269736b2046756e643a204c6f6f7073206c696d69742063616e206e6f74206260448201526565207a65726f60d01b6064820152608401610487565b610930611644565b61093983611673565b61012f80546001600160a01b038089166001600160a01b03199283161790925561013087905561012d80549287169290911691909117905561097a8261169a565b80156109c0576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050565b610a066040518060400160405280602081526020017f736574436f6e7665727469626c65426173654173736574286164647265737329815250611734565b6001600160a01b038116610a7a5760405162461bcd60e51b815260206004820152603560248201527f5269736b2046756e643a206e657720636f6e7665727469626c65206261736520604482015274185cdcd95d081859191c995cdcc81a5b9d985b1a59605a1b6064820152608401610487565b61012d80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f5fa61583da12070720613fefdd68cc6c0e464a71e009742526bd2b2e0ac62cd290600090a35050565b610ad5611505565b610ade8161161d565b61012f80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907fd37b9d138f53ea58d7e50292588239a46efa8f523966febf4066da96defc77fd90600090a35050565b6000600260cc5403610b555760405162461bcd60e51b81526004016104879061295e565b600260cc81905550610b7e60405180606001604052806038815260200161302960389139611734565b42821015610bce5760405162461bcd60e51b815260206004820152601a60248201527f5269736b2066756e643a20646561646c696e65207061737365640000000000006044820152606401610487565b60cb546001600160a01b0316610be38161161d565b878614610c585760405162461bcd60e51b815260206004820152603860248201527f5269736b2066756e643a206d61726b65747320616e6420616d6f756e74734f7560448201527f744d696e2061726520756e657175616c206c656e6774687300000000000000006064820152608401610487565b878414610cc05760405162461bcd60e51b815260206004820152603060248201527f5269736b2066756e643a206d61726b65747320616e642070617468732061726560448201526f20756e657175616c206c656e6774687360801b6064820152608401610487565b600088610ccc816117ce565b60005b818110156110325760008c8c83818110610ceb57610ceb6129e3565b9050602002016020810190610d0091906127a5565b6001600160a01b0316635fe3b5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d3d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d6191906129f9565b604051637aee632d60e01b81526001600160a01b038083166004830152919250600091871690637aee632d90602401600060405180830381865afa158015610dad573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610dd59190810190612ac6565b9050816001600160a01b031681604001516001600160a01b031614610e4c5760405162461bcd60e51b815260206004820152602760248201527f636f6d7074726f6c6c657220646f65736e277420657869737420706f6f6c20726044820152666567697374727960c81b6064820152608401610487565b816001600160a01b0316633d98a1e58f8f86818110610e6d57610e6d6129e3565b9050602002016020810190610e8291906127a5565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa158015610ec6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610eea9190612bbc565b610f2d5760405162461bcd60e51b81526020600482015260146024820152731b585c9ad95d081a5cc81b9bdd081b1a5cdd195960621b6044820152606401610487565b6000610f9c8f8f86818110610f4457610f446129e3565b9050602002016020810190610f5991906127a5565b848f8f88818110610f6c57610f6c6129e3565b905060200201358e8e89818110610f8557610f856129e3565b9050602002810190610f979190612bde565b6117ff565b6001600160a01b03808516600090815260ca6020908152604080832061012d54909416835292905290812080549293508392909190610fdc908490612c3e565b909155505061012d546001600160a01b0316600090815260c960205260408120805483929061100c908490612c3e565b9091555061101c90508187612c3e565b95505050508061102b90612c56565b9050610ccf565b507fb17530966b045b50d4975e7f05048ca00d7335780c24f1c465165a4b94b2d37d8b8b8b8b8660405161106a959493929190612cb8565b60405180910390a150600160cc559998505050505050505050565b60006110908261161d565b826001600160a01b0316627e3dd26040518163ffffffff1660e01b8152600401602060405180830381865afa1580156110cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110f19190612bbc565b61110d5760405162461bcd60e51b815260040161048790612d13565b506001600160a01b03808316600090815260ca60209081526040808320938516835292905220545b92915050565b611143611505565b61114d6000611da2565b565b61118d6040518060400160405280601e81526020017f7365744d696e416d6f756e74546f436f6e766572742875696e74323536290000815250611734565b600081116111ad5760405162461bcd60e51b81526004016104879061299b565b61013080549082905560408051828152602081018490527fada67d0d38fa20c8ae6a5c17cb9d60b0fe7f2d4e4f27ac9ee55e54ac88de9d8d91015b60405180910390a15050565b6111fc611505565b6112058161161d565b61012e80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907fb6e5fcf02f7fbb8acfbaa3bac4fd5abf9ff51e3f2e8884b5498927179b211b2890600090a35050565b60655433906001600160a01b031681146112c65760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b6064820152608401610487565b61064381611da2565b6112d7611505565b6112e08161161d565b60cb80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907fa87b964d321035d2165e484ff4b722dd6eae30606c0b98887d2ed1a34e594bfe90600090a35050565b61133a611505565b6106438161169a565b6000816001600160a01b0316627e3dd26040518163ffffffff1660e01b8152600401602060405180830381865afa158015611382573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113a69190612bbc565b6114015760405162461bcd60e51b815260206004820152602660248201527f5269736b2046756e643a20436f6d7074726f6c6c6572206164647265737320696044820152651b9d985b1a5960d21b6064820152608401610487565b506001600160a01b03908116600090815260ca6020908152604080832061012d549094168352929052205490565b6114398282611dbb565b5050565b611445611505565b606580546001600160a01b0383166001600160a01b031990911681179091556114766033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b179052611500908490612078565b505050565b6033546001600160a01b0316331461114d5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610487565b6001600160a01b0381166115c35760405162461bcd60e51b815260206004820152602560248201527f696e76616c696420616365737320636f6e74726f6c206d616e61676572206164604482015264647265737360d81b6064820152608401610487565b609780546001600160a01b038381166001600160a01b031983168117909355604080519190921680825260208201939093527f66fd58e82f7b31a2a5c30e0888f3093efe4e111b00cd2b0c31fe014601293aa091016111e8565b6001600160a01b038116610643576040516342bcdf7f60e11b815260040160405180910390fd5b600054610100900460ff1661166b5760405162461bcd60e51b815260040161048790612d5e565b61114d61214d565b600054610100900460ff1661063a5760405162461bcd60e51b815260040161048790612d5e565b60fb5481116116f65760405162461bcd60e51b815260206004820152602260248201527f436f6d7074726f6c6c65723a20496e76616c6964206d61784c6f6f70734c696d6044820152611a5d60f21b6064820152608401610487565b60fb80549082905560408051828152602081018490527fc2d09fef144f7c8a86f71ea459f8fc17f675768eb1ae369cbd77fb31d467aafa91016111e8565b6097546040516318c5e8ab60e01b81526000916001600160a01b0316906318c5e8ab906117679033908690600401612dd5565b602060405180830381865afa158015611784573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117a89190612bbc565b90508061143957333083604051634a3fa29360e01b815260040161048793929190612df9565b60fb548111156106435760fb5460405163792bfb1b60e11b8152600481019190915260248101829052604401610487565b6000836000036118775760405162461bcd60e51b815260206004820152603c60248201527f5269736b46756e643a20616d6f756e744f75744d696e206d757374206265206760448201527f726561746572207468616e203020746f20737761702076546f6b656e000000006064820152608401610487565b600080876001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa1580156118b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118dc91906129f9565b61012d546001600160a01b03898116600090815260ca60209081526040808320848716845290915281205493945091169190819003611922576000945050505050611d99565b6000896001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa158015611962573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061198691906129f9565b60405163b62cad6960e01b81526001600160a01b0385811660048301529192509082169063b62cad6990602401600060405180830381600087803b1580156119cd57600080fd5b505af11580156119e1573d6000803e3d6000fd5b50506040805160208101918290526341976e0960e01b9091526001600160a01b03868116602483015260009350909150819084166341976e0960448301602060405180830381865afa158015611a3b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a5f9190612982565b905290506000611a6f828c61217d565b905061013054811015611ad25760405162461bcd60e51b815260206004820152602560248201527f5269736b46756e643a206d696e416d6f756e74546f436f6e766572742076696f6044820152641b185d195960da1b6064820152608401610487565b6001600160a01b038616600090815260c9602052604081208054869290611afa908490612e25565b90915550506001600160a01b03808d16600090815260ca60209081526040808320938a1683529290529081208054869290611b36908490612e25565b90915550506001600160a01b0386811690861614611d8b57856001600160a01b03168a8a6000818110611b6b57611b6b6129e3565b9050602002016020810190611b8091906127a5565b6001600160a01b031614611bfc5760405162461bcd60e51b815260206004820152603860248201527f5269736b46756e643a20737761702070617468206d757374207374617274207760448201527f6974682074686520756e6465726c79696e6720617373657400000000000000006064820152608401610487565b6001600160a01b0385168a8a611c13600182612e25565b818110611c2257611c226129e3565b9050602002016020810190611c3791906127a5565b6001600160a01b031614611cab5760405162461bcd60e51b815260206004820152603560248201527f5269736b46756e643a2066696e616c6c792070617468206d75737420626520636044820152741bdb9d995c9d1a589b194818985cd948185cdcd95d605a1b6064820152608401610487565b61012f546001600160a01b0390811690611cc990881682600061219d565b611cdd6001600160a01b038816828761219d565b6000816001600160a01b03166338ed1739878f8f8f30426040518763ffffffff1660e01b8152600401611d1596959493929190612e3c565b6000604051808303816000875af1158015611d34573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611d5c9190810190612e9e565b905080611d6a60018d612e25565b81518110611d7a57611d7a6129e3565b602002602001015198505050611d8f565b8396505b5094955050505050505b95945050505050565b606580546001600160a01b031916905561064381612289565b611dc48161161d565b816001600160a01b0316627e3dd26040518163ffffffff1660e01b8152600401602060405180830381865afa158015611e01573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e259190612bbc565b611e415760405162461bcd60e51b815260040161048790612d13565b60cb546001600160a01b031680611eb35760405162461bcd60e51b815260206004820152603060248201527f5265736572766548656c706572733a20506f6f6c20526567697374727920616460448201526f191c995cdcc81a5cc81b9bdd081cd95d60821b6064820152608401610487565b611ebd83836122db565b611f245760405162461bcd60e51b815260206004820152603260248201527f5265736572766548656c706572733a2054686520706f6f6c20646f65736e2774604482015271081cdd5c1c1bdc9d081d1a1948185cdcd95d60721b6064820152608401610487565b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa158015611f6b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f8f9190612982565b6001600160a01b038416600090815260c9602052604090205490915080821115612071576001600160a01b038416600090815260c960205260408120805483850392839291611fdf908490612c3e565b90915550506001600160a01b03808716600090815260ca602090815260408083209389168352929052908120805483929061201b908490612c3e565b92505081905550846001600160a01b0316866001600160a01b03167fc39e3e80c0219fde334a8cb5d8468b628482e23388b6e809c90cb00c63c8ce388360405161206791815260200190565b60405180910390a3505b5050505050565b60006120cd826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166123af9092919063ffffffff16565b90508051600014806120ee5750808060200190518101906120ee9190612bbc565b6115005760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610487565b600054610100900460ff166121745760405162461bcd60e51b815260040161048790612d5e565b61114d33611da2565b60008061218a84846123be565b9050612195816123ef565b949350505050565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663095ea7b360e01b1790529151909160009182918716906121fb908590612f29565b6000604051808303816000865af19150503d8060008114612238576040519150601f19603f3d011682016040523d82523d6000602084013e61223d565b606091505b509150915081158061226b575080511580159061226b5750808060200190518101906122699190612bbc565b155b156109c057604051633e3f8f7360e01b815260040160405180910390fd5b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316836001600160a01b0316036123265761231f82612407565b9050611135565b60cb5460405163266e0a7f60e01b81526001600160a01b0385811660048301528481166024830152600092169063266e0a7f90604401602060405180830381865afa158015612379573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061239d91906129f9565b6001600160a01b031614159392505050565b606061219584846000856125d8565b60408051602081019091526000815260405180602001604052806123e68560000151856126b3565b90529392505050565b805160009061113590670de0b6b3a764000090612f45565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b0772d0b6040518163ffffffff1660e01b8152600401600060405180830381865afa158015612468573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526124909190810190612f67565b905060005b81518110156125d1578181815181106124b0576124b06129e3565b60200260200101516001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03161461258457836001600160a01b031682828151811061250c5761250c6129e3565b60200260200101516001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa158015612551573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061257591906129f9565b6001600160a01b0316146125ba565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316846001600160a01b0316145b9250826125d1576125ca81612c56565b9050612495565b5050919050565b6060824710156126395760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610487565b600080866001600160a01b031685876040516126559190612f29565b60006040518083038185875af1925050503d8060008114612692576040519150601f19603f3d011682016040523d82523d6000602084013e612697565b606091505b50915091506126a8878383876126c6565b979650505050505050565b60006126bf8284612ff6565b9392505050565b6060831561273557825160000361272e576001600160a01b0385163b61272e5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610487565b5081612195565b612195838381511561274a5781518083602001fd5b8060405162461bcd60e51b81526004016104879190613015565b6001600160a01b038116811461064357600080fd5b6000806040838503121561278c57600080fd5b823561279781612764565b946020939093013593505050565b6000602082840312156127b757600080fd5b81356126bf81612764565b600080604083850312156127d557600080fd5b82356127e081612764565b915060208301356127f081612764565b809150509250929050565b600080600080600060a0868803121561281357600080fd5b853561281e81612764565b945060208601359350604086013561283581612764565b9250606086013561284581612764565b949793965091946080013592915050565b60008083601f84011261286857600080fd5b50813567ffffffffffffffff81111561288057600080fd5b6020830191508360208260051b850101111561289b57600080fd5b9250929050565b60008060008060008060006080888a0312156128bd57600080fd5b873567ffffffffffffffff808211156128d557600080fd5b6128e18b838c01612856565b909950975060208a01359150808211156128fa57600080fd5b6129068b838c01612856565b909750955060408a013591508082111561291f57600080fd5b5061292c8a828b01612856565b989b979a50959894979596606090950135949350505050565b60006020828403121561295757600080fd5b5035919050565b6020808252600a90820152691c994b595b9d195c995960b21b604082015260600190565b60006020828403121561299457600080fd5b5051919050565b60208082526028908201527f5269736b2046756e643a20496e76616c6964206d696e20616d6f756e7420746f6040820152670818dbdb9d995c9d60c21b606082015260800190565b634e487b7160e01b600052603260045260246000fd5b600060208284031215612a0b57600080fd5b81516126bf81612764565b634e487b7160e01b600052604160045260246000fd5b60405160a0810167ffffffffffffffff81118282101715612a4f57612a4f612a16565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715612a7e57612a7e612a16565b604052919050565b60005b83811015612aa1578181015183820152602001612a89565b83811115612ab0576000848401525b50505050565b8051612ac181612764565b919050565b60006020808385031215612ad957600080fd5b825167ffffffffffffffff80821115612af157600080fd5b9084019060a08287031215612b0557600080fd5b612b0d612a2c565b825182811115612b1c57600080fd5b8301601f81018813612b2d57600080fd5b805183811115612b3f57612b3f612a16565b612b51601f8201601f19168701612a55565b93508084528886828401011115612b6757600080fd5b612b7681878601888501612a86565b5050818152612b86848401612ab6565b84820152612b9660408401612ab6565b604082015260608301516060820152608083015160808201528094505050505092915050565b600060208284031215612bce57600080fd5b815180151581146126bf57600080fd5b6000808335601e19843603018112612bf557600080fd5b83018035915067ffffffffffffffff821115612c1057600080fd5b6020019150600581901b360382131561289b57600080fd5b634e487b7160e01b600052601160045260246000fd5b60008219821115612c5157612c51612c28565b500190565b600060018201612c6857612c68612c28565b5060010190565b8183526000602080850194508260005b85811015612cad578135612c9281612764565b6001600160a01b031687529582019590820190600101612c7f565b509495945050505050565b606081526000612ccc606083018789612c6f565b82810360208401528481526001600160fb1b03851115612ceb57600080fd5b8460051b80876020840137600091016020019081526040929092019290925295945050505050565b6020808252602b908201527f5265736572766548656c706572733a20436f6d7074726f6c6c6572206164647260408201526a195cdcc81a5b9d985b1a5960aa1b606082015260800190565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b60008151808452612dc1816020860160208601612a86565b601f01601f19169290920160200192915050565b6001600160a01b038316815260406020820181905260009061219590830184612da9565b6001600160a01b03848116825283166020820152606060408201819052600090611d9990830184612da9565b600082821015612e3757612e37612c28565b500390565b86815285602082015260a060408201526000612e5c60a083018688612c6f565b6001600160a01b039490941660608301525060800152949350505050565b600067ffffffffffffffff821115612e9457612e94612a16565b5060051b60200190565b60006020808385031215612eb157600080fd5b825167ffffffffffffffff811115612ec857600080fd5b8301601f81018513612ed957600080fd5b8051612eec612ee782612e7a565b612a55565b81815260059190911b82018301908381019087831115612f0b57600080fd5b928401925b828410156126a857835182529284019290840190612f10565b60008251612f3b818460208701612a86565b9190910192915050565b600082612f6257634e487b7160e01b600052601260045260246000fd5b500490565b60006020808385031215612f7a57600080fd5b825167ffffffffffffffff811115612f9157600080fd5b8301601f81018513612fa257600080fd5b8051612fb0612ee782612e7a565b81815260059190911b82018301908381019087831115612fcf57600080fd5b928401925b828410156126a8578351612fe781612764565b82529284019290840190612fd4565b600081600019048311821515161561301057613010612c28565b500290565b6020815260006126bf6020830184612da956fe73776170506f6f6c7341737365747328616464726573735b5d2c75696e743235365b5d2c616464726573735b5d5b5d2c75696e7432353629a2646970667358221220c967afe4ee07c007702bfe8b40ad090042c372456a0a152775ad412949fc6bc564736f6c634300080d0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101da5760003560e01c806377d4937f11610104578063afcff50f116100a2578063e30c397811610071578063e30c39781461040e578063f2fde38b1461041f578063fa7b81a014610432578063fe3da9841461045957600080fd5b8063afcff50f146103cd578063b4a0bdf3146103e0578063be26317e146103f1578063c8ecc0d3146103fa57600080fd5b806380d45a2d116100de57806380d45a2d146103835780638da5cb5b14610396578063a69bd19e146103a7578063aac59a75146103ba57600080fd5b806377d4937f1461035557806379ba5097146103685780637b77cd6a1461037057600080fd5b80633421fc521161017c5780635f30e37b1161014b5780635f30e37b146103145780636fb0527514610327578063715018a61461033a578063746460a91461034257600080fd5b80633421fc5214610293578063362b6795146102ba578063439b5517146102e15780634dd9584a1461030157600080fd5b806324558995116101b85780632455899514610246578063258836fe1461025a5780632a1d05471461026d5780632e6881411461028057600080fd5b80630a9837c5146101df5780630e32cb861461020557806319b1faef1461021a575b600080fd5b6101f26101ed366004612779565b610463565b6040519081526020015b60405180910390f35b6102186102133660046127a5565b610632565b005b61012e5461022e906001600160a01b031681565b6040516001600160a01b0390911681526020016101fc565b61012f5461022e906001600160a01b031681565b6102186102683660046127c2565b610646565b61021861027b3660046127fb565b6107d7565b61021861028e3660046127a5565b6109c8565b61022e7f000000000000000000000000000000000000000000000000000000000000000081565b61022e7f000000000000000000000000000000000000000000000000000000000000000081565b6101f26102ef3660046127a5565b60c96020526000908152604090205481565b61021861030f3660046127a5565b610acd565b6101f26103223660046128a2565b610b31565b6101f26103353660046127c2565b611085565b61021861113b565b610218610350366004612945565b61114f565b6102186103633660046127a5565b6111f4565b610218611258565b61021861037e3660046127a5565b6112cf565b610218610391366004612945565b611332565b6033546001600160a01b031661022e565b6101f26103b53660046127a5565b611343565b6102186103c83660046127c2565b61142f565b60cb5461022e906001600160a01b031681565b6097546001600160a01b031661022e565b6101f260fb5481565b61012d5461022e906001600160a01b031681565b6065546001600160a01b031661022e565b61021861042d3660046127a5565b61143d565b61022e7f000000000000000000000000000000000000000000000000000000000000000081565b6101f26101305481565b6000600260cc54036104905760405162461bcd60e51b81526004016104879061295e565b60405180910390fd5b600260cc5561012e546001600160a01b03163381146105085760405162461bcd60e51b815260206004820152602e60248201527f5269736b2066756e643a204f6e6c792063616c6c61626c652062792053686f7260448201526d1d19985b1b0818dbdb9d1c9858dd60921b6064820152608401610487565b6001600160a01b03808516600090815260ca6020908152604080832061012d549094168352929052205483111561058f5760405162461bcd60e51b815260206004820152602560248201527f5269736b2046756e643a20496e73756666696369656e7420706f6f6c2072657360448201526432b93b329760d91b6064820152608401610487565b6001600160a01b03808516600081815260ca6020908152604080832061012d80548716855290835281842080548a9003905554909416825260c990528290208054869003905590517fc8d0a37ed16dfaa43514df00e18f478b60d5cc7b4bfc687103948b9020f737fd906106069086815260200190565b60405180910390a261012d54610626906001600160a01b031682856114ae565b5050600160cc55919050565b61063a611505565b6106438161155f565b50565b61064e611505565b600260cc54036106705760405162461bcd60e51b81526004016104879061295e565b600260cc5561067e8161161d565b6040516370a0823160e01b815230600482015260009081906001600160a01b038516906370a0823190602401602060405180830381865afa1580156106c7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106eb9190612982565b6001600160a01b038516600090815260c9602052604090205490915081116107615760405162461bcd60e51b815260206004820152602360248201527f5265736572766548656c706572733a205a65726f20737572706c757320746f6b604482015262656e7360e81b6064820152608401610487565b6001600160a01b03848116600081815260c960209081526040918290205491519185038083529550928616927f6d25be279134f4ecaa4770aff0c3d916d9e7c5ef37b65ed95dbdba411f5d54d5910160405180910390a36107cc6001600160a01b03851684846114ae565b5050600160cc555050565b600054610100900460ff16158080156107f75750600054600160ff909116105b806108115750303b158015610811575060005460ff166001145b6108745760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610487565b6000805460ff191660011790558015610897576000805461ff0019166101001790555b6108a08661161d565b6108a98461161d565b600085116108c95760405162461bcd60e51b81526004016104879061299b565b600082116109285760405162461bcd60e51b815260206004820152602660248201527f5269736b2046756e643a204c6f6f7073206c696d69742063616e206e6f74206260448201526565207a65726f60d01b6064820152608401610487565b610930611644565b61093983611673565b61012f80546001600160a01b038089166001600160a01b03199283161790925561013087905561012d80549287169290911691909117905561097a8261169a565b80156109c0576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050565b610a066040518060400160405280602081526020017f736574436f6e7665727469626c65426173654173736574286164647265737329815250611734565b6001600160a01b038116610a7a5760405162461bcd60e51b815260206004820152603560248201527f5269736b2046756e643a206e657720636f6e7665727469626c65206261736520604482015274185cdcd95d081859191c995cdcc81a5b9d985b1a59605a1b6064820152608401610487565b61012d80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f5fa61583da12070720613fefdd68cc6c0e464a71e009742526bd2b2e0ac62cd290600090a35050565b610ad5611505565b610ade8161161d565b61012f80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907fd37b9d138f53ea58d7e50292588239a46efa8f523966febf4066da96defc77fd90600090a35050565b6000600260cc5403610b555760405162461bcd60e51b81526004016104879061295e565b600260cc81905550610b7e60405180606001604052806038815260200161302960389139611734565b42821015610bce5760405162461bcd60e51b815260206004820152601a60248201527f5269736b2066756e643a20646561646c696e65207061737365640000000000006044820152606401610487565b60cb546001600160a01b0316610be38161161d565b878614610c585760405162461bcd60e51b815260206004820152603860248201527f5269736b2066756e643a206d61726b65747320616e6420616d6f756e74734f7560448201527f744d696e2061726520756e657175616c206c656e6774687300000000000000006064820152608401610487565b878414610cc05760405162461bcd60e51b815260206004820152603060248201527f5269736b2066756e643a206d61726b65747320616e642070617468732061726560448201526f20756e657175616c206c656e6774687360801b6064820152608401610487565b600088610ccc816117ce565b60005b818110156110325760008c8c83818110610ceb57610ceb6129e3565b9050602002016020810190610d0091906127a5565b6001600160a01b0316635fe3b5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d3d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d6191906129f9565b604051637aee632d60e01b81526001600160a01b038083166004830152919250600091871690637aee632d90602401600060405180830381865afa158015610dad573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610dd59190810190612ac6565b9050816001600160a01b031681604001516001600160a01b031614610e4c5760405162461bcd60e51b815260206004820152602760248201527f636f6d7074726f6c6c657220646f65736e277420657869737420706f6f6c20726044820152666567697374727960c81b6064820152608401610487565b816001600160a01b0316633d98a1e58f8f86818110610e6d57610e6d6129e3565b9050602002016020810190610e8291906127a5565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa158015610ec6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610eea9190612bbc565b610f2d5760405162461bcd60e51b81526020600482015260146024820152731b585c9ad95d081a5cc81b9bdd081b1a5cdd195960621b6044820152606401610487565b6000610f9c8f8f86818110610f4457610f446129e3565b9050602002016020810190610f5991906127a5565b848f8f88818110610f6c57610f6c6129e3565b905060200201358e8e89818110610f8557610f856129e3565b9050602002810190610f979190612bde565b6117ff565b6001600160a01b03808516600090815260ca6020908152604080832061012d54909416835292905290812080549293508392909190610fdc908490612c3e565b909155505061012d546001600160a01b0316600090815260c960205260408120805483929061100c908490612c3e565b9091555061101c90508187612c3e565b95505050508061102b90612c56565b9050610ccf565b507fb17530966b045b50d4975e7f05048ca00d7335780c24f1c465165a4b94b2d37d8b8b8b8b8660405161106a959493929190612cb8565b60405180910390a150600160cc559998505050505050505050565b60006110908261161d565b826001600160a01b0316627e3dd26040518163ffffffff1660e01b8152600401602060405180830381865afa1580156110cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110f19190612bbc565b61110d5760405162461bcd60e51b815260040161048790612d13565b506001600160a01b03808316600090815260ca60209081526040808320938516835292905220545b92915050565b611143611505565b61114d6000611da2565b565b61118d6040518060400160405280601e81526020017f7365744d696e416d6f756e74546f436f6e766572742875696e74323536290000815250611734565b600081116111ad5760405162461bcd60e51b81526004016104879061299b565b61013080549082905560408051828152602081018490527fada67d0d38fa20c8ae6a5c17cb9d60b0fe7f2d4e4f27ac9ee55e54ac88de9d8d91015b60405180910390a15050565b6111fc611505565b6112058161161d565b61012e80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907fb6e5fcf02f7fbb8acfbaa3bac4fd5abf9ff51e3f2e8884b5498927179b211b2890600090a35050565b60655433906001600160a01b031681146112c65760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b6064820152608401610487565b61064381611da2565b6112d7611505565b6112e08161161d565b60cb80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907fa87b964d321035d2165e484ff4b722dd6eae30606c0b98887d2ed1a34e594bfe90600090a35050565b61133a611505565b6106438161169a565b6000816001600160a01b0316627e3dd26040518163ffffffff1660e01b8152600401602060405180830381865afa158015611382573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113a69190612bbc565b6114015760405162461bcd60e51b815260206004820152602660248201527f5269736b2046756e643a20436f6d7074726f6c6c6572206164647265737320696044820152651b9d985b1a5960d21b6064820152608401610487565b506001600160a01b03908116600090815260ca6020908152604080832061012d549094168352929052205490565b6114398282611dbb565b5050565b611445611505565b606580546001600160a01b0383166001600160a01b031990911681179091556114766033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b179052611500908490612078565b505050565b6033546001600160a01b0316331461114d5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610487565b6001600160a01b0381166115c35760405162461bcd60e51b815260206004820152602560248201527f696e76616c696420616365737320636f6e74726f6c206d616e61676572206164604482015264647265737360d81b6064820152608401610487565b609780546001600160a01b038381166001600160a01b031983168117909355604080519190921680825260208201939093527f66fd58e82f7b31a2a5c30e0888f3093efe4e111b00cd2b0c31fe014601293aa091016111e8565b6001600160a01b038116610643576040516342bcdf7f60e11b815260040160405180910390fd5b600054610100900460ff1661166b5760405162461bcd60e51b815260040161048790612d5e565b61114d61214d565b600054610100900460ff1661063a5760405162461bcd60e51b815260040161048790612d5e565b60fb5481116116f65760405162461bcd60e51b815260206004820152602260248201527f436f6d7074726f6c6c65723a20496e76616c6964206d61784c6f6f70734c696d6044820152611a5d60f21b6064820152608401610487565b60fb80549082905560408051828152602081018490527fc2d09fef144f7c8a86f71ea459f8fc17f675768eb1ae369cbd77fb31d467aafa91016111e8565b6097546040516318c5e8ab60e01b81526000916001600160a01b0316906318c5e8ab906117679033908690600401612dd5565b602060405180830381865afa158015611784573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117a89190612bbc565b90508061143957333083604051634a3fa29360e01b815260040161048793929190612df9565b60fb548111156106435760fb5460405163792bfb1b60e11b8152600481019190915260248101829052604401610487565b6000836000036118775760405162461bcd60e51b815260206004820152603c60248201527f5269736b46756e643a20616d6f756e744f75744d696e206d757374206265206760448201527f726561746572207468616e203020746f20737761702076546f6b656e000000006064820152608401610487565b600080876001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa1580156118b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118dc91906129f9565b61012d546001600160a01b03898116600090815260ca60209081526040808320848716845290915281205493945091169190819003611922576000945050505050611d99565b6000896001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa158015611962573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061198691906129f9565b60405163b62cad6960e01b81526001600160a01b0385811660048301529192509082169063b62cad6990602401600060405180830381600087803b1580156119cd57600080fd5b505af11580156119e1573d6000803e3d6000fd5b50506040805160208101918290526341976e0960e01b9091526001600160a01b03868116602483015260009350909150819084166341976e0960448301602060405180830381865afa158015611a3b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a5f9190612982565b905290506000611a6f828c61217d565b905061013054811015611ad25760405162461bcd60e51b815260206004820152602560248201527f5269736b46756e643a206d696e416d6f756e74546f436f6e766572742076696f6044820152641b185d195960da1b6064820152608401610487565b6001600160a01b038616600090815260c9602052604081208054869290611afa908490612e25565b90915550506001600160a01b03808d16600090815260ca60209081526040808320938a1683529290529081208054869290611b36908490612e25565b90915550506001600160a01b0386811690861614611d8b57856001600160a01b03168a8a6000818110611b6b57611b6b6129e3565b9050602002016020810190611b8091906127a5565b6001600160a01b031614611bfc5760405162461bcd60e51b815260206004820152603860248201527f5269736b46756e643a20737761702070617468206d757374207374617274207760448201527f6974682074686520756e6465726c79696e6720617373657400000000000000006064820152608401610487565b6001600160a01b0385168a8a611c13600182612e25565b818110611c2257611c226129e3565b9050602002016020810190611c3791906127a5565b6001600160a01b031614611cab5760405162461bcd60e51b815260206004820152603560248201527f5269736b46756e643a2066696e616c6c792070617468206d75737420626520636044820152741bdb9d995c9d1a589b194818985cd948185cdcd95d605a1b6064820152608401610487565b61012f546001600160a01b0390811690611cc990881682600061219d565b611cdd6001600160a01b038816828761219d565b6000816001600160a01b03166338ed1739878f8f8f30426040518763ffffffff1660e01b8152600401611d1596959493929190612e3c565b6000604051808303816000875af1158015611d34573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611d5c9190810190612e9e565b905080611d6a60018d612e25565b81518110611d7a57611d7a6129e3565b602002602001015198505050611d8f565b8396505b5094955050505050505b95945050505050565b606580546001600160a01b031916905561064381612289565b611dc48161161d565b816001600160a01b0316627e3dd26040518163ffffffff1660e01b8152600401602060405180830381865afa158015611e01573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e259190612bbc565b611e415760405162461bcd60e51b815260040161048790612d13565b60cb546001600160a01b031680611eb35760405162461bcd60e51b815260206004820152603060248201527f5265736572766548656c706572733a20506f6f6c20526567697374727920616460448201526f191c995cdcc81a5cc81b9bdd081cd95d60821b6064820152608401610487565b611ebd83836122db565b611f245760405162461bcd60e51b815260206004820152603260248201527f5265736572766548656c706572733a2054686520706f6f6c20646f65736e2774604482015271081cdd5c1c1bdc9d081d1a1948185cdcd95d60721b6064820152608401610487565b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa158015611f6b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f8f9190612982565b6001600160a01b038416600090815260c9602052604090205490915080821115612071576001600160a01b038416600090815260c960205260408120805483850392839291611fdf908490612c3e565b90915550506001600160a01b03808716600090815260ca602090815260408083209389168352929052908120805483929061201b908490612c3e565b92505081905550846001600160a01b0316866001600160a01b03167fc39e3e80c0219fde334a8cb5d8468b628482e23388b6e809c90cb00c63c8ce388360405161206791815260200190565b60405180910390a3505b5050505050565b60006120cd826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166123af9092919063ffffffff16565b90508051600014806120ee5750808060200190518101906120ee9190612bbc565b6115005760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610487565b600054610100900460ff166121745760405162461bcd60e51b815260040161048790612d5e565b61114d33611da2565b60008061218a84846123be565b9050612195816123ef565b949350505050565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663095ea7b360e01b1790529151909160009182918716906121fb908590612f29565b6000604051808303816000865af19150503d8060008114612238576040519150601f19603f3d011682016040523d82523d6000602084013e61223d565b606091505b509150915081158061226b575080511580159061226b5750808060200190518101906122699190612bbc565b155b156109c057604051633e3f8f7360e01b815260040160405180910390fd5b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316836001600160a01b0316036123265761231f82612407565b9050611135565b60cb5460405163266e0a7f60e01b81526001600160a01b0385811660048301528481166024830152600092169063266e0a7f90604401602060405180830381865afa158015612379573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061239d91906129f9565b6001600160a01b031614159392505050565b606061219584846000856125d8565b60408051602081019091526000815260405180602001604052806123e68560000151856126b3565b90529392505050565b805160009061113590670de0b6b3a764000090612f45565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b0772d0b6040518163ffffffff1660e01b8152600401600060405180830381865afa158015612468573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526124909190810190612f67565b905060005b81518110156125d1578181815181106124b0576124b06129e3565b60200260200101516001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03161461258457836001600160a01b031682828151811061250c5761250c6129e3565b60200260200101516001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa158015612551573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061257591906129f9565b6001600160a01b0316146125ba565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316846001600160a01b0316145b9250826125d1576125ca81612c56565b9050612495565b5050919050565b6060824710156126395760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610487565b600080866001600160a01b031685876040516126559190612f29565b60006040518083038185875af1925050503d8060008114612692576040519150601f19603f3d011682016040523d82523d6000602084013e612697565b606091505b50915091506126a8878383876126c6565b979650505050505050565b60006126bf8284612ff6565b9392505050565b6060831561273557825160000361272e576001600160a01b0385163b61272e5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610487565b5081612195565b612195838381511561274a5781518083602001fd5b8060405162461bcd60e51b81526004016104879190613015565b6001600160a01b038116811461064357600080fd5b6000806040838503121561278c57600080fd5b823561279781612764565b946020939093013593505050565b6000602082840312156127b757600080fd5b81356126bf81612764565b600080604083850312156127d557600080fd5b82356127e081612764565b915060208301356127f081612764565b809150509250929050565b600080600080600060a0868803121561281357600080fd5b853561281e81612764565b945060208601359350604086013561283581612764565b9250606086013561284581612764565b949793965091946080013592915050565b60008083601f84011261286857600080fd5b50813567ffffffffffffffff81111561288057600080fd5b6020830191508360208260051b850101111561289b57600080fd5b9250929050565b60008060008060008060006080888a0312156128bd57600080fd5b873567ffffffffffffffff808211156128d557600080fd5b6128e18b838c01612856565b909950975060208a01359150808211156128fa57600080fd5b6129068b838c01612856565b909750955060408a013591508082111561291f57600080fd5b5061292c8a828b01612856565b989b979a50959894979596606090950135949350505050565b60006020828403121561295757600080fd5b5035919050565b6020808252600a90820152691c994b595b9d195c995960b21b604082015260600190565b60006020828403121561299457600080fd5b5051919050565b60208082526028908201527f5269736b2046756e643a20496e76616c6964206d696e20616d6f756e7420746f6040820152670818dbdb9d995c9d60c21b606082015260800190565b634e487b7160e01b600052603260045260246000fd5b600060208284031215612a0b57600080fd5b81516126bf81612764565b634e487b7160e01b600052604160045260246000fd5b60405160a0810167ffffffffffffffff81118282101715612a4f57612a4f612a16565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715612a7e57612a7e612a16565b604052919050565b60005b83811015612aa1578181015183820152602001612a89565b83811115612ab0576000848401525b50505050565b8051612ac181612764565b919050565b60006020808385031215612ad957600080fd5b825167ffffffffffffffff80821115612af157600080fd5b9084019060a08287031215612b0557600080fd5b612b0d612a2c565b825182811115612b1c57600080fd5b8301601f81018813612b2d57600080fd5b805183811115612b3f57612b3f612a16565b612b51601f8201601f19168701612a55565b93508084528886828401011115612b6757600080fd5b612b7681878601888501612a86565b5050818152612b86848401612ab6565b84820152612b9660408401612ab6565b604082015260608301516060820152608083015160808201528094505050505092915050565b600060208284031215612bce57600080fd5b815180151581146126bf57600080fd5b6000808335601e19843603018112612bf557600080fd5b83018035915067ffffffffffffffff821115612c1057600080fd5b6020019150600581901b360382131561289b57600080fd5b634e487b7160e01b600052601160045260246000fd5b60008219821115612c5157612c51612c28565b500190565b600060018201612c6857612c68612c28565b5060010190565b8183526000602080850194508260005b85811015612cad578135612c9281612764565b6001600160a01b031687529582019590820190600101612c7f565b509495945050505050565b606081526000612ccc606083018789612c6f565b82810360208401528481526001600160fb1b03851115612ceb57600080fd5b8460051b80876020840137600091016020019081526040929092019290925295945050505050565b6020808252602b908201527f5265736572766548656c706572733a20436f6d7074726f6c6c6572206164647260408201526a195cdcc81a5b9d985b1a5960aa1b606082015260800190565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b60008151808452612dc1816020860160208601612a86565b601f01601f19169290920160200192915050565b6001600160a01b038316815260406020820181905260009061219590830184612da9565b6001600160a01b03848116825283166020820152606060408201819052600090611d9990830184612da9565b600082821015612e3757612e37612c28565b500390565b86815285602082015260a060408201526000612e5c60a083018688612c6f565b6001600160a01b039490941660608301525060800152949350505050565b600067ffffffffffffffff821115612e9457612e94612a16565b5060051b60200190565b60006020808385031215612eb157600080fd5b825167ffffffffffffffff811115612ec857600080fd5b8301601f81018513612ed957600080fd5b8051612eec612ee782612e7a565b612a55565b81815260059190911b82018301908381019087831115612f0b57600080fd5b928401925b828410156126a857835182529284019290840190612f10565b60008251612f3b818460208701612a86565b9190910192915050565b600082612f6257634e487b7160e01b600052601260045260246000fd5b500490565b60006020808385031215612f7a57600080fd5b825167ffffffffffffffff811115612f9157600080fd5b8301601f81018513612fa257600080fd5b8051612fb0612ee782612e7a565b81815260059190911b82018301908381019087831115612fcf57600080fd5b928401925b828410156126a8578351612fe781612764565b82529284019290840190612fd4565b600081600019048311821515161561301057613010612c28565b500290565b6020815260006126bf6020830184612da956fe73776170506f6f6c7341737365747328616464726573735b5d2c75696e743235365b5d2c616464726573735b5d5b5d2c75696e7432353629a2646970667358221220c967afe4ee07c007702bfe8b40ad090042c372456a0a152775ad412949fc6bc564736f6c634300080d0033", + "solcInputHash": "09e209110f36e8c9fe7ecc1925064673", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"corePoolComptroller_\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"vbnb_\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nativeWrapped_\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"ApproveFailed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"loopsLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requiredLoops\",\"type\":\"uint256\"}],\"name\":\"MaxLoopsLimitExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"calledContract\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"methodSignature\",\"type\":\"string\"}],\"name\":\"Unauthorized\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"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\":\"oldConvertibleBaseAsset\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newConvertibleBaseAsset\",\"type\":\"address\"}],\"name\":\"ConvertibleBaseAssetUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldMaxLoopsLimit\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newmaxLoopsLimit\",\"type\":\"uint256\"}],\"name\":\"MaxLoopsLimitUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldMinAmountToConvert\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newMinAmountToConvert\",\"type\":\"uint256\"}],\"name\":\"MinAmountToConvertUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldAccessControlManager\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newAccessControlManager\",\"type\":\"address\"}],\"name\":\"NewAccessControlManager\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferStarted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"oldPancakeSwapRouter\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newPancakeSwapRouter\",\"type\":\"address\"}],\"name\":\"PancakeSwapRouterUpdated\",\"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\":\"oldShortfallContract\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"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\":\"totalAmount\",\"type\":\"uint256\"}],\"name\":\"SwappedPoolsAssets\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"SweepToken\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"TransferredReserveForAuction\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"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\",\"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\"}],\"name\":\"assetsReserves\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"convertibleBaseAsset\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"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\":\"comptroller\",\"type\":\"address\"}],\"name\":\"getPoolsBaseAssetReserves\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"pancakeSwapRouter_\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmountToConvert_\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"convertibleBaseAsset_\",\"type\":\"address\"},{\"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\":\"minAmountToConvert\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pancakeSwapRouter\",\"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\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"accessControlManager_\",\"type\":\"address\"}],\"name\":\"setAccessControlManager\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_convertibleBaseAsset\",\"type\":\"address\"}],\"name\":\"setConvertibleBaseAsset\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"limit\",\"type\":\"uint256\"}],\"name\":\"setMaxLoopsLimit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minAmountToConvert_\",\"type\":\"uint256\"}],\"name\":\"setMinAmountToConvert\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"pancakeSwapRouter_\",\"type\":\"address\"}],\"name\":\"setPancakeSwapRouter\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"poolRegistry_\",\"type\":\"address\"}],\"name\":\"setPoolRegistry\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"shortfallContractAddress_\",\"type\":\"address\"}],\"name\":\"setShortfallContractAddress\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"shortfall\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"markets\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"amountsOutMin\",\"type\":\"uint256[]\"},{\"internalType\":\"address[][]\",\"name\":\"paths\",\"type\":\"address[][]\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"swapPoolsAssets\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"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\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transferReserveForAuction\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"}],\"name\":\"updateAssetsState\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Venus\",\"details\":\"This contract does not support BNB.\",\"kind\":\"dev\",\"methods\":{\"acceptOwnership()\":{\"details\":\"The new owner accepts the ownership transfer.\"},\"constructor\":{\"custom:oz-upgrades-unsafe-allow\":\"constructor\",\"details\":\"Note that the contract is upgradeable. Use initialize() or reinitializers to set the state variables.\"},\"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.\"}},\"getPoolsBaseAssetReserves(address)\":{\"params\":{\"comptroller\":\"Comptroller address(pool).\"},\"returns\":{\"_0\":\"Base Asset's reserve in risk fund.\"}},\"initialize(address,uint256,address,address,uint256)\":{\"custom:error\":\"ZeroAddressNotAllowed is thrown when PCS router address is zeroZeroAddressNotAllowed is thrown when convertible base asset address is zero\",\"params\":{\"accessControlManager_\":\"Address of the access control contract\",\"convertibleBaseAsset_\":\"Address of the base asset\",\"loopsLimit_\":\"Limit for the loops in the contract to avoid DOS\",\"minAmountToConvert_\":\"Minimum amount assets must be worth to convert into base asset\",\"pancakeSwapRouter_\":\"Address of the PancakeSwap router\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"pendingOwner()\":{\"details\":\"Returns the address of the pending owner.\"},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner.\"},\"setAccessControlManager(address)\":{\"custom:access\":\"Only Governance\",\"custom:event\":\"Emits NewAccessControlManager event\",\"details\":\"Admin function to set address of AccessControlManager\",\"params\":{\"accessControlManager_\":\"The new address of the AccessControlManager\"}},\"setConvertibleBaseAsset(address)\":{\"params\":{\"_convertibleBaseAsset\":\"Address for new convertible base asset.\"}},\"setMaxLoopsLimit(uint256)\":{\"params\":{\"limit\":\"Limit for the max loops can execute at a time\"}},\"setMinAmountToConvert(uint256)\":{\"params\":{\"minAmountToConvert_\":\"Min amount to convert.\"}},\"setPancakeSwapRouter(address)\":{\"custom:error\":\"ZeroAddressNotAllowed is thrown when PCS router address is zero\",\"params\":{\"pancakeSwapRouter_\":\"Address of the PancakeSwap router\"}},\"setPoolRegistry(address)\":{\"custom:error\":\"ZeroAddressNotAllowed is thrown when pool registry address is zero\",\"params\":{\"poolRegistry_\":\"Address of the pool registry\"}},\"setShortfallContractAddress(address)\":{\"custom:error\":\"ZeroAddressNotAllowed is thrown when shortfall contract address is zero\",\"params\":{\"shortfallContractAddress_\":\"Address of the auction contract\"}},\"swapPoolsAssets(address[],uint256[],address[][],uint256)\":{\"custom:error\":\"ZeroAddressNotAllowed is thrown if PoolRegistry contract address is not configured\",\"params\":{\"amountsOutMin\":\"Minimum amount to receive for swap\",\"deadline\":\"Deadline for the swap\",\"markets\":\"Array of vTokens whose assets to swap for base asset\",\"paths\":\"A path consisting of PCS token pairs for each swap\"},\"returns\":{\"_0\":\"Number of swapped tokens\"}},\"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.\"},\"transferReserveForAuction(address,uint256)\":{\"params\":{\"amount\":\"Amount to be transferred to auction contract.\",\"comptroller\":\"Comptroller of the pool.\"},\"returns\":{\"_0\":\"Number reserved tokens.\"}},\"updateAssetsState(address,address)\":{\"params\":{\"asset\":\"Asset address.\",\"comptroller\":\"Comptroller address(pool).\"}}},\"title\":\"RiskFund\",\"version\":1},\"userdoc\":{\"errors\":{\"ApproveFailed()\":[{\"notice\":\"Thrown if a contract is unable to approve a transfer\"}],\"MaxLoopsLimitExceeded(uint256,uint256)\":[{\"notice\":\"Thrown an error on maxLoopsLimit exceeds for any loop\"}],\"Unauthorized(address,address,string)\":[{\"notice\":\"Thrown when the action is prohibited by AccessControlManager\"}],\"ZeroAddressNotAllowed()\":[{\"notice\":\"Thrown if the supplied address is a zero address where it is not allowed\"}]},\"events\":{\"AssetsReservesUpdated(address,address,uint256)\":{\"notice\":\"Event emitted after the update of the assets reserves.\"},\"ConvertibleBaseAssetUpdated(address,address)\":{\"notice\":\"Emitted when convertible base asset is updated\"},\"MaxLoopsLimitUpdated(uint256,uint256)\":{\"notice\":\"Emitted when max loops limit is set\"},\"MinAmountToConvertUpdated(uint256,uint256)\":{\"notice\":\"Emitted when minimum amount to convert is updated\"},\"NewAccessControlManager(address,address)\":{\"notice\":\"Emitted when access control manager contract address is changed\"},\"PancakeSwapRouterUpdated(address,address)\":{\"notice\":\"Emitted when PancakeSwap router contract address is updated\"},\"PoolRegistryUpdated(address,address)\":{\"notice\":\"Emitted when pool registry address is updated\"},\"ShortfallContractUpdated(address,address)\":{\"notice\":\"Emitted when shortfall contract address is updated\"},\"SwappedPoolsAssets(address[],uint256[],uint256)\":{\"notice\":\"Emitted when pools assets are swapped\"},\"SweepToken(address,address,uint256)\":{\"notice\":\"event emitted on sweep token success\"},\"TransferredReserveForAuction(address,uint256)\":{\"notice\":\"Emitted when reserves are transferred for auction\"}},\"kind\":\"user\",\"methods\":{\"accessControlManager()\":{\"notice\":\"Returns the address of the access control manager contract\"},\"getPoolAssetReserve(address,address)\":{\"notice\":\"Get the Amount of the asset in the risk fund for the specific pool.\"},\"getPoolsBaseAssetReserves(address)\":{\"notice\":\"Get the Amount of the Base asset in the risk fund for the specific pool.\"},\"initialize(address,uint256,address,address,uint256)\":{\"notice\":\"Initializes the deployer to owner.\"},\"setAccessControlManager(address)\":{\"notice\":\"Sets the address of AccessControlManager\"},\"setConvertibleBaseAsset(address)\":{\"notice\":\"Sets a new convertible base asset\"},\"setMaxLoopsLimit(uint256)\":{\"notice\":\"Set the limit for the loops can iterate to avoid the DOS\"},\"setMinAmountToConvert(uint256)\":{\"notice\":\"Min amount to convert setter\"},\"setPancakeSwapRouter(address)\":{\"notice\":\"PancakeSwap router address setter\"},\"setPoolRegistry(address)\":{\"notice\":\"Pool registry setter\"},\"setShortfallContractAddress(address)\":{\"notice\":\"Shortfall contract address setter\"},\"swapPoolsAssets(address[],uint256[],address[][],uint256)\":{\"notice\":\"Swap array of pool assets into base asset's tokens of at least a minimum amount\"},\"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\"},\"transferReserveForAuction(address,uint256)\":{\"notice\":\"Transfer tokens for auction.\"},\"updateAssetsState(address,address)\":{\"notice\":\"Update the reserve of the asset for the specific pool after transferring to risk fund.\"}},\"notice\":\"Contract with basic features to track/hold different assets for different Comptrollers.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/RiskFund/RiskFund.sol\":\"RiskFund\"},\"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(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 \\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\":\"0xef1ca0adc3ce1ff540279d424953087771b4a07470caac99777fafd2ceea38a9\",\"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 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(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/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\",\"keccak256\":\"0x7e4d140bd2a5671389ad7a3975b65d05a4f750daf6a61c16139d123d9782b96e\",\"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/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/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\",\"keccak256\":\"0x7aefc03f77721f91f13d0bce91d53085b799443f7ef41b975ac6205b2c15d982\",\"license\":\"BSD-3-Clause\"},\"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\",\"keccak256\":\"0x918526b067c834935f5dd0788139e1a73c64cbf6f8b7d6fd43242eaa93aa7f37\",\"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(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 \\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 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 \\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(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\",\"keccak256\":\"0xcda9eb71f6ceb8a4c3bfbc1c42d72e2f0523d30f6d3252fbd90819e953640fe5\",\"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(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\":\"0x2947e95eb97a3a45f90ec36d4fd5a4cbb9409319f6ad000e950550055a3f2324\",\"license\":\"BSD-3-Clause\"},\"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\",\"keccak256\":\"0x9bbc31c80a4c537ddfd06cbd03a412ba64842a708381fbc4bf2e33ef56c92b4d\",\"license\":\"MIT\"},\"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": "0x60e06040523480156200001157600080fd5b50604051620032b8380380620032b883398101604081905262000034916200018c565b828282620000428362000083565b6200004d8262000083565b620000588162000083565b6001600160a01b0392831660805290821660a0521660c0526200007a620000ae565b505050620001d6565b6001600160a01b038116620000ab576040516342bcdf7f60e11b815260040160405180910390fd5b50565b600054610100900460ff16156200011b5760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b60005460ff908116146200016d576000805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b80516001600160a01b03811681146200018757600080fd5b919050565b600080600060608486031215620001a257600080fd5b620001ad846200016f565b9250620001bd602085016200016f565b9150620001cd604085016200016f565b90509250925092565b60805160a05160c05161309662000222600039600081816102bf015261258601526000818161029801526124c3015260008181610437015281816122df015261240c01526130966000f3fe608060405234801561001057600080fd5b50600436106101da5760003560e01c806377d4937f11610104578063afcff50f116100a2578063e30c397811610071578063e30c39781461040e578063f2fde38b1461041f578063fa7b81a014610432578063fe3da9841461045957600080fd5b8063afcff50f146103cd578063b4a0bdf3146103e0578063be26317e146103f1578063c8ecc0d3146103fa57600080fd5b806380d45a2d116100de57806380d45a2d146103835780638da5cb5b14610396578063a69bd19e146103a7578063aac59a75146103ba57600080fd5b806377d4937f1461035557806379ba5097146103685780637b77cd6a1461037057600080fd5b80633421fc521161017c5780635f30e37b1161014b5780635f30e37b146103145780636fb0527514610327578063715018a61461033a578063746460a91461034257600080fd5b80633421fc5214610293578063362b6795146102ba578063439b5517146102e15780634dd9584a1461030157600080fd5b806324558995116101b85780632455899514610246578063258836fe1461025a5780632a1d05471461026d5780632e6881411461028057600080fd5b80630a9837c5146101df5780630e32cb861461020557806319b1faef1461021a575b600080fd5b6101f26101ed366004612779565b610463565b6040519081526020015b60405180910390f35b6102186102133660046127a5565b610632565b005b61012e5461022e906001600160a01b031681565b6040516001600160a01b0390911681526020016101fc565b61012f5461022e906001600160a01b031681565b6102186102683660046127c2565b610646565b61021861027b3660046127fb565b6107d7565b61021861028e3660046127a5565b6109c8565b61022e7f000000000000000000000000000000000000000000000000000000000000000081565b61022e7f000000000000000000000000000000000000000000000000000000000000000081565b6101f26102ef3660046127a5565b60c96020526000908152604090205481565b61021861030f3660046127a5565b610acd565b6101f26103223660046128a2565b610b31565b6101f26103353660046127c2565b611085565b61021861113b565b610218610350366004612945565b61114f565b6102186103633660046127a5565b6111f4565b610218611258565b61021861037e3660046127a5565b6112cf565b610218610391366004612945565b611332565b6033546001600160a01b031661022e565b6101f26103b53660046127a5565b611343565b6102186103c83660046127c2565b61142f565b60cb5461022e906001600160a01b031681565b6097546001600160a01b031661022e565b6101f260fb5481565b61012d5461022e906001600160a01b031681565b6065546001600160a01b031661022e565b61021861042d3660046127a5565b61143d565b61022e7f000000000000000000000000000000000000000000000000000000000000000081565b6101f26101305481565b6000600260cc54036104905760405162461bcd60e51b81526004016104879061295e565b60405180910390fd5b600260cc5561012e546001600160a01b03163381146105085760405162461bcd60e51b815260206004820152602e60248201527f5269736b2066756e643a204f6e6c792063616c6c61626c652062792053686f7260448201526d1d19985b1b0818dbdb9d1c9858dd60921b6064820152608401610487565b6001600160a01b03808516600090815260ca6020908152604080832061012d549094168352929052205483111561058f5760405162461bcd60e51b815260206004820152602560248201527f5269736b2046756e643a20496e73756666696369656e7420706f6f6c2072657360448201526432b93b329760d91b6064820152608401610487565b6001600160a01b03808516600081815260ca6020908152604080832061012d80548716855290835281842080548a9003905554909416825260c990528290208054869003905590517fc8d0a37ed16dfaa43514df00e18f478b60d5cc7b4bfc687103948b9020f737fd906106069086815260200190565b60405180910390a261012d54610626906001600160a01b031682856114ae565b5050600160cc55919050565b61063a611505565b6106438161155f565b50565b61064e611505565b600260cc54036106705760405162461bcd60e51b81526004016104879061295e565b600260cc5561067e8161161d565b6040516370a0823160e01b815230600482015260009081906001600160a01b038516906370a0823190602401602060405180830381865afa1580156106c7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106eb9190612982565b6001600160a01b038516600090815260c9602052604090205490915081116107615760405162461bcd60e51b815260206004820152602360248201527f5265736572766548656c706572733a205a65726f20737572706c757320746f6b604482015262656e7360e81b6064820152608401610487565b6001600160a01b03848116600081815260c960209081526040918290205491519185038083529550928616927f6d25be279134f4ecaa4770aff0c3d916d9e7c5ef37b65ed95dbdba411f5d54d5910160405180910390a36107cc6001600160a01b03851684846114ae565b5050600160cc555050565b600054610100900460ff16158080156107f75750600054600160ff909116105b806108115750303b158015610811575060005460ff166001145b6108745760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610487565b6000805460ff191660011790558015610897576000805461ff0019166101001790555b6108a08661161d565b6108a98461161d565b600085116108c95760405162461bcd60e51b81526004016104879061299b565b600082116109285760405162461bcd60e51b815260206004820152602660248201527f5269736b2046756e643a204c6f6f7073206c696d69742063616e206e6f74206260448201526565207a65726f60d01b6064820152608401610487565b610930611644565b61093983611673565b61012f80546001600160a01b038089166001600160a01b03199283161790925561013087905561012d80549287169290911691909117905561097a8261169a565b80156109c0576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050565b610a066040518060400160405280602081526020017f736574436f6e7665727469626c65426173654173736574286164647265737329815250611734565b6001600160a01b038116610a7a5760405162461bcd60e51b815260206004820152603560248201527f5269736b2046756e643a206e657720636f6e7665727469626c65206261736520604482015274185cdcd95d081859191c995cdcc81a5b9d985b1a59605a1b6064820152608401610487565b61012d80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f5fa61583da12070720613fefdd68cc6c0e464a71e009742526bd2b2e0ac62cd290600090a35050565b610ad5611505565b610ade8161161d565b61012f80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907fd37b9d138f53ea58d7e50292588239a46efa8f523966febf4066da96defc77fd90600090a35050565b6000600260cc5403610b555760405162461bcd60e51b81526004016104879061295e565b600260cc81905550610b7e60405180606001604052806038815260200161302960389139611734565b42821015610bce5760405162461bcd60e51b815260206004820152601a60248201527f5269736b2066756e643a20646561646c696e65207061737365640000000000006044820152606401610487565b60cb546001600160a01b0316610be38161161d565b878614610c585760405162461bcd60e51b815260206004820152603860248201527f5269736b2066756e643a206d61726b65747320616e6420616d6f756e74734f7560448201527f744d696e2061726520756e657175616c206c656e6774687300000000000000006064820152608401610487565b878414610cc05760405162461bcd60e51b815260206004820152603060248201527f5269736b2066756e643a206d61726b65747320616e642070617468732061726560448201526f20756e657175616c206c656e6774687360801b6064820152608401610487565b600088610ccc816117ce565b60005b818110156110325760008c8c83818110610ceb57610ceb6129e3565b9050602002016020810190610d0091906127a5565b6001600160a01b0316635fe3b5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d3d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d6191906129f9565b604051637aee632d60e01b81526001600160a01b038083166004830152919250600091871690637aee632d90602401600060405180830381865afa158015610dad573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610dd59190810190612ac6565b9050816001600160a01b031681604001516001600160a01b031614610e4c5760405162461bcd60e51b815260206004820152602760248201527f636f6d7074726f6c6c657220646f65736e277420657869737420706f6f6c20726044820152666567697374727960c81b6064820152608401610487565b816001600160a01b0316633d98a1e58f8f86818110610e6d57610e6d6129e3565b9050602002016020810190610e8291906127a5565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa158015610ec6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610eea9190612bbc565b610f2d5760405162461bcd60e51b81526020600482015260146024820152731b585c9ad95d081a5cc81b9bdd081b1a5cdd195960621b6044820152606401610487565b6000610f9c8f8f86818110610f4457610f446129e3565b9050602002016020810190610f5991906127a5565b848f8f88818110610f6c57610f6c6129e3565b905060200201358e8e89818110610f8557610f856129e3565b9050602002810190610f979190612bde565b6117ff565b6001600160a01b03808516600090815260ca6020908152604080832061012d54909416835292905290812080549293508392909190610fdc908490612c3e565b909155505061012d546001600160a01b0316600090815260c960205260408120805483929061100c908490612c3e565b9091555061101c90508187612c3e565b95505050508061102b90612c56565b9050610ccf565b507fb17530966b045b50d4975e7f05048ca00d7335780c24f1c465165a4b94b2d37d8b8b8b8b8660405161106a959493929190612cb8565b60405180910390a150600160cc559998505050505050505050565b60006110908261161d565b826001600160a01b0316627e3dd26040518163ffffffff1660e01b8152600401602060405180830381865afa1580156110cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110f19190612bbc565b61110d5760405162461bcd60e51b815260040161048790612d13565b506001600160a01b03808316600090815260ca60209081526040808320938516835292905220545b92915050565b611143611505565b61114d6000611da2565b565b61118d6040518060400160405280601e81526020017f7365744d696e416d6f756e74546f436f6e766572742875696e74323536290000815250611734565b600081116111ad5760405162461bcd60e51b81526004016104879061299b565b61013080549082905560408051828152602081018490527fada67d0d38fa20c8ae6a5c17cb9d60b0fe7f2d4e4f27ac9ee55e54ac88de9d8d91015b60405180910390a15050565b6111fc611505565b6112058161161d565b61012e80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907fb6e5fcf02f7fbb8acfbaa3bac4fd5abf9ff51e3f2e8884b5498927179b211b2890600090a35050565b60655433906001600160a01b031681146112c65760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b6064820152608401610487565b61064381611da2565b6112d7611505565b6112e08161161d565b60cb80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907fa87b964d321035d2165e484ff4b722dd6eae30606c0b98887d2ed1a34e594bfe90600090a35050565b61133a611505565b6106438161169a565b6000816001600160a01b0316627e3dd26040518163ffffffff1660e01b8152600401602060405180830381865afa158015611382573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113a69190612bbc565b6114015760405162461bcd60e51b815260206004820152602660248201527f5269736b2046756e643a20436f6d7074726f6c6c6572206164647265737320696044820152651b9d985b1a5960d21b6064820152608401610487565b506001600160a01b03908116600090815260ca6020908152604080832061012d549094168352929052205490565b6114398282611dbb565b5050565b611445611505565b606580546001600160a01b0383166001600160a01b031990911681179091556114766033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b179052611500908490612078565b505050565b6033546001600160a01b0316331461114d5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610487565b6001600160a01b0381166115c35760405162461bcd60e51b815260206004820152602560248201527f696e76616c696420616365737320636f6e74726f6c206d616e61676572206164604482015264647265737360d81b6064820152608401610487565b609780546001600160a01b038381166001600160a01b031983168117909355604080519190921680825260208201939093527f66fd58e82f7b31a2a5c30e0888f3093efe4e111b00cd2b0c31fe014601293aa091016111e8565b6001600160a01b038116610643576040516342bcdf7f60e11b815260040160405180910390fd5b600054610100900460ff1661166b5760405162461bcd60e51b815260040161048790612d5e565b61114d61214d565b600054610100900460ff1661063a5760405162461bcd60e51b815260040161048790612d5e565b60fb5481116116f65760405162461bcd60e51b815260206004820152602260248201527f436f6d7074726f6c6c65723a20496e76616c6964206d61784c6f6f70734c696d6044820152611a5d60f21b6064820152608401610487565b60fb80549082905560408051828152602081018490527fc2d09fef144f7c8a86f71ea459f8fc17f675768eb1ae369cbd77fb31d467aafa91016111e8565b6097546040516318c5e8ab60e01b81526000916001600160a01b0316906318c5e8ab906117679033908690600401612dd5565b602060405180830381865afa158015611784573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117a89190612bbc565b90508061143957333083604051634a3fa29360e01b815260040161048793929190612df9565b60fb548111156106435760fb5460405163792bfb1b60e11b8152600481019190915260248101829052604401610487565b6000836000036118775760405162461bcd60e51b815260206004820152603c60248201527f5269736b46756e643a20616d6f756e744f75744d696e206d757374206265206760448201527f726561746572207468616e203020746f20737761702076546f6b656e000000006064820152608401610487565b600080876001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa1580156118b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118dc91906129f9565b61012d546001600160a01b03898116600090815260ca60209081526040808320848716845290915281205493945091169190819003611922576000945050505050611d99565b6000896001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa158015611962573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061198691906129f9565b60405163b62cad6960e01b81526001600160a01b0385811660048301529192509082169063b62cad6990602401600060405180830381600087803b1580156119cd57600080fd5b505af11580156119e1573d6000803e3d6000fd5b50506040805160208101918290526341976e0960e01b9091526001600160a01b03868116602483015260009350909150819084166341976e0960448301602060405180830381865afa158015611a3b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a5f9190612982565b905290506000611a6f828c61217d565b905061013054811015611ad25760405162461bcd60e51b815260206004820152602560248201527f5269736b46756e643a206d696e416d6f756e74546f436f6e766572742076696f6044820152641b185d195960da1b6064820152608401610487565b6001600160a01b038616600090815260c9602052604081208054869290611afa908490612e25565b90915550506001600160a01b03808d16600090815260ca60209081526040808320938a1683529290529081208054869290611b36908490612e25565b90915550506001600160a01b0386811690861614611d8b57856001600160a01b03168a8a6000818110611b6b57611b6b6129e3565b9050602002016020810190611b8091906127a5565b6001600160a01b031614611bfc5760405162461bcd60e51b815260206004820152603860248201527f5269736b46756e643a20737761702070617468206d757374207374617274207760448201527f6974682074686520756e6465726c79696e6720617373657400000000000000006064820152608401610487565b6001600160a01b0385168a8a611c13600182612e25565b818110611c2257611c226129e3565b9050602002016020810190611c3791906127a5565b6001600160a01b031614611cab5760405162461bcd60e51b815260206004820152603560248201527f5269736b46756e643a2066696e616c6c792070617468206d75737420626520636044820152741bdb9d995c9d1a589b194818985cd948185cdcd95d605a1b6064820152608401610487565b61012f546001600160a01b0390811690611cc990881682600061219d565b611cdd6001600160a01b038816828761219d565b6000816001600160a01b03166338ed1739878f8f8f30426040518763ffffffff1660e01b8152600401611d1596959493929190612e3c565b6000604051808303816000875af1158015611d34573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611d5c9190810190612e9e565b905080611d6a60018d612e25565b81518110611d7a57611d7a6129e3565b602002602001015198505050611d8f565b8396505b5094955050505050505b95945050505050565b606580546001600160a01b031916905561064381612289565b611dc48161161d565b816001600160a01b0316627e3dd26040518163ffffffff1660e01b8152600401602060405180830381865afa158015611e01573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e259190612bbc565b611e415760405162461bcd60e51b815260040161048790612d13565b60cb546001600160a01b031680611eb35760405162461bcd60e51b815260206004820152603060248201527f5265736572766548656c706572733a20506f6f6c20526567697374727920616460448201526f191c995cdcc81a5cc81b9bdd081cd95d60821b6064820152608401610487565b611ebd83836122db565b611f245760405162461bcd60e51b815260206004820152603260248201527f5265736572766548656c706572733a2054686520706f6f6c20646f65736e2774604482015271081cdd5c1c1bdc9d081d1a1948185cdcd95d60721b6064820152608401610487565b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa158015611f6b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f8f9190612982565b6001600160a01b038416600090815260c9602052604090205490915080821115612071576001600160a01b038416600090815260c960205260408120805483850392839291611fdf908490612c3e565b90915550506001600160a01b03808716600090815260ca602090815260408083209389168352929052908120805483929061201b908490612c3e565b92505081905550846001600160a01b0316866001600160a01b03167fc39e3e80c0219fde334a8cb5d8468b628482e23388b6e809c90cb00c63c8ce388360405161206791815260200190565b60405180910390a3505b5050505050565b60006120cd826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166123af9092919063ffffffff16565b90508051600014806120ee5750808060200190518101906120ee9190612bbc565b6115005760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610487565b600054610100900460ff166121745760405162461bcd60e51b815260040161048790612d5e565b61114d33611da2565b60008061218a84846123be565b9050612195816123ef565b949350505050565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663095ea7b360e01b1790529151909160009182918716906121fb908590612f29565b6000604051808303816000865af19150503d8060008114612238576040519150601f19603f3d011682016040523d82523d6000602084013e61223d565b606091505b509150915081158061226b575080511580159061226b5750808060200190518101906122699190612bbc565b155b156109c057604051633e3f8f7360e01b815260040160405180910390fd5b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316836001600160a01b0316036123265761231f82612407565b9050611135565b60cb5460405163266e0a7f60e01b81526001600160a01b0385811660048301528481166024830152600092169063266e0a7f90604401602060405180830381865afa158015612379573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061239d91906129f9565b6001600160a01b031614159392505050565b606061219584846000856125d8565b60408051602081019091526000815260405180602001604052806123e68560000151856126b3565b90529392505050565b805160009061113590670de0b6b3a764000090612f45565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b0772d0b6040518163ffffffff1660e01b8152600401600060405180830381865afa158015612468573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526124909190810190612f67565b905060005b81518110156125d1578181815181106124b0576124b06129e3565b60200260200101516001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03161461258457836001600160a01b031682828151811061250c5761250c6129e3565b60200260200101516001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa158015612551573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061257591906129f9565b6001600160a01b0316146125ba565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316846001600160a01b0316145b9250826125d1576125ca81612c56565b9050612495565b5050919050565b6060824710156126395760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610487565b600080866001600160a01b031685876040516126559190612f29565b60006040518083038185875af1925050503d8060008114612692576040519150601f19603f3d011682016040523d82523d6000602084013e612697565b606091505b50915091506126a8878383876126c6565b979650505050505050565b60006126bf8284612ff6565b9392505050565b6060831561273557825160000361272e576001600160a01b0385163b61272e5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610487565b5081612195565b612195838381511561274a5781518083602001fd5b8060405162461bcd60e51b81526004016104879190613015565b6001600160a01b038116811461064357600080fd5b6000806040838503121561278c57600080fd5b823561279781612764565b946020939093013593505050565b6000602082840312156127b757600080fd5b81356126bf81612764565b600080604083850312156127d557600080fd5b82356127e081612764565b915060208301356127f081612764565b809150509250929050565b600080600080600060a0868803121561281357600080fd5b853561281e81612764565b945060208601359350604086013561283581612764565b9250606086013561284581612764565b949793965091946080013592915050565b60008083601f84011261286857600080fd5b50813567ffffffffffffffff81111561288057600080fd5b6020830191508360208260051b850101111561289b57600080fd5b9250929050565b60008060008060008060006080888a0312156128bd57600080fd5b873567ffffffffffffffff808211156128d557600080fd5b6128e18b838c01612856565b909950975060208a01359150808211156128fa57600080fd5b6129068b838c01612856565b909750955060408a013591508082111561291f57600080fd5b5061292c8a828b01612856565b989b979a50959894979596606090950135949350505050565b60006020828403121561295757600080fd5b5035919050565b6020808252600a90820152691c994b595b9d195c995960b21b604082015260600190565b60006020828403121561299457600080fd5b5051919050565b60208082526028908201527f5269736b2046756e643a20496e76616c6964206d696e20616d6f756e7420746f6040820152670818dbdb9d995c9d60c21b606082015260800190565b634e487b7160e01b600052603260045260246000fd5b600060208284031215612a0b57600080fd5b81516126bf81612764565b634e487b7160e01b600052604160045260246000fd5b60405160a0810167ffffffffffffffff81118282101715612a4f57612a4f612a16565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715612a7e57612a7e612a16565b604052919050565b60005b83811015612aa1578181015183820152602001612a89565b83811115612ab0576000848401525b50505050565b8051612ac181612764565b919050565b60006020808385031215612ad957600080fd5b825167ffffffffffffffff80821115612af157600080fd5b9084019060a08287031215612b0557600080fd5b612b0d612a2c565b825182811115612b1c57600080fd5b8301601f81018813612b2d57600080fd5b805183811115612b3f57612b3f612a16565b612b51601f8201601f19168701612a55565b93508084528886828401011115612b6757600080fd5b612b7681878601888501612a86565b5050818152612b86848401612ab6565b84820152612b9660408401612ab6565b604082015260608301516060820152608083015160808201528094505050505092915050565b600060208284031215612bce57600080fd5b815180151581146126bf57600080fd5b6000808335601e19843603018112612bf557600080fd5b83018035915067ffffffffffffffff821115612c1057600080fd5b6020019150600581901b360382131561289b57600080fd5b634e487b7160e01b600052601160045260246000fd5b60008219821115612c5157612c51612c28565b500190565b600060018201612c6857612c68612c28565b5060010190565b8183526000602080850194508260005b85811015612cad578135612c9281612764565b6001600160a01b031687529582019590820190600101612c7f565b509495945050505050565b606081526000612ccc606083018789612c6f565b82810360208401528481526001600160fb1b03851115612ceb57600080fd5b8460051b80876020840137600091016020019081526040929092019290925295945050505050565b6020808252602b908201527f5265736572766548656c706572733a20436f6d7074726f6c6c6572206164647260408201526a195cdcc81a5b9d985b1a5960aa1b606082015260800190565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b60008151808452612dc1816020860160208601612a86565b601f01601f19169290920160200192915050565b6001600160a01b038316815260406020820181905260009061219590830184612da9565b6001600160a01b03848116825283166020820152606060408201819052600090611d9990830184612da9565b600082821015612e3757612e37612c28565b500390565b86815285602082015260a060408201526000612e5c60a083018688612c6f565b6001600160a01b039490941660608301525060800152949350505050565b600067ffffffffffffffff821115612e9457612e94612a16565b5060051b60200190565b60006020808385031215612eb157600080fd5b825167ffffffffffffffff811115612ec857600080fd5b8301601f81018513612ed957600080fd5b8051612eec612ee782612e7a565b612a55565b81815260059190911b82018301908381019087831115612f0b57600080fd5b928401925b828410156126a857835182529284019290840190612f10565b60008251612f3b818460208701612a86565b9190910192915050565b600082612f6257634e487b7160e01b600052601260045260246000fd5b500490565b60006020808385031215612f7a57600080fd5b825167ffffffffffffffff811115612f9157600080fd5b8301601f81018513612fa257600080fd5b8051612fb0612ee782612e7a565b81815260059190911b82018301908381019087831115612fcf57600080fd5b928401925b828410156126a8578351612fe781612764565b82529284019290840190612fd4565b600081600019048311821515161561301057613010612c28565b500290565b6020815260006126bf6020830184612da956fe73776170506f6f6c7341737365747328616464726573735b5d2c75696e743235365b5d2c616464726573735b5d5b5d2c75696e7432353629a26469706673582212200663ba64facc893c046f05256383f974657252f4c49516250551dac4f0a40cd564736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101da5760003560e01c806377d4937f11610104578063afcff50f116100a2578063e30c397811610071578063e30c39781461040e578063f2fde38b1461041f578063fa7b81a014610432578063fe3da9841461045957600080fd5b8063afcff50f146103cd578063b4a0bdf3146103e0578063be26317e146103f1578063c8ecc0d3146103fa57600080fd5b806380d45a2d116100de57806380d45a2d146103835780638da5cb5b14610396578063a69bd19e146103a7578063aac59a75146103ba57600080fd5b806377d4937f1461035557806379ba5097146103685780637b77cd6a1461037057600080fd5b80633421fc521161017c5780635f30e37b1161014b5780635f30e37b146103145780636fb0527514610327578063715018a61461033a578063746460a91461034257600080fd5b80633421fc5214610293578063362b6795146102ba578063439b5517146102e15780634dd9584a1461030157600080fd5b806324558995116101b85780632455899514610246578063258836fe1461025a5780632a1d05471461026d5780632e6881411461028057600080fd5b80630a9837c5146101df5780630e32cb861461020557806319b1faef1461021a575b600080fd5b6101f26101ed366004612779565b610463565b6040519081526020015b60405180910390f35b6102186102133660046127a5565b610632565b005b61012e5461022e906001600160a01b031681565b6040516001600160a01b0390911681526020016101fc565b61012f5461022e906001600160a01b031681565b6102186102683660046127c2565b610646565b61021861027b3660046127fb565b6107d7565b61021861028e3660046127a5565b6109c8565b61022e7f000000000000000000000000000000000000000000000000000000000000000081565b61022e7f000000000000000000000000000000000000000000000000000000000000000081565b6101f26102ef3660046127a5565b60c96020526000908152604090205481565b61021861030f3660046127a5565b610acd565b6101f26103223660046128a2565b610b31565b6101f26103353660046127c2565b611085565b61021861113b565b610218610350366004612945565b61114f565b6102186103633660046127a5565b6111f4565b610218611258565b61021861037e3660046127a5565b6112cf565b610218610391366004612945565b611332565b6033546001600160a01b031661022e565b6101f26103b53660046127a5565b611343565b6102186103c83660046127c2565b61142f565b60cb5461022e906001600160a01b031681565b6097546001600160a01b031661022e565b6101f260fb5481565b61012d5461022e906001600160a01b031681565b6065546001600160a01b031661022e565b61021861042d3660046127a5565b61143d565b61022e7f000000000000000000000000000000000000000000000000000000000000000081565b6101f26101305481565b6000600260cc54036104905760405162461bcd60e51b81526004016104879061295e565b60405180910390fd5b600260cc5561012e546001600160a01b03163381146105085760405162461bcd60e51b815260206004820152602e60248201527f5269736b2066756e643a204f6e6c792063616c6c61626c652062792053686f7260448201526d1d19985b1b0818dbdb9d1c9858dd60921b6064820152608401610487565b6001600160a01b03808516600090815260ca6020908152604080832061012d549094168352929052205483111561058f5760405162461bcd60e51b815260206004820152602560248201527f5269736b2046756e643a20496e73756666696369656e7420706f6f6c2072657360448201526432b93b329760d91b6064820152608401610487565b6001600160a01b03808516600081815260ca6020908152604080832061012d80548716855290835281842080548a9003905554909416825260c990528290208054869003905590517fc8d0a37ed16dfaa43514df00e18f478b60d5cc7b4bfc687103948b9020f737fd906106069086815260200190565b60405180910390a261012d54610626906001600160a01b031682856114ae565b5050600160cc55919050565b61063a611505565b6106438161155f565b50565b61064e611505565b600260cc54036106705760405162461bcd60e51b81526004016104879061295e565b600260cc5561067e8161161d565b6040516370a0823160e01b815230600482015260009081906001600160a01b038516906370a0823190602401602060405180830381865afa1580156106c7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106eb9190612982565b6001600160a01b038516600090815260c9602052604090205490915081116107615760405162461bcd60e51b815260206004820152602360248201527f5265736572766548656c706572733a205a65726f20737572706c757320746f6b604482015262656e7360e81b6064820152608401610487565b6001600160a01b03848116600081815260c960209081526040918290205491519185038083529550928616927f6d25be279134f4ecaa4770aff0c3d916d9e7c5ef37b65ed95dbdba411f5d54d5910160405180910390a36107cc6001600160a01b03851684846114ae565b5050600160cc555050565b600054610100900460ff16158080156107f75750600054600160ff909116105b806108115750303b158015610811575060005460ff166001145b6108745760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610487565b6000805460ff191660011790558015610897576000805461ff0019166101001790555b6108a08661161d565b6108a98461161d565b600085116108c95760405162461bcd60e51b81526004016104879061299b565b600082116109285760405162461bcd60e51b815260206004820152602660248201527f5269736b2046756e643a204c6f6f7073206c696d69742063616e206e6f74206260448201526565207a65726f60d01b6064820152608401610487565b610930611644565b61093983611673565b61012f80546001600160a01b038089166001600160a01b03199283161790925561013087905561012d80549287169290911691909117905561097a8261169a565b80156109c0576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050565b610a066040518060400160405280602081526020017f736574436f6e7665727469626c65426173654173736574286164647265737329815250611734565b6001600160a01b038116610a7a5760405162461bcd60e51b815260206004820152603560248201527f5269736b2046756e643a206e657720636f6e7665727469626c65206261736520604482015274185cdcd95d081859191c995cdcc81a5b9d985b1a59605a1b6064820152608401610487565b61012d80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f5fa61583da12070720613fefdd68cc6c0e464a71e009742526bd2b2e0ac62cd290600090a35050565b610ad5611505565b610ade8161161d565b61012f80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907fd37b9d138f53ea58d7e50292588239a46efa8f523966febf4066da96defc77fd90600090a35050565b6000600260cc5403610b555760405162461bcd60e51b81526004016104879061295e565b600260cc81905550610b7e60405180606001604052806038815260200161302960389139611734565b42821015610bce5760405162461bcd60e51b815260206004820152601a60248201527f5269736b2066756e643a20646561646c696e65207061737365640000000000006044820152606401610487565b60cb546001600160a01b0316610be38161161d565b878614610c585760405162461bcd60e51b815260206004820152603860248201527f5269736b2066756e643a206d61726b65747320616e6420616d6f756e74734f7560448201527f744d696e2061726520756e657175616c206c656e6774687300000000000000006064820152608401610487565b878414610cc05760405162461bcd60e51b815260206004820152603060248201527f5269736b2066756e643a206d61726b65747320616e642070617468732061726560448201526f20756e657175616c206c656e6774687360801b6064820152608401610487565b600088610ccc816117ce565b60005b818110156110325760008c8c83818110610ceb57610ceb6129e3565b9050602002016020810190610d0091906127a5565b6001600160a01b0316635fe3b5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d3d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d6191906129f9565b604051637aee632d60e01b81526001600160a01b038083166004830152919250600091871690637aee632d90602401600060405180830381865afa158015610dad573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610dd59190810190612ac6565b9050816001600160a01b031681604001516001600160a01b031614610e4c5760405162461bcd60e51b815260206004820152602760248201527f636f6d7074726f6c6c657220646f65736e277420657869737420706f6f6c20726044820152666567697374727960c81b6064820152608401610487565b816001600160a01b0316633d98a1e58f8f86818110610e6d57610e6d6129e3565b9050602002016020810190610e8291906127a5565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa158015610ec6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610eea9190612bbc565b610f2d5760405162461bcd60e51b81526020600482015260146024820152731b585c9ad95d081a5cc81b9bdd081b1a5cdd195960621b6044820152606401610487565b6000610f9c8f8f86818110610f4457610f446129e3565b9050602002016020810190610f5991906127a5565b848f8f88818110610f6c57610f6c6129e3565b905060200201358e8e89818110610f8557610f856129e3565b9050602002810190610f979190612bde565b6117ff565b6001600160a01b03808516600090815260ca6020908152604080832061012d54909416835292905290812080549293508392909190610fdc908490612c3e565b909155505061012d546001600160a01b0316600090815260c960205260408120805483929061100c908490612c3e565b9091555061101c90508187612c3e565b95505050508061102b90612c56565b9050610ccf565b507fb17530966b045b50d4975e7f05048ca00d7335780c24f1c465165a4b94b2d37d8b8b8b8b8660405161106a959493929190612cb8565b60405180910390a150600160cc559998505050505050505050565b60006110908261161d565b826001600160a01b0316627e3dd26040518163ffffffff1660e01b8152600401602060405180830381865afa1580156110cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110f19190612bbc565b61110d5760405162461bcd60e51b815260040161048790612d13565b506001600160a01b03808316600090815260ca60209081526040808320938516835292905220545b92915050565b611143611505565b61114d6000611da2565b565b61118d6040518060400160405280601e81526020017f7365744d696e416d6f756e74546f436f6e766572742875696e74323536290000815250611734565b600081116111ad5760405162461bcd60e51b81526004016104879061299b565b61013080549082905560408051828152602081018490527fada67d0d38fa20c8ae6a5c17cb9d60b0fe7f2d4e4f27ac9ee55e54ac88de9d8d91015b60405180910390a15050565b6111fc611505565b6112058161161d565b61012e80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907fb6e5fcf02f7fbb8acfbaa3bac4fd5abf9ff51e3f2e8884b5498927179b211b2890600090a35050565b60655433906001600160a01b031681146112c65760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b6064820152608401610487565b61064381611da2565b6112d7611505565b6112e08161161d565b60cb80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907fa87b964d321035d2165e484ff4b722dd6eae30606c0b98887d2ed1a34e594bfe90600090a35050565b61133a611505565b6106438161169a565b6000816001600160a01b0316627e3dd26040518163ffffffff1660e01b8152600401602060405180830381865afa158015611382573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113a69190612bbc565b6114015760405162461bcd60e51b815260206004820152602660248201527f5269736b2046756e643a20436f6d7074726f6c6c6572206164647265737320696044820152651b9d985b1a5960d21b6064820152608401610487565b506001600160a01b03908116600090815260ca6020908152604080832061012d549094168352929052205490565b6114398282611dbb565b5050565b611445611505565b606580546001600160a01b0383166001600160a01b031990911681179091556114766033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b179052611500908490612078565b505050565b6033546001600160a01b0316331461114d5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610487565b6001600160a01b0381166115c35760405162461bcd60e51b815260206004820152602560248201527f696e76616c696420616365737320636f6e74726f6c206d616e61676572206164604482015264647265737360d81b6064820152608401610487565b609780546001600160a01b038381166001600160a01b031983168117909355604080519190921680825260208201939093527f66fd58e82f7b31a2a5c30e0888f3093efe4e111b00cd2b0c31fe014601293aa091016111e8565b6001600160a01b038116610643576040516342bcdf7f60e11b815260040160405180910390fd5b600054610100900460ff1661166b5760405162461bcd60e51b815260040161048790612d5e565b61114d61214d565b600054610100900460ff1661063a5760405162461bcd60e51b815260040161048790612d5e565b60fb5481116116f65760405162461bcd60e51b815260206004820152602260248201527f436f6d7074726f6c6c65723a20496e76616c6964206d61784c6f6f70734c696d6044820152611a5d60f21b6064820152608401610487565b60fb80549082905560408051828152602081018490527fc2d09fef144f7c8a86f71ea459f8fc17f675768eb1ae369cbd77fb31d467aafa91016111e8565b6097546040516318c5e8ab60e01b81526000916001600160a01b0316906318c5e8ab906117679033908690600401612dd5565b602060405180830381865afa158015611784573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117a89190612bbc565b90508061143957333083604051634a3fa29360e01b815260040161048793929190612df9565b60fb548111156106435760fb5460405163792bfb1b60e11b8152600481019190915260248101829052604401610487565b6000836000036118775760405162461bcd60e51b815260206004820152603c60248201527f5269736b46756e643a20616d6f756e744f75744d696e206d757374206265206760448201527f726561746572207468616e203020746f20737761702076546f6b656e000000006064820152608401610487565b600080876001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa1580156118b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118dc91906129f9565b61012d546001600160a01b03898116600090815260ca60209081526040808320848716845290915281205493945091169190819003611922576000945050505050611d99565b6000896001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa158015611962573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061198691906129f9565b60405163b62cad6960e01b81526001600160a01b0385811660048301529192509082169063b62cad6990602401600060405180830381600087803b1580156119cd57600080fd5b505af11580156119e1573d6000803e3d6000fd5b50506040805160208101918290526341976e0960e01b9091526001600160a01b03868116602483015260009350909150819084166341976e0960448301602060405180830381865afa158015611a3b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a5f9190612982565b905290506000611a6f828c61217d565b905061013054811015611ad25760405162461bcd60e51b815260206004820152602560248201527f5269736b46756e643a206d696e416d6f756e74546f436f6e766572742076696f6044820152641b185d195960da1b6064820152608401610487565b6001600160a01b038616600090815260c9602052604081208054869290611afa908490612e25565b90915550506001600160a01b03808d16600090815260ca60209081526040808320938a1683529290529081208054869290611b36908490612e25565b90915550506001600160a01b0386811690861614611d8b57856001600160a01b03168a8a6000818110611b6b57611b6b6129e3565b9050602002016020810190611b8091906127a5565b6001600160a01b031614611bfc5760405162461bcd60e51b815260206004820152603860248201527f5269736b46756e643a20737761702070617468206d757374207374617274207760448201527f6974682074686520756e6465726c79696e6720617373657400000000000000006064820152608401610487565b6001600160a01b0385168a8a611c13600182612e25565b818110611c2257611c226129e3565b9050602002016020810190611c3791906127a5565b6001600160a01b031614611cab5760405162461bcd60e51b815260206004820152603560248201527f5269736b46756e643a2066696e616c6c792070617468206d75737420626520636044820152741bdb9d995c9d1a589b194818985cd948185cdcd95d605a1b6064820152608401610487565b61012f546001600160a01b0390811690611cc990881682600061219d565b611cdd6001600160a01b038816828761219d565b6000816001600160a01b03166338ed1739878f8f8f30426040518763ffffffff1660e01b8152600401611d1596959493929190612e3c565b6000604051808303816000875af1158015611d34573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611d5c9190810190612e9e565b905080611d6a60018d612e25565b81518110611d7a57611d7a6129e3565b602002602001015198505050611d8f565b8396505b5094955050505050505b95945050505050565b606580546001600160a01b031916905561064381612289565b611dc48161161d565b816001600160a01b0316627e3dd26040518163ffffffff1660e01b8152600401602060405180830381865afa158015611e01573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e259190612bbc565b611e415760405162461bcd60e51b815260040161048790612d13565b60cb546001600160a01b031680611eb35760405162461bcd60e51b815260206004820152603060248201527f5265736572766548656c706572733a20506f6f6c20526567697374727920616460448201526f191c995cdcc81a5cc81b9bdd081cd95d60821b6064820152608401610487565b611ebd83836122db565b611f245760405162461bcd60e51b815260206004820152603260248201527f5265736572766548656c706572733a2054686520706f6f6c20646f65736e2774604482015271081cdd5c1c1bdc9d081d1a1948185cdcd95d60721b6064820152608401610487565b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa158015611f6b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f8f9190612982565b6001600160a01b038416600090815260c9602052604090205490915080821115612071576001600160a01b038416600090815260c960205260408120805483850392839291611fdf908490612c3e565b90915550506001600160a01b03808716600090815260ca602090815260408083209389168352929052908120805483929061201b908490612c3e565b92505081905550846001600160a01b0316866001600160a01b03167fc39e3e80c0219fde334a8cb5d8468b628482e23388b6e809c90cb00c63c8ce388360405161206791815260200190565b60405180910390a3505b5050505050565b60006120cd826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166123af9092919063ffffffff16565b90508051600014806120ee5750808060200190518101906120ee9190612bbc565b6115005760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610487565b600054610100900460ff166121745760405162461bcd60e51b815260040161048790612d5e565b61114d33611da2565b60008061218a84846123be565b9050612195816123ef565b949350505050565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663095ea7b360e01b1790529151909160009182918716906121fb908590612f29565b6000604051808303816000865af19150503d8060008114612238576040519150601f19603f3d011682016040523d82523d6000602084013e61223d565b606091505b509150915081158061226b575080511580159061226b5750808060200190518101906122699190612bbc565b155b156109c057604051633e3f8f7360e01b815260040160405180910390fd5b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316836001600160a01b0316036123265761231f82612407565b9050611135565b60cb5460405163266e0a7f60e01b81526001600160a01b0385811660048301528481166024830152600092169063266e0a7f90604401602060405180830381865afa158015612379573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061239d91906129f9565b6001600160a01b031614159392505050565b606061219584846000856125d8565b60408051602081019091526000815260405180602001604052806123e68560000151856126b3565b90529392505050565b805160009061113590670de0b6b3a764000090612f45565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b0772d0b6040518163ffffffff1660e01b8152600401600060405180830381865afa158015612468573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526124909190810190612f67565b905060005b81518110156125d1578181815181106124b0576124b06129e3565b60200260200101516001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03161461258457836001600160a01b031682828151811061250c5761250c6129e3565b60200260200101516001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa158015612551573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061257591906129f9565b6001600160a01b0316146125ba565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316846001600160a01b0316145b9250826125d1576125ca81612c56565b9050612495565b5050919050565b6060824710156126395760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610487565b600080866001600160a01b031685876040516126559190612f29565b60006040518083038185875af1925050503d8060008114612692576040519150601f19603f3d011682016040523d82523d6000602084013e612697565b606091505b50915091506126a8878383876126c6565b979650505050505050565b60006126bf8284612ff6565b9392505050565b6060831561273557825160000361272e576001600160a01b0385163b61272e5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610487565b5081612195565b612195838381511561274a5781518083602001fd5b8060405162461bcd60e51b81526004016104879190613015565b6001600160a01b038116811461064357600080fd5b6000806040838503121561278c57600080fd5b823561279781612764565b946020939093013593505050565b6000602082840312156127b757600080fd5b81356126bf81612764565b600080604083850312156127d557600080fd5b82356127e081612764565b915060208301356127f081612764565b809150509250929050565b600080600080600060a0868803121561281357600080fd5b853561281e81612764565b945060208601359350604086013561283581612764565b9250606086013561284581612764565b949793965091946080013592915050565b60008083601f84011261286857600080fd5b50813567ffffffffffffffff81111561288057600080fd5b6020830191508360208260051b850101111561289b57600080fd5b9250929050565b60008060008060008060006080888a0312156128bd57600080fd5b873567ffffffffffffffff808211156128d557600080fd5b6128e18b838c01612856565b909950975060208a01359150808211156128fa57600080fd5b6129068b838c01612856565b909750955060408a013591508082111561291f57600080fd5b5061292c8a828b01612856565b989b979a50959894979596606090950135949350505050565b60006020828403121561295757600080fd5b5035919050565b6020808252600a90820152691c994b595b9d195c995960b21b604082015260600190565b60006020828403121561299457600080fd5b5051919050565b60208082526028908201527f5269736b2046756e643a20496e76616c6964206d696e20616d6f756e7420746f6040820152670818dbdb9d995c9d60c21b606082015260800190565b634e487b7160e01b600052603260045260246000fd5b600060208284031215612a0b57600080fd5b81516126bf81612764565b634e487b7160e01b600052604160045260246000fd5b60405160a0810167ffffffffffffffff81118282101715612a4f57612a4f612a16565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715612a7e57612a7e612a16565b604052919050565b60005b83811015612aa1578181015183820152602001612a89565b83811115612ab0576000848401525b50505050565b8051612ac181612764565b919050565b60006020808385031215612ad957600080fd5b825167ffffffffffffffff80821115612af157600080fd5b9084019060a08287031215612b0557600080fd5b612b0d612a2c565b825182811115612b1c57600080fd5b8301601f81018813612b2d57600080fd5b805183811115612b3f57612b3f612a16565b612b51601f8201601f19168701612a55565b93508084528886828401011115612b6757600080fd5b612b7681878601888501612a86565b5050818152612b86848401612ab6565b84820152612b9660408401612ab6565b604082015260608301516060820152608083015160808201528094505050505092915050565b600060208284031215612bce57600080fd5b815180151581146126bf57600080fd5b6000808335601e19843603018112612bf557600080fd5b83018035915067ffffffffffffffff821115612c1057600080fd5b6020019150600581901b360382131561289b57600080fd5b634e487b7160e01b600052601160045260246000fd5b60008219821115612c5157612c51612c28565b500190565b600060018201612c6857612c68612c28565b5060010190565b8183526000602080850194508260005b85811015612cad578135612c9281612764565b6001600160a01b031687529582019590820190600101612c7f565b509495945050505050565b606081526000612ccc606083018789612c6f565b82810360208401528481526001600160fb1b03851115612ceb57600080fd5b8460051b80876020840137600091016020019081526040929092019290925295945050505050565b6020808252602b908201527f5265736572766548656c706572733a20436f6d7074726f6c6c6572206164647260408201526a195cdcc81a5b9d985b1a5960aa1b606082015260800190565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b60008151808452612dc1816020860160208601612a86565b601f01601f19169290920160200192915050565b6001600160a01b038316815260406020820181905260009061219590830184612da9565b6001600160a01b03848116825283166020820152606060408201819052600090611d9990830184612da9565b600082821015612e3757612e37612c28565b500390565b86815285602082015260a060408201526000612e5c60a083018688612c6f565b6001600160a01b039490941660608301525060800152949350505050565b600067ffffffffffffffff821115612e9457612e94612a16565b5060051b60200190565b60006020808385031215612eb157600080fd5b825167ffffffffffffffff811115612ec857600080fd5b8301601f81018513612ed957600080fd5b8051612eec612ee782612e7a565b612a55565b81815260059190911b82018301908381019087831115612f0b57600080fd5b928401925b828410156126a857835182529284019290840190612f10565b60008251612f3b818460208701612a86565b9190910192915050565b600082612f6257634e487b7160e01b600052601260045260246000fd5b500490565b60006020808385031215612f7a57600080fd5b825167ffffffffffffffff811115612f9157600080fd5b8301601f81018513612fa257600080fd5b8051612fb0612ee782612e7a565b81815260059190911b82018301908381019087831115612fcf57600080fd5b928401925b828410156126a8578351612fe781612764565b82529284019290840190612fd4565b600081600019048311821515161561301057613010612c28565b500290565b6020815260006126bf6020830184612da956fe73776170506f6f6c7341737365747328616464726573735b5d2c75696e743235365b5d2c616464726573735b5d5b5d2c75696e7432353629a26469706673582212200663ba64facc893c046f05256383f974657252f4c49516250551dac4f0a40cd564736f6c634300080d0033", "devdoc": { "author": "Venus", "details": "This contract does not support BNB.", @@ -1164,7 +1164,7 @@ "type": "t_array(t_uint256)49_storage" }, { - "astId": 8855, + "astId": 8853, "contract": "contracts/RiskFund/RiskFund.sol:RiskFund", "label": "assetsReserves", "offset": 0, @@ -1172,7 +1172,7 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 8861, + "astId": 8859, "contract": "contracts/RiskFund/RiskFund.sol:RiskFund", "label": "_poolsAssetsReserves", "offset": 0, @@ -1180,7 +1180,7 @@ "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))" }, { - "astId": 8863, + "astId": 8861, "contract": "contracts/RiskFund/RiskFund.sol:RiskFund", "label": "poolRegistry", "offset": 0, @@ -1188,7 +1188,7 @@ "type": "t_address" }, { - "astId": 8866, + "astId": 8864, "contract": "contracts/RiskFund/RiskFund.sol:RiskFund", "label": "status", "offset": 0, @@ -1196,7 +1196,7 @@ "type": "t_uint256" }, { - "astId": 8871, + "astId": 8869, "contract": "contracts/RiskFund/RiskFund.sol:RiskFund", "label": "__gap", "offset": 0, @@ -1220,7 +1220,7 @@ "type": "t_array(t_uint256)49_storage" }, { - "astId": 9284, + "astId": 9282, "contract": "contracts/RiskFund/RiskFund.sol:RiskFund", "label": "convertibleBaseAsset", "offset": 0, @@ -1228,7 +1228,7 @@ "type": "t_address" }, { - "astId": 9286, + "astId": 9284, "contract": "contracts/RiskFund/RiskFund.sol:RiskFund", "label": "shortfall", "offset": 0, @@ -1236,7 +1236,7 @@ "type": "t_address" }, { - "astId": 9288, + "astId": 9286, "contract": "contracts/RiskFund/RiskFund.sol:RiskFund", "label": "pancakeSwapRouter", "offset": 0, @@ -1244,7 +1244,7 @@ "type": "t_address" }, { - "astId": 9290, + "astId": 9288, "contract": "contracts/RiskFund/RiskFund.sol:RiskFund", "label": "minAmountToConvert", "offset": 0, diff --git a/deployments/bscmainnet/solcInputs/09e209110f36e8c9fe7ecc1925064673.json b/deployments/bscmainnet/solcInputs/09e209110f36e8c9fe7ecc1925064673.json new file mode 100644 index 000000000..9657e68fd --- /dev/null +++ b/deployments/bscmainnet/solcInputs/09e209110f36e8c9fe7ecc1925064673.json @@ -0,0 +1,132 @@ +{ + "language": "Solidity", + "sources": { + "@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable2Step.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./OwnableUpgradeable.sol\";\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module which provides access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership} and {acceptOwnership}.\n *\n * This module is used through inheritance. It will make available all functions\n * from parent (Ownable).\n */\nabstract contract Ownable2StepUpgradeable is Initializable, OwnableUpgradeable {\n function __Ownable2Step_init() internal onlyInitializing {\n __Ownable_init_unchained();\n }\n\n function __Ownable2Step_init_unchained() internal onlyInitializing {\n }\n address private _pendingOwner;\n\n event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Returns the address of the pending owner.\n */\n function pendingOwner() public view virtual returns (address) {\n return _pendingOwner;\n }\n\n /**\n * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual override onlyOwner {\n _pendingOwner = newOwner;\n emit OwnershipTransferStarted(owner(), newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual override {\n delete _pendingOwner;\n super._transferOwnership(newOwner);\n }\n\n /**\n * @dev The new owner accepts the ownership transfer.\n */\n function acceptOwnership() public virtual {\n address sender = _msgSender();\n require(pendingOwner() == sender, \"Ownable2Step: caller is not the new owner\");\n _transferOwnership(sender);\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/ContextUpgradeable.sol\";\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n function __Ownable_init() internal onlyInitializing {\n __Ownable_init_unchained();\n }\n\n function __Ownable_init_unchained() internal onlyInitializing {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n _checkOwner();\n _;\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if the sender is not the owner.\n */\n function _checkOwner() internal view virtual {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby disabling any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)\n\npragma solidity ^0.8.2;\n\nimport \"../../utils/AddressUpgradeable.sol\";\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```solidity\n * contract MyToken is ERC20Upgradeable {\n * function initialize() initializer public {\n * __ERC20_init(\"MyToken\", \"MTK\");\n * }\n * }\n *\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n * function initializeV2() reinitializer(2) public {\n * __ERC20Permit_init(\"MyToken\");\n * }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n * _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n /**\n * @dev Indicates that the contract has been initialized.\n * @custom:oz-retyped-from bool\n */\n uint8 private _initialized;\n\n /**\n * @dev Indicates that the contract is in the process of being initialized.\n */\n bool private _initializing;\n\n /**\n * @dev Triggered when the contract has been initialized or reinitialized.\n */\n event Initialized(uint8 version);\n\n /**\n * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n * `onlyInitializing` functions can be used to initialize parent contracts.\n *\n * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a\n * constructor.\n *\n * Emits an {Initialized} event.\n */\n modifier initializer() {\n bool isTopLevelCall = !_initializing;\n require(\n (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),\n \"Initializable: contract is already initialized\"\n );\n _initialized = 1;\n if (isTopLevelCall) {\n _initializing = true;\n }\n _;\n if (isTopLevelCall) {\n _initializing = false;\n emit Initialized(1);\n }\n }\n\n /**\n * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n * used to initialize parent contracts.\n *\n * A reinitializer may be used after the original initialization step. This is essential to configure modules that\n * are added through upgrades and that require initialization.\n *\n * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\n * cannot be nested. If one is invoked in the context of another, execution will revert.\n *\n * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n * a contract, executing them in the right order is up to the developer or operator.\n *\n * WARNING: setting the version to 255 will prevent any future reinitialization.\n *\n * Emits an {Initialized} event.\n */\n modifier reinitializer(uint8 version) {\n require(!_initializing && _initialized < version, \"Initializable: contract is already initialized\");\n _initialized = version;\n _initializing = true;\n _;\n _initializing = false;\n emit Initialized(version);\n }\n\n /**\n * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n * {initializer} and {reinitializer} modifiers, directly or indirectly.\n */\n modifier onlyInitializing() {\n require(_initializing, \"Initializable: contract is not initializing\");\n _;\n }\n\n /**\n * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n * through proxies.\n *\n * Emits an {Initialized} event the first time it is successfully executed.\n */\n function _disableInitializers() internal virtual {\n require(!_initializing, \"Initializable: contract is initializing\");\n if (_initialized != type(uint8).max) {\n _initialized = type(uint8).max;\n emit Initialized(type(uint8).max);\n }\n }\n\n /**\n * @dev Returns the highest version that has been initialized. See {reinitializer}.\n */\n function _getInitializedVersion() internal view returns (uint8) {\n return _initialized;\n }\n\n /**\n * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\n */\n function _isInitializing() internal view returns (bool) {\n return _initializing;\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/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/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" + }, + "@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/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/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" + }, + "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/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/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 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 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\";\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/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" + } + }, + "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/bsctestnet/RiskFund_Implementation.json b/deployments/bsctestnet/RiskFund_Implementation.json index ea2c6b26f..b4a6483dc 100644 --- a/deployments/bsctestnet/RiskFund_Implementation.json +++ b/deployments/bsctestnet/RiskFund_Implementation.json @@ -1,5 +1,5 @@ { - "address": "0x50B26c741Db8F45b24498575C203c862Fe70d934", + "address": "0x1E7DEC93C77740c2bB46daf87ef42056E388dA14", "abi": [ { "inputs": [ @@ -811,30 +811,30 @@ "type": "function" } ], - "transactionHash": "0x510331028fd96d747253dc318dfe753c619a984f00bb506ae0d2c8412f0f1a97", + "transactionHash": "0x78a1f1133460389edb19df8860f5962780302da105e824405069a3f7119fdff7", "receipt": { "to": null, "from": "0x8BDA9f9E1fEF0DFd404Fef338D9fE4c543d172e1", - "contractAddress": "0x50B26c741Db8F45b24498575C203c862Fe70d934", + "contractAddress": "0x1E7DEC93C77740c2bB46daf87ef42056E388dA14", "transactionIndex": 1, - "gasUsed": "2769907", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000080000000000000000000000001000000000000000000000400000000000000000000000000000000000000000000000000000000000000040000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x40bb0a783e69d9664ac6d5f47534a224f64b75c190858f0fba51d114e51cfd08", - "transactionHash": "0x510331028fd96d747253dc318dfe753c619a984f00bb506ae0d2c8412f0f1a97", + "gasUsed": "2769919", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000400000000080000000000000000000000000000000000000000080000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x20295993abef40dfb22c7e8f1a28802f19060fae319585029055abc21639ce3d", + "transactionHash": "0x78a1f1133460389edb19df8860f5962780302da105e824405069a3f7119fdff7", "logs": [ { "transactionIndex": 1, - "blockNumber": 34057466, - "transactionHash": "0x510331028fd96d747253dc318dfe753c619a984f00bb506ae0d2c8412f0f1a97", - "address": "0x50B26c741Db8F45b24498575C203c862Fe70d934", + "blockNumber": 34082218, + "transactionHash": "0x78a1f1133460389edb19df8860f5962780302da105e824405069a3f7119fdff7", + "address": "0x1E7DEC93C77740c2bB46daf87ef42056E388dA14", "topics": ["0x7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498"], "data": "0x00000000000000000000000000000000000000000000000000000000000000ff", "logIndex": 0, - "blockHash": "0x40bb0a783e69d9664ac6d5f47534a224f64b75c190858f0fba51d114e51cfd08" + "blockHash": "0x20295993abef40dfb22c7e8f1a28802f19060fae319585029055abc21639ce3d" } ], - "blockNumber": 34057466, - "cumulativeGasUsed": "2801148", + "blockNumber": 34082218, + "cumulativeGasUsed": "2801160", "status": 1, "byzantium": true }, @@ -844,10 +844,10 @@ "0xae13d989daC2f0dEbFf460aC112a837C89BAa7cd" ], "numDeployments": 1, - "solcInputHash": "f237ea044837d6f4ff4c08abcdd27558", - "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"corePoolComptroller_\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"vbnb_\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nativeWrapped_\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"ApproveFailed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"loopsLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requiredLoops\",\"type\":\"uint256\"}],\"name\":\"MaxLoopsLimitExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"calledContract\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"methodSignature\",\"type\":\"string\"}],\"name\":\"Unauthorized\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"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\":\"oldConvertibleBaseAsset\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newConvertibleBaseAsset\",\"type\":\"address\"}],\"name\":\"ConvertibleBaseAssetUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldMaxLoopsLimit\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newmaxLoopsLimit\",\"type\":\"uint256\"}],\"name\":\"MaxLoopsLimitUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldMinAmountToConvert\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newMinAmountToConvert\",\"type\":\"uint256\"}],\"name\":\"MinAmountToConvertUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldAccessControlManager\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newAccessControlManager\",\"type\":\"address\"}],\"name\":\"NewAccessControlManager\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferStarted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"oldPancakeSwapRouter\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newPancakeSwapRouter\",\"type\":\"address\"}],\"name\":\"PancakeSwapRouterUpdated\",\"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\":\"oldShortfallContract\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"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\":\"totalAmount\",\"type\":\"uint256\"}],\"name\":\"SwappedPoolsAssets\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"SweepToken\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"TransferredReserveForAuction\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"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\",\"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\"}],\"name\":\"assetsReserves\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"convertibleBaseAsset\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"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\":\"comptroller\",\"type\":\"address\"}],\"name\":\"getPoolsBaseAssetReserves\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"pancakeSwapRouter_\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmountToConvert_\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"convertibleBaseAsset_\",\"type\":\"address\"},{\"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\":\"minAmountToConvert\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pancakeSwapRouter\",\"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\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"accessControlManager_\",\"type\":\"address\"}],\"name\":\"setAccessControlManager\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_convertibleBaseAsset\",\"type\":\"address\"}],\"name\":\"setConvertibleBaseAsset\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"limit\",\"type\":\"uint256\"}],\"name\":\"setMaxLoopsLimit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minAmountToConvert_\",\"type\":\"uint256\"}],\"name\":\"setMinAmountToConvert\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"pancakeSwapRouter_\",\"type\":\"address\"}],\"name\":\"setPancakeSwapRouter\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"poolRegistry_\",\"type\":\"address\"}],\"name\":\"setPoolRegistry\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"shortfallContractAddress_\",\"type\":\"address\"}],\"name\":\"setShortfallContractAddress\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"shortfall\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"markets\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"amountsOutMin\",\"type\":\"uint256[]\"},{\"internalType\":\"address[][]\",\"name\":\"paths\",\"type\":\"address[][]\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"swapPoolsAssets\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"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\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transferReserveForAuction\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"}],\"name\":\"updateAssetsState\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Venus\",\"details\":\"This contract does not support BNB.\",\"kind\":\"dev\",\"methods\":{\"acceptOwnership()\":{\"details\":\"The new owner accepts the ownership transfer.\"},\"constructor\":{\"custom:oz-upgrades-unsafe-allow\":\"constructor\",\"details\":\"Note that the contract is upgradeable. Use initialize() or reinitializers to set the state variables.\"},\"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.\"}},\"getPoolsBaseAssetReserves(address)\":{\"params\":{\"comptroller\":\"Comptroller address(pool).\"},\"returns\":{\"_0\":\"Base Asset's reserve in risk fund.\"}},\"initialize(address,uint256,address,address,uint256)\":{\"custom:error\":\"ZeroAddressNotAllowed is thrown when PCS router address is zeroZeroAddressNotAllowed is thrown when convertible base asset address is zero\",\"params\":{\"accessControlManager_\":\"Address of the access control contract\",\"convertibleBaseAsset_\":\"Address of the base asset\",\"loopsLimit_\":\"Limit for the loops in the contract to avoid DOS\",\"minAmountToConvert_\":\"Minimum amount assets must be worth to convert into base asset\",\"pancakeSwapRouter_\":\"Address of the PancakeSwap router\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"pendingOwner()\":{\"details\":\"Returns the address of the pending owner.\"},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner.\"},\"setAccessControlManager(address)\":{\"custom:access\":\"Only Governance\",\"custom:event\":\"Emits NewAccessControlManager event\",\"details\":\"Admin function to set address of AccessControlManager\",\"params\":{\"accessControlManager_\":\"The new address of the AccessControlManager\"}},\"setConvertibleBaseAsset(address)\":{\"params\":{\"_convertibleBaseAsset\":\"Address for new convertible base asset.\"}},\"setMaxLoopsLimit(uint256)\":{\"params\":{\"limit\":\"Limit for the max loops can execute at a time\"}},\"setMinAmountToConvert(uint256)\":{\"params\":{\"minAmountToConvert_\":\"Min amount to convert.\"}},\"setPancakeSwapRouter(address)\":{\"custom:error\":\"ZeroAddressNotAllowed is thrown when PCS router address is zero\",\"params\":{\"pancakeSwapRouter_\":\"Address of the PancakeSwap router\"}},\"setPoolRegistry(address)\":{\"custom:error\":\"ZeroAddressNotAllowed is thrown when pool registry address is zero\",\"params\":{\"poolRegistry_\":\"Address of the pool registry\"}},\"setShortfallContractAddress(address)\":{\"custom:error\":\"ZeroAddressNotAllowed is thrown when shortfall contract address is zero\",\"params\":{\"shortfallContractAddress_\":\"Address of the auction contract\"}},\"swapPoolsAssets(address[],uint256[],address[][],uint256)\":{\"custom:error\":\"ZeroAddressNotAllowed is thrown if PoolRegistry contract address is not configured\",\"params\":{\"amountsOutMin\":\"Minimum amount to receive for swap\",\"deadline\":\"Deadline for the swap\",\"markets\":\"Array of vTokens whose assets to swap for base asset\",\"paths\":\"A path consisting of PCS token pairs for each swap\"},\"returns\":{\"_0\":\"Number of swapped tokens\"}},\"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.\"},\"transferReserveForAuction(address,uint256)\":{\"params\":{\"amount\":\"Amount to be transferred to auction contract.\",\"comptroller\":\"Comptroller of the pool.\"},\"returns\":{\"_0\":\"Number reserved tokens.\"}},\"updateAssetsState(address,address)\":{\"params\":{\"asset\":\"Asset address.\",\"comptroller\":\"Comptroller address(pool).\"}}},\"title\":\"RiskFund\",\"version\":1},\"userdoc\":{\"errors\":{\"ApproveFailed()\":[{\"notice\":\"Thrown if a contract is unable to approve a transfer\"}],\"MaxLoopsLimitExceeded(uint256,uint256)\":[{\"notice\":\"Thrown an error on maxLoopsLimit exceeds for any loop\"}],\"Unauthorized(address,address,string)\":[{\"notice\":\"Thrown when the action is prohibited by AccessControlManager\"}],\"ZeroAddressNotAllowed()\":[{\"notice\":\"Thrown if the supplied address is a zero address where it is not allowed\"}]},\"events\":{\"AssetsReservesUpdated(address,address,uint256)\":{\"notice\":\"Event emitted after the update of the assets reserves.\"},\"ConvertibleBaseAssetUpdated(address,address)\":{\"notice\":\"Emitted when convertible base asset is updated\"},\"MaxLoopsLimitUpdated(uint256,uint256)\":{\"notice\":\"Emitted when max loops limit is set\"},\"MinAmountToConvertUpdated(uint256,uint256)\":{\"notice\":\"Emitted when minimum amount to convert is updated\"},\"NewAccessControlManager(address,address)\":{\"notice\":\"Emitted when access control manager contract address is changed\"},\"PancakeSwapRouterUpdated(address,address)\":{\"notice\":\"Emitted when PancakeSwap router contract address is updated\"},\"PoolRegistryUpdated(address,address)\":{\"notice\":\"Emitted when pool registry address is updated\"},\"ShortfallContractUpdated(address,address)\":{\"notice\":\"Emitted when shortfall contract address is updated\"},\"SwappedPoolsAssets(address[],uint256[],uint256)\":{\"notice\":\"Emitted when pools assets are swapped\"},\"SweepToken(address,address,uint256)\":{\"notice\":\"event emitted on sweep token success\"},\"TransferredReserveForAuction(address,uint256)\":{\"notice\":\"Emitted when reserves are transferred for auction\"}},\"kind\":\"user\",\"methods\":{\"accessControlManager()\":{\"notice\":\"Returns the address of the access control manager contract\"},\"getPoolAssetReserve(address,address)\":{\"notice\":\"Get the Amount of the asset in the risk fund for the specific pool.\"},\"getPoolsBaseAssetReserves(address)\":{\"notice\":\"Get the Amount of the Base asset in the risk fund for the specific pool.\"},\"initialize(address,uint256,address,address,uint256)\":{\"notice\":\"Initializes the deployer to owner.\"},\"setAccessControlManager(address)\":{\"notice\":\"Sets the address of AccessControlManager\"},\"setConvertibleBaseAsset(address)\":{\"notice\":\"Sets a new convertible base asset\"},\"setMaxLoopsLimit(uint256)\":{\"notice\":\"Set the limit for the loops can iterate to avoid the DOS\"},\"setMinAmountToConvert(uint256)\":{\"notice\":\"Min amount to convert setter\"},\"setPancakeSwapRouter(address)\":{\"notice\":\"PancakeSwap router address setter\"},\"setPoolRegistry(address)\":{\"notice\":\"Pool registry setter\"},\"setShortfallContractAddress(address)\":{\"notice\":\"Shortfall contract address setter\"},\"swapPoolsAssets(address[],uint256[],address[][],uint256)\":{\"notice\":\"Swap array of pool assets into base asset's tokens of at least a minimum amount\"},\"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\"},\"transferReserveForAuction(address,uint256)\":{\"notice\":\"Transfer tokens for auction.\"},\"updateAssetsState(address,address)\":{\"notice\":\"Update the reserve of the asset for the specific pool after transferring to risk fund.\"}},\"notice\":\"Contract with basic features to track/hold different assets for different Comptrollers.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/RiskFund/RiskFund.sol\":\"RiskFund\"},\"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(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 \\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\":\"0xef1ca0adc3ce1ff540279d424953087771b4a07470caac99777fafd2ceea38a9\",\"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 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(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/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\",\"keccak256\":\"0x7e4d140bd2a5671389ad7a3975b65d05a4f750daf6a61c16139d123d9782b96e\",\"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/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/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\\\";\\nimport { PoolRegistry } from \\\"../Pool/PoolRegistry.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 PoolRegistry(poolRegistry).getVTokenForAsset(comptroller, asset) != address(0);\\n }\\n}\\n\",\"keccak256\":\"0xf30155bbbb7251eb8445c7d282427ed0040d015fe34efcb5ec61bc92a289b0cc\",\"license\":\"BSD-3-Clause\"},\"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\",\"keccak256\":\"0x918526b067c834935f5dd0788139e1a73c64cbf6f8b7d6fd43242eaa93aa7f37\",\"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(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 \\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 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 \\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(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\",\"keccak256\":\"0xcda9eb71f6ceb8a4c3bfbc1c42d72e2f0523d30f6d3252fbd90819e953640fe5\",\"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(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\":\"0x2947e95eb97a3a45f90ec36d4fd5a4cbb9409319f6ad000e950550055a3f2324\",\"license\":\"BSD-3-Clause\"},\"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\",\"keccak256\":\"0x9bbc31c80a4c537ddfd06cbd03a412ba64842a708381fbc4bf2e33ef56c92b4d\",\"license\":\"MIT\"},\"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": "0x60e06040523480156200001157600080fd5b50604051620032b8380380620032b883398101604081905262000034916200018c565b828282620000428362000083565b6200004d8262000083565b620000588162000083565b6001600160a01b0392831660805290821660a0521660c0526200007a620000ae565b505050620001d6565b6001600160a01b038116620000ab576040516342bcdf7f60e11b815260040160405180910390fd5b50565b600054610100900460ff16156200011b5760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b60005460ff908116146200016d576000805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b80516001600160a01b03811681146200018757600080fd5b919050565b600080600060608486031215620001a257600080fd5b620001ad846200016f565b9250620001bd602085016200016f565b9150620001cd604085016200016f565b90509250925092565b60805160a05160c05161309662000222600039600081816102bf015261258601526000818161029801526124c3015260008181610437015281816122df015261240c01526130966000f3fe608060405234801561001057600080fd5b50600436106101da5760003560e01c806377d4937f11610104578063afcff50f116100a2578063e30c397811610071578063e30c39781461040e578063f2fde38b1461041f578063fa7b81a014610432578063fe3da9841461045957600080fd5b8063afcff50f146103cd578063b4a0bdf3146103e0578063be26317e146103f1578063c8ecc0d3146103fa57600080fd5b806380d45a2d116100de57806380d45a2d146103835780638da5cb5b14610396578063a69bd19e146103a7578063aac59a75146103ba57600080fd5b806377d4937f1461035557806379ba5097146103685780637b77cd6a1461037057600080fd5b80633421fc521161017c5780635f30e37b1161014b5780635f30e37b146103145780636fb0527514610327578063715018a61461033a578063746460a91461034257600080fd5b80633421fc5214610293578063362b6795146102ba578063439b5517146102e15780634dd9584a1461030157600080fd5b806324558995116101b85780632455899514610246578063258836fe1461025a5780632a1d05471461026d5780632e6881411461028057600080fd5b80630a9837c5146101df5780630e32cb861461020557806319b1faef1461021a575b600080fd5b6101f26101ed366004612779565b610463565b6040519081526020015b60405180910390f35b6102186102133660046127a5565b610632565b005b61012e5461022e906001600160a01b031681565b6040516001600160a01b0390911681526020016101fc565b61012f5461022e906001600160a01b031681565b6102186102683660046127c2565b610646565b61021861027b3660046127fb565b6107d7565b61021861028e3660046127a5565b6109c8565b61022e7f000000000000000000000000000000000000000000000000000000000000000081565b61022e7f000000000000000000000000000000000000000000000000000000000000000081565b6101f26102ef3660046127a5565b60c96020526000908152604090205481565b61021861030f3660046127a5565b610acd565b6101f26103223660046128a2565b610b31565b6101f26103353660046127c2565b611085565b61021861113b565b610218610350366004612945565b61114f565b6102186103633660046127a5565b6111f4565b610218611258565b61021861037e3660046127a5565b6112cf565b610218610391366004612945565b611332565b6033546001600160a01b031661022e565b6101f26103b53660046127a5565b611343565b6102186103c83660046127c2565b61142f565b60cb5461022e906001600160a01b031681565b6097546001600160a01b031661022e565b6101f260fb5481565b61012d5461022e906001600160a01b031681565b6065546001600160a01b031661022e565b61021861042d3660046127a5565b61143d565b61022e7f000000000000000000000000000000000000000000000000000000000000000081565b6101f26101305481565b6000600260cc54036104905760405162461bcd60e51b81526004016104879061295e565b60405180910390fd5b600260cc5561012e546001600160a01b03163381146105085760405162461bcd60e51b815260206004820152602e60248201527f5269736b2066756e643a204f6e6c792063616c6c61626c652062792053686f7260448201526d1d19985b1b0818dbdb9d1c9858dd60921b6064820152608401610487565b6001600160a01b03808516600090815260ca6020908152604080832061012d549094168352929052205483111561058f5760405162461bcd60e51b815260206004820152602560248201527f5269736b2046756e643a20496e73756666696369656e7420706f6f6c2072657360448201526432b93b329760d91b6064820152608401610487565b6001600160a01b03808516600081815260ca6020908152604080832061012d80548716855290835281842080548a9003905554909416825260c990528290208054869003905590517fc8d0a37ed16dfaa43514df00e18f478b60d5cc7b4bfc687103948b9020f737fd906106069086815260200190565b60405180910390a261012d54610626906001600160a01b031682856114ae565b5050600160cc55919050565b61063a611505565b6106438161155f565b50565b61064e611505565b600260cc54036106705760405162461bcd60e51b81526004016104879061295e565b600260cc5561067e8161161d565b6040516370a0823160e01b815230600482015260009081906001600160a01b038516906370a0823190602401602060405180830381865afa1580156106c7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106eb9190612982565b6001600160a01b038516600090815260c9602052604090205490915081116107615760405162461bcd60e51b815260206004820152602360248201527f5265736572766548656c706572733a205a65726f20737572706c757320746f6b604482015262656e7360e81b6064820152608401610487565b6001600160a01b03848116600081815260c960209081526040918290205491519185038083529550928616927f6d25be279134f4ecaa4770aff0c3d916d9e7c5ef37b65ed95dbdba411f5d54d5910160405180910390a36107cc6001600160a01b03851684846114ae565b5050600160cc555050565b600054610100900460ff16158080156107f75750600054600160ff909116105b806108115750303b158015610811575060005460ff166001145b6108745760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610487565b6000805460ff191660011790558015610897576000805461ff0019166101001790555b6108a08661161d565b6108a98461161d565b600085116108c95760405162461bcd60e51b81526004016104879061299b565b600082116109285760405162461bcd60e51b815260206004820152602660248201527f5269736b2046756e643a204c6f6f7073206c696d69742063616e206e6f74206260448201526565207a65726f60d01b6064820152608401610487565b610930611644565b61093983611673565b61012f80546001600160a01b038089166001600160a01b03199283161790925561013087905561012d80549287169290911691909117905561097a8261169a565b80156109c0576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050565b610a066040518060400160405280602081526020017f736574436f6e7665727469626c65426173654173736574286164647265737329815250611734565b6001600160a01b038116610a7a5760405162461bcd60e51b815260206004820152603560248201527f5269736b2046756e643a206e657720636f6e7665727469626c65206261736520604482015274185cdcd95d081859191c995cdcc81a5b9d985b1a59605a1b6064820152608401610487565b61012d80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f5fa61583da12070720613fefdd68cc6c0e464a71e009742526bd2b2e0ac62cd290600090a35050565b610ad5611505565b610ade8161161d565b61012f80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907fd37b9d138f53ea58d7e50292588239a46efa8f523966febf4066da96defc77fd90600090a35050565b6000600260cc5403610b555760405162461bcd60e51b81526004016104879061295e565b600260cc81905550610b7e60405180606001604052806038815260200161302960389139611734565b42821015610bce5760405162461bcd60e51b815260206004820152601a60248201527f5269736b2066756e643a20646561646c696e65207061737365640000000000006044820152606401610487565b60cb546001600160a01b0316610be38161161d565b878614610c585760405162461bcd60e51b815260206004820152603860248201527f5269736b2066756e643a206d61726b65747320616e6420616d6f756e74734f7560448201527f744d696e2061726520756e657175616c206c656e6774687300000000000000006064820152608401610487565b878414610cc05760405162461bcd60e51b815260206004820152603060248201527f5269736b2066756e643a206d61726b65747320616e642070617468732061726560448201526f20756e657175616c206c656e6774687360801b6064820152608401610487565b600088610ccc816117ce565b60005b818110156110325760008c8c83818110610ceb57610ceb6129e3565b9050602002016020810190610d0091906127a5565b6001600160a01b0316635fe3b5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d3d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d6191906129f9565b604051637aee632d60e01b81526001600160a01b038083166004830152919250600091871690637aee632d90602401600060405180830381865afa158015610dad573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610dd59190810190612ac6565b9050816001600160a01b031681604001516001600160a01b031614610e4c5760405162461bcd60e51b815260206004820152602760248201527f636f6d7074726f6c6c657220646f65736e277420657869737420706f6f6c20726044820152666567697374727960c81b6064820152608401610487565b816001600160a01b0316633d98a1e58f8f86818110610e6d57610e6d6129e3565b9050602002016020810190610e8291906127a5565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa158015610ec6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610eea9190612bbc565b610f2d5760405162461bcd60e51b81526020600482015260146024820152731b585c9ad95d081a5cc81b9bdd081b1a5cdd195960621b6044820152606401610487565b6000610f9c8f8f86818110610f4457610f446129e3565b9050602002016020810190610f5991906127a5565b848f8f88818110610f6c57610f6c6129e3565b905060200201358e8e89818110610f8557610f856129e3565b9050602002810190610f979190612bde565b6117ff565b6001600160a01b03808516600090815260ca6020908152604080832061012d54909416835292905290812080549293508392909190610fdc908490612c3e565b909155505061012d546001600160a01b0316600090815260c960205260408120805483929061100c908490612c3e565b9091555061101c90508187612c3e565b95505050508061102b90612c56565b9050610ccf565b507fb17530966b045b50d4975e7f05048ca00d7335780c24f1c465165a4b94b2d37d8b8b8b8b8660405161106a959493929190612cb8565b60405180910390a150600160cc559998505050505050505050565b60006110908261161d565b826001600160a01b0316627e3dd26040518163ffffffff1660e01b8152600401602060405180830381865afa1580156110cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110f19190612bbc565b61110d5760405162461bcd60e51b815260040161048790612d13565b506001600160a01b03808316600090815260ca60209081526040808320938516835292905220545b92915050565b611143611505565b61114d6000611da2565b565b61118d6040518060400160405280601e81526020017f7365744d696e416d6f756e74546f436f6e766572742875696e74323536290000815250611734565b600081116111ad5760405162461bcd60e51b81526004016104879061299b565b61013080549082905560408051828152602081018490527fada67d0d38fa20c8ae6a5c17cb9d60b0fe7f2d4e4f27ac9ee55e54ac88de9d8d91015b60405180910390a15050565b6111fc611505565b6112058161161d565b61012e80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907fb6e5fcf02f7fbb8acfbaa3bac4fd5abf9ff51e3f2e8884b5498927179b211b2890600090a35050565b60655433906001600160a01b031681146112c65760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b6064820152608401610487565b61064381611da2565b6112d7611505565b6112e08161161d565b60cb80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907fa87b964d321035d2165e484ff4b722dd6eae30606c0b98887d2ed1a34e594bfe90600090a35050565b61133a611505565b6106438161169a565b6000816001600160a01b0316627e3dd26040518163ffffffff1660e01b8152600401602060405180830381865afa158015611382573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113a69190612bbc565b6114015760405162461bcd60e51b815260206004820152602660248201527f5269736b2046756e643a20436f6d7074726f6c6c6572206164647265737320696044820152651b9d985b1a5960d21b6064820152608401610487565b506001600160a01b03908116600090815260ca6020908152604080832061012d549094168352929052205490565b6114398282611dbb565b5050565b611445611505565b606580546001600160a01b0383166001600160a01b031990911681179091556114766033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b179052611500908490612078565b505050565b6033546001600160a01b0316331461114d5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610487565b6001600160a01b0381166115c35760405162461bcd60e51b815260206004820152602560248201527f696e76616c696420616365737320636f6e74726f6c206d616e61676572206164604482015264647265737360d81b6064820152608401610487565b609780546001600160a01b038381166001600160a01b031983168117909355604080519190921680825260208201939093527f66fd58e82f7b31a2a5c30e0888f3093efe4e111b00cd2b0c31fe014601293aa091016111e8565b6001600160a01b038116610643576040516342bcdf7f60e11b815260040160405180910390fd5b600054610100900460ff1661166b5760405162461bcd60e51b815260040161048790612d5e565b61114d61214d565b600054610100900460ff1661063a5760405162461bcd60e51b815260040161048790612d5e565b60fb5481116116f65760405162461bcd60e51b815260206004820152602260248201527f436f6d7074726f6c6c65723a20496e76616c6964206d61784c6f6f70734c696d6044820152611a5d60f21b6064820152608401610487565b60fb80549082905560408051828152602081018490527fc2d09fef144f7c8a86f71ea459f8fc17f675768eb1ae369cbd77fb31d467aafa91016111e8565b6097546040516318c5e8ab60e01b81526000916001600160a01b0316906318c5e8ab906117679033908690600401612dd5565b602060405180830381865afa158015611784573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117a89190612bbc565b90508061143957333083604051634a3fa29360e01b815260040161048793929190612df9565b60fb548111156106435760fb5460405163792bfb1b60e11b8152600481019190915260248101829052604401610487565b6000836000036118775760405162461bcd60e51b815260206004820152603c60248201527f5269736b46756e643a20616d6f756e744f75744d696e206d757374206265206760448201527f726561746572207468616e203020746f20737761702076546f6b656e000000006064820152608401610487565b600080876001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa1580156118b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118dc91906129f9565b61012d546001600160a01b03898116600090815260ca60209081526040808320848716845290915281205493945091169190819003611922576000945050505050611d99565b6000896001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa158015611962573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061198691906129f9565b60405163b62cad6960e01b81526001600160a01b0385811660048301529192509082169063b62cad6990602401600060405180830381600087803b1580156119cd57600080fd5b505af11580156119e1573d6000803e3d6000fd5b50506040805160208101918290526341976e0960e01b9091526001600160a01b03868116602483015260009350909150819084166341976e0960448301602060405180830381865afa158015611a3b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a5f9190612982565b905290506000611a6f828c61217d565b905061013054811015611ad25760405162461bcd60e51b815260206004820152602560248201527f5269736b46756e643a206d696e416d6f756e74546f436f6e766572742076696f6044820152641b185d195960da1b6064820152608401610487565b6001600160a01b038616600090815260c9602052604081208054869290611afa908490612e25565b90915550506001600160a01b03808d16600090815260ca60209081526040808320938a1683529290529081208054869290611b36908490612e25565b90915550506001600160a01b0386811690861614611d8b57856001600160a01b03168a8a6000818110611b6b57611b6b6129e3565b9050602002016020810190611b8091906127a5565b6001600160a01b031614611bfc5760405162461bcd60e51b815260206004820152603860248201527f5269736b46756e643a20737761702070617468206d757374207374617274207760448201527f6974682074686520756e6465726c79696e6720617373657400000000000000006064820152608401610487565b6001600160a01b0385168a8a611c13600182612e25565b818110611c2257611c226129e3565b9050602002016020810190611c3791906127a5565b6001600160a01b031614611cab5760405162461bcd60e51b815260206004820152603560248201527f5269736b46756e643a2066696e616c6c792070617468206d75737420626520636044820152741bdb9d995c9d1a589b194818985cd948185cdcd95d605a1b6064820152608401610487565b61012f546001600160a01b0390811690611cc990881682600061219d565b611cdd6001600160a01b038816828761219d565b6000816001600160a01b03166338ed1739878f8f8f30426040518763ffffffff1660e01b8152600401611d1596959493929190612e3c565b6000604051808303816000875af1158015611d34573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611d5c9190810190612e9e565b905080611d6a60018d612e25565b81518110611d7a57611d7a6129e3565b602002602001015198505050611d8f565b8396505b5094955050505050505b95945050505050565b606580546001600160a01b031916905561064381612289565b611dc48161161d565b816001600160a01b0316627e3dd26040518163ffffffff1660e01b8152600401602060405180830381865afa158015611e01573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e259190612bbc565b611e415760405162461bcd60e51b815260040161048790612d13565b60cb546001600160a01b031680611eb35760405162461bcd60e51b815260206004820152603060248201527f5265736572766548656c706572733a20506f6f6c20526567697374727920616460448201526f191c995cdcc81a5cc81b9bdd081cd95d60821b6064820152608401610487565b611ebd83836122db565b611f245760405162461bcd60e51b815260206004820152603260248201527f5265736572766548656c706572733a2054686520706f6f6c20646f65736e2774604482015271081cdd5c1c1bdc9d081d1a1948185cdcd95d60721b6064820152608401610487565b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa158015611f6b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f8f9190612982565b6001600160a01b038416600090815260c9602052604090205490915080821115612071576001600160a01b038416600090815260c960205260408120805483850392839291611fdf908490612c3e565b90915550506001600160a01b03808716600090815260ca602090815260408083209389168352929052908120805483929061201b908490612c3e565b92505081905550846001600160a01b0316866001600160a01b03167fc39e3e80c0219fde334a8cb5d8468b628482e23388b6e809c90cb00c63c8ce388360405161206791815260200190565b60405180910390a3505b5050505050565b60006120cd826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166123af9092919063ffffffff16565b90508051600014806120ee5750808060200190518101906120ee9190612bbc565b6115005760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610487565b600054610100900460ff166121745760405162461bcd60e51b815260040161048790612d5e565b61114d33611da2565b60008061218a84846123be565b9050612195816123ef565b949350505050565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663095ea7b360e01b1790529151909160009182918716906121fb908590612f29565b6000604051808303816000865af19150503d8060008114612238576040519150601f19603f3d011682016040523d82523d6000602084013e61223d565b606091505b509150915081158061226b575080511580159061226b5750808060200190518101906122699190612bbc565b155b156109c057604051633e3f8f7360e01b815260040160405180910390fd5b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316836001600160a01b0316036123265761231f82612407565b9050611135565b60cb5460405163266e0a7f60e01b81526001600160a01b0385811660048301528481166024830152600092169063266e0a7f90604401602060405180830381865afa158015612379573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061239d91906129f9565b6001600160a01b031614159392505050565b606061219584846000856125d8565b60408051602081019091526000815260405180602001604052806123e68560000151856126b3565b90529392505050565b805160009061113590670de0b6b3a764000090612f45565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b0772d0b6040518163ffffffff1660e01b8152600401600060405180830381865afa158015612468573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526124909190810190612f67565b905060005b81518110156125d1578181815181106124b0576124b06129e3565b60200260200101516001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03161461258457836001600160a01b031682828151811061250c5761250c6129e3565b60200260200101516001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa158015612551573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061257591906129f9565b6001600160a01b0316146125ba565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316846001600160a01b0316145b9250826125d1576125ca81612c56565b9050612495565b5050919050565b6060824710156126395760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610487565b600080866001600160a01b031685876040516126559190612f29565b60006040518083038185875af1925050503d8060008114612692576040519150601f19603f3d011682016040523d82523d6000602084013e612697565b606091505b50915091506126a8878383876126c6565b979650505050505050565b60006126bf8284612ff6565b9392505050565b6060831561273557825160000361272e576001600160a01b0385163b61272e5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610487565b5081612195565b612195838381511561274a5781518083602001fd5b8060405162461bcd60e51b81526004016104879190613015565b6001600160a01b038116811461064357600080fd5b6000806040838503121561278c57600080fd5b823561279781612764565b946020939093013593505050565b6000602082840312156127b757600080fd5b81356126bf81612764565b600080604083850312156127d557600080fd5b82356127e081612764565b915060208301356127f081612764565b809150509250929050565b600080600080600060a0868803121561281357600080fd5b853561281e81612764565b945060208601359350604086013561283581612764565b9250606086013561284581612764565b949793965091946080013592915050565b60008083601f84011261286857600080fd5b50813567ffffffffffffffff81111561288057600080fd5b6020830191508360208260051b850101111561289b57600080fd5b9250929050565b60008060008060008060006080888a0312156128bd57600080fd5b873567ffffffffffffffff808211156128d557600080fd5b6128e18b838c01612856565b909950975060208a01359150808211156128fa57600080fd5b6129068b838c01612856565b909750955060408a013591508082111561291f57600080fd5b5061292c8a828b01612856565b989b979a50959894979596606090950135949350505050565b60006020828403121561295757600080fd5b5035919050565b6020808252600a90820152691c994b595b9d195c995960b21b604082015260600190565b60006020828403121561299457600080fd5b5051919050565b60208082526028908201527f5269736b2046756e643a20496e76616c6964206d696e20616d6f756e7420746f6040820152670818dbdb9d995c9d60c21b606082015260800190565b634e487b7160e01b600052603260045260246000fd5b600060208284031215612a0b57600080fd5b81516126bf81612764565b634e487b7160e01b600052604160045260246000fd5b60405160a0810167ffffffffffffffff81118282101715612a4f57612a4f612a16565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715612a7e57612a7e612a16565b604052919050565b60005b83811015612aa1578181015183820152602001612a89565b83811115612ab0576000848401525b50505050565b8051612ac181612764565b919050565b60006020808385031215612ad957600080fd5b825167ffffffffffffffff80821115612af157600080fd5b9084019060a08287031215612b0557600080fd5b612b0d612a2c565b825182811115612b1c57600080fd5b8301601f81018813612b2d57600080fd5b805183811115612b3f57612b3f612a16565b612b51601f8201601f19168701612a55565b93508084528886828401011115612b6757600080fd5b612b7681878601888501612a86565b5050818152612b86848401612ab6565b84820152612b9660408401612ab6565b604082015260608301516060820152608083015160808201528094505050505092915050565b600060208284031215612bce57600080fd5b815180151581146126bf57600080fd5b6000808335601e19843603018112612bf557600080fd5b83018035915067ffffffffffffffff821115612c1057600080fd5b6020019150600581901b360382131561289b57600080fd5b634e487b7160e01b600052601160045260246000fd5b60008219821115612c5157612c51612c28565b500190565b600060018201612c6857612c68612c28565b5060010190565b8183526000602080850194508260005b85811015612cad578135612c9281612764565b6001600160a01b031687529582019590820190600101612c7f565b509495945050505050565b606081526000612ccc606083018789612c6f565b82810360208401528481526001600160fb1b03851115612ceb57600080fd5b8460051b80876020840137600091016020019081526040929092019290925295945050505050565b6020808252602b908201527f5265736572766548656c706572733a20436f6d7074726f6c6c6572206164647260408201526a195cdcc81a5b9d985b1a5960aa1b606082015260800190565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b60008151808452612dc1816020860160208601612a86565b601f01601f19169290920160200192915050565b6001600160a01b038316815260406020820181905260009061219590830184612da9565b6001600160a01b03848116825283166020820152606060408201819052600090611d9990830184612da9565b600082821015612e3757612e37612c28565b500390565b86815285602082015260a060408201526000612e5c60a083018688612c6f565b6001600160a01b039490941660608301525060800152949350505050565b600067ffffffffffffffff821115612e9457612e94612a16565b5060051b60200190565b60006020808385031215612eb157600080fd5b825167ffffffffffffffff811115612ec857600080fd5b8301601f81018513612ed957600080fd5b8051612eec612ee782612e7a565b612a55565b81815260059190911b82018301908381019087831115612f0b57600080fd5b928401925b828410156126a857835182529284019290840190612f10565b60008251612f3b818460208701612a86565b9190910192915050565b600082612f6257634e487b7160e01b600052601260045260246000fd5b500490565b60006020808385031215612f7a57600080fd5b825167ffffffffffffffff811115612f9157600080fd5b8301601f81018513612fa257600080fd5b8051612fb0612ee782612e7a565b81815260059190911b82018301908381019087831115612fcf57600080fd5b928401925b828410156126a8578351612fe781612764565b82529284019290840190612fd4565b600081600019048311821515161561301057613010612c28565b500290565b6020815260006126bf6020830184612da956fe73776170506f6f6c7341737365747328616464726573735b5d2c75696e743235365b5d2c616464726573735b5d5b5d2c75696e7432353629a2646970667358221220c967afe4ee07c007702bfe8b40ad090042c372456a0a152775ad412949fc6bc564736f6c634300080d0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101da5760003560e01c806377d4937f11610104578063afcff50f116100a2578063e30c397811610071578063e30c39781461040e578063f2fde38b1461041f578063fa7b81a014610432578063fe3da9841461045957600080fd5b8063afcff50f146103cd578063b4a0bdf3146103e0578063be26317e146103f1578063c8ecc0d3146103fa57600080fd5b806380d45a2d116100de57806380d45a2d146103835780638da5cb5b14610396578063a69bd19e146103a7578063aac59a75146103ba57600080fd5b806377d4937f1461035557806379ba5097146103685780637b77cd6a1461037057600080fd5b80633421fc521161017c5780635f30e37b1161014b5780635f30e37b146103145780636fb0527514610327578063715018a61461033a578063746460a91461034257600080fd5b80633421fc5214610293578063362b6795146102ba578063439b5517146102e15780634dd9584a1461030157600080fd5b806324558995116101b85780632455899514610246578063258836fe1461025a5780632a1d05471461026d5780632e6881411461028057600080fd5b80630a9837c5146101df5780630e32cb861461020557806319b1faef1461021a575b600080fd5b6101f26101ed366004612779565b610463565b6040519081526020015b60405180910390f35b6102186102133660046127a5565b610632565b005b61012e5461022e906001600160a01b031681565b6040516001600160a01b0390911681526020016101fc565b61012f5461022e906001600160a01b031681565b6102186102683660046127c2565b610646565b61021861027b3660046127fb565b6107d7565b61021861028e3660046127a5565b6109c8565b61022e7f000000000000000000000000000000000000000000000000000000000000000081565b61022e7f000000000000000000000000000000000000000000000000000000000000000081565b6101f26102ef3660046127a5565b60c96020526000908152604090205481565b61021861030f3660046127a5565b610acd565b6101f26103223660046128a2565b610b31565b6101f26103353660046127c2565b611085565b61021861113b565b610218610350366004612945565b61114f565b6102186103633660046127a5565b6111f4565b610218611258565b61021861037e3660046127a5565b6112cf565b610218610391366004612945565b611332565b6033546001600160a01b031661022e565b6101f26103b53660046127a5565b611343565b6102186103c83660046127c2565b61142f565b60cb5461022e906001600160a01b031681565b6097546001600160a01b031661022e565b6101f260fb5481565b61012d5461022e906001600160a01b031681565b6065546001600160a01b031661022e565b61021861042d3660046127a5565b61143d565b61022e7f000000000000000000000000000000000000000000000000000000000000000081565b6101f26101305481565b6000600260cc54036104905760405162461bcd60e51b81526004016104879061295e565b60405180910390fd5b600260cc5561012e546001600160a01b03163381146105085760405162461bcd60e51b815260206004820152602e60248201527f5269736b2066756e643a204f6e6c792063616c6c61626c652062792053686f7260448201526d1d19985b1b0818dbdb9d1c9858dd60921b6064820152608401610487565b6001600160a01b03808516600090815260ca6020908152604080832061012d549094168352929052205483111561058f5760405162461bcd60e51b815260206004820152602560248201527f5269736b2046756e643a20496e73756666696369656e7420706f6f6c2072657360448201526432b93b329760d91b6064820152608401610487565b6001600160a01b03808516600081815260ca6020908152604080832061012d80548716855290835281842080548a9003905554909416825260c990528290208054869003905590517fc8d0a37ed16dfaa43514df00e18f478b60d5cc7b4bfc687103948b9020f737fd906106069086815260200190565b60405180910390a261012d54610626906001600160a01b031682856114ae565b5050600160cc55919050565b61063a611505565b6106438161155f565b50565b61064e611505565b600260cc54036106705760405162461bcd60e51b81526004016104879061295e565b600260cc5561067e8161161d565b6040516370a0823160e01b815230600482015260009081906001600160a01b038516906370a0823190602401602060405180830381865afa1580156106c7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106eb9190612982565b6001600160a01b038516600090815260c9602052604090205490915081116107615760405162461bcd60e51b815260206004820152602360248201527f5265736572766548656c706572733a205a65726f20737572706c757320746f6b604482015262656e7360e81b6064820152608401610487565b6001600160a01b03848116600081815260c960209081526040918290205491519185038083529550928616927f6d25be279134f4ecaa4770aff0c3d916d9e7c5ef37b65ed95dbdba411f5d54d5910160405180910390a36107cc6001600160a01b03851684846114ae565b5050600160cc555050565b600054610100900460ff16158080156107f75750600054600160ff909116105b806108115750303b158015610811575060005460ff166001145b6108745760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610487565b6000805460ff191660011790558015610897576000805461ff0019166101001790555b6108a08661161d565b6108a98461161d565b600085116108c95760405162461bcd60e51b81526004016104879061299b565b600082116109285760405162461bcd60e51b815260206004820152602660248201527f5269736b2046756e643a204c6f6f7073206c696d69742063616e206e6f74206260448201526565207a65726f60d01b6064820152608401610487565b610930611644565b61093983611673565b61012f80546001600160a01b038089166001600160a01b03199283161790925561013087905561012d80549287169290911691909117905561097a8261169a565b80156109c0576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050565b610a066040518060400160405280602081526020017f736574436f6e7665727469626c65426173654173736574286164647265737329815250611734565b6001600160a01b038116610a7a5760405162461bcd60e51b815260206004820152603560248201527f5269736b2046756e643a206e657720636f6e7665727469626c65206261736520604482015274185cdcd95d081859191c995cdcc81a5b9d985b1a59605a1b6064820152608401610487565b61012d80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f5fa61583da12070720613fefdd68cc6c0e464a71e009742526bd2b2e0ac62cd290600090a35050565b610ad5611505565b610ade8161161d565b61012f80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907fd37b9d138f53ea58d7e50292588239a46efa8f523966febf4066da96defc77fd90600090a35050565b6000600260cc5403610b555760405162461bcd60e51b81526004016104879061295e565b600260cc81905550610b7e60405180606001604052806038815260200161302960389139611734565b42821015610bce5760405162461bcd60e51b815260206004820152601a60248201527f5269736b2066756e643a20646561646c696e65207061737365640000000000006044820152606401610487565b60cb546001600160a01b0316610be38161161d565b878614610c585760405162461bcd60e51b815260206004820152603860248201527f5269736b2066756e643a206d61726b65747320616e6420616d6f756e74734f7560448201527f744d696e2061726520756e657175616c206c656e6774687300000000000000006064820152608401610487565b878414610cc05760405162461bcd60e51b815260206004820152603060248201527f5269736b2066756e643a206d61726b65747320616e642070617468732061726560448201526f20756e657175616c206c656e6774687360801b6064820152608401610487565b600088610ccc816117ce565b60005b818110156110325760008c8c83818110610ceb57610ceb6129e3565b9050602002016020810190610d0091906127a5565b6001600160a01b0316635fe3b5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d3d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d6191906129f9565b604051637aee632d60e01b81526001600160a01b038083166004830152919250600091871690637aee632d90602401600060405180830381865afa158015610dad573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610dd59190810190612ac6565b9050816001600160a01b031681604001516001600160a01b031614610e4c5760405162461bcd60e51b815260206004820152602760248201527f636f6d7074726f6c6c657220646f65736e277420657869737420706f6f6c20726044820152666567697374727960c81b6064820152608401610487565b816001600160a01b0316633d98a1e58f8f86818110610e6d57610e6d6129e3565b9050602002016020810190610e8291906127a5565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa158015610ec6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610eea9190612bbc565b610f2d5760405162461bcd60e51b81526020600482015260146024820152731b585c9ad95d081a5cc81b9bdd081b1a5cdd195960621b6044820152606401610487565b6000610f9c8f8f86818110610f4457610f446129e3565b9050602002016020810190610f5991906127a5565b848f8f88818110610f6c57610f6c6129e3565b905060200201358e8e89818110610f8557610f856129e3565b9050602002810190610f979190612bde565b6117ff565b6001600160a01b03808516600090815260ca6020908152604080832061012d54909416835292905290812080549293508392909190610fdc908490612c3e565b909155505061012d546001600160a01b0316600090815260c960205260408120805483929061100c908490612c3e565b9091555061101c90508187612c3e565b95505050508061102b90612c56565b9050610ccf565b507fb17530966b045b50d4975e7f05048ca00d7335780c24f1c465165a4b94b2d37d8b8b8b8b8660405161106a959493929190612cb8565b60405180910390a150600160cc559998505050505050505050565b60006110908261161d565b826001600160a01b0316627e3dd26040518163ffffffff1660e01b8152600401602060405180830381865afa1580156110cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110f19190612bbc565b61110d5760405162461bcd60e51b815260040161048790612d13565b506001600160a01b03808316600090815260ca60209081526040808320938516835292905220545b92915050565b611143611505565b61114d6000611da2565b565b61118d6040518060400160405280601e81526020017f7365744d696e416d6f756e74546f436f6e766572742875696e74323536290000815250611734565b600081116111ad5760405162461bcd60e51b81526004016104879061299b565b61013080549082905560408051828152602081018490527fada67d0d38fa20c8ae6a5c17cb9d60b0fe7f2d4e4f27ac9ee55e54ac88de9d8d91015b60405180910390a15050565b6111fc611505565b6112058161161d565b61012e80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907fb6e5fcf02f7fbb8acfbaa3bac4fd5abf9ff51e3f2e8884b5498927179b211b2890600090a35050565b60655433906001600160a01b031681146112c65760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b6064820152608401610487565b61064381611da2565b6112d7611505565b6112e08161161d565b60cb80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907fa87b964d321035d2165e484ff4b722dd6eae30606c0b98887d2ed1a34e594bfe90600090a35050565b61133a611505565b6106438161169a565b6000816001600160a01b0316627e3dd26040518163ffffffff1660e01b8152600401602060405180830381865afa158015611382573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113a69190612bbc565b6114015760405162461bcd60e51b815260206004820152602660248201527f5269736b2046756e643a20436f6d7074726f6c6c6572206164647265737320696044820152651b9d985b1a5960d21b6064820152608401610487565b506001600160a01b03908116600090815260ca6020908152604080832061012d549094168352929052205490565b6114398282611dbb565b5050565b611445611505565b606580546001600160a01b0383166001600160a01b031990911681179091556114766033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b179052611500908490612078565b505050565b6033546001600160a01b0316331461114d5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610487565b6001600160a01b0381166115c35760405162461bcd60e51b815260206004820152602560248201527f696e76616c696420616365737320636f6e74726f6c206d616e61676572206164604482015264647265737360d81b6064820152608401610487565b609780546001600160a01b038381166001600160a01b031983168117909355604080519190921680825260208201939093527f66fd58e82f7b31a2a5c30e0888f3093efe4e111b00cd2b0c31fe014601293aa091016111e8565b6001600160a01b038116610643576040516342bcdf7f60e11b815260040160405180910390fd5b600054610100900460ff1661166b5760405162461bcd60e51b815260040161048790612d5e565b61114d61214d565b600054610100900460ff1661063a5760405162461bcd60e51b815260040161048790612d5e565b60fb5481116116f65760405162461bcd60e51b815260206004820152602260248201527f436f6d7074726f6c6c65723a20496e76616c6964206d61784c6f6f70734c696d6044820152611a5d60f21b6064820152608401610487565b60fb80549082905560408051828152602081018490527fc2d09fef144f7c8a86f71ea459f8fc17f675768eb1ae369cbd77fb31d467aafa91016111e8565b6097546040516318c5e8ab60e01b81526000916001600160a01b0316906318c5e8ab906117679033908690600401612dd5565b602060405180830381865afa158015611784573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117a89190612bbc565b90508061143957333083604051634a3fa29360e01b815260040161048793929190612df9565b60fb548111156106435760fb5460405163792bfb1b60e11b8152600481019190915260248101829052604401610487565b6000836000036118775760405162461bcd60e51b815260206004820152603c60248201527f5269736b46756e643a20616d6f756e744f75744d696e206d757374206265206760448201527f726561746572207468616e203020746f20737761702076546f6b656e000000006064820152608401610487565b600080876001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa1580156118b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118dc91906129f9565b61012d546001600160a01b03898116600090815260ca60209081526040808320848716845290915281205493945091169190819003611922576000945050505050611d99565b6000896001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa158015611962573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061198691906129f9565b60405163b62cad6960e01b81526001600160a01b0385811660048301529192509082169063b62cad6990602401600060405180830381600087803b1580156119cd57600080fd5b505af11580156119e1573d6000803e3d6000fd5b50506040805160208101918290526341976e0960e01b9091526001600160a01b03868116602483015260009350909150819084166341976e0960448301602060405180830381865afa158015611a3b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a5f9190612982565b905290506000611a6f828c61217d565b905061013054811015611ad25760405162461bcd60e51b815260206004820152602560248201527f5269736b46756e643a206d696e416d6f756e74546f436f6e766572742076696f6044820152641b185d195960da1b6064820152608401610487565b6001600160a01b038616600090815260c9602052604081208054869290611afa908490612e25565b90915550506001600160a01b03808d16600090815260ca60209081526040808320938a1683529290529081208054869290611b36908490612e25565b90915550506001600160a01b0386811690861614611d8b57856001600160a01b03168a8a6000818110611b6b57611b6b6129e3565b9050602002016020810190611b8091906127a5565b6001600160a01b031614611bfc5760405162461bcd60e51b815260206004820152603860248201527f5269736b46756e643a20737761702070617468206d757374207374617274207760448201527f6974682074686520756e6465726c79696e6720617373657400000000000000006064820152608401610487565b6001600160a01b0385168a8a611c13600182612e25565b818110611c2257611c226129e3565b9050602002016020810190611c3791906127a5565b6001600160a01b031614611cab5760405162461bcd60e51b815260206004820152603560248201527f5269736b46756e643a2066696e616c6c792070617468206d75737420626520636044820152741bdb9d995c9d1a589b194818985cd948185cdcd95d605a1b6064820152608401610487565b61012f546001600160a01b0390811690611cc990881682600061219d565b611cdd6001600160a01b038816828761219d565b6000816001600160a01b03166338ed1739878f8f8f30426040518763ffffffff1660e01b8152600401611d1596959493929190612e3c565b6000604051808303816000875af1158015611d34573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611d5c9190810190612e9e565b905080611d6a60018d612e25565b81518110611d7a57611d7a6129e3565b602002602001015198505050611d8f565b8396505b5094955050505050505b95945050505050565b606580546001600160a01b031916905561064381612289565b611dc48161161d565b816001600160a01b0316627e3dd26040518163ffffffff1660e01b8152600401602060405180830381865afa158015611e01573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e259190612bbc565b611e415760405162461bcd60e51b815260040161048790612d13565b60cb546001600160a01b031680611eb35760405162461bcd60e51b815260206004820152603060248201527f5265736572766548656c706572733a20506f6f6c20526567697374727920616460448201526f191c995cdcc81a5cc81b9bdd081cd95d60821b6064820152608401610487565b611ebd83836122db565b611f245760405162461bcd60e51b815260206004820152603260248201527f5265736572766548656c706572733a2054686520706f6f6c20646f65736e2774604482015271081cdd5c1c1bdc9d081d1a1948185cdcd95d60721b6064820152608401610487565b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa158015611f6b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f8f9190612982565b6001600160a01b038416600090815260c9602052604090205490915080821115612071576001600160a01b038416600090815260c960205260408120805483850392839291611fdf908490612c3e565b90915550506001600160a01b03808716600090815260ca602090815260408083209389168352929052908120805483929061201b908490612c3e565b92505081905550846001600160a01b0316866001600160a01b03167fc39e3e80c0219fde334a8cb5d8468b628482e23388b6e809c90cb00c63c8ce388360405161206791815260200190565b60405180910390a3505b5050505050565b60006120cd826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166123af9092919063ffffffff16565b90508051600014806120ee5750808060200190518101906120ee9190612bbc565b6115005760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610487565b600054610100900460ff166121745760405162461bcd60e51b815260040161048790612d5e565b61114d33611da2565b60008061218a84846123be565b9050612195816123ef565b949350505050565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663095ea7b360e01b1790529151909160009182918716906121fb908590612f29565b6000604051808303816000865af19150503d8060008114612238576040519150601f19603f3d011682016040523d82523d6000602084013e61223d565b606091505b509150915081158061226b575080511580159061226b5750808060200190518101906122699190612bbc565b155b156109c057604051633e3f8f7360e01b815260040160405180910390fd5b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316836001600160a01b0316036123265761231f82612407565b9050611135565b60cb5460405163266e0a7f60e01b81526001600160a01b0385811660048301528481166024830152600092169063266e0a7f90604401602060405180830381865afa158015612379573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061239d91906129f9565b6001600160a01b031614159392505050565b606061219584846000856125d8565b60408051602081019091526000815260405180602001604052806123e68560000151856126b3565b90529392505050565b805160009061113590670de0b6b3a764000090612f45565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b0772d0b6040518163ffffffff1660e01b8152600401600060405180830381865afa158015612468573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526124909190810190612f67565b905060005b81518110156125d1578181815181106124b0576124b06129e3565b60200260200101516001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03161461258457836001600160a01b031682828151811061250c5761250c6129e3565b60200260200101516001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa158015612551573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061257591906129f9565b6001600160a01b0316146125ba565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316846001600160a01b0316145b9250826125d1576125ca81612c56565b9050612495565b5050919050565b6060824710156126395760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610487565b600080866001600160a01b031685876040516126559190612f29565b60006040518083038185875af1925050503d8060008114612692576040519150601f19603f3d011682016040523d82523d6000602084013e612697565b606091505b50915091506126a8878383876126c6565b979650505050505050565b60006126bf8284612ff6565b9392505050565b6060831561273557825160000361272e576001600160a01b0385163b61272e5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610487565b5081612195565b612195838381511561274a5781518083602001fd5b8060405162461bcd60e51b81526004016104879190613015565b6001600160a01b038116811461064357600080fd5b6000806040838503121561278c57600080fd5b823561279781612764565b946020939093013593505050565b6000602082840312156127b757600080fd5b81356126bf81612764565b600080604083850312156127d557600080fd5b82356127e081612764565b915060208301356127f081612764565b809150509250929050565b600080600080600060a0868803121561281357600080fd5b853561281e81612764565b945060208601359350604086013561283581612764565b9250606086013561284581612764565b949793965091946080013592915050565b60008083601f84011261286857600080fd5b50813567ffffffffffffffff81111561288057600080fd5b6020830191508360208260051b850101111561289b57600080fd5b9250929050565b60008060008060008060006080888a0312156128bd57600080fd5b873567ffffffffffffffff808211156128d557600080fd5b6128e18b838c01612856565b909950975060208a01359150808211156128fa57600080fd5b6129068b838c01612856565b909750955060408a013591508082111561291f57600080fd5b5061292c8a828b01612856565b989b979a50959894979596606090950135949350505050565b60006020828403121561295757600080fd5b5035919050565b6020808252600a90820152691c994b595b9d195c995960b21b604082015260600190565b60006020828403121561299457600080fd5b5051919050565b60208082526028908201527f5269736b2046756e643a20496e76616c6964206d696e20616d6f756e7420746f6040820152670818dbdb9d995c9d60c21b606082015260800190565b634e487b7160e01b600052603260045260246000fd5b600060208284031215612a0b57600080fd5b81516126bf81612764565b634e487b7160e01b600052604160045260246000fd5b60405160a0810167ffffffffffffffff81118282101715612a4f57612a4f612a16565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715612a7e57612a7e612a16565b604052919050565b60005b83811015612aa1578181015183820152602001612a89565b83811115612ab0576000848401525b50505050565b8051612ac181612764565b919050565b60006020808385031215612ad957600080fd5b825167ffffffffffffffff80821115612af157600080fd5b9084019060a08287031215612b0557600080fd5b612b0d612a2c565b825182811115612b1c57600080fd5b8301601f81018813612b2d57600080fd5b805183811115612b3f57612b3f612a16565b612b51601f8201601f19168701612a55565b93508084528886828401011115612b6757600080fd5b612b7681878601888501612a86565b5050818152612b86848401612ab6565b84820152612b9660408401612ab6565b604082015260608301516060820152608083015160808201528094505050505092915050565b600060208284031215612bce57600080fd5b815180151581146126bf57600080fd5b6000808335601e19843603018112612bf557600080fd5b83018035915067ffffffffffffffff821115612c1057600080fd5b6020019150600581901b360382131561289b57600080fd5b634e487b7160e01b600052601160045260246000fd5b60008219821115612c5157612c51612c28565b500190565b600060018201612c6857612c68612c28565b5060010190565b8183526000602080850194508260005b85811015612cad578135612c9281612764565b6001600160a01b031687529582019590820190600101612c7f565b509495945050505050565b606081526000612ccc606083018789612c6f565b82810360208401528481526001600160fb1b03851115612ceb57600080fd5b8460051b80876020840137600091016020019081526040929092019290925295945050505050565b6020808252602b908201527f5265736572766548656c706572733a20436f6d7074726f6c6c6572206164647260408201526a195cdcc81a5b9d985b1a5960aa1b606082015260800190565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b60008151808452612dc1816020860160208601612a86565b601f01601f19169290920160200192915050565b6001600160a01b038316815260406020820181905260009061219590830184612da9565b6001600160a01b03848116825283166020820152606060408201819052600090611d9990830184612da9565b600082821015612e3757612e37612c28565b500390565b86815285602082015260a060408201526000612e5c60a083018688612c6f565b6001600160a01b039490941660608301525060800152949350505050565b600067ffffffffffffffff821115612e9457612e94612a16565b5060051b60200190565b60006020808385031215612eb157600080fd5b825167ffffffffffffffff811115612ec857600080fd5b8301601f81018513612ed957600080fd5b8051612eec612ee782612e7a565b612a55565b81815260059190911b82018301908381019087831115612f0b57600080fd5b928401925b828410156126a857835182529284019290840190612f10565b60008251612f3b818460208701612a86565b9190910192915050565b600082612f6257634e487b7160e01b600052601260045260246000fd5b500490565b60006020808385031215612f7a57600080fd5b825167ffffffffffffffff811115612f9157600080fd5b8301601f81018513612fa257600080fd5b8051612fb0612ee782612e7a565b81815260059190911b82018301908381019087831115612fcf57600080fd5b928401925b828410156126a8578351612fe781612764565b82529284019290840190612fd4565b600081600019048311821515161561301057613010612c28565b500290565b6020815260006126bf6020830184612da956fe73776170506f6f6c7341737365747328616464726573735b5d2c75696e743235365b5d2c616464726573735b5d5b5d2c75696e7432353629a2646970667358221220c967afe4ee07c007702bfe8b40ad090042c372456a0a152775ad412949fc6bc564736f6c634300080d0033", + "solcInputHash": "09e209110f36e8c9fe7ecc1925064673", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"corePoolComptroller_\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"vbnb_\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"nativeWrapped_\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"ApproveFailed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"loopsLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requiredLoops\",\"type\":\"uint256\"}],\"name\":\"MaxLoopsLimitExceeded\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"calledContract\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"methodSignature\",\"type\":\"string\"}],\"name\":\"Unauthorized\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"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\":\"oldConvertibleBaseAsset\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newConvertibleBaseAsset\",\"type\":\"address\"}],\"name\":\"ConvertibleBaseAssetUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"name\":\"Initialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldMaxLoopsLimit\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newmaxLoopsLimit\",\"type\":\"uint256\"}],\"name\":\"MaxLoopsLimitUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldMinAmountToConvert\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newMinAmountToConvert\",\"type\":\"uint256\"}],\"name\":\"MinAmountToConvertUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldAccessControlManager\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newAccessControlManager\",\"type\":\"address\"}],\"name\":\"NewAccessControlManager\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferStarted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"oldPancakeSwapRouter\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newPancakeSwapRouter\",\"type\":\"address\"}],\"name\":\"PancakeSwapRouterUpdated\",\"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\":\"oldShortfallContract\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"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\":\"totalAmount\",\"type\":\"uint256\"}],\"name\":\"SwappedPoolsAssets\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"SweepToken\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"TransferredReserveForAuction\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"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\",\"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\"}],\"name\":\"assetsReserves\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"convertibleBaseAsset\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"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\":\"comptroller\",\"type\":\"address\"}],\"name\":\"getPoolsBaseAssetReserves\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"pancakeSwapRouter_\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"minAmountToConvert_\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"convertibleBaseAsset_\",\"type\":\"address\"},{\"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\":\"minAmountToConvert\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pancakeSwapRouter\",\"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\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"accessControlManager_\",\"type\":\"address\"}],\"name\":\"setAccessControlManager\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_convertibleBaseAsset\",\"type\":\"address\"}],\"name\":\"setConvertibleBaseAsset\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"limit\",\"type\":\"uint256\"}],\"name\":\"setMaxLoopsLimit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"minAmountToConvert_\",\"type\":\"uint256\"}],\"name\":\"setMinAmountToConvert\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"pancakeSwapRouter_\",\"type\":\"address\"}],\"name\":\"setPancakeSwapRouter\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"poolRegistry_\",\"type\":\"address\"}],\"name\":\"setPoolRegistry\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"shortfallContractAddress_\",\"type\":\"address\"}],\"name\":\"setShortfallContractAddress\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"shortfall\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"markets\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"amountsOutMin\",\"type\":\"uint256[]\"},{\"internalType\":\"address[][]\",\"name\":\"paths\",\"type\":\"address[][]\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"}],\"name\":\"swapPoolsAssets\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"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\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transferReserveForAuction\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"}],\"name\":\"updateAssetsState\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Venus\",\"details\":\"This contract does not support BNB.\",\"kind\":\"dev\",\"methods\":{\"acceptOwnership()\":{\"details\":\"The new owner accepts the ownership transfer.\"},\"constructor\":{\"custom:oz-upgrades-unsafe-allow\":\"constructor\",\"details\":\"Note that the contract is upgradeable. Use initialize() or reinitializers to set the state variables.\"},\"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.\"}},\"getPoolsBaseAssetReserves(address)\":{\"params\":{\"comptroller\":\"Comptroller address(pool).\"},\"returns\":{\"_0\":\"Base Asset's reserve in risk fund.\"}},\"initialize(address,uint256,address,address,uint256)\":{\"custom:error\":\"ZeroAddressNotAllowed is thrown when PCS router address is zeroZeroAddressNotAllowed is thrown when convertible base asset address is zero\",\"params\":{\"accessControlManager_\":\"Address of the access control contract\",\"convertibleBaseAsset_\":\"Address of the base asset\",\"loopsLimit_\":\"Limit for the loops in the contract to avoid DOS\",\"minAmountToConvert_\":\"Minimum amount assets must be worth to convert into base asset\",\"pancakeSwapRouter_\":\"Address of the PancakeSwap router\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"pendingOwner()\":{\"details\":\"Returns the address of the pending owner.\"},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner.\"},\"setAccessControlManager(address)\":{\"custom:access\":\"Only Governance\",\"custom:event\":\"Emits NewAccessControlManager event\",\"details\":\"Admin function to set address of AccessControlManager\",\"params\":{\"accessControlManager_\":\"The new address of the AccessControlManager\"}},\"setConvertibleBaseAsset(address)\":{\"params\":{\"_convertibleBaseAsset\":\"Address for new convertible base asset.\"}},\"setMaxLoopsLimit(uint256)\":{\"params\":{\"limit\":\"Limit for the max loops can execute at a time\"}},\"setMinAmountToConvert(uint256)\":{\"params\":{\"minAmountToConvert_\":\"Min amount to convert.\"}},\"setPancakeSwapRouter(address)\":{\"custom:error\":\"ZeroAddressNotAllowed is thrown when PCS router address is zero\",\"params\":{\"pancakeSwapRouter_\":\"Address of the PancakeSwap router\"}},\"setPoolRegistry(address)\":{\"custom:error\":\"ZeroAddressNotAllowed is thrown when pool registry address is zero\",\"params\":{\"poolRegistry_\":\"Address of the pool registry\"}},\"setShortfallContractAddress(address)\":{\"custom:error\":\"ZeroAddressNotAllowed is thrown when shortfall contract address is zero\",\"params\":{\"shortfallContractAddress_\":\"Address of the auction contract\"}},\"swapPoolsAssets(address[],uint256[],address[][],uint256)\":{\"custom:error\":\"ZeroAddressNotAllowed is thrown if PoolRegistry contract address is not configured\",\"params\":{\"amountsOutMin\":\"Minimum amount to receive for swap\",\"deadline\":\"Deadline for the swap\",\"markets\":\"Array of vTokens whose assets to swap for base asset\",\"paths\":\"A path consisting of PCS token pairs for each swap\"},\"returns\":{\"_0\":\"Number of swapped tokens\"}},\"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.\"},\"transferReserveForAuction(address,uint256)\":{\"params\":{\"amount\":\"Amount to be transferred to auction contract.\",\"comptroller\":\"Comptroller of the pool.\"},\"returns\":{\"_0\":\"Number reserved tokens.\"}},\"updateAssetsState(address,address)\":{\"params\":{\"asset\":\"Asset address.\",\"comptroller\":\"Comptroller address(pool).\"}}},\"title\":\"RiskFund\",\"version\":1},\"userdoc\":{\"errors\":{\"ApproveFailed()\":[{\"notice\":\"Thrown if a contract is unable to approve a transfer\"}],\"MaxLoopsLimitExceeded(uint256,uint256)\":[{\"notice\":\"Thrown an error on maxLoopsLimit exceeds for any loop\"}],\"Unauthorized(address,address,string)\":[{\"notice\":\"Thrown when the action is prohibited by AccessControlManager\"}],\"ZeroAddressNotAllowed()\":[{\"notice\":\"Thrown if the supplied address is a zero address where it is not allowed\"}]},\"events\":{\"AssetsReservesUpdated(address,address,uint256)\":{\"notice\":\"Event emitted after the update of the assets reserves.\"},\"ConvertibleBaseAssetUpdated(address,address)\":{\"notice\":\"Emitted when convertible base asset is updated\"},\"MaxLoopsLimitUpdated(uint256,uint256)\":{\"notice\":\"Emitted when max loops limit is set\"},\"MinAmountToConvertUpdated(uint256,uint256)\":{\"notice\":\"Emitted when minimum amount to convert is updated\"},\"NewAccessControlManager(address,address)\":{\"notice\":\"Emitted when access control manager contract address is changed\"},\"PancakeSwapRouterUpdated(address,address)\":{\"notice\":\"Emitted when PancakeSwap router contract address is updated\"},\"PoolRegistryUpdated(address,address)\":{\"notice\":\"Emitted when pool registry address is updated\"},\"ShortfallContractUpdated(address,address)\":{\"notice\":\"Emitted when shortfall contract address is updated\"},\"SwappedPoolsAssets(address[],uint256[],uint256)\":{\"notice\":\"Emitted when pools assets are swapped\"},\"SweepToken(address,address,uint256)\":{\"notice\":\"event emitted on sweep token success\"},\"TransferredReserveForAuction(address,uint256)\":{\"notice\":\"Emitted when reserves are transferred for auction\"}},\"kind\":\"user\",\"methods\":{\"accessControlManager()\":{\"notice\":\"Returns the address of the access control manager contract\"},\"getPoolAssetReserve(address,address)\":{\"notice\":\"Get the Amount of the asset in the risk fund for the specific pool.\"},\"getPoolsBaseAssetReserves(address)\":{\"notice\":\"Get the Amount of the Base asset in the risk fund for the specific pool.\"},\"initialize(address,uint256,address,address,uint256)\":{\"notice\":\"Initializes the deployer to owner.\"},\"setAccessControlManager(address)\":{\"notice\":\"Sets the address of AccessControlManager\"},\"setConvertibleBaseAsset(address)\":{\"notice\":\"Sets a new convertible base asset\"},\"setMaxLoopsLimit(uint256)\":{\"notice\":\"Set the limit for the loops can iterate to avoid the DOS\"},\"setMinAmountToConvert(uint256)\":{\"notice\":\"Min amount to convert setter\"},\"setPancakeSwapRouter(address)\":{\"notice\":\"PancakeSwap router address setter\"},\"setPoolRegistry(address)\":{\"notice\":\"Pool registry setter\"},\"setShortfallContractAddress(address)\":{\"notice\":\"Shortfall contract address setter\"},\"swapPoolsAssets(address[],uint256[],address[][],uint256)\":{\"notice\":\"Swap array of pool assets into base asset's tokens of at least a minimum amount\"},\"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\"},\"transferReserveForAuction(address,uint256)\":{\"notice\":\"Transfer tokens for auction.\"},\"updateAssetsState(address,address)\":{\"notice\":\"Update the reserve of the asset for the specific pool after transferring to risk fund.\"}},\"notice\":\"Contract with basic features to track/hold different assets for different Comptrollers.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/RiskFund/RiskFund.sol\":\"RiskFund\"},\"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(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 \\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\":\"0xef1ca0adc3ce1ff540279d424953087771b4a07470caac99777fafd2ceea38a9\",\"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 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(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/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\",\"keccak256\":\"0x7e4d140bd2a5671389ad7a3975b65d05a4f750daf6a61c16139d123d9782b96e\",\"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/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/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\",\"keccak256\":\"0x7aefc03f77721f91f13d0bce91d53085b799443f7ef41b975ac6205b2c15d982\",\"license\":\"BSD-3-Clause\"},\"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\",\"keccak256\":\"0x918526b067c834935f5dd0788139e1a73c64cbf6f8b7d6fd43242eaa93aa7f37\",\"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(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 \\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 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 \\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(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\",\"keccak256\":\"0xcda9eb71f6ceb8a4c3bfbc1c42d72e2f0523d30f6d3252fbd90819e953640fe5\",\"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(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\":\"0x2947e95eb97a3a45f90ec36d4fd5a4cbb9409319f6ad000e950550055a3f2324\",\"license\":\"BSD-3-Clause\"},\"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\",\"keccak256\":\"0x9bbc31c80a4c537ddfd06cbd03a412ba64842a708381fbc4bf2e33ef56c92b4d\",\"license\":\"MIT\"},\"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": "0x60e06040523480156200001157600080fd5b50604051620032b8380380620032b883398101604081905262000034916200018c565b828282620000428362000083565b6200004d8262000083565b620000588162000083565b6001600160a01b0392831660805290821660a0521660c0526200007a620000ae565b505050620001d6565b6001600160a01b038116620000ab576040516342bcdf7f60e11b815260040160405180910390fd5b50565b600054610100900460ff16156200011b5760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b60005460ff908116146200016d576000805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b80516001600160a01b03811681146200018757600080fd5b919050565b600080600060608486031215620001a257600080fd5b620001ad846200016f565b9250620001bd602085016200016f565b9150620001cd604085016200016f565b90509250925092565b60805160a05160c05161309662000222600039600081816102bf015261258601526000818161029801526124c3015260008181610437015281816122df015261240c01526130966000f3fe608060405234801561001057600080fd5b50600436106101da5760003560e01c806377d4937f11610104578063afcff50f116100a2578063e30c397811610071578063e30c39781461040e578063f2fde38b1461041f578063fa7b81a014610432578063fe3da9841461045957600080fd5b8063afcff50f146103cd578063b4a0bdf3146103e0578063be26317e146103f1578063c8ecc0d3146103fa57600080fd5b806380d45a2d116100de57806380d45a2d146103835780638da5cb5b14610396578063a69bd19e146103a7578063aac59a75146103ba57600080fd5b806377d4937f1461035557806379ba5097146103685780637b77cd6a1461037057600080fd5b80633421fc521161017c5780635f30e37b1161014b5780635f30e37b146103145780636fb0527514610327578063715018a61461033a578063746460a91461034257600080fd5b80633421fc5214610293578063362b6795146102ba578063439b5517146102e15780634dd9584a1461030157600080fd5b806324558995116101b85780632455899514610246578063258836fe1461025a5780632a1d05471461026d5780632e6881411461028057600080fd5b80630a9837c5146101df5780630e32cb861461020557806319b1faef1461021a575b600080fd5b6101f26101ed366004612779565b610463565b6040519081526020015b60405180910390f35b6102186102133660046127a5565b610632565b005b61012e5461022e906001600160a01b031681565b6040516001600160a01b0390911681526020016101fc565b61012f5461022e906001600160a01b031681565b6102186102683660046127c2565b610646565b61021861027b3660046127fb565b6107d7565b61021861028e3660046127a5565b6109c8565b61022e7f000000000000000000000000000000000000000000000000000000000000000081565b61022e7f000000000000000000000000000000000000000000000000000000000000000081565b6101f26102ef3660046127a5565b60c96020526000908152604090205481565b61021861030f3660046127a5565b610acd565b6101f26103223660046128a2565b610b31565b6101f26103353660046127c2565b611085565b61021861113b565b610218610350366004612945565b61114f565b6102186103633660046127a5565b6111f4565b610218611258565b61021861037e3660046127a5565b6112cf565b610218610391366004612945565b611332565b6033546001600160a01b031661022e565b6101f26103b53660046127a5565b611343565b6102186103c83660046127c2565b61142f565b60cb5461022e906001600160a01b031681565b6097546001600160a01b031661022e565b6101f260fb5481565b61012d5461022e906001600160a01b031681565b6065546001600160a01b031661022e565b61021861042d3660046127a5565b61143d565b61022e7f000000000000000000000000000000000000000000000000000000000000000081565b6101f26101305481565b6000600260cc54036104905760405162461bcd60e51b81526004016104879061295e565b60405180910390fd5b600260cc5561012e546001600160a01b03163381146105085760405162461bcd60e51b815260206004820152602e60248201527f5269736b2066756e643a204f6e6c792063616c6c61626c652062792053686f7260448201526d1d19985b1b0818dbdb9d1c9858dd60921b6064820152608401610487565b6001600160a01b03808516600090815260ca6020908152604080832061012d549094168352929052205483111561058f5760405162461bcd60e51b815260206004820152602560248201527f5269736b2046756e643a20496e73756666696369656e7420706f6f6c2072657360448201526432b93b329760d91b6064820152608401610487565b6001600160a01b03808516600081815260ca6020908152604080832061012d80548716855290835281842080548a9003905554909416825260c990528290208054869003905590517fc8d0a37ed16dfaa43514df00e18f478b60d5cc7b4bfc687103948b9020f737fd906106069086815260200190565b60405180910390a261012d54610626906001600160a01b031682856114ae565b5050600160cc55919050565b61063a611505565b6106438161155f565b50565b61064e611505565b600260cc54036106705760405162461bcd60e51b81526004016104879061295e565b600260cc5561067e8161161d565b6040516370a0823160e01b815230600482015260009081906001600160a01b038516906370a0823190602401602060405180830381865afa1580156106c7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106eb9190612982565b6001600160a01b038516600090815260c9602052604090205490915081116107615760405162461bcd60e51b815260206004820152602360248201527f5265736572766548656c706572733a205a65726f20737572706c757320746f6b604482015262656e7360e81b6064820152608401610487565b6001600160a01b03848116600081815260c960209081526040918290205491519185038083529550928616927f6d25be279134f4ecaa4770aff0c3d916d9e7c5ef37b65ed95dbdba411f5d54d5910160405180910390a36107cc6001600160a01b03851684846114ae565b5050600160cc555050565b600054610100900460ff16158080156107f75750600054600160ff909116105b806108115750303b158015610811575060005460ff166001145b6108745760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610487565b6000805460ff191660011790558015610897576000805461ff0019166101001790555b6108a08661161d565b6108a98461161d565b600085116108c95760405162461bcd60e51b81526004016104879061299b565b600082116109285760405162461bcd60e51b815260206004820152602660248201527f5269736b2046756e643a204c6f6f7073206c696d69742063616e206e6f74206260448201526565207a65726f60d01b6064820152608401610487565b610930611644565b61093983611673565b61012f80546001600160a01b038089166001600160a01b03199283161790925561013087905561012d80549287169290911691909117905561097a8261169a565b80156109c0576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050565b610a066040518060400160405280602081526020017f736574436f6e7665727469626c65426173654173736574286164647265737329815250611734565b6001600160a01b038116610a7a5760405162461bcd60e51b815260206004820152603560248201527f5269736b2046756e643a206e657720636f6e7665727469626c65206261736520604482015274185cdcd95d081859191c995cdcc81a5b9d985b1a59605a1b6064820152608401610487565b61012d80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f5fa61583da12070720613fefdd68cc6c0e464a71e009742526bd2b2e0ac62cd290600090a35050565b610ad5611505565b610ade8161161d565b61012f80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907fd37b9d138f53ea58d7e50292588239a46efa8f523966febf4066da96defc77fd90600090a35050565b6000600260cc5403610b555760405162461bcd60e51b81526004016104879061295e565b600260cc81905550610b7e60405180606001604052806038815260200161302960389139611734565b42821015610bce5760405162461bcd60e51b815260206004820152601a60248201527f5269736b2066756e643a20646561646c696e65207061737365640000000000006044820152606401610487565b60cb546001600160a01b0316610be38161161d565b878614610c585760405162461bcd60e51b815260206004820152603860248201527f5269736b2066756e643a206d61726b65747320616e6420616d6f756e74734f7560448201527f744d696e2061726520756e657175616c206c656e6774687300000000000000006064820152608401610487565b878414610cc05760405162461bcd60e51b815260206004820152603060248201527f5269736b2066756e643a206d61726b65747320616e642070617468732061726560448201526f20756e657175616c206c656e6774687360801b6064820152608401610487565b600088610ccc816117ce565b60005b818110156110325760008c8c83818110610ceb57610ceb6129e3565b9050602002016020810190610d0091906127a5565b6001600160a01b0316635fe3b5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d3d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d6191906129f9565b604051637aee632d60e01b81526001600160a01b038083166004830152919250600091871690637aee632d90602401600060405180830381865afa158015610dad573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610dd59190810190612ac6565b9050816001600160a01b031681604001516001600160a01b031614610e4c5760405162461bcd60e51b815260206004820152602760248201527f636f6d7074726f6c6c657220646f65736e277420657869737420706f6f6c20726044820152666567697374727960c81b6064820152608401610487565b816001600160a01b0316633d98a1e58f8f86818110610e6d57610e6d6129e3565b9050602002016020810190610e8291906127a5565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa158015610ec6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610eea9190612bbc565b610f2d5760405162461bcd60e51b81526020600482015260146024820152731b585c9ad95d081a5cc81b9bdd081b1a5cdd195960621b6044820152606401610487565b6000610f9c8f8f86818110610f4457610f446129e3565b9050602002016020810190610f5991906127a5565b848f8f88818110610f6c57610f6c6129e3565b905060200201358e8e89818110610f8557610f856129e3565b9050602002810190610f979190612bde565b6117ff565b6001600160a01b03808516600090815260ca6020908152604080832061012d54909416835292905290812080549293508392909190610fdc908490612c3e565b909155505061012d546001600160a01b0316600090815260c960205260408120805483929061100c908490612c3e565b9091555061101c90508187612c3e565b95505050508061102b90612c56565b9050610ccf565b507fb17530966b045b50d4975e7f05048ca00d7335780c24f1c465165a4b94b2d37d8b8b8b8b8660405161106a959493929190612cb8565b60405180910390a150600160cc559998505050505050505050565b60006110908261161d565b826001600160a01b0316627e3dd26040518163ffffffff1660e01b8152600401602060405180830381865afa1580156110cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110f19190612bbc565b61110d5760405162461bcd60e51b815260040161048790612d13565b506001600160a01b03808316600090815260ca60209081526040808320938516835292905220545b92915050565b611143611505565b61114d6000611da2565b565b61118d6040518060400160405280601e81526020017f7365744d696e416d6f756e74546f436f6e766572742875696e74323536290000815250611734565b600081116111ad5760405162461bcd60e51b81526004016104879061299b565b61013080549082905560408051828152602081018490527fada67d0d38fa20c8ae6a5c17cb9d60b0fe7f2d4e4f27ac9ee55e54ac88de9d8d91015b60405180910390a15050565b6111fc611505565b6112058161161d565b61012e80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907fb6e5fcf02f7fbb8acfbaa3bac4fd5abf9ff51e3f2e8884b5498927179b211b2890600090a35050565b60655433906001600160a01b031681146112c65760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b6064820152608401610487565b61064381611da2565b6112d7611505565b6112e08161161d565b60cb80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907fa87b964d321035d2165e484ff4b722dd6eae30606c0b98887d2ed1a34e594bfe90600090a35050565b61133a611505565b6106438161169a565b6000816001600160a01b0316627e3dd26040518163ffffffff1660e01b8152600401602060405180830381865afa158015611382573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113a69190612bbc565b6114015760405162461bcd60e51b815260206004820152602660248201527f5269736b2046756e643a20436f6d7074726f6c6c6572206164647265737320696044820152651b9d985b1a5960d21b6064820152608401610487565b506001600160a01b03908116600090815260ca6020908152604080832061012d549094168352929052205490565b6114398282611dbb565b5050565b611445611505565b606580546001600160a01b0383166001600160a01b031990911681179091556114766033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b179052611500908490612078565b505050565b6033546001600160a01b0316331461114d5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610487565b6001600160a01b0381166115c35760405162461bcd60e51b815260206004820152602560248201527f696e76616c696420616365737320636f6e74726f6c206d616e61676572206164604482015264647265737360d81b6064820152608401610487565b609780546001600160a01b038381166001600160a01b031983168117909355604080519190921680825260208201939093527f66fd58e82f7b31a2a5c30e0888f3093efe4e111b00cd2b0c31fe014601293aa091016111e8565b6001600160a01b038116610643576040516342bcdf7f60e11b815260040160405180910390fd5b600054610100900460ff1661166b5760405162461bcd60e51b815260040161048790612d5e565b61114d61214d565b600054610100900460ff1661063a5760405162461bcd60e51b815260040161048790612d5e565b60fb5481116116f65760405162461bcd60e51b815260206004820152602260248201527f436f6d7074726f6c6c65723a20496e76616c6964206d61784c6f6f70734c696d6044820152611a5d60f21b6064820152608401610487565b60fb80549082905560408051828152602081018490527fc2d09fef144f7c8a86f71ea459f8fc17f675768eb1ae369cbd77fb31d467aafa91016111e8565b6097546040516318c5e8ab60e01b81526000916001600160a01b0316906318c5e8ab906117679033908690600401612dd5565b602060405180830381865afa158015611784573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117a89190612bbc565b90508061143957333083604051634a3fa29360e01b815260040161048793929190612df9565b60fb548111156106435760fb5460405163792bfb1b60e11b8152600481019190915260248101829052604401610487565b6000836000036118775760405162461bcd60e51b815260206004820152603c60248201527f5269736b46756e643a20616d6f756e744f75744d696e206d757374206265206760448201527f726561746572207468616e203020746f20737761702076546f6b656e000000006064820152608401610487565b600080876001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa1580156118b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118dc91906129f9565b61012d546001600160a01b03898116600090815260ca60209081526040808320848716845290915281205493945091169190819003611922576000945050505050611d99565b6000896001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa158015611962573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061198691906129f9565b60405163b62cad6960e01b81526001600160a01b0385811660048301529192509082169063b62cad6990602401600060405180830381600087803b1580156119cd57600080fd5b505af11580156119e1573d6000803e3d6000fd5b50506040805160208101918290526341976e0960e01b9091526001600160a01b03868116602483015260009350909150819084166341976e0960448301602060405180830381865afa158015611a3b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a5f9190612982565b905290506000611a6f828c61217d565b905061013054811015611ad25760405162461bcd60e51b815260206004820152602560248201527f5269736b46756e643a206d696e416d6f756e74546f436f6e766572742076696f6044820152641b185d195960da1b6064820152608401610487565b6001600160a01b038616600090815260c9602052604081208054869290611afa908490612e25565b90915550506001600160a01b03808d16600090815260ca60209081526040808320938a1683529290529081208054869290611b36908490612e25565b90915550506001600160a01b0386811690861614611d8b57856001600160a01b03168a8a6000818110611b6b57611b6b6129e3565b9050602002016020810190611b8091906127a5565b6001600160a01b031614611bfc5760405162461bcd60e51b815260206004820152603860248201527f5269736b46756e643a20737761702070617468206d757374207374617274207760448201527f6974682074686520756e6465726c79696e6720617373657400000000000000006064820152608401610487565b6001600160a01b0385168a8a611c13600182612e25565b818110611c2257611c226129e3565b9050602002016020810190611c3791906127a5565b6001600160a01b031614611cab5760405162461bcd60e51b815260206004820152603560248201527f5269736b46756e643a2066696e616c6c792070617468206d75737420626520636044820152741bdb9d995c9d1a589b194818985cd948185cdcd95d605a1b6064820152608401610487565b61012f546001600160a01b0390811690611cc990881682600061219d565b611cdd6001600160a01b038816828761219d565b6000816001600160a01b03166338ed1739878f8f8f30426040518763ffffffff1660e01b8152600401611d1596959493929190612e3c565b6000604051808303816000875af1158015611d34573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611d5c9190810190612e9e565b905080611d6a60018d612e25565b81518110611d7a57611d7a6129e3565b602002602001015198505050611d8f565b8396505b5094955050505050505b95945050505050565b606580546001600160a01b031916905561064381612289565b611dc48161161d565b816001600160a01b0316627e3dd26040518163ffffffff1660e01b8152600401602060405180830381865afa158015611e01573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e259190612bbc565b611e415760405162461bcd60e51b815260040161048790612d13565b60cb546001600160a01b031680611eb35760405162461bcd60e51b815260206004820152603060248201527f5265736572766548656c706572733a20506f6f6c20526567697374727920616460448201526f191c995cdcc81a5cc81b9bdd081cd95d60821b6064820152608401610487565b611ebd83836122db565b611f245760405162461bcd60e51b815260206004820152603260248201527f5265736572766548656c706572733a2054686520706f6f6c20646f65736e2774604482015271081cdd5c1c1bdc9d081d1a1948185cdcd95d60721b6064820152608401610487565b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa158015611f6b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f8f9190612982565b6001600160a01b038416600090815260c9602052604090205490915080821115612071576001600160a01b038416600090815260c960205260408120805483850392839291611fdf908490612c3e565b90915550506001600160a01b03808716600090815260ca602090815260408083209389168352929052908120805483929061201b908490612c3e565b92505081905550846001600160a01b0316866001600160a01b03167fc39e3e80c0219fde334a8cb5d8468b628482e23388b6e809c90cb00c63c8ce388360405161206791815260200190565b60405180910390a3505b5050505050565b60006120cd826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166123af9092919063ffffffff16565b90508051600014806120ee5750808060200190518101906120ee9190612bbc565b6115005760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610487565b600054610100900460ff166121745760405162461bcd60e51b815260040161048790612d5e565b61114d33611da2565b60008061218a84846123be565b9050612195816123ef565b949350505050565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663095ea7b360e01b1790529151909160009182918716906121fb908590612f29565b6000604051808303816000865af19150503d8060008114612238576040519150601f19603f3d011682016040523d82523d6000602084013e61223d565b606091505b509150915081158061226b575080511580159061226b5750808060200190518101906122699190612bbc565b155b156109c057604051633e3f8f7360e01b815260040160405180910390fd5b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316836001600160a01b0316036123265761231f82612407565b9050611135565b60cb5460405163266e0a7f60e01b81526001600160a01b0385811660048301528481166024830152600092169063266e0a7f90604401602060405180830381865afa158015612379573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061239d91906129f9565b6001600160a01b031614159392505050565b606061219584846000856125d8565b60408051602081019091526000815260405180602001604052806123e68560000151856126b3565b90529392505050565b805160009061113590670de0b6b3a764000090612f45565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b0772d0b6040518163ffffffff1660e01b8152600401600060405180830381865afa158015612468573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526124909190810190612f67565b905060005b81518110156125d1578181815181106124b0576124b06129e3565b60200260200101516001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03161461258457836001600160a01b031682828151811061250c5761250c6129e3565b60200260200101516001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa158015612551573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061257591906129f9565b6001600160a01b0316146125ba565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316846001600160a01b0316145b9250826125d1576125ca81612c56565b9050612495565b5050919050565b6060824710156126395760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610487565b600080866001600160a01b031685876040516126559190612f29565b60006040518083038185875af1925050503d8060008114612692576040519150601f19603f3d011682016040523d82523d6000602084013e612697565b606091505b50915091506126a8878383876126c6565b979650505050505050565b60006126bf8284612ff6565b9392505050565b6060831561273557825160000361272e576001600160a01b0385163b61272e5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610487565b5081612195565b612195838381511561274a5781518083602001fd5b8060405162461bcd60e51b81526004016104879190613015565b6001600160a01b038116811461064357600080fd5b6000806040838503121561278c57600080fd5b823561279781612764565b946020939093013593505050565b6000602082840312156127b757600080fd5b81356126bf81612764565b600080604083850312156127d557600080fd5b82356127e081612764565b915060208301356127f081612764565b809150509250929050565b600080600080600060a0868803121561281357600080fd5b853561281e81612764565b945060208601359350604086013561283581612764565b9250606086013561284581612764565b949793965091946080013592915050565b60008083601f84011261286857600080fd5b50813567ffffffffffffffff81111561288057600080fd5b6020830191508360208260051b850101111561289b57600080fd5b9250929050565b60008060008060008060006080888a0312156128bd57600080fd5b873567ffffffffffffffff808211156128d557600080fd5b6128e18b838c01612856565b909950975060208a01359150808211156128fa57600080fd5b6129068b838c01612856565b909750955060408a013591508082111561291f57600080fd5b5061292c8a828b01612856565b989b979a50959894979596606090950135949350505050565b60006020828403121561295757600080fd5b5035919050565b6020808252600a90820152691c994b595b9d195c995960b21b604082015260600190565b60006020828403121561299457600080fd5b5051919050565b60208082526028908201527f5269736b2046756e643a20496e76616c6964206d696e20616d6f756e7420746f6040820152670818dbdb9d995c9d60c21b606082015260800190565b634e487b7160e01b600052603260045260246000fd5b600060208284031215612a0b57600080fd5b81516126bf81612764565b634e487b7160e01b600052604160045260246000fd5b60405160a0810167ffffffffffffffff81118282101715612a4f57612a4f612a16565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715612a7e57612a7e612a16565b604052919050565b60005b83811015612aa1578181015183820152602001612a89565b83811115612ab0576000848401525b50505050565b8051612ac181612764565b919050565b60006020808385031215612ad957600080fd5b825167ffffffffffffffff80821115612af157600080fd5b9084019060a08287031215612b0557600080fd5b612b0d612a2c565b825182811115612b1c57600080fd5b8301601f81018813612b2d57600080fd5b805183811115612b3f57612b3f612a16565b612b51601f8201601f19168701612a55565b93508084528886828401011115612b6757600080fd5b612b7681878601888501612a86565b5050818152612b86848401612ab6565b84820152612b9660408401612ab6565b604082015260608301516060820152608083015160808201528094505050505092915050565b600060208284031215612bce57600080fd5b815180151581146126bf57600080fd5b6000808335601e19843603018112612bf557600080fd5b83018035915067ffffffffffffffff821115612c1057600080fd5b6020019150600581901b360382131561289b57600080fd5b634e487b7160e01b600052601160045260246000fd5b60008219821115612c5157612c51612c28565b500190565b600060018201612c6857612c68612c28565b5060010190565b8183526000602080850194508260005b85811015612cad578135612c9281612764565b6001600160a01b031687529582019590820190600101612c7f565b509495945050505050565b606081526000612ccc606083018789612c6f565b82810360208401528481526001600160fb1b03851115612ceb57600080fd5b8460051b80876020840137600091016020019081526040929092019290925295945050505050565b6020808252602b908201527f5265736572766548656c706572733a20436f6d7074726f6c6c6572206164647260408201526a195cdcc81a5b9d985b1a5960aa1b606082015260800190565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b60008151808452612dc1816020860160208601612a86565b601f01601f19169290920160200192915050565b6001600160a01b038316815260406020820181905260009061219590830184612da9565b6001600160a01b03848116825283166020820152606060408201819052600090611d9990830184612da9565b600082821015612e3757612e37612c28565b500390565b86815285602082015260a060408201526000612e5c60a083018688612c6f565b6001600160a01b039490941660608301525060800152949350505050565b600067ffffffffffffffff821115612e9457612e94612a16565b5060051b60200190565b60006020808385031215612eb157600080fd5b825167ffffffffffffffff811115612ec857600080fd5b8301601f81018513612ed957600080fd5b8051612eec612ee782612e7a565b612a55565b81815260059190911b82018301908381019087831115612f0b57600080fd5b928401925b828410156126a857835182529284019290840190612f10565b60008251612f3b818460208701612a86565b9190910192915050565b600082612f6257634e487b7160e01b600052601260045260246000fd5b500490565b60006020808385031215612f7a57600080fd5b825167ffffffffffffffff811115612f9157600080fd5b8301601f81018513612fa257600080fd5b8051612fb0612ee782612e7a565b81815260059190911b82018301908381019087831115612fcf57600080fd5b928401925b828410156126a8578351612fe781612764565b82529284019290840190612fd4565b600081600019048311821515161561301057613010612c28565b500290565b6020815260006126bf6020830184612da956fe73776170506f6f6c7341737365747328616464726573735b5d2c75696e743235365b5d2c616464726573735b5d5b5d2c75696e7432353629a26469706673582212200663ba64facc893c046f05256383f974657252f4c49516250551dac4f0a40cd564736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101da5760003560e01c806377d4937f11610104578063afcff50f116100a2578063e30c397811610071578063e30c39781461040e578063f2fde38b1461041f578063fa7b81a014610432578063fe3da9841461045957600080fd5b8063afcff50f146103cd578063b4a0bdf3146103e0578063be26317e146103f1578063c8ecc0d3146103fa57600080fd5b806380d45a2d116100de57806380d45a2d146103835780638da5cb5b14610396578063a69bd19e146103a7578063aac59a75146103ba57600080fd5b806377d4937f1461035557806379ba5097146103685780637b77cd6a1461037057600080fd5b80633421fc521161017c5780635f30e37b1161014b5780635f30e37b146103145780636fb0527514610327578063715018a61461033a578063746460a91461034257600080fd5b80633421fc5214610293578063362b6795146102ba578063439b5517146102e15780634dd9584a1461030157600080fd5b806324558995116101b85780632455899514610246578063258836fe1461025a5780632a1d05471461026d5780632e6881411461028057600080fd5b80630a9837c5146101df5780630e32cb861461020557806319b1faef1461021a575b600080fd5b6101f26101ed366004612779565b610463565b6040519081526020015b60405180910390f35b6102186102133660046127a5565b610632565b005b61012e5461022e906001600160a01b031681565b6040516001600160a01b0390911681526020016101fc565b61012f5461022e906001600160a01b031681565b6102186102683660046127c2565b610646565b61021861027b3660046127fb565b6107d7565b61021861028e3660046127a5565b6109c8565b61022e7f000000000000000000000000000000000000000000000000000000000000000081565b61022e7f000000000000000000000000000000000000000000000000000000000000000081565b6101f26102ef3660046127a5565b60c96020526000908152604090205481565b61021861030f3660046127a5565b610acd565b6101f26103223660046128a2565b610b31565b6101f26103353660046127c2565b611085565b61021861113b565b610218610350366004612945565b61114f565b6102186103633660046127a5565b6111f4565b610218611258565b61021861037e3660046127a5565b6112cf565b610218610391366004612945565b611332565b6033546001600160a01b031661022e565b6101f26103b53660046127a5565b611343565b6102186103c83660046127c2565b61142f565b60cb5461022e906001600160a01b031681565b6097546001600160a01b031661022e565b6101f260fb5481565b61012d5461022e906001600160a01b031681565b6065546001600160a01b031661022e565b61021861042d3660046127a5565b61143d565b61022e7f000000000000000000000000000000000000000000000000000000000000000081565b6101f26101305481565b6000600260cc54036104905760405162461bcd60e51b81526004016104879061295e565b60405180910390fd5b600260cc5561012e546001600160a01b03163381146105085760405162461bcd60e51b815260206004820152602e60248201527f5269736b2066756e643a204f6e6c792063616c6c61626c652062792053686f7260448201526d1d19985b1b0818dbdb9d1c9858dd60921b6064820152608401610487565b6001600160a01b03808516600090815260ca6020908152604080832061012d549094168352929052205483111561058f5760405162461bcd60e51b815260206004820152602560248201527f5269736b2046756e643a20496e73756666696369656e7420706f6f6c2072657360448201526432b93b329760d91b6064820152608401610487565b6001600160a01b03808516600081815260ca6020908152604080832061012d80548716855290835281842080548a9003905554909416825260c990528290208054869003905590517fc8d0a37ed16dfaa43514df00e18f478b60d5cc7b4bfc687103948b9020f737fd906106069086815260200190565b60405180910390a261012d54610626906001600160a01b031682856114ae565b5050600160cc55919050565b61063a611505565b6106438161155f565b50565b61064e611505565b600260cc54036106705760405162461bcd60e51b81526004016104879061295e565b600260cc5561067e8161161d565b6040516370a0823160e01b815230600482015260009081906001600160a01b038516906370a0823190602401602060405180830381865afa1580156106c7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106eb9190612982565b6001600160a01b038516600090815260c9602052604090205490915081116107615760405162461bcd60e51b815260206004820152602360248201527f5265736572766548656c706572733a205a65726f20737572706c757320746f6b604482015262656e7360e81b6064820152608401610487565b6001600160a01b03848116600081815260c960209081526040918290205491519185038083529550928616927f6d25be279134f4ecaa4770aff0c3d916d9e7c5ef37b65ed95dbdba411f5d54d5910160405180910390a36107cc6001600160a01b03851684846114ae565b5050600160cc555050565b600054610100900460ff16158080156107f75750600054600160ff909116105b806108115750303b158015610811575060005460ff166001145b6108745760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610487565b6000805460ff191660011790558015610897576000805461ff0019166101001790555b6108a08661161d565b6108a98461161d565b600085116108c95760405162461bcd60e51b81526004016104879061299b565b600082116109285760405162461bcd60e51b815260206004820152602660248201527f5269736b2046756e643a204c6f6f7073206c696d69742063616e206e6f74206260448201526565207a65726f60d01b6064820152608401610487565b610930611644565b61093983611673565b61012f80546001600160a01b038089166001600160a01b03199283161790925561013087905561012d80549287169290911691909117905561097a8261169a565b80156109c0576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050565b610a066040518060400160405280602081526020017f736574436f6e7665727469626c65426173654173736574286164647265737329815250611734565b6001600160a01b038116610a7a5760405162461bcd60e51b815260206004820152603560248201527f5269736b2046756e643a206e657720636f6e7665727469626c65206261736520604482015274185cdcd95d081859191c995cdcc81a5b9d985b1a59605a1b6064820152608401610487565b61012d80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f5fa61583da12070720613fefdd68cc6c0e464a71e009742526bd2b2e0ac62cd290600090a35050565b610ad5611505565b610ade8161161d565b61012f80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907fd37b9d138f53ea58d7e50292588239a46efa8f523966febf4066da96defc77fd90600090a35050565b6000600260cc5403610b555760405162461bcd60e51b81526004016104879061295e565b600260cc81905550610b7e60405180606001604052806038815260200161302960389139611734565b42821015610bce5760405162461bcd60e51b815260206004820152601a60248201527f5269736b2066756e643a20646561646c696e65207061737365640000000000006044820152606401610487565b60cb546001600160a01b0316610be38161161d565b878614610c585760405162461bcd60e51b815260206004820152603860248201527f5269736b2066756e643a206d61726b65747320616e6420616d6f756e74734f7560448201527f744d696e2061726520756e657175616c206c656e6774687300000000000000006064820152608401610487565b878414610cc05760405162461bcd60e51b815260206004820152603060248201527f5269736b2066756e643a206d61726b65747320616e642070617468732061726560448201526f20756e657175616c206c656e6774687360801b6064820152608401610487565b600088610ccc816117ce565b60005b818110156110325760008c8c83818110610ceb57610ceb6129e3565b9050602002016020810190610d0091906127a5565b6001600160a01b0316635fe3b5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d3d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d6191906129f9565b604051637aee632d60e01b81526001600160a01b038083166004830152919250600091871690637aee632d90602401600060405180830381865afa158015610dad573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610dd59190810190612ac6565b9050816001600160a01b031681604001516001600160a01b031614610e4c5760405162461bcd60e51b815260206004820152602760248201527f636f6d7074726f6c6c657220646f65736e277420657869737420706f6f6c20726044820152666567697374727960c81b6064820152608401610487565b816001600160a01b0316633d98a1e58f8f86818110610e6d57610e6d6129e3565b9050602002016020810190610e8291906127a5565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa158015610ec6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610eea9190612bbc565b610f2d5760405162461bcd60e51b81526020600482015260146024820152731b585c9ad95d081a5cc81b9bdd081b1a5cdd195960621b6044820152606401610487565b6000610f9c8f8f86818110610f4457610f446129e3565b9050602002016020810190610f5991906127a5565b848f8f88818110610f6c57610f6c6129e3565b905060200201358e8e89818110610f8557610f856129e3565b9050602002810190610f979190612bde565b6117ff565b6001600160a01b03808516600090815260ca6020908152604080832061012d54909416835292905290812080549293508392909190610fdc908490612c3e565b909155505061012d546001600160a01b0316600090815260c960205260408120805483929061100c908490612c3e565b9091555061101c90508187612c3e565b95505050508061102b90612c56565b9050610ccf565b507fb17530966b045b50d4975e7f05048ca00d7335780c24f1c465165a4b94b2d37d8b8b8b8b8660405161106a959493929190612cb8565b60405180910390a150600160cc559998505050505050505050565b60006110908261161d565b826001600160a01b0316627e3dd26040518163ffffffff1660e01b8152600401602060405180830381865afa1580156110cd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110f19190612bbc565b61110d5760405162461bcd60e51b815260040161048790612d13565b506001600160a01b03808316600090815260ca60209081526040808320938516835292905220545b92915050565b611143611505565b61114d6000611da2565b565b61118d6040518060400160405280601e81526020017f7365744d696e416d6f756e74546f436f6e766572742875696e74323536290000815250611734565b600081116111ad5760405162461bcd60e51b81526004016104879061299b565b61013080549082905560408051828152602081018490527fada67d0d38fa20c8ae6a5c17cb9d60b0fe7f2d4e4f27ac9ee55e54ac88de9d8d91015b60405180910390a15050565b6111fc611505565b6112058161161d565b61012e80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907fb6e5fcf02f7fbb8acfbaa3bac4fd5abf9ff51e3f2e8884b5498927179b211b2890600090a35050565b60655433906001600160a01b031681146112c65760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b6064820152608401610487565b61064381611da2565b6112d7611505565b6112e08161161d565b60cb80546001600160a01b038381166001600160a01b0319831681179093556040519116919082907fa87b964d321035d2165e484ff4b722dd6eae30606c0b98887d2ed1a34e594bfe90600090a35050565b61133a611505565b6106438161169a565b6000816001600160a01b0316627e3dd26040518163ffffffff1660e01b8152600401602060405180830381865afa158015611382573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113a69190612bbc565b6114015760405162461bcd60e51b815260206004820152602660248201527f5269736b2046756e643a20436f6d7074726f6c6c6572206164647265737320696044820152651b9d985b1a5960d21b6064820152608401610487565b506001600160a01b03908116600090815260ca6020908152604080832061012d549094168352929052205490565b6114398282611dbb565b5050565b611445611505565b606580546001600160a01b0383166001600160a01b031990911681179091556114766033546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b179052611500908490612078565b505050565b6033546001600160a01b0316331461114d5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610487565b6001600160a01b0381166115c35760405162461bcd60e51b815260206004820152602560248201527f696e76616c696420616365737320636f6e74726f6c206d616e61676572206164604482015264647265737360d81b6064820152608401610487565b609780546001600160a01b038381166001600160a01b031983168117909355604080519190921680825260208201939093527f66fd58e82f7b31a2a5c30e0888f3093efe4e111b00cd2b0c31fe014601293aa091016111e8565b6001600160a01b038116610643576040516342bcdf7f60e11b815260040160405180910390fd5b600054610100900460ff1661166b5760405162461bcd60e51b815260040161048790612d5e565b61114d61214d565b600054610100900460ff1661063a5760405162461bcd60e51b815260040161048790612d5e565b60fb5481116116f65760405162461bcd60e51b815260206004820152602260248201527f436f6d7074726f6c6c65723a20496e76616c6964206d61784c6f6f70734c696d6044820152611a5d60f21b6064820152608401610487565b60fb80549082905560408051828152602081018490527fc2d09fef144f7c8a86f71ea459f8fc17f675768eb1ae369cbd77fb31d467aafa91016111e8565b6097546040516318c5e8ab60e01b81526000916001600160a01b0316906318c5e8ab906117679033908690600401612dd5565b602060405180830381865afa158015611784573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117a89190612bbc565b90508061143957333083604051634a3fa29360e01b815260040161048793929190612df9565b60fb548111156106435760fb5460405163792bfb1b60e11b8152600481019190915260248101829052604401610487565b6000836000036118775760405162461bcd60e51b815260206004820152603c60248201527f5269736b46756e643a20616d6f756e744f75744d696e206d757374206265206760448201527f726561746572207468616e203020746f20737761702076546f6b656e000000006064820152608401610487565b600080876001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa1580156118b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118dc91906129f9565b61012d546001600160a01b03898116600090815260ca60209081526040808320848716845290915281205493945091169190819003611922576000945050505050611d99565b6000896001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa158015611962573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061198691906129f9565b60405163b62cad6960e01b81526001600160a01b0385811660048301529192509082169063b62cad6990602401600060405180830381600087803b1580156119cd57600080fd5b505af11580156119e1573d6000803e3d6000fd5b50506040805160208101918290526341976e0960e01b9091526001600160a01b03868116602483015260009350909150819084166341976e0960448301602060405180830381865afa158015611a3b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a5f9190612982565b905290506000611a6f828c61217d565b905061013054811015611ad25760405162461bcd60e51b815260206004820152602560248201527f5269736b46756e643a206d696e416d6f756e74546f436f6e766572742076696f6044820152641b185d195960da1b6064820152608401610487565b6001600160a01b038616600090815260c9602052604081208054869290611afa908490612e25565b90915550506001600160a01b03808d16600090815260ca60209081526040808320938a1683529290529081208054869290611b36908490612e25565b90915550506001600160a01b0386811690861614611d8b57856001600160a01b03168a8a6000818110611b6b57611b6b6129e3565b9050602002016020810190611b8091906127a5565b6001600160a01b031614611bfc5760405162461bcd60e51b815260206004820152603860248201527f5269736b46756e643a20737761702070617468206d757374207374617274207760448201527f6974682074686520756e6465726c79696e6720617373657400000000000000006064820152608401610487565b6001600160a01b0385168a8a611c13600182612e25565b818110611c2257611c226129e3565b9050602002016020810190611c3791906127a5565b6001600160a01b031614611cab5760405162461bcd60e51b815260206004820152603560248201527f5269736b46756e643a2066696e616c6c792070617468206d75737420626520636044820152741bdb9d995c9d1a589b194818985cd948185cdcd95d605a1b6064820152608401610487565b61012f546001600160a01b0390811690611cc990881682600061219d565b611cdd6001600160a01b038816828761219d565b6000816001600160a01b03166338ed1739878f8f8f30426040518763ffffffff1660e01b8152600401611d1596959493929190612e3c565b6000604051808303816000875af1158015611d34573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611d5c9190810190612e9e565b905080611d6a60018d612e25565b81518110611d7a57611d7a6129e3565b602002602001015198505050611d8f565b8396505b5094955050505050505b95945050505050565b606580546001600160a01b031916905561064381612289565b611dc48161161d565b816001600160a01b0316627e3dd26040518163ffffffff1660e01b8152600401602060405180830381865afa158015611e01573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e259190612bbc565b611e415760405162461bcd60e51b815260040161048790612d13565b60cb546001600160a01b031680611eb35760405162461bcd60e51b815260206004820152603060248201527f5265736572766548656c706572733a20506f6f6c20526567697374727920616460448201526f191c995cdcc81a5cc81b9bdd081cd95d60821b6064820152608401610487565b611ebd83836122db565b611f245760405162461bcd60e51b815260206004820152603260248201527f5265736572766548656c706572733a2054686520706f6f6c20646f65736e2774604482015271081cdd5c1c1bdc9d081d1a1948185cdcd95d60721b6064820152608401610487565b6040516370a0823160e01b81523060048201526000906001600160a01b038416906370a0823190602401602060405180830381865afa158015611f6b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f8f9190612982565b6001600160a01b038416600090815260c9602052604090205490915080821115612071576001600160a01b038416600090815260c960205260408120805483850392839291611fdf908490612c3e565b90915550506001600160a01b03808716600090815260ca602090815260408083209389168352929052908120805483929061201b908490612c3e565b92505081905550846001600160a01b0316866001600160a01b03167fc39e3e80c0219fde334a8cb5d8468b628482e23388b6e809c90cb00c63c8ce388360405161206791815260200190565b60405180910390a3505b5050505050565b60006120cd826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166123af9092919063ffffffff16565b90508051600014806120ee5750808060200190518101906120ee9190612bbc565b6115005760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610487565b600054610100900460ff166121745760405162461bcd60e51b815260040161048790612d5e565b61114d33611da2565b60008061218a84846123be565b9050612195816123ef565b949350505050565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663095ea7b360e01b1790529151909160009182918716906121fb908590612f29565b6000604051808303816000865af19150503d8060008114612238576040519150601f19603f3d011682016040523d82523d6000602084013e61223d565b606091505b509150915081158061226b575080511580159061226b5750808060200190518101906122699190612bbc565b155b156109c057604051633e3f8f7360e01b815260040160405180910390fd5b603380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316836001600160a01b0316036123265761231f82612407565b9050611135565b60cb5460405163266e0a7f60e01b81526001600160a01b0385811660048301528481166024830152600092169063266e0a7f90604401602060405180830381865afa158015612379573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061239d91906129f9565b6001600160a01b031614159392505050565b606061219584846000856125d8565b60408051602081019091526000815260405180602001604052806123e68560000151856126b3565b90529392505050565b805160009061113590670de0b6b3a764000090612f45565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663b0772d0b6040518163ffffffff1660e01b8152600401600060405180830381865afa158015612468573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526124909190810190612f67565b905060005b81518110156125d1578181815181106124b0576124b06129e3565b60200260200101516001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03161461258457836001600160a01b031682828151811061250c5761250c6129e3565b60200260200101516001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa158015612551573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061257591906129f9565b6001600160a01b0316146125ba565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316846001600160a01b0316145b9250826125d1576125ca81612c56565b9050612495565b5050919050565b6060824710156126395760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610487565b600080866001600160a01b031685876040516126559190612f29565b60006040518083038185875af1925050503d8060008114612692576040519150601f19603f3d011682016040523d82523d6000602084013e612697565b606091505b50915091506126a8878383876126c6565b979650505050505050565b60006126bf8284612ff6565b9392505050565b6060831561273557825160000361272e576001600160a01b0385163b61272e5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610487565b5081612195565b612195838381511561274a5781518083602001fd5b8060405162461bcd60e51b81526004016104879190613015565b6001600160a01b038116811461064357600080fd5b6000806040838503121561278c57600080fd5b823561279781612764565b946020939093013593505050565b6000602082840312156127b757600080fd5b81356126bf81612764565b600080604083850312156127d557600080fd5b82356127e081612764565b915060208301356127f081612764565b809150509250929050565b600080600080600060a0868803121561281357600080fd5b853561281e81612764565b945060208601359350604086013561283581612764565b9250606086013561284581612764565b949793965091946080013592915050565b60008083601f84011261286857600080fd5b50813567ffffffffffffffff81111561288057600080fd5b6020830191508360208260051b850101111561289b57600080fd5b9250929050565b60008060008060008060006080888a0312156128bd57600080fd5b873567ffffffffffffffff808211156128d557600080fd5b6128e18b838c01612856565b909950975060208a01359150808211156128fa57600080fd5b6129068b838c01612856565b909750955060408a013591508082111561291f57600080fd5b5061292c8a828b01612856565b989b979a50959894979596606090950135949350505050565b60006020828403121561295757600080fd5b5035919050565b6020808252600a90820152691c994b595b9d195c995960b21b604082015260600190565b60006020828403121561299457600080fd5b5051919050565b60208082526028908201527f5269736b2046756e643a20496e76616c6964206d696e20616d6f756e7420746f6040820152670818dbdb9d995c9d60c21b606082015260800190565b634e487b7160e01b600052603260045260246000fd5b600060208284031215612a0b57600080fd5b81516126bf81612764565b634e487b7160e01b600052604160045260246000fd5b60405160a0810167ffffffffffffffff81118282101715612a4f57612a4f612a16565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715612a7e57612a7e612a16565b604052919050565b60005b83811015612aa1578181015183820152602001612a89565b83811115612ab0576000848401525b50505050565b8051612ac181612764565b919050565b60006020808385031215612ad957600080fd5b825167ffffffffffffffff80821115612af157600080fd5b9084019060a08287031215612b0557600080fd5b612b0d612a2c565b825182811115612b1c57600080fd5b8301601f81018813612b2d57600080fd5b805183811115612b3f57612b3f612a16565b612b51601f8201601f19168701612a55565b93508084528886828401011115612b6757600080fd5b612b7681878601888501612a86565b5050818152612b86848401612ab6565b84820152612b9660408401612ab6565b604082015260608301516060820152608083015160808201528094505050505092915050565b600060208284031215612bce57600080fd5b815180151581146126bf57600080fd5b6000808335601e19843603018112612bf557600080fd5b83018035915067ffffffffffffffff821115612c1057600080fd5b6020019150600581901b360382131561289b57600080fd5b634e487b7160e01b600052601160045260246000fd5b60008219821115612c5157612c51612c28565b500190565b600060018201612c6857612c68612c28565b5060010190565b8183526000602080850194508260005b85811015612cad578135612c9281612764565b6001600160a01b031687529582019590820190600101612c7f565b509495945050505050565b606081526000612ccc606083018789612c6f565b82810360208401528481526001600160fb1b03851115612ceb57600080fd5b8460051b80876020840137600091016020019081526040929092019290925295945050505050565b6020808252602b908201527f5265736572766548656c706572733a20436f6d7074726f6c6c6572206164647260408201526a195cdcc81a5b9d985b1a5960aa1b606082015260800190565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b60008151808452612dc1816020860160208601612a86565b601f01601f19169290920160200192915050565b6001600160a01b038316815260406020820181905260009061219590830184612da9565b6001600160a01b03848116825283166020820152606060408201819052600090611d9990830184612da9565b600082821015612e3757612e37612c28565b500390565b86815285602082015260a060408201526000612e5c60a083018688612c6f565b6001600160a01b039490941660608301525060800152949350505050565b600067ffffffffffffffff821115612e9457612e94612a16565b5060051b60200190565b60006020808385031215612eb157600080fd5b825167ffffffffffffffff811115612ec857600080fd5b8301601f81018513612ed957600080fd5b8051612eec612ee782612e7a565b612a55565b81815260059190911b82018301908381019087831115612f0b57600080fd5b928401925b828410156126a857835182529284019290840190612f10565b60008251612f3b818460208701612a86565b9190910192915050565b600082612f6257634e487b7160e01b600052601260045260246000fd5b500490565b60006020808385031215612f7a57600080fd5b825167ffffffffffffffff811115612f9157600080fd5b8301601f81018513612fa257600080fd5b8051612fb0612ee782612e7a565b81815260059190911b82018301908381019087831115612fcf57600080fd5b928401925b828410156126a8578351612fe781612764565b82529284019290840190612fd4565b600081600019048311821515161561301057613010612c28565b500290565b6020815260006126bf6020830184612da956fe73776170506f6f6c7341737365747328616464726573735b5d2c75696e743235365b5d2c616464726573735b5d5b5d2c75696e7432353629a26469706673582212200663ba64facc893c046f05256383f974657252f4c49516250551dac4f0a40cd564736f6c634300080d0033", "devdoc": { "author": "Venus", "details": "This contract does not support BNB.", @@ -1164,7 +1164,7 @@ "type": "t_array(t_uint256)49_storage" }, { - "astId": 8855, + "astId": 8853, "contract": "contracts/RiskFund/RiskFund.sol:RiskFund", "label": "assetsReserves", "offset": 0, @@ -1172,7 +1172,7 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 8861, + "astId": 8859, "contract": "contracts/RiskFund/RiskFund.sol:RiskFund", "label": "_poolsAssetsReserves", "offset": 0, @@ -1180,7 +1180,7 @@ "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))" }, { - "astId": 8863, + "astId": 8861, "contract": "contracts/RiskFund/RiskFund.sol:RiskFund", "label": "poolRegistry", "offset": 0, @@ -1188,7 +1188,7 @@ "type": "t_address" }, { - "astId": 8866, + "astId": 8864, "contract": "contracts/RiskFund/RiskFund.sol:RiskFund", "label": "status", "offset": 0, @@ -1196,7 +1196,7 @@ "type": "t_uint256" }, { - "astId": 8871, + "astId": 8869, "contract": "contracts/RiskFund/RiskFund.sol:RiskFund", "label": "__gap", "offset": 0, @@ -1220,7 +1220,7 @@ "type": "t_array(t_uint256)49_storage" }, { - "astId": 9284, + "astId": 9282, "contract": "contracts/RiskFund/RiskFund.sol:RiskFund", "label": "convertibleBaseAsset", "offset": 0, @@ -1228,7 +1228,7 @@ "type": "t_address" }, { - "astId": 9286, + "astId": 9284, "contract": "contracts/RiskFund/RiskFund.sol:RiskFund", "label": "shortfall", "offset": 0, @@ -1236,7 +1236,7 @@ "type": "t_address" }, { - "astId": 9288, + "astId": 9286, "contract": "contracts/RiskFund/RiskFund.sol:RiskFund", "label": "pancakeSwapRouter", "offset": 0, @@ -1244,7 +1244,7 @@ "type": "t_address" }, { - "astId": 9290, + "astId": 9288, "contract": "contracts/RiskFund/RiskFund.sol:RiskFund", "label": "minAmountToConvert", "offset": 0, diff --git a/deployments/bsctestnet/solcInputs/09e209110f36e8c9fe7ecc1925064673.json b/deployments/bsctestnet/solcInputs/09e209110f36e8c9fe7ecc1925064673.json new file mode 100644 index 000000000..9657e68fd --- /dev/null +++ b/deployments/bsctestnet/solcInputs/09e209110f36e8c9fe7ecc1925064673.json @@ -0,0 +1,132 @@ +{ + "language": "Solidity", + "sources": { + "@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable2Step.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./OwnableUpgradeable.sol\";\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module which provides access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership} and {acceptOwnership}.\n *\n * This module is used through inheritance. It will make available all functions\n * from parent (Ownable).\n */\nabstract contract Ownable2StepUpgradeable is Initializable, OwnableUpgradeable {\n function __Ownable2Step_init() internal onlyInitializing {\n __Ownable_init_unchained();\n }\n\n function __Ownable2Step_init_unchained() internal onlyInitializing {\n }\n address private _pendingOwner;\n\n event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Returns the address of the pending owner.\n */\n function pendingOwner() public view virtual returns (address) {\n return _pendingOwner;\n }\n\n /**\n * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual override onlyOwner {\n _pendingOwner = newOwner;\n emit OwnershipTransferStarted(owner(), newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual override {\n delete _pendingOwner;\n super._transferOwnership(newOwner);\n }\n\n /**\n * @dev The new owner accepts the ownership transfer.\n */\n function acceptOwnership() public virtual {\n address sender = _msgSender();\n require(pendingOwner() == sender, \"Ownable2Step: caller is not the new owner\");\n _transferOwnership(sender);\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/ContextUpgradeable.sol\";\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n function __Ownable_init() internal onlyInitializing {\n __Ownable_init_unchained();\n }\n\n function __Ownable_init_unchained() internal onlyInitializing {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n _checkOwner();\n _;\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if the sender is not the owner.\n */\n function _checkOwner() internal view virtual {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby disabling any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)\n\npragma solidity ^0.8.2;\n\nimport \"../../utils/AddressUpgradeable.sol\";\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```solidity\n * contract MyToken is ERC20Upgradeable {\n * function initialize() initializer public {\n * __ERC20_init(\"MyToken\", \"MTK\");\n * }\n * }\n *\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n * function initializeV2() reinitializer(2) public {\n * __ERC20Permit_init(\"MyToken\");\n * }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n * _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n /**\n * @dev Indicates that the contract has been initialized.\n * @custom:oz-retyped-from bool\n */\n uint8 private _initialized;\n\n /**\n * @dev Indicates that the contract is in the process of being initialized.\n */\n bool private _initializing;\n\n /**\n * @dev Triggered when the contract has been initialized or reinitialized.\n */\n event Initialized(uint8 version);\n\n /**\n * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n * `onlyInitializing` functions can be used to initialize parent contracts.\n *\n * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a\n * constructor.\n *\n * Emits an {Initialized} event.\n */\n modifier initializer() {\n bool isTopLevelCall = !_initializing;\n require(\n (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),\n \"Initializable: contract is already initialized\"\n );\n _initialized = 1;\n if (isTopLevelCall) {\n _initializing = true;\n }\n _;\n if (isTopLevelCall) {\n _initializing = false;\n emit Initialized(1);\n }\n }\n\n /**\n * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n * used to initialize parent contracts.\n *\n * A reinitializer may be used after the original initialization step. This is essential to configure modules that\n * are added through upgrades and that require initialization.\n *\n * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\n * cannot be nested. If one is invoked in the context of another, execution will revert.\n *\n * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n * a contract, executing them in the right order is up to the developer or operator.\n *\n * WARNING: setting the version to 255 will prevent any future reinitialization.\n *\n * Emits an {Initialized} event.\n */\n modifier reinitializer(uint8 version) {\n require(!_initializing && _initialized < version, \"Initializable: contract is already initialized\");\n _initialized = version;\n _initializing = true;\n _;\n _initializing = false;\n emit Initialized(version);\n }\n\n /**\n * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n * {initializer} and {reinitializer} modifiers, directly or indirectly.\n */\n modifier onlyInitializing() {\n require(_initializing, \"Initializable: contract is not initializing\");\n _;\n }\n\n /**\n * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n * through proxies.\n *\n * Emits an {Initialized} event the first time it is successfully executed.\n */\n function _disableInitializers() internal virtual {\n require(!_initializing, \"Initializable: contract is initializing\");\n if (_initialized != type(uint8).max) {\n _initialized = type(uint8).max;\n emit Initialized(type(uint8).max);\n }\n }\n\n /**\n * @dev Returns the highest version that has been initialized. See {reinitializer}.\n */\n function _getInitializedVersion() internal view returns (uint8) {\n return _initialized;\n }\n\n /**\n * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\n */\n function _isInitializing() internal view returns (bool) {\n return _initializing;\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/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/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" + }, + "@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/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/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" + }, + "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/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/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 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 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\";\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/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" + } + }, + "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 + } + } +} From 80f7a58f68ab0e949dcb8c5248123bf2ec4d9ba9 Mon Sep 17 00:00:00 2001 From: Jesus Lanchas Date: Tue, 10 Oct 2023 17:23:40 +0200 Subject: [PATCH 23/33] feat: add info about the DefaultProxyAdmin used in testnet --- deployments/bsctestnet.json | 165 +++++++++++ deployments/bsctestnet/DefaultProxyAdmin.json | 257 ++++++++++++++++++ 2 files changed, 422 insertions(+) create mode 100644 deployments/bsctestnet/DefaultProxyAdmin.json diff --git a/deployments/bsctestnet.json b/deployments/bsctestnet.json index 83eb8845a..a1bb7c019 100644 --- a/deployments/bsctestnet.json +++ b/deployments/bsctestnet.json @@ -2140,6 +2140,171 @@ } ] }, + "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" + } + ] + }, "JumpRateModelV2_base200bps_slope1000bps_jump25000bps_kink5000bps": { "address": "0x6Ba592934fD60d7A180d65cdb1C9BF561FeAD3D4", "abi": [ diff --git a/deployments/bsctestnet/DefaultProxyAdmin.json b/deployments/bsctestnet/DefaultProxyAdmin.json new file mode 100644 index 000000000..da7e5d4b0 --- /dev/null +++ b/deployments/bsctestnet/DefaultProxyAdmin.json @@ -0,0 +1,257 @@ +{ + "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" + } + ], + "transactionHash": "0xf94cc086d3edcb7da8edef0fae2cd35afc4257e5a9655b948ae1f1da7e94f185", + "receipt": { + "to": null, + "from": "0xFEA1c651A47FE29dB9b1bf3cC1f224d8D9CFF68C", + "contractAddress": "0x7877ffd62649b6a1557b55d4c20fcbab17344c91", + "transactionIndex": 5, + "gasUsed": "642671", + "logsBloom": "0x00000000000000000000000000000000000000000000040000800000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000020000000000000000000800000000000000000000000000000000400000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000020000000000000000000000000000000040000000000000000000000004000000000", + "blockHash": "0xf4b9323108cb30aeb942d5215bb0e76bdae569250f5c6fd60dd4f11a68ed6b86", + "transactionHash": "0xf94cc086d3edcb7da8edef0fae2cd35afc4257e5a9655b948ae1f1da7e94f185", + "logs": [ + { + "transactionIndex": 5, + "blockNumber": 30883288, + "transactionHash": "0xf94cc086d3edcb7da8edef0fae2cd35afc4257e5a9655b948ae1f1da7e94f185", + "address": "0x7877ffd62649b6a1557b55d4c20fcbab17344c91", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000ce10739590001705f7ff231611ba4a48b2820327" + ], + "data": "0x", + "logIndex": 17, + "blockHash": "0xf4b9323108cb30aeb942d5215bb0e76bdae569250f5c6fd60dd4f11a68ed6b86" + } + ], + "blockNumber": 30883288, + "cumulativeGasUsed": "4838707", + "status": 1, + "byzantium": true + }, + "args": ["0xce10739590001705F7FF231611ba4A48B2820327"], + "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" + } + } + } +} From 133ccd1dca4c020e6a8c773408ca278aac7e3536 Mon Sep 17 00:00:00 2001 From: Narayan Prusty Date: Tue, 10 Oct 2023 16:45:25 +0100 Subject: [PATCH 24/33] fix: removed only --- tests/integration/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/integration/index.ts b/tests/integration/index.ts index f68c80245..ef2573e35 100644 --- a/tests/integration/index.ts +++ b/tests/integration/index.ts @@ -157,7 +157,7 @@ describe("Positive Cases", function () { } = fixture); }); describe("Setup", () => { - it.only("PoolRegistry should be initialized properly", async function () { + it("PoolRegistry should be initialized properly", async function () { await expect(PoolRegistry.initialize(ethers.constants.AddressZero)).to.be.revertedWith( "Initializable: contract is already initialized", ); From a4b0d198948ec1cc369134eb69b2b31ffa91659d Mon Sep 17 00:00:00 2001 From: Venus Tools Date: Tue, 10 Oct 2023 15:50:00 +0000 Subject: [PATCH 25/33] chore(release): 2.1.0-dev.5 [skip ci] ## [2.1.0-dev.5](https://github.com/VenusProtocol/isolated-pools/compare/v2.1.0-dev.4...v2.1.0-dev.5) (2023-10-10) ### Features * add info about the DefaultProxyAdmin used in testnet ([80f7a58](https://github.com/VenusProtocol/isolated-pools/commit/80f7a58f68ab0e949dcb8c5248123bf2ec4d9ba9)) --- CHANGELOG.md | 7 +++++++ package.json | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5d747825a..f9d8566d6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [2.1.0-dev.5](https://github.com/VenusProtocol/isolated-pools/compare/v2.1.0-dev.4...v2.1.0-dev.5) (2023-10-10) + + +### Features + +* add info about the DefaultProxyAdmin used in testnet ([80f7a58](https://github.com/VenusProtocol/isolated-pools/commit/80f7a58f68ab0e949dcb8c5248123bf2ec4d9ba9)) + ## [2.1.0-dev.4](https://github.com/VenusProtocol/isolated-pools/compare/v2.1.0-dev.3...v2.1.0-dev.4) (2023-10-10) diff --git a/package.json b/package.json index 2b0fd086b..1c9e2d201 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@venusprotocol/isolated-pools", - "version": "2.1.0-dev.4", + "version": "2.1.0-dev.5", "description": "", "files": [ "artifacts", From a665c14f0820670ddbe75b76e4b0fcb27127ee6c Mon Sep 17 00:00:00 2001 From: Venus Tools Date: Tue, 10 Oct 2023 20:38:22 +0000 Subject: [PATCH 26/33] chore(release): 2.1.0-dev.6 [skip ci] ## [2.1.0-dev.6](https://github.com/VenusProtocol/isolated-pools/compare/v2.1.0-dev.5...v2.1.0-dev.6) (2023-10-10) --- CHANGELOG.md | 2 ++ package.json | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f9d8566d6..930290691 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,5 @@ +## [2.1.0-dev.6](https://github.com/VenusProtocol/isolated-pools/compare/v2.1.0-dev.5...v2.1.0-dev.6) (2023-10-10) + ## [2.1.0-dev.5](https://github.com/VenusProtocol/isolated-pools/compare/v2.1.0-dev.4...v2.1.0-dev.5) (2023-10-10) diff --git a/package.json b/package.json index 1c9e2d201..313d7f54e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@venusprotocol/isolated-pools", - "version": "2.1.0-dev.5", + "version": "2.1.0-dev.6", "description": "", "files": [ "artifacts", From f4e8d2b5517ad6b104cffcdbe03c9eb2fd94ddbc Mon Sep 17 00:00:00 2001 From: Debugger022 Date: Thu, 12 Oct 2023 14:07:56 +0530 Subject: [PATCH 27/33] fix: CVP-04 --- contracts/Comptroller.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/Comptroller.sol b/contracts/Comptroller.sol index 33a4fe45c..1ae39027f 100644 --- a/contracts/Comptroller.sol +++ b/contracts/Comptroller.sol @@ -1021,7 +1021,7 @@ contract Comptroller is revert MarketNotListed(vTokenBorrowed); } - isForcedLiquidationEnabled[address(vTokenBorrowed)] = enable; + isForcedLiquidationEnabled[vTokenBorrowed] = enable; emit IsForcedLiquidationEnabledUpdated(vTokenBorrowed, enable); } From ebc9a9b043064e6fe4af2ac48fdc24e24eddba58 Mon Sep 17 00:00:00 2001 From: Debugger022 Date: Thu, 12 Oct 2023 14:09:47 +0530 Subject: [PATCH 28/33] fix: CVP-03 --- contracts/Comptroller.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/Comptroller.sol b/contracts/Comptroller.sol index 1ae39027f..525d29650 100644 --- a/contracts/Comptroller.sol +++ b/contracts/Comptroller.sol @@ -477,7 +477,7 @@ contract Comptroller is uint256 borrowBalance = VToken(vTokenBorrowed).borrowBalanceStored(borrower); - /* Allow accounts to be liquidated if the market is deprecated or it is a forced liquidation */ + /* Allow accounts to be liquidated if it is a forced liquidation */ if (skipLiquidityCheck || isForcedLiquidationEnabled[vTokenBorrowed]) { if (repayAmount > borrowBalance) { revert TooMuchRepay(); From 82166e505b87c90d602a1eaff78253fe55376aaa Mon Sep 17 00:00:00 2001 From: Narayan Prusty Date: Thu, 12 Oct 2023 12:36:37 +0100 Subject: [PATCH 29/33] fix: fixed build --- package-lock.json | 16619 ++++++++++++++++++++++++++++++++++++++++++++ package.json | 1 + yarn.lock | 11 + 3 files changed, 16631 insertions(+) create mode 100644 package-lock.json diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 000000000..a2ac81a0b --- /dev/null +++ b/package-lock.json @@ -0,0 +1,16619 @@ +{ + "name": "@venusprotocol/isolated-pools", + "version": "2.1.0-dev.6", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "@venusprotocol/isolated-pools", + "version": "2.1.0-dev.6", + "license": "ISC", + "dependencies": { + "@openzeppelin/contracts": "^4.8.3", + "@openzeppelin/contracts-upgradeable": "^4.8.3", + "@openzeppelin/hardhat-upgrades": "^1.21.0", + "@solidity-parser/parser": "^0.13.2", + "@venusprotocol/protocol-reserve": "^1.0.0-dev.6", + "ethers": "^5.7.0", + "hardhat-deploy": "^0.11.14", + "module-alias": "^2.2.2" + }, + "devDependencies": { + "@commitlint/cli": "^17.0.3", + "@commitlint/config-conventional": "^17.0.3", + "@defi-wonderland/smock": "^2.2.0", + "@nomicfoundation/hardhat-chai-matchers": "^1.0.3", + "@nomicfoundation/hardhat-network-helpers": "^1.0.4", + "@nomicfoundation/hardhat-toolbox": "^2.0.0", + "@nomiclabs/hardhat-etherscan": "^3.0.3", + "@semantic-release/changelog": "^6.0.1", + "@semantic-release/git": "^10.0.1", + "@semantic-release/npm": "^9.0.1", + "@trivago/prettier-plugin-sort-imports": "3.4.0", + "@typechain/ethers-v5": "^7.2.0", + "@typechain/hardhat": "^2.3.1", + "@types/chai": "^4.3.1", + "@types/mocha": "^9.1.1", + "@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/venus-protocol": "3.0.0-dev.18", + "bignumber.js": "9.0.0", + "chai": "^4.3.6", + "dotenv": "^10.0.0", + "eslint": "^7.32.0", + "eslint-config-prettier": "8.5.0", + "eslint-plugin-import": "^2.26.0", + "eslint-plugin-node": "^11.1.0", + "eslint-plugin-prettier": "3.4.1", + "eslint-plugin-promise": "^5.2.0", + "hardhat": "^2.16.1", + "hardhat-deploy": "^0.11.26", + "hardhat-deploy-ethers": "^0.3.0-beta.13", + "hardhat-gas-reporter": "^1.0.8", + "husky": "^8.0.1", + "prettier": "2.7.1", + "prettier-plugin-solidity": "1.1.3", + "semantic-release": "^19.0.3", + "solhint": "^3.3.7", + "solidity-coverage": "^0.8.4", + "solidity-docgen": "^0.6.0-beta.29", + "solparse": "^2.2.8", + "ts-node": "^10.7.0", + "typechain": "^5.2.0", + "typescript": "^4.6.3" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@aashutoshrathi/word-wrap": { + "version": "1.2.6", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@ampproject/remapping": { + "version": "2.2.1", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@aws-crypto/sha256-js": { + "version": "1.2.2", + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/util": "^1.2.2", + "@aws-sdk/types": "^3.1.0", + "tslib": "^1.11.1" + } + }, + "node_modules/@aws-crypto/util": { + "version": "1.2.2", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/types": "^3.1.0", + "@aws-sdk/util-utf8-browser": "^3.0.0", + "tslib": "^1.11.1" + } + }, + "node_modules/@aws-sdk/types": { + "version": "3.357.0", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/types/node_modules/tslib": { + "version": "2.6.0", + "license": "0BSD" + }, + "node_modules/@aws-sdk/util-utf8-browser": { + "version": "3.259.0", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.3.1" + } + }, + "node_modules/@aws-sdk/util-utf8-browser/node_modules/tslib": { + "version": "2.6.0", + "license": "0BSD" + }, + "node_modules/@babel/code-frame": { + "version": "7.22.5", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/highlight": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.22.6", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.17.8", + "dev": true, + "license": "MIT", + "dependencies": { + "@ampproject/remapping": "^2.1.0", + "@babel/code-frame": "^7.16.7", + "@babel/generator": "^7.17.7", + "@babel/helper-compilation-targets": "^7.17.7", + "@babel/helper-module-transforms": "^7.17.7", + "@babel/helpers": "^7.17.8", + "@babel/parser": "^7.17.8", + "@babel/template": "^7.16.7", + "@babel/traverse": "^7.17.3", + "@babel/types": "^7.17.0", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.1.2", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.0", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/generator": { + "version": "7.22.7", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.22.5", + "@jridgewell/gen-mapping": "^0.3.2", + "@jridgewell/trace-mapping": "^0.3.17", + "jsesc": "^2.5.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.22.6", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.22.6", + "@babel/helper-validator-option": "^7.22.5", + "@nicolo-ribaudo/semver-v6": "^6.3.3", + "browserslist": "^4.21.9", + "lru-cache": "^5.1.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/lru-cache": { + "version": "5.1.1", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/yallist": { + "version": "3.1.1", + "dev": true, + "license": "ISC" + }, + "node_modules/@babel/helper-environment-visitor": { + "version": "7.22.5", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-function-name": { + "version": "7.22.5", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.22.5", + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-hoist-variables": { + "version": "7.22.5", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.22.5", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.22.5", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-environment-visitor": "^7.22.5", + "@babel/helper-module-imports": "^7.22.5", + "@babel/helper-simple-access": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.5", + "@babel/template": "^7.22.5", + "@babel/traverse": "^7.22.5", + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-simple-access": { + "version": "7.22.5", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-split-export-declaration": { + "version": "7.22.6", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.22.5", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.22.5", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.22.5", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.22.6", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.22.5", + "@babel/traverse": "^7.22.6", + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.22.5", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.22.5", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight/node_modules/ansi-styles": { + "version": "3.2.1", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/chalk": { + "version": "2.4.2", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/color-convert": { + "version": "1.9.3", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/@babel/highlight/node_modules/color-name": { + "version": "1.1.3", + "dev": true, + "license": "MIT" + }, + "node_modules/@babel/highlight/node_modules/has-flag": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/supports-color": { + "version": "5.5.0", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/parser": { + "version": "7.22.7", + "dev": true, + "license": "MIT", + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/template": { + "version": "7.22.5", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.22.5", + "@babel/parser": "^7.22.5", + "@babel/types": "^7.22.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.22.8", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.22.5", + "@babel/generator": "^7.22.7", + "@babel/helper-environment-visitor": "^7.22.5", + "@babel/helper-function-name": "^7.22.5", + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/parser": "^7.22.7", + "@babel/types": "^7.22.5", + "debug": "^4.1.0", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse/node_modules/globals": { + "version": "11.12.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/types": { + "version": "7.22.5", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.5", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@chainlink/contracts": { + "version": "0.5.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@eth-optimism/contracts": "^0.5.21", + "@openzeppelin/contracts": "^4.3.3", + "@openzeppelin/contracts-v0.7": "npm:@openzeppelin/contracts@v3.4.2" + } + }, + "node_modules/@chainsafe/as-sha256": { + "version": "0.3.1", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/@chainsafe/persistent-merkle-tree": { + "version": "0.5.0", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@chainsafe/as-sha256": "^0.3.1" + } + }, + "node_modules/@chainsafe/ssz": { + "version": "0.10.2", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@chainsafe/as-sha256": "^0.3.1", + "@chainsafe/persistent-merkle-tree": "^0.5.0" + } + }, + "node_modules/@colors/colors": { + "version": "1.5.0", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.1.90" + } + }, + "node_modules/@commitlint/cli": { + "version": "17.6.6", + "dev": true, + "license": "MIT", + "dependencies": { + "@commitlint/format": "^17.4.4", + "@commitlint/lint": "^17.6.6", + "@commitlint/load": "^17.5.0", + "@commitlint/read": "^17.5.1", + "@commitlint/types": "^17.4.4", + "execa": "^5.0.0", + "lodash.isfunction": "^3.0.9", + "resolve-from": "5.0.0", + "resolve-global": "1.0.0", + "yargs": "^17.0.0" + }, + "bin": { + "commitlint": "cli.js" + }, + "engines": { + "node": ">=v14" + } + }, + "node_modules/@commitlint/cli/node_modules/yargs": { + "version": "17.7.2", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@commitlint/cli/node_modules/yargs-parser": { + "version": "21.1.1", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/@commitlint/config-conventional": { + "version": "17.6.6", + "dev": true, + "license": "MIT", + "dependencies": { + "conventional-changelog-conventionalcommits": "^5.0.0" + }, + "engines": { + "node": ">=v14" + } + }, + "node_modules/@commitlint/config-validator": { + "version": "17.4.4", + "dev": true, + "license": "MIT", + "dependencies": { + "@commitlint/types": "^17.4.4", + "ajv": "^8.11.0" + }, + "engines": { + "node": ">=v14" + } + }, + "node_modules/@commitlint/config-validator/node_modules/ajv": { + "version": "8.12.0", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@commitlint/ensure": { + "version": "17.4.4", + "dev": true, + "license": "MIT", + "dependencies": { + "@commitlint/types": "^17.4.4", + "lodash.camelcase": "^4.3.0", + "lodash.kebabcase": "^4.1.1", + "lodash.snakecase": "^4.1.1", + "lodash.startcase": "^4.4.0", + "lodash.upperfirst": "^4.3.1" + }, + "engines": { + "node": ">=v14" + } + }, + "node_modules/@commitlint/execute-rule": { + "version": "17.4.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=v14" + } + }, + "node_modules/@commitlint/format": { + "version": "17.4.4", + "dev": true, + "license": "MIT", + "dependencies": { + "@commitlint/types": "^17.4.4", + "chalk": "^4.1.0" + }, + "engines": { + "node": ">=v14" + } + }, + "node_modules/@commitlint/is-ignored": { + "version": "17.6.6", + "dev": true, + "license": "MIT", + "dependencies": { + "@commitlint/types": "^17.4.4", + "semver": "7.5.2" + }, + "engines": { + "node": ">=v14" + } + }, + "node_modules/@commitlint/is-ignored/node_modules/lru-cache": { + "version": "6.0.0", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@commitlint/is-ignored/node_modules/semver": { + "version": "7.5.2", + "dev": true, + "license": "ISC", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@commitlint/lint": { + "version": "17.6.6", + "dev": true, + "license": "MIT", + "dependencies": { + "@commitlint/is-ignored": "^17.6.6", + "@commitlint/parse": "^17.6.5", + "@commitlint/rules": "^17.6.5", + "@commitlint/types": "^17.4.4" + }, + "engines": { + "node": ">=v14" + } + }, + "node_modules/@commitlint/load": { + "version": "17.5.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@commitlint/config-validator": "^17.4.4", + "@commitlint/execute-rule": "^17.4.0", + "@commitlint/resolve-extends": "^17.4.4", + "@commitlint/types": "^17.4.4", + "@types/node": "*", + "chalk": "^4.1.0", + "cosmiconfig": "^8.0.0", + "cosmiconfig-typescript-loader": "^4.0.0", + "lodash.isplainobject": "^4.0.6", + "lodash.merge": "^4.6.2", + "lodash.uniq": "^4.5.0", + "resolve-from": "^5.0.0", + "ts-node": "^10.8.1", + "typescript": "^4.6.4 || ^5.0.0" + }, + "engines": { + "node": ">=v14" + } + }, + "node_modules/@commitlint/load/node_modules/@types/node": { + "version": "20.4.1", + "dev": true, + "license": "MIT" + }, + "node_modules/@commitlint/load/node_modules/acorn": { + "version": "8.10.0", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/@commitlint/load/node_modules/cosmiconfig-typescript-loader": { + "version": "4.3.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12", + "npm": ">=6" + }, + "peerDependencies": { + "@types/node": "*", + "cosmiconfig": ">=7", + "ts-node": ">=10", + "typescript": ">=3" + } + }, + "node_modules/@commitlint/load/node_modules/diff": { + "version": "4.0.2", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/@commitlint/load/node_modules/ts-node": { + "version": "10.9.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } + } + }, + "node_modules/@commitlint/load/node_modules/typescript": { + "version": "5.1.6", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/@commitlint/message": { + "version": "17.4.2", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=v14" + } + }, + "node_modules/@commitlint/parse": { + "version": "17.6.5", + "dev": true, + "license": "MIT", + "dependencies": { + "@commitlint/types": "^17.4.4", + "conventional-changelog-angular": "^5.0.11", + "conventional-commits-parser": "^3.2.2" + }, + "engines": { + "node": ">=v14" + } + }, + "node_modules/@commitlint/read": { + "version": "17.5.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@commitlint/top-level": "^17.4.0", + "@commitlint/types": "^17.4.4", + "fs-extra": "^11.0.0", + "git-raw-commits": "^2.0.11", + "minimist": "^1.2.6" + }, + "engines": { + "node": ">=v14" + } + }, + "node_modules/@commitlint/resolve-extends": { + "version": "17.4.4", + "dev": true, + "license": "MIT", + "dependencies": { + "@commitlint/config-validator": "^17.4.4", + "@commitlint/types": "^17.4.4", + "import-fresh": "^3.0.0", + "lodash.mergewith": "^4.6.2", + "resolve-from": "^5.0.0", + "resolve-global": "^1.0.0" + }, + "engines": { + "node": ">=v14" + } + }, + "node_modules/@commitlint/rules": { + "version": "17.6.5", + "dev": true, + "license": "MIT", + "dependencies": { + "@commitlint/ensure": "^17.4.4", + "@commitlint/message": "^17.4.2", + "@commitlint/to-lines": "^17.4.0", + "@commitlint/types": "^17.4.4", + "execa": "^5.0.0" + }, + "engines": { + "node": ">=v14" + } + }, + "node_modules/@commitlint/to-lines": { + "version": "17.4.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=v14" + } + }, + "node_modules/@commitlint/top-level": { + "version": "17.4.0", + "dev": true, + "license": "MIT", + "dependencies": { + "find-up": "^5.0.0" + }, + "engines": { + "node": ">=v14" + } + }, + "node_modules/@commitlint/top-level/node_modules/find-up": { + "version": "5.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@commitlint/top-level/node_modules/locate-path": { + "version": "6.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@commitlint/top-level/node_modules/p-limit": { + "version": "3.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@commitlint/top-level/node_modules/p-locate": { + "version": "5.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@commitlint/types": { + "version": "17.4.4", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.1.0" + }, + "engines": { + "node": ">=v14" + } + }, + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "0.3.9" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "node_modules/@defi-wonderland/smock": { + "version": "2.3.5", + "dev": true, + "license": "MIT", + "dependencies": { + "@nomicfoundation/ethereumjs-evm": "^1.0.0-rc.3", + "@nomicfoundation/ethereumjs-util": "^8.0.0-rc.3", + "@nomicfoundation/ethereumjs-vm": "^6.0.0-rc.3", + "diff": "^5.0.0", + "lodash.isequal": "^4.5.0", + "lodash.isequalwith": "^4.4.0", + "rxjs": "^7.2.0", + "semver": "^7.3.5" + }, + "peerDependencies": { + "@ethersproject/abi": "^5", + "@ethersproject/abstract-provider": "^5", + "@ethersproject/abstract-signer": "^5", + "@nomiclabs/hardhat-ethers": "^2", + "ethers": "^5", + "hardhat": "^2" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.0", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "3.4.1", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.5.1", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "0.4.3", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.1.1", + "espree": "^7.3.0", + "globals": "^13.9.0", + "ignore": "^4.0.6", + "import-fresh": "^3.2.1", + "js-yaml": "^3.13.1", + "minimatch": "^3.0.4", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/@eslint/eslintrc/node_modules/ignore": { + "version": "4.0.6", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/@eslint/eslintrc/node_modules/js-yaml": { + "version": "3.14.1", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/@eth-optimism/contracts": { + "version": "0.5.40", + "dev": true, + "license": "MIT", + "dependencies": { + "@eth-optimism/core-utils": "0.12.0", + "@ethersproject/abstract-provider": "^5.7.0", + "@ethersproject/abstract-signer": "^5.7.0" + }, + "peerDependencies": { + "ethers": "^5" + } + }, + "node_modules/@eth-optimism/core-utils": { + "version": "0.12.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@ethersproject/abi": "^5.7.0", + "@ethersproject/abstract-provider": "^5.7.0", + "@ethersproject/address": "^5.7.0", + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/constants": "^5.7.0", + "@ethersproject/contracts": "^5.7.0", + "@ethersproject/hash": "^5.7.0", + "@ethersproject/keccak256": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/providers": "^5.7.0", + "@ethersproject/rlp": "^5.7.0", + "@ethersproject/transactions": "^5.7.0", + "@ethersproject/web": "^5.7.0", + "bufio": "^1.0.7", + "chai": "^4.3.4" + } + }, + "node_modules/@ethersproject/abi": { + "version": "5.7.0", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/address": "^5.7.0", + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/constants": "^5.7.0", + "@ethersproject/hash": "^5.7.0", + "@ethersproject/keccak256": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/strings": "^5.7.0" + } + }, + "node_modules/@ethersproject/abstract-provider": { + "version": "5.7.0", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/networks": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/transactions": "^5.7.0", + "@ethersproject/web": "^5.7.0" + } + }, + "node_modules/@ethersproject/abstract-signer": { + "version": "5.7.0", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/abstract-provider": "^5.7.0", + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/properties": "^5.7.0" + } + }, + "node_modules/@ethersproject/address": { + "version": "5.7.0", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/keccak256": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/rlp": "^5.7.0" + } + }, + "node_modules/@ethersproject/base64": { + "version": "5.7.0", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/bytes": "^5.7.0" + } + }, + "node_modules/@ethersproject/basex": { + "version": "5.7.0", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/properties": "^5.7.0" + } + }, + "node_modules/@ethersproject/bignumber": { + "version": "5.7.0", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "bn.js": "^5.2.1" + } + }, + "node_modules/@ethersproject/bytes": { + "version": "5.7.0", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/logger": "^5.7.0" + } + }, + "node_modules/@ethersproject/constants": { + "version": "5.7.0", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/bignumber": "^5.7.0" + } + }, + "node_modules/@ethersproject/contracts": { + "version": "5.7.0", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/abi": "^5.7.0", + "@ethersproject/abstract-provider": "^5.7.0", + "@ethersproject/abstract-signer": "^5.7.0", + "@ethersproject/address": "^5.7.0", + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/constants": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/transactions": "^5.7.0" + } + }, + "node_modules/@ethersproject/hash": { + "version": "5.7.0", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/abstract-signer": "^5.7.0", + "@ethersproject/address": "^5.7.0", + "@ethersproject/base64": "^5.7.0", + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/keccak256": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/strings": "^5.7.0" + } + }, + "node_modules/@ethersproject/hdnode": { + "version": "5.7.0", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/abstract-signer": "^5.7.0", + "@ethersproject/basex": "^5.7.0", + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/pbkdf2": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/sha2": "^5.7.0", + "@ethersproject/signing-key": "^5.7.0", + "@ethersproject/strings": "^5.7.0", + "@ethersproject/transactions": "^5.7.0", + "@ethersproject/wordlists": "^5.7.0" + } + }, + "node_modules/@ethersproject/json-wallets": { + "version": "5.7.0", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/abstract-signer": "^5.7.0", + "@ethersproject/address": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/hdnode": "^5.7.0", + "@ethersproject/keccak256": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/pbkdf2": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/random": "^5.7.0", + "@ethersproject/strings": "^5.7.0", + "@ethersproject/transactions": "^5.7.0", + "aes-js": "3.0.0", + "scrypt-js": "3.0.1" + } + }, + "node_modules/@ethersproject/keccak256": { + "version": "5.7.0", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/bytes": "^5.7.0", + "js-sha3": "0.8.0" + } + }, + "node_modules/@ethersproject/logger": { + "version": "5.7.0", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT" + }, + "node_modules/@ethersproject/networks": { + "version": "5.7.1", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/logger": "^5.7.0" + } + }, + "node_modules/@ethersproject/pbkdf2": { + "version": "5.7.0", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/sha2": "^5.7.0" + } + }, + "node_modules/@ethersproject/properties": { + "version": "5.7.0", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/logger": "^5.7.0" + } + }, + "node_modules/@ethersproject/providers": { + "version": "5.7.2", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/abstract-provider": "^5.7.0", + "@ethersproject/abstract-signer": "^5.7.0", + "@ethersproject/address": "^5.7.0", + "@ethersproject/base64": "^5.7.0", + "@ethersproject/basex": "^5.7.0", + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/constants": "^5.7.0", + "@ethersproject/hash": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/networks": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/random": "^5.7.0", + "@ethersproject/rlp": "^5.7.0", + "@ethersproject/sha2": "^5.7.0", + "@ethersproject/strings": "^5.7.0", + "@ethersproject/transactions": "^5.7.0", + "@ethersproject/web": "^5.7.0", + "bech32": "1.1.4", + "ws": "7.4.6" + } + }, + "node_modules/@ethersproject/random": { + "version": "5.7.0", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/logger": "^5.7.0" + } + }, + "node_modules/@ethersproject/rlp": { + "version": "5.7.0", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/logger": "^5.7.0" + } + }, + "node_modules/@ethersproject/sha2": { + "version": "5.7.0", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "hash.js": "1.1.7" + } + }, + "node_modules/@ethersproject/signing-key": { + "version": "5.7.0", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "bn.js": "^5.2.1", + "elliptic": "6.5.4", + "hash.js": "1.1.7" + } + }, + "node_modules/@ethersproject/solidity": { + "version": "5.7.0", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/keccak256": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/sha2": "^5.7.0", + "@ethersproject/strings": "^5.7.0" + } + }, + "node_modules/@ethersproject/strings": { + "version": "5.7.0", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/constants": "^5.7.0", + "@ethersproject/logger": "^5.7.0" + } + }, + "node_modules/@ethersproject/transactions": { + "version": "5.7.0", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/address": "^5.7.0", + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/constants": "^5.7.0", + "@ethersproject/keccak256": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/rlp": "^5.7.0", + "@ethersproject/signing-key": "^5.7.0" + } + }, + "node_modules/@ethersproject/units": { + "version": "5.7.0", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/constants": "^5.7.0", + "@ethersproject/logger": "^5.7.0" + } + }, + "node_modules/@ethersproject/wallet": { + "version": "5.7.0", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/abstract-provider": "^5.7.0", + "@ethersproject/abstract-signer": "^5.7.0", + "@ethersproject/address": "^5.7.0", + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/hash": "^5.7.0", + "@ethersproject/hdnode": "^5.7.0", + "@ethersproject/json-wallets": "^5.7.0", + "@ethersproject/keccak256": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/random": "^5.7.0", + "@ethersproject/signing-key": "^5.7.0", + "@ethersproject/transactions": "^5.7.0", + "@ethersproject/wordlists": "^5.7.0" + } + }, + "node_modules/@ethersproject/web": { + "version": "5.7.1", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/base64": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/strings": "^5.7.0" + } + }, + "node_modules/@ethersproject/wordlists": { + "version": "5.7.0", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/hash": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/strings": "^5.7.0" + } + }, + "node_modules/@gar/promisify": { + "version": "1.1.3", + "dev": true, + "license": "MIT" + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.5.0", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanwhocodes/object-schema": "^1.2.0", + "debug": "^4.1.1", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "1.2.1", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-styles": { + "version": "6.2.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/emoji-regex": { + "version": "9.2.2", + "dev": true, + "license": "MIT" + }, + "node_modules/@isaacs/cliui/node_modules/string-width": { + "version": "5.1.2", + "dev": true, + "license": "MIT", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { + "version": "8.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/@isaacs/string-locale-compare": { + "version": "1.1.0", + "dev": true, + "license": "ISC" + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.3", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.1.2", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.18", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "3.1.0", + "@jridgewell/sourcemap-codec": "1.4.14" + } + }, + "node_modules/@jridgewell/trace-mapping/node_modules/@jridgewell/resolve-uri": { + "version": "3.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/trace-mapping/node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.14", + "dev": true, + "license": "MIT" + }, + "node_modules/@metamask/eth-sig-util": { + "version": "4.0.1", + "dev": true, + "license": "ISC", + "dependencies": { + "ethereumjs-abi": "^0.6.8", + "ethereumjs-util": "^6.2.1", + "ethjs-util": "^0.1.6", + "tweetnacl": "^1.0.3", + "tweetnacl-util": "^0.15.1" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/@metamask/eth-sig-util/node_modules/@types/bn.js": { + "version": "4.11.6", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@metamask/eth-sig-util/node_modules/@types/node": { + "version": "20.4.1", + "dev": true, + "license": "MIT" + }, + "node_modules/@metamask/eth-sig-util/node_modules/bn.js": { + "version": "4.12.0", + "dev": true, + "license": "MIT" + }, + "node_modules/@metamask/eth-sig-util/node_modules/ethereumjs-util": { + "version": "6.2.1", + "dev": true, + "license": "MPL-2.0", + "dependencies": { + "@types/bn.js": "^4.11.3", + "bn.js": "^4.11.0", + "create-hash": "^1.1.2", + "elliptic": "^6.5.2", + "ethereum-cryptography": "^0.1.3", + "ethjs-util": "0.1.6", + "rlp": "^2.2.3" + } + }, + "node_modules/@metamask/eth-sig-util/node_modules/tweetnacl": { + "version": "1.0.3", + "dev": true, + "license": "Unlicense" + }, + "node_modules/@nicolo-ribaudo/semver-v6": { + "version": "6.3.3", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@noble/hashes": { + "version": "1.2.0", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "license": "MIT" + }, + "node_modules/@noble/secp256k1": { + "version": "1.7.1", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "license": "MIT" + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nomicfoundation/ethereumjs-block": { + "version": "5.0.1", + "dev": true, + "license": "MPL-2.0", + "dependencies": { + "@nomicfoundation/ethereumjs-common": "4.0.1", + "@nomicfoundation/ethereumjs-rlp": "5.0.1", + "@nomicfoundation/ethereumjs-trie": "6.0.1", + "@nomicfoundation/ethereumjs-tx": "5.0.1", + "@nomicfoundation/ethereumjs-util": "9.0.1", + "ethereum-cryptography": "0.1.3", + "ethers": "^5.7.1" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@nomicfoundation/ethereumjs-block/node_modules/@nomicfoundation/ethereumjs-trie": { + "version": "6.0.1", + "dev": true, + "license": "MPL-2.0", + "dependencies": { + "@nomicfoundation/ethereumjs-rlp": "5.0.1", + "@nomicfoundation/ethereumjs-util": "9.0.1", + "@types/readable-stream": "^2.3.13", + "ethereum-cryptography": "0.1.3", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@nomicfoundation/ethereumjs-block/node_modules/@nomicfoundation/ethereumjs-util": { + "version": "9.0.1", + "dev": true, + "license": "MPL-2.0", + "dependencies": { + "@chainsafe/ssz": "^0.10.0", + "@nomicfoundation/ethereumjs-rlp": "5.0.1", + "ethereum-cryptography": "0.1.3" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@nomicfoundation/ethereumjs-blockchain": { + "version": "7.0.1", + "dev": true, + "license": "MPL-2.0", + "dependencies": { + "@nomicfoundation/ethereumjs-block": "5.0.1", + "@nomicfoundation/ethereumjs-common": "4.0.1", + "@nomicfoundation/ethereumjs-ethash": "3.0.1", + "@nomicfoundation/ethereumjs-rlp": "5.0.1", + "@nomicfoundation/ethereumjs-trie": "6.0.1", + "@nomicfoundation/ethereumjs-tx": "5.0.1", + "@nomicfoundation/ethereumjs-util": "9.0.1", + "abstract-level": "^1.0.3", + "debug": "^4.3.3", + "ethereum-cryptography": "0.1.3", + "level": "^8.0.0", + "lru-cache": "^5.1.1", + "memory-level": "^1.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@nomicfoundation/ethereumjs-blockchain/node_modules/@nomicfoundation/ethereumjs-ethash": { + "version": "3.0.1", + "dev": true, + "license": "MPL-2.0", + "dependencies": { + "@nomicfoundation/ethereumjs-block": "5.0.1", + "@nomicfoundation/ethereumjs-rlp": "5.0.1", + "@nomicfoundation/ethereumjs-util": "9.0.1", + "abstract-level": "^1.0.3", + "bigint-crypto-utils": "^3.0.23", + "ethereum-cryptography": "0.1.3" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@nomicfoundation/ethereumjs-blockchain/node_modules/@nomicfoundation/ethereumjs-trie": { + "version": "6.0.1", + "dev": true, + "license": "MPL-2.0", + "dependencies": { + "@nomicfoundation/ethereumjs-rlp": "5.0.1", + "@nomicfoundation/ethereumjs-util": "9.0.1", + "@types/readable-stream": "^2.3.13", + "ethereum-cryptography": "0.1.3", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@nomicfoundation/ethereumjs-blockchain/node_modules/@nomicfoundation/ethereumjs-util": { + "version": "9.0.1", + "dev": true, + "license": "MPL-2.0", + "dependencies": { + "@chainsafe/ssz": "^0.10.0", + "@nomicfoundation/ethereumjs-rlp": "5.0.1", + "ethereum-cryptography": "0.1.3" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@nomicfoundation/ethereumjs-blockchain/node_modules/lru-cache": { + "version": "5.1.1", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/@nomicfoundation/ethereumjs-blockchain/node_modules/yallist": { + "version": "3.1.1", + "dev": true, + "license": "ISC" + }, + "node_modules/@nomicfoundation/ethereumjs-common": { + "version": "4.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@nomicfoundation/ethereumjs-util": "9.0.1", + "crc-32": "^1.2.0" + } + }, + "node_modules/@nomicfoundation/ethereumjs-common/node_modules/@nomicfoundation/ethereumjs-util": { + "version": "9.0.1", + "dev": true, + "license": "MPL-2.0", + "dependencies": { + "@chainsafe/ssz": "^0.10.0", + "@nomicfoundation/ethereumjs-rlp": "5.0.1", + "ethereum-cryptography": "0.1.3" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@nomicfoundation/ethereumjs-ethash": { + "version": "2.0.5", + "dev": true, + "license": "MPL-2.0", + "dependencies": { + "@nomicfoundation/ethereumjs-block": "4.2.2", + "@nomicfoundation/ethereumjs-rlp": "4.0.3", + "@nomicfoundation/ethereumjs-util": "8.0.6", + "abstract-level": "^1.0.3", + "bigint-crypto-utils": "^3.0.23", + "ethereum-cryptography": "0.1.3" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@nomicfoundation/ethereumjs-ethash/node_modules/@nomicfoundation/ethereumjs-block": { + "version": "4.2.2", + "dev": true, + "license": "MPL-2.0", + "dependencies": { + "@nomicfoundation/ethereumjs-common": "3.1.2", + "@nomicfoundation/ethereumjs-rlp": "4.0.3", + "@nomicfoundation/ethereumjs-trie": "5.0.5", + "@nomicfoundation/ethereumjs-tx": "4.1.2", + "@nomicfoundation/ethereumjs-util": "8.0.6", + "ethereum-cryptography": "0.1.3" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@nomicfoundation/ethereumjs-ethash/node_modules/@nomicfoundation/ethereumjs-common": { + "version": "3.1.2", + "dev": true, + "license": "MIT", + "dependencies": { + "@nomicfoundation/ethereumjs-util": "8.0.6", + "crc-32": "^1.2.0" + } + }, + "node_modules/@nomicfoundation/ethereumjs-ethash/node_modules/@nomicfoundation/ethereumjs-rlp": { + "version": "4.0.3", + "dev": true, + "license": "MPL-2.0", + "bin": { + "rlp": "bin/rlp" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@nomicfoundation/ethereumjs-ethash/node_modules/@nomicfoundation/ethereumjs-tx": { + "version": "4.1.2", + "dev": true, + "license": "MPL-2.0", + "dependencies": { + "@nomicfoundation/ethereumjs-common": "3.1.2", + "@nomicfoundation/ethereumjs-rlp": "4.0.3", + "@nomicfoundation/ethereumjs-util": "8.0.6", + "ethereum-cryptography": "0.1.3" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@nomicfoundation/ethereumjs-evm": { + "version": "1.3.2", + "dev": true, + "license": "MPL-2.0", + "dependencies": { + "@nomicfoundation/ethereumjs-common": "3.1.2", + "@nomicfoundation/ethereumjs-util": "8.0.6", + "@types/async-eventemitter": "^0.2.1", + "async-eventemitter": "^0.2.4", + "debug": "^4.3.3", + "ethereum-cryptography": "0.1.3", + "mcl-wasm": "^0.7.1", + "rustbn.js": "~0.2.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@nomicfoundation/ethereumjs-evm/node_modules/@nomicfoundation/ethereumjs-common": { + "version": "3.1.2", + "dev": true, + "license": "MIT", + "dependencies": { + "@nomicfoundation/ethereumjs-util": "8.0.6", + "crc-32": "^1.2.0" + } + }, + "node_modules/@nomicfoundation/ethereumjs-rlp": { + "version": "5.0.1", + "dev": true, + "license": "MPL-2.0", + "bin": { + "rlp": "bin/rlp" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@nomicfoundation/ethereumjs-statemanager": { + "version": "2.0.1", + "dev": true, + "license": "MPL-2.0", + "dependencies": { + "@nomicfoundation/ethereumjs-common": "4.0.1", + "@nomicfoundation/ethereumjs-rlp": "5.0.1", + "debug": "^4.3.3", + "ethereum-cryptography": "0.1.3", + "ethers": "^5.7.1", + "js-sdsl": "^4.1.4" + } + }, + "node_modules/@nomicfoundation/ethereumjs-trie": { + "version": "5.0.5", + "dev": true, + "license": "MPL-2.0", + "dependencies": { + "@nomicfoundation/ethereumjs-rlp": "4.0.3", + "@nomicfoundation/ethereumjs-util": "8.0.6", + "ethereum-cryptography": "0.1.3", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@nomicfoundation/ethereumjs-trie/node_modules/@nomicfoundation/ethereumjs-rlp": { + "version": "4.0.3", + "dev": true, + "license": "MPL-2.0", + "bin": { + "rlp": "bin/rlp" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@nomicfoundation/ethereumjs-tx": { + "version": "5.0.1", + "dev": true, + "license": "MPL-2.0", + "dependencies": { + "@chainsafe/ssz": "^0.9.2", + "@ethersproject/providers": "^5.7.2", + "@nomicfoundation/ethereumjs-common": "4.0.1", + "@nomicfoundation/ethereumjs-rlp": "5.0.1", + "@nomicfoundation/ethereumjs-util": "9.0.1", + "ethereum-cryptography": "0.1.3" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@nomicfoundation/ethereumjs-tx/node_modules/@chainsafe/ssz": { + "version": "0.9.4", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@chainsafe/as-sha256": "^0.3.1", + "@chainsafe/persistent-merkle-tree": "^0.4.2", + "case": "^1.6.3" + } + }, + "node_modules/@nomicfoundation/ethereumjs-tx/node_modules/@chainsafe/ssz/node_modules/@chainsafe/persistent-merkle-tree": { + "version": "0.4.2", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@chainsafe/as-sha256": "^0.3.1" + } + }, + "node_modules/@nomicfoundation/ethereumjs-tx/node_modules/@nomicfoundation/ethereumjs-util": { + "version": "9.0.1", + "dev": true, + "license": "MPL-2.0", + "dependencies": { + "@chainsafe/ssz": "^0.10.0", + "@nomicfoundation/ethereumjs-rlp": "5.0.1", + "ethereum-cryptography": "0.1.3" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@nomicfoundation/ethereumjs-tx/node_modules/@nomicfoundation/ethereumjs-util/node_modules/@chainsafe/ssz": { + "version": "0.10.2", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@chainsafe/as-sha256": "^0.3.1", + "@chainsafe/persistent-merkle-tree": "^0.5.0" + } + }, + "node_modules/@nomicfoundation/ethereumjs-util": { + "version": "8.0.6", + "dev": true, + "license": "MPL-2.0", + "dependencies": { + "@nomicfoundation/ethereumjs-rlp": "4.0.3", + "ethereum-cryptography": "0.1.3" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@nomicfoundation/ethereumjs-util/node_modules/@nomicfoundation/ethereumjs-rlp": { + "version": "4.0.3", + "dev": true, + "license": "MPL-2.0", + "bin": { + "rlp": "bin/rlp" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@nomicfoundation/ethereumjs-vm": { + "version": "6.4.2", + "dev": true, + "license": "MPL-2.0", + "dependencies": { + "@nomicfoundation/ethereumjs-block": "4.2.2", + "@nomicfoundation/ethereumjs-blockchain": "6.2.2", + "@nomicfoundation/ethereumjs-common": "3.1.2", + "@nomicfoundation/ethereumjs-evm": "1.3.2", + "@nomicfoundation/ethereumjs-rlp": "4.0.3", + "@nomicfoundation/ethereumjs-statemanager": "1.0.5", + "@nomicfoundation/ethereumjs-trie": "5.0.5", + "@nomicfoundation/ethereumjs-tx": "4.1.2", + "@nomicfoundation/ethereumjs-util": "8.0.6", + "@types/async-eventemitter": "^0.2.1", + "async-eventemitter": "^0.2.4", + "debug": "^4.3.3", + "ethereum-cryptography": "0.1.3", + "functional-red-black-tree": "^1.0.1", + "mcl-wasm": "^0.7.1", + "rustbn.js": "~0.2.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@nomicfoundation/ethereumjs-vm/node_modules/@nomicfoundation/ethereumjs-block": { + "version": "4.2.2", + "dev": true, + "license": "MPL-2.0", + "dependencies": { + "@nomicfoundation/ethereumjs-common": "3.1.2", + "@nomicfoundation/ethereumjs-rlp": "4.0.3", + "@nomicfoundation/ethereumjs-trie": "5.0.5", + "@nomicfoundation/ethereumjs-tx": "4.1.2", + "@nomicfoundation/ethereumjs-util": "8.0.6", + "ethereum-cryptography": "0.1.3" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@nomicfoundation/ethereumjs-vm/node_modules/@nomicfoundation/ethereumjs-blockchain": { + "version": "6.2.2", + "dev": true, + "license": "MPL-2.0", + "dependencies": { + "@nomicfoundation/ethereumjs-block": "4.2.2", + "@nomicfoundation/ethereumjs-common": "3.1.2", + "@nomicfoundation/ethereumjs-ethash": "2.0.5", + "@nomicfoundation/ethereumjs-rlp": "4.0.3", + "@nomicfoundation/ethereumjs-trie": "5.0.5", + "@nomicfoundation/ethereumjs-util": "8.0.6", + "abstract-level": "^1.0.3", + "debug": "^4.3.3", + "ethereum-cryptography": "0.1.3", + "level": "^8.0.0", + "lru-cache": "^5.1.1", + "memory-level": "^1.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@nomicfoundation/ethereumjs-vm/node_modules/@nomicfoundation/ethereumjs-common": { + "version": "3.1.2", + "dev": true, + "license": "MIT", + "dependencies": { + "@nomicfoundation/ethereumjs-util": "8.0.6", + "crc-32": "^1.2.0" + } + }, + "node_modules/@nomicfoundation/ethereumjs-vm/node_modules/@nomicfoundation/ethereumjs-rlp": { + "version": "4.0.3", + "dev": true, + "license": "MPL-2.0", + "bin": { + "rlp": "bin/rlp" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@nomicfoundation/ethereumjs-vm/node_modules/@nomicfoundation/ethereumjs-statemanager": { + "version": "1.0.5", + "dev": true, + "license": "MPL-2.0", + "dependencies": { + "@nomicfoundation/ethereumjs-common": "3.1.2", + "@nomicfoundation/ethereumjs-rlp": "4.0.3", + "@nomicfoundation/ethereumjs-trie": "5.0.5", + "@nomicfoundation/ethereumjs-util": "8.0.6", + "debug": "^4.3.3", + "ethereum-cryptography": "0.1.3", + "functional-red-black-tree": "^1.0.1" + } + }, + "node_modules/@nomicfoundation/ethereumjs-vm/node_modules/@nomicfoundation/ethereumjs-tx": { + "version": "4.1.2", + "dev": true, + "license": "MPL-2.0", + "dependencies": { + "@nomicfoundation/ethereumjs-common": "3.1.2", + "@nomicfoundation/ethereumjs-rlp": "4.0.3", + "@nomicfoundation/ethereumjs-util": "8.0.6", + "ethereum-cryptography": "0.1.3" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@nomicfoundation/ethereumjs-vm/node_modules/lru-cache": { + "version": "5.1.1", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/@nomicfoundation/ethereumjs-vm/node_modules/yallist": { + "version": "3.1.1", + "dev": true, + "license": "ISC" + }, + "node_modules/@nomicfoundation/hardhat-chai-matchers": { + "version": "1.0.6", + "dev": true, + "license": "MIT", + "dependencies": { + "@ethersproject/abi": "^5.1.2", + "@types/chai-as-promised": "^7.1.3", + "chai-as-promised": "^7.1.1", + "deep-eql": "^4.0.1", + "ordinal": "^1.0.3" + }, + "peerDependencies": { + "@nomiclabs/hardhat-ethers": "^2.0.0", + "chai": "^4.2.0", + "ethers": "^5.0.0", + "hardhat": "^2.9.4" + } + }, + "node_modules/@nomicfoundation/hardhat-network-helpers": { + "version": "1.0.8", + "dev": true, + "license": "MIT", + "dependencies": { + "ethereumjs-util": "^7.1.4" + }, + "peerDependencies": { + "hardhat": "^2.9.5" + } + }, + "node_modules/@nomicfoundation/hardhat-toolbox": { + "version": "2.0.2", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@ethersproject/abi": "^5.4.7", + "@ethersproject/providers": "^5.4.7", + "@nomicfoundation/hardhat-chai-matchers": "^1.0.0", + "@nomicfoundation/hardhat-network-helpers": "^1.0.0", + "@nomiclabs/hardhat-ethers": "^2.0.0", + "@nomiclabs/hardhat-etherscan": "^3.0.0", + "@typechain/ethers-v5": "^10.1.0", + "@typechain/hardhat": "^6.1.2", + "@types/chai": "^4.2.0", + "@types/mocha": ">=9.1.0", + "@types/node": ">=12.0.0", + "chai": "^4.2.0", + "ethers": "^5.4.7", + "hardhat": "^2.11.0", + "hardhat-gas-reporter": "^1.0.8", + "solidity-coverage": "^0.8.1", + "ts-node": ">=8.0.0", + "typechain": "^8.1.0", + "typescript": ">=4.5.0" + } + }, + "node_modules/@nomicfoundation/solidity-analyzer": { + "version": "0.1.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 12" + }, + "optionalDependencies": { + "@nomicfoundation/solidity-analyzer-darwin-arm64": "0.1.1", + "@nomicfoundation/solidity-analyzer-darwin-x64": "0.1.1", + "@nomicfoundation/solidity-analyzer-freebsd-x64": "0.1.1", + "@nomicfoundation/solidity-analyzer-linux-arm64-gnu": "0.1.1", + "@nomicfoundation/solidity-analyzer-linux-arm64-musl": "0.1.1", + "@nomicfoundation/solidity-analyzer-linux-x64-gnu": "0.1.1", + "@nomicfoundation/solidity-analyzer-linux-x64-musl": "0.1.1", + "@nomicfoundation/solidity-analyzer-win32-arm64-msvc": "0.1.1", + "@nomicfoundation/solidity-analyzer-win32-ia32-msvc": "0.1.1", + "@nomicfoundation/solidity-analyzer-win32-x64-msvc": "0.1.1" + } + }, + "node_modules/@nomicfoundation/solidity-analyzer-darwin-x64": { + "version": "0.1.1", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nomiclabs/hardhat-etherscan": { + "version": "3.1.7", + "dev": true, + "license": "MIT", + "dependencies": { + "@ethersproject/abi": "^5.1.2", + "@ethersproject/address": "^5.0.2", + "cbor": "^8.1.0", + "chalk": "^2.4.2", + "debug": "^4.1.1", + "fs-extra": "^7.0.1", + "lodash": "^4.17.11", + "semver": "^6.3.0", + "table": "^6.8.0", + "undici": "^5.14.0" + }, + "peerDependencies": { + "hardhat": "^2.0.4" + } + }, + "node_modules/@nomiclabs/hardhat-etherscan/node_modules/ansi-styles": { + "version": "3.2.1", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@nomiclabs/hardhat-etherscan/node_modules/chalk": { + "version": "2.4.2", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@nomiclabs/hardhat-etherscan/node_modules/color-convert": { + "version": "1.9.3", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/@nomiclabs/hardhat-etherscan/node_modules/color-name": { + "version": "1.1.3", + "dev": true, + "license": "MIT" + }, + "node_modules/@nomiclabs/hardhat-etherscan/node_modules/fs-extra": { + "version": "7.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "node_modules/@nomiclabs/hardhat-etherscan/node_modules/has-flag": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/@nomiclabs/hardhat-etherscan/node_modules/jsonfile": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/@nomiclabs/hardhat-etherscan/node_modules/semver": { + "version": "6.3.0", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@nomiclabs/hardhat-etherscan/node_modules/supports-color": { + "version": "5.5.0", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@nomiclabs/hardhat-etherscan/node_modules/universalify": { + "version": "0.1.2", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/@npmcli/arborist": { + "version": "5.6.3", + "dev": true, + "license": "ISC", + "dependencies": { + "@isaacs/string-locale-compare": "^1.1.0", + "@npmcli/installed-package-contents": "^1.0.7", + "@npmcli/map-workspaces": "^2.0.3", + "@npmcli/metavuln-calculator": "^3.0.1", + "@npmcli/move-file": "^2.0.0", + "@npmcli/name-from-folder": "^1.0.1", + "@npmcli/node-gyp": "^2.0.0", + "@npmcli/package-json": "^2.0.0", + "@npmcli/query": "^1.2.0", + "@npmcli/run-script": "^4.1.3", + "bin-links": "^3.0.3", + "cacache": "^16.1.3", + "common-ancestor-path": "^1.0.1", + "hosted-git-info": "^5.2.1", + "json-parse-even-better-errors": "^2.3.1", + "json-stringify-nice": "^1.1.4", + "minimatch": "^5.1.0", + "mkdirp": "^1.0.4", + "mkdirp-infer-owner": "^2.0.0", + "nopt": "^6.0.0", + "npm-install-checks": "^5.0.0", + "npm-package-arg": "^9.0.0", + "npm-pick-manifest": "^7.0.2", + "npm-registry-fetch": "^13.0.0", + "npmlog": "^6.0.2", + "pacote": "^13.6.1", + "parse-conflict-json": "^2.0.1", + "proc-log": "^2.0.0", + "promise-all-reject-late": "^1.0.0", + "promise-call-limit": "^1.0.1", + "read-package-json-fast": "^2.0.2", + "readdir-scoped-modules": "^1.1.0", + "rimraf": "^3.0.2", + "semver": "^7.3.7", + "ssri": "^9.0.0", + "treeverse": "^2.0.0", + "walk-up-path": "^1.0.0" + }, + "bin": { + "arborist": "bin/index.js" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/@npmcli/arborist/node_modules/minimatch": { + "version": "5.1.6", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@npmcli/ci-detect": { + "version": "2.0.0", + "dev": true, + "license": "ISC", + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16" + } + }, + "node_modules/@npmcli/config": { + "version": "4.2.2", + "dev": true, + "license": "ISC", + "dependencies": { + "@npmcli/map-workspaces": "^2.0.2", + "ini": "^3.0.0", + "mkdirp-infer-owner": "^2.0.0", + "nopt": "^6.0.0", + "proc-log": "^2.0.0", + "read-package-json-fast": "^2.0.3", + "semver": "^7.3.5", + "walk-up-path": "^1.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/@npmcli/config/node_modules/ini": { + "version": "3.0.1", + "dev": true, + "license": "ISC", + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/@npmcli/disparity-colors": { + "version": "2.0.0", + "dev": true, + "license": "ISC", + "dependencies": { + "ansi-styles": "^4.3.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/@npmcli/fs": { + "version": "2.1.2", + "dev": true, + "license": "ISC", + "dependencies": { + "@gar/promisify": "^1.1.3", + "semver": "^7.3.5" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/@npmcli/git": { + "version": "3.0.2", + "dev": true, + "license": "ISC", + "dependencies": { + "@npmcli/promise-spawn": "^3.0.0", + "lru-cache": "^7.4.4", + "mkdirp": "^1.0.4", + "npm-pick-manifest": "^7.0.0", + "proc-log": "^2.0.0", + "promise-inflight": "^1.0.1", + "promise-retry": "^2.0.1", + "semver": "^7.3.5", + "which": "^2.0.2" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/@npmcli/installed-package-contents": { + "version": "1.0.7", + "dev": true, + "license": "ISC", + "dependencies": { + "npm-bundled": "^1.1.1", + "npm-normalize-package-bin": "^1.0.1" + }, + "bin": { + "installed-package-contents": "index.js" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/@npmcli/installed-package-contents/node_modules/npm-normalize-package-bin": { + "version": "1.0.1", + "dev": true, + "license": "ISC" + }, + "node_modules/@npmcli/map-workspaces": { + "version": "2.0.4", + "dev": true, + "license": "ISC", + "dependencies": { + "@npmcli/name-from-folder": "^1.0.1", + "glob": "^8.0.1", + "minimatch": "^5.0.1", + "read-package-json-fast": "^2.0.3" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/@npmcli/map-workspaces/node_modules/glob": { + "version": "8.1.0", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@npmcli/map-workspaces/node_modules/minimatch": { + "version": "5.1.6", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@npmcli/metavuln-calculator": { + "version": "3.1.1", + "dev": true, + "license": "ISC", + "dependencies": { + "cacache": "^16.0.0", + "json-parse-even-better-errors": "^2.3.1", + "pacote": "^13.0.3", + "semver": "^7.3.5" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/@npmcli/move-file": { + "version": "2.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "mkdirp": "^1.0.4", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/@npmcli/name-from-folder": { + "version": "1.0.1", + "dev": true, + "license": "ISC" + }, + "node_modules/@npmcli/node-gyp": { + "version": "2.0.0", + "dev": true, + "license": "ISC", + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/@npmcli/package-json": { + "version": "2.0.0", + "dev": true, + "license": "ISC", + "dependencies": { + "json-parse-even-better-errors": "^2.3.1" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/@npmcli/promise-spawn": { + "version": "3.0.0", + "dev": true, + "license": "ISC", + "dependencies": { + "infer-owner": "^1.0.4" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/@npmcli/query": { + "version": "1.2.0", + "dev": true, + "license": "ISC", + "dependencies": { + "npm-package-arg": "^9.1.0", + "postcss-selector-parser": "^6.0.10", + "semver": "^7.3.7" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/@npmcli/run-script": { + "version": "4.2.1", + "dev": true, + "license": "ISC", + "dependencies": { + "@npmcli/node-gyp": "^2.0.0", + "@npmcli/promise-spawn": "^3.0.0", + "node-gyp": "^9.0.0", + "read-package-json-fast": "^2.0.3", + "which": "^2.0.2" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/@octokit/auth-token": { + "version": "3.0.4", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14" + } + }, + "node_modules/@octokit/core": { + "version": "4.2.4", + "dev": true, + "license": "MIT", + "dependencies": { + "@octokit/auth-token": "^3.0.0", + "@octokit/graphql": "^5.0.0", + "@octokit/request": "^6.0.0", + "@octokit/request-error": "^3.0.0", + "@octokit/types": "^9.0.0", + "before-after-hook": "^2.2.0", + "universal-user-agent": "^6.0.0" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/@octokit/endpoint": { + "version": "7.0.6", + "dev": true, + "license": "MIT", + "dependencies": { + "@octokit/types": "^9.0.0", + "is-plain-object": "^5.0.0", + "universal-user-agent": "^6.0.0" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/@octokit/graphql": { + "version": "5.0.6", + "dev": true, + "license": "MIT", + "dependencies": { + "@octokit/request": "^6.0.0", + "@octokit/types": "^9.0.0", + "universal-user-agent": "^6.0.0" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/@octokit/openapi-types": { + "version": "18.0.0", + "dev": true, + "license": "MIT" + }, + "node_modules/@octokit/plugin-paginate-rest": { + "version": "6.1.2", + "dev": true, + "license": "MIT", + "dependencies": { + "@octokit/tsconfig": "^1.0.2", + "@octokit/types": "^9.2.3" + }, + "engines": { + "node": ">= 14" + }, + "peerDependencies": { + "@octokit/core": ">=4" + } + }, + "node_modules/@octokit/plugin-retry": { + "version": "4.1.6", + "dev": true, + "license": "MIT", + "dependencies": { + "@octokit/types": "^9.0.0", + "bottleneck": "^2.15.3" + }, + "engines": { + "node": ">= 14" + }, + "peerDependencies": { + "@octokit/core": ">=3" + } + }, + "node_modules/@octokit/plugin-throttling": { + "version": "5.2.3", + "dev": true, + "license": "MIT", + "dependencies": { + "@octokit/types": "^9.0.0", + "bottleneck": "^2.15.3" + }, + "engines": { + "node": ">= 14" + }, + "peerDependencies": { + "@octokit/core": "^4.0.0" + } + }, + "node_modules/@octokit/request": { + "version": "6.2.8", + "dev": true, + "license": "MIT", + "dependencies": { + "@octokit/endpoint": "^7.0.0", + "@octokit/request-error": "^3.0.0", + "@octokit/types": "^9.0.0", + "is-plain-object": "^5.0.0", + "node-fetch": "^2.6.7", + "universal-user-agent": "^6.0.0" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/@octokit/request-error": { + "version": "3.0.3", + "dev": true, + "license": "MIT", + "dependencies": { + "@octokit/types": "^9.0.0", + "deprecation": "^2.0.0", + "once": "^1.4.0" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/@octokit/tsconfig": { + "version": "1.0.2", + "dev": true, + "license": "MIT" + }, + "node_modules/@octokit/types": { + "version": "9.3.2", + "dev": true, + "license": "MIT", + "dependencies": { + "@octokit/openapi-types": "^18.0.0" + } + }, + "node_modules/@openzeppelin/contracts": { + "version": "4.9.2", + "license": "MIT" + }, + "node_modules/@openzeppelin/contracts-upgradeable": { + "version": "4.9.2", + "license": "MIT" + }, + "node_modules/@openzeppelin/contracts-v0.7": { + "name": "@openzeppelin/contracts", + "version": "3.4.2", + "dev": true, + "license": "MIT" + }, + "node_modules/@openzeppelin/defender-base-client": { + "version": "1.46.0", + "license": "MIT", + "dependencies": { + "amazon-cognito-identity-js": "^6.0.1", + "async-retry": "^1.3.3", + "axios": "^0.21.2", + "lodash": "^4.17.19", + "node-fetch": "^2.6.0" + } + }, + "node_modules/@openzeppelin/hardhat-upgrades": { + "version": "1.28.0", + "license": "MIT", + "dependencies": { + "@openzeppelin/defender-base-client": "^1.46.0", + "@openzeppelin/platform-deploy-client": "^0.8.0", + "@openzeppelin/upgrades-core": "^1.27.0", + "chalk": "^4.1.0", + "debug": "^4.1.1", + "proper-lockfile": "^4.1.1" + }, + "bin": { + "migrate-oz-cli-project": "dist/scripts/migrate-oz-cli-project.js" + }, + "peerDependencies": { + "@nomiclabs/hardhat-ethers": "^2.0.0", + "@nomiclabs/hardhat-etherscan": "^3.1.0", + "ethers": "^5.0.5", + "hardhat": "^2.0.2" + }, + "peerDependenciesMeta": { + "@nomiclabs/harhdat-etherscan": { + "optional": true + } + } + }, + "node_modules/@openzeppelin/platform-deploy-client": { + "version": "0.8.0", + "license": "MIT", + "dependencies": { + "@ethersproject/abi": "^5.6.3", + "@openzeppelin/defender-base-client": "^1.46.0", + "axios": "^0.21.2", + "lodash": "^4.17.19", + "node-fetch": "^2.6.0" + } + }, + "node_modules/@openzeppelin/upgrades-core": { + "version": "1.27.1", + "license": "MIT", + "dependencies": { + "cbor": "^8.0.0", + "chalk": "^4.1.0", + "compare-versions": "^5.0.0", + "debug": "^4.1.1", + "ethereumjs-util": "^7.0.3", + "minimist": "^1.2.7", + "proper-lockfile": "^4.1.1", + "solidity-ast": "^0.4.15" + }, + "bin": { + "openzeppelin-upgrades-core": "dist/cli/cli.js" + } + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@pnpm/config.env-replace": { + "version": "1.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.22.0" + } + }, + "node_modules/@pnpm/network.ca-file": { + "version": "1.0.2", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "4.2.10" + }, + "engines": { + "node": ">=12.22.0" + } + }, + "node_modules/@pnpm/network.ca-file/node_modules/graceful-fs": { + "version": "4.2.10", + "dev": true, + "license": "ISC" + }, + "node_modules/@pnpm/npm-conf": { + "version": "2.2.2", + "dev": true, + "license": "MIT", + "dependencies": { + "@pnpm/config.env-replace": "^1.1.0", + "@pnpm/network.ca-file": "^1.0.1", + "config-chain": "^1.1.11" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@scure/base": { + "version": "1.1.1", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "license": "MIT" + }, + "node_modules/@scure/bip32": { + "version": "1.1.5", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "license": "MIT", + "dependencies": { + "@noble/hashes": "~1.2.0", + "@noble/secp256k1": "~1.7.0", + "@scure/base": "~1.1.0" + } + }, + "node_modules/@scure/bip39": { + "version": "1.1.1", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "license": "MIT", + "dependencies": { + "@noble/hashes": "~1.2.0", + "@scure/base": "~1.1.0" + } + }, + "node_modules/@semantic-release/changelog": { + "version": "6.0.3", + "dev": true, + "license": "MIT", + "dependencies": { + "@semantic-release/error": "^3.0.0", + "aggregate-error": "^3.0.0", + "fs-extra": "^11.0.0", + "lodash": "^4.17.4" + }, + "engines": { + "node": ">=14.17" + }, + "peerDependencies": { + "semantic-release": ">=18.0.0" + } + }, + "node_modules/@semantic-release/commit-analyzer": { + "version": "9.0.2", + "dev": true, + "license": "MIT", + "dependencies": { + "conventional-changelog-angular": "^5.0.0", + "conventional-commits-filter": "^2.0.0", + "conventional-commits-parser": "^3.2.3", + "debug": "^4.0.0", + "import-from": "^4.0.0", + "lodash": "^4.17.4", + "micromatch": "^4.0.2" + }, + "engines": { + "node": ">=14.17" + }, + "peerDependencies": { + "semantic-release": ">=18.0.0-beta.1" + } + }, + "node_modules/@semantic-release/error": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.17" + } + }, + "node_modules/@semantic-release/git": { + "version": "10.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@semantic-release/error": "^3.0.0", + "aggregate-error": "^3.0.0", + "debug": "^4.0.0", + "dir-glob": "^3.0.0", + "execa": "^5.0.0", + "lodash": "^4.17.4", + "micromatch": "^4.0.0", + "p-reduce": "^2.0.0" + }, + "engines": { + "node": ">=14.17" + }, + "peerDependencies": { + "semantic-release": ">=18.0.0" + } + }, + "node_modules/@semantic-release/github": { + "version": "8.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@octokit/core": "^4.2.1", + "@octokit/plugin-paginate-rest": "^6.1.2", + "@octokit/plugin-retry": "^4.1.3", + "@octokit/plugin-throttling": "^5.2.3", + "@semantic-release/error": "^3.0.0", + "aggregate-error": "^3.0.0", + "debug": "^4.0.0", + "dir-glob": "^3.0.0", + "fs-extra": "^11.0.0", + "globby": "^11.0.0", + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.0", + "issue-parser": "^6.0.0", + "lodash": "^4.17.4", + "mime": "^3.0.0", + "p-filter": "^2.0.0", + "url-join": "^4.0.0" + }, + "engines": { + "node": ">=14.17" + }, + "peerDependencies": { + "semantic-release": ">=18.0.0-beta.1" + } + }, + "node_modules/@semantic-release/github/node_modules/agent-base": { + "version": "7.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/@semantic-release/github/node_modules/http-proxy-agent": { + "version": "7.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/@semantic-release/github/node_modules/https-proxy-agent": { + "version": "7.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.0.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/@semantic-release/npm": { + "version": "9.0.2", + "dev": true, + "license": "MIT", + "dependencies": { + "@semantic-release/error": "^3.0.0", + "aggregate-error": "^3.0.0", + "execa": "^5.0.0", + "fs-extra": "^11.0.0", + "lodash": "^4.17.15", + "nerf-dart": "^1.0.0", + "normalize-url": "^6.0.0", + "npm": "^8.3.0", + "rc": "^1.2.8", + "read-pkg": "^5.0.0", + "registry-auth-token": "^5.0.0", + "semver": "^7.1.2", + "tempy": "^1.0.0" + }, + "engines": { + "node": ">=16 || ^14.17" + }, + "peerDependencies": { + "semantic-release": ">=19.0.0" + } + }, + "node_modules/@semantic-release/release-notes-generator": { + "version": "10.0.3", + "dev": true, + "license": "MIT", + "dependencies": { + "conventional-changelog-angular": "^5.0.0", + "conventional-changelog-writer": "^5.0.0", + "conventional-commits-filter": "^2.0.0", + "conventional-commits-parser": "^3.2.3", + "debug": "^4.0.0", + "get-stream": "^6.0.0", + "import-from": "^4.0.0", + "into-stream": "^6.0.0", + "lodash": "^4.17.4", + "read-pkg-up": "^7.0.0" + }, + "engines": { + "node": ">=14.17" + }, + "peerDependencies": { + "semantic-release": ">=18.0.0-beta.1" + } + }, + "node_modules/@sentry/core": { + "version": "5.30.0", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@sentry/hub": "5.30.0", + "@sentry/minimal": "5.30.0", + "@sentry/types": "5.30.0", + "@sentry/utils": "5.30.0", + "tslib": "^1.9.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@sentry/hub": { + "version": "5.30.0", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@sentry/types": "5.30.0", + "@sentry/utils": "5.30.0", + "tslib": "^1.9.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@sentry/minimal": { + "version": "5.30.0", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@sentry/hub": "5.30.0", + "@sentry/types": "5.30.0", + "tslib": "^1.9.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@sentry/node": { + "version": "5.30.0", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@sentry/core": "5.30.0", + "@sentry/hub": "5.30.0", + "@sentry/tracing": "5.30.0", + "@sentry/types": "5.30.0", + "@sentry/utils": "5.30.0", + "cookie": "^0.4.1", + "https-proxy-agent": "^5.0.0", + "lru_map": "^0.3.3", + "tslib": "^1.9.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@sentry/tracing": { + "version": "5.30.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@sentry/hub": "5.30.0", + "@sentry/minimal": "5.30.0", + "@sentry/types": "5.30.0", + "@sentry/utils": "5.30.0", + "tslib": "^1.9.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@sentry/types": { + "version": "5.30.0", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=6" + } + }, + "node_modules/@sentry/utils": { + "version": "5.30.0", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@sentry/types": "5.30.0", + "tslib": "^1.9.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@solidity-parser/parser": { + "version": "0.13.2", + "license": "MIT", + "dependencies": { + "antlr4ts": "^0.5.0-alpha.4" + } + }, + "node_modules/@tootallnate/once": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10" + } + }, + "node_modules/@trivago/prettier-plugin-sort-imports": { + "version": "3.4.0", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@babel/core": "7.17.8", + "@babel/generator": "7.17.7", + "@babel/parser": "7.18.9", + "@babel/traverse": "7.17.3", + "@babel/types": "7.17.0", + "@vue/compiler-sfc": "^3.2.40", + "javascript-natural-sort": "0.7.1", + "lodash": "4.17.21" + }, + "peerDependencies": { + "prettier": "2.x" + } + }, + "node_modules/@trivago/prettier-plugin-sort-imports/node_modules/@babel/generator": { + "version": "7.17.7", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.17.0", + "jsesc": "^2.5.1", + "source-map": "^0.5.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@trivago/prettier-plugin-sort-imports/node_modules/@babel/generator/node_modules/@babel/types": { + "version": "7.22.5", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.5", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@trivago/prettier-plugin-sort-imports/node_modules/@babel/parser": { + "version": "7.18.9", + "dev": true, + "license": "MIT", + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@trivago/prettier-plugin-sort-imports/node_modules/@babel/traverse": { + "version": "7.17.3", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.16.7", + "@babel/generator": "^7.17.3", + "@babel/helper-environment-visitor": "^7.16.7", + "@babel/helper-function-name": "^7.16.7", + "@babel/helper-hoist-variables": "^7.16.7", + "@babel/helper-split-export-declaration": "^7.16.7", + "@babel/parser": "^7.17.3", + "@babel/types": "^7.17.0", + "debug": "^4.1.0", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@trivago/prettier-plugin-sort-imports/node_modules/@babel/traverse/node_modules/@babel/generator": { + "version": "7.22.7", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.22.5", + "@jridgewell/gen-mapping": "^0.3.2", + "@jridgewell/trace-mapping": "^0.3.17", + "jsesc": "^2.5.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@trivago/prettier-plugin-sort-imports/node_modules/@babel/traverse/node_modules/@babel/parser": { + "version": "7.22.7", + "dev": true, + "license": "MIT", + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@trivago/prettier-plugin-sort-imports/node_modules/@babel/traverse/node_modules/@babel/types": { + "version": "7.22.5", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.5", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@trivago/prettier-plugin-sort-imports/node_modules/@babel/types": { + "version": "7.17.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.16.7", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@trivago/prettier-plugin-sort-imports/node_modules/globals": { + "version": "11.12.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/@trivago/prettier-plugin-sort-imports/node_modules/source-map": { + "version": "0.5.7", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@tsconfig/node10": { + "version": "1.0.9", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node12": { + "version": "1.0.11", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node14": { + "version": "1.0.3", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.4", + "dev": true, + "license": "MIT" + }, + "node_modules/@typechain/ethers-v5": { + "version": "7.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "lodash": "^4.17.15", + "ts-essentials": "^7.0.1" + }, + "peerDependencies": { + "@ethersproject/abi": "^5.0.0", + "@ethersproject/bytes": "^5.0.0", + "@ethersproject/providers": "^5.0.0", + "ethers": "^5.1.3", + "typechain": "^5.0.0", + "typescript": ">=4.0.0" + } + }, + "node_modules/@typechain/hardhat": { + "version": "2.3.1", + "dev": true, + "license": "MIT", + "dependencies": { + "fs-extra": "^9.1.0" + }, + "peerDependencies": { + "hardhat": "^2.0.10", + "lodash": "^4.17.15", + "typechain": "^5.1.2" + } + }, + "node_modules/@typechain/hardhat/node_modules/fs-extra": { + "version": "9.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@types/async-eventemitter": { + "version": "0.2.1", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/bn.js": { + "version": "5.1.1", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/bn.js/node_modules/@types/node": { + "version": "20.4.1", + "license": "MIT" + }, + "node_modules/@types/chai": { + "version": "4.3.5", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/chai-as-promised": { + "version": "7.1.5", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/chai": "*" + } + }, + "node_modules/@types/concat-stream": { + "version": "1.6.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/concat-stream/node_modules/@types/node": { + "version": "20.4.1", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/form-data": { + "version": "0.0.33", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/form-data/node_modules/@types/node": { + "version": "20.4.1", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/glob": { + "version": "7.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/minimatch": "*", + "@types/node": "*" + } + }, + "node_modules/@types/glob/node_modules/@types/node": { + "version": "20.4.1", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/json-schema": { + "version": "7.0.12", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/json5": { + "version": "0.0.29", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/lru-cache": { + "version": "5.1.1", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/minimatch": { + "version": "5.1.2", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/minimist": { + "version": "1.2.2", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/mocha": { + "version": "9.1.1", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "12.20.55", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/normalize-package-data": { + "version": "2.4.1", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/parse-json": { + "version": "4.0.0", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/pbkdf2": { + "version": "3.1.0", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/pbkdf2/node_modules/@types/node": { + "version": "20.4.1", + "license": "MIT" + }, + "node_modules/@types/prettier": { + "version": "2.7.3", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/qs": { + "version": "6.9.7", + "license": "MIT" + }, + "node_modules/@types/readable-stream": { + "version": "2.3.15", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "safe-buffer": "~5.1.1" + } + }, + "node_modules/@types/readable-stream/node_modules/@types/node": { + "version": "20.4.1", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/readable-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/secp256k1": { + "version": "4.0.3", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/secp256k1/node_modules/@types/node": { + "version": "20.4.1", + "license": "MIT" + }, + "node_modules/@types/semver": { + "version": "7.5.0", + "dev": true, + "license": "MIT" + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "5.61.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/regexpp": "^4.4.0", + "@typescript-eslint/scope-manager": "5.61.0", + "@typescript-eslint/type-utils": "5.61.0", + "@typescript-eslint/utils": "5.61.0", + "debug": "^4.3.4", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "natural-compare-lite": "^1.4.0", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^5.0.0", + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "5.61.0", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "@typescript-eslint/scope-manager": "5.61.0", + "@typescript-eslint/types": "5.61.0", + "@typescript-eslint/typescript-estree": "5.61.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "5.61.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "5.61.0", + "@typescript-eslint/visitor-keys": "5.61.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "5.61.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/typescript-estree": "5.61.0", + "@typescript-eslint/utils": "5.61.0", + "debug": "^4.3.4", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/types": { + "version": "5.61.0", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "5.61.0", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "@typescript-eslint/types": "5.61.0", + "@typescript-eslint/visitor-keys": "5.61.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "5.61.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@types/json-schema": "^7.0.9", + "@types/semver": "^7.3.12", + "@typescript-eslint/scope-manager": "5.61.0", + "@typescript-eslint/types": "5.61.0", + "@typescript-eslint/typescript-estree": "5.61.0", + "eslint-scope": "^5.1.1", + "semver": "^7.3.7" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "5.61.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "5.61.0", + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { + "version": "3.4.1", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@venusprotocol/governance-contracts": { + "version": "1.0.0", + "dev": true + }, + "node_modules/@venusprotocol/isolated-pools": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@venusprotocol/isolated-pools/-/isolated-pools-1.3.0.tgz", + "integrity": "sha512-w395lfpuZkRHKlL6eFrlFlCTzz9cTvcvLMDj4d+7Jk1KGcEEy2ByEMVtlnFks2srERyQnpMAXxih1yHuO49eHg==", + "dependencies": { + "@openzeppelin/contracts": "^4.8.3", + "@openzeppelin/contracts-upgradeable": "^4.8.3", + "@openzeppelin/hardhat-upgrades": "^1.21.0", + "@solidity-parser/parser": "^0.13.2", + "ethers": "^5.7.0", + "hardhat-deploy": "^0.11.14", + "module-alias": "^2.2.2" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@venusprotocol/oracle": { + "version": "1.7.2", + "dev": true, + "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/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" + }, + "engines": { + "node": ">=18.x.x" + } + }, + "node_modules/@venusprotocol/oracle/node_modules/@venusprotocol/governance-contracts": { + "version": "0.0.2", + "dev": true + }, + "node_modules/@venusprotocol/oracle/node_modules/@venusprotocol/venus-protocol": { + "version": "0.7.0", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@openzeppelin/contracts-upgradeable": "^4.8.0", + "dotenv": "^16.0.1" + }, + "peerDependencies": { + "hardhat": "^2.10.1" + } + }, + "node_modules/@venusprotocol/oracle/node_modules/dotenv": { + "version": "16.3.1", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/motdotla/dotenv?sponsor=1" + } + }, + "node_modules/@venusprotocol/protocol-reserve": { + "version": "1.0.0-dev.6", + "resolved": "https://registry.npmjs.org/@venusprotocol/protocol-reserve/-/protocol-reserve-1.0.0-dev.6.tgz", + "integrity": "sha512-ji7IDPpeW3bH2Cy0bRzoNPDONRzgTEi8vxVhOl9W5Aqsd2/gOgYBRVhvMAUHOoY1c3sW8jUpaLA9tK8jvs87Og==", + "dependencies": { + "@venusprotocol/isolated-pools": "^1.3.0" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@venusprotocol/venus-protocol": { + "version": "3.0.0-dev.18", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@openzeppelin/contracts": "^4.8.3", + "@openzeppelin/contracts-upgradeable": "^4.8.0", + "dotenv": "^16.0.1", + "module-alias": "^2.2.2" + }, + "engines": { + "node": ">=18.x.x" + }, + "peerDependencies": { + "hardhat": "^2.10.1" + } + }, + "node_modules/@venusprotocol/venus-protocol/node_modules/dotenv": { + "version": "16.3.1", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/motdotla/dotenv?sponsor=1" + } + }, + "node_modules/@vue/compiler-core": { + "version": "3.3.4", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.21.3", + "@vue/shared": "3.3.4", + "estree-walker": "^2.0.2", + "source-map-js": "^1.0.2" + } + }, + "node_modules/@vue/compiler-dom": { + "version": "3.3.4", + "dev": true, + "license": "MIT", + "dependencies": { + "@vue/compiler-core": "3.3.4", + "@vue/shared": "3.3.4" + } + }, + "node_modules/@vue/compiler-sfc": { + "version": "3.3.4", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.20.15", + "@vue/compiler-core": "3.3.4", + "@vue/compiler-dom": "3.3.4", + "@vue/compiler-ssr": "3.3.4", + "@vue/reactivity-transform": "3.3.4", + "@vue/shared": "3.3.4", + "estree-walker": "^2.0.2", + "magic-string": "^0.30.0", + "postcss": "^8.1.10", + "source-map-js": "^1.0.2" + } + }, + "node_modules/@vue/compiler-ssr": { + "version": "3.3.4", + "dev": true, + "license": "MIT", + "dependencies": { + "@vue/compiler-dom": "3.3.4", + "@vue/shared": "3.3.4" + } + }, + "node_modules/@vue/reactivity-transform": { + "version": "3.3.4", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.20.15", + "@vue/compiler-core": "3.3.4", + "@vue/shared": "3.3.4", + "estree-walker": "^2.0.2", + "magic-string": "^0.30.0" + } + }, + "node_modules/@vue/shared": { + "version": "3.3.4", + "dev": true, + "license": "MIT" + }, + "node_modules/abbrev": { + "version": "1.1.1", + "dev": true, + "license": "ISC" + }, + "node_modules/abort-controller": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "event-target-shim": "^5.0.0" + }, + "engines": { + "node": ">=6.5" + } + }, + "node_modules/abstract-level": { + "version": "1.0.3", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer": "^6.0.3", + "catering": "^2.1.0", + "is-buffer": "^2.0.5", + "level-supports": "^4.0.0", + "level-transcoder": "^1.0.1", + "module-error": "^1.0.1", + "queue-microtask": "^1.2.3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/acorn": { + "version": "7.4.1", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "dev": true, + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.2.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/address": { + "version": "1.2.2", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/adm-zip": { + "version": "0.4.16", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.3.0" + } + }, + "node_modules/aes-js": { + "version": "3.0.0", + "license": "MIT" + }, + "node_modules/agent-base": { + "version": "6.0.2", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/agentkeepalive": { + "version": "4.3.0", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.1.0", + "depd": "^2.0.0", + "humanize-ms": "^1.2.1" + }, + "engines": { + "node": ">= 8.0.0" + } + }, + "node_modules/aggregate-error": { + "version": "3.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv/node_modules/json-schema-traverse": { + "version": "0.4.1", + "dev": true, + "license": "MIT" + }, + "node_modules/amazon-cognito-identity-js": { + "version": "6.3.1", + "license": "Apache-2.0", + "dependencies": { + "@aws-crypto/sha256-js": "1.2.2", + "buffer": "4.9.2", + "fast-base64-decode": "^1.0.0", + "isomorphic-unfetch": "^3.0.0", + "js-cookie": "^2.2.1" + } + }, + "node_modules/amazon-cognito-identity-js/node_modules/buffer": { + "version": "4.9.2", + "license": "MIT", + "dependencies": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4", + "isarray": "^1.0.0" + } + }, + "node_modules/amdefine": { + "version": "1.0.1", + "dev": true, + "license": "BSD-3-Clause OR MIT", + "optional": true, + "engines": { + "node": ">=0.4.2" + } + }, + "node_modules/ansi-colors": { + "version": "3.2.3", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/ansi-escapes": { + "version": "4.3.2", + "dev": true, + "license": "MIT", + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-escapes/node_modules/type-fest": { + "version": "0.21.3", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/ansicolors": { + "version": "0.3.2", + "dev": true, + "license": "MIT" + }, + "node_modules/antlr4": { + "version": "4.13.0", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=16" + } + }, + "node_modules/antlr4ts": { + "version": "0.5.0-dev", + "license": "BSD-3-Clause", + "dependencies": { + "source-map-support": "^0.5.16" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "license": "ISC", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/aproba": { + "version": "2.0.0", + "dev": true, + "license": "ISC" + }, + "node_modules/archy": { + "version": "1.0.0", + "dev": true, + "license": "MIT" + }, + "node_modules/are-we-there-yet": { + "version": "3.0.1", + "dev": true, + "license": "ISC", + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/arg": { + "version": "4.1.3", + "dev": true, + "license": "MIT" + }, + "node_modules/argparse": { + "version": "1.0.10", + "dev": true, + "license": "MIT", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/argv-formatter": { + "version": "1.0.0", + "dev": true, + "license": "MIT" + }, + "node_modules/array-back": { + "version": "1.0.4", + "dev": true, + "license": "MIT", + "dependencies": { + "typical": "^2.6.0" + }, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "is-array-buffer": "^3.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-ify": { + "version": "1.0.0", + "dev": true, + "license": "MIT" + }, + "node_modules/array-includes": { + "version": "3.1.6", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", + "get-intrinsic": "^1.1.3", + "is-string": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-union": { + "version": "2.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/array-uniq": { + "version": "1.0.3", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/array.prototype.flat": { + "version": "1.3.1", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", + "es-shim-unscopables": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flatmap": { + "version": "1.3.1", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", + "es-shim-unscopables": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.reduce": { + "version": "1.0.5", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4", + "es-array-method-boxes-properly": "^1.0.0", + "is-string": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/arrify": { + "version": "1.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/asap": { + "version": "2.0.6", + "dev": true, + "license": "MIT" + }, + "node_modules/asn1": { + "version": "0.2.6", + "dev": true, + "license": "MIT", + "dependencies": { + "safer-buffer": "~2.1.0" + } + }, + "node_modules/assert-plus": { + "version": "1.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/assertion-error": { + "version": "1.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/ast-parents": { + "version": "0.0.1", + "dev": true, + "license": "MIT" + }, + "node_modules/astral-regex": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/async": { + "version": "2.6.4", + "dev": true, + "license": "MIT", + "dependencies": { + "lodash": "^4.17.14" + } + }, + "node_modules/async-eventemitter": { + "version": "0.2.4", + "dev": true, + "license": "MIT", + "dependencies": { + "async": "^2.4.0" + } + }, + "node_modules/async-retry": { + "version": "1.3.3", + "license": "MIT", + "dependencies": { + "retry": "0.13.1" + } + }, + "node_modules/async-retry/node_modules/retry": { + "version": "0.13.1", + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "license": "MIT" + }, + "node_modules/at-least-node": { + "version": "1.0.0", + "dev": true, + "license": "ISC", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/available-typed-arrays": { + "version": "1.0.5", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/aws-sign2": { + "version": "0.7.0", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "*" + } + }, + "node_modules/aws4": { + "version": "1.12.0", + "dev": true, + "license": "MIT" + }, + "node_modules/axios": { + "version": "0.21.4", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.14.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "dev": true, + "license": "MIT" + }, + "node_modules/base-x": { + "version": "3.0.9", + "license": "MIT", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, + "node_modules/base64-js": { + "version": "1.5.1", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/bcrypt-pbkdf": { + "version": "1.0.2", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "tweetnacl": "^0.14.3" + } + }, + "node_modules/bech32": { + "version": "1.1.4", + "license": "MIT" + }, + "node_modules/before-after-hook": { + "version": "2.2.3", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/bigint-crypto-utils": { + "version": "3.3.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/bignumber.js": { + "version": "9.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/bin-links": { + "version": "3.0.3", + "dev": true, + "license": "ISC", + "dependencies": { + "cmd-shim": "^5.0.0", + "mkdirp-infer-owner": "^2.0.0", + "npm-normalize-package-bin": "^2.0.0", + "read-cmd-shim": "^3.0.0", + "rimraf": "^3.0.0", + "write-file-atomic": "^4.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/binary-extensions": { + "version": "2.2.0", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/blakejs": { + "version": "1.2.1", + "license": "MIT" + }, + "node_modules/bn.js": { + "version": "5.2.1", + "license": "MIT" + }, + "node_modules/bottleneck": { + "version": "2.19.5", + "dev": true, + "license": "MIT" + }, + "node_modules/brace-expansion": { + "version": "2.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "license": "MIT", + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/brorand": { + "version": "1.1.0", + "license": "MIT" + }, + "node_modules/browser-level": { + "version": "1.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "abstract-level": "^1.0.2", + "catering": "^2.1.1", + "module-error": "^1.0.2", + "run-parallel-limit": "^1.1.0" + } + }, + "node_modules/browser-stdout": { + "version": "1.3.1", + "dev": true, + "license": "ISC" + }, + "node_modules/browserify-aes": { + "version": "1.2.0", + "license": "MIT", + "dependencies": { + "buffer-xor": "^1.0.3", + "cipher-base": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.3", + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/browserslist": { + "version": "4.21.9", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "caniuse-lite": "^1.0.30001503", + "electron-to-chromium": "^1.4.431", + "node-releases": "^2.0.12", + "update-browserslist-db": "^1.0.11" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/bs58": { + "version": "4.0.1", + "license": "MIT", + "dependencies": { + "base-x": "^3.0.2" + } + }, + "node_modules/bs58check": { + "version": "2.1.2", + "license": "MIT", + "dependencies": { + "bs58": "^4.0.0", + "create-hash": "^1.1.0", + "safe-buffer": "^5.1.2" + } + }, + "node_modules/buffer": { + "version": "6.0.3", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "license": "MIT" + }, + "node_modules/buffer-xor": { + "version": "1.0.3", + "license": "MIT" + }, + "node_modules/bufio": { + "version": "1.2.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/builtins": { + "version": "5.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^7.0.0" + } + }, + "node_modules/busboy": { + "version": "1.6.0", + "dev": true, + "dependencies": { + "streamsearch": "^1.1.0" + }, + "engines": { + "node": ">=10.16.0" + } + }, + "node_modules/bytes": { + "version": "3.1.2", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/cacache": { + "version": "16.1.3", + "dev": true, + "license": "ISC", + "dependencies": { + "@npmcli/fs": "^2.1.0", + "@npmcli/move-file": "^2.0.0", + "chownr": "^2.0.0", + "fs-minipass": "^2.1.0", + "glob": "^8.0.1", + "infer-owner": "^1.0.4", + "lru-cache": "^7.7.1", + "minipass": "^3.1.6", + "minipass-collect": "^1.0.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "mkdirp": "^1.0.4", + "p-map": "^4.0.0", + "promise-inflight": "^1.0.1", + "rimraf": "^3.0.2", + "ssri": "^9.0.0", + "tar": "^6.1.11", + "unique-filename": "^2.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/cacache/node_modules/glob": { + "version": "8.1.0", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/cacache/node_modules/minimatch": { + "version": "5.1.6", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/cacache/node_modules/unique-filename": { + "version": "2.0.1", + "dev": true, + "license": "ISC", + "dependencies": { + "unique-slug": "^3.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/cacache/node_modules/unique-slug": { + "version": "3.0.0", + "dev": true, + "license": "ISC", + "dependencies": { + "imurmurhash": "^0.1.4" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/call-bind": { + "version": "1.0.2", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase": { + "version": "5.3.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase-keys": { + "version": "6.2.2", + "dev": true, + "license": "MIT", + "dependencies": { + "camelcase": "^5.3.1", + "map-obj": "^4.0.0", + "quick-lru": "^4.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001514", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/cardinal": { + "version": "2.1.1", + "dev": true, + "license": "MIT", + "dependencies": { + "ansicolors": "~0.3.2", + "redeyed": "~2.1.0" + }, + "bin": { + "cdl": "bin/cdl.js" + } + }, + "node_modules/case": { + "version": "1.6.3", + "dev": true, + "license": "(MIT OR GPL-3.0-or-later)", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/caseless": { + "version": "0.12.0", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/catering": { + "version": "2.1.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/cbor": { + "version": "8.1.0", + "license": "MIT", + "dependencies": { + "nofilter": "^3.1.0" + }, + "engines": { + "node": ">=12.19" + } + }, + "node_modules/chai": { + "version": "4.3.7", + "dev": true, + "license": "MIT", + "dependencies": { + "assertion-error": "^1.1.0", + "check-error": "^1.0.2", + "deep-eql": "^4.1.2", + "get-func-name": "^2.0.0", + "loupe": "^2.3.1", + "pathval": "^1.1.1", + "type-detect": "^4.0.5" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/chai-as-promised": { + "version": "7.1.1", + "dev": true, + "license": "WTFPL", + "dependencies": { + "check-error": "^1.0.2" + }, + "peerDependencies": { + "chai": ">= 2.1.2 < 5" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chalk/node_modules/supports-color": { + "version": "7.2.0", + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/charenc": { + "version": "0.0.2", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": "*" + } + }, + "node_modules/check-error": { + "version": "1.0.2", + "dev": true, + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/chokidar": { + "version": "3.5.3", + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "license": "MIT", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chownr": { + "version": "2.0.0", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/ci-info": { + "version": "2.0.0", + "dev": true, + "license": "MIT" + }, + "node_modules/cidr-regex": { + "version": "3.1.1", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "ip-regex": "^4.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/cipher-base": { + "version": "1.0.4", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/classic-level": { + "version": "1.3.0", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "abstract-level": "^1.0.2", + "catering": "^2.1.0", + "module-error": "^1.0.1", + "napi-macros": "^2.2.2", + "node-gyp-build": "^4.3.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/clean-stack": { + "version": "2.2.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/cli-columns": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/cli-table3": { + "version": "0.6.3", + "dev": true, + "license": "MIT", + "dependencies": { + "string-width": "^4.2.0" + }, + "engines": { + "node": "10.* || >= 12.*" + }, + "optionalDependencies": { + "@colors/colors": "1.5.0" + } + }, + "node_modules/cliui": { + "version": "8.0.1", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/clone": { + "version": "1.0.4", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/cmd-shim": { + "version": "5.0.0", + "dev": true, + "license": "ISC", + "dependencies": { + "mkdirp-infer-owner": "^2.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/code-point-at": { + "version": "1.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "license": "MIT" + }, + "node_modules/color-support": { + "version": "1.1.3", + "dev": true, + "license": "ISC", + "bin": { + "color-support": "bin.js" + } + }, + "node_modules/colors": { + "version": "1.4.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.1.90" + } + }, + "node_modules/columnify": { + "version": "1.6.0", + "dev": true, + "license": "MIT", + "dependencies": { + "strip-ansi": "^6.0.1", + "wcwidth": "^1.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/command-exists": { + "version": "1.2.9", + "dev": true, + "license": "MIT" + }, + "node_modules/command-line-args": { + "version": "4.0.7", + "dev": true, + "license": "MIT", + "dependencies": { + "array-back": "^2.0.0", + "find-replace": "^1.0.3", + "typical": "^2.6.1" + }, + "bin": { + "command-line-args": "bin/cli.js" + } + }, + "node_modules/command-line-args/node_modules/array-back": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "typical": "^2.6.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/commander": { + "version": "3.0.2", + "dev": true, + "license": "MIT" + }, + "node_modules/common-ancestor-path": { + "version": "1.0.1", + "dev": true, + "license": "ISC" + }, + "node_modules/compare-func": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "array-ify": "^1.0.0", + "dot-prop": "^5.1.0" + } + }, + "node_modules/compare-versions": { + "version": "5.0.3", + "license": "MIT" + }, + "node_modules/concat-map": { + "version": "0.0.1", + "dev": true, + "license": "MIT" + }, + "node_modules/concat-stream": { + "version": "1.6.2", + "dev": true, + "engines": [ + "node >= 0.8" + ], + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "node_modules/concat-stream/node_modules/readable-stream": { + "version": "2.3.8", + "dev": true, + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/concat-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "dev": true, + "license": "MIT" + }, + "node_modules/concat-stream/node_modules/string_decoder": { + "version": "1.1.1", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/config-chain": { + "version": "1.1.13", + "dev": true, + "license": "MIT", + "dependencies": { + "ini": "^1.3.4", + "proto-list": "~1.2.1" + } + }, + "node_modules/console-control-strings": { + "version": "1.1.0", + "dev": true, + "license": "ISC" + }, + "node_modules/conventional-changelog-angular": { + "version": "5.0.13", + "dev": true, + "license": "ISC", + "dependencies": { + "compare-func": "^2.0.0", + "q": "^1.5.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/conventional-changelog-conventionalcommits": { + "version": "5.0.0", + "dev": true, + "license": "ISC", + "dependencies": { + "compare-func": "^2.0.0", + "lodash": "^4.17.15", + "q": "^1.5.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/conventional-changelog-writer": { + "version": "5.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "conventional-commits-filter": "^2.0.7", + "dateformat": "^3.0.0", + "handlebars": "^4.7.7", + "json-stringify-safe": "^5.0.1", + "lodash": "^4.17.15", + "meow": "^8.0.0", + "semver": "^6.0.0", + "split": "^1.0.0", + "through2": "^4.0.0" + }, + "bin": { + "conventional-changelog-writer": "cli.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/conventional-changelog-writer/node_modules/semver": { + "version": "6.3.0", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/conventional-commits-filter": { + "version": "2.0.7", + "dev": true, + "license": "MIT", + "dependencies": { + "lodash.ismatch": "^4.4.0", + "modify-values": "^1.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/conventional-commits-parser": { + "version": "3.2.4", + "dev": true, + "license": "MIT", + "dependencies": { + "is-text-path": "^1.0.1", + "JSONStream": "^1.0.4", + "lodash": "^4.17.15", + "meow": "^8.0.0", + "split2": "^3.0.0", + "through2": "^4.0.0" + }, + "bin": { + "conventional-commits-parser": "cli.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/convert-source-map": { + "version": "1.9.0", + "dev": true, + "license": "MIT" + }, + "node_modules/cookie": { + "version": "0.4.2", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/core-util-is": { + "version": "1.0.3", + "dev": true, + "license": "MIT" + }, + "node_modules/cosmiconfig": { + "version": "8.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "parse-json": "^5.0.0", + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + } + }, + "node_modules/crc-32": { + "version": "1.2.2", + "dev": true, + "license": "Apache-2.0", + "bin": { + "crc32": "bin/crc32.njs" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/create-hash": { + "version": "1.2.0", + "license": "MIT", + "dependencies": { + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "md5.js": "^1.3.4", + "ripemd160": "^2.0.1", + "sha.js": "^2.4.0" + } + }, + "node_modules/create-hmac": { + "version": "1.1.7", + "license": "MIT", + "dependencies": { + "cipher-base": "^1.0.3", + "create-hash": "^1.1.0", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "node_modules/create-require": { + "version": "1.1.1", + "dev": true, + "license": "MIT" + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/crypt": { + "version": "0.0.2", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": "*" + } + }, + "node_modules/crypto-random-string": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/cssesc": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/dargs": { + "version": "7.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/dashdash": { + "version": "1.14.1", + "dev": true, + "license": "MIT", + "dependencies": { + "assert-plus": "^1.0.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/dateformat": { + "version": "3.0.3", + "dev": true, + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/death": { + "version": "1.1.0", + "dev": true + }, + "node_modules/debug": { + "version": "4.3.4", + "license": "MIT", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/debug/node_modules/ms": { + "version": "2.1.2", + "license": "MIT" + }, + "node_modules/debuglog": { + "version": "1.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/decamelize": { + "version": "1.2.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/decamelize-keys": { + "version": "1.1.1", + "dev": true, + "license": "MIT", + "dependencies": { + "decamelize": "^1.1.0", + "map-obj": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/decamelize-keys/node_modules/map-obj": { + "version": "1.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/deep-eql": { + "version": "4.1.3", + "dev": true, + "license": "MIT", + "dependencies": { + "type-detect": "^4.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "dev": true, + "license": "MIT" + }, + "node_modules/defaults": { + "version": "1.0.4", + "dev": true, + "license": "MIT", + "dependencies": { + "clone": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/define-properties": { + "version": "1.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/del": { + "version": "6.1.1", + "dev": true, + "license": "MIT", + "dependencies": { + "globby": "^11.0.1", + "graceful-fs": "^4.2.4", + "is-glob": "^4.0.1", + "is-path-cwd": "^2.2.0", + "is-path-inside": "^3.0.2", + "p-map": "^4.0.0", + "rimraf": "^3.0.2", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/delegates": { + "version": "1.0.0", + "dev": true, + "license": "MIT" + }, + "node_modules/depd": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/deprecation": { + "version": "2.3.1", + "dev": true, + "license": "ISC" + }, + "node_modules/detect-port": { + "version": "1.5.1", + "dev": true, + "license": "MIT", + "dependencies": { + "address": "^1.0.1", + "debug": "4" + }, + "bin": { + "detect": "bin/detect-port.js", + "detect-port": "bin/detect-port.js" + } + }, + "node_modules/dezalgo": { + "version": "1.0.4", + "dev": true, + "license": "ISC", + "dependencies": { + "asap": "^2.0.0", + "wrappy": "1" + } + }, + "node_modules/diff": { + "version": "5.1.0", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/difflib": { + "version": "0.2.4", + "dev": true, + "dependencies": { + "heap": ">= 0.2.0" + } + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/doctrine": { + "version": "3.0.0", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/dot-prop": { + "version": "5.3.0", + "dev": true, + "license": "MIT", + "dependencies": { + "is-obj": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/dotenv": { + "version": "10.0.0", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=10" + } + }, + "node_modules/duplexer2": { + "version": "0.1.4", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "readable-stream": "^2.0.2" + } + }, + "node_modules/duplexer2/node_modules/readable-stream": { + "version": "2.3.8", + "dev": true, + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/duplexer2/node_modules/safe-buffer": { + "version": "5.1.2", + "dev": true, + "license": "MIT" + }, + "node_modules/duplexer2/node_modules/string_decoder": { + "version": "1.1.1", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "dev": true, + "license": "MIT" + }, + "node_modules/ecc-jsbn": { + "version": "0.1.2", + "dev": true, + "license": "MIT", + "dependencies": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.4.454", + "dev": true, + "license": "ISC" + }, + "node_modules/elliptic": { + "version": "6.5.4", + "license": "MIT", + "dependencies": { + "bn.js": "^4.11.9", + "brorand": "^1.1.0", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.1", + "inherits": "^2.0.4", + "minimalistic-assert": "^1.0.1", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "node_modules/elliptic/node_modules/bn.js": { + "version": "4.12.0", + "license": "MIT" + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "dev": true, + "license": "MIT" + }, + "node_modules/encode-utf8": { + "version": "1.0.3", + "license": "MIT" + }, + "node_modules/encoding": { + "version": "0.1.13", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "iconv-lite": "^0.6.2" + } + }, + "node_modules/enquirer": { + "version": "2.3.6", + "license": "MIT", + "dependencies": { + "ansi-colors": "^4.1.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/enquirer/node_modules/ansi-colors": { + "version": "4.1.3", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/env-ci": { + "version": "5.5.0", + "dev": true, + "license": "MIT", + "dependencies": { + "execa": "^5.0.0", + "fromentries": "^1.3.2", + "java-properties": "^1.0.0" + }, + "engines": { + "node": ">=10.17" + } + }, + "node_modules/env-paths": { + "version": "2.2.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/err-code": { + "version": "2.0.3", + "dev": true, + "license": "MIT" + }, + "node_modules/error-ex": { + "version": "1.3.2", + "dev": true, + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/es-abstract": { + "version": "1.21.2", + "dev": true, + "license": "MIT", + "dependencies": { + "array-buffer-byte-length": "^1.0.0", + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "es-set-tostringtag": "^2.0.1", + "es-to-primitive": "^1.2.1", + "function.prototype.name": "^1.1.5", + "get-intrinsic": "^1.2.0", + "get-symbol-description": "^1.0.0", + "globalthis": "^1.0.3", + "gopd": "^1.0.1", + "has": "^1.0.3", + "has-property-descriptors": "^1.0.0", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.5", + "is-array-buffer": "^3.0.2", + "is-callable": "^1.2.7", + "is-negative-zero": "^2.0.2", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.2", + "is-string": "^1.0.7", + "is-typed-array": "^1.1.10", + "is-weakref": "^1.0.2", + "object-inspect": "^1.12.3", + "object-keys": "^1.1.1", + "object.assign": "^4.1.4", + "regexp.prototype.flags": "^1.4.3", + "safe-regex-test": "^1.0.0", + "string.prototype.trim": "^1.2.7", + "string.prototype.trimend": "^1.0.6", + "string.prototype.trimstart": "^1.0.6", + "typed-array-length": "^1.0.4", + "unbox-primitive": "^1.0.2", + "which-typed-array": "^1.1.9" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-abstract/node_modules/object.assign": { + "version": "4.1.4", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-array-method-boxes-properly": { + "version": "1.0.0", + "dev": true, + "license": "MIT" + }, + "node_modules/es-set-tostringtag": { + "version": "2.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "get-intrinsic": "^1.1.3", + "has": "^1.0.3", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-shim-unscopables": { + "version": "1.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "has": "^1.0.3" + } + }, + "node_modules/es-to-primitive": { + "version": "1.2.1", + "dev": true, + "license": "MIT", + "dependencies": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/escalade": { + "version": "3.1.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/escodegen": { + "version": "1.8.1", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esprima": "^2.7.1", + "estraverse": "^1.9.1", + "esutils": "^2.0.2", + "optionator": "^0.8.1" + }, + "bin": { + "escodegen": "bin/escodegen.js", + "esgenerate": "bin/esgenerate.js" + }, + "engines": { + "node": ">=0.12.0" + }, + "optionalDependencies": { + "source-map": "~0.2.0" + } + }, + "node_modules/escodegen/node_modules/esprima": { + "version": "2.7.3", + "dev": true, + "license": "BSD-2-Clause", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/escodegen/node_modules/estraverse": { + "version": "1.9.3", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/escodegen/node_modules/levn": { + "version": "0.3.0", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/escodegen/node_modules/optionator": { + "version": "0.8.3", + "dev": true, + "license": "MIT", + "dependencies": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.6", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "word-wrap": "~1.2.3" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/escodegen/node_modules/prelude-ls": { + "version": "1.1.2", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/escodegen/node_modules/source-map": { + "version": "0.2.0", + "dev": true, + "optional": true, + "dependencies": { + "amdefine": ">=0.0.4" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/escodegen/node_modules/type-check": { + "version": "0.3.2", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "~1.1.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/eslint": { + "version": "7.32.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "7.12.11", + "@eslint/eslintrc": "^0.4.3", + "@humanwhocodes/config-array": "^0.5.0", + "ajv": "^6.10.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.0.1", + "doctrine": "^3.0.0", + "enquirer": "^2.3.5", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^5.1.1", + "eslint-utils": "^2.1.0", + "eslint-visitor-keys": "^2.0.0", + "espree": "^7.3.1", + "esquery": "^1.4.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "functional-red-black-tree": "^1.0.1", + "glob-parent": "^5.1.2", + "globals": "^13.6.0", + "ignore": "^4.0.6", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "js-yaml": "^3.13.1", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.0.4", + "natural-compare": "^1.4.0", + "optionator": "^0.9.1", + "progress": "^2.0.0", + "regexpp": "^3.1.0", + "semver": "^7.2.1", + "strip-ansi": "^6.0.0", + "strip-json-comments": "^3.1.0", + "table": "^6.0.9", + "text-table": "^0.2.0", + "v8-compile-cache": "^2.0.3" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-config-prettier": { + "version": "8.5.0", + "dev": true, + "license": "MIT", + "bin": { + "eslint-config-prettier": "bin/cli.js" + }, + "peerDependencies": { + "eslint": ">=7.0.0" + } + }, + "node_modules/eslint-import-resolver-node": { + "version": "0.3.7", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^3.2.7", + "is-core-module": "^2.11.0", + "resolve": "^1.22.1" + } + }, + "node_modules/eslint-import-resolver-node/node_modules/debug": { + "version": "3.2.7", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-module-utils": { + "version": "2.8.0", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^3.2.7" + }, + "engines": { + "node": ">=4" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + } + } + }, + "node_modules/eslint-module-utils/node_modules/debug": { + "version": "3.2.7", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-es": { + "version": "3.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-utils": "^2.0.0", + "regexpp": "^3.0.0" + }, + "engines": { + "node": ">=8.10.0" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + }, + "peerDependencies": { + "eslint": ">=4.19.1" + } + }, + "node_modules/eslint-plugin-import": { + "version": "2.27.5", + "dev": true, + "license": "MIT", + "dependencies": { + "array-includes": "^3.1.6", + "array.prototype.flat": "^1.3.1", + "array.prototype.flatmap": "^1.3.1", + "debug": "^3.2.7", + "doctrine": "^2.1.0", + "eslint-import-resolver-node": "^0.3.7", + "eslint-module-utils": "^2.7.4", + "has": "^1.0.3", + "is-core-module": "^2.11.0", + "is-glob": "^4.0.3", + "minimatch": "^3.1.2", + "object.values": "^1.1.6", + "resolve": "^1.22.1", + "semver": "^6.3.0", + "tsconfig-paths": "^3.14.1" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8" + } + }, + "node_modules/eslint-plugin-import/node_modules/debug": { + "version": "3.2.7", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-import/node_modules/doctrine": { + "version": "2.1.0", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eslint-plugin-import/node_modules/semver": { + "version": "6.3.0", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/eslint-plugin-node": { + "version": "11.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-plugin-es": "^3.0.0", + "eslint-utils": "^2.0.0", + "ignore": "^5.1.1", + "minimatch": "^3.0.4", + "resolve": "^1.10.1", + "semver": "^6.1.0" + }, + "engines": { + "node": ">=8.10.0" + }, + "peerDependencies": { + "eslint": ">=5.16.0" + } + }, + "node_modules/eslint-plugin-node/node_modules/semver": { + "version": "6.3.0", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/eslint-plugin-prettier": { + "version": "3.4.1", + "dev": true, + "license": "MIT", + "dependencies": { + "prettier-linter-helpers": "^1.0.0" + }, + "engines": { + "node": ">=6.0.0" + }, + "peerDependencies": { + "eslint": ">=5.0.0", + "prettier": ">=1.13.0" + }, + "peerDependenciesMeta": { + "eslint-config-prettier": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-promise": { + "version": "5.2.0", + "dev": true, + "license": "ISC", + "engines": { + "node": "^10.12.0 || >=12.0.0" + }, + "peerDependencies": { + "eslint": "^7.0.0" + } + }, + "node_modules/eslint-scope": { + "version": "5.1.1", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/eslint-scope/node_modules/estraverse": { + "version": "4.3.0", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/eslint-utils": { + "version": "2.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^1.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "1.3.0", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=4" + } + }, + "node_modules/eslint/node_modules/@babel/code-frame": { + "version": "7.12.11", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/highlight": "^7.10.4" + } + }, + "node_modules/eslint/node_modules/escape-string-regexp": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/eslint-visitor-keys": { + "version": "2.1.0", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=10" + } + }, + "node_modules/eslint/node_modules/ignore": { + "version": "4.0.6", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/eslint/node_modules/js-yaml": { + "version": "3.14.1", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/espree": { + "version": "7.3.1", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^7.4.0", + "acorn-jsx": "^5.3.1", + "eslint-visitor-keys": "^1.3.0" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "dev": true, + "license": "BSD-2-Clause", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/esquery": { + "version": "1.5.0", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estree-walker": { + "version": "2.0.2", + "dev": true, + "license": "MIT" + }, + "node_modules/esutils": { + "version": "2.0.3", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eth-gas-reporter": { + "version": "0.2.25", + "dev": true, + "license": "MIT", + "dependencies": { + "@ethersproject/abi": "^5.0.0-beta.146", + "@solidity-parser/parser": "^0.14.0", + "cli-table3": "^0.5.0", + "colors": "1.4.0", + "ethereum-cryptography": "^1.0.3", + "ethers": "^4.0.40", + "fs-readdir-recursive": "^1.1.0", + "lodash": "^4.17.14", + "markdown-table": "^1.1.3", + "mocha": "^7.1.1", + "req-cwd": "^2.0.0", + "request": "^2.88.0", + "request-promise-native": "^1.0.5", + "sha1": "^1.1.1", + "sync-request": "^6.0.0" + }, + "peerDependencies": { + "@codechecks/client": "^0.1.0" + }, + "peerDependenciesMeta": { + "@codechecks/client": { + "optional": true + } + } + }, + "node_modules/eth-gas-reporter/node_modules/@solidity-parser/parser": { + "version": "0.14.5", + "dev": true, + "license": "MIT", + "dependencies": { + "antlr4ts": "^0.5.0-alpha.4" + } + }, + "node_modules/eth-gas-reporter/node_modules/ansi-regex": { + "version": "3.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/eth-gas-reporter/node_modules/bn.js": { + "version": "4.12.0", + "dev": true, + "license": "MIT" + }, + "node_modules/eth-gas-reporter/node_modules/brace-expansion": { + "version": "1.1.11", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eth-gas-reporter/node_modules/chokidar": { + "version": "3.3.0", + "dev": true, + "license": "MIT", + "dependencies": { + "anymatch": "~3.1.1", + "braces": "~3.0.2", + "glob-parent": "~5.1.0", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.2.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.1.1" + } + }, + "node_modules/eth-gas-reporter/node_modules/cli-table3": { + "version": "0.5.1", + "dev": true, + "license": "MIT", + "dependencies": { + "object-assign": "^4.1.0", + "string-width": "^2.1.1" + }, + "engines": { + "node": ">=6" + }, + "optionalDependencies": { + "colors": "^1.1.2" + } + }, + "node_modules/eth-gas-reporter/node_modules/debug": { + "version": "3.2.6", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eth-gas-reporter/node_modules/debug/node_modules/ms": { + "version": "2.1.3", + "dev": true, + "license": "MIT" + }, + "node_modules/eth-gas-reporter/node_modules/diff": { + "version": "3.5.0", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/eth-gas-reporter/node_modules/ethereum-cryptography": { + "version": "1.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@noble/hashes": "1.2.0", + "@noble/secp256k1": "1.7.1", + "@scure/bip32": "1.1.5", + "@scure/bip39": "1.1.1" + } + }, + "node_modules/eth-gas-reporter/node_modules/ethers": { + "version": "4.0.49", + "dev": true, + "license": "MIT", + "dependencies": { + "aes-js": "3.0.0", + "bn.js": "^4.11.9", + "elliptic": "6.5.4", + "hash.js": "1.1.3", + "js-sha3": "0.5.7", + "scrypt-js": "2.0.4", + "setimmediate": "1.0.4", + "uuid": "2.0.1", + "xmlhttprequest": "1.8.0" + } + }, + "node_modules/eth-gas-reporter/node_modules/find-up": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/eth-gas-reporter/node_modules/fsevents": { + "version": "2.1.3", + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/eth-gas-reporter/node_modules/glob": { + "version": "7.1.3", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + } + }, + "node_modules/eth-gas-reporter/node_modules/hash.js": { + "version": "1.1.3", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.0" + } + }, + "node_modules/eth-gas-reporter/node_modules/is-fullwidth-code-point": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/eth-gas-reporter/node_modules/js-sha3": { + "version": "0.5.7", + "dev": true, + "license": "MIT" + }, + "node_modules/eth-gas-reporter/node_modules/js-yaml": { + "version": "3.13.1", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/eth-gas-reporter/node_modules/locate-path": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/eth-gas-reporter/node_modules/minimatch": { + "version": "3.1.2", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/eth-gas-reporter/node_modules/mkdirp": { + "version": "0.5.5", + "dev": true, + "license": "MIT", + "dependencies": { + "minimist": "^1.2.5" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/eth-gas-reporter/node_modules/mocha": { + "version": "7.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-colors": "3.2.3", + "browser-stdout": "1.3.1", + "chokidar": "3.3.0", + "debug": "3.2.6", + "diff": "3.5.0", + "escape-string-regexp": "1.0.5", + "find-up": "3.0.0", + "glob": "7.1.3", + "growl": "1.10.5", + "he": "1.2.0", + "js-yaml": "3.13.1", + "log-symbols": "3.0.0", + "minimatch": "3.0.4", + "mkdirp": "0.5.5", + "ms": "2.1.1", + "node-environment-flags": "1.0.6", + "object.assign": "4.1.0", + "strip-json-comments": "2.0.1", + "supports-color": "6.0.0", + "which": "1.3.1", + "wide-align": "1.1.3", + "yargs": "13.3.2", + "yargs-parser": "13.1.2", + "yargs-unparser": "1.6.0" + }, + "bin": { + "_mocha": "bin/_mocha", + "mocha": "bin/mocha" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mochajs" + } + }, + "node_modules/eth-gas-reporter/node_modules/mocha/node_modules/minimatch": { + "version": "3.0.4", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/eth-gas-reporter/node_modules/ms": { + "version": "2.1.1", + "dev": true, + "license": "MIT" + }, + "node_modules/eth-gas-reporter/node_modules/p-locate": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/eth-gas-reporter/node_modules/path-exists": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/eth-gas-reporter/node_modules/readdirp": { + "version": "3.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/eth-gas-reporter/node_modules/scrypt-js": { + "version": "2.0.4", + "dev": true, + "license": "MIT" + }, + "node_modules/eth-gas-reporter/node_modules/setimmediate": { + "version": "1.0.4", + "dev": true, + "license": "MIT" + }, + "node_modules/eth-gas-reporter/node_modules/string-width": { + "version": "2.1.1", + "dev": true, + "license": "MIT", + "dependencies": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/eth-gas-reporter/node_modules/strip-ansi": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/eth-gas-reporter/node_modules/strip-json-comments": { + "version": "2.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eth-gas-reporter/node_modules/uuid": { + "version": "2.0.1", + "dev": true + }, + "node_modules/eth-gas-reporter/node_modules/which": { + "version": "1.3.1", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/ethereum-bloom-filters": { + "version": "1.0.10", + "dev": true, + "license": "MIT", + "dependencies": { + "js-sha3": "^0.8.0" + } + }, + "node_modules/ethereum-cryptography": { + "version": "0.1.3", + "license": "MIT", + "dependencies": { + "@types/pbkdf2": "^3.0.0", + "@types/secp256k1": "^4.0.1", + "blakejs": "^1.1.0", + "browserify-aes": "^1.2.0", + "bs58check": "^2.1.2", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "hash.js": "^1.1.7", + "keccak": "^3.0.0", + "pbkdf2": "^3.0.17", + "randombytes": "^2.1.0", + "safe-buffer": "^5.1.2", + "scrypt-js": "^3.0.0", + "secp256k1": "^4.0.1", + "setimmediate": "^1.0.5" + } + }, + "node_modules/ethereumjs-abi": { + "version": "0.6.8", + "dev": true, + "license": "MIT", + "dependencies": { + "bn.js": "^4.11.8", + "ethereumjs-util": "^6.0.0" + } + }, + "node_modules/ethereumjs-abi/node_modules/@types/bn.js": { + "version": "4.11.6", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/ethereumjs-abi/node_modules/@types/node": { + "version": "20.4.1", + "dev": true, + "license": "MIT" + }, + "node_modules/ethereumjs-abi/node_modules/bn.js": { + "version": "4.12.0", + "dev": true, + "license": "MIT" + }, + "node_modules/ethereumjs-abi/node_modules/ethereumjs-util": { + "version": "6.2.1", + "dev": true, + "license": "MPL-2.0", + "dependencies": { + "@types/bn.js": "^4.11.3", + "bn.js": "^4.11.0", + "create-hash": "^1.1.2", + "elliptic": "^6.5.2", + "ethereum-cryptography": "^0.1.3", + "ethjs-util": "0.1.6", + "rlp": "^2.2.3" + } + }, + "node_modules/ethereumjs-util": { + "version": "7.1.5", + "license": "MPL-2.0", + "dependencies": { + "@types/bn.js": "^5.1.0", + "bn.js": "^5.1.2", + "create-hash": "^1.1.2", + "ethereum-cryptography": "^0.1.3", + "rlp": "^2.2.4" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/ethers": { + "version": "5.7.2", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/abi": "5.7.0", + "@ethersproject/abstract-provider": "5.7.0", + "@ethersproject/abstract-signer": "5.7.0", + "@ethersproject/address": "5.7.0", + "@ethersproject/base64": "5.7.0", + "@ethersproject/basex": "5.7.0", + "@ethersproject/bignumber": "5.7.0", + "@ethersproject/bytes": "5.7.0", + "@ethersproject/constants": "5.7.0", + "@ethersproject/contracts": "5.7.0", + "@ethersproject/hash": "5.7.0", + "@ethersproject/hdnode": "5.7.0", + "@ethersproject/json-wallets": "5.7.0", + "@ethersproject/keccak256": "5.7.0", + "@ethersproject/logger": "5.7.0", + "@ethersproject/networks": "5.7.1", + "@ethersproject/pbkdf2": "5.7.0", + "@ethersproject/properties": "5.7.0", + "@ethersproject/providers": "5.7.2", + "@ethersproject/random": "5.7.0", + "@ethersproject/rlp": "5.7.0", + "@ethersproject/sha2": "5.7.0", + "@ethersproject/signing-key": "5.7.0", + "@ethersproject/solidity": "5.7.0", + "@ethersproject/strings": "5.7.0", + "@ethersproject/transactions": "5.7.0", + "@ethersproject/units": "5.7.0", + "@ethersproject/wallet": "5.7.0", + "@ethersproject/web": "5.7.1", + "@ethersproject/wordlists": "5.7.0" + } + }, + "node_modules/ethjs-unit": { + "version": "0.1.6", + "dev": true, + "license": "MIT", + "dependencies": { + "bn.js": "4.11.6", + "number-to-bn": "1.7.0" + }, + "engines": { + "node": ">=6.5.0", + "npm": ">=3" + } + }, + "node_modules/ethjs-unit/node_modules/bn.js": { + "version": "4.11.6", + "dev": true, + "license": "MIT" + }, + "node_modules/ethjs-util": { + "version": "0.1.6", + "dev": true, + "license": "MIT", + "dependencies": { + "is-hex-prefixed": "1.0.0", + "strip-hex-prefix": "1.0.0" + }, + "engines": { + "node": ">=6.5.0", + "npm": ">=3" + } + }, + "node_modules/event-target-shim": { + "version": "5.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/evp_bytestokey": { + "version": "1.0.3", + "license": "MIT", + "dependencies": { + "md5.js": "^1.3.4", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/execa": { + "version": "5.1.1", + "dev": true, + "license": "MIT", + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/exponential-backoff": { + "version": "3.1.1", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/extend": { + "version": "3.0.2", + "dev": true, + "license": "MIT" + }, + "node_modules/extsprintf": { + "version": "1.3.0", + "dev": true, + "engines": [ + "node >=0.6.0" + ], + "license": "MIT" + }, + "node_modules/fast-base64-decode": { + "version": "1.0.0", + "license": "MIT" + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-diff": { + "version": "1.3.0", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/fast-glob": { + "version": "3.3.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "dev": true, + "license": "MIT" + }, + "node_modules/fastest-levenshtein": { + "version": "1.0.16", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4.9.1" + } + }, + "node_modules/fastq": { + "version": "1.15.0", + "dev": true, + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/figures": { + "version": "3.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "escape-string-regexp": "^1.0.5" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/fill-range": { + "version": "7.0.1", + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-replace": { + "version": "1.0.3", + "dev": true, + "license": "MIT", + "dependencies": { + "array-back": "^1.0.4", + "test-value": "^2.1.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/find-up": { + "version": "2.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/find-up/node_modules/locate-path": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/find-up/node_modules/p-limit": { + "version": "1.3.0", + "dev": true, + "license": "MIT", + "dependencies": { + "p-try": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/find-up/node_modules/p-locate": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^1.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/find-up/node_modules/p-try": { + "version": "1.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/find-up/node_modules/path-exists": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/find-versions": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "semver-regex": "^3.1.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat": { + "version": "5.0.2", + "dev": true, + "license": "BSD-3-Clause", + "bin": { + "flat": "cli.js" + } + }, + "node_modules/flat-cache": { + "version": "3.0.4", + "dev": true, + "license": "MIT", + "dependencies": { + "flatted": "^3.1.0", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flatted": { + "version": "3.2.7", + "dev": true, + "license": "ISC" + }, + "node_modules/fmix": { + "version": "0.1.0", + "license": "MIT", + "dependencies": { + "imul": "^1.0.0" + } + }, + "node_modules/follow-redirects": { + "version": "1.15.2", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/for-each": { + "version": "0.3.3", + "dev": true, + "license": "MIT", + "dependencies": { + "is-callable": "^1.1.3" + } + }, + "node_modules/foreground-child": { + "version": "3.1.1", + "dev": true, + "license": "ISC", + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/foreground-child/node_modules/signal-exit": { + "version": "4.0.2", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/forever-agent": { + "version": "0.6.1", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "*" + } + }, + "node_modules/form-data": { + "version": "4.0.0", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fp-ts": { + "version": "1.19.3", + "dev": true, + "license": "MIT" + }, + "node_modules/from2": { + "version": "2.3.0", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.1", + "readable-stream": "^2.0.0" + } + }, + "node_modules/from2/node_modules/readable-stream": { + "version": "2.3.8", + "dev": true, + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/from2/node_modules/safe-buffer": { + "version": "5.1.2", + "dev": true, + "license": "MIT" + }, + "node_modules/from2/node_modules/string_decoder": { + "version": "1.1.1", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/fromentries": { + "version": "1.3.2", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/fs-extra": { + "version": "11.1.1", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, + "node_modules/fs-minipass": { + "version": "2.1.0", + "dev": true, + "license": "ISC", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/fs-readdir-recursive": { + "version": "1.1.0", + "dev": true, + "license": "MIT" + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "dev": true, + "license": "ISC" + }, + "node_modules/fsevents": { + "version": "2.3.2", + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.1", + "license": "MIT" + }, + "node_modules/function.prototype.name": { + "version": "1.1.5", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.19.0", + "functions-have-names": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/functional-red-black-tree": { + "version": "1.0.1", + "dev": true, + "license": "MIT" + }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gauge": { + "version": "4.0.4", + "dev": true, + "license": "ISC", + "dependencies": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.3", + "console-control-strings": "^1.1.0", + "has-unicode": "^2.0.1", + "signal-exit": "^3.0.7", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.5" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/gauge/node_modules/wide-align": { + "version": "1.1.5", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "dev": true, + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-func-name": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.1", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-port": { + "version": "3.2.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/get-stream": { + "version": "6.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-symbol-description": { + "version": "1.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/getpass": { + "version": "0.1.7", + "dev": true, + "license": "MIT", + "dependencies": { + "assert-plus": "^1.0.0" + } + }, + "node_modules/ghost-testrpc": { + "version": "0.0.2", + "dev": true, + "license": "ISC", + "dependencies": { + "chalk": "^2.4.2", + "node-emoji": "^1.10.0" + }, + "bin": { + "testrpc-sc": "index.js" + } + }, + "node_modules/ghost-testrpc/node_modules/ansi-styles": { + "version": "3.2.1", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/ghost-testrpc/node_modules/chalk": { + "version": "2.4.2", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/ghost-testrpc/node_modules/color-convert": { + "version": "1.9.3", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/ghost-testrpc/node_modules/color-name": { + "version": "1.1.3", + "dev": true, + "license": "MIT" + }, + "node_modules/ghost-testrpc/node_modules/has-flag": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/ghost-testrpc/node_modules/supports-color": { + "version": "5.5.0", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/git-log-parser": { + "version": "1.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "argv-formatter": "~1.0.0", + "spawn-error-forwarder": "~1.0.0", + "split2": "~1.0.0", + "stream-combiner2": "~1.1.1", + "through2": "~2.0.0", + "traverse": "~0.6.6" + } + }, + "node_modules/git-log-parser/node_modules/readable-stream": { + "version": "2.3.8", + "dev": true, + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/git-log-parser/node_modules/safe-buffer": { + "version": "5.1.2", + "dev": true, + "license": "MIT" + }, + "node_modules/git-log-parser/node_modules/split2": { + "version": "1.0.0", + "dev": true, + "license": "ISC", + "dependencies": { + "through2": "~2.0.0" + } + }, + "node_modules/git-log-parser/node_modules/string_decoder": { + "version": "1.1.1", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/git-log-parser/node_modules/through2": { + "version": "2.0.5", + "dev": true, + "license": "MIT", + "dependencies": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "node_modules/git-raw-commits": { + "version": "2.0.11", + "dev": true, + "license": "MIT", + "dependencies": { + "dargs": "^7.0.0", + "lodash": "^4.17.15", + "meow": "^8.0.0", + "split2": "^3.0.0", + "through2": "^4.0.0" + }, + "bin": { + "git-raw-commits": "cli.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/global-dirs": { + "version": "0.1.1", + "dev": true, + "license": "MIT", + "dependencies": { + "ini": "^1.3.4" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/global-modules": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "global-prefix": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/global-prefix": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "ini": "^1.3.5", + "kind-of": "^6.0.2", + "which": "^1.3.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/global-prefix/node_modules/which": { + "version": "1.3.1", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/globals": { + "version": "13.20.0", + "dev": true, + "license": "MIT", + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globals/node_modules/type-fest": { + "version": "0.20.2", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globalthis": { + "version": "1.0.3", + "dev": true, + "license": "MIT", + "dependencies": { + "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/globby": { + "version": "11.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/gopd": { + "version": "1.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "license": "ISC" + }, + "node_modules/graphemer": { + "version": "1.4.0", + "dev": true, + "license": "MIT" + }, + "node_modules/growl": { + "version": "1.10.5", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4.x" + } + }, + "node_modules/handlebars": { + "version": "4.7.7", + "dev": true, + "license": "MIT", + "dependencies": { + "minimist": "^1.2.5", + "neo-async": "^2.6.0", + "source-map": "^0.6.1", + "wordwrap": "^1.0.0" + }, + "bin": { + "handlebars": "bin/handlebars" + }, + "engines": { + "node": ">=0.4.7" + }, + "optionalDependencies": { + "uglify-js": "^3.1.4" + } + }, + "node_modules/har-schema": { + "version": "2.0.0", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=4" + } + }, + "node_modules/har-validator": { + "version": "5.1.5", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^6.12.3", + "har-schema": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/hard-rejection": { + "version": "2.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/hardhat": { + "version": "2.16.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@ethersproject/abi": "^5.1.2", + "@metamask/eth-sig-util": "^4.0.0", + "@nomicfoundation/ethereumjs-block": "5.0.1", + "@nomicfoundation/ethereumjs-blockchain": "7.0.1", + "@nomicfoundation/ethereumjs-common": "4.0.1", + "@nomicfoundation/ethereumjs-evm": "2.0.1", + "@nomicfoundation/ethereumjs-rlp": "5.0.1", + "@nomicfoundation/ethereumjs-statemanager": "2.0.1", + "@nomicfoundation/ethereumjs-trie": "6.0.1", + "@nomicfoundation/ethereumjs-tx": "5.0.1", + "@nomicfoundation/ethereumjs-util": "9.0.1", + "@nomicfoundation/ethereumjs-vm": "7.0.1", + "@nomicfoundation/solidity-analyzer": "^0.1.0", + "@sentry/node": "^5.18.1", + "@types/bn.js": "^5.1.0", + "@types/lru-cache": "^5.1.0", + "abort-controller": "^3.0.0", + "adm-zip": "^0.4.16", + "aggregate-error": "^3.0.0", + "ansi-escapes": "^4.3.0", + "chalk": "^2.4.2", + "chokidar": "^3.4.0", + "ci-info": "^2.0.0", + "debug": "^4.1.1", + "enquirer": "^2.3.0", + "env-paths": "^2.2.0", + "ethereum-cryptography": "^1.0.3", + "ethereumjs-abi": "^0.6.8", + "find-up": "^2.1.0", + "fp-ts": "1.19.3", + "fs-extra": "^7.0.1", + "glob": "7.2.0", + "immutable": "^4.0.0-rc.12", + "io-ts": "1.10.4", + "keccak": "^3.0.2", + "lodash": "^4.17.11", + "mnemonist": "^0.38.0", + "mocha": "^10.0.0", + "p-map": "^4.0.0", + "raw-body": "^2.4.1", + "resolve": "1.17.0", + "semver": "^6.3.0", + "solc": "0.7.3", + "source-map-support": "^0.5.13", + "stacktrace-parser": "^0.1.10", + "tsort": "0.0.1", + "undici": "^5.14.0", + "uuid": "^8.3.2", + "ws": "^7.4.6" + }, + "bin": { + "hardhat": "internal/cli/bootstrap.js" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "ts-node": "*", + "typescript": "*" + }, + "peerDependenciesMeta": { + "ts-node": { + "optional": true + }, + "typescript": { + "optional": true + } + } + }, + "node_modules/hardhat-deploy": { + "version": "0.11.34", + "license": "MIT", + "dependencies": { + "@ethersproject/abi": "^5.7.0", + "@ethersproject/abstract-signer": "^5.7.0", + "@ethersproject/address": "^5.7.0", + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/constants": "^5.7.0", + "@ethersproject/contracts": "^5.7.0", + "@ethersproject/providers": "^5.7.2", + "@ethersproject/solidity": "^5.7.0", + "@ethersproject/transactions": "^5.7.0", + "@ethersproject/wallet": "^5.7.0", + "@types/qs": "^6.9.7", + "axios": "^0.21.1", + "chalk": "^4.1.2", + "chokidar": "^3.5.2", + "debug": "^4.3.2", + "enquirer": "^2.3.6", + "ethers": "^5.5.3", + "form-data": "^4.0.0", + "fs-extra": "^10.0.0", + "match-all": "^1.2.6", + "murmur-128": "^0.2.1", + "qs": "^6.9.4", + "zksync-web3": "^0.14.3" + } + }, + "node_modules/hardhat-deploy-ethers": { + "version": "0.3.0-beta.13", + "dev": true, + "license": "MIT", + "peerDependencies": { + "ethers": "^5.0.0", + "hardhat": "^2.0.0" + } + }, + "node_modules/hardhat-deploy/node_modules/fs-extra": { + "version": "10.1.0", + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/hardhat-gas-reporter": { + "version": "1.0.9", + "dev": true, + "license": "MIT", + "dependencies": { + "array-uniq": "1.0.3", + "eth-gas-reporter": "^0.2.25", + "sha1": "^1.1.1" + }, + "peerDependencies": { + "hardhat": "^2.0.2" + } + }, + "node_modules/hardhat/node_modules/@nomicfoundation/ethereumjs-evm": { + "version": "2.0.1", + "dev": true, + "license": "MPL-2.0", + "dependencies": { + "@ethersproject/providers": "^5.7.1", + "@nomicfoundation/ethereumjs-common": "4.0.1", + "@nomicfoundation/ethereumjs-tx": "5.0.1", + "@nomicfoundation/ethereumjs-util": "9.0.1", + "debug": "^4.3.3", + "ethereum-cryptography": "0.1.3", + "mcl-wasm": "^0.7.1", + "rustbn.js": "~0.2.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/hardhat/node_modules/@nomicfoundation/ethereumjs-evm/node_modules/ethereum-cryptography": { + "version": "0.1.3", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/pbkdf2": "^3.0.0", + "@types/secp256k1": "^4.0.1", + "blakejs": "^1.1.0", + "browserify-aes": "^1.2.0", + "bs58check": "^2.1.2", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "hash.js": "^1.1.7", + "keccak": "^3.0.0", + "pbkdf2": "^3.0.17", + "randombytes": "^2.1.0", + "safe-buffer": "^5.1.2", + "scrypt-js": "^3.0.0", + "secp256k1": "^4.0.1", + "setimmediate": "^1.0.5" + } + }, + "node_modules/hardhat/node_modules/@nomicfoundation/ethereumjs-trie": { + "version": "6.0.1", + "dev": true, + "license": "MPL-2.0", + "dependencies": { + "@nomicfoundation/ethereumjs-rlp": "5.0.1", + "@nomicfoundation/ethereumjs-util": "9.0.1", + "@types/readable-stream": "^2.3.13", + "ethereum-cryptography": "0.1.3", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/hardhat/node_modules/@nomicfoundation/ethereumjs-trie/node_modules/ethereum-cryptography": { + "version": "0.1.3", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/pbkdf2": "^3.0.0", + "@types/secp256k1": "^4.0.1", + "blakejs": "^1.1.0", + "browserify-aes": "^1.2.0", + "bs58check": "^2.1.2", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "hash.js": "^1.1.7", + "keccak": "^3.0.0", + "pbkdf2": "^3.0.17", + "randombytes": "^2.1.0", + "safe-buffer": "^5.1.2", + "scrypt-js": "^3.0.0", + "secp256k1": "^4.0.1", + "setimmediate": "^1.0.5" + } + }, + "node_modules/hardhat/node_modules/@nomicfoundation/ethereumjs-util": { + "version": "9.0.1", + "dev": true, + "license": "MPL-2.0", + "dependencies": { + "@chainsafe/ssz": "^0.10.0", + "@nomicfoundation/ethereumjs-rlp": "5.0.1", + "ethereum-cryptography": "0.1.3" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/hardhat/node_modules/@nomicfoundation/ethereumjs-util/node_modules/ethereum-cryptography": { + "version": "0.1.3", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/pbkdf2": "^3.0.0", + "@types/secp256k1": "^4.0.1", + "blakejs": "^1.1.0", + "browserify-aes": "^1.2.0", + "bs58check": "^2.1.2", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "hash.js": "^1.1.7", + "keccak": "^3.0.0", + "pbkdf2": "^3.0.17", + "randombytes": "^2.1.0", + "safe-buffer": "^5.1.2", + "scrypt-js": "^3.0.0", + "secp256k1": "^4.0.1", + "setimmediate": "^1.0.5" + } + }, + "node_modules/hardhat/node_modules/@nomicfoundation/ethereumjs-vm": { + "version": "7.0.1", + "dev": true, + "license": "MPL-2.0", + "dependencies": { + "@nomicfoundation/ethereumjs-block": "5.0.1", + "@nomicfoundation/ethereumjs-blockchain": "7.0.1", + "@nomicfoundation/ethereumjs-common": "4.0.1", + "@nomicfoundation/ethereumjs-evm": "2.0.1", + "@nomicfoundation/ethereumjs-rlp": "5.0.1", + "@nomicfoundation/ethereumjs-statemanager": "2.0.1", + "@nomicfoundation/ethereumjs-trie": "6.0.1", + "@nomicfoundation/ethereumjs-tx": "5.0.1", + "@nomicfoundation/ethereumjs-util": "9.0.1", + "debug": "^4.3.3", + "ethereum-cryptography": "0.1.3", + "mcl-wasm": "^0.7.1", + "rustbn.js": "~0.2.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/hardhat/node_modules/@nomicfoundation/ethereumjs-vm/node_modules/ethereum-cryptography": { + "version": "0.1.3", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/pbkdf2": "^3.0.0", + "@types/secp256k1": "^4.0.1", + "blakejs": "^1.1.0", + "browserify-aes": "^1.2.0", + "bs58check": "^2.1.2", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "hash.js": "^1.1.7", + "keccak": "^3.0.0", + "pbkdf2": "^3.0.17", + "randombytes": "^2.1.0", + "safe-buffer": "^5.1.2", + "scrypt-js": "^3.0.0", + "secp256k1": "^4.0.1", + "setimmediate": "^1.0.5" + } + }, + "node_modules/hardhat/node_modules/ansi-styles": { + "version": "3.2.1", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/hardhat/node_modules/chalk": { + "version": "2.4.2", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/hardhat/node_modules/color-convert": { + "version": "1.9.3", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/hardhat/node_modules/color-name": { + "version": "1.1.3", + "dev": true, + "license": "MIT" + }, + "node_modules/hardhat/node_modules/ethereum-cryptography": { + "version": "1.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@noble/hashes": "1.2.0", + "@noble/secp256k1": "1.7.1", + "@scure/bip32": "1.1.5", + "@scure/bip39": "1.1.1" + } + }, + "node_modules/hardhat/node_modules/fs-extra": { + "version": "7.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "node_modules/hardhat/node_modules/glob": { + "version": "7.2.0", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/hardhat/node_modules/has-flag": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/hardhat/node_modules/jsonfile": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/hardhat/node_modules/resolve": { + "version": "1.17.0", + "dev": true, + "license": "MIT", + "dependencies": { + "path-parse": "^1.0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hardhat/node_modules/semver": { + "version": "6.3.0", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/hardhat/node_modules/supports-color": { + "version": "5.5.0", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/hardhat/node_modules/universalify": { + "version": "0.1.2", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/hardhat/node_modules/ws": { + "version": "7.5.9", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/has": { + "version": "1.0.3", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/has-bigints": { + "version": "1.0.2", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "get-intrinsic": "^1.1.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.1", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-unicode": { + "version": "2.0.1", + "dev": true, + "license": "ISC" + }, + "node_modules/hash-base": { + "version": "3.1.0", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.4", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/hash.js": { + "version": "1.1.7", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } + }, + "node_modules/he": { + "version": "1.2.0", + "dev": true, + "license": "MIT", + "bin": { + "he": "bin/he" + } + }, + "node_modules/heap": { + "version": "0.2.7", + "dev": true, + "license": "MIT" + }, + "node_modules/hmac-drbg": { + "version": "1.0.1", + "license": "MIT", + "dependencies": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "node_modules/hook-std": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/hosted-git-info": { + "version": "5.2.1", + "dev": true, + "license": "ISC", + "dependencies": { + "lru-cache": "^7.5.1" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/http-basic": { + "version": "8.1.3", + "dev": true, + "license": "MIT", + "dependencies": { + "caseless": "^0.12.0", + "concat-stream": "^1.6.2", + "http-response-object": "^3.0.1", + "parse-cache-control": "^1.0.1" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/http-cache-semantics": { + "version": "4.1.1", + "dev": true, + "license": "BSD-2-Clause" + }, + "node_modules/http-errors": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/http-proxy-agent": { + "version": "5.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@tootallnate/once": "2", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/http-response-object": { + "version": "3.0.2", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "^10.0.3" + } + }, + "node_modules/http-response-object/node_modules/@types/node": { + "version": "10.17.60", + "dev": true, + "license": "MIT" + }, + "node_modules/http-signature": { + "version": "1.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + }, + "engines": { + "node": ">=0.8", + "npm": ">=1.3.7" + } + }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/human-signals": { + "version": "2.1.0", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=10.17.0" + } + }, + "node_modules/humanize-ms": { + "version": "1.2.1", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.0.0" + } + }, + "node_modules/husky": { + "version": "8.0.3", + "dev": true, + "license": "MIT", + "bin": { + "husky": "lib/bin.js" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/typicode" + } + }, + "node_modules/iconv-lite": { + "version": "0.6.3", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/ignore": { + "version": "5.2.4", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/ignore-walk": { + "version": "5.0.1", + "dev": true, + "license": "ISC", + "dependencies": { + "minimatch": "^5.0.1" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/ignore-walk/node_modules/minimatch": { + "version": "5.1.6", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/immutable": { + "version": "4.3.0", + "dev": true, + "license": "MIT" + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "dev": true, + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/import-fresh/node_modules/resolve-from": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/import-from": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.2" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imul": { + "version": "1.0.1", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/indent-string": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/infer-owner": { + "version": "1.0.4", + "dev": true, + "license": "ISC" + }, + "node_modules/inflight": { + "version": "1.0.6", + "dev": true, + "license": "ISC", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "license": "ISC" + }, + "node_modules/ini": { + "version": "1.3.8", + "dev": true, + "license": "ISC" + }, + "node_modules/init-package-json": { + "version": "3.0.2", + "dev": true, + "license": "ISC", + "dependencies": { + "npm-package-arg": "^9.0.1", + "promzard": "^0.3.0", + "read": "^1.0.7", + "read-package-json": "^5.0.0", + "semver": "^7.3.5", + "validate-npm-package-license": "^3.0.4", + "validate-npm-package-name": "^4.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/internal-slot": { + "version": "1.0.5", + "dev": true, + "license": "MIT", + "dependencies": { + "get-intrinsic": "^1.2.0", + "has": "^1.0.3", + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/interpret": { + "version": "1.4.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/into-stream": { + "version": "6.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "from2": "^2.3.0", + "p-is-promise": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/invert-kv": { + "version": "1.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/io-ts": { + "version": "1.10.4", + "dev": true, + "license": "MIT", + "dependencies": { + "fp-ts": "^1.0.0" + } + }, + "node_modules/io-ts/node_modules/fp-ts": { + "version": "1.19.5", + "dev": true, + "license": "MIT" + }, + "node_modules/ip": { + "version": "2.0.0", + "dev": true, + "license": "MIT" + }, + "node_modules/ip-regex": { + "version": "4.3.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-array-buffer": { + "version": "3.0.2", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.0", + "is-typed-array": "^1.1.10" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "dev": true, + "license": "MIT" + }, + "node_modules/is-bigint": { + "version": "1.0.4", + "dev": true, + "license": "MIT", + "dependencies": { + "has-bigints": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "license": "MIT", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-boolean-object": { + "version": "1.1.2", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-buffer": { + "version": "2.0.5", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/is-callable": { + "version": "1.2.7", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-cidr": { + "version": "4.0.2", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "cidr-regex": "^3.1.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/is-core-module": { + "version": "2.12.1", + "dev": true, + "license": "MIT", + "dependencies": { + "has": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-date-object": { + "version": "1.0.5", + "dev": true, + "license": "MIT", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-hex-prefixed": { + "version": "1.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.5.0", + "npm": ">=3" + } + }, + "node_modules/is-lambda": { + "version": "1.0.1", + "dev": true, + "license": "MIT" + }, + "node_modules/is-negative-zero": { + "version": "2.0.2", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-number-object": { + "version": "1.0.7", + "dev": true, + "license": "MIT", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-obj": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-path-cwd": { + "version": "2.2.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-plain-obj": { + "version": "1.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-plain-object": { + "version": "5.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-regex": { + "version": "1.1.4", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.2", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-stream": { + "version": "2.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-string": { + "version": "1.0.7", + "dev": true, + "license": "MIT", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.0.4", + "dev": true, + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-text-path": { + "version": "1.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "text-extensions": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.10", + "dev": true, + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typedarray": { + "version": "1.0.0", + "dev": true, + "license": "MIT" + }, + "node_modules/is-unicode-supported": { + "version": "0.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-weakref": { + "version": "1.0.2", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "license": "MIT" + }, + "node_modules/isexe": { + "version": "2.0.0", + "dev": true, + "license": "ISC" + }, + "node_modules/isomorphic-unfetch": { + "version": "3.1.0", + "license": "MIT", + "dependencies": { + "node-fetch": "^2.6.1", + "unfetch": "^4.2.0" + } + }, + "node_modules/isstream": { + "version": "0.1.2", + "dev": true, + "license": "MIT" + }, + "node_modules/issue-parser": { + "version": "6.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "lodash.capitalize": "^4.2.1", + "lodash.escaperegexp": "^4.1.2", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.uniqby": "^4.7.0" + }, + "engines": { + "node": ">=10.13" + } + }, + "node_modules/jackspeak": { + "version": "2.2.1", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/java-properties": { + "version": "1.0.2", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/javascript-natural-sort": { + "version": "0.7.1", + "dev": true, + "license": "MIT" + }, + "node_modules/js-cookie": { + "version": "2.2.1", + "license": "MIT" + }, + "node_modules/js-sdsl": { + "version": "4.4.1", + "dev": true, + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/js-sdsl" + } + }, + "node_modules/js-sha3": { + "version": "0.8.0", + "license": "MIT" + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "dev": true, + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/js-yaml/node_modules/argparse": { + "version": "2.0.1", + "dev": true, + "license": "Python-2.0" + }, + "node_modules/jsbn": { + "version": "0.1.1", + "dev": true, + "license": "MIT" + }, + "node_modules/jsesc": { + "version": "2.5.2", + "dev": true, + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/json-parse-better-errors": { + "version": "1.0.2", + "dev": true, + "license": "MIT" + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "dev": true, + "license": "MIT" + }, + "node_modules/json-schema": { + "version": "0.4.0", + "dev": true, + "license": "(AFL-2.1 OR BSD-3-Clause)" + }, + "node_modules/json-schema-traverse": { + "version": "1.0.0", + "dev": true, + "license": "MIT" + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "dev": true, + "license": "MIT" + }, + "node_modules/json-stringify-nice": { + "version": "1.1.4", + "dev": true, + "license": "ISC", + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/json-stringify-safe": { + "version": "5.0.1", + "dev": true, + "license": "ISC" + }, + "node_modules/json5": { + "version": "2.2.3", + "dev": true, + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/jsonparse": { + "version": "1.3.1", + "dev": true, + "engines": [ + "node >= 0.2.0" + ], + "license": "MIT" + }, + "node_modules/jsonschema": { + "version": "1.4.1", + "dev": true, + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/JSONStream": { + "version": "1.3.5", + "dev": true, + "license": "(MIT OR Apache-2.0)", + "dependencies": { + "jsonparse": "^1.2.0", + "through": ">=2.2.7 <3" + }, + "bin": { + "JSONStream": "bin.js" + }, + "engines": { + "node": "*" + } + }, + "node_modules/jsprim": { + "version": "1.4.2", + "dev": true, + "license": "MIT", + "dependencies": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.4.0", + "verror": "1.10.0" + }, + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/just-diff": { + "version": "5.2.0", + "dev": true, + "license": "MIT" + }, + "node_modules/just-diff-apply": { + "version": "5.5.0", + "dev": true, + "license": "MIT" + }, + "node_modules/keccak": { + "version": "3.0.3", + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "node-addon-api": "^2.0.0", + "node-gyp-build": "^4.2.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/kind-of": { + "version": "6.0.3", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/klaw": { + "version": "1.3.1", + "dev": true, + "license": "MIT", + "optionalDependencies": { + "graceful-fs": "^4.1.9" + } + }, + "node_modules/lcid": { + "version": "1.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "invert-kv": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/level": { + "version": "8.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "browser-level": "^1.0.1", + "classic-level": "^1.2.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/level" + } + }, + "node_modules/level-supports": { + "version": "4.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + } + }, + "node_modules/level-transcoder": { + "version": "1.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer": "^6.0.3", + "module-error": "^1.0.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/libnpmaccess": { + "version": "6.0.4", + "dev": true, + "license": "ISC", + "dependencies": { + "aproba": "^2.0.0", + "minipass": "^3.1.1", + "npm-package-arg": "^9.0.1", + "npm-registry-fetch": "^13.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/libnpmdiff": { + "version": "4.0.5", + "dev": true, + "license": "ISC", + "dependencies": { + "@npmcli/disparity-colors": "^2.0.0", + "@npmcli/installed-package-contents": "^1.0.7", + "binary-extensions": "^2.2.0", + "diff": "^5.1.0", + "minimatch": "^5.0.1", + "npm-package-arg": "^9.0.1", + "pacote": "^13.6.1", + "tar": "^6.1.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/libnpmdiff/node_modules/minimatch": { + "version": "5.1.6", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/libnpmexec": { + "version": "4.0.14", + "dev": true, + "license": "ISC", + "dependencies": { + "@npmcli/arborist": "^5.6.3", + "@npmcli/ci-detect": "^2.0.0", + "@npmcli/fs": "^2.1.1", + "@npmcli/run-script": "^4.2.0", + "chalk": "^4.1.0", + "mkdirp-infer-owner": "^2.0.0", + "npm-package-arg": "^9.0.1", + "npmlog": "^6.0.2", + "pacote": "^13.6.1", + "proc-log": "^2.0.0", + "read": "^1.0.7", + "read-package-json-fast": "^2.0.2", + "semver": "^7.3.7", + "walk-up-path": "^1.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/libnpmfund": { + "version": "3.0.5", + "dev": true, + "license": "ISC", + "dependencies": { + "@npmcli/arborist": "^5.6.3" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/libnpmhook": { + "version": "8.0.4", + "dev": true, + "license": "ISC", + "dependencies": { + "aproba": "^2.0.0", + "npm-registry-fetch": "^13.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/libnpmorg": { + "version": "4.0.4", + "dev": true, + "license": "ISC", + "dependencies": { + "aproba": "^2.0.0", + "npm-registry-fetch": "^13.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/libnpmpack": { + "version": "4.1.3", + "dev": true, + "license": "ISC", + "dependencies": { + "@npmcli/run-script": "^4.1.3", + "npm-package-arg": "^9.0.1", + "pacote": "^13.6.1" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/libnpmpublish": { + "version": "6.0.5", + "dev": true, + "license": "ISC", + "dependencies": { + "normalize-package-data": "^4.0.0", + "npm-package-arg": "^9.0.1", + "npm-registry-fetch": "^13.0.0", + "semver": "^7.3.7", + "ssri": "^9.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/libnpmsearch": { + "version": "5.0.4", + "dev": true, + "license": "ISC", + "dependencies": { + "npm-registry-fetch": "^13.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/libnpmteam": { + "version": "4.0.4", + "dev": true, + "license": "ISC", + "dependencies": { + "aproba": "^2.0.0", + "npm-registry-fetch": "^13.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/libnpmversion": { + "version": "3.0.7", + "dev": true, + "license": "ISC", + "dependencies": { + "@npmcli/git": "^3.0.0", + "@npmcli/run-script": "^4.1.3", + "json-parse-even-better-errors": "^2.3.1", + "proc-log": "^2.0.0", + "semver": "^7.3.7" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "dev": true, + "license": "MIT" + }, + "node_modules/load-json-file": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.1.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/load-json-file/node_modules/parse-json": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/locate-path": { + "version": "5.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "license": "MIT" + }, + "node_modules/lodash.camelcase": { + "version": "4.3.0", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.capitalize": { + "version": "4.2.1", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.escaperegexp": { + "version": "4.1.2", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.isequal": { + "version": "4.5.0", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.isequalwith": { + "version": "4.4.0", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.isfunction": { + "version": "3.0.9", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.ismatch": { + "version": "4.4.0", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.isstring": { + "version": "4.0.1", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.kebabcase": { + "version": "4.1.1", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.mergewith": { + "version": "4.6.2", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.snakecase": { + "version": "4.1.1", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.startcase": { + "version": "4.4.0", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.truncate": { + "version": "4.4.2", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.uniq": { + "version": "4.5.0", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.uniqby": { + "version": "4.7.0", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.upperfirst": { + "version": "4.3.1", + "dev": true, + "license": "MIT" + }, + "node_modules/log-symbols": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^2.4.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/log-symbols/node_modules/ansi-styles": { + "version": "3.2.1", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/log-symbols/node_modules/chalk": { + "version": "2.4.2", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/log-symbols/node_modules/color-convert": { + "version": "1.9.3", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/log-symbols/node_modules/color-name": { + "version": "1.1.3", + "dev": true, + "license": "MIT" + }, + "node_modules/log-symbols/node_modules/has-flag": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/log-symbols/node_modules/supports-color": { + "version": "5.5.0", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/loupe": { + "version": "2.3.6", + "dev": true, + "license": "MIT", + "dependencies": { + "get-func-name": "^2.0.0" + } + }, + "node_modules/lru_map": { + "version": "0.3.3", + "dev": true, + "license": "MIT" + }, + "node_modules/lru-cache": { + "version": "7.18.3", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/magic-string": { + "version": "0.30.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.4.15" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/make-error": { + "version": "1.3.6", + "dev": true, + "license": "ISC" + }, + "node_modules/make-fetch-happen": { + "version": "10.2.1", + "dev": true, + "license": "ISC", + "dependencies": { + "agentkeepalive": "^4.2.1", + "cacache": "^16.1.0", + "http-cache-semantics": "^4.1.0", + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.0", + "is-lambda": "^1.0.1", + "lru-cache": "^7.7.1", + "minipass": "^3.1.6", + "minipass-collect": "^1.0.2", + "minipass-fetch": "^2.0.3", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^0.6.3", + "promise-retry": "^2.0.1", + "socks-proxy-agent": "^7.0.0", + "ssri": "^9.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/map-obj": { + "version": "4.3.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/markdown-table": { + "version": "1.1.3", + "dev": true, + "license": "MIT" + }, + "node_modules/marked": { + "version": "4.3.0", + "dev": true, + "license": "MIT", + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 12" + } + }, + "node_modules/marked-terminal": { + "version": "5.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-escapes": "^6.2.0", + "cardinal": "^2.1.1", + "chalk": "^5.2.0", + "cli-table3": "^0.6.3", + "node-emoji": "^1.11.0", + "supports-hyperlinks": "^2.3.0" + }, + "engines": { + "node": ">=14.13.1 || >=16.0.0" + }, + "peerDependencies": { + "marked": "^1.0.0 || ^2.0.0 || ^3.0.0 || ^4.0.0 || ^5.0.0" + } + }, + "node_modules/marked-terminal/node_modules/ansi-escapes": { + "version": "6.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "type-fest": "^3.0.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/marked-terminal/node_modules/chalk": { + "version": "5.3.0", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/marked-terminal/node_modules/type-fest": { + "version": "3.13.0", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/match-all": { + "version": "1.2.6", + "license": "MIT" + }, + "node_modules/mcl-wasm": { + "version": "0.7.9", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=8.9.0" + } + }, + "node_modules/md5.js": { + "version": "1.3.5", + "license": "MIT", + "dependencies": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "node_modules/mem": { + "version": "1.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-fn": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mem/node_modules/mimic-fn": { + "version": "1.2.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/memory-level": { + "version": "1.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "abstract-level": "^1.0.0", + "functional-red-black-tree": "^1.0.1", + "module-error": "^1.0.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/memorystream": { + "version": "0.3.1", + "dev": true, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/meow": { + "version": "8.1.2", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/minimist": "^1.2.0", + "camelcase-keys": "^6.2.2", + "decamelize-keys": "^1.1.0", + "hard-rejection": "^2.1.0", + "minimist-options": "4.1.0", + "normalize-package-data": "^3.0.0", + "read-pkg-up": "^7.0.1", + "redent": "^3.0.0", + "trim-newlines": "^3.0.0", + "type-fest": "^0.18.0", + "yargs-parser": "^20.2.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/meow/node_modules/hosted-git-info": { + "version": "4.1.0", + "dev": true, + "license": "ISC", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/meow/node_modules/lru-cache": { + "version": "6.0.0", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/meow/node_modules/normalize-package-data": { + "version": "3.0.3", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "hosted-git-info": "^4.0.1", + "is-core-module": "^2.5.0", + "semver": "^7.3.4", + "validate-npm-package-license": "^3.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/meow/node_modules/type-fest": { + "version": "0.18.1", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/meow/node_modules/yargs-parser": { + "version": "20.2.9", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "dev": true, + "license": "MIT" + }, + "node_modules/merge2": { + "version": "1.4.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.5", + "dev": true, + "license": "MIT", + "dependencies": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/min-indent": { + "version": "1.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/minimalistic-assert": { + "version": "1.0.1", + "license": "ISC" + }, + "node_modules/minimalistic-crypto-utils": { + "version": "1.0.1", + "license": "MIT" + }, + "node_modules/minimatch": { + "version": "3.1.2", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimatch/node_modules/brace-expansion": { + "version": "1.1.11", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minimist-options": { + "version": "4.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "arrify": "^1.0.1", + "is-plain-obj": "^1.1.0", + "kind-of": "^6.0.3" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/minipass": { + "version": "3.3.6", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-collect": { + "version": "1.0.2", + "dev": true, + "license": "ISC", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minipass-fetch": { + "version": "2.1.2", + "dev": true, + "license": "MIT", + "dependencies": { + "minipass": "^3.1.6", + "minipass-sized": "^1.0.3", + "minizlib": "^2.1.2" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + }, + "optionalDependencies": { + "encoding": "^0.1.13" + } + }, + "node_modules/minipass-flush": { + "version": "1.0.5", + "dev": true, + "license": "ISC", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minipass-json-stream": { + "version": "1.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "jsonparse": "^1.3.1", + "minipass": "^3.0.0" + } + }, + "node_modules/minipass-pipeline": { + "version": "1.2.4", + "dev": true, + "license": "ISC", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-sized": { + "version": "1.0.3", + "dev": true, + "license": "ISC", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minizlib": { + "version": "2.1.2", + "dev": true, + "license": "MIT", + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/mkdirp": { + "version": "1.0.4", + "dev": true, + "license": "MIT", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/mkdirp-infer-owner": { + "version": "2.0.0", + "dev": true, + "license": "ISC", + "dependencies": { + "chownr": "^2.0.0", + "infer-owner": "^1.0.4", + "mkdirp": "^1.0.3" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/mnemonist": { + "version": "0.38.5", + "dev": true, + "license": "MIT", + "dependencies": { + "obliterator": "^2.0.0" + } + }, + "node_modules/mocha": { + "version": "10.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-colors": "4.1.1", + "browser-stdout": "1.3.1", + "chokidar": "3.5.3", + "debug": "4.3.4", + "diff": "5.0.0", + "escape-string-regexp": "4.0.0", + "find-up": "5.0.0", + "glob": "7.2.0", + "he": "1.2.0", + "js-yaml": "4.1.0", + "log-symbols": "4.1.0", + "minimatch": "5.0.1", + "ms": "2.1.3", + "nanoid": "3.3.3", + "serialize-javascript": "6.0.0", + "strip-json-comments": "3.1.1", + "supports-color": "8.1.1", + "workerpool": "6.2.1", + "yargs": "16.2.0", + "yargs-parser": "20.2.4", + "yargs-unparser": "2.0.0" + }, + "bin": { + "_mocha": "bin/_mocha", + "mocha": "bin/mocha.js" + }, + "engines": { + "node": ">= 14.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mochajs" + } + }, + "node_modules/mocha/node_modules/ansi-colors": { + "version": "4.1.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/mocha/node_modules/camelcase": { + "version": "6.3.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mocha/node_modules/cliui": { + "version": "7.0.4", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "node_modules/mocha/node_modules/debug": { + "version": "4.3.4", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/mocha/node_modules/debug/node_modules/ms": { + "version": "2.1.2", + "dev": true, + "license": "MIT" + }, + "node_modules/mocha/node_modules/decamelize": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mocha/node_modules/diff": { + "version": "5.0.0", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/mocha/node_modules/escape-string-regexp": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mocha/node_modules/find-up": { + "version": "5.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mocha/node_modules/glob": { + "version": "7.2.0", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/mocha/node_modules/glob/node_modules/brace-expansion": { + "version": "1.1.11", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/mocha/node_modules/glob/node_modules/minimatch": { + "version": "3.1.2", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/mocha/node_modules/is-plain-obj": { + "version": "2.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/mocha/node_modules/locate-path": { + "version": "6.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mocha/node_modules/log-symbols": { + "version": "4.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mocha/node_modules/minimatch": { + "version": "5.0.1", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/mocha/node_modules/p-limit": { + "version": "3.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mocha/node_modules/p-locate": { + "version": "5.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mocha/node_modules/supports-color": { + "version": "8.1.1", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/mocha/node_modules/yargs": { + "version": "16.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/mocha/node_modules/yargs-parser": { + "version": "20.2.4", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/mocha/node_modules/yargs-unparser": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "camelcase": "^6.0.0", + "decamelize": "^4.0.0", + "flat": "^5.0.2", + "is-plain-obj": "^2.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/mocha/node_modules/yargs/node_modules/yargs-parser": { + "version": "20.2.9", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/modify-values": { + "version": "1.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/module-alias": { + "version": "2.2.3", + "license": "MIT" + }, + "node_modules/module-error": { + "version": "1.0.2", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "dev": true, + "license": "MIT" + }, + "node_modules/murmur-128": { + "version": "0.2.1", + "license": "MIT", + "dependencies": { + "encode-utf8": "^1.0.2", + "fmix": "^0.1.0", + "imul": "^1.0.0" + } + }, + "node_modules/mute-stream": { + "version": "0.0.8", + "dev": true, + "license": "ISC" + }, + "node_modules/nanoid": { + "version": "3.3.3", + "dev": true, + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/napi-macros": { + "version": "2.2.2", + "dev": true, + "license": "MIT" + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "dev": true, + "license": "MIT" + }, + "node_modules/natural-compare-lite": { + "version": "1.4.0", + "dev": true, + "license": "MIT" + }, + "node_modules/negotiator": { + "version": "0.6.3", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/neo-async": { + "version": "2.6.2", + "dev": true, + "license": "MIT" + }, + "node_modules/nerf-dart": { + "version": "1.0.0", + "dev": true, + "license": "MIT" + }, + "node_modules/node-addon-api": { + "version": "2.0.2", + "license": "MIT" + }, + "node_modules/node-emoji": { + "version": "1.11.0", + "dev": true, + "license": "MIT", + "dependencies": { + "lodash": "^4.17.21" + } + }, + "node_modules/node-environment-flags": { + "version": "1.0.6", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "object.getownpropertydescriptors": "^2.0.3", + "semver": "^5.7.0" + } + }, + "node_modules/node-environment-flags/node_modules/semver": { + "version": "5.7.1", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/node-fetch": { + "version": "2.6.12", + "license": "MIT", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/node-gyp": { + "version": "9.4.0", + "dev": true, + "license": "MIT", + "dependencies": { + "env-paths": "^2.2.0", + "exponential-backoff": "^3.1.1", + "glob": "^7.1.4", + "graceful-fs": "^4.2.6", + "make-fetch-happen": "^11.0.3", + "nopt": "^6.0.0", + "npmlog": "^6.0.0", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.2", + "which": "^2.0.2" + }, + "bin": { + "node-gyp": "bin/node-gyp.js" + }, + "engines": { + "node": "^12.13 || ^14.13 || >=16" + } + }, + "node_modules/node-gyp-build": { + "version": "4.6.0", + "license": "MIT", + "bin": { + "node-gyp-build": "bin.js", + "node-gyp-build-optional": "optional.js", + "node-gyp-build-test": "build-test.js" + } + }, + "node_modules/node-gyp/node_modules/@npmcli/fs": { + "version": "3.1.0", + "dev": true, + "license": "ISC", + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/node-gyp/node_modules/cacache": { + "version": "17.1.3", + "dev": true, + "license": "ISC", + "dependencies": { + "@npmcli/fs": "^3.1.0", + "fs-minipass": "^3.0.0", + "glob": "^10.2.2", + "lru-cache": "^7.7.1", + "minipass": "^5.0.0", + "minipass-collect": "^1.0.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "p-map": "^4.0.0", + "ssri": "^10.0.0", + "tar": "^6.1.11", + "unique-filename": "^3.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/node-gyp/node_modules/cacache/node_modules/glob": { + "version": "10.3.3", + "dev": true, + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^2.0.3", + "minimatch": "^9.0.1", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", + "path-scurry": "^1.10.1" + }, + "bin": { + "glob": "dist/cjs/src/bin.js" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/node-gyp/node_modules/cacache/node_modules/glob/node_modules/minipass": { + "version": "7.0.1", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/node-gyp/node_modules/fs-minipass": { + "version": "3.0.2", + "dev": true, + "license": "ISC", + "dependencies": { + "minipass": "^5.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/node-gyp/node_modules/make-fetch-happen": { + "version": "11.1.1", + "dev": true, + "license": "ISC", + "dependencies": { + "agentkeepalive": "^4.2.1", + "cacache": "^17.0.0", + "http-cache-semantics": "^4.1.1", + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.0", + "is-lambda": "^1.0.1", + "lru-cache": "^7.7.1", + "minipass": "^5.0.0", + "minipass-fetch": "^3.0.0", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^0.6.3", + "promise-retry": "^2.0.1", + "socks-proxy-agent": "^7.0.0", + "ssri": "^10.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/node-gyp/node_modules/minimatch": { + "version": "9.0.3", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/node-gyp/node_modules/minipass": { + "version": "5.0.0", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=8" + } + }, + "node_modules/node-gyp/node_modules/minipass-fetch": { + "version": "3.0.3", + "dev": true, + "license": "MIT", + "dependencies": { + "minipass": "^5.0.0", + "minipass-sized": "^1.0.3", + "minizlib": "^2.1.2" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + }, + "optionalDependencies": { + "encoding": "^0.1.13" + } + }, + "node_modules/node-gyp/node_modules/ssri": { + "version": "10.0.4", + "dev": true, + "license": "ISC", + "dependencies": { + "minipass": "^5.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/node-releases": { + "version": "2.0.13", + "dev": true, + "license": "MIT" + }, + "node_modules/nofilter": { + "version": "3.1.0", + "license": "MIT", + "engines": { + "node": ">=12.19" + } + }, + "node_modules/nopt": { + "version": "6.0.0", + "dev": true, + "license": "ISC", + "dependencies": { + "abbrev": "^1.0.0" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/normalize-package-data": { + "version": "4.0.1", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "hosted-git-info": "^5.0.0", + "is-core-module": "^2.8.1", + "semver": "^7.3.5", + "validate-npm-package-license": "^3.0.4" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/normalize-url": { + "version": "6.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm": { + "version": "8.19.4", + "bundleDependencies": [ + "@isaacs/string-locale-compare", + "@npmcli/arborist", + "@npmcli/ci-detect", + "@npmcli/config", + "@npmcli/fs", + "@npmcli/map-workspaces", + "@npmcli/package-json", + "@npmcli/run-script", + "abbrev", + "archy", + "cacache", + "chalk", + "chownr", + "cli-columns", + "cli-table3", + "columnify", + "fastest-levenshtein", + "fs-minipass", + "glob", + "graceful-fs", + "hosted-git-info", + "ini", + "init-package-json", + "is-cidr", + "json-parse-even-better-errors", + "libnpmaccess", + "libnpmdiff", + "libnpmexec", + "libnpmfund", + "libnpmhook", + "libnpmorg", + "libnpmpack", + "libnpmpublish", + "libnpmsearch", + "libnpmteam", + "libnpmversion", + "make-fetch-happen", + "minimatch", + "minipass", + "minipass-pipeline", + "mkdirp", + "mkdirp-infer-owner", + "ms", + "node-gyp", + "nopt", + "npm-audit-report", + "npm-install-checks", + "npm-package-arg", + "npm-pick-manifest", + "npm-profile", + "npm-registry-fetch", + "npm-user-validate", + "npmlog", + "opener", + "p-map", + "pacote", + "parse-conflict-json", + "proc-log", + "qrcode-terminal", + "read", + "read-package-json", + "read-package-json-fast", + "readdir-scoped-modules", + "rimraf", + "semver", + "ssri", + "tar", + "text-table", + "tiny-relative-date", + "treeverse", + "validate-npm-package-name", + "which", + "write-file-atomic" + ], + "dev": true, + "license": "Artistic-2.0", + "workspaces": [ + "docs", + "smoke-tests", + "workspaces/*" + ], + "dependencies": { + "@isaacs/string-locale-compare": "^1.1.0", + "@npmcli/arborist": "^5.6.3", + "@npmcli/ci-detect": "^2.0.0", + "@npmcli/config": "^4.2.1", + "@npmcli/fs": "^2.1.0", + "@npmcli/map-workspaces": "^2.0.3", + "@npmcli/package-json": "^2.0.0", + "@npmcli/run-script": "^4.2.1", + "abbrev": "~1.1.1", + "archy": "~1.0.0", + "cacache": "^16.1.3", + "chalk": "^4.1.2", + "chownr": "^2.0.0", + "cli-columns": "^4.0.0", + "cli-table3": "^0.6.2", + "columnify": "^1.6.0", + "fastest-levenshtein": "^1.0.12", + "fs-minipass": "^2.1.0", + "glob": "^8.0.1", + "graceful-fs": "^4.2.10", + "hosted-git-info": "^5.2.1", + "ini": "^3.0.1", + "init-package-json": "^3.0.2", + "is-cidr": "^4.0.2", + "json-parse-even-better-errors": "^2.3.1", + "libnpmaccess": "^6.0.4", + "libnpmdiff": "^4.0.5", + "libnpmexec": "^4.0.14", + "libnpmfund": "^3.0.5", + "libnpmhook": "^8.0.4", + "libnpmorg": "^4.0.4", + "libnpmpack": "^4.1.3", + "libnpmpublish": "^6.0.5", + "libnpmsearch": "^5.0.4", + "libnpmteam": "^4.0.4", + "libnpmversion": "^3.0.7", + "make-fetch-happen": "^10.2.0", + "minimatch": "^5.1.0", + "minipass": "^3.1.6", + "minipass-pipeline": "^1.2.4", + "mkdirp": "^1.0.4", + "mkdirp-infer-owner": "^2.0.0", + "ms": "^2.1.2", + "node-gyp": "^9.1.0", + "nopt": "^6.0.0", + "npm-audit-report": "^3.0.0", + "npm-install-checks": "^5.0.0", + "npm-package-arg": "^9.1.0", + "npm-pick-manifest": "^7.0.2", + "npm-profile": "^6.2.0", + "npm-registry-fetch": "^13.3.1", + "npm-user-validate": "^1.0.1", + "npmlog": "^6.0.2", + "opener": "^1.5.2", + "p-map": "^4.0.0", + "pacote": "^13.6.2", + "parse-conflict-json": "^2.0.2", + "proc-log": "^2.0.1", + "qrcode-terminal": "^0.12.0", + "read": "~1.0.7", + "read-package-json": "^5.0.2", + "read-package-json-fast": "^2.0.3", + "readdir-scoped-modules": "^1.1.0", + "rimraf": "^3.0.2", + "semver": "^7.3.7", + "ssri": "^9.0.1", + "tar": "^6.1.11", + "text-table": "~0.2.0", + "tiny-relative-date": "^1.3.0", + "treeverse": "^2.0.0", + "validate-npm-package-name": "^4.0.0", + "which": "^2.0.2", + "write-file-atomic": "^4.0.1" + }, + "bin": { + "npm": "bin/npm-cli.js", + "npx": "bin/npx-cli.js" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/npm-audit-report": { + "version": "3.0.0", + "dev": true, + "license": "ISC", + "dependencies": { + "chalk": "^4.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/npm-bundled": { + "version": "1.1.2", + "dev": true, + "license": "ISC", + "dependencies": { + "npm-normalize-package-bin": "^1.0.1" + } + }, + "node_modules/npm-bundled/node_modules/npm-normalize-package-bin": { + "version": "1.0.1", + "dev": true, + "license": "ISC" + }, + "node_modules/npm-install-checks": { + "version": "5.0.0", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "semver": "^7.1.1" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/npm-normalize-package-bin": { + "version": "2.0.0", + "dev": true, + "license": "ISC", + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/npm-package-arg": { + "version": "9.1.2", + "dev": true, + "license": "ISC", + "dependencies": { + "hosted-git-info": "^5.0.0", + "proc-log": "^2.0.1", + "semver": "^7.3.5", + "validate-npm-package-name": "^4.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/npm-packlist": { + "version": "5.1.3", + "dev": true, + "license": "ISC", + "dependencies": { + "glob": "^8.0.1", + "ignore-walk": "^5.0.1", + "npm-bundled": "^2.0.0", + "npm-normalize-package-bin": "^2.0.0" + }, + "bin": { + "npm-packlist": "bin/index.js" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/npm-packlist/node_modules/glob": { + "version": "8.1.0", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/npm-packlist/node_modules/minimatch": { + "version": "5.1.6", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/npm-packlist/node_modules/npm-bundled": { + "version": "2.0.1", + "dev": true, + "license": "ISC", + "dependencies": { + "npm-normalize-package-bin": "^2.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/npm-pick-manifest": { + "version": "7.0.2", + "dev": true, + "license": "ISC", + "dependencies": { + "npm-install-checks": "^5.0.0", + "npm-normalize-package-bin": "^2.0.0", + "npm-package-arg": "^9.0.0", + "semver": "^7.3.5" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/npm-profile": { + "version": "6.2.1", + "dev": true, + "license": "ISC", + "dependencies": { + "npm-registry-fetch": "^13.0.1", + "proc-log": "^2.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/npm-registry-fetch": { + "version": "13.3.1", + "dev": true, + "license": "ISC", + "dependencies": { + "make-fetch-happen": "^10.0.6", + "minipass": "^3.1.6", + "minipass-fetch": "^2.0.3", + "minipass-json-stream": "^1.0.1", + "minizlib": "^2.1.2", + "npm-package-arg": "^9.0.1", + "proc-log": "^2.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/npm-run-path": { + "version": "4.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npm-user-validate": { + "version": "1.0.1", + "dev": true, + "license": "BSD-2-Clause" + }, + "node_modules/npm/node_modules/glob": { + "version": "8.1.0", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/npm/node_modules/ini": { + "version": "3.0.1", + "dev": true, + "inBundle": true, + "license": "ISC", + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/npm/node_modules/minimatch": { + "version": "5.1.6", + "dev": true, + "inBundle": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/npmlog": { + "version": "6.0.2", + "dev": true, + "license": "ISC", + "dependencies": { + "are-we-there-yet": "^3.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^4.0.3", + "set-blocking": "^2.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/number-is-nan": { + "version": "1.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/number-to-bn": { + "version": "1.7.0", + "dev": true, + "license": "MIT", + "dependencies": { + "bn.js": "4.11.6", + "strip-hex-prefix": "1.0.0" + }, + "engines": { + "node": ">=6.5.0", + "npm": ">=3" + } + }, + "node_modules/number-to-bn/node_modules/bn.js": { + "version": "4.11.6", + "dev": true, + "license": "MIT" + }, + "node_modules/oauth-sign": { + "version": "0.9.0", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "*" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.12.3", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "define-properties": "^1.1.2", + "function-bind": "^1.1.1", + "has-symbols": "^1.0.0", + "object-keys": "^1.0.11" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.getownpropertydescriptors": { + "version": "2.1.6", + "dev": true, + "license": "MIT", + "dependencies": { + "array.prototype.reduce": "^1.0.5", + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.21.2", + "safe-array-concat": "^1.0.0" + }, + "engines": { + "node": ">= 0.8" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.values": { + "version": "1.1.6", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/obliterator": { + "version": "2.0.4", + "dev": true, + "license": "MIT" + }, + "node_modules/once": { + "version": "1.4.0", + "dev": true, + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "5.1.2", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/opener": { + "version": "1.5.2", + "dev": true, + "license": "(WTFPL OR MIT)", + "bin": { + "opener": "bin/opener-bin.js" + } + }, + "node_modules/optionator": { + "version": "0.9.3", + "dev": true, + "license": "MIT", + "dependencies": { + "@aashutoshrathi/word-wrap": "^1.2.3", + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/ordinal": { + "version": "1.0.3", + "dev": true, + "license": "MIT" + }, + "node_modules/os-locale": { + "version": "2.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "execa": "^0.7.0", + "lcid": "^1.0.0", + "mem": "^1.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/os-locale/node_modules/cross-spawn": { + "version": "5.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "lru-cache": "^4.0.1", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "node_modules/os-locale/node_modules/execa": { + "version": "0.7.0", + "dev": true, + "license": "MIT", + "dependencies": { + "cross-spawn": "^5.0.1", + "get-stream": "^3.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/os-locale/node_modules/get-stream": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/os-locale/node_modules/is-stream": { + "version": "1.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/os-locale/node_modules/lru-cache": { + "version": "4.1.5", + "dev": true, + "license": "ISC", + "dependencies": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "node_modules/os-locale/node_modules/npm-run-path": { + "version": "2.0.2", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/os-locale/node_modules/path-key": { + "version": "2.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/os-locale/node_modules/shebang-command": { + "version": "1.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/os-locale/node_modules/shebang-regex": { + "version": "1.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/os-locale/node_modules/which": { + "version": "1.3.1", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/os-locale/node_modules/yallist": { + "version": "2.1.2", + "dev": true, + "license": "ISC" + }, + "node_modules/os-tmpdir": { + "version": "1.0.2", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/p-each-series": { + "version": "2.2.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-filter": { + "version": "2.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "p-map": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-filter/node_modules/p-map": { + "version": "2.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/p-finally": { + "version": "1.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/p-is-promise": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/p-limit": { + "version": "2.3.0", + "dev": true, + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "4.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-map": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "aggregate-error": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-reduce": { + "version": "2.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/pacote": { + "version": "13.6.2", + "dev": true, + "license": "ISC", + "dependencies": { + "@npmcli/git": "^3.0.0", + "@npmcli/installed-package-contents": "^1.0.7", + "@npmcli/promise-spawn": "^3.0.0", + "@npmcli/run-script": "^4.1.0", + "cacache": "^16.0.0", + "chownr": "^2.0.0", + "fs-minipass": "^2.1.0", + "infer-owner": "^1.0.4", + "minipass": "^3.1.6", + "mkdirp": "^1.0.4", + "npm-package-arg": "^9.0.0", + "npm-packlist": "^5.1.0", + "npm-pick-manifest": "^7.0.0", + "npm-registry-fetch": "^13.0.1", + "proc-log": "^2.0.0", + "promise-retry": "^2.0.1", + "read-package-json": "^5.0.0", + "read-package-json-fast": "^2.0.3", + "rimraf": "^3.0.2", + "ssri": "^9.0.0", + "tar": "^6.1.11" + }, + "bin": { + "pacote": "lib/bin.js" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-cache-control": { + "version": "1.0.1", + "dev": true + }, + "node_modules/parse-conflict-json": { + "version": "2.0.2", + "dev": true, + "license": "ISC", + "dependencies": { + "json-parse-even-better-errors": "^2.3.1", + "just-diff": "^5.0.1", + "just-diff-apply": "^5.2.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/parse-json": { + "version": "5.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "dev": true, + "license": "MIT" + }, + "node_modules/path-scurry": { + "version": "1.10.1", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^9.1.1 || ^10.0.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "10.0.0", + "dev": true, + "license": "ISC", + "engines": { + "node": "14 || >=16.14" + } + }, + "node_modules/path-scurry/node_modules/minipass": { + "version": "7.0.1", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/path-type": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/pathval": { + "version": "1.1.1", + "dev": true, + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/pbkdf2": { + "version": "3.1.2", + "license": "MIT", + "dependencies": { + "create-hash": "^1.1.2", + "create-hmac": "^1.1.4", + "ripemd160": "^2.0.1", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + }, + "engines": { + "node": ">=0.12" + } + }, + "node_modules/pegjs": { + "version": "0.10.0", + "dev": true, + "license": "MIT", + "bin": { + "pegjs": "bin/pegjs" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/performance-now": { + "version": "2.1.0", + "dev": true, + "license": "MIT" + }, + "node_modules/picocolors": { + "version": "1.0.0", + "dev": true, + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pify": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/pkg-conf": { + "version": "2.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "find-up": "^2.0.0", + "load-json-file": "^4.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/pluralize": { + "version": "8.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss": { + "version": "8.4.25", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.6", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.0.13", + "dev": true, + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss/node_modules/nanoid": { + "version": "3.3.6", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prettier": { + "version": "2.7.1", + "dev": true, + "license": "MIT", + "bin": { + "prettier": "bin-prettier.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/prettier-linter-helpers": { + "version": "1.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-diff": "^1.1.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/prettier-plugin-solidity": { + "version": "1.1.3", + "dev": true, + "license": "MIT", + "dependencies": { + "@solidity-parser/parser": "^0.16.0", + "semver": "^7.3.8", + "solidity-comments-extractor": "^0.0.7" + }, + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "prettier": ">=2.3.0 || >=3.0.0-alpha.0" + } + }, + "node_modules/prettier-plugin-solidity/node_modules/@solidity-parser/parser": { + "version": "0.16.0", + "dev": true, + "license": "MIT", + "dependencies": { + "antlr4ts": "^0.5.0-alpha.4" + } + }, + "node_modules/proc-log": { + "version": "2.0.1", + "dev": true, + "license": "ISC", + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "dev": true, + "license": "MIT" + }, + "node_modules/progress": { + "version": "2.0.3", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/promise": { + "version": "8.3.0", + "dev": true, + "license": "MIT", + "dependencies": { + "asap": "~2.0.6" + } + }, + "node_modules/promise-all-reject-late": { + "version": "1.0.1", + "dev": true, + "license": "ISC", + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/promise-call-limit": { + "version": "1.0.2", + "dev": true, + "license": "ISC", + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/promise-inflight": { + "version": "1.0.1", + "dev": true, + "license": "ISC" + }, + "node_modules/promise-retry": { + "version": "2.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "err-code": "^2.0.2", + "retry": "^0.12.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/promzard": { + "version": "0.3.0", + "dev": true, + "license": "ISC", + "dependencies": { + "read": "1" + } + }, + "node_modules/proper-lockfile": { + "version": "4.1.2", + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.4", + "retry": "^0.12.0", + "signal-exit": "^3.0.2" + } + }, + "node_modules/proto-list": { + "version": "1.2.4", + "dev": true, + "license": "ISC" + }, + "node_modules/pseudomap": { + "version": "1.0.2", + "dev": true, + "license": "ISC" + }, + "node_modules/psl": { + "version": "1.9.0", + "dev": true, + "license": "MIT" + }, + "node_modules/punycode": { + "version": "2.3.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/q": { + "version": "1.5.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.6.0", + "teleport": ">=0.2.0" + } + }, + "node_modules/qrcode-terminal": { + "version": "0.12.0", + "dev": true, + "bin": { + "qrcode-terminal": "bin/qrcode-terminal.js" + } + }, + "node_modules/qs": { + "version": "6.11.2", + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/quick-lru": { + "version": "4.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/randombytes": { + "version": "2.1.0", + "license": "MIT", + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/raw-body": { + "version": "2.5.2", + "dev": true, + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/raw-body/node_modules/iconv-lite": { + "version": "0.4.24", + "dev": true, + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/rc": { + "version": "1.2.8", + "dev": true, + "license": "(BSD-2-Clause OR MIT OR Apache-2.0)", + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/rc/node_modules/strip-json-comments": { + "version": "2.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/read": { + "version": "1.0.7", + "dev": true, + "license": "ISC", + "dependencies": { + "mute-stream": "~0.0.4" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/read-cmd-shim": { + "version": "3.0.1", + "dev": true, + "license": "ISC", + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/read-package-json": { + "version": "5.0.2", + "dev": true, + "license": "ISC", + "dependencies": { + "glob": "^8.0.1", + "json-parse-even-better-errors": "^2.3.1", + "normalize-package-data": "^4.0.0", + "npm-normalize-package-bin": "^2.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/read-package-json-fast": { + "version": "2.0.3", + "dev": true, + "license": "ISC", + "dependencies": { + "json-parse-even-better-errors": "^2.3.0", + "npm-normalize-package-bin": "^1.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/read-package-json-fast/node_modules/npm-normalize-package-bin": { + "version": "1.0.1", + "dev": true, + "license": "ISC" + }, + "node_modules/read-package-json/node_modules/glob": { + "version": "8.1.0", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/read-package-json/node_modules/minimatch": { + "version": "5.1.6", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/read-pkg": { + "version": "5.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/normalize-package-data": "^2.4.0", + "normalize-package-data": "^2.5.0", + "parse-json": "^5.0.0", + "type-fest": "^0.6.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/read-pkg-up": { + "version": "7.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "find-up": "^4.1.0", + "read-pkg": "^5.2.0", + "type-fest": "^0.8.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-pkg-up/node_modules/find-up": { + "version": "4.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/read-pkg-up/node_modules/type-fest": { + "version": "0.8.1", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=8" + } + }, + "node_modules/read-pkg/node_modules/hosted-git-info": { + "version": "2.8.9", + "dev": true, + "license": "ISC" + }, + "node_modules/read-pkg/node_modules/normalize-package-data": { + "version": "2.5.0", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "node_modules/read-pkg/node_modules/semver": { + "version": "5.7.1", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/readdir-scoped-modules": { + "version": "1.1.0", + "dev": true, + "license": "ISC", + "dependencies": { + "debuglog": "^1.0.1", + "dezalgo": "^1.0.0", + "graceful-fs": "^4.1.2", + "once": "^1.3.0" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "license": "MIT", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/rechoir": { + "version": "0.6.2", + "dev": true, + "dependencies": { + "resolve": "^1.1.6" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/recursive-readdir": { + "version": "2.2.3", + "dev": true, + "license": "MIT", + "dependencies": { + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/redent": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "indent-string": "^4.0.0", + "strip-indent": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/redeyed": { + "version": "2.1.1", + "dev": true, + "license": "MIT", + "dependencies": { + "esprima": "~4.0.0" + } + }, + "node_modules/regexp.prototype.flags": { + "version": "1.5.0", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "functions-have-names": "^1.2.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/regexpp": { + "version": "3.2.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + } + }, + "node_modules/registry-auth-token": { + "version": "5.0.2", + "dev": true, + "license": "MIT", + "dependencies": { + "@pnpm/npm-conf": "^2.1.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/req-cwd": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "req-from": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/req-from": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "resolve-from": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/req-from/node_modules/resolve-from": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/request": { + "version": "2.88.2", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.3", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.5.0", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/request-promise-core": { + "version": "1.1.4", + "dev": true, + "license": "ISC", + "dependencies": { + "lodash": "^4.17.19" + }, + "engines": { + "node": ">=0.10.0" + }, + "peerDependencies": { + "request": "^2.34" + } + }, + "node_modules/request-promise-native": { + "version": "1.0.9", + "dev": true, + "license": "ISC", + "dependencies": { + "request-promise-core": "1.1.4", + "stealthy-require": "^1.1.1", + "tough-cookie": "^2.3.3" + }, + "engines": { + "node": ">=0.12.0" + }, + "peerDependencies": { + "request": "^2.34" + } + }, + "node_modules/request/node_modules/form-data": { + "version": "2.3.3", + "dev": true, + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 0.12" + } + }, + "node_modules/request/node_modules/qs": { + "version": "6.5.3", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/request/node_modules/uuid": { + "version": "3.4.0", + "dev": true, + "license": "MIT", + "bin": { + "uuid": "bin/uuid" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-main-filename": { + "version": "1.0.1", + "dev": true, + "license": "ISC" + }, + "node_modules/resolve": { + "version": "1.22.3", + "dev": true, + "license": "MIT", + "dependencies": { + "is-core-module": "^2.12.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-from": { + "version": "5.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-global": { + "version": "1.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "global-dirs": "^0.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/retry": { + "version": "0.12.0", + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "dev": true, + "license": "ISC", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/ripemd160": { + "version": "2.0.2", + "license": "MIT", + "dependencies": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1" + } + }, + "node_modules/rlp": { + "version": "2.2.7", + "license": "MPL-2.0", + "dependencies": { + "bn.js": "^5.2.0" + }, + "bin": { + "rlp": "bin/rlp" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/run-parallel-limit": { + "version": "1.1.0", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/rustbn.js": { + "version": "0.2.0", + "dev": true, + "license": "(MIT OR Apache-2.0)" + }, + "node_modules/rxjs": { + "version": "7.8.1", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/rxjs/node_modules/tslib": { + "version": "2.6.0", + "dev": true, + "license": "0BSD" + }, + "node_modules/safe-array-concat": { + "version": "1.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.0", + "has-symbols": "^1.0.3", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-array-concat/node_modules/isarray": { + "version": "2.0.5", + "dev": true, + "license": "MIT" + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/safe-regex-test": { + "version": "1.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.3", + "is-regex": "^1.1.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "dev": true, + "license": "MIT" + }, + "node_modules/sc-istanbul": { + "version": "0.4.6", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "abbrev": "1.0.x", + "async": "1.x", + "escodegen": "1.8.x", + "esprima": "2.7.x", + "glob": "^5.0.15", + "handlebars": "^4.0.1", + "js-yaml": "3.x", + "mkdirp": "0.5.x", + "nopt": "3.x", + "once": "1.x", + "resolve": "1.1.x", + "supports-color": "^3.1.0", + "which": "^1.1.1", + "wordwrap": "^1.0.0" + }, + "bin": { + "istanbul": "lib/cli.js" + } + }, + "node_modules/sc-istanbul/node_modules/abbrev": { + "version": "1.0.9", + "dev": true, + "license": "ISC" + }, + "node_modules/sc-istanbul/node_modules/async": { + "version": "1.5.2", + "dev": true, + "license": "MIT" + }, + "node_modules/sc-istanbul/node_modules/esprima": { + "version": "2.7.3", + "dev": true, + "license": "BSD-2-Clause", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sc-istanbul/node_modules/glob": { + "version": "5.0.15", + "dev": true, + "license": "ISC", + "dependencies": { + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "2 || 3", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + } + }, + "node_modules/sc-istanbul/node_modules/has-flag": { + "version": "1.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sc-istanbul/node_modules/js-yaml": { + "version": "3.14.1", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/sc-istanbul/node_modules/js-yaml/node_modules/esprima": { + "version": "4.0.1", + "dev": true, + "license": "BSD-2-Clause", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/sc-istanbul/node_modules/mkdirp": { + "version": "0.5.6", + "dev": true, + "license": "MIT", + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/sc-istanbul/node_modules/nopt": { + "version": "3.0.6", + "dev": true, + "license": "ISC", + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + } + }, + "node_modules/sc-istanbul/node_modules/nopt/node_modules/abbrev": { + "version": "1.1.1", + "dev": true, + "license": "ISC" + }, + "node_modules/sc-istanbul/node_modules/resolve": { + "version": "1.1.7", + "dev": true, + "license": "MIT" + }, + "node_modules/sc-istanbul/node_modules/supports-color": { + "version": "3.2.3", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^1.0.0" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/sc-istanbul/node_modules/which": { + "version": "1.3.1", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/scrypt-js": { + "version": "3.0.1", + "license": "MIT" + }, + "node_modules/secp256k1": { + "version": "4.0.3", + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "elliptic": "^6.5.4", + "node-addon-api": "^2.0.0", + "node-gyp-build": "^4.2.0" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/semantic-release": { + "version": "19.0.5", + "dev": true, + "license": "MIT", + "dependencies": { + "@semantic-release/commit-analyzer": "^9.0.2", + "@semantic-release/error": "^3.0.0", + "@semantic-release/github": "^8.0.0", + "@semantic-release/npm": "^9.0.0", + "@semantic-release/release-notes-generator": "^10.0.0", + "aggregate-error": "^3.0.0", + "cosmiconfig": "^7.0.0", + "debug": "^4.0.0", + "env-ci": "^5.0.0", + "execa": "^5.0.0", + "figures": "^3.0.0", + "find-versions": "^4.0.0", + "get-stream": "^6.0.0", + "git-log-parser": "^1.2.0", + "hook-std": "^2.0.0", + "hosted-git-info": "^4.0.0", + "lodash": "^4.17.21", + "marked": "^4.0.10", + "marked-terminal": "^5.0.0", + "micromatch": "^4.0.2", + "p-each-series": "^2.1.0", + "p-reduce": "^2.0.0", + "read-pkg-up": "^7.0.0", + "resolve-from": "^5.0.0", + "semver": "^7.3.2", + "semver-diff": "^3.1.1", + "signale": "^1.2.1", + "yargs": "^16.2.0" + }, + "bin": { + "semantic-release": "bin/semantic-release.js" + }, + "engines": { + "node": ">=16 || ^14.17" + } + }, + "node_modules/semantic-release/node_modules/cliui": { + "version": "7.0.4", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "node_modules/semantic-release/node_modules/cosmiconfig": { + "version": "7.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.2.1", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.10.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semantic-release/node_modules/hosted-git-info": { + "version": "4.1.0", + "dev": true, + "license": "ISC", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semantic-release/node_modules/lru-cache": { + "version": "6.0.0", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semantic-release/node_modules/yargs": { + "version": "16.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semantic-release/node_modules/yargs-parser": { + "version": "20.2.9", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/semver": { + "version": "7.5.4", + "dev": true, + "license": "ISC", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver-diff": { + "version": "3.1.1", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^6.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/semver-diff/node_modules/semver": { + "version": "6.3.0", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/semver-regex": { + "version": "3.1.4", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/semver/node_modules/lru-cache": { + "version": "6.0.0", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/serialize-javascript": { + "version": "6.0.0", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "dev": true, + "license": "ISC" + }, + "node_modules/setimmediate": { + "version": "1.0.5", + "license": "MIT" + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "dev": true, + "license": "ISC" + }, + "node_modules/sha.js": { + "version": "2.4.11", + "license": "(MIT AND BSD-3-Clause)", + "dependencies": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + }, + "bin": { + "sha.js": "bin.js" + } + }, + "node_modules/sha1": { + "version": "1.1.1", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "charenc": ">= 0.0.1", + "crypt": ">= 0.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/shelljs": { + "version": "0.8.5", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "glob": "^7.0.0", + "interpret": "^1.0.0", + "rechoir": "^0.6.2" + }, + "bin": { + "shjs": "bin/shjs" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/side-channel": { + "version": "1.0.4", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "license": "ISC" + }, + "node_modules/signale": { + "version": "1.4.0", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^2.3.2", + "figures": "^2.0.0", + "pkg-conf": "^2.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/signale/node_modules/ansi-styles": { + "version": "3.2.1", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/signale/node_modules/chalk": { + "version": "2.4.2", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/signale/node_modules/color-convert": { + "version": "1.9.3", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/signale/node_modules/color-name": { + "version": "1.1.3", + "dev": true, + "license": "MIT" + }, + "node_modules/signale/node_modules/figures": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "escape-string-regexp": "^1.0.5" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/signale/node_modules/has-flag": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/signale/node_modules/supports-color": { + "version": "5.5.0", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/slash": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/slice-ansi": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/smart-buffer": { + "version": "4.2.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks": { + "version": "2.7.1", + "dev": true, + "license": "MIT", + "dependencies": { + "ip": "^2.0.0", + "smart-buffer": "^4.2.0" + }, + "engines": { + "node": ">= 10.13.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks-proxy-agent": { + "version": "7.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "^6.0.2", + "debug": "^4.3.3", + "socks": "^2.6.2" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/solc": { + "version": "0.7.3", + "dev": true, + "license": "MIT", + "dependencies": { + "command-exists": "^1.2.8", + "commander": "3.0.2", + "follow-redirects": "^1.12.1", + "fs-extra": "^0.30.0", + "js-sha3": "0.8.0", + "memorystream": "^0.3.1", + "require-from-string": "^2.0.0", + "semver": "^5.5.0", + "tmp": "0.0.33" + }, + "bin": { + "solcjs": "solcjs" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/solc/node_modules/fs-extra": { + "version": "0.30.0", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.1.2", + "jsonfile": "^2.1.0", + "klaw": "^1.0.0", + "path-is-absolute": "^1.0.0", + "rimraf": "^2.2.8" + } + }, + "node_modules/solc/node_modules/jsonfile": { + "version": "2.4.0", + "dev": true, + "license": "MIT", + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/solc/node_modules/rimraf": { + "version": "2.7.1", + "dev": true, + "license": "ISC", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/solc/node_modules/semver": { + "version": "5.7.1", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/solhint": { + "version": "3.4.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@solidity-parser/parser": "^0.16.0", + "ajv": "^6.12.6", + "antlr4": "^4.11.0", + "ast-parents": "^0.0.1", + "chalk": "^4.1.2", + "commander": "^10.0.0", + "cosmiconfig": "^8.0.0", + "fast-diff": "^1.2.0", + "glob": "^8.0.3", + "ignore": "^5.2.4", + "js-yaml": "^4.1.0", + "lodash": "^4.17.21", + "pluralize": "^8.0.0", + "semver": "^6.3.0", + "strip-ansi": "^6.0.1", + "table": "^6.8.1", + "text-table": "^0.2.0" + }, + "bin": { + "solhint": "solhint.js" + }, + "optionalDependencies": { + "prettier": "^2.8.3" + } + }, + "node_modules/solhint/node_modules/@solidity-parser/parser": { + "version": "0.16.0", + "dev": true, + "license": "MIT", + "dependencies": { + "antlr4ts": "^0.5.0-alpha.4" + } + }, + "node_modules/solhint/node_modules/commander": { + "version": "10.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + } + }, + "node_modules/solhint/node_modules/glob": { + "version": "8.1.0", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/solhint/node_modules/minimatch": { + "version": "5.1.6", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/solhint/node_modules/prettier": { + "version": "2.8.8", + "dev": true, + "license": "MIT", + "optional": true, + "bin": { + "prettier": "bin-prettier.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/solhint/node_modules/semver": { + "version": "6.3.0", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/solidity-ast": { + "version": "0.4.49", + "license": "MIT" + }, + "node_modules/solidity-comments-extractor": { + "version": "0.0.7", + "dev": true, + "license": "MIT" + }, + "node_modules/solidity-coverage": { + "version": "0.8.4", + "dev": true, + "license": "ISC", + "dependencies": { + "@ethersproject/abi": "^5.0.9", + "@solidity-parser/parser": "^0.16.0", + "chalk": "^2.4.2", + "death": "^1.1.0", + "detect-port": "^1.3.0", + "difflib": "^0.2.4", + "fs-extra": "^8.1.0", + "ghost-testrpc": "^0.0.2", + "global-modules": "^2.0.0", + "globby": "^10.0.1", + "jsonschema": "^1.2.4", + "lodash": "^4.17.15", + "mocha": "7.1.2", + "node-emoji": "^1.10.0", + "pify": "^4.0.1", + "recursive-readdir": "^2.2.2", + "sc-istanbul": "^0.4.5", + "semver": "^7.3.4", + "shelljs": "^0.8.3", + "web3-utils": "^1.3.6" + }, + "bin": { + "solidity-coverage": "plugins/bin.js" + }, + "peerDependencies": { + "hardhat": "^2.11.0" + } + }, + "node_modules/solidity-coverage/node_modules/@solidity-parser/parser": { + "version": "0.16.0", + "dev": true, + "license": "MIT", + "dependencies": { + "antlr4ts": "^0.5.0-alpha.4" + } + }, + "node_modules/solidity-coverage/node_modules/ansi-styles": { + "version": "3.2.1", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/solidity-coverage/node_modules/brace-expansion": { + "version": "1.1.11", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/solidity-coverage/node_modules/chalk": { + "version": "2.4.2", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/solidity-coverage/node_modules/chalk/node_modules/supports-color": { + "version": "5.5.0", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/solidity-coverage/node_modules/chokidar": { + "version": "3.3.0", + "dev": true, + "license": "MIT", + "dependencies": { + "anymatch": "~3.1.1", + "braces": "~3.0.2", + "glob-parent": "~5.1.0", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.2.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.1.1" + } + }, + "node_modules/solidity-coverage/node_modules/color-convert": { + "version": "1.9.3", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/solidity-coverage/node_modules/color-name": { + "version": "1.1.3", + "dev": true, + "license": "MIT" + }, + "node_modules/solidity-coverage/node_modules/debug": { + "version": "3.2.6", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/solidity-coverage/node_modules/debug/node_modules/ms": { + "version": "2.1.3", + "dev": true, + "license": "MIT" + }, + "node_modules/solidity-coverage/node_modules/diff": { + "version": "3.5.0", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/solidity-coverage/node_modules/find-up": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/solidity-coverage/node_modules/fs-extra": { + "version": "8.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "node_modules/solidity-coverage/node_modules/fsevents": { + "version": "2.1.3", + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/solidity-coverage/node_modules/globby": { + "version": "10.0.2", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/glob": "^7.1.1", + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.0.3", + "glob": "^7.1.3", + "ignore": "^5.1.1", + "merge2": "^1.2.3", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/solidity-coverage/node_modules/has-flag": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/solidity-coverage/node_modules/js-yaml": { + "version": "3.13.1", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/solidity-coverage/node_modules/jsonfile": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/solidity-coverage/node_modules/locate-path": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/solidity-coverage/node_modules/minimatch": { + "version": "3.0.4", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/solidity-coverage/node_modules/mkdirp": { + "version": "0.5.5", + "dev": true, + "license": "MIT", + "dependencies": { + "minimist": "^1.2.5" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/solidity-coverage/node_modules/mocha": { + "version": "7.1.2", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-colors": "3.2.3", + "browser-stdout": "1.3.1", + "chokidar": "3.3.0", + "debug": "3.2.6", + "diff": "3.5.0", + "escape-string-regexp": "1.0.5", + "find-up": "3.0.0", + "glob": "7.1.3", + "growl": "1.10.5", + "he": "1.2.0", + "js-yaml": "3.13.1", + "log-symbols": "3.0.0", + "minimatch": "3.0.4", + "mkdirp": "0.5.5", + "ms": "2.1.1", + "node-environment-flags": "1.0.6", + "object.assign": "4.1.0", + "strip-json-comments": "2.0.1", + "supports-color": "6.0.0", + "which": "1.3.1", + "wide-align": "1.1.3", + "yargs": "13.3.2", + "yargs-parser": "13.1.2", + "yargs-unparser": "1.6.0" + }, + "bin": { + "_mocha": "bin/_mocha", + "mocha": "bin/mocha" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mochajs" + } + }, + "node_modules/solidity-coverage/node_modules/mocha/node_modules/glob": { + "version": "7.1.3", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + } + }, + "node_modules/solidity-coverage/node_modules/mocha/node_modules/glob/node_modules/minimatch": { + "version": "3.1.2", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/solidity-coverage/node_modules/ms": { + "version": "2.1.1", + "dev": true, + "license": "MIT" + }, + "node_modules/solidity-coverage/node_modules/p-locate": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/solidity-coverage/node_modules/path-exists": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/solidity-coverage/node_modules/pify": { + "version": "4.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/solidity-coverage/node_modules/readdirp": { + "version": "3.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/solidity-coverage/node_modules/strip-json-comments": { + "version": "2.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/solidity-coverage/node_modules/universalify": { + "version": "0.1.2", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/solidity-coverage/node_modules/which": { + "version": "1.3.1", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/solidity-docgen": { + "version": "0.6.0-beta.35", + "dev": true, + "license": "MIT", + "dependencies": { + "handlebars": "^4.7.7", + "solidity-ast": "^0.4.38" + }, + "peerDependencies": { + "hardhat": "^2.8.0" + } + }, + "node_modules/solparse": { + "version": "2.2.8", + "dev": true, + "license": "MIT", + "dependencies": { + "mocha": "^4.0.1", + "pegjs": "^0.10.0", + "yargs": "^10.0.3" + }, + "bin": { + "solidity-parser": "cli.js" + } + }, + "node_modules/solparse/node_modules/ansi-regex": { + "version": "3.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/solparse/node_modules/browser-stdout": { + "version": "1.3.0", + "dev": true, + "license": "ISC" + }, + "node_modules/solparse/node_modules/camelcase": { + "version": "4.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/solparse/node_modules/cliui": { + "version": "4.1.0", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^2.1.1", + "strip-ansi": "^4.0.0", + "wrap-ansi": "^2.0.0" + } + }, + "node_modules/solparse/node_modules/commander": { + "version": "2.11.0", + "dev": true, + "license": "MIT" + }, + "node_modules/solparse/node_modules/debug": { + "version": "3.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/solparse/node_modules/diff": { + "version": "3.3.1", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/solparse/node_modules/get-caller-file": { + "version": "1.0.3", + "dev": true, + "license": "ISC" + }, + "node_modules/solparse/node_modules/glob": { + "version": "7.1.2", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + } + }, + "node_modules/solparse/node_modules/growl": { + "version": "1.10.3", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4.x" + } + }, + "node_modules/solparse/node_modules/has-flag": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/solparse/node_modules/he": { + "version": "1.1.1", + "dev": true, + "license": "MIT", + "bin": { + "he": "bin/he" + } + }, + "node_modules/solparse/node_modules/is-fullwidth-code-point": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/solparse/node_modules/minimist": { + "version": "0.0.8", + "dev": true, + "license": "MIT" + }, + "node_modules/solparse/node_modules/mkdirp": { + "version": "0.5.1", + "dev": true, + "license": "MIT", + "dependencies": { + "minimist": "0.0.8" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/solparse/node_modules/mocha": { + "version": "4.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "browser-stdout": "1.3.0", + "commander": "2.11.0", + "debug": "3.1.0", + "diff": "3.3.1", + "escape-string-regexp": "1.0.5", + "glob": "7.1.2", + "growl": "1.10.3", + "he": "1.1.1", + "mkdirp": "0.5.1", + "supports-color": "4.4.0" + }, + "bin": { + "_mocha": "bin/_mocha", + "mocha": "bin/mocha" + }, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/solparse/node_modules/ms": { + "version": "2.0.0", + "dev": true, + "license": "MIT" + }, + "node_modules/solparse/node_modules/string-width": { + "version": "2.1.1", + "dev": true, + "license": "MIT", + "dependencies": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/solparse/node_modules/strip-ansi": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/solparse/node_modules/supports-color": { + "version": "4.4.0", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/solparse/node_modules/wrap-ansi": { + "version": "2.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/solparse/node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "2.1.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/solparse/node_modules/wrap-ansi/node_modules/is-fullwidth-code-point": { + "version": "1.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "number-is-nan": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/solparse/node_modules/wrap-ansi/node_modules/string-width": { + "version": "1.0.2", + "dev": true, + "license": "MIT", + "dependencies": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/solparse/node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "3.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/solparse/node_modules/y18n": { + "version": "3.2.2", + "dev": true, + "license": "ISC" + }, + "node_modules/solparse/node_modules/yargs": { + "version": "10.1.2", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^4.0.0", + "decamelize": "^1.1.1", + "find-up": "^2.1.0", + "get-caller-file": "^1.0.1", + "os-locale": "^2.0.0", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^2.0.0", + "which-module": "^2.0.0", + "y18n": "^3.2.1", + "yargs-parser": "^8.1.0" + } + }, + "node_modules/solparse/node_modules/yargs-parser": { + "version": "8.1.0", + "dev": true, + "license": "ISC", + "dependencies": { + "camelcase": "^4.1.0" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-js": { + "version": "1.0.2", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/spawn-error-forwarder": { + "version": "1.0.0", + "dev": true, + "license": "MIT" + }, + "node_modules/spdx-correct": { + "version": "3.2.0", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-exceptions": { + "version": "2.3.0", + "dev": true, + "license": "CC-BY-3.0" + }, + "node_modules/spdx-expression-parse": { + "version": "3.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-license-ids": { + "version": "3.0.13", + "dev": true, + "license": "CC0-1.0" + }, + "node_modules/split": { + "version": "1.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "through": "2" + }, + "engines": { + "node": "*" + } + }, + "node_modules/split2": { + "version": "3.2.2", + "dev": true, + "license": "ISC", + "dependencies": { + "readable-stream": "^3.0.0" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/sshpk": { + "version": "1.17.0", + "dev": true, + "license": "MIT", + "dependencies": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + }, + "bin": { + "sshpk-conv": "bin/sshpk-conv", + "sshpk-sign": "bin/sshpk-sign", + "sshpk-verify": "bin/sshpk-verify" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ssri": { + "version": "9.0.1", + "dev": true, + "license": "ISC", + "dependencies": { + "minipass": "^3.1.1" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/stacktrace-parser": { + "version": "0.1.10", + "dev": true, + "license": "MIT", + "dependencies": { + "type-fest": "^0.7.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/stacktrace-parser/node_modules/type-fest": { + "version": "0.7.1", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=8" + } + }, + "node_modules/statuses": { + "version": "2.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/stealthy-require": { + "version": "1.1.1", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/stream-combiner2": { + "version": "1.1.1", + "dev": true, + "license": "MIT", + "dependencies": { + "duplexer2": "~0.1.0", + "readable-stream": "^2.0.2" + } + }, + "node_modules/stream-combiner2/node_modules/readable-stream": { + "version": "2.3.8", + "dev": true, + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/stream-combiner2/node_modules/safe-buffer": { + "version": "5.1.2", + "dev": true, + "license": "MIT" + }, + "node_modules/stream-combiner2/node_modules/string_decoder": { + "version": "1.1.1", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/streamsearch": { + "version": "1.1.0", + "dev": true, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string.prototype.trim": { + "version": "1.2.7", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.6", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.6", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/strip-eof": { + "version": "1.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-final-newline": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/strip-hex-prefix": { + "version": "1.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "is-hex-prefixed": "1.0.0" + }, + "engines": { + "node": ">=6.5.0", + "npm": ">=3" + } + }, + "node_modules/strip-indent": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "min-indent": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/supports-color": { + "version": "6.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/supports-color/node_modules/has-flag": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/supports-hyperlinks": { + "version": "2.3.0", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0", + "supports-color": "^7.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-hyperlinks/node_modules/supports-color": { + "version": "7.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/sync-request": { + "version": "6.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "http-response-object": "^3.0.1", + "sync-rpc": "^1.2.1", + "then-request": "^6.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/sync-rpc": { + "version": "1.3.6", + "dev": true, + "license": "MIT", + "dependencies": { + "get-port": "^3.1.0" + } + }, + "node_modules/table": { + "version": "6.8.1", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "ajv": "^8.0.1", + "lodash.truncate": "^4.4.2", + "slice-ansi": "^4.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/table/node_modules/ajv": { + "version": "8.12.0", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/tar": { + "version": "6.1.15", + "dev": true, + "license": "ISC", + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/tar/node_modules/minipass": { + "version": "5.0.0", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=8" + } + }, + "node_modules/temp-dir": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/tempy": { + "version": "1.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "del": "^6.0.0", + "is-stream": "^2.0.0", + "temp-dir": "^2.0.0", + "type-fest": "^0.16.0", + "unique-string": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/tempy/node_modules/type-fest": { + "version": "0.16.0", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/test-value": { + "version": "2.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "array-back": "^1.0.3", + "typical": "^2.6.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/text-extensions": { + "version": "1.9.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10" + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "dev": true, + "license": "MIT" + }, + "node_modules/then-request": { + "version": "6.0.2", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/concat-stream": "^1.6.0", + "@types/form-data": "0.0.33", + "@types/node": "^8.0.0", + "@types/qs": "^6.2.31", + "caseless": "~0.12.0", + "concat-stream": "^1.6.0", + "form-data": "^2.2.0", + "http-basic": "^8.1.1", + "http-response-object": "^3.0.1", + "promise": "^8.0.0", + "qs": "^6.4.0" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/then-request/node_modules/@types/node": { + "version": "8.10.66", + "dev": true, + "license": "MIT" + }, + "node_modules/then-request/node_modules/form-data": { + "version": "2.5.1", + "dev": true, + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 0.12" + } + }, + "node_modules/through": { + "version": "2.3.8", + "dev": true, + "license": "MIT" + }, + "node_modules/through2": { + "version": "4.0.2", + "dev": true, + "license": "MIT", + "dependencies": { + "readable-stream": "3" + } + }, + "node_modules/tiny-relative-date": { + "version": "1.3.0", + "dev": true, + "license": "MIT" + }, + "node_modules/tmp": { + "version": "0.0.33", + "dev": true, + "license": "MIT", + "dependencies": { + "os-tmpdir": "~1.0.2" + }, + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/to-fast-properties": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/tough-cookie": { + "version": "2.5.0", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/tr46": { + "version": "0.0.3", + "license": "MIT" + }, + "node_modules/traverse": { + "version": "0.6.7", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/treeverse": { + "version": "2.0.0", + "dev": true, + "license": "ISC", + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/trim-newlines": { + "version": "3.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ts-essentials": { + "version": "7.0.3", + "dev": true, + "license": "MIT", + "peerDependencies": { + "typescript": ">=3.7.0" + } + }, + "node_modules/ts-node": { + "version": "10.9.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } + } + }, + "node_modules/ts-node/node_modules/acorn": { + "version": "8.10.0", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/ts-node/node_modules/diff": { + "version": "4.0.2", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/tsconfig-paths": { + "version": "3.14.2", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/json5": "^0.0.29", + "json5": "^1.0.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + } + }, + "node_modules/tsconfig-paths/node_modules/json5": { + "version": "1.0.2", + "dev": true, + "license": "MIT", + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/tslib": { + "version": "1.14.1", + "license": "0BSD" + }, + "node_modules/tsort": { + "version": "0.0.1", + "dev": true, + "license": "MIT" + }, + "node_modules/tsutils": { + "version": "3.21.0", + "dev": true, + "license": "MIT", + "dependencies": { + "tslib": "^1.8.1" + }, + "engines": { + "node": ">= 6" + }, + "peerDependencies": { + "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" + } + }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/tweetnacl": { + "version": "0.14.5", + "dev": true, + "license": "Unlicense" + }, + "node_modules/tweetnacl-util": { + "version": "0.15.1", + "dev": true, + "license": "Unlicense" + }, + "node_modules/type-check": { + "version": "0.4.0", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-detect": { + "version": "4.0.8", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/type-fest": { + "version": "0.6.0", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=8" + } + }, + "node_modules/typechain": { + "version": "5.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/prettier": "^2.1.1", + "command-line-args": "^4.0.7", + "debug": "^4.1.1", + "fs-extra": "^7.0.0", + "glob": "^7.1.6", + "js-sha3": "^0.8.0", + "lodash": "^4.17.15", + "mkdirp": "^1.0.4", + "prettier": "^2.1.2", + "ts-essentials": "^7.0.1" + }, + "bin": { + "typechain": "dist/cli/cli.js" + }, + "peerDependencies": { + "typescript": ">=4.1.0" + } + }, + "node_modules/typechain/node_modules/fs-extra": { + "version": "7.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "node_modules/typechain/node_modules/jsonfile": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/typechain/node_modules/prettier": { + "version": "2.8.8", + "dev": true, + "license": "MIT", + "bin": { + "prettier": "bin-prettier.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/typechain/node_modules/universalify": { + "version": "0.1.2", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/typed-array-length": { + "version": "1.0.4", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "is-typed-array": "^1.1.9" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typedarray": { + "version": "0.0.6", + "dev": true, + "license": "MIT" + }, + "node_modules/typescript": { + "version": "4.9.5", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "node_modules/typical": { + "version": "2.6.1", + "dev": true, + "license": "MIT" + }, + "node_modules/uglify-js": { + "version": "3.17.4", + "dev": true, + "license": "BSD-2-Clause", + "optional": true, + "bin": { + "uglifyjs": "bin/uglifyjs" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/unbox-primitive": { + "version": "1.0.2", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", + "which-boxed-primitive": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/undici": { + "version": "5.22.1", + "dev": true, + "license": "MIT", + "dependencies": { + "busboy": "^1.6.0" + }, + "engines": { + "node": ">=14.0" + } + }, + "node_modules/unfetch": { + "version": "4.2.0", + "license": "MIT" + }, + "node_modules/unique-filename": { + "version": "3.0.0", + "dev": true, + "license": "ISC", + "dependencies": { + "unique-slug": "^4.0.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/unique-slug": { + "version": "4.0.0", + "dev": true, + "license": "ISC", + "dependencies": { + "imurmurhash": "^0.1.4" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/unique-string": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "crypto-random-string": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/universal-user-agent": { + "version": "6.0.0", + "dev": true, + "license": "ISC" + }, + "node_modules/universalify": { + "version": "2.0.0", + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.0.11", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.1.1", + "picocolors": "^1.0.0" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/url-join": { + "version": "4.0.1", + "dev": true, + "license": "MIT" + }, + "node_modules/utf8": { + "version": "3.0.0", + "dev": true, + "license": "MIT" + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "license": "MIT" + }, + "node_modules/uuid": { + "version": "8.3.2", + "dev": true, + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/v8-compile-cache": { + "version": "2.3.0", + "dev": true, + "license": "MIT" + }, + "node_modules/v8-compile-cache-lib": { + "version": "3.0.1", + "dev": true, + "license": "MIT" + }, + "node_modules/validate-npm-package-license": { + "version": "3.0.4", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "node_modules/validate-npm-package-name": { + "version": "4.0.0", + "dev": true, + "license": "ISC", + "dependencies": { + "builtins": "^5.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/verror": { + "version": "1.10.0", + "dev": true, + "engines": [ + "node >=0.6.0" + ], + "license": "MIT", + "dependencies": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "node_modules/verror/node_modules/core-util-is": { + "version": "1.0.2", + "dev": true, + "license": "MIT" + }, + "node_modules/verror/node_modules/extsprintf": { + "version": "1.4.1", + "dev": true, + "engines": [ + "node >=0.6.0" + ], + "license": "MIT" + }, + "node_modules/walk-up-path": { + "version": "1.0.0", + "dev": true, + "license": "ISC" + }, + "node_modules/wcwidth": { + "version": "1.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "defaults": "^1.0.3" + } + }, + "node_modules/web3-utils": { + "version": "1.10.0", + "dev": true, + "license": "LGPL-3.0", + "dependencies": { + "bn.js": "^5.2.1", + "ethereum-bloom-filters": "^1.0.6", + "ethereumjs-util": "^7.1.0", + "ethjs-unit": "0.1.6", + "number-to-bn": "1.7.0", + "randombytes": "^2.1.0", + "utf8": "3.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "license": "BSD-2-Clause" + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "license": "MIT", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.0.2", + "dev": true, + "license": "MIT", + "dependencies": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-module": { + "version": "2.0.1", + "dev": true, + "license": "ISC" + }, + "node_modules/which-typed-array": { + "version": "1.1.9", + "dev": true, + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.0", + "is-typed-array": "^1.1.10" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/wide-align": { + "version": "1.1.3", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^1.0.2 || 2" + } + }, + "node_modules/wide-align/node_modules/ansi-regex": { + "version": "3.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/wide-align/node_modules/is-fullwidth-code-point": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/wide-align/node_modules/string-width": { + "version": "2.1.1", + "dev": true, + "license": "MIT", + "dependencies": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/wide-align/node_modules/strip-ansi": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/word-wrap": { + "version": "1.2.3", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wordwrap": { + "version": "1.0.0", + "dev": true, + "license": "MIT" + }, + "node_modules/workerpool": { + "version": "6.2.1", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "dev": true, + "license": "ISC" + }, + "node_modules/write-file-atomic": { + "version": "4.0.2", + "dev": true, + "license": "ISC", + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.7" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/ws": { + "version": "7.4.6", + "license": "MIT", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xmlhttprequest": { + "version": "1.8.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/xtend": { + "version": "4.0.2", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.4" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "dev": true, + "license": "ISC" + }, + "node_modules/yaml": { + "version": "1.10.2", + "dev": true, + "license": "ISC", + "engines": { + "node": ">= 6" + } + }, + "node_modules/yargs": { + "version": "13.3.2", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^5.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.2" + } + }, + "node_modules/yargs-parser": { + "version": "13.1.2", + "dev": true, + "license": "ISC", + "dependencies": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + }, + "node_modules/yargs-unparser": { + "version": "1.6.0", + "dev": true, + "license": "MIT", + "dependencies": { + "flat": "^4.1.0", + "lodash": "^4.17.15", + "yargs": "^13.3.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/yargs-unparser/node_modules/flat": { + "version": "4.1.1", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "is-buffer": "~2.0.3" + }, + "bin": { + "flat": "cli.js" + } + }, + "node_modules/yargs/node_modules/ansi-regex": { + "version": "4.1.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/yargs/node_modules/ansi-styles": { + "version": "3.2.1", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/yargs/node_modules/cliui": { + "version": "5.0.0", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" + } + }, + "node_modules/yargs/node_modules/color-convert": { + "version": "1.9.3", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/yargs/node_modules/color-name": { + "version": "1.1.3", + "dev": true, + "license": "MIT" + }, + "node_modules/yargs/node_modules/emoji-regex": { + "version": "7.0.3", + "dev": true, + "license": "MIT" + }, + "node_modules/yargs/node_modules/find-up": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/yargs/node_modules/is-fullwidth-code-point": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/yargs/node_modules/locate-path": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/yargs/node_modules/p-locate": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/yargs/node_modules/path-exists": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/yargs/node_modules/require-main-filename": { + "version": "2.0.0", + "dev": true, + "license": "ISC" + }, + "node_modules/yargs/node_modules/string-width": { + "version": "3.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/yargs/node_modules/strip-ansi": { + "version": "5.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^4.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/yargs/node_modules/wrap-ansi": { + "version": "5.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/yargs/node_modules/y18n": { + "version": "4.0.3", + "dev": true, + "license": "ISC" + }, + "node_modules/yn": { + "version": "3.1.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/zksync-web3": { + "version": "0.14.4", + "license": "MIT", + "peerDependencies": { + "ethers": "^5.7.0" + } + } + } +} diff --git a/package.json b/package.json index 2b0fd086b..ba8b4b431 100644 --- a/package.json +++ b/package.json @@ -41,6 +41,7 @@ "node": ">=18.0.0" }, "dependencies": { + "@nomiclabs/hardhat-ethers": "^2.2.3", "@openzeppelin/contracts": "^4.8.3", "@openzeppelin/contracts-upgradeable": "^4.8.3", "@openzeppelin/hardhat-upgrades": "^1.21.0", diff --git a/yarn.lock b/yarn.lock index 7abe6637d..8730dfa7b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1767,6 +1767,16 @@ __metadata: languageName: node linkType: hard +"@nomiclabs/hardhat-ethers@npm:^2.2.3": + version: 2.2.3 + resolution: "@nomiclabs/hardhat-ethers@npm:2.2.3" + peerDependencies: + ethers: ^5.0.0 + hardhat: ^2.0.0 + checksum: 72321317e55eb510306e04c42353c5f7ceb42d086fc76cc740120da6e1635b7ad5bbf23a8d6b02bd590754adcf646618933111624085ab249b1ff3482e773226 + languageName: node + linkType: hard + "@nomiclabs/hardhat-etherscan@npm:^3.0.3": version: 3.1.7 resolution: "@nomiclabs/hardhat-etherscan@npm:3.1.7" @@ -2948,6 +2958,7 @@ __metadata: "@nomicfoundation/hardhat-chai-matchers": ^1.0.3 "@nomicfoundation/hardhat-network-helpers": ^1.0.4 "@nomicfoundation/hardhat-toolbox": ^2.0.0 + "@nomiclabs/hardhat-ethers": ^2.2.3 "@nomiclabs/hardhat-etherscan": ^3.0.3 "@openzeppelin/contracts": ^4.8.3 "@openzeppelin/contracts-upgradeable": ^4.8.3 From 41a96ca24b0e32b8087ea7b916ae2864cbf1a05f Mon Sep 17 00:00:00 2001 From: Jesus Lanchas Date: Mon, 16 Oct 2023 17:02:43 +0200 Subject: [PATCH 30/33] docs: add audit report for Forced liquidations on IL --- ...078_forcedLiquidations_certik_20231016.pdf | Bin 0 -> 1313951 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 audits/078_forcedLiquidations_certik_20231016.pdf diff --git a/audits/078_forcedLiquidations_certik_20231016.pdf b/audits/078_forcedLiquidations_certik_20231016.pdf new file mode 100644 index 0000000000000000000000000000000000000000..3c43db1aaac5e5b62c337c3c141eabd7bfeada8b GIT binary patch literal 1313951 zcmeFYcT^K;{4b2_sw)DhM0Os`W{p<)jf6Ml*Y*uCpAxMU@#{%RZpByMn1@OcA-B1 z=SvI?rF}zue$b%tKeSx%K6p}E-Nf#ox_xMPuy@e^Ty*+>E&^gM`5shvb~sP;y$~s_ zjwhXu{BOl7*xTP%THPtYC-UOKlNfDnX?08A0RM}T2Tz?kt%;Bx8Wb9izvO)Zx!cq? zD&T@I&cXz_-_AQC@E``+ABQ|TATq+yH~eg9@TJfY-;l_I$R_3iL6Ha)>gGYnnN58! zg!&*)vGon{M;>$f^vRRj+J=S)BO(zPgQYJQOgve)PD)DZuk_W*so$iL|9<}bMBpa^ zKN0wez)u8zBJdM|p9uU!;3on<5%`I~PXvA<@c%Rdf4y&%Io?Ro2z)7jm{v~n}Yu3(~&H%{xH}GzT^y%iZZx zlw8{DAHAH4t=_^CN&j>d^TJx2Hbw`9thr0?6^7%nZ^f6UI)+F?h6j|NEO$eGhaOa{EsF2gkDtyc|4jT6hTWtP`E{)K|MzraXxy>hnrF0{kG8 z<(_r|>P%{Qedz-krmcQ|tFz!AnbW%D{r**1`%0po-4D#aLJbWu0P{D}V(v_PVd$@` z-*@=gzns6795J<4WSu*IJ!;1A!z2Fl^%4Ntvhpv^K674Id-3s)S~H_}9@wP6(4AoR-~KxuQ8I)+8Y0GVqbO}c=U89S8*bzm*LBFw)?JJ5ndywq~#rE@!)2;h&y6(~_WVOy2Rc5X?a@6jVu zn-$mMUN1NV=dlnm`5@isngQs0#1FX&6&2QRk#)4NDp;LkuDQtjy^kMAJs0mz+ItmF zYR;}$Jx{&y;|^l|_88&j2CVW*+iKs3fUs|4^@m>5yn-#3ZQCt5+g02P=U#q&!yoFZ z@U!G9{g94&cPGV6qDQBmnT{xupF!Jcs&?r{&F8)+9jzZeJSKXt5w$tG-mavH$`+0u zF#JLuk?*4(NhgStLYReLp1*P;HqY%^!%dgY@$Sijm-J=gK`3vqTDK+l8J6#O?-TSqG`NdoLkQr}>l%(k;_oX74Tw~EBwn>x4}s~(Lv9A=Y#;lzbwvO$lr8VJwU z{p4_d2O3c!9nVHVjPT+9g*y1iUg5cYqOv#mV(rsfZ84wfW?x(#6>eYq&1tYrXI-~1 zSe?4Zt&Qk>U?ET>V`0mwz#*q(BB%V@op%DwKC^$QZt#=bxK``g@=Uv3q}x&=Z5Ok2 z%(mxtp%WdiJ{7O=tVe$v>Ts4EE!!k0gaZ12JkimwdIWjlKClF)|`9sHW9J4z8IiLe%n9+N&h5M}Xj-2>YfgQ&1IJYjo^AE(U2 zaujWtGhJ@VI?Dh4Q*Zv1GjxnnUiFn&Pb6Kt30D;mS#G3D9MNN1;ZU0`QI(wV z^4w{UE3SlyhM_+?+wz}0%G^~`Yd*E-_!swW^JS84oX%ljXF1dfK-(9S#urA9<6}O^ zNJ(kay4$OQCA+4Zs@*QSW+EJKGyy85xnBZNRbw}q;x;W_P|YTa)l&CZ zP1Y6{+XI!GFiYm1%wI9g)ksT8O_Gbb#$7@A_de;4$ql1jp`%feyH?;@Wyx39!QA9( ztsM9A4!2}{S;h#+zl7oVW164HMRMLo2nvWa!huE{$aU&JXKh5R z1#ylN_NAId+pD4>SKt&dkXr1wn@%=hJ=`dq=nELJI>kKb(!e!n?Q6h9?rJRH$7}TG zp*$1S${rr%fc3J|E@};^casE%iF+Ywbq2F9C%guu=+b+d$n8tGr#e9DD7E& zDg5O;snuyV5+Y!OFpb_I%-QuP$GjL)q(Z7FT;Wk>rX!+dvmQhnk+Ui;S(%~R#v&Mr zK7Zfcyr`Mlf?!U4$ zwDk(XqE8xEmKEg5&E$L%a_B5{AjrdRAVg3=8#L&21VWoYHj+mJBqJ%QbN`fZ8J?;$ zESm~Tk_1~Q{oFePDBcS<-_s%_6H)YrU{=hcvHLZ2qXTI;KxM-#dMN*+kA=kW(Utu2aBJ;chAacCf7+ zz#N7W55Yq;{c$B&(G>h)Iq!$J=Lky@u?b%$EZUA)wEb2r3KyOvV$1D?#@*j;n$zaT z@XFC5aRjuiAW_PqTPknQo$BXlkvI0qO9=1lXx}SuCtTh=S~uP9Q^Va{uXL)SooT>6 zw_z}->TOPfjz6mX!Qe$9$J`A}c>@){1`m`ta3_=-TCAw!@ra$&amS%aWp1&p zIQHEYmi=MO4y%@7)+;~ZYgb`BYxys0K<_UK+3^BB-oE&Ar~N$%s`Q)6QCrH?U}M6+ zdm}##4iELIwx<&)ppvWiP&eybe{<(pwcSOha@l8u3yK_VCI#`wf{WluCrltqbUO}8 z+zjjZvET02YF|k+LtJ8bLBPl5s;4YJISf-C^ZVJAM=SR|nftl-_rff*ZBcZk9><*^ z%iKz-<2Yr_OD~L~XMa|$RG0He``Lh;Zm2_ni_#i#xBu7mjoRz4IxoA(ss?f!oUgZW z=0`v#k*a@68?18O@7&S?eGCDsK^OuKs6o0RG@`dXsa=Vhj@VaEf^r%|aEQIWmf<&w zZ8IgB8xc=u$|9O|(LBZ0EX5Q{It0Nt^U!B8HjX>R%=#(eQN7?m6JF+9)BBP7)2Hp% z)_NuLD{F!<+ZOkJboWTspxXJwHV(R0TH49Cjz}lM0nP^o%As8xzetWG0&FEfsc)GL z1?i$_>|IgK+QAG&6&~As>2dFK`|4IsFoN0{+ovs3a*9V_`h4_UPG9>z71P8+XE@R% z<;rGT&HGPXn0~_nO~S|<&yQ}o_CjA>a&z$kI7AgS+)Zpm|5AiuPg&;1#DG0q zK6_yleVdq5?B|0G-Pp#O?3wM`L!_Ea_Bih5GrefFj5b`5^kl4~)q~$L_pkK@Jea9b z2$M~_^a5A9scrVdlV>)Dg)$>U`*SXWZ@NAj6NG%q42L|6u5_jL5c{1Uh z7VWo*jfCDfu{dcIQks@hIt!-sCRECwgk;fp4|{vkq8-$|mAPK(F)4g+1nyQYBXy_M zHU~>JH4E+%79T3I(<)BwPs;1NNvthuFkl65B&o}ii38R9((aX#?Jg*mpxyJP-{`al z@#8wKT?{l&<51mGZaS@al z*SGv5uIpSp$Sv13;MDtow_VKAHqJMIODsr4Xya|w?t}82*sgs{3GE?EblDeLJOsyR z{%{GL4^_!Hjh*blwfWeBBMh7c$MQh5K9Rm3^FBo+q>EfFVboDCK_H4w(F8J0`&&7V z$xPY^aBoJ6$a-3nlDXaTuAC8he*x#n^4H_-ACtPAT>@$D+ZHO#*K_9o0qcq2>9W#s za54l0%X%g_>O86XODtlIgLw2|I#HoWci`b3-T;3;>K1k>9!StcSD5u5>!NQA#D*!ORZROsxkZB5m`&9CGedaSp0VzN(j%oW z-@DvV=PiBjFPfcdOmLxf(Y!9XCKNuA35clxuZYZt%2b-rtKEHCmFDVOqihJFbv6W& zAF7*EC59k3)UQoe04bL4jKQ)YFR21gwn)tO3>CA#6 z9cI_dW5%lnQf5jAe2gGVdTkqv-u*|VS;GM3yo&P5tz3&0#7sW7 z-)D6|TNyK6rx~Vz(Nw@3Fh}jg%`Rb|++Ixi;KF-#0#dOkA7ZtKrcC=Z4x6coLhhOR zs$#tl5!c+7>`{>5zHIJv-Zs{&DZFEpvB9tFL*-jjP@PCV{l{Egimoo7os+`0JHYfVzOcQn*#^+4kT zs_I@~A;^09%ADhZ{aaRp4=UH&2u~}L(vayc7GU&iFc3rfMJD4smcwb$2N$=o*-j}B6N27nq zkPh|;wno;_j|HB3ny2E<H>(`~mmUyj(nJKi8qR841^4M?YmQY=2b0uyoxGccgA!3CAXRAGBdW zOXN1ySS`WHS+YLVn=0#)3jMizZVEtt`vY%cv)qO!O@!C4>>-}p0l8hv>x>heXN^og zIv66-OdcuKn&vI6X3nnq7B0&7UegXF*m2@IFCBg$+ZV20TmJU9(|y%w|1!CnkY8S0 z1zpRaigiMpbzu;`FG$Pg?6 z%8R!K1FMcoN!^+2u{y%;h5(UihOjCJSo2zNa+=S}8d1wyVMXl+#l=bjY_#k!t85oa zv-m|cU3UvMC5Ba`31~~9%pG?2Gt0!nt%chs)a}e|r}=BfR}Aa7D@*`JN7mx#Uwn`8PaUvvSM2+}M53J^A*+pJ-wWAu8nOtaXT+gLkLPz@U0)1_jwXZH zhs17(q6*gKQ=ujYQXtC#mCM$|g4MRD6jlcsZ?+k9EY(#g%FA^q4ANfdTPxcn^_S|G z8Z~zJc4uuPg*4rIMXFIvod-s~!jifZ7a$8ySWt&qA4)ynr&&{W8tXt0Jq_R8rs!eY zT!CHYid2^8A;>LJlyiS$1oKHLzCVOwZOSWS@6(F={xK_e?AVqnbFvHRNMOh;^oLs_ z$nkpxaec%Wwfx{o0<{Ht@h^FNJY*j@d8@w^4MtOHAPuZIzdui6Nkjh)RhC+Uj zZOdQ17E+y5XmXO@JIqOVVhRr#f^lP^q8DCuwxsVQek&1ofMbr(JcZDV3PUC1s#mEC zST`K(7W*+>c+QNdkV1J;ELvgBlzPIcXbIL#4ueZ2Vv6OmvxYnMuwv^)$3qZr6PNKT ztYX;GJq~^Kp(&*ZZ<*5>X(NSchGcTsJGvF}d^eNfPpF|5cUNV2t}X1-it^`HJ-*T938 z_H?I@aRX@d@EwnkT6H%5E1CK0VIVK3baS(`R(;I`FA`N!h}4?lnePB8;} zHW5IWr~(l&Wp7!~V0ljpAvhUKX@QPGf@ILD1fmj9s^G#cC1_sUniL0p=JB7Lg7aIB zfunc%tH)q$K9I0y8{1DANH&2Y)=nWuY#%1?E=lDpiplRY(P&(Gj_?VJ9c}{2rZwPm zis!wB{bYS&{eD!iIX54>6b>}(6o*_uqbE#JR>A^JfWHZR;rMY|qy2@^!|V4R)3&R< z1Nj6TGbGPXEY8ecdE+9fizSD>m1&k}zzaM9cgS?yio-^kJ4fg_k0XVaiBdw<-TSi>P^MBd6uGSi-Fl}Nj0F6 z4~#ZVX(=Q8s@#O|YsO=iE(GjE|ERIe4|8Qo243G{lpba?4wK%P|1H5Toj@b!(mN@K z^2Ltlm;tHQw6~mmY?{Ci7@cggQ-ch4U`TrE#IrESs^3KQ`=d~TZ=A`_ExbnT)Ql9F z*>*&a`rLh++(|p)>)tVL%4z3TIRsSaqJRfIcfsOINKE?l9dt4PBaZxVI|LSPczm@5 zssUjZKyrehBxtEI2{NaNqWYPxFURsB|2#YoH42pbLf^Djw+GYgwB31WkIILba!WZmfY#*~oY{eSyfrHGc zyXWY=G2#t8_8zp{%{*BJ`3Ylq9bhnc`fW61!t|^em&Y7l^1)e&LuuB))ftolBrzCRuL^ zKN$g)IgtFr3q)PzbsJx>p;Pc}7wC~4G-eFhY+*NSh94!wAQG1Q>C|ENH(O$i0w`wq zea0rVqj8{un4c0h8~*OfK5HHv<5wB)TY21aQm(tPdN8dae;6B`b%N-X+AtX7Qt6&b zRz_P;*N?RM0ePl8xBhlc7OQ9v`lu(u+UV*61 z$8g2mkT!7TQ)LKlTPV{Z6la#Y4@c@^wXdlDid5Cuy z@;QBxp@G*nU4wCI6kQ5!T`=_B_h6Xx_4^Kn$J>=xX2-@H7S^+jKD<~6R7ebruB-Yp zFn$rzS@v`)zxOA|dBuW4oa5?KA<-K#%MGIe<*5)Rr=)fr0wb5yD}k1sU<^$(slaUL z7U30*idqiA<*-e{Y#!iZNt#iDKOclI>thD!&`!jB{78rGKO@W)^EVg?_846?5(~BVyp6;D$&#HNBSX_GyG`doq=_IOwgBumV?NEhtz9T zP;3g;IgpIL;LFiq?;qmEM*p*JzK~m;)9e^23-Tz{Wm$#Z%*436>rn-!Z&} z!OAGQ$Xm{Ggf$vyGI#ai%2Bd2Z~`X!YXg1OA1( zk!qq!V~`4G}`f-3+6`{PnkPSEji z=o}5|W?Hub3xZRiA^n~@zGOPx-g7}!0F13q*pdhIUM6BqxOy&zq=_5Wnj54Zw|-K{ z5Kc=o(-^5?VbdRSgl=zgfV&nRLa96ydott_E>mP{nHW0)8WBBG$@Myg-&ill;&|=h z0FWyEj73&MKf1qL|E`uWiLwQI0spyhDY~PvpV{Tx5YiTK$_45;bAK-8vSEI#p%-~% zjpr&qJ8>-VV2|wddGRc#>=G3$CmV38e2|p6iVS{w^mt_F)h7Znwk*$*Gh_{Wby_0| zX0ToLN9gQLp00e)6y3&`&$FjWeW5FQJTxAz2E0w+i?~EzC_W4FD$Z-3s;fDR*?}uu z>PCXoOZA-$9C(7%0}w_1ydpr9(x8HYGszJ(ilhj6s|{C$rH84**p?fBdj@)jbzdGF z=;nBJ<;N33U38!~w~4l9c9C?=wye`h&=#!mKH~ZHXtXid`teBjxZ!}JJt&32IZMi@ z>XV=Dt1ESkdd+p@=7#6VKmI4$J60*8JZVSw?bm2QrGT_B;8V3V@%JLG2>V zN6unT=d!#$2wky?T38j_T9dmK2W?7;gYG*}Q}I--Rp=CW&ku`yJV5B$g#Jc+p(c08XaLVA#>tLuy=wTWA|t#qEmR>>#(M-v_ik5kDHn(K1i z`?t{E0{^y=!+#!FaHo- zDe5OCE?1uvpJ~Q6SD<sZoOZlea=z+O0%SfJj z0E&KEfUf_Ni($XDgDzs?sQ7XdD8H^s3H(GKyp|3%ebMqyfwr=D4a{WOt&{rtR@)d& z+D5^Rv4rPrpfbyp8b-*78e4@*1Q=5z8A9Gt0QbI22Khm`<$+3hZXo_whlxo6Hb6tP z^10bF&R0Fq++gv6bn!jgAalE>yzT-Dv8G6A)2s1~0GI%&I`|F&!}irC%nc{sTs7_- zF0en=wS0W*s1tYtwfkXdCWjRz4y%lTRb9BU1bhUzR0B;BP)=*}EzrCvywn(*Fzvq+ z)Ifs?NB`4cEXIb~FOL0sZsCO&p_I&&W)pP41Gs+P?$hk4nmnMffEbm9zDKtDHLOCsO@i3}XP56u0SDx1u>iDOH=RHF~GM|iv%6>dYlQ!V3~EriXGy=cW%p9)?z zTdO!kQZBO`uA8S&gy=NuTZ|b?(d89ZyB$yew&cTg{WK^K+p9-*ce5l$RdJa00|4x5IAM` zh3iLfzSy_Q9}aXb>G(yn5wtQpVa>U>App+ua1|@qa}0l*XAj7;ft1exqQReDhTSE` zO{>3W5OdiSLs0y9@HkVX#SYnqVUO6Bb`025w(<%e&OJ#8JCgs4)Q1KgUo_@QT<8N; zIE^9NawWwPI%bW^0GzX>kFe_xa|5jU^HLd*O>FeE;+9d~?uDlm;WO4@uDTk)8CgQI zm15V*iC_UXzxPaeAlX*|3^AvABWJE8sjGYajjk=KG67VRhz2RSbN5ACp)w<`tHUj? z3^zoz#bPb>moB@A2a4%FTOo{*~ED(io3kUK_1o=Rns~x0uT?x+by&*Esc0?V5 zHH(N^Y~63dp>$CnzX2)ES~34-c;?5&Oz+7MmYK0f3V^ktft2MT&m(C9H{APVY_BPC zr55nafLw8HyB7xD^XhZUEDg2}^t4Wm8w@z@zSc_SbjlQG#tSRI;DV10`XVJoowN`FLQ8r%U()k^Xf=% z?x)wAtLAAX*N>FhFQWNo+Wob}zTc0jZ}eP#5VYM{+yHW_)1V=$cw+lRBu8XLZma$0 zE~htPF*c#_KP1%4V-wP<3(%8z1Iq|#=qg{7!e6;Yb}VhkHT>F*#+RRk#+2aWMY0W3 zx!o**F{Hu}L_lYiIy+Wcw@OKU(F;Gp{U8~r0w9Ujt0Ngg8WPTuKQ>91$|Br$Brf$0 z2$N&;2X{`|;1*`;<~7yWPbfgV@3eQVJm_FKsfugVCqnY@os;SUtb^e{n_g=nQyAwA z-`^%<+o`!+R+5QO>AGMGRxAgcFlnwdv75hN8lA5DrgOP0AbR8B!qC>)wwA>y>4Gtt z;?)ngu9vkjFNWm6uPb+ zQEwZwK;?=xy@j`4T_-OwCpQVOz8cW&qI(uHqnO?FOcP=0Hu2c=V~e9St=#*WQli!d zO^r-Lu?8!~1)r&{c*sF7OmbX5VJ&LtO7v0Y!pSQUVNhCAZe+0GX0K_J^1UTxgd9xq z75KQjZ-SCsEiuIfDIn;a!|>cdE>xwpE=#?^ALNJv_JRhRi=j4{ul#Zx&us+)?75-1 z60KEA?y6i+E0D4;;p6&*086;(Tiv2n{FjEoxz6~N=#`N~AnO1UQfIE0k|Ms`T55ke zE|iETA`&qEo-Uj#5T+mECd@38LlouOU%EN+U zfp{kTaZ~4QK_C{C!(jh*U6Wg@zW+NYb2eq#7~U(iTwv!K2a}DTl@x=H)oqum)-E^9 z_7C#CF4?bOVcLy276vPjgzWPnRh4DTfU101mqwyy+0b6j`+lgwS^TQm8Pfyhy=LEI zIIa23u{T->Kb?XI;BfG>?mb8NALd~(q57(@&^Dj!%%M+f0jj3yV%Q8+u^xE8ip za2EZ;usd}uHsV@62iRy-VtC*5@-OyYIWE%%( zvML38h)qj1YT9vb{&s^w;Z#C0JHKN&&O53`XV8f$$x2vTy|qF4yQ)RPw>FwPdE*Rc zX6JXiDABR;-nNpbiG>_EEj_9OEzPc4+tcA}7sZ+Bhr06rS|NZgZ1O#Gu-sUjCNLID zV19!Ge0jPOV-E}1vaP^k34iD=-+h2Vk^A172Nb5G2O(+)%dLkmYo`*z;637{A>5SK6?tp5nV0+d~y2$cJT?6$SGB#AdGpZytCa$tKTb9BgJ4|mdWABUY zw?xyjC~mmkgop9|y_pU8Y=*8Hn{a zWpn#Q3MwxD+qJH`1ing&kiztB^QooNTvAp;DBrx~KHxPH+#91pB0 zb?9dK>5IC{e=z>AlvIRIhTQH$vc=xxO!Hme;elbH^m zL0HUDH`ltF z6S<4D(ydiD1D)Pnzdl&wxi1J)Cfdu9oI3aQIv?r!dam#50Da3Lhpuwysx>$>JebEK zPUA~rzW<{QPcgX-w(tZVlgpOdrp12Sy)t75mA50@@3n&_JosAq(-J!&%TEd6Km3FL z_m4!E9RIYgIZNHz_sHn_2wY=h?3<<-T!wThqc(aW&kYx2BQiEnKyeuY3X;I51_Q*!sf|h>UsYG|2PcExTKs0GB&d%w0J$EwaW+EWp?|A)ljcADVYWDp zciMC4-5Yze2ybq~O(9^7GuMG5dIT|$@f@Js{_9sS11xuK?~#6{bU1XeKy;mMD_%9d z3r*ljIc&Ldhhi)7xo(DZ#S%3ih~|vP@3ez1rxU+=@CSdhItw42RxN=5z^YeT8 zRk?&8)#th9fh-R>F2}NbzIdMBxK*y(rWLC`qc8d-s`At&cfP+ZSx%l@tlFa{L&S1U zK&eF=Jzu)PPR)z+z2R9+s58ML2kd&tXs%{bue>U?=xGN~HP@;1@I6CoNn`)g^311> zCyN2Gl(oxr{Bqoa{Hsv;k0UbiclY`zDz8L}dtIuhcGLzs4WhW5Q;$U3+`xSk-aI0e zunn2uXn_tx)@~q;P!7#I!c4OgQHw5v{N@YZAasH?dPLO1k|9OxXMl{ zu@qNM7w$7wK^?bF`Ljef0*AFjb1Ylbr#7guZ}n1y#YKnMuWro`3?fMbMVM7{7$%>u zM6BmSpVh-(EZ|Vl9T}xPyELXfnwwBCzh7s>+6Z+$tm_}%(~mu1?5|}YmzZ59kf$w)#YG_? zP$nVPfM5`4b{3@B1CVPRG&3-0YELzs-`zB)g5KuOK`i}O> zjLn_-<>gkRu2Cj!?cvg=HkwNzO}WEpRVQrwqUzQwQsS43y$ikzyyRy!w1q)GdL`F> z{)MV@ifLF)F#Nt&HqbeR#GzBgWzOI+g0Cv*C9GS!Rs=~V`A9Nh*64uZE#%$;9I7{n z4>P6jE$08j&e3Aanc6|YmL&cg26`jACwfH_1J#vINwx`DGs*FjvPiv-`U_Isngjwz zm90t$l^fa)Pis61E&^%*->96P+Bd8wBUXe*27{RXadQ^|K=MpOiD ztemH)#$Jfpz0e~w8F#0-Y60t<(Q^yiAySP6<-jzH;8_+rsVB|CY?xKm`bX1!Eq^sp zzStGu?*zTt8h3f+P=Q=Xatwohhj)i(-@|-xepjNG$Y2^R4sgDvu9aEdgR}aP^&6gRMBS(N>IY zvgO8%sJ~)IZ3h3qrMNG+X|bas5*C%<5#}7crgm?>wPGna5LlSs3`eFAxU;BqyXUw?T(jSy%UhfzG zeYP@rwqs?{0*PVb6IQu;eEWjAeTWE^%P6gAJIOCbR-hC-j!c#jIz+i}z_3$RFo*CF z9pXGG?^$L;`1luWS%+SRj=F+g+k?PhG?-t5By7WnU`Y8<%#8Zqkl}j^(CV&eG4ig+ z<AxUikmz4G>kX!6BDc!WOK zA7Vm^J+B^z!u6}1g+|QyCm2Yh${CqfUUVO;0GKMIFD#&1g>*sQO1!H?)_~nRuD3hJ z3M%*!1tAhTt#5mnz5IsvDo6Odh4;cOHb4Qsd@)qs%0Shr&5PkMA)X$eR38uae?1#7 zMEZ15I%uT%c-c7gRGRhRKTC&f=*aM{l9uynDe-Jae^;lv_xRBOUCeZ|_*sd)AiE&W zbFM@5=T+RwHc@EAhs|rdR?-w+HFh!g`D}PZ*cL z-w=68G$;;-mbagK#P%!)kZiuzL2TB?bWH?kb~gauyCSoPw&G)|c!OjC@am=~(tJc0 zp^=t$KG5R9XIN3U;kZO#p;{IWNg*0s*mDz@lts#1UQ|a65eX1T$Sc3zQ_ZRBEhG_j2=z)K+M-m zMrdb`gy-dcC&+-b$|s>QwGqwg z)-87IAbV(O%JX+*^4cO(jeR;J9xEv@x>dj@^5tmD~pewbe}n*y6h7&?!0Eb z&jq`I(|qE4NBk&c6pr%TTHsX)NnZ_cg;fY~)yYuiBM4nC@PqjiNY>%5n=qr^!|d@~ z2^6#MCAc@uEgas;uGIluN=1F&dynDE>pFKM9>U2Ein9c_;uJY!3(4ukg$l0%$H~yPJjRXdnOPI^@NoOEu?2^&aeSfcRwn6)Pu*f0SyD`$h){+0q*96{X4J zSEiBDeCf^Y=-TKlkUz?Cg60Z0H! z%&zr?F4G|LSfytv`JNg+4p7H~)xelW!nY{N1R{0)mn6rF$j;kwi5O@}+!#OZ{jAr; z64Yde)GBvAOOE&cQLwpf^hTf%&Q z{iBOkyAJSZAJZz7gyDDSmhZ?99s))!%eB7@b*yRWuI;9+xfiTOKb;+1TXI;Mjt`@x z%?>sGuH?7261^vex>B*`KGz%{{Hu%i?!e2kf$}EBDDRjUp6Gi3&4Zlm`A^&R73)_tO{!1p&3a^6ow|E@ z=wxm6`;(e`f|}0lJCVPxdh=G3eLW>1q&h~3+K1(}?j_-SQ2`!ws5_Hdz-R{#*>PZE zIbpDmKX^4_e12ghyXfEG=;qM&{^gTe$=!oj@mI<}=d8X+Y#hEW^GY9x|EhD|Z*bx5 zOaI$tC59WMJ^P0o2g z-5B@DlzkhW_{ZjRxKIU4v_;9lscoZ7`@IU{D7L*|WNoBF=k;Tr#85Qrt8D#Ww?}t?o;nVsB%@sil9R)qp*+;nyZ@W@`!ou8}5?hL5YImC7jY6k>gS?(Es?tb*{ zp8@8JOiB!I%RP%Yzua*vT8wn@6`x843#!vtiXt|kY)n8smPCOzBXR%T_~Y5p@XZ-Y z%O|UZj7v%R_6dSLj!9#tJu-KUq)(d-0Vndp?HjY(46k1suS?-`hK;=r^oNoKNZHdIemAFATnsqVM z(X2AE`i|L7x~oRi$Ltd@S;QU4)PO?l%8LNt#6xvnfq0+% z+>$udUZPd-KQgxV`>Y13WR>TxidjdMq`k5!IaL8%D|t>8B;&#s^1vO^F z9QqDrk*m#FA?AoFHCUx?zFjjEZx=lgN7)EmqCJ0oG+HZQQduUC-X3X$$q|lO->=@YH+{JE(Tr!;q+YaQ z&>dTx)Mft)Z%92T#=79g#Ag^*7iK&9sR&*biqzl_@xIp4}XN zin_oKKLsat7*-eT&tq#ZF!R~%GzT5(9bmLCkKdPSw4Nu-IrE#ot5F{Fo#3zPBRN5G%8ss-C$lK*1l&!El?>p^Wa5cV0yt$(pie2SNBz@GfMEU zvYURzv*@?e3Lo`=dm+Pp%8K*9q1L@Ty1q~#9A3RXz4>&%!{#0Coy%ik=}g!5s zLFW3p0;0~s#H8C))YDBP1Nh7GE10bN(9p|WhFe@HRL!t}2Im`2b)7*U)J9!W>^8{q zAh?|J*jkqJD_C-#%7xyBi=#>?0pKg9q~Qx*$DW$Oo*4$rORe__J9;;YBZP$&woqEf zyQ#Tad#JOie|o+ALae$8gsAZc;0)_I<5W8O5D>~Y*@p@Meq~#`@Np>EY7P3&7XGK% zqyBnES5-;-4>fm3lvMF>e4^Xqh5VD7n|Ea6N&)k1ftEF|r9ya=+8^tdgqwb9o6}!S z!hH=LpXTVY`F^JClj0Hopt?s~hGA_E;9irvc}g*P{p zJ*^qWG0GI_;j^lIpFR0&tq9_xktYRoC0>(9U>|DYF{bc zDvK`Igim`Kv!^}IFmiZs__-EE*oP7}rvBzCx#0Q2WutRH)4}&`-|#Qj zFW6MPF#W}2i5!MKhw~t*p*TtpAWt>Pt;^DcJ?|(`sP!YhkahlNbuj0C5k+cGfNSz-@tzHCvI;FS`lz9Cg)?&E}~mE(3{w&;>PIM;r-Br zIX`PP@rOtG|LkMOrPLJbl_6)3qm?!XibTssuDiZc-Pz~K4vn~yoLQ~gM^R?%!CcuA z99H17a5_`+?2U*a{e&m;!VM=+wh;w!6j8^&Mm!A4K-!?X++2`h=wEUOe+VA2@IZgZ z=DH5ERAY2RP)70h&7>V|jZtTFbH*VS&I<5xe7kKpSOsrZp?9CYn(gMa+wI;Sg2KP- zzYUd49g;4d#vC%0{$dp}`{kjb%*z7#39Cw-R1M6$_nnvf2f4TAJpzqAWlAj<(0Z;j zPj>%db3FSlmA5(-H@HAuM~Eibr)S-J_)4Vb@%Ub?(>JG3LRrJWVS>uQORDQz(26&O=3}7Pwk(A&JK>)&2cK@rlVF z+^|)Dzn(9RU!GR03t9lX#10#xG~8|@n4()e5Ag#AI^zE{+|c;qBxR#K+G$CsT*-h1 zv)_Ouy)RKVnQMjI>21AM|IMSfdz&dT7l+y*UxO@g1S&_Ow-Z>2V7O}Kl?kI2Y4xhz zKv+!ApMf&Grc|h@Ze-U*Q>i+WFORWJMwb?GXSrr>9J2dUa`zmlVw2|DaaTEwwFU1R z_DCyAMgwqWly1(O^Ka6AxAi! z=w}4pez=iXR7P(7vmbwNJmpA@-;+q8+g7D^l@zKoj#9X3>{oU{bOq`PL&%tg3d>^r zyN6yM@v}D|UB^5FC&ykj_#~x+C_-8PuCYoIqXa2{p^^8z-`0hZ(RFjj@NR^l!tc7I zYlz=dJ%CQ+`Ca3!lSKKqFQ{n02GoXfi1UMal#7!Perz^ZjBZ zZE;7WqYktVK9s2nh>FxtBbvIMWLZKY6aDq1}!MF6e1j6pXNmVc;@q9wHlYEJeq8OkYDX$hZg zO=hcblQRy-+M28vZwOs9dQCLY#5$Rd+2jk_aInyJHvfoc>PKa%hiU0i6IO23(K7YM zd5j)?8GIThwETGP=J>&$sr74s{PrE>tc+j&`xs&V@W)Sf@}jzO=s#bPG768jq+mxZ zNDga7ceo+Qt1u*rezL!UPl?`6w6~4H^t>?FA;IPab!5HBf|BUDd4ke9zE@<(q^D$T z`)IsUpX4|D4B-s%p82wFdnlDXIE9%?BPz?KBAHL3z>+sTGIX-ddAhY{gVbM2-V&IH z-nF|%QM^THHHW|V1&#mny|ekK>N9x!PY&IZ^*bcwcg+G}jlkPCP8yJIJDZBvr_A7% zN&g7x)}G>M2JQ(w2-m4M0U^{boZ1gZmIsFi+D8M(Pk}c8{`&?9L5RIO$R`JIt`qj# z%aBeyaJ119IIM%{B(T8WJTE~%bYMcyG5wp&__&x+9$5-etG93rHuf`8Zi`h&$|RCi z*lrFSi59LrqM7^s7q2_dcI&iB91Wdm?4Ue?e3zuJc|=Y4Owy!+@a&4O@`d`HgZ!br z8Pm=qmJ%z_^iC49*o7d%IxRo${82TtY5643(C2ixNSNBkp zOr8lzfS!_V^ck9JzU$OHB-%k#<~KrMwd>D9$;JFagDi{QC{U4clj z1!ypHIgdF2t?D)m6`bD%zb_EOS^pc4K4mL%#mUMZ76=m1;7tL8AsEOFem|~W6)Gcv zLPJ~y0`JUPzpO9E0&{-A!mhAojWZc6N?JZS+0vy}M(p@gLp+3Zl!8o>q@j=m+@W<^ zvRVSCYMhn^!)=K`RuqBR@;M8>CU07WO>CgbOGFwvv7@`QHbHL$acu<6c2h|XCA#cw z%q1Vs`SfGbp(UJ#9JjETr0+*;L1m+Do~m$t(v5;MG2$Zz32QF}v^t%#RMSIQCZpB6 zM^r-l6Z;GaOj-C=K)mwG; zEfw;-wOCT*@AyoS6Y>7M%wRS+9LrOHJ7&-z&&kBP=89z*jYQ?grJAzAw@t?XL@_<_2Z3FmrSw zN4dRI*F=xz}Kco!C|m z1PNWIsR@G@zyI?SM}J$gFo>m-_U49O9mo&kuyDPA=dF5dQas!ZGS;i-f<05`f)(mh zut1Y8WSB_{UVwW&dzZ3!MSw~2eCWOM;Cy3jL@?-S_m(Jq*1#2}ddS0&Aon9&9+0Ky zq643+87~qPR%P@{427k8%64v`*>p?!{mhsnhd7$9s+n1NJfao%4;2U@b^=8gw3Yb$ zQaab&wZPe@D7T!CuGQkAnrdE0xNe>}sd!?2__nS3#1Y9Rfs}LCCt9adWlhuMuirn? zQIxS6`EcUQa0%yG;n@zz3E6KIZsA z^W#H7L$(dM*Xc%R$~T2?WYBg!o?%_PynwX}kJqAng`}swDKAaNZ-(;}8)7J=#Lq*{ zE>f6lkUCNYBEqb)tZ!iq$qMzYZQc3lc_0>bj1Dg~oydis1MVlek3#;Ot2}Lw{a?kx zkFk?EDVhUlXjm{b?0fNB3x;8xV5W)%)`0X@VmzoL6*Wx{_S&{nuP-=H3h`gqb@;S- zG*HMu!S~usF5T0KTlM#K2QXH+pwUjR_xH>1Z>{R@7yD@H!V)J@TYTv7h0F3j zMNF>vuV!pTUMRMXm!~tbrjxqkou0|JTff7N=*Nt8t~{K`mXX(!eqH`rCF!?e9oG={ zf=~N9y^)?}7aSSlFikg}EmMlwZWZhO1({X$&0ShOK29jZ4!$p8!- z&(j*jTEIRcyq@O@1nTSX;<*aC6)+dqIg=3g!Gh)mW;ZX!zl5KYqCw)tdlEQe8B)dQ zivNL}y8n&fy(}Nq+lc2IcC}Wn92S&A`LCMs4v53I5oW&9H8^?F^?JpYH8swm?WYoW zS02(nWUd&7oU~O)LvpXppF=aov@&s(MD?Zf>wS{Yl0FN>g#ffkZv~lt$b=e)cp7&k zv3}QluEzjDwAvxhoI8t8AjE4AJii-=qjbA;=Ut1dF>ptZDAhhi>%J)SdLMC;c`$$R z0ec|TGeaNbsJ%QC?bZAe^(*z*c{$EIMpn)!TM>fjxqPCF39F>lEgQRAt=W?X5_^*T zLr+v}-iEus3Oo_RkZjU0`zCL3$(H4wWwZq87OK6~k)8W}S}LJ4Cj?=6ckEY=d2!ZZ zEBv2B75B!iiUr@K-6%mNJzhQRsf1Zm5q?Nf3GmeGKUGBO{|w#7H_r9fnC(8F0Trhk zB24fg6kfOu9VpoP`4F*L`c#%aUS!DKvlBZ0bI0~&1*p8v;|Pxeyyaq#6Hq~2Ypco^ z4c?V~hH?WV>wTYt$nOj63RCL}?yE7p7zoP(go*Cf*B)0CN$63T1Y-E@Ons?nX0_a047J_*6 z!Bv7suu`j9gMu)cioj---^^xTXiE>eJ(J5J!0>vT%lCKjYo9604fOc+zff?tlhHu8 zUGeV(W&U z(tq_w$5vmu^)?hNYMK(=esB~|DtWb?wRGfh^Z1Z|Os)@qhMIM@A0cXawbDD(yoS4> zu92~Kv)H1EL0QXu?8Tn*5TWXEFvkU|aX;{QKM*;Ut&8c&!;FW(1feN3yvds)p}cM} zxVmoCXDEM1iavSQkixp!{p)SMj{s(4f0pH3lv9y7Q8{T~M$wqiD#L86LZ`-t)yV8- z3Qet>vp|USe?iiw#p|&nW-u|3KmJ-dQ36wh=Rn{~@Yp(F?95^vchy2>7l^7{Xv*@j zN079kYxO+mNf~0yC$j^Dtp1l`a4~Kp_a{cc1`fyX6+d7zXrvkNu!lsBc>q zv-ZGs0R<9O6HyXG_<)JE6Lm+dQbzmLsL&60v)jhXN2y&B_t61YKNFF(&;g7({zu-% zxlrErU{LHi#|h@I`G!wpZC|o=j>xy;^@=p4Ov}47I(tdy;L!H|guZ(^A~o?z3EsC{ zjIs}iTLm}=7Au|iHvehhY}UcJ7v*XH?$hGLw{-J3*Wy6*)-ccIVUBMV`5MPMMH?+U zest|nE;+b7;?8vd!sPieg{jv>r>uI7uGT6P<@?5BfU5bJpO?$i67M!qwmn2|Gt34? zJa2YF9#Q))$$b7JcpXjQ$Y!J!lX=bZ=970rRm}4d>7Zq5Ytt^w8h8#TAr3-`@Z#rN zcw~6-()IFStSx}IWTbSH_f#uo)C$n!$GA0Nz$6d-2bfG0oAJXj`V3J@GH=R|ijxJS zVVO$X0HDiX)(72Zl&T8X9SF2wT^x!*e5?oe`Kh;;AUPd0HUWIp;XQ8y>$7<@?POZY zTr%k2V`rWK^Wu%;SiR7~F$J%NteDyH9kN3pE|G9a_%kch!`YS4^(HG(O|0mT|Kv#d z!clg9HGT65wXb+>=zf-mNcI^%;hDu}n$rr))92c9B%jN!x~NYFVDYHv4cwNo<Z z*6mXnw=K)Op&R?n%ijLTKVVrBl(FAD%M$8B4Bf)B?;C7Z@Vn)XRHx6q^WE1+JB=C0 zU(GhBM40#`g(5yd59UpBDGI5rn_#}?KpL1LtFnhP^!t1`yxJIX6_PF7#UWu{t?vD- z)gs@(t!8ITe+FnE%Ba!FBIG>f>7kVWGt#wvim0?-=FsH`=<+)t2@Mh60a73%eDJJ2 zf_Vllei?N&A?@CF76~{tWTwvug)QOXL6?Dt9kzgb96m7yF?3= zie=nJ51slVhCKf)J$|Gppyo#MK4IoorXBy^-wgKQ2T^kI<=t)_{;Ip*dSiL~Kc1UC zk^YHCH{|&S;Ftd6wgp@L+fAQmC2U7M&)KsMnqOxueQs+f#KyhXm|8n}@lnt435BYy z{r-MIk1K0t(g*ZQ%dW@FN}hgu$gWs7%u%xF?IkxIo_mfN5 z5M7AOqu^Tu z1Sq{K8sFLi_BtVUT8@($qbWRcBHVk!cw+>a{OW)B5v7waxHb1HyGnzoD*Z^&$NBn{Zv+pbD#D)6Pld1Ce4%4K!1R@t@TZUDkULyU zWWA1;-hSf%H>svI`^_nx=1N@W4RY&o^y$-6hzCz|-yRY^>xyQoS4(@Lz1}mqrn_ZZ zj9nhT%IWUYbq+0;5bT~flk+<4y6v#sz@C3qXO4K6P|nTTkp~N}{GUHs^VbcoCF~BU zDSxVa`fzRfrR?M>HhcB!&&&0~>wlSr(|JBddn()H>z(D3Qd^$5n0s)cXa0UkpyCsc z$hdt6s)`pA&iMvC^^gH1aqrUNgvgfnou9noej0Ve?t^8|4nn@9D?gxT>eVmAkb7hz z_jk%UOY!?{MZQt=BOQL){mvfHjZ zZ1vIo9YdzJlOhexn8~DfusFGH4EU)V>v1lXK}m)ljLQ53dXF&S-Lv!S z-69x|TKhDnT=DdKI0l|CYuiV*aojp*o$7IovYw=XIJQ-nZH}&v4eJy8fUV8oHERZ_aj3Su|T$^(6|n?7PO+}%3k!?^H-v`DoO%KIT_bVT1zxv zaR>)zp7xUwC-j~yk1_QW(?5z zJLx%DNkY5VG|Tvp)C5b5-zgb0IX+=AkB~fUL5_wdP5P0FW(co-B~|elrSrD)JGBdQ zf?m9Hmu*ikIzX=?m7?zU8b4Dda9l(@EI>|m3nhcmZo+R{>jRFiWh$#)SZAvYKUC&w zuG^{=f0#?+?0xH}nU@N3Lk?G1owvoFjPT)h8*D0v&-Mv5wLmvmi-tEuBTCD0YgnZbQ$J^m7dWI+HlGA4xd8$NfR~2zKdOcF9~P*Q=*>$nn3UtCHy5EDCA#st!tP*! zNpKXSM4!BuwniFjXnV=Jm2lIqt3i|g|IK{(9V#UU+FtQ{3AR3lE*Fn%yVycQ+%}M6 za}970RkvcCjDil?-vD$hu<_umk|GJ9q8T^OkUHKeL*@0xh|8$njV#yef3H~q_EXA` z?=&Bn^EMht^$Y%z*eVWO=&c=<6qgQe(O&cLzQ=A{t;Kj{MP1)@=lm%#!L+%xpdQ8S z8uY$OC_2NaUU{iH-c(|Db-|ZC8r9Ss0d6;1G);>uf7V*xvv&9IQBcNO26kc} z7uVp@z*GFcM;v)IrjNj zhMJiUrf+KU0t`ikDgQxHw~m<_py7J`sUab^jWQ}NoJi%G0-DEBkuY1^r4FNZJ!2$< zivcMrS0TWOL%9es_otvfG-z9+8HBhCc;)l!^O=}rTJ!P5#Bd2uW8U9Mvvx0{UMoX} z4?SNB`?XjBDKcYnG9zf?gqlPQk!ow9iV_DDJ%V&vCz#(8v3KfJ0^IFNK)&%iFkt1A z5N+kwO|2CBgU-`wqL5RsWh%zq5nIrPOta49eQ^+b_t;C-B~p-`rTo$Pfnqjdb z`86ylTV2QheMegUb!R!(&4}mYK@o4#8_Y`J(4eC?x9rpY0lVz6C$@)+;w|wfCGs$Z zK~L@;C_1C|X1NaIrIhpfnaO2Jkcc|B%#<23p!c_0`FH6r$#?b?w9gb`(s(OqG~shqcUZbo0`C?8Bi^_|7G^X*#uNXz~mY z%D65WHq?GSU5(d z%}__SF?j}8@rdG)^OGoHl?|N4xQ_S?s>x2=3^8saZbEu5p+f>hU~fX{@Asm?wrHTt zSB3;2>QhXiTS6F{njQyaOC@9=_)qF#@j>A|q+<-R&#GMxi(8Q6F=$=Wvpmbatj->( z*CgvxXDX9GFf?TUBj%|aDI6rnr|Zbu7IOtLv7BtJ4{9H>Il;}^f_{-`E++Q0Z~W3= z{ZfwLV`a(Fgg?Xwtz*!$_|HCPhkl+_n?ANWedBX(&-)LjucQQLtbO1aeS$o)c&Yk| zd6Dc}*Tlx#dtb!2SSu_>+-_2+{-wmar;RM8_@dK)=ucdp(9;latmNk~29<6D>*l>( zl<*2KVogG%Y{yvto$p2XMSw#RsiNz6 z21B~K`*oO{85WgpS>tkz(FyugBaTP@0hccfCC@eh46nD`9eyK`mD0uUYU1Cp+{6w4~ zU{c(b{;F^_OW)8_#C+!0|p`p#atlq7oWR^?Zkr8Iut=G&3-qXt_OfJ!@;K;N$3-sCyIvkFepJavV zJK%N69JEeSYZZDtc`Me9fUrO#e=evU-|B_8)YHpW|EXTU|EZo{X2Xm~y+t=kgneoH z*icI~Q1BHW)XzjcfnOBlK(EFwAR*e(h3&cE0+RxeahYdGrA>HpG9FbyM<$4oAlf94 zdYjaMoF8BxEhhX|aH0Gk+tn4>6twcKrmhgCM{0IeDHgB+6)LKa_`_69?84&ofP4)~ z@i)~4JvF*F&CrI_>_offym}xmP4WC{-kA!0H8ho)VLnkjg%6x@wH(~S(r&u@{#2|z zfAOQ~9hJc~=>y~s^ADZ%XBH1UEvxu*{D@bbZlp0$U&|rlfzYo%@iX;H5d;%1L9^8_ zH*#-Q6qwi>KTOiz^v##yT$0E`1XLXlKxBpnD+MR^uXNQ3a8mB19eOa`gupqD6GA4s z171g=17oG?RDXUPl@Xf1J2cQ=AX1nq!1YG%4dcKYt4XORe3)XH;@1pBDMhf@3UI)* zA#RjWZYK!mA@VS~kQUJpg^$~-4nsTxpPPk-%Pc`GZF?RA0;!Bz>n=m?P|8a~{OrbE zkaP*J0C8yfwVb9HjKKw5#ZTwQGd?=o6YZs2{A#^=8BPj2Cv=wIhJ<~X#yq{GVJ*<64*)#Zh-?{laVkQrb{4H!H(!Dcv zqWH`nZC$Mo{{2|Q#50l8q9aveB}d%t+;p?~Ln=qaTYkmgOIfv-Gadz-b?OM)hD@$L zk8q9TKSV2Kle->c7u2YzPISYi(CrpIDkM5A&MbkId9D%9ZnNE*j{5PQRlo3!S6%n{ z8z&yJIy}ytG9Uj;`COb>@%SgDYg*$C#p$M&Ki@?iTTnQX@q!Y8B%$edo1w7#OVE|| z0L6(tzFWpkvfMk8qrbBe1rDH&EIpt~wV=j>GrWiOABo@AIHucA04{0$D-pU5|9YDy zrPH#AZrKo_>(^0*&WyHfNRACFh}C628JH3k*QosgTfGhcF#)-e3qvCHcTX-|ER2j_iUJr6jI zY#CJBXST@R`wB%0UQgTnC^fL{;Enztordm;?DbgjEEcBQ2^~(R%`Jcr7tU0qHBUaK zXu(+XOWXk=ZV95VU0ggD7wz-cESFbU`H611t~-1|>CUB}E_@TS%;QmEAM?ZE8zaNve_(c2|C%>p^=BJ|BKc~&IP;)K433AV<8zX#aE>Bom-JkoO zXJVf_oE$iMuX9YYTf_cMxo+NFo#b&1-sR|i3r&Mv0YnHSv`m)}IaG07FOG9iB@a{g z!C&+RW*3H;vs7v&O?H#QoQ=MBy002g$PV9S{K$_@;n>ive_6WUmyS;P&x(N~o7!~1>7;#4qzoL- zw1#QIpja&sbktr2-&zBNx4wfT6E;wT2xhWC4l|j9f&lUIP#JgJa^ZT{uw9=IRR@xh z;d5Ewy9Bkhm+CWGt1Mde5vI`0VIfCu@wdb-o!~0N7&z7I8^wgE&`e#;o}JBVY9O zs4S}ncq4FbBgTIjimey<=DF>fep~-RpJRT#lI@k@96_+x=_ab}R_X?q#@qCzirshO z115}4+3@PVBbJQFC6-G$2fVu|m_+z3@MwInm3q{?Np9lH*lUcBs$1(BT3mSt%eU4y z(5|7@L&GCi?*7)~dl($>mOeE2J2A}9yYP*DXdu3r^6s&0$W1jxKa9jj$P|iL$-q+J zO!3sv>g)qJcANnxU-(qAS?~y9Gd16M7~oWD+lubh%e8|;1NV_T;{tfw#ek-Cus$AP zJLk*_0s4`DpXDB-JJ-ZAl1ya2h6f4FI8(^)bsdk<^%6|sQOSPDBozUN7Dabs%>Qe! zYf1_T`m28o>OL~9p*HpXqH4;pTLF+|h>Vb#MD5N`QQ?HQXE1^}U%TLB3y;su?LZ60 zLGB@y;;~@Zy*`bco(q0P%#avgo4=Dun`A>?#V-f1WBmaCX}-&lL~CLfh%FBe8q3lF zdM+k9@ZqHrT|EfgpVA9JP!Jui9q%%QjH`sxm9w_@&7;(IdQ>uQP5 zn~ulgWV>doH-u8?0;P4~jw)|Km+hSw{9dBB!-K23&p-I6a6=o@UiD2j4}MT>IlR(a zHIy5LWjYwIgO|84?Fa58EBM*$h`KX!KxA|fNO{yd#J+r)RFQ#r0tPHhua=gWI4Avs zRN)hO)Fedje1MWO5XuP`a!wJh;!euP!@FEWS33C^kg1V!8FXHLhUlFtNb6!M!>Iz> z!hgx1u}heA`UdK@>+-1~ndUpMGLf z{wEDyNyb7hyceD9GDq*uUb2itYDK1gQch}J=l+E|pt+_~yO+Go@DBcqIDXo-!0_pf z12H%#5K>tq?M2jo`tVxu9$yz*%q@p|O`rJrYm8W1-JXC)U9BCWZ=F#t>iY%O2ru4$ zM#Lj|(jHxT8sohfF=i6326)*!y?`obBEWLMLpT7HugQnh29KMP`zO}u!k#grQq z36F|w86sky>0{X-BNG&h@^^ks3agaaKN3ju6p&*Z|Q z4@~!2=>7~7QJ6xkio$`xlD}W|19XF*4*d9eDTh*FtP8P3tywu?DMS)BFZ?lOSVheo ztk?v*JO79tpV*Tuz_#rHsVt$0x@j3aLd5VcQFCNO1<;C|+ttU|Ox@LAbq8P;R>Hl!d*hGb&_7e6T8Qz{;AB*2M04{xfW~HNla*or z$yV~(Kb{jw0`v|WZyiU@5IxAVS+{_pKm#nJognPje`tN4l+1NWoU_+V3bIrs*W1fbo)i^y%KD;E2ldnRPm8qay+L*ygsJxmka&oX5A2{wF@G*sr>#6eF zaHHhji}!ADmO}>*6WD0>a1=jsM0h;9f}j3T=+|fNnIeh&bLmS zT#@uLG*gqOI$y^hHIt!>CrQ{^jBj8d?sj2dvrV20bFvaLtLu(EzmJT4na`Jd3?<2DYFq1?!HyM43r@P2kn$;h`{1YPx40X7-x8XGDG(oM0H|; z$Vm*Wgs}-LB+HAT%GUkX#jtIm&*Q0i*mx8tB`zt)ei-b?-7+m%QJJ={`_C4f3N*5C z^|o~#J!Q{^yy(JdpNy&~8cA{$*CRO$Y%Vzd!ppi(7GT{cqb0`4Tmn$EEz}KzRDFh_ zLVdt12z1&WJe&uha9cKXWU0hBgJ`ujABbkDCE~>VgwqGwqz7sP2k8Ig5#Ln6t2$NP zf)H6>?Y#-eI4vkn7u0E*$k#$Fi|GRUb=xU>t3XID_-h!6%8_15m>H1dafn(ZPu!u4C_yp zcq6r!$4xPP_wWu9JE)scsB-8jkBn4q+CEGm9g&cKC_A|Yv%)-qqQ7CyWVoeYWPt1g z9_L?D6p~RW{3tkTc9jB1{QX)0qm*0uX@D@pG8M&3gHjRl(CRA<3j@EIwe~{*ek?3s zeiz%hWec+fPmvxn)&QPxTatxn@hCP76n)9G6wAWM}ZFgPl5grxa$ug zEtcvcq~+NR$F)KlwlJ>@b|-qO>sRzifHl@uyy1DLnfODJ@x>$w=082sJTn}JLkTab zjiF#rLY>@^8}QjvG7~>VqA}`9E+oQfQeB(_0?$n%8Z%tkkekna9FYUs28`t6^CQ`- zzTZrtqss3BG=|)br2vsKo~l_T4c9CS*q0Z(MHNkFKGW-+AjdjVuiAf_5Hn;jtAg9R z!yo+|QdQ|_MOUu%K7kHh6~2wV4I2LXa5x}1+;fv7_xD=O`*Zl@OOD;nQ0Sjwlk{)p zcTHc4fr zp-|*CZX)6|g4s23T4CYA%G|j=nhJ<+lEU;ASXHUxK@c4mq>ULhYhS8wsNOua71Oro zWUIuz1KkW?G;?E=%0pjh1w8VIm)oH!z5w#4Ol_Y`f0{He9?VbaCwJv!gJ^hX5Ci6* zuV!sYnxk{K+#t0Z=Ma zi%%EoDsabq&*b(yf$Ec&Y%_)CzUKSmZZw?|akh?@Jw&B_KYTFo=+LX*pZv4dh7GEi zc&rgKL66BicPSkqkiYS&e|zYa?~Ca(c4G0;)qj(Z*|ps4KgY&&X7Loig1U76p~3{H zq>pzti>CkV$Orph%R;^j$`?nBQ`Oh%4u;Da6|SijFSiK~M4}PGAM+nioc3TR{C5w>W=osP`T6w;?~Wyj1Rdh zYQ#B*p6WuK+PE!Q3xp#XM@>TUlCHF(Zve?CqZh=k*{mued`SK>6m<_NuERL03#gZ^ ze=_?-$m-zLL71l%1giCw@I0a=vd;*__1QGF2UWJHs`7hgJ$JSksKAWlo<6ekS@r{t z<7FSYzD@Z^{e;eK47rYKq)~ZDV2{~o*D=1UG_8SK9@TQc&4Vy}4X^iQMk%!$oZCB5 z`l!{Ei*3e5LAWYl_N$G|AlI0|zqQfItO&t3~BO4St)8^B+o8_8*t#{&B_|F(&9F zQ}vKCY&JK??jM!8cWDDmw|283@d@CUp%VqI6EI|P_2(17tc)EqL`b8LX3I&Td!jX( zp?FhLJi;3h0RsAdqC3OfT670s$;7)mZ7>gQ>)}E`rECd@PPgbbu(s%Gq%Uu4ALE7- ze$U|I!s{lb|Ek*IDy#J9kH|;q8i8?=qo41~v zME0BhjuBZA`)S1+|C6PXn9A2oZ4er|(vD=v<97 zv1ZA=rmxdHpP=h_oO>s=bE{OB4(K##YS2@{_HTEMX|$Stm(e2&ONLLK zw~ldyjPU#0(l=A#j%ov~oJ06&{%snq^9fvE?DF3W3MYe)@)Xqw*6p8krO-r&NL<@Yf*|*<*f9EhBSG0MSA)_s z$4qyg@2@4~rVtVjWQ2r+&x~)z5_dR#R#sK7spHS#J{`DKt8JqXnMTANQj5;Twa1(u zLHA0(PpX>;E86G|26Z^X(Pa_Ka=Ukh#DnMzmv@x_Ws1uM^zZamlDvX;w ziUTS_eA0ZVYb-;>fm-8f^n(R`GoB0nK~E>5ZmbaYZ9}Jk=`h5Gk4^N}M~9WCFMjTn z8b*?_m+)7ieE6tUs|Y4>L9`FNS#=4=3{|783S~sQ?EB`&fvluAU z1Tyks7DAI0GVJr6&*%HrcS+F2QHj0)Xu~jpH_V>b@GF+Zd?NH z?~CY|NH^y5(>G7{h6+AwlBH9B@6)gmcv>xEuOIwNn$2P!-wSSN&yFd@S8)?w1^HwP zdZrn*oQ$8HYt-|68x`=%Q#gdW&TfC<{UdSFRn3bR=EYB?ag$ITd<}7nY%J4d4_qzm z`QYe>ZxM3e&+mxUqS30wJH*!DkMRcT+_T$mVZ4oH4N^Ghc5k*8rjTQoz~T1?WW|~x zpj)=iO(fo1cdczT6%+qP$xKSs;&6ODBm5n@CF+{v#CGb~>+9&kKybB-|=$J!Iw-EU>il z$3!P*;WEV-EbYLOm^J_kkP^6-#3uXwRG7$8!fnubQsOk|bEfR;@#ktei4 zP8o*G*{Fi<(xg_Az1OB{iSLF6evbNfr|}(wcTG9nz@BJRTPY^VIc3YXb)6I*_=8C* zc*cl8ZHjB@xRy#Ach=lT?#9WaX!M>)%Dj z`HJ^_Soi3_Z<*CRT~Pb=0e%i!SNbJ%sG!qP`=aDLhQ))3-9HgSA1oMnL=AxWP(bE- z0-eCOMgu*q!jr;6+%xS@P)dA}CYh$VkG8=|LQL&~wF7wg*n(WHzUy-?ajUll*2L9h zwGs5Gs!}X1p9@(WP?H(f&`=k%&GauF74ON*$Pvx%NlM{0aQ)lJJuP+x&&&a?$h+zR zwKu36;!5&t6>r36_r>)r<|}pPe?~d@mlE6(h$}YZ!`F5jd$`MJ0}Q{k?twnAfba;H zk9l;iWcGV6qj65cpYdUP1r>2F;BQ3!Hpu73h>7-vqY-uo07(kqSXoK@6e)1hLle?gQkK+lS&9Mc8m;4mHj`yd> z3wNJ>I@mUVV0$H78E=xl*F?bs@8$W>bIIfS}lQn zVvb~5@vnzrg{GpIH^dhx7XySZ66xw0bfmVuz}X4D)0-a;JFYOWv})H(=z9UxG21KN zIC>WLvj*19O;lf*t5w8;rK*q?g^K9c>1Wqir)SO|$!=#`ESy+& zat^(mF>%0#pZcLKvv^|VS3kpSiR(0_I4egg@9H}b_Mw>%#@Z%zVJrU8iQ*3VdBoz1QDYU!>l0K6Zu==_3q4yPrP2erlGCD|AkQ|1lm$UXRz|9s9de zgX~AFb(g#F)yB}s+_jcO<Ywf(r z^>pzD0~QluUQF2!6BjUu{=h5KUedtX_%ItBsLuM2-kE4LYm;7yH!D_4%fCYD*dp8v z5~T55Sq%wL^2aYLA9>ZC0E!iS$Y)QV3O+$4NHF(K+d}2ePxMN~n%p)FE4X5Sq}gFN z+s5^F#d-^dw-)Ig$gmbh1qzL8Lks%2n$ry8OR-3khk}V)doVA*e?9ywbAsJH1!r5u z!)Py9a^WGa-5VP}uWS?$wdz*lbI{kpX~0b%T%1XQx>pFym}> zLzzl$0Hb}~GLbK_}*WnA=f&?C#Cmum4h*FW2Ii)N4AH9&+yLhp~f%<^Rv7Ys*# zF&nMJ`PVRuQ!l&s|Ne1p3Uw;3?&1&fDd6;J#1lN?lDS40N-7et}%sndNWQKZI z_A{BtHm1k@6=(z+BZxP%MxI9#1#(yHiB6#QGxa4_7)>4j|9Z`l#bREoUwW%4L@7(U=x23;Q*`Dz< zohX_BDdo1D2&OYgd4|$Kdf%71pC|t|Tw$o`PP=`88+T2&B^<}5@7N@6`MTr>QI+Vx zgZz&S)d=thk)?k(%(Q>^%En8thNw8sScDV2-Ad{wpCEQULqvj+xS^^RWsUBX`AZlV z!cfzWt_CagTe-nRlMwMYF>GrZzIO6|z8=*QlEE&&+T1M$(-(4h(HQ|HyFywoWGp|e zt5iIf=>sl|%2By61}+v1_hdM=M)HMPV3Bng75aL1xSL9=M*1(_iCFk3LTN3L06zYpzymGDP{hg0pku4aH)guqFjGh5Dzc?-A6VFic7=T16Itx z%{&pT*pCHQ!2ie8Tg64yfL-6DNJ)dz9fN?PbT`b9!_cKDHGm-9-AFTZ!vF))jew*m z-Q7rcNh!YD_xqmrehxU91CI9Z+Sgv!TL1Nu5w&jW5d}|mQ=?q9br8^?+WC>ROPa{v zr@5zXha%P>gVL+o(Dj+56gX`CB!HP#Rb_m$kjcs8;4%Xbb9%aJBD|6tH$UaPOif$A ze1z#MwIQ6)g7pF}m&GZJkw=g(ds*KRXhoM!y7IKr%*4oy(8By+u-tao00`OKQOkn7 zM=zsp42Rp%2hFqCglvzcjLBp}jf~U>@K&g3eQcb~jT6$0np)7_m){Z`l2M5YzxKW! zqV9Nl8QjR5yyW(15l+NN<*#y09>~>v0jRT2GB3`zqEn^lJAR*GXQfI#9ATS1nSB@T z`DxFl-Zd{F8MZ2R_r8&#jJTj1+(S25d|s3+M6swBR zr*C((e1`l~q=XXMS2u|a6VV!9G&RmEB!Om1>Qozg`2mr4Nfo(2*$2RVltbA8$jy7G zf-?5UuQ-&@b)xr8vvG_Fll>CaGPjuh;&2%6E{6wRd1>WSc6xh#3(A$n8231*KLcLEOQ#QKNurZYxP?^Gl#SVK*qb!CtNBPf0-P@nRq5b|6QM*&{= zWt!p8PH0pk(`qI`{!GLtpK74#l=E7A%JTYL!*0XU@5iX=2!!`29#4fAob#qBESpOCEIlR9dpS)*kabnx=ZLDCmb>EA*HBF< zXvCUzaMDP&3Bs`J`wjY)yBSTapMcf(8u!GoO@XN9x=WByeAhj$i4pBADg}* z=uO!zUQLsYX%s7*LV6~O@wudOlkP2j%DQWUO9lV-M(t7wqn2P?sYYTIwK}kTj ztR0-s@mrKuVOXWx%Rst*(5zETPC5AQm#YsSSY_JDW5#zfA$r;`L_0=!Lx|tQ;BSiq z-A!V>v(?OvCEC~%d?7ZZVVl=6?G@1#! z+o=wQeJgSb0m{HiJO8l?#7eYkR4j0Hv

bYQ8IAkf$GlL97~&DhC>>R6T6f3c8$ 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�n(^MO1Z%lRyS+*Q1`lv?@K7Csw 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
  • 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

    tK+ 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

    Rmis4-+G9haaZWal#|$-^AV2CJ7w$OB*S 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 z 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 G@c#g=6H_$+ literal 0 HcmV?d00001 From f608b0640e5e91797de45f9a252bde5edc621f6c Mon Sep 17 00:00:00 2001 From: Venus Tools Date: Wed, 18 Oct 2023 17:35:50 +0000 Subject: [PATCH 31/33] chore(release): 2.1.0-dev.7 [skip ci] ## [2.1.0-dev.7](https://github.com/VenusProtocol/isolated-pools/compare/v2.1.0-dev.6...v2.1.0-dev.7) (2023-10-18) ### Bug Fixes * added support for core pool assets in risk fund ([e161438](https://github.com/VenusProtocol/isolated-pools/commit/e1614383fe6a24b098c98ff509ce2f7e84e4e2bc)) * fixed build ([82166e5](https://github.com/VenusProtocol/isolated-pools/commit/82166e505b87c90d602a1eaff78253fe55376aaa)) * fixed integration tests ([31a4c44](https://github.com/VenusProtocol/isolated-pools/commit/31a4c449a1386f8bb222a3263cc0b39aeec4b85a)) * fixed tests ([635e206](https://github.com/VenusProtocol/isolated-pools/commit/635e2062bb972e5fa1949b2879d657d715b412d5)) * redeployed risk fund implementation ([35d7139](https://github.com/VenusProtocol/isolated-pools/commit/35d7139b1de2c29815f5d4c691cb316b3a1a7c0c)) * removed only ([133ccd1](https://github.com/VenusProtocol/isolated-pools/commit/133ccd1dca4c020e6a8c773408ca278aac7e3536)) * resolved conflict ([b712134](https://github.com/VenusProtocol/isolated-pools/commit/b7121344c344a11c2a06eb4a17e53e73d847a7d1)) * use PoolRegistry interface ([761b0e1](https://github.com/VenusProtocol/isolated-pools/commit/761b0e1386ea27db1a410c29be7ad2bc3e5109aa)) --- CHANGELOG.md | 14 ++++++++++++++ package.json | 2 +- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 930290691..b0989b103 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,17 @@ +## [2.1.0-dev.7](https://github.com/VenusProtocol/isolated-pools/compare/v2.1.0-dev.6...v2.1.0-dev.7) (2023-10-18) + + +### Bug Fixes + +* added support for core pool assets in risk fund ([e161438](https://github.com/VenusProtocol/isolated-pools/commit/e1614383fe6a24b098c98ff509ce2f7e84e4e2bc)) +* fixed build ([82166e5](https://github.com/VenusProtocol/isolated-pools/commit/82166e505b87c90d602a1eaff78253fe55376aaa)) +* fixed integration tests ([31a4c44](https://github.com/VenusProtocol/isolated-pools/commit/31a4c449a1386f8bb222a3263cc0b39aeec4b85a)) +* fixed tests ([635e206](https://github.com/VenusProtocol/isolated-pools/commit/635e2062bb972e5fa1949b2879d657d715b412d5)) +* redeployed risk fund implementation ([35d7139](https://github.com/VenusProtocol/isolated-pools/commit/35d7139b1de2c29815f5d4c691cb316b3a1a7c0c)) +* removed only ([133ccd1](https://github.com/VenusProtocol/isolated-pools/commit/133ccd1dca4c020e6a8c773408ca278aac7e3536)) +* resolved conflict ([b712134](https://github.com/VenusProtocol/isolated-pools/commit/b7121344c344a11c2a06eb4a17e53e73d847a7d1)) +* use PoolRegistry interface ([761b0e1](https://github.com/VenusProtocol/isolated-pools/commit/761b0e1386ea27db1a410c29be7ad2bc3e5109aa)) + ## [2.1.0-dev.6](https://github.com/VenusProtocol/isolated-pools/compare/v2.1.0-dev.5...v2.1.0-dev.6) (2023-10-10) ## [2.1.0-dev.5](https://github.com/VenusProtocol/isolated-pools/compare/v2.1.0-dev.4...v2.1.0-dev.5) (2023-10-10) diff --git a/package.json b/package.json index 349d489ab..892c0fb00 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@venusprotocol/isolated-pools", - "version": "2.1.0-dev.6", + "version": "2.1.0-dev.7", "description": "", "files": [ "artifacts", From cc79358d5533c8e5f00d36878699b9b7168ffb57 Mon Sep 17 00:00:00 2001 From: Venus Tools Date: Wed, 18 Oct 2023 17:47:31 +0000 Subject: [PATCH 32/33] chore(release): 2.1.0-dev.8 [skip ci] ## [2.1.0-dev.8](https://github.com/VenusProtocol/isolated-pools/compare/v2.1.0-dev.7...v2.1.0-dev.8) (2023-10-18) ### Features * ven-1930 force liquidation ([b871eab](https://github.com/VenusProtocol/isolated-pools/commit/b871eabaf65322e54507c7c8e3aae1db3aa9aa66)) ### Bug Fixes * CVP-03 ([ebc9a9b](https://github.com/VenusProtocol/isolated-pools/commit/ebc9a9b043064e6fe4af2ac48fdc24e24eddba58)) * CVP-04 ([f4e8d2b](https://github.com/VenusProtocol/isolated-pools/commit/f4e8d2b5517ad6b104cffcdbe03c9eb2fd94ddbc)) * pr comments ([cbd9b18](https://github.com/VenusProtocol/isolated-pools/commit/cbd9b18a99c4e1f92bf9404e88fceb8ebc36d55f)) --- CHANGELOG.md | 14 ++++++++++++++ package.json | 2 +- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b0989b103..12e3c1894 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,17 @@ +## [2.1.0-dev.8](https://github.com/VenusProtocol/isolated-pools/compare/v2.1.0-dev.7...v2.1.0-dev.8) (2023-10-18) + + +### Features + +* ven-1930 force liquidation ([b871eab](https://github.com/VenusProtocol/isolated-pools/commit/b871eabaf65322e54507c7c8e3aae1db3aa9aa66)) + + +### Bug Fixes + +* CVP-03 ([ebc9a9b](https://github.com/VenusProtocol/isolated-pools/commit/ebc9a9b043064e6fe4af2ac48fdc24e24eddba58)) +* CVP-04 ([f4e8d2b](https://github.com/VenusProtocol/isolated-pools/commit/f4e8d2b5517ad6b104cffcdbe03c9eb2fd94ddbc)) +* pr comments ([cbd9b18](https://github.com/VenusProtocol/isolated-pools/commit/cbd9b18a99c4e1f92bf9404e88fceb8ebc36d55f)) + ## [2.1.0-dev.7](https://github.com/VenusProtocol/isolated-pools/compare/v2.1.0-dev.6...v2.1.0-dev.7) (2023-10-18) diff --git a/package.json b/package.json index 892c0fb00..8886b3e24 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@venusprotocol/isolated-pools", - "version": "2.1.0-dev.7", + "version": "2.1.0-dev.8", "description": "", "files": [ "artifacts", From 4a9875da2e383bb7e04aaa527498807924b03bb3 Mon Sep 17 00:00:00 2001 From: Venus Tools Date: Thu, 19 Oct 2023 15:16:50 +0000 Subject: [PATCH 33/33] chore(release): 2.1.0 [skip ci] ## [2.1.0](https://github.com/VenusProtocol/isolated-pools/compare/v2.0.0...v2.1.0) (2023-10-19) ### Features * add deployments of agEUR market ([667ac5f](https://github.com/VenusProtocol/isolated-pools/commit/667ac5feeedf0a7337258389f16110df864948cb)) * add info about the DefaultProxyAdmin used in testnet ([80f7a58](https://github.com/VenusProtocol/isolated-pools/commit/80f7a58f68ab0e949dcb8c5248123bf2ec4d9ba9)) * add reward distributor in agEUR market ([072714d](https://github.com/VenusProtocol/isolated-pools/commit/072714ded3dc712e9ed99748ff6a2da2adb94a02)) * add SnBNB market deployments ([add6956](https://github.com/VenusProtocol/isolated-pools/commit/add695693f9e835835e8e53a83dce81aaddfe29e)) * deploy PSR, RiskFund, Shortfall ([93408b1](https://github.com/VenusProtocol/isolated-pools/commit/93408b18da5a390869aab251354789910416c80e)) * set needed dependency to allow the deployment of SwapRouter ([96a684f](https://github.com/VenusProtocol/isolated-pools/commit/96a684fb80775b82a0ea02c2afc383fb032a7c09)) * ven-1930 force liquidation ([b871eab](https://github.com/VenusProtocol/isolated-pools/commit/b871eabaf65322e54507c7c8e3aae1db3aa9aa66)) ### Bug Fixes * added support for core pool assets in risk fund ([e161438](https://github.com/VenusProtocol/isolated-pools/commit/e1614383fe6a24b098c98ff509ce2f7e84e4e2bc)) * CVP-03 ([ebc9a9b](https://github.com/VenusProtocol/isolated-pools/commit/ebc9a9b043064e6fe4af2ac48fdc24e24eddba58)) * CVP-04 ([f4e8d2b](https://github.com/VenusProtocol/isolated-pools/commit/f4e8d2b5517ad6b104cffcdbe03c9eb2fd94ddbc)) * fixed build ([82166e5](https://github.com/VenusProtocol/isolated-pools/commit/82166e505b87c90d602a1eaff78253fe55376aaa)) * fixed integration tests ([31a4c44](https://github.com/VenusProtocol/isolated-pools/commit/31a4c449a1386f8bb222a3263cc0b39aeec4b85a)) * fixed tests ([635e206](https://github.com/VenusProtocol/isolated-pools/commit/635e2062bb972e5fa1949b2879d657d715b412d5)) * pr comments ([cbd9b18](https://github.com/VenusProtocol/isolated-pools/commit/cbd9b18a99c4e1f92bf9404e88fceb8ebc36d55f)) * redeployed risk fund implementation ([35d7139](https://github.com/VenusProtocol/isolated-pools/commit/35d7139b1de2c29815f5d4c691cb316b3a1a7c0c)) * removed only ([133ccd1](https://github.com/VenusProtocol/isolated-pools/commit/133ccd1dca4c020e6a8c773408ca278aac7e3536)) * resolved conflict ([b712134](https://github.com/VenusProtocol/isolated-pools/commit/b7121344c344a11c2a06eb4a17e53e73d847a7d1)) * use PoolRegistry interface ([761b0e1](https://github.com/VenusProtocol/isolated-pools/commit/761b0e1386ea27db1a410c29be7ad2bc3e5109aa)) --- CHANGELOG.md | 28 ++++++++++++++++++++++++++++ package.json | 2 +- 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 12e3c1894..c526b2848 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,31 @@ +## [2.1.0](https://github.com/VenusProtocol/isolated-pools/compare/v2.0.0...v2.1.0) (2023-10-19) + + +### Features + +* add deployments of agEUR market ([667ac5f](https://github.com/VenusProtocol/isolated-pools/commit/667ac5feeedf0a7337258389f16110df864948cb)) +* add info about the DefaultProxyAdmin used in testnet ([80f7a58](https://github.com/VenusProtocol/isolated-pools/commit/80f7a58f68ab0e949dcb8c5248123bf2ec4d9ba9)) +* add reward distributor in agEUR market ([072714d](https://github.com/VenusProtocol/isolated-pools/commit/072714ded3dc712e9ed99748ff6a2da2adb94a02)) +* add SnBNB market deployments ([add6956](https://github.com/VenusProtocol/isolated-pools/commit/add695693f9e835835e8e53a83dce81aaddfe29e)) +* deploy PSR, RiskFund, Shortfall ([93408b1](https://github.com/VenusProtocol/isolated-pools/commit/93408b18da5a390869aab251354789910416c80e)) +* set needed dependency to allow the deployment of SwapRouter ([96a684f](https://github.com/VenusProtocol/isolated-pools/commit/96a684fb80775b82a0ea02c2afc383fb032a7c09)) +* ven-1930 force liquidation ([b871eab](https://github.com/VenusProtocol/isolated-pools/commit/b871eabaf65322e54507c7c8e3aae1db3aa9aa66)) + + +### Bug Fixes + +* added support for core pool assets in risk fund ([e161438](https://github.com/VenusProtocol/isolated-pools/commit/e1614383fe6a24b098c98ff509ce2f7e84e4e2bc)) +* CVP-03 ([ebc9a9b](https://github.com/VenusProtocol/isolated-pools/commit/ebc9a9b043064e6fe4af2ac48fdc24e24eddba58)) +* CVP-04 ([f4e8d2b](https://github.com/VenusProtocol/isolated-pools/commit/f4e8d2b5517ad6b104cffcdbe03c9eb2fd94ddbc)) +* fixed build ([82166e5](https://github.com/VenusProtocol/isolated-pools/commit/82166e505b87c90d602a1eaff78253fe55376aaa)) +* fixed integration tests ([31a4c44](https://github.com/VenusProtocol/isolated-pools/commit/31a4c449a1386f8bb222a3263cc0b39aeec4b85a)) +* fixed tests ([635e206](https://github.com/VenusProtocol/isolated-pools/commit/635e2062bb972e5fa1949b2879d657d715b412d5)) +* pr comments ([cbd9b18](https://github.com/VenusProtocol/isolated-pools/commit/cbd9b18a99c4e1f92bf9404e88fceb8ebc36d55f)) +* redeployed risk fund implementation ([35d7139](https://github.com/VenusProtocol/isolated-pools/commit/35d7139b1de2c29815f5d4c691cb316b3a1a7c0c)) +* removed only ([133ccd1](https://github.com/VenusProtocol/isolated-pools/commit/133ccd1dca4c020e6a8c773408ca278aac7e3536)) +* resolved conflict ([b712134](https://github.com/VenusProtocol/isolated-pools/commit/b7121344c344a11c2a06eb4a17e53e73d847a7d1)) +* use PoolRegistry interface ([761b0e1](https://github.com/VenusProtocol/isolated-pools/commit/761b0e1386ea27db1a410c29be7ad2bc3e5109aa)) + ## [2.1.0-dev.8](https://github.com/VenusProtocol/isolated-pools/compare/v2.1.0-dev.7...v2.1.0-dev.8) (2023-10-18) diff --git a/package.json b/package.json index 8886b3e24..e2d602874 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@venusprotocol/isolated-pools", - "version": "2.1.0-dev.8", + "version": "2.1.0", "description": "", "files": [ "artifacts",

    rge%Om#f#X7lBt#zbH$iC^Z|2hI)bxN_bf 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·t9n7y9e_$k35}-V77UZQ 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 z�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