Skip to content

Commit

Permalink
Add RedeemOptimizerFIFO partial shares case
Browse files Browse the repository at this point in the history
  • Loading branch information
lucasia committed Oct 7, 2024
1 parent f8f5be9 commit 6418100
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 10 deletions.
9 changes: 4 additions & 5 deletions packages/contracts/src/token/ERC1155/RedeemOptimizerFIFO.sol
Original file line number Diff line number Diff line change
Expand Up @@ -121,14 +121,13 @@ contract RedeemOptimizerFIFO is IRedeemOptimizer {
if (amountFound + amountAtPeriod > optimizerParams.amountToFind) {
uint256 amountToInclude = optimizerParams.amountToFind - amountFound; // we only need the amount that brings us to amountToFind

// only include equivalent amount of shares for the amountToInclude assets
// in the assets case, the amounts include principal AND returns. we want the shares on deposit, which is the principal only.
// use this ratio: partialShares / totalShares = partialAssets / totalAssets
// partialShares = (partialAssets * totalShares) / totalAssets
uint256 sharesToInclude = sharesAtPeriod.mulDiv(amountToInclude, amountAtPeriod);

// only include equivalent amount of shares for the amountToInclude assets
cacheSharesAtPeriods[arrayIndex] =
optimizerParams.optimizerBasis == OptimizerBasis.Shares ? amountToInclude : sharesToInclude;
cacheSharesAtPeriods[arrayIndex] = optimizerParams.optimizerBasis == OptimizerBasis.Shares
? amountToInclude // amount is shares, amountToInclude already correct
: amountToInclude.mulDiv(sharesAtPeriod, amountAtPeriod); // amount is assets, calc the correct shares

// optimization succeeded - return here to be explicit we exit the function at this point
return _trimToSize(arrayIndex + 1, cacheDepositPeriods, cacheSharesAtPeriods);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,36 @@ contract RedeemOptimizerTest is MultiTokenVaultTest {
assertEq(depositShares, sharesAtPeriods, "optimizeRedeem - shares not correct");
}

function test__RedeemOptimizerTest__PartialRedeem() public {
uint256 residualShareAmount = 1 * _scale; // leave 1 share after redeem
uint256 redeemPeriod = _testParams3.redeemPeriod;

// ---------------------- setup ----------------------
IMultiTokenVault multiTokenVault = _createMultiTokenVault(_asset, 2, 10);
IRedeemOptimizer redeemOptimizer = new RedeemOptimizerFIFO(
IRedeemOptimizer.OptimizerBasis.AssetsWithReturns, multiTokenVault.currentPeriodsElapsed()
);
uint256[] memory depositShares = _testDepositOnly(_alice, multiTokenVault, testParamsArr.all());

uint256 sharesToWithdraw = depositShares[0] + depositShares[1] + depositShares[2] - residualShareAmount;

// ---------------------- redeem ----------------------
_warpToPeriod(multiTokenVault, redeemPeriod); // warp vault ahead to redeemPeriod

(uint256[] memory redeemDepositPeriods, uint256[] memory redeemSharesAtPeriods) =
redeemOptimizer.optimizeRedeemShares(multiTokenVault, _alice, sharesToWithdraw, redeemPeriod);
// verify using shares
assertEq(depositShares[0], redeemSharesAtPeriods[0], "optimizeRedeem partial - wrong shares period 0");
assertEq(depositShares[1], redeemSharesAtPeriods[1], "optimizeRedeem partial - wrong shares period 1");
assertEq(
depositShares[2] - residualShareAmount,
redeemSharesAtPeriods[2],
"optimizeRedeem partial - wrong shares period 2"
); // reduced by 1 share

assertEq(testParamsArr.depositPeriods(), redeemDepositPeriods, "optimizeRedeem - depositPeriods not correct");
}

function test__RedeemOptimizerTest__PartialWithdraw() public {
uint256 residualShareAmount = 1 * _scale; // leave 1 share after redeem
uint256 redeemPeriod = _testParams3.redeemPeriod;
Expand Down Expand Up @@ -101,10 +131,12 @@ contract RedeemOptimizerTest is MultiTokenVaultTest {
redeemOptimizer.optimizeWithdrawAssets(multiTokenVault, _alice, assetsToWithdraw, redeemPeriod);

// verify using shares
assertEq(depositShares[0], actualSharesAtPeriods[0], "optimizeWithdraw - wrong shares period 0");
assertEq(depositShares[1], actualSharesAtPeriods[1], "optimizeWithdraw - wrong shares period 1");
assertEq(depositShares[0], actualSharesAtPeriods[0], "optimizeWithdraw partial - wrong shares period 0");
assertEq(depositShares[1], actualSharesAtPeriods[1], "optimizeWithdraw partial - wrong shares period 1");
assertEq(
depositShares[2] - residualShareAmount, actualSharesAtPeriods[2], "optimizeWithdraw - wrong shares period 2"
depositShares[2] - residualShareAmount,
actualSharesAtPeriods[2],
"optimizeWithdraw partial - wrong shares period 2"
); // reduced by 1 share with returns

// // verify using assets
Expand All @@ -114,12 +146,12 @@ contract RedeemOptimizerTest is MultiTokenVaultTest {
assertEq(
testParamsArr.depositPeriods().length,
actualAssetsAtPeriods.length,
"convertToAssetsForDepositPeriods (partial) - length incorrect"
"convertToAssetsForDepositPeriods partial - length incorrect"
);
assertEq(
assetsToWithdraw,
actualAssetsAtPeriods[0] + actualAssetsAtPeriods[1] + actualAssetsAtPeriods[2],
"convertToAssetsForDepositPeriods (partial) - total incorrect"
"convertToAssetsForDepositPeriods partial - total incorrect"
);
}

Expand Down

0 comments on commit 6418100

Please sign in to comment.