@@ -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.
0 commit comments