tx · 5rLA6NLHwVoD8RAXZzAhbsLQ68pPq6hxGZzYBmmcDUDH 3PAi1ePLQrYrY3jj9omBtT6isMkZsapbmks: -0.01400000 Waves 2022.04.05 13:57 [3060454] smart account 3PAi1ePLQrYrY3jj9omBtT6isMkZsapbmks > SELF 0.00000000 Waves
{ "type": 13, "id": "5rLA6NLHwVoD8RAXZzAhbsLQ68pPq6hxGZzYBmmcDUDH", "fee": 1400000, "feeAssetId": null, "timestamp": 1649156233553, "version": 2, "chainId": 87, "sender": "3PAi1ePLQrYrY3jj9omBtT6isMkZsapbmks", "senderPublicKey": "XrNmTusDFaLSz3wAjmdfcyC5h6uYyVbpdh18758UpFv", "proofs": [ "4i7UwqGt1UZ781jqgeUCZyzU7fBE7TNdJyfYfNqPLPwyBrSy4tNBquCR6oX98ppnqBQPahUGkz4iW78MExGxng2w" ], "script": "base64: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ZXIAAAACAAAAB2FkZHJlc3MAAAAHYXNzZXRJZAkBAAAADXRyeUdldEludGVnZXIAAAABCQABLAAAAAIJAAEsAAAAAgkAASwAAAACCQABLAAAAAICAAAACGFkZHJlc3NfBQAAAAdhZGRyZXNzAgAAAAdfYXNzZXRfBQAAAAdhc3NldElkAgAAAA1fZmFybWluZ1Bvd2VyAQAAAA5nZXRBc3NldHNCeUdlbgAAAAEAAAADZ2VuBAAAAAFzCQEAAAAMdHJ5R2V0U3RyaW5nAAAAAQkAASwAAAACAgAAAAdhc3NldHNfBQAAAANnZW4DCQAAAAAAAAIFAAAAAXMCAAAAAAUAAAADbmlsCQAEtQAAAAIFAAAAAXMCAAAAASwBAAAADGNhbGNJbnRlcmVzdAAAAAMAAAAQcHJldmlvdXNJbnRlcmVzdAAAABZwcmV2aW91c0ludGVyZXN0SGVpZ2h0AAAAEXRvdGFsRmFybWluZ1Bvd2VyCQAAZAAAAAIFAAAAEHByZXZpb3VzSW50ZXJlc3QJAABpAAAAAgkAAGgAAAACCQAAaAAAAAIFAAAABXNjYWxlCQEAAAARZ2V0UmV3YXJkUGVyQmxvY2sAAAAACQAAZQAAAAIFAAAABmhlaWdodAUAAAAWcHJldmlvdXNJbnRlcmVzdEhlaWdodAUAAAARdG90YWxGYXJtaW5nUG93ZXIBAAAAEmdldEN1cnJlbnRJbnRlcmVzdAAAAAADCQAAZgAAAAIJAQAAAA10cnlHZXRJbnRlZ2VyAAAAAQIAAAASdG90YWxfZmFybWluZ1Bvd2VyAAAAAAAAAAAABAAAABBwcmV2aW91c0ludGVyZXN0CQEAAAANdHJ5R2V0SW50ZWdlcgAAAAECAAAAF3RvdGFsX2xhc3RDaGVja0ludGVyZXN0BAAAABZwcmV2aW91c0ludGVyZXN0SGVpZ2h0CQEAAAANdHJ5R2V0SW50ZWdlcgAAAAECAAAAHXRvdGFsX2xhc3RDaGVja0ludGVyZXN0SGVpZ2h0BAAAABF0b3RhbEZhcm1pbmdQb3dlcgkBAAAADXRyeUdldEludGVnZXIAAAABAgAAABJ0b3RhbF9mYXJtaW5nUG93ZXIJAQAAAAxjYWxjSW50ZXJlc3QAAAADBQAAABBwcmV2aW91c0ludGVyZXN0BQAAABZwcmV2aW91c0ludGVyZXN0SGVpZ2h0BQAAABF0b3RhbEZhcm1pbmdQb3dlcgMJAQAAAAIhPQAAAAIJAQAAAA10cnlHZXRJbnRlZ2VyAAAAAQIAAAARdG90YWxfc3RhcnRIZWlnaHQAAAAAAAAAAAAJAQAAAA10cnlHZXRJbnRlZ2VyAAAAAQIAAAAXdG90YWxfbGFzdENoZWNrSW50ZXJlc3QJAAACAAAAAQIAAAAcZmFybWluZyBpcyBub3QgbGF1bmNoZWQsIHlldAEAAAAUY2FsY0Fzc2V0UmV3YXJkRGVsdGEAAAADAAAAB2FkZHJlc3MAAAAHYXNzZXRJZAAAABFhc3NldEZhcm1pbmdQb3dlcgQAAAAWbGFzdENoZWNrQXNzZXRJbnRlcmVzdAkBAAAADXRyeUdldEludGVnZXIAAAABCQABLAAAAAIJAAEsAAAAAgkAASwAAAACCQABLAAAAAICAAAACGFkZHJlc3NfBQAAAAdhZGRyZXNzAgAAAAdfYXNzZXRfBQAAAAdhc3NldElkAgAAABJfbGFzdENoZWNrSW50ZXJlc3QEAAAAD2N1cnJlbnRJbnRlcmVzdAkBAAAAEmdldEN1cnJlbnRJbnRlcmVzdAAAAAAJAABoAAAAAgUAAAARYXNzZXRGYXJtaW5nUG93ZXIJAABlAAAAAgUAAAAPY3VycmVudEludGVyZXN0BQAAABZsYXN0Q2hlY2tBc3NldEludGVyZXN0AQAAABRhZGRBc3NldElkVG9HZW5FbnRyeQAAAAIAAAAHYXNzZXRJZAAAAAhhc3NldEdlbgQAAAAMY3VycmVudFZhbHVlCQEAAAAMdHJ5R2V0U3RyaW5nAAAAAQkAASwAAAACCQABLAAAAAICAAAAB2Fzc2V0c18FAAAACGFzc2V0R2VuAgAAAAdfbG9ja2VkAwkAAAAAAAACBQAAAAxjdXJyZW50VmFsdWUCAAAAAAUAAAAHYXNzZXRJZAkAASwAAAACCQABLAAAAAIFAAAADGN1cnJlbnRWYWx1ZQIAAAABLAUAAAAHYXNzZXRJZAEAAAAOZ2V0U3Rha2VSZXN1bHQAAAADAAAAB2FkZHJlc3MAAAAHYXNzZXRJZAAAABFhc3NldEZhcm1pbmdQb3dlcgQAAAAFYXNzZXQJAAJYAAAAAQUAAAAHYXNzZXRJZAkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgIAAAASdG90YWxfZmFybWluZ1Bvd2VyCQAAZAAAAAIJAQAAAA10cnlHZXRJbnRlZ2VyAAAAAQIAAAASdG90YWxfZmFybWluZ1Bvd2VyBQAAABFhc3NldEZhcm1pbmdQb3dlcgkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgIAAAAXdG90YWxfbGFzdENoZWNrSW50ZXJlc3QJAQAAABJnZXRDdXJyZW50SW50ZXJlc3QAAAAACQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACAgAAAB10b3RhbF9sYXN0Q2hlY2tJbnRlcmVzdEhlaWdodAUAAAAGaGVpZ2h0CQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACCQABLAAAAAIJAAEsAAAAAgkAASwAAAACCQABLAAAAAICAAAACGFkZHJlc3NfBQAAAAdhZGRyZXNzAgAAAAdfYXNzZXRfBQAAAAVhc3NldAIAAAANX2Zhcm1pbmdQb3dlcgUAAAARYXNzZXRGYXJtaW5nUG93ZXIJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAIJAAEsAAAAAgkAASwAAAACCQABLAAAAAIJAAEsAAAAAgIAAAAIYWRkcmVzc18FAAAAB2FkZHJlc3MCAAAAB19hc3NldF8FAAAABWFzc2V0AgAAABJfbGFzdENoZWNrSW50ZXJlc3QJAQAAABJnZXRDdXJyZW50SW50ZXJlc3QAAAAABQAAAANuaWwBAAAAEGdldFVuc3Rha2VSZXN1bHQAAAAFAAAAB2FkZHJlc3MAAAAHYXNzZXRJZAAAAAtyZXdhcmREZWx0YQAAAA93aXRoZHJhd25BbW91bnQAAAARYXNzZXRGYXJtaW5nUG93ZXIEAAAABWFzc2V0CQACWAAAAAEFAAAAB2Fzc2V0SWQJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAICAAAAEnRvdGFsX2Zhcm1pbmdQb3dlcgkAAGUAAAACCQEAAAANdHJ5R2V0SW50ZWdlcgAAAAECAAAAEnRvdGFsX2Zhcm1pbmdQb3dlcgUAAAARYXNzZXRGYXJtaW5nUG93ZXIJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAICAAAAF3RvdGFsX2xh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ZGRyZXNzBQAAAAVhc3NldAQAAAAQYXNzZXRSZXdhcmREZWx0YQkBAAAAFGNhbGNBc3NldFJld2FyZERlbHRhAAAAAwUAAAAHYWRkcmVzcwUAAAAFYXNzZXQFAAAAEWFzc2V0RmFybWluZ1Bvd2VyBAAAAAxmYXJtZWRBbW91bnQJAABkAAAAAgUAAAAQYXNzZXRSZXdhcmREZWx0YQkBAAAADXRyeUdldEludGVnZXIAAAABCQABLAAAAAIJAAEsAAAAAgkAASwAAAACCQABLAAAAAICAAAACGFkZHJlc3NfBQAAAAdhZGRyZXNzAgAAAAdfYXNzZXRfBQAAAAVhc3NldAIAAAAWX2xhc3RDaGVja0Zhcm1lZEFtb3VudAQAAAAPd2l0aGRyYXduQW1vdW50CQEAAAANdHJ5R2V0SW50ZWdlcgAAAAEJAAEsAAAAAgkAASwAAAACCQABLAAAAAIJAAEsAAAAAgIAAAAIYWRkcmVzc18FAAAAB2FkZHJlc3MCAAAAB19hc3NldF8FAAAABWFzc2V0AgAAABBfd2l0aGRyYXduQW1vdW50BAAAAAZyZXdhcmQJAABpAAAAAgkAAGUAAAACBQAAAAxmYXJtZWRBbW91bnQFAAAAD3dpdGhkcmF3bkFtb3VudAkAAGgAAAACBQAAAAVzY2FsZQAAAAAAAAAAZAQAAAAFY29sb3IJAQAAAAl0YWtlUmlnaHQAAAACCAkBAAAABXZhbHVlAAAAAQkAA+wAAAABBQAAAAdhc3NldElkAAAABG5hbWUAAAAAAAAAAAEDCQAAZwAAAAIAAAAAAAAAAAAFAAAAEWFzc2V0RmFybWluZ1Bvd2VyCQAAAgAAAAECAAAAE2Fzc2V0IG5vdCBhdmFpbGFibGUDCQAAAAAAAAIFAAAABWNvbG9yAgAAAAFVCQAAAgAAAAECAAAAK3VzZSBhbm90aGVyIGZ1bmN0aW9uIHRvIHVuc3Rha2UgSmFja3BvdCBORlQEAAAABnJlc3VsdAkBAAAAEGdldFVuc3Rha2VSZXN1bHQAAAAFBQAAAAdhZGRyZXNzBQAAAAdhc3NldElkBQAAABBhc3NldFJld2FyZERlbHRhBQAAAAZyZXdhcmQFAAAAEWFzc2V0RmFybWluZ1Bvd2VyCQAFFAAAAAIJAAROAAAAAgUAAAAGcmVzdWx0CQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACCQABLAAAAAIJAAEsAAAAAgkAASwAAAACAgAAAAhhZGRyZXNzXwkABCUAAAABCAUAAAABaQAAAAZjYWxsZXICAAAAEl9wZXJjaGVzQXZhaWxhYmxlXwUAAAAFY29sb3IJAABkAAAAAgkBAAAADXRyeUdldEludGVnZXIAAAABCQABLAAAAAIJAAEsAAAAAgkAASwAAAACAgAAAAhhZGRyZXNzXwkABCUAAAABCAUAAAABaQAAAAZjYWxsZXICAAAAEl9wZXJjaGVzQXZhaWxhYmxlXwUAAAAFY29sb3IAAAAAAAAAAAEJAARMAAAAAgkBAAAADlNjcmlwdFRyYW5zZmVyAAAAAwgFAAAAAWkAAAAGY2FsbGVyCQAAaAAAAAIFAAAABnJld2FyZAAAAAAAAA9CQAkBAAAADWdldEVnZ0Fzc2V0SWQAAAAACQAETAAAAAIJAQAAAA5TY3JpcHRUcmFuc2ZlcgAAAAMIBQAAAAFpAAAABmNhbGxlcgAAAAAAAAAAAQUAAAAHYXNzZXRJZAUAAAADbmlsCQAAaAAAAAIFAAAABnJld2FyZAAAAAAAAA9CQAAAAAFpAQAAAAxzdGFrZUphY2twb3QAAAABAAAABWNvbG9yAwkAAGYAAAACCQEAAAAIaXNMb2NrZWQAAAAAAAAAAAAAAAAACQAAAgAAAAECAAAAJUVHRyBvcGVyYXRpb25zIGFyZSB0ZW1wb3JhcmlseSBsb2NrZWQEAAAAA3BtdAkBAAAABXZhbHVlAAAAAQkAAZEAAAACCAUAAAABaQAAAAhwYXltZW50cwAAAAAAAAAAAAQAAAAHYXNzZXRJZAkBAAAABXZhbHVlAAAAAQgFAAAAA3BtdAAAAAdhc3NldElkBAAAAAdhZGRyZXNzCQAEJQAAAAEIBQAAAAFpAAAABmNhbGxlcgQAAAAQYXZhaWxhYmxlUGVyY2hlcwkBAAAADXRyeUdldEludGVnZXIAAAABCQABLAAAAAIJAAEsAAAAAgkAASwAAAACAgAAAAhhZGRyZXNzXwkABCUAAAABCAUAAAABaQAAAAZjYWxsZXICAAAAEl9wZXJjaGVzQXZhaWxhYmxlXwUAAAAFY29sb3IEAAAAC2Fzc2V0SXNzdWVyCAkBAAAABXZhbHVlAAAAAQkAA+wAAAABBQAAAAdhc3NldElkAAAABmlzc3VlcgMJAQAAAAIhPQAAAAIIBQAAAANwbXQAAAAGYW1vdW50AAAAAAAAAAABCQAAAgAAAAECAAAAE05GVCBpcyBub3QgYXR0YWNoZWQDAwkAAAAAAAACBQAAAAthc3NldElzc3VlcgkBAAAAE2dldEluY3ViYXRvckFkZHJlc3MAAAAABgkAAAAAAAACBQAAAAthc3NldElzc3VlcgkBAAAAEWdldEJyZWVkZXJBZGRyZXNzAAAAAAMJAQAAAAIhPQAAAAIJAQAAAAl0YWtlUmlnaHQAAAACCQEAAAAFdmFsdWUAAAABCAkBAAAABXZhbHVlAAAAAQkAA+wAAAABBQAAAAdhc3NldElkAAAABG5hbWUAAAAAAAAAAAECAAAAAVUJAAACAAAAAQIAAAAMamFja3BvdCBvbmx5AwkAAGcAAAACAAAAAAAAAAAABQAAABBhdmFpbGFibGVQZXJjaGVzCQAAAgAAAAEJAAEsAAAAAgIAAAAjbm8gcGVyY2hlcyBhdmFpbGFibGUgZm9yIHRoZSBjb2xvciAFAAAABWNvbG9yCQAETgAAAAIJAQAAAA5nZXRTdGFrZVJlc3VsdAAAAAMFAAAAB2FkZHJlc3MFAAAAB2Fzc2V0SWQAAAAAAAAAAGQJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAIJAAEsAAAAAgkAASwAAAACCQABLAAAAAICAAAACGFkZHJlc3NfCQAEJQAAAAEIBQAAAAFpAAAABmNhbGxlcgIAAAASX3BlcmNoZXNBdmFpbGFibGVfBQAAAAVjb2xvcgkAAGUAAAACBQAAABBhdmFpbGFibGVQZXJjaGVzAAAAAAAAAAABCQAETAAAAAIJAQAAAAtTdHJpbmdFbnRyeQAAAAIJAAEsAAAAAgkAASwAAAACCQABLAAAAAIJAAEsAAAAAgIAAAAIYWRkcmVzc18JAAQlAAAAAQgFAAAAAWkAAAAGY2FsbGVyAgAAAAdfYXNzZXRfCQACWAAAAAEFAAAAB2Fzc2V0SWQCAAAAC19wZXJjaENvbG9yBQAAAAVjb2xvcgUAAAADbmlsCQAAAgAAAAECAAAAEmFzc2V0IGlzIG5vdCB2YWxpZAAAAAFpAQAAAA51bnN0YWtlSmFja3BvdAAAAAEAAAAFYXNzZXQDCQEAAAARaXNVc2VyQmxhY2tsaXN0ZWQAAAABCQAEJQAAAAEIBQAAAAFpAAAABmNhbGxlcgkAAAIAAAABAgAAANNPb29wcywgbG9va3MgbGlrZSB5b3UgbG9zdCBpbiBvbmUgb2YgdGhlIER1Y2tzcXVpZCBnYW1lcyEgQXMgeW91IGFscmVhZHkga25vdywgYW55IGxvc3MgaGFzIGl0cyBjb25zZXF1ZW5jZXMsIHNvIHlvdSB3aWxsIGJlIG5vdCBhYmxlIHRvIGNsYWltIHlvdXIgZmFybWluZyByZXdhcmRzIHRpbGwgdGhlIGVuZCBvZiBEdWNrU3F1aWQgZ2FtZS4gUXVhY2sgaW4gcGVhY2UhAwkAAGYAAAACCQEAAAAIaXNMb2NrZWQAAAAAAAAAAAAAAAAACQAAAgAAAAECAAAAJUVHRyBvcGVyYXRpb25zIGFyZSB0ZW1wb3JhcmlseSBsb2NrZWQEAAAAB2Fzc2V0SWQJAAJZAAAAAQUAAAAFYXNzZXQEAAAAB2FkZHJlc3MJAAQlAAAAAQgFAAAAAWkAAAAGY2FsbGVyBAAAAAVjb2xvcgkBAAAADHRyeUdldFN0cmluZwAAAAEJAAEsAAAAAgkAASwAAAACCQABLAAAAAIJAAEsAAAAAgIAAAAIYWRkcmVzc18FAAAAB2FkZHJlc3MCAAAAB19hc3NldF8FAAAABWFzc2V0AgAAAAtfcGVyY2hDb2xvcgQAAAARYXNzZXRGYXJtaW5nUG93ZXIJAQAAAB1nZXRMYXN0S25vd25Bc3NldEZhcm1pbmdQb3dlcgAAAAIFAAAAB2FkZHJlc3MFAAAABWFzc2V0BAAAABBhc3NldFJld2FyZERlbHRhCQEAAAAUY2FsY0Fzc2V0UmV3YXJkRGVsdGEAAAADBQAAAAdhZGRyZXNzBQAAAAVhc3NldAUAAAARYXNzZXRGYXJtaW5nUG93ZXIEAAAADGZhcm1lZEFtb3VudAkAAGQAAAACBQAAABBhc3NldFJld2FyZERlbHRhCQEAAAANdHJ5R2V0SW50ZWdlcgAAAAEJAAEsAAAAAgkAASwAAAACCQABLAAAAAIJAAEsAAAAAgIAAAAIYWRkcmVzc18FAAAAB2FkZHJlc3MCAAAAB19hc3NldF8FAAAABWFzc2V0AgAAABZfbGFzdENo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", "height": 3060454, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: HWVRBXmVzjmCTYkptvNcpRMf8ig6Pydir5Fe6Fgi5z9x Next: 9C71e3yn4YfrUEd2rSiq4v1SoZv7wLftWAv47c8cHwrN Diff:
Old | New | Differences | |
---|---|---|---|
1 | 1 | {-# STDLIB_VERSION 5 #-} | |
2 | 2 | {-# SCRIPT_TYPE ACCOUNT #-} | |
3 | 3 | {-# CONTENT_TYPE DAPP #-} | |
4 | - | ||
4 | + | let perchPrice = (100 * 1000000) | |
5 | 5 | ||
6 | + | let scale = 10000 | |
6 | 7 | ||
7 | - | func keyUnstakeHeight (artefactName,artefactId) = (((artefactName + "_") + artefactId) + "_unstake_height") | |
8 | - | ||
9 | - | ||
10 | - | func getProcessFinishHeightKey (address,txId) = (((address + "_") + toBase58String(txId)) + "_fh") | |
11 | - | ||
12 | - | ||
13 | - | let devAddress = base58'3P44yqcpfhPF2iC1nptm2ZJCTaN7VYhz9og' | |
14 | - | ||
15 | - | let eggsNeeded = (3 * 100000000) | |
16 | - | ||
17 | - | let artefactsLimit = (301 + 600) | |
18 | - | ||
19 | - | let freeGenes = ["A", "B", "C", "D", "E"] | |
20 | - | ||
21 | - | let oldArtefacts = ["ART-LAKE", "ART-HOUSE", "ART-BIGHOUSE", "ART-FIXGENE", "ART-FREEGENE", "ART-MIRROR", "ART-POMP", "ART-CAPE", "ART-HAT", "ART-CUSTOMDUCK"] | |
22 | - | ||
23 | - | let artefacts = ["ART-XMISTL", "ART-XHAT", "ART-XSCARF", "ART-XSWEATER", "ART-XSOCK", "ART-XTREE"] | |
24 | - | ||
25 | - | let stakeableWithLock = ["ART-LAKE", "ART-XTREE"] | |
26 | - | ||
27 | - | let stakeableWithoutLock = ["ART-XMISTL"] | |
28 | - | ||
29 | - | let allStakeable = (stakeableWithoutLock ++ stakeableWithLock) | |
30 | - | ||
31 | - | let allArtefact = (artefacts ++ oldArtefacts) | |
32 | - | ||
33 | - | func tryGetString (key) = match getString(this, key) { | |
34 | - | case a: String => | |
35 | - | a | |
36 | - | case _ => | |
37 | - | "" | |
38 | - | } | |
39 | - | ||
40 | - | ||
41 | - | func tryGetInteger (key) = match getInteger(this, key) { | |
42 | - | case a: Int => | |
43 | - | a | |
44 | - | case _ => | |
45 | - | 0 | |
46 | - | } | |
47 | - | ||
48 | - | ||
49 | - | func getRandomNumber (variants,txId,finishHeight,offset) = { | |
50 | - | let randomSeedBlock = value(blockInfoByHeight((finishHeight - 1))) | |
51 | - | let randomHash = sha256(((base58'items' + txId) + value(randomSeedBlock.vrf))) | |
52 | - | (toInt(randomHash, offset) % variants) | |
53 | - | } | |
54 | - | ||
55 | - | ||
56 | - | func getRandomArtefact (boxId,h) = { | |
57 | - | let randomNumber = getRandomNumber(6, boxId, h, 1) | |
58 | - | artefacts[randomNumber] | |
59 | - | } | |
60 | - | ||
61 | - | ||
62 | - | func getRandomGenes (txId,h) = { | |
63 | - | let randomNumber = getRandomNumber(6, txId, h, 2) | |
64 | - | freeGenes[randomNumber] | |
65 | - | } | |
66 | - | ||
67 | - | ||
68 | - | func checkArtefactDetails (assetId) = { | |
69 | - | let asset = value(assetInfo(assetId)) | |
70 | - | let assetName = value(asset.name) | |
71 | - | if (if (containsElement(allArtefact, assetName)) | |
72 | - | then (asset.issuer == this) | |
73 | - | else false) | |
74 | - | then assetName | |
75 | - | else throw("Invalid artefact") | |
76 | - | } | |
77 | - | ||
8 | + | let scale2 = 1000000 | |
78 | 9 | ||
79 | 10 | func tryGetStringExternal (address,key) = match getString(address, key) { | |
80 | 11 | case a: String => | |
84 | 15 | } | |
85 | 16 | ||
86 | 17 | ||
18 | + | func tryGetString (key) = tryGetStringExternal(this, key) | |
19 | + | ||
20 | + | ||
87 | 21 | func getOracle () = Address(fromBase58String(tryGetString("static_oracleAddress"))) | |
22 | + | ||
23 | + | ||
24 | + | func getEggAssetId () = fromBase58String(tryGetStringExternal(getOracle(), "static_eggAssetId")) | |
25 | + | ||
26 | + | ||
27 | + | func getIncubatorAddress () = Address(fromBase58String(tryGetStringExternal(getOracle(), "static_incubatorAddress"))) | |
28 | + | ||
29 | + | ||
30 | + | func getRebirthAddress () = Address(fromBase58String(tryGetStringExternal(getOracle(), "static_rebirthAddress"))) | |
31 | + | ||
32 | + | ||
33 | + | func getSwopPromoAddress () = Address(fromBase58String(tryGetStringExternal(getOracle(), "static_swopPromoAddress"))) | |
88 | 34 | ||
89 | 35 | ||
90 | 36 | func getBreederAddress () = Address(fromBase58String(tryGetStringExternal(getOracle(), "static_breederAddress"))) | |
91 | 37 | ||
92 | 38 | ||
93 | - | func getEggAssetId () = fromBase58String(tryGetStringExternal(getOracle(), "static_eggAssetId")) | |
39 | + | func getRefContractAddress () = Address(fromBase58String(tryGetStringExternal(getOracle(), "static_refContractAddress"))) | |
40 | + | ||
41 | + | ||
42 | + | func getItemsAddress () = Address(fromBase58String(tryGetStringExternal(getOracle(), "static_itemsAddress"))) | |
43 | + | ||
44 | + | ||
45 | + | let RefererReward = 5 | |
46 | + | ||
47 | + | func getRewardPerBlock () = 684 | |
48 | + | ||
49 | + | ||
50 | + | func isLocked () = { | |
51 | + | let masterAddress = Address(base58'3PEPftf2kWZDmAaWBjs6BUJa9957kiA2PkU') | |
52 | + | match getInteger(masterAddress, "egglock") { | |
53 | + | case b: Int => | |
54 | + | b | |
55 | + | case _ => | |
56 | + | 0 | |
57 | + | } | |
58 | + | } | |
59 | + | ||
60 | + | ||
61 | + | func tryGetInteger (key) = match getInteger(this, key) { | |
62 | + | case b: Int => | |
63 | + | b | |
64 | + | case _ => | |
65 | + | 0 | |
66 | + | } | |
67 | + | ||
68 | + | ||
69 | + | func isUserBlacklisted (address) = false | |
70 | + | ||
71 | + | ||
72 | + | func getAssetOrigin (generation) = if ((generation == "G")) | |
73 | + | then getIncubatorAddress() | |
74 | + | else getBreederAddress() | |
75 | + | ||
76 | + | ||
77 | + | func getAssetRarity (genotype,generation) = { | |
78 | + | let quantity = valueOrErrorMessage(getInteger(getAssetOrigin(generation), (("stats_" + genotype) + "_quantity")), (("stats_" + genotype) + "_quantity not found")) | |
79 | + | let power = pow((10000 / quantity), 4, 5, 1, 2, FLOOR) | |
80 | + | if ((power > 0)) | |
81 | + | then power | |
82 | + | else 2 | |
83 | + | } | |
94 | 84 | ||
95 | 85 | ||
96 | 86 | func asString (value) = match value { | |
109 | 99 | } | |
110 | 100 | ||
111 | 101 | ||
112 | - | func manipulateName (assetName,position,char) = ((take(assetName, (position - 1)) + char) + takeRight(assetName, (16 - position))) | |
102 | + | func getAssetFarmingPower (assetId,address) = if (if ((value(assetInfo(assetId)).issuer == getBreederAddress())) | |
103 | + | then true | |
104 | + | else (value(assetInfo(assetId)).issuer == getIncubatorAddress())) | |
105 | + | then { | |
106 | + | let assetName = value(assetInfo(assetId)).name | |
107 | + | let generation = take(takeRight(assetName, 2), 1) | |
108 | + | let farmGen = asString(invoke(getBreederAddress(), "getGenFromName", [assetName], nil)) | |
109 | + | if ((farmGen == farmGen)) | |
110 | + | then { | |
111 | + | let farmBoost = asInt(invoke(getItemsAddress(), "calculateFarmingPowerBoost", [toBase58String(assetId), address], nil)) | |
112 | + | if ((farmBoost == farmBoost)) | |
113 | + | then { | |
114 | + | let rarity = getAssetRarity(farmGen, generation) | |
115 | + | let totalFarmingPower = (rarity + fraction(rarity, farmBoost, 100)) | |
116 | + | $Tuple2(farmGen, totalFarmingPower) | |
117 | + | } | |
118 | + | else throw("Strict value is not equal to itself.") | |
119 | + | } | |
120 | + | else throw("Strict value is not equal to itself.") | |
121 | + | } | |
122 | + | else throw("not valid NFT") | |
113 | 123 | ||
114 | 124 | ||
115 | - | func itemIsInCoolDown (artefactName,artefactId) = { | |
116 | - | let unstakeHeightLast = tryGetInteger(keyUnstakeHeight(artefactName, artefactId)) | |
117 | - | let cooldownPeriod = 240 | |
118 | - | if ((height > (unstakeHeightLast + cooldownPeriod))) | |
119 | - | then false | |
120 | - | else true | |
125 | + | func getLastKnownAssetFarmingPower (address,assetId) = tryGetInteger((((("address_" + address) + "_asset_") + assetId) + "_farmingPower")) | |
126 | + | ||
127 | + | ||
128 | + | func getAssetsByGen (gen) = { | |
129 | + | let s = tryGetString(("assets_" + gen)) | |
130 | + | if ((s == "")) | |
131 | + | then nil | |
132 | + | else split(s, ",") | |
133 | + | } | |
134 | + | ||
135 | + | ||
136 | + | func calcInterest (previousInterest,previousInterestHeight,totalFarmingPower) = (previousInterest + (((scale * getRewardPerBlock()) * (height - previousInterestHeight)) / totalFarmingPower)) | |
137 | + | ||
138 | + | ||
139 | + | func getCurrentInterest () = if ((tryGetInteger("total_farmingPower") > 0)) | |
140 | + | then { | |
141 | + | let previousInterest = tryGetInteger("total_lastCheckInterest") | |
142 | + | let previousInterestHeight = tryGetInteger("total_lastCheckInterestHeight") | |
143 | + | let totalFarmingPower = tryGetInteger("total_farmingPower") | |
144 | + | calcInterest(previousInterest, previousInterestHeight, totalFarmingPower) | |
145 | + | } | |
146 | + | else if ((tryGetInteger("total_startHeight") != 0)) | |
147 | + | then tryGetInteger("total_lastCheckInterest") | |
148 | + | else throw("farming is not launched, yet") | |
149 | + | ||
150 | + | ||
151 | + | func calcAssetRewardDelta (address,assetId,assetFarmingPower) = { | |
152 | + | let lastCheckAssetInterest = tryGetInteger((((("address_" + address) + "_asset_") + assetId) + "_lastCheckInterest")) | |
153 | + | let currentInterest = getCurrentInterest() | |
154 | + | (assetFarmingPower * (currentInterest - lastCheckAssetInterest)) | |
155 | + | } | |
156 | + | ||
157 | + | ||
158 | + | func addAssetIdToGenEntry (assetId,assetGen) = { | |
159 | + | let currentValue = tryGetString((("assets_" + assetGen) + "_locked")) | |
160 | + | if ((currentValue == "")) | |
161 | + | then assetId | |
162 | + | else ((currentValue + ",") + assetId) | |
163 | + | } | |
164 | + | ||
165 | + | ||
166 | + | func getStakeResult (address,assetId,assetFarmingPower) = { | |
167 | + | let asset = toBase58String(assetId) | |
168 | + | [IntegerEntry("total_farmingPower", (tryGetInteger("total_farmingPower") + assetFarmingPower)), IntegerEntry("total_lastCheckInterest", getCurrentInterest()), IntegerEntry("total_lastCheckInterestHeight", height), IntegerEntry((((("address_" + address) + "_asset_") + asset) + "_farmingPower"), assetFarmingPower), IntegerEntry((((("address_" + address) + "_asset_") + asset) + "_lastCheckInterest"), getCurrentInterest())] | |
169 | + | } | |
170 | + | ||
171 | + | ||
172 | + | func getUnstakeResult (address,assetId,rewardDelta,withdrawnAmount,assetFarmingPower) = { | |
173 | + | let asset = toBase58String(assetId) | |
174 | + | [IntegerEntry("total_farmingPower", (tryGetInteger("total_farmingPower") - assetFarmingPower)), IntegerEntry("total_lastCheckInterest", getCurrentInterest()), IntegerEntry("total_lastCheckInterestHeight", height), IntegerEntry((((("address_" + address) + "_asset_") + asset) + "_farmingPower"), 0), IntegerEntry((((("address_" + address) + "_asset_") + asset) + "_lastCheckInterest"), getCurrentInterest()), IntegerEntry((((("address_" + address) + "_asset_") + asset) + "_withdrawnAmount"), (tryGetInteger((((("address_" + address) + "_asset_") + asset) + "_withdrawnAmount")) + (withdrawnAmount * scale2))), IntegerEntry((((("address_" + address) + "_asset_") + asset) + "_lastCheckFarmedAmount"), (tryGetInteger((((("address_" + address) + "_asset_") + asset) + "_lastCheckFarmedAmount")) + rewardDelta))] | |
175 | + | } | |
176 | + | ||
177 | + | ||
178 | + | func calculatePerchPrice (address) = { | |
179 | + | let hasArtefactStaked = tryGetStringExternal(getItemsAddress(), (("ART-XMISTL_" + address) + "_owner")) | |
180 | + | if ((hasArtefactStaked == "")) | |
181 | + | then perchPrice | |
182 | + | else ((perchPrice / 10) * 9) | |
121 | 183 | } | |
122 | 184 | ||
123 | 185 | ||
129 | 191 | ||
130 | 192 | ||
131 | 193 | @Callable(i) | |
132 | - | func calculateFarmingPowerBoost (duckId,address) = { | |
133 | - | let lakeBoost = if ((tryGetString(keyArtefactOwner("ART-LAKE", address)) != "")) | |
134 | - | then 2 | |
135 | - | else 0 | |
136 | - | let xmasTreeBoost = if ((tryGetString(keyArtefactOwner("ART-XTREE", address)) != "")) | |
137 | - | then 3 | |
138 | - | else 0 | |
139 | - | let totalBoost = (lakeBoost + xmasTreeBoost) | |
140 | - | $Tuple2(nil, totalBoost) | |
141 | - | } | |
194 | + | func init () = if ((i.caller != this)) | |
195 | + | then throw("admin only") | |
196 | + | else [IntegerEntry("total_startHeight", height)] | |
142 | 197 | ||
143 | 198 | ||
144 | 199 | ||
145 | 200 | @Callable(i) | |
146 | - | func fixedGene (txIdStr,parentFixedGene,positionFixedGene) = { | |
147 | - | let firstPayment = value(i.payments[0]) | |
148 | - | let firstAssetId = toBase58String(value(firstPayment.assetId)) | |
149 | - | if ((firstPayment.amount != 1)) | |
150 | - | then throw("NFT is not attached") | |
201 | + | func buyPerch (color,refererAddress) = if ((isLocked() > 0)) | |
202 | + | then throw("EGG operations are temporarily locked") | |
203 | + | else if ((0 > value(indexOf(["B", "R", "G", "Y"], color)))) | |
204 | + | then throw("you need to set color properly") | |
151 | 205 | else { | |
152 | - | let | |
153 | - | | |
154 | - | | |
155 | - | | |
156 | - | | |
157 | - | | |
158 | - | | |
159 | - | let | |
160 | - | | |
161 | - | | |
162 | - | | |
163 | - | | |
164 | - | | |
165 | - | ||
166 | - | } | |
167 | - | else throw("Strict value is not equal to itself.") | |
168 | - | } | |
206 | + | let firstPayment = value(i.payments[0]) | |
207 | + | let exactPrice = calculatePerchPrice(toString(i.caller)) | |
208 | + | if ((firstPayment.assetId != getEggAssetId())) | |
209 | + | then throw(("You can attach only EGG tokens with the following asset id: " + toBase58String(getEggAssetId()))) | |
210 | + | else if ((firstPayment.amount != exactPrice)) | |
211 | + | then throw(("To buy a perch you currently need the following amount of EGGlets: " + toString(exactPrice))) | |
212 | + | else { | |
213 | + | let refererRewardForPerch = fraction(firstPayment.amount, RefererReward, 100) | |
214 | + | let refCall = invoke(getRefContractAddress(), "refPayment", [refererAddress], [AttachedPayment(getEggAssetId(), refererRewardForPerch)]) | |
215 | + | if ((refCall == refCall)) | |
216 | + | then { | |
217 | + | let perchAmountKey = ((("address_" + toString(i.caller)) + "_perchesAvailable_") + color) | |
218 | + | let perchAmount = tryGetInteger(perchAmountKey) | |
219 | + | [IntegerEntry(perchAmountKey, (perchAmount + 1))] | |
220 | + | } | |
221 | + | else throw("Strict value is not equal to itself.") | |
222 | + | } | |
169 | 223 | } | |
170 | - | } | |
171 | 224 | ||
172 | 225 | ||
173 | 226 | ||
174 | 227 | @Callable(i) | |
175 | - | func freeGene (txIdStr) = { | |
176 | - | let firstPayment = value(i.payments[0]) | |
177 | - | let firstAssetId = toBase58String(value(firstPayment.assetId)) | |
178 | - | if ((firstPayment.amount != 1)) | |
179 | - | then throw("NFT is not attached") | |
228 | + | func addFreePerch (address,color) = if ((0 > value(indexOf(["B", "R", "G", "Y"], color)))) | |
229 | + | then throw("you need to set color properly") | |
230 | + | else if (if (if ((i.caller != getRebirthAddress())) | |
231 | + | then (i.caller != this) | |
232 | + | else false) | |
233 | + | then (i.caller != getSwopPromoAddress()) | |
234 | + | else false) | |
235 | + | then throw("rebirth and swop promo only") | |
180 | 236 | else { | |
181 | - | let artefact = checkArtefactDetails(value(firstPayment.assetId)) | |
182 | - | if ((artefact != "ART-FREEGENE")) | |
183 | - | then throw("You need to attach a ART-FREEGENE artefact") | |
184 | - | else { | |
185 | - | let txId = fromBase58String(txIdStr) | |
186 | - | let finishHeightKey = getProcessFinishHeightKey(toString(i.caller), txId) | |
187 | - | let processFinishHeight = getIntegerValue(getBreederAddress(), finishHeightKey) | |
188 | - | let selectedGene = getRandomGenes(txId, processFinishHeight) | |
189 | - | let randomPosition = getRandomNumber(7, txId, processFinishHeight, 3) | |
190 | - | let duckGenesString = asString(invoke(getBreederAddress(), "generateDuck", [txIdStr, processFinishHeight, 0, 0, selectedGene, randomPosition], nil)) | |
191 | - | if ((duckGenesString == duckGenesString)) | |
192 | - | then { | |
193 | - | let call = invoke(getBreederAddress(), "finishDuckHatchingItems", [txIdStr, duckGenesString], nil) | |
194 | - | if ((call == call)) | |
195 | - | then [Burn(value(firstPayment.assetId), 1)] | |
196 | - | else throw("Strict value is not equal to itself.") | |
197 | - | } | |
198 | - | else throw("Strict value is not equal to itself.") | |
199 | - | } | |
237 | + | let perchAmountKey = ((("address_" + address) + "_perchesAvailable_") + color) | |
238 | + | let perchAmount = tryGetInteger(perchAmountKey) | |
239 | + | $Tuple2([IntegerEntry(perchAmountKey, (perchAmount + 1))], "") | |
200 | 240 | } | |
201 | - | } | |
202 | 241 | ||
203 | 242 | ||
204 | 243 | ||
205 | 244 | @Callable(i) | |
206 | - | func | |
207 | - | | |
208 | - | | |
209 | - | let | |
210 | - | let | |
211 | - | | |
212 | - | | |
213 | - | | |
214 | - | | |
245 | + | func stakeNFT () = if ((isLocked() > 0)) | |
246 | + | then throw("EGG operations are temporarily locked") | |
247 | + | else { | |
248 | + | let pmt = value(i.payments[0]) | |
249 | + | let assetId = value(value(i.payments[0]).assetId) | |
250 | + | let address = toString(i.caller) | |
251 | + | let color = takeRight(value(assetInfo(assetId)).name, 1) | |
252 | + | let availablePerches = tryGetInteger(((("address_" + toString(i.caller)) + "_perchesAvailable_") + color)) | |
253 | + | if ((pmt.amount != 1)) | |
215 | 254 | then throw("NFT is not attached") | |
216 | - | else { | |
217 | - | let artefact = checkArtefactDetails(value(secondPayment.assetId)) | |
218 | - | if ((artefact != "ART-MIRROR")) | |
219 | - | then throw("You need to attach a ART-MIRROR artefact") | |
220 | - | else { | |
221 | - | let nftInfo = value(assetInfo(value(firstPayment.assetId))) | |
222 | - | let asset1Gen = split(nftInfo.name, "") | |
223 | - | if (if ((asset1Gen[14] == "G")) | |
224 | - | then true | |
225 | - | else (asset1Gen[14] == "J")) | |
226 | - | then throw("You can't mirror this duck") | |
227 | - | else { | |
228 | - | let duckGen = nftInfo.name | |
229 | - | let call = invoke(getBreederAddress(), "createDuckSpecialGenes", [i.caller.bytes, duckGen, children], nil) | |
230 | - | if ((call == call)) | |
231 | - | then [ScriptTransfer(i.caller, 1, firstPayment.assetId), Burn(value(secondPayment.assetId), 1)] | |
232 | - | else throw("Strict value is not equal to itself.") | |
233 | - | } | |
234 | - | } | |
235 | - | } | |
236 | - | else throw("Strict value is not equal to itself.") | |
237 | - | } | |
255 | + | else if ((0 >= availablePerches)) | |
256 | + | then throw(("no perches available for the color " + color)) | |
257 | + | else { | |
258 | + | let $t096749747 = getAssetFarmingPower(assetId, address) | |
259 | + | let assetGen = $t096749747._1 | |
260 | + | let assetFarmingPower = $t096749747._2 | |
261 | + | let assetRewardDelta = calcAssetRewardDelta(address, toBase58String(assetId), assetFarmingPower) | |
262 | + | (getStakeResult(address, assetId, assetFarmingPower) ++ [IntegerEntry(((("address_" + toString(i.caller)) + "_perchesAvailable_") + color), (availablePerches - 1))]) | |
263 | + | } | |
264 | + | } | |
238 | 265 | ||
239 | 266 | ||
240 | 267 | ||
241 | 268 | @Callable(i) | |
242 | - | func addArteFactToDuck () = { | |
243 | - | let firstPayment = value(i.payments[0]) | |
244 | - | let secondPayment = value(i.payments[1]) | |
245 | - | let firstAssetId = toBase58String(value(firstPayment.assetId)) | |
246 | - | if (if ((firstPayment.amount != 1)) | |
247 | - | then true | |
248 | - | else (secondPayment.amount != 1)) | |
249 | - | then throw("NFT is not attached") | |
269 | + | func unstakeNFT (asset) = if (isUserBlacklisted(toString(i.caller))) | |
270 | + | then throw("Ooops, looks like you lost in one of the Ducksquid games! As you already know, any loss has its consequences, so you will be not able to claim your farming rewards till the end of DuckSquid game. Quack in peace!") | |
271 | + | else if ((isLocked() > 0)) | |
272 | + | then throw("EGG operations are temporarily locked") | |
250 | 273 | else { | |
251 | - | let children = asInt(invoke(getBreederAddress(), "validateAndGetChildren", [firstAssetId], nil)) | |
252 | - | if ((children == children)) | |
253 | - | then if ((children == 0)) | |
254 | - | then throw("You can only pick a sterile NFT-duck") | |
274 | + | let assetId = fromBase58String(asset) | |
275 | + | let address = toString(i.caller) | |
276 | + | let assetFarmingPower = getLastKnownAssetFarmingPower(address, asset) | |
277 | + | let assetRewardDelta = calcAssetRewardDelta(address, asset, assetFarmingPower) | |
278 | + | let farmedAmount = (assetRewardDelta + tryGetInteger((((("address_" + address) + "_asset_") + asset) + "_lastCheckFarmedAmount"))) | |
279 | + | let withdrawnAmount = tryGetInteger((((("address_" + address) + "_asset_") + asset) + "_withdrawnAmount")) | |
280 | + | let reward = ((farmedAmount - withdrawnAmount) / (scale * 100)) | |
281 | + | let color = takeRight(value(assetInfo(assetId)).name, 1) | |
282 | + | if ((0 >= assetFarmingPower)) | |
283 | + | then throw("asset not available") | |
284 | + | else if ((color == "U")) | |
285 | + | then throw("use another function to unstake Jackpot NFT") | |
255 | 286 | else { | |
256 | - | let artefact = checkArtefactDetails(value(secondPayment.assetId)) | |
257 | - | if (if ((artefact != "ART-XHAT")) | |
258 | - | then (artefact != "ART-POMP") | |
259 | - | else false) | |
260 | - | then throw("You need to attach a ART-XHAT or ART-POMP artefact") | |
261 | - | else { | |
262 | - | let nftInfo = value(assetInfo(value(firstPayment.assetId))) | |
263 | - | let asset1Gen = split(nftInfo.name, "") | |
264 | - | if (if ((asset1Gen[14] == "G")) | |
265 | - | then true | |
266 | - | else (asset1Gen[14] == "J")) | |
267 | - | then throw("You can't mirror this duck") | |
268 | - | else if (if ((asset1Gen[5] == "S")) | |
269 | - | then true | |
270 | - | else (asset1Gen[5] == "T")) | |
271 | - | then throw("you already attached a artefact") | |
272 | - | else { | |
273 | - | let char = if ((artefact == "ART-XHAT")) | |
274 | - | then "T" | |
275 | - | else if ((artefact == "ART-POMP")) | |
276 | - | then "S" | |
277 | - | else throw("No char defined") | |
278 | - | let oldDuckGen = nftInfo.name | |
279 | - | let oldFarmGen = asString(invoke(getBreederAddress(), "getGenFromName", [oldDuckGen], nil)) | |
280 | - | if ((oldFarmGen == oldFarmGen)) | |
281 | - | then { | |
282 | - | let duckGen = manipulateName(oldDuckGen, 6, char) | |
283 | - | let call = invoke(getBreederAddress(), "createDuckSpecialGenes", [i.caller.bytes, duckGen, children], nil) | |
284 | - | if ((call == call)) | |
285 | - | then { | |
286 | - | let callReduce = invoke(getBreederAddress(), "reduceRarity", [firstAssetId, oldFarmGen], nil) | |
287 | - | if ((callReduce == callReduce)) | |
288 | - | then [Burn(value(firstPayment.assetId), 1), Burn(value(secondPayment.assetId), 1)] | |
289 | - | else throw("Strict value is not equal to itself.") | |
290 | - | } | |
291 | - | else throw("Strict value is not equal to itself.") | |
292 | - | } | |
293 | - | else throw("Strict value is not equal to itself.") | |
294 | - | } | |
295 | - | } | |
287 | + | let result = getUnstakeResult(address, assetId, assetRewardDelta, reward, assetFarmingPower) | |
288 | + | $Tuple2((result ++ [IntegerEntry(((("address_" + toString(i.caller)) + "_perchesAvailable_") + color), (tryGetInteger(((("address_" + toString(i.caller)) + "_perchesAvailable_") + color)) + 1)), ScriptTransfer(i.caller, (reward * 1000000), getEggAssetId()), ScriptTransfer(i.caller, 1, assetId)]), (reward * 1000000)) | |
296 | 289 | } | |
297 | - | else throw("Strict value is not equal to itself.") | |
298 | 290 | } | |
299 | - | } | |
300 | 291 | ||
301 | 292 | ||
302 | 293 | ||
303 | 294 | @Callable(i) | |
304 | - | func | |
305 | - | then ( | |
306 | - | else | |
307 | - | | |
308 | - | let assetId = value( | |
309 | - | let | |
310 | - | | |
311 | - | | |
312 | - | | |
313 | - | | |
314 | - | | |
315 | - | | |
316 | - | | |
317 | - | | |
318 | - | | |
319 | - | | |
320 | - | | |
321 | - | | |
322 | - | else throw(" | |
295 | + | func stakeJackpot (color) = if ((isLocked() > 0)) | |
296 | + | then throw("EGG operations are temporarily locked") | |
297 | + | else { | |
298 | + | let pmt = value(i.payments[0]) | |
299 | + | let assetId = value(pmt.assetId) | |
300 | + | let address = toString(i.caller) | |
301 | + | let availablePerches = tryGetInteger(((("address_" + toString(i.caller)) + "_perchesAvailable_") + color)) | |
302 | + | let assetIssuer = value(assetInfo(assetId)).issuer | |
303 | + | if ((pmt.amount != 1)) | |
304 | + | then throw("NFT is not attached") | |
305 | + | else if (if ((assetIssuer == getIncubatorAddress())) | |
306 | + | then true | |
307 | + | else (assetIssuer == getBreederAddress())) | |
308 | + | then if ((takeRight(value(value(assetInfo(assetId)).name), 1) != "U")) | |
309 | + | then throw("jackpot only") | |
310 | + | else if ((0 >= availablePerches)) | |
311 | + | then throw(("no perches available for the color " + color)) | |
312 | + | else (getStakeResult(address, assetId, 100) ++ [IntegerEntry(((("address_" + toString(i.caller)) + "_perchesAvailable_") + color), (availablePerches - 1)), StringEntry((((("address_" + toString(i.caller)) + "_asset_") + toBase58String(assetId)) + "_perchColor"), color)]) | |
313 | + | else throw("asset is not valid") | |
323 | 314 | } | |
324 | - | else throw("Invalid payment") | |
325 | 315 | ||
326 | 316 | ||
327 | 317 | ||
328 | 318 | @Callable(i) | |
329 | - | func unstakeItem (artefactName) = if (containsElement(allArtefact, artefactName)) | |
330 | - | then { | |
331 | - | let invoker = toString(i.caller) | |
332 | - | let artefactId = tryGetString(keyArtefactOwner(artefactName, invoker)) | |
333 | - | if ((artefactId == "")) | |
334 | - | then throw(("You didnt stake " + artefactName)) | |
335 | - | else [IntegerEntry(keyUnstakeHeight(artefactName, artefactId), height), ScriptTransfer(i.caller, 1, fromBase58String(artefactId)), DeleteEntry(keyArtefactOwner(artefactName, invoker))] | |
336 | - | } | |
337 | - | else throw("This artefact doesn't exist") | |
319 | + | func unstakeJackpot (asset) = if (isUserBlacklisted(toString(i.caller))) | |
320 | + | then throw("Ooops, looks like you lost in one of the Ducksquid games! As you already know, any loss has its consequences, so you will be not able to claim your farming rewards till the end of DuckSquid game. Quack in peace!") | |
321 | + | else if ((isLocked() > 0)) | |
322 | + | then throw("EGG operations are temporarily locked") | |
323 | + | else { | |
324 | + | let assetId = fromBase58String(asset) | |
325 | + | let address = toString(i.caller) | |
326 | + | let color = tryGetString((((("address_" + address) + "_asset_") + asset) + "_perchColor")) | |
327 | + | let assetFarmingPower = getLastKnownAssetFarmingPower(address, asset) | |
328 | + | let assetRewardDelta = calcAssetRewardDelta(address, asset, assetFarmingPower) | |
329 | + | let farmedAmount = (assetRewardDelta + tryGetInteger((((("address_" + address) + "_asset_") + asset) + "_lastCheckFarmedAmount"))) | |
330 | + | let withdrawnAmount = tryGetInteger((((("address_" + address) + "_asset_") + asset) + "_withdrawnAmount")) | |
331 | + | let reward = ((farmedAmount - withdrawnAmount) / (scale * 100)) | |
332 | + | if ((takeRight(value(value(assetInfo(assetId)).name), 1) != "U")) | |
333 | + | then throw("jackpot only") | |
334 | + | else if ((assetFarmingPower > 0)) | |
335 | + | then { | |
336 | + | let result = getUnstakeResult(address, assetId, assetRewardDelta, reward, assetFarmingPower) | |
337 | + | $Tuple2((result ++ [IntegerEntry(((("address_" + toString(i.caller)) + "_perchesAvailable_") + color), (tryGetInteger(((("address_" + toString(i.caller)) + "_perchesAvailable_") + color)) + 1)), ScriptTransfer(i.caller, (reward * 1000000), getEggAssetId()), ScriptTransfer(i.caller, 1, assetId)]), (reward * 1000000)) | |
338 | + | } | |
339 | + | else throw("") | |
340 | + | } | |
338 | 341 | ||
339 | 342 | ||
340 | 343 | ||
341 | 344 | @Callable(i) | |
342 | - | func preInit () = [IntegerEntry("static_ART-LAKE_farmingSlots", 200), IntegerEntry("static_ART-LAKE_farmingBoost", 2), IntegerEntry("static_ART-HOUSE_farmingSlots", 4), IntegerEntry("static_ART-HOUSE_farmingBoost", 30), IntegerEntry("static_ART-BIGHOUSE_farmingSlots", 10), IntegerEntry("static_ART-BIGHOUSE_farmingBoost", 15)] | |
345 | + | func claimReward (asset) = if (isUserBlacklisted(toString(i.caller))) | |
346 | + | then throw("Ooops, looks like you lost in one of the Ducksquid games! As you already know, any loss has its consequences, so you will be not able to claim your farming rewards till the end of DuckSquid game. Quack in peace!") | |
347 | + | else if ((isLocked() > 0)) | |
348 | + | then throw("EGG operations are temporarily locked") | |
349 | + | else { | |
350 | + | let address = toString(i.caller) | |
351 | + | let assetId = fromBase58String(asset) | |
352 | + | let assetFarmingPower = getLastKnownAssetFarmingPower(address, asset) | |
353 | + | let assetRewardDelta = calcAssetRewardDelta(address, asset, assetFarmingPower) | |
354 | + | let farmedAmount = (assetRewardDelta + tryGetInteger((((("address_" + address) + "_asset_") + asset) + "_lastCheckFarmedAmount"))) | |
355 | + | let withdrawnAmount = tryGetInteger((((("address_" + address) + "_asset_") + asset) + "_withdrawnAmount")) | |
356 | + | let reward = ((farmedAmount - withdrawnAmount) / (scale * 100)) | |
357 | + | if ((0 >= reward)) | |
358 | + | then throw("you have no EGGs to withdraw") | |
359 | + | else $Tuple2([IntegerEntry((((("address_" + address) + "_asset_") + asset) + "_withdrawnAmount"), (tryGetInteger((((("address_" + address) + "_asset_") + asset) + "_withdrawnAmount")) + (reward * scale2))), ScriptTransfer(Address(fromBase58String(address)), (reward * 1000000), getEggAssetId())], (reward * 1000000)) | |
360 | + | } | |
343 | 361 | ||
344 | - | ||
345 | - | ||
346 | - | @Callable(i) | |
347 | - | func issueArtefact (type,receiver) = if ((i.caller == this)) | |
348 | - | then { | |
349 | - | let txIdStr = toBase58String(i.transactionId) | |
350 | - | let address = Address(fromBase58String(receiver)) | |
351 | - | let artefact = Issue(type, "NFT artefact of Waves Ducks game. Drop #2.", 1, 0, false, unit, 0) | |
352 | - | let artefactId = calculateAssetId(artefact) | |
353 | - | [artefact, StringEntry((("artefact_" + toBase58String(artefactId)) + "_type"), type), ScriptTransfer(address, 1, artefactId)] | |
354 | - | } | |
355 | - | else throw("admin only") | |
356 | - | ||
357 | - | ||
358 | - | ||
359 | - | @Callable(i) | |
360 | - | func setLock (n) = if ((i.caller == this)) | |
361 | - | then [IntegerEntry("global_locked", n)] | |
362 | - | else throw("admin only") | |
363 | - | ||
364 | - | ||
365 | - | ||
366 | - | @Callable(i) | |
367 | - | func buyArtefact () = if ((lastBlock.timestamp > 1639742400000)) | |
368 | - | then throw("There are no active sales now... ") | |
369 | - | else if ((tryGetInteger("global_locked") > 0)) | |
370 | - | then throw("contract is temporarily locked") | |
371 | - | else if ((tryGetInteger("global_artAmount") >= artefactsLimit)) | |
372 | - | then throw("SOLDOUT!!! Hurray!") | |
373 | - | else if (if ((1639605600000 > lastBlock.timestamp)) | |
374 | - | then (i.caller != Address(devAddress)) | |
375 | - | else false) | |
376 | - | then throw("Too early...") | |
377 | - | else { | |
378 | - | let firstPayment = value(i.payments[0]) | |
379 | - | if ((firstPayment.assetId != getEggAssetId())) | |
380 | - | then throw(("You can attach only EGG tokens with the following asset id: " + toBase58String(getEggAssetId()))) | |
381 | - | else if ((eggsNeeded > firstPayment.amount)) | |
382 | - | then throw(("To hatch a duck you currently need the following amount of EGGlets: " + toString(eggsNeeded))) | |
383 | - | else [StringEntry((((toString(i.caller) + "_") + toBase58String(i.transactionId)) + "_status"), "started"), IntegerEntry((((toString(i.caller) + "_") + toBase58String(i.transactionId)) + "_finishHeight"), (height + 2)), IntegerEntry("global_artAmount", (tryGetInteger("global_artAmount") + 1))] | |
384 | - | } | |
385 | - | ||
386 | - | ||
387 | - | ||
388 | - | @Callable(i) | |
389 | - | func setGlobalArtAmount (newAmount) = if (if ((i.caller == this)) | |
390 | - | then true | |
391 | - | else (i.caller == Address(devAddress))) | |
392 | - | then [IntegerEntry("global_artAmount", newAmount)] | |
393 | - | else throw("Permission denied") | |
394 | - | ||
395 | - | ||
396 | - | ||
397 | - | @Callable(i) | |
398 | - | func claimArtefact (boxIdStr) = { | |
399 | - | let txId = fromBase58String(boxIdStr) | |
400 | - | let statusKey = (((toString(i.caller) + "_") + boxIdStr) + "_status") | |
401 | - | let heightKey = (((toString(i.caller) + "_") + boxIdStr) + "_finishHeight") | |
402 | - | if ((getStringValue(statusKey) != "started")) | |
403 | - | then throw("claimed already") | |
404 | - | else if ((getIntegerValue(heightKey) > height)) | |
405 | - | then throw("you cannot claim yet") | |
406 | - | else { | |
407 | - | let artType = getRandomArtefact(txId, getIntegerValue(heightKey)) | |
408 | - | let asset = Issue(artType, "Artefact of Waves Ducks metaverse.", 1, 0, false, unit, getIntegerValue(heightKey)) | |
409 | - | let assetId = calculateAssetId(asset) | |
410 | - | [StringEntry(statusKey, artType), StringEntry((((toString(i.caller) + "_") + boxIdStr) + "_artefactId"), toBase58String(assetId)), StringEntry((toBase58String(assetId) + "_type"), artType), asset, ScriptTransfer(i.caller, 1, assetId)] | |
411 | - | } | |
412 | - | } | |
413 | - | ||
414 | - | ||
415 | - | @Verifier(tx) | |
416 | - | func verify () = sigVerify(tx.bodyBytes, tx.proofs[0], tx.senderPublicKey) | |
417 | 362 |
Old | New | Differences | |
---|---|---|---|
1 | 1 | {-# STDLIB_VERSION 5 #-} | |
2 | 2 | {-# SCRIPT_TYPE ACCOUNT #-} | |
3 | 3 | {-# CONTENT_TYPE DAPP #-} | |
4 | - | ||
4 | + | let perchPrice = (100 * 1000000) | |
5 | 5 | ||
6 | + | let scale = 10000 | |
6 | 7 | ||
7 | - | func keyUnstakeHeight (artefactName,artefactId) = (((artefactName + "_") + artefactId) + "_unstake_height") | |
8 | - | ||
9 | - | ||
10 | - | func getProcessFinishHeightKey (address,txId) = (((address + "_") + toBase58String(txId)) + "_fh") | |
11 | - | ||
12 | - | ||
13 | - | let devAddress = base58'3P44yqcpfhPF2iC1nptm2ZJCTaN7VYhz9og' | |
14 | - | ||
15 | - | let eggsNeeded = (3 * 100000000) | |
16 | - | ||
17 | - | let artefactsLimit = (301 + 600) | |
18 | - | ||
19 | - | let freeGenes = ["A", "B", "C", "D", "E"] | |
20 | - | ||
21 | - | let oldArtefacts = ["ART-LAKE", "ART-HOUSE", "ART-BIGHOUSE", "ART-FIXGENE", "ART-FREEGENE", "ART-MIRROR", "ART-POMP", "ART-CAPE", "ART-HAT", "ART-CUSTOMDUCK"] | |
22 | - | ||
23 | - | let artefacts = ["ART-XMISTL", "ART-XHAT", "ART-XSCARF", "ART-XSWEATER", "ART-XSOCK", "ART-XTREE"] | |
24 | - | ||
25 | - | let stakeableWithLock = ["ART-LAKE", "ART-XTREE"] | |
26 | - | ||
27 | - | let stakeableWithoutLock = ["ART-XMISTL"] | |
28 | - | ||
29 | - | let allStakeable = (stakeableWithoutLock ++ stakeableWithLock) | |
30 | - | ||
31 | - | let allArtefact = (artefacts ++ oldArtefacts) | |
32 | - | ||
33 | - | func tryGetString (key) = match getString(this, key) { | |
34 | - | case a: String => | |
35 | - | a | |
36 | - | case _ => | |
37 | - | "" | |
38 | - | } | |
39 | - | ||
40 | - | ||
41 | - | func tryGetInteger (key) = match getInteger(this, key) { | |
42 | - | case a: Int => | |
43 | - | a | |
44 | - | case _ => | |
45 | - | 0 | |
46 | - | } | |
47 | - | ||
48 | - | ||
49 | - | func getRandomNumber (variants,txId,finishHeight,offset) = { | |
50 | - | let randomSeedBlock = value(blockInfoByHeight((finishHeight - 1))) | |
51 | - | let randomHash = sha256(((base58'items' + txId) + value(randomSeedBlock.vrf))) | |
52 | - | (toInt(randomHash, offset) % variants) | |
53 | - | } | |
54 | - | ||
55 | - | ||
56 | - | func getRandomArtefact (boxId,h) = { | |
57 | - | let randomNumber = getRandomNumber(6, boxId, h, 1) | |
58 | - | artefacts[randomNumber] | |
59 | - | } | |
60 | - | ||
61 | - | ||
62 | - | func getRandomGenes (txId,h) = { | |
63 | - | let randomNumber = getRandomNumber(6, txId, h, 2) | |
64 | - | freeGenes[randomNumber] | |
65 | - | } | |
66 | - | ||
67 | - | ||
68 | - | func checkArtefactDetails (assetId) = { | |
69 | - | let asset = value(assetInfo(assetId)) | |
70 | - | let assetName = value(asset.name) | |
71 | - | if (if (containsElement(allArtefact, assetName)) | |
72 | - | then (asset.issuer == this) | |
73 | - | else false) | |
74 | - | then assetName | |
75 | - | else throw("Invalid artefact") | |
76 | - | } | |
77 | - | ||
8 | + | let scale2 = 1000000 | |
78 | 9 | ||
79 | 10 | func tryGetStringExternal (address,key) = match getString(address, key) { | |
80 | 11 | case a: String => | |
81 | 12 | a | |
82 | 13 | case _ => | |
83 | 14 | "" | |
84 | 15 | } | |
85 | 16 | ||
86 | 17 | ||
18 | + | func tryGetString (key) = tryGetStringExternal(this, key) | |
19 | + | ||
20 | + | ||
87 | 21 | func getOracle () = Address(fromBase58String(tryGetString("static_oracleAddress"))) | |
22 | + | ||
23 | + | ||
24 | + | func getEggAssetId () = fromBase58String(tryGetStringExternal(getOracle(), "static_eggAssetId")) | |
25 | + | ||
26 | + | ||
27 | + | func getIncubatorAddress () = Address(fromBase58String(tryGetStringExternal(getOracle(), "static_incubatorAddress"))) | |
28 | + | ||
29 | + | ||
30 | + | func getRebirthAddress () = Address(fromBase58String(tryGetStringExternal(getOracle(), "static_rebirthAddress"))) | |
31 | + | ||
32 | + | ||
33 | + | func getSwopPromoAddress () = Address(fromBase58String(tryGetStringExternal(getOracle(), "static_swopPromoAddress"))) | |
88 | 34 | ||
89 | 35 | ||
90 | 36 | func getBreederAddress () = Address(fromBase58String(tryGetStringExternal(getOracle(), "static_breederAddress"))) | |
91 | 37 | ||
92 | 38 | ||
93 | - | func getEggAssetId () = fromBase58String(tryGetStringExternal(getOracle(), "static_eggAssetId")) | |
39 | + | func getRefContractAddress () = Address(fromBase58String(tryGetStringExternal(getOracle(), "static_refContractAddress"))) | |
40 | + | ||
41 | + | ||
42 | + | func getItemsAddress () = Address(fromBase58String(tryGetStringExternal(getOracle(), "static_itemsAddress"))) | |
43 | + | ||
44 | + | ||
45 | + | let RefererReward = 5 | |
46 | + | ||
47 | + | func getRewardPerBlock () = 684 | |
48 | + | ||
49 | + | ||
50 | + | func isLocked () = { | |
51 | + | let masterAddress = Address(base58'3PEPftf2kWZDmAaWBjs6BUJa9957kiA2PkU') | |
52 | + | match getInteger(masterAddress, "egglock") { | |
53 | + | case b: Int => | |
54 | + | b | |
55 | + | case _ => | |
56 | + | 0 | |
57 | + | } | |
58 | + | } | |
59 | + | ||
60 | + | ||
61 | + | func tryGetInteger (key) = match getInteger(this, key) { | |
62 | + | case b: Int => | |
63 | + | b | |
64 | + | case _ => | |
65 | + | 0 | |
66 | + | } | |
67 | + | ||
68 | + | ||
69 | + | func isUserBlacklisted (address) = false | |
70 | + | ||
71 | + | ||
72 | + | func getAssetOrigin (generation) = if ((generation == "G")) | |
73 | + | then getIncubatorAddress() | |
74 | + | else getBreederAddress() | |
75 | + | ||
76 | + | ||
77 | + | func getAssetRarity (genotype,generation) = { | |
78 | + | let quantity = valueOrErrorMessage(getInteger(getAssetOrigin(generation), (("stats_" + genotype) + "_quantity")), (("stats_" + genotype) + "_quantity not found")) | |
79 | + | let power = pow((10000 / quantity), 4, 5, 1, 2, FLOOR) | |
80 | + | if ((power > 0)) | |
81 | + | then power | |
82 | + | else 2 | |
83 | + | } | |
94 | 84 | ||
95 | 85 | ||
96 | 86 | func asString (value) = match value { | |
97 | 87 | case string: String => | |
98 | 88 | string | |
99 | 89 | case _ => | |
100 | 90 | throw("wrong type, expected: String") | |
101 | 91 | } | |
102 | 92 | ||
103 | 93 | ||
104 | 94 | func asInt (value) = match value { | |
105 | 95 | case int: Int => | |
106 | 96 | int | |
107 | 97 | case _ => | |
108 | 98 | throw("wrong type, expected: Int") | |
109 | 99 | } | |
110 | 100 | ||
111 | 101 | ||
112 | - | func manipulateName (assetName,position,char) = ((take(assetName, (position - 1)) + char) + takeRight(assetName, (16 - position))) | |
102 | + | func getAssetFarmingPower (assetId,address) = if (if ((value(assetInfo(assetId)).issuer == getBreederAddress())) | |
103 | + | then true | |
104 | + | else (value(assetInfo(assetId)).issuer == getIncubatorAddress())) | |
105 | + | then { | |
106 | + | let assetName = value(assetInfo(assetId)).name | |
107 | + | let generation = take(takeRight(assetName, 2), 1) | |
108 | + | let farmGen = asString(invoke(getBreederAddress(), "getGenFromName", [assetName], nil)) | |
109 | + | if ((farmGen == farmGen)) | |
110 | + | then { | |
111 | + | let farmBoost = asInt(invoke(getItemsAddress(), "calculateFarmingPowerBoost", [toBase58String(assetId), address], nil)) | |
112 | + | if ((farmBoost == farmBoost)) | |
113 | + | then { | |
114 | + | let rarity = getAssetRarity(farmGen, generation) | |
115 | + | let totalFarmingPower = (rarity + fraction(rarity, farmBoost, 100)) | |
116 | + | $Tuple2(farmGen, totalFarmingPower) | |
117 | + | } | |
118 | + | else throw("Strict value is not equal to itself.") | |
119 | + | } | |
120 | + | else throw("Strict value is not equal to itself.") | |
121 | + | } | |
122 | + | else throw("not valid NFT") | |
113 | 123 | ||
114 | 124 | ||
115 | - | func itemIsInCoolDown (artefactName,artefactId) = { | |
116 | - | let unstakeHeightLast = tryGetInteger(keyUnstakeHeight(artefactName, artefactId)) | |
117 | - | let cooldownPeriod = 240 | |
118 | - | if ((height > (unstakeHeightLast + cooldownPeriod))) | |
119 | - | then false | |
120 | - | else true | |
125 | + | func getLastKnownAssetFarmingPower (address,assetId) = tryGetInteger((((("address_" + address) + "_asset_") + assetId) + "_farmingPower")) | |
126 | + | ||
127 | + | ||
128 | + | func getAssetsByGen (gen) = { | |
129 | + | let s = tryGetString(("assets_" + gen)) | |
130 | + | if ((s == "")) | |
131 | + | then nil | |
132 | + | else split(s, ",") | |
133 | + | } | |
134 | + | ||
135 | + | ||
136 | + | func calcInterest (previousInterest,previousInterestHeight,totalFarmingPower) = (previousInterest + (((scale * getRewardPerBlock()) * (height - previousInterestHeight)) / totalFarmingPower)) | |
137 | + | ||
138 | + | ||
139 | + | func getCurrentInterest () = if ((tryGetInteger("total_farmingPower") > 0)) | |
140 | + | then { | |
141 | + | let previousInterest = tryGetInteger("total_lastCheckInterest") | |
142 | + | let previousInterestHeight = tryGetInteger("total_lastCheckInterestHeight") | |
143 | + | let totalFarmingPower = tryGetInteger("total_farmingPower") | |
144 | + | calcInterest(previousInterest, previousInterestHeight, totalFarmingPower) | |
145 | + | } | |
146 | + | else if ((tryGetInteger("total_startHeight") != 0)) | |
147 | + | then tryGetInteger("total_lastCheckInterest") | |
148 | + | else throw("farming is not launched, yet") | |
149 | + | ||
150 | + | ||
151 | + | func calcAssetRewardDelta (address,assetId,assetFarmingPower) = { | |
152 | + | let lastCheckAssetInterest = tryGetInteger((((("address_" + address) + "_asset_") + assetId) + "_lastCheckInterest")) | |
153 | + | let currentInterest = getCurrentInterest() | |
154 | + | (assetFarmingPower * (currentInterest - lastCheckAssetInterest)) | |
155 | + | } | |
156 | + | ||
157 | + | ||
158 | + | func addAssetIdToGenEntry (assetId,assetGen) = { | |
159 | + | let currentValue = tryGetString((("assets_" + assetGen) + "_locked")) | |
160 | + | if ((currentValue == "")) | |
161 | + | then assetId | |
162 | + | else ((currentValue + ",") + assetId) | |
163 | + | } | |
164 | + | ||
165 | + | ||
166 | + | func getStakeResult (address,assetId,assetFarmingPower) = { | |
167 | + | let asset = toBase58String(assetId) | |
168 | + | [IntegerEntry("total_farmingPower", (tryGetInteger("total_farmingPower") + assetFarmingPower)), IntegerEntry("total_lastCheckInterest", getCurrentInterest()), IntegerEntry("total_lastCheckInterestHeight", height), IntegerEntry((((("address_" + address) + "_asset_") + asset) + "_farmingPower"), assetFarmingPower), IntegerEntry((((("address_" + address) + "_asset_") + asset) + "_lastCheckInterest"), getCurrentInterest())] | |
169 | + | } | |
170 | + | ||
171 | + | ||
172 | + | func getUnstakeResult (address,assetId,rewardDelta,withdrawnAmount,assetFarmingPower) = { | |
173 | + | let asset = toBase58String(assetId) | |
174 | + | [IntegerEntry("total_farmingPower", (tryGetInteger("total_farmingPower") - assetFarmingPower)), IntegerEntry("total_lastCheckInterest", getCurrentInterest()), IntegerEntry("total_lastCheckInterestHeight", height), IntegerEntry((((("address_" + address) + "_asset_") + asset) + "_farmingPower"), 0), IntegerEntry((((("address_" + address) + "_asset_") + asset) + "_lastCheckInterest"), getCurrentInterest()), IntegerEntry((((("address_" + address) + "_asset_") + asset) + "_withdrawnAmount"), (tryGetInteger((((("address_" + address) + "_asset_") + asset) + "_withdrawnAmount")) + (withdrawnAmount * scale2))), IntegerEntry((((("address_" + address) + "_asset_") + asset) + "_lastCheckFarmedAmount"), (tryGetInteger((((("address_" + address) + "_asset_") + asset) + "_lastCheckFarmedAmount")) + rewardDelta))] | |
175 | + | } | |
176 | + | ||
177 | + | ||
178 | + | func calculatePerchPrice (address) = { | |
179 | + | let hasArtefactStaked = tryGetStringExternal(getItemsAddress(), (("ART-XMISTL_" + address) + "_owner")) | |
180 | + | if ((hasArtefactStaked == "")) | |
181 | + | then perchPrice | |
182 | + | else ((perchPrice / 10) * 9) | |
121 | 183 | } | |
122 | 184 | ||
123 | 185 | ||
124 | 186 | @Callable(i) | |
125 | 187 | func configureOracle (oracle) = if ((i.caller != this)) | |
126 | 188 | then throw("admin only") | |
127 | 189 | else [StringEntry("static_oracleAddress", oracle)] | |
128 | 190 | ||
129 | 191 | ||
130 | 192 | ||
131 | 193 | @Callable(i) | |
132 | - | func calculateFarmingPowerBoost (duckId,address) = { | |
133 | - | let lakeBoost = if ((tryGetString(keyArtefactOwner("ART-LAKE", address)) != "")) | |
134 | - | then 2 | |
135 | - | else 0 | |
136 | - | let xmasTreeBoost = if ((tryGetString(keyArtefactOwner("ART-XTREE", address)) != "")) | |
137 | - | then 3 | |
138 | - | else 0 | |
139 | - | let totalBoost = (lakeBoost + xmasTreeBoost) | |
140 | - | $Tuple2(nil, totalBoost) | |
141 | - | } | |
194 | + | func init () = if ((i.caller != this)) | |
195 | + | then throw("admin only") | |
196 | + | else [IntegerEntry("total_startHeight", height)] | |
142 | 197 | ||
143 | 198 | ||
144 | 199 | ||
145 | 200 | @Callable(i) | |
146 | - | func fixedGene (txIdStr,parentFixedGene,positionFixedGene) = { | |
147 | - | let firstPayment = value(i.payments[0]) | |
148 | - | let firstAssetId = toBase58String(value(firstPayment.assetId)) | |
149 | - | if ((firstPayment.amount != 1)) | |
150 | - | then throw("NFT is not attached") | |
201 | + | func buyPerch (color,refererAddress) = if ((isLocked() > 0)) | |
202 | + | then throw("EGG operations are temporarily locked") | |
203 | + | else if ((0 > value(indexOf(["B", "R", "G", "Y"], color)))) | |
204 | + | then throw("you need to set color properly") | |
151 | 205 | else { | |
152 | - | let | |
153 | - | | |
154 | - | | |
155 | - | | |
156 | - | | |
157 | - | | |
158 | - | | |
159 | - | let | |
160 | - | | |
161 | - | | |
162 | - | | |
163 | - | | |
164 | - | | |
165 | - | ||
166 | - | } | |
167 | - | else throw("Strict value is not equal to itself.") | |
168 | - | } | |
206 | + | let firstPayment = value(i.payments[0]) | |
207 | + | let exactPrice = calculatePerchPrice(toString(i.caller)) | |
208 | + | if ((firstPayment.assetId != getEggAssetId())) | |
209 | + | then throw(("You can attach only EGG tokens with the following asset id: " + toBase58String(getEggAssetId()))) | |
210 | + | else if ((firstPayment.amount != exactPrice)) | |
211 | + | then throw(("To buy a perch you currently need the following amount of EGGlets: " + toString(exactPrice))) | |
212 | + | else { | |
213 | + | let refererRewardForPerch = fraction(firstPayment.amount, RefererReward, 100) | |
214 | + | let refCall = invoke(getRefContractAddress(), "refPayment", [refererAddress], [AttachedPayment(getEggAssetId(), refererRewardForPerch)]) | |
215 | + | if ((refCall == refCall)) | |
216 | + | then { | |
217 | + | let perchAmountKey = ((("address_" + toString(i.caller)) + "_perchesAvailable_") + color) | |
218 | + | let perchAmount = tryGetInteger(perchAmountKey) | |
219 | + | [IntegerEntry(perchAmountKey, (perchAmount + 1))] | |
220 | + | } | |
221 | + | else throw("Strict value is not equal to itself.") | |
222 | + | } | |
169 | 223 | } | |
170 | - | } | |
171 | 224 | ||
172 | 225 | ||
173 | 226 | ||
174 | 227 | @Callable(i) | |
175 | - | func freeGene (txIdStr) = { | |
176 | - | let firstPayment = value(i.payments[0]) | |
177 | - | let firstAssetId = toBase58String(value(firstPayment.assetId)) | |
178 | - | if ((firstPayment.amount != 1)) | |
179 | - | then throw("NFT is not attached") | |
228 | + | func addFreePerch (address,color) = if ((0 > value(indexOf(["B", "R", "G", "Y"], color)))) | |
229 | + | then throw("you need to set color properly") | |
230 | + | else if (if (if ((i.caller != getRebirthAddress())) | |
231 | + | then (i.caller != this) | |
232 | + | else false) | |
233 | + | then (i.caller != getSwopPromoAddress()) | |
234 | + | else false) | |
235 | + | then throw("rebirth and swop promo only") | |
180 | 236 | else { | |
181 | - | let artefact = checkArtefactDetails(value(firstPayment.assetId)) | |
182 | - | if ((artefact != "ART-FREEGENE")) | |
183 | - | then throw("You need to attach a ART-FREEGENE artefact") | |
184 | - | else { | |
185 | - | let txId = fromBase58String(txIdStr) | |
186 | - | let finishHeightKey = getProcessFinishHeightKey(toString(i.caller), txId) | |
187 | - | let processFinishHeight = getIntegerValue(getBreederAddress(), finishHeightKey) | |
188 | - | let selectedGene = getRandomGenes(txId, processFinishHeight) | |
189 | - | let randomPosition = getRandomNumber(7, txId, processFinishHeight, 3) | |
190 | - | let duckGenesString = asString(invoke(getBreederAddress(), "generateDuck", [txIdStr, processFinishHeight, 0, 0, selectedGene, randomPosition], nil)) | |
191 | - | if ((duckGenesString == duckGenesString)) | |
192 | - | then { | |
193 | - | let call = invoke(getBreederAddress(), "finishDuckHatchingItems", [txIdStr, duckGenesString], nil) | |
194 | - | if ((call == call)) | |
195 | - | then [Burn(value(firstPayment.assetId), 1)] | |
196 | - | else throw("Strict value is not equal to itself.") | |
197 | - | } | |
198 | - | else throw("Strict value is not equal to itself.") | |
199 | - | } | |
237 | + | let perchAmountKey = ((("address_" + address) + "_perchesAvailable_") + color) | |
238 | + | let perchAmount = tryGetInteger(perchAmountKey) | |
239 | + | $Tuple2([IntegerEntry(perchAmountKey, (perchAmount + 1))], "") | |
200 | 240 | } | |
201 | - | } | |
202 | 241 | ||
203 | 242 | ||
204 | 243 | ||
205 | 244 | @Callable(i) | |
206 | - | func | |
207 | - | | |
208 | - | | |
209 | - | let | |
210 | - | let | |
211 | - | | |
212 | - | | |
213 | - | | |
214 | - | | |
245 | + | func stakeNFT () = if ((isLocked() > 0)) | |
246 | + | then throw("EGG operations are temporarily locked") | |
247 | + | else { | |
248 | + | let pmt = value(i.payments[0]) | |
249 | + | let assetId = value(value(i.payments[0]).assetId) | |
250 | + | let address = toString(i.caller) | |
251 | + | let color = takeRight(value(assetInfo(assetId)).name, 1) | |
252 | + | let availablePerches = tryGetInteger(((("address_" + toString(i.caller)) + "_perchesAvailable_") + color)) | |
253 | + | if ((pmt.amount != 1)) | |
215 | 254 | then throw("NFT is not attached") | |
216 | - | else { | |
217 | - | let artefact = checkArtefactDetails(value(secondPayment.assetId)) | |
218 | - | if ((artefact != "ART-MIRROR")) | |
219 | - | then throw("You need to attach a ART-MIRROR artefact") | |
220 | - | else { | |
221 | - | let nftInfo = value(assetInfo(value(firstPayment.assetId))) | |
222 | - | let asset1Gen = split(nftInfo.name, "") | |
223 | - | if (if ((asset1Gen[14] == "G")) | |
224 | - | then true | |
225 | - | else (asset1Gen[14] == "J")) | |
226 | - | then throw("You can't mirror this duck") | |
227 | - | else { | |
228 | - | let duckGen = nftInfo.name | |
229 | - | let call = invoke(getBreederAddress(), "createDuckSpecialGenes", [i.caller.bytes, duckGen, children], nil) | |
230 | - | if ((call == call)) | |
231 | - | then [ScriptTransfer(i.caller, 1, firstPayment.assetId), Burn(value(secondPayment.assetId), 1)] | |
232 | - | else throw("Strict value is not equal to itself.") | |
233 | - | } | |
234 | - | } | |
235 | - | } | |
236 | - | else throw("Strict value is not equal to itself.") | |
237 | - | } | |
255 | + | else if ((0 >= availablePerches)) | |
256 | + | then throw(("no perches available for the color " + color)) | |
257 | + | else { | |
258 | + | let $t096749747 = getAssetFarmingPower(assetId, address) | |
259 | + | let assetGen = $t096749747._1 | |
260 | + | let assetFarmingPower = $t096749747._2 | |
261 | + | let assetRewardDelta = calcAssetRewardDelta(address, toBase58String(assetId), assetFarmingPower) | |
262 | + | (getStakeResult(address, assetId, assetFarmingPower) ++ [IntegerEntry(((("address_" + toString(i.caller)) + "_perchesAvailable_") + color), (availablePerches - 1))]) | |
263 | + | } | |
264 | + | } | |
238 | 265 | ||
239 | 266 | ||
240 | 267 | ||
241 | 268 | @Callable(i) | |
242 | - | func addArteFactToDuck () = { | |
243 | - | let firstPayment = value(i.payments[0]) | |
244 | - | let secondPayment = value(i.payments[1]) | |
245 | - | let firstAssetId = toBase58String(value(firstPayment.assetId)) | |
246 | - | if (if ((firstPayment.amount != 1)) | |
247 | - | then true | |
248 | - | else (secondPayment.amount != 1)) | |
249 | - | then throw("NFT is not attached") | |
269 | + | func unstakeNFT (asset) = if (isUserBlacklisted(toString(i.caller))) | |
270 | + | then throw("Ooops, looks like you lost in one of the Ducksquid games! As you already know, any loss has its consequences, so you will be not able to claim your farming rewards till the end of DuckSquid game. Quack in peace!") | |
271 | + | else if ((isLocked() > 0)) | |
272 | + | then throw("EGG operations are temporarily locked") | |
250 | 273 | else { | |
251 | - | let children = asInt(invoke(getBreederAddress(), "validateAndGetChildren", [firstAssetId], nil)) | |
252 | - | if ((children == children)) | |
253 | - | then if ((children == 0)) | |
254 | - | then throw("You can only pick a sterile NFT-duck") | |
274 | + | let assetId = fromBase58String(asset) | |
275 | + | let address = toString(i.caller) | |
276 | + | let assetFarmingPower = getLastKnownAssetFarmingPower(address, asset) | |
277 | + | let assetRewardDelta = calcAssetRewardDelta(address, asset, assetFarmingPower) | |
278 | + | let farmedAmount = (assetRewardDelta + tryGetInteger((((("address_" + address) + "_asset_") + asset) + "_lastCheckFarmedAmount"))) | |
279 | + | let withdrawnAmount = tryGetInteger((((("address_" + address) + "_asset_") + asset) + "_withdrawnAmount")) | |
280 | + | let reward = ((farmedAmount - withdrawnAmount) / (scale * 100)) | |
281 | + | let color = takeRight(value(assetInfo(assetId)).name, 1) | |
282 | + | if ((0 >= assetFarmingPower)) | |
283 | + | then throw("asset not available") | |
284 | + | else if ((color == "U")) | |
285 | + | then throw("use another function to unstake Jackpot NFT") | |
255 | 286 | else { | |
256 | - | let artefact = checkArtefactDetails(value(secondPayment.assetId)) | |
257 | - | if (if ((artefact != "ART-XHAT")) | |
258 | - | then (artefact != "ART-POMP") | |
259 | - | else false) | |
260 | - | then throw("You need to attach a ART-XHAT or ART-POMP artefact") | |
261 | - | else { | |
262 | - | let nftInfo = value(assetInfo(value(firstPayment.assetId))) | |
263 | - | let asset1Gen = split(nftInfo.name, "") | |
264 | - | if (if ((asset1Gen[14] == "G")) | |
265 | - | then true | |
266 | - | else (asset1Gen[14] == "J")) | |
267 | - | then throw("You can't mirror this duck") | |
268 | - | else if (if ((asset1Gen[5] == "S")) | |
269 | - | then true | |
270 | - | else (asset1Gen[5] == "T")) | |
271 | - | then throw("you already attached a artefact") | |
272 | - | else { | |
273 | - | let char = if ((artefact == "ART-XHAT")) | |
274 | - | then "T" | |
275 | - | else if ((artefact == "ART-POMP")) | |
276 | - | then "S" | |
277 | - | else throw("No char defined") | |
278 | - | let oldDuckGen = nftInfo.name | |
279 | - | let oldFarmGen = asString(invoke(getBreederAddress(), "getGenFromName", [oldDuckGen], nil)) | |
280 | - | if ((oldFarmGen == oldFarmGen)) | |
281 | - | then { | |
282 | - | let duckGen = manipulateName(oldDuckGen, 6, char) | |
283 | - | let call = invoke(getBreederAddress(), "createDuckSpecialGenes", [i.caller.bytes, duckGen, children], nil) | |
284 | - | if ((call == call)) | |
285 | - | then { | |
286 | - | let callReduce = invoke(getBreederAddress(), "reduceRarity", [firstAssetId, oldFarmGen], nil) | |
287 | - | if ((callReduce == callReduce)) | |
288 | - | then [Burn(value(firstPayment.assetId), 1), Burn(value(secondPayment.assetId), 1)] | |
289 | - | else throw("Strict value is not equal to itself.") | |
290 | - | } | |
291 | - | else throw("Strict value is not equal to itself.") | |
292 | - | } | |
293 | - | else throw("Strict value is not equal to itself.") | |
294 | - | } | |
295 | - | } | |
287 | + | let result = getUnstakeResult(address, assetId, assetRewardDelta, reward, assetFarmingPower) | |
288 | + | $Tuple2((result ++ [IntegerEntry(((("address_" + toString(i.caller)) + "_perchesAvailable_") + color), (tryGetInteger(((("address_" + toString(i.caller)) + "_perchesAvailable_") + color)) + 1)), ScriptTransfer(i.caller, (reward * 1000000), getEggAssetId()), ScriptTransfer(i.caller, 1, assetId)]), (reward * 1000000)) | |
296 | 289 | } | |
297 | - | else throw("Strict value is not equal to itself.") | |
298 | 290 | } | |
299 | - | } | |
300 | 291 | ||
301 | 292 | ||
302 | 293 | ||
303 | 294 | @Callable(i) | |
304 | - | func | |
305 | - | then ( | |
306 | - | else | |
307 | - | | |
308 | - | let assetId = value( | |
309 | - | let | |
310 | - | | |
311 | - | | |
312 | - | | |
313 | - | | |
314 | - | | |
315 | - | | |
316 | - | | |
317 | - | | |
318 | - | | |
319 | - | | |
320 | - | | |
321 | - | | |
322 | - | else throw(" | |
295 | + | func stakeJackpot (color) = if ((isLocked() > 0)) | |
296 | + | then throw("EGG operations are temporarily locked") | |
297 | + | else { | |
298 | + | let pmt = value(i.payments[0]) | |
299 | + | let assetId = value(pmt.assetId) | |
300 | + | let address = toString(i.caller) | |
301 | + | let availablePerches = tryGetInteger(((("address_" + toString(i.caller)) + "_perchesAvailable_") + color)) | |
302 | + | let assetIssuer = value(assetInfo(assetId)).issuer | |
303 | + | if ((pmt.amount != 1)) | |
304 | + | then throw("NFT is not attached") | |
305 | + | else if (if ((assetIssuer == getIncubatorAddress())) | |
306 | + | then true | |
307 | + | else (assetIssuer == getBreederAddress())) | |
308 | + | then if ((takeRight(value(value(assetInfo(assetId)).name), 1) != "U")) | |
309 | + | then throw("jackpot only") | |
310 | + | else if ((0 >= availablePerches)) | |
311 | + | then throw(("no perches available for the color " + color)) | |
312 | + | else (getStakeResult(address, assetId, 100) ++ [IntegerEntry(((("address_" + toString(i.caller)) + "_perchesAvailable_") + color), (availablePerches - 1)), StringEntry((((("address_" + toString(i.caller)) + "_asset_") + toBase58String(assetId)) + "_perchColor"), color)]) | |
313 | + | else throw("asset is not valid") | |
323 | 314 | } | |
324 | - | else throw("Invalid payment") | |
325 | 315 | ||
326 | 316 | ||
327 | 317 | ||
328 | 318 | @Callable(i) | |
329 | - | func unstakeItem (artefactName) = if (containsElement(allArtefact, artefactName)) | |
330 | - | then { | |
331 | - | let invoker = toString(i.caller) | |
332 | - | let artefactId = tryGetString(keyArtefactOwner(artefactName, invoker)) | |
333 | - | if ((artefactId == "")) | |
334 | - | then throw(("You didnt stake " + artefactName)) | |
335 | - | else [IntegerEntry(keyUnstakeHeight(artefactName, artefactId), height), ScriptTransfer(i.caller, 1, fromBase58String(artefactId)), DeleteEntry(keyArtefactOwner(artefactName, invoker))] | |
336 | - | } | |
337 | - | else throw("This artefact doesn't exist") | |
319 | + | func unstakeJackpot (asset) = if (isUserBlacklisted(toString(i.caller))) | |
320 | + | then throw("Ooops, looks like you lost in one of the Ducksquid games! As you already know, any loss has its consequences, so you will be not able to claim your farming rewards till the end of DuckSquid game. Quack in peace!") | |
321 | + | else if ((isLocked() > 0)) | |
322 | + | then throw("EGG operations are temporarily locked") | |
323 | + | else { | |
324 | + | let assetId = fromBase58String(asset) | |
325 | + | let address = toString(i.caller) | |
326 | + | let color = tryGetString((((("address_" + address) + "_asset_") + asset) + "_perchColor")) | |
327 | + | let assetFarmingPower = getLastKnownAssetFarmingPower(address, asset) | |
328 | + | let assetRewardDelta = calcAssetRewardDelta(address, asset, assetFarmingPower) | |
329 | + | let farmedAmount = (assetRewardDelta + tryGetInteger((((("address_" + address) + "_asset_") + asset) + "_lastCheckFarmedAmount"))) | |
330 | + | let withdrawnAmount = tryGetInteger((((("address_" + address) + "_asset_") + asset) + "_withdrawnAmount")) | |
331 | + | let reward = ((farmedAmount - withdrawnAmount) / (scale * 100)) | |
332 | + | if ((takeRight(value(value(assetInfo(assetId)).name), 1) != "U")) | |
333 | + | then throw("jackpot only") | |
334 | + | else if ((assetFarmingPower > 0)) | |
335 | + | then { | |
336 | + | let result = getUnstakeResult(address, assetId, assetRewardDelta, reward, assetFarmingPower) | |
337 | + | $Tuple2((result ++ [IntegerEntry(((("address_" + toString(i.caller)) + "_perchesAvailable_") + color), (tryGetInteger(((("address_" + toString(i.caller)) + "_perchesAvailable_") + color)) + 1)), ScriptTransfer(i.caller, (reward * 1000000), getEggAssetId()), ScriptTransfer(i.caller, 1, assetId)]), (reward * 1000000)) | |
338 | + | } | |
339 | + | else throw("") | |
340 | + | } | |
338 | 341 | ||
339 | 342 | ||
340 | 343 | ||
341 | 344 | @Callable(i) | |
342 | - | func preInit () = [IntegerEntry("static_ART-LAKE_farmingSlots", 200), IntegerEntry("static_ART-LAKE_farmingBoost", 2), IntegerEntry("static_ART-HOUSE_farmingSlots", 4), IntegerEntry("static_ART-HOUSE_farmingBoost", 30), IntegerEntry("static_ART-BIGHOUSE_farmingSlots", 10), IntegerEntry("static_ART-BIGHOUSE_farmingBoost", 15)] | |
345 | + | func claimReward (asset) = if (isUserBlacklisted(toString(i.caller))) | |
346 | + | then throw("Ooops, looks like you lost in one of the Ducksquid games! As you already know, any loss has its consequences, so you will be not able to claim your farming rewards till the end of DuckSquid game. Quack in peace!") | |
347 | + | else if ((isLocked() > 0)) | |
348 | + | then throw("EGG operations are temporarily locked") | |
349 | + | else { | |
350 | + | let address = toString(i.caller) | |
351 | + | let assetId = fromBase58String(asset) | |
352 | + | let assetFarmingPower = getLastKnownAssetFarmingPower(address, asset) | |
353 | + | let assetRewardDelta = calcAssetRewardDelta(address, asset, assetFarmingPower) | |
354 | + | let farmedAmount = (assetRewardDelta + tryGetInteger((((("address_" + address) + "_asset_") + asset) + "_lastCheckFarmedAmount"))) | |
355 | + | let withdrawnAmount = tryGetInteger((((("address_" + address) + "_asset_") + asset) + "_withdrawnAmount")) | |
356 | + | let reward = ((farmedAmount - withdrawnAmount) / (scale * 100)) | |
357 | + | if ((0 >= reward)) | |
358 | + | then throw("you have no EGGs to withdraw") | |
359 | + | else $Tuple2([IntegerEntry((((("address_" + address) + "_asset_") + asset) + "_withdrawnAmount"), (tryGetInteger((((("address_" + address) + "_asset_") + asset) + "_withdrawnAmount")) + (reward * scale2))), ScriptTransfer(Address(fromBase58String(address)), (reward * 1000000), getEggAssetId())], (reward * 1000000)) | |
360 | + | } | |
343 | 361 | ||
344 | - | ||
345 | - | ||
346 | - | @Callable(i) | |
347 | - | func issueArtefact (type,receiver) = if ((i.caller == this)) | |
348 | - | then { | |
349 | - | let txIdStr = toBase58String(i.transactionId) | |
350 | - | let address = Address(fromBase58String(receiver)) | |
351 | - | let artefact = Issue(type, "NFT artefact of Waves Ducks game. Drop #2.", 1, 0, false, unit, 0) | |
352 | - | let artefactId = calculateAssetId(artefact) | |
353 | - | [artefact, StringEntry((("artefact_" + toBase58String(artefactId)) + "_type"), type), ScriptTransfer(address, 1, artefactId)] | |
354 | - | } | |
355 | - | else throw("admin only") | |
356 | - | ||
357 | - | ||
358 | - | ||
359 | - | @Callable(i) | |
360 | - | func setLock (n) = if ((i.caller == this)) | |
361 | - | then [IntegerEntry("global_locked", n)] | |
362 | - | else throw("admin only") | |
363 | - | ||
364 | - | ||
365 | - | ||
366 | - | @Callable(i) | |
367 | - | func buyArtefact () = if ((lastBlock.timestamp > 1639742400000)) | |
368 | - | then throw("There are no active sales now... ") | |
369 | - | else if ((tryGetInteger("global_locked") > 0)) | |
370 | - | then throw("contract is temporarily locked") | |
371 | - | else if ((tryGetInteger("global_artAmount") >= artefactsLimit)) | |
372 | - | then throw("SOLDOUT!!! Hurray!") | |
373 | - | else if (if ((1639605600000 > lastBlock.timestamp)) | |
374 | - | then (i.caller != Address(devAddress)) | |
375 | - | else false) | |
376 | - | then throw("Too early...") | |
377 | - | else { | |
378 | - | let firstPayment = value(i.payments[0]) | |
379 | - | if ((firstPayment.assetId != getEggAssetId())) | |
380 | - | then throw(("You can attach only EGG tokens with the following asset id: " + toBase58String(getEggAssetId()))) | |
381 | - | else if ((eggsNeeded > firstPayment.amount)) | |
382 | - | then throw(("To hatch a duck you currently need the following amount of EGGlets: " + toString(eggsNeeded))) | |
383 | - | else [StringEntry((((toString(i.caller) + "_") + toBase58String(i.transactionId)) + "_status"), "started"), IntegerEntry((((toString(i.caller) + "_") + toBase58String(i.transactionId)) + "_finishHeight"), (height + 2)), IntegerEntry("global_artAmount", (tryGetInteger("global_artAmount") + 1))] | |
384 | - | } | |
385 | - | ||
386 | - | ||
387 | - | ||
388 | - | @Callable(i) | |
389 | - | func setGlobalArtAmount (newAmount) = if (if ((i.caller == this)) | |
390 | - | then true | |
391 | - | else (i.caller == Address(devAddress))) | |
392 | - | then [IntegerEntry("global_artAmount", newAmount)] | |
393 | - | else throw("Permission denied") | |
394 | - | ||
395 | - | ||
396 | - | ||
397 | - | @Callable(i) | |
398 | - | func claimArtefact (boxIdStr) = { | |
399 | - | let txId = fromBase58String(boxIdStr) | |
400 | - | let statusKey = (((toString(i.caller) + "_") + boxIdStr) + "_status") | |
401 | - | let heightKey = (((toString(i.caller) + "_") + boxIdStr) + "_finishHeight") | |
402 | - | if ((getStringValue(statusKey) != "started")) | |
403 | - | then throw("claimed already") | |
404 | - | else if ((getIntegerValue(heightKey) > height)) | |
405 | - | then throw("you cannot claim yet") | |
406 | - | else { | |
407 | - | let artType = getRandomArtefact(txId, getIntegerValue(heightKey)) | |
408 | - | let asset = Issue(artType, "Artefact of Waves Ducks metaverse.", 1, 0, false, unit, getIntegerValue(heightKey)) | |
409 | - | let assetId = calculateAssetId(asset) | |
410 | - | [StringEntry(statusKey, artType), StringEntry((((toString(i.caller) + "_") + boxIdStr) + "_artefactId"), toBase58String(assetId)), StringEntry((toBase58String(assetId) + "_type"), artType), asset, ScriptTransfer(i.caller, 1, assetId)] | |
411 | - | } | |
412 | - | } | |
413 | - | ||
414 | - | ||
415 | - | @Verifier(tx) | |
416 | - | func verify () = sigVerify(tx.bodyBytes, tx.proofs[0], tx.senderPublicKey) | |
417 | 362 |
github/deemru/w8io/3ef1775 108.13 ms ◑