52 | | - | let adminPubKey1 = getAdminPub(keyAdminPubKey1) |
---|
53 | | - | |
---|
54 | | - | let adminPubKey2 = getAdminPub(keyAdminPubKey2) |
---|
55 | | - | |
---|
56 | | - | let adminPubKey3 = getAdminPub(keyAdminPubKey3) |
---|
57 | | - | |
---|
58 | | - | let admStartStop = base58'Kn7NpzaG12dLZgcHf2ipUftU6hbJygmrhFqQYE4B7ZK' |
---|
59 | | - | |
---|
60 | | - | let admStaking = base58'Kn7NpzaG12dLZgcHf2ipUftU6hbJygmrhFqQYE4B7ZK' |
---|
61 | | - | |
---|
62 | | - | let walletAddress = Address(base58'3NAGTtZz6WpupSN89NZD5rMZwwziZEg4Kx4') |
---|
63 | | - | |
---|
64 | | - | let USDN = base58'8UrfDVd5GreeUwm7uPk7eYz1eMv376kzR52C6sANPkwS' |
---|
65 | | - | |
---|
66 | | - | let EURN = base58'ECBCkHS68DckpBrzLeoRgYbFg7sCVqR176mPqbXsj9pA' |
---|
67 | | - | |
---|
68 | | - | let stakingAssets = [toBase58String(USDN), toBase58String(EURN)] |
---|
69 | | - | |
---|
70 | | - | let stakingUSDNNSBTAddress = Address(fromBase58String(valueOrErrorMessage(getString(oracle, keyUSDNNSBTAddress), "no usdn staking address"))) |
---|
71 | | - | |
---|
72 | | - | let stakingEURNAddress = Address(fromBase58String(valueOrErrorMessage(getString(oracle, keyEURNAddress), "no usdn staking address"))) |
---|
73 | | - | |
---|
74 | | - | let isActive = getBooleanValue(this, kActive) |
---|
75 | | - | |
---|
76 | | - | let strAssetIdA = getStringValue(this, kAssetIdA) |
---|
77 | | - | |
---|
78 | | - | let strAssetIdB = getStringValue(this, kAssetIdB) |
---|
79 | | - | |
---|
80 | | - | let assetIdA = if ((strAssetIdA == "WAVES")) |
---|
81 | | - | then unit |
---|
82 | | - | else fromBase58String(strAssetIdA) |
---|
83 | | - | |
---|
84 | | - | let assetIdB = if ((strAssetIdB == "WAVES")) |
---|
85 | | - | then unit |
---|
86 | | - | else fromBase58String(strAssetIdB) |
---|
87 | | - | |
---|
88 | | - | let assetNameA = match assetIdA { |
---|
89 | | - | case id: ByteVector => |
---|
90 | | - | value(assetInfo(id)).name |
---|
91 | | - | case waves: Unit => |
---|
92 | | - | "WAVES" |
---|
93 | | - | case _ => |
---|
94 | | - | throw("Match error") |
---|
95 | | - | } |
---|
96 | | - | |
---|
97 | | - | let assetNameB = match assetIdB { |
---|
98 | | - | case id: ByteVector => |
---|
99 | | - | value(assetInfo(id)).name |
---|
100 | | - | case waves: Unit => |
---|
101 | | - | "WAVES" |
---|
102 | | - | case _ => |
---|
103 | | - | throw("Match error") |
---|
104 | | - | } |
---|
105 | | - | |
---|
106 | | - | let balanceA = getIntegerValue(this, kBalanceA) |
---|
107 | | - | |
---|
108 | | - | let balanceB = getIntegerValue(this, kBalanceB) |
---|
109 | | - | |
---|
110 | | - | let shareAssetId = fromBase58String(getStringValue(this, kShareAssetId)) |
---|
111 | | - | |
---|
112 | | - | let shareAssetSupply = getIntegerValue(this, kShareAssetSupply) |
---|
113 | | - | |
---|
114 | | - | let invariant = getIntegerValue(this, kInvariant) |
---|
115 | | - | |
---|
116 | | - | let fee = 500 |
---|
117 | | - | |
---|
118 | | - | let feeGovernance = 200 |
---|
119 | | - | |
---|
120 | | - | let feeScale6 = 1000000 |
---|
121 | | - | |
---|
122 | | - | let scale3 = 1000 |
---|
123 | | - | |
---|
124 | | - | let scale8 = 100000000 |
---|
125 | | - | |
---|
126 | | - | let scale12 = 1000000000000 |
---|
127 | | - | |
---|
128 | | - | let slippageScale3 = 1000 |
---|
129 | | - | |
---|
130 | | - | let digits8 = 8 |
---|
131 | | - | |
---|
132 | | - | let digits12 = 12 |
---|
133 | | - | |
---|
134 | | - | let dAppThreshold = 50 |
---|
135 | | - | |
---|
136 | | - | let dAppThresholdScale2 = 100 |
---|
137 | | - | |
---|
138 | | - | let exchangeRatioLimitMin = 90000000 |
---|
139 | | - | |
---|
140 | | - | let exchangeRatioLimitMax = 110000000 |
---|
141 | | - | |
---|
142 | | - | let alpha = 50 |
---|
143 | | - | |
---|
144 | | - | let alphaDigits = 2 |
---|
145 | | - | |
---|
146 | | - | let beta = 460000000000 |
---|
147 | | - | |
---|
148 | | - | func accountBalance (assetId) = match assetId { |
---|
149 | | - | case id: ByteVector => |
---|
150 | | - | assetBalance(this, id) |
---|
151 | | - | case waves: Unit => |
---|
152 | | - | wavesBalance(this).available |
---|
153 | | - | case _ => |
---|
154 | | - | throw("Match error") |
---|
155 | | - | } |
---|
156 | | - | |
---|
157 | | - | |
---|
158 | | - | func stakedAmount (assetId) = { |
---|
159 | | - | let stakedAmountCalculated = match assetId { |
---|
160 | | - | case aId: ByteVector => |
---|
161 | | - | if ((aId == USDN)) |
---|
162 | | - | then getInteger(stakingUSDNNSBTAddress, ((("rpd_balance_" + toBase58String(aId)) + "_") + toString(this))) |
---|
163 | | - | else if ((aId == EURN)) |
---|
164 | | - | then getInteger(stakingEURNAddress, ((("%s%s%s__stakingBalance__" + toBase58String(aId)) + "__") + toString(this))) |
---|
165 | | - | else 0 |
---|
166 | | - | case _: Unit => |
---|
167 | | - | 0 |
---|
168 | | - | case _ => |
---|
169 | | - | throw("Match error") |
---|
170 | | - | } |
---|
171 | | - | match stakedAmountCalculated { |
---|
172 | | - | case i: Int => |
---|
173 | | - | i |
---|
174 | | - | case _ => |
---|
175 | | - | 0 |
---|
176 | | - | } |
---|
177 | | - | } |
---|
178 | | - | |
---|
179 | | - | |
---|
180 | | - | let stakedAmountA = stakedAmount(assetIdA) |
---|
181 | | - | |
---|
182 | | - | let stakedAmountB = stakedAmount(assetIdB) |
---|
183 | | - | |
---|
184 | | - | let availableBalanceA = (balanceA - stakedAmountA) |
---|
185 | | - | |
---|
186 | | - | let availableBalanceB = (balanceB - stakedAmountB) |
---|
187 | | - | |
---|
188 | | - | let accountBalanceWithStakedA = (accountBalance(assetIdA) + stakedAmountA) |
---|
189 | | - | |
---|
190 | | - | let accountBalanceWithStakedB = (accountBalance(assetIdB) + stakedAmountB) |
---|
191 | | - | |
---|
192 | | - | let hasEnoughBalance = if ((accountBalanceWithStakedA >= balanceA)) |
---|
193 | | - | then (accountBalanceWithStakedB >= balanceB) |
---|
194 | | - | else false |
---|
195 | | - | |
---|
196 | | - | func skewness (x,y) = ((fraction(scale12, x, y) + fraction(scale12, y, x)) / 2) |
---|
197 | | - | |
---|
198 | | - | |
---|
199 | | - | func invariantCalc (x,y) = { |
---|
200 | | - | let sk = skewness(x, y) |
---|
201 | | - | (toInt(fraction(toBigInt((x + y)), toBigInt(scale12), pow(toBigInt(sk), digits12, toBigInt(alpha), alphaDigits, digits12, CEILING))) + (2 * toInt(fraction(pow(fraction(toBigInt(x), toBigInt(y), toBigInt(scale8)), 0, toBigInt(5), 1, (digits8 / 2), DOWN), pow(toBigInt((sk - beta)), digits12, toBigInt(alpha), alphaDigits, digits12, DOWN), toBigInt(scale12))))) |
---|
202 | | - | } |
---|
203 | | - | |
---|
204 | | - | |
---|
205 | | - | func calculateSendAmount (amountToSendEstimated,minTokenReceiveAmount,tokenReceiveAmount,tokenId) = { |
---|
206 | | - | let slippageValue = (scale8 - ((scale8 * 1) / 10000000)) |
---|
207 | | - | let deltaBetweenMaxAndMinSendValue = (amountToSendEstimated - minTokenReceiveAmount) |
---|
208 | | - | let x = (balanceA + tokenReceiveAmount) |
---|
209 | | - | let y = (balanceB + tokenReceiveAmount) |
---|
210 | | - | let invariantNew = if ((tokenId == assetIdA)) |
---|
211 | | - | then invariantCalc(x, (balanceB - amountToSendEstimated)) |
---|
212 | | - | else if ((tokenId == assetIdB)) |
---|
213 | | - | then invariantCalc((balanceA - amountToSendEstimated), y) |
---|
214 | | - | else throw("Wrong asset in payment") |
---|
215 | | - | let invariantEstimatedRatio = fraction(scale8, invariant, invariantNew) |
---|
216 | | - | func getStepAmount (acc,step) = if ((acc == -1)) |
---|
217 | | - | then { |
---|
218 | | - | let amountToSend = (amountToSendEstimated - ((step * deltaBetweenMaxAndMinSendValue) / 5)) |
---|
219 | | - | let stepInvariant = if ((tokenId == assetIdA)) |
---|
220 | | - | then invariantCalc(x, (balanceB - amountToSend)) |
---|
221 | | - | else invariantCalc((balanceA - amountToSend), y) |
---|
222 | | - | if ((stepInvariant > invariant)) |
---|
223 | | - | then amountToSend |
---|
224 | | - | else -1 |
---|
225 | | - | } |
---|
226 | | - | else acc |
---|
227 | | - | |
---|
228 | | - | let stepAmount = { |
---|
229 | | - | let $l = [1, 2, 3, 4, 5] |
---|
230 | | - | let $s = size($l) |
---|
231 | | - | let $acc0 = -1 |
---|
232 | | - | func $f0_1 ($a,$i) = if (($i >= $s)) |
---|
233 | | - | then $a |
---|
234 | | - | else getStepAmount($a, $l[$i]) |
---|
235 | | - | |
---|
236 | | - | func $f0_2 ($a,$i) = if (($i >= $s)) |
---|
237 | | - | then $a |
---|
238 | | - | else throw("List size exceeds 5") |
---|
239 | | - | |
---|
240 | | - | $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5) |
---|
241 | | - | } |
---|
242 | | - | if ((0 > stepAmount)) |
---|
243 | | - | then throw("something went wrong while working with amountToSend") |
---|
244 | | - | else if (if ((invariantEstimatedRatio > slippageValue)) |
---|
245 | | - | then (invariantNew > invariant) |
---|
246 | | - | else false) |
---|
247 | | - | then amountToSendEstimated |
---|
248 | | - | else stepAmount |
---|
249 | | - | } |
---|
250 | | - | |
---|
251 | | - | |
---|
252 | | - | func getAssetInfo (assetId) = match assetId { |
---|
253 | | - | case id: ByteVector => |
---|
254 | | - | let stringId = toBase58String(id) |
---|
255 | | - | let info = valueOrErrorMessage(assetInfo(id), (("Asset " + stringId) + " doesn't exist")) |
---|
256 | | - | $Tuple3(stringId, info.name, info.decimals) |
---|
257 | | - | case waves: Unit => |
---|
258 | | - | $Tuple3("WAVES", "WAVES", 8) |
---|
259 | | - | case _ => |
---|
260 | | - | throw("Match error") |
---|
261 | | - | } |
---|
262 | | - | |
---|
263 | | - | |
---|
264 | | - | func suspend (cause) = [BooleanEntry(kActive, false), StringEntry(kCause, cause)] |
---|
265 | | - | |
---|
266 | | - | |
---|
267 | | - | func throwIsActive () = throw("DApp is already active") |
---|
268 | | - | |
---|
269 | | - | |
---|
270 | | - | func throwIsInactive () = throw("DApp is inactive at this moment") |
---|
271 | | - | |
---|
272 | | - | |
---|
273 | | - | func throwOnlyAdmin () = throw("Only admin can call this function") |
---|
274 | | - | |
---|
275 | | - | |
---|
276 | | - | func throwAssets () = throw(((("Incorrect assets attached. Expected: " + strAssetIdA) + " and ") + strAssetIdB)) |
---|
277 | | - | |
---|
278 | | - | |
---|
279 | | - | func throwThreshold (threshold,amountA,amountB) = throw(((((((((("New balance in assets of the DApp is less than threshold " + toString(threshold)) + ": ") + toString(amountA)) + " ") + assetNameA) + ", ") + toString(amountB)) + " ") + assetNameB)) |
---|
280 | | - | |
---|
281 | | - | |
---|
282 | | - | func suspendSuspicious () = suspend(((((((((((((((("Suspicious state. Actual balances: " + toString(balanceA)) + " ") + assetNameA) + ", ") + toString(balanceB)) + " ") + assetNameB) + ". State: ") + toString(accountBalance(assetIdA))) + " ") + assetNameA) + ", ") + toString(accountBalance(assetIdB))) + " ") + assetNameB)) |
---|
283 | | - | |
---|
284 | | - | |
---|
285 | | - | func calcStakingFuncAndAddres (stake,assetId) = if (stake) |
---|
286 | | - | then if ((assetId == USDN)) |
---|
287 | | - | then $Tuple2("lockNeutrino", stakingUSDNNSBTAddress) |
---|
288 | | - | else $Tuple2("startStaking", stakingEURNAddress) |
---|
289 | | - | else if ((assetId == USDN)) |
---|
290 | | - | then $Tuple2("unlockNeutrino", stakingUSDNNSBTAddress) |
---|
291 | | - | else $Tuple2("stopStaking", stakingEURNAddress) |
---|
292 | | - | |
---|
293 | | - | |
---|
294 | | - | func calcStakingParams (stake,amount,assetId) = if (stake) |
---|
295 | | - | then { |
---|
296 | | - | let $t089218987 = calcStakingFuncAndAddres(stake, assetId) |
---|
297 | | - | let call = $t089218987._1 |
---|
298 | | - | let stakingAddr = $t089218987._2 |
---|
299 | | - | $Tuple4(call, stakingAddr, nil, [AttachedPayment(assetId, amount)]) |
---|
300 | | - | } |
---|
301 | | - | else { |
---|
302 | | - | let $t090739139 = calcStakingFuncAndAddres(stake, assetId) |
---|
303 | | - | let call = $t090739139._1 |
---|
304 | | - | let stakingAddr = $t090739139._2 |
---|
305 | | - | $Tuple4(call, stakingAddr, [amount, toBase58String(assetId)], nil) |
---|
306 | | - | } |
---|
307 | | - | |
---|
308 | | - | |
---|
309 | | - | @Callable(i) |
---|
310 | | - | func init () = { |
---|
311 | | - | let $t092449321 = $Tuple2(i.payments[0].amount, i.payments[0].assetId) |
---|
312 | | - | let pmtAmountA = $t092449321._1 |
---|
313 | | - | let pmtAssetIdA = $t092449321._2 |
---|
314 | | - | let $t093269403 = $Tuple2(i.payments[1].amount, i.payments[1].assetId) |
---|
315 | | - | let pmtAmountB = $t093269403._1 |
---|
316 | | - | let pmtAssetIdB = $t093269403._2 |
---|
317 | | - | let $t094089485 = getAssetInfo(pmtAssetIdA) |
---|
318 | | - | let pmtStrAssetIdA = $t094089485._1 |
---|
319 | | - | let pmtAssetNameA = $t094089485._2 |
---|
320 | | - | let pmtDecimalsA = $t094089485._3 |
---|
321 | | - | let $t094909567 = getAssetInfo(pmtAssetIdB) |
---|
322 | | - | let pmtStrAssetIdB = $t094909567._1 |
---|
323 | | - | let pmtAssetNameB = $t094909567._2 |
---|
324 | | - | let pmtDecimalsB = $t094909567._3 |
---|
325 | | - | if (isDefined(getBoolean(this, kActive))) |
---|
326 | | - | then throwIsActive() |
---|
327 | | - | else if ((pmtAssetIdA == pmtAssetIdB)) |
---|
328 | | - | then throw("Assets must be different") |
---|
329 | | - | else { |
---|
330 | | - | let shareName = ((("s" + take(pmtAssetNameA, 7)) + "_") + take(pmtAssetNameB, 7)) |
---|
331 | | - | let shareDescription = ((((("ShareToken of SwopFi protocol for " + pmtAssetNameA) + " and ") + pmtAssetNameB) + " at address ") + toString(this)) |
---|
332 | | - | let shareDecimals = ((pmtDecimalsA + pmtDecimalsB) / 2) |
---|
333 | | - | let shareInitialSupply = fraction(pow(pmtAmountA, pmtDecimalsA, 5, 1, pmtDecimalsA, DOWN), pow(pmtAmountB, pmtDecimalsB, 5, 1, pmtDecimalsB, DOWN), pow(10, 0, shareDecimals, 0, 0, DOWN)) |
---|
334 | | - | let shareIssue = Issue(shareName, shareDescription, shareInitialSupply, shareDecimals, true) |
---|
335 | | - | let shareIssueId = calculateAssetId(shareIssue) |
---|
336 | | - | let invariantCalculated = invariantCalc(pmtAmountA, pmtAmountB) |
---|
337 | | - | let stake1 = if (containsElement(stakingAssets, pmtStrAssetIdA)) |
---|
338 | | - | then invoke(this, "stakeUnstake", [true, pmtAmountA, pmtStrAssetIdA], nil) |
---|
339 | | - | else 0 |
---|
340 | | - | if ((stake1 == stake1)) |
---|
341 | | - | then { |
---|
342 | | - | let stake2 = if (containsElement(stakingAssets, pmtStrAssetIdB)) |
---|
343 | | - | then invoke(this, "stakeUnstake", [true, pmtAmountB, pmtStrAssetIdB], nil) |
---|
344 | | - | else 0 |
---|
345 | | - | if ((stake2 == stake2)) |
---|
346 | | - | then [StringEntry(kVersion, version), BooleanEntry(kActive, true), StringEntry(kAssetIdA, pmtStrAssetIdA), StringEntry(kAssetIdB, pmtStrAssetIdB), IntegerEntry(kBalanceA, pmtAmountA), IntegerEntry(kBalanceB, pmtAmountB), IntegerEntry(kInvariant, invariantCalculated), IntegerEntry(kFee, fee), IntegerEntry(kFeeScaleDelimiter, feeScale6), shareIssue, StringEntry(kShareAssetId, toBase58String(shareIssueId)), IntegerEntry(kShareAssetSupply, shareInitialSupply), ScriptTransfer(i.caller, shareInitialSupply, shareIssueId)] |
---|
347 | | - | else throw("Strict value is not equal to itself.") |
---|
348 | | - | } |
---|
349 | | - | else throw("Strict value is not equal to itself.") |
---|
350 | | - | } |
---|
351 | | - | } |
---|
352 | | - | |
---|
353 | | - | |
---|
354 | | - | |
---|
355 | | - | @Callable(i) |
---|
356 | | - | func replenishWithTwoTokens (slippageTolerance) = { |
---|
357 | | - | let pmtAssetIdA = i.payments[0].assetId |
---|
358 | | - | let pmtAssetIdB = i.payments[1].assetId |
---|
359 | | - | let pmtAmountA = i.payments[0].amount |
---|
360 | | - | let pmtAmountB = i.payments[1].amount |
---|
361 | | - | let $t01208312160 = getAssetInfo(pmtAssetIdA) |
---|
362 | | - | let pmtStrAssetIdA = $t01208312160._1 |
---|
363 | | - | let pmtAssetNameA = $t01208312160._2 |
---|
364 | | - | let pmtDecimalsA = $t01208312160._3 |
---|
365 | | - | let $t01216512359 = getAssetInfo(pmtAssetIdB) |
---|
366 | | - | let pmtStrAssetIdB = $t01216512359._1 |
---|
367 | | - | let pmtAssetNameB = $t01216512359._2 |
---|
368 | | - | let pmtDecimalsB = $t01216512359._3 |
---|
369 | | - | let tokenRatio = fraction(fraction(scale8, balanceA, pmtAmountA), scale3, fraction(scale8, balanceB, pmtAmountB)) |
---|
370 | | - | let ratioShareTokensInA = fraction(scale8, pmtAmountA, balanceA) |
---|
371 | | - | let ratioShareTokensInB = fraction(scale8, pmtAmountB, balanceB) |
---|
372 | | - | let shareTokenToPayAmount = fraction(min([ratioShareTokensInA, ratioShareTokensInB]), shareAssetSupply, scale8) |
---|
373 | | - | let invariantCalculated = invariantCalc((balanceA + pmtAmountA), (balanceB + pmtAmountB)) |
---|
374 | | - | if (!(isActive)) |
---|
375 | | - | then throwIsInactive() |
---|
376 | | - | else if (if ((0 > slippageTolerance)) |
---|
377 | | - | then true |
---|
378 | | - | else (slippageTolerance > 10)) |
---|
379 | | - | then throw("Slippage tolerance must be <= 1%") |
---|
380 | | - | else if ((size(i.payments) != 2)) |
---|
381 | | - | then throw("Two attached assets expected") |
---|
382 | | - | else if (if ((pmtAssetIdA != assetIdA)) |
---|
383 | | - | then true |
---|
384 | | - | else (pmtAssetIdB != assetIdB)) |
---|
385 | | - | then throwAssets() |
---|
386 | | - | else if (if ((((scale3 * (slippageScale3 - slippageTolerance)) / slippageScale3) > tokenRatio)) |
---|
387 | | - | then true |
---|
388 | | - | else (tokenRatio > ((scale3 * (slippageScale3 + slippageTolerance)) / slippageScale3))) |
---|
389 | | - | then throw("Incorrect assets amount: amounts must have the contract ratio") |
---|
390 | | - | else if ((shareTokenToPayAmount == 0)) |
---|
391 | | - | then throw("Too small amount to replenish") |
---|
392 | | - | else if (!(hasEnoughBalance)) |
---|
393 | | - | then ([ScriptTransfer(i.caller, pmtAmountA, pmtAssetIdA), ScriptTransfer(i.caller, pmtAmountB, pmtAssetIdB)] ++ suspendSuspicious()) |
---|
394 | | - | else { |
---|
395 | | - | let stake1 = if (containsElement(stakingAssets, pmtStrAssetIdA)) |
---|
396 | | - | then invoke(this, "stakeUnstake", [true, pmtAmountA, pmtStrAssetIdA], nil) |
---|
397 | | - | else 0 |
---|
398 | | - | if ((stake1 == stake1)) |
---|
399 | | - | then { |
---|
400 | | - | let stake2 = if (containsElement(stakingAssets, pmtStrAssetIdB)) |
---|
401 | | - | then invoke(this, "stakeUnstake", [true, pmtAmountB, pmtStrAssetIdB], nil) |
---|
402 | | - | else 0 |
---|
403 | | - | if ((stake2 == stake2)) |
---|
404 | | - | then [IntegerEntry(kBalanceA, (balanceA + pmtAmountA)), IntegerEntry(kBalanceB, (balanceB + pmtAmountB)), IntegerEntry(kShareAssetSupply, (shareAssetSupply + shareTokenToPayAmount)), IntegerEntry(kInvariant, invariantCalculated), Reissue(shareAssetId, shareTokenToPayAmount, true), ScriptTransfer(i.caller, shareTokenToPayAmount, shareAssetId)] |
---|
405 | | - | else throw("Strict value is not equal to itself.") |
---|
406 | | - | } |
---|
407 | | - | else throw("Strict value is not equal to itself.") |
---|
408 | | - | } |
---|
409 | | - | } |
---|
410 | | - | |
---|
411 | | - | |
---|
412 | | - | |
---|
413 | | - | @Callable(i) |
---|
414 | | - | func replenishWithOneToken (virtualSwapTokenPay,virtualSwapTokenGet) = { |
---|
415 | | - | let $t01465814733 = $Tuple2(i.payments[0].amount, i.payments[0].assetId) |
---|
416 | | - | let pmtAmount = $t01465814733._1 |
---|
417 | | - | let pmtAssetId = $t01465814733._2 |
---|
418 | | - | let $t01473814811 = getAssetInfo(pmtAssetId) |
---|
419 | | - | let pmtStrAssetId = $t01473814811._1 |
---|
420 | | - | let pmtAssetName = $t01473814811._2 |
---|
421 | | - | let pmtDecimals = $t01473814811._3 |
---|
422 | | - | let pmtMinThreshold = 5000000 |
---|
423 | | - | let thresholdValueForMinTolerance = 50000000 |
---|
424 | | - | let tolerance = if ((thresholdValueForMinTolerance > pmtAmount)) |
---|
425 | | - | then 100000 |
---|
426 | | - | else 1 |
---|
427 | | - | let slippageValueMinForReplenish = (scale8 - ((scale8 * tolerance) / 10000000)) |
---|
428 | | - | let slippageValueMaxForReplenish = (scale8 + ((scale8 * tolerance) / 10000000)) |
---|
429 | | - | let slippageValueMinForSwap = (scale8 - ((scale8 * 1) / 10000000)) |
---|
430 | | - | if (!(isActive)) |
---|
431 | | - | then throwIsInactive() |
---|
432 | | - | else if ((pmtMinThreshold > pmtAmount)) |
---|
433 | | - | then throw((((("Payment amount " + toString(pmtAmount)) + " does not exceed the minimum amount of ") + toString(pmtMinThreshold)) + " tokens")) |
---|
434 | | - | else if ((size(i.payments) != 1)) |
---|
435 | | - | then throw("One attached payment expected") |
---|
436 | | - | else if (!(hasEnoughBalance)) |
---|
437 | | - | then ([ScriptTransfer(i.caller, pmtAmount, pmtAssetId)] ++ suspendSuspicious()) |
---|
438 | | - | else if (if ((pmtAssetId != assetIdA)) |
---|
439 | | - | then (pmtAssetId != assetIdB) |
---|
440 | | - | else false) |
---|
441 | | - | then throwAssets() |
---|
442 | | - | else { |
---|
443 | | - | let $t01582316588 = if ((pmtAssetId == assetIdA)) |
---|
444 | | - | then $Tuple7((pmtAmount - virtualSwapTokenPay), virtualSwapTokenGet, (balanceA + virtualSwapTokenPay), (balanceB - virtualSwapTokenGet), invariantCalc((balanceA + pmtAmount), balanceB), (balanceA + pmtAmount), balanceB) |
---|
445 | | - | else $Tuple7(virtualSwapTokenGet, (pmtAmount - virtualSwapTokenPay), (balanceA - virtualSwapTokenGet), (balanceB + virtualSwapTokenPay), invariantCalc(balanceA, (balanceB + pmtAmount)), balanceA, (balanceB + pmtAmount)) |
---|
446 | | - | let virtualReplenishA = $t01582316588._1 |
---|
447 | | - | let virtualReplenishB = $t01582316588._2 |
---|
448 | | - | let balanceAfterSwapA = $t01582316588._3 |
---|
449 | | - | let balanceAfterSwapB = $t01582316588._4 |
---|
450 | | - | let invariantCalculated = $t01582316588._5 |
---|
451 | | - | let newBalanceA = $t01582316588._6 |
---|
452 | | - | let newBalanceB = $t01582316588._7 |
---|
453 | | - | let newBalanceEntry = if ((pmtAssetId == assetIdA)) |
---|
454 | | - | then IntegerEntry(kBalanceA, newBalanceA) |
---|
455 | | - | else IntegerEntry(kBalanceB, newBalanceB) |
---|
456 | | - | let invariantNew = invariantCalc(balanceAfterSwapA, balanceAfterSwapB) |
---|
457 | | - | let invariantEstimatedRatio = fraction(scale8, invariant, invariantNew) |
---|
458 | | - | let ratioVirtualBalanceToVirtualReplenish = (fraction((scale8 * scale8), balanceAfterSwapA, balanceAfterSwapB) / fraction(scale8, virtualReplenishA, virtualReplenishB)) |
---|
459 | | - | let dAppThresholdAmount = fraction((newBalanceA + newBalanceB), dAppThreshold, (2 * dAppThresholdScale2)) |
---|
460 | | - | if (if ((slippageValueMinForSwap >= invariantEstimatedRatio)) |
---|
461 | | - | then true |
---|
462 | | - | else (invariant > invariantNew)) |
---|
463 | | - | then throw("Incorrect virtualSwapTokenPay or virtualSwapTokenGet value") |
---|
464 | | - | else if (if ((slippageValueMinForReplenish > ratioVirtualBalanceToVirtualReplenish)) |
---|
465 | | - | then true |
---|
466 | | - | else (ratioVirtualBalanceToVirtualReplenish > slippageValueMaxForReplenish)) |
---|
467 | | - | then throw("Swap with virtualSwapTokenPay and virtualSwapTokenGet is possible, but ratio after virtual swap is incorrect") |
---|
468 | | - | else if (if ((dAppThresholdAmount > newBalanceA)) |
---|
469 | | - | then true |
---|
470 | | - | else (dAppThresholdAmount > newBalanceB)) |
---|
471 | | - | then throwThreshold(dAppThresholdAmount, newBalanceA, newBalanceB) |
---|
472 | | - | else { |
---|
473 | | - | let stake1 = if (containsElement(stakingAssets, pmtStrAssetId)) |
---|
474 | | - | then invoke(this, "stakeUnstake", [true, pmtAmount, pmtStrAssetId], nil) |
---|
475 | | - | else 0 |
---|
476 | | - | if ((stake1 == stake1)) |
---|
477 | | - | then { |
---|
478 | | - | let ratioShareTokensInA = fraction(virtualReplenishA, scale8, balanceAfterSwapA) |
---|
479 | | - | let ratioShareTokensInB = fraction(virtualReplenishB, scale8, balanceAfterSwapB) |
---|
480 | | - | let shareTokenToPayAmount = fraction(min([ratioShareTokensInA, ratioShareTokensInB]), shareAssetSupply, scale8) |
---|
481 | | - | [Reissue(shareAssetId, shareTokenToPayAmount, true), ScriptTransfer(i.caller, shareTokenToPayAmount, shareAssetId), IntegerEntry(kShareAssetSupply, (shareAssetSupply + shareTokenToPayAmount)), newBalanceEntry, IntegerEntry(kInvariant, invariantCalculated)] |
---|
482 | | - | } |
---|
483 | | - | else throw("Strict value is not equal to itself.") |
---|
484 | | - | } |
---|
485 | | - | } |
---|
486 | | - | } |
---|
487 | | - | |
---|
488 | | - | |
---|
489 | | - | |
---|
490 | | - | @Callable(i) |
---|
491 | | - | func withdraw () = { |
---|
492 | | - | let $t01881418957 = $Tuple2(i.payments[0].amount, i.payments[0].assetId) |
---|
493 | | - | let pmtAmount = $t01881418957._1 |
---|
494 | | - | let pmtAssetId = $t01881418957._2 |
---|
495 | | - | let amountToPayA = fraction(pmtAmount, balanceA, shareAssetSupply) |
---|
496 | | - | let amountToPayB = fraction(pmtAmount, balanceB, shareAssetSupply) |
---|
497 | | - | let invariantCalculated = invariantCalc((balanceA - amountToPayA), (balanceB - amountToPayB)) |
---|
498 | | - | if (!(isActive)) |
---|
499 | | - | then throwIsInactive() |
---|
500 | | - | else if ((size(i.payments) != 1)) |
---|
501 | | - | then throw("One attached payment expected") |
---|
502 | | - | else if ((pmtAssetId != shareAssetId)) |
---|
503 | | - | then throw(("Incorrect asset attached. Expected: " + toBase58String(shareAssetId))) |
---|
504 | | - | else if (!(hasEnoughBalance)) |
---|
505 | | - | then ([ScriptTransfer(i.caller, pmtAmount, pmtAssetId)] ++ suspendSuspicious()) |
---|
506 | | - | else { |
---|
507 | | - | let stake1 = if (containsElement(stakingAssets, strAssetIdA)) |
---|
508 | | - | then invoke(this, "stakeUnstake", [false, amountToPayA, strAssetIdA], nil) |
---|
509 | | - | else 0 |
---|
510 | | - | if ((stake1 == stake1)) |
---|
511 | | - | then { |
---|
512 | | - | let stake2 = if (containsElement(stakingAssets, strAssetIdB)) |
---|
513 | | - | then invoke(this, "stakeUnstake", [false, amountToPayB, strAssetIdB], nil) |
---|
514 | | - | else 0 |
---|
515 | | - | if ((stake2 == stake2)) |
---|
516 | | - | then [IntegerEntry(kBalanceA, (balanceA - amountToPayA)), IntegerEntry(kBalanceB, (balanceB - amountToPayB)), IntegerEntry(kShareAssetSupply, (shareAssetSupply - pmtAmount)), IntegerEntry(kInvariant, invariantCalculated), Burn(shareAssetId, pmtAmount), ScriptTransfer(i.caller, amountToPayA, assetIdA), ScriptTransfer(i.caller, amountToPayB, assetIdB)] |
---|
517 | | - | else throw("Strict value is not equal to itself.") |
---|
518 | | - | } |
---|
519 | | - | else throw("Strict value is not equal to itself.") |
---|
520 | | - | } |
---|
521 | | - | } |
---|
522 | | - | |
---|
523 | | - | |
---|
524 | | - | |
---|
525 | | - | @Callable(i) |
---|
526 | | - | func exchange (estimatedAmountToReceive,minAmountToReceive) = { |
---|
527 | | - | let $t02047120546 = $Tuple2(i.payments[0].amount, i.payments[0].assetId) |
---|
528 | | - | let pmtAmount = $t02047120546._1 |
---|
529 | | - | let pmtAssetId = $t02047120546._2 |
---|
530 | | - | if (!(isActive)) |
---|
531 | | - | then throwIsInactive() |
---|
532 | | - | else if ((0 >= estimatedAmountToReceive)) |
---|
533 | | - | then throw(("Estimated amount must be positive. Actual: " + toString(estimatedAmountToReceive))) |
---|
534 | | - | else if ((minAmountToReceive > estimatedAmountToReceive)) |
---|
535 | | - | then throw(((("Minimal amount can't be greater than estimated. Estimated: " + toString(estimatedAmountToReceive)) + ". Minimal: ") + toString(minAmountToReceive))) |
---|
536 | | - | else if ((size(i.payments) != 1)) |
---|
537 | | - | then throw("One attached payment expected") |
---|
538 | | - | else if (!(hasEnoughBalance)) |
---|
539 | | - | then ([ScriptTransfer(i.caller, pmtAmount, pmtAssetId)] ++ suspendSuspicious()) |
---|
540 | | - | else if (if ((pmtAssetId != assetIdA)) |
---|
541 | | - | then (pmtAssetId != assetIdB) |
---|
542 | | - | else false) |
---|
543 | | - | then throwAssets() |
---|
544 | | - | else if ((10000000 > pmtAmount)) |
---|
545 | | - | then throw("Only swap of 10.000000 or more tokens is allowed") |
---|
546 | | - | else if (if ((exchangeRatioLimitMin > fraction(scale8, minAmountToReceive, pmtAmount))) |
---|
547 | | - | then true |
---|
548 | | - | else (fraction(scale8, estimatedAmountToReceive, pmtAmount) > exchangeRatioLimitMax)) |
---|
549 | | - | then throw("Incorrect args and pmt ratio") |
---|
550 | | - | else { |
---|
551 | | - | let sendAssetId = if ((pmtAssetId == assetIdA)) |
---|
552 | | - | then assetIdB |
---|
553 | | - | else assetIdA |
---|
554 | | - | let amount = calculateSendAmount(estimatedAmountToReceive, minAmountToReceive, pmtAmount, pmtAssetId) |
---|
555 | | - | let governanceReward = fraction(amount, feeGovernance, feeScale6) |
---|
556 | | - | let amountMinusFee = fraction(amount, (feeScale6 - fee), feeScale6) |
---|
557 | | - | let $t02196822230 = if ((pmtAssetId == assetIdA)) |
---|
558 | | - | then $Tuple2((balanceA + pmtAmount), ((balanceB - amountMinusFee) - governanceReward)) |
---|
559 | | - | else $Tuple2(((balanceA - amountMinusFee) - governanceReward), (balanceB + pmtAmount)) |
---|
560 | | - | let newBalanceA = $t02196822230._1 |
---|
561 | | - | let newBalanceB = $t02196822230._2 |
---|
562 | | - | let dAppThresholdAmount = fraction((newBalanceA + newBalanceB), dAppThreshold, (2 * dAppThresholdScale2)) |
---|
563 | | - | if (if ((dAppThresholdAmount > newBalanceA)) |
---|
564 | | - | then true |
---|
565 | | - | else (dAppThresholdAmount > newBalanceB)) |
---|
566 | | - | then throwThreshold(dAppThresholdAmount, newBalanceA, newBalanceB) |
---|
567 | | - | else { |
---|
568 | | - | let $t02252822601 = getAssetInfo(pmtAssetId) |
---|
569 | | - | let pmtStrAssetId = $t02252822601._1 |
---|
570 | | - | let pmtAssetName = $t02252822601._2 |
---|
571 | | - | let pmtDecimals = $t02252822601._3 |
---|
572 | | - | let $t02261422691 = getAssetInfo(sendAssetId) |
---|
573 | | - | let sendStrAssetId = $t02261422691._1 |
---|
574 | | - | let sendAssetName = $t02261422691._2 |
---|
575 | | - | let sendDecimals = $t02261422691._3 |
---|
576 | | - | let stake1 = if (containsElement(stakingAssets, pmtStrAssetId)) |
---|
577 | | - | then invoke(this, "stakeUnstake", [true, pmtAmount, pmtStrAssetId], nil) |
---|
578 | | - | else 0 |
---|
579 | | - | if ((stake1 == stake1)) |
---|
580 | | - | then { |
---|
581 | | - | let stake2 = if (containsElement(stakingAssets, sendStrAssetId)) |
---|
582 | | - | then invoke(this, "stakeUnstake", [false, (amountMinusFee + governanceReward), sendStrAssetId], nil) |
---|
583 | | - | else 0 |
---|
584 | | - | if ((stake2 == stake2)) |
---|
585 | | - | then [IntegerEntry(kBalanceA, newBalanceA), IntegerEntry(kBalanceB, newBalanceB), IntegerEntry(kInvariant, invariantCalc(newBalanceA, newBalanceB)), ScriptTransfer(i.caller, amountMinusFee, sendAssetId), ScriptTransfer(walletAddress, governanceReward, sendAssetId)] |
---|
586 | | - | else throw("Strict value is not equal to itself.") |
---|
587 | | - | } |
---|
588 | | - | else throw("Strict value is not equal to itself.") |
---|
589 | | - | } |
---|
590 | | - | } |
---|
591 | | - | } |
---|
592 | | - | |
---|
593 | | - | |
---|
594 | | - | |
---|
595 | | - | @Callable(i) |
---|
596 | | - | func shutdown () = if (!(isActive)) |
---|
597 | | - | then throw(("DApp is already suspended. Cause: " + valueOrElse(getString(this, kCause), "the cause wasn't specified"))) |
---|
598 | | - | else if (!(containsElement([adminPubKey1, adminPubKey2, adminPubKey3, admStartStop], i.callerPublicKey))) |
---|
599 | | - | then throwOnlyAdmin() |
---|
600 | | - | else suspend("Paused by admin") |
---|
601 | | - | |
---|
602 | | - | |
---|
603 | | - | |
---|
604 | | - | @Callable(i) |
---|
605 | | - | func activate () = if (isActive) |
---|
606 | | - | then throwIsActive() |
---|
607 | | - | else if (!(containsElement([adminPubKey1, adminPubKey2, adminPubKey3, admStartStop], i.callerPublicKey))) |
---|
608 | | - | then throwOnlyAdmin() |
---|
609 | | - | else [BooleanEntry(kActive, true), DeleteEntry(kCause)] |
---|
610 | | - | |
---|
611 | | - | |
---|
612 | | - | |
---|
613 | | - | @Callable(i) |
---|
614 | | - | func takeIntoAccountExtraFunds () = { |
---|
615 | | - | let amountEnrollA = (accountBalanceWithStakedA - balanceA) |
---|
616 | | - | let amountEnrollB = (accountBalanceWithStakedB - balanceB) |
---|
617 | | - | let invariantNew = invariantCalc((balanceA + amountEnrollA), (balanceB + amountEnrollB)) |
---|
618 | | - | if (!(isActive)) |
---|
619 | | - | then throwIsInactive() |
---|
620 | | - | else if ((i.caller != walletAddress)) |
---|
621 | | - | then throw("Only the wallet can call this function") |
---|
622 | | - | else if (if ((0 > amountEnrollA)) |
---|
623 | | - | then true |
---|
624 | | - | else (0 > amountEnrollB)) |
---|
625 | | - | then suspend("Enroll amount negative") |
---|
626 | | - | else if (if ((amountEnrollA == 0)) |
---|
627 | | - | then (amountEnrollB == 0) |
---|
628 | | - | else false) |
---|
629 | | - | then throw("No money to take") |
---|
630 | | - | else { |
---|
631 | | - | let stake1 = if (if (containsElement(stakingAssets, strAssetIdA)) |
---|
632 | | - | then (amountEnrollA > 0) |
---|
633 | | - | else false) |
---|
634 | | - | then invoke(this, "stakeUnstake", [true, amountEnrollA, strAssetIdA], nil) |
---|
635 | | - | else 0 |
---|
636 | | - | if ((stake1 == stake1)) |
---|
637 | | - | then { |
---|
638 | | - | let stake2 = if (if (containsElement(stakingAssets, strAssetIdB)) |
---|
639 | | - | then (amountEnrollB > 0) |
---|
640 | | - | else false) |
---|
641 | | - | then invoke(this, "stakeUnstake", [true, amountEnrollB, strAssetIdB], nil) |
---|
642 | | - | else 0 |
---|
643 | | - | if ((stake2 == stake2)) |
---|
644 | | - | then [IntegerEntry(kInvariant, invariantNew), IntegerEntry(kBalanceA, (balanceA + amountEnrollA)), IntegerEntry(kBalanceB, (balanceB + amountEnrollB)), IntegerEntry(("last_income_" + strAssetIdA), amountEnrollA), IntegerEntry(("last_income_" + strAssetIdB), amountEnrollB)] |
---|
645 | | - | else throw("Strict value is not equal to itself.") |
---|
646 | | - | } |
---|
647 | | - | else throw("Strict value is not equal to itself.") |
---|
648 | | - | } |
---|
649 | | - | } |
---|
650 | | - | |
---|
651 | | - | |
---|
652 | | - | |
---|
653 | | - | @Callable(i) |
---|
654 | | - | func stakeUnstake (stake,amount,assetIdString) = if ((i.caller != this)) |
---|
655 | | - | then throw("Only contract itself can invoke this function") |
---|
656 | | - | else { |
---|
657 | | - | let $t02575325856 = calcStakingParams(stake, amount, fromBase58String(assetIdString)) |
---|
658 | | - | let call = $t02575325856._1 |
---|
659 | | - | let addr = $t02575325856._2 |
---|
660 | | - | let params = $t02575325856._3 |
---|
661 | | - | let payments = $t02575325856._4 |
---|
662 | | - | let inv = invoke(addr, call, params, payments) |
---|
663 | | - | if ((inv == inv)) |
---|
664 | | - | then nil |
---|
665 | | - | else throw("Strict value is not equal to itself.") |
---|
666 | | - | } |
---|
667 | | - | |
---|
668 | | - | |
---|
669 | | - | |
---|
670 | | - | @Callable(i) |
---|
671 | | - | func stakeAll () = if (!(isActive)) |
---|
672 | | - | then throw("DApp is inactive at this moment") |
---|
673 | | - | else if (!(containsElement([adminPubKey1, adminPubKey2, adminPubKey3, admStartStop], i.callerPublicKey))) |
---|
674 | | - | then throw("Only admin can call this function") |
---|
675 | | - | else { |
---|
676 | | - | let stake1 = if (containsElement(stakingAssets, strAssetIdA)) |
---|
677 | | - | then { |
---|
678 | | - | let amountA = (balanceA - stakedAmountA) |
---|
679 | | - | if ((amountA > 0)) |
---|
680 | | - | then invoke(this, "stakeUnstake", [true, amountA, strAssetIdA], nil) |
---|
681 | | - | else 0 |
---|
682 | | - | } |
---|
683 | | - | else 0 |
---|
684 | | - | if ((stake1 == stake1)) |
---|
685 | | - | then { |
---|
686 | | - | let stake2 = if (containsElement(stakingAssets, strAssetIdB)) |
---|
687 | | - | then { |
---|
688 | | - | let amountB = (balanceB - stakedAmountB) |
---|
689 | | - | if ((amountB > 0)) |
---|
690 | | - | then invoke(this, "stakeUnstake", [true, amountB, strAssetIdB], nil) |
---|
691 | | - | else 0 |
---|
692 | | - | } |
---|
693 | | - | else 0 |
---|
694 | | - | if ((stake2 == stake2)) |
---|
695 | | - | then nil |
---|
696 | | - | else throw("Strict value is not equal to itself.") |
---|
697 | | - | } |
---|
698 | | - | else throw("Strict value is not equal to itself.") |
---|
699 | | - | } |
---|
700 | | - | |
---|
701 | | - | |
---|
702 | | - | @Verifier(tx) |
---|
703 | | - | func verify () = { |
---|
704 | | - | let multiSignedByAdmins = { |
---|
705 | | - | let adminPubKey1Signed = if (sigVerify(tx.bodyBytes, tx.proofs[0], adminPubKey1)) |
---|
706 | | - | then 1 |
---|
707 | | - | else 0 |
---|
708 | | - | let adminPubKey2Signed = if (sigVerify(tx.bodyBytes, tx.proofs[1], adminPubKey2)) |
---|
709 | | - | then 1 |
---|
710 | | - | else 0 |
---|
711 | | - | let adminPubKey3Signed = if (sigVerify(tx.bodyBytes, tx.proofs[2], adminPubKey3)) |
---|
712 | | - | then 1 |
---|
713 | | - | else 0 |
---|
714 | | - | (((adminPubKey1Signed + adminPubKey2Signed) + adminPubKey3Signed) >= 2) |
---|
715 | | - | } |
---|
716 | | - | match tx { |
---|
717 | | - | case inv: InvokeScriptTransaction => |
---|
718 | | - | let callTakeIntoAccount = if ((inv.dApp == this)) |
---|
719 | | - | then (inv.function == "takeIntoAccountExtraFunds") |
---|
720 | | - | else false |
---|
721 | | - | let signedByAdmin = if (if (if (sigVerify(tx.bodyBytes, tx.proofs[0], adminPubKey1)) |
---|
722 | | - | then true |
---|
723 | | - | else sigVerify(tx.bodyBytes, tx.proofs[0], adminPubKey2)) |
---|
724 | | - | then true |
---|
725 | | - | else sigVerify(tx.bodyBytes, tx.proofs[0], adminPubKey3)) |
---|
726 | | - | then true |
---|
727 | | - | else sigVerify(tx.bodyBytes, tx.proofs[0], admStaking) |
---|
728 | | - | if (if (callTakeIntoAccount) |
---|
729 | | - | then signedByAdmin |
---|
730 | | - | else false) |
---|
731 | | - | then true |
---|
732 | | - | else multiSignedByAdmins |
---|
733 | | - | case _ => |
---|
734 | | - | multiSignedByAdmins |
---|
735 | | - | } |
---|
736 | | - | } |
---|