tx · Ffohhby5ENVZRFcPY7CgTsbpYXna4tK6gmK5iRWsc4L8

3PLncXtS1U83D6cQbFD3H8rBHPLgzxSFKZ1:  -0.01100000 Waves

2022.12.12 02:55 [3421834] smart account 3PLncXtS1U83D6cQbFD3H8rBHPLgzxSFKZ1 > SELF 0.00000000 Waves

{ "type": 13, "id": "Ffohhby5ENVZRFcPY7CgTsbpYXna4tK6gmK5iRWsc4L8", "fee": 1100000, "feeAssetId": null, "timestamp": 1670802937689, "version": 2, "chainId": 87, "sender": "3PLncXtS1U83D6cQbFD3H8rBHPLgzxSFKZ1", "senderPublicKey": "BtDpFhgHQKHFVqYTMLReuZzqy94CRPSRkrYcSEVyjt4q", "proofs": [ "3QrUt7W5fifpHYnNcJhRqNqvFVzxPa6rbCzWtJgaBRV4gaY1h9gn9PaWr97DQCnbvJFjGdTYGUTGUg8tG52VCdQo" ], "script": "base64:BgIoCAISABIDCgEIEgASAwoBCBIECgIBCBIECgICAhIECgIBCBIECgIICCkAC3VzZG5Bc3NldElkASC2JinDBPXOU5GkDkt1JC9kjFGx+t+vVCm9SNIdKrKq0QANaW5jdWJhdG9yQWRkcgkBEUBleHRyTmF0aXZlKDEwNjIpAQIjM1BFa3RWdXgyUmhjaFNONjNEc0RvNGI0bXo0UXF6S1NlRHYAC2JyZWVkZXJBZGRyCQERQGV4dHJOYXRpdmUoMTA2MikBAiMzUERWdVU0NUg3RWg1ZG10TmJuUk5SU3RHd1VMQTdOWTZIYgALYmFja0VuZEFkZHIJARFAZXh0ck5hdGl2ZSgxMDYyKQECIzNQQktldTc4eGROeWFLdzVrMlVhNm5wcWU4TVJRZWdvcTE3AAtlY29ub215QWRkcgkBEUBleHRyTmF0aXZlKDEwNjIpAQIjM1Ayc2sxS25jU3hSYVpzOGI0Q1dHUHcyamt2dmF2NzR1NEQAA3B1YgEgT1PiGj9UqNadUk4THUYnVb2zU/Mse8lUVLD/Q8G0FCgACkxBTkRQUkVGSVgCBExBTkQACkRVQ0tQUkVGSVgCBERVQ0sAD0RFRkFVTFRMT0NBVElPTgIPQWZyaWNhX0ZfQWZyaWNhAA9EQUlMWVJFU0JZUElFQ0UAgPjSAQAJREFZTUlMTElTAIC4mSkAEUZJVkVNSU5VVEVTTUlMTElTAOCnEgERa2V5QXNzZXRJZFRvT3duZXIBB2Fzc2V0SWQJAKwCAgIJbmZ0T3duZXJfBQdhc3NldElkARBrZXlEdWNrSWRUb093bmVyAQdhc3NldElkCQCsAgICCmR1Y2tPd25lcl8FB2Fzc2V0SWQBFmtleVN0YWtlZFRpbWVCeUFzc2V0SWQBB2Fzc2V0SWQJAKwCAgILc3Rha2VkVGltZV8FB2Fzc2V0SWQBFGtleVN0YWtlZER1Y2tCeU93bmVyAQlvd25lckFkZHIJAKwCAgISc3Rha2VkRHVja0J5T3duZXJfBQlvd25lckFkZHIBImtleVN0YWtlZFRpbWVCeVR5cGVBc3NldElkQW5kT3duZXIDB25mdFR5cGUHYXNzZXRJZAlvd25lckFkZHIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICAiBzdGFrZWRUaW1lQnlUeXBlQXNzZXRJZEFuZE93bmVyXwUHbmZ0VHlwZQIBXwUHYXNzZXRJZAIBXwUJb3duZXJBZGRyAQ5rZXlMYW5kVG9Pd25lcgEHbGFuZE51bQkArAICAgpsYW5kT3duZXJfBQdsYW5kTnVtARFrZXlCYWNrcGFja0J5RHVjawELZHVja0Fzc2V0SWQJAKwCAgIJYmFja1BhY2tfBQtkdWNrQXNzZXRJZAEPa2V5RHVja0xvY2F0aW9uAQtkdWNrQXNzZXRJZAkArAICAg1kdWNrTG9jYXRpb25fBQtkdWNrQXNzZXRJZAENa2V5RHVja0hlYWx0aAELZHVja0Fzc2V0SWQJAKwCAgILZHVja0hlYWx0aF8FC2R1Y2tBc3NldElkAApyZWNMYW5kTnVtAAAAC3JlY0xhbmRTaXplAAEAC3JlY1RlcnJhaW5zAAIADHJlY0NvbnRpbmVudAADAA9sb2NJZHhDb250aW5lbnQAAAAKbG9jSWR4VHlwZQABAAhsb2NJZHhJZAACAApicElkeExldmVsAAAACGJwSWR4UmVzAAEACGJwSWR4TWF0AAIACWJwSWR4UHJvZAADAARpZHhBAAAABGlkeEIAAQAEaWR4QwACAARpZHhEAAMABGlkeEUABAAEaWR4RgAFAQ1jb3VudFRlcnJhaW5zAQh0ZXJyYWlucwkAzAgCCQBlAgkAkAMBCQC1CQIFCHRlcnJhaW5zAgFBAAEJAMwIAgkAZQIJAJADAQkAtQkCBQh0ZXJyYWlucwIBQgABCQDMCAIJAGUCCQCQAwEJALUJAgUIdGVycmFpbnMCAUMAAQkAzAgCCQBlAgkAkAMBCQC1CQIFCHRlcnJhaW5zAgFEAAEJAMwIAgkAZQIJAJADAQkAtQkCBQh0ZXJyYWlucwIBRQABCQDMCAIJAGUCCQCQAwEJALUJAgUIdGVycmFpbnMCAUYAAQUDbmlsAQ9udW1QaWVjZXNCeVNpemUBCGxhbmRTaXplBAckbWF0Y2gwBQhsYW5kU2l6ZQMJAAACAgFTBQckbWF0Y2gwABkDCQAAAgIBTQUHJG1hdGNoMABkAwkAAAICAUwFByRtYXRjaDAA4QEDCQAAAgICWEwFByRtYXRjaDAAkAMDCQAAAgIDWFhMBQckbWF0Y2gwAPEECQACAQIRVW5rbm93biBsYW5kIHNpemUBBmFkZFJlcwMKY3VycmVudFJlcw10ZXJyYWluQ291bnRzCWRlbHRhVGltZQoBBWFkZGVyAgNhY2MBaQQJcmVzT2ZUeXBlCQBoAgkAawMFCWRlbHRhVGltZQUPREFJTFlSRVNCWVBJRUNFBQlEQVlNSUxMSVMJAJEDAgUNdGVycmFpbkNvdW50cwUBaQkAzQgCBQNhY2MJAKQDAQkAZAIJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQpjdXJyZW50UmVzBQFpBQlyZXNPZlR5cGUEAXIKAAIkbAkAzAgCAAAJAMwIAgABCQDMCAIAAgkAzAgCAAMJAMwIAgAECQDMCAIABQUDbmlsCgACJHMJAJADAQUCJGwKAAUkYWNjMAUDbmlsCgEFJGYwXzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAQVhZGRlcgIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmMF8yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQITTGlzdCBzaXplIGV4Y2VlZHMgNgkBBSRmMF8yAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgUFJGFjYzAAAAABAAIAAwAEAAUABgkAuQkCBQFyAgFfCAFpAQlzdGFrZUxhbmQABANwbXQJAQV2YWx1ZQEJAJEDAggFAWkIcGF5bWVudHMAAAQHYXNzZXRJZAkBBXZhbHVlAQgFA3BtdAdhc3NldElkBAdhZGRyZXNzCQClCAEIBQFpBmNhbGxlcgMJAQIhPQIIBQNwbXQGYW1vdW50AAEJAAIBCQCsAgIJAKwCAgIETkZUIAUKTEFORFBSRUZJWAIkIHRva2VuIHNob3VsZCBiZSBhdHRhY2hlZCBhcyBwYXltZW50BAVhc3NldAkBBXZhbHVlAQkA7AcBBQdhc3NldElkAwkBAiE9AggFBWFzc2V0Bmlzc3VlcgUEdGhpcwkAAgECF1Vua25vd24gaXNzdWVyIG9mIHRva2VuAwkBASEBCQEIY29udGFpbnMCCAUFYXNzZXQEbmFtZQUKTEFORFBSRUZJWAkAAgEJAKwCAgkArAICAglPbmx5IE5GVCAFCkxBTkRQUkVGSVgCFCB0b2tlbnMgYXJlIGFjY2VwdGVkBAtsYW5kTnVtU2l6ZQkAsAICCAUFYXNzZXQEbmFtZQAEBAdsYW5kTnVtAwkBCGNvbnRhaW5zAgULbGFuZE51bVNpemUCA1hYTAkAswICBQtsYW5kTnVtU2l6ZQADAwkBCGNvbnRhaW5zAgULbGFuZE51bVNpemUCAlhMCQCzAgIFC2xhbmROdW1TaXplAAIJALMCAgULbGFuZE51bVNpemUAAQMJAQEhAQkBCWlzRGVmaW5lZAEJALYJAQUHbGFuZE51bQkAAgEJAKwCAgIeQ2Fubm90IHBhcnNlIGxhbmQgbnVtYmVyIGZyb20gCAUFYXNzZXQEbmFtZQQHdGltZUtleQkBFmtleVN0YWtlZFRpbWVCeUFzc2V0SWQBCQDYBAEFB2Fzc2V0SWQDCQEJaXNEZWZpbmVkAQkAnwgBBQd0aW1lS2V5CQACAQkArAICCQCsAgICBE5GVCAIBQVhc3NldARuYW1lAhIgaXMgYWxyZWFkeSBzdGFrZWQJAMwIAgkBDEludGVnZXJFbnRyeQIFB3RpbWVLZXkIBQlsYXN0QmxvY2sJdGltZXN0YW1wCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEia2V5U3Rha2VkVGltZUJ5VHlwZUFzc2V0SWRBbmRPd25lcgMFCkxBTkRQUkVGSVgJANgEAQUHYXNzZXRJZAUHYWRkcmVzcwgFCWxhc3RCbG9jawl0aW1lc3RhbXAJAMwIAgkBC1N0cmluZ0VudHJ5AgkBEWtleUFzc2V0SWRUb093bmVyAQkA2AQBBQdhc3NldElkBQdhZGRyZXNzCQDMCAIJAQtTdHJpbmdFbnRyeQIJAQ5rZXlMYW5kVG9Pd25lcgEFB2xhbmROdW0FB2FkZHJlc3MFA25pbAFpAQt1bnN0YWtlTGFuZAELbGFuZEFzc2V0SWQDCQECIT0CCQCQAwEIBQFpCHBheW1lbnRzAAAJAAIBAiR1bnN0YWtlIGRvZXNuJ3QgcmVxdWlyZSBhbnkgcGF5bWVudHMEB2Fzc2V0SWQJANkEAQULbGFuZEFzc2V0SWQEB2FkZHJlc3MJAKUIAQgFAWkGY2FsbGVyBAVhc3NldAkBBXZhbHVlAQkA7AcBBQdhc3NldElkAwkBAiE9AggFBWFzc2V0Bmlzc3VlcgUEdGhpcwkAAgECF1Vua25vd24gaXNzdWVyIG9mIHRva2VuAwkBASEBCQEIY29udGFpbnMCCAUFYXNzZXQEbmFtZQUKTEFORFBSRUZJWAkAAgEJAKwCAgkArAICAglPbmx5IE5GVCAFCkxBTkRQUkVGSVgCFyB0b2tlbnMgY2FuIGJlIHVuc3Rha2VkBAd0aW1lS2V5CQEWa2V5U3Rha2VkVGltZUJ5QXNzZXRJZAEFC2xhbmRBc3NldElkAwkBASEBCQEJaXNEZWZpbmVkAQUHdGltZUtleQkAAgEJAKwCAgkArAICAgRORlQgCAUFYXNzZXQEbmFtZQIOIGlzIG5vdCBzdGFrZWQEBW93bmVyCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKIIAQkBEWtleUFzc2V0SWRUb093bmVyAQULbGFuZEFzc2V0SWQJAKwCAgkArAICAgRORlQgCAUFYXNzZXQEbmFtZQIMIGlzIG9ycGhhbmVkAwkBAiE9AgUFb3duZXIFB2FkZHJlc3MJAAIBAhdTdGFrZWQgTkZUIGlzIG5vdCB5b3VycwkAzAgCCQEOU2NyaXB0VHJhbnNmZXIDCAUBaQZjYWxsZXIAAQUHYXNzZXRJZAkAzAgCCQELRGVsZXRlRW50cnkBBQd0aW1lS2V5CQDMCAIJAQtEZWxldGVFbnRyeQEJASJrZXlTdGFrZWRUaW1lQnlUeXBlQXNzZXRJZEFuZE93bmVyAwUKTEFORFBSRUZJWAULbGFuZEFzc2V0SWQFB2FkZHJlc3MFA25pbAFpAQlzdGFrZUR1Y2sABANwbXQJAQV2YWx1ZQEJAJEDAggFAWkIcGF5bWVudHMAAAQHYXNzZXRJZAkBBXZhbHVlAQgFA3BtdAdhc3NldElkBAdhZGRyZXNzCQClCAEIBQFpBmNhbGxlcgMJAQIhPQIIBQNwbXQGYW1vdW50AAEJAAIBCQCsAgIJAKwCAgIETkZUIAUKRFVDS1BSRUZJWAIkIHRva2VuIHNob3VsZCBiZSBhdHRhY2hlZCBhcyBwYXltZW50BAVhc3NldAkBBXZhbHVlAQkA7AcBBQdhc3NldElkAwMJAQIhPQIIBQVhc3NldAZpc3N1ZXIFDWluY3ViYXRvckFkZHIJAQIhPQIIBQVhc3NldAZpc3N1ZXIFC2JyZWVkZXJBZGRyBwkAAgEJAKwCAgkArAICAhJVbmtub3duIGlzc3VlciBvZiAFCkRVQ0tQUkVGSVgCBiB0b2tlbgMJAQEhAQkBCGNvbnRhaW5zAggFBWFzc2V0BG5hbWUFCkRVQ0tQUkVGSVgJAAIBCQCsAgIJAKwCAgIJT25seSBORlQgBQpEVUNLUFJFRklYAhQgdG9rZW5zIGFyZSBhY2NlcHRlZAQKYXNzZXRJZFN0cgkA2AQBBQdhc3NldElkBAd0aW1lS2V5CQEWa2V5U3Rha2VkVGltZUJ5QXNzZXRJZAEFCmFzc2V0SWRTdHIDCQEJaXNEZWZpbmVkAQkAnwgBBQd0aW1lS2V5CQACAQkArAICCQCsAgICBE5GVCAIBQVhc3NldARuYW1lAhIgaXMgYWxyZWFkeSBzdGFrZWQDCQEJaXNEZWZpbmVkAQkAoggBCQEUa2V5U3Rha2VkRHVja0J5T3duZXIBBQdhZGRyZXNzCQACAQkArAICAh1Zb3UgYWxyZWFkeSBzdGFrZWQgb25lIGR1Y2s6IAgFBWFzc2V0BG5hbWUEBmxvY0tleQkBD2tleUR1Y2tMb2NhdGlvbgEFCmFzc2V0SWRTdHIECGxvY2F0aW9uCQCiCAEFBmxvY0tleQQJa2V5SGVhbHRoCQENa2V5RHVja0hlYWx0aAEFCmFzc2V0SWRTdHIEBmhlYWx0aAkAnwgBBQlrZXlIZWFsdGgEBWJwS2V5CQERa2V5QmFja3BhY2tCeUR1Y2sBBQphc3NldElkU3RyBAhiYWNrcGFjawkAoggBBQVicEtleQkAzggCCQDMCAIJAQxJbnRlZ2VyRW50cnkCBQd0aW1lS2V5CAUJbGFzdEJsb2NrCXRpbWVzdGFtcAkAzAgCCQEMSW50ZWdlckVudHJ5AgkBImtleVN0YWtlZFRpbWVCeVR5cGVBc3NldElkQW5kT3duZXIDBQpEVUNLUFJFRklYCQDYBAEFB2Fzc2V0SWQFB2FkZHJlc3MIBQlsYXN0QmxvY2sJdGltZXN0YW1wCQDMCAIJAQtTdHJpbmdFbnRyeQIJARBrZXlEdWNrSWRUb093bmVyAQUKYXNzZXRJZFN0cgUHYWRkcmVzcwkAzAgCCQELU3RyaW5nRW50cnkCCQEUa2V5U3Rha2VkRHVja0J5T3duZXIBBQdhZGRyZXNzBQphc3NldElkU3RyBQNuaWwDCQEJaXNEZWZpbmVkAQUIbG9jYXRpb24FA25pbAkAzggCCQDMCAIJAQtTdHJpbmdFbnRyeQIFBmxvY0tleQUPREVGQVVMVExPQ0FUSU9OBQNuaWwDCQEJaXNEZWZpbmVkAQUGaGVhbHRoBQNuaWwJAM4IAgkAzAgCCQEMSW50ZWdlckVudHJ5AgUJa2V5SGVhbHRoAGQFA25pbAMJAQlpc0RlZmluZWQBBQhiYWNrcGFjawUDbmlsCQDMCAIJAQtTdHJpbmdFbnRyeQIFBWJwS2V5Ag8wOjBfMF8wXzBfMF8wOjoFA25pbAFpAQt1bnN0YWtlRHVjawEKYXNzZXRJZFN0cgMJAQIhPQIJAJADAQgFAWkIcGF5bWVudHMAAAkAAgECJHVuc3Rha2UgZG9lc24ndCByZXF1aXJlIGFueSBwYXltZW50cwQHYXNzZXRJZAkA2QQBBQphc3NldElkU3RyBAdhZGRyZXNzCQClCAEIBQFpBmNhbGxlcgQFYXNzZXQJAQV2YWx1ZQEJAOwHAQUHYXNzZXRJZAMDCQECIT0CCAUFYXNzZXQGaXNzdWVyBQ1pbmN1YmF0b3JBZGRyCQECIT0CCAUFYXNzZXQGaXNzdWVyBQticmVlZGVyQWRkcgcJAAIBCQCsAgIJAKwCAgISVW5rbm93biBpc3N1ZXIgb2YgBQpEVUNLUFJFRklYAgYgdG9rZW4DCQEBIQEJAQhjb250YWlucwIIBQVhc3NldARuYW1lBQpEVUNLUFJFRklYCQACAQkArAICCQCsAgICCU9ubHkgTkZUIAUKRFVDS1BSRUZJWAIXIHRva2VucyBjYW4gYmUgdW5zdGFrZWQEB3RpbWVLZXkJARZrZXlTdGFrZWRUaW1lQnlBc3NldElkAQkA2AQBBQdhc3NldElkAwkBASEBCQEJaXNEZWZpbmVkAQUHdGltZUtleQkAAgEJAKwCAgkArAICAgRORlQgCAUFYXNzZXQEbmFtZQIOIGlzIG5vdCBzdGFrZWQDCQEBIQEJAQlpc0RlZmluZWQBCQEUa2V5U3Rha2VkRHVja0J5T3duZXIBBQdhZGRyZXNzCQACAQkArAICCQCsAgICCVRoZSBkdWNrIAgFBWFzc2V0BG5hbWUCDiBpcyBub3Qgc3Rha2VkBAVvd25lcgkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCiCAEJARBrZXlEdWNrSWRUb093bmVyAQkA2AQBBQdhc3NldElkCQCsAgIJAKwCAgIETkZUIAgFBWFzc2V0BG5hbWUCDCBpcyBvcnBoYW5lZAMJAQIhPQIFBW93bmVyBQdhZGRyZXNzCQACAQIXU3Rha2VkIE5GVCBpcyBub3QgeW91cnMJAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwgFAWkGY2FsbGVyAAEFB2Fzc2V0SWQJAMwIAgkBC0RlbGV0ZUVudHJ5AQUHdGltZUtleQkAzAgCCQELRGVsZXRlRW50cnkBCQEPa2V5RHVja0xvY2F0aW9uAQUKYXNzZXRJZFN0cgkAzAgCCQELRGVsZXRlRW50cnkBCQEia2V5U3Rha2VkVGltZUJ5VHlwZUFzc2V0SWRBbmRPd25lcgMFCkRVQ0tQUkVGSVgFCmFzc2V0SWRTdHIFB2FkZHJlc3MJAMwIAgkBC0RlbGV0ZUVudHJ5AQkBFGtleVN0YWtlZER1Y2tCeU93bmVyAQUHYWRkcmVzcwUDbmlsAWkBCGNsYWltUmVzAgZhbW91bnQLbGFuZEFzc2V0SWQDCQECIT0CCQCQAwEIBQFpCHBheW1lbnRzAAAJAAIBAiVjbGFpbVJlcyBkb2Vzbid0IHJlcXVpcmUgYW55IHBheW1lbnRzBARhZGRyCQClCAEIBQFpBmNhbGxlcgQFYXNzZXQJAQV2YWx1ZQEJAOwHAQkA2QQBBQtsYW5kQXNzZXRJZAMJAQEhAQkBCGNvbnRhaW5zAggFBWFzc2V0BG5hbWUFCkxBTkRQUkVGSVgJAAIBCQCsAgIJAKwCAgIETkZUIAUKTEFORFBSRUZJWAIgIHRva2VuIHNob3VsZCBiZSBwYXNzZWQgYXMgcGFyYW0EB3RpbWVLZXkJARZrZXlTdGFrZWRUaW1lQnlBc3NldElkAQULbGFuZEFzc2V0SWQECXNhdmVkVGltZQkAnwgBBQd0aW1lS2V5AwkBASEBCQEJaXNEZWZpbmVkAQUJc2F2ZWRUaW1lCQACAQkArAICCQCsAgICBE5GVCAIBQVhc3NldARuYW1lAg4gaXMgbm90IHN0YWtlZAQFb3duZXIJARFAZXh0ck5hdGl2ZSgxMDU4KQEJARFrZXlBc3NldElkVG9Pd25lcgEFC2xhbmRBc3NldElkAwkBAiE9AgUFb3duZXIFBGFkZHIJAAIBCQCsAgIFCkxBTkRQUkVGSVgCDSBpcyBub3QgeW91cnMEAWQJALUJAggFBWFzc2V0C2Rlc2NyaXB0aW9uAgFfBAhsYW5kU2l6ZQkAkQMCBQFkBQtyZWNMYW5kU2l6ZQQNdGVycmFpbkNvdW50cwkBDWNvdW50VGVycmFpbnMBCQCRAwIFAWQFC3JlY1RlcnJhaW5zBARkdWNrCQCiCAEJARRrZXlTdGFrZWREdWNrQnlPd25lcgEFBGFkZHIDCQEBIQEJAQlpc0RlZmluZWQBBQRkdWNrCQACAQIcWW91IGRvbid0IGhhdmUgYSBkdWNrIHN0YWtlZAQOZHVja0Fzc2V0SWRTdHIJAQV2YWx1ZQEFBGR1Y2sEC2N1ckxvY2F0aW9uCQELdmFsdWVPckVsc2UCCQCiCAEJAQ9rZXlEdWNrTG9jYXRpb24BBQ5kdWNrQXNzZXRJZFN0cgUPREVGQVVMVExPQ0FUSU9OBANsb2MJALUJAgkBBXZhbHVlAQULY3VyTG9jYXRpb24CAV8DCQECIT0CCQCRAwIFA2xvYwUKbG9jSWR4VHlwZQIBTAkAAgEJAKwCAgkArAICAhZEdWNrIGxvY2F0aW9uIHR5cGUgaXMgCQCRAwIFA2xvYwUKbG9jSWR4VHlwZQIRLCBidXQgc2hvdWxkIGJlIEwDCQECIT0CCQCRAwIFA2xvYwUIbG9jSWR4SWQFC2xhbmRBc3NldElkCQACAQkArAICCQCsAgIJAKwCAgIURHVjayBsb2NhdGlvbiBpZCBpcyAJAJEDAgUDbG9jBQhsb2NJZHhJZAIQLCBidXQgc2hvdWxkIGJlIAULbGFuZEFzc2V0SWQECWRlbHRhVGltZQkAZQIIBQlsYXN0QmxvY2sJdGltZXN0YW1wCQEFdmFsdWUBBQlzYXZlZFRpbWUDCQBmAgAABQlkZWx0YVRpbWUJAAIBCQCsAgIJAKwCAgkArAICAiZTYXZlZCB0aW1lc3RhbXAgaXMgaW4gZnV0dXJlLCBzYXZlZCA9IAkApAMBCQEFdmFsdWUBBQlzYXZlZFRpbWUCDCwgY3VycmVudCA9IAkApAMBCAUJbGFzdEJsb2NrCXRpbWVzdGFtcAQGcGllY2VzCQEPbnVtUGllY2VzQnlTaXplAQUIbGFuZFNpemUECGF2YWlsUmVzCQBoAgkAawMFCWRlbHRhVGltZQUPREFJTFlSRVNCWVBJRUNFBQlEQVlNSUxMSVMFBnBpZWNlcwMJAGYCBQZhbW91bnQFCGF2YWlsUmVzCQACAQkArAICCQCsAgIJAKwCAgIiTm90IGVub3VnaCByZXNvdXJjZXMsIGF2YWlsYWJsZSA9IAkApAMBBQhhdmFpbFJlcwIOLCByZXF1ZXN0ZWQgPSAJAKQDAQUGYW1vdW50BAxuZXdEZWx0YVRpbWUJAGsDCQBlAgUIYXZhaWxSZXMFBmFtb3VudAUJREFZTUlMTElTCQBoAgUGcGllY2VzBQ9EQUlMWVJFU0JZUElFQ0UEDG5ld1RpbWVzdGFtcAkAZQIIBQlsYXN0QmxvY2sJdGltZXN0YW1wBQxuZXdEZWx0YVRpbWUEBWJwS2V5CQERa2V5QmFja3BhY2tCeUR1Y2sBBQ5kdWNrQXNzZXRJZFN0cgQLY3VycmVudFBhY2sJALUJAgkBC3ZhbHVlT3JFbHNlAgkAoggBBQVicEtleQIPMDowXzBfMF8wXzBfMDo6AgE6BApjdXJyZW50UmVzCQC1CQIJAJEDAgULY3VycmVudFBhY2sFCGJwSWR4UmVzAgFfBAVicFJlcwkBBmFkZFJlcwMFCmN1cnJlbnRSZXMFDXRlcnJhaW5Db3VudHMJAGUCBQlkZWx0YVRpbWUFDG5ld0RlbHRhVGltZQQHbmV3UGFjawkAuQkCCQDMCAIJAJEDAgULY3VycmVudFBhY2sFCmJwSWR4TGV2ZWwJAMwIAgUFYnBSZXMJAMwIAgkAkQMCBQtjdXJyZW50UGFjawUIYnBJZHhNYXQJAMwIAgkAkQMCBQtjdXJyZW50UGFjawUJYnBJZHhQcm9kBQNuaWwCAToJAJQKAgkAzAgCCQELU3RyaW5nRW50cnkCBQVicEtleQUHbmV3UGFjawkAzAgCCQEMSW50ZWdlckVudHJ5AgUHdGltZUtleQUMbmV3VGltZXN0YW1wCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEia2V5U3Rha2VkVGltZUJ5VHlwZUFzc2V0SWRBbmRPd25lcgMFCkxBTkRQUkVGSVgFC2xhbmRBc3NldElkBQVvd25lcgUMbmV3VGltZXN0YW1wBQNuaWwFBHVuaXQBaQEGZmxpZ2h0AgdtZXNzYWdlA3NpZwMJAQEhAQkAxBMDBQdtZXNzYWdlBQNzaWcFA3B1YgkAAgECGHNpZ25hdHVyZSBkb2VzIG5vdCBtYXRjaAMJAQIhPQIJAJADAQgFAWkIcGF5bWVudHMAAAkAAgECI2ZsaWdodCBkb2Vzbid0IHJlcXVpcmUgYW55IHBheW1lbnRzBAVwYXJ0cwkAtQkCCQCwCQEFB21lc3NhZ2UCATsEAmhwCQC1CQIJAJEDAgkAtQkCCQCRAwIFBXBhcnRzAAACAXwAAAIBXwQFY3VySFAJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQJocAAABAVuZXdIUAkBDXBhcnNlSW50VmFsdWUBCQCRAwIFAmhwAAEEDW5ld0xvY0FuZFRpbWUJALUJAgkAkQMCBQVwYXJ0cwABAgE6BAtuZXdMb2NhdGlvbgkAkQMCBQ1uZXdMb2NBbmRUaW1lAAAEBHRpbWUJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQ1uZXdMb2NBbmRUaW1lAAEDAwkAZgIFBHRpbWUJAGQCCAUJbGFzdEJsb2NrCXRpbWVzdGFtcAURRklWRU1JTlVURVNNSUxMSVMGCQBmAgkAZQIIBQlsYXN0QmxvY2sJdGltZXN0YW1wBRFGSVZFTUlOVVRFU01JTExJUwUEdGltZQkAAgECEnNpZ25hdHVyZSBvdXRkYXRlZAQLZHVja0Fzc2V0SWQJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAoggBCQEUa2V5U3Rha2VkRHVja0J5T3duZXIBCQClCAEIBQFpBmNhbGxlcgIcWW91IGRvbid0IGhhdmUgYSBkdWNrIHN0YWtlZAQJa2V5SGVhbHRoCQENa2V5RHVja0hlYWx0aAEFC2R1Y2tBc3NldElkBAxvbGRGcm9tU3RhdGUJAQt2YWx1ZU9yRWxzZQIJAJ8IAQUJa2V5SGVhbHRoAGQDCQECIT0CBQxvbGRGcm9tU3RhdGUFBWN1ckhQCQACAQkArAICCQCsAgIJAKwCAgIKb2xkSGVhbHRoPQkApAMBCQELdmFsdWVPckVsc2UCCQCfCAEFCWtleUhlYWx0aABkAi8gZnJvbSBzdGF0ZSBkb2VzIG5vdCBtYXRjaCBvbmUgZnJvbSBmbGlnaHQgbG9nPQkApAMBBQVjdXJIUAMJAGcCAAAFBWN1ckhQCQACAQIeWW91IGNhbid0IGZseSB3aXRoIHplcm8gaGVhbHRoBAZsb2NLZXkJAQ9rZXlEdWNrTG9jYXRpb24BBQtkdWNrQXNzZXRJZAQLY3VyTG9jYXRpb24JAQt2YWx1ZU9yRWxzZQIJAKIIAQUGbG9jS2V5BQ9ERUZBVUxUTE9DQVRJT04DCQAAAgULbmV3TG9jYXRpb24FC2N1ckxvY2F0aW9uCQACAQIiWW91IGNhbid0IGZseSB0byB0aGUgc2FtZSBsb2NhdGlvbgkAlAoCCQDMCAIJAQtTdHJpbmdFbnRyeQIFBmxvY0tleQMJAGYCBQVuZXdIUAAABQtuZXdMb2NhdGlvbgULY3VyTG9jYXRpb24JAMwIAgkBDEludGVnZXJFbnRyeQIFCWtleUhlYWx0aAUFbmV3SFAFA25pbAUEdW5pdAFpAQlzZXRIZWFsdGgCBmhlYWx0aAtkdWNrQXNzZXRJZAQOZHVja0Fzc2V0SWRTdHIJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAoggBCQEUa2V5U3Rha2VkRHVja0J5T3duZXIBCQClCAEIBQFpBmNhbGxlcgIcWW91IGRvbid0IGhhdmUgYSBkdWNrIHN0YWtlZAMDCQBmAgAABQZoZWFsdGgGCQBmAgUGaGVhbHRoAGQJAAIBAhpIUCBzaG91bGQgYmUgd2l0aGluIDAuLjEwMAkAzAgCCQEMSW50ZWdlckVudHJ5AgkBDWtleUR1Y2tIZWFsdGgBBQtkdWNrQXNzZXRJZAUGaGVhbHRoBQNuaWwBaQEOdXBkYXRlQmFja3BhY2sCC2R1Y2tBc3NldElkB25ld1BhY2sDCQECIT0CCAUBaQZjYWxsZXIFC2Vjb25vbXlBZGRyCQACAQIRcGVybWlzc2lvbiBkZW5pZWQJAJQKAgkAzAgCCQELU3RyaW5nRW50cnkCCQERa2V5QmFja3BhY2tCeUR1Y2sBBQtkdWNrQXNzZXRJZAUHbmV3UGFjawUDbmlsBQduZXdQYWNrAGTcKf4=", "height": 3421834, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: AUF3WKjnuuh9u7oXNsaqw8mm1s7GhVRDSPcFvNdUKUvs Next: ADE5WWDHcWwh1kxhCyQq9Tt32t4RRHVEJ35yQUdUquxT Diff:
OldNewDifferences
11 {-# STDLIB_VERSION 6 #-}
22 {-# SCRIPT_TYPE ACCOUNT #-}
33 {-# CONTENT_TYPE DAPP #-}
4-let DEFAULTPRICES = 250000000
5-
6-let DEFAULTPRICEM = 1000000000
7-
8-let DEFAULTPRICEL = 2250000000
9-
10-let DEFAULTPRICEXL = 4000000000
11-
124 let usdnAssetId = base58'DG2xFkPdDwKUoBkzGAhQtLpSGzfXLiCYPEzeKH2Ad24p'
135
146 let incubatorAddr = addressFromStringValue("3PEktVux2RhchSN63DsDo4b4mz4QqzKSeDv")
179
1810 let backEndAddr = addressFromStringValue("3PBKeu78xdNyaKw5k2Ua6npqe8MRQegoq17")
1911
12+let economyAddr = addressFromStringValue("3P2sk1KncSxRaZs8b4CWGPw2jkvvav74u4D")
13+
14+let pub = base58'6LfPuKJjLgekmncBhMg2LZyMTNVzZBccXR28ySXm9uXD'
15+
2016 let LANDPREFIX = "LAND"
2117
2218 let DUCKPREFIX = "DUCK"
2319
24-let LENS = "sLen"
20+let DEFAULTLOCATION = "Africa_F_Africa"
2521
26-let LENM = "mLen"
22+let DAILYRESBYPIECE = 3456000
2723
28-let LENL = "lLen"
24+let DAYMILLIS = 86400000
2925
30-let LENXL = "xlLen"
31-
32-let MAPS = "sMap"
33-
34-let MAPM = "mMap"
35-
36-let MAPL = "lMap"
37-
38-let MAPXL = "xlMap"
39-
40-func keyPaymentRequired (landSize) = ("paymentRequired_" + landSize)
41-
42-
43-func keyLandToAssetId (landNum) = ("landToAsset_" + landNum)
44-
26+let FIVEMINUTESMILLIS = 300000
4527
4628 func keyAssetIdToOwner (assetId) = ("nftOwner_" + assetId)
4729
5840 func keyStakedTimeByTypeAssetIdAndOwner (nftType,assetId,ownerAddr) = ((((("stakedTimeByTypeAssetIdAndOwner_" + nftType) + "_") + assetId) + "_") + ownerAddr)
5941
6042
61-func keyFromContinentByAssetId (assetId) = ("fromContinent_" + assetId)
62-
63-
64-func keyToContinentByAssetId (assetId) = ("toContinent_" + assetId)
65-
66-
67-func keyWindsByAssetId (assetId) = ("winds_" + assetId)
68-
69-
70-func keyObstaclesByAssetId (assetId) = ("obstacles_" + assetId)
71-
72-
73-func keyMovesByAssetId (assetId) = ("userMoves_" + assetId)
74-
75-
7643 func keyLandToOwner (landNum) = ("landOwner_" + landNum)
7744
7845
79-func keyBatchesCount () = "batchesCount"
46+func keyBackpackByDuck (duckAssetId) = ("backPack_" + duckAssetId)
8047
8148
82-func keyBatchProcessed (batch) = ("batchOk_" + toString(batch))
49+func keyDuckLocation (duckAssetId) = ("duckLocation_" + duckAssetId)
8350
8451
85-func keyNftName (landNum,landSize) = ((LANDPREFIX + landNum) + landSize)
52+func keyDuckHealth (duckAssetId) = ("duckHealth_" + duckAssetId)
8653
8754
8855 let recLandNum = 0
9360
9461 let recContinent = 3
9562
96-func abs (x) = if ((x >= 0))
97- then x
98- else -(x)
63+let locIdxContinent = 0
64+
65+let locIdxType = 1
66+
67+let locIdxId = 2
68+
69+let bpIdxLevel = 0
70+
71+let bpIdxRes = 1
72+
73+let bpIdxMat = 2
74+
75+let bpIdxProd = 3
76+
77+let idxA = 0
78+
79+let idxB = 1
80+
81+let idxC = 2
82+
83+let idxD = 3
84+
85+let idxE = 4
86+
87+let idxF = 5
88+
89+func countTerrains (terrains) = [(size(split(terrains, "A")) - 1), (size(split(terrains, "B")) - 1), (size(split(terrains, "C")) - 1), (size(split(terrains, "D")) - 1), (size(split(terrains, "E")) - 1), (size(split(terrains, "F")) - 1)]
9990
10091
101-func buyInternal (pmt,txId,caller,landSize,lenKey,mapKey,defaultPrice) = if ((pmt.assetId != usdnAssetId))
102- then throw("Allowed USDN payment only!")
103- else {
104- let pmtReq = valueOrElse(getInteger(keyPaymentRequired(landSize)), defaultPrice)
105- if ((pmtReq > pmt.amount))
106- then throw(("Payment attached should be at least " + toString(pmtReq)))
107- else {
108- let len = valueOrErrorMessage(getInteger(lenKey), "initPresale should be called first")
109- if ((len == 0))
110- then throw((("All " + landSize) + " lands are sold out"))
111- else {
112- let random = abs(toInt((toBigInt(txId) % toBigInt(len))))
113- let lands = split_51C(valueOrErrorMessage(getString(mapKey), (mapKey + " is not initialized")), "_")
114- let landNum = lands[random]
115- let nft = valueOrErrorMessage(getString(keyLandToAssetId(landNum)), (keyNftName(landNum, landSize) + " does not exist"))
116-[IntegerEntry(lenKey, (len - 1)), StringEntry(mapKey, makeString_11C(removeByIndex(lands, random), "_")), ScriptTransfer(caller, 1, fromBase58String(nft)), StringEntry(keyAssetIdToOwner(nft), toString(caller)), StringEntry(keyLandToOwner(landNum), toString(caller))]
117- }
118- }
92+func numPiecesBySize (landSize) = match landSize {
93+ case _ =>
94+ if (("S" == $match0))
95+ then 25
96+ else if (("M" == $match0))
97+ then 100
98+ else if (("L" == $match0))
99+ then 225
100+ else if (("XL" == $match0))
101+ then 400
102+ else if (("XXL" == $match0))
103+ then 625
104+ else throw("Unknown land size")
105+}
106+
107+
108+func addRes (currentRes,terrainCounts,deltaTime) = {
109+ func adder (acc,i) = {
110+ let resOfType = (fraction(deltaTime, DAILYRESBYPIECE, DAYMILLIS) * terrainCounts[i])
111+ (acc :+ toString((parseIntValue(currentRes[i]) + resOfType)))
119112 }
113+
114+ let r = {
115+ let $l = [0, 1, 2, 3, 4, 5]
116+ let $s = size($l)
117+ let $acc0 = nil
118+ func $f0_1 ($a,$i) = if (($i >= $s))
119+ then $a
120+ else adder($a, $l[$i])
121+
122+ func $f0_2 ($a,$i) = if (($i >= $s))
123+ then $a
124+ else throw("List size exceeds 6")
125+
126+ $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6)
127+ }
128+ makeString(r, "_")
129+ }
120130
121131
122132 @Callable(i)
154164
155165
156166 @Callable(i)
157-func updateStakedLand (assetIdStr,newTimestamp) = if ((i.caller != backEndAddr))
158- then throw("permission denied")
159- else if ((size(i.payments) != 0))
160- then throw("updateStakedLand doesn't require any payments")
161- else {
162- let assetId = fromBase58String(assetIdStr)
163- let asset = value(assetInfo(assetId))
164- if ((asset.issuer != this))
165- then throw("Unknown issuer of token")
166- else if (!(contains(asset.name, LANDPREFIX)))
167- then throw((("Only NFT " + LANDPREFIX) + " tokens are accepted"))
168- else {
169- let timeKey = keyStakedTimeByAssetId(toBase58String(assetId))
170- if (!(isDefined(getInteger(timeKey))))
171- then throw((("NFT " + asset.name) + " is not staked"))
172- else {
173- let ownerAddr = getStringValue(keyAssetIdToOwner(assetIdStr))
174-[IntegerEntry(timeKey, newTimestamp), IntegerEntry(keyStakedTimeByTypeAssetIdAndOwner(LANDPREFIX, assetIdStr, ownerAddr), newTimestamp)]
175- }
176- }
177- }
178-
179-
180-
181-@Callable(i)
182-func unstakeLand (assetIdStr) = if ((size(i.payments) != 0))
167+func unstakeLand (landAssetId) = if ((size(i.payments) != 0))
183168 then throw("unstake doesn't require any payments")
184169 else {
185- let assetId = fromBase58String(assetIdStr)
170+ let assetId = fromBase58String(landAssetId)
186171 let address = toString(i.caller)
187172 let asset = value(assetInfo(assetId))
188173 if ((asset.issuer != this))
190175 else if (!(contains(asset.name, LANDPREFIX)))
191176 then throw((("Only NFT " + LANDPREFIX) + " tokens can be unstaked"))
192177 else {
193- let timeKey = keyStakedTimeByAssetId(assetIdStr)
178+ let timeKey = keyStakedTimeByAssetId(landAssetId)
194179 if (!(isDefined(timeKey)))
195180 then throw((("NFT " + asset.name) + " is not staked"))
196181 else {
197- let owner = valueOrErrorMessage(getString(keyAssetIdToOwner(assetIdStr)), (("NFT " + asset.name) + " is orphaned"))
182+ let owner = valueOrErrorMessage(getString(keyAssetIdToOwner(landAssetId)), (("NFT " + asset.name) + " is orphaned"))
198183 if ((owner != address))
199184 then throw("Staked NFT is not yours")
200- else [ScriptTransfer(i.caller, 1, assetId), DeleteEntry(timeKey), DeleteEntry(keyStakedTimeByTypeAssetIdAndOwner(LANDPREFIX, assetIdStr, address))]
185+ else [ScriptTransfer(i.caller, 1, assetId), DeleteEntry(timeKey), DeleteEntry(keyStakedTimeByTypeAssetIdAndOwner(LANDPREFIX, landAssetId, address))]
201186 }
202187 }
203188 }
226211 then throw((("NFT " + asset.name) + " is already staked"))
227212 else if (isDefined(getString(keyStakedDuckByOwner(address))))
228213 then throw(("You already staked one duck: " + asset.name))
229- else [IntegerEntry(timeKey, lastBlock.timestamp), IntegerEntry(keyStakedTimeByTypeAssetIdAndOwner(DUCKPREFIX, toBase58String(assetId), address), lastBlock.timestamp), StringEntry(keyDuckIdToOwner(assetIdStr), address), StringEntry(keyStakedDuckByOwner(address), assetIdStr)]
214+ else {
215+ let locKey = keyDuckLocation(assetIdStr)
216+ let location = getString(locKey)
217+ let keyHealth = keyDuckHealth(assetIdStr)
218+ let health = getInteger(keyHealth)
219+ let bpKey = keyBackpackByDuck(assetIdStr)
220+ let backpack = getString(bpKey)
221+ ([IntegerEntry(timeKey, lastBlock.timestamp), IntegerEntry(keyStakedTimeByTypeAssetIdAndOwner(DUCKPREFIX, toBase58String(assetId), address), lastBlock.timestamp), StringEntry(keyDuckIdToOwner(assetIdStr), address), StringEntry(keyStakedDuckByOwner(address), assetIdStr)] ++ (if (isDefined(location))
222+ then nil
223+ else ([StringEntry(locKey, DEFAULTLOCATION)] ++ (if (isDefined(health))
224+ then nil
225+ else ([IntegerEntry(keyHealth, 100)] ++ (if (isDefined(backpack))
226+ then nil
227+ else [StringEntry(bpKey, "0:0_0_0_0_0_0::")]))))))
228+ }
230229 }
231230 }
232231 }
256255 let owner = valueOrErrorMessage(getString(keyDuckIdToOwner(toBase58String(assetId))), (("NFT " + asset.name) + " is orphaned"))
257256 if ((owner != address))
258257 then throw("Staked NFT is not yours")
259- else [ScriptTransfer(i.caller, 1, assetId), DeleteEntry(timeKey), DeleteEntry(keyStakedTimeByTypeAssetIdAndOwner(DUCKPREFIX, assetIdStr, address)), DeleteEntry(keyStakedDuckByOwner(address))]
258+ else [ScriptTransfer(i.caller, 1, assetId), DeleteEntry(timeKey), DeleteEntry(keyDuckLocation(assetIdStr)), DeleteEntry(keyStakedTimeByTypeAssetIdAndOwner(DUCKPREFIX, assetIdStr, address)), DeleteEntry(keyStakedDuckByOwner(address))]
260259 }
261260 }
262261 }
264263
265264
266265 @Callable(i)
267-func buyLand (landSize) = if ((i.caller != this))
268- then throw("Permission denied")
269- else if ((size(i.payments) != 1))
270- then throw("Exactly one payment required")
266+func claimRes (amount,landAssetId) = if ((size(i.payments) != 0))
267+ then throw("claimRes doesn't require any payments")
268+ else {
269+ let addr = toString(i.caller)
270+ let asset = value(assetInfo(fromBase58String(landAssetId)))
271+ if (!(contains(asset.name, LANDPREFIX)))
272+ then throw((("NFT " + LANDPREFIX) + " token should be passed as param"))
273+ else {
274+ let timeKey = keyStakedTimeByAssetId(landAssetId)
275+ let savedTime = getInteger(timeKey)
276+ if (!(isDefined(savedTime)))
277+ then throw((("NFT " + asset.name) + " is not staked"))
278+ else {
279+ let owner = getStringValue(keyAssetIdToOwner(landAssetId))
280+ if ((owner != addr))
281+ then throw((LANDPREFIX + " is not yours"))
282+ else {
283+ let d = split(asset.description, "_")
284+ let landSize = d[recLandSize]
285+ let terrainCounts = countTerrains(d[recTerrains])
286+ let duck = getString(keyStakedDuckByOwner(addr))
287+ if (!(isDefined(duck)))
288+ then throw("You don't have a duck staked")
289+ else {
290+ let duckAssetIdStr = value(duck)
291+ let curLocation = valueOrElse(getString(keyDuckLocation(duckAssetIdStr)), DEFAULTLOCATION)
292+ let loc = split(value(curLocation), "_")
293+ if ((loc[locIdxType] != "L"))
294+ then throw((("Duck location type is " + loc[locIdxType]) + ", but should be L"))
295+ else if ((loc[locIdxId] != landAssetId))
296+ then throw(((("Duck location id is " + loc[locIdxId]) + ", but should be ") + landAssetId))
297+ else {
298+ let deltaTime = (lastBlock.timestamp - value(savedTime))
299+ if ((0 > deltaTime))
300+ then throw(((("Saved timestamp is in future, saved = " + toString(value(savedTime))) + ", current = ") + toString(lastBlock.timestamp)))
301+ else {
302+ let pieces = numPiecesBySize(landSize)
303+ let availRes = (fraction(deltaTime, DAILYRESBYPIECE, DAYMILLIS) * pieces)
304+ if ((amount > availRes))
305+ then throw(((("Not enough resources, available = " + toString(availRes)) + ", requested = ") + toString(amount)))
306+ else {
307+ let newDeltaTime = fraction((availRes - amount), DAYMILLIS, (pieces * DAILYRESBYPIECE))
308+ let newTimestamp = (lastBlock.timestamp - newDeltaTime)
309+ let bpKey = keyBackpackByDuck(duckAssetIdStr)
310+ let currentPack = split(valueOrElse(getString(bpKey), "0:0_0_0_0_0_0::"), ":")
311+ let currentRes = split(currentPack[bpIdxRes], "_")
312+ let bpRes = addRes(currentRes, terrainCounts, (deltaTime - newDeltaTime))
313+ let newPack = makeString([currentPack[bpIdxLevel], bpRes, currentPack[bpIdxMat], currentPack[bpIdxProd]], ":")
314+ $Tuple2([StringEntry(bpKey, newPack), IntegerEntry(timeKey, newTimestamp), IntegerEntry(keyStakedTimeByTypeAssetIdAndOwner(LANDPREFIX, landAssetId, owner), newTimestamp)], unit)
315+ }
316+ }
317+ }
318+ }
319+ }
320+ }
321+ }
322+ }
323+
324+
325+
326+@Callable(i)
327+func flight (message,sig) = if (!(sigVerify_8Kb(message, sig, pub)))
328+ then throw("signature does not match")
329+ else if ((size(i.payments) != 0))
330+ then throw("flight doesn't require any payments")
271331 else {
272- let pmt = value(i.payments[0])
273- let actions = match landSize {
274- case _ =>
275- if (("S" == $match0))
276- then buyInternal(pmt, i.transactionId, i.caller, landSize, LENS, MAPS, DEFAULTPRICES)
277- else if (("M" == $match0))
278- then buyInternal(pmt, i.transactionId, i.caller, landSize, LENM, MAPM, DEFAULTPRICEM)
279- else if (("L" == $match0))
280- then buyInternal(pmt, i.transactionId, i.caller, landSize, LENL, MAPL, DEFAULTPRICEL)
281- else if (("XL" == $match0))
282- then buyInternal(pmt, i.transactionId, i.caller, landSize, LENXL, MAPXL, DEFAULTPRICEXL)
283- else throw("Unknown land size")
332+ let parts = split(toUtf8String(message), ";")
333+ let hp = split(split(parts[0], "|")[0], "_")
334+ let curHP = parseIntValue(hp[0])
335+ let newHP = parseIntValue(hp[1])
336+ let newLocAndTime = split(parts[1], ":")
337+ let newLocation = newLocAndTime[0]
338+ let time = parseIntValue(newLocAndTime[1])
339+ if (if ((time > (lastBlock.timestamp + FIVEMINUTESMILLIS)))
340+ then true
341+ else ((lastBlock.timestamp - FIVEMINUTESMILLIS) > time))
342+ then throw("signature outdated")
343+ else {
344+ let duckAssetId = valueOrErrorMessage(getString(keyStakedDuckByOwner(toString(i.caller))), "You don't have a duck staked")
345+ let keyHealth = keyDuckHealth(duckAssetId)
346+ let oldFromState = valueOrElse(getInteger(keyHealth), 100)
347+ if ((oldFromState != curHP))
348+ then throw(((("oldHealth=" + toString(valueOrElse(getInteger(keyHealth), 100))) + " from state does not match one from flight log=") + toString(curHP)))
349+ else if ((0 >= curHP))
350+ then throw("You can't fly with zero health")
351+ else {
352+ let locKey = keyDuckLocation(duckAssetId)
353+ let curLocation = valueOrElse(getString(locKey), DEFAULTLOCATION)
354+ if ((newLocation == curLocation))
355+ then throw("You can't fly to the same location")
356+ else $Tuple2([StringEntry(locKey, if ((newHP > 0))
357+ then newLocation
358+ else curLocation), IntegerEntry(keyHealth, newHP)], unit)
359+ }
360+ }
284361 }
285- $Tuple2(actions, unit)
286- }
362+
363+
364+
365+@Callable(i)
366+func setHealth (health,duckAssetId) = {
367+ let duckAssetIdStr = valueOrErrorMessage(getString(keyStakedDuckByOwner(toString(i.caller))), "You don't have a duck staked")
368+ if (if ((0 > health))
369+ then true
370+ else (health > 100))
371+ then throw("HP should be within 0..100")
372+ else [IntegerEntry(keyDuckHealth(duckAssetId), health)]
373+ }
374+
375+
376+
377+@Callable(i)
378+func updateBackpack (duckAssetId,newPack) = if ((i.caller != economyAddr))
379+ then throw("permission denied")
380+ else $Tuple2([StringEntry(keyBackpackByDuck(duckAssetId), newPack)], newPack)
287381
288382
Full:
OldNewDifferences
11 {-# STDLIB_VERSION 6 #-}
22 {-# SCRIPT_TYPE ACCOUNT #-}
33 {-# CONTENT_TYPE DAPP #-}
4-let DEFAULTPRICES = 250000000
5-
6-let DEFAULTPRICEM = 1000000000
7-
8-let DEFAULTPRICEL = 2250000000
9-
10-let DEFAULTPRICEXL = 4000000000
11-
124 let usdnAssetId = base58'DG2xFkPdDwKUoBkzGAhQtLpSGzfXLiCYPEzeKH2Ad24p'
135
146 let incubatorAddr = addressFromStringValue("3PEktVux2RhchSN63DsDo4b4mz4QqzKSeDv")
157
168 let breederAddr = addressFromStringValue("3PDVuU45H7Eh5dmtNbnRNRStGwULA7NY6Hb")
179
1810 let backEndAddr = addressFromStringValue("3PBKeu78xdNyaKw5k2Ua6npqe8MRQegoq17")
1911
12+let economyAddr = addressFromStringValue("3P2sk1KncSxRaZs8b4CWGPw2jkvvav74u4D")
13+
14+let pub = base58'6LfPuKJjLgekmncBhMg2LZyMTNVzZBccXR28ySXm9uXD'
15+
2016 let LANDPREFIX = "LAND"
2117
2218 let DUCKPREFIX = "DUCK"
2319
24-let LENS = "sLen"
20+let DEFAULTLOCATION = "Africa_F_Africa"
2521
26-let LENM = "mLen"
22+let DAILYRESBYPIECE = 3456000
2723
28-let LENL = "lLen"
24+let DAYMILLIS = 86400000
2925
30-let LENXL = "xlLen"
31-
32-let MAPS = "sMap"
33-
34-let MAPM = "mMap"
35-
36-let MAPL = "lMap"
37-
38-let MAPXL = "xlMap"
39-
40-func keyPaymentRequired (landSize) = ("paymentRequired_" + landSize)
41-
42-
43-func keyLandToAssetId (landNum) = ("landToAsset_" + landNum)
44-
26+let FIVEMINUTESMILLIS = 300000
4527
4628 func keyAssetIdToOwner (assetId) = ("nftOwner_" + assetId)
4729
4830
4931 func keyDuckIdToOwner (assetId) = ("duckOwner_" + assetId)
5032
5133
5234 func keyStakedTimeByAssetId (assetId) = ("stakedTime_" + assetId)
5335
5436
5537 func keyStakedDuckByOwner (ownerAddr) = ("stakedDuckByOwner_" + ownerAddr)
5638
5739
5840 func keyStakedTimeByTypeAssetIdAndOwner (nftType,assetId,ownerAddr) = ((((("stakedTimeByTypeAssetIdAndOwner_" + nftType) + "_") + assetId) + "_") + ownerAddr)
5941
6042
61-func keyFromContinentByAssetId (assetId) = ("fromContinent_" + assetId)
62-
63-
64-func keyToContinentByAssetId (assetId) = ("toContinent_" + assetId)
65-
66-
67-func keyWindsByAssetId (assetId) = ("winds_" + assetId)
68-
69-
70-func keyObstaclesByAssetId (assetId) = ("obstacles_" + assetId)
71-
72-
73-func keyMovesByAssetId (assetId) = ("userMoves_" + assetId)
74-
75-
7643 func keyLandToOwner (landNum) = ("landOwner_" + landNum)
7744
7845
79-func keyBatchesCount () = "batchesCount"
46+func keyBackpackByDuck (duckAssetId) = ("backPack_" + duckAssetId)
8047
8148
82-func keyBatchProcessed (batch) = ("batchOk_" + toString(batch))
49+func keyDuckLocation (duckAssetId) = ("duckLocation_" + duckAssetId)
8350
8451
85-func keyNftName (landNum,landSize) = ((LANDPREFIX + landNum) + landSize)
52+func keyDuckHealth (duckAssetId) = ("duckHealth_" + duckAssetId)
8653
8754
8855 let recLandNum = 0
8956
9057 let recLandSize = 1
9158
9259 let recTerrains = 2
9360
9461 let recContinent = 3
9562
96-func abs (x) = if ((x >= 0))
97- then x
98- else -(x)
63+let locIdxContinent = 0
64+
65+let locIdxType = 1
66+
67+let locIdxId = 2
68+
69+let bpIdxLevel = 0
70+
71+let bpIdxRes = 1
72+
73+let bpIdxMat = 2
74+
75+let bpIdxProd = 3
76+
77+let idxA = 0
78+
79+let idxB = 1
80+
81+let idxC = 2
82+
83+let idxD = 3
84+
85+let idxE = 4
86+
87+let idxF = 5
88+
89+func countTerrains (terrains) = [(size(split(terrains, "A")) - 1), (size(split(terrains, "B")) - 1), (size(split(terrains, "C")) - 1), (size(split(terrains, "D")) - 1), (size(split(terrains, "E")) - 1), (size(split(terrains, "F")) - 1)]
9990
10091
101-func buyInternal (pmt,txId,caller,landSize,lenKey,mapKey,defaultPrice) = if ((pmt.assetId != usdnAssetId))
102- then throw("Allowed USDN payment only!")
103- else {
104- let pmtReq = valueOrElse(getInteger(keyPaymentRequired(landSize)), defaultPrice)
105- if ((pmtReq > pmt.amount))
106- then throw(("Payment attached should be at least " + toString(pmtReq)))
107- else {
108- let len = valueOrErrorMessage(getInteger(lenKey), "initPresale should be called first")
109- if ((len == 0))
110- then throw((("All " + landSize) + " lands are sold out"))
111- else {
112- let random = abs(toInt((toBigInt(txId) % toBigInt(len))))
113- let lands = split_51C(valueOrErrorMessage(getString(mapKey), (mapKey + " is not initialized")), "_")
114- let landNum = lands[random]
115- let nft = valueOrErrorMessage(getString(keyLandToAssetId(landNum)), (keyNftName(landNum, landSize) + " does not exist"))
116-[IntegerEntry(lenKey, (len - 1)), StringEntry(mapKey, makeString_11C(removeByIndex(lands, random), "_")), ScriptTransfer(caller, 1, fromBase58String(nft)), StringEntry(keyAssetIdToOwner(nft), toString(caller)), StringEntry(keyLandToOwner(landNum), toString(caller))]
117- }
118- }
92+func numPiecesBySize (landSize) = match landSize {
93+ case _ =>
94+ if (("S" == $match0))
95+ then 25
96+ else if (("M" == $match0))
97+ then 100
98+ else if (("L" == $match0))
99+ then 225
100+ else if (("XL" == $match0))
101+ then 400
102+ else if (("XXL" == $match0))
103+ then 625
104+ else throw("Unknown land size")
105+}
106+
107+
108+func addRes (currentRes,terrainCounts,deltaTime) = {
109+ func adder (acc,i) = {
110+ let resOfType = (fraction(deltaTime, DAILYRESBYPIECE, DAYMILLIS) * terrainCounts[i])
111+ (acc :+ toString((parseIntValue(currentRes[i]) + resOfType)))
119112 }
113+
114+ let r = {
115+ let $l = [0, 1, 2, 3, 4, 5]
116+ let $s = size($l)
117+ let $acc0 = nil
118+ func $f0_1 ($a,$i) = if (($i >= $s))
119+ then $a
120+ else adder($a, $l[$i])
121+
122+ func $f0_2 ($a,$i) = if (($i >= $s))
123+ then $a
124+ else throw("List size exceeds 6")
125+
126+ $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6)
127+ }
128+ makeString(r, "_")
129+ }
120130
121131
122132 @Callable(i)
123133 func stakeLand () = {
124134 let pmt = value(i.payments[0])
125135 let assetId = value(pmt.assetId)
126136 let address = toString(i.caller)
127137 if ((pmt.amount != 1))
128138 then throw((("NFT " + LANDPREFIX) + " token should be attached as payment"))
129139 else {
130140 let asset = value(assetInfo(assetId))
131141 if ((asset.issuer != this))
132142 then throw("Unknown issuer of token")
133143 else if (!(contains(asset.name, LANDPREFIX)))
134144 then throw((("Only NFT " + LANDPREFIX) + " tokens are accepted"))
135145 else {
136146 let landNumSize = drop(asset.name, 4)
137147 let landNum = if (contains(landNumSize, "XXL"))
138148 then dropRight(landNumSize, 3)
139149 else if (contains(landNumSize, "XL"))
140150 then dropRight(landNumSize, 2)
141151 else dropRight(landNumSize, 1)
142152 if (!(isDefined(parseInt(landNum))))
143153 then throw(("Cannot parse land number from " + asset.name))
144154 else {
145155 let timeKey = keyStakedTimeByAssetId(toBase58String(assetId))
146156 if (isDefined(getInteger(timeKey)))
147157 then throw((("NFT " + asset.name) + " is already staked"))
148158 else [IntegerEntry(timeKey, lastBlock.timestamp), IntegerEntry(keyStakedTimeByTypeAssetIdAndOwner(LANDPREFIX, toBase58String(assetId), address), lastBlock.timestamp), StringEntry(keyAssetIdToOwner(toBase58String(assetId)), address), StringEntry(keyLandToOwner(landNum), address)]
149159 }
150160 }
151161 }
152162 }
153163
154164
155165
156166 @Callable(i)
157-func updateStakedLand (assetIdStr,newTimestamp) = if ((i.caller != backEndAddr))
158- then throw("permission denied")
159- else if ((size(i.payments) != 0))
160- then throw("updateStakedLand doesn't require any payments")
161- else {
162- let assetId = fromBase58String(assetIdStr)
163- let asset = value(assetInfo(assetId))
164- if ((asset.issuer != this))
165- then throw("Unknown issuer of token")
166- else if (!(contains(asset.name, LANDPREFIX)))
167- then throw((("Only NFT " + LANDPREFIX) + " tokens are accepted"))
168- else {
169- let timeKey = keyStakedTimeByAssetId(toBase58String(assetId))
170- if (!(isDefined(getInteger(timeKey))))
171- then throw((("NFT " + asset.name) + " is not staked"))
172- else {
173- let ownerAddr = getStringValue(keyAssetIdToOwner(assetIdStr))
174-[IntegerEntry(timeKey, newTimestamp), IntegerEntry(keyStakedTimeByTypeAssetIdAndOwner(LANDPREFIX, assetIdStr, ownerAddr), newTimestamp)]
175- }
176- }
177- }
178-
179-
180-
181-@Callable(i)
182-func unstakeLand (assetIdStr) = if ((size(i.payments) != 0))
167+func unstakeLand (landAssetId) = if ((size(i.payments) != 0))
183168 then throw("unstake doesn't require any payments")
184169 else {
185- let assetId = fromBase58String(assetIdStr)
170+ let assetId = fromBase58String(landAssetId)
186171 let address = toString(i.caller)
187172 let asset = value(assetInfo(assetId))
188173 if ((asset.issuer != this))
189174 then throw("Unknown issuer of token")
190175 else if (!(contains(asset.name, LANDPREFIX)))
191176 then throw((("Only NFT " + LANDPREFIX) + " tokens can be unstaked"))
192177 else {
193- let timeKey = keyStakedTimeByAssetId(assetIdStr)
178+ let timeKey = keyStakedTimeByAssetId(landAssetId)
194179 if (!(isDefined(timeKey)))
195180 then throw((("NFT " + asset.name) + " is not staked"))
196181 else {
197- let owner = valueOrErrorMessage(getString(keyAssetIdToOwner(assetIdStr)), (("NFT " + asset.name) + " is orphaned"))
182+ let owner = valueOrErrorMessage(getString(keyAssetIdToOwner(landAssetId)), (("NFT " + asset.name) + " is orphaned"))
198183 if ((owner != address))
199184 then throw("Staked NFT is not yours")
200- else [ScriptTransfer(i.caller, 1, assetId), DeleteEntry(timeKey), DeleteEntry(keyStakedTimeByTypeAssetIdAndOwner(LANDPREFIX, assetIdStr, address))]
185+ else [ScriptTransfer(i.caller, 1, assetId), DeleteEntry(timeKey), DeleteEntry(keyStakedTimeByTypeAssetIdAndOwner(LANDPREFIX, landAssetId, address))]
201186 }
202187 }
203188 }
204189
205190
206191
207192 @Callable(i)
208193 func stakeDuck () = {
209194 let pmt = value(i.payments[0])
210195 let assetId = value(pmt.assetId)
211196 let address = toString(i.caller)
212197 if ((pmt.amount != 1))
213198 then throw((("NFT " + DUCKPREFIX) + " token should be attached as payment"))
214199 else {
215200 let asset = value(assetInfo(assetId))
216201 if (if ((asset.issuer != incubatorAddr))
217202 then (asset.issuer != breederAddr)
218203 else false)
219204 then throw((("Unknown issuer of " + DUCKPREFIX) + " token"))
220205 else if (!(contains(asset.name, DUCKPREFIX)))
221206 then throw((("Only NFT " + DUCKPREFIX) + " tokens are accepted"))
222207 else {
223208 let assetIdStr = toBase58String(assetId)
224209 let timeKey = keyStakedTimeByAssetId(assetIdStr)
225210 if (isDefined(getInteger(timeKey)))
226211 then throw((("NFT " + asset.name) + " is already staked"))
227212 else if (isDefined(getString(keyStakedDuckByOwner(address))))
228213 then throw(("You already staked one duck: " + asset.name))
229- else [IntegerEntry(timeKey, lastBlock.timestamp), IntegerEntry(keyStakedTimeByTypeAssetIdAndOwner(DUCKPREFIX, toBase58String(assetId), address), lastBlock.timestamp), StringEntry(keyDuckIdToOwner(assetIdStr), address), StringEntry(keyStakedDuckByOwner(address), assetIdStr)]
214+ else {
215+ let locKey = keyDuckLocation(assetIdStr)
216+ let location = getString(locKey)
217+ let keyHealth = keyDuckHealth(assetIdStr)
218+ let health = getInteger(keyHealth)
219+ let bpKey = keyBackpackByDuck(assetIdStr)
220+ let backpack = getString(bpKey)
221+ ([IntegerEntry(timeKey, lastBlock.timestamp), IntegerEntry(keyStakedTimeByTypeAssetIdAndOwner(DUCKPREFIX, toBase58String(assetId), address), lastBlock.timestamp), StringEntry(keyDuckIdToOwner(assetIdStr), address), StringEntry(keyStakedDuckByOwner(address), assetIdStr)] ++ (if (isDefined(location))
222+ then nil
223+ else ([StringEntry(locKey, DEFAULTLOCATION)] ++ (if (isDefined(health))
224+ then nil
225+ else ([IntegerEntry(keyHealth, 100)] ++ (if (isDefined(backpack))
226+ then nil
227+ else [StringEntry(bpKey, "0:0_0_0_0_0_0::")]))))))
228+ }
230229 }
231230 }
232231 }
233232
234233
235234
236235 @Callable(i)
237236 func unstakeDuck (assetIdStr) = if ((size(i.payments) != 0))
238237 then throw("unstake doesn't require any payments")
239238 else {
240239 let assetId = fromBase58String(assetIdStr)
241240 let address = toString(i.caller)
242241 let asset = value(assetInfo(assetId))
243242 if (if ((asset.issuer != incubatorAddr))
244243 then (asset.issuer != breederAddr)
245244 else false)
246245 then throw((("Unknown issuer of " + DUCKPREFIX) + " token"))
247246 else if (!(contains(asset.name, DUCKPREFIX)))
248247 then throw((("Only NFT " + DUCKPREFIX) + " tokens can be unstaked"))
249248 else {
250249 let timeKey = keyStakedTimeByAssetId(toBase58String(assetId))
251250 if (!(isDefined(timeKey)))
252251 then throw((("NFT " + asset.name) + " is not staked"))
253252 else if (!(isDefined(keyStakedDuckByOwner(address))))
254253 then throw((("The duck " + asset.name) + " is not staked"))
255254 else {
256255 let owner = valueOrErrorMessage(getString(keyDuckIdToOwner(toBase58String(assetId))), (("NFT " + asset.name) + " is orphaned"))
257256 if ((owner != address))
258257 then throw("Staked NFT is not yours")
259- else [ScriptTransfer(i.caller, 1, assetId), DeleteEntry(timeKey), DeleteEntry(keyStakedTimeByTypeAssetIdAndOwner(DUCKPREFIX, assetIdStr, address)), DeleteEntry(keyStakedDuckByOwner(address))]
258+ else [ScriptTransfer(i.caller, 1, assetId), DeleteEntry(timeKey), DeleteEntry(keyDuckLocation(assetIdStr)), DeleteEntry(keyStakedTimeByTypeAssetIdAndOwner(DUCKPREFIX, assetIdStr, address)), DeleteEntry(keyStakedDuckByOwner(address))]
260259 }
261260 }
262261 }
263262
264263
265264
266265 @Callable(i)
267-func buyLand (landSize) = if ((i.caller != this))
268- then throw("Permission denied")
269- else if ((size(i.payments) != 1))
270- then throw("Exactly one payment required")
266+func claimRes (amount,landAssetId) = if ((size(i.payments) != 0))
267+ then throw("claimRes doesn't require any payments")
268+ else {
269+ let addr = toString(i.caller)
270+ let asset = value(assetInfo(fromBase58String(landAssetId)))
271+ if (!(contains(asset.name, LANDPREFIX)))
272+ then throw((("NFT " + LANDPREFIX) + " token should be passed as param"))
273+ else {
274+ let timeKey = keyStakedTimeByAssetId(landAssetId)
275+ let savedTime = getInteger(timeKey)
276+ if (!(isDefined(savedTime)))
277+ then throw((("NFT " + asset.name) + " is not staked"))
278+ else {
279+ let owner = getStringValue(keyAssetIdToOwner(landAssetId))
280+ if ((owner != addr))
281+ then throw((LANDPREFIX + " is not yours"))
282+ else {
283+ let d = split(asset.description, "_")
284+ let landSize = d[recLandSize]
285+ let terrainCounts = countTerrains(d[recTerrains])
286+ let duck = getString(keyStakedDuckByOwner(addr))
287+ if (!(isDefined(duck)))
288+ then throw("You don't have a duck staked")
289+ else {
290+ let duckAssetIdStr = value(duck)
291+ let curLocation = valueOrElse(getString(keyDuckLocation(duckAssetIdStr)), DEFAULTLOCATION)
292+ let loc = split(value(curLocation), "_")
293+ if ((loc[locIdxType] != "L"))
294+ then throw((("Duck location type is " + loc[locIdxType]) + ", but should be L"))
295+ else if ((loc[locIdxId] != landAssetId))
296+ then throw(((("Duck location id is " + loc[locIdxId]) + ", but should be ") + landAssetId))
297+ else {
298+ let deltaTime = (lastBlock.timestamp - value(savedTime))
299+ if ((0 > deltaTime))
300+ then throw(((("Saved timestamp is in future, saved = " + toString(value(savedTime))) + ", current = ") + toString(lastBlock.timestamp)))
301+ else {
302+ let pieces = numPiecesBySize(landSize)
303+ let availRes = (fraction(deltaTime, DAILYRESBYPIECE, DAYMILLIS) * pieces)
304+ if ((amount > availRes))
305+ then throw(((("Not enough resources, available = " + toString(availRes)) + ", requested = ") + toString(amount)))
306+ else {
307+ let newDeltaTime = fraction((availRes - amount), DAYMILLIS, (pieces * DAILYRESBYPIECE))
308+ let newTimestamp = (lastBlock.timestamp - newDeltaTime)
309+ let bpKey = keyBackpackByDuck(duckAssetIdStr)
310+ let currentPack = split(valueOrElse(getString(bpKey), "0:0_0_0_0_0_0::"), ":")
311+ let currentRes = split(currentPack[bpIdxRes], "_")
312+ let bpRes = addRes(currentRes, terrainCounts, (deltaTime - newDeltaTime))
313+ let newPack = makeString([currentPack[bpIdxLevel], bpRes, currentPack[bpIdxMat], currentPack[bpIdxProd]], ":")
314+ $Tuple2([StringEntry(bpKey, newPack), IntegerEntry(timeKey, newTimestamp), IntegerEntry(keyStakedTimeByTypeAssetIdAndOwner(LANDPREFIX, landAssetId, owner), newTimestamp)], unit)
315+ }
316+ }
317+ }
318+ }
319+ }
320+ }
321+ }
322+ }
323+
324+
325+
326+@Callable(i)
327+func flight (message,sig) = if (!(sigVerify_8Kb(message, sig, pub)))
328+ then throw("signature does not match")
329+ else if ((size(i.payments) != 0))
330+ then throw("flight doesn't require any payments")
271331 else {
272- let pmt = value(i.payments[0])
273- let actions = match landSize {
274- case _ =>
275- if (("S" == $match0))
276- then buyInternal(pmt, i.transactionId, i.caller, landSize, LENS, MAPS, DEFAULTPRICES)
277- else if (("M" == $match0))
278- then buyInternal(pmt, i.transactionId, i.caller, landSize, LENM, MAPM, DEFAULTPRICEM)
279- else if (("L" == $match0))
280- then buyInternal(pmt, i.transactionId, i.caller, landSize, LENL, MAPL, DEFAULTPRICEL)
281- else if (("XL" == $match0))
282- then buyInternal(pmt, i.transactionId, i.caller, landSize, LENXL, MAPXL, DEFAULTPRICEXL)
283- else throw("Unknown land size")
332+ let parts = split(toUtf8String(message), ";")
333+ let hp = split(split(parts[0], "|")[0], "_")
334+ let curHP = parseIntValue(hp[0])
335+ let newHP = parseIntValue(hp[1])
336+ let newLocAndTime = split(parts[1], ":")
337+ let newLocation = newLocAndTime[0]
338+ let time = parseIntValue(newLocAndTime[1])
339+ if (if ((time > (lastBlock.timestamp + FIVEMINUTESMILLIS)))
340+ then true
341+ else ((lastBlock.timestamp - FIVEMINUTESMILLIS) > time))
342+ then throw("signature outdated")
343+ else {
344+ let duckAssetId = valueOrErrorMessage(getString(keyStakedDuckByOwner(toString(i.caller))), "You don't have a duck staked")
345+ let keyHealth = keyDuckHealth(duckAssetId)
346+ let oldFromState = valueOrElse(getInteger(keyHealth), 100)
347+ if ((oldFromState != curHP))
348+ then throw(((("oldHealth=" + toString(valueOrElse(getInteger(keyHealth), 100))) + " from state does not match one from flight log=") + toString(curHP)))
349+ else if ((0 >= curHP))
350+ then throw("You can't fly with zero health")
351+ else {
352+ let locKey = keyDuckLocation(duckAssetId)
353+ let curLocation = valueOrElse(getString(locKey), DEFAULTLOCATION)
354+ if ((newLocation == curLocation))
355+ then throw("You can't fly to the same location")
356+ else $Tuple2([StringEntry(locKey, if ((newHP > 0))
357+ then newLocation
358+ else curLocation), IntegerEntry(keyHealth, newHP)], unit)
359+ }
360+ }
284361 }
285- $Tuple2(actions, unit)
286- }
362+
363+
364+
365+@Callable(i)
366+func setHealth (health,duckAssetId) = {
367+ let duckAssetIdStr = valueOrErrorMessage(getString(keyStakedDuckByOwner(toString(i.caller))), "You don't have a duck staked")
368+ if (if ((0 > health))
369+ then true
370+ else (health > 100))
371+ then throw("HP should be within 0..100")
372+ else [IntegerEntry(keyDuckHealth(duckAssetId), health)]
373+ }
374+
375+
376+
377+@Callable(i)
378+func updateBackpack (duckAssetId,newPack) = if ((i.caller != economyAddr))
379+ then throw("permission denied")
380+ else $Tuple2([StringEntry(keyBackpackByDuck(duckAssetId), newPack)], newPack)
287381
288382

github/deemru/w8io/0e76f2f 
191.61 ms