From 329a9d053673b749969603d519821a39c7d82565 Mon Sep 17 00:00:00 2001 From: Cash Baller Date: Tue, 26 Mar 2024 18:23:28 -0500 Subject: [PATCH 01/21] First step, migrated open long test cases for stETH to testing suite --- test/instances/steth/StETHHyperdrive.t.sol | 97 ++- test/utils/InstanceTestV2.sol | 648 +++++++++++++++++++++ 2 files changed, 742 insertions(+), 3 deletions(-) create mode 100644 test/utils/InstanceTestV2.sol diff --git a/test/instances/steth/StETHHyperdrive.t.sol b/test/instances/steth/StETHHyperdrive.t.sol index 0c0cd3d5e..6264a4a80 100644 --- a/test/instances/steth/StETHHyperdrive.t.sol +++ b/test/instances/steth/StETHHyperdrive.t.sol @@ -19,11 +19,11 @@ import { FixedPointMath, ONE } from "contracts/src/libraries/FixedPointMath.sol" import { HyperdriveMath } from "contracts/src/libraries/HyperdriveMath.sol"; import { ERC20ForwarderFactory } from "contracts/src/token/ERC20ForwarderFactory.sol"; import { ERC20Mintable } from "contracts/test/ERC20Mintable.sol"; -import { InstanceTest } from "test/utils/InstanceTest.sol"; +import { InstanceTestV2 } from "test/utils/InstanceTestV2.sol"; import { HyperdriveUtils } from "test/utils/HyperdriveUtils.sol"; import { Lib } from "test/utils/Lib.sol"; -contract StETHHyperdriveTest is InstanceTest { +contract StETHHyperdriveTest is InstanceTestV2 { using FixedPointMath for uint256; using Lib for *; using stdStorage for StdStorage; @@ -54,7 +54,7 @@ contract StETHHyperdriveTest is InstanceTest { ); /// @dev Instantiates the Instance testing suite with the configuration. - constructor() InstanceTest(__testConfig) {} + constructor() InstanceTestV2(__testConfig) {} /// @dev Forge function that is invoked to setup the testing environment. function setUp() public override __mainnet_fork(17_376_154) { @@ -64,6 +64,16 @@ contract StETHHyperdriveTest is InstanceTest { /// Overrides /// + function getSupply() internal override returns (uint256, uint256) { + return (LIDO.getTotalPooledEther(), LIDO.getTotalShares()); + } + + function getTokenBalances( + address account + ) internal view override returns (uint256, uint256) { + return (LIDO.sharesOf(account), LIDO.balanceOf(account)); + } + /// @dev Converts base amount to the equivalent about in stETH. function convertToShares( uint256 baseAmount @@ -91,6 +101,87 @@ contract StETHHyperdriveTest is InstanceTest { ); } + function _verifyDeposit( + address trader, + uint256 amountPaid, + bool asBase, + uint256 totalBaseBefore, + uint256 totalSharesBefore, + AccountBalances2 memory traderBalancesBefore, + AccountBalances2 memory hyperdriveBalancesBefore + ) internal override { + if (asBase) { + // Ensure that the amount of pooled ether increased by the base paid. + assertEq(LIDO.getTotalPooledEther(), totalBaseBefore + amountPaid); + + // Ensure that the ETH balances were updated correctly. + assertEq( + address(hyperdrive).balance, + hyperdriveBalancesBefore.ETHBalance + ); + assertEq(bob.balance, traderBalancesBefore.ETHBalance - amountPaid); + + // Ensure that the stETH balances were updated correctly. + assertApproxEqAbs( + LIDO.balanceOf(address(hyperdrive)), + hyperdriveBalancesBefore.baseBalance + amountPaid, + 1 + ); + assertEq(LIDO.balanceOf(trader), traderBalancesBefore.baseBalance); + + // Ensure that the stETH shares were updated correctly. + uint256 expectedShares = amountPaid.mulDivDown( + totalSharesBefore, + totalBaseBefore + ); + assertEq(LIDO.getTotalShares(), totalSharesBefore + expectedShares); + assertEq( + LIDO.sharesOf(address(hyperdrive)), + hyperdriveBalancesBefore.sharesBalance + expectedShares + ); + assertEq(LIDO.sharesOf(bob), traderBalancesBefore.sharesBalance); + } else { + // Ensure that the amount of pooled ether stays the same. + assertEq(LIDO.getTotalPooledEther(), totalBaseBefore); + + // Ensure that the ETH balances were updated correctly. + assertEq( + address(hyperdrive).balance, + hyperdriveBalancesBefore.ETHBalance + ); + assertEq(trader.balance, traderBalancesBefore.ETHBalance); + + // Ensure that the stETH balances were updated correctly. + assertApproxEqAbs( + LIDO.balanceOf(address(hyperdrive)), + hyperdriveBalancesBefore.baseBalance + amountPaid, + 1 + ); + assertApproxEqAbs( + LIDO.balanceOf(trader), + traderBalancesBefore.baseBalance - amountPaid, + 1 + ); + + // Ensure that the stETH shares were updated correctly. + uint256 expectedShares = amountPaid.mulDivDown( + totalSharesBefore, + totalBaseBefore + ); + assertEq(LIDO.getTotalShares(), totalSharesBefore); + assertApproxEqAbs( + LIDO.sharesOf(address(hyperdrive)), + hyperdriveBalancesBefore.sharesBalance + expectedShares, + 1 + ); + assertApproxEqAbs( + LIDO.sharesOf(trader), + traderBalancesBefore.sharesBalance - expectedShares, + 1 + ); + } + } + /// Price Per Share /// function test__pricePerVaultShare(uint256 basePaid) external { diff --git a/test/utils/InstanceTestV2.sol b/test/utils/InstanceTestV2.sol new file mode 100644 index 000000000..43b553bdf --- /dev/null +++ b/test/utils/InstanceTestV2.sol @@ -0,0 +1,648 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity 0.8.20; + +import { ERC20ForwarderFactory } from "contracts/src/token/ERC20ForwarderFactory.sol"; +import { HyperdriveFactory } from "contracts/src/factory/HyperdriveFactory.sol"; +import { IERC20 } from "contracts/src/interfaces/IERC20.sol"; +import { IHyperdrive } from "contracts/src/interfaces/IHyperdrive.sol"; +import { AssetId } from "contracts/src/libraries/AssetId.sol"; +import { ETH } from "contracts/src/libraries/Constants.sol"; +import { FixedPointMath, ONE } from "contracts/src/libraries/FixedPointMath.sol"; +import { HyperdriveTest } from "test/utils/HyperdriveTest.sol"; +import { HyperdriveUtils } from "test/utils/HyperdriveUtils.sol"; +import { Lib } from "test/utils/Lib.sol"; + +/// @author DELV +/// @title InstanceTest +/// @notice The base contract for the instance testing suite. +/// @dev A testing suite that provides a foundation to setup, deploy, and +/// test common cases for Hyperdrive instances. +/// @custom:disclaimer The language used in this code is for coding convenience +/// only, and is not intended to, and does not, have any +/// particular legal or regulatory significance. +abstract contract InstanceTestV2 is HyperdriveTest { + using Lib for *; + using FixedPointMath for uint256; + + /// @dev Configuration for the Instance testing suite. + struct InstanceTestConfig { + address[] whaleAccounts; + IERC20 token; + IERC20 baseToken; + uint256 shareTolerance; + uint256 minTransactionAmount; + uint256 positionDuration; + bool enableBaseDeposits; + bool enableShareDeposits; + } + + // Fixed rate used to configure market. + uint256 internal constant FIXED_RATE = 0.05e18; + + // Default deployment constants. + bytes32 private constant DEFAULT_DEPLOYMENT_ID = + bytes32(uint256(0xdeadbeef)); + bytes32 private constant DEFAULT_DEPLOYMENT_SALT = + bytes32(uint256(0xdeadbabe)); + + // The configuration for the Instance testing suite. + InstanceTestConfig private config; + + // The configuration for the pool. + IHyperdrive.PoolDeployConfig private poolConfig; + + // The address of the deployer coordinator contract. + address private deployerCoordinator; + + // The factory contract used for deployment in this testing suite. + HyperdriveFactory private factory; + + // Flag for denoting if the base token is ETH. + bool private immutable isBaseETH; + + /// @dev Constructor for the Instance testing suite. + /// @param _config The Instance configuration. + constructor(InstanceTestConfig storage _config) { + config = _config; + isBaseETH = config.baseToken == IERC20(ETH); + } + + /// Deployments /// + + /// @notice Forge setup function. + /// @dev Inherits from HyperdriveTest and deploys the + /// Hyperdrive factory, deployer coordinator, and targets. + function setUp() public virtual override { + super.setUp(); + + // Initial contribution. + uint256 contribution = 5_000e18; + + // Fund accounts with ETH and token from whales. + vm.deal(alice, 100_000e18); + vm.deal(bob, 100_000e18); + address[] memory accounts = new address[](2); + accounts[0] = alice; + accounts[1] = bob; + for (uint256 i = 0; i < config.whaleAccounts.length; i++) { + fundAccounts( + address(hyperdrive), + config.token, + config.whaleAccounts[i], + accounts + ); + } + + // Deploy the Hyperdrive Factory contract. + deployFactory(); + + // Set the deployer coordinator address and add to the factory. + deployerCoordinator = deployCoordinator(); + factory.addDeployerCoordinator(deployerCoordinator); + + // Deploy all Hyperdrive contracts using deployer coordinator contract. + deployHyperdrive( + DEFAULT_DEPLOYMENT_ID, // Deployment Id + DEFAULT_DEPLOYMENT_SALT, // Deployment Salt + contribution, // Contribution + false // asBase + ); + + config.token.approve(address(hyperdrive), 100_000e18); + vm.startPrank(bob); + config.token.approve(address(hyperdrive), 100_000e18); + + // Ensure that Alice received the correct amount of LP tokens. She should + // receive LP shares totaling the amount of shares that she contributed + // minus the shares set aside for the minimum share reserves and the + // zero address's initial LP contribution. + assertApproxEqAbs( + hyperdrive.balanceOf(AssetId._LP_ASSET_ID, alice), + contribution - 2 * hyperdrive.getPoolConfig().minimumShareReserves, + config.shareTolerance + ); + + // Start recording event logs. + vm.recordLogs(); + } + + /// @dev Deploys all Hyperdrive contracts using the + /// deployer coordinator contract. + /// @param deploymentId The deployment id. + /// @param deploymentSalt The deployment salt for create2. + /// @param contribution The amount to initialize the market. + /// @param asBase Initialize the market with base token. + function deployHyperdrive( + bytes32 deploymentId, + bytes32 deploymentSalt, + uint256 contribution, + bool asBase + ) private { + // Alice is the default deployer. + vm.startPrank(alice); + + // Deploy Hyperdrive target contracts. + factory.deployTarget( + deploymentId, + deployerCoordinator, + poolConfig, + new bytes(0), + FIXED_RATE, + FIXED_RATE, + 0, + deploymentSalt + ); + factory.deployTarget( + deploymentId, + deployerCoordinator, + poolConfig, + new bytes(0), + FIXED_RATE, + FIXED_RATE, + 1, + deploymentSalt + ); + factory.deployTarget( + deploymentId, + deployerCoordinator, + poolConfig, + new bytes(0), + FIXED_RATE, + FIXED_RATE, + 2, + deploymentSalt + ); + factory.deployTarget( + deploymentId, + deployerCoordinator, + poolConfig, + new bytes(0), + FIXED_RATE, + FIXED_RATE, + 3, + deploymentSalt + ); + factory.deployTarget( + deploymentId, + deployerCoordinator, + poolConfig, + new bytes(0), + FIXED_RATE, + FIXED_RATE, + 4, + deploymentSalt + ); + + // Alice gives approval to the deployer coordinator to fund the market. + config.token.approve(deployerCoordinator, 100_000e18); + + // We expect the deployAndInitialize to fail with an + // Unsupported token error if depositing with base is not supported. + // If the base token is ETH we expect a NotPayable error. + if (!config.enableBaseDeposits && asBase) { + vm.expectRevert( + isBaseETH + ? IHyperdrive.NotPayable.selector + : IHyperdrive.UnsupportedToken.selector + ); + } + + // We expect the deployAndInitialize to fail with an + // Unsupported token error if depositing with shares is not supported. + if (!config.enableShareDeposits && !asBase) { + vm.expectRevert(IHyperdrive.UnsupportedToken.selector); + } + + // Record Alice's ETH balance before the deployment call. + uint256 aliceBalanceBefore = address(alice).balance; + + // Deploy and initialize the market. If the base token is ETH we pass the + // contribution through the call. + hyperdrive = factory.deployAndInitialize{ + value: asBase && isBaseETH ? contribution : 0 + }( + deploymentId, + deployerCoordinator, + poolConfig, + new bytes(0), + contribution, + FIXED_RATE, + FIXED_RATE, + IHyperdrive.Options({ + asBase: asBase, + destination: alice, + extraData: new bytes(0) + }), + deploymentSalt + ); + + // Ensure that refunds are handled properly. + if (config.enableBaseDeposits && asBase && isBaseETH) { + assertEq(aliceBalanceBefore - contribution, address(alice).balance); + } else { + assertEq(aliceBalanceBefore, address(alice).balance); + } + } + + /// @dev Deploys the Hyperdrive Factory contract and + /// sets the default pool configuration. + function deployFactory() private { + // Deploy the hyperdrive factory. + vm.startPrank(deployer); + address[] memory defaults = new address[](1); + defaults[0] = bob; + forwarderFactory = new ERC20ForwarderFactory(); + factory = new HyperdriveFactory( + HyperdriveFactory.FactoryConfig({ + governance: alice, + hyperdriveGovernance: bob, + feeCollector: celine, + sweepCollector: sweepCollector, + defaultPausers: defaults, + checkpointDurationResolution: 1 hours, + minCheckpointDuration: 8 hours, + maxCheckpointDuration: 1 days, + minPositionDuration: 7 days, + maxPositionDuration: 10 * 365 days, + minFixedAPR: 0.001e18, + maxFixedAPR: 0.5e18, + minTimeStretchAPR: 0.005e18, + maxTimeStretchAPR: 0.5e18, + minFees: IHyperdrive.Fees({ + curve: 0, + flat: 0, + governanceLP: 0, + governanceZombie: 0 + }), + maxFees: IHyperdrive.Fees({ + curve: ONE, + flat: ONE, + governanceLP: ONE, + governanceZombie: ONE + }), + linkerFactory: address(forwarderFactory), + linkerCodeHash: forwarderFactory.ERC20LINK_HASH() + }) + ); + + // Set the pool configuration that will be used for instance deployments. + poolConfig = IHyperdrive.PoolDeployConfig({ + baseToken: config.baseToken, + linkerFactory: factory.linkerFactory(), + linkerCodeHash: factory.linkerCodeHash(), + minimumShareReserves: 1e15, + minimumTransactionAmount: config.minTransactionAmount, + positionDuration: config.positionDuration, + checkpointDuration: CHECKPOINT_DURATION, + timeStretch: 0, + governance: factory.hyperdriveGovernance(), + feeCollector: factory.feeCollector(), + sweepCollector: factory.sweepCollector(), + fees: IHyperdrive.Fees({ + curve: 0, + flat: 0, + governanceLP: 0, + governanceZombie: 0 + }) + }); + } + + /// Overrides /// + + /// @dev A virtual function that defines the deployer coordinator + /// contract that will be used to deploy all the instance targets. + function deployCoordinator() internal virtual returns (address); + + /// @dev A virtual function that converts an amount in terms of the base token + /// to equivalent amount in shares. + /// @param baseAmount Amount in terms of the base. + /// @return shareAmount Amount in terms of shares. + function convertToShares( + uint256 baseAmount + ) internal view virtual returns (uint256 shareAmount); + + /// Tests /// + + /// @dev Test to verify a market can be deployed and initialized funded by the + /// base token. Is expected to revert when base deposits are not supported. + function test__deployAndInitialize__asBase() external virtual { + uint256 aliceBalanceBefore = address(alice).balance; + + // Contribution in terms of base. + uint256 contribution = 5_000e18; + + // Contribution in terms of shares. + uint256 contributionShares = convertToShares(contribution); + + // Deploy all Hyperdrive contract using deployer coordinator contract. + // This function reverts if base deposits are disabled. + deployHyperdrive( + bytes32(uint256(0xbeefbabe)), // Deployment Id + bytes32(uint256(0xdeadfade)), // Deployment Salt + contribution, // Contribution + true // asBase + ); + + // Early termination if base deposits are not supported. + if (!config.enableBaseDeposits) { + return; + } + + // If base deposits are enabled we verify some assertions. + if (isBaseETH) { + // If the base token is ETH we assert the ETH balance is correct. + assertEq(address(alice).balance, aliceBalanceBefore - contribution); + } + + // Ensure that the decimals are set correctly. + assertEq(hyperdrive.decimals(), 18); + + // Ensure that Alice received the correct amount of LP tokens. She should + // receive LP shares totaling the amount of shares that he contributed + // minus the shares set aside for the minimum share reserves and the + // zero address's initial LP contribution. + assertApproxEqAbs( + hyperdrive.balanceOf(AssetId._LP_ASSET_ID, alice), + contribution.divDown( + hyperdrive.getPoolConfig().initialVaultSharePrice + ) - 2 * hyperdrive.getPoolConfig().minimumShareReserves, + config.shareTolerance // Custom share tolerance per instance. + ); + + // Ensure that the share reserves and LP total supply are equal and correct. + assertApproxEqAbs( + hyperdrive.getPoolInfo().shareReserves, + contributionShares, + 1 + ); + assertEq( + hyperdrive.getPoolInfo().lpTotalSupply, + hyperdrive.getPoolInfo().shareReserves - + hyperdrive.getPoolConfig().minimumShareReserves + ); + + // Verify that the correct events were emitted. + verifyFactoryEvents( + deployerCoordinator, + hyperdrive, + alice, + contribution, + FIXED_RATE, + true, + hyperdrive.getPoolConfig().minimumShareReserves, + new bytes(0), + config.shareTolerance + ); + } + + /// @dev Test to verify a market can be deployed and initialized funded + /// by the share token. + function test__deployAndInitialize__asShares() external { + uint256 aliceBalanceBefore = address(alice).balance; + + // Contribution in terms of base. + uint256 contribution = 5_000e18; + + // Contribution in terms of shares. + uint256 contributionShares = convertToShares(contribution); + + // Deploy all Hyperdrive contracts using deployer coordinator contract. + deployHyperdrive( + bytes32(uint256(0xbeefbabe)), // Deployment Id + bytes32(uint256(0xdeadfade)), // Deployment Salt + contributionShares, // Contribution + false // asBase + ); + + // Early termination if share deposits are not supported. + if (!config.enableShareDeposits) { + return; + } + + // Ensure Alice's ETH balance remains the same. + assertEq(address(alice).balance, aliceBalanceBefore); + + // Ensure that the decimals are set correctly. + assertEq(hyperdrive.decimals(), 18); + + // Ensure that Alice received the correct amount of LP tokens. She should + // receive LP shares totaling the amount of shares that he contributed + // minus the shares set aside for the minimum share reserves and the + // zero address's initial LP contribution. + assertApproxEqAbs( + hyperdrive.balanceOf(AssetId._LP_ASSET_ID, alice), + contribution.divDown( + hyperdrive.getPoolConfig().initialVaultSharePrice + ) - 2 * hyperdrive.getPoolConfig().minimumShareReserves, + config.shareTolerance // Custom share tolerance per instance. + ); + + // Ensure that the share reserves and LP total supply are equal and correct. + assertEq(hyperdrive.getPoolInfo().shareReserves, contributionShares); + assertEq( + hyperdrive.getPoolInfo().lpTotalSupply, + hyperdrive.getPoolInfo().shareReserves - + poolConfig.minimumShareReserves + ); + + // Verify that the correct events were emitted. + verifyFactoryEvents( + deployerCoordinator, + hyperdrive, + alice, + contributionShares, + FIXED_RATE, + false, + poolConfig.minimumShareReserves, + new bytes(0), + config.shareTolerance + ); + } + + struct AccountBalances2 { + uint256 sharesBalance; + uint256 baseBalance; + uint256 ETHBalance; + } + + function getTokenBalances( + address account + ) internal view virtual returns (uint256, uint256); + + function getSupply() internal virtual returns (uint256, uint256); + + function _getAccountBalances( + address account + ) internal view returns (AccountBalances2 memory) { + (uint256 shares, uint256 base) = getTokenBalances(account); + + return + AccountBalances2({ + sharesBalance: shares, + baseBalance: base, + ETHBalance: account.balance + }); + } + + function _verifyDeposit( + address trader, + uint256 amountPaid, + bool asBase, + uint256 totalBaseBefore, + uint256 totalSharesBefore, + AccountBalances2 memory traderBalancesBefore, + AccountBalances2 memory hyperdriveBalancesBefore + ) internal virtual; + + function test__open_long_with_shares(uint256 basePaid) external { + ( + uint256 totalBaseSupplyBefore, + uint256 totalSharesSupplyBefore + ) = getSupply(); + + AccountBalances2 memory bobBalancesBefore = _getAccountBalances(bob); + AccountBalances2 memory hyperdriveBalanceBefore = _getAccountBalances( + address(hyperdrive) + ); + + // Bob opens a long by depositing stETH. + basePaid = basePaid.normalizeToRange( + 2 * hyperdrive.getPoolConfig().minimumTransactionAmount, + HyperdriveUtils.calculateMaxLong(hyperdrive) + ); + + uint256 sharesPaid = convertToShares(basePaid); + + openLong(bob, sharesPaid, false); + _verifyDeposit( + bob, + basePaid, + false, + totalBaseSupplyBefore, + totalSharesSupplyBefore, + bobBalancesBefore, + hyperdriveBalanceBefore + ); + } + + function test__open_long_with_base(uint256 basePaid) external { + ( + uint256 totalBaseSupplyBefore, + uint256 totalSharesSupplyBefore + ) = getSupply(); + + AccountBalances2 memory bobBalancesBefore = _getAccountBalances(bob); + AccountBalances2 memory hyperdriveBalanceBefore = _getAccountBalances( + address(hyperdrive) + ); + + // Bob opens a long by depositing stETH. + basePaid = basePaid.normalizeToRange( + 2 * hyperdrive.getPoolConfig().minimumTransactionAmount, + HyperdriveUtils.calculateMaxLong(hyperdrive) + ); + + // uint256 sharesPaid = convertToShares(basePaid); + + openLong(bob, basePaid, true); + _verifyDeposit( + bob, + basePaid, + true, + totalBaseSupplyBefore, + totalSharesSupplyBefore, + bobBalancesBefore, + hyperdriveBalanceBefore + ); + } + + // function verifyDeposit( + // address trader, + // uint256 amountPaid, + // bool asBase, + // uint256 totalBaseBefore, + // uint256 totalSharesBefore, + // AccountBalances memory traderBalancesBefore, + // AccountBalances memory hyperdriveBalancesBefore + // ) internal { + // if (asBase) { + // // // Ensure that the amount of pooled ether increased by the base paid. + // // assertEq(LIDO.getTotalPooledEther(), totalBaseBefore + basePaid); + // // // Ensure that the ETH balances were updated correctly. + // // assertEq( + // // address(hyperdrive).balance, + // // hyperdriveBalancesBefore.ethBalance + // // ); + // // assertEq(bob.balance, traderBalancesBefore.ethBalance - basePaid); + // // // Ensure that the stETH balances were updated correctly. + // // assertApproxEqAbs( + // // LIDO.balanceOf(address(hyperdrive)), + // // hyperdriveBalancesBefore.stethBalance + basePaid, + // // 1 + // // ); + // // assertEq(LIDO.balanceOf(trader), traderBalancesBefore.stethBalance); + // // // Ensure that the stETH shares were updated correctly. + // // uint256 expectedShares = basePaid.mulDivDown( + // // totalSharesBefore, + // // totalBaseBefore + // // ); + // // assertEq(LIDO.getTotalShares(), totalSharesBefore + expectedShares); + // // assertEq( + // // LIDO.sharesOf(address(hyperdrive)), + // // hyperdriveBalancesBefore.stethShares + expectedShares + // // ); + // // assertEq(LIDO.sharesOf(bob), traderBalancesBefore.stethShares); + // } else { + // ( + // uint256 totalBaseSupplyNow, + // uint256 totalSharesSupplyNow + // ) = getSupply(); + + // (uint256 traderShares, uint256 traderBase) = getTokenBalances( + // trader + // ); + // ( + // uint256 hyperdriveShares, + // uint256 hyperdriveBase + // ) = getTokenBalances(address(hyperdrive)); + // // Ensure that the amount of pooled ether stays the same. + // assertEq(totalBaseSupplyNow, totalBaseBefore); + + // // Ensure that the ETH balances were updated correctly. + // assertEq( + // address(hyperdrive).balance, + // hyperdriveBalancesBefore.ethBalance + // ); + // assertEq(trader.balance, traderBalancesBefore.ethBalance); + + // // Ensure that the stETH balances were updated correctly. + // assertApproxEqAbs( + // LIDO.balanceOf(address(hyperdrive)), + // hyperdriveBalancesBefore.baseBalance + basePaid, + // 1 + // ); + // assertApproxEqAbs( + // LIDO.balanceOf(trader), + // traderBalancesBefore.stethBalance - basePaid, + // 1 + // ); + + // // Ensure that the stETH shares were updated correctly. + // uint256 expectedShares = basePaid.mulDivDown( + // totalSharesBefore, + // totalBaseBefore + // ); + // assertEq(LIDO.getTotalShares(), totalSharesBefore); + // assertApproxEqAbs( + // LIDO.sharesOf(address(hyperdrive)), + // hyperdriveBalancesBefore.stethShares + expectedShares, + // 1 + // ); + // assertApproxEqAbs( + // LIDO.sharesOf(trader), + // traderBalancesBefore.stethShares - expectedShares, + // 1 + // ); + // } + // } +} From 918a05ddaec85f82ba133a3380fbc2fcb316e981 Mon Sep 17 00:00:00 2001 From: Cash Baller Date: Tue, 26 Mar 2024 21:35:10 -0500 Subject: [PATCH 02/21] Migrated all yield sources to InstanceTestV2 --- test/instances/ezETH/EzETHHyperdrive.t.sol | 224 ++++++++++++++------- test/instances/lseth/LsETHHyperdrive.t.sol | 52 ++++- test/instances/reth/RETHHyperdrive.t.sol | 56 +++++- test/utils/InstanceTestV2.sol | 51 ++++- 4 files changed, 293 insertions(+), 90 deletions(-) diff --git a/test/instances/ezETH/EzETHHyperdrive.t.sol b/test/instances/ezETH/EzETHHyperdrive.t.sol index c3dc214cd..114baa4c8 100644 --- a/test/instances/ezETH/EzETHHyperdrive.t.sol +++ b/test/instances/ezETH/EzETHHyperdrive.t.sol @@ -21,11 +21,11 @@ import { FixedPointMath, ONE } from "contracts/src/libraries/FixedPointMath.sol" import { HyperdriveMath } from "contracts/src/libraries/HyperdriveMath.sol"; import { ERC20ForwarderFactory } from "contracts/src/token/ERC20ForwarderFactory.sol"; import { ERC20Mintable } from "contracts/test/ERC20Mintable.sol"; -import { InstanceTest } from "test/utils/InstanceTest.sol"; +import { InstanceTestV2 } from "test/utils/InstanceTestV2.sol"; import { HyperdriveUtils } from "test/utils/HyperdriveUtils.sol"; import { Lib } from "test/utils/Lib.sol"; -contract EzETHHyperdriveTest is InstanceTest { +contract EzETHHyperdriveTest is InstanceTestV2 { using FixedPointMath for uint256; using Lib for *; using stdStorage for StdStorage; @@ -72,7 +72,7 @@ contract EzETHHyperdriveTest is InstanceTest { ); /// @dev Instantiates the Instance testing suite with the configuration. - constructor() InstanceTest(__testConfig) {} + constructor() InstanceTestV2(__testConfig) {} /// @dev Forge function that is invoked to setup the testing environment. function setUp() public override __mainnet_fork(STARTING_BLOCK) { @@ -97,6 +97,17 @@ contract EzETHHyperdriveTest is InstanceTest { return baseAmount.divDown(sharePrice); } + function getTokenBalances( + address account + ) internal view override returns (uint256, uint256) { + return (EZETH.balanceOf(account), 0); + } + + function getSupply() internal override returns (uint256, uint256) { + (, uint256 totalPooledEther, ) = getSharePrice(); + return (totalPooledEther, EZETH.totalSupply()); + } + /// @dev Deploys the EzETH deployer coordinator contract. function deployCoordinator() internal override returns (address) { vm.startPrank(alice); @@ -114,6 +125,143 @@ contract EzETHHyperdriveTest is InstanceTest { ); } + function verifyDeposit( + address trader, + uint256 basePaid, + bool asBase, + uint256 totalBaseSupplyBefore, + uint256 totalSharesBefore, + AccountBalances memory traderBalancesBefore, + AccountBalances memory hyperdriveBalancesBefore + ) internal { + if (asBase) { + // Ensure that the amount of pooled ether increased by the base paid. + (, uint256 totalPooledEther, ) = getSharePrice(); + assertEq(totalPooledEther, totalBaseSupplyBefore + basePaid); + + // Ensure that the ETH balances were updated correctly. + assertEq( + address(hyperdrive).balance, + hyperdriveBalancesBefore.ETHBalance + ); + assertEq(bob.balance, traderBalancesBefore.ETHBalance - basePaid); + + // Ensure ezETH shares were updated correctly. + assertEq( + EZETH.balanceOf(trader), + traderBalancesBefore.ezethBalance + ); + + // Ensure that the ezETH shares were updated correctly. + uint256 expectedShares = RENZO_ORACLE.calculateMintAmount( + totalBaseSupplyBefore, + basePaid, + totalSharesBefore + ); + assertEq(EZETH.totalSupply(), totalSharesBefore + expectedShares); + assertEq( + EZETH.balanceOf(address(hyperdrive)), + hyperdriveBalancesBefore.ezethBalance + expectedShares + ); + assertEq(EZETH.balanceOf(bob), traderBalancesBefore.ezethBalance); + } else { + // Ensure that the amount of pooled ether stays the same. + (, uint256 totalPooledEther, ) = getSharePrice(); + assertEq(totalPooledEther, totalBaseSupplyBefore); + + // Ensure that the ETH balances were updated correctly. + assertEq( + address(hyperdrive).balance, + hyperdriveBalancesBefore.ETHBalance + ); + assertEq(trader.balance, traderBalancesBefore.ETHBalance); + + // Ensure that the ezETH shares were updated correctly. + uint256 expectedShares = basePaid.mulDivDown( + totalSharesBefore, + totalBaseSupplyBefore + ); + assertEq(EZETH.totalSupply(), totalSharesBefore); + assertApproxEqAbs( + EZETH.balanceOf(address(hyperdrive)), + hyperdriveBalancesBefore.ezethBalance + expectedShares, + 1 + ); + assertApproxEqAbs( + EZETH.balanceOf(trader), + traderBalancesBefore.ezethBalance - expectedShares, + 1 + ); + } + } + + function _verifyDeposit( + address trader, + uint256 basePaid, + bool asBase, + uint256 totalBaseSupplyBefore, + uint256 totalSharesBefore, + AccountBalances2 memory traderBalancesBefore, + AccountBalances2 memory hyperdriveBalancesBefore + ) internal override { + if (asBase) { + // Ensure that the amount of pooled ether increased by the base paid. + (, uint256 totalPooledEther, ) = getSharePrice(); + assertEq(totalPooledEther, totalBaseSupplyBefore + basePaid); + + // Ensure that the ETH balances were updated correctly. + assertEq( + address(hyperdrive).balance, + hyperdriveBalancesBefore.ETHBalance + ); + assertEq(bob.balance, traderBalancesBefore.ETHBalance - basePaid); + + // Ensure ezETH shares were updated correctly. + assertEq( + EZETH.balanceOf(trader), + traderBalancesBefore.sharesBalance + ); + + // Ensure that the ezETH shares were updated correctly. + uint256 expectedShares = RENZO_ORACLE.calculateMintAmount( + totalBaseSupplyBefore, + basePaid, + totalSharesBefore + ); + assertEq(EZETH.totalSupply(), totalSharesBefore + expectedShares); + assertEq( + EZETH.balanceOf(address(hyperdrive)), + hyperdriveBalancesBefore.sharesBalance + expectedShares + ); + assertEq(EZETH.balanceOf(bob), traderBalancesBefore.sharesBalance); + } else { + // Ensure that the amount of pooled ether stays the same. + (, uint256 totalPooledEther, ) = getSharePrice(); + assertEq(totalPooledEther, totalBaseSupplyBefore); + + // Ensure that the ETH balances were updated correctly. + assertEq( + address(hyperdrive).balance, + hyperdriveBalancesBefore.ETHBalance + ); + assertEq(trader.balance, traderBalancesBefore.ETHBalance); + + // Ensure that the ezETH shares were updated correctly. + uint256 expectedShares = convertToShares(basePaid); + assertEq(EZETH.totalSupply(), totalSharesBefore); + assertApproxEqAbs( + EZETH.balanceOf(address(hyperdrive)), + hyperdriveBalancesBefore.sharesBalance + expectedShares, + 2 + ); + assertApproxEqAbs( + EZETH.balanceOf(trader), + traderBalancesBefore.sharesBalance - expectedShares, + 2 + ); + } + } + /// Getters /// function test_getters() external { @@ -651,76 +799,6 @@ contract EzETHHyperdriveTest is InstanceTest { ); } - function verifyDeposit( - address trader, - uint256 basePaid, - bool asBase, - uint256 totalPooledEtherBefore, - uint256 totalSharesBefore, - AccountBalances memory traderBalancesBefore, - AccountBalances memory hyperdriveBalancesBefore - ) internal { - if (asBase) { - // Ensure that the amount of pooled ether increased by the base paid. - (, uint256 totalPooledEther, ) = getSharePrice(); - assertEq(totalPooledEther, totalPooledEtherBefore + basePaid); - - // Ensure that the ETH balances were updated correctly. - assertEq( - address(hyperdrive).balance, - hyperdriveBalancesBefore.ETHBalance - ); - assertEq(bob.balance, traderBalancesBefore.ETHBalance - basePaid); - - // Ensure ezETH shares were updated correctly. - assertEq( - EZETH.balanceOf(trader), - traderBalancesBefore.ezethBalance - ); - - // Ensure that the ezETH shares were updated correctly. - uint256 expectedShares = RENZO_ORACLE.calculateMintAmount( - totalPooledEtherBefore, - basePaid, - totalSharesBefore - ); - assertEq(EZETH.totalSupply(), totalSharesBefore + expectedShares); - assertEq( - EZETH.balanceOf(address(hyperdrive)), - hyperdriveBalancesBefore.ezethBalance + expectedShares - ); - assertEq(EZETH.balanceOf(bob), traderBalancesBefore.ezethBalance); - } else { - // Ensure that the amount of pooled ether stays the same. - (, uint256 totalPooledEther, ) = getSharePrice(); - assertEq(totalPooledEther, totalPooledEtherBefore); - - // Ensure that the ETH balances were updated correctly. - assertEq( - address(hyperdrive).balance, - hyperdriveBalancesBefore.ETHBalance - ); - assertEq(trader.balance, traderBalancesBefore.ETHBalance); - - // Ensure that the ezETH shares were updated correctly. - uint256 expectedShares = basePaid.mulDivDown( - totalSharesBefore, - totalPooledEtherBefore - ); - assertEq(EZETH.totalSupply(), totalSharesBefore); - assertApproxEqAbs( - EZETH.balanceOf(address(hyperdrive)), - hyperdriveBalancesBefore.ezethBalance + expectedShares, - 1 - ); - assertApproxEqAbs( - EZETH.balanceOf(trader), - traderBalancesBefore.ezethBalance - expectedShares, - 1 - ); - } - } - function verifyEzethWithdrawal( address trader, uint256 baseProceeds, diff --git a/test/instances/lseth/LsETHHyperdrive.t.sol b/test/instances/lseth/LsETHHyperdrive.t.sol index 7d8130035..7dc5c04f9 100644 --- a/test/instances/lseth/LsETHHyperdrive.t.sol +++ b/test/instances/lseth/LsETHHyperdrive.t.sol @@ -19,11 +19,11 @@ import { ETH } from "contracts/src/libraries/Constants.sol"; import { HyperdriveMath } from "contracts/src/libraries/HyperdriveMath.sol"; import { FixedPointMath, ONE } from "contracts/src/libraries/FixedPointMath.sol"; import { ERC20Mintable } from "contracts/test/ERC20Mintable.sol"; -import { InstanceTest } from "test/utils/InstanceTest.sol"; +import { InstanceTestV2 } from "test/utils/InstanceTestV2.sol"; import { HyperdriveUtils } from "test/utils/HyperdriveUtils.sol"; import { Lib } from "test/utils/Lib.sol"; -contract LsETHHyperdriveTest is InstanceTest { +contract LsETHHyperdriveTest is InstanceTestV2 { using FixedPointMath for uint256; using Lib for *; using stdStorage for StdStorage; @@ -59,7 +59,7 @@ contract LsETHHyperdriveTest is InstanceTest { ); /// @dev Instantiates the Instance testing suite with the configuration. - constructor() InstanceTest(__testConfig) {} + constructor() InstanceTestV2(__testConfig) {} /// @dev Forge function that is invoked to setup the testing environment. @@ -95,6 +95,52 @@ contract LsETHHyperdriveTest is InstanceTest { return RIVER.sharesFromUnderlyingBalance(baseAmount); } + function getTokenBalances( + address account + ) internal view override returns (uint256, uint256) { + return (RIVER.balanceOf(account), RIVER.balanceOfUnderlying(account)); + } + + function getSupply() internal override returns (uint256, uint256) { + return (RIVER.totalUnderlyingSupply(), RIVER.totalSupply()); + } + + function _verifyDeposit( + address trader, + uint256 amount, + bool asBase, + uint totalBaseBefore, // unused + uint256 totalSharesBefore, + AccountBalances2 memory traderBalancesBefore, + AccountBalances2 memory hyperdriveBalancesBefore + ) internal override { + if (asBase) { + revert IHyperdrive.NotPayable(); + } + + amount = convertToShares(amount); + + // Ensure that the ether balances were updated correctly. + assertEq( + address(hyperdrive).balance, + hyperdriveBalancesBefore.ETHBalance + ); + assertEq(trader.balance, traderBalancesBefore.ETHBalance); + + // Ensure that the LsETH balances were updated correctly. + assertEq( + RIVER.balanceOf(address(hyperdrive)), + hyperdriveBalancesBefore.sharesBalance + amount + ); + assertEq( + RIVER.balanceOf(trader), + traderBalancesBefore.sharesBalance - amount + ); + + // Ensure the total supply was updated correctly. + assertEq(RIVER.totalSupply(), totalSharesBefore); + } + /// Price Per Share /// function test_pricePerVaultShare(uint256 basePaid) external { diff --git a/test/instances/reth/RETHHyperdrive.t.sol b/test/instances/reth/RETHHyperdrive.t.sol index 417bc6209..e5c0692f4 100644 --- a/test/instances/reth/RETHHyperdrive.t.sol +++ b/test/instances/reth/RETHHyperdrive.t.sol @@ -8,7 +8,7 @@ import { ETH } from "contracts/src/libraries/Constants.sol"; import { FixedPointMath, ONE } from "contracts/src/libraries/FixedPointMath.sol"; import { HyperdriveFactory } from "contracts/src/factory/HyperdriveFactory.sol"; import { HyperdriveMath } from "contracts/src/libraries/HyperdriveMath.sol"; -import { InstanceTest } from "test/utils/InstanceTest.sol"; +import { InstanceTestV2 } from "test/utils/InstanceTestV2.sol"; import { HyperdriveUtils } from "test/utils/HyperdriveUtils.sol"; import { IERC20 } from "contracts/src/interfaces/IERC20.sol"; import { IHyperdrive } from "contracts/src/interfaces/IHyperdrive.sol"; @@ -28,7 +28,7 @@ import { RETHTarget3Deployer } from "contracts/src/deployers/reth/RETHTarget3Dep import { RETHTarget4Deployer } from "contracts/src/deployers/reth/RETHTarget4Deployer.sol"; import { stdStorage, StdStorage } from "forge-std/Test.sol"; -contract RETHHyperdriveTest is InstanceTest { +contract RETHHyperdriveTest is InstanceTestV2 { using FixedPointMath for uint256; using Lib for *; using stdStorage for StdStorage; @@ -63,7 +63,7 @@ contract RETHHyperdriveTest is InstanceTest { ); /// @dev Instantiates the Instance testing suite with the configuration. - constructor() InstanceTest(__testConfig) {} + constructor() InstanceTestV2(__testConfig) {} /// @dev Forge function that is invoked to setup the testing environment. function setUp() public override __mainnet_fork(19_429_100) { @@ -101,6 +101,56 @@ contract RETHHyperdriveTest is InstanceTest { ); } + function getTokenBalances( + address account + ) internal view override returns (uint256, uint256) { + uint256 rethBalance = rocketTokenRETH.balanceOf(account); + return (rethBalance, rocketTokenRETH.getEthValue(rethBalance)); + } + + function getSupply() internal override returns (uint256, uint256) { + return ( + rocketNetworkBalances.getTotalETHBalance(), + rocketNetworkBalances.getTotalRETHSupply() + ); + } + + function _verifyDeposit( + address trader, + uint256 amount, + bool asBase, + uint256 totalBaseBefore, // unused + uint256 totalSharesBefore, + AccountBalances2 memory traderBalancesBefore, + AccountBalances2 memory hyperdriveBalancesBefore + ) internal override { + if (asBase) { + revert IHyperdrive.UnsupportedToken(); + } + + amount = convertToShares(amount); + + // Ensure that the ether balances were updated correctly. + assertEq( + address(hyperdrive).balance, + hyperdriveBalancesBefore.ETHBalance + ); + assertEq(trader.balance, traderBalancesBefore.ETHBalance); + + // Ensure that the rETH balances were updated correctly. + assertEq( + rocketTokenRETH.balanceOf(address(hyperdrive)), + hyperdriveBalancesBefore.sharesBalance + amount + ); + assertEq( + rocketTokenRETH.balanceOf(trader), + traderBalancesBefore.sharesBalance - amount + ); + + // // Ensure the total supply was updated correctly. + assertEq(rocketTokenRETH.totalSupply(), totalSharesBefore); + } + /// Getters /// function test_getters() external { diff --git a/test/utils/InstanceTestV2.sol b/test/utils/InstanceTestV2.sol index 43b553bdf..0f700f4b9 100644 --- a/test/utils/InstanceTestV2.sol +++ b/test/utils/InstanceTestV2.sol @@ -46,7 +46,7 @@ abstract contract InstanceTestV2 is HyperdriveTest { bytes32(uint256(0xdeadbabe)); // The configuration for the Instance testing suite. - InstanceTestConfig private config; + InstanceTestConfig internal config; // The configuration for the pool. IHyperdrive.PoolDeployConfig private poolConfig; @@ -505,10 +505,16 @@ abstract contract InstanceTestV2 is HyperdriveTest { address(hyperdrive) ); + // Calculate the maximum amount of basePaid we can test. The limit is + // either the max long that Hyperdrive can open or the amount of rETH + // tokens the trader has. + uint256 maxLongAmount = HyperdriveUtils.calculateMaxLong(hyperdrive); + uint256 maxSharesAmount = bobBalancesBefore.sharesBalance; + // Bob opens a long by depositing stETH. basePaid = basePaid.normalizeToRange( 2 * hyperdrive.getPoolConfig().minimumTransactionAmount, - HyperdriveUtils.calculateMaxLong(hyperdrive) + maxLongAmount > maxSharesAmount ? maxSharesAmount : maxLongAmount ); uint256 sharesPaid = convertToShares(basePaid); @@ -537,23 +543,46 @@ abstract contract InstanceTestV2 is HyperdriveTest { ); // Bob opens a long by depositing stETH. + vm.startPrank(bob); basePaid = basePaid.normalizeToRange( 2 * hyperdrive.getPoolConfig().minimumTransactionAmount, HyperdriveUtils.calculateMaxLong(hyperdrive) ); - // uint256 sharesPaid = convertToShares(basePaid); + // We expect the deployAndInitialize to fail with an + // Unsupported token error if depositing with base is not supported. + // If the base token is ETH we expect a NotPayable error. + if (!config.enableBaseDeposits) { + vm.expectRevert( + isBaseETH + ? IHyperdrive.NotPayable.selector + : IHyperdrive.UnsupportedToken.selector + ); + } - openLong(bob, basePaid, true); - _verifyDeposit( - bob, + hyperdrive.openLong{ value: isBaseETH ? basePaid : 0 }( basePaid, - true, - totalBaseSupplyBefore, - totalSharesSupplyBefore, - bobBalancesBefore, - hyperdriveBalanceBefore + 0, + 0, + IHyperdrive.Options({ + destination: bob, + asBase: true, + extraData: new bytes(0) + }) ); + // openLong(bob, basePaid, true); + + if (config.enableBaseDeposits) { + _verifyDeposit( + bob, + basePaid, + true, + totalBaseSupplyBefore, + totalSharesSupplyBefore, + bobBalancesBefore, + hyperdriveBalanceBefore + ); + } } // function verifyDeposit( From c5bd365a60ac629f21b097729a19d171086ba441 Mon Sep 17 00:00:00 2001 From: Cash Baller Date: Tue, 26 Mar 2024 21:58:37 -0500 Subject: [PATCH 03/21] Removed duplicate AccountBalances and verifyDeposit functions --- test/instances/ezETH/EzETHHyperdrive.t.sol | 240 +++++--------- test/instances/lseth/LsETHHyperdrive.t.sol | 347 +++++++++++---------- test/instances/reth/RETHHyperdrive.t.sol | 246 ++++++++------- test/instances/steth/StETHHyperdrive.t.sol | 274 +++++++--------- test/utils/InstanceTestV2.sol | 116 +------ 5 files changed, 511 insertions(+), 712 deletions(-) diff --git a/test/instances/ezETH/EzETHHyperdrive.t.sol b/test/instances/ezETH/EzETHHyperdrive.t.sol index 114baa4c8..2aca90aa6 100644 --- a/test/instances/ezETH/EzETHHyperdrive.t.sol +++ b/test/instances/ezETH/EzETHHyperdrive.t.sol @@ -133,76 +133,6 @@ contract EzETHHyperdriveTest is InstanceTestV2 { uint256 totalSharesBefore, AccountBalances memory traderBalancesBefore, AccountBalances memory hyperdriveBalancesBefore - ) internal { - if (asBase) { - // Ensure that the amount of pooled ether increased by the base paid. - (, uint256 totalPooledEther, ) = getSharePrice(); - assertEq(totalPooledEther, totalBaseSupplyBefore + basePaid); - - // Ensure that the ETH balances were updated correctly. - assertEq( - address(hyperdrive).balance, - hyperdriveBalancesBefore.ETHBalance - ); - assertEq(bob.balance, traderBalancesBefore.ETHBalance - basePaid); - - // Ensure ezETH shares were updated correctly. - assertEq( - EZETH.balanceOf(trader), - traderBalancesBefore.ezethBalance - ); - - // Ensure that the ezETH shares were updated correctly. - uint256 expectedShares = RENZO_ORACLE.calculateMintAmount( - totalBaseSupplyBefore, - basePaid, - totalSharesBefore - ); - assertEq(EZETH.totalSupply(), totalSharesBefore + expectedShares); - assertEq( - EZETH.balanceOf(address(hyperdrive)), - hyperdriveBalancesBefore.ezethBalance + expectedShares - ); - assertEq(EZETH.balanceOf(bob), traderBalancesBefore.ezethBalance); - } else { - // Ensure that the amount of pooled ether stays the same. - (, uint256 totalPooledEther, ) = getSharePrice(); - assertEq(totalPooledEther, totalBaseSupplyBefore); - - // Ensure that the ETH balances were updated correctly. - assertEq( - address(hyperdrive).balance, - hyperdriveBalancesBefore.ETHBalance - ); - assertEq(trader.balance, traderBalancesBefore.ETHBalance); - - // Ensure that the ezETH shares were updated correctly. - uint256 expectedShares = basePaid.mulDivDown( - totalSharesBefore, - totalBaseSupplyBefore - ); - assertEq(EZETH.totalSupply(), totalSharesBefore); - assertApproxEqAbs( - EZETH.balanceOf(address(hyperdrive)), - hyperdriveBalancesBefore.ezethBalance + expectedShares, - 1 - ); - assertApproxEqAbs( - EZETH.balanceOf(trader), - traderBalancesBefore.ezethBalance - expectedShares, - 1 - ); - } - } - - function _verifyDeposit( - address trader, - uint256 basePaid, - bool asBase, - uint256 totalBaseSupplyBefore, - uint256 totalSharesBefore, - AccountBalances2 memory traderBalancesBefore, - AccountBalances2 memory hyperdriveBalancesBefore ) internal override { if (asBase) { // Ensure that the amount of pooled ether increased by the base paid. @@ -252,12 +182,12 @@ contract EzETHHyperdriveTest is InstanceTestV2 { assertApproxEqAbs( EZETH.balanceOf(address(hyperdrive)), hyperdriveBalancesBefore.sharesBalance + expectedShares, - 2 + 1 ); assertApproxEqAbs( EZETH.balanceOf(trader), traderBalancesBefore.sharesBalance - expectedShares, - 2 + 1 ); } } @@ -332,73 +262,73 @@ contract EzETHHyperdriveTest is InstanceTestV2 { /// Long /// - function test_open_long_with_eth(uint256 basePaid) external { - // Bob opens a long by depositing ETH. - basePaid = basePaid.normalizeToRange( - 2 * hyperdrive.getPoolConfig().minimumTransactionAmount, - HyperdriveUtils.calculateMaxLong(hyperdrive) - ); - - // Ensure that we get an UnsupportedToken error. Opening positions - // with ETH are not allowed right now. There is a great enough - // precision loss when minting ezeth that warrants some investigation - // before we can turn this on. Until then, we can zap ezeth into the - // pool. - vm.expectRevert(IHyperdrive.NotPayable.selector); - hyperdrive.openLong{ value: basePaid }( - basePaid, - 0, // min bond proceeds - 0, // min vault share price - IHyperdrive.Options({ - destination: bob, - asBase: true, - extraData: new bytes(0) - }) - ); - } - - function test_open_long_with_ezeth(uint256 basePaid) external { - vm.stopPrank(); - vm.startPrank(bob); - - // Get some balance information before the deposit. - ( - , - uint256 totalPooledEtherBefore, - uint256 totalSharesBefore - ) = getSharePrice(); - AccountBalances memory bobBalancesBefore = getAccountBalances(bob); - AccountBalances memory hyperdriveBalancesBefore = getAccountBalances( - address(hyperdrive) - ); - - // Calculate the maximum amount of basePaid we can test. - uint256 maxLong = HyperdriveUtils.calculateMaxLong(hyperdrive); - uint256 maxEzEth = EZETH.balanceOf(address(bob)); - uint256 maxRange = maxLong > maxEzEth ? maxEzEth : maxLong; - basePaid = basePaid.normalizeToRange( - 2 * hyperdrive.getPoolConfig().minimumTransactionAmount, - maxRange - ); - - // Convert to shares and approve hyperdrive. - uint256 sharesPaid = getAndApproveShares(basePaid); - - // Open the position. - openLong(bob, sharesPaid, false); - - // Ensure that Renzo's aggregates and the token balances were updated - // correctly during the trade. - verifyDeposit( - bob, - basePaid, - false, - totalPooledEtherBefore, - totalSharesBefore, - bobBalancesBefore, - hyperdriveBalancesBefore - ); - } + // function test_open_long_with_eth(uint256 basePaid) external { + // // Bob opens a long by depositing ETH. + // basePaid = basePaid.normalizeToRange( + // 2 * hyperdrive.getPoolConfig().minimumTransactionAmount, + // HyperdriveUtils.calculateMaxLong(hyperdrive) + // ); + + // // Ensure that we get an UnsupportedToken error. Opening positions + // // with ETH are not allowed right now. There is a great enough + // // precision loss when minting ezeth that warrants some investigation + // // before we can turn this on. Until then, we can zap ezeth into the + // // pool. + // vm.expectRevert(IHyperdrive.NotPayable.selector); + // hyperdrive.openLong{ value: basePaid }( + // basePaid, + // 0, // min bond proceeds + // 0, // min vault share price + // IHyperdrive.Options({ + // destination: bob, + // asBase: true, + // extraData: new bytes(0) + // }) + // ); + // } + + // function test_open_long_with_ezeth(uint256 basePaid) external { + // vm.stopPrank(); + // vm.startPrank(bob); + + // // Get some balance information before the deposit. + // ( + // , + // uint256 totalPooledEtherBefore, + // uint256 totalSharesBefore + // ) = getSharePrice(); + // AccountBalances memory bobBalancesBefore = getAccountBalances(bob); + // AccountBalances memory hyperdriveBalancesBefore = getAccountBalances( + // address(hyperdrive) + // ); + + // // Calculate the maximum amount of basePaid we can test. + // uint256 maxLong = HyperdriveUtils.calculateMaxLong(hyperdrive); + // uint256 maxEzEth = EZETH.balanceOf(address(bob)); + // uint256 maxRange = maxLong > maxEzEth ? maxEzEth : maxLong; + // basePaid = basePaid.normalizeToRange( + // 2 * hyperdrive.getPoolConfig().minimumTransactionAmount, + // maxRange + // ); + + // // Convert to shares and approve hyperdrive. + // uint256 sharesPaid = getAndApproveShares(basePaid); + + // // Open the position. + // openLong(bob, sharesPaid, false); + + // // Ensure that Renzo's aggregates and the token balances were updated + // // correctly during the trade. + // verifyDeposit( + // bob, + // basePaid, + // false, + // totalPooledEtherBefore, + // totalSharesBefore, + // bobBalancesBefore, + // hyperdriveBalancesBefore + // ); + // } function test_close_long_with_eth(uint256 basePaid) external { vm.stopPrank(); @@ -826,12 +756,12 @@ contract EzETHHyperdriveTest is InstanceTestV2 { ); assertApproxEqAbs( EZETH.balanceOf(address(hyperdrive)), - hyperdriveBalancesBefore.ezethBalance - expectedShares, + hyperdriveBalancesBefore.sharesBalance - expectedShares, 1 ); assertApproxEqAbs( EZETH.balanceOf(trader), - traderBalancesBefore.ezethBalance + expectedShares, + traderBalancesBefore.sharesBalance + expectedShares, 1 ); } @@ -882,20 +812,20 @@ contract EzETHHyperdriveTest is InstanceTestV2 { } } - struct AccountBalances { - uint256 ezethBalance; - uint256 ETHBalance; - } - - function getAccountBalances( - address account - ) internal view returns (AccountBalances memory) { - return - AccountBalances({ - ezethBalance: EZETH.balanceOf(account), - ETHBalance: account.balance - }); - } + // struct AccountBalances { + // uint256 ezethBalance; + // uint256 ETHBalance; + // } + + // function getAccountBalances( + // address account + // ) internal view returns (AccountBalances memory) { + // return + // AccountBalances({ + // ezethBalance: EZETH.balanceOf(account), + // ETHBalance: account.balance + // }); + // } // returns share price information. function getSharePrice() diff --git a/test/instances/lseth/LsETHHyperdrive.t.sol b/test/instances/lseth/LsETHHyperdrive.t.sol index 7dc5c04f9..471beac10 100644 --- a/test/instances/lseth/LsETHHyperdrive.t.sol +++ b/test/instances/lseth/LsETHHyperdrive.t.sol @@ -105,14 +105,14 @@ contract LsETHHyperdriveTest is InstanceTestV2 { return (RIVER.totalUnderlyingSupply(), RIVER.totalSupply()); } - function _verifyDeposit( + function verifyDeposit( address trader, uint256 amount, bool asBase, uint totalBaseBefore, // unused uint256 totalSharesBefore, - AccountBalances2 memory traderBalancesBefore, - AccountBalances2 memory hyperdriveBalancesBefore + AccountBalances memory traderBalancesBefore, + AccountBalances memory hyperdriveBalancesBefore ) internal override { if (asBase) { revert IHyperdrive.NotPayable(); @@ -128,13 +128,15 @@ contract LsETHHyperdriveTest is InstanceTestV2 { assertEq(trader.balance, traderBalancesBefore.ETHBalance); // Ensure that the LsETH balances were updated correctly. - assertEq( + assertApproxEqAbs( RIVER.balanceOf(address(hyperdrive)), - hyperdriveBalancesBefore.sharesBalance + amount + hyperdriveBalancesBefore.sharesBalance + amount, + 1 ); - assertEq( + assertApproxEqAbs( RIVER.balanceOf(trader), - traderBalancesBefore.sharesBalance - amount + traderBalancesBefore.sharesBalance - amount, + 1 ); // Ensure the total supply was updated correctly. @@ -190,7 +192,10 @@ contract LsETHHyperdriveTest is InstanceTestV2 { function test_open_long_with_lseth(uint256 basePaid) external { // Get some balance information before the deposit. - uint256 totalSharesBefore = RIVER.totalSupply(); + ( + uint256 totalBaseSupplyBefore, + uint256 totalSharesSupplyBefore + ) = getSupply(); AccountBalances memory bobBalancesBefore = getAccountBalances(bob); AccountBalances memory hyperdriveBalancesBefore = getAccountBalances( address(hyperdrive) @@ -218,9 +223,10 @@ contract LsETHHyperdriveTest is InstanceTestV2 { // correctly during the trade. verifyDeposit( bob, - sharesPaid, + basePaid, false, - totalSharesBefore, + totalBaseSupplyBefore, + totalSharesSupplyBefore, bobBalancesBefore, hyperdriveBalancesBefore ); @@ -262,114 +268,114 @@ contract LsETHHyperdriveTest is InstanceTestV2 { assertEq(address(bob).balance, ethBalanceBefore); } - function test_close_long_with_eth( - uint256 basePaid, - int256 variableRate - ) external { - // Accrue interest for a term to ensure that the share price is greater - // than one. - advanceTime(POSITION_DURATION, 0.05e18); - vm.startPrank(bob); - - // Calculate the maximum amount of basePaid we can test. The limit is - // either the max long that Hyperdrive can open or the amount of LsETH - // tokens the trader has. - uint256 maxLongAmount = HyperdriveUtils.calculateMaxLong(hyperdrive); - uint256 maxEthAmount = RIVER.underlyingBalanceFromShares( - RIVER.balanceOf(bob) - ); - - // Bob opens a long, paying with LsETH. - basePaid = basePaid.normalizeToRange( - 2 * hyperdrive.getPoolConfig().minimumTransactionAmount, - maxLongAmount > maxEthAmount ? maxEthAmount : maxLongAmount - ); - uint256 sharesPaid = RIVER.sharesFromUnderlyingBalance(basePaid); - RIVER.approve(address(hyperdrive), sharesPaid); - (uint256 maturityTime, uint256 longAmount) = openLong( - bob, - sharesPaid, - false - ); - - // The term passes and some interest accrues. - variableRate = variableRate.normalizeToRange(0, 2.5e18); - advanceTime(POSITION_DURATION, variableRate); - - // Bob closes the long with ETH as the target asset. - vm.expectRevert(IHyperdrive.UnsupportedToken.selector); - hyperdrive.closeLong( - maturityTime, - longAmount, - 0, - IHyperdrive.Options({ - destination: bob, - asBase: true, - extraData: new bytes(0) - }) - ); - } - - function test_close_long_with_lseth( - uint256 basePaid, - int256 variableRate - ) external { - // Accrue interest for a term to ensure that the share price is greater - // than one. - advanceTime(POSITION_DURATION, 0.05e18); - vm.startPrank(bob); - - // Calculate the maximum amount of basePaid we can test. The limit is - // either the max long that Hyperdrive can open or the amount of LsETH - // tokens the trader has. - uint256 maxLongAmount = HyperdriveUtils.calculateMaxLong(hyperdrive); - uint256 maxEthAmount = RIVER.underlyingBalanceFromShares( - RIVER.balanceOf(bob) - ); - - // Bob opens a long by depositing LsETH. - basePaid = basePaid.normalizeToRange( - 2 * hyperdrive.getPoolConfig().minimumTransactionAmount, - maxLongAmount > maxEthAmount ? maxEthAmount : maxLongAmount - ); - uint256 sharesPaid = RIVER.sharesFromUnderlyingBalance(basePaid); - RIVER.approve(address(hyperdrive), sharesPaid); - (uint256 maturityTime, uint256 longAmount) = openLong( - bob, - sharesPaid, - false - ); - - // The term passes and some interest accrues. - variableRate = variableRate.normalizeToRange(0, 2.5e18); - advanceTime(POSITION_DURATION, variableRate); - - // Get some balance information before the withdrawal. - AccountBalances memory bobBalancesBefore = getAccountBalances(bob); - AccountBalances memory hyperdriveBalancesBefore = getAccountBalances( - address(hyperdrive) - ); - uint256 totalLsethSupplyBefore = RIVER.totalSupply(); - - // Bob closes his long with LsETH as the target asset. - uint256 shareProceeds = closeLong(bob, maturityTime, longAmount, false); - uint256 baseProceeds = RIVER.underlyingBalanceFromShares(shareProceeds); - - // Ensure Bob is credited the correct amount of bonds. - assertLe(baseProceeds, longAmount); - assertApproxEqAbs(baseProceeds, longAmount, 10); - - // Ensure that River aggregates and the token balances were updated - // correctly during the trade. - verifyLsethWithdrawal( - bob, - shareProceeds, - false, - totalLsethSupplyBefore, - bobBalancesBefore, - hyperdriveBalancesBefore - ); - } + // function test_close_long_with_eth( + // uint256 basePaid, + // int256 variableRate + // ) external { + // // Accrue interest for a term to ensure that the share price is greater + // // than one. + // advanceTime(POSITION_DURATION, 0.05e18); + // vm.startPrank(bob); + + // // Calculate the maximum amount of basePaid we can test. The limit is + // // either the max long that Hyperdrive can open or the amount of LsETH + // // tokens the trader has. + // uint256 maxLongAmount = HyperdriveUtils.calculateMaxLong(hyperdrive); + // uint256 maxEthAmount = RIVER.underlyingBalanceFromShares( + // RIVER.balanceOf(bob) + // ); + + // // Bob opens a long, paying with LsETH. + // basePaid = basePaid.normalizeToRange( + // 2 * hyperdrive.getPoolConfig().minimumTransactionAmount, + // maxLongAmount > maxEthAmount ? maxEthAmount : maxLongAmount + // ); + // uint256 sharesPaid = RIVER.sharesFromUnderlyingBalance(basePaid); + // RIVER.approve(address(hyperdrive), sharesPaid); + // (uint256 maturityTime, uint256 longAmount) = openLong( + // bob, + // sharesPaid, + // false + // ); + + // // The term passes and some interest accrues. + // variableRate = variableRate.normalizeToRange(0, 2.5e18); + // advanceTime(POSITION_DURATION, variableRate); + + // // Bob closes the long with ETH as the target asset. + // vm.expectRevert(IHyperdrive.UnsupportedToken.selector); + // hyperdrive.closeLong( + // maturityTime, + // longAmount, + // 0, + // IHyperdrive.Options({ + // destination: bob, + // asBase: true, + // extraData: new bytes(0) + // }) + // ); + // } + + // function test_close_long_with_lseth( + // uint256 basePaid, + // int256 variableRate + // ) external { + // // Accrue interest for a term to ensure that the share price is greater + // // than one. + // advanceTime(POSITION_DURATION, 0.05e18); + // vm.startPrank(bob); + + // // Calculate the maximum amount of basePaid we can test. The limit is + // // either the max long that Hyperdrive can open or the amount of LsETH + // // tokens the trader has. + // uint256 maxLongAmount = HyperdriveUtils.calculateMaxLong(hyperdrive); + // uint256 maxEthAmount = RIVER.underlyingBalanceFromShares( + // RIVER.balanceOf(bob) + // ); + + // // Bob opens a long by depositing LsETH. + // basePaid = basePaid.normalizeToRange( + // 2 * hyperdrive.getPoolConfig().minimumTransactionAmount, + // maxLongAmount > maxEthAmount ? maxEthAmount : maxLongAmount + // ); + // uint256 sharesPaid = RIVER.sharesFromUnderlyingBalance(basePaid); + // RIVER.approve(address(hyperdrive), sharesPaid); + // (uint256 maturityTime, uint256 longAmount) = openLong( + // bob, + // sharesPaid, + // false + // ); + + // // The term passes and some interest accrues. + // variableRate = variableRate.normalizeToRange(0, 2.5e18); + // advanceTime(POSITION_DURATION, variableRate); + + // // Get some balance information before the withdrawal. + // AccountBalances memory bobBalancesBefore = getAccountBalances(bob); + // AccountBalances memory hyperdriveBalancesBefore = getAccountBalances( + // address(hyperdrive) + // ); + // uint256 totalLsethSupplyBefore = RIVER.totalSupply(); + + // // Bob closes his long with LsETH as the target asset. + // uint256 shareProceeds = closeLong(bob, maturityTime, longAmount, false); + // uint256 baseProceeds = RIVER.underlyingBalanceFromShares(shareProceeds); + + // // Ensure Bob is credited the correct amount of bonds. + // assertLe(baseProceeds, longAmount); + // assertApproxEqAbs(baseProceeds, longAmount, 10); + + // // Ensure that River aggregates and the token balances were updated + // // correctly during the trade. + // verifyLsethWithdrawal( + // bob, + // shareProceeds, + // false, + // totalLsethSupplyBefore, + // bobBalancesBefore, + // hyperdriveBalancesBefore + // ); + // } /// Short /// @@ -396,6 +402,10 @@ contract LsETHHyperdriveTest is InstanceTestV2 { function test_open_short_with_lseth(uint256 shortAmount) external { // Get some balance information before the deposit. + ( + uint256 totalBaseSupplyBefore, + uint256 totalSharesSupplyBefore + ) = getSupply(); uint256 totalLsethSupplyBefore = RIVER.totalSupply(); AccountBalances memory bobBalancesBefore = getAccountBalances(bob); AccountBalances memory hyperdriveBalancesBefore = getAccountBalances( @@ -425,9 +435,10 @@ contract LsETHHyperdriveTest is InstanceTestV2 { // correctly during the trade. verifyDeposit( bob, - sharesPaid, + basePaid, false, - totalLsethSupplyBefore, + totalBaseSupplyBefore, + totalSharesSupplyBefore, bobBalancesBefore, hyperdriveBalancesBefore ); @@ -563,38 +574,38 @@ contract LsETHHyperdriveTest is InstanceTestV2 { ); } - function verifyDeposit( - address trader, - uint256 amount, - bool asBase, - uint256 totalSharesBefore, - AccountBalances memory traderBalancesBefore, - AccountBalances memory hyperdriveBalancesBefore - ) internal { - if (asBase) { - revert IHyperdrive.NotPayable(); - } - - // Ensure that the ether balances were updated correctly. - assertEq( - address(hyperdrive).balance, - hyperdriveBalancesBefore.ETHBalance - ); - assertEq(trader.balance, traderBalancesBefore.ETHBalance); - - // Ensure that the LsETH balances were updated correctly. - assertEq( - RIVER.balanceOf(address(hyperdrive)), - hyperdriveBalancesBefore.lsethBalance + amount - ); - assertEq( - RIVER.balanceOf(trader), - traderBalancesBefore.lsethBalance - amount - ); - - // Ensure the total supply was updated correctly. - assertEq(RIVER.totalSupply(), totalSharesBefore); - } + // function verifyDeposit( + // address trader, + // uint256 amount, + // bool asBase, + // uint256 totalSharesBefore, + // AccountBalances memory traderBalancesBefore, + // AccountBalances memory hyperdriveBalancesBefore + // ) internal { + // if (asBase) { + // revert IHyperdrive.NotPayable(); + // } + + // // Ensure that the ether balances were updated correctly. + // assertEq( + // address(hyperdrive).balance, + // hyperdriveBalancesBefore.ETHBalance + // ); + // assertEq(trader.balance, traderBalancesBefore.ETHBalance); + + // // Ensure that the LsETH balances were updated correctly. + // assertEq( + // RIVER.balanceOf(address(hyperdrive)), + // hyperdriveBalancesBefore.lsethBalance + amount + // ); + // assertEq( + // RIVER.balanceOf(trader), + // traderBalancesBefore.lsethBalance - amount + // ); + + // // Ensure the total supply was updated correctly. + // assertEq(RIVER.totalSupply(), totalSharesBefore); + // } function verifyLsethWithdrawal( address trader, @@ -621,11 +632,11 @@ contract LsETHHyperdriveTest is InstanceTestV2 { // Ensure the LsETH balances were updated correctly. assertEq( RIVER.balanceOf(address(hyperdrive)), - hyperdriveBalancesBefore.lsethBalance - amount + hyperdriveBalancesBefore.sharesBalance - amount ); assertEq( RIVER.balanceOf(address(trader)), - traderBalancesBefore.lsethBalance + amount + traderBalancesBefore.sharesBalance + amount ); } @@ -673,18 +684,18 @@ contract LsETHHyperdriveTest is InstanceTestV2 { assertGt(RIVER.underlyingBalanceFromShares(1e18), oldRate); } - struct AccountBalances { - uint256 lsethBalance; - uint256 ETHBalance; - } - - function getAccountBalances( - address account - ) internal view returns (AccountBalances memory) { - return - AccountBalances({ - lsethBalance: RIVER.balanceOf(account), - ETHBalance: account.balance - }); - } + // struct AccountBalances { + // uint256 lsethBalance; + // uint256 ETHBalance; + // } + + // function getAccountBalances( + // address account + // ) internal view returns (AccountBalances memory) { + // return + // AccountBalances({ + // lsethBalance: RIVER.balanceOf(account), + // ETHBalance: account.balance + // }); + // } } diff --git a/test/instances/reth/RETHHyperdrive.t.sol b/test/instances/reth/RETHHyperdrive.t.sol index e5c0692f4..17f994411 100644 --- a/test/instances/reth/RETHHyperdrive.t.sol +++ b/test/instances/reth/RETHHyperdrive.t.sol @@ -115,14 +115,14 @@ contract RETHHyperdriveTest is InstanceTestV2 { ); } - function _verifyDeposit( + function verifyDeposit( address trader, uint256 amount, bool asBase, uint256 totalBaseBefore, // unused uint256 totalSharesBefore, - AccountBalances2 memory traderBalancesBefore, - AccountBalances2 memory hyperdriveBalancesBefore + AccountBalances memory traderBalancesBefore, + AccountBalances memory hyperdriveBalancesBefore ) internal override { if (asBase) { revert IHyperdrive.UnsupportedToken(); @@ -138,13 +138,15 @@ contract RETHHyperdriveTest is InstanceTestV2 { assertEq(trader.balance, traderBalancesBefore.ETHBalance); // Ensure that the rETH balances were updated correctly. - assertEq( + assertApproxEqAbs( rocketTokenRETH.balanceOf(address(hyperdrive)), - hyperdriveBalancesBefore.sharesBalance + amount + hyperdriveBalancesBefore.sharesBalance + amount, + 1 ); - assertEq( + assertApproxEqAbs( rocketTokenRETH.balanceOf(trader), - traderBalancesBefore.sharesBalance - amount + traderBalancesBefore.sharesBalance - amount, + 1 ); // // Ensure the total supply was updated correctly. @@ -188,64 +190,68 @@ contract RETHHyperdriveTest is InstanceTestV2 { /// Long /// - function test_open_long_with_eth(uint256 basePaid) external { - // Bob opens a long by depositing ETH. This is not allowed and - // should throw an unsupported token exception. - vm.startPrank(bob); - basePaid = basePaid.normalizeToRange( - 2 * hyperdrive.getPoolConfig().minimumTransactionAmount, - HyperdriveUtils.calculateMaxLong(hyperdrive) - ); - vm.expectRevert(IHyperdrive.NotPayable.selector); - hyperdrive.openLong{ value: basePaid }( - basePaid, - 0, - 0, - IHyperdrive.Options({ - destination: bob, - asBase: true, - extraData: new bytes(0) - }) - ); - } - - function test_open_long_with_reth(uint256 basePaid) external { - // Get some balance information before the deposit. - uint256 totalSharesBefore = rocketTokenRETH.totalSupply(); - AccountBalances memory bobBalancesBefore = getAccountBalances(bob); - AccountBalances memory hyperdriveBalancesBefore = getAccountBalances( - address(hyperdrive) - ); - - // Calculate the maximum amount of basePaid we can test. The limit is - // either the max long that Hyperdrive can open or the amount of rETH - // tokens the trader has. - uint256 maxLongAmount = HyperdriveUtils.calculateMaxLong(hyperdrive); - uint256 maxEthAmount = rocketTokenRETH.getEthValue( - rocketTokenRETH.balanceOf(bob) - ); - - // Bob opens a long by depositing rETH. - vm.startPrank(bob); - basePaid = basePaid.normalizeToRange( - 2 * hyperdrive.getPoolConfig().minimumTransactionAmount, - maxLongAmount > maxEthAmount ? maxEthAmount : maxLongAmount - ); - uint256 sharesPaid = rocketTokenRETH.getRethValue(basePaid); - rocketTokenRETH.approve(address(hyperdrive), sharesPaid); - openLong(bob, sharesPaid, false); - - // Ensure that Rocket Pool's aggregates and the token balances were updated - // correctly during the trade. - verifyDeposit( - bob, - sharesPaid, - false, - totalSharesBefore, - bobBalancesBefore, - hyperdriveBalancesBefore - ); - } + // function test_open_long_with_eth(uint256 basePaid) external { + // // Bob opens a long by depositing ETH. This is not allowed and + // // should throw an unsupported token exception. + // vm.startPrank(bob); + // basePaid = basePaid.normalizeToRange( + // 2 * hyperdrive.getPoolConfig().minimumTransactionAmount, + // HyperdriveUtils.calculateMaxLong(hyperdrive) + // ); + // vm.expectRevert(IHyperdrive.NotPayable.selector); + // hyperdrive.openLong{ value: basePaid }( + // basePaid, + // 0, + // 0, + // IHyperdrive.Options({ + // destination: bob, + // asBase: true, + // extraData: new bytes(0) + // }) + // ); + // } + + // function test_open_long_with_reth(uint256 basePaid) external { + // // Get some balance information before the deposit. + // ( + // uint256 totalBaseSupplyBefore, + // uint256 totalSharesSupplyBefore + // ) = getSupply(); + // AccountBalances memory bobBalancesBefore = getAccountBalances(bob); + // AccountBalances memory hyperdriveBalancesBefore = getAccountBalances( + // address(hyperdrive) + // ); + + // // Calculate the maximum amount of basePaid we can test. The limit is + // // either the max long that Hyperdrive can open or the amount of rETH + // // tokens the trader has. + // uint256 maxLongAmount = HyperdriveUtils.calculateMaxLong(hyperdrive); + // uint256 maxEthAmount = rocketTokenRETH.getEthValue( + // rocketTokenRETH.balanceOf(bob) + // ); + + // // Bob opens a long by depositing rETH. + // vm.startPrank(bob); + // basePaid = basePaid.normalizeToRange( + // 2 * hyperdrive.getPoolConfig().minimumTransactionAmount, + // maxLongAmount > maxEthAmount ? maxEthAmount : maxLongAmount + // ); + // uint256 sharesPaid = rocketTokenRETH.getRethValue(basePaid); + // rocketTokenRETH.approve(address(hyperdrive), sharesPaid); + // openLong(bob, sharesPaid, false); + + // // Ensure that Rocket Pool's aggregates and the token balances were updated + // // correctly during the trade. + // verifyDeposit( + // bob, + // basePaid, + // false, + // totalBaseSupplyBefore, + // totalSharesSupplyBefore, + // bobBalancesBefore, + // hyperdriveBalancesBefore + // ); + // } function test_open_long_refunds() external { vm.startPrank(bob); @@ -429,7 +435,10 @@ contract RETHHyperdriveTest is InstanceTestV2 { function test_open_short_with_reth(uint256 shortAmount) external { // Get some balance information before the deposit. - uint256 totalRethSupplyBefore = rocketTokenRETH.totalSupply(); + ( + uint256 totalBaseSupplyBefore, + uint256 totalSharesSupplyBefore + ) = getSupply(); AccountBalances memory bobBalancesBefore = getAccountBalances(bob); AccountBalances memory hyperdriveBalancesBefore = getAccountBalances( address(hyperdrive) @@ -458,9 +467,10 @@ contract RETHHyperdriveTest is InstanceTestV2 { // correctly during the trade. verifyDeposit( bob, - sharesPaid, + basePaid, false, - totalRethSupplyBefore, + totalBaseSupplyBefore, + totalSharesSupplyBefore, bobBalancesBefore, hyperdriveBalancesBefore ); @@ -615,38 +625,38 @@ contract RETHHyperdriveTest is InstanceTestV2 { ); } - function verifyDeposit( - address trader, - uint256 amount, - bool asBase, - uint256 totalSharesBefore, - AccountBalances memory traderBalancesBefore, - AccountBalances memory hyperdriveBalancesBefore - ) internal { - if (asBase) { - revert IHyperdrive.UnsupportedToken(); - } - - // Ensure that the ether balances were updated correctly. - assertEq( - address(hyperdrive).balance, - hyperdriveBalancesBefore.ETHBalance - ); - assertEq(trader.balance, traderBalancesBefore.ETHBalance); - - // Ensure that the rETH balances were updated correctly. - assertEq( - rocketTokenRETH.balanceOf(address(hyperdrive)), - hyperdriveBalancesBefore.rethBalance + amount - ); - assertEq( - rocketTokenRETH.balanceOf(trader), - traderBalancesBefore.rethBalance - amount - ); - - // Ensure the total supply was updated correctly. - assertEq(rocketTokenRETH.totalSupply(), totalSharesBefore); - } + // function verifyDeposit( + // address trader, + // uint256 amount, + // bool asBase, + // uint256 totalSharesBefore, + // AccountBalances memory traderBalancesBefore, + // AccountBalances memory hyperdriveBalancesBefore + // ) internal { + // if (asBase) { + // revert IHyperdrive.UnsupportedToken(); + // } + + // // Ensure that the ether balances were updated correctly. + // assertEq( + // address(hyperdrive).balance, + // hyperdriveBalancesBefore.ETHBalance + // ); + // assertEq(trader.balance, traderBalancesBefore.ETHBalance); + + // // Ensure that the rETH balances were updated correctly. + // assertEq( + // rocketTokenRETH.balanceOf(address(hyperdrive)), + // hyperdriveBalancesBefore.rethBalance + amount + // ); + // assertEq( + // rocketTokenRETH.balanceOf(trader), + // traderBalancesBefore.rethBalance - amount + // ); + + // // Ensure the total supply was updated correctly. + // assertEq(rocketTokenRETH.totalSupply(), totalSharesBefore); + // } function verifyRethWithdrawal( address trader, @@ -676,12 +686,12 @@ contract RETHHyperdriveTest is InstanceTestV2 { // Ensure the rETH balances were updated correctly. assertApproxEqAbs( rocketTokenRETH.balanceOf(address(hyperdrive)), - hyperdriveBalancesBefore.rethBalance - amountAsShares, + hyperdriveBalancesBefore.sharesBalance - amountAsShares, 1 ); assertEq( rocketTokenRETH.balanceOf(address(trader)), - traderBalancesBefore.rethBalance + traderBalancesBefore.sharesBalance ); } else { // Ensure the total amount of rETH stays the same. @@ -697,11 +707,11 @@ contract RETHHyperdriveTest is InstanceTestV2 { // Ensure the rETH balances were updated correctly. assertEq( rocketTokenRETH.balanceOf(address(hyperdrive)), - hyperdriveBalancesBefore.rethBalance - amount + hyperdriveBalancesBefore.sharesBalance - amount ); assertEq( rocketTokenRETH.balanceOf(address(trader)), - traderBalancesBefore.rethBalance + amount + traderBalancesBefore.sharesBalance + amount ); } } @@ -747,18 +757,18 @@ contract RETHHyperdriveTest is InstanceTestV2 { assertGt(rocketTokenRETH.getExchangeRate(), oldRate); } - struct AccountBalances { - uint256 rethBalance; - uint256 ETHBalance; - } - - function getAccountBalances( - address account - ) internal view returns (AccountBalances memory) { - return - AccountBalances({ - rethBalance: rocketTokenRETH.balanceOf(account), - ETHBalance: account.balance - }); - } + // struct AccountBalances { + // uint256 rethBalance; + // uint256 ETHBalance; + // } + + // function getAccountBalances( + // address account + // ) internal view returns (AccountBalances memory) { + // return + // AccountBalances({ + // rethBalance: rocketTokenRETH.balanceOf(account), + // ETHBalance: account.balance + // }); + // } } diff --git a/test/instances/steth/StETHHyperdrive.t.sol b/test/instances/steth/StETHHyperdrive.t.sol index 6264a4a80..22ec1c5f5 100644 --- a/test/instances/steth/StETHHyperdrive.t.sol +++ b/test/instances/steth/StETHHyperdrive.t.sol @@ -101,14 +101,14 @@ contract StETHHyperdriveTest is InstanceTestV2 { ); } - function _verifyDeposit( + function verifyDeposit( address trader, uint256 amountPaid, bool asBase, uint256 totalBaseBefore, uint256 totalSharesBefore, - AccountBalances2 memory traderBalancesBefore, - AccountBalances2 memory hyperdriveBalancesBefore + AccountBalances memory traderBalancesBefore, + AccountBalances memory hyperdriveBalancesBefore ) internal override { if (asBase) { // Ensure that the amount of pooled ether increased by the base paid. @@ -210,35 +210,6 @@ contract StETHHyperdriveTest is InstanceTestV2 { /// Long /// - function test_open_long_with_ETH(uint256 basePaid) external { - // Get some balance information before the deposit. - uint256 totalPooledEtherBefore = LIDO.getTotalPooledEther(); - uint256 totalSharesBefore = LIDO.getTotalShares(); - AccountBalances memory bobBalancesBefore = getAccountBalances(bob); - AccountBalances memory hyperdriveBalancesBefore = getAccountBalances( - address(hyperdrive) - ); - - // Bob opens a long by depositing ETH. - basePaid = basePaid.normalizeToRange( - 2 * hyperdrive.getPoolConfig().minimumTransactionAmount, - HyperdriveUtils.calculateMaxLong(hyperdrive) - ); - openLong(bob, basePaid); - - // Ensure that Lido's aggregates and the token balances were updated - // correctly during the trade. - verifyDeposit( - bob, - basePaid, - true, - totalPooledEtherBefore, - totalSharesBefore, - bobBalancesBefore, - hyperdriveBalancesBefore - ); - } - function test_open_long_refunds() external { vm.startPrank(bob); @@ -273,39 +244,6 @@ contract StETHHyperdriveTest is InstanceTestV2 { assertEq(address(bob).balance, ethBalanceBefore); } - function test_open_long_with_steth(uint256 basePaid) external { - // Get some balance information before the deposit. - uint256 totalPooledEtherBefore = LIDO.getTotalPooledEther(); - uint256 totalSharesBefore = LIDO.getTotalShares(); - AccountBalances memory bobBalancesBefore = getAccountBalances(bob); - AccountBalances memory hyperdriveBalancesBefore = getAccountBalances( - address(hyperdrive) - ); - - // Bob opens a long by depositing stETH. - basePaid = basePaid.normalizeToRange( - 2 * hyperdrive.getPoolConfig().minimumTransactionAmount, - HyperdriveUtils.calculateMaxLong(hyperdrive) - ); - uint256 sharesPaid = basePaid.mulDivDown( - LIDO.getTotalShares(), - LIDO.getTotalPooledEther() - ); - openLong(bob, sharesPaid, false); - - // Ensure that Lido's aggregates and the token balances were updated - // correctly during the trade. - verifyDeposit( - bob, - basePaid, - false, - totalPooledEtherBefore, - totalSharesBefore, - bobBalancesBefore, - hyperdriveBalancesBefore - ); - } - function test_close_long_with_ETH(uint256 basePaid) external { // Bob opens a long. basePaid = basePaid.normalizeToRange( @@ -747,89 +685,89 @@ contract StETHHyperdriveTest is InstanceTestV2 { closeLong(bob, maturityTime_, longAmount_ / 2, false); } - function verifyDeposit( - address trader, - uint256 basePaid, - bool asBase, - uint256 totalPooledEtherBefore, - uint256 totalSharesBefore, - AccountBalances memory traderBalancesBefore, - AccountBalances memory hyperdriveBalancesBefore - ) internal { - if (asBase) { - // Ensure that the amount of pooled ether increased by the base paid. - assertEq( - LIDO.getTotalPooledEther(), - totalPooledEtherBefore + basePaid - ); - - // Ensure that the ETH balances were updated correctly. - assertEq( - address(hyperdrive).balance, - hyperdriveBalancesBefore.ETHBalance - ); - assertEq(bob.balance, traderBalancesBefore.ETHBalance - basePaid); - - // Ensure that the stETH balances were updated correctly. - assertApproxEqAbs( - LIDO.balanceOf(address(hyperdrive)), - hyperdriveBalancesBefore.stethBalance + basePaid, - 1 - ); - assertEq(LIDO.balanceOf(trader), traderBalancesBefore.stethBalance); - - // Ensure that the stETH shares were updated correctly. - uint256 expectedShares = basePaid.mulDivDown( - totalSharesBefore, - totalPooledEtherBefore - ); - assertEq(LIDO.getTotalShares(), totalSharesBefore + expectedShares); - assertEq( - LIDO.sharesOf(address(hyperdrive)), - hyperdriveBalancesBefore.stethShares + expectedShares - ); - assertEq(LIDO.sharesOf(bob), traderBalancesBefore.stethShares); - } else { - // Ensure that the amount of pooled ether stays the same. - assertEq(LIDO.getTotalPooledEther(), totalPooledEtherBefore); - - // Ensure that the ETH balances were updated correctly. - assertEq( - address(hyperdrive).balance, - hyperdriveBalancesBefore.ETHBalance - ); - assertEq(trader.balance, traderBalancesBefore.ETHBalance); - - // Ensure that the stETH balances were updated correctly. - assertApproxEqAbs( - LIDO.balanceOf(address(hyperdrive)), - hyperdriveBalancesBefore.stethBalance + basePaid, - 1 - ); - assertApproxEqAbs( - LIDO.balanceOf(trader), - traderBalancesBefore.stethBalance - basePaid, - 1 - ); - - // Ensure that the stETH shares were updated correctly. - uint256 expectedShares = basePaid.mulDivDown( - totalSharesBefore, - totalPooledEtherBefore - ); - assertEq(LIDO.getTotalShares(), totalSharesBefore); - assertApproxEqAbs( - LIDO.sharesOf(address(hyperdrive)), - hyperdriveBalancesBefore.stethShares + expectedShares, - 1 - ); - assertApproxEqAbs( - LIDO.sharesOf(trader), - traderBalancesBefore.stethShares - expectedShares, - 1 - ); - } - } + // function verifyDeposit( + // address trader, + // uint256 basePaid, + // bool asBase, + // uint256 totalPooledEtherBefore, + // uint256 totalSharesBefore, + // AccountBalances memory traderBalancesBefore, + // AccountBalances memory hyperdriveBalancesBefore + // ) internal { + // if (asBase) { + // // Ensure that the amount of pooled ether increased by the base paid. + // assertEq( + // LIDO.getTotalPooledEther(), + // totalPooledEtherBefore + basePaid + // ); + + // // Ensure that the ETH balances were updated correctly. + // assertEq( + // address(hyperdrive).balance, + // hyperdriveBalancesBefore.ETHBalance + // ); + // assertEq(bob.balance, traderBalancesBefore.ETHBalance - basePaid); + + // // Ensure that the stETH balances were updated correctly. + // assertApproxEqAbs( + // LIDO.balanceOf(address(hyperdrive)), + // hyperdriveBalancesBefore.stethBalance + basePaid, + // 1 + // ); + // assertEq(LIDO.balanceOf(trader), traderBalancesBefore.stethBalance); + + // // Ensure that the stETH shares were updated correctly. + // uint256 expectedShares = basePaid.mulDivDown( + // totalSharesBefore, + // totalPooledEtherBefore + // ); + // assertEq(LIDO.getTotalShares(), totalSharesBefore + expectedShares); + // assertEq( + // LIDO.sharesOf(address(hyperdrive)), + // hyperdriveBalancesBefore.stethShares + expectedShares + // ); + // assertEq(LIDO.sharesOf(bob), traderBalancesBefore.stethShares); + // } else { + // // Ensure that the amount of pooled ether stays the same. + // assertEq(LIDO.getTotalPooledEther(), totalPooledEtherBefore); + + // // Ensure that the ETH balances were updated correctly. + // assertEq( + // address(hyperdrive).balance, + // hyperdriveBalancesBefore.ETHBalance + // ); + // assertEq(trader.balance, traderBalancesBefore.ETHBalance); + + // // Ensure that the stETH balances were updated correctly. + // assertApproxEqAbs( + // LIDO.balanceOf(address(hyperdrive)), + // hyperdriveBalancesBefore.stethBalance + basePaid, + // 1 + // ); + // assertApproxEqAbs( + // LIDO.balanceOf(trader), + // traderBalancesBefore.stethBalance - basePaid, + // 1 + // ); + + // // Ensure that the stETH shares were updated correctly. + // uint256 expectedShares = basePaid.mulDivDown( + // totalSharesBefore, + // totalPooledEtherBefore + // ); + // assertEq(LIDO.getTotalShares(), totalSharesBefore); + // assertApproxEqAbs( + // LIDO.sharesOf(address(hyperdrive)), + // hyperdriveBalancesBefore.stethShares + expectedShares, + // 1 + // ); + // assertApproxEqAbs( + // LIDO.sharesOf(trader), + // traderBalancesBefore.stethShares - expectedShares, + // 1 + // ); + // } + // } function verifyStethWithdrawal( address trader, @@ -853,12 +791,12 @@ contract StETHHyperdriveTest is InstanceTestV2 { // Ensure that the stETH balances were updated correctly. assertApproxEqAbs( LIDO.balanceOf(address(hyperdrive)), - hyperdriveBalancesBefore.stethBalance - baseProceeds, + hyperdriveBalancesBefore.baseBalance - baseProceeds, 1 ); assertApproxEqAbs( LIDO.balanceOf(trader), - traderBalancesBefore.stethBalance + baseProceeds, + traderBalancesBefore.baseBalance + baseProceeds, 1 ); @@ -869,12 +807,12 @@ contract StETHHyperdriveTest is InstanceTestV2 { ); assertApproxEqAbs( LIDO.sharesOf(address(hyperdrive)), - hyperdriveBalancesBefore.stethShares - expectedShares, + hyperdriveBalancesBefore.sharesBalance - expectedShares, 1 ); assertApproxEqAbs( LIDO.sharesOf(trader), - traderBalancesBefore.stethShares + expectedShares, + traderBalancesBefore.sharesBalance + expectedShares, 1 ); } @@ -904,20 +842,20 @@ contract StETHHyperdriveTest is InstanceTestV2 { ); } - struct AccountBalances { - uint256 stethShares; - uint256 stethBalance; - uint256 ETHBalance; - } - - function getAccountBalances( - address account - ) internal view returns (AccountBalances memory) { - return - AccountBalances({ - stethShares: LIDO.sharesOf(account), - stethBalance: LIDO.balanceOf(account), - ETHBalance: account.balance - }); - } + // struct AccountBalances { + // uint256 stethShares; + // uint256 stethBalance; + // uint256 ETHBalance; + // } + + // function getAccountBalances( + // address account + // ) internal view returns (AccountBalances memory) { + // return + // AccountBalances({ + // stethShares: LIDO.sharesOf(account), + // stethBalance: LIDO.balanceOf(account), + // ETHBalance: account.balance + // }); + // } } diff --git a/test/utils/InstanceTestV2.sol b/test/utils/InstanceTestV2.sol index 0f700f4b9..aaa8594d4 100644 --- a/test/utils/InstanceTestV2.sol +++ b/test/utils/InstanceTestV2.sol @@ -459,7 +459,7 @@ abstract contract InstanceTestV2 is HyperdriveTest { ); } - struct AccountBalances2 { + struct AccountBalances { uint256 sharesBalance; uint256 baseBalance; uint256 ETHBalance; @@ -471,27 +471,27 @@ abstract contract InstanceTestV2 is HyperdriveTest { function getSupply() internal virtual returns (uint256, uint256); - function _getAccountBalances( + function getAccountBalances( address account - ) internal view returns (AccountBalances2 memory) { + ) internal view returns (AccountBalances memory) { (uint256 shares, uint256 base) = getTokenBalances(account); return - AccountBalances2({ + AccountBalances({ sharesBalance: shares, baseBalance: base, ETHBalance: account.balance }); } - function _verifyDeposit( + function verifyDeposit( address trader, uint256 amountPaid, bool asBase, uint256 totalBaseBefore, uint256 totalSharesBefore, - AccountBalances2 memory traderBalancesBefore, - AccountBalances2 memory hyperdriveBalancesBefore + AccountBalances memory traderBalancesBefore, + AccountBalances memory hyperdriveBalancesBefore ) internal virtual; function test__open_long_with_shares(uint256 basePaid) external { @@ -500,8 +500,8 @@ abstract contract InstanceTestV2 is HyperdriveTest { uint256 totalSharesSupplyBefore ) = getSupply(); - AccountBalances2 memory bobBalancesBefore = _getAccountBalances(bob); - AccountBalances2 memory hyperdriveBalanceBefore = _getAccountBalances( + AccountBalances memory bobBalancesBefore = getAccountBalances(bob); + AccountBalances memory hyperdriveBalanceBefore = getAccountBalances( address(hyperdrive) ); @@ -520,7 +520,7 @@ abstract contract InstanceTestV2 is HyperdriveTest { uint256 sharesPaid = convertToShares(basePaid); openLong(bob, sharesPaid, false); - _verifyDeposit( + verifyDeposit( bob, basePaid, false, @@ -537,8 +537,8 @@ abstract contract InstanceTestV2 is HyperdriveTest { uint256 totalSharesSupplyBefore ) = getSupply(); - AccountBalances2 memory bobBalancesBefore = _getAccountBalances(bob); - AccountBalances2 memory hyperdriveBalanceBefore = _getAccountBalances( + AccountBalances memory bobBalancesBefore = getAccountBalances(bob); + AccountBalances memory hyperdriveBalanceBefore = getAccountBalances( address(hyperdrive) ); @@ -573,7 +573,7 @@ abstract contract InstanceTestV2 is HyperdriveTest { // openLong(bob, basePaid, true); if (config.enableBaseDeposits) { - _verifyDeposit( + verifyDeposit( bob, basePaid, true, @@ -584,94 +584,4 @@ abstract contract InstanceTestV2 is HyperdriveTest { ); } } - - // function verifyDeposit( - // address trader, - // uint256 amountPaid, - // bool asBase, - // uint256 totalBaseBefore, - // uint256 totalSharesBefore, - // AccountBalances memory traderBalancesBefore, - // AccountBalances memory hyperdriveBalancesBefore - // ) internal { - // if (asBase) { - // // // Ensure that the amount of pooled ether increased by the base paid. - // // assertEq(LIDO.getTotalPooledEther(), totalBaseBefore + basePaid); - // // // Ensure that the ETH balances were updated correctly. - // // assertEq( - // // address(hyperdrive).balance, - // // hyperdriveBalancesBefore.ethBalance - // // ); - // // assertEq(bob.balance, traderBalancesBefore.ethBalance - basePaid); - // // // Ensure that the stETH balances were updated correctly. - // // assertApproxEqAbs( - // // LIDO.balanceOf(address(hyperdrive)), - // // hyperdriveBalancesBefore.stethBalance + basePaid, - // // 1 - // // ); - // // assertEq(LIDO.balanceOf(trader), traderBalancesBefore.stethBalance); - // // // Ensure that the stETH shares were updated correctly. - // // uint256 expectedShares = basePaid.mulDivDown( - // // totalSharesBefore, - // // totalBaseBefore - // // ); - // // assertEq(LIDO.getTotalShares(), totalSharesBefore + expectedShares); - // // assertEq( - // // LIDO.sharesOf(address(hyperdrive)), - // // hyperdriveBalancesBefore.stethShares + expectedShares - // // ); - // // assertEq(LIDO.sharesOf(bob), traderBalancesBefore.stethShares); - // } else { - // ( - // uint256 totalBaseSupplyNow, - // uint256 totalSharesSupplyNow - // ) = getSupply(); - - // (uint256 traderShares, uint256 traderBase) = getTokenBalances( - // trader - // ); - // ( - // uint256 hyperdriveShares, - // uint256 hyperdriveBase - // ) = getTokenBalances(address(hyperdrive)); - // // Ensure that the amount of pooled ether stays the same. - // assertEq(totalBaseSupplyNow, totalBaseBefore); - - // // Ensure that the ETH balances were updated correctly. - // assertEq( - // address(hyperdrive).balance, - // hyperdriveBalancesBefore.ethBalance - // ); - // assertEq(trader.balance, traderBalancesBefore.ethBalance); - - // // Ensure that the stETH balances were updated correctly. - // assertApproxEqAbs( - // LIDO.balanceOf(address(hyperdrive)), - // hyperdriveBalancesBefore.baseBalance + basePaid, - // 1 - // ); - // assertApproxEqAbs( - // LIDO.balanceOf(trader), - // traderBalancesBefore.stethBalance - basePaid, - // 1 - // ); - - // // Ensure that the stETH shares were updated correctly. - // uint256 expectedShares = basePaid.mulDivDown( - // totalSharesBefore, - // totalBaseBefore - // ); - // assertEq(LIDO.getTotalShares(), totalSharesBefore); - // assertApproxEqAbs( - // LIDO.sharesOf(address(hyperdrive)), - // hyperdriveBalancesBefore.stethShares + expectedShares, - // 1 - // ); - // assertApproxEqAbs( - // LIDO.sharesOf(trader), - // traderBalancesBefore.stethShares - expectedShares, - // 1 - // ); - // } - // } } From 600c7481b03ff37b4be6789317a2d89efc21a653 Mon Sep 17 00:00:00 2001 From: Cash Baller Date: Tue, 26 Mar 2024 22:05:25 -0500 Subject: [PATCH 04/21] Bigger delta for ezeth verifyDeposit --- test/instances/ezETH/EzETHHyperdrive.t.sol | 87 +--------------------- 1 file changed, 2 insertions(+), 85 deletions(-) diff --git a/test/instances/ezETH/EzETHHyperdrive.t.sol b/test/instances/ezETH/EzETHHyperdrive.t.sol index 2aca90aa6..f3629db63 100644 --- a/test/instances/ezETH/EzETHHyperdrive.t.sol +++ b/test/instances/ezETH/EzETHHyperdrive.t.sol @@ -182,12 +182,12 @@ contract EzETHHyperdriveTest is InstanceTestV2 { assertApproxEqAbs( EZETH.balanceOf(address(hyperdrive)), hyperdriveBalancesBefore.sharesBalance + expectedShares, - 1 + 2 ); assertApproxEqAbs( EZETH.balanceOf(trader), traderBalancesBefore.sharesBalance - expectedShares, - 1 + 2 ); } } @@ -262,74 +262,6 @@ contract EzETHHyperdriveTest is InstanceTestV2 { /// Long /// - // function test_open_long_with_eth(uint256 basePaid) external { - // // Bob opens a long by depositing ETH. - // basePaid = basePaid.normalizeToRange( - // 2 * hyperdrive.getPoolConfig().minimumTransactionAmount, - // HyperdriveUtils.calculateMaxLong(hyperdrive) - // ); - - // // Ensure that we get an UnsupportedToken error. Opening positions - // // with ETH are not allowed right now. There is a great enough - // // precision loss when minting ezeth that warrants some investigation - // // before we can turn this on. Until then, we can zap ezeth into the - // // pool. - // vm.expectRevert(IHyperdrive.NotPayable.selector); - // hyperdrive.openLong{ value: basePaid }( - // basePaid, - // 0, // min bond proceeds - // 0, // min vault share price - // IHyperdrive.Options({ - // destination: bob, - // asBase: true, - // extraData: new bytes(0) - // }) - // ); - // } - - // function test_open_long_with_ezeth(uint256 basePaid) external { - // vm.stopPrank(); - // vm.startPrank(bob); - - // // Get some balance information before the deposit. - // ( - // , - // uint256 totalPooledEtherBefore, - // uint256 totalSharesBefore - // ) = getSharePrice(); - // AccountBalances memory bobBalancesBefore = getAccountBalances(bob); - // AccountBalances memory hyperdriveBalancesBefore = getAccountBalances( - // address(hyperdrive) - // ); - - // // Calculate the maximum amount of basePaid we can test. - // uint256 maxLong = HyperdriveUtils.calculateMaxLong(hyperdrive); - // uint256 maxEzEth = EZETH.balanceOf(address(bob)); - // uint256 maxRange = maxLong > maxEzEth ? maxEzEth : maxLong; - // basePaid = basePaid.normalizeToRange( - // 2 * hyperdrive.getPoolConfig().minimumTransactionAmount, - // maxRange - // ); - - // // Convert to shares and approve hyperdrive. - // uint256 sharesPaid = getAndApproveShares(basePaid); - - // // Open the position. - // openLong(bob, sharesPaid, false); - - // // Ensure that Renzo's aggregates and the token balances were updated - // // correctly during the trade. - // verifyDeposit( - // bob, - // basePaid, - // false, - // totalPooledEtherBefore, - // totalSharesBefore, - // bobBalancesBefore, - // hyperdriveBalancesBefore - // ); - // } - function test_close_long_with_eth(uint256 basePaid) external { vm.stopPrank(); vm.startPrank(bob); @@ -812,21 +744,6 @@ contract EzETHHyperdriveTest is InstanceTestV2 { } } - // struct AccountBalances { - // uint256 ezethBalance; - // uint256 ETHBalance; - // } - - // function getAccountBalances( - // address account - // ) internal view returns (AccountBalances memory) { - // return - // AccountBalances({ - // ezethBalance: EZETH.balanceOf(account), - // ETHBalance: account.balance - // }); - // } - // returns share price information. function getSharePrice() internal From 93d3a992b6da802f783bc8d1d4fa431ddb93fa65 Mon Sep 17 00:00:00 2001 From: Cash Baller Date: Tue, 26 Mar 2024 22:05:32 -0500 Subject: [PATCH 05/21] remove unused code and comments --- test/instances/lseth/LsETHHyperdrive.t.sol | 313 +++++++-------------- test/instances/reth/RETHHyperdrive.t.sol | 78 ----- test/instances/steth/StETHHyperdrive.t.sol | 17 -- 3 files changed, 101 insertions(+), 307 deletions(-) diff --git a/test/instances/lseth/LsETHHyperdrive.t.sol b/test/instances/lseth/LsETHHyperdrive.t.sol index 471beac10..bbfbb6fb7 100644 --- a/test/instances/lseth/LsETHHyperdrive.t.sol +++ b/test/instances/lseth/LsETHHyperdrive.t.sol @@ -169,17 +169,14 @@ contract LsETHHyperdriveTest is InstanceTestV2 { /// Long /// - function test_open_long_with_eth(uint256 basePaid) external { - // Bob opens a long by depositing ETH. This is not allowed and - // should throw an unsupported token exception. + function test_open_long_refunds() external { vm.startPrank(bob); - basePaid = basePaid.normalizeToRange( - 2 * hyperdrive.getPoolConfig().minimumTransactionAmount, - HyperdriveUtils.calculateMaxLong(hyperdrive) - ); + + // Ensure that the call fails when he opens a long with "asBase" + // set to true and sends ether to the contract. vm.expectRevert(IHyperdrive.NotPayable.selector); - hyperdrive.openLong{ value: basePaid }( - basePaid, + hyperdrive.openLong{ value: 2e18 }( + 1e18, 0, 0, IHyperdrive.Options({ @@ -188,18 +185,34 @@ contract LsETHHyperdriveTest is InstanceTestV2 { extraData: new bytes(0) }) ); - } - function test_open_long_with_lseth(uint256 basePaid) external { - // Get some balance information before the deposit. - ( - uint256 totalBaseSupplyBefore, - uint256 totalSharesSupplyBefore - ) = getSupply(); - AccountBalances memory bobBalancesBefore = getAccountBalances(bob); - AccountBalances memory hyperdriveBalancesBefore = getAccountBalances( - address(hyperdrive) + // Ensure that the call fails when he opens a long with "asBase" + // set to false and sends ether to the contract. + uint256 sharesPaid = 1e18; + uint256 ethBalanceBefore = address(bob).balance; + RIVER.approve(address(hyperdrive), sharesPaid); + vm.expectRevert(IHyperdrive.NotPayable.selector); + hyperdrive.openLong{ value: sharesPaid }( + sharesPaid, + 0, + 0, + IHyperdrive.Options({ + destination: bob, + asBase: false, + extraData: new bytes(0) + }) ); + assertEq(address(bob).balance, ethBalanceBefore); + } + + function test_close_long_with_eth( + uint256 basePaid, + int256 variableRate + ) external { + // Accrue interest for a term to ensure that the share price is greater + // than one. + advanceTime(POSITION_DURATION, 0.05e18); + vm.startPrank(bob); // Calculate the maximum amount of basePaid we can test. The limit is // either the max long that Hyperdrive can open or the amount of LsETH @@ -209,38 +222,28 @@ contract LsETHHyperdriveTest is InstanceTestV2 { RIVER.balanceOf(bob) ); - // Bob opens a long by depositing LsETH. - vm.startPrank(bob); + // Bob opens a long, paying with LsETH. basePaid = basePaid.normalizeToRange( 2 * hyperdrive.getPoolConfig().minimumTransactionAmount, maxLongAmount > maxEthAmount ? maxEthAmount : maxLongAmount ); uint256 sharesPaid = RIVER.sharesFromUnderlyingBalance(basePaid); RIVER.approve(address(hyperdrive), sharesPaid); - openLong(bob, sharesPaid, false); - - // Ensure that River aggregates and the token balances were updated - // correctly during the trade. - verifyDeposit( + (uint256 maturityTime, uint256 longAmount) = openLong( bob, - basePaid, - false, - totalBaseSupplyBefore, - totalSharesSupplyBefore, - bobBalancesBefore, - hyperdriveBalancesBefore + sharesPaid, + false ); - } - function test_open_long_refunds() external { - vm.startPrank(bob); + // The term passes and some interest accrues. + variableRate = variableRate.normalizeToRange(0, 2.5e18); + advanceTime(POSITION_DURATION, variableRate); - // Ensure that the call fails when he opens a long with "asBase" - // set to true and sends ether to the contract. - vm.expectRevert(IHyperdrive.NotPayable.selector); - hyperdrive.openLong{ value: 2e18 }( - 1e18, - 0, + // Bob closes the long with ETH as the target asset. + vm.expectRevert(IHyperdrive.UnsupportedToken.selector); + hyperdrive.closeLong( + maturityTime, + longAmount, 0, IHyperdrive.Options({ destination: bob, @@ -248,134 +251,68 @@ contract LsETHHyperdriveTest is InstanceTestV2 { extraData: new bytes(0) }) ); + } - // Ensure that the call fails when he opens a long with "asBase" - // set to false and sends ether to the contract. - uint256 sharesPaid = 1e18; - uint256 ethBalanceBefore = address(bob).balance; + function test_close_long_with_lseth( + uint256 basePaid, + int256 variableRate + ) external { + // Accrue interest for a term to ensure that the share price is greater + // than one. + advanceTime(POSITION_DURATION, 0.05e18); + vm.startPrank(bob); + + // Calculate the maximum amount of basePaid we can test. The limit is + // either the max long that Hyperdrive can open or the amount of LsETH + // tokens the trader has. + uint256 maxLongAmount = HyperdriveUtils.calculateMaxLong(hyperdrive); + uint256 maxEthAmount = RIVER.underlyingBalanceFromShares( + RIVER.balanceOf(bob) + ); + + // Bob opens a long by depositing LsETH. + basePaid = basePaid.normalizeToRange( + 2 * hyperdrive.getPoolConfig().minimumTransactionAmount, + maxLongAmount > maxEthAmount ? maxEthAmount : maxLongAmount + ); + uint256 sharesPaid = RIVER.sharesFromUnderlyingBalance(basePaid); RIVER.approve(address(hyperdrive), sharesPaid); - vm.expectRevert(IHyperdrive.NotPayable.selector); - hyperdrive.openLong{ value: sharesPaid }( + (uint256 maturityTime, uint256 longAmount) = openLong( + bob, sharesPaid, - 0, - 0, - IHyperdrive.Options({ - destination: bob, - asBase: false, - extraData: new bytes(0) - }) + false ); - assertEq(address(bob).balance, ethBalanceBefore); - } - // function test_close_long_with_eth( - // uint256 basePaid, - // int256 variableRate - // ) external { - // // Accrue interest for a term to ensure that the share price is greater - // // than one. - // advanceTime(POSITION_DURATION, 0.05e18); - // vm.startPrank(bob); - - // // Calculate the maximum amount of basePaid we can test. The limit is - // // either the max long that Hyperdrive can open or the amount of LsETH - // // tokens the trader has. - // uint256 maxLongAmount = HyperdriveUtils.calculateMaxLong(hyperdrive); - // uint256 maxEthAmount = RIVER.underlyingBalanceFromShares( - // RIVER.balanceOf(bob) - // ); - - // // Bob opens a long, paying with LsETH. - // basePaid = basePaid.normalizeToRange( - // 2 * hyperdrive.getPoolConfig().minimumTransactionAmount, - // maxLongAmount > maxEthAmount ? maxEthAmount : maxLongAmount - // ); - // uint256 sharesPaid = RIVER.sharesFromUnderlyingBalance(basePaid); - // RIVER.approve(address(hyperdrive), sharesPaid); - // (uint256 maturityTime, uint256 longAmount) = openLong( - // bob, - // sharesPaid, - // false - // ); - - // // The term passes and some interest accrues. - // variableRate = variableRate.normalizeToRange(0, 2.5e18); - // advanceTime(POSITION_DURATION, variableRate); - - // // Bob closes the long with ETH as the target asset. - // vm.expectRevert(IHyperdrive.UnsupportedToken.selector); - // hyperdrive.closeLong( - // maturityTime, - // longAmount, - // 0, - // IHyperdrive.Options({ - // destination: bob, - // asBase: true, - // extraData: new bytes(0) - // }) - // ); - // } - - // function test_close_long_with_lseth( - // uint256 basePaid, - // int256 variableRate - // ) external { - // // Accrue interest for a term to ensure that the share price is greater - // // than one. - // advanceTime(POSITION_DURATION, 0.05e18); - // vm.startPrank(bob); - - // // Calculate the maximum amount of basePaid we can test. The limit is - // // either the max long that Hyperdrive can open or the amount of LsETH - // // tokens the trader has. - // uint256 maxLongAmount = HyperdriveUtils.calculateMaxLong(hyperdrive); - // uint256 maxEthAmount = RIVER.underlyingBalanceFromShares( - // RIVER.balanceOf(bob) - // ); - - // // Bob opens a long by depositing LsETH. - // basePaid = basePaid.normalizeToRange( - // 2 * hyperdrive.getPoolConfig().minimumTransactionAmount, - // maxLongAmount > maxEthAmount ? maxEthAmount : maxLongAmount - // ); - // uint256 sharesPaid = RIVER.sharesFromUnderlyingBalance(basePaid); - // RIVER.approve(address(hyperdrive), sharesPaid); - // (uint256 maturityTime, uint256 longAmount) = openLong( - // bob, - // sharesPaid, - // false - // ); - - // // The term passes and some interest accrues. - // variableRate = variableRate.normalizeToRange(0, 2.5e18); - // advanceTime(POSITION_DURATION, variableRate); - - // // Get some balance information before the withdrawal. - // AccountBalances memory bobBalancesBefore = getAccountBalances(bob); - // AccountBalances memory hyperdriveBalancesBefore = getAccountBalances( - // address(hyperdrive) - // ); - // uint256 totalLsethSupplyBefore = RIVER.totalSupply(); - - // // Bob closes his long with LsETH as the target asset. - // uint256 shareProceeds = closeLong(bob, maturityTime, longAmount, false); - // uint256 baseProceeds = RIVER.underlyingBalanceFromShares(shareProceeds); - - // // Ensure Bob is credited the correct amount of bonds. - // assertLe(baseProceeds, longAmount); - // assertApproxEqAbs(baseProceeds, longAmount, 10); - - // // Ensure that River aggregates and the token balances were updated - // // correctly during the trade. - // verifyLsethWithdrawal( - // bob, - // shareProceeds, - // false, - // totalLsethSupplyBefore, - // bobBalancesBefore, - // hyperdriveBalancesBefore - // ); - // } + // The term passes and some interest accrues. + variableRate = variableRate.normalizeToRange(0, 2.5e18); + advanceTime(POSITION_DURATION, variableRate); + + // Get some balance information before the withdrawal. + AccountBalances memory bobBalancesBefore = getAccountBalances(bob); + AccountBalances memory hyperdriveBalancesBefore = getAccountBalances( + address(hyperdrive) + ); + uint256 totalLsethSupplyBefore = RIVER.totalSupply(); + + // Bob closes his long with LsETH as the target asset. + uint256 shareProceeds = closeLong(bob, maturityTime, longAmount, false); + uint256 baseProceeds = RIVER.underlyingBalanceFromShares(shareProceeds); + + // Ensure Bob is credited the correct amount of bonds. + assertLe(baseProceeds, longAmount); + assertApproxEqAbs(baseProceeds, longAmount, 10); + + // Ensure that River aggregates and the token balances were updated + // correctly during the trade. + verifyLsethWithdrawal( + bob, + shareProceeds, + false, + totalLsethSupplyBefore, + bobBalancesBefore, + hyperdriveBalancesBefore + ); + } /// Short /// @@ -574,39 +511,6 @@ contract LsETHHyperdriveTest is InstanceTestV2 { ); } - // function verifyDeposit( - // address trader, - // uint256 amount, - // bool asBase, - // uint256 totalSharesBefore, - // AccountBalances memory traderBalancesBefore, - // AccountBalances memory hyperdriveBalancesBefore - // ) internal { - // if (asBase) { - // revert IHyperdrive.NotPayable(); - // } - - // // Ensure that the ether balances were updated correctly. - // assertEq( - // address(hyperdrive).balance, - // hyperdriveBalancesBefore.ETHBalance - // ); - // assertEq(trader.balance, traderBalancesBefore.ETHBalance); - - // // Ensure that the LsETH balances were updated correctly. - // assertEq( - // RIVER.balanceOf(address(hyperdrive)), - // hyperdriveBalancesBefore.lsethBalance + amount - // ); - // assertEq( - // RIVER.balanceOf(trader), - // traderBalancesBefore.lsethBalance - amount - // ); - - // // Ensure the total supply was updated correctly. - // assertEq(RIVER.totalSupply(), totalSharesBefore); - // } - function verifyLsethWithdrawal( address trader, uint256 amount, @@ -683,19 +587,4 @@ contract LsETHHyperdriveTest is InstanceTestV2 { // Ensure the new rate is higher than the old rate. assertGt(RIVER.underlyingBalanceFromShares(1e18), oldRate); } - - // struct AccountBalances { - // uint256 lsethBalance; - // uint256 ETHBalance; - // } - - // function getAccountBalances( - // address account - // ) internal view returns (AccountBalances memory) { - // return - // AccountBalances({ - // lsethBalance: RIVER.balanceOf(account), - // ETHBalance: account.balance - // }); - // } } diff --git a/test/instances/reth/RETHHyperdrive.t.sol b/test/instances/reth/RETHHyperdrive.t.sol index 17f994411..425b72324 100644 --- a/test/instances/reth/RETHHyperdrive.t.sol +++ b/test/instances/reth/RETHHyperdrive.t.sol @@ -190,69 +190,6 @@ contract RETHHyperdriveTest is InstanceTestV2 { /// Long /// - // function test_open_long_with_eth(uint256 basePaid) external { - // // Bob opens a long by depositing ETH. This is not allowed and - // // should throw an unsupported token exception. - // vm.startPrank(bob); - // basePaid = basePaid.normalizeToRange( - // 2 * hyperdrive.getPoolConfig().minimumTransactionAmount, - // HyperdriveUtils.calculateMaxLong(hyperdrive) - // ); - // vm.expectRevert(IHyperdrive.NotPayable.selector); - // hyperdrive.openLong{ value: basePaid }( - // basePaid, - // 0, - // 0, - // IHyperdrive.Options({ - // destination: bob, - // asBase: true, - // extraData: new bytes(0) - // }) - // ); - // } - - // function test_open_long_with_reth(uint256 basePaid) external { - // // Get some balance information before the deposit. - // ( - // uint256 totalBaseSupplyBefore, - // uint256 totalSharesSupplyBefore - // ) = getSupply(); - // AccountBalances memory bobBalancesBefore = getAccountBalances(bob); - // AccountBalances memory hyperdriveBalancesBefore = getAccountBalances( - // address(hyperdrive) - // ); - - // // Calculate the maximum amount of basePaid we can test. The limit is - // // either the max long that Hyperdrive can open or the amount of rETH - // // tokens the trader has. - // uint256 maxLongAmount = HyperdriveUtils.calculateMaxLong(hyperdrive); - // uint256 maxEthAmount = rocketTokenRETH.getEthValue( - // rocketTokenRETH.balanceOf(bob) - // ); - - // // Bob opens a long by depositing rETH. - // vm.startPrank(bob); - // basePaid = basePaid.normalizeToRange( - // 2 * hyperdrive.getPoolConfig().minimumTransactionAmount, - // maxLongAmount > maxEthAmount ? maxEthAmount : maxLongAmount - // ); - // uint256 sharesPaid = rocketTokenRETH.getRethValue(basePaid); - // rocketTokenRETH.approve(address(hyperdrive), sharesPaid); - // openLong(bob, sharesPaid, false); - - // // Ensure that Rocket Pool's aggregates and the token balances were updated - // // correctly during the trade. - // verifyDeposit( - // bob, - // basePaid, - // false, - // totalBaseSupplyBefore, - // totalSharesSupplyBefore, - // bobBalancesBefore, - // hyperdriveBalancesBefore - // ); - // } - function test_open_long_refunds() external { vm.startPrank(bob); @@ -756,19 +693,4 @@ contract RETHHyperdriveTest is InstanceTestV2 { // Ensure the new rate is higher than the old rate. assertGt(rocketTokenRETH.getExchangeRate(), oldRate); } - - // struct AccountBalances { - // uint256 rethBalance; - // uint256 ETHBalance; - // } - - // function getAccountBalances( - // address account - // ) internal view returns (AccountBalances memory) { - // return - // AccountBalances({ - // rethBalance: rocketTokenRETH.balanceOf(account), - // ETHBalance: account.balance - // }); - // } } diff --git a/test/instances/steth/StETHHyperdrive.t.sol b/test/instances/steth/StETHHyperdrive.t.sol index 22ec1c5f5..9f6b65628 100644 --- a/test/instances/steth/StETHHyperdrive.t.sol +++ b/test/instances/steth/StETHHyperdrive.t.sol @@ -841,21 +841,4 @@ contract StETHHyperdriveTest is InstanceTestV2 { bytes32(bufferedEther) ); } - - // struct AccountBalances { - // uint256 stethShares; - // uint256 stethBalance; - // uint256 ETHBalance; - // } - - // function getAccountBalances( - // address account - // ) internal view returns (AccountBalances memory) { - // return - // AccountBalances({ - // stethShares: LIDO.sharesOf(account), - // stethBalance: LIDO.balanceOf(account), - // ETHBalance: account.balance - // }); - // } } From 570a5f1db69bd57cd715733f61413e73ce55576c Mon Sep 17 00:00:00 2001 From: Cash Baller Date: Tue, 26 Mar 2024 22:10:54 -0500 Subject: [PATCH 06/21] cut down on sol warnings --- test/instances/ezETH/EzETHHyperdrive.t.sol | 2 +- test/instances/lseth/LsETHHyperdrive.t.sol | 3 +-- test/instances/reth/RETHHyperdrive.t.sol | 2 +- test/instances/steth/StETHHyperdrive.t.sol | 2 +- 4 files changed, 4 insertions(+), 5 deletions(-) diff --git a/test/instances/ezETH/EzETHHyperdrive.t.sol b/test/instances/ezETH/EzETHHyperdrive.t.sol index f3629db63..291c3428f 100644 --- a/test/instances/ezETH/EzETHHyperdrive.t.sol +++ b/test/instances/ezETH/EzETHHyperdrive.t.sol @@ -103,7 +103,7 @@ contract EzETHHyperdriveTest is InstanceTestV2 { return (EZETH.balanceOf(account), 0); } - function getSupply() internal override returns (uint256, uint256) { + function getSupply() internal view override returns (uint256, uint256) { (, uint256 totalPooledEther, ) = getSharePrice(); return (totalPooledEther, EZETH.totalSupply()); } diff --git a/test/instances/lseth/LsETHHyperdrive.t.sol b/test/instances/lseth/LsETHHyperdrive.t.sol index bbfbb6fb7..fb1f3431d 100644 --- a/test/instances/lseth/LsETHHyperdrive.t.sol +++ b/test/instances/lseth/LsETHHyperdrive.t.sol @@ -101,7 +101,7 @@ contract LsETHHyperdriveTest is InstanceTestV2 { return (RIVER.balanceOf(account), RIVER.balanceOfUnderlying(account)); } - function getSupply() internal override returns (uint256, uint256) { + function getSupply() internal view override returns (uint256, uint256) { return (RIVER.totalUnderlyingSupply(), RIVER.totalSupply()); } @@ -343,7 +343,6 @@ contract LsETHHyperdriveTest is InstanceTestV2 { uint256 totalBaseSupplyBefore, uint256 totalSharesSupplyBefore ) = getSupply(); - uint256 totalLsethSupplyBefore = RIVER.totalSupply(); AccountBalances memory bobBalancesBefore = getAccountBalances(bob); AccountBalances memory hyperdriveBalancesBefore = getAccountBalances( address(hyperdrive) diff --git a/test/instances/reth/RETHHyperdrive.t.sol b/test/instances/reth/RETHHyperdrive.t.sol index 425b72324..77d921adf 100644 --- a/test/instances/reth/RETHHyperdrive.t.sol +++ b/test/instances/reth/RETHHyperdrive.t.sol @@ -108,7 +108,7 @@ contract RETHHyperdriveTest is InstanceTestV2 { return (rethBalance, rocketTokenRETH.getEthValue(rethBalance)); } - function getSupply() internal override returns (uint256, uint256) { + function getSupply() internal view override returns (uint256, uint256) { return ( rocketNetworkBalances.getTotalETHBalance(), rocketNetworkBalances.getTotalRETHSupply() diff --git a/test/instances/steth/StETHHyperdrive.t.sol b/test/instances/steth/StETHHyperdrive.t.sol index 9f6b65628..1f0e23877 100644 --- a/test/instances/steth/StETHHyperdrive.t.sol +++ b/test/instances/steth/StETHHyperdrive.t.sol @@ -64,7 +64,7 @@ contract StETHHyperdriveTest is InstanceTestV2 { /// Overrides /// - function getSupply() internal override returns (uint256, uint256) { + function getSupply() internal view override returns (uint256, uint256) { return (LIDO.getTotalPooledEther(), LIDO.getTotalShares()); } From 412e042fdb5a739a8d227b7ed58f0acf2edb4dd9 Mon Sep 17 00:00:00 2001 From: Cash Baller Date: Tue, 26 Mar 2024 22:13:54 -0500 Subject: [PATCH 07/21] remove more comments --- test/instances/reth/RETHHyperdrive.t.sol | 33 --------- test/instances/steth/StETHHyperdrive.t.sol | 84 ---------------------- 2 files changed, 117 deletions(-) diff --git a/test/instances/reth/RETHHyperdrive.t.sol b/test/instances/reth/RETHHyperdrive.t.sol index 77d921adf..e2f5cde05 100644 --- a/test/instances/reth/RETHHyperdrive.t.sol +++ b/test/instances/reth/RETHHyperdrive.t.sol @@ -562,39 +562,6 @@ contract RETHHyperdriveTest is InstanceTestV2 { ); } - // function verifyDeposit( - // address trader, - // uint256 amount, - // bool asBase, - // uint256 totalSharesBefore, - // AccountBalances memory traderBalancesBefore, - // AccountBalances memory hyperdriveBalancesBefore - // ) internal { - // if (asBase) { - // revert IHyperdrive.UnsupportedToken(); - // } - - // // Ensure that the ether balances were updated correctly. - // assertEq( - // address(hyperdrive).balance, - // hyperdriveBalancesBefore.ETHBalance - // ); - // assertEq(trader.balance, traderBalancesBefore.ETHBalance); - - // // Ensure that the rETH balances were updated correctly. - // assertEq( - // rocketTokenRETH.balanceOf(address(hyperdrive)), - // hyperdriveBalancesBefore.rethBalance + amount - // ); - // assertEq( - // rocketTokenRETH.balanceOf(trader), - // traderBalancesBefore.rethBalance - amount - // ); - - // // Ensure the total supply was updated correctly. - // assertEq(rocketTokenRETH.totalSupply(), totalSharesBefore); - // } - function verifyRethWithdrawal( address trader, uint256 amount, diff --git a/test/instances/steth/StETHHyperdrive.t.sol b/test/instances/steth/StETHHyperdrive.t.sol index 1f0e23877..25174231d 100644 --- a/test/instances/steth/StETHHyperdrive.t.sol +++ b/test/instances/steth/StETHHyperdrive.t.sol @@ -685,90 +685,6 @@ contract StETHHyperdriveTest is InstanceTestV2 { closeLong(bob, maturityTime_, longAmount_ / 2, false); } - // function verifyDeposit( - // address trader, - // uint256 basePaid, - // bool asBase, - // uint256 totalPooledEtherBefore, - // uint256 totalSharesBefore, - // AccountBalances memory traderBalancesBefore, - // AccountBalances memory hyperdriveBalancesBefore - // ) internal { - // if (asBase) { - // // Ensure that the amount of pooled ether increased by the base paid. - // assertEq( - // LIDO.getTotalPooledEther(), - // totalPooledEtherBefore + basePaid - // ); - - // // Ensure that the ETH balances were updated correctly. - // assertEq( - // address(hyperdrive).balance, - // hyperdriveBalancesBefore.ETHBalance - // ); - // assertEq(bob.balance, traderBalancesBefore.ETHBalance - basePaid); - - // // Ensure that the stETH balances were updated correctly. - // assertApproxEqAbs( - // LIDO.balanceOf(address(hyperdrive)), - // hyperdriveBalancesBefore.stethBalance + basePaid, - // 1 - // ); - // assertEq(LIDO.balanceOf(trader), traderBalancesBefore.stethBalance); - - // // Ensure that the stETH shares were updated correctly. - // uint256 expectedShares = basePaid.mulDivDown( - // totalSharesBefore, - // totalPooledEtherBefore - // ); - // assertEq(LIDO.getTotalShares(), totalSharesBefore + expectedShares); - // assertEq( - // LIDO.sharesOf(address(hyperdrive)), - // hyperdriveBalancesBefore.stethShares + expectedShares - // ); - // assertEq(LIDO.sharesOf(bob), traderBalancesBefore.stethShares); - // } else { - // // Ensure that the amount of pooled ether stays the same. - // assertEq(LIDO.getTotalPooledEther(), totalPooledEtherBefore); - - // // Ensure that the ETH balances were updated correctly. - // assertEq( - // address(hyperdrive).balance, - // hyperdriveBalancesBefore.ETHBalance - // ); - // assertEq(trader.balance, traderBalancesBefore.ETHBalance); - - // // Ensure that the stETH balances were updated correctly. - // assertApproxEqAbs( - // LIDO.balanceOf(address(hyperdrive)), - // hyperdriveBalancesBefore.stethBalance + basePaid, - // 1 - // ); - // assertApproxEqAbs( - // LIDO.balanceOf(trader), - // traderBalancesBefore.stethBalance - basePaid, - // 1 - // ); - - // // Ensure that the stETH shares were updated correctly. - // uint256 expectedShares = basePaid.mulDivDown( - // totalSharesBefore, - // totalPooledEtherBefore - // ); - // assertEq(LIDO.getTotalShares(), totalSharesBefore); - // assertApproxEqAbs( - // LIDO.sharesOf(address(hyperdrive)), - // hyperdriveBalancesBefore.stethShares + expectedShares, - // 1 - // ); - // assertApproxEqAbs( - // LIDO.sharesOf(trader), - // traderBalancesBefore.stethShares - expectedShares, - // 1 - // ); - // } - // } - function verifyStethWithdrawal( address trader, uint256 baseProceeds, From 4b1f5cfb68140c646694f35781e32f5a2eefcd85 Mon Sep 17 00:00:00 2001 From: Cash Baller Date: Tue, 26 Mar 2024 22:16:41 -0500 Subject: [PATCH 08/21] Replace v1 with v2 InstanceTest --- test/instances/ezETH/EzETHHyperdrive.t.sol | 6 +- test/instances/lseth/LsETHHyperdrive.t.sol | 6 +- test/instances/reth/RETHHyperdrive.t.sol | 6 +- test/instances/steth/StETHHyperdrive.t.sol | 6 +- test/utils/InstanceTest.sol | 126 +++++ test/utils/InstanceTestV2.sol | 587 --------------------- 6 files changed, 138 insertions(+), 599 deletions(-) delete mode 100644 test/utils/InstanceTestV2.sol diff --git a/test/instances/ezETH/EzETHHyperdrive.t.sol b/test/instances/ezETH/EzETHHyperdrive.t.sol index 291c3428f..e85904719 100644 --- a/test/instances/ezETH/EzETHHyperdrive.t.sol +++ b/test/instances/ezETH/EzETHHyperdrive.t.sol @@ -21,11 +21,11 @@ import { FixedPointMath, ONE } from "contracts/src/libraries/FixedPointMath.sol" import { HyperdriveMath } from "contracts/src/libraries/HyperdriveMath.sol"; import { ERC20ForwarderFactory } from "contracts/src/token/ERC20ForwarderFactory.sol"; import { ERC20Mintable } from "contracts/test/ERC20Mintable.sol"; -import { InstanceTestV2 } from "test/utils/InstanceTestV2.sol"; +import { InstanceTest } from "test/utils/InstanceTest.sol"; import { HyperdriveUtils } from "test/utils/HyperdriveUtils.sol"; import { Lib } from "test/utils/Lib.sol"; -contract EzETHHyperdriveTest is InstanceTestV2 { +contract EzETHHyperdriveTest is InstanceTest { using FixedPointMath for uint256; using Lib for *; using stdStorage for StdStorage; @@ -72,7 +72,7 @@ contract EzETHHyperdriveTest is InstanceTestV2 { ); /// @dev Instantiates the Instance testing suite with the configuration. - constructor() InstanceTestV2(__testConfig) {} + constructor() InstanceTest(__testConfig) {} /// @dev Forge function that is invoked to setup the testing environment. function setUp() public override __mainnet_fork(STARTING_BLOCK) { diff --git a/test/instances/lseth/LsETHHyperdrive.t.sol b/test/instances/lseth/LsETHHyperdrive.t.sol index fb1f3431d..8c5703e57 100644 --- a/test/instances/lseth/LsETHHyperdrive.t.sol +++ b/test/instances/lseth/LsETHHyperdrive.t.sol @@ -19,11 +19,11 @@ import { ETH } from "contracts/src/libraries/Constants.sol"; import { HyperdriveMath } from "contracts/src/libraries/HyperdriveMath.sol"; import { FixedPointMath, ONE } from "contracts/src/libraries/FixedPointMath.sol"; import { ERC20Mintable } from "contracts/test/ERC20Mintable.sol"; -import { InstanceTestV2 } from "test/utils/InstanceTestV2.sol"; +import { InstanceTest } from "test/utils/InstanceTest.sol"; import { HyperdriveUtils } from "test/utils/HyperdriveUtils.sol"; import { Lib } from "test/utils/Lib.sol"; -contract LsETHHyperdriveTest is InstanceTestV2 { +contract LsETHHyperdriveTest is InstanceTest { using FixedPointMath for uint256; using Lib for *; using stdStorage for StdStorage; @@ -59,7 +59,7 @@ contract LsETHHyperdriveTest is InstanceTestV2 { ); /// @dev Instantiates the Instance testing suite with the configuration. - constructor() InstanceTestV2(__testConfig) {} + constructor() InstanceTest(__testConfig) {} /// @dev Forge function that is invoked to setup the testing environment. diff --git a/test/instances/reth/RETHHyperdrive.t.sol b/test/instances/reth/RETHHyperdrive.t.sol index e2f5cde05..7cdd3898d 100644 --- a/test/instances/reth/RETHHyperdrive.t.sol +++ b/test/instances/reth/RETHHyperdrive.t.sol @@ -8,7 +8,7 @@ import { ETH } from "contracts/src/libraries/Constants.sol"; import { FixedPointMath, ONE } from "contracts/src/libraries/FixedPointMath.sol"; import { HyperdriveFactory } from "contracts/src/factory/HyperdriveFactory.sol"; import { HyperdriveMath } from "contracts/src/libraries/HyperdriveMath.sol"; -import { InstanceTestV2 } from "test/utils/InstanceTestV2.sol"; +import { InstanceTest } from "test/utils/InstanceTest.sol"; import { HyperdriveUtils } from "test/utils/HyperdriveUtils.sol"; import { IERC20 } from "contracts/src/interfaces/IERC20.sol"; import { IHyperdrive } from "contracts/src/interfaces/IHyperdrive.sol"; @@ -28,7 +28,7 @@ import { RETHTarget3Deployer } from "contracts/src/deployers/reth/RETHTarget3Dep import { RETHTarget4Deployer } from "contracts/src/deployers/reth/RETHTarget4Deployer.sol"; import { stdStorage, StdStorage } from "forge-std/Test.sol"; -contract RETHHyperdriveTest is InstanceTestV2 { +contract RETHHyperdriveTest is InstanceTest { using FixedPointMath for uint256; using Lib for *; using stdStorage for StdStorage; @@ -63,7 +63,7 @@ contract RETHHyperdriveTest is InstanceTestV2 { ); /// @dev Instantiates the Instance testing suite with the configuration. - constructor() InstanceTestV2(__testConfig) {} + constructor() InstanceTest(__testConfig) {} /// @dev Forge function that is invoked to setup the testing environment. function setUp() public override __mainnet_fork(19_429_100) { diff --git a/test/instances/steth/StETHHyperdrive.t.sol b/test/instances/steth/StETHHyperdrive.t.sol index 25174231d..c0e0031e9 100644 --- a/test/instances/steth/StETHHyperdrive.t.sol +++ b/test/instances/steth/StETHHyperdrive.t.sol @@ -19,11 +19,11 @@ import { FixedPointMath, ONE } from "contracts/src/libraries/FixedPointMath.sol" import { HyperdriveMath } from "contracts/src/libraries/HyperdriveMath.sol"; import { ERC20ForwarderFactory } from "contracts/src/token/ERC20ForwarderFactory.sol"; import { ERC20Mintable } from "contracts/test/ERC20Mintable.sol"; -import { InstanceTestV2 } from "test/utils/InstanceTestV2.sol"; +import { InstanceTest } from "test/utils/InstanceTest.sol"; import { HyperdriveUtils } from "test/utils/HyperdriveUtils.sol"; import { Lib } from "test/utils/Lib.sol"; -contract StETHHyperdriveTest is InstanceTestV2 { +contract StETHHyperdriveTest is InstanceTest { using FixedPointMath for uint256; using Lib for *; using stdStorage for StdStorage; @@ -54,7 +54,7 @@ contract StETHHyperdriveTest is InstanceTestV2 { ); /// @dev Instantiates the Instance testing suite with the configuration. - constructor() InstanceTestV2(__testConfig) {} + constructor() InstanceTest(__testConfig) {} /// @dev Forge function that is invoked to setup the testing environment. function setUp() public override __mainnet_fork(17_376_154) { diff --git a/test/utils/InstanceTest.sol b/test/utils/InstanceTest.sol index 027d8ddc2..ae79288ce 100644 --- a/test/utils/InstanceTest.sol +++ b/test/utils/InstanceTest.sol @@ -459,4 +459,130 @@ abstract contract InstanceTest is HyperdriveTest { config.shareTolerance ); } + + struct AccountBalances { + uint256 sharesBalance; + uint256 baseBalance; + uint256 ETHBalance; + } + + function getTokenBalances( + address account + ) internal view virtual returns (uint256, uint256); + + function getSupply() internal virtual returns (uint256, uint256); + + function getAccountBalances( + address account + ) internal view returns (AccountBalances memory) { + (uint256 shares, uint256 base) = getTokenBalances(account); + + return + AccountBalances({ + sharesBalance: shares, + baseBalance: base, + ETHBalance: account.balance + }); + } + + function verifyDeposit( + address trader, + uint256 amountPaid, + bool asBase, + uint256 totalBaseBefore, + uint256 totalSharesBefore, + AccountBalances memory traderBalancesBefore, + AccountBalances memory hyperdriveBalancesBefore + ) internal virtual; + + function test__open_long_with_shares(uint256 basePaid) external { + ( + uint256 totalBaseSupplyBefore, + uint256 totalSharesSupplyBefore + ) = getSupply(); + + AccountBalances memory bobBalancesBefore = getAccountBalances(bob); + AccountBalances memory hyperdriveBalanceBefore = getAccountBalances( + address(hyperdrive) + ); + + // Calculate the maximum amount of basePaid we can test. The limit is + // either the max long that Hyperdrive can open or the amount of rETH + // tokens the trader has. + uint256 maxLongAmount = HyperdriveUtils.calculateMaxLong(hyperdrive); + uint256 maxSharesAmount = bobBalancesBefore.sharesBalance; + + // Bob opens a long by depositing stETH. + basePaid = basePaid.normalizeToRange( + 2 * hyperdrive.getPoolConfig().minimumTransactionAmount, + maxLongAmount > maxSharesAmount ? maxSharesAmount : maxLongAmount + ); + + uint256 sharesPaid = convertToShares(basePaid); + + openLong(bob, sharesPaid, false); + verifyDeposit( + bob, + basePaid, + false, + totalBaseSupplyBefore, + totalSharesSupplyBefore, + bobBalancesBefore, + hyperdriveBalanceBefore + ); + } + + function test__open_long_with_base(uint256 basePaid) external { + ( + uint256 totalBaseSupplyBefore, + uint256 totalSharesSupplyBefore + ) = getSupply(); + + AccountBalances memory bobBalancesBefore = getAccountBalances(bob); + AccountBalances memory hyperdriveBalanceBefore = getAccountBalances( + address(hyperdrive) + ); + + // Bob opens a long by depositing stETH. + vm.startPrank(bob); + basePaid = basePaid.normalizeToRange( + 2 * hyperdrive.getPoolConfig().minimumTransactionAmount, + HyperdriveUtils.calculateMaxLong(hyperdrive) + ); + + // We expect the deployAndInitialize to fail with an + // Unsupported token error if depositing with base is not supported. + // If the base token is ETH we expect a NotPayable error. + if (!config.enableBaseDeposits) { + vm.expectRevert( + isBaseETH + ? IHyperdrive.NotPayable.selector + : IHyperdrive.UnsupportedToken.selector + ); + } + + hyperdrive.openLong{ value: isBaseETH ? basePaid : 0 }( + basePaid, + 0, + 0, + IHyperdrive.Options({ + destination: bob, + asBase: true, + extraData: new bytes(0) + }) + ); + // openLong(bob, basePaid, true); + + if (config.enableBaseDeposits) { + verifyDeposit( + bob, + basePaid, + true, + totalBaseSupplyBefore, + totalSharesSupplyBefore, + bobBalancesBefore, + hyperdriveBalanceBefore + ); + } + } } diff --git a/test/utils/InstanceTestV2.sol b/test/utils/InstanceTestV2.sol deleted file mode 100644 index aaa8594d4..000000000 --- a/test/utils/InstanceTestV2.sol +++ /dev/null @@ -1,587 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -pragma solidity 0.8.20; - -import { ERC20ForwarderFactory } from "contracts/src/token/ERC20ForwarderFactory.sol"; -import { HyperdriveFactory } from "contracts/src/factory/HyperdriveFactory.sol"; -import { IERC20 } from "contracts/src/interfaces/IERC20.sol"; -import { IHyperdrive } from "contracts/src/interfaces/IHyperdrive.sol"; -import { AssetId } from "contracts/src/libraries/AssetId.sol"; -import { ETH } from "contracts/src/libraries/Constants.sol"; -import { FixedPointMath, ONE } from "contracts/src/libraries/FixedPointMath.sol"; -import { HyperdriveTest } from "test/utils/HyperdriveTest.sol"; -import { HyperdriveUtils } from "test/utils/HyperdriveUtils.sol"; -import { Lib } from "test/utils/Lib.sol"; - -/// @author DELV -/// @title InstanceTest -/// @notice The base contract for the instance testing suite. -/// @dev A testing suite that provides a foundation to setup, deploy, and -/// test common cases for Hyperdrive instances. -/// @custom:disclaimer The language used in this code is for coding convenience -/// only, and is not intended to, and does not, have any -/// particular legal or regulatory significance. -abstract contract InstanceTestV2 is HyperdriveTest { - using Lib for *; - using FixedPointMath for uint256; - - /// @dev Configuration for the Instance testing suite. - struct InstanceTestConfig { - address[] whaleAccounts; - IERC20 token; - IERC20 baseToken; - uint256 shareTolerance; - uint256 minTransactionAmount; - uint256 positionDuration; - bool enableBaseDeposits; - bool enableShareDeposits; - } - - // Fixed rate used to configure market. - uint256 internal constant FIXED_RATE = 0.05e18; - - // Default deployment constants. - bytes32 private constant DEFAULT_DEPLOYMENT_ID = - bytes32(uint256(0xdeadbeef)); - bytes32 private constant DEFAULT_DEPLOYMENT_SALT = - bytes32(uint256(0xdeadbabe)); - - // The configuration for the Instance testing suite. - InstanceTestConfig internal config; - - // The configuration for the pool. - IHyperdrive.PoolDeployConfig private poolConfig; - - // The address of the deployer coordinator contract. - address private deployerCoordinator; - - // The factory contract used for deployment in this testing suite. - HyperdriveFactory private factory; - - // Flag for denoting if the base token is ETH. - bool private immutable isBaseETH; - - /// @dev Constructor for the Instance testing suite. - /// @param _config The Instance configuration. - constructor(InstanceTestConfig storage _config) { - config = _config; - isBaseETH = config.baseToken == IERC20(ETH); - } - - /// Deployments /// - - /// @notice Forge setup function. - /// @dev Inherits from HyperdriveTest and deploys the - /// Hyperdrive factory, deployer coordinator, and targets. - function setUp() public virtual override { - super.setUp(); - - // Initial contribution. - uint256 contribution = 5_000e18; - - // Fund accounts with ETH and token from whales. - vm.deal(alice, 100_000e18); - vm.deal(bob, 100_000e18); - address[] memory accounts = new address[](2); - accounts[0] = alice; - accounts[1] = bob; - for (uint256 i = 0; i < config.whaleAccounts.length; i++) { - fundAccounts( - address(hyperdrive), - config.token, - config.whaleAccounts[i], - accounts - ); - } - - // Deploy the Hyperdrive Factory contract. - deployFactory(); - - // Set the deployer coordinator address and add to the factory. - deployerCoordinator = deployCoordinator(); - factory.addDeployerCoordinator(deployerCoordinator); - - // Deploy all Hyperdrive contracts using deployer coordinator contract. - deployHyperdrive( - DEFAULT_DEPLOYMENT_ID, // Deployment Id - DEFAULT_DEPLOYMENT_SALT, // Deployment Salt - contribution, // Contribution - false // asBase - ); - - config.token.approve(address(hyperdrive), 100_000e18); - vm.startPrank(bob); - config.token.approve(address(hyperdrive), 100_000e18); - - // Ensure that Alice received the correct amount of LP tokens. She should - // receive LP shares totaling the amount of shares that she contributed - // minus the shares set aside for the minimum share reserves and the - // zero address's initial LP contribution. - assertApproxEqAbs( - hyperdrive.balanceOf(AssetId._LP_ASSET_ID, alice), - contribution - 2 * hyperdrive.getPoolConfig().minimumShareReserves, - config.shareTolerance - ); - - // Start recording event logs. - vm.recordLogs(); - } - - /// @dev Deploys all Hyperdrive contracts using the - /// deployer coordinator contract. - /// @param deploymentId The deployment id. - /// @param deploymentSalt The deployment salt for create2. - /// @param contribution The amount to initialize the market. - /// @param asBase Initialize the market with base token. - function deployHyperdrive( - bytes32 deploymentId, - bytes32 deploymentSalt, - uint256 contribution, - bool asBase - ) private { - // Alice is the default deployer. - vm.startPrank(alice); - - // Deploy Hyperdrive target contracts. - factory.deployTarget( - deploymentId, - deployerCoordinator, - poolConfig, - new bytes(0), - FIXED_RATE, - FIXED_RATE, - 0, - deploymentSalt - ); - factory.deployTarget( - deploymentId, - deployerCoordinator, - poolConfig, - new bytes(0), - FIXED_RATE, - FIXED_RATE, - 1, - deploymentSalt - ); - factory.deployTarget( - deploymentId, - deployerCoordinator, - poolConfig, - new bytes(0), - FIXED_RATE, - FIXED_RATE, - 2, - deploymentSalt - ); - factory.deployTarget( - deploymentId, - deployerCoordinator, - poolConfig, - new bytes(0), - FIXED_RATE, - FIXED_RATE, - 3, - deploymentSalt - ); - factory.deployTarget( - deploymentId, - deployerCoordinator, - poolConfig, - new bytes(0), - FIXED_RATE, - FIXED_RATE, - 4, - deploymentSalt - ); - - // Alice gives approval to the deployer coordinator to fund the market. - config.token.approve(deployerCoordinator, 100_000e18); - - // We expect the deployAndInitialize to fail with an - // Unsupported token error if depositing with base is not supported. - // If the base token is ETH we expect a NotPayable error. - if (!config.enableBaseDeposits && asBase) { - vm.expectRevert( - isBaseETH - ? IHyperdrive.NotPayable.selector - : IHyperdrive.UnsupportedToken.selector - ); - } - - // We expect the deployAndInitialize to fail with an - // Unsupported token error if depositing with shares is not supported. - if (!config.enableShareDeposits && !asBase) { - vm.expectRevert(IHyperdrive.UnsupportedToken.selector); - } - - // Record Alice's ETH balance before the deployment call. - uint256 aliceBalanceBefore = address(alice).balance; - - // Deploy and initialize the market. If the base token is ETH we pass the - // contribution through the call. - hyperdrive = factory.deployAndInitialize{ - value: asBase && isBaseETH ? contribution : 0 - }( - deploymentId, - deployerCoordinator, - poolConfig, - new bytes(0), - contribution, - FIXED_RATE, - FIXED_RATE, - IHyperdrive.Options({ - asBase: asBase, - destination: alice, - extraData: new bytes(0) - }), - deploymentSalt - ); - - // Ensure that refunds are handled properly. - if (config.enableBaseDeposits && asBase && isBaseETH) { - assertEq(aliceBalanceBefore - contribution, address(alice).balance); - } else { - assertEq(aliceBalanceBefore, address(alice).balance); - } - } - - /// @dev Deploys the Hyperdrive Factory contract and - /// sets the default pool configuration. - function deployFactory() private { - // Deploy the hyperdrive factory. - vm.startPrank(deployer); - address[] memory defaults = new address[](1); - defaults[0] = bob; - forwarderFactory = new ERC20ForwarderFactory(); - factory = new HyperdriveFactory( - HyperdriveFactory.FactoryConfig({ - governance: alice, - hyperdriveGovernance: bob, - feeCollector: celine, - sweepCollector: sweepCollector, - defaultPausers: defaults, - checkpointDurationResolution: 1 hours, - minCheckpointDuration: 8 hours, - maxCheckpointDuration: 1 days, - minPositionDuration: 7 days, - maxPositionDuration: 10 * 365 days, - minFixedAPR: 0.001e18, - maxFixedAPR: 0.5e18, - minTimeStretchAPR: 0.005e18, - maxTimeStretchAPR: 0.5e18, - minFees: IHyperdrive.Fees({ - curve: 0, - flat: 0, - governanceLP: 0, - governanceZombie: 0 - }), - maxFees: IHyperdrive.Fees({ - curve: ONE, - flat: ONE, - governanceLP: ONE, - governanceZombie: ONE - }), - linkerFactory: address(forwarderFactory), - linkerCodeHash: forwarderFactory.ERC20LINK_HASH() - }) - ); - - // Set the pool configuration that will be used for instance deployments. - poolConfig = IHyperdrive.PoolDeployConfig({ - baseToken: config.baseToken, - linkerFactory: factory.linkerFactory(), - linkerCodeHash: factory.linkerCodeHash(), - minimumShareReserves: 1e15, - minimumTransactionAmount: config.minTransactionAmount, - positionDuration: config.positionDuration, - checkpointDuration: CHECKPOINT_DURATION, - timeStretch: 0, - governance: factory.hyperdriveGovernance(), - feeCollector: factory.feeCollector(), - sweepCollector: factory.sweepCollector(), - fees: IHyperdrive.Fees({ - curve: 0, - flat: 0, - governanceLP: 0, - governanceZombie: 0 - }) - }); - } - - /// Overrides /// - - /// @dev A virtual function that defines the deployer coordinator - /// contract that will be used to deploy all the instance targets. - function deployCoordinator() internal virtual returns (address); - - /// @dev A virtual function that converts an amount in terms of the base token - /// to equivalent amount in shares. - /// @param baseAmount Amount in terms of the base. - /// @return shareAmount Amount in terms of shares. - function convertToShares( - uint256 baseAmount - ) internal view virtual returns (uint256 shareAmount); - - /// Tests /// - - /// @dev Test to verify a market can be deployed and initialized funded by the - /// base token. Is expected to revert when base deposits are not supported. - function test__deployAndInitialize__asBase() external virtual { - uint256 aliceBalanceBefore = address(alice).balance; - - // Contribution in terms of base. - uint256 contribution = 5_000e18; - - // Contribution in terms of shares. - uint256 contributionShares = convertToShares(contribution); - - // Deploy all Hyperdrive contract using deployer coordinator contract. - // This function reverts if base deposits are disabled. - deployHyperdrive( - bytes32(uint256(0xbeefbabe)), // Deployment Id - bytes32(uint256(0xdeadfade)), // Deployment Salt - contribution, // Contribution - true // asBase - ); - - // Early termination if base deposits are not supported. - if (!config.enableBaseDeposits) { - return; - } - - // If base deposits are enabled we verify some assertions. - if (isBaseETH) { - // If the base token is ETH we assert the ETH balance is correct. - assertEq(address(alice).balance, aliceBalanceBefore - contribution); - } - - // Ensure that the decimals are set correctly. - assertEq(hyperdrive.decimals(), 18); - - // Ensure that Alice received the correct amount of LP tokens. She should - // receive LP shares totaling the amount of shares that he contributed - // minus the shares set aside for the minimum share reserves and the - // zero address's initial LP contribution. - assertApproxEqAbs( - hyperdrive.balanceOf(AssetId._LP_ASSET_ID, alice), - contribution.divDown( - hyperdrive.getPoolConfig().initialVaultSharePrice - ) - 2 * hyperdrive.getPoolConfig().minimumShareReserves, - config.shareTolerance // Custom share tolerance per instance. - ); - - // Ensure that the share reserves and LP total supply are equal and correct. - assertApproxEqAbs( - hyperdrive.getPoolInfo().shareReserves, - contributionShares, - 1 - ); - assertEq( - hyperdrive.getPoolInfo().lpTotalSupply, - hyperdrive.getPoolInfo().shareReserves - - hyperdrive.getPoolConfig().minimumShareReserves - ); - - // Verify that the correct events were emitted. - verifyFactoryEvents( - deployerCoordinator, - hyperdrive, - alice, - contribution, - FIXED_RATE, - true, - hyperdrive.getPoolConfig().minimumShareReserves, - new bytes(0), - config.shareTolerance - ); - } - - /// @dev Test to verify a market can be deployed and initialized funded - /// by the share token. - function test__deployAndInitialize__asShares() external { - uint256 aliceBalanceBefore = address(alice).balance; - - // Contribution in terms of base. - uint256 contribution = 5_000e18; - - // Contribution in terms of shares. - uint256 contributionShares = convertToShares(contribution); - - // Deploy all Hyperdrive contracts using deployer coordinator contract. - deployHyperdrive( - bytes32(uint256(0xbeefbabe)), // Deployment Id - bytes32(uint256(0xdeadfade)), // Deployment Salt - contributionShares, // Contribution - false // asBase - ); - - // Early termination if share deposits are not supported. - if (!config.enableShareDeposits) { - return; - } - - // Ensure Alice's ETH balance remains the same. - assertEq(address(alice).balance, aliceBalanceBefore); - - // Ensure that the decimals are set correctly. - assertEq(hyperdrive.decimals(), 18); - - // Ensure that Alice received the correct amount of LP tokens. She should - // receive LP shares totaling the amount of shares that he contributed - // minus the shares set aside for the minimum share reserves and the - // zero address's initial LP contribution. - assertApproxEqAbs( - hyperdrive.balanceOf(AssetId._LP_ASSET_ID, alice), - contribution.divDown( - hyperdrive.getPoolConfig().initialVaultSharePrice - ) - 2 * hyperdrive.getPoolConfig().minimumShareReserves, - config.shareTolerance // Custom share tolerance per instance. - ); - - // Ensure that the share reserves and LP total supply are equal and correct. - assertEq(hyperdrive.getPoolInfo().shareReserves, contributionShares); - assertEq( - hyperdrive.getPoolInfo().lpTotalSupply, - hyperdrive.getPoolInfo().shareReserves - - poolConfig.minimumShareReserves - ); - - // Verify that the correct events were emitted. - verifyFactoryEvents( - deployerCoordinator, - hyperdrive, - alice, - contributionShares, - FIXED_RATE, - false, - poolConfig.minimumShareReserves, - new bytes(0), - config.shareTolerance - ); - } - - struct AccountBalances { - uint256 sharesBalance; - uint256 baseBalance; - uint256 ETHBalance; - } - - function getTokenBalances( - address account - ) internal view virtual returns (uint256, uint256); - - function getSupply() internal virtual returns (uint256, uint256); - - function getAccountBalances( - address account - ) internal view returns (AccountBalances memory) { - (uint256 shares, uint256 base) = getTokenBalances(account); - - return - AccountBalances({ - sharesBalance: shares, - baseBalance: base, - ETHBalance: account.balance - }); - } - - function verifyDeposit( - address trader, - uint256 amountPaid, - bool asBase, - uint256 totalBaseBefore, - uint256 totalSharesBefore, - AccountBalances memory traderBalancesBefore, - AccountBalances memory hyperdriveBalancesBefore - ) internal virtual; - - function test__open_long_with_shares(uint256 basePaid) external { - ( - uint256 totalBaseSupplyBefore, - uint256 totalSharesSupplyBefore - ) = getSupply(); - - AccountBalances memory bobBalancesBefore = getAccountBalances(bob); - AccountBalances memory hyperdriveBalanceBefore = getAccountBalances( - address(hyperdrive) - ); - - // Calculate the maximum amount of basePaid we can test. The limit is - // either the max long that Hyperdrive can open or the amount of rETH - // tokens the trader has. - uint256 maxLongAmount = HyperdriveUtils.calculateMaxLong(hyperdrive); - uint256 maxSharesAmount = bobBalancesBefore.sharesBalance; - - // Bob opens a long by depositing stETH. - basePaid = basePaid.normalizeToRange( - 2 * hyperdrive.getPoolConfig().minimumTransactionAmount, - maxLongAmount > maxSharesAmount ? maxSharesAmount : maxLongAmount - ); - - uint256 sharesPaid = convertToShares(basePaid); - - openLong(bob, sharesPaid, false); - verifyDeposit( - bob, - basePaid, - false, - totalBaseSupplyBefore, - totalSharesSupplyBefore, - bobBalancesBefore, - hyperdriveBalanceBefore - ); - } - - function test__open_long_with_base(uint256 basePaid) external { - ( - uint256 totalBaseSupplyBefore, - uint256 totalSharesSupplyBefore - ) = getSupply(); - - AccountBalances memory bobBalancesBefore = getAccountBalances(bob); - AccountBalances memory hyperdriveBalanceBefore = getAccountBalances( - address(hyperdrive) - ); - - // Bob opens a long by depositing stETH. - vm.startPrank(bob); - basePaid = basePaid.normalizeToRange( - 2 * hyperdrive.getPoolConfig().minimumTransactionAmount, - HyperdriveUtils.calculateMaxLong(hyperdrive) - ); - - // We expect the deployAndInitialize to fail with an - // Unsupported token error if depositing with base is not supported. - // If the base token is ETH we expect a NotPayable error. - if (!config.enableBaseDeposits) { - vm.expectRevert( - isBaseETH - ? IHyperdrive.NotPayable.selector - : IHyperdrive.UnsupportedToken.selector - ); - } - - hyperdrive.openLong{ value: isBaseETH ? basePaid : 0 }( - basePaid, - 0, - 0, - IHyperdrive.Options({ - destination: bob, - asBase: true, - extraData: new bytes(0) - }) - ); - // openLong(bob, basePaid, true); - - if (config.enableBaseDeposits) { - verifyDeposit( - bob, - basePaid, - true, - totalBaseSupplyBefore, - totalSharesSupplyBefore, - bobBalancesBefore, - hyperdriveBalanceBefore - ); - } - } -} From b3190f68820ea6fe43d879a39415b1f2492bb06c Mon Sep 17 00:00:00 2001 From: Cash Baller Date: Wed, 27 Mar 2024 14:02:45 -0500 Subject: [PATCH 09/21] natspec for rETH overrides and InstanceTest virtuals --- test/instances/reth/RETHHyperdrive.t.sol | 9 +- test/utils/InstanceTest.sol | 132 ++++++++++++++--------- 2 files changed, 89 insertions(+), 52 deletions(-) diff --git a/test/instances/reth/RETHHyperdrive.t.sol b/test/instances/reth/RETHHyperdrive.t.sol index 7cdd3898d..6a4f4eb3a 100644 --- a/test/instances/reth/RETHHyperdrive.t.sol +++ b/test/instances/reth/RETHHyperdrive.t.sol @@ -101,6 +101,7 @@ contract RETHHyperdriveTest is InstanceTest { ); } + /// @dev Fetches the token balance information of an account. function getTokenBalances( address account ) internal view override returns (uint256, uint256) { @@ -108,6 +109,7 @@ contract RETHHyperdriveTest is InstanceTest { return (rethBalance, rocketTokenRETH.getEthValue(rethBalance)); } + /// @dev Fetches the total supply of the base and share tokens. function getSupply() internal view override returns (uint256, uint256) { return ( rocketNetworkBalances.getTotalETHBalance(), @@ -115,6 +117,7 @@ contract RETHHyperdriveTest is InstanceTest { ); } + /// @dev Verifies that deposit accounting is correct when opening positions. function verifyDeposit( address trader, uint256 amount, @@ -124,13 +127,15 @@ contract RETHHyperdriveTest is InstanceTest { AccountBalances memory traderBalancesBefore, AccountBalances memory hyperdriveBalancesBefore ) internal override { + // Deposits as base is not supported for this instance. if (asBase) { revert IHyperdrive.UnsupportedToken(); } + // Convert the amount in terms of shares. amount = convertToShares(amount); - // Ensure that the ether balances were updated correctly. + // Ensure that the ETH balances were updated correctly. assertEq( address(hyperdrive).balance, hyperdriveBalancesBefore.ETHBalance @@ -149,7 +154,7 @@ contract RETHHyperdriveTest is InstanceTest { 1 ); - // // Ensure the total supply was updated correctly. + // Ensure the total supply was updated correctly. assertEq(rocketTokenRETH.totalSupply(), totalSharesBefore); } diff --git a/test/utils/InstanceTest.sol b/test/utils/InstanceTest.sol index ae79288ce..ae7c15073 100644 --- a/test/utils/InstanceTest.sol +++ b/test/utils/InstanceTest.sol @@ -244,8 +244,7 @@ abstract contract InstanceTest is HyperdriveTest { } } - /// @dev Deploys the Hyperdrive Factory contract and - /// sets the default pool configuration. + /// @dev Deploys the Hyperdrive Factory contract and sets the default pool configuration. function deployFactory() private { // Deploy the hyperdrive factory. vm.startPrank(deployer); @@ -322,6 +321,41 @@ abstract contract InstanceTest is HyperdriveTest { uint256 baseAmount ) internal view virtual returns (uint256 shareAmount); + /// @dev A virtual function that ensures the deposit accounting is correct when opening positions. + /// @param trader The account opening the position. + /// @param basePaid The amount the position was opened with in terms of base. + /// @param asBase Flag to determine whether the position was opened with the base or share token. + /// @param totalBaseBefore Total supply of the base token before the trade. + /// @param totalSharesBefore Total supply of the share token before the trade. + /// @param traderBalancesBefore Balances of tokens of the trader before the trade. + /// @param hyperdriveBalanceBefore Balances of tokens of the Hyperdrive contract before the trade. + function verifyDeposit( + address trader, + uint256 basePaid, + bool asBase, + uint256 totalBaseBefore, + uint256 totalSharesBefore, + AccountBalances memory traderBalancesBefore, + AccountBalances memory hyperdriveBalancesBefore + ) internal virtual; + + /// @dev A virtual function that fetches the token balance information of an account. + /// @param account The account to fetch token balances of. + /// @return sharesBalance The shares token balance of the account. + /// @return baseBalance The base token balance of the account. + function getTokenBalances( + address account + ) + internal + view + virtual + returns (uint256 sharesBalance, uint256 baseBalance); + + /// @dev A virtual function that fetches the total supply of the base and share tokens. + /// @return sharesBalance The total supply of the share token. + /// @return baseBalance The total supply of the base token. + function getSupply() internal virtual returns (uint256, uint256); + /// Tests /// /// @dev Test to verify a market can be deployed and initialized funded by the @@ -460,67 +494,39 @@ abstract contract InstanceTest is HyperdriveTest { ); } - struct AccountBalances { - uint256 sharesBalance; - uint256 baseBalance; - uint256 ETHBalance; - } - - function getTokenBalances( - address account - ) internal view virtual returns (uint256, uint256); - - function getSupply() internal virtual returns (uint256, uint256); - - function getAccountBalances( - address account - ) internal view returns (AccountBalances memory) { - (uint256 shares, uint256 base) = getTokenBalances(account); - - return - AccountBalances({ - sharesBalance: shares, - baseBalance: base, - ETHBalance: account.balance - }); - } - - function verifyDeposit( - address trader, - uint256 amountPaid, - bool asBase, - uint256 totalBaseBefore, - uint256 totalSharesBefore, - AccountBalances memory traderBalancesBefore, - AccountBalances memory hyperdriveBalancesBefore - ) internal virtual; - + /// @dev Fuzz Test to ensure deposit accounting is correct for opening longs + /// with the share token. + /// @param basePaid Amount in terms of base to open a long. function test__open_long_with_shares(uint256 basePaid) external { + // Get balance information before opening a long. ( uint256 totalBaseSupplyBefore, uint256 totalSharesSupplyBefore ) = getSupply(); - AccountBalances memory bobBalancesBefore = getAccountBalances(bob); AccountBalances memory hyperdriveBalanceBefore = getAccountBalances( address(hyperdrive) ); // Calculate the maximum amount of basePaid we can test. The limit is - // either the max long that Hyperdrive can open or the amount of rETH - // tokens the trader has. + // either the maximum long that Hyperdrive can open or the amount of the + // share token the trader has. uint256 maxLongAmount = HyperdriveUtils.calculateMaxLong(hyperdrive); - uint256 maxSharesAmount = bobBalancesBefore.sharesBalance; + uint256 maxShareAmount = bobBalancesBefore.sharesBalance; - // Bob opens a long by depositing stETH. + // We normalize the basePaid variable within a valid range the market can support. basePaid = basePaid.normalizeToRange( 2 * hyperdrive.getPoolConfig().minimumTransactionAmount, - maxLongAmount > maxSharesAmount ? maxSharesAmount : maxLongAmount + maxLongAmount > maxShareAmount ? maxShareAmount : maxLongAmount ); + // Convert the amount to deposit in terms of the share token. uint256 sharesPaid = convertToShares(basePaid); + // Bob opens a long by depositing the share token. openLong(bob, sharesPaid, false); + + // Ensure the deposit accounting is correct. verifyDeposit( bob, basePaid, @@ -532,27 +538,30 @@ abstract contract InstanceTest is HyperdriveTest { ); } + /// @dev Fuzz Test to ensure deposit accounting is correct for opening longs + /// with the base token. This test case is expected to fail if base deposits + /// is not supported. + /// @param basePaid Amount in terms of base to open a long. function test__open_long_with_base(uint256 basePaid) external { + // Get balance information before opening a long. ( uint256 totalBaseSupplyBefore, uint256 totalSharesSupplyBefore ) = getSupply(); - AccountBalances memory bobBalancesBefore = getAccountBalances(bob); AccountBalances memory hyperdriveBalanceBefore = getAccountBalances( address(hyperdrive) ); - // Bob opens a long by depositing stETH. - vm.startPrank(bob); + // We normalize the basePaid variable within a valid range the market can support. basePaid = basePaid.normalizeToRange( 2 * hyperdrive.getPoolConfig().minimumTransactionAmount, HyperdriveUtils.calculateMaxLong(hyperdrive) ); - // We expect the deployAndInitialize to fail with an - // Unsupported token error if depositing with base is not supported. - // If the base token is ETH we expect a NotPayable error. + // We expect the openLong to fail with an Unsupported token error + // if depositing with base is not supported or a NotPayable error + // if the base token is ETH. if (!config.enableBaseDeposits) { vm.expectRevert( isBaseETH @@ -561,6 +570,8 @@ abstract contract InstanceTest is HyperdriveTest { ); } + // Bob opens a long by depositing the base token. + vm.startPrank(bob); hyperdrive.openLong{ value: isBaseETH ? basePaid : 0 }( basePaid, 0, @@ -571,8 +582,8 @@ abstract contract InstanceTest is HyperdriveTest { extraData: new bytes(0) }) ); - // openLong(bob, basePaid, true); + // If base deposits are supported we ensure the deposit accounting is correct. if (config.enableBaseDeposits) { verifyDeposit( bob, @@ -585,4 +596,25 @@ abstract contract InstanceTest is HyperdriveTest { ); } } + + /// Utilities /// + + struct AccountBalances { + uint256 sharesBalance; + uint256 baseBalance; + uint256 ETHBalance; + } + + function getAccountBalances( + address account + ) internal view returns (AccountBalances memory) { + (uint256 shares, uint256 base) = getTokenBalances(account); + + return + AccountBalances({ + sharesBalance: shares, + baseBalance: base, + ETHBalance: account.balance + }); + } } From a20c79993b88419e2669095c6b299ffb59e1b51e Mon Sep 17 00:00:00 2001 From: Cash Baller Date: Wed, 27 Mar 2024 14:06:48 -0500 Subject: [PATCH 10/21] comments in other instances --- test/instances/ezETH/EzETHHyperdrive.t.sol | 29 ++++++++++++---------- test/instances/lseth/LsETHHyperdrive.t.sol | 7 +++++- test/instances/reth/RETHHyperdrive.t.sol | 16 ++++++------ test/instances/steth/StETHHyperdrive.t.sol | 23 +++++++++-------- 4 files changed, 43 insertions(+), 32 deletions(-) diff --git a/test/instances/ezETH/EzETHHyperdrive.t.sol b/test/instances/ezETH/EzETHHyperdrive.t.sol index e85904719..2d6cfd289 100644 --- a/test/instances/ezETH/EzETHHyperdrive.t.sol +++ b/test/instances/ezETH/EzETHHyperdrive.t.sol @@ -97,17 +97,6 @@ contract EzETHHyperdriveTest is InstanceTest { return baseAmount.divDown(sharePrice); } - function getTokenBalances( - address account - ) internal view override returns (uint256, uint256) { - return (EZETH.balanceOf(account), 0); - } - - function getSupply() internal view override returns (uint256, uint256) { - (, uint256 totalPooledEther, ) = getSharePrice(); - return (totalPooledEther, EZETH.totalSupply()); - } - /// @dev Deploys the EzETH deployer coordinator contract. function deployCoordinator() internal override returns (address) { vm.startPrank(alice); @@ -125,6 +114,20 @@ contract EzETHHyperdriveTest is InstanceTest { ); } + /// @dev Fetches the token balance information of an account. + function getTokenBalances( + address account + ) internal view override returns (uint256, uint256) { + return (EZETH.balanceOf(account), 0); + } + + /// @dev Fetches the total supply of the base and share tokens. + function getSupply() internal view override returns (uint256, uint256) { + (, uint256 totalPooledEther, ) = getSharePrice(); + return (totalPooledEther, EZETH.totalSupply()); + } + + /// @dev Verifies that deposit accounting is correct when opening positions. function verifyDeposit( address trader, uint256 basePaid, @@ -182,12 +185,12 @@ contract EzETHHyperdriveTest is InstanceTest { assertApproxEqAbs( EZETH.balanceOf(address(hyperdrive)), hyperdriveBalancesBefore.sharesBalance + expectedShares, - 2 + 2 // Higher tolerance due to rounding when converting back into shares. ); assertApproxEqAbs( EZETH.balanceOf(trader), traderBalancesBefore.sharesBalance - expectedShares, - 2 + 2 // Higher tolerance due to rounding when converting back into shares. ); } } diff --git a/test/instances/lseth/LsETHHyperdrive.t.sol b/test/instances/lseth/LsETHHyperdrive.t.sol index 8c5703e57..c993fd107 100644 --- a/test/instances/lseth/LsETHHyperdrive.t.sol +++ b/test/instances/lseth/LsETHHyperdrive.t.sol @@ -95,16 +95,19 @@ contract LsETHHyperdriveTest is InstanceTest { return RIVER.sharesFromUnderlyingBalance(baseAmount); } + /// @dev Fetches the token balance information of an account. function getTokenBalances( address account ) internal view override returns (uint256, uint256) { return (RIVER.balanceOf(account), RIVER.balanceOfUnderlying(account)); } + /// @dev Fetches the total supply of the base and share tokens. function getSupply() internal view override returns (uint256, uint256) { return (RIVER.totalUnderlyingSupply(), RIVER.totalSupply()); } + /// @dev Verifies that deposit accounting is correct when opening positions. function verifyDeposit( address trader, uint256 amount, @@ -114,13 +117,15 @@ contract LsETHHyperdriveTest is InstanceTest { AccountBalances memory traderBalancesBefore, AccountBalances memory hyperdriveBalancesBefore ) internal override { + // Deposits as base is not supported for this instance. if (asBase) { revert IHyperdrive.NotPayable(); } + // Convert the amount in terms of shares. amount = convertToShares(amount); - // Ensure that the ether balances were updated correctly. + // Ensure that the ETH balances were updated correctly. assertEq( address(hyperdrive).balance, hyperdriveBalancesBefore.ETHBalance diff --git a/test/instances/reth/RETHHyperdrive.t.sol b/test/instances/reth/RETHHyperdrive.t.sol index 6a4f4eb3a..56f970d03 100644 --- a/test/instances/reth/RETHHyperdrive.t.sol +++ b/test/instances/reth/RETHHyperdrive.t.sol @@ -101,14 +101,6 @@ contract RETHHyperdriveTest is InstanceTest { ); } - /// @dev Fetches the token balance information of an account. - function getTokenBalances( - address account - ) internal view override returns (uint256, uint256) { - uint256 rethBalance = rocketTokenRETH.balanceOf(account); - return (rethBalance, rocketTokenRETH.getEthValue(rethBalance)); - } - /// @dev Fetches the total supply of the base and share tokens. function getSupply() internal view override returns (uint256, uint256) { return ( @@ -117,6 +109,14 @@ contract RETHHyperdriveTest is InstanceTest { ); } + /// @dev Fetches the token balance information of an account. + function getTokenBalances( + address account + ) internal view override returns (uint256, uint256) { + uint256 rethBalance = rocketTokenRETH.balanceOf(account); + return (rethBalance, rocketTokenRETH.getEthValue(rethBalance)); + } + /// @dev Verifies that deposit accounting is correct when opening positions. function verifyDeposit( address trader, diff --git a/test/instances/steth/StETHHyperdrive.t.sol b/test/instances/steth/StETHHyperdrive.t.sol index c0e0031e9..a06e80a92 100644 --- a/test/instances/steth/StETHHyperdrive.t.sol +++ b/test/instances/steth/StETHHyperdrive.t.sol @@ -64,16 +64,6 @@ contract StETHHyperdriveTest is InstanceTest { /// Overrides /// - function getSupply() internal view override returns (uint256, uint256) { - return (LIDO.getTotalPooledEther(), LIDO.getTotalShares()); - } - - function getTokenBalances( - address account - ) internal view override returns (uint256, uint256) { - return (LIDO.sharesOf(account), LIDO.balanceOf(account)); - } - /// @dev Converts base amount to the equivalent about in stETH. function convertToShares( uint256 baseAmount @@ -101,6 +91,19 @@ contract StETHHyperdriveTest is InstanceTest { ); } + /// @dev Fetches the total supply of the base and share tokens. + function getSupply() internal view override returns (uint256, uint256) { + return (LIDO.getTotalPooledEther(), LIDO.getTotalShares()); + } + + /// @dev Fetches the token balance information of an account. + function getTokenBalances( + address account + ) internal view override returns (uint256, uint256) { + return (LIDO.sharesOf(account), LIDO.balanceOf(account)); + } + + /// @dev Verifies that deposit accounting is correct when opening positions. function verifyDeposit( address trader, uint256 amountPaid, From 5806382ec49d3d0d02753470bb95d7f76cb1482c Mon Sep 17 00:00:00 2001 From: Cash Baller Date: Wed, 27 Mar 2024 14:22:43 -0500 Subject: [PATCH 11/21] fix build --- test/utils/InstanceTest.sol | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/test/utils/InstanceTest.sol b/test/utils/InstanceTest.sol index ae7c15073..ed3fcafeb 100644 --- a/test/utils/InstanceTest.sol +++ b/test/utils/InstanceTest.sol @@ -328,7 +328,7 @@ abstract contract InstanceTest is HyperdriveTest { /// @param totalBaseBefore Total supply of the base token before the trade. /// @param totalSharesBefore Total supply of the share token before the trade. /// @param traderBalancesBefore Balances of tokens of the trader before the trade. - /// @param hyperdriveBalanceBefore Balances of tokens of the Hyperdrive contract before the trade. + /// @param hyperdriveBalancesBefore Balances of tokens of the Hyperdrive contract before the trade. function verifyDeposit( address trader, uint256 basePaid, @@ -352,9 +352,12 @@ abstract contract InstanceTest is HyperdriveTest { returns (uint256 sharesBalance, uint256 baseBalance); /// @dev A virtual function that fetches the total supply of the base and share tokens. - /// @return sharesBalance The total supply of the share token. - /// @return baseBalance The total supply of the base token. - function getSupply() internal virtual returns (uint256, uint256); + /// @return totalSupplyShares The total supply of the share token. + /// @return totalSupplyBase The total supply of the base token. + function getSupply() + internal + virtual + returns (uint256 totalSupplyShares, uint256 totalSupplyBase); /// Tests /// From 00fa7d163f4139c9d7c30c6601d68def05f6fb1e Mon Sep 17 00:00:00 2001 From: Cash Baller Date: Wed, 27 Mar 2024 14:28:16 -0500 Subject: [PATCH 12/21] Fix lint errors by asserting value stays the same in rETH and lsETH --- test/instances/lseth/LsETHHyperdrive.t.sol | 3 +++ test/instances/reth/RETHHyperdrive.t.sol | 3 +++ 2 files changed, 6 insertions(+) diff --git a/test/instances/lseth/LsETHHyperdrive.t.sol b/test/instances/lseth/LsETHHyperdrive.t.sol index c993fd107..bbc857868 100644 --- a/test/instances/lseth/LsETHHyperdrive.t.sol +++ b/test/instances/lseth/LsETHHyperdrive.t.sol @@ -144,6 +144,9 @@ contract LsETHHyperdriveTest is InstanceTest { 1 ); + // Ensure the total base supply was updated correctly. + assertEq(RIVER.totalUnderlyingSupply(), totalBaseBefore); + // Ensure the total supply was updated correctly. assertEq(RIVER.totalSupply(), totalSharesBefore); } diff --git a/test/instances/reth/RETHHyperdrive.t.sol b/test/instances/reth/RETHHyperdrive.t.sol index 56f970d03..d42a4941e 100644 --- a/test/instances/reth/RETHHyperdrive.t.sol +++ b/test/instances/reth/RETHHyperdrive.t.sol @@ -154,6 +154,9 @@ contract RETHHyperdriveTest is InstanceTest { 1 ); + // Ensure the total base supply was updated correctly. + assertEq(rocketNetworkBalances.getTotalETHBalance(), totalBaseBefore); + // Ensure the total supply was updated correctly. assertEq(rocketTokenRETH.totalSupply(), totalSharesBefore); } From afd79609bf09b13cb6713e9b38ea6e4a06c2e0a2 Mon Sep 17 00:00:00 2001 From: Cash Baller Date: Wed, 27 Mar 2024 15:06:52 -0500 Subject: [PATCH 13/21] address nits --- test/instances/lseth/LsETHHyperdrive.t.sol | 2 +- test/instances/reth/RETHHyperdrive.t.sol | 2 +- test/utils/InstanceTest.sol | 13 +++++++------ 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/test/instances/lseth/LsETHHyperdrive.t.sol b/test/instances/lseth/LsETHHyperdrive.t.sol index bbc857868..08a90d909 100644 --- a/test/instances/lseth/LsETHHyperdrive.t.sol +++ b/test/instances/lseth/LsETHHyperdrive.t.sol @@ -112,7 +112,7 @@ contract LsETHHyperdriveTest is InstanceTest { address trader, uint256 amount, bool asBase, - uint totalBaseBefore, // unused + uint totalBaseBefore, uint256 totalSharesBefore, AccountBalances memory traderBalancesBefore, AccountBalances memory hyperdriveBalancesBefore diff --git a/test/instances/reth/RETHHyperdrive.t.sol b/test/instances/reth/RETHHyperdrive.t.sol index d42a4941e..b703b98b3 100644 --- a/test/instances/reth/RETHHyperdrive.t.sol +++ b/test/instances/reth/RETHHyperdrive.t.sol @@ -122,7 +122,7 @@ contract RETHHyperdriveTest is InstanceTest { address trader, uint256 amount, bool asBase, - uint256 totalBaseBefore, // unused + uint256 totalBaseBefore, uint256 totalSharesBefore, AccountBalances memory traderBalancesBefore, AccountBalances memory hyperdriveBalancesBefore diff --git a/test/utils/InstanceTest.sol b/test/utils/InstanceTest.sol index ed3fcafeb..834809417 100644 --- a/test/utils/InstanceTest.sol +++ b/test/utils/InstanceTest.sol @@ -197,7 +197,7 @@ abstract contract InstanceTest is HyperdriveTest { config.vaultSharesToken.approve(deployerCoordinator, 100_000e18); // We expect the deployAndInitialize to fail with an - // Unsupported token error if depositing with base is not supported. + // UnsupportedToken error if depositing with base is not supported. // If the base token is ETH we expect a NotPayable error. if (!config.enableBaseDeposits && asBase) { vm.expectRevert( @@ -208,7 +208,7 @@ abstract contract InstanceTest is HyperdriveTest { } // We expect the deployAndInitialize to fail with an - // Unsupported token error if depositing with shares is not supported. + // UnsupportedToken error if depositing with shares is not supported. if (!config.enableShareDeposits && !asBase) { vm.expectRevert(IHyperdrive.UnsupportedToken.selector); } @@ -321,7 +321,8 @@ abstract contract InstanceTest is HyperdriveTest { uint256 baseAmount ) internal view virtual returns (uint256 shareAmount); - /// @dev A virtual function that ensures the deposit accounting is correct when opening positions. + /// @dev A virtual function that ensures the deposit accounting is correct + /// when opening positions. /// @param trader The account opening the position. /// @param basePaid The amount the position was opened with in terms of base. /// @param asBase Flag to determine whether the position was opened with the base or share token. @@ -500,7 +501,7 @@ abstract contract InstanceTest is HyperdriveTest { /// @dev Fuzz Test to ensure deposit accounting is correct for opening longs /// with the share token. /// @param basePaid Amount in terms of base to open a long. - function test__open_long_with_shares(uint256 basePaid) external { + function test_open_long_with_shares(uint256 basePaid) external { // Get balance information before opening a long. ( uint256 totalBaseSupplyBefore, @@ -545,7 +546,7 @@ abstract contract InstanceTest is HyperdriveTest { /// with the base token. This test case is expected to fail if base deposits /// is not supported. /// @param basePaid Amount in terms of base to open a long. - function test__open_long_with_base(uint256 basePaid) external { + function test_open_long_with_base(uint256 basePaid) external { // Get balance information before opening a long. ( uint256 totalBaseSupplyBefore, @@ -562,7 +563,7 @@ abstract contract InstanceTest is HyperdriveTest { HyperdriveUtils.calculateMaxLong(hyperdrive) ); - // We expect the openLong to fail with an Unsupported token error + // We expect the openLong to fail with an UnsupportedToken error // if depositing with base is not supported or a NotPayable error // if the base token is ETH. if (!config.enableBaseDeposits) { From 35cfe8957b54f7cab5260d897d360260f600f196 Mon Sep 17 00:00:00 2001 From: Cash Baller Date: Thu, 28 Mar 2024 11:57:30 -0500 Subject: [PATCH 14/21] update func sig for getSupply --- test/utils/InstanceTest.sol | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/test/utils/InstanceTest.sol b/test/utils/InstanceTest.sol index 834809417..d5d533bbb 100644 --- a/test/utils/InstanceTest.sol +++ b/test/utils/InstanceTest.sol @@ -244,7 +244,8 @@ abstract contract InstanceTest is HyperdriveTest { } } - /// @dev Deploys the Hyperdrive Factory contract and sets the default pool configuration. + /// @dev Deploys the Hyperdrive Factory contract and sets + /// the default pool configuration. function deployFactory() private { // Deploy the hyperdrive factory. vm.startPrank(deployer); @@ -353,12 +354,12 @@ abstract contract InstanceTest is HyperdriveTest { returns (uint256 sharesBalance, uint256 baseBalance); /// @dev A virtual function that fetches the total supply of the base and share tokens. - /// @return totalSupplyShares The total supply of the share token. /// @return totalSupplyBase The total supply of the base token. + /// @return totalSupplyShares The total supply of the share token. function getSupply() internal virtual - returns (uint256 totalSupplyShares, uint256 totalSupplyBase); + returns (uint256 totalSupplyBase, uint256 totalSupplyShares); /// Tests /// From 95b38b575033708c8e4ff69fc76cbc85249bf461 Mon Sep 17 00:00:00 2001 From: Cash Baller Date: Thu, 28 Mar 2024 13:30:00 -0500 Subject: [PATCH 15/21] added check for open long return value --- test/utils/InstanceTest.sol | 34 ++++++++++++++++++++++++++++++---- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/test/utils/InstanceTest.sol b/test/utils/InstanceTest.sol index d5d533bbb..2e38b4b3c 100644 --- a/test/utils/InstanceTest.sol +++ b/test/utils/InstanceTest.sol @@ -529,7 +529,20 @@ abstract contract InstanceTest is HyperdriveTest { uint256 sharesPaid = convertToShares(basePaid); // Bob opens a long by depositing the share token. - openLong(bob, sharesPaid, false); + (uint256 maturityTime, uint256 bondAmount) = openLong( + bob, + sharesPaid, + false + ); + + // Ensure that Bob received the correct amount of bonds. + assertEq( + hyperdrive.balanceOf( + AssetId.encodeAssetId(AssetId.AssetIdPrefix.Long, maturityTime), + bob + ), + bondAmount + ); // Ensure the deposit accounting is correct. verifyDeposit( @@ -577,7 +590,9 @@ abstract contract InstanceTest is HyperdriveTest { // Bob opens a long by depositing the base token. vm.startPrank(bob); - hyperdrive.openLong{ value: isBaseETH ? basePaid : 0 }( + (uint256 maturityTime, uint256 bondAmount) = hyperdrive.openLong{ + value: isBaseETH ? basePaid : 0 + }( basePaid, 0, 0, @@ -587,9 +602,20 @@ abstract contract InstanceTest is HyperdriveTest { extraData: new bytes(0) }) ); - - // If base deposits are supported we ensure the deposit accounting is correct. if (config.enableBaseDeposits) { + // Ensure that Bob received the correct amount of bonds. + assertEq( + hyperdrive.balanceOf( + AssetId.encodeAssetId( + AssetId.AssetIdPrefix.Long, + maturityTime + ), + bob + ), + bondAmount + ); + + // If base deposits are supported we ensure the deposit accounting is correct. verifyDeposit( bob, basePaid, From 33f94d24d882aa55ceed918e92d3312bf3c2bf9b Mon Sep 17 00:00:00 2001 From: Cash Baller Date: Wed, 27 Mar 2024 19:01:02 -0500 Subject: [PATCH 16/21] Generalize open short with share token test case --- test/instances/ezETH/EzETHHyperdrive.t.sol | 20 +++++++- test/instances/lseth/LsETHHyperdrive.t.sol | 10 +++- test/instances/reth/RETHHyperdrive.t.sol | 10 +++- test/instances/steth/StETHHyperdrive.t.sol | 10 +++- test/utils/InstanceTest.sol | 54 ++++++++++++++++++++++ 5 files changed, 100 insertions(+), 4 deletions(-) diff --git a/test/instances/ezETH/EzETHHyperdrive.t.sol b/test/instances/ezETH/EzETHHyperdrive.t.sol index 2d6cfd289..a33c1616a 100644 --- a/test/instances/ezETH/EzETHHyperdrive.t.sol +++ b/test/instances/ezETH/EzETHHyperdrive.t.sol @@ -91,12 +91,30 @@ contract EzETHHyperdriveTest is InstanceTest { /// @dev Converts base amount to the equivalent about in EzETH. function convertToShares( uint256 baseAmount - ) internal view override returns (uint256 shareAmount) { + ) internal view override returns (uint256) { // Get protocol state information used for calculating shares. (uint256 sharePrice, , ) = getSharePrice(); return baseAmount.divDown(sharePrice); } + /// @dev Converts share amount to the equivalent amount in ETH. + function convertToBase( + uint256 baseAmount + ) internal view override returns (uint256) { + // Get the total TVL priced in ETH from RestakeManager. + (, , uint256 totalTVL) = RESTAKE_MANAGER.calculateTVLs(); + + // Get the total supply of the ezETH token. + uint256 totalSupply = EZETH.totalSupply(); + + return + RENZO_ORACLE.calculateRedeemAmount( + baseAmount, + totalSupply, + totalTVL + ); + } + /// @dev Deploys the EzETH deployer coordinator contract. function deployCoordinator() internal override returns (address) { vm.startPrank(alice); diff --git a/test/instances/lseth/LsETHHyperdrive.t.sol b/test/instances/lseth/LsETHHyperdrive.t.sol index 08a90d909..8fcae8f81 100644 --- a/test/instances/lseth/LsETHHyperdrive.t.sol +++ b/test/instances/lseth/LsETHHyperdrive.t.sol @@ -90,11 +90,19 @@ contract LsETHHyperdriveTest is InstanceTest { /// @dev Converts base amount to the equivalent amount in LsETH. function convertToShares( uint256 baseAmount - ) internal view override returns (uint256 shareAmount) { + ) internal view override returns (uint256) { // River has a built-in function for computing price in terms of shares. return RIVER.sharesFromUnderlyingBalance(baseAmount); } + /// @dev Converts base amount to the equivalent amount in ETH. + function convertToBase( + uint256 shareAmount + ) internal view override returns (uint256) { + // River has a built-in function for computing price in terms of base. + return RIVER.underlyingBalanceFromShares(shareAmount); + } + /// @dev Fetches the token balance information of an account. function getTokenBalances( address account diff --git a/test/instances/reth/RETHHyperdrive.t.sol b/test/instances/reth/RETHHyperdrive.t.sol index b703b98b3..b8bc1da44 100644 --- a/test/instances/reth/RETHHyperdrive.t.sol +++ b/test/instances/reth/RETHHyperdrive.t.sol @@ -79,11 +79,19 @@ contract RETHHyperdriveTest is InstanceTest { /// @dev Converts base amount to the equivalent amount in rETH. function convertToShares( uint256 baseAmount - ) internal view override returns (uint256 shareAmount) { + ) internal view override returns (uint256) { // Rocket Pool has a built-in function for computing price in terms of shares. return rocketTokenRETH.getRethValue(baseAmount); } + /// @dev Converts share amount to the equivalent amount in ETH. + function convertToBase( + uint256 baseAmount + ) internal view override returns (uint256) { + // Rocket Pool has a built-in function for computing price in terms of base. + return rocketTokenRETH.getEthValue(baseAmount); + } + /// @dev Deploys the rETH deployer coordinator contract. function deployCoordinator() internal override returns (address) { vm.startPrank(alice); diff --git a/test/instances/steth/StETHHyperdrive.t.sol b/test/instances/steth/StETHHyperdrive.t.sol index a06e80a92..f620a9106 100644 --- a/test/instances/steth/StETHHyperdrive.t.sol +++ b/test/instances/steth/StETHHyperdrive.t.sol @@ -67,13 +67,21 @@ contract StETHHyperdriveTest is InstanceTest { /// @dev Converts base amount to the equivalent about in stETH. function convertToShares( uint256 baseAmount - ) internal view override returns (uint256 shareAmount) { + ) internal view override returns (uint256) { // Get protocol state information used for calculating shares. uint256 totalPooledEther = LIDO.getTotalPooledEther(); uint256 totalShares = LIDO.getTotalShares(); return baseAmount.mulDivDown(totalShares, totalPooledEther); } + /// @dev Converts share amount to the equivalent amount in ETH. + function convertToBase( + uint256 shareAmount + ) internal view override returns (uint256) { + // Lido has a built-in function for computing price in terms of base. + return LIDO.getPooledEthByShares(shareAmount); + } + /// @dev Deploys the rETH deployer coordinator contract. function deployCoordinator() internal override returns (address) { vm.startPrank(alice); diff --git a/test/utils/InstanceTest.sol b/test/utils/InstanceTest.sol index 2e38b4b3c..5533ede1e 100644 --- a/test/utils/InstanceTest.sol +++ b/test/utils/InstanceTest.sol @@ -322,6 +322,14 @@ abstract contract InstanceTest is HyperdriveTest { uint256 baseAmount ) internal view virtual returns (uint256 shareAmount); + /// @dev A virtual function that converts an amount in terms of the share token + /// to equivalent amount in base. + /// @param shareAmount Amount in terms of the shares. + /// @return baseAmount in terms of base. + function convertToBase( + uint256 shareAmount + ) internal view virtual returns (uint256 baseAmount); + /// @dev A virtual function that ensures the deposit accounting is correct /// when opening positions. /// @param trader The account opening the position. @@ -628,6 +636,52 @@ abstract contract InstanceTest is HyperdriveTest { } } + function test_open_short_with_shares(uint256 shortAmount) external { + // Get some balance information before the deposit. + ( + uint256 totalBaseSupplyBefore, + uint256 totalSharesSupplyBefore + ) = getSupply(); + AccountBalances memory bobBalancesBefore = getAccountBalances(bob); + AccountBalances memory hyperdriveBalancesBefore = getAccountBalances( + address(hyperdrive) + ); + + // Bob opens a short by depositing LsETH. + vm.startPrank(bob); + shortAmount = shortAmount.normalizeToRange( + 100 * hyperdrive.getPoolConfig().minimumTransactionAmount, + HyperdriveUtils.calculateMaxShort(hyperdrive) + ); + // RIVER.approve(address(hyperdrive), shortAmount); + (, uint256 sharesPaid) = openShort(bob, shortAmount, false); + uint256 basePaid = convertToBase(sharesPaid); + + // Ensure that the amount of base paid by the short is reasonable. + uint256 realizedRate = HyperdriveUtils.calculateAPRFromRealizedPrice( + shortAmount - basePaid, + shortAmount, + 1e18 + ); + assertGt(basePaid, 0); + assertGe( + realizedRate, + FIXED_RATE.mulDown(config.positionDuration.divDown(365 days)) + ); + + // Ensure that River aggregates and the token balances were updated + // correctly during the trade. + verifyDeposit( + bob, + basePaid, + false, + totalBaseSupplyBefore, + totalSharesSupplyBefore, + bobBalancesBefore, + hyperdriveBalancesBefore + ); + } + /// Utilities /// struct AccountBalances { From 5786aef2a35559e8c22ccd8b379e811899f81a6e Mon Sep 17 00:00:00 2001 From: Cash Baller Date: Thu, 28 Mar 2024 14:55:45 -0500 Subject: [PATCH 17/21] Add open short generalization to instance test --- test/instances/ezETH/EzETHHyperdrive.t.sol | 82 ---------- test/instances/lseth/LsETHHyperdrive.t.sol | 64 -------- test/instances/reth/RETHHyperdrive.t.sol | 64 -------- test/instances/steth/StETHHyperdrive.t.sol | 83 ---------- test/utils/InstanceTest.sol | 179 +++++++++++++++++---- 5 files changed, 145 insertions(+), 327 deletions(-) diff --git a/test/instances/ezETH/EzETHHyperdrive.t.sol b/test/instances/ezETH/EzETHHyperdrive.t.sol index a33c1616a..e5f4a2d6a 100644 --- a/test/instances/ezETH/EzETHHyperdrive.t.sol +++ b/test/instances/ezETH/EzETHHyperdrive.t.sol @@ -395,88 +395,6 @@ contract EzETHHyperdriveTest is InstanceTest { // /// Short /// - function test_open_short_with_eth(uint256 shortAmount) external { - vm.stopPrank(); - vm.startPrank(bob); - - // Bob opens a short by depositing ETH. - shortAmount = shortAmount.normalizeToRange( - 2 * hyperdrive.getPoolConfig().minimumTransactionAmount, - HyperdriveUtils.calculateMaxShort(hyperdrive) - ); - - // Ensure that we get an UnsupportedToken error. Opening positions - // with ETH are not allowed right now. There is a great enough - // precision loss when minting ezeth that warrants some investigation - // before we can turn this on. Until then, we can zap ezeth into the - // pool. - vm.expectRevert(IHyperdrive.NotPayable.selector); - hyperdrive.openShort{ value: shortAmount }( - shortAmount, - shortAmount, - 0, - IHyperdrive.Options({ - destination: bob, - asBase: true, - extraData: new bytes(0) - }) - ); - } - - function test_open_short_with_ezeth(uint256 shortAmount) external { - vm.stopPrank(); - vm.startPrank(bob); - - // Get some balance information before the deposit. - ( - , - uint256 totalPooledEtherBefore, - uint256 totalSharesBefore - ) = getSharePrice(); - AccountBalances memory bobBalancesBefore = getAccountBalances(bob); - AccountBalances memory hyperdriveBalancesBefore = getAccountBalances( - address(hyperdrive) - ); - - // Calculate the maximum amount we can short. - shortAmount = shortAmount.normalizeToRange( - 2 * hyperdrive.getPoolConfig().minimumTransactionAmount, - HyperdriveUtils.calculateMaxShort(hyperdrive) - ); - - // Bob opens a short by depositing ezETH. - EZETH.approve(address(hyperdrive), shortAmount); - (, uint256 sharesPaid) = openShort(bob, shortAmount, false); - - // Get the base Bob paid for the short. - (, uint256 totalPooledEther, uint256 totalShares) = getSharePrice(); - uint256 basePaid = sharesPaid.mulDivDown(totalPooledEther, totalShares); - - // Ensure that the amount of base paid by the short is reasonable. - uint256 realizedRate = HyperdriveUtils.calculateAPRFromRealizedPrice( - shortAmount - basePaid, - shortAmount, - 1e18 - ); - assertGt(basePaid, 0); - assertGe( - realizedRate, - FIXED_RATE.mulDown(POSITION_DURATION_15_DAYS.divDown(365 days)) - ); - - // Ensure that Renzo's aggregates and the token balances were updated - // correctly during the trade. - verifyDeposit( - bob, - basePaid, - false, - totalPooledEtherBefore, - totalSharesBefore, - bobBalancesBefore, - hyperdriveBalancesBefore - ); - } - function test_open_short_refunds() external { vm.startPrank(bob); diff --git a/test/instances/lseth/LsETHHyperdrive.t.sol b/test/instances/lseth/LsETHHyperdrive.t.sol index 8fcae8f81..df15f2ce8 100644 --- a/test/instances/lseth/LsETHHyperdrive.t.sol +++ b/test/instances/lseth/LsETHHyperdrive.t.sol @@ -332,70 +332,6 @@ contract LsETHHyperdriveTest is InstanceTest { /// Short /// - function test_open_short_with_eth(uint256 shortAmount) external { - // Bob opens a short by depositing ETH. This is not allowed and - // should throw an unsupported token exception. - shortAmount = shortAmount.normalizeToRange( - 100 * hyperdrive.getPoolConfig().minimumTransactionAmount, - HyperdriveUtils.calculateMaxShort(hyperdrive) - ); - vm.deal(bob, shortAmount); - vm.expectRevert(IHyperdrive.NotPayable.selector); - hyperdrive.openShort{ value: shortAmount }( - shortAmount, - shortAmount, - 0, - IHyperdrive.Options({ - destination: bob, - asBase: true, - extraData: new bytes(0) - }) - ); - } - - function test_open_short_with_lseth(uint256 shortAmount) external { - // Get some balance information before the deposit. - ( - uint256 totalBaseSupplyBefore, - uint256 totalSharesSupplyBefore - ) = getSupply(); - AccountBalances memory bobBalancesBefore = getAccountBalances(bob); - AccountBalances memory hyperdriveBalancesBefore = getAccountBalances( - address(hyperdrive) - ); - - // Bob opens a short by depositing LsETH. - vm.startPrank(bob); - shortAmount = shortAmount.normalizeToRange( - 100 * hyperdrive.getPoolConfig().minimumTransactionAmount, - HyperdriveUtils.calculateMaxShort(hyperdrive) - ); - RIVER.approve(address(hyperdrive), shortAmount); - (, uint256 sharesPaid) = openShort(bob, shortAmount, false); - uint256 basePaid = RIVER.underlyingBalanceFromShares(sharesPaid); - - // Ensure that the amount of base paid by the short is reasonable. - uint256 realizedRate = HyperdriveUtils.calculateAPRFromRealizedPrice( - shortAmount - basePaid, - shortAmount, - 1e18 - ); - assertGt(basePaid, 0); - assertGe(realizedRate, FIXED_RATE); - - // Ensure that River aggregates and the token balances were updated - // correctly during the trade. - verifyDeposit( - bob, - basePaid, - false, - totalBaseSupplyBefore, - totalSharesSupplyBefore, - bobBalancesBefore, - hyperdriveBalancesBefore - ); - } - function test_open_short_refunds() external { vm.startPrank(bob); diff --git a/test/instances/reth/RETHHyperdrive.t.sol b/test/instances/reth/RETHHyperdrive.t.sol index b8bc1da44..061cb6e7e 100644 --- a/test/instances/reth/RETHHyperdrive.t.sol +++ b/test/instances/reth/RETHHyperdrive.t.sol @@ -365,70 +365,6 @@ contract RETHHyperdriveTest is InstanceTest { // /// Short /// - function test_open_short_with_eth(uint256 shortAmount) external { - // Bob opens a short by depositing ETH. This is not allowed and - // should throw an unsupported token exception. - shortAmount = shortAmount.normalizeToRange( - 100 * hyperdrive.getPoolConfig().minimumTransactionAmount, - HyperdriveUtils.calculateMaxShort(hyperdrive) - ); - vm.deal(bob, shortAmount); - vm.expectRevert(IHyperdrive.NotPayable.selector); - hyperdrive.openShort{ value: shortAmount }( - shortAmount, - shortAmount, - 0, - IHyperdrive.Options({ - destination: bob, - asBase: true, - extraData: new bytes(0) - }) - ); - } - - function test_open_short_with_reth(uint256 shortAmount) external { - // Get some balance information before the deposit. - ( - uint256 totalBaseSupplyBefore, - uint256 totalSharesSupplyBefore - ) = getSupply(); - AccountBalances memory bobBalancesBefore = getAccountBalances(bob); - AccountBalances memory hyperdriveBalancesBefore = getAccountBalances( - address(hyperdrive) - ); - - // Bob opens a short by depositing rETH. - vm.startPrank(bob); - shortAmount = shortAmount.normalizeToRange( - 100 * hyperdrive.getPoolConfig().minimumTransactionAmount, - HyperdriveUtils.calculateMaxShort(hyperdrive) - ); - rocketTokenRETH.approve(address(hyperdrive), shortAmount); - (, uint256 sharesPaid) = openShort(bob, shortAmount, false); - uint256 basePaid = rocketTokenRETH.getEthValue(sharesPaid); - - // Ensure that the amount of base paid by the short is reasonable. - uint256 realizedRate = HyperdriveUtils.calculateAPRFromRealizedPrice( - shortAmount - basePaid, - shortAmount, - 1e18 - ); - assertGt(basePaid, 0); - assertGe(realizedRate, FIXED_RATE); - - // Ensure that Rocket Pool's aggregates and the token balances were updated - // correctly during the trade. - verifyDeposit( - bob, - basePaid, - false, - totalBaseSupplyBefore, - totalSharesSupplyBefore, - bobBalancesBefore, - hyperdriveBalancesBefore - ); - } - function test_open_short_refunds() external { vm.startPrank(bob); diff --git a/test/instances/steth/StETHHyperdrive.t.sol b/test/instances/steth/StETHHyperdrive.t.sol index f620a9106..128921920 100644 --- a/test/instances/steth/StETHHyperdrive.t.sol +++ b/test/instances/steth/StETHHyperdrive.t.sol @@ -333,89 +333,6 @@ contract StETHHyperdriveTest is InstanceTest { /// Short /// - function test_open_short_with_ETH(uint256 shortAmount) external { - // Get some balance information before the deposit. - uint256 totalPooledEtherBefore = LIDO.getTotalPooledEther(); - uint256 totalSharesBefore = LIDO.getTotalShares(); - AccountBalances memory bobBalancesBefore = getAccountBalances(bob); - AccountBalances memory hyperdriveBalancesBefore = getAccountBalances( - address(hyperdrive) - ); - - // Bob opens a short by depositing ETH. - shortAmount = shortAmount.normalizeToRange( - 2 * hyperdrive.getPoolConfig().minimumTransactionAmount, - HyperdriveUtils.calculateMaxShort(hyperdrive) - ); - uint256 balanceBefore = bob.balance; - vm.deal(bob, shortAmount); - (, uint256 basePaid) = openShort(bob, shortAmount); - vm.deal(bob, balanceBefore - basePaid); - - // Ensure that the amount of base paid by the short is reasonable. - uint256 realizedRate = HyperdriveUtils.calculateAPRFromRealizedPrice( - shortAmount - basePaid, - shortAmount, - 1e18 - ); - assertGt(basePaid, 0); - assertGe(realizedRate, FIXED_RATE); - - // Ensure that Lido's aggregates and the token balances were updated - // correctly during the trade. - verifyDeposit( - bob, - basePaid, - true, - totalPooledEtherBefore, - totalSharesBefore, - bobBalancesBefore, - hyperdriveBalancesBefore - ); - } - - function test_open_short_with_steth(uint256 shortAmount) external { - // Get some balance information before the deposit. - uint256 totalPooledEtherBefore = LIDO.getTotalPooledEther(); - uint256 totalSharesBefore = LIDO.getTotalShares(); - AccountBalances memory bobBalancesBefore = getAccountBalances(bob); - AccountBalances memory hyperdriveBalancesBefore = getAccountBalances( - address(hyperdrive) - ); - - // Bob opens a short by depositing ETH. - shortAmount = shortAmount.normalizeToRange( - 2 * hyperdrive.getPoolConfig().minimumTransactionAmount, - HyperdriveUtils.calculateMaxShort(hyperdrive) - ); - (, uint256 sharesPaid) = openShort(bob, shortAmount, false); - uint256 basePaid = sharesPaid.mulDivDown( - LIDO.getTotalPooledEther(), - LIDO.getTotalShares() - ); - - // Ensure that the amount of base paid by the short is reasonable. - uint256 realizedRate = HyperdriveUtils.calculateAPRFromRealizedPrice( - shortAmount - basePaid, - shortAmount, - 1e18 - ); - assertGt(basePaid, 0); - assertGe(realizedRate, FIXED_RATE); - - // Ensure that Lido's aggregates and the token balances were updated - // correctly during the trade. - verifyDeposit( - bob, - basePaid, - false, - totalPooledEtherBefore, - totalSharesBefore, - bobBalancesBefore, - hyperdriveBalancesBefore - ); - } - function test_open_short_refunds() external { vm.startPrank(bob); diff --git a/test/utils/InstanceTest.sol b/test/utils/InstanceTest.sol index 5533ede1e..ee49dcf8c 100644 --- a/test/utils/InstanceTest.sol +++ b/test/utils/InstanceTest.sol @@ -507,7 +507,7 @@ abstract contract InstanceTest is HyperdriveTest { ); } - /// @dev Fuzz Test to ensure deposit accounting is correct for opening longs + /// @dev Fuzz Test to ensure deposit accounting is correct when opening longs /// with the share token. /// @param basePaid Amount in terms of base to open a long. function test_open_long_with_shares(uint256 basePaid) external { @@ -536,11 +536,22 @@ abstract contract InstanceTest is HyperdriveTest { // Convert the amount to deposit in terms of the share token. uint256 sharesPaid = convertToShares(basePaid); - // Bob opens a long by depositing the share token. - (uint256 maturityTime, uint256 bondAmount) = openLong( - bob, + // Bob opens a long by depositing the base token. + // We expect the openShort to fail with an UnsupportedToken error + // if depositing with shares is not supported. + vm.startPrank(bob); + if (!config.enableShareDeposits) { + vm.expectRevert(IHyperdrive.UnsupportedToken.selector); + } + (uint256 maturityTime, uint256 bondAmount) = hyperdrive.openLong( sharesPaid, - false + 0, + 0, + IHyperdrive.Options({ + destination: bob, + asBase: false, + extraData: new bytes(0) + }) ); // Ensure that Bob received the correct amount of bonds. @@ -564,7 +575,7 @@ abstract contract InstanceTest is HyperdriveTest { ); } - /// @dev Fuzz Test to ensure deposit accounting is correct for opening longs + /// @dev Fuzz Test to ensure deposit accounting is correct when opening longs /// with the base token. This test case is expected to fail if base deposits /// is not supported. /// @param basePaid Amount in terms of base to open a long. @@ -610,32 +621,37 @@ abstract contract InstanceTest is HyperdriveTest { extraData: new bytes(0) }) ); - if (config.enableBaseDeposits) { - // Ensure that Bob received the correct amount of bonds. - assertEq( - hyperdrive.balanceOf( - AssetId.encodeAssetId( - AssetId.AssetIdPrefix.Long, - maturityTime - ), - bob - ), - bondAmount - ); - // If base deposits are supported we ensure the deposit accounting is correct. - verifyDeposit( - bob, - basePaid, - true, - totalBaseSupplyBefore, - totalSharesSupplyBefore, - bobBalancesBefore, - hyperdriveBalanceBefore - ); + // Early termination if base deposits are not supported. + if (!config.enableBaseDeposits) { + return; } + + // Ensure that Bob received the correct amount of bonds. + assertEq( + hyperdrive.balanceOf( + AssetId.encodeAssetId(AssetId.AssetIdPrefix.Long, maturityTime), + bob + ), + bondAmount + ); + + // If base deposits are supported we ensure the deposit accounting is correct. + verifyDeposit( + bob, + basePaid, + true, + totalBaseSupplyBefore, + totalSharesSupplyBefore, + bobBalancesBefore, + hyperdriveBalanceBefore + ); } + /// @dev Fuzz Test to ensure deposit accounting is correct when opening shorts + /// with the share token. This test case is expected to fail if base deposits + /// is not supported. + /// @param shortAmount Amount of bonds to short. function test_open_short_with_shares(uint256 shortAmount) external { // Get some balance information before the deposit. ( @@ -647,14 +663,36 @@ abstract contract InstanceTest is HyperdriveTest { address(hyperdrive) ); - // Bob opens a short by depositing LsETH. - vm.startPrank(bob); shortAmount = shortAmount.normalizeToRange( 100 * hyperdrive.getPoolConfig().minimumTransactionAmount, HyperdriveUtils.calculateMaxShort(hyperdrive) ); - // RIVER.approve(address(hyperdrive), shortAmount); - (, uint256 sharesPaid) = openShort(bob, shortAmount, false); + + // Bob opens a short by depositing shares. + // We expect the openShort to fail with an UnsupportedToken error + // if depositing with shares is not supported. + + vm.startPrank(bob); + if (!config.enableShareDeposits) { + vm.expectRevert(IHyperdrive.UnsupportedToken.selector); + } + (uint256 maturityTime, uint256 sharesPaid) = hyperdrive.openShort( + shortAmount, + shortAmount, + 0, + IHyperdrive.Options({ + destination: bob, + asBase: false, + extraData: new bytes(0) + }) + ); + + // Early termination if base deposits are not supported. + if (!config.enableShareDeposits) { + return; + } + + // Convert shares paid when opening short to base for deposit accounting. uint256 basePaid = convertToBase(sharesPaid); // Ensure that the amount of base paid by the short is reasonable. @@ -669,8 +707,7 @@ abstract contract InstanceTest is HyperdriveTest { FIXED_RATE.mulDown(config.positionDuration.divDown(365 days)) ); - // Ensure that River aggregates and the token balances were updated - // correctly during the trade. + // Ensure the deposit accounting is correct. verifyDeposit( bob, basePaid, @@ -682,6 +719,80 @@ abstract contract InstanceTest is HyperdriveTest { ); } + /// @dev Fuzz Test to ensure deposit accounting is correct when opening shorts + /// with the share token. This test case is expected to fail if base deposits + /// is not supported. + /// @param shortAmount Amount of bonds to short. + function test_open_short_with_base(uint256 shortAmount) external { + // Get some balance information before the deposit. + ( + uint256 totalBaseSupplyBefore, + uint256 totalSharesSupplyBefore + ) = getSupply(); + AccountBalances memory bobBalancesBefore = getAccountBalances(bob); + AccountBalances memory hyperdriveBalancesBefore = getAccountBalances( + address(hyperdrive) + ); + + // Bob opens a short by depositing base. + vm.startPrank(bob); + shortAmount = shortAmount.normalizeToRange( + 100 * hyperdrive.getPoolConfig().minimumTransactionAmount, + HyperdriveUtils.calculateMaxShort(hyperdrive) + ); + + // We expect the openShort to fail with an UnsupportedToken error + // if depositing with base is not supported or a NotPayable error + // if the base token is ETH. + if (!config.enableBaseDeposits) { + vm.expectRevert( + isBaseETH + ? IHyperdrive.NotPayable.selector + : IHyperdrive.UnsupportedToken.selector + ); + } + (uint256 maturityTime, uint256 basePaid) = hyperdrive.openShort{ + value: isBaseETH ? shortAmount : 0 + }( + shortAmount, + shortAmount, + 0, + IHyperdrive.Options({ + destination: bob, + asBase: true, + extraData: new bytes(0) + }) + ); + + // Early termination if base deposits are not supported. + if (!config.enableBaseDeposits) { + return; + } + + // Ensure that the amount of base paid by the short is reasonable. + uint256 realizedRate = HyperdriveUtils.calculateAPRFromRealizedPrice( + shortAmount - basePaid, + shortAmount, + 1e18 + ); + assertGt(basePaid, 0); + assertGe( + realizedRate, + FIXED_RATE.mulDown(config.positionDuration.divDown(365 days)) + ); + + // Ensure the deposit accounting is correct. + verifyDeposit( + bob, + basePaid, + true, + totalBaseSupplyBefore, + totalSharesSupplyBefore, + bobBalancesBefore, + hyperdriveBalancesBefore + ); + } + /// Utilities /// struct AccountBalances { From bd15fea31485ca162b402eebf7c8a90cc5c69587 Mon Sep 17 00:00:00 2001 From: Cash Baller Date: Thu, 28 Mar 2024 15:02:36 -0500 Subject: [PATCH 18/21] better comments for open short cases --- test/utils/InstanceTest.sol | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/test/utils/InstanceTest.sol b/test/utils/InstanceTest.sol index ee49dcf8c..23b1fdbc3 100644 --- a/test/utils/InstanceTest.sol +++ b/test/utils/InstanceTest.sol @@ -537,7 +537,7 @@ abstract contract InstanceTest is HyperdriveTest { uint256 sharesPaid = convertToShares(basePaid); // Bob opens a long by depositing the base token. - // We expect the openShort to fail with an UnsupportedToken error + // We expect openLong to fail with an UnsupportedToken error // if depositing with shares is not supported. vm.startPrank(bob); if (!config.enableShareDeposits) { @@ -554,6 +554,11 @@ abstract contract InstanceTest is HyperdriveTest { }) ); + // Early termination if share deposits is not supported. + if (!config.enableShareDeposits) { + return; + } + // Ensure that Bob received the correct amount of bonds. assertEq( hyperdrive.balanceOf( @@ -596,9 +601,11 @@ abstract contract InstanceTest is HyperdriveTest { HyperdriveUtils.calculateMaxLong(hyperdrive) ); - // We expect the openLong to fail with an UnsupportedToken error + // Bob opens a long by depositing the base token. + // We expect openLong to fail with an UnsupportedToken error // if depositing with base is not supported or a NotPayable error // if the base token is ETH. + vm.startPrank(bob); if (!config.enableBaseDeposits) { vm.expectRevert( isBaseETH @@ -606,9 +613,6 @@ abstract contract InstanceTest is HyperdriveTest { : IHyperdrive.UnsupportedToken.selector ); } - - // Bob opens a long by depositing the base token. - vm.startPrank(bob); (uint256 maturityTime, uint256 bondAmount) = hyperdrive.openLong{ value: isBaseETH ? basePaid : 0 }( @@ -653,7 +657,7 @@ abstract contract InstanceTest is HyperdriveTest { /// is not supported. /// @param shortAmount Amount of bonds to short. function test_open_short_with_shares(uint256 shortAmount) external { - // Get some balance information before the deposit. + // Get some balance information before opening a short. ( uint256 totalBaseSupplyBefore, uint256 totalSharesSupplyBefore @@ -663,6 +667,7 @@ abstract contract InstanceTest is HyperdriveTest { address(hyperdrive) ); + // We normalize the short amount within a valid range the market can support. shortAmount = shortAmount.normalizeToRange( 100 * hyperdrive.getPoolConfig().minimumTransactionAmount, HyperdriveUtils.calculateMaxShort(hyperdrive) @@ -671,7 +676,6 @@ abstract contract InstanceTest is HyperdriveTest { // Bob opens a short by depositing shares. // We expect the openShort to fail with an UnsupportedToken error // if depositing with shares is not supported. - vm.startPrank(bob); if (!config.enableShareDeposits) { vm.expectRevert(IHyperdrive.UnsupportedToken.selector); @@ -687,7 +691,7 @@ abstract contract InstanceTest is HyperdriveTest { }) ); - // Early termination if base deposits are not supported. + // Early termination if base deposits is not supported. if (!config.enableShareDeposits) { return; } @@ -724,7 +728,7 @@ abstract contract InstanceTest is HyperdriveTest { /// is not supported. /// @param shortAmount Amount of bonds to short. function test_open_short_with_base(uint256 shortAmount) external { - // Get some balance information before the deposit. + // Get some balance information before opening a short. ( uint256 totalBaseSupplyBefore, uint256 totalSharesSupplyBefore @@ -734,16 +738,17 @@ abstract contract InstanceTest is HyperdriveTest { address(hyperdrive) ); - // Bob opens a short by depositing base. - vm.startPrank(bob); + // We normalize the short amount within a valid range the market can support. shortAmount = shortAmount.normalizeToRange( 100 * hyperdrive.getPoolConfig().minimumTransactionAmount, HyperdriveUtils.calculateMaxShort(hyperdrive) ); + // Bob opens a short by depositing base. // We expect the openShort to fail with an UnsupportedToken error // if depositing with base is not supported or a NotPayable error // if the base token is ETH. + vm.startPrank(bob); if (!config.enableBaseDeposits) { vm.expectRevert( isBaseETH @@ -764,7 +769,7 @@ abstract contract InstanceTest is HyperdriveTest { }) ); - // Early termination if base deposits are not supported. + // Early termination if base deposits is not supported. if (!config.enableBaseDeposits) { return; } From d041bddbfac5c7ee4baa772f24db6bc3e9ae0f21 Mon Sep 17 00:00:00 2001 From: Cash Baller Date: Thu, 28 Mar 2024 15:07:47 -0500 Subject: [PATCH 19/21] Add checks for receiving correct amount of tokens --- test/utils/InstanceTest.sol | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/test/utils/InstanceTest.sol b/test/utils/InstanceTest.sol index 23b1fdbc3..cbf9e38cb 100644 --- a/test/utils/InstanceTest.sol +++ b/test/utils/InstanceTest.sol @@ -696,6 +696,18 @@ abstract contract InstanceTest is HyperdriveTest { return; } + // Ensure that Bob received the correct amount of shorted bonds. + assertEq( + hyperdrive.balanceOf( + AssetId.encodeAssetId( + AssetId.AssetIdPrefix.Short, + maturityTime + ), + bob + ), + shortAmount + ); + // Convert shares paid when opening short to base for deposit accounting. uint256 basePaid = convertToBase(sharesPaid); @@ -774,6 +786,18 @@ abstract contract InstanceTest is HyperdriveTest { return; } + // Ensure that Bob received the correct amount of shorted bonds. + assertEq( + hyperdrive.balanceOf( + AssetId.encodeAssetId( + AssetId.AssetIdPrefix.Short, + maturityTime + ), + bob + ), + shortAmount + ); + // Ensure that the amount of base paid by the short is reasonable. uint256 realizedRate = HyperdriveUtils.calculateAPRFromRealizedPrice( shortAmount - basePaid, From 985dc299205fad6d9c0d10f7682c6c7ddaa90e77 Mon Sep 17 00:00:00 2001 From: Cash Baller Date: Thu, 28 Mar 2024 15:10:26 -0500 Subject: [PATCH 20/21] Update InstanceTest.sol --- test/utils/InstanceTest.sol | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/utils/InstanceTest.sol b/test/utils/InstanceTest.sol index cbf9e38cb..5a2386835 100644 --- a/test/utils/InstanceTest.sol +++ b/test/utils/InstanceTest.sol @@ -316,7 +316,7 @@ abstract contract InstanceTest is HyperdriveTest { /// @dev A virtual function that converts an amount in terms of the base token /// to equivalent amount in shares. - /// @param baseAmount Amount in terms of the base. + /// @param baseAmount Amount in terms of base. /// @return shareAmount Amount in terms of shares. function convertToShares( uint256 baseAmount @@ -324,8 +324,8 @@ abstract contract InstanceTest is HyperdriveTest { /// @dev A virtual function that converts an amount in terms of the share token /// to equivalent amount in base. - /// @param shareAmount Amount in terms of the shares. - /// @return baseAmount in terms of base. + /// @param shareAmount Amount in terms of shares. + /// @return baseAmount Amount in terms of base. function convertToBase( uint256 shareAmount ) internal view virtual returns (uint256 baseAmount); From 777a085165b48ac03d721aa478c2f61fefe74888 Mon Sep 17 00:00:00 2001 From: Cash Baller Date: Thu, 28 Mar 2024 21:40:42 -0500 Subject: [PATCH 21/21] Address comments --- test/instances/ezETH/EzETHHyperdrive.t.sol | 3 ++- test/instances/lseth/LsETHHyperdrive.t.sol | 2 +- test/instances/reth/RETHHyperdrive.t.sol | 2 +- test/instances/steth/StETHHyperdrive.t.sol | 2 +- test/utils/InstanceTest.sol | 14 +++++--------- 5 files changed, 10 insertions(+), 13 deletions(-) diff --git a/test/instances/ezETH/EzETHHyperdrive.t.sol b/test/instances/ezETH/EzETHHyperdrive.t.sol index e5f4a2d6a..a0c1487e6 100644 --- a/test/instances/ezETH/EzETHHyperdrive.t.sol +++ b/test/instances/ezETH/EzETHHyperdrive.t.sol @@ -136,7 +136,8 @@ contract EzETHHyperdriveTest is InstanceTest { function getTokenBalances( address account ) internal view override returns (uint256, uint256) { - return (EZETH.balanceOf(account), 0); + // EzETH does not have a convenient function for fetching base balance. + return (0, EZETH.balanceOf(account)); } /// @dev Fetches the total supply of the base and share tokens. diff --git a/test/instances/lseth/LsETHHyperdrive.t.sol b/test/instances/lseth/LsETHHyperdrive.t.sol index df15f2ce8..69f48e577 100644 --- a/test/instances/lseth/LsETHHyperdrive.t.sol +++ b/test/instances/lseth/LsETHHyperdrive.t.sol @@ -107,7 +107,7 @@ contract LsETHHyperdriveTest is InstanceTest { function getTokenBalances( address account ) internal view override returns (uint256, uint256) { - return (RIVER.balanceOf(account), RIVER.balanceOfUnderlying(account)); + return (RIVER.balanceOfUnderlying(account), RIVER.balanceOf(account)); } /// @dev Fetches the total supply of the base and share tokens. diff --git a/test/instances/reth/RETHHyperdrive.t.sol b/test/instances/reth/RETHHyperdrive.t.sol index 061cb6e7e..01ece42b0 100644 --- a/test/instances/reth/RETHHyperdrive.t.sol +++ b/test/instances/reth/RETHHyperdrive.t.sol @@ -122,7 +122,7 @@ contract RETHHyperdriveTest is InstanceTest { address account ) internal view override returns (uint256, uint256) { uint256 rethBalance = rocketTokenRETH.balanceOf(account); - return (rethBalance, rocketTokenRETH.getEthValue(rethBalance)); + return (rocketTokenRETH.getEthValue(rethBalance), rethBalance); } /// @dev Verifies that deposit accounting is correct when opening positions. diff --git a/test/instances/steth/StETHHyperdrive.t.sol b/test/instances/steth/StETHHyperdrive.t.sol index 128921920..10439488a 100644 --- a/test/instances/steth/StETHHyperdrive.t.sol +++ b/test/instances/steth/StETHHyperdrive.t.sol @@ -108,7 +108,7 @@ contract StETHHyperdriveTest is InstanceTest { function getTokenBalances( address account ) internal view override returns (uint256, uint256) { - return (LIDO.sharesOf(account), LIDO.balanceOf(account)); + return (LIDO.balanceOf(account), LIDO.sharesOf(account)); } /// @dev Verifies that deposit accounting is correct when opening positions. diff --git a/test/utils/InstanceTest.sol b/test/utils/InstanceTest.sol index 5a2386835..855190ce6 100644 --- a/test/utils/InstanceTest.sol +++ b/test/utils/InstanceTest.sol @@ -351,15 +351,11 @@ abstract contract InstanceTest is HyperdriveTest { /// @dev A virtual function that fetches the token balance information of an account. /// @param account The account to fetch token balances of. - /// @return sharesBalance The shares token balance of the account. - /// @return baseBalance The base token balance of the account. + /// @return baseBalance The shares token balance of the account. + /// @return shareBalance The base token balance of the account. function getTokenBalances( address account - ) - internal - view - virtual - returns (uint256 sharesBalance, uint256 baseBalance); + ) internal view virtual returns (uint256 baseBalance, uint256 shareBalance); /// @dev A virtual function that fetches the total supply of the base and share tokens. /// @return totalSupplyBase The total supply of the base token. @@ -640,7 +636,7 @@ abstract contract InstanceTest is HyperdriveTest { bondAmount ); - // If base deposits are supported we ensure the deposit accounting is correct. + // Ensure the deposit accounting is correct. verifyDeposit( bob, basePaid, @@ -833,7 +829,7 @@ abstract contract InstanceTest is HyperdriveTest { function getAccountBalances( address account ) internal view returns (AccountBalances memory) { - (uint256 shares, uint256 base) = getTokenBalances(account); + (uint256 base, uint256 shares) = getTokenBalances(account); return AccountBalances({