tx · oLvNyjBeZwcZcPEo8j9y5PtWZzgucb4Z8A5QErBQZ6K 3MuVPd1NeQSnzumvZdaDeHwuwFUw3V3R7b1: -0.03400000 Waves 2022.09.02 16:55 [2211593] smart account 3MuVPd1NeQSnzumvZdaDeHwuwFUw3V3R7b1 > SELF 0.00000000 Waves
{ "type": 13, "id": "oLvNyjBeZwcZcPEo8j9y5PtWZzgucb4Z8A5QErBQZ6K", "fee": 3400000, "feeAssetId": null, "timestamp": 1662126932256, "version": 2, "chainId": 84, "sender": "3MuVPd1NeQSnzumvZdaDeHwuwFUw3V3R7b1", "senderPublicKey": "4btfk5pXDrFDWvshTaXTnRLU9Z6PMgAERH6LiB1Wh4xM", "proofs": [ "4B71VesWmquq2j3Q5KjQnU3WK54VQ7R4CNY7ERfXh6oH5etweAy9uasw3xpk9dBn9QzoVwx8tUivydM6FXJuu4Go" ], "script": "base64:BgIVCAISAwoBCBIAEgMKAQgSBQoDCAgIFAAUa19jb29yZGluYXRvckFkZHJlc3MCFGtfY29vcmRpbmF0b3JBZGRyZXNzABJrX2FkbWluX3B1YmxpY19rZXkCEmtfYWRtaW5fcHVibGljX2tleQATa19xdW90ZUFzc2V0UmVzZXJ2ZQIIa19xdEFzdFIAEmtfYmFzZUFzc2V0UmVzZXJ2ZQIIa19ic0FzdFIAFGtfcG9zaXRpb25DbG9zZWREYXRlAhRrX3Bvc2l0aW9uQ2xvc2VkRGF0ZQAQa19leGVjdXRlZE9yZGVycwIQa19leGVjdXRlZE9yZGVycwAIa19zZW5kZXICCGtfc2VuZGVyAA1rX2luaXRpYWxpemVkAg1rX2luaXRpYWxpemVkAAtUQUtFX1BST0ZJVAABAAlTVE9QX0xPU1MAAgAEVElNRQgFCWxhc3RCbG9jawl0aW1lc3RhbXAADERFQ0lNQUxfVU5JVAkAaAIAAQkAaAIJAGgCCQBoAgkAaAIJAGgCAAoACgAKAAoACgAKAQRkaXZkAgJfeAJfeQkAbgQFAl94BQxERUNJTUFMX1VOSVQFAl95BQhIQUxGRVZFTgEEbXVsZAICX3gCX3kJAG4EBQJfeAUCX3kFDERFQ0lNQUxfVU5JVAUISEFMRkVWRU4BEGV4ZWN1dGVkT3JkZXJLZXkBCF9vcmRlcklkCQCsAgIJAKwCAgUQa19leGVjdXRlZE9yZGVycwIBXwUIX29yZGVySWQBC2Nvb3JkaW5hdG9yAAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCmCAEJARFAZXh0ck5hdGl2ZSgxMDUzKQIFBHRoaXMFFGtfY29vcmRpbmF0b3JBZGRyZXNzAhNDb29yZGluYXRvciBub3Qgc2V0AQ5hZG1pblB1YmxpY0tleQAJANkEAQkBEUBleHRyTmF0aXZlKDEwNTMpAgkBC2Nvb3JkaW5hdG9yAAUSa19hZG1pbl9wdWJsaWNfa2V5AQtpbml0aWFsaXplZAAJAQt2YWx1ZU9yRWxzZQIJAJsIAgUEdGhpcwUNa19pbml0aWFsaXplZAcBGnJlcXVpcmVWYWxpZE9yZGVyU2lnbmF0dXJlBAdfcHJlZml4Bl9vcmRlcgpfc2lnbmF0dXJlEF9zZW5kZXJQdWJsaWNLZXkEB21lc3NhZ2UJAJsDAQkArAICBQdfcHJlZml4BQZfb3JkZXIEA3NpZwkA2QQBBQpfc2lnbmF0dXJlBANwdWIJANkEAQUQX3NlbmRlclB1YmxpY0tleQMJAPQDAwUHbWVzc2FnZQUDc2lnBQNwdWIFBHVuaXQJAAIBAhdJbnZhbGlkIG9yZGVyIHNpZ25hdHVyZQEScmVxdWlyZU5vdEV4ZWN1dGVkAQhfb3JkZXJJZAMJAQt2YWx1ZU9yRWxzZQIJAJsIAgUEdGhpcwkBEGV4ZWN1dGVkT3JkZXJLZXkBBQhfb3JkZXJJZAcJAAIBCQCsAgICGE9yZGVyIGFscmVhZHkgZXhlY3V0ZWQ6IAUIX29yZGVySWQFBHVuaXQEAWkBCnNldENvbnRleHQBB19zZW5kZXIDCQECIT0CCAUBaQZjYWxsZXIFBHRoaXMJAAIBAg5Pbmx5IHNlbGYtY2FsbAkAzAgCCQELU3RyaW5nRW50cnkCBQhrX3NlbmRlcgUHX3NlbmRlcgUDbmlsAWkBDHJlc2V0Q29udGV4dAADCQECIT0CCAUBaQZjYWxsZXIFBHRoaXMJAAIBAg5Pbmx5IHNlbGYtY2FsbAkAzAgCCQELRGVsZXRlRW50cnkBBQhrX3NlbmRlcgUDbmlsAWkBCmluaXRpYWxpemUBDF9jb29yZGluYXRvcgMJAQtpbml0aWFsaXplZAAJAAIBAhNBbHJlYWR5IGluaXRpYWxpemVkCQDMCAIJAQtTdHJpbmdFbnRyeQIFFGtfY29vcmRpbmF0b3JBZGRyZXNzBQxfY29vcmRpbmF0b3IJAMwIAgkBDEJvb2xlYW5FbnRyeQIFDWtfaW5pdGlhbGl6ZWQGBQNuaWwBaQEMZXhlY3V0ZU9yZGVyAwdfcHJlZml4Bl9vcmRlcgpfc2lnbmF0dXJlBApvcmRlclBhcnRzCQC1CQIFBl9vcmRlcgIBLAQJb3JkZXJUeXBlCQETdmFsdWVPckVycm9yTWVzc2FnZQIJALYJAQkAkQMCBQpvcmRlclBhcnRzAAACGUludmFsaWQgb3JkZXIgZGF0YSBbdHlwZV0EB29yZGVySWQJANgEAQkA9wMBCQCbAwEFBl9vcmRlcgQTdmFsaWRhdGVOb3RFeGVjdXRlZAkBEnJlcXVpcmVOb3RFeGVjdXRlZAEFB29yZGVySWQDCQAAAgUTdmFsaWRhdGVOb3RFeGVjdXRlZAUTdmFsaWRhdGVOb3RFeGVjdXRlZAMDCQAAAgUJb3JkZXJUeXBlBQtUQUtFX1BST0ZJVAYJAAACBQlvcmRlclR5cGUFCVNUT1BfTE9TUwQDYW1tCQCRAwIFCm9yZGVyUGFydHMAAQQPc2VuZGVyUHVibGljS2V5CQCRAwIFCm9yZGVyUGFydHMAAgQFcHJpY2UJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAtgkBCQCRAwIFCm9yZGVyUGFydHMAAwIaSW52YWxpZCBvcmRlciBkYXRhIFtwcmljZV0ECXRpbWVzdGFtcAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQC2CQEJAJEDAgUKb3JkZXJQYXJ0cwAEAh5JbnZhbGlkIG9yZGVyIGRhdGEgW3RpbWVzdGFtcF0ECHZhbGlkRHVlCQETdmFsdWVPckVycm9yTWVzc2FnZQIJALYJAQkAkQMCBQpvcmRlclBhcnRzAAUCHUludmFsaWQgb3JkZXIgZGF0YSBbdmFsaWREdWVdBBF2YWxpZGF0ZVNpZ25hdHVyZQkBGnJlcXVpcmVWYWxpZE9yZGVyU2lnbmF0dXJlBAUHX3ByZWZpeAUGX29yZGVyBQpfc2lnbmF0dXJlBQ9zZW5kZXJQdWJsaWNLZXkDCQAAAgURdmFsaWRhdGVTaWduYXR1cmUFEXZhbGlkYXRlU2lnbmF0dXJlBAphbW1BZGRyZXNzCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKYIAQUDYW1tAhhJbnZhbGlkIG9yZGVyIGRhdGEgW2FtbV0EEXF1b3RlQXNzZXRSZXNlcnZlCQERQGV4dHJOYXRpdmUoMTA1MCkCBQphbW1BZGRyZXNzBRNrX3F1b3RlQXNzZXRSZXNlcnZlBBBiYXNlQXNzZXRSZXNlcnZlCQERQGV4dHJOYXRpdmUoMTA1MCkCBQphbW1BZGRyZXNzBRJrX2Jhc2VBc3NldFJlc2VydmUECGFtbVByaWNlCQEEZGl2ZAIFEXF1b3RlQXNzZXRSZXNlcnZlBRBiYXNlQXNzZXRSZXNlcnZlBApwcmljZU1hdGNoAwkAAAIFCW9yZGVyVHlwZQULVEFLRV9QUk9GSVQJAGcCBQhhbW1QcmljZQUFcHJpY2UJAGcCBQVwcmljZQUIYW1tUHJpY2UEDXZhbGlkYXRlUHJpY2UDCQEBIQEFCnByaWNlTWF0Y2gJAAIBCQCsAgIJAKwCAgkArAICAilDYW4gbm90IGV4ZWN1dGUgb3JkZXIgW3ByaWNlXTogQU1NIFByaWNlPQkApAMBBQhhbW1QcmljZQINIE9yZGVyIFByaWNlPQkApAMBBQVwcmljZQUEdW5pdAMJAAACBQ12YWxpZGF0ZVByaWNlBQ12YWxpZGF0ZVByaWNlBAhkdWVNYXRjaAMJAAACBQh2YWxpZER1ZQAABgkAZwIFCHZhbGlkRHVlBQRUSU1FBAt2YWxpZGF0ZUR1ZQMJAQEhAQUIZHVlTWF0Y2gJAAIBCQCsAgIJAKwCAgkArAICAiFDYW4gbm90IGV4ZWN1dGUgb3JkZXIgW2R1ZV06IER1ZT0JAKQDAQUIdmFsaWREdWUCBiBUaW1lPQkApAMBBQRUSU1FBQR1bml0AwkAAAIFC3ZhbGlkYXRlRHVlBQt2YWxpZGF0ZUR1ZQQNdHJhZGVyQWRkcmVzcwkApQgBCQCnCAEJANkEAQUPc2VuZGVyUHVibGljS2V5BBFwb3NpdGlvbldhc0Nsb3NlZAkBC3ZhbHVlT3JFbHNlAgkAmggCBQphbW1BZGRyZXNzCQCsAgIJAKwCAgUUa19wb3NpdGlvbkNsb3NlZERhdGUCAV8FDXRyYWRlckFkZHJlc3MAAAQNcG9zaXRpb25NYXRjaAkAZwIFCXRpbWVzdGFtcAURcG9zaXRpb25XYXNDbG9zZWQEEHZhbGlkYXRlUG9zaXRpb24DCQEBIQEFDXBvc2l0aW9uTWF0Y2gJAAIBCQCsAgIJAKwCAgkArAICAjdDYW4gbm90IGV4ZWN1dGUgb3JkZXIgW3Bvc2l0aW9uIGNsb3NlZF06IE9yZGVyIENyZWF0ZWQ9CQCkAwEFCXRpbWVzdGFtcAIRIFBvc2l0aW9uIENsb3NlZD0JAKQDAQURcG9zaXRpb25XYXNDbG9zZWQFBHVuaXQDCQAAAgUQdmFsaWRhdGVQb3NpdGlvbgUQdmFsaWRhdGVQb3NpdGlvbgMDAwUKcHJpY2VNYXRjaAUIZHVlTWF0Y2gHBQ1wb3NpdGlvbk1hdGNoBwQMZG9TZXRDb250ZXh0CQD8BwQFBHRoaXMCCnNldENvbnRleHQJAMwIAgUNdHJhZGVyQWRkcmVzcwUDbmlsBQNuaWwDCQAAAgUMZG9TZXRDb250ZXh0BQxkb1NldENvbnRleHQED2RvQ2xvc2VQb3NpdGlvbgkA/AcEBQphbW1BZGRyZXNzAg1jbG9zZVBvc2l0aW9uBQNuaWwFA25pbAMJAAACBQ9kb0Nsb3NlUG9zaXRpb24FD2RvQ2xvc2VQb3NpdGlvbgQOZG9SZXNldENvbnRleHQJAPwHBAUEdGhpcwIMcmVzZXRDb250ZXh0BQNuaWwFA25pbAMJAAACBQ5kb1Jlc2V0Q29udGV4dAUOZG9SZXNldENvbnRleHQJAMwIAgkBDEJvb2xlYW5FbnRyeQIJARBleGVjdXRlZE9yZGVyS2V5AQUHb3JkZXJJZAYFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECHkludmFsaWQgb3JkZXIgZXhlY3V0aW9uIHRpbWluZwkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgEJAKwCAgIUSW52YWxpZCBvcmRlciB0eXBlOiAJAKQDAQUJb3JkZXJUeXBlCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAQJ0eAEGdmVyaWZ5AAkA9AMDCAUCdHgJYm9keUJ5dGVzCQCRAwIIBQJ0eAZwcm9vZnMAAAkBDmFkbWluUHVibGljS2V5ABetHkM=", "height": 2211593, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: none Next: none Full:
Old | New | Differences | |
---|---|---|---|
1 | - | # no script | |
1 | + | {-# STDLIB_VERSION 6 #-} | |
2 | + | {-# SCRIPT_TYPE ACCOUNT #-} | |
3 | + | {-# CONTENT_TYPE DAPP #-} | |
4 | + | let k_coordinatorAddress = "k_coordinatorAddress" | |
5 | + | ||
6 | + | let k_admin_public_key = "k_admin_public_key" | |
7 | + | ||
8 | + | let k_quoteAssetReserve = "k_qtAstR" | |
9 | + | ||
10 | + | let k_baseAssetReserve = "k_bsAstR" | |
11 | + | ||
12 | + | let k_positionClosedDate = "k_positionClosedDate" | |
13 | + | ||
14 | + | let k_executedOrders = "k_executedOrders" | |
15 | + | ||
16 | + | let k_sender = "k_sender" | |
17 | + | ||
18 | + | let k_initialized = "k_initialized" | |
19 | + | ||
20 | + | let TAKE_PROFIT = 1 | |
21 | + | ||
22 | + | let STOP_LOSS = 2 | |
23 | + | ||
24 | + | let TIME = lastBlock.timestamp | |
25 | + | ||
26 | + | let DECIMAL_UNIT = (1 * (((((10 * 10) * 10) * 10) * 10) * 10)) | |
27 | + | ||
28 | + | func divd (_x,_y) = fraction(_x, DECIMAL_UNIT, _y, HALFEVEN) | |
29 | + | ||
30 | + | ||
31 | + | func muld (_x,_y) = fraction(_x, _y, DECIMAL_UNIT, HALFEVEN) | |
32 | + | ||
33 | + | ||
34 | + | func executedOrderKey (_orderId) = ((k_executedOrders + "_") + _orderId) | |
35 | + | ||
36 | + | ||
37 | + | func coordinator () = valueOrErrorMessage(addressFromString(getStringValue(this, k_coordinatorAddress)), "Coordinator not set") | |
38 | + | ||
39 | + | ||
40 | + | func adminPublicKey () = fromBase58String(getStringValue(coordinator(), k_admin_public_key)) | |
41 | + | ||
42 | + | ||
43 | + | func initialized () = valueOrElse(getBoolean(this, k_initialized), false) | |
44 | + | ||
45 | + | ||
46 | + | func requireValidOrderSignature (_prefix,_order,_signature,_senderPublicKey) = { | |
47 | + | let message = toBytes((_prefix + _order)) | |
48 | + | let sig = fromBase58String(_signature) | |
49 | + | let pub = fromBase58String(_senderPublicKey) | |
50 | + | if (sigVerify(message, sig, pub)) | |
51 | + | then unit | |
52 | + | else throw("Invalid order signature") | |
53 | + | } | |
54 | + | ||
55 | + | ||
56 | + | func requireNotExecuted (_orderId) = if (valueOrElse(getBoolean(this, executedOrderKey(_orderId)), false)) | |
57 | + | then throw(("Order already executed: " + _orderId)) | |
58 | + | else unit | |
59 | + | ||
60 | + | ||
61 | + | @Callable(i) | |
62 | + | func setContext (_sender) = if ((i.caller != this)) | |
63 | + | then throw("Only self-call") | |
64 | + | else [StringEntry(k_sender, _sender)] | |
65 | + | ||
66 | + | ||
67 | + | ||
68 | + | @Callable(i) | |
69 | + | func resetContext () = if ((i.caller != this)) | |
70 | + | then throw("Only self-call") | |
71 | + | else [DeleteEntry(k_sender)] | |
72 | + | ||
73 | + | ||
74 | + | ||
75 | + | @Callable(i) | |
76 | + | func initialize (_coordinator) = if (initialized()) | |
77 | + | then throw("Already initialized") | |
78 | + | else [StringEntry(k_coordinatorAddress, _coordinator), BooleanEntry(k_initialized, true)] | |
79 | + | ||
80 | + | ||
81 | + | ||
82 | + | @Callable(i) | |
83 | + | func executeOrder (_prefix,_order,_signature) = { | |
84 | + | let orderParts = split(_order, ",") | |
85 | + | let orderType = valueOrErrorMessage(parseInt(orderParts[0]), "Invalid order data [type]") | |
86 | + | let orderId = toBase58String(sha256(toBytes(_order))) | |
87 | + | let validateNotExecuted = requireNotExecuted(orderId) | |
88 | + | if ((validateNotExecuted == validateNotExecuted)) | |
89 | + | then if (if ((orderType == TAKE_PROFIT)) | |
90 | + | then true | |
91 | + | else (orderType == STOP_LOSS)) | |
92 | + | then { | |
93 | + | let amm = orderParts[1] | |
94 | + | let senderPublicKey = orderParts[2] | |
95 | + | let price = valueOrErrorMessage(parseInt(orderParts[3]), "Invalid order data [price]") | |
96 | + | let timestamp = valueOrErrorMessage(parseInt(orderParts[4]), "Invalid order data [timestamp]") | |
97 | + | let validDue = valueOrErrorMessage(parseInt(orderParts[5]), "Invalid order data [validDue]") | |
98 | + | let validateSignature = requireValidOrderSignature(_prefix, _order, _signature, senderPublicKey) | |
99 | + | if ((validateSignature == validateSignature)) | |
100 | + | then { | |
101 | + | let ammAddress = valueOrErrorMessage(addressFromString(amm), "Invalid order data [amm]") | |
102 | + | let quoteAssetReserve = getIntegerValue(ammAddress, k_quoteAssetReserve) | |
103 | + | let baseAssetReserve = getIntegerValue(ammAddress, k_baseAssetReserve) | |
104 | + | let ammPrice = divd(quoteAssetReserve, baseAssetReserve) | |
105 | + | let priceMatch = if ((orderType == TAKE_PROFIT)) | |
106 | + | then (ammPrice >= price) | |
107 | + | else (price >= ammPrice) | |
108 | + | let validatePrice = if (!(priceMatch)) | |
109 | + | then throw(((("Can not execute order [price]: AMM Price=" + toString(ammPrice)) + " Order Price=") + toString(price))) | |
110 | + | else unit | |
111 | + | if ((validatePrice == validatePrice)) | |
112 | + | then { | |
113 | + | let dueMatch = if ((validDue == 0)) | |
114 | + | then true | |
115 | + | else (validDue >= TIME) | |
116 | + | let validateDue = if (!(dueMatch)) | |
117 | + | then throw(((("Can not execute order [due]: Due=" + toString(validDue)) + " Time=") + toString(TIME))) | |
118 | + | else unit | |
119 | + | if ((validateDue == validateDue)) | |
120 | + | then { | |
121 | + | let traderAddress = toString(addressFromPublicKey(fromBase58String(senderPublicKey))) | |
122 | + | let positionWasClosed = valueOrElse(getInteger(ammAddress, ((k_positionClosedDate + "_") + traderAddress)), 0) | |
123 | + | let positionMatch = (timestamp >= positionWasClosed) | |
124 | + | let validatePosition = if (!(positionMatch)) | |
125 | + | then throw(((("Can not execute order [position closed]: Order Created=" + toString(timestamp)) + " Position Closed=") + toString(positionWasClosed))) | |
126 | + | else unit | |
127 | + | if ((validatePosition == validatePosition)) | |
128 | + | then if (if (if (priceMatch) | |
129 | + | then dueMatch | |
130 | + | else false) | |
131 | + | then positionMatch | |
132 | + | else false) | |
133 | + | then { | |
134 | + | let doSetContext = invoke(this, "setContext", [traderAddress], nil) | |
135 | + | if ((doSetContext == doSetContext)) | |
136 | + | then { | |
137 | + | let doClosePosition = invoke(ammAddress, "closePosition", nil, nil) | |
138 | + | if ((doClosePosition == doClosePosition)) | |
139 | + | then { | |
140 | + | let doResetContext = invoke(this, "resetContext", nil, nil) | |
141 | + | if ((doResetContext == doResetContext)) | |
142 | + | then [BooleanEntry(executedOrderKey(orderId), true)] | |
143 | + | else throw("Strict value is not equal to itself.") | |
144 | + | } | |
145 | + | else throw("Strict value is not equal to itself.") | |
146 | + | } | |
147 | + | else throw("Strict value is not equal to itself.") | |
148 | + | } | |
149 | + | else throw("Invalid order execution timing") | |
150 | + | else throw("Strict value is not equal to itself.") | |
151 | + | } | |
152 | + | else throw("Strict value is not equal to itself.") | |
153 | + | } | |
154 | + | else throw("Strict value is not equal to itself.") | |
155 | + | } | |
156 | + | else throw("Strict value is not equal to itself.") | |
157 | + | } | |
158 | + | else throw(("Invalid order type: " + toString(orderType))) | |
159 | + | else throw("Strict value is not equal to itself.") | |
160 | + | } | |
161 | + | ||
162 | + | ||
163 | + | @Verifier(tx) | |
164 | + | func verify () = sigVerify(tx.bodyBytes, tx.proofs[0], adminPublicKey()) | |
165 | + |
github/deemru/w8io/169f3d6 27.10 ms ◑