tx · 8SW79yERkseQURvtRNdZpXn41YYvGyR7r9wgcsRYQe8h 3N4Kzbxu521DHPxcgrmZ4XUqN2kF6TqLTzs: -0.01000000 Waves 2023.09.01 15:52 [2736333] smart account 3N4Kzbxu521DHPxcgrmZ4XUqN2kF6TqLTzs > SELF 0.00000000 Waves
{ "type": 13, "id": "8SW79yERkseQURvtRNdZpXn41YYvGyR7r9wgcsRYQe8h", "fee": 1000000, "feeAssetId": null, "timestamp": 1693572747622, "version": 2, "chainId": 84, "sender": "3N4Kzbxu521DHPxcgrmZ4XUqN2kF6TqLTzs", "senderPublicKey": "8yQuxvQ2qLzXJrgbKZHbsfnNNjuU5wfHheyVujdALGsF", "proofs": [ "24vED4nXBsc6j7EcBBvPK1pbE77CUUFYPEWPaHF3QX5jzh1PVMyuDtmhD6a2sD8tCHQQY7Fd3M7i7ScivyPaPeci" ], "script": "base64:BgIfCAISABIECgIIARIGCgQIAQEIEgQKAggBEgUKAwgICBIADmxvdHRlcnlBc3NldElECQDZBAECLDNMejIzbVNVdlQxRXN3Y0JuMnNVUllKRzJhdDhyRzVhRnVVclRBd2FQTTZRAAp0aWNrZXRTaXplAAEBEGdldEludGVnZXJPckVsc2UCA2tleQN2YWwJAQt2YWx1ZU9yRWxzZQIJAJ8IAQUDa2V5BQN2YWwBD2dldFN0cmluZ09yRWxzZQIDa2V5A3ZhbAkBC3ZhbHVlT3JFbHNlAgkAoggBBQNrZXkFA3ZhbAECbWsBAXgJALkJAgUBeAIBXwERa2V5QWRyVG90YWxTdGFrZWQBA2FkcgkBAm1rAQkAzAgCAgNhZHIJAMwIAgUDYWRyCQDMCAICC3RvdGFsU3Rha2VkBQNuaWwBFWtleUxvdHRlcnlUb3RhbFN0YWtlZAELbG90dGVyeU5hbWUJAQJtawEJAMwIAgIHbG90dGVyeQkAzAgCBQtsb3R0ZXJ5TmFtZQkAzAgCAgt0b3RhbFN0YWtlZAUDbmlsARNrZXlMb3R0ZXJ5QWRyU3Rha2VkAgtsb3R0ZXJ5TmFtZQNhZHIJAQJtawEJAMwIAgIHbG90dGVyeQkAzAgCBQtsb3R0ZXJ5TmFtZQkAzAgCAgNhZHIJAMwIAgUDYWRyCQDMCAICBnN0YWtlZAUDbmlsARNrZXlMb3R0ZXJ5QWRyTG9ja2VkAgtsb3R0ZXJ5TmFtZQNhZHIJAQJtawEJAMwIAgIHbG90dGVyeQkAzAgCBQtsb3R0ZXJ5TmFtZQkAzAgCAgNhZHIJAMwIAgUDYWRyCQDMCAICBmxvY2tlZAUDbmlsARVrZXlMb3R0ZXJ5RmluYWxIZWlnaHQBC2xvdHRlcnlOYW1lCQECbWsBCQDMCAICB2xvdHRlcnkJAMwIAgULbG90dGVyeU5hbWUJAMwIAgILZmluYWxIZWlnaHQFA25pbAEUa2V5TG90dGVyeVByaXplVmFsdWUCC2xvdHRlcnlOYW1lB3ByaXplSUQJAQJtawEJAMwIAgIHbG90dGVyeQkAzAgCBQtsb3R0ZXJ5TmFtZQkAzAgCAgVwcml6ZQkAzAgCCQCkAwEFB3ByaXplSUQJAMwIAgIFdmFsdWUFA25pbAEYa2V5TG90dGVyeVByaXplVGhyZXNob2xkAgtsb3R0ZXJ5TmFtZQdwcml6ZUlECQECbWsBCQDMCAICB2xvdHRlcnkJAMwIAgULbG90dGVyeU5hbWUJAMwIAgIFcHJpemUJAMwIAgkApAMBBQdwcml6ZUlECQDMCAICCXRocmVzaG9sZAUDbmlsARVrZXlMb3R0ZXJ5UHJpemVDaG9pY2UCC2xvdHRlcnlOYW1lB3ByaXplSUQJAQJtawEJAMwIAgIHbG90dGVyeQkAzAgCBQtsb3R0ZXJ5TmFtZQkAzAgCAgVwcml6ZQkAzAgCCQCkAwEFB3ByaXplSUQJAMwIAgIGY2hvaWNlBQNuaWwBFWtleUxvdHRlcnlQcml6ZVJhbmRvbQILbG90dGVyeU5hbWUHcHJpemVJRAkBAm1rAQkAzAgCAgdsb3R0ZXJ5CQDMCAIFC2xvdHRlcnlOYW1lCQDMCAICBXByaXplCQDMCAIJAKQDAQUHcHJpemVJRAkAzAgCAgZyYW5kb20FA25pbAEWa2V5TG90dGVyeVRpY2tldHNPd25lcgMLbG90dGVyeU5hbWUEZnJvbQJ0bwkBAm1rAQkAzAgCAgdsb3R0ZXJ5CQDMCAIFC2xvdHRlcnlOYW1lCQDMCAICBGZyb20JAMwIAgkApAMBBQRmcm9tCQDMCAICAnRvCQDMCAIJAKQDAQUCdG8JAMwIAgIFb3duZXIFA25pbAASX2FjdGl2ZUxvdHRlcnlOYW1lCQECbWsBCQDMCAICBXBhcmFtCQDMCAICEWFjdGl2ZUxvdHRlcnlOYW1lBQNuaWwAEl9nbG9iYWxUb3RhbFN0YWtlZAkBAm1rAQkAzAgCAgVwYXJhbQkAzAgCAhFnbG9iYWxUb3RhbFN0YWtlZAUDbmlsARFhY3RpdmVMb3R0ZXJ5TmFtZQAEC2xvdHRlcnlOYW1lCQEPZ2V0U3RyaW5nT3JFbHNlAgUSX2FjdGl2ZUxvdHRlcnlOYW1lAgADCQAAAgULbG90dGVyeU5hbWUCAAIABBJsb3R0ZXJ5RmluYWxIZWlnaHQJARFAZXh0ck5hdGl2ZSgxMDU1KQEJARVrZXlMb3R0ZXJ5RmluYWxIZWlnaHQBBQtsb3R0ZXJ5TmFtZQMJAGcCBQZoZWlnaHQFEmxvdHRlcnlGaW5hbEhlaWdodAIABQtsb3R0ZXJ5TmFtZQUBaQEFc3Rha2UABAtsb3R0ZXJ5TmFtZQkBEWFjdGl2ZUxvdHRlcnlOYW1lAAMJAAACBQtsb3R0ZXJ5TmFtZQIACQACAQISTG90dGVyeSBub3QgYWN0aXZlAwkAAAIJAJADAQgFAWkIcGF5bWVudHMAAAkAAgECEE5vIHBheW1lbnQgYWRkZWQDCQECIT0CCQCQAwEIBQFpCHBheW1lbnRzAAEJAAIBAhdUb28gbWFueSBwYXltZW50cyBhZGRlZAMJAQIhPQIICQCRAwIIBQFpCHBheW1lbnRzAAAHYXNzZXRJZAUObG90dGVyeUFzc2V0SUQJAAIBAhVXcm9uZyBwYXltZW50IGFzc2V0SWQEBmFtb3VudAgJAJEDAggFAWkIcGF5bWVudHMAAAZhbW91bnQEDHRpY2tldEFtb3VudAkAaQIFBmFtb3VudAUKdGlja2V0U2l6ZQMJAAACBQx0aWNrZXRBbW91bnQAAAkAAgECJU5vdCBlbm91Z2ggdG8gYnV5IGF0IGxlYXN0IG9uZSB0aWNrZXQEDWNhbGxlckFkZHJlc3MJAKUIAQgFAWkGY2FsbGVyBBNfbG90dGVyeVRvdGFsU3Rha2VkCQEVa2V5TG90dGVyeVRvdGFsU3Rha2VkAQULbG90dGVyeU5hbWUEEmxvdHRlcnlUb3RhbFN0YWtlZAkBEGdldEludGVnZXJPckVsc2UCBRNfbG90dGVyeVRvdGFsU3Rha2VkAAAEBl9vd25lcgkBFmtleUxvdHRlcnlUaWNrZXRzT3duZXIDBQtsb3R0ZXJ5TmFtZQUSbG90dGVyeVRvdGFsU3Rha2VkCQBlAgkAZAIFEmxvdHRlcnlUb3RhbFN0YWtlZAUMdGlja2V0QW1vdW50AAEED19hZHJUb3RhbFN0YWtlZAkBEWtleUFkclRvdGFsU3Rha2VkAQUNY2FsbGVyQWRkcmVzcwQOYWRyVG90YWxTdGFrZWQJARBnZXRJbnRlZ2VyT3JFbHNlAgUPX2FkclRvdGFsU3Rha2VkAAAEEV9sb3R0ZXJ5QWRyU3Rha2VkCQETa2V5TG90dGVyeUFkclN0YWtlZAIFC2xvdHRlcnlOYW1lBQ1jYWxsZXJBZGRyZXNzBBVhZHJMb3R0ZXJ5VG90YWxTdGFrZWQJARBnZXRJbnRlZ2VyT3JFbHNlAgURX2xvdHRlcnlBZHJTdGFrZWQAAAQGY2hhbmdlCQBlAgUGYW1vdW50CQBoAgUMdGlja2V0QW1vdW50BQp0aWNrZXRTaXplBBFnbG9iYWxUb3RhbFN0YWtlZAkBEGdldEludGVnZXJPckVsc2UCBRJfZ2xvYmFsVG90YWxTdGFrZWQAAAkAzAgCCQEOU2NyaXB0VHJhbnNmZXIDCAUBaQZjYWxsZXIFBmNoYW5nZQUObG90dGVyeUFzc2V0SUQJAMwIAgkBC1N0cmluZ0VudHJ5AgUGX293bmVyBQ1jYWxsZXJBZGRyZXNzCQDMCAIJAQxJbnRlZ2VyRW50cnkCBRJfZ2xvYmFsVG90YWxTdGFrZWQJAGQCBRFnbG9iYWxUb3RhbFN0YWtlZAUMdGlja2V0QW1vdW50CQDMCAIJAQxJbnRlZ2VyRW50cnkCBRNfbG90dGVyeVRvdGFsU3Rha2VkCQBkAgUSbG90dGVyeVRvdGFsU3Rha2VkBQx0aWNrZXRBbW91bnQJAMwIAgkBDEludGVnZXJFbnRyeQIFD19hZHJUb3RhbFN0YWtlZAkAZAIFDmFkclRvdGFsU3Rha2VkBQx0aWNrZXRBbW91bnQJAMwIAgkBDEludGVnZXJFbnRyeQIFEV9sb3R0ZXJ5QWRyU3Rha2VkCQBkAgUVYWRyTG90dGVyeVRvdGFsU3Rha2VkBQx0aWNrZXRBbW91bnQFA25pbAFpAQxzdGFydExvdHRlcnkCC2xvdHRlcnlOYW1lEmxvdHRlcnlGaW5hbEhlaWdodAMJAQIhPQIIBQFpBmNhbGxlcgUEdGhpcwkAAgECCkFkbWluIG9ubHkJAMwIAgkBC1N0cmluZ0VudHJ5AgUSX2FjdGl2ZUxvdHRlcnlOYW1lBQtsb3R0ZXJ5TmFtZQkAzAgCCQEMSW50ZWdlckVudHJ5AgkBFWtleUxvdHRlcnlGaW5hbEhlaWdodAEFC2xvdHRlcnlOYW1lBRJsb3R0ZXJ5RmluYWxIZWlnaHQFA25pbAFpAQxkZWNsYXJlUHJpemUEC2xvdHRlcnlOYW1lB3ByaXplSWQOcHJpemVUaHJlc2hvbGQKcHJpemVWYWx1ZQMJAQIhPQIIBQFpBmNhbGxlcgUEdGhpcwkAAgECCkFkbWluIG9ubHkJAMwIAgkBDEludGVnZXJFbnRyeQIJARhrZXlMb3R0ZXJ5UHJpemVUaHJlc2hvbGQCBQtsb3R0ZXJ5TmFtZQUHcHJpemVJZAUOcHJpemVUaHJlc2hvbGQJAMwIAgkBC1N0cmluZ0VudHJ5AgkBFGtleUxvdHRlcnlQcml6ZVZhbHVlAgULbG90dGVyeU5hbWUFB3ByaXplSWQFCnByaXplVmFsdWUFA25pbAFpARRmaW5hbGFpemVQcml6ZVJhbmRvbQILbG90dGVyeU5hbWUHcHJpemVJZAMJAQIhPQIIBQFpBmNhbGxlcgUEdGhpcwkAAgECCkFkbWluIG9ubHkEEmxvdHRlcnlGaW5hbEhlaWdodAkBEUBleHRyTmF0aXZlKDEwNTUpAQkBFWtleUxvdHRlcnlGaW5hbEhlaWdodAEFC2xvdHRlcnlOYW1lAwkAZgIJAGQCBRJsb3R0ZXJ5RmluYWxIZWlnaHQAAQUGaGVpZ2h0CQACAQIXTG90dGVyeSBpcyBub3Qgb3ZlciB5ZXQEEWxvdHRlcnlQcml6ZVZhbHVlCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKIIAQkBFGtleUxvdHRlcnlQcml6ZVZhbHVlAgULbG90dGVyeU5hbWUFB3ByaXplSWQCFFByaXplIGRvZXMgbm90IGV4aXN0BAtmaW5hbEJsb2NrMAkBBXZhbHVlAQkA7QcBBRJsb3R0ZXJ5RmluYWxIZWlnaHQEC2ZpbmFsQmxvY2sxCQEFdmFsdWUBCQDtBwEJAGQCBRJsb3R0ZXJ5RmluYWxIZWlnaHQAAQQOcHJpemVSYW5kb21SYXcJAJ4DAQkA9wMBCQDLAQIJAMsBAgkAywECAQl2h2WWWi216vIJAJoDAQUHcHJpemVJZAkBBXZhbHVlAQgFC2ZpbmFsQmxvY2swA3ZyZgkBBXZhbHVlAQgFC2ZpbmFsQmxvY2sxA3ZyZgQLcHJpemVSYW5kb20DCQC/AgIJALYCAQAABQ5wcml6ZVJhbmRvbVJhdwkAvgIBBQ5wcml6ZVJhbmRvbVJhdwUOcHJpemVSYW5kb21SYXcJAMwIAgkBC1N0cmluZ0VudHJ5AgkBFWtleUxvdHRlcnlQcml6ZVJhbmRvbQIFC2xvdHRlcnlOYW1lBQdwcml6ZUlkCQCmAwEFC3ByaXplUmFuZG9tBQNuaWwBaQESZGVjbGFyZVByaXplV2lubmVyAwtsb3R0ZXJ5TmFtZQdwcml6ZUlkCXdpbm5lckFkcgMJAQIhPQIIBQFpBmNhbGxlcgUEdGhpcwkAAgECCkFkbWluIG9ubHkJAMwIAgkBC1N0cmluZ0VudHJ5AgIAAgAFA25pbAECdHgBBnZlcmlmeQAJAPQDAwgFAnR4CWJvZHlCeXRlcwkAkQMCCAUCdHgGcHJvb2ZzAAAIBQJ0eA9zZW5kZXJQdWJsaWNLZXld86KR", "height": 2736333, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: G7NkxgAfk2ZZCr5khc1QMJ5s799kj65gXxtJ7pm1dWZz Next: DN7jhGs21wgMBEH7XJMegDU6v1WdtCuPm2SnXkVY747P Diff:
Old | New | Differences | |
---|---|---|---|
20 | 20 | func keyLotteryTotalStaked (lotteryName) = mk(["lottery", lotteryName, "totalStaked"]) | |
21 | 21 | ||
22 | 22 | ||
23 | - | func keyAdrLotteryTotalStaked (lotteryName,adr) = mk(["lottery", lotteryName, "adr", adr, "totalStaked"]) | |
23 | + | func keyLotteryAdrStaked (lotteryName,adr) = mk(["lottery", lotteryName, "adr", adr, "staked"]) | |
24 | + | ||
25 | + | ||
26 | + | func keyLotteryAdrLocked (lotteryName,adr) = mk(["lottery", lotteryName, "adr", adr, "locked"]) | |
24 | 27 | ||
25 | 28 | ||
26 | 29 | func keyLotteryFinalHeight (lotteryName) = mk(["lottery", lotteryName, "finalHeight"]) | |
27 | 30 | ||
28 | 31 | ||
29 | - | func keyLotteryPrizeValue (lotteryName,prizeID) = mk(["lottery", lotteryName, "prize", prizeID, "value"]) | |
32 | + | func keyLotteryPrizeValue (lotteryName,prizeID) = mk(["lottery", lotteryName, "prize", toString(prizeID), "value"]) | |
30 | 33 | ||
31 | 34 | ||
32 | - | func keyLotteryPrizeChoice (lotteryName,prizeID) = mk(["lottery", lotteryName, "prize", prizeID, "choice"]) | |
35 | + | func keyLotteryPrizeThreshold (lotteryName,prizeID) = mk(["lottery", lotteryName, "prize", toString(prizeID), "threshold"]) | |
36 | + | ||
37 | + | ||
38 | + | func keyLotteryPrizeChoice (lotteryName,prizeID) = mk(["lottery", lotteryName, "prize", toString(prizeID), "choice"]) | |
39 | + | ||
40 | + | ||
41 | + | func keyLotteryPrizeRandom (lotteryName,prizeID) = mk(["lottery", lotteryName, "prize", toString(prizeID), "random"]) | |
42 | + | ||
43 | + | ||
44 | + | func keyLotteryTicketsOwner (lotteryName,from,to) = mk(["lottery", lotteryName, "from", toString(from), "to", toString(to), "owner"]) | |
33 | 45 | ||
34 | 46 | ||
35 | 47 | let _activeLotteryName = mk(["param", "activeLotteryName"]) | |
48 | + | ||
49 | + | let _globalTotalStaked = mk(["param", "globalTotalStaked"]) | |
36 | 50 | ||
37 | 51 | func activeLotteryName () = { | |
38 | 52 | let lotteryName = getStringOrElse(_activeLotteryName, "") | |
40 | 54 | then "" | |
41 | 55 | else { | |
42 | 56 | let lotteryFinalHeight = getIntegerValue(keyLotteryFinalHeight(lotteryName)) | |
43 | - | if (( | |
57 | + | if ((height >= lotteryFinalHeight)) | |
44 | 58 | then "" | |
45 | 59 | else lotteryName | |
46 | 60 | } | |
60 | 74 | then throw("Wrong payment assetId") | |
61 | 75 | else { | |
62 | 76 | let amount = i.payments[0].amount | |
63 | - | let ticketAmount = | |
77 | + | let ticketAmount = (amount / ticketSize) | |
64 | 78 | if ((ticketAmount == 0)) | |
65 | 79 | then throw("Not enough to buy at least one ticket") | |
66 | 80 | else { | |
67 | 81 | let callerAddress = toString(i.caller) | |
68 | 82 | let _lotteryTotalStaked = keyLotteryTotalStaked(lotteryName) | |
69 | - | let lotteryTotalStaked = | |
70 | - | let _owner = | |
83 | + | let lotteryTotalStaked = getIntegerOrElse(_lotteryTotalStaked, 0) | |
84 | + | let _owner = keyLotteryTicketsOwner(lotteryName, lotteryTotalStaked, ((lotteryTotalStaked + ticketAmount) - 1)) | |
71 | 85 | let _adrTotalStaked = keyAdrTotalStaked(callerAddress) | |
72 | 86 | let adrTotalStaked = getIntegerOrElse(_adrTotalStaked, 0) | |
73 | - | let _ | |
74 | - | let adrLotteryTotalStaked = getIntegerOrElse(_ | |
87 | + | let _lotteryAdrStaked = keyLotteryAdrStaked(lotteryName, callerAddress) | |
88 | + | let adrLotteryTotalStaked = getIntegerOrElse(_lotteryAdrStaked, 0) | |
75 | 89 | let change = (amount - (ticketAmount * ticketSize)) | |
76 | - | [IntegerEntry(_lotteryTotalStaked, (lotteryTotalStaked + ticketAmount)), StringEntry(_owner, callerAddress), IntegerEntry(_adrTotalStaked, (adrTotalStaked + ticketAmount)), IntegerEntry(_adrLotteryTotalStaked, (adrLotteryTotalStaked + ticketAmount))] | |
90 | + | let globalTotalStaked = getIntegerOrElse(_globalTotalStaked, 0) | |
91 | + | [ScriptTransfer(i.caller, change, lotteryAssetID), StringEntry(_owner, callerAddress), IntegerEntry(_globalTotalStaked, (globalTotalStaked + ticketAmount)), IntegerEntry(_lotteryTotalStaked, (lotteryTotalStaked + ticketAmount)), IntegerEntry(_adrTotalStaked, (adrTotalStaked + ticketAmount)), IntegerEntry(_lotteryAdrStaked, (adrLotteryTotalStaked + ticketAmount))] | |
77 | 92 | } | |
78 | 93 | } | |
79 | 94 | } | |
81 | 96 | ||
82 | 97 | ||
83 | 98 | @Callable(i) | |
84 | - | func claim () = if ((size(i.payments) > 0)) | |
85 | - | then throw("No payments needed") | |
99 | + | func startLottery (lotteryName,lotteryFinalHeight) = if ((i.caller != this)) | |
100 | + | then throw("Admin only") | |
101 | + | else [StringEntry(_activeLotteryName, lotteryName), IntegerEntry(keyLotteryFinalHeight(lotteryName), lotteryFinalHeight)] | |
102 | + | ||
103 | + | ||
104 | + | ||
105 | + | @Callable(i) | |
106 | + | func declarePrize (lotteryName,prizeId,prizeThreshold,prizeValue) = if ((i.caller != this)) | |
107 | + | then throw("Admin only") | |
108 | + | else [IntegerEntry(keyLotteryPrizeThreshold(lotteryName, prizeId), prizeThreshold), StringEntry(keyLotteryPrizeValue(lotteryName, prizeId), prizeValue)] | |
109 | + | ||
110 | + | ||
111 | + | ||
112 | + | @Callable(i) | |
113 | + | func finalaizePrizeRandom (lotteryName,prizeId) = if ((i.caller != this)) | |
114 | + | then throw("Admin only") | |
86 | 115 | else { | |
87 | - | let callerAddress = toString(i.caller) | |
88 | - | let lotteryName = activeLotteryName() | |
89 | - | let stakedInActiveLottery = if ((lotteryName == "")) | |
90 | - | then 0 | |
91 | - | else getIntegerOrElse(keyAdrLotteryTotalStaked(lotteryName, callerAddress), 0) | |
92 | - | let _adrTotalStaked = keyAdrTotalStaked(callerAddress) | |
93 | - | let adrTotalStaked = getIntegerOrElse(_adrTotalStaked, 0) | |
94 | - | let available = (adrTotalStaked - stakedInActiveLottery) | |
95 | - | if ((0 >= available)) | |
96 | - | then throw("No assets available for claim") | |
97 | - | else [ScriptTransfer(i.caller, available, lotteryAssetID), IntegerEntry(_adrTotalStaked, (adrTotalStaked - available))] | |
116 | + | let lotteryFinalHeight = getIntegerValue(keyLotteryFinalHeight(lotteryName)) | |
117 | + | if (((lotteryFinalHeight + 1) > height)) | |
118 | + | then throw("Lottery is not over yet") | |
119 | + | else { | |
120 | + | let lotteryPrizeValue = valueOrErrorMessage(getString(keyLotteryPrizeValue(lotteryName, prizeId)), "Prize does not exist") | |
121 | + | let finalBlock0 = value(blockInfoByHeight(lotteryFinalHeight)) | |
122 | + | let finalBlock1 = value(blockInfoByHeight((lotteryFinalHeight + 1))) | |
123 | + | let prizeRandomRaw = toBigInt(sha256((((base58'2WWKxchwx7zBB' + toBytes(prizeId)) + value(finalBlock0.vrf)) + value(finalBlock1.vrf)))) | |
124 | + | let prizeRandom = if ((toBigInt(0) > prizeRandomRaw)) | |
125 | + | then -(prizeRandomRaw) | |
126 | + | else prizeRandomRaw | |
127 | + | [StringEntry(keyLotteryPrizeRandom(lotteryName, prizeId), toString(prizeRandom))] | |
128 | + | } | |
98 | 129 | } | |
99 | 130 | ||
100 | 131 | ||
101 | 132 | ||
102 | 133 | @Callable(i) | |
103 | - | func | |
134 | + | func declarePrizeWinner (lotteryName,prizeId,winnerAdr) = if ((i.caller != this)) | |
104 | 135 | then throw("Admin only") | |
105 | - | else [StringEntry(_activeLotteryName, lotteryName), IntegerEntry(keyLotteryFinalHeight(lotteryName), lotteryFinalHeight), IntegerEntry(keyLotteryTotalStaked(lotteryName), 0)] | |
106 | - | ||
107 | - | ||
108 | - | ||
109 | - | @Callable(i) | |
110 | - | func declarePrize (lotteryName,prizeId,prizeValue) = if ((i.caller != this)) | |
111 | - | then throw("Admin only") | |
112 | - | else [StringEntry(keyLotteryPrizeValue(lotteryName, prizeId), prizeValue)] | |
113 | - | ||
114 | - | ||
115 | - | ||
116 | - | @Callable(i) | |
117 | - | func finalaizePrizeChoice (lotteryName,prizeId) = if ((i.caller != this)) | |
118 | - | then throw("Admin only") | |
119 | - | else { | |
120 | - | let lotteryFinalHeight = getIntegerValue(keyLotteryFinalHeight(lotteryName)) | |
121 | - | if ((lotteryFinalHeight > height)) | |
122 | - | then throw("Lottery is not over yet") | |
123 | - | else { | |
124 | - | let lotteryTotalStaked = getIntegerValue(keyLotteryTotalStaked(lotteryName)) | |
125 | - | if ((lotteryTotalStaked == 0)) | |
126 | - | then throw("No one entered the lottery") | |
127 | - | else { | |
128 | - | let lotteryPrizeValue = getStringOrElse(keyLotteryPrizeValue(lotteryName, prizeId), "") | |
129 | - | if ((lotteryPrizeValue == "")) | |
130 | - | then throw("prize does not exist") | |
131 | - | else { | |
132 | - | let finalBlock = value(blockInfoByHeight(lotteryFinalHeight)) | |
133 | - | let randomHash = sha256(((toBytes(prizeId) + value(finalBlock.vrf)) + base58'2WWKxchwx7zBB')) | |
134 | - | let rawChoice = toInt((toBigInt(randomHash) % toBigInt(lotteryTotalStaked))) | |
135 | - | let choice = if ((0 > rawChoice)) | |
136 | - | then -(rawChoice) | |
137 | - | else rawChoice | |
138 | - | [StringEntry("lastHash", toString(toBigInt(randomHash))), IntegerEntry(keyLotteryPrizeChoice(lotteryName, prizeId), choice)] | |
139 | - | } | |
140 | - | } | |
141 | - | } | |
142 | - | } | |
136 | + | else [StringEntry("", "")] | |
143 | 137 | ||
144 | 138 | ||
145 | 139 | @Verifier(tx) |
Old | New | Differences | |
---|---|---|---|
1 | 1 | {-# STDLIB_VERSION 6 #-} | |
2 | 2 | {-# SCRIPT_TYPE ACCOUNT #-} | |
3 | 3 | {-# CONTENT_TYPE DAPP #-} | |
4 | 4 | let lotteryAssetID = fromBase58String("3Lz23mSUvT1EswcBn2sURYJG2at8rG5aFuUrTAwaPM6Q") | |
5 | 5 | ||
6 | 6 | let ticketSize = 1 | |
7 | 7 | ||
8 | 8 | func getIntegerOrElse (key,val) = valueOrElse(getInteger(key), val) | |
9 | 9 | ||
10 | 10 | ||
11 | 11 | func getStringOrElse (key,val) = valueOrElse(getString(key), val) | |
12 | 12 | ||
13 | 13 | ||
14 | 14 | func mk (x) = makeString(x, "_") | |
15 | 15 | ||
16 | 16 | ||
17 | 17 | func keyAdrTotalStaked (adr) = mk(["adr", adr, "totalStaked"]) | |
18 | 18 | ||
19 | 19 | ||
20 | 20 | func keyLotteryTotalStaked (lotteryName) = mk(["lottery", lotteryName, "totalStaked"]) | |
21 | 21 | ||
22 | 22 | ||
23 | - | func keyAdrLotteryTotalStaked (lotteryName,adr) = mk(["lottery", lotteryName, "adr", adr, "totalStaked"]) | |
23 | + | func keyLotteryAdrStaked (lotteryName,adr) = mk(["lottery", lotteryName, "adr", adr, "staked"]) | |
24 | + | ||
25 | + | ||
26 | + | func keyLotteryAdrLocked (lotteryName,adr) = mk(["lottery", lotteryName, "adr", adr, "locked"]) | |
24 | 27 | ||
25 | 28 | ||
26 | 29 | func keyLotteryFinalHeight (lotteryName) = mk(["lottery", lotteryName, "finalHeight"]) | |
27 | 30 | ||
28 | 31 | ||
29 | - | func keyLotteryPrizeValue (lotteryName,prizeID) = mk(["lottery", lotteryName, "prize", prizeID, "value"]) | |
32 | + | func keyLotteryPrizeValue (lotteryName,prizeID) = mk(["lottery", lotteryName, "prize", toString(prizeID), "value"]) | |
30 | 33 | ||
31 | 34 | ||
32 | - | func keyLotteryPrizeChoice (lotteryName,prizeID) = mk(["lottery", lotteryName, "prize", prizeID, "choice"]) | |
35 | + | func keyLotteryPrizeThreshold (lotteryName,prizeID) = mk(["lottery", lotteryName, "prize", toString(prizeID), "threshold"]) | |
36 | + | ||
37 | + | ||
38 | + | func keyLotteryPrizeChoice (lotteryName,prizeID) = mk(["lottery", lotteryName, "prize", toString(prizeID), "choice"]) | |
39 | + | ||
40 | + | ||
41 | + | func keyLotteryPrizeRandom (lotteryName,prizeID) = mk(["lottery", lotteryName, "prize", toString(prizeID), "random"]) | |
42 | + | ||
43 | + | ||
44 | + | func keyLotteryTicketsOwner (lotteryName,from,to) = mk(["lottery", lotteryName, "from", toString(from), "to", toString(to), "owner"]) | |
33 | 45 | ||
34 | 46 | ||
35 | 47 | let _activeLotteryName = mk(["param", "activeLotteryName"]) | |
48 | + | ||
49 | + | let _globalTotalStaked = mk(["param", "globalTotalStaked"]) | |
36 | 50 | ||
37 | 51 | func activeLotteryName () = { | |
38 | 52 | let lotteryName = getStringOrElse(_activeLotteryName, "") | |
39 | 53 | if ((lotteryName == "")) | |
40 | 54 | then "" | |
41 | 55 | else { | |
42 | 56 | let lotteryFinalHeight = getIntegerValue(keyLotteryFinalHeight(lotteryName)) | |
43 | - | if (( | |
57 | + | if ((height >= lotteryFinalHeight)) | |
44 | 58 | then "" | |
45 | 59 | else lotteryName | |
46 | 60 | } | |
47 | 61 | } | |
48 | 62 | ||
49 | 63 | ||
50 | 64 | @Callable(i) | |
51 | 65 | func stake () = { | |
52 | 66 | let lotteryName = activeLotteryName() | |
53 | 67 | if ((lotteryName == "")) | |
54 | 68 | then throw("Lottery not active") | |
55 | 69 | else if ((size(i.payments) == 0)) | |
56 | 70 | then throw("No payment added") | |
57 | 71 | else if ((size(i.payments) != 1)) | |
58 | 72 | then throw("Too many payments added") | |
59 | 73 | else if ((i.payments[0].assetId != lotteryAssetID)) | |
60 | 74 | then throw("Wrong payment assetId") | |
61 | 75 | else { | |
62 | 76 | let amount = i.payments[0].amount | |
63 | - | let ticketAmount = | |
77 | + | let ticketAmount = (amount / ticketSize) | |
64 | 78 | if ((ticketAmount == 0)) | |
65 | 79 | then throw("Not enough to buy at least one ticket") | |
66 | 80 | else { | |
67 | 81 | let callerAddress = toString(i.caller) | |
68 | 82 | let _lotteryTotalStaked = keyLotteryTotalStaked(lotteryName) | |
69 | - | let lotteryTotalStaked = | |
70 | - | let _owner = | |
83 | + | let lotteryTotalStaked = getIntegerOrElse(_lotteryTotalStaked, 0) | |
84 | + | let _owner = keyLotteryTicketsOwner(lotteryName, lotteryTotalStaked, ((lotteryTotalStaked + ticketAmount) - 1)) | |
71 | 85 | let _adrTotalStaked = keyAdrTotalStaked(callerAddress) | |
72 | 86 | let adrTotalStaked = getIntegerOrElse(_adrTotalStaked, 0) | |
73 | - | let _ | |
74 | - | let adrLotteryTotalStaked = getIntegerOrElse(_ | |
87 | + | let _lotteryAdrStaked = keyLotteryAdrStaked(lotteryName, callerAddress) | |
88 | + | let adrLotteryTotalStaked = getIntegerOrElse(_lotteryAdrStaked, 0) | |
75 | 89 | let change = (amount - (ticketAmount * ticketSize)) | |
76 | - | [IntegerEntry(_lotteryTotalStaked, (lotteryTotalStaked + ticketAmount)), StringEntry(_owner, callerAddress), IntegerEntry(_adrTotalStaked, (adrTotalStaked + ticketAmount)), IntegerEntry(_adrLotteryTotalStaked, (adrLotteryTotalStaked + ticketAmount))] | |
90 | + | let globalTotalStaked = getIntegerOrElse(_globalTotalStaked, 0) | |
91 | + | [ScriptTransfer(i.caller, change, lotteryAssetID), StringEntry(_owner, callerAddress), IntegerEntry(_globalTotalStaked, (globalTotalStaked + ticketAmount)), IntegerEntry(_lotteryTotalStaked, (lotteryTotalStaked + ticketAmount)), IntegerEntry(_adrTotalStaked, (adrTotalStaked + ticketAmount)), IntegerEntry(_lotteryAdrStaked, (adrLotteryTotalStaked + ticketAmount))] | |
77 | 92 | } | |
78 | 93 | } | |
79 | 94 | } | |
80 | 95 | ||
81 | 96 | ||
82 | 97 | ||
83 | 98 | @Callable(i) | |
84 | - | func claim () = if ((size(i.payments) > 0)) | |
85 | - | then throw("No payments needed") | |
99 | + | func startLottery (lotteryName,lotteryFinalHeight) = if ((i.caller != this)) | |
100 | + | then throw("Admin only") | |
101 | + | else [StringEntry(_activeLotteryName, lotteryName), IntegerEntry(keyLotteryFinalHeight(lotteryName), lotteryFinalHeight)] | |
102 | + | ||
103 | + | ||
104 | + | ||
105 | + | @Callable(i) | |
106 | + | func declarePrize (lotteryName,prizeId,prizeThreshold,prizeValue) = if ((i.caller != this)) | |
107 | + | then throw("Admin only") | |
108 | + | else [IntegerEntry(keyLotteryPrizeThreshold(lotteryName, prizeId), prizeThreshold), StringEntry(keyLotteryPrizeValue(lotteryName, prizeId), prizeValue)] | |
109 | + | ||
110 | + | ||
111 | + | ||
112 | + | @Callable(i) | |
113 | + | func finalaizePrizeRandom (lotteryName,prizeId) = if ((i.caller != this)) | |
114 | + | then throw("Admin only") | |
86 | 115 | else { | |
87 | - | let callerAddress = toString(i.caller) | |
88 | - | let lotteryName = activeLotteryName() | |
89 | - | let stakedInActiveLottery = if ((lotteryName == "")) | |
90 | - | then 0 | |
91 | - | else getIntegerOrElse(keyAdrLotteryTotalStaked(lotteryName, callerAddress), 0) | |
92 | - | let _adrTotalStaked = keyAdrTotalStaked(callerAddress) | |
93 | - | let adrTotalStaked = getIntegerOrElse(_adrTotalStaked, 0) | |
94 | - | let available = (adrTotalStaked - stakedInActiveLottery) | |
95 | - | if ((0 >= available)) | |
96 | - | then throw("No assets available for claim") | |
97 | - | else [ScriptTransfer(i.caller, available, lotteryAssetID), IntegerEntry(_adrTotalStaked, (adrTotalStaked - available))] | |
116 | + | let lotteryFinalHeight = getIntegerValue(keyLotteryFinalHeight(lotteryName)) | |
117 | + | if (((lotteryFinalHeight + 1) > height)) | |
118 | + | then throw("Lottery is not over yet") | |
119 | + | else { | |
120 | + | let lotteryPrizeValue = valueOrErrorMessage(getString(keyLotteryPrizeValue(lotteryName, prizeId)), "Prize does not exist") | |
121 | + | let finalBlock0 = value(blockInfoByHeight(lotteryFinalHeight)) | |
122 | + | let finalBlock1 = value(blockInfoByHeight((lotteryFinalHeight + 1))) | |
123 | + | let prizeRandomRaw = toBigInt(sha256((((base58'2WWKxchwx7zBB' + toBytes(prizeId)) + value(finalBlock0.vrf)) + value(finalBlock1.vrf)))) | |
124 | + | let prizeRandom = if ((toBigInt(0) > prizeRandomRaw)) | |
125 | + | then -(prizeRandomRaw) | |
126 | + | else prizeRandomRaw | |
127 | + | [StringEntry(keyLotteryPrizeRandom(lotteryName, prizeId), toString(prizeRandom))] | |
128 | + | } | |
98 | 129 | } | |
99 | 130 | ||
100 | 131 | ||
101 | 132 | ||
102 | 133 | @Callable(i) | |
103 | - | func | |
134 | + | func declarePrizeWinner (lotteryName,prizeId,winnerAdr) = if ((i.caller != this)) | |
104 | 135 | then throw("Admin only") | |
105 | - | else [StringEntry(_activeLotteryName, lotteryName), IntegerEntry(keyLotteryFinalHeight(lotteryName), lotteryFinalHeight), IntegerEntry(keyLotteryTotalStaked(lotteryName), 0)] | |
106 | - | ||
107 | - | ||
108 | - | ||
109 | - | @Callable(i) | |
110 | - | func declarePrize (lotteryName,prizeId,prizeValue) = if ((i.caller != this)) | |
111 | - | then throw("Admin only") | |
112 | - | else [StringEntry(keyLotteryPrizeValue(lotteryName, prizeId), prizeValue)] | |
113 | - | ||
114 | - | ||
115 | - | ||
116 | - | @Callable(i) | |
117 | - | func finalaizePrizeChoice (lotteryName,prizeId) = if ((i.caller != this)) | |
118 | - | then throw("Admin only") | |
119 | - | else { | |
120 | - | let lotteryFinalHeight = getIntegerValue(keyLotteryFinalHeight(lotteryName)) | |
121 | - | if ((lotteryFinalHeight > height)) | |
122 | - | then throw("Lottery is not over yet") | |
123 | - | else { | |
124 | - | let lotteryTotalStaked = getIntegerValue(keyLotteryTotalStaked(lotteryName)) | |
125 | - | if ((lotteryTotalStaked == 0)) | |
126 | - | then throw("No one entered the lottery") | |
127 | - | else { | |
128 | - | let lotteryPrizeValue = getStringOrElse(keyLotteryPrizeValue(lotteryName, prizeId), "") | |
129 | - | if ((lotteryPrizeValue == "")) | |
130 | - | then throw("prize does not exist") | |
131 | - | else { | |
132 | - | let finalBlock = value(blockInfoByHeight(lotteryFinalHeight)) | |
133 | - | let randomHash = sha256(((toBytes(prizeId) + value(finalBlock.vrf)) + base58'2WWKxchwx7zBB')) | |
134 | - | let rawChoice = toInt((toBigInt(randomHash) % toBigInt(lotteryTotalStaked))) | |
135 | - | let choice = if ((0 > rawChoice)) | |
136 | - | then -(rawChoice) | |
137 | - | else rawChoice | |
138 | - | [StringEntry("lastHash", toString(toBigInt(randomHash))), IntegerEntry(keyLotteryPrizeChoice(lotteryName, prizeId), choice)] | |
139 | - | } | |
140 | - | } | |
141 | - | } | |
142 | - | } | |
136 | + | else [StringEntry("", "")] | |
143 | 137 | ||
144 | 138 | ||
145 | 139 | @Verifier(tx) | |
146 | 140 | func verify () = sigVerify(tx.bodyBytes, tx.proofs[0], tx.senderPublicKey) | |
147 | 141 |
github/deemru/w8io/169f3d6 37.35 ms ◑![]()