Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BaseVaultTest refactoring #1196

Merged
merged 6 commits into from
Jan 3, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 31 additions & 60 deletions pkg/pool-hooks/test/foundry/NftLiquidityPositionExample.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -44,71 +44,38 @@ contract NftLiquidityPositionExampleTest is BaseVaultTest {

// Overrides `setUp` to include a deployment for NftLiquidityPositionExample.
function setUp() public virtual override {
BaseTest.setUp();

vault = deployVaultMock();
vm.label(address(vault), "vault");
vaultExtension = IVaultExtension(vault.getVaultExtension());
vm.label(address(vaultExtension), "vaultExtension");
vaultAdmin = IVaultAdmin(vault.getVaultAdmin());
vm.label(address(vaultAdmin), "vaultAdmin");
authorizer = BasicAuthorizerMock(address(vault.getAuthorizer()));
vm.label(address(authorizer), "authorizer");
poolFactory = address(PoolFactoryMock(address(vault.getPoolFactoryMock())));
vm.label(address(poolFactory), "factory");
router = deployRouterMock(IVault(address(vault)), weth, permit2);
vm.label(address(router), "router");
batchRouter = deployBatchRouterMock(IVault(address(vault)), weth, permit2);
vm.label(address(batchRouter), "batch router");
feeController = vault.getProtocolFeeController();
vm.label(address(feeController), "fee controller");
BaseVaultTest.setUp();

approveNFTRouterForSender();
approveNFTRouterForPool(IERC20(pool));

(daiIdx, usdcIdx) = getSortedIndexes(address(dai), address(usdc));
}

function onAfterDeployMainContracts() internal override {
nftRouter = new NftLiquidityPositionExample(IVault(address(vault)), weth, permit2, "NFT LiquidityPosition v1");
vm.label(address(nftRouter), "nftRouter");
}

// Here the Router is also the hook.
poolHooksContract = address(nftRouter);
(pool, ) = createPool();

// Approve vault allowances.
function approveNFTRouterForSender() internal virtual {
for (uint256 i = 0; i < users.length; ++i) {
address user = users[i];
vm.startPrank(user);
approveForSender();
vm.startPrank(users[i]);
for (uint256 j = 0; j < tokens.length; ++j) {
permit2.approve(address(tokens[j]), address(nftRouter), type(uint160).max, type(uint48).max);
}
vm.stopPrank();
}
if (pool != address(0)) {
approveForPool(IERC20(pool));
}
// Add initial liquidity.
initPool();

(daiIdx, usdcIdx) = getSortedIndexes(address(dai), address(usdc));
}

// Overrides approval to include NFTRouter.
function approveForSender() internal override {
for (uint256 i = 0; i < tokens.length; ++i) {
tokens[i].approve(address(permit2), type(uint256).max);
permit2.approve(address(tokens[i]), address(router), type(uint160).max, type(uint48).max);
permit2.approve(address(tokens[i]), address(batchRouter), type(uint160).max, type(uint48).max);
permit2.approve(address(tokens[i]), address(nftRouter), type(uint160).max, type(uint48).max);
}
function createHook() internal override returns (address) {
return address(nftRouter);
}

// Overrides approval to include NFTRouter.
function approveForPool(IERC20 bpt) internal override {
function approveNFTRouterForPool(IERC20 bpt) internal {
for (uint256 i = 0; i < users.length; ++i) {
vm.startPrank(users[i]);

bpt.approve(address(router), type(uint256).max);
bpt.approve(address(batchRouter), type(uint256).max);
bpt.approve(address(nftRouter), type(uint256).max);

IERC20(bpt).approve(address(permit2), type(uint256).max);
permit2.approve(address(bpt), address(router), type(uint160).max, type(uint48).max);
permit2.approve(address(bpt), address(batchRouter), type(uint160).max, type(uint48).max);
permit2.approve(address(bpt), address(nftRouter), type(uint160).max, type(uint48).max);

vm.stopPrank();
}
}
Expand Down Expand Up @@ -149,7 +116,7 @@ contract NftLiquidityPositionExampleTest is BaseVaultTest {
uint256[] memory amountsIn = nftRouter.addLiquidityProportional(
pool,
maxAmountsIn,
bptAmount,
DEFAULT_BPT_AMOUNT,
false,
bytes("")
);
Expand All @@ -170,12 +137,16 @@ contract NftLiquidityPositionExampleTest is BaseVaultTest {
);
// Router should set correct lp data
uint256 expectedTokenId = 0;
assertEq(nftRouter.bptAmount(expectedTokenId), bptAmount, "bptAmount mapping is wrong");
assertEq(nftRouter.bptAmount(expectedTokenId), DEFAULT_BPT_AMOUNT, "bptAmount mapping is wrong");
assertEq(nftRouter.startTime(expectedTokenId), block.timestamp, "startTime mapping is wrong");
assertEq(nftRouter.nftPool(expectedTokenId), pool, "pool mapping is wrong");

// Router should receive BPT instead of bob, he gets the NFT
assertEq(BalancerPoolToken(pool).balanceOf(address(nftRouter)), bptAmount, "NftRouter should hold BPT");
assertEq(
BalancerPoolToken(pool).balanceOf(address(nftRouter)),
DEFAULT_BPT_AMOUNT,
"NftRouter should hold BPT"
);
assertEq(nftRouter.ownerOf(expectedTokenId), bob, "bob should have an NFT");
assertEq(balancesAfter.bobBpt, 0, "bob should not hold any BPT");
}
Expand All @@ -184,7 +155,7 @@ contract NftLiquidityPositionExampleTest is BaseVaultTest {
// Add liquidity so bob has BPT to remove liquidity
uint256[] memory maxAmountsIn = [dai.balanceOf(bob), usdc.balanceOf(bob)].toMemoryArray();
vm.prank(bob);
nftRouter.addLiquidityProportional(pool, maxAmountsIn, bptAmount, false, bytes(""));
nftRouter.addLiquidityProportional(pool, maxAmountsIn, DEFAULT_BPT_AMOUNT, false, bytes(""));
vm.stopPrank();

// Skip to fee has decayed to 5%
Expand All @@ -202,7 +173,7 @@ contract NftLiquidityPositionExampleTest is BaseVaultTest {

// 5% exit fee.
uint64 exitFeePercentage = 5e16;
uint256 amountOut = bptAmount / 2;
uint256 amountOut = DEFAULT_BPT_AMOUNT / 2;
uint256 hookFee = amountOut.mulDown(exitFeePercentage);
// Bob gets original liquidity with fee deducted.
assertEq(
Expand Down Expand Up @@ -258,7 +229,7 @@ contract NftLiquidityPositionExampleTest is BaseVaultTest {
// Add liquidity so bob has BPT to remove liquidity.
uint256[] memory maxAmountsIn = [dai.balanceOf(bob), usdc.balanceOf(bob)].toMemoryArray();
vm.prank(bob);
nftRouter.addLiquidityProportional(pool, maxAmountsIn, bptAmount, false, bytes(""));
nftRouter.addLiquidityProportional(pool, maxAmountsIn, DEFAULT_BPT_AMOUNT, false, bytes(""));
vm.stopPrank();

// Skip to fee has decayed to 0.
Expand All @@ -274,7 +245,7 @@ contract NftLiquidityPositionExampleTest is BaseVaultTest {

BaseVaultTest.Balances memory balancesAfter = getBalances(bob);

uint256 amountOut = bptAmount / 2;
uint256 amountOut = DEFAULT_BPT_AMOUNT / 2;
// Bob gets original liquidity with no fee applied because of full decay.
assertEq(
balancesAfter.bobTokens[daiIdx] - balancesBefore.bobTokens[daiIdx],
Expand Down Expand Up @@ -329,7 +300,7 @@ contract NftLiquidityPositionExampleTest is BaseVaultTest {
// Add liquidity so bob has BPT to remove liquidity.
uint256[] memory maxAmountsIn = [dai.balanceOf(bob), usdc.balanceOf(bob)].toMemoryArray();
vm.prank(bob);
nftRouter.addLiquidityProportional(pool, maxAmountsIn, bptAmount, false, bytes(""));
nftRouter.addLiquidityProportional(pool, maxAmountsIn, DEFAULT_BPT_AMOUNT, false, bytes(""));
vm.stopPrank();

uint256 nftTokenId = 0;
Expand All @@ -348,7 +319,7 @@ contract NftLiquidityPositionExampleTest is BaseVaultTest {
uint256[] memory maxAmountsIn = [dai.balanceOf(bob), usdc.balanceOf(bob)].toMemoryArray();
vm.expectRevert(abi.encodeWithSelector(NftLiquidityPositionExample.CannotUseExternalRouter.selector, router));
vm.prank(bob);
router.addLiquidityProportional(pool, maxAmountsIn, bptAmount, false, bytes(""));
router.addLiquidityProportional(pool, maxAmountsIn, DEFAULT_BPT_AMOUNT, false, bytes(""));
}

function testRemoveFromExternalRouter() public {
Expand Down
6 changes: 4 additions & 2 deletions pkg/pool-hooks/test/foundry/StableSurgeHook.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ contract StableSurgeHookTest is BaseVaultTest {
vault.buildTokenConfig(tokens.asIERC20()),
DEFAULT_AMP_FACTOR,
roleAccounts,
swapFeePercentage,
DEFAULT_SWAP_FEE_PERCENTAGE,
poolHooksContract,
false,
false,
Expand Down Expand Up @@ -105,7 +105,7 @@ contract StableSurgeHookTest is BaseVaultTest {
SwapKind kind = SwapKind(bound(kindRaw, 0, 1));

vault.manuallySetSwapFee(pool, bound(swapFeePercentageRaw, 0, 1e16));
swapFeePercentage = vault.getStaticSwapFeePercentage(pool);
uint256 swapFeePercentage = vault.getStaticSwapFeePercentage(pool);

BaseVaultTest.Balances memory balancesBefore = getBalances(alice);

Expand All @@ -129,6 +129,7 @@ contract StableSurgeHookTest is BaseVaultTest {
uint256 actualSwapFeePercentage = _calculateFee(
amountGivenScaled18,
kind,
swapFeePercentage,
[poolInitAmount, poolInitAmount].toMemoryArray()
);

Expand Down Expand Up @@ -182,6 +183,7 @@ contract StableSurgeHookTest is BaseVaultTest {
function _calculateFee(
uint256 amountGivenScaled18,
SwapKind kind,
uint256 swapFeePercentage,
uint256[] memory balances
) internal view returns (uint256) {
uint256 amountCalculatedScaled18 = StablePool(pool).onSwap(
Expand Down
2 changes: 1 addition & 1 deletion pkg/pool-stable/test/foundry/FungibilityStable.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ contract FungibilityStableTest is StablePoolContractsDeployer, FungibilityTest {
vault.buildTokenConfig(tokens.asIERC20()),
DEFAULT_AMP_FACTOR,
roleAccounts,
swapFeePercentage, // 1% swap fee, but test will force it to be 0
DEFAULT_SWAP_FEE_PERCENTAGE, // 1% swap fee, but test will force it to be 0
poolHooksContract,
false, // Do not enable donations
false, // Do not disable unbalanced add/remove liquidity
Expand Down
2 changes: 1 addition & 1 deletion pkg/pool-stable/test/foundry/StablePool.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ contract StablePoolTest is BasePoolTest, StablePoolContractsDeployer {
assertEq(data.staticSwapFeePercentage, BASE_MIN_SWAP_FEE, "Swap fee mismatch");

for (uint256 i = 0; i < tokens.length; ++i) {
assertEq(data.balancesLiveScaled18[i], defaultAmount, "Live balance mismatch");
assertEq(data.balancesLiveScaled18[i], DEFAULT_AMOUNT, "Live balance mismatch");
assertEq(data.tokenRates[i], tokenRates[i], "Token rate mismatch");
}
}
Expand Down
8 changes: 4 additions & 4 deletions pkg/pool-weighted/test/foundry/BigWeightedPool.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -99,22 +99,22 @@ contract BigWeightedPoolTest is WeightedPoolContractsDeployer, BasePoolTest {
tokenAmounts.push(TOKEN_AMOUNT);
}

_approveForPool(IERC20(address(newPool)));
_approvePoolTokensForPool(IERC20(address(newPool)));
}

function _approveForSender() internal {
function _approvePoolTokensForSender() internal {
for (uint256 i = 0; i < poolTokens.length; ++i) {
poolTokens[i].approve(address(permit2), type(uint256).max);
permit2.approve(address(poolTokens[i]), address(router), type(uint160).max, type(uint48).max);
permit2.approve(address(poolTokens[i]), address(batchRouter), type(uint160).max, type(uint48).max);
}
}

function _approveForPool(IERC20 bpt) internal {
function _approvePoolTokensForPool(IERC20 bpt) internal {
for (uint256 i = 0; i < users.length; ++i) {
vm.startPrank(users[i]);

_approveForSender();
_approvePoolTokensForSender();

bpt.approve(address(router), type(uint256).max);
bpt.approve(address(batchRouter), type(uint256).max);
Expand Down
2 changes: 1 addition & 1 deletion pkg/pool-weighted/test/foundry/E2eSwap.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@ contract E2eSwapWeightedTest is E2eSwapTest, WeightedPoolContractsDeployer {
bytes("")
);

// An ExactIn swap with `defaultAmount` tokenIn returned `amountOut` tokenOut.
// An ExactIn swap with `DEFAULT_AMOUNT` tokenIn returned `amountOut` tokenOut.
// Since Exact_In and Exact_Out are symmetrical, an ExactOut swap with `amountOut` tokenOut should return the
// same amount of tokenIn.
assertApproxEqRel(amountIn, tokenAAmountIn, 0.00001e16, "Swap fees are not symmetric for ExactIn and ExactOut");
Expand Down
2 changes: 1 addition & 1 deletion pkg/pool-weighted/test/foundry/FungibilityWeighted.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ contract FungibilityWeightedTest is WeightedPoolContractsDeployer, FungibilityTe
vault.buildTokenConfig(tokens.asIERC20()),
[uint256(80e16), uint256(20e16)].toMemoryArray(),
roleAccounts,
swapFeePercentage, // 1% swap fee, but test will force it to be 0
DEFAULT_SWAP_FEE_PERCENTAGE, // 1% swap fee, but test will force it to be 0
poolHooksContract,
false, // Do not enable donations
false, // Do not disable unbalanced add/remove liquidity
Expand Down
2 changes: 1 addition & 1 deletion pkg/pool-weighted/test/foundry/WeightedPool.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ contract WeightedPoolTest is WeightedPoolContractsDeployer, BasePoolTest {
assertEq(data.staticSwapFeePercentage, DEFAULT_SWAP_FEE, "Swap fee mismatch");

for (uint256 i = 0; i < tokens.length; ++i) {
assertEq(data.balancesLiveScaled18[i], defaultAmount, "Live balance mismatch");
assertEq(data.balancesLiveScaled18[i], DEFAULT_AMOUNT, "Live balance mismatch");
assertEq(data.tokenRates[i], tokenRates[i], "Token rate mismatch");
}
}
Expand Down
3 changes: 3 additions & 0 deletions pkg/solidity-utils/test/foundry/utils/BaseTest.sol
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ abstract contract BaseTest is Test, GasSnapshot {
// Raw token balances are stored in half a slot, so the max is uint128.
uint256 internal constant MAX_UINT128 = type(uint128).max;

bytes32 internal constant ZERO_BYTES32 = 0x0000000000000000000000000000000000000000000000000000000000000000;
bytes32 internal constant ONE_BYTES32 = 0x0000000000000000000000000000000000000000000000000000000000000001;

// Default admin.
address payable internal admin;
uint256 internal adminKey;
Expand Down
Loading
Loading