Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds mint and burn functions #1220

Merged
merged 34 commits into from
Jan 23, 2025
Merged
Show file tree
Hide file tree
Changes from 24 commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
66edc7f
Adds an `openPair` function
jalextowle Nov 20, 2024
2614a15
Removes some outdated comments
jalextowle Nov 20, 2024
8a557f6
Added governance fees to the mint function
jalextowle Nov 23, 2024
4f75460
Updated the implementation of `HyperdrivePair`
jalextowle Nov 26, 2024
c96d744
Updated the `mint` logic and wired it up
jalextowle Nov 26, 2024
be28b36
Added unit test cases for the `mint` function
jalextowle Nov 26, 2024
94a124a
Adds comprehensive unit tests for the mint function
jalextowle Nov 27, 2024
75bd986
Adds a `minOutput` parameter to `mint`
jalextowle Dec 4, 2024
7817f25
Wrote a comprehensive integration test suite for the `mint` function
jalextowle Dec 6, 2024
1daa62f
Started implementing `burn`
jalextowle Jan 2, 2025
f3c1627
Made some targeted fixes to `mint`
jalextowle Jan 2, 2025
886ad43
Added zombie interest to the `burn` flow and cleaned up `HyperdrivePair`
jalextowle Jan 3, 2025
e748cf9
Started adding a test suite for the `burn` function
jalextowle Jan 4, 2025
788ea8b
Added the remaining test cases. Some of them are broken.
jalextowle Jan 4, 2025
22a3871
Fixed the remaining `burn` unit tests
jalextowle Jan 6, 2025
39b5573
Added an integration test suite for `burn`
jalextowle Jan 7, 2025
9399732
Bumping solidity version of mint to match rest of repo (#1235)
slundqui Jan 9, 2025
dd155a8
Added tests for zombie interest for `mint` and `burn`
jalextowle Jan 10, 2025
e6bc826
Added more integration tests for `mint` and `burn`
jalextowle Jan 10, 2025
1203d12
Added a negative interest test for `mint`
jalextowle Jan 10, 2025
f96ea1f
Addressed review feedback from @Sean329
jalextowle Jan 10, 2025
0a5b6f2
Committed incremental progress
jalextowle Jan 10, 2025
92abb8e
Added more `mint` and `burn` related cases to the `InstanceTest` suite
jalextowle Jan 11, 2025
4c4a651
Fixed the failing `test_burn_with_base` tests
jalextowle Jan 16, 2025
a47ce3c
Added another instance test and got all of the tests working
jalextowle Jan 16, 2025
030af8e
Uncommented and fixed another test
jalextowle Jan 17, 2025
9883329
Uncommented the remaining test
jalextowle Jan 17, 2025
c2196c2
Fixed the code size issue
jalextowle Jan 18, 2025
a81ff87
Removed fixmes -- the investigation showed that the calculations work…
jalextowle Jan 18, 2025
5b85f8d
Fixed some of the CI jobs
jalextowle Jan 18, 2025
a554bc3
Fixed the LPWithdrawal tests
jalextowle Jan 21, 2025
552c1ab
Attempted to fix the code coverage job
jalextowle Jan 22, 2025
14591d7
Removed the code coverage badge
jalextowle Jan 22, 2025
fa22255
Fixed a rare issue in the fixed point math tests
jalextowle Jan 23, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions contracts/src/external/Hyperdrive.sol
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,28 @@ abstract contract Hyperdrive is
_delegate(target4);
}

/// Pairs ///

/// @inheritdoc IHyperdriveCore
function mint(
uint256,
uint256,
uint256,
IHyperdrive.PairOptions calldata
) external payable returns (uint256, uint256) {
_delegate(target4);
}

/// @inheritdoc IHyperdriveCore
function burn(
uint256,
uint256,
uint256,
IHyperdrive.Options calldata
) external returns (uint256) {
_delegate(target4);
}

/// Checkpoints ///

/// @inheritdoc IHyperdriveCore
Expand Down
2 changes: 2 additions & 0 deletions contracts/src/external/HyperdriveTarget0.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { HyperdriveCheckpoint } from "../internal/HyperdriveCheckpoint.sol";
import { HyperdriveLong } from "../internal/HyperdriveLong.sol";
import { HyperdriveLP } from "../internal/HyperdriveLP.sol";
import { HyperdriveMultiToken } from "../internal/HyperdriveMultiToken.sol";
import { HyperdrivePair } from "../internal/HyperdrivePair.sol";
import { HyperdriveShort } from "../internal/HyperdriveShort.sol";
import { HyperdriveStorage } from "../internal/HyperdriveStorage.sol";
import { AssetId } from "../libraries/AssetId.sol";
Expand All @@ -30,6 +31,7 @@ abstract contract HyperdriveTarget0 is
HyperdriveLP,
HyperdriveLong,
HyperdriveShort,
HyperdrivePair,
HyperdriveCheckpoint
{
using FixedPointMath for uint256;
Expand Down
2 changes: 2 additions & 0 deletions contracts/src/external/HyperdriveTarget1.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { HyperdriveCheckpoint } from "../internal/HyperdriveCheckpoint.sol";
import { HyperdriveLong } from "../internal/HyperdriveLong.sol";
import { HyperdriveLP } from "../internal/HyperdriveLP.sol";
import { HyperdriveMultiToken } from "../internal/HyperdriveMultiToken.sol";
import { HyperdrivePair } from "../internal/HyperdrivePair.sol";
import { HyperdriveShort } from "../internal/HyperdriveShort.sol";
import { HyperdriveStorage } from "../internal/HyperdriveStorage.sol";

Expand All @@ -23,6 +24,7 @@ abstract contract HyperdriveTarget1 is
HyperdriveLP,
HyperdriveLong,
HyperdriveShort,
HyperdrivePair,
HyperdriveCheckpoint
{
/// @notice Instantiates target1.
Expand Down
2 changes: 2 additions & 0 deletions contracts/src/external/HyperdriveTarget2.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { HyperdriveCheckpoint } from "../internal/HyperdriveCheckpoint.sol";
import { HyperdriveLong } from "../internal/HyperdriveLong.sol";
import { HyperdriveLP } from "../internal/HyperdriveLP.sol";
import { HyperdriveMultiToken } from "../internal/HyperdriveMultiToken.sol";
import { HyperdrivePair } from "../internal/HyperdrivePair.sol";
import { HyperdriveShort } from "../internal/HyperdriveShort.sol";
import { HyperdriveStorage } from "../internal/HyperdriveStorage.sol";

Expand All @@ -23,6 +24,7 @@ abstract contract HyperdriveTarget2 is
HyperdriveLP,
HyperdriveLong,
HyperdriveShort,
HyperdrivePair,
HyperdriveCheckpoint
{
/// @notice Instantiates target2.
Expand Down
2 changes: 2 additions & 0 deletions contracts/src/external/HyperdriveTarget3.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { HyperdriveCheckpoint } from "../internal/HyperdriveCheckpoint.sol";
import { HyperdriveLong } from "../internal/HyperdriveLong.sol";
import { HyperdriveLP } from "../internal/HyperdriveLP.sol";
import { HyperdriveMultiToken } from "../internal/HyperdriveMultiToken.sol";
import { HyperdrivePair } from "../internal/HyperdrivePair.sol";
import { HyperdriveShort } from "../internal/HyperdriveShort.sol";
import { HyperdriveStorage } from "../internal/HyperdriveStorage.sol";

Expand All @@ -23,6 +24,7 @@ abstract contract HyperdriveTarget3 is
HyperdriveLP,
HyperdriveLong,
HyperdriveShort,
HyperdrivePair,
HyperdriveCheckpoint
{
/// @notice Instantiates target3.
Expand Down
51 changes: 51 additions & 0 deletions contracts/src/external/HyperdriveTarget4.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { HyperdriveCheckpoint } from "../internal/HyperdriveCheckpoint.sol";
import { HyperdriveLong } from "../internal/HyperdriveLong.sol";
import { HyperdriveLP } from "../internal/HyperdriveLP.sol";
import { HyperdriveMultiToken } from "../internal/HyperdriveMultiToken.sol";
import { HyperdrivePair } from "../internal/HyperdrivePair.sol";
import { HyperdriveShort } from "../internal/HyperdriveShort.sol";
import { HyperdriveStorage } from "../internal/HyperdriveStorage.sol";

Expand All @@ -23,6 +24,7 @@ abstract contract HyperdriveTarget4 is
HyperdriveLP,
HyperdriveLong,
HyperdriveShort,
HyperdrivePair,
HyperdriveCheckpoint
{
/// @notice Instantiates target4.
Expand Down Expand Up @@ -86,6 +88,55 @@ abstract contract HyperdriveTarget4 is
);
}

/// Pairs ///

// FIXME: Where does this fit?
jalextowle marked this conversation as resolved.
Show resolved Hide resolved
//
/// @notice Mints a pair of long and short positions that directly match
/// each other. The amount of long and short positions that are
/// created is equal to the base value of the deposit. These
/// positions are sent to the provided destinations.
/// @param _amount The amount of capital provided to open the long. The
/// units of this quantity are either base or vault shares, depending
/// on the value of `_options.asBase`.
/// @param _minOutput The minimum number of bonds to receive.
/// @param _minVaultSharePrice The minimum vault share price at which to
/// mint the bonds. This allows traders to protect themselves from
/// opening a long in a checkpoint where negative interest has
/// accrued.
/// @param _options The pair options that configure how the trade is settled.
/// @return maturityTime The maturity time of the new long and short positions.
/// @return bondAmount The bond amount of the new long and short positoins.
function mint(
uint256 _amount,
uint256 _minOutput,
uint256 _minVaultSharePrice,
IHyperdrive.PairOptions calldata _options
) external payable returns (uint256 maturityTime, uint256 bondAmount) {
return _mint(_amount, _minOutput, _minVaultSharePrice, _options);
}

// FIXME: Where does this fit?
jalextowle marked this conversation as resolved.
Show resolved Hide resolved
//
/// @dev Burns a pair of long and short positions that directly match each
/// other. The capital underlying these positions is released to the
/// trader burning the positions.
/// @param _maturityTime The maturity time of the long and short positions.
/// @param _bondAmount The amount of longs and shorts to close.
/// @param _minOutput The minimum amount of proceeds to receive.
/// @param _options The options that configure how the trade is settled.
/// @return proceeds The proceeds the user receives. The units of this
/// quantity are either base or vault shares, depending on the value
/// of `_options.asBase`.
function burn(
uint256 _maturityTime,
uint256 _bondAmount,
uint256 _minOutput,
IHyperdrive.Options calldata _options
) external returns (uint256 proceeds) {
return _burn(_maturityTime, _bondAmount, _minOutput, _options);
}

/// Checkpoints ///

/// @notice Allows anyone to mint a new checkpoint.
Expand Down
15 changes: 15 additions & 0 deletions contracts/src/interfaces/IHyperdrive.sol
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,21 @@ interface IHyperdrive is
bytes extraData;
}

struct PairOptions {
/// @dev The address that receives the long proceeds from a pair action.
address longDestination;
/// @dev The address that receives the short proceeds from a pair action.
address shortDestination;
/// @dev A boolean indicating that the trade or LP action should be
/// settled in base if true and in the yield source shares if false.
bool asBase;
/// @dev Additional data that can be used to implement custom logic in
/// implementation contracts. By convention, the last 32 bytes of
/// extra data are ignored by instances and "passed through" to the
/// event. This can be used to pass metadata through transactions.
bytes extraData;
}

/// Errors ///

/// @notice Thrown when the inputs to a batch transfer don't match in
Expand Down
41 changes: 41 additions & 0 deletions contracts/src/interfaces/IHyperdriveCore.sol
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,47 @@ interface IHyperdriveCore is IMultiTokenCore {
IHyperdrive.Options calldata _options
) external returns (uint256 proceeds, uint256 withdrawalSharesRedeemed);

/// Pairs ///

/// @notice Mints a pair of long and short positions that directly match
/// each other. The amount of long and short positions that are
/// created is equal to the base value of the deposit. These
/// positions are sent to the provided destinations.
/// @param _amount The amount of capital provided to open the long. The
/// units of this quantity are either base or vault shares, depending
/// on the value of `_options.asBase`.
/// @param _minOutput The minimum number of bonds to receive.
/// @param _minVaultSharePrice The minimum vault share price at which to
/// mint the bonds. This allows traders to protect themselves from
/// opening a long in a checkpoint where negative interest has
/// accrued.
/// @param _options The pair options that configure how the trade is settled.
/// @return maturityTime The maturity time of the new long and short positions.
/// @return bondAmount The bond amount of the new long and short positoins.
function mint(
uint256 _amount,
uint256 _minOutput,
uint256 _minVaultSharePrice,
IHyperdrive.PairOptions calldata _options
) external payable returns (uint256 maturityTime, uint256 bondAmount);

/// @dev Burns a pair of long and short positions that directly match each
/// other. The capital underlying these positions is released to the
/// trader burning the positions.
/// @param _maturityTime The maturity time of the long and short positions.
/// @param _bondAmount The amount of longs and shorts to close.
/// @param _minOutput The minimum amount of proceeds to receive.
/// @param _options The options that configure how the trade is settled.
/// @return proceeds The proceeds the user receives. The units of this
/// quantity are either base or vault shares, depending on the value
/// of `_options.asBase`.
function burn(
uint256 _maturityTime,
uint256 _bondAmount,
uint256 _minOutput,
IHyperdrive.Options calldata _options
) external returns (uint256 proceeds);

/// Checkpoints ///

/// @notice Attempts to mint a checkpoint with the specified checkpoint time.
Expand Down
28 changes: 28 additions & 0 deletions contracts/src/interfaces/IHyperdriveEvents.sol
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,34 @@ interface IHyperdriveEvents is IMultiTokenEvents {
bytes extraData
);

/// @notice Emitted when a pair of long and short positions are minted.
event Mint(
address indexed longTrader,
address indexed shortTrader,
uint256 indexed maturityTime,
uint256 longAssetId,
uint256 shortAssetId,
uint256 amount,
uint256 vaultSharePrice,
bool asBase,
uint256 bondAmount,
bytes extraData
);

/// @notice Emitted when a pair of long and short positions are burned.
event Burn(
address indexed trader,
address indexed destination,
uint256 indexed maturityTime,
uint256 longAssetId,
uint256 shortAssetId,
uint256 amount,
uint256 vaultSharePrice,
bool asBase,
uint256 bondAmount,
bytes extraData
);

/// @notice Emitted when a checkpoint is created.
event CreateCheckpoint(
uint256 indexed checkpointTime,
Expand Down
42 changes: 30 additions & 12 deletions contracts/src/internal/HyperdriveBase.sol
Original file line number Diff line number Diff line change
Expand Up @@ -29,16 +29,20 @@ abstract contract HyperdriveBase is IHyperdriveEvents, HyperdriveStorage {
/// @dev Process a deposit in either base or vault shares.
/// @param _amount The amount of capital to deposit. The units of this
/// quantity are either base or vault shares, depending on the value
/// of `_options.asBase`.
/// @param _options The options that configure how the deposit is
/// settled. In particular, the currency used in the deposit is
/// specified here. Aside from those options, yield sources can
/// choose to implement additional options.
/// of `_asBase`.
/// @param _asBase A flag indicating if the deposit should be made in base
/// or in vault shares.
/// @param _extraData Additional data that can be used to implement custom
/// logic in implementation contracts. By convention, the last 32
/// bytes of extra data are ignored by instances and "passed through"
/// to the event. This can be used to pass metadata through
/// transactions.
/// @return sharesMinted The shares created by this deposit.
/// @return vaultSharePrice The vault share price.
function _deposit(
uint256 _amount,
IHyperdrive.Options calldata _options
bool _asBase,
bytes calldata _extraData
) internal returns (uint256 sharesMinted, uint256 vaultSharePrice) {
// WARN: This logic doesn't account for slippage in the conversion
// from base to shares. If deposits to the yield source incur
Expand All @@ -50,19 +54,16 @@ abstract contract HyperdriveBase is IHyperdriveEvents, HyperdriveStorage {

// Deposit with either base or shares depending on the provided options.
uint256 refund;
if (_options.asBase) {
if (_asBase) {
// Process the deposit in base.
(sharesMinted, refund) = _depositWithBase(
_amount,
_options.extraData
);
(sharesMinted, refund) = _depositWithBase(_amount, _extraData);
} else {
// The refund is equal to the full message value since ETH will
// never be a shares asset.
refund = msg.value;

// Process the deposit in shares.
_depositWithShares(_amount, _options.extraData);
_depositWithShares(_amount, _extraData);
}

// Calculate the vault share price.
Expand Down Expand Up @@ -198,6 +199,23 @@ abstract contract HyperdriveBase is IHyperdriveEvents, HyperdriveStorage {
}
}

/// @dev A yield source dependent check that verifies that the provided
/// pair options are valid. The default check is that the destinations
/// are non-zero to prevent users from accidentally transferring funds
/// to the zero address. Custom integrations can override this to
/// implement additional checks.
/// @param _options The provided options for the transaction.
function _checkPairOptions(
IHyperdrive.PairOptions calldata _options
) internal pure virtual {
if (
_options.longDestination == address(0) ||
_options.shortDestination == address(0)
) {
revert IHyperdrive.RestrictedZeroAddress();
}
}

/// @dev Convert an amount of vault shares to an amount of base.
/// @param _shareAmount The vault shares amount.
/// @return baseAmount The base amount.
Expand Down
6 changes: 4 additions & 2 deletions contracts/src/internal/HyperdriveLP.sol
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,8 @@ abstract contract HyperdriveLP is
// their contribution was worth.
(uint256 shareContribution, uint256 vaultSharePrice) = _deposit(
_contribution,
_options
_options.asBase,
_options.extraData
);

// Ensure that the contribution is large enough to set aside the minimum
Expand Down Expand Up @@ -210,7 +211,8 @@ abstract contract HyperdriveLP is
// Deposit for the user, this call also transfers from them
(uint256 shareContribution, uint256 vaultSharePrice) = _deposit(
_contribution,
_options
_options.asBase,
_options.extraData
);

// Perform a checkpoint.
Expand Down
3 changes: 2 additions & 1 deletion contracts/src/internal/HyperdriveLong.sol
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,8 @@ abstract contract HyperdriveLong is IHyperdriveEvents, HyperdriveLP {
// Deposit the user's input amount.
(uint256 sharesDeposited, uint256 vaultSharePrice) = _deposit(
_amount,
_options
_options.asBase,
_options.extraData
);

// Enforce the minimum user outputs and the minimum vault share price.
Expand Down
Loading
Loading