From 2fb282d0634b2d0d2d1d06568efe6e26b081eaf6 Mon Sep 17 00:00:00 2001 From: yruej301 <114962854+yruej301@users.noreply.github.com> Date: Thu, 20 Mar 2025 10:43:45 -0400 Subject: [PATCH 1/2] bump: v3.1.0 (#82) --- core/contracts/BaseEngine.sol | 6 +- core/contracts/Clearinghouse.sol | 186 +++++++++++++----- core/contracts/ClearinghouseLiq.sol | 5 +- core/contracts/Endpoint.sol | 147 +++++++------- core/contracts/OffchainExchange.sol | 12 +- core/contracts/SpotEngineState.sol | 5 +- core/contracts/Verifier.sol | 2 +- core/contracts/common/Constants.sol | 3 + core/contracts/interfaces/IEndpoint.sol | 36 +++- .../clearinghouse/IClearinghouse.sol | 24 ++- core/package.json | 2 +- lba/package.json | 2 +- 12 files changed, 288 insertions(+), 142 deletions(-) diff --git a/core/contracts/BaseEngine.sol b/core/contracts/BaseEngine.sol index e9fd2c6..c00a5a5 100644 --- a/core/contracts/BaseEngine.sol +++ b/core/contracts/BaseEngine.sol @@ -253,10 +253,8 @@ abstract contract BaseEngine is IProductEngine, EndpointGated { IOffchainExchange(IEndpoint(getEndpoint()).getOffchainExchange()); } - function updatePrice(uint32 productId, int128 priceX18) - external - onlyEndpoint - { + function updatePrice(uint32 productId, int128 priceX18) external { + require(msg.sender == address(_clearinghouse), ERR_UNAUTHORIZED); _risk().value[productId].priceX18 = priceX18; } diff --git a/core/contracts/Clearinghouse.sol b/core/contracts/Clearinghouse.sol index 93ff67e..5eb3430 100644 --- a/core/contracts/Clearinghouse.sol +++ b/core/contracts/Clearinghouse.sol @@ -24,29 +24,6 @@ interface IProxyManager { function getCodeHash(string memory name) external view returns (bytes32); } -enum YieldMode { - AUTOMATIC, - DISABLED, - CLAIMABLE -} - -enum GasMode { - VOID, - CLAIMABLE -} - -interface IBlastPoints { - function configurePointsOperator(address operator) external; -} - -interface IBlast { - function configure( - YieldMode _yield, - GasMode gasMode, - address governor - ) external; -} - contract Clearinghouse is EndpointGated, ClearinghouseStorage, IClearinghouse { using MathSD21x18 for int128; using ERC20Helper for IERC20Base; @@ -369,6 +346,72 @@ contract Clearinghouse is EndpointGated, ClearinghouseStorage, IClearinghouse { require(sumBase == 0, ERR_INVALID_HOLDER_LIST); } + function rebalanceXWithdraw(bytes calldata transaction, uint64 nSubmissions) + external + onlyEndpoint + { + IEndpoint.RebalanceXWithdraw memory txn = abi.decode( + transaction[1:], + (IEndpoint.RebalanceXWithdraw) + ); + + withdrawCollateral( + X_ACCOUNT, + txn.productId, + txn.amount, + txn.sendTo, + nSubmissions + ); + } + + function updateMinDepositRate(bytes calldata transaction) + external + onlyEndpoint + { + IEndpoint.UpdateMinDepositRate memory txn = abi.decode( + transaction[1:], + (IEndpoint.UpdateMinDepositRate) + ); + ISpotEngine spotEngine = ISpotEngine( + address(engineByType[IProductEngine.EngineType.SPOT]) + ); + spotEngine.updateMinDepositRate(txn.productId, txn.minDepositRateX18); + } + + function updateFeeRates(bytes calldata transaction) external onlyEndpoint { + IEndpoint.UpdateFeeRates memory txn = abi.decode( + transaction[1:], + (IEndpoint.UpdateFeeRates) + ); + address offchainExchange = IEndpoint(getEndpoint()) + .getOffchainExchange(); + IOffchainExchange(offchainExchange).updateFeeRates( + txn.user, + txn.productId, + txn.makerRateX18, + txn.takerRateX18 + ); + } + + function updatePrice(bytes calldata transaction) + external + onlyEndpoint + returns (uint32, int128) + { + IEndpoint.UpdatePrice memory txn = abi.decode( + transaction[1:], + (IEndpoint.UpdatePrice) + ); + require(txn.priceX18 > 0, ERR_INVALID_PRICE); + IProductEngine engine = productToEngine[txn.productId]; + if (address(engine) != address(0)) { + engine.updatePrice(txn.productId, txn.priceX18); + return (txn.productId, txn.priceX18); + } else { + return (0, 0); + } + } + function handleWithdrawTransfer( IERC20Base token, address to, @@ -389,7 +432,7 @@ contract Clearinghouse is EndpointGated, ClearinghouseStorage, IClearinghouse { uint128 amount, address sendTo, uint64 idx - ) external virtual onlyEndpoint { + ) public virtual onlyEndpoint { require(!RiskHelper.isIsolatedSubaccount(sender), ERR_UNAUTHORIZED); require(amount <= INT128_MAX, ERR_CONVERSION_OVERFLOW); ISpotEngine spotEngine = ISpotEngine( @@ -447,6 +490,70 @@ contract Clearinghouse is EndpointGated, ClearinghouseStorage, IClearinghouse { ); } + function mintVlp(IEndpoint.MintVlp calldata txn, int128 oraclePriceX18) + external + onlyEndpoint + { + require(!RiskHelper.isIsolatedSubaccount(txn.sender), ERR_UNAUTHORIZED); + ISpotEngine spotEngine = ISpotEngine( + address(engineByType[IProductEngine.EngineType.SPOT]) + ); + spotEngine.updatePrice(VLP_PRODUCT_ID, oraclePriceX18); + require(txn.quoteAmount <= INT128_MAX, ERR_CONVERSION_OVERFLOW); + + int128 quoteAmount = int128(txn.quoteAmount); + spotEngine.updateBalance(QUOTE_PRODUCT_ID, txn.sender, -quoteAmount); + spotEngine.updateBalance(QUOTE_PRODUCT_ID, V_ACCOUNT, quoteAmount); + + int128 vlpAmount = quoteAmount.div(oraclePriceX18); + spotEngine.updateBalance(VLP_PRODUCT_ID, txn.sender, vlpAmount); + spotEngine.updateBalance(VLP_PRODUCT_ID, V_ACCOUNT, -vlpAmount); + + require( + getHealth(txn.sender, IProductEngine.HealthType.INITIAL) >= 0, + ERR_SUBACCT_HEALTH + ); + } + + function burnVlp(IEndpoint.BurnVlp calldata txn, int128 oraclePriceX18) + external + onlyEndpoint + { + require(!RiskHelper.isIsolatedSubaccount(txn.sender), ERR_UNAUTHORIZED); + ISpotEngine spotEngine = ISpotEngine( + address(engineByType[IProductEngine.EngineType.SPOT]) + ); + spotEngine.updatePrice(VLP_PRODUCT_ID, oraclePriceX18); + require(txn.vlpAmount <= INT128_MAX, ERR_CONVERSION_OVERFLOW); + + int128 vlpAmount = int128(txn.vlpAmount); + spotEngine.updateBalance(VLP_PRODUCT_ID, txn.sender, -vlpAmount); + spotEngine.updateBalance(VLP_PRODUCT_ID, V_ACCOUNT, vlpAmount); + + int128 quoteAmount = vlpAmount.mul(oraclePriceX18); + spotEngine.updateBalance(QUOTE_PRODUCT_ID, txn.sender, quoteAmount); + spotEngine.updateBalance(QUOTE_PRODUCT_ID, V_ACCOUNT, -quoteAmount); + + require( + spotEngine.getBalance(VLP_PRODUCT_ID, txn.sender).amount >= 0, + ERR_SUBACCT_HEALTH + ); + } + + function rebalanceVlp(bytes calldata transaction) external onlyEndpoint { + IEndpoint.RebalanceVlp memory txn = abi.decode( + transaction[1:], + (IEndpoint.RebalanceVlp) + ); + ISpotEngine spotEngine = ISpotEngine( + address(engineByType[IProductEngine.EngineType.SPOT]) + ); + spotEngine.updateBalance(QUOTE_PRODUCT_ID, V_ACCOUNT, txn.quoteAmount); + spotEngine.updateBalance(QUOTE_PRODUCT_ID, X_ACCOUNT, -txn.quoteAmount); + spotEngine.updateBalance(VLP_PRODUCT_ID, V_ACCOUNT, txn.vlpAmount); + spotEngine.updateBalance(VLP_PRODUCT_ID, X_ACCOUNT, -txn.vlpAmount); + } + function burnLpAndTransfer(IEndpoint.BurnLpAndTransfer calldata txn) external virtual @@ -473,18 +580,14 @@ contract Clearinghouse is EndpointGated, ClearinghouseStorage, IClearinghouse { require(_isAboveInitial(txn.sender), ERR_SUBACCT_HEALTH); } - function claimSequencerFees( - IEndpoint.ClaimSequencerFees calldata txn, - int128[] calldata fees - ) external virtual onlyEndpoint { - require( - !RiskHelper.isIsolatedSubaccount(txn.subaccount), - ERR_UNAUTHORIZED - ); + function claimSequencerFees(int128[] calldata fees) + external + virtual + onlyEndpoint + { ISpotEngine spotEngine = ISpotEngine( address(engineByType[IProductEngine.EngineType.SPOT]) ); - IPerpEngine perpEngine = IPerpEngine( address(engineByType[IProductEngine.EngineType.PERP]) ); @@ -497,13 +600,11 @@ contract Clearinghouse is EndpointGated, ClearinghouseStorage, IClearinghouse { spotIds[i], FEES_ACCOUNT ); - spotEngine.updateBalance( spotIds[i], - txn.subaccount, + X_ACCOUNT, fees[i] + feeBalance.amount ); - spotEngine.updateBalance( spotIds[i], FEES_ACCOUNT, @@ -516,14 +617,12 @@ contract Clearinghouse is EndpointGated, ClearinghouseStorage, IClearinghouse { perpIds[i], FEES_ACCOUNT ); - perpEngine.updateBalance( perpIds[i], - txn.subaccount, + X_ACCOUNT, feeBalance.amount, feeBalance.vQuoteBalance ); - perpEngine.updateBalance( perpIds[i], FEES_ACCOUNT, @@ -617,15 +716,6 @@ contract Clearinghouse is EndpointGated, ClearinghouseStorage, IClearinghouse { return spreads; } - function configurePoints( - address blastPoints, - address blast, - address gov - ) external onlyOwner { - IBlastPoints(blastPoints).configurePointsOperator(gov); - IBlast(blast).configure(YieldMode.CLAIMABLE, GasMode.CLAIMABLE, gov); - } - function requireMinDeposit(uint32 productId, uint128 amount) external { require(amount <= INT128_MAX, ERR_CONVERSION_OVERFLOW); uint8 decimals = _decimals(productId); diff --git a/core/contracts/ClearinghouseLiq.sol b/core/contracts/ClearinghouseLiq.sol index e8abcb8..856e3e3 100644 --- a/core/contracts/ClearinghouseLiq.sol +++ b/core/contracts/ClearinghouseLiq.sol @@ -715,7 +715,10 @@ contract ClearinghouseLiq is require(!RiskHelper.isIsolatedSubaccount(txn.sender), ERR_UNAUTHORIZED); require(txn.sender != txn.liquidatee, ERR_UNAUTHORIZED); require(isUnderMaintenance(txn.liquidatee), ERR_NOT_LIQUIDATABLE); - require(txn.liquidatee != X_ACCOUNT, ERR_NOT_LIQUIDATABLE); + require( + txn.liquidatee != X_ACCOUNT && txn.liquidatee != V_ACCOUNT, + ERR_NOT_LIQUIDATABLE + ); require( txn.productId != QUOTE_PRODUCT_ID, ERR_INVALID_LIQUIDATION_PARAMS diff --git a/core/contracts/Endpoint.sol b/core/contracts/Endpoint.sol index 7bd89a3..a9cbcff 100644 --- a/core/contracts/Endpoint.sol +++ b/core/contracts/Endpoint.sol @@ -79,20 +79,15 @@ contract Endpoint is IEndpoint, EIP712Upgradeable, OwnableUpgradeable { "MintLp(bytes32 sender,uint32 productId,uint128 amountBase,uint128 quoteAmountLow,uint128 quoteAmountHigh,uint64 nonce)"; string internal constant BURN_LP_SIGNATURE = "BurnLp(bytes32 sender,uint32 productId,uint128 amount,uint64 nonce)"; + string internal constant MINT_VLP_SIGNATURE = + "MintVlp(bytes32 sender,uint128 quoteAmount,uint64 nonce)"; + string internal constant BURN_VLP_SIGNATURE = + "BurnVlp(bytes32 sender,uint128 vlpAmount,uint64 nonce)"; string internal constant LINK_SIGNER_SIGNATURE = "LinkSigner(bytes32 sender,bytes32 signer,uint64 nonce)"; IVerifier private verifier; - function _updatePrice(uint32 productId, int128 _priceX18) internal { - require(_priceX18 > 0, ERR_INVALID_PRICE); - address engine = clearinghouse.getEngineByProduct(productId); - if (engine != address(0)) { - priceX18[productId] = _priceX18; - IProductEngine(engine).updatePrice(productId, _priceX18); - } - } - function initialize( address _sanctions, address _sequencer, @@ -365,6 +360,10 @@ contract Endpoint is IEndpoint, EIP712Upgradeable, OwnableUpgradeable { require(sender == owner()); } else if (txType == TransactionType.DelistProduct) { require(sender == owner()); + } else if (txType == TransactionType.DumpFees) { + require(sender == owner()); + } else if (txType == TransactionType.RebalanceXWithdraw) { + require(sender == owner()); } else { chargeSlowModeFee(_getQuote(), sender); slowModeFees += SLOW_MODE_FEE; @@ -441,15 +440,7 @@ contract Endpoint is IEndpoint, EIP712Upgradeable, OwnableUpgradeable { ) public { require(msg.sender == address(this)); TransactionType txType = TransactionType(uint8(transaction[0])); - if (txType == TransactionType.LiquidateSubaccount) { - LiquidateSubaccount memory txn = abi.decode( - transaction[1:], - (LiquidateSubaccount) - ); - validateSender(txn.sender, sender); - requireSubaccount(txn.sender); - clearinghouse.liquidateSubaccount(txn); - } else if (txType == TransactionType.DepositCollateral) { + if (txType == TransactionType.DepositCollateral) { DepositCollateral memory txn = abi.decode( transaction[1:], (DepositCollateral) @@ -462,7 +453,6 @@ contract Endpoint is IEndpoint, EIP712Upgradeable, OwnableUpgradeable { transaction[1:], (WithdrawCollateral) ); - validateSender(txn.sender, sender); clearinghouse.withdrawCollateral( txn.sender, @@ -471,8 +461,6 @@ contract Endpoint is IEndpoint, EIP712Upgradeable, OwnableUpgradeable { address(0), nSubmissions ); - } else if (txType == TransactionType.SettlePnl) { - clearinghouse.settlePnl(transaction); } else if (txType == TransactionType.DepositInsurance) { clearinghouse.depositInsurance(transaction); } else if (txType == TransactionType.MintLp) { @@ -518,6 +506,18 @@ contract Endpoint is IEndpoint, EIP712Upgradeable, OwnableUpgradeable { clearinghouse.withdrawInsurance(transaction, nSubmissions); } else if (txType == TransactionType.DelistProduct) { clearinghouse.delistProduct(transaction); + } else if (txType == TransactionType.DumpFees) { + IOffchainExchange(offchainExchange).dumpFees(); + uint32[] memory spotIds = spotEngine.getProductIds(); + int128[] memory fees = new int128[](spotIds.length); + for (uint256 i = 0; i < spotIds.length; i++) { + fees[i] = sequencerFee[spotIds[i]]; + sequencerFee[spotIds[i]] = 0; + } + requireSubaccount(X_ACCOUNT); + clearinghouse.claimSequencerFees(fees); + } else if (txType == TransactionType.RebalanceXWithdraw) { + clearinghouse.rebalanceXWithdraw(transaction, nSubmissions); } else { revert(); } @@ -599,8 +599,12 @@ contract Endpoint is IEndpoint, EIP712Upgradeable, OwnableUpgradeable { t.perpTime = txn.time; times = t; } else if (txType == TransactionType.UpdatePrice) { - UpdatePrice memory txn = abi.decode(transaction[1:], (UpdatePrice)); - _updatePrice(txn.productId, txn.priceX18); + (uint32 productId, int128 newPriceX18) = clearinghouse.updatePrice( + transaction + ); + if (productId != 0) { + priceX18[productId] = newPriceX18; + } } else if (txType == TransactionType.SettlePnl) { clearinghouse.settlePnl(transaction); } else if ( @@ -678,21 +682,52 @@ contract Endpoint is IEndpoint, EIP712Upgradeable, OwnableUpgradeable { ); chargeFee(signedTx.tx.sender, HEALTHCHECK_FEE); clearinghouse.burnLp(signedTx.tx); - } else if (txType == TransactionType.DumpFees) { - IOffchainExchange(offchainExchange).dumpFees(); - } else if (txType == TransactionType.ClaimSequencerFees) { - ClaimSequencerFees memory txn = abi.decode( + } else if (txType == TransactionType.MintVlp) { + SignedMintVlp memory signedTx = abi.decode( transaction[1:], - (ClaimSequencerFees) + (SignedMintVlp) ); - uint32[] memory spotIds = spotEngine.getProductIds(); - int128[] memory fees = new int128[](spotIds.length); - for (uint256 i = 0; i < spotIds.length; i++) { - fees[i] = sequencerFee[spotIds[i]]; - sequencerFee[spotIds[i]] = 0; - } - requireSubaccount(txn.subaccount); - clearinghouse.claimSequencerFees(txn, fees); + validateNonce(signedTx.tx.sender, signedTx.tx.nonce); + validateSignature( + signedTx.tx.sender, + _hashTypedDataV4( + keccak256( + abi.encode( + keccak256(bytes(MINT_VLP_SIGNATURE)), + signedTx.tx.sender, + signedTx.tx.quoteAmount, + signedTx.tx.nonce + ) + ) + ), + signedTx.signature + ); + chargeFee(signedTx.tx.sender, HEALTHCHECK_FEE); + priceX18[VLP_PRODUCT_ID] = signedTx.oraclePriceX18; + clearinghouse.mintVlp(signedTx.tx, signedTx.oraclePriceX18); + } else if (txType == TransactionType.BurnVlp) { + SignedBurnVlp memory signedTx = abi.decode( + transaction[1:], + (SignedBurnVlp) + ); + validateNonce(signedTx.tx.sender, signedTx.tx.nonce); + validateSignature( + signedTx.tx.sender, + _hashTypedDataV4( + keccak256( + abi.encode( + keccak256(bytes(BURN_VLP_SIGNATURE)), + signedTx.tx.sender, + signedTx.tx.vlpAmount, + signedTx.tx.nonce + ) + ) + ), + signedTx.signature + ); + chargeFee(signedTx.tx.sender, HEALTHCHECK_FEE); + priceX18[VLP_PRODUCT_ID] = signedTx.oraclePriceX18; + clearinghouse.burnVlp(signedTx.tx, signedTx.oraclePriceX18); } else if (txType == TransactionType.ManualAssert) { clearinghouse.manualAssert(transaction); } else if (txType == TransactionType.LinkSigner) { @@ -719,16 +754,7 @@ contract Endpoint is IEndpoint, EIP712Upgradeable, OwnableUpgradeable { uint160(bytes20(signedTx.tx.signer)) ); } else if (txType == TransactionType.UpdateFeeRates) { - UpdateFeeRates memory txn = abi.decode( - transaction[1:], - (UpdateFeeRates) - ); - IOffchainExchange(offchainExchange).updateFeeRates( - txn.user, - txn.productId, - txn.makerRateX18, - txn.takerRateX18 - ); + clearinghouse.updateFeeRates(transaction); } else if (txType == TransactionType.TransferQuote) { SignedTransferQuote memory signedTx = abi.decode( transaction[1:], @@ -753,29 +779,8 @@ contract Endpoint is IEndpoint, EIP712Upgradeable, OwnableUpgradeable { validateNonce(signedTx.tx.sender, signedTx.tx.nonce); chargeFee(signedTx.tx.sender, HEALTHCHECK_FEE); clearinghouse.transferQuote(signedTx.tx); - } else if (txType == TransactionType.RebalanceXWithdraw) { - RebalanceXWithdraw memory txn = abi.decode( - transaction[1:], - (RebalanceXWithdraw) - ); - - clearinghouse.withdrawCollateral( - X_ACCOUNT, - txn.productId, - txn.amount, - txn.sendTo, - nSubmissions - ); } else if (txType == TransactionType.UpdateMinDepositRate) { - UpdateMinDepositRate memory txn = abi.decode( - transaction[1:], - (UpdateMinDepositRate) - ); - - spotEngine.updateMinDepositRate( - txn.productId, - txn.minDepositRateX18 - ); + clearinghouse.updateMinDepositRate(transaction); } else if (txType == TransactionType.AssertCode) { clearinghouse.assertCode(transaction); } else if (txType == TransactionType.CreateIsolatedSubaccount) { @@ -789,6 +794,8 @@ contract Endpoint is IEndpoint, EIP712Upgradeable, OwnableUpgradeable { getLinkedSigner(txn.order.sender) ); _recordSubaccount(newIsolatedSubaccount); + } else if (txType == TransactionType.RebalanceVlp) { + clearinghouse.rebalanceVlp(transaction); } else { revert(); } @@ -891,8 +898,4 @@ contract Endpoint is IEndpoint, EIP712Upgradeable, OwnableUpgradeable { function getNonce(address sender) external view returns (uint64) { return nonces[sender]; } - - function updateSanctions(address _sanctions) external onlyOwner { - sanctions = ISanctionsList(_sanctions); - } } diff --git a/core/contracts/OffchainExchange.sol b/core/contracts/OffchainExchange.sol index 2a64419..847d541 100644 --- a/core/contracts/OffchainExchange.sol +++ b/core/contracts/OffchainExchange.sol @@ -888,16 +888,13 @@ contract OffchainExchange is for (uint32 i = 1; i < productIds.length; i++) { uint32 productId = productIds[i]; MarketInfoStore memory market = marketInfo[productId]; - - // its possible for fees to be <= 0 if there is a cross-chain trade - // and the maker rebate is exclusively coming from one chain - if (market.collectedFees <= 0) { + if (market.collectedFees == 0) { continue; } spotEngine.updateBalance( quoteIds[productId], - FEES_ACCOUNT, + X_ACCOUNT, market.collectedFees ); @@ -916,7 +913,7 @@ contract OffchainExchange is perpEngine.updateBalance( productId, - FEES_ACCOUNT, + X_ACCOUNT, 0, market.collectedFees ); @@ -979,7 +976,8 @@ contract OffchainExchange is uint32 productId, int64 makerRateX18, int64 takerRateX18 - ) external onlyEndpoint { + ) external { + require(msg.sender == address(clearinghouse), ERR_UNAUTHORIZED); if (!addressTouched[user]) { addressTouched[user] = true; customFeeAddresses.push(user); diff --git a/core/contracts/SpotEngineState.sol b/core/contracts/SpotEngineState.sol index f34bc8f..bc1846d 100644 --- a/core/contracts/SpotEngineState.sol +++ b/core/contracts/SpotEngineState.sol @@ -397,6 +397,9 @@ abstract contract SpotEngineState is ISpotEngine, BaseEngine { require(dt < 7 * SECONDS_PER_DAY, ERR_INVALID_TIME); for (uint32 i = 0; i < productIds.length; i++) { uint32 productId = productIds[i]; + if (productId == VLP_PRODUCT_ID) { + continue; + } State memory state = states[productId]; if (productId == QUOTE_PRODUCT_ID) { quoteState = state; @@ -416,8 +419,8 @@ abstract contract SpotEngineState is ISpotEngine, BaseEngine { function updateMinDepositRate(uint32 productId, int128 minDepositRateX18) external - onlyEndpoint { + require(msg.sender == address(_clearinghouse), ERR_UNAUTHORIZED); // deposit rate can't be larger than 100% so that when the rate is incorrectly // set, we still can rescue it without having too much damage. require( diff --git a/core/contracts/Verifier.sol b/core/contracts/Verifier.sol index a960457..8746f0d 100644 --- a/core/contracts/Verifier.sol +++ b/core/contracts/Verifier.sol @@ -238,7 +238,7 @@ contract Verifier is EIP712Upgradeable, OwnableUpgradeable, IVerifier { bytes calldata txn, uint64 idx, bytes[] calldata signatures - ) public { + ) public view { bytes32 data = keccak256( abi.encodePacked(uint256(block.chainid), uint256(idx), txn) ); diff --git a/core/contracts/common/Constants.sol b/core/contracts/common/Constants.sol index e6add20..6a3042c 100644 --- a/core/contracts/common/Constants.sol +++ b/core/contracts/common/Constants.sol @@ -7,6 +7,7 @@ uint32 constant QUOTE_PRODUCT_ID = 0; /// @dev Fees account bytes32 constant FEES_ACCOUNT = bytes32(0); bytes32 constant X_ACCOUNT = 0x0000000000000000000000000000000000000000000000000000000000000001; +bytes32 constant V_ACCOUNT = 0x0000000000000000000000000000000000000000000000000000000000000002; string constant DEFAULT_REFERRAL_CODE = "-1"; @@ -38,3 +39,5 @@ int128 constant INTEREST_FEE_FRACTION = 200_000_000_000_000_000; // 20% int256 constant MIN_DEPOSIT_AMOUNT = 5 * ONE; uint32 constant MAX_ISOLATED_SUBACCOUNTS_PER_ADDRESS = 10; + +uint32 constant VLP_PRODUCT_ID = 153; diff --git a/core/contracts/interfaces/IEndpoint.sol b/core/contracts/interfaces/IEndpoint.sol index 871babf..df9dbc4 100644 --- a/core/contracts/interfaces/IEndpoint.sol +++ b/core/contracts/interfaces/IEndpoint.sol @@ -22,7 +22,7 @@ interface IEndpoint { SwapAMM, MatchOrderAMM, DumpFees, - ClaimSequencerFees, + ClaimSequencerFees, // deprecated PerpTick, ManualAssert, Rebate, // deprecated @@ -37,7 +37,10 @@ interface IEndpoint { AssertCode, WithdrawInsurance, CreateIsolatedSubaccount, - DelistProduct + DelistProduct, + MintVlp, + BurnVlp, + RebalanceVlp } struct UpdateProduct { @@ -129,6 +132,35 @@ interface IEndpoint { bytes signature; } + struct MintVlp { + bytes32 sender; + uint128 quoteAmount; + uint64 nonce; + } + + struct SignedMintVlp { + MintVlp tx; + bytes signature; + int128 oraclePriceX18; + } + + struct BurnVlp { + bytes32 sender; + uint128 vlpAmount; + uint64 nonce; + } + + struct SignedBurnVlp { + BurnVlp tx; + bytes signature; + int128 oraclePriceX18; + } + + struct RebalanceVlp { + int128 quoteAmount; + int128 vlpAmount; + } + struct LinkSigner { bytes32 sender; bytes32 signer; diff --git a/core/contracts/interfaces/clearinghouse/IClearinghouse.sol b/core/contracts/interfaces/clearinghouse/IClearinghouse.sol index 07b7874..979cb3c 100644 --- a/core/contracts/interfaces/clearinghouse/IClearinghouse.sol +++ b/core/contracts/interfaces/clearinghouse/IClearinghouse.sol @@ -33,6 +33,12 @@ interface IClearinghouse is IClearinghouseEventEmitter, IEndpointGated { function burnLp(IEndpoint.BurnLp calldata tx) external; + function mintVlp(IEndpoint.MintVlp calldata txn, int128 oraclePriceX18) + external; + + function burnVlp(IEndpoint.BurnVlp calldata txn, int128 oraclePriceX18) + external; + function liquidateSubaccount(IEndpoint.LiquidateSubaccount calldata tx) external; @@ -44,10 +50,20 @@ interface IClearinghouse is IClearinghouseEventEmitter, IEndpointGated { function settlePnl(bytes calldata transaction) external; - function claimSequencerFees( - IEndpoint.ClaimSequencerFees calldata tx, - int128[] calldata fees - ) external; + function rebalanceXWithdraw(bytes calldata transaction, uint64 nSubmissions) + external; + + function updateMinDepositRate(bytes calldata transaction) external; + + function updateFeeRates(bytes calldata transaction) external; + + function updatePrice(bytes calldata transaction) + external + returns (uint32, int128); + + function rebalanceVlp(bytes calldata transaction) external; + + function claimSequencerFees(int128[] calldata fees) external; /// @notice Retrieve quote ERC20 address function getQuote() external view returns (address); diff --git a/core/package.json b/core/package.json index a0c0c66..374d640 100644 --- a/core/package.json +++ b/core/package.json @@ -1,6 +1,6 @@ { "name": "vertex-core", - "version": "3.0.1", + "version": "3.1.0", "license": "UNLICENSED", "description": "EVM implementation of Vertex", "scripts": { diff --git a/lba/package.json b/lba/package.json index 238877b..04868fa 100644 --- a/lba/package.json +++ b/lba/package.json @@ -1,6 +1,6 @@ { "name": "vertex-lba", - "version": "3.0.1", + "version": "3.1.0", "license": "UNLICENSED", "description": "Vertex LBA contracts", "scripts": { From bcd3bf81b3f90e49c43d4db794c48a989df49e4f Mon Sep 17 00:00:00 2001 From: yruej301 <114962854+yruej301@users.noreply.github.com> Date: Thu, 20 Mar 2025 10:47:37 -0400 Subject: [PATCH 2/2] chore: readme (#84) --- README.md | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..602188a --- /dev/null +++ b/README.md @@ -0,0 +1,49 @@ +# Vertex Protocol + +This repository contains the smart contract implementations for the Vertex Protocol ecosystem. + +## Project Structure + +The repository is organized into two main projects: + +- **[vertex-contracts/core](./vertex-contracts/core)**: EVM implementation of Vertex core functionality +- **[vertex-contracts/lba](./vertex-contracts/lba)**: Vertex LBA (Liquidity Bootstrap Auction) contracts + +## Requirements + +- Node.js >=16 +- [Yarn](https://yarnpkg.com/) + +## Getting Started + +Each project has its own setup and development commands. Navigate to the respective directories for project-specific instructions: + +``` +# For Vertex EVM Core Contracts +cd vertex-contracts/core +yarn install +yarn compile + +# For Vertex LBA Contracts +cd vertex-contracts/lba +yarn install +# Follow the .env setup instructions +``` + +## Available Commands + +### Core Contracts + +- `yarn compile`: Compile Vertex EVM contracts +- See project-specific README for more details + +### LBA Contracts + +- `yarn lint`: Run prettier & SolHint +- `yarn contracts:force-compile`: Compile contracts and generate TS bindings + ABIs +- `yarn run-local-node`: Run a persistent local Hardhat node for testing +- See project-specific README for more details + +## Further Documentation + +For more detailed information about each project, please refer to their respective README files. \ No newline at end of file