Skip to content

Commit 8b1a42b

Browse files
benesjanLHerskind
andauthored
Fixing Liquity tests so that they work at the latest block (#212)
* test: labeling used Uni pools + constraining visibility * test: fixed StabilityPool tests * test: replaces custom random function with fuzzying * update fuzzing Co-authored-by: LHerskind <[email protected]>
1 parent 3984611 commit 8b1a42b

9 files changed

+55
-128
lines changed

package.json

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,10 @@
1818
"test:pinned:14000000": "forge test --fork-block-number 14000000 --match-contract 'Element|OracleHelper' --fork-url https://mainnet.infura.io/v3/9928b52099854248b3a096be07a6b23c",
1919
"test:pinned:14970000": "forge test --fork-block-number 14970000 -m 'testRedistributionSuccessfulSwap|testRedistributionExitWhenICREqualsMCR' --fork-url https://mainnet.infura.io/v3/9928b52099854248b3a096be07a6b23c",
2020
"test:pinned:14972000": "forge test --fork-block-number 14972000 -m 'testRedistributionFailingSwap' --fork-url https://mainnet.infura.io/v3/9928b52099854248b3a096be07a6b23c",
21-
"test:pinned:15220000": "forge test --fork-block-number 15220000 --match-contract 'StabilityPoolBridge' --fork-url https://mainnet.infura.io/v3/9928b52099854248b3a096be07a6b23c",
22-
"test:pinned": "yarn test:pinned:14000000 && yarn test:pinned:14970000 && yarn test:pinned:14972000 && yarn test:pinned:15220000",
21+
"test:pinned": "yarn test:pinned:14000000 && yarn test:pinned:14970000 && yarn test:pinned:14972000",
2322
"test:contracts:block": "forge test --fork-block-number",
2423
"cast": "cast",
25-
"test:contracts": "forge test --no-match-contract 'Element|AceOfZk|StabilityPoolBridge' --no-match-test 'testRedistribution' && yarn test:pinned",
24+
"test:contracts": "forge test --no-match-contract 'Element|AceOfZk' --no-match-test 'testRedistribution' && yarn test:pinned",
2625
"build": "yarn clean && yarn compile:client-dest",
2726
"formatting": "yarn prettier --write .",
2827
"formatting:check": "prettier --check .",

src/test/bridges/liquity/StabilityPoolBridgeE2E.t.sol

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,9 @@ contract StabilityPoolBridgeE2ETest is BridgeTestBase {
4545

4646
// Fetch the id of the stability pool bridge
4747
id = ROLLUP_PROCESSOR.getSupportedBridgesLength();
48+
49+
// Reset ETH balance to 0 to make accounting easier
50+
deal(address(bridge), 0);
4851
}
4952

5053
// @dev In order to avoid overflows we set _depositAmount to be uint96 instead of uint256.

src/test/bridges/liquity/StabilityPoolBridgeInternal.t.sol

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,9 @@ import {TestUtil} from "./utils/TestUtil.sol";
88
import {StabilityPoolBridge} from "../../../bridges/liquity/StabilityPoolBridge.sol";
99

1010
contract StabilityPoolBridgeTestInternal is TestUtil, StabilityPoolBridge(address(0), address(0)) {
11-
address public constant LQTY_ETH_POOL = 0xD1D5A4c0eA98971894772Dcd6D2f1dc71083C44E; // 3000 bps fee tier
12-
address public constant USDC_ETH_POOL = 0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640; // 500 bps fee tier
13-
address public constant LUSD_USDC_POOL = 0x4e0924d3a751bE199C426d52fb1f2337fa96f736; // 500 bps fee tier
14-
1511
function setUp() public {
12+
_setUpTokensAndLabels();
1613
rollupProcessor = address(this);
17-
setUpTokens();
1814

1915
// solhint-disable-next-line
2016
require(IERC20(WETH).approve(address(UNI_ROUTER), type(uint256).max), "WETH_APPROVE_FAILED");

src/test/bridges/liquity/StabilityPoolBridgeUnit.t.sol

Lines changed: 28 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,12 @@ import {TestUtil} from "./utils/TestUtil.sol";
99
import {StabilityPoolBridge} from "../../../bridges/liquity/StabilityPoolBridge.sol";
1010

1111
contract StabilityPoolBridgeUnitTest is TestUtil {
12-
address public constant LQTY_ETH_POOL = 0xD1D5A4c0eA98971894772Dcd6D2f1dc71083C44E; // 3000 bps fee tier
13-
address public constant USDC_ETH_POOL = 0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640; // 500 bps fee tier
14-
address public constant LUSD_USDC_POOL = 0x4e0924d3a751bE199C426d52fb1f2337fa96f736; // 500 bps fee tier
15-
1612
AztecTypes.AztecAsset internal emptyAsset;
1713
StabilityPoolBridge private bridge;
1814

1915
function setUp() public {
16+
_setUpTokensAndLabels();
2017
rollupProcessor = address(this);
21-
setUpTokens();
2218

2319
bridge = new StabilityPoolBridge(rollupProcessor, address(0));
2420
bridge.setApprovals();
@@ -30,6 +26,9 @@ contract StabilityPoolBridgeUnitTest is TestUtil {
3026
deal(tokens["LUSD"].addr, address(bridge), 1);
3127
deal(tokens["LQTY"].addr, address(bridge), 1);
3228
deal(tokens["WETH"].addr, address(bridge), 1);
29+
30+
// Reset ETH balance to 0 to make accounting easier
31+
deal(address(bridge), 0);
3332
}
3433

3534
function testInitialERC20Params() public {
@@ -44,10 +43,14 @@ contract StabilityPoolBridgeUnitTest is TestUtil {
4443
bridge.convert(emptyAsset, emptyAsset, emptyAsset, emptyAsset, 0, 0, 0, address(0));
4544
}
4645

47-
function testFullDepositWithdrawalFlow() public {
48-
// I will deposit and withdraw 1 million LUSD
49-
uint256 inputValue = 1e24;
50-
_deposit(inputValue);
46+
function testFullDepositWithdrawalFlow(
47+
uint96 _depositAmount,
48+
uint96 _withdrawalAmount,
49+
uint64 _ethRewards,
50+
uint72 _lqtyRewards
51+
) public {
52+
uint256 depositAmount = bound(_depositAmount, 10, type(uint256).max);
53+
uint256 spbReceived = _deposit(depositAmount);
5154

5255
AztecTypes.AztecAsset memory inputAssetA = AztecTypes.AztecAsset(
5356
2,
@@ -61,104 +64,34 @@ contract StabilityPoolBridgeUnitTest is TestUtil {
6164
);
6265

6366
// Transfer StabilityPoolBridge accounting token (SPB) back to the bridge
64-
IERC20(inputAssetA.erc20Address).transfer(address(bridge), inputValue);
67+
IERC20(inputAssetA.erc20Address).transfer(address(bridge), spbReceived);
68+
69+
// Mint rewards to the bridge
70+
deal(address(bridge), _ethRewards);
71+
deal(tokens["LQTY"].addr, address(bridge), _lqtyRewards);
6572

6673
// Withdraw LUSD from StabilityPool through the bridge
74+
uint256 withdrawalAmount = bound(_withdrawalAmount, 10, spbReceived);
75+
6776
(uint256 outputValueA, , ) = bridge.convert(
6877
inputAssetA,
6978
emptyAsset,
7079
outputAssetA,
7180
emptyAsset,
72-
inputValue,
81+
withdrawalAmount,
7382
1,
7483
0,
7584
address(0)
7685
);
7786

78-
// Check the total supply of SPB token is 0
79-
assertEq(bridge.totalSupply(), 0);
87+
// Check the total supply of SPB token is spbReceived - withdrawalAmount
88+
assertEq(bridge.totalSupply(), spbReceived - withdrawalAmount);
8089

8190
// Transfer the funds back from the bridge to the rollup processor
82-
IERC20(outputAssetA.erc20Address).transferFrom(address(bridge), rollupProcessor, outputValueA);
83-
84-
// Check the LUSD balance of rollupProcessor is greater or equal to the initial LUSD deposit
85-
assertGe(outputValueA, inputValue);
86-
}
87-
88-
function testMultipleDepositsWithdrawals() public {
89-
uint256 i = 0;
90-
uint256 numIters = 2;
91-
uint256 depositAmount = 203;
92-
uint256[] memory spbBalances = new uint256[](numIters);
93-
94-
AztecTypes.AztecAsset memory inputAssetA = AztecTypes.AztecAsset(
95-
1,
96-
tokens["LUSD"].addr,
97-
AztecTypes.AztecAssetType.ERC20
98-
);
99-
AztecTypes.AztecAsset memory outputAssetA = AztecTypes.AztecAsset(
100-
2,
101-
address(bridge),
102-
AztecTypes.AztecAssetType.ERC20
91+
assertTrue(
92+
IERC20(outputAssetA.erc20Address).transferFrom(address(bridge), rollupProcessor, outputValueA),
93+
"Transfer failed"
10394
);
104-
105-
while (i < numIters) {
106-
depositAmount = rand(depositAmount);
107-
// 1. Mint deposit amount of LUSD directly to the bridge (to avoid transfer)
108-
deal(inputAssetA.erc20Address, address(bridge), depositAmount);
109-
// 2. Mint rewards to the bridge
110-
deal(tokens["LQTY"].addr, address(bridge), 1e20);
111-
deal(tokens["WETH"].addr, address(bridge), 1e18);
112-
113-
// 3. Deposit LUSD to StabilityPool through the bridge
114-
(uint256 outputValueA, , ) = bridge.convert(
115-
inputAssetA,
116-
emptyAsset,
117-
outputAssetA,
118-
emptyAsset,
119-
depositAmount,
120-
i,
121-
0,
122-
address(0)
123-
);
124-
125-
// 4. Transfer SPB back to RollupProcessor
126-
IERC20(outputAssetA.erc20Address).transferFrom(address(bridge), rollupProcessor, outputValueA);
127-
128-
spbBalances[i] = outputValueA;
129-
i++;
130-
}
131-
132-
// 5. Swap input/output assets to execute withdraw flow in the next convert call
133-
(inputAssetA, outputAssetA) = (outputAssetA, inputAssetA);
134-
135-
i = 0;
136-
while (i < numIters) {
137-
uint256 inputValue = spbBalances[i];
138-
139-
// 6. Transfer SPB back to the bridge
140-
IERC20(inputAssetA.erc20Address).transfer(address(bridge), inputValue);
141-
142-
// 7. Withdraw LUSD from StabilityPool through the bridge
143-
(uint256 outputValueA, , ) = bridge.convert(
144-
inputAssetA,
145-
emptyAsset,
146-
outputAssetA,
147-
emptyAsset,
148-
inputValue,
149-
numIters + i,
150-
0,
151-
address(0)
152-
);
153-
154-
// 8. Transfer LUSD back to RollupProcessor
155-
IERC20(outputAssetA.erc20Address).transferFrom(address(bridge), rollupProcessor, outputValueA);
156-
157-
i++;
158-
}
159-
160-
// 5. Check the total supply of SPB token is 0
161-
assertEq(bridge.totalSupply(), 0);
16295
}
16396

16497
function testUrgentModeOffSwap1() public {
@@ -239,7 +172,7 @@ contract StabilityPoolBridgeUnitTest is TestUtil {
239172
);
240173
}
241174

242-
function _deposit(uint256 _depositAmount) private {
175+
function _deposit(uint256 _depositAmount) private returns (uint256) {
243176
// 1. Mint the deposit amount of LUSD to the bridge
244177
deal(tokens["LUSD"].addr, address(bridge), _depositAmount);
245178

@@ -268,5 +201,7 @@ contract StabilityPoolBridgeUnitTest is TestUtil {
268201
// 6. Check the LUSD balance of the StabilityPoolBridge in the StabilityPool contract is greater than or equal
269202
// to the amount of LUSD deposited
270203
assertGe(bridge.STABILITY_POOL().getCompoundedLUSDDeposit(address(bridge)), _depositAmount);
204+
205+
return outputValueA;
271206
}
272207
}

src/test/bridges/liquity/StakingBridgeInternal.t.sol

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,9 @@ import {StakingBridge} from "../../../bridges/liquity/StakingBridge.sol";
88
import {TestUtil} from "./utils/TestUtil.sol";
99

1010
contract StakingBridgeTestInternal is TestUtil, StakingBridge(address(0)) {
11-
address public constant LUSD_USDC_POOL = 0x4e0924d3a751bE199C426d52fb1f2337fa96f736; // 500 bps fee tier
12-
address public constant USDC_ETH_POOL = 0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640; // 500 bps fee tier
13-
address public constant LQTY_ETH_POOL = 0xD1D5A4c0eA98971894772Dcd6D2f1dc71083C44E; // 3000 bps fee tier
14-
1511
function setUp() public {
12+
_setUpTokensAndLabels();
1613
rollupProcessor = address(this);
17-
setUpTokens();
1814

1915
// solhint-disable-next-line
2016
require(IERC20(WETH).approve(address(UNI_ROUTER), type(uint256).max), "WETH_APPROVE_FAILED");

src/test/bridges/liquity/StakingBridgeUnit.t.sol

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,12 @@ import {TestUtil} from "./utils/TestUtil.sol";
99
import {StakingBridge} from "../../../bridges/liquity/StakingBridge.sol";
1010

1111
contract StakingBridgeUnitTest is TestUtil {
12-
address public constant LUSD_USDC_POOL = 0x4e0924d3a751bE199C426d52fb1f2337fa96f736; // 500 bps fee tier
13-
address public constant USDC_ETH_POOL = 0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640; // 500 bps fee tier
14-
address public constant LQTY_ETH_POOL = 0xD1D5A4c0eA98971894772Dcd6D2f1dc71083C44E; // 3000 bps fee tier
15-
1612
AztecTypes.AztecAsset internal emptyAsset;
1713
StakingBridge private bridge;
1814

1915
function setUp() public {
16+
_setUpTokensAndLabels();
2017
rollupProcessor = address(this);
21-
setUpTokens();
2218

2319
bridge = new StakingBridge(rollupProcessor);
2420
bridge.setApprovals();
@@ -85,10 +81,9 @@ contract StakingBridgeUnitTest is TestUtil {
8581
assertGe(outputValueA, inputValue);
8682
}
8783

88-
function testMultipleDepositsWithdrawals() public {
84+
function testMultipleDepositsWithdrawals(uint256[2] memory _depositAmounts) public {
8985
uint256 i = 0;
9086
uint256 numIters = 2;
91-
uint256 depositAmount = 203;
9287
uint256[] memory sbBalances = new uint256[](numIters);
9388

9489
AztecTypes.AztecAsset memory inputAssetA = AztecTypes.AztecAsset(
@@ -103,7 +98,7 @@ contract StakingBridgeUnitTest is TestUtil {
10398
);
10499

105100
while (i < numIters) {
106-
depositAmount = rand(depositAmount);
101+
uint256 depositAmount = bound(_depositAmounts[i], 1e18, 1e25);
107102
// 1. Mint deposit amount of LQTY directly to the bridge (to avoid transfer)
108103
deal(inputAssetA.erc20Address, address(bridge), depositAmount);
109104
// 2. Mint rewards to the bridge

src/test/bridges/liquity/TroveBridgeTestBase.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ contract TroveBridgeTestBase is TestUtil {
5050
fallback() external payable {}
5151

5252
function _baseSetUp() internal {
53-
setUpTokens();
53+
_setUpTokensAndLabels();
5454

5555
vm.label(address(bridge.USDC()), "USDC");
5656
vm.label(address(BORROWER_OPERATIONS), "BORROWER_OPERATIONS");

src/test/bridges/liquity/TroveBridgeUnit.t.sol

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ contract TroveBridgeUnitTest is TroveBridgeTestBase {
7777
_borrow(ROLLUP_PROCESSOR_ETH_BALANCE);
7878

7979
// Drop price and liquidate the trove
80-
setLiquityPrice(LIQUITY_PRICE_FEED.fetchPrice() / 2);
80+
_setLiquityPrice(LIQUITY_PRICE_FEED.fetchPrice() / 2);
8181
TROVE_MANAGER.liquidate(address(bridge));
8282
Status troveStatus = Status(TROVE_MANAGER.getTroveStatus(address(bridge)));
8383
assertTrue(troveStatus == Status.closedByLiquidation, "Invalid trove status");
@@ -107,7 +107,7 @@ contract TroveBridgeUnitTest is TroveBridgeTestBase {
107107
_borrow(ROLLUP_PROCESSOR_ETH_BALANCE);
108108

109109
uint256 targetPrice = (currentPrice * targetCollateralRatio) / totalCollateralRatio;
110-
setLiquityPrice(targetPrice);
110+
_setLiquityPrice(targetPrice);
111111
assertTrue(TROVE_MANAGER.checkRecoveryMode(targetPrice), "Liquity not in recovery mode");
112112

113113
uint256 icr = TROVE_MANAGER.getCurrentICR(address(bridge), targetPrice);
@@ -321,13 +321,13 @@ contract TroveBridgeUnitTest is TroveBridgeTestBase {
321321

322322
uint256 priceBeforeDrop = TROVE_MANAGER.priceFeed().fetchPrice();
323323

324-
setLiquityPrice(LIQUITY_PRICE_FEED.fetchPrice() / 2);
324+
_setLiquityPrice(LIQUITY_PRICE_FEED.fetchPrice() / 2);
325325
TROVE_MANAGER.liquidateTroves(10);
326326

327327
_borrowAfterRedistribution();
328328

329329
// Rise the price back so that the system is not in recovery mode - allows me to drop trove's CR for a bit
330-
setLiquityPrice(priceBeforeDrop);
330+
_setLiquityPrice(priceBeforeDrop);
331331

332332
// Drop Trove's CR to MCR by impersonating the bridge and directly withdrawing collateral
333333
(uint256 debt, uint256 coll, , ) = TROVE_MANAGER.getEntireDebtAndColl(address(bridge));
@@ -466,7 +466,7 @@ contract TroveBridgeUnitTest is TroveBridgeTestBase {
466466

467467
uint256 priceBeforeDrop = TROVE_MANAGER.priceFeed().fetchPrice();
468468

469-
setLiquityPrice(LIQUITY_PRICE_FEED.fetchPrice() / 2);
469+
_setLiquityPrice(LIQUITY_PRICE_FEED.fetchPrice() / 2);
470470
TROVE_MANAGER.liquidateTroves(10);
471471

472472
(uint256 debtAfter, uint256 collAfter, , ) = TROVE_MANAGER.getEntireDebtAndColl(address(bridge));
@@ -477,7 +477,7 @@ contract TroveBridgeUnitTest is TroveBridgeTestBase {
477477
_borrowAfterRedistribution();
478478

479479
// Rise the price back so that the system is not in recovery mode - allows me to drop trove's CR for a bit
480-
setLiquityPrice(priceBeforeDrop);
480+
_setLiquityPrice(priceBeforeDrop);
481481
}
482482

483483
function _repay(

src/test/bridges/liquity/utils/TestUtil.sol

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@ contract TestUtil is Test {
1515
IERC20 erc;
1616
}
1717

18+
address internal constant LQTY_ETH_POOL = 0xD1D5A4c0eA98971894772Dcd6D2f1dc71083C44E; // 3000 bps fee tier
19+
address internal constant USDC_ETH_POOL = 0x88e6A0c2dDD26FEEb64F039a2c41296FcB3f5640; // 500 bps fee tier
20+
address internal constant LUSD_USDC_POOL = 0x4e0924d3a751bE199C426d52fb1f2337fa96f736; // 500 bps fee tier
21+
1822
IPriceFeed internal constant LIQUITY_PRICE_FEED = IPriceFeed(0x4c517D4e2C851CA76d7eC94B805269Df0f2201De);
1923

2024
mapping(bytes32 => Token) internal tokens;
@@ -25,7 +29,7 @@ contract TestUtil is Test {
2529
// rollup processor would.
2630
function receiveEthFromBridge(uint256 _interactionNonce) external payable {}
2731

28-
function setUpTokens() public {
32+
function _setUpTokensAndLabels() internal {
2933
tokens["LUSD"].addr = 0x5f98805A4E8be255a32880FDeC7F6728C6568bA0;
3034
tokens["LUSD"].erc = IERC20(tokens["LUSD"].addr);
3135
vm.label(tokens["LUSD"].addr, "LUSD");
@@ -41,16 +45,15 @@ contract TestUtil is Test {
4145
tokens["USDC"].addr = 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48;
4246
tokens["USDC"].erc = IERC20(tokens["USDC"].addr);
4347
vm.label(tokens["USDC"].addr, "USDC");
48+
49+
vm.label(LQTY_ETH_POOL, "LQTY_ETH_POOL");
50+
vm.label(USDC_ETH_POOL, "USDC_ETH_POOL");
51+
vm.label(LUSD_USDC_POOL, "LUSD_USDC_POOL");
4452
}
4553

46-
function setLiquityPrice(uint256 _price) public {
54+
function _setLiquityPrice(uint256 _price) internal {
4755
IPriceFeed mockFeed = new MockPriceFeed(_price);
4856
vm.etch(address(LIQUITY_PRICE_FEED), address(mockFeed).code);
4957
assertEq(LIQUITY_PRICE_FEED.fetchPrice(), _price);
5058
}
51-
52-
function rand(uint256 _seed) public pure returns (uint256) {
53-
// I want a number between 1 WAD and 10 million WAD
54-
return uint256(keccak256(abi.encodePacked(_seed))) % 10**25;
55-
}
5659
}

0 commit comments

Comments
 (0)