tx · GMDENNUJ4RGF6CpPjrJ5Zr3c85fBWe3acXFGVD6m8PL1

3N3nfqFcxXfd3T18V9icDdh58MJ9wQ2k2xx:  -0.00600000 Waves

2024.12.08 04:17 [3404985] smart account 3N3nfqFcxXfd3T18V9icDdh58MJ9wQ2k2xx > SELF 0.00000000 Waves

{ "type": 13, "id": "GMDENNUJ4RGF6CpPjrJ5Zr3c85fBWe3acXFGVD6m8PL1", "fee": 600000, "feeAssetId": null, "timestamp": 1733620675720, "version": 2, "chainId": 84, "sender": "3N3nfqFcxXfd3T18V9icDdh58MJ9wQ2k2xx", "senderPublicKey": "UGqkWsCpv7xRVXkQRXyLd6pWPDtYGXmPip7FxSd1pAu", "proofs": [ "4q3wPUqtott29KFXBTWMMttXCU3ptitzb8TzbRrgnkMasJ1qdaaC8TqZdvLwPy458Ah3impvPbvAeqeo7DaPp4Aw" ], "script": "base64:BgIRCAISAwoBARIDCgEIEgMKAQgXAANTRVACAl9fAAVjaGFpbgkAyQECCQDKAQIIBQR0aGlzBWJ5dGVzAAEAAQAWZGVmYXVsdFJlc3QyQWRkcmVzc1N0cgQHJG1hdGNoMAUFY2hhaW4DCQAAAgEBVwUHJG1hdGNoMAIjM1BGd1l0YThiaUV6MzF6cGVGZTVESks4d0U1dHJTcFFWRjgDCQAAAgEBVAUHJG1hdGNoMAIjM043VXVZYXI2MjY0UDU4RkJoVldLUFFBaDRZdWEyaGduZ3YJAAIBAg1Vbmtub3duIGNoYWluAQ9nZXRTdHJpbmdPckZhaWwCB2FkZHJlc3MDa2V5CQETdmFsdWVPckVycm9yTWVzc2FnZQIJAJ0IAgUHYWRkcmVzcwUDa2V5CQC5CQIJAMwIAgIKbWFuZGF0b3J5IAkAzAgCCQClCAEFB2FkZHJlc3MJAMwIAgIBLgkAzAgCBQNrZXkJAMwIAgIPIGlzIG5vdCBkZWZpbmVkBQNuaWwCAAAQSWR4Q2ZnQWNyZXMyRGFwcAABAA1JZHhDZmdXbGdEYXBwAAIBCmtleVJlc3RDZmcAAg4lc19fcmVzdENvbmZpZwEPa2V5UmVzdDJBZGRyZXNzAAINJXNfX3Jlc3QyQWRkcgERcmVhZFJlc3RDZmdPckZhaWwBBHJlc3QJALwJAgkBD2dldFN0cmluZ09yRmFpbAIFBHJlc3QJAQprZXlSZXN0Q2ZnAAUDU0VQARhnZXRDb250cmFjdEFkZHJlc3NPckZhaWwCCHJlc3QyQ2ZnA2lkeAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCmCAEJAJEDAgUIcmVzdDJDZmcFA2lkeAkArAICAipSZXN0IGNmZyBkb2Vzbid0IGNvbnRhaW4gYWRkcmVzcyBhdCBpbmRleCAJAKQDAQUDaWR4AA1yZXN0MkNvbnRyYWN0CQERQGV4dHJOYXRpdmUoMTA2MikBCQELdmFsdWVPckVsc2UCCQCdCAIFBHRoaXMJAQ9rZXlSZXN0MkFkZHJlc3MABRZkZWZhdWx0UmVzdDJBZGRyZXNzU3RyAAhyZXN0MkNmZwkBEXJlYWRSZXN0Q2ZnT3JGYWlsAQUNcmVzdDJDb250cmFjdAAOYWNyZXMyQ29udHJhY3QJARhnZXRDb250cmFjdEFkZHJlc3NPckZhaWwCBQhyZXN0MkNmZwUQSWR4Q2ZnQWNyZXMyRGFwcAALd2xnQ29udHJhY3QJARhnZXRDb250cmFjdEFkZHJlc3NPckZhaWwCBQhyZXN0MkNmZwUNSWR4Q2ZnV2xnRGFwcAANd2xnQXNzZXRJZEtleQILd2xnX2Fzc2V0SWQACndsZ0Fzc2V0SWQJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAnAgCBQt3bGdDb250cmFjdAUNd2xnQXNzZXRJZEtleQIYV0xHT0xEIGlzIG5vdCBpc3N1ZWQgeWV0ARJrZXlTZWxsZXJCeUFzc2V0SWQBB2Fzc2V0SWQJAKwCAgIHc2VsbGVyXwUHYXNzZXRJZAERa2V5UHJpY2VCeUFzc2V0SWQBB2Fzc2V0SWQJAKwCAgIGcHJpY2VfBQdhc3NldElkARNrZXlBc3NldElkc0J5U2VsbGVyAQRhZGRyCQCsAgICCWFzc2V0SWRzXwUEYWRkcgEFYXNJbnQBAXYEByRtYXRjaDAFAXYDCQABAgUHJG1hdGNoMAIDSW50BAFuBQckbWF0Y2gwBQFuCQACAQIVZmFpbCB0byBjYXN0IGludG8gSW50AQpmaXhlZFBvaW50AgN2YWwIZGVjaW1hbHMEBnRlblBvdwkAbAYACgAABQhkZWNpbWFscwAAAAAFBERPV04EB2xvd1BhcnQJAKQDAQkAagIFA3ZhbAUGdGVuUG93BAZ6ZXJvZXMJALACAgkApAMBBQZ0ZW5Qb3cJAGQCAAEJALECAQUHbG93UGFydAkArAICCQCsAgIJAKwCAgkApAMBCQBpAgUDdmFsBQZ0ZW5Qb3cCAS4FBnplcm9lcwUHbG93UGFydAALdGVhbUFkZHJLZXkCCHRlYW1BZGRyAQdwcm9sb2cyAAkBBWFzSW50AQkA/QcEBQ5hY3JlczJDb250cmFjdAIKc2F2ZUxhc3RUeAUDbmlsBQNuaWwDAWkBDnBsYWNlU2VsbE9yZGVyAQVwcmljZQQMcHJvbG9nUmVzdWx0CQEHcHJvbG9nMgADCQAAAgUMcHJvbG9nUmVzdWx0BQxwcm9sb2dSZXN1bHQDCQBnAgAABQVwcmljZQkAAgECGFByaWNlIHNob3VsZCBiZSBwb3NpdGl2ZQMJAQIhPQIJAJADAQgFAWkIcGF5bWVudHMAAgkAAgECNUV4YWN0bHkgMiBwYXltZW50cyByZXF1aXJlZDogTkZUIGFuZCA1JSBmZWUgaW4gV0xHT0xEBANwbXQJAQV2YWx1ZQEJAJEDAggFAWkIcGF5bWVudHMAAAMJAQIhPQIIBQNwbXQGYW1vdW50AAEJAAIBAitORlQgdG9rZW4gc2hvdWxkIGJlIGF0dGFjaGVkIGFzIDFzdCBwYXltZW50BARwbXQxCQEFdmFsdWUBCQCRAwIIBQFpCHBheW1lbnRzAAEECHdBc3NldElkCQETdmFsdWVPckVycm9yTWVzc2FnZQIIBQRwbXQxB2Fzc2V0SWQCGU5vIFdBVkVTIHBheW1lbnRzIGFsbG93ZWQDCQECIT0CBQh3QXNzZXRJZAUKd2xnQXNzZXRJZAkAAgECME9ubHkgV0xHT0xEIHBheW1lbnRzIGFyZSBhY2NlcHRlZCBhcyAybmQgcGF5bWVudAQGY2hhbmdlCQBlAggFBHBtdDEGYW1vdW50CQBpAgUFcHJpY2UAFAMJAGYCAAAFBmNoYW5nZQkAAgECKDUlIGZlZSBzaG91bGQgYmUgYXR0YWNoZWQgYXMgMm5kIHBheW1lbnQEDWNoYW5nZUFjdGlvbnMDCQBmAgUGY2hhbmdlAAAJAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwgFAWkGY2FsbGVyBQZjaGFuZ2UFCndsZ0Fzc2V0SWQFA25pbAUDbmlsBAdhc3NldElkCQETdmFsdWVPckVycm9yTWVzc2FnZQIIBQNwbXQHYXNzZXRJZAIZTm8gV0FWRVMgcGF5bWVudHMgYWxsb3dlZAQFYXNzZXQJAQV2YWx1ZQEJAOwHAQUHYXNzZXRJZAQKYXNzZXRJZFN0cgkA2AQBBQdhc3NldElkBARhZGRyCQClCAEIBQFpBmNhbGxlcgMJAQIhPQIIBQVhc3NldAZpc3N1ZXIFDmFjcmVzMkNvbnRyYWN0CQACAQInT25seSBXYXZlc0xhbmRzIE5GVCB0b2tlbnMgYXJlIGFjY2VwdGVkBAduZnRzS2V5CQETa2V5QXNzZXRJZHNCeVNlbGxlcgEFBGFkZHIEB25mdHNTdHIJAQt2YWx1ZU9yRWxzZQIJAKIIAQUHbmZ0c0tleQIABARuZnRzAwkBAiE9AgUHbmZ0c1N0cgIACQC9CQIJAQV2YWx1ZQEFB25mdHNTdHICAV8FA25pbAkAlAoCCQDOCAIJAMwIAgkBDEludGVnZXJFbnRyeQIJARFrZXlQcmljZUJ5QXNzZXRJZAEFCmFzc2V0SWRTdHIFBXByaWNlCQDMCAIJAQtTdHJpbmdFbnRyeQIJARJrZXlTZWxsZXJCeUFzc2V0SWQBBQphc3NldElkU3RyBQRhZGRyCQDMCAIJAQtTdHJpbmdFbnRyeQIFB25mdHNLZXkJALsJAgkAzQgCBQRuZnRzBQphc3NldElkU3RyAgFfBQNuaWwFDWNoYW5nZUFjdGlvbnMFDHByb2xvZ1Jlc3VsdAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpAQ9jYW5jZWxTZWxsT3JkZXIBCmFzc2V0SWRTdHIEDHByb2xvZ1Jlc3VsdAkBB3Byb2xvZzIAAwkAAAIFDHByb2xvZ1Jlc3VsdAUMcHJvbG9nUmVzdWx0BARhZGRyCQClCAEIBQFpBmNhbGxlcgQHbmZ0c0tleQkBE2tleUFzc2V0SWRzQnlTZWxsZXIBBQRhZGRyBAduZnRzU3RyCQELdmFsdWVPckVsc2UCCQCiCAEFB25mdHNLZXkCAAQEbmZ0cwMJAQIhPQIFB25mdHNTdHICAAkAvQkCCQEFdmFsdWUBBQduZnRzU3RyAgFfBQNuaWwEA2lkeAkAzwgCBQRuZnRzBQphc3NldElkU3RyAwkBASEBCQEJaXNEZWZpbmVkAQUDaWR4CQACAQkArAICAh9Zb3VyIGRvbid0IGhhdmUgc2VsbCBvcmRlciBmb3IgBQphc3NldElkU3RyBApsaXN0QWN0aW9uAwkAZgIJAJADAQUEbmZ0cwABCQELU3RyaW5nRW50cnkCBQduZnRzS2V5CQC7CQIJANEIAgUEbmZ0cwkBBXZhbHVlAQUDaWR4AgFfCQELRGVsZXRlRW50cnkBBQduZnRzS2V5BAVwcmljZQkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCfCAEJARFrZXlQcmljZUJ5QXNzZXRJZAEFCmFzc2V0SWRTdHIJAKwCAgIeWW91IGRvbid0IGhhdmUgc2VsbCBvcmRlciBmb3IgBQphc3NldElkU3RyCQCUCgIJAMwIAgUKbGlzdEFjdGlvbgkAzAgCCQELRGVsZXRlRW50cnkBCQESa2V5U2VsbGVyQnlBc3NldElkAQUKYXNzZXRJZFN0cgkAzAgCCQELRGVsZXRlRW50cnkBCQERa2V5UHJpY2VCeUFzc2V0SWQBBQphc3NldElkU3RyCQDMCAIJAQ5TY3JpcHRUcmFuc2ZlcgMIBQFpBmNhbGxlcgkAaQIFBXByaWNlABQFCndsZ0Fzc2V0SWQFA25pbAUMcHJvbG9nUmVzdWx0CQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBD2FjY2VwdFNlbGxPcmRlcgEKYXNzZXRJZFN0cgQMcHJvbG9nUmVzdWx0CQEHcHJvbG9nMgADCQAAAgUMcHJvbG9nUmVzdWx0BQxwcm9sb2dSZXN1bHQDCQECIT0CCQCQAwEIBQFpCHBheW1lbnRzAAEJAAIBAiJleGFjdGx5IDEgcGF5bWVudCBtdXN0IGJlIGF0dGFjaGVkBANwbXQJAJEDAggFAWkIcGF5bWVudHMAAAMDCQEBIQEJAQlpc0RlZmluZWQBCAUDcG10B2Fzc2V0SWQGCQECIT0CCQEFdmFsdWUBCAUDcG10B2Fzc2V0SWQFCndsZ0Fzc2V0SWQJAAIBAhVXTEdPTEQgcGF5bWVudHMgb25seSEEBXByaWNlCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAJ8IAQkBEWtleVByaWNlQnlBc3NldElkAQUKYXNzZXRJZFN0cgkArAICCQCsAgICBE5GVCAFCmFzc2V0SWRTdHICDyBpcyBub3Qgc2VsbGluZwQGY2hhbmdlCQBlAggFA3BtdAZhbW91bnQFBXByaWNlAwkAZgIAAAUGY2hhbmdlCQACAQkArAICCQCsAgICLVBheW1lbnQgYXR0YWNoZWQgZG9lc24ndCBjb3ZlciBzZWxsIHByaWNlIG9mIAkBCmZpeGVkUG9pbnQCBQVwcmljZQAIAgcgV0xHT0xEBA1jaGFuZ2VBY3Rpb25zAwkAZgIFBmNoYW5nZQAACQDMCAIJAQ5TY3JpcHRUcmFuc2ZlcgMIBQFpBmNhbGxlcgUGY2hhbmdlBQp3bGdBc3NldElkBQNuaWwFA25pbAQGc2VsbGVyCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKIIAQkBEmtleVNlbGxlckJ5QXNzZXRJZAEFCmFzc2V0SWRTdHIJAKwCAgkArAICAgRORlQgBQphc3NldElkU3RyAg8gaXMgbm90IHNlbGxpbmcEB25mdHNLZXkJARNrZXlBc3NldElkc0J5U2VsbGVyAQUGc2VsbGVyBAduZnRzU3RyCQELdmFsdWVPckVsc2UCCQCiCAEFB25mdHNLZXkCAAQEbmZ0cwMJAQIhPQIFB25mdHNTdHICAAkAvQkCCQEFdmFsdWUBBQduZnRzU3RyAgFfBQNuaWwEA2lkeAkAzwgCBQRuZnRzBQphc3NldElkU3RyAwkBASEBCQEJaXNEZWZpbmVkAQUDaWR4CQACAQkArAICAiFTZWxsZXIgZG9uJ3QgaGF2ZSBzZWxsIG9yZGVyIGZvciAFCmFzc2V0SWRTdHIECmxpc3RBY3Rpb24DCQBmAgkAkAMBBQRuZnRzAAEJAQtTdHJpbmdFbnRyeQIFB25mdHNLZXkJALsJAgkA0QgCBQRuZnRzCQEFdmFsdWUBBQNpZHgCAV8JAQtEZWxldGVFbnRyeQEFB25mdHNLZXkEA2ZlZQkAaQIFBXByaWNlABQEB2ZvclRlYW0JAGkCBQNmZWUAAgQJd2xnUmVtYWluCQEFYXNJbnQBCQD8BwQFC3dsZ0NvbnRyYWN0AgpidXJuV2xnb2xkCQDMCAIJAGUCBQNmZWUFB2ZvclRlYW0FA25pbAUDbmlsCQCUCgIJAM4IAgkAzAgCBQpsaXN0QWN0aW9uCQDMCAIJAQtEZWxldGVFbnRyeQEJARJrZXlTZWxsZXJCeUFzc2V0SWQBBQphc3NldElkU3RyCQDMCAIJAQtEZWxldGVFbnRyeQEJARFrZXlQcmljZUJ5QXNzZXRJZAEFCmFzc2V0SWRTdHIJAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwkBEUBleHRyTmF0aXZlKDEwNjIpAQUGc2VsbGVyBQVwcmljZQUKd2xnQXNzZXRJZAkAzAgCCQEOU2NyaXB0VHJhbnNmZXIDCQERQGV4dHJOYXRpdmUoMTA2MikBCQERQGV4dHJOYXRpdmUoMTA1MykCBQt3bGdDb250cmFjdAULdGVhbUFkZHJLZXkFB2ZvclRlYW0FCndsZ0Fzc2V0SWQJAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwgFAWkGY2FsbGVyAAEJANkEAQUKYXNzZXRJZFN0cgUDbmlsBQ1jaGFuZ2VBY3Rpb25zBQxwcm9sb2dSZXN1bHQJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4AWHxRLQ==", "height": 3404985, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: 7DULw3wfLc9rHFBz31io411pyN33WkDEKpUs6dFXNCT4 Next: BA8AULfhgW1nv4c5pdyScPwqMnybGt3UbdN3TYoN9jH4 Diff:
OldNewDifferences
11 {-# STDLIB_VERSION 6 #-}
22 {-# SCRIPT_TYPE ACCOUNT #-}
33 {-# CONTENT_TYPE DAPP #-}
4-let DEFAULTLOCATION = "Africa_F_Africa"
5-
6-let locIdxContinent = 0
7-
8-let locIdxType = 1
9-
10-func keyStakedDuckByOwner (ownerAddr) = ("stakedDuckByOwner_" + ownerAddr)
11-
12-
13-func keyDuckLocation (duckAssetId) = ("duckLocation_" + duckAssetId)
14-
15-
16-let lastTourIdKey = "%s__lastTourId"
17-
18-func keyTourStaticDataById (tId) = ("%s%d__tourStaticData__" + toString(tId))
19-
20-
21-func keyTourDynamicDataById (tId) = ("%s%d__tourDynamicData__" + toString(tId))
22-
23-
24-func keyScoreBoardByTour (tId) = ("%s%d__scoreBoard__" + toString(tId))
25-
26-
27-func keySumScoresByTour (tId) = ("%s%d__sumScores__" + toString(tId))
28-
29-
30-func keyUnpaidRewardsByTour (tId) = ("%s%d__unpaidRewards__" + toString(tId))
31-
32-
33-func keyLastRegisteredTourByDuck (duckAssetId) = ("%s%s__lastRegisteredTourByDuck__" + duckAssetId)
34-
35-
36-func keyIsRegisteredByTourAndDuck (tId,duckAssetId) = makeString(["%s%d%s__isRegisteredByTourAndDuck", toString(tId), duckAssetId], "__")
37-
38-
39-func keyIsAwardedByTourAndDuck (tId,duckAssetId) = makeString(["%s%d%s__isAwardedByTourAndDuck", toString(tId), duckAssetId], "__")
40-
41-
42-func keyLastAttemptByTourAndDuck (tId,duckAssetId) = makeString(["%s%d%s__lastAttemptByTourAndDuck", toString(tId), duckAssetId], "__")
43-
44-
45-func keyBestResultByTourAndDuck (tId,duckAssetId) = makeString(["%s%d%s__bestResultByTourAndDuck", toString(tId), duckAssetId], "__")
46-
47-
48-func keyBestTxByTourAndDuck (tId,duckAssetId) = makeString(["%s%d%s__bestTxByTourAndDuck", toString(tId), duckAssetId], "__")
49-
50-
51-let idxStatic = 0
52-
53-let idxDynamic = 1
54-
55-let tStaticRegisterCost = 2
56-
57-let tStaticAttemptCost = 3
58-
59-let tStaticStart = 5
60-
61-let tStaticEnd = 6
62-
63-let tStaticNumGrands = 7
64-
65-let tStaticPrizeFund = 8
66-
67-let tStaticAsset = 9
68-
69-let tDynamicStatus = 1
70-
71-let tDynamicLeaders = 2
72-
73-let tDynamicWinResult = 3
74-
75-let tDynamicTotalRegCount = 4
76-
77-let tDynamicTotalAttempts = 5
78-
79-func getTourData (tourContract,tId) = {
80- let static = split(valueOrErrorMessage(getString(tourContract, keyTourStaticDataById(tId)), (("Error reading tournament " + toString(tId)) + " data")), "__")
81- let dynamic = split_4C(valueOrErrorMessage(getString(tourContract, keyTourDynamicDataById(tId)), (("Error reading tournament " + toString(tId)) + " data")), "__")
82-[static, dynamic]
83- }
84-
85-
86-func isInTournament (tourContract,location) = {
87- let lastId = valueOrElse(getInteger(tourContract, lastTourIdKey), 0)
88- let loc = split(location, "_")
89- let now = lastBlock.timestamp
90- let tData = getTourData(tourContract, lastId)
91- let static = tData[idxStatic]
92- let dynamic = tData[idxDynamic]
93- if (if (if ((loc[locIdxType] == "T"))
94- then (parseIntValue(loc[locIdxContinent]) == lastId)
95- else false)
96- then (dynamic[tDynamicStatus] == "INPROGRESS")
97- else false)
98- then (parseIntValue(static[tStaticEnd]) > now)
99- else false
100- }
101-
4+let SEP = "__"
1025
1036 let chain = take(drop(this.bytes, 1), 1)
1047
105-let defaultRestAddressStr = match chain {
8+let defaultRest2AddressStr = match chain {
1069 case _ =>
10710 if ((base58'2W' == $match0))
108- then "3PQCuvFbvh4LkPUnrnU1z3jnbA1p9m3WNhv"
11+ then "3PFwYta8biEz31zpeFe5DJK8wE5trSpQVF8"
10912 else if ((base58'2T' == $match0))
110- then "3MumkGGztCKAXpWDqxkddofqXSUbqQkvSJy"
13+ then "3N7UuYar6264P58FBhVWKPQAh4Yua2hgngv"
11114 else throw("Unknown chain")
11215 }
113-
114-let SEP = "__"
11516
11617 func getStringOrFail (address,key) = valueOrErrorMessage(getString(address, key), makeString(["mandatory ", toString(address), ".", key, " is not defined"], ""))
11718
11819
119-let IdxCfgStakingDapp = 1
20+let IdxCfgAcres2Dapp = 1
12021
121-let IdxCfgWlgDapp = 4
22+let IdxCfgWlgDapp = 2
12223
12324 func keyRestCfg () = "%s__restConfig"
12425
12526
126-func keyRestAddress () = "%s__restAddr"
27+func keyRest2Address () = "%s__rest2Addr"
12728
12829
12930 func readRestCfgOrFail (rest) = split_4C(getStringOrFail(rest, keyRestCfg()), SEP)
13031
13132
132-func getContractAddressOrFail (restCfg,idx) = valueOrErrorMessage(addressFromString(restCfg[idx]), ("Rest cfg doesn't contain address at index " + toString(idx)))
33+func getContractAddressOrFail (rest2Cfg,idx) = valueOrErrorMessage(addressFromString(rest2Cfg[idx]), ("Rest cfg doesn't contain address at index " + toString(idx)))
13334
13435
135-let restContract = addressFromStringValue(valueOrElse(getString(this, keyRestAddress()), defaultRestAddressStr))
36+let rest2Contract = addressFromStringValue(valueOrElse(getString(this, keyRest2Address()), defaultRest2AddressStr))
13637
137-let restCfg = readRestCfgOrFail(restContract)
38+let rest2Cfg = readRestCfgOrFail(rest2Contract)
13839
139-let stakingContract = getContractAddressOrFail(restCfg, IdxCfgStakingDapp)
40+let acres2Contract = getContractAddressOrFail(rest2Cfg, IdxCfgAcres2Dapp)
14041
141-let wlgContract = getContractAddressOrFail(restCfg, IdxCfgWlgDapp)
42+let wlgContract = getContractAddressOrFail(rest2Cfg, IdxCfgWlgDapp)
14243
14344 let wlgAssetIdKey = "wlg_assetId"
14445
14546 let wlgAssetId = valueOrErrorMessage(getBinary(wlgContract, wlgAssetIdKey), "WLGOLD is not issued yet")
14647
147-func asString (v) = match v {
148- case s: String =>
149- s
150- case _ =>
151- throw("fail to cast into String")
152-}
48+func keySellerByAssetId (assetId) = ("seller_" + assetId)
49+
50+
51+func keyPriceByAssetId (assetId) = ("price_" + assetId)
52+
53+
54+func keyAssetIdsBySeller (addr) = ("assetIds_" + addr)
15355
15456
15557 func asInt (v) = match v {
16870 }
16971
17072
171-func padL (val,len) = {
172- let valS = toString(val)
173- let zeroes = drop(toString(pow(10, 0, (len - size(valS)), 0, 0, DOWN)), 1)
174- (zeroes + valS)
175- }
73+let teamAddrKey = "teamAddr"
17674
177-
178-let MAXTOURNAMENTLENGTH = 1296000000
179-
180-let HOUR = 3600000
181-
182-let adminsList = [toString(this), match chain {
183- case _ =>
184- if ((base58'2W' == $match0))
185- then "3PEe2RELUHCFCBsmSCNcBJ8N3URLVQende7"
186- else if ((base58'2T' == $match0))
187- then "3MtBgJTaLxPB3C7UJD1UE8qjkHthfKvFQYY"
188- else throw("Unknown chain")
189-}]
190-
191-func staticData (txId,registerCost,attemptCost,creationTime,startTime,endTime,numGrands,prizeFund,prizeAsset) = makeString(["%s%d%d%d%d%d%d%d%s", txId, toString(registerCost), toString(attemptCost), toString(creationTime), toString(startTime), toString(endTime), toString(numGrands), toString(prizeFund), prizeAsset], SEP)
192-
193-
194-func dynamicData (status,leaders,winResult,totalRegs,totalAttempts) = makeString_2C(["%s%s%d%d%d", status, leaders, toString(winResult), toString(totalRegs), toString(totalAttempts)], SEP)
195-
196-
197-func prolog () = asInt(reentrantInvoke(stakingContract, "saveLastTx", nil, nil))
198-
199-
200-func duckByCaller (caller) = valueOrErrorMessage(getString(stakingContract, keyStakedDuckByOwner(toString(caller))), "You don't have a duck staked")
75+func prolog2 () = asInt(reentrantInvoke(acres2Contract, "saveLastTx", nil, nil))
20176
20277
20378 @Callable(i)
204-func createTournament (startTime,endTime,registerCost,attemptCost,numGrands,prizeFund,prizeAsset) = {
205- let caller = toString(i.caller)
206- if (!(containsElement(adminsList, caller)))
207- then throw("Permission denied")
208- else {
209- let lastId = getInteger(lastTourIdKey)
210- let tId = if (isDefined(lastId))
211- then {
212- let lastTourId = value(lastId)
213- let dynamic = valueOrErrorMessage(getString(keyTourDynamicDataById(lastTourId)), (("Error reading tournament " + toString(lastTourId)) + " data"))
214- let status = split(dynamic, SEP)[tDynamicStatus]
215- if (if ((status != "ARCHIVED"))
216- then (status != "PROCESSING")
217- else false)
218- then throw(("Current tournement is not completed, status=" + status))
219- else (lastTourId + 1)
79+func placeSellOrder (price) = {
80+ let prologResult = prolog2()
81+ if ((prologResult == prologResult))
82+ then if ((0 >= price))
83+ then throw("Price should be positive")
84+ else if ((size(i.payments) != 2))
85+ then throw("Exactly 2 payments required: NFT and 5% fee in WLGOLD")
86+ else {
87+ let pmt = value(i.payments[0])
88+ if ((pmt.amount != 1))
89+ then throw("NFT token should be attached as 1st payment")
90+ else {
91+ let pmt1 = value(i.payments[1])
92+ let wAssetId = valueOrErrorMessage(pmt1.assetId, "No WAVES payments allowed")
93+ if ((wAssetId != wlgAssetId))
94+ then throw("Only WLGOLD payments are accepted as 2nd payment")
95+ else {
96+ let change = (pmt1.amount - (price / 20))
97+ if ((0 > change))
98+ then throw("5% fee should be attached as 2nd payment")
99+ else {
100+ let changeActions = if ((change > 0))
101+ then [ScriptTransfer(i.caller, change, wlgAssetId)]
102+ else nil
103+ let assetId = valueOrErrorMessage(pmt.assetId, "No WAVES payments allowed")
104+ let asset = value(assetInfo(assetId))
105+ let assetIdStr = toBase58String(assetId)
106+ let addr = toString(i.caller)
107+ if ((asset.issuer != acres2Contract))
108+ then throw("Only WavesLands NFT tokens are accepted")
109+ else {
110+ let nftsKey = keyAssetIdsBySeller(addr)
111+ let nftsStr = valueOrElse(getString(nftsKey), "")
112+ let nfts = if ((nftsStr != ""))
113+ then split_51C(value(nftsStr), "_")
114+ else nil
115+ $Tuple2(([IntegerEntry(keyPriceByAssetId(assetIdStr), price), StringEntry(keySellerByAssetId(assetIdStr), addr), StringEntry(nftsKey, makeString_11C((nfts :+ assetIdStr), "_"))] ++ changeActions), prologResult)
116+ }
117+ }
118+ }
119+ }
220120 }
221- else 1
222- let now = lastBlock.timestamp
223- if ((now > startTime))
224- then throw(((("startTime=" + toString(startTime)) + " < creationTime=") + toString(now)))
225- else if ((startTime > endTime))
226- then throw(((("endTime=" + toString(endTime)) + " < startTime=") + toString(startTime)))
227- else if (((endTime - startTime) > MAXTOURNAMENTLENGTH))
228- then throw(((("Tournament period exceeds max: " + toString((endTime - startTime))) + " > ") + toString(MAXTOURNAMENTLENGTH)))
229- else if (if ((0 > registerCost))
230- then true
231- else (0 > attemptCost))
232- then throw(((("Cost should be positive, but passed " + toString(registerCost)) + " and ") + toString(attemptCost)))
233- else if ((0 > numGrands))
234- then throw("Number of Grand Prizes should be non-negative")
235- else if ((0 > prizeFund))
236- then throw("Prize Fund should be non-negative")
237- else $Tuple2([IntegerEntry(lastTourIdKey, tId), StringEntry(keyTourStaticDataById(tId), staticData(toBase58String(i.transactionId), registerCost, attemptCost, now, startTime, endTime, numGrands, prizeFund, prizeAsset)), StringEntry(keyTourDynamicDataById(tId), dynamicData("CREATED", " ", 0, 0, 0))], tId)
238- }
121+ else throw("Strict value is not equal to itself.")
239122 }
240123
241124
242125
243126 @Callable(i)
244-func register () = {
245- let prologResult = prolog()
127+func cancelSellOrder (assetIdStr) = {
128+ let prologResult = prolog2()
246129 if ((prologResult == prologResult))
247130 then {
248- let lastId = valueOrErrorMessage(getInteger(lastTourIdKey), "No active tournaments")
249- let now = lastBlock.timestamp
250- let tData = getTourData(this, lastId)
251- let static = tData[idxStatic]
252- let dynamic = tData[idxDynamic]
253- let status = dynamic[tDynamicStatus]
254- if (!(if (if (if ((status == "CREATED"))
255- then (now > parseIntValue(static[tStaticStart]))
256- else false)
257- then ((parseIntValue(static[tStaticEnd]) - HOUR) > now)
258- else false)
259- then true
260- else if ((status == "INPROGRESS"))
261- then ((parseIntValue(static[tStaticEnd]) - HOUR) > now)
262- else false))
263- then throw("Cannot register now")
131+ let addr = toString(i.caller)
132+ let nftsKey = keyAssetIdsBySeller(addr)
133+ let nftsStr = valueOrElse(getString(nftsKey), "")
134+ let nfts = if ((nftsStr != ""))
135+ then split_51C(value(nftsStr), "_")
136+ else nil
137+ let idx = indexOf(nfts, assetIdStr)
138+ if (!(isDefined(idx)))
139+ then throw(("Your don't have sell order for " + assetIdStr))
264140 else {
265- let regCost = parseIntValue(static[tStaticRegisterCost])
266- let assetId = if ((size(static) > tStaticAsset))
267- then fromBase58String(static[tStaticAsset])
268- else wlgAssetId
269- let nfo = valueOrErrorMessage(assetInfo(assetId), "No assetInfo available")
270- let assetName = nfo.name
271- let assetDecimals = nfo.decimals
272- let regAmt = if ((regCost > 0))
273- then if ((size(i.payments) != 1))
274- then throw("exactly 1 payment must be attached")
275- else {
276- let pmt = i.payments[0]
277- if (if (!(isDefined(pmt.assetId)))
278- then true
279- else (value(pmt.assetId) != assetId))
280- then throw((assetName + " payments only!"))
281- else pmt.amount
282- }
283- else if ((size(i.payments) != 0))
284- then throw("No payments required")
285- else 0
286- if ((regAmt != regCost))
287- then throw(((("Need payment of " + fixedPoint(regCost, assetDecimals)) + " ") + assetName))
288- else {
289- let duckAssetId = duckByCaller(i.originCaller)
290- let scoreKey = keyScoreBoardByTour(lastId)
291- let oldScoreBoard = valueOrElse(getString(scoreKey), "")
292- if (if (valueOrElse(getBoolean(keyIsRegisteredByTourAndDuck(lastId, duckAssetId)), false))
293- then true
294- else contains(oldScoreBoard, duckAssetId))
295- then throw(((("Your duck " + duckAssetId) + " is already registered at tournament ") + toString(lastId)))
296- else {
297- let updatedDynamicData = dynamicData("INPROGRESS", dynamic[tDynamicLeaders], parseIntValue(dynamic[tDynamicWinResult]), (parseIntValue(dynamic[tDynamicTotalRegCount]) + 1), parseIntValue(dynamic[tDynamicTotalAttempts]))
298- $Tuple2([IntegerEntry(keyLastRegisteredTourByDuck(duckAssetId), lastId), BooleanEntry(keyIsRegisteredByTourAndDuck(lastId, duckAssetId), true), StringEntry(scoreKey, if ((oldScoreBoard == ""))
299- then (duckAssetId + ":000")
300- else (((oldScoreBoard + "_") + duckAssetId) + ":000")), StringEntry(keyTourDynamicDataById(lastId), updatedDynamicData)], prologResult)
301- }
302- }
141+ let listAction = if ((size(nfts) > 1))
142+ then StringEntry(nftsKey, makeString_11C(removeByIndex(nfts, value(idx)), "_"))
143+ else DeleteEntry(nftsKey)
144+ let price = valueOrErrorMessage(getInteger(keyPriceByAssetId(assetIdStr)), ("You don't have sell order for " + assetIdStr))
145+ $Tuple2([listAction, DeleteEntry(keySellerByAssetId(assetIdStr)), DeleteEntry(keyPriceByAssetId(assetIdStr)), ScriptTransfer(i.caller, (price / 20), wlgAssetId)], prologResult)
303146 }
304147 }
305148 else throw("Strict value is not equal to itself.")
308151
309152
310153 @Callable(i)
311-func newAttempt () = {
312- let prologResult = prolog()
154+func acceptSellOrder (assetIdStr) = {
155+ let prologResult = prolog2()
313156 if ((prologResult == prologResult))
314- then {
315- let duckAssetId = duckByCaller(i.originCaller)
316- let lastId = valueOrErrorMessage(getInteger(lastTourIdKey), "No active tournaments")
317- let now = lastBlock.timestamp
318- let tData = getTourData(this, lastId)
319- let static = tData[idxStatic]
320- let dynamic = tData[idxDynamic]
321- let status = dynamic[tDynamicStatus]
322- if (!(if ((status == "INPROGRESS"))
323- then ((parseIntValue(static[tStaticEnd]) - HOUR) > now)
324- else false))
325- then throw("Attempt is not possible")
326- else if (!(valueOrElse(getBoolean(keyIsRegisteredByTourAndDuck(lastId, duckAssetId)), false)))
327- then throw(((("Your duck " + duckAssetId) + " is not registered at tournament ") + toString(lastId)))
157+ then if ((size(i.payments) != 1))
158+ then throw("exactly 1 payment must be attached")
159+ else {
160+ let pmt = i.payments[0]
161+ if (if (!(isDefined(pmt.assetId)))
162+ then true
163+ else (value(pmt.assetId) != wlgAssetId))
164+ then throw("WLGOLD payments only!")
328165 else {
329- let attemptsIteratorKey = keyLastAttemptByTourAndDuck(lastId, duckAssetId)
330- let lastAttempt = getInteger(attemptsIteratorKey)
331- let $t067497614 = if (!(isDefined(lastAttempt)))
332- then $Tuple2(0, 0)
333- else if ((size(i.payments) != 1))
334- then throw("exactly 1 payment must be attached")
335- else {
336- let pmt = i.payments[0]
337- let assetId = if ((size(static) > tStaticAsset))
338- then fromBase58String(static[tStaticAsset])
339- else wlgAssetId
340- let nfo = valueOrErrorMessage(assetInfo(assetId), "No assetInfo available")
341- let assetName = nfo.name
342- let assetDecimals = nfo.decimals
343- let amt = pmt.amount
344- if (if (!(isDefined(pmt.assetId)))
345- then true
346- else (value(pmt.assetId) != assetId))
347- then throw((assetName + " payments only!"))
348- else {
349- let attCost = parseIntValue(static[tStaticAttemptCost])
350- if ((amt != attCost))
351- then throw(((("Need payment of " + fixedPoint(attCost, assetDecimals)) + " ") + assetName))
352- else $Tuple2((value(lastAttempt) + 1), 1)
353- }
354- }
355- let payedAttempts = $t067497614._1
356- let increment = $t067497614._2
357- let updatedDynamicData = dynamicData("INPROGRESS", dynamic[tDynamicLeaders], parseIntValue(dynamic[tDynamicWinResult]), parseIntValue(dynamic[tDynamicTotalRegCount]), (parseIntValue(dynamic[tDynamicTotalAttempts]) + increment))
358- let tourLoc = asString(invoke(stakingContract, "initDuckTourAttempt", [duckAssetId], nil))
359- $Tuple2([IntegerEntry(attemptsIteratorKey, payedAttempts), StringEntry(keyTourDynamicDataById(lastId), updatedDynamicData)], [prologResult, payedAttempts, tourLoc])
360- }
361- }
362- else throw("Strict value is not equal to itself.")
363- }
364-
365-
366-
367-@Callable(i)
368-func saveDuckResult (duckAssetId,duckNewBest) = if ((i.caller != stakingContract))
369- then throw("Access denied")
370- else {
371- let lastId = valueOrErrorMessage(getInteger(lastTourIdKey), "No active tournaments")
372- let tData = getTourData(this, lastId)
373- let static = tData[idxStatic]
374- let dynamic = tData[idxDynamic]
375- let curLocation = valueOrElse(getString(stakingContract, keyDuckLocation(duckAssetId)), DEFAULTLOCATION)
376- let bestResultKey = keyBestResultByTourAndDuck(lastId, duckAssetId)
377- let sumScoresKey = keySumScoresByTour(lastId)
378- let oldSumScores = valueOrElse(getInteger(sumScoresKey), 0)
379- if (isInTournament(this, curLocation))
380- then {
381- let duckOldBest = valueOrElse(getInteger(bestResultKey), 0)
382- let scoreKey = keyScoreBoardByTour(lastId)
383- let oldScoreBoard = valueOrElse(getString(scoreKey), "")
384- let $t0910710268 = if ((duckNewBest > duckOldBest))
385- then if (!(contains(oldScoreBoard, duckAssetId)))
386- then throw(("scoreBoard does not contain " + duckAssetId))
387- else {
388- let oldBest = parseIntValue(dynamic[tDynamicWinResult])
389- let leaders = dynamic[tDynamicLeaders]
390- let oldLeadersList = if (if ((leaders == ""))
391- then true
392- else (leaders == " "))
393- then nil
394- else split_4C(leaders, ",")
395- let newLeadersList = if ((duckNewBest > oldBest))
396- then [duckAssetId]
397- else if (if ((oldBest > duckNewBest))
398- then true
399- else containsElement(oldLeadersList, duckAssetId))
400- then oldLeadersList
401- else (oldLeadersList :+ duckAssetId)
402- let updatedDynamicData = dynamicData("INPROGRESS", makeString_2C(newLeadersList, ","), max([duckNewBest, oldBest]), parseIntValue(dynamic[tDynamicTotalRegCount]), parseIntValue(dynamic[tDynamicTotalAttempts]))
403- let parts = split_51C(oldScoreBoard, duckAssetId)
404- $Tuple3(((((parts[0] + duckAssetId) + ":") + padL(duckNewBest, 3)) + drop(parts[1], 4)), ((oldSumScores + duckNewBest) - duckOldBest), [StringEntry(keyTourDynamicDataById(lastId), updatedDynamicData)])
405- }
406- else $Tuple3(oldScoreBoard, oldSumScores, nil)
407- let newScoreBoard = $t0910710268._1
408- let newSumScores = $t0910710268._2
409- let globalActions = $t0910710268._3
410- $Tuple2(([IntegerEntry(bestResultKey, max([duckOldBest, duckNewBest])), IntegerEntry(sumScoresKey, newSumScores), StringEntry(keyBestTxByTourAndDuck(lastId, duckAssetId), toBase58String(i.transactionId)), StringEntry(scoreKey, newScoreBoard)] ++ globalActions), 0)
411- }
412- else $Tuple2(nil, 0)
413- }
414-
415-
416-
417-@Callable(i)
418-func processTournament (tId) = {
419- let caller = toString(i.caller)
420- if (!(containsElement(adminsList, caller)))
421- then throw("Permission denied")
422- else {
423- let now = lastBlock.timestamp
424- let tData = getTourData(this, tId)
425- let static = tData[idxStatic]
426- let dynamic = tData[idxDynamic]
427- let status = dynamic[tDynamicStatus]
428- let registrations = parseIntValue(dynamic[tDynamicTotalRegCount])
429- let paidAttempts = parseIntValue(dynamic[tDynamicTotalAttempts])
430- let regCost = parseIntValue(static[tStaticRegisterCost])
431- let attCost = parseIntValue(static[tStaticAttemptCost])
432- if ((status == "ARCHIVED"))
433- then throw((("Tournament " + toString(tId)) + " is already ARCHIVED"))
434- else if (if ((status == "INPROGRESS"))
435- then (parseIntValue(static[tStaticEnd]) > now)
436- else false)
437- then throw((("Tournament " + toString(tId)) + " is not over yet"))
438- else {
439- let updatedDynamicData = dynamicData("PROCESSING", dynamic[tDynamicLeaders], parseIntValue(dynamic[tDynamicWinResult]), registrations, paidAttempts)
440- let prizeFund = if ((size(static) > tStaticPrizeFund))
441- then parseIntValue(static[tStaticPrizeFund])
442- else 0
443- let unpaid = ((((registrations * regCost) + (paidAttempts * attCost)) / 2) + prizeFund)
444- $Tuple2([StringEntry(keyTourDynamicDataById(tId), updatedDynamicData), IntegerEntry(keyUnpaidRewardsByTour(tId), unpaid)], 0)
445- }
446- }
447- }
448-
449-
450-
451-@Callable(i)
452-func claimPrize (tId) = {
453- let prologResult = prolog()
454- if ((prologResult == prologResult))
455- then if ((size(i.payments) != 0))
456- then throw("No payments required")
457- else {
458- let tData = getTourData(this, tId)
459- let static = tData[idxStatic]
460- let dynamic = tData[idxDynamic]
461- let status = dynamic[tDynamicStatus]
462- if ((status != "PROCESSING"))
463- then throw((("Tournament " + toString(tId)) + " is not PROCESSING"))
464- else {
465- let registrations = parseIntValue(dynamic[tDynamicTotalRegCount])
466- let paidAttempts = parseIntValue(dynamic[tDynamicTotalAttempts])
467- let regCost = parseIntValue(static[tStaticRegisterCost])
468- let attCost = parseIntValue(static[tStaticAttemptCost])
469- let prizeFund = if ((size(static) > tStaticPrizeFund))
470- then parseIntValue(static[tStaticPrizeFund])
471- else 0
472- let awardFunds = ((((registrations * regCost) + (paidAttempts * attCost)) / 2) + prizeFund)
473- let unpaidKey = keyUnpaidRewardsByTour(tId)
474- let unpaidFunds = valueOrElse(getInteger(unpaidKey), 0)
475- let duckAssetId = duckByCaller(i.originCaller)
476- if (!(valueOrElse(getBoolean(keyIsRegisteredByTourAndDuck(tId, duckAssetId)), false)))
477- then throw(((("Your duck " + duckAssetId) + " is not registered at tournament ") + toString(tId)))
166+ let price = valueOrErrorMessage(getInteger(keyPriceByAssetId(assetIdStr)), (("NFT " + assetIdStr) + " is not selling"))
167+ let change = (pmt.amount - price)
168+ if ((0 > change))
169+ then throw((("Payment attached doesn't cover sell price of " + fixedPoint(price, 8)) + " WLGOLD"))
478170 else {
479- let bestResultKey = keyBestResultByTourAndDuck(tId, duckAssetId)
480- let duckBest = valueOrElse(getInteger(bestResultKey), 0)
481- if ((duckBest == 0))
482- then throw("Your duck got zero score")
171+ let changeActions = if ((change > 0))
172+ then [ScriptTransfer(i.caller, change, wlgAssetId)]
173+ else nil
174+ let seller = valueOrErrorMessage(getString(keySellerByAssetId(assetIdStr)), (("NFT " + assetIdStr) + " is not selling"))
175+ let nftsKey = keyAssetIdsBySeller(seller)
176+ let nftsStr = valueOrElse(getString(nftsKey), "")
177+ let nfts = if ((nftsStr != ""))
178+ then split_51C(value(nftsStr), "_")
179+ else nil
180+ let idx = indexOf(nfts, assetIdStr)
181+ if (!(isDefined(idx)))
182+ then throw(("Seller don't have sell order for " + assetIdStr))
483183 else {
484- let awardedKey = keyIsAwardedByTourAndDuck(tId, duckAssetId)
485- if (valueOrElse(getBoolean(awardedKey), false))
486- then throw(((("Your duck " + duckAssetId) + " is already awarded at tournament ") + toString(tId)))
487- else {
488- let sumScoresKey = keySumScoresByTour(tId)
489- let sumScores = valueOrElse(getInteger(sumScoresKey), 0)
490- let leaders = dynamic[tDynamicLeaders]
491- let leadersList = if (if ((leaders == ""))
492- then true
493- else (leaders == " "))
494- then nil
495- else split_4C(leaders, ",")
496- let numLeaders = size(leadersList)
497- if ((numLeaders == 0))
498- then throw(("No leaders at tournament " + toString(tId)))
499- else {
500- let numGrands = parseIntValue(static[tStaticNumGrands])
501- let winResult = parseIntValue(dynamic[tDynamicWinResult])
502- let sumLeaderScores = if ((numLeaders > numGrands))
503- then 0
504- else if (containsElement(leadersList, duckAssetId))
505- then throw("As one of winners, you will be awarded by admins")
506- else (numLeaders * winResult)
507- let yourAmount = min([fraction(duckBest, awardFunds, (sumScores - sumLeaderScores)), unpaidFunds])
508- let newUnpaidAmount = (unpaidFunds - yourAmount)
509- let updatedDynamicData = dynamicData("ARCHIVED", dynamic[tDynamicLeaders], winResult, registrations, paidAttempts)
510- let archiveAction = if ((0 >= newUnpaidAmount))
511- then [StringEntry(keyTourDynamicDataById(tId), updatedDynamicData)]
512- else nil
513- let assetId = if ((size(static) > tStaticAsset))
514- then fromBase58String(static[tStaticAsset])
515- else wlgAssetId
516- let loc = split(valueOrElse(getString(stakingContract, keyDuckLocation(duckAssetId)), DEFAULTLOCATION), "_")
517- let breakActions = if (if ((loc[locIdxType] == "T"))
518- then (getTourData(this, parseIntValue(loc[locIdxContinent]))[idxDynamic][tDynamicStatus] == "PROCESSING")
519- else false)
520- then invoke(stakingContract, "breakAttemptCallback", nil, nil)
521- else unit
522- $Tuple2(([ScriptTransfer(i.caller, yourAmount, assetId), BooleanEntry(awardedKey, true), IntegerEntry(unpaidKey, newUnpaidAmount)] ++ archiveAction), breakActions)
523- }
524- }
184+ let listAction = if ((size(nfts) > 1))
185+ then StringEntry(nftsKey, makeString_11C(removeByIndex(nfts, value(idx)), "_"))
186+ else DeleteEntry(nftsKey)
187+ let fee = (price / 20)
188+ let forTeam = (fee / 2)
189+ let wlgRemain = asInt(invoke(wlgContract, "burnWlgold", [(fee - forTeam)], nil))
190+ $Tuple2(([listAction, DeleteEntry(keySellerByAssetId(assetIdStr)), DeleteEntry(keyPriceByAssetId(assetIdStr)), ScriptTransfer(addressFromStringValue(seller), price, wlgAssetId), ScriptTransfer(addressFromStringValue(getStringValue(wlgContract, teamAddrKey)), forTeam, wlgAssetId), ScriptTransfer(i.caller, 1, fromBase58String(assetIdStr))] ++ changeActions), prologResult)
525191 }
526192 }
527193 }
Full:
OldNewDifferences
11 {-# STDLIB_VERSION 6 #-}
22 {-# SCRIPT_TYPE ACCOUNT #-}
33 {-# CONTENT_TYPE DAPP #-}
4-let DEFAULTLOCATION = "Africa_F_Africa"
5-
6-let locIdxContinent = 0
7-
8-let locIdxType = 1
9-
10-func keyStakedDuckByOwner (ownerAddr) = ("stakedDuckByOwner_" + ownerAddr)
11-
12-
13-func keyDuckLocation (duckAssetId) = ("duckLocation_" + duckAssetId)
14-
15-
16-let lastTourIdKey = "%s__lastTourId"
17-
18-func keyTourStaticDataById (tId) = ("%s%d__tourStaticData__" + toString(tId))
19-
20-
21-func keyTourDynamicDataById (tId) = ("%s%d__tourDynamicData__" + toString(tId))
22-
23-
24-func keyScoreBoardByTour (tId) = ("%s%d__scoreBoard__" + toString(tId))
25-
26-
27-func keySumScoresByTour (tId) = ("%s%d__sumScores__" + toString(tId))
28-
29-
30-func keyUnpaidRewardsByTour (tId) = ("%s%d__unpaidRewards__" + toString(tId))
31-
32-
33-func keyLastRegisteredTourByDuck (duckAssetId) = ("%s%s__lastRegisteredTourByDuck__" + duckAssetId)
34-
35-
36-func keyIsRegisteredByTourAndDuck (tId,duckAssetId) = makeString(["%s%d%s__isRegisteredByTourAndDuck", toString(tId), duckAssetId], "__")
37-
38-
39-func keyIsAwardedByTourAndDuck (tId,duckAssetId) = makeString(["%s%d%s__isAwardedByTourAndDuck", toString(tId), duckAssetId], "__")
40-
41-
42-func keyLastAttemptByTourAndDuck (tId,duckAssetId) = makeString(["%s%d%s__lastAttemptByTourAndDuck", toString(tId), duckAssetId], "__")
43-
44-
45-func keyBestResultByTourAndDuck (tId,duckAssetId) = makeString(["%s%d%s__bestResultByTourAndDuck", toString(tId), duckAssetId], "__")
46-
47-
48-func keyBestTxByTourAndDuck (tId,duckAssetId) = makeString(["%s%d%s__bestTxByTourAndDuck", toString(tId), duckAssetId], "__")
49-
50-
51-let idxStatic = 0
52-
53-let idxDynamic = 1
54-
55-let tStaticRegisterCost = 2
56-
57-let tStaticAttemptCost = 3
58-
59-let tStaticStart = 5
60-
61-let tStaticEnd = 6
62-
63-let tStaticNumGrands = 7
64-
65-let tStaticPrizeFund = 8
66-
67-let tStaticAsset = 9
68-
69-let tDynamicStatus = 1
70-
71-let tDynamicLeaders = 2
72-
73-let tDynamicWinResult = 3
74-
75-let tDynamicTotalRegCount = 4
76-
77-let tDynamicTotalAttempts = 5
78-
79-func getTourData (tourContract,tId) = {
80- let static = split(valueOrErrorMessage(getString(tourContract, keyTourStaticDataById(tId)), (("Error reading tournament " + toString(tId)) + " data")), "__")
81- let dynamic = split_4C(valueOrErrorMessage(getString(tourContract, keyTourDynamicDataById(tId)), (("Error reading tournament " + toString(tId)) + " data")), "__")
82-[static, dynamic]
83- }
84-
85-
86-func isInTournament (tourContract,location) = {
87- let lastId = valueOrElse(getInteger(tourContract, lastTourIdKey), 0)
88- let loc = split(location, "_")
89- let now = lastBlock.timestamp
90- let tData = getTourData(tourContract, lastId)
91- let static = tData[idxStatic]
92- let dynamic = tData[idxDynamic]
93- if (if (if ((loc[locIdxType] == "T"))
94- then (parseIntValue(loc[locIdxContinent]) == lastId)
95- else false)
96- then (dynamic[tDynamicStatus] == "INPROGRESS")
97- else false)
98- then (parseIntValue(static[tStaticEnd]) > now)
99- else false
100- }
101-
4+let SEP = "__"
1025
1036 let chain = take(drop(this.bytes, 1), 1)
1047
105-let defaultRestAddressStr = match chain {
8+let defaultRest2AddressStr = match chain {
1069 case _ =>
10710 if ((base58'2W' == $match0))
108- then "3PQCuvFbvh4LkPUnrnU1z3jnbA1p9m3WNhv"
11+ then "3PFwYta8biEz31zpeFe5DJK8wE5trSpQVF8"
10912 else if ((base58'2T' == $match0))
110- then "3MumkGGztCKAXpWDqxkddofqXSUbqQkvSJy"
13+ then "3N7UuYar6264P58FBhVWKPQAh4Yua2hgngv"
11114 else throw("Unknown chain")
11215 }
113-
114-let SEP = "__"
11516
11617 func getStringOrFail (address,key) = valueOrErrorMessage(getString(address, key), makeString(["mandatory ", toString(address), ".", key, " is not defined"], ""))
11718
11819
119-let IdxCfgStakingDapp = 1
20+let IdxCfgAcres2Dapp = 1
12021
121-let IdxCfgWlgDapp = 4
22+let IdxCfgWlgDapp = 2
12223
12324 func keyRestCfg () = "%s__restConfig"
12425
12526
126-func keyRestAddress () = "%s__restAddr"
27+func keyRest2Address () = "%s__rest2Addr"
12728
12829
12930 func readRestCfgOrFail (rest) = split_4C(getStringOrFail(rest, keyRestCfg()), SEP)
13031
13132
132-func getContractAddressOrFail (restCfg,idx) = valueOrErrorMessage(addressFromString(restCfg[idx]), ("Rest cfg doesn't contain address at index " + toString(idx)))
33+func getContractAddressOrFail (rest2Cfg,idx) = valueOrErrorMessage(addressFromString(rest2Cfg[idx]), ("Rest cfg doesn't contain address at index " + toString(idx)))
13334
13435
135-let restContract = addressFromStringValue(valueOrElse(getString(this, keyRestAddress()), defaultRestAddressStr))
36+let rest2Contract = addressFromStringValue(valueOrElse(getString(this, keyRest2Address()), defaultRest2AddressStr))
13637
137-let restCfg = readRestCfgOrFail(restContract)
38+let rest2Cfg = readRestCfgOrFail(rest2Contract)
13839
139-let stakingContract = getContractAddressOrFail(restCfg, IdxCfgStakingDapp)
40+let acres2Contract = getContractAddressOrFail(rest2Cfg, IdxCfgAcres2Dapp)
14041
141-let wlgContract = getContractAddressOrFail(restCfg, IdxCfgWlgDapp)
42+let wlgContract = getContractAddressOrFail(rest2Cfg, IdxCfgWlgDapp)
14243
14344 let wlgAssetIdKey = "wlg_assetId"
14445
14546 let wlgAssetId = valueOrErrorMessage(getBinary(wlgContract, wlgAssetIdKey), "WLGOLD is not issued yet")
14647
147-func asString (v) = match v {
148- case s: String =>
149- s
150- case _ =>
151- throw("fail to cast into String")
152-}
48+func keySellerByAssetId (assetId) = ("seller_" + assetId)
49+
50+
51+func keyPriceByAssetId (assetId) = ("price_" + assetId)
52+
53+
54+func keyAssetIdsBySeller (addr) = ("assetIds_" + addr)
15355
15456
15557 func asInt (v) = match v {
15658 case n: Int =>
15759 n
15860 case _ =>
15961 throw("fail to cast into Int")
16062 }
16163
16264
16365 func fixedPoint (val,decimals) = {
16466 let tenPow = pow(10, 0, decimals, 0, 0, DOWN)
16567 let lowPart = toString((val % tenPow))
16668 let zeroes = drop(toString(tenPow), (1 + size(lowPart)))
16769 (((toString((val / tenPow)) + ".") + zeroes) + lowPart)
16870 }
16971
17072
171-func padL (val,len) = {
172- let valS = toString(val)
173- let zeroes = drop(toString(pow(10, 0, (len - size(valS)), 0, 0, DOWN)), 1)
174- (zeroes + valS)
175- }
73+let teamAddrKey = "teamAddr"
17674
177-
178-let MAXTOURNAMENTLENGTH = 1296000000
179-
180-let HOUR = 3600000
181-
182-let adminsList = [toString(this), match chain {
183- case _ =>
184- if ((base58'2W' == $match0))
185- then "3PEe2RELUHCFCBsmSCNcBJ8N3URLVQende7"
186- else if ((base58'2T' == $match0))
187- then "3MtBgJTaLxPB3C7UJD1UE8qjkHthfKvFQYY"
188- else throw("Unknown chain")
189-}]
190-
191-func staticData (txId,registerCost,attemptCost,creationTime,startTime,endTime,numGrands,prizeFund,prizeAsset) = makeString(["%s%d%d%d%d%d%d%d%s", txId, toString(registerCost), toString(attemptCost), toString(creationTime), toString(startTime), toString(endTime), toString(numGrands), toString(prizeFund), prizeAsset], SEP)
192-
193-
194-func dynamicData (status,leaders,winResult,totalRegs,totalAttempts) = makeString_2C(["%s%s%d%d%d", status, leaders, toString(winResult), toString(totalRegs), toString(totalAttempts)], SEP)
195-
196-
197-func prolog () = asInt(reentrantInvoke(stakingContract, "saveLastTx", nil, nil))
198-
199-
200-func duckByCaller (caller) = valueOrErrorMessage(getString(stakingContract, keyStakedDuckByOwner(toString(caller))), "You don't have a duck staked")
75+func prolog2 () = asInt(reentrantInvoke(acres2Contract, "saveLastTx", nil, nil))
20176
20277
20378 @Callable(i)
204-func createTournament (startTime,endTime,registerCost,attemptCost,numGrands,prizeFund,prizeAsset) = {
205- let caller = toString(i.caller)
206- if (!(containsElement(adminsList, caller)))
207- then throw("Permission denied")
208- else {
209- let lastId = getInteger(lastTourIdKey)
210- let tId = if (isDefined(lastId))
211- then {
212- let lastTourId = value(lastId)
213- let dynamic = valueOrErrorMessage(getString(keyTourDynamicDataById(lastTourId)), (("Error reading tournament " + toString(lastTourId)) + " data"))
214- let status = split(dynamic, SEP)[tDynamicStatus]
215- if (if ((status != "ARCHIVED"))
216- then (status != "PROCESSING")
217- else false)
218- then throw(("Current tournement is not completed, status=" + status))
219- else (lastTourId + 1)
79+func placeSellOrder (price) = {
80+ let prologResult = prolog2()
81+ if ((prologResult == prologResult))
82+ then if ((0 >= price))
83+ then throw("Price should be positive")
84+ else if ((size(i.payments) != 2))
85+ then throw("Exactly 2 payments required: NFT and 5% fee in WLGOLD")
86+ else {
87+ let pmt = value(i.payments[0])
88+ if ((pmt.amount != 1))
89+ then throw("NFT token should be attached as 1st payment")
90+ else {
91+ let pmt1 = value(i.payments[1])
92+ let wAssetId = valueOrErrorMessage(pmt1.assetId, "No WAVES payments allowed")
93+ if ((wAssetId != wlgAssetId))
94+ then throw("Only WLGOLD payments are accepted as 2nd payment")
95+ else {
96+ let change = (pmt1.amount - (price / 20))
97+ if ((0 > change))
98+ then throw("5% fee should be attached as 2nd payment")
99+ else {
100+ let changeActions = if ((change > 0))
101+ then [ScriptTransfer(i.caller, change, wlgAssetId)]
102+ else nil
103+ let assetId = valueOrErrorMessage(pmt.assetId, "No WAVES payments allowed")
104+ let asset = value(assetInfo(assetId))
105+ let assetIdStr = toBase58String(assetId)
106+ let addr = toString(i.caller)
107+ if ((asset.issuer != acres2Contract))
108+ then throw("Only WavesLands NFT tokens are accepted")
109+ else {
110+ let nftsKey = keyAssetIdsBySeller(addr)
111+ let nftsStr = valueOrElse(getString(nftsKey), "")
112+ let nfts = if ((nftsStr != ""))
113+ then split_51C(value(nftsStr), "_")
114+ else nil
115+ $Tuple2(([IntegerEntry(keyPriceByAssetId(assetIdStr), price), StringEntry(keySellerByAssetId(assetIdStr), addr), StringEntry(nftsKey, makeString_11C((nfts :+ assetIdStr), "_"))] ++ changeActions), prologResult)
116+ }
117+ }
118+ }
119+ }
220120 }
221- else 1
222- let now = lastBlock.timestamp
223- if ((now > startTime))
224- then throw(((("startTime=" + toString(startTime)) + " < creationTime=") + toString(now)))
225- else if ((startTime > endTime))
226- then throw(((("endTime=" + toString(endTime)) + " < startTime=") + toString(startTime)))
227- else if (((endTime - startTime) > MAXTOURNAMENTLENGTH))
228- then throw(((("Tournament period exceeds max: " + toString((endTime - startTime))) + " > ") + toString(MAXTOURNAMENTLENGTH)))
229- else if (if ((0 > registerCost))
230- then true
231- else (0 > attemptCost))
232- then throw(((("Cost should be positive, but passed " + toString(registerCost)) + " and ") + toString(attemptCost)))
233- else if ((0 > numGrands))
234- then throw("Number of Grand Prizes should be non-negative")
235- else if ((0 > prizeFund))
236- then throw("Prize Fund should be non-negative")
237- else $Tuple2([IntegerEntry(lastTourIdKey, tId), StringEntry(keyTourStaticDataById(tId), staticData(toBase58String(i.transactionId), registerCost, attemptCost, now, startTime, endTime, numGrands, prizeFund, prizeAsset)), StringEntry(keyTourDynamicDataById(tId), dynamicData("CREATED", " ", 0, 0, 0))], tId)
238- }
121+ else throw("Strict value is not equal to itself.")
239122 }
240123
241124
242125
243126 @Callable(i)
244-func register () = {
245- let prologResult = prolog()
127+func cancelSellOrder (assetIdStr) = {
128+ let prologResult = prolog2()
246129 if ((prologResult == prologResult))
247130 then {
248- let lastId = valueOrErrorMessage(getInteger(lastTourIdKey), "No active tournaments")
249- let now = lastBlock.timestamp
250- let tData = getTourData(this, lastId)
251- let static = tData[idxStatic]
252- let dynamic = tData[idxDynamic]
253- let status = dynamic[tDynamicStatus]
254- if (!(if (if (if ((status == "CREATED"))
255- then (now > parseIntValue(static[tStaticStart]))
256- else false)
257- then ((parseIntValue(static[tStaticEnd]) - HOUR) > now)
258- else false)
259- then true
260- else if ((status == "INPROGRESS"))
261- then ((parseIntValue(static[tStaticEnd]) - HOUR) > now)
262- else false))
263- then throw("Cannot register now")
131+ let addr = toString(i.caller)
132+ let nftsKey = keyAssetIdsBySeller(addr)
133+ let nftsStr = valueOrElse(getString(nftsKey), "")
134+ let nfts = if ((nftsStr != ""))
135+ then split_51C(value(nftsStr), "_")
136+ else nil
137+ let idx = indexOf(nfts, assetIdStr)
138+ if (!(isDefined(idx)))
139+ then throw(("Your don't have sell order for " + assetIdStr))
264140 else {
265- let regCost = parseIntValue(static[tStaticRegisterCost])
266- let assetId = if ((size(static) > tStaticAsset))
267- then fromBase58String(static[tStaticAsset])
268- else wlgAssetId
269- let nfo = valueOrErrorMessage(assetInfo(assetId), "No assetInfo available")
270- let assetName = nfo.name
271- let assetDecimals = nfo.decimals
272- let regAmt = if ((regCost > 0))
273- then if ((size(i.payments) != 1))
274- then throw("exactly 1 payment must be attached")
275- else {
276- let pmt = i.payments[0]
277- if (if (!(isDefined(pmt.assetId)))
278- then true
279- else (value(pmt.assetId) != assetId))
280- then throw((assetName + " payments only!"))
281- else pmt.amount
282- }
283- else if ((size(i.payments) != 0))
284- then throw("No payments required")
285- else 0
286- if ((regAmt != regCost))
287- then throw(((("Need payment of " + fixedPoint(regCost, assetDecimals)) + " ") + assetName))
288- else {
289- let duckAssetId = duckByCaller(i.originCaller)
290- let scoreKey = keyScoreBoardByTour(lastId)
291- let oldScoreBoard = valueOrElse(getString(scoreKey), "")
292- if (if (valueOrElse(getBoolean(keyIsRegisteredByTourAndDuck(lastId, duckAssetId)), false))
293- then true
294- else contains(oldScoreBoard, duckAssetId))
295- then throw(((("Your duck " + duckAssetId) + " is already registered at tournament ") + toString(lastId)))
296- else {
297- let updatedDynamicData = dynamicData("INPROGRESS", dynamic[tDynamicLeaders], parseIntValue(dynamic[tDynamicWinResult]), (parseIntValue(dynamic[tDynamicTotalRegCount]) + 1), parseIntValue(dynamic[tDynamicTotalAttempts]))
298- $Tuple2([IntegerEntry(keyLastRegisteredTourByDuck(duckAssetId), lastId), BooleanEntry(keyIsRegisteredByTourAndDuck(lastId, duckAssetId), true), StringEntry(scoreKey, if ((oldScoreBoard == ""))
299- then (duckAssetId + ":000")
300- else (((oldScoreBoard + "_") + duckAssetId) + ":000")), StringEntry(keyTourDynamicDataById(lastId), updatedDynamicData)], prologResult)
301- }
302- }
141+ let listAction = if ((size(nfts) > 1))
142+ then StringEntry(nftsKey, makeString_11C(removeByIndex(nfts, value(idx)), "_"))
143+ else DeleteEntry(nftsKey)
144+ let price = valueOrErrorMessage(getInteger(keyPriceByAssetId(assetIdStr)), ("You don't have sell order for " + assetIdStr))
145+ $Tuple2([listAction, DeleteEntry(keySellerByAssetId(assetIdStr)), DeleteEntry(keyPriceByAssetId(assetIdStr)), ScriptTransfer(i.caller, (price / 20), wlgAssetId)], prologResult)
303146 }
304147 }
305148 else throw("Strict value is not equal to itself.")
306149 }
307150
308151
309152
310153 @Callable(i)
311-func newAttempt () = {
312- let prologResult = prolog()
154+func acceptSellOrder (assetIdStr) = {
155+ let prologResult = prolog2()
313156 if ((prologResult == prologResult))
314- then {
315- let duckAssetId = duckByCaller(i.originCaller)
316- let lastId = valueOrErrorMessage(getInteger(lastTourIdKey), "No active tournaments")
317- let now = lastBlock.timestamp
318- let tData = getTourData(this, lastId)
319- let static = tData[idxStatic]
320- let dynamic = tData[idxDynamic]
321- let status = dynamic[tDynamicStatus]
322- if (!(if ((status == "INPROGRESS"))
323- then ((parseIntValue(static[tStaticEnd]) - HOUR) > now)
324- else false))
325- then throw("Attempt is not possible")
326- else if (!(valueOrElse(getBoolean(keyIsRegisteredByTourAndDuck(lastId, duckAssetId)), false)))
327- then throw(((("Your duck " + duckAssetId) + " is not registered at tournament ") + toString(lastId)))
157+ then if ((size(i.payments) != 1))
158+ then throw("exactly 1 payment must be attached")
159+ else {
160+ let pmt = i.payments[0]
161+ if (if (!(isDefined(pmt.assetId)))
162+ then true
163+ else (value(pmt.assetId) != wlgAssetId))
164+ then throw("WLGOLD payments only!")
328165 else {
329- let attemptsIteratorKey = keyLastAttemptByTourAndDuck(lastId, duckAssetId)
330- let lastAttempt = getInteger(attemptsIteratorKey)
331- let $t067497614 = if (!(isDefined(lastAttempt)))
332- then $Tuple2(0, 0)
333- else if ((size(i.payments) != 1))
334- then throw("exactly 1 payment must be attached")
335- else {
336- let pmt = i.payments[0]
337- let assetId = if ((size(static) > tStaticAsset))
338- then fromBase58String(static[tStaticAsset])
339- else wlgAssetId
340- let nfo = valueOrErrorMessage(assetInfo(assetId), "No assetInfo available")
341- let assetName = nfo.name
342- let assetDecimals = nfo.decimals
343- let amt = pmt.amount
344- if (if (!(isDefined(pmt.assetId)))
345- then true
346- else (value(pmt.assetId) != assetId))
347- then throw((assetName + " payments only!"))
348- else {
349- let attCost = parseIntValue(static[tStaticAttemptCost])
350- if ((amt != attCost))
351- then throw(((("Need payment of " + fixedPoint(attCost, assetDecimals)) + " ") + assetName))
352- else $Tuple2((value(lastAttempt) + 1), 1)
353- }
354- }
355- let payedAttempts = $t067497614._1
356- let increment = $t067497614._2
357- let updatedDynamicData = dynamicData("INPROGRESS", dynamic[tDynamicLeaders], parseIntValue(dynamic[tDynamicWinResult]), parseIntValue(dynamic[tDynamicTotalRegCount]), (parseIntValue(dynamic[tDynamicTotalAttempts]) + increment))
358- let tourLoc = asString(invoke(stakingContract, "initDuckTourAttempt", [duckAssetId], nil))
359- $Tuple2([IntegerEntry(attemptsIteratorKey, payedAttempts), StringEntry(keyTourDynamicDataById(lastId), updatedDynamicData)], [prologResult, payedAttempts, tourLoc])
360- }
361- }
362- else throw("Strict value is not equal to itself.")
363- }
364-
365-
366-
367-@Callable(i)
368-func saveDuckResult (duckAssetId,duckNewBest) = if ((i.caller != stakingContract))
369- then throw("Access denied")
370- else {
371- let lastId = valueOrErrorMessage(getInteger(lastTourIdKey), "No active tournaments")
372- let tData = getTourData(this, lastId)
373- let static = tData[idxStatic]
374- let dynamic = tData[idxDynamic]
375- let curLocation = valueOrElse(getString(stakingContract, keyDuckLocation(duckAssetId)), DEFAULTLOCATION)
376- let bestResultKey = keyBestResultByTourAndDuck(lastId, duckAssetId)
377- let sumScoresKey = keySumScoresByTour(lastId)
378- let oldSumScores = valueOrElse(getInteger(sumScoresKey), 0)
379- if (isInTournament(this, curLocation))
380- then {
381- let duckOldBest = valueOrElse(getInteger(bestResultKey), 0)
382- let scoreKey = keyScoreBoardByTour(lastId)
383- let oldScoreBoard = valueOrElse(getString(scoreKey), "")
384- let $t0910710268 = if ((duckNewBest > duckOldBest))
385- then if (!(contains(oldScoreBoard, duckAssetId)))
386- then throw(("scoreBoard does not contain " + duckAssetId))
387- else {
388- let oldBest = parseIntValue(dynamic[tDynamicWinResult])
389- let leaders = dynamic[tDynamicLeaders]
390- let oldLeadersList = if (if ((leaders == ""))
391- then true
392- else (leaders == " "))
393- then nil
394- else split_4C(leaders, ",")
395- let newLeadersList = if ((duckNewBest > oldBest))
396- then [duckAssetId]
397- else if (if ((oldBest > duckNewBest))
398- then true
399- else containsElement(oldLeadersList, duckAssetId))
400- then oldLeadersList
401- else (oldLeadersList :+ duckAssetId)
402- let updatedDynamicData = dynamicData("INPROGRESS", makeString_2C(newLeadersList, ","), max([duckNewBest, oldBest]), parseIntValue(dynamic[tDynamicTotalRegCount]), parseIntValue(dynamic[tDynamicTotalAttempts]))
403- let parts = split_51C(oldScoreBoard, duckAssetId)
404- $Tuple3(((((parts[0] + duckAssetId) + ":") + padL(duckNewBest, 3)) + drop(parts[1], 4)), ((oldSumScores + duckNewBest) - duckOldBest), [StringEntry(keyTourDynamicDataById(lastId), updatedDynamicData)])
405- }
406- else $Tuple3(oldScoreBoard, oldSumScores, nil)
407- let newScoreBoard = $t0910710268._1
408- let newSumScores = $t0910710268._2
409- let globalActions = $t0910710268._3
410- $Tuple2(([IntegerEntry(bestResultKey, max([duckOldBest, duckNewBest])), IntegerEntry(sumScoresKey, newSumScores), StringEntry(keyBestTxByTourAndDuck(lastId, duckAssetId), toBase58String(i.transactionId)), StringEntry(scoreKey, newScoreBoard)] ++ globalActions), 0)
411- }
412- else $Tuple2(nil, 0)
413- }
414-
415-
416-
417-@Callable(i)
418-func processTournament (tId) = {
419- let caller = toString(i.caller)
420- if (!(containsElement(adminsList, caller)))
421- then throw("Permission denied")
422- else {
423- let now = lastBlock.timestamp
424- let tData = getTourData(this, tId)
425- let static = tData[idxStatic]
426- let dynamic = tData[idxDynamic]
427- let status = dynamic[tDynamicStatus]
428- let registrations = parseIntValue(dynamic[tDynamicTotalRegCount])
429- let paidAttempts = parseIntValue(dynamic[tDynamicTotalAttempts])
430- let regCost = parseIntValue(static[tStaticRegisterCost])
431- let attCost = parseIntValue(static[tStaticAttemptCost])
432- if ((status == "ARCHIVED"))
433- then throw((("Tournament " + toString(tId)) + " is already ARCHIVED"))
434- else if (if ((status == "INPROGRESS"))
435- then (parseIntValue(static[tStaticEnd]) > now)
436- else false)
437- then throw((("Tournament " + toString(tId)) + " is not over yet"))
438- else {
439- let updatedDynamicData = dynamicData("PROCESSING", dynamic[tDynamicLeaders], parseIntValue(dynamic[tDynamicWinResult]), registrations, paidAttempts)
440- let prizeFund = if ((size(static) > tStaticPrizeFund))
441- then parseIntValue(static[tStaticPrizeFund])
442- else 0
443- let unpaid = ((((registrations * regCost) + (paidAttempts * attCost)) / 2) + prizeFund)
444- $Tuple2([StringEntry(keyTourDynamicDataById(tId), updatedDynamicData), IntegerEntry(keyUnpaidRewardsByTour(tId), unpaid)], 0)
445- }
446- }
447- }
448-
449-
450-
451-@Callable(i)
452-func claimPrize (tId) = {
453- let prologResult = prolog()
454- if ((prologResult == prologResult))
455- then if ((size(i.payments) != 0))
456- then throw("No payments required")
457- else {
458- let tData = getTourData(this, tId)
459- let static = tData[idxStatic]
460- let dynamic = tData[idxDynamic]
461- let status = dynamic[tDynamicStatus]
462- if ((status != "PROCESSING"))
463- then throw((("Tournament " + toString(tId)) + " is not PROCESSING"))
464- else {
465- let registrations = parseIntValue(dynamic[tDynamicTotalRegCount])
466- let paidAttempts = parseIntValue(dynamic[tDynamicTotalAttempts])
467- let regCost = parseIntValue(static[tStaticRegisterCost])
468- let attCost = parseIntValue(static[tStaticAttemptCost])
469- let prizeFund = if ((size(static) > tStaticPrizeFund))
470- then parseIntValue(static[tStaticPrizeFund])
471- else 0
472- let awardFunds = ((((registrations * regCost) + (paidAttempts * attCost)) / 2) + prizeFund)
473- let unpaidKey = keyUnpaidRewardsByTour(tId)
474- let unpaidFunds = valueOrElse(getInteger(unpaidKey), 0)
475- let duckAssetId = duckByCaller(i.originCaller)
476- if (!(valueOrElse(getBoolean(keyIsRegisteredByTourAndDuck(tId, duckAssetId)), false)))
477- then throw(((("Your duck " + duckAssetId) + " is not registered at tournament ") + toString(tId)))
166+ let price = valueOrErrorMessage(getInteger(keyPriceByAssetId(assetIdStr)), (("NFT " + assetIdStr) + " is not selling"))
167+ let change = (pmt.amount - price)
168+ if ((0 > change))
169+ then throw((("Payment attached doesn't cover sell price of " + fixedPoint(price, 8)) + " WLGOLD"))
478170 else {
479- let bestResultKey = keyBestResultByTourAndDuck(tId, duckAssetId)
480- let duckBest = valueOrElse(getInteger(bestResultKey), 0)
481- if ((duckBest == 0))
482- then throw("Your duck got zero score")
171+ let changeActions = if ((change > 0))
172+ then [ScriptTransfer(i.caller, change, wlgAssetId)]
173+ else nil
174+ let seller = valueOrErrorMessage(getString(keySellerByAssetId(assetIdStr)), (("NFT " + assetIdStr) + " is not selling"))
175+ let nftsKey = keyAssetIdsBySeller(seller)
176+ let nftsStr = valueOrElse(getString(nftsKey), "")
177+ let nfts = if ((nftsStr != ""))
178+ then split_51C(value(nftsStr), "_")
179+ else nil
180+ let idx = indexOf(nfts, assetIdStr)
181+ if (!(isDefined(idx)))
182+ then throw(("Seller don't have sell order for " + assetIdStr))
483183 else {
484- let awardedKey = keyIsAwardedByTourAndDuck(tId, duckAssetId)
485- if (valueOrElse(getBoolean(awardedKey), false))
486- then throw(((("Your duck " + duckAssetId) + " is already awarded at tournament ") + toString(tId)))
487- else {
488- let sumScoresKey = keySumScoresByTour(tId)
489- let sumScores = valueOrElse(getInteger(sumScoresKey), 0)
490- let leaders = dynamic[tDynamicLeaders]
491- let leadersList = if (if ((leaders == ""))
492- then true
493- else (leaders == " "))
494- then nil
495- else split_4C(leaders, ",")
496- let numLeaders = size(leadersList)
497- if ((numLeaders == 0))
498- then throw(("No leaders at tournament " + toString(tId)))
499- else {
500- let numGrands = parseIntValue(static[tStaticNumGrands])
501- let winResult = parseIntValue(dynamic[tDynamicWinResult])
502- let sumLeaderScores = if ((numLeaders > numGrands))
503- then 0
504- else if (containsElement(leadersList, duckAssetId))
505- then throw("As one of winners, you will be awarded by admins")
506- else (numLeaders * winResult)
507- let yourAmount = min([fraction(duckBest, awardFunds, (sumScores - sumLeaderScores)), unpaidFunds])
508- let newUnpaidAmount = (unpaidFunds - yourAmount)
509- let updatedDynamicData = dynamicData("ARCHIVED", dynamic[tDynamicLeaders], winResult, registrations, paidAttempts)
510- let archiveAction = if ((0 >= newUnpaidAmount))
511- then [StringEntry(keyTourDynamicDataById(tId), updatedDynamicData)]
512- else nil
513- let assetId = if ((size(static) > tStaticAsset))
514- then fromBase58String(static[tStaticAsset])
515- else wlgAssetId
516- let loc = split(valueOrElse(getString(stakingContract, keyDuckLocation(duckAssetId)), DEFAULTLOCATION), "_")
517- let breakActions = if (if ((loc[locIdxType] == "T"))
518- then (getTourData(this, parseIntValue(loc[locIdxContinent]))[idxDynamic][tDynamicStatus] == "PROCESSING")
519- else false)
520- then invoke(stakingContract, "breakAttemptCallback", nil, nil)
521- else unit
522- $Tuple2(([ScriptTransfer(i.caller, yourAmount, assetId), BooleanEntry(awardedKey, true), IntegerEntry(unpaidKey, newUnpaidAmount)] ++ archiveAction), breakActions)
523- }
524- }
184+ let listAction = if ((size(nfts) > 1))
185+ then StringEntry(nftsKey, makeString_11C(removeByIndex(nfts, value(idx)), "_"))
186+ else DeleteEntry(nftsKey)
187+ let fee = (price / 20)
188+ let forTeam = (fee / 2)
189+ let wlgRemain = asInt(invoke(wlgContract, "burnWlgold", [(fee - forTeam)], nil))
190+ $Tuple2(([listAction, DeleteEntry(keySellerByAssetId(assetIdStr)), DeleteEntry(keyPriceByAssetId(assetIdStr)), ScriptTransfer(addressFromStringValue(seller), price, wlgAssetId), ScriptTransfer(addressFromStringValue(getStringValue(wlgContract, teamAddrKey)), forTeam, wlgAssetId), ScriptTransfer(i.caller, 1, fromBase58String(assetIdStr))] ++ changeActions), prologResult)
525191 }
526192 }
527193 }
528194 }
529195 else throw("Strict value is not equal to itself.")
530196 }
531197
532198

github/deemru/w8io/169f3d6 
54.23 ms