diff --git a/spot-contracts/contracts/FeePolicy.sol b/spot-contracts/contracts/FeePolicy.sol index 73f0683b..323aad74 100644 --- a/spot-contracts/contracts/FeePolicy.sol +++ b/spot-contracts/contracts/FeePolicy.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.20; import { IFeePolicy } from "./_interfaces/IFeePolicy.sol"; -import { SubscriptionParams, Range, Line } from "./_interfaces/CommonTypes.sol"; +import { SystemTVL, Range, Line } from "./_interfaces/CommonTypes.sol"; import { InvalidPerc, InvalidRange, InvalidFees } from "./_interfaces/ProtocolErrors.sol"; import { LineHelpers } from "./_utils/LineHelpers.sol"; @@ -22,21 +22,21 @@ import { MathHelpers } from "./_utils/MathHelpers.sol"; * supports rolling over all mature collateral backing perps. * * The system's balance is defined by it's `deviationRatio` which is defined as follows. - * - `subscriptionRatio` = (vaultTVL * seniorTR) / (perpTVL * 1-seniorTR) - * - `deviationRatio` (dr) = subscriptionRatio / targetSubscriptionRatio + * - `systemRatio` = vaultTVL / perpTVL + * - `deviationRatio` (dr) = systemRatio / targetSystemRatio * * When the dr = 1, the system is considered perfectly balanced. - * When the dr < 1, it's considered "under-subscribed". - * When the dr > 1, it's considered "over-subscribed". + * When the dr < 1, the vault is considered "under-subscribed". + * When the dr > 1, the vault is considered "over-subscribed". * * Fees: * - The system charges a greater fee for operations that move it away from the balance point. * - If an operation moves the system back to the balance point, it charges a lower fee (or no fee). * * Incentives: - * - When the system is "under-subscribed", value is transferred from perp to the vault at a predefined rate. + * - When the vault is "under-subscribed", value is transferred from perp to the vault at the computed rate. * This debases perp tokens gradually and enriches the rollover vault. - * - When the system is "over-subscribed", value is transferred from the vault to perp at a predefined rate. + * - When the vault is "over-subscribed", value is transferred from the vault to perp at the computed rate. * This enriches perp tokens gradually and debases the rollover vault. * - This transfer is implemented through a periodic "rebalance" operation, executed by the vault, and * gradually nudges the system back into balance. On rebalance, the vault queries this policy @@ -54,10 +54,6 @@ contract FeePolicy is IFeePolicy, OwnableUpgradeable { using SafeCastUpgradeable for uint256; using SafeCastUpgradeable for int256; - // Replicating value used here: - // https://github.com/buttonwood-protocol/tranche/blob/main/contracts/BondController.sol - uint256 private constant TRANCHE_RATIO_GRANULARITY = 1000; - /// @notice The returned fee percentages are fixed point numbers with {DECIMALS} places. /// @dev The decimals should line up with value expected by consumer (perp, vault). /// NOTE: 10**DECIMALS => 100% or 1.0 @@ -67,10 +63,10 @@ contract FeePolicy is IFeePolicy, OwnableUpgradeable { uint256 public constant ONE = (10 ** DECIMALS); //----------------------------------------------------------------------------- - /// @notice The target subscription ratio i.e) the normalization factor. - /// @dev The ratio under which the system is considered "under-subscribed". - /// Adds a safety buffer to ensure that rollovers are better sustained. - uint256 public targetSubscriptionRatio; + /// @notice The target system ratio i.e) the normalization factor. + /// @dev The target system ratio, the target vault tvl to perp tvl ratio and + /// is *different* from button-wood's tranche ratios. + uint256 public override targetSystemRatio; //----------------------------------------------------------------------------- // Fee parameters @@ -116,7 +112,7 @@ contract FeePolicy is IFeePolicy, OwnableUpgradeable { function init() external initializer { __Ownable_init(); - targetSubscriptionRatio = (ONE * 150) / 100; // 1.5 + targetSystemRatio = 3 * ONE; // 3.0 // initializing fees feeFnDRDown = Line({ @@ -151,10 +147,10 @@ contract FeePolicy is IFeePolicy, OwnableUpgradeable { //----------------------------------------------------------------------------- // Owner only - /// @notice Updates the target subscription ratio. - /// @param targetSubscriptionRatio_ The new target subscription ratio as a fixed point number with {DECIMALS} places. - function updateTargetSubscriptionRatio(uint256 targetSubscriptionRatio_) external onlyOwner { - targetSubscriptionRatio = targetSubscriptionRatio_; + /// @notice Updates the target system ratio. + /// @param targetSystemRatio_ The new target system ratio as a fixed point number with {DECIMALS} places. + function updateTargetSystemRatio(uint256 targetSystemRatio_) external onlyOwner { + targetSystemRatio = targetSystemRatio_; } /// @notice Updates the system fee functions. @@ -262,9 +258,7 @@ contract FeePolicy is IFeePolicy, OwnableUpgradeable { } /// @inheritdoc IFeePolicy - function computeRebalanceAmount( - SubscriptionParams memory s - ) external view override returns (int256 underlyingAmtIntoPerp) { + function computeRebalanceAmount(SystemTVL memory s) external view override returns (int256 underlyingAmtIntoPerp) { // We skip rebalancing if dr is close to 1.0 uint256 dr = computeDeviationRatio(s); Range memory drEq = drEqZone(); @@ -273,8 +267,7 @@ contract FeePolicy is IFeePolicy, OwnableUpgradeable { } // We compute the total value that should flow into perp to push the system into equilibrium. - uint256 totalTVL = s.perpTVL + s.vaultTVL; - uint256 reqPerpTVL = totalTVL.mulDiv(computeDRNormSeniorTR(s.seniorTR), ONE); + uint256 reqPerpTVL = (s.perpTVL + s.vaultTVL).mulDiv(ONE, targetSystemRatio + ONE); int256 reqUnderlyingAmtIntoPerp = reqPerpTVL.toInt256() - s.perpTVL.toInt256(); // Perp debasement, value needs to flow from perp into the vault @@ -308,16 +301,9 @@ contract FeePolicy is IFeePolicy, OwnableUpgradeable { } /// @inheritdoc IFeePolicy - function computeDeviationRatio(SubscriptionParams memory s) public view override returns (uint256) { + function computeDeviationRatio(SystemTVL memory s) public view override returns (uint256) { // NOTE: We assume that perp's TVL and vault's TVL values have the same base denomination. - uint256 juniorTR = TRANCHE_RATIO_GRANULARITY - s.seniorTR; - return (s.vaultTVL * s.seniorTR).mulDiv(ONE, (s.perpTVL * juniorTR)).mulDiv(ONE, targetSubscriptionRatio); - } - - /// @inheritdoc IFeePolicy - function computeDRNormSeniorTR(uint256 seniorTR) public view override returns (uint256) { - uint256 juniorTR = (TRANCHE_RATIO_GRANULARITY - seniorTR); - return ONE.mulDiv((seniorTR * ONE), (seniorTR * ONE) + (juniorTR * targetSubscriptionRatio)); + return s.vaultTVL.mulDiv(ONE, s.perpTVL).mulDiv(ONE, targetSystemRatio); } /// @return The range of deviation ratios which define the equilibrium zone. diff --git a/spot-contracts/contracts/PerpetualTranche.sol b/spot-contracts/contracts/PerpetualTranche.sol index a75d6fa2..6aee433c 100644 --- a/spot-contracts/contracts/PerpetualTranche.sol +++ b/spot-contracts/contracts/PerpetualTranche.sol @@ -4,7 +4,7 @@ pragma solidity ^0.8.20; import { IERC20MetadataUpgradeable } from "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol"; import { IERC20Upgradeable, IPerpetualTranche, IBondIssuer, IFeePolicy, IBondController, ITranche } from "./_interfaces/IPerpetualTranche.sol"; import { IRolloverVault } from "./_interfaces/IRolloverVault.sol"; -import { TokenAmount, RolloverData, SubscriptionParams } from "./_interfaces/CommonTypes.sol"; +import { TokenAmount, RolloverData, SystemTVL } from "./_interfaces/CommonTypes.sol"; import { UnauthorizedCall, UnauthorizedTransferOut, UnexpectedDecimals, UnexpectedAsset, UnacceptableParams, UnacceptableRollover, ExceededMaxSupply, ExceededMaxMintPerTranche, ReserveCountOverLimit, InvalidPerc } from "./_interfaces/ProtocolErrors.sol"; import { OwnableUpgradeable } from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; @@ -642,7 +642,7 @@ contract PerpetualTranche is /// @inheritdoc IPerpetualTranche function deviationRatio() external override afterStateUpdate nonReentrant returns (uint256) { - return feePolicy.computeDeviationRatio(_querySubscriptionState()); + return feePolicy.computeDeviationRatio(_querySystemTVL()); } //-------------------------------------------------------------------------- @@ -785,14 +785,12 @@ contract PerpetualTranche is //----------------------------------------------------------------------------- // We charge no mint fee when interacting with other callers within the system. - SubscriptionParams memory s = _querySubscriptionState(); + SystemTVL memory s = _querySystemTVL(); uint256 feePerc = _isProtocolCaller() ? 0 : feePolicy.computeFeePerc( feePolicy.computeDeviationRatio(s), - feePolicy.computeDeviationRatio( - SubscriptionParams({ perpTVL: s.perpTVL + valueIn, vaultTVL: s.vaultTVL, seniorTR: s.seniorTR }) - ) + feePolicy.computeDeviationRatio(SystemTVL({ perpTVL: s.perpTVL + valueIn, vaultTVL: s.vaultTVL })) ); //----------------------------------------------------------------------------- @@ -818,17 +816,13 @@ contract PerpetualTranche is //----------------------------------------------------------------------------- // We charge no burn fee when interacting with other parts of the system. - SubscriptionParams memory s = _querySubscriptionState(); + SystemTVL memory s = _querySystemTVL(); uint256 feePerc = _isProtocolCaller() ? 0 : feePolicy.computeFeePerc( feePolicy.computeDeviationRatio(s), feePolicy.computeDeviationRatio( - SubscriptionParams({ - perpTVL: s.perpTVL.mulDiv(perpSupply - perpAmt, perpSupply), - vaultTVL: s.vaultTVL, - seniorTR: s.seniorTR - }) + SystemTVL({ perpTVL: s.perpTVL.mulDiv(perpSupply - perpAmt, perpSupply), vaultTVL: s.vaultTVL }) ) ); //----------------------------------------------------------------------------- @@ -1051,14 +1045,9 @@ contract PerpetualTranche is return (trancheSupply > 0) ? trancheClaim.mulDiv(trancheAmt, trancheSupply, rounding) : trancheAmt; } - /// @dev Queries the current subscription state of the perp and vault systems. - function _querySubscriptionState() private view returns (SubscriptionParams memory) { - return - SubscriptionParams({ - perpTVL: _reserveValue(), - vaultTVL: vault.getTVL(), - seniorTR: _depositBond.getSeniorTrancheRatio() - }); + /// @dev Queries the current TVL of the perp and vault systems. + function _querySystemTVL() private view returns (SystemTVL memory) { + return SystemTVL({ perpTVL: _reserveValue(), vaultTVL: vault.getTVL() }); } /// @dev Checks if the given token is the underlying collateral token. diff --git a/spot-contracts/contracts/RolloverVault.sol b/spot-contracts/contracts/RolloverVault.sol index e7cafee3..a30f1190 100644 --- a/spot-contracts/contracts/RolloverVault.sol +++ b/spot-contracts/contracts/RolloverVault.sol @@ -5,7 +5,7 @@ import { IERC20Upgradeable, IPerpetualTranche, IBondController, ITranche, IFeePo import { IVault } from "./_interfaces/IVault.sol"; import { IRolloverVault } from "./_interfaces/IRolloverVault.sol"; import { IERC20Burnable } from "./_interfaces/IERC20Burnable.sol"; -import { TokenAmount, RolloverData, SubscriptionParams } from "./_interfaces/CommonTypes.sol"; +import { TokenAmount, RolloverData, SystemTVL } from "./_interfaces/CommonTypes.sol"; import { UnauthorizedCall, UnauthorizedTransferOut, UnexpectedDecimals, UnexpectedAsset, OutOfBounds, UnacceptableSwap, InsufficientDeployment, DeployedCountOverLimit, InsufficientLiquidity, LastRebalanceTooRecent } from "./_interfaces/ProtocolErrors.sol"; import { OwnableUpgradeable } from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; @@ -103,15 +103,12 @@ contract RolloverVault is /// @dev The maximum number of deployed assets that can be held in this vault at any given time. uint8 public constant MAX_DEPLOYED_COUNT = 47; - // Replicating value used here: - // https://github.com/buttonwood-protocol/tranche/blob/main/contracts/BondController.sol - uint256 private constant TRANCHE_RATIO_GRANULARITY = 1000; - /// @dev Immature redemption may result in some dust tranches when balances are not perfectly divisible by the tranche ratio. /// Based on current the implementation of `computeRedeemableTrancheAmounts`, /// the dust balances which remain after immature redemption will be *at most* {TRANCHE_RATIO_GRANULARITY} or 1000. /// We exclude the vault's dust tranche balances from TVL computation, note redemption and /// during recovery (through recurrent immature redemption). + /// https://github.com/buttonwood-protocol/tranche/blob/main/contracts/BondController.sol uint256 public constant TRANCHE_DUST_AMT = 10000000; //-------------------------------------------------------------------------- @@ -161,13 +158,9 @@ contract RolloverVault is /// @custom:oz-upgrades-renamed-from minUnderlyingBal uint256 public reservedUnderlyingBal; - /// @notice The percentage of the vault's "neutrally" subscribed TVL, reserved. - /// @dev A neutral subscription state implies the vault's TVL is exactly enough to - /// rollover over the entire supply of perp tokens. - /// NOTE: A neutral subscription ratio of 1.0 is distinct from a deviation ratio (dr) of 1.0. - /// For more details, refer to the fee policy documentation. - /// @custom:oz-upgrades-renamed-from minUnderlyingPerc - uint256 public reservedSubscriptionPerc; + /// @notice The amount of underlying tokens as percentage of the vault's TVL, reserved. + /// @custom:oz-upgrades-renamed-from reservedSubscriptionPerc + uint256 public reservedUnderlyingPerc; //-------------------------------------------------------------------------- // v3.0.0 STORAGE ADDITION @@ -227,7 +220,7 @@ contract RolloverVault is // setting initial parameter values minDeploymentAmt = 0; reservedUnderlyingBal = 0; - reservedSubscriptionPerc = 0; + reservedUnderlyingPerc = 0; lastRebalanceTimestampSec = block.timestamp; // sync underlying @@ -291,15 +284,15 @@ contract RolloverVault is /// @notice Updates the vault's minimum liquidity requirements. /// @param minDeploymentAmt_ The new minimum deployment amount, denominated in underlying tokens. /// @param reservedUnderlyingBal_ The new reserved underlying balance. - /// @param reservedSubscriptionPerc_ The new reserved subscription percentage. + /// @param reservedUnderlyingPerc_ The new reserved subscription percentage. function updateLiquidityLimits( uint256 minDeploymentAmt_, uint256 reservedUnderlyingBal_, - uint256 reservedSubscriptionPerc_ + uint256 reservedUnderlyingPerc_ ) external onlyKeeper { minDeploymentAmt = minDeploymentAmt_; reservedUnderlyingBal = reservedUnderlyingBal_; - reservedSubscriptionPerc = reservedSubscriptionPerc_; + reservedUnderlyingPerc = reservedUnderlyingPerc_; } //-------------------------------------------------------------------------- @@ -331,7 +324,7 @@ contract RolloverVault is // We calculate the usable underlying balance. uint256 underlyingBal = underlying_.balanceOf(address(this)); - uint256 reservedBal = _totalReservedBalance(perp_.getTVL(), perp_.getDepositTrancheRatio()); + uint256 reservedBal = _totalReservedBalance(getTVL()); uint256 usableBal = (underlyingBal > reservedBal) ? underlyingBal - reservedBal : 0; // We ensure that at-least `minDeploymentAmt` amount of underlying tokens are deployed @@ -426,8 +419,8 @@ contract RolloverVault is IERC20Upgradeable underlying_ = underlying; // Compute perp vault asset split. - SubscriptionParams memory s = _querySubscriptionState(perp_); - uint256 underlyingAmtIntoPerp = feePolicy.computeDRNormSeniorTR(s.seniorTR).mulDiv(underlyingAmtIn, ONE); + SystemTVL memory s = _querySystemTVL(perp_); + uint256 underlyingAmtIntoPerp = underlyingAmtIn.mulDiv(ONE, ONE + feePolicy.targetSystemRatio()); uint256 underlyingAmtIntoVault = underlyingAmtIn - underlyingAmtIntoPerp; // Compute perp amount and vault note amount to mint @@ -438,7 +431,7 @@ contract RolloverVault is underlying_.safeTransferFrom(msg.sender, address(this), underlyingAmtIn); // Mint perps to user - _trancheAndMintPerps(perp_, underlying_, s.perpTVL, s.seniorTR, perpAmt); + _trancheAndMintPerps(perp_, underlying_, s.perpTVL, perp_.getDepositTrancheRatio(), perpAmt); IERC20Upgradeable(address(perp_)).safeTransfer(msg.sender, perpAmt); // Mint vault notes to user @@ -513,12 +506,10 @@ contract RolloverVault is /// @inheritdoc IVault function deposit(uint256 underlyingAmtIn) external override nonReentrant whenNotPaused returns (uint256) { // Compute the mint fees - SubscriptionParams memory s = _querySubscriptionState(perp); + SystemTVL memory s = _querySystemTVL(perp); uint256 feePerc = feePolicy.computeFeePerc( feePolicy.computeDeviationRatio(s), - feePolicy.computeDeviationRatio( - SubscriptionParams({ perpTVL: s.perpTVL, vaultTVL: s.vaultTVL + underlyingAmtIn, seniorTR: s.seniorTR }) - ) + feePolicy.computeDeviationRatio(SystemTVL({ perpTVL: s.perpTVL, vaultTVL: s.vaultTVL + underlyingAmtIn })) ); // Calculates the fee adjusted amount of vault notes minted when depositing `underlyingAmtIn` of underlying tokens. @@ -546,15 +537,14 @@ contract RolloverVault is } // Compute the redemption fees - SubscriptionParams memory s = _querySubscriptionState(perp); + SystemTVL memory s = _querySystemTVL(perp); uint256 vaultNoteSupply = totalSupply(); uint256 feePerc = feePolicy.computeFeePerc( feePolicy.computeDeviationRatio(s), feePolicy.computeDeviationRatio( - SubscriptionParams({ + SystemTVL({ perpTVL: s.perpTVL, - vaultTVL: s.vaultTVL.mulDiv(vaultNoteSupply - vaultNoteAmt, vaultNoteSupply), - seniorTR: s.seniorTR + vaultTVL: s.vaultTVL.mulDiv(vaultNoteSupply - vaultNoteAmt, vaultNoteSupply) }) ) ); @@ -594,7 +584,7 @@ contract RolloverVault is IPerpetualTranche perp_ = perp; IERC20Upgradeable underlying_ = underlying; uint256 underlyingBalPre = underlying_.balanceOf(address(this)); - (uint256 perpAmtOut, , SubscriptionParams memory s) = computeUnderlyingToPerpSwapAmt(underlyingAmtIn); + (uint256 perpAmtOut, , SystemTVL memory s) = computeUnderlyingToPerpSwapAmt(underlyingAmtIn); // Revert if insufficient tokens are swapped in or out if (perpAmtOut <= 0 || underlyingAmtIn <= 0) { @@ -605,7 +595,7 @@ contract RolloverVault is underlying_.safeTransferFrom(msg.sender, address(this), underlyingAmtIn); // tranche and mint perps as needed - _trancheAndMintPerps(perp_, underlying_, s.perpTVL, s.seniorTR, perpAmtOut); + _trancheAndMintPerps(perp_, underlying_, s.perpTVL, perp_.getDepositTrancheRatio(), perpAmtOut); // transfer remaining perps out to the user IERC20Upgradeable(address(perp_)).safeTransfer(msg.sender, perpAmtOut); @@ -616,10 +606,7 @@ contract RolloverVault is // We ensure that the vault's underlying token liquidity // remains above the reserved level after swap. uint256 underlyingBalPost = underlying_.balanceOf(address(this)); - if ( - (underlyingBalPost < underlyingBalPre) && - (underlyingBalPost <= _totalReservedBalance((s.perpTVL + underlyingAmtIn), s.seniorTR)) - ) { + if ((underlyingBalPost < underlyingBalPre) && (underlyingBalPost <= _totalReservedBalance(s.vaultTVL))) { revert InsufficientLiquidity(); } @@ -668,26 +655,24 @@ contract RolloverVault is /// @inheritdoc IRolloverVault function deviationRatio() external override nonReentrant returns (uint256) { - return feePolicy.computeDeviationRatio(_querySubscriptionState(perp)); + return feePolicy.computeDeviationRatio(_querySystemTVL(perp)); } /// @inheritdoc IRolloverVault function computeUnderlyingToPerpSwapAmt( uint256 underlyingAmtIn - ) public returns (uint256, uint256, SubscriptionParams memory) { + ) public returns (uint256, uint256, SystemTVL memory) { IPerpetualTranche perp_ = perp; // Compute equal value perps to swap out to the user - SubscriptionParams memory s = _querySubscriptionState(perp_); + SystemTVL memory s = _querySystemTVL(perp_); uint256 perpAmtOut = underlyingAmtIn.mulDiv(perp_.totalSupply(), s.perpTVL); //----------------------------------------------------------------------------- // When user swaps underlying for vault's perps -> perps are minted by the vault - // We thus compute fees based on the post-mint subscription state. + // We thus compute fees based on the post-mint system tvl. uint256 feePerc = feePolicy.computeFeePerc( feePolicy.computeDeviationRatio(s), - feePolicy.computeDeviationRatio( - SubscriptionParams({ perpTVL: s.perpTVL + underlyingAmtIn, vaultTVL: s.vaultTVL, seniorTR: s.seniorTR }) - ) + feePolicy.computeDeviationRatio(SystemTVL({ perpTVL: s.perpTVL + underlyingAmtIn, vaultTVL: s.vaultTVL })) ); //----------------------------------------------------------------------------- @@ -698,26 +683,18 @@ contract RolloverVault is } /// @inheritdoc IRolloverVault - function computePerpToUnderlyingSwapAmt( - uint256 perpAmtIn - ) public returns (uint256, uint256, SubscriptionParams memory) { + function computePerpToUnderlyingSwapAmt(uint256 perpAmtIn) public returns (uint256, uint256, SystemTVL memory) { IPerpetualTranche perp_ = perp; // Compute equal value underlying tokens to swap out - SubscriptionParams memory s = _querySubscriptionState(perp_); + SystemTVL memory s = _querySystemTVL(perp_); uint256 underlyingAmtOut = perpAmtIn.mulDiv(s.perpTVL, perp_.totalSupply()); //----------------------------------------------------------------------------- // When user swaps perps for vault's underlying -> perps are redeemed by the vault - // We thus compute fees based on the post-burn subscription state. + // We thus compute fees based on the post-burn system tvl. uint256 feePerc = feePolicy.computeFeePerc( feePolicy.computeDeviationRatio(s), - feePolicy.computeDeviationRatio( - SubscriptionParams({ - perpTVL: s.perpTVL - underlyingAmtOut, - vaultTVL: s.vaultTVL, - seniorTR: s.seniorTR - }) - ) + feePolicy.computeDeviationRatio(SystemTVL({ perpTVL: s.perpTVL - underlyingAmtOut, vaultTVL: s.vaultTVL })) ); //----------------------------------------------------------------------------- @@ -867,7 +844,7 @@ contract RolloverVault is perp_.claimFees(address(this)); _meldPerps(perp_); - SubscriptionParams memory s = _querySubscriptionState(perp_); + SystemTVL memory s = _querySystemTVL(perp_); int256 underlyingAmtIntoPerp = feePolicy.computeRebalanceAmount(s); // When value is flowing into perp from the vault. @@ -882,7 +859,7 @@ contract RolloverVault is // We transfer value by minting the perp tokens (after making required deposit) // and then simply burning the newly minted perp tokens. uint256 perpAmtToTransfer = (underlyingAmtIntoPerp.toUint256()).mulDiv(perp_.totalSupply(), s.perpTVL); - _trancheAndMintPerps(perp_, underlying_, s.perpTVL, s.seniorTR, perpAmtToTransfer); + _trancheAndMintPerps(perp_, underlying_, s.perpTVL, perp_.getDepositTrancheRatio(), perpAmtToTransfer); IERC20Burnable(address(perp_)).burn(perpAmtToTransfer); } @@ -969,7 +946,7 @@ contract RolloverVault is IPerpetualTranche perp_, IERC20Upgradeable underlying_, uint256 perpTVL, - uint256 seniorTR, + uint256 depositTrancheTR, uint256 perpAmtToMint ) private { // Tranche as needed @@ -982,7 +959,7 @@ contract RolloverVault is depositBondCollateralBalance: underlying_.balanceOf(address(depositBond)), depositBondTotalDebt: depositBond.totalDebt(), depositTrancheSupply: trancheIntoPerp.totalSupply(), - depositTrancheTR: seniorTR + depositTrancheTR: depositTrancheTR }), perpAmtToMint ); @@ -1089,25 +1066,16 @@ contract RolloverVault is emit AssetSynced(token, balance); } - /// @dev Queries the current subscription state of the perp and vault systems. - function _querySubscriptionState(IPerpetualTranche perp_) private returns (SubscriptionParams memory) { - return - SubscriptionParams({ - perpTVL: perp_.getTVL(), - vaultTVL: getTVL(), - seniorTR: perp_.getDepositTrancheRatio() - }); + /// @dev Queries the current TVL of the perp and vault systems. + function _querySystemTVL(IPerpetualTranche perp_) private returns (SystemTVL memory) { + return SystemTVL({ perpTVL: perp_.getTVL(), vaultTVL: getTVL() }); } //-------------------------------------------------------------------------- // Private view methods /// @dev Computes the balance of underlying tokens to NOT be used for any operation. - function _totalReservedBalance(uint256 perpTVL, uint256 seniorTR) private view returns (uint256) { - return - MathUpgradeable.max( - reservedUnderlyingBal, - perpTVL.mulDiv(TRANCHE_RATIO_GRANULARITY - seniorTR, seniorTR).mulDiv(reservedSubscriptionPerc, ONE) - ); + function _totalReservedBalance(uint256 vaultTVL) private view returns (uint256) { + return MathUpgradeable.max(reservedUnderlyingBal, vaultTVL.mulDiv(reservedUnderlyingPerc, ONE)); } } diff --git a/spot-contracts/contracts/_interfaces/CommonTypes.sol b/spot-contracts/contracts/_interfaces/CommonTypes.sol index 6ef1437d..cd344c85 100644 --- a/spot-contracts/contracts/_interfaces/CommonTypes.sol +++ b/spot-contracts/contracts/_interfaces/CommonTypes.sol @@ -10,14 +10,12 @@ struct TokenAmount { uint256 amount; } -/// @notice The system subscription parameters. -struct SubscriptionParams { +/// @notice The system TVL parameters. +struct SystemTVL { /// @notice The current TVL of perp denominated in the underlying. uint256 perpTVL; /// @notice The current TVL of the vault denominated in the underlying. uint256 vaultTVL; - /// @notice The tranche ratio of seniors accepted by perp. - uint256 seniorTR; } struct RolloverData { diff --git a/spot-contracts/contracts/_interfaces/IFeePolicy.sol b/spot-contracts/contracts/_interfaces/IFeePolicy.sol index 801a2d9a..1622443d 100644 --- a/spot-contracts/contracts/_interfaces/IFeePolicy.sol +++ b/spot-contracts/contracts/_interfaces/IFeePolicy.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.0; -import { SubscriptionParams } from "./CommonTypes.sol"; +import { SystemTVL } from "./CommonTypes.sol"; interface IFeePolicy { /// @return The percentage of the mint perp tokens to be charged as fees, @@ -12,20 +12,18 @@ interface IFeePolicy { /// @return Number of decimals representing a multiplier of 1.0. So, 100% = 1*10**decimals. function decimals() external view returns (uint8); - /// @param s The subscription parameters of both the perp and vault systems. - /// @return The deviation ratio given the system subscription parameters. - function computeDeviationRatio(SubscriptionParams memory s) external view returns (uint256); + /// @param s The TVL of both the perp and vault systems. + /// @return The deviation ratio given the system TVL. + function computeDeviationRatio(SystemTVL memory s) external view returns (uint256); - /// @param seniorTR The senior tranche ratio of the deposit bond. - /// @return The "targetSR" adjusted senior tranche ratio, - /// as a fixed-point number with {DECIMALS} decimal places. - function computeDRNormSeniorTR(uint256 seniorTR) external view returns (uint256); + /// @return The target system ratio as a fixed-point number with {DECIMALS} decimal places. + function targetSystemRatio() external view returns (uint256); /// @notice Computes magnitude and direction of value flow between perp and the rollover vault /// expressed in underlying tokens. - /// @param s The subscription parameters of both the perp and vault systems. + /// @param s The TVL of both the perp and vault systems. /// @return underlyingAmtIntoPerp The value in underlying tokens, that need to flow from the vault into perp. - function computeRebalanceAmount(SubscriptionParams memory s) external view returns (int256 underlyingAmtIntoPerp); + function computeRebalanceAmount(SystemTVL memory s) external view returns (int256 underlyingAmtIntoPerp); /// @return The share of the system tvl paid to the protocol owner as fees. function protocolSharePerc() external view returns (uint256); diff --git a/spot-contracts/contracts/_interfaces/IRolloverVault.sol b/spot-contracts/contracts/_interfaces/IRolloverVault.sol index 7ccc0847..1a11d119 100644 --- a/spot-contracts/contracts/_interfaces/IRolloverVault.sol +++ b/spot-contracts/contracts/_interfaces/IRolloverVault.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.0; import { IVault } from "./IVault.sol"; -import { SubscriptionParams, TokenAmount } from "./CommonTypes.sol"; +import { SystemTVL, TokenAmount } from "./CommonTypes.sol"; interface IRolloverVault is IVault { /// @notice Gradually transfers value between the perp and vault, to bring the system back into balance. @@ -40,19 +40,17 @@ interface IRolloverVault is IVault { /// @param underlyingAmtIn The number of underlying tokens the user swaps in. /// @return perpAmtOut The number of perp tokens returned to the user. /// @return perpFeeAmtToBurn The amount of perp tokens to be paid to the perp contract as mint fees. - /// @return s The pre-swap perp and vault subscription state. + /// @return s The pre-swap perp and vault TVL. function computeUnderlyingToPerpSwapAmt( uint256 underlyingAmtIn - ) external returns (uint256, uint256, SubscriptionParams memory); + ) external returns (uint256, uint256, SystemTVL memory); /// @notice Computes the amount of underlying tokens that are returned when user swaps a given number of perp tokens. /// @param perpAmtIn The number of perp tokens the user swaps in. /// @return underlyingAmtOut The number of underlying tokens returned to the user. /// @return perpFeeAmtToBurn The amount of perp tokens to be paid to the perp contract as burn fees. - /// @return s The pre-swap perp and vault subscription state. - function computePerpToUnderlyingSwapAmt( - uint256 perpAmtIn - ) external returns (uint256, uint256, SubscriptionParams memory); + /// @return s The pre-swap perp and vault TVL. + function computePerpToUnderlyingSwapAmt(uint256 perpAmtIn) external returns (uint256, uint256, SystemTVL memory); /// @return The system's current deviation ratio. function deviationRatio() external returns (uint256); diff --git a/spot-contracts/hardhat.config.ts b/spot-contracts/hardhat.config.ts index 25ab7126..45427cc3 100644 --- a/spot-contracts/hardhat.config.ts +++ b/spot-contracts/hardhat.config.ts @@ -53,7 +53,7 @@ export default { settings: { optimizer: { enabled: true, - runs: 40, + runs: 50, }, }, }, diff --git a/spot-contracts/tasks/ops/vaults.ts b/spot-contracts/tasks/ops/vaults.ts index e2549e0e..4c547e8b 100644 --- a/spot-contracts/tasks/ops/vaults.ts +++ b/spot-contracts/tasks/ops/vaults.ts @@ -80,11 +80,7 @@ task("ops:vault:info") const subscriptionRatio = (vaultTVL * seniorTR * feeOne) / perpTVL / juniorTR; const targetSubscriptionRatio = await feePolicy.targetSubscriptionRatio(); const expectedVaultTVL = (targetSubscriptionRatio * perpTVL * juniorTR) / seniorTR / feeOne; - const deviationRatio = await feePolicy["computeDeviationRatio((uint256,uint256,uint256))"]([ - perpTVL, - vaultTVL, - seniorTR, - ]); + const deviationRatio = await feePolicy["computeDeviationRatio((uint256,uint256))"]([perpTVL, vaultTVL, seniorTR]); console.log("perpTVL:", hre.ethers.formatUnits(perpTVL, underlyingDecimals)); console.log("vaultTVL:", hre.ethers.formatUnits(vaultTVL, underlyingDecimals)); console.log("expectedVaultTVL:", hre.ethers.formatUnits(expectedVaultTVL, underlyingDecimals)); diff --git a/spot-contracts/test/FeePolicy.ts b/spot-contracts/test/FeePolicy.ts index 9c140133..8793edef 100644 --- a/spot-contracts/test/FeePolicy.ts +++ b/spot-contracts/test/FeePolicy.ts @@ -32,7 +32,7 @@ describe("FeePolicy", function () { describe("#init", function () { it("should return the initial parameters", async function () { - expect(await feePolicy.targetSubscriptionRatio()).to.eq(toPerc("1.5")); + expect(await feePolicy.targetSystemRatio()).to.eq(toPerc("3")); const f1 = await feePolicy.feeFnDRDown(); expect(f1[0]).to.eq(toPerc("0.66")); @@ -73,20 +73,20 @@ describe("FeePolicy", function () { }); }); - describe("#updateTargetSubscriptionRatio", function () { + describe("#updateTargetSystemRatio", function () { describe("when triggered by non-owner", function () { it("should revert", async function () { - await expect(feePolicy.connect(otherUser).updateTargetSubscriptionRatio(toPerc("1.25"))).to.be.revertedWith( + await expect(feePolicy.connect(otherUser).updateTargetSystemRatio(toPerc("2"))).to.be.revertedWith( "Ownable: caller is not the owner", ); }); }); describe("when triggered by owner", function () { - it("should update the target sr", async function () { - expect(await feePolicy.targetSubscriptionRatio()).to.eq(toPerc("1.5")); - await feePolicy.connect(deployer).updateTargetSubscriptionRatio(toPerc("1.25")); - expect(await feePolicy.targetSubscriptionRatio()).to.eq(toPerc("1.25")); + it("should update the target system ratio", async function () { + expect(await feePolicy.targetSystemRatio()).to.eq(toPerc("3")); + await feePolicy.connect(deployer).updateTargetSystemRatio(toPerc("2")); + expect(await feePolicy.targetSystemRatio()).to.eq(toPerc("2")); }); }); }); @@ -291,15 +291,14 @@ describe("FeePolicy", function () { describe("#computeDeviationRatio", async function () { beforeEach(async function () { - await feePolicy.updateTargetSubscriptionRatio(toPerc("1.25")); + await feePolicy.updateTargetSystemRatio(toPerc("3")); }); describe("when deviation = 1.0", function () { it("should return 1", async function () { - const r = await feePolicy["computeDeviationRatio((uint256,uint256,uint256))"]({ + const r = await feePolicy.computeDeviationRatio({ perpTVL: toAmt("100"), - vaultTVL: toAmt("500"), - seniorTR: 200, + vaultTVL: toAmt("300"), }); expect(r).to.eq(toPerc("1")); }); @@ -307,10 +306,9 @@ describe("FeePolicy", function () { describe("when deviation > 1.0", function () { it("should compute dr", async function () { - const r = await feePolicy["computeDeviationRatio((uint256,uint256,uint256))"]({ + const r = await feePolicy.computeDeviationRatio({ perpTVL: toAmt("100"), - vaultTVL: toAmt("1000"), - seniorTR: 200, + vaultTVL: toAmt("600"), }); expect(r).to.eq(toPerc("2")); }); @@ -318,30 +316,18 @@ describe("FeePolicy", function () { describe("when deviation < 1.0", function () { it("should compute dr", async function () { - const r = await feePolicy["computeDeviationRatio((uint256,uint256,uint256))"]({ + const r = await feePolicy.computeDeviationRatio({ perpTVL: toAmt("100"), - vaultTVL: toAmt("250"), - seniorTR: 200, + vaultTVL: toAmt("150"), }); expect(r).to.eq(toPerc("0.5")); }); }); }); - describe("#computeDRNormSeniorTR", function () { - it("should compute the dr norm ratio", async function () { - await feePolicy.updateTargetSubscriptionRatio(toPerc("2")); - expect(await feePolicy.computeDRNormSeniorTR(200)).to.eq(toPerc("0.11111111")); - expect(await feePolicy.computeDRNormSeniorTR(500)).to.eq(toPerc("0.33333333")); - expect(await feePolicy.computeDRNormSeniorTR(333)).to.eq(toPerc("0.19976004")); - expect(await feePolicy.computeDRNormSeniorTR(666)).to.eq(toPerc("0.49925037")); - expect(await feePolicy.computeDRNormSeniorTR(750)).to.eq(toPerc("0.6")); - }); - }); - describe("#computeRebalanceAmount", async function () { beforeEach(async function () { - await feePolicy.updateTargetSubscriptionRatio(toPerc("1.25")); + await feePolicy.updateTargetSystemRatio(toPerc("5")); await feePolicy.connect(deployer).updateRebalanceConfig(1, 1, toRange("0", "10"), toRange("0", "10"), 86400); }); @@ -351,13 +337,11 @@ describe("FeePolicy", function () { const r1 = await feePolicy.computeRebalanceAmount({ perpTVL: toAmt("120"), vaultTVL: toAmt("500"), - seniorTR: 200, }); expect(r1).to.eq(0n); const r2 = await feePolicy.computeRebalanceAmount({ perpTVL: toAmt("80"), vaultTVL: toAmt("500"), - seniorTR: 200, }); expect(r2).to.eq(0n); }); @@ -368,7 +352,6 @@ describe("FeePolicy", function () { const r = await feePolicy.computeRebalanceAmount({ perpTVL: toAmt("100"), vaultTVL: toAmt("500"), - seniorTR: 200, }); expect(r).to.eq(0n); }); @@ -379,7 +362,6 @@ describe("FeePolicy", function () { const r = await feePolicy.computeRebalanceAmount({ perpTVL: toAmt("100"), vaultTVL: toAmt("500.001"), - seniorTR: 200, }); expect(r).to.eq(0n); }); @@ -390,7 +372,6 @@ describe("FeePolicy", function () { const r = await feePolicy.computeRebalanceAmount({ perpTVL: toAmt("99.999"), vaultTVL: toAmt("500"), - seniorTR: 200, }); expect(r).to.eq(0n); }); @@ -401,9 +382,8 @@ describe("FeePolicy", function () { const r = await feePolicy.computeRebalanceAmount({ perpTVL: toAmt("100"), vaultTVL: toAmt("1000"), - seniorTR: 200, }); - expect(r).to.eq(toAmt("83.333326")); + expect(r).to.eq(toAmt("83.333333333333333333")); }); it("should compute rebalance data", async function () { @@ -411,9 +391,8 @@ describe("FeePolicy", function () { const r = await feePolicy.computeRebalanceAmount({ perpTVL: toAmt("100"), vaultTVL: toAmt("1000"), - seniorTR: 200, }); - expect(r).to.eq(toAmt("41.666663")); + expect(r).to.eq(toAmt("41.666666666666666666")); }); it("should compute rebalance data", async function () { @@ -421,7 +400,6 @@ describe("FeePolicy", function () { const r = await feePolicy.computeRebalanceAmount({ perpTVL: toAmt("100"), vaultTVL: toAmt("1000"), - seniorTR: 200, }); expect(r).to.eq(toAmt("10")); }); @@ -431,7 +409,6 @@ describe("FeePolicy", function () { const r = await feePolicy.computeRebalanceAmount({ perpTVL: toAmt("100"), vaultTVL: toAmt("1000"), - seniorTR: 200, }); expect(r).to.eq(toAmt("5")); }); @@ -441,9 +418,8 @@ describe("FeePolicy", function () { const r = await feePolicy.computeRebalanceAmount({ perpTVL: toAmt("100"), vaultTVL: toAmt("1000"), - seniorTR: 200, }); - expect(r).to.eq(toAmt("83.333326")); + expect(r).to.eq(toAmt("83.333333333333333333")); }); }); @@ -452,9 +428,8 @@ describe("FeePolicy", function () { const r = await feePolicy.computeRebalanceAmount({ perpTVL: toAmt("1000"), vaultTVL: toAmt("2500"), - seniorTR: 200, }); - expect(r).to.eq(toAmt("-416.66669")); + expect(r).to.eq(toAmt("-416.666666666666666667")); }); it("should compute rebalance data", async function () { @@ -462,9 +437,8 @@ describe("FeePolicy", function () { const r = await feePolicy.computeRebalanceAmount({ perpTVL: toAmt("1000"), vaultTVL: toAmt("2500"), - seniorTR: 200, }); - expect(r).to.eq(toAmt("-208.333345")); + expect(r).to.eq(toAmt("-208.333333333333333333")); }); it("should compute rebalance data", async function () { @@ -474,7 +448,6 @@ describe("FeePolicy", function () { const r = await feePolicy.computeRebalanceAmount({ perpTVL: toAmt("1000"), vaultTVL: toAmt("2500"), - seniorTR: 200, }); expect(r).to.eq(toAmt("-50")); }); @@ -484,7 +457,6 @@ describe("FeePolicy", function () { const r = await feePolicy.computeRebalanceAmount({ perpTVL: toAmt("1000"), vaultTVL: toAmt("2500"), - seniorTR: 200, }); expect(r).to.eq(toAmt("-30")); }); @@ -494,9 +466,8 @@ describe("FeePolicy", function () { const r = await feePolicy.computeRebalanceAmount({ perpTVL: toAmt("1000"), vaultTVL: toAmt("2500"), - seniorTR: 200, }); - expect(r).to.eq(toAmt("-416.66669")); + expect(r).to.eq(toAmt("-416.666666666666666667")); }); }); }); diff --git a/spot-contracts/test/RouterV2.ts b/spot-contracts/test/RouterV2.ts index 27374c59..a278d2c2 100644 --- a/spot-contracts/test/RouterV2.ts +++ b/spot-contracts/test/RouterV2.ts @@ -49,7 +49,7 @@ describe("RouterV2", function () { feePolicy = new DMock(await ethers.getContractFactory("FeePolicy")); await feePolicy.deploy(); await feePolicy.mockMethod("decimals()", [8]); - await feePolicy.mockMethod("computeDeviationRatio((uint256,uint256,uint256))", [toPercFixedPtAmt("1")]); + await feePolicy.mockMethod("computeDeviationRatio((uint256,uint256))", [toPercFixedPtAmt("1")]); await feePolicy.mockMethod("computeFeePerc(uint256,uint256)", [0]); const PerpetualTranche = await ethers.getContractFactory("PerpetualTranche"); diff --git a/spot-contracts/test/perp/PerpetualTranche.ts b/spot-contracts/test/perp/PerpetualTranche.ts index 71055038..994b9305 100644 --- a/spot-contracts/test/perp/PerpetualTranche.ts +++ b/spot-contracts/test/perp/PerpetualTranche.ts @@ -43,7 +43,7 @@ describe("PerpetualTranche", function () { feePolicy = new DMock(await ethers.getContractFactory("FeePolicy")); await feePolicy.deploy(); await feePolicy.mockMethod("decimals()", [8]); - await feePolicy.mockMethod("computeDeviationRatio((uint256,uint256,uint256))", [toPercFixedPtAmt("1")]); + await feePolicy.mockMethod("computeDeviationRatio((uint256,uint256))", [toPercFixedPtAmt("1")]); await feePolicy.mockMethod("computeFeePerc(uint256,uint256)", [0]); const PerpetualTranche = await ethers.getContractFactory("PerpetualTranche"); diff --git a/spot-contracts/test/perp/PerpetualTranche_deposit.ts b/spot-contracts/test/perp/PerpetualTranche_deposit.ts index 3e254598..eb441960 100644 --- a/spot-contracts/test/perp/PerpetualTranche_deposit.ts +++ b/spot-contracts/test/perp/PerpetualTranche_deposit.ts @@ -51,7 +51,7 @@ describe("PerpetualTranche", function () { feePolicy = new DMock(await ethers.getContractFactory("FeePolicy")); await feePolicy.deploy(); await feePolicy.mockMethod("decimals()", [8]); - await feePolicy.mockMethod("computeDeviationRatio((uint256,uint256,uint256))", [toPercFixedPtAmt("1")]); + await feePolicy.mockMethod("computeDeviationRatio((uint256,uint256))", [toPercFixedPtAmt("1")]); await feePolicy.mockMethod("computeFeePerc(uint256,uint256)", [0]); const PerpetualTranche = await ethers.getContractFactory("PerpetualTranche"); @@ -482,15 +482,15 @@ describe("PerpetualTranche", function () { describe("when fee is set", function () { beforeEach(async function () { - await feePolicy.clearMockMethod("computeDeviationRatio((uint256,uint256,uint256))"); + await feePolicy.clearMockMethod("computeDeviationRatio((uint256,uint256))"); await feePolicy.mockCall( - "computeDeviationRatio((uint256,uint256,uint256))", - [[toFixedPtAmt("0"), toFixedPtAmt("0"), "500"]], + "computeDeviationRatio((uint256,uint256))", + [[toFixedPtAmt("0"), toFixedPtAmt("0")]], [toPercFixedPtAmt("1")], ); await feePolicy.mockCall( - "computeDeviationRatio((uint256,uint256,uint256))", - [[toFixedPtAmt("500"), toFixedPtAmt("0"), "500"]], + "computeDeviationRatio((uint256,uint256))", + [[toFixedPtAmt("500"), toFixedPtAmt("0")]], [toPercFixedPtAmt("1")], ); await feePolicy.mockMethod("computeFeePerc(uint256,uint256)", [toPercFixedPtAmt("0.01")]); diff --git a/spot-contracts/test/perp/PerpetualTranche_redeem.ts b/spot-contracts/test/perp/PerpetualTranche_redeem.ts index f0f3d04f..bb7112b0 100644 --- a/spot-contracts/test/perp/PerpetualTranche_redeem.ts +++ b/spot-contracts/test/perp/PerpetualTranche_redeem.ts @@ -52,7 +52,7 @@ describe("PerpetualTranche", function () { feePolicy = new DMock(await ethers.getContractFactory("FeePolicy")); await feePolicy.deploy(); await feePolicy.mockMethod("decimals()", [8]); - await feePolicy.mockMethod("computeDeviationRatio((uint256,uint256,uint256))", [toPercFixedPtAmt("1")]); + await feePolicy.mockMethod("computeDeviationRatio((uint256,uint256))", [toPercFixedPtAmt("1")]); await feePolicy.mockMethod("computeFeePerc(uint256,uint256)", [0]); const PerpetualTranche = await ethers.getContractFactory("PerpetualTranche"); @@ -582,15 +582,15 @@ describe("PerpetualTranche", function () { ); expect(await perp.totalSupply()).to.eq(toFixedPtAmt("1000")); - await feePolicy.clearMockMethod("computeDeviationRatio((uint256,uint256,uint256))"); + await feePolicy.clearMockMethod("computeDeviationRatio((uint256,uint256))"); await feePolicy.mockCall( - "computeDeviationRatio((uint256,uint256,uint256))", - [[toFixedPtAmt("1100"), toFixedPtAmt("0"), "500"]], + "computeDeviationRatio((uint256,uint256))", + [[toFixedPtAmt("1100"), toFixedPtAmt("0")]], [toPercFixedPtAmt("1")], ); await feePolicy.mockCall( - "computeDeviationRatio((uint256,uint256,uint256))", - [[toFixedPtAmt("550"), toFixedPtAmt("0"), "500"]], + "computeDeviationRatio((uint256,uint256))", + [[toFixedPtAmt("550"), toFixedPtAmt("0")]], [toPercFixedPtAmt("1")], ); await feePolicy.mockMethod("computeFeePerc(uint256,uint256)", [toPercFixedPtAmt("0.1")]); diff --git a/spot-contracts/test/perp/PerpetualTranche_rollover.ts b/spot-contracts/test/perp/PerpetualTranche_rollover.ts index efb244c1..6576c9ea 100644 --- a/spot-contracts/test/perp/PerpetualTranche_rollover.ts +++ b/spot-contracts/test/perp/PerpetualTranche_rollover.ts @@ -58,7 +58,7 @@ describe("PerpetualTranche", function () { feePolicy = new DMock(await ethers.getContractFactory("FeePolicy")); await feePolicy.deploy(); await feePolicy.mockMethod("decimals()", [8]); - await feePolicy.mockMethod("computeDeviationRatio((uint256,uint256,uint256))", [toPercFixedPtAmt("1")]); + await feePolicy.mockMethod("computeDeviationRatio((uint256,uint256))", [toPercFixedPtAmt("1")]); await feePolicy.mockMethod("computeFeePerc(uint256,uint256)", [0]); const MockVault = await ethers.getContractFactory("MockVault"); diff --git a/spot-contracts/test/rollover-vault/RolloverVault.ts b/spot-contracts/test/rollover-vault/RolloverVault.ts index 64d8441a..75ca1178 100644 --- a/spot-contracts/test/rollover-vault/RolloverVault.ts +++ b/spot-contracts/test/rollover-vault/RolloverVault.ts @@ -39,7 +39,7 @@ describe("RolloverVault", function () { feePolicy = new DMock(await ethers.getContractFactory("FeePolicy")); await feePolicy.deploy(); await feePolicy.mockMethod("decimals()", [8]); - await feePolicy.mockMethod("computeDeviationRatio((uint256,uint256,uint256))", [toPercFixedPtAmt("1")]); + await feePolicy.mockMethod("computeDeviationRatio((uint256,uint256))", [toPercFixedPtAmt("1")]); await feePolicy.mockMethod("computeFeePerc(uint256,uint256)", [0]); const TrancheManager = await ethers.getContractFactory("TrancheManager"); @@ -84,7 +84,7 @@ describe("RolloverVault", function () { it("should set initial param values", async function () { expect(await vault.minDeploymentAmt()).to.eq("0"); expect(await vault.reservedUnderlyingBal()).to.eq("0"); - expect(await vault.reservedSubscriptionPerc()).to.eq("0"); + expect(await vault.reservedUnderlyingPerc()).to.eq("0"); expect(await vault.lastRebalanceTimestampSec()).not.to.eq("0"); }); @@ -375,7 +375,7 @@ describe("RolloverVault", function () { it("should update the liquidity parameters", async function () { expect(await vault.minDeploymentAmt()).to.eq(toFixedPtAmt("1000")); expect(await vault.reservedUnderlyingBal()).to.eq(toFixedPtAmt("100000")); - expect(await vault.reservedSubscriptionPerc()).to.eq(toPercFixedPtAmt("0.25")); + expect(await vault.reservedUnderlyingPerc()).to.eq(toPercFixedPtAmt("0.25")); }); }); }); diff --git a/spot-contracts/test/rollover-vault/RolloverVault_deploy.ts b/spot-contracts/test/rollover-vault/RolloverVault_deploy.ts index 07ae3d54..b2627157 100644 --- a/spot-contracts/test/rollover-vault/RolloverVault_deploy.ts +++ b/spot-contracts/test/rollover-vault/RolloverVault_deploy.ts @@ -55,7 +55,7 @@ describe("RolloverVault", function () { feePolicy = new DMock(await ethers.getContractFactory("FeePolicy")); await feePolicy.deploy(); await feePolicy.mockMethod("decimals()", [8]); - await feePolicy.mockMethod("computeDeviationRatio((uint256,uint256,uint256))", [toPercFixedPtAmt("1")]); + await feePolicy.mockMethod("computeDeviationRatio((uint256,uint256))", [toPercFixedPtAmt("1")]); await feePolicy.mockMethod("computeFeePerc(uint256,uint256)", [0]); const PerpetualTranche = await ethers.getContractFactory("PerpetualTranche"); diff --git a/spot-contracts/test/rollover-vault/RolloverVault_deposit_redeem.ts b/spot-contracts/test/rollover-vault/RolloverVault_deposit_redeem.ts index 188b2ce5..2d3126fd 100644 --- a/spot-contracts/test/rollover-vault/RolloverVault_deposit_redeem.ts +++ b/spot-contracts/test/rollover-vault/RolloverVault_deposit_redeem.ts @@ -61,7 +61,7 @@ describe("RolloverVault", function () { feePolicy = new DMock(await ethers.getContractFactory("FeePolicy")); await feePolicy.deploy(); await feePolicy.mockMethod("decimals()", [8]); - await feePolicy.mockMethod("computeDeviationRatio((uint256,uint256,uint256))", [toPercFixedPtAmt("1")]); + await feePolicy.mockMethod("computeDeviationRatio((uint256,uint256))", [toPercFixedPtAmt("1")]); await feePolicy.mockMethod("computeFeePerc(uint256,uint256)", [0]); const PerpetualTranche = await ethers.getContractFactory("PerpetualTranche"); @@ -467,15 +467,15 @@ describe("RolloverVault", function () { await collateralToken.approve(vault.target, toFixedPtAmt("100")); await vault.deposit(toFixedPtAmt("100")); - await feePolicy.clearMockMethod("computeDeviationRatio((uint256,uint256,uint256))"); + await feePolicy.clearMockMethod("computeDeviationRatio((uint256,uint256))"); await feePolicy.mockCall( - "computeDeviationRatio((uint256,uint256,uint256))", - [[toFixedPtAmt("600"), toFixedPtAmt("100"), "200"]], + "computeDeviationRatio((uint256,uint256))", + [[toFixedPtAmt("600"), toFixedPtAmt("100")]], [toPercFixedPtAmt("1")], ); await feePolicy.mockCall( - "computeDeviationRatio((uint256,uint256,uint256))", - [[toFixedPtAmt("600"), toFixedPtAmt("200"), "200"]], + "computeDeviationRatio((uint256,uint256))", + [[toFixedPtAmt("600"), toFixedPtAmt("200")]], [toPercFixedPtAmt("1")], ); await feePolicy.mockMethod("computeFeePerc(uint256,uint256)", [toPercFixedPtAmt("0.05")]); @@ -799,15 +799,15 @@ describe("RolloverVault", function () { await collateralToken.transfer(vault.target, toFixedPtAmt("20")); bal = toFixedPtAmt("50") * 1000000n; - await feePolicy.clearMockMethod("computeDeviationRatio((uint256,uint256,uint256))"); + await feePolicy.clearMockMethod("computeDeviationRatio((uint256,uint256))"); await feePolicy.mockCall( - "computeDeviationRatio((uint256,uint256,uint256))", - [[toFixedPtAmt("600"), toFixedPtAmt("220"), "200"]], + "computeDeviationRatio((uint256,uint256))", + [[toFixedPtAmt("600"), toFixedPtAmt("220")]], [toPercFixedPtAmt("1")], ); await feePolicy.mockCall( - "computeDeviationRatio((uint256,uint256,uint256))", - [[toFixedPtAmt("600"), toFixedPtAmt("165"), "200"]], + "computeDeviationRatio((uint256,uint256))", + [[toFixedPtAmt("600"), toFixedPtAmt("165")]], [toPercFixedPtAmt("1")], ); await feePolicy.mockMethod("computeFeePerc(uint256,uint256)", [toPercFixedPtAmt("0.1")]); diff --git a/spot-contracts/test/rollover-vault/RolloverVault_pair_ops.ts b/spot-contracts/test/rollover-vault/RolloverVault_pair_ops.ts index ca7e6714..15fc8c4d 100644 --- a/spot-contracts/test/rollover-vault/RolloverVault_pair_ops.ts +++ b/spot-contracts/test/rollover-vault/RolloverVault_pair_ops.ts @@ -53,7 +53,7 @@ describe("RolloverVault", function () { feePolicy = new DMock(await ethers.getContractFactory("FeePolicy")); await feePolicy.deploy(); await feePolicy.mockMethod("decimals()", [8]); - await feePolicy.mockMethod("computeDeviationRatio((uint256,uint256,uint256))", [toPercFixedPtAmt("1")]); + await feePolicy.mockMethod("computeDeviationRatio((uint256,uint256))", [toPercFixedPtAmt("1")]); await feePolicy.mockMethod("computeFeePerc(uint256,uint256)", [0]); const PerpetualTranche = await ethers.getContractFactory("PerpetualTranche"); @@ -131,7 +131,7 @@ describe("RolloverVault", function () { describe("#mint2", function () { describe("when dr = 1", function () { beforeEach(async function () { - await feePolicy.mockMethod("computeDRNormSeniorTR(uint256)", [toPercFixedPtAmt("0.25")]); + await feePolicy.mockMethod("targetSystemRatio()", [toPercFixedPtAmt("3")]); }); it("should compute amounts", async function () { @@ -193,8 +193,8 @@ describe("RolloverVault", function () { describe("when dr > 1", function () { beforeEach(async function () { - await feePolicy.mockMethod("computeDRNormSeniorTR(uint256)", [toPercFixedPtAmt("0.25")]); - await feePolicy.mockMethod("computeDeviationRatio((uint256,uint256,uint256))", [toPercFixedPtAmt("1.25")]); + await feePolicy.mockMethod("targetSystemRatio()", [toPercFixedPtAmt("3")]); + await feePolicy.mockMethod("computeDeviationRatio((uint256,uint256))", [toPercFixedPtAmt("1.25")]); await vault.deposit(toFixedPtAmt("1000")); }); @@ -257,8 +257,8 @@ describe("RolloverVault", function () { describe("when dr < 1", function () { beforeEach(async function () { - await feePolicy.mockMethod("computeDRNormSeniorTR(uint256)", [toPercFixedPtAmt("0.25")]); - await feePolicy.mockMethod("computeDeviationRatio((uint256,uint256,uint256))", [toPercFixedPtAmt("0.75")]); + await feePolicy.mockMethod("targetSystemRatio()", [toPercFixedPtAmt("3")]); + await feePolicy.mockMethod("computeDeviationRatio((uint256,uint256))", [toPercFixedPtAmt("0.75")]); await vault.redeem(toFixedPtAmt("500") * 1000000n); expect(await vault.getTVL.staticCall()).to.eq(toFixedPtAmt("1500")); }); diff --git a/spot-contracts/test/rollover-vault/RolloverVault_rebalance.ts b/spot-contracts/test/rollover-vault/RolloverVault_rebalance.ts index eacbda7d..e5eb49eb 100644 --- a/spot-contracts/test/rollover-vault/RolloverVault_rebalance.ts +++ b/spot-contracts/test/rollover-vault/RolloverVault_rebalance.ts @@ -52,7 +52,7 @@ describe("RolloverVault", function () { feePolicy = new DMock(await ethers.getContractFactory("FeePolicy")); await feePolicy.deploy(); await feePolicy.mockMethod("decimals()", [8]); - await feePolicy.mockMethod("computeDeviationRatio((uint256,uint256,uint256))", [toPercFixedPtAmt("1")]); + await feePolicy.mockMethod("computeDeviationRatio((uint256,uint256))", [toPercFixedPtAmt("1")]); await feePolicy.mockMethod("computeFeePerc(uint256,uint256)", [0]); const PerpetualTranche = await ethers.getContractFactory("PerpetualTranche"); @@ -116,7 +116,7 @@ describe("RolloverVault", function () { await TimeHelpers.increaseTime(86401); await feePolicy.mockMethod("protocolSharePerc()", [0n]); - await feePolicy.mockMethod("computeRebalanceAmount((uint256,uint256,uint256))", [0n]); + await feePolicy.mockMethod("computeRebalanceAmount((uint256,uint256))", [0n]); await feePolicy.mockMethod("protocolFeeCollector()", [await deployer.getAddress()]); await feePolicy.mockMethod("rebalanceFreqSec()", [86400]); }); @@ -151,7 +151,7 @@ describe("RolloverVault", function () { describe("no-change", function () { beforeEach(async function () { - await feePolicy.mockMethod("computeRebalanceAmount((uint256,uint256,uint256))", [toFixedPtAmt("0")]); + await feePolicy.mockMethod("computeRebalanceAmount((uint256,uint256))", [toFixedPtAmt("0")]); }); it("should transfer value to the vault (by minting and melding perps)", async function () { expect(await perp.totalSupply()).to.eq(toFixedPtAmt("800")); @@ -168,7 +168,7 @@ describe("RolloverVault", function () { describe("no-change with protocol fee", function () { beforeEach(async function () { await feePolicy.mockMethod("protocolSharePerc()", [toPercFixedPtAmt("0.01")]); - await feePolicy.mockMethod("computeRebalanceAmount((uint256,uint256,uint256))", [toFixedPtAmt("0")]); + await feePolicy.mockMethod("computeRebalanceAmount((uint256,uint256))", [toFixedPtAmt("0")]); }); it("should transfer value to the vault (by minting and melding perps)", async function () { expect(await perp.totalSupply()).to.eq(toFixedPtAmt("800")); @@ -198,7 +198,7 @@ describe("RolloverVault", function () { describe("perp debasement", function () { beforeEach(async function () { - await feePolicy.mockMethod("computeRebalanceAmount((uint256,uint256,uint256))", [toFixedPtAmt("-10")]); + await feePolicy.mockMethod("computeRebalanceAmount((uint256,uint256))", [toFixedPtAmt("-10")]); }); it("should transfer value to the vault (by minting and melding perps)", async function () { expect(await perp.totalSupply()).to.eq(toFixedPtAmt("800")); @@ -223,7 +223,7 @@ describe("RolloverVault", function () { describe("perp debasement with protocol fee", function () { beforeEach(async function () { await feePolicy.mockMethod("protocolSharePerc()", [toPercFixedPtAmt("0.01")]); - await feePolicy.mockMethod("computeRebalanceAmount((uint256,uint256,uint256))", [toFixedPtAmt("-10")]); + await feePolicy.mockMethod("computeRebalanceAmount((uint256,uint256))", [toFixedPtAmt("-10")]); }); it("should transfer value to the vault (by minting and melding perps)", async function () { expect(await perp.totalSupply()).to.eq(toFixedPtAmt("800")); @@ -262,7 +262,7 @@ describe("RolloverVault", function () { describe("perp enrichment", function () { let depositBond: Contract, depositTranches: Contract[]; beforeEach(async function () { - await feePolicy.mockMethod("computeRebalanceAmount((uint256,uint256,uint256))", [toFixedPtAmt("25")]); + await feePolicy.mockMethod("computeRebalanceAmount((uint256,uint256))", [toFixedPtAmt("25")]); await perp.updateState(); depositBond = await getDepositBond(perp); depositTranches = await getTranches(depositBond); @@ -310,7 +310,7 @@ describe("RolloverVault", function () { let depositBond: Contract, depositTranches: Contract[]; beforeEach(async function () { await feePolicy.mockMethod("protocolSharePerc()", [toPercFixedPtAmt("0.01")]); - await feePolicy.mockMethod("computeRebalanceAmount((uint256,uint256,uint256))", [toFixedPtAmt("25")]); + await feePolicy.mockMethod("computeRebalanceAmount((uint256,uint256))", [toFixedPtAmt("25")]); await perp.updateState(); depositBond = await getDepositBond(perp); depositTranches = await getTranches(depositBond); diff --git a/spot-contracts/test/rollover-vault/RolloverVault_recover.ts b/spot-contracts/test/rollover-vault/RolloverVault_recover.ts index 484f6753..8bb3d2a7 100644 --- a/spot-contracts/test/rollover-vault/RolloverVault_recover.ts +++ b/spot-contracts/test/rollover-vault/RolloverVault_recover.ts @@ -54,7 +54,7 @@ describe("RolloverVault", function () { feePolicy = new DMock(await ethers.getContractFactory("FeePolicy")); await feePolicy.deploy(); await feePolicy.mockMethod("decimals()", [8]); - await feePolicy.mockMethod("computeDeviationRatio((uint256,uint256,uint256))", [toPercFixedPtAmt("1")]); + await feePolicy.mockMethod("computeDeviationRatio((uint256,uint256))", [toPercFixedPtAmt("1")]); await feePolicy.mockMethod("computeFeePerc(uint256,uint256)", [0]); const PerpetualTranche = await ethers.getContractFactory("PerpetualTranche"); diff --git a/spot-contracts/test/rollover-vault/RolloverVault_swap.ts b/spot-contracts/test/rollover-vault/RolloverVault_swap.ts index de666072..647e268e 100644 --- a/spot-contracts/test/rollover-vault/RolloverVault_swap.ts +++ b/spot-contracts/test/rollover-vault/RolloverVault_swap.ts @@ -55,7 +55,7 @@ describe("RolloverVault", function () { feePolicy = new DMock(await ethers.getContractFactory("FeePolicy")); await feePolicy.deploy(); await feePolicy.mockMethod("decimals()", [8]); - await feePolicy.mockMethod("computeDeviationRatio((uint256,uint256,uint256))", [toPercFixedPtAmt("1")]); + await feePolicy.mockMethod("computeDeviationRatio((uint256,uint256))", [toPercFixedPtAmt("1")]); await feePolicy.mockMethod("computeFeePerc(uint256,uint256)", [0]); const PerpetualTranche = await ethers.getContractFactory("PerpetualTranche"); @@ -138,7 +138,6 @@ describe("RolloverVault", function () { expect(s[1]).to.eq(0); expect(s[2].perpTVL).to.eq(toFixedPtAmt("800")); expect(s[2].vaultTVL).to.eq(toFixedPtAmt("2000")); - expect(s[2].seniorTR).to.eq("200"); }); it("should update vault after swap", async function () { @@ -169,7 +168,6 @@ describe("RolloverVault", function () { expect(s[1]).to.eq(0); expect(s[2].perpTVL).to.eq(toFixedPtAmt("1600")); expect(s[2].vaultTVL).to.eq(toFixedPtAmt("2000")); - expect(s[2].seniorTR).to.eq("200"); }); it("should update vault after swap", async function () { @@ -199,7 +197,6 @@ describe("RolloverVault", function () { expect(s[1]).to.eq(0); expect(s[2].perpTVL).to.eq(toFixedPtAmt("400")); expect(s[2].vaultTVL).to.eq(toFixedPtAmt("120")); - expect(s[2].seniorTR).to.eq("200"); }); it("should update vault after swap", async function () { await checkVaultComposition( @@ -229,7 +226,6 @@ describe("RolloverVault", function () { expect(s[1]).to.eq(0); expect(s[2].perpTVL).to.eq(toFixedPtAmt("800")); expect(s[2].vaultTVL).to.eq(toFixedPtAmt("1780")); - expect(s[2].seniorTR).to.eq("200"); }); it("should update vault after swap", async function () { @@ -260,7 +256,6 @@ describe("RolloverVault", function () { expect(s[1]).to.eq(0); expect(s[2].perpTVL).to.eq(toFixedPtAmt("800")); expect(s[2].vaultTVL).to.eq(toFixedPtAmt("2220")); - expect(s[2].seniorTR).to.eq("200"); }); it("should update vault after swap", async function () { @@ -292,7 +287,6 @@ describe("RolloverVault", function () { expect(s[1]).to.eq(toFixedPtAmt("0")); expect(s[2].perpTVL).to.eq(toFixedPtAmt("800")); expect(s[2].vaultTVL).to.eq(toFixedPtAmt("2000")); - expect(s[2].seniorTR).to.eq("200"); }); }); @@ -317,7 +311,7 @@ describe("RolloverVault", function () { describe("when percentage of liquidity is too low", function () { beforeEach(async function () { - await vault.updateLiquidityLimits(toFixedPtAmt("2500"), toFixedPtAmt("0"), toPercFixedPtAmt("0.25")); + await vault.updateLiquidityLimits(toFixedPtAmt("2500"), toFixedPtAmt("0"), toPercFixedPtAmt("0.4")); }); it("should be reverted", async function () { await expect(vault.swapUnderlyingForPerps(toFixedPtAmt("100"))).to.be.revertedWithCustomError( @@ -609,7 +603,6 @@ describe("RolloverVault", function () { expect(s[1]).to.eq(0); expect(s[2].perpTVL).to.eq(toFixedPtAmt("800")); expect(s[2].vaultTVL).to.eq(toFixedPtAmt("2000")); - expect(s[2].seniorTR).to.eq("200"); }); }); @@ -623,7 +616,6 @@ describe("RolloverVault", function () { expect(s[1]).to.eq(0); expect(s[2].perpTVL).to.eq(toFixedPtAmt("1600")); expect(s[2].vaultTVL).to.eq(toFixedPtAmt("2000")); - expect(s[2].seniorTR).to.eq("200"); }); }); @@ -637,7 +629,6 @@ describe("RolloverVault", function () { expect(s[1]).to.eq(0); expect(s[2].perpTVL).to.eq(toFixedPtAmt("400")); expect(s[2].vaultTVL).to.eq(toFixedPtAmt("120")); - expect(s[2].seniorTR).to.eq("200"); }); }); }); @@ -653,7 +644,6 @@ describe("RolloverVault", function () { expect(s[1]).to.eq(toFixedPtAmt("0")); expect(s[2].perpTVL).to.eq(toFixedPtAmt("800")); expect(s[2].vaultTVL).to.eq(toFixedPtAmt("2000")); - expect(s[2].seniorTR).to.eq("200"); }); });