tx · 4HfReAZ5UweZTCzPBt5qUBEw4sF8rKxMb2nS8YmLrWj7

3PLncXtS1U83D6cQbFD3H8rBHPLgzxSFKZ1:  -0.03500000 Waves

2023.02.05 17:42 [3502028] smart account 3PLncXtS1U83D6cQbFD3H8rBHPLgzxSFKZ1 > SELF 0.00000000 Waves

{ "type": 13, "id": "4HfReAZ5UweZTCzPBt5qUBEw4sF8rKxMb2nS8YmLrWj7", "fee": 3500000, "feeAssetId": null, "timestamp": 1675608142042, "version": 2, "chainId": 87, "sender": "3PLncXtS1U83D6cQbFD3H8rBHPLgzxSFKZ1", "senderPublicKey": "BtDpFhgHQKHFVqYTMLReuZzqy94CRPSRkrYcSEVyjt4q", "proofs": [ "5bxQxuJwBNNPV8B7nPgZW23eoJcyqnnHUuM8ZzHTAuXHKn94dU1v1XQuxoHFKBoithtxxi6g3BFa8JTwoEtmUBaD" ], "script": "base64:BgJqCAISAwoBBBIAEgMKAQgSABIDCgEIEgQKAgEIEgQKAgICEgQKAgEIEgQKAgEBEgQKAggIEgASBAoCAgISBAoCAgISAwoBCBIDCgEIEgMKAQgSAwoBGBIDCgEYEgMKAQESBAoCAQgSAwoBCGIABWNoYWluCQDJAQIJAMoBAggFBHRoaXMFYnl0ZXMAAQABAAt1c2RuQXNzZXRJZAQHJG1hdGNoMAUFY2hhaW4DCQAAAgEBVwUHJG1hdGNoMAEgtiYpwwT1zlORpA5LdSQvZIxRsfrfr1QpvUjSHSqyqtEDCQAAAgEBVAUHJG1hdGNoMAEg93bq9/eDymXbbhPuAjvPWCmVqcHRjfJL2mzYHWKAyN4JAAIBAg1Vbmtub3duIGNoYWluAA1pbmN1YmF0b3JBZGRyBAckbWF0Y2gwBQVjaGFpbgMJAAACAQFXBQckbWF0Y2gwCQERQGV4dHJOYXRpdmUoMTA2MikBAiMzUEVrdFZ1eDJSaGNoU042M0RzRG80YjRtejRRcXpLU2VEdgMJAAACAQFUBQckbWF0Y2gwBQR0aGlzCQACAQINVW5rbm93biBjaGFpbgALYnJlZWRlckFkZHIEByRtYXRjaDAFBWNoYWluAwkAAAIBAVcFByRtYXRjaDAJARFAZXh0ck5hdGl2ZSgxMDYyKQECIzNQRFZ1VTQ1SDdFaDVkbXROYm5STlJTdEd3VUxBN05ZNkhiAwkAAAIBAVQFByRtYXRjaDAFBHRoaXMJAAIBAg1Vbmtub3duIGNoYWluAA9lY29ub215Q29udHJhY3QJARFAZXh0ck5hdGl2ZSgxMDYyKQEEByRtYXRjaDAFBWNoYWluAwkAAAIBAVcFByRtYXRjaDACIzNQMnNrMUtuY1N4UmFaczhiNENXR1B3MmprdnZhdjc0dTREAwkAAAIBAVQFByRtYXRjaDACIzNOOHk0d3hYM0pDNFRkckNKQlhYMTZTaldmNlgyNTZocmVwCQACAQINVW5rbm93biBjaGFpbgADcHViASBPU+IaP1So1p1SThMdRidVvbNT8yx7yVRUsP9DwbQUKAAISEVBTENPU1QAkE4ACkxBTkRQUkVGSVgCBExBTkQACkRVQ0tQUkVGSVgCBERVQ0sAD0RFRkFVTFRMT0NBVElPTgIPQWZyaWNhX0ZfQWZyaWNhAAZOVU1SRVMABgAFU1NJWkUAGQAFTVNJWkUAZAAFTFNJWkUA4QEABlhMU0laRQCQAwAHWFhMU0laRQDxBAAPREFJTFlSRVNCWVBJRUNFAID40gEACURBWU1JTExJUwCAuJkpABFGSVZFTUlOVVRFU01JTExJUwDgpxIAEFJFU09VUkNFUFJJQ0VNSU4A1dYJABFJbmZyYVVwZ3JhZGVDb3N0UwQHJG1hdGNoMAUFY2hhaW4DCQAAAgEBVwUHJG1hdGNoMADG68C/FwMJAAACAQFUBQckbWF0Y2gwAPDNiR4JAAIBAg1Vbmtub3duIGNoYWluABVJbmZyYVVwZ3JhZGVDb3N0U1VzZG4EByRtYXRjaDAFBWNoYWluAwkAAAIBAVcFByRtYXRjaDAAgLSJEwMJAAACAQFUBQckbWF0Y2gwAIC1GAkAAgECDVVua25vd24gY2hhaW4ADEVYUE1BVEVSSUFMUwQHJG1hdGNoMAUFY2hhaW4DCQAAAgEBVwUHJG1hdGNoMADLgNWzywQDCQAAAgEBVAUHJG1hdGNoMADxmvDvBQkAAgECDVVua25vd24gY2hhaW4AB0VYUFVTRE4EByRtYXRjaDAFBWNoYWluAwkAAAIBAVcFByRtYXRjaDAAgJTr3AMDCQAAAgEBVAUHJG1hdGNoMACAreIECQACAQINVW5rbm93biBjaGFpbgAFTVVMVDYAwIQ9AAVGSVZFWAkAtgIBAAUAB1RXRU5UWVgJALYCAQAUAAhUV0VOVFkyWAkAtgIBCQBoAgAUABQACFRXRU5UWTNYCQC2AgEJAGgCCQBoAgAUABQAFAAIVFdFTlRZNFgJALYCAQkAaAIJAGgCCQBoAgAUABQAFAAUAAhUV0VOVFk1WAkAtgIBCQBoAgkAaAIJAGgCCQBoAgAUABQAFAAUABQACG1hdFR5cGVzCQDMCAICBEZ1ZWwJAMwIAgIFTWV0YWwJAMwIAgIFUGxhbmsJAMwIAgIFR2xhc3MJAMwIAgIHUGxhc3RpYwkAzAgCAgdQcm90ZWluBQNuaWwACmNvbnRpbmVudHMJAMwIAgIEQXNpYQkAzAgCAgZFdXJvcGUJAMwIAgIIQW1lcmljYXMJAMwIAgIHT2NlYW5pYQkAzAgCAgZBZnJpY2EFA25pbAAKQVJUUFJFU0FMRQIHUFJFU0FMRQAPUFJFU0FMRU5VTUxBTkRTAPQDARFrZXlMYXN0VHhJZEJ5VXNlcgEEYWRkcgkArAICAg9sYXN0VHhJZEJ5VXNlcl8FBGFkZHIBEmtleU5leHRGcmVlTGFuZE51bQACC25leHRMYW5kTnVtARBrZXlMYW5kVG9Bc3NldElkAQdsYW5kTnVtCQCsAgICDGxhbmRUb0Fzc2V0XwUHbGFuZE51bQEKa2V5TmZ0TmFtZQIHbGFuZE51bQhsYW5kU2l6ZQkArAICCQCsAgIFCkxBTkRQUkVGSVgFB2xhbmROdW0FCGxhbmRTaXplARVrZXlMYW5kQXNzZXRJZFRvT3duZXIBB2Fzc2V0SWQJAKwCAgIJbmZ0T3duZXJfBQdhc3NldElkARBrZXlEdWNrSWRUb093bmVyAQdhc3NldElkCQCsAgICCmR1Y2tPd25lcl8FB2Fzc2V0SWQBFmtleVN0YWtlZFRpbWVCeUFzc2V0SWQBB2Fzc2V0SWQJAKwCAgILc3Rha2VkVGltZV8FB2Fzc2V0SWQBFmtleUluZnJhTGV2ZWxCeUFzc2V0SWQBB2Fzc2V0SWQJAKwCAgILaW5mcmFMZXZlbF8FB2Fzc2V0SWQBHmtleUluZnJhTGV2ZWxCeUFzc2V0SWRBbmRPd25lcgIHYXNzZXRJZAlvd25lckFkZHIJAKwCAgkArAICCQCsAgICHGluZnJhTGV2ZWxCeUFzc2V0SWRBbmRPd25lcl8FB2Fzc2V0SWQCAV8FCW93bmVyQWRkcgEfa2V5UHJlc2FsZUFydEFjdGl2YXRlZEJ5QXNzZXRJZAEHYXNzZXRJZAkArAICAhRwcmVzYWxlQXJ0QWN0aXZhdGVkXwUHYXNzZXRJZAEna2V5UHJlc2FsZUFydEFjdGl2YXRlZEJ5QXNzZXRJZEFuZE93bmVyAgdhc3NldElkCW93bmVyQWRkcgkArAICCQCsAgIJAKwCAgIlcHJlc2FsZUFydEFjdGl2YXRlZEJ5QXNzZXRJZEFuZE93bmVyXwUHYXNzZXRJZAIBXwUJb3duZXJBZGRyASBrZXlMYW5kQXJ0U3RhdHVzQnlUeXBlQW5kQXNzZXRJZAIEdHlwZQdhc3NldElkCQC5CQIJAMwIAgINbGFuZEFydFN0YXR1cwkAzAgCBQR0eXBlCQDMCAIFB2Fzc2V0SWQFA25pbAIBXwEla2V5TGFuZEFydFN0YXR1c0J5VHlwZUFzc2V0SWRBbmRPd25lcgMEdHlwZQdhc3NldElkCW93bmVyQWRkcgkAuQkCCQDMCAICImxhbmRBcnRTdGF0dXNCeVR5cGVBc3NldElkQW5kT3duZXIJAMwIAgUEdHlwZQkAzAgCBQdhc3NldElkCQDMCAIFCW93bmVyQWRkcgUDbmlsAgFfARRrZXlTdGFrZWREdWNrQnlPd25lcgEJb3duZXJBZGRyCQCsAgICEnN0YWtlZER1Y2tCeU93bmVyXwUJb3duZXJBZGRyASJrZXlTdGFrZWRUaW1lQnlUeXBlQXNzZXRJZEFuZE93bmVyAwduZnRUeXBlB2Fzc2V0SWQJb3duZXJBZGRyCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgIgc3Rha2VkVGltZUJ5VHlwZUFzc2V0SWRBbmRPd25lcl8FB25mdFR5cGUCAV8FB2Fzc2V0SWQCAV8FCW93bmVyQWRkcgERa2V5TGFuZE51bVRvT3duZXIBB2xhbmROdW0JAKwCAgIKbGFuZE93bmVyXwUHbGFuZE51bQERa2V5QmFja3BhY2tCeUR1Y2sBC2R1Y2tBc3NldElkCQCsAgICCWJhY2tQYWNrXwULZHVja0Fzc2V0SWQBD2tleUR1Y2tMb2NhdGlvbgELZHVja0Fzc2V0SWQJAKwCAgINZHVja0xvY2F0aW9uXwULZHVja0Fzc2V0SWQBDWtleUR1Y2tIZWFsdGgBC2R1Y2tBc3NldElkCQCsAgICC2R1Y2tIZWFsdGhfBQtkdWNrQXNzZXRJZAERa2V5UmVzUHJvcG9ydGlvbnMAAhNyZXNUeXBlc1Byb3BvcnRpb25zARVrZXlTdGFrZWRMYW5kc0J5T3duZXIBCW93bmVyQWRkcgkArAICAhNzdGFrZWRMYW5kc0J5T3duZXJfBQlvd25lckFkZHIBCmtleUJsb2NrZWQAAhBjb250cmFjdHNCbG9ja2VkAApyZWNMYW5kTnVtAAAAC3JlY0xhbmRTaXplAAEAC3JlY1RlcnJhaW5zAAIADHJlY0NvbnRpbmVudAADAA9sb2NJZHhDb250aW5lbnQAAAAKbG9jSWR4VHlwZQABAAhsb2NJZHhJZAACAApicElkeExldmVsAAAACGJwSWR4UmVzAAEACGJwSWR4TWF0AAIACWJwSWR4UHJvZAADAQhhc1N0cmluZwEBdgQHJG1hdGNoMAUBdgMJAAECBQckbWF0Y2gwAgZTdHJpbmcEAXMFByRtYXRjaDAFAXMJAAIBAhhmYWlsIHRvIGNhc3QgaW50byBTdHJpbmcBE2Rpc3RyaWJ1dGVCeVdlaWdodHMCBXRvdGFsB3dlaWdodHMEA3N1bQkAZAIJAGQCCQBkAgkAZAIJAGQCCQCRAwIFB3dlaWdodHMAAAkAkQMCBQd3ZWlnaHRzAAEJAJEDAgUHd2VpZ2h0cwACCQCRAwIFB3dlaWdodHMAAwkAkQMCBQd3ZWlnaHRzAAQJAJEDAgUHd2VpZ2h0cwAFAwkAZwIAAAUDc3VtCQACAQIQWmVybyB3ZWlnaHRzIHN1bQQFbm9ybTYJAGsDBQV0b3RhbAUFTVVMVDYFA3N1bQoBCm5vcm1hbGl6ZXICA2FjYwRlbGVtCQDNCAIFA2FjYwkAawMFBGVsZW0FBW5vcm02BQVNVUxUNgoAAiRsBQd3ZWlnaHRzCgACJHMJAJADAQUCJGwKAAUkYWNjMAUDbmlsCgEFJGYwXzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAQpub3JtYWxpemVyAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGYwXzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhNMaXN0IHNpemUgZXhjZWVkcyA2CQEFJGYwXzICCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECBQUkYWNjMAAAAAEAAgADAAQABQAGARJnZXROZWVkZWRNYXRlcmlhbHMBBXRvdGFsBAVwcm9wcwkAtQkCCQEFdmFsdWUBCQCiCAEJARFrZXlSZXNQcm9wb3J0aW9ucwACAV8DCQECIT0CCQCQAwEFBXByb3BzBQZOVU1SRVMJAAIBAhZXcm9uZyBwcm9wb3J0aW9ucyBkYXRhBAFyCQDMCAIJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQVwcm9wcwAACQDMCAIJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQVwcm9wcwABCQDMCAIJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQVwcm9wcwACCQDMCAIJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQVwcm9wcwADCQDMCAIJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQVwcm9wcwAECQDMCAIJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQVwcm9wcwAFBQNuaWwJARNkaXN0cmlidXRlQnlXZWlnaHRzAgUFdG90YWwFAXIBEXN1YnRyYWN0TWF0ZXJpYWxzAwxzaG91bGRVc2VNYXQDaGFzCXRvdGFsTmVlZAQEbmVlZAkBEmdldE5lZWRlZE1hdGVyaWFscwEFCXRvdGFsTmVlZAoBCnN1YnRyYWN0b3ICA2FjYwNpZHgEBnJlc3VsdAkAZQIJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQNoYXMFA2lkeAkAkQMCBQRuZWVkBQNpZHgDCQBmAgAABQZyZXN1bHQJAAIBCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgIYTm90IGVub3VnaCBtYXRlcmlhbCBpZHg9CQCkAwEFA2lkeAILLCB5b3UgaGF2ZSAJAJEDAgUDaGFzBQNpZHgCCywgYnV0IG5lZWQgCQCkAwEJAJEDAgUEbmVlZAUDaWR4CQDNCAIFA2FjYwkApAMBBQZyZXN1bHQDBQxzaG91bGRVc2VNYXQKAAIkbAkAzAgCAAAJAMwIAgABCQDMCAIAAgkAzAgCAAMJAMwIAgAECQDMCAIABQUDbmlsCgACJHMJAJADAQUCJGwKAAUkYWNjMAUDbmlsCgEFJGYwXzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAQpzdWJ0cmFjdG9yAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGYwXzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhNMaXN0IHNpemUgZXhjZWVkcyA2CQEFJGYwXzICCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECBQUkYWNjMAAAAAEAAgADAAQABQAGBQNoYXMBGXVwZGF0ZVByb3BvcnRpb25zSW50ZXJuYWwECHByb3BMaXN0DXRlcnJhaW5Db3VudHMNbGFuZFNpemVJbmRleARzaWduAwkBAiE9AgkAkAMBBQhwcm9wTGlzdAUGTlVNUkVTCQACAQIWV3JvbmcgcHJvcG9ydGlvbnMgZGF0YQoBB3VwZGF0ZXICA2FjYwFpBAZyZXN1bHQJAGQCCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUIcHJvcExpc3QFAWkJAGgCCQBoAgUEc2lnbgkAkQMCBQ10ZXJyYWluQ291bnRzBQFpBQ1sYW5kU2l6ZUluZGV4AwkAZgIAAAUGcmVzdWx0CQACAQkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICAhZQYW5pYyEgUGllY2VzIG9mIHR5cGU9CQCkAwEFAWkCBywgc2lnbj0JAKQDAQUEc2lnbgIULCAgdGVycmFpbkNvdW50c1tpXT0JAKQDAQkAkQMCBQ10ZXJyYWluQ291bnRzBQFpAhAsIGxhbmRTaXplSW5kZXg9CQCkAwEFDWxhbmRTaXplSW5kZXgJAM0IAgUDYWNjCQCkAwEFBnJlc3VsdAQBcgoAAiRsCQDMCAIAAAkAzAgCAAEJAMwIAgACCQDMCAIAAwkAzAgCAAQJAMwIAgAFBQNuaWwKAAIkcwkAkAMBBQIkbAoABSRhY2MwBQNuaWwKAQUkZjBfMQICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkBB3VwZGF0ZXICBQIkYQkAkQMCBQIkbAUCJGkKAQUkZjBfMgICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkAAgECE0xpc3Qgc2l6ZSBleGNlZWRzIDYJAQUkZjBfMgIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYJALkJAgUBcgIBXwERdXBkYXRlUHJvcG9ydGlvbnMDDXRlcnJhaW5Db3VudHMNbGFuZFNpemVJbmRleARzaWduBAhwcm9wTGlzdAkAtQkCCQELdmFsdWVPckVsc2UCCQCiCAEJARFrZXlSZXNQcm9wb3J0aW9ucwACCzBfMF8wXzBfMF8wAgFfCQEZdXBkYXRlUHJvcG9ydGlvbnNJbnRlcm5hbAQFCHByb3BMaXN0BQ10ZXJyYWluQ291bnRzBQ1sYW5kU2l6ZUluZGV4BQRzaWduAQ1jb3VudFRlcnJhaW5zAQh0ZXJyYWlucwkAzAgCCQBlAgkAkAMBCQC1CQIFCHRlcnJhaW5zAgFBAAEJAMwIAgkAZQIJAJADAQkAtQkCBQh0ZXJyYWlucwIBQgABCQDMCAIJAGUCCQCQAwEJALUJAgUIdGVycmFpbnMCAUMAAQkAzAgCCQBlAgkAkAMBCQC1CQIFCHRlcnJhaW5zAgFEAAEJAMwIAgkAZQIJAJADAQkAtQkCBQh0ZXJyYWlucwIBRQABCQDMCAIJAGUCCQCQAwEJALUJAgUIdGVycmFpbnMCAUYAAQUDbmlsAQ9udW1QaWVjZXNCeVNpemUBCGxhbmRTaXplBAckbWF0Y2gwBQhsYW5kU2l6ZQMJAAACAgFTBQckbWF0Y2gwBQVTU0laRQMJAAACAgFNBQckbWF0Y2gwBQVNU0laRQMJAAACAgFMBQckbWF0Y2gwBQVMU0laRQMJAAACAgJYTAUHJG1hdGNoMAUGWExTSVpFAwkAAAICA1hYTAUHJG1hdGNoMAUHWFhMU0laRQkAAgECEVVua25vd24gbGFuZCBzaXplAQxzdWJPbmVJbkxpc3QDBWFMaXN0A2lkeAZhbW91bnQKAQZzdWJiZXICA2FjYwFpCQDNCAIFA2FjYwMJAAACBQFpBQNpZHgJAKQDAQkAZQIJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQVhTGlzdAUBaQUGYW1vdW50CQCRAwIFBWFMaXN0BQFpBAFyCgACJGwJAMwIAgAACQDMCAIAAQkAzAgCAAIJAMwIAgADCQDMCAIABAkAzAgCAAUFA25pbAoAAiRzCQCQAwEFAiRsCgAFJGFjYzAFA25pbAoBBSRmMF8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQEGc3ViYmVyAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGYwXzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhNMaXN0IHNpemUgZXhjZWVkcyA2CQEFJGYwXzICCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECBQUkYWNjMAAAAAEAAgADAAQABQAGCQC5CQIFAXICAV8BBmFkZFJlcwUKY3VycmVudFJlcw10ZXJyYWluQ291bnRzCWRlbHRhVGltZQ1sYW5kU2l6ZUluZGV4F2RhaWx5QnlQaWVjZVdpdGhCb251c2VzCgEFYWRkZXICA2FjYwFpBAlyZXNPZlR5cGUJAGgCCQBoAgkAawMFCWRlbHRhVGltZQUXZGFpbHlCeVBpZWNlV2l0aEJvbnVzZXMFCURBWU1JTExJUwkAkQMCBQ10ZXJyYWluQ291bnRzBQFpBQ1sYW5kU2l6ZUluZGV4CQDNCAIFA2FjYwkApAMBCQBkAgkBDXBhcnNlSW50VmFsdWUBCQCRAwIFCmN1cnJlbnRSZXMFAWkFCXJlc09mVHlwZQQBcgoAAiRsCQDMCAIAAAkAzAgCAAEJAMwIAgACCQDMCAIAAwkAzAgCAAQJAMwIAgAFBQNuaWwKAAIkcwkAkAMBBQIkbAoABSRhY2MwBQNuaWwKAQUkZjBfMQICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkBBWFkZGVyAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGYwXzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhNMaXN0IHNpemUgZXhjZWVkcyA2CQEFJGYwXzICCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECBQUkYWNjMAAAAAEAAgADAAQABQAGCQC5CQIFAXICAV8BA2FicwEBeAMJAMACAgUBeAkAtgIBAAAFAXgJAL4CAQUBeAAEZnJlcQkAzAgCCQDMCAIAAQkAzAgCAAQJAMwIAgAJCQDMCAIACgkAzAgCAA8FA25pbAkAzAgCCQDMCAIABQkAzAgCAAgJAMwIAgANCQDMCAIADgkAzAgCAA8FA25pbAkAzAgCCQDMCAIABgkAzAgCAAkJAMwIAgAOCQDMCAIADwkAzAgCABAFA25pbAkAzAgCCQDMCAIABAkAzAgCAAcJAMwIAgAICQDMCAIADQkAzAgCABIFA25pbAkAzAgCCQDMCAIAAQkAzAgCAAYJAMwIAgAHCQDMCAIADwkAzAgCABMFA25pbAUDbmlsAQdnZW5DaGFyAgFuBWZyZXFzBANyZW0JAKADAQkAuwICBQFuBQdUV0VOVFlYBAZsZXR0ZXIDCQBmAgkAkQMCBQVmcmVxcwAABQNyZW0CAUEDCQBmAgkAkQMCBQVmcmVxcwABBQNyZW0CAUIDCQBmAgkAkQMCBQVmcmVxcwACBQNyZW0CAUMDCQBmAgkAkQMCBQVmcmVxcwADBQNyZW0CAUQDCQBmAgkAkQMCBQVmcmVxcwAEBQNyZW0CAUUCAUYFBmxldHRlcgELZ2VuVGVycmFpbnMCBHNlZWQMY29udGluZW50SWR4BAFmCQCRAwIFBGZyZXEFDGNvbnRpbmVudElkeAoBEHRlcnJhaW5HZW5lcmF0b3ICA2FjYwRlbGVtCQCUCgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCAUDYWNjAl8xCQEHZ2VuQ2hhcgIIBQNhY2MCXzIFAWYJAQdnZW5DaGFyAgkAugICCAUDYWNjAl8yBQdUV0VOVFlYBQFmCQEHZ2VuQ2hhcgIJALoCAggFA2FjYwJfMgUIVFdFTlRZMlgFAWYJAQdnZW5DaGFyAgkAugICCAUDYWNjAl8yBQhUV0VOVFkzWAUBZgkBB2dlbkNoYXICCQC6AgIIBQNhY2MCXzIFCFRXRU5UWTRYBQFmCQC6AgIIBQNhY2MCXzIFCFRXRU5UWTVYBAF0CgACJGwJAMwIAgABCQDMCAIAAgkAzAgCAAMJAMwIAgAECQDMCAIABQUDbmlsCgACJHMJAJADAQUCJGwKAAUkYWNjMAkAlAoCAgAJALoCAgUEc2VlZAUFRklWRVgKAQUkZjBfMQICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkBEHRlcnJhaW5HZW5lcmF0b3ICBQIkYQkAkQMCBQIkbAUCJGkKAQUkZjBfMgICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkAAgECE0xpc3Qgc2l6ZSBleGNlZWRzIDUJAQUkZjBfMgIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIFBSRhY2MwAAAAAQACAAMABAAFCAUBdAJfMQELZ2V0QmFja3BhY2sBBWJwS2V5BAFwCQC1CQIJAQt2YWx1ZU9yRWxzZQIJAKIIAQUFYnBLZXkCGjA6MF8wXzBfMF8wXzA6MF8wXzBfMF8wXzA6AgE6CQDMCAIJAKQDAQkBC3ZhbHVlT3JFbHNlAgkAtgkBCQCRAwIFAXAFCmJwSWR4TGV2ZWwAAAkAzAgCAwkAAAIJAJADAQkAtQkCCQCRAwIFAXAFCGJwSWR4UmVzAgFfBQZOVU1SRVMJAJEDAgUBcAUIYnBJZHhSZXMCCzBfMF8wXzBfMF8wCQDMCAIDCQAAAgkAkAMBCQC1CQIJAJEDAgUBcAUIYnBJZHhNYXQCAV8FBk5VTVJFUwkAkQMCBQFwBQhicElkeE1hdAILMF8wXzBfMF8wXzAJAMwIAgkAkQMCBQFwBQlicElkeFByb2QFA25pbAESZXhwZWRpdGlvbkludGVybmFsAgZjYWxsZXIEdHhJZAQIdXNlckFkZHIJAKUIAQUGY2FsbGVyBAZiaWdOdW0JAQNhYnMBCQCeAwEFBHR4SWQEB2ZyZWVOdW0JAQt2YWx1ZU9yRWxzZQIJAJ8IAQkBEmtleU5leHRGcmVlTGFuZE51bQAJAGQCBQ9QUkVTQUxFTlVNTEFORFMAAQQHbGFuZE51bQkApAMBBQdmcmVlTnVtBAxjb250aW5lbnRJZHgJAKADAQkAuwICBQZiaWdOdW0FBUZJVkVYBAh0ZXJyYWlucwkBC2dlblRlcnJhaW5zAgUGYmlnTnVtBQxjb250aW5lbnRJZHgECWNvbnRpbmVudAkAkQMCBQpjb250aW5lbnRzBQxjb250aW5lbnRJZHgEBWlzc3VlCQDCCAUJAQprZXlOZnROYW1lAgUHbGFuZE51bQIBUwkAuQkCCQDMCAIFB2xhbmROdW0JAMwIAgIBUwkAzAgCBQh0ZXJyYWlucwkAzAgCBQljb250aW5lbnQFA25pbAIBXwABAAAHBAdhc3NldElkCQC4CAEFBWlzc3VlBAJpZAkA2AQBBQdhc3NldElkCQCUCgIJAMwIAgkBDEludGVnZXJFbnRyeQIJARJrZXlOZXh0RnJlZUxhbmROdW0ACQBkAgUHZnJlZU51bQABCQDMCAIFBWlzc3VlCQDMCAIJAQtTdHJpbmdFbnRyeQIJARBrZXlMYW5kVG9Bc3NldElkAQUHbGFuZE51bQUCaWQJAMwIAgkBC1N0cmluZ0VudHJ5AgkBFWtleUxhbmRBc3NldElkVG9Pd25lcgEFAmlkBQh1c2VyQWRkcgkAzAgCCQELU3RyaW5nRW50cnkCCQERa2V5TGFuZE51bVRvT3duZXIBBQdsYW5kTnVtBQh1c2VyQWRkcgkAzAgCCQEMSW50ZWdlckVudHJ5AgkBFmtleUluZnJhTGV2ZWxCeUFzc2V0SWQBBQJpZAAACQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEea2V5SW5mcmFMZXZlbEJ5QXNzZXRJZEFuZE93bmVyAgUCaWQFCHVzZXJBZGRyAAAJAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwUGY2FsbGVyAAEFB2Fzc2V0SWQFA25pbAkAlAoCBQJpZAUJY29udGluZW50ARBleHBlZGl0aW9uQ29tbW9uBQxzaG91bGRVc2VNYXQGY2FsbGVyBHR4SWQHbWVzc2FnZQNzaWcDCQEBIQEJAMQTAwUHbWVzc2FnZQUDc2lnBQNwdWIJAAIBAhhzaWduYXR1cmUgZG9lcyBub3QgbWF0Y2gEBXBhcnRzCQC1CQIJALAJAQUHbWVzc2FnZQIBOwQCaHAJALUJAgkAkQMCCQC1CQIJAJEDAgUFcGFydHMAAAIBfAAAAgFfBAVjdXJIUAkBDXBhcnNlSW50VmFsdWUBCQCRAwIFAmhwAAAEBW5ld0hQCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUCaHAAAQQKbG9jQW5kVGltZQkAtQkCCQCRAwIFBXBhcnRzAAECAToEDnRhcmdldExvY2F0aW9uCQC1CQIJAJEDAgUKbG9jQW5kVGltZQAAAgFfAwkBAiE9AgkAkQMCBQ50YXJnZXRMb2NhdGlvbgABAgFFCQACAQIrZXhwZWRpdGlvbiB0YXJnZXQgbG9jYXRpb24gdHlwZSBzaG91bGQgYmUgRQQEdGltZQkBDXBhcnNlSW50VmFsdWUBCQCRAwIFCmxvY0FuZFRpbWUAAQMDCQBmAgUEdGltZQkAZAIIBQlsYXN0QmxvY2sJdGltZXN0YW1wBRFGSVZFTUlOVVRFU01JTExJUwYJAGYCCQBlAggFCWxhc3RCbG9jawl0aW1lc3RhbXAFEUZJVkVNSU5VVEVTTUlMTElTBQR0aW1lCQACAQISc2lnbmF0dXJlIG91dGRhdGVkBAh1c2VyQWRkcgkApQgBBQZjYWxsZXIEC2R1Y2tBc3NldElkCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKIIAQkBFGtleVN0YWtlZER1Y2tCeU93bmVyAQUIdXNlckFkZHICHFlvdSBkb24ndCBoYXZlIGEgZHVjayBzdGFrZWQECWtleUhlYWx0aAkBDWtleUR1Y2tIZWFsdGgBBQtkdWNrQXNzZXRJZAQMb2xkRnJvbVN0YXRlCQELdmFsdWVPckVsc2UCCQCfCAEFCWtleUhlYWx0aABkAwkBAiE9AgUMb2xkRnJvbVN0YXRlBQVjdXJIUAkAAgEJAKwCAgkArAICCQCsAgICCm9sZEhlYWx0aD0JAKQDAQkBC3ZhbHVlT3JFbHNlAgkAnwgBBQlrZXlIZWFsdGgAZAIvIGZyb20gc3RhdGUgZG9lcyBub3QgbWF0Y2ggb25lIGZyb20gZmxpZ2h0IGxvZz0JAKQDAQUFY3VySFADCQBnAgAABQVjdXJIUAkAAgECHllvdSBjYW4ndCBmbHkgd2l0aCB6ZXJvIGhlYWx0aAMJAGcCAAAFBW5ld0hQCQCUCgIJAM0IAgMJAQEhAQUMc2hvdWxkVXNlTWF0CQDMCAIJAQ5TY3JpcHRUcmFuc2ZlcgMFBmNhbGxlcgUHRVhQVVNETgULdXNkbkFzc2V0SWQFA25pbAUDbmlsCQEMSW50ZWdlckVudHJ5AgUJa2V5SGVhbHRoAAACAAQFYnBLZXkJARFrZXlCYWNrcGFja0J5RHVjawEFC2R1Y2tBc3NldElkBAtjdXJyZW50UGFjawkBC2dldEJhY2twYWNrAQUFYnBLZXkEBW1MaXN0CQC1CQIJAJEDAgULY3VycmVudFBhY2sFCGJwSWR4TWF0AgFfBAZuZXdNYXQJALkJAgkBEXN1YnRyYWN0TWF0ZXJpYWxzAwUMc2hvdWxkVXNlTWF0BQVtTGlzdAUMRVhQTUFURVJJQUxTAgFfBAFlCQESZXhwZWRpdGlvbkludGVybmFsAgUGY2FsbGVyBQR0eElkBAJpZAgIBQFlAl8yAl8xCQCUCgIJAM0IAgkAzQgCCQDNCAIIBQFlAl8xCQELU3RyaW5nRW50cnkCCQEPa2V5RHVja0xvY2F0aW9uAQULZHVja0Fzc2V0SWQJALkJAgkAzAgCCAgFAWUCXzICXzIJAMwIAgIBTAkAzAgCBQJpZAUDbmlsAgFfCQEMSW50ZWdlckVudHJ5AgUJa2V5SGVhbHRoBQVuZXdIUAkBC1N0cmluZ0VudHJ5AgUFYnBLZXkJALkJAgkAzAgCCQCRAwIFC2N1cnJlbnRQYWNrBQpicElkeExldmVsCQDMCAIJAJEDAgULY3VycmVudFBhY2sFCGJwSWR4UmVzCQDMCAIFBm5ld01hdAkAzAgCCQCRAwIFC2N1cnJlbnRQYWNrBQlicElkeFByb2QFA25pbAIBOgUCaWQBDGFwcGx5Qm9udXNlcwILbGFuZEFzc2V0SWQGcGllY2VzBAppbmZyYUxldmVsCQELdmFsdWVPckVsc2UCCQCfCAEJARZrZXlJbmZyYUxldmVsQnlBc3NldElkAQULbGFuZEFzc2V0SWQAAAQJYXJ0UGllY2VzCQELdmFsdWVPckVsc2UCCQCfCAEJASBrZXlMYW5kQXJ0U3RhdHVzQnlUeXBlQW5kQXNzZXRJZAIFCkFSVFBSRVNBTEUFC2xhbmRBc3NldElkAwkBC3ZhbHVlT3JFbHNlAgkAoAgBCQEfa2V5UHJlc2FsZUFydEFjdGl2YXRlZEJ5QXNzZXRJZAEFC2xhbmRBc3NldElkBwUGcGllY2VzAAAJAGQCCQBkAgUPREFJTFlSRVNCWVBJRUNFCQBrAwUPREFJTFlSRVNCWVBJRUNFBQppbmZyYUxldmVsAAQJAGsDBQ9EQUlMWVJFU0JZUElFQ0UJAGgCBQlhcnRQaWVjZXMAAwkAaAIFBnBpZWNlcwAUARRjaGVja0NsYWltQ29uZGl0aW9ucwEEYWRkcgQLZHVja0Fzc2V0SWQJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAoggBCQEUa2V5U3Rha2VkRHVja0J5T3duZXIBBQRhZGRyAhxZb3UgZG9uJ3QgaGF2ZSBhIGR1Y2sgc3Rha2VkBAtjdXJMb2NhdGlvbgkBC3ZhbHVlT3JFbHNlAgkAoggBCQEPa2V5RHVja0xvY2F0aW9uAQULZHVja0Fzc2V0SWQFD0RFRkFVTFRMT0NBVElPTgQDbG9jCQC1CQIJAQV2YWx1ZQEFC2N1ckxvY2F0aW9uAgFfAwkBAiE9AgkAkQMCBQNsb2MFCmxvY0lkeFR5cGUCAUwJAAIBCQCsAgIJAKwCAgIWRHVjayBsb2NhdGlvbiB0eXBlIGlzIAkAkQMCBQNsb2MFCmxvY0lkeFR5cGUCESwgYnV0IHNob3VsZCBiZSBMBAtsYW5kQXNzZXRJZAkAkQMCBQNsb2MFCGxvY0lkeElkBAVhc3NldAkBBXZhbHVlAQkA7AcBCQDZBAEFC2xhbmRBc3NldElkBAd0aW1lS2V5CQEWa2V5U3Rha2VkVGltZUJ5QXNzZXRJZAEFC2xhbmRBc3NldElkBAlzYXZlZFRpbWUJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAnwgBBQd0aW1lS2V5CQCsAgIJAKwCAgIQWW91ciBkdWNrIGlzIG9uIAgFBWFzc2V0BG5hbWUCFSwgd2hpY2ggaXMgbm90IHN0YWtlZAQFb3duZXIJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAoggBCQEVa2V5TGFuZEFzc2V0SWRUb093bmVyAQULbGFuZEFzc2V0SWQJAKwCAgkArAICAgRORlQgCAUFYXNzZXQEbmFtZQIMIGlzIG9ycGhhbmVkAwkBAiE9AgUFb3duZXIFBGFkZHIJAAIBCQCsAgIFCkxBTkRQUkVGSVgCDSBpcyBub3QgeW91cnMEAWQJALUJAggFBWFzc2V0C2Rlc2NyaXB0aW9uAgFfCQCWCgQFC2R1Y2tBc3NldElkBQtsYW5kQXNzZXRJZAUBZAUJc2F2ZWRUaW1lARBjbGFpbVJlc0ludGVybmFsAgRhZGRyBmFtb3VudAMJAGYCAAAFBmFtb3VudAkAAgECD05lZ2F0aXZlIGFtb3VudAQBYwkBFGNoZWNrQ2xhaW1Db25kaXRpb25zAQUEYWRkcgQIbGFuZFNpemUJAJEDAggFAWMCXzMFC3JlY0xhbmRTaXplBA10ZXJyYWluQ291bnRzCQENY291bnRUZXJyYWlucwEJAJEDAggFAWMCXzMFC3JlY1RlcnJhaW5zBAlkZWx0YVRpbWUJAGUCCAUJbGFzdEJsb2NrCXRpbWVzdGFtcAgFAWMCXzQDCQBmAgAABQlkZWx0YVRpbWUJAAIBCQCsAgIJAKwCAgkArAICAiZTYXZlZCB0aW1lc3RhbXAgaXMgaW4gZnV0dXJlLCBzYXZlZCA9IAkApAMBCAUBYwJfNAIMLCBjdXJyZW50ID0gCQCkAwEIBQlsYXN0QmxvY2sJdGltZXN0YW1wBAZwaWVjZXMJAQ9udW1QaWVjZXNCeVNpemUBBQhsYW5kU2l6ZQQWZGFpbHlQcm9kdWN0aW9uQnlQaWVjZQkBDGFwcGx5Qm9udXNlcwIIBQFjAl8yBQZwaWVjZXMECGF2YWlsUmVzCQBrAwUJZGVsdGFUaW1lCQBoAgUWZGFpbHlQcm9kdWN0aW9uQnlQaWVjZQUGcGllY2VzBQlEQVlNSUxMSVMDCQBmAgUGYW1vdW50BQhhdmFpbFJlcwkAAgEJAKwCAgkArAICCQCsAgICIk5vdCBlbm91Z2ggcmVzb3VyY2VzLCBhdmFpbGFibGUgPSAJAKQDAQUIYXZhaWxSZXMCDiwgcmVxdWVzdGVkID0gCQCkAwEFBmFtb3VudAQMbmV3RGVsdGFUaW1lCQBrAwkAZQIFCGF2YWlsUmVzBQZhbW91bnQFCURBWU1JTExJUwkAaAIFFmRhaWx5UHJvZHVjdGlvbkJ5UGllY2UFBnBpZWNlcwQMbmV3VGltZXN0YW1wCQBlAggFCWxhc3RCbG9jawl0aW1lc3RhbXAFDG5ld0RlbHRhVGltZQQFYnBLZXkJARFrZXlCYWNrcGFja0J5RHVjawEIBQFjAl8xBAtjdXJyZW50UGFjawkBC2dldEJhY2twYWNrAQUFYnBLZXkECmN1cnJlbnRSZXMJALUJAgkAkQMCBQtjdXJyZW50UGFjawUIYnBJZHhSZXMCAV8EBWJwUmVzCQEGYWRkUmVzBQUKY3VycmVudFJlcwUNdGVycmFpbkNvdW50cwkAZQIFCWRlbHRhVGltZQUMbmV3RGVsdGFUaW1lCQBpAgUGcGllY2VzBQVTU0laRQUWZGFpbHlQcm9kdWN0aW9uQnlQaWVjZQkAlQoDCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEWa2V5U3Rha2VkVGltZUJ5QXNzZXRJZAEIBQFjAl8yBQxuZXdUaW1lc3RhbXAJAMwIAgkBDEludGVnZXJFbnRyeQIJASJrZXlTdGFrZWRUaW1lQnlUeXBlQXNzZXRJZEFuZE93bmVyAwUKTEFORFBSRUZJWAgFAWMCXzIFBGFkZHIFDG5ld1RpbWVzdGFtcAUDbmlsBQVicEtleQkAzAgCCQCRAwIFC2N1cnJlbnRQYWNrBQpicElkeExldmVsCQDMCAIFBWJwUmVzCQDMCAIJAJEDAgULY3VycmVudFBhY2sFCGJwSWR4TWF0CQDMCAIJAJEDAgULY3VycmVudFBhY2sFCWJwSWR4UHJvZAUDbmlsAQhjbGFpbUFsbAMEYWRkcgtsYW5kQXNzZXRJZAZwaWVjZXMEB3RpbWVLZXkJARZrZXlTdGFrZWRUaW1lQnlBc3NldElkAQULbGFuZEFzc2V0SWQECXNhdmVkVGltZQkBBXZhbHVlAQkAnwgBBQd0aW1lS2V5BAhhdmFpbFJlcwkAaAIJAGsDCQBlAggFCWxhc3RCbG9jawl0aW1lc3RhbXAFCXNhdmVkVGltZQkBDGFwcGx5Qm9udXNlcwIFC2xhbmRBc3NldElkBQZwaWVjZXMFCURBWU1JTExJUwUGcGllY2VzCQEQY2xhaW1SZXNJbnRlcm5hbAIFBGFkZHIFCGF2YWlsUmVzAQ11cEluZnJhQ29tbW9uAwxzaG91bGRVc2VNYXQGY2FsbGVyDXBheW1lbnRBbW91bnQEBGFkZHIJAKUIAQUGY2FsbGVyBAFjCQEUY2hlY2tDbGFpbUNvbmRpdGlvbnMBBQRhZGRyBAZwaWVjZXMJAQ9udW1QaWVjZXNCeVNpemUBCQCRAwIIBQFjAl8zBQtyZWNMYW5kU2l6ZQQIaW5mcmFLZXkJARZrZXlJbmZyYUxldmVsQnlBc3NldElkAQgFAWMCXzIECGN1ckxldmVsCQELdmFsdWVPckVsc2UCCQCfCAEFCGluZnJhS2V5AAADCQBnAgUIY3VyTGV2ZWwAAwkAAgECJkN1cnJlbnRseSBtYXggaW5mcmFzdHJ1Y3R1cmUgbGV2ZWwgPSAzBAhuZXdMZXZlbAkAZAIFCGN1ckxldmVsAAEEBGNvc3QJAGsDBRVJbmZyYVVwZ3JhZGVDb3N0U1VzZG4JAGgCBQZwaWVjZXMFCG5ld0xldmVsBQVTU0laRQMDCQEBIQEFDHNob3VsZFVzZU1hdAkBAiE9AgUNcGF5bWVudEFtb3VudAUEY29zdAcJAAIBCQCsAgICG1BheW1lbnQgYXR0YWNoZWQgc2hvdWxkIGJlIAkApAMBBQRjb3N0BAVicEtleQkBEWtleUJhY2twYWNrQnlEdWNrAQgFAWMCXzEEC2N1cnJlbnRQYWNrCQELZ2V0QmFja3BhY2sBBQVicEtleQQFbUxpc3QJALUJAgkAkQMCBQtjdXJyZW50UGFjawUIYnBJZHhNYXQCAV8EBm5ld01hdAkAuQkCCQERc3VidHJhY3RNYXRlcmlhbHMDBQxzaG91bGRVc2VNYXQFBW1MaXN0CQBrAwURSW5mcmFVcGdyYWRlQ29zdFMJAGgCBQZwaWVjZXMFCG5ld0xldmVsBQVTU0laRQIBXwQLY2xhaW1SZXN1bHQJAQhjbGFpbUFsbAMFBGFkZHIIBQFjAl8yBQZwaWVjZXMJAJQKAgkAzggCCQDMCAIJAQxJbnRlZ2VyRW50cnkCBQhpbmZyYUtleQUIbmV3TGV2ZWwJAMwIAgkBDEludGVnZXJFbnRyeQIJAR5rZXlJbmZyYUxldmVsQnlBc3NldElkQW5kT3duZXICCAUBYwJfMgUEYWRkcgUIbmV3TGV2ZWwJAMwIAgkBC1N0cmluZ0VudHJ5AgUFYnBLZXkJALkJAgkAzAgCCQCRAwIFC2N1cnJlbnRQYWNrBQpicElkeExldmVsCQDMCAIJAJEDAggFC2NsYWltUmVzdWx0Al8zBQhicElkeFJlcwkAzAgCBQZuZXdNYXQJAMwIAgkAkQMCBQtjdXJyZW50UGFjawUJYnBJZHhQcm9kBQNuaWwCAToFA25pbAgFC2NsYWltUmVzdWx0Al8xBQhuZXdMZXZlbAESYWN0aXZhdGVQcmVzYWxlQXJ0AQRhZGRyBAFjCQEUY2hlY2tDbGFpbUNvbmRpdGlvbnMBBQRhZGRyBAtsYW5kQXNzZXRJZAgFAWMCXzIEDWFjdGl2YXRpb25LZXkJAR9rZXlQcmVzYWxlQXJ0QWN0aXZhdGVkQnlBc3NldElkAQULbGFuZEFzc2V0SWQDCQELdmFsdWVPckVsc2UCCQCgCAEFDWFjdGl2YXRpb25LZXkHCQACAQIlUHJlc2FsZSBhcnRpZmFjdCBpcyBhbHJlYWR5IGFjdGl2YXRlZAMJAGYCCQENcGFyc2VJbnRWYWx1ZQEJAJEDAggFAWMCXzMFCnJlY0xhbmROdW0FD1BSRVNBTEVOVU1MQU5EUwkAAgEJAKwCAgkArAICCQCsAgIFCkxBTkRQUkVGSVgCASAFC2xhbmRBc3NldElkAiUgaXMgbm90IGVsaWdpYmxlIGZvciBwcmVzYWxlIGFydGlmYWN0BAZwaWVjZXMJAQ9udW1QaWVjZXNCeVNpemUBCQCRAwIIBQFjAl8zBQtyZWNMYW5kU2l6ZQQLY2xhaW1SZXN1bHQJAQhjbGFpbUFsbAMFBGFkZHIFC2xhbmRBc3NldElkBQZwaWVjZXMJAM0IAgkAzQgCCQDNCAIJAM0IAgkAzQgCCAULY2xhaW1SZXN1bHQCXzEJAQxCb29sZWFuRW50cnkCBQ1hY3RpdmF0aW9uS2V5BgkBDEJvb2xlYW5FbnRyeQIJASdrZXlQcmVzYWxlQXJ0QWN0aXZhdGVkQnlBc3NldElkQW5kT3duZXICBQtsYW5kQXNzZXRJZAUEYWRkcgYJAQxJbnRlZ2VyRW50cnkCCQEga2V5TGFuZEFydFN0YXR1c0J5VHlwZUFuZEFzc2V0SWQCBQpBUlRQUkVTQUxFBQtsYW5kQXNzZXRJZAUGcGllY2VzCQEMSW50ZWdlckVudHJ5AgkBJWtleUxhbmRBcnRTdGF0dXNCeVR5cGVBc3NldElkQW5kT3duZXIDBQpBUlRQUkVTQUxFBQtsYW5kQXNzZXRJZAUEYWRkcgUGcGllY2VzCQELU3RyaW5nRW50cnkCCAULY2xhaW1SZXN1bHQCXzIJALkJAggFC2NsYWltUmVzdWx0Al8zAgE6AQ1tZXJnZUludGVybmFsBwtuZXdMYW5kU2l6ZQhuZXdMZXZlbAdmb3JtdWxhBGFkZHIMbGFuZEFzc2V0SWRzBHR4SWQHbmVlZE1hdAQLZHVja0Fzc2V0SWQJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAoggBCQEUa2V5U3Rha2VkRHVja0J5T3duZXIBBQRhZGRyAhxZb3UgZG9uJ3QgaGF2ZSBhIGR1Y2sgc3Rha2VkCgEKY2hlY2tNZXJnZQIDYWNjC2xhbmRBc3NldElkBAVhc3NldAkBBXZhbHVlAQkA7AcBCQDZBAEFC2xhbmRBc3NldElkBAd0aW1lS2V5CQEWa2V5U3Rha2VkVGltZUJ5QXNzZXRJZAEFC2xhbmRBc3NldElkBAlzYXZlZFRpbWUJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAnwgBBQd0aW1lS2V5CQCsAgIJAKwCAgIETkZUIAgFBWFzc2V0BG5hbWUCDiBpcyBub3Qgc3Rha2VkBAVvd25lcgkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCiCAEJARVrZXlMYW5kQXNzZXRJZFRvT3duZXIBBQtsYW5kQXNzZXRJZAkArAICCQCsAgICBE5GVCAIBQVhc3NldARuYW1lAgwgaXMgb3JwaGFuZWQDCQECIT0CBQVvd25lcgUEYWRkcgkAAgEJAKwCAgUKTEFORFBSRUZJWAINIGlzIG5vdCB5b3VycwQBZAkAtQkCCAUFYXNzZXQLZGVzY3JpcHRpb24CAV8ECWNvbnRpbmVudAkAkQMCBQFkBQxyZWNDb250aW5lbnQDAwkBAiE9AggFA2FjYwJfMwIACQECIT0CCAUDYWNjAl8zBQljb250aW5lbnQHCQACAQIuTGFuZHMgc2hvdWxkIGJlIG9uIHRoZSBzYW1lIGNvbnRpbmVudCB0byBtZXJnZQQIbGFuZFNpemUJAJEDAgUBZAULcmVjTGFuZFNpemUEB3NpemVzSW4IBQNhY2MCXzEEAWkJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAswkCBQdzaXplc0luBQhsYW5kU2l6ZQInWW91IGhhdmVuJ3QgcGFzc2VkIGFsbCB0aGUgbGFuZHMgbmVlZGVkBAhzaXplc091dAkArAICCQCvAgIFB3NpemVzSW4FAWkJALACAgUHc2l6ZXNJbgkAZAIFAWkAAQQGcGllY2VzCQEPbnVtUGllY2VzQnlTaXplAQUIbGFuZFNpemUEBGFydHMJAGQCCAUDYWNjAl8yCQELdmFsdWVPckVsc2UCCQCfCAEJASBrZXlMYW5kQXJ0U3RhdHVzQnlUeXBlQW5kQXNzZXRJZAIFCkFSVFBSRVNBTEUFC2xhbmRBc3NldElkAwkBC3ZhbHVlT3JFbHNlAgkAoAgBCQEfa2V5UHJlc2FsZUFydEFjdGl2YXRlZEJ5QXNzZXRJZAEFC2xhbmRBc3NldElkBwUGcGllY2VzAAAECmluZnJhTGV2ZWwJAQt2YWx1ZU9yRWxzZQIJAJ8IAQkBFmtleUluZnJhTGV2ZWxCeUFzc2V0SWQBBQtsYW5kQXNzZXRJZAAABAhyZXFMZXZlbAQHJG1hdGNoMAUIbGFuZFNpemUDCQAAAgIBUwUHJG1hdGNoMAADAwkAAAICAU0FByRtYXRjaDAABAMJAAACAgFMBQckbWF0Y2gwAAUDCQAAAgICWEwFByRtYXRjaDAABgkAAgECGk9ubHkgUywgTSwgTCwgWEwgY2FuIG1lcmdlAwkBAiE9AgUKaW5mcmFMZXZlbAUIcmVxTGV2ZWwJAAIBAiJBbGwgbGFuZHMgc2hvdWxkIGJlIG1heGVkIHRvIG1lcmdlBAdsYW5kTnVtCQCRAwIFAWQFCnJlY0xhbmROdW0EDXRlcnJhaW5Db3VudHMJAQ1jb3VudFRlcnJhaW5zAQkAkQMCBQFkBQtyZWNUZXJyYWlucwQJZGVsdGFUaW1lCQBlAggFCWxhc3RCbG9jawl0aW1lc3RhbXAFCXNhdmVkVGltZQMJAGYCAAAFCWRlbHRhVGltZQkAAgEJAKwCAgkArAICCQCsAgICJlNhdmVkIHRpbWVzdGFtcCBpcyBpbiBmdXR1cmUsIHNhdmVkID0gCQCkAwEFCXNhdmVkVGltZQIMLCBjdXJyZW50ID0gCQCkAwEIBQlsYXN0QmxvY2sJdGltZXN0YW1wBBZkYWlseVByb2R1Y3Rpb25CeVBpZWNlCQEMYXBwbHlCb251c2VzAgULbGFuZEFzc2V0SWQFBnBpZWNlcwQFYnBSZXMJAQZhZGRSZXMFCQC1CQIIBQNhY2MCXzQCAV8FDXRlcnJhaW5Db3VudHMFCWRlbHRhVGltZQkAaQIFBnBpZWNlcwUFU1NJWkUFFmRhaWx5UHJvZHVjdGlvbkJ5UGllY2UEBXByb3BzCQEZdXBkYXRlUHJvcG9ydGlvbnNJbnRlcm5hbAQJALUJAggFA2FjYwJfNgIBXwUNdGVycmFpbkNvdW50cwkAaQIFBnBpZWNlcwUFU1NJWkUA////////////AQQFbGFuZHMIBQNhY2MCXzcEA2lkeAkAzwgCBQVsYW5kcwULbGFuZEFzc2V0SWQDCQEBIQEJAQlpc0RlZmluZWQBBQNpZHgJAAIBCQCsAgICIFlvdXIgc3Rha2VkIGxhbmRzIGRvbid0IGNvbnRhaW4gBQtsYW5kQXNzZXRJZAkAmQoHBQhzaXplc091dAUEYXJ0cwUJY29udGluZW50BQVicFJlcwkAzQgCCQDNCAIJAM0IAgkAzQgCCQDNCAIJAM0IAgkAzQgCCQDNCAIJAM0IAgkAzQgCCQDNCAIJAM0IAgkAzQgCCAUDYWNjAl81CQELRGVsZXRlRW50cnkBCQEWa2V5U3Rha2VkVGltZUJ5QXNzZXRJZAEFC2xhbmRBc3NldElkCQELRGVsZXRlRW50cnkBCQEia2V5U3Rha2VkVGltZUJ5VHlwZUFzc2V0SWRBbmRPd25lcgMFCkxBTkRQUkVGSVgFC2xhbmRBc3NldElkBQRhZGRyCQELRGVsZXRlRW50cnkBCQEQa2V5TGFuZFRvQXNzZXRJZAEFB2xhbmROdW0JAQtEZWxldGVFbnRyeQEJAQprZXlOZnROYW1lAgUHbGFuZE51bQUIbGFuZFNpemUJAQtEZWxldGVFbnRyeQEJARVrZXlMYW5kQXNzZXRJZFRvT3duZXIBBQtsYW5kQXNzZXRJZAkBC0RlbGV0ZUVudHJ5AQkBFmtleUluZnJhTGV2ZWxCeUFzc2V0SWQBBQtsYW5kQXNzZXRJZAkBC0RlbGV0ZUVudHJ5AQkBHmtleUluZnJhTGV2ZWxCeUFzc2V0SWRBbmRPd25lcgIFC2xhbmRBc3NldElkBQRhZGRyCQELRGVsZXRlRW50cnkBCQEfa2V5UHJlc2FsZUFydEFjdGl2YXRlZEJ5QXNzZXRJZAEFC2xhbmRBc3NldElkCQELRGVsZXRlRW50cnkBCQEna2V5UHJlc2FsZUFydEFjdGl2YXRlZEJ5QXNzZXRJZEFuZE93bmVyAgULbGFuZEFzc2V0SWQFBGFkZHIJAQtEZWxldGVFbnRyeQEJASBrZXlMYW5kQXJ0U3RhdHVzQnlUeXBlQW5kQXNzZXRJZAIFCkFSVFBSRVNBTEUFC2xhbmRBc3NldElkCQELRGVsZXRlRW50cnkBCQEla2V5TGFuZEFydFN0YXR1c0J5VHlwZUFzc2V0SWRBbmRPd25lcgMFCkFSVFBSRVNBTEUFC2xhbmRBc3NldElkBQRhZGRyCQELRGVsZXRlRW50cnkBCQERa2V5TGFuZE51bVRvT3duZXIBBQdsYW5kTnVtCQEEQnVybgIJANkEAQULbGFuZEFzc2V0SWQAAQUFcHJvcHMJANEIAgUFbGFuZHMJAQV2YWx1ZQEFA2lkeAQFYnBLZXkJARFrZXlCYWNrcGFja0J5RHVjawEFC2R1Y2tBc3NldElkBAtjdXJyZW50UGFjawkBC2dldEJhY2twYWNrAQUFYnBLZXkEB3Byb3BTdHIJAQt2YWx1ZU9yRWxzZQIJAKIIAQkBEWtleVJlc1Byb3BvcnRpb25zAAILMF8wXzBfMF8wXzAECGxhbmRzS2V5CQEVa2V5U3Rha2VkTGFuZHNCeU93bmVyAQUEYWRkcgQIbGFuZHNTdHIJAKIIAQUIbGFuZHNLZXkEB2xhbmRzSW4DCQEJaXNEZWZpbmVkAQUIbGFuZHNTdHIJAL0JAgkBBXZhbHVlAQUIbGFuZHNTdHICAV8FA25pbAQBcgoAAiRsBQxsYW5kQXNzZXRJZHMKAAIkcwkAkAMBBQIkbAoABSRhY2MwCQCZCgcFB2Zvcm11bGEAAAIACQCRAwIFC2N1cnJlbnRQYWNrBQhicElkeFJlcwUDbmlsBQdwcm9wU3RyBQdsYW5kc0luCgEFJGYwXzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAQpjaGVja01lcmdlAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGYwXzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhNMaXN0IHNpemUgZXhjZWVkcyA1CQEFJGYwXzICCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECBQUkYWNjMAAAAAEAAgADAAQABQQJY29udGluZW50CAUBcgJfMwQMY29udGluZW50SWR4CQETdmFsdWVPckVycm9yTWVzc2FnZQIJAM8IAgUKY29udGluZW50cwUJY29udGluZW50CQCsAgICE1Vua25vd24gY29udGluZW50OiAFCWNvbnRpbmVudAQIdGVycmFpbnMJAQtnZW5UZXJyYWlucwIJAQNhYnMBCQCeAwEFBHR4SWQFDGNvbnRpbmVudElkeAQHZnJlZU51bQkBC3ZhbHVlT3JFbHNlAgkAnwgBCQESa2V5TmV4dEZyZWVMYW5kTnVtAAkAZAIFD1BSRVNBTEVOVU1MQU5EUwABBApuZXdMYW5kTnVtCQCkAwEFB2ZyZWVOdW0EBWlzc3VlCQDCCAUJAQprZXlOZnROYW1lAgUKbmV3TGFuZE51bQULbmV3TGFuZFNpemUJALkJAgkAzAgCBQpuZXdMYW5kTnVtCQDMCAIFC25ld0xhbmRTaXplCQDMCAIFCHRlcnJhaW5zCQDMCAIFCWNvbnRpbmVudAUDbmlsAgFfAAEAAAcEB2Fzc2V0SWQJALgIAQUFaXNzdWUEDm5ld0xhbmRBc3NldElkCQDYBAEFB2Fzc2V0SWQEBm5ld01hdAkAuQkCCQERc3VidHJhY3RNYXRlcmlhbHMDCQBmAgUHbmVlZE1hdAAACQC1CQIJAJEDAgULY3VycmVudFBhY2sFCGJwSWR4TWF0AgFfBQduZWVkTWF0AgFfCQCUCgIJAM0IAgkAzQgCCQDNCAIJAM0IAgkAzQgCCQDNCAIJAM0IAgkAzQgCCQDNCAIJAM0IAgkAzQgCCQDNCAIJAM0IAgkAzQgCCAUBcgJfNQMJAGYCCQCQAwEIBQFyAl83AAAJAQtTdHJpbmdFbnRyeQIFCGxhbmRzS2V5CQC7CQIIBQFyAl83AgFfCQELRGVsZXRlRW50cnkBBQhsYW5kc0tleQkBDEludGVnZXJFbnRyeQIJARJrZXlOZXh0RnJlZUxhbmROdW0ACQBkAgUHZnJlZU51bQABBQVpc3N1ZQkBC1N0cmluZ0VudHJ5AgkBEGtleUxhbmRUb0Fzc2V0SWQBBQpuZXdMYW5kTnVtBQ5uZXdMYW5kQXNzZXRJZAkBC1N0cmluZ0VudHJ5AgkBFWtleUxhbmRBc3NldElkVG9Pd25lcgEFDm5ld0xhbmRBc3NldElkBQRhZGRyCQELU3RyaW5nRW50cnkCCQERa2V5TGFuZE51bVRvT3duZXIBBQpuZXdMYW5kTnVtBQRhZGRyCQEMSW50ZWdlckVudHJ5AgkBIGtleUxhbmRBcnRTdGF0dXNCeVR5cGVBbmRBc3NldElkAgUKQVJUUFJFU0FMRQUObmV3TGFuZEFzc2V0SWQIBQFyAl8yCQEMSW50ZWdlckVudHJ5AgkBJWtleUxhbmRBcnRTdGF0dXNCeVR5cGVBc3NldElkQW5kT3duZXIDBQpBUlRQUkVTQUxFBQ5uZXdMYW5kQXNzZXRJZAUEYWRkcggFAXICXzIJAQxJbnRlZ2VyRW50cnkCCQEWa2V5SW5mcmFMZXZlbEJ5QXNzZXRJZAEFDm5ld0xhbmRBc3NldElkBQhuZXdMZXZlbAkBDEludGVnZXJFbnRyeQIJAR5rZXlJbmZyYUxldmVsQnlBc3NldElkQW5kT3duZXICBQ5uZXdMYW5kQXNzZXRJZAUEYWRkcgUIbmV3TGV2ZWwJAQtTdHJpbmdFbnRyeQIFBWJwS2V5CQC5CQIJAMwIAgkAkQMCBQtjdXJyZW50UGFjawUKYnBJZHhMZXZlbAkAzAgCCAUBcgJfNAkAzAgCBQZuZXdNYXQJAMwIAgkAkQMCBQtjdXJyZW50UGFjawUJYnBJZHhQcm9kBQNuaWwCAToJAQtTdHJpbmdFbnRyeQIJARFrZXlSZXNQcm9wb3J0aW9ucwAIBQFyAl82CQELU3RyaW5nRW50cnkCCQEPa2V5RHVja0xvY2F0aW9uAQULZHVja0Fzc2V0SWQJALkJAgkAzAgCBQljb250aW5lbnQJAMwIAgIBTAkAzAgCBQ5uZXdMYW5kQXNzZXRJZAUDbmlsAgFfCQEOU2NyaXB0VHJhbnNmZXIDCQERQGV4dHJOYXRpdmUoMTA2MikBBQRhZGRyAAEFB2Fzc2V0SWQFDm5ld0xhbmRBc3NldElkAQNzMm0DBGFkZHIMbGFuZEFzc2V0SWRzBHR4SWQJAQ1tZXJnZUludGVybmFsBwIBTQADAgRTU1NTBQRhZGRyBQxsYW5kQXNzZXRJZHMFBHR4SWQAAAEDbTJsBQRhZGRyDGxhbmRBc3NldElkcwR0eElkDHNob3VsZFVzZU1hdA1wYXltZW50QW1vdW50BARjb3N0CQBoAgUVSW5mcmFVcGdyYWRlQ29zdFNVc2RuAAQDAwkBASEBBQxzaG91bGRVc2VNYXQJAQIhPQIFDXBheW1lbnRBbW91bnQFBGNvc3QHCQACAQkArAICAhtQYXltZW50IGF0dGFjaGVkIHNob3VsZCBiZSAJAKQDAQUEY29zdAkBDW1lcmdlSW50ZXJuYWwHAgFMAAQCA1NNTQUEYWRkcgUMbGFuZEFzc2V0SWRzBQR0eElkCQBoAgURSW5mcmFVcGdyYWRlQ29zdFMABAEEbDJ4bAUEYWRkcgxsYW5kQXNzZXRJZHMEdHhJZAxzaG91bGRVc2VNYXQNcGF5bWVudEFtb3VudAQEY29zdAkAaAIFFUluZnJhVXBncmFkZUNvc3RTVXNkbgAvAwMJAQEhAQUMc2hvdWxkVXNlTWF0CQECIT0CBQ1wYXltZW50QW1vdW50BQRjb3N0BwkAAgEJAKwCAgIbUGF5bWVudCBhdHRhY2hlZCBzaG91bGQgYmUgCQCkAwEFBGNvc3QJAQ1tZXJnZUludGVybmFsBwICWEwABQIFU1NTTUwFBGFkZHIFDGxhbmRBc3NldElkcwUEdHhJZAkAaAIFEUluZnJhVXBncmFkZUNvc3RTAC8BBnhsMnh4bAUEYWRkcgxsYW5kQXNzZXRJZHMEdHhJZAxzaG91bGRVc2VNYXQNcGF5bWVudEFtb3VudAQEY29zdAkAaAIFFUluZnJhVXBncmFkZUNvc3RTVXNkbgA2AwMJAQEhAQUMc2hvdWxkVXNlTWF0CQECIT0CBQ1wYXltZW50QW1vdW50BQRjb3N0BwkAAgEJAKwCAgIbUGF5bWVudCBhdHRhY2hlZCBzaG91bGQgYmUgCQCkAwEFBGNvc3QJAQ1tZXJnZUludGVybmFsBwIDWFhMAAYCA0xYTAUEYWRkcgUMbGFuZEFzc2V0SWRzBQR0eElkCQBoAgURSW5mcmFVcGdyYWRlQ29zdFMANgELbWVyZ2VDb21tb24FDHNob3VsZFVzZU1hdARhZGRyDXBheW1lbnRBbW91bnQMbGFuZEFzc2V0SWRzBHR4SWQEC21lcmdlUmVzdWx0BAckbWF0Y2gwCQCQAwEFDGxhbmRBc3NldElkcwMJAAACAAQFByRtYXRjaDAJAQNzMm0DBQRhZGRyBQxsYW5kQXNzZXRJZHMFBHR4SWQDCQAAAgADBQckbWF0Y2gwCQEDbTJsBQUEYWRkcgUMbGFuZEFzc2V0SWRzBQR0eElkBQxzaG91bGRVc2VNYXQFDXBheW1lbnRBbW91bnQDCQAAAgAFBQckbWF0Y2gwCQEEbDJ4bAUFBGFkZHIFDGxhbmRBc3NldElkcwUEdHhJZAUMc2hvdWxkVXNlTWF0BQ1wYXltZW50QW1vdW50AwkAAAIAAgUHJG1hdGNoMAkBBnhsMnh4bAUFBGFkZHIFDGxhbmRBc3NldElkcwUEdHhJZAUMc2hvdWxkVXNlTWF0BQ1wYXltZW50QW1vdW50CQACAQINVW5rbm93biBtZXJnZQULbWVyZ2VSZXN1bHQBBnByb2xvZwEBaQMJAQt2YWx1ZU9yRWxzZQIJAKAIAQkBCmtleUJsb2NrZWQABwkAAgECH0NvbnRyYWN0cyBhcmUgdW5kZXIgbWFpbnRlbmFuY2UJAQtTdHJpbmdFbnRyeQIJARFrZXlMYXN0VHhJZEJ5VXNlcgEJAKUIAQgFAWkMb3JpZ2luQ2FsbGVyCQDYBAEIBQFpDXRyYW5zYWN0aW9uSWQVAWkBCnNldEJsb2NrZWQBCWlzQmxvY2tlZAMJAQIhPQIIBQFpBmNhbGxlcgUEdGhpcwkAAgECEXBlcm1pc3Npb24gZGVuaWVkCQDMCAIJAQxCb29sZWFuRW50cnkCCQEKa2V5QmxvY2tlZAAFCWlzQmxvY2tlZAUDbmlsAWkBCXN0YWtlTGFuZAAEDHByb2xvZ0FjdGlvbgkBBnByb2xvZwEFAWkDCQECIT0CCQCQAwEIBQFpCHBheW1lbnRzAAEJAAIBAhxFeGFjdGx5IG9uZSBwYXltZW50IHJlcXVpcmVkBANwbXQJAQV2YWx1ZQEJAJEDAggFAWkIcGF5bWVudHMAAAQHYXNzZXRJZAkBBXZhbHVlAQgFA3BtdAdhc3NldElkBAdhZGRyZXNzCQClCAEIBQFpBmNhbGxlcgMJAQIhPQIIBQNwbXQGYW1vdW50AAEJAAIBCQCsAgIJAKwCAgIETkZUIAUKTEFORFBSRUZJWAIkIHRva2VuIHNob3VsZCBiZSBhdHRhY2hlZCBhcyBwYXltZW50BAVhc3NldAkBBXZhbHVlAQkA7AcBBQdhc3NldElkAwkBAiE9AggFBWFzc2V0Bmlzc3VlcgUEdGhpcwkAAgECF1Vua25vd24gaXNzdWVyIG9mIHRva2VuAwkBASEBCQEIY29udGFpbnMCCAUFYXNzZXQEbmFtZQUKTEFORFBSRUZJWAkAAgEJAKwCAgkArAICAglPbmx5IE5GVCAFCkxBTkRQUkVGSVgCFCB0b2tlbnMgYXJlIGFjY2VwdGVkBAtsYW5kTnVtU2l6ZQkAsAICCAUFYXNzZXQEbmFtZQAEBAdsYW5kTnVtAwkBCGNvbnRhaW5zAgULbGFuZE51bVNpemUCA1hYTAkAswICBQtsYW5kTnVtU2l6ZQADAwkBCGNvbnRhaW5zAgULbGFuZE51bVNpemUCAlhMCQCzAgIFC2xhbmROdW1TaXplAAIJALMCAgULbGFuZE51bVNpemUAAQMJAQEhAQkBCWlzRGVmaW5lZAEJALYJAQUHbGFuZE51bQkAAgEJAKwCAgIeQ2Fubm90IHBhcnNlIGxhbmQgbnVtYmVyIGZyb20gCAUFYXNzZXQEbmFtZQQLbGFuZEFzc2V0SWQJANgEAQUHYXNzZXRJZAQHdGltZUtleQkBFmtleVN0YWtlZFRpbWVCeUFzc2V0SWQBBQtsYW5kQXNzZXRJZAMJAQlpc0RlZmluZWQBCQCfCAEFB3RpbWVLZXkJAAIBCQCsAgIJAKwCAgIETkZUIAgFBWFzc2V0BG5hbWUCEiBpcyBhbHJlYWR5IHN0YWtlZAQBZAkAtQkCCAUFYXNzZXQLZGVzY3JpcHRpb24CAV8EDXRlcnJhaW5Db3VudHMJAQ1jb3VudFRlcnJhaW5zAQkAkQMCBQFkBQtyZWNUZXJyYWlucwQFcHJvcHMJARF1cGRhdGVQcm9wb3J0aW9ucwMFDXRlcnJhaW5Db3VudHMJAGkCCQEPbnVtUGllY2VzQnlTaXplAQkAkQMCBQFkBQtyZWNMYW5kU2l6ZQUFU1NJWkUAAQQIbGFuZHNTdHIJAKIIAQkBFWtleVN0YWtlZExhbmRzQnlPd25lcgEFB2FkZHJlc3MEBWxhbmRzAwkBCWlzRGVmaW5lZAEFCGxhbmRzU3RyCQC9CQIJAQV2YWx1ZQEFCGxhbmRzU3RyAgFfBQNuaWwDCQEPY29udGFpbnNFbGVtZW50AgUFbGFuZHMFC2xhbmRBc3NldElkCQACAQkArAICAiJZb3VyIHN0YWtlZCBsYW5kcyBhbHJlYWR5IGNvbnRhaW4gBQtsYW5kQXNzZXRJZAkAzAgCCQEMSW50ZWdlckVudHJ5AgUHdGltZUtleQgFCWxhc3RCbG9jawl0aW1lc3RhbXAJAMwIAgkBDEludGVnZXJFbnRyeQIJASJrZXlTdGFrZWRUaW1lQnlUeXBlQXNzZXRJZEFuZE93bmVyAwUKTEFORFBSRUZJWAULbGFuZEFzc2V0SWQFB2FkZHJlc3MIBQlsYXN0QmxvY2sJdGltZXN0YW1wCQDMCAIJAQtTdHJpbmdFbnRyeQIJARVrZXlTdGFrZWRMYW5kc0J5T3duZXIBBQdhZGRyZXNzCQC7CQIJAM0IAgUFbGFuZHMFC2xhbmRBc3NldElkAgFfCQDMCAIJAQtTdHJpbmdFbnRyeQIJARVrZXlMYW5kQXNzZXRJZFRvT3duZXIBBQtsYW5kQXNzZXRJZAUHYWRkcmVzcwkAzAgCCQELU3RyaW5nRW50cnkCCQERa2V5TGFuZE51bVRvT3duZXIBBQdsYW5kTnVtBQdhZGRyZXNzCQDMCAIJAQtTdHJpbmdFbnRyeQIJARFrZXlSZXNQcm9wb3J0aW9ucwAFBXByb3BzCQDMCAIFDHByb2xvZ0FjdGlvbgUDbmlsAWkBC3Vuc3Rha2VMYW5kARJsYW5kQXNzZXRJZElnbm9yZWQEDHByb2xvZ0FjdGlvbgkBBnByb2xvZwEFAWkDCQECIT0CCQCQAwEIBQFpCHBheW1lbnRzAAAJAAIBAiR1bnN0YWtlIGRvZXNuJ3QgcmVxdWlyZSBhbnkgcGF5bWVudHMEBGFkZHIJAKUIAQgFAWkGY2FsbGVyBAFjCQEUY2hlY2tDbGFpbUNvbmRpdGlvbnMBBQRhZGRyBAtsYW5kQXNzZXRJZAgFAWMCXzIECGxhbmRzS2V5CQEVa2V5U3Rha2VkTGFuZHNCeU93bmVyAQUEYWRkcgQNdGVycmFpbkNvdW50cwkBDWNvdW50VGVycmFpbnMBCQCRAwIIBQFjAl8zBQtyZWNUZXJyYWlucwQGcGllY2VzCQEPbnVtUGllY2VzQnlTaXplAQkAkQMCCAUBYwJfMwULcmVjTGFuZFNpemUEBXByb3BzCQERdXBkYXRlUHJvcG9ydGlvbnMDBQ10ZXJyYWluQ291bnRzCQBpAgUGcGllY2VzBQVTU0laRQD///////////8BBAtjbGFpbVJlc3VsdAkBCGNsYWltQWxsAwUEYWRkcgULbGFuZEFzc2V0SWQFBnBpZWNlcwQFbGFuZHMJAL0JAgkBC3ZhbHVlT3JFbHNlAgkAoggBBQhsYW5kc0tleQIAAgFfBANpZHgJAM8IAgUFbGFuZHMFC2xhbmRBc3NldElkAwkBASEBCQEJaXNEZWZpbmVkAQUDaWR4CQACAQkArAICAiBZb3VyIHN0YWtlZCBsYW5kcyBkb24ndCBjb250YWluIAULbGFuZEFzc2V0SWQJAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwgFAWkGY2FsbGVyAAEJANkEAQULbGFuZEFzc2V0SWQJAMwIAgkBC0RlbGV0ZUVudHJ5AQkBFmtleVN0YWtlZFRpbWVCeUFzc2V0SWQBBQtsYW5kQXNzZXRJZAkAzAgCCQELRGVsZXRlRW50cnkBCQEia2V5U3Rha2VkVGltZUJ5VHlwZUFzc2V0SWRBbmRPd25lcgMFCkxBTkRQUkVGSVgFC2xhbmRBc3NldElkBQRhZGRyCQDMCAIJAQtTdHJpbmdFbnRyeQIJARFrZXlSZXNQcm9wb3J0aW9ucwAFBXByb3BzCQDMCAIJAQtTdHJpbmdFbnRyeQIIBQtjbGFpbVJlc3VsdAJfMgkAuQkCCAULY2xhaW1SZXN1bHQCXzMCAToJAMwIAgMJAGYCCQCQAwEFBWxhbmRzAAEJAQtTdHJpbmdFbnRyeQIFCGxhbmRzS2V5CQC7CQIJANEIAgUFbGFuZHMJAQV2YWx1ZQEFA2lkeAIBXwkBC0RlbGV0ZUVudHJ5AQUIbGFuZHNLZXkJAMwIAgUMcHJvbG9nQWN0aW9uBQNuaWwBaQEJc3Rha2VEdWNrAAQMcHJvbG9nQWN0aW9uCQEGcHJvbG9nAQUBaQMJAQIhPQIJAJADAQgFAWkIcGF5bWVudHMAAQkAAgECHEV4YWN0bHkgb25lIHBheW1lbnQgcmVxdWlyZWQEA3BtdAkBBXZhbHVlAQkAkQMCCAUBaQhwYXltZW50cwAABAdhc3NldElkCQEFdmFsdWUBCAUDcG10B2Fzc2V0SWQEB2FkZHJlc3MJAKUIAQgFAWkGY2FsbGVyAwkBAiE9AggFA3BtdAZhbW91bnQAAQkAAgEJAKwCAgkArAICAgRORlQgBQpEVUNLUFJFRklYAiQgdG9rZW4gc2hvdWxkIGJlIGF0dGFjaGVkIGFzIHBheW1lbnQEBWFzc2V0CQEFdmFsdWUBCQDsBwEFB2Fzc2V0SWQDAwkBAiE9AggFBWFzc2V0Bmlzc3VlcgUNaW5jdWJhdG9yQWRkcgkBAiE9AggFBWFzc2V0Bmlzc3VlcgULYnJlZWRlckFkZHIHCQACAQkArAICCQCsAgICElVua25vd24gaXNzdWVyIG9mIAUKRFVDS1BSRUZJWAIGIHRva2VuAwkBASEBCQEIY29udGFpbnMCCAUFYXNzZXQEbmFtZQUKRFVDS1BSRUZJWAkAAgEJAKwCAgkArAICAglPbmx5IE5GVCAFCkRVQ0tQUkVGSVgCFCB0b2tlbnMgYXJlIGFjY2VwdGVkBAphc3NldElkU3RyCQDYBAEFB2Fzc2V0SWQEB3RpbWVLZXkJARZrZXlTdGFrZWRUaW1lQnlBc3NldElkAQUKYXNzZXRJZFN0cgMJAQlpc0RlZmluZWQBCQCfCAEFB3RpbWVLZXkJAAIBCQCsAgIJAKwCAgIETkZUIAgFBWFzc2V0BG5hbWUCEiBpcyBhbHJlYWR5IHN0YWtlZAMJAQlpc0RlZmluZWQBCQCiCAEJARRrZXlTdGFrZWREdWNrQnlPd25lcgEFB2FkZHJlc3MJAAIBCQCsAgICHVlvdSBhbHJlYWR5IHN0YWtlZCBvbmUgZHVjazogCAUFYXNzZXQEbmFtZQQGbG9jS2V5CQEPa2V5RHVja0xvY2F0aW9uAQUKYXNzZXRJZFN0cgQIbG9jYXRpb24JAKIIAQUGbG9jS2V5BAVicEtleQkBEWtleUJhY2twYWNrQnlEdWNrAQUKYXNzZXRJZFN0cgQIYmFja3BhY2sJAKIIAQUFYnBLZXkJAM4IAgkAzAgCCQEMSW50ZWdlckVudHJ5AgUHdGltZUtleQgFCWxhc3RCbG9jawl0aW1lc3RhbXAJAMwIAgkBDEludGVnZXJFbnRyeQIJASJrZXlTdGFrZWRUaW1lQnlUeXBlQXNzZXRJZEFuZE93bmVyAwUKRFVDS1BSRUZJWAkA2AQBBQdhc3NldElkBQdhZGRyZXNzCAUJbGFzdEJsb2NrCXRpbWVzdGFtcAkAzAgCCQELU3RyaW5nRW50cnkCCQEQa2V5RHVja0lkVG9Pd25lcgEFCmFzc2V0SWRTdHIFB2FkZHJlc3MJAMwIAgkBC1N0cmluZ0VudHJ5AgkBFGtleVN0YWtlZER1Y2tCeU93bmVyAQUHYWRkcmVzcwUKYXNzZXRJZFN0cgUDbmlsAwkBCWlzRGVmaW5lZAEFCGxvY2F0aW9uBQNuaWwJAM4IAgkAzAgCCQELU3RyaW5nRW50cnkCBQZsb2NLZXkFD0RFRkFVTFRMT0NBVElPTgUDbmlsAwkBCWlzRGVmaW5lZAEFCGJhY2twYWNrBQNuaWwJAM0IAgkAzQgCCQDMCAIJAQtTdHJpbmdFbnRyeQIFBWJwS2V5AhowOjBfMF8wXzBfMF8wOjBfMF8wXzBfMF8wOgUDbmlsCQEMSW50ZWdlckVudHJ5AgkBDWtleUR1Y2tIZWFsdGgBBQphc3NldElkU3RyAGQFDHByb2xvZ0FjdGlvbgFpAQt1bnN0YWtlRHVjawEKYXNzZXRJZFN0cgQMcHJvbG9nQWN0aW9uCQEGcHJvbG9nAQUBaQMJAQIhPQIJAJADAQgFAWkIcGF5bWVudHMAAAkAAgECJHVuc3Rha2UgZG9lc24ndCByZXF1aXJlIGFueSBwYXltZW50cwQHYXNzZXRJZAkA2QQBBQphc3NldElkU3RyBAdhZGRyZXNzCQClCAEIBQFpBmNhbGxlcgQFYXNzZXQJAQV2YWx1ZQEJAOwHAQUHYXNzZXRJZAQHdGltZUtleQkBFmtleVN0YWtlZFRpbWVCeUFzc2V0SWQBCQDYBAEFB2Fzc2V0SWQDCQEBIQEJAQlpc0RlZmluZWQBBQd0aW1lS2V5CQACAQkArAICCQCsAgICBE5GVCAIBQVhc3NldARuYW1lAg4gaXMgbm90IHN0YWtlZAMJAQEhAQkBCWlzRGVmaW5lZAEJARRrZXlTdGFrZWREdWNrQnlPd25lcgEFB2FkZHJlc3MJAAIBCQCsAgIJAKwCAgIJVGhlIGR1Y2sgCAUFYXNzZXQEbmFtZQIOIGlzIG5vdCBzdGFrZWQEBW93bmVyCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKIIAQkBEGtleUR1Y2tJZFRvT3duZXIBCQDYBAEFB2Fzc2V0SWQJAKwCAgkArAICAgRORlQgCAUFYXNzZXQEbmFtZQIMIGlzIG9ycGhhbmVkAwkBAiE9AgUFb3duZXIFB2FkZHJlc3MJAAIBAhdTdGFrZWQgTkZUIGlzIG5vdCB5b3VycwQJa2V5SGVhbHRoCQENa2V5RHVja0hlYWx0aAEFCmFzc2V0SWRTdHIEBmhlYWx0aAkBC3ZhbHVlT3JFbHNlAgkAnwgBBQlrZXlIZWFsdGgAZAMJAQIhPQIFBmhlYWx0aABkCQACAQImUGxlYXNlIGhlYWwgeW91ciBkdWNrIGJlZm9yZSB1bnN0YWtpbmcJAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwgFAWkGY2FsbGVyAAEFB2Fzc2V0SWQJAMwIAgkBC0RlbGV0ZUVudHJ5AQUHdGltZUtleQkAzAgCCQELRGVsZXRlRW50cnkBBQlrZXlIZWFsdGgJAMwIAgkBC0RlbGV0ZUVudHJ5AQkBD2tleUR1Y2tMb2NhdGlvbgEFCmFzc2V0SWRTdHIJAMwIAgkBC0RlbGV0ZUVudHJ5AQkBEGtleUR1Y2tJZFRvT3duZXIBBQphc3NldElkU3RyCQDMCAIJAQtEZWxldGVFbnRyeQEJASJrZXlTdGFrZWRUaW1lQnlUeXBlQXNzZXRJZEFuZE93bmVyAwUKRFVDS1BSRUZJWAUKYXNzZXRJZFN0cgUHYWRkcmVzcwkAzAgCCQELRGVsZXRlRW50cnkBCQEUa2V5U3Rha2VkRHVja0J5T3duZXIBBQdhZGRyZXNzCQDMCAIFDHByb2xvZ0FjdGlvbgUDbmlsAWkBCGNsYWltUmVzAgZhbW91bnQObGFuZEFzc2V0SWRTdHIEDHByb2xvZ0FjdGlvbgkBBnByb2xvZwEFAWkDCQECIT0CCQCQAwEIBQFpCHBheW1lbnRzAAAJAAIBAiVjbGFpbVJlcyBkb2Vzbid0IHJlcXVpcmUgYW55IHBheW1lbnRzBARhZGRyCQClCAEIBQFpDG9yaWdpbkNhbGxlcgQGcmVzdWx0CQEQY2xhaW1SZXNJbnRlcm5hbAIFBGFkZHIFBmFtb3VudAkAlAoCCQDNCAIJAM0IAggFBnJlc3VsdAJfMQkBC1N0cmluZ0VudHJ5AggFBnJlc3VsdAJfMgkAuQkCCAUGcmVzdWx0Al8zAgE6BQxwcm9sb2dBY3Rpb24JAJEDAggFBnJlc3VsdAJfMwUIYnBJZHhSZXMBaQEGZmxpZ2h0AgdtZXNzYWdlA3NpZwQMcHJvbG9nQWN0aW9uCQEGcHJvbG9nAQUBaQMJAQEhAQkAxBMDBQdtZXNzYWdlBQNzaWcFA3B1YgkAAgECGHNpZ25hdHVyZSBkb2VzIG5vdCBtYXRjaAMJAQIhPQIJAJADAQgFAWkIcGF5bWVudHMAAAkAAgECI2ZsaWdodCBkb2Vzbid0IHJlcXVpcmUgYW55IHBheW1lbnRzBAVwYXJ0cwkAtQkCCQCwCQEFB21lc3NhZ2UCATsEAmhwCQC1CQIJAJEDAgkAtQkCCQCRAwIFBXBhcnRzAAACAXwAAAIBXwQFY3VySFAJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQJocAAABAVuZXdIUAkBDXBhcnNlSW50VmFsdWUBCQCRAwIFAmhwAAEEDW5ld0xvY0FuZFRpbWUJALUJAgkAkQMCBQVwYXJ0cwABAgE6BAtuZXdMb2NhdGlvbgkAkQMCBQ1uZXdMb2NBbmRUaW1lAAAEBHRpbWUJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQ1uZXdMb2NBbmRUaW1lAAEDAwkAZgIFBHRpbWUJAGQCCAUJbGFzdEJsb2NrCXRpbWVzdGFtcAURRklWRU1JTlVURVNNSUxMSVMGCQBmAgkAZQIIBQlsYXN0QmxvY2sJdGltZXN0YW1wBRFGSVZFTUlOVVRFU01JTExJUwUEdGltZQkAAgECEnNpZ25hdHVyZSBvdXRkYXRlZAQLZHVja0Fzc2V0SWQJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAoggBCQEUa2V5U3Rha2VkRHVja0J5T3duZXIBCQClCAEIBQFpBmNhbGxlcgIcWW91IGRvbid0IGhhdmUgYSBkdWNrIHN0YWtlZAQJa2V5SGVhbHRoCQENa2V5RHVja0hlYWx0aAEFC2R1Y2tBc3NldElkBAxvbGRGcm9tU3RhdGUJAQt2YWx1ZU9yRWxzZQIJAJ8IAQUJa2V5SGVhbHRoAGQDCQECIT0CBQxvbGRGcm9tU3RhdGUFBWN1ckhQCQACAQkArAICCQCsAgIJAKwCAgIKb2xkSGVhbHRoPQkApAMBCQELdmFsdWVPckVsc2UCCQCfCAEFCWtleUhlYWx0aABkAi8gZnJvbSBzdGF0ZSBkb2VzIG5vdCBtYXRjaCBvbmUgZnJvbSBmbGlnaHQgbG9nPQkApAMBBQVjdXJIUAMJAGcCAAAFBWN1ckhQCQACAQIeWW91IGNhbid0IGZseSB3aXRoIHplcm8gaGVhbHRoBAZsb2NLZXkJAQ9rZXlEdWNrTG9jYXRpb24BBQtkdWNrQXNzZXRJZAQLY3VyTG9jYXRpb24JAQt2YWx1ZU9yRWxzZQIJAKIIAQUGbG9jS2V5BQ9ERUZBVUxUTE9DQVRJT04DCQAAAgULbmV3TG9jYXRpb24FC2N1ckxvY2F0aW9uCQACAQIiWW91IGNhbid0IGZseSB0byB0aGUgc2FtZSBsb2NhdGlvbgkAlAoCCQDMCAIJAQtTdHJpbmdFbnRyeQIFBmxvY0tleQMJAGYCBQVuZXdIUAAABQtuZXdMb2NhdGlvbgULY3VyTG9jYXRpb24JAMwIAgkBDEludGVnZXJFbnRyeQIFCWtleUhlYWx0aAUFbmV3SFAJAMwIAgUMcHJvbG9nQWN0aW9uBQNuaWwFBHVuaXQBaQEJc2V0SGVhbHRoAgZoZWFsdGgLZHVja0Fzc2V0SWQEDHByb2xvZ0FjdGlvbgkBBnByb2xvZwEFAWkDAwkAZgIAAAUGaGVhbHRoBgkAZgIFBmhlYWx0aABkCQACAQIaSFAgc2hvdWxkIGJlIHdpdGhpbiAwLi4xMDAJAMwIAgkBDEludGVnZXJFbnRyeQIJAQ1rZXlEdWNrSGVhbHRoAQULZHVja0Fzc2V0SWQFBmhlYWx0aAkAzAgCBQxwcm9sb2dBY3Rpb24FA25pbAFpAQRoZWFsAgdtYXRUeXBlBmFtb3VudAQMcHJvbG9nQWN0aW9uCQEGcHJvbG9nAQUBaQMDCQBmAgAABQdtYXRUeXBlBgkAZwIFB21hdFR5cGUFBk5VTVJFUwkAAgEJAKwCAgISVW5rbm93biBtYXRlcmlhbDogCQCkAwEFB21hdFR5cGUDCQBnAgAABQZhbW91bnQJAAIBCQCsAgICG0Ftb3VudCBzaG91bGQgYmUgcG9zaXRpdmUhIAkApAMBBQZhbW91bnQEC2R1Y2tBc3NldElkCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKIIAQkBFGtleVN0YWtlZER1Y2tCeU93bmVyAQkApQgBCAUBaQZjYWxsZXICHFlvdSBkb24ndCBoYXZlIGEgZHVjayBzdGFrZWQECWtleUhlYWx0aAkBDWtleUR1Y2tIZWFsdGgBBQtkdWNrQXNzZXRJZAQJb2xkSGVhbHRoCQELdmFsdWVPckVsc2UCCQCfCAEFCWtleUhlYWx0aABkAwkAZwIFCW9sZEhlYWx0aABkCQACAQIaSFAgc2hvdWxkIGJlIDwgMTAwIHRvIGhlYWwEBWJwS2V5CQERa2V5QmFja3BhY2tCeUR1Y2sBBQtkdWNrQXNzZXRJZAQLY3VycmVudFBhY2sJAQtnZXRCYWNrcGFjawEFBWJwS2V5BAVtTGlzdAkAtQkCCQCRAwIFC2N1cnJlbnRQYWNrBQhicElkeE1hdAIBXwQNY3VycmVudEFtb3VudAkBDXBhcnNlSW50VmFsdWUBCQCRAwIFBW1MaXN0BQdtYXRUeXBlBAtkZWx0YUhlYWx0aAkAlwMBCQDMCAIJAGkCBQZhbW91bnQFCEhFQUxDT1NUCQDMCAIJAGUCAGQFCW9sZEhlYWx0aAUDbmlsBAtzcGVuZEFtb3VudAkAaAIFC2RlbHRhSGVhbHRoBQhIRUFMQ09TVAMJAGYCBQtzcGVuZEFtb3VudAUNY3VycmVudEFtb3VudAkAAgEJAKwCAgkArAICCQCsAgIJAKwCAgkArAICAglZb3UgbmVlZCAJAKQDAQULc3BlbmRBbW91bnQCBCBvZiAJAJEDAgUIbWF0VHlwZXMFB21hdFR5cGUCJCB0byBoZWFsLCBidXQgeW91IGJhY2twYWNrIGNvbnRhaW5zIAkApAMBBQ1jdXJyZW50QW1vdW50BAZuZXdNYXQJAQxzdWJPbmVJbkxpc3QDBQVtTGlzdAUHbWF0VHlwZQULc3BlbmRBbW91bnQJAMwIAgkBDEludGVnZXJFbnRyeQIFCWtleUhlYWx0aAkAZAIFCW9sZEhlYWx0aAULZGVsdGFIZWFsdGgJAMwIAgkBC1N0cmluZ0VudHJ5AgUFYnBLZXkJALkJAgkAzAgCCQCRAwIFC2N1cnJlbnRQYWNrBQpicElkeExldmVsCQDMCAIJAJEDAgULY3VycmVudFBhY2sFCGJwSWR4UmVzCQDMCAIFBm5ld01hdAkAzAgCCQCRAwIFC2N1cnJlbnRQYWNrBQlicElkeFByb2QFA25pbAIBOgkAzAgCBQxwcm9sb2dBY3Rpb24FA25pbAFpAQ51cGRhdGVCYWNrcGFjawILZHVja0Fzc2V0SWQHbmV3UGFjawQMcHJvbG9nQWN0aW9uCQEGcHJvbG9nAQUBaQMJAQIhPQIIBQFpBmNhbGxlcgUPZWNvbm9teUNvbnRyYWN0CQACAQIRcGVybWlzc2lvbiBkZW5pZWQJAJQKAgkAzAgCCQELU3RyaW5nRW50cnkCCQERa2V5QmFja3BhY2tCeUR1Y2sBBQtkdWNrQXNzZXRJZAUHbmV3UGFjawkAzAgCBQxwcm9sb2dBY3Rpb24FA25pbAUHbmV3UGFjawFpAQhidXlTTGFuZAAEDHByb2xvZ0FjdGlvbgkBBnByb2xvZwEFAWkDCQECIT0CCQCQAwEIBQFpCHBheW1lbnRzAAEJAAIBAhxFeGFjdGx5IG9uZSBwYXltZW50IHJlcXVpcmVkBANwbXQJAQV2YWx1ZQEJAJEDAggFAWkIcGF5bWVudHMAAAMJAQIhPQIIBQNwbXQHYXNzZXRJZAULdXNkbkFzc2V0SWQJAAIBAhpBbGxvd2VkIFVTRE4gcGF5bWVudCBvbmx5IQMJAQIhPQIIBQNwbXQGYW1vdW50BQdFWFBVU0ROCQACAQkArAICAhtQYXltZW50IGF0dGFjaGVkIHNob3VsZCBiZSAJAKQDAQUHRVhQVVNETgQGcmVzdWx0CQESZXhwZWRpdGlvbkludGVybmFsAggFAWkGY2FsbGVyCAUBaQ10cmFuc2FjdGlvbklkCQCUCgIJAM0IAgkAzQgCCAUGcmVzdWx0Al8xCQEOU2NyaXB0VHJhbnNmZXIDBQ9lY29ub215Q29udHJhY3QIBQNwbXQGYW1vdW50BQt1c2RuQXNzZXRJZAUMcHJvbG9nQWN0aW9uCAgFBnJlc3VsdAJfMgJfMQFpAQ1leHBlZGl0aW9uQnV5AgdtZXNzYWdlA3NpZwQMcHJvbG9nQWN0aW9uCQEGcHJvbG9nAQUBaQMJAQIhPQIJAJADAQgFAWkIcGF5bWVudHMAAQkAAgECHEV4YWN0bHkgb25lIHBheW1lbnQgcmVxdWlyZWQEA3BtdAkBBXZhbHVlAQkAkQMCCAUBaQhwYXltZW50cwAAAwkBAiE9AggFA3BtdAdhc3NldElkBQt1c2RuQXNzZXRJZAkAAgECGkFsbG93ZWQgVVNETiBwYXltZW50IG9ubHkhAwkBAiE9AggFA3BtdAZhbW91bnQFB0VYUFVTRE4JAAIBCQCsAgICG1BheW1lbnQgYXR0YWNoZWQgc2hvdWxkIGJlIAkApAMBBQdFWFBVU0ROBAZyZXN1bHQJARBleHBlZGl0aW9uQ29tbW9uBQcIBQFpBmNhbGxlcggFAWkNdHJhbnNhY3Rpb25JZAUHbWVzc2FnZQUDc2lnAwkAAAIIBQZyZXN1bHQCXzICAAUGcmVzdWx0CQCUCgIJAM0IAgkAzQgCCAUGcmVzdWx0Al8xCQEOU2NyaXB0VHJhbnNmZXIDBQ9lY29ub215Q29udHJhY3QIBQNwbXQGYW1vdW50BQt1c2RuQXNzZXRJZAUMcHJvbG9nQWN0aW9uCAUGcmVzdWx0Al8yAWkBCmV4cGVkaXRpb24CB21lc3NhZ2UDc2lnBAxwcm9sb2dBY3Rpb24JAQZwcm9sb2cBBQFpAwkBAiE9AgkAkAMBCAUBaQhwYXltZW50cwAACQACAQInZXhwZWRpdGlvbiBkb2Vzbid0IHJlcXVpcmUgYW55IHBheW1lbnRzBAZyZXN1bHQJARBleHBlZGl0aW9uQ29tbW9uBQYIBQFpBmNhbGxlcggFAWkNdHJhbnNhY3Rpb25JZAUHbWVzc2FnZQUDc2lnCQCUCgIJAM0IAggFBnJlc3VsdAJfMQUMcHJvbG9nQWN0aW9uCAUGcmVzdWx0Al8yAWkBDHVwZ3JhZGVJbmZyYQESbGFuZEFzc2V0SWRJZ25vcmVkBAxwcm9sb2dBY3Rpb24JAQZwcm9sb2cBBQFpAwkBAiE9AgkAkAMBCAUBaQhwYXltZW50cwAACQACAQIzSW5mcmFzdHJ1Y3R1cmUgdXBncmFkZSBkb2Vzbid0IHJlcXVpcmUgYW55IHBheW1lbnRzBAZyZXN1bHQJAQ11cEluZnJhQ29tbW9uAwYIBQFpBmNhbGxlcgAACQCUCgIJAM0IAggFBnJlc3VsdAJfMQUMcHJvbG9nQWN0aW9uCAUGcmVzdWx0Al8yAWkBEHVwZ3JhZGVJbmZyYVVzZG4BEmxhbmRBc3NldElkSWdub3JlZAQMcHJvbG9nQWN0aW9uCQEGcHJvbG9nAQUBaQMJAQIhPQIJAJADAQgFAWkIcGF5bWVudHMAAQkAAgECHEV4YWN0bHkgb25lIHBheW1lbnQgcmVxdWlyZWQEA3BtdAkBBXZhbHVlAQkAkQMCCAUBaQhwYXltZW50cwAAAwkBAiE9AggFA3BtdAdhc3NldElkBQt1c2RuQXNzZXRJZAkAAgECGkFsbG93ZWQgVVNETiBwYXltZW50IG9ubHkhBAZyZXN1bHQJAQ11cEluZnJhQ29tbW9uAwcIBQFpBmNhbGxlcggFA3BtdAZhbW91bnQJAJQKAgkAzQgCCQDNCAIIBQZyZXN1bHQCXzEJAQ5TY3JpcHRUcmFuc2ZlcgMFD2Vjb25vbXlDb250cmFjdAgFA3BtdAZhbW91bnQFC3VzZG5Bc3NldElkBQxwcm9sb2dBY3Rpb24IBQZyZXN1bHQCXzIBaQEQYWN0aXZhdGVBcnRpZmFjdAEHYXJ0TmFtZQQMcHJvbG9nQWN0aW9uCQEGcHJvbG9nAQUBaQMJAQIhPQIJAJADAQgFAWkIcGF5bWVudHMAAAkAAgECMEFydGlmYWN0IGFjdGl2YXRpb24gZG9lc24ndCByZXF1aXJlIGFueSBwYXltZW50cwQGcmVzdWx0BAckbWF0Y2gwBQdhcnROYW1lAwkAAAICB1BSRVNBTEUFByRtYXRjaDAJARJhY3RpdmF0ZVByZXNhbGVBcnQBCQClCAEIBQFpBmNhbGxlcgkAAgECEFVua25vd24gYXJ0aWZhY3QJAM0IAgUGcmVzdWx0BQxwcm9sb2dBY3Rpb24BaQEKbWVyZ2VMYW5kcwEMbGFuZEFzc2V0SWRzBAxwcm9sb2dBY3Rpb24JAQZwcm9sb2cBBQFpAwkBAiE9AgkAkAMBCAUBaQhwYXltZW50cwAACQACAQIqTGFuZHMgbWVyZ2luZyBkb2Vzbid0IHJlcXVpcmUgYW55IHBheW1lbnRzBAZyZXN1bHQJAQttZXJnZUNvbW1vbgUGCQClCAEIBQFpBmNhbGxlcgAABQxsYW5kQXNzZXRJZHMIBQFpDXRyYW5zYWN0aW9uSWQJAJQKAgkAzQgCCAUGcmVzdWx0Al8xBQxwcm9sb2dBY3Rpb24IBQZyZXN1bHQCXzIBaQEObWVyZ2VMYW5kc1VzZG4BDGxhbmRBc3NldElkcwQMcHJvbG9nQWN0aW9uCQEGcHJvbG9nAQUBaQMJAQIhPQIJAJADAQgFAWkIcGF5bWVudHMAAQkAAgECHEV4YWN0bHkgb25lIHBheW1lbnQgcmVxdWlyZWQEA3BtdAkBBXZhbHVlAQkAkQMCCAUBaQhwYXltZW50cwAAAwkBAiE9AggFA3BtdAdhc3NldElkBQt1c2RuQXNzZXRJZAkAAgECGkFsbG93ZWQgVVNETiBwYXltZW50IG9ubHkhBAZyZXN1bHQJAQttZXJnZUNvbW1vbgUHCQClCAEIBQFpBmNhbGxlcggFA3BtdAZhbW91bnQFDGxhbmRBc3NldElkcwgFAWkNdHJhbnNhY3Rpb25JZAkAlAoCCQDNCAIJAM0IAggFBnJlc3VsdAJfMQkBDlNjcmlwdFRyYW5zZmVyAwUPZWNvbm9teUNvbnRyYWN0CAUDcG10BmFtb3VudAULdXNkbkFzc2V0SWQFDHByb2xvZ0FjdGlvbggFBnJlc3VsdAJfMgFpARxzcGxpdEJ5R2xvYmFsV2VpZ2h0c1JFQURPTkxZAQZhbW91bnQJAJQKAgUDbmlsCQESZ2V0TmVlZGVkTWF0ZXJpYWxzAQUGYW1vdW50AWkBG3NwbGl0QnlMb2NhbFdlaWdodHNSRUFET05MWQIGYW1vdW50CHRlcnJhaW5zBA10ZXJyYWluQ291bnRzCQENY291bnRUZXJyYWlucwEFCHRlcnJhaW5zCQCUCgIFA25pbAkBE2Rpc3RyaWJ1dGVCeVdlaWdodHMCBQZhbW91bnQFDXRlcnJhaW5Db3VudHMBaQETZ2V0QmFja3BhY2tSRUFET05MWQELZHVja0Fzc2V0SWQJAJQKAgUDbmlsCQC5CQIJAQtnZXRCYWNrcGFjawEJARFrZXlCYWNrcGFja0J5RHVjawEFC2R1Y2tBc3NldElkAgE6AIhEa6g=", "height": 3502028, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: 2bdXR5o749gf4wGve1noJMMiUhvGA61adYNYqAr3TRpw Next: BQGo9Ctdd2x6udTSw7bd8Aje967VWx5FezHNuNVsi5m8 Diff:
OldNewDifferences
442442 }
443443
444444
445+func expeditionInternal (caller,txId) = {
446+ let userAddr = toString(caller)
447+ let bigNum = abs(toBigInt(txId))
448+ let freeNum = valueOrElse(getInteger(keyNextFreeLandNum()), (PRESALENUMLANDS + 1))
449+ let landNum = toString(freeNum)
450+ let continentIdx = toInt((bigNum % FIVEX))
451+ let terrains = genTerrains(bigNum, continentIdx)
452+ let continent = continents[continentIdx]
453+ let issue = Issue(keyNftName(landNum, "S"), makeString([landNum, "S", terrains, continent], "_"), 1, 0, false)
454+ let assetId = calculateAssetId(issue)
455+ let id = toBase58String(assetId)
456+ $Tuple2([IntegerEntry(keyNextFreeLandNum(), (freeNum + 1)), issue, StringEntry(keyLandToAssetId(landNum), id), StringEntry(keyLandAssetIdToOwner(id), userAddr), StringEntry(keyLandNumToOwner(landNum), userAddr), IntegerEntry(keyInfraLevelByAssetId(id), 0), IntegerEntry(keyInfraLevelByAssetIdAndOwner(id, userAddr), 0), ScriptTransfer(caller, 1, assetId)], $Tuple2(id, continent))
457+ }
458+
459+
445460 func expeditionCommon (shouldUseMat,caller,txId,message,sig) = if (!(sigVerify_8Kb(message, sig, pub)))
446461 then throw("signature does not match")
447462 else {
477492 let currentPack = getBackpack(bpKey)
478493 let mList = split(currentPack[bpIdxMat], "_")
479494 let newMat = makeString(subtractMaterials(shouldUseMat, mList, EXPMATERIALS), "_")
480- let bigNum = abs(toBigInt(txId))
481- let freeNum = valueOrElse(getInteger(keyNextFreeLandNum()), (PRESALENUMLANDS + 1))
482- let landNum = toString(freeNum)
483- let continentIdx = toInt((bigNum % FIVEX))
484- let terrains = genTerrains(bigNum, continentIdx)
485- let continent = continents[continentIdx]
486- let issue = Issue(keyNftName(landNum, "S"), makeString([landNum, "S", terrains, continent], "_"), 1, 0, false)
487- let assetId = calculateAssetId(issue)
488- let id = toBase58String(assetId)
489- $Tuple2([IntegerEntry(keyNextFreeLandNum(), (freeNum + 1)), issue, StringEntry(keyLandToAssetId(landNum), id), StringEntry(keyLandAssetIdToOwner(id), userAddr), StringEntry(keyLandNumToOwner(landNum), userAddr), IntegerEntry(keyInfraLevelByAssetId(id), 0), IntegerEntry(keyInfraLevelByAssetIdAndOwner(id, userAddr), 0), ScriptTransfer(caller, 1, assetId), StringEntry(keyDuckLocation(duckAssetId), makeString([continent, "L", id], "_")), IntegerEntry(keyHealth, newHP), StringEntry(bpKey, makeString([currentPack[bpIdxLevel], currentPack[bpIdxRes], newMat, currentPack[bpIdxProd]], ":"))], id)
495+ let e = expeditionInternal(caller, txId)
496+ let id = e._2._1
497+ $Tuple2((((e._1 :+ StringEntry(keyDuckLocation(duckAssetId), makeString([e._2._2, "L", id], "_"))) :+ IntegerEntry(keyHealth, newHP)) :+ StringEntry(bpKey, makeString([currentPack[bpIdxLevel], currentPack[bpIdxRes], newMat, currentPack[bpIdxProd]], ":"))), id)
490498 }
491499 }
492500 }
668676 let currentPack = getBackpack(bpKey)
669677 let propStr = valueOrElse(getString(keyResProportions()), "0_0_0_0_0_0")
670678 let landsKey = keyStakedLandsByOwner(addr)
671- let landsIn = split_51C(valueOrElse(getString(landsKey), ""), "_")
679+ let landsStr = getString(landsKey)
680+ let landsIn = if (isDefined(landsStr))
681+ then split_51C(value(landsStr), "_")
682+ else nil
672683 let r = {
673684 let $l = landAssetIds
674685 let $s = size($l)
748759 }
749760
750761
751-func saveTxId (addr,txId) = StringEntry(keyLastTxIdByUser(toString(addr)), toBase58String(txId))
752-
753-
754-func checkBlocked () = if (valueOrElse(getBoolean(keyBlocked()), false))
762+func prolog (i) = if (valueOrElse(getBoolean(keyBlocked()), false))
755763 then throw("Contracts are under maintenance")
756- else unit
764+ else StringEntry(keyLastTxIdByUser(toString(i.originCaller)), toBase58String(i.transactionId))
757765
758766
759767 @Callable(i)
765773
766774 @Callable(i)
767775 func stakeLand () = {
768- let blocked = checkBlocked()
769- if ((blocked == blocked))
770- then if ((size(i.payments) != 1))
771- then throw("Exactly one payment required")
772- else {
773- let pmt = value(i.payments[0])
774- let assetId = value(pmt.assetId)
775- let address = toString(i.caller)
776- if ((pmt.amount != 1))
777- then throw((("NFT " + LANDPREFIX) + " token should be attached as payment"))
778- else {
779- let asset = value(assetInfo(assetId))
780- if ((asset.issuer != this))
781- then throw("Unknown issuer of token")
782- else if (!(contains(asset.name, LANDPREFIX)))
783- then throw((("Only NFT " + LANDPREFIX) + " tokens are accepted"))
784- else {
785- let landNumSize = drop(asset.name, 4)
786- let landNum = if (contains(landNumSize, "XXL"))
787- then dropRight(landNumSize, 3)
788- else if (contains(landNumSize, "XL"))
789- then dropRight(landNumSize, 2)
790- else dropRight(landNumSize, 1)
791- if (!(isDefined(parseInt(landNum))))
792- then throw(("Cannot parse land number from " + asset.name))
793- else {
794- let landAssetId = toBase58String(assetId)
795- let timeKey = keyStakedTimeByAssetId(landAssetId)
796- if (isDefined(getInteger(timeKey)))
797- then throw((("NFT " + asset.name) + " is already staked"))
798- else {
799- let d = split(asset.description, "_")
800- let terrainCounts = countTerrains(d[recTerrains])
801- let props = updateProportions(terrainCounts, (numPiecesBySize(d[recLandSize]) / SSIZE), 1)
802- let lands = split_51C(valueOrElse(getString(keyStakedLandsByOwner(address)), ""), "_")
803- if (containsElement(lands, landAssetId))
804- then throw(("Your staked lands already contain " + landAssetId))
805- else [IntegerEntry(timeKey, lastBlock.timestamp), IntegerEntry(keyStakedTimeByTypeAssetIdAndOwner(LANDPREFIX, landAssetId, address), lastBlock.timestamp), StringEntry(keyStakedLandsByOwner(address), makeString_11C((lands :+ landAssetId), "_")), StringEntry(keyLandAssetIdToOwner(landAssetId), address), StringEntry(keyLandNumToOwner(landNum), address), StringEntry(keyResProportions(), props)]
806- }
807- }
808- }
809- }
810- }
811- else throw("Strict value is not equal to itself.")
776+ let prologAction = prolog(i)
777+ if ((size(i.payments) != 1))
778+ then throw("Exactly one payment required")
779+ else {
780+ let pmt = value(i.payments[0])
781+ let assetId = value(pmt.assetId)
782+ let address = toString(i.caller)
783+ if ((pmt.amount != 1))
784+ then throw((("NFT " + LANDPREFIX) + " token should be attached as payment"))
785+ else {
786+ let asset = value(assetInfo(assetId))
787+ if ((asset.issuer != this))
788+ then throw("Unknown issuer of token")
789+ else if (!(contains(asset.name, LANDPREFIX)))
790+ then throw((("Only NFT " + LANDPREFIX) + " tokens are accepted"))
791+ else {
792+ let landNumSize = drop(asset.name, 4)
793+ let landNum = if (contains(landNumSize, "XXL"))
794+ then dropRight(landNumSize, 3)
795+ else if (contains(landNumSize, "XL"))
796+ then dropRight(landNumSize, 2)
797+ else dropRight(landNumSize, 1)
798+ if (!(isDefined(parseInt(landNum))))
799+ then throw(("Cannot parse land number from " + asset.name))
800+ else {
801+ let landAssetId = toBase58String(assetId)
802+ let timeKey = keyStakedTimeByAssetId(landAssetId)
803+ if (isDefined(getInteger(timeKey)))
804+ then throw((("NFT " + asset.name) + " is already staked"))
805+ else {
806+ let d = split(asset.description, "_")
807+ let terrainCounts = countTerrains(d[recTerrains])
808+ let props = updateProportions(terrainCounts, (numPiecesBySize(d[recLandSize]) / SSIZE), 1)
809+ let landsStr = getString(keyStakedLandsByOwner(address))
810+ let lands = if (isDefined(landsStr))
811+ then split_51C(value(landsStr), "_")
812+ else nil
813+ if (containsElement(lands, landAssetId))
814+ then throw(("Your staked lands already contain " + landAssetId))
815+ else [IntegerEntry(timeKey, lastBlock.timestamp), IntegerEntry(keyStakedTimeByTypeAssetIdAndOwner(LANDPREFIX, landAssetId, address), lastBlock.timestamp), StringEntry(keyStakedLandsByOwner(address), makeString_11C((lands :+ landAssetId), "_")), StringEntry(keyLandAssetIdToOwner(landAssetId), address), StringEntry(keyLandNumToOwner(landNum), address), StringEntry(keyResProportions(), props), prologAction]
816+ }
817+ }
818+ }
819+ }
820+ }
812821 }
813822
814823
815824
816825 @Callable(i)
817826 func unstakeLand (landAssetIdIgnored) = {
818- let blocked = checkBlocked()
819- if ((blocked == blocked))
820- then if ((size(i.payments) != 0))
821- then throw("unstake doesn't require any payments")
822- else {
823- let addr = toString(i.caller)
824- let c = checkClaimConditions(addr)
825- let landAssetId = c._2
826- let landsKey = keyStakedLandsByOwner(addr)
827- let terrainCounts = countTerrains(c._3[recTerrains])
828- let pieces = numPiecesBySize(c._3[recLandSize])
829- let props = updateProportions(terrainCounts, (pieces / SSIZE), -1)
830- let claimResult = claimAll(addr, landAssetId, pieces)
831- let lands = split_51C(valueOrElse(getString(landsKey), ""), "_")
832- let idx = indexOf(lands, landAssetId)
833- if (!(isDefined(idx)))
834- then throw(("Your staked lands don't contain " + landAssetId))
835- else [ScriptTransfer(i.caller, 1, fromBase58String(landAssetId)), DeleteEntry(keyStakedTimeByAssetId(landAssetId)), DeleteEntry(keyStakedTimeByTypeAssetIdAndOwner(LANDPREFIX, landAssetId, addr)), StringEntry(keyResProportions(), props), StringEntry(claimResult._2, makeString(claimResult._3, ":")), if ((size(lands) > 1))
836- then StringEntry(landsKey, makeString_11C(removeByIndex(lands, value(idx)), "_"))
837- else DeleteEntry(landsKey)]
838- }
839- else throw("Strict value is not equal to itself.")
827+ let prologAction = prolog(i)
828+ if ((size(i.payments) != 0))
829+ then throw("unstake doesn't require any payments")
830+ else {
831+ let addr = toString(i.caller)
832+ let c = checkClaimConditions(addr)
833+ let landAssetId = c._2
834+ let landsKey = keyStakedLandsByOwner(addr)
835+ let terrainCounts = countTerrains(c._3[recTerrains])
836+ let pieces = numPiecesBySize(c._3[recLandSize])
837+ let props = updateProportions(terrainCounts, (pieces / SSIZE), -1)
838+ let claimResult = claimAll(addr, landAssetId, pieces)
839+ let lands = split_51C(valueOrElse(getString(landsKey), ""), "_")
840+ let idx = indexOf(lands, landAssetId)
841+ if (!(isDefined(idx)))
842+ then throw(("Your staked lands don't contain " + landAssetId))
843+ else [ScriptTransfer(i.caller, 1, fromBase58String(landAssetId)), DeleteEntry(keyStakedTimeByAssetId(landAssetId)), DeleteEntry(keyStakedTimeByTypeAssetIdAndOwner(LANDPREFIX, landAssetId, addr)), StringEntry(keyResProportions(), props), StringEntry(claimResult._2, makeString(claimResult._3, ":")), if ((size(lands) > 1))
844+ then StringEntry(landsKey, makeString_11C(removeByIndex(lands, value(idx)), "_"))
845+ else DeleteEntry(landsKey), prologAction]
846+ }
840847 }
841848
842849
843850
844851 @Callable(i)
845852 func stakeDuck () = {
846- let blocked = checkBlocked()
847- if ((blocked == blocked))
848- then if ((size(i.payments) != 1))
849- then throw("Exactly one payment required")
850- else {
851- let pmt = value(i.payments[0])
852- let assetId = value(pmt.assetId)
853- let address = toString(i.caller)
854- if ((pmt.amount != 1))
855- then throw((("NFT " + DUCKPREFIX) + " token should be attached as payment"))
856- else {
857- let asset = value(assetInfo(assetId))
858- if (if ((asset.issuer != incubatorAddr))
859- then (asset.issuer != breederAddr)
860- else false)
861- then throw((("Unknown issuer of " + DUCKPREFIX) + " token"))
862- else if (!(contains(asset.name, DUCKPREFIX)))
863- then throw((("Only NFT " + DUCKPREFIX) + " tokens are accepted"))
864- else {
865- let assetIdStr = toBase58String(assetId)
866- let timeKey = keyStakedTimeByAssetId(assetIdStr)
867- if (isDefined(getInteger(timeKey)))
868- then throw((("NFT " + asset.name) + " is already staked"))
869- else if (isDefined(getString(keyStakedDuckByOwner(address))))
870- then throw(("You already staked one duck: " + asset.name))
871- else {
872- let locKey = keyDuckLocation(assetIdStr)
873- let location = getString(locKey)
874- let bpKey = keyBackpackByDuck(assetIdStr)
875- let backpack = getString(bpKey)
876- ([IntegerEntry(timeKey, lastBlock.timestamp), IntegerEntry(keyStakedTimeByTypeAssetIdAndOwner(DUCKPREFIX, toBase58String(assetId), address), lastBlock.timestamp), StringEntry(keyDuckIdToOwner(assetIdStr), address), StringEntry(keyStakedDuckByOwner(address), assetIdStr)] ++ (if (isDefined(location))
853+ let prologAction = prolog(i)
854+ if ((size(i.payments) != 1))
855+ then throw("Exactly one payment required")
856+ else {
857+ let pmt = value(i.payments[0])
858+ let assetId = value(pmt.assetId)
859+ let address = toString(i.caller)
860+ if ((pmt.amount != 1))
861+ then throw((("NFT " + DUCKPREFIX) + " token should be attached as payment"))
862+ else {
863+ let asset = value(assetInfo(assetId))
864+ if (if ((asset.issuer != incubatorAddr))
865+ then (asset.issuer != breederAddr)
866+ else false)
867+ then throw((("Unknown issuer of " + DUCKPREFIX) + " token"))
868+ else if (!(contains(asset.name, DUCKPREFIX)))
869+ then throw((("Only NFT " + DUCKPREFIX) + " tokens are accepted"))
870+ else {
871+ let assetIdStr = toBase58String(assetId)
872+ let timeKey = keyStakedTimeByAssetId(assetIdStr)
873+ if (isDefined(getInteger(timeKey)))
874+ then throw((("NFT " + asset.name) + " is already staked"))
875+ else if (isDefined(getString(keyStakedDuckByOwner(address))))
876+ then throw(("You already staked one duck: " + asset.name))
877+ else {
878+ let locKey = keyDuckLocation(assetIdStr)
879+ let location = getString(locKey)
880+ let bpKey = keyBackpackByDuck(assetIdStr)
881+ let backpack = getString(bpKey)
882+ ([IntegerEntry(timeKey, lastBlock.timestamp), IntegerEntry(keyStakedTimeByTypeAssetIdAndOwner(DUCKPREFIX, toBase58String(assetId), address), lastBlock.timestamp), StringEntry(keyDuckIdToOwner(assetIdStr), address), StringEntry(keyStakedDuckByOwner(address), assetIdStr)] ++ (if (isDefined(location))
883+ then nil
884+ else ([StringEntry(locKey, DEFAULTLOCATION)] ++ (if (isDefined(backpack))
877885 then nil
878- else ([StringEntry(locKey, DEFAULTLOCATION)] ++ (if (isDefined(backpack))
879- then nil
880- else ([StringEntry(bpKey, "0:0_0_0_0_0_0:0_0_0_0_0_0:")] :+ IntegerEntry(keyDuckHealth(assetIdStr), 100))))))
881- }
882- }
883- }
884- }
885- else throw("Strict value is not equal to itself.")
886+ else (([StringEntry(bpKey, "0:0_0_0_0_0_0:0_0_0_0_0_0:")] :+ IntegerEntry(keyDuckHealth(assetIdStr), 100)) :+ prologAction)))))
887+ }
888+ }
889+ }
890+ }
886891 }
887892
888893
889894
890895 @Callable(i)
891896 func unstakeDuck (assetIdStr) = {
892- let blocked = checkBlocked()
893- if ((blocked == blocked))
894- then if ((size(i.payments) != 0))
895- then throw("unstake doesn't require any payments")
896- else {
897- let assetId = fromBase58String(assetIdStr)
898- let address = toString(i.caller)
899- let asset = value(assetInfo(assetId))
900- let timeKey = keyStakedTimeByAssetId(toBase58String(assetId))
901- if (!(isDefined(timeKey)))
902- then throw((("NFT " + asset.name) + " is not staked"))
903- else if (!(isDefined(keyStakedDuckByOwner(address))))
904- then throw((("The duck " + asset.name) + " is not staked"))
905- else {
906- let owner = valueOrErrorMessage(getString(keyDuckIdToOwner(toBase58String(assetId))), (("NFT " + asset.name) + " is orphaned"))
907- if ((owner != address))
908- then throw("Staked NFT is not yours")
909- else {
910- let keyHealth = keyDuckHealth(assetIdStr)
911- let health = valueOrElse(getInteger(keyHealth), 100)
912- if ((health != 100))
913- then throw("Please heal your duck before unstaking")
914- else [ScriptTransfer(i.caller, 1, assetId), DeleteEntry(timeKey), DeleteEntry(keyHealth), DeleteEntry(keyDuckLocation(assetIdStr)), DeleteEntry(keyDuckIdToOwner(assetIdStr)), DeleteEntry(keyStakedTimeByTypeAssetIdAndOwner(DUCKPREFIX, assetIdStr, address)), DeleteEntry(keyStakedDuckByOwner(address))]
915- }
916- }
917- }
918- else throw("Strict value is not equal to itself.")
897+ let prologAction = prolog(i)
898+ if ((size(i.payments) != 0))
899+ then throw("unstake doesn't require any payments")
900+ else {
901+ let assetId = fromBase58String(assetIdStr)
902+ let address = toString(i.caller)
903+ let asset = value(assetInfo(assetId))
904+ let timeKey = keyStakedTimeByAssetId(toBase58String(assetId))
905+ if (!(isDefined(timeKey)))
906+ then throw((("NFT " + asset.name) + " is not staked"))
907+ else if (!(isDefined(keyStakedDuckByOwner(address))))
908+ then throw((("The duck " + asset.name) + " is not staked"))
909+ else {
910+ let owner = valueOrErrorMessage(getString(keyDuckIdToOwner(toBase58String(assetId))), (("NFT " + asset.name) + " is orphaned"))
911+ if ((owner != address))
912+ then throw("Staked NFT is not yours")
913+ else {
914+ let keyHealth = keyDuckHealth(assetIdStr)
915+ let health = valueOrElse(getInteger(keyHealth), 100)
916+ if ((health != 100))
917+ then throw("Please heal your duck before unstaking")
918+ else [ScriptTransfer(i.caller, 1, assetId), DeleteEntry(timeKey), DeleteEntry(keyHealth), DeleteEntry(keyDuckLocation(assetIdStr)), DeleteEntry(keyDuckIdToOwner(assetIdStr)), DeleteEntry(keyStakedTimeByTypeAssetIdAndOwner(DUCKPREFIX, assetIdStr, address)), DeleteEntry(keyStakedDuckByOwner(address)), prologAction]
919+ }
920+ }
921+ }
919922 }
920923
921924
922925
923926 @Callable(i)
924927 func claimRes (amount,landAssetIdStr) = {
925- let blocked = checkBlocked()
926- if ((blocked == blocked))
927- then if ((size(i.payments) != 0))
928- then throw("claimRes doesn't require any payments")
929- else {
930- let addr = toString(i.originCaller)
931- let result = claimResInternal(addr, amount)
932- $Tuple2((result._1 :+ StringEntry(result._2, makeString(result._3, ":"))), result._3[bpIdxRes])
933- }
934- else throw("Strict value is not equal to itself.")
928+ let prologAction = prolog(i)
929+ if ((size(i.payments) != 0))
930+ then throw("claimRes doesn't require any payments")
931+ else {
932+ let addr = toString(i.originCaller)
933+ let result = claimResInternal(addr, amount)
934+ $Tuple2(((result._1 :+ StringEntry(result._2, makeString(result._3, ":"))) :+ prologAction), result._3[bpIdxRes])
935+ }
935936 }
936937
937938
938939
939940 @Callable(i)
940941 func flight (message,sig) = {
941- let blocked = checkBlocked()
942- if ((blocked == blocked))
943- then if (!(sigVerify_8Kb(message, sig, pub)))
944- then throw("signature does not match")
945- else if ((size(i.payments) != 0))
946- then throw("flight doesn't require any payments")
947- else {
948- let parts = split(toUtf8String(message), ";")
949- let hp = split(split(parts[0], "|")[0], "_")
950- let curHP = parseIntValue(hp[0])
951- let newHP = parseIntValue(hp[1])
952- let newLocAndTime = split(parts[1], ":")
953- let newLocation = newLocAndTime[0]
954- let time = parseIntValue(newLocAndTime[1])
955- if (if ((time > (lastBlock.timestamp + FIVEMINUTESMILLIS)))
956- then true
957- else ((lastBlock.timestamp - FIVEMINUTESMILLIS) > time))
958- then throw("signature outdated")
959- else {
960- let duckAssetId = valueOrErrorMessage(getString(keyStakedDuckByOwner(toString(i.caller))), "You don't have a duck staked")
961- let keyHealth = keyDuckHealth(duckAssetId)
962- let oldFromState = valueOrElse(getInteger(keyHealth), 100)
963- if ((oldFromState != curHP))
964- then throw(((("oldHealth=" + toString(valueOrElse(getInteger(keyHealth), 100))) + " from state does not match one from flight log=") + toString(curHP)))
965- else if ((0 >= curHP))
966- then throw("You can't fly with zero health")
967- else {
968- let locKey = keyDuckLocation(duckAssetId)
969- let curLocation = valueOrElse(getString(locKey), DEFAULTLOCATION)
970- if ((newLocation == curLocation))
971- then throw("You can't fly to the same location")
972- else $Tuple2([StringEntry(locKey, if ((newHP > 0))
973- then newLocation
974- else curLocation), IntegerEntry(keyHealth, newHP)], unit)
975- }
976- }
977- }
978- else throw("Strict value is not equal to itself.")
942+ let prologAction = prolog(i)
943+ if (!(sigVerify_8Kb(message, sig, pub)))
944+ then throw("signature does not match")
945+ else if ((size(i.payments) != 0))
946+ then throw("flight doesn't require any payments")
947+ else {
948+ let parts = split(toUtf8String(message), ";")
949+ let hp = split(split(parts[0], "|")[0], "_")
950+ let curHP = parseIntValue(hp[0])
951+ let newHP = parseIntValue(hp[1])
952+ let newLocAndTime = split(parts[1], ":")
953+ let newLocation = newLocAndTime[0]
954+ let time = parseIntValue(newLocAndTime[1])
955+ if (if ((time > (lastBlock.timestamp + FIVEMINUTESMILLIS)))
956+ then true
957+ else ((lastBlock.timestamp - FIVEMINUTESMILLIS) > time))
958+ then throw("signature outdated")
959+ else {
960+ let duckAssetId = valueOrErrorMessage(getString(keyStakedDuckByOwner(toString(i.caller))), "You don't have a duck staked")
961+ let keyHealth = keyDuckHealth(duckAssetId)
962+ let oldFromState = valueOrElse(getInteger(keyHealth), 100)
963+ if ((oldFromState != curHP))
964+ then throw(((("oldHealth=" + toString(valueOrElse(getInteger(keyHealth), 100))) + " from state does not match one from flight log=") + toString(curHP)))
965+ else if ((0 >= curHP))
966+ then throw("You can't fly with zero health")
967+ else {
968+ let locKey = keyDuckLocation(duckAssetId)
969+ let curLocation = valueOrElse(getString(locKey), DEFAULTLOCATION)
970+ if ((newLocation == curLocation))
971+ then throw("You can't fly to the same location")
972+ else $Tuple2([StringEntry(locKey, if ((newHP > 0))
973+ then newLocation
974+ else curLocation), IntegerEntry(keyHealth, newHP), prologAction], unit)
975+ }
976+ }
977+ }
979978 }
980979
981980
982981
983982 @Callable(i)
984983 func setHealth (health,duckAssetId) = {
985- let blocked = checkBlocked()
986- if ((blocked == blocked))
987- then if (if ((0 > health))
988- then true
989- else (health > 100))
990- then throw("HP should be within 0..100")
991- else [IntegerEntry(keyDuckHealth(duckAssetId), health)]
992- else throw("Strict value is not equal to itself.")
984+ let prologAction = prolog(i)
985+ if (if ((0 > health))
986+ then true
987+ else (health > 100))
988+ then throw("HP should be within 0..100")
989+ else [IntegerEntry(keyDuckHealth(duckAssetId), health), prologAction]
993990 }
994991
995992
996993
997994 @Callable(i)
998995 func heal (matType,amount) = {
999- let blocked = checkBlocked()
1000- if ((blocked == blocked))
1001- then if (if ((0 > matType))
1002- then true
1003- else (matType >= NUMRES))
1004- then throw(("Unknown material: " + toString(matType)))
1005- else if ((0 >= amount))
1006- then throw(("Amount should be positive! " + toString(amount)))
1007- else {
1008- let duckAssetId = valueOrErrorMessage(getString(keyStakedDuckByOwner(toString(i.caller))), "You don't have a duck staked")
1009- let keyHealth = keyDuckHealth(duckAssetId)
1010- let oldHealth = valueOrElse(getInteger(keyHealth), 100)
1011- if ((oldHealth >= 100))
1012- then throw("HP should be < 100 to heal")
1013- else {
1014- let bpKey = keyBackpackByDuck(duckAssetId)
1015- let currentPack = getBackpack(bpKey)
1016- let mList = split(currentPack[bpIdxMat], "_")
1017- let currentAmount = parseIntValue(mList[matType])
1018- let deltaHealth = min([(amount / HEALCOST), (100 - oldHealth)])
1019- let spendAmount = (deltaHealth * HEALCOST)
1020- if ((spendAmount > currentAmount))
1021- then throw(((((("You need " + toString(spendAmount)) + " of ") + matTypes[matType]) + " to heal, but you backpack contains ") + toString(currentAmount)))
1022- else {
1023- let newMat = subOneInList(mList, matType, spendAmount)
1024-[IntegerEntry(keyHealth, (oldHealth + deltaHealth)), StringEntry(bpKey, makeString([currentPack[bpIdxLevel], currentPack[bpIdxRes], newMat, currentPack[bpIdxProd]], ":"))]
1025- }
1026- }
1027- }
1028- else throw("Strict value is not equal to itself.")
996+ let prologAction = prolog(i)
997+ if (if ((0 > matType))
998+ then true
999+ else (matType >= NUMRES))
1000+ then throw(("Unknown material: " + toString(matType)))
1001+ else if ((0 >= amount))
1002+ then throw(("Amount should be positive! " + toString(amount)))
1003+ else {
1004+ let duckAssetId = valueOrErrorMessage(getString(keyStakedDuckByOwner(toString(i.caller))), "You don't have a duck staked")
1005+ let keyHealth = keyDuckHealth(duckAssetId)
1006+ let oldHealth = valueOrElse(getInteger(keyHealth), 100)
1007+ if ((oldHealth >= 100))
1008+ then throw("HP should be < 100 to heal")
1009+ else {
1010+ let bpKey = keyBackpackByDuck(duckAssetId)
1011+ let currentPack = getBackpack(bpKey)
1012+ let mList = split(currentPack[bpIdxMat], "_")
1013+ let currentAmount = parseIntValue(mList[matType])
1014+ let deltaHealth = min([(amount / HEALCOST), (100 - oldHealth)])
1015+ let spendAmount = (deltaHealth * HEALCOST)
1016+ if ((spendAmount > currentAmount))
1017+ then throw(((((("You need " + toString(spendAmount)) + " of ") + matTypes[matType]) + " to heal, but you backpack contains ") + toString(currentAmount)))
1018+ else {
1019+ let newMat = subOneInList(mList, matType, spendAmount)
1020+[IntegerEntry(keyHealth, (oldHealth + deltaHealth)), StringEntry(bpKey, makeString([currentPack[bpIdxLevel], currentPack[bpIdxRes], newMat, currentPack[bpIdxProd]], ":")), prologAction]
1021+ }
1022+ }
1023+ }
10291024 }
10301025
10311026
10321027
10331028 @Callable(i)
1034-func updateBackpack (duckAssetId,newPack) = if ((i.caller != economyContract))
1035- then throw("permission denied")
1036- else $Tuple2([StringEntry(keyBackpackByDuck(duckAssetId), newPack)], newPack)
1029+func updateBackpack (duckAssetId,newPack) = {
1030+ let prologAction = prolog(i)
1031+ if ((i.caller != economyContract))
1032+ then throw("permission denied")
1033+ else $Tuple2([StringEntry(keyBackpackByDuck(duckAssetId), newPack), prologAction], newPack)
1034+ }
1035+
1036+
1037+
1038+@Callable(i)
1039+func buySLand () = {
1040+ let prologAction = prolog(i)
1041+ if ((size(i.payments) != 1))
1042+ then throw("Exactly one payment required")
1043+ else {
1044+ let pmt = value(i.payments[0])
1045+ if ((pmt.assetId != usdnAssetId))
1046+ then throw("Allowed USDN payment only!")
1047+ else if ((pmt.amount != EXPUSDN))
1048+ then throw(("Payment attached should be " + toString(EXPUSDN)))
1049+ else {
1050+ let result = expeditionInternal(i.caller, i.transactionId)
1051+ $Tuple2(((result._1 :+ ScriptTransfer(economyContract, pmt.amount, usdnAssetId)) :+ prologAction), result._2._1)
1052+ }
1053+ }
1054+ }
10371055
10381056
10391057
10401058 @Callable(i)
10411059 func expeditionBuy (message,sig) = {
1042- let blocked = checkBlocked()
1043- if ((blocked == blocked))
1044- then if ((size(i.payments) != 1))
1045- then throw("Exactly one payment required")
1046- else {
1047- let pmt = value(i.payments[0])
1048- if ((pmt.assetId != usdnAssetId))
1049- then throw("Allowed USDN payment only!")
1050- else if ((pmt.amount != EXPUSDN))
1051- then throw(("Payment attached should be " + toString(EXPUSDN)))
1052- else {
1053- let result = expeditionCommon(false, i.caller, i.transactionId, message, sig)
1054- if ((result._2 == ""))
1055- then result
1056- else $Tuple2((result._1 :+ ScriptTransfer(economyContract, pmt.amount, usdnAssetId)), result._2)
1057- }
1058- }
1059- else throw("Strict value is not equal to itself.")
1060+ let prologAction = prolog(i)
1061+ if ((size(i.payments) != 1))
1062+ then throw("Exactly one payment required")
1063+ else {
1064+ let pmt = value(i.payments[0])
1065+ if ((pmt.assetId != usdnAssetId))
1066+ then throw("Allowed USDN payment only!")
1067+ else if ((pmt.amount != EXPUSDN))
1068+ then throw(("Payment attached should be " + toString(EXPUSDN)))
1069+ else {
1070+ let result = expeditionCommon(false, i.caller, i.transactionId, message, sig)
1071+ if ((result._2 == ""))
1072+ then result
1073+ else $Tuple2(((result._1 :+ ScriptTransfer(economyContract, pmt.amount, usdnAssetId)) :+ prologAction), result._2)
1074+ }
1075+ }
10601076 }
10611077
10621078
10631079
10641080 @Callable(i)
10651081 func expedition (message,sig) = {
1066- let blocked = checkBlocked()
1067- if ((blocked == blocked))
1068- then if ((size(i.payments) != 0))
1069- then throw("expedition doesn't require any payments")
1070- else expeditionCommon(true, i.caller, i.transactionId, message, sig)
1071- else throw("Strict value is not equal to itself.")
1082+ let prologAction = prolog(i)
1083+ if ((size(i.payments) != 0))
1084+ then throw("expedition doesn't require any payments")
1085+ else {
1086+ let result = expeditionCommon(true, i.caller, i.transactionId, message, sig)
1087+ $Tuple2((result._1 :+ prologAction), result._2)
1088+ }
10721089 }
10731090
10741091
10751092
10761093 @Callable(i)
10771094 func upgradeInfra (landAssetIdIgnored) = {
1078- let blocked = checkBlocked()
1079- if ((blocked == blocked))
1080- then if ((size(i.payments) != 0))
1081- then throw("Infrastructure upgrade doesn't require any payments")
1082- else upInfraCommon(true, i.caller, 0)
1083- else throw("Strict value is not equal to itself.")
1095+ let prologAction = prolog(i)
1096+ if ((size(i.payments) != 0))
1097+ then throw("Infrastructure upgrade doesn't require any payments")
1098+ else {
1099+ let result = upInfraCommon(true, i.caller, 0)
1100+ $Tuple2((result._1 :+ prologAction), result._2)
1101+ }
10841102 }
10851103
10861104
10871105
10881106 @Callable(i)
10891107 func upgradeInfraUsdn (landAssetIdIgnored) = {
1090- let blocked = checkBlocked()
1091- if ((blocked == blocked))
1092- then if ((size(i.payments) != 1))
1093- then throw("Exactly one payment required")
1094- else {
1095- let pmt = value(i.payments[0])
1096- if ((pmt.assetId != usdnAssetId))
1097- then throw("Allowed USDN payment only!")
1098- else {
1099- let result = upInfraCommon(false, i.caller, pmt.amount)
1100- $Tuple2((result._1 :+ ScriptTransfer(economyContract, pmt.amount, usdnAssetId)), result._2)
1101- }
1102- }
1103- else throw("Strict value is not equal to itself.")
1108+ let prologAction = prolog(i)
1109+ if ((size(i.payments) != 1))
1110+ then throw("Exactly one payment required")
1111+ else {
1112+ let pmt = value(i.payments[0])
1113+ if ((pmt.assetId != usdnAssetId))
1114+ then throw("Allowed USDN payment only!")
1115+ else {
1116+ let result = upInfraCommon(false, i.caller, pmt.amount)
1117+ $Tuple2(((result._1 :+ ScriptTransfer(economyContract, pmt.amount, usdnAssetId)) :+ prologAction), result._2)
1118+ }
1119+ }
11041120 }
11051121
11061122
11071123
11081124 @Callable(i)
11091125 func activateArtifact (artName) = {
1110- let blocked = checkBlocked()
1111- if ((blocked == blocked))
1112- then if ((size(i.payments) != 0))
1113- then throw("Artifact activation doesn't require any payments")
1114- else {
1115- let result = match artName {
1116- case _ =>
1117- if (("PRESALE" == $match0))
1118- then activatePresaleArt(toString(i.caller))
1119- else throw("Unknown artifact")
1120- }
1121- result
1122- }
1123- else throw("Strict value is not equal to itself.")
1126+ let prologAction = prolog(i)
1127+ if ((size(i.payments) != 0))
1128+ then throw("Artifact activation doesn't require any payments")
1129+ else {
1130+ let result = match artName {
1131+ case _ =>
1132+ if (("PRESALE" == $match0))
1133+ then activatePresaleArt(toString(i.caller))
1134+ else throw("Unknown artifact")
1135+ }
1136+ (result :+ prologAction)
1137+ }
11241138 }
11251139
11261140
11271141
11281142 @Callable(i)
1129-func mergeLands (landAssetIds) = if ((i.caller != this))
1130- then throw("permission denied")
1131- else {
1132- let blocked = checkBlocked()
1133- if ((blocked == blocked))
1134- then if ((size(i.payments) != 0))
1135- then throw("Lands merging doesn't require any payments")
1136- else mergeCommon(true, toString(i.caller), 0, landAssetIds, i.transactionId)
1137- else throw("Strict value is not equal to itself.")
1138- }
1143+func mergeLands (landAssetIds) = {
1144+ let prologAction = prolog(i)
1145+ if ((size(i.payments) != 0))
1146+ then throw("Lands merging doesn't require any payments")
1147+ else {
1148+ let result = mergeCommon(true, toString(i.caller), 0, landAssetIds, i.transactionId)
1149+ $Tuple2((result._1 :+ prologAction), result._2)
1150+ }
1151+ }
11391152
11401153
11411154
11421155 @Callable(i)
1143-func mergeLandsUsdn (landAssetIds) = if ((i.caller != this))
1144- then throw("permission denied")
1145- else {
1146- let blocked = checkBlocked()
1147- if ((blocked == blocked))
1148- then if ((size(i.payments) != 1))
1149- then throw("Exactly one payment required")
1156+func mergeLandsUsdn (landAssetIds) = {
1157+ let prologAction = prolog(i)
1158+ if ((size(i.payments) != 1))
1159+ then throw("Exactly one payment required")
1160+ else {
1161+ let pmt = value(i.payments[0])
1162+ if ((pmt.assetId != usdnAssetId))
1163+ then throw("Allowed USDN payment only!")
11501164 else {
1151- let pmt = value(i.payments[0])
1152- if ((pmt.assetId != usdnAssetId))
1153- then throw("Allowed USDN payment only!")
1154- else {
1155- let result = mergeCommon(false, toString(i.caller), pmt.amount, landAssetIds, i.transactionId)
1156- $Tuple2((result._1 :+ ScriptTransfer(economyContract, pmt.amount, usdnAssetId)), result._2)
1157- }
1165+ let result = mergeCommon(false, toString(i.caller), pmt.amount, landAssetIds, i.transactionId)
1166+ $Tuple2(((result._1 :+ ScriptTransfer(economyContract, pmt.amount, usdnAssetId)) :+ prologAction), result._2)
11581167 }
1159- else throw("Strict value is not equal to itself.")
1160- }
1168+ }
1169+ }
11611170
11621171
11631172
11731182 }
11741183
11751184
1185+
1186+@Callable(i)
1187+func getBackpackREADONLY (duckAssetId) = $Tuple2(nil, makeString(getBackpack(keyBackpackByDuck(duckAssetId)), ":"))
1188+
1189+
Full:
OldNewDifferences
11 {-# STDLIB_VERSION 6 #-}
22 {-# SCRIPT_TYPE ACCOUNT #-}
33 {-# CONTENT_TYPE DAPP #-}
44 let chain = take(drop(this.bytes, 1), 1)
55
66 let usdnAssetId = match chain {
77 case _ =>
88 if ((base58'2W' == $match0))
99 then base58'DG2xFkPdDwKUoBkzGAhQtLpSGzfXLiCYPEzeKH2Ad24p'
1010 else if ((base58'2T' == $match0))
1111 then base58'HezsdQuRDtzksAYUy97gfhKy7Z1NW2uXYSHA3bgqenNZ'
1212 else throw("Unknown chain")
1313 }
1414
1515 let incubatorAddr = match chain {
1616 case _ =>
1717 if ((base58'2W' == $match0))
1818 then addressFromStringValue("3PEktVux2RhchSN63DsDo4b4mz4QqzKSeDv")
1919 else if ((base58'2T' == $match0))
2020 then this
2121 else throw("Unknown chain")
2222 }
2323
2424 let breederAddr = match chain {
2525 case _ =>
2626 if ((base58'2W' == $match0))
2727 then addressFromStringValue("3PDVuU45H7Eh5dmtNbnRNRStGwULA7NY6Hb")
2828 else if ((base58'2T' == $match0))
2929 then this
3030 else throw("Unknown chain")
3131 }
3232
3333 let economyContract = addressFromStringValue(match chain {
3434 case _ =>
3535 if ((base58'2W' == $match0))
3636 then "3P2sk1KncSxRaZs8b4CWGPw2jkvvav74u4D"
3737 else if ((base58'2T' == $match0))
3838 then "3N8y4wxX3JC4TdrCJBXX16SjWf6X256hrep"
3939 else throw("Unknown chain")
4040 })
4141
4242 let pub = base58'6LfPuKJjLgekmncBhMg2LZyMTNVzZBccXR28ySXm9uXD'
4343
4444 let HEALCOST = 10000
4545
4646 let LANDPREFIX = "LAND"
4747
4848 let DUCKPREFIX = "DUCK"
4949
5050 let DEFAULTLOCATION = "Africa_F_Africa"
5151
5252 let NUMRES = 6
5353
5454 let SSIZE = 25
5555
5656 let MSIZE = 100
5757
5858 let LSIZE = 225
5959
6060 let XLSIZE = 400
6161
6262 let XXLSIZE = 625
6363
6464 let DAILYRESBYPIECE = 3456000
6565
6666 let DAYMILLIS = 86400000
6767
6868 let FIVEMINUTESMILLIS = 300000
6969
7070 let RESOURCEPRICEMIN = 158549
7171
7272 let InfraUpgradeCostS = match chain {
7373 case _ =>
7474 if ((base58'2W' == $match0))
7575 then 6307198406
7676 else if ((base58'2T' == $match0))
7777 then 63071984
7878 else throw("Unknown chain")
7979 }
8080
8181 let InfraUpgradeCostSUsdn = match chain {
8282 case _ =>
8383 if ((base58'2W' == $match0))
8484 then 40000000
8585 else if ((base58'2T' == $match0))
8686 then 400000
8787 else throw("Unknown chain")
8888 }
8989
9090 let EXPMATERIALS = match chain {
9191 case _ =>
9292 if ((base58'2W' == $match0))
9393 then 157679960139
9494 else if ((base58'2T' == $match0))
9595 then 1576799601
9696 else throw("Unknown chain")
9797 }
9898
9999 let EXPUSDN = match chain {
100100 case _ =>
101101 if ((base58'2W' == $match0))
102102 then 1000000000
103103 else if ((base58'2T' == $match0))
104104 then 10000000
105105 else throw("Unknown chain")
106106 }
107107
108108 let MULT6 = 1000000
109109
110110 let FIVEX = toBigInt(5)
111111
112112 let TWENTYX = toBigInt(20)
113113
114114 let TWENTY2X = toBigInt((20 * 20))
115115
116116 let TWENTY3X = toBigInt(((20 * 20) * 20))
117117
118118 let TWENTY4X = toBigInt((((20 * 20) * 20) * 20))
119119
120120 let TWENTY5X = toBigInt(((((20 * 20) * 20) * 20) * 20))
121121
122122 let matTypes = ["Fuel", "Metal", "Plank", "Glass", "Plastic", "Protein"]
123123
124124 let continents = ["Asia", "Europe", "Americas", "Oceania", "Africa"]
125125
126126 let ARTPRESALE = "PRESALE"
127127
128128 let PRESALENUMLANDS = 500
129129
130130 func keyLastTxIdByUser (addr) = ("lastTxIdByUser_" + addr)
131131
132132
133133 func keyNextFreeLandNum () = "nextLandNum"
134134
135135
136136 func keyLandToAssetId (landNum) = ("landToAsset_" + landNum)
137137
138138
139139 func keyNftName (landNum,landSize) = ((LANDPREFIX + landNum) + landSize)
140140
141141
142142 func keyLandAssetIdToOwner (assetId) = ("nftOwner_" + assetId)
143143
144144
145145 func keyDuckIdToOwner (assetId) = ("duckOwner_" + assetId)
146146
147147
148148 func keyStakedTimeByAssetId (assetId) = ("stakedTime_" + assetId)
149149
150150
151151 func keyInfraLevelByAssetId (assetId) = ("infraLevel_" + assetId)
152152
153153
154154 func keyInfraLevelByAssetIdAndOwner (assetId,ownerAddr) = ((("infraLevelByAssetIdAndOwner_" + assetId) + "_") + ownerAddr)
155155
156156
157157 func keyPresaleArtActivatedByAssetId (assetId) = ("presaleArtActivated_" + assetId)
158158
159159
160160 func keyPresaleArtActivatedByAssetIdAndOwner (assetId,ownerAddr) = ((("presaleArtActivatedByAssetIdAndOwner_" + assetId) + "_") + ownerAddr)
161161
162162
163163 func keyLandArtStatusByTypeAndAssetId (type,assetId) = makeString(["landArtStatus", type, assetId], "_")
164164
165165
166166 func keyLandArtStatusByTypeAssetIdAndOwner (type,assetId,ownerAddr) = makeString(["landArtStatusByTypeAssetIdAndOwner", type, assetId, ownerAddr], "_")
167167
168168
169169 func keyStakedDuckByOwner (ownerAddr) = ("stakedDuckByOwner_" + ownerAddr)
170170
171171
172172 func keyStakedTimeByTypeAssetIdAndOwner (nftType,assetId,ownerAddr) = ((((("stakedTimeByTypeAssetIdAndOwner_" + nftType) + "_") + assetId) + "_") + ownerAddr)
173173
174174
175175 func keyLandNumToOwner (landNum) = ("landOwner_" + landNum)
176176
177177
178178 func keyBackpackByDuck (duckAssetId) = ("backPack_" + duckAssetId)
179179
180180
181181 func keyDuckLocation (duckAssetId) = ("duckLocation_" + duckAssetId)
182182
183183
184184 func keyDuckHealth (duckAssetId) = ("duckHealth_" + duckAssetId)
185185
186186
187187 func keyResProportions () = "resTypesProportions"
188188
189189
190190 func keyStakedLandsByOwner (ownerAddr) = ("stakedLandsByOwner_" + ownerAddr)
191191
192192
193193 func keyBlocked () = "contractsBlocked"
194194
195195
196196 let recLandNum = 0
197197
198198 let recLandSize = 1
199199
200200 let recTerrains = 2
201201
202202 let recContinent = 3
203203
204204 let locIdxContinent = 0
205205
206206 let locIdxType = 1
207207
208208 let locIdxId = 2
209209
210210 let bpIdxLevel = 0
211211
212212 let bpIdxRes = 1
213213
214214 let bpIdxMat = 2
215215
216216 let bpIdxProd = 3
217217
218218 func asString (v) = match v {
219219 case s: String =>
220220 s
221221 case _ =>
222222 throw("fail to cast into String")
223223 }
224224
225225
226226 func distributeByWeights (total,weights) = {
227227 let sum = (((((weights[0] + weights[1]) + weights[2]) + weights[3]) + weights[4]) + weights[5])
228228 if ((0 >= sum))
229229 then throw("Zero weights sum")
230230 else {
231231 let norm6 = fraction(total, MULT6, sum)
232232 func normalizer (acc,elem) = (acc :+ fraction(elem, norm6, MULT6))
233233
234234 let $l = weights
235235 let $s = size($l)
236236 let $acc0 = nil
237237 func $f0_1 ($a,$i) = if (($i >= $s))
238238 then $a
239239 else normalizer($a, $l[$i])
240240
241241 func $f0_2 ($a,$i) = if (($i >= $s))
242242 then $a
243243 else throw("List size exceeds 6")
244244
245245 $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6)
246246 }
247247 }
248248
249249
250250 func getNeededMaterials (total) = {
251251 let props = split(value(getString(keyResProportions())), "_")
252252 if ((size(props) != NUMRES))
253253 then throw("Wrong proportions data")
254254 else {
255255 let r = [parseIntValue(props[0]), parseIntValue(props[1]), parseIntValue(props[2]), parseIntValue(props[3]), parseIntValue(props[4]), parseIntValue(props[5])]
256256 distributeByWeights(total, r)
257257 }
258258 }
259259
260260
261261 func subtractMaterials (shouldUseMat,has,totalNeed) = {
262262 let need = getNeededMaterials(totalNeed)
263263 func subtractor (acc,idx) = {
264264 let result = (parseIntValue(has[idx]) - need[idx])
265265 if ((0 > result))
266266 then throw(((((("Not enough material idx=" + toString(idx)) + ", you have ") + has[idx]) + ", but need ") + toString(need[idx])))
267267 else (acc :+ toString(result))
268268 }
269269
270270 if (shouldUseMat)
271271 then {
272272 let $l = [0, 1, 2, 3, 4, 5]
273273 let $s = size($l)
274274 let $acc0 = nil
275275 func $f0_1 ($a,$i) = if (($i >= $s))
276276 then $a
277277 else subtractor($a, $l[$i])
278278
279279 func $f0_2 ($a,$i) = if (($i >= $s))
280280 then $a
281281 else throw("List size exceeds 6")
282282
283283 $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6)
284284 }
285285 else has
286286 }
287287
288288
289289 func updateProportionsInternal (propList,terrainCounts,landSizeIndex,sign) = if ((size(propList) != NUMRES))
290290 then throw("Wrong proportions data")
291291 else {
292292 func updater (acc,i) = {
293293 let result = (parseIntValue(propList[i]) + ((sign * terrainCounts[i]) * landSizeIndex))
294294 if ((0 > result))
295295 then throw(((((((("Panic! Pieces of type=" + toString(i)) + ", sign=") + toString(sign)) + ", terrainCounts[i]=") + toString(terrainCounts[i])) + ", landSizeIndex=") + toString(landSizeIndex)))
296296 else (acc :+ toString(result))
297297 }
298298
299299 let r = {
300300 let $l = [0, 1, 2, 3, 4, 5]
301301 let $s = size($l)
302302 let $acc0 = nil
303303 func $f0_1 ($a,$i) = if (($i >= $s))
304304 then $a
305305 else updater($a, $l[$i])
306306
307307 func $f0_2 ($a,$i) = if (($i >= $s))
308308 then $a
309309 else throw("List size exceeds 6")
310310
311311 $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6)
312312 }
313313 makeString(r, "_")
314314 }
315315
316316
317317 func updateProportions (terrainCounts,landSizeIndex,sign) = {
318318 let propList = split(valueOrElse(getString(keyResProportions()), "0_0_0_0_0_0"), "_")
319319 updateProportionsInternal(propList, terrainCounts, landSizeIndex, sign)
320320 }
321321
322322
323323 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)]
324324
325325
326326 func numPiecesBySize (landSize) = match landSize {
327327 case _ =>
328328 if (("S" == $match0))
329329 then SSIZE
330330 else if (("M" == $match0))
331331 then MSIZE
332332 else if (("L" == $match0))
333333 then LSIZE
334334 else if (("XL" == $match0))
335335 then XLSIZE
336336 else if (("XXL" == $match0))
337337 then XXLSIZE
338338 else throw("Unknown land size")
339339 }
340340
341341
342342 func subOneInList (aList,idx,amount) = {
343343 func subber (acc,i) = (acc :+ (if ((i == idx))
344344 then toString((parseIntValue(aList[i]) - amount))
345345 else aList[i]))
346346
347347 let r = {
348348 let $l = [0, 1, 2, 3, 4, 5]
349349 let $s = size($l)
350350 let $acc0 = nil
351351 func $f0_1 ($a,$i) = if (($i >= $s))
352352 then $a
353353 else subber($a, $l[$i])
354354
355355 func $f0_2 ($a,$i) = if (($i >= $s))
356356 then $a
357357 else throw("List size exceeds 6")
358358
359359 $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6)
360360 }
361361 makeString(r, "_")
362362 }
363363
364364
365365 func addRes (currentRes,terrainCounts,deltaTime,landSizeIndex,dailyByPieceWithBonuses) = {
366366 func adder (acc,i) = {
367367 let resOfType = ((fraction(deltaTime, dailyByPieceWithBonuses, DAYMILLIS) * terrainCounts[i]) * landSizeIndex)
368368 (acc :+ toString((parseIntValue(currentRes[i]) + resOfType)))
369369 }
370370
371371 let r = {
372372 let $l = [0, 1, 2, 3, 4, 5]
373373 let $s = size($l)
374374 let $acc0 = nil
375375 func $f0_1 ($a,$i) = if (($i >= $s))
376376 then $a
377377 else adder($a, $l[$i])
378378
379379 func $f0_2 ($a,$i) = if (($i >= $s))
380380 then $a
381381 else throw("List size exceeds 6")
382382
383383 $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6)
384384 }
385385 makeString(r, "_")
386386 }
387387
388388
389389 func abs (x) = if ((x >= toBigInt(0)))
390390 then x
391391 else -(x)
392392
393393
394394 let freq = [[1, 4, 9, 10, 15], [5, 8, 13, 14, 15], [6, 9, 14, 15, 16], [4, 7, 8, 13, 18], [1, 6, 7, 15, 19]]
395395
396396 func genChar (n,freqs) = {
397397 let rem = toInt((n % TWENTYX))
398398 let letter = if ((freqs[0] > rem))
399399 then "A"
400400 else if ((freqs[1] > rem))
401401 then "B"
402402 else if ((freqs[2] > rem))
403403 then "C"
404404 else if ((freqs[3] > rem))
405405 then "D"
406406 else if ((freqs[4] > rem))
407407 then "E"
408408 else "F"
409409 letter
410410 }
411411
412412
413413 func genTerrains (seed,continentIdx) = {
414414 let f = freq[continentIdx]
415415 func terrainGenerator (acc,elem) = $Tuple2((((((acc._1 + genChar(acc._2, f)) + genChar((acc._2 / TWENTYX), f)) + genChar((acc._2 / TWENTY2X), f)) + genChar((acc._2 / TWENTY3X), f)) + genChar((acc._2 / TWENTY4X), f)), (acc._2 / TWENTY5X))
416416
417417 let t = {
418418 let $l = [1, 2, 3, 4, 5]
419419 let $s = size($l)
420420 let $acc0 = $Tuple2("", (seed / FIVEX))
421421 func $f0_1 ($a,$i) = if (($i >= $s))
422422 then $a
423423 else terrainGenerator($a, $l[$i])
424424
425425 func $f0_2 ($a,$i) = if (($i >= $s))
426426 then $a
427427 else throw("List size exceeds 5")
428428
429429 $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5)
430430 }
431431 t._1
432432 }
433433
434434
435435 func getBackpack (bpKey) = {
436436 let p = split(valueOrElse(getString(bpKey), "0:0_0_0_0_0_0:0_0_0_0_0_0:"), ":")
437437 [toString(valueOrElse(parseInt(p[bpIdxLevel]), 0)), if ((size(split(p[bpIdxRes], "_")) == NUMRES))
438438 then p[bpIdxRes]
439439 else "0_0_0_0_0_0", if ((size(split(p[bpIdxMat], "_")) == NUMRES))
440440 then p[bpIdxMat]
441441 else "0_0_0_0_0_0", p[bpIdxProd]]
442442 }
443443
444444
445+func expeditionInternal (caller,txId) = {
446+ let userAddr = toString(caller)
447+ let bigNum = abs(toBigInt(txId))
448+ let freeNum = valueOrElse(getInteger(keyNextFreeLandNum()), (PRESALENUMLANDS + 1))
449+ let landNum = toString(freeNum)
450+ let continentIdx = toInt((bigNum % FIVEX))
451+ let terrains = genTerrains(bigNum, continentIdx)
452+ let continent = continents[continentIdx]
453+ let issue = Issue(keyNftName(landNum, "S"), makeString([landNum, "S", terrains, continent], "_"), 1, 0, false)
454+ let assetId = calculateAssetId(issue)
455+ let id = toBase58String(assetId)
456+ $Tuple2([IntegerEntry(keyNextFreeLandNum(), (freeNum + 1)), issue, StringEntry(keyLandToAssetId(landNum), id), StringEntry(keyLandAssetIdToOwner(id), userAddr), StringEntry(keyLandNumToOwner(landNum), userAddr), IntegerEntry(keyInfraLevelByAssetId(id), 0), IntegerEntry(keyInfraLevelByAssetIdAndOwner(id, userAddr), 0), ScriptTransfer(caller, 1, assetId)], $Tuple2(id, continent))
457+ }
458+
459+
445460 func expeditionCommon (shouldUseMat,caller,txId,message,sig) = if (!(sigVerify_8Kb(message, sig, pub)))
446461 then throw("signature does not match")
447462 else {
448463 let parts = split(toUtf8String(message), ";")
449464 let hp = split(split(parts[0], "|")[0], "_")
450465 let curHP = parseIntValue(hp[0])
451466 let newHP = parseIntValue(hp[1])
452467 let locAndTime = split(parts[1], ":")
453468 let targetLocation = split(locAndTime[0], "_")
454469 if ((targetLocation[1] != "E"))
455470 then throw("expedition target location type should be E")
456471 else {
457472 let time = parseIntValue(locAndTime[1])
458473 if (if ((time > (lastBlock.timestamp + FIVEMINUTESMILLIS)))
459474 then true
460475 else ((lastBlock.timestamp - FIVEMINUTESMILLIS) > time))
461476 then throw("signature outdated")
462477 else {
463478 let userAddr = toString(caller)
464479 let duckAssetId = valueOrErrorMessage(getString(keyStakedDuckByOwner(userAddr)), "You don't have a duck staked")
465480 let keyHealth = keyDuckHealth(duckAssetId)
466481 let oldFromState = valueOrElse(getInteger(keyHealth), 100)
467482 if ((oldFromState != curHP))
468483 then throw(((("oldHealth=" + toString(valueOrElse(getInteger(keyHealth), 100))) + " from state does not match one from flight log=") + toString(curHP)))
469484 else if ((0 >= curHP))
470485 then throw("You can't fly with zero health")
471486 else if ((0 >= newHP))
472487 then $Tuple2(((if (!(shouldUseMat))
473488 then [ScriptTransfer(caller, EXPUSDN, usdnAssetId)]
474489 else nil) :+ IntegerEntry(keyHealth, 0)), "")
475490 else {
476491 let bpKey = keyBackpackByDuck(duckAssetId)
477492 let currentPack = getBackpack(bpKey)
478493 let mList = split(currentPack[bpIdxMat], "_")
479494 let newMat = makeString(subtractMaterials(shouldUseMat, mList, EXPMATERIALS), "_")
480- let bigNum = abs(toBigInt(txId))
481- let freeNum = valueOrElse(getInteger(keyNextFreeLandNum()), (PRESALENUMLANDS + 1))
482- let landNum = toString(freeNum)
483- let continentIdx = toInt((bigNum % FIVEX))
484- let terrains = genTerrains(bigNum, continentIdx)
485- let continent = continents[continentIdx]
486- let issue = Issue(keyNftName(landNum, "S"), makeString([landNum, "S", terrains, continent], "_"), 1, 0, false)
487- let assetId = calculateAssetId(issue)
488- let id = toBase58String(assetId)
489- $Tuple2([IntegerEntry(keyNextFreeLandNum(), (freeNum + 1)), issue, StringEntry(keyLandToAssetId(landNum), id), StringEntry(keyLandAssetIdToOwner(id), userAddr), StringEntry(keyLandNumToOwner(landNum), userAddr), IntegerEntry(keyInfraLevelByAssetId(id), 0), IntegerEntry(keyInfraLevelByAssetIdAndOwner(id, userAddr), 0), ScriptTransfer(caller, 1, assetId), StringEntry(keyDuckLocation(duckAssetId), makeString([continent, "L", id], "_")), IntegerEntry(keyHealth, newHP), StringEntry(bpKey, makeString([currentPack[bpIdxLevel], currentPack[bpIdxRes], newMat, currentPack[bpIdxProd]], ":"))], id)
495+ let e = expeditionInternal(caller, txId)
496+ let id = e._2._1
497+ $Tuple2((((e._1 :+ StringEntry(keyDuckLocation(duckAssetId), makeString([e._2._2, "L", id], "_"))) :+ IntegerEntry(keyHealth, newHP)) :+ StringEntry(bpKey, makeString([currentPack[bpIdxLevel], currentPack[bpIdxRes], newMat, currentPack[bpIdxProd]], ":"))), id)
490498 }
491499 }
492500 }
493501 }
494502
495503
496504 func applyBonuses (landAssetId,pieces) = {
497505 let infraLevel = valueOrElse(getInteger(keyInfraLevelByAssetId(landAssetId)), 0)
498506 let artPieces = valueOrElse(getInteger(keyLandArtStatusByTypeAndAssetId(ARTPRESALE, landAssetId)), if (valueOrElse(getBoolean(keyPresaleArtActivatedByAssetId(landAssetId)), false))
499507 then pieces
500508 else 0)
501509 ((DAILYRESBYPIECE + fraction(DAILYRESBYPIECE, infraLevel, 4)) + fraction(DAILYRESBYPIECE, (artPieces * 3), (pieces * 20)))
502510 }
503511
504512
505513 func checkClaimConditions (addr) = {
506514 let duckAssetId = valueOrErrorMessage(getString(keyStakedDuckByOwner(addr)), "You don't have a duck staked")
507515 let curLocation = valueOrElse(getString(keyDuckLocation(duckAssetId)), DEFAULTLOCATION)
508516 let loc = split(value(curLocation), "_")
509517 if ((loc[locIdxType] != "L"))
510518 then throw((("Duck location type is " + loc[locIdxType]) + ", but should be L"))
511519 else {
512520 let landAssetId = loc[locIdxId]
513521 let asset = value(assetInfo(fromBase58String(landAssetId)))
514522 let timeKey = keyStakedTimeByAssetId(landAssetId)
515523 let savedTime = valueOrErrorMessage(getInteger(timeKey), (("Your duck is on " + asset.name) + ", which is not staked"))
516524 let owner = valueOrErrorMessage(getString(keyLandAssetIdToOwner(landAssetId)), (("NFT " + asset.name) + " is orphaned"))
517525 if ((owner != addr))
518526 then throw((LANDPREFIX + " is not yours"))
519527 else {
520528 let d = split(asset.description, "_")
521529 $Tuple4(duckAssetId, landAssetId, d, savedTime)
522530 }
523531 }
524532 }
525533
526534
527535 func claimResInternal (addr,amount) = if ((0 > amount))
528536 then throw("Negative amount")
529537 else {
530538 let c = checkClaimConditions(addr)
531539 let landSize = c._3[recLandSize]
532540 let terrainCounts = countTerrains(c._3[recTerrains])
533541 let deltaTime = (lastBlock.timestamp - c._4)
534542 if ((0 > deltaTime))
535543 then throw(((("Saved timestamp is in future, saved = " + toString(c._4)) + ", current = ") + toString(lastBlock.timestamp)))
536544 else {
537545 let pieces = numPiecesBySize(landSize)
538546 let dailyProductionByPiece = applyBonuses(c._2, pieces)
539547 let availRes = fraction(deltaTime, (dailyProductionByPiece * pieces), DAYMILLIS)
540548 if ((amount > availRes))
541549 then throw(((("Not enough resources, available = " + toString(availRes)) + ", requested = ") + toString(amount)))
542550 else {
543551 let newDeltaTime = fraction((availRes - amount), DAYMILLIS, (dailyProductionByPiece * pieces))
544552 let newTimestamp = (lastBlock.timestamp - newDeltaTime)
545553 let bpKey = keyBackpackByDuck(c._1)
546554 let currentPack = getBackpack(bpKey)
547555 let currentRes = split(currentPack[bpIdxRes], "_")
548556 let bpRes = addRes(currentRes, terrainCounts, (deltaTime - newDeltaTime), (pieces / SSIZE), dailyProductionByPiece)
549557 $Tuple3([IntegerEntry(keyStakedTimeByAssetId(c._2), newTimestamp), IntegerEntry(keyStakedTimeByTypeAssetIdAndOwner(LANDPREFIX, c._2, addr), newTimestamp)], bpKey, [currentPack[bpIdxLevel], bpRes, currentPack[bpIdxMat], currentPack[bpIdxProd]])
550558 }
551559 }
552560 }
553561
554562
555563 func claimAll (addr,landAssetId,pieces) = {
556564 let timeKey = keyStakedTimeByAssetId(landAssetId)
557565 let savedTime = value(getInteger(timeKey))
558566 let availRes = (fraction((lastBlock.timestamp - savedTime), applyBonuses(landAssetId, pieces), DAYMILLIS) * pieces)
559567 claimResInternal(addr, availRes)
560568 }
561569
562570
563571 func upInfraCommon (shouldUseMat,caller,paymentAmount) = {
564572 let addr = toString(caller)
565573 let c = checkClaimConditions(addr)
566574 let pieces = numPiecesBySize(c._3[recLandSize])
567575 let infraKey = keyInfraLevelByAssetId(c._2)
568576 let curLevel = valueOrElse(getInteger(infraKey), 0)
569577 if ((curLevel >= 3))
570578 then throw("Currently max infrastructure level = 3")
571579 else {
572580 let newLevel = (curLevel + 1)
573581 let cost = fraction(InfraUpgradeCostSUsdn, (pieces * newLevel), SSIZE)
574582 if (if (!(shouldUseMat))
575583 then (paymentAmount != cost)
576584 else false)
577585 then throw(("Payment attached should be " + toString(cost)))
578586 else {
579587 let bpKey = keyBackpackByDuck(c._1)
580588 let currentPack = getBackpack(bpKey)
581589 let mList = split(currentPack[bpIdxMat], "_")
582590 let newMat = makeString(subtractMaterials(shouldUseMat, mList, fraction(InfraUpgradeCostS, (pieces * newLevel), SSIZE)), "_")
583591 let claimResult = claimAll(addr, c._2, pieces)
584592 $Tuple2(([IntegerEntry(infraKey, newLevel), IntegerEntry(keyInfraLevelByAssetIdAndOwner(c._2, addr), newLevel), StringEntry(bpKey, makeString([currentPack[bpIdxLevel], claimResult._3[bpIdxRes], newMat, currentPack[bpIdxProd]], ":"))] ++ claimResult._1), newLevel)
585593 }
586594 }
587595 }
588596
589597
590598 func activatePresaleArt (addr) = {
591599 let c = checkClaimConditions(addr)
592600 let landAssetId = c._2
593601 let activationKey = keyPresaleArtActivatedByAssetId(landAssetId)
594602 if (valueOrElse(getBoolean(activationKey), false))
595603 then throw("Presale artifact is already activated")
596604 else if ((parseIntValue(c._3[recLandNum]) > PRESALENUMLANDS))
597605 then throw((((LANDPREFIX + " ") + landAssetId) + " is not eligible for presale artifact"))
598606 else {
599607 let pieces = numPiecesBySize(c._3[recLandSize])
600608 let claimResult = claimAll(addr, landAssetId, pieces)
601609 (((((claimResult._1 :+ BooleanEntry(activationKey, true)) :+ BooleanEntry(keyPresaleArtActivatedByAssetIdAndOwner(landAssetId, addr), true)) :+ IntegerEntry(keyLandArtStatusByTypeAndAssetId(ARTPRESALE, landAssetId), pieces)) :+ IntegerEntry(keyLandArtStatusByTypeAssetIdAndOwner(ARTPRESALE, landAssetId, addr), pieces)) :+ StringEntry(claimResult._2, makeString(claimResult._3, ":")))
602610 }
603611 }
604612
605613
606614 func mergeInternal (newLandSize,newLevel,formula,addr,landAssetIds,txId,needMat) = {
607615 let duckAssetId = valueOrErrorMessage(getString(keyStakedDuckByOwner(addr)), "You don't have a duck staked")
608616 func checkMerge (acc,landAssetId) = {
609617 let asset = value(assetInfo(fromBase58String(landAssetId)))
610618 let timeKey = keyStakedTimeByAssetId(landAssetId)
611619 let savedTime = valueOrErrorMessage(getInteger(timeKey), (("NFT " + asset.name) + " is not staked"))
612620 let owner = valueOrErrorMessage(getString(keyLandAssetIdToOwner(landAssetId)), (("NFT " + asset.name) + " is orphaned"))
613621 if ((owner != addr))
614622 then throw((LANDPREFIX + " is not yours"))
615623 else {
616624 let d = split(asset.description, "_")
617625 let continent = d[recContinent]
618626 if (if ((acc._3 != ""))
619627 then (acc._3 != continent)
620628 else false)
621629 then throw("Lands should be on the same continent to merge")
622630 else {
623631 let landSize = d[recLandSize]
624632 let sizesIn = acc._1
625633 let i = valueOrErrorMessage(indexOf(sizesIn, landSize), "You haven't passed all the lands needed")
626634 let sizesOut = (take(sizesIn, i) + drop(sizesIn, (i + 1)))
627635 let pieces = numPiecesBySize(landSize)
628636 let arts = (acc._2 + valueOrElse(getInteger(keyLandArtStatusByTypeAndAssetId(ARTPRESALE, landAssetId)), if (valueOrElse(getBoolean(keyPresaleArtActivatedByAssetId(landAssetId)), false))
629637 then pieces
630638 else 0))
631639 let infraLevel = valueOrElse(getInteger(keyInfraLevelByAssetId(landAssetId)), 0)
632640 let reqLevel = match landSize {
633641 case _ =>
634642 if (("S" == $match0))
635643 then 3
636644 else if (("M" == $match0))
637645 then 4
638646 else if (("L" == $match0))
639647 then 5
640648 else if (("XL" == $match0))
641649 then 6
642650 else throw("Only S, M, L, XL can merge")
643651 }
644652 if ((infraLevel != reqLevel))
645653 then throw("All lands should be maxed to merge")
646654 else {
647655 let landNum = d[recLandNum]
648656 let terrainCounts = countTerrains(d[recTerrains])
649657 let deltaTime = (lastBlock.timestamp - savedTime)
650658 if ((0 > deltaTime))
651659 then throw(((("Saved timestamp is in future, saved = " + toString(savedTime)) + ", current = ") + toString(lastBlock.timestamp)))
652660 else {
653661 let dailyProductionByPiece = applyBonuses(landAssetId, pieces)
654662 let bpRes = addRes(split(acc._4, "_"), terrainCounts, deltaTime, (pieces / SSIZE), dailyProductionByPiece)
655663 let props = updateProportionsInternal(split(acc._6, "_"), terrainCounts, (pieces / SSIZE), -1)
656664 let lands = acc._7
657665 let idx = indexOf(lands, landAssetId)
658666 if (!(isDefined(idx)))
659667 then throw(("Your staked lands don't contain " + landAssetId))
660668 else $Tuple7(sizesOut, arts, continent, bpRes, (((((((((((((acc._5 :+ DeleteEntry(keyStakedTimeByAssetId(landAssetId))) :+ DeleteEntry(keyStakedTimeByTypeAssetIdAndOwner(LANDPREFIX, landAssetId, addr))) :+ DeleteEntry(keyLandToAssetId(landNum))) :+ DeleteEntry(keyNftName(landNum, landSize))) :+ DeleteEntry(keyLandAssetIdToOwner(landAssetId))) :+ DeleteEntry(keyInfraLevelByAssetId(landAssetId))) :+ DeleteEntry(keyInfraLevelByAssetIdAndOwner(landAssetId, addr))) :+ DeleteEntry(keyPresaleArtActivatedByAssetId(landAssetId))) :+ DeleteEntry(keyPresaleArtActivatedByAssetIdAndOwner(landAssetId, addr))) :+ DeleteEntry(keyLandArtStatusByTypeAndAssetId(ARTPRESALE, landAssetId))) :+ DeleteEntry(keyLandArtStatusByTypeAssetIdAndOwner(ARTPRESALE, landAssetId, addr))) :+ DeleteEntry(keyLandNumToOwner(landNum))) :+ Burn(fromBase58String(landAssetId), 1)), props, removeByIndex(lands, value(idx)))
661669 }
662670 }
663671 }
664672 }
665673 }
666674
667675 let bpKey = keyBackpackByDuck(duckAssetId)
668676 let currentPack = getBackpack(bpKey)
669677 let propStr = valueOrElse(getString(keyResProportions()), "0_0_0_0_0_0")
670678 let landsKey = keyStakedLandsByOwner(addr)
671- let landsIn = split_51C(valueOrElse(getString(landsKey), ""), "_")
679+ let landsStr = getString(landsKey)
680+ let landsIn = if (isDefined(landsStr))
681+ then split_51C(value(landsStr), "_")
682+ else nil
672683 let r = {
673684 let $l = landAssetIds
674685 let $s = size($l)
675686 let $acc0 = $Tuple7(formula, 0, "", currentPack[bpIdxRes], nil, propStr, landsIn)
676687 func $f0_1 ($a,$i) = if (($i >= $s))
677688 then $a
678689 else checkMerge($a, $l[$i])
679690
680691 func $f0_2 ($a,$i) = if (($i >= $s))
681692 then $a
682693 else throw("List size exceeds 5")
683694
684695 $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5)
685696 }
686697 let continent = r._3
687698 let continentIdx = valueOrErrorMessage(indexOf(continents, continent), ("Unknown continent: " + continent))
688699 let terrains = genTerrains(abs(toBigInt(txId)), continentIdx)
689700 let freeNum = valueOrElse(getInteger(keyNextFreeLandNum()), (PRESALENUMLANDS + 1))
690701 let newLandNum = toString(freeNum)
691702 let issue = Issue(keyNftName(newLandNum, newLandSize), makeString([newLandNum, newLandSize, terrains, continent], "_"), 1, 0, false)
692703 let assetId = calculateAssetId(issue)
693704 let newLandAssetId = toBase58String(assetId)
694705 let newMat = makeString(subtractMaterials((needMat > 0), split(currentPack[bpIdxMat], "_"), needMat), "_")
695706 $Tuple2(((((((((((((((r._5 :+ (if ((size(r._7) > 0))
696707 then StringEntry(landsKey, makeString_11C(r._7, "_"))
697708 else DeleteEntry(landsKey))) :+ IntegerEntry(keyNextFreeLandNum(), (freeNum + 1))) :+ issue) :+ StringEntry(keyLandToAssetId(newLandNum), newLandAssetId)) :+ StringEntry(keyLandAssetIdToOwner(newLandAssetId), addr)) :+ StringEntry(keyLandNumToOwner(newLandNum), addr)) :+ IntegerEntry(keyLandArtStatusByTypeAndAssetId(ARTPRESALE, newLandAssetId), r._2)) :+ IntegerEntry(keyLandArtStatusByTypeAssetIdAndOwner(ARTPRESALE, newLandAssetId, addr), r._2)) :+ IntegerEntry(keyInfraLevelByAssetId(newLandAssetId), newLevel)) :+ IntegerEntry(keyInfraLevelByAssetIdAndOwner(newLandAssetId, addr), newLevel)) :+ StringEntry(bpKey, makeString([currentPack[bpIdxLevel], r._4, newMat, currentPack[bpIdxProd]], ":"))) :+ StringEntry(keyResProportions(), r._6)) :+ StringEntry(keyDuckLocation(duckAssetId), makeString([continent, "L", newLandAssetId], "_"))) :+ ScriptTransfer(addressFromStringValue(addr), 1, assetId)), newLandAssetId)
698709 }
699710
700711
701712 func s2m (addr,landAssetIds,txId) = mergeInternal("M", 3, "SSSS", addr, landAssetIds, txId, 0)
702713
703714
704715 func m2l (addr,landAssetIds,txId,shouldUseMat,paymentAmount) = {
705716 let cost = (InfraUpgradeCostSUsdn * 4)
706717 if (if (!(shouldUseMat))
707718 then (paymentAmount != cost)
708719 else false)
709720 then throw(("Payment attached should be " + toString(cost)))
710721 else mergeInternal("L", 4, "SMM", addr, landAssetIds, txId, (InfraUpgradeCostS * 4))
711722 }
712723
713724
714725 func l2xl (addr,landAssetIds,txId,shouldUseMat,paymentAmount) = {
715726 let cost = (InfraUpgradeCostSUsdn * 47)
716727 if (if (!(shouldUseMat))
717728 then (paymentAmount != cost)
718729 else false)
719730 then throw(("Payment attached should be " + toString(cost)))
720731 else mergeInternal("XL", 5, "SSSML", addr, landAssetIds, txId, (InfraUpgradeCostS * 47))
721732 }
722733
723734
724735 func xl2xxl (addr,landAssetIds,txId,shouldUseMat,paymentAmount) = {
725736 let cost = (InfraUpgradeCostSUsdn * 54)
726737 if (if (!(shouldUseMat))
727738 then (paymentAmount != cost)
728739 else false)
729740 then throw(("Payment attached should be " + toString(cost)))
730741 else mergeInternal("XXL", 6, "LXL", addr, landAssetIds, txId, (InfraUpgradeCostS * 54))
731742 }
732743
733744
734745 func mergeCommon (shouldUseMat,addr,paymentAmount,landAssetIds,txId) = {
735746 let mergeResult = match size(landAssetIds) {
736747 case _ =>
737748 if ((4 == $match0))
738749 then s2m(addr, landAssetIds, txId)
739750 else if ((3 == $match0))
740751 then m2l(addr, landAssetIds, txId, shouldUseMat, paymentAmount)
741752 else if ((5 == $match0))
742753 then l2xl(addr, landAssetIds, txId, shouldUseMat, paymentAmount)
743754 else if ((2 == $match0))
744755 then xl2xxl(addr, landAssetIds, txId, shouldUseMat, paymentAmount)
745756 else throw("Unknown merge")
746757 }
747758 mergeResult
748759 }
749760
750761
751-func saveTxId (addr,txId) = StringEntry(keyLastTxIdByUser(toString(addr)), toBase58String(txId))
752-
753-
754-func checkBlocked () = if (valueOrElse(getBoolean(keyBlocked()), false))
762+func prolog (i) = if (valueOrElse(getBoolean(keyBlocked()), false))
755763 then throw("Contracts are under maintenance")
756- else unit
764+ else StringEntry(keyLastTxIdByUser(toString(i.originCaller)), toBase58String(i.transactionId))
757765
758766
759767 @Callable(i)
760768 func setBlocked (isBlocked) = if ((i.caller != this))
761769 then throw("permission denied")
762770 else [BooleanEntry(keyBlocked(), isBlocked)]
763771
764772
765773
766774 @Callable(i)
767775 func stakeLand () = {
768- let blocked = checkBlocked()
769- if ((blocked == blocked))
770- then if ((size(i.payments) != 1))
771- then throw("Exactly one payment required")
772- else {
773- let pmt = value(i.payments[0])
774- let assetId = value(pmt.assetId)
775- let address = toString(i.caller)
776- if ((pmt.amount != 1))
777- then throw((("NFT " + LANDPREFIX) + " token should be attached as payment"))
778- else {
779- let asset = value(assetInfo(assetId))
780- if ((asset.issuer != this))
781- then throw("Unknown issuer of token")
782- else if (!(contains(asset.name, LANDPREFIX)))
783- then throw((("Only NFT " + LANDPREFIX) + " tokens are accepted"))
784- else {
785- let landNumSize = drop(asset.name, 4)
786- let landNum = if (contains(landNumSize, "XXL"))
787- then dropRight(landNumSize, 3)
788- else if (contains(landNumSize, "XL"))
789- then dropRight(landNumSize, 2)
790- else dropRight(landNumSize, 1)
791- if (!(isDefined(parseInt(landNum))))
792- then throw(("Cannot parse land number from " + asset.name))
793- else {
794- let landAssetId = toBase58String(assetId)
795- let timeKey = keyStakedTimeByAssetId(landAssetId)
796- if (isDefined(getInteger(timeKey)))
797- then throw((("NFT " + asset.name) + " is already staked"))
798- else {
799- let d = split(asset.description, "_")
800- let terrainCounts = countTerrains(d[recTerrains])
801- let props = updateProportions(terrainCounts, (numPiecesBySize(d[recLandSize]) / SSIZE), 1)
802- let lands = split_51C(valueOrElse(getString(keyStakedLandsByOwner(address)), ""), "_")
803- if (containsElement(lands, landAssetId))
804- then throw(("Your staked lands already contain " + landAssetId))
805- else [IntegerEntry(timeKey, lastBlock.timestamp), IntegerEntry(keyStakedTimeByTypeAssetIdAndOwner(LANDPREFIX, landAssetId, address), lastBlock.timestamp), StringEntry(keyStakedLandsByOwner(address), makeString_11C((lands :+ landAssetId), "_")), StringEntry(keyLandAssetIdToOwner(landAssetId), address), StringEntry(keyLandNumToOwner(landNum), address), StringEntry(keyResProportions(), props)]
806- }
807- }
808- }
809- }
810- }
811- else throw("Strict value is not equal to itself.")
776+ let prologAction = prolog(i)
777+ if ((size(i.payments) != 1))
778+ then throw("Exactly one payment required")
779+ else {
780+ let pmt = value(i.payments[0])
781+ let assetId = value(pmt.assetId)
782+ let address = toString(i.caller)
783+ if ((pmt.amount != 1))
784+ then throw((("NFT " + LANDPREFIX) + " token should be attached as payment"))
785+ else {
786+ let asset = value(assetInfo(assetId))
787+ if ((asset.issuer != this))
788+ then throw("Unknown issuer of token")
789+ else if (!(contains(asset.name, LANDPREFIX)))
790+ then throw((("Only NFT " + LANDPREFIX) + " tokens are accepted"))
791+ else {
792+ let landNumSize = drop(asset.name, 4)
793+ let landNum = if (contains(landNumSize, "XXL"))
794+ then dropRight(landNumSize, 3)
795+ else if (contains(landNumSize, "XL"))
796+ then dropRight(landNumSize, 2)
797+ else dropRight(landNumSize, 1)
798+ if (!(isDefined(parseInt(landNum))))
799+ then throw(("Cannot parse land number from " + asset.name))
800+ else {
801+ let landAssetId = toBase58String(assetId)
802+ let timeKey = keyStakedTimeByAssetId(landAssetId)
803+ if (isDefined(getInteger(timeKey)))
804+ then throw((("NFT " + asset.name) + " is already staked"))
805+ else {
806+ let d = split(asset.description, "_")
807+ let terrainCounts = countTerrains(d[recTerrains])
808+ let props = updateProportions(terrainCounts, (numPiecesBySize(d[recLandSize]) / SSIZE), 1)
809+ let landsStr = getString(keyStakedLandsByOwner(address))
810+ let lands = if (isDefined(landsStr))
811+ then split_51C(value(landsStr), "_")
812+ else nil
813+ if (containsElement(lands, landAssetId))
814+ then throw(("Your staked lands already contain " + landAssetId))
815+ else [IntegerEntry(timeKey, lastBlock.timestamp), IntegerEntry(keyStakedTimeByTypeAssetIdAndOwner(LANDPREFIX, landAssetId, address), lastBlock.timestamp), StringEntry(keyStakedLandsByOwner(address), makeString_11C((lands :+ landAssetId), "_")), StringEntry(keyLandAssetIdToOwner(landAssetId), address), StringEntry(keyLandNumToOwner(landNum), address), StringEntry(keyResProportions(), props), prologAction]
816+ }
817+ }
818+ }
819+ }
820+ }
812821 }
813822
814823
815824
816825 @Callable(i)
817826 func unstakeLand (landAssetIdIgnored) = {
818- let blocked = checkBlocked()
819- if ((blocked == blocked))
820- then if ((size(i.payments) != 0))
821- then throw("unstake doesn't require any payments")
822- else {
823- let addr = toString(i.caller)
824- let c = checkClaimConditions(addr)
825- let landAssetId = c._2
826- let landsKey = keyStakedLandsByOwner(addr)
827- let terrainCounts = countTerrains(c._3[recTerrains])
828- let pieces = numPiecesBySize(c._3[recLandSize])
829- let props = updateProportions(terrainCounts, (pieces / SSIZE), -1)
830- let claimResult = claimAll(addr, landAssetId, pieces)
831- let lands = split_51C(valueOrElse(getString(landsKey), ""), "_")
832- let idx = indexOf(lands, landAssetId)
833- if (!(isDefined(idx)))
834- then throw(("Your staked lands don't contain " + landAssetId))
835- else [ScriptTransfer(i.caller, 1, fromBase58String(landAssetId)), DeleteEntry(keyStakedTimeByAssetId(landAssetId)), DeleteEntry(keyStakedTimeByTypeAssetIdAndOwner(LANDPREFIX, landAssetId, addr)), StringEntry(keyResProportions(), props), StringEntry(claimResult._2, makeString(claimResult._3, ":")), if ((size(lands) > 1))
836- then StringEntry(landsKey, makeString_11C(removeByIndex(lands, value(idx)), "_"))
837- else DeleteEntry(landsKey)]
838- }
839- else throw("Strict value is not equal to itself.")
827+ let prologAction = prolog(i)
828+ if ((size(i.payments) != 0))
829+ then throw("unstake doesn't require any payments")
830+ else {
831+ let addr = toString(i.caller)
832+ let c = checkClaimConditions(addr)
833+ let landAssetId = c._2
834+ let landsKey = keyStakedLandsByOwner(addr)
835+ let terrainCounts = countTerrains(c._3[recTerrains])
836+ let pieces = numPiecesBySize(c._3[recLandSize])
837+ let props = updateProportions(terrainCounts, (pieces / SSIZE), -1)
838+ let claimResult = claimAll(addr, landAssetId, pieces)
839+ let lands = split_51C(valueOrElse(getString(landsKey), ""), "_")
840+ let idx = indexOf(lands, landAssetId)
841+ if (!(isDefined(idx)))
842+ then throw(("Your staked lands don't contain " + landAssetId))
843+ else [ScriptTransfer(i.caller, 1, fromBase58String(landAssetId)), DeleteEntry(keyStakedTimeByAssetId(landAssetId)), DeleteEntry(keyStakedTimeByTypeAssetIdAndOwner(LANDPREFIX, landAssetId, addr)), StringEntry(keyResProportions(), props), StringEntry(claimResult._2, makeString(claimResult._3, ":")), if ((size(lands) > 1))
844+ then StringEntry(landsKey, makeString_11C(removeByIndex(lands, value(idx)), "_"))
845+ else DeleteEntry(landsKey), prologAction]
846+ }
840847 }
841848
842849
843850
844851 @Callable(i)
845852 func stakeDuck () = {
846- let blocked = checkBlocked()
847- if ((blocked == blocked))
848- then if ((size(i.payments) != 1))
849- then throw("Exactly one payment required")
850- else {
851- let pmt = value(i.payments[0])
852- let assetId = value(pmt.assetId)
853- let address = toString(i.caller)
854- if ((pmt.amount != 1))
855- then throw((("NFT " + DUCKPREFIX) + " token should be attached as payment"))
856- else {
857- let asset = value(assetInfo(assetId))
858- if (if ((asset.issuer != incubatorAddr))
859- then (asset.issuer != breederAddr)
860- else false)
861- then throw((("Unknown issuer of " + DUCKPREFIX) + " token"))
862- else if (!(contains(asset.name, DUCKPREFIX)))
863- then throw((("Only NFT " + DUCKPREFIX) + " tokens are accepted"))
864- else {
865- let assetIdStr = toBase58String(assetId)
866- let timeKey = keyStakedTimeByAssetId(assetIdStr)
867- if (isDefined(getInteger(timeKey)))
868- then throw((("NFT " + asset.name) + " is already staked"))
869- else if (isDefined(getString(keyStakedDuckByOwner(address))))
870- then throw(("You already staked one duck: " + asset.name))
871- else {
872- let locKey = keyDuckLocation(assetIdStr)
873- let location = getString(locKey)
874- let bpKey = keyBackpackByDuck(assetIdStr)
875- let backpack = getString(bpKey)
876- ([IntegerEntry(timeKey, lastBlock.timestamp), IntegerEntry(keyStakedTimeByTypeAssetIdAndOwner(DUCKPREFIX, toBase58String(assetId), address), lastBlock.timestamp), StringEntry(keyDuckIdToOwner(assetIdStr), address), StringEntry(keyStakedDuckByOwner(address), assetIdStr)] ++ (if (isDefined(location))
853+ let prologAction = prolog(i)
854+ if ((size(i.payments) != 1))
855+ then throw("Exactly one payment required")
856+ else {
857+ let pmt = value(i.payments[0])
858+ let assetId = value(pmt.assetId)
859+ let address = toString(i.caller)
860+ if ((pmt.amount != 1))
861+ then throw((("NFT " + DUCKPREFIX) + " token should be attached as payment"))
862+ else {
863+ let asset = value(assetInfo(assetId))
864+ if (if ((asset.issuer != incubatorAddr))
865+ then (asset.issuer != breederAddr)
866+ else false)
867+ then throw((("Unknown issuer of " + DUCKPREFIX) + " token"))
868+ else if (!(contains(asset.name, DUCKPREFIX)))
869+ then throw((("Only NFT " + DUCKPREFIX) + " tokens are accepted"))
870+ else {
871+ let assetIdStr = toBase58String(assetId)
872+ let timeKey = keyStakedTimeByAssetId(assetIdStr)
873+ if (isDefined(getInteger(timeKey)))
874+ then throw((("NFT " + asset.name) + " is already staked"))
875+ else if (isDefined(getString(keyStakedDuckByOwner(address))))
876+ then throw(("You already staked one duck: " + asset.name))
877+ else {
878+ let locKey = keyDuckLocation(assetIdStr)
879+ let location = getString(locKey)
880+ let bpKey = keyBackpackByDuck(assetIdStr)
881+ let backpack = getString(bpKey)
882+ ([IntegerEntry(timeKey, lastBlock.timestamp), IntegerEntry(keyStakedTimeByTypeAssetIdAndOwner(DUCKPREFIX, toBase58String(assetId), address), lastBlock.timestamp), StringEntry(keyDuckIdToOwner(assetIdStr), address), StringEntry(keyStakedDuckByOwner(address), assetIdStr)] ++ (if (isDefined(location))
883+ then nil
884+ else ([StringEntry(locKey, DEFAULTLOCATION)] ++ (if (isDefined(backpack))
877885 then nil
878- else ([StringEntry(locKey, DEFAULTLOCATION)] ++ (if (isDefined(backpack))
879- then nil
880- else ([StringEntry(bpKey, "0:0_0_0_0_0_0:0_0_0_0_0_0:")] :+ IntegerEntry(keyDuckHealth(assetIdStr), 100))))))
881- }
882- }
883- }
884- }
885- else throw("Strict value is not equal to itself.")
886+ else (([StringEntry(bpKey, "0:0_0_0_0_0_0:0_0_0_0_0_0:")] :+ IntegerEntry(keyDuckHealth(assetIdStr), 100)) :+ prologAction)))))
887+ }
888+ }
889+ }
890+ }
886891 }
887892
888893
889894
890895 @Callable(i)
891896 func unstakeDuck (assetIdStr) = {
892- let blocked = checkBlocked()
893- if ((blocked == blocked))
894- then if ((size(i.payments) != 0))
895- then throw("unstake doesn't require any payments")
896- else {
897- let assetId = fromBase58String(assetIdStr)
898- let address = toString(i.caller)
899- let asset = value(assetInfo(assetId))
900- let timeKey = keyStakedTimeByAssetId(toBase58String(assetId))
901- if (!(isDefined(timeKey)))
902- then throw((("NFT " + asset.name) + " is not staked"))
903- else if (!(isDefined(keyStakedDuckByOwner(address))))
904- then throw((("The duck " + asset.name) + " is not staked"))
905- else {
906- let owner = valueOrErrorMessage(getString(keyDuckIdToOwner(toBase58String(assetId))), (("NFT " + asset.name) + " is orphaned"))
907- if ((owner != address))
908- then throw("Staked NFT is not yours")
909- else {
910- let keyHealth = keyDuckHealth(assetIdStr)
911- let health = valueOrElse(getInteger(keyHealth), 100)
912- if ((health != 100))
913- then throw("Please heal your duck before unstaking")
914- else [ScriptTransfer(i.caller, 1, assetId), DeleteEntry(timeKey), DeleteEntry(keyHealth), DeleteEntry(keyDuckLocation(assetIdStr)), DeleteEntry(keyDuckIdToOwner(assetIdStr)), DeleteEntry(keyStakedTimeByTypeAssetIdAndOwner(DUCKPREFIX, assetIdStr, address)), DeleteEntry(keyStakedDuckByOwner(address))]
915- }
916- }
917- }
918- else throw("Strict value is not equal to itself.")
897+ let prologAction = prolog(i)
898+ if ((size(i.payments) != 0))
899+ then throw("unstake doesn't require any payments")
900+ else {
901+ let assetId = fromBase58String(assetIdStr)
902+ let address = toString(i.caller)
903+ let asset = value(assetInfo(assetId))
904+ let timeKey = keyStakedTimeByAssetId(toBase58String(assetId))
905+ if (!(isDefined(timeKey)))
906+ then throw((("NFT " + asset.name) + " is not staked"))
907+ else if (!(isDefined(keyStakedDuckByOwner(address))))
908+ then throw((("The duck " + asset.name) + " is not staked"))
909+ else {
910+ let owner = valueOrErrorMessage(getString(keyDuckIdToOwner(toBase58String(assetId))), (("NFT " + asset.name) + " is orphaned"))
911+ if ((owner != address))
912+ then throw("Staked NFT is not yours")
913+ else {
914+ let keyHealth = keyDuckHealth(assetIdStr)
915+ let health = valueOrElse(getInteger(keyHealth), 100)
916+ if ((health != 100))
917+ then throw("Please heal your duck before unstaking")
918+ else [ScriptTransfer(i.caller, 1, assetId), DeleteEntry(timeKey), DeleteEntry(keyHealth), DeleteEntry(keyDuckLocation(assetIdStr)), DeleteEntry(keyDuckIdToOwner(assetIdStr)), DeleteEntry(keyStakedTimeByTypeAssetIdAndOwner(DUCKPREFIX, assetIdStr, address)), DeleteEntry(keyStakedDuckByOwner(address)), prologAction]
919+ }
920+ }
921+ }
919922 }
920923
921924
922925
923926 @Callable(i)
924927 func claimRes (amount,landAssetIdStr) = {
925- let blocked = checkBlocked()
926- if ((blocked == blocked))
927- then if ((size(i.payments) != 0))
928- then throw("claimRes doesn't require any payments")
929- else {
930- let addr = toString(i.originCaller)
931- let result = claimResInternal(addr, amount)
932- $Tuple2((result._1 :+ StringEntry(result._2, makeString(result._3, ":"))), result._3[bpIdxRes])
933- }
934- else throw("Strict value is not equal to itself.")
928+ let prologAction = prolog(i)
929+ if ((size(i.payments) != 0))
930+ then throw("claimRes doesn't require any payments")
931+ else {
932+ let addr = toString(i.originCaller)
933+ let result = claimResInternal(addr, amount)
934+ $Tuple2(((result._1 :+ StringEntry(result._2, makeString(result._3, ":"))) :+ prologAction), result._3[bpIdxRes])
935+ }
935936 }
936937
937938
938939
939940 @Callable(i)
940941 func flight (message,sig) = {
941- let blocked = checkBlocked()
942- if ((blocked == blocked))
943- then if (!(sigVerify_8Kb(message, sig, pub)))
944- then throw("signature does not match")
945- else if ((size(i.payments) != 0))
946- then throw("flight doesn't require any payments")
947- else {
948- let parts = split(toUtf8String(message), ";")
949- let hp = split(split(parts[0], "|")[0], "_")
950- let curHP = parseIntValue(hp[0])
951- let newHP = parseIntValue(hp[1])
952- let newLocAndTime = split(parts[1], ":")
953- let newLocation = newLocAndTime[0]
954- let time = parseIntValue(newLocAndTime[1])
955- if (if ((time > (lastBlock.timestamp + FIVEMINUTESMILLIS)))
956- then true
957- else ((lastBlock.timestamp - FIVEMINUTESMILLIS) > time))
958- then throw("signature outdated")
959- else {
960- let duckAssetId = valueOrErrorMessage(getString(keyStakedDuckByOwner(toString(i.caller))), "You don't have a duck staked")
961- let keyHealth = keyDuckHealth(duckAssetId)
962- let oldFromState = valueOrElse(getInteger(keyHealth), 100)
963- if ((oldFromState != curHP))
964- then throw(((("oldHealth=" + toString(valueOrElse(getInteger(keyHealth), 100))) + " from state does not match one from flight log=") + toString(curHP)))
965- else if ((0 >= curHP))
966- then throw("You can't fly with zero health")
967- else {
968- let locKey = keyDuckLocation(duckAssetId)
969- let curLocation = valueOrElse(getString(locKey), DEFAULTLOCATION)
970- if ((newLocation == curLocation))
971- then throw("You can't fly to the same location")
972- else $Tuple2([StringEntry(locKey, if ((newHP > 0))
973- then newLocation
974- else curLocation), IntegerEntry(keyHealth, newHP)], unit)
975- }
976- }
977- }
978- else throw("Strict value is not equal to itself.")
942+ let prologAction = prolog(i)
943+ if (!(sigVerify_8Kb(message, sig, pub)))
944+ then throw("signature does not match")
945+ else if ((size(i.payments) != 0))
946+ then throw("flight doesn't require any payments")
947+ else {
948+ let parts = split(toUtf8String(message), ";")
949+ let hp = split(split(parts[0], "|")[0], "_")
950+ let curHP = parseIntValue(hp[0])
951+ let newHP = parseIntValue(hp[1])
952+ let newLocAndTime = split(parts[1], ":")
953+ let newLocation = newLocAndTime[0]
954+ let time = parseIntValue(newLocAndTime[1])
955+ if (if ((time > (lastBlock.timestamp + FIVEMINUTESMILLIS)))
956+ then true
957+ else ((lastBlock.timestamp - FIVEMINUTESMILLIS) > time))
958+ then throw("signature outdated")
959+ else {
960+ let duckAssetId = valueOrErrorMessage(getString(keyStakedDuckByOwner(toString(i.caller))), "You don't have a duck staked")
961+ let keyHealth = keyDuckHealth(duckAssetId)
962+ let oldFromState = valueOrElse(getInteger(keyHealth), 100)
963+ if ((oldFromState != curHP))
964+ then throw(((("oldHealth=" + toString(valueOrElse(getInteger(keyHealth), 100))) + " from state does not match one from flight log=") + toString(curHP)))
965+ else if ((0 >= curHP))
966+ then throw("You can't fly with zero health")
967+ else {
968+ let locKey = keyDuckLocation(duckAssetId)
969+ let curLocation = valueOrElse(getString(locKey), DEFAULTLOCATION)
970+ if ((newLocation == curLocation))
971+ then throw("You can't fly to the same location")
972+ else $Tuple2([StringEntry(locKey, if ((newHP > 0))
973+ then newLocation
974+ else curLocation), IntegerEntry(keyHealth, newHP), prologAction], unit)
975+ }
976+ }
977+ }
979978 }
980979
981980
982981
983982 @Callable(i)
984983 func setHealth (health,duckAssetId) = {
985- let blocked = checkBlocked()
986- if ((blocked == blocked))
987- then if (if ((0 > health))
988- then true
989- else (health > 100))
990- then throw("HP should be within 0..100")
991- else [IntegerEntry(keyDuckHealth(duckAssetId), health)]
992- else throw("Strict value is not equal to itself.")
984+ let prologAction = prolog(i)
985+ if (if ((0 > health))
986+ then true
987+ else (health > 100))
988+ then throw("HP should be within 0..100")
989+ else [IntegerEntry(keyDuckHealth(duckAssetId), health), prologAction]
993990 }
994991
995992
996993
997994 @Callable(i)
998995 func heal (matType,amount) = {
999- let blocked = checkBlocked()
1000- if ((blocked == blocked))
1001- then if (if ((0 > matType))
1002- then true
1003- else (matType >= NUMRES))
1004- then throw(("Unknown material: " + toString(matType)))
1005- else if ((0 >= amount))
1006- then throw(("Amount should be positive! " + toString(amount)))
1007- else {
1008- let duckAssetId = valueOrErrorMessage(getString(keyStakedDuckByOwner(toString(i.caller))), "You don't have a duck staked")
1009- let keyHealth = keyDuckHealth(duckAssetId)
1010- let oldHealth = valueOrElse(getInteger(keyHealth), 100)
1011- if ((oldHealth >= 100))
1012- then throw("HP should be < 100 to heal")
1013- else {
1014- let bpKey = keyBackpackByDuck(duckAssetId)
1015- let currentPack = getBackpack(bpKey)
1016- let mList = split(currentPack[bpIdxMat], "_")
1017- let currentAmount = parseIntValue(mList[matType])
1018- let deltaHealth = min([(amount / HEALCOST), (100 - oldHealth)])
1019- let spendAmount = (deltaHealth * HEALCOST)
1020- if ((spendAmount > currentAmount))
1021- then throw(((((("You need " + toString(spendAmount)) + " of ") + matTypes[matType]) + " to heal, but you backpack contains ") + toString(currentAmount)))
1022- else {
1023- let newMat = subOneInList(mList, matType, spendAmount)
1024-[IntegerEntry(keyHealth, (oldHealth + deltaHealth)), StringEntry(bpKey, makeString([currentPack[bpIdxLevel], currentPack[bpIdxRes], newMat, currentPack[bpIdxProd]], ":"))]
1025- }
1026- }
1027- }
1028- else throw("Strict value is not equal to itself.")
996+ let prologAction = prolog(i)
997+ if (if ((0 > matType))
998+ then true
999+ else (matType >= NUMRES))
1000+ then throw(("Unknown material: " + toString(matType)))
1001+ else if ((0 >= amount))
1002+ then throw(("Amount should be positive! " + toString(amount)))
1003+ else {
1004+ let duckAssetId = valueOrErrorMessage(getString(keyStakedDuckByOwner(toString(i.caller))), "You don't have a duck staked")
1005+ let keyHealth = keyDuckHealth(duckAssetId)
1006+ let oldHealth = valueOrElse(getInteger(keyHealth), 100)
1007+ if ((oldHealth >= 100))
1008+ then throw("HP should be < 100 to heal")
1009+ else {
1010+ let bpKey = keyBackpackByDuck(duckAssetId)
1011+ let currentPack = getBackpack(bpKey)
1012+ let mList = split(currentPack[bpIdxMat], "_")
1013+ let currentAmount = parseIntValue(mList[matType])
1014+ let deltaHealth = min([(amount / HEALCOST), (100 - oldHealth)])
1015+ let spendAmount = (deltaHealth * HEALCOST)
1016+ if ((spendAmount > currentAmount))
1017+ then throw(((((("You need " + toString(spendAmount)) + " of ") + matTypes[matType]) + " to heal, but you backpack contains ") + toString(currentAmount)))
1018+ else {
1019+ let newMat = subOneInList(mList, matType, spendAmount)
1020+[IntegerEntry(keyHealth, (oldHealth + deltaHealth)), StringEntry(bpKey, makeString([currentPack[bpIdxLevel], currentPack[bpIdxRes], newMat, currentPack[bpIdxProd]], ":")), prologAction]
1021+ }
1022+ }
1023+ }
10291024 }
10301025
10311026
10321027
10331028 @Callable(i)
1034-func updateBackpack (duckAssetId,newPack) = if ((i.caller != economyContract))
1035- then throw("permission denied")
1036- else $Tuple2([StringEntry(keyBackpackByDuck(duckAssetId), newPack)], newPack)
1029+func updateBackpack (duckAssetId,newPack) = {
1030+ let prologAction = prolog(i)
1031+ if ((i.caller != economyContract))
1032+ then throw("permission denied")
1033+ else $Tuple2([StringEntry(keyBackpackByDuck(duckAssetId), newPack), prologAction], newPack)
1034+ }
1035+
1036+
1037+
1038+@Callable(i)
1039+func buySLand () = {
1040+ let prologAction = prolog(i)
1041+ if ((size(i.payments) != 1))
1042+ then throw("Exactly one payment required")
1043+ else {
1044+ let pmt = value(i.payments[0])
1045+ if ((pmt.assetId != usdnAssetId))
1046+ then throw("Allowed USDN payment only!")
1047+ else if ((pmt.amount != EXPUSDN))
1048+ then throw(("Payment attached should be " + toString(EXPUSDN)))
1049+ else {
1050+ let result = expeditionInternal(i.caller, i.transactionId)
1051+ $Tuple2(((result._1 :+ ScriptTransfer(economyContract, pmt.amount, usdnAssetId)) :+ prologAction), result._2._1)
1052+ }
1053+ }
1054+ }
10371055
10381056
10391057
10401058 @Callable(i)
10411059 func expeditionBuy (message,sig) = {
1042- let blocked = checkBlocked()
1043- if ((blocked == blocked))
1044- then if ((size(i.payments) != 1))
1045- then throw("Exactly one payment required")
1046- else {
1047- let pmt = value(i.payments[0])
1048- if ((pmt.assetId != usdnAssetId))
1049- then throw("Allowed USDN payment only!")
1050- else if ((pmt.amount != EXPUSDN))
1051- then throw(("Payment attached should be " + toString(EXPUSDN)))
1052- else {
1053- let result = expeditionCommon(false, i.caller, i.transactionId, message, sig)
1054- if ((result._2 == ""))
1055- then result
1056- else $Tuple2((result._1 :+ ScriptTransfer(economyContract, pmt.amount, usdnAssetId)), result._2)
1057- }
1058- }
1059- else throw("Strict value is not equal to itself.")
1060+ let prologAction = prolog(i)
1061+ if ((size(i.payments) != 1))
1062+ then throw("Exactly one payment required")
1063+ else {
1064+ let pmt = value(i.payments[0])
1065+ if ((pmt.assetId != usdnAssetId))
1066+ then throw("Allowed USDN payment only!")
1067+ else if ((pmt.amount != EXPUSDN))
1068+ then throw(("Payment attached should be " + toString(EXPUSDN)))
1069+ else {
1070+ let result = expeditionCommon(false, i.caller, i.transactionId, message, sig)
1071+ if ((result._2 == ""))
1072+ then result
1073+ else $Tuple2(((result._1 :+ ScriptTransfer(economyContract, pmt.amount, usdnAssetId)) :+ prologAction), result._2)
1074+ }
1075+ }
10601076 }
10611077
10621078
10631079
10641080 @Callable(i)
10651081 func expedition (message,sig) = {
1066- let blocked = checkBlocked()
1067- if ((blocked == blocked))
1068- then if ((size(i.payments) != 0))
1069- then throw("expedition doesn't require any payments")
1070- else expeditionCommon(true, i.caller, i.transactionId, message, sig)
1071- else throw("Strict value is not equal to itself.")
1082+ let prologAction = prolog(i)
1083+ if ((size(i.payments) != 0))
1084+ then throw("expedition doesn't require any payments")
1085+ else {
1086+ let result = expeditionCommon(true, i.caller, i.transactionId, message, sig)
1087+ $Tuple2((result._1 :+ prologAction), result._2)
1088+ }
10721089 }
10731090
10741091
10751092
10761093 @Callable(i)
10771094 func upgradeInfra (landAssetIdIgnored) = {
1078- let blocked = checkBlocked()
1079- if ((blocked == blocked))
1080- then if ((size(i.payments) != 0))
1081- then throw("Infrastructure upgrade doesn't require any payments")
1082- else upInfraCommon(true, i.caller, 0)
1083- else throw("Strict value is not equal to itself.")
1095+ let prologAction = prolog(i)
1096+ if ((size(i.payments) != 0))
1097+ then throw("Infrastructure upgrade doesn't require any payments")
1098+ else {
1099+ let result = upInfraCommon(true, i.caller, 0)
1100+ $Tuple2((result._1 :+ prologAction), result._2)
1101+ }
10841102 }
10851103
10861104
10871105
10881106 @Callable(i)
10891107 func upgradeInfraUsdn (landAssetIdIgnored) = {
1090- let blocked = checkBlocked()
1091- if ((blocked == blocked))
1092- then if ((size(i.payments) != 1))
1093- then throw("Exactly one payment required")
1094- else {
1095- let pmt = value(i.payments[0])
1096- if ((pmt.assetId != usdnAssetId))
1097- then throw("Allowed USDN payment only!")
1098- else {
1099- let result = upInfraCommon(false, i.caller, pmt.amount)
1100- $Tuple2((result._1 :+ ScriptTransfer(economyContract, pmt.amount, usdnAssetId)), result._2)
1101- }
1102- }
1103- else throw("Strict value is not equal to itself.")
1108+ let prologAction = prolog(i)
1109+ if ((size(i.payments) != 1))
1110+ then throw("Exactly one payment required")
1111+ else {
1112+ let pmt = value(i.payments[0])
1113+ if ((pmt.assetId != usdnAssetId))
1114+ then throw("Allowed USDN payment only!")
1115+ else {
1116+ let result = upInfraCommon(false, i.caller, pmt.amount)
1117+ $Tuple2(((result._1 :+ ScriptTransfer(economyContract, pmt.amount, usdnAssetId)) :+ prologAction), result._2)
1118+ }
1119+ }
11041120 }
11051121
11061122
11071123
11081124 @Callable(i)
11091125 func activateArtifact (artName) = {
1110- let blocked = checkBlocked()
1111- if ((blocked == blocked))
1112- then if ((size(i.payments) != 0))
1113- then throw("Artifact activation doesn't require any payments")
1114- else {
1115- let result = match artName {
1116- case _ =>
1117- if (("PRESALE" == $match0))
1118- then activatePresaleArt(toString(i.caller))
1119- else throw("Unknown artifact")
1120- }
1121- result
1122- }
1123- else throw("Strict value is not equal to itself.")
1126+ let prologAction = prolog(i)
1127+ if ((size(i.payments) != 0))
1128+ then throw("Artifact activation doesn't require any payments")
1129+ else {
1130+ let result = match artName {
1131+ case _ =>
1132+ if (("PRESALE" == $match0))
1133+ then activatePresaleArt(toString(i.caller))
1134+ else throw("Unknown artifact")
1135+ }
1136+ (result :+ prologAction)
1137+ }
11241138 }
11251139
11261140
11271141
11281142 @Callable(i)
1129-func mergeLands (landAssetIds) = if ((i.caller != this))
1130- then throw("permission denied")
1131- else {
1132- let blocked = checkBlocked()
1133- if ((blocked == blocked))
1134- then if ((size(i.payments) != 0))
1135- then throw("Lands merging doesn't require any payments")
1136- else mergeCommon(true, toString(i.caller), 0, landAssetIds, i.transactionId)
1137- else throw("Strict value is not equal to itself.")
1138- }
1143+func mergeLands (landAssetIds) = {
1144+ let prologAction = prolog(i)
1145+ if ((size(i.payments) != 0))
1146+ then throw("Lands merging doesn't require any payments")
1147+ else {
1148+ let result = mergeCommon(true, toString(i.caller), 0, landAssetIds, i.transactionId)
1149+ $Tuple2((result._1 :+ prologAction), result._2)
1150+ }
1151+ }
11391152
11401153
11411154
11421155 @Callable(i)
1143-func mergeLandsUsdn (landAssetIds) = if ((i.caller != this))
1144- then throw("permission denied")
1145- else {
1146- let blocked = checkBlocked()
1147- if ((blocked == blocked))
1148- then if ((size(i.payments) != 1))
1149- then throw("Exactly one payment required")
1156+func mergeLandsUsdn (landAssetIds) = {
1157+ let prologAction = prolog(i)
1158+ if ((size(i.payments) != 1))
1159+ then throw("Exactly one payment required")
1160+ else {
1161+ let pmt = value(i.payments[0])
1162+ if ((pmt.assetId != usdnAssetId))
1163+ then throw("Allowed USDN payment only!")
11501164 else {
1151- let pmt = value(i.payments[0])
1152- if ((pmt.assetId != usdnAssetId))
1153- then throw("Allowed USDN payment only!")
1154- else {
1155- let result = mergeCommon(false, toString(i.caller), pmt.amount, landAssetIds, i.transactionId)
1156- $Tuple2((result._1 :+ ScriptTransfer(economyContract, pmt.amount, usdnAssetId)), result._2)
1157- }
1165+ let result = mergeCommon(false, toString(i.caller), pmt.amount, landAssetIds, i.transactionId)
1166+ $Tuple2(((result._1 :+ ScriptTransfer(economyContract, pmt.amount, usdnAssetId)) :+ prologAction), result._2)
11581167 }
1159- else throw("Strict value is not equal to itself.")
1160- }
1168+ }
1169+ }
11611170
11621171
11631172
11641173 @Callable(i)
11651174 func splitByGlobalWeightsREADONLY (amount) = $Tuple2(nil, getNeededMaterials(amount))
11661175
11671176
11681177
11691178 @Callable(i)
11701179 func splitByLocalWeightsREADONLY (amount,terrains) = {
11711180 let terrainCounts = countTerrains(terrains)
11721181 $Tuple2(nil, distributeByWeights(amount, terrainCounts))
11731182 }
11741183
11751184
1185+
1186+@Callable(i)
1187+func getBackpackREADONLY (duckAssetId) = $Tuple2(nil, makeString(getBackpack(keyBackpackByDuck(duckAssetId)), ":"))
1188+
1189+

github/deemru/w8io/6500d08 
151.41 ms