Skip to content

Commit 036d7bd

Browse files
authored
Added events to all of the core Hyperdrive flows (#245)
* Added events to all of the Hyperdrive functions * Added tests for the events * Updated optimizer runs to address the code size issues
1 parent 69d4a19 commit 036d7bd

14 files changed

+547
-79
lines changed

contracts/src/HyperdriveBase.sol

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,60 @@ abstract contract HyperdriveBase is MultiToken, HyperdriveStorage {
2121
using FixedPointMath for uint256;
2222
using SafeCast for uint256;
2323

24+
event Initialize(
25+
address indexed provider,
26+
uint256 lpAmount,
27+
uint256 baseAmount,
28+
uint256 apr
29+
);
30+
31+
event AddLiquidity(
32+
address indexed provider,
33+
uint256 lpAmount,
34+
uint256 baseAmount
35+
);
36+
37+
event RemoveLiquidity(
38+
address indexed provider,
39+
uint256 lpAmount,
40+
uint256 baseAmount,
41+
uint256 withdrawalShareAmount
42+
);
43+
44+
event RedeemWithdrawalShares(
45+
address indexed provider,
46+
uint256 withdrawalShareAmount,
47+
uint256 baseAmount
48+
);
49+
50+
event OpenLong(
51+
address indexed trader,
52+
uint256 maturityTime,
53+
uint256 baseAmount,
54+
uint256 bondAmount
55+
);
56+
57+
event OpenShort(
58+
address indexed trader,
59+
uint256 maturityTime,
60+
uint256 baseAmount,
61+
uint256 bondAmount
62+
);
63+
64+
event CloseLong(
65+
address indexed trader,
66+
uint256 maturityTime,
67+
uint256 baseAmount,
68+
uint256 bondAmount
69+
);
70+
71+
event CloseShort(
72+
address indexed trader,
73+
uint256 maturityTime,
74+
uint256 baseAmount,
75+
uint256 bondAmount
76+
);
77+
2478
/// @notice Initializes a Hyperdrive pool.
2579
/// @param _config The configuration of the Hyperdrive pool.
2680
/// @param _dataProvider The address of the data provider.

contracts/src/HyperdriveLP.sol

Lines changed: 117 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,9 @@ abstract contract HyperdriveLP is HyperdriveTWAP {
6868

6969
// Mint LP shares to the initializer.
7070
_mint(AssetId._LP_ASSET_ID, _destination, initialLpShares);
71+
72+
// Emit an Initialize event.
73+
emit Initialize(_destination, initialLpShares, _contribution, _apr);
7174
}
7275

7376
/// @notice Allows LPs to supply liquidity for LP shares.
@@ -192,6 +195,9 @@ abstract contract HyperdriveLP is HyperdriveTWAP {
192195

193196
// Mint LP shares to the supplier.
194197
_mint(AssetId._LP_ASSET_ID, _destination, lpShares);
198+
199+
// Emit an AddLiquidity event.
200+
emit AddLiquidity(_destination, lpShares, _contribution);
195201
}
196202

197203
/// @notice Allows an LP to burn shares and withdraw from the pool.
@@ -221,85 +227,31 @@ abstract contract HyperdriveLP is HyperdriveTWAP {
221227
_applyCheckpoint(_latestCheckpoint(), sharePrice);
222228

223229
// Burn the LP shares.
224-
uint256 activeLpTotalSupply = _totalSupply[AssetId._LP_ASSET_ID];
230+
uint256 totalActiveLpSupply = _totalSupply[AssetId._LP_ASSET_ID];
225231
uint256 withdrawalSharesOutstanding = _totalSupply[
226232
AssetId._WITHDRAWAL_SHARE_ASSET_ID
227233
] - _withdrawPool.readyToWithdraw;
228-
uint256 lpTotalSupply = activeLpTotalSupply +
234+
uint256 totalLpSupply = totalActiveLpSupply +
229235
withdrawalSharesOutstanding;
230236
_burn(AssetId._LP_ASSET_ID, msg.sender, _shares);
231237

232-
// Calculate the starting present value of the pool.
233-
HyperdriveMath.PresentValueParams memory params = HyperdriveMath
234-
.PresentValueParams({
235-
shareReserves: _marketState.shareReserves,
236-
bondReserves: _marketState.bondReserves,
237-
sharePrice: sharePrice,
238-
initialSharePrice: _initialSharePrice,
239-
timeStretch: _timeStretch,
240-
longsOutstanding: _marketState.longsOutstanding,
241-
longAverageTimeRemaining: _calculateTimeRemaining(
242-
uint256(_marketState.longAverageMaturityTime).divUp(1e36) // scale to seconds
243-
),
244-
shortsOutstanding: _marketState.shortsOutstanding,
245-
shortAverageTimeRemaining: _calculateTimeRemaining(
246-
uint256(_marketState.shortAverageMaturityTime).divUp(1e36) // scale to seconds
247-
),
248-
shortBaseVolume: _marketState.shortBaseVolume
249-
});
250-
uint256 startingPresentValue = HyperdriveMath.calculatePresentValue(
251-
params
252-
);
253-
254-
// The LP is given their share of the idle capital in the pool. This
255-
// is removed from the pool's reserves and paid out immediately. We use
256-
// the average opening share price of longs to avoid double counting
257-
// the variable rate interest accrued on long positions. The idle amount
258-
// is given by:
259-
//
260-
// idle = (z - (o_l / c_0)) * (dl / l_a)
261-
uint256 shareProceeds = _marketState.shareReserves;
262-
if (_marketState.longsOutstanding > 0) {
263-
shareProceeds -= uint256(_marketState.longsOutstanding).divDown(
264-
_marketState.longOpenSharePrice
265-
);
266-
}
267-
shareProceeds = shareProceeds.mulDivDown(_shares, activeLpTotalSupply);
268-
_updateLiquidity(-int256(shareProceeds));
269-
params.shareReserves = _marketState.shareReserves;
270-
params.bondReserves = _marketState.bondReserves;
271-
uint256 endingPresentValue = HyperdriveMath.calculatePresentValue(
272-
params
273-
);
274-
275-
// Calculate the amount of withdrawal shares that should be minted. We
276-
// solve for this value by solving the present value equation as
277-
// follows:
278-
//
279-
// PV0 / l0 = PV1 / (l0 - dl + dw) => dw = (PV1 / PV0) * l0 - (l0 - dl)
280-
int256 withdrawalShares = int256(
281-
lpTotalSupply.mulDivDown(endingPresentValue, startingPresentValue)
282-
);
283-
withdrawalShares -= int256(lpTotalSupply) - int256(_shares);
284-
if (withdrawalShares < 0) {
285-
// We backtrack by calculating the amount of the idle that should
286-
// be returned to the pool using the original present value ratio.
287-
uint256 overestimatedProceeds = uint256(-withdrawalShares)
288-
.mulDivDown(startingPresentValue, lpTotalSupply);
289-
_updateLiquidity(int256(overestimatedProceeds));
290-
_applyWithdrawalProceeds(
291-
overestimatedProceeds,
292-
withdrawalSharesOutstanding,
293-
sharePrice
238+
// Remove the liquidity from the pool.
239+
(
240+
uint256 shareProceeds,
241+
uint256 withdrawalShares
242+
) = _applyRemoveLiquidity(
243+
_shares,
244+
sharePrice,
245+
totalLpSupply,
246+
totalActiveLpSupply,
247+
withdrawalSharesOutstanding
294248
);
295-
withdrawalShares = 0;
296-
}
297249

298250
// Mint the withdrawal shares to the LP.
299251
_mint(
300252
AssetId._WITHDRAWAL_SHARE_ASSET_ID,
301253
_destination,
302-
uint256(withdrawalShares)
254+
withdrawalShares
303255
);
304256

305257
// Withdraw the shares from the yield source.
@@ -312,6 +264,15 @@ abstract contract HyperdriveLP is HyperdriveTWAP {
312264
// Enforce min user outputs
313265
if (_minOutput > baseProceeds) revert Errors.OutputLimit();
314266

267+
// Emit a RemoveLiquidity event.
268+
uint256 shares = _shares;
269+
emit RemoveLiquidity(
270+
_destination,
271+
shares,
272+
baseProceeds,
273+
uint256(withdrawalShares)
274+
);
275+
315276
return (baseProceeds, uint256(withdrawalShares));
316277
}
317278

@@ -362,6 +323,9 @@ abstract contract HyperdriveLP is HyperdriveTWAP {
362323

363324
// Enforce min user outputs
364325
if (_minOutput > _proceeds) revert Errors.OutputLimit();
326+
327+
// Emit a RedeemWithdrawalShares event.
328+
emit RedeemWithdrawalShares(_destination, _shares, _proceeds);
365329
}
366330

367331
/// @dev Updates the pool's liquidity and holds the pool's APR constant.
@@ -389,6 +353,92 @@ abstract contract HyperdriveLP is HyperdriveTWAP {
389353
}
390354
}
391355

356+
/// @dev Removes liquidity from the pool and calculates the amount of
357+
/// withdrawal shares that should be minted.
358+
/// @param _shares The amount of shares to remove.
359+
/// @param _sharePrice The current price of a share.
360+
/// @param _totalLpSupply The total amount of LP shares.
361+
/// @param _totalActiveLpSupply The total amount of active LP shares.
362+
/// @param _withdrawalSharesOutstanding The total amount of withdrawal
363+
/// shares outstanding.
364+
/// @return shareProceeds The share proceeds that will be paid to the LP.
365+
/// @return The amount of withdrawal shares that should be minted.
366+
function _applyRemoveLiquidity(
367+
uint256 _shares,
368+
uint256 _sharePrice,
369+
uint256 _totalLpSupply,
370+
uint256 _totalActiveLpSupply,
371+
uint256 _withdrawalSharesOutstanding
372+
) internal returns (uint256 shareProceeds, uint256) {
373+
// Calculate the starting present value of the pool.
374+
HyperdriveMath.PresentValueParams memory params = HyperdriveMath
375+
.PresentValueParams({
376+
shareReserves: _marketState.shareReserves,
377+
bondReserves: _marketState.bondReserves,
378+
sharePrice: _sharePrice,
379+
initialSharePrice: _initialSharePrice,
380+
timeStretch: _timeStretch,
381+
longsOutstanding: _marketState.longsOutstanding,
382+
longAverageTimeRemaining: _calculateTimeRemaining(
383+
uint256(_marketState.longAverageMaturityTime).divUp(1e36) // scale to seconds
384+
),
385+
shortsOutstanding: _marketState.shortsOutstanding,
386+
shortAverageTimeRemaining: _calculateTimeRemaining(
387+
uint256(_marketState.shortAverageMaturityTime).divUp(1e36) // scale to seconds
388+
),
389+
shortBaseVolume: _marketState.shortBaseVolume
390+
});
391+
uint256 startingPresentValue = HyperdriveMath.calculatePresentValue(
392+
params
393+
);
394+
395+
// The LP is given their share of the idle capital in the pool. This
396+
// is removed from the pool's reserves and paid out immediately. We use
397+
// the average opening share price of longs to avoid double counting
398+
// the variable rate interest accrued on long positions. The idle amount
399+
// is given by:
400+
//
401+
// idle = (z - (o_l / c_0)) * (dl / l_a)
402+
shareProceeds = _marketState.shareReserves;
403+
if (_marketState.longsOutstanding > 0) {
404+
shareProceeds -= uint256(_marketState.longsOutstanding).divDown(
405+
_marketState.longOpenSharePrice
406+
);
407+
}
408+
shareProceeds = shareProceeds.mulDivDown(_shares, _totalActiveLpSupply);
409+
_updateLiquidity(-int256(shareProceeds));
410+
params.shareReserves = _marketState.shareReserves;
411+
params.bondReserves = _marketState.bondReserves;
412+
uint256 endingPresentValue = HyperdriveMath.calculatePresentValue(
413+
params
414+
);
415+
416+
// Calculate the amount of withdrawal shares that should be minted. We
417+
// solve for this value by solving the present value equation as
418+
// follows:
419+
//
420+
// PV0 / l0 = PV1 / (l0 - dl + dw) => dw = (PV1 / PV0) * l0 - (l0 - dl)
421+
int256 withdrawalShares = int256(
422+
_totalLpSupply.mulDivDown(endingPresentValue, startingPresentValue)
423+
);
424+
withdrawalShares -= int256(_totalLpSupply) - int256(_shares);
425+
if (withdrawalShares < 0) {
426+
// We backtrack by calculating the amount of the idle that should
427+
// be returned to the pool using the original present value ratio.
428+
uint256 overestimatedProceeds = uint256(-withdrawalShares)
429+
.mulDivDown(startingPresentValue, _totalLpSupply);
430+
_updateLiquidity(int256(overestimatedProceeds));
431+
_applyWithdrawalProceeds(
432+
overestimatedProceeds,
433+
_withdrawalSharesOutstanding,
434+
_sharePrice
435+
);
436+
withdrawalShares = 0;
437+
}
438+
439+
return (shareProceeds, uint256(withdrawalShares));
440+
}
441+
392442
/// @dev Pays out the maximum amount of withdrawal shares given a specified
393443
/// amount of withdrawal proceeds.
394444
/// @param _withdrawalProceeds The amount of withdrawal proceeds to pay out.

contracts/src/HyperdriveLong.sol

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,11 @@ abstract contract HyperdriveLong is HyperdriveLP {
8484
_destination,
8585
bondProceeds
8686
);
87+
88+
// Emit an OpenLong event.
89+
uint256 baseAmount = _baseAmount; // Avoid stack too deep error.
90+
emit OpenLong(_destination, maturityTime, baseAmount, bondProceeds);
91+
8792
return (bondProceeds);
8893
}
8994

@@ -155,6 +160,9 @@ abstract contract HyperdriveLong is HyperdriveLP {
155160
// Enforce min user outputs
156161
if (_minOutput > baseProceeds) revert Errors.OutputLimit();
157162

163+
// Emit a CloseLong event.
164+
emit CloseLong(_destination, _maturityTime, baseProceeds, _bondAmount);
165+
158166
return (baseProceeds);
159167
}
160168

contracts/src/HyperdriveShort.sol

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,10 @@ abstract contract HyperdriveShort is HyperdriveLP {
103103
_bondAmount
104104
);
105105

106+
// Emit an OpenShort event.
107+
uint256 bondAmount = _bondAmount; // Avoid stack too deep error.
108+
emit OpenShort(_destination, maturityTime, traderDeposit, bondAmount);
109+
106110
return (traderDeposit);
107111
}
108112

@@ -185,7 +189,13 @@ abstract contract HyperdriveShort is HyperdriveLP {
185189

186190
// Enforce min user outputs
187191
if (baseProceeds < _minOutput) revert Errors.OutputLimit();
188-
return (baseProceeds);
192+
193+
// Emit a CloseShort event.
194+
uint256 maturityTime = _maturityTime; // Avoid stack too deep error.
195+
uint256 bondAmount = _bondAmount; // Avoid stack too deep error.
196+
emit CloseShort(_destination, maturityTime, baseProceeds, bondAmount);
197+
198+
return baseProceeds;
189199
}
190200

191201
/// @dev Applies an open short to the state. This includes updating the

foundry.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ fs_permissions = [{ access = "write", path = "./artifacts/script_addresses.json"
2525
deny_warnings = true
2626
# optimizer settings
2727
optimizer = true
28-
optimizer_runs = 8000
28+
optimizer_runs = 4500
2929
# Enable via-ir
3030
via_ir = true
3131
# Enable gas-reporting for all contracts

0 commit comments

Comments
 (0)