diff --git a/src/factory/MarketFactory.sol b/src/factory/MarketFactory.sol new file mode 100644 index 0000000..794f576 --- /dev/null +++ b/src/factory/MarketFactory.sol @@ -0,0 +1,122 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +import "src/Market.sol"; + +contract MarketFactory { + IDolaBorrowingRights public constant DBR = IDolaBorrowingRights(0xAD038Eb671c44b853887A7E32528FaB35dC5D710); + uint256 public constant INITIAL_COLLATERAL_FACTOR_BPS = 5000; + uint256 public constant INITIAL_REPLENISHMENT_INCENTIVE_BPS = 5000; + uint256 public constant INITIAL_LIQUIDATION_INCENTIVE_BPS = 100; + IOracle public oracle; + address public gov; + address public fed; + address public pauseGuardian; + address public pendingGov; + + mapping(address => bool) public isFromFactory; + + event NewMarket(address indexed collateral, address indexed market); + event NewOracle(address indexed oldOracle, address indexed newOracle); + event NewFed(address indexed oldFed, address indexed newFed); + event NewPauseGuardian(address indexed oldPauseGuardian, address indexed newPauseGuardian); + event NewPendingGov(address indexed oldPendingGov, address indexed newPendingGov); + event NewGov(address indexed oldGov, address indexed newGov); + + constructor(address _gov, address _oracle, address _fed, address _pauseGuardian) { + gov = _gov; + oracle = IOracle(_oracle); + fed = _fed; + pauseGuardian = _pauseGuardian; + + } + + modifier onlyGov() { + require(msg.sender == gov, "Only gov"); + _; + } + + /** + * @notice Deploy a new market contract with preset values. + * @dev This market then has to be approved and initialized by on-chain vote after deployment. + * @param collateral collateral for the market + * @param escrowImpl implementation of the escrow contract + * @param callbackOnDeposit whether to callback on deposit + */ + function deployMarket(address collateral, address escrowImpl, bool callbackOnDeposit) + external + returns (address market) + { + market = address( + new Market( + gov, + fed, + pauseGuardian, + escrowImpl, + DBR, + IERC20(collateral), + oracle, + INITIAL_COLLATERAL_FACTOR_BPS, + INITIAL_REPLENISHMENT_INCENTIVE_BPS, + INITIAL_LIQUIDATION_INCENTIVE_BPS, + callbackOnDeposit + ) + ); + isFromFactory[market] = true; + emit NewMarket(collateral, market); + } + + // Admin functions + + /** + * @notice Set a new pending gov. The new pending gov then has to call `acceptGov`. + * @dev Can only be called by the gov. + * @param _pendingGov address of the new pending gov + */ + function setPendingGov(address _pendingGov) external onlyGov { + emit NewPendingGov(pendingGov, _pendingGov); + pendingGov = _pendingGov; + + } + + /** + * @notice Accept the new pending gov. + * @dev Can only be called by the pending gov. + */ + function acceptGov() external { + require(msg.sender == pendingGov, "Only pending gov"); + emit NewGov(gov, pendingGov); + gov = pendingGov; + pendingGov = address(0); + } + + /** + * @notice Set a new oracle. + * @dev Can only be called by the gov. + * @param _oracle address of the new oracle + */ + function setOracle(address _oracle) external onlyGov { + emit NewOracle(address(oracle), _oracle); + oracle = IOracle(_oracle); + } + + /** + * @notice Set a new fed. + * @dev Can only be called by the gov. + * @param _fed address of the new fed + */ + function setFed(address _fed) external onlyGov { + emit NewFed(fed, _fed); + fed = _fed; + } + + /** + * @notice Set a new pause guardian. + * @dev Can only be called by the gov. + * @param _pauseGuardian address of the new pause guardian + */ + function setPauseGuardian(address _pauseGuardian) external onlyGov { + emit NewPauseGuardian(pauseGuardian, _pauseGuardian); + pauseGuardian = _pauseGuardian; + } +} diff --git a/src/factory/PTUSDeFeedSwitchFactory.sol b/src/factory/PTUSDeFeedSwitchFactory.sol new file mode 100644 index 0000000..1a4d3d1 --- /dev/null +++ b/src/factory/PTUSDeFeedSwitchFactory.sol @@ -0,0 +1,125 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +import {FeedSwitch} from "src/util/FeedSwitch.sol"; +import {USDeNavBeforeMaturityFeed} from "src/feeds/USDeNavBeforeMaturityFeed.sol"; +import {NavBeforeMaturityFeed} from "src/feeds/NavBeforeMaturityFeed.sol"; +import {PendleNAVFeed} from "src/feeds/PendleNAVFeed.sol"; + +contract PTUSDeFeedSwitchFactory { + address public constant USDeWrapperFeed = 0xB3C1D801A02d88adC96A294123c2Daa382345058; + address public constant sUSDeWrapper = 0xD723a0910e261de49A90779d38A94aFaAA028F15; + address public constant sUSDe = 0x9D39A5DE30e57443BfF2A8307A4256c8797A3497; + address public gov; + uint256 public timelockPeriod; + address public guardian; + address public pendingGov; + + mapping(address => bool) public isFromFactory; + + event NewFeedSwitch( + address indexed pendlePT, address indexed feedSwitch, address indexed navFeed, address beforeMaturityFeed, address afterMaturityFeed + ); + event NewPendingGov(address indexed oldPendingGov, address indexed newPendingGov); + event NewGov(address indexed oldGov, address indexed newGov); + event NewTimelockPeriod(uint256 oldTimelockPeriod, uint256 newTimelockPeriod); + event NewGuardian(address indexed oldGuardian, address indexed newGuardian); + + constructor(address _gov, address _guardian, uint256 _timelockPeriod) { + gov = _gov; + guardian = _guardian; + timelockPeriod = _timelockPeriod; + } + + modifier onlyGov() { + require(msg.sender == gov, "Only gov"); + _; + } + + /** + * @notice Deploy a new PT USDe feed. + * @dev The deployed feed has to be set in the oracle for the specific market via on-chain vote. + * @param pendlePT address of the Pendle PT + * @param baseDiscount base discount for the feed + */ + function deployUSDeFeed(address pendlePT, uint256 baseDiscount) external returns (address feedSwitch) { + PendleNAVFeed navFeed = new PendleNAVFeed(pendlePT, baseDiscount); + + NavBeforeMaturityFeed beforeMaturityFeed = new NavBeforeMaturityFeed(USDeWrapperFeed, address(navFeed)); + + feedSwitch = address( + new FeedSwitch( + address(navFeed), address(beforeMaturityFeed), USDeWrapperFeed, timelockPeriod, pendlePT, guardian + ) + ); + isFromFactory[feedSwitch] = true; + + emit NewFeedSwitch(pendlePT, feedSwitch, address(navFeed), address(beforeMaturityFeed), USDeWrapperFeed); + } + + /** + * @notice Deploy a new PT sUSDe feed. + * @dev The deployed feed has to be set in the oracle for the specific market via on-chain vote. + * @param pendlePT address of the Pendle PT + * @param baseDiscount base discount for the feed + */ + function deploySUSDeFeed(address pendlePT, uint256 baseDiscount) external returns (address feedSwitch) { + PendleNAVFeed navFeed = new PendleNAVFeed(pendlePT, baseDiscount); + + USDeNavBeforeMaturityFeed beforeMaturityFeed = + new USDeNavBeforeMaturityFeed(sUSDeWrapper, sUSDe, address(navFeed)); // USDeBeforeMaturityFeed: USDe/USD Feed using sUSDe Chainlink feed and sUSDe/USDe rate and NAV + + feedSwitch = address( + new FeedSwitch( + address(navFeed), address(beforeMaturityFeed), USDeWrapperFeed, timelockPeriod, pendlePT, guardian + ) + ); + + isFromFactory[feedSwitch] = true; + + emit NewFeedSwitch(pendlePT, feedSwitch, address(navFeed), address(beforeMaturityFeed), USDeWrapperFeed); + } + + // Admin functions + + /** + * @notice Set a new pending gov. The new pending gov then has to call `acceptGov`. + * @dev Can only be called by the gov. + * @param _pendingGov address of the new pending gov + */ + function setPendingGov(address _pendingGov) external onlyGov { + emit NewPendingGov(pendingGov, _pendingGov); + pendingGov = _pendingGov; + } + + /** + * @notice Accept the new pending gov. + * @dev Can only be called by the pending gov. + */ + function acceptGov() external { + require(msg.sender == pendingGov, "Only pending gov"); + emit NewGov(gov, pendingGov); + gov = pendingGov; + pendingGov = address(0); + } + + /** + * @notice Set a new timelock period for all deployed feeds. + * @dev Can only be called by the gov. + * @param _timelockPeriod new timelock period + */ + function setTimelockPeriod(uint256 _timelockPeriod) external onlyGov { + emit NewTimelockPeriod(timelockPeriod, _timelockPeriod); + timelockPeriod = _timelockPeriod; + } + + /** + * @notice Set a new guardian. + * @dev Can only be called by the gov. + * @param _guardian address of the new guardian + */ + function setGuardian(address _guardian) external onlyGov { + emit NewGuardian(guardian, _guardian); + guardian = _guardian; + } +} diff --git a/test/factoryTests/FeedSwitchFactoryTest.t.sol b/test/factoryTests/FeedSwitchFactoryTest.t.sol new file mode 100644 index 0000000..f03b601 --- /dev/null +++ b/test/factoryTests/FeedSwitchFactoryTest.t.sol @@ -0,0 +1,156 @@ +pragma solidity ^0.8.20; + + +import "forge-std/Test.sol"; +import "src/factory/PTUSDeFeedSwitchFactory.sol"; +import {ConfigAddr} from "test/ConfigAddr.sol"; +contract PTUSDeFeedSwitchFactoryTest is Test, ConfigAddr { + + PTUSDeFeedSwitchFactory factory; + uint256 timelockPeriod = 18 hours; + address pendlePT = address(0xe6A934089BBEe34F832060CE98848359883749B3); // PT sUSDe 24 Nov 25 + address pendlePTsUSDe = address(0x62C6E813b9589C3631Ba0Cdb013acdB8544038B7); // PT USDe 27 Nov 25 + address guardian = address(0x4b6c63E6a94ef26E2dF60b89372db2d8e211F1B7); + address usdeWrappedFeed = address(0xB3C1D801A02d88adC96A294123c2Daa382345058); // USDe/USD wrapper + uint256 baseDiscount = 0.2 ether; + address sUSDeWrapper = address(0xD723a0910e261de49A90779d38A94aFaAA028F15); + address sUSDe = address(0x9D39A5DE30e57443BfF2A8307A4256c8797A3497); + function setUp() public { + string memory rpcUrl = vm.rpcUrl('mainnet'); + vm.createSelectFork(rpcUrl); + + factory = new PTUSDeFeedSwitchFactory(gov, guardian, timelockPeriod); + } + + function test_deployment() public view { + assertEq(gov, factory.gov()); + assertEq(timelockPeriod, factory.timelockPeriod()); + assertEq(guardian, factory.guardian()); + } + + function test_PT_USDe_deployment() public { + address factoryFeed = factory.deployUSDeFeed(pendlePT, baseDiscount); + assertTrue(factory.isFromFactory(factoryFeed)); + + address navFeed = address(new PendleNAVFeed(pendlePT, baseDiscount)); + address beforeMaturityFeed = address(new NavBeforeMaturityFeed( + address(usdeWrappedFeed), + address(navFeed) + )); + + FeedSwitch feedSwitch = new FeedSwitch( + navFeed, + beforeMaturityFeed, + usdeWrappedFeed, + 18 hours, + pendlePT, + guardian + ); + + FeedSwitch feed = FeedSwitch(factoryFeed); + + assertEq(PendleNAVFeed(address(feed.initialFeed())).PT(), PendleNAVFeed(address(feedSwitch.initialFeed())).PT()); + assertEq(PendleNAVFeed(address(feed.initialFeed())).maturity(), PendleNAVFeed(address(feedSwitch.initialFeed())).maturity()); + assertEq(PendleNAVFeed(address(feed.initialFeed())).baseDiscountPerYear(), PendleNAVFeed(address(feedSwitch.initialFeed())).baseDiscountPerYear()); + assertEq(address(NavBeforeMaturityFeed(address(feed.beforeMaturityFeed())).feed()), address(NavBeforeMaturityFeed(address(feedSwitch.beforeMaturityFeed())).feed())); + assertEq(address(NavBeforeMaturityFeed(address(feed.beforeMaturityFeed())).navFeed()),address(feed.initialFeed())); + assertEq(address(feed.afterMaturityFeed()), address(feedSwitch.afterMaturityFeed())); + assertEq(feed.timelockPeriod(), feedSwitch.timelockPeriod()); + assertEq(feed.guardian(), feedSwitch.guardian()); + } + + function test_PT_sUSDe_deployment() public { + address factoryFeed = factory.deploySUSDeFeed(pendlePTsUSDe, baseDiscount); + assertTrue(factory.isFromFactory(factoryFeed)); + + address navFeed = address(new PendleNAVFeed(pendlePTsUSDe, baseDiscount)); + address beforeMaturityFeed = address(new USDeNavBeforeMaturityFeed( + sUSDeWrapper, + sUSDe, + address(navFeed) + )); + FeedSwitch feedSwitch = new FeedSwitch( + navFeed, + beforeMaturityFeed, + usdeWrappedFeed, + 18 hours, + pendlePTsUSDe, + guardian + ); + + FeedSwitch feed = FeedSwitch(factoryFeed); + + assertEq(PendleNAVFeed(address(feed.initialFeed())).PT(), PendleNAVFeed(address(feedSwitch.initialFeed())).PT()); + assertEq(PendleNAVFeed(address(feed.initialFeed())).maturity(), PendleNAVFeed(address(feedSwitch.initialFeed())).maturity()); + assertEq(PendleNAVFeed(address(feed.initialFeed())).baseDiscountPerYear(), PendleNAVFeed(address(feedSwitch.initialFeed())).baseDiscountPerYear()); + assertEq(address(USDeNavBeforeMaturityFeed(address(feed.beforeMaturityFeed())).sUSDe()), address(USDeNavBeforeMaturityFeed(address(feedSwitch.beforeMaturityFeed())).sUSDe())); + assertEq(address(USDeNavBeforeMaturityFeed(address(feed.beforeMaturityFeed())).sUSDeFeed()), address(USDeNavBeforeMaturityFeed(address(feedSwitch.beforeMaturityFeed())).sUSDeFeed())); + assertEq(address(USDeNavBeforeMaturityFeed(address(feed.beforeMaturityFeed())).navFeed()),address(feed.initialFeed())); + assertEq(address(feed.afterMaturityFeed()), address(feedSwitch.afterMaturityFeed())); + assertEq(feed.timelockPeriod(), feedSwitch.timelockPeriod()); + assertEq(feed.guardian(), feedSwitch.guardian()); + } + + + function test_setPendingGov() public { + address newGov = address(0x123); + vm.prank(gov); + factory.setPendingGov(newGov); + assertEq(factory.pendingGov(), newGov); + } + + function test_fail_setPendingGov_if_not_gov() public { + address newGov = address(0x123); + vm.expectRevert("Only gov"); + factory.setPendingGov(newGov); + } + + function test_acceptGov() public { + address newGov = address(0x123); + vm.prank(gov); + factory.setPendingGov(newGov); + assertEq(factory.pendingGov(), newGov); + + vm.prank(newGov); + factory.acceptGov(); + assertEq(factory.gov(), newGov); + assertEq(factory.pendingGov(), address(0)); + } + + function test_fail_acceptGov_if_not_gov() public { + address newGov = address(0x123); + vm.prank(gov); + factory.setPendingGov(newGov); + assertEq(factory.pendingGov(), newGov); + + vm.expectRevert("Only pending gov"); + factory.acceptGov(); + } + + + function test_setTimelockPeriod() public { + uint256 newTimelockPeriod = 1 days; + vm.prank(gov); + factory.setTimelockPeriod(newTimelockPeriod); + assertEq(factory.timelockPeriod(), newTimelockPeriod); + } + + function test_fail_setTimelockPeriod_if_not_gov() public { + uint256 newTimelockPeriod = 1 days; + vm.expectRevert("Only gov"); + factory.setTimelockPeriod(newTimelockPeriod); + } + + function test_setGuardian() public { + address newGuardian = address(0x123); + vm.prank(gov); + factory.setGuardian(newGuardian); + assertEq(factory.guardian(), newGuardian); + } + + function test_fail_setGuardian_if_not_gov() public { + address newGuardian = address(0x123); + vm.expectRevert("Only gov"); + factory.setGuardian(newGuardian); + } +} \ No newline at end of file diff --git a/test/factoryTests/MarketFactoryTest.t.sol b/test/factoryTests/MarketFactoryTest.t.sol new file mode 100644 index 0000000..d705bac --- /dev/null +++ b/test/factoryTests/MarketFactoryTest.t.sol @@ -0,0 +1,129 @@ +pragma solidity ^0.8.20; + + +import "forge-std/Test.sol"; +import "src/factory/MarketFactory.sol"; +import {ConfigAddr} from "test/ConfigAddr.sol"; +contract MarketFactoryTest is Test, ConfigAddr { + + MarketFactory factory; + address pendlePT = address(0xe6A934089BBEe34F832060CE98848359883749B3); // PT sUSDe 24 Nov 25 + function setUp() public { + string memory rpcUrl = vm.rpcUrl('mainnet'); + vm.createSelectFork(rpcUrl); + + factory = new MarketFactory(gov, oracleAddr, fedAddr, pauseGuardian); + } + + function test_deployment() public view { + assertEq(gov, factory.gov()); + assertEq(oracleAddr, address(factory.oracle())); + assertEq(fedAddr, factory.fed()); + assertEq(pauseGuardian, factory.pauseGuardian()); + } + + function test_market_deployment() public { + address factoryMarket = factory.deployMarket(pendlePT, simpleERC20EscrowAddr, false); + assertTrue(factory.isFromFactory(factoryMarket)); + + Market pendleMarket = new Market( + gov, + fedAddr, + pauseGuardian, + simpleERC20EscrowAddr, + IDolaBorrowingRights(address(dbrAddr)), + IERC20(address(pendlePT)), + IOracle(address(oracleAddr)), + 5000, + 5000, + 100, + false + ); + Market market = Market(factoryMarket); + + assertEq(address(market.collateral()),address(pendleMarket.collateral())); + assertEq(market.gov(),pendleMarket.gov()); + assertEq(market.lender(),pendleMarket.lender()); + assertEq(market.pauseGuardian(),pendleMarket.pauseGuardian()); + assertEq(market.escrowImplementation(), pendleMarket.escrowImplementation()); + assertEq(address(market.dbr()),address(pendleMarket.dbr())); + assertEq(address(market.oracle()),address(pendleMarket.oracle())); + assertEq(market.collateralFactorBps(),pendleMarket.collateralFactorBps()); + assertEq(market.replenishmentIncentiveBps(),pendleMarket.replenishmentIncentiveBps()); + assertEq(market.liquidationFactorBps(),pendleMarket.liquidationFactorBps()); + } + + function test_setPendingGov() public { + address newGov = address(0x123); + vm.prank(gov); + factory.setPendingGov(newGov); + assertEq(factory.pendingGov(), newGov); + } + + function test_fail_setPendingGov_if_not_gov() public { + address newGov = address(0x123); + vm.expectRevert("Only gov"); + factory.setPendingGov(newGov); + } + + function test_acceptGov() public { + address newGov = address(0x123); + vm.prank(gov); + factory.setPendingGov(newGov); + assertEq(factory.pendingGov(), newGov); + + vm.prank(newGov); + factory.acceptGov(); + assertEq(factory.gov(), newGov); + assertEq(factory.pendingGov(), address(0)); + } + + function test_fail_acceptGov_if_not_gov() public { + address newGov = address(0x123); + vm.prank(gov); + factory.setPendingGov(newGov); + assertEq(factory.pendingGov(), newGov); + + vm.expectRevert("Only pending gov"); + factory.acceptGov(); + } + + function test_setOracle() public { + address newOracle = address(0x123); + vm.prank(gov); + factory.setOracle(newOracle); + assertEq(address(factory.oracle()), newOracle); + } + + function test_fail_setOracle_if_not_gov() public { + address newOracle = address(0x123); + vm.expectRevert("Only gov"); + factory.setOracle(newOracle); + } + + function test_setFed() public { + address newFed = address(0x123); + vm.prank(gov); + factory.setFed(newFed); + assertEq(factory.fed(), newFed); + } + + function test_fail_setFed_if_not_gov() public { + address newFed = address(0x123); + vm.expectRevert("Only gov"); + factory.setFed(newFed); + } + + function test_setPauseGuardian() public { + address newGuardian = address(0x123); + vm.prank(gov); + factory.setPauseGuardian(newGuardian); + assertEq(factory.pauseGuardian(), newGuardian); + } + + function test_fail_setGuardian_if_not_gov() public { + address newGuardian = address(0x123); + vm.expectRevert("Only gov"); + factory.setPauseGuardian(newGuardian); + } +} \ No newline at end of file diff --git a/test/marketForkTests/PendlePTsUSDe27Nov25MarketForkTest.t.sol b/test/marketForkTests/PendlePTsUSDe27Nov25MarketForkTest.t.sol new file mode 100644 index 0000000..2ab0a0c --- /dev/null +++ b/test/marketForkTests/PendlePTsUSDe27Nov25MarketForkTest.t.sol @@ -0,0 +1,94 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.13; + +import "forge-std/Test.sol"; +import "./MarketBaseForkTest.sol"; +import {USDeNavBeforeMaturityFeed} from "src/feeds/USDeNavBeforeMaturityFeed.sol"; +import {ChainlinkBasePriceFeed} from "src/feeds/ChainlinkBasePriceFeed.sol"; +import {FeedSwitch} from "src/util/FeedSwitch.sol"; +import {PendleNAVFeed} from "src/feeds/PendleNAVFeed.sol"; + +contract PendlePTsUSDe27Nov25MarketForkTest is MarketBaseForkTest { + address USDeFeed = address(0xa569d910839Ae8865Da8F8e70FfFb0cBA869F961); + address sUSDeFeed = address(0xFF3BC18cCBd5999CE63E788A1c250a88626aD099); + address sUSDe = address(0x9D39A5DE30e57443BfF2A8307A4256c8797A3497); + address pendlePT = address(0xe6A934089BBEe34F832060CE98848359883749B3); // PT sUSDe 24 Nov 25 + address pendlePTHolder = + address(0xdfcAF20A17521A761036af8a3a758FcDD91dfC07); + + ChainlinkBasePriceFeed sUSDeWrappedFeed; + USDeNavBeforeMaturityFeed beforeMaturityFeed; + ChainlinkBasePriceFeed afterMaturityFeed; + address navFeed; + + uint256 baseDiscount = 0.2 ether; // 20% + FeedSwitch feedSwitch; + + address feedAddr; //FeedSwitch + address marketAddr; + + function setUp() public virtual { + //This will fail if there's no mainnet variable in foundry.toml + string memory url = vm.rpcUrl("mainnet"); + vm.createSelectFork(url, 23231780); + + feedAddr = _deployFeed(); + + marketAddr = address( + new Market( + gov, + lender, + pauseGuardian, + simpleERC20EscrowAddr, + IDolaBorrowingRights(dbrAddr), + IERC20(pendlePT), + IOracle(oracleAddr), + 9150, + 5000, + 500, + false + ) + ); + _advancedInit(marketAddr, feedAddr, false); + } + + function _deployFeed() internal returns (address feed) { + sUSDeWrappedFeed = new ChainlinkBasePriceFeed( + gov, + sUSDeFeed, + address(0), + 24 hours + ); + navFeed = address(new PendleNAVFeed(pendlePT, baseDiscount)); + beforeMaturityFeed = new USDeNavBeforeMaturityFeed( + address(sUSDeWrappedFeed), + address(sUSDe), + address(navFeed) + ); + afterMaturityFeed = new ChainlinkBasePriceFeed( + gov, + USDeFeed, + address(0), + 24 hours + ); + + feedSwitch = new FeedSwitch( + address(navFeed), + address(beforeMaturityFeed), + address(afterMaturityFeed), + 18 hours, + pendlePT, + pauseGuardian + ); + return address(feedSwitch); + } + + // Override the function to use the PendlePTHolder to avoid error revert: stdStorage find(StdStorage): Slot(s) not found + function gibCollateral( + address _address, + uint _amount + ) internal virtual override { + vm.prank(pendlePTHolder); + IERC20(pendlePT).transfer(_address, _amount); + } +} diff --git a/test/util/FeedSwitchNavSUSDe27Nov25.t.sol b/test/util/FeedSwitchNavSUSDe27Nov25.t.sol new file mode 100644 index 0000000..7569aed --- /dev/null +++ b/test/util/FeedSwitchNavSUSDe27Nov25.t.sol @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.18; + +import {FeedSwitch, IChainlinkFeed} from "src/util/FeedSwitch.sol"; +import {BaseFeedSwitchNavForkTest} from "test/util/BaseFeedSwitchNavFork.t.sol"; +import {USDeNavBeforeMaturityFeed} from "src/feeds/USDeNavBeforeMaturityFeed.sol"; +import {PendleNAVFeed} from "src/feeds/PendleNAVFeed.sol"; + +contract FeedSwitchNavSUSDe27Nov25Test is BaseFeedSwitchNavForkTest { + address _beforeMaturityFeed; + address _afterMaturityFeed = address(0xB3C1D801A02d88adC96A294123c2Daa382345058); // USDe Chainlink Wrapper + address _pendlePT = address(0xe6A934089BBEe34F832060CE98848359883749B3); // PT sUSDe 27 Nov 25 + uint256 _baseDiscount = 0.2 ether; // 20% + address sUSDeWrapper = address(0xD723a0910e261de49A90779d38A94aFaAA028F15); + address sUSDe = address(0x9D39A5DE30e57443BfF2A8307A4256c8797A3497); + + function setUp() public { + string memory url = vm.rpcUrl("mainnet"); + vm.createSelectFork(url); + + PendleNAVFeed _navFeed = new PendleNAVFeed(_pendlePT, _baseDiscount); + _beforeMaturityFeed = address(new USDeNavBeforeMaturityFeed(sUSDeWrapper,sUSDe,address(_navFeed))); // USDeBeforeMaturityFeed: USDe/USD Feed using sUSDe Chainlink feed and sUSDe/USDe rate and NAV + + initialize(address(_beforeMaturityFeed), address(_afterMaturityFeed), _pendlePT , _baseDiscount, address(_navFeed)); + } +} diff --git a/test/util/aleTests/ALEPendlePTUSDe25Sep25.t.sol b/test/util/aleTests/ALEPendlePTUSDe25Sep25.t.sol index 78d028f..1a86a34 100644 --- a/test/util/aleTests/ALEPendlePTUSDe25Sep25.t.sol +++ b/test/util/aleTests/ALEPendlePTUSDe25Sep25.t.sol @@ -76,7 +76,7 @@ contract ALEV2PTUSDe25Sep25Test is PendlePTUSDe25Sep25MarketForkTest { uint256 ptAmount = SimpleERC20Escrow(userPkEscrow).balance(); uint maxBorrowAmount = _getMaxBorrowAmount(ptAmount); - console2.log(maxBorrowAmount, "maxBorrowAmount"); + // Sign Message for borrow on behalf bytes32 hash = keccak256( abi.encodePacked( @@ -300,7 +300,7 @@ contract ALEV2PTUSDe25Sep25Test is PendlePTUSDe25Sep25MarketForkTest { gibDBR(userPk, 20000 ether); uint maxBorrowAmount = _getMaxBorrowAmount(ptAmount); - console2.log(maxBorrowAmount,"ESTEEE"); + // Sign Message for borrow on behalf bytes32 hash = keccak256( abi.encodePacked( @@ -390,7 +390,7 @@ contract ALEV2PTUSDe25Sep25Test is PendlePTUSDe25Sep25MarketForkTest { gibDBR(userPk, 20000 ether); uint maxBorrowAmount = _getMaxBorrowAmount(lpAmount); - console2.log(maxBorrowAmount, "LAST ONE"); + // Sign Message for borrow on behalf bytes32 hash = keccak256( abi.encodePacked( @@ -453,7 +453,7 @@ contract ALEV2PTUSDe25Sep25Test is PendlePTUSDe25Sep25MarketForkTest { test_leveragePosition_Mint_PT_and_YT_with_DOLA_router(); uint256 amountToWithdraw = SimpleERC20Escrow(userPkEscrow).balance(); - console2.log(amountToWithdraw,"amount to withdraw"); + bytes32 hash = keccak256( abi.encodePacked( "\x19\x01", @@ -590,7 +590,7 @@ contract ALEV2PTUSDe25Sep25Test is PendlePTUSDe25Sep25MarketForkTest { test_leveragePosition_Swap_DOLA_for_PT_router(); uint256 amountToWithdraw = SimpleERC20Escrow(userPkEscrow).balance(); - console2.log(amountToWithdraw,"amount to withdraw"); + bytes32 hash = keccak256( abi.encodePacked( "\x19\x01", @@ -761,7 +761,6 @@ contract ALEV2PTUSDe25Sep25Test is PendlePTUSDe25Sep25MarketForkTest { assertEq(SimpleERC20Escrow(userPkEscrow).balance(), 0); assertEq(dbr.balanceOf(userPk), 0); - console2.log(DOLA.balanceOf(userPk)+debt,"HERE"); // Dola balance is greater than collateral sold for DOLA minus debt because we also sold DBR assertGt(DOLA.balanceOf(userPk), 190176420699205756775404 - debt); assertEq(market.debts(address(userPk)), 0); @@ -807,7 +806,7 @@ contract ALEV2PTUSDe25Sep25Test is PendlePTUSDe25Sep25MarketForkTest { ); uint256 amountToWithdraw = SimpleERC20Escrow(userPkEscrow).balance(); - console2.log(amountToWithdraw,"THIS ONE"); + bytes32 hash = keccak256( abi.encodePacked( "\x19\x01", @@ -863,7 +862,7 @@ contract ALEV2PTUSDe25Sep25Test is PendlePTUSDe25Sep25MarketForkTest { gibDBR(userPk, 20000 ether); uint256 amountToWithdraw = SimpleERC20Escrow(userPkEscrow).balance(); - console2.log(amountToWithdraw,"REDEEM amount"); + bytes32 hash = keccak256( abi.encodePacked( "\x19\x01", diff --git a/test/util/aleTests/ALEPendlePTUSDe.t.sol b/test/util/aleTests/ALEPendlePTsUSDe.t.sol similarity index 99% rename from test/util/aleTests/ALEPendlePTUSDe.t.sol rename to test/util/aleTests/ALEPendlePTsUSDe.t.sol index 26cd95d..070cf74 100644 --- a/test/util/aleTests/ALEPendlePTUSDe.t.sol +++ b/test/util/aleTests/ALEPendlePTsUSDe.t.sol @@ -14,7 +14,7 @@ import {SimpleERC20Escrow} from "src/escrows/SimpleERC20Escrow.sol"; DOLA 0x865377367054516e17014CcdED1e7d814EDC9ce4 address pendlePT = 0xE00bd3Df25fb187d6ABBB620b3dfd19839947b81 */ -contract ALEV2PTUSDeTest is PendlePTsUSDe27Mar25MarketForkTest { +contract ALEV2PTsUSDeTest is PendlePTsUSDe27Mar25MarketForkTest { ALEV2 ale; address userPk = vm.addr(1); PendlePTHelper helper; diff --git a/test/util/aleTests/ALEPendlePTUSDe24Sep25.t.sol b/test/util/aleTests/ALEPendlePTsUSDe24Sep25.t.sol similarity index 99% rename from test/util/aleTests/ALEPendlePTUSDe24Sep25.t.sol rename to test/util/aleTests/ALEPendlePTsUSDe24Sep25.t.sol index f553af7..fed2bcf 100644 --- a/test/util/aleTests/ALEPendlePTUSDe24Sep25.t.sol +++ b/test/util/aleTests/ALEPendlePTsUSDe24Sep25.t.sol @@ -13,7 +13,7 @@ import {SimpleERC20Escrow} from "src/escrows/SimpleERC20Escrow.sol"; DOLA 0x865377367054516e17014CcdED1e7d814EDC9ce4 pendlePT 0x9F56094C450763769BA0EA9Fe2876070c0fD5F77 */ -contract ALEV2PTUSDe24Sep25Test is PendlePTsUSDe24Sep25MarketForkTest { +contract ALEV2PTsUSDe24Sep25Test is PendlePTsUSDe24Sep25MarketForkTest { ALEV2 ale; address userPk = vm.addr(1); PendlePTHelper helper; diff --git a/test/util/aleTests/ALEPendlePTsUSDe27Nov25.t.sol b/test/util/aleTests/ALEPendlePTsUSDe27Nov25.t.sol new file mode 100644 index 0000000..40973ef --- /dev/null +++ b/test/util/aleTests/ALEPendlePTsUSDe27Nov25.t.sol @@ -0,0 +1,1031 @@ +pragma solidity ^0.8.13; + +import {ICurvePool} from "src/interfaces/ICurvePool.sol"; +import {PendlePTHelper, IPendleHelper} from "src/util/PendlePTHelper.sol"; +import "test/marketForkTests/PendlePTsUSDe27Nov25MarketForkTest.t.sol"; +import {ALEV2} from "src/util/ALEV2.sol"; +import {SimpleERC20Escrow} from "src/escrows/SimpleERC20Escrow.sol"; + +/* + User 0x7E5F4552091A69125d5DfCb7b8C2659029395Bdf + ALE 0x4dF2EaA1658a220FDB415B9966a9ae7c3d16e240 + helper 0x4809fE7d314c2AE5b2Eb7fa19C1B166434D29141 + DOLA 0x865377367054516e17014CcdED1e7d814EDC9ce4 + pendlePT 0xe6A934089BBEe34F832060CE98848359883749B3 +*/ +contract ALEV2PTsUSDe27Nov25Test is PendlePTsUSDe27Nov25MarketForkTest { + ALEV2 ale; + address userPk = vm.addr(1); + PendlePTHelper helper; + address userPkEscrow; + + address pendleRouter = address(0x888888888889758F76e7103c6CbF23ABbF58F946); + address pendleYT = address(0x28E626b560F1FaaC01544770425e2De8FD179c79); + address marketPT = address(0xb6aC3d5da138918aC4E84441e924a20daA60dBdd); + + // Pendle Router Mock + address pendleYTHolder = + address(0xda3D20278eC5D01A420c0bA9A5A7a0A963099660); + + // Get initial PT + // Swap 100K DOLA for PT (recipient helper) + bytes pendleDataInitial = + hex"c81f847a0000000000000000000000004809fe7d314c2ae5b2eb7fa19c1b166434d29141000000000000000000000000b6ac3d5da138918ac4e84441e924a20daa60dbdd00000000000000000000000000000000000000000000155cd11575122cc0369c000000000000000000000000000000000000000000000aca0755d3b1428f9f760000000000000000000000000000000000000000000016a8429aa2f43efa68770000000000000000000000000000000000000000000015940eaba762851f3eec000000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000009184e72a00000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000b80000000000000000000000000865377367054516e17014ccded1e7d814edc9ce400000000000000000000000000000000000000000000152d02c7e14af68000000000000000000000000000009d39a5de30e57443bff2a8307a4256c8797a3497000000000000000000000000d4f480965d2347d421f1bec7f545682e5ec2151d00000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000010000000000000000000000006131b5fae19ea4f9d964eac0408e4408b66337b50000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008e4e21fd0e900000000000000000000000000000000000000000000000000000000000000200000000000000000000000006e4141d33021b52c91c28608403db4a0ffb50ec6000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000003c000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000865377367054516e17014ccded1e7d814edc9ce40000000000000000000000009d39a5de30e57443bff2a8307a4256c8797a3497000000000000000000000000888888888889758f76e7103c6cbf23abbf58f946000000000000000000000000000000000000000000000000000000007fffffff00000000000000000000000000000000000000000000000000000000000002a000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000040d90ce491000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000100000000000000000000000000744793b5110f6ca9cc7cdfe1ce16677c3eb192ef000000000000000000000000865377367054516e17014ccded1e7d814edc9ce40000000000000000000000009d39a5de30e57443bff2a8307a4256c8797a34970000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000152d02c7e14af68000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000012928fdbd4660f500000000000011b64db9c15b25000000000000000000000000000000865377367054516e17014ccded1e7d814edc9ce40000000000000000000000009d39a5de30e57443bff2a8307a4256c8797a3497000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000001e00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000888888888889758f76e7103c6cbf23abbf58f94600000000000000000000000000000000000000000000152d02c7e14af6800000000000000000000000000000000000000000000000001188f5e889a997d47ae00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000022000000000000000000000000000000000000000000000000000000000000000010000000000000000000000006e4141d33021b52c91c28608403db4a0ffb50ec6000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000152d02c7e14af680000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002887b22536f75726365223a2250656e646c65222c22416d6f756e74496e555344223a2239393436372e3030303834363736343332222c22416d6f756e744f7574555344223a2239393438362e3230383737313530393835222c22526566657272616c223a22222c22466c616773223a302c22416d6f756e744f7574223a223833363433313338333530343037393235383931303731222c2254696d657374616d70223a313735363238393737352c22526f7574654944223a2239626466613239302d303333302d343132622d613432612d6534646533373466626634383a61383730653065362d393636312d346335392d616137372d356534393931343066396266222c22496e74656772697479496e666f223a7b224b65794944223a2231222c225369676e6174757265223a2252336d6a506b447168766b706a482b752b6646374e582b396144576756642b306567716134414675486b4774634965586933526832324b454e627a68332f6f79456f68357542763143564c4157756b367366716c536d554734425a6a463059313345484a65676263453335494d645556573348784b4c7950782f465463766a646556464d6738506639442f684b665934566b41764d4b733037647645384b4232344873556731346253316371765a6470786b526f6a386d4b667a6e5a717263457a4c6e4e49706b69584c717841434550514c6366316c435838593059394a736938737151723468685342345979784c487574794c772f634738383456597254424f626d6575675a68722f5033592b786c6e446362476479584c38637656697575554f646a4e4a586b4d6b59525a7432564e713843396c526f507663505466356150576e657069676b526b31482b586e757742386441513d3d227d7d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"; + // Swap maxBorrowAmount from 100k DOLA to PT deposit (recipient helper) + bytes pendleSwapData = + hex"c81f847a0000000000000000000000004809fe7d314c2ae5b2eb7fa19c1b166434d29141000000000000000000000000b6ac3d5da138918ac4e84441e924a20daa60dbdd0000000000000000000000000000000000000000000012eb5e868b4cfaa0da9200000000000000000000000000000000000000000000094e62f9bcf93e3858f3000000000000000000000000000000000000000000001410d4709e361b6cdf2000000000000000000000000000000000000000000000129cc5f379f27c70b1e7000000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000009184e72a00000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000b80000000000000000000000000865377367054516e17014ccded1e7d814edc9ce40000000000000000000000000000000000000000000012c0e02deedaf74fec290000000000000000000000009d39a5de30e57443bff2a8307a4256c8797a3497000000000000000000000000d4f480965d2347d421f1bec7f545682e5ec2151d00000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000010000000000000000000000006131b5fae19ea4f9d964eac0408e4408b66337b50000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008e4e21fd0e900000000000000000000000000000000000000000000000000000000000000200000000000000000000000006e4141d33021b52c91c28608403db4a0ffb50ec6000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000003c000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000865377367054516e17014ccded1e7d814edc9ce40000000000000000000000009d39a5de30e57443bff2a8307a4256c8797a3497000000000000000000000000888888888889758f76e7103c6cbf23abbf58f946000000000000000000000000000000000000000000000000000000007fffffff00000000000000000000000000000000000000000000000000000000000002a000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000040d90ce491000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000100000000000000000000000000744793b5110f6ca9cc7cdfe1ce16677c3eb192ef000000000000000000000000865377367054516e17014ccded1e7d814edc9ce40000000000000000000000009d39a5de30e57443bff2a8307a4256c8797a3497000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000012c0e02deedaf74fec29000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000001072a8bdc4e368f0000000000000faf98f49a5870000000000000000000000000000000865377367054516e17014ccded1e7d814edc9ce40000000000000000000000009d39a5de30e57443bff2a8307a4256c8797a3497000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000001e00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000888888888889758f76e7103c6cbf23abbf58f9460000000000000000000000000000000000000000000012c0e02deedaf74fec29000000000000000000000000000000000000000000000f877106a30ac0cccccb0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000022000000000000000000000000000000000000000000000000000000000000000010000000000000000000000006e4141d33021b52c91c28608403db4a0ffb50ec600000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000012c0e02deedaf74fec2900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002887b22536f75726365223a2250656e646c65222c22416d6f756e74496e555344223a2238383235322e3730323432343531373836222c22416d6f756e744f7574555344223a2238383135352e3033393633363131353232222c22526566657272616c223a22222c22466c616773223a302c22416d6f756e744f7574223a223734303734363939303539383336353539303332333139222c2254696d657374616d70223a313735363239303032332c22526f7574654944223a2266653662386331612d663163372d346162362d383565372d3961623036653134363131363a63353434666436322d316162332d343438302d623431362d313064323631316236623237222c22496e74656772697479496e666f223a7b224b65794944223a2231222c225369676e6174757265223a22503250327a5562513047494669357734324f4c487076464945556e383539375932316d4370355372514e5a596779724132474b472b63323968784f455137636c6945704f4150754b58723247314f7155354a3453582b7539507a55794c4a4c44316c524d77706c452f484459387956727367617a3063424741794a37513445326f644456674245423969566c4a423270786c3333616b5a42644a7566744b5752366531466b6c77736b627736715174585978456638397a516b447a446938797a47424c3950457a35316b7063674f494441433974774439474d746d304c786f302b34484130524a2b6d4238442b4c434e77394a645a6275437848793969683053364176613054324b54464b4d484357544e3438384b484a7847746837353659674a475846476841545962763269565869376a58363856772f31624d4c52457a4955724c364a2b4f3168376c365a76717847775a6247673d3d227d7d00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c9b3e2c3ec88b1b4c0cd853f4321000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000062000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000002c00000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000242331de715df68c7132ffb90567bcf8ea432223e869457a5131b486ad199b1b12efee73e94f696fe0000000000000000000000000000000000000000000000000000000068aedcf800000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000000000000000abf8165dd7a90ab75878161db15bf85f6f781d9b00000000000000000000000028e626b560f1faac01544770425e2de8fd179c79000000000000000000000000f29573d68775cfe819dcde4e34a03a26dc7698b7000000000000000000000000f29573d68775cfe819dcde4e34a03a26dc7698b700000000000000000000000000000000000000000000000242331de715df68c700000000000000000000000000000000000000000000000001322ac247df34300000000000000000000000000000000000000000000000000c7d713b49da000000000000000000000000000000000000000000000000000000000000000001800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004139d853773b933b01d68b806e031f7ba9abe5eb4f606ae7aeabf1455f7fd64982165887208db105354e57b220f8423b646ca153082bc07c5ab95391d646213daa1b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000078673f2d54958422481933faab263a259cc2911e9f9eba40823fde0b86b20cbf95ce43be0360f570000000000000000000000000000000000000000000000000000000068aef3db000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000009d39a5de30e57443bff2a8307a4256c8797a349700000000000000000000000028e626b560f1faac01544770425e2de8fd179c79000000000000000000000000a14ad7f4c766bd5ca9b79a4a81873b8bcdf57c86000000000000000000000000a14ad7f4c766bd5ca9b79a4a81873b8bcdf57c86000000000000000000000000000000000000000000000019e168cff5a6dad8e000000000000000000000000000000000000000000000000001322a287c026aac0000000000000000000000000000000000000000000000000c7d713b49da0000000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000041cb7c465288b05282eada29ebfa88d4635d6e7f0fe440feedf8a37a0263b13ec34755e79b2eeeaf21867a7443ca8bb9052e256abb1200561725172735674f1c711b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"; + + uint256 initialDolaAmount = 100000 ether; // 100K DOLA + + function setUp() public override { + super.setUp(); + + vm.startPrank(gov); + + ale = ALEV2(payable(aleV2Addr)); + + helper = PendlePTHelper( + pendlePTHelperAddr + ); + ale.setMarket(address(market), address(DOLA), address(helper), false); + helper.setMarket(address(market), address(pendlePT), pendleYT); + borrowController.allow(address(ale)); + DOLA.mint(address(market), 1000000 ether); + vm.stopPrank(); + + userPkEscrow = address(market.predictEscrow(userPk)); + + vm.prank(userPk); + DOLA.approve(address(helper), initialDolaAmount); + } + + function _mintInitialDolaAmountToUser() internal { + vm.prank(gov); + DOLA.mint(userPk, initialDolaAmount); + } + function test_leveragePosition_Mint_PT_and_YT_with_DOLA_router() public { + _mintInitialDolaAmountToUser(); + vm.prank(userPk); + helper.convertToCollateralAndDeposit( + initialDolaAmount, + userPk, + abi.encode(address(market), 0, pendleDataInitial) + ); + + gibDBR(userPk, 20000 ether); + + uint256 ptAmount = SimpleERC20Escrow(userPkEscrow).balance(); + + uint maxBorrowAmount = _getMaxBorrowAmount(ptAmount); + + // Sign Message for borrow on behalf + bytes32 hash = keccak256( + abi.encodePacked( + "\x19\x01", + market.DOMAIN_SEPARATOR(), + keccak256( + abi.encode( + keccak256( + "BorrowOnBehalf(address caller,address from,uint256 amount,uint256 nonce,uint256 deadline)" + ), + address(ale), + userPk, + maxBorrowAmount, + 0, + block.timestamp + ) + ) + ) + ); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(1, hash); + + ALEV2.Permit memory permit = ALEV2.Permit( + block.timestamp, + v, + r, + s + ); + + bytes memory swapData; + + ALEV2.DBRHelper memory dbrData; + // Mint PT and YT with maxBorrowAmount (swap recipient is the helper, then distribute PT to ALE and YT to userPk) + bytes + memory pendleMintData = hex"d0f423850000000000000000000000004809fe7d314c2ae5b2eb7fa19c1b166434d2914100000000000000000000000028e626b560f1faac01544770425e2de8fd179c79000000000000000000000000000000000000000000001282f915ef976670abac0000000000000000000000000000000000000000000000000000000000000080000000000000000000000000865377367054516e17014ccded1e7d814edc9ce40000000000000000000000000000000000000000000012c0e02deedaf74fec290000000000000000000000009d39a5de30e57443bff2a8307a4256c8797a3497000000000000000000000000d4f480965d2347d421f1bec7f545682e5ec2151d00000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000010000000000000000000000006131b5fae19ea4f9d964eac0408e4408b66337b50000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008e4e21fd0e900000000000000000000000000000000000000000000000000000000000000200000000000000000000000006e4141d33021b52c91c28608403db4a0ffb50ec6000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000003c000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000865377367054516e17014ccded1e7d814edc9ce40000000000000000000000009d39a5de30e57443bff2a8307a4256c8797a3497000000000000000000000000888888888889758f76e7103c6cbf23abbf58f946000000000000000000000000000000000000000000000000000000007fffffff00000000000000000000000000000000000000000000000000000000000002a000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000040d90ce491000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000100000000000000000000000000744793b5110f6ca9cc7cdfe1ce16677c3eb192ef000000000000000000000000865377367054516e17014ccded1e7d814edc9ce40000000000000000000000009d39a5de30e57443bff2a8307a4256c8797a3497000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000012c0e02deedaf74fec29000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000001072bd0fd0ed6450000000000000fafac55a95ba5000000000000000000000000000000865377367054516e17014ccded1e7d814edc9ce40000000000000000000000009d39a5de30e57443bff2a8307a4256c8797a3497000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000001e00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000888888888889758f76e7103c6cbf23abbf58f9460000000000000000000000000000000000000000000012c0e02deedaf74fec29000000000000000000000000000000000000000000000f87843615be916e14790000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000022000000000000000000000000000000000000000000000000000000000000000010000000000000000000000006e4141d33021b52c91c28608403db4a0ffb50ec600000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000012c0e02deedaf74fec2900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002877b22536f75726365223a2250656e646c65222c22416d6f756e74496e555344223a2238383035332e3539373237323135323331222c22416d6f756e744f7574555344223a2238383133312e39333634373432323133222c22526566657272616c223a22222c22466c616773223a302c22416d6f756e744f7574223a223734303736303935343733373032343639313037373131222c2254696d657374616d70223a313735363239303734312c22526f7574654944223a2231326464333835312d373931642d343165622d386366342d3363626639626562623034393a31326338626665622d643162632d343434322d393339302d643431396635663131316362222c22496e74656772697479496e666f223a7b224b65794944223a2231222c225369676e6174757265223a22535362436230762b4e4d58587264376e634747445a5153647568414e5645516d67342f377a5664684a59647437694b514b4661616d74492b593570684f43754e516e6742426c514339436e4949414a32512b3863586564576f3348353453765854687a4b56756d44344379794d6d33346f74786564746431354f654b6f5a506735557242536a6162514f73445634567974534f467a33376275644b66686c616f56636a324d744b7a39344b474b626766692f6976455063786e62325a546e4d4f696c3176694a54642f336c6d68524f4a6846546f564832354e30374a7a533875455569704a7559492b42383736684d5a4d4157792f3452324d6e482f42424a4b6a6552344c6b644d74354a55566d2b32435571703543774c6b39636c504d4d746e473848304b6439645147624a3477542b41786e4a67627832514b355236787876576c476748644534446271714e6e4e347762436e413d3d227d7d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"; + vm.prank(userPk); + ale.leveragePosition( + maxBorrowAmount, + address(market), + address(0), + swapData, + permit, + abi.encode(address(market), 0, pendleMintData), + dbrData + ); + + assertEq(DOLA.balanceOf(userPk), 0); + assertApproxEqRel( + SimpleERC20Escrow(userPkEscrow).balance(), + ptAmount + ((maxBorrowAmount * 0.99706 ether) / 1 ether), //0.99706 ratio minted PT and YT to DOLA + 1e14 // 0.01% Delta + ); + + assertApproxEqRel( + IERC20(pendleYT).balanceOf(userPk), + ((maxBorrowAmount * 0.99706 ether) / 1 ether), // 0.99706 ratio minted PT and YT to DOLA + 1e14 // 0.01% Delta + ); + } + + function test_leveragePosition_Swap_DOLA_for_PT_router() public { + _mintInitialDolaAmountToUser(); + + vm.prank(userPk); + helper.convertToCollateralAndDeposit( + initialDolaAmount, + userPk, + abi.encode(address(market), initialDolaAmount, pendleDataInitial) + ); + gibDBR(userPk, 20000 ether); + + uint256 ptAmount = SimpleERC20Escrow(userPkEscrow).balance(); + uint maxBorrowAmount = _getMaxBorrowAmount(ptAmount); + // Sign Message for borrow on behalf + bytes32 hash = keccak256( + abi.encodePacked( + "\x19\x01", + market.DOMAIN_SEPARATOR(), + keccak256( + abi.encode( + keccak256( + "BorrowOnBehalf(address caller,address from,uint256 amount,uint256 nonce,uint256 deadline)" + ), + address(ale), + userPk, + maxBorrowAmount, + 0, + block.timestamp + ) + ) + ) + ); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(1, hash); + + ALEV2.Permit memory permit = ALEV2.Permit( + block.timestamp, + v, + r, + s + ); + + bytes memory swapData; + + ALEV2.DBRHelper memory dbrData; + + vm.prank(userPk); + ale.leveragePosition( + maxBorrowAmount, + address(market), + address(0), + swapData, + permit, + abi.encode(address(market), 0, pendleSwapData), + dbrData + ); + + assertEq(DOLA.balanceOf(userPk), 0); + assertApproxEqRel( + SimpleERC20Escrow(userPkEscrow).balance(), + ptAmount + ((maxBorrowAmount * 1.0185 ether) / 1 ether), // approx 1.0185 ratio PT/DOLA + 1e14 // 0.01% Delta + ); + assertEq(DOLA.balanceOf(address(ale)), 0); + } + + function test_leveragePosition_buyDBR_Swap_DOLA_for_PT() public { + _mintInitialDolaAmountToUser(); + + vm.startPrank(userPk, userPk); + DOLA.approve(address(helper), initialDolaAmount); + helper.convertToCollateralAndDeposit( + initialDolaAmount, + userPk, + abi.encode(address(market), 0, pendleDataInitial) + ); + vm.stopPrank(); + + uint256 ptAmount = SimpleERC20Escrow(userPkEscrow).balance(); + + uint maxBorrowAmount = _getMaxBorrowAmount(ptAmount); + + // Calculate the amount of DOLA needed to borrow to buy the DBR needed to cover for the borrowing period + (uint256 dolaForDBR, uint256 dbrAmount) = ale + .approximateDolaAndDbrNeeded(maxBorrowAmount, 15 days, 8); + + // Sign Message for borrow on behalf + bytes32 hash = keccak256( + abi.encodePacked( + "\x19\x01", + market.DOMAIN_SEPARATOR(), + keccak256( + abi.encode( + keccak256( + "BorrowOnBehalf(address caller,address from,uint256 amount,uint256 nonce,uint256 deadline)" + ), + address(ale), + userPk, + maxBorrowAmount + dolaForDBR, + 0, + block.timestamp + ) + ) + ) + ); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(1, hash); + + ALEV2.Permit memory permit = ALEV2.Permit( + block.timestamp, + v, + r, + s + ); + + bytes memory swapData; + + ALEV2.DBRHelper memory dbrData = ALEV2.DBRHelper( + dolaForDBR, + (dbrAmount * 90) / 100, + 0 + ); + + vm.prank(userPk); + ale.leveragePosition( + maxBorrowAmount, + address(market), + address(0), + swapData, + permit, + abi.encode(address(market), 0, pendleSwapData), + dbrData + ); + + assertEq(DOLA.balanceOf(userPk), 0); + assertApproxEqRel( + SimpleERC20Escrow(userPkEscrow).balance(), + ptAmount + ((maxBorrowAmount * 1.0185 ether) / 1 ether), // approx 1.0185 ratio PT/DOLA + 1e14 // 0.01% Delta + ); + assertEq(DOLA.balanceOf(address(ale)), 0); + assertGt(dbr.balanceOf(userPk), (dbrAmount * 90) / 100); + } + + function test_depositAndLeveragePosition_DOLA() public { + _mintInitialDolaAmountToUser(); + + uint256 initialDolaDeposit = initialDolaAmount / 10; + // Swap DOLA for PT (initialDolaAmount - initialDolaDeposit) (receiver is the helper) + bytes + memory pendleInitialDepositData = hex"c81f847a0000000000000000000000004809fe7d314c2ae5b2eb7fa19c1b166434d29141000000000000000000000000b6ac3d5da138918ac4e84441e924a20daa60dbdd000000000000000000000000000000000000000000001339d1103cb6b2e86e590000000000000000000000000000000000000000000009b5c417b73aa7eeecbe0000000000000000000000000000000000000000000014641bcb672e60a8f12800000000000000000000000000000000000000000000136b882f6e754fddd97c000000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000009184e72a00000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000b80000000000000000000000000865377367054516e17014ccded1e7d814edc9ce400000000000000000000000000000000000000000000130ee8e71790444000000000000000000000000000009d39a5de30e57443bff2a8307a4256c8797a3497000000000000000000000000d4f480965d2347d421f1bec7f545682e5ec2151d00000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000010000000000000000000000006131b5fae19ea4f9d964eac0408e4408b66337b50000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008e4e21fd0e900000000000000000000000000000000000000000000000000000000000000200000000000000000000000006e4141d33021b52c91c28608403db4a0ffb50ec6000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000003c000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000865377367054516e17014ccded1e7d814edc9ce40000000000000000000000009d39a5de30e57443bff2a8307a4256c8797a3497000000000000000000000000888888888889758f76e7103c6cbf23abbf58f946000000000000000000000000000000000000000000000000000000007fffffff00000000000000000000000000000000000000000000000000000000000002a000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000040d90ce491000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000100000000000000000000000000744793b5110f6ca9cc7cdfe1ce16677c3eb192ef000000000000000000000000865377367054516e17014ccded1e7d814edc9ce40000000000000000000000009d39a5de30e57443bff2a8307a4256c8797a34970000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000130ee8e71790444000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000010b6e39c2a7f8650000000000000ff0aaa8da7786000000000000000000000000000000865377367054516e17014ccded1e7d814edc9ce40000000000000000000000009d39a5de30e57443bff2a8307a4256c8797a3497000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000001e00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000888888888889758f76e7103c6cbf23abbf58f94600000000000000000000000000000000000000000000130ee8e7179044400000000000000000000000000000000000000000000000000fc7dc272a33c4a8f5c10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000022000000000000000000000000000000000000000000000000000000000000000010000000000000000000000006e4141d33021b52c91c28608403db4a0ffb50ec6000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000130ee8e717904440000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002887b22536f75726365223a2250656e646c65222c22416d6f756e74496e555344223a2238393536392e3535303932343339353231222c22416d6f756e744f7574555344223a2238393731372e3637323938343638323231222c22526566657272616c223a22222c22466c616773223a302c22416d6f756e744f7574223a223735323735303133313339373234333839383432393433222c2254696d657374616d70223a313735363239313539392c22526f7574654944223a2263636134636536642d383835352d343237352d383139352d3262383062386266636339343a39353565386630632d363465322d343065332d623930362d366131363362396134326537222c22496e74656772697479496e666f223a7b224b65794944223a2231222c225369676e6174757265223a224a48673771696a4d4b525668777a65752b6d6a4959615435384b7054674f745a7a784f445a3834332f303674784a535849676751434f424d66364b45597a62574c5543387a6b59756e3948686a705a3465455563583747726f344d3941597964574f566651686961616b34477155436471583057666c775a3352474a33746a74737339792f566451746345665737676e4c3577574248415442465279682b6f5a3566647779596e786d41767253516a4d4c635679656d424d344270534364386f50627138792b7678796970457538614639706f2f7144626f356147335734514d556332764a526230734934334b667358317a5651736f346943636e442b6f73376243623665776544447361764d596556563469715a6730564643376461777a4f5a6379383471652b4c585856445444414b7667686869363565486f344d79363865504b6d757a57376a316d782f656e464347676c68673d3d227d7d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"; + vm.startPrank(userPk, userPk); + DOLA.approve(address(helper), initialDolaAmount - initialDolaDeposit); + helper.convertToCollateralAndDeposit( + initialDolaAmount - initialDolaDeposit, + userPk, + abi.encode(address(market), 0, pendleInitialDepositData) + ); + assertEq(DOLA.balanceOf(address(helper)), 0); + vm.stopPrank(); + + uint256 ptAmount = SimpleERC20Escrow(userPkEscrow).balance(); + gibDBR(userPk, 20000 ether); + + uint maxBorrowAmount = _getMaxBorrowAmount(ptAmount); + // Sign Message for borrow on behalf + bytes32 hash = keccak256( + abi.encodePacked( + "\x19\x01", + market.DOMAIN_SEPARATOR(), + keccak256( + abi.encode( + keccak256( + "BorrowOnBehalf(address caller,address from,uint256 amount,uint256 nonce,uint256 deadline)" + ), + address(ale), + userPk, + maxBorrowAmount, + 0, + block.timestamp + ) + ) + ) + ); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(1, hash); + + ALEV2.Permit memory permit = ALEV2.Permit( + block.timestamp, + v, + r, + s + ); + + bytes memory swapData; + + ALEV2.DBRHelper memory dbrData; + + // Swap DOLA for PT (maxBorrowAmount + initialDolaDeposit) (receiver is the helper) + bytes + memory pendleSwapDataDeposit = hex"c81f847a0000000000000000000000004809fe7d314c2ae5b2eb7fa19c1b166434d29141000000000000000000000000b6ac3d5da138918ac4e84441e924a20daa60dbdd000000000000000000000000000000000000000000001329ce90a350e6a8b9100000000000000000000000000000000000000000000009adae24d8f28e5a62a300000000000000000000000000000000000000000000145320e6faca2af1025700000000000000000000000000000000000000000000135b5c49b1e51cb4c547000000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000009184e72a00000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000b80000000000000000000000000865377367054516e17014ccded1e7d814edc9ce40000000000000000000000000000000000000000000012fef6d0e9251ab41d250000000000000000000000009d39a5de30e57443bff2a8307a4256c8797a3497000000000000000000000000d4f480965d2347d421f1bec7f545682e5ec2151d00000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000010000000000000000000000006131b5fae19ea4f9d964eac0408e4408b66337b50000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008e4e21fd0e900000000000000000000000000000000000000000000000000000000000000200000000000000000000000006e4141d33021b52c91c28608403db4a0ffb50ec6000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000003c000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000865377367054516e17014ccded1e7d814edc9ce40000000000000000000000009d39a5de30e57443bff2a8307a4256c8797a3497000000000000000000000000888888888889758f76e7103c6cbf23abbf58f946000000000000000000000000000000000000000000000000000000007fffffff00000000000000000000000000000000000000000000000000000000000002a000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000040d90ce491000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000100000000000000000000000000744793b5110f6ca9cc7cdfe1ce16677c3eb192ef000000000000000000000000865377367054516e17014ccded1e7d814edc9ce40000000000000000000000009d39a5de30e57443bff2a8307a4256c8797a3497000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000012fef6d0e9251ab41d250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000010a8e91648aa1480000000000000fe355ea046453800000000000000000000000000000865377367054516e17014ccded1e7d814edc9ce40000000000000000000000009d39a5de30e57443bff2a8307a4256c8797a3497000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000001e00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000888888888889758f76e7103c6cbf23abbf58f9460000000000000000000000000000000000000000000012fef6d0e9251ab41d25000000000000000000000000000000000000000000000fbaa988f4fcec43d7090000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000022000000000000000000000000000000000000000000000000000000000000000010000000000000000000000006e4141d33021b52c91c28608403db4a0ffb50ec600000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000012fef6d0e9251ab41d2500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002877b22536f75726365223a2250656e646c65222c22416d6f756e74496e555344223a2238393235302e35353432313237313037222c22416d6f756e744f7574555344223a2238393431322e3432383131303836333931222c22526566657272616c223a22222c22466c616773223a302c22416d6f756e744f7574223a223735303239303938393133323433343634373238353735222c2254696d657374616d70223a313735363239313636332c22526f7574654944223a2234383830623133312d636266642d346539302d393730312d6563386363646130356134663a30656366316635612d393264352d346330612d396662622d343165313536636437323631222c22496e74656772697479496e666f223a7b224b65794944223a2231222c225369676e6174757265223a2246634633594d2b4d4561476f784c62626b4267346f64574f6a3132365a6f4534726a464c68692f4b756454754952417a4e316b5a574f344c77487a2b6e31783345734c4d4255424933434c376c796a6c6c51636439637877706a685a7343443845544d2f49312b4956756164706f6c4f6f704a5450644b666c5046484578746c77466d4b6f702b6c6654786f4d6b7759665a693856456e71632b57564863685454756430544c6a654b6877664f2f6c56367a6a7531426349526854704943424548676a375a576a4158574d5a4262546c70656f55356c6535442f4c7a533434336f304f5a2f696c615a50306d37535146476d6d565a596e44534a596c4e5656562b494865724c624c496b696d30713962474f534f342b46536e6f735a616f6a3877586a38353643594a69384d6f567541424e376d7138624744384558747548552b7672536530707a6a674f7642424c396a4776674e773d3d227d7d00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"; + + vm.startPrank(userPk); + DOLA.approve(address(ale), initialDolaDeposit); + ale.depositAndLeveragePosition( + initialDolaDeposit, + maxBorrowAmount, + address(market), + address(0), + swapData, + permit, + abi.encode(address(market), uint(100000), pendleSwapDataDeposit), + dbrData, + false + ); + + assertEq(DOLA.balanceOf(userPk), 0); + + assertApproxEqRel( + SimpleERC20Escrow(userPkEscrow).balance(), + ptAmount + + (((maxBorrowAmount + initialDolaDeposit) * 1.0185 ether) / + 1 ether), // approx 1.0185 ratio PT/DOLA + 1e14 // 0.01% Delta + ); + } + + function test_depositAndLeveragePosition_PT() public { + _mintInitialDolaAmountToUser(); + + uint256 initialDolaDeposit = initialDolaAmount / 10; + + vm.startPrank(userPk, userPk); + DOLA.approve(address(helper), initialDolaAmount); + // Swap DOLA for PT (initialDolaDeposit) (receiver is the helper, recipient is the user which will be depositing them) + bytes + memory pendleDataInitialPT = hex"c81f847a0000000000000000000000004809fe7d314c2ae5b2eb7fa19c1b166434d29141000000000000000000000000b6ac3d5da138918ac4e84441e924a20daa60dbdd000000000000000000000000000000000000000000000222fedc0a68c3cf528900000000000000000000000000000000000000000000011442a80541d741eba000000000000000000000000000000000000000000000024425940b0a440a6ed000000000000000000000000000000000000000000000022885500a83ae83d740000000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000009184e72a00000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000b80000000000000000000000000865377367054516e17014ccded1e7d814edc9ce400000000000000000000000000000000000000000000021e19e0c9bab24000000000000000000000000000009d39a5de30e57443bff2a8307a4256c8797a3497000000000000000000000000d4f480965d2347d421f1bec7f545682e5ec2151d00000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000010000000000000000000000006131b5fae19ea4f9d964eac0408e4408b66337b50000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008e4e21fd0e900000000000000000000000000000000000000000000000000000000000000200000000000000000000000006e4141d33021b52c91c28608403db4a0ffb50ec6000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000003c000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000865377367054516e17014ccded1e7d814edc9ce40000000000000000000000009d39a5de30e57443bff2a8307a4256c8797a3497000000000000000000000000888888888889758f76e7103c6cbf23abbf58f946000000000000000000000000000000000000000000000000000000007fffffff00000000000000000000000000000000000000000000000000000000000002a000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000040d90ce491000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000100000000000000000000000000744793b5110f6ca9cc7cdfe1ce16677c3eb192ef000000000000000000000000865377367054516e17014ccded1e7d814edc9ce40000000000000000000000009d39a5de30e57443bff2a8307a4256c8797a34970000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000021e19e0c9bab24000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000001db717a5de506000000000000001c56b0496b37df00000000000000000000000000000865377367054516e17014ccded1e7d814edc9ce40000000000000000000000009d39a5de30e57443bff2a8307a4256c8797a3497000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000001e00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000888888888889758f76e7103c6cbf23abbf58f94600000000000000000000000000000000000000000000021e19e0c9bab24000000000000000000000000000000000000000000000000001c0e2448af441cc51ea0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000022000000000000000000000000000000000000000000000000000000000000000010000000000000000000000006e4141d33021b52c91c28608403db4a0ffb50ec6000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000021e19e0c9bab240000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002877b22536f75726365223a2250656e646c65222c22416d6f756e74496e555344223a22393935352e353130313634333730333737222c22416d6f756e744f7574555344223a22393936372e353130373134393937363635222c22526566657272616c223a22222c22466c616773223a302c22416d6f756e744f7574223a2238333634303836353139353530303438323036383437222c2254696d657374616d70223a313735363239313733362c22526f7574654944223a2263636266306633332d333865302d343363612d396365342d3339396639613439386233633a39383166313432612d613932322d343632372d623833662d383131306634373132343130222c22496e74656772697479496e666f223a7b224b65794944223a2231222c225369676e6174757265223a2251636838746f4847726f636665537a624a4563526f5046632b6b777a5a4a692f564c6d5848687274615832414179476f536f3862352b383238534b4332725474757a6c2b7345374432636849584f4c304b314a545847494166327a3839654b695056696f5174594a556552646b705332416930776c795364464b316e757653526538376277765051414d4f6e37364c4b6b68365078754f6148686536463666736d64384b6f386f4672354e4c4e7a433831654669584c4b66566e50664a5378584b374153382b6d4538472b4d717534775a39567270336e5a7a68546f767434614b4c6b53624b6956626b51386e6456535753562b486a725a7266457a7063694f71687135644951624d49745733466237656e4763725666394e414c3858765a55472f6b4e4d64443054654774795a70774d415763535645342b6677675566337464347358307653454167683364384f4a7645764c38413d3d227d7d00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"; + + uint256 initialLpAmount = helper.convertToCollateral( + initialDolaDeposit, + abi.encode(address(market), 0, pendleDataInitialPT) + ); + + // Swap DOLA to PT (initialDolaAmount - initialDolaDeposit) (receiver is the helper) + bytes + memory pendleDataInitialDeposit = hex"c81f847a0000000000000000000000004809fe7d314c2ae5b2eb7fa19c1b166434d29141000000000000000000000000b6ac3d5da138918ac4e84441e924a20daa60dbdd000000000000000000000000000000000000000000001339d0f7c7b6179316130000000000000000000000000000000000000000000009b5c40b5d1b51b97a570000000000000000000000000000000000000000000014641bb176b95ed24db700000000000000000000000000000000000000000000136b8816ba36a372f4af000000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000009184e72a00000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000b80000000000000000000000000865377367054516e17014ccded1e7d814edc9ce400000000000000000000000000000000000000000000130ee8e71790444000000000000000000000000000009d39a5de30e57443bff2a8307a4256c8797a3497000000000000000000000000d4f480965d2347d421f1bec7f545682e5ec2151d00000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000010000000000000000000000006131b5fae19ea4f9d964eac0408e4408b66337b50000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008e4e21fd0e900000000000000000000000000000000000000000000000000000000000000200000000000000000000000006e4141d33021b52c91c28608403db4a0ffb50ec6000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000003c000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000865377367054516e17014ccded1e7d814edc9ce40000000000000000000000009d39a5de30e57443bff2a8307a4256c8797a3497000000000000000000000000888888888889758f76e7103c6cbf23abbf58f946000000000000000000000000000000000000000000000000000000007fffffff00000000000000000000000000000000000000000000000000000000000002a000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000040d90ce491000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000100000000000000000000000000744793b5110f6ca9cc7cdfe1ce16677c3eb192ef000000000000000000000000865377367054516e17014ccded1e7d814edc9ce40000000000000000000000009d39a5de30e57443bff2a8307a4256c8797a34970000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000130ee8e71790444000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000010b6e569e5cf08c0000000000000ff0ac6131eda5800000000000000000000000000000865377367054516e17014ccded1e7d814edc9ce40000000000000000000000009d39a5de30e57443bff2a8307a4256c8797a3497000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000001e00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000888888888889758f76e7103c6cbf23abbf58f94600000000000000000000000000000000000000000000130ee8e7179044400000000000000000000000000000000000000000000000000fc7dddb1a63970b851d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000022000000000000000000000000000000000000000000000000000000000000000010000000000000000000000006e4141d33021b52c91c28608403db4a0ffb50ec6000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000130ee8e717904440000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002887b22536f75726365223a2250656e646c65222c22416d6f756e74496e555344223a2238393536302e3739303138363637323333222c22416d6f756e744f7574555344223a2238393638382e3231353638343432333335222c22526566657272616c223a22222c22466c616773223a302c22416d6f756e744f7574223a223735323735313337303834383738393838373731333237222c2254696d657374616d70223a313735363239313737322c22526f7574654944223a2266363736333238612d623364372d343766612d613234312d3637373638316437363833633a64333063336632632d643539612d343963342d396563622d393364613231623731343665222c22496e74656772697479496e666f223a7b224b65794944223a2231222c225369676e6174757265223a22525032707a4330725156427a6a4a53723152715674537942377643545776624348516b746731625967594f524c7230314d526d786646485968446f436f37576451534f2f36323762434277785778357676424367554d354a2b334f634836536d454b6c304e56373177624a376665776244695958323930764a65545732686f3335746357432b436b58344536674e757462394f614641796d5655597a547a6e683944615a6f4b444f734a6369544774474c5457717343714d2f5266572f63425865484b70677373443458536f3855396a4b436a6b4c484a436d6676547159625a784e52505853705455684c44774f495134365754386d71396b4c425276424a494a5442565667357a754f554978566a646b646b4d65476641567370514f726a5550576f55384239695037534a6c734f4846684c4e4634705967476d42723232696d6956306135634452506d4336664939366974584a673d3d227d7d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"; + helper.convertToCollateralAndDeposit( + initialDolaAmount - initialDolaDeposit, + userPk, + abi.encode(address(market), 0, pendleDataInitialDeposit) + ); + vm.stopPrank(); + + uint256 lpAmount = SimpleERC20Escrow(userPkEscrow).balance(); + gibDBR(userPk, 20000 ether); + + uint maxBorrowAmount = _getMaxBorrowAmount(lpAmount); + // Sign Message for borrow on behalf + bytes32 hash = keccak256( + abi.encodePacked( + "\x19\x01", + market.DOMAIN_SEPARATOR(), + keccak256( + abi.encode( + keccak256( + "BorrowOnBehalf(address caller,address from,uint256 amount,uint256 nonce,uint256 deadline)" + ), + address(ale), + userPk, + maxBorrowAmount, + 0, + block.timestamp + ) + ) + ) + ); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(1, hash); + + ALEV2.Permit memory permit = ALEV2.Permit( + block.timestamp, + v, + r, + s + ); + + bytes memory swapData; + + ALEV2.DBRHelper memory dbrData; + // Swap DOLA Max borrow amount to PT (receiver is the helper) + bytes + memory pendleDataLeverage = hex"c81f847a0000000000000000000000004809fe7d314c2ae5b2eb7fa19c1b166434d29141000000000000000000000000b6ac3d5da138918ac4e84441e924a20daa60dbdd000000000000000000000000000000000000000000001106cf8e4d4ed89100630000000000000000000000000000000000000000000008996b697c60b5c7f0ae00000000000000000000000000000000000000000000120efb2a51fe4a8a463b000000000000000000000000000000000000000000001132d6d2f8c16b8fe15d000000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000009184e72a00000000000000000000000000000000000000000000000000000000000000001400000000000000000000000000000000000000000000000000000000000000b80000000000000000000000000865377367054516e17014ccded1e7d814edc9ce40000000000000000000000000000000000000000000010e0b1813c668d29ab2a0000000000000000000000009d39a5de30e57443bff2a8307a4256c8797a3497000000000000000000000000d4f480965d2347d421f1bec7f545682e5ec2151d00000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000010000000000000000000000006131b5fae19ea4f9d964eac0408e4408b66337b50000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008e4e21fd0e900000000000000000000000000000000000000000000000000000000000000200000000000000000000000006e4141d33021b52c91c28608403db4a0ffb50ec6000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000003c000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000865377367054516e17014ccded1e7d814edc9ce40000000000000000000000009d39a5de30e57443bff2a8307a4256c8797a3497000000000000000000000000888888888889758f76e7103c6cbf23abbf58f946000000000000000000000000000000000000000000000000000000007fffffff00000000000000000000000000000000000000000000000000000000000002a000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000040d90ce491000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000100000000000000000000000000744793b5110f6ca9cc7cdfe1ce16677c3eb192ef000000000000000000000000865377367054516e17014ccded1e7d814edc9ce40000000000000000000000009d39a5de30e57443bff2a8307a4256c8797a3497000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000010e0b1813c668d29ab2a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000ecd542a83378f60000000000000e1dc9185b0b68800000000000000000000000000000865377367054516e17014ccded1e7d814edc9ce40000000000000000000000009d39a5de30e57443bff2a8307a4256c8797a3497000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000001e00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000888888888889758f76e7103c6cbf23abbf58f9460000000000000000000000000000000000000000000010e0b1813c668d29ab2a000000000000000000000000000000000000000000000df9a5cddf410ddae1460000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000022000000000000000000000000000000000000000000000000000000000000000010000000000000000000000006e4141d33021b52c91c28608403db4a0ffb50ec600000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000010e0b1813c668d29ab2a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002887b22536f75726365223a2250656e646c65222c22416d6f756e74496e555344223a2237393239342e3332363939333836323131222c22416d6f756e744f7574555344223a2237393334312e3430343533343330333736222c22526566657272616c223a22222c22466c616773223a302c22416d6f756e744f7574223a223636363632353736373730323138323330353436343331222c2254696d657374616d70223a313735363239313935342c22526f7574654944223a2238313362363031662d623238332d343232662d623335312d3763303163356534316137343a63613064326130662d613032632d343434642d383765652d326661353536313464363938222c22496e74656772697479496e666f223a7b224b65794944223a2231222c225369676e6174757265223a224756677a6a2f50706f436c464d7739416c4150614f382f3230646e4d492f32484f6d5461756d374a536e2f49765237737a525431355279536535375665716d4936463476327075386c675442617054624a4331706b4e7a724670393762705279584852446e6d7675717559416a556f4b4737647572706e597361394c6b5834514348327774367279544d596852726935384376412f46336a6e75786e3175506c4d657a4c5238574769525673566f36722f66494d47387a49427744452f6e4c7265393937506a45596d506765685472454957724f61694a6b784452564a555270324649426e357749562f4c704d3332346446774d4a652f4d454b456d6d6c503850756f4d484a6530522b782b57356a45454d585578327766374a3131696a784354536e5434494e51626f744b4f4c7850553561703068416b55514738704b4d6e4a4f6149302b6f646d797a4c4257694b627a506751413d3d227d7d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"; + + vm.startPrank(userPk); + IERC20(pendlePT).approve(address(ale), initialLpAmount); + ale.depositAndLeveragePosition( + initialLpAmount, + maxBorrowAmount, + address(market), + address(0), + swapData, + permit, + abi.encode(address(market), uint(100000), pendleDataLeverage), + dbrData, + true + ); + + assertEq(DOLA.balanceOf(userPk), 0); + assertApproxEqRel( + SimpleERC20Escrow(userPkEscrow).balance(), + lpAmount + + initialLpAmount + + ((maxBorrowAmount * 1.0185 ether) / 1 ether), + 1e14 // 0.01% Delta + ); + } + + function test_deleveragePosition_Redeem_with_PT_and_YT_router() public { + test_leveragePosition_Mint_PT_and_YT_with_DOLA_router(); + + uint256 amountToWithdraw = SimpleERC20Escrow(userPkEscrow).balance(); + bytes32 hash = keccak256( + abi.encodePacked( + "\x19\x01", + market.DOMAIN_SEPARATOR(), + keccak256( + abi.encode( + keccak256( + "WithdrawOnBehalf(address caller,address from,uint256 amount,uint256 nonce,uint256 deadline)" + ), + address(ale), + userPk, + amountToWithdraw, + 1, + block.timestamp + ) + ) + ) + ); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(1, hash); + + ALEV2.Permit memory permit = ALEV2.Permit( + block.timestamp, + v, + r, + s + ); + + ALEV2.DBRHelper memory dbrData; + bytes memory swapData; + + vm.startPrank(pendleYTHolder); + IERC20(pendleYT).transfer( + userPk, + amountToWithdraw - IERC20(pendleYT).balanceOf(userPk) + ); + vm.stopPrank(); + + // Redeem PT and YT using all collateral (amountToWithdraw) (receiver is the ALE) + bytes + memory pendleRedeemData = hex"47f1de220000000000000000000000004df2eaa1658a220fdb415b9966a9ae7c3d16e24000000000000000000000000028e626b560f1faac01544770425e2de8fd179c790000000000000000000000000000000000000000000028465c6fc0ea0cf81d120000000000000000000000000000000000000000000000000000000000000080000000000000000000000000865377367054516e17014ccded1e7d814edc9ce40000000000000000000000000000000000000000000027fa43ed9377238787870000000000000000000000009d39a5de30e57443bff2a8307a4256c8797a3497000000000000000000000000d4f480965d2347d421f1bec7f545682e5ec2151d00000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000010000000000000000000000006131b5fae19ea4f9d964eac0408e4408b66337b50000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000008e4e21fd0e900000000000000000000000000000000000000000000000000000000000000200000000000000000000000006e4141d33021b52c91c28608403db4a0ffb50ec6000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000003c000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000009d39a5de30e57443bff2a8307a4256c8797a3497000000000000000000000000865377367054516e17014ccded1e7d814edc9ce4000000000000000000000000888888888889758f76e7103c6cbf23abbf58f946000000000000000000000000000000000000000000000000000000007fffffff00000000000000000000000000000000000000000000000000000000000002a000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000040d90ce491000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000100000000000000000000000000744793b5110f6ca9cc7cdfe1ce16677c3eb192ef0000000000000000000000009d39a5de30e57443bff2a8307a4256c8797a3497000000000000000000000000865377367054516e17014ccded1e7d814edc9ce400000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002276532d86fbae5830e9000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000002b30995f2f2f4cf000000000000293065044a5bb80000000000000000000000000000009d39a5de30e57443bff2a8307a4256c8797a3497000000000000000000000000865377367054516e17014ccded1e7d814edc9ce4000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000001e00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000888888888889758f76e7103c6cbf23abbf58f946000000000000000000000000000000000000000000002276532d86fbae5830e90000000000000000000000000000000000000000000028c6f35dd8f985851eb70000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000022000000000000000000000000000000000000000000000000000000000000000010000000000000000000000006e4141d33021b52c91c28608403db4a0ffb50ec60000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000002276532d86fbae5830e9000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028a7b22536f75726365223a2250656e646c65222c22416d6f756e74496e555344223a223139333937302e31313936353431353637222c22416d6f756e744f7574555344223a223139333835362e3133393735373338333437222c22526566657272616c223a22222c22466c616773223a302c22416d6f756e744f7574223a22313934353039373438353337383439303339323930333637222c2254696d657374616d70223a313735363239313032322c22526f7574654944223a2262636564663735322d356530632d343066642d626666322d6336356365393566303135613a30343637666361382d323034372d343339322d393363362d393936363465313662313535222c22496e74656772697479496e666f223a7b224b65794944223a2231222c225369676e6174757265223a22534b54494f3147475754784555487a6779583375645051447446705166453451727234396d7a56395356784258706d656e4e54495a75443650554e70384a583456335161307a4c6f4552754e63506a6f4359632b56755335306550555663706d303172637a6553653331307a383943753066774e4154742b714b457a4645566f616a44327274744e616f7a544462716a4f34586d476f30664e43704a786166374755436c6971376349643472354b4362302b30547869514174366a6667577053616f613051646f754332334b68776f506c446472612f7636474372346163595a7972734c7835354f55794a766951646f30326e766e727941764a346a466b4b74576433497933414863563248666c534a446961685168575776364974507744437a4b387079617974327a7558623276796d514c657477505954466654596569536e3372726b314955656970666e436f6a453462682f513d3d227d7d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"; + + uint256 debt = market.debts(userPk); + vm.startPrank(userPk); + IERC20(pendleYT).approve(address(helper), amountToWithdraw); + + ale.deleveragePosition( + debt, // dola redeemed to be deleveraged + address(market), + address(0), + amountToWithdraw, + swapData, + permit, + abi.encode(address(market), uint(100000), pendleRedeemData), + dbrData + ); + + assertEq(SimpleERC20Escrow(userPkEscrow).balance(), 0); + assertApproxEqRel( + DOLA.balanceOf(userPk), + 190695831899851999304282 - debt, + 0.01 ether + ); + assertEq(IERC20(pendleYT).balanceOf(userPk), 0); + assertEq(market.debts(userPk), 0); + assertEq(DOLA.balanceOf(address(ale)), 0); + } + + function test_AFTER_DEADLINE_deleveragePosition_Redeem_with_PT_and_YT_router() + public + { + test_leveragePosition_Mint_PT_and_YT_with_DOLA_router(); + + uint256 amountToWithdraw = SimpleERC20Escrow(userPkEscrow).balance(); + gibDBR(userPk, 1000000 ether); + vm.warp(block.timestamp + 180 days); + bytes32 hash = keccak256( + abi.encodePacked( + "\x19\x01", + market.DOMAIN_SEPARATOR(), + keccak256( + abi.encode( + keccak256( + "WithdrawOnBehalf(address caller,address from,uint256 amount,uint256 nonce,uint256 deadline)" + ), + address(ale), + userPk, + amountToWithdraw, + 1, + block.timestamp + ) + ) + ) + ); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(1, hash); + + ALEV2.Permit memory permit = ALEV2.Permit( + block.timestamp, + v, + r, + s + ); + + ALEV2.DBRHelper memory dbrData; + bytes memory swapData; + + vm.startPrank(pendleYTHolder); + IERC20(pendleYT).transfer( + userPk, + amountToWithdraw - IERC20(pendleYT).balanceOf(userPk) + ); + vm.stopPrank(); + // Redeem PT and YT using all collateral (amountToWithdraw) (receiver is the ALE) + bytes + memory pendleRedeemData = hex"47f1de220000000000000000000000004df2eaa1658a220fdb415b9966a9ae7c3d16e24000000000000000000000000028e626b560f1faac01544770425e2de8fd179c790000000000000000000000000000000000000000000028465c6fc0ea0cf81d120000000000000000000000000000000000000000000000000000000000000080000000000000000000000000865377367054516e17014ccded1e7d814edc9ce40000000000000000000000000000000000000000000027fa43ed9377238787870000000000000000000000009d39a5de30e57443bff2a8307a4256c8797a3497000000000000000000000000d4f480965d2347d421f1bec7f545682e5ec2151d00000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000010000000000000000000000006131b5fae19ea4f9d964eac0408e4408b66337b50000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000008e4e21fd0e900000000000000000000000000000000000000000000000000000000000000200000000000000000000000006e4141d33021b52c91c28608403db4a0ffb50ec6000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000003c000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000009d39a5de30e57443bff2a8307a4256c8797a3497000000000000000000000000865377367054516e17014ccded1e7d814edc9ce4000000000000000000000000888888888889758f76e7103c6cbf23abbf58f946000000000000000000000000000000000000000000000000000000007fffffff00000000000000000000000000000000000000000000000000000000000002a000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000040d90ce491000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000100000000000000000000000000744793b5110f6ca9cc7cdfe1ce16677c3eb192ef0000000000000000000000009d39a5de30e57443bff2a8307a4256c8797a3497000000000000000000000000865377367054516e17014ccded1e7d814edc9ce400000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002276532d86fbae5830e9000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000002b30995f2f2f4cf000000000000293065044a5bb80000000000000000000000000000009d39a5de30e57443bff2a8307a4256c8797a3497000000000000000000000000865377367054516e17014ccded1e7d814edc9ce4000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000001e00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000888888888889758f76e7103c6cbf23abbf58f946000000000000000000000000000000000000000000002276532d86fbae5830e90000000000000000000000000000000000000000000028c6f35dd8f985851eb70000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000022000000000000000000000000000000000000000000000000000000000000000010000000000000000000000006e4141d33021b52c91c28608403db4a0ffb50ec60000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000002276532d86fbae5830e9000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028a7b22536f75726365223a2250656e646c65222c22416d6f756e74496e555344223a223139333937302e31313936353431353637222c22416d6f756e744f7574555344223a223139333835362e3133393735373338333437222c22526566657272616c223a22222c22466c616773223a302c22416d6f756e744f7574223a22313934353039373438353337383439303339323930333637222c2254696d657374616d70223a313735363239313032322c22526f7574654944223a2262636564663735322d356530632d343066642d626666322d6336356365393566303135613a30343637666361382d323034372d343339322d393363362d393936363465313662313535222c22496e74656772697479496e666f223a7b224b65794944223a2231222c225369676e6174757265223a22534b54494f3147475754784555487a6779583375645051447446705166453451727234396d7a56395356784258706d656e4e54495a75443650554e70384a583456335161307a4c6f4552754e63506a6f4359632b56755335306550555663706d303172637a6553653331307a383943753066774e4154742b714b457a4645566f616a44327274744e616f7a544462716a4f34586d476f30664e43704a786166374755436c6971376349643472354b4362302b30547869514174366a6667577053616f613051646f754332334b68776f506c446472612f7636474372346163595a7972734c7835354f55794a766951646f30326e766e727941764a346a466b4b74576433497933414863563248666c534a446961685168575776364974507744437a4b387079617974327a7558623276796d514c657477505954466654596569536e3372726b314955656970666e436f6a453462682f513d3d227d7d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"; + + uint256 debt = market.debts(userPk); + vm.startPrank(userPk); + uint256 ytBalBefore = IERC20(pendleYT).balanceOf(userPk); + + ale.deleveragePosition( + debt, // dola redeemed to be deleveraged + address(market), + address(0), + amountToWithdraw, + swapData, + permit, + abi.encode(address(market), uint(100000), pendleRedeemData), + dbrData + ); + assertEq(IERC20(pendleYT).balanceOf(userPk), ytBalBefore); + } + + function test_deleveragePosition_Swap_PT_to_DOLA_router() public { + test_leveragePosition_Swap_DOLA_for_PT_router(); + + uint256 amountToWithdraw = SimpleERC20Escrow(userPkEscrow).balance(); + bytes32 hash = keccak256( + abi.encodePacked( + "\x19\x01", + market.DOMAIN_SEPARATOR(), + keccak256( + abi.encode( + keccak256( + "WithdrawOnBehalf(address caller,address from,uint256 amount,uint256 nonce,uint256 deadline)" + ), + address(ale), + userPk, + amountToWithdraw, + 1, + block.timestamp + ) + ) + ) + ); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(1, hash); + + ALEV2.Permit memory permit = ALEV2.Permit( + block.timestamp, + v, + r, + s + ); + + ALEV2.DBRHelper memory dbrData; + bytes memory swapData; + // Swap all collateral (amountToWithdraw) to DOLA (receiver is the ALE) + bytes + memory pendleSwapToDolaData = hex"594a88cc0000000000000000000000004df2eaa1658a220fdb415b9966a9ae7c3d16e240000000000000000000000000b6ac3d5da138918ac4e84441e924a20daa60dbdd0000000000000000000000000000000000000000000028ae82afbb987816ff5e00000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000ae0000000000000000000000000865377367054516e17014ccded1e7d814edc9ce40000000000000000000000000000000000000000000027742e6ef7cae7f0f0f00000000000000000000000009d39a5de30e57443bff2a8307a4256c8797a3497000000000000000000000000d4f480965d2347d421f1bec7f545682e5ec2151d00000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000010000000000000000000000006131b5fae19ea4f9d964eac0408e4408b66337b50000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000008e4e21fd0e900000000000000000000000000000000000000000000000000000000000000200000000000000000000000006e4141d33021b52c91c28608403db4a0ffb50ec6000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000003c000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000009d39a5de30e57443bff2a8307a4256c8797a3497000000000000000000000000865377367054516e17014ccded1e7d814edc9ce4000000000000000000000000888888888889758f76e7103c6cbf23abbf58f946000000000000000000000000000000000000000000000000000000007fffffff00000000000000000000000000000000000000000000000000000000000002a000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000040d90ce491000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000100000000000000000000000000744793b5110f6ca9cc7cdfe1ce16677c3eb192ef0000000000000000000000009d39a5de30e57443bff2a8307a4256c8797a3497000000000000000000000000865377367054516e17014ccded1e7d814edc9ce40000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000220290c5acc19627a044000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000002a9fbdc9d463de600000000000028a63f5b0ed10e0000000000000000000000000000009d39a5de30e57443bff2a8307a4256c8797a3497000000000000000000000000865377367054516e17014ccded1e7d814edc9ce4000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000001e00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000888888888889758f76e7103c6cbf23abbf58f94600000000000000000000000000000000000000000000220290c5acc19627a04400000000000000000000000000000000000000000000283e2f5cb511862e14790000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000022000000000000000000000000000000000000000000000000000000000000000010000000000000000000000006e4141d33021b52c91c28608403db4a0ffb50ec6000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000220290c5acc19627a044000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028b7b22536f75726365223a2250656e646c65222c22416d6f756e74496e555344223a223139313539322e3036333632393136353933222c22416d6f756e744f7574555344223a223139313033322e3736393031383639343236222c22526566657272616c223a22222c22466c616773223a302c22416d6f756e744f7574223a22313931393631333834303839393539393130303830353131222c2254696d657374616d70223a313735363239303334322c22526f7574654944223a2262303566623361382d623933632d346466632d383330342d3464336635653066613938363a30363562613464642d633239322d343065362d623163392d656561626435666362356335222c22496e74656772697479496e666f223a7b224b65794944223a2231222c225369676e6174757265223a2242426b6d31545635754e7956413036484e76356c64655168334c764a54757461635557585849693264356151355070466a616b574f613950576856536f4b48684e38313234675567614a64686b442b4e54514e4b4a46774a45726759483171744b72502f6e5367516474735636463078623036474c375a516a2b62784f4f6c436d4971576a72546477586d3573744c566d547433663379303441444475732f52716b442b786270363935455335356c2f3868574b394434582b4c7972366b71645571664931442f776e31374552742b453347394b526e63447a67595030584465706477354d68694661656e533538464a6e7878424e3677532b37304f467643365a744838376d6774316332393938303447574a326553716475624b356e636d374f6737776b69625770543249583854693532755456357a43496b666d5a49356c6a516962427a2b6f725747724a3168726258453067773d3d227d7d00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c9b3e2c3ec88b1b4c0cd853f4321000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000062000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000002c00000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000021e19e0c9bab240000004e71e5039748325c336f3705fdbef470cbb213f898cf2000e1eb4a18844353f0000000000000000000000000000000000000000000000000000000068af0bd2000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030000000000000000000000009d39a5de30e57443bff2a8307a4256c8797a349700000000000000000000000028e626b560f1faac01544770425e2de8fd179c79000000000000000000000000e530105324cf1722172a197e7624bd617edf2cc8000000000000000000000000e530105324cf1722172a197e7624bd617edf2cc800000000000000000000000000000000000000000000021e19e0c9bab240000000000000000000000000000000000000000000000000000001426c9cd06efe0f0000000000000000000000000000000000000000000000000c7d713b49da0000000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000041f5aeeee8d054ce67b905a98e6a7e540dbdf2cb8832af6400e123e9b8b1044ef85f8bac3f7bd9c3aa3c24f9ff8c3bd3600002af77ff73f1c06076461e8234a1be1b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000704f188c120bff71fbe020794dd64cb9004497950f0b7245ac038ff1556ad964acbd5957cf24408058b0000000000000000000000000000000000000000000000000000000068b04d50000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030000000000000000000000009d39a5de30e57443bff2a8307a4256c8797a349700000000000000000000000028e626b560f1faac01544770425e2de8fd179c79000000000000000000000000d550f576eba6911c27b578c886701688133d5708000000000000000000000000d550f576eba6911c27b578c886701688133d570800000000000000000000000000000000000000000000130ee8e71790444000000000000000000000000000000000000000000000000000000148e8465e9241490000000000000000000000000000000000000000000000000c7d713b49da000000000000000000000000000000000000000000000000000000000000000001800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004104533c3f4acdbb1f72df8a5904b18751c78413b233666297ebf1c9c6e6249b2b575887fbed27715bc746466566443a8af3572dba37ff138f82ae2984052b886e1b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"; + + uint256 debt = market.debts(address(userPk)); + vm.startPrank(userPk); + ale.deleveragePosition( + debt, // dola redeemed to be deleveraged (repay debt) + address(market), + address(0), + amountToWithdraw, + swapData, + permit, + abi.encode(address(market), uint(100000), pendleSwapToDolaData), + dbrData + ); + + assertEq(SimpleERC20Escrow(userPkEscrow).balance(), 0); + // Dola balance is equal to collateral sold for DOLA minus debt + assertEq(DOLA.balanceOf(userPk), 188282027755723644359069- debt); + assertEq(market.debts(address(userPk)), 0); + assertEq(DOLA.balanceOf(address(ale)), 0); + } + + function test_fail_AFTER_DEADLINE_deleveragePosition_Swap_PT_to_DOLA_router() + public + { + test_leveragePosition_Swap_DOLA_for_PT_router(); + + uint256 amountToWithdraw = SimpleERC20Escrow(userPkEscrow).balance(); + gibDBR(userPk, 1000000 ether); + vm.warp(block.timestamp + 180 days); + bytes32 hash = keccak256( + abi.encodePacked( + "\x19\x01", + market.DOMAIN_SEPARATOR(), + keccak256( + abi.encode( + keccak256( + "WithdrawOnBehalf(address caller,address from,uint256 amount,uint256 nonce,uint256 deadline)" + ), + address(ale), + userPk, + amountToWithdraw, + 1, + block.timestamp + ) + ) + ) + ); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(1, hash); + + ALEV2.Permit memory permit = ALEV2.Permit( + block.timestamp, + v, + r, + s + ); + + ALEV2.DBRHelper memory dbrData; + bytes memory swapData; + // Swap all collateral (amountToWithdraw) to DOLA (receiver is the ALE) + bytes + memory pendleSwapToDolaData = hex"594a88cc0000000000000000000000004df2eaa1658a220fdb415b9966a9ae7c3d16e240000000000000000000000000b6ac3d5da138918ac4e84441e924a20daa60dbdd0000000000000000000000000000000000000000000028ae82afbb987816ff5e00000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000ae0000000000000000000000000865377367054516e17014ccded1e7d814edc9ce40000000000000000000000000000000000000000000027742e6ef7cae7f0f0f00000000000000000000000009d39a5de30e57443bff2a8307a4256c8797a3497000000000000000000000000d4f480965d2347d421f1bec7f545682e5ec2151d00000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000010000000000000000000000006131b5fae19ea4f9d964eac0408e4408b66337b50000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000008e4e21fd0e900000000000000000000000000000000000000000000000000000000000000200000000000000000000000006e4141d33021b52c91c28608403db4a0ffb50ec6000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000003c000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000009d39a5de30e57443bff2a8307a4256c8797a3497000000000000000000000000865377367054516e17014ccded1e7d814edc9ce4000000000000000000000000888888888889758f76e7103c6cbf23abbf58f946000000000000000000000000000000000000000000000000000000007fffffff00000000000000000000000000000000000000000000000000000000000002a000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000040d90ce491000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000100000000000000000000000000744793b5110f6ca9cc7cdfe1ce16677c3eb192ef0000000000000000000000009d39a5de30e57443bff2a8307a4256c8797a3497000000000000000000000000865377367054516e17014ccded1e7d814edc9ce40000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000220290c5acc19627a044000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000002a9fbdc9d463de600000000000028a63f5b0ed10e0000000000000000000000000000009d39a5de30e57443bff2a8307a4256c8797a3497000000000000000000000000865377367054516e17014ccded1e7d814edc9ce4000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000001e00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000888888888889758f76e7103c6cbf23abbf58f94600000000000000000000000000000000000000000000220290c5acc19627a04400000000000000000000000000000000000000000000283e2f5cb511862e14790000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000022000000000000000000000000000000000000000000000000000000000000000010000000000000000000000006e4141d33021b52c91c28608403db4a0ffb50ec6000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000220290c5acc19627a044000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028b7b22536f75726365223a2250656e646c65222c22416d6f756e74496e555344223a223139313539322e3036333632393136353933222c22416d6f756e744f7574555344223a223139313033322e3736393031383639343236222c22526566657272616c223a22222c22466c616773223a302c22416d6f756e744f7574223a22313931393631333834303839393539393130303830353131222c2254696d657374616d70223a313735363239303334322c22526f7574654944223a2262303566623361382d623933632d346466632d383330342d3464336635653066613938363a30363562613464642d633239322d343065362d623163392d656561626435666362356335222c22496e74656772697479496e666f223a7b224b65794944223a2231222c225369676e6174757265223a2242426b6d31545635754e7956413036484e76356c64655168334c764a54757461635557585849693264356151355070466a616b574f613950576856536f4b48684e38313234675567614a64686b442b4e54514e4b4a46774a45726759483171744b72502f6e5367516474735636463078623036474c375a516a2b62784f4f6c436d4971576a72546477586d3573744c566d547433663379303441444475732f52716b442b786270363935455335356c2f3868574b394434582b4c7972366b71645571664931442f776e31374552742b453347394b526e63447a67595030584465706477354d68694661656e533538464a6e7878424e3677532b37304f467643365a744838376d6774316332393938303447574a326553716475624b356e636d374f6737776b69625770543249583854693532755456357a43496b666d5a49356c6a516962427a2b6f725747724a3168726258453067773d3d227d7d00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c9b3e2c3ec88b1b4c0cd853f4321000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000062000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000002c00000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000021e19e0c9bab240000004e71e5039748325c336f3705fdbef470cbb213f898cf2000e1eb4a18844353f0000000000000000000000000000000000000000000000000000000068af0bd2000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030000000000000000000000009d39a5de30e57443bff2a8307a4256c8797a349700000000000000000000000028e626b560f1faac01544770425e2de8fd179c79000000000000000000000000e530105324cf1722172a197e7624bd617edf2cc8000000000000000000000000e530105324cf1722172a197e7624bd617edf2cc800000000000000000000000000000000000000000000021e19e0c9bab240000000000000000000000000000000000000000000000000000001426c9cd06efe0f0000000000000000000000000000000000000000000000000c7d713b49da0000000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000041f5aeeee8d054ce67b905a98e6a7e540dbdf2cb8832af6400e123e9b8b1044ef85f8bac3f7bd9c3aa3c24f9ff8c3bd3600002af77ff73f1c06076461e8234a1be1b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000704f188c120bff71fbe020794dd64cb9004497950f0b7245ac038ff1556ad964acbd5957cf24408058b0000000000000000000000000000000000000000000000000000000068b04d50000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030000000000000000000000009d39a5de30e57443bff2a8307a4256c8797a349700000000000000000000000028e626b560f1faac01544770425e2de8fd179c79000000000000000000000000d550f576eba6911c27b578c886701688133d5708000000000000000000000000d550f576eba6911c27b578c886701688133d570800000000000000000000000000000000000000000000130ee8e71790444000000000000000000000000000000000000000000000000000000148e8465e9241490000000000000000000000000000000000000000000000000c7d713b49da000000000000000000000000000000000000000000000000000000000000000001800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004104533c3f4acdbb1f72df8a5904b18751c78413b233666297ebf1c9c6e6249b2b575887fbed27715bc746466566443a8af3572dba37ff138f82ae2984052b886e1b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"; + + uint256 debt = market.debts(address(userPk)); + + vm.startPrank(userPk); + vm.expectRevert(PendlePTHelper.PendleSwapFailed.selector); + ale.deleveragePosition( + debt, // dola redeemed to be deleveraged (repay debt) + address(market), + address(0), + amountToWithdraw, + swapData, + permit, + abi.encode(address(market), uint(100000), pendleSwapToDolaData), + dbrData + ); + } + + function test_deleveragePosition_sellDBR() public { + test_leveragePosition_Swap_DOLA_for_PT_router(); + + uint256 amountToWithdraw = SimpleERC20Escrow(userPkEscrow).balance(); + + uint256 debt = market.debts(address(userPk)); + + bytes32 hash = keccak256( + abi.encodePacked( + "\x19\x01", + market.DOMAIN_SEPARATOR(), + keccak256( + abi.encode( + keccak256( + "WithdrawOnBehalf(address caller,address from,uint256 amount,uint256 nonce,uint256 deadline)" + ), + address(ale), + userPk, + amountToWithdraw, + 1, + block.timestamp + ) + ) + ) + ); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(1, hash); + + ALEV2.Permit memory permit = ALEV2.Permit( + block.timestamp, + v, + r, + s + ); + + ALEV2.DBRHelper memory dbrData = ALEV2.DBRHelper( + dbr.balanceOf(userPk), + 10000, + 0 + ); // sell all DBR + bytes memory swapData; + // Swap all collateral (amountToWithdraw) to DOLA (receiver is the ALE) + bytes + memory pendleSwapToDolaData = hex"594a88cc0000000000000000000000004df2eaa1658a220fdb415b9966a9ae7c3d16e240000000000000000000000000b6ac3d5da138918ac4e84441e924a20daa60dbdd0000000000000000000000000000000000000000000028ae82afbb987816ff5e00000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000ae0000000000000000000000000865377367054516e17014ccded1e7d814edc9ce40000000000000000000000000000000000000000000027742e6ef7cae7f0f0f00000000000000000000000009d39a5de30e57443bff2a8307a4256c8797a3497000000000000000000000000d4f480965d2347d421f1bec7f545682e5ec2151d00000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000010000000000000000000000006131b5fae19ea4f9d964eac0408e4408b66337b50000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000008e4e21fd0e900000000000000000000000000000000000000000000000000000000000000200000000000000000000000006e4141d33021b52c91c28608403db4a0ffb50ec6000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000003c000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000009d39a5de30e57443bff2a8307a4256c8797a3497000000000000000000000000865377367054516e17014ccded1e7d814edc9ce4000000000000000000000000888888888889758f76e7103c6cbf23abbf58f946000000000000000000000000000000000000000000000000000000007fffffff00000000000000000000000000000000000000000000000000000000000002a000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000040d90ce491000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000100000000000000000000000000744793b5110f6ca9cc7cdfe1ce16677c3eb192ef0000000000000000000000009d39a5de30e57443bff2a8307a4256c8797a3497000000000000000000000000865377367054516e17014ccded1e7d814edc9ce40000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000220290c5acc19627a044000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000002a9fbdc9d463de600000000000028a63f5b0ed10e0000000000000000000000000000009d39a5de30e57443bff2a8307a4256c8797a3497000000000000000000000000865377367054516e17014ccded1e7d814edc9ce4000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000001e00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000888888888889758f76e7103c6cbf23abbf58f94600000000000000000000000000000000000000000000220290c5acc19627a04400000000000000000000000000000000000000000000283e2f5cb511862e14790000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000022000000000000000000000000000000000000000000000000000000000000000010000000000000000000000006e4141d33021b52c91c28608403db4a0ffb50ec6000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000220290c5acc19627a044000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028b7b22536f75726365223a2250656e646c65222c22416d6f756e74496e555344223a223139313539322e3036333632393136353933222c22416d6f756e744f7574555344223a223139313033322e3736393031383639343236222c22526566657272616c223a22222c22466c616773223a302c22416d6f756e744f7574223a22313931393631333834303839393539393130303830353131222c2254696d657374616d70223a313735363239303334322c22526f7574654944223a2262303566623361382d623933632d346466632d383330342d3464336635653066613938363a30363562613464642d633239322d343065362d623163392d656561626435666362356335222c22496e74656772697479496e666f223a7b224b65794944223a2231222c225369676e6174757265223a2242426b6d31545635754e7956413036484e76356c64655168334c764a54757461635557585849693264356151355070466a616b574f613950576856536f4b48684e38313234675567614a64686b442b4e54514e4b4a46774a45726759483171744b72502f6e5367516474735636463078623036474c375a516a2b62784f4f6c436d4971576a72546477586d3573744c566d547433663379303441444475732f52716b442b786270363935455335356c2f3868574b394434582b4c7972366b71645571664931442f776e31374552742b453347394b526e63447a67595030584465706477354d68694661656e533538464a6e7878424e3677532b37304f467643365a744838376d6774316332393938303447574a326553716475624b356e636d374f6737776b69625770543249583854693532755456357a43496b666d5a49356c6a516962427a2b6f725747724a3168726258453067773d3d227d7d00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c9b3e2c3ec88b1b4c0cd853f4321000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000062000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000002c00000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000021e19e0c9bab240000004e71e5039748325c336f3705fdbef470cbb213f898cf2000e1eb4a18844353f0000000000000000000000000000000000000000000000000000000068af0bd2000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030000000000000000000000009d39a5de30e57443bff2a8307a4256c8797a349700000000000000000000000028e626b560f1faac01544770425e2de8fd179c79000000000000000000000000e530105324cf1722172a197e7624bd617edf2cc8000000000000000000000000e530105324cf1722172a197e7624bd617edf2cc800000000000000000000000000000000000000000000021e19e0c9bab240000000000000000000000000000000000000000000000000000001426c9cd06efe0f0000000000000000000000000000000000000000000000000c7d713b49da0000000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000041f5aeeee8d054ce67b905a98e6a7e540dbdf2cb8832af6400e123e9b8b1044ef85f8bac3f7bd9c3aa3c24f9ff8c3bd3600002af77ff73f1c06076461e8234a1be1b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000704f188c120bff71fbe020794dd64cb9004497950f0b7245ac038ff1556ad964acbd5957cf24408058b0000000000000000000000000000000000000000000000000000000068b04d50000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030000000000000000000000009d39a5de30e57443bff2a8307a4256c8797a349700000000000000000000000028e626b560f1faac01544770425e2de8fd179c79000000000000000000000000d550f576eba6911c27b578c886701688133d5708000000000000000000000000d550f576eba6911c27b578c886701688133d570800000000000000000000000000000000000000000000130ee8e71790444000000000000000000000000000000000000000000000000000000148e8465e9241490000000000000000000000000000000000000000000000000c7d713b49da000000000000000000000000000000000000000000000000000000000000000001800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004104533c3f4acdbb1f72df8a5904b18751c78413b233666297ebf1c9c6e6249b2b575887fbed27715bc746466566443a8af3572dba37ff138f82ae2984052b886e1b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"; + + vm.startPrank(userPk); + dbr.approve(address(ale), dbr.balanceOf(userPk)); + ale.deleveragePosition( + debt, + address(market), + address(0), + amountToWithdraw, + swapData, + permit, + abi.encode(address(market), uint(100000), pendleSwapToDolaData), + dbrData + ); + + assertEq(SimpleERC20Escrow(userPkEscrow).balance(), 0); + + assertEq(dbr.balanceOf(userPk), 0); + // Dola balance is greater than collateral sold for DOLA minus debt because we also sold DBR + assertGt(DOLA.balanceOf(userPk), 188282027755723644359069 - debt); + assertEq(market.debts(address(userPk)), 0); + assertEq(DOLA.balanceOf(address(ale)), 0); + } + + function test_fail_InsufficientPT_after_swap() public { + _mintInitialDolaAmountToUser(); + + vm.prank(userPk); + vm.expectRevert(PendlePTHelper.InsufficientPT.selector); + helper.convertToCollateralAndDeposit( + initialDolaAmount, + userPk, + abi.encode( + address(market), + (initialDolaAmount * 1.1 ether) / 1 ether, + pendleDataInitial + ) + ); + } + + function test_fail_InsufficientPT_after_mint() public { + _mintInitialDolaAmountToUser(); + bytes + memory pendleMintData = hex"d0f423850000000000000000000000004809fe7d314c2ae5b2eb7fa19c1b166434d29141000000000000000000000000029d6247adb0a57138c62e3019c92d3dfc9c18400000000000000000000000000000000000000000000014873730979a6d2c1c8a0000000000000000000000000000000000000000000000000000000000000080000000000000000000000000865377367054516e17014ccded1e7d814edc9ce400000000000000000000000000000000000000000000152d02c7e14af68000000000000000000000000000009d39a5de30e57443bff2a8307a4256c8797a3497000000000000000000000000fe6228a3866426e96611ed7a3d0dee918244fcb300000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000060000000000000000000000006a000f20005980200259b80c5102003040001068000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ea4e3ead59e00000000000000000000000000c600b30fb0400701010f4b080409018b9006e0000000000000000000000000865377367054516e17014ccded1e7d814edc9ce40000000000000000000000009d39a5de30e57443bff2a8307a4256c8797a349700000000000000000000000000000000000000000000152d02c7e14af6800000000000000000000000000000000000000000000000001179b249655b0520d7980000000000000000000000000000000000000000000012040ee4bcf1a0ff8c7333931ebd147448b49293fd0e11563e0a0000000000000000000000000158b7c2000000000000000000000000888888888889758f76e7103c6cbf23abbf58f94600000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000160000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d0000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000d000000000000000000000000000000064000000000000000000000000000001900865377367054516e17014ccded1e7d814edc9ce40000006000000044ff00000000000000000000000000000000000000000000000000000000000000095ea7b300000000000000000000000016c6521dff6bab339122a0fe25a9116693265353ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff16c6521dff6bab339122a0fe25a9116693265353000005a0048400000000000300000000000000000000000000000000000000000000000000000000c872a3c5000000000000000000000000865377367054516e17014ccded1e7d814edc9ce40000000000000000000000008b83c4aa949254895507d09365229bc3a8c7f710000000000000000000000000a3931d71877c0e7a3148cb7eb4463524fec27fbd0000000000000000000000003cef1afc0e8324b57293a6e7ce663781bbefbb790000000000000000000000009d39a5de30e57443bff2a8307a4256c8797a3497000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000d8d726b7177a800000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000008b83c4aa949254895507d09365229bc3a8c7f7100000000000000000000000003cef1afc0e8324b57293a6e7ce663781bbefbb790000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006a000f20005980200259b80c51020030400010680000000000000000000000000000064000000000000000000000000000000e10865377367054516e17014ccded1e7d814edc9ce40000006000000044ff00000000000000000000000000000000000000000000000000000000000000095ea7b300000000000000000000000016c6521dff6bab339122a0fe25a9116693265353ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff16c6521dff6bab339122a0fe25a9116693265353000005a0048400000000000300000000000000000000000000000000000000000000000000000000c872a3c5000000000000000000000000865377367054516e17014ccded1e7d814edc9ce4000000000000000000000000ff17dab22f1e61078aba2623c89ce6110e878b3c0000000000000000000000000655977feb2f289a4ab78af67bab0d17aab84367000000000000000000000000d29f8980852c2c76fc3f6e96a7aa06e0bedcc1b10000000000000000000000009d39a5de30e57443bff2a8307a4256c8797a3497000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000079f905c6fd34e8000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000ff17dab22f1e61078aba2623c89ce6110e878b3c000000000000000000000000d29f8980852c2c76fc3f6e96a7aa06e0bedcc1b10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006a000f20005980200259b80c510200304000106800000000000000000000000000000000000000000000000000000000"; + vm.prank(userPk); + vm.expectRevert(PendlePTHelper.InsufficientPT.selector); + helper.convertToCollateral( + initialDolaAmount, + abi.encode(address(market), initialDolaAmount, pendleMintData) + ); + } + + function test_withdrawAndConvertFromCollateral_SWAP() public { + _mintInitialDolaAmountToUser(); + + vm.prank(userPk); + helper.convertToCollateralAndDeposit( + initialDolaAmount, + userPk, + abi.encode(address(market), 0, pendleDataInitial) + ); + + uint256 amountToWithdraw = SimpleERC20Escrow(userPkEscrow).balance(); + bytes32 hash = keccak256( + abi.encodePacked( + "\x19\x01", + market.DOMAIN_SEPARATOR(), + keccak256( + abi.encode( + keccak256( + "WithdrawOnBehalf(address caller,address from,uint256 amount,uint256 nonce,uint256 deadline)" + ), + address(helper), + userPk, + amountToWithdraw, + 0, + block.timestamp + ) + ) + ) + ); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(1, hash); + + IPendleHelper.Permit memory permit = IPendleHelper.Permit( + block.timestamp, + v, + r, + s + ); + + // Swap all collateral (amountToWithdraw) to DOLA (receiver is the User) + bytes + memory pendleSwapToDolaData = hex"594a88cc0000000000000000000000007e5f4552091a69125d5dfcb7b8c2659029395bdf000000000000000000000000b6ac3d5da138918ac4e84441e924a20daa60dbdd0000000000000000000000000000000000000000000015940b8e04a76675c7d200000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000ae0000000000000000000000000865377367054516e17014ccded1e7d814edc9ce40000000000000000000000000000000000000000000014ee96005f4e29da5a5a0000000000000000000000009d39a5de30e57443bff2a8307a4256c8797a3497000000000000000000000000d4f480965d2347d421f1bec7f545682e5ec2151d00000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000010000000000000000000000006131b5fae19ea4f9d964eac0408e4408b66337b50000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000008e4e21fd0e900000000000000000000000000000000000000000000000000000000000000200000000000000000000000006e4141d33021b52c91c28608403db4a0ffb50ec6000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000003c000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000009d39a5de30e57443bff2a8307a4256c8797a3497000000000000000000000000865377367054516e17014ccded1e7d814edc9ce4000000000000000000000000888888888889758f76e7103c6cbf23abbf58f946000000000000000000000000000000000000000000000000000000007fffffff00000000000000000000000000000000000000000000000000000000000002a000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000040d90ce491000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000100000000000000000000000000744793b5110f6ca9cc7cdfe1ce16677c3eb192ef0000000000000000000000009d39a5de30e57443bff2a8307a4256c8797a3497000000000000000000000000865377367054516e17014ccded1e7d814edc9ce40000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000120b32562617a94dcc0d00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000169d27625d782c20000000000001590f7a34aebaf0000000000000000000000000000009d39a5de30e57443bff2a8307a4256c8797a3497000000000000000000000000865377367054516e17014ccded1e7d814edc9ce4000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000001e00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000888888888889758f76e7103c6cbf23abbf58f94600000000000000000000000000000000000000000000120b32562617a94dcc0d000000000000000000000000000000000000000000001559c1f623c57c9c28f40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000022000000000000000000000000000000000000000000000000000000000000000010000000000000000000000006e4141d33021b52c91c28608403db4a0ffb50ec6000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000120b32562617a94dcc0d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028b7b22536f75726365223a2250656e646c65222c22416d6f756e74496e555344223a223130313432342e3535353232303537373639222c22416d6f756e744f7574555344223a223130313439332e3633393534393430333434222c22526566657272616c223a22222c22466c616773223a302c22416d6f756e744f7574223a22313031383433383731343735343031343130373430323233222c2254696d657374616d70223a313735363239303631372c22526f7574654944223a2237663330643562312d353332362d343437312d623838372d3738646537303966643262393a30333466666634392d373534622d346564362d626136612d383439313338383534326666222c22496e74656772697479496e666f223a7b224b65794944223a2231222c225369676e6174757265223a22624f7741633447655253574a6858773152522f48443479754c634756534c5463362b304773745a672f427a307a4d6951374f696234767a6c686378774b6572734f7831766e6c563330514259686b7a634c5a4c2f2f7541464d6d4d366579672f55667532643571515652484d6f383074623471434235494a4a2f51746d487a4c62465245536e34433734304739584b7464343831625a756479414e78376a6e355a70687651714b4b756d677a427233546e2b33725254637530647574595a53625769354f33704f6458434769394f6156354a326d3136395346667564595164654a30356d304b627648735264656a7a73666a69307935724a7351354b355133726a336f626d726f306a3370636e6f55356f733957384c36617744683770574f347270324464705862797537496d6a394a615065396863434546777a58476f3237636c366b6243342b497162635a505949392f344463773d3d227d7d00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c9b3e2c3ec88b1b4c0cd853f4321000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000003800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000021e19e0c9bab240000004e71e5039748325c336f3705fdbef470cbb213f898cf2000e1eb4a18844353f0000000000000000000000000000000000000000000000000000000068af0bd2000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030000000000000000000000009d39a5de30e57443bff2a8307a4256c8797a349700000000000000000000000028e626b560f1faac01544770425e2de8fd179c79000000000000000000000000e530105324cf1722172a197e7624bd617edf2cc8000000000000000000000000e530105324cf1722172a197e7624bd617edf2cc800000000000000000000000000000000000000000000021e19e0c9bab240000000000000000000000000000000000000000000000000000001426c9cd06efe0f0000000000000000000000000000000000000000000000000c7d713b49da0000000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000041f5aeeee8d054ce67b905a98e6a7e540dbdf2cb8832af6400e123e9b8b1044ef85f8bac3f7bd9c3aa3c24f9ff8c3bd3600002af77ff73f1c06076461e8234a1be1b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"; + assertEq(DOLA.balanceOf(userPk), 0); + + vm.startPrank(userPk); + uint256 dolaAmount = helper.withdrawAndConvertFromCollateral( + amountToWithdraw, + userPk, + permit, + abi.encode(address(market), 99000 ether, pendleSwapToDolaData) + ); + assertEq(DOLA.balanceOf(userPk), dolaAmount); + } + + function test_withdrawAndConvertFromCollateral_REDEEM() public { + _mintInitialDolaAmountToUser(); + + vm.prank(userPk); + helper.convertToCollateralAndDeposit( + initialDolaAmount, + userPk, + abi.encode(address(market), 0, pendleDataInitial) + ); + + gibDBR(userPk, 20000 ether); + + uint256 amountToWithdraw = SimpleERC20Escrow(userPkEscrow).balance(); + bytes32 hash = keccak256( + abi.encodePacked( + "\x19\x01", + market.DOMAIN_SEPARATOR(), + keccak256( + abi.encode( + keccak256( + "WithdrawOnBehalf(address caller,address from,uint256 amount,uint256 nonce,uint256 deadline)" + ), + address(helper), + userPk, + amountToWithdraw, + 0, + block.timestamp + ) + ) + ) + ); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(1, hash); + + IPendleHelper.Permit memory permit = IPendleHelper.Permit( + block.timestamp, + v, + r, + s + ); + + // Swap all collateral (amountToWithdraw) to DOLA (receiver is the User) + bytes + memory pendleRedeemToDolaData = hex"47f1de220000000000000000000000007e5f4552091a69125d5dfcb7b8c2659029395bdf00000000000000000000000028e626b560f1faac01544770425e2de8fd179c790000000000000000000000000000000000000000000015940b8e04a76675c7d20000000000000000000000000000000000000000000000000000000000000080000000000000000000000000865377367054516e17014ccded1e7d814edc9ce400000000000000000000000000000000000000000000156bc4ed7a55ea1696960000000000000000000000009d39a5de30e57443bff2a8307a4256c8797a3497000000000000000000000000d4f480965d2347d421f1bec7f545682e5ec2151d00000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000010000000000000000000000006131b5fae19ea4f9d964eac0408e4408b66337b50000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000008e4e21fd0e900000000000000000000000000000000000000000000000000000000000000200000000000000000000000006e4141d33021b52c91c28608403db4a0ffb50ec6000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000003c000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000009d39a5de30e57443bff2a8307a4256c8797a3497000000000000000000000000865377367054516e17014ccded1e7d814edc9ce4000000000000000000000000888888888889758f76e7103c6cbf23abbf58f946000000000000000000000000000000000000000000000000000000007fffffff00000000000000000000000000000000000000000000000000000000000002a000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000040d90ce491000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000100000000000000000000000000744793b5110f6ca9cc7cdfe1ce16677c3eb192ef0000000000000000000000009d39a5de30e57443bff2a8307a4256c8797a3497000000000000000000000000865377367054516e17014ccded1e7d814edc9ce400000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001276c9bad6bdbdcb0c3200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000172465506058d470000000000001611f1aedb22370000000000000000000000000000009d39a5de30e57443bff2a8307a4256c8797a3497000000000000000000000000865377367054516e17014ccded1e7d814edc9ce4000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000001e00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000888888888889758f76e7103c6cbf23abbf58f946000000000000000000000000000000000000000000001276c9bad6bdbdcb0c320000000000000000000000000000000000000000000015d971d381e6fe2147ad0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000022000000000000000000000000000000000000000000000000000000000000000010000000000000000000000006e4141d33021b52c91c28608403db4a0ffb50ec60000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000001276c9bad6bdbdcb0c32000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028b7b22536f75726365223a2250656e646c65222c22416d6f756e74496e555344223a223130343036342e3032383030323538363037222c22416d6f756e744f7574555344223a223130333734342e3438333231353538303837222c22526566657272616c223a22222c22466c616773223a302c22416d6f756e744f7574223a22313034323233303732333730313334333433343833333931222c2254696d657374616d70223a313735363239313237322c22526f7574654944223a2236303564613762622d343132332d343830382d386632632d6133383035396133636262613a36663238383862372d306533392d346266632d623035372d643561303436373133363933222c22496e74656772697479496e666f223a7b224b65794944223a2231222c225369676e6174757265223a22584730686f64496b507275794e30554c362f6a3476413074737343493876752f413957627a7a7561526569464d71473463446e4a774f354f4a555847564a333139654a776669754f69685453464363716841497470656d6a78444442683145567a692f456d6d5a5745657a79417a5955436c487139787543726670725670346533384150416633363662327566335835314d306255415a617a66584932302b736636724b76545a2f594c6b36513170314e6966665a644c30656470744556424746656c694d2b786150634a4c377a69526654513746786e416f3262626b7139346c6a4e7278774470793772426573656432342f6f546939355478774e527a6c6f70304f505749756b564d336c626a7a7561696471654651524a4a4f72386a487776556252363032724e544c4c53357350514c6676376c5869336c6f70746d67646a6c485567456c7970474f414c4a54433471784749513d3d227d7d00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"; + vm.startPrank(pendleYTHolder); + IERC20(pendleYT).transfer(userPk, amountToWithdraw); + vm.stopPrank(); + + assertEq(DOLA.balanceOf(userPk), 0); + vm.startPrank(userPk); + IERC20(pendleYT).approve(address(helper), amountToWithdraw); + uint256 dolaAmount = helper.withdrawAndConvertFromCollateral( + amountToWithdraw, + userPk, + permit, + abi.encode( + address(market), + (initialDolaAmount * 98) / 100, + pendleRedeemToDolaData + ) + ); + assertEq(DOLA.balanceOf(userPk), dolaAmount); + assertEq(IERC20(pendleYT).balanceOf(userPk), 0); + } + + function test_withdrawAndConvertFromCollateral_REDEEM_AFTER_DEADLINE() + public + { + _mintInitialDolaAmountToUser(); + + vm.prank(userPk); + helper.convertToCollateralAndDeposit( + initialDolaAmount, + userPk, + abi.encode(address(market), 0, pendleDataInitial) + ); + + gibDBR(userPk, 1000000 ether); + + uint256 amountToWithdraw = SimpleERC20Escrow(userPkEscrow).balance(); + vm.warp(block.timestamp + 180 days); + bytes32 hash = keccak256( + abi.encodePacked( + "\x19\x01", + market.DOMAIN_SEPARATOR(), + keccak256( + abi.encode( + keccak256( + "WithdrawOnBehalf(address caller,address from,uint256 amount,uint256 nonce,uint256 deadline)" + ), + address(helper), + userPk, + amountToWithdraw, + 0, + block.timestamp + ) + ) + ) + ); + (uint8 v, bytes32 r, bytes32 s) = vm.sign(1, hash); + + IPendleHelper.Permit memory permit = IPendleHelper.Permit( + block.timestamp, + v, + r, + s + ); + + // Swap all collateral (amountToWithdraw) to DOLA (receiver is the User) + bytes + memory pendleRedeemToDolaData = hex"47f1de220000000000000000000000007e5f4552091a69125d5dfcb7b8c2659029395bdf00000000000000000000000028e626b560f1faac01544770425e2de8fd179c790000000000000000000000000000000000000000000015940b8e04a76675c7d20000000000000000000000000000000000000000000000000000000000000080000000000000000000000000865377367054516e17014ccded1e7d814edc9ce400000000000000000000000000000000000000000000156bc4ed7a55ea1696960000000000000000000000009d39a5de30e57443bff2a8307a4256c8797a3497000000000000000000000000d4f480965d2347d421f1bec7f545682e5ec2151d00000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000010000000000000000000000006131b5fae19ea4f9d964eac0408e4408b66337b50000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000008e4e21fd0e900000000000000000000000000000000000000000000000000000000000000200000000000000000000000006e4141d33021b52c91c28608403db4a0ffb50ec6000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000003c000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000009d39a5de30e57443bff2a8307a4256c8797a3497000000000000000000000000865377367054516e17014ccded1e7d814edc9ce4000000000000000000000000888888888889758f76e7103c6cbf23abbf58f946000000000000000000000000000000000000000000000000000000007fffffff00000000000000000000000000000000000000000000000000000000000002a000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000040d90ce491000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000100000000000000000000000000744793b5110f6ca9cc7cdfe1ce16677c3eb192ef0000000000000000000000009d39a5de30e57443bff2a8307a4256c8797a3497000000000000000000000000865377367054516e17014ccded1e7d814edc9ce400000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001276c9bad6bdbdcb0c3200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000172465506058d470000000000001611f1aedb22370000000000000000000000000000009d39a5de30e57443bff2a8307a4256c8797a3497000000000000000000000000865377367054516e17014ccded1e7d814edc9ce4000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001a000000000000000000000000000000000000000000000000000000000000001e00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000888888888889758f76e7103c6cbf23abbf58f946000000000000000000000000000000000000000000001276c9bad6bdbdcb0c320000000000000000000000000000000000000000000015d971d381e6fe2147ad0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000022000000000000000000000000000000000000000000000000000000000000000010000000000000000000000006e4141d33021b52c91c28608403db4a0ffb50ec60000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000001276c9bad6bdbdcb0c32000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028b7b22536f75726365223a2250656e646c65222c22416d6f756e74496e555344223a223130343036342e3032383030323538363037222c22416d6f756e744f7574555344223a223130333734342e3438333231353538303837222c22526566657272616c223a22222c22466c616773223a302c22416d6f756e744f7574223a22313034323233303732333730313334333433343833333931222c2254696d657374616d70223a313735363239313237322c22526f7574654944223a2236303564613762622d343132332d343830382d386632632d6133383035396133636262613a36663238383862372d306533392d346266632d623035372d643561303436373133363933222c22496e74656772697479496e666f223a7b224b65794944223a2231222c225369676e6174757265223a22584730686f64496b507275794e30554c362f6a3476413074737343493876752f413957627a7a7561526569464d71473463446e4a774f354f4a555847564a333139654a776669754f69685453464363716841497470656d6a78444442683145567a692f456d6d5a5745657a79417a5955436c487139787543726670725670346533384150416633363662327566335835314d306255415a617a66584932302b736636724b76545a2f594c6b36513170314e6966665a644c30656470744556424746656c694d2b786150634a4c377a69526654513746786e416f3262626b7139346c6a4e7278774470793772426573656432342f6f546939355478774e527a6c6f70304f505749756b564d336c626a7a7561696471654651524a4a4f72386a487776556252363032724e544c4c53357350514c6676376c5869336c6f70746d67646a6c485567456c7970474f414c4a54433471784749513d3d227d7d00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"; + vm.startPrank(pendleYTHolder); + IERC20(pendleYT).transfer(userPk, amountToWithdraw); + vm.stopPrank(); + + assertEq(DOLA.balanceOf(userPk), 0); + vm.startPrank(userPk); + IERC20(pendleYT).approve(address(helper), amountToWithdraw); + + helper.withdrawAndConvertFromCollateral( + amountToWithdraw, + userPk, + permit, + abi.encode( + address(market), + (initialDolaAmount * 98) / 100, + pendleRedeemToDolaData + ) + ); + assertGt(DOLA.balanceOf(userPk), (initialDolaAmount * 98) / 100); + // Didn't transfer token even if approval granted because after maturity + assertEq(IERC20(pendleYT).balanceOf(userPk), amountToWithdraw); + } + function test_Access_Control_convertToCollateral_ALE() public { + vm.expectRevert(PendlePTHelper.NotALE.selector); + helper.convertToCollateral( + userPk, + initialDolaAmount, + abi.encode(address(market), initialDolaAmount, pendleDataInitial) + ); + } + + function test_Access_Control_convertFromCollateral_ALE() public { + vm.expectRevert(PendlePTHelper.NotALE.selector); + helper.convertFromCollateral( + userPk, + initialDolaAmount, + abi.encode(address(market), initialDolaAmount, pendleDataInitial) + ); + } + + function test_updateMarketHelper_if_helper_not_address_zero() public { + vm.prank(gov); + ale.updateMarketHelper(address(market), address(1)); + (, , IPendleHelper helper, ) = ale.markets(address(market)); + assertEq(address(helper), address(1)); + } + + function test_updateMarketHelper_if_market_not_set() public { + vm.expectRevert( + abi.encodeWithSelector(ALEV2.MarketNotSet.selector, address(2)) + ); + vm.prank(gov); + ale.updateMarketHelper(address(2), address(1)); + } + + function test_updateMarketHelper_fails_if_helper_not_set() public { + vm.expectRevert(ALEV2.InvalidHelperAddress.selector); + vm.prank(gov); + ale.updateMarketHelper(address(market), address(0)); + } + + function _getMaxBorrowAmount( + uint amountCollat + ) internal view returns (uint) { + return + (amountCollat * + oracle.viewPrice(address(pendlePT), 0) * + market.collateralFactorBps()) / + 10_000 / + 1e18; + } +} diff --git a/test/util/aleTests/ALEPendlePTUSDe29May25.t.sol b/test/util/aleTests/ALEPendlePTsUSDe29May25.t.sol similarity index 99% rename from test/util/aleTests/ALEPendlePTUSDe29May25.t.sol rename to test/util/aleTests/ALEPendlePTsUSDe29May25.t.sol index 46d8ee3..a1f8bcb 100644 --- a/test/util/aleTests/ALEPendlePTUSDe29May25.t.sol +++ b/test/util/aleTests/ALEPendlePTsUSDe29May25.t.sol @@ -13,7 +13,7 @@ import {SimpleERC20Escrow} from "src/escrows/SimpleERC20Escrow.sol"; DOLA 0x865377367054516e17014CcdED1e7d814EDC9ce4 address pendlePT = 0xb7de5dFCb74d25c2f21841fbd6230355C50d9308 */ -contract ALEV2PTUSDe29May25Test is PendlePTsUSDe29May25MarketForkTest { +contract ALEV2PTsUSDe29May25Test is PendlePTsUSDe29May25MarketForkTest { ALEV2 ale; address userPk = vm.addr(1); PendlePTHelper helper; diff --git a/test/util/aleTests/ALEPendlePTUSDe31July25.t.sol b/test/util/aleTests/ALEPendlePTsUSDe31July25.t.sol similarity index 99% rename from test/util/aleTests/ALEPendlePTUSDe31July25.t.sol rename to test/util/aleTests/ALEPendlePTsUSDe31July25.t.sol index fe075de..f9484f8 100644 --- a/test/util/aleTests/ALEPendlePTUSDe31July25.t.sol +++ b/test/util/aleTests/ALEPendlePTsUSDe31July25.t.sol @@ -13,7 +13,7 @@ import {SimpleERC20Escrow} from "src/escrows/SimpleERC20Escrow.sol"; DOLA 0x865377367054516e17014CcdED1e7d814EDC9ce4 pendlePT 0x3b3fB9C57858EF816833dC91565EFcd85D96f634; */ -contract ALEV2PTUSDe31July25Test is PendlePTsUSDe31July25MarketForkTest { +contract ALEV2PTsUSDe31July25Test is PendlePTsUSDe31July25MarketForkTest { ALEV2 ale; address userPk = vm.addr(1); PendlePTHelper helper; diff --git a/test/util/aleTests/ALEPendlePTUSDeMock.t.sol b/test/util/aleTests/ALEPendlePTsUSDeMock.t.sol similarity index 99% rename from test/util/aleTests/ALEPendlePTUSDeMock.t.sol rename to test/util/aleTests/ALEPendlePTsUSDeMock.t.sol index 06d2c0f..43b8c34 100644 --- a/test/util/aleTests/ALEPendlePTUSDeMock.t.sol +++ b/test/util/aleTests/ALEPendlePTsUSDeMock.t.sol @@ -10,7 +10,7 @@ interface IFlashMinter { function setMaxFlashLimit(uint256 _maxFlashLimit) external; } -contract ALEV2PTUSDeMockTest is PendlePTsUSDe27Mar25MarketForkTest { +contract ALEV2PTsUSDeMockTest is PendlePTsUSDe27Mar25MarketForkTest { MockPendleRouter.ApproxParams emptyApprox; MockPendleRouter.TokenInput emptyTokenInput; MockPendleRouter.TokenOutput emptyTokenOutput;