diff --git a/contracts/base/GammaPoolERC4626.sol b/contracts/base/GammaPoolERC4626.sol index 4d4c0fea..7837207b 100644 --- a/contracts/base/GammaPoolERC4626.sol +++ b/contracts/base/GammaPoolERC4626.sol @@ -102,7 +102,15 @@ abstract contract GammaPoolERC4626 is GammaPoolERC20, DelegateCaller, Refunds, P /// @dev Convert CFMM LP tokens to GS LP tokens /// @param assets - CFMM LP tokens /// @return shares - GS LP tokens quantity that corresponds to assets quantity provided as a parameter (CFMM LP tokens) - function convertToShares(uint256 assets) public view virtual returns (uint256) { + function convertToShares(uint256 assets) external view virtual returns (uint256) { + return _convertToShares(assets, true); + } + + /// @dev Convert CFMM LP tokens to GS LP tokens + /// @param assets - CFMM LP tokens + /// @param roundUp - if true round up result else round down + /// @return shares - GS LP tokens quantity that corresponds to assets quantity provided as a parameter (CFMM LP tokens) + function _convertToShares(uint256 assets, bool roundUp) internal view virtual returns (uint256) { if(assets == 0) { return 0; } @@ -115,23 +123,35 @@ abstract contract GammaPoolERC4626 is GammaPoolERC20, DelegateCaller, Refunds, P return assets - MIN_SHARES; } } + + if(roundUp) { + return (assets * supply + (_totalAssets - 1))/ _totalAssets; + } return (assets * supply) / _totalAssets; } /// @dev Convert GS LP tokens to GS LP tokens /// @param shares - GS LP tokens /// @return assets - CFMM LP tokens quantity that corresponds to shares quantity provided as a parameter (GS LP tokens) - function convertToAssets(uint256 shares) public view virtual returns (uint256) { + function convertToAssets(uint256 shares) external view virtual returns (uint256) { + return _convertToAssets(shares, false); + } + + /// @dev Convert GS LP tokens to GS LP tokens + /// @param shares - GS LP tokens + /// @param roundUp - if true round up result else round down + /// @return assets - CFMM LP tokens quantity that corresponds to shares quantity provided as a parameter (GS LP tokens) + function _convertToAssets(uint256 shares, bool roundUp) internal view virtual returns (uint256) { if(shares == 0) { return 0; } (uint256 assets, uint256 supply) = _totalAssetsAndSupply(); if(supply == 0) { - if(shares <= MIN_SHARES) revert MinShares(); + return shares + MIN_SHARES; + } - unchecked { - return shares - MIN_SHARES; - } + if(roundUp) { + return (shares * assets + (supply - 1)) / supply; } // totalAssets is total CFMM LP tokens, including accrued interest, calculated using state variables return (shares * assets) / supply; @@ -141,28 +161,28 @@ abstract contract GammaPoolERC4626 is GammaPoolERC20, DelegateCaller, Refunds, P /// @param assets - CFMM LP tokens /// @return shares - expected GS LP tokens to get from assets (CFMM LP tokens) deposited function previewDeposit(uint256 assets) public view virtual returns (uint256) { - return convertToShares(assets); + return _convertToShares(assets, false); } /// @dev Allows an on-chain or off-chain user to simulate the effects of their mint at the current block, given current on-chain conditions. /// @param shares - GS LP tokens /// @return assets - CFMM LP tokens needed to deposit to get the desired shares (GS LP tokens) function previewMint(uint256 shares) public view virtual returns (uint256) { - return convertToAssets(shares); + return _convertToAssets(shares, true); } /// @dev Allows an on-chain or off-chain user to simulate the effects of their withdrawal at the current block, given current on-chain conditions. /// @param assets - CFMM LP tokens /// @return shares - expected GS LP tokens needed to burn to withdraw desired assets (CFMM LP tokens) function previewWithdraw(uint256 assets) public view virtual returns (uint256) { - return convertToShares(assets); + return _convertToShares(assets, true); } /// @dev Allows an on-chain or off-chain user to simulate the effects of their redemption at the current block, given current on-chain conditions. /// @param shares - GS LP tokens /// @return assets - expected CFMM LP tokens withdrawn if shares (GS LP tokens) burned function previewRedeem(uint256 shares) public view virtual returns (uint256) { - return convertToAssets(shares); + return _convertToAssets(shares, false); } /// @dev Returns the maximum amount of CFMM LP tokens that can be deposited into the Vault for the receiver, through a deposit call. Ignores address parameter @@ -193,14 +213,14 @@ abstract contract GammaPoolERC4626 is GammaPoolERC20, DelegateCaller, Refunds, P /// @param owner - address that owns GS LP tokens /// @return maxAssets - maximum amount of CFMM LP tokens that can be withdrawn by owner address function maxWithdraw(address owner) public view virtual returns (uint256) { - return maxAssets(convertToAssets(s.balanceOf[owner])); // convert owner GS LP tokens to equivalent CFMM LP tokens and check if available to withdraw + return maxAssets(_convertToAssets(s.balanceOf[owner], false)); // convert owner GS LP tokens to equivalent CFMM LP tokens and check if available to withdraw } /// @dev Returns the maximum amount of GS LP tokens that can be redeemed from the owner balance in the Vault, through a redeem call. /// @param owner - address that owns GS LP tokens /// @return maxShares - maximum amount of GS LP tokens that can be redeemed by owner address function maxRedeem(address owner) public view virtual returns (uint256) { - return convertToShares(maxWithdraw(owner)); // get maximum amount of CFMM LP tokens that can be withdrawn and convert to equivalent GS LP token amount + return s.balanceOf[owner]; // get maximum amount of CFMM LP tokens that can be withdrawn and convert to equivalent GS LP token amount } /// @dev Calculate and return total CFMM LP tokens belonging to GammaPool liquidity providers using state global variables. @@ -209,21 +229,23 @@ abstract contract GammaPoolERC4626 is GammaPoolERC20, DelegateCaller, Refunds, P /// @return assets - current total CFMM LP tokens (real and virtual) in existence in the GammaPool, including accrued interest /// @return supply - total supply of GS LP tokens after taking protocol revenue dilution into account function _totalAssetsAndSupply() internal view virtual returns (uint256 assets, uint256 supply) { - IShortStrategy.VaultBalancesParams memory _params; - _params.factory = s.factory; - _params.pool = address(this); - _params.paramsStore = _params.factory; - _params.BORROWED_INVARIANT = s.BORROWED_INVARIANT; - _params.latestCfmmInvariant = _getLatestCFMMInvariant(); - _params.latestCfmmTotalSupply = _getLatestCFMMTotalSupply(); - _params.LAST_BLOCK_NUMBER = s.LAST_BLOCK_NUMBER; - _params.lastCFMMInvariant = s.lastCFMMInvariant; - _params.lastCFMMTotalSupply = s.lastCFMMTotalSupply; - _params.lastCFMMFeeIndex = s.lastCFMMFeeIndex; - _params.totalSupply = s.totalSupply; - _params.LP_TOKEN_BALANCE = s.LP_TOKEN_BALANCE; - _params.LP_INVARIANT = s.LP_INVARIANT; - - (assets, supply) = IShortStrategy(vaultImplementation()).totalAssetsAndSupply(_params); + address _factory = s.factory; + (assets, supply) = IShortStrategy(vaultImplementation()).totalAssetsAndSupply( + IShortStrategy.VaultBalancesParams({ + factory: _factory, + pool: address(this), + paramsStore: _factory, + BORROWED_INVARIANT: s.BORROWED_INVARIANT, + latestCfmmInvariant: _getLatestCFMMInvariant(), + latestCfmmTotalSupply: _getLatestCFMMTotalSupply(), + LAST_BLOCK_NUMBER: s.LAST_BLOCK_NUMBER, + lastCFMMInvariant: s.lastCFMMInvariant, + lastCFMMTotalSupply: s.lastCFMMTotalSupply, + lastCFMMFeeIndex: s.lastCFMMFeeIndex, + totalSupply: s.totalSupply, + LP_TOKEN_BALANCE: s.LP_TOKEN_BALANCE, + LP_INVARIANT: s.LP_INVARIANT + }) + ); } } \ No newline at end of file diff --git a/contracts/strategies/ShortStrategy.sol b/contracts/strategies/ShortStrategy.sol index 9dcf86da..9ef4e16e 100644 --- a/contracts/strategies/ShortStrategy.sol +++ b/contracts/strategies/ShortStrategy.sol @@ -114,13 +114,12 @@ abstract contract ShortStrategy is IShortStrategy, BaseStrategy { updateIndex(); // Convert CFMM LP tokens (`assets`) to GS LP tokens (`shares`) - shares = convertToShares(assets); + shares = convertToShares(assets, false); // revert if request is for 0 GS LP tokens if(shares == 0) revert ZeroShares(); // To prevent rounding errors, lock min shares in first deposit if(s.totalSupply == 0) { - shares = shares - MIN_SHARES; assets = assets - MIN_SHARES; depositAssets(msg.sender, address(0), MIN_SHARES, MIN_SHARES, isDepositReserves); } @@ -209,7 +208,7 @@ abstract contract ShortStrategy is IShortStrategy, BaseStrategy { updateIndex(); // Convert GS LP tokens (`shares`) to CFMM LP tokens (`assets`) - assets = convertToAssets(shares); + assets = convertToAssets(shares, false); // revert if request is for 0 CFMM LP tokens if(assets == 0) revert ZeroAssets(); @@ -307,17 +306,38 @@ abstract contract ShortStrategy is IShortStrategy, BaseStrategy { /// @dev Check if `spender` has permissions to spend `amount` of GS LP tokens belonging to `owner` /// @param assets - address that owns the GS LP tokens - function convertToShares(uint256 assets) internal view virtual returns (uint256) { + /// @param roundUp - if true round up result, else round down + function convertToShares(uint256 assets, bool roundUp) internal view virtual returns (uint256) { + if(assets == 0) { + return 0; + } uint256 supply = s.totalSupply; // Saves an extra SLOAD if totalSupply is non-zero. uint256 _totalAssets = s.LP_TOKEN_BALANCE + s.LP_TOKEN_BORROWED_PLUS_INTEREST; - return supply == 0 || _totalAssets == 0 ? assets : (assets * supply / _totalAssets); + if(supply == 0 || _totalAssets == 0) { + return assets - MIN_SHARES; + } + if(roundUp) { + return (assets * supply + (_totalAssets - 1)) / _totalAssets; + } + return (assets * supply / _totalAssets); } /// @dev Check if `spender` has permissions to spend `amount` of GS LP tokens belonging to `owner` /// @param shares - address that owns the GS LP tokens - function convertToAssets(uint256 shares) internal view virtual returns (uint256) { + /// @param roundUp - if true round up result, else round down + function convertToAssets(uint256 shares, bool roundUp) internal view virtual returns (uint256) { + if(shares == 0) { + return 0; + } uint256 supply = s.totalSupply; // Saves an extra SLOAD if totalSupply is non-zero. - return supply == 0 ? shares : (shares * (s.LP_TOKEN_BALANCE + s.LP_TOKEN_BORROWED_PLUS_INTEREST) / supply); + if(supply == 0) { + return shares + MIN_SHARES; + } + uint256 _totalAssets = s.LP_TOKEN_BALANCE + s.LP_TOKEN_BORROWED_PLUS_INTEREST; + if(roundUp) { + return (shares * _totalAssets + (supply - 1)) / supply; + } + return (shares * _totalAssets) / supply; } // INTERNAL HOOKS LOGIC diff --git a/contracts/strategies/ShortStrategyERC4626.sol b/contracts/strategies/ShortStrategyERC4626.sol index 7470c065..2360093e 100644 --- a/contracts/strategies/ShortStrategyERC4626.sol +++ b/contracts/strategies/ShortStrategyERC4626.sol @@ -15,7 +15,7 @@ abstract contract ShortStrategyERC4626 is ShortStrategy { updateIndex(); // Convert CFMM LP tokens to GS LP tokens - shares = convertToShares(assets); + shares = convertToShares(assets, false); // Revert if redeeming 0 GS LP tokens if(shares == 0) revert ZeroShares(); @@ -30,7 +30,7 @@ abstract contract ShortStrategyERC4626 is ShortStrategy { updateIndex(); // Convert GS LP tokens to CFMM LP tokens - assets = convertToAssets(shares); + assets = convertToAssets(shares, true); // Revert if withdrawing 0 CFMM LP tokens if(assets == 0) revert ZeroAssets(); @@ -48,7 +48,7 @@ abstract contract ShortStrategyERC4626 is ShortStrategy { if(assets > s.LP_TOKEN_BALANCE) revert ExcessiveWithdrawal(); // Convert CFMM LP tokens to GS LP tokens - shares = convertToShares(assets); + shares = convertToShares(assets, true); // Revert if redeeming 0 GS LP tokens if(shares == 0) revert ZeroShares(); @@ -63,7 +63,7 @@ abstract contract ShortStrategyERC4626 is ShortStrategy { updateIndex(); // Convert GS LP tokens to CFMM LP tokens - assets = convertToAssets(shares); + assets = convertToAssets(shares, false); if(assets == 0) revert ZeroAssets(); // revert if withdrawing 0 CFMM LP tokens // Revert if not enough CFMM LP tokens to withdraw @@ -84,7 +84,6 @@ abstract contract ShortStrategyERC4626 is ShortStrategy { // To prevent rounding errors, lock min shares in first deposit if(s.totalSupply == 0) { - shares = shares - MIN_SHARES; assets = assets - MIN_SHARES; depositAssets(caller, address(0), MIN_SHARES, MIN_SHARES, false); } diff --git a/contracts/strategies/base/BaseStrategy.sol b/contracts/strategies/base/BaseStrategy.sol index 87b0eb21..6bd90cf9 100644 --- a/contracts/strategies/base/BaseStrategy.sol +++ b/contracts/strategies/base/BaseStrategy.sol @@ -167,8 +167,8 @@ abstract contract BaseStrategy is AppStorage, AbstractRateModel { /// @param borrowedInvariant - liquidity invariant borrowed in the GammaPool /// @param lastFeeIndex - interest accrued to loans in GammaPool /// @return newBorrowedInvariant - borrowed invariant with accrued interest - function accrueBorrowedInvariant(uint256 borrowedInvariant, uint256 lastFeeIndex) internal virtual pure returns(uint256) { - return borrowedInvariant * lastFeeIndex / 1e18; + function accrueBorrowedInvariant(uint256 borrowedInvariant, uint256 lastFeeIndex) internal virtual view returns(uint256) { + return borrowedInvariant * lastFeeIndex / 1e18; } /// @notice Convert CFMM LP tokens into liquidity invariant units. diff --git a/contracts/test/strategies/base/TestBaseShortStrategy.sol b/contracts/test/strategies/base/TestBaseShortStrategy.sol index da97dd38..4299ca1e 100644 --- a/contracts/test/strategies/base/TestBaseShortStrategy.sol +++ b/contracts/test/strategies/base/TestBaseShortStrategy.sol @@ -101,7 +101,7 @@ abstract contract TestBaseShortStrategy is ShortStrategy { function depositLPTokens(address to) public virtual { uint256 assets = IERC20(s.cfmm).balanceOf(address(this)) - s.LP_TOKEN_BALANCE; - uint256 shares = convertToShares(assets); + uint256 shares = convertToShares(assets, false); _mint(to, shares); s.LP_TOKEN_BALANCE = IERC20(s.cfmm).balanceOf(address(this)); } @@ -138,11 +138,15 @@ abstract contract TestBaseShortStrategy is ShortStrategy { } function _convertToShares(uint256 assets) public view virtual returns(uint256) { - return convertToShares(assets); + return convertToShares(assets, true); } function _convertToAssets(uint256 shares) public view virtual returns(uint256) { - return convertToAssets(shares); + return convertToAssets(shares, false); + } + + function _convertToAssets2(uint256 shares, bool roundUp) public view virtual returns(uint256) { + return convertToAssets(shares, roundUp); } function calcBorrowRate(uint256 lpInvariant, uint256 borrowedInvariant, address paramsStore, address pool) public virtual diff --git a/package.json b/package.json index 91a81011..293ae231 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@gammaswap/v1-core", - "version": "1.2.11", + "version": "1.2.12", "description": "Core smart contracts for the GammaSwap V1 protocol", "homepage": "https://gammaswap.com", "scripts": { diff --git a/test/GammaPoolERC4626.test.ts b/test/GammaPoolERC4626.test.ts index bc1ecaec..a61326aa 100644 --- a/test/GammaPoolERC4626.test.ts +++ b/test/GammaPoolERC4626.test.ts @@ -100,7 +100,8 @@ describe("GammaPoolERC4626", function () { async function convertToShares( assets: BigNumber, supply: BigNumber, - totalAssets: BigNumber + totalAssets: BigNumber, + roundUp: boolean ): Promise { if (assets.eq(0)) { return ethers.constants.Zero; @@ -108,19 +109,26 @@ describe("GammaPoolERC4626", function () { if (supply.eq(0) || totalAssets.eq(0)) { return assets.sub(MIN_SHARES); // First deposit in GammaPool will require minting MIN_SHARES } + if (roundUp) { + return assets.mul(supply).add(totalAssets.sub(1)).div(totalAssets); + } return assets.mul(supply).div(totalAssets); } async function convertToAssets( shares: BigNumber, supply: BigNumber, - totalAssets: BigNumber + totalAssets: BigNumber, + roundUp: boolean ): Promise { if (shares.eq(0)) { return ethers.constants.Zero; } if (supply.eq(0)) { - return shares.sub(MIN_SHARES); // First deposit in GammaPool will require minting MIN_SHARES + return shares.add(MIN_SHARES); // First deposit in GammaPool will require minting MIN_SHARES + } + if (roundUp) { + return shares.mul(totalAssets).add(supply.sub(1)).div(supply); } return shares.mul(totalAssets).div(supply); } @@ -147,21 +155,29 @@ describe("GammaPoolERC4626", function () { async function testConvertToShares( assets: BigNumber, convert2Shares: Function, - convert2Assets: Function + convert2Assets: Function, + roundUpShares: boolean, + roundUpAssets: boolean ): Promise { const totalSupply = await gammaPool.totalSupply(); const totalAssets = await gammaPool.totalAssets(); const convertedToShares = await convertToShares( assets, totalSupply, - totalAssets + totalAssets, + roundUpShares ); const _convertedToShares = await convert2Shares(assets); expect(_convertedToShares).to.be.equal(convertedToShares); expect(await convert2Assets(convertedToShares)).to.be.equal( - await convertToAssets(convertedToShares, totalSupply, totalAssets) + await convertToAssets( + convertedToShares, + totalSupply, + totalAssets, + roundUpAssets + ) ); return convertedToShares; @@ -170,21 +186,60 @@ describe("GammaPoolERC4626", function () { async function testConvertToAssets( shares: BigNumber, convert2Assets: Function, - convert2Shares: Function + convert2Shares: Function, + roundUpAssets: boolean, + roundUpShares: boolean ): Promise { const totalSupply = await gammaPool.totalSupply(); const totalAssets = await gammaPool.totalAssets(); const convertedToAssets = await convertToAssets( shares, totalSupply, - totalAssets + totalAssets, + roundUpAssets ); const _convertedToAssets = await convert2Assets(shares); expect(_convertedToAssets).to.be.equal(convertedToAssets); expect(await convert2Shares(convertedToAssets)).to.be.equal( - await convertToShares(convertedToAssets, totalSupply, totalAssets) + await convertToShares( + convertedToAssets, + totalSupply, + totalAssets, + roundUpShares + ) + ); + + return convertedToAssets; + } + + async function testConvertToAssets2( + shares: BigNumber, + convert2Assets: Function, + convert2Assets2: Function, + roundUpAssets: boolean, + roundUpAssets2: boolean + ): Promise { + const totalSupply = await gammaPool.totalSupply(); + const totalAssets = await gammaPool.totalAssets(); + const convertedToAssets = await convertToAssets( + shares, + totalSupply, + totalAssets, + roundUpAssets + ); + + const _convertedToAssets = await convert2Assets(shares); + + expect(_convertedToAssets).to.be.equal(convertedToAssets); + expect(await convert2Assets2(convertedToAssets)).to.be.equal( + await convertToAssets( + convertedToAssets, + totalSupply, + totalAssets, + roundUpAssets2 + ) ); return convertedToAssets; @@ -347,7 +402,9 @@ describe("GammaPoolERC4626", function () { expect(await gammaPool.maxWithdraw(owner.address)).to.be.equal( await gammaPool.convertToAssets(balanceOwner) ); - expect(await gammaPool.maxRedeem(owner.address)).to.be.equal(0); + expect(await gammaPool.maxRedeem(owner.address)).to.be.equal( + balanceOwner + ); // supply > 0, (assets > 0, shares > 0) const assets1 = ONE.mul(1000); @@ -379,14 +436,18 @@ describe("GammaPoolERC4626", function () { await testConvertToShares( assets0, gammaPool.convertToShares, - gammaPool.convertToAssets + gammaPool.convertToAssets, + true, + false ) ).to.be.equal(assets0); expect( await testConvertToAssets( shares0, gammaPool.convertToAssets, - gammaPool.convertToShares + gammaPool.convertToShares, + false, + true ) ).to.be.equal(shares0); @@ -400,14 +461,18 @@ describe("GammaPoolERC4626", function () { await testConvertToShares( assets1, gammaPool.convertToShares, - gammaPool.convertToAssets + gammaPool.convertToAssets, + true, + false ) ).to.be.equal(assets1.sub(MIN_SHARES)); expect( await testConvertToAssets( shares1, gammaPool.convertToAssets, - gammaPool.convertToShares + gammaPool.convertToShares, + false, + true ) ).to.be.equal(shares1); }); @@ -425,14 +490,18 @@ describe("GammaPoolERC4626", function () { await testConvertToShares( assets0, gammaPool.convertToShares, - gammaPool.convertToAssets + gammaPool.convertToAssets, + true, + false ) ).to.be.equal(assets0); expect( await testConvertToAssets( shares0, gammaPool.convertToAssets, - gammaPool.convertToShares + gammaPool.convertToShares, + false, + true ) ).to.be.equal(0); @@ -446,14 +515,18 @@ describe("GammaPoolERC4626", function () { await testConvertToShares( assets1, gammaPool.convertToShares, - gammaPool.convertToAssets + gammaPool.convertToAssets, + true, + false ) ).to.not.equal(assets1); expect( await testConvertToAssets( shares1, gammaPool.convertToAssets, - gammaPool.convertToShares + gammaPool.convertToShares, + false, + true ) ).to.not.equal(shares1); @@ -467,14 +540,18 @@ describe("GammaPoolERC4626", function () { await testConvertToShares( assets2, gammaPool.convertToShares, - gammaPool.convertToAssets + gammaPool.convertToAssets, + true, + false ) ).to.not.equal(assets2); expect( await testConvertToAssets( shares2, gammaPool.convertToAssets, - gammaPool.convertToShares + gammaPool.convertToShares, + false, + true ) ).to.not.equal(shares2); }); @@ -492,14 +569,18 @@ describe("GammaPoolERC4626", function () { await testConvertToShares( assets0, gammaPool.previewDeposit, - gammaPool.previewMint + gammaPool.previewMint, + false, + true ) ).to.be.equal(assets0); expect( await testConvertToAssets( shares0, gammaPool.previewMint, - gammaPool.previewDeposit + gammaPool.previewDeposit, + true, + false ) ).to.be.equal(shares0); @@ -510,17 +591,12 @@ describe("GammaPoolERC4626", function () { await updateBalances(assets1, shares1); expect( - await testConvertToShares( - assets1, - gammaPool.previewMint, - gammaPool.convertToAssets - ) - ).to.be.equal(assets1.sub(MIN_SHARES)); - expect( - await testConvertToAssets( + await testConvertToAssets2( shares1, gammaPool.convertToAssets, - gammaPool.previewMint + gammaPool.previewMint, + false, + true ) ).to.be.equal(shares1); }); @@ -538,14 +614,18 @@ describe("GammaPoolERC4626", function () { await testConvertToShares( assets0, gammaPool.previewDeposit, - gammaPool.previewMint + gammaPool.previewMint, + false, + true ) ).to.be.equal(assets0); expect( await testConvertToAssets( shares0, gammaPool.previewMint, - gammaPool.previewDeposit + gammaPool.previewDeposit, + true, + false ) ).to.be.equal(0); @@ -559,14 +639,18 @@ describe("GammaPoolERC4626", function () { await testConvertToShares( assets1, gammaPool.previewDeposit, - gammaPool.previewMint + gammaPool.previewMint, + false, + true ) ).to.not.equal(assets1); expect( await testConvertToAssets( shares1, gammaPool.previewMint, - gammaPool.previewDeposit + gammaPool.previewDeposit, + true, + false ) ).to.not.equal(shares1); @@ -580,14 +664,18 @@ describe("GammaPoolERC4626", function () { await testConvertToShares( assets2, gammaPool.previewDeposit, - gammaPool.previewMint + gammaPool.previewMint, + false, + true ) ).to.not.equal(assets2); expect( await testConvertToAssets( shares2, gammaPool.previewMint, - gammaPool.previewDeposit + gammaPool.previewDeposit, + true, + false ) ).to.not.equal(shares2); }); @@ -603,14 +691,18 @@ describe("GammaPoolERC4626", function () { await testConvertToShares( assets0, gammaPool.previewWithdraw, - gammaPool.previewRedeem + gammaPool.previewRedeem, + true, + false ) ).to.be.equal(assets0); expect( await testConvertToAssets( shares0, gammaPool.previewRedeem, - gammaPool.previewWithdraw + gammaPool.previewWithdraw, + false, + true ) ).to.be.equal(shares0); @@ -624,14 +716,18 @@ describe("GammaPoolERC4626", function () { await testConvertToShares( assets1, gammaPool.previewWithdraw, - gammaPool.previewRedeem + gammaPool.previewRedeem, + true, + false ) ).to.be.equal(assets1.sub(MIN_SHARES)); expect( await testConvertToAssets( shares1, gammaPool.previewRedeem, - gammaPool.previewWithdraw + gammaPool.previewWithdraw, + false, + true ) ).to.be.equal(shares1); }); @@ -649,14 +745,18 @@ describe("GammaPoolERC4626", function () { await testConvertToShares( assets0, gammaPool.previewWithdraw, - gammaPool.previewRedeem + gammaPool.previewRedeem, + true, + false ) ).to.be.equal(assets0); expect( await testConvertToAssets( shares0, gammaPool.previewRedeem, - gammaPool.previewWithdraw + gammaPool.previewWithdraw, + false, + true ) ).to.be.equal(0); @@ -670,14 +770,18 @@ describe("GammaPoolERC4626", function () { await testConvertToShares( assets1, gammaPool.previewWithdraw, - gammaPool.previewRedeem + gammaPool.previewRedeem, + true, + false ) ).to.not.equal(assets1); expect( await testConvertToAssets( shares1, gammaPool.previewRedeem, - gammaPool.previewWithdraw + gammaPool.previewWithdraw, + false, + true ) ).to.not.equal(shares1); @@ -691,14 +795,18 @@ describe("GammaPoolERC4626", function () { await testConvertToShares( assets2, gammaPool.previewWithdraw, - gammaPool.previewRedeem + gammaPool.previewRedeem, + true, + false ) ).to.not.equal(assets2); expect( await testConvertToAssets( shares2, gammaPool.previewRedeem, - gammaPool.previewWithdraw + gammaPool.previewWithdraw, + false, + true ) ).to.not.equal(shares2); }); diff --git a/test/strategies/ShortStrategy.test.ts b/test/strategies/ShortStrategy.test.ts index 64aa125a..a113e569 100644 --- a/test/strategies/ShortStrategy.test.ts +++ b/test/strategies/ShortStrategy.test.ts @@ -4,6 +4,7 @@ import { BigNumber } from "ethers"; import { Address } from "cluster"; const PROTOCOL_ID = 1; +const MIN_SHARES = 1000; describe("ShortStrategy", function () { let TestERC20: any; @@ -65,19 +66,37 @@ describe("ShortStrategy", function () { async function convertToShares( assets: BigNumber, supply: BigNumber, - totalAssets: BigNumber + totalAssets: BigNumber, + roundUp: boolean ): Promise { - return supply.eq(0) || totalAssets.eq(0) - ? assets - : assets.mul(supply).div(totalAssets); + if (assets.eq(0)) { + return BigNumber.from(0); + } + if (supply.eq(0) || totalAssets.eq(0)) { + return assets.sub(MIN_SHARES); + } + if (roundUp) { + return assets.mul(supply).add(totalAssets.sub(1)).div(totalAssets); + } + return assets.mul(supply).div(totalAssets); } async function convertToAssets( shares: BigNumber, supply: BigNumber, - totalAssets: BigNumber + totalAssets: BigNumber, + roundUp: boolean ): Promise { - return supply.eq(0) ? shares : shares.mul(totalAssets).div(supply); + if (shares.eq(0)) { + return BigNumber.from(0); + } + if (supply.eq(0)) { + return shares.add(MIN_SHARES); + } + if (roundUp) { + return shares.mul(totalAssets).add(supply.sub(1)).div(supply); + } + return shares.mul(totalAssets).div(supply); } // increase totalAssets by assets, increase totalSupply by shares @@ -108,14 +127,15 @@ describe("ShortStrategy", function () { const convertedToShares = await convertToShares( assets, totalSupply, - totalAssets + totalAssets, + true ); const _convertedToShares = await convert2Shares(assets); expect(_convertedToShares).to.be.equal(convertedToShares); expect(await convert2Assets(convertedToShares)).to.be.equal( - await convertToAssets(convertedToShares, totalSupply, totalAssets) + await convertToAssets(convertedToShares, totalSupply, totalAssets, false) ); return convertedToShares; @@ -477,7 +497,7 @@ describe("ShortStrategy", function () { strategy._convertToShares, strategy._convertToAssets ) - ).to.be.equal(assets1); + ).to.be.equal(assets1.sub(MIN_SHARES)); expect( await testConvertToAssets( shares1, @@ -623,7 +643,7 @@ describe("ShortStrategy", function () { await expect( strategy._depositNoPull(owner.address) - ).to.be.revertedWithCustomError(strategy, "ZeroAmount"); + ).to.be.revertedWithCustomError(strategy, "ZeroShares"); }); it("First Deposit Assets/LP Tokens", async function () { @@ -699,9 +719,7 @@ describe("ShortStrategy", function () { expect(depositEvent.args.caller).to.equal(owner.address); expect(depositEvent.args.to).to.equal(owner.address); expect(depositEvent.args.assets).to.equal(assets.sub(minShares)); - expect(depositEvent.args.shares).to.equal( - expectedGSShares.sub(minShares) - ); + expect(depositEvent.args.shares).to.equal(expectedGSShares); const poolUpdatedEvent = events[events.length - 1]; expect(poolUpdatedEvent.event).to.equal("PoolUpdated"); @@ -724,13 +742,15 @@ describe("ShortStrategy", function () { expect(poolUpdatedEvent.args.cfmmReserves[1]).to.equal(cfmmReserves[1]); expect(poolUpdatedEvent.args.txType).to.equal(0); - expect(await strategy.totalSupply0()).to.equal(expectedGSShares); + expect(await strategy.totalSupply0()).to.equal( + expectedGSShares.add(minShares) + ); expect(await strategy.balanceOf(owner.address)).to.equal( - expectedGSShares.sub(minShares) + expectedGSShares ); const params1 = await strategy.getTotalAssetsParams(); expect(params1.lpBalance).to.equal(assets); - expect(assets).to.equal(expectedGSShares); + expect(assets).to.equal(expectedGSShares.add(minShares)); }); it("Total Assets Ignore CFMM Fee if Same Block", async function () { @@ -872,13 +892,13 @@ describe("ShortStrategy", function () { expect(depositEvent.args.caller).to.equal(owner.address); expect(depositEvent.args.to).to.equal(owner.address); expect(depositEvent.args.assets).to.equal(assets.sub(minShares)); - expect(depositEvent.args.shares).to.equal( - expectedGSShares.sub(minShares) - ); + expect(depositEvent.args.shares).to.equal(expectedGSShares); - expect(await strategy.totalSupply0()).to.equal(expectedGSShares); + expect(await strategy.totalSupply0()).to.equal( + expectedGSShares.add(minShares) + ); expect(await strategy.balanceOf(owner.address)).to.equal( - expectedGSShares.sub(minShares) + expectedGSShares ); await (await cfmm.trade(tradeYield)).wait(); @@ -973,7 +993,10 @@ describe("ShortStrategy", function () { strategy._withdrawNoPull(owner.address) ).to.be.revertedWithCustomError(strategy, "ZeroAssets"); - await (await strategy.transfer(strategy.address, assets)).wait(); + const minShares = BigNumber.from(1000); + await ( + await strategy.transfer(strategy.address, assets.sub(minShares)) + ).wait(); await borrowLPTokens(ONE.mul(1)); @@ -987,9 +1010,17 @@ describe("ShortStrategy", function () { const assets = ONE.mul(200); await prepareAssetsToWithdraw(assets, owner); - const withdrawAssets = ONE.mul(50); const shares = ONE.mul(50); + const totalSupply = await strategy.totalSupply0(); + const strategyCFMMBalance = await cfmm.balanceOf(strategy.address); + const withdrawAssets = await convertToAssets( + shares, + totalSupply, + strategyCFMMBalance, + false + ); + await (await strategy.transfer(strategy.address, shares)).wait(); await testWithdraw( @@ -1123,7 +1154,7 @@ describe("ShortStrategy", function () { await expect( posManager.depositReserves(owner.address, [500, 500], [0, 0]) - ).to.be.revertedWithCustomError(posManager, "ZeroAmount"); + ).to.be.revertedWithCustomError(posManager, "ZeroShares"); }); it("First Deposit Reserves", async function () { @@ -1241,11 +1272,11 @@ describe("ShortStrategy", function () { expect(depositReserveEvent.args.reserves[1]).to.equal(1000); expect(depositReserveEvent.args.shares).to.equal(minShares); - expect(await strategy.totalSupply0()).to.equal(expectedGSShares); + expect(await strategy.totalSupply0()).to.equal(expectedGSShares.add(minShares)); expect(await strategy.balanceOf(owner.address)).to.equal(minShares); const params1 = await strategy.getTotalAssetsParams(); expect(params1.lpBalance).to.equal(assets); - expect(assets).to.equal(expectedGSShares); + expect(assets).to.equal(expectedGSShares.add(minShares)); }); it("More Deposit Reserves", async function () { @@ -1288,13 +1319,13 @@ describe("ShortStrategy", function () { expect(depositEvent.args.caller).to.equal(posManager.address); expect(depositEvent.args.to).to.equal(owner.address); expect(depositEvent.args.assets).to.equal(assets.sub(minShares)); - expect(depositEvent.args.shares).to.equal( - expectedGSShares.sub(minShares) - ); + expect(depositEvent.args.shares).to.equal(expectedGSShares); - expect(await strategy.totalSupply0()).to.equal(expectedGSShares); + expect(await strategy.totalSupply0()).to.equal( + expectedGSShares.add(minShares) + ); expect(await strategy.balanceOf(owner.address)).to.equal( - expectedGSShares.sub(minShares) + expectedGSShares ); await (await cfmm.trade(tradeYield)).wait(); @@ -1393,7 +1424,10 @@ describe("ShortStrategy", function () { strategy._withdrawReserves(owner.address) ).to.be.revertedWithCustomError(strategy, "ZeroAssets"); - await (await strategy.transfer(strategy.address, assets)).wait(); + const minShares = BigNumber.from(1000); + await ( + await strategy.transfer(strategy.address, assets.sub(minShares)) + ).wait(); await borrowLPTokens(ONE.mul(1)); @@ -1407,9 +1441,17 @@ describe("ShortStrategy", function () { const assets = ONE.mul(200); await prepareAssetsToWithdraw(assets, owner); - const withdrawAssets = ONE.mul(50); const shares = ONE.mul(50); + const totalSupply = await strategy.totalSupply0(); + const strategyCFMMBalance = await cfmm.balanceOf(strategy.address); + const withdrawAssets = await convertToAssets( + shares, + totalSupply, + strategyCFMMBalance, + false + ); + // px is assumed to be 2 await (await strategy.transfer(strategy.address, shares)).wait(); diff --git a/test/strategies/ShortStrategyERC4626.test.ts b/test/strategies/ShortStrategyERC4626.test.ts index fc6d81c7..22308c91 100644 --- a/test/strategies/ShortStrategyERC4626.test.ts +++ b/test/strategies/ShortStrategyERC4626.test.ts @@ -52,19 +52,37 @@ describe("ShortStrategyERC4626", function () { async function convertToShares( assets: BigNumber, supply: BigNumber, - totalAssets: BigNumber + totalAssets: BigNumber, + roundUp: boolean ): Promise { - return supply.eq(0) || totalAssets.eq(0) - ? assets - : assets.mul(supply).div(totalAssets); + if (assets.eq(0)) { + return BigNumber.from(0); + } + if (supply.eq(0) || totalAssets.eq(0)) { + return assets.sub(1000); + } + if (roundUp) { + return assets.mul(supply).add(totalAssets.sub(1)).div(totalAssets); + } + return assets.mul(supply).div(totalAssets); } async function convertToAssets( shares: BigNumber, supply: BigNumber, - totalAssets: BigNumber + totalAssets: BigNumber, + roundUp: boolean ): Promise { - return supply.eq(0) ? shares : shares.mul(totalAssets).div(supply); + if (shares.eq(0)) { + return BigNumber.from(0); + } + if (supply.eq(0)) { + return shares.add(1000); + } + if (roundUp) { + return shares.mul(totalAssets).add(supply.sub(1)).div(supply); + } + return shares.mul(totalAssets).div(supply); } // increase totalAssets by assets, increase totalSupply by shares @@ -88,21 +106,29 @@ describe("ShortStrategyERC4626", function () { async function testConvertToShares( assets: BigNumber, convert2Shares: Function, - convert2Assets: Function + convert2Assets: Function, + roundUpShares: boolean, + roundUpAssets: boolean ): Promise { const totalSupply = await strategy.totalSupply0(); const totalAssets = await strategy.getTotalAssets(); const convertedToShares = await convertToShares( assets, totalSupply, - totalAssets + totalAssets, + roundUpShares ); const _convertedToShares = await convert2Shares(assets); expect(_convertedToShares).to.be.equal(convertedToShares); expect(await convert2Assets(convertedToShares)).to.be.equal( - await convertToAssets(convertedToShares, totalSupply, totalAssets) + await convertToAssets( + convertedToShares, + totalSupply, + totalAssets, + roundUpAssets + ) ); return convertedToShares; @@ -111,21 +137,29 @@ describe("ShortStrategyERC4626", function () { async function testConvertToAssets( shares: BigNumber, convert2Assets: Function, - convert2Shares: Function + convert2Shares: Function, + roundUpAssets: boolean, + roundUpShares: boolean ): Promise { const totalSupply = await strategy.totalSupply0(); const totalAssets = await strategy.getTotalAssets(); const convertedToAssets = await convertToAssets( shares, totalSupply, - totalAssets + totalAssets, + roundUpAssets ); const _convertedToAssets = await convert2Assets(shares); expect(_convertedToAssets).to.be.equal(convertedToAssets); expect(await convert2Shares(convertedToAssets)).to.be.equal( - await convertToShares(convertedToAssets, totalSupply, totalAssets) + await convertToShares( + convertedToAssets, + totalSupply, + totalAssets, + roundUpShares + ) ); return convertedToAssets; @@ -311,6 +345,48 @@ describe("ShortStrategyERC4626", function () { ); } + async function testERC4626Redeem( + from: Address, + to: Address, + assets: BigNumber, + shares: BigNumber, + ownerAssetChange: BigNumber, + receiverAssetChange: BigNumber, + ownerShareChange: BigNumber, + receiverShareChange: BigNumber, + cfmmSupplyChange: BigNumber, + erc4626WithdrawFunc: Function + ) { + const resp = await strategy.getLPTokenBalAndBorrowedInv(); + + const totalSupply = await strategy.totalSupply0(); + const ownerBalance = await strategy.balanceOf(from); + const receiverBalance = await strategy.balanceOf(to); + const totalCFMMSupply = await cfmm.totalSupply(); + const strategyCFMMBalance = await cfmm.balanceOf(strategy.address); + const ownerCFMMBalance = await cfmm.balanceOf(from); + const receiverCFMMBalance = await cfmm.balanceOf(to); + + expect(resp.lpTokenBal).to.equal(strategyCFMMBalance); + + const receiverAddr = to; + const ownerAddr = from; + + await erc4626WithdrawFunc(shares, receiverAddr, ownerAddr); + + await checkWithdrawal( + from, + to, + totalSupply.sub(shares), + ownerBalance.sub(ownerShareChange), + receiverBalance.sub(receiverShareChange), + totalCFMMSupply.sub(cfmmSupplyChange), + strategyCFMMBalance.sub(assets), + ownerCFMMBalance.add(ownerAssetChange), + receiverCFMMBalance.add(receiverAssetChange) + ); + } + // You can nest describe calls to create subsections. describe("Deployment", function () { it("Check Init Params", async function () { @@ -490,7 +566,7 @@ describe("ShortStrategyERC4626", function () { await expect( strategy._deposit(minShares, owner.address) - ).to.be.revertedWithCustomError(strategy, "ZeroAmount"); + ).to.be.revertedWithCustomError(strategy, "ZeroShares"); }); it("First Deposit Assets/LP Tokens", async function () { @@ -567,9 +643,7 @@ describe("ShortStrategyERC4626", function () { expect(depositEvent.args.caller).to.equal(owner.address); expect(depositEvent.args.to).to.equal(owner.address); expect(depositEvent.args.assets).to.equal(assets.sub(minShares)); - expect(depositEvent.args.shares).to.equal( - expectedGSShares.sub(minShares) - ); + expect(depositEvent.args.shares).to.equal(expectedGSShares); const poolUpdatedEvent = events[events.length - 1]; expect(poolUpdatedEvent.event).to.equal("PoolUpdated"); @@ -591,13 +665,15 @@ describe("ShortStrategyERC4626", function () { expect(poolUpdatedEvent.args.cfmmReserves[1]).to.equal(cfmmReserves[1]); expect(poolUpdatedEvent.args.txType).to.equal(0); - expect(await strategy.totalSupply0()).to.equal(expectedGSShares); + expect(await strategy.totalSupply0()).to.equal( + expectedGSShares.add(minShares) + ); expect(await strategy.balanceOf(owner.address)).to.equal( - expectedGSShares.sub(minShares) + expectedGSShares ); const params1 = await strategy.getTotalAssetsParams(); expect(params1.lpBalance).to.equal(assets); - expect(assets).to.equal(expectedGSShares); + expect(assets).to.equal(expectedGSShares.add(minShares)); }); it("More Deposit Assets/LP Tokens", async function () { @@ -633,13 +709,13 @@ describe("ShortStrategyERC4626", function () { expect(depositEvent.args.caller).to.equal(owner.address); expect(depositEvent.args.to).to.equal(owner.address); expect(depositEvent.args.assets).to.equal(assets.sub(minShares)); - expect(depositEvent.args.shares).to.equal( - expectedGSShares.sub(minShares) - ); + expect(depositEvent.args.shares).to.equal(expectedGSShares); - expect(await strategy.totalSupply0()).to.equal(expectedGSShares); + expect(await strategy.totalSupply0()).to.equal( + expectedGSShares.add(minShares) + ); expect(await strategy.balanceOf(owner.address)).to.equal( - expectedGSShares.sub(minShares) + expectedGSShares ); await (await cfmm.trade(tradeYield)).wait(); @@ -759,11 +835,10 @@ describe("ShortStrategyERC4626", function () { await cfmm.approve(strategy.address, ethers.constants.MaxUint256) ).wait(); - const minShares = 999; - + const shares = await cfmm.balanceOf(owner.address); await expect( - strategy._mint(minShares, owner.address) - ).to.be.revertedWithPanic(); + strategy._mint(shares, owner.address) + ).to.be.revertedWithCustomError(strategy, "STF_Fail"); }); it("= Min Shares Mint Shares", async function () { @@ -792,11 +867,11 @@ describe("ShortStrategyERC4626", function () { await cfmm.approve(strategy.address, ethers.constants.MaxUint256) ).wait(); - const minShares = 1000; + const shares = BigNumber.from(0); await expect( - strategy._mint(minShares, owner.address) - ).to.be.revertedWithCustomError(strategy, "ZeroAmount"); + strategy._mint(shares, owner.address) + ).to.be.revertedWithCustomError(strategy, "ZeroAssets"); }); it("First Mint Shares", async function () { @@ -819,7 +894,7 @@ describe("ShortStrategyERC4626", function () { expect(await cfmm.invariant()).to.equal(lpTokens.add(tradeYield)); const shares = lpTokens.div(2); - const expectedAssets = await strategy._convertToAssets(shares); + const expectedAssets = await strategy._convertToAssets2(shares, true); const params = await strategy.getTotalAssetsParams(); expect(params.lpBalance).to.equal(0); @@ -875,7 +950,7 @@ describe("ShortStrategyERC4626", function () { expect(depositEvent.args.assets).to.equal( expectedAssets.sub(minShares) ); - expect(depositEvent.args.shares).to.equal(shares.sub(minShares)); + expect(depositEvent.args.shares).to.equal(shares); const poolUpdatedEvent = events[events.length - 1]; expect(poolUpdatedEvent.event).to.equal("PoolUpdated"); @@ -897,13 +972,11 @@ describe("ShortStrategyERC4626", function () { expect(poolUpdatedEvent.args.cfmmReserves[1]).to.equal(cfmmReserves[1]); expect(poolUpdatedEvent.args.txType).to.equal(0); - expect(await strategy.totalSupply0()).to.equal(shares); - expect(await strategy.balanceOf(owner.address)).to.equal( - shares.sub(minShares) - ); + expect(await strategy.totalSupply0()).to.equal(shares.add(minShares)); + expect(await strategy.balanceOf(owner.address)).to.equal(shares); const params1 = await strategy.getTotalAssetsParams(); expect(params1.lpBalance).to.equal(expectedAssets); - expect(expectedAssets).to.equal(shares); + expect(expectedAssets).to.equal(shares.add(minShares)); }); it("More Mint Shares", async function () { @@ -920,7 +993,7 @@ describe("ShortStrategyERC4626", function () { expect(await cfmm.invariant()).to.equal(lpTokens.add(tradeYield)); const shares = lpTokens.div(2); - const expectedAssets = await strategy._convertToAssets(shares); + const expectedAssets = await strategy._convertToAssets2(shares, true); const params = await strategy.getTotalAssetsParams(); expect(params.lpBalance).to.equal(0); @@ -941,12 +1014,10 @@ describe("ShortStrategyERC4626", function () { expect(depositEvent.args.assets).to.equal( expectedAssets.sub(minShares) ); - expect(depositEvent.args.shares).to.equal(shares.sub(minShares)); + expect(depositEvent.args.shares).to.equal(shares); - expect(await strategy.totalSupply0()).to.equal(shares); - expect(await strategy.balanceOf(owner.address)).to.equal( - shares.sub(minShares) - ); + expect(await strategy.totalSupply0()).to.equal(shares.add(minShares)); + expect(await strategy.balanceOf(owner.address)).to.equal(shares); await (await cfmm.trade(tradeYield)).wait(); @@ -1042,9 +1113,14 @@ describe("ShortStrategyERC4626", function () { cfmmTotalSupply2, lastFees.lastFeeIndex ); - const expectedAssets3 = shares3 - .mul(currTotalAssets2) - .div(await strategy.totalSupply0()); + + const totalSupply = await strategy.totalSupply0(); + const expectedAssets3 = await convertToAssets( + shares3, + totalSupply, + currTotalAssets2, + true + ); const resp1 = await ( await strategy._mint(shares3, owner.address) @@ -1169,7 +1245,14 @@ describe("ShortStrategyERC4626", function () { await prepareAssetsToWithdraw(assets, owner); const withdrawAssets = ONE.mul(50); - const shares = ONE.mul(50); + const totalSupply = await strategy.totalSupply0(); + const strategyCFMMBalance = await cfmm.balanceOf(strategy.address); + const shares = await convertToShares( + withdrawAssets, + totalSupply, + strategyCFMMBalance, + true + ); await testERC4626Withdraw( owner.address, @@ -1217,10 +1300,17 @@ describe("ShortStrategyERC4626", function () { const assets = ONE.mul(200); await prepareAssetsToWithdraw(assets, owner); - const withdrawAssets = ONE.mul(50); const shares = ONE.mul(50); + const totalSupply = await strategy.totalSupply0(); + const strategyCFMMBalance = await cfmm.balanceOf(strategy.address); + const withdrawAssets = await convertToAssets( + shares, + totalSupply, + strategyCFMMBalance, + false + ); - await testERC4626Withdraw( + await testERC4626Redeem( owner.address, addr1.address, withdrawAssets, @@ -1233,7 +1323,7 @@ describe("ShortStrategyERC4626", function () { erc4626Redeem ); - await testERC4626Withdraw( + await testERC4626Redeem( owner.address, owner.address, withdrawAssets, @@ -1413,14 +1503,18 @@ describe("ShortStrategyERC4626", function () { await testConvertToShares( assets0, strategy._convertToShares, - strategy._convertToAssets + strategy._convertToAssets, + true, + false ) ).to.be.equal(assets0); expect( await testConvertToAssets( shares0, strategy._convertToAssets, - strategy._convertToShares + strategy._convertToShares, + false, + true ) ).to.be.equal(shares0); @@ -1434,14 +1528,18 @@ describe("ShortStrategyERC4626", function () { await testConvertToShares( assets1, strategy._convertToShares, - strategy._convertToAssets + strategy._convertToAssets, + true, + false ) - ).to.be.equal(assets1); + ).to.be.equal(assets1.sub(1000)); expect( await testConvertToAssets( shares1, strategy._convertToAssets, - strategy._convertToShares + strategy._convertToShares, + false, + true ) ).to.be.equal(shares1); }); @@ -1459,14 +1557,18 @@ describe("ShortStrategyERC4626", function () { await testConvertToShares( assets0, strategy._convertToShares, - strategy._convertToAssets + strategy._convertToAssets, + true, + false ) ).to.be.equal(assets0); expect( await testConvertToAssets( shares0, strategy._convertToAssets, - strategy._convertToShares + strategy._convertToShares, + false, + true ) ).to.be.equal(0); @@ -1480,14 +1582,18 @@ describe("ShortStrategyERC4626", function () { await testConvertToShares( assets1, strategy._convertToShares, - strategy._convertToAssets + strategy._convertToAssets, + true, + false ) ).to.not.equal(assets1); expect( await testConvertToAssets( shares1, strategy._convertToAssets, - strategy._convertToShares + strategy._convertToShares, + false, + true ) ).to.not.equal(shares1); @@ -1501,14 +1607,18 @@ describe("ShortStrategyERC4626", function () { await testConvertToShares( assets2, strategy._convertToShares, - strategy._convertToAssets + strategy._convertToAssets, + true, + false ) ).to.not.equal(assets2); expect( await testConvertToAssets( shares2, strategy._convertToAssets, - strategy._convertToShares + strategy._convertToShares, + false, + true ) ).to.not.equal(shares2); });