Skip to content

Commit

Permalink
fix tests for Renzo
Browse files Browse the repository at this point in the history
  • Loading branch information
GuillaumeNervoXS committed Jun 11, 2024
1 parent 927a3da commit 03b1a5e
Show file tree
Hide file tree
Showing 4 changed files with 247 additions and 19 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.17;

import "borrow-staked/swapper/LevSwapper/morpho/PendleLevSwapperMorpho.sol";

/// @author Angle Labs, Inc.
/// @notice PT ezETH leverage swapper with maturity Dec 24
contract PendleLevSwapperMorphoEzETHDec24 is PendleLevSwapperMorpho {
constructor(
ICoreBorrow _core,
IUniswapV3Router _uniV3Router,
address _aggregator,
IAngleRouterSidechain _angleRouter,
IMorphoBase _morpho
) PendleLevSwapperMorpho(_core, _uniV3Router, _aggregator, _angleRouter, _morpho) {}

/// @inheritdoc BaseLevSwapper
function angleStaker() public pure override returns (IBorrowStaker) {
return IBorrowStaker(address(0));
}

/// @inheritdoc PendleLevSwapperMorpho
function PT() public pure override returns (IERC20) {
return IERC20(0xf7906F274c174A52d444175729E3fa98f9bde285);
}

/// @inheritdoc PendleLevSwapperMorpho
function SY() public pure override returns (IStandardizedYield) {
return IStandardizedYield(0x22E12A50e3ca49FB183074235cB1db84Fe4C716D);
}

/// @inheritdoc PendleLevSwapperMorpho
function YT() public pure override returns (IPYieldTokenV2) {
return IPYieldTokenV2(0x7749F5Ed1e356EDc63D469c2fcaC9adEB56d1C2b);
}

/// @inheritdoc PendleLevSwapperMorpho
function market() public pure override returns (IPMarketV3) {
return IPMarketV3(0xD8F12bCDE578c653014F27379a6114F67F0e445f);
}

/// @inheritdoc PendleLevSwapperMorpho
function collateral() public pure override returns (IERC20) {
return IERC20(0xbf5495Efe5DB9ce00f80364C8B423567e58d2110);
}
}
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
"test:unit": "forge test -vvv --gas-report --match-path \"test/unit/**/*.sol\"",
"test:invariant": "forge test -vvv --gas-report --match-path \"test/invariant/**/*.sol\"",
"test:fuzz": "forge test -vvv --gas-report --match-path \"test/fuzz/**/*.sol\"",
"test": "FOUNDRY_PROFILE=dev forge test -vvvv",
"test": "FOUNDRY_PROFILE=dev forge test -vvv",
"slither": "slither .",
"lcov:clean": "lcov --remove lcov.info -o lcov.info 'test/**' 'scripts/**' 'contracts/transmuter/configs/**' 'contracts/utils/**'",
"lcov:generate-html": "genhtml lcov.info --output=coverage",
Expand Down
36 changes: 18 additions & 18 deletions scripts/foundry/mainnet/morpho/MorphoDeployMarket.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import { IOracle as IMorphoOracle } from "morpho-blue/interfaces/IOracle.sol";
import "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol";
import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
import { MorphoFeedPTweETH } from "borrow/oracle/morpho/mainnet/MorphoFeedPTweETH.sol";
import { MorphoFeedPTweETHDec24 } from "borrow/oracle/morpho/mainnet/MorphoFeedPTweETHDec24.sol";
// import { MorphoFeedPTweETHDec24 } from "borrow/oracle/morpho/mainnet/MorphoFeedPTweETHDec24.sol";
import { IAccessControlManager } from "borrow/interfaces/IAccessControlManager.sol";
import "borrow-staked/mock/MockCoreBorrow.sol";
import "borrow-staked/interfaces/external/morpho/IMorphoChainlinkOracleV2Factory.sol";
Expand All @@ -43,23 +43,23 @@ contract MorphoDeployMarket is Script, MainnetConstants, StdCheats, StdAssertion
address oracle;
bytes32 salt;

// PT weETH market
address priceFeed = address(
new MorphoFeedPTweETHDec24(IAccessControlManager(address(coreBorrow)), _MAX_IMPLIED_RATE, _TWAP_DURATION)
);
oracle = IMorphoChainlinkOracleV2Factory(MORPHO_ORACLE_FACTORY).createMorphoChainlinkOracleV2(
address(0),
1,
address(priceFeed),
address(WEETH_USD_ORACLE),
IERC20Metadata(PTWeETH).decimals(),
address(0),
1,
address(0),
address(0),
IERC20Metadata(USDA).decimals(),
salt
);
// // PT weETH market
// address priceFeed = address(
// new MorphoFeedPTweETHDec24(IAccessControlManager(address(coreBorrow)), _MAX_IMPLIED_RATE, _TWAP_DURATION)
// );
// oracle = IMorphoChainlinkOracleV2Factory(MORPHO_ORACLE_FACTORY).createMorphoChainlinkOracleV2(
// address(0),
// 1,
// address(priceFeed),
// address(WEETH_USD_ORACLE),
// IERC20Metadata(PTWeETH).decimals(),
// address(0),
// 1,
// address(0),
// address(0),
// IERC20Metadata(USDA).decimals(),
// salt
// );

// // GTUSDCPrime market
// oracle = IMorphoChainlinkOracleV2Factory(MORPHO_ORACLE_FACTORY).createMorphoChainlinkOracleV2(
Expand Down
182 changes: 182 additions & 0 deletions test/foundry/swapper/morpho/PendleLevSwapperMorphoEzETHDec24Test.t.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.17;

import "../../BaseTest.test.sol";
import "borrow-staked/interfaces/IBorrowStaker.sol";
import "borrow/interfaces/ICoreBorrow.sol";
import "borrow-staked/mock/MockTokenPermit.sol";
import { SwapType, BaseLevSwapper, PendleLevSwapperMorphoEzETHDec24, PendleLevSwapperMorpho, Swapper, IUniswapV3Router, IAngleRouterSidechain } from "borrow-staked/swapper/LevSwapper/morpho/implementations/PendleLevSwapperMorphoEzETHDec24.sol";
import { IMorphoBase } from "morpho-blue/interfaces/IMorpho.sol";

contract PendleLevSwapperMorphoEzETHDec24Test is BaseTest {
using stdStorage for StdStorage;
using SafeERC20 for IERC20;

address internal constant _ONE_INCH = 0x111111125421cA6dc452d289314280a0f8842A65;
IUniswapV3Router internal constant _UNI_V3_ROUTER = IUniswapV3Router(0xE592427A0AEce92De3Edee1F18E0157C05861564);
IAngleRouterSidechain internal constant _ANGLE_ROUTER =
IAngleRouterSidechain(address(uint160(uint256(keccak256(abi.encodePacked("_fakeAngleRouter"))))));

uint256 internal constant _BPS = 10000;
IERC20 constant WETH = IERC20(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2);
IMorphoBase constant MORPHO = IMorphoBase(0xBBBBBbbBBb9cC5e90e3b3Af64bdAF62C37EEFFCb);
PendleLevSwapperMorpho public swapper;
IERC20 public asset;
IERC20 public collateral;

uint256 public constant DEPOSIT_LENGTH = 10;
uint256 public constant WITHDRAW_LENGTH = 10;

function setUp() public override {
super.setUp();

_ethereum = vm.createFork(vm.envString("ETH_NODE_URI_MAINNET"), 20062045);
vm.selectFork(_ethereum);

// reset coreBorrow because the `makePersistent()` doens't work on my end
coreBorrow = new MockCoreBorrow();
coreBorrow.toggleGuardian(_GUARDIAN);
coreBorrow.toggleGovernor(_GOVERNOR);

swapper = new PendleLevSwapperMorphoEzETHDec24(coreBorrow, _UNI_V3_ROUTER, _ONE_INCH, _ANGLE_ROUTER, MORPHO);
asset = swapper.PT();
collateral = swapper.collateral();

vm.startPrank(_alice);
asset.approve(address(swapper), type(uint256).max);
collateral.approve(address(swapper), type(uint256).max);
vm.stopPrank();
}

function test_Leverage_NoSwap_Success(uint256 amount) public {
amount = bound(amount, 10 ** 15, 10 ** 20);
deal(address(collateral), address(_alice), amount);

vm.startPrank(_alice);

// intermediary variables
bytes[] memory oneInchData = new bytes[](0);

uint256 minAmountOut = amount / 2;
bytes memory addData;
bytes memory swapData = abi.encode(oneInchData, addData);
bytes memory leverageData = abi.encode(true, _alice, swapData);
bytes memory data = abi.encode(address(0), 0, SwapType.Leverage, leverageData);

// we first need to send the tokens before hand, you should always use the swapper
// in another tx to not loose your funds by front running
collateral.transfer(address(swapper), amount);
swapper.swap(IERC20(address(collateral)), IERC20(address(asset)), _alice, 0, amount, data);

vm.stopPrank();

assertEq(collateral.balanceOf(_alice), 0);
assertEq(collateral.balanceOf(address(swapper)), 0);
assertEq(asset.balanceOf(address(swapper)), 0);
assertGe(asset.balanceOf(_alice), minAmountOut);
}

function test_Deleverage_NoSwap_Success(uint256 amount) public {
amount = bound(amount, 10 ** 15, 10 ** 20);
deal(address(asset), address(_alice), amount);

vm.startPrank(_alice);

// intermediary variables
bytes[] memory oneInchData = new bytes[](0);

uint256 minAmountOut = amount / 2;
IERC20[] memory sweepTokens = new IERC20[](0);
bytes memory removeData = abi.encode(uint256(minAmountOut));
bytes memory swapData = abi.encode(0, amount, sweepTokens, oneInchData, removeData);
bytes memory leverageData = abi.encode(false, _alice, swapData);
bytes memory data = abi.encode(address(0), 0, SwapType.Leverage, leverageData);

// we first need to send the tokens before hand, you should always use the swapper
// in another tx to not loose your funds by front running
asset.transfer(address(swapper), amount);
swapper.swap(IERC20(address(asset)), IERC20(address(collateral)), _alice, 0, amount, data);

vm.stopPrank();

assertGe(collateral.balanceOf(_alice), minAmountOut);
assertEq(collateral.balanceOf(address(swapper)), 0);
assertEq(asset.balanceOf(address(swapper)), 0);
assertEq(asset.balanceOf(_alice), 0);
}

function test_Leverage_Swap_Success() public {
uint256 amount = 10 ether;
deal(address(WETH), address(_alice), amount);

vm.startPrank(_alice);

// intermediary variables
bytes[] memory oneInchData = new bytes[](1);
// swap WETH for ezETH
oneInchData[0] = abi.encode(
address(WETH),
0,
hex"83800a8e000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000000000000000000000000000008ac7230489e8000000000000000000000000000000000000000000000000000089a0435b8d704154280000000000000000000000be80225f09645f172b079394312220637c440a63f737be46"
);

uint256 minAmountOut = amount / 2;
bytes memory addData;
bytes memory swapData = abi.encode(oneInchData, addData);
bytes memory leverageData = abi.encode(true, _alice, swapData);
bytes memory data = abi.encode(address(0), 0, SwapType.Leverage, leverageData);

// we first need to send the tokens before hand, you should always use the swapper
// in another tx to not loose your funds by front running
WETH.transfer(address(swapper), amount);
swapper.swap(IERC20(address(WETH)), IERC20(address(asset)), _alice, 0, amount, data);

vm.stopPrank();

assertEq(WETH.balanceOf(_alice), 0);
assertEq(WETH.balanceOf(address(swapper)), 0);
assertEq(collateral.balanceOf(_alice), 0);
assertEq(collateral.balanceOf(address(swapper)), 0);
assertEq(asset.balanceOf(address(swapper)), 0);
assertGe(asset.balanceOf(_alice), minAmountOut);
}

function test_Deleverage_Swap_Success() public {
uint256 eps = 2 ether;
uint256 amount = 10 ether;
deal(address(asset), address(_alice), amount + eps);

vm.startPrank(_alice);

// intermediary variables
bytes[] memory oneInchData = new bytes[](1);
// swap weETH for WETH
oneInchData[0] = abi.encode(
address(collateral),
0,
hex"07ed2379000000000000000000000000e37e799d5077682fa0a244d46e5649f71457bd09000000000000000000000000bf5495efe5db9ce00f80364c8b423567e58d2110000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000e37e799d5077682fa0a244d46e5649f71457bd090000000000000000000000005991a2df15a8f6a256d3ec51e99254cd3fb576a90000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000008924bd0fa19555130000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000001130000000000000000000000000000000000000000f50000c700009900004f00a0fbb7cd0600596192bb6e41802428ac943d2f1476c1af25cc0e000000000000000000000659bf5495efe5db9ce00f80364c8b423567e58d2110c02aaa39b223fe8d0a0e5c4f27ead9083c756cc200a0f2fa6b66c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000000000000000000000000000008a875f4b4389e95400000000000000000005058c6b58c80e80a06c4eca27c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2111111125421ca6dc452d289314280a0f8842a650020d6bdbf78c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2111111125421ca6dc452d289314280a0f8842a6500000000000000000000000000f737be46"
);

uint256 minAmountOut = amount / 2;
IERC20[] memory sweepTokens = new IERC20[](1);
sweepTokens[0] = collateral;
bytes memory removeData = abi.encode(uint256(minAmountOut));
bytes memory swapData = abi.encode(0, amount + eps, sweepTokens, oneInchData, removeData);
bytes memory leverageData = abi.encode(false, _alice, swapData);
bytes memory data = abi.encode(address(0), 0, SwapType.Leverage, leverageData);

// we first need to send the tokens before hand, you should always use the swapper
// in another tx to not loose your funds by front running
asset.transfer(address(swapper), amount + eps);
swapper.swap(IERC20(address(asset)), IERC20(address(WETH)), _alice, 0, amount, data);

vm.stopPrank();

assertGe(WETH.balanceOf(_alice), (amount * 99) / 100);
assertEq(WETH.balanceOf(address(swapper)), 0);
assertGt(collateral.balanceOf(_alice), 0);
assertEq(collateral.balanceOf(address(swapper)), 0);
assertEq(asset.balanceOf(address(swapper)), 0);
assertEq(asset.balanceOf(_alice), 0);
}
}

0 comments on commit 03b1a5e

Please sign in to comment.