GMX 合成物合約。
本節提供系統如何運作的總體概述。
有關技術概述,請參閱下面的部分。
市場支援現貨和永續交易,它們是透過指定多頭抵押品代幣、空頭抵押品代幣和指數代幣來創建的。
範例:
流動性提供者可以存入多頭或空頭抵押代幣或兩者都存入以鑄造流動性代幣。
多頭抵押品代幣用於支援多頭頭寸,而空頭抵押品代幣則用於支援空頭頭寸。
流動性提供者承擔其提供流動性的市場的交易者的利潤和損失。
擁有獨立的市場可以實現風險隔離,流動性提供者只暴露於他們存入資金的市場,這可能允許無需許可的上市。
交易者可以使用多頭或空頭代幣作為市場的抵押品。
這些合約支援以下主要功能:
為了避免搶先交易問題,大多數操作需要執行兩個步驟:
價格由鏈下預言機系統提供,該系統根據查詢價格的時間不斷對價格進行簽名。
最低價格和最高價格都已簽署,這樣就可以包含有關買賣價差的資訊。
Oracle 合約中儲存的價格代表一單位代幣的價格,使用精確到 30 位元小數的值。
以這種方式表示價格可以簡化代幣金額和法幣價值之間的轉換,例如,要計算給定數量代幣的法幣價值,計算結果如下:代幣金額* 預言機價格,計算某個代幣的代幣金額法定價值將是:法定價值/預言機價格。
資金費用和價格影響保持多頭/空頭平衡,同時降低價格操縱的風險。
系統中有一些守護者和節點:
合約主要有以下幾種類型:
合約分為這些類型,以允許逐步升級。
大多數的資料是使用 DataStore 合約儲存。
*storeUtils 合約使用 DataStore 儲存結構數據,這允許將新金鑰新增至結構。
EnumberableSets 用於允許介面或守護者輕鬆查詢訂單列表和位置列表,這在索引器上使用,因為索引器同步最新區塊可能會有延遲。將清單直接儲存在合約中還有助於確保在需要時可以檢索和驗證準確的資料。
*eventUtils 合約使用事件發射器發出事件,這些事件被泛化為允許將新的鍵值新增至事件中,而不需要更新 ABI。
GMX Liquidity Vault 的縮寫:具有相同多頭和空頭代幣的多個市場的包裝。根據市場利用率,基礎市場之間的流動性自動重新平衡。
本節提供合約的技術描述。
市場是使用MarketFactory.createMarket
創建的,這會建立一個 MarketToken 並將 Market.Props 結構儲存在 MarketStore 中。
MarketToken 用於追蹤流動性提供者在市場池中的份額並儲存每個市場的代幣。
在任何時間點,MarketToken 的價格都是(worth of market pool) / MarketToken.totalSupply()
,可以使用函數MarketUtils.getMarketTokenPrice
來檢索該值。
市場池的價值是
存款將多頭/空頭代幣添加到市場池中,並向存款人鑄造 MarketTokens。
存款請求是透過呼叫 ExchangeRouter.createDeposit 建立的,並指定:
存款請求使用 DepositHandler.executeDeposit 執行,如果存款是在時間戳n
處建立的,則應使用時間戳n
後的預言機價格執行。
在費用和價格影響之前,要鑄造的 MarketToken 數量的計算方式為(worth of tokens deposited) / (worth of market pool) * MarketToken.totalSupply()
。
提款會燃燒 MarketTokens,以換取市場池中的多頭/空頭代幣。
提款請求是透過呼叫 ExchangeRouter.createWithdrawal 建立的,並指定:
提款請求使用 WithdrawalHandler.executeWithdrawal 執行,如果提款是在時間戳n
處創建的,則應使用時間戳n
後的預言機價格執行。
在費用和價格影響之前,要贖回的多頭或空頭代幣數量的計算方式為(worth of market tokens) / (long / short token price)
。
市場的多頭和空頭代幣可以互相互換。
例如,如果 ETH/USD 市場有 WETH 作為多頭,USDC 作為空頭,則可以將 WETH 發送到市場兌換 USDC,將 USDC 發送到市場兌換 WETH。
掉期訂單請求是透過呼叫 ExchangeRouter.createOrder 建立的,並指定:
在費用和價格影響之前的交換輸出金額, (amount of tokens in) * (token in price) / (token out price)
。
市場掉期訂單請求使用 OrderHandler.executeOrder 執行,如果訂單是在時間戳n
處建立的,則應使用時間戳n
後的預言機價格執行。
當輸出金額與使用者指定的最小輸出金額相符時應執行的被動掉期訂單。
限價掉期訂單請求使用 OrderHandler.executeOrder 執行,如果訂單是在時間戳n
創建的,則應在時間戳n
之後使用預言機價格執行。
開立或增加多頭/空頭永續部位。
市價增加訂單請求是透過呼叫 ExchangeRouter.createOrder 建立的,並指定:
市價上漲訂單請求使用 OrderHandler.executeOrder 執行,如果訂單在時間戳n
處創建,則應使用時間戳n
後的預言機價格執行。
當指數代幣價格與用戶指定的可接受價格相符時應執行的被動增倉訂單。
多倉範例:如果當前指數代幣價格為$5000,可以建立限價上漲訂單,可接受價格為$4990,當指數代幣價格<=$4990時可以執行該訂單。
空倉範例:如果目前指數代幣價格為$5000,可以建立限價上漲訂單,可接受價格為$5010,當指數代幣價格>=$5010時可以執行該訂單。
限價增加訂單請求使用 OrderHandler.executeOrder 執行,如果訂單在時間戳n
處創建,則應使用時間戳n
後的預言機價格執行。
平倉或減少多頭/空頭永久部位。
市場減價訂單請求是透過呼叫 ExchangeRouter.createOrder 建立的,並指定:
市價減價訂單請求使用 OrderHandler.executeOrder 執行,如果訂單在時間戳n
處創建,則應使用時間戳n
後的預言機價格執行。
當指數代幣價格符合用戶指定的可接受價格時應執行的被動減倉訂單。
多倉範例:如果目前指數代幣價格為$5000,可以建立限價跌價訂單,可接受價格為$5010,當指數代幣價格>=$5010時,訂單可以執行。
空倉範例:如果目前指數代幣價格為$5000,可以建立限價跌價訂單,可接受價格為$4990,當指數代幣價格<=$4990時可以執行該訂單。
限價減少訂單請求使用 OrderHandler.executeOrder 執行,如果訂單在時間戳n
處創建,則應使用時間戳n
後的預言機價格執行。
當指數代幣價格超過用戶指定的可接受價格時應執行的被動減倉訂單。
多倉範例:如果當前指數代幣價格為 5000 美元,可以建立停損減量訂單,可接受價格為 4990 美元,當指數代幣價格 <= 4990 美元時可以執行該訂單。
空倉範例:如果目前指數代幣價格為$5000,可以建立停損減量訂單,可接受價格為$5010,當指數代幣價格>=$5010時可以執行該訂單。
止損減單請求使用 OrderHandler.executeOrder 執行,如果訂單是在時間戳n
處建立的,則應使用時間戳n
後的預言機價格執行。
ETH的價格是5000,ETH有18位小數。
一單位 ETH 的價格為5000 / (10 ^ 18), 5 * (10 ^ -15)
。
要處理小數,請將數值乘以(10 ^ 30)
。
價格將儲存為5000 / (10 ^ 18) * (10 ^ 30) => 5000 * (10 ^ 12)
。
對於 Gas 最佳化,這些價格以 uint8 十進制乘數值和 uint32 價格值的形式傳送到預言機。
如果十進位乘數值設定為 8,則 uint32 值將為5000 * (10 ^ 12) / (10 ^ 8) => 5000 * (10 ^ 4)
。
使用此配置,ETH 價格的最大值可為(2 ^ 32) / (10 ^ 4) => 4,294,967,296 / (10 ^ 4) => 429,496.7296
精確度為 4 位元小數。
BTC的價格是60000,BTC有8位小數。
一單位BTC的價格為60,000 / (10 ^ 8), 6 * (10 ^ -4)
。
價格將儲存為60,000 / (10 ^ 8) * (10 ^ 30) => 6 * (10 ^ 26) => 60,000 * (10 ^ 22)
。
BTC價格最大值: (2 ^ 64) / (10 ^ 2) => 4,294,967,296 / (10 ^ 2) => 42,949,672.96
。
精度小數:2。
USDC的價格為1,USDC有6位小數。
一單位 USDC 的價格為1 / (10 ^ 6), 1 * (10 ^ -6)
。
價格將儲存為1 / (10 ^ 6) * (10 ^ 30) => 1 * (10 ^ 24)
。
USDC 價格最大值: (2 ^ 64) / (10 ^ 6) => 4,294,967,296 / (10 ^ 6) => 4294.967296
。
精度小數:6。
DG的價格為0.00000001,DG有18位小數。
一單位DG的價格為0.00000001 / (10 ^ 18), 1 * (10 ^ -26)
。
價格將儲存為1 * (10 ^ -26) * (10 ^ 30) => 1 * (10 ^ 3)
。
DG價格最大: (2 ^ 64) / (10 ^ 11) => 4,294,967,296 / (10 ^ 11) => 0.04294967296
。
精度小數:11。
計算小數乘數應設定為多少的公式:
小數:30 - (令牌小數) - (精確度所需的小數位數)
WNT 的計算範例:
dataStreamPrice / (10 ^ 8) / (10 ^ 18) * (10 ^ 30)
(5000 * (10 ^ 8)) / (10 ^ 8) / (10 ^ 18) * (10 ^ 30) = 5000 * (10 ^ 12)
dataStreamPrice * multiplier / (10 ^ 30)
(5000 * (10 ^ 8)) * (10 ^ 34) / (10 ^ 30) = 5000 * (10 ^ 12)
WBTC 計算範例:
dataStreamPrice / (10 ^ 8) / (10 ^ 8) * (10 ^ 30)
(50,000 * (10 ^ 8)) / (10 ^ 8) / (10 ^ 8) * (10 ^ 30) = 50,000 * (10 ^ 22)
dataStreamPrice * multiplier / (10 ^ 30)
(50,000 * (10 ^ 8)) * (10 ^ 44) / (10 ^ 30) = 50,000 * (10 ^ 22)
乘數的公式為: 10 ^ (60 - dataStreamDecimals - tokenDecimals)
資金費用激勵多頭和空頭部位的平衡,持倉量較大的一方向持倉量較小的一方支付資金費用。
較大一方的資金費用計算公式為(funding factor per second) * (open interest imbalance) ^ (funding exponent factor) / (total open interest)
。
例如,如果每秒的融資因子為 1 / 50,000,融資指數因子為 1,多頭持倉量為 150,000 美元,空頭持倉量為 50,000 美元,則多頭每秒的融資費用將為(1 / 50,000) * 100,000 / 200,000 => 0.00001 => 0.001%
。
空頭每秒的資金費用為-0.00001 * 150,000 / 50,000 => 0.00003 => -0.003%
。
還可以設定fundingIncreaseFactorPerSecond值,這將導致以下資金邏輯:
longShortImbalance
的計算方式為[abs(longOpenInterest - shortOpenInterest) / totalOpenInterest] ^ fundingExponentFactor
longShortImbalance
大於thresholdForStableFunding
,則資金費率將增加longShortImbalance * fundingIncreaseFactorPerSecond
longShortImbalance
大於thresholdForDecreaseFunding
且小於thresholdForStableFunding
且偏斜與資金方向相同,則資金費率不會改變longShortImbalance
小於thresholdForDecreaseFunding
且偏差與資金方向相同,則資金費率將減少fundingDecreaseFactorPerSecond
由於 longShortImbalance > ThresholdForStableFunding,savedFundingFactorPerSecond 應增加0.0001% * 6% * 600 = 0.0036%
由於多頭已經在支付空頭費用,因此偏差是相同的,並且 longShortImbalance < ThresholdForStableFunding、savedFundingFactorPerSecond 不應改變
由於 longShortImbalance < ThresholdForDecreaseFunding,savedFundingFactorPerSecond 應減少0.000002% * 600 = 0.0012%
由於偏差是在另一個方向,savedFundingFactorPerSecond 應減少0.0001% * 1% * 600 = 0.0006%
請注意,有多種可能的方式來博弈資金費用,應調整資金因素以盡量減少這種可能性:
如果longOpenInterest>shortOpenInterest且longShortImbalance在thresholdForStableFunding之內,則持有空頭頭寸的用戶可以開立多頭頭寸以增加longShortImbalance並試圖導致資金費用增加。在活躍的市場中,很難預測何時會有其他人開設相反的空頭頭寸以賺取增加的資金費用,這將使這種博弈變得困難,也可以調整資金因素以幫助最大限度地減少這種博弈的收益。
如果longOpenInterest>shortOpenInterest且longShortImbalance>thresholdForStableFunding,持有多頭頭寸的交易者可以在這段時間內進行多次小額交易,以確保資金因子不斷更新,而不是在整個持續時間內使用較大的值,這應最大限度地減少多頭頭寸的融資費用,但不應將融資費用降低至低於預期費率。
向流動性提供者支付借款費用,這有助於防止用戶在不支付任何費用的情況下開設多頭和空頭部位以佔用資金池容量。
借款費用可以使用曲線模型或扭結模型。
要使用曲線模型,要配置的鍵是BORROWING_FACTOR
和BORROWING_EXPONENT_FACTOR
,每秒的借用因子將計算為:
// reservedUsd is the total USD value reserved for positions
reservedUsd = MarketUtils.getReservedUsd(...)
// poolUsd is the USD value of the pool excluding pending trader PnL
poolUsd = MarketUtils.getPoolUsdWithoutPnl(...)
// reservedUsdAfterExponent is the reservedUsd after applying the borrowingExponentFactor for the market
reservedUsdAfterExponent = applyExponentFactor(reservedUsd, borrowingExponentFactor)
borrowingFactorPerSecond = borrowingFactor * reservedUsdAfterExponent / poolUsd
要使用扭結模型,要配置的鍵是OPTIMAL_USAGE_FACTOR
、 BASE_BORROWING_FACTOR
和ABOVE_OPTIMAL_USAGE_BORROWING_FACTOR
,每秒的借用因子將計算為:
// usageFactor is the ratio of value reserved for positions to available value that can be reserved
usageFactor = MarketUtils.getUsageFactor(...)
borrowingFactorPerSecond = baseBorrowingFactor * usageFactor
if (usageFactor > optimalUsageFactor) {
diff = usageFactor - optimalUsageFactor
additionalBorrowingFactorPerSecond = aboveOptimalUsageBorrowingFactor - baseBorrowingFactor
borrowingFactorPerSecond += additionalBorrowingFactorPerSecond * diff / (Precision.FLOAT_PRECISION - optimalUsageFactor)
}
還有一個選項可以設定 SkipBorrowingFeeForSmallerSide 標誌,這將導致較小一側的借貸費用設為零。例如,如果多頭多於空頭,且skipBorrowingFeeForSmallerSide為true,則空頭的借入費用將為零。
價格影響的代碼可以在/pricing
合約中找到。
價格影響計算如下:
(initial USD difference) ^ (price impact exponent) * (price impact factor) - (next USD difference) ^ (price impact exponent) * (price impact factor)
對於掉期,不平衡度計算為多頭代幣和空頭代幣的價值差異。
例如:
price impact exponent
設定為 2, price impact factor
設定為0.01 / 50,000
0 ^ 2 * (0.01 / 50,000) - 50,000 ^ 2 * (0.01 / 50,000) => -$500
50,000 ^ 2 * (0.01 / 50,000) - 25,000 ^ 2 * (0.01 / 50,000) => $375
對於部位操作(增加/減少部位),不平衡計算為多頭和空頭未平倉合約的差額。
price impact exponents
和price impact factors
是根據市場配置的,並且對於現貨和頭寸操作可能有所不同。
請注意,此計算是對用戶交易的價格影響,而不是對池的價格影響。例如,用戶的交易可能會產生 0.25% 的價格影響,下一筆非常小的交易可能會產生 0.5% 的價格影響。
價格影響的目的是:
由於合約使用預言機價格,該價格將是多個參考交易所的平均或中位數價格。在沒有價格影響的情況下,在執行合約訂單時操縱參考交易所的價格可能會有利可圖。
如果正面和負面價格影響值相似,也會存在這種風險,因此在波動或不規則價格變動時,正面價格影響應設定為較低值。
對於倉位增加/減少的價格影響,如果從部位扣除抵押品的負面價格影響,這可能會導致倉位的槓桿率與使用者預期的不同,因此倉位的進場/出場價格不是扣除抵押品,而是根據價格影響進行調整。
例如:
如果指數代幣與市場的多頭和空頭代幣都不同,那麼如果頭寸影響池非常大且指數代幣價格較大,則池子價值可能會受到頭寸影響池的顯著影響增加。如果這成為一個問題,可以添加逐漸減少部位影響池大小的選項。
還使用頭寸和掉期的虛擬庫存價值來追蹤價格影響,這追蹤了類似市場(例如 ETH/USDC、ETH/USDT)之間代幣的不平衡。
如果價格大幅波動,一側可能會出現大量頭寸減倉或平倉,導致多頭和空頭持倉量嚴重失衡,這可能會導致非常高的價格影響值。為了緩解這種情況,可以配置最大位置影響因子值。如果當前價格影響超過最大負價格影響,則扣除最大負價格影響之外的任何超額抵押品將保留在合約內,如果沒有偵測到價格操縱,則該抵押品可以釋放給使用者。當負面價格影響受到限制時,開倉並立即平倉可能會有利可圖,因為正面價格影響現在可能超過受限制的負面價格影響。為了避免這種情況,最大正價格影響應配置為低於最大負價格影響。
每個市場都有可配置的掉期費用和部位費用。
執行費用也會在建立存款、提款、訂單請求時進行估算和核算,以便管理員能夠以接近零成本的方式執行交易。
如果市場以穩定幣作為空頭抵押代幣,且最大空頭持倉量不超過池中穩定幣的數量,則該市場應該能夠全額支付空頭利潤。
如果市場存在與指數代幣不同的多頭抵押代幣,如果指數代幣的價格漲幅超過多頭抵押品代幣的價格漲幅,則多頭利潤可能無法完全支付。
市場有一個準備金係數,允許未平倉頭寸限制在資金池規模的一定百分比,這減少了空頭頭寸利潤的影響,並降低了多頭頭寸無法完全支付的風險。
市場代幣的價格取決於池中資產的價值以及交易者未平倉部位的淨未決盈虧。
待處理的盈虧可能會受到限制,用於計算市場代幣價格的因素可能會因活動而異:
Keys.MAX_PNL_FACTOR_FOR_DEPOSITS:這是計算存款的市場代幣價格時的 PnL 因子上限
Keys.MAX_PNL_FACTOR_FOR_WITHDRAWALS:這是計算提款市場代幣價格時的 PnL 因子上限
Keys.MAX_PNL_FACTOR_FOR_TRADERS:這是計算平倉的市場代幣價格時的 PnL 因子上限
這些不同的因素可以配置為幫助流動性提供者管理風險並在需要時激勵存款,例如,交易者盈虧上限有助於限制市場代幣價格因交易者盈虧而下降的金額,存款和取款的盈虧上限可能導致與提款相比,存款的市場代幣價格較低,這可以在未決損益較高時刺激存款。
minCollatealFactor:這決定了(頭寸抵押品)/(頭寸規模)的最小允許比率
maxPoolAmount:可以存入市場的最大代幣數量
maxOpenInterest:市場可開倉的最大持股量
ReserveFactor:這決定了(為部位保留的代幣價值)/(池中的代幣)的最大允許比率
maxPnlFactor:(PnL / 池中代幣價值)的最大比率
positionFeeFactor:決定增倉/減倉作業要扣除的費用百分比,費用金額依部位大小的變動而定
positionImpactFactor:這是“價格影響”部分中描述的部位的“價格影響因子”
maxPositionImpactFactor:這是“價格影響”部分中描述的部位的“最大價格影響”
positionImpactExponentFactor:這是倉位操作的「價格影響指數」值,如「價格影響」部分所述
swapFeeFactor:決定掉期要扣除的費用百分比,費用金額是根據掉期金額
swapImpactFactor:這是“價格影響”部分中描述的“價格影響因子”
swapImpactExponentFactor:這是存款和掉期的「價格影響指數」值,如上面的「價格影響」部分所述
fundingFactor:這是「資金費用」部分中所描述的「每秒資金因素」值
BorrowingFactorForLongs:這是“借款費用”部分中描述的多頭部位的“借款係數”
BorrowingFactorForShorts:這是“借入費用”部分中所述的空頭部位的“借入係數”
BorrowingExponentFactorForLongs:這是“借款費用”部分中描述的多頭部位的“借款指數因子”
BorrowingExponentFactorForShorts:這是“借款費用”部分中描述的多頭頭寸的“借款指數因子”
角色在 RoleStore 中進行管理,RoleAdmin 有權授予和撤銷任何角色。
RoleAdmin 最初將是部署者,但在角色設定後應將其刪除。
初始設定後:
只有 Timelock 合約才應具有 RoleAdmin 角色
時間鎖定管理員可以延遲授予新角色
系統值只能使用 Config 合約設定
EOA 不應具有控制者角色
配置管理員和時間鎖管理員可能會透過停用功能、錯誤設定值、將惡意代幣列入白名單、濫用積極的價格影響值等來擾亂正常操作
預計時間鎖多重簽章應撤銷惡意或受損帳號的權限
訂單守護者和凍結訂單守護者可能透過交易排序、延遲交易執行、ADL 執行等來獲取價值,這將透過守護者網路部分緩解
甲骨文簽名者應準確報告代幣的價格
抵押代幣需要透過配置的 TOKEN_TRANSFER_GAS_LIMIT 列入白名單
變基代幣、在轉移時改變餘額的代幣、代幣銷毀、帶有回調的代幣(例如 ERC-777 代幣等)與系統不相容,不應列入白名單
訂單管理者可以使用不同時間戳記的價格進行具有掉期的限價訂單,這將導致不同的輸出金額
訂單管理員應在發送交易之前驗證交易是否會恢復,以最大程度地減少天然氣浪費
訂單守護者可能會透過在 Gas 不足的情況下執行請求來導致請求被取消而不是執行
如果執行交易需要大量接近區塊最大 Gas 限制的 Gas,則可能會填充區塊以防止交易被包含在區塊中
在某些區塊鏈中,守護者可以控制用於執行交易的 tx.gasprice,這將影響支付給守護者的執行費用
惡意用戶可能會故意阻止訂單執行,導致市場不平衡,從而導致高價格影響,這應該是成本高且難以受益的
透過使用頭寸和掉期以及跨市場、鏈、分叉、其他協議的交易可以減少價格影響,虛擬庫存追蹤可以部分緩解這一影響
使用者可以透過使用高槓桿頭寸來減少價格影響,這可以透過 MIN_COLLATERAL_FACTOR_FOR_OPEN_INTEREST_MULTIPLIER 值部分緩解
價格影響值的計算不考慮費用以及價格影響本身所產生的影響,在大多數情況下,對價格影響計算的影響應該很小
池的價值很少但有可能變成負數,這種情況可能會發生,因為池中代幣的價值減去了impactPoolAmount和待處理的PnL
由於持倉價格影響的正負差異,持倉影響池中的虛擬代幣數量可能會不斷積累,從而影響市場代幣的定價,如有需要,應逐步分配持倉影響池
虛擬庫存追蹤池中代幣數量,必須保證每個分組中的代幣類型相同且小數點相同,即組內跨池的長代幣應具有相同的小數,跨池的短代幣應具有相同的小數位組內的小數位應相同,假設 USDC 有 6 位小數,DAI 有 18 位小數,則 ETH-USDC、ETH-DAI 等市場不應分組
虛擬ID必須在市場創建/代幣白名單之前設置,如果在代幣/市場交易完成後設置,追蹤將不準確,可能需要調整
對於帶有定序器的L2,沒有合約驗證來檢查L2 定序器是否處於活動狀態,如果定序器沒有創建任何區塊,則預言機管理員應停止簽署價格;如果定序器恢復正常運行,則預言機管理員應為使用最新獲取價格的最新區塊
如果 L2 定序器發生故障,它可能會阻止存款入倉以防止清算
對於可以完全使用鏈上價格源執行的交易,由於價格延遲或鏈關閉,可能可以利用過時的定價,鏈上價格源的使用應該是臨時的,並且應該使用低延遲源一旦支持所有令牌,即可使用
如果價格走勢對用戶不利,則區塊重組可以允許用戶在訂單執行後追溯取消訂單,如果在可能進行長期重組的鏈上使用合約,則應注意處理這種情況
更新和取消訂單可以提前運行以防止訂單執行,如果成功提前運行的機率小於或等於 50%,這應該不是問題,如果機率高於 50%,則費用和應調整價格影響以確保該策略不會實現淨利潤,調整UI 費用或推薦折扣同樣可用於導致訂單取消
如果區塊鏈或預言機停機,訂單可能會以明顯不同的價格執行,或者如果無法滿足訂單可接受的價格,則可能不會執行
依賴區塊時間戳記的準確性,因為預言機價格是根據該值進行驗證的,對於區塊鏈節點對時間戳記有一定控制的區塊鏈,應注意將oracleTimestampAdjustment 設定為一個值,該值會導致對區塊時間戳記的操縱。
可以透過暫時提高通常利用率較低的市場中的利用率來利用 GLV 轉換功能。一旦守門者執行轉移,攻擊者就可以將利用率降低到正常水準。頭寸費用和價格影響的配置方式應使此次攻擊的成本足以彌補 GLV 損失。
在 GLV 中,可能存在高於其最大 pnlToPoolFactorForTraders 的 GM 市場。如果該 GM 市場的 maxPnlFactorForDeposits 高於 maxPnlFactorForTraders,則 GM 市場在存款期間的估值將低於交易者實現利潤上限後的估值。惡意用戶可能會觀察到這種情況下的 GM 市場,並將其存入包含該市場的 GLV,以便從即將到來的 ADL 中獲利。為了避免這種情況,maxPnlFactorForDeposits 應小於或等於 maxPnlFactorForTraders。
從技術上講,市場價值有可能變成負值。在這種情況下,GLV 在市場價值變為正數之前將無法使用。
由於高盈虧因素或高保留美元,GM 代幣可能變得缺乏流動性。用戶可以將非流動性的 GM 代幣存入 GVL 並從不同的市場提取流動性,從而使 GLV 留下非流動性的代幣。 glvMaxMarketTokenBalanceUsd 和 glvMaxMarketTokenBalanceAmount 參數應考慮市場的風險,以避免來自風險市場的過多 GM 代幣。
scripts/verifyFallback.ts
可用於驗證合約npx hardhat verify
驗證一份 MarketToken 合約,之後所有 MarketToken 合約都應進行驗證,因為原始程式碼是相同的如果新增合約可能會導致定價差異,例如新舊合約之間的市場代幣價格差異,則應注意在啟用新合約之前停用舊合約
應提醒任何使用 Reader 合約或可能過時的定價計算的外部協議使用最新的合約和計算,例如 GM 代幣的 Chainlink 價格源
建議發布盡力而為的變更日誌,記錄整合應注意的重要更改,例如,如果將欄位添加到傳遞到回調函數的結構中,則此更改對於整合可能並不明顯
如果合約用於支持股權合成市場,應注意確保可以處理股票分割和類似的變化
具有「CONTROLLER」角色的合約可以存取重要功能,例如設定DataStore值,因此,應注意確保此類合約沒有通用函數或可用於更改重要值的函數
應針對不同的市場類型添加測試,例如現貨市場、單一代幣市場
除非絕對必要,否則不應修改回呼的 eventData 中值的順序,因為回呼合約可能透過固定索引來引用這些值
請注意,如果傳遞到回調的結構發生更改,例如存款、取款、訂單結構,這將導致回調合約期望先前結構的功能停止工作,因此,結構中的更改應突出顯示到集成中
如果正在使用推薦系統,則應授予 OrderHandler 更新交易者推薦代碼的權限
如果無法滿足請求中指定的要求(例如最低出金金額),存款、提款和訂單可能會被取消。請檢查取消時資金和汽油退款將發送到哪裡,以確保符合預期。
減倉訂單可以輸出兩個代幣,而不是單一代幣,如果減倉互換失敗,也有可能輸出金額和抵押品不足以支付費用,導致訂單無法執行
如果價差較大,開倉/平倉可能會顯著改變市場代幣的最低和最高價格,這不應該以有利可圖的方式進行操縱
FUNDING_FACTOR、STABLE_FUNDING_FACTOR、BORROWING_FACTOR、SKIP_BORROWING_FEE_FOR_SMALLER_SIDE、BORROWING_FEE_RECEIVER_FACTOR等配置值的變更可能會導致使用者產生額外費用,也可能導致市場代幣價格變動
如果交易者盈虧因 MAX_PNL_FACTOR_FOR_TRADERS 而受到限制,則支付給交易者的利潤百分比可能會有所不同,具體取決於頭寸減少/平倉的順序,因為上限是根據資金池的當前狀態重新計算的
事件資料可以傳遞給回調合約,eventData中參數的順序將嘗試保持不變,因此可以透過索引存取參數,為了安全起見,在使用之前仍應驗證參數的金鑰以檢查其是否匹配期望值
一些參數如 order.sizeDelta 和 order.initialCollateralDeltaAmount 在執行過程中可能會更新,更新後的值可能不會傳遞給回調合約
在創建回調合約時,回調合約可能需要將 DepositHandler、OrderHandler 或 WithdrawalHandler 列入白名單,需要注意的是,這些處理程序的新版本可能會隨著新程式碼添加到處理程序而部署,也可能兩個處理程序暫時同時存在,例如OrderHandler(1)、OrderHandler(2),因此回調合約應該能夠列入白名單並同時接受來自多個DepositHandler、OrderHandler 和WithdrawalHandler 的回調
對於回調合約,而不是為 DepositHandlers、OrderHandlers、WithdrawalHandlers 維護單獨的白名單,一個可能的解決方案是驗證 RoleStore 中 msg.sender 的角色,例如RoleStore.hasRole(msg.sender, Role.CONTROLLER)
,這將檢查msg.sender 是否為有效的處理程序
如果使用 ExchangeRouter、Oracle 或 Reader 等合約,請注意它們的位址會隨著新邏輯的新增而改變
如果更新了 ExchangeRouter、Oracle 或 Reader 等合約,應努力保持函數參數相同,但是,這可能並不總是可行,例如,如果要支援新的訂單屬性,則 ExchangeRouter.createOrder 參數必須改變
用於部署的 RoleStore 和 DataStore 不應更改,如果更改,可能需要將資金從先前的合約遷移到新合約
雖然程式碼的結構是為了最大限度地降低只讀重入的風險,但應注意防止這種可能性
GM代幣持有者的帳戶可能會發生代幣空投,持有GM代幣的整合合約必須能夠領取這些代幣,否則代幣將被鎖定,具體實現方式將根據整合合約而有所不同,一種可能是允許領取非市場代幣的代幣數量,可以使用Keys.MARKET_LIST
值進行檢查
ETH 轉帳以 NATIVE_TOKEN_TRANSFER_GAS_LIMIT 發送,以達到 Gas 限制,如果由於 Gas 不足或其他錯誤導致轉帳失敗,則 ETH 將以 WETH 形式發送
帳戶可能會收到用於 ADL/清算的 ETH,如果帳戶無法收到 ETH,則會發送 WETH
正面的價格影響受到影響池中代幣數量和配置值的限制
負面價格影響可能會受到配置值的限制
如果負面價格影響受到限制,額外金額將保留在可索賠抵押品池中,需要使用 ExchangeRouter.claimCollateral 函數手動索賠
需要使用 ExchangeRouter.claimFundingFees 函數手動申領正資金費用
聯盟獎勵需要使用 ExchangeRouter.claimAffiliateRewards 函數手動領取
市場或功能可能被停用
即使回呼恢復,執行仍將繼續
確保回調有足夠的gas
子帳戶可以建立、更新和取消帳戶的任何訂單
子帳戶可以從帳戶中支出 wnt 和抵押品
UI 費用可以更改
推薦折扣可以更改
黑名單地址的資金將保留在協議內
索引令牌並不總是保證是長令牌
費率的變化取決於是否有正面或負面影響
估算 GM 價格時考慮損益因子
處理存款取消
確保只有具有 CONTROLLER 角色的處理程序才能呼叫 afterDepositExecution 和 afterDepositCancellation 回呼函數
確保只有正確的存款執行才能呼叫回調函數
考慮具有相同多頭和空頭代幣的市場,這些市場不支持掉期
考慮積極和消極的價格影響
配置的延遲有一個請求取消期限,在此期間無法取消存款請求
產出金額受價格影響及費用影響
存款金額不得超過 MAX_PNL_FACTOR_FOR_DEPOSITS
任何市場的第一筆存款都必須存入 RECEIVER_FOR_FIRST_DEPOSIT
提款必須使用至少兩個輸出
處理提款取消
確保只有具有 CONTROLLER 角色的處理程序才能呼叫 afterWithdrawalExecution 和 afterWithdrawalCancellation 回呼函數
確保只有正確的提現執行才能呼叫回調函數
考慮具有相同多頭和空頭代幣的市場,這些市場不支持掉期
考慮積極和消極的價格影響
配置的延遲有一個請求取消期限,在此期間提款請求無法取消
產出金額受價格影響及費用影響
提款金額不得超過 MAX_PNL_FACTOR_FOR_WITHDRAWALS
處理訂單取消
強平和 ADL 可以觸發已儲存的回調合約
訂單可能會被凍結
確保只有具有 CONTROLLER 角色的處理程序才能呼叫 afterOrderExecution、afterOrderCancellation 和 afterOrderFrozen 回呼函數
確保只有正確的訂單執行才能呼叫回調函數
考慮具有相同多頭和空頭代幣的市場,這些市場不支持掉期
考慮積極和消極的價格影響
已儲存的回調合約可以更改
配置的延遲有一個請求取消期限,在此期間訂單請求無法取消
產出金額受價格影響及費用影響
隨著時間的推移,頭寸影響池會分配給流動性提供者
如果嘗試計算價格影響,應參考虛擬庫存
交易者盈虧上限高於 MAX_PNL_FACTOR_FOR_TRADERS
頭寸減少可以限制負面價格影響
減少訂單大小Delta 和抵押品Delta 如果大於部位可以處理的大小,則會自動更新
考慮 willPositionCollatealBeSufficient 驗證
考慮減少PositionSwapTypes
考慮最低抵押金額
清算期間仍會支付推薦費
頭寸的抵押品可能為零
零規模的部位不能存在
編譯合約:
npx hardhat compile
運行所有測試:
npx hardhat test
執行測試可能需要export NODE_OPTIONS=--max_old_space_size=4096
。
要列印程式碼指標:
npx ts-node metrics.ts
列印測試覆蓋率:
npx hardhat coverage