From 4b85a1e1b2bf526fee180c5354df49cab3d162b0 Mon Sep 17 00:00:00 2001 From: Trevor Richard Date: Thu, 8 Aug 2024 12:38:27 +0000 Subject: [PATCH] add beefy silo weth vault integration tests --- .../beefy/BeefyOpWethInEzethSilo.t.sol | 85 +++++++++++++++++++ .../beefy/BeefyOpWethInWstethSilo.t.sol | 85 +++++++++++++++++++ 2 files changed, 170 insertions(+) create mode 100644 test/integration/beefy/BeefyOpWethInEzethSilo.t.sol create mode 100644 test/integration/beefy/BeefyOpWethInWstethSilo.t.sol diff --git a/test/integration/beefy/BeefyOpWethInEzethSilo.t.sol b/test/integration/beefy/BeefyOpWethInEzethSilo.t.sol new file mode 100644 index 0000000..335fc72 --- /dev/null +++ b/test/integration/beefy/BeefyOpWethInEzethSilo.t.sol @@ -0,0 +1,85 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.24; + +import { BaseIntegration, IERC20, IERC4626 } from "../BaseIntegration.t.sol"; + +contract BeefyOpWethInEzethSiloIntegrationTest is BaseIntegration { + uint256 fork; + uint256 forkBlock = 123760428; + uint256 forkBlockTimestamp = 1723119633; + + address internal _beefyWrapper = address(0x182be93E1C0C4d305fe43bD093292F21fd679797); + + address internal _asset = address(0x4200000000000000000000000000000000000006); + address internal _assetWhale = address(0x86Bb63148d17d445Ed5398ef26Aa05Bf76dD5b59); + address internal _yieldVault; + address internal _mooVault = address(0xe50d9121d1fefcEFE720731C805C5B6E6B1FC779); + address internal _mooYieldSource = address(0xc1EB34965346D959115b93024c99F3F8eD701DA8); + address internal _siloYieldToken = address(0x9f3f998f52dda45D83234cF3A29995C391dB2b16); + + /* ============ setup ============ */ + + function setUpUnderlyingAsset() public virtual override returns (IERC20 asset, uint8 decimals, uint256 approxAssetUsdExchangeRate) { + return (IERC20(_asset), 18, 3000e18); + } + + function setUpYieldVault() public virtual override returns (IERC4626) { + (bool success, bytes memory data) = _beefyWrapper.call(abi.encodeWithSignature("clone(address)", _mooVault)); + require(success, "beefy vault wrapper failed"); + (_yieldVault) = abi.decode(data, (address)); + return IERC4626(_yieldVault); + } + + function setUpFork() public virtual override { + fork = vm.createFork(vm.rpcUrl("optimism"), forkBlock); + vm.selectFork(fork); + vm.warp(forkBlockTimestamp); + } + + function beforeSetup() public virtual override { + lowGasPriceEstimate = 0.05 gwei; // just L2 gas, we ignore L1 costs for a super low estimate + assetPrecisionLoss = 1; // additional rounding errors + } + + function afterSetup() public virtual override { } + + /* ============ helpers to override ============ */ + + /// @dev The max amount of assets than can be dealt. + function maxDeal() public virtual override returns (uint256) { + return underlyingAsset.balanceOf(_assetWhale); + } + + /// @dev May revert if the amount requested exceeds the amount available to deal. + function dealAssets(address to, uint256 amount) public virtual override prankception(_assetWhale) { + underlyingAsset.transfer(to, amount); + } + + /// @dev Accrues yield by letting time pass and triggering multiple yield accruals + function _accrueYield() internal virtual override prankception(_assetWhale) { + // yield accrues on deposit / withdraw so we can do a deposit and withdraw to the yield vault directly to trigger some yield accrual + uint256 amount = 10 ** assetDecimals; // some small amount of assets + underlyingAsset.approve(_yieldVault, amount); + yieldVault.deposit(amount, _assetWhale); + vm.warp(block.timestamp + 1 days); // let 1 day pass by + uint256 maxRedeem = yieldVault.maxRedeem(_assetWhale); + yieldVault.redeem(maxRedeem, _assetWhale, _assetWhale); + + // we also call a deposit directly on the moo vault to ensure it triggers a yield accrual + underlyingAsset.approve(_mooVault, amount); + (bool success,) = _mooVault.call(abi.encodeWithSignature("deposit(uint256)", amount)); + assertEq(success, true, "moo vault deposit success"); + } + + /// @dev Simulates loss by sending yield-bearing tokens out of the yield source and re-depositing some assets to trigger an update + function _simulateLoss() internal virtual override prankception(_mooYieldSource) { + IERC20(_siloYieldToken).transfer(_assetWhale, IERC20(_siloYieldToken).balanceOf(_mooYieldSource) / 2); + startPrank(alice); + uint256 amount = 10 ** assetDecimals; + dealAssets(alice, amount); + underlyingAsset.approve(_yieldVault, amount); + yieldVault.deposit(amount, alice); + stopPrank(); + } + +} \ No newline at end of file diff --git a/test/integration/beefy/BeefyOpWethInWstethSilo.t.sol b/test/integration/beefy/BeefyOpWethInWstethSilo.t.sol new file mode 100644 index 0000000..d1cc61f --- /dev/null +++ b/test/integration/beefy/BeefyOpWethInWstethSilo.t.sol @@ -0,0 +1,85 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.24; + +import { BaseIntegration, IERC20, IERC4626 } from "../BaseIntegration.t.sol"; + +contract BeefyOpWethInWstethSiloIntegrationTest is BaseIntegration { + uint256 fork; + uint256 forkBlock = 123760428; + uint256 forkBlockTimestamp = 1723119633; + + address internal _beefyWrapper = address(0x182be93E1C0C4d305fe43bD093292F21fd679797); + + address internal _asset = address(0x4200000000000000000000000000000000000006); + address internal _assetWhale = address(0x86Bb63148d17d445Ed5398ef26Aa05Bf76dD5b59); + address internal _yieldVault; + address internal _mooVault = address(0x9F18a883209095CB3a5E600BBAa22be3F0f8880a); + address internal _mooYieldSource = address(0xc2c4229FD4357eCc0D11c919e311A138F973d829); + address internal _siloYieldToken = address(0x633De586a3e4764f63B9ceF97F8c04d3b1d9895e); + + /* ============ setup ============ */ + + function setUpUnderlyingAsset() public virtual override returns (IERC20 asset, uint8 decimals, uint256 approxAssetUsdExchangeRate) { + return (IERC20(_asset), 18, 3000e18); + } + + function setUpYieldVault() public virtual override returns (IERC4626) { + (bool success, bytes memory data) = _beefyWrapper.call(abi.encodeWithSignature("clone(address)", _mooVault)); + require(success, "beefy vault wrapper failed"); + (_yieldVault) = abi.decode(data, (address)); + return IERC4626(_yieldVault); + } + + function setUpFork() public virtual override { + fork = vm.createFork(vm.rpcUrl("optimism"), forkBlock); + vm.selectFork(fork); + vm.warp(forkBlockTimestamp); + } + + function beforeSetup() public virtual override { + lowGasPriceEstimate = 0.05 gwei; // just L2 gas, we ignore L1 costs for a super low estimate + assetPrecisionLoss = 1; // additional rounding errors + } + + function afterSetup() public virtual override { } + + /* ============ helpers to override ============ */ + + /// @dev The max amount of assets than can be dealt. + function maxDeal() public virtual override returns (uint256) { + return underlyingAsset.balanceOf(_assetWhale); + } + + /// @dev May revert if the amount requested exceeds the amount available to deal. + function dealAssets(address to, uint256 amount) public virtual override prankception(_assetWhale) { + underlyingAsset.transfer(to, amount); + } + + /// @dev Accrues yield by letting time pass and triggering multiple yield accruals + function _accrueYield() internal virtual override prankception(_assetWhale) { + // yield accrues on deposit / withdraw so we can do a deposit and withdraw to the yield vault directly to trigger some yield accrual + uint256 amount = 10 ** assetDecimals; // some small amount of assets + underlyingAsset.approve(_yieldVault, amount); + yieldVault.deposit(amount, _assetWhale); + vm.warp(block.timestamp + 1 days); // let 1 day pass by + uint256 maxRedeem = yieldVault.maxRedeem(_assetWhale); + yieldVault.redeem(maxRedeem, _assetWhale, _assetWhale); + + // we also call a deposit directly on the moo vault to ensure it triggers a yield accrual + underlyingAsset.approve(_mooVault, amount); + (bool success,) = _mooVault.call(abi.encodeWithSignature("deposit(uint256)", amount)); + assertEq(success, true, "moo vault deposit success"); + } + + /// @dev Simulates loss by sending yield-bearing tokens out of the yield source and re-depositing some assets to trigger an update + function _simulateLoss() internal virtual override prankception(_mooYieldSource) { + IERC20(_siloYieldToken).transfer(_assetWhale, IERC20(_siloYieldToken).balanceOf(_mooYieldSource) / 2); + startPrank(alice); + uint256 amount = 10 ** assetDecimals; + dealAssets(alice, amount); + underlyingAsset.approve(_yieldVault, amount); + yieldVault.deposit(amount, alice); + stopPrank(); + } + +} \ No newline at end of file