tx · 5ZdWShJqCUVN578vvEZFHEdBw7e8fC9mPHkjZj68bip

3MuZayPFVLM2GSiVHDbo1SCGagfLQh6pQEr:  -0.01900000 Waves

2022.09.27 02:48 [2246772] smart account 3MuZayPFVLM2GSiVHDbo1SCGagfLQh6pQEr > SELF 0.00000000 Waves

{ "type": 13, "id": "5ZdWShJqCUVN578vvEZFHEdBw7e8fC9mPHkjZj68bip", "fee": 1900000, "feeAssetId": null, "timestamp": 1664236132503, "version": 2, "chainId": 84, "sender": "3MuZayPFVLM2GSiVHDbo1SCGagfLQh6pQEr", "senderPublicKey": "GscL7UdayRbv4gkUuDa4FDPnDR2s81kqve8sM5MpDKdN", "proofs": [ "4S8Lm4TKqf9nxiBRCCocGuKuFQ9AL8LCLChAyhzNrgMm1JRjcsuGKk7qvKt3W9gQJR5niCk7G211r5cnf89RF3s4" ], "script": "base64:AAIEAAAAAAAAACAIAhIAEgQKAggBEgMKAQgSAwoBCBIAEgASABIECgIICAAAADEAAAAAE2dhbWVNYXN0ZXJQdWJsaWNLZXkJAAJZAAAAAQIAAAAsOWNlSmtLRFZZcmJjall1R1NwczNOYUFlUHRRUGpCY3lFZzNMR2thcFhpeVgAAAAADmdhbWVUb2tlbkxhYmVsAgAAAAlHX1RPS0VOSUQAAAAAEGdhbWVCYWxhbmNlTGFiZWwCAAAACUdfQkFMQU5DRQAAAAAVZ2FtZUNvbW11bml0eVBvdExhYmVsAgAAAA5HX0NPTU1VTklUWVBPVAEAAAARZ2FtZVByaXplUG90TGFiZWwAAAABAAAACmdhbWVOdW1iZXIJAAEsAAAAAgkAASwAAAACAgAAAAJHXwkAAaQAAAABBQAAAApnYW1lTnVtYmVyAgAAAAlfUFJJWkVQT1QBAAAAGWdhbWVQcml6ZVNoYXJlQW1vdW50TGFiZWwAAAABAAAACmdhbWVOdW1iZXIJAAEsAAAAAgkAASwAAAACAgAAAAJHXwkAAaQAAAABBQAAAApnYW1lTnVtYmVyAgAAABFfUFJJWkVTSEFSRUFNT1VOVAAAAAAQZ2FtZUNvdW50ZXJMYWJlbAIAAAAOR19HQU1FU0NPVU5URVIBAAAAEmdhbWVUb3RhbEJldHNMYWJlbAAAAAEAAAAKZ2FtZU51bWJlcgkAASwAAAACCQABLAAAAAICAAAAAkdfCQABpAAAAAEFAAAACmdhbWVOdW1iZXICAAAACl9UT1RBTEJFVFMBAAAAFmdhbWVQcm9jZXNzZWRCZXRzTGFiZWwAAAABAAAACmdhbWVOdW1iZXIJAAEsAAAAAgkAASwAAAACAgAAAAJHXwkAAaQAAAABBQAAAApnYW1lTnVtYmVyAgAAAA5fUFJPQ0VTU0VEQkVUUwEAAAAXZ2FtZVdpbm5lcnNDb3VudGVyTGFiZWwAAAABAAAACmdhbWVOdW1iZXIJAAEsAAAAAgkAASwAAAACAgAAAAJHXwkAAaQAAAABBQAAAApnYW1lTnVtYmVyAgAAAA1fV0lOTkVSU0NPVU5UAQAAABlnYW1lUHJvY2Vzc2VkV2lubmVyc0xhYmVsAAAAAQAAAApnYW1lTnVtYmVyCQABLAAAAAIJAAEsAAAAAgIAAAACR18JAAGkAAAAAQUAAAAKZ2FtZU51bWJlcgIAAAARX1BST0NFU1NFRFdJTk5FUlMBAAAAD2dhbWVSZXN1bHRMYWJlbAAAAAEAAAAKZ2FtZU51bWJlcgkAASwAAAACCQABLAAAAAICAAAAAkdfCQABpAAAAAEFAAAACmdhbWVOdW1iZXICAAAAB19SRVNVTFQBAAAAD2JldERldGFpbHNMYWJlbAAAAAIAAAAKZ2FtZU51bWJlcgAAAAliZXROdW1iZXIJAAEsAAAAAgkAASwAAAACCQABLAAAAAIJAAEsAAAAAgIAAAACR18JAAGkAAAAAQUAAAAKZ2FtZU51bWJlcgIAAAADX0JfCQABpAAAAAEFAAAACWJldE51bWJlcgIAAAALX0JFVERFVEFJTFMBAAAAEndpbm5lckRldGFpbHNMYWJlbAAAAAIAAAAKZ2FtZU51bWJlcgAAAAx3aW5uZXJOdW1iZXIJAAEsAAAAAgkAASwAAAACCQABLAAAAAIJAAEsAAAAAgIAAAACR18JAAGkAAAAAQUAAAAKZ2FtZU51bWJlcgIAAAADX1dfCQABpAAAAAEFAAAADHdpbm5lck51bWJlcgIAAAAOX1dJTk5FUkRFVEFJTFMBAAAADmdhbWVTdGF0ZUxhYmVsAAAAAQAAAApnYW1lTnVtYmVyCQABLAAAAAIJAAEsAAAAAgIAAAACR18JAAGkAAAAAQUAAAAKZ2FtZU51bWJlcgIAAAAGX1NUQVRFAQAAABNnYW1lUmFuZG9tSGFzaExhYmVsAAAAAQAAAApnYW1lTnVtYmVyCQABLAAAAAIJAAEsAAAAAgIAAAACR18JAAGkAAAAAQUAAAAKZ2FtZU51bWJlcgIAAAALX1JBTkRPTUhBU0gBAAAAD2dhbWVTdW1TaGFMYWJlbAAAAAEAAAAKZ2FtZU51bWJlcgkAASwAAAACCQABLAAAAAICAAAAAkdfCQABpAAAAAEFAAAACmdhbWVOdW1iZXICAAAAB19TVU1TSEEAAAAAEmdhbWVSU0FQdWJsaWNMYWJlbAIAAAALR19SU0FQVUJMSUMBAAAAFGdhbWVTdGFydEhlaWdodExhYmVsAAAAAQAAAApnYW1lTnVtYmVyCQABLAAAAAIJAAEsAAAAAgIAAAACR18JAAGkAAAAAQUAAAAKZ2FtZU51bWJlcgIAAAAMX1NUQVJUSEVJR0hUAQAAABJnYW1lRW5kSGVpZ2h0TGFiZWwAAAABAAAACmdhbWVOdW1iZXIJAAEsAAAAAgkAASwAAAACAgAAAAJHXwkAAaQAAAABBQAAAApnYW1lTnVtYmVyAgAAAApfRU5ESEVJR0hUAAAAABRnYW1lVGlja2V0UHJpY2VMYWJlbAIAAAANR19USUNLRVRQUklDRQEAAAALZ2FtZUJhbGFuY2UAAAAACQAEGgAAAAIFAAAABHRoaXMFAAAAEGdhbWVCYWxhbmNlTGFiZWwBAAAAEGdhbWVDb21tdW5pdHlQb3QAAAAACQAEGgAAAAIFAAAABHRoaXMFAAAAFWdhbWVDb21tdW5pdHlQb3RMYWJlbAEAAAAMZ2FtZVByaXplUG90AAAAAQAAAApnYW1lTnVtYmVyCQAEGgAAAAIFAAAABHRoaXMJAQAAABFnYW1lUHJpemVQb3RMYWJlbAAAAAEFAAAACmdhbWVOdW1iZXIBAAAAFGdhbWVQcml6ZVNoYXJlQW1vdW50AAAAAQAAAApnYW1lTnVtYmVyCQAEGgAAAAIFAAAABHRoaXMJAQAAABlnYW1lUHJpemVTaGFyZUFtb3VudExhYmVsAAAAAQUAAAAKZ2FtZU51bWJlcgEAAAAPZ2FtZXNHZXRDb3VudGVyAAAAAAkABBoAAAACBQAAAAR0aGlzBQAAABBnYW1lQ291bnRlckxhYmVsAQAAAA1nYW1lVG90YWxCZXRzAAAAAQAAAApnYW1lTnVtYmVyCQAEGgAAAAIFAAAABHRoaXMJAQAAABJnYW1lVG90YWxCZXRzTGFiZWwAAAABBQAAAApnYW1lTnVtYmVyAQAAABFnYW1lUHJvY2Vzc2VkQmV0cwAAAAEAAAAKZ2FtZU51bWJlcgkABBoAAAACBQAAAAR0aGlzCQEAAAAWZ2FtZVByb2Nlc3NlZEJldHNMYWJlbAAAAAEFAAAACmdhbWVOdW1iZXIBAAAAEmdhbWVXaW5uZXJzQ291bnRlcgAAAAEAAAAKZ2FtZU51bWJlcgkABBoAAAACBQAAAAR0aGlzCQEAAAAXZ2FtZVdpbm5lcnNDb3VudGVyTGFiZWwAAAABBQAAAApnYW1lTnVtYmVyAQAAABRnYW1lUHJvY2Vzc2VkV2lubmVycwAAAAEAAAAKZ2FtZU51bWJlcgkABBoAAAACBQAAAAR0aGlzCQEAAAAZZ2FtZVByb2Nlc3NlZFdpbm5lcnNMYWJlbAAAAAEFAAAACmdhbWVOdW1iZXIBAAAADWdhbWVHZXRSZXN1bHQAAAABAAAACmdhbWVOdW1iZXIJAQAAABFAZXh0ck5hdGl2ZSgxMDUzKQAAAAIFAAAABHRoaXMJAQAAAA9nYW1lUmVzdWx0TGFiZWwAAAABBQAAAApnYW1lTnVtYmVyAQAAAApiZXREZXRhaWxzAAAAAgAAAApnYW1lTnVtYmVyAAAACWJldE51bWJlcgkBAAAAEUBleHRyTmF0aXZlKDEwNTMpAAAAAgUAAAAEdGhpcwkBAAAAD2JldERldGFpbHNMYWJlbAAAAAIFAAAACmdhbWVOdW1iZXIFAAAACWJldE51bWJlcgEAAAANd2lubmVyRGV0YWlscwAAAAIAAAAKZ2FtZU51bWJlcgAAAAx3aW5uZXJOdW1iZXIJAQAAABFAZXh0ck5hdGl2ZSgxMDUzKQAAAAIFAAAABHRoaXMJAQAAABJ3aW5uZXJEZXRhaWxzTGFiZWwAAAACBQAAAApnYW1lTnVtYmVyBQAAAAx3aW5uZXJOdW1iZXIBAAAADGdhbWVHZXRTdGF0ZQAAAAEAAAAKZ2FtZU51bWJlcgkABBoAAAACBQAAAAR0aGlzCQEAAAAOZ2FtZVN0YXRlTGFiZWwAAAABBQAAAApnYW1lTnVtYmVyAQAAAA1nYW1lR2V0U3VtU2hhAAAAAQAAAApnYW1lTnVtYmVyCQAEHQAAAAIFAAAABHRoaXMJAQAAAA9nYW1lU3VtU2hhTGFiZWwAAAABBQAAAApnYW1lTnVtYmVyAQAAABNnYW1lUlNBUHVibGljU3RyaW5nAAAAAAkBAAAAEUBleHRyTmF0aXZlKDEwNTMpAAAAAgUAAAAEdGhpcwUAAAASZ2FtZVJTQVB1YmxpY0xhYmVsAQAAAA1nYW1lUlNBUHVibGljAAAAAAkAAlsAAAABAgAAANhNSUdmTUEwR0NTcUdTSWIzRFFFQkFRVUFBNEdOQURDQmlRS0JnUUQxRllSbkd4Kzk4UmJkVTVNMnFpd2pQWmU5T0o3OSs1cXEveEJ0dHpQVnJNRkhucVFtVHdzNk8ydFBhcHBha1gwOWhTTU1tWHA1NTgzRzgyVUZuc0NuUWU0MnRrYzNzdnVnY2QwUnYzeThhbHJMM3JXdElpV3gzY2l5RWhFZEdJdXd0UTgwMTA4aHFldldlS1BSdmdVeHpHbms0MjJyaStZaGFrck9IZ3JoNlFJREFRQUIBAAAAD2dhbWVUaWNrZXRQcmljZQAAAAAJAAQaAAAAAgUAAAAEdGhpcwUAAAAUZ2FtZVRpY2tldFByaWNlTGFiZWwBAAAAD2NoZWNrUGVybWlzc2lvbgAAAAEAAAAPY2FsbGVyUHVibGljS2V5CQEAAAACIT0AAAACBQAAAA9jYWxsZXJQdWJsaWNLZXkFAAAAE2dhbWVNYXN0ZXJQdWJsaWNLZXkBAAAADGdldEdhbWVUb2tlbgAAAAAEAAAAByRtYXRjaDAJAAQdAAAAAgUAAAAEdGhpcwUAAAAOZ2FtZVRva2VuTGFiZWwDCQAAAQAAAAIFAAAAByRtYXRjaDACAAAABlN0cmluZwQAAAAHdG9rZW5JZAUAAAAHJG1hdGNoMAMJAAAAAAAAAgUAAAAHdG9rZW5JZAIAAAAABQAAAAR1bml0CQACWQAAAAEFAAAAB3Rva2VuSWQFAAAABHVuaXQBAAAAEmdldEdhbWVUaWNrZXRQcmljZQAAAAAEAAAAByRtYXRjaDAJAQAAAA9nYW1lVGlja2V0UHJpY2UAAAAAAwkAAAEAAAACBQAAAAckbWF0Y2gwAgAAAANJbnQEAAAAC3RpY2tldFByaWNlBQAAAAckbWF0Y2gwBQAAAAt0aWNrZXRQcmljZQkAAAIAAAABAgAAADZHYW1lIGhhcyBub3QgYmVlbiBpbml0aWFsaXplZCwgdGlja2V0IHByaWNlIG5vdCBmb3VuZC4BAAAADmdldEN1cnJlbnRHYW1lAAAAAAQAAAAHJG1hdGNoMAkBAAAAD2dhbWVzR2V0Q291bnRlcgAAAAADCQAAAQAAAAIFAAAAByRtYXRjaDACAAAAA0ludAQAAAALY3VycmVudEdhbWUFAAAAByRtYXRjaDAFAAAAC2N1cnJlbnRHYW1lCQAAAgAAAAECAAAANUdhbWUgaGFzIG5vdCBiZWVuIGluaXRpYWxpemVkLCB0b3RhbCBnYW1lcyBub3QgZm91bmQuAQAAAAxnZXRHYW1lU3RhdGUAAAABAAAAC2N1cnJlbnRHYW1lBAAAAAckbWF0Y2gwCQEAAAAMZ2FtZUdldFN0YXRlAAAAAQUAAAALY3VycmVudEdhbWUDCQAAAQAAAAIFAAAAByRtYXRjaDACAAAAA0ludAQAAAAJZ2FtZVN0YXRlBQAAAAckbWF0Y2gwBQAAAAlnYW1lU3RhdGUJAAACAAAAAQIAAAAVR2FtZSBzdGF0ZSBub3QgZm91bmQuAQAAAAxnZXRUb3RhbEJldHMAAAABAAAAC2N1cnJlbnRHYW1lBAAAAAckbWF0Y2gwCQEAAAANZ2FtZVRvdGFsQmV0cwAAAAEFAAAAC2N1cnJlbnRHYW1lAwkAAAEAAAACBQAAAAckbWF0Y2gwAgAAAANJbnQEAAAACXRvdGFsQmV0cwUAAAAHJG1hdGNoMAUAAAAJdG90YWxCZXRzCQAAAgAAAAECAAAANEdhbWUgaGFzIG5vdCBiZWVuIGluaXRpYWxpemVkLCB0b3RhbCBiZXRzIG5vdCBmb3VuZC4BAAAAFWdldFRvdGFsUHJvY2Vzc2VkQmV0cwAAAAEAAAALY3VycmVudEdhbWUEAAAAByRtYXRjaDAJAQAAABFnYW1lUHJvY2Vzc2VkQmV0cwAAAAEFAAAAC2N1cnJlbnRHYW1lAwkAAAEAAAACBQAAAAckbWF0Y2gwAgAAAANJbnQEAAAAEnRvdGFsUHJvY2Vzc2VkQmV0cwUAAAAHJG1hdGNoMAUAAAASdG90YWxQcm9jZXNzZWRCZXRzCQAAAgAAAAECAAAAPkdhbWUgaGFzIG5vdCBiZWVuIGluaXRpYWxpemVkLCB0b3RhbCBwcm9jZXNzZWQgYmV0cyBub3QgZm91bmQuAQAAABFnZXRXaW5uZXJzQ291bnRlcgAAAAEAAAALY3VycmVudEdhbWUEAAAAByRtYXRjaDAJAQAAABJnYW1lV2lubmVyc0NvdW50ZXIAAAABBQAAAAtjdXJyZW50R2FtZQMJAAABAAAAAgUAAAAHJG1hdGNoMAIAAAADSW50BAAAAAx3aW5uZXJzQ291bnQFAAAAByRtYXRjaDAFAAAADHdpbm5lcnNDb3VudAkAAAIAAAABAgAAADdHYW1lIGhhcyBub3QgYmVlbiBpbml0aWFsaXplZCwgdG90YWwgd2lubmVycyBub3QgZm91bmQuAQAAABhnZXRUb3RhbFByb2Nlc3NlZFdpbm5lcnMAAAABAAAAC2N1cnJlbnRHYW1lBAAAAAckbWF0Y2gwCQEAAAAUZ2FtZVByb2Nlc3NlZFdpbm5lcnMAAAABBQAAAAtjdXJyZW50R2FtZQMJAAABAAAAAgUAAAAHJG1hdGNoMAIAAAADSW50BAAAABV0b3RhbFByb2Nlc3NlZFdpbm5lcnMFAAAAByRtYXRjaDAFAAAAFXRvdGFsUHJvY2Vzc2VkV2lubmVycwkAAAIAAAABAgAAAEFHYW1lIGhhcyBub3QgYmVlbiBpbml0aWFsaXplZCwgdG90YWwgcHJvY2Vzc2VkIHdpbm5lcnMgbm90IGZvdW5kLgEAAAATZ2V0R2FtZUNvbW11bml0eVBvdAAAAAAEAAAAByRtYXRjaDAJAQAAABBnYW1lQ29tbXVuaXR5UG90AAAAAAMJAAABAAAAAgUAAAAHJG1hdGNoMAIAAAADSW50BAAAAAxjb21tdW5pdHlQb3QFAAAAByRtYXRjaDAFAAAADGNvbW11bml0eVBvdAkAAAIAAAABAgAAADNHYW1lIGhhcyBub3QgYmVlbiBpbml0aWFsaXplZCwgcHJpemUgcG90IG5vdCBmb3VuZC4BAAAAD2dldEdhbWVQcml6ZVBvdAAAAAEAAAALY3VycmVudEdhbWUEAAAAByRtYXRjaDAJAQAAAAxnYW1lUHJpemVQb3QAAAABBQAAAAtjdXJyZW50R2FtZQMJAAABAAAAAgUAAAAHJG1hdGNoMAIAAAADSW50BAAAAAhwcml6ZVBvdAUAAAAHJG1hdGNoMAUAAAAIcHJpemVQb3QJAAACAAAAAQIAAAAzR2FtZSBoYXMgbm90IGJlZW4gaW5pdGlhbGl6ZWQsIHByaXplIHBvdCBub3QgZm91bmQuAAAACAAAAAFpAQAAAAhpbml0R2FtZQAAAAADCQEAAAAPY2hlY2tQZXJtaXNzaW9uAAAAAQgFAAAAAWkAAAAPY2FsbGVyUHVibGljS2V5CQAAAgAAAAECAAAAEmluaXRHYW1lX0ZPUkJCSURFTgQAAAAHJG1hdGNoMAkBAAAAD2dhbWVzR2V0Q291bnRlcgAAAAADCQAAAQAAAAIFAAAAByRtYXRjaDACAAAAA0ludAQAAAAMR0FNRVNDT1VOVEVSBQAAAAckbWF0Y2gwCQAAAgAAAAECAAAAGEdhbWUgYWxyZWFkeSBpbml0aWFsaXplZAkABEwAAAACCQEAAAAMSW50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TAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACCQEAAAAUZ2FtZVN0YXJ0SGVpZ2h0TGFiZWwAAAABBQAAAAtjdXJyZW50R2FtZQgFAAAACWxhc3RCbG9jawAAAAZoZWlnaHQJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAIFAAAAEGdhbWVDb3VudGVyTGFiZWwFAAAAB25ld0dhbWUJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAIJAQAAABFnYW1lUHJpemVQb3RMYWJlbAAAAAEFAAAAB25ld0dhbWUFAAAACHByaXplUG90CQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACCQEAAAAZZ2FtZVByaXplU2hhcmVBbW91bnRMYWJlbAAAAAEFAAAAB25ld0dhbWUAAAAAAAAAAAAJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAIJAQAAABJnYW1lVG90YWxCZXRzTGFiZWwAAAABBQAAAAduZXdHYW1lAAAAAAAAAAAACQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACCQEAAAAWZ2FtZVByb2Nlc3NlZEJldHNMYWJlbAAAAAEFAAAAB25ld0dhbWUAAAAAAAAAAAAJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAIJAQAAABdnYW1lV2lubmVyc0NvdW50ZXJMYWJlbAAAAAEFAAAAB25ld0dhbWUAAAAAAAAAAAAJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAIJAQAAABlnYW1lUHJvY2Vzc2VkV2lubmVyc0xhYmVsAAAAAQUAAAAHbmV3R2FtZQAAAAAAAAAAAAkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgkBAAAADmdhbWVTdGF0ZUxhYmVsAAAAAQUAAAAHbmV3R2FtZQAAAAAAAAAAAAkABEwAAAACCQEAAAALU3RyaW5nRW50cnkAAAACCQEAAAAPZ2FtZVN1bVNoYUxhYmVsAAAAAQUAAAAHbmV3R2FtZQkAAlgAAAABCQAB9wAAAAEJAAJbAAAAAQUAAAAKcmFuZG9tSGFzaAkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgkBAAAAFGdhbWVTdGFydEhlaWdodExhYmVsAAAAAQUAAAAHbmV3R2FtZQgFAAAACWxhc3RCbG9jawAAAAZoZWlnaHQJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAIJAQAAABJnYW1lRW5kSGVpZ2h0TGFiZWwAAAABBQAAAAduZXdHYW1lCQAAZAAAAAIFAAAABmhlaWdodAUAAAAMYmxvY2tJblJvdW5kBQAAAANuaWwEAAAACHByaXplUG90CQAAZQAAAAIFAAAAB2JhbGFuY2UFAAAAEmNvbW11bml0eVBvdEFtb3VudAkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgkBAAAAFGdhbWVTdGFydEhlaWdodExhYmVsAAAAAQUAAAALY3VycmVudEdhbWUIBQAAAAlsYXN0QmxvY2sAAAAGaGVpZ2h0CQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACBQAAABBnYW1lQ291bnRlckxhYmVsBQAAAAduZXdHYW1lCQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACCQEAAAARZ2FtZVByaXplUG90TGFiZWwAAAABBQAAAAduZXdHYW1lBQAAAAhwcml6ZVBvdAkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgkBAAAAGWdhbWVQcml6ZVNoYXJlQW1vdW50TGFiZWwAAAABBQAAAAduZXdHYW1lAAAAAAAAAAAACQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACCQEAAAASZ2FtZVRvdGFsQmV0c0xhYmVsAAAAAQUAAAAHbmV3R2FtZQAAAAAAAAAAAAkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgkBAAAAFmdhbWVQcm9jZXNzZWRCZXRzTGFiZWwAAAABBQAAAAduZXdHYW1lAAAAAAAAAAAACQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACCQEAAAAXZ2FtZVdpbm5lcnNDb3VudGVyTGFiZWwAAAABBQAAAAduZXdHYW1lAAAAAAAAAAAACQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACCQEAAAAZZ2FtZVByb2Nlc3NlZFdpbm5lcnNMYWJlbAAAAAEFAAAAB25ld0dhbWUAAAAAAAAAAAAJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAA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YXRlCQEAAAAMZ2V0R2FtZVN0YXRlAAAAAQUAAAALY3VycmVudEdhbWUDCQAAAAAAAAIFAAAACWdhbWVTdGF0ZQAAAAAAAAAAAAkAAAIAAAABAgAAAB9MYXN0IGdhbWUgaGFzIG5vdCBmaW5pc2hlZCB5ZXQuBAAAAAl0b3RhbEJldHMJAQAAAAxnZXRUb3RhbEJldHMAAAABBQAAAAtjdXJyZW50R2FtZQQAAAAQbGFzdFByb2Nlc3NlZEJldAkBAAAAFWdldFRvdGFsUHJvY2Vzc2VkQmV0cwAAAAEFAAAAC2N1cnJlbnRHYW1lBAAAAAduZXh0QmV0CQAAZAAAAAIFAAAAEGxhc3RQcm9jZXNzZWRCZXQAAAAAAAAAAAEDCQAAZgAAAAIFAAAAB25leHRCZXQFAAAACXRvdGFsQmV0cwkAAAIAAAABAgAAAB1OZXh0IGJldCBoYXMgbm90IGJlZW4gcGxhY2VkLgQAAAAMd2lubmVyc0NvdW50CQEAAAARZ2V0V2lubmVyc0NvdW50ZXIAAAABBQAAAAtjdXJyZW50R2FtZQQAAAAGcmVzdWx0CQEAAAANZ2FtZUdldFJlc3VsdAAAAAEFAAAAC2N1cnJlbnRHYW1lBAAAAAliZXREZXRhaWwJAAGRAAAAAgkABLUAAAACCQEAAAAKYmV0RGV0YWlscwAAAAIFAAAAC2N1cnJlbnRHYW1lBQAAAAduZXh0QmV0AgAAAAF8AAAAAAAAAAAABAAAAApiZXRBZGRyZXNzCQABkQAAAAIJAAS1AAAAAgkBAAAACmJldERldGFpbHMAAAACBQAAAAtjdXJyZW50R2FtZQUAAAAHbmV4dEJldAIAAAABfAAAAAAAAAAAAQMJAAAAAAAAAgUAAAAJYmV0RGV0YWlsBQAAAAZyZXN1bHQEAAAAD25ld1dpbm5lcnNDb3VudAkAAGQAAAACBQAAAAx3aW5uZXJzQ291bnQAAAAAAAAAAAEJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAIJAQAAABZnYW1lUHJvY2Vzc2VkQmV0c0xhYmVsAAAAAQUAAAALY3VycmVudEdhbWUFAAAAB25leHRCZXQJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAIJAQAAABdnYW1lV2lubmVyc0NvdW50ZXJMYWJlbAAAAAEFAAAAC2N1cnJlbnRHYW1lBQAAAA9uZXdXaW5uZXJzQ291bnQJAARMAAAAAgkBAAAAC1N0cmluZ0VudHJ5AAAAAgkBAAAAEndpbm5lckRldGFpbHNMYWJlbAAAAAIFAAAAC2N1cnJlbnRHYW1lBQAAAA9uZXdXaW5uZXJzQ291bnQFAAAACmJldEFkZHJlc3MFAAAAA25pbAkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgkBAAAAFmdhbWVQcm9jZXNzZWRCZXRzTGFiZWwAAAABBQAAAAtjdXJyZW50R2FtZQUAAAAHbmV4dEJldAUAAAADbmlsAAAAAWkBAAAADmNhbGN1bGF0ZVByaXplAAAAAAMJAQAAAA9jaGVja1Blcm1pc3Npb24AAAABCAUAAAABaQAAAA9jYWxsZXJQdWJsaWNLZXkJAAACAAAAAQIAAAATc3RhcnRHYW1lX0ZPUkJCSURFTgQAAAALY3VycmVudEdhbWUJAQAAAA5nZXRDdXJyZW50R2FtZQAAAAAEAAAACWdhbWVTdGF0ZQkBAAAADGdldEdhbWVTdGF0ZQAAAAEFAAAAC2N1cnJlbnRHYW1lAwkAAAAAAAACBQAAAAlnYW1lU3RhdGUAAAAAAAAAAAAJAAACAAAAAQIAAAAfTGFzdCBnYW1lIGhhcyBub3QgZmluaXNoZWQgeWV0LgQAAAAJdG90YWxCZXRzCQEAAAAMZ2V0VG90YWxCZXRzAAAAAQUAAAALY3VycmVudEdhbWUEAAAAEGxhc3RQcm9jZXNzZWRCZXQJAQAAABVnZXRUb3RhbFByb2Nlc3NlZEJldHMAAAABBQAAAAtjdXJyZW50R2FtZQMJAAAAAAAAAgUAAAAJdG90YWxCZXRzBQAAABBsYXN0UHJvY2Vzc2VkQmV0BAAAAAx3aW5uZXJzQ291bnQJAQAAABFnZXRXaW5uZXJzQ291bnRlcgAAAAEFAAAAC2N1cnJlbnRHYW1lAwkAAAAAAAACBQAAAAx3aW5uZXJzQ291bnQAAAAAAAAAAAAJAAACAAAAAQIAAAAgVGhlcmUgYXJlIG5vIHdpbm5lcnMgdGhpcyByb3VuZC4EAAAAByRtYXRjaDAJAQAAAAxnYW1lUHJpemVQb3QAAAABBQAAAAtjdXJyZW50R2FtZQMJAAABAAAAAgUAAAAHJG1hdGNoMAIAAAADSW50BAAAAA5wcml6ZVBvdEFtb3VudAUAAAAHJG1hdGNoMAQAAAAQcHJpemVTaGFyZUFtb3VudAkAAGkAAAACBQAAAA5wcml6ZVBvdEFtb3VudAUAAAAMd2lubmVyc0NvdW50CQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACCQEAAAAZZ2FtZVByaXplU2hhcmVBbW91bnRMYWJlbAAAAAEFAAAAC2N1cnJlbnRHYW1lBQAAABBwcml6ZVNoYXJlQW1vdW50BQAAAANuaWwJAAACAAAAAQIAAAA6R2FtZSBoYXMgbm90IGJlZW4gaW5pdGlhbGl6ZWQsIFByaXplIFBvdCBBbW91bnQgbm90IGZvdW5kLgkAAAIAAAABAgAAAEtUaGVyZSBhcmUgc3RpbGwgYmV0cyB0aGF0IG5lZWQgdG8gYmUgcHJvY2Vzc2VkLiBDYW5ub3QgY2FsY3VsYXRlIHByaXplIHlldC4AAAABaQEAAAARcHJvY2Vzc05leHRXaW5uZXIAAAAAAwkBAAAAD2NoZWNrUGVybWlzc2lvbgAAAAEIBQAAAAFpAAAAD2NhbGxlclB1YmxpY0tleQkAAAIAAAABAgAAABNzdGFydEdhbWVfRk9SQkJJREVOBAAAAAtjdXJyZW50R2FtZQkBAAAADmdldEN1cnJlbnRHYW1lAAAAAAQAAAAJZ2FtZVN0YXRlCQEAAAAMZ2V0R2FtZVN0YXRlAAAAAQUAAAALY3VycmVudEdhbWUDCQAAAAAAAAIFAAAACWdhbWVTdGF0ZQAAAAAAAAAAAAkAAAIAAAABAgAAAB9MYXN0IGdhbWUgaGFzIG5vdCBmaW5pc2hlZCB5ZXQuBAAAAAx0b3RhbFdpbm5lcnMJAQAAABFnZXRXaW5uZXJzQ291bnRlcgAAAAEFAAAAC2N1cnJlbnRHYW1lAwkAAAAAAAACBQAAAAx0b3RhbFdpbm5lcnMAAAAAAAAAAAAJAAACAAAAAQIAAAAgVGhlcmUgYXJlIG5vIHdpbm5lcnMgdGhpcyByb3VuZC4EAAAAE2xhc3RQcm9jZXNzZWRXaW5uZXIJAQAAABhnZXRUb3RhbFByb2Nlc3NlZFdpbm5lcnMAAAABBQAAAAtjdXJyZW50R2FtZQQAAAAKbmV4dFdpbm5lcgkAAGQAAAACBQAAABNsYXN0UHJvY2Vzc2VkV2lubmVyAAAAAAAAAAABAwkAAGYAAAACBQAAAApuZXh0V2lubmVyBQAAAAx0b3RhbFdpbm5lcnMJAAACAAAAAQIAAAAgTm8gbW9yZSB3aW5uZXJzIHRvIGJlIHByb2Nlc3NlZC4EAAAAByRtYXRjaDAJAQAAABRnYW1lUHJpemVTaGFyZUFtb3VudAAAAAEFAAAAC2N1cnJlbnRHYW1lAwkAAAEAAAACBQAAAAckbWF0Y2gwAgAAAANJbnQEAAAAEHByaXplU2hhcmVBbW91bnQFAAAAByRtYXRjaDADCQAAAAAAAAIFAAAAEHByaXplU2hhcmVBbW91bnQAAAAAAAAAAAAJAAACAAAAAQIAAAAvUHJpemUgc2hhcmUgYW1vdW50IGhhcyBub3QgYmVlbiBjYWxjdWxhdGVkIHlldC4EAAAACWJldFBsYWNlcgkBAAAADXdpbm5lckRldGFpbHMAAAACBQAAAAtjdXJyZW50R2FtZQUAAAAKbmV4dFdpbm5lcgQAAAAHYWRkcmVzcwkBAAAABXZhbHVlAAAAAQkABCYAAAABBQAAAAliZXRQbGFjZXIJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAIJAQAAABlnYW1lUHJvY2Vzc2VkV2lubmVyc0xhYmVsAAAAAQUAAAALY3VycmVudEdhbWUFAAAACm5leHRXaW5uZXIJAARMAAAAAgkBAAAADlNjcmlwdFRyYW5zZmVyAAAAAwUAAAAHYWRkcmVzcwUAAAAQcHJpemVTaGFyZUFtb3VudAkBAAAADGdldEdhbWVUb2tlbgAAAAAFAAAAA25pbAkAAAIAAAABAgAAAC9Qcml6ZSBzaGFyZSBhbW91bnQgaGFzIG5vdCBiZWVuIGNhbGN1bGF0ZWQgeWV0LgAAAAFpAQAAAAxzZXRQYXJhbWV0ZXIAAAACAAAADXBhcmFtZXRlck5hbWUAAAAOcGFyYW1ldGVyVmFsdWUDCQEAAAAPY2hlY2tQZXJtaXNzaW9uAAAAAQgFAAAAAWkAAAAPY2FsbGVyUHVibGljS2V5CQAAAgAAAAECAAAAFnNldFBhcmFtZXRlcl9GT1JCQklERU4DCQAAAAAAAAIFAAAADXBhcmFtZXRlck5hbWUCAAAAEWNoYW5nZVRpY2tldFByaWNlBAAAABB0aWNrZXRQcmljZVZhbHVlCQEAAAALdmFsdWVPckVsc2UAAAACCQEAAAANcGFyc2VJbnRWYWx1ZQAAAAEFAAAADnBhcmFtZXRlclZhbHVlAAAAAAAAAAAAAwkAAGYAAAACAAAAAAAAAAAABQAAABB0aWNrZXRQcmljZVZhbHVlCQAAAgAAAAECAAAAHHZhbHVlIGNhbm5vdCBiZSBsb3dlciB0aGFuIDAJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAIFAAAAFGdhbWVUaWNrZXRQcmljZUxhYmVsBQAAABB0aWNrZXRQcmljZVZhbHVlBQAAAANuaWwDCQAAAAAAAAIFAAAADXBhcmFtZXRlck5hbWUCAAAACWNoYW5nZVJTQQQAAAAHJG1hdGNoMAkBAAAAD2dhbWVzR2V0Q291bnRlcgAAAAADCQAAAQAAAAIFAAAAByRtYXRjaDACAAAAA0ludAQAAAAMR0FNRVNDT1VOVEVSBQAAAAckbWF0Y2gwBAAAAAckbWF0Y2gxCQEAAAAMZ2FtZUdldFN0YXRlAAAAAQUAAAAMR0FNRVNDT1VOVEVSAwkAAAEAAAACBQAAAAckbWF0Y2gxAgAAAANJbnQEAAAABXN0YXRlBQAAAAckbWF0Y2gxAwkBAAAAAiE9AAAAAgUAAAAFc3RhdGUAAAAAAAAAAAEJAAACAAAAAQIAAAAYR2FtZSBoYXMgdG8gYmUgZmluaXNoZWQuCQAETAAAAAIJAQAAAAtTdHJpbmdFbnRyeQAAAAIFAAAAEmdhbWVSU0FQdWJsaWNMYWJlbAUAAAAOcGFyYW1ldGVyVmFsdWUFAAAAA25pbAkABEwAAAACCQEAAAALU3RyaW5nRW50cnkAAAACBQAAABJnYW1lUlNBUHVibGljTGFiZWwFAAAADnBhcmFtZXRlclZhbHVlBQAAAANuaWwJAAACAAAAAQIAAAAdR2FtZSBuZWVkcyB0byBiZSBpbml0aWFsaXplZC4DCQAAAAAAAAIFAAAADXBhcmFtZXRlck5hbWUCAAAAD2NoYW5nZUVuZEhlaWdodAQAAAAHJG1hdGNoMAkBAAAAD2dhbWVzR2V0Q291bnRlcgAAAAADCQAAAQAAAAIFAAAAByRtYXRjaDACAAAAA0ludAQAAAAMR0FNRVNDT1VOVEVSBQAAAAckbWF0Y2gwBAAAAA5lbmRIZWlnaHRWYWx1ZQkBAAAAC3ZhbHVlT3JFbHNlAAAAAgkBAAAADXBhcnNlSW50VmFsdWUAAAABBQAAAA5wYXJhbWV0ZXJWYWx1ZQAAAAAAAAAAAAMJAABmAAAAAgAAAAAAAAAAAAUAAAAOZW5kSGVpZ2h0VmFsdWUJAAACAAAAAQIAAAAcdmFsdWUgY2Fubm90IGJlIGxvd2VyIHRoYW4gMAkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgkBAAAAEmdhbWVFbmRIZWlnaHRMYWJlbAAAAAEFAAAADEdBTUVTQ09VTlRFUgUAAAAOZW5kSGVpZ2h0VmFsdWUFAAAAA25pbAkAAAIAAAABAgAAAB1HYW1lIG5lZWRzIHRvIGJlIGluaXRpYWxpemVkLgkAAAIAAAABAgAAADhTZXR0aW5nIG5vdCBmb3VuZC4gQWxsb3dlZDogY2hhbmdlVGlja2V0UHJpY2UsIGNoYW5nZVJTQQAAAADhe2X/", "height": 2246772, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: 7da6B6VMRwNn1VK5wdiir1PRmhtaiQkqzLYgEcNHB9uX Next: none Diff:
OldNewDifferences
11 {-# STDLIB_VERSION 4 #-}
22 {-# SCRIPT_TYPE ACCOUNT #-}
33 {-# CONTENT_TYPE DAPP #-}
4+let gameMasterPublicKey = fromBase58String("9ceJkKDVYrbcjYuGSps3NaAePtQPjBcyEg3LGkapXiyX")
5+
46 let gameTokenLabel = "G_TOKENID"
57
68 let gameBalanceLabel = "G_BALANCE"
1012 func gamePrizePotLabel (gameNumber) = (("G_" + toString(gameNumber)) + "_PRIZEPOT")
1113
1214
13-func gamePrizeShareAmountLabel (gameNumber) = (("G_" + toString(gameNumber)) + "P_RIZESHAREAMOUNT")
15+func gamePrizeShareAmountLabel (gameNumber) = (("G_" + toString(gameNumber)) + "_PRIZESHAREAMOUNT")
1416
1517
1618 let gameCounterLabel = "G_GAMESCOUNTER"
3032 func gameResultLabel (gameNumber) = (("G_" + toString(gameNumber)) + "_RESULT")
3133
3234
33-func betDetailsLabel (betNumber) = (("B_" + toString(betNumber)) + "_BETDETAILS")
35+func betDetailsLabel (gameNumber,betNumber) = (((("G_" + toString(gameNumber)) + "_B_") + toString(betNumber)) + "_BETDETAILS")
3436
3537
36-func winnerDetailsLabel (winnerNumber) = (("W_" + toString(winnerNumber)) + "_WINNERDETAILS")
38+func winnerDetailsLabel (gameNumber,winnerNumber) = (((("G_" + toString(gameNumber)) + "_W_") + toString(winnerNumber)) + "_WINNERDETAILS")
3739
3840
3941 func gameStateLabel (gameNumber) = (("G_" + toString(gameNumber)) + "_STATE")
4042
43+
44+func gameRandomHashLabel (gameNumber) = (("G_" + toString(gameNumber)) + "_RANDOMHASH")
45+
46+
47+func gameSumShaLabel (gameNumber) = (("G_" + toString(gameNumber)) + "_SUMSHA")
48+
49+
50+let gameRSAPublicLabel = "G_RSAPUBLIC"
51+
52+func gameStartHeightLabel (gameNumber) = (("G_" + toString(gameNumber)) + "_STARTHEIGHT")
53+
54+
55+func gameEndHeightLabel (gameNumber) = (("G_" + toString(gameNumber)) + "_ENDHEIGHT")
56+
57+
58+let gameTicketPriceLabel = "G_TICKETPRICE"
4159
4260 func gameBalance () = getInteger(this, gameBalanceLabel)
4361
6987 func gameGetResult (gameNumber) = getStringValue(this, gameResultLabel(gameNumber))
7088
7189
72-func betDetails (betNumber) = getStringValue(this, betDetailsLabel(betNumber))
90+func betDetails (gameNumber,betNumber) = getStringValue(this, betDetailsLabel(gameNumber, betNumber))
7391
7492
75-func winnerDetails (winnerNumber) = getStringValue(this, winnerDetailsLabel(winnerNumber))
93+func winnerDetails (gameNumber,winnerNumber) = getStringValue(this, winnerDetailsLabel(gameNumber, winnerNumber))
7694
7795
7896 func gameGetState (gameNumber) = getInteger(this, gameStateLabel(gameNumber))
7997
8098
81-func gameToken () = match getString(this, gameTokenLabel) {
99+func gameGetSumSha (gameNumber) = getString(this, gameSumShaLabel(gameNumber))
100+
101+
102+func gameRSAPublicString () = getStringValue(this, gameRSAPublicLabel)
103+
104+
105+func gameRSAPublic () = fromBase64String("MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQD1FYRnGx+98RbdU5M2qiwjPZe9OJ79+5qq/xBttzPVrMFHnqQmTws6O2tPappakX09hSMMmXp5583G82UFnsCnQe42tkc3svugcd0Rv3y8alrL3rWtIiWx3ciyEhEdGIuwtQ80108hqevWeKPRvgUxzGnk422ri+YhakrOHgrh6QIDAQAB")
106+
107+
108+func gameTicketPrice () = getInteger(this, gameTicketPriceLabel)
109+
110+
111+func checkPermission (callerPublicKey) = (callerPublicKey != gameMasterPublicKey)
112+
113+
114+func getGameToken () = match getString(this, gameTokenLabel) {
82115 case tokenId: String =>
83116 if ((tokenId == ""))
84117 then unit
88121 }
89122
90123
91-@Callable(i)
92-func initGame () = [IntegerEntry(gameBalanceLabel, 0), IntegerEntry(gameCommunityPotLabel, 0), IntegerEntry(gameCounterLabel, 0), IntegerEntry(gameStateLabel(0), 1), IntegerEntry(gameWinnersCounterLabel(0), 0), IntegerEntry(gameProcessedWinnersLabel(0), 0), IntegerEntry(gameTotalBetsLabel(0), 0), IntegerEntry(gameProcessedBetsLabel(0), 0)]
124+func getGameTicketPrice () = match gameTicketPrice() {
125+ case ticketPrice: Int =>
126+ ticketPrice
127+ case _ =>
128+ throw("Game has not been initialized, ticket price not found.")
129+}
93130
94131
95-
96-@Callable(i)
97-func startGame () = match gamesGetCounter() {
132+func getCurrentGame () = match gamesGetCounter() {
98133 case currentGame: Int =>
99- match gameGetState(currentGame) {
100- case gameState: Int =>
101- if ((gameState == 0))
102- then throw("Last game has not finished yet.")
103- else match gameTotalBets(currentGame) {
104- case totalBets: Int =>
105- match gameProcessedBets(currentGame) {
106- case totalProcessedBets: Int =>
107- if ((totalBets == totalProcessedBets))
108- then match gameWinnersCounter(currentGame) {
109- case totalWinners: Int =>
110- match gameProcessedWinners(currentGame) {
111- case lastProcessedWinner: Int =>
112- if ((totalWinners == lastProcessedWinner))
113- then {
114- let newGame = (currentGame + 1)
115-[IntegerEntry(gameCounterLabel, newGame), IntegerEntry(gamePrizePotLabel(newGame), 100000000), IntegerEntry(gamePrizeShareAmountLabel(newGame), 0), IntegerEntry(gameTotalBetsLabel(newGame), 0), IntegerEntry(gameProcessedBetsLabel(newGame), 0), IntegerEntry(gameWinnersCounterLabel(newGame), 0), IntegerEntry(gameProcessedWinnersLabel(newGame), 0), IntegerEntry(gameStateLabel(newGame), 0)]
116- }
117- else throw("All winners have not been processed yet. Cannot start new game.")
118- case _ =>
119- throw("Game has not been initialized, total processed winners not found.")
120- }
121- case _ =>
122- throw("Game has not been initialized, total winners not found.")
123- }
124- else throw("All bets have not been processed yet. Cannot start new game.")
125- case _ =>
126- throw("Game has not been initialized, total processed bets not found.")
127- }
128- case _ =>
129- throw("Game has not been initialized, total bets not found.")
130- }
131- case _ =>
132- throw("Game state not found.")
133- }
134+ currentGame
134135 case _ =>
135136 throw("Game has not been initialized, total games not found.")
136137 }
137138
138139
140+func getGameState (currentGame) = match gameGetState(currentGame) {
141+ case gameState: Int =>
142+ gameState
143+ case _ =>
144+ throw("Game state not found.")
145+}
146+
147+
148+func getTotalBets (currentGame) = match gameTotalBets(currentGame) {
149+ case totalBets: Int =>
150+ totalBets
151+ case _ =>
152+ throw("Game has not been initialized, total bets not found.")
153+}
154+
155+
156+func getTotalProcessedBets (currentGame) = match gameProcessedBets(currentGame) {
157+ case totalProcessedBets: Int =>
158+ totalProcessedBets
159+ case _ =>
160+ throw("Game has not been initialized, total processed bets not found.")
161+}
162+
163+
164+func getWinnersCounter (currentGame) = match gameWinnersCounter(currentGame) {
165+ case winnersCount: Int =>
166+ winnersCount
167+ case _ =>
168+ throw("Game has not been initialized, total winners not found.")
169+}
170+
171+
172+func getTotalProcessedWinners (currentGame) = match gameProcessedWinners(currentGame) {
173+ case totalProcessedWinners: Int =>
174+ totalProcessedWinners
175+ case _ =>
176+ throw("Game has not been initialized, total processed winners not found.")
177+}
178+
179+
180+func getGameCommunityPot () = match gameCommunityPot() {
181+ case communityPot: Int =>
182+ communityPot
183+ case _ =>
184+ throw("Game has not been initialized, prize pot not found.")
185+}
186+
187+
188+func getGamePrizePot (currentGame) = match gamePrizePot(currentGame) {
189+ case prizePot: Int =>
190+ prizePot
191+ case _ =>
192+ throw("Game has not been initialized, prize pot not found.")
193+}
194+
139195
140196 @Callable(i)
141-func placeBet (guessValue) = match gamesGetCounter() {
142- case currentGame: Int =>
143- match gameGetState(currentGame) {
144- case gameState: Int =>
145- if ((gameState == 1))
146- then throw("Game is finished and next game has not started.")
147- else match gameTotalBets(currentGame) {
148- case totalBets: Int =>
149- let newBet = (totalBets + 1)
150- let bet = guessValue
151-[IntegerEntry(gameTotalBetsLabel(currentGame), newBet), StringEntry(betDetailsLabel(newBet), ((("G" + toString(currentGame)) + "-") + bet))]
152- case _ =>
153- throw("Game has not been initialized, total bets not found.")
154- }
155- case _ =>
156- throw("Game state not found.")
157- }
158- case _ =>
159- throw("Game has not been initialized, total games not found.")
160-}
197+func initGame () = if (checkPermission(i.callerPublicKey))
198+ then throw("initGame_FORBBIDEN")
199+ else match gamesGetCounter() {
200+ case GAMESCOUNTER: Int =>
201+ throw("Game already initialized")
202+ case _ =>
203+[IntegerEntry(gameBalanceLabel, 0), IntegerEntry(gameCommunityPotLabel, 0), IntegerEntry(gameCounterLabel, 0), IntegerEntry(gameStateLabel(0), 1), IntegerEntry(gameWinnersCounterLabel(0), 0), IntegerEntry(gameProcessedWinnersLabel(0), 0), IntegerEntry(gameTotalBetsLabel(0), 0), IntegerEntry(gameProcessedBetsLabel(0), 0), StringEntry(gameTokenLabel, ""), IntegerEntry(gameTicketPriceLabel, 1000000)]
204+ }
161205
162206
163207
164208 @Callable(i)
165-func endGame () = match gamesGetCounter() {
166- case currentGame: Int =>
167- match gameGetState(currentGame) {
168- case gameState: Int =>
169- if ((gameState == 1))
170- then throw("Game is finished and next game has not started.")
171- else [StringEntry(gameResultLabel(currentGame), ((("G" + toString(currentGame)) + "-") + "1,2,3")), IntegerEntry(gameStateLabel(currentGame), 1)]
172- case _ =>
173- throw("Game state not found.")
209+func startGame (randomHash,blockInRound) = if (checkPermission(i.callerPublicKey))
210+ then throw("startGame_FORBBIDEN")
211+ else {
212+ let currentGame = getCurrentGame()
213+ let gameState = getGameState(currentGame)
214+ if ((gameState == 0))
215+ then throw("Last game has not finished yet.")
216+ else {
217+ let totalBets = getTotalBets(currentGame)
218+ let totalProcessedBets = getTotalProcessedBets(currentGame)
219+ if ((totalBets == totalProcessedBets))
220+ then {
221+ let totalWinners = getWinnersCounter(currentGame)
222+ let lastProcessedWinner = getTotalProcessedWinners(currentGame)
223+ if ((totalWinners == lastProcessedWinner))
224+ then {
225+ let newGame = (currentGame + 1)
226+ match gameCommunityPot() {
227+ case communityPotAmount: Int =>
228+ let balance = 10000000
229+ let generator = (toInt(sha256(take(i.transactionId, 16))) % 17729)
230+ let randomNumber = ((toInt(toBytes(pow(generator, 0, 2, 0, 0, UP))) + currentGame) % 100)
231+ if ((randomNumber == 50))
232+ then {
233+ let prizePot = balance
234+[IntegerEntry(gameStartHeightLabel(currentGame), lastBlock.height), IntegerEntry(gameCounterLabel, newGame), IntegerEntry(gamePrizePotLabel(newGame), prizePot), IntegerEntry(gamePrizeShareAmountLabel(newGame), 0), IntegerEntry(gameTotalBetsLabel(newGame), 0), IntegerEntry(gameProcessedBetsLabel(newGame), 0), IntegerEntry(gameWinnersCounterLabel(newGame), 0), IntegerEntry(gameProcessedWinnersLabel(newGame), 0), IntegerEntry(gameStateLabel(newGame), 0), StringEntry(gameSumShaLabel(newGame), toBase58String(sha256(fromBase64String(randomHash)))), IntegerEntry(gameStartHeightLabel(newGame), lastBlock.height), IntegerEntry(gameEndHeightLabel(newGame), (height + blockInRound))]
235+ }
236+ else {
237+ let prizePot = (balance - communityPotAmount)
238+[IntegerEntry(gameStartHeightLabel(currentGame), lastBlock.height), IntegerEntry(gameCounterLabel, newGame), IntegerEntry(gamePrizePotLabel(newGame), prizePot), IntegerEntry(gamePrizeShareAmountLabel(newGame), 0), IntegerEntry(gameTotalBetsLabel(newGame), 0), IntegerEntry(gameProcessedBetsLabel(newGame), 0), IntegerEntry(gameWinnersCounterLabel(newGame), 0), IntegerEntry(gameProcessedWinnersLabel(newGame), 0), IntegerEntry(gameStateLabel(newGame), 0), StringEntry(gameSumShaLabel(newGame), toBase58String(sha256(fromBase64String(randomHash)))), IntegerEntry(gameStartHeightLabel(newGame), lastBlock.height), IntegerEntry(gameEndHeightLabel(newGame), (height + blockInRound))]
239+ }
240+ case _ =>
241+ throw("Game has not been initialized, total community pot not found.")
242+ }
243+ }
244+ else throw("All winners have not been processed yet. Cannot start new game.")
245+ }
246+ else throw("All bets have not been processed yet. Cannot start new game.")
247+ }
174248 }
175- case _ =>
176- throw("Game has not been initialized, total games not found.")
177-}
178249
179250
180251
181252 @Callable(i)
182-func processNextBet () = match gamesGetCounter() {
183- case currentGame: Int =>
184- match gameGetState(currentGame) {
185- case gameState: Int =>
186- if ((gameState == 0))
187- then throw("Last game has not finished yet.")
188- else match gameTotalBets(currentGame) {
189- case totalBets: Int =>
190- match gameProcessedBets(currentGame) {
191- case lastProcessedBet: Int =>
192- let nextBet = (lastProcessedBet + 1)
193- if ((nextBet > totalBets))
194- then throw("Next bet has not been placed.")
195- else match gamesGetCounter() {
196- case gameNumber: Int =>
197- match gameWinnersCounter(currentGame) {
198- case winnersCount: Int =>
199- let result = gameGetResult(gameNumber)
200- let betDetail = betDetails(nextBet)
201- if ((betDetail == result))
202- then {
203- let newWinnersCount = (winnersCount + 1)
204-[IntegerEntry(gameProcessedBetsLabel(currentGame), nextBet), IntegerEntry(gameWinnersCounterLabel(currentGame), newWinnersCount), StringEntry(winnerDetailsLabel(newWinnersCount), toBase58String(i.caller.bytes))]
205- }
206- else [IntegerEntry(gameProcessedBetsLabel(currentGame), nextBet)]
207- case _ =>
208- throw("Game has not been initialized, total winners not found.")
209- }
210- case _ =>
211- throw("Game has not been initialized, total games not found.")
212- }
213- case _ =>
214- throw("Game has not been initialized, total processed bets not found.")
215- }
216- case _ =>
217- throw("Game has not been initialized, total bets not found.")
218- }
219- case _ =>
220- throw("Game state not found.")
221- }
222- case _ =>
223- throw("Game has not been initialized, total games not found.")
224-}
253+func placeBet (guessValue) = {
254+ let currentGame = getCurrentGame()
255+ let gameState = getGameState(currentGame)
256+ if ((gameState == 1))
257+ then throw("Game is finished and next game has not started.")
258+ else if ((size(i.payments) != 1))
259+ then throw("Payment not attached or there is more then 1 payment attached.")
260+ else {
261+ let ticketPrice = getGameTicketPrice()
262+ if ((i.payments[0].amount != ticketPrice))
263+ then throw("Incorrect payment amount.")
264+ else {
265+ let totalBets = getTotalBets(currentGame)
266+ let newBet = (totalBets + 1)
267+ let bet = guessValue
268+ let prizePot = getGamePrizePot(currentGame)
269+ let communityPot = getGameCommunityPot()
270+[IntegerEntry(gameCounterLabel, currentGame), IntegerEntry(gameTotalBetsLabel(currentGame), newBet), StringEntry(betDetailsLabel(currentGame, newBet), ((((("G" + toString(currentGame)) + "-") + bet) + "|") + toBase58String(i.caller.bytes))), IntegerEntry(gamePrizePotLabel(currentGame), (prizePot + ((ticketPrice * 9) / 10))), IntegerEntry(gameCommunityPotLabel, (communityPot + ((ticketPrice * 1) / 10)))]
271+ }
272+ }
273+ }
225274
226275
227276
228277 @Callable(i)
229-func calculatePrize () = match gamesGetCounter() {
230- case currentGame: Int =>
231- match gameGetState(currentGame) {
232- case gameState: Int =>
233- if ((gameState == 0))
234- then throw("Last game has not finished yet.")
235- else match gameTotalBets(currentGame) {
236- case totalBets: Int =>
237- match gameProcessedBets(currentGame) {
238- case lastProcessedBet: Int =>
239- if ((totalBets == lastProcessedBet))
240- then match gameWinnersCounter(currentGame) {
241- case winnersCount: Int =>
242- if ((winnersCount == 0))
243- then throw("There are no winners this round.")
244- else match gamePrizePot(currentGame) {
245- case prizePotAmount: Int =>
246- let prizeShareAmount = (prizePotAmount / winnersCount)
247-[IntegerEntry(gamePrizeShareAmountLabel(currentGame), prizeShareAmount)]
248- case _ =>
249- throw("Game has not been initialized, total games not found.")
250- }
251- case _ =>
252- throw("Game has not been initialized, total winners not found.")
253- }
254- else throw("There are still bets that need to be processed. Cannot calculate prize yet.")
255- case _ =>
256- throw("Game has not been initialized, total processed bets not found.")
278+func endGame (rsaSign) = if (checkPermission(i.callerPublicKey))
279+ then throw("startGame_FORBBIDEN")
280+ else {
281+ let currentGame = getCurrentGame()
282+ let gameState = getGameState(currentGame)
283+ if ((gameState == 1))
284+ then throw("Game is finished and next game has not started.")
285+ else match gameGetSumSha(currentGame) {
286+ case SUMSHA: String =>
287+ let sig = fromBase64String(rsaSign)
288+ let rsaSigValid = rsaVerify(SHA256, fromBase58String(SUMSHA), sig, gameRSAPublic())
289+ if (!(rsaSigValid))
290+ then throw((("INVALID_RSA_SIGN " + "on game ") + toString(currentGame)))
291+ else {
292+ let generator = (toInt(sha256((take(sig, 16) + take(i.transactionId, 16)))) % 17729)
293+ let generatedResult1 = ((toInt(toBytes(pow(generator, 0, 2, 0, 0, UP))) + currentGame) % 26)
294+ let generatedResult2 = ((toInt(toBytes(pow(generator, 0, 3, 0, 0, UP))) + currentGame) % 26)
295+ let generatedResult3 = ((toInt(toBytes(pow(generator, 0, 4, 0, 0, UP))) + currentGame) % 26)
296+ if (if (if ((generatedResult1 == generatedResult2))
297+ then true
298+ else (generatedResult1 == generatedResult3))
299+ then true
300+ else (generatedResult2 == generatedResult3))
301+ then throw("Collision detected between randomly generated results.")
302+ else {
303+ let resultsList = [generatedResult1, generatedResult2, generatedResult3]
304+ let orderedResult1 = min(resultsList)
305+ let indexResult1 = indexOf(resultsList, orderedResult1)
306+ let resultsList1 = removeByIndex(resultsList, valueOrElse(indexResult1, 0))
307+ let orderedResult2 = min(resultsList1)
308+ let indexResult2 = indexOf(resultsList1, orderedResult2)
309+ let resultsList2 = removeByIndex(resultsList1, valueOrElse(indexResult2, 0))
310+ let orderedResult3 = resultsList2[0]
311+[StringEntry(gameResultLabel(currentGame), ((((((("G" + toString(currentGame)) + "-") + toString(orderedResult1)) + ",") + toString(orderedResult2)) + ",") + toString(orderedResult3))), IntegerEntry(gameStateLabel(currentGame), 1), IntegerEntry(gameCounterLabel, currentGame)]
312+ }
257313 }
258- case _ =>
259- throw("Game has not been initialized, total bets not found.")
260- }
261- case _ =>
262- throw("Game state not found.")
314+ case _ =>
315+ throw("SHA does not exist")
316+ }
263317 }
264- case _ =>
265- throw("Game has not been initialized, total games not found")
266-}
267318
268319
269320
270321 @Callable(i)
271-func processNextWinner () = match gamesGetCounter() {
272- case currentGame: Int =>
273- match gameGetState(currentGame) {
274- case gameState: Int =>
275- if ((gameState == 0))
276- then throw("Last game has not finished yet.")
277- else match gamePrizeShareAmount(currentGame) {
278- case prizeShareAmount: Int =>
279- if ((prizeShareAmount == 0))
280- then throw("Prize share amount has not been calculated yet.")
281- else match gameWinnersCounter(currentGame) {
282- case totalWinners: Int =>
283- if ((totalWinners == 0))
284- then throw("There are no winners this round.")
285- else match gameProcessedWinners(currentGame) {
286- case lastProcessedWinner: Int =>
287- let nextWinner = (lastProcessedWinner + 1)
288- if ((nextWinner > totalWinners))
289- then throw("No more winners to be processed.")
290- else {
291- let betPlacer = winnerDetails(nextWinner)
292- let address = value(addressFromString(betPlacer))
293-[ScriptTransfer(address, prizeShareAmount, gameToken()), IntegerEntry(gameProcessedWinnersLabel(currentGame), nextWinner)]
294- }
295- case _ =>
296- throw("Game has not been initialized, total processed winners not found.")
322+func processNextBet () = if (checkPermission(i.callerPublicKey))
323+ then throw("startGame_FORBBIDEN")
324+ else {
325+ let currentGame = getCurrentGame()
326+ let gameState = getGameState(currentGame)
327+ if ((gameState == 0))
328+ then throw("Last game has not finished yet.")
329+ else {
330+ let totalBets = getTotalBets(currentGame)
331+ let lastProcessedBet = getTotalProcessedBets(currentGame)
332+ let nextBet = (lastProcessedBet + 1)
333+ if ((nextBet > totalBets))
334+ then throw("Next bet has not been placed.")
335+ else {
336+ let winnersCount = getWinnersCounter(currentGame)
337+ let result = gameGetResult(currentGame)
338+ let betDetail = split(betDetails(currentGame, nextBet), "|")[0]
339+ let betAddress = split(betDetails(currentGame, nextBet), "|")[1]
340+ if ((betDetail == result))
341+ then {
342+ let newWinnersCount = (winnersCount + 1)
343+[IntegerEntry(gameProcessedBetsLabel(currentGame), nextBet), IntegerEntry(gameWinnersCounterLabel(currentGame), newWinnersCount), StringEntry(winnerDetailsLabel(currentGame, newWinnersCount), betAddress)]
344+ }
345+ else [IntegerEntry(gameProcessedBetsLabel(currentGame), nextBet)]
346+ }
347+ }
348+ }
349+
350+
351+
352+@Callable(i)
353+func calculatePrize () = if (checkPermission(i.callerPublicKey))
354+ then throw("startGame_FORBBIDEN")
355+ else {
356+ let currentGame = getCurrentGame()
357+ let gameState = getGameState(currentGame)
358+ if ((gameState == 0))
359+ then throw("Last game has not finished yet.")
360+ else {
361+ let totalBets = getTotalBets(currentGame)
362+ let lastProcessedBet = getTotalProcessedBets(currentGame)
363+ if ((totalBets == lastProcessedBet))
364+ then {
365+ let winnersCount = getWinnersCounter(currentGame)
366+ if ((winnersCount == 0))
367+ then throw("There are no winners this round.")
368+ else match gamePrizePot(currentGame) {
369+ case prizePotAmount: Int =>
370+ let prizeShareAmount = (prizePotAmount / winnersCount)
371+[IntegerEntry(gamePrizeShareAmountLabel(currentGame), prizeShareAmount)]
372+ case _ =>
373+ throw("Game has not been initialized, Prize Pot Amount not found.")
374+ }
375+ }
376+ else throw("There are still bets that need to be processed. Cannot calculate prize yet.")
377+ }
378+ }
379+
380+
381+
382+@Callable(i)
383+func processNextWinner () = if (checkPermission(i.callerPublicKey))
384+ then throw("startGame_FORBBIDEN")
385+ else {
386+ let currentGame = getCurrentGame()
387+ let gameState = getGameState(currentGame)
388+ if ((gameState == 0))
389+ then throw("Last game has not finished yet.")
390+ else {
391+ let totalWinners = getWinnersCounter(currentGame)
392+ if ((totalWinners == 0))
393+ then throw("There are no winners this round.")
394+ else {
395+ let lastProcessedWinner = getTotalProcessedWinners(currentGame)
396+ let nextWinner = (lastProcessedWinner + 1)
397+ if ((nextWinner > totalWinners))
398+ then throw("No more winners to be processed.")
399+ else match gamePrizeShareAmount(currentGame) {
400+ case prizeShareAmount: Int =>
401+ if ((prizeShareAmount == 0))
402+ then throw("Prize share amount has not been calculated yet.")
403+ else {
404+ let betPlacer = winnerDetails(currentGame, nextWinner)
405+ let address = value(addressFromString(betPlacer))
406+[IntegerEntry(gameProcessedWinnersLabel(currentGame), nextWinner), ScriptTransfer(address, prizeShareAmount, getGameToken())]
297407 }
298- case _ =>
299- throw("Game has not been initialized, total winners not found.")
300- }
408+ case _ =>
409+ throw("Prize share amount has not been calculated yet.")
410+ }
411+ }
412+ }
413+ }
414+
415+
416+
417+@Callable(i)
418+func setParameter (parameterName,parameterValue) = if (checkPermission(i.callerPublicKey))
419+ then throw("setParameter_FORBBIDEN")
420+ else if ((parameterName == "changeTicketPrice"))
421+ then {
422+ let ticketPriceValue = valueOrElse(parseIntValue(parameterValue), 0)
423+ if ((0 > ticketPriceValue))
424+ then throw("value cannot be lower than 0")
425+ else [IntegerEntry(gameTicketPriceLabel, ticketPriceValue)]
426+ }
427+ else if ((parameterName == "changeRSA"))
428+ then match gamesGetCounter() {
429+ case GAMESCOUNTER: Int =>
430+ match gameGetState(GAMESCOUNTER) {
431+ case state: Int =>
432+ if ((state != 1))
433+ then throw("Game has to be finished.")
434+ else [StringEntry(gameRSAPublicLabel, parameterValue)]
301435 case _ =>
302- throw("Prize share amount has not been calculated yet.")
436+[StringEntry(gameRSAPublicLabel, parameterValue)]
303437 }
304- case _ =>
305- throw("Game state not found.")
306- }
307- case _ =>
308- throw("Game has not been initialized, total games not found.")
309-}
438+ case _ =>
439+ throw("Game needs to be initialized.")
440+ }
441+ else if ((parameterName == "changeEndHeight"))
442+ then match gamesGetCounter() {
443+ case GAMESCOUNTER: Int =>
444+ let endHeightValue = valueOrElse(parseIntValue(parameterValue), 0)
445+ if ((0 > endHeightValue))
446+ then throw("value cannot be lower than 0")
447+ else [IntegerEntry(gameEndHeightLabel(GAMESCOUNTER), endHeightValue)]
448+ case _ =>
449+ throw("Game needs to be initialized.")
450+ }
451+ else throw("Setting not found. Allowed: changeTicketPrice, changeRSA")
310452
311453
Full:
OldNewDifferences
11 {-# STDLIB_VERSION 4 #-}
22 {-# SCRIPT_TYPE ACCOUNT #-}
33 {-# CONTENT_TYPE DAPP #-}
4+let gameMasterPublicKey = fromBase58String("9ceJkKDVYrbcjYuGSps3NaAePtQPjBcyEg3LGkapXiyX")
5+
46 let gameTokenLabel = "G_TOKENID"
57
68 let gameBalanceLabel = "G_BALANCE"
79
810 let gameCommunityPotLabel = "G_COMMUNITYPOT"
911
1012 func gamePrizePotLabel (gameNumber) = (("G_" + toString(gameNumber)) + "_PRIZEPOT")
1113
1214
13-func gamePrizeShareAmountLabel (gameNumber) = (("G_" + toString(gameNumber)) + "P_RIZESHAREAMOUNT")
15+func gamePrizeShareAmountLabel (gameNumber) = (("G_" + toString(gameNumber)) + "_PRIZESHAREAMOUNT")
1416
1517
1618 let gameCounterLabel = "G_GAMESCOUNTER"
1719
1820 func gameTotalBetsLabel (gameNumber) = (("G_" + toString(gameNumber)) + "_TOTALBETS")
1921
2022
2123 func gameProcessedBetsLabel (gameNumber) = (("G_" + toString(gameNumber)) + "_PROCESSEDBETS")
2224
2325
2426 func gameWinnersCounterLabel (gameNumber) = (("G_" + toString(gameNumber)) + "_WINNERSCOUNT")
2527
2628
2729 func gameProcessedWinnersLabel (gameNumber) = (("G_" + toString(gameNumber)) + "_PROCESSEDWINNERS")
2830
2931
3032 func gameResultLabel (gameNumber) = (("G_" + toString(gameNumber)) + "_RESULT")
3133
3234
33-func betDetailsLabel (betNumber) = (("B_" + toString(betNumber)) + "_BETDETAILS")
35+func betDetailsLabel (gameNumber,betNumber) = (((("G_" + toString(gameNumber)) + "_B_") + toString(betNumber)) + "_BETDETAILS")
3436
3537
36-func winnerDetailsLabel (winnerNumber) = (("W_" + toString(winnerNumber)) + "_WINNERDETAILS")
38+func winnerDetailsLabel (gameNumber,winnerNumber) = (((("G_" + toString(gameNumber)) + "_W_") + toString(winnerNumber)) + "_WINNERDETAILS")
3739
3840
3941 func gameStateLabel (gameNumber) = (("G_" + toString(gameNumber)) + "_STATE")
4042
43+
44+func gameRandomHashLabel (gameNumber) = (("G_" + toString(gameNumber)) + "_RANDOMHASH")
45+
46+
47+func gameSumShaLabel (gameNumber) = (("G_" + toString(gameNumber)) + "_SUMSHA")
48+
49+
50+let gameRSAPublicLabel = "G_RSAPUBLIC"
51+
52+func gameStartHeightLabel (gameNumber) = (("G_" + toString(gameNumber)) + "_STARTHEIGHT")
53+
54+
55+func gameEndHeightLabel (gameNumber) = (("G_" + toString(gameNumber)) + "_ENDHEIGHT")
56+
57+
58+let gameTicketPriceLabel = "G_TICKETPRICE"
4159
4260 func gameBalance () = getInteger(this, gameBalanceLabel)
4361
4462
4563 func gameCommunityPot () = getInteger(this, gameCommunityPotLabel)
4664
4765
4866 func gamePrizePot (gameNumber) = getInteger(this, gamePrizePotLabel(gameNumber))
4967
5068
5169 func gamePrizeShareAmount (gameNumber) = getInteger(this, gamePrizeShareAmountLabel(gameNumber))
5270
5371
5472 func gamesGetCounter () = getInteger(this, gameCounterLabel)
5573
5674
5775 func gameTotalBets (gameNumber) = getInteger(this, gameTotalBetsLabel(gameNumber))
5876
5977
6078 func gameProcessedBets (gameNumber) = getInteger(this, gameProcessedBetsLabel(gameNumber))
6179
6280
6381 func gameWinnersCounter (gameNumber) = getInteger(this, gameWinnersCounterLabel(gameNumber))
6482
6583
6684 func gameProcessedWinners (gameNumber) = getInteger(this, gameProcessedWinnersLabel(gameNumber))
6785
6886
6987 func gameGetResult (gameNumber) = getStringValue(this, gameResultLabel(gameNumber))
7088
7189
72-func betDetails (betNumber) = getStringValue(this, betDetailsLabel(betNumber))
90+func betDetails (gameNumber,betNumber) = getStringValue(this, betDetailsLabel(gameNumber, betNumber))
7391
7492
75-func winnerDetails (winnerNumber) = getStringValue(this, winnerDetailsLabel(winnerNumber))
93+func winnerDetails (gameNumber,winnerNumber) = getStringValue(this, winnerDetailsLabel(gameNumber, winnerNumber))
7694
7795
7896 func gameGetState (gameNumber) = getInteger(this, gameStateLabel(gameNumber))
7997
8098
81-func gameToken () = match getString(this, gameTokenLabel) {
99+func gameGetSumSha (gameNumber) = getString(this, gameSumShaLabel(gameNumber))
100+
101+
102+func gameRSAPublicString () = getStringValue(this, gameRSAPublicLabel)
103+
104+
105+func gameRSAPublic () = fromBase64String("MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQD1FYRnGx+98RbdU5M2qiwjPZe9OJ79+5qq/xBttzPVrMFHnqQmTws6O2tPappakX09hSMMmXp5583G82UFnsCnQe42tkc3svugcd0Rv3y8alrL3rWtIiWx3ciyEhEdGIuwtQ80108hqevWeKPRvgUxzGnk422ri+YhakrOHgrh6QIDAQAB")
106+
107+
108+func gameTicketPrice () = getInteger(this, gameTicketPriceLabel)
109+
110+
111+func checkPermission (callerPublicKey) = (callerPublicKey != gameMasterPublicKey)
112+
113+
114+func getGameToken () = match getString(this, gameTokenLabel) {
82115 case tokenId: String =>
83116 if ((tokenId == ""))
84117 then unit
85118 else fromBase58String(tokenId)
86119 case _ =>
87120 unit
88121 }
89122
90123
91-@Callable(i)
92-func initGame () = [IntegerEntry(gameBalanceLabel, 0), IntegerEntry(gameCommunityPotLabel, 0), IntegerEntry(gameCounterLabel, 0), IntegerEntry(gameStateLabel(0), 1), IntegerEntry(gameWinnersCounterLabel(0), 0), IntegerEntry(gameProcessedWinnersLabel(0), 0), IntegerEntry(gameTotalBetsLabel(0), 0), IntegerEntry(gameProcessedBetsLabel(0), 0)]
124+func getGameTicketPrice () = match gameTicketPrice() {
125+ case ticketPrice: Int =>
126+ ticketPrice
127+ case _ =>
128+ throw("Game has not been initialized, ticket price not found.")
129+}
93130
94131
95-
96-@Callable(i)
97-func startGame () = match gamesGetCounter() {
132+func getCurrentGame () = match gamesGetCounter() {
98133 case currentGame: Int =>
99- match gameGetState(currentGame) {
100- case gameState: Int =>
101- if ((gameState == 0))
102- then throw("Last game has not finished yet.")
103- else match gameTotalBets(currentGame) {
104- case totalBets: Int =>
105- match gameProcessedBets(currentGame) {
106- case totalProcessedBets: Int =>
107- if ((totalBets == totalProcessedBets))
108- then match gameWinnersCounter(currentGame) {
109- case totalWinners: Int =>
110- match gameProcessedWinners(currentGame) {
111- case lastProcessedWinner: Int =>
112- if ((totalWinners == lastProcessedWinner))
113- then {
114- let newGame = (currentGame + 1)
115-[IntegerEntry(gameCounterLabel, newGame), IntegerEntry(gamePrizePotLabel(newGame), 100000000), IntegerEntry(gamePrizeShareAmountLabel(newGame), 0), IntegerEntry(gameTotalBetsLabel(newGame), 0), IntegerEntry(gameProcessedBetsLabel(newGame), 0), IntegerEntry(gameWinnersCounterLabel(newGame), 0), IntegerEntry(gameProcessedWinnersLabel(newGame), 0), IntegerEntry(gameStateLabel(newGame), 0)]
116- }
117- else throw("All winners have not been processed yet. Cannot start new game.")
118- case _ =>
119- throw("Game has not been initialized, total processed winners not found.")
120- }
121- case _ =>
122- throw("Game has not been initialized, total winners not found.")
123- }
124- else throw("All bets have not been processed yet. Cannot start new game.")
125- case _ =>
126- throw("Game has not been initialized, total processed bets not found.")
127- }
128- case _ =>
129- throw("Game has not been initialized, total bets not found.")
130- }
131- case _ =>
132- throw("Game state not found.")
133- }
134+ currentGame
134135 case _ =>
135136 throw("Game has not been initialized, total games not found.")
136137 }
137138
138139
140+func getGameState (currentGame) = match gameGetState(currentGame) {
141+ case gameState: Int =>
142+ gameState
143+ case _ =>
144+ throw("Game state not found.")
145+}
146+
147+
148+func getTotalBets (currentGame) = match gameTotalBets(currentGame) {
149+ case totalBets: Int =>
150+ totalBets
151+ case _ =>
152+ throw("Game has not been initialized, total bets not found.")
153+}
154+
155+
156+func getTotalProcessedBets (currentGame) = match gameProcessedBets(currentGame) {
157+ case totalProcessedBets: Int =>
158+ totalProcessedBets
159+ case _ =>
160+ throw("Game has not been initialized, total processed bets not found.")
161+}
162+
163+
164+func getWinnersCounter (currentGame) = match gameWinnersCounter(currentGame) {
165+ case winnersCount: Int =>
166+ winnersCount
167+ case _ =>
168+ throw("Game has not been initialized, total winners not found.")
169+}
170+
171+
172+func getTotalProcessedWinners (currentGame) = match gameProcessedWinners(currentGame) {
173+ case totalProcessedWinners: Int =>
174+ totalProcessedWinners
175+ case _ =>
176+ throw("Game has not been initialized, total processed winners not found.")
177+}
178+
179+
180+func getGameCommunityPot () = match gameCommunityPot() {
181+ case communityPot: Int =>
182+ communityPot
183+ case _ =>
184+ throw("Game has not been initialized, prize pot not found.")
185+}
186+
187+
188+func getGamePrizePot (currentGame) = match gamePrizePot(currentGame) {
189+ case prizePot: Int =>
190+ prizePot
191+ case _ =>
192+ throw("Game has not been initialized, prize pot not found.")
193+}
194+
139195
140196 @Callable(i)
141-func placeBet (guessValue) = match gamesGetCounter() {
142- case currentGame: Int =>
143- match gameGetState(currentGame) {
144- case gameState: Int =>
145- if ((gameState == 1))
146- then throw("Game is finished and next game has not started.")
147- else match gameTotalBets(currentGame) {
148- case totalBets: Int =>
149- let newBet = (totalBets + 1)
150- let bet = guessValue
151-[IntegerEntry(gameTotalBetsLabel(currentGame), newBet), StringEntry(betDetailsLabel(newBet), ((("G" + toString(currentGame)) + "-") + bet))]
152- case _ =>
153- throw("Game has not been initialized, total bets not found.")
154- }
155- case _ =>
156- throw("Game state not found.")
157- }
158- case _ =>
159- throw("Game has not been initialized, total games not found.")
160-}
197+func initGame () = if (checkPermission(i.callerPublicKey))
198+ then throw("initGame_FORBBIDEN")
199+ else match gamesGetCounter() {
200+ case GAMESCOUNTER: Int =>
201+ throw("Game already initialized")
202+ case _ =>
203+[IntegerEntry(gameBalanceLabel, 0), IntegerEntry(gameCommunityPotLabel, 0), IntegerEntry(gameCounterLabel, 0), IntegerEntry(gameStateLabel(0), 1), IntegerEntry(gameWinnersCounterLabel(0), 0), IntegerEntry(gameProcessedWinnersLabel(0), 0), IntegerEntry(gameTotalBetsLabel(0), 0), IntegerEntry(gameProcessedBetsLabel(0), 0), StringEntry(gameTokenLabel, ""), IntegerEntry(gameTicketPriceLabel, 1000000)]
204+ }
161205
162206
163207
164208 @Callable(i)
165-func endGame () = match gamesGetCounter() {
166- case currentGame: Int =>
167- match gameGetState(currentGame) {
168- case gameState: Int =>
169- if ((gameState == 1))
170- then throw("Game is finished and next game has not started.")
171- else [StringEntry(gameResultLabel(currentGame), ((("G" + toString(currentGame)) + "-") + "1,2,3")), IntegerEntry(gameStateLabel(currentGame), 1)]
172- case _ =>
173- throw("Game state not found.")
209+func startGame (randomHash,blockInRound) = if (checkPermission(i.callerPublicKey))
210+ then throw("startGame_FORBBIDEN")
211+ else {
212+ let currentGame = getCurrentGame()
213+ let gameState = getGameState(currentGame)
214+ if ((gameState == 0))
215+ then throw("Last game has not finished yet.")
216+ else {
217+ let totalBets = getTotalBets(currentGame)
218+ let totalProcessedBets = getTotalProcessedBets(currentGame)
219+ if ((totalBets == totalProcessedBets))
220+ then {
221+ let totalWinners = getWinnersCounter(currentGame)
222+ let lastProcessedWinner = getTotalProcessedWinners(currentGame)
223+ if ((totalWinners == lastProcessedWinner))
224+ then {
225+ let newGame = (currentGame + 1)
226+ match gameCommunityPot() {
227+ case communityPotAmount: Int =>
228+ let balance = 10000000
229+ let generator = (toInt(sha256(take(i.transactionId, 16))) % 17729)
230+ let randomNumber = ((toInt(toBytes(pow(generator, 0, 2, 0, 0, UP))) + currentGame) % 100)
231+ if ((randomNumber == 50))
232+ then {
233+ let prizePot = balance
234+[IntegerEntry(gameStartHeightLabel(currentGame), lastBlock.height), IntegerEntry(gameCounterLabel, newGame), IntegerEntry(gamePrizePotLabel(newGame), prizePot), IntegerEntry(gamePrizeShareAmountLabel(newGame), 0), IntegerEntry(gameTotalBetsLabel(newGame), 0), IntegerEntry(gameProcessedBetsLabel(newGame), 0), IntegerEntry(gameWinnersCounterLabel(newGame), 0), IntegerEntry(gameProcessedWinnersLabel(newGame), 0), IntegerEntry(gameStateLabel(newGame), 0), StringEntry(gameSumShaLabel(newGame), toBase58String(sha256(fromBase64String(randomHash)))), IntegerEntry(gameStartHeightLabel(newGame), lastBlock.height), IntegerEntry(gameEndHeightLabel(newGame), (height + blockInRound))]
235+ }
236+ else {
237+ let prizePot = (balance - communityPotAmount)
238+[IntegerEntry(gameStartHeightLabel(currentGame), lastBlock.height), IntegerEntry(gameCounterLabel, newGame), IntegerEntry(gamePrizePotLabel(newGame), prizePot), IntegerEntry(gamePrizeShareAmountLabel(newGame), 0), IntegerEntry(gameTotalBetsLabel(newGame), 0), IntegerEntry(gameProcessedBetsLabel(newGame), 0), IntegerEntry(gameWinnersCounterLabel(newGame), 0), IntegerEntry(gameProcessedWinnersLabel(newGame), 0), IntegerEntry(gameStateLabel(newGame), 0), StringEntry(gameSumShaLabel(newGame), toBase58String(sha256(fromBase64String(randomHash)))), IntegerEntry(gameStartHeightLabel(newGame), lastBlock.height), IntegerEntry(gameEndHeightLabel(newGame), (height + blockInRound))]
239+ }
240+ case _ =>
241+ throw("Game has not been initialized, total community pot not found.")
242+ }
243+ }
244+ else throw("All winners have not been processed yet. Cannot start new game.")
245+ }
246+ else throw("All bets have not been processed yet. Cannot start new game.")
247+ }
174248 }
175- case _ =>
176- throw("Game has not been initialized, total games not found.")
177-}
178249
179250
180251
181252 @Callable(i)
182-func processNextBet () = match gamesGetCounter() {
183- case currentGame: Int =>
184- match gameGetState(currentGame) {
185- case gameState: Int =>
186- if ((gameState == 0))
187- then throw("Last game has not finished yet.")
188- else match gameTotalBets(currentGame) {
189- case totalBets: Int =>
190- match gameProcessedBets(currentGame) {
191- case lastProcessedBet: Int =>
192- let nextBet = (lastProcessedBet + 1)
193- if ((nextBet > totalBets))
194- then throw("Next bet has not been placed.")
195- else match gamesGetCounter() {
196- case gameNumber: Int =>
197- match gameWinnersCounter(currentGame) {
198- case winnersCount: Int =>
199- let result = gameGetResult(gameNumber)
200- let betDetail = betDetails(nextBet)
201- if ((betDetail == result))
202- then {
203- let newWinnersCount = (winnersCount + 1)
204-[IntegerEntry(gameProcessedBetsLabel(currentGame), nextBet), IntegerEntry(gameWinnersCounterLabel(currentGame), newWinnersCount), StringEntry(winnerDetailsLabel(newWinnersCount), toBase58String(i.caller.bytes))]
205- }
206- else [IntegerEntry(gameProcessedBetsLabel(currentGame), nextBet)]
207- case _ =>
208- throw("Game has not been initialized, total winners not found.")
209- }
210- case _ =>
211- throw("Game has not been initialized, total games not found.")
212- }
213- case _ =>
214- throw("Game has not been initialized, total processed bets not found.")
215- }
216- case _ =>
217- throw("Game has not been initialized, total bets not found.")
218- }
219- case _ =>
220- throw("Game state not found.")
221- }
222- case _ =>
223- throw("Game has not been initialized, total games not found.")
224-}
253+func placeBet (guessValue) = {
254+ let currentGame = getCurrentGame()
255+ let gameState = getGameState(currentGame)
256+ if ((gameState == 1))
257+ then throw("Game is finished and next game has not started.")
258+ else if ((size(i.payments) != 1))
259+ then throw("Payment not attached or there is more then 1 payment attached.")
260+ else {
261+ let ticketPrice = getGameTicketPrice()
262+ if ((i.payments[0].amount != ticketPrice))
263+ then throw("Incorrect payment amount.")
264+ else {
265+ let totalBets = getTotalBets(currentGame)
266+ let newBet = (totalBets + 1)
267+ let bet = guessValue
268+ let prizePot = getGamePrizePot(currentGame)
269+ let communityPot = getGameCommunityPot()
270+[IntegerEntry(gameCounterLabel, currentGame), IntegerEntry(gameTotalBetsLabel(currentGame), newBet), StringEntry(betDetailsLabel(currentGame, newBet), ((((("G" + toString(currentGame)) + "-") + bet) + "|") + toBase58String(i.caller.bytes))), IntegerEntry(gamePrizePotLabel(currentGame), (prizePot + ((ticketPrice * 9) / 10))), IntegerEntry(gameCommunityPotLabel, (communityPot + ((ticketPrice * 1) / 10)))]
271+ }
272+ }
273+ }
225274
226275
227276
228277 @Callable(i)
229-func calculatePrize () = match gamesGetCounter() {
230- case currentGame: Int =>
231- match gameGetState(currentGame) {
232- case gameState: Int =>
233- if ((gameState == 0))
234- then throw("Last game has not finished yet.")
235- else match gameTotalBets(currentGame) {
236- case totalBets: Int =>
237- match gameProcessedBets(currentGame) {
238- case lastProcessedBet: Int =>
239- if ((totalBets == lastProcessedBet))
240- then match gameWinnersCounter(currentGame) {
241- case winnersCount: Int =>
242- if ((winnersCount == 0))
243- then throw("There are no winners this round.")
244- else match gamePrizePot(currentGame) {
245- case prizePotAmount: Int =>
246- let prizeShareAmount = (prizePotAmount / winnersCount)
247-[IntegerEntry(gamePrizeShareAmountLabel(currentGame), prizeShareAmount)]
248- case _ =>
249- throw("Game has not been initialized, total games not found.")
250- }
251- case _ =>
252- throw("Game has not been initialized, total winners not found.")
253- }
254- else throw("There are still bets that need to be processed. Cannot calculate prize yet.")
255- case _ =>
256- throw("Game has not been initialized, total processed bets not found.")
278+func endGame (rsaSign) = if (checkPermission(i.callerPublicKey))
279+ then throw("startGame_FORBBIDEN")
280+ else {
281+ let currentGame = getCurrentGame()
282+ let gameState = getGameState(currentGame)
283+ if ((gameState == 1))
284+ then throw("Game is finished and next game has not started.")
285+ else match gameGetSumSha(currentGame) {
286+ case SUMSHA: String =>
287+ let sig = fromBase64String(rsaSign)
288+ let rsaSigValid = rsaVerify(SHA256, fromBase58String(SUMSHA), sig, gameRSAPublic())
289+ if (!(rsaSigValid))
290+ then throw((("INVALID_RSA_SIGN " + "on game ") + toString(currentGame)))
291+ else {
292+ let generator = (toInt(sha256((take(sig, 16) + take(i.transactionId, 16)))) % 17729)
293+ let generatedResult1 = ((toInt(toBytes(pow(generator, 0, 2, 0, 0, UP))) + currentGame) % 26)
294+ let generatedResult2 = ((toInt(toBytes(pow(generator, 0, 3, 0, 0, UP))) + currentGame) % 26)
295+ let generatedResult3 = ((toInt(toBytes(pow(generator, 0, 4, 0, 0, UP))) + currentGame) % 26)
296+ if (if (if ((generatedResult1 == generatedResult2))
297+ then true
298+ else (generatedResult1 == generatedResult3))
299+ then true
300+ else (generatedResult2 == generatedResult3))
301+ then throw("Collision detected between randomly generated results.")
302+ else {
303+ let resultsList = [generatedResult1, generatedResult2, generatedResult3]
304+ let orderedResult1 = min(resultsList)
305+ let indexResult1 = indexOf(resultsList, orderedResult1)
306+ let resultsList1 = removeByIndex(resultsList, valueOrElse(indexResult1, 0))
307+ let orderedResult2 = min(resultsList1)
308+ let indexResult2 = indexOf(resultsList1, orderedResult2)
309+ let resultsList2 = removeByIndex(resultsList1, valueOrElse(indexResult2, 0))
310+ let orderedResult3 = resultsList2[0]
311+[StringEntry(gameResultLabel(currentGame), ((((((("G" + toString(currentGame)) + "-") + toString(orderedResult1)) + ",") + toString(orderedResult2)) + ",") + toString(orderedResult3))), IntegerEntry(gameStateLabel(currentGame), 1), IntegerEntry(gameCounterLabel, currentGame)]
312+ }
257313 }
258- case _ =>
259- throw("Game has not been initialized, total bets not found.")
260- }
261- case _ =>
262- throw("Game state not found.")
314+ case _ =>
315+ throw("SHA does not exist")
316+ }
263317 }
264- case _ =>
265- throw("Game has not been initialized, total games not found")
266-}
267318
268319
269320
270321 @Callable(i)
271-func processNextWinner () = match gamesGetCounter() {
272- case currentGame: Int =>
273- match gameGetState(currentGame) {
274- case gameState: Int =>
275- if ((gameState == 0))
276- then throw("Last game has not finished yet.")
277- else match gamePrizeShareAmount(currentGame) {
278- case prizeShareAmount: Int =>
279- if ((prizeShareAmount == 0))
280- then throw("Prize share amount has not been calculated yet.")
281- else match gameWinnersCounter(currentGame) {
282- case totalWinners: Int =>
283- if ((totalWinners == 0))
284- then throw("There are no winners this round.")
285- else match gameProcessedWinners(currentGame) {
286- case lastProcessedWinner: Int =>
287- let nextWinner = (lastProcessedWinner + 1)
288- if ((nextWinner > totalWinners))
289- then throw("No more winners to be processed.")
290- else {
291- let betPlacer = winnerDetails(nextWinner)
292- let address = value(addressFromString(betPlacer))
293-[ScriptTransfer(address, prizeShareAmount, gameToken()), IntegerEntry(gameProcessedWinnersLabel(currentGame), nextWinner)]
294- }
295- case _ =>
296- throw("Game has not been initialized, total processed winners not found.")
322+func processNextBet () = if (checkPermission(i.callerPublicKey))
323+ then throw("startGame_FORBBIDEN")
324+ else {
325+ let currentGame = getCurrentGame()
326+ let gameState = getGameState(currentGame)
327+ if ((gameState == 0))
328+ then throw("Last game has not finished yet.")
329+ else {
330+ let totalBets = getTotalBets(currentGame)
331+ let lastProcessedBet = getTotalProcessedBets(currentGame)
332+ let nextBet = (lastProcessedBet + 1)
333+ if ((nextBet > totalBets))
334+ then throw("Next bet has not been placed.")
335+ else {
336+ let winnersCount = getWinnersCounter(currentGame)
337+ let result = gameGetResult(currentGame)
338+ let betDetail = split(betDetails(currentGame, nextBet), "|")[0]
339+ let betAddress = split(betDetails(currentGame, nextBet), "|")[1]
340+ if ((betDetail == result))
341+ then {
342+ let newWinnersCount = (winnersCount + 1)
343+[IntegerEntry(gameProcessedBetsLabel(currentGame), nextBet), IntegerEntry(gameWinnersCounterLabel(currentGame), newWinnersCount), StringEntry(winnerDetailsLabel(currentGame, newWinnersCount), betAddress)]
344+ }
345+ else [IntegerEntry(gameProcessedBetsLabel(currentGame), nextBet)]
346+ }
347+ }
348+ }
349+
350+
351+
352+@Callable(i)
353+func calculatePrize () = if (checkPermission(i.callerPublicKey))
354+ then throw("startGame_FORBBIDEN")
355+ else {
356+ let currentGame = getCurrentGame()
357+ let gameState = getGameState(currentGame)
358+ if ((gameState == 0))
359+ then throw("Last game has not finished yet.")
360+ else {
361+ let totalBets = getTotalBets(currentGame)
362+ let lastProcessedBet = getTotalProcessedBets(currentGame)
363+ if ((totalBets == lastProcessedBet))
364+ then {
365+ let winnersCount = getWinnersCounter(currentGame)
366+ if ((winnersCount == 0))
367+ then throw("There are no winners this round.")
368+ else match gamePrizePot(currentGame) {
369+ case prizePotAmount: Int =>
370+ let prizeShareAmount = (prizePotAmount / winnersCount)
371+[IntegerEntry(gamePrizeShareAmountLabel(currentGame), prizeShareAmount)]
372+ case _ =>
373+ throw("Game has not been initialized, Prize Pot Amount not found.")
374+ }
375+ }
376+ else throw("There are still bets that need to be processed. Cannot calculate prize yet.")
377+ }
378+ }
379+
380+
381+
382+@Callable(i)
383+func processNextWinner () = if (checkPermission(i.callerPublicKey))
384+ then throw("startGame_FORBBIDEN")
385+ else {
386+ let currentGame = getCurrentGame()
387+ let gameState = getGameState(currentGame)
388+ if ((gameState == 0))
389+ then throw("Last game has not finished yet.")
390+ else {
391+ let totalWinners = getWinnersCounter(currentGame)
392+ if ((totalWinners == 0))
393+ then throw("There are no winners this round.")
394+ else {
395+ let lastProcessedWinner = getTotalProcessedWinners(currentGame)
396+ let nextWinner = (lastProcessedWinner + 1)
397+ if ((nextWinner > totalWinners))
398+ then throw("No more winners to be processed.")
399+ else match gamePrizeShareAmount(currentGame) {
400+ case prizeShareAmount: Int =>
401+ if ((prizeShareAmount == 0))
402+ then throw("Prize share amount has not been calculated yet.")
403+ else {
404+ let betPlacer = winnerDetails(currentGame, nextWinner)
405+ let address = value(addressFromString(betPlacer))
406+[IntegerEntry(gameProcessedWinnersLabel(currentGame), nextWinner), ScriptTransfer(address, prizeShareAmount, getGameToken())]
297407 }
298- case _ =>
299- throw("Game has not been initialized, total winners not found.")
300- }
408+ case _ =>
409+ throw("Prize share amount has not been calculated yet.")
410+ }
411+ }
412+ }
413+ }
414+
415+
416+
417+@Callable(i)
418+func setParameter (parameterName,parameterValue) = if (checkPermission(i.callerPublicKey))
419+ then throw("setParameter_FORBBIDEN")
420+ else if ((parameterName == "changeTicketPrice"))
421+ then {
422+ let ticketPriceValue = valueOrElse(parseIntValue(parameterValue), 0)
423+ if ((0 > ticketPriceValue))
424+ then throw("value cannot be lower than 0")
425+ else [IntegerEntry(gameTicketPriceLabel, ticketPriceValue)]
426+ }
427+ else if ((parameterName == "changeRSA"))
428+ then match gamesGetCounter() {
429+ case GAMESCOUNTER: Int =>
430+ match gameGetState(GAMESCOUNTER) {
431+ case state: Int =>
432+ if ((state != 1))
433+ then throw("Game has to be finished.")
434+ else [StringEntry(gameRSAPublicLabel, parameterValue)]
301435 case _ =>
302- throw("Prize share amount has not been calculated yet.")
436+[StringEntry(gameRSAPublicLabel, parameterValue)]
303437 }
304- case _ =>
305- throw("Game state not found.")
306- }
307- case _ =>
308- throw("Game has not been initialized, total games not found.")
309-}
438+ case _ =>
439+ throw("Game needs to be initialized.")
440+ }
441+ else if ((parameterName == "changeEndHeight"))
442+ then match gamesGetCounter() {
443+ case GAMESCOUNTER: Int =>
444+ let endHeightValue = valueOrElse(parseIntValue(parameterValue), 0)
445+ if ((0 > endHeightValue))
446+ then throw("value cannot be lower than 0")
447+ else [IntegerEntry(gameEndHeightLabel(GAMESCOUNTER), endHeightValue)]
448+ case _ =>
449+ throw("Game needs to be initialized.")
450+ }
451+ else throw("Setting not found. Allowed: changeTicketPrice, changeRSA")
310452
311453

github/deemru/w8io/169f3d6 
80.44 ms