From a007c472a0603a31e9b12d18c082a71686f14229 Mon Sep 17 00:00:00 2001 From: Taylor Brent Date: Wed, 18 Oct 2023 14:21:39 -0400 Subject: [PATCH] Trust M-07: RTokenAsset.refresh() (#964) --- CHANGELOG.md | 4 +- README.md | 1 + contracts/facade/FacadeRead.sol | 6 +- contracts/facade/FacadeTest.sol | 1 - contracts/interfaces/IAssetRegistry.sol | 2 +- contracts/p0/BackingManager.sol | 2 - contracts/p0/Furnace.sol | 12 +-- contracts/p0/Main.sol | 3 +- contracts/p1/AssetRegistry.sol | 2 + contracts/p1/BackingManager.sol | 2 - contracts/p1/Furnace.sol | 12 +-- contracts/p1/Main.sol | 3 +- contracts/p1/RToken.sol | 5 -- contracts/p1/RevenueTrader.sol | 6 +- contracts/plugins/assets/RTokenAsset.sol | 5 ++ docs/pause-freeze-states.md | 73 +++++++++++++++++++ test/Furnace.test.ts | 49 +++++++++---- test/__snapshots__/FacadeWrite.test.ts.snap | 2 +- test/__snapshots__/Furnace.test.ts.snap | 34 ++++----- test/__snapshots__/Main.test.ts.snap | 2 +- test/__snapshots__/RToken.test.ts.snap | 6 +- .../Recollateralization.test.ts.snap | 12 +-- test/__snapshots__/Revenues.test.ts.snap | 4 +- test/__snapshots__/ZZStRSR.test.ts.snap | 8 +- test/plugins/Asset.test.ts | 24 ++++++ .../ATokenFiatCollateral.test.ts.snap | 8 +- .../SDaiCollateralTestSuite.test.ts.snap | 2 +- .../StargateETHTestSuite.test.ts.snap | 49 ------------- .../StargateUSDCTestSuite.test.ts.snap | 25 +++++++ .../__snapshots__/MaxBasketSize.test.ts.snap | 16 ++-- 30 files changed, 225 insertions(+), 155 deletions(-) create mode 100644 docs/pause-freeze-states.md delete mode 100644 test/plugins/individual-collateral/stargate/__snapshots__/StargateETHTestSuite.test.ts.snap create mode 100644 test/plugins/individual-collateral/stargate/__snapshots__/StargateUSDCTestSuite.test.ts.snap diff --git a/CHANGELOG.md b/CHANGELOG.md index 95af3e13a..1b73a106a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ ### Upgrade Steps -- Required -Upgrade `BackingManager`, `Broker`, and _all_ assets. ERC20s do not need to be upgraded. +Upgrade all core contracts and _all_ assets. ERC20s do not need to be upgraded. Use `Deployer.deployRTokenAsset()` to create a new `RTokenAsset` instance. This asset should be swapped too. Then, call `Broker.cacheComponents()`. @@ -16,6 +16,8 @@ Then, call `Broker.cacheComponents()`. - Remove `lotPrice()` - `Broker` [+1 slot] - Disallow starting dutch trades with non-RTokenAsset assets when `lastSave() != block.timestamp` +- `Furnace` + - Allow melting while frozen ## Plugins diff --git a/README.md b/README.md index 1c569eb49..e8ab78fae 100644 --- a/README.md +++ b/README.md @@ -22,6 +22,7 @@ For a much more detailed explanation of the economic design, including an hour-l - [Testing with Echidna](https://github.com/reserve-protocol/protocol/blob/master/docs/using-echidna.md): Notes so far on setup and usage of Echidna (which is decidedly an integration-in-progress!) - [Deployment](https://github.com/reserve-protocol/protocol/blob/master/docs/deployment.md): How to do test deployments in our environment. - [System Design](https://github.com/reserve-protocol/protocol/blob/master/docs/system-design.md): The overall architecture of our system, and some detailed descriptions about what our protocol is _intended_ to do. +- [Pause and Freeze States](https://github.com/reserve-protocol/protocol/blob/master/docs/pause-freeze-states.md): An overview of which protocol functions are halted in the paused and frozen states. - [Deployment Variables](https://github.com/reserve-protocol/protocol/blob/master/docs/deployment-variables.md) A detailed description of the governance variables of the protocol. - [Our Solidity Style](https://github.com/reserve-protocol/protocol/blob/master/docs/solidity-style.md): Common practices, details, and conventions relevant to reading and writing our Solidity source code, estpecially where those go beyond standard practice. - [Writing Collateral Plugins](https://github.com/reserve-protocol/protocol/blob/master/docs/collateral.md): An overview of how to develop collateral plugins and the concepts / questions involved. diff --git a/contracts/facade/FacadeRead.sol b/contracts/facade/FacadeRead.sol index 10f60d918..a42d5c613 100644 --- a/contracts/facade/FacadeRead.sol +++ b/contracts/facade/FacadeRead.sol @@ -33,7 +33,6 @@ contract FacadeRead is IFacadeRead { // Poke Main main.assetRegistry().refresh(); - main.furnace().melt(); // {BU} BasketRange memory basketsHeld = main.basketHandler().basketsHeldBy(account); @@ -74,7 +73,6 @@ contract FacadeRead is IFacadeRead { // Poke Main reg.refresh(); - main.furnace().melt(); // Compute # of baskets to create `amount` qRTok uint192 baskets = (rTok.totalSupply() > 0) // {BU} @@ -120,7 +118,6 @@ contract FacadeRead is IFacadeRead { // Poke Main main.assetRegistry().refresh(); - main.furnace().melt(); uint256 supply = rTok.totalSupply(); @@ -202,7 +199,7 @@ contract FacadeRead is IFacadeRead { IBasketHandler basketHandler = rToken.main().basketHandler(); // solhint-disable-next-line no-empty-blocks - try rToken.main().furnace().melt() {} catch {} + try rToken.main().furnace().melt() {} catch {} // <3.1.0 RTokens may revert while frozen (erc20s, deposits) = basketHandler.quote(FIX_ONE, CEIL); @@ -241,7 +238,6 @@ contract FacadeRead is IFacadeRead { { IMain main = rToken.main(); main.assetRegistry().refresh(); - main.furnace().melt(); erc20s = main.assetRegistry().erc20s(); balances = new uint256[](erc20s.length); diff --git a/contracts/facade/FacadeTest.sol b/contracts/facade/FacadeTest.sol index d16c6ab6d..78ee2173e 100644 --- a/contracts/facade/FacadeTest.sol +++ b/contracts/facade/FacadeTest.sol @@ -97,7 +97,6 @@ contract FacadeTest is IFacadeTest { // Poke Main reg.refresh(); - main.furnace().melt(); address backingManager = address(main.backingManager()); IERC20 rsr = main.rsr(); diff --git a/contracts/interfaces/IAssetRegistry.sol b/contracts/interfaces/IAssetRegistry.sol index caeaac2f3..add18d69b 100644 --- a/contracts/interfaces/IAssetRegistry.sol +++ b/contracts/interfaces/IAssetRegistry.sol @@ -34,7 +34,7 @@ interface IAssetRegistry is IComponent { function init(IMain main_, IAsset[] memory assets_) external; /// Fully refresh all asset state - /// @custom:interaction + /// @custom:refresher function refresh() external; /// Register `asset` diff --git a/contracts/p0/BackingManager.sol b/contracts/p0/BackingManager.sol index 18e2427b8..2d4bb0de2 100644 --- a/contracts/p0/BackingManager.sol +++ b/contracts/p0/BackingManager.sol @@ -86,7 +86,6 @@ contract BackingManagerP0 is TradingP0, IBackingManager { /// @custom:interaction function rebalance(TradeKind kind) external notTradingPausedOrFrozen { main.assetRegistry().refresh(); - main.furnace().melt(); // DoS prevention: unless caller is self, require 1 empty block between like-kind auctions require( @@ -149,7 +148,6 @@ contract BackingManagerP0 is TradingP0, IBackingManager { require(ArrayLib.allUnique(erc20s), "duplicate tokens"); main.assetRegistry().refresh(); - main.furnace().melt(); require(tradesOpen == 0, "trade open"); require(main.basketHandler().isReady(), "basket not ready"); diff --git a/contracts/p0/Furnace.sol b/contracts/p0/Furnace.sol index aa99a8140..ea0a404a2 100644 --- a/contracts/p0/Furnace.sol +++ b/contracts/p0/Furnace.sol @@ -36,7 +36,7 @@ contract FurnaceP0 is ComponentP0, IFurnace { /// Performs any melting that has vested since last call. /// @custom:refresher - function melt() public notFrozen { + function melt() public { if (uint48(block.timestamp) < uint64(lastPayout) + PERIOD) return; // # of whole periods that have passed since lastPayout @@ -58,15 +58,9 @@ contract FurnaceP0 is ComponentP0, IFurnace { /// Ratio setting /// @custom:governance function setRatio(uint192 ratio_) public governance { - if (lastPayout > 0) { - // solhint-disable-next-line no-empty-blocks - try this.melt() {} catch { - uint48 numPeriods = uint48((block.timestamp) - lastPayout) / PERIOD; - lastPayout += numPeriods * PERIOD; - lastPayoutBal = main.rToken().balanceOf(address(this)); - } - } require(ratio_ <= MAX_RATIO, "invalid ratio"); + melt(); // cannot revert + // The ratio can safely be set to 0, though it is not recommended emit RatioSet(ratio, ratio_); ratio = ratio_; diff --git a/contracts/p0/Main.sol b/contracts/p0/Main.sol index 9493b72c5..1859ad8ec 100644 --- a/contracts/p0/Main.sol +++ b/contracts/p0/Main.sol @@ -37,8 +37,7 @@ contract MainP0 is Versioned, Initializable, Auth, ComponentRegistry, IMain { /// @custom:refresher function poke() external { - assetRegistry.refresh(); - if (!frozen()) furnace.melt(); + assetRegistry.refresh(); // runs furnace.melt() stRSR.payoutRewards(); // NOT basketHandler.refreshBasket } diff --git a/contracts/p1/AssetRegistry.sol b/contracts/p1/AssetRegistry.sol index 098e47f93..c556a9612 100644 --- a/contracts/p1/AssetRegistry.sol +++ b/contracts/p1/AssetRegistry.sol @@ -57,6 +57,8 @@ contract AssetRegistryP1 is ComponentP1, IAssetRegistry { // tracks basket status on basketHandler function refresh() public { // It's a waste of gas to require notPausedOrFrozen because assets can be updated directly + // Assuming an RTokenAsset is registered, furnace.melt() will also be called + uint256 length = _erc20s.length(); for (uint256 i = 0; i < length; ++i) { assets[IERC20(_erc20s.at(i))].refresh(); diff --git a/contracts/p1/BackingManager.sol b/contracts/p1/BackingManager.sol index edb22151d..da8473e66 100644 --- a/contracts/p1/BackingManager.sol +++ b/contracts/p1/BackingManager.sol @@ -113,7 +113,6 @@ contract BackingManagerP1 is TradingP1, IBackingManager { function rebalance(TradeKind kind) external nonReentrant notTradingPausedOrFrozen { // == Refresh == assetRegistry.refresh(); - furnace.melt(); // DoS prevention: unless caller is self, require 1 empty block between like-kind auctions require( @@ -184,7 +183,6 @@ contract BackingManagerP1 is TradingP1, IBackingManager { require(ArrayLib.allUnique(erc20s), "duplicate tokens"); assetRegistry.refresh(); - furnace.melt(); BasketRange memory basketsHeld = basketHandler.basketsHeldBy(address(this)); diff --git a/contracts/p1/Furnace.sol b/contracts/p1/Furnace.sol index 923ba3373..63dcc695d 100644 --- a/contracts/p1/Furnace.sol +++ b/contracts/p1/Furnace.sol @@ -71,7 +71,7 @@ contract FurnaceP1 is ComponentP1, IFurnace { // actions: // rToken.melt(payoutAmount), paying payoutAmount to RToken holders - function melt() external notFrozen { + function melt() public { if (uint48(block.timestamp) < uint64(lastPayout) + PERIOD) return; // # of whole periods that have passed since lastPayout @@ -90,15 +90,9 @@ contract FurnaceP1 is ComponentP1, IFurnace { /// Ratio setting /// @custom:governance function setRatio(uint192 ratio_) public governance { - if (lastPayout > 0) { - // solhint-disable-next-line no-empty-blocks - try this.melt() {} catch { - uint48 numPeriods = uint48((block.timestamp) - lastPayout) / PERIOD; - lastPayout += numPeriods * PERIOD; - lastPayoutBal = rToken.balanceOf(address(this)); - } - } require(ratio_ <= MAX_RATIO, "invalid ratio"); + melt(); // cannot revert + // The ratio can safely be set to 0 to turn off payouts, though it is not recommended emit RatioSet(ratio, ratio_); ratio = ratio_; diff --git a/contracts/p1/Main.sol b/contracts/p1/Main.sol index 43bddcaed..21781ca08 100644 --- a/contracts/p1/Main.sol +++ b/contracts/p1/Main.sol @@ -43,10 +43,9 @@ contract MainP1 is Versioned, Initializable, Auth, ComponentRegistry, UUPSUpgrad /// @dev Not intended to be used in production, only for equivalence with P0 function poke() external { // == Refresher == - assetRegistry.refresh(); + assetRegistry.refresh(); // runs furnace.melt() // == CE block == - if (!frozen()) furnace.melt(); stRSR.payoutRewards(); } diff --git a/contracts/p1/RToken.sol b/contracts/p1/RToken.sol index 77f15bef5..cfbbdcd92 100644 --- a/contracts/p1/RToken.sol +++ b/contracts/p1/RToken.sol @@ -108,7 +108,6 @@ contract RTokenP1 is ComponentP1, ERC20PermitUpgradeable, IRToken { // == Refresh == assetRegistry.refresh(); - furnace.melt(); // == Checks-effects block == @@ -182,8 +181,6 @@ contract RTokenP1 is ComponentP1, ERC20PermitUpgradeable, IRToken { function redeemTo(address recipient, uint256 amount) public notFrozen { // == Refresh == assetRegistry.refresh(); - // solhint-disable-next-line no-empty-blocks - try furnace.melt() {} catch {} // nice for the redeemer, but not necessary // == Checks and Effects == @@ -254,8 +251,6 @@ contract RTokenP1 is ComponentP1, ERC20PermitUpgradeable, IRToken { ) external notFrozen { // == Refresh == assetRegistry.refresh(); - // solhint-disable-next-line no-empty-blocks - try furnace.melt() {} catch {} // nice for the redeemer, but not necessary // == Checks and Effects == diff --git a/contracts/p1/RevenueTrader.sol b/contracts/p1/RevenueTrader.sol index bda4be079..a220e6ca1 100644 --- a/contracts/p1/RevenueTrader.sol +++ b/contracts/p1/RevenueTrader.sol @@ -134,10 +134,8 @@ contract RevenueTraderP1 is TradingP1, IRevenueTrader { IAsset assetToBuy = assetRegistry.toAsset(tokenToBuy); // Refresh everything if RToken is involved - if (involvesRToken) { - assetRegistry.refresh(); - furnace.melt(); - } else { + if (involvesRToken) assetRegistry.refresh(); + else { // Otherwise: refresh just the needed assets and nothing more for (uint256 i = 0; i < len; ++i) { assetRegistry.toAsset(erc20s[i]).refresh(); diff --git a/contracts/plugins/assets/RTokenAsset.sol b/contracts/plugins/assets/RTokenAsset.sol index 2dd0010f0..f187651e3 100644 --- a/contracts/plugins/assets/RTokenAsset.sol +++ b/contracts/plugins/assets/RTokenAsset.sol @@ -22,6 +22,7 @@ contract RTokenAsset is IAsset, VersionedAsset, IRTokenOracle { IBasketHandler public immutable basketHandler; IAssetRegistry public immutable assetRegistry; IBackingManager public immutable backingManager; + IFurnace public immutable furnace; IERC20Metadata public immutable erc20; @@ -41,6 +42,7 @@ contract RTokenAsset is IAsset, VersionedAsset, IRTokenOracle { basketHandler = main.basketHandler(); assetRegistry = main.assetRegistry(); backingManager = main.backingManager(); + furnace = main.furnace(); erc20 = IERC20Metadata(address(erc20_)); erc20Decimals = erc20_.decimals(); @@ -81,6 +83,9 @@ contract RTokenAsset is IAsset, VersionedAsset, IRTokenOracle { function refresh() public virtual override { // No need to save lastPrice; can piggyback off the backing collateral's saved prices + if (msg.sender != address(assetRegistry)) assetRegistry.refresh(); + furnace.melt(); + cachedOracleData.cachedAtTime = 0; // force oracle refresh } diff --git a/docs/pause-freeze-states.md b/docs/pause-freeze-states.md new file mode 100644 index 000000000..009ab64b2 --- /dev/null +++ b/docs/pause-freeze-states.md @@ -0,0 +1,73 @@ +# Pause Freeze States + +Some protocol functions may be halted while the protocol is either (i) issuance-paused; (ii) trading-paused; or (iii) frozen. Below is a table that shows which protocol interactions (`@custom:interaction`) and refreshers (`@custom:refresher`) execute during paused/frozen states, as of the 3.1.0 release. + +All governance functions (`@custom:governance`) remain enabled during all paused/frozen states. They are not mentioned here. + +A :heavy_check_mark: indicates the function still executes in this state. +A :x: indicates it reverts. + +| Function | Issuance-Paused | Trading-Paused | Frozen | +| --------------------------------------- | ------------------ | ----------------------- | ----------------------- | +| `BackingManager.claimRewards()` | :heavy_check_mark: | :x: | :x: | +| `BackingManager.claimRewardsSingle()` | :heavy_check_mark: | :x: | :x: | +| `BackingManager.grantRTokenAllowance()` | :heavy_check_mark: | :heavy_check_mark: | :x: | +| `BackingManager.forwardRevenue()` | :heavy_check_mark: | :x: | :x: | +| `BackingManager.rebalance()` | :heavy_check_mark: | :x: | :x: | +| `BackingManager.settleTrade()` | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | +| `BasketHandler.refreshBasket()` | :heavy_check_mark: | :x: (unless governance) | :x: (unless governance) | +| `Broker.openTrade()` | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | +| `Broker.reportViolation()` | :heavy_check_mark: | :x: | :x: | +| `Distributor.distribute()` | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | +| `Furnace.melt()` | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | +| `Main.poke()` | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | +| `RevenueTrader.claimRewards()` | :heavy_check_mark: | :x: | :x: | +| `RevenueTrader.claimRewardsSingle()` | :heavy_check_mark: | :x: | :x: | +| `RevenueTrader.distributeTokenToBuy()` | :heavy_check_mark: | :x: | :x: | +| `RevenueTrader.manageTokens()` | :heavy_check_mark: | :x: | :x: | +| `RevenueTrader.returnTokens()` | :heavy_check_mark: | :x: | :x: | +| `RevenueTrader.settleTrade()` | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | +| `RToken.issue()` | :x: | :heavy_check_mark: | :x: | +| `RToken.issueTo()` | :x: | :heavy_check_mark: | :x: | +| `RToken.redeem()` | :heavy_check_mark: | :heavy_check_mark: | :x: | +| `RToken.redeemTo()` | :heavy_check_mark: | :heavy_check_mark: | :x: | +| `RToken.redeemCustom()` | :heavy_check_mark: | :heavy_check_mark: | :x: | +| `StRSR.cancelUnstake()` | :heavy_check_mark: | :heavy_check_mark: | :x: | +| `StRSR.payoutRewards()` | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | +| `StRSR.stake()` | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | +| `StRSR.seizeRSR()` | :heavy_check_mark: | :x: | :x: | +| `StRSR.unstake()` | :heavy_check_mark: | :x: | :x: | +| `StRSR.withdraw()` | :heavy_check_mark: | :x: | :x: | + +## Issuance-pause + +The issuance-paused states indicates that RToken issuance should be paused, and _only_ that. It is a narrow control knob that is designed solely to protect against a case where bad debt is being injected into the protocol, say, because default detection for an asset has a false negative. + +## Trading-pause + +The trading-paused state has significantly more scope than the issuance-paused state. It is designed to prevent against cases where the protocol may trade unneccesarily. Many other functions in addition to just `BackingManager.rebalance()` and `RevenueTrader.manageTokens()` are halted. In general anything that manages the backing and revenue for an RToken is halted. This may become neccessary to use due to (among other things): + +- An asset's `price()` malfunctions or is manipulated +- A collateral's default detection has a false positive or negative + +## Freezing + +The scope of freezing is the largest, and it should be used least frequently. Nearly all protocol interactions (`@custom:interaction`) are halted. Any refreshers (`@custom:refresher`) remain enabled, as well as `StRSR.stake()` and the "wrap up" routine `*.settleTrade()`. + +An important function of freezing is to provide a finite time for governance to push through a repair proposal an RToken in the event that a 0-day is discovered that requires a contract upgrade. + +### `Furnace.melt()` + +It is necessary for `Furnace.melt()` to remain emabled in order to allow `RTokenAsset.refresh()` to update its `price()`. Any revenue RToken that has already accumulated at the Furnace will continue to be melted, but the flow of new revenue RToken into the contract is halted. + +### `StRSR.payoutRewards()` + +It is necessary for `StRSR.payoutRewards()` to remain enabled in order for `StRSR.stake()` to use the up-to-date StRSR-RSR exchange rate. If it did not, then in the event of freezing there would be an unfair benefit to new stakers. Any revenue RSR that has already accumulated at the StRSR contract will continue to be paid out, but the flow of new revenue RSR into the contract is halted. + +### `StRSR.stake()` + +It is important for `StRSR.stake()` to remain emabled while frozen in order to allow honest RSR to flow into an RToken to vote against malicious governance proposals. + +### `*.settleTrade()` + +The settleTrade functionality must remain enabled in order to maintain the property that dutch auctions will discover the optimal price. If settleTrade were halted, it could become possible for a dutch auction to clear at a much lower price than it should have, simply because bidding was disabled during the earlier portion of the auction. diff --git a/test/Furnace.test.ts b/test/Furnace.test.ts index 15776210b..84d16f32c 100644 --- a/test/Furnace.test.ts +++ b/test/Furnace.test.ts @@ -204,9 +204,9 @@ describe(`FurnaceP${IMPLEMENTATION} contract`, () => { await furnace.connect(addr1).melt() }) - it('Should not melt if frozen #fast', async () => { + it('Should melt if frozen #fast', async () => { await main.connect(owner).freezeShort() - await expect(furnace.connect(addr1).melt()).to.be.revertedWith('frozen') + await furnace.connect(addr1).melt() }) it('Should not melt any funds in the initial block #fast', async () => { @@ -450,40 +450,57 @@ describe(`FurnaceP${IMPLEMENTATION} contract`, () => { it('Regression test -- C4 June 2023 Issue #29', async () => { // https://github.com/code-423n4/2023-06-reserve-findings/issues/29 + const firstRatio = fp('1e-6') + const secondRatio = fp('1e-4') + const mintAmount = fp('100') + + // Set ratio to something cleaner + await expect(furnace.connect(owner).setRatio(firstRatio)) + .to.emit(furnace, 'RatioSet') + .withArgs(config.rewardRatio, firstRatio) + // Transfer to Furnace and do first melt - await rToken.connect(addr1).transfer(furnace.address, bn('10e18')) + await rToken.connect(addr1).transfer(furnace.address, mintAmount) await setNextBlockTimestamp(Number(await getLatestBlockTimestamp()) + Number(ONE_PERIOD)) await furnace.melt() // Should have updated lastPayout + lastPayoutBal expect(await furnace.lastPayout()).to.be.closeTo(await getLatestBlockTimestamp(), 12) expect(await furnace.lastPayout()).to.be.lte(await getLatestBlockTimestamp()) - expect(await furnace.lastPayoutBal()).to.equal(bn('10e18')) + expect(await furnace.lastPayoutBal()).to.equal(mintAmount) - // Advance 99 periods -- should melt at old ratio - await setNextBlockTimestamp(Number(await getLatestBlockTimestamp()) + 99 * Number(ONE_PERIOD)) + // Advance 100 periods -- should melt at old ratio + await setNextBlockTimestamp( + Number(await getLatestBlockTimestamp()) + 100 * Number(ONE_PERIOD) + ) - // Freeze and change ratio + // Freeze and change ratio (melting as a pre-step) await main.connect(owner).freezeForever() - const maxRatio = bn('1e14') - await expect(furnace.connect(owner).setRatio(maxRatio)) + await expect(furnace.connect(owner).setRatio(secondRatio)) .to.emit(furnace, 'RatioSet') - .withArgs(config.rewardRatio, maxRatio) + .withArgs(firstRatio, secondRatio) - // Should have updated lastPayout + lastPayoutBal + // Should have melted expect(await furnace.lastPayout()).to.be.closeTo(await getLatestBlockTimestamp(), 12) expect(await furnace.lastPayout()).to.be.lte(await getLatestBlockTimestamp()) - expect(await furnace.lastPayoutBal()).to.equal(bn('10e18')) // no change + expect(await furnace.lastPayoutBal()).to.eq(fp('99.990000494983830300')) - // Unfreeze and advance 1 period + // Unfreeze and advance 100 periods await main.connect(owner).unfreeze() - await setNextBlockTimestamp(Number(await getLatestBlockTimestamp()) + Number(ONE_PERIOD)) + await setNextBlockTimestamp( + Number(await getLatestBlockTimestamp()) + 100 * Number(ONE_PERIOD) + ) await expect(furnace.melt()).to.emit(rToken, 'Melted') - // Should have updated lastPayout + lastPayoutBal + // Should have updated lastPayout + lastPayoutBal and melted at new ratio expect(await furnace.lastPayout()).to.be.closeTo(await getLatestBlockTimestamp(), 12) expect(await furnace.lastPayout()).to.be.lte(await getLatestBlockTimestamp()) - expect(await furnace.lastPayoutBal()).to.equal(bn('9.999e18')) + expect(await furnace.lastPayoutBal()).to.equal(fp('98.995033865808581644')) + // if the ratio were not increased 100x, this would be more like 99.980001989868666200 + + // Total supply should have decreased by the cumulative melted amount + expect(await rToken.totalSupply()).to.equal(mintAmount.add(await furnace.lastPayoutBal())) + expect(await rToken.basketsNeeded()).to.equal(mintAmount.mul(2)) }) }) diff --git a/test/__snapshots__/FacadeWrite.test.ts.snap b/test/__snapshots__/FacadeWrite.test.ts.snap index 4b4c7894f..143651b3a 100644 --- a/test/__snapshots__/FacadeWrite.test.ts.snap +++ b/test/__snapshots__/FacadeWrite.test.ts.snap @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`FacadeWrite contract Deployment Process Gas Reporting Phase 1 - RToken Deployment 1`] = `8497592`; +exports[`FacadeWrite contract Deployment Process Gas Reporting Phase 1 - RToken Deployment 1`] = `8572904`; exports[`FacadeWrite contract Deployment Process Gas Reporting Phase 2 - Deploy governance 1`] = `5464253`; diff --git a/test/__snapshots__/Furnace.test.ts.snap b/test/__snapshots__/Furnace.test.ts.snap index af06969a2..e905f3eec 100644 --- a/test/__snapshots__/Furnace.test.ts.snap +++ b/test/__snapshots__/Furnace.test.ts.snap @@ -1,35 +1,35 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`FurnaceP1 contract Gas Reporting Melt - A million periods, all at once 1`] = `83931`; +exports[`FurnaceP1 contract Gas Reporting Melt - A million periods, all at once 1`] = `71626`; -exports[`FurnaceP1 contract Gas Reporting Melt - A million periods, all at once 2`] = `89820`; +exports[`FurnaceP1 contract Gas Reporting Melt - A million periods, all at once 2`] = `77515`; -exports[`FurnaceP1 contract Gas Reporting Melt - Many periods, one after the other 1`] = `83931`; +exports[`FurnaceP1 contract Gas Reporting Melt - Many periods, one after the other 1`] = `71626`; -exports[`FurnaceP1 contract Gas Reporting Melt - Many periods, one after the other 2`] = `78303`; +exports[`FurnaceP1 contract Gas Reporting Melt - Many periods, one after the other 2`] = `65998`; -exports[`FurnaceP1 contract Gas Reporting Melt - Many periods, one after the other 3`] = `78303`; +exports[`FurnaceP1 contract Gas Reporting Melt - Many periods, one after the other 3`] = `65998`; -exports[`FurnaceP1 contract Gas Reporting Melt - Many periods, one after the other 4`] = `78303`; +exports[`FurnaceP1 contract Gas Reporting Melt - Many periods, one after the other 4`] = `65998`; -exports[`FurnaceP1 contract Gas Reporting Melt - Many periods, one after the other 5`] = `78303`; +exports[`FurnaceP1 contract Gas Reporting Melt - Many periods, one after the other 5`] = `65998`; -exports[`FurnaceP1 contract Gas Reporting Melt - Many periods, one after the other 6`] = `78303`; +exports[`FurnaceP1 contract Gas Reporting Melt - Many periods, one after the other 6`] = `65998`; -exports[`FurnaceP1 contract Gas Reporting Melt - Many periods, one after the other 7`] = `78303`; +exports[`FurnaceP1 contract Gas Reporting Melt - Many periods, one after the other 7`] = `65998`; -exports[`FurnaceP1 contract Gas Reporting Melt - Many periods, one after the other 8`] = `78303`; +exports[`FurnaceP1 contract Gas Reporting Melt - Many periods, one after the other 8`] = `65998`; -exports[`FurnaceP1 contract Gas Reporting Melt - Many periods, one after the other 9`] = `78303`; +exports[`FurnaceP1 contract Gas Reporting Melt - Many periods, one after the other 9`] = `65998`; -exports[`FurnaceP1 contract Gas Reporting Melt - Many periods, one after the other 10`] = `78303`; +exports[`FurnaceP1 contract Gas Reporting Melt - Many periods, one after the other 10`] = `65998`; -exports[`FurnaceP1 contract Gas Reporting Melt - Many periods, one after the other 11`] = `78303`; +exports[`FurnaceP1 contract Gas Reporting Melt - Many periods, one after the other 11`] = `65998`; -exports[`FurnaceP1 contract Gas Reporting Melt - One period 1`] = `64031`; +exports[`FurnaceP1 contract Gas Reporting Melt - One period 1`] = `51726`; -exports[`FurnaceP1 contract Gas Reporting Melt - One period 2`] = `80663`; +exports[`FurnaceP1 contract Gas Reporting Melt - One period 2`] = `68358`; -exports[`FurnaceP1 contract Gas Reporting Melt - One period 3`] = `78303`; +exports[`FurnaceP1 contract Gas Reporting Melt - One period 3`] = `65998`; -exports[`FurnaceP1 contract Gas Reporting Melt - One period 4`] = `40761`; +exports[`FurnaceP1 contract Gas Reporting Melt - One period 4`] = `28452`; diff --git a/test/__snapshots__/Main.test.ts.snap b/test/__snapshots__/Main.test.ts.snap index 9591a2762..ffecb35bc 100644 --- a/test/__snapshots__/Main.test.ts.snap +++ b/test/__snapshots__/Main.test.ts.snap @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`MainP1 contract Gas Reporting Asset Registry - Refresh 1`] = `357740`; +exports[`MainP1 contract Gas Reporting Asset Registry - Refresh 1`] = `393837`; exports[`MainP1 contract Gas Reporting Asset Registry - Register Asset 1`] = `195889`; diff --git a/test/__snapshots__/RToken.test.ts.snap b/test/__snapshots__/RToken.test.ts.snap index ee00025ae..c725eeb99 100644 --- a/test/__snapshots__/RToken.test.ts.snap +++ b/test/__snapshots__/RToken.test.ts.snap @@ -1,10 +1,10 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`RTokenP1 contract Gas Reporting Issuance: within block 1`] = `787553`; +exports[`RTokenP1 contract Gas Reporting Issuance: within block 1`] = `782158`; -exports[`RTokenP1 contract Gas Reporting Issuance: within block 2`] = `614557`; +exports[`RTokenP1 contract Gas Reporting Issuance: within block 2`] = `609158`; -exports[`RTokenP1 contract Gas Reporting Redemption 1`] = `589266`; +exports[`RTokenP1 contract Gas Reporting Redemption 1`] = `583862`; exports[`RTokenP1 contract Gas Reporting Transfer 1`] = `56658`; diff --git a/test/__snapshots__/Recollateralization.test.ts.snap b/test/__snapshots__/Recollateralization.test.ts.snap index 4222c553e..ddde5b4fe 100644 --- a/test/__snapshots__/Recollateralization.test.ts.snap +++ b/test/__snapshots__/Recollateralization.test.ts.snap @@ -1,19 +1,19 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Recollateralization - P1 Gas Reporting rebalance() - DutchTrade 1`] = `1370490`; +exports[`Recollateralization - P1 Gas Reporting rebalance() - DutchTrade 1`] = `1365473`; -exports[`Recollateralization - P1 Gas Reporting rebalance() - DutchTrade 2`] = `1506234`; +exports[`Recollateralization - P1 Gas Reporting rebalance() - DutchTrade 2`] = `1500861`; -exports[`Recollateralization - P1 Gas Reporting rebalance() - DutchTrade 3`] = `760457`; +exports[`Recollateralization - P1 Gas Reporting rebalance() - DutchTrade 3`] = `755062`; -exports[`Recollateralization - P1 Gas Reporting rebalance() - GnosisTrade 1`] = `1665048`; +exports[`Recollateralization - P1 Gas Reporting rebalance() - GnosisTrade 1`] = `1659319`; exports[`Recollateralization - P1 Gas Reporting rebalance() - GnosisTrade 2`] = `174808`; -exports[`Recollateralization - P1 Gas Reporting rebalance() - GnosisTrade 3`] = `1607593`; +exports[`Recollateralization - P1 Gas Reporting rebalance() - GnosisTrade 3`] = `1602220`; exports[`Recollateralization - P1 Gas Reporting rebalance() - GnosisTrade 4`] = `174808`; -exports[`Recollateralization - P1 Gas Reporting rebalance() - GnosisTrade 5`] = `1695355`; +exports[`Recollateralization - P1 Gas Reporting rebalance() - GnosisTrade 5`] = `1689982`; exports[`Recollateralization - P1 Gas Reporting rebalance() - GnosisTrade 6`] = `202908`; diff --git a/test/__snapshots__/Revenues.test.ts.snap b/test/__snapshots__/Revenues.test.ts.snap index 4275db183..bb7a77e72 100644 --- a/test/__snapshots__/Revenues.test.ts.snap +++ b/test/__snapshots__/Revenues.test.ts.snap @@ -12,11 +12,11 @@ exports[`Revenues - P1 Gas Reporting Claim and Sweep Rewards 5`] = `229377`; exports[`Revenues - P1 Gas Reporting Claim and Sweep Rewards 6`] = `212277`; -exports[`Revenues - P1 Gas Reporting Selling RToken 1`] = `1025829`; +exports[`Revenues - P1 Gas Reporting Selling RToken 1`] = `1020522`; exports[`Revenues - P1 Gas Reporting Settle Trades / Manage Funds 1`] = `774070`; -exports[`Revenues - P1 Gas Reporting Settle Trades / Manage Funds 2`] = `1181105`; +exports[`Revenues - P1 Gas Reporting Settle Trades / Manage Funds 2`] = `1175816`; exports[`Revenues - P1 Gas Reporting Settle Trades / Manage Funds 3`] = `311446`; diff --git a/test/__snapshots__/ZZStRSR.test.ts.snap b/test/__snapshots__/ZZStRSR.test.ts.snap index f4ec1f241..63500d716 100644 --- a/test/__snapshots__/ZZStRSR.test.ts.snap +++ b/test/__snapshots__/ZZStRSR.test.ts.snap @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`StRSRP1 contract Gas Reporting Stake 1`] = `156559`; +exports[`StRSRP1 contract Gas Reporting Stake 1`] = `139717`; exports[`StRSRP1 contract Gas Reporting Stake 2`] = `134917`; @@ -10,10 +10,10 @@ exports[`StRSRP1 contract Gas Reporting Transfer 2`] = `41509`; exports[`StRSRP1 contract Gas Reporting Transfer 3`] = `58621`; -exports[`StRSRP1 contract Gas Reporting Unstake 1`] = `241951`; +exports[`StRSRP1 contract Gas Reporting Unstake 1`] = `222609`; exports[`StRSRP1 contract Gas Reporting Unstake 2`] = `139758`; -exports[`StRSRP1 contract Gas Reporting Withdraw 1`] = `572112`; +exports[`StRSRP1 contract Gas Reporting Withdraw 1`] = `606273`; -exports[`StRSRP1 contract Gas Reporting Withdraw 2`] = `526116`; +exports[`StRSRP1 contract Gas Reporting Withdraw 2`] = `536407`; diff --git a/test/plugins/Asset.test.ts b/test/plugins/Asset.test.ts index c0a49a79a..95ad7cd34 100644 --- a/test/plugins/Asset.test.ts +++ b/test/plugins/Asset.test.ts @@ -34,6 +34,7 @@ import { RTokenAsset, StaticATokenMock, TestIBackingManager, + TestIFurnace, TestIRToken, USDCMock, UnpricedAssetMock, @@ -88,6 +89,7 @@ describe('Assets contracts #fast', () => { let wallet: Wallet let assetRegistry: IAssetRegistry let backingManager: TestIBackingManager + let furnace: TestIFurnace // Factory let AssetFactory: ContractFactory @@ -112,6 +114,7 @@ describe('Assets contracts #fast', () => { assetRegistry, backingManager, config, + furnace, rToken, rTokenAsset, } = await loadFixture(defaultFixture)) @@ -481,6 +484,27 @@ describe('Assets contracts #fast', () => { await expectUnpriced(rTokenAsset.address) }) + it('Regression test -- RTokenAsset.refresh() should refresh everything', async () => { + // AssetRegistry should refresh + const lastRefreshed = await assetRegistry.lastRefresh() + await rTokenAsset.refresh() + expect(await assetRegistry.lastRefresh()).to.be.gt(lastRefreshed) + + // Furnace should melt + const lastPayout = await furnace.lastPayout() + await advanceTime(12) + await rTokenAsset.refresh() + expect(await furnace.lastPayout()).to.be.gt(lastPayout) + + // Should clear oracle cache + await rTokenAsset.forceUpdatePrice() + let [, cachedAtTime] = await rTokenAsset.cachedOracleData() + expect(cachedAtTime).to.be.gt(0) + await rTokenAsset.refresh() + ;[, cachedAtTime] = await rTokenAsset.cachedOracleData() + expect(cachedAtTime).to.eq(0) + }) + it('Should be able to refresh saved prices', async () => { // Check initial prices - use RSR as example let currBlockTimestamp: number = await getLatestBlockTimestamp() diff --git a/test/plugins/individual-collateral/aave/__snapshots__/ATokenFiatCollateral.test.ts.snap b/test/plugins/individual-collateral/aave/__snapshots__/ATokenFiatCollateral.test.ts.snap index 70324e7f4..579773bc8 100644 --- a/test/plugins/individual-collateral/aave/__snapshots__/ATokenFiatCollateral.test.ts.snap +++ b/test/plugins/individual-collateral/aave/__snapshots__/ATokenFiatCollateral.test.ts.snap @@ -14,12 +14,12 @@ exports[`ATokenFiatCollateral - Mainnet Forking P1 Gas Reporting refresh() after exports[`ATokenFiatCollateral - Mainnet Forking P1 Gas Reporting refresh() after soft default 1`] = `91147`; -exports[`ATokenFiatCollateral - Mainnet Forking P1 Gas Reporting refresh() after soft default 2`] = `91073`; +exports[`ATokenFiatCollateral - Mainnet Forking P1 Gas Reporting refresh() after soft default 2`] = `91147`; -exports[`ATokenFiatCollateral - Mainnet Forking P1 Gas Reporting refresh() during SOUND 1`] = `92285`; +exports[`ATokenFiatCollateral - Mainnet Forking P1 Gas Reporting refresh() during SOUND 1`] = `92211`; -exports[`ATokenFiatCollateral - Mainnet Forking P1 Gas Reporting refresh() during SOUND 2`] = `92211`; +exports[`ATokenFiatCollateral - Mainnet Forking P1 Gas Reporting refresh() during SOUND 2`] = `92285`; exports[`ATokenFiatCollateral - Mainnet Forking P1 Gas Reporting refresh() during soft default 1`] = `127356`; -exports[`ATokenFiatCollateral - Mainnet Forking P1 Gas Reporting refresh() during soft default 2`] = `91414`; +exports[`ATokenFiatCollateral - Mainnet Forking P1 Gas Reporting refresh() during soft default 2`] = `91488`; diff --git a/test/plugins/individual-collateral/dsr/__snapshots__/SDaiCollateralTestSuite.test.ts.snap b/test/plugins/individual-collateral/dsr/__snapshots__/SDaiCollateralTestSuite.test.ts.snap index 08efe17a7..eb9ff1862 100644 --- a/test/plugins/individual-collateral/dsr/__snapshots__/SDaiCollateralTestSuite.test.ts.snap +++ b/test/plugins/individual-collateral/dsr/__snapshots__/SDaiCollateralTestSuite.test.ts.snap @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Collateral: SDaiCollateral collateral functionality Gas Reporting refresh() after full price timeout 1`] = `116743`; +exports[`Collateral: SDaiCollateral collateral functionality Gas Reporting refresh() after full price timeout 1`] = `116848`; exports[`Collateral: SDaiCollateral collateral functionality Gas Reporting refresh() after full price timeout 2`] = `108431`; diff --git a/test/plugins/individual-collateral/stargate/__snapshots__/StargateETHTestSuite.test.ts.snap b/test/plugins/individual-collateral/stargate/__snapshots__/StargateETHTestSuite.test.ts.snap deleted file mode 100644 index 3eb694220..000000000 --- a/test/plugins/individual-collateral/stargate/__snapshots__/StargateETHTestSuite.test.ts.snap +++ /dev/null @@ -1,49 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Collateral: Stargate ETH Pool collateral functionality Gas Reporting refresh() after full price timeout 1`] = `55263`; - -exports[`Collateral: Stargate ETH Pool collateral functionality Gas Reporting refresh() after full price timeout 2`] = `50795`; - -exports[`Collateral: Stargate ETH Pool collateral functionality Gas Reporting refresh() after hard default 1`] = `68999`; - -exports[`Collateral: Stargate ETH Pool collateral functionality Gas Reporting refresh() after hard default 2`] = `66385`; - -exports[`Collateral: Stargate ETH Pool collateral functionality Gas Reporting refresh() after oracle timeout 1`] = `55263`; - -exports[`Collateral: Stargate ETH Pool collateral functionality Gas Reporting refresh() after oracle timeout 2`] = `50795`; - -exports[`Collateral: Stargate ETH Pool collateral functionality Gas Reporting refresh() after soft default 1`] = `50454`; - -exports[`Collateral: Stargate ETH Pool collateral functionality Gas Reporting refresh() after soft default 2`] = `50454`; - -exports[`Collateral: Stargate ETH Pool collateral functionality Gas Reporting refresh() during SOUND 1`] = `66260`; - -exports[`Collateral: Stargate ETH Pool collateral functionality Gas Reporting refresh() during SOUND 2`] = `66260`; - -exports[`Collateral: Stargate ETH Pool collateral functionality Gas Reporting refresh() during soft default 1`] = `73810`; - -exports[`Collateral: Stargate ETH Pool collateral functionality Gas Reporting refresh() during soft default 2`] = `66542`; - -exports[`Collateral: Stargate USDC Pool collateral functionality Gas Reporting refresh() after full price timeout 1`] = `55263`; - -exports[`Collateral: Stargate USDC Pool collateral functionality Gas Reporting refresh() after full price timeout 2`] = `50795`; - -exports[`Collateral: Stargate USDC Pool collateral functionality Gas Reporting refresh() after hard default 1`] = `68999`; - -exports[`Collateral: Stargate USDC Pool collateral functionality Gas Reporting refresh() after hard default 2`] = `66385`; - -exports[`Collateral: Stargate USDC Pool collateral functionality Gas Reporting refresh() after oracle timeout 1`] = `55263`; - -exports[`Collateral: Stargate USDC Pool collateral functionality Gas Reporting refresh() after oracle timeout 2`] = `50795`; - -exports[`Collateral: Stargate USDC Pool collateral functionality Gas Reporting refresh() after soft default 1`] = `50454`; - -exports[`Collateral: Stargate USDC Pool collateral functionality Gas Reporting refresh() after soft default 2`] = `50454`; - -exports[`Collateral: Stargate USDC Pool collateral functionality Gas Reporting refresh() during SOUND 1`] = `66260`; - -exports[`Collateral: Stargate USDC Pool collateral functionality Gas Reporting refresh() during SOUND 2`] = `66260`; - -exports[`Collateral: Stargate USDC Pool collateral functionality Gas Reporting refresh() during soft default 1`] = `73810`; - -exports[`Collateral: Stargate USDC Pool collateral functionality Gas Reporting refresh() during soft default 2`] = `66542`; diff --git a/test/plugins/individual-collateral/stargate/__snapshots__/StargateUSDCTestSuite.test.ts.snap b/test/plugins/individual-collateral/stargate/__snapshots__/StargateUSDCTestSuite.test.ts.snap new file mode 100644 index 000000000..fc27356e8 --- /dev/null +++ b/test/plugins/individual-collateral/stargate/__snapshots__/StargateUSDCTestSuite.test.ts.snap @@ -0,0 +1,25 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Collateral: Stargate USDC Pool collateral functionality Gas Reporting refresh() after full price timeout 1`] = `56094`; + +exports[`Collateral: Stargate USDC Pool collateral functionality Gas Reporting refresh() after full price timeout 2`] = `51626`; + +exports[`Collateral: Stargate USDC Pool collateral functionality Gas Reporting refresh() after hard default 1`] = `74579`; + +exports[`Collateral: Stargate USDC Pool collateral functionality Gas Reporting refresh() after hard default 2`] = `66897`; + +exports[`Collateral: Stargate USDC Pool collateral functionality Gas Reporting refresh() after oracle timeout 1`] = `56094`; + +exports[`Collateral: Stargate USDC Pool collateral functionality Gas Reporting refresh() after oracle timeout 2`] = `51626`; + +exports[`Collateral: Stargate USDC Pool collateral functionality Gas Reporting refresh() after soft default 1`] = `51285`; + +exports[`Collateral: Stargate USDC Pool collateral functionality Gas Reporting refresh() after soft default 2`] = `51285`; + +exports[`Collateral: Stargate USDC Pool collateral functionality Gas Reporting refresh() during SOUND 1`] = `66894`; + +exports[`Collateral: Stargate USDC Pool collateral functionality Gas Reporting refresh() during SOUND 2`] = `66894`; + +exports[`Collateral: Stargate USDC Pool collateral functionality Gas Reporting refresh() during soft default 1`] = `74444`; + +exports[`Collateral: Stargate USDC Pool collateral functionality Gas Reporting refresh() during soft default 2`] = `67176`; diff --git a/test/scenario/__snapshots__/MaxBasketSize.test.ts.snap b/test/scenario/__snapshots__/MaxBasketSize.test.ts.snap index fa7f07dd1..156f63233 100644 --- a/test/scenario/__snapshots__/MaxBasketSize.test.ts.snap +++ b/test/scenario/__snapshots__/MaxBasketSize.test.ts.snap @@ -1,19 +1,19 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Max Basket Size - P1 ATokens/CTokens Should Issue/Redeem with max basket correctly 1`] = `12090932`; +exports[`Max Basket Size - P1 ATokens/CTokens Should Issue/Redeem with max basket correctly 1`] = `12082293`; -exports[`Max Basket Size - P1 ATokens/CTokens Should Issue/Redeem with max basket correctly 2`] = `9829293`; +exports[`Max Basket Size - P1 ATokens/CTokens Should Issue/Redeem with max basket correctly 2`] = `9836895`; exports[`Max Basket Size - P1 ATokens/CTokens Should claim rewards correctly 1`] = `2281990`; -exports[`Max Basket Size - P1 ATokens/CTokens Should switch basket correctly 1`] = `13615367`; +exports[`Max Basket Size - P1 ATokens/CTokens Should switch basket correctly 1`] = `13653640`; -exports[`Max Basket Size - P1 ATokens/CTokens Should switch basket correctly 2`] = `20701409`; +exports[`Max Basket Size - P1 ATokens/CTokens Should switch basket correctly 2`] = `20688663`; -exports[`Max Basket Size - P1 Fiatcoins Should Issue/Redeem with max basket correctly 1`] = `10991970`; +exports[`Max Basket Size - P1 Fiatcoins Should Issue/Redeem with max basket correctly 1`] = `10984043`; -exports[`Max Basket Size - P1 Fiatcoins Should Issue/Redeem with max basket correctly 2`] = `8713193`; +exports[`Max Basket Size - P1 Fiatcoins Should Issue/Redeem with max basket correctly 2`] = `8707789`; -exports[`Max Basket Size - P1 Fiatcoins Should switch basket correctly 1`] = `6561514`; +exports[`Max Basket Size - P1 Fiatcoins Should switch basket correctly 1`] = `6592417`; -exports[`Max Basket Size - P1 Fiatcoins Should switch basket correctly 2`] = `14454943`; +exports[`Max Basket Size - P1 Fiatcoins Should switch basket correctly 2`] = `14441485`;