Skip to content

Commit

Permalink
Add MultiTokenVault validation testing
Browse files Browse the repository at this point in the history
  • Loading branch information
lucasia committed Oct 5, 2024
1 parent eb49981 commit 3092975
Show file tree
Hide file tree
Showing 4 changed files with 121 additions and 22 deletions.
109 changes: 99 additions & 10 deletions packages/contracts/test/src/token/ERC1155/MultiTokenVaultTest.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ contract MultiTokenVaultTest is IMultiTokenVaultTestBase {

address private _owner = makeAddr("owner");
address private _alice = makeAddr("alice");
address private _bob = makeAddr("bob");
address private _charlie = makeAddr("charlie");

TestParam internal _testParams1;
TestParam internal _testParams2;
Expand All @@ -38,7 +40,7 @@ contract MultiTokenVaultTest is IMultiTokenVaultTestBase {
function test__MultiTokenVaulTest__SimpleDeposit() public {
uint256 assetToSharesRatio = 1;

MultiTokenVault vault = _createMultiTokenVault(_asset, assetToSharesRatio, 10);
IMultiTokenVault vault = _createMultiTokenVault(_asset, assetToSharesRatio, 10);

address vaultAddress = address(vault);

Expand All @@ -61,22 +63,79 @@ contract MultiTokenVaultTest is IMultiTokenVaultTestBase {
testVaultAtOffsets(_alice, vault, _testParams1);
}

function test__MultiTokenVaulTest__SingleDeposit() public {
function test__MultiTokenVaulTest__DepositAndRedeem() public {
uint256 assetToSharesRatio = 1;
address charlie = makeAddr("charlie");

_transferAndAssert(_asset, _owner, charlie, 100_000 * _scale);
_transferAndAssert(_asset, _owner, _charlie, 100_000 * _scale);

MultiTokenVault vault = _createMultiTokenVault(_asset, assetToSharesRatio, 10);

testVaultAtPeriod(charlie, vault, _testParams1);
testVaultAtPeriod(_charlie, vault, _testParams1);
}

function test__MultiTokenVaulTest__RedeemBeforeDepositPeriodReverts() public {
MultiTokenVault vault = _createMultiTokenVault(_asset, 1, 10);

TestParam memory testParam = TestParam({ principal: 1001 * _scale, depositPeriod: 2, redeemPeriod: 1 });

// deposit period > redeem period should fail
vm.expectRevert(
abi.encodeWithSelector(
MultiTokenVault.MultiTokenVault__RedeemBeforeDeposit.selector,
_alice,
testParam.depositPeriod,
testParam.redeemPeriod
)
);
vault.redeemForDepositPeriod(1, _alice, _alice, testParam.depositPeriod, testParam.redeemPeriod);
}

function test__MultiTokenVaulTest__CurrentBeforeRedeemPeriodReverts() public {
MultiTokenVault vault = _createMultiTokenVault(_asset, 1, 10);

TestParam memory testParam = TestParam({ principal: 1001 * _scale, depositPeriod: 1, redeemPeriod: 3 });

uint256 currentPeriod = testParam.redeemPeriod - 1;

_warpToPeriod(vault, currentPeriod);

vm.expectRevert(
abi.encodeWithSelector(
MultiTokenVault.MultiTokenVault__RedeemTimePeriodNotSupported.selector,
_alice,
currentPeriod,
testParam.redeemPeriod
)
);
vault.redeemForDepositPeriod(1, _alice, _alice, testParam.depositPeriod, testParam.redeemPeriod);
}

function test__MultiTokenVaulTest__MultipleDeposits() public {
function test__MultiTokenVaulTest__RedeemOverMaxSharesReverts() public {
MultiTokenVault vault = _createMultiTokenVault(_asset, 1, 10);

TestParam memory testParam = TestParam({ principal: 1001 * _scale, depositPeriod: 1, redeemPeriod: 3 });

uint256 sharesToRedeem = 1;

_warpToPeriod(vault, testParam.redeemPeriod);

vm.expectRevert(
abi.encodeWithSelector(
MultiTokenVault.MultiTokenVault__ExceededMaxRedeem.selector,
_alice,
testParam.depositPeriod,
sharesToRedeem,
0
)
);
vault.redeemForDepositPeriod(sharesToRedeem, _alice, _alice, testParam.depositPeriod, testParam.redeemPeriod);
}

function test__MultiTokenVaulTest__MultipleDepositsAndRedeem() public {
uint256 assetToSharesRatio = 2;

// setup
MultiTokenVaultDailyPeriods vault = _createMultiTokenVault(_asset, assetToSharesRatio, 10);
IMultiTokenVault vault = _createMultiTokenVault(_asset, assetToSharesRatio, 10);

// verify deposit - period 1
uint256 deposit1Shares = _testDepositOnly(_alice, vault, _testParams1);
Expand Down Expand Up @@ -129,8 +188,6 @@ contract MultiTokenVaultTest is IMultiTokenVaultTestBase {
uint256 assetToSharesRatio = 2;
uint256 redeemPeriod = 2001;

MultiTokenVaultDailyPeriods vault = _createMultiTokenVault(_asset, assetToSharesRatio, 10);

IMTVTestParamArray testParamsArray = new IMTVTestParamArray();
testParamsArray.addTestParam(
TestParam({ principal: 1001 * _scale, depositPeriod: 1, redeemPeriod: redeemPeriod })
Expand All @@ -142,10 +199,12 @@ contract MultiTokenVaultTest is IMultiTokenVaultTestBase {
TestParam({ principal: 3003 * _scale, depositPeriod: 303, redeemPeriod: redeemPeriod })
);

IMultiTokenVault vault = _createMultiTokenVault(_asset, assetToSharesRatio, 10);

uint256[] memory shares = _testDepositOnly(_alice, vault, testParamsArray.getAll());
uint256[] memory depositPeriods = testParamsArray.getAllDepositPeriods();

// check the sharesAtDepositPeriods match
// ------------------------ batch convert to assets ------------------------
uint256[] memory assets = vault.convertToAssetsForDepositPeriods(shares, depositPeriods, redeemPeriod);

assertEq(3, assets.length, "assets are wrong length");
Expand All @@ -164,6 +223,36 @@ contract MultiTokenVaultTest is IMultiTokenVaultTestBase {
vault.convertToAssetsForDepositPeriod(shares[2], depositPeriods[2], redeemPeriod),
"asset mismatch period 2"
);

// ------------------------ batch approvalForAll safeBatchTransferFrom balance ------------------------
uint256[] memory aliceBalances = _testBalanceOfBatch(_alice, vault, testParamsArray, assetToSharesRatio);

// have alice approve bob for all
vm.prank(_alice);
vault.setApprovalForAll(_bob, true);

// now bob can transfer on behalf of alice to charlie
vm.prank(_bob);
vault.safeBatchTransferFrom(_alice, _charlie, depositPeriods, aliceBalances, "");

_testBalanceOfBatch(_charlie, vault, testParamsArray, assetToSharesRatio); // verify bob
}

function _testBalanceOfBatch(
address account,
IMultiTokenVault vault,
IMTVTestParamArray testParamsArray,
uint256 assetToSharesRatio
) internal view returns (uint256[] memory balances_) {
address[] memory accounts = testParamsArray.accountArray(account, testParamsArray.length());
uint256[] memory balances = vault.balanceOfBatch(accounts, testParamsArray.getAllDepositPeriods());
assertEq(3, balances.length, "balances size incorrect");

assertEq(testParamsArray.get(0).principal / assetToSharesRatio, balances[0], "balance mismatch period 0");
assertEq(testParamsArray.get(1).principal / assetToSharesRatio, balances[1], "balance mismatch period 1");
assertEq(testParamsArray.get(2).principal / assetToSharesRatio, balances[2], "balance mismatch period 2");

return balances;
}

function _expectedReturns(uint256, /* shares */ IMultiTokenVault vault, TestParam memory testParam)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,4 +51,14 @@ contract IMTVTestParamArray {

return depositPeriods;
}

function accountArray(address account, uint256 size) public pure returns (address[] memory accounts_) {
address[] memory accounts = new address[](size);

for (uint256 i = 0; i < size; i++) {
accounts[i] = account;
}

return accounts;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ abstract contract IMultiTokenVaultTestBase is Test {
);
assertEq(
prevReceiverVaultBalance + actualSharesAtPeriod,
vault.sharesAtPeriod(account, testParam.depositPeriod),
vault.balanceOf(account, testParam.depositPeriod),
_assertMsg("receiver did not receive the correct vault shares - balanceOf ", vault, testParam.depositPeriod)
);

Expand All @@ -196,7 +196,7 @@ abstract contract IMultiTokenVaultTestBase is Test {
function _testRedeemOnly(
address account,
IMultiTokenVault vault,
TestParam memory testParams,
TestParam memory testParam,
uint256 sharesToRedeemAtPeriod
) internal virtual returns (uint256 actualAssetsAtPeriod_) {
IERC20 asset = IERC20(vault.asset());
Expand All @@ -205,31 +205,31 @@ abstract contract IMultiTokenVaultTestBase is Test {

// ------------------- prep redeem -------------------
uint256 assetBalanceBeforeRedeem = asset.balanceOf(account);
uint256 expectedReturns = _expectedReturns(sharesToRedeemAtPeriod, vault, testParams);
uint256 expectedReturns = _expectedReturns(sharesToRedeemAtPeriod, vault, testParam);

_transferFromTokenOwner(asset, address(vault), expectedReturns);

// ------------------- redeem -------------------
_warpToPeriod(vault, testParams.redeemPeriod); // warp the vault to redeem period
_warpToPeriod(vault, testParam.redeemPeriod); // warp the vault to redeem period

vm.startPrank(account);
uint256 actualAssetsAtPeriod =
vault.redeemForDepositPeriod(sharesToRedeemAtPeriod, account, account, testParams.depositPeriod);
vault.redeemForDepositPeriod(sharesToRedeemAtPeriod, account, account, testParam.depositPeriod);
vm.stopPrank();

assertApproxEqAbs(
testParams.principal + expectedReturns,
testParam.principal + expectedReturns,
actualAssetsAtPeriod,
TOLERANCE,
_assertMsg("assets does not equal principal + yield", vault, testParams.depositPeriod)
_assertMsg("assets does not equal principal + yield", vault, testParam.depositPeriod)
);

// verify the receiver has the USDC back
assertApproxEqAbs(
assetBalanceBeforeRedeem + testParams.principal + expectedReturns,
assetBalanceBeforeRedeem + testParam.principal + expectedReturns,
asset.balanceOf(account),
TOLERANCE,
_assertMsg("receiver did not receive the correct yield", vault, testParams.depositPeriod)
_assertMsg("receiver did not receive the correct yield", vault, testParam.depositPeriod)
);

_warpToPeriod(vault, prevVaultPeriodsElapsed); // restore the vault to previous state
Expand Down Expand Up @@ -286,8 +286,8 @@ abstract contract IMultiTokenVaultTestBase is Test {
vm.warp(Timer.timestamp() + timePeriod * 24 hours);
}

/// @dev - creates a IMultiTokenVaultTestParams for testing
function _createTestParams(uint256 principal, uint256 depositPeriod, uint256 redeemPeriod)
/// @dev - creates a TestParam for testing
function _createTestParam(uint256 principal, uint256 depositPeriod, uint256 redeemPeriod)
internal
pure
returns (TestParam memory testParam)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ abstract contract LiquidContinuousMultiTokenVaultTestBase is IMultiTokenVaultTes

assertEq(
actualSharesAtPeriod,
vault.sharesAtPeriod(receiver, testParam.depositPeriod),
vault.balanceOf(receiver, testParam.depositPeriod),
_assertMsg(
"!!! receiver did not receive the correct vault shares - balanceOf ", vault, testParam.depositPeriod
)
Expand Down

0 comments on commit 3092975

Please sign in to comment.