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 因子上限
这些不同的因素可以配置为帮助流动性提供者管理风险并在需要时激励存款,例如,交易者盈亏上限有助于限制市场代币价格因交易者盈亏而下降的金额,存款和取款的盈亏上限可能导致与提款相比,存款的市场代币价格较低,这可以在未决损益较高时刺激存款。
minCollateralFactor:这决定了(头寸抵押品)/(头寸规模)的最小允许比率
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是从池中代币的价值中减去的
由于位置价格影响的差异差异,可以在影响池的虚拟令牌数量增加,这将影响市场代币的价格,应在需要时逐渐分配该位置影响池
虚拟库存跟踪池中的令牌数量,必须确保每个分组中的令牌是相同的类型,并且具有相同的小数,即整个小组中的跨池中的长令牌应该具有相同的小数,在小组中应有相同的小数
虚拟ID必须在创建市场 /代币白名单之前设置,如果完成令牌 /市场交易之后设置的虚拟ID,则该跟踪不会准确,并且可能需要调整
对于带有音序器的L2S,没有合同验证可以检查L2 Sequencer是否活跃,如果Sequencer没有创建块,则Oracle Keepers应该停止签署价格使用最新提取价格的最新块
如果L2音序器下降,它可能会阻止沉积物进入位置以防止清算
对于可以完全使用链价格提要进行完全执行的交易,可能会利用由于价格延迟或链条下降而陈旧的定价,使用链价格供稿应为临时,低延迟供稿是一旦支持所有令牌
块重新计算可以允许用户在执行订单后,如果价格对用户不利,则可以追溯取消订单,如果使用长期重新计算的链条上使用合同,则应注意处理这种情况。
更新和取消订单可能是防止订单执行的前运行,如果成功的正面运行的概率小于或等于50%,这不是一个问题,如果概率高于50%,费用和费用应调整价格影响以确保策略不净利,调整UI费用或推荐折扣可以类似地用于导致取消订单
如果有区块链或甲骨文的停机时间,则可以以明显不同的价格执行订单,或者如果无法满足订单的可接受价格,则可能无法执行
由于Oracle价格得到了该值的验证,因此对区块链节点对时间戳有一定的控制权的区块链验证了块时间戳的准确性,因此应注意将OracleTimestampAdmjustment设置为可以使操纵的值设置时间戳无利可图
可以通过暂时增加利用率较低的市场的利用来利用GLV换档功能。守护者执行班次后,攻击者可以将利用率降低到其正常水平。职位费用和价格影响应以使这次攻击足够昂贵以覆盖GLV损失的方式配置。
在GLV中,可能有高于其最大PNLTOPOOLFACTORFORTRADERS的转基因市场。如果该通用汽车市场的Maxpnlfactorfordeposits高于Maxpnlfactorfortraders,那么在存款期间,通用汽车市场的价值低于交易者意识到其上限利润。恶意用户可能会在这种情况下观察到通用汽车市场,并将其存入GLV,以从ADL中获得,并很快就会随之而来。为了避免这种maxpnlfactorfordeposits,应小于或等于maxpnlfactorfortraders。
从技术上讲,市场价值成为负面。在这种情况下,GLV将无法使用,直到市场价值变为正面。
GM令牌可能由于高PNL因子或高保留的USD而变得不流动。用户可以将流动性的转基因令牌存入GVL中,并从其他市场中撤回流动性,从而使GLV带有流动的代币。 GlvMaxmarketTokenBalanceUsd和Glvmaxmarkettokenbalanceamount参数应解释市场的风险,以免从风险市场中拥有太多的GM代币。
scripts/verifyFallback.ts
可用于验证合同npx hardhat verify
来验证一项市场义合同,此后应验证所有Markettoken合同,因为源代码将相同如果添加了可能导致定价差异的新合同,例如新旧合同之间的市场令牌,则应注意在启用新合同之前禁用旧合同
任何使用读者合同或可能过时的计算定价的外部协议都应提醒使用最新的合同和计算,例如GM代币的链链接价格提要
建议发布最佳的努力ChangElog记录集成应该意识到的重要更改,例如,如果将字段添加到传递到回调函数的结构中,则此更改对于集成可能并不明显
如果合同用于支持股票合成市场,则应注意确保可以处理股票分割和类似更改
与“控制器”角色的合同可以访问重要功能,例如设置数据存储值,因此应注意确保此类合同没有可用于更改重要值的通用功能或功能
应添加针对不同市场类型的测试
除非严格必要
请注意,如果更改了回调的结构,例如存款,提款,订单结构,这将导致回调合同的功能,希望上一个结构停止工作,因此,由于此类的变化,结构的变化应突出显示为集成
如果使用了推荐系统,则应让OrderHandler访问贸易商更新推荐代码
如果无法满足请求中指定的要求,则可以取消存款,提款和订单,例如最低金额。请检查资金和汽油退款将在取消时发送到哪里,以确保与期望的期望相匹配。
减少位置订单可以输出两个令牌而不是一个令牌,如果降低位置交换失败,则可能不足
如果有巨大的价差,就有可能打开 /关闭职位可以大大改变市场代币的最低价格和最高价格,这不应以有利可图的方式进行操纵
配置值的变化,例如funding_factor,stable_funding_factor,borrowing_factor,skip_borrowing_fee_fee_for_for_smaller_side,borory_fee_receiver_factor,可能会导致用户的额外费用,也可能导致市场上的价格变化。
如果交易者PNL因MAX_PNL_FACTOR_FOR_TRADERS限制,则支付给交易者的利润百分比可能会有所不同,具体取决于位置降低 /关闭的订购,因为根据池的当前状态对CAP进行重新计算,
事件数据可以传递给回调合同,将尝试将访问的访问订单不变,因此可以通过索引访问参数,为了安全性,应在使用之前验证参数的密钥以检查是否匹配该参数是否匹配。期望值
某些参数,例如order.sizedelta和order.InitialCollateralDeltEltaAmount,可以在执行过程中更新,更新的值可能不会传递给回调合同
在签订回调合同时,回调合同可能需要将存款人,OrderHandler或提款人打白人,应注意,随着新代码的添加,可以部署这些处理程序的新版本暂时存在,例如,订购(1),OrderHandler(2),因此,回调合同应能够白白并同时接受来自多个存款人,订购者,订购者和提款人的回调
对于回调合同RoleStore.hasRole(msg.sender, Role.CONTROLLER)
而不是为存款人,订单手,提款人维护单独的白名单,一个可能的解决方案是验证sg.sender在rolestore中的角色检查MSG.Sender是有效的处理程序
如果使用诸如Exchangerouter之类的合同,Oracle或Reader确实会注意到,随着新逻辑的添加,它们的地址将会改变
如果更新了诸如Exchangerouter,Oracle或读者之类的合同,则应努力保持功能参数相同,但是,如果要支持新的订单属性,则可能并非总是可能将不得不改变
部署的Rolestore和数据存储不应更改,如果将其更改为从以前的合同到新合同的迁移,则可能需要
虽然该代码的结构是为了最大程度地降低仅阅读重新入侵的风险,但应注意防御这种可能性
通用代币持有人的帐户可能会出现令牌空调,整合持有GM令牌的合同必须能够索取这些令牌,否则代币将被锁定,确切的实施将根据综合合同而有所不同,一种可能性是允许索赔要求在不是市场代币的令牌中,可以使用Keys.MARKET_LIST
进行检查。market_list值
ETH传输是通过本机_token_transfer_gas_limit发送气体限制的,如果转移由于气体不足或其他错误而失败,则将ETH作为WETH发送为WETH
帐户可能会收到ADL /清算的ETH,如果帐户无法接收ETH,则将发送WETH
积极的价格影响是由影响池中的令牌量限制的,并基于配置的值
负价影响可能由配置的值限制
如果价格负面影响,则将额外的金额保留在可声称的附带池中,则需要使用Exchangerouter.claimcollateral功能手动要求这一点
需要使用ExchangerOuter.claimfundingfees功能手动索取正筹资费用
需要使用Exchangerouter.ClaimaffiliaTerewards功能手动要求会员奖励
市场或功能可能被禁用
即使回调恢复,执行仍将继续
确保回调有足够的气体
子帐户可以创建,更新和取消帐户的任何订单
子帐户可以从帐户中花费Wnt和抵押品
UI费用可以更改
推荐折扣可以更改
黑名单地址的资金将保留在协议中
索引令牌并不总是保证为长令牌
收费率根据是否有正面或负面影响而变化
估计通用汽车价格时考虑PNL因子
处理存款取消
确保只有具有控制器角色的处理程序可以调用AfterDepositexecution和AfterDepoSitCancellation回调功能
确保只有正确的存款执行才能调用回调功能
考虑具有相同长和短令牌的市场,这些市场不支持掉期
考虑积极的价格和负面影响
有一个已配置延迟的请求取消期,无法取消存款请求
产出金额可能会受到价格影响和费用
在max_pnl_factor_for_deposits上方不允许存款
任何市场中的第一个存款都必须转到reveriver_for_first_deposit
必须使用两个最低输出来提取
处理取消取消
确保只有具有控制器角色的处理程序才能调用AfterwithDrawAlexecution和AfterwithDrawAlcancellation回调功能
确保只有正确的提款执行才能调用回调功能
考虑具有相同长和短令牌的市场,这些市场不支持掉期
考虑积极的价格和负面影响
在无法取消提款请求的情况下,有一个已配置延迟的请求取消期
产出金额可能会受到价格影响和费用
在max_pnl_factor_for_withdrawals上方不允许提款
处理取消订单
清算和ADL可以触发保存的回调合同
订单可以冻结
确保只有具有控制器角色的处理程序可以调用后deperderexecution,AftererDorderCancellation和Aftererdorefrozen回调功能
确保只有正确的订单执行才能调用回调功能
考虑具有相同长和短令牌的市场,这些市场不支持掉期
考虑积极的价格和负面影响
可以更改保存的回调合同
有一个未能取消订单请求的已配置延迟的请求取消期
产出金额可能会受到价格影响和费用
随着时间的推移,位置影响池分配给流动性提供商
如果试图计算价格影响,应咨询虚拟库存
Trader PNL被封顶在max_pnl_factor_for_traders上方
负价影响可以限制在位置下降
降低订单的尺寸sipedelta和conterallaldelta将自动更新,如果他们的位置大于该位置可以处理
考虑WillPositionCollabesalabesive验证
考虑降低序列化型
考虑最低附带金额
清算期间仍会付款
职位有可能具有零抵押品
零大小的位置不存在
汇编合同:
npx hardhat compile
运行所有测试:
npx hardhat test
export NODE_OPTIONS=--max_old_space_size=4096
可能需要运行测试。
打印代码指标:
npx ts-node metrics.ts
打印测试覆盖范围:
npx hardhat coverage