tx · 9XbMTyPLt5fDyAAJKWfgvEwsGt5hfeRo6ZJyxN98cJX8

3Mz1td457M34EA7wU1swt2DBQDZEDpsMtgE:  -0.00500000 Waves

2022.08.29 19:21 [2205975] smart account 3Mz1td457M34EA7wU1swt2DBQDZEDpsMtgE > SELF 0.00000000 Waves

{ "type": 13, "id": "9XbMTyPLt5fDyAAJKWfgvEwsGt5hfeRo6ZJyxN98cJX8", "fee": 500000, "feeAssetId": null, "timestamp": 1661790122655, "version": 2, "chainId": 84, "sender": "3Mz1td457M34EA7wU1swt2DBQDZEDpsMtgE", "senderPublicKey": "DKoVYQRirYnan4ojiUkT12oE6XmpyNoht3ZcecUpgLsf", "proofs": [ "42mRuMYySEftmW4mLnuXy6uWWTwSzFCvK7J19zXtT6E4wmBYh8DHdtZKdH7tLEFJ2w4t6n8eTfCn3izZaYXnuWLt" ], "script": null, "height": 2205975, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: H5tixCueY28hRMFvxKbcyfS8TVKS588AKVuHdFoF88ZY Next: 3ePt1D3XZNax2NH1dGhkYXoxRz6DpMs4rrNR4YczzPwS Full:
OldNewDifferences
1-{-# STDLIB_VERSION 6 #-}
2-{-# SCRIPT_TYPE ACCOUNT #-}
3-{-# CONTENT_TYPE DAPP #-}
4-let k_ora_key = "k_ora_key"
5-
6-let k_ora_block_key = "k_ora_block_key"
7-
8-let k_ora = "k_ora"
9-
10-let k_balance = "k_balance"
11-
12-let k_positionSize = "k_positionSize"
13-
14-let k_positionMargin = "k_positionMargin"
15-
16-let k_positionOpenNotional = "k_positionOpenNotional"
17-
18-let k_positionLastUpdatedCumulativePremiumFraction = "k_positionFraction"
19-
20-let k_initialized = "k_initialized"
21-
22-let k_paused = "k_paused"
23-
24-let k_fee = "k_fee"
25-
26-let k_fundingPeriod = "k_fundingPeriod"
27-
28-let k_initMarginRatio = "k_initMarginRatio"
29-
30-let k_maintenanceMarginRatio = "k_mmr"
31-
32-let k_liquidationFeeRatio = "k_liquidationFeeRatio"
33-
34-let k_partialLiquidationRatio = "k_partLiquidationRatio"
35-
36-let k_spreadLimit = "k_spreadLimit"
37-
38-let k_maxPriceImpact = "k_maxPriceImpact"
39-
40-let k_maxPriceSpread = "k_maxPriceSpread"
41-
42-let k_lastDataStr = "k_lastDataStr"
43-
44-let k_lastMinuteId = "k_lastMinuteId"
45-
46-let k_twapDataLastCumulativePrice = "k_twapDataLastCumulativePrice"
47-
48-let k_twapDataLastPrice = "k_twapDataLastPrice"
49-
50-let k_twapDataPreviousMinuteId = "k_twapDataPreviousMinuteId"
51-
52-let k_latestLongCumulativePremiumFraction = "k_latestLongPremiumFraction"
53-
54-let k_latestShortCumulativePremiumFraction = "k_latestShortPremiumFraction"
55-
56-let k_nextFundingBlock = "k_nextFundingBlockMinTimestamp"
57-
58-let k_longFundingRate = "k_longFundingRate"
59-
60-let k_shortFundingRate = "k_shortFundingRate"
61-
62-let k_quoteAssetReserve = "k_qtAstR"
63-
64-let k_baseAssetReserve = "k_bsAstR"
65-
66-let k_totalPositionSize = "k_totalPositionSize"
67-
68-let k_totalLongPositionSize = "k_totalLongPositionSize"
69-
70-let k_totalShortPositionSize = "k_totalShortPositionSize"
71-
72-let k_cumulativeNotional = "k_cumulativeNotional"
73-
74-let k_openInterestNotional = "k_openInterestNotional"
75-
76-let k_coordinatorAddress = "k_coordinatorAddress"
77-
78-let k_insurance_address = "k_insurance_address"
79-
80-let k_admin_address = "k_admin_address"
81-
82-let k_admin_public_key = "k_admin_public_key"
83-
84-let k_quote_asset = "k_quote_asset"
85-
86-let k_quote_staking = "k_quote_staking"
87-
88-let k_staking_address = "k_staking_address"
89-
90-let k_miner_address = "k_miner_address"
91-
92-func coordinator () = valueOrErrorMessage(addressFromString(getStringValue(this, k_coordinatorAddress)), "Coordinator not set")
93-
94-
95-func adminAddress () = addressFromString(getStringValue(coordinator(), k_admin_address))
96-
97-
98-func adminPublicKey () = fromBase58String(getStringValue(coordinator(), k_admin_public_key))
99-
100-
101-func quoteAsset () = fromBase58String(getStringValue(coordinator(), k_quote_asset))
102-
103-
104-func quoteAssetStaking () = valueOrErrorMessage(addressFromString(getStringValue(coordinator(), k_quote_staking)), "Quote asset staking not set")
105-
106-
107-func stakingAddress () = valueOrErrorMessage(addressFromString(getStringValue(coordinator(), k_staking_address)), "Insurance not set")
108-
109-
110-func insuranceAddress () = valueOrErrorMessage(addressFromString(getStringValue(coordinator(), k_insurance_address)), "Insurance not set")
111-
112-
113-func minerAddress () = valueOrErrorMessage(addressFromString(getStringValue(coordinator(), k_miner_address)), "Insurance not set")
114-
115-
116-let DIR_LONG = 1
117-
118-let DIR_SHORT = 2
119-
120-let TWAP_INTERVAL = 15
121-
122-let ORACLE_INTERVAL = 15
123-
124-let SECONDS = 1000
125-
126-let DECIMAL_UNIT = (1 * (((((10 * 10) * 10) * 10) * 10) * 10))
127-
128-let ONE_DAY = (86400 * DECIMAL_UNIT)
129-
130-let ALL_FEES = 100
131-
132-let PNL_OPTION_SPOT = 1
133-
134-let PNL_OPTION_ORACLE = 2
135-
136-func s (_x) = (toString(_x) + ",")
137-
138-
139-func divd (_x,_y) = fraction(_x, DECIMAL_UNIT, _y, HALFEVEN)
140-
141-
142-func muld (_x,_y) = fraction(_x, _y, DECIMAL_UNIT, HALFEVEN)
143-
144-
145-func abs (_x) = if ((_x > 0))
146- then _x
147- else -(_x)
148-
149-
150-func vmax (_x,_y) = if ((_x >= _y))
151- then _x
152- else _y
153-
154-
155-func toCompositeKey (_key,_address) = ((_key + "_") + _address)
156-
157-
158-func listToStr (_list) = {
159- func _join (accumulator,val) = ((accumulator + val) + ",")
160-
161- let newListStr = {
162- let $l = _list
163- let $s = size($l)
164- let $acc0 = ""
165- func $f0_1 ($a,$i) = if (($i >= $s))
166- then $a
167- else _join($a, $l[$i])
168-
169- func $f0_2 ($a,$i) = if (($i >= $s))
170- then $a
171- else throw("List size exceeds 20")
172-
173- $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10), 11), 12), 13), 14), 15), 16), 17), 18), 19), 20)
174- }
175- let newListStrU = dropRight(newListStr, 1)
176- let newListStrR = if ((take(newListStrU, 1) == ","))
177- then drop(newListStrU, 1)
178- else newListStrU
179- newListStrR
180- }
181-
182-
183-func strToList (_str) = split(_str, ",")
184-
185-
186-func pushToQueue (_list,_maxSize,_value) = if ((size(_list) > _maxSize))
187- then (removeByIndex(_list, 0) :+ _value)
188- else (_list :+ _value)
189-
190-
191-func int (k) = valueOrErrorMessage(getInteger(this, k), ("no value for " + k))
192-
193-
194-func cbalance () = int(k_balance)
195-
196-
197-func fee () = int(k_fee)
198-
199-
200-func initMarginRatio () = int(k_initMarginRatio)
201-
202-
203-func qtAstR () = int(k_quoteAssetReserve)
204-
205-
206-func bsAstR () = int(k_baseAssetReserve)
207-
208-
209-func totalPositionSize () = int(k_totalPositionSize)
210-
211-
212-func cumulativeNotional () = int(k_cumulativeNotional)
213-
214-
215-func openInterestNotional () = int(k_openInterestNotional)
216-
217-
218-func nextFundingBlockTimestamp () = int(k_nextFundingBlock)
219-
220-
221-func fundingPeriodRaw () = int(k_fundingPeriod)
222-
223-
224-func fundingPeriodDecimal () = (fundingPeriodRaw() * DECIMAL_UNIT)
225-
226-
227-func fundingPeriodSeconds () = (fundingPeriodRaw() * SECONDS)
228-
229-
230-func maintenanceMarginRatio () = int(k_maintenanceMarginRatio)
231-
232-
233-func liquidationFeeRatio () = int(k_liquidationFeeRatio)
234-
235-
236-func partialLiquidationRatio () = int(k_partialLiquidationRatio)
237-
238-
239-func spreadLimit () = int(k_spreadLimit)
240-
241-
242-func maxPriceImpact () = int(k_maxPriceImpact)
243-
244-
245-func maxPriceSpread () = int(k_maxPriceSpread)
246-
247-
248-func latestLongCumulativePremiumFraction () = int(k_latestLongCumulativePremiumFraction)
249-
250-
251-func latestShortCumulativePremiumFraction () = int(k_latestShortCumulativePremiumFraction)
252-
253-
254-func totalShortPositionSize () = int(k_totalShortPositionSize)
255-
256-
257-func totalLongPositionSize () = int(k_totalLongPositionSize)
258-
259-
260-func requireMoreMarginRatio (_marginRatio,_baseMarginRatio,_largerThanOrEqualTo) = {
261- let remainingMarginRatio = (_marginRatio - _baseMarginRatio)
262- if (if (_largerThanOrEqualTo)
263- then (0 > remainingMarginRatio)
264- else false)
265- then throw("Invalid margin")
266- else if (if (!(_largerThanOrEqualTo))
267- then (remainingMarginRatio >= 0)
268- else false)
269- then throw("Invalid margin")
270- else true
271- }
272-
273-
274-func latestCumulativePremiumFraction (_positionSize) = if ((_positionSize == 0))
275- then throw("Should not be called with _positionSize == 0")
276- else if ((_positionSize > 0))
277- then latestLongCumulativePremiumFraction()
278- else latestShortCumulativePremiumFraction()
279-
280-
281-func getPosition (_trader) = {
282- let positionSizeOpt = getInteger(this, toCompositeKey(k_positionSize, _trader))
283- match positionSizeOpt {
284- case positionSize: Int =>
285- $Tuple4(positionSize, getIntegerValue(this, toCompositeKey(k_positionMargin, _trader)), getIntegerValue(this, toCompositeKey(k_positionOpenNotional, _trader)), getIntegerValue(this, toCompositeKey(k_positionLastUpdatedCumulativePremiumFraction, _trader)))
286- case _ =>
287- $Tuple4(0, 0, 0, 0)
288- }
289- }
290-
291-
292-func requireOpenPosition (_trader) = if ((getPosition(_trader)._1 == 0))
293- then throw("No open position")
294- else true
295-
296-
297-func initialized () = valueOrElse(getBoolean(this, k_initialized), false)
298-
299-
300-func paused () = valueOrElse(getBoolean(this, k_paused), false)
301-
302-
303-func updateReserve (_isAdd,_quoteAssetAmount,_baseAssetAmount) = if (_isAdd)
304- then {
305- let newBase = (bsAstR() - _baseAssetAmount)
306- if ((0 >= newBase))
307- then throw("Tx lead to base asset reserve <= 0, revert")
308- else $Tuple4((qtAstR() + _quoteAssetAmount), newBase, (totalPositionSize() + _baseAssetAmount), (cumulativeNotional() + _quoteAssetAmount))
309- }
310- else {
311- let newQuote = (qtAstR() - _quoteAssetAmount)
312- if ((0 >= newQuote))
313- then throw("Tx lead to base quote reserve <= 0, revert")
314- else $Tuple4(newQuote, (bsAstR() + _baseAssetAmount), (totalPositionSize() - _baseAssetAmount), (cumulativeNotional() - _quoteAssetAmount))
315- }
316-
317-
318-func swapInput (_isAdd,_quoteAssetAmount) = {
319- let _qtAstR = qtAstR()
320- let _bsAstR = bsAstR()
321- let k = muld(_qtAstR, _bsAstR)
322- let quoteAssetReserveAfter = if (_isAdd)
323- then (_qtAstR + _quoteAssetAmount)
324- else (_qtAstR - _quoteAssetAmount)
325- let baseAssetReserveAfter = divd(k, quoteAssetReserveAfter)
326- let amountBaseAssetBoughtAbs = abs((baseAssetReserveAfter - _bsAstR))
327- let amountBaseAssetBought = if (_isAdd)
328- then amountBaseAssetBoughtAbs
329- else -(amountBaseAssetBoughtAbs)
330- let $t01217712370 = updateReserve(_isAdd, _quoteAssetAmount, amountBaseAssetBoughtAbs)
331- let quoteAssetReserveAfter1 = $t01217712370._1
332- let baseAssetReserveAfter1 = $t01217712370._2
333- let totalPositionSizeAfter1 = $t01217712370._3
334- let cumulativeNotionalAfter1 = $t01217712370._4
335- let priceBefore = divd(_qtAstR, _bsAstR)
336- let marketPrice = divd(_quoteAssetAmount, amountBaseAssetBoughtAbs)
337- let priceDiff = abs((priceBefore - marketPrice))
338- let priceImpact = (DECIMAL_UNIT - divd(priceBefore, (priceBefore + priceDiff)))
339- let maxPriceImpactValue = maxPriceImpact()
340- if ((priceImpact > maxPriceImpactValue))
341- then throw(((((((((((((("Price impact " + toString(priceImpact)) + " > max price impact ") + toString(maxPriceImpactValue)) + " before quote asset: ") + toString(_qtAstR)) + " before base asset: ") + toString(_bsAstR)) + " quote asset amount to exchange: ") + toString(_quoteAssetAmount)) + " price before: ") + toString(priceBefore)) + " marketPrice: ") + toString(marketPrice)))
342- else $Tuple5(amountBaseAssetBought, quoteAssetReserveAfter1, baseAssetReserveAfter1, totalPositionSizeAfter1, cumulativeNotionalAfter1)
343- }
344-
345-
346-func calcRemainMarginWithFundingPayment (_oldPositionSize,_oldPositionMargin,_oldPositionCumulativePremiumFraction,_marginDelta) = {
347- let fundingPayment = if ((_oldPositionSize != 0))
348- then {
349- let _latestCumulativePremiumFraction = latestCumulativePremiumFraction(_oldPositionSize)
350- muld((_latestCumulativePremiumFraction - _oldPositionCumulativePremiumFraction), _oldPositionSize)
351- }
352- else 0
353- let signedMargin = ((_marginDelta - fundingPayment) + _oldPositionMargin)
354- let $t01386113988 = if ((0 > signedMargin))
355- then $Tuple2(0, abs(signedMargin))
356- else $Tuple2(abs(signedMargin), 0)
357- let remainMargin = $t01386113988._1
358- let badDebt = $t01386113988._2
359- $Tuple3(remainMargin, badDebt, fundingPayment)
360- }
361-
362-
363-func swapOutputWithReserves (_isAdd,_baseAssetAmount,_checkMaxPriceImpact,_quoteAssetReserve,_baseAssetReserve) = {
364- let priceBefore = divd(_quoteAssetReserve, _baseAssetReserve)
365- if ((_baseAssetAmount == 0))
366- then throw("Invalid base asset amount")
367- else {
368- let k = muld(_quoteAssetReserve, _baseAssetReserve)
369- let baseAssetPoolAmountAfter = if (_isAdd)
370- then (_baseAssetReserve + _baseAssetAmount)
371- else (_baseAssetReserve - _baseAssetAmount)
372- let quoteAssetAfter = divd(k, baseAssetPoolAmountAfter)
373- let quoteAssetSold = abs((quoteAssetAfter - _quoteAssetReserve))
374- let maxPriceImpactValue = maxPriceImpact()
375- let $t01496515158 = updateReserve(!(_isAdd), quoteAssetSold, _baseAssetAmount)
376- let quoteAssetReserveAfter1 = $t01496515158._1
377- let baseAssetReserveAfter1 = $t01496515158._2
378- let totalPositionSizeAfter1 = $t01496515158._3
379- let cumulativeNotionalAfter1 = $t01496515158._4
380- let marketPrice = divd(quoteAssetSold, _baseAssetAmount)
381- let priceDiff = abs((priceBefore - marketPrice))
382- let priceImpact = (DECIMAL_UNIT - divd(priceBefore, (priceBefore + priceDiff)))
383- if (if ((priceImpact > maxPriceImpactValue))
384- then _checkMaxPriceImpact
385- else false)
386- then throw(((((((((((((("Price impact " + toString(priceImpact)) + " > max price impact ") + toString(maxPriceImpactValue)) + " before quote asset: ") + toString(_quoteAssetReserve)) + " before base asset: ") + toString(_baseAssetReserve)) + " base asset amount to exchange: ") + toString(_baseAssetAmount)) + " price before: ") + toString(priceBefore)) + " market price: ") + toString(marketPrice)))
387- else $Tuple8(quoteAssetSold, quoteAssetReserveAfter1, baseAssetReserveAfter1, totalPositionSizeAfter1, cumulativeNotionalAfter1, (totalLongPositionSize() - (if (_isAdd)
388- then abs(_baseAssetAmount)
389- else 0)), (totalShortPositionSize() - (if (!(_isAdd))
390- then abs(_baseAssetAmount)
391- else 0)), priceImpact)
392- }
393- }
394-
395-
396-func swapOutput (_isAdd,_baseAssetAmount,_checkMaxPriceImpact) = swapOutputWithReserves(_isAdd, _baseAssetAmount, _checkMaxPriceImpact, qtAstR(), bsAstR())
397-
398-
399-func getOracleTwapPrice () = {
400- let oracle = valueOrErrorMessage(addressFromString(getStringValue(this, k_ora)), "")
401- let priceKey = getStringValue(this, k_ora_key)
402- let blockKey = getStringValue(this, k_ora_block_key)
403- let lastValue = valueOrErrorMessage(getInteger(oracle, priceKey), ((("Can not get oracle price. Oracle: " + toString(oracle)) + " key: ") + priceKey))
404- lastValue
405- }
406-
407-
408-func requireNotOverSpreadLimit (_quoteAssetReserve,_baseAssetReserve) = {
409- let oraclePrice = getOracleTwapPrice()
410- let priceAfter = divd(_quoteAssetReserve, _baseAssetReserve)
411- let averagePrice = divd((oraclePrice + priceAfter), (2 * DECIMAL_UNIT))
412- let absPriceDiff = divd(abs((oraclePrice - priceAfter)), averagePrice)
413- if ((absPriceDiff > maxPriceSpread()))
414- then throw(((("Price spread " + toString(absPriceDiff)) + " > max price spread ") + toString(maxPriceSpread())))
415- else true
416- }
417-
418-
419-func getSpotPrice () = {
420- let _quoteAssetReserve = qtAstR()
421- let _baseAssetReserve = bsAstR()
422- divd(_quoteAssetReserve, _baseAssetReserve)
423- }
424-
425-
426-func isOverFluctuationLimit () = {
427- let oraclePrice = getOracleTwapPrice()
428- let currentPrice = getSpotPrice()
429- (divd(abs((oraclePrice - currentPrice)), oraclePrice) > spreadLimit())
430- }
431-
432-
433-func getPositionAdjustedOpenNotional (_positionSize,_option,_quoteAssetReserve,_baseAssetReserve) = {
434- let positionSizeAbs = abs(_positionSize)
435- let isShort = (0 > _positionSize)
436- let positionNotional = if ((_option == PNL_OPTION_SPOT))
437- then {
438- let $t01837618547 = swapOutputWithReserves(!(isShort), positionSizeAbs, false, _quoteAssetReserve, _baseAssetReserve)
439- let outPositionNotional = $t01837618547._1
440- let x1 = $t01837618547._2
441- let x2 = $t01837618547._3
442- let x3 = $t01837618547._4
443- outPositionNotional
444- }
445- else muld(positionSizeAbs, getOracleTwapPrice())
446- positionNotional
447- }
448-
449-
450-func getPositionNotionalAndUnrealizedPnl (_trader,_option) = {
451- let $t01894119069 = getPosition(_trader)
452- let positionSize = $t01894119069._1
453- let positionMargin = $t01894119069._2
454- let positionOpenNotional = $t01894119069._3
455- let positionLstUpdCPF = $t01894119069._4
456- if ((positionSize == 0))
457- then throw("Invalid position size")
458- else {
459- let isShort = (0 > positionSize)
460- let positionNotional = getPositionAdjustedOpenNotional(positionSize, _option, qtAstR(), bsAstR())
461- let unrealizedPnl = if (isShort)
462- then (positionOpenNotional - positionNotional)
463- else (positionNotional - positionOpenNotional)
464- $Tuple2(positionNotional, unrealizedPnl)
465- }
466- }
467-
468-
469-func calcMarginRatio (_remainMargin,_badDebt,_positionNotional) = divd((_remainMargin - _badDebt), _positionNotional)
470-
471-
472-func getMarginRatioByOption (_trader,_option) = {
473- let $t01990220013 = getPosition(_trader)
474- let positionSize = $t01990220013._1
475- let positionMargin = $t01990220013._2
476- let pon = $t01990220013._3
477- let positionLstUpdCPF = $t01990220013._4
478- let $t02001920112 = getPositionNotionalAndUnrealizedPnl(_trader, _option)
479- let positionNotional = $t02001920112._1
480- let unrealizedPnl = $t02001920112._2
481- let $t02011720283 = calcRemainMarginWithFundingPayment(positionSize, positionMargin, positionLstUpdCPF, unrealizedPnl)
482- let remainMargin = $t02011720283._1
483- let badDebt = $t02011720283._2
484- calcMarginRatio(remainMargin, badDebt, positionNotional)
485- }
486-
487-
488-func getMarginRatio (_trader) = getMarginRatioByOption(_trader, PNL_OPTION_SPOT)
489-
490-
491-func getPartialLiquidationAmount (_trader,_positionSize) = {
492- let maximumRatio = vmax(partialLiquidationRatio(), (DECIMAL_UNIT - divd(getMarginRatio(_trader), maintenanceMarginRatio())))
493- let maxExchangedPositionSize = muld(abs(_positionSize), maximumRatio)
494- let swapResult = swapOutput((_positionSize > 0), maxExchangedPositionSize, false)
495- let maxExchangedQuoteAssetAmount = swapResult._1
496- let priceImpact = swapResult._8
497- if ((maxPriceImpact() > priceImpact))
498- then maxExchangedQuoteAssetAmount
499- else {
500- let exchangedPositionSize = muld(abs(_positionSize), partialLiquidationRatio())
501- let exchangedQuoteAssetAmount = swapOutput((_positionSize > 0), exchangedPositionSize, false)._1
502- exchangedQuoteAssetAmount
503- }
504- }
505-
506-
507-func internalClosePosition (_trader,_checkMaxPriceImpact) = {
508- let $t02146521593 = getPosition(_trader)
509- let positionSize = $t02146521593._1
510- let positionMargin = $t02146521593._2
511- let positionOpenNotional = $t02146521593._3
512- let positionLstUpdCPF = $t02146521593._4
513- let unrealizedPnl = getPositionNotionalAndUnrealizedPnl(_trader, PNL_OPTION_SPOT)._2
514- let $t02168821856 = calcRemainMarginWithFundingPayment(positionSize, positionMargin, positionLstUpdCPF, unrealizedPnl)
515- let remainMargin = $t02168821856._1
516- let badDebt = $t02168821856._2
517- let exchangedPositionSize = -(positionSize)
518- let realizedPnl = unrealizedPnl
519- let marginToVault = -(remainMargin)
520- let $t02198322294 = swapOutput((positionSize > 0), abs(positionSize), _checkMaxPriceImpact)
521- let exchangedQuoteAssetAmount = $t02198322294._1
522- let quoteAssetReserveAfter = $t02198322294._2
523- let baseAssetReserveAfter = $t02198322294._3
524- let totalPositionSizeAfter = $t02198322294._4
525- let cumulativeNotionalAfter = $t02198322294._5
526- let totalLongAfter = $t02198322294._6
527- let totalShortAfter = $t02198322294._7
528- let openInterestNotionalAfter = (openInterestNotional() - positionOpenNotional)
529- $Tuple12(exchangedPositionSize, badDebt, realizedPnl, marginToVault, quoteAssetReserveAfter, baseAssetReserveAfter, totalPositionSizeAfter, cumulativeNotionalAfter, openInterestNotionalAfter, exchangedQuoteAssetAmount, totalLongAfter, totalShortAfter)
530- }
531-
532-
533-func getTwapSpotPrice () = {
534- let minuteId = ((lastBlock.timestamp / 1000) / 60)
535- let startMinuteId = (minuteId - TWAP_INTERVAL)
536- let listStr = valueOrElse(getString(this, k_lastDataStr), "")
537- let list = split(listStr, ",")
538- func filterFn (accumulator,next) = if ((startMinuteId >= parseIntValue(next)))
539- then (accumulator :+ parseIntValue(next))
540- else accumulator
541-
542- let listF = {
543- let $l = list
544- let $s = size($l)
545- let $acc0 = nil
546- func $f0_1 ($a,$i) = if (($i >= $s))
547- then $a
548- else filterFn($a, $l[$i])
549-
550- func $f0_2 ($a,$i) = if (($i >= $s))
551- then $a
552- else throw("List size exceeds 20")
553-
554- $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10), 11), 12), 13), 14), 15), 16), 17), 18), 19), 20)
555- }
556- let maxIndex = if ((size(listF) > 0))
557- then max(listF)
558- else parseIntValue(list[0])
559- let lastMinuteId = valueOrElse(getInteger(this, k_lastMinuteId), 0)
560- let endLastCumulativePrice = valueOrElse(getInteger(this, ((k_twapDataLastCumulativePrice + "_") + toString(lastMinuteId))), 0)
561- let endLastPrice = valueOrElse(getInteger(this, ((k_twapDataLastPrice + "_") + toString(lastMinuteId))), 0)
562- let nowCumulativePrice = (endLastCumulativePrice + ((minuteId - lastMinuteId) * endLastPrice))
563- let startLastCumulativePrice = valueOrElse(getInteger(this, ((k_twapDataLastCumulativePrice + "_") + toString(maxIndex))), 0)
564- let startLastPrice = valueOrElse(getInteger(this, ((k_twapDataLastPrice + "_") + toString(maxIndex))), 0)
565- let startCumulativePrice = (startLastCumulativePrice + ((startMinuteId - maxIndex) * startLastPrice))
566- ((nowCumulativePrice - startCumulativePrice) / TWAP_INTERVAL)
567- }
568-
569-
570-func updateSettings (_initMarginRatio,_mmr,_liquidationFeeRatio,_fundingPeriod,_fee,_spreadLimit,_maxPriceImpact,_partialLiquidationRatio,_maxPriceSpread) = [IntegerEntry(k_initMarginRatio, _initMarginRatio), IntegerEntry(k_maintenanceMarginRatio, _mmr), IntegerEntry(k_liquidationFeeRatio, _liquidationFeeRatio), IntegerEntry(k_fundingPeriod, _fundingPeriod), IntegerEntry(k_fee, _fee), IntegerEntry(k_spreadLimit, _spreadLimit), IntegerEntry(k_maxPriceImpact, _maxPriceImpact), IntegerEntry(k_partialLiquidationRatio, _partialLiquidationRatio), IntegerEntry(k_maxPriceSpread, _maxPriceSpread)]
571-
572-
573-func updateFunding (_nextFundingBlock,_latestLongCumulativePremiumFraction,_latestShortCumulativePremiumFraction,_longFundingRate,_shortFundingRate) = [IntegerEntry(k_nextFundingBlock, _nextFundingBlock), IntegerEntry(k_latestLongCumulativePremiumFraction, _latestLongCumulativePremiumFraction), IntegerEntry(k_latestShortCumulativePremiumFraction, _latestShortCumulativePremiumFraction), IntegerEntry(k_longFundingRate, _longFundingRate), IntegerEntry(k_shortFundingRate, _shortFundingRate)]
574-
575-
576-func updatePosition (_address,_size,_margin,_openNotional,_latestCumulativePremiumFraction) = [IntegerEntry(toCompositeKey(k_positionSize, _address), _size), IntegerEntry(toCompositeKey(k_positionMargin, _address), _margin), IntegerEntry(toCompositeKey(k_positionOpenNotional, _address), _openNotional), IntegerEntry(toCompositeKey(k_positionLastUpdatedCumulativePremiumFraction, _address), _latestCumulativePremiumFraction)]
577-
578-
579-func appendTwap (price) = {
580- let minuteId = ((lastBlock.timestamp / 1000) / 60)
581- let previousMinuteId = valueOrElse(getInteger(this, k_lastMinuteId), 0)
582- if ((previousMinuteId > minuteId))
583- then throw("TWAP out-of-order")
584- else {
585- let lastMinuteId = if ((previousMinuteId == 0))
586- then minuteId
587- else previousMinuteId
588- if ((minuteId > previousMinuteId))
589- then {
590- let prevCumulativePrice = valueOrElse(getInteger(this, ((k_twapDataLastCumulativePrice + "_") + toString(previousMinuteId))), 0)
591- let prevPrice = valueOrElse(getInteger(this, ((k_twapDataLastPrice + "_") + toString(previousMinuteId))), price)
592- let lastCumulativePrice = (prevCumulativePrice + ((minuteId - lastMinuteId) * prevPrice))
593- let list = pushToQueue(strToList(valueOrElse(getString(this, k_lastDataStr), "")), TWAP_INTERVAL, toString(minuteId))
594-[IntegerEntry(toCompositeKey(k_twapDataLastCumulativePrice, toString(minuteId)), lastCumulativePrice), IntegerEntry(toCompositeKey(k_twapDataLastPrice, toString(minuteId)), price), IntegerEntry(toCompositeKey(k_twapDataPreviousMinuteId, toString(minuteId)), previousMinuteId), IntegerEntry(k_lastMinuteId, minuteId), StringEntry(k_lastDataStr, listToStr(list))]
595- }
596- else {
597- let twapDataPreviousMinuteId = valueOrElse(getInteger(this, toCompositeKey(k_twapDataPreviousMinuteId, toString(minuteId))), 0)
598- let prevCumulativePrice = valueOrElse(getInteger(this, toCompositeKey(k_twapDataLastCumulativePrice, toString(twapDataPreviousMinuteId))), 0)
599- let prevPrice = valueOrElse(getInteger(this, toCompositeKey(k_twapDataLastPrice, toString(twapDataPreviousMinuteId))), price)
600- let lastCumulativePrice = (prevCumulativePrice + ((minuteId - twapDataPreviousMinuteId) * prevPrice))
601-[IntegerEntry(toCompositeKey(k_twapDataLastCumulativePrice, toString(minuteId)), lastCumulativePrice), IntegerEntry(toCompositeKey(k_twapDataLastPrice, toString(minuteId)), price)]
602- }
603- }
604- }
605-
606-
607-func updateAmmReserves (_qtAstR,_bsAstR) = [IntegerEntry(k_quoteAssetReserve, _qtAstR), IntegerEntry(k_baseAssetReserve, _bsAstR)]
608-
609-
610-func updateAmm (_qtAstR,_bsAstR,_totalPositionSizeAfter,_cumulativeNotionalAfter,_openInterestNotional,_totalLongPositionSize,_totalShortPositionSize) = if (((_totalLongPositionSize - _totalShortPositionSize) != _totalPositionSizeAfter))
611- then throw(((((("Invalid AMM state data: " + toString(_totalLongPositionSize)) + " + ") + toString(_totalShortPositionSize)) + " != ") + toString(_totalPositionSizeAfter)))
612- else ((updateAmmReserves(_qtAstR, _bsAstR) ++ [IntegerEntry(k_totalPositionSize, _totalPositionSizeAfter), IntegerEntry(k_cumulativeNotional, _cumulativeNotionalAfter), IntegerEntry(k_openInterestNotional, _openInterestNotional), IntegerEntry(k_totalLongPositionSize, _totalLongPositionSize), IntegerEntry(k_totalShortPositionSize, _totalShortPositionSize)]) ++ appendTwap(divd(_qtAstR, _bsAstR)))
613-
614-
615-func deletePosition (_address) = [DeleteEntry(toCompositeKey(k_positionSize, _address)), DeleteEntry(toCompositeKey(k_positionMargin, _address)), DeleteEntry(toCompositeKey(k_positionOpenNotional, _address)), DeleteEntry(toCompositeKey(k_positionLastUpdatedCumulativePremiumFraction, _address))]
616-
617-
618-func withdraw (_address,_amount) = {
619- let balance = assetBalance(this, quoteAsset())
620- if ((_amount > balance))
621- then throw(((("Unable to withdraw " + toString(_amount)) + " from contract balance ") + toString(balance)))
622- else [ScriptTransfer(_address, _amount, quoteAsset())]
623- }
624-
625-
626-func updateBalance (i) = if ((0 > i))
627- then throw("Balance")
628- else [IntegerEntry(k_balance, i)]
629-
630-
631-func transferFee (i) = [ScriptTransfer(stakingAddress(), i, quoteAsset())]
632-
633-
634-@Callable(i)
635-func pause () = if ((i.caller != adminAddress()))
636- then throw("Invalid togglePause params")
637- else [BooleanEntry(k_paused, true)]
638-
639-
640-
641-@Callable(i)
642-func unpause () = if ((i.caller != adminAddress()))
643- then throw("Invalid togglePause params")
644- else [BooleanEntry(k_paused, false)]
645-
646-
647-
648-@Callable(i)
649-func addLiquidity (_quoteAssetAmount) = if (if ((i.caller != adminAddress()))
650- then true
651- else (0 >= _quoteAssetAmount))
652- then throw("Invalid addLiquidity params")
653- else {
654- let _qtAstR = qtAstR()
655- let _bsAstR = bsAstR()
656- let price = divd(_qtAstR, _bsAstR)
657- let baseAssetAmountToAdd = divd(_quoteAssetAmount, price)
658- let qtAstRAfter = (_qtAstR + _quoteAssetAmount)
659- let bsAstRAfter = (_bsAstR + baseAssetAmountToAdd)
660- updateAmmReserves(qtAstRAfter, bsAstRAfter)
661- }
662-
663-
664-
665-@Callable(i)
666-func removeLiquidity (_quoteAssetAmount) = if (if ((i.caller != adminAddress()))
667- then true
668- else (0 >= _quoteAssetAmount))
669- then throw("Invalid removeLiquidity params")
670- else {
671- let _qtAstR = qtAstR()
672- let _bsAstR = bsAstR()
673- let price = divd(_qtAstR, _bsAstR)
674- let baseAssetAmountToRemove = divd(_quoteAssetAmount, price)
675- let qtAstRAfter = (_qtAstR - _quoteAssetAmount)
676- let bsAstRAfter = (_bsAstR - baseAssetAmountToRemove)
677- updateAmmReserves(qtAstRAfter, bsAstRAfter)
678- }
679-
680-
681-
682-@Callable(i)
683-func changeSettings (_initMarginRatio,_mmr,_liquidationFeeRatio,_fundingPeriod,_fee,_spreadLimit,_maxPriceImpact,_partialLiquidationRatio,_maxPriceSpread) = if ((i.caller != adminAddress()))
684- then throw("Invalid changeSettings params")
685- else updateSettings(_initMarginRatio, _mmr, _liquidationFeeRatio, _fundingPeriod, _fee, _spreadLimit, _maxPriceImpact, _partialLiquidationRatio, _maxPriceSpread)
686-
687-
688-
689-@Callable(i)
690-func initialize (_qtAstR,_bsAstR,_fundingPeriod,_initMarginRatio,_mmr,_liquidationFeeRatio,_fee,_oracle,_oracleKey,_coordinator,_spreadLimit,_maxPriceImpact,_partialLiquidationRatio,_maxPriceSpread) = if (if (if (if (if (if (if (if (if (if (if (if ((0 >= _qtAstR))
691- then true
692- else (0 >= _bsAstR))
693- then true
694- else (0 >= _fundingPeriod))
695- then true
696- else (0 >= _initMarginRatio))
697- then true
698- else (0 >= _mmr))
699- then true
700- else (0 >= _liquidationFeeRatio))
701- then true
702- else (0 >= _fee))
703- then true
704- else (0 >= _spreadLimit))
705- then true
706- else (0 >= _maxPriceImpact))
707- then true
708- else (0 >= _partialLiquidationRatio))
709- then true
710- else (0 >= _maxPriceSpread))
711- then true
712- else initialized())
713- then throw("Invalid initialize parameters")
714- else ((((updateAmm(_qtAstR, _bsAstR, 0, 0, 0, 0, 0) ++ updateSettings(_initMarginRatio, _mmr, _liquidationFeeRatio, _fundingPeriod, _fee, _spreadLimit, _maxPriceImpact, _partialLiquidationRatio, _maxPriceSpread)) ++ updateFunding((lastBlock.timestamp + _fundingPeriod), 0, 0, 0, 0)) ++ updateBalance(0)) ++ [BooleanEntry(k_initialized, true), StringEntry(k_ora, _oracle), StringEntry(k_ora_key, _oracleKey), StringEntry(k_coordinatorAddress, _coordinator)])
715-
716-
717-
718-@Callable(i)
719-func setInitMarginRatio (_initMarginRatio) = if (if ((0 >= _initMarginRatio))
720- then true
721- else !(initialized()))
722- then throw("Invalid setInitMarginRatio parameters")
723- else updateSettings(_initMarginRatio, maintenanceMarginRatio(), liquidationFeeRatio(), fundingPeriodRaw(), fee(), spreadLimit(), maxPriceImpact(), partialLiquidationRatio(), maxPriceSpread())
724-
725-
726-
727-@Callable(i)
728-func decreasePosition (_amount,_leverage,_minBaseAssetAmount) = if (if (if (if (if ((0 >= _amount))
729- then true
730- else !(initialized()))
731- then true
732- else !(requireMoreMarginRatio(divd(DECIMAL_UNIT, _leverage), initMarginRatio(), true)))
733- then true
734- else !(requireOpenPosition(toString(i.caller))))
735- then true
736- else paused())
737- then throw("Invalid decreasePosition parameters")
738- else {
739- let $t03418734339 = getPosition(toString(i.caller))
740- let oldPositionSize = $t03418734339._1
741- let oldPositionMargin = $t03418734339._2
742- let oldPositionOpenNotional = $t03418734339._3
743- let oldPositionLstUpdCPF = $t03418734339._4
744- let _direction = if ((oldPositionSize > 0))
745- then DIR_SHORT
746- else DIR_LONG
747- let isAdd = (_direction == DIR_LONG)
748- let openNotional = muld(_amount, _leverage)
749- let $t03451234628 = getPositionNotionalAndUnrealizedPnl(toString(i.caller), PNL_OPTION_SPOT)
750- let oldPositionNotional = $t03451234628._1
751- let unrealizedPnl = $t03451234628._2
752- let $t03463437183 = if ((oldPositionNotional > openNotional))
753- then {
754- let $t03501135230 = swapInput(isAdd, openNotional)
755- let exchangedPositionSize = $t03501135230._1
756- let quoteAssetReserveAfter = $t03501135230._2
757- let baseAssetReserveAfter = $t03501135230._3
758- let totalPositionSizeAfter = $t03501135230._4
759- let cumulativeNotionalAfter = $t03501135230._5
760- let exchangedPositionSizeAbs = abs(exchangedPositionSize)
761- if (if ((_minBaseAssetAmount != 0))
762- then (_minBaseAssetAmount > exchangedPositionSizeAbs)
763- else false)
764- then throw(((("Too little base asset exchanged, got " + toString(exchangedPositionSizeAbs)) + " expected ") + toString(_minBaseAssetAmount)))
765- else {
766- let realizedPnl = divd(muld(unrealizedPnl, exchangedPositionSizeAbs), abs(oldPositionSize))
767- let $t03566735912 = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, realizedPnl)
768- let remainMargin = $t03566735912._1
769- let badDebt = $t03566735912._2
770- let fundingPayment = $t03566735912._3
771- let exchangedQuoteAssetAmount = openNotional
772- let unrealizedPnlAfter = (unrealizedPnl - realizedPnl)
773- let remainOpenNotional = if ((oldPositionSize > 0))
774- then ((oldPositionNotional - exchangedQuoteAssetAmount) - unrealizedPnlAfter)
775- else ((unrealizedPnlAfter + oldPositionNotional) - exchangedQuoteAssetAmount)
776- let newPositionSize = (oldPositionSize + exchangedPositionSize)
777- $Tuple11(newPositionSize, remainMargin, abs(remainOpenNotional), latestCumulativePremiumFraction(newPositionSize), baseAssetReserveAfter, quoteAssetReserveAfter, totalPositionSizeAfter, cumulativeNotionalAfter, (openInterestNotional() - openNotional), (totalLongPositionSize() - (if ((newPositionSize > 0))
778- then abs(exchangedPositionSize)
779- else 0)), (totalShortPositionSize() - (if ((0 > newPositionSize))
780- then abs(exchangedPositionSize)
781- else 0)))
782- }
783- }
784- else throw("Close position first")
785- let newPositionSize = $t03463437183._1
786- let newPositionRemainMargin = $t03463437183._2
787- let newPositionOpenNotional = $t03463437183._3
788- let newPositionLatestCPF = $t03463437183._4
789- let baseAssetReserveAfter = $t03463437183._5
790- let quoteAssetReserveAfter = $t03463437183._6
791- let totalPositionSizeAfter = $t03463437183._7
792- let cumulativeNotionalAfter = $t03463437183._8
793- let openInterestNotionalAfter = $t03463437183._9
794- let totalLongAfter = $t03463437183._10
795- let totalShortAfter = $t03463437183._11
796- let notifyNotional = invoke(minerAddress(), "notifyNotional", [toString(i.caller), newPositionOpenNotional], nil)
797- if ((notifyNotional == notifyNotional))
798- then (updatePosition(toString(i.caller), newPositionSize, newPositionRemainMargin, newPositionOpenNotional, newPositionLatestCPF) ++ updateAmm(quoteAssetReserveAfter, baseAssetReserveAfter, totalPositionSizeAfter, cumulativeNotionalAfter, openInterestNotionalAfter, totalLongAfter, totalShortAfter))
799- else throw("Strict value is not equal to itself.")
800- }
801-
802-
803-
804-@Callable(i)
805-func increasePosition (_direction,_leverage,_minBaseAssetAmount) = {
806- let _rawAmount = i.payments[0].amount
807- if (if (if (if (if (if (if ((_direction != DIR_LONG))
808- then (_direction != DIR_SHORT)
809- else false)
810- then true
811- else (0 >= _rawAmount))
812- then true
813- else !(initialized()))
814- then true
815- else (i.payments[0].assetId != quoteAsset()))
816- then true
817- else !(requireMoreMarginRatio(divd(DECIMAL_UNIT, _leverage), initMarginRatio(), true)))
818- then true
819- else paused())
820- then throw("Invalid increasePosition parameters")
821- else {
822- let feeAmount = muld(_rawAmount, fee())
823- let _amount = (_rawAmount - feeAmount)
824- let $t03830138453 = getPosition(toString(i.caller))
825- let oldPositionSize = $t03830138453._1
826- let oldPositionMargin = $t03830138453._2
827- let oldPositionOpenNotional = $t03830138453._3
828- let oldPositionLstUpdCPF = $t03830138453._4
829- let isNewPosition = (oldPositionSize == 0)
830- let isSameDirection = if ((oldPositionSize > 0))
831- then (_direction == DIR_LONG)
832- else (_direction == DIR_SHORT)
833- let expandExisting = if (!(isNewPosition))
834- then isSameDirection
835- else false
836- let isAdd = (_direction == DIR_LONG)
837- let $t03874241310 = if (if (isNewPosition)
838- then true
839- else expandExisting)
840- then {
841- let openNotional = muld(_amount, _leverage)
842- let $t03916639372 = swapInput(isAdd, openNotional)
843- let amountBaseAssetBought = $t03916639372._1
844- let quoteAssetReserveAfter = $t03916639372._2
845- let baseAssetReserveAfter = $t03916639372._3
846- let totalPositionSizeAfter = $t03916639372._4
847- let cumulativeNotionalAfter = $t03916639372._5
848- if (if ((_minBaseAssetAmount != 0))
849- then (_minBaseAssetAmount > abs(amountBaseAssetBought))
850- else false)
851- then throw(((("Limit error: " + toString(abs(amountBaseAssetBought))) + " < ") + toString(_minBaseAssetAmount)))
852- else {
853- let newPositionSize = (oldPositionSize + amountBaseAssetBought)
854- let increaseMarginRequirement = divd(openNotional, _leverage)
855- let $t03975339992 = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, increaseMarginRequirement)
856- let remainMargin = $t03975339992._1
857- let x1 = $t03975339992._2
858- let x2 = $t03975339992._3
859- if (!(requireNotOverSpreadLimit(quoteAssetReserveAfter, baseAssetReserveAfter)))
860- then throw("Over max spread limit")
861- else $Tuple11(newPositionSize, remainMargin, (oldPositionOpenNotional + openNotional), latestCumulativePremiumFraction(newPositionSize), baseAssetReserveAfter, quoteAssetReserveAfter, totalPositionSizeAfter, cumulativeNotionalAfter, (openInterestNotional() + openNotional), (totalLongPositionSize() + (if ((newPositionSize > 0))
862- then abs(amountBaseAssetBought)
863- else 0)), (totalShortPositionSize() + (if ((0 > newPositionSize))
864- then abs(amountBaseAssetBought)
865- else 0)))
866- }
867- }
868- else {
869- let openNotional = muld(_amount, _leverage)
870- let $t04100341119 = getPositionNotionalAndUnrealizedPnl(toString(i.caller), PNL_OPTION_SPOT)
871- let oldPositionNotional = $t04100341119._1
872- let unrealizedPnl = $t04100341119._2
873- if ((oldPositionNotional > openNotional))
874- then throw("Use decreasePosition to decrease position size")
875- else throw("Close position first")
876- }
877- let newPositionSize = $t03874241310._1
878- let newPositionRemainMargin = $t03874241310._2
879- let newPositionOpenNotional = $t03874241310._3
880- let newPositionLatestCPF = $t03874241310._4
881- let baseAssetReserveAfter = $t03874241310._5
882- let quoteAssetReserveAfter = $t03874241310._6
883- let totalPositionSizeAfter = $t03874241310._7
884- let cumulativeNotionalAfter = $t03874241310._8
885- let openInterestNotionalAfter = $t03874241310._9
886- let totalLongAfter = $t03874241310._10
887- let totalShortAfter = $t03874241310._11
888- let feeToStakers = (feeAmount / 2)
889- let feeToInsurance = (feeAmount - feeToStakers)
890- let stake = invoke(quoteAssetStaking(), "lockNeutrinoSP", [toString(stakingAddress()), ALL_FEES], [AttachedPayment(quoteAsset(), _amount)])
891- if ((stake == stake))
892- then {
893- let depositInsurance = invoke(insuranceAddress(), "deposit", nil, [AttachedPayment(quoteAsset(), feeToInsurance)])
894- if ((depositInsurance == depositInsurance))
895- then {
896- let notifyFee = invoke(minerAddress(), "notifyFees", [toString(i.caller), feeAmount], nil)
897- if ((notifyFee == notifyFee))
898- then {
899- let notifyNotional = invoke(minerAddress(), "notifyNotional", [toString(i.caller), newPositionOpenNotional], nil)
900- if ((notifyNotional == notifyNotional))
901- then (((updatePosition(toString(i.caller), newPositionSize, newPositionRemainMargin, newPositionOpenNotional, newPositionLatestCPF) ++ updateAmm(quoteAssetReserveAfter, baseAssetReserveAfter, totalPositionSizeAfter, cumulativeNotionalAfter, openInterestNotionalAfter, totalLongAfter, totalShortAfter)) ++ transferFee(feeToStakers)) ++ updateBalance((cbalance() + _amount)))
902- else throw("Strict value is not equal to itself.")
903- }
904- else throw("Strict value is not equal to itself.")
905- }
906- else throw("Strict value is not equal to itself.")
907- }
908- else throw("Strict value is not equal to itself.")
909- }
910- }
911-
912-
913-
914-@Callable(i)
915-func addMargin () = {
916- let _rawAmount = i.payments[0].amount
917- if (if (if (if ((i.payments[0].assetId != quoteAsset()))
918- then true
919- else !(requireOpenPosition(toString(i.caller))))
920- then true
921- else !(initialized()))
922- then true
923- else paused())
924- then throw("Invalid addMargin parameters")
925- else {
926- let feeAmount = muld(_rawAmount, fee())
927- let _amount = (_rawAmount - feeAmount)
928- let $t04286643018 = getPosition(toString(i.caller))
929- let oldPositionSize = $t04286643018._1
930- let oldPositionMargin = $t04286643018._2
931- let oldPositionOpenNotional = $t04286643018._3
932- let oldPositionLstUpdCPF = $t04286643018._4
933- let feeToStakers = (feeAmount / 2)
934- let feeToInsurance = (feeAmount - feeToStakers)
935- let stake = invoke(quoteAssetStaking(), "lockNeutrinoSP", [toString(stakingAddress()), ALL_FEES], [AttachedPayment(quoteAsset(), _amount)])
936- if ((stake == stake))
937- then {
938- let depositInsurance = invoke(insuranceAddress(), "deposit", nil, [AttachedPayment(quoteAsset(), feeToInsurance)])
939- if ((depositInsurance == depositInsurance))
940- then {
941- let notifyFee = invoke(minerAddress(), "notifyFees", [toString(i.caller), feeAmount], nil)
942- if ((notifyFee == notifyFee))
943- then ((updatePosition(toString(i.caller), oldPositionSize, (oldPositionMargin + _amount), oldPositionOpenNotional, oldPositionLstUpdCPF) ++ transferFee(feeToStakers)) ++ updateBalance((cbalance() + _amount)))
944- else throw("Strict value is not equal to itself.")
945- }
946- else throw("Strict value is not equal to itself.")
947- }
948- else throw("Strict value is not equal to itself.")
949- }
950- }
951-
952-
953-
954-@Callable(i)
955-func removeMargin (_amount) = if (if (if (if ((0 >= _amount))
956- then true
957- else !(requireOpenPosition(toString(i.caller))))
958- then true
959- else !(initialized()))
960- then true
961- else paused())
962- then throw("Invalid removeMargin parameters")
963- else {
964- let $t04406744219 = getPosition(toString(i.caller))
965- let oldPositionSize = $t04406744219._1
966- let oldPositionMargin = $t04406744219._2
967- let oldPositionOpenNotional = $t04406744219._3
968- let oldPositionLstUpdCPF = $t04406744219._4
969- let marginDelta = -(_amount)
970- let $t04425644435 = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, marginDelta)
971- let remainMargin = $t04425644435._1
972- let badDebt = $t04425644435._2
973- if ((badDebt != 0))
974- then throw("Invalid removed margin amount")
975- else {
976- let marginRatio = calcMarginRatio(remainMargin, badDebt, oldPositionOpenNotional)
977- if (!(requireMoreMarginRatio(marginRatio, initMarginRatio(), true)))
978- then throw(((("Too much margin removed: " + toString(marginRatio)) + " < ") + toString(initMarginRatio())))
979- else {
980- let unstake = invoke(quoteAssetStaking(), "unlockNeutrino", [_amount, toBase58String(quoteAsset())], nil)
981- if ((unstake == unstake))
982- then ((updatePosition(toString(i.caller), oldPositionSize, remainMargin, oldPositionOpenNotional, latestCumulativePremiumFraction(oldPositionSize)) ++ withdraw(i.caller, _amount)) ++ updateBalance((cbalance() - _amount)))
983- else throw("Strict value is not equal to itself.")
984- }
985- }
986- }
987-
988-
989-
990-@Callable(i)
991-func closePosition () = if (if (if (!(requireOpenPosition(toString(i.caller))))
992- then true
993- else !(initialized()))
994- then true
995- else paused())
996- then throw("Invalid closePosition parameters")
997- else {
998- let $t04553145921 = internalClosePosition(toString(i.caller), true)
999- let x1 = $t04553145921._1
1000- let positionBadDebt = $t04553145921._2
1001- let realizedPnl = $t04553145921._3
1002- let marginToVault = $t04553145921._4
1003- let quoteAssetReserveAfter = $t04553145921._5
1004- let baseAssetReserveAfter = $t04553145921._6
1005- let totalPositionSizeAfter = $t04553145921._7
1006- let cumulativeNotionalAfter = $t04553145921._8
1007- let openInterestNotionalAfter = $t04553145921._9
1008- let x2 = $t04553145921._10
1009- let totalLongAfter = $t04553145921._11
1010- let totalShortAfter = $t04553145921._12
1011- if ((positionBadDebt > 0))
1012- then throw("Unable to close position with bad debt")
1013- else {
1014- let withdrawAmount = abs(marginToVault)
1015- let ammBalance = (cbalance() - withdrawAmount)
1016- let $t04613046272 = if ((0 > ammBalance))
1017- then $Tuple2(0, abs(ammBalance))
1018- else $Tuple2(ammBalance, 0)
1019- let ammNewBalance = $t04613046272._1
1020- let getFromInsurance = $t04613046272._2
1021- let x = if ((getFromInsurance > 0))
1022- then {
1023- let withdrawInsurance = invoke(insuranceAddress(), "withdraw", [getFromInsurance], nil)
1024- if ((withdrawInsurance == withdrawInsurance))
1025- then nil
1026- else throw("Strict value is not equal to itself.")
1027- }
1028- else nil
1029- if ((x == x))
1030- then {
1031- let unstake = invoke(quoteAssetStaking(), "unlockNeutrino", [(withdrawAmount - getFromInsurance), toBase58String(quoteAsset())], nil)
1032- if ((unstake == unstake))
1033- then {
1034- let notifyNotional = invoke(minerAddress(), "notifyNotional", [toString(i.caller), 0], nil)
1035- if ((notifyNotional == notifyNotional))
1036- then (((deletePosition(toString(i.caller)) ++ updateAmm(quoteAssetReserveAfter, baseAssetReserveAfter, totalPositionSizeAfter, cumulativeNotionalAfter, openInterestNotionalAfter, totalLongAfter, totalShortAfter)) ++ withdraw(i.caller, withdrawAmount)) ++ updateBalance(ammNewBalance))
1037- else throw("Strict value is not equal to itself.")
1038- }
1039- else throw("Strict value is not equal to itself.")
1040- }
1041- else throw("Strict value is not equal to itself.")
1042- }
1043- }
1044-
1045-
1046-
1047-@Callable(i)
1048-func liquidate (_trader) = {
1049- let spotMarginRatio = getMarginRatioByOption(_trader, PNL_OPTION_SPOT)
1050- let marginRatio = if (isOverFluctuationLimit())
1051- then {
1052- let oracleMarginRatio = getMarginRatioByOption(_trader, PNL_OPTION_ORACLE)
1053- vmax(spotMarginRatio, oracleMarginRatio)
1054- }
1055- else spotMarginRatio
1056- if (if (if (if (!(requireMoreMarginRatio(marginRatio, maintenanceMarginRatio(), false)))
1057- then true
1058- else !(requireOpenPosition(_trader)))
1059- then true
1060- else !(initialized()))
1061- then true
1062- else paused())
1063- then throw("Unable to liquidate")
1064- else if (if (if ((spotMarginRatio > liquidationFeeRatio()))
1065- then (partialLiquidationRatio() > 0)
1066- else false)
1067- then (DECIMAL_UNIT > partialLiquidationRatio())
1068- else false)
1069- then {
1070- let $t04837348523 = getPosition(_trader)
1071- let oldPositionSize = $t04837348523._1
1072- let oldPositionMargin = $t04837348523._2
1073- let oldPositionOpenNotional = $t04837348523._3
1074- let oldPositionLstUpdCPF = $t04837348523._4
1075- let _direction = if ((oldPositionSize > 0))
1076- then DIR_SHORT
1077- else DIR_LONG
1078- let isAdd = (_direction == DIR_LONG)
1079- let exchangedQuoteAssetAmount = getPartialLiquidationAmount(_trader, oldPositionSize)
1080- let $t04874848852 = getPositionNotionalAndUnrealizedPnl(_trader, PNL_OPTION_SPOT)
1081- let oldPositionNotional = $t04874848852._1
1082- let unrealizedPnl = $t04874848852._2
1083- let $t04886049150 = swapInput(isAdd, exchangedQuoteAssetAmount)
1084- let exchangedPositionSize = $t04886049150._1
1085- let quoteAssetReserveAfter = $t04886049150._2
1086- let baseAssetReserveAfter = $t04886049150._3
1087- let totalPositionSizeAfter = $t04886049150._4
1088- let cumulativeNotionalAfter = $t04886049150._5
1089- let realizedPnl = divd(muld(unrealizedPnl, abs(exchangedPositionSize)), abs(oldPositionSize))
1090- let $t04925749490 = calcRemainMarginWithFundingPayment(oldPositionSize, oldPositionMargin, oldPositionLstUpdCPF, realizedPnl)
1091- let remainMargin = $t04925749490._1
1092- let badDebt = $t04925749490._2
1093- let fundingPayment = $t04925749490._3
1094- let unrealizedPnlAfter = (unrealizedPnl - realizedPnl)
1095- let remainOpenNotional = if ((oldPositionSize > 0))
1096- then ((oldPositionNotional - exchangedQuoteAssetAmount) - unrealizedPnlAfter)
1097- else ((unrealizedPnlAfter + oldPositionNotional) - exchangedQuoteAssetAmount)
1098- let liquidationPenalty = muld(exchangedQuoteAssetAmount, liquidationFeeRatio())
1099- let feeToLiquidator = (liquidationPenalty / 2)
1100- let feeToInsurance = (liquidationPenalty - feeToLiquidator)
1101- let newPositionMargin = (remainMargin - liquidationPenalty)
1102- let newPositionSize = (oldPositionSize + exchangedPositionSize)
1103- let newPositionOpenNotional = abs(remainOpenNotional)
1104- let newPositionLstUpdCPF = latestCumulativePremiumFraction(newPositionSize)
1105- let openInterestNotionalAfter = (openInterestNotional() - exchangedQuoteAssetAmount)
1106- let ammBalance = (cbalance() - liquidationPenalty)
1107- let $t05066350806 = if ((0 > ammBalance))
1108- then $Tuple2(0, abs(ammBalance))
1109- else $Tuple2(ammBalance, 0)
1110- let newAmmBalance = $t05066350806._1
1111- let takeFromInsurance = $t05066350806._2
1112- let x = if ((takeFromInsurance > 0))
1113- then {
1114- let withdrawInsurance = invoke(insuranceAddress(), "withdraw", [takeFromInsurance], nil)
1115- if ((withdrawInsurance == withdrawInsurance))
1116- then nil
1117- else throw("Strict value is not equal to itself.")
1118- }
1119- else nil
1120- if ((x == x))
1121- then {
1122- let unstake = invoke(quoteAssetStaking(), "unlockNeutrino", [(liquidationPenalty - takeFromInsurance), toBase58String(quoteAsset())], nil)
1123- if ((unstake == unstake))
1124- then {
1125- let depositInsurance = invoke(insuranceAddress(), "deposit", nil, [AttachedPayment(quoteAsset(), feeToInsurance)])
1126- if ((depositInsurance == depositInsurance))
1127- then {
1128- let notifyNotional = invoke(minerAddress(), "notifyNotional", [_trader, newPositionOpenNotional], nil)
1129- if ((notifyNotional == notifyNotional))
1130- then (((updatePosition(_trader, newPositionSize, newPositionMargin, newPositionOpenNotional, newPositionLstUpdCPF) ++ updateAmm(quoteAssetReserveAfter, baseAssetReserveAfter, totalPositionSizeAfter, cumulativeNotionalAfter, openInterestNotionalAfter, (totalLongPositionSize() - (if ((newPositionSize > 0))
1131- then abs(exchangedPositionSize)
1132- else 0)), (totalShortPositionSize() - (if ((0 > newPositionSize))
1133- then abs(exchangedPositionSize)
1134- else 0)))) ++ withdraw(i.caller, feeToLiquidator)) ++ updateBalance(newAmmBalance))
1135- else throw("Strict value is not equal to itself.")
1136- }
1137- else throw("Strict value is not equal to itself.")
1138- }
1139- else throw("Strict value is not equal to itself.")
1140- }
1141- else throw("Strict value is not equal to itself.")
1142- }
1143- else {
1144- let $t05226252717 = internalClosePosition(_trader, false)
1145- let x1 = $t05226252717._1
1146- let badDebt = $t05226252717._2
1147- let x2 = $t05226252717._3
1148- let x3 = $t05226252717._4
1149- let quoteAssetReserveAfter = $t05226252717._5
1150- let baseAssetReserveAfter = $t05226252717._6
1151- let totalPositionSizeAfter = $t05226252717._7
1152- let cumulativeNotionalAfter = $t05226252717._8
1153- let openInterestNotionalAfter = $t05226252717._9
1154- let exchangedQuoteAssetAmount = $t05226252717._10
1155- let totalLongAfter = $t05226252717._11
1156- let totalShortAfter = $t05226252717._12
1157- let liquidationPenalty = muld(exchangedQuoteAssetAmount, liquidationFeeRatio())
1158- let feeToLiquidator = (liquidationPenalty / 2)
1159- let feeToInsurance = (liquidationPenalty - feeToLiquidator)
1160- let ammBalance = (cbalance() - liquidationPenalty)
1161- let $t05312953272 = if ((0 > ammBalance))
1162- then $Tuple2(0, abs(ammBalance))
1163- else $Tuple2(ammBalance, 0)
1164- let newAmmBalance = $t05312953272._1
1165- let takeFromInsurance = $t05312953272._2
1166- let x = if ((takeFromInsurance > 0))
1167- then {
1168- let withdrawInsurance = invoke(insuranceAddress(), "withdraw", [takeFromInsurance], nil)
1169- if ((withdrawInsurance == withdrawInsurance))
1170- then nil
1171- else throw("Strict value is not equal to itself.")
1172- }
1173- else nil
1174- if ((x == x))
1175- then {
1176- let unstake = invoke(quoteAssetStaking(), "unlockNeutrino", [(liquidationPenalty - takeFromInsurance), toBase58String(quoteAsset())], nil)
1177- if ((unstake == unstake))
1178- then {
1179- let depositInsurance = invoke(insuranceAddress(), "deposit", nil, [AttachedPayment(quoteAsset(), feeToInsurance)])
1180- if ((depositInsurance == depositInsurance))
1181- then {
1182- let notifyNotional = invoke(minerAddress(), "notifyNotional", [_trader, 0], nil)
1183- if ((notifyNotional == notifyNotional))
1184- then (((deletePosition(_trader) ++ updateAmm(quoteAssetReserveAfter, baseAssetReserveAfter, totalPositionSizeAfter, cumulativeNotionalAfter, openInterestNotionalAfter, totalLongAfter, totalShortAfter)) ++ withdraw(i.caller, feeToLiquidator)) ++ updateBalance(newAmmBalance))
1185- else throw("Strict value is not equal to itself.")
1186- }
1187- else throw("Strict value is not equal to itself.")
1188- }
1189- else throw("Strict value is not equal to itself.")
1190- }
1191- else throw("Strict value is not equal to itself.")
1192- }
1193- }
1194-
1195-
1196-
1197-@Callable(i)
1198-func payFunding () = {
1199- let fundingBlockTimestamp = nextFundingBlockTimestamp()
1200- if (if (if ((fundingBlockTimestamp > lastBlock.timestamp))
1201- then true
1202- else !(initialized()))
1203- then true
1204- else paused())
1205- then throw(((("Invalid funding block timestamp: " + toString(lastBlock.timestamp)) + " < ") + toString(fundingBlockTimestamp)))
1206- else {
1207- let underlyingPrice = getOracleTwapPrice()
1208- let spotTwapPrice = getTwapSpotPrice()
1209- let premium = (spotTwapPrice - underlyingPrice)
1210- let $t05486056195 = if (if ((totalShortPositionSize() == 0))
1211- then true
1212- else (totalLongPositionSize() == 0))
1213- then $Tuple2(0, 0)
1214- else if ((0 > premium))
1215- then {
1216- let shortPremiumFraction = divd(muld(premium, fundingPeriodDecimal()), ONE_DAY)
1217- let longPremiumFraction = divd(muld(shortPremiumFraction, totalShortPositionSize()), totalLongPositionSize())
1218- $Tuple2(shortPremiumFraction, longPremiumFraction)
1219- }
1220- else {
1221- let longPremiumFraction = divd(muld(premium, fundingPeriodDecimal()), ONE_DAY)
1222- let shortPremiumFraction = divd(muld(longPremiumFraction, totalLongPositionSize()), totalShortPositionSize())
1223- $Tuple2(shortPremiumFraction, longPremiumFraction)
1224- }
1225- let shortPremiumFraction = $t05486056195._1
1226- let longPremiumFraction = $t05486056195._2
1227- updateFunding((fundingBlockTimestamp + fundingPeriodSeconds()), (latestLongCumulativePremiumFraction() + longPremiumFraction), (latestShortCumulativePremiumFraction() + shortPremiumFraction), divd(longPremiumFraction, underlyingPrice), divd(shortPremiumFraction, underlyingPrice))
1228- }
1229- }
1230-
1231-
1232-
1233-@Callable(i)
1234-func v_get (_trader) = {
1235- let $t05657056630 = internalClosePosition(_trader, false)
1236- let x1 = $t05657056630._1
1237- let x2 = $t05657056630._2
1238- let x3 = $t05657056630._3
1239- let x4 = $t05657056630._4
1240- throw((((s(x2) + s(x3)) + s(x4)) + s(getMarginRatio(_trader))))
1241- }
1242-
1243-
1244-
1245-@Callable(i)
1246-func view_calcRemainMarginWithFundingPayment (_trader) = {
1247- let $t05677756888 = getPosition(_trader)
1248- let positionSize = $t05677756888._1
1249- let positionMargin = $t05677756888._2
1250- let pon = $t05677756888._3
1251- let positionLstUpdCPF = $t05677756888._4
1252- let $t05689356994 = getPositionNotionalAndUnrealizedPnl(_trader, PNL_OPTION_SPOT)
1253- let positionNotional = $t05689356994._1
1254- let unrealizedPnl = $t05689356994._2
1255- let $t05699957181 = calcRemainMarginWithFundingPayment(positionSize, positionMargin, positionLstUpdCPF, unrealizedPnl)
1256- let remainMargin = $t05699957181._1
1257- let badDebt = $t05699957181._2
1258- let fundingPayment = $t05699957181._3
1259- throw((((((s(remainMargin) + s(fundingPayment)) + s(getMarginRatio(_trader))) + s(unrealizedPnl)) + s(badDebt)) + s(positionNotional)))
1260- }
1261-
1262-
1263-
1264-@Callable(i)
1265-func forceMoveAsset (_trader,_amount) = if (if ((addressFromPublicKey(adminPublicKey()) != i.caller))
1266- then true
1267- else (0 > _amount))
1268- then throw("Invalid forceMoveAsset parameters")
1269- else {
1270- let unstake = invoke(quoteAssetStaking(), "unlockNeutrino", [_amount, toBase58String(quoteAsset())], nil)
1271- if ((unstake == unstake))
1272- then (withdraw(addressFromStringValue(_trader), _amount) ++ updateBalance((cbalance() - _amount)))
1273- else throw("Strict value is not equal to itself.")
1274- }
1275-
1276-
1277-@Verifier(tx)
1278-func verify () = sigVerify(tx.bodyBytes, tx.proofs[0], adminPublicKey())
1279-
1+# no script

github/deemru/w8io/3ef1775 
86.81 ms