diff --git a/README.md b/README.md index 02cc2b2..15c1a57 100644 --- a/README.md +++ b/README.md @@ -18,15 +18,12 @@ The following outlines principles for core protocol funcitonality. Logic: -- None for now. +- None at the moment🙂 Tests: -- [ ] Create integration test for multiple calls `add()` -- [ ] Create integration test for multiple calls `addLeverage()` -- [ ] Create integration test for multiple calls `addWithPermit()` -- [ ] Remove all test_ActiveFork +- None at the moment🙂 Considerations: -- None for now. +- None at the moment🙂 diff --git a/package.json b/package.json index 8d9fe9c..206f79a 100644 --- a/package.json +++ b/package.json @@ -9,13 +9,13 @@ }, "scripts": { "commit": "cz", - "coverage": "forge coverage --report lcov && npm run coverage:filter && npx lcov-summary lcov.info", + "coverage": "forge coverage --fork-url https://arbitrum.llamarpc.com --report lcov && npm run coverage:filter && npx lcov-summary lcov.info", "coverage:filter": "lcov -r lcov.info 'test/*' 'src/dependencies/*' -o lcov.info", "format": "forge fmt", "format:check": "forge fmt --check", "lint:check": "solhint --config ./.solhint.json 'src/**/*.sol'", "prepare": "husky install", - "test": "forge test --optimize && npm run coverage" + "test": "forge test --fork-url https://arbitrum.llamarpc.com --optimize && npm run coverage" }, "commitlint": { "extends": [ diff --git a/src/FeeCollector.sol b/src/FeeCollector.sol index cc35437..2711463 100644 --- a/src/FeeCollector.sol +++ b/src/FeeCollector.sol @@ -39,8 +39,11 @@ contract FeeCollector is Ownable { // 2. Update client balances if (_client != address(0)) { - balances[_client][_token] += _clientFee; - totalClientBalances[_token] += _clientFee; + // Cannot overflow because the sum of all client balances can't exceed the max uint256 value. + unchecked { + balances[_client][_token] += _clientFee; + totalClientBalances[_token] += _clientFee; + } } } diff --git a/src/Position.sol b/src/Position.sol index 4e0e823..5a17d40 100644 --- a/src/Position.sol +++ b/src/Position.sol @@ -34,7 +34,7 @@ contract Position is DebtService, SwapService { } /** - * @notice Adds to this contract's short position. + * @notice Adds to this contract's position. * @param _cAmt The amount of collateral token to be supplied for this transaction-specific loan (units: C_DECIMALS). * @param _ltv The desired loan-to-value ratio for this transaction-specific loan (ex: 75 is 75%). * @param _swapAmtOutMin The minimum amount of output tokens from swap for the tx to go through. @@ -63,7 +63,7 @@ contract Position is DebtService, SwapService { } /** - * @notice Adds to this contract's short position with permit, obviating the need for a separate approve tx. + * @notice Adds to this contract's position with permit, obviating the need for a separate approve tx. * This function can only be used for ERC-2612-compliant tokens. * @param _cAmt The amount of collateral token to be supplied for this transaction-specific loan (units: C_DECIMALS). * @param _ltv The desired loan-to-value ratio for this transaction-specific loan (ex: 75 is 75%). @@ -94,7 +94,7 @@ contract Position is DebtService, SwapService { } /** - * @notice Adds leverage to this contract's short position. This function can only be used for positions where the + * @notice Adds leverage to this contract's position. This function can only be used for positions where the * collateral token is the same as the base token. * @param _ltv The desired loan-to-value ratio for this transaction-specific loan (ex: 75 is 75%). * @param _swapAmtOutMin The minimum amount of output tokens from swap for the tx to go through. @@ -123,7 +123,7 @@ contract Position is DebtService, SwapService { } /** - * @notice Fully closes the short position. + * @notice Fully closes the position. * @param _poolFee The fee of the Uniswap pool. * @param _exactOutput Whether to swap exact output or exact input (true for exact output, false for exact input). * @param _swapAmtOutMin The minimum amount of output tokens from swap for the tx to go through (only used if _exactOutput is false, supply 0 if true). diff --git a/src/interfaces/IPosition.sol b/src/interfaces/IPosition.sol index ee30214..c6c704a 100644 --- a/src/interfaces/IPosition.sol +++ b/src/interfaces/IPosition.sol @@ -46,7 +46,7 @@ interface IPosition { ** ******************************************************************************/ /** - * @notice Adds to this contract's short position. + * @notice Adds to this contract's position. * @param _cAmt The amount of collateral token to be supplied for this transaction-specific loan (units: C_DECIMALS). * @param _ltv The desired loan-to-value ratio for this transaction-specific loan (ex: 75 is 75%). * @param _swapAmtOutMin The minimum amount of output tokens from swap for the tx to go through. @@ -58,7 +58,7 @@ interface IPosition { payable; /** - * @notice Adds to this contract's short position with permit, obviating the need for a separate approve tx. + * @notice Adds to this contract's position with permit, obviating the need for a separate approve tx. * This function can only be used for ERC-2612-compliant tokens. * @param _cAmt The amount of collateral token to be supplied for this transaction-specific loan (units: C_DECIMALS). * @param _ltv The desired loan-to-value ratio for this transaction-specific loan (ex: 75 is 75%). @@ -83,7 +83,7 @@ interface IPosition { ) external payable; /** - * @notice Adds leverage to this contract's short position. This function can only be used for positions where the + * @notice Adds leverage to this contract's position. This function can only be used for positions where the * collateral token is the same as the base token. * @param _ltv The desired loan-to-value ratio for this transaction-specific loan (ex: 75 is 75%). * @param _swapAmtOutMin The minimum amount of output tokens from swap for the tx to go through. @@ -93,7 +93,7 @@ interface IPosition { function addLeverage(uint256 _ltv, uint256 _swapAmtOutMin, uint24 _poolFee, address _client) external payable; /** - * @notice Fully closes the short position. + * @notice Fully closes the position. * @param _poolFee The fee of the Uniswap pool. * @param _exactOutput Whether to swap exact output or exact input (true for exact output, false for exact input). * @param _swapAmtOutMin The minimum amount of output tokens from swap for the tx to go through (only used if _exactOutput is false, supply 0 if true). diff --git a/test/FeeCollector.t.sol b/test/FeeCollector.t.sol index ecf5275..eb5ca5d 100644 --- a/test/FeeCollector.t.sol +++ b/test/FeeCollector.t.sol @@ -32,15 +32,10 @@ contract FeeCollectorTest is Test, TokenUtils, FeeUtils { TestPosition[] public positions; // Test Storage - uint256 public mainnetFork; address public positionOwner = address(this); address public feeCollectorAddr; function setUp() public { - // Setup: use mainnet fork - mainnetFork = vm.createFork(vm.envString("RPC_URL")); - vm.selectFork(mainnetFork); - // Deploy assets assets = new Assets(); address[4] memory supportedAssets = assets.getSupported(); @@ -74,12 +69,6 @@ contract FeeCollectorTest is Test, TokenUtils, FeeUtils { positions.push(newPosition); } - /// @dev - // - The active fork should be the forked network created in the setup - function test_ActiveFork() public { - assertEq(vm.activeFork(), mainnetFork, "vm.activeFork() != mainnetFork"); - } - /// @dev // - The FeeCollector's feeToken balance should increase by _protocolFee // - The feeToken totalClientBalances should increase by clientFee diff --git a/test/Position.t.sol b/test/Position.t.sol index 9fbfae6..1cfbfe1 100644 --- a/test/Position.t.sol +++ b/test/Position.t.sol @@ -43,14 +43,9 @@ contract PositionTest is Test, TokenUtils, DebtUtils { // Test Storage VmSafe.Wallet public wallet; address public positionAddr; - uint256 public mainnetFork; address public owner; function setUp() public { - // Setup: use mainnet fork - mainnetFork = vm.createFork(vm.envString("RPC_URL")); - vm.selectFork(mainnetFork); - // Set contract owner wallet = vm.createWallet(uint256(keccak256(abi.encodePacked(uint256(1))))); owner = wallet.addr; @@ -98,12 +93,6 @@ contract PositionTest is Test, TokenUtils, DebtUtils { } } - /// @dev - // - The active fork should be the forked network created in the setup - function test_ActiveFork() public { - assertEq(vm.activeFork(), mainnetFork, "vm.activeFork() != mainnetFork"); - } - /// @dev // - It should revert with Unauthorized() error when called by an unauthorized sender. function testFuzz_CannotAdd(address _sender) public { @@ -249,7 +238,7 @@ contract PositionTest is Test, TokenUtils, DebtUtils { // Test variables address addr = positions[i].addr; - // Setup: open short position + // Setup: open position uint256 cAmt = assets.maxCAmts(positions[i].cToken); _fund(owner, positions[i].cToken, cAmt); vm.startPrank(owner); diff --git a/test/PositionFactory.t.sol b/test/PositionFactory.t.sol index de9c79a..229b779 100644 --- a/test/PositionFactory.t.sol +++ b/test/PositionFactory.t.sol @@ -19,7 +19,6 @@ contract PositionFactoryTest is Test, TokenUtils { Assets public assets; // Test Storage - uint256 public mainnetFork; address public positionOwner = address(this); // Errors @@ -29,21 +28,11 @@ contract PositionFactoryTest is Test, TokenUtils { event PositionCreated(address indexed owner, address indexed position); function setUp() public { - // Setup: use mainnet fork - mainnetFork = vm.createFork(vm.envString("RPC_URL")); - vm.selectFork(mainnetFork); - vm.prank(CONTRACT_DEPLOYER); positionFactory = new PositionFactory(CONTRACT_DEPLOYER); assets = new Assets(); } - /// @dev - // - The active fork should be the forked network created in the setup - function test_ActiveFork() public { - assertEq(vm.activeFork(), mainnetFork, "vm.activeFork() != mainnetFork"); - } - /// @dev // - It should create a Position contract for each possible permutation of cToken, bToken, and bToken. function test_CreatePosition() public { diff --git a/test/common/Constants.t.sol b/test/common/Constants.t.sol index fe178a5..28c7340 100644 --- a/test/common/Constants.t.sol +++ b/test/common/Constants.t.sol @@ -26,6 +26,8 @@ uint256 constant WITHDRAW_BUFFER = 100_000; uint256 constant REPAY_BUFFER = 2; uint256 constant PROTOCOL_FEE_RATE = 3; uint256 constant CLIENT_RATE = 30; +uint256 constant CLIENT_TAKE_RATE = 50; +uint256 constant SUCCESSIVE_ITERATIONS = 5; contract Assets { address[4] public supported = [USDC, DAI, WETH, WBTC]; @@ -43,10 +45,10 @@ contract Assets { decimals[WBTC] = 8; // Set max collateral amounts - maxCAmts[USDC] = 1_000 * 10 ** 6; - maxCAmts[DAI] = 100_000 * 10 ** 18; - maxCAmts[WETH] = 50 * 10 ** 18; - maxCAmts[WBTC] = 2 * 10 ** 8; + maxCAmts[USDC] = 10_000 * 10 ** 6; + maxCAmts[DAI] = 10_000 * 10 ** 18; + maxCAmts[WETH] = 25 * 10 ** 18; + maxCAmts[WBTC] = 1 * 10 ** 8; // Set min collateral amounts minCAmts[USDC] = 100 * 10 ** 6; diff --git a/test/integration/FeeCollector.add.t.sol b/test/integration/FeeCollector.add.t.sol index 2d3e2f0..46e2c61 100644 --- a/test/integration/FeeCollector.add.t.sol +++ b/test/integration/FeeCollector.add.t.sol @@ -53,14 +53,9 @@ contract FeeCollectorAddTest is Test, TokenUtils, FeeUtils, DebtUtils { TestPosition[] public positions; // Test Storage - uint256 public mainnetFork; address public positionOwner = address(this); function setUp() public { - // Setup: use mainnet fork - mainnetFork = vm.createFork(vm.envString("RPC_URL")); - vm.selectFork(mainnetFork); - // Deploy assets assets = new Assets(); address[4] memory supportedAssets = assets.getSupported(); @@ -102,12 +97,6 @@ contract FeeCollectorAddTest is Test, TokenUtils, FeeUtils, DebtUtils { } } - /// @dev - // - The active fork should be the forked network created in the setup - function test_ActiveFork() public { - assertEq(vm.activeFork(), mainnetFork, "vm.activeFork() != mainnetFork"); - } - /// @dev // - The FeeCollector's cToken balance should increase by (maxFee - userSavings). // - The cToken amount supplied as collateral should be cAmt - (maxFee - userSavings). @@ -150,7 +139,7 @@ contract FeeCollectorAddTest is Test, TokenUtils, FeeUtils, DebtUtils { uint256 prePositionATokenBal = _getATokenBalance(positionAddr, cToken); assertEq(prePositionATokenBal, 0); - // Act: increase short position + // Act: increase position IPosition(positionAddr).add(_cAmt, 50, 0, TEST_POOL_FEE, TEST_CLIENT); // Post-act balances @@ -204,7 +193,7 @@ contract FeeCollectorAddTest is Test, TokenUtils, FeeUtils, DebtUtils { uint256 prePositionATokenBal = _getATokenBalance(positionAddr, cToken); assertEq(prePositionATokenBal, 0); - // Act: increase short position + // Act: increase position IPosition(positionAddr).add(_cAmt, 50, 0, TEST_POOL_FEE, address(0)); // Post-act balances diff --git a/test/integration/FeeCollector.addLeverage.t.sol b/test/integration/FeeCollector.addLeverage.t.sol index 1bc8dbf..dd12864 100644 --- a/test/integration/FeeCollector.addLeverage.t.sol +++ b/test/integration/FeeCollector.addLeverage.t.sol @@ -57,13 +57,8 @@ contract FeeCollectorAddLeverageTest is Test, TokenUtils, DebtUtils, FeeUtils { // Test Storage address public positionAddr; - uint256 public mainnetFork; function setUp() public { - // Setup: use mainnet fork - mainnetFork = vm.createFork(vm.envString("RPC_URL")); - vm.selectFork(mainnetFork); - // Deploy assets assets = new Assets(); address[4] memory supportedAssets = assets.getSupported(); @@ -109,12 +104,6 @@ contract FeeCollectorAddLeverageTest is Test, TokenUtils, DebtUtils, FeeUtils { } } - /// @dev - // - The active fork should be the forked network created in the setup - function test_ActiveFork() public { - assertEq(vm.activeFork(), mainnetFork, "vm.activeFork() != mainnetFork"); - } - /// @dev // - The FeeCollector's feeToken balance should increase by (maxFee - userSavings). // - The feeToken amount supplied as collateral should be _bAmt - (maxFee - userSavings). diff --git a/test/integration/FeeCollector.clientFees.t.sol b/test/integration/FeeCollector.clientFees.t.sol index 5fe7347..b058d3f 100644 --- a/test/integration/FeeCollector.clientFees.t.sol +++ b/test/integration/FeeCollector.clientFees.t.sol @@ -19,15 +19,10 @@ contract FeeCollectorClientFeesTest is Test, TokenUtils { // Test Storage address[] public supportedAssets; - uint256 public mainnetFork; address public owner = address(this); address public feeCollectorAddr; function setUp() public { - // Setup: use mainnet fork - mainnetFork = vm.createFork(vm.envString("RPC_URL")); - vm.selectFork(mainnetFork); - // Deploy assets assets = new Assets(); supportedAssets = assets.getSupported(); @@ -38,12 +33,6 @@ contract FeeCollectorClientFeesTest is Test, TokenUtils { feeCollectorAddr = address(feeCollector); } - /// @dev - // - The active fork should be the forked network created in the setup - function test_ActiveFork() public { - assertEq(vm.activeFork(), mainnetFork, "vm.activeFork() != mainnetFork"); - } - /// @dev // - The sum of all client fees should equal totalClientBalances // - The expectedClientFee should always be equal to or 1 less than clientFee, due to integer division diff --git a/test/integration/Position.add.t.sol b/test/integration/Position.add.t.sol index 99b8436..703ed44 100644 --- a/test/integration/Position.add.t.sol +++ b/test/integration/Position.add.t.sol @@ -10,20 +10,26 @@ import { PositionFactory } from "src/PositionFactory.sol"; import { Assets, AAVE_ORACLE, + CLIENT_RATE, + CLIENT_TAKE_RATE, CONTRACT_DEPLOYER, DAI, FEE_COLLECTOR, + PROTOCOL_FEE_RATE, + SUCCESSIVE_ITERATIONS, TEST_CLIENT, TEST_POOL_FEE, USDC } from "test/common/Constants.t.sol"; import { TokenUtils } from "test/common/utils/TokenUtils.t.sol"; import { DebtUtils } from "test/common/utils/DebtUtils.t.sol"; +import { FeeUtils } from "test/common/utils/FeeUtils.t.sol"; +import { IFeeCollector } from "src/interfaces/IFeeCollector.sol"; import { IAaveOracle } from "src/interfaces/aave/IAaveOracle.sol"; import { IPosition } from "src/interfaces/IPosition.sol"; import { IERC20 } from "src/interfaces/token/IERC20.sol"; -contract PositionAddTest is Test, TokenUtils, DebtUtils { +contract PositionAddTest is Test, TokenUtils, DebtUtils, FeeUtils { /* solhint-disable func-name-mixedcase */ struct TestPosition { @@ -33,6 +39,41 @@ contract PositionAddTest is Test, TokenUtils, DebtUtils { address bToken; } + struct PositionBalances { + uint256 preBToken; + uint256 postBToken; + uint256 preVDToken; + uint256 postVDToken; + uint256 preAToken; + uint256 postAToken; + } + + struct OwnerBalances { + uint256 preCToken; + uint256 postCToken; + } + + struct FeeData { + uint256 maxFee; + uint256 userSavings; + uint256 protocolFee; + } + + struct SuccessiveSums { + uint256 cAmt; + uint256 dAmt; + uint256 bAmt; + } + + struct LoanData { + uint256 debtBeforeTimeDelta; + uint256 debtAfterTimeDelta; + uint256 debtInterest; + uint256 colBeforeTimeDelta; + uint256 colAfterTimeDelta; + uint256 colInterest; + } + // Test contracts PositionFactory public positionFactory; Assets public assets; @@ -40,14 +81,9 @@ contract PositionAddTest is Test, TokenUtils, DebtUtils { // Test Storage address public positionAddr; - uint256 public mainnetFork; address public owner = address(this); function setUp() public { - // Setup: use mainnet fork - mainnetFork = vm.createFork(vm.envString("RPC_URL")); - vm.selectFork(mainnetFork); - // Deploy assets assets = new Assets(); address[4] memory supportedAssets = assets.getSupported(); @@ -56,6 +92,14 @@ contract PositionAddTest is Test, TokenUtils, DebtUtils { vm.prank(CONTRACT_DEPLOYER); deployCodeTo("FeeCollector.sol", abi.encode(CONTRACT_DEPLOYER), FEE_COLLECTOR); + // Set client rate + vm.prank(CONTRACT_DEPLOYER); + IFeeCollector(FEE_COLLECTOR).setClientRate(CLIENT_RATE); + + // Set client take rate + vm.prank(TEST_CLIENT); + IFeeCollector(FEE_COLLECTOR).setClientTakeRate(CLIENT_TAKE_RATE); + // Deploy PositionFactory vm.prank(CONTRACT_DEPLOYER); positionFactory = new PositionFactory(CONTRACT_DEPLOYER); @@ -91,63 +135,173 @@ contract PositionAddTest is Test, TokenUtils, DebtUtils { } } - /// @dev - // - The active fork should be the forked network created in the setup - function test_ActiveFork() public { - assertEq(vm.activeFork(), mainnetFork, "vm.activeFork() != mainnetFork"); - } - /// @dev // - Owner's cToken balance should decrease by collateral amount supplied. - // - Position's bToken balance should increase by amount receieved from swap. + // - The Position contract's bToken balance should increase by bAmt receieved from swap. + // - The Position contract's aToken balance should increase by (collateral - protocolFee). + // - The Position contract's variableDebtToken balance should increase by dAmt received from swap. // - The above should be true for a wide range of LTVs. // - The above should be true for a wide range of collateral amounts. // - The above should be true for all supported tokens. function testFuzz_Add(uint256 _ltv, uint256 _cAmt) public { + // Setup + PositionBalances memory positionBalances; + OwnerBalances memory ownerBalances; + FeeData memory feeData; + TestPosition memory p; + // Take snapshot uint256 id = vm.snapshot(); for (uint256 i; i < positions.length; i++) { // Test variables - address addr = positions[i].addr; - address cToken = positions[i].cToken; - address bToken = positions[i].bToken; + p.addr = positions[i].addr; + p.cToken = positions[i].cToken; + p.dToken = positions[i].dToken; + p.bToken = positions[i].bToken; // Bound fuzzed variables _ltv = bound(_ltv, 1, 60); - _cAmt = bound(_cAmt, assets.minCAmts(cToken), assets.maxCAmts(cToken)); + _cAmt = bound(_cAmt, assets.minCAmts(p.cToken), assets.maxCAmts(p.cToken)); // Fund owner with collateral - _fund(owner, cToken, _cAmt); + _fund(owner, p.cToken, _cAmt); - // Approve position to spend collateral - IERC20(cToken).approve(addr, _cAmt); + // Expectations + feeData.maxFee = (_cAmt * PROTOCOL_FEE_RATE) / 1000; + (feeData.userSavings,) = _getExpectedClientAllocations(feeData.maxFee, CLIENT_TAKE_RATE); + feeData.protocolFee = feeData.maxFee - feeData.userSavings; // Pre-act balances - uint256 cTokenPreBal = IERC20(cToken).balanceOf(owner); - uint256 bTokenPreBal = IERC20(bToken).balanceOf(addr); + ownerBalances.preCToken = IERC20(p.cToken).balanceOf(owner); + positionBalances.preBToken = IERC20(p.bToken).balanceOf(p.addr); + positionBalances.preAToken = _getATokenBalance(p.addr, p.cToken); + positionBalances.preVDToken = _getVariableDebtTokenBalance(p.addr, p.dToken); + assertEq(positionBalances.preAToken, 0); + assertEq(positionBalances.preVDToken, 0); // Act vm.recordLogs(); - IPosition(addr).add(_cAmt, _ltv, 0, TEST_POOL_FEE, TEST_CLIENT); - VmSafe.Log[] memory entries = vm.getRecordedLogs(); + IERC20(p.cToken).approve(p.addr, _cAmt); + IPosition(p.addr).add(_cAmt, _ltv, 0, TEST_POOL_FEE, TEST_CLIENT); // Post-act balances - uint256 cTokenPostBal = IERC20(cToken).balanceOf(owner); - uint256 bTokenPostBal = IERC20(bToken).balanceOf(addr); + VmSafe.Log[] memory entries = vm.getRecordedLogs(); + ownerBalances.postCToken = IERC20(p.cToken).balanceOf(owner); + positionBalances.postBToken = IERC20(p.bToken).balanceOf(p.addr); + positionBalances.postAToken = _getATokenBalance(p.addr, p.cToken); + positionBalances.postVDToken = _getVariableDebtTokenBalance(p.addr, p.dToken); + + // Retrieve bAmt and dAmt from Add event bytes memory addEvent = entries[entries.length - 1].data; + uint256 dAmt; uint256 bAmt; - assembly { - let startPos := sub(mload(addEvent), 32) - bAmt := mload(add(addEvent, add(0x20, startPos))) + dAmt := mload(add(addEvent, 0x40)) + bAmt := mload(add(addEvent, 0x60)) + } + + // Assertions + assertEq(ownerBalances.postCToken, ownerBalances.preCToken - _cAmt); + assertEq(positionBalances.postBToken, positionBalances.preBToken + bAmt); + assertApproxEqAbs(positionBalances.postAToken, _cAmt - feeData.protocolFee, 1); + assertApproxEqAbs(positionBalances.postVDToken, dAmt, 1); + + // Revert to snapshot to standardize chain state for each position + vm.revertTo(id); + } + } + + /// @dev + // - The Position contract's bToken balance should increase by total bAmt receieved from swap across all add actions. + // - The Position contract's aToken balance should increase by emitted cAmt across all add actions. + // - The Position contract's variableDebtToken balance should increase by total dAmt received from borrow across all add actions. + // - The above should be true for a wide range of LTVs. + // - The above should be true for a wide range of collateral amounts. + // - The above should be true for all supported tokens. + function testFuzz_AddSuccessive(uint256 _ltv, uint256 _cAmt, uint256 _time) public { + // Setup + PositionBalances memory positionBalances; + TestPosition memory p; + SuccessiveSums memory sums; + LoanData memory loanData; + + // Take snapshot + uint256 id = vm.snapshot(); + + /// @dev Test each position + for (uint256 i; i < positions.length; i++) { + // Test variables + p.addr = positions[i].addr; + p.cToken = positions[i].cToken; + p.dToken = positions[i].dToken; + p.bToken = positions[i].bToken; + + sums.cAmt = 0; + sums.dAmt = 0; + sums.bAmt = 0; + loanData.debtBeforeTimeDelta = 0; + loanData.debtAfterTimeDelta = 0; + loanData.debtInterest = 0; + loanData.colBeforeTimeDelta = 0; + loanData.colAfterTimeDelta = 0; + loanData.colInterest = 0; + for (uint256 j; j < SUCCESSIVE_ITERATIONS; j++) { + // Bound fuzzed variables + _ltv = bound(_ltv, 1, 60); + _cAmt = bound(_cAmt, assets.minCAmts(p.cToken), assets.maxCAmts(p.cToken)); + _time = bound(_time, 1 minutes, 12 weeks); + + // Fund owner with collateral + _fund(owner, p.cToken, _cAmt); + + // Act + vm.recordLogs(); + IERC20(p.cToken).approve(p.addr, _cAmt); + IPosition(p.addr).add(_cAmt, _ltv, 0, TEST_POOL_FEE, TEST_CLIENT); + + // Retrieve bAmt and dAmt from Add event + VmSafe.Log[] memory entries = vm.getRecordedLogs(); + bytes memory addEvent = entries[entries.length - 1].data; + uint256 netCAmt; + uint256 dAmt; + uint256 bAmt; + assembly { + netCAmt := mload(add(addEvent, 0x20)) + dAmt := mload(add(addEvent, 0x40)) + bAmt := mload(add(addEvent, 0x60)) + } + + // Sum successive adds + sums.cAmt += (netCAmt + loanData.colInterest); + sums.dAmt += (dAmt + loanData.debtInterest); + sums.bAmt += bAmt; + + // Introduce time delta between successive adds + if (j != SUCCESSIVE_ITERATIONS - 1) { + loanData.debtBeforeTimeDelta = _getVariableDebtTokenBalance(p.addr, p.dToken); + loanData.colBeforeTimeDelta = _getATokenBalance(p.addr, p.cToken); + skip(_time); + loanData.debtAfterTimeDelta = _getVariableDebtTokenBalance(p.addr, p.dToken); + loanData.colAfterTimeDelta = _getATokenBalance(p.addr, p.cToken); + loanData.debtInterest = loanData.debtAfterTimeDelta - loanData.debtBeforeTimeDelta; + loanData.colInterest = loanData.colAfterTimeDelta - loanData.colBeforeTimeDelta; + } } + // Post-act balances + positionBalances.postBToken = IERC20(p.bToken).balanceOf(p.addr); + positionBalances.postAToken = _getATokenBalance(p.addr, p.cToken); + positionBalances.postVDToken = _getVariableDebtTokenBalance(p.addr, p.dToken); + // Assertions - assertEq(cTokenPostBal, cTokenPreBal - _cAmt); - assertEq(bTokenPostBal, bTokenPreBal + bAmt); + assertEq(positionBalances.postBToken, sums.bAmt); + /// @dev The max delta per iteration is 1. Therefore, the max + // delta for all iterations is the number of iterations. + assertApproxEqAbs(positionBalances.postAToken, sums.cAmt, SUCCESSIVE_ITERATIONS); + assertApproxEqAbs(positionBalances.postVDToken, sums.dAmt, SUCCESSIVE_ITERATIONS); - // Revert to snapshot + // Revert to snapshot to standardize chain state for each position vm.revertTo(id); } } diff --git a/test/integration/Position.addLeverage.t.sol b/test/integration/Position.addLeverage.t.sol index d556e75..011d00f 100644 --- a/test/integration/Position.addLeverage.t.sol +++ b/test/integration/Position.addLeverage.t.sol @@ -9,19 +9,23 @@ import { VmSafe } from "forge-std/Vm.sol"; import { PositionFactory } from "src/PositionFactory.sol"; import { Assets, + AAVE_POOL, AAVE_ORACLE, CONTRACT_DEPLOYER, DAI, FEE_COLLECTOR, + SUCCESSIVE_ITERATIONS, TEST_CLIENT, TEST_POOL_FEE, - USDC + USDC, + WBTC } from "test/common/Constants.t.sol"; import { TokenUtils } from "test/common/utils/TokenUtils.t.sol"; import { DebtUtils } from "test/common/utils/DebtUtils.t.sol"; import { IAaveOracle } from "src/interfaces/aave/IAaveOracle.sol"; import { IPosition } from "src/interfaces/IPosition.sol"; import { IERC20 } from "src/interfaces/token/IERC20.sol"; +import { IPool } from "src/interfaces/aave/IPool.sol"; contract PositionAddLeverageTest is Test, TokenUtils, DebtUtils { /* solhint-disable func-name-mixedcase */ @@ -33,13 +37,29 @@ contract PositionAddLeverageTest is Test, TokenUtils, DebtUtils { address bToken; } - struct ContractBalances { + struct PositionBalances { uint256 preBToken; uint256 postBToken; uint256 preVDToken; uint256 postVDToken; uint256 preAToken; uint256 postAToken; + uint256 cTotalUSD; + uint256 dTotalUSD; + } + + struct SuccessiveSums { + uint256 cAmt; + uint256 dAmt; + } + + struct LoanData { + uint256 debtBeforeTimeDelta; + uint256 debtAfterTimeDelta; + uint256 debtInterest; + uint256 colBeforeTimeDelta; + uint256 colAfterTimeDelta; + uint256 colInterest; } // Test contracts @@ -49,14 +69,9 @@ contract PositionAddLeverageTest is Test, TokenUtils, DebtUtils { // Test Storage address public positionAddr; - uint256 public mainnetFork; address public owner = address(this); function setUp() public { - // Setup: use mainnet fork - mainnetFork = vm.createFork(vm.envString("RPC_URL")); - vm.selectFork(mainnetFork); - // Deploy assets assets = new Assets(); address[4] memory supportedAssets = assets.getSupported(); @@ -98,12 +113,6 @@ contract PositionAddLeverageTest is Test, TokenUtils, DebtUtils { } } - /// @dev - // - The active fork should be the forked network created in the setup - function test_ActiveFork() public { - assertEq(vm.activeFork(), mainnetFork, "vm.activeFork() != mainnetFork"); - } - /// @dev // - The Position contract's bToken balance after adding leverage should equal bAmt (from swap). // - The Position contract's aToken balance should increase by its bToken balance before adding leverage. @@ -111,38 +120,40 @@ contract PositionAddLeverageTest is Test, TokenUtils, DebtUtils { // - The above should be true for a large range of LTVs and cAmts. function testFuzz_AddLeverage(uint256 _ltv, uint256 _cAmt) public { // Setup - ContractBalances memory contractBalances; + PositionBalances memory positionBalances; + TestPosition memory p; // Take snapshot uint256 id = vm.snapshot(); for (uint256 i; i < positions.length; i++) { // Test variables - address addr = positions[i].addr; - address cToken = positions[i].cToken; - address bToken = cToken; + p.addr = positions[i].addr; + p.cToken = positions[i].cToken; + p.dToken = positions[i].dToken; + p.bToken = positions[i].bToken; // Bound fuzzed variables _ltv = bound(_ltv, 1, 60); - _cAmt = bound(_cAmt, assets.minCAmts(cToken), assets.maxCAmts(cToken)); + _cAmt = bound(_cAmt, assets.minCAmts(p.cToken), assets.maxCAmts(p.cToken)); // Fund owner with collateral - _fund(owner, cToken, _cAmt); + _fund(owner, p.cToken, _cAmt); // Approve position to spend collateral - IERC20(cToken).approve(addr, _cAmt); + IERC20(p.cToken).approve(p.addr, _cAmt); - // Add initial short position - IPosition(addr).add(_cAmt, 50, 0, TEST_POOL_FEE, TEST_CLIENT); + // Add initial position + IPosition(p.addr).add(_cAmt, 50, 0, TEST_POOL_FEE, TEST_CLIENT); // Pre-act balances - contractBalances.preBToken = IERC20(bToken).balanceOf(addr); - contractBalances.preVDToken = _getVariableDebtTokenBalance(addr, positions[i].dToken); - contractBalances.preAToken = _getATokenBalance(addr, positions[i].cToken); + positionBalances.preBToken = IERC20(p.bToken).balanceOf(p.addr); + positionBalances.preVDToken = _getVariableDebtTokenBalance(p.addr, p.dToken); + positionBalances.preAToken = _getATokenBalance(p.addr, p.cToken); // Act vm.recordLogs(); - IPosition(addr).addLeverage(_ltv, 0, TEST_POOL_FEE, TEST_CLIENT); + IPosition(p.addr).addLeverage(_ltv, 0, TEST_POOL_FEE, TEST_CLIENT); // Retrieve bAmt and dAmt from AddLeverage event VmSafe.Log[] memory entries = vm.getRecordedLogs(); @@ -157,17 +168,122 @@ contract PositionAddLeverageTest is Test, TokenUtils, DebtUtils { } // Post-act balances - contractBalances.postBToken = IERC20(bToken).balanceOf(addr); - contractBalances.postVDToken = _getVariableDebtTokenBalance(addr, positions[i].dToken); - contractBalances.postAToken = _getATokenBalance(addr, positions[i].cToken); + positionBalances.postBToken = IERC20(p.bToken).balanceOf(p.addr); + positionBalances.postVDToken = _getVariableDebtTokenBalance(p.addr, p.dToken); + positionBalances.postAToken = _getATokenBalance(p.addr, p.cToken); // Assertions - assertEq(contractBalances.postBToken, bAmt); - assertApproxEqAbs(contractBalances.postAToken, contractBalances.preAToken + cAmt, 1); - assertApproxEqAbs(contractBalances.postVDToken, contractBalances.preVDToken + dAmt, 1); + assertEq(positionBalances.postBToken, bAmt); + assertApproxEqAbs(positionBalances.postAToken, positionBalances.preAToken + cAmt, 1); + assertApproxEqAbs(positionBalances.postVDToken, positionBalances.preVDToken + dAmt, 1); // Revert to snapshot vm.revertTo(id); } } + + /// @dev + // - The Position contract's bToken balance after adding leverage should equal bAmt receieved from swap across all addLeverage actions. + // - The Position contract's aToken balance should increase by emitted cAmt across all add actions. + // - The Position contract's variable debt token balance should increase by dAmt received from borrow across all add actions + // - The above should be true for a large range of LTVs and cAmts. + // - The above should be true for all positions where the collateral token is the same as the base token. + function testFuzz_AddLeverageSuccessive(uint256 _cAmt, uint256 _time) public { + // Setup + PositionBalances memory positionBalances; + TestPosition memory p; + SuccessiveSums memory sums; + LoanData memory loanData; + + // Take snapshot + uint256 id = vm.snapshot(); + + for (uint256 i; i < positions.length; i++) { + // Test variables + p.addr = positions[i].addr; + p.cToken = positions[i].cToken; + p.dToken = positions[i].dToken; + p.bToken = positions[i].bToken; + + // Bound fuzzed variables + // _ltv = bound(_ltv, 1, 60); + _cAmt = bound(_cAmt, assets.minCAmts(p.cToken), assets.maxCAmts(p.cToken)); + + // Fund owner with collateral + _fund(owner, p.cToken, _cAmt); + + // Add initial position + IERC20(p.cToken).approve(p.addr, _cAmt); + IPosition(p.addr).add(_cAmt, 50, 0, TEST_POOL_FEE, TEST_CLIENT); + + /// @dev Initial balances to refect inital add + uint256 bAmtEndState; + sums.cAmt = _getATokenBalance(p.addr, p.cToken); + sums.dAmt = _getVariableDebtTokenBalance(p.addr, p.dToken); + loanData.debtBeforeTimeDelta = 0; + loanData.debtAfterTimeDelta = 0; + loanData.debtInterest = 0; + loanData.colBeforeTimeDelta = 0; + loanData.colAfterTimeDelta = 0; + loanData.colInterest = 0; + + bool shallowLiquidity = (p.bToken == DAI && p.dToken == WBTC) || (p.bToken == WBTC && p.dToken == DAI); + if (!shallowLiquidity) { + for (uint256 j; j < SUCCESSIVE_ITERATIONS; j++) { + _time = bound(_time, 1 minutes, 2 minutes); + + (positionBalances.cTotalUSD, positionBalances.dTotalUSD,,,,) = + IPool(AAVE_POOL).getUserAccountData(p.addr); + + // Act + vm.recordLogs(); + IPosition(p.addr).addLeverage(50, 0, TEST_POOL_FEE, TEST_CLIENT); + + // Retrieve bAmt and dAmt from AddLeverage event + VmSafe.Log[] memory entries = vm.getRecordedLogs(); + bytes memory addLeverageEvent = entries[entries.length - 1].data; + uint256 netCAmt; + uint256 dAmt; + uint256 bAmt; + assembly { + netCAmt := mload(add(addLeverageEvent, 0x20)) + dAmt := mload(add(addLeverageEvent, 0x40)) + bAmt := mload(add(addLeverageEvent, 0x60)) + } + + // Sum successive adds + sums.cAmt += (netCAmt + loanData.colInterest); + sums.dAmt += (dAmt + loanData.debtInterest); + + // Introduce time delta between successive adds + if (j != SUCCESSIVE_ITERATIONS - 1) { + loanData.debtBeforeTimeDelta = _getVariableDebtTokenBalance(p.addr, p.dToken); + loanData.colBeforeTimeDelta = _getATokenBalance(p.addr, p.cToken); + skip(_time); + loanData.debtAfterTimeDelta = _getVariableDebtTokenBalance(p.addr, p.dToken); + loanData.colAfterTimeDelta = _getATokenBalance(p.addr, p.cToken); + loanData.debtInterest = loanData.debtAfterTimeDelta - loanData.debtBeforeTimeDelta; + loanData.colInterest = loanData.colAfterTimeDelta - loanData.colBeforeTimeDelta; + } else { + bAmtEndState = bAmt; + } + } + // Post-act balances + positionBalances.postBToken = IERC20(p.bToken).balanceOf(p.addr); + positionBalances.postAToken = _getATokenBalance(p.addr, p.cToken); + positionBalances.postVDToken = _getVariableDebtTokenBalance(p.addr, p.dToken); + + // Assertions + + assertEq(positionBalances.postBToken, bAmtEndState); + /// @dev The max delta per iteration is 1. Therefore, the max + // delta for all iterations is the number of iterations. + assertApproxEqAbs(positionBalances.postAToken, sums.cAmt, SUCCESSIVE_ITERATIONS); + assertApproxEqAbs(positionBalances.postVDToken, sums.dAmt, SUCCESSIVE_ITERATIONS); + } + + // Revert to snapshot to standardize chain state for each position + vm.revertTo(id); + } + } } diff --git a/test/integration/Position.shortWithPermit.t.sol b/test/integration/Position.addWithPermit.t.sol similarity index 61% rename from test/integration/Position.shortWithPermit.t.sol rename to test/integration/Position.addWithPermit.t.sol index d926bc9..d390585 100644 --- a/test/integration/Position.shortWithPermit.t.sol +++ b/test/integration/Position.addWithPermit.t.sol @@ -10,20 +10,25 @@ import { PositionFactory } from "src/PositionFactory.sol"; import { Assets, AAVE_ORACLE, + CLIENT_RATE, + CLIENT_TAKE_RATE, CONTRACT_DEPLOYER, DAI, FEE_COLLECTOR, TEST_CLIENT, TEST_POOL_FEE, + PROTOCOL_FEE_RATE, USDC } from "test/common/Constants.t.sol"; import { TokenUtils } from "test/common/utils/TokenUtils.t.sol"; import { DebtUtils } from "test/common/utils/DebtUtils.t.sol"; +import { FeeUtils } from "test/common/utils/FeeUtils.t.sol"; +import { IFeeCollector } from "src/interfaces/IFeeCollector.sol"; import { IAaveOracle } from "src/interfaces/aave/IAaveOracle.sol"; import { IPosition } from "src/interfaces/IPosition.sol"; import { IERC20 } from "src/interfaces/token/IERC20.sol"; -contract PositionShortPermitTest is Test, TokenUtils, DebtUtils { +contract PositionAddPermitTest is Test, TokenUtils, DebtUtils, FeeUtils { /* solhint-disable func-name-mixedcase */ struct TestPosition { @@ -33,24 +38,32 @@ contract PositionShortPermitTest is Test, TokenUtils, DebtUtils { address bToken; } - struct ContractBalances { + struct PositionBalances { uint256 preBToken; uint256 postBToken; uint256 preVDToken; uint256 postVDToken; uint256 preAToken; uint256 postAToken; - uint256 preDToken; - uint256 postDToken; } struct OwnerBalances { - uint256 preBToken; - uint256 postBToken; uint256 preCToken; uint256 postCToken; } + struct FeeData { + uint256 maxFee; + uint256 userSavings; + uint256 protocolFee; + } + + struct Permit { + uint8 v; + bytes32 r; + bytes32 s; + } + // Test contracts PositionFactory public positionFactory; Assets public assets; @@ -59,17 +72,12 @@ contract PositionShortPermitTest is Test, TokenUtils, DebtUtils { // Test Storage VmSafe.Wallet public wallet; address public positionAddr; - uint256 public mainnetFork; address public owner; // Events event Add(uint256 cAmt, uint256 dAmt, uint256 bAmt); function setUp() public { - // Setup: use mainnet fork - mainnetFork = vm.createFork(vm.envString("RPC_URL")); - vm.selectFork(mainnetFork); - // Deploy assets assets = new Assets(); address[4] memory supportedAssets = assets.getSupported(); @@ -78,6 +86,14 @@ contract PositionShortPermitTest is Test, TokenUtils, DebtUtils { vm.prank(CONTRACT_DEPLOYER); deployCodeTo("FeeCollector.sol", abi.encode(CONTRACT_DEPLOYER), FEE_COLLECTOR); + // Set client rate + vm.prank(CONTRACT_DEPLOYER); + IFeeCollector(FEE_COLLECTOR).setClientRate(CLIENT_RATE); + + // Set client take rate + vm.prank(TEST_CLIENT); + IFeeCollector(FEE_COLLECTOR).setClientTakeRate(CLIENT_TAKE_RATE); + // Deploy PositionFactory vm.prank(CONTRACT_DEPLOYER); positionFactory = new PositionFactory(CONTRACT_DEPLOYER); @@ -120,62 +136,84 @@ contract PositionShortPermitTest is Test, TokenUtils, DebtUtils { /// @dev // - Owner's cToken balance should decrease by collateral amount supplied. - // - Position's bToken balance should increase by amount receieved from swap. + // - The Position contract's bToken balance should increase by bAmt receieved from swap. + // - The Position contract's aToken balance should increase by (collateral - protocolFee). + // - The Position contract's variableDebtToken balance should increase by dAmt received from swap. // - The above should be true for a wide range of LTVs. // - The above should be true for a wide range of collateral amounts. // - The above should be true for all supported tokens. // - The act should be accomplished without a separate approve tx. function testFuzz_AddWithPermit(uint256 _ltv, uint256 _cAmt) public { - ContractBalances memory contractBalances; + PositionBalances memory positionBalances; OwnerBalances memory ownerBalances; + FeeData memory feeData; + TestPosition memory p; + Permit memory permit; // Take snapshot uint256 id = vm.snapshot(); for (uint256 i; i < positions.length; i++) { // Test variables - address cToken = positions[i].cToken; - address bToken = positions[i].bToken; + p.addr = positions[i].addr; + p.cToken = positions[i].cToken; + p.dToken = positions[i].dToken; + p.bToken = positions[i].bToken; // Bound fuzzed variables _ltv = bound(_ltv, 1, 60); - _cAmt = bound(_cAmt, assets.minCAmts(cToken), assets.maxCAmts(cToken)); + _cAmt = bound(_cAmt, assets.minCAmts(p.cToken), assets.maxCAmts(p.cToken)); // Fund owner with collateral - _fund(owner, cToken, _cAmt); + _fund(owner, p.cToken, _cAmt); - // Get permit - uint256 permitTimestamp = block.timestamp + 1000; - (uint8 v, bytes32 r, bytes32 s) = _getPermit(cToken, wallet, positions[i].addr, _cAmt, permitTimestamp); + // Expectations + feeData.maxFee = (_cAmt * PROTOCOL_FEE_RATE) / 1000; + (feeData.userSavings,) = _getExpectedClientAllocations(feeData.maxFee, CLIENT_TAKE_RATE); + feeData.protocolFee = feeData.maxFee - feeData.userSavings; // Pre-act balances - contractBalances.preBToken = IERC20(bToken).balanceOf(positions[i].addr); - ownerBalances.preCToken = IERC20(cToken).balanceOf(owner); + ownerBalances.preCToken = IERC20(p.cToken).balanceOf(owner); + positionBalances.preBToken = IERC20(p.bToken).balanceOf(p.addr); + positionBalances.preAToken = _getATokenBalance(p.addr, p.cToken); + positionBalances.preVDToken = _getVariableDebtTokenBalance(p.addr, p.dToken); + assertEq(positionBalances.preAToken, 0); + assertEq(positionBalances.preVDToken, 0); + + // Get permit + uint256 permitTimestamp = block.timestamp + 1000; + (permit.v, permit.r, permit.s) = _getPermit(p.cToken, wallet, positions[i].addr, _cAmt, permitTimestamp); // Act vm.recordLogs(); vm.prank(owner); IPosition(positions[i].addr).addWithPermit( - _cAmt, _ltv, 0, TEST_POOL_FEE, TEST_CLIENT, permitTimestamp, v, r, s + _cAmt, _ltv, 0, TEST_POOL_FEE, TEST_CLIENT, permitTimestamp, permit.v, permit.r, permit.s ); VmSafe.Log[] memory entries = vm.getRecordedLogs(); // Post-act balances - contractBalances.postBToken = IERC20(bToken).balanceOf(positions[i].addr); - ownerBalances.postCToken = IERC20(cToken).balanceOf(owner); + ownerBalances.postCToken = IERC20(p.cToken).balanceOf(owner); + positionBalances.postBToken = IERC20(p.bToken).balanceOf(p.addr); + positionBalances.postAToken = _getATokenBalance(p.addr, p.cToken); + positionBalances.postVDToken = _getVariableDebtTokenBalance(p.addr, p.dToken); + + // Retrieve bAmt and dAmt from Add event bytes memory addEvent = entries[entries.length - 1].data; + uint256 dAmt; uint256 bAmt; - assembly { - let startPos := sub(mload(addEvent), 32) - bAmt := mload(add(addEvent, add(0x20, startPos))) + dAmt := mload(add(addEvent, 0x40)) + bAmt := mload(add(addEvent, 0x60)) } // Assertions assertEq(ownerBalances.postCToken, ownerBalances.preCToken - _cAmt); - assertEq(contractBalances.postBToken, contractBalances.preBToken + bAmt); + assertEq(positionBalances.postBToken, positionBalances.preBToken + bAmt); + assertApproxEqAbs(positionBalances.postAToken, _cAmt - feeData.protocolFee, 1); + assertApproxEqAbs(positionBalances.postVDToken, dAmt, 1); - // Revert to snapshot + // Revert to snapshot to standardize chain state for each position vm.revertTo(id); } } diff --git a/test/integration/Position.close.t.sol b/test/integration/Position.close.t.sol index bf5ed4f..fd25b53 100644 --- a/test/integration/Position.close.t.sol +++ b/test/integration/Position.close.t.sol @@ -63,14 +63,9 @@ contract PositionCloseTest is Test, TokenUtils, DebtUtils { // Test Storage address public positionAddr; - uint256 public mainnetFork; address public owner = address(this); function setUp() public { - // Setup: use mainnet fork - mainnetFork = vm.createFork(vm.envString("RPC_URL")); - vm.selectFork(mainnetFork); - // Deploy assets assets = new Assets(); address[4] memory supportedAssets = assets.getSupported(); @@ -114,12 +109,6 @@ contract PositionCloseTest is Test, TokenUtils, DebtUtils { } } - /// @dev - // - The active fork should be the forked network created in the setup - function test_ActiveFork() public { - assertEq(vm.activeFork(), mainnetFork, "vm.activeFork() != mainnetFork"); - } - /// @dev // - Position contract's bToken balance should go to 0. // - Position contract's debt on Aave should go to 0. @@ -138,7 +127,7 @@ contract PositionCloseTest is Test, TokenUtils, DebtUtils { // Test variables address addr = positions[i].addr; - // Setup: open short position + // Setup: open position uint256 cAmt = assets.maxCAmts(positions[i].cToken); uint256 ltv = 50; _fund(owner, positions[i].cToken, cAmt); @@ -221,7 +210,7 @@ contract PositionCloseTest is Test, TokenUtils, DebtUtils { // Test variables address addr = positions[i].addr; - // Setup: open short position + // Setup: open position uint256 cAmt = assets.maxCAmts(positions[i].cToken); uint256 ltv = 50; _fund(owner, positions[i].cToken, cAmt); @@ -312,7 +301,7 @@ contract PositionCloseTest is Test, TokenUtils, DebtUtils { // Test variables address addr = positions[i].addr; - // Setup: open short position + // Setup: open position uint256 cAmt = assets.maxCAmts(positions[i].cToken); uint256 ltv = 50; _fund(owner, positions[i].cToken, cAmt); @@ -380,7 +369,7 @@ contract PositionCloseTest is Test, TokenUtils, DebtUtils { // Test variables address addr = positions[i].addr; - // Setup: open short position + // Setup: open position uint256 cAmt = assets.maxCAmts(positions[i].cToken); uint256 ltv = 50; _fund(owner, positions[i].cToken, cAmt); diff --git a/test/invariant/FeeCollector.netProtocolFees.t.sol b/test/invariant/FeeCollector.netProtocolFees.t.sol index 6e525f3..707073a 100644 --- a/test/invariant/FeeCollector.netProtocolFees.t.sol +++ b/test/invariant/FeeCollector.netProtocolFees.t.sol @@ -19,15 +19,10 @@ contract FeeCollectorNetProtocolFeesTest is Test, TokenUtils { // Test Storage address[] public supportedAssets; - uint256 public mainnetFork; address public owner = address(this); address public feeCollectorAddr; function setUp() public { - // Setup: use mainnet fork - mainnetFork = vm.createFork(vm.envString("RPC_URL")); - vm.selectFork(mainnetFork); - // Deploy assets assets = new Assets(); supportedAssets = assets.getSupported(); @@ -38,12 +33,6 @@ contract FeeCollectorNetProtocolFeesTest is Test, TokenUtils { feeCollectorAddr = address(feeCollector); } - /// @dev - // - The active fork should be the forked network created in the setup - function test_ActiveFork() public { - assertEq(vm.activeFork(), mainnetFork, "vm.activeFork() != mainnetFork"); - } - /// @dev // - Invariant: netProtocolFees = 1 - clientRate * sum(clientTakeRate_i * maxFee_i) // - Ensure netProtocolFees >= (1 - clientRate) * totalBal diff --git a/test/libraries/FeeLib.t.sol b/test/libraries/FeeLib.t.sol index c1631d6..3f7440d 100644 --- a/test/libraries/FeeLib.t.sol +++ b/test/libraries/FeeLib.t.sol @@ -26,14 +26,7 @@ contract FeeLibTest is Test, TokenUtils, FeeUtils { Assets public assets; address[] public supportedAssets; - // Test Storage - uint256 public mainnetFork; - function setUp() public { - // Setup: use mainnet fork - mainnetFork = vm.createFork(vm.envString("RPC_URL")); - vm.selectFork(mainnetFork); - // Deploy assets assets = new Assets(); supportedAssets = assets.getSupported(); @@ -47,12 +40,6 @@ contract FeeLibTest is Test, TokenUtils, FeeUtils { IFeeCollector(FEE_COLLECTOR).setClientRate(CLIENT_RATE); } - /// @dev - // - The active fork should be the forked network created in the setup - function test_ActiveFork() public { - assertEq(vm.activeFork(), mainnetFork, "vm.activeFork() != mainnetFork"); - } - /// @dev // - This contract's token balance should decrease by: (max fee - user savings). // - The balance of the FeeCollector should increase by: (max fee - user savings). diff --git a/test/services/AdminService.t.sol b/test/services/AdminService.t.sol index adcdd0a..774e57c 100644 --- a/test/services/AdminService.t.sol +++ b/test/services/AdminService.t.sol @@ -21,14 +21,9 @@ contract AdminServiceTest is Test, TokenUtils { // Test Storage address public positionAddr; - uint256 public mainnetFork; address public owner = address(this); function setUp() public { - // Setup: use mainnet fork - mainnetFork = vm.createFork(vm.envString("RPC_URL")); - vm.selectFork(mainnetFork); - // Deploy assets assets = new Assets(); address[4] memory supportedAssets = assets.getSupported(); @@ -41,12 +36,6 @@ contract AdminServiceTest is Test, TokenUtils { positionAddr = positionFactory.createPosition(supportedAssets[0], supportedAssets[3], supportedAssets[2]); } - /// @dev - // - The active fork should be the forked network created in the setup - function test_ActiveFork() public { - assertEq(vm.activeFork(), mainnetFork, "vm.activeFork() != mainnetFork"); - } - /// @dev // - The contract's native balance should decrease by the amount transferred. // - The owner's native balance should increase by the amount transferred. diff --git a/test/services/DebtService.t.sol b/test/services/DebtService.t.sol index 5772715..4e32f56 100644 --- a/test/services/DebtService.t.sol +++ b/test/services/DebtService.t.sol @@ -24,14 +24,9 @@ contract DebtServiceTest is Test, DebtUtils, TokenUtils { // Test Storage DebtServiceHarness[] public debtServices; address[4] public supportedAssets; - uint256 public mainnetFork; address public owner = address(this); function setUp() public { - // Setup: use mainnet fork - mainnetFork = vm.createFork(vm.envString("RPC_URL")); - vm.selectFork(mainnetFork); - assets = new Assets(); supportedAssets = assets.getSupported(); @@ -52,12 +47,6 @@ contract DebtServiceTest is Test, DebtUtils, TokenUtils { } } - /// @dev - // - The active fork should be the forked network created in the setup - function test_ActiveFork() public { - assertEq(vm.activeFork(), mainnetFork, "vm.activeFork() != mainnetFork"); - } - /// @dev // - cToken should have correct decimals. // - dToken should have correct decimals. @@ -444,14 +433,9 @@ contract DebtServicePermitTest is Test, DebtUtils, TokenUtils { DebtServiceHarness[] public debtServices; VmSafe.Wallet public wallet; address[4] public supportedAssets; - uint256 public mainnetFork; address public owner; function setUp() public { - // Setup: use mainnet fork - mainnetFork = vm.createFork(vm.envString("RPC_URL")); - vm.selectFork(mainnetFork); - // Deploy Assets contract assets = new Assets(); supportedAssets = assets.getSupported(); diff --git a/test/services/SwapService.t.sol b/test/services/SwapService.t.sol index 245789e..d4af438 100644 --- a/test/services/SwapService.t.sol +++ b/test/services/SwapService.t.sol @@ -20,13 +20,8 @@ contract SwapServiceTest is Test, TokenUtils { // Test Storage address[4] public supportedAssets; address swapServiceAddr; - uint256 public mainnetFork; function setUp() public { - // Setup: use mainnet fork - mainnetFork = vm.createFork(vm.envString("RPC_URL")); - vm.selectFork(mainnetFork); - assets = new Assets(); supportedAssets = assets.getSupported(); @@ -34,12 +29,6 @@ contract SwapServiceTest is Test, TokenUtils { swapServiceAddr = address(swapService); } - /// @dev - // - The active fork should be the forked network created in the setup - function test_ActiveFork() public { - assertEq(vm.activeFork(), mainnetFork, "vm.activeFork() != mainnetFork"); - } - /// @dev // - The swap service's input token balance should decrease by the amount inputted. // - The swap service's output token balance should increase by the amount outputted.