tx · 5hYXzNHpujRezK3uX59EtuPTNcfmz1g94C1gPvpVR763

3NDCyBG5q85JuaRiigUeEtainyjCQT3XpZm:  -0.03100000 Waves

2023.01.17 14:37 [2408879] smart account 3NDCyBG5q85JuaRiigUeEtainyjCQT3XpZm > SELF 0.00000000 Waves

{ "type": 13, "id": "5hYXzNHpujRezK3uX59EtuPTNcfmz1g94C1gPvpVR763", "fee": 3100000, "feeAssetId": null, "timestamp": 1673955453662, "version": 2, "chainId": 84, "sender": "3NDCyBG5q85JuaRiigUeEtainyjCQT3XpZm", "senderPublicKey": "EVooykMNV691Venwp1dHUTBd7KWequzUcda57Wd3LQEX", "proofs": [ "2FLHzysA4hsoWuUQtP5nqpaiEgyCQ2fzJzu4Dytp8VqorWmjX2SMkNNpCiah4PnTxrHM7WemKHkEbwJvbZdFMYYc" ], "script": "base64:BgJTCAISABIDCgEIEgASAwoBCBIECgIBCBIECgICAhIECgIBCBIECgIBARIECgIICBIECgICAhIECgICAhIDCgEIEgMKAQgSAwoBCBIDCgEYEgMKARhcAAVjaGFpbgkAsAkBCQDJAQIJAMoBAggFBHRoaXMFYnl0ZXMAAQABAAt1c2RuQXNzZXRJZAQHJG1hdGNoMAUFY2hhaW4DCQAAAgIBVwUHJG1hdGNoMAEgtiYpwwT1zlORpA5LdSQvZIxRsfrfr1QpvUjSHSqyqtEDCQAAAgIBVAUHJG1hdGNoMAEg93bq9/eDymXbbhPuAjvPWCmVqcHRjfJL2mzYHWKAyN4JAAIBAg1Vbmtub3duIGNoYWluAA1pbmN1YmF0b3JBZGRyBAckbWF0Y2gwBQVjaGFpbgMJAAACAgFXBQckbWF0Y2gwCQERQGV4dHJOYXRpdmUoMTA2MikBAiMzUEVrdFZ1eDJSaGNoU042M0RzRG80YjRtejRRcXpLU2VEdgMJAAACAgFUBQckbWF0Y2gwBQR0aGlzCQACAQINVW5rbm93biBjaGFpbgALYnJlZWRlckFkZHIEByRtYXRjaDAFBWNoYWluAwkAAAICAVcFByRtYXRjaDAJARFAZXh0ck5hdGl2ZSgxMDYyKQECIzNQRFZ1VTQ1SDdFaDVkbXROYm5STlJTdEd3VUxBN05ZNkhiAwkAAAICAVQFByRtYXRjaDAFBHRoaXMJAAIBAg1Vbmtub3duIGNoYWluAAtlY29ub215QWRkcgQHJG1hdGNoMAUFY2hhaW4DCQAAAgIBVwUHJG1hdGNoMAkBEUBleHRyTmF0aXZlKDEwNjIpAQIjM1Ayc2sxS25jU3hSYVpzOGI0Q1dHUHcyamt2dmF2NzR1NEQDCQAAAgIBVAUHJG1hdGNoMAkBEUBleHRyTmF0aXZlKDEwNjIpAQIjM044eTR3eFgzSkM0VGRyQ0pCWFgxNlNqV2Y2WDI1NmhyZXAJAAIBAg1Vbmtub3duIGNoYWluAANwdWIBIE9T4ho/VKjWnVJOEx1GJ1W9s1PzLHvJVFSw/0PBtBQoAAhIRUFMQ09TVACQTgAKTEFORFBSRUZJWAIETEFORAAKRFVDS1BSRUZJWAIERFVDSwAPREVGQVVMVExPQ0FUSU9OAg9BZnJpY2FfRl9BZnJpY2EABk5VTVJFUwAGAAVTU0laRQAZAAVNU0laRQBkAAVMU0laRQDhAQAGWExTSVpFAJADAAdYWExTSVpFAPEEAA9EQUlMWVJFU0JZUElFQ0UAgPjSAQAJREFZTUlMTElTAIC4mSkAEUZJVkVNSU5VVEVTTUlMTElTAOCnEgAQUkVTT1VSQ0VQUklDRU1JTgDV1gkAEUluZnJhVXBncmFkZUNvc3RTBAckbWF0Y2gwBQVjaGFpbgMJAAACAgFXBQckbWF0Y2gwAMbrwL8XAwkAAAICAVQFByRtYXRjaDAA8M2JHgkAAgECDVVua25vd24gY2hhaW4AFUluZnJhVXBncmFkZUNvc3RTVXNkbgQHJG1hdGNoMAUFY2hhaW4DCQAAAgIBVwUHJG1hdGNoMACAtIkTAwkAAAICAVQFByRtYXRjaDAAgLUYCQACAQINVW5rbm93biBjaGFpbgAMRVhQTUFURVJJQUxTBAckbWF0Y2gwBQVjaGFpbgMJAAACAgFXBQckbWF0Y2gwAMuA1bPLBAMJAAACAgFUBQckbWF0Y2gwAPGa8O8FCQACAQINVW5rbm93biBjaGFpbgAHRVhQVVNETgQHJG1hdGNoMAUFY2hhaW4DCQAAAgIBVwUHJG1hdGNoMACAlOvcAwMJAAACAgFUBQckbWF0Y2gwAICt4gQJAAIBAg1Vbmtub3duIGNoYWluAAVNVUxUNgDAhD0ABUZJVkVYCQC2AgEABQAHVFdFTlRZWAkAtgIBABQACFRXRU5UWTJYCQC2AgEJAGgCABQAFAAIVFdFTlRZM1gJALYCAQkAaAIJAGgCABQAFAAUAAhUV0VOVFk0WAkAtgIBCQBoAgkAaAIJAGgCABQAFAAUABQACFRXRU5UWTVYCQC2AgEJAGgCCQBoAgkAaAIJAGgCABQAFAAUABQAFAAIbWF0VHlwZXMJAMwIAgIERnVlbAkAzAgCAgVNZXRhbAkAzAgCAgVQbGFuawkAzAgCAgVHbGFzcwkAzAgCAgdQbGFzdGljCQDMCAICB1Byb3RlaW4FA25pbAAKY29udGluZW50cwkAzAgCAgRBc2lhCQDMCAICBkV1cm9wZQkAzAgCAghBbWVyaWNhcwkAzAgCAgdPY2VhbmlhCQDMCAICBkFmcmljYQUDbmlsAApBUlRQUkVTQUxFAgdQUkVTQUxFAA9QUkVTQUxFTlVNTEFORFMA9AMBEmtleU5leHRGcmVlTGFuZE51bQACC25leHRMYW5kTnVtARBrZXlMYW5kVG9Bc3NldElkAQdsYW5kTnVtCQCsAgICDGxhbmRUb0Fzc2V0XwUHbGFuZE51bQEKa2V5TmZ0TmFtZQIHbGFuZE51bQhsYW5kU2l6ZQkArAICCQCsAgIFCkxBTkRQUkVGSVgFB2xhbmROdW0FCGxhbmRTaXplARVrZXlMYW5kQXNzZXRJZFRvT3duZXIBB2Fzc2V0SWQJAKwCAgIJbmZ0T3duZXJfBQdhc3NldElkARBrZXlEdWNrSWRUb093bmVyAQdhc3NldElkCQCsAgICCmR1Y2tPd25lcl8FB2Fzc2V0SWQBFmtleVN0YWtlZFRpbWVCeUFzc2V0SWQBB2Fzc2V0SWQJAKwCAgILc3Rha2VkVGltZV8FB2Fzc2V0SWQBFmtleUluZnJhTGV2ZWxCeUFzc2V0SWQBB2Fzc2V0SWQJAKwCAgILaW5mcmFMZXZlbF8FB2Fzc2V0SWQBHmtleUluZnJhTGV2ZWxCeUFzc2V0SWRBbmRPd25lcgIHYXNzZXRJZAlvd25lckFkZHIJAKwCAgkArAICCQCsAgICHGluZnJhTGV2ZWxCeUFzc2V0SWRBbmRPd25lcl8FB2Fzc2V0SWQCAV8FCW93bmVyQWRkcgEfa2V5UHJlc2FsZUFydEFjdGl2YXRlZEJ5QXNzZXRJZAEHYXNzZXRJZAkArAICAhRwcmVzYWxlQXJ0QWN0aXZhdGVkXwUHYXNzZXRJZAEna2V5UHJlc2FsZUFydEFjdGl2YXRlZEJ5QXNzZXRJZEFuZE93bmVyAgdhc3NldElkCW93bmVyQWRkcgkArAICCQCsAgIJAKwCAgIlcHJlc2FsZUFydEFjdGl2YXRlZEJ5QXNzZXRJZEFuZE93bmVyXwUHYXNzZXRJZAIBXwUJb3duZXJBZGRyASBrZXlMYW5kQXJ0U3RhdHVzQnlUeXBlQW5kQXNzZXRJZAIEdHlwZQdhc3NldElkCQC5CQIJAMwIAgINbGFuZEFydFN0YXR1cwkAzAgCBQR0eXBlCQDMCAIFB2Fzc2V0SWQFA25pbAIBXwEla2V5TGFuZEFydFN0YXR1c0J5VHlwZUFzc2V0SWRBbmRPd25lcgMEdHlwZQdhc3NldElkCW93bmVyQWRkcgkAuQkCCQDMCAICImxhbmRBcnRTdGF0dXNCeVR5cGVBc3NldElkQW5kT3duZXIJAMwIAgUEdHlwZQkAzAgCBQdhc3NldElkCQDMCAIFCW93bmVyQWRkcgUDbmlsAgFfARRrZXlTdGFrZWREdWNrQnlPd25lcgEJb3duZXJBZGRyCQCsAgICEnN0YWtlZER1Y2tCeU93bmVyXwUJb3duZXJBZGRyASJrZXlTdGFrZWRUaW1lQnlUeXBlQXNzZXRJZEFuZE93bmVyAwduZnRUeXBlB2Fzc2V0SWQJb3duZXJBZGRyCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgIgc3Rha2VkVGltZUJ5VHlwZUFzc2V0SWRBbmRPd25lcl8FB25mdFR5cGUCAV8FB2Fzc2V0SWQCAV8FCW93bmVyQWRkcgERa2V5TGFuZE51bVRvT3duZXIBB2xhbmROdW0JAKwCAgIKbGFuZE93bmVyXwUHbGFuZE51bQERa2V5QmFja3BhY2tCeUR1Y2sBC2R1Y2tBc3NldElkCQCsAgICCWJhY2tQYWNrXwULZHVja0Fzc2V0SWQBD2tleUR1Y2tMb2NhdGlvbgELZHVja0Fzc2V0SWQJAKwCAgINZHVja0xvY2F0aW9uXwULZHVja0Fzc2V0SWQBDWtleUR1Y2tIZWFsdGgBC2R1Y2tBc3NldElkCQCsAgICC2R1Y2tIZWFsdGhfBQtkdWNrQXNzZXRJZAERa2V5UmVzUHJvcG9ydGlvbnMAAhNyZXNUeXBlc1Byb3BvcnRpb25zAApyZWNMYW5kTnVtAAAAC3JlY0xhbmRTaXplAAEAC3JlY1RlcnJhaW5zAAIADHJlY0NvbnRpbmVudAADAA9sb2NJZHhDb250aW5lbnQAAAAKbG9jSWR4VHlwZQABAAhsb2NJZHhJZAACAApicElkeExldmVsAAAACGJwSWR4UmVzAAEACGJwSWR4TWF0AAIACWJwSWR4UHJvZAADAQhhc1N0cmluZwEBdgQHJG1hdGNoMAUBdgMJAAECBQckbWF0Y2gwAgZTdHJpbmcEAXMFByRtYXRjaDAFAXMJAAIBAhhmYWlsIHRvIGNhc3QgaW50byBTdHJpbmcBEmdldE5lZWRlZE1hdGVyaWFscwEFdG90YWwEBXByb3BzCQC1CQIJAQV2YWx1ZQEJAKIIAQkBEWtleVJlc1Byb3BvcnRpb25zAAIBXwMJAQIhPQIJAJADAQUFcHJvcHMFBk5VTVJFUwkAAgECFldyb25nIHByb3BvcnRpb25zIGRhdGEEAXIJAMwIAgkBDXBhcnNlSW50VmFsdWUBCQCRAwIFBXByb3BzAAAJAMwIAgkBDXBhcnNlSW50VmFsdWUBCQCRAwIFBXByb3BzAAEJAMwIAgkBDXBhcnNlSW50VmFsdWUBCQCRAwIFBXByb3BzAAIJAMwIAgkBDXBhcnNlSW50VmFsdWUBCQCRAwIFBXByb3BzAAMJAMwIAgkBDXBhcnNlSW50VmFsdWUBCQCRAwIFBXByb3BzAAQJAMwIAgkBDXBhcnNlSW50VmFsdWUBCQCRAwIFBXByb3BzAAUFA25pbAQDc3VtCQBkAgkAZAIJAGQCCQBkAgkAZAIJAJEDAgUBcgAACQCRAwIFAXIAAQkAkQMCBQFyAAIJAJEDAgUBcgADCQCRAwIFAXIABAkAkQMCBQFyAAUDCQBnAgAABQNzdW0JAAIBAg9ObyBsYW5kcyBzdGFrZWQEBW5vcm02CQBrAwUFdG90YWwFBU1VTFQ2BQNzdW0KAQpub3JtYWxpemVyAgNhY2MEZWxlbQkAzQgCBQNhY2MJAGsDBQRlbGVtBQVub3JtNgUFTVVMVDYKAAIkbAUBcgoAAiRzCQCQAwEFAiRsCgAFJGFjYzAFA25pbAoBBSRmMF8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQEKbm9ybWFsaXplcgIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmMF8yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQITTGlzdCBzaXplIGV4Y2VlZHMgNgkBBSRmMF8yAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgUFJGFjYzAAAAABAAIAAwAEAAUABgERc3VidHJhY3RNYXRlcmlhbHMDDHNob3VsZFVzZU1hdANoYXMJdG90YWxOZWVkBARuZWVkCQESZ2V0TmVlZGVkTWF0ZXJpYWxzAQUJdG90YWxOZWVkCgEKc3VidHJhY3RvcgIDYWNjA2lkeAQGcmVzdWx0CQBlAgkBDXBhcnNlSW50VmFsdWUBCQCRAwIFA2hhcwUDaWR4CQCRAwIF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BW5ld0hQCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUCaHAAAQQKbG9jQW5kVGltZQkAtQkCCQCRAwIFBXBhcnRzAAECAToEDnRhcmdldExvY2F0aW9uCQC1CQIJAJEDAgUKbG9jQW5kVGltZQAAAgFfAwkBAiE9AgkAkQMCBQ50YXJnZXRMb2NhdGlvbgABAgFFCQACAQIrZXhwZWRpdGlvbiB0YXJnZXQgbG9jYXRpb24gdHlwZSBzaG91bGQgYmUgRQQEdGltZQkBDXBhcnNlSW50VmFsdWUBCQCRAwIFCmxvY0FuZFRpbWUAAQMDCQBmAgUEdGltZQkAZAIIBQlsYXN0QmxvY2sJdGltZXN0YW1wBRFGSVZFTUlOVVRFU01JTExJUwYJAGYCCQBlAggFCWxhc3RCbG9jawl0aW1lc3RhbXAFEUZJVkVNSU5VVEVTTUlMTElTBQR0aW1lCQACAQISc2lnbmF0dXJlIG91dGRhdGVkBAh1c2VyQWRkcgkApQgBBQZjYWxsZXIEC2R1Y2tBc3NldElkCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKIIAQkBFGtleVN0YWtlZER1Y2tCeU93bmVyAQUIdXNlckFkZHICHFlvdSBkb24ndCBoYXZlIGEgZHVjayBzdGFrZWQECWtleUhlYWx0aAkBDWtleUR1Y2tIZWFsdGgBBQtkdWNrQXNzZXRJZAQMb2xkRnJvbVN0YXRlCQELdmFsdWVPckVsc2UCCQCfCAEFCWtleUhlYWx0aABkAwkBAiE9AgUMb2xkRnJvbVN0YXRlBQVjdXJIUAkAAgEJAKwCAgkArAICCQCsAgICCm9sZEhlYWx0aD0JAKQDAQkBC3ZhbHVlT3JFbHNlAgkAnwgBBQlrZXlIZWFsdGgAZAIvIGZyb20gc3RhdGUgZG9lcyBub3QgbWF0Y2ggb25lIGZyb20gZmxpZ2h0IGxvZz0JAKQDAQUFY3VySFADCQBnAgAABQVjdXJIUAkAAgECHllvdSBjYW4ndCBmbHkgd2l0aCB6ZXJvIGhlYWx0aAMJAGcCAAAFBW5ld0hQCQCUCgIJAM0IAgMJAQEhAQUMc2hvdWxkVXNlTWF0CQDMCAIJAQ5TY3JpcHRUcmFuc2ZlcgMFBmNhbGxlcgUHRVhQVVNETgULdXNkbkFzc2V0SWQFA25pbAUDbmlsCQEMSW50ZWdlckVudHJ5AgUJa2V5SGVhbHRoAAACAAQFYnBLZXkJARFrZXlCYWNrcGFja0J5RHVjawEFC2R1Y2tBc3NldElkBAtjdXJyZW50UGFjawkBC2dldEJhY2twYWNrAQUFYnBLZXkEBW1MaXN0CQC1CQIJAJEDAgULY3VycmVudFBhY2sFCGJwSWR4TWF0AgFfBAZuZXdNYXQJALkJAgkBEXN1YnRyYWN0TWF0ZXJpYWxzAwUMc2hvdWxkVXNlTWF0BQVtTGlzdAUMRVhQTUFURVJJQUxTAgFfBAZiaWdOdW0JAQNhYnMBCQCeAwEFBHR4SWQEB2ZyZWVOdW0JAQt2YWx1ZU9yRWxzZQIJAJ8IAQkBEmtleU5leHRGcmVlTGFuZE51bQAJAGQCBQ9QUkVTQUxFTlVNTEFORFMAAQQHbGFuZE51bQkApAMBBQdmcmVlTnVtBAxjb250aW5lbnRJZHgJAKADAQkAuwICBQZiaWdOdW0FBUZJVkVYBAh0ZXJyYWlucwkBC2dlblRlcnJhaW5zAgUGYmlnTnVtBQxjb250aW5lbnRJZHgECWNvbnRpbmVudAkAkQMCBQpjb250aW5lbnRzBQxjb250aW5lbnRJZHgEBWlzc3VlCQDCCAUJAQprZXlOZnROYW1lAgUHbGFuZE51bQIBUwkAuQkCCQDMCAIFB2xhbmROdW0JAMwIAgIBUwkAzAgCBQh0ZXJyYWlucwkAzAgCBQljb250aW5lbnQFA25pbAIBXwABAAAHBAdhc3NldElkCQC4CAEFBWlzc3VlBAJpZAkA2AQBBQdhc3NldElkCQCUCgIJAMwIAgkBDEludGVnZXJFbnRyeQIJARJrZXlOZXh0RnJlZUxhbmROdW0ACQBkAgUHZnJlZU51bQABCQDMCAIFBWlzc3VlCQDMCAIJAQtTdHJpbmdFbnRyeQIJARBrZXlMYW5kVG9Bc3NldElkAQUHbGFuZE51bQUCaWQJAMwIAgkBC1N0cmluZ0VudHJ5AgkBFWtleUxhbmRBc3NldElkVG9Pd25lcgEFAmlkBQh1c2VyQWRkcgkAzAgCCQELU3RyaW5nRW50cnkCCQERa2V5TGFuZE51bVRvT3duZXIBBQdsYW5kTnVtBQh1c2VyQWRkcgkAzAgCCQEMSW50ZWdlckVudHJ5AgkBFmtleUluZnJhTGV2ZWxCeUFzc2V0SWQBBQJpZAAACQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEea2V5SW5mcmFMZXZlbEJ5QXNzZXRJZEFuZE93bmVyAgUCaWQFCHVzZXJBZGRyAAAJAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwUGY2FsbGVyAAEFB2Fzc2V0SWQJAMwIAgkBC1N0cmluZ0VudHJ5AgkBD2tleUR1Y2tMb2NhdGlvbgEFC2R1Y2tBc3NldElkCQC5CQIJAMwIAgUJY29udGluZW50CQDMCAICAUwJAMwIAgUCaWQFA25pbAIBXwkAzAgCCQEMSW50ZWdlckVudHJ5AgUJa2V5SGVhbHRoBQVuZXdIUAkAzAgCCQELU3RyaW5nRW50cnkCBQVicEtleQkAuQkCCQDMCAIJAJEDAgULY3VycmVudFBhY2sFCmJwSWR4TGV2ZWwJAMwIAgkAkQMCBQtjdXJyZW50UGFjawUIYnBJZHhSZXMJAMwIAgUGbmV3TWF0CQDMCAIJAJEDAgULY3VycmVudFBhY2sFCWJwSWR4UHJvZAUDbmlsAgE6BQNuaWwFAmlkAQxhcHBseUJvbnVzZXMCC2xhbmRBc3NldElkBnBpZWNlcwQKaW5mcmFMZXZlbAkBC3ZhbHVlT3JFbHNlAgkAnwgBCQEWa2V5SW5mcmFMZXZlbEJ5QXNzZXRJZAEFC2xhbmRBc3NldElkAAAECWFydFBpZWNlcwkBC3ZhbHVlT3JFbHNlAgkAnwgBCQEga2V5TGFuZEFydFN0YXR1c0J5VHlwZUFuZEFzc2V0SWQCBQpBUlRQUkVTQUxFBQtsYW5kQXNzZXRJZAMJAQt2YWx1ZU9yRWxzZQIJAKAIAQkBH2tleVByZXNhbGVBcnRBY3RpdmF0ZWRCeUFzc2V0SWQBBQtsYW5kQXNzZXRJZAcFBnBpZWNlcwAACQBkAgkAZAIFD0RBSUxZUkVTQllQSUVDRQkAawMFD0RBSUxZUkVTQllQSUVDRQUKaW5mcmFMZXZlbAAECQBrAwUPREFJTFlSRVNCWVBJRUNFCQBoAgUJYXJ0UGllY2VzAAMJAGgCBQZwaWVjZXMAFAEUY2hlY2tDbGFpbUNvbmRpdGlvbnMBBGFkZHIEC2R1Y2tBc3NldElkCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKIIAQkBFGtleVN0YWtlZER1Y2tCeU93bmVyAQUEYWRkcgIcWW91IGRvbid0IGhhdmUgYSBkdWNrIHN0YWtlZAQLY3VyTG9jYXRpb24JAQt2YWx1ZU9yRWxzZQIJAKIIAQkBD2tleUR1Y2tMb2NhdGlvbgEFC2R1Y2tBc3NldElkBQ9ERUZBVUxUTE9DQVRJT04EA2xvYwkAtQkCCQEFdmFsdWUBBQtjdXJMb2NhdGlvbgIBXwMJAQIhPQIJAJEDAgUDbG9jBQpsb2NJZHhUeXBlAgFMCQACAQkArAICCQCsAgICFkR1Y2sgbG9jYXRpb24gdHlwZSBpcyAJAJEDAgUDbG9jBQpsb2NJZHhUeXBlAhEsIGJ1dCBzaG91bGQgYmUgTAQLbGFuZEFzc2V0SWQJAJEDAgUDbG9jBQhsb2NJZHhJZAQFYXNzZXQJAQV2YWx1ZQEJAOwHAQkA2QQBBQtsYW5kQXNzZXRJZAQHdGltZUtleQkBFmtleVN0YWtlZFRpbWVCeUFzc2V0SWQBBQtsYW5kQXNzZXRJZAQJc2F2ZWRUaW1lCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAJ8IAQUHdGltZUtleQkArAICCQCsAgICEFlvdXIgZHVjayBpcyBvbiAIBQVhc3NldARuYW1lAhUsIHdoaWNoIGlzIG5vdCBzdGFrZWQEBW93bmVyCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKIIAQkBFWtleUxhbmRBc3NldElkVG9Pd25lcgEFC2xhbmRBc3NldElkCQCsAgIJAKwCAgIETkZUIAgFBWFzc2V0BG5hbWUCDCBpcyBvcnBoYW5lZAMJAQIhPQIFBW93bmVyBQRhZGRyCQACAQkArAICBQpMQU5EUFJFRklYAg0gaXMgbm90IHlvdXJzBAFkCQC1CQIIBQVhc3NldAtkZXNjcmlwdGlvbgIBXwkAlgoEBQtkdWNrQXNzZXRJZAULbGFuZEFzc2V0SWQFAWQFCXNhdmVkVGltZQEQY2xhaW1SZXNJbnRlcm5hbAIEYWRkcgZhbW91bnQDCQBmAgAABQZhbW91bnQJAAIBAg9OZWdhdGl2ZSBhbW91bnQEAWMJARRjaGVja0NsYWltQ29uZGl0aW9ucwEFBGFkZHIECGxhbmRTaXplCQCRAwIIBQFjAl8zBQtyZWNMYW5kU2l6ZQQNdGVycmFpbkNvdW50cwkBDWNvdW50VGVycmFpbnMBCQCRAwIIBQFjAl8zBQtyZWNUZXJyYWlucwQJZGVsdGFUaW1lCQBlAggFCWxhc3RCbG9jawl0aW1lc3RhbXAIBQFjAl80AwkAZgIAAAUJZGVsdGFUaW1lCQACAQkArAICCQCsAgIJAKwCAgImU2F2ZWQgdGltZXN0YW1wIGlzIGluIGZ1dHVyZSwgc2F2ZWQgPSAJAKQDAQgFAWMCXzQCDCwgY3VycmVudCA9IAkApAMBCAUJbGFzdEJsb2NrCXRpbWVzdGFtcAQGcGllY2VzCQEPbnVtUGllY2VzQnlTaXplAQUIbGFuZFNpemUEFmRhaWx5UHJvZHVjdGlvbkJ5UGllY2UJAQxhcHBseUJvbnVzZXMCCAUBYwJfMgUGcGllY2VzBAhhdmFpbFJlcwkAawMFCWRlbHRhVGltZQkAaAIFFmRhaWx5UHJvZHVjdGlvbkJ5UGllY2UFBnBpZWNlcwUJREFZTUlMTElTAwkAZgIFBmFtb3VudAUIYXZhaWxSZXMJAAIBCQCsAgIJAKwCAgkArAICAiJOb3QgZW5vdWdoIHJlc291cmNlcywgYXZhaWxhYmxlID0gCQCkAwEFCGF2YWlsUmVzAg4sIHJlcXVlc3RlZCA9IAkApAMBBQZhbW91bnQEDG5ld0RlbHRhVGltZQkAawMJAGUCBQhhdmFpbFJlcwUGYW1vdW50BQlEQVlNSUxMSVMJAGgCBRZkYWlseVByb2R1Y3Rpb25CeVBpZWNlBQZwaWVjZXMEDG5ld1RpbWVzdGFtcAkAZQIIBQlsYXN0QmxvY2sJdGltZXN0YW1wBQxuZXdEZWx0YVRpbWUEBWJwS2V5CQERa2V5QmFja3BhY2tCeUR1Y2sBCAUBYwJfMQQLY3VycmVudFBhY2sJAQtnZXRCYWNrcGFjawEFBWJwS2V5BApjdXJyZW50UmVzCQC1CQIJAJEDAgULY3VycmVudFBhY2sFCGJwSWR4UmVzAgFfBAVicFJlcwkBBmFkZFJlcwUFCmN1cnJlbnRSZXMFDXRlcnJhaW5Db3VudHMJAGUCBQlkZWx0YVRpbWUFDG5ld0RlbHRhVGltZQkAaQIFBnBpZWNlcwUFU1NJWkUFFmRhaWx5UHJvZHVjdGlvbkJ5UGllY2UJAJUKAwkAzAgCCQEMSW50ZWdlckVudHJ5AgkBFmtleVN0YWtlZFRpbWVCeUFzc2V0SWQBCAUBYwJfMgUMbmV3VGltZXN0YW1wCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEia2V5U3Rha2VkVGltZUJ5VHlwZUFzc2V0SWRBbmRPd25lcgMFCkxBTkRQUkVGSVgIBQFjAl8yBQRhZGRyBQxuZXdUaW1lc3RhbXAFA25pbAUFYnBLZXkJAMwIAgkAkQMCBQtjdXJyZW50UGFjawUKYnBJZHhMZXZlbAkAzAgCBQVicFJlcwkAzAgCCQCRAwIFC2N1cnJlbnRQYWNrBQhicElkeE1hdAkAzAgCCQCRAwIFC2N1cnJlbnRQYWNrBQlicElkeFByb2QFA25pbAEIY2xhaW1BbGwDBGFkZHILbGFuZEFzc2V0SWQGcGllY2VzBAd0aW1lS2V5CQEWa2V5U3Rha2VkVGltZUJ5QXNzZXRJZAEFC2xhbmRBc3NldElkBAlzYXZlZFRpbWUJAQV2YWx1ZQEJAJ8IAQUHdGltZUtleQQIYXZhaWxSZXMJAGgCCQBrAwkAZQIIBQlsYXN0QmxvY2sJdGltZXN0YW1wBQlzYXZlZFRpbWUJAQxhcHBseUJvbnVzZXMCBQtsYW5kQXNzZXRJZAUGcGllY2VzBQlEQVlNSUxMSVMFBnBpZWNlcwkBEGNsYWltUmVzSW50ZXJuYWwCBQRhZGRyBQhhdmFpbFJlcwENdXBJbmZyYUNvbW1vbgMMc2hvdWxkVXNlTWF0BmNhbGxlcg1wYXltZW50QW1vdW50BARhZGRyCQClCAEFBmNhbGxlcgQBYwkBFGNoZWNrQ2xhaW1Db25kaXRpb25zAQUEYWRkcgQGcGllY2VzCQEPbnVtUGllY2VzQnlTaXplAQkAkQMCCAUBYwJfMwULcmVjTGFuZFNpemUECGluZnJhS2V5CQEWa2V5SW5mcmFMZXZlbEJ5QXNzZXRJZAEIBQFjAl8yBAhjdXJMZXZlbAkBC3ZhbHVlT3JFbHNlAgkAnwgBBQhpbmZyYUtleQAAAwkAZwIFCGN1ckxldmVsAAMJAAIBAiZDdXJyZW50bHkgbWF4IGluZnJhc3RydWN0dXJlIGxldmVsID0gMwQIbmV3TGV2ZWwJAGQCBQhjdXJMZXZlbAABBARjb3N0CQBrAwUVSW5mcmFVcGdyYWRlQ29zdFNVc2RuCQBoAgUGcGllY2VzBQhuZXdMZXZlbAUFU1NJWkUDAwkBASEBBQxzaG91bGRVc2VNYXQJAQIhPQIFDXBheW1lbnRBbW91bnQFBGNvc3QHCQACAQkArAICAhtQYXltZW50IGF0dGFjaGVkIHNob3VsZCBiZSAJAKQDAQUEY29zdAQFYnBLZXkJARFrZXlCYWNrcGFja0J5RHVjawEIBQFjAl8xBAtjdXJyZW50UGFjawkBC2dldEJhY2twYWNrAQUFYnBLZXkEBW1MaXN0CQC1CQIJAJEDAgULY3VycmVudFBhY2sFCGJwSWR4TWF0AgFfBAZuZXdNYXQJALkJAgkBEXN1YnRyYWN0TWF0ZXJpYWxzAwUMc2hvdWxkVXNlTWF0BQVtTGlzdAkAawMFEUluZnJhVXBncmFkZUNvc3RTCQBoAgUGcGllY2VzBQhuZXdMZXZlbAUFU1NJWkUCAV8EC2NsYWltUmVzdWx0CQEIY2xhaW1BbGwDBQRhZGRyCAUBYwJfMgUGcGllY2VzCQCUCgIJAM4IAgkAzAgCCQEMSW50ZWdlckVudHJ5AgUIaW5mcmFLZXkFCG5ld0xldmVsCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEea2V5SW5mcmFMZXZlbEJ5QXNzZXRJZEFuZE93bmVyAggFAWMCXzIFBGFkZHIFCG5ld0xldmVsCQDMCAIJAQtTdHJpbmdFbnRyeQIFBWJwS2V5CQC5CQIJAMwIAgkAkQMCBQtjdXJyZW50UGFjawUKYnBJZHhMZXZlbAkAzAgCCQCRAwIIBQtjbGFpbVJlc3VsdAJfMwUIYnBJZHhSZXMJAMwIAgUGbmV3TWF0CQDMCAIJAJEDAgULY3VycmVudFBhY2sFCWJwSWR4UHJvZAUDbmlsAgE6BQNuaWwIBQtjbGFpbVJlc3VsdAJfMQUIbmV3TGV2ZWwBEmFjdGl2YXRlUHJlc2FsZUFydAEEYWRkcgQBYwkBFGNoZWNrQ2xhaW1Db25kaXRpb25zAQUEYWRkcgQLbGFuZEFzc2V0SWQIBQFjAl8yBA1hY3RpdmF0aW9uS2V5CQEfa2V5UHJlc2FsZUFydEFjdGl2YXRlZEJ5QXNzZXRJZAEFC2xhbmRBc3NldElkAwkBC3ZhbHVlT3JFbHNlAgkAoAgBBQ1hY3RpdmF0aW9uS2V5BwkAAgECJVByZXNhbGUgYXJ0aWZhY3QgaXMgYWxyZWFkeSBhY3RpdmF0ZWQDCQBmAgkBDXBhcnNlSW50VmFsdWUBCQCRAwIIBQFjAl8zBQpyZWNMYW5kTnVtBQ9QUkVTQUxFTlVNTEFORFMJAAIBCQCsAgIJAKwCAgkArAICBQpMQU5EUFJFRklYAgEgBQtsYW5kQXNzZXRJZAIlIGlzIG5vdCBlbGlnaWJsZSBmb3IgcHJlc2FsZSBhcnRpZmFjdAQGcGllY2VzCQEPbnVtUGllY2VzQnlTaXplAQkAkQMCCAUBYwJfMwULcmVjTGFuZFNpemUEC2NsYWltUmVzdWx0CQEIY2xhaW1BbGwDBQRhZGRyBQtsYW5kQXNzZXRJZAUGcGllY2VzCQDNCAIJAM0IAgkAzQgCCQDNCAIJAM0IAggFC2NsYWltUmVzdWx0Al8xCQEMQm9vbGVhbkVudHJ5AgUNYWN0aXZhdGlvbktleQYJAQxCb29sZWFuRW50cnkCCQEna2V5UHJlc2FsZUFydEFjdGl2YXRlZEJ5QXNzZXRJZEFuZE93bmVyAgULbGFuZEFzc2V0SWQFBGFkZHIGCQEMSW50ZWdlckVudHJ5AgkBIGtleUxhbmRBcnRTdGF0dXNCeVR5cGVBbmRBc3NldElkAgUKQVJUUFJFU0FMRQULbGFuZEFzc2V0SWQFBnBpZWNlcwkBDEludGVnZXJFbnRyeQIJASVrZXlMYW5kQXJ0U3RhdHVzQnlUeXBlQXNzZXRJZEFuZE93bmVyAwUKQVJUUFJFU0FMRQULbGFuZEFzc2V0SWQFBGFkZHIFBnBpZWNlcwkBC1N0cmluZ0VudHJ5AggFC2NsYWltUmVzdWx0Al8yCQC5CQIIBQtjbGFpbVJlc3VsdAJfMwIBOgENbWVyZ2VJbnRlcm5hbAcLbmV3TGFuZFNpemUIbmV3TGV2ZWwHZm9ybXVsYQRhZGRyDGxhbmRBc3NldElkcwR0eElkB25lZWRNYXQEC2R1Y2tBc3NldElkCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKIIAQkBFGtleVN0YWtlZER1Y2tCeU93bmVyAQUEYWRkcgIcWW91IGRvbid0IGhhdmUgYSBkdWNrIHN0YWtlZAoBCmNoZWNrTWVyZ2UCA2FjYwtsYW5kQXNzZXRJZAQFYXNzZXQJAQV2YWx1ZQEJAOwHAQkA2QQBBQtsYW5kQXNzZXRJZAQHdGltZUtleQkBFmtleVN0YWtlZFRpbWVCeUFzc2V0SWQBBQtsYW5kQXNzZXRJZAQJc2F2ZWRUaW1lCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAJ8IAQUHdGltZUtleQkArAICCQCsAgICBE5GVCAIBQVhc3NldARuYW1lAg4gaXMgbm90IHN0YWtlZAQFb3duZXIJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAoggBCQEVa2V5TGFuZEFzc2V0SWRUb093bmVyAQULbGFuZEFzc2V0SWQJAKwCAgkArAICAgRORlQgCAUFYXNzZXQEbmFtZQIMIGlzIG9ycGhhbmVkAwkBAiE9AgUFb3duZXIFBGFkZHIJAAIBCQCsAgIFCkxBTkRQUkVGSVgCDSBpcyBub3QgeW91cnMEAWQJALUJAggFBWFzc2V0C2Rlc2NyaXB0aW9uAgFfBAljb250aW5lbnQJAJEDAgUBZAUMcmVjQ29udGluZW50AwMJAQIhPQIIBQNhY2MCXzMCAAkBAiE9AggFA2FjYwJfMwUJY29udGluZW50BwkAAgECLkxhbmRzIHNob3VsZCBiZSBvbiB0aGUgc2FtZSBjb250aW5lbnQgdG8gbWVyZ2UECGxhbmRTaXplCQCRAwIFAWQFC3JlY0xhbmRTaXplBAdzaXplc0luCAUDYWNjAl8xBAFpCQETdmFsdWVPckVycm9yTWVzc2FnZQIJALMJAgUHc2l6ZXNJbgUIbGFuZFNpemUCJ1lvdSBoYXZlbid0IHBhc3NlZCBhbGwgdGhlIGxhbmRzIG5lZWRlZAQIc2l6ZXNPdXQJAKwCAgkArwICBQdzaXplc0luBQFpCQCwAgIFB3NpemVzSW4JAGQCBQFpAAEEBnBpZWNlcwkBD251bVBpZWNlc0J5U2l6ZQEFCGxhbmRTaXplBARhcnRzCQBkAggFA2FjYwJfMgkBC3ZhbHVlT3JFbHNlAgkAnwgBCQEga2V5TGFuZEFydFN0YXR1c0J5VHlwZUFuZEFzc2V0SWQCBQpBUlRQUkVTQUxFBQtsYW5kQXNzZXRJZAMJAQt2YWx1ZU9yRWxzZQIJAKAIAQkBH2tleVByZXNhbGVBcnRBY3RpdmF0ZWRCeUFzc2V0SWQBBQtsYW5kQXNzZXRJZAcFBnBpZWNlcwAABAppbmZyYUxldmVsCQELdmFsdWVPckVsc2UCCQCfCAEJARZrZXlJbmZyYUxldmVsQnlBc3NldElkAQULbGFuZEFzc2V0SWQAAAQIcmVxTGV2ZWwEByRtYXRjaDAFCGxhbmRTaXplAwkAAAICAVMFByRtYXRjaDAAAwMJAAACAgFNBQckbWF0Y2gwAAQDCQAAAgIBTAUHJG1hdGNoMAAFAwkAAAICAlhMBQckbWF0Y2gwAAYJAAIBAhpPbmx5IFMsIE0sIEwsIFhMIGNhbiBtZXJnZQMJAQIhPQIFCmluZnJhTGV2ZWwFCHJlcUxldmVsCQACAQIiQWxsIGxhbmRzIHNob3VsZCBiZSBtYXhlZCB0byBtZXJnZQQHbGFuZE51bQkAkQMCBQFkBQpyZWNMYW5kTnVtBA10ZXJyYWluQ291bnRzCQENY291bnRUZXJyYWlucwEJAJEDAgUBZAULcmVjVGVycmFpbnMECWRlbHRhVGltZQkAZQIIBQlsYXN0QmxvY2sJdGltZXN0YW1wBQlzYXZlZFRpbWUDCQBmAgAABQlkZWx0YVRpbWUJAAIBCQCsAgIJAKwCAgkArAICAiZTYXZlZCB0aW1lc3RhbXAgaXMgaW4gZnV0dXJlLCBzYXZlZCA9IAkApAMBBQlzYXZlZFRpbWUCDCwgY3VycmVudCA9IAkApAMBCAUJbGFzdEJsb2NrCXRpbWVzdGFtcAQWZGFpbHlQcm9kdWN0aW9uQnlQaWVjZQkBDGFwcGx5Qm9udXNlcwIFC2xhbmRBc3NldElkBQZwaWVjZXMEBWJwUmVzCQEGYWRkUmVzBQkAtQkCCAUDYWNjAl80AgFfBQ10ZXJyYWluQ291bnRzBQlkZWx0YVRpbWUJAGkCBQZwaWVjZXMFBVNTSVpFBRZkYWlseVByb2R1Y3Rpb25CeVBpZWNlBAVwcm9wcwkBGXVwZGF0ZVByb3BvcnRpb25zSW50ZXJuYWwECQC1CQIIBQNhY2MCXzYCAV8FDXRlcnJhaW5Db3VudHMJAGkCBQZwaWVjZXMFBVNTSVpFAP///////////wEJAJgKBgUIc2l6ZXNPdXQFBGFydHMFCWNvbnRpbmVudAUFYnBSZXMJAM0IAgkAzQgCCQDNCAIJAM0IAgkAzQgCCQDNCAIJAM0IAgkAzQgCCQDNCAIJAM0IAgkAzQgCCQDNCAIJAM0IAggFA2FjYwJfNQkBC0RlbGV0ZUVudHJ5AQkBFmtleVN0YWtlZFRpbWVCeUFzc2V0SWQBBQtsYW5kQXNzZXRJZAkBC0RlbGV0ZUVudHJ5AQkBImtleVN0YWtlZFRpbWVCeVR5cGVBc3NldElkQW5kT3duZXIDBQpMQU5EUFJFRklYBQtsYW5kQXNzZXRJZAUEYWRkcgkBC0RlbGV0ZUVudHJ5AQkBEGtleUxhbmRUb0Fzc2V0SWQBBQdsYW5kTnVtCQELRGVsZXRlRW50cnkBCQEKa2V5TmZ0TmFtZQIFB2xhbmROdW0FCGxhbmRTaXplCQELRGVsZXRlRW50cnkBCQEVa2V5TGFuZEFzc2V0SWRUb093bmVyAQULbGFuZEFzc2V0SWQJAQtEZWxldGVFbnRyeQEJARZrZXlJbmZyYUxldmVsQnlBc3NldElkAQULbGFuZEFzc2V0SWQJAQtEZWxldGVFbnRyeQEJAR5rZXlJbmZyYUxldmVsQnlBc3NldElkQW5kT3duZXICBQtsYW5kQXNzZXRJZAUEYWRkcgkBC0RlbGV0ZUVudHJ5AQkBH2tleVByZXNhbGVBcnRBY3RpdmF0ZWRCeUFzc2V0SWQBBQtsYW5kQXNzZXRJZAkBC0RlbGV0ZUVudHJ5AQkBJ2tleVByZXNhbGVBcnRBY3RpdmF0ZWRCeUFzc2V0SWRBbmRPd25lcgIFC2xhbmRBc3NldElkBQRhZGRyCQELRGVsZXRlRW50cnkBCQEga2V5TGFuZEFydFN0YXR1c0J5VHlwZUFuZEFzc2V0SWQCBQpBUlRQUkVTQUxFBQtsYW5kQXNzZXRJZAkBC0RlbGV0ZUVudHJ5AQkBJWtleUxhbmRBcnRTdGF0dXNCeVR5cGVBc3NldElkQW5kT3duZXIDBQpBUlRQUkVTQUxFBQtsYW5kQXNzZXRJZAUEYWRkcgkBC0RlbGV0ZUVudHJ5AQkBEWtleUxhbmROdW1Ub093bmVyAQUHbGFuZE51bQkBBEJ1cm4CCQDZBAEFC2xhbmRBc3NldElkAAEFBXByb3BzBAVicEtleQkBEWtleUJhY2twYWNrQnlEdWNrAQULZHVja0Fzc2V0SWQEC2N1cnJlbnRQYWNrCQELZ2V0QmFja3BhY2sBBQVicEtleQQHcHJvcFN0cgkBC3ZhbHVlT3JFbHNlAgkAoggBCQERa2V5UmVzUHJvcG9ydGlvbnMAAgswXzBfMF8wXzBfMAQBcgoAAiRsBQxsYW5kQXNzZXRJZHMKAAIkcwkAkAMBBQIkbAoABSRhY2MwCQCYCgYFB2Zvcm11bGEAAAIACQCRAwIFC2N1cnJlbnRQYWNrBQhicElkeFJlcwUDbmlsBQdwcm9wU3RyCgEFJGYwXzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAQpjaGVja01lcmdlAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGYwXzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhNMaXN0IHNpemUgZXhjZWVkcyA0CQEFJGYwXzICCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECBQUkYWNjMAAAAAEAAgADAAQECWNvbnRpbmVudAgFAXICXzMEDGNvbnRpbmVudElkeAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQDPCAIFCmNvbnRpbmVudHMFCWNvbnRpbmVudAkArAICAhNVbmtub3duIGNvbnRpbmVudDogBQljb250aW5lbnQECHRlcnJhaW5zCQELZ2VuVGVycmFpbnMCCQEDYWJzAQkAngMBBQR0eElkBQxjb250aW5lbnRJZHgEB2ZyZWVOdW0JAQt2YWx1ZU9yRWxzZQIJAJ8IAQkBEmtleU5leHRGcmVlTGFuZE51bQAJAGQCBQ9QUkVTQUxFTlVNTEFORFMAAQQKbmV3TGFuZE51bQkApAMBBQdmcmVlTnVtBAVpc3N1ZQkAwggFCQEKa2V5TmZ0TmFtZQIFCm5ld0xhbmROdW0FC25ld0xhbmRTaXplCQC5CQIJAMwIAgUKbmV3TGFuZE51bQkAzAgCBQtuZXdMYW5kU2l6ZQkAzAgCBQh0ZXJyYWlucwkAzAgCBQljb250aW5lbnQFA25pbAIBXwABAAAHBAdhc3NldElkCQC4CAEFBWlzc3VlBA5uZXdMYW5kQXNzZXRJZAkA2AQBBQdhc3NldElkBAZuZXdNYXQJALkJAgkBEXN1YnRyYWN0TWF0ZXJpYWxzAwkAZgIFB25lZWRNYXQAAAkAtQkCCQCRAwIFC2N1cnJlbnRQYWNrBQhicElkeE1hdAIBXwUHbmVlZE1hdAIBXwkAlAoCCQDNCAIJAM0IAgkAzQgCCQDNCAIJAM0IAgkAzQgCCQDNCAIJAM0IAgkAzQgCCQDNCAIJAM0IAgkAzQgCCQDNCAIIBQFyAl81CQEMSW50ZWdlckVudHJ5AgkBEmtleU5leHRGcmVlTGFuZE51bQAJAGQCBQdmcmVlTnVtAAEFBWlzc3VlCQELU3RyaW5nRW50cnkCCQEQa2V5TGFuZFRvQXNzZXRJZAEFCm5ld0xhbmROdW0FDm5ld0xhbmRBc3NldElkCQELU3RyaW5nRW50cnkCCQEVa2V5TGFuZEFzc2V0SWRUb093bmVyAQUObmV3TGFuZEFzc2V0SWQFBGFkZHIJAQtTdHJpbmdFbnRyeQIJARFrZXlMYW5kTnVtVG9Pd25lcgEFCm5ld0xhbmROdW0FBGFkZHIJAQxJbnRlZ2VyRW50cnkCCQEga2V5TGFuZEFydFN0YXR1c0J5VHlwZUFuZEFzc2V0SWQCBQpBUlRQUkVTQUxFBQ5uZXdMYW5kQXNzZXRJZAgFAXICXzIJAQxJbnRlZ2VyRW50cnkCCQEla2V5TGFuZEFydFN0YXR1c0J5VHlwZUFzc2V0SWRBbmRPd25lcgMFCkFSVFBSRVNBTEUFDm5ld0xhbmRBc3NldElkBQRhZGRyCAUBcgJfMgkBDEludGVnZXJFbnRyeQIJARZrZXlJbmZyYUxldmVsQnlBc3NldElkAQUObmV3TGFuZEFzc2V0SWQFCG5ld0xldmVsCQEMSW50ZWdlckVudHJ5AgkBHmtleUluZnJhTGV2ZWxCeUFzc2V0SWRBbmRPd25lcgIFDm5ld0xhbmRBc3NldElkBQRhZGRyBQhuZXdMZXZlbAkBC1N0cmluZ0VudHJ5AgUFYnBLZXkJALkJAgkAzAgCCQCRAwIFC2N1cnJlbnRQYWNrBQpicElkeExldmVsCQDMCAIIBQFyAl80CQDMCAIFBm5ld01hdAkAzAgCCQCRAwIFC2N1cnJlbnRQYWNrBQlicElkeFByb2QFA25pbAIBOgkBC1N0cmluZ0VudHJ5AgkBEWtleVJlc1Byb3BvcnRpb25zAAgFAXICXzYJAQtTdHJpbmdFbnRyeQIJAQ9rZXlEdWNrTG9jYXRpb24BBQtkdWNrQXNzZXRJZAkAuQkCCQDMCAIFCWNvbnRpbmVudAkAzAgCAgFMCQDMCAIFDm5ld0xhbmRBc3NldElkBQNuaWwCAV8JAQ5TY3JpcHRUcmFuc2ZlcgMJARFAZXh0ck5hdGl2ZSgxMDYyKQEFBGFkZHIAAQUHYXNzZXRJZAUObmV3TGFuZEFzc2V0SWQBA3MybQMEYWRkcgxsYW5kQXNzZXRJZHMEdHhJZAkBDW1lcmdlSW50ZXJuYWwHAgFNAAMCBFNTU1MFBGFkZHIFDGxhbmRBc3NldElkcwUEdHhJZAAAAQNtMmwFBGFkZHIMbGFuZEFzc2V0SWRzBHR4SWQMc2hvdWxkVXNlTWF0DXBheW1lbnRBbW91bnQEBGNvc3QJAGgCBRVJbmZyYVVwZ3JhZGVDb3N0U1VzZG4ABAMDCQEBIQEFDHNob3VsZFVzZU1hdAkBAiE9AgUNcGF5bWVudEFtb3VudAUEY29zdAcJAAIBCQCsAgICG1BheW1lbnQgYXR0YWNoZWQgc2hvdWxkIGJlIAkApAMBBQRjb3N0CQENbWVyZ2VJbnRlcm5hbAcCAUwABAIDU01NBQRhZGRyBQxsYW5kQXNzZXRJZHMFBHR4SWQJAGgCBRFJbmZyYVVwZ3JhZGVDb3N0UwAEAQRsMnhsBQRhZGRyDGxhbmRBc3NldElkcwR0eElkDHNob3VsZFVzZU1hdA1wYXltZW50QW1vdW50BARjb3N0CQBoAgUVSW5mcmFVcGdyYWRlQ29zdFNVc2RuAC8DAwkBASEBBQxzaG91bGRVc2VNYXQJAQIhPQIFDXBheW1lbnRBbW91bnQFBGNvc3QHCQACAQkArAICAhtQYXltZW50IGF0dGFjaGVkIHNob3VsZCBiZSAJAKQDAQUEY29zdAkBDW1lcmdlSW50ZXJuYWwHAgJYTAAFAgVTU1NNTAUEYWRkcgUMbGFuZEFzc2V0SWRzBQR0eElkCQBoAgURSW5mcmFVcGdyYWRlQ29zdFMALwEGeGwyeHhsBQRhZGRyDGxhbmRBc3NldElkcwR0eElkDHNob3VsZFVzZU1hdA1wYXltZW50QW1vdW50BARjb3N0CQBoAgUVSW5mcmFVcGdyYWRlQ29zdFNVc2RuADYDAwkBASEBBQxzaG91bGRVc2VNYXQJAQIhPQIFDXBheW1lbnRBbW91bnQFBGNvc3QHCQACAQkArAICAhtQYXltZW50IGF0dGFjaGVkIHNob3VsZCBiZSAJAKQDAQUEY29zdAkBDW1lcmdlSW50ZXJuYWwHAgNYWEwABgIDTFhMBQRhZGRyBQxsYW5kQXNzZXRJZHMFBHR4SWQJAGgCBRFJbmZyYVVwZ3JhZGVDb3N0UwA2AQttZXJnZUNvbW1vbgUMc2hvdWxkVXNlTWF0BGFkZHINcGF5bWVudEFtb3VudAxsYW5kQXNzZXRJZHMEdHhJZAQLbWVyZ2VSZXN1bHQEByRtYXRjaDAJAJADAQUMbGFuZEFzc2V0SWRzAwkAAAIABAUHJG1hdGNoMAkBA3MybQMFBGFkZHIFDGxhbmRBc3NldElkcwUEdHhJZAMJAAACAAMFByRtYXRjaDAJAQNtMmwFBQRhZGRyBQxsYW5kQXNzZXRJZHMFBHR4SWQFDHNob3VsZFVzZU1hdAUNcGF5bWVudEFtb3VudAMJAAACAAUFByRtYXRjaDAJAQRsMnhsBQUEYWRkcgUMbGFuZEFzc2V0SWRzBQR0eElkBQxzaG91bGRVc2VNYXQFDXBheW1lbnRBbW91bnQDCQAAAgACBQckbWF0Y2gwCQEGeGwyeHhsBQUEYWRkcgUMbGFuZEFzc2V0SWRzBQR0eElkBQxzaG91bGRVc2VNYXQFDXBheW1lbnRBbW91bnQJAAIBAg1Vbmtub3duIG1lcmdlBQttZXJnZVJlc3VsdBABaQEJc3Rha2VMYW5kAAMJAQIhPQIJAJADAQgFAWkIcGF5bWVudHMAAQkAAgECHEV4YWN0bHkgb25lIHBheW1lbnQgcmVxdWlyZWQEA3BtdAkBBXZhbHVlAQkAkQMCCAUBaQhwYXltZW50cwAABAdhc3NldElkCQEFdmFsdWUBCAUDcG10B2Fzc2V0SWQEB2FkZHJlc3MJAKUIAQgFAWkGY2FsbGVyAwkBAiE9AggFA3BtdAZhbW91bnQAAQkAAgEJAKwCAgkArAICAgRORlQgBQpMQU5EUFJFRklYAiQgdG9rZW4gc2hvdWxkIGJlIGF0dGFjaGVkIGFzIHBheW1lbnQEBWFzc2V0CQEFdmFsdWUBCQDsBwEFB2Fzc2V0SWQDCQECIT0CCAUFYXNzZXQGaXNzdWVyBQR0aGlzCQACAQIXVW5rbm93biBpc3N1ZXIgb2YgdG9rZW4DCQEBIQEJAQhjb250YWlucwIIBQVhc3NldARuYW1lBQpMQU5EUFJFRklYCQACAQkArAICCQCsAgICCU9ubHkgTkZUIAUKTEFORFBSRUZJWAIUIHRva2VucyBhcmUgYWNjZXB0ZWQEC2xhbmROdW1TaXplCQCwAgIIBQVhc3NldARuYW1lAAQEB2xhbmROdW0DCQEIY29udGFpbnMCBQtsYW5kTnVtU2l6ZQIDWFhMCQCzAgIFC2xhbmROdW1TaXplAAMDCQEIY29udGFpbnMCBQtsYW5kTnVtU2l6ZQICWEwJALMCAgULbGFuZE51bVNpemUAAgkAswICBQtsYW5kTnVtU2l6ZQABAwkBASEBCQEJaXNEZWZpbmVkAQkAtgkBBQdsYW5kTnVtCQACAQkArAICAh5DYW5ub3QgcGFyc2UgbGFuZCBudW1iZXIgZnJvbSAIBQVhc3NldARuYW1lBAtsYW5kQXNzZXRJZAkA2AQBBQdhc3NldElkBAd0aW1lS2V5CQEWa2V5U3Rha2VkVGltZUJ5QXNzZXRJZAEFC2xhbmRBc3NldElkAwkBCWlzRGVmaW5lZAEJAJ8IAQUHdGltZUtleQkAAgEJAKwCAgkArAICAgRORlQgCAUFYXNzZXQEbmFtZQISIGlzIGFscmVhZHkgc3Rha2VkBAFkCQC1CQIIBQVhc3NldAtkZXNjcmlwdGlvbgIBXwQNdGVycmFpbkNvdW50cwkBDWNvdW50VGVycmFpbnMBCQCRAwIFAWQFC3JlY1RlcnJhaW5zBAVwcm9wcwkBEXVwZGF0ZVByb3BvcnRpb25zAwUNdGVycmFpbkNvdW50cwkAaQIJAQ9udW1QaWVjZXNCeVNpemUBCQCRAwIFAWQFC3JlY0xhbmRTaXplBQVTU0laRQABCQDMCAIJAQxJbnRlZ2VyRW50cnkCBQd0aW1lS2V5CAUJbGFzdEJsb2NrCXRpbWVzdGFtcAkAzAgCCQEMSW50ZWdlckVudHJ5AgkBImtleVN0YWtlZFRpbWVCeVR5cGVBc3NldElkQW5kT3duZXIDBQpMQU5EUFJFRklYBQtsYW5kQXNzZXRJZAUHYWRkcmVzcwgFCWxhc3RCbG9jawl0aW1lc3RhbXAJAMwIAgkBC1N0cmluZ0VudHJ5AgkBFWtleUxhbmRBc3NldElkVG9Pd25lcgEFC2xhbmRBc3NldElkBQdhZGRyZXNzCQDMCAIJAQtTdHJpbmdFbnRyeQIJARFrZXlMYW5kTnVtVG9Pd25lcgEFB2xhbmROdW0FB2FkZHJlc3MJAMwIAgkBC1N0cmluZ0VudHJ5AgkBEWtleVJlc1Byb3BvcnRpb25zAAUFcHJvcHMFA25pbAFpAQt1bnN0YWtlTGFuZAEObGFuZEFzc2V0SWRTdHIDCQECIT0CCQCQAwEIBQFpCHBheW1lbnRzAAAJAAIBAiR1bnN0YWtlIGRvZXNuJ3QgcmVxdWlyZSBhbnkgcGF5bWVudHMEBGFkZHIJAKUIAQgFAWkGY2FsbGVyBAFjCQEUY2hlY2tDbGFpbUNvbmRpdGlvbnMBBQRhZGRyBA10ZXJyYWluQ291bnRzCQENY291bnRUZXJyYWlucwEJAJEDAggFAWMCXzMFC3JlY1RlcnJhaW5zBAZwaWVjZXMJAQ9udW1QaWVjZXNCeVNpemUBCQCRAwIIBQFjAl8zBQtyZWNMYW5kU2l6ZQQFcHJvcHMJARF1cGRhdGVQcm9wb3J0aW9ucwMFDXRlcnJhaW5Db3VudHMJAGkCBQZwaWVjZXMFBVNTSVpFAP///////////wEEC2NsYWltUmVzdWx0CQEIY2xhaW1BbGwDBQRhZGRyCAUBYwJfMgUGcGllY2VzCQDMCAIJAQ5TY3JpcHRUcmFuc2ZlcgMIBQFpBmNhbGxlcgABCQDZBAEIBQFjAl8yCQDMCAIJAQtEZWxldGVFbnRyeQEJARZrZXlTdGFrZWRUaW1lQnlBc3NldElkAQgFAWMCXzIJAMwIAgkBC0RlbGV0ZUVudHJ5AQkBImtleVN0YWtlZFRpbWVCeVR5cGVBc3NldElkQW5kT3duZXIDBQpMQU5EUFJFRklYCAUBYwJfMgUEYWRkcgkAzAgCCQELU3RyaW5nRW50cnkCCQERa2V5UmVzUHJvcG9ydGlvbnMABQVwcm9wcwkAzAgCCQELU3RyaW5nRW50cnkCCAULY2xhaW1SZXN1bHQCXzIJALkJAggFC2NsYWltUmVzdWx0Al8zAgE6BQNuaWwBaQEJc3Rha2VEdWNrAAMJAQIhPQIJAJADAQgFAWkIcGF5bWVudHMAAQkAAgECHEV4YWN0bHkgb25lIHBheW1lbnQgcmVxdWlyZWQEA3BtdAkBBXZhbHVlAQkAkQMCCAUBaQhwYXltZW50cwAABAdhc3NldElkCQEFdmFsdWUBCAUDcG10B2Fzc2V0SWQEB2FkZHJlc3MJAKUIAQgFAWkGY2FsbGVyAwkBAiE9AggFA3BtdAZhbW91bnQAAQkAAgEJAKwCAgkArAICAgRORlQgBQpEVUNLUFJFRklYAiQgdG9rZW4gc2hvdWxkIGJlIGF0dGFjaGVkIGFzIHBheW1lbnQEBWFzc2V0CQEFdmFsdWUBCQDsBwEFB2Fzc2V0SWQDAwkBAiE9AggFBWFzc2V0Bmlzc3VlcgUNaW5jdWJhdG9yQWRkcgkBAiE9AggFBWFzc2V0Bmlzc3VlcgULYnJlZWRlckFkZHIHCQACAQkArAICCQCsAgICElVua25vd24gaXNzdWVyIG9mIAUKRFVDS1BSRUZJWAIGIHRva2VuAwkBASEBCQEIY29udGFpbnMCCAUFYXNzZXQEbmFtZQUKRFVDS1BSRUZJWAkAAgEJAKwCAgkArAICAglPbmx5IE5GVCAFCkRVQ0tQUkVGSVgCFCB0b2tlbnMgYXJlIGFjY2VwdGVkBAphc3NldElkU3RyCQDYBAEFB2Fzc2V0SWQEB3RpbWVLZXkJARZrZXlTdGFrZWRUaW1lQnlBc3NldElkAQUKYXNzZXRJZFN0cgMJAQlpc0RlZmluZWQBCQCfCAEFB3RpbWVLZXkJAAIBCQCsAgIJAKwCAgIETkZUIAgFBWFzc2V0BG5hbWUCEiBpcyBhbHJlYWR5IHN0YWtlZAMJAQlpc0RlZmluZWQBCQCiCAEJARRrZXlTdGFrZWREdWNrQnlPd25lcgEFB2FkZHJlc3MJAAIBCQCsAgICHVlvdSBhbHJlYWR5IHN0YWtlZCBvbmUgZHVjazogCAUFYXNzZXQEbmFtZQQGbG9jS2V5CQEPa2V5RHVja0xvY2F0aW9uAQUKYXNzZXRJZFN0cgQIbG9jYXRpb24JAKIIAQUGbG9jS2V5BAVicEtleQkBEWtleUJhY2twYWNrQnlEdWNrAQUKYXNzZXRJZFN0cgQIYmFja3BhY2sJAKIIAQUFYnBLZXkJAM4IAgkAzAgCCQEMSW50ZWdlckVudHJ5AgUHdGltZUtleQgFCWxhc3RCbG9jawl0aW1lc3RhbXAJAMwIAgkBDEludGVnZXJFbnRyeQIJASJrZXlTdGFrZWRUaW1lQnlUeXBlQXNzZXRJZEFuZE93bmVyAwUKRFVDS1BSRUZJWAkA2AQBBQdhc3NldElkBQdhZGRyZXNzCAUJbGFzdEJsb2NrCXRpbWVzdGFtcAkAzAgCCQELU3RyaW5nRW50cnkCCQEQa2V5RHVja0lkVG9Pd25lcgEFCmFzc2V0SWRTdHIFB2FkZHJlc3MJAMwIAgkBC1N0cmluZ0VudHJ5AgkBFGtleVN0YWtlZER1Y2tCeU93bmVyAQUHYWRkcmVzcwUKYXNzZXRJZFN0cgUDbmlsAwkBCWlzRGVmaW5lZAEFCGxvY2F0aW9uBQNuaWwJAM4IAgkAzAgCCQELU3RyaW5nRW50cnkCBQZsb2NLZXkFD0RFRkFVTFRMT0NBVElPTgUDbmlsAwkBCWlzRGVmaW5lZAEFCGJhY2twYWNrBQNuaWwJAM0IAgkAzAgCCQELU3RyaW5nRW50cnkCBQVicEtleQIaMDowXzBfMF8wXzBfMDowXzBfMF8wXzBfMDoFA25pbAkBDEludGVnZXJFbnRyeQIJAQ1rZXlEdWNrSGVhbHRoAQUKYXNzZXRJZFN0cgBkAWkBC3Vuc3Rha2VEdWNrAQphc3NldElkU3RyAwkBAiE9AgkAkAMBCAUBaQhwYXltZW50cwAACQACAQIkdW5zdGFrZSBkb2Vzbid0IHJlcXVpcmUgYW55IHBheW1lbnRzBAdhc3NldElkCQDZBAEFCmFzc2V0SWRTdHIEB2FkZHJlc3MJAKUIAQgFAWkGY2FsbGVyBAVhc3NldAkBBXZhbHVlAQkA7AcBBQdhc3NldElkBAd0aW1lS2V5CQEWa2V5U3Rha2VkVGltZUJ5QXNzZXRJZAEJANgEAQUHYXNzZXRJZAMJAQEhAQkBCWlzRGVmaW5lZAEFB3RpbWVLZXkJAAIBCQCsAgIJAKwCAgIETkZUIAgFBWFzc2V0BG5hbWUCDiBpcyBub3Qgc3Rha2VkAwkBASEBCQEJaXNEZWZpbmVkAQkBFGtleVN0YWtlZER1Y2tCeU93bmVyAQUHYWRkcmVzcwkAAgEJAKwCAgkArAICAglUaGUgZHVjayAIBQVhc3NldARuYW1lAg4gaXMgbm90IHN0YWtlZAQFb3duZXIJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAoggBCQEQa2V5RHVja0lkVG9Pd25lcgEJANgEAQUHYXNzZXRJZAkArAICCQCsAgICBE5GVCAIBQVhc3NldARuYW1lAgwgaXMgb3JwaGFuZWQDCQECIT0CBQVvd25lcgUHYWRkcmVzcwkAAgECF1N0YWtlZCBORlQgaXMgbm90IHlvdXJzBAlrZXlIZWFsdGgJAQ1rZXlEdWNrSGVhbHRoAQUKYXNzZXRJZFN0cgQGaGVhbHRoCQCfCAEFCWtleUhlYWx0aAMJAQIhPQIFBmhlYWx0aABkCQACAQImUGxlYXNlIGhlYWwgeW91ciBkdWNrIGJlZm9yZSB1bnN0YWtpbmcJAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwgFAWkGY2FsbGVyAAEFB2Fzc2V0SWQJAMwIAgkBC0RlbGV0ZUVudHJ5AQUHdGltZUtleQkAzAgCCQELRGVsZXRlRW50cnkBBQlrZXlIZWFsdGgJAMwIAgkBC0RlbGV0ZUVudHJ5AQkBD2tleUR1Y2tMb2NhdGlvbgEFCmFzc2V0SWRTdHIJAMwIAgkBC0RlbGV0ZUVudHJ5AQkBEGtleUR1Y2tJZFRvT3duZXIBBQphc3NldElkU3RyCQDMCAIJAQtEZWxldGVFbnRyeQEJASJrZXlTdGFrZWRUaW1lQnlUeXBlQXNzZXRJZEFuZE93bmVyAwUKRFVDS1BSRUZJWAUKYXNzZXRJZFN0cgUHYWRkcmVzcwkAzAgCCQELRGVsZXRlRW50cnkBCQEUa2V5U3Rha2VkRHVja0J5T3duZXIBBQdhZGRyZXNzBQNuaWwBaQEIY2xhaW1SZXMCBmFtb3VudA5sYW5kQXNzZXRJZFN0cgMJAQIhPQIJAJADAQgFAWkIcGF5bWVudHMAAAkAAgECJWNsYWltUmVzIGRvZXNuJ3QgcmVxdWlyZSBhbnkgcGF5bWVudHMEBGFkZHIJAKUIAQgFAWkMb3JpZ2luQ2FsbGVyBAZyZXN1bHQJARBjbGFpbVJlc0ludGVybmFsAgUEYWRkcgUGYW1vdW50CQCUCgIJAM0IAggFBnJlc3VsdAJfMQkBC1N0cmluZ0VudHJ5AggFBnJlc3VsdAJfMgkAuQkCCAUGcmVzdWx0Al8zAgE6CQCRAwIIBQZyZXN1bHQCXzMFCGJwSWR4UmVzAWkBBmZsaWdodAIHbWVzc2FnZQNzaWcDCQEBIQEJAMQTAwUHbWVzc2FnZQUDc2lnBQNwdWIJAAIBAhhzaWduYXR1cmUgZG9lcyBub3QgbWF0Y2gDCQECIT0CCQCQAwEIBQFpCHBheW1lbnRzAAAJAAIBAiNmbGlnaHQgZG9lc24ndCByZXF1aXJlIGFueSBwYXltZW50cwQFcGFydHMJALUJAgkAsAkBBQdtZXNzYWdlAgE7BAJocAkAtQkCCQCRAwIJALUJAgkAkQMCBQVwYXJ0cwAAAgF8AAACAV8EBWN1ckhQCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUCaHAAAAQFbmV3SFAJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQJocAABBA1uZXdMb2NBbmRUaW1lCQC1CQIJAJEDAgUFcGFydHMAAQIBOgQLbmV3TG9jYXRpb24JAJEDAgUNbmV3TG9jQW5kVGltZQAABAR0aW1lCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUNbmV3TG9jQW5kVGltZQABAwMJAGYCBQR0aW1lCQBkAggFCWxhc3RCbG9jawl0aW1lc3RhbXAFEUZJVkVNSU5VVEVTTUlMTElTBgkAZgIJAGUCCAUJbGFzdEJsb2NrCXRpbWVzdGFtcAURRklWRU1JTlVURVNNSUxMSVMFBHRpbWUJAAIBAhJzaWduYXR1cmUgb3V0ZGF0ZWQEC2R1Y2tBc3NldElkCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKIIAQkBFGtleVN0YWtlZER1Y2tCeU93bmVyAQkApQgBCAUBaQZjYWxsZXICHFlvdSBkb24ndCBoYXZlIGEgZHVjayBzdGFrZWQECWtleUhlYWx0aAkBDWtleUR1Y2tIZWFsdGgBBQtkdWNrQXNzZXRJZAQMb2xkRnJvbVN0YXRlCQELdmFsdWVPckVsc2UCCQCfCAEFCWtleUhlYWx0aABkAwkBAiE9AgUMb2xkRnJvbVN0YXRlBQVjdXJIUAkAAgEJAKwCAgkArAICCQCsAgICCm9sZEhlYWx0aD0JAKQDAQkBC3ZhbHVlT3JFbHNlAgkAnwgBBQlrZXlIZWFsdGgAZAIvIGZyb20gc3RhdGUgZG9lcyBub3QgbWF0Y2ggb25lIGZyb20gZmxpZ2h0IGxvZz0JAKQDAQUFY3VySFADCQBnAgAABQVjdXJIUAkAAgECHllvdSBjYW4ndCBmbHkgd2l0aCB6ZXJvIGhlYWx0aAQGbG9jS2V5CQEPa2V5RHVja0xvY2F0aW9uAQULZHVja0Fzc2V0SWQEC2N1ckxvY2F0aW9uCQELdmFsdWVPckVsc2UCCQCiCAEFBmxvY0tleQUPREVGQVVMVExPQ0FUSU9OAwkAAAIFC25ld0xvY2F0aW9uBQtjdXJMb2NhdGlvbgkAAgECIllvdSBjYW4ndCBmbHkgdG8gdGhlIHNhbWUgbG9jYXRpb24JAJQKAgkAzAgCCQELU3RyaW5nRW50cnkCBQZsb2NLZXkDCQBmAgUFbmV3SFAAAAULbmV3TG9jYXRpb24FC2N1ckxvY2F0aW9uCQDMCAIJAQxJbnRlZ2VyRW50cnkCBQlrZXlIZWFsdGgFBW5ld0hQBQNuaWwFBHVuaXQBaQEJc2V0SGVhbHRoAgZoZWFsdGgLZHVja0Fzc2V0SWQDAwkAZgIAAAUGaGVhbHRoBgkAZgIFBmhlYWx0aABkCQACAQIaSFAgc2hvdWxkIGJlIHdpdGhpbiAwLi4xMDAJAMwIAgkBDEludGVnZXJFbnRyeQIJAQ1rZXlEdWNrSGVhbHRoAQULZHVja0Fzc2V0SWQFBmhlYWx0aAUDbmlsAWkBBGhlYWwCB21hdFR5cGUGYW1vdW50AwMJAGYCAAAFB21hdFR5cGUGCQBnAgUHbWF0VHlwZQUGTlVNUkVTCQACAQkArAICAhJVbmtub3duIG1hdGVyaWFsOiAJAKQDAQUHbWF0VHlwZQMJAGcCAAAFBmFtb3VudAkAAgEJAKwCAgIbQW1vdW50IHNob3VsZCBiZSBwb3NpdGl2ZSEgCQCkAwEFBmFtb3VudAQLZHVja0Fzc2V0SWQJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAoggBCQEUa2V5U3Rha2VkRHVja0J5T3duZXIBCQClCAEIBQFpBmNhbGxlcgIcWW91IGRvbid0IGhhdmUgYSBkdWNrIHN0YWtlZAQJa2V5SGVhbHRoCQENa2V5RHVja0hlYWx0aAEFC2R1Y2tBc3NldElkBAlvbGRIZWFsdGgJAQt2YWx1ZU9yRWxzZQIJAJ8IAQUJa2V5SGVhbHRoAGQDCQBnAgUJb2xkSGVhbHRoAGQJAAIBAhpIUCBzaG91bGQgYmUgPCAxMDAgdG8gaGVhbAQFYnBLZXkJARFrZXlCYWNrcGFja0J5RHVjawEFC2R1Y2tBc3NldElkBAtjdXJyZW50UGFjawkBC2dldEJhY2twYWNrAQUFYnBLZXkEBW1MaXN0CQC1CQIJAJEDAgULY3VycmVudFBhY2sFCGJwSWR4TWF0AgFfBA1jdXJyZW50QW1vdW50CQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUFbUxpc3QFB21hdFR5cGUEC2RlbHRhSGVhbHRoCQCXAwEJAMwIAgkAaQIFBmFtb3VudAUISEVBTENPU1QJAMwIAgkAZQIAZAUJb2xkSGVhbHRoBQNuaWwEC3NwZW5kQW1vdW50CQBoAgULZGVsdGFIZWFsdGgFCEhFQUxDT1NUAwkAZgIFC3NwZW5kQW1vdW50BQ1jdXJyZW50QW1vdW50CQACAQkArAICCQCsAgIJAKwCAgkArAICCQCsAgICCVlvdSBuZWVkIAkApAMBBQtzcGVuZEFtb3VudAIEIG9mIAkAkQMCBQhtYXRUeXBlcwUHbWF0VHlwZQIkIHRvIGhlYWwsIGJ1dCB5b3UgYmFja3BhY2sgY29udGFpbnMgCQCkAwEFDWN1cnJlbnRBbW91bnQEBm5ld01hdAkBDHN1Yk9uZUluTGlzdAMFBW1MaXN0BQdtYXRUeXBlBQtzcGVuZEFtb3VudAkAzAgCCQEMSW50ZWdlckVudHJ5AgUJa2V5SGVhbHRoCQBkAgUJb2xkSGVhbHRoBQtkZWx0YUhlYWx0aAkAzAgCCQELU3RyaW5nRW50cnkCBQVicEtleQkAuQkCCQDMCAIJAJEDAgULY3VycmVudFBhY2sFCmJwSWR4TGV2ZWwJAMwIAgkAkQMCBQtjdXJyZW50UGFjawUIYnBJZHhSZXMJAMwIAgUGbmV3TWF0CQDMCAIJAJEDAgULY3VycmVudFBhY2sFCWJwSWR4UHJvZAUDbmlsAgE6BQNuaWwBaQEOdXBkYXRlQmFja3BhY2sCC2R1Y2tBc3NldElkB25ld1BhY2sDCQECIT0CCAUBaQZjYWxsZXIFC2Vjb25vbXlBZGRyCQACAQIRcGVybWlzc2lvbiBkZW5pZWQJAJQKAgkAzAgCCQELU3RyaW5nRW50cnkCCQERa2V5QmFja3BhY2tCeUR1Y2sBBQtkdWNrQXNzZXRJZAUHbmV3UGFjawUDbmlsBQduZXdQYWNrAWkBDWV4cGVkaXRpb25CdXkCB21lc3NhZ2UDc2lnAwkBAiE9AgkAkAMBCAUBaQhwYXltZW50cwABCQACAQIcRXhhY3RseSBvbmUgcGF5bWVudCByZXF1aXJlZAQDcG10CQEFdmFsdWUBCQCRAwIIBQFpCHBheW1lbnRzAAADCQECIT0CCAUDcG10B2Fzc2V0SWQFC3VzZG5Bc3NldElkCQACAQIaQWxsb3dlZCBVU0ROIHBheW1lbnQgb25seSEDCQECIT0CCAUDcG10BmFtb3VudAUHRVhQVVNETgkAAgEJAKwCAgIbUGF5bWVudCBhdHRhY2hlZCBzaG91bGQgYmUgCQCkAwEFB0VYUFVTRE4EBnJlc3VsdAkBEGV4cGVkaXRpb25Db21tb24FBwgFAWkGY2FsbGVyCAUBaQ10cmFuc2FjdGlvbklkBQdtZXNzYWdlBQNzaWcDCQAAAggFBnJlc3VsdAJfMgIABQZyZXN1bHQJAJQKAgkAzQgCCAUGcmVzdWx0Al8xCQEOU2NyaXB0VHJhbnNmZXIDBQtlY29ub215QWRkcggFA3BtdAZhbW91bnQFC3VzZG5Bc3NldElkCAUGcmVzdWx0Al8yAWkBCmV4cGVkaXRpb24CB21lc3NhZ2UDc2lnAwkBAiE9AgkAkAMBCAUBaQhwYXltZW50cwAACQACAQInZXhwZWRpdGlvbiBkb2Vzbid0IHJlcXVpcmUgYW55IHBheW1lbnRzCQEQZXhwZWRpdGlvbkNvbW1vbgUGCAUBaQZjYWxsZXIIBQFpDXRyYW5zYWN0aW9uSWQFB21lc3NhZ2UFA3NpZwFpAQx1cGdyYWRlSW5mcmEBEmxhbmRBc3NldElkSWdub3JlZAMJAQIhPQIJAJADAQgFAWkIcGF5bWVudHMAAAkAAgECM0luZnJhc3RydWN0dXJlIHVwZ3JhZGUgZG9lc24ndCByZXF1aXJlIGFueSBwYXltZW50cwkBDXVwSW5mcmFDb21tb24DBggFAWkGY2FsbGVyAAABaQEQdXBncmFkZUluZnJhVXNkbgESbGFuZEFzc2V0SWRJZ25vcmVkAwkBAiE9AgkAkAMBCAUBaQhwYXltZW50cwABCQACAQIcRXhhY3RseSBvbmUgcGF5bWVudCByZXF1aXJlZAQDcG10CQEFdmFsdWUBCQCRAwIIBQFpCHBheW1lbnRzAAADCQECIT0CCAUDcG10B2Fzc2V0SWQFC3VzZG5Bc3NldElkCQACAQIaQWxsb3dlZCBVU0ROIHBheW1lbnQgb25seSEEBnJlc3VsdAkBDXVwSW5mcmFDb21tb24DBwgFAWkGY2FsbGVyCAUDcG10BmFtb3VudAkAlAoCCQDNCAIIBQZyZXN1bHQCXzEJAQ5TY3JpcHRUcmFuc2ZlcgMFC2Vjb25vbXlBZGRyCAUDcG10BmFtb3VudAULdXNkbkFzc2V0SWQIBQZyZXN1bHQCXzIBaQEQYWN0aXZhdGVBcnRpZmFjdAEHYXJ0TmFtZQMJAQIhPQIJAJADAQgFAWkIcGF5bWVudHMAAAkAAgECMEFydGlmYWN0IGFjdGl2YXRpb24gZG9lc24ndCByZXF1aXJlIGFueSBwYXltZW50cwQGcmVzdWx0BAckbWF0Y2gwBQdhcnROYW1lAwkAAAICB1BSRVNBTEUFByRtYXRjaDAJARJhY3RpdmF0ZVByZXNhbGVBcnQBCQClCAEIBQFpBmNhbGxlcgkAAgECEFVua25vd24gYXJ0aWZhY3QFBnJlc3VsdAFpAQptZXJnZUxhbmRzAQxsYW5kQXNzZXRJZHMDCQECIT0CCQCQAwEIBQFpCHBheW1lbnRzAAAJAAIBAipMYW5kcyBtZXJnaW5nIGRvZXNuJ3QgcmVxdWlyZSBhbnkgcGF5bWVudHMJAQttZXJnZUNvbW1vbgUGCQClCAEIBQFpBmNhbGxlcgAABQxsYW5kQXNzZXRJZHMIBQFpDXRyYW5zYWN0aW9uSWQBaQEObWVyZ2VMYW5kc1VzZG4BDGxhbmRBc3NldElkcwMJAQIhPQIJAJADAQgFAWkIcGF5bWVudHMAAQkAAgECHEV4YWN0bHkgb25lIHBheW1lbnQgcmVxdWlyZWQEA3BtdAkBBXZhbHVlAQkAkQMCCAUBaQhwYXltZW50cwAAAwkBAiE9AggFA3BtdAdhc3NldElkBQt1c2RuQXNzZXRJZAkAAgECGkFsbG93ZWQgVVNETiBwYXltZW50IG9ubHkhBAZyZXN1bHQJAQttZXJnZUNvbW1vbgUHCQClCAEIBQFpBmNhbGxlcggFA3BtdAZhbW91bnQFDGxhbmRBc3NldElkcwgFAWkNdHJhbnNhY3Rpb25JZAkAlAoCCQDNCAIIBQZyZXN1bHQCXzEJAQ5TY3JpcHRUcmFuc2ZlcgMFC2Vjb25vbXlBZGRyCAUDcG10BmFtb3VudAULdXNkbkFzc2V0SWQIBQZyZXN1bHQCXzIAitoKeg==", "height": 2408879, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: CSj2Lang9fny8wCZJy3ynqzQ5f1sJkfxXAFwqzFjQX6v Next: 9Sd9fKnJy22Q6qdjKALnRW5DMrLQZSXSp1rnJeVj6gbc Diff:
OldNewDifferences
5050 let DEFAULTLOCATION = "Africa_F_Africa"
5151
5252 let NUMRES = 6
53+
54+let SSIZE = 25
55+
56+let MSIZE = 100
57+
58+let LSIZE = 225
59+
60+let XLSIZE = 400
61+
62+let XXLSIZE = 625
5363
5464 let DAILYRESBYPIECE = 3456000
5565
114124 let continents = ["Asia", "Europe", "Americas", "Oceania", "Africa"]
115125
116126 let ARTPRESALE = "PRESALE"
127+
128+let PRESALENUMLANDS = 500
117129
118130 func keyNextFreeLandNum () = "nextLandNum"
119131
300312 func numPiecesBySize (landSize) = match landSize {
301313 case _ =>
302314 if (("S" == $match0))
303- then 25
315+ then SSIZE
304316 else if (("M" == $match0))
305- then 100
317+ then MSIZE
306318 else if (("L" == $match0))
307- then 225
319+ then LSIZE
308320 else if (("XL" == $match0))
309- then 400
321+ then XLSIZE
310322 else if (("XXL" == $match0))
311- then 625
323+ then XXLSIZE
312324 else throw("Unknown land size")
313325 }
314326
452464 let mList = split(currentPack[bpIdxMat], "_")
453465 let newMat = makeString(subtractMaterials(shouldUseMat, mList, EXPMATERIALS), "_")
454466 let bigNum = abs(toBigInt(txId))
455- let freeNum = valueOrElse(getInteger(keyNextFreeLandNum()), 501)
467+ let freeNum = valueOrElse(getInteger(keyNextFreeLandNum()), (PRESALENUMLANDS + 1))
456468 let landNum = toString(freeNum)
457469 let continentIdx = toInt((bigNum % FIVEX))
458470 let terrains = genTerrains(bigNum, continentIdx)
486498 let landAssetId = loc[locIdxId]
487499 let asset = value(assetInfo(fromBase58String(landAssetId)))
488500 let timeKey = keyStakedTimeByAssetId(landAssetId)
489- let savedTime = valueOrErrorMessage(getInteger(timeKey), (("NFT " + asset.name) + " is not staked"))
501+ let savedTime = valueOrErrorMessage(getInteger(timeKey), (("Your duck is on " + asset.name) + ", which is not staked"))
490502 let owner = valueOrErrorMessage(getString(keyLandAssetIdToOwner(landAssetId)), (("NFT " + asset.name) + " is orphaned"))
491503 if ((owner != addr))
492504 then throw((LANDPREFIX + " is not yours"))
498510 }
499511
500512
501-func claimResInternal (addr,amount) = {
502- let c = checkClaimConditions(addr)
503- let landSize = c._3[recLandSize]
504- let terrainCounts = countTerrains(c._3[recTerrains])
505- let deltaTime = (lastBlock.timestamp - c._4)
506- if ((0 > deltaTime))
507- then throw(((("Saved timestamp is in future, saved = " + toString(c._4)) + ", current = ") + toString(lastBlock.timestamp)))
508- else {
509- let pieces = numPiecesBySize(landSize)
510- let dailyProductionByPiece = applyBonuses(c._2, pieces)
511- let availRes = fraction(deltaTime, (dailyProductionByPiece * pieces), DAYMILLIS)
512- if ((amount > availRes))
513- then throw(((("Not enough resources, available = " + toString(availRes)) + ", requested = ") + toString(amount)))
514- else {
515- let newDeltaTime = fraction((availRes - amount), DAYMILLIS, (dailyProductionByPiece * pieces))
516- let newTimestamp = (lastBlock.timestamp - newDeltaTime)
517- let bpKey = keyBackpackByDuck(c._1)
518- let currentPack = getBackpack(bpKey)
519- let currentRes = split(currentPack[bpIdxRes], "_")
520- let bpRes = addRes(currentRes, terrainCounts, (deltaTime - newDeltaTime), (pieces / 25), dailyProductionByPiece)
521- $Tuple3([IntegerEntry(keyStakedTimeByAssetId(c._2), newTimestamp), IntegerEntry(keyStakedTimeByTypeAssetIdAndOwner(LANDPREFIX, c._2, addr), newTimestamp)], bpKey, [currentPack[bpIdxLevel], bpRes, currentPack[bpIdxMat], currentPack[bpIdxProd]])
522- }
523- }
524- }
513+func claimResInternal (addr,amount) = if ((0 > amount))
514+ then throw("Negative amount")
515+ else {
516+ let c = checkClaimConditions(addr)
517+ let landSize = c._3[recLandSize]
518+ let terrainCounts = countTerrains(c._3[recTerrains])
519+ let deltaTime = (lastBlock.timestamp - c._4)
520+ if ((0 > deltaTime))
521+ then throw(((("Saved timestamp is in future, saved = " + toString(c._4)) + ", current = ") + toString(lastBlock.timestamp)))
522+ else {
523+ let pieces = numPiecesBySize(landSize)
524+ let dailyProductionByPiece = applyBonuses(c._2, pieces)
525+ let availRes = fraction(deltaTime, (dailyProductionByPiece * pieces), DAYMILLIS)
526+ if ((amount > availRes))
527+ then throw(((("Not enough resources, available = " + toString(availRes)) + ", requested = ") + toString(amount)))
528+ else {
529+ let newDeltaTime = fraction((availRes - amount), DAYMILLIS, (dailyProductionByPiece * pieces))
530+ let newTimestamp = (lastBlock.timestamp - newDeltaTime)
531+ let bpKey = keyBackpackByDuck(c._1)
532+ let currentPack = getBackpack(bpKey)
533+ let currentRes = split(currentPack[bpIdxRes], "_")
534+ let bpRes = addRes(currentRes, terrainCounts, (deltaTime - newDeltaTime), (pieces / SSIZE), dailyProductionByPiece)
535+ $Tuple3([IntegerEntry(keyStakedTimeByAssetId(c._2), newTimestamp), IntegerEntry(keyStakedTimeByTypeAssetIdAndOwner(LANDPREFIX, c._2, addr), newTimestamp)], bpKey, [currentPack[bpIdxLevel], bpRes, currentPack[bpIdxMat], currentPack[bpIdxProd]])
536+ }
537+ }
538+ }
525539
526540
527541 func claimAll (addr,landAssetId,pieces) = {
542556 then throw("Currently max infrastructure level = 3")
543557 else {
544558 let newLevel = (curLevel + 1)
545- let cost = fraction(InfraUpgradeCostSUsdn, (pieces * newLevel), 25)
559+ let cost = fraction(InfraUpgradeCostSUsdn, (pieces * newLevel), SSIZE)
546560 if (if (!(shouldUseMat))
547561 then (paymentAmount != cost)
548562 else false)
551565 let bpKey = keyBackpackByDuck(c._1)
552566 let currentPack = getBackpack(bpKey)
553567 let mList = split(currentPack[bpIdxMat], "_")
554- let newMat = makeString(subtractMaterials(shouldUseMat, mList, fraction(InfraUpgradeCostS, (pieces * newLevel), 25)), "_")
568+ let newMat = makeString(subtractMaterials(shouldUseMat, mList, fraction(InfraUpgradeCostS, (pieces * newLevel), SSIZE)), "_")
555569 let claimResult = claimAll(addr, c._2, pieces)
556570 $Tuple2(([IntegerEntry(infraKey, newLevel), IntegerEntry(keyInfraLevelByAssetIdAndOwner(c._2, addr), newLevel), StringEntry(bpKey, makeString([currentPack[bpIdxLevel], claimResult._3[bpIdxRes], newMat, currentPack[bpIdxProd]], ":"))] ++ claimResult._1), newLevel)
557571 }
565579 let activationKey = keyPresaleArtActivatedByAssetId(landAssetId)
566580 if (valueOrElse(getBoolean(activationKey), false))
567581 then throw("Presale artifact is already activated")
568- else if ((parseIntValue(c._3[recLandNum]) > 500))
582+ else if ((parseIntValue(c._3[recLandNum]) > PRESALENUMLANDS))
569583 then throw((((LANDPREFIX + " ") + landAssetId) + " is not eligible for presale artifact"))
570584 else {
571585 let pieces = numPiecesBySize(c._3[recLandSize])
623637 then throw(((("Saved timestamp is in future, saved = " + toString(savedTime)) + ", current = ") + toString(lastBlock.timestamp)))
624638 else {
625639 let dailyProductionByPiece = applyBonuses(landAssetId, pieces)
626- let bpRes = addRes(split(acc._4, "_"), terrainCounts, deltaTime, (pieces / 25), dailyProductionByPiece)
627- let props = updateProportionsInternal(split(acc._6, "_"), terrainCounts, (pieces / 25), -1)
640+ let bpRes = addRes(split(acc._4, "_"), terrainCounts, deltaTime, (pieces / SSIZE), dailyProductionByPiece)
641+ let props = updateProportionsInternal(split(acc._6, "_"), terrainCounts, (pieces / SSIZE), -1)
628642 $Tuple6(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)
629643 }
630644 }
652666 let continent = r._3
653667 let continentIdx = valueOrErrorMessage(indexOf(continents, continent), ("Unknown continent: " + continent))
654668 let terrains = genTerrains(abs(toBigInt(txId)), continentIdx)
655- let freeNum = valueOrElse(getInteger(keyNextFreeLandNum()), 501)
669+ let freeNum = valueOrElse(getInteger(keyNextFreeLandNum()), (PRESALENUMLANDS + 1))
656670 let newLandNum = toString(freeNum)
657671 let issue = Issue(keyNftName(newLandNum, newLandSize), makeString([newLandNum, newLandSize, terrains, continent], "_"), 1, 0, false)
658672 let assetId = calculateAssetId(issue)
713727
714728
715729 @Callable(i)
716-func stakeLand () = {
717- let pmt = value(i.payments[0])
718- let assetId = value(pmt.assetId)
719- let address = toString(i.caller)
720- if ((pmt.amount != 1))
721- then throw((("NFT " + LANDPREFIX) + " token should be attached as payment"))
722- else {
723- let asset = value(assetInfo(assetId))
724- if ((asset.issuer != this))
725- then throw("Unknown issuer of token")
726- else if (!(contains(asset.name, LANDPREFIX)))
727- then throw((("Only NFT " + LANDPREFIX) + " tokens are accepted"))
728- else {
729- let landNumSize = drop(asset.name, 4)
730- let landNum = if (contains(landNumSize, "XXL"))
731- then dropRight(landNumSize, 3)
732- else if (contains(landNumSize, "XL"))
733- then dropRight(landNumSize, 2)
734- else dropRight(landNumSize, 1)
735- let landNumInt = valueOrErrorMessage(parseInt(landNum), ("Cannot parse land number from " + asset.name))
736- let landAssetId = toBase58String(assetId)
737- let timeKey = keyStakedTimeByAssetId(landAssetId)
738- if (isDefined(getInteger(timeKey)))
739- then throw((("NFT " + asset.name) + " is already staked"))
740- else {
741- let d = split(asset.description, "_")
742- let terrainCounts = countTerrains(d[recTerrains])
743- let props = updateProportions(terrainCounts, (numPiecesBySize(d[recLandSize]) / 25), 1)
730+func stakeLand () = if ((size(i.payments) != 1))
731+ then throw("Exactly one payment required")
732+ else {
733+ let pmt = value(i.payments[0])
734+ let assetId = value(pmt.assetId)
735+ let address = toString(i.caller)
736+ if ((pmt.amount != 1))
737+ then throw((("NFT " + LANDPREFIX) + " token should be attached as payment"))
738+ else {
739+ let asset = value(assetInfo(assetId))
740+ if ((asset.issuer != this))
741+ then throw("Unknown issuer of token")
742+ else if (!(contains(asset.name, LANDPREFIX)))
743+ then throw((("Only NFT " + LANDPREFIX) + " tokens are accepted"))
744+ else {
745+ let landNumSize = drop(asset.name, 4)
746+ let landNum = if (contains(landNumSize, "XXL"))
747+ then dropRight(landNumSize, 3)
748+ else if (contains(landNumSize, "XL"))
749+ then dropRight(landNumSize, 2)
750+ else dropRight(landNumSize, 1)
751+ if (!(isDefined(parseInt(landNum))))
752+ then throw(("Cannot parse land number from " + asset.name))
753+ else {
754+ let landAssetId = toBase58String(assetId)
755+ let timeKey = keyStakedTimeByAssetId(landAssetId)
756+ if (isDefined(getInteger(timeKey)))
757+ then throw((("NFT " + asset.name) + " is already staked"))
758+ else {
759+ let d = split(asset.description, "_")
760+ let terrainCounts = countTerrains(d[recTerrains])
761+ let props = updateProportions(terrainCounts, (numPiecesBySize(d[recLandSize]) / SSIZE), 1)
744762 [IntegerEntry(timeKey, lastBlock.timestamp), IntegerEntry(keyStakedTimeByTypeAssetIdAndOwner(LANDPREFIX, landAssetId, address), lastBlock.timestamp), StringEntry(keyLandAssetIdToOwner(landAssetId), address), StringEntry(keyLandNumToOwner(landNum), address), StringEntry(keyResProportions(), props)]
745- }
746- }
747- }
748- }
763+ }
764+ }
765+ }
766+ }
767+ }
749768
750769
751770
757776 let c = checkClaimConditions(addr)
758777 let terrainCounts = countTerrains(c._3[recTerrains])
759778 let pieces = numPiecesBySize(c._3[recLandSize])
760- let props = updateProportions(terrainCounts, (pieces / 25), -1)
779+ let props = updateProportions(terrainCounts, (pieces / SSIZE), -1)
761780 let claimResult = claimAll(addr, c._2, pieces)
762781 [ScriptTransfer(i.caller, 1, fromBase58String(c._2)), DeleteEntry(keyStakedTimeByAssetId(c._2)), DeleteEntry(keyStakedTimeByTypeAssetIdAndOwner(LANDPREFIX, c._2, addr)), StringEntry(keyResProportions(), props), StringEntry(claimResult._2, makeString(claimResult._3, ":"))]
763782 }
765784
766785
767786 @Callable(i)
768-func stakeDuck () = {
769- let pmt = value(i.payments[0])
770- let assetId = value(pmt.assetId)
771- let address = toString(i.caller)
772- if ((pmt.amount != 1))
773- then throw((("NFT " + DUCKPREFIX) + " token should be attached as payment"))
774- else {
775- let asset = value(assetInfo(assetId))
776- if (if ((asset.issuer != incubatorAddr))
777- then (asset.issuer != breederAddr)
778- else false)
779- then throw((("Unknown issuer of " + DUCKPREFIX) + " token"))
780- else if (!(contains(asset.name, DUCKPREFIX)))
781- then throw((("Only NFT " + DUCKPREFIX) + " tokens are accepted"))
782- else {
783- let assetIdStr = toBase58String(assetId)
784- let timeKey = keyStakedTimeByAssetId(assetIdStr)
785- if (isDefined(getInteger(timeKey)))
786- then throw((("NFT " + asset.name) + " is already staked"))
787- else if (isDefined(getString(keyStakedDuckByOwner(address))))
788- then throw(("You already staked one duck: " + asset.name))
789- else {
790- let locKey = keyDuckLocation(assetIdStr)
791- let location = getString(locKey)
792- let keyHealth = keyDuckHealth(assetIdStr)
793- let health = getInteger(keyHealth)
794- let bpKey = keyBackpackByDuck(assetIdStr)
795- let backpack = getString(bpKey)
796- ([IntegerEntry(timeKey, lastBlock.timestamp), IntegerEntry(keyStakedTimeByTypeAssetIdAndOwner(DUCKPREFIX, toBase58String(assetId), address), lastBlock.timestamp), StringEntry(keyDuckIdToOwner(assetIdStr), address), StringEntry(keyStakedDuckByOwner(address), assetIdStr)] ++ (if (isDefined(location))
797- then nil
798- else ([StringEntry(locKey, DEFAULTLOCATION)] ++ (if (isDefined(health))
787+func stakeDuck () = if ((size(i.payments) != 1))
788+ then throw("Exactly one payment required")
789+ else {
790+ let pmt = value(i.payments[0])
791+ let assetId = value(pmt.assetId)
792+ let address = toString(i.caller)
793+ if ((pmt.amount != 1))
794+ then throw((("NFT " + DUCKPREFIX) + " token should be attached as payment"))
795+ else {
796+ let asset = value(assetInfo(assetId))
797+ if (if ((asset.issuer != incubatorAddr))
798+ then (asset.issuer != breederAddr)
799+ else false)
800+ then throw((("Unknown issuer of " + DUCKPREFIX) + " token"))
801+ else if (!(contains(asset.name, DUCKPREFIX)))
802+ then throw((("Only NFT " + DUCKPREFIX) + " tokens are accepted"))
803+ else {
804+ let assetIdStr = toBase58String(assetId)
805+ let timeKey = keyStakedTimeByAssetId(assetIdStr)
806+ if (isDefined(getInteger(timeKey)))
807+ then throw((("NFT " + asset.name) + " is already staked"))
808+ else if (isDefined(getString(keyStakedDuckByOwner(address))))
809+ then throw(("You already staked one duck: " + asset.name))
810+ else {
811+ let locKey = keyDuckLocation(assetIdStr)
812+ let location = getString(locKey)
813+ let bpKey = keyBackpackByDuck(assetIdStr)
814+ let backpack = getString(bpKey)
815+ ([IntegerEntry(timeKey, lastBlock.timestamp), IntegerEntry(keyStakedTimeByTypeAssetIdAndOwner(DUCKPREFIX, toBase58String(assetId), address), lastBlock.timestamp), StringEntry(keyDuckIdToOwner(assetIdStr), address), StringEntry(keyStakedDuckByOwner(address), assetIdStr)] ++ (if (isDefined(location))
799816 then nil
800- else ([IntegerEntry(keyHealth, 100)] ++ (if (isDefined(backpack))
817+ else ([StringEntry(locKey, DEFAULTLOCATION)] ++ (if (isDefined(backpack))
801818 then nil
802- else [StringEntry(bpKey, "0:0_0_0_0_0_0:0_0_0_0_0_0:")]))))))
803- }
804- }
805- }
806- }
819+ else ([StringEntry(bpKey, "0:0_0_0_0_0_0:0_0_0_0_0_0:")] :+ IntegerEntry(keyDuckHealth(assetIdStr), 100))))))
820+ }
821+ }
822+ }
823+ }
807824
808825
809826
814831 let assetId = fromBase58String(assetIdStr)
815832 let address = toString(i.caller)
816833 let asset = value(assetInfo(assetId))
817- if (if ((asset.issuer != incubatorAddr))
818- then (asset.issuer != breederAddr)
819- else false)
820- then throw((("Unknown issuer of " + DUCKPREFIX) + " token"))
821- else if (!(contains(asset.name, DUCKPREFIX)))
822- then throw((("Only NFT " + DUCKPREFIX) + " tokens can be unstaked"))
834+ let timeKey = keyStakedTimeByAssetId(toBase58String(assetId))
835+ if (!(isDefined(timeKey)))
836+ then throw((("NFT " + asset.name) + " is not staked"))
837+ else if (!(isDefined(keyStakedDuckByOwner(address))))
838+ then throw((("The duck " + asset.name) + " is not staked"))
823839 else {
824- let timeKey = keyStakedTimeByAssetId(toBase58String(assetId))
825- if (!(isDefined(timeKey)))
826- then throw((("NFT " + asset.name) + " is not staked"))
827- else if (!(isDefined(keyStakedDuckByOwner(address))))
828- then throw((("The duck " + asset.name) + " is not staked"))
829- else {
830- let owner = valueOrErrorMessage(getString(keyDuckIdToOwner(toBase58String(assetId))), (("NFT " + asset.name) + " is orphaned"))
831- if ((owner != address))
832- then throw("Staked NFT is not yours")
833- else [ScriptTransfer(i.caller, 1, assetId), DeleteEntry(timeKey), DeleteEntry(keyDuckLocation(assetIdStr)), DeleteEntry(keyDuckIdToOwner(assetIdStr)), DeleteEntry(keyStakedTimeByTypeAssetIdAndOwner(DUCKPREFIX, assetIdStr, address)), DeleteEntry(keyStakedDuckByOwner(address))]
834- }
840+ let owner = valueOrErrorMessage(getString(keyDuckIdToOwner(toBase58String(assetId))), (("NFT " + asset.name) + " is orphaned"))
841+ if ((owner != address))
842+ then throw("Staked NFT is not yours")
843+ else {
844+ let keyHealth = keyDuckHealth(assetIdStr)
845+ let health = getInteger(keyHealth)
846+ if ((health != 100))
847+ then throw("Please heal your duck before unstaking")
848+ else [ScriptTransfer(i.caller, 1, assetId), DeleteEntry(timeKey), DeleteEntry(keyHealth), DeleteEntry(keyDuckLocation(assetIdStr)), DeleteEntry(keyDuckIdToOwner(assetIdStr)), DeleteEntry(keyStakedTimeByTypeAssetIdAndOwner(DUCKPREFIX, assetIdStr, address)), DeleteEntry(keyStakedDuckByOwner(address))]
849+ }
835850 }
836851 }
837852
945960 then throw(("Payment attached should be " + toString(EXPUSDN)))
946961 else {
947962 let result = expeditionCommon(false, i.caller, i.transactionId, message, sig)
948- $Tuple2((result._1 :+ ScriptTransfer(economyAddr, pmt.amount, usdnAssetId)), result._2)
963+ if ((result._2 == ""))
964+ then result
965+ else $Tuple2((result._1 :+ ScriptTransfer(economyAddr, pmt.amount, usdnAssetId)), result._2)
949966 }
950967 }
951968
Full:
OldNewDifferences
11 {-# STDLIB_VERSION 6 #-}
22 {-# SCRIPT_TYPE ACCOUNT #-}
33 {-# CONTENT_TYPE DAPP #-}
44 let chain = toUtf8String(take(drop(this.bytes, 1), 1))
55
66 let usdnAssetId = match chain {
77 case _ =>
88 if (("W" == $match0))
99 then base58'DG2xFkPdDwKUoBkzGAhQtLpSGzfXLiCYPEzeKH2Ad24p'
1010 else if (("T" == $match0))
1111 then base58'HezsdQuRDtzksAYUy97gfhKy7Z1NW2uXYSHA3bgqenNZ'
1212 else throw("Unknown chain")
1313 }
1414
1515 let incubatorAddr = match chain {
1616 case _ =>
1717 if (("W" == $match0))
1818 then addressFromStringValue("3PEktVux2RhchSN63DsDo4b4mz4QqzKSeDv")
1919 else if (("T" == $match0))
2020 then this
2121 else throw("Unknown chain")
2222 }
2323
2424 let breederAddr = match chain {
2525 case _ =>
2626 if (("W" == $match0))
2727 then addressFromStringValue("3PDVuU45H7Eh5dmtNbnRNRStGwULA7NY6Hb")
2828 else if (("T" == $match0))
2929 then this
3030 else throw("Unknown chain")
3131 }
3232
3333 let economyAddr = match chain {
3434 case _ =>
3535 if (("W" == $match0))
3636 then addressFromStringValue("3P2sk1KncSxRaZs8b4CWGPw2jkvvav74u4D")
3737 else if (("T" == $match0))
3838 then addressFromStringValue("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
53+
54+let SSIZE = 25
55+
56+let MSIZE = 100
57+
58+let LSIZE = 225
59+
60+let XLSIZE = 400
61+
62+let XXLSIZE = 625
5363
5464 let DAILYRESBYPIECE = 3456000
5565
5666 let DAYMILLIS = 86400000
5767
5868 let FIVEMINUTESMILLIS = 300000
5969
6070 let RESOURCEPRICEMIN = 158549
6171
6272 let InfraUpgradeCostS = match chain {
6373 case _ =>
6474 if (("W" == $match0))
6575 then 6307198406
6676 else if (("T" == $match0))
6777 then 63071984
6878 else throw("Unknown chain")
6979 }
7080
7181 let InfraUpgradeCostSUsdn = match chain {
7282 case _ =>
7383 if (("W" == $match0))
7484 then 40000000
7585 else if (("T" == $match0))
7686 then 400000
7787 else throw("Unknown chain")
7888 }
7989
8090 let EXPMATERIALS = match chain {
8191 case _ =>
8292 if (("W" == $match0))
8393 then 157679960139
8494 else if (("T" == $match0))
8595 then 1576799601
8696 else throw("Unknown chain")
8797 }
8898
8999 let EXPUSDN = match chain {
90100 case _ =>
91101 if (("W" == $match0))
92102 then 1000000000
93103 else if (("T" == $match0))
94104 then 10000000
95105 else throw("Unknown chain")
96106 }
97107
98108 let MULT6 = 1000000
99109
100110 let FIVEX = toBigInt(5)
101111
102112 let TWENTYX = toBigInt(20)
103113
104114 let TWENTY2X = toBigInt((20 * 20))
105115
106116 let TWENTY3X = toBigInt(((20 * 20) * 20))
107117
108118 let TWENTY4X = toBigInt((((20 * 20) * 20) * 20))
109119
110120 let TWENTY5X = toBigInt(((((20 * 20) * 20) * 20) * 20))
111121
112122 let matTypes = ["Fuel", "Metal", "Plank", "Glass", "Plastic", "Protein"]
113123
114124 let continents = ["Asia", "Europe", "Americas", "Oceania", "Africa"]
115125
116126 let ARTPRESALE = "PRESALE"
127+
128+let PRESALENUMLANDS = 500
117129
118130 func keyNextFreeLandNum () = "nextLandNum"
119131
120132
121133 func keyLandToAssetId (landNum) = ("landToAsset_" + landNum)
122134
123135
124136 func keyNftName (landNum,landSize) = ((LANDPREFIX + landNum) + landSize)
125137
126138
127139 func keyLandAssetIdToOwner (assetId) = ("nftOwner_" + assetId)
128140
129141
130142 func keyDuckIdToOwner (assetId) = ("duckOwner_" + assetId)
131143
132144
133145 func keyStakedTimeByAssetId (assetId) = ("stakedTime_" + assetId)
134146
135147
136148 func keyInfraLevelByAssetId (assetId) = ("infraLevel_" + assetId)
137149
138150
139151 func keyInfraLevelByAssetIdAndOwner (assetId,ownerAddr) = ((("infraLevelByAssetIdAndOwner_" + assetId) + "_") + ownerAddr)
140152
141153
142154 func keyPresaleArtActivatedByAssetId (assetId) = ("presaleArtActivated_" + assetId)
143155
144156
145157 func keyPresaleArtActivatedByAssetIdAndOwner (assetId,ownerAddr) = ((("presaleArtActivatedByAssetIdAndOwner_" + assetId) + "_") + ownerAddr)
146158
147159
148160 func keyLandArtStatusByTypeAndAssetId (type,assetId) = makeString(["landArtStatus", type, assetId], "_")
149161
150162
151163 func keyLandArtStatusByTypeAssetIdAndOwner (type,assetId,ownerAddr) = makeString(["landArtStatusByTypeAssetIdAndOwner", type, assetId, ownerAddr], "_")
152164
153165
154166 func keyStakedDuckByOwner (ownerAddr) = ("stakedDuckByOwner_" + ownerAddr)
155167
156168
157169 func keyStakedTimeByTypeAssetIdAndOwner (nftType,assetId,ownerAddr) = ((((("stakedTimeByTypeAssetIdAndOwner_" + nftType) + "_") + assetId) + "_") + ownerAddr)
158170
159171
160172 func keyLandNumToOwner (landNum) = ("landOwner_" + landNum)
161173
162174
163175 func keyBackpackByDuck (duckAssetId) = ("backPack_" + duckAssetId)
164176
165177
166178 func keyDuckLocation (duckAssetId) = ("duckLocation_" + duckAssetId)
167179
168180
169181 func keyDuckHealth (duckAssetId) = ("duckHealth_" + duckAssetId)
170182
171183
172184 func keyResProportions () = "resTypesProportions"
173185
174186
175187 let recLandNum = 0
176188
177189 let recLandSize = 1
178190
179191 let recTerrains = 2
180192
181193 let recContinent = 3
182194
183195 let locIdxContinent = 0
184196
185197 let locIdxType = 1
186198
187199 let locIdxId = 2
188200
189201 let bpIdxLevel = 0
190202
191203 let bpIdxRes = 1
192204
193205 let bpIdxMat = 2
194206
195207 let bpIdxProd = 3
196208
197209 func asString (v) = match v {
198210 case s: String =>
199211 s
200212 case _ =>
201213 throw("fail to cast into String")
202214 }
203215
204216
205217 func getNeededMaterials (total) = {
206218 let props = split(value(getString(keyResProportions())), "_")
207219 if ((size(props) != NUMRES))
208220 then throw("Wrong proportions data")
209221 else {
210222 let r = [parseIntValue(props[0]), parseIntValue(props[1]), parseIntValue(props[2]), parseIntValue(props[3]), parseIntValue(props[4]), parseIntValue(props[5])]
211223 let sum = (((((r[0] + r[1]) + r[2]) + r[3]) + r[4]) + r[5])
212224 if ((0 >= sum))
213225 then throw("No lands staked")
214226 else {
215227 let norm6 = fraction(total, MULT6, sum)
216228 func normalizer (acc,elem) = (acc :+ fraction(elem, norm6, MULT6))
217229
218230 let $l = r
219231 let $s = size($l)
220232 let $acc0 = nil
221233 func $f0_1 ($a,$i) = if (($i >= $s))
222234 then $a
223235 else normalizer($a, $l[$i])
224236
225237 func $f0_2 ($a,$i) = if (($i >= $s))
226238 then $a
227239 else throw("List size exceeds 6")
228240
229241 $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6)
230242 }
231243 }
232244 }
233245
234246
235247 func subtractMaterials (shouldUseMat,has,totalNeed) = {
236248 let need = getNeededMaterials(totalNeed)
237249 func subtractor (acc,idx) = {
238250 let result = (parseIntValue(has[idx]) - need[idx])
239251 if ((0 > result))
240252 then throw(((((("Not enough material idx=" + toString(idx)) + ", you have ") + has[idx]) + ", but need ") + toString(need[idx])))
241253 else (acc :+ toString(result))
242254 }
243255
244256 if (shouldUseMat)
245257 then {
246258 let $l = [0, 1, 2, 3, 4, 5]
247259 let $s = size($l)
248260 let $acc0 = nil
249261 func $f0_1 ($a,$i) = if (($i >= $s))
250262 then $a
251263 else subtractor($a, $l[$i])
252264
253265 func $f0_2 ($a,$i) = if (($i >= $s))
254266 then $a
255267 else throw("List size exceeds 6")
256268
257269 $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6)
258270 }
259271 else has
260272 }
261273
262274
263275 func updateProportionsInternal (propList,terrainCounts,landSizeIndex,sign) = if ((size(propList) != NUMRES))
264276 then throw("Wrong proportions data")
265277 else {
266278 func updater (acc,i) = {
267279 let result = (parseIntValue(propList[i]) + ((sign * terrainCounts[i]) * landSizeIndex))
268280 if ((0 > result))
269281 then throw(((((((("Panic! Pieces of type=" + toString(i)) + ", sign=") + toString(sign)) + ", terrainCounts[i]=") + toString(terrainCounts[i])) + ", landSizeIndex=") + toString(landSizeIndex)))
270282 else (acc :+ toString(result))
271283 }
272284
273285 let r = {
274286 let $l = [0, 1, 2, 3, 4, 5]
275287 let $s = size($l)
276288 let $acc0 = nil
277289 func $f0_1 ($a,$i) = if (($i >= $s))
278290 then $a
279291 else updater($a, $l[$i])
280292
281293 func $f0_2 ($a,$i) = if (($i >= $s))
282294 then $a
283295 else throw("List size exceeds 6")
284296
285297 $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6)
286298 }
287299 makeString(r, "_")
288300 }
289301
290302
291303 func updateProportions (terrainCounts,landSizeIndex,sign) = {
292304 let propList = split(valueOrElse(getString(keyResProportions()), "0_0_0_0_0_0"), "_")
293305 updateProportionsInternal(propList, terrainCounts, landSizeIndex, sign)
294306 }
295307
296308
297309 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)]
298310
299311
300312 func numPiecesBySize (landSize) = match landSize {
301313 case _ =>
302314 if (("S" == $match0))
303- then 25
315+ then SSIZE
304316 else if (("M" == $match0))
305- then 100
317+ then MSIZE
306318 else if (("L" == $match0))
307- then 225
319+ then LSIZE
308320 else if (("XL" == $match0))
309- then 400
321+ then XLSIZE
310322 else if (("XXL" == $match0))
311- then 625
323+ then XXLSIZE
312324 else throw("Unknown land size")
313325 }
314326
315327
316328 func subOneInList (aList,idx,amount) = {
317329 func subber (acc,i) = (acc :+ (if ((i == idx))
318330 then toString((parseIntValue(aList[i]) - amount))
319331 else aList[i]))
320332
321333 let r = {
322334 let $l = [0, 1, 2, 3, 4, 5]
323335 let $s = size($l)
324336 let $acc0 = nil
325337 func $f0_1 ($a,$i) = if (($i >= $s))
326338 then $a
327339 else subber($a, $l[$i])
328340
329341 func $f0_2 ($a,$i) = if (($i >= $s))
330342 then $a
331343 else throw("List size exceeds 6")
332344
333345 $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6)
334346 }
335347 makeString(r, "_")
336348 }
337349
338350
339351 func addRes (currentRes,terrainCounts,deltaTime,landSizeIndex,dailyByPieceWithBonuses) = {
340352 func adder (acc,i) = {
341353 let resOfType = ((fraction(deltaTime, dailyByPieceWithBonuses, DAYMILLIS) * terrainCounts[i]) * landSizeIndex)
342354 (acc :+ toString((parseIntValue(currentRes[i]) + resOfType)))
343355 }
344356
345357 let r = {
346358 let $l = [0, 1, 2, 3, 4, 5]
347359 let $s = size($l)
348360 let $acc0 = nil
349361 func $f0_1 ($a,$i) = if (($i >= $s))
350362 then $a
351363 else adder($a, $l[$i])
352364
353365 func $f0_2 ($a,$i) = if (($i >= $s))
354366 then $a
355367 else throw("List size exceeds 6")
356368
357369 $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6)
358370 }
359371 makeString(r, "_")
360372 }
361373
362374
363375 func abs (x) = if ((x >= toBigInt(0)))
364376 then x
365377 else -(x)
366378
367379
368380 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]]
369381
370382 func genChar (n,freqs) = {
371383 let rem = toInt((n % TWENTYX))
372384 let letter = if ((freqs[0] > rem))
373385 then "A"
374386 else if ((freqs[1] > rem))
375387 then "B"
376388 else if ((freqs[2] > rem))
377389 then "C"
378390 else if ((freqs[3] > rem))
379391 then "D"
380392 else if ((freqs[4] > rem))
381393 then "E"
382394 else "F"
383395 letter
384396 }
385397
386398
387399 func genTerrains (seed,continentIdx) = {
388400 let f = freq[continentIdx]
389401 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))
390402
391403 let t = {
392404 let $l = [1, 2, 3, 4, 5]
393405 let $s = size($l)
394406 let $acc0 = $Tuple2("", (seed / FIVEX))
395407 func $f0_1 ($a,$i) = if (($i >= $s))
396408 then $a
397409 else terrainGenerator($a, $l[$i])
398410
399411 func $f0_2 ($a,$i) = if (($i >= $s))
400412 then $a
401413 else throw("List size exceeds 5")
402414
403415 $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5)
404416 }
405417 t._1
406418 }
407419
408420
409421 func getBackpack (bpKey) = {
410422 let p = split(valueOrElse(getString(bpKey), "0:0_0_0_0_0_0:0_0_0_0_0_0:"), ":")
411423 [toString(valueOrElse(parseInt(p[bpIdxLevel]), 0)), if ((size(split(p[bpIdxRes], "_")) == NUMRES))
412424 then p[bpIdxRes]
413425 else "0_0_0_0_0_0", if ((size(split(p[bpIdxMat], "_")) == NUMRES))
414426 then p[bpIdxMat]
415427 else "0_0_0_0_0_0", p[bpIdxProd]]
416428 }
417429
418430
419431 func expeditionCommon (shouldUseMat,caller,txId,message,sig) = if (!(sigVerify_8Kb(message, sig, pub)))
420432 then throw("signature does not match")
421433 else {
422434 let parts = split(toUtf8String(message), ";")
423435 let hp = split(split(parts[0], "|")[0], "_")
424436 let curHP = parseIntValue(hp[0])
425437 let newHP = parseIntValue(hp[1])
426438 let locAndTime = split(parts[1], ":")
427439 let targetLocation = split(locAndTime[0], "_")
428440 if ((targetLocation[1] != "E"))
429441 then throw("expedition target location type should be E")
430442 else {
431443 let time = parseIntValue(locAndTime[1])
432444 if (if ((time > (lastBlock.timestamp + FIVEMINUTESMILLIS)))
433445 then true
434446 else ((lastBlock.timestamp - FIVEMINUTESMILLIS) > time))
435447 then throw("signature outdated")
436448 else {
437449 let userAddr = toString(caller)
438450 let duckAssetId = valueOrErrorMessage(getString(keyStakedDuckByOwner(userAddr)), "You don't have a duck staked")
439451 let keyHealth = keyDuckHealth(duckAssetId)
440452 let oldFromState = valueOrElse(getInteger(keyHealth), 100)
441453 if ((oldFromState != curHP))
442454 then throw(((("oldHealth=" + toString(valueOrElse(getInteger(keyHealth), 100))) + " from state does not match one from flight log=") + toString(curHP)))
443455 else if ((0 >= curHP))
444456 then throw("You can't fly with zero health")
445457 else if ((0 >= newHP))
446458 then $Tuple2(((if (!(shouldUseMat))
447459 then [ScriptTransfer(caller, EXPUSDN, usdnAssetId)]
448460 else nil) :+ IntegerEntry(keyHealth, 0)), "")
449461 else {
450462 let bpKey = keyBackpackByDuck(duckAssetId)
451463 let currentPack = getBackpack(bpKey)
452464 let mList = split(currentPack[bpIdxMat], "_")
453465 let newMat = makeString(subtractMaterials(shouldUseMat, mList, EXPMATERIALS), "_")
454466 let bigNum = abs(toBigInt(txId))
455- let freeNum = valueOrElse(getInteger(keyNextFreeLandNum()), 501)
467+ let freeNum = valueOrElse(getInteger(keyNextFreeLandNum()), (PRESALENUMLANDS + 1))
456468 let landNum = toString(freeNum)
457469 let continentIdx = toInt((bigNum % FIVEX))
458470 let terrains = genTerrains(bigNum, continentIdx)
459471 let continent = continents[continentIdx]
460472 let issue = Issue(keyNftName(landNum, "S"), makeString([landNum, "S", terrains, continent], "_"), 1, 0, false)
461473 let assetId = calculateAssetId(issue)
462474 let id = toBase58String(assetId)
463475 $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)
464476 }
465477 }
466478 }
467479 }
468480
469481
470482 func applyBonuses (landAssetId,pieces) = {
471483 let infraLevel = valueOrElse(getInteger(keyInfraLevelByAssetId(landAssetId)), 0)
472484 let artPieces = valueOrElse(getInteger(keyLandArtStatusByTypeAndAssetId(ARTPRESALE, landAssetId)), if (valueOrElse(getBoolean(keyPresaleArtActivatedByAssetId(landAssetId)), false))
473485 then pieces
474486 else 0)
475487 ((DAILYRESBYPIECE + fraction(DAILYRESBYPIECE, infraLevel, 4)) + fraction(DAILYRESBYPIECE, (artPieces * 3), (pieces * 20)))
476488 }
477489
478490
479491 func checkClaimConditions (addr) = {
480492 let duckAssetId = valueOrErrorMessage(getString(keyStakedDuckByOwner(addr)), "You don't have a duck staked")
481493 let curLocation = valueOrElse(getString(keyDuckLocation(duckAssetId)), DEFAULTLOCATION)
482494 let loc = split(value(curLocation), "_")
483495 if ((loc[locIdxType] != "L"))
484496 then throw((("Duck location type is " + loc[locIdxType]) + ", but should be L"))
485497 else {
486498 let landAssetId = loc[locIdxId]
487499 let asset = value(assetInfo(fromBase58String(landAssetId)))
488500 let timeKey = keyStakedTimeByAssetId(landAssetId)
489- let savedTime = valueOrErrorMessage(getInteger(timeKey), (("NFT " + asset.name) + " is not staked"))
501+ let savedTime = valueOrErrorMessage(getInteger(timeKey), (("Your duck is on " + asset.name) + ", which is not staked"))
490502 let owner = valueOrErrorMessage(getString(keyLandAssetIdToOwner(landAssetId)), (("NFT " + asset.name) + " is orphaned"))
491503 if ((owner != addr))
492504 then throw((LANDPREFIX + " is not yours"))
493505 else {
494506 let d = split(asset.description, "_")
495507 $Tuple4(duckAssetId, landAssetId, d, savedTime)
496508 }
497509 }
498510 }
499511
500512
501-func claimResInternal (addr,amount) = {
502- let c = checkClaimConditions(addr)
503- let landSize = c._3[recLandSize]
504- let terrainCounts = countTerrains(c._3[recTerrains])
505- let deltaTime = (lastBlock.timestamp - c._4)
506- if ((0 > deltaTime))
507- then throw(((("Saved timestamp is in future, saved = " + toString(c._4)) + ", current = ") + toString(lastBlock.timestamp)))
508- else {
509- let pieces = numPiecesBySize(landSize)
510- let dailyProductionByPiece = applyBonuses(c._2, pieces)
511- let availRes = fraction(deltaTime, (dailyProductionByPiece * pieces), DAYMILLIS)
512- if ((amount > availRes))
513- then throw(((("Not enough resources, available = " + toString(availRes)) + ", requested = ") + toString(amount)))
514- else {
515- let newDeltaTime = fraction((availRes - amount), DAYMILLIS, (dailyProductionByPiece * pieces))
516- let newTimestamp = (lastBlock.timestamp - newDeltaTime)
517- let bpKey = keyBackpackByDuck(c._1)
518- let currentPack = getBackpack(bpKey)
519- let currentRes = split(currentPack[bpIdxRes], "_")
520- let bpRes = addRes(currentRes, terrainCounts, (deltaTime - newDeltaTime), (pieces / 25), dailyProductionByPiece)
521- $Tuple3([IntegerEntry(keyStakedTimeByAssetId(c._2), newTimestamp), IntegerEntry(keyStakedTimeByTypeAssetIdAndOwner(LANDPREFIX, c._2, addr), newTimestamp)], bpKey, [currentPack[bpIdxLevel], bpRes, currentPack[bpIdxMat], currentPack[bpIdxProd]])
522- }
523- }
524- }
513+func claimResInternal (addr,amount) = if ((0 > amount))
514+ then throw("Negative amount")
515+ else {
516+ let c = checkClaimConditions(addr)
517+ let landSize = c._3[recLandSize]
518+ let terrainCounts = countTerrains(c._3[recTerrains])
519+ let deltaTime = (lastBlock.timestamp - c._4)
520+ if ((0 > deltaTime))
521+ then throw(((("Saved timestamp is in future, saved = " + toString(c._4)) + ", current = ") + toString(lastBlock.timestamp)))
522+ else {
523+ let pieces = numPiecesBySize(landSize)
524+ let dailyProductionByPiece = applyBonuses(c._2, pieces)
525+ let availRes = fraction(deltaTime, (dailyProductionByPiece * pieces), DAYMILLIS)
526+ if ((amount > availRes))
527+ then throw(((("Not enough resources, available = " + toString(availRes)) + ", requested = ") + toString(amount)))
528+ else {
529+ let newDeltaTime = fraction((availRes - amount), DAYMILLIS, (dailyProductionByPiece * pieces))
530+ let newTimestamp = (lastBlock.timestamp - newDeltaTime)
531+ let bpKey = keyBackpackByDuck(c._1)
532+ let currentPack = getBackpack(bpKey)
533+ let currentRes = split(currentPack[bpIdxRes], "_")
534+ let bpRes = addRes(currentRes, terrainCounts, (deltaTime - newDeltaTime), (pieces / SSIZE), dailyProductionByPiece)
535+ $Tuple3([IntegerEntry(keyStakedTimeByAssetId(c._2), newTimestamp), IntegerEntry(keyStakedTimeByTypeAssetIdAndOwner(LANDPREFIX, c._2, addr), newTimestamp)], bpKey, [currentPack[bpIdxLevel], bpRes, currentPack[bpIdxMat], currentPack[bpIdxProd]])
536+ }
537+ }
538+ }
525539
526540
527541 func claimAll (addr,landAssetId,pieces) = {
528542 let timeKey = keyStakedTimeByAssetId(landAssetId)
529543 let savedTime = value(getInteger(timeKey))
530544 let availRes = (fraction((lastBlock.timestamp - savedTime), applyBonuses(landAssetId, pieces), DAYMILLIS) * pieces)
531545 claimResInternal(addr, availRes)
532546 }
533547
534548
535549 func upInfraCommon (shouldUseMat,caller,paymentAmount) = {
536550 let addr = toString(caller)
537551 let c = checkClaimConditions(addr)
538552 let pieces = numPiecesBySize(c._3[recLandSize])
539553 let infraKey = keyInfraLevelByAssetId(c._2)
540554 let curLevel = valueOrElse(getInteger(infraKey), 0)
541555 if ((curLevel >= 3))
542556 then throw("Currently max infrastructure level = 3")
543557 else {
544558 let newLevel = (curLevel + 1)
545- let cost = fraction(InfraUpgradeCostSUsdn, (pieces * newLevel), 25)
559+ let cost = fraction(InfraUpgradeCostSUsdn, (pieces * newLevel), SSIZE)
546560 if (if (!(shouldUseMat))
547561 then (paymentAmount != cost)
548562 else false)
549563 then throw(("Payment attached should be " + toString(cost)))
550564 else {
551565 let bpKey = keyBackpackByDuck(c._1)
552566 let currentPack = getBackpack(bpKey)
553567 let mList = split(currentPack[bpIdxMat], "_")
554- let newMat = makeString(subtractMaterials(shouldUseMat, mList, fraction(InfraUpgradeCostS, (pieces * newLevel), 25)), "_")
568+ let newMat = makeString(subtractMaterials(shouldUseMat, mList, fraction(InfraUpgradeCostS, (pieces * newLevel), SSIZE)), "_")
555569 let claimResult = claimAll(addr, c._2, pieces)
556570 $Tuple2(([IntegerEntry(infraKey, newLevel), IntegerEntry(keyInfraLevelByAssetIdAndOwner(c._2, addr), newLevel), StringEntry(bpKey, makeString([currentPack[bpIdxLevel], claimResult._3[bpIdxRes], newMat, currentPack[bpIdxProd]], ":"))] ++ claimResult._1), newLevel)
557571 }
558572 }
559573 }
560574
561575
562576 func activatePresaleArt (addr) = {
563577 let c = checkClaimConditions(addr)
564578 let landAssetId = c._2
565579 let activationKey = keyPresaleArtActivatedByAssetId(landAssetId)
566580 if (valueOrElse(getBoolean(activationKey), false))
567581 then throw("Presale artifact is already activated")
568- else if ((parseIntValue(c._3[recLandNum]) > 500))
582+ else if ((parseIntValue(c._3[recLandNum]) > PRESALENUMLANDS))
569583 then throw((((LANDPREFIX + " ") + landAssetId) + " is not eligible for presale artifact"))
570584 else {
571585 let pieces = numPiecesBySize(c._3[recLandSize])
572586 let claimResult = claimAll(addr, landAssetId, pieces)
573587 (((((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, ":")))
574588 }
575589 }
576590
577591
578592 func mergeInternal (newLandSize,newLevel,formula,addr,landAssetIds,txId,needMat) = {
579593 let duckAssetId = valueOrErrorMessage(getString(keyStakedDuckByOwner(addr)), "You don't have a duck staked")
580594 func checkMerge (acc,landAssetId) = {
581595 let asset = value(assetInfo(fromBase58String(landAssetId)))
582596 let timeKey = keyStakedTimeByAssetId(landAssetId)
583597 let savedTime = valueOrErrorMessage(getInteger(timeKey), (("NFT " + asset.name) + " is not staked"))
584598 let owner = valueOrErrorMessage(getString(keyLandAssetIdToOwner(landAssetId)), (("NFT " + asset.name) + " is orphaned"))
585599 if ((owner != addr))
586600 then throw((LANDPREFIX + " is not yours"))
587601 else {
588602 let d = split(asset.description, "_")
589603 let continent = d[recContinent]
590604 if (if ((acc._3 != ""))
591605 then (acc._3 != continent)
592606 else false)
593607 then throw("Lands should be on the same continent to merge")
594608 else {
595609 let landSize = d[recLandSize]
596610 let sizesIn = acc._1
597611 let i = valueOrErrorMessage(indexOf(sizesIn, landSize), "You haven't passed all the lands needed")
598612 let sizesOut = (take(sizesIn, i) + drop(sizesIn, (i + 1)))
599613 let pieces = numPiecesBySize(landSize)
600614 let arts = (acc._2 + valueOrElse(getInteger(keyLandArtStatusByTypeAndAssetId(ARTPRESALE, landAssetId)), if (valueOrElse(getBoolean(keyPresaleArtActivatedByAssetId(landAssetId)), false))
601615 then pieces
602616 else 0))
603617 let infraLevel = valueOrElse(getInteger(keyInfraLevelByAssetId(landAssetId)), 0)
604618 let reqLevel = match landSize {
605619 case _ =>
606620 if (("S" == $match0))
607621 then 3
608622 else if (("M" == $match0))
609623 then 4
610624 else if (("L" == $match0))
611625 then 5
612626 else if (("XL" == $match0))
613627 then 6
614628 else throw("Only S, M, L, XL can merge")
615629 }
616630 if ((infraLevel != reqLevel))
617631 then throw("All lands should be maxed to merge")
618632 else {
619633 let landNum = d[recLandNum]
620634 let terrainCounts = countTerrains(d[recTerrains])
621635 let deltaTime = (lastBlock.timestamp - savedTime)
622636 if ((0 > deltaTime))
623637 then throw(((("Saved timestamp is in future, saved = " + toString(savedTime)) + ", current = ") + toString(lastBlock.timestamp)))
624638 else {
625639 let dailyProductionByPiece = applyBonuses(landAssetId, pieces)
626- let bpRes = addRes(split(acc._4, "_"), terrainCounts, deltaTime, (pieces / 25), dailyProductionByPiece)
627- let props = updateProportionsInternal(split(acc._6, "_"), terrainCounts, (pieces / 25), -1)
640+ let bpRes = addRes(split(acc._4, "_"), terrainCounts, deltaTime, (pieces / SSIZE), dailyProductionByPiece)
641+ let props = updateProportionsInternal(split(acc._6, "_"), terrainCounts, (pieces / SSIZE), -1)
628642 $Tuple6(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)
629643 }
630644 }
631645 }
632646 }
633647 }
634648
635649 let bpKey = keyBackpackByDuck(duckAssetId)
636650 let currentPack = getBackpack(bpKey)
637651 let propStr = valueOrElse(getString(keyResProportions()), "0_0_0_0_0_0")
638652 let r = {
639653 let $l = landAssetIds
640654 let $s = size($l)
641655 let $acc0 = $Tuple6(formula, 0, "", currentPack[bpIdxRes], nil, propStr)
642656 func $f0_1 ($a,$i) = if (($i >= $s))
643657 then $a
644658 else checkMerge($a, $l[$i])
645659
646660 func $f0_2 ($a,$i) = if (($i >= $s))
647661 then $a
648662 else throw("List size exceeds 4")
649663
650664 $f0_2($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4)
651665 }
652666 let continent = r._3
653667 let continentIdx = valueOrErrorMessage(indexOf(continents, continent), ("Unknown continent: " + continent))
654668 let terrains = genTerrains(abs(toBigInt(txId)), continentIdx)
655- let freeNum = valueOrElse(getInteger(keyNextFreeLandNum()), 501)
669+ let freeNum = valueOrElse(getInteger(keyNextFreeLandNum()), (PRESALENUMLANDS + 1))
656670 let newLandNum = toString(freeNum)
657671 let issue = Issue(keyNftName(newLandNum, newLandSize), makeString([newLandNum, newLandSize, terrains, continent], "_"), 1, 0, false)
658672 let assetId = calculateAssetId(issue)
659673 let newLandAssetId = toBase58String(assetId)
660674 let newMat = makeString(subtractMaterials((needMat > 0), split(currentPack[bpIdxMat], "_"), needMat), "_")
661675 $Tuple2((((((((((((((r._5 :+ 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)
662676 }
663677
664678
665679 func s2m (addr,landAssetIds,txId) = mergeInternal("M", 3, "SSSS", addr, landAssetIds, txId, 0)
666680
667681
668682 func m2l (addr,landAssetIds,txId,shouldUseMat,paymentAmount) = {
669683 let cost = (InfraUpgradeCostSUsdn * 4)
670684 if (if (!(shouldUseMat))
671685 then (paymentAmount != cost)
672686 else false)
673687 then throw(("Payment attached should be " + toString(cost)))
674688 else mergeInternal("L", 4, "SMM", addr, landAssetIds, txId, (InfraUpgradeCostS * 4))
675689 }
676690
677691
678692 func l2xl (addr,landAssetIds,txId,shouldUseMat,paymentAmount) = {
679693 let cost = (InfraUpgradeCostSUsdn * 47)
680694 if (if (!(shouldUseMat))
681695 then (paymentAmount != cost)
682696 else false)
683697 then throw(("Payment attached should be " + toString(cost)))
684698 else mergeInternal("XL", 5, "SSSML", addr, landAssetIds, txId, (InfraUpgradeCostS * 47))
685699 }
686700
687701
688702 func xl2xxl (addr,landAssetIds,txId,shouldUseMat,paymentAmount) = {
689703 let cost = (InfraUpgradeCostSUsdn * 54)
690704 if (if (!(shouldUseMat))
691705 then (paymentAmount != cost)
692706 else false)
693707 then throw(("Payment attached should be " + toString(cost)))
694708 else mergeInternal("XXL", 6, "LXL", addr, landAssetIds, txId, (InfraUpgradeCostS * 54))
695709 }
696710
697711
698712 func mergeCommon (shouldUseMat,addr,paymentAmount,landAssetIds,txId) = {
699713 let mergeResult = match size(landAssetIds) {
700714 case _ =>
701715 if ((4 == $match0))
702716 then s2m(addr, landAssetIds, txId)
703717 else if ((3 == $match0))
704718 then m2l(addr, landAssetIds, txId, shouldUseMat, paymentAmount)
705719 else if ((5 == $match0))
706720 then l2xl(addr, landAssetIds, txId, shouldUseMat, paymentAmount)
707721 else if ((2 == $match0))
708722 then xl2xxl(addr, landAssetIds, txId, shouldUseMat, paymentAmount)
709723 else throw("Unknown merge")
710724 }
711725 mergeResult
712726 }
713727
714728
715729 @Callable(i)
716-func stakeLand () = {
717- let pmt = value(i.payments[0])
718- let assetId = value(pmt.assetId)
719- let address = toString(i.caller)
720- if ((pmt.amount != 1))
721- then throw((("NFT " + LANDPREFIX) + " token should be attached as payment"))
722- else {
723- let asset = value(assetInfo(assetId))
724- if ((asset.issuer != this))
725- then throw("Unknown issuer of token")
726- else if (!(contains(asset.name, LANDPREFIX)))
727- then throw((("Only NFT " + LANDPREFIX) + " tokens are accepted"))
728- else {
729- let landNumSize = drop(asset.name, 4)
730- let landNum = if (contains(landNumSize, "XXL"))
731- then dropRight(landNumSize, 3)
732- else if (contains(landNumSize, "XL"))
733- then dropRight(landNumSize, 2)
734- else dropRight(landNumSize, 1)
735- let landNumInt = valueOrErrorMessage(parseInt(landNum), ("Cannot parse land number from " + asset.name))
736- let landAssetId = toBase58String(assetId)
737- let timeKey = keyStakedTimeByAssetId(landAssetId)
738- if (isDefined(getInteger(timeKey)))
739- then throw((("NFT " + asset.name) + " is already staked"))
740- else {
741- let d = split(asset.description, "_")
742- let terrainCounts = countTerrains(d[recTerrains])
743- let props = updateProportions(terrainCounts, (numPiecesBySize(d[recLandSize]) / 25), 1)
730+func stakeLand () = if ((size(i.payments) != 1))
731+ then throw("Exactly one payment required")
732+ else {
733+ let pmt = value(i.payments[0])
734+ let assetId = value(pmt.assetId)
735+ let address = toString(i.caller)
736+ if ((pmt.amount != 1))
737+ then throw((("NFT " + LANDPREFIX) + " token should be attached as payment"))
738+ else {
739+ let asset = value(assetInfo(assetId))
740+ if ((asset.issuer != this))
741+ then throw("Unknown issuer of token")
742+ else if (!(contains(asset.name, LANDPREFIX)))
743+ then throw((("Only NFT " + LANDPREFIX) + " tokens are accepted"))
744+ else {
745+ let landNumSize = drop(asset.name, 4)
746+ let landNum = if (contains(landNumSize, "XXL"))
747+ then dropRight(landNumSize, 3)
748+ else if (contains(landNumSize, "XL"))
749+ then dropRight(landNumSize, 2)
750+ else dropRight(landNumSize, 1)
751+ if (!(isDefined(parseInt(landNum))))
752+ then throw(("Cannot parse land number from " + asset.name))
753+ else {
754+ let landAssetId = toBase58String(assetId)
755+ let timeKey = keyStakedTimeByAssetId(landAssetId)
756+ if (isDefined(getInteger(timeKey)))
757+ then throw((("NFT " + asset.name) + " is already staked"))
758+ else {
759+ let d = split(asset.description, "_")
760+ let terrainCounts = countTerrains(d[recTerrains])
761+ let props = updateProportions(terrainCounts, (numPiecesBySize(d[recLandSize]) / SSIZE), 1)
744762 [IntegerEntry(timeKey, lastBlock.timestamp), IntegerEntry(keyStakedTimeByTypeAssetIdAndOwner(LANDPREFIX, landAssetId, address), lastBlock.timestamp), StringEntry(keyLandAssetIdToOwner(landAssetId), address), StringEntry(keyLandNumToOwner(landNum), address), StringEntry(keyResProportions(), props)]
745- }
746- }
747- }
748- }
763+ }
764+ }
765+ }
766+ }
767+ }
749768
750769
751770
752771 @Callable(i)
753772 func unstakeLand (landAssetIdStr) = if ((size(i.payments) != 0))
754773 then throw("unstake doesn't require any payments")
755774 else {
756775 let addr = toString(i.caller)
757776 let c = checkClaimConditions(addr)
758777 let terrainCounts = countTerrains(c._3[recTerrains])
759778 let pieces = numPiecesBySize(c._3[recLandSize])
760- let props = updateProportions(terrainCounts, (pieces / 25), -1)
779+ let props = updateProportions(terrainCounts, (pieces / SSIZE), -1)
761780 let claimResult = claimAll(addr, c._2, pieces)
762781 [ScriptTransfer(i.caller, 1, fromBase58String(c._2)), DeleteEntry(keyStakedTimeByAssetId(c._2)), DeleteEntry(keyStakedTimeByTypeAssetIdAndOwner(LANDPREFIX, c._2, addr)), StringEntry(keyResProportions(), props), StringEntry(claimResult._2, makeString(claimResult._3, ":"))]
763782 }
764783
765784
766785
767786 @Callable(i)
768-func stakeDuck () = {
769- let pmt = value(i.payments[0])
770- let assetId = value(pmt.assetId)
771- let address = toString(i.caller)
772- if ((pmt.amount != 1))
773- then throw((("NFT " + DUCKPREFIX) + " token should be attached as payment"))
774- else {
775- let asset = value(assetInfo(assetId))
776- if (if ((asset.issuer != incubatorAddr))
777- then (asset.issuer != breederAddr)
778- else false)
779- then throw((("Unknown issuer of " + DUCKPREFIX) + " token"))
780- else if (!(contains(asset.name, DUCKPREFIX)))
781- then throw((("Only NFT " + DUCKPREFIX) + " tokens are accepted"))
782- else {
783- let assetIdStr = toBase58String(assetId)
784- let timeKey = keyStakedTimeByAssetId(assetIdStr)
785- if (isDefined(getInteger(timeKey)))
786- then throw((("NFT " + asset.name) + " is already staked"))
787- else if (isDefined(getString(keyStakedDuckByOwner(address))))
788- then throw(("You already staked one duck: " + asset.name))
789- else {
790- let locKey = keyDuckLocation(assetIdStr)
791- let location = getString(locKey)
792- let keyHealth = keyDuckHealth(assetIdStr)
793- let health = getInteger(keyHealth)
794- let bpKey = keyBackpackByDuck(assetIdStr)
795- let backpack = getString(bpKey)
796- ([IntegerEntry(timeKey, lastBlock.timestamp), IntegerEntry(keyStakedTimeByTypeAssetIdAndOwner(DUCKPREFIX, toBase58String(assetId), address), lastBlock.timestamp), StringEntry(keyDuckIdToOwner(assetIdStr), address), StringEntry(keyStakedDuckByOwner(address), assetIdStr)] ++ (if (isDefined(location))
797- then nil
798- else ([StringEntry(locKey, DEFAULTLOCATION)] ++ (if (isDefined(health))
787+func stakeDuck () = if ((size(i.payments) != 1))
788+ then throw("Exactly one payment required")
789+ else {
790+ let pmt = value(i.payments[0])
791+ let assetId = value(pmt.assetId)
792+ let address = toString(i.caller)
793+ if ((pmt.amount != 1))
794+ then throw((("NFT " + DUCKPREFIX) + " token should be attached as payment"))
795+ else {
796+ let asset = value(assetInfo(assetId))
797+ if (if ((asset.issuer != incubatorAddr))
798+ then (asset.issuer != breederAddr)
799+ else false)
800+ then throw((("Unknown issuer of " + DUCKPREFIX) + " token"))
801+ else if (!(contains(asset.name, DUCKPREFIX)))
802+ then throw((("Only NFT " + DUCKPREFIX) + " tokens are accepted"))
803+ else {
804+ let assetIdStr = toBase58String(assetId)
805+ let timeKey = keyStakedTimeByAssetId(assetIdStr)
806+ if (isDefined(getInteger(timeKey)))
807+ then throw((("NFT " + asset.name) + " is already staked"))
808+ else if (isDefined(getString(keyStakedDuckByOwner(address))))
809+ then throw(("You already staked one duck: " + asset.name))
810+ else {
811+ let locKey = keyDuckLocation(assetIdStr)
812+ let location = getString(locKey)
813+ let bpKey = keyBackpackByDuck(assetIdStr)
814+ let backpack = getString(bpKey)
815+ ([IntegerEntry(timeKey, lastBlock.timestamp), IntegerEntry(keyStakedTimeByTypeAssetIdAndOwner(DUCKPREFIX, toBase58String(assetId), address), lastBlock.timestamp), StringEntry(keyDuckIdToOwner(assetIdStr), address), StringEntry(keyStakedDuckByOwner(address), assetIdStr)] ++ (if (isDefined(location))
799816 then nil
800- else ([IntegerEntry(keyHealth, 100)] ++ (if (isDefined(backpack))
817+ else ([StringEntry(locKey, DEFAULTLOCATION)] ++ (if (isDefined(backpack))
801818 then nil
802- else [StringEntry(bpKey, "0:0_0_0_0_0_0:0_0_0_0_0_0:")]))))))
803- }
804- }
805- }
806- }
819+ else ([StringEntry(bpKey, "0:0_0_0_0_0_0:0_0_0_0_0_0:")] :+ IntegerEntry(keyDuckHealth(assetIdStr), 100))))))
820+ }
821+ }
822+ }
823+ }
807824
808825
809826
810827 @Callable(i)
811828 func unstakeDuck (assetIdStr) = if ((size(i.payments) != 0))
812829 then throw("unstake doesn't require any payments")
813830 else {
814831 let assetId = fromBase58String(assetIdStr)
815832 let address = toString(i.caller)
816833 let asset = value(assetInfo(assetId))
817- if (if ((asset.issuer != incubatorAddr))
818- then (asset.issuer != breederAddr)
819- else false)
820- then throw((("Unknown issuer of " + DUCKPREFIX) + " token"))
821- else if (!(contains(asset.name, DUCKPREFIX)))
822- then throw((("Only NFT " + DUCKPREFIX) + " tokens can be unstaked"))
834+ let timeKey = keyStakedTimeByAssetId(toBase58String(assetId))
835+ if (!(isDefined(timeKey)))
836+ then throw((("NFT " + asset.name) + " is not staked"))
837+ else if (!(isDefined(keyStakedDuckByOwner(address))))
838+ then throw((("The duck " + asset.name) + " is not staked"))
823839 else {
824- let timeKey = keyStakedTimeByAssetId(toBase58String(assetId))
825- if (!(isDefined(timeKey)))
826- then throw((("NFT " + asset.name) + " is not staked"))
827- else if (!(isDefined(keyStakedDuckByOwner(address))))
828- then throw((("The duck " + asset.name) + " is not staked"))
829- else {
830- let owner = valueOrErrorMessage(getString(keyDuckIdToOwner(toBase58String(assetId))), (("NFT " + asset.name) + " is orphaned"))
831- if ((owner != address))
832- then throw("Staked NFT is not yours")
833- else [ScriptTransfer(i.caller, 1, assetId), DeleteEntry(timeKey), DeleteEntry(keyDuckLocation(assetIdStr)), DeleteEntry(keyDuckIdToOwner(assetIdStr)), DeleteEntry(keyStakedTimeByTypeAssetIdAndOwner(DUCKPREFIX, assetIdStr, address)), DeleteEntry(keyStakedDuckByOwner(address))]
834- }
840+ let owner = valueOrErrorMessage(getString(keyDuckIdToOwner(toBase58String(assetId))), (("NFT " + asset.name) + " is orphaned"))
841+ if ((owner != address))
842+ then throw("Staked NFT is not yours")
843+ else {
844+ let keyHealth = keyDuckHealth(assetIdStr)
845+ let health = getInteger(keyHealth)
846+ if ((health != 100))
847+ then throw("Please heal your duck before unstaking")
848+ else [ScriptTransfer(i.caller, 1, assetId), DeleteEntry(timeKey), DeleteEntry(keyHealth), DeleteEntry(keyDuckLocation(assetIdStr)), DeleteEntry(keyDuckIdToOwner(assetIdStr)), DeleteEntry(keyStakedTimeByTypeAssetIdAndOwner(DUCKPREFIX, assetIdStr, address)), DeleteEntry(keyStakedDuckByOwner(address))]
849+ }
835850 }
836851 }
837852
838853
839854
840855 @Callable(i)
841856 func claimRes (amount,landAssetIdStr) = if ((size(i.payments) != 0))
842857 then throw("claimRes doesn't require any payments")
843858 else {
844859 let addr = toString(i.originCaller)
845860 let result = claimResInternal(addr, amount)
846861 $Tuple2((result._1 :+ StringEntry(result._2, makeString(result._3, ":"))), result._3[bpIdxRes])
847862 }
848863
849864
850865
851866 @Callable(i)
852867 func flight (message,sig) = if (!(sigVerify_8Kb(message, sig, pub)))
853868 then throw("signature does not match")
854869 else if ((size(i.payments) != 0))
855870 then throw("flight doesn't require any payments")
856871 else {
857872 let parts = split(toUtf8String(message), ";")
858873 let hp = split(split(parts[0], "|")[0], "_")
859874 let curHP = parseIntValue(hp[0])
860875 let newHP = parseIntValue(hp[1])
861876 let newLocAndTime = split(parts[1], ":")
862877 let newLocation = newLocAndTime[0]
863878 let time = parseIntValue(newLocAndTime[1])
864879 if (if ((time > (lastBlock.timestamp + FIVEMINUTESMILLIS)))
865880 then true
866881 else ((lastBlock.timestamp - FIVEMINUTESMILLIS) > time))
867882 then throw("signature outdated")
868883 else {
869884 let duckAssetId = valueOrErrorMessage(getString(keyStakedDuckByOwner(toString(i.caller))), "You don't have a duck staked")
870885 let keyHealth = keyDuckHealth(duckAssetId)
871886 let oldFromState = valueOrElse(getInteger(keyHealth), 100)
872887 if ((oldFromState != curHP))
873888 then throw(((("oldHealth=" + toString(valueOrElse(getInteger(keyHealth), 100))) + " from state does not match one from flight log=") + toString(curHP)))
874889 else if ((0 >= curHP))
875890 then throw("You can't fly with zero health")
876891 else {
877892 let locKey = keyDuckLocation(duckAssetId)
878893 let curLocation = valueOrElse(getString(locKey), DEFAULTLOCATION)
879894 if ((newLocation == curLocation))
880895 then throw("You can't fly to the same location")
881896 else $Tuple2([StringEntry(locKey, if ((newHP > 0))
882897 then newLocation
883898 else curLocation), IntegerEntry(keyHealth, newHP)], unit)
884899 }
885900 }
886901 }
887902
888903
889904
890905 @Callable(i)
891906 func setHealth (health,duckAssetId) = if (if ((0 > health))
892907 then true
893908 else (health > 100))
894909 then throw("HP should be within 0..100")
895910 else [IntegerEntry(keyDuckHealth(duckAssetId), health)]
896911
897912
898913
899914 @Callable(i)
900915 func heal (matType,amount) = if (if ((0 > matType))
901916 then true
902917 else (matType >= NUMRES))
903918 then throw(("Unknown material: " + toString(matType)))
904919 else if ((0 >= amount))
905920 then throw(("Amount should be positive! " + toString(amount)))
906921 else {
907922 let duckAssetId = valueOrErrorMessage(getString(keyStakedDuckByOwner(toString(i.caller))), "You don't have a duck staked")
908923 let keyHealth = keyDuckHealth(duckAssetId)
909924 let oldHealth = valueOrElse(getInteger(keyHealth), 100)
910925 if ((oldHealth >= 100))
911926 then throw("HP should be < 100 to heal")
912927 else {
913928 let bpKey = keyBackpackByDuck(duckAssetId)
914929 let currentPack = getBackpack(bpKey)
915930 let mList = split(currentPack[bpIdxMat], "_")
916931 let currentAmount = parseIntValue(mList[matType])
917932 let deltaHealth = min([(amount / HEALCOST), (100 - oldHealth)])
918933 let spendAmount = (deltaHealth * HEALCOST)
919934 if ((spendAmount > currentAmount))
920935 then throw(((((("You need " + toString(spendAmount)) + " of ") + matTypes[matType]) + " to heal, but you backpack contains ") + toString(currentAmount)))
921936 else {
922937 let newMat = subOneInList(mList, matType, spendAmount)
923938 [IntegerEntry(keyHealth, (oldHealth + deltaHealth)), StringEntry(bpKey, makeString([currentPack[bpIdxLevel], currentPack[bpIdxRes], newMat, currentPack[bpIdxProd]], ":"))]
924939 }
925940 }
926941 }
927942
928943
929944
930945 @Callable(i)
931946 func updateBackpack (duckAssetId,newPack) = if ((i.caller != economyAddr))
932947 then throw("permission denied")
933948 else $Tuple2([StringEntry(keyBackpackByDuck(duckAssetId), newPack)], newPack)
934949
935950
936951
937952 @Callable(i)
938953 func expeditionBuy (message,sig) = if ((size(i.payments) != 1))
939954 then throw("Exactly one payment required")
940955 else {
941956 let pmt = value(i.payments[0])
942957 if ((pmt.assetId != usdnAssetId))
943958 then throw("Allowed USDN payment only!")
944959 else if ((pmt.amount != EXPUSDN))
945960 then throw(("Payment attached should be " + toString(EXPUSDN)))
946961 else {
947962 let result = expeditionCommon(false, i.caller, i.transactionId, message, sig)
948- $Tuple2((result._1 :+ ScriptTransfer(economyAddr, pmt.amount, usdnAssetId)), result._2)
963+ if ((result._2 == ""))
964+ then result
965+ else $Tuple2((result._1 :+ ScriptTransfer(economyAddr, pmt.amount, usdnAssetId)), result._2)
949966 }
950967 }
951968
952969
953970
954971 @Callable(i)
955972 func expedition (message,sig) = if ((size(i.payments) != 0))
956973 then throw("expedition doesn't require any payments")
957974 else expeditionCommon(true, i.caller, i.transactionId, message, sig)
958975
959976
960977
961978 @Callable(i)
962979 func upgradeInfra (landAssetIdIgnored) = if ((size(i.payments) != 0))
963980 then throw("Infrastructure upgrade doesn't require any payments")
964981 else upInfraCommon(true, i.caller, 0)
965982
966983
967984
968985 @Callable(i)
969986 func upgradeInfraUsdn (landAssetIdIgnored) = if ((size(i.payments) != 1))
970987 then throw("Exactly one payment required")
971988 else {
972989 let pmt = value(i.payments[0])
973990 if ((pmt.assetId != usdnAssetId))
974991 then throw("Allowed USDN payment only!")
975992 else {
976993 let result = upInfraCommon(false, i.caller, pmt.amount)
977994 $Tuple2((result._1 :+ ScriptTransfer(economyAddr, pmt.amount, usdnAssetId)), result._2)
978995 }
979996 }
980997
981998
982999
9831000 @Callable(i)
9841001 func activateArtifact (artName) = if ((size(i.payments) != 0))
9851002 then throw("Artifact activation doesn't require any payments")
9861003 else {
9871004 let result = match artName {
9881005 case _ =>
9891006 if (("PRESALE" == $match0))
9901007 then activatePresaleArt(toString(i.caller))
9911008 else throw("Unknown artifact")
9921009 }
9931010 result
9941011 }
9951012
9961013
9971014
9981015 @Callable(i)
9991016 func mergeLands (landAssetIds) = if ((size(i.payments) != 0))
10001017 then throw("Lands merging doesn't require any payments")
10011018 else mergeCommon(true, toString(i.caller), 0, landAssetIds, i.transactionId)
10021019
10031020
10041021
10051022 @Callable(i)
10061023 func mergeLandsUsdn (landAssetIds) = if ((size(i.payments) != 1))
10071024 then throw("Exactly one payment required")
10081025 else {
10091026 let pmt = value(i.payments[0])
10101027 if ((pmt.assetId != usdnAssetId))
10111028 then throw("Allowed USDN payment only!")
10121029 else {
10131030 let result = mergeCommon(false, toString(i.caller), pmt.amount, landAssetIds, i.transactionId)
10141031 $Tuple2((result._1 :+ ScriptTransfer(economyAddr, pmt.amount, usdnAssetId)), result._2)
10151032 }
10161033 }
10171034
10181035

github/deemru/w8io/169f3d6 
118.69 ms