Closed dpaiton closed 10 months ago
Relevant crash report after v0.4.0 update: fuzz_long_short_maturity_values2024_01_10_20_11_05_Z.json
I created this test to try to repro:
function test_foo(
) external {
uint256 fixedRate = 0.05e18;
uint256 initialLiquidity = 100_000_000e18;
uint256 zombieShareReserves1;
uint256 shareReserves1;
{
// Initialize the pool with capital.
deploy(bob, fixedRate, 1e18, 0, 0, 0, 0);
initialize(bob, fixedRate, 2 * MINIMUM_SHARE_RESERVES);
// Alice adds liquidity.
addLiquidity(alice, initialLiquidity);
// Limit the fuzz testing to variableRate's less than or equal to 200%.
int256 variableRate = 0.05e18;
// Ensure a feasible trade size.
uint256 longTradeSize = 20_000e18;
// Celine opens a long.
(uint256 maturityTime, uint256 bonds) = openLong(celine, longTradeSize);
// One term passes and longs mature.
advanceTime(POSITION_DURATION, variableRate);
hyperdrive.checkpoint(HyperdriveUtils.latestCheckpoint(hyperdrive));
closeLong(celine, maturityTime, bonds);
}
}
results are:
baseProceeds 19999.999999999999999999
sharePrice 1.051271096376024039
bondAmount 20000.000000000000000000
shareProceeds x sharePrice-flat fee 19999.999999999999999999
i would expect baseProceeds = bondAmount, but we are off by 1 wei.
To reproduce the config above:
100 milly in liquidity, 5% variable, 5% fixed, zero fees 1) open a long with 20k base 2) exactly one term passes 3) close long
I wrote the following test to try to reproduce the issues with the ERC4626Hyperdrive
deployment. This may be helpful for the continued investigation, so I figured I'd post it here:
// SPDX-License-Identifier: Apache-2.0
pragma solidity 0.8.19;
// FIXME
import { console2 as console } from "forge-std/console2.sol";
import { Lib } from "test/utils/Lib.sol";
import { ERC4626Hyperdrive } from "contracts/src/instances/erc4626/ERC4626Hyperdrive.sol";
import { ERC4626Target0 } from "contracts/src/instances/erc4626/ERC4626Target0.sol";
import { ERC4626Target1 } from "contracts/src/instances/erc4626/ERC4626Target1.sol";
import { ERC4626Target2 } from "contracts/src/instances/erc4626/ERC4626Target2.sol";
import { ERC4626Target3 } from "contracts/src/instances/erc4626/ERC4626Target3.sol";
import { IERC4626 } from "contracts/src/interfaces/IERC4626.sol";
import { IHyperdrive } from "contracts/src/interfaces/IHyperdrive.sol";
import { FixedPointMath } from "contracts/src/libraries/FixedPointMath.sol";
import { ERC20Mintable } from "contracts/test/ERC20Mintable.sol";
import { MockERC4626 } from "contracts/test/MockERC4626.sol";
import { HyperdriveTest } from "test/utils/HyperdriveTest.sol";
import { HyperdriveUtils } from "test/utils/HyperdriveUtils.sol";
contract ExampleTest is HyperdriveTest {
using FixedPointMath for uint256;
using HyperdriveUtils for IHyperdrive;
using Lib for *;
function setUp() public override {
super.setUp();
// Deploy the base token and vault.
baseToken = new ERC20Mintable(
"Base Token",
"BASE",
18,
address(0),
false
);
IERC4626 vault = IERC4626(address(new MockERC4626(
baseToken,
"Vault Token",
"VAULT",
2e18,
address(0),
false
)));
// Deploy the hyperdrive instance.
IHyperdrive.PoolConfig memory config = testConfig(0.05e18, POSITION_DURATION);
hyperdrive = IHyperdrive(address(new ERC4626Hyperdrive(
config,
address(new ERC4626Target0(config, vault)),
address(new ERC4626Target1(config, vault)),
address(new ERC4626Target2(config, vault)),
address(new ERC4626Target3(config, vault)),
vault
)));
}
function test_example() external {
// Initialize the Hyperdrive pool.
initialize(alice, 0.05e18, 100_000_000e18);
// Alice opens a long.
console.log("test_example: 0");
(uint256 maturityTime, uint256 longAmount) = openLong(alice, 100_000e18);
console.log("test_example: 0.1");
// A small amount of time passes.
vm.warp(block.timestamp + POSITION_DURATION.mulDown(0.2e18));
hyperdrive.checkpoint(hyperdrive.latestCheckpoint());
console.log("test_example: 0.2");
// Alice opens a large short.
uint256 basePaid = hyperdrive.calculateMaxLong().mulDown(0.2e18);
(, uint256 bondAmount) = openLong(alice, basePaid);
openShort(alice, bondAmount);
openLong(alice, basePaid);
openShort(alice, bondAmount);
openLong(alice, basePaid);
openShort(alice, bondAmount);
openLong(alice, basePaid);
openShort(alice, bondAmount);
openLong(alice, hyperdrive.calculateMaxLong().mulDown(0.55e18));
openLong(alice, hyperdrive.calculateMaxShort().mulDown(0.1034e18));
// The term passes and interest accrues.
vm.warp(maturityTime);
// Alice closes her long.
uint256 baseProceeds = closeLong(alice, maturityTime, longAmount);
console.log("bondAmount = %s", longAmount.toString(18));
console.log("baseProceeds = %s", baseProceeds.toString(18));
console.log("difference = %s", (longAmount - baseProceeds).toString(18));
}
}
Okay, we can recreate the issue in Solidity with this test:
// SPDX-License-Identifier: Apache-2.0
pragma solidity 0.8.19;
// FIXME
import { console2 as console } from "forge-std/console2.sol";
import { Lib } from "test/utils/Lib.sol";
import { ERC4626Hyperdrive } from "contracts/src/instances/erc4626/ERC4626Hyperdrive.sol";
import { ERC4626Target0 } from "contracts/src/instances/erc4626/ERC4626Target0.sol";
import { ERC4626Target1 } from "contracts/src/instances/erc4626/ERC4626Target1.sol";
import { ERC4626Target2 } from "contracts/src/instances/erc4626/ERC4626Target2.sol";
import { ERC4626Target3 } from "contracts/src/instances/erc4626/ERC4626Target3.sol";
import { IERC4626 } from "contracts/src/interfaces/IERC4626.sol";
import { IHyperdrive } from "contracts/src/interfaces/IHyperdrive.sol";
import { ERC20Mintable } from "contracts/test/ERC20Mintable.sol";
import { MockERC4626 } from "contracts/test/MockERC4626.sol";
import { HyperdriveTest } from "test/utils/HyperdriveTest.sol";
import { HyperdriveUtils } from "test/utils/HyperdriveUtils.sol";
contract ExampleTest is HyperdriveTest {
using Lib for *;
function setUp() public override {
super.setUp();
// Deploy the base token and vault.
baseToken = new ERC20Mintable(
"Base Token",
"BASE",
18,
address(0),
false
);
IERC4626 vault = IERC4626(address(new MockERC4626(
baseToken,
"Vault Token",
"VAULT",
0.05e18,
address(0),
false
)));
// Deploy the hyperdrive instance.
IHyperdrive.PoolConfig memory config = testConfig(0.05e18, 7 days);
hyperdrive = IHyperdrive(address(new ERC4626Hyperdrive(
config,
address(new ERC4626Target0(config, vault)),
address(new ERC4626Target1(config, vault)),
address(new ERC4626Target2(config, vault)),
address(new ERC4626Target3(config, vault)),
vault
)));
}
function test_example() external {
// Initialize the Hyperdrive pool.
initialize(alice, 0.05e18, 100_000_000e18);
console.log("sharePrice = %s", hyperdrive.getPoolInfo().sharePrice.toString(18));
vm.warp(block.timestamp + 36 seconds);
//hyperdrive.checkpoint(HyperdriveUtils.latestCheckpoint(hyperdrive));
console.log("sharePrice = %s", hyperdrive.getPoolInfo().sharePrice.toString(18));
// Alice opens a long.
(uint256 maturityTime, uint256 longAmount) = openLong(alice, 20_000e18);
console.log("longAmount = %s", longAmount.toString(18));
// The term passes and interest accrues.
vm.warp(maturityTime);
// Alice closes her long.
uint256 baseProceeds = closeLong(alice, maturityTime, longAmount);
console.log("longAmount = %s", longAmount.toString(18));
console.log("baseProceeds = %s", baseProceeds.toString(18));
console.log("delta = %s", baseProceeds - longAmount);
}
}
Running 1 test for test/units/derp.t.sol:ExampleTest
[PASS] test_example() (gas: 699843)
Logs:
sharePrice = 1.000000000000000000
sharePrice = 1.000000057077625570
longAmount = 20019.175749563363684514
longAmount = 20019.175749563363684514
baseProceeds = 20019.175749563363701900
delta = 17386
Test result: ok. 1 passed; 0 failed; finished in 10.64ms
Crash Report
https://app.rollbar.com/a/delv/fix/item/FirstProject/38
Description
Test: fuzz_long_short_maturity_values.py
Expected Behavior
The trades should have matured from advancing time and an expected amount should have been returned.
expected value:
expected_base_amount_from_trade = open_trade_event.bond_amount - open_trade_event.bond_amount * flat_fee_percent
actual value:
actual_base_amount = close_trade_event.base_amount
Actual Behavior
The expected and actual returned amounts do not match.
Steps to Reproduce
Run the fuzz test
Screenshots or Error Messages
Logs or Stack Traces
fuzz_long_short_maturity_values2023_12_12_18_49_15_Z.json