From 50ddf93cb8911d90ed012d9f71d7e61b92603fdd Mon Sep 17 00:00:00 2001 From: duelinggalois Date: Mon, 15 Jun 2026 21:21:46 +0000 Subject: [PATCH] Updated contract docs for published pull request --- .../AmmalgamPair.sol/contract.AmmalgamPair.md | 233 +++++--- ...ontract.SaturationAndGeometricTWAPState.md | 84 ++- .../contract.AmmalgamFactory.md | 2 +- ...contract.ERC20DebtLiquidityTokenFactory.md | 2 +- .../contract.ERC20LiquidityTokenFactory.md | 2 +- .../contract.ERC4626DebtTokenFactory.md | 2 +- .../contract.ERC4626DepositTokenFactory.md | 2 +- .../interface.IAmmalgamPair.md | 12 +- ...erface.ISaturationAndGeometricTWAPState.md | 54 +- .../interface.IBorrowCallback.md | 6 +- .../interface.ICallback.md | 2 +- .../interface.ISwapCallback.md | 2 +- .../interface.ITransferValidator.md | 25 +- .../interface.IAmmalgamFactory.md | 2 +- .../interface.IBeaconCallback.md | 2 +- .../interface.IFactoryCallback.md | 2 +- .../interface.ITokenFactory.md | 2 +- .../interface.IAmmalgamERC20.md | 2 +- .../interface.IERC20DebtToken.md | 2 +- .../interface.IHookRegistry.md | 2 +- .../constants.ITokenController.md | 2 +- .../interface.ITokenController.md | 17 +- .../libraries/Convert.sol/library.Convert.md | 2 +- .../library.GeometricTWAP.md | 60 +-- .../Interest.sol/library.Interest.md | 2 +- .../Liquidation.sol/library.Liquidation.md | 143 ++--- .../library.PartialLiquidations.md | 497 +++++++++++++++--- .../library.PriceExtremes.md | 91 ++++ .../library.QuadraticSwapFees.md | 18 +- .../Saturation.sol/library.Saturation.md | 317 ++++++++--- .../TickMath.sol/library.TickMath.md | 2 +- .../TokenSymbol.sol/library.TokenSymbol.md | 2 +- .../Uint16Set.sol/library.Uint16Set.md | 8 +- .../Validation.sol/library.Validation.md | 118 +---- .../constants.sol/constants.constants.md | 13 +- .../contract.BeaconController.md | 2 +- .../interface.IBeaconController.md | 2 +- .../contract.InitializablePair.md | 22 +- .../contract.PairBeaconProxy.md | 2 +- .../interface.IPairInitializable.md | 2 +- .../contract.PairBlockLendingFundRemoval.md} | 19 +- .../PairFrozen.sol/contract.PairFrozen.md | 11 +- .../contract.PairLockedLoans.md | 17 +- .../ERC20Base.sol/abstract.ERC20Base.md | 2 +- .../ERC20Base.sol/struct.ERC20BaseConfig.md | 2 +- .../abstract.ERC20DebtBase.md | 7 +- .../contract.ERC20DebtLiquidityToken.md | 2 +- .../contract.ERC20LiquidityToken.md | 6 +- .../contract.ERC4626DebtToken.md | 8 +- .../contract.ERC4626DepositToken.md | 10 +- .../HookRegistry.sol/contract.HookRegistry.md | 2 +- .../contract.TokenController.md | 106 +++- .../function.deployFactory.md | 2 +- 53 files changed, 1373 insertions(+), 585 deletions(-) create mode 100644 docs/developer-guide/contracts/libraries/PriceExtremes.sol/library.PriceExtremes.md rename docs/developer-guide/contracts/proxy/{PairBlockAllTransfers.sol/contract.PairBlockAllTransfers.md => PairBlockLendingFundRemoval.sol/contract.PairBlockLendingFundRemoval.md} (69%) diff --git a/docs/developer-guide/contracts/AmmalgamPair.sol/contract.AmmalgamPair.md b/docs/developer-guide/contracts/AmmalgamPair.sol/contract.AmmalgamPair.md index 45ac2ef2..d3e80ed1 100644 --- a/docs/developer-guide/contracts/AmmalgamPair.sol/contract.AmmalgamPair.md +++ b/docs/developer-guide/contracts/AmmalgamPair.sol/contract.AmmalgamPair.md @@ -1,5 +1,5 @@ # AmmalgamPair -[Git Source](https://github.com/Ammalgam-Protocol/core-v1/blob/2b185eab2df708b55f7ffa534655c69f626e73b3/contracts/AmmalgamPair.sol) +[Git Source](https://github.com/Ammalgam-Protocol/core-v1/blob/ec51218155bd2f8c1e5dc761ed4728baae81a01b/contracts/AmmalgamPair.sol) **Inherits:** [IAmmalgamPair](/docs/developer-guide/contracts/interfaces/IAmmalgamPair.sol/interface.IAmmalgamPair.md), [TokenController](/docs/developer-guide/contracts/tokens/TokenController.sol/contract.TokenController.md) @@ -34,6 +34,13 @@ uint256 private transient locked; ``` +### activeBorrower + +```solidity +address private transient activeBorrower; +``` + + ## Functions ### lock @@ -56,6 +63,13 @@ function _lock() private; function _unlock() private; ``` +### _revertNestedBorrow + + +```solidity +function _revertNestedBorrow() private view; +``` + ### mint @@ -110,11 +124,9 @@ function calculateAmountIn( helper method to calculate balance after fees *Note that amountIn + reserve does not always equal balance if amountOut > 0. -When assets are depleted, we should multiply (balance - missing) * BUFFER_NUMERATOR / -INVERSE_BUFFER, but instead of divide here, we multiply the other side of the K -comparison, see `calculateReserveAdjustmentsForMissingAssets` where we multiply by -INVERSE_BUFFER. When not depleted, we multiply by INVERSE_BUFFER instead of dividing on -the other side.* +In the depleted case the balance is scaled by `BUFFER_NUMERATOR`; the matching +scaling is applied on the reserve side in `calculateReserveAdjustmentsForMissingAssets` +so the K comparison stays division-free on both branches.* ```solidity @@ -137,42 +149,6 @@ function calculateBalanceAfterFees( |`missing`|`uint256`|the missing assets, zero if deposits > borrows of X or Y| -### calculateReserveAdjustmentsForMissingAssets - -helper method to calculate balance adjustment for missing assets - -*For swap, when assets are depleted, we should multiply (reserve - missing) by -BUFFER_NUMERATOR / INVERSE_BUFFER, but instead of divide here, we multiply the other -side of the K comparison, see `calculateBalanceAfterFees` where we multiply by -INVERSE_BUFFER. -For updateObservation, different scaled `buffer` and `bufferNumerator` values -are supplied so the adjusted reserve reflects observation-specific logic.* - - -```solidity -function calculateReserveAdjustmentsForMissingAssets( - uint256 reserve, - uint256 missing, - uint256 buffer, - uint256 bufferNumerator -) private pure returns (uint256 reserveAdjustment); -``` -**Parameters** - -|Name|Type|Description| -|----|----|-----------| -|`reserve`|`uint256`|the starting reserve| -|`missing`|`uint256`|the missing assets, zero if deposits > borrows of X or Y| -|`buffer`|`uint256`| Scaling factor applied to the reserve for the depletion comparison.| -|`bufferNumerator`|`uint256`| Scaling factor applied to the missing amount for the comparison and for computing the depleted-case adjusted reserve.| - -**Returns** - -|Name|Type|Description| -|----|----|-----------| -|`reserveAdjustment`|`uint256`|The adjusted reserve value used for swap or updateObservation depends on the buffer, bufferNumerator to be passed in.| - - ### deposit @@ -338,7 +314,85 @@ function liquidate( LTV based liquidation. The LTV dictates the max premium that can be had by the liquidator. We determine the amount of borrowed liquidity to be repaid by reducing the -actual amount paid by the amount passed in for the borrow x and borrow y amount. +actual amount transferred prior to calling `liquidate()` by the amount passed in for the +repayXAssets and repayYAssets parameters. +## Calculating a Hard Liquidation +Hard liquidations can be partial subset of the borrower's entire position based on +tranche saturation composition. Use `LiquidationUtils.calculatePartialLiquidationAmount()` +to compute the partial position, max premium, and the amounts needed for the call. +Three prices are in play and each is used at a different stage: +| Price | Source | Where used | +|---------------------|-------------------------|------------------------------------| +| Reserve price | reserveX / reserveY | `_repayLiquidity`: splits tokens | +| | | into the X/Y ratio the pool needs | +| | | to burn BORROW_L. | +| sqrtPriceMin (TWAP) | geometric TWAP low tick | Verification converts: | +| | | BORROW_X → L (worst-case borrow) | +| | | DEPOSIT_Y → L (worst-case dep.) | +| sqrtPriceMax (TWAP) | geometric TWAP high tick| Verification converts: | +| | | BORROW_Y → L (worst-case borrow) | +| | | DEPOSIT_X → L (worst-case dep.) | +Verification (`verifyHardLiquidation`) swaps min and max when calling +`getCheckLtvParams(proposed, sqrtPriceMax, sqrtPriceMin)`. This values deposits at +their highest and borrows at their lowest, favoring the borrower by making the +position appear as healthy as possible. This limits the ability of liquidators to +manipulate premiums. +The reserve price and TWAP prices may diverge. Seized deposit amounts must be +computed using TWAP prices (the verification domain), not reserve prices. +### Net Debt Calculation and the BORROW_L Overlap +`getBorrowedInL` initializes BOTH sides from BORROW_L: +```text +netBorrowedXinL = BORROW_L + convertXToL(BORROW_X, sqrtPriceMin) +netBorrowedYinL = BORROW_L + convertYToL(BORROW_Y, sqrtPriceMax) +``` +`getDepositsInL` initializes BOTH sides from DEPOSIT_L: +```text +netDepositedXinL = DEPOSIT_L + convertXToL(DEPOSIT_X, sqrtPriceMax) +netDepositedYinL = DEPOSIT_L + convertYToL(DEPOSIT_Y, sqrtPriceMin) +``` +`calcDebtAndCollateral` then nets these to determine `netDebtX`: +```text +netDebtX = true when netDepositedX <= netBorrowedX AND netDepositedY > netBorrowedY +netDebtX = false when netDepositedY <= netBorrowedY AND netDepositedX > netBorrowedX +``` +`netDebtX` selects the saturation account. A wrong value causes +`calculatePartialLiquidation` to return the wrong tranche set, reverting the +liquidation. +### Computing Seized amounts Borrow X, Seize Y +For a position with BORROW_X and DEPOSIT_Y, the seized Y only needs +to cover the liquidation premium on the repaid debt: +```text +borrowXInL = ceil(BORROW_X * Q72 / sqrtPriceMax) +premiumInL = borrowXInL * maxPremiumBips / BIPS +seizedY = premiumInL * Q72 / sqrtPriceMax +``` +### Overlap Case: Borrow X + Borrow L, Seize Y +When BORROW_L is present and BORROW_Y is zero, `getBorrowedInL` computes: +```text +netBorrowedXinL = BORROW_L + convertXToL(BORROW_X, sqrtPriceMin) +netBorrowedYinL = BORROW_L +``` +The seized Y (in L-terms at TWAP price) must exceed BORROW_L so that +`netDepositedYinL > netBorrowedYinL`, which is required for `netDebtX = true`. +The seized amount includes the BORROW_L overlap plus the liquidation premium: +```text +borrowXInL = ceil(BORROW_X * Q72 / sqrtPriceMax) +netRepaidInL = BORROW_L + borrowXInL +premiumInL = netRepaidInL * maxPremiumBips / BIPS +seizedYInL = BORROW_L + premiumInL +seizedY = seizedYInL * Q72 / sqrtPriceMax +``` +### Token Transfer Amounts +The liquidator must transfer enough tokens to cover both direct borrows and BORROW_L: +```text +repayLX = ceil(BORROW_L * reserveX / activeLiquidity) +repayLY = ceil(BORROW_L * reserveY / activeLiquidity) +totalXTransfer = BORROW_X + repayLX +totalYTransfer = repayLY +``` +These use reserve prices because `_repayLiquidity` splits tokens by the reserve ratio. +The seized Y amount uses TWAP prices because `verifyHardLiquidation` operates in that +domain. ```solidity @@ -369,14 +423,7 @@ Liquidation based on change of saturation because of time. ```solidity -function resetSaturation( - Validation.InputParams memory inputParams, - address borrower, - address to, - uint256 depositLToBeTransferredInLAssets, - uint256 depositXToBeTransferredInXAssets, - uint256 depositYToBeTransferredInYAssets -) private; +function resetSaturation(Validation.InputParams memory inputParams, address borrower, address to) private; ``` **Parameters** @@ -385,9 +432,6 @@ function resetSaturation( |`inputParams`|`Validation.InputParams`|| |`borrower`|`address`|The account being liquidated.| |`to`|`address`|The account to send the liquidated deposit to| -|`depositLToBeTransferredInLAssets`|`uint256`|The amount of L to be transferred to the liquidator.| -|`depositXToBeTransferredInXAssets`|`uint256`|The amount of X to be transferred to the liquidator.| -|`depositYToBeTransferredInYAssets`|`uint256`|The amount of Y to be transferred to the liquidator.| ### liquidateLeverage @@ -400,24 +444,66 @@ function liquidateLeverage( Validation.InputParams memory inputParams, address borrower, address to, - uint256 repaidXAssets, - uint256 repaidYAssets, - bool depositL, - bool repayL + uint256 actualRepaidXAssets, + uint256 actualRepaidYAssets ) private; ``` **Parameters** |Name|Type|Description| |----|----|-----------| -|`inputParams`|`Validation.InputParams`|| +|`inputParams`|`Validation.InputParams`|The input parameters for the liquidation, including reserves and price.| |`borrower`|`address`|The account being liquidated.| -|`to`|`address`|The account to send the liquidated deposit to| -|`repaidXAssets`|`uint256`|| -|`repaidYAssets`|`uint256`|| -|`depositL`|`bool`|Flag indicating whether the deposit transferred to the liquidator is L xor X+Y.| -|`repayL`|`bool`|Flag indicating whether the repay by the liquidator is L xor X+Y.| +|`to`|`address`|The account to send the liquidated deposit to.| +|`actualRepaidXAssets`|`uint256`|The actual amount of X assets repaid by the liquidator.| +|`actualRepaidYAssets`|`uint256`|The actual amount of Y assets repaid by the liquidator.| + + +### _liquidationRepayHelper + +Repays the borrow legs of a liquidation and verifies the liquidator repaid enough. + +*Shared by hard and leverage liquidations. The required X/Y repayments must be fully +covered by the assets the liquidator sent in; any remainder repays borrowed liquidity. +`liquidationParams[BORROW_L]` carries the minimum liquidity that must be repaid and is +overwritten with the liquidity actually repaid so `verifyHardLiquidation` can read it back.* + + +```solidity +function _liquidationRepayHelper( + address borrower, + uint256[6] memory liquidationParams, + uint256 actualRepaidXAssets, + uint256 actualRepaidYAssets, + uint256 _reserveXAssets, + uint256 _reserveYAssets +) private; +``` +**Parameters** +|Name|Type|Description| +|----|----|-----------| +|`borrower`|`address`|The account being liquidated.| +|`liquidationParams`|`uint256[6]`|Borrow legs to repay, indexed by BORROW_X / BORROW_Y / BORROW_L.| +|`actualRepaidXAssets`|`uint256`|The X assets the liquidator transferred in for the repayment.| +|`actualRepaidYAssets`|`uint256`|The Y assets the liquidator transferred in for the repayment.| +|`_reserveXAssets`|`uint256`|Current X reserves, used to split repaid liquidity by the reserve ratio.| +|`_reserveYAssets`|`uint256`|Current Y reserves, used to split repaid liquidity by the reserve ratio.| + + +### _revertNotEnoughRepaidForLiquidation + + +```solidity +function _revertNotEnoughRepaidForLiquidation() private pure; +``` + +### _burnBadDebt + + +```solidity +function _burnBadDebt(address borrower, uint256[6] memory userAssets) private; +``` ### finalizeLiquidation @@ -510,12 +596,27 @@ function validateOnUpdate(address validate, address update, bool alwaysUpdate) p function validateSolvency(address validate, bool alwaysUpdate) private; ``` -### getInputParamsAndUpdateSaturation +### updateSaturationIfNeeded + +Update saturation state for an account if it already exists in saturation. + +*Note that during a repay of debt, we may not have an entry in saturation if +1. The position is a straddle with a payout that never reaches zero +2. Repay is occurring during a callback of a flash loan, saturation will not be updated +until the end of the borrow call after the callback concludes.* ```solidity -function getInputParamsAndUpdateSaturation(address toUpdate, bool alwaysUpdate) private; +function updateSaturationIfNeeded( + address toUpdate +) private; ``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`toUpdate`|`address`|The account to update saturation for.| + ### getInputParams diff --git a/docs/developer-guide/contracts/SaturationAndGeometricTWAPState.sol/contract.SaturationAndGeometricTWAPState.md b/docs/developer-guide/contracts/SaturationAndGeometricTWAPState.sol/contract.SaturationAndGeometricTWAPState.md index 2989d0d2..7454b3a9 100644 --- a/docs/developer-guide/contracts/SaturationAndGeometricTWAPState.sol/contract.SaturationAndGeometricTWAPState.md +++ b/docs/developer-guide/contracts/SaturationAndGeometricTWAPState.sol/contract.SaturationAndGeometricTWAPState.md @@ -1,5 +1,5 @@ # SaturationAndGeometricTWAPState -[Git Source](https://github.com/Ammalgam-Protocol/core-v1/blob/2b185eab2df708b55f7ffa534655c69f626e73b3/contracts/SaturationAndGeometricTWAPState.sol) +[Git Source](https://github.com/Ammalgam-Protocol/core-v1/blob/ec51218155bd2f8c1e5dc761ed4728baae81a01b/contracts/SaturationAndGeometricTWAPState.sol) **Inherits:** Initializable, [ISaturationAndGeometricTWAPState](/docs/developer-guide/contracts/interfaces/ISaturationAndGeometricTWAPState.sol/interface.ISaturationAndGeometricTWAPState.md), OwnableUpgradeable @@ -55,6 +55,13 @@ mapping(address => bool) internal isPairInitialized; ``` +### priceExtremesGivenPair + +```solidity +mapping(address => PriceExtremes.State) internal priceExtremesGivenPair; +``` + + ## Functions ### constructor @@ -151,12 +158,47 @@ function getAccount( ) external view returns (Saturation.Account memory); ``` +### accountExistsInSaturation + +Check if an account exists in either netX or netY saturation tree + + +```solidity +function accountExistsInSaturation(address pairAddress, address accountAddress) external view returns (bool exists); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`pairAddress`|`address`|The address of the pair| +|`accountAddress`|`address`|The address of the account to check| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|`exists`|`bool`|True if the account exists in either tree| + + +### _accountExistsInSaturation + +Internal sibling of `accountExistsInSaturation` so callers within this contract +can check tree membership without paying the external-call overhead or making the +getter `public`. + + +```solidity +function _accountExistsInSaturation(address pairAddress, address accountAddress) private view returns (bool exists); +``` + ### update update the borrow position of an account and potentially check (and revert) if the resulting sat is too high -*run accruePenalties before running this function* +*run accruePenalties before running this function. `lastUsedActiveLiquidityInLAssets` +is captured only on the transition into saturation, so third-party-triggered updates +cannot clobber a position's baseline ALA (OV-6-1).* ```solidity @@ -183,7 +225,9 @@ Scales the desired saturation threshold based on changes in Active Liquidity Ass existing positions to appear more saturated (since saturation = borrows / ALA), potentially triggering unwarranted liquidation premiums. This function scales the desired saturation proportionally to ALA changes to maintain the position's relative health. -The scaling formula: scaled = lastUsedALA * desiredSat / currentALA* +The scaling formula: scaled = lastUsedALA * desiredSat / currentALA. +Scaling is applied only while the account is in the saturation tree, so baselines +left over from previously-closed positions cannot influence a freshly-opened one.* ```solidity @@ -249,15 +293,15 @@ function calcSatChangeRatioBips( uint256 liqSqrtPriceInYInQ72, address pairAddress, address account -) external view virtual isInitialized returns (uint256 ratioNetXBips, uint256 ratioNetYBips); +) external view virtual isInitialized returns (uint256 ratioBips); ``` **Parameters** |Name|Type|Description| |----|----|-----------| |`inputParams`|`Validation.InputParams`|The params containing the position of `account`.| -|`liqSqrtPriceInXInQ72`|`uint256`|The liquidation price.| -|`liqSqrtPriceInYInQ72`|`uint256`|| +|`liqSqrtPriceInXInQ72`|`uint256`|The liquidation sqrt price for netX in Q72; pass 0 if not applicable.| +|`liqSqrtPriceInYInQ72`|`uint256`|The liquidation sqrt price for netY in Q72; pass 0 if not applicable.| |`pairAddress`|`address`|The address of the pair| |`account`|`address`|The account for which we are calculating the saturation change ratio.| @@ -265,9 +309,17 @@ function calcSatChangeRatioBips( |Name|Type|Description| |----|----|-----------| -|`ratioNetXBips`|`uint256`|The ratio representing the change in netX saturation for account.| -|`ratioNetYBips`|`uint256`|The ratio representing the change in netY saturation for account.| +|`ratioBips`|`uint256`|The ratio representing the change saturation for account.| + +### recordPriceExtreme + + +```solidity +function recordPriceExtreme( + uint256 priceQ128 +) external isInitialized; +``` ### getObservations @@ -339,7 +391,7 @@ function getTickRange( uint256 reserveXAssets, uint256 reserveYAssets, bool includeLongTermTick -) external view virtual returns (int16, int16); +) external view virtual returns (int16 minTick, int16 maxTick); ``` **Parameters** @@ -354,8 +406,8 @@ function getTickRange( |Name|Type|Description| |----|----|-----------| -|``|`int16`|minTick The minimum tick value among the three observed ticks.| -|``|`int16`|maxTick The maximum tick value among the three observed ticks.| +|`minTick`|`int16`|The minimum tick value among the three observed ticks.| +|`maxTick`|`int16`|The maximum tick value among the three observed ticks.| ### getLendingStateTickAndCheckpoint @@ -395,16 +447,8 @@ function getLendingStateTickAndCheckpoint( ```solidity -function getObservedMidTermTick( - bool isLongTermBufferInitialized -) external view returns (int16); +function getObservedMidTermTick() external view returns (int16); ``` -**Parameters** - -|Name|Type|Description| -|----|----|-----------| -|`isLongTermBufferInitialized`|`bool`|Boolean value which represents whether long-term buffer is filled or not.| - **Returns** |Name|Type|Description| diff --git a/docs/developer-guide/contracts/factories/AmmalgamFactory.sol/contract.AmmalgamFactory.md b/docs/developer-guide/contracts/factories/AmmalgamFactory.sol/contract.AmmalgamFactory.md index 66322b97..82efc8e9 100644 --- a/docs/developer-guide/contracts/factories/AmmalgamFactory.sol/contract.AmmalgamFactory.md +++ b/docs/developer-guide/contracts/factories/AmmalgamFactory.sol/contract.AmmalgamFactory.md @@ -1,5 +1,5 @@ # AmmalgamFactory -[Git Source](https://github.com/Ammalgam-Protocol/core-v1/blob/2b185eab2df708b55f7ffa534655c69f626e73b3/contracts/factories/AmmalgamFactory.sol) +[Git Source](https://github.com/Ammalgam-Protocol/core-v1/blob/ec51218155bd2f8c1e5dc761ed4728baae81a01b/contracts/factories/AmmalgamFactory.sol) **Inherits:** [IAmmalgamFactory](/docs/developer-guide/contracts/interfaces/factories/IAmmalgamFactory.sol/interface.IAmmalgamFactory.md) diff --git a/docs/developer-guide/contracts/factories/ERC20DebtLiquidityTokenFactory.sol/contract.ERC20DebtLiquidityTokenFactory.md b/docs/developer-guide/contracts/factories/ERC20DebtLiquidityTokenFactory.sol/contract.ERC20DebtLiquidityTokenFactory.md index dd4d9e02..efafb392 100644 --- a/docs/developer-guide/contracts/factories/ERC20DebtLiquidityTokenFactory.sol/contract.ERC20DebtLiquidityTokenFactory.md +++ b/docs/developer-guide/contracts/factories/ERC20DebtLiquidityTokenFactory.sol/contract.ERC20DebtLiquidityTokenFactory.md @@ -1,5 +1,5 @@ # ERC20DebtLiquidityTokenFactory -[Git Source](https://github.com/Ammalgam-Protocol/core-v1/blob/2b185eab2df708b55f7ffa534655c69f626e73b3/contracts/factories/ERC20DebtLiquidityTokenFactory.sol) +[Git Source](https://github.com/Ammalgam-Protocol/core-v1/blob/ec51218155bd2f8c1e5dc761ed4728baae81a01b/contracts/factories/ERC20DebtLiquidityTokenFactory.sol) **Inherits:** [ITokenFactory](/docs/developer-guide/contracts/interfaces/factories/ITokenFactory.sol/interface.ITokenFactory.md) diff --git a/docs/developer-guide/contracts/factories/ERC20LiquidityTokenFactory.sol/contract.ERC20LiquidityTokenFactory.md b/docs/developer-guide/contracts/factories/ERC20LiquidityTokenFactory.sol/contract.ERC20LiquidityTokenFactory.md index 158afd54..3d42d512 100644 --- a/docs/developer-guide/contracts/factories/ERC20LiquidityTokenFactory.sol/contract.ERC20LiquidityTokenFactory.md +++ b/docs/developer-guide/contracts/factories/ERC20LiquidityTokenFactory.sol/contract.ERC20LiquidityTokenFactory.md @@ -1,5 +1,5 @@ # ERC20LiquidityTokenFactory -[Git Source](https://github.com/Ammalgam-Protocol/core-v1/blob/2b185eab2df708b55f7ffa534655c69f626e73b3/contracts/factories/ERC20LiquidityTokenFactory.sol) +[Git Source](https://github.com/Ammalgam-Protocol/core-v1/blob/ec51218155bd2f8c1e5dc761ed4728baae81a01b/contracts/factories/ERC20LiquidityTokenFactory.sol) **Inherits:** [ITokenFactory](/docs/developer-guide/contracts/interfaces/factories/ITokenFactory.sol/interface.ITokenFactory.md) diff --git a/docs/developer-guide/contracts/factories/ERC4626DebtTokenFactory.sol/contract.ERC4626DebtTokenFactory.md b/docs/developer-guide/contracts/factories/ERC4626DebtTokenFactory.sol/contract.ERC4626DebtTokenFactory.md index 44479635..f99e3e7a 100644 --- a/docs/developer-guide/contracts/factories/ERC4626DebtTokenFactory.sol/contract.ERC4626DebtTokenFactory.md +++ b/docs/developer-guide/contracts/factories/ERC4626DebtTokenFactory.sol/contract.ERC4626DebtTokenFactory.md @@ -1,5 +1,5 @@ # ERC4626DebtTokenFactory -[Git Source](https://github.com/Ammalgam-Protocol/core-v1/blob/2b185eab2df708b55f7ffa534655c69f626e73b3/contracts/factories/ERC4626DebtTokenFactory.sol) +[Git Source](https://github.com/Ammalgam-Protocol/core-v1/blob/ec51218155bd2f8c1e5dc761ed4728baae81a01b/contracts/factories/ERC4626DebtTokenFactory.sol) **Inherits:** [ITokenFactory](/docs/developer-guide/contracts/interfaces/factories/ITokenFactory.sol/interface.ITokenFactory.md) diff --git a/docs/developer-guide/contracts/factories/ERC4626DepositTokenFactory.sol/contract.ERC4626DepositTokenFactory.md b/docs/developer-guide/contracts/factories/ERC4626DepositTokenFactory.sol/contract.ERC4626DepositTokenFactory.md index 7b34e7a4..abeebaa4 100644 --- a/docs/developer-guide/contracts/factories/ERC4626DepositTokenFactory.sol/contract.ERC4626DepositTokenFactory.md +++ b/docs/developer-guide/contracts/factories/ERC4626DepositTokenFactory.sol/contract.ERC4626DepositTokenFactory.md @@ -1,5 +1,5 @@ # ERC4626DepositTokenFactory -[Git Source](https://github.com/Ammalgam-Protocol/core-v1/blob/2b185eab2df708b55f7ffa534655c69f626e73b3/contracts/factories/ERC4626DepositTokenFactory.sol) +[Git Source](https://github.com/Ammalgam-Protocol/core-v1/blob/ec51218155bd2f8c1e5dc761ed4728baae81a01b/contracts/factories/ERC4626DepositTokenFactory.sol) **Inherits:** [ITokenFactory](/docs/developer-guide/contracts/interfaces/factories/ITokenFactory.sol/interface.ITokenFactory.md) diff --git a/docs/developer-guide/contracts/interfaces/IAmmalgamPair.sol/interface.IAmmalgamPair.md b/docs/developer-guide/contracts/interfaces/IAmmalgamPair.sol/interface.IAmmalgamPair.md index a130c3f6..dc4c39f2 100644 --- a/docs/developer-guide/contracts/interfaces/IAmmalgamPair.sol/interface.IAmmalgamPair.md +++ b/docs/developer-guide/contracts/interfaces/IAmmalgamPair.sol/interface.IAmmalgamPair.md @@ -1,11 +1,15 @@ # IAmmalgamPair -[Git Source](https://github.com/Ammalgam-Protocol/core-v1/blob/2b185eab2df708b55f7ffa534655c69f626e73b3/contracts/interfaces/IAmmalgamPair.sol) - -**Inherits:** -[ITransferValidator](/docs/developer-guide/contracts/interfaces/callbacks/ITransferValidator.sol/interface.ITransferValidator.md) +[Git Source](https://github.com/Ammalgam-Protocol/core-v1/blob/ec51218155bd2f8c1e5dc761ed4728baae81a01b/contracts/interfaces/IAmmalgamPair.sol) ## Functions +### validateOnUpdate + + +```solidity +function validateOnUpdate(address validate, address update, bool alwaysUpdate) external; +``` + ### mint Mints tokens and assigns them to `to` address. diff --git a/docs/developer-guide/contracts/interfaces/ISaturationAndGeometricTWAPState.sol/interface.ISaturationAndGeometricTWAPState.md b/docs/developer-guide/contracts/interfaces/ISaturationAndGeometricTWAPState.sol/interface.ISaturationAndGeometricTWAPState.md index b6a1508f..b0f77a5a 100644 --- a/docs/developer-guide/contracts/interfaces/ISaturationAndGeometricTWAPState.sol/interface.ISaturationAndGeometricTWAPState.md +++ b/docs/developer-guide/contracts/interfaces/ISaturationAndGeometricTWAPState.sol/interface.ISaturationAndGeometricTWAPState.md @@ -1,5 +1,5 @@ # ISaturationAndGeometricTWAPState -[Git Source](https://github.com/Ammalgam-Protocol/core-v1/blob/2b185eab2df708b55f7ffa534655c69f626e73b3/contracts/interfaces/ISaturationAndGeometricTWAPState.sol) +[Git Source](https://github.com/Ammalgam-Protocol/core-v1/blob/ec51218155bd2f8c1e5dc761ed4728baae81a01b/contracts/interfaces/ISaturationAndGeometricTWAPState.sol) ## Functions @@ -99,6 +99,28 @@ function getAccount( ) external view returns (Saturation.Account memory); ``` +### accountExistsInSaturation + +Check if an account exists in either netX or netY saturation tree + + +```solidity +function accountExistsInSaturation(address pairAddress, address accountAddress) external view returns (bool exists); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`pairAddress`|`address`|The address of the pair| +|`accountAddress`|`address`|The address of the account to check| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|`exists`|`bool`|True if the account exists in either tree| + + ### update update the borrow position of an account and potentially check (and revert) if the @@ -156,15 +178,15 @@ function calcSatChangeRatioBips( uint256 liqSqrtPriceInYInQ72, address pairAddress, address account -) external view returns (uint256 ratioNetXBips, uint256 ratioNetYBips); +) external view returns (uint256 ratioBips); ``` **Parameters** |Name|Type|Description| |----|----|-----------| |`inputParams`|`Validation.InputParams`|The params containing the position of `account`.| -|`liqSqrtPriceInXInQ72`|`uint256`|The liquidation price.| -|`liqSqrtPriceInYInQ72`|`uint256`|| +|`liqSqrtPriceInXInQ72`|`uint256`|The liquidation sqrt price for netX in Q72; pass 0 if not applicable.| +|`liqSqrtPriceInYInQ72`|`uint256`|The liquidation sqrt price for netY in Q72; pass 0 if not applicable.| |`pairAddress`|`address`|The address of the pair| |`account`|`address`|The account for which we are calculating the saturation change ratio.| @@ -172,9 +194,19 @@ function calcSatChangeRatioBips( |Name|Type|Description| |----|----|-----------| -|`ratioNetXBips`|`uint256`|The ratio representing the change in netX saturation for account.| -|`ratioNetYBips`|`uint256`|The ratio representing the change in netY saturation for account.| +|`ratioBips`|`uint256`|The ratio representing the change in saturation for account.| + + +### recordPriceExtreme + +Record a price extreme observation for the calling pair. + +```solidity +function recordPriceExtreme( + uint256 priceQ128 +) external; +``` ### configLongTermInterval @@ -287,16 +319,8 @@ function getLendingStateTickAndCheckpoint( ```solidity -function getObservedMidTermTick( - bool isLongTermBufferInitialized -) external view returns (int16 midTermTick); +function getObservedMidTermTick() external view returns (int16 midTermTick); ``` -**Parameters** - -|Name|Type|Description| -|----|----|-----------| -|`isLongTermBufferInitialized`|`bool`|Boolean value which represents whether long-term buffer is filled or not.| - **Returns** |Name|Type|Description| diff --git a/docs/developer-guide/contracts/interfaces/callbacks/IAmmalgamCallee.sol/interface.IBorrowCallback.md b/docs/developer-guide/contracts/interfaces/callbacks/IAmmalgamCallee.sol/interface.IBorrowCallback.md index d0f03544..b08e6382 100644 --- a/docs/developer-guide/contracts/interfaces/callbacks/IAmmalgamCallee.sol/interface.IBorrowCallback.md +++ b/docs/developer-guide/contracts/interfaces/callbacks/IAmmalgamCallee.sol/interface.IBorrowCallback.md @@ -1,5 +1,5 @@ # IBorrowCallback -[Git Source](https://github.com/Ammalgam-Protocol/core-v1/blob/2b185eab2df708b55f7ffa534655c69f626e73b3/contracts/interfaces/callbacks/IAmmalgamCallee.sol) +[Git Source](https://github.com/Ammalgam-Protocol/core-v1/blob/ec51218155bd2f8c1e5dc761ed4728baae81a01b/contracts/interfaces/callbacks/IAmmalgamCallee.sol) ## Functions @@ -24,7 +24,7 @@ function ammalgamBorrowCallV1( |Name|Type|Description| |----|----|-----------| -|`sender`|`address`|| +|`sender`|`address`|The address of the sender initiating the borrow call.| |`amountXAssets`|`uint256`|The amount of token X involved in the borrow.| |`amountYAssets`|`uint256`|The amount of token Y involved in the borrow.| |`amountXShares`|`uint256`|The shares of token X involved in the borrow including the initial lending fee.| @@ -52,7 +52,7 @@ function ammalgamBorrowLiquidityCallV1( |Name|Type|Description| |----|----|-----------| -|`sender`|`address`|| +|`sender`|`address`|The address of the sender initiating the borrow liquidity call.| |`amountXAssets`|`uint256`|The amount of token X involved in the borrow liquidity.| |`amountYAssets`|`uint256`|The amount of token Y involved in the borrow liquidity.| |`amountLShares`|`uint256`|The shares of liquidity involved in the borrow liquidity including the initial lending fee.| diff --git a/docs/developer-guide/contracts/interfaces/callbacks/IAmmalgamCallee.sol/interface.ICallback.md b/docs/developer-guide/contracts/interfaces/callbacks/IAmmalgamCallee.sol/interface.ICallback.md index 7dda2492..63ce65d5 100644 --- a/docs/developer-guide/contracts/interfaces/callbacks/IAmmalgamCallee.sol/interface.ICallback.md +++ b/docs/developer-guide/contracts/interfaces/callbacks/IAmmalgamCallee.sol/interface.ICallback.md @@ -1,5 +1,5 @@ # ICallback -[Git Source](https://github.com/Ammalgam-Protocol/core-v1/blob/2b185eab2df708b55f7ffa534655c69f626e73b3/contracts/interfaces/callbacks/IAmmalgamCallee.sol) +[Git Source](https://github.com/Ammalgam-Protocol/core-v1/blob/ec51218155bd2f8c1e5dc761ed4728baae81a01b/contracts/interfaces/callbacks/IAmmalgamCallee.sol) **Inherits:** [ISwapCallback](/docs/developer-guide/contracts/interfaces/callbacks/IAmmalgamCallee.sol/interface.ISwapCallback.md), [IBorrowCallback](/docs/developer-guide/contracts/interfaces/callbacks/IAmmalgamCallee.sol/interface.IBorrowCallback.md) diff --git a/docs/developer-guide/contracts/interfaces/callbacks/IAmmalgamCallee.sol/interface.ISwapCallback.md b/docs/developer-guide/contracts/interfaces/callbacks/IAmmalgamCallee.sol/interface.ISwapCallback.md index d6519fa9..161d4882 100644 --- a/docs/developer-guide/contracts/interfaces/callbacks/IAmmalgamCallee.sol/interface.ISwapCallback.md +++ b/docs/developer-guide/contracts/interfaces/callbacks/IAmmalgamCallee.sol/interface.ISwapCallback.md @@ -1,5 +1,5 @@ # ISwapCallback -[Git Source](https://github.com/Ammalgam-Protocol/core-v1/blob/2b185eab2df708b55f7ffa534655c69f626e73b3/contracts/interfaces/callbacks/IAmmalgamCallee.sol) +[Git Source](https://github.com/Ammalgam-Protocol/core-v1/blob/ec51218155bd2f8c1e5dc761ed4728baae81a01b/contracts/interfaces/callbacks/IAmmalgamCallee.sol) *This interface should be implemented by anyone wishing to use callbacks in the `swap`, `borrow`, and `borrowLiquidity` functions in the IAmmalgamPair interface.* diff --git a/docs/developer-guide/contracts/interfaces/callbacks/ITransferValidator.sol/interface.ITransferValidator.md b/docs/developer-guide/contracts/interfaces/callbacks/ITransferValidator.sol/interface.ITransferValidator.md index 5dd7fcee..4480f666 100644 --- a/docs/developer-guide/contracts/interfaces/callbacks/ITransferValidator.sol/interface.ITransferValidator.md +++ b/docs/developer-guide/contracts/interfaces/callbacks/ITransferValidator.sol/interface.ITransferValidator.md @@ -1,5 +1,5 @@ # ITransferValidator -[Git Source](https://github.com/Ammalgam-Protocol/core-v1/blob/2b185eab2df708b55f7ffa534655c69f626e73b3/contracts/interfaces/callbacks/ITransferValidator.sol) +[Git Source](https://github.com/Ammalgam-Protocol/core-v1/blob/ec51218155bd2f8c1e5dc761ed4728baae81a01b/contracts/interfaces/callbacks/ITransferValidator.sol) This interface is intended for validating the solvency of an account when transfers occur. @@ -25,3 +25,26 @@ function validateOnUpdate(address validate, address update, bool alwaysUpdate) e |`alwaysUpdate`|`bool`|Whether to always update the saturation, even if the account is not borrowing| +### tokens + +Return the IAmmalgamERC20 token corresponding to the token type + + +```solidity +function tokens( + uint256 tokenType +) external view returns (IAmmalgamERC20); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`tokenType`|`uint256`|The type of token for which the scaler is being computed. Can be one of BORROW_X, DEPOSIT_X, BORROW_Y, DEPOSIT_Y, BORROW_L, or DEPOSIT_L.| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`IAmmalgamERC20`|The IAmmalgamERC20 token| + + diff --git a/docs/developer-guide/contracts/interfaces/factories/IAmmalgamFactory.sol/interface.IAmmalgamFactory.md b/docs/developer-guide/contracts/interfaces/factories/IAmmalgamFactory.sol/interface.IAmmalgamFactory.md index 56841a14..c794e8e0 100644 --- a/docs/developer-guide/contracts/interfaces/factories/IAmmalgamFactory.sol/interface.IAmmalgamFactory.md +++ b/docs/developer-guide/contracts/interfaces/factories/IAmmalgamFactory.sol/interface.IAmmalgamFactory.md @@ -1,5 +1,5 @@ # IAmmalgamFactory -[Git Source](https://github.com/Ammalgam-Protocol/core-v1/blob/2b185eab2df708b55f7ffa534655c69f626e73b3/contracts/interfaces/factories/IAmmalgamFactory.sol) +[Git Source](https://github.com/Ammalgam-Protocol/core-v1/blob/ec51218155bd2f8c1e5dc761ed4728baae81a01b/contracts/interfaces/factories/IAmmalgamFactory.sol) **Inherits:** [IFactoryCallback](/docs/developer-guide/contracts/interfaces/factories/IFactoryCallback.sol/interface.IFactoryCallback.md), [IBeaconCallback](/docs/developer-guide/contracts/interfaces/factories/IAmmalgamFactory.sol/interface.IBeaconCallback.md) diff --git a/docs/developer-guide/contracts/interfaces/factories/IAmmalgamFactory.sol/interface.IBeaconCallback.md b/docs/developer-guide/contracts/interfaces/factories/IAmmalgamFactory.sol/interface.IBeaconCallback.md index 21404d6c..2a407cc3 100644 --- a/docs/developer-guide/contracts/interfaces/factories/IAmmalgamFactory.sol/interface.IBeaconCallback.md +++ b/docs/developer-guide/contracts/interfaces/factories/IAmmalgamFactory.sol/interface.IBeaconCallback.md @@ -1,5 +1,5 @@ # IBeaconCallback -[Git Source](https://github.com/Ammalgam-Protocol/core-v1/blob/2b185eab2df708b55f7ffa534655c69f626e73b3/contracts/interfaces/factories/IAmmalgamFactory.sol) +[Git Source](https://github.com/Ammalgam-Protocol/core-v1/blob/ec51218155bd2f8c1e5dc761ed4728baae81a01b/contracts/interfaces/factories/IAmmalgamFactory.sol) ## Functions diff --git a/docs/developer-guide/contracts/interfaces/factories/IFactoryCallback.sol/interface.IFactoryCallback.md b/docs/developer-guide/contracts/interfaces/factories/IFactoryCallback.sol/interface.IFactoryCallback.md index 832f69ae..37ff89d7 100644 --- a/docs/developer-guide/contracts/interfaces/factories/IFactoryCallback.sol/interface.IFactoryCallback.md +++ b/docs/developer-guide/contracts/interfaces/factories/IFactoryCallback.sol/interface.IFactoryCallback.md @@ -1,5 +1,5 @@ # IFactoryCallback -[Git Source](https://github.com/Ammalgam-Protocol/core-v1/blob/2b185eab2df708b55f7ffa534655c69f626e73b3/contracts/interfaces/factories/IFactoryCallback.sol) +[Git Source](https://github.com/Ammalgam-Protocol/core-v1/blob/ec51218155bd2f8c1e5dc761ed4728baae81a01b/contracts/interfaces/factories/IFactoryCallback.sol) This interface provides methods for getting the token factory configuration. diff --git a/docs/developer-guide/contracts/interfaces/factories/ITokenFactory.sol/interface.ITokenFactory.md b/docs/developer-guide/contracts/interfaces/factories/ITokenFactory.sol/interface.ITokenFactory.md index 44db468d..d2115516 100644 --- a/docs/developer-guide/contracts/interfaces/factories/ITokenFactory.sol/interface.ITokenFactory.md +++ b/docs/developer-guide/contracts/interfaces/factories/ITokenFactory.sol/interface.ITokenFactory.md @@ -1,5 +1,5 @@ # ITokenFactory -[Git Source](https://github.com/Ammalgam-Protocol/core-v1/blob/2b185eab2df708b55f7ffa534655c69f626e73b3/contracts/interfaces/factories/ITokenFactory.sol) +[Git Source](https://github.com/Ammalgam-Protocol/core-v1/blob/ec51218155bd2f8c1e5dc761ed4728baae81a01b/contracts/interfaces/factories/ITokenFactory.sol) ## Functions diff --git a/docs/developer-guide/contracts/interfaces/tokens/IAmmalgamERC20.sol/interface.IAmmalgamERC20.md b/docs/developer-guide/contracts/interfaces/tokens/IAmmalgamERC20.sol/interface.IAmmalgamERC20.md index 39383c87..8d0c0c68 100644 --- a/docs/developer-guide/contracts/interfaces/tokens/IAmmalgamERC20.sol/interface.IAmmalgamERC20.md +++ b/docs/developer-guide/contracts/interfaces/tokens/IAmmalgamERC20.sol/interface.IAmmalgamERC20.md @@ -1,5 +1,5 @@ # IAmmalgamERC20 -[Git Source](https://github.com/Ammalgam-Protocol/core-v1/blob/2b185eab2df708b55f7ffa534655c69f626e73b3/contracts/interfaces/tokens/IAmmalgamERC20.sol) +[Git Source](https://github.com/Ammalgam-Protocol/core-v1/blob/ec51218155bd2f8c1e5dc761ed4728baae81a01b/contracts/interfaces/tokens/IAmmalgamERC20.sol) **Inherits:** IERC20, IERC20Metadata, IERC20Permit diff --git a/docs/developer-guide/contracts/interfaces/tokens/IERC20DebtToken.sol/interface.IERC20DebtToken.md b/docs/developer-guide/contracts/interfaces/tokens/IERC20DebtToken.sol/interface.IERC20DebtToken.md index c77dd330..3446beb1 100644 --- a/docs/developer-guide/contracts/interfaces/tokens/IERC20DebtToken.sol/interface.IERC20DebtToken.md +++ b/docs/developer-guide/contracts/interfaces/tokens/IERC20DebtToken.sol/interface.IERC20DebtToken.md @@ -1,5 +1,5 @@ # IERC20DebtToken -[Git Source](https://github.com/Ammalgam-Protocol/core-v1/blob/2b185eab2df708b55f7ffa534655c69f626e73b3/contracts/interfaces/tokens/IERC20DebtToken.sol) +[Git Source](https://github.com/Ammalgam-Protocol/core-v1/blob/ec51218155bd2f8c1e5dc761ed4728baae81a01b/contracts/interfaces/tokens/IERC20DebtToken.sol) **Inherits:** [IAmmalgamERC20](/docs/developer-guide/contracts/interfaces/tokens/IAmmalgamERC20.sol/interface.IAmmalgamERC20.md) diff --git a/docs/developer-guide/contracts/interfaces/tokens/IHookRegistry.sol/interface.IHookRegistry.md b/docs/developer-guide/contracts/interfaces/tokens/IHookRegistry.sol/interface.IHookRegistry.md index e9e8be77..c3bedf1d 100644 --- a/docs/developer-guide/contracts/interfaces/tokens/IHookRegistry.sol/interface.IHookRegistry.md +++ b/docs/developer-guide/contracts/interfaces/tokens/IHookRegistry.sol/interface.IHookRegistry.md @@ -1,5 +1,5 @@ # IHookRegistry -[Git Source](https://github.com/Ammalgam-Protocol/core-v1/blob/2b185eab2df708b55f7ffa534655c69f626e73b3/contracts/interfaces/tokens/IHookRegistry.sol) +[Git Source](https://github.com/Ammalgam-Protocol/core-v1/blob/ec51218155bd2f8c1e5dc761ed4728baae81a01b/contracts/interfaces/tokens/IHookRegistry.sol) ## Functions diff --git a/docs/developer-guide/contracts/interfaces/tokens/ITokenController.sol/constants.ITokenController.md b/docs/developer-guide/contracts/interfaces/tokens/ITokenController.sol/constants.ITokenController.md index 4dfba71e..21982fae 100644 --- a/docs/developer-guide/contracts/interfaces/tokens/ITokenController.sol/constants.ITokenController.md +++ b/docs/developer-guide/contracts/interfaces/tokens/ITokenController.sol/constants.ITokenController.md @@ -1,5 +1,5 @@ # Constants -[Git Source](https://github.com/Ammalgam-Protocol/core-v1/blob/2b185eab2df708b55f7ffa534655c69f626e73b3/contracts/interfaces/tokens/ITokenController.sol) +[Git Source](https://github.com/Ammalgam-Protocol/core-v1/blob/ec51218155bd2f8c1e5dc761ed4728baae81a01b/contracts/interfaces/tokens/ITokenController.sol) ### DEPOSIT_L diff --git a/docs/developer-guide/contracts/interfaces/tokens/ITokenController.sol/interface.ITokenController.md b/docs/developer-guide/contracts/interfaces/tokens/ITokenController.sol/interface.ITokenController.md index 85f1e34c..c49113a6 100644 --- a/docs/developer-guide/contracts/interfaces/tokens/ITokenController.sol/interface.ITokenController.md +++ b/docs/developer-guide/contracts/interfaces/tokens/ITokenController.sol/interface.ITokenController.md @@ -1,5 +1,5 @@ # ITokenController -[Git Source](https://github.com/Ammalgam-Protocol/core-v1/blob/2b185eab2df708b55f7ffa534655c69f626e73b3/contracts/interfaces/tokens/ITokenController.sol) +[Git Source](https://github.com/Ammalgam-Protocol/core-v1/blob/ec51218155bd2f8c1e5dc761ed4728baae81a01b/contracts/interfaces/tokens/ITokenController.sol) The interface of a ERC20 facade for multiple token types with functionality similar to ERC1155. @@ -199,7 +199,8 @@ event BurnBadDebt(address indexed borrower, uint256 indexed tokenType, uint256 b ```solidity event InterestAccrued( - uint112 depositLAssets, + uint256 reserveXAssets, + uint256 reserveYAssets, uint112 depositXAssets, uint112 depositYAssets, uint112 borrowLAssets, @@ -212,10 +213,20 @@ event InterestAccrued( |Name|Type|Description| |----|----|-----------| -|`depositLAssets`|`uint112`|The amount of total `DEPOSIT_L` assets in the pool after interest accrual| +|`reserveXAssets`|`uint256`|The amount reserve X assets in the pool after interest accrual| +|`reserveYAssets`|`uint256`|The amount reserve Y assets in the pool after interest accrual| |`depositXAssets`|`uint112`|The amount of total `DEPOSIT_X` assets in the pool after interest accrual| |`depositYAssets`|`uint112`|The amount of total `DEPOSIT_Y` assets in the pool after interest accrual| |`borrowLAssets`|`uint112`|The amount of total `BORROW_L` assets in the pool after interest accrual| |`borrowXAssets`|`uint112`|The amount of total `BORROW_X` assets in the pool after interest accrual| |`borrowYAssets`|`uint112`|The amount of total `BORROW_Y` assets in the pool after interest accrual| +## Errors +### FragileLiquidityExceedsActiveLiquidity +Reverts when fragile liquidity exceeds active liquidity available for risk checks. + + +```solidity +error FragileLiquidityExceedsActiveLiquidity(); +``` + diff --git a/docs/developer-guide/contracts/libraries/Convert.sol/library.Convert.md b/docs/developer-guide/contracts/libraries/Convert.sol/library.Convert.md index ecb9c701..8b174b9a 100644 --- a/docs/developer-guide/contracts/libraries/Convert.sol/library.Convert.md +++ b/docs/developer-guide/contracts/libraries/Convert.sol/library.Convert.md @@ -1,5 +1,5 @@ # Convert -[Git Source](https://github.com/Ammalgam-Protocol/core-v1/blob/2b185eab2df708b55f7ffa534655c69f626e73b3/contracts/libraries/Convert.sol) +[Git Source](https://github.com/Ammalgam-Protocol/core-v1/blob/ec51218155bd2f8c1e5dc761ed4728baae81a01b/contracts/libraries/Convert.sol) ## Functions diff --git a/docs/developer-guide/contracts/libraries/GeometricTWAP.sol/library.GeometricTWAP.md b/docs/developer-guide/contracts/libraries/GeometricTWAP.sol/library.GeometricTWAP.md index 0c5cc002..8d5ca1af 100644 --- a/docs/developer-guide/contracts/libraries/GeometricTWAP.sol/library.GeometricTWAP.md +++ b/docs/developer-guide/contracts/libraries/GeometricTWAP.sol/library.GeometricTWAP.md @@ -1,5 +1,5 @@ # GeometricTWAP -[Git Source](https://github.com/Ammalgam-Protocol/core-v1/blob/2b185eab2df708b55f7ffa534655c69f626e73b3/contracts/libraries/GeometricTWAP.sol) +[Git Source](https://github.com/Ammalgam-Protocol/core-v1/blob/ec51218155bd2f8c1e5dc761ed4728baae81a01b/contracts/libraries/GeometricTWAP.sol) ## State Variables @@ -43,7 +43,7 @@ Minimum long-term interval factor is used to verify the long-term interval is at least 14 times the mid-term interval. This ensures that the long term interval is required to be at least 14 times the mid-term interval, this is ```math -\left \lceil \frac{2 * MID\_TERM\_ARRAY\_LAST\_INDEX}{LONG\_TERM\_ARRAY\_LAST\_INDEX} \right \rceil. +\left \lceil \frac{2 * MID\_TERM\_ARRAY\_LAST\_INDEX}`LONG\_TERM\_ARRAY\_LAST\_INDEX` \right \rceil. ``` @@ -225,8 +225,7 @@ function getObservedTicks( ```solidity function getObservedMidTermTick( - Observations storage self, - bool isLongTermBufferInitialized + Observations storage self ) internal view returns (int16 midTermTick); ``` **Parameters** @@ -234,7 +233,6 @@ function getObservedMidTermTick( |Name|Type|Description| |----|----|-----------| |`self`|`Observations`|The observation struct.| -|`isLongTermBufferInitialized`|`bool`|Boolean value which represents whether long-term buffer is filled or not.| **Returns** @@ -380,42 +378,6 @@ function getLendingStateTick( |``|`int56`|currentCumulativeSum The current cumulative sum for the last updated timestamp.| -### calculateLendingStateTick - -Computes the lending state tick based on the cumulative sum and duration. - -*If no time has passed since the last lending timestamp, it returns the last lending state tick.* - - -```solidity -function calculateLendingStateTick( - int56 cumulativeSum, - int56 previousCumulativeSum, - uint32 timeElapsedSinceLendingUpdate -) private pure returns (int16); -``` -**Parameters** - -|Name|Type|Description| -|----|----|-----------| -|`cumulativeSum`|`int56`|The current cumulative sum of mid-term values.| -|`previousCumulativeSum`|`int56`|The previous cumulative sum recorded for lending.| -|`timeElapsedSinceLendingUpdate`|`uint32`|time elapsed since the last lending state update.| - -**Returns** - -|Name|Type|Description| -|----|----|-----------| -|``|`int16`|lendingStateTick The computed or fallback lending state tick.| - - -### setLendingState - - -```solidity -function setLendingState(Observations storage self, int16 lendingStateTick, int56 currentCumulativeSum) private; -``` - ### setObservationData Updates the observation data with the new tick value and current timestamp. @@ -559,21 +521,6 @@ function calculateTickAverageTowardsMidTerm(int256 midTermTick, int256 newTick) |``|`int16`|The calculated average tick value| -## Events -### UpdateLendingTick -*Emitted when `lendingStateTick` is updated* - - -```solidity -event UpdateLendingTick(int16 lendingStateTick); -``` - -**Parameters** - -|Name|Type|Description| -|----|----|-----------| -|`lendingStateTick`|`int16`|The updated value for lending state tick| - ## Errors ### InvalidIntervalConfig @@ -596,7 +543,6 @@ struct Observations { uint8 midTermIndex; uint8 longTermIndex; int16 lastTick; - int16 lastLendingStateTick; uint24 midTermIntervalConfig; uint24 longTermIntervalConfig; int56 lendingCumulativeSum; diff --git a/docs/developer-guide/contracts/libraries/Interest.sol/library.Interest.md b/docs/developer-guide/contracts/libraries/Interest.sol/library.Interest.md index f3d19359..d76ede46 100644 --- a/docs/developer-guide/contracts/libraries/Interest.sol/library.Interest.md +++ b/docs/developer-guide/contracts/libraries/Interest.sol/library.Interest.md @@ -1,5 +1,5 @@ # Interest -[Git Source](https://github.com/Ammalgam-Protocol/core-v1/blob/2b185eab2df708b55f7ffa534655c69f626e73b3/contracts/libraries/Interest.sol) +[Git Source](https://github.com/Ammalgam-Protocol/core-v1/blob/ec51218155bd2f8c1e5dc761ed4728baae81a01b/contracts/libraries/Interest.sol) This library is used for calculating and accruing interest. diff --git a/docs/developer-guide/contracts/libraries/Liquidation.sol/library.Liquidation.md b/docs/developer-guide/contracts/libraries/Liquidation.sol/library.Liquidation.md index 670ab145..e576df04 100644 --- a/docs/developer-guide/contracts/libraries/Liquidation.sol/library.Liquidation.md +++ b/docs/developer-guide/contracts/libraries/Liquidation.sol/library.Liquidation.md @@ -1,5 +1,5 @@ # Liquidation -[Git Source](https://github.com/Ammalgam-Protocol/core-v1/blob/2b185eab2df708b55f7ffa534655c69f626e73b3/contracts/libraries/Liquidation.sol) +[Git Source](https://github.com/Ammalgam-Protocol/core-v1/blob/ec51218155bd2f8c1e5dc761ed4728baae81a01b/contracts/libraries/Liquidation.sol) ## State Variables @@ -45,13 +45,22 @@ uint256 private constant POSITIVE_PREMIUM_INTERCEPT_IN_BIPS = 4444; ``` -### LEVERAGE_LIQUIDATION_BREAK_EVEN_FACTOR -The factor to controls the pace of the increase in the premium the leverage -liquidation premium function. +### LEVERAGE_LIQUIDATION_BREAK_EVEN_FACTOR_MAG2 +This factor brings a leveraged position just below the leverage liquidation threshold ```solidity -uint256 private constant LEVERAGE_LIQUIDATION_BREAK_EVEN_FACTOR = 5; +uint256 internal constant LEVERAGE_LIQUIDATION_BREAK_EVEN_FACTOR_MAG2 = 10; +``` + + +### LEVERAGE_LIQUIDATION_FACTOR +Leverage liquidation factor derived from max allowed leverage scaled by the break-even factor + + +```solidity +uint256 internal constant LEVERAGE_LIQUIDATION_FACTOR = + ALLOWED_LIQUIDITY_LEVERAGE * MAG2 / LEVERAGE_LIQUIDATION_BREAK_EVEN_FACTOR_MAG2; ``` @@ -114,7 +123,6 @@ function checkHardPremiums( ```solidity function calculateNetDebtAndSeizedDeposits( uint256[6] memory proposedLiquidation, - uint256 activeLiquidityScalerInQ72, uint256 sqrtPriceMinInQ72, uint256 sqrtPriceMaxInQ72 ) internal pure returns (uint256 netDebtInLAssets, uint256 netCollateralInLAssets, bool netDebtX); @@ -127,61 +135,83 @@ function calculateNetDebtAndSeizedDeposits( function checkSaturationPremiums( ISaturationAndGeometricTWAPState saturationAndGeometricTWAPState, Validation.InputParams memory inputParams, - address borrower, - uint256 depositLToTransferInLAssets, - uint256 depositXToTransferInXAssets, - uint256 depositYToTransferInYAssets -) external view; + address borrower +) external view returns (uint256 seizeLAssets, uint256 seizeXAssets, uint256 seizeYAssets); ``` ### liquidateLeverageCalcDeltaAndPremium -Calculate the amount to be closed (from both deposit and borrow) and premium to be -paid. The formula for the premium is calculated with the average net borrow of X and Y -$$B$$ and the net deposit of X and Y $$B$$ and a scaler $$S$$ that sets the pace at which -the premium increased, in code we call this `LEVERAGE_LIQUIDATION_BREAK_EVEN_FACTOR`, and -allowed leverage $$AL$$, `ALLOWED_LIQUIDITY_LEVERAGE`: +Calculate weighted leverage liquidation repayments and seized deposits. + +*The first three return indices are seized deposits, the last three are required +repayments, and all values are in each token's native units. The formula for the premium +is calculated with the average net borrow of X and Y $$B$$ and the net deposit of X and Y +$$D$$ and a scaler $$S$$ that sets the pace at which the premium increased, in code we +call this `LEVERAGE_LIQUIDATION_BREAK_EVEN_FACTOR_MAG2`, and allowed leverage $$AL$$, +`ALLOWED_LIQUIDITY_LEVERAGE`: ```math premium = \begin{cases} S \left( -\frac{B}{D} -- \frac{AL - 1}{AL} +\frac`B``D` +- \frac`AL - 1``AL` \right) -\text { if } \frac{B}{D} > -\frac{AL - 1}{AL} \\ +\text { if } \frac`B``D` > +\frac`AL - 1``AL` \\ 0 \text { otherwise } \end{cases} ``` -This can be visualized [here](https://www.desmos.com/calculator/slheqlelvu). +This can be visualized [here](https://www.desmos.com/calculator/1cd55f1yhz). The premium is a percentage of the total deposit. If the premium is low enough, then we we attempt to deleverage the position such that the premium and closed part of the position leaves it under the leveraged threshold. If this is not possible, then all of the users deposit will be transferred to the liquidator and there will be bad debt. Note that the de leveraging relies on the min and max tick to be equal, so the result may not be a valid amount of leverage using a min and max price as is done in the Validation -library. +library.* ```solidity function liquidateLeverageCalcDeltaAndPremium( - Validation.InputParams memory inputParams, - bool depositXAndY, - bool repayXAndY -) external pure returns (LeveragedLiquidationParams memory leveragedLiquidationParams); + Validation.InputParams memory inputParams +) external pure returns (uint256[6] memory leveragedLiquidationParams, bool badDebt); ``` **Parameters** |Name|Type|Description| |----|----|-----------| |`inputParams`|`Validation.InputParams`|The params representing the position of the borrower.| -|`depositXAndY`|`bool`|Flag indicating whether the liquidator is taking deposit of X and Y.| -|`repayXAndY`|`bool`|Flag indicating whether the liquidator is repaying borrow of X and Y.| **Returns** |Name|Type|Description| |----|----|-----------| -|`leveragedLiquidationParams`|`LeveragedLiquidationParams`|a struct of type LeveragedLiquidationParams containing the amounts to be closed and the premium to be paid.| +|`leveragedLiquidationParams`|`uint256[6]`|Array indexed by DEPOSIT_L, DEPOSIT_X, DEPOSIT_Y, BORROW_L, BORROW_X, BORROW_Y.| +|`badDebt`|`bool`|Whether the leverage liquidation leaves bad debt to burn.| + + +### calculateLeverageLiquidationAsset + +Calculate the amount of an asset to be liquidated in a leverage liquidation. + +*we use the min so amounts don't exceed balances* + + +```solidity +function calculateLeverageLiquidationAsset( + uint256 userAsset, + uint256 totalShareLAsset, + uint256 totalLAsset, + bool rounding +) internal pure returns (uint256); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`userAsset`|`uint256`|The amount of the asset held by the user.| +|`totalShareLAsset`|`uint256`|The portion getting seized or repaid in L assets, or fraction of the total borrowed l or deposited l respectively.| +|`totalLAsset`|`uint256`|The total borrowed l or deposited l respectively.| +|`rounding`|`bool`|Whether to round up the result, we round up for the borrow legs to make sure enough is repaid to cover the seized deposits.| ### calcHardMaxPremiumInBips @@ -195,7 +225,6 @@ Calculate the maximum premium the liquidator may receive given the LTV of the bo function calcHardMaxPremiumInBips( uint256[6] memory validatedLiquidation, uint256 activeLiquidityAssets, - uint256 activeLiquidityScalerInQ72, uint256 sqrtPriceMinInQ72, uint256 sqrtPriceMaxInQ72 ) internal pure returns (uint256 maxPremiumInBips); @@ -268,36 +297,17 @@ function convertLtvToPremium( |`maxPremiumInBips`|`uint256`|The maximum premium for the liquidator.| -### calcSaturationPremiumBips - -Calculate the premium the saturation liquidator is receiving given the borrowers deposit and the depositToTransfer to the liquidator. -The end premium is the max of the premiums in L, X, Y -If no saturation liq is requested (liquidationParams.saturationDepositLToBeTransferred==liquidationParams.saturationDepositXToBeTransferred==liquidationParams.saturationDepositYToBeTransferred==0), the premium will be 0 +### calcSaturationSeizedAssets ```solidity -function calcSaturationPremiumBips( - Validation.InputParams memory inputParams, - uint256 depositLToTransferInLAssets, - uint256 depositXToTransferInXAssets, - uint256 depositYToTransferInYAssets -) internal pure returns (uint256 premiumInBips); +function calcSaturationSeizedAssets( + uint256 depositedLAssets, + uint256 depositedXAssets, + uint256 depositedYAssets, + uint256 premiumInBips +) internal pure returns (uint256 seizedLAssets, uint256 seizedXAssets, uint256 seizedYAssets); ``` -**Parameters** - -|Name|Type|Description| -|----|----|-----------| -|`inputParams`|`Validation.InputParams`|The params containing the position of the borrower.| -|`depositLToTransferInLAssets`|`uint256`|| -|`depositXToTransferInXAssets`|`uint256`|| -|`depositYToTransferInYAssets`|`uint256`|| - -**Returns** - -|Name|Type|Description| -|----|----|-----------| -|`premiumInBips`|`uint256`|The premium being received by the liquidator.| - ### calcSaturationMaxPremiumInBips @@ -334,6 +344,12 @@ function calcSaturationMaxPremiumInBips( error LiquidationPremiumTooHigh(); ``` +### LiquidationZeroPremium + +```solidity +error LiquidationZeroPremium(); +``` + ### NotEnoughRepaidForLiquidation ```solidity @@ -352,18 +368,3 @@ error TooMuchDepositToTransferForLeverageLiquidation(); error LiquidationMutation(); ``` -## Structs -### LeveragedLiquidationParams - -```solidity -struct LeveragedLiquidationParams { - uint256 closeInLAssets; - uint256 closeInXAssets; - uint256 closeInYAssets; - uint256 premiumInLAssets; - uint256 premiumLInXAssets; - uint256 premiumLInYAssets; - bool badDebt; -} -``` - diff --git a/docs/developer-guide/contracts/libraries/PartialLiquidations.sol/library.PartialLiquidations.md b/docs/developer-guide/contracts/libraries/PartialLiquidations.sol/library.PartialLiquidations.md index 77d125ee..d0329cfb 100644 --- a/docs/developer-guide/contracts/libraries/PartialLiquidations.sol/library.PartialLiquidations.md +++ b/docs/developer-guide/contracts/libraries/PartialLiquidations.sol/library.PartialLiquidations.md @@ -1,38 +1,56 @@ # PartialLiquidations -[Git Source](https://github.com/Ammalgam-Protocol/core-v1/blob/2b185eab2df708b55f7ffa534655c69f626e73b3/contracts/libraries/PartialLiquidations.sol) +[Git Source](https://github.com/Ammalgam-Protocol/core-v1/blob/ec51218155bd2f8c1e5dc761ed4728baae81a01b/contracts/libraries/PartialLiquidations.sol) We allow liquidations to happen in parts when the position is spread across more than one tranche. These partial liquidations allow the liquidator to specify how many tranches they -are liquidating based on how much they are repaying. Fewer tranches will result in a higher -LTV as they start with the portion of the position closest to the price and move outward. In -most cases, one tranche will be liquidated at once, but in some cases, a sliver of liquidity -in the first tranche may not be worth the cost to liquidate until it and the next tranche have -become profitable to liquidate. -Once we determine the number of tranches of a position they want to liquidate, we mutate the -position getting liquidated to a smaller scaled portion of the initial position. To calculate -the portion of a position, we start with the following requirements: +are liquidating based on how much they are repaying. Smaller slices start with the tranche range +closest to the current price and move outward, so the slice reaches expected LTV before the full +position on the same debt side does. In most cases, one tranche will be liquidated at one time, +but in some cases, a sliver of liquidity in the first tranche may not be worth the cost to +liquidate until it and the next tranche have become profitable to liquidate. +Once we determine the number of tranches to liquidate, we build the liquidated slice from the +debt side first. L uses a weight because both deposit and borrow L can be included together; +the opposing side is then solved directly so the slice lands on the expected liquidation LTV. +A partial liquidation splits the signed position into the liquidated slice and the remaining +position: +```math +P_0=P_\Delta+P_1, +\qquad +P_0=[L_0,X_0,Y_0], +\qquad +P_\Delta=[L_\Delta,X_\Delta,Y_\Delta] +``` +The slice must preserve component signs, must not exceed the original component magnitudes, and +must have exact expected liquidation LTV at the slice square-root price `s_delta`. The whole +position and the remaining position do not need to have the same LTV as the liquidated slice. +Signed components are net deposits minus borrows: ```math \begin{align} -EXPECTED\_LTV -&= \frac{NET\_BORROW\_0}{NET\_DEPOSIT\_0} = \frac{NET\_BORROW\_1}{NET\_DEPOSIT\_1} -\\ -NET\_BORROW\_0 -&= LIQUIDATED\_BORROW + NET\_BORROW\_1 -\\ -NET\_DEPOSIT\_0 -&= LIQUIDATED\_DEPOSIT + NET\_DEPOSIT\_1 +L_0 &= depositL - borrowL \\ +X_0 &= depositX - borrowX \\ +Y_0 &= depositY - borrowY \end{align} ``` - - -## State Variables -### EXPECTED_SATURATION_LTV_MAG2_INT - -```solidity -int256 internal constant EXPECTED_SATURATION_LTV_MAG2_INT = int256(EXPECTED_SATURATION_LTV_MAG2); +The slice is constructed from the debt-side component first. Throughout this library, `s` is +a square-root price, not a price. At square-root price `s`, X is measured in L as `X / s` and +Y is measured in L as `Y * s`. +Let `k` be the unscaled expected liquidation LTV: +```math +k=EXPECTED\_SATURATION\_LTV +``` +In code, `k` is represented by `EXPECTED_SATURATION_LTV_MAG2 / MAG2`. +In signed slice notation, repaid debt components are negative and seized collateral components +are positive. For net debt X, the exact-LTV slice condition is: +```math +k=\dfrac{-X_\Delta/s_\Delta-L_\Delta}`L_\Delta+Y_\Delta s_\Delta` +``` +The net debt Y equations are symmetric: +```math +k=\dfrac{-Y_\Delta s_\Delta-L_\Delta}`L_\Delta+X_\Delta/s_\Delta` ``` +## State Variables ### MAG2_INT ```solidity @@ -40,16 +58,15 @@ int256 internal constant MAG2_INT = int256(MAG2); ``` -### Q72_INT - -```solidity -int256 internal constant Q72_INT = int256(Q72); -``` - - ## Functions ### calculatePartialLiquidation +Calculates the partial liquidation slice for the tranches covered by the repayment. + +*Returns the full user asset array when every tranche is included. Returns the zero array +when no L-denominated debt is repaid. The tranche count is chosen from absolute +`satInLAssets`, while the slice geometry uses the corresponding relative saturation values.* + ```solidity function calculatePartialLiquidation( @@ -62,9 +79,49 @@ function calculatePartialLiquidation( bool netDebtX ) internal pure returns (uint256[6] memory liquidation); ``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`satPairPerTranche`|`Saturation.SaturationPair[]`|Saturation entries for the borrower, ordered from the end of liquidation toward the start of liquidation.| +|`lastTranche`|`int16`|Last tranche occupied by the borrower in the liquidation direction.| +|`userAssets`|`uint256[6]`|Borrower assets in `[depositL, depositX, depositY, borrowL, borrowX, borrowY]` order.| +|`activeLiquidityAssets`|`uint256`|Active liquidity used to scale tranche saturation.| +|`netRepaidLAssets`|`uint256`|Net debt repaid by the liquidator, denominated in L.| +|`netSeizedLAssets`|`uint256`|Net collateral seized by the liquidator, denominated in L.| +|`netDebtX`|`bool`|Whether the liquidation repays net X debt. If false, it repays net Y debt.| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|`liquidation`|`uint256[6]`|Component-bounded asset amounts to remove from the borrower.| + ### calcMutation +Builds a liquidation slice from raw tranche-boundary and saturation inputs. +It derives the target square-root price and asset weights from the same saturation window, +applies L through a shared weight, then solves the deposit-side delta directly from the +exact-LTV equation. +The target slice square-root price is the selected tranche boundary moved by the start +weight from the same saturation walk: +```math +s_\Delta=b^T\sqrt{w_s} +``` +In signed notation, the debt-side slice then fixes one raw borrow amount: +```math +X_\Delta=-borrowX\cdot w_X +\qquad \text{for net debt X} +``` +```math +Y_\Delta=-borrowY\cdot w_Y +\qquad \text{for net debt Y} +``` +L is selected next. The remaining side is solved last from the exact-LTV equation and may be +either collateral seized or same-side borrow repaid, depending on the sign of the solved +delta. + ```solidity function calcMutation( @@ -74,20 +131,186 @@ function calcMutation( uint256 totalSaturation, uint256 activeLiquidityAssets, bool netDebtX -) private pure returns (uint256[6] memory); +) internal pure returns (uint256[6] memory liquidation); ``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`userAssets`|`uint256[6]`|Borrower assets in `[depositL, depositX, depositY, borrowL, borrowX, borrowY]` order.| +|`trancheBoundarySqrtPriceQ72`|`uint256`|Boundary sqrt price for the tranche adjacent to the included slice.| +|`partialSaturation`|`uint256`|Relative saturation included in the partial liquidation.| +|`totalSaturation`|`uint256`|Total relative borrower saturation across all tranches.| +|`activeLiquidityAssets`|`uint256`|Active liquidity used to scale tranche saturation.| +|`netDebtX`|`bool`|Whether the debt side is X. If false, the debt side is Y.| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|`liquidation`|`uint256[6]`|Component-bounded asset amounts to remove from the borrower.| + + +### applyLMutation + +Applies the L weight to both L legs and returns the resulting signed L delta. +The raw L legs are both included at the same weight: +```math +depositL_\Delta=depositL\cdot w_L,\qquad borrowL_\Delta=borrowL\cdot w_L +``` +The signed L contribution is: +```math +L_\Delta=depositL_\Delta-borrowL_\Delta +``` + + +```solidity +function applyLMutation( + uint256[6] memory liquidation, + uint256[6] memory userAssets, + uint256 lWeightQ72 +) private pure returns (int256 lDelta); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`liquidation`|`uint256[6]`|Liquidation array being built.| +|`userAssets`|`uint256[6]`|Borrower assets in `[depositL, depositX, depositY, borrowL, borrowX, borrowY]` order.| +|`lWeightQ72`|`uint256`|Q72 weight to apply to deposit L and borrow L.| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|`lDelta`|`int256`|Signed L contribution of the liquidated slice.| + + +### calcDebtSideWeightQ72 + +Calculates the saturation-derived weight for the debt-side borrow asset. +The selected debt-side weight is: +```math +w_{debt}= +\begin{cases} +w_X & \text{if net debt X} \\ +w_Y & \text{if net debt Y} +\end{cases} +``` + + +```solidity +function calcDebtSideWeightQ72( + uint256 sqrtStartWeightQ72, + uint256 sqrtEndWeightQ72, + bool netDebtX +) private pure returns (uint256 debtSideWeightQ72); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`sqrtStartWeightQ72`|`uint256`|Start sqrt weight of the included saturation window.| +|`sqrtEndWeightQ72`|`uint256`|End sqrt weight of the included saturation window.| +|`netDebtX`|`bool`|Whether the debt side is X. If false, the debt side is Y.| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|`debtSideWeightQ72`|`uint256`|Q72 weight applied to the debt-side borrow amount.| + + +### applyRemainingSideDelta + +Applies the signed remaining-side delta to the matching deposit or borrow leg. +Positive deltas seize remaining-side collateral. Negative deltas repay borrow on that side. +Partial borrow repayment is valid as long as it is not greater than the starting borrow. +```math +R_\Delta>0 \Rightarrow deposit_\Delta=\min(R_\Delta, deposit) +``` +```math +R_\Delta<0 \Rightarrow borrow_\Delta=\min(-R_\Delta, borrow) +``` + + +```solidity +function applyRemainingSideDelta( + uint256[6] memory liquidation, + uint256[6] memory userAssets, + int256 remainingSideDelta, + uint256 depositIndex, + uint256 borrowIndex +) private pure; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`liquidation`|`uint256[6]`|Liquidation array being built.| +|`userAssets`|`uint256[6]`|Borrower assets in `[depositL, depositX, depositY, borrowL, borrowX, borrowY]` order.| +|`remainingSideDelta`|`int256`|Signed amount for the side opposite the fixed debt-side borrow.| +|`depositIndex`|`uint256`|Deposit token index for the remaining side.| +|`borrowIndex`|`uint256`|Borrow token index for the remaining side.| -### calcXWeightQ72 -calculates partial liquidation weight for asset X. +### calcRemainingSideDelta -*formulas for w_X derived from: +Solves the signed remaining-side delta for the fixed debt-side repayment. +The returned delta is positive when the slice must seize deposit-side collateral and +negative when it must repay borrow on that side to land on expected LTV. +For net debt X, define the fixed X-side debt value in L-units: +```math +debtSideValueInL=-\frac`X_\Delta`{s_\Delta}=\frac{borrowX_\Delta}{s_\Delta} +``` +Then: +```math +Y_\Delta=\dfrac{debtSideValueInL-(1+k)L_\Delta}{ks_\Delta} +``` +For net debt Y, define the fixed Y-side debt value in L-units: +```math +debtSideValueInL=-Y_\Delta s_\Delta=borrowY_\Delta s_\Delta +``` +Then: +```math +X_\Delta=\dfrac{s_\Delta(debtSideValueInL-(1+k)L_\Delta)}{k} +``` + + +```solidity +function calcRemainingSideDelta( + uint256 borrowDelta, + int256 lDelta, + uint256 sqrtPriceQ72, + bool netDebtX +) private pure returns (int256 remainingSideDelta); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`borrowDelta`|`uint256`|Final debt-side borrow amount repaid by the liquidation.| +|`lDelta`|`int256`|Signed L contribution already included in the liquidation.| +|`sqrtPriceQ72`|`uint256`|Target liquidation sqrt price for the slice.| +|`netDebtX`|`bool`|Whether the debt side is X. If false, the debt side is Y.| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|`remainingSideDelta`|`int256`|Signed delta for the remaining side.| + + +### calcXWeightQ72 + +Calculates the partial liquidation weight for asset X. +Formula for `w_X`: ```math w_X &= \large \frac{ 1- \sqrt{w_s} }{ \sqrt{w_e}-\sqrt{w_s} } -```* +``` ```solidity @@ -96,64 +319,136 @@ function calcXWeightQ72( uint256 sqrtEndWeightQ72 ) private pure returns (uint256 xWeightQ72); ``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`sqrtStartWeightQ72`|`uint256`|Q72 start sqrt weight for the included saturation window.| +|`sqrtEndWeightQ72`|`uint256`|Q72 end sqrt weight for the included saturation window.| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|`xWeightQ72`|`uint256`|Q72 weight for asset X.| -### calcYWeightQ72 -calculates partial liquidation weight for asset Y. +### calcYWeightQ72 -*formulas for w_Y derived from: +Calculates the partial liquidation weight for asset Y. +Formula for `w_Y`: ```math \begin{equation} w_Y = \sqrt{w_e} \cdot w_X \end{equation} -```* +``` ```solidity function calcYWeightQ72(uint256 weightXQ72, uint256 sqrtEndWeightQ72) private pure returns (uint256 yWeightQ72); ``` +**Parameters** -### calcLWeightQ72 +|Name|Type|Description| +|----|----|-----------| +|`weightXQ72`|`uint256`|Q72 weight for asset X.| +|`sqrtEndWeightQ72`|`uint256`|Q72 end sqrt weight for the included saturation window.| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|`yWeightQ72`|`uint256`|Q72 weight for asset Y.| -calculates partial liquidation weight for asset L. -*formula for w_L is derived from: +### calcLWeightQ72 + +Calculates the partial liquidation weight for asset L from the debt-side slice. +Net-zero L is omitted. Net-borrow L uses the debt-side weight. Net-deposit L +chooses the lower feasible L endpoint implied by the fixed debt-side repayment. +For net-borrow L: ```math -\begin{equation} -w_L = -- \frac{ -\frac{X_\Delta}{b^{t_1}} -+ EXPECTED\_LTV \cdot Y_\Delta \cdot b^{t_1} -}{ -(EXPECTED\_LTV+1) L_0 -} -\end{equation} +L_\Delta=L_0\cdot w_{debt} +``` +For net-deposit L, L is the free collateral-side variable: +```math +0 \le L_\Delta \le L_0 +``` +Let `debtSideValueInL` be the fixed debt-side value and `remainingCollateralInL` be the +remaining positive deposit-side collateral, both in L-units: +```math +debtSideValueInL= +\begin{cases} +\dfrac{borrowX_\Delta}{s_\Delta} & \text{if net debt X} \\ +borrowY_\Delta s_\Delta & \text{if net debt Y} +\end{cases} +``` +```math +remainingCollateralInL= +\begin{cases} +(depositY-borrowY)s_\Delta & \text{if net debt X and } depositY>borrowY \\ +\dfrac{depositX-borrowX}{s_\Delta} & \text{if net debt Y and } depositX>borrowX \\ +0 & \text{otherwise} +\end{cases} +``` +Exact LTV gives the lower feasible endpoint. Only positive remaining-side collateral changes +that endpoint; zero or net-borrow remaining-side value uses the same lower bound: +```math +L_\Delta=\max\left(0,\frac{debtSideValueInL-k\cdot remainingCollateralInL}{1+k}\right) +\qquad \text{when } remainingCollateralInL>0 +``` +```math +L_\Delta=\frac{debtSideValueInL}{1+k} +\qquad \text{when } remainingCollateralInL=0 ``` -where $$t_1 = b^{T} \cdot \sqrt{w_s}$$ for the tranche boundary $$T$$ of the tranche being -liquidated.* ```solidity function calcLWeightQ72( uint256[6] memory userAssets, - int256 xWeightQ72, - int256 yWeightQ72, - uint256 sqrtStartWeightQ72, - uint256 tranchesSqrtPriceQ72, + uint256 debtSideWeightQ72, + uint256 debtSideDelta, + uint256 targetLiquidationSqrtPriceQ72, bool netDebtX ) private pure returns (uint256 lWeightQ72); ``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`userAssets`|`uint256[6]`|Borrower assets in `[depositL, depositX, depositY, borrowL, borrowX, borrowY]` order.| +|`debtSideWeightQ72`|`uint256`|Q72 weight applied to the debt-side borrow amount.| +|`debtSideDelta`|`uint256`|Final debt-side borrow amount repaid by the liquidation.| +|`targetLiquidationSqrtPriceQ72`|`uint256`|Target liquidation sqrt price for the slice.| +|`netDebtX`|`bool`|Whether the debt side is X. If false, the debt side is Y.| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|`lWeightQ72`|`uint256`|Q72 weight applied to deposit L and borrow L.| + ### calcSqrtStartWeightQ72 -calculates weight based on the formula below. Note that we don't use all of the -active liquidity assets, must the max allowed saturation. +Calculates the start sqrt weight for the included saturation window. +The saturation is normalized by the active liquidity scaled by the maximum allowed +saturation ratio. Define: +```math +r_{max}=\frac`MAX\_SATURATION\_RATIO\_IN\_MAG2``MAG2` +``` +We round up the sqrt to avoid `sqrtStartWeightQ72 == Q72`, which would return `0` from `calcXWeightQ72`. +Normalize the included saturation by active liquidity: +```math +a_s=\frac{sat}{r_{max}L} +``` +The underlying non-sqrt start weight is: ```math \begin{equation} w_s = \begin{cases} -\frac{sat}}{MAX\_SAT\RATIO \cdot L} ( B - 1 ) + 1 +1+a_s(B-1) & \text{ if net debt of X } \\ -\frac{ 1 }{ \frac{sat}}{MAX\_SAT\RATIO \cdot L} ( B - 1 ) + 1 } +\frac{1}{1+a_s(B-1)} & \text{ if net debt of Y} \end{cases} \end{equation} @@ -165,18 +460,39 @@ function calcSqrtStartWeightQ72( uint256 partialSaturation, uint256 activeLiquidityAssets, bool netDebtX -) private pure returns (uint256 sqrtStartWeightQ72); +) internal pure returns (uint256 sqrtStartWeightQ72); ``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`partialSaturation`|`uint256`|Saturation included in the partial liquidation.| +|`activeLiquidityAssets`|`uint256`|Active liquidity used to scale tranche saturation.| +|`netDebtX`|`bool`|Whether the debt side is X. If false, the reciprocal weight is used.| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|`sqrtStartWeightQ72`|`uint256`|Q72 start sqrt weight, adjusted for the debt side.| + ### calcSqrtEndWeightQ72 -calculates weight based on the formula below. +Calculates the end sqrt weight for the included saturation window. +Normalize the remaining saturation by active liquidity: +```math +r_{max}=\frac`MAX\_SATURATION\_RATIO\_IN\_MAG2``MAG2`, +\qquad +a_e=\frac{sat_{total}-sat}{r_{max}L} +``` +The underlying non-sqrt end weight is: ```math \begin{equation} -w_s = \begin{cases} -\frac{ sat - sat_{total} }{ MAX\_SAT\RATIO \cdot L} ( B - 1 ) + 1 +w_e = \begin{cases} +1-a_e(B-1) & \text{ if net debt of X } \\ -\frac{ 1 }{ \frac{ sat - sat_{total} }{ MAX\_SAT\RATIO \cdot L } ( B - 1 ) + 1 } +\frac{1}{1-a_e(B-1)} & \text{ if net debt of Y} \end{cases} \end{equation} @@ -191,9 +507,30 @@ function calcSqrtEndWeightQ72( bool netDebtX ) private pure returns (uint256 sqrtEndWeightQ72); ``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`partialSaturation`|`uint256`|Saturation included in the partial liquidation.| +|`totalSaturation`|`uint256`|Total borrower saturation across all tranches.| +|`activeLiquidityAssets`|`uint256`|Active liquidity used to scale tranche saturation.| +|`netDebtX`|`bool`|Whether the debt side is X. If false, the reciprocal weight is used.| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|`sqrtEndWeightQ72`|`uint256`|Q72 end sqrt weight, adjusted for the debt side.| + ### weightInNumeratorOrDenominator +Adjusts a sqrt weight into numerator form for X debt or denominator form for Y debt. +Net debt Y walks the same tranche geometry in inverted square-root-price space: +```math +\sqrt{w}\mapsto\frac{1}{\sqrt{w}} +``` + ```solidity function weightInNumeratorOrDenominator( @@ -201,27 +538,19 @@ function weightInNumeratorOrDenominator( bool netDebtX ) private pure returns (uint256 adjustedSqrtWeight); ``` +**Parameters** -### mutatePosition +|Name|Type|Description| +|----|----|-----------| +|`sqrtWeight`|`uint256`|Q72 sqrt weight before debt-side orientation.| +|`netDebtX`|`bool`|Whether the debt side is X. If false, the reciprocal weight is returned.| +**Returns** -```solidity -function mutatePosition( - uint256[6] memory userAssets, - uint256 lWeightQ72, - uint256 xWeightQ72, - uint256 yWeightQ72 -) internal pure returns (uint256[6] memory); -``` +|Name|Type|Description| +|----|----|-----------| +|`adjustedSqrtWeight`|`uint256`|Q72 sqrt weight oriented for the debt side.| -### netAssets - - -```solidity -function netAssets( - uint256[6] memory userAssets -) internal pure returns (int256 netL, int256 netX, int256 netY); -``` ## Structs ### LoopMemoryState diff --git a/docs/developer-guide/contracts/libraries/PriceExtremes.sol/library.PriceExtremes.md b/docs/developer-guide/contracts/libraries/PriceExtremes.sol/library.PriceExtremes.md new file mode 100644 index 00000000..489d5b26 --- /dev/null +++ b/docs/developer-guide/contracts/libraries/PriceExtremes.sol/library.PriceExtremes.md @@ -0,0 +1,91 @@ +# PriceExtremes +[Git Source](https://github.com/Ammalgam-Protocol/core-v1/blob/ec51218155bd2f8c1e5dc761ed4728baae81a01b/contracts/libraries/PriceExtremes.sol) + +Tracks intra-observation price extremes to mitigate TWAP lag attacks. + +*Records max/min ticks per observation interval so arb-driven price signals are captured +even if the attacker resets the price afterward.* + + +## Functions +### record + +Record a priceQ128 observation as inclusive min and exclusive max ticks. + + +```solidity +function record(State storage state, uint256 priceQ128, uint32 interval) internal; +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`state`|`State`| The per-pair extreme tracking state| +|`priceQ128`|`uint256`|The current price as reserveX * Q128 / reserveY| +|`interval`|`uint32`| The observation interval (DEFAULT_MID_TERM_INTERVAL)| + + +### widen + +Widen a [minTick, maxTick) range using fresh price extremes. Never narrows. + + +```solidity +function widen( + State storage state, + int16 minTick, + int16 maxTick, + uint32 interval +) internal view returns (int16 widenedMin, int16 widenedMax); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`state`|`State`| The per-pair extreme tracking state| +|`minTick`|`int16`| Current minimum tick (from getTickRange)| +|`maxTick`|`int16`| Current exclusive maximum tick (from getTickRange)| +|`interval`|`uint32`|The observation interval (DEFAULT_MID_TERM_INTERVAL)| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|`widenedMin`|`int16`| The potentially widened minimum tick| +|`widenedMax`|`int16`| The potentially widened maximum tick| + + +### _widen + + +```solidity +function _widen( + uint32 stateTimestamp, + int16 slotMinTick, + int16 slotMaxTick, + bool initialized, + uint32 currentTimestamp, + uint32 maxAge, + int16 widenMin, + int16 widenMax +) private pure returns (int16, int16); +``` + +## Structs +### State +State for tracking price extremes within an observation interval. + + +```solidity +struct State { + uint32 currentTimestamp; + uint32 previousTimestamp; + int16 currentMaxTick; + int16 currentMinTick; + int16 previousMaxTick; + int16 previousMinTick; + bool currentInitialized; + bool previousInitialized; +} +``` + diff --git a/docs/developer-guide/contracts/libraries/QuadraticSwapFees.sol/library.QuadraticSwapFees.md b/docs/developer-guide/contracts/libraries/QuadraticSwapFees.sol/library.QuadraticSwapFees.md index 22a74753..f7d05246 100644 --- a/docs/developer-guide/contracts/libraries/QuadraticSwapFees.sol/library.QuadraticSwapFees.md +++ b/docs/developer-guide/contracts/libraries/QuadraticSwapFees.sol/library.QuadraticSwapFees.md @@ -1,5 +1,5 @@ # QuadraticSwapFees -[Git Source](https://github.com/Ammalgam-Protocol/core-v1/blob/2b185eab2df708b55f7ffa534655c69f626e73b3/contracts/libraries/QuadraticSwapFees.sol) +[Git Source](https://github.com/Ammalgam-Protocol/core-v1/blob/ec51218155bd2f8c1e5dc761ed4728baae81a01b/contracts/libraries/QuadraticSwapFees.sol) **Author:** Will @@ -151,14 +151,14 @@ The resulting fee for the beyond-reference portion is then weighted by `pastBy / \begin{equation*} f_\phi(X_{in}) = \begin{cases} -n \cdot \frac{2(X_{0}-X_{R})+X_{in}}{X_{R}} -&\text{if } X_0 \ge X_R \text{ \& } X_{in} + 2 X_{0} \le X_{R}\left(\frac{M_Q +\ 2n}{n}\right) \\ -M_Q \left( 2 - X_R \frac{M_Q}{n\left( X_{in} + 2 (X_0 - X_R) \right)} \right) -&\text {if } X_0 \ge X_R \text{ \& } X_{in} + 2X_{0} \ge X_{R}\left(\frac{M_Q+\ 2n}{n}\right) \\ -\frac{n \cdot \left( \frac{pastBy^2}{X_R} \right)}{X_{in}} -&\text{ if } X_0 + X_{in} \gt X_R \text{ \& } X_{in} + 2 X_{0} \le X_{R}\left(\frac{M_Q +\ 2n}{n}\right) \\ -\frac{M_Q \left( 2 - X_R \frac{M_Q}{n \cdot pastBy} \right) \cdot pastBy}{X_{in}} -&\text{ if } X_0 + X_{in} \gt X_R \text{ \& } X_{in} + 2 X_{0} \ge X_{R}\left(\frac{M_Q +\ 2n}{n}\right) \\ +n \cdot \frac{2(X_{0}-X_`R`)+X_{in}}`X_{R`} +&\text{if } X_0 \ge X_R \text{ \& } X_{in} + 2 X_{0} \le X_`R`\left(\frac`M_Q +\ 2n`{n}\right) \\ +M_Q \left( 2 - X_R \frac`M_Q`{n\left( X_{in} + 2 (X_0 - X_R) \right)} \right) +&\text {if } X_0 \ge X_R \text{ \& } X_{in} + 2X_{0} \ge X_`R`\left(\frac`M_Q+\ 2n`{n}\right) \\ +\frac{n \cdot \left( \frac{pastBy^2}`X_R` \right)}`X_{in`} +&\text{ if } X_0 + X_{in} \gt X_R \text{ \& } X_{in} + 2 X_{0} \le X_`R`\left(\frac`M_Q +\ 2n`{n}\right) \\ +\frac`M_Q \left( 2 - X_R \frac{M_Q`{n \cdot pastBy} \right) \cdot pastBy}`X_{in`} +&\text{ if } X_0 + X_{in} \gt X_R \text{ \& } X_{in} + 2 X_{0} \ge X_`R`\left(\frac`M_Q +\ 2n`{n}\right) \\ MinBips &\text{ otherwise } X_0 + X_{in} \le X_R \\ \end{cases} \end{equation*} diff --git a/docs/developer-guide/contracts/libraries/Saturation.sol/library.Saturation.md b/docs/developer-guide/contracts/libraries/Saturation.sol/library.Saturation.md index a73338f0..94e5ec68 100644 --- a/docs/developer-guide/contracts/libraries/Saturation.sol/library.Saturation.md +++ b/docs/developer-guide/contracts/libraries/Saturation.sol/library.Saturation.md @@ -1,5 +1,5 @@ # Saturation -[Git Source](https://github.com/Ammalgam-Protocol/core-v1/blob/2b185eab2df708b55f7ffa534655c69f626e73b3/contracts/libraries/Saturation.sol) +[Git Source](https://github.com/Ammalgam-Protocol/core-v1/blob/ec51218155bd2f8c1e5dc761ed4728baae81a01b/contracts/libraries/Saturation.sol) **Authors:** imi@1m1.io, Will duelingGalois@protonmail.com @@ -15,8 +15,8 @@ square root price as $B^T$ for some tranche $T$. Using the square root price, we amount of x or y in each tranche as: ```math \begin{align*} -x = L \cdot B^{T_0} - L \cdot B^{T_1} \\ -y = \frac{L}{ B^{T_1}} - \frac{L}{B^{T_0}} +x = L \cdot B^`T_0` - L \cdot B^`T_1` \\ +y = \frac`L`{ B^`T_1`} - \frac`L``B^{T_0`} \end{align*} ``` where liquidity is $L = \sqrt{reserveX \cdot reserveY}$. If we want to know how much debt of x @@ -24,7 +24,7 @@ or y can be liquidated within one tick, we can solve these equations for L and t of x and y are considered the debt we would like to see if it could be liquidated in one tick. If saturation with respect to our starting $L$ is smaller, that amount of debt can be liquidated in one swap in the given ticks. Otherwise it is too big and can not. Note that we -assume $$t_1 \text{ and } t_0 \in \mathbb{Z}$$ and $$t_0 + 1 = t_1$$. Then our definition of +assume $$t_1 \text{ and } t_0 \in \mathbb`Z`$$ and $$t_0 + 1 = t_1$$. Then our definition of saturation relative to L is as follows, ```math \begin{equation} @@ -76,22 +76,22 @@ for the start and end of liquidation $$t_s$$ and $$t_e$$ respectively. When we c buckets of TICKS_PER_TRANCHE we can rewrite this as a series where each boundary of each tranche $$T_i$$ where $$T_0 = t_e \% TICKS_PER_TRANCHE$$ for a net debt of X and $$T_0 = (-t_e) \% TICKS_PER_TRANCHE$$ for a net debt of Y and $$T_i = T_{i-1} + TICKS_PER_TRANCHE$$ for each -subsequent tranche and $$B= b^{TICKS_PER_TRANCHE}$$. Thus we can rewrite the equations as: +subsequent tranche and $$B= b^`TICKS_PER_TRANCHE`$$. Thus we can rewrite the equations as: ```math \begin{align*} X &= -L \left(b^{T_1} - b^{t_e} \right) -+ L \left( b^{T_2} - b^{T_1}\right) +L \left(b^`T_1` - b^{t_e} \right) ++ L \left( b^`T_2` - b^`T_1`\right) + ... -+ L \left( b^{T_n} - b^{T_{n-1}}\right) -+ L \left(b^{t_s}-b^{T_n} \right) ++ L \left( b^`T_n` - b^`T_{n-1`}\right) ++ L \left(b^{t_s}-b^`T_n` \right) \\ -\Large\frac{X}{b^{t_e}(B-1)} &= +\Large\frac`X`{b^{t_e}(B-1)} &= \Large L \left( -\frac{B \cdot b^{t_e-T_0} - 1}{B-1} +\frac`B \cdot b^{t_e-T_0` - 1}`B-1` + \frac{ \sum_{i=1}^{n-1} B^{i} }{ b^{t_e-T_0} } -+ \frac{B^{n} \left( -\frac{b^{t_s}}{B^{n} \cdot b^{T_0}}-1 \right) }{ b^{t_e-T_0}(B-1)} ++ \frac`B^{n` \left( +\frac{b^{t_s}}`B^{n` \cdot b^`T_0`}-1 \right) }{ b^{t_e-T_0}(B-1)} \right) \end{align*} ``` @@ -104,13 +104,13 @@ furthest point from the tranche and moving forward. T_{sat} &= s_0 + \frac{\sum_{i=1}^{n-1} s_i \cdot B^{i}}{b^{t_e-T_0}} -+ \frac{B^n \cdot s_n}{b^{t_e-T_0}} ++ \frac`B^n \cdot s_n`{b^{t_e-T_0}} \\ -\frac{(T_{sat} - s_0)b^{t_e-T_0}}{B} - s_1 &= +\frac{(T_{sat} - s_0)b^{t_e-T_0}}`B` - s_1 &= \left(\sum_{i=2}^{n-1} s_i \cdot B^{i-1} \right) + B^{n-1} \cdot s_n \\ -\frac{\frac{(T_{sat} - s_0)b^{t_e-T_0}}{B} - s_1 }{ B } -s_2 &= +\frac{\frac{(T_{sat} - s_0)b^{t_e-T_0}}`B` - s_1 }{ B } -s_2 &= \left(\sum_{i=2}^{n-1} s_i \cdot B^{i-2} \right) + B^{n-2} \cdot s_n \end{align*} @@ -181,6 +181,29 @@ uint256 internal constant EXPECTED_SATURATION_LTV_PLUS_ONE_MAG2 = 185; ``` +### SAT_RESET_FOR_STRADDLE_SLOPE_BIPS +Slope for calculating premium when resetting saturation for straddle positions +where $$L^2 < X \cdot Y$$ transitions to $$L^2 > X \cdot Y$$. Applied to +$$(L^{2} - X \cdot Y) / (X \cdot Y)$$ to produce `premiumBips`. Matches the +Desmos coefficient $$\frac`BIPS`{10} \cdot 100 = 100000$$. At +$$L^{2} = 1.02 \cdot X \cdot Y$$ the raw premium evaluates to +`MAX_SAT_RESET_FOR_STRADDLE_PREMIUM_BIPS`; past that point the cap engages. + + +```solidity +uint256 internal constant SAT_RESET_FOR_STRADDLE_SLOPE_BIPS = 100_000; +``` + + +### MAX_SAT_RESET_FOR_STRADDLE_PREMIUM_BIPS +Maximum premium when resetting saturation for zero-to-positive straddle positions. + + +```solidity +uint256 internal constant MAX_SAT_RESET_FOR_STRADDLE_PREMIUM_BIPS = 2000; +``` + + ### SAT_CHANGE_OF_BASE_Q128 a constant used to change the log base from the tick math base to the saturation to leaf base. @@ -314,7 +337,7 @@ int256 internal constant TICKS_PER_TRANCHE = 25; ### TRANCHE_BASE_OVER_BASE_MINUS_ONE_Q72 for convenience, used to determine max sat per tranche to not cross in liq swap: -$$\frac{B}{B-1}$$ +$$\frac`B``B-1`$$ ```solidity @@ -387,16 +410,6 @@ uint256 private constant NUMBER_OF_QUARTERS = 4; ``` -### SATURATION_LIQUIDATION_SCALER -We make the penalty slightly larger to hit our desired premium for exceeding the -time buffer. - - -```solidity -uint256 private constant SATURATION_LIQUIDATION_SCALER = 10_020; -``` - - ### TWO_Q72 $$2 * 2**72 * 2$$, used in saturation formula. @@ -580,9 +593,7 @@ function removeSatFromTrancheStateUpdates( Tree storage tree, SaturationPair memory oldAccountSaturationInTranche, int256 tranche, - uint256 oldLeaf, - address account, - uint256 trancheIndex + uint256 oldLeaf ) internal; ``` **Parameters** @@ -593,8 +604,6 @@ function removeSatFromTrancheStateUpdates( |`oldAccountSaturationInTranche`|`SaturationPair`|account sat| |`tranche`|`int256`| under consideration| |`oldLeaf`|`uint256`|where tranche was located before this sat removal| -|`account`|`address`| needed to accrue penalty| -|`trancheIndex`|`uint256`|which tranche of the account are we handling?| ### addSatToTranche @@ -616,13 +625,13 @@ The formula applied here, derived in the introduction, is, T_{sat} &= s_0 + \frac{\sum_{i=1}^{n-1} s_i \cdot B^{i}}{b^{t_e-T_0}} -+ \frac{B^n \cdot s_n}{b^{t_e-T_0}} ++ \frac`B^n \cdot s_n`{b^{t_e-T_0}} \\ -\frac{(T_{sat} - s_0)b^{t_e-T_0}}{B} - s_1 &= +\frac{(T_{sat} - s_0)b^{t_e-T_0}}`B` - s_1 &= \left(\sum_{i=2}^{n-1} s_i \cdot B^{i-1} \right) + B^{n-1} \cdot s_n \\ -\frac{\frac{(T_{sat} - s_0)b^{t_e-T_0}}{B} - s_1 }{ B } -s_2 &= +\frac{\frac{(T_{sat} - s_0)b^{t_e-T_0}}`B` - s_1 }{ B } -s_2 &= \left(\sum_{i=2}^{n-1} s_i \cdot B^{i-2} \right) + B^{n-2} \cdot s_n \end{align*} @@ -882,6 +891,41 @@ function getPenaltySharesPerSatFromLeaf( |`penaltyInBorrowLSharesPerSatInQ72`|`uint256`| total penalty at the leaf, non-negative but returned as an int for recursion| +### getEffectivePenalty + +get effective penalty for a tranche, combining leaf penalty and tranche adjustment. +When a tranche moves between leaves, the adjustment bridges the gap between the old and new +leaf accumulators so that existing accounts' onset values remain valid. + +*Invariant: `leafPen + adjustment >= 0` always holds. Within a single tranche +lifecycle, moves preserve continuity of `effective` (the move logic adds the same delta +to `adjustment` that it subtracts from `leafPen`), so `effective` only ever grows from +its initial non-negative value. The `delete` in `removeSatFromTrancheStateUpdates` resets +the adjustment when a tranche empties so each new lifecycle starts from `adj = 0`.* + + +```solidity +function getEffectivePenalty( + Tree storage tree, + uint256 leaf, + int256 tranche +) private view returns (uint256 effectivePenalty); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`tree`|`Tree`|that is being read from| +|`leaf`|`uint256`| index (0 based) of the leaf containing the tranche| +|`tranche`|`int256`| the tranche identifier| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|`effectivePenalty`|`uint256`| the effective cumulative penalty for this tranche| + + ### accrueAccountPenalty calc penalty owed by account for repay, total over all the tranches that might @@ -934,7 +978,8 @@ function calcNewAccountPenalty( uint256 leaf, uint256 accountSatInTrancheInLAssets, address account, - uint256 trancheIndex + uint256 trancheIndex, + int256 tranche ) private view returns (uint256 penaltyInBorrowLShares, uint256 accountTreePenaltyInBorrowLSharesPerSatInQ72); ``` **Parameters** @@ -946,6 +991,7 @@ function calcNewAccountPenalty( |`accountSatInTrancheInLAssets`|`uint256`| the sat of the account in the tranche| |`account`|`address`| whose position is being considered| |`trancheIndex`|`uint256`| the index of the tranche that is being added to| +|`tranche`|`int256`|| **Returns** @@ -955,33 +1001,6 @@ function calcNewAccountPenalty( |`accountTreePenaltyInBorrowLSharesPerSatInQ72`|`uint256`| the penalty owed by the account in the tranche| -### calcAndAccrueNewAccountPenalty - -calc and accrue new account penalty - - -```solidity -function calcAndAccrueNewAccountPenalty( - Tree storage tree, - SaturationPair memory oldAccountSaturationInTranche, - uint256 oldLeaf, - address account, - uint256 trancheIndex, - uint256 newTreePenaltyAtOnsetInBorrowLSharesPerSatInQ72PerTranche -) private; -``` -**Parameters** - -|Name|Type|Description| -|----|----|-----------| -|`tree`|`Tree`|that is being read from or written to| -|`oldAccountSaturationInTranche`|`SaturationPair`| the old sat of the account in the tranche| -|`oldLeaf`|`uint256`| the leaf that the tranche was located in before it was removed| -|`account`|`address`| whose position is being considered| -|`trancheIndex`|`uint256`| the index of the tranche that is being added to| -|`newTreePenaltyAtOnsetInBorrowLSharesPerSatInQ72PerTranche`|`uint256`| the new penalty at onset in borrow l shares per sat in q72 per tranche| - - ### accruePenalties accrue penalties since last accrual based on all over saturated positions @@ -1211,7 +1230,46 @@ function findHighestSetLeafDownwards( ### calcLiqSqrtPriceQ72 -Calc sqrt price at which positions' LTV would reach LTV_MAX +Calc sqrt price at which positions' LTV would reach LTV_MAX. Given the net $$L$$, +$$X$$, and Y, we define the the sqrt price $$s_p$$ at which the position would be at the +expected loan to value of liquidation $$k$$, then the following formulas are what we are +calculating, +```math +\begin{align} +k &= +\begin{cases} +-\frac`L + \frac{X`{s_p}}`L + Y \cdot s_p` +\text{ if } L+ \frac`X`{s_p} < 0 +\\ +-\frac`L + Y \cdot s_p``L + \frac{X`{s_p}} +\text{ if } L + Y \cdot s_p < 0 +\end{cases} +\\ +s_p &= +\begin{cases} +\frac{ +-(k+1)L + +\sqrt{\left((k+1)L\right)^2 - 4 \left( k\cdot Y \right) \left(X \right)} +}{ +2 \cdot k \cdot Y +} +\text{ if } L + \frac`X`{s_p} < 0 +\\ +\frac{ +-(k+1)L - +\sqrt{((k+1)L)^2-4(Y)(k\cdot X)} +}{ +2\cdot k +} +\text{ if } L + Y \cdot s_p < 0 +\end{cases} +\end{align} +``` +The equation gives four solutions due to the plus minus of the radical, but we choose the +direction due to the conditions. When we have a net debt of x, $$L + \frac`X`{s_p} < 0$$, +the loan to value will be increasing as the price decreases, thus we choose the positive +value of the radical. For the net debt of y, $$L + Y \cdot s_p < 0$$ we have the loan to +value increasing as the price increases, thus we use the negative value of the radical. Output guarantees $$0 \le liqSqrtPriceXInQ72 \le uint256(type(uint56).max) << 72$$ (fuzz tested and logic) @@ -1283,7 +1341,7 @@ function calcSatChangeRatioBips( uint256 liqSqrtPriceInYInQ72, address account, uint256 desiredSaturationMAG2 -) internal view returns (uint256 ratioNetXBips, uint256 ratioNetYBips); +) internal view returns (uint256 ratioBips); ``` **Parameters** @@ -1300,8 +1358,115 @@ function calcSatChangeRatioBips( |Name|Type|Description| |----|----|-----------| -|`ratioNetXBips`|`uint256`|The ratio representing the change in netX saturation for account.| -|`ratioNetYBips`|`uint256`|The ratio representing the change in netY saturation for account.| +|`ratioBips`|`uint256`|The ratio representing the change in saturation for account.| + + +### calcTreeRatioBips + +*Per-tree ratio computation extracted from `calcSatChangeRatioBips`. +Stored `satPairs[i].satRelativeToL` lives in tranche-i units +(= 1/B^i of tranche-0 units, modulo the partial first-tranche adjustment). +`scaleAndSumSaturation` converts each stored sat back to tranche-0 units, so +the old and new saturation totals are compared in the same unit system.* + + +```solidity +function calcTreeRatioBips( + SaturationPair[] storage satPairs, + Validation.InputParams memory inputParams, + uint256 liqSqrtPriceInXInQ72, + uint256 liqSqrtPriceInYInQ72, + uint256 desiredSaturationMAG2, + bool netDebtX +) private view returns (uint256 ratioBips); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`satPairs`|`SaturationPair[]`|Storage array of per-tranche saturation pairs for the tree being evaluated.| +|`inputParams`|`Validation.InputParams`|User asset balances and pool state used to compute the new saturation.| +|`liqSqrtPriceInXInQ72`|`uint256`|Liquidation sqrt price (upper root) in Q72, for the netDebtX side.| +|`liqSqrtPriceInYInQ72`|`uint256`|Liquidation sqrt price (lower root) in Q72, for the netDebtY side.| +|`desiredSaturationMAG2`|`uint256`|Target saturation level in MAG2 units used to project the new sat.| +|`netDebtX`|`bool`|True when evaluating the netDebtX tree; false for the netDebtY tree.| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|`ratioBips`|`uint256`|Growth ratio in BIPS of (old + remaining) / old saturation for this tree; zero when the new saturation does not exceed the absorbed old saturation.| + + +### scaleAndSumSaturation + +*Sum stored per-tranche saturation in tranche-0 units. +`satPairs[i].satRelativeToL` is stored in tranche-`i` units (= 1/B^i of tranche-0 units, +modulo the partial first-tranche adjustment from `calculateEndOfLiquidationAdjustment`). +Summing them directly would mix units across tranches and undercount the total. The loop +tracks an inverse Q72 scale factor `bScaleQ72` that rescales each stored sat back into +tranche-0 units before accumulation; the first iteration also folds in the partial +first-tranche `endOfLiquidationAdjustmentQ72`, which then resets to `Q72`.* + + +```solidity +function scaleAndSumSaturation( + SaturationPair[] storage satPairs, + int256 endOfLiquidationInTicks, + bool netDebtX +) internal view returns (uint256 oldSatInLAssets); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`satPairs`|`SaturationPair[]`|Storage array of per-tranche saturation pairs.| +|`endOfLiquidationInTicks`|`int256`|Tick at which liquidation ends (sets the first-tranche offset).| +|`netDebtX`|`bool`|True when summing the netDebtX tree; false for the netDebtY tree.| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|`oldSatInLAssets`|`uint256`|Total saturation in tranche-0 (L-asset) units.| + + +### calcStraddlePremiumRatioBips + +Calculate the ratio bips for a straddle position transitioning from zero to positive saturation. +Let $$S$$ be `SAT_RESET_FOR_STRADDLE_SLOPE_BIPS`, the slope that controls how quickly the +straddle reset premium increases once $$L^2 > X \cdot Y$$. +Let $$P_{max}$$ be `MAX_SAT_RESET_FOR_STRADDLE_PREMIUM_BIPS`, the maximum premium allowed for +this zero-to-positive straddle reset path. +```math +premiumBips = \min\left( +P_{max}, +\left\lceil\frac{(L^2 - X \cdot Y) \cdot S}`X \cdot Y`\right\rceil +\right) +``` +The ratioBips encodes premium for downstream consumption: +```math +\text{ratioBips} = \text{premiumBips} \cdot \text`MAG1` + \text`BIPS` +``` +and premium is recovered as: `(ratioBips - BIPS) / MAG1`. + + +```solidity +function calcStraddlePremiumRatioBips( + uint256[6] memory userAssets +) private pure returns (uint256 ratioBips); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`userAssets`|`uint256[6]`|The user's position parameters.| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|`ratioBips`|`uint256`|The ratio in bips, or 0 if $$L^2 <= X \cdot Y$$.| ### calculateEndOfLiquidationAdjustment @@ -1314,14 +1479,16 @@ of the liquidation relative to the the boundary of the tranches. ```solidity function calculateEndOfLiquidationAdjustment( - int256 endOfLiquidationInTicks -) private pure returns (uint256 endOfLiquidationSqrtPriceAdjustment); + int256 endOfLiquidationInTicks, + bool netDebtX +) internal pure returns (uint256 endOfLiquidationSqrtPriceAdjustment); ``` **Parameters** |Name|Type|Description| |----|----|-----------| |`endOfLiquidationInTicks`|`int256`| the tick at which liquidation should end by.| +|`netDebtX`|`bool`| whether this is a net X debt path.| **Returns** @@ -1582,7 +1749,7 @@ number of tranches we need to move back, \Large\frac{debt}{b^{t_e}(B-1)} &\text{ when debt is in X asset } \\ -\Large\frac{debt \cdot b^{t_e}}{B-1} +\Large\frac{debt \cdot b^{t_e}}`B-1` &\text{ otherwise } \end{cases} \end{equation} @@ -1744,14 +1911,6 @@ if the largest sat in the trees is too large error MaxTrancheOverSaturated(); ``` -### NegativeSpan -raised if the $$log_b(spanSqrtPrice) < 0$$, this shouldn't be possible. - - -```solidity -error NegativeSpan(); -``` - ### LiquidationPassesMinOrMaxTick raised if the start of liquidation would occur on the wrong side of the min or max tick price from the GeometricTWAP. @@ -1793,12 +1952,12 @@ struct Tree { bool netX; uint16 highestSetLeaf; uint128 totalSatInLAssets; - uint256 tranchesWithSaturation; uint256[][LEVELS_WITHOUT_LEAFS] nodes; Leaf[LEAFS] leafs; mapping(int16 => uint16) trancheToLeaf; mapping(int16 => SaturationPair) trancheToSaturation; mapping(address => Account) accountData; + mapping(int16 => int256) tranchePenaltyAdjustment; } ``` diff --git a/docs/developer-guide/contracts/libraries/TickMath.sol/library.TickMath.md b/docs/developer-guide/contracts/libraries/TickMath.sol/library.TickMath.md index 6f547b0b..cd19c446 100644 --- a/docs/developer-guide/contracts/libraries/TickMath.sol/library.TickMath.md +++ b/docs/developer-guide/contracts/libraries/TickMath.sol/library.TickMath.md @@ -1,5 +1,5 @@ # TickMath -[Git Source](https://github.com/Ammalgam-Protocol/core-v1/blob/2b185eab2df708b55f7ffa534655c69f626e73b3/contracts/libraries/TickMath.sol) +[Git Source](https://github.com/Ammalgam-Protocol/core-v1/blob/ec51218155bd2f8c1e5dc761ed4728baae81a01b/contracts/libraries/TickMath.sol) Computes sqrt price for ticks of size B=(1-2^-9)^-1 as fixed point Q72 numbers. Supports prices between 2**-112 and 2**112-1 diff --git a/docs/developer-guide/contracts/libraries/TokenSymbol.sol/library.TokenSymbol.md b/docs/developer-guide/contracts/libraries/TokenSymbol.sol/library.TokenSymbol.md index 92328998..89ea8875 100644 --- a/docs/developer-guide/contracts/libraries/TokenSymbol.sol/library.TokenSymbol.md +++ b/docs/developer-guide/contracts/libraries/TokenSymbol.sol/library.TokenSymbol.md @@ -1,5 +1,5 @@ # TokenSymbol -[Git Source](https://github.com/Ammalgam-Protocol/core-v1/blob/2b185eab2df708b55f7ffa534655c69f626e73b3/contracts/libraries/TokenSymbol.sol) +[Git Source](https://github.com/Ammalgam-Protocol/core-v1/blob/ec51218155bd2f8c1e5dc761ed4728baae81a01b/contracts/libraries/TokenSymbol.sol) ## Functions diff --git a/docs/developer-guide/contracts/libraries/Uint16Set.sol/library.Uint16Set.md b/docs/developer-guide/contracts/libraries/Uint16Set.sol/library.Uint16Set.md index c1872326..273f4031 100644 --- a/docs/developer-guide/contracts/libraries/Uint16Set.sol/library.Uint16Set.md +++ b/docs/developer-guide/contracts/libraries/Uint16Set.sol/library.Uint16Set.md @@ -1,5 +1,5 @@ # Uint16Set -[Git Source](https://github.com/Ammalgam-Protocol/core-v1/blob/2b185eab2df708b55f7ffa534655c69f626e73b3/contracts/libraries/Uint16Set.sol) +[Git Source](https://github.com/Ammalgam-Protocol/core-v1/blob/ec51218155bd2f8c1e5dc761ed4728baae81a01b/contracts/libraries/Uint16Set.sol) based on https://github.com/rob-Hitchens/SetTypes/blob/master/contracts/UintSet.sol @@ -40,11 +40,11 @@ function insert(Set storage self, uint16 key) internal returns (bool keyAlreadyE remove a key. -*key to remove must exist.* +*If the key does not exist, this function is a no-op and returns true.* ```solidity -function remove(Set storage self, uint16 key) internal returns (bool keyDidNotExist); +function remove(Set storage self, uint16 key) internal returns (bool isSetEmpty); ``` **Parameters** @@ -57,7 +57,7 @@ function remove(Set storage self, uint16 key) internal returns (bool keyDidNotEx |Name|Type|Description| |----|----|-----------| -|`keyDidNotExist`|`bool`|whether the key already did not yet exist in the set| +|`isSetEmpty`|`bool`|whether the key did not exist or the set still has items after removal| ### count diff --git a/docs/developer-guide/contracts/libraries/Validation.sol/library.Validation.md b/docs/developer-guide/contracts/libraries/Validation.sol/library.Validation.md index af34a9d1..19bb0f33 100644 --- a/docs/developer-guide/contracts/libraries/Validation.sol/library.Validation.md +++ b/docs/developer-guide/contracts/libraries/Validation.sol/library.Validation.md @@ -1,5 +1,5 @@ # Validation -[Git Source](https://github.com/Ammalgam-Protocol/core-v1/blob/2b185eab2df708b55f7ffa534655c69f626e73b3/contracts/libraries/Validation.sol) +[Git Source](https://github.com/Ammalgam-Protocol/core-v1/blob/ec51218155bd2f8c1e5dc761ed4728baae81a01b/contracts/libraries/Validation.sol) SPDX-License-Identifier: GPL-3.0-only @@ -8,63 +8,7 @@ SPDX-License-Identifier: GPL-3.0-only ### MAX_BORROW_PERCENTAGE ```solidity -uint256 private constant MAX_BORROW_PERCENTAGE = 90; -``` - - -### ONE_HUNDRED_TIMES_N - -```solidity -uint256 private constant ONE_HUNDRED_TIMES_N = 2000; -``` - - -### TWO_Q64 - -```solidity -uint256 private constant TWO_Q64 = 0x20000000000000000; -``` - - -### FIVE_Q64 - -```solidity -uint256 private constant FIVE_Q64 = 0x50000000000000000; -``` - - -### NINE_Q64 - -```solidity -uint256 private constant NINE_Q64 = 0x90000000000000000; -``` - - -### FIFTY_Q64 - -```solidity -uint256 private constant FIFTY_Q64 = 0x320000000000000000; -``` - - -### TWO_TIMES_N_Q64 - -```solidity -uint256 private constant TWO_TIMES_N_Q64 = 0x280000000000000000; -``` - - -### TWO_Q128 - -```solidity -uint256 private constant TWO_Q128 = 0x200000000000000000000000000000000; -``` - - -### TWO_THOUSAND_FIVE_HUNDRED_Q128 - -```solidity -uint256 private constant TWO_THOUSAND_FIVE_HUNDRED_Q128 = 0x9c400000000000000000000000000000000; +uint256 internal constant MAX_BORROW_PERCENTAGE = 90; ``` @@ -118,7 +62,6 @@ to switch them as needed in liquidation and other cases.* ```solidity function getCheckLtvParams( uint256[6] memory userAssets, - uint256 activeLiquidityScalerInQ72, uint256 sqrtPriceMinInQ72, uint256 sqrtPriceMaxInQ72 ) internal pure returns (CheckLtvParams memory checkLtvParams); @@ -128,13 +71,15 @@ function getCheckLtvParams( |Name|Type|Description| |----|----|-----------| |`userAssets`|`uint256[6]`|User asset array| -|`activeLiquidityScalerInQ72`|`uint256`|The active liquidity scaler in Q72| |`sqrtPriceMinInQ72`|`uint256`|The minimum sqrt price in Q72| |`sqrtPriceMaxInQ72`|`uint256`|The maximum sqrt price in Q72| ### validateBalanceAndLiqAndNotSameAssetsSuppliedAndBorrowed +Verifies that debt is backed by liquidity from an independent provider and +that users do not borrow the same underlying assets they supply as collateral. + ```solidity function validateBalanceAndLiqAndNotSameAssetsSuppliedAndBorrowed( @@ -142,6 +87,13 @@ function validateBalanceAndLiqAndNotSameAssetsSuppliedAndBorrowed( uint256 activeLiquidityAssets ) internal pure; ``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`userAssets`|`uint256[6]`|The account's assets by token type.| +|`activeLiquidityAssets`|`uint256`|The pair's active liquidity assets.| + ### validateLTVAndLeverage @@ -162,9 +114,8 @@ function validateSolvency( uint256[6] memory userAssets, uint256 sqrtPriceMinInQ72, uint256 sqrtPriceMaxInQ72, - uint256 activeLiquidityScalerInQ72, uint256 activeLiquidityAssets -) internal pure; +) external pure; ``` ### verifyNotSameAssetsSuppliedAndBorrowed @@ -194,7 +145,6 @@ function verifyMaxBorrow( ```solidity function getDepositsInL( uint256[6] memory userAssets, - uint256 activeLiquidityScalerInQ72, uint256 sqrtPriceMinInQ72, uint256 sqrtPriceMaxInQ72 ) private pure returns (uint256 netDepositedXinLAssets, uint256 netDepositedYinLAssets); @@ -206,7 +156,6 @@ function getDepositsInL( ```solidity function getBorrowedInL( uint256[6] memory userAssets, - uint256 activeLiquidityScalerInQ72, uint256 sqrtPriceMinInQ72, uint256 sqrtPriceMaxInQ72 ) private pure returns (uint256 netBorrowedXinLAssets, uint256 netBorrowedYinLAssets); @@ -214,70 +163,56 @@ function getBorrowedInL( ### convertXToL -The original math: -L * activeLiquidityScalerInQ72 = x / sqrt(p) -previous equation: -amountLAssets = mulDiv(amount, Q72, sqrtPriceInXInQ72, rounding); -adding activeLiquidityScalerInQ72: -amountLAssets = (amount * Q72 / sqrtPriceInXInQ72) / (activeLiquidityScalerInQ72 / Q72); -simplify to: -(amount * Q72 * Q72) / (sqrtPriceInXInQ72 * activeLiquidityScalerInQ72) -final equation: -amountLAssets = mulDiv(mulDiv(amount, Q72, sqrtPriceInXInQ72, rounding), Q72, activeLiquidityScalerInQ72, rounding); -or more simplified (failed for some tests) -amountLAssets = mulDiv(amount, Q72 * Q72, sqrtPriceInQ72 * activeLiquidityScalerInQ72); +Convert X assets to L assets: L = x / sqrt(p) +amountLAssets = amountInXAssets * Q72 / sqrtPriceInXInQ72 ```solidity function convertXToL( uint256 amountInXAssets, uint256 sqrtPriceInXInQ72, - uint256 activeLiquidityScalerInQ72, bool roundUp ) internal pure returns (uint256 amountLAssets); ``` ### convertLToX +Convert L assets to X assets: x = L * sqrt(p) +amountXAssets = amount * sqrtPriceQ72 / Q72 + ```solidity function convertLToX( uint256 amount, uint256 sqrtPriceQ72, - uint256 activeLiquidityScalerInQ72, bool roundUp ) internal pure returns (uint256 amountXAssets); ``` ### convertYToL -The simplified math: L = y * sqrt(p) -mulDiv(amount, sqrtPriceInXInQ72, rounding); -amountLAssets = amount * sqrtPriceInXInQ72Scaled / Q72; -sqrtPriceInXInQ72Scaled = sqrtPriceInXInQ72 / activeLiquidityScalerInQ72 / Q72; -simplify to: -amount * sqrtPriceInXInQ72 / activeLiquidityScalerInQ72 -final equation: -amountLAssets = mulDiv(amount, sqrtPriceInXInQ72, activeLiquidityScalerInQ72, rounding); +Convert Y assets to L assets: L = y * sqrt(p) +amountLAssets = amountInYAssets * sqrtPriceInXInQ72 / Q72 ```solidity function convertYToL( uint256 amountInYAssets, uint256 sqrtPriceInXInQ72, - uint256 activeLiquidityScalerInQ72, bool roundUp ) internal pure returns (uint256 amountInLAssets); ``` ### convertLToY +Convert L assets to Y assets: y = L / sqrt(p) +amountYAssets = amount * Q72 / sqrtPriceQ72 + ```solidity function convertLToY( uint256 amount, uint256 sqrtPriceQ72, - uint256 activeLiquidityScalerInQ72, bool roundUp ) internal pure returns (uint256 amountYAssets); ``` @@ -310,7 +245,7 @@ The reserves available in and out for swapping can be defined in terms of $L$, a ```math \begin{align*} reserveIn &= L \cdot \sqrt{p} \\ -reserveOut &= \frac{L}{ \sqrt{p} } \\ +reserveOut &= \frac`L`{ \sqrt{p} } \\ \end{align*} ``` The swap amount $in$ and $out$ can also be defined in terms of $L_{in}$ and @@ -336,10 +271,10 @@ We now plug in liquidity values in place of $reserveIn$, $reserveOut$, $in$, and \begin{align*} L_{in} \cdot 2 \cdot \sqrt{p} &= \frac{ L \cdot \sqrt{p} \cdot \frac{ 2 \cdot L_{out} }{ \sqrt{p} } } -{ \frac{L}{ \sqrt{p} } - \frac{ 2 \cdot L_{out} }{\sqrt{p} } } \\ +{ \frac`L`{ \sqrt{p} } - \frac{ 2 \cdot L_{out} }{\sqrt{p} } } \\ L_{in} &= \frac{ L \cdot \sqrt{p} \cdot \frac{ 2 \cdot L_{out} }{ \sqrt{p} } } -{ 2 \cdot \sqrt{p} \cdot \left(\frac{L}{ \sqrt{p} } - \frac{ 2 \cdot L_{out} }{\sqrt{p} }\right)} \\ +{ 2 \cdot \sqrt{p} \cdot \left(\frac`L`{ \sqrt{p} } - \frac{ 2 \cdot L_{out} }{\sqrt{p} }\right)} \\ L_{in} &= \frac { L \cdot L_{out} } { (L - 2 \cdot L_{out}) } \\ @@ -432,7 +367,6 @@ struct InputParams { int16 maxTick; uint256 sqrtPriceMinInQ72; uint256 sqrtPriceMaxInQ72; - uint256 activeLiquidityScalerInQ72; uint256 activeLiquidityAssets; uint256 reservesXAssets; uint256 reservesYAssets; diff --git a/docs/developer-guide/contracts/libraries/constants.sol/constants.constants.md b/docs/developer-guide/contracts/libraries/constants.sol/constants.constants.md index f0fc46f4..499f86db 100644 --- a/docs/developer-guide/contracts/libraries/constants.sol/constants.constants.md +++ b/docs/developer-guide/contracts/libraries/constants.sol/constants.constants.md @@ -1,5 +1,5 @@ # Constants -[Git Source](https://github.com/Ammalgam-Protocol/core-v1/blob/2b185eab2df708b55f7ffa534655c69f626e73b3/contracts/libraries/constants.sol) +[Git Source](https://github.com/Ammalgam-Protocol/core-v1/blob/ec51218155bd2f8c1e5dc761ed4728baae81a01b/contracts/libraries/constants.sol) ### B_IN_Q72 *This basis was a modification to Uniswap V3's basis, to fit ticks into int16 instead of @@ -81,7 +81,7 @@ uint256 constant EXPECTED_SATURATION_LTV_MAG2 = 85; ### MAX_SATURATION_RATIO_IN_MAG2 *percentage of max sat per tranche considered healthy; max sat per -tranche is $$liquidity \frac{B-1}{2}$$ with B the tranche basis, which is the max +tranche is $$liquidity \frac`B-1`{2}$$ with B the tranche basis, which is the max sat such that the liquidation would not cause a swap larger than a tranche* @@ -89,15 +89,6 @@ sat such that the liquidation would not cause a swap larger than a tranche* uint256 constant MAX_SATURATION_RATIO_IN_MAG2 = 95; ``` -### LENDING_TICK_NOT_AVAILABLE -*Represents the absence of a valid lending tick, initialized to `int16` minimum value since a -`type(int16).min < MIN_TICK`.* - - -```solidity -int16 constant LENDING_TICK_NOT_AVAILABLE = type(int16).min; -``` - ### ZERO_ADDRESS *the default zero address* diff --git a/docs/developer-guide/contracts/proxy/BeaconController.sol/contract.BeaconController.md b/docs/developer-guide/contracts/proxy/BeaconController.sol/contract.BeaconController.md index 6ccb1f0e..2e123a5f 100644 --- a/docs/developer-guide/contracts/proxy/BeaconController.sol/contract.BeaconController.md +++ b/docs/developer-guide/contracts/proxy/BeaconController.sol/contract.BeaconController.md @@ -1,5 +1,5 @@ # BeaconController -[Git Source](https://github.com/Ammalgam-Protocol/core-v1/blob/2b185eab2df708b55f7ffa534655c69f626e73b3/contracts/proxy/BeaconController.sol) +[Git Source](https://github.com/Ammalgam-Protocol/core-v1/blob/ec51218155bd2f8c1e5dc761ed4728baae81a01b/contracts/proxy/BeaconController.sol) **Inherits:** [IBeaconController](/docs/developer-guide/contracts/proxy/BeaconController.sol/interface.IBeaconController.md), AccessControl diff --git a/docs/developer-guide/contracts/proxy/BeaconController.sol/interface.IBeaconController.md b/docs/developer-guide/contracts/proxy/BeaconController.sol/interface.IBeaconController.md index b6e532dc..1b116a24 100644 --- a/docs/developer-guide/contracts/proxy/BeaconController.sol/interface.IBeaconController.md +++ b/docs/developer-guide/contracts/proxy/BeaconController.sol/interface.IBeaconController.md @@ -1,5 +1,5 @@ # IBeaconController -[Git Source](https://github.com/Ammalgam-Protocol/core-v1/blob/2b185eab2df708b55f7ffa534655c69f626e73b3/contracts/proxy/BeaconController.sol) +[Git Source](https://github.com/Ammalgam-Protocol/core-v1/blob/ec51218155bd2f8c1e5dc761ed4728baae81a01b/contracts/proxy/BeaconController.sol) ## Functions diff --git a/docs/developer-guide/contracts/proxy/PairBeaconProxy.sol/contract.InitializablePair.md b/docs/developer-guide/contracts/proxy/PairBeaconProxy.sol/contract.InitializablePair.md index b125b4fd..66b77afb 100644 --- a/docs/developer-guide/contracts/proxy/PairBeaconProxy.sol/contract.InitializablePair.md +++ b/docs/developer-guide/contracts/proxy/PairBeaconProxy.sol/contract.InitializablePair.md @@ -1,5 +1,5 @@ # InitializablePair -[Git Source](https://github.com/Ammalgam-Protocol/core-v1/blob/2b185eab2df708b55f7ffa534655c69f626e73b3/contracts/proxy/PairBeaconProxy.sol) +[Git Source](https://github.com/Ammalgam-Protocol/core-v1/blob/ec51218155bd2f8c1e5dc761ed4728baae81a01b/contracts/proxy/PairBeaconProxy.sol) **Inherits:** [IPairInitializable](/docs/developer-guide/contracts/proxy/PairBeaconProxy.sol/interface.IPairInitializable.md), Initializable @@ -27,11 +27,22 @@ function initialize() external initializer; function _initialize() internal virtual; ``` +### onlyProxySelfCall + +Allows only the proxy-controlled self-call used by beacon upgrade reinitialization. + + +```solidity +modifier onlyProxySelfCall(); +``` + ### reInitialize +Reinitializes the pair only when the proxy calls itself after a beacon implementation upgrade. + ```solidity -function reInitialize() external reinitializer(_getInitializedVersion() + 1); +function reInitialize() external onlyProxySelfCall reinitializer(_getInitializedVersion() + 1); ``` ### _reInitialize @@ -41,3 +52,10 @@ function reInitialize() external reinitializer(_getInitializedVersion() + 1); function _reInitialize() internal virtual; ``` +## Errors +### AccessDenied + +```solidity +error AccessDenied(); +``` + diff --git a/docs/developer-guide/contracts/proxy/PairBeaconProxy.sol/contract.PairBeaconProxy.md b/docs/developer-guide/contracts/proxy/PairBeaconProxy.sol/contract.PairBeaconProxy.md index b43beede..9ed6a269 100644 --- a/docs/developer-guide/contracts/proxy/PairBeaconProxy.sol/contract.PairBeaconProxy.md +++ b/docs/developer-guide/contracts/proxy/PairBeaconProxy.sol/contract.PairBeaconProxy.md @@ -1,5 +1,5 @@ # PairBeaconProxy -[Git Source](https://github.com/Ammalgam-Protocol/core-v1/blob/2b185eab2df708b55f7ffa534655c69f626e73b3/contracts/proxy/PairBeaconProxy.sol) +[Git Source](https://github.com/Ammalgam-Protocol/core-v1/blob/ec51218155bd2f8c1e5dc761ed4728baae81a01b/contracts/proxy/PairBeaconProxy.sol) **Inherits:** BeaconProxy diff --git a/docs/developer-guide/contracts/proxy/PairBeaconProxy.sol/interface.IPairInitializable.md b/docs/developer-guide/contracts/proxy/PairBeaconProxy.sol/interface.IPairInitializable.md index 3d13d075..ddcb5ce1 100644 --- a/docs/developer-guide/contracts/proxy/PairBeaconProxy.sol/interface.IPairInitializable.md +++ b/docs/developer-guide/contracts/proxy/PairBeaconProxy.sol/interface.IPairInitializable.md @@ -1,5 +1,5 @@ # IPairInitializable -[Git Source](https://github.com/Ammalgam-Protocol/core-v1/blob/2b185eab2df708b55f7ffa534655c69f626e73b3/contracts/proxy/PairBeaconProxy.sol) +[Git Source](https://github.com/Ammalgam-Protocol/core-v1/blob/ec51218155bd2f8c1e5dc761ed4728baae81a01b/contracts/proxy/PairBeaconProxy.sol) ## Functions diff --git a/docs/developer-guide/contracts/proxy/PairBlockAllTransfers.sol/contract.PairBlockAllTransfers.md b/docs/developer-guide/contracts/proxy/PairBlockLendingFundRemoval.sol/contract.PairBlockLendingFundRemoval.md similarity index 69% rename from docs/developer-guide/contracts/proxy/PairBlockAllTransfers.sol/contract.PairBlockAllTransfers.md rename to docs/developer-guide/contracts/proxy/PairBlockLendingFundRemoval.sol/contract.PairBlockLendingFundRemoval.md index 0d836be5..19ca3030 100644 --- a/docs/developer-guide/contracts/proxy/PairBlockAllTransfers.sol/contract.PairBlockAllTransfers.md +++ b/docs/developer-guide/contracts/proxy/PairBlockLendingFundRemoval.sol/contract.PairBlockLendingFundRemoval.md @@ -1,11 +1,20 @@ -# PairBlockAllTransfers -[Git Source](https://github.com/Ammalgam-Protocol/core-v1/blob/2b185eab2df708b55f7ffa534655c69f626e73b3/contracts/proxy/PairBlockAllTransfers.sol) +# PairBlockLendingFundRemoval +[Git Source](https://github.com/Ammalgam-Protocol/core-v1/blob/ec51218155bd2f8c1e5dc761ed4728baae81a01b/contracts/proxy/PairBlockLendingFundRemoval.sol) **Inherits:** [AmmalgamPair](/docs/developer-guide/contracts/AmmalgamPair.sol/contract.AmmalgamPair.md) ## Functions +### _initialize + +*Reverts during proxy construction so createPair fails, forbidding new pairs under this restricted implementation.* + + +```solidity +function _initialize() internal pure override; +``` + ### withdraw @@ -70,3 +79,9 @@ error BORROW_BLOCKED(); error LIQUIDATION_BLOCKED(); ``` +### INIT_BLOCKED + +```solidity +error INIT_BLOCKED(); +``` + diff --git a/docs/developer-guide/contracts/proxy/PairFrozen.sol/contract.PairFrozen.md b/docs/developer-guide/contracts/proxy/PairFrozen.sol/contract.PairFrozen.md index 1cfa72a3..3c423810 100644 --- a/docs/developer-guide/contracts/proxy/PairFrozen.sol/contract.PairFrozen.md +++ b/docs/developer-guide/contracts/proxy/PairFrozen.sol/contract.PairFrozen.md @@ -1,11 +1,20 @@ # PairFrozen -[Git Source](https://github.com/Ammalgam-Protocol/core-v1/blob/2b185eab2df708b55f7ffa534655c69f626e73b3/contracts/proxy/PairFrozen.sol) +[Git Source](https://github.com/Ammalgam-Protocol/core-v1/blob/ec51218155bd2f8c1e5dc761ed4728baae81a01b/contracts/proxy/PairFrozen.sol) **Inherits:** [InitializablePair](/docs/developer-guide/contracts/proxy/PairBeaconProxy.sol/contract.InitializablePair.md) ## Functions +### _initialize + +*Reverts during proxy construction so createPair fails instead of poisoning the factory slot.* + + +```solidity +function _initialize() internal pure override; +``` + ### fallback diff --git a/docs/developer-guide/contracts/proxy/PairLockedLoans.sol/contract.PairLockedLoans.md b/docs/developer-guide/contracts/proxy/PairLockedLoans.sol/contract.PairLockedLoans.md index b092e973..0e39de8a 100644 --- a/docs/developer-guide/contracts/proxy/PairLockedLoans.sol/contract.PairLockedLoans.md +++ b/docs/developer-guide/contracts/proxy/PairLockedLoans.sol/contract.PairLockedLoans.md @@ -1,11 +1,20 @@ # PairLockedLoans -[Git Source](https://github.com/Ammalgam-Protocol/core-v1/blob/2b185eab2df708b55f7ffa534655c69f626e73b3/contracts/proxy/PairLockedLoans.sol) +[Git Source](https://github.com/Ammalgam-Protocol/core-v1/blob/ec51218155bd2f8c1e5dc761ed4728baae81a01b/contracts/proxy/PairLockedLoans.sol) **Inherits:** [AmmalgamPair](/docs/developer-guide/contracts/AmmalgamPair.sol/contract.AmmalgamPair.md) ## Functions +### _initialize + +*Reverts during proxy construction so createPair cannot deploy new pairs using this restricted implementation.* + + +```solidity +function _initialize() internal pure override; +``` + ### borrow @@ -57,3 +66,9 @@ error WITHDRAW_LOCKED(); error BURN_LOCKED(); ``` +### INIT_LOCKED + +```solidity +error INIT_LOCKED(); +``` + diff --git a/docs/developer-guide/contracts/tokens/ERC20Base.sol/abstract.ERC20Base.md b/docs/developer-guide/contracts/tokens/ERC20Base.sol/abstract.ERC20Base.md index ba4da0ce..3d1a88a2 100644 --- a/docs/developer-guide/contracts/tokens/ERC20Base.sol/abstract.ERC20Base.md +++ b/docs/developer-guide/contracts/tokens/ERC20Base.sol/abstract.ERC20Base.md @@ -1,5 +1,5 @@ # ERC20Base -[Git Source](https://github.com/Ammalgam-Protocol/core-v1/blob/2b185eab2df708b55f7ffa534655c69f626e73b3/contracts/tokens/ERC20Base.sol) +[Git Source](https://github.com/Ammalgam-Protocol/core-v1/blob/ec51218155bd2f8c1e5dc761ed4728baae81a01b/contracts/tokens/ERC20Base.sol) **Inherits:** ERC20Hooks, Ownable, ERC20Permit, [IAmmalgamERC20](/docs/developer-guide/contracts/interfaces/tokens/IAmmalgamERC20.sol/interface.IAmmalgamERC20.md) diff --git a/docs/developer-guide/contracts/tokens/ERC20Base.sol/struct.ERC20BaseConfig.md b/docs/developer-guide/contracts/tokens/ERC20Base.sol/struct.ERC20BaseConfig.md index c60f834d..ad6c48a1 100644 --- a/docs/developer-guide/contracts/tokens/ERC20Base.sol/struct.ERC20BaseConfig.md +++ b/docs/developer-guide/contracts/tokens/ERC20Base.sol/struct.ERC20BaseConfig.md @@ -1,5 +1,5 @@ # ERC20BaseConfig -[Git Source](https://github.com/Ammalgam-Protocol/core-v1/blob/2b185eab2df708b55f7ffa534655c69f626e73b3/contracts/tokens/ERC20Base.sol) +[Git Source](https://github.com/Ammalgam-Protocol/core-v1/blob/ec51218155bd2f8c1e5dc761ed4728baae81a01b/contracts/tokens/ERC20Base.sol) ```solidity diff --git a/docs/developer-guide/contracts/tokens/ERC20DebtBase.sol/abstract.ERC20DebtBase.md b/docs/developer-guide/contracts/tokens/ERC20DebtBase.sol/abstract.ERC20DebtBase.md index 35b8764b..3b8e11a7 100644 --- a/docs/developer-guide/contracts/tokens/ERC20DebtBase.sol/abstract.ERC20DebtBase.md +++ b/docs/developer-guide/contracts/tokens/ERC20DebtBase.sol/abstract.ERC20DebtBase.md @@ -1,5 +1,5 @@ # ERC20DebtBase -[Git Source](https://github.com/Ammalgam-Protocol/core-v1/blob/2b185eab2df708b55f7ffa534655c69f626e73b3/contracts/tokens/ERC20DebtBase.sol) +[Git Source](https://github.com/Ammalgam-Protocol/core-v1/blob/ec51218155bd2f8c1e5dc761ed4728baae81a01b/contracts/tokens/ERC20DebtBase.sol) **Inherits:** [ERC20Base](/docs/developer-guide/contracts/tokens/ERC20Base.sol/abstract.ERC20Base.md), [IERC20DebtToken](/docs/developer-guide/contracts/interfaces/tokens/IERC20DebtToken.sol/interface.IERC20DebtToken.md) @@ -26,12 +26,9 @@ function nonces( ### approve -*Standard ERC20 approve is disabled for debt tokens. -Allowances must be set via approveDebt using debt-specific semantics.* - ```solidity -function approve(address, uint256) public pure virtual override(ERC20, IERC20) returns (bool); +function approve(address spender, uint256 amount) public virtual override(ERC20, IERC20) returns (bool); ``` ### allowance diff --git a/docs/developer-guide/contracts/tokens/ERC20DebtLiquidityToken.sol/contract.ERC20DebtLiquidityToken.md b/docs/developer-guide/contracts/tokens/ERC20DebtLiquidityToken.sol/contract.ERC20DebtLiquidityToken.md index 49c58f0a..0c8d52d4 100644 --- a/docs/developer-guide/contracts/tokens/ERC20DebtLiquidityToken.sol/contract.ERC20DebtLiquidityToken.md +++ b/docs/developer-guide/contracts/tokens/ERC20DebtLiquidityToken.sol/contract.ERC20DebtLiquidityToken.md @@ -1,5 +1,5 @@ # ERC20DebtLiquidityToken -[Git Source](https://github.com/Ammalgam-Protocol/core-v1/blob/2b185eab2df708b55f7ffa534655c69f626e73b3/contracts/tokens/ERC20DebtLiquidityToken.sol) +[Git Source](https://github.com/Ammalgam-Protocol/core-v1/blob/ec51218155bd2f8c1e5dc761ed4728baae81a01b/contracts/tokens/ERC20DebtLiquidityToken.sol) **Inherits:** [ERC20DebtBase](/docs/developer-guide/contracts/tokens/ERC20DebtBase.sol/abstract.ERC20DebtBase.md) diff --git a/docs/developer-guide/contracts/tokens/ERC20LiquidityToken.sol/contract.ERC20LiquidityToken.md b/docs/developer-guide/contracts/tokens/ERC20LiquidityToken.sol/contract.ERC20LiquidityToken.md index 8f51988b..fbdf3be5 100644 --- a/docs/developer-guide/contracts/tokens/ERC20LiquidityToken.sol/contract.ERC20LiquidityToken.md +++ b/docs/developer-guide/contracts/tokens/ERC20LiquidityToken.sol/contract.ERC20LiquidityToken.md @@ -1,5 +1,5 @@ # ERC20LiquidityToken -[Git Source](https://github.com/Ammalgam-Protocol/core-v1/blob/2b185eab2df708b55f7ffa534655c69f626e73b3/contracts/tokens/ERC20LiquidityToken.sol) +[Git Source](https://github.com/Ammalgam-Protocol/core-v1/blob/ec51218155bd2f8c1e5dc761ed4728baae81a01b/contracts/tokens/ERC20LiquidityToken.sol) **Inherits:** [ERC20Base](/docs/developer-guide/contracts/tokens/ERC20Base.sol/abstract.ERC20Base.md) @@ -17,7 +17,7 @@ constructor( ### ownerMint -*override [ERC20Base-ownerMint](/docs/developer-guide/contracts/tokens/ERC4626DebtToken.sol/contract.ERC4626DebtToken.md#ownermint).* +*override [ERC20Base-ownerMint](/docs/developer-guide/contracts/tokens/ERC4626DepositToken.sol/contract.ERC4626DepositToken.md#ownermint).* ```solidity @@ -26,7 +26,7 @@ function ownerMint(address sender, address to, uint256 assets, uint256 shares) p ### ownerBurn -*override [ERC20Base-ownerBurn](/docs/developer-guide/contracts/tokens/ERC4626DebtToken.sol/contract.ERC4626DebtToken.md#ownerburn).* +*override [ERC20Base-ownerBurn](/docs/developer-guide/contracts/tokens/ERC4626DepositToken.sol/contract.ERC4626DepositToken.md#ownerburn).* ```solidity diff --git a/docs/developer-guide/contracts/tokens/ERC4626DebtToken.sol/contract.ERC4626DebtToken.md b/docs/developer-guide/contracts/tokens/ERC4626DebtToken.sol/contract.ERC4626DebtToken.md index 3cbef634..eaebf9e2 100644 --- a/docs/developer-guide/contracts/tokens/ERC4626DebtToken.sol/contract.ERC4626DebtToken.md +++ b/docs/developer-guide/contracts/tokens/ERC4626DebtToken.sol/contract.ERC4626DebtToken.md @@ -1,5 +1,5 @@ # ERC4626DebtToken -[Git Source](https://github.com/Ammalgam-Protocol/core-v1/blob/2b185eab2df708b55f7ffa534655c69f626e73b3/contracts/tokens/ERC4626DebtToken.sol) +[Git Source](https://github.com/Ammalgam-Protocol/core-v1/blob/ec51218155bd2f8c1e5dc761ed4728baae81a01b/contracts/tokens/ERC4626DebtToken.sol) **Inherits:** ERC4626, [ERC20DebtBase](/docs/developer-guide/contracts/tokens/ERC20DebtBase.sol/abstract.ERC20DebtBase.md) @@ -119,7 +119,7 @@ function previewMint( ### _deposit -*ERC4626 facade for [IAmmalgamPair-borrow](/docs/developer-guide/contracts/interfaces/IAmmalgamPair.sol/interface.IAmmalgamPair.md#borrow). +*ERC4626 facade for IAmmalgamPair-borrow. both deposit and mint calls _deposit This is called when the user is borrowing* @@ -130,7 +130,7 @@ function _deposit(address caller, address receiver, uint256 assets, uint256) int ### _withdraw -*ERC4626 facade for [IAmmalgamPair-repay](/docs/developer-guide/contracts/interfaces/IAmmalgamPair.sol/interface.IAmmalgamPair.md#repay). +*ERC4626 facade for IAmmalgamPair-repay. both withdraw and redeem calls _withdraw This is called when the user is repaying their debt* @@ -149,7 +149,7 @@ function _withdraw( ```solidity -function approve(address account, uint256 balance) public pure override(ERC20, ERC20DebtBase, IERC20) returns (bool); +function approve(address spender, uint256 amount) public override(ERC20, ERC20DebtBase, IERC20) returns (bool); ``` ### allowance diff --git a/docs/developer-guide/contracts/tokens/ERC4626DepositToken.sol/contract.ERC4626DepositToken.md b/docs/developer-guide/contracts/tokens/ERC4626DepositToken.sol/contract.ERC4626DepositToken.md index a7ee1db6..7ad7c690 100644 --- a/docs/developer-guide/contracts/tokens/ERC4626DepositToken.sol/contract.ERC4626DepositToken.md +++ b/docs/developer-guide/contracts/tokens/ERC4626DepositToken.sol/contract.ERC4626DepositToken.md @@ -1,5 +1,5 @@ # ERC4626DepositToken -[Git Source](https://github.com/Ammalgam-Protocol/core-v1/blob/2b185eab2df708b55f7ffa534655c69f626e73b3/contracts/tokens/ERC4626DepositToken.sol) +[Git Source](https://github.com/Ammalgam-Protocol/core-v1/blob/ec51218155bd2f8c1e5dc761ed4728baae81a01b/contracts/tokens/ERC4626DepositToken.sol) **Inherits:** ERC4626, [ERC20Base](/docs/developer-guide/contracts/tokens/ERC20Base.sol/abstract.ERC20Base.md) @@ -15,7 +15,7 @@ constructor(ERC20BaseConfig memory config, address _asset) ERC4626(IERC20(_asset ### ownerMint -*override [ERC20Base-ownerMint](/docs/developer-guide/contracts/interfaces/tokens/IAmmalgamERC20.sol/interface.IAmmalgamERC20.md#ownermint).* +*override `ERC20Base-ownerMint`.* ```solidity @@ -33,7 +33,7 @@ function ownerMint(address sender, address to, uint256 assets, uint256 shares) p ### ownerBurn -*override [ERC20Base-ownerBurn](/docs/developer-guide/contracts/interfaces/tokens/IAmmalgamERC20.sol/interface.IAmmalgamERC20.md#ownerburn).* +*override `ERC20Base-ownerBurn`.* ```solidity @@ -51,7 +51,7 @@ function ownerBurn(address sender, address to, uint256 assets, uint256 shares) p ### _deposit -*ERC4626 facade for [IAmmalgamPair-deposit](/docs/developer-guide/contracts/interfaces/IAmmalgamPair.sol/interface.IAmmalgamPair.md#deposit). +*ERC4626 facade for IAmmalgamPair-deposit. both deposit and mint calls _deposit* @@ -61,7 +61,7 @@ function _deposit(address caller, address receiver, uint256 assets, uint256) int ### _withdraw -*ERC4626 facade for [IAmmalgamPair-withdraw](/docs/developer-guide/contracts/interfaces/IAmmalgamPair.sol/interface.IAmmalgamPair.md#withdraw). +*ERC4626 facade for IAmmalgamPair-withdraw. both withdraw and redeem calls _withdraw* diff --git a/docs/developer-guide/contracts/tokens/HookRegistry.sol/contract.HookRegistry.md b/docs/developer-guide/contracts/tokens/HookRegistry.sol/contract.HookRegistry.md index fcc54896..8c3111b9 100644 --- a/docs/developer-guide/contracts/tokens/HookRegistry.sol/contract.HookRegistry.md +++ b/docs/developer-guide/contracts/tokens/HookRegistry.sol/contract.HookRegistry.md @@ -1,5 +1,5 @@ # HookRegistry -[Git Source](https://github.com/Ammalgam-Protocol/core-v1/blob/2b185eab2df708b55f7ffa534655c69f626e73b3/contracts/tokens/HookRegistry.sol) +[Git Source](https://github.com/Ammalgam-Protocol/core-v1/blob/ec51218155bd2f8c1e5dc761ed4728baae81a01b/contracts/tokens/HookRegistry.sol) **Inherits:** [IHookRegistry](/docs/developer-guide/contracts/interfaces/tokens/IHookRegistry.sol/interface.IHookRegistry.md), Ownable diff --git a/docs/developer-guide/contracts/tokens/TokenController.sol/contract.TokenController.md b/docs/developer-guide/contracts/tokens/TokenController.sol/contract.TokenController.md index 443f0516..3c1685f3 100644 --- a/docs/developer-guide/contracts/tokens/TokenController.sol/contract.TokenController.md +++ b/docs/developer-guide/contracts/tokens/TokenController.sol/contract.TokenController.md @@ -1,5 +1,5 @@ # TokenController -[Git Source](https://github.com/Ammalgam-Protocol/core-v1/blob/2b185eab2df708b55f7ffa534655c69f626e73b3/contracts/tokens/TokenController.sol) +[Git Source](https://github.com/Ammalgam-Protocol/core-v1/blob/ec51218155bd2f8c1e5dc761ed4728baae81a01b/contracts/tokens/TokenController.sol) **Inherits:** [InitializablePair](/docs/developer-guide/contracts/proxy/PairBeaconProxy.sol/contract.InitializablePair.md), [ITokenController](/docs/developer-guide/contracts/interfaces/tokens/ITokenController.sol/interface.ITokenController.md) @@ -86,9 +86,14 @@ uint112[6] private allShares; ### allAssets +The first position in this array is never stored because it is instead computed as +$$\sqrt{reserveX * reserveY} + borrowedLAssets$$. We keep this storage spot because +we heavily use DEPOSIT_L, DEPOSIT_X, DEPOSIT_Y, BORROW_L, BORROW_X, BORROW_Y to look +up positions throughout the code and didn't want to change all those references. + ```solidity -uint112[6] internal allAssets; +uint112[6] private allAssets; ``` @@ -134,13 +139,6 @@ uint32 internal lastLendingTimestamp; ``` -### lastReserveLiquidity - -```solidity -uint112 internal lastReserveLiquidity; -``` - - ### externalLiquidity ```solidity @@ -204,6 +202,13 @@ uint112 internal transient totalBorrowYAssets; ``` +### activeLiquidityAssets + +```solidity +uint112 internal transient activeLiquidityAssets; +``` + + ## Functions ### _initialize @@ -237,7 +242,7 @@ function underlyingTokens() public view virtual override returns (IERC20, IERC20 ```solidity -function updateAssets(uint256 tokenType, uint112 assets) private; +function updateAssets(uint256 tokenType, uint112 assets) internal; ``` ### updateExternalLiquidity @@ -294,7 +299,7 @@ function totalShares( ```solidity function rawTotalAssets( uint256 tokenType -) internal view returns (uint112); +) internal view returns (uint256 assetAmount); ``` ### getRawReserves @@ -333,10 +338,20 @@ function totalAssetsAndShares( ### fragileLiquidityAssets +Computes fragile liquidity and validates it can be removed from active liquidity. + ```solidity -function fragileLiquidityAssets() internal view returns (uint256 _fragileLiquidityAssets); +function fragileLiquidityAssets( + uint256 _activeLiquidityAssets +) internal view returns (uint256 _fragileLiquidityAssets); ``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`_activeLiquidityAssets`|`uint256`|The active liquidity available before the fragile liquidity decrement.| + ### updateFragileLiquidity @@ -492,11 +507,72 @@ function getNetBalances(uint256 _reserveXAssets, uint256 _reserveYAssets) intern function missingAssets() internal view returns (uint112 missingXAssets, uint112 missingYAssets); ``` -### getDepositAndActiveLiquidityAssets +### calculateActiveLiquidityAssets + +Active liquidity from reserves, using the same depletion adjustment as the swap +K-check in `calculateReserveAdjustmentsForMissingAssets`. Caching raw `sqrt(X*Y)` is +non-monotonic across depletion cycles, letting saturation-tree leaves register above the +post-recovery `maxLeaf` and bricking the pair with `MaxTrancheOverSaturated()`. + + +```solidity +function calculateActiveLiquidityAssets( + uint256 _reserveXAssets, + uint256 _reserveYAssets +) internal view returns (uint256); +``` +**Parameters** -Get the deposit, borrow, and active liquidity assets. +|Name|Type|Description| +|----|----|-----------| +|`_reserveXAssets`|`uint256`|The reserve X used for the active-liquidity calculation.| +|`_reserveYAssets`|`uint256`|The reserve Y used for the active-liquidity calculation.| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|``|`uint256`|The depletion-adjusted active liquidity, i.e. sqrt of the adjusted-reserve product.| + + +### calculateReserveAdjustmentsForMissingAssets + +helper method to calculate balance adjustment for missing assets + +*In the depleted case the adjusted reserve is `(reserve - missing) * bufferNumerator`, +matching the `BUFFER_NUMERATOR` scaling applied by `calculateBalanceAfterFees` so the +K comparison stays division-free. +For updateObservation, different scaled `buffer` and `bufferNumerator` values +are supplied so the adjusted reserve reflects observation-specific logic.* + + +```solidity +function calculateReserveAdjustmentsForMissingAssets( + uint256 reserve, + uint256 missing, + uint256 buffer, + uint256 bufferNumerator +) internal pure returns (uint256 reserveAdjustment); +``` +**Parameters** + +|Name|Type|Description| +|----|----|-----------| +|`reserve`|`uint256`|the starting reserve| +|`missing`|`uint256`|the missing assets, zero if deposits > borrows of X or Y| +|`buffer`|`uint256`| Scaling factor applied to the reserve for the depletion comparison.| +|`bufferNumerator`|`uint256`| Scaling factor applied to the missing amount for the comparison and for computing the depleted-case adjusted reserve.| + +**Returns** + +|Name|Type|Description| +|----|----|-----------| +|`reserveAdjustment`|`uint256`|The adjusted reserve value used for swap or updateObservation depends on the buffer, bufferNumerator to be passed in.| + + +### getDepositAndActiveLiquidityAssets -*This function is used to get the deposit liquidity assets, borrow liquidity assets (BLA), last active liquidity assets (ALA_0), and current active liquidity assets (ALA_1).* +Get the deposit, and active liquidity assets. ```solidity diff --git a/docs/developer-guide/contracts/utils/deployHelper.sol/function.deployFactory.md b/docs/developer-guide/contracts/utils/deployHelper.sol/function.deployFactory.md index 10f5adf2..203bbcf1 100644 --- a/docs/developer-guide/contracts/utils/deployHelper.sol/function.deployFactory.md +++ b/docs/developer-guide/contracts/utils/deployHelper.sol/function.deployFactory.md @@ -1,5 +1,5 @@ # function deployFactory -[Git Source](https://github.com/Ammalgam-Protocol/core-v1/blob/2b185eab2df708b55f7ffa534655c69f626e73b3/contracts/utils/deployHelper.sol) +[Git Source](https://github.com/Ammalgam-Protocol/core-v1/blob/ec51218155bd2f8c1e5dc761ed4728baae81a01b/contracts/utils/deployHelper.sol) ### deployFactory(address)