From 23ddfafd465c4d445442c99ec8cf27a1025e063c Mon Sep 17 00:00:00 2001 From: Alexis-ETH Date: Tue, 21 Nov 2023 15:29:11 +0800 Subject: [PATCH 01/16] fix typo --- src/core/Arena.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/Arena.sol b/src/core/Arena.sol index 36c5a7f..bc493dd 100644 --- a/src/core/Arena.sol +++ b/src/core/Arena.sol @@ -86,7 +86,7 @@ contract Arena is IArena, Ownable { if (msg.sender != ma) { revert Errors.OnlyManager(); } - // collaterl address error + // collateral address error if (params.bk.collateral == address(0)) { revert Errors.ZeroValue(); } From 1e66926fd20d0aa787cb45c4b6b8e82161b6dcd9 Mon Sep 17 00:00:00 2001 From: 0xSpear <83915876+0xSpear@users.noreply.github.com> Date: Tue, 21 Nov 2023 07:43:12 +0000 Subject: [PATCH 02/16] inline comment change --- src/core/Arena.sol | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/core/Arena.sol b/src/core/Arena.sol index bc493dd..3c6f4e2 100644 --- a/src/core/Arena.sol +++ b/src/core/Arena.sol @@ -16,9 +16,7 @@ import { DeploymentParams } from "core/params/coreParams.sol"; import { SToken } from "core/token/SToken.sol"; import { getAdjustPrice } from "core/utils.sol"; -/// @notice Deploys battles. Sets pool underlying, collateral, fees and other -/// deployment -/// parameters. +/// @notice Deploys battles. Sets pool underlying, collateral, fees, expiries and other deployment parameters. contract Arena is IArena, Ownable { address public oracleAddr; address public managerAddr; @@ -102,7 +100,7 @@ contract Arena is IArena, Ownable { revert Errors.NotSupported(); } - // expiries must at 8am utc + // expiries must be at 8am utc if ((params.bk.expiries - 28_800) % 86_400 != 0 || block.timestamp >= params.bk.expiries) { revert Errors.NotSupportedExpiries(); } From d05fda407c48bcce4d8cd10805f12cac699e1aff Mon Sep 17 00:00:00 2001 From: 0xSpear <83915876+0xSpear@users.noreply.github.com> Date: Tue, 21 Nov 2023 08:19:31 +0000 Subject: [PATCH 03/16] update inline comments --- src/core/Arena.sol | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/core/Arena.sol b/src/core/Arena.sol index 3c6f4e2..f41ce4c 100644 --- a/src/core/Arena.sol +++ b/src/core/Arena.sol @@ -84,27 +84,27 @@ contract Arena is IArena, Ownable { if (msg.sender != ma) { revert Errors.OnlyManager(); } - // collateral address error + // checks for collateral address error if (params.bk.collateral == address(0)) { revert Errors.ZeroValue(); } - // not supported + // checks whether the collateral is supported if (!isPermissionless) { if (!collateralWhitelist[params.bk.collateral]) { revert Errors.NotSupported(); } } - + // checks whether the underlying is supported if (!underlyingWhitelist[params.bk.underlying]) { revert Errors.NotSupported(); } - // expiries must be at 8am utc + // requires expiries to be at 8am utc if ((params.bk.expiries - 28_800) % 86_400 != 0 || block.timestamp >= params.bk.expiries) { revert Errors.NotSupportedExpiries(); } - + // requires strike prices to be non-zero and rounded accordingly params.bk.strikeValue = getAdjustPrice(params.bk.strikeValue); if (params.bk.strikeValue == 0) { revert Errors.ZeroValue(); From 496657a5f7eb481ab565333d92a6434efd819007 Mon Sep 17 00:00:00 2001 From: 0xSpear <83915876+0xSpear@users.noreply.github.com> Date: Tue, 21 Nov 2023 13:03:24 +0000 Subject: [PATCH 04/16] updates inline comments for battle --- src/core/Battle.sol | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/src/core/Battle.sol b/src/core/Battle.sol index c55bdb4..88ff6e1 100644 --- a/src/core/Battle.sol +++ b/src/core/Battle.sol @@ -92,7 +92,7 @@ contract Battle is IBattle { _; } - /// @notice init storage state variable, only be caled once + /// @notice Initiates storage state variables. Only called once for a battle. function init(DeploymentParams memory params) external override { if (_bk.expiries != 0) { revert Errors.InitTwice(); @@ -110,7 +110,7 @@ contract Battle is IBattle { shield = params.shield; manager = params.manager; arena = address(msg.sender); - slot0 = Slot0({ sqrtPriceX96: params.sqrtPriceX96, tick: TickMath.getTickAtSqrtRatio(params.sqrtPriceX96), unlocked: true }); + slot0 = Slot0({sqrtPriceX96: params.sqrtPriceX96, tick: TickMath.getTickAtSqrtRatio(params.sqrtPriceX96), unlocked: true}); maxLiquidityPerTick = Tick.tickSpacingToMaxLiquidityPerTick(30); } @@ -269,7 +269,7 @@ contract Battle is IBattle { ); slot0.unlocked = false; - TradeCache memory cache = TradeCache({ feeProtocol: fee.protocolFee }); + TradeCache memory cache = TradeCache({feeProtocol: fee.protocolFee}); TradeState memory state = TradeState({ amountSpecifiedRemaining: params.amountSpecified, amountCalculated: 0, @@ -311,7 +311,7 @@ contract Battle is IBattle { state.amountSpecifiedRemaining += (step.amountOut).toInt256(); state.amountCalculated += (step.amountIn).toInt256(); } - + // feeAmount is computed on a notional basis using amountOut step.feeAmount = FullMath.mulDiv(step.amountOut, fee.transactionFee, 1e6); if (cache.feeProtocol > 0) { uint256 delta = FullMath.mulDiv(step.feeAmount, cache.feeProtocol, 1e6); @@ -324,15 +324,10 @@ contract Battle is IBattle { state.global.fee += FullMath.mulDiv(step.feeAmount, FixedPoint128.Q128, state.liquidity); state.transactionFee += step.feeAmount; state.global.collateralIn += FullMath.mulDiv(step.amountIn, FixedPoint128.Q128, state.liquidity); - + // Updates all-time growth of spear or shield deltas in the global state if (params.tradeType == TradeType.BUY_SPEAR) { - // buy spear => spearBought and shieldBankOut need be - // considered - // spear bought state.global.spearOut += FullMath.mulDiv(step.amountOut, FixedPoint128.Q128, state.liquidity); } else { - // buy shield => shieldBought and spearBankOut need be - // considered state.global.shieldOut += FullMath.mulDiv(step.amountOut, FixedPoint128.Q128, state.liquidity); } } @@ -381,10 +376,10 @@ contract Battle is IBattle { } if (params.tradeType == TradeType.BUY_SPEAR) { - // mint spear to user + // mints spear tokens to the buyer ISToken(spear).mint(params.recipient, sAmount); } else { - // mint shield to user + // mints shield tokens to the buyer ISToken(shield).mint(params.recipient, sAmount); } emit Traded(params.recipient, state.liquidity, cAmount, sAmount, params.tradeType, state.sqrtPriceX96, state.tick); From 940dcb82c89376b0495004e38ab05c4bfac3889f Mon Sep 17 00:00:00 2001 From: 0xSpear <83915876+0xSpear@users.noreply.github.com> Date: Tue, 21 Nov 2023 14:06:18 +0000 Subject: [PATCH 05/16] update inline comments for oracle --- src/core/Oracle.sol | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/src/core/Oracle.sol b/src/core/Oracle.sol index 74f847b..51f85bc 100644 --- a/src/core/Oracle.sol +++ b/src/core/Oracle.sol @@ -15,9 +15,8 @@ contract Oracle is Ownable { mapping(string => address) private _externalOracleOf; mapping(address => mapping(uint256 => uint256)) public fixPrices; - /// @notice Defines the underlying asset symbol and oracle address for a - /// pool. Only called by the owner. - /// @param symbols The asset symbol for which to retrieve price feed + /// @notice Defines the underlying asset symbol and oracle address for a pool. Only called by the owner. + /// @param symbols The asset symbol for which to retrieve a price feed /// @param oracles_ The external oracle address function setExternalOracle(string[] calldata symbols, address[] calldata oracles_) external onlyOwner { require(symbols.length == oracles_.length, "symbols not match oracles"); @@ -45,8 +44,8 @@ contract Oracle is Ownable { uint256 decimalDiff = 10 ** (18 - cOracle.decimals()); (uint256 cPrice, uint256 cActualTs) = _getPrice(cOracle, roundID, ts, decimalDiff); + // If the price remains unreported or inaccessible an hour post expiry, the closest available price will be fixed based on the external oracle data. if (block.timestamp - ts > 1 hours && cPrice == 0) { - // get price from setting require(fixPrices[cOracleAddr][ts] != 0, "setting price"); price = fixPrices[cOracleAddr][ts]; actualTs = ts; @@ -60,8 +59,7 @@ contract Oracle is Ownable { /// @param cOracle Oracle interface for retrieving price feed /// @param id The roundId using which price is retrieved /// @param ts Timestamp for the asset price - /// @param decimalDiff Precision differences for the number of decimal - /// places of retrieved data + /// @param decimalDiff Precision differences for the number of decimal places of retrieved data function _getPrice( AggregatorV3Interface cOracle, uint80 id, @@ -72,13 +70,13 @@ contract Oracle is Ownable { view returns (uint256 finalPrice, uint256 finalTs) { - // get next price after 8am utc + // get the next price after 8am utc uint80 phaseId = _getPhaseIdFromRoundId(id); uint80 startRoundId = _getStartRoundId(phaseId); try AggregatorV3Interface(cOracle).getRoundData(startRoundId) returns (uint80, int256, uint256, uint256 updatedAt, uint80) { //updatedAt == 0, invalid value //The situation where 'startRound' occurs after the 'endTs' of a battle is a special case that will affect corrections. - //Therefore, it will simply return a value of 0. The correct price will be provided by 'fixPrices'. + //Therefore, it will simply return a value of 0. The correct price will be provided by fixPrices. if (updatedAt == 0 || updatedAt >= ts) { return (0, 0); } else { @@ -86,7 +84,7 @@ contract Oracle is Ownable { (finalPrice, finalTs) = _getPriceInPhase(cOracle, startRoundId, id, ts, decimalDiff); } } catch { - // If there are any errors encountered, then the correct price will be provided by the 'fixPrices' + // If there are any errors encountered, then the correct price will be provided by fixPrices. // just return (0, 0) } } @@ -126,7 +124,7 @@ contract Oracle is Ownable { actualTs = updatedAt; } } catch { - // something is wrong + // in case of errors return (0, 0); } } From 257a9a783382ccade584d9b78f3ddea842aa3d81 Mon Sep 17 00:00:00 2001 From: 0xSpear <83915876+0xSpear@users.noreply.github.com> Date: Wed, 22 Nov 2023 09:14:48 +0000 Subject: [PATCH 06/16] update inline comments for oracle --- src/core/Oracle.sol | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/core/Oracle.sol b/src/core/Oracle.sol index 51f85bc..4fe32a9 100644 --- a/src/core/Oracle.sol +++ b/src/core/Oracle.sol @@ -8,7 +8,7 @@ import { AggregatorV3Interface } from "chainlink/interfaces/AggregatorV3Interfac import { getAdjustPrice } from "./utils.sol"; /// @title Oracle -/// @notice Get external price by Oracle +/// @notice Retrieves underlying asset prices used for settling options. contract Oracle is Ownable { using SafeCast for int256; @@ -32,7 +32,7 @@ contract Oracle is Ownable { } /// @notice Gets and computes price from external oracles - /// @param cOracleAddr chainlink price contract + /// @param cOracleAddr the contract address for a chainlink price feed /// @param ts Timestamp for the asset price /// @return price The retrieved price function getPriceByExternal(address cOracleAddr, uint256 ts) external view returns (uint256 price, uint256 actualTs) { @@ -75,8 +75,7 @@ contract Oracle is Ownable { uint80 startRoundId = _getStartRoundId(phaseId); try AggregatorV3Interface(cOracle).getRoundData(startRoundId) returns (uint80, int256, uint256, uint256 updatedAt, uint80) { //updatedAt == 0, invalid value - //The situation where 'startRound' occurs after the 'endTs' of a battle is a special case that will affect corrections. - //Therefore, it will simply return a value of 0. The correct price will be provided by fixPrices. + //In case the 'startRound' occurs after the 'endTs' of a battle due to external oracle updates, it returns 0. The correct price will be provided by fixPrices. if (updatedAt == 0 || updatedAt >= ts) { return (0, 0); } else { @@ -84,8 +83,7 @@ contract Oracle is Ownable { (finalPrice, finalTs) = _getPriceInPhase(cOracle, startRoundId, id, ts, decimalDiff); } } catch { - // If there are any errors encountered, then the correct price will be provided by fixPrices. - // just return (0, 0) + // If there are any errors encountered, it returns (0, 0). the correct price will be provided by fixPrices. } } From f8f701d4ec2c1e160a8b03b2db240dd450e5819a Mon Sep 17 00:00:00 2001 From: 0xSpear <83915876+0xSpear@users.noreply.github.com> Date: Wed, 22 Nov 2023 09:31:16 +0000 Subject: [PATCH 07/16] update inline comment for utils --- src/core/utils.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/utils.sol b/src/core/utils.sol index 7b9f15c..78f00d3 100644 --- a/src/core/utils.sol +++ b/src/core/utils.sol @@ -2,8 +2,8 @@ pragma solidity ^0.8.19; -// round down to two significant digits. -/// @param price price of underlying. price has decimal 18, eg. eth price 1500 will be 1500 * 10**18 +// Rounds down price input to two significant digits to adjust it for strike price. Assumes 18 decimal places (e.g., ETH price 1500 as 1500 * 10**18). +/// @param price Price of the underlying asset in 18 decimal format. function getAdjustPrice(uint256 price) pure returns (uint256 adjustedPrice) { require(price >= 1e12, "price too small"); uint256 i = 12; From 2836a3422be4fd9d372920e1350c5e9ca5fb8be2 Mon Sep 17 00:00:00 2001 From: 0xSpear <83915876+0xSpear@users.noreply.github.com> Date: Wed, 22 Nov 2023 09:39:41 +0000 Subject: [PATCH 08/16] update inline comments for stoken --- src/core/token/SToken.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/token/SToken.sol b/src/core/token/SToken.sol index 3e915d1..f999bb5 100644 --- a/src/core/token/SToken.sol +++ b/src/core/token/SToken.sol @@ -8,8 +8,8 @@ import { Ownable } from "@oz/access/Ownable.sol"; import { ISToken } from "core/interfaces/ISToken.sol"; /** - * @notice Spear or Shield - * @dev only battle contract(aka.owner) can mint or burn SToken + * @notice Implements digital call (Spear) and put (Shield) options as ERC-20 tokens (STokens). + * @dev Only the battle contract (owner) can mint or burn SToken */ contract SToken is ERC20Burnable, Ownable, ISToken { uint8 private immutable _decimals; From 8e91c5950f6494ec4aee13cd7a75ea9931238a25 Mon Sep 17 00:00:00 2001 From: 0xSpear <83915876+0xSpear@users.noreply.github.com> Date: Thu, 23 Nov 2023 02:51:47 +0000 Subject: [PATCH 09/16] update inline comments --- src/core/interfaces/battle/IBattleActions.sol | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/core/interfaces/battle/IBattleActions.sol b/src/core/interfaces/battle/IBattleActions.sol index f210b5d..adabb39 100644 --- a/src/core/interfaces/battle/IBattleActions.sol +++ b/src/core/interfaces/battle/IBattleActions.sol @@ -6,7 +6,7 @@ import { BattleMintParams, BattleBurnParams, BattleTradeParams } from "core/para import { PositionInfo, TradeType, Outcome, LiquidityType } from "core/types/common.sol"; interface IBattleMintBurn { - /// @param sender The address who minted the liquidity + /// @param sender The address that minted the liquidity /// @param liquidityType The type of liquidity minted /// @param tickLower The lower tick of the position /// @param tickUpper The upper tick of the position @@ -42,7 +42,7 @@ interface IBattleMintBurn { /// @title IBattleTrade interface IBattleTrade { - /// @notice trade spear/shield for collateral + /// @notice trade spear/shield tokens for collateral /// @param recipient The address who receive spear/shield /// @param liquidity liquity in battle after trade /// @param amountIn The amount of spear/shield to be traded @@ -72,7 +72,7 @@ interface IBattleBase { event ProtocolFeeCollected(address recipient, uint256 amount); - /// @notice settle the battle + /// @notice Settles the battle and determines the outcome. /// battle will fetch the price of underlying asset, and determinate the /// battle result. /// battle finished after settle function was called From 1ddcef29056633f249bc1bedbc7f08f0784e0e8e Mon Sep 17 00:00:00 2001 From: 0xSpear <83915876+0xSpear@users.noreply.github.com> Date: Thu, 23 Nov 2023 09:40:40 +0000 Subject: [PATCH 10/16] update inline comments --- src/core/interfaces/battle/IBattleActions.sol | 70 ++++++++----------- src/core/types/enums.sol | 3 +- 2 files changed, 30 insertions(+), 43 deletions(-) diff --git a/src/core/interfaces/battle/IBattleActions.sol b/src/core/interfaces/battle/IBattleActions.sol index adabb39..1f03253 100644 --- a/src/core/interfaces/battle/IBattleActions.sol +++ b/src/core/interfaces/battle/IBattleActions.sol @@ -6,34 +6,30 @@ import { BattleMintParams, BattleBurnParams, BattleTradeParams } from "core/para import { PositionInfo, TradeType, Outcome, LiquidityType } from "core/types/common.sol"; interface IBattleMintBurn { - /// @param sender The address that minted the liquidity - /// @param liquidityType The type of liquidity minted + /// @param sender The address used for minting liquidity + /// @param liquidityType The type of token used as liquidity /// @param tickLower The lower tick of the position /// @param tickUpper The upper tick of the position /// @param liquidity The amount of liquidity minted - /// @param seedAmount The amount of collateral/spear/shield(according to liquidityType) spent + /// @param seedAmount The amount of tokens used for minting liquidity, per collateral, spear or shield liquidityType event Minted(address indexed sender, LiquidityType liquidityType, int24 tickLower, int24 tickUpper, uint128 liquidity, uint256 seedAmount); /// @param tickLower The lower tick of the position /// @param tickUpper The upper tick of the position - /// @param liquidityType The type of liquidity burned + /// @param liquidityType The type of token used as liquidity /// @param liquidityAmount The amount of liquidity burned event Burned(int24 tickLower, int24 tickUpper, LiquidityType liquidityType, uint128 liquidityAmount); /// @notice Mint liquidity - /// @param mp The params of mint + /// @param mp The params for minting liquidity function mint(BattleMintParams memory mp) external; - // / @notice Burn liquidity for a slot - // / @dev - // / @return spearAmount The amount of spear tokens to be removed from curve - // / @return shieldAmount The amount of shield tokens to be removed from - // curve + /// @notice Burn liquidity + /// @param BurnParams The params for burning liquidity function burn(BattleBurnParams memory BurnParams) external; - /// @notice transfer collateral/spear/shield to lp - /// @dev only called by Manager contract - /// @param recipient The address who receive collateral/spear/shield + /// @notice Transfers collateral/spear/shield tokens to the liquidity provider. Only called by the manager contract + /// @param recipient The address who receive collateral/spear/shield tokens /// @param cAmount The amount of collateral to be transfered /// @param spAmount The amount of spear to be transfered /// @param shAmount The amount of shield to be transfered @@ -42,22 +38,22 @@ interface IBattleMintBurn { /// @title IBattleTrade interface IBattleTrade { - /// @notice trade spear/shield tokens for collateral - /// @param recipient The address who receive spear/shield + /// @notice Swap collateral for spear or shield tokens + /// @param recipient The address who receive spear or shield tokens /// @param liquidity liquity in battle after trade - /// @param amountIn The amount of spear/shield to be traded - /// @param amountOut The amount of collateral to be traded - /// @param tradeType buySpard or buyShield - /// @param sqrtPriceX96 The sqrt price of the battle after trade - /// @param tick The tick of the battle after trade + /// @param amountIn The amount of token input + /// @param amountOut The amount of token output + /// @param tradeType buySpear or buyShield + /// @param sqrtPriceX96 The sqrt price of the battle after the trade + /// @param tick The tick of the battle after the trade event Traded( address indexed recipient, uint128 liquidity, uint256 amountIn, uint256 amountOut, TradeType tradeType, uint160 sqrtPriceX96, int24 tick ); - /// @notice trade spear/shield for collateral - /// @param tp The params of trade - /// @return cAmount The amount of collateral user spent - /// @return sAmount The amount of spear/shield user received + /// @notice Swap collateral for spear or shield tokens + /// @param tp The params for the trade + /// @return cAmount The amount of collateral paid by the trader + /// @return sAmount The amount of spear or shield tokens received by the trader function trade(BattleTradeParams memory tp) external returns (uint256 cAmount, uint256 sAmount, uint256 fAmount); } @@ -73,29 +69,21 @@ interface IBattleBase { event ProtocolFeeCollected(address recipient, uint256 amount); /// @notice Settles the battle and determines the outcome. - /// battle will fetch the price of underlying asset, and determinate the - /// battle result. - /// battle finished after settle function was called + /// The Battle contract will fetch the price of underlying asset, and determines the outcome. + /// Once settled, a pool's address is not reused for new battles function settle() external; - /// @notice If a user bought some spear/shield and won, he can switch - /// spear/shield to collateral by 1:1 ratio. - /// eg. Alice bought 100 spear and the battle result was spear_win, she can - /// switch 100 collateral by call this - /// function + /// @notice After settlement, an in-the-money spear or shield token is exercised for one collateral. + /// eg. Alice bought 100 spear. If the outcome is spear_win, she can + /// claim 100 collateral minus an exercise fee by calling this function. function exercise() external; - /// @notice Returns the amount of unused collateral to the options seller - /// after settlement. For options that expire - /// out-of-money, the amount of collateral obligation reserved prior to - /// settlement becomes exercisable. Only called - /// by - /// the Manager. - /// @param recipient address which receive collateral - /// @param amount the amount of collateral will receive + /// @notice Enables the liquidity provider to withdraw the collateral amount reserved for settlement. Only called by the manager contract. + /// @param recipient The liquidity provider address to receive collateral + /// @param amount the amount of collateral to be received function withdrawObligation(address recipient, uint256 amount) external; - /// @notice collect protocol fee + /// @notice Allows the accumulated protocol fee to be collected. Can only be called by the owner. function collectProtocolFee(address recipient) external; } diff --git a/src/core/types/enums.sol b/src/core/types/enums.sol index 511d27f..117cc59 100644 --- a/src/core/types/enums.sol +++ b/src/core/types/enums.sol @@ -11,9 +11,8 @@ enum LiquidityType } enum Outcome -// battle is ongoing { - ONGOING, + ONGOING, // battle is ongoing SPEAR_WIN, SHIELD_WIN } From 1938879c004f0ece15b892db380b752a467e5e56 Mon Sep 17 00:00:00 2001 From: 0xSpear <83915876+0xSpear@users.noreply.github.com> Date: Fri, 24 Nov 2023 03:36:49 +0000 Subject: [PATCH 11/16] update inline comments for interface --- src/core/interfaces/IArena.sol | 7 +++---- src/core/interfaces/IOracle.sol | 6 ++---- src/core/interfaces/ISToken.sol | 6 +++--- src/core/interfaces/battle/IBattleActions.sol | 2 +- src/core/interfaces/battle/IBattleState.sol | 10 +++++----- 5 files changed, 14 insertions(+), 17 deletions(-) diff --git a/src/core/interfaces/IArena.sol b/src/core/interfaces/IArena.sol index 59792fc..486c91f 100644 --- a/src/core/interfaces/IArena.sol +++ b/src/core/interfaces/IArena.sol @@ -25,13 +25,12 @@ interface IArenaAdmin { interface IArenaCreation { event BattleCreated(BattleKey bk, address battleAddr, address spear, address shield, Fee fee); - /// @notice create new battle - /// @param params Params for creating new battle + /// @notice Create a new battle + /// @param params Params for creating a new battle /// @return battleAddr new battle address function createBattle(CreateAndInitBattleParams memory params) external returns (address battleAddr); - /// @notice Get existed battle address by battleKey. If not exist, will - /// return address(0) + /// @notice Get the address of the existing battle or address(0) if not found function getBattle(BattleKey memory battleKey) external view returns (address battleAddr); } diff --git a/src/core/interfaces/IOracle.sol b/src/core/interfaces/IOracle.sol index 6a748d9..3a24c58 100644 --- a/src/core/interfaces/IOracle.sol +++ b/src/core/interfaces/IOracle.sol @@ -2,10 +2,8 @@ pragma solidity ^0.8.0; -/// @title Get external price by oracle -/// @notice Collects and updates underlying asset prices used for settling -/// options. -/// It retrieves asset prices and supplies them to all contracts that use them. +/// @title Get price from external oracle +/// @notice Retrieves underlying asset prices used for settling options. interface IOracle { function getPriceByExternal(address cOracleAddr, uint256 ts) external view returns (uint256 price_, uint256 actualTs); diff --git a/src/core/interfaces/ISToken.sol b/src/core/interfaces/ISToken.sol index af13a62..95b19be 100644 --- a/src/core/interfaces/ISToken.sol +++ b/src/core/interfaces/ISToken.sol @@ -5,15 +5,15 @@ pragma solidity ^0.8.0; /** * @title ISToken * - * @notice ISToken is a spear/shield that can be minted and burned by the battle contract. + * @notice Mints or burns Spear or Shield tokens */ interface ISToken { /** - * @notice Mint `amount` of ISToken to `account` + * @notice Mint an amount of sToken to account */ function mint(address account, uint256 amount) external; /** - * @notice Burn `amount` of ISToken from `account` + * @notice Burn an amount of sToken from account */ function burn(address account, uint256 amount) external; } diff --git a/src/core/interfaces/battle/IBattleActions.sol b/src/core/interfaces/battle/IBattleActions.sol index 1f03253..b915ef8 100644 --- a/src/core/interfaces/battle/IBattleActions.sol +++ b/src/core/interfaces/battle/IBattleActions.sol @@ -43,7 +43,7 @@ interface IBattleTrade { /// @param liquidity liquity in battle after trade /// @param amountIn The amount of token input /// @param amountOut The amount of token output - /// @param tradeType buySpear or buyShield + /// @param tradeType BUY_SPEAR or BUY_SHIELD /// @param sqrtPriceX96 The sqrt price of the battle after the trade /// @param tick The tick of the battle after the trade event Traded( diff --git a/src/core/interfaces/battle/IBattleState.sol b/src/core/interfaces/battle/IBattleState.sol index ee9c68a..8ca4a35 100644 --- a/src/core/interfaces/battle/IBattleState.sol +++ b/src/core/interfaces/battle/IBattleState.sol @@ -5,16 +5,16 @@ pragma solidity ^0.8.0; import "core/types/common.sol"; interface IBattleState { - /// @notice Get slotInfo by slotKey. - /// @param pk positon key check how slotKey is generated in Position.sol - /// @param info check PositionInfo in PositionTypes.sol + /// @notice Retrieves position info for a given position key + /// @param pk positon key + /// @param info Information about the position function positions(bytes32 pk) external view returns (PositionInfo memory info); /// @notice The result of battle. - /// @return result check different battle result type in Outcome.sol + /// @return result check different battle result type in enums.sol function battleOutcome() external view returns (Outcome); - /// @notice A battleKey can uniquely identify a battle + /// @notice Returns the BattleKey that uniquely identifies a battle function battleKey() external view returns (BattleKey memory key); /// @notice Get Manager address in this battle From c2c4a6183d165a03c5e405fdd60c809e67be335f Mon Sep 17 00:00:00 2001 From: 0xSpear <83915876+0xSpear@users.noreply.github.com> Date: Fri, 24 Nov 2023 07:01:46 +0000 Subject: [PATCH 12/16] Update inline comment for DiverSqrtPriceMath --- src/core/libs/DiverSqrtPriceMath.sol | 41 ++++++++++++++++++++++++---- 1 file changed, 35 insertions(+), 6 deletions(-) diff --git a/src/core/libs/DiverSqrtPriceMath.sol b/src/core/libs/DiverSqrtPriceMath.sol index c06423d..4f2c5c7 100644 --- a/src/core/libs/DiverSqrtPriceMath.sol +++ b/src/core/libs/DiverSqrtPriceMath.sol @@ -12,12 +12,17 @@ library DiverSqrtPriceMath { using SafeCast for uint256; using SafeCast for int128; - /** - * formula - * amount = liquidity * (sqrtRatioBX96 - sqrtRatioAX96) * (1 + 1 / - * (sqrtRatioAX96 * sqrtRatioBX96)); - * - */ + // @notice Gets the delta amount of Spear or Shield tokens based on the given sqrt ratios and liquidity. + // Computes for Spear token delta when the sqrtPrice moves from upper to lower; or Shield token delta when the sqrtPrice moves from lower to upper. + // For the same sqrt ratio range and liquidity, the computed delta amounts of Spear and Shield are equal. + // Formula for this is: + // stoken delta amount = liquidity * (sqrtRatioBX96 - sqrtRatioAX96) * (1 + 1 /(sqrtRatioAX96 * sqrtRatioBX96)); + + // @param sqrtRatioAX96 A sqrt ratio + // @param sqrtRatioBX96 Another sqrt ratio + // @param liquidity The change in liquidity for which to compute the Spear or Shield token delta + // @param roundUp Whether to round the amount up or down + // @return amount The amount of Spear or Shield token corresponding to the passed liquidityDelta between the two prices function getSTokenDelta(uint160 sqrtRatioAX96, uint160 sqrtRatioBX96, uint128 liquidity, bool roundUp) internal pure returns (uint256 amount) { if (sqrtRatioAX96 > sqrtRatioBX96) { (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96); @@ -37,6 +42,11 @@ library DiverSqrtPriceMath { } } + // @notice Helper that gets signed spear or shield token delta + // @param sqrtRatioAX96 A sqrt ratio + // @param sqrtRatioBX96 Another sqrt ratio + // @param liquidity The change in liquidity for which to compute the Spear or Shield token delta + // @return amount The amount of Spear or Shield token corresponding to the passed liquidityDelta between the two prices function getSTokenDelta(uint160 sqrtPriceAX96, uint160 sqrtPriceBX96, int128 liquidity) internal pure returns (int256 amount) { if (sqrtPriceAX96 > sqrtPriceBX96) { (sqrtPriceAX96, sqrtPriceBX96) = (sqrtPriceBX96, sqrtPriceAX96); @@ -48,6 +58,18 @@ library DiverSqrtPriceMath { } } + // @notice Gets the next sqrt ratio based on the given the Spear token delta and liquidity. + // The formula for this is: + // a = (sqrt(4 b^2 L^2 + (b^2 (-L) + b s + L)^2) + b^2 L - b s - L)/(2 b L) + // where a = sqrtPriceLower b=sqrtPriceUpper s = spear delta + // Derived from the getSTokenDelta() formula with adjustments for token decimal units and Q96. For reference: + // https://wolfreealpha.gitlab.io/input/?i=solve+for+a+in+s+%3D+L*%28b-a%29%281%2BDivide%5B1%2Cab%5D&lang=en + + // @param sqrtPrice The starting price, i.e. before accounting for the spear token delta + // @param liquidity The amount of usable liquidity + // @param amount The amount of Spear token delta to mint for the trade + // @param unit The token decimal unit, e.g. a token with 18 decimals has a unit of 10**18 + function getNextSqrtPriceFromSpear( uint160 sqrtPrice, uint128 liquidity, @@ -77,6 +99,13 @@ library DiverSqrtPriceMath { nextSqrtPrice = FullMath.mulDiv(numerator, FixedPoint96.Q96, 2 * bl).toUint160(); } + // @notice Gets the next sqrt ratio based on the given the Shield token delta and liquidity. + // The formula for this is: + // a = (sqrt(4 b^2 L^2 + ((b^2 - 1) L + b s)^2) + b^2 L + b s - L)/(2 b L) + // where a = sqrtPriceUpper b=sqrtPriceLower s = shield delta + // Derived from the getSTokenDelta() formula with adjustments for token decimal units and Q96. For reference: + // https://wolfreealpha.gitlab.io/input/?i=solve+for+a+in+s+%3D+L*%28a-b%29%281%2BDivide%5B1%2Cab%5D&lang=en + function getNextSqrtPriceFromShield( uint160 sqrtPrice, uint128 liquidity, From 20532e8d19a87e10e9de0d4b194f7a8faa67d9eb Mon Sep 17 00:00:00 2001 From: 0xSpear <83915876+0xSpear@users.noreply.github.com> Date: Fri, 24 Nov 2023 07:09:19 +0000 Subject: [PATCH 13/16] update inline comment for DiverSqrtPriceMath --- src/core/libs/DiverSqrtPriceMath.sol | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/core/libs/DiverSqrtPriceMath.sol b/src/core/libs/DiverSqrtPriceMath.sol index 4f2c5c7..35bff79 100644 --- a/src/core/libs/DiverSqrtPriceMath.sol +++ b/src/core/libs/DiverSqrtPriceMath.sol @@ -69,6 +69,7 @@ library DiverSqrtPriceMath { // @param liquidity The amount of usable liquidity // @param amount The amount of Spear token delta to mint for the trade // @param unit The token decimal unit, e.g. a token with 18 decimals has a unit of 10**18 + // @return nextSqrtPrice The next sqrt ratio after minting the given amount of Spear tokens function getNextSqrtPriceFromSpear( uint160 sqrtPrice, @@ -106,6 +107,12 @@ library DiverSqrtPriceMath { // Derived from the getSTokenDelta() formula with adjustments for token decimal units and Q96. For reference: // https://wolfreealpha.gitlab.io/input/?i=solve+for+a+in+s+%3D+L*%28a-b%29%281%2BDivide%5B1%2Cab%5D&lang=en + // @param sqrtPrice The starting price, i.e. before accounting for the Shield token delta + // @param liquidity The amount of usable liquidity + // @param amount The amount of Shield token delta to mint for the trade + // @param unit The token decimal unit, e.g. a token with 18 decimals has a unit of 10**18 + // @return nextSqrtPrice The next sqrt ratio after minting the given amount of Shield tokens + function getNextSqrtPriceFromShield( uint160 sqrtPrice, uint128 liquidity, From 68d52b3307b32bf911166f9eed7d52a58e01a4e0 Mon Sep 17 00:00:00 2001 From: 0xSpear <83915876+0xSpear@users.noreply.github.com> Date: Fri, 24 Nov 2023 10:06:38 +0000 Subject: [PATCH 14/16] update inline comments --- src/core/libs/Position.sol | 2 ++ src/core/libs/Tick.sol | 2 ++ src/core/libs/TickMath.sol | 4 ++++ src/core/libs/TradeMath.sol | 4 +++- src/core/params/BattleBurnParams.sol | 8 +++---- src/core/params/BattleMintParams.sol | 12 +++++----- src/core/params/BattleTradeParams.sol | 8 +++---- src/core/params/ComputeTradeStepParams.sol | 12 +++++----- src/core/params/CreateBattleParams.sol | 8 +++---- src/core/params/DeploymentParams.sol | 18 +++++++------- src/core/params/ModifyPositionParams.sol | 8 +++---- src/core/params/UpdatePositionParams.sol | 2 +- src/core/types/TradeTypes.sol | 19 ++++++++++++++- src/core/types/common.sol | 28 +++++++++++++++------- src/core/types/enums.sol | 11 ++++----- 15 files changed, 90 insertions(+), 56 deletions(-) diff --git a/src/core/libs/Position.sol b/src/core/libs/Position.sol index 52e65ca..0362c86 100644 --- a/src/core/libs/Position.sol +++ b/src/core/libs/Position.sol @@ -7,6 +7,8 @@ import { FullMath } from "@uniswap/v3-core/contracts/libraries/FullMath.sol"; import { FixedPoint128 } from "@uniswap/v3-core/contracts/libraries/FixedPoint128.sol"; import { PositionInfo, GrowthX128, Owed } from "core/types/common.sol"; +/// @notice Manages and updates the position information + library Position { using SafeCast for uint256; diff --git a/src/core/libs/Tick.sol b/src/core/libs/Tick.sol index 9865358..870951b 100644 --- a/src/core/libs/Tick.sol +++ b/src/core/libs/Tick.sol @@ -4,6 +4,8 @@ pragma solidity ^0.8.0; import { TickMath } from "./TickMath.sol"; import { GrowthX128, TickInfo } from "core/types/common.sol"; +/// @notice Manages tick processes and computes variables stored in the tick state + library Tick { function tickSpacingToMaxLiquidityPerTick(int24 tickSpacing) internal pure returns (uint128) { unchecked { diff --git a/src/core/libs/TickMath.sol b/src/core/libs/TickMath.sol index a9f6f09..dd60ea1 100644 --- a/src/core/libs/TickMath.sol +++ b/src/core/libs/TickMath.sol @@ -4,6 +4,10 @@ pragma solidity ^0.8.0; import { TickMath as UniTickMath } from "@uniswap/v3-core/contracts/libraries/TickMath.sol"; import { Errors } from "core/errors/Errors.sol"; +/// @notice Math library for computing sqrt prices from ticks and vice versa. Sets the minimum and maximum of ticks and sqrt prices. +/// As digital calls and puts are priced between [0.01, 0.99] per collateral, per put-call parity, the sqrtPrice is the sqrt ratio of shieldPrice/spearPrice is between [sqrt(1/99), sqrt(99)]. +/// Computes sqrtPrice for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. + library TickMath { int24 internal constant MIN_TICK = -45953; int24 internal constant MAX_TICK = 45953; diff --git a/src/core/libs/TradeMath.sol b/src/core/libs/TradeMath.sol index bf645ae..7343163 100644 --- a/src/core/libs/TradeMath.sol +++ b/src/core/libs/TradeMath.sol @@ -10,6 +10,8 @@ import { ComputeTradeStepParams } from "core/params/ComputeTradeStepParams.sol"; import { TickMath } from "./TickMath.sol"; import { TradeType } from "core/types/enums.sol"; +/// @notice Computes the result of a swap within ticks. Contains methods for computing the result of a swap within a single tick price range, i.e., a single tick. + library TradeMath { using SafeCast for int256; @@ -21,7 +23,7 @@ library TradeMath { bool isSpear = params.tradeType == TradeType.BUY_SPEAR; bool exactIn = params.amountRemaining >= 0; - // calculate next price + // calculate the next price, given an amount of collateral input or sToken output if (exactIn) { amountIn = isSpear ? SqrtPriceMath.getAmount0Delta(params.sqrtRatioCurrentX96, params.sqrtRatioTargetX96, params.liquidity, true) diff --git a/src/core/params/BattleBurnParams.sol b/src/core/params/BattleBurnParams.sol index 5d85df2..d399bee 100644 --- a/src/core/params/BattleBurnParams.sol +++ b/src/core/params/BattleBurnParams.sol @@ -5,8 +5,8 @@ pragma solidity ^0.8.0; import { LiquidityType } from "core/types/common.sol"; struct BattleBurnParams { - int24 tickLower; - int24 tickUpper; - LiquidityType liquidityType; - uint128 liquidityAmount; + int24 tickLower; //The lower tick boundary of the position for which to burn liquidity + int24 tickUpper; //The upper tick boundary of the position for which to burn liquidity + LiquidityType liquidityType; //The chosen liquidity type can be Collateral, Spear, or Shield + uint128 liquidityAmount; //The amount of liquidity to be burnt } diff --git a/src/core/params/BattleMintParams.sol b/src/core/params/BattleMintParams.sol index 09a9631..73655e1 100644 --- a/src/core/params/BattleMintParams.sol +++ b/src/core/params/BattleMintParams.sol @@ -5,11 +5,11 @@ pragma solidity ^0.8.0; import { LiquidityType } from "core/types/enums.sol"; struct BattleMintParams { - address recipient; - int24 tickLower; - int24 tickUpper; - LiquidityType liquidityType; - uint128 amount; - uint128 seed; + address recipient; //The address for which the liquidity will be added + int24 tickLower; //The lower tick boundary of the position in which to add liquidity + int24 tickUpper; //The upper tick boundary of the position in which to add liquidity + LiquidityType liquidityType; //The chosen liquidity type can be Collateral, Spear, or Shield + uint128 amount; // The amount of liquidity to be added + uint128 seed; //The seed amount for the given liquidity type bytes data; } diff --git a/src/core/params/BattleTradeParams.sol b/src/core/params/BattleTradeParams.sol index e7d58af..0d7b96e 100644 --- a/src/core/params/BattleTradeParams.sol +++ b/src/core/params/BattleTradeParams.sol @@ -5,9 +5,9 @@ pragma solidity ^0.8.0; import { TradeType } from "core/types/enums.sol"; struct BattleTradeParams { - address recipient; - TradeType tradeType; - int256 amountSpecified; - uint160 sqrtPriceLimitX96; + address recipient; //The address to receive the output of the swap + TradeType tradeType; //whether to buy spear or buy shield + int256 amountSpecified; //The amount of the swap, which implicitly configures the swap as exact input of collateral or exact output of spear or shield token delta + uint160 sqrtPriceLimitX96; // The Q64.96 sqrtPrice limit bytes data; } diff --git a/src/core/params/ComputeTradeStepParams.sol b/src/core/params/ComputeTradeStepParams.sol index b9f0ab6..28a00a3 100644 --- a/src/core/params/ComputeTradeStepParams.sol +++ b/src/core/params/ComputeTradeStepParams.sol @@ -5,10 +5,10 @@ pragma solidity ^0.8.0; import { TradeType } from "core/types/common.sol"; struct ComputeTradeStepParams { - TradeType tradeType; - uint160 sqrtRatioCurrentX96; - uint160 sqrtRatioTargetX96; - uint128 liquidity; - int256 amountRemaining; - uint256 unit; + TradeType tradeType; //whether to buy spear or buy shield + uint160 sqrtRatioCurrentX96; //The current sqrt ratio of the pool + uint160 sqrtRatioTargetX96; //The price that cannot be exceeded, from which the direction of the swap is inferred + uint128 liquidity; // The usable liquidity + int256 amountRemaining; //How much input or output amount is remaining to be swapped in/out + uint256 unit; //The token decimal unit, e.g. a token with 18 decimals has a unit of 10**18 } diff --git a/src/core/params/CreateBattleParams.sol b/src/core/params/CreateBattleParams.sol index 41aca90..d2174c7 100644 --- a/src/core/params/CreateBattleParams.sol +++ b/src/core/params/CreateBattleParams.sol @@ -3,8 +3,8 @@ pragma solidity ^0.8.0; struct CreateBattleParams { - address collateralToken; - string underlying; - uint256 expiries; - uint256 strikeValue; + address collateralToken; //The supported collateral token address for the battle + string underlying; //The underlying asset symbol + uint256 expiries; //The of expiry timestamp of the battle + uint256 strikeValue; //The value of an option's strike price } diff --git a/src/core/params/DeploymentParams.sol b/src/core/params/DeploymentParams.sol index 9967261..ced0639 100644 --- a/src/core/params/DeploymentParams.sol +++ b/src/core/params/DeploymentParams.sol @@ -5,13 +5,13 @@ pragma solidity ^0.8.0; import { BattleKey, Fee } from "core/types/common.sol"; struct DeploymentParams { - address arenaAddr; - BattleKey battleKey; - address oracleAddr; - address cOracleAddr; - Fee fee; - address spear; - address shield; - address manager; - uint160 sqrtPriceX96; + address arenaAddr; //The address for the arena contract + BattleKey battleKey; //The battle Key containing a pool's specifications + address oracleAddr; //The address for the oracle + address cOracleAddr; //the contract address for a chainlink price feed + Fee fee; // The fee structure for the battle + address spear; //The address of the Spear tokens for a pool + address shield; // The address of the Shield tokens for a pool + address manager; //The address for the manager contract + uint160 sqrtPriceX96; //The starting sqrt ratio when initiating a battle } diff --git a/src/core/params/ModifyPositionParams.sol b/src/core/params/ModifyPositionParams.sol index f8530d3..96cea49 100644 --- a/src/core/params/ModifyPositionParams.sol +++ b/src/core/params/ModifyPositionParams.sol @@ -5,8 +5,8 @@ pragma solidity ^0.8.0; import { LiquidityType } from "core/types/enums.sol"; struct ModifyPositionParams { - int24 tickLower; - int24 tickUpper; - LiquidityType liquidityType; - int128 liquidityDelta; + int24 tickLower; //The lower tick boundary of the position + int24 tickUpper; //The upper tick boundary of the position + LiquidityType liquidityType; //The chosen liquidity type can be Collateral, Spear, or Shield + int128 liquidityDelta; //The change in liquidity } diff --git a/src/core/params/UpdatePositionParams.sol b/src/core/params/UpdatePositionParams.sol index a3d891f..78f64b6 100644 --- a/src/core/params/UpdatePositionParams.sol +++ b/src/core/params/UpdatePositionParams.sol @@ -6,5 +6,5 @@ import { ModifyPositionParams } from "./ModifyPositionParams.sol"; struct UpdatePositionParams { ModifyPositionParams mpParams; - int24 tick; + int24 tick; //the current tick } diff --git a/src/core/types/TradeTypes.sol b/src/core/types/TradeTypes.sol index 3285ce5..f58ffec 100644 --- a/src/core/types/TradeTypes.sol +++ b/src/core/types/TradeTypes.sol @@ -5,28 +5,45 @@ pragma solidity ^0.8.0; import { GrowthX128 } from "./common.sol"; struct TradeCache { - uint256 feeProtocol; + uint256 feeProtocol; //The protocol fee for the trade } struct TradeState { + /// @dev How much collateral input or SToken output amount is remaining to be swapped in/out int256 amountSpecifiedRemaining; + /// @dev The amount of collateral input or SToken output that has been calculated for the swap int256 amountCalculated; + /// @dev A fixed point Q64.96 number representing the sqrt of the ratio of shieldPrice/spearPrice uint160 sqrtPriceX96; + /// @dev The current tick int24 tick; + /// @dev GrowthX128 info per unit of liquidity as of the last update to the pool's global state GrowthX128 global; + /// @dev The amount of collateral token to be paid as protocol fee uint128 protocolFee; + /// @dev The amount of usable liquidity uint128 liquidity; + /// @dev The transaction fee for the trade uint256 transactionFee; } struct StepComputations { + /// @dev The sqrtPrice from which to start step computation uint160 sqrtPriceStartX96; + /// @dev The next tick up to the max or min tick of the virtual curve int24 tickNext; + /// @dev Whether the next tick is initialized bool initialized; + /// @dev The price after swapping the amount in/out, not to exceed the price target uint160 sqrtPriceNextX96; + /// @dev The collateral amount to be swapped in, based on the direction of the swap uint256 amountIn; + /// @dev The amount to be received, of either Spear or Shield token, based on the direction of the swap uint256 amountOut; + /// @dev The amount of collateral input that will be taken as a fee uint256 feeAmount; + /// @dev The lower tick for the step int24 tickLower; + /// @dev The upper tick for the step int24 tickUpper; } diff --git a/src/core/types/common.sol b/src/core/types/common.sol index 8772ff4..26a7780 100644 --- a/src/core/types/common.sol +++ b/src/core/types/common.sol @@ -6,50 +6,60 @@ import { LiquidityType, Outcome, TradeType } from "core/types/enums.sol"; struct BattleKey { /// @dev The address of the token used as collateral in the battle, eg: usdt/usdc address collateral; - /// @dev asset price be tracked, like btc, eth, etc + /// @dev The underlying asset symbol, such as btc, eth, etc string underlying; /// @dev end time of the battle uint256 expiries; - /// @dev strike price of the battle + /// @dev strike price of the options within the pool uint256 strikeValue; } struct Fee { /// @dev The fee ratio taken on every trade uint256 transactionFee; - /// @dev it is from transaction fee, and it is used to pay protocol fee + /// @dev The portion of transaction fee that goes to the protocol uint256 protocolFee; - /// @dev user call exercise() will pay this fee + /// @dev The exercise fee paid by those who call exercise() uint256 exerciseFee; } struct GrowthX128 { - /// @dev the growth of the transaction fee + /// @dev The all-time growth in transaction fee, per unit of liquidity, in collateral token uint256 fee; - /// @dev the growth amount of collateral LP got, premium + /// @dev The all-time growth in the received collateral inputs, per unit of liquidity, as options premium uint256 collateralIn; - /// @dev the growth amount of spear LP sold + /// @dev The all-time growth in Spear token outputs per unit of liquidity uint256 spearOut; - /// @dev the growth amount of shield LP sold + /// @dev The all-time growth in Shield token outputs per unit of liquidity uint256 shieldOut; } -/// @notice accoummulate amount of GrowthX128 +/// @notice tracking the GrowthX128 amounts owed to a position struct Owed { + /// @dev The amount of transaction fee owed to the position as of the last computation uint128 fee; + /// @dev The collateral inputs owed to the position as of the last computation uint128 collateralIn; + /// @dev The Spear token outputs owed to the position as of the last computation uint128 spearOut; + /// @dev The Shield token outputs owed to the position as of the last computation uint128 shieldOut; } struct TickInfo { + /// @dev The total amount of liquidity that the pool uses either at tickLower or tickUpper uint128 liquidityGross; + /// @dev The amount of liquidity added (subtracted) when tick is crossed from left to right (right to left) int128 liquidityNet; + /// @dev The GrowthX128 info recorded on the other side of the tick from the current tick GrowthX128 outside; + /// @dev Whether the tick is initialized bool initialized; } struct PositionInfo { + /// @dev The amount of usable liquidity uint128 liquidity; + /// @dev The GrowthX128 info per unit of liquidity inside the a position's bound as of the last action GrowthX128 insideLast; } diff --git a/src/core/types/enums.sol b/src/core/types/enums.sol index 117cc59..176c2dd 100644 --- a/src/core/types/enums.sol +++ b/src/core/types/enums.sol @@ -2,19 +2,16 @@ pragma solidity ^0.8.0; -enum LiquidityType -// eg. usdt\usdc -{ +enum LiquidityType { COLLATERAL, SPEAR, SHIELD } -enum Outcome -{ +enum Outcome { ONGOING, // battle is ongoing - SPEAR_WIN, - SHIELD_WIN + SPEAR_WIN, // calls expire in-the-money + SHIELD_WIN // puts expire in-the-money } enum TradeType { From f948d234bec0e8b039ab017eefab582a14fa651d Mon Sep 17 00:00:00 2001 From: 0xSpear <83915876+0xSpear@users.noreply.github.com> Date: Mon, 27 Nov 2023 11:25:36 +0000 Subject: [PATCH 15/16] update inline comments --- src/core/Battle.sol | 2 + src/core/interfaces/battle/IBattleActions.sol | 1 + src/periphery/Manager.sol | 57 ++++++++++++++----- src/periphery/base/LiquidityManagement.sol | 8 ++- src/periphery/base/PeripheryPayments.sol | 7 ++- src/periphery/interfaces/IManagerActions.sol | 41 +++++++------ src/periphery/interfaces/IManagerState.sol | 2 +- src/periphery/interfaces/IQuoter.sol | 2 +- src/periphery/lens/Quoter.sol | 29 ++++++++++ src/periphery/libs/DiverLiquidityAmounts.sol | 17 +++++- src/periphery/params/peripheryParams.sol | 26 +++------ src/periphery/types/common.sol | 16 +++--- 12 files changed, 144 insertions(+), 64 deletions(-) diff --git a/src/core/Battle.sol b/src/core/Battle.sol index 88ff6e1..761aeb1 100644 --- a/src/core/Battle.sol +++ b/src/core/Battle.sol @@ -37,6 +37,8 @@ import { } from "core/params/coreParams.sol"; /// @title Battle +/// @notice Each options pool is contained in a Battle contract. Battle contracts provide core functionalities including minting and burning liquidity, trading options tokens, settling and exercising options, and withdrawing collateral reserved for settlement. + contract Battle is IBattle { using Tick for mapping(int24 => TickInfo); using TickBitmap for mapping(int16 => uint256); diff --git a/src/core/interfaces/battle/IBattleActions.sol b/src/core/interfaces/battle/IBattleActions.sol index b915ef8..530dce9 100644 --- a/src/core/interfaces/battle/IBattleActions.sol +++ b/src/core/interfaces/battle/IBattleActions.sol @@ -54,6 +54,7 @@ interface IBattleTrade { /// @param tp The params for the trade /// @return cAmount The amount of collateral paid by the trader /// @return sAmount The amount of spear or shield tokens received by the trader + /// @return fAmount The amount of fee in collateral token to be spent for the trade function trade(BattleTradeParams memory tp) external returns (uint256 cAmount, uint256 sAmount, uint256 fAmount); } diff --git a/src/periphery/Manager.sol b/src/periphery/Manager.sol index 8e7396f..e6e1cba 100644 --- a/src/periphery/Manager.sol +++ b/src/periphery/Manager.sol @@ -26,6 +26,9 @@ import { CallbackValidation } from "./libs/CallbackValidation.sol"; import { PositionInfo, BattleKey, GrowthX128, Owed, LiquidityType, Outcome } from "core/types/common.sol"; /// @title Manager +/// @notice Sets up the necessary state variables, mappings, and inheritance +/// to handle position NFTs, manage liquidity, and interact with the battle contracts + contract Manager is IManager, Multicall, ERC721Enumerable, PeripheryImmutableState, BattleInitializer, LiquidityManagement { uint256 public override nextId; mapping(uint256 => Position) private _positions; @@ -37,7 +40,10 @@ contract Manager is IManager, Multicall, ERC721Enumerable, PeripheryImmutableSta constructor(address _arena, address _weth) ERC721("Divergence Protocol Positions NFT", "DIVER-POS") PeripheryImmutableState(_arena, _weth) { } - /// @inheritdoc IManagerLiquidity + /// @notice Adds liquidity to a battle contract, mints a new token representing the liquidity position + /// records the position information for later reference. + /// @return tokenId The ID of the NFT that represents the liquidity position + /// @return liquidity The amount of liquidity for this position function addLiquidity(AddLiqParams calldata params) external override returns (uint256 tokenId, uint128 liquidity) { if (block.timestamp > params.deadline) { revert Errors.Deadline(); @@ -65,6 +71,7 @@ contract Manager is IManager, Multicall, ERC721Enumerable, PeripheryImmutableSta _safeMint(params.recipient, tokenId); } + /// @notice Updates the growth of fees and token deltas as of the last action on the individual position function updateInsideLast(PositionInfo memory pb, Position storage pm) private { unchecked { pm.owed.fee += uint128(FullMath.mulDiv(pb.insideLast.fee - pm.insideLast.fee, pm.liquidity, FixedPoint128.Q128)); @@ -76,7 +83,13 @@ contract Manager is IManager, Multicall, ERC721Enumerable, PeripheryImmutableSta } } - /// @inheritdoc IManagerLiquidity + /// @notice Removes liquidity from the pool, given the tokenId of a position. Only to be called once by the liquidity provider. + /// @param tokenId The ID of the NFT that represents the liquidity position + /// @return collateral The amount of collateral to be received by the liqudity provider + /// @return spear The amount of Spear to be received by the liquidity provider + /// @return shield The amount of Shield to be received by the liquidity provider + /// @return spearObligation The obligatory reserve of collateral amount for settling spear tokens sold by the position + /// @return shieldObligation The obligatory reserve of collateral amount for settling shield tokens sold by the position function removeLiquidity(uint256 tokenId) external override @@ -114,6 +127,14 @@ contract Manager is IManager, Multicall, ERC721Enumerable, PeripheryImmutableSta emit LiquidityRemoved(tokenId, collateral, spear > shield ? spear : shield); } + /// @notice Calculates the obligatory reserve of collateral amounts for settling sold spear and shield amounts + /// The remaining collateral/spear/shield token amounts receivable for a given position. + /// @param pm The position for which to calculate the obligation amounts and receivable token amounts + /// @return collateral The amount of collateral that can be received by the liqudity provider + /// @return spear The remaining spear amount that can be received by the liqudity provider, after adjusting for obligations + /// @return shield The remaining shield amount that can be received by the liqudity provider, after adjusting for obligations + /// @return spearObligation The obligatory reserve of collateral amount for settling spear tokens sold by the position + /// @return shieldObligation The obligatory reserve of collateral amount for settling shield tokens sold by the position function getObligation(Position memory pm) private pure @@ -123,15 +144,13 @@ contract Manager is IManager, Multicall, ERC721Enumerable, PeripheryImmutableSta spearObligation = pm.owed.spearOut; shieldObligation = pm.owed.shieldOut; uint256 obligation = spearObligation > shieldObligation ? spearObligation : shieldObligation; - // minus 1 to avoid rounding error, insure the collateral is enough - // to pay the obligation + // minus 1 to avoid rounding error, ensuring the reserved collateral is enough to pay the obligation collateral = pm.owed.collateralIn + pm.seed == obligation ? 0 : pm.owed.collateralIn + pm.seed - obligation - 1; } else if (pm.liquidityType == LiquidityType.SPEAR) { spearObligation = pm.owed.spearOut > pm.seed ? pm.owed.spearOut - pm.seed : 0; shieldObligation = pm.owed.shieldOut; uint256 obligation = spearObligation > shieldObligation ? spearObligation : shieldObligation; - // minus 1 to avoid rounding error, insure the collateral is enough - // to pay the obligation + // minus 1 to avoid rounding error, ensuring the reserved collateral is enough to pay the obligation collateral = pm.owed.collateralIn == obligation ? 0 : pm.owed.collateralIn - obligation - 1; if (pm.seed > pm.owed.spearOut) { spear = pm.seed - pm.owed.spearOut; @@ -140,8 +159,7 @@ contract Manager is IManager, Multicall, ERC721Enumerable, PeripheryImmutableSta spearObligation = pm.owed.spearOut; shieldObligation = pm.owed.shieldOut > pm.seed ? pm.owed.shieldOut - pm.seed : 0; uint256 obligation = spearObligation > shieldObligation ? spearObligation : shieldObligation; - // minus 1 to avoid rounding error, insure the collateral is enough - // to pay the obligation + // minus 1 to avoid rounding error, ensuring the reserved collateral is enough to pay the obligation collateral = pm.owed.collateralIn == obligation ? 0 : pm.owed.collateralIn - obligation - 1; if (pm.seed > pm.owed.shieldOut) { shield = pm.seed - pm.owed.shieldOut; @@ -149,7 +167,9 @@ contract Manager is IManager, Multicall, ERC721Enumerable, PeripheryImmutableSta } } - /// @inheritdoc IManagerLiquidity + /// @notice Returns the amount of collateral reserved for options that settle out-of-money. + /// Can be called once after expiry by the liquidity provider and must be called after liquidity has been removed. + /// @param tokenId The ID of the NFT that represents the liquidity position function withdrawObligation(uint256 tokenId) external override isAuthorizedForToken(tokenId) { Position memory pm = _positions[tokenId]; @@ -177,6 +197,10 @@ contract Manager is IManager, Multicall, ERC721Enumerable, PeripheryImmutableSta emit ObligationWithdrawn(pm.battleAddr, tokenId, toLp); } + /// @notice Returns the amount of collateral reserved for the liquidity providers' open short interest. + /// The LP gets one collateral for sending one spear or shield token back to the pool to close the net amount of short options exposure. + /// Can be called once before expiry by the LP and must be called after liquidity has been removed. + /// @param tokenId The ID of the NFT that represents the liquidity position function redeemObligation(uint256 tokenId) external override isAuthorizedForToken(tokenId) { Position memory pm = _positions[tokenId]; if (pm.state != PositionState.LiquidityRemoved) { @@ -197,6 +221,10 @@ contract Manager is IManager, Multicall, ERC721Enumerable, PeripheryImmutableSta } } + /// @notice Calls the battle contract to execute a trade + /// @return amountIn The collateral amount to be swapped in based on the direction of the swap + /// @return amountOut The amount to be received, of either spear or shield token, based on the direction of the swap + /// @return amountFee The amount of fee in collateral token to be spent for the trade function trade(TradeParams calldata p) external override returns (uint256 amountIn, uint256 amountOut, uint256 amountFee) { if (block.timestamp > p.deadline) { revert Errors.Deadline(); @@ -211,7 +239,7 @@ contract Manager is IManager, Multicall, ERC721Enumerable, PeripheryImmutableSta tps.recipient = p.recipient; tps.tradeType = p.tradeType; tps.amountSpecified = p.amountSpecified; - tps.data = abi.encode(TradeCallbackData({ battleKey: p.battleKey, payer: msg.sender })); + tps.data = abi.encode(TradeCallbackData({battleKey: p.battleKey, payer: msg.sender})); if (p.sqrtPriceLimitX96 == 0) { if (p.tradeType == TradeType.BUY_SPEAR) { tps.sqrtPriceLimitX96 = TickMath.MIN_SQRT_RATIO + 1; @@ -230,15 +258,18 @@ contract Manager is IManager, Multicall, ERC721Enumerable, PeripheryImmutableSta emit Traded(p.recipient, p.tradeType, amountIn, amountOut); } + /// @notice Called to msg.sender after executing a swap via Manager. + /// @param cAmount The amount of collateral transferred in the trade + /// @param sAmount The amount of spear or shield transferred in the trade + /// @param _data Data passed through by the caller function tradeCallback(uint256 cAmount, uint256 sAmount, bytes calldata _data) external override { TradeCallbackData memory data = abi.decode(_data, (TradeCallbackData)); CallbackValidation.verifyCallback(arena, data.battleKey); pay(data.battleKey.collateral, data.payer, msg.sender, cAmount); } - // ====view==== - - /// @inheritdoc IManagerState + /// @notice Retrieves the position data for the given TokenId + /// @param tokenId The ID of the NFT that represents the liquidity position function positions(uint256 tokenId) external view override returns (Position memory) { return _positions[tokenId]; } diff --git a/src/periphery/base/LiquidityManagement.sol b/src/periphery/base/LiquidityManagement.sol index b337206..13825b5 100644 --- a/src/periphery/base/LiquidityManagement.sol +++ b/src/periphery/base/LiquidityManagement.sol @@ -25,6 +25,9 @@ abstract contract LiquidityManagement is IMintCallback, PeripheryImmutableState, address payer; } + /// @notice Called to msg.sender after minting liquidity to a position + /// @param amountOwed The amount of tokens owed for the minted liquidity + /// @param data Any data passed through by the caller function mintCallback(uint256 amountOwed, bytes calldata data) external override { MintCallbackData memory decode = abi.decode(data, (MintCallbackData)); CallbackValidation.verifyCallback(arena, decode.battleKey); @@ -33,6 +36,9 @@ abstract contract LiquidityManagement is IMintCallback, PeripheryImmutableState, } } + /// @notice Add liquidity to an initialized pool + /// @return liquidityAmount The amount of liquidity to add + /// @return battleAddr The address to which an AMM pool is created function _addLiquidity(AddLiqParams memory params) internal returns (uint128 liquidityAmount, address battleAddr) { battleAddr = IArenaCreation(arena).getBattle(params.battleKey); if (battleAddr == address(0)) { @@ -71,7 +77,7 @@ abstract contract LiquidityManagement is IMintCallback, PeripheryImmutableState, liquidityType: params.liquidityType, amount: liquidityAmount, seed: params.amount, - data: abi.encode(MintCallbackData({ battleKey: params.battleKey, token: token, payer: msg.sender })) + data: abi.encode(MintCallbackData({battleKey: params.battleKey, token: token, payer: msg.sender})) }) ); } diff --git a/src/periphery/base/PeripheryPayments.sol b/src/periphery/base/PeripheryPayments.sol index 957dfc2..684df16 100644 --- a/src/periphery/base/PeripheryPayments.sol +++ b/src/periphery/base/PeripheryPayments.sol @@ -15,9 +15,14 @@ abstract contract PeripheryPayments is PeripheryImmutableState { } } + /// @notice Handles the payment of tokens or ETH from one address to another + /// @param tokenAddr The address of the token to pay + /// @param payer The account that should pay the tokens + /// @param recipient The account that should receive the tokens + /// @param value The amount to pay function pay(address tokenAddr, address payer, address recipient, uint256 value) internal { if (tokenAddr == WETH9 && address(this).balance >= value) { - IWETH9(WETH9).deposit{ value: value }(); + IWETH9(WETH9).deposit{value: value}(); IWETH9(WETH9).transfer(recipient, value); } else { TransferHelper.safeTransferFrom(tokenAddr, payer, recipient, value); diff --git a/src/periphery/interfaces/IManagerActions.sol b/src/periphery/interfaces/IManagerActions.sol index d9dbd24..303fa87 100644 --- a/src/periphery/interfaces/IManagerActions.sol +++ b/src/periphery/interfaces/IManagerActions.sol @@ -12,8 +12,8 @@ interface IManagerLiquidity { /// @param owner The owner of the position and nft /// @param tokenId The id of the nft /// @param liquidity The amount of liquidity added to nft - /// @param liquidityType The type of liquidity added, collateral, spear, or shield - /// @param seedAmount The amount of seed added to nft, seed is the amount of collateral/spear/shield + /// @param liquidityType Specifies the type of liquidity seeded to the position is collateral, spear, or shield + /// @param seedAmount The token amount provided for the position, of the collateral, spear or shield liquidity type event LiquidityAdded( address indexed battleAddress, address indexed owner, uint256 tokenId, uint128 liquidity, LiquidityType liquidityType, uint256 seedAmount ); @@ -28,36 +28,43 @@ interface IManagerLiquidity { event ObligationRedeemed(address battle, uint256 tokenId, uint256 amount); - /// @notice add liquidity - /// @param params The params of add liquidity + /// @notice Adds liquidity to the protocol. + /// @param params The params for adding liquidity + /// @return tokenId The id of the nft + /// @return liquidity The amount of added liquidity function addLiquidity(AddLiqParams calldata params) external returns (uint256 tokenId, uint128 liquidity); - /// @notice remove liquidity, one nft will call this function once - /// @param tokenId The id of the nft - /// @return collateral The amount of collateral that lp got - /// @return spear The amount of spear that lp got - /// @return shield The amount of shield that lp got - /// @return spearObligation The amount of spear obligation belong to nft - /// @return shieldObligation The amount of shield obligation belong to nft + /// @notice Removes liquidity from the pool, given the tokenId of a position. Only to be called once by the liquidity provider. + /// @param tokenId The ID of the NFT that represents the liquidity position + /// @return collateral The amount of collateral to be received by the liqudity provider + /// @return spear The amount of Spear to be received by the liquidity provider + /// @return shield The amount of Shield to be received by the liquidity provider + /// @return spearObligation The obligatory reserve of collateral amount for settling spear tokens sold by the position + /// @return shieldObligation The obligatory reserve of collateral amount for settling shield tokens sold by the position function removeLiquidity(uint256 tokenId) external returns (uint256 collateral, uint256 spear, uint256 shield, uint256 spearObligation, uint256 shieldObligation); - /// @notice withdraw obligation, it will be call after removeLiquidity - /// @notice tokenId The id of the nft + /// @notice Returns the amount of collateral reserved for options that settle out-of-money. + /// Can be called once after expiry by the liquidity provider and must be called after liquidity has been removed. + /// @param tokenId The ID of the NFT that represents the liquidity position function withdrawObligation(uint256 tokenId) external; - /// @notice after removeLiquidity users can call redeemObligation to get their collateral by spending stoken - /// @param tokenId The id of the nft + /// @notice Returns the amount of collateral reserved for the liquidity providers' open short interest. + /// The LP gets one collateral for sending one spear or shield token back to the pool to close the net amount of short options exposure. + /// Can be called once before expiry by the LP and must be called after liquidity has been removed. + /// @param tokenId The ID of the NFT that represents the liquidity position function redeemObligation(uint256 tokenId) external; } interface IManagerTrade is ITradeCallback { event Traded(address recipient, TradeType tradeType, uint256 amountIn, uint256 amountOut); - /// @notice buySpear or buyShield + /// @notice Calls the battle contract to execute a trade /// @param mtp The params of trade in manager contract - /// @return amountOut The amount of spear/shield that user who bought spear/shield got + /// @return amountIn The collateral amount to be swapped in based on the direction of the swap + /// @return amountOut The amount to be received, of either spear or shield token, based on the direction of the swap + /// @return amountFee The amount of fee in collateral token to be spent for the trade function trade(TradeParams calldata mtp) external returns (uint256, uint256, uint256); } diff --git a/src/periphery/interfaces/IManagerState.sol b/src/periphery/interfaces/IManagerState.sol index 4be0199..6ef99c8 100644 --- a/src/periphery/interfaces/IManagerState.sol +++ b/src/periphery/interfaces/IManagerState.sol @@ -6,7 +6,7 @@ import { PositionState, Position } from "../types/common.sol"; interface IManagerState { /** - * @notice Get the position belong to a nft + * @notice Get the position belonging to an nft */ function positions(uint256 tokenId) external view returns (Position memory); diff --git a/src/periphery/interfaces/IQuoter.sol b/src/periphery/interfaces/IQuoter.sol index 0216cac..b6a1644 100644 --- a/src/periphery/interfaces/IQuoter.sol +++ b/src/periphery/interfaces/IQuoter.sol @@ -9,7 +9,7 @@ interface IQuoter { function positions(uint256 tokenId) external view returns (Position memory); /** - * @notice Get all positions belong to an account + * @notice Returns all the position details belonging to an account */ function accountPositions(address account) external view returns (Position[] memory); diff --git a/src/periphery/lens/Quoter.sol b/src/periphery/lens/Quoter.sol index 5449a72..b4d76c0 100644 --- a/src/periphery/lens/Quoter.sol +++ b/src/periphery/lens/Quoter.sol @@ -23,6 +23,8 @@ import { IQuoter, Position, PositionState } from "../interfaces/IQuoter.sol"; import { IManagerState } from "../interfaces/IManagerState.sol"; import { PositionInfo, BattleKey, GrowthX128, Owed, LiquidityType, Outcome } from "core/types/common.sol"; +/// @notice Gets the expected amountOut or amountIn for a given swap without executing the swap + contract Quoter is Multicall, ITradeCallback, IQuoter { using SafeCast for int256; using SafeCast for uint256; @@ -35,6 +37,10 @@ contract Quoter is Multicall, ITradeCallback, IQuoter { manager = _manager; } + /// @notice Callback function that handles the result of a trade. It reverts with the trade amounts. + /// @param cAmount Amount of collateral token input spent to be spent for the trade + /// @param sAmount Amount of spear or shield token output to be received for the trade + function tradeCallback(uint256 cAmount, uint256 sAmount, bytes calldata data) external pure override { uint256 spend = cAmount; uint256 get = sAmount; @@ -46,6 +52,11 @@ contract Quoter is Multicall, ITradeCallback, IQuoter { } } + /// @notice Parses a revert reason that should contain the numeric quote + /// @param reason The revert reason bytes + /// @return The first parsed value + /// @return The second parsed value + function parseRevertReason(bytes memory reason) private pure returns (uint256, uint256) { if (reason.length != 64) { if (reason.length < 68) { @@ -59,6 +70,10 @@ contract Quoter is Multicall, ITradeCallback, IQuoter { return abi.decode(reason, (uint256, uint256)); } + /// @notice Returns the amount of collateral input and options token output for the given parameters + /// @return spend The amount of collateral to spend| + /// @return get The amount of Spear or shield to receive | + function quoteExactInput(BattleTradeParams memory params, address battleAddr) public override returns (uint256 spend, uint256 get) { (uint160 p,,) = IBattleState(battleAddr).slot0(); if (params.tradeType == TradeType.BUY_SPEAR && p == TickMath.MIN_SQRT_RATIO + 1) { @@ -81,6 +96,9 @@ contract Quoter is Multicall, ITradeCallback, IQuoter { } } + /// @notice Calculates the amount of Spear or shield tokens based on the given liquidity + /// @param params required for adding liquidity + /// @return The amount of spear or shield token calculated based on the given liquidity function getSTokenByLiquidity(AddLiqParams calldata params) external view returns (uint256) { address battleAddr = IArenaCreation(arena).getBattle(params.battleKey); if (battleAddr == address(0)) { @@ -94,6 +112,13 @@ contract Quoter is Multicall, ITradeCallback, IQuoter { } } + /// @notice Calculates the amount of Spear or shield tokens based on the given amount of seed collateral when a liquidity position is created + /// @param sqrtPriceX96 The current sqrt price + /// @param tickLower The lower tick boundary of the position + /// @param tickUpper The upper tick boundary of the position + /// @param amount The seed collateral amount for minting the liquidity position + /// @return The amount of spear or shield token calculated based on the given liquidity + function getSTokenByLiquidityWhenCreate(uint160 sqrtPriceX96, int24 tickLower, int24 tickUpper, uint256 amount) public pure returns (uint256) { uint160 priceLower = TickMath.getSqrtRatioAtTick(tickLower); uint160 priceUpper = TickMath.getSqrtRatioAtTick(tickUpper); @@ -101,10 +126,12 @@ contract Quoter is Multicall, ITradeCallback, IQuoter { return DiverSqrtPriceMath.getSTokenDelta(priceLower, priceUpper, liquidityAmount, false); } + /// @notice Gets the position information for the given token ID function positions(uint256 tokenId) external view override returns (Position memory) { return handlePosition(tokenId); } + /// @notice Gets the position information for the given token ID function handlePosition(uint256 tokenId) private view returns (Position memory p) { p = IManagerState(manager).positions(tokenId); // p = _positions[tokenId]; @@ -120,6 +147,8 @@ contract Quoter is Multicall, ITradeCallback, IQuoter { } } + /// @notice Gets the positions for the given account + function accountPositions(address account) external view override returns (Position[] memory) { uint256 balance = IERC721Enumerable(manager).balanceOf(account); Position[] memory p = new Position[](balance); diff --git a/src/periphery/libs/DiverLiquidityAmounts.sol b/src/periphery/libs/DiverLiquidityAmounts.sol index 4cf60cc..4bc00b1 100644 --- a/src/periphery/libs/DiverLiquidityAmounts.sol +++ b/src/periphery/libs/DiverLiquidityAmounts.sol @@ -9,9 +9,15 @@ import { LiquidityAmounts } from "@uniswap/v3-periphery/contracts/libraries/Liqu library DiverLiquidityAmounts { using SafeCast for uint256; + /// @notice Computes the amount of liquidity to be received by the pool, for a given amount of collateral and price range. The formula is: + /// L = ΔC*sqrtPrice*sqrt(P_h)/(sqrt(P_h) - sqrtPrice + + /// sqrt(P_h)*sqrtPrice**2 - sqrtPrice*sqrt(P_h)*sqrt(P_l)) + /// @param sqrtRatioX96 The current square root ratio| + /// @param sqrtRatioAX96 A sqrt ratio + /// @param sqrtRatioBX96 Another sqrt ratio + /// @param amount The seed collateral amount for minting the liquidity position + /// @return liquidity The amount of liquidity to be received by the pool - // L = ΔC*sqrtPrice*sqrt(P_h)/(sqrt(P_h) - sqrtPrice + - // sqrt(P_h)*sqrtPrice**2 - sqrtPrice*sqrt(P_h)*sqrt(P_l)) function getLiquidityFromCs( uint160 sqrtRatioX96, uint160 sqrtRatioAX96, @@ -37,12 +43,17 @@ library DiverLiquidityAmounts { } } + /// @notice Computes the amount of liquidity to be received by the pool, for a given amount of Spear or Shield tokens and price range. The formula is: /** - * * @dev liquidity = (amount * sqrtRatioAX96 * sqrtRatioBX96) / ( * (sqrtRatioBX96 - sqrtRatioAX96) * (1 + * sqrtRatioAX96 * sqrtRatioBX96)); */ + /// @param sqrtRatioAX96 A sqrt ratio + /// @param sqrtRatioBX96 Another sqrt ratio + /// @param amount The seed Spear or Shield amount for minting the liquidity position + /// @return liquidity The amount of liquidity to be received by the pool + function getLiquidityFromSToken(uint160 sqrtRatioAX96, uint160 sqrtRatioBX96, uint256 amount) internal pure returns (uint128 liquidity) { if (sqrtRatioAX96 > sqrtRatioBX96) { (sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96); diff --git a/src/periphery/params/peripheryParams.sol b/src/periphery/params/peripheryParams.sol index 9415386..2d452b7 100644 --- a/src/periphery/params/peripheryParams.sol +++ b/src/periphery/params/peripheryParams.sol @@ -14,9 +14,9 @@ struct CreateAndInitBattleParams { /// @notice Parameters for adding liquidity /// @param battleKey The battle key /// @param recipient The address that receives nft -/// @param tickLower The lower tick of the position -/// @param tickUpper The upper tick of the position -/// @param liquidityType The liquidity type of the position, collateral, spear, shield +/// @param tickLower The lower tick boundary of the position +/// @param tickUpper The upper tick boundary of the position +/// @param liquidityType Specifies the type of liquidity added to the position is collateral, spear, or shield /// @param amount The amount of collateral/spear/shield to add /// @param deadline The deadline of the transaction struct AddLiqParams { @@ -32,22 +32,12 @@ struct AddLiqParams { } /// @param battleKey The battle key -/// @param tradeType The trade type, buySpear or buyShield -/// @param amountSpecified The amount of collateral to spend -/// @param recipient The address that receives spear/shield -/// @param amountOutMin The minimum amount of spear/shield to receive -/// @param sqrtPriceLimitX96 The max/min price when trading end +/// @param tradeType The trade type, BUY_SPEAR or BUY_SHIELD +/// @param amountSpecified How much collateral input or SToken output amount to be swapped in/out +/// @param recipient The address that receives spear or shield tokens +/// @param amountOutMin The minimum amount of spear or shield tokens to receive +/// @param sqrtPriceLimitX96 The max/min price when trading ends /// @param deadline The deadline of the transaction -// struct TradeParams { -// BattleKey battleKey; -// TradeType tradeType; -// uint256 amountSpecified; -// address recipient; -// uint256 amountOutMin; -// uint160 sqrtPriceLimitX96; -// uint256 deadline; -// } - struct TradeParams { BattleKey battleKey; TradeType tradeType; diff --git a/src/periphery/types/common.sol b/src/periphery/types/common.sol index 6c63838..921e285 100644 --- a/src/periphery/types/common.sol +++ b/src/periphery/types/common.sol @@ -17,13 +17,11 @@ struct Position { int24 tickLower; int24 tickUpper; uint128 liquidity; - LiquidityType liquidityType; - // when liquidity is added, it is the amount of collateral/spear/shield(according to liquidityType) lp spent - uint256 seed; - GrowthX128 insideLast; - Owed owed; - PositionState state; - // obligation will be set when liquidity is removed - uint256 spearObligation; - uint256 shieldObligation; + LiquidityType liquidityType; // The chosen liquidity type can be Collateral, Spear, or Shield + uint256 seed; //The amount of tokens from the LP for the given liquidity type | + GrowthX128 insideLast; // GrowthX128 info per unit of liquidity inside the a position's bound as of the last action + Owed owed; // the amounts of fees and deltas of collateral, Spear and Shield tokens that are owed to a position + PositionState state; // obligation will be set when liquidity is removed + uint256 spearObligation; //The obligatory reserve of collateral amount for settling spear tokens sold by the position + uint256 shieldObligation; //The obligatory reserve of collateral amount for settling shield tokens sold by the position } From 4830aa84b5eea9c87461de3383b36281e9546f63 Mon Sep 17 00:00:00 2001 From: Alexis-ETH Date: Fri, 8 Dec 2023 17:14:28 +0800 Subject: [PATCH 16/16] format --- src/core/Battle.sol | 7 ++++--- src/core/Oracle.sol | 6 ++++-- src/core/interfaces/IOracle.sol | 2 +- src/core/interfaces/battle/IBattleState.sol | 2 +- src/core/libs/DiverSqrtPriceMath.sol | 3 ++- src/core/libs/Position.sol | 2 +- src/core/libs/TickMath.sol | 3 ++- src/core/libs/TradeMath.sol | 3 ++- src/core/params/BattleTradeParams.sol | 3 ++- src/periphery/Manager.sol | 2 +- src/periphery/base/LiquidityManagement.sol | 2 +- src/periphery/base/PeripheryPayments.sol | 2 +- src/periphery/lens/Quoter.sol | 2 +- src/periphery/libs/DiverLiquidityAmounts.sol | 3 ++- 14 files changed, 25 insertions(+), 17 deletions(-) diff --git a/src/core/Battle.sol b/src/core/Battle.sol index 761aeb1..824edf2 100644 --- a/src/core/Battle.sol +++ b/src/core/Battle.sol @@ -37,7 +37,8 @@ import { } from "core/params/coreParams.sol"; /// @title Battle -/// @notice Each options pool is contained in a Battle contract. Battle contracts provide core functionalities including minting and burning liquidity, trading options tokens, settling and exercising options, and withdrawing collateral reserved for settlement. +/// @notice Each options pool is contained in a Battle contract. Battle contracts provide core functionalities including minting and burning +/// liquidity, trading options tokens, settling and exercising options, and withdrawing collateral reserved for settlement. contract Battle is IBattle { using Tick for mapping(int24 => TickInfo); @@ -112,7 +113,7 @@ contract Battle is IBattle { shield = params.shield; manager = params.manager; arena = address(msg.sender); - slot0 = Slot0({sqrtPriceX96: params.sqrtPriceX96, tick: TickMath.getTickAtSqrtRatio(params.sqrtPriceX96), unlocked: true}); + slot0 = Slot0({ sqrtPriceX96: params.sqrtPriceX96, tick: TickMath.getTickAtSqrtRatio(params.sqrtPriceX96), unlocked: true }); maxLiquidityPerTick = Tick.tickSpacingToMaxLiquidityPerTick(30); } @@ -271,7 +272,7 @@ contract Battle is IBattle { ); slot0.unlocked = false; - TradeCache memory cache = TradeCache({feeProtocol: fee.protocolFee}); + TradeCache memory cache = TradeCache({ feeProtocol: fee.protocolFee }); TradeState memory state = TradeState({ amountSpecifiedRemaining: params.amountSpecified, amountCalculated: 0, diff --git a/src/core/Oracle.sol b/src/core/Oracle.sol index 4fe32a9..f3160cb 100644 --- a/src/core/Oracle.sol +++ b/src/core/Oracle.sol @@ -44,7 +44,8 @@ contract Oracle is Ownable { uint256 decimalDiff = 10 ** (18 - cOracle.decimals()); (uint256 cPrice, uint256 cActualTs) = _getPrice(cOracle, roundID, ts, decimalDiff); - // If the price remains unreported or inaccessible an hour post expiry, the closest available price will be fixed based on the external oracle data. + // If the price remains unreported or inaccessible an hour post expiry, the closest available price will be fixed based on the external oracle + // data. if (block.timestamp - ts > 1 hours && cPrice == 0) { require(fixPrices[cOracleAddr][ts] != 0, "setting price"); price = fixPrices[cOracleAddr][ts]; @@ -75,7 +76,8 @@ contract Oracle is Ownable { uint80 startRoundId = _getStartRoundId(phaseId); try AggregatorV3Interface(cOracle).getRoundData(startRoundId) returns (uint80, int256, uint256, uint256 updatedAt, uint80) { //updatedAt == 0, invalid value - //In case the 'startRound' occurs after the 'endTs' of a battle due to external oracle updates, it returns 0. The correct price will be provided by fixPrices. + //In case the 'startRound' occurs after the 'endTs' of a battle due to external oracle updates, it returns 0. The correct price will be + // provided by fixPrices. if (updatedAt == 0 || updatedAt >= ts) { return (0, 0); } else { diff --git a/src/core/interfaces/IOracle.sol b/src/core/interfaces/IOracle.sol index 3a24c58..165f2e9 100644 --- a/src/core/interfaces/IOracle.sol +++ b/src/core/interfaces/IOracle.sol @@ -3,7 +3,7 @@ pragma solidity ^0.8.0; /// @title Get price from external oracle -/// @notice Retrieves underlying asset prices used for settling options. +/// @notice Retrieves underlying asset prices used for settling options. interface IOracle { function getPriceByExternal(address cOracleAddr, uint256 ts) external view returns (uint256 price_, uint256 actualTs); diff --git a/src/core/interfaces/battle/IBattleState.sol b/src/core/interfaces/battle/IBattleState.sol index 8ca4a35..dfe3ba5 100644 --- a/src/core/interfaces/battle/IBattleState.sol +++ b/src/core/interfaces/battle/IBattleState.sol @@ -14,7 +14,7 @@ interface IBattleState { /// @return result check different battle result type in enums.sol function battleOutcome() external view returns (Outcome); - /// @notice Returns the BattleKey that uniquely identifies a battle + /// @notice Returns the BattleKey that uniquely identifies a battle function battleKey() external view returns (BattleKey memory key); /// @notice Get Manager address in this battle diff --git a/src/core/libs/DiverSqrtPriceMath.sol b/src/core/libs/DiverSqrtPriceMath.sol index 35bff79..bb58593 100644 --- a/src/core/libs/DiverSqrtPriceMath.sol +++ b/src/core/libs/DiverSqrtPriceMath.sol @@ -13,7 +13,8 @@ library DiverSqrtPriceMath { using SafeCast for int128; // @notice Gets the delta amount of Spear or Shield tokens based on the given sqrt ratios and liquidity. - // Computes for Spear token delta when the sqrtPrice moves from upper to lower; or Shield token delta when the sqrtPrice moves from lower to upper. + // Computes for Spear token delta when the sqrtPrice moves from upper to lower; or Shield token delta when the sqrtPrice moves from lower to + // upper. // For the same sqrt ratio range and liquidity, the computed delta amounts of Spear and Shield are equal. // Formula for this is: // stoken delta amount = liquidity * (sqrtRatioBX96 - sqrtRatioAX96) * (1 + 1 /(sqrtRatioAX96 * sqrtRatioBX96)); diff --git a/src/core/libs/Position.sol b/src/core/libs/Position.sol index 0362c86..32eea6f 100644 --- a/src/core/libs/Position.sol +++ b/src/core/libs/Position.sol @@ -7,7 +7,7 @@ import { FullMath } from "@uniswap/v3-core/contracts/libraries/FullMath.sol"; import { FixedPoint128 } from "@uniswap/v3-core/contracts/libraries/FixedPoint128.sol"; import { PositionInfo, GrowthX128, Owed } from "core/types/common.sol"; -/// @notice Manages and updates the position information +/// @notice Manages and updates the position information library Position { using SafeCast for uint256; diff --git a/src/core/libs/TickMath.sol b/src/core/libs/TickMath.sol index dd60ea1..4d58cb8 100644 --- a/src/core/libs/TickMath.sol +++ b/src/core/libs/TickMath.sol @@ -5,7 +5,8 @@ import { TickMath as UniTickMath } from "@uniswap/v3-core/contracts/libraries/Ti import { Errors } from "core/errors/Errors.sol"; /// @notice Math library for computing sqrt prices from ticks and vice versa. Sets the minimum and maximum of ticks and sqrt prices. -/// As digital calls and puts are priced between [0.01, 0.99] per collateral, per put-call parity, the sqrtPrice is the sqrt ratio of shieldPrice/spearPrice is between [sqrt(1/99), sqrt(99)]. +/// As digital calls and puts are priced between [0.01, 0.99] per collateral, per put-call parity, the sqrtPrice is the sqrt ratio of +/// shieldPrice/spearPrice is between [sqrt(1/99), sqrt(99)]. /// Computes sqrtPrice for ticks of size 1.0001, i.e. sqrt(1.0001^tick) as fixed point Q64.96 numbers. library TickMath { diff --git a/src/core/libs/TradeMath.sol b/src/core/libs/TradeMath.sol index 7343163..e2211a7 100644 --- a/src/core/libs/TradeMath.sol +++ b/src/core/libs/TradeMath.sol @@ -10,7 +10,8 @@ import { ComputeTradeStepParams } from "core/params/ComputeTradeStepParams.sol"; import { TickMath } from "./TickMath.sol"; import { TradeType } from "core/types/enums.sol"; -/// @notice Computes the result of a swap within ticks. Contains methods for computing the result of a swap within a single tick price range, i.e., a single tick. +/// @notice Computes the result of a swap within ticks. Contains methods for computing the result of a swap within a single tick price range, i.e., a +/// single tick. library TradeMath { using SafeCast for int256; diff --git a/src/core/params/BattleTradeParams.sol b/src/core/params/BattleTradeParams.sol index 0d7b96e..acb2b7a 100644 --- a/src/core/params/BattleTradeParams.sol +++ b/src/core/params/BattleTradeParams.sol @@ -7,7 +7,8 @@ import { TradeType } from "core/types/enums.sol"; struct BattleTradeParams { address recipient; //The address to receive the output of the swap TradeType tradeType; //whether to buy spear or buy shield - int256 amountSpecified; //The amount of the swap, which implicitly configures the swap as exact input of collateral or exact output of spear or shield token delta + int256 amountSpecified; //The amount of the swap, which implicitly configures the swap as exact input of collateral or exact output of spear or + // shield token delta uint160 sqrtPriceLimitX96; // The Q64.96 sqrtPrice limit bytes data; } diff --git a/src/periphery/Manager.sol b/src/periphery/Manager.sol index e6e1cba..2d38fd6 100644 --- a/src/periphery/Manager.sol +++ b/src/periphery/Manager.sol @@ -239,7 +239,7 @@ contract Manager is IManager, Multicall, ERC721Enumerable, PeripheryImmutableSta tps.recipient = p.recipient; tps.tradeType = p.tradeType; tps.amountSpecified = p.amountSpecified; - tps.data = abi.encode(TradeCallbackData({battleKey: p.battleKey, payer: msg.sender})); + tps.data = abi.encode(TradeCallbackData({ battleKey: p.battleKey, payer: msg.sender })); if (p.sqrtPriceLimitX96 == 0) { if (p.tradeType == TradeType.BUY_SPEAR) { tps.sqrtPriceLimitX96 = TickMath.MIN_SQRT_RATIO + 1; diff --git a/src/periphery/base/LiquidityManagement.sol b/src/periphery/base/LiquidityManagement.sol index 13825b5..959c693 100644 --- a/src/periphery/base/LiquidityManagement.sol +++ b/src/periphery/base/LiquidityManagement.sol @@ -77,7 +77,7 @@ abstract contract LiquidityManagement is IMintCallback, PeripheryImmutableState, liquidityType: params.liquidityType, amount: liquidityAmount, seed: params.amount, - data: abi.encode(MintCallbackData({battleKey: params.battleKey, token: token, payer: msg.sender})) + data: abi.encode(MintCallbackData({ battleKey: params.battleKey, token: token, payer: msg.sender })) }) ); } diff --git a/src/periphery/base/PeripheryPayments.sol b/src/periphery/base/PeripheryPayments.sol index 684df16..afaadc1 100644 --- a/src/periphery/base/PeripheryPayments.sol +++ b/src/periphery/base/PeripheryPayments.sol @@ -22,7 +22,7 @@ abstract contract PeripheryPayments is PeripheryImmutableState { /// @param value The amount to pay function pay(address tokenAddr, address payer, address recipient, uint256 value) internal { if (tokenAddr == WETH9 && address(this).balance >= value) { - IWETH9(WETH9).deposit{value: value}(); + IWETH9(WETH9).deposit{ value: value }(); IWETH9(WETH9).transfer(recipient, value); } else { TransferHelper.safeTransferFrom(tokenAddr, payer, recipient, value); diff --git a/src/periphery/lens/Quoter.sol b/src/periphery/lens/Quoter.sol index b4d76c0..b978fba 100644 --- a/src/periphery/lens/Quoter.sol +++ b/src/periphery/lens/Quoter.sol @@ -115,7 +115,7 @@ contract Quoter is Multicall, ITradeCallback, IQuoter { /// @notice Calculates the amount of Spear or shield tokens based on the given amount of seed collateral when a liquidity position is created /// @param sqrtPriceX96 The current sqrt price /// @param tickLower The lower tick boundary of the position - /// @param tickUpper The upper tick boundary of the position + /// @param tickUpper The upper tick boundary of the position /// @param amount The seed collateral amount for minting the liquidity position /// @return The amount of spear or shield token calculated based on the given liquidity diff --git a/src/periphery/libs/DiverLiquidityAmounts.sol b/src/periphery/libs/DiverLiquidityAmounts.sol index 4bc00b1..82489af 100644 --- a/src/periphery/libs/DiverLiquidityAmounts.sol +++ b/src/periphery/libs/DiverLiquidityAmounts.sol @@ -43,7 +43,8 @@ library DiverLiquidityAmounts { } } - /// @notice Computes the amount of liquidity to be received by the pool, for a given amount of Spear or Shield tokens and price range. The formula is: + /// @notice Computes the amount of liquidity to be received by the pool, for a given amount of Spear or Shield tokens and price range. The formula + /// is: /** * @dev liquidity = (amount * sqrtRatioAX96 * sqrtRatioBX96) / ( * (sqrtRatioBX96 - sqrtRatioAX96) * (1 +