tx · 1W7obizLaGvWBdXZfEaubk2K6eiBT59GaidPXP8kUwC

3NDCyBG5q85JuaRiigUeEtainyjCQT3XpZm:  -0.02400000 Waves

2023.01.03 00:14 [2387871] smart account 3NDCyBG5q85JuaRiigUeEtainyjCQT3XpZm > SELF 0.00000000 Waves

{ "type": 13, "id": "1W7obizLaGvWBdXZfEaubk2K6eiBT59GaidPXP8kUwC", "fee": 2400000, "feeAssetId": null, "timestamp": 1672694052800, "version": 2, "chainId": 84, "sender": "3NDCyBG5q85JuaRiigUeEtainyjCQT3XpZm", "senderPublicKey": "EVooykMNV691Venwp1dHUTBd7KWequzUcda57Wd3LQEX", "proofs": [ "58qphyjcb7BQ946h8JKtf8PPdG1xgR9YtXaLWdYpSeHwyWz4XzQLFNyWcTsHYTbQawijBzBY6stATEhibsFMvDVx" ], "script": "base64:BgJECAISABIDCgEIEgASAwoBCBIECgIBCBIECgICAhIECgIBCBIECgIBARIECgIICBIECgICAhIECgICAhIDCgEIEgMKAQhGAAVjaGFpbgkAsAkBCQDJAQIJAMoBAggFBHRoaXMFYnl0ZXMAAQABAAt1c2RuQXNzZXRJZAQHJG1hdGNoMAUFY2hhaW4DCQAAAgIBVwUHJG1hdGNoMAEgtiYpwwT1zlORpA5LdSQvZIxRsfrfr1QpvUjSHSqyqtEDCQAAAgIBVAUHJG1hdGNoMAEg93bq9/eDymXbbhPuAjvPWCmVqcHRjfJL2mzYHWKAyN4JAAIBAg1Vbmtub3duIGNoYWluAA1pbmN1YmF0b3JBZGRyBAckbWF0Y2gwBQVjaGFpbgMJAAACAgFXBQckbWF0Y2gwCQERQGV4dHJOYXRpdmUoMTA2MikBAiMzUEVrdFZ1eDJSaGNoU042M0RzRG80YjRtejRRcXpLU2VEdgMJAAACAgFUBQckbWF0Y2gwBQR0aGlzCQACAQINVW5rbm93biBjaGFpbgALYnJlZWRlckFkZHIEByRtYXRjaDAFBWNoYWluAwkAAAICAVcFByRtYXRjaDAJARFAZXh0ck5hdGl2ZSgxMDYyKQECIzNQRFZ1VTQ1SDdFaDVkbXROYm5STlJTdEd3VUxBN05ZNkhiAwkAAAICAVQFByRtYXRjaDAFBHRoaXMJAAIBAg1Vbmtub3duIGNoYWluAAtlY29ub215QWRkcgQHJG1hdGNoMAUFY2hhaW4DCQAAAgIBVwUHJG1hdGNoMAkBEUBleHRyTmF0aXZlKDEwNjIpAQIjM1Ayc2sxS25jU3hSYVpzOGI0Q1dHUHcyamt2dmF2NzR1NEQDCQAAAgIBVAUHJG1hdGNoMAkBEUBleHRyTmF0aXZlKDEwNjIpAQIjM044eTR3eFgzSkM0VGRyQ0pCWFgxNlNqV2Y2WDI1NmhyZXAJAAIBAg1Vbmtub3duIGNoYWluAANwdWIBIE9T4ho/VKjWnVJOEx1GJ1W9s1PzLHvJVFSw/0PBtBQoAAhIRUFMQ09TVACQTgAKTEFORFBSRUZJWAIETEFORAAKRFVDS1BSRUZJWAIERFVDSwAPREVGQVVMVExPQ0FUSU9OAg9BZnJpY2FfRl9BZnJpY2EABk5VTVJFUwAGAA9EQUlMWVJFU0JZUElFQ0UAgPjSAQAJREFZTUlMTElTAIC4mSkAEUZJVkVNSU5VVEVTTUlMTElTAOCnEgAQUkVTT1VSQ0VQUklDRU1JTgDV1gkAEUluZnJhVXBncmFkZUNvc3RTBAckbWF0Y2gwBQVjaGFpbgMJAAACAgFXBQckbWF0Y2gwANHCwr5GAwkAAAICAVQFByRtYXRjaDAA0OmcWgkAAgECDVVua25vd24gY2hhaW4AFUluZnJhVXBncmFkZUNvc3RTVXNkbgQHJG1hdGNoMAUFY2hhaW4DCQAAAgIBVwUHJG1hdGNoMACAnJw5AwkAAAICAVQFByRtYXRjaDAAgJ9JCQACAQINVW5rbm93biBjaGFpbgAMRVhQTUFURVJJQUxTBAckbWF0Y2gwBQVjaGFpbgMJAAACAgFXBQckbWF0Y2gwAMuA1bPLBAMJAAACAgFUBQckbWF0Y2gwAPGa8O8FCQACAQINVW5rbm93biBjaGFpbgAHRVhQVVNETgQHJG1hdGNoMAUFY2hhaW4DCQAAAgIBVwUHJG1hdGNoMACAlOvcAwMJAAACAgFUBQckbWF0Y2gwAICt4gQJAAIBAg1Vbmtub3duIGNoYWluAB1QcmVzYWxlQXJ0aWZhY3RBY3RpdmF0aW9uVGltZQQHJG1hdGNoMAUFY2hhaW4DCQAAAgIBVwUHJG1hdGNoMACAmLX12DADCQAAAgIBVAUHJG1hdGNoMACAuM/Q1zAJAAIBAg1Vbmtub3duIGNoYWluAAVNVUxUNgDAhD0ABUZJVkVYCQC2AgEABQAHVFdFTlRZWAkAtgIBABQACFRXRU5UWTJYCQC2AgEJAGgCABQAFAAIVFdFTlRZM1gJALYCAQkAaAIJAGgCABQAFAAUAAhUV0VOVFk0WAkAtgIBCQBoAgkAaAIJAGgCABQAFAAUABQACFRXRU5UWTVYCQC2AgEJAGgCCQBoAgkAaAIJAGgCABQAFAAUABQAFAAIbWF0VHlwZXMJAMwIAgIERnVlbAkAzAgCAgVNZXRhbAkAzAgCAgVQbGFuawkAzAgCAgVHbGFzcwkAzAgCAgdQbGFzdGljCQDMCAICB1Byb3RlaW4FA25pbAAKY29udGluZW50cwkAzAgCAgRBc2lhCQDMCAICBkV1cm9wZQkAzAgCAghBbWVyaWNhcwkAzAgCAgdPY2VhbmlhCQDMCAICBkFmcmljYQUDbmlsARJrZXlOZXh0RnJlZUxhbmROdW0AAgtuZXh0TGFuZE51bQEQa2V5TGFuZFRvQXNzZXRJZAEHbGFuZE51bQkArAICAgxsYW5kVG9Bc3NldF8FB2xhbmROdW0BCmtleU5mdE5hbWUCB2xhbmROdW0IbGFuZFNpemUJAKwCAgkArAICBQpMQU5EUFJFRklYBQdsYW5kTnVtBQhsYW5kU2l6ZQEVa2V5TGFuZEFzc2V0SWRUb093bmVyAQdhc3NldElkCQCsAgICCW5mdE93bmVyXwUHYXNzZXRJZAEQa2V5RHVja0lkVG9Pd25lcgEHYXNzZXRJZAkArAICAgpkdWNrT3duZXJfBQdhc3NldElkARZrZXlTdGFrZWRUaW1lQnlBc3NldElkAQdhc3NldElkCQCsAgICC3N0YWtlZFRpbWVfBQdhc3NldElkARZrZXlJbmZyYUxldmVsQnlBc3NldElkAQdhc3NldElkCQCsAgICC2luZnJhTGV2ZWxfBQdhc3NldElkAR9rZXlwcmVzYWxlQXJ0QWN0aXZhdGVkQnlBc3NldElkAQdhc3NldElkCQCsAgICFHByZXNhbGVBcnRBY3RpdmF0ZWRfBQdhc3NldElkARRrZXlTdGFrZWREdWNrQnlPd25lcgEJb3duZXJBZGRyCQCsAgICEnN0YWtlZER1Y2tCeU93bmVyXwUJb3duZXJBZGRyASJrZXlTdGFrZWRUaW1lQnlUeXBlQXNzZXRJZEFuZE93bmVyAwduZnRUeXBlB2Fzc2V0SWQJb3duZXJBZGRyCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgIgc3Rha2VkVGltZUJ5VHlwZUFzc2V0SWRBbmRPd25lcl8FB25mdFR5cGUCAV8FB2Fzc2V0SWQCAV8FCW93bmVyQWRkcgERa2V5TGFuZE51bVRvT3duZXIBB2xhbmROdW0JAKwCAgIKbGFuZE93bmVyXwUHbGFuZE51bQERa2V5QmFja3BhY2tCeUR1Y2sBC2R1Y2tBc3NldElkCQCsAgICCWJhY2tQYWNrXwULZHVja0Fzc2V0SWQBD2tleUR1Y2tMb2NhdGlvbgELZHVja0Fzc2V0SWQJAKwCAgINZHVja0xvY2F0aW9uXwULZHVja0Fzc2V0SWQBDWtleUR1Y2tIZWFsdGgBC2R1Y2tBc3NldElkCQCsAgICC2R1Y2tIZWFsdGhfBQtkdWNrQXNzZXRJZAERa2V5UmVzUHJvcG9ydGlvbnMAAhNyZXNUeXBlc1Byb3BvcnRpb25zAApyZWNMYW5kTnVtAAAAC3JlY0xhbmRTaXplAAEAC3JlY1RlcnJhaW5zAAIADHJlY0NvbnRpbmVudAADAA9sb2NJZHhDb250aW5lbnQAAAAKbG9jSWR4VHlwZQABAAhsb2NJZHhJZAACAApicElkeExldmVsAAAACGJwSWR4UmVzAAEACGJwSWR4TWF0AAIACWJwSWR4UHJvZAADAQhhc1N0cmluZwEBdgQHJG1hdGNoMAUBdgMJAAECBQckbWF0Y2gwAgZTdHJpbmcEAXMFByRtYXRjaDAFAXMJAAIBAhhmYWlsIHRvIGNhc3QgaW50byBTdHJpbmcBEmdldE5lZWRlZE1hdGVyaWFscwEFdG90YWwEBXByb3BzCQC1CQIJAQV2YWx1ZQEJAKIIAQkBEWtleVJlc1Byb3BvcnRpb25zAAIBXwMJAQIhPQIJAJADAQUFcHJvcHMFBk5VTVJFUwkAAgECFldyb25nIHByb3BvcnRpb25zIGRhdGEEAXIJAMwIAgkBDXBhcnNlSW50VmFsdWUBCQCRAwIFBXByb3BzAAAJAMwIAgkBDXBhcnNlSW50VmFsdWUBCQCRAwIFBXByb3BzAAEJAMwIAgkBDXBhcnNlSW50VmFsdWUBCQCRAwIFBXByb3BzAAIJAMwIAgkBDXBhcnNlSW50VmFsdWUBCQCRAwIFBXByb3BzAAMJAMwIAgkBDXBhcnNlSW50VmFsdWUBCQCRAwIFBXByb3BzAAQJAMwIAgkBDXBhcnNlSW50VmFsdWUBCQCRAwIFBXByb3BzAAUFA25pbAQDc3VtCQBkAgkAZAIJAGQCCQBkAgkAZAIJAJEDAgUBcgAACQCRAwIFAXIAAQkAkQMCBQFyAAIJAJEDAgUBcgADCQCRAwIFAXIABAkAkQMCBQFyAAUDCQBnAgAABQNzdW0JAAIBAg9ObyBsYW5kcyBzdGFrZWQEBW5vcm02CQBrAwUFdG90YWwFBU1VTFQ2BQNzdW0KAQpub3JtYWxpemVyAgNhY2MEZWxlbQkAzQgCBQNhY2MJAGsDBQRlbGVtBQVub3JtNgUFTVVMVDYKAAIkbAUBcgoAAiRzCQCQAwEFAiRsCgAFJGFjYzAFA25pbAoBBSRmMF8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQEKbm9ybWFsaXplcgIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmMF8yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQITTGlzdCBzaXplIGV4Y2VlZHMgNgkBBSRmMF8yAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgUFJGFjYzAAAAABAAIAAwAEAAUABgERc3VidHJhY3RNYXRlcmlhbHMDDHNob3VsZFVzZU1hdANoYXMJdG90YWxOZWVkBARuZWVkCQESZ2V0TmVlZGVkTWF0ZXJpYWxzAQUJdG90YWxOZWVkCgEKc3VidHJhY3RvcgIDYWNjA2lkeAQGcmVzdWx0CQBlAgkBDXBhcnNlSW50VmFsdWUBCQCRAwIFA2hhcwUDaWR4CQCRAwIFBG5lZWQFA2lkeAMJAGYCAAAFBnJlc3VsdAkAAgEJAKwCAgkArAICCQCsAgIJAKwCAgkArAICAhhOb3QgZW5vdWdoIG1hdGVyaWFsIGlkeD0JAKQDAQUDaWR4AgssIHlvdSBoYXZlIAkAkQMCBQNoYXMFA2lkeAILLCBidXQgbmVlZCAJAKQDAQkAkQMCBQRuZWVkBQNpZHgJAM0IAgUDYWNjCQCkAwEFBnJlc3VsdAMFDHNob3VsZFVzZU1hdAoAAiRsCQDMCAIAAAkAzAgCAAEJAMwIAgACCQDMCAIAAwkAzAgCAAQJAMwIAgAFBQNuaWwKAAIkcwkAkAMBBQIkbAoABSRhY2MwBQNuaWwKAQUkZjBfMQICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkBCnN1YnRyYWN0b3ICBQIkYQkAkQMCBQIkbAUCJGkKAQUkZjBfMgICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkAAgECE0xpc3Qgc2l6ZSBleGNlZWRzIDYJAQUkZjBfMgIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYFA2hhcwERdXBkYXRlUHJvcG9ydGlvbnMDDXRlcnJhaW5Db3VudHMNbGFuZFNpemVJbmRleARzaWduBAVwcm9wcwkAtQkCCQELdmFsdWVPckVsc2UCCQCiCAEJARFrZXlSZXNQcm9wb3J0aW9ucwACCzBfMF8wXzBfMF8wAgFfAwkBAiE9AgkAkAMBBQVwcm9wcwUGTlVNUkVTCQACAQIWV3JvbmcgcHJvcG9ydGlvbnMgZGF0YQoBB3VwZGF0ZXICA2FjYwFpBAZyZXN1bHQJAGQCCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUFcHJvcHMFAWkJAGgCCQBoAgUEc2lnbgkAkQMCBQ10ZXJyYWluQ291bnRzBQFpBQ1sYW5kU2l6ZUluZGV4AwkAZgIAAAUGcmVzdWx0CQACAQkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICAhZQYW5pYyEgUGllY2VzIG9mIHR5cGU9CQCkAwEFAWkCBywgc2lnbj0JAKQDAQUEc2lnbgIULCAgdGVycmFpbkNvdW50c1tpXT0JAKQDAQkAkQMCBQ10ZXJyYWluQ291bnRzBQFpAhAsIGxhbmRTaXplSW5kZXg9CQCkAwEFDWxhbmRTaXplSW5kZXgJAM0IAgUDYWNjCQCkAwEFBnJlc3VsdAQBcgoAAiRsCQDMCAIAAAkAzAgCAAEJAMwIAgACCQDMCAIAAwkAzAgCAAQJAMwIAgAFBQNuaWwKAAIkcwkAkAMBBQIkbAoABSRhY2MwBQNuaWwKAQUkZjBfMQICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkBB3VwZGF0ZXICBQIkYQkAkQMCBQIkbAUCJGkKAQUkZjBfMgICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkAAgECE0xpc3Qgc2l6ZSBleGNlZWRzIDYJAQUkZjBfMgIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYJALkJAgUBcgIBXwENY291bnRUZXJyYWlucwEIdGVycmFpbnMJAMwIAgkAZQIJAJADAQkAtQkCBQh0ZXJyYWlucwIBQQABCQDMCAIJAGUCCQCQAwEJALUJAgUIdGVycmFpbnMCAUIAAQkAzAgCCQBlAgkAkAMBCQC1CQIFCHRlcnJhaW5zAgFDAAEJAMwIAgkAZQIJAJADAQkAtQkCBQh0ZXJyYWlucwIBRAABCQDMCAIJAGUCCQCQAwEJALUJAgUIdGVycmFpbnMCAUUAAQkAzAgCCQBlAgkAkAMBCQC1CQIFCHRlcnJhaW5zAgFGAAEFA25pbAEPbnVtUGllY2VzQnlTaXplAQhsYW5kU2l6ZQQHJG1hdGNoMAUIbGFuZFNpemUDCQAAAgIBUwUHJG1hdGNoMAAZAwkAAAICAU0FByRtYXRjaDAAZAMJAAACAgFMBQckbWF0Y2gwAOEBAwkAAAICAlhMBQckbWF0Y2gwAJADAwkAAAICA1hYTAUHJG1hdGNoMADxBAkAAgECEVVua25vd24gbGFuZCBzaXplAQxzdWJPbmVJbkxpc3QDBWFMaXN0A2lkeAZhbW91bnQKAQZzdWJiZXICA2FjYwFpCQDNCAIFA2FjYwMJAAACBQFpBQNpZHgJAKQDAQkAZQIJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQVhTGlzdAUBaQUGYW1vdW50CQCRAwIFBWFMaXN0BQFpBAFyCgACJGwJAMwIAgAACQDMCAIAAQkAzAgCAAIJAMwIAgADCQDMCAIABAkAzAgCAAUFA25pbAoAAiRzCQCQAwEFAiRsCgAFJGFjYzAFA25pbAoBBSRmMF8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQEGc3ViYmVyAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGYwXzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhNMaXN0IHNpemUgZXhjZWVkcyA2CQEFJGYwXzICCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECBQUkYWNjMAAAAAEAAgADAAQABQAGCQC5CQIFAXICAV8BBmFkZFJlcwUKY3VycmVudFJlcw10ZXJyYWluQ291bnRzCWRlbHRhVGltZQ1sYW5kU2l6ZUluZGV4F2RhaWx5QnlQaWVjZVdpdGhCb251c2VzCgEFYWRkZXICA2FjYwFpBAlyZXNPZlR5cGUJAGgCCQBoAgkAawMFCWRlbHRhVGltZQUXZGFpbHlCeVBpZWNlV2l0aEJvbnVzZXMFCURBWU1JTExJUwkAkQMCBQ10ZXJyYWluQ291bnRzBQFpBQ1sYW5kU2l6ZUluZGV4CQDNCAIFA2FjYwkApAMBCQBkAgkBDXBhcnNlSW50VmFsdWUBCQCRAwIFCmN1cnJlbnRSZXMFAWkFCXJlc09mVHlwZQQBcgoAAiRsCQDMCAIAAAkAzAgCAAEJAMwIAgACCQDMCAIAAwkAzAgCAAQJAMwIAgAFBQNuaWwKAAIkcwkAkAMBBQIkbAoABSRhY2MwBQNuaWwKAQUkZjBfMQICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkBBWFkZGVyAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGYwXzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhNMaXN0IHNpemUgZXhjZWVkcyA2CQEFJGYwXzICCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECBQUkYWNjMAAAAAEAAgADAAQABQAGCQC5CQIFAXICAV8BA2FicwEBeAMJAMACAgUBeAkAtgIBAAAFAXgJAL4CAQUBeAAEZnJlcQkAzAgCCQDMCAIAAQkAzAgCAAQJAMwIAgAJCQDMCAIACgkAzAgCAA8FA25pbAkAzAgCCQDMCAIABQkAzAgCAAgJAMwIAgANCQDMCAIADgkAzAgCAA8FA25pbAkAzAgCCQDMCAIABgkAzAgCAAkJAMwIAgAOCQDMCAIADwkAzAgCABAFA25pbAkAzAgCCQDMCAIABAkAzAgCAAcJAMwIAgAICQDMCAIADQkAzAgCABIFA25pbAkAzAgCCQDMCAIAAQkAzAgCAAYJAMwIAgAHCQDMCAIADwkAzAgCABMFA25pbAUDbmlsAQdnZW5DaGFyAgFuBWZyZXFzBANyZW0JAKADAQkAuwICBQFuBQdUV0VOVFlYBAZsZXR0ZXIDCQBmAgkAkQMCBQVmcmVxcwAABQNyZW0CAUEDCQBmAgkAkQMCBQVmcmVxcwABBQNyZW0CAUIDCQBmAgkAkQMCBQVmcmVxcwACBQNyZW0CAUMDCQBmAgkAkQMCBQVmcmVxcwADBQNyZW0CAUQDCQBmAgkAkQMCBQVmcmVxcwAEBQNyZW0CAUUCAUYFBmxldHRlcgELZ2V0QmFja3BhY2sBBWJwS2V5BAFwCQC1CQIJAQt2YWx1ZU9yRWxzZQIJAKIIAQUFYnBLZXkCGjA6MF8wXzBfMF8wXzA6MF8wXzBfMF8wXzA6AgE6CQDMCAIJAKQDAQkBC3ZhbHVlT3JFbHNlAgkAtgkBCQCRAwIFAXAFCmJwSWR4TGV2ZWwAAAkAzAgCAwkAAAIJAJADAQkAtQkCCQCRAwIFAXAFCGJwSWR4UmVzAgFfBQZOVU1SRVMJAJEDAgUBcAUIYnBJZHhSZXMCCzBfMF8wXzBfMF8wCQDMCAIDCQAAAgkAkAMBCQC1CQIJAJEDAgUBcAUIYnBJZHhNYXQCAV8FBk5VTVJFUwkAkQMCBQFwBQhicElkeE1hdAILMF8wXzBfMF8wXzAJAMwIAgkAkQMCBQFwBQlicElkeFByb2QFA25pbAEQZXhwZWRpdGlvbkNvbW1vbgUMc2hvdWxkVXNlTWF0BmNhbGxlcgR0eElkB21lc3NhZ2UDc2lnAwkBASEBCQDEEwMFB21lc3NhZ2UFA3NpZwUDcHViCQACAQIYc2lnbmF0dXJlIGRvZXMgbm90IG1hdGNoBAVwYXJ0cwkAtQkCCQCwCQEFB21lc3NhZ2UCATsEAmhwCQC1CQIJAJEDAgkAtQkCCQCRAwIFBXBhcnRzAAACAXwAAAIBXwQFY3VySFAJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQJocAAABAVuZXdIUAkBDXBhcnNlSW50VmFsdWUBCQCRAwIFAmhwAAEECmxvY0FuZFRpbWUJALUJAgkAkQMCBQVwYXJ0cwABAgE6BA50YXJnZXRMb2NhdGlvbgkAtQkCCQCRAwIFCmxvY0FuZFRpbWUAAAIBXwMJAQIhPQIJAJEDAgUOdGFyZ2V0TG9jYXRpb24AAQIBRQkAAgECK2V4cGVkaXRpb24gdGFyZ2V0IGxvY2F0aW9uIHR5cGUgc2hvdWxkIGJlIEUEBHRpbWUJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQpsb2NBbmRUaW1lAAEDAwkAZgIFBHRpbWUJAGQCCAUJbGFzdEJsb2NrCXRpbWVzdGFtcAURRklWRU1JTlVURVNNSUxMSVMGCQBmAgkAZQIIBQlsYXN0QmxvY2sJdGltZXN0YW1wBRFGSVZFTUlOVVRFU01JTExJUwUEdGltZQkAAgECEnNpZ25hdHVyZSBvdXRkYXRlZAQIdXNlckFkZHIJAKUIAQUGY2FsbGVyBAtkdWNrQXNzZXRJZAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCiCAEJARRrZXlTdGFrZWREdWNrQnlPd25lcgEFCHVzZXJBZGRyAhxZb3UgZG9uJ3QgaGF2ZSBhIGR1Y2sgc3Rha2VkBAlrZXlIZWFsdGgJAQ1rZXlEdWNrSGVhbHRoAQULZHVja0Fzc2V0SWQEDG9sZEZyb21TdGF0ZQkBC3ZhbHVlT3JFbHNlAgkAnwgBBQlrZXlIZWFsdGgAZAMJAQIhPQIFDG9sZEZyb21TdGF0ZQUFY3VySFAJAAIBCQCsAgIJAKwCAgkArAICAgpvbGRIZWFsdGg9CQCkAwEJAQt2YWx1ZU9yRWxzZQIJAJ8IAQUJa2V5SGVhbHRoAGQCLyBmcm9tIHN0YXRlIGRvZXMgbm90IG1hdGNoIG9uZSBmcm9tIGZsaWdodCBsb2c9CQCkAwEFBWN1ckhQAwkAZwIAAAUFY3VySFAJAAIBAh5Zb3UgY2FuJ3QgZmx5IHdpdGggemVybyBoZWFsdGgDCQBnAgAABQVuZXdIUAkAAgECK1lvdXIgZHVjayBoZWFsdGggaXMgemVybywgZXhwZWRpdGlvbiBmYWlsZWQEBWJwS2V5CQERa2V5QmFja3BhY2tCeUR1Y2sBBQtkdWNrQXNzZXRJZAQLY3VycmVudFBhY2sJAQtnZXRCYWNrcGFjawEFBWJwS2V5BAVtTGlzdAkAtQkCCQCRAwIFC2N1cnJlbnRQYWNrBQhicElkeE1hdAIBXwQGbmV3TWF0CQC5CQIJARFzdWJ0cmFjdE1hdGVyaWFscwMFDHNob3VsZFVzZU1hdAUFbUxpc3QFDEVYUE1BVEVSSUFMUwIBXwQGYmlnTnVtCQEDYWJzAQkAngMBBQR0eElkBAdmcmVlTnVtCQELdmFsdWVPckVsc2UCCQCfCAEJARJrZXlOZXh0RnJlZUxhbmROdW0AAPUDBAdsYW5kTnVtCQCkAwEFB2ZyZWVOdW0EDGNvbnRpbmVudElkeAkAoAMBCQC7AgIFBmJpZ051bQUFRklWRVgEAWYJAJEDAgUEZnJlcQUMY29udGluZW50SWR4CgEQdGVycmFpbkdlbmVyYXRvcgIDYWNjBGVsZW0JAJQKAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIIBQNhY2MCXzEJAQdnZW5DaGFyAggFA2FjYwJfMgUBZgkBB2dlbkNoYXICCQC6AgIIBQNhY2MCXzIFB1RXRU5UWVgFAWYJAQdnZW5DaGFyAgkAugICCAUDYWNjAl8yBQhUV0VOVFkyWAUBZgkBB2dlbkNoYXICCQC6AgIIBQNhY2MCXzIFCFRXRU5UWTNYBQFmCQEHZ2VuQ2hhcgIJALoCAggFA2FjYwJfMgUIVFdFTlRZNFgFAWYJALoCAggFA2FjYwJfMgUIVFdFTlRZNVgEAXQKAAIkbAkAzAgCAAEJAMwIAgACCQDMCAIAAwkAzAgCAAQJAMwIAgAFBQNuaWwKAAIkcwkAkAMBBQIkbAoABSRhY2MwCQCUCgICAAkAugICBQZiaWdOdW0FBUZJVkVYCgEFJGYwXzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJARB0ZXJyYWluR2VuZXJhdG9yAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGYwXzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhNMaXN0IHNpemUgZXhjZWVkcyA1CQEFJGYwXzICCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECBQUkYWNjMAAAAAEAAgADAAQABQQJY29udGluZW50CQCRAwIFCmNvbnRpbmVudHMFDGNvbnRpbmVudElkeAQFaXNzdWUJAMIIBQkBCmtleU5mdE5hbWUCBQdsYW5kTnVtAgFTCQC5CQIJAMwIAgUHbGFuZE51bQkAzAgCAgFTCQDMCAIIBQF0Al8xCQDMCAIFCWNvbnRpbmVudAUDbmlsAgFfAAEAAAcEB2Fzc2V0SWQJALgIAQUFaXNzdWUEAmlkCQDYBAEFB2Fzc2V0SWQJAJQKAgkAzAgCCQEMSW50ZWdlckVudHJ5AgkBEmtleU5leHRGcmVlTGFuZE51bQAJAGQCBQdmcmVlTnVtAAEJAMwIAgUFaXNzdWUJAMwIAgkBC1N0cmluZ0VudHJ5AgkBEGtleUxhbmRUb0Fzc2V0SWQBBQdsYW5kTnVtBQJpZAkAzAgCCQELU3RyaW5nRW50cnkCCQEVa2V5TGFuZEFzc2V0SWRUb093bmVyAQUCaWQFCHVzZXJBZGRyCQDMCAIJAQtTdHJpbmdFbnRyeQIJARFrZXlMYW5kTnVtVG9Pd25lcgEFB2xhbmROdW0FCHVzZXJBZGRyCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEWa2V5SW5mcmFMZXZlbEJ5QXNzZXRJZAEFAmlkAAAJAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwUGY2FsbGVyAAEFB2Fzc2V0SWQJAMwIAgkBC1N0cmluZ0VudHJ5AgkBD2tleUR1Y2tMb2NhdGlvbgEFC2R1Y2tBc3NldElkCQC5CQIJAMwIAgUJY29udGluZW50CQDMCAICAUwJAMwIAgUCaWQFA25pbAIBXwkAzAgCCQEMSW50ZWdlckVudHJ5AgUJa2V5SGVhbHRoBQVuZXdIUAkAzAgCCQELU3RyaW5nRW50cnkCBQVicEtleQkAuQkCCQDMCAIJAJEDAgULY3VycmVudFBhY2sFCmJwSWR4TGV2ZWwJAMwIAgkAkQMCBQtjdXJyZW50UGFjawUIYnBJZHhSZXMJAMwIAgUGbmV3TWF0CQDMCAIJAJEDAgULY3VycmVudFBhY2sFCWJwSWR4UHJvZAUDbmlsAgE6BQNuaWwFBHVuaXQBDXVwSW5mcmFDb21tb24DDHNob3VsZFVzZU1hdAZjYWxsZXILbGFuZEFzc2V0SWQEBGFkZHIJAKUIAQUGY2FsbGVyBAhpbmZyYUtleQkBFmtleUluZnJhTGV2ZWxCeUFzc2V0SWQBBQtsYW5kQXNzZXRJZAQIY3VyTGV2ZWwJAQt2YWx1ZU9yRWxzZQIJAJ8IAQUIaW5mcmFLZXkAAAMJAGcCBQhjdXJMZXZlbAADCQACAQImQ3VycmVudGx5IG1heCBpbmZyYXN0cnVjdHVyZSBsZXZlbCA9IDMECG5ld0xldmVsCQBkAgUIY3VyTGV2ZWwAAQQFYXNzZXQJAQV2YWx1ZQEJAOwHAQkA2QQBBQtsYW5kQXNzZXRJZAMJAQEhAQkBCGNvbnRhaW5zAggFBWFzc2V0BG5hbWUFCkxBTkRQUkVGSVgJAAIBCQCsAgIJAKwCAgIETkZUIAUKTEFORFBSRUZJWAIgIHRva2VuIHNob3VsZCBiZSBwYXNzZWQgYXMgcGFyYW0EB3RpbWVLZXkJARZrZXlTdGFrZWRUaW1lQnlBc3NldElkAQULbGFuZEFzc2V0SWQEBW93bmVyCQERQGV4dHJOYXRpdmUoMTA1OCkBCQEVa2V5TGFuZEFzc2V0SWRUb093bmVyAQULbGFuZEFzc2V0SWQDCQECIT0CBQVvd25lcgUEYWRkcgkAAgEJAKwCAgUKTEFORFBSRUZJWAINIGlzIG5vdCB5b3VycwQBZAkAtQkCCAUFYXNzZXQLZGVzY3JpcHRpb24CAV8ECGxhbmRTaXplCQCRAwIFAWQFC3JlY0xhbmRTaXplBAZwaWVjZXMJAQ9udW1QaWVjZXNCeVNpemUBBQhsYW5kU2l6ZQQLZHVja0Fzc2V0SWQJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAoggBCQEUa2V5U3Rha2VkRHVja0J5T3duZXIBBQRhZGRyAhxZb3UgZG9uJ3QgaGF2ZSBhIGR1Y2sgc3Rha2VkBAtjdXJMb2NhdGlvbgkBC3ZhbHVlT3JFbHNlAgkAoggBCQEPa2V5RHVja0xvY2F0aW9uAQULZHVja0Fzc2V0SWQFD0RFRkFVTFRMT0NBVElPTgQDbG9jCQC1CQIJAQV2YWx1ZQEFC2N1ckxvY2F0aW9uAgFfAwkBAiE9AgkAkQMCBQNsb2MFCmxvY0lkeFR5cGUCAUwJAAIBCQCsAgIJAKwCAgIWRHVjayBsb2NhdGlvbiB0eXBlIGlzIAkAkQMCBQNsb2MFCmxvY0lkeFR5cGUCESwgYnV0IHNob3VsZCBiZSBMAwkBAiE9AgkAkQMCBQNsb2MFCGxvY0lkeElkBQtsYW5kQXNzZXRJZAkAAgEJAKwCAgkArAICCQCsAgICFER1Y2sgbG9jYXRpb24gaWQgaXMgCQCRAwIFA2xvYwUIbG9jSWR4SWQCECwgYnV0IHNob3VsZCBiZSAFC2xhbmRBc3NldElkBAVicEtleQkBEWtleUJhY2twYWNrQnlEdWNrAQULZHVja0Fzc2V0SWQEC2N1cnJlbnRQYWNrCQELZ2V0QmFja3BhY2sBBQVicEtleQQFbUxpc3QJALUJAgkAkQMCBQtjdXJyZW50UGFjawUIYnBJZHhNYXQCAV8EBm5ld01hdAkAuQkCCQERc3VidHJhY3RNYXRlcmlhbHMDBQxzaG91bGRVc2VNYXQFBW1MaXN0CQBrAwURSW5mcmFVcGdyYWRlQ29zdFMJAGgCBQZwaWVjZXMFCG5ld0xldmVsABkCAV8ECXNhdmVkVGltZQkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCfCAEFB3RpbWVLZXkJAKwCAgkArAICAgRORlQgCAUFYXNzZXQEbmFtZQIOIGlzIG5vdCBzdGFrZWQECWRlbHRhVGltZQkAZQIIBQlsYXN0QmxvY2sJdGltZXN0YW1wBQlzYXZlZFRpbWUDCQBmAgAABQlkZWx0YVRpbWUJAAIBCQCsAgIJAKwCAgkArAICAiZTYXZlZCB0aW1lc3RhbXAgaXMgaW4gZnV0dXJlLCBzYXZlZCA9IAkApAMBBQlzYXZlZFRpbWUCDCwgY3VycmVudCA9IAkApAMBCAUJbGFzdEJsb2NrCXRpbWVzdGFtcAQIYXZhaWxSZXMJAGgCCQBrAwUJZGVsdGFUaW1lBQ9EQUlMWVJFU0JZUElFQ0UFCURBWU1JTExJUwUGcGllY2VzBAZuZXdSZXMJAQhhc1N0cmluZwEJAPwHBAUEdGhpcwIIY2xhaW1SZXMJAMwIAgUIYXZhaWxSZXMJAMwIAgULbGFuZEFzc2V0SWQFA25pbAUDbmlsCQCUCgIJAMwIAgkBDEludGVnZXJFbnRyeQIFCGluZnJhS2V5BQhuZXdMZXZlbAkAzAgCCQELU3RyaW5nRW50cnkCBQVicEtleQkAuQkCCQDMCAIJAJEDAgULY3VycmVudFBhY2sFCmJwSWR4TGV2ZWwJAMwIAgUGbmV3UmVzCQDMCAIFBm5ld01hdAkAzAgCCQCRAwIFC2N1cnJlbnRQYWNrBQlicElkeFByb2QFA25pbAIBOgUDbmlsBQhuZXdMZXZlbAEMYXBwbHlCb251c2VzAQtsYW5kQXNzZXRJZAQKaW5mcmFMZXZlbAkBC3ZhbHVlT3JFbHNlAgkAnwgBCQEWa2V5SW5mcmFMZXZlbEJ5QXNzZXRJZAEFC2xhbmRBc3NldElkAAAEDHByZXNhbGVCb251cwMJAQt2YWx1ZU9yRWxzZQIJAKAIAQkBH2tleXByZXNhbGVBcnRBY3RpdmF0ZWRCeUFzc2V0SWQBBQtsYW5kQXNzZXRJZAcAAwAACQBkAgkAZAIFD0RBSUxZUkVTQllQSUVDRQkAawMFD0RBSUxZUkVTQllQSUVDRQUKaW5mcmFMZXZlbAAECQBrAwUPREFJTFlSRVNCWVBJRUNFBQxwcmVzYWxlQm9udXMAFA0BaQEJc3Rha2VMYW5kAAQDcG10CQEFdmFsdWUBCQCRAwIIBQFpCHBheW1lbnRzAAAEB2Fzc2V0SWQJAQV2YWx1ZQEIBQNwbXQHYXNzZXRJZAQHYWRkcmVzcwkApQgBCAUBaQZjYWxsZXIDCQECIT0CCAUDcG10BmFtb3VudAABCQACAQkArAICCQCsAgICBE5GVCAFCkxBTkRQUkVGSVgCJCB0b2tlbiBzaG91bGQgYmUgYXR0YWNoZWQgYXMgcGF5bWVudAQFYXNzZXQJAQV2YWx1ZQEJAOwHAQUHYXNzZXRJZAMJAQIhPQIIBQVhc3NldAZpc3N1ZXIFBHRoaXMJAAIBAhdVbmtub3duIGlzc3VlciBvZiB0b2tlbgMJAQEhAQkBCGNvbnRhaW5zAggFBWFzc2V0BG5hbWUFCkxBTkRQUkVGSVgJAAIBCQCsAgIJAKwCAgIJT25seSBORlQgBQpMQU5EUFJFRklYAhQgdG9rZW5zIGFyZSBhY2NlcHRlZAQLbGFuZE51bVNpemUJALACAggFBWFzc2V0BG5hbWUABAQHbGFuZE51bQMJAQhjb250YWlucwIFC2xhbmROdW1TaXplAgNYWEwJALMCAgULbGFuZE51bVNpemUAAwMJAQhjb250YWlucwIFC2xhbmROdW1TaXplAgJYTAkAswICBQtsYW5kTnVtU2l6ZQACCQCzAgIFC2xhbmROdW1TaXplAAEECmxhbmROdW1JbnQJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAtgkBBQdsYW5kTnVtCQCsAgICHkNhbm5vdCBwYXJzZSBsYW5kIG51bWJlciBmcm9tIAgFBWFzc2V0BG5hbWUEC2xhbmRBc3NldElkCQDYBAEFB2Fzc2V0SWQEB3RpbWVLZXkJARZrZXlTdGFrZWRUaW1lQnlBc3NldElkAQULbGFuZEFzc2V0SWQDCQEJaXNEZWZpbmVkAQkAnwgBBQd0aW1lS2V5CQACAQkArAICCQCsAgICBE5GVCAIBQVhc3NldARuYW1lAhIgaXMgYWxyZWFkeSBzdGFrZWQEAWQJALUJAggFBWFzc2V0C2Rlc2NyaXB0aW9uAgFfBA10ZXJyYWluQ291bnRzCQENY291bnRUZXJyYWlucwEJAJEDAgUBZAULcmVjVGVycmFpbnMEBXByb3BzCQERdXBkYXRlUHJvcG9ydGlvbnMDBQ10ZXJyYWluQ291bnRzCQBpAgkBD251bVBpZWNlc0J5U2l6ZQEJAJEDAgUBZAULcmVjTGFuZFNpemUAGQABBA1wcmVzYWxlQWN0aXZlAwkAZwIA9AMFCmxhbmROdW1JbnQJAGYCCAUJbGFzdEJsb2NrCXRpbWVzdGFtcAUdUHJlc2FsZUFydGlmYWN0QWN0aXZhdGlvblRpbWUHCQDMCAIJAQxJbnRlZ2VyRW50cnkCBQd0aW1lS2V5CAUJbGFzdEJsb2NrCXRpbWVzdGFtcAkAzAgCCQEMQm9vbGVhbkVudHJ5AgkBH2tleXByZXNhbGVBcnRBY3RpdmF0ZWRCeUFzc2V0SWQBBQtsYW5kQXNzZXRJZAUNcHJlc2FsZUFjdGl2ZQkAzAgCCQEMSW50ZWdlckVudHJ5AgkBImtleVN0YWtlZFRpbWVCeVR5cGVBc3NldElkQW5kT3duZXIDBQpMQU5EUFJFRklYBQtsYW5kQXNzZXRJZAUHYWRkcmVzcwgFCWxhc3RCbG9jawl0aW1lc3RhbXAJAMwIAgkBC1N0cmluZ0VudHJ5AgkBFWtleUxhbmRBc3NldElkVG9Pd25lcgEFC2xhbmRBc3NldElkBQdhZGRyZXNzCQDMCAIJAQtTdHJpbmdFbnRyeQIJARFrZXlMYW5kTnVtVG9Pd25lcgEFB2xhbmROdW0FB2FkZHJlc3MJAMwIAgkBC1N0cmluZ0VudHJ5AgkBEWtleVJlc1Byb3BvcnRpb25zAAUFcHJvcHMFA25pbAFpAQt1bnN0YWtlTGFuZAELbGFuZEFzc2V0SWQDCQECIT0CCQCQAwEIBQFpCHBheW1lbnRzAAAJAAIBAiR1bnN0YWtlIGRvZXNuJ3QgcmVxdWlyZSBhbnkgcGF5bWVudHMEB2Fzc2V0SWQJANkEAQULbGFuZEFzc2V0SWQEB2FkZHJlc3MJAKUIAQgFAWkGY2FsbGVyBAVhc3NldAkBBXZhbHVlAQkA7AcBBQdhc3NldElkAwkBAiE9AggFBWFzc2V0Bmlzc3VlcgUEdGhpcwkAAgECF1Vua25vd24gaXNzdWVyIG9mIHRva2VuAwkBASEBCQEIY29udGFpbnMCCAUFYXNzZXQEbmFtZQUKTEFORFBSRUZJWAkAAgEJAKwCAgkArAICAglPbmx5IE5GVCAFCkxBTkRQUkVGSVgCFyB0b2tlbnMgY2FuIGJlIHVuc3Rha2VkBAd0aW1lS2V5CQEWa2V5U3Rha2VkVGltZUJ5QXNzZXRJZAEFC2xhbmRBc3NldElkAwkBASEBCQEJaXNEZWZpbmVkAQUHdGltZUtleQkAAgEJAKwCAgkArAICAgRORlQgCAUFYXNzZXQEbmFtZQIOIGlzIG5vdCBzdGFrZWQEBW93bmVyCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKIIAQkBFWtleUxhbmRBc3NldElkVG9Pd25lcgEFC2xhbmRBc3NldElkCQCsAgIJAKwCAgIETkZUIAgFBWFzc2V0BG5hbWUCDCBpcyBvcnBoYW5lZAMJAQIhPQIFBW93bmVyBQdhZGRyZXNzCQACAQIXU3Rha2VkIE5GVCBpcyBub3QgeW91cnMEAWQJALUJAggFBWFzc2V0C2Rlc2NyaXB0aW9uAgFfBA10ZXJyYWluQ291bnRzCQENY291bnRUZXJyYWlucwEJAJEDAgUBZAULcmVjVGVycmFpbnMEBXByb3BzCQERdXBkYXRlUHJvcG9ydGlvbnMDBQ10ZXJyYWluQ291bnRzCQBpAgkBD251bVBpZWNlc0J5U2l6ZQEJAJEDAgUBZAULcmVjTGFuZFNpemUAGQD///////////8BCQDMCAIJAQ5TY3JpcHRUcmFuc2ZlcgMIBQFpBmNhbGxlcgABBQdhc3NldElkCQDMCAIJAQtEZWxldGVFbnRyeQEFB3RpbWVLZXkJAMwIAgkBC0RlbGV0ZUVudHJ5AQkBImtleVN0YWtlZFRpbWVCeVR5cGVBc3NldElkQW5kT3duZXIDBQpMQU5EUFJFRklYBQtsYW5kQXNzZXRJZAUHYWRkcmVzcwkAzAgCCQELU3RyaW5nRW50cnkCCQERa2V5UmVzUHJvcG9ydGlvbnMABQVwcm9wcwUDbmlsAWkBCXN0YWtlRHVjawAEA3BtdAkBBXZhbHVlAQkAkQMCCAUBaQhwYXltZW50cwAABAdhc3NldElkCQEFdmFsdWUBCAUDcG10B2Fzc2V0SWQEB2FkZHJlc3MJAKUIAQgFAWkGY2FsbGVyAwkBAiE9AggFA3BtdAZhbW91bnQAAQkAAgEJAKwCAgkArAICAgRORlQgBQpEVUNLUFJFRklYAiQgdG9rZW4gc2hvdWxkIGJlIGF0dGFjaGVkIGFzIHBheW1lbnQEBWFzc2V0CQEFdmFsdWUBCQDsBwEFB2Fzc2V0SWQDAwkBAiE9AggFBWFzc2V0Bmlzc3VlcgUNaW5jdWJhdG9yQWRkcgkBAiE9AggFBWFzc2V0Bmlzc3VlcgULYnJlZWRlckFkZHIHCQACAQkArAICCQCsAgICElVua25vd24gaXNzdWVyIG9mIAUKRFVDS1BSRUZJWAIGIHRva2VuAwkBASEBCQEIY29udGFpbnMCCAUFYXNzZXQEbmFtZQUKRFVDS1BSRUZJWAkAAgEJAKwCAgkArAICAglPbmx5IE5GVCAFCkRVQ0tQUkVGSVgCFCB0b2tlbnMgYXJlIGFjY2VwdGVkBAphc3NldElkU3RyCQDYBAEFB2Fzc2V0SWQEB3RpbWVLZXkJARZrZXlTdGFrZWRUaW1lQnlBc3NldElkAQUKYXNzZXRJZFN0cgMJAQlpc0RlZmluZWQBCQCfCAEFB3RpbWVLZXkJAAIBCQCsAgIJAKwCAgIETkZUIAgFBWFzc2V0BG5hbWUCEiBpcyBhbHJlYWR5IHN0YWtlZAMJAQlpc0RlZmluZWQBCQCiCAEJARRrZXlTdGFrZWREdWNrQnlPd25lcgEFB2FkZHJlc3MJAAIBCQCsAgICHVlvdSBhbHJlYWR5IHN0YWtlZCBvbmUgZHVjazogCAUFYXNzZXQEbmFtZQQGbG9jS2V5CQEPa2V5RHVja0xvY2F0aW9uAQUKYXNzZXRJZFN0cgQIbG9jYXRpb24JAKIIAQUGbG9jS2V5BAlrZXlIZWFsdGgJAQ1rZXlEdWNrSGVhbHRoAQUKYXNzZXRJZFN0cgQGaGVhbHRoCQCfCAEFCWtleUhlYWx0aAQFYnBLZXkJARFrZXlCYWNrcGFja0J5RHVjawEFCmFzc2V0SWRTdHIECGJhY2twYWNrCQCiCAEFBWJwS2V5CQDOCAIJAMwIAgkBDEludGVnZXJFbnRyeQIFB3RpbWVLZXkIBQlsYXN0QmxvY2sJdGltZXN0YW1wCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEia2V5U3Rha2VkVGltZUJ5VHlwZUFzc2V0SWRBbmRPd25lcgMFCkRVQ0tQUkVGSVgJANgEAQUHYXNzZXRJZAUHYWRkcmVzcwgFCWxhc3RCbG9jawl0aW1lc3RhbXAJAMwIAgkBC1N0cmluZ0VudHJ5AgkBEGtleUR1Y2tJZFRvT3duZXIBBQphc3NldElkU3RyBQdhZGRyZXNzCQDMCAIJAQtTdHJpbmdFbnRyeQIJARRrZXlTdGFrZWREdWNrQnlPd25lcgEFB2FkZHJlc3MFCmFzc2V0SWRTdHIFA25pbAMJAQlpc0RlZmluZWQBBQhsb2NhdGlvbgUDbmlsCQDOCAIJAMwIAgkBC1N0cmluZ0VudHJ5AgUGbG9jS2V5BQ9ERUZBVUxUTE9DQVRJT04FA25pbAMJAQlpc0RlZmluZWQBBQZoZWFsdGgFA25pbAkAzggCCQDMCAIJAQxJbnRlZ2VyRW50cnkCBQlrZXlIZWFsdGgAZAUDbmlsAwkBCWlzRGVmaW5lZAEFCGJhY2twYWNrBQNuaWwJAMwIAgkBC1N0cmluZ0VudHJ5AgUFYnBLZXkCGjA6MF8wXzBfMF8wXzA6MF8wXzBfMF8wXzA6BQNuaWwBaQELdW5zdGFrZUR1Y2sBCmFzc2V0SWRTdHIDCQECIT0CCQCQAwEIBQFpCHBheW1lbnRzAAAJAAIBAiR1bnN0YWtlIGRvZXNuJ3QgcmVxdWlyZSBhbnkgcGF5bWVudHMEB2Fzc2V0SWQJANkEAQUKYXNzZXRJZFN0cgQHYWRkcmVzcwkApQgBCAUBaQZjYWxsZXIEBWFzc2V0CQEFdmFsdWUBCQDsBwEFB2Fzc2V0SWQDAwkBAiE9AggFBWFzc2V0Bmlzc3VlcgUNaW5jdWJhdG9yQWRkcgkBAiE9AggFBWFzc2V0Bmlzc3VlcgULYnJlZWRlckFkZHIHCQACAQkArAICCQCsAgICElVua25vd24gaXNzdWVyIG9mIAUKRFVDS1BSRUZJWAIGIHRva2VuAwkBASEBCQEIY29udGFpbnMCCAUFYXNzZXQEbmFtZQUKRFVDS1BSRUZJWAkAAgEJAKwCAgkArAICAglPbmx5IE5GVCAFCkRVQ0tQUkVGSVgCFyB0b2tlbnMgY2FuIGJlIHVuc3Rha2VkBAd0aW1lS2V5CQEWa2V5U3Rha2VkVGltZUJ5QXNzZXRJZAEJANgEAQUHYXNzZXRJZAMJAQEhAQkBCWlzRGVmaW5lZAEFB3RpbWVLZXkJAAIBCQCsAgIJAKwCAgIETkZUIAgFBWFzc2V0BG5hbWUCDiBpcyBub3Qgc3Rha2VkAwkBASEBCQEJaXNEZWZpbmVkAQkBFGtleVN0YWtlZER1Y2tCeU93bmVyAQUHYWRkcmVzcwkAAgEJAKwCAgkArAICAglUaGUgZHVjayAIBQVhc3NldARuYW1lAg4gaXMgbm90IHN0YWtlZAQFb3duZXIJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAoggBCQEQa2V5RHVja0lkVG9Pd25lcgEJANgEAQUHYXNzZXRJZAkArAICCQCsAgICBE5GVCAIBQVhc3NldARuYW1lAgwgaXMgb3JwaGFuZWQDCQECIT0CBQVvd25lcgUHYWRkcmVzcwkAAgECF1N0YWtlZCBORlQgaXMgbm90IHlvdXJzCQDMCAIJAQ5TY3JpcHRUcmFuc2ZlcgMIBQFpBmNhbGxlcgABBQdhc3NldElkCQDMCAIJAQtEZWxldGVFbnRyeQEFB3RpbWVLZXkJAMwIAgkBC0RlbGV0ZUVudHJ5AQkBD2tleUR1Y2tMb2NhdGlvbgEFCmFzc2V0SWRTdHIJAMwIAgkBC0RlbGV0ZUVudHJ5AQkBImtleVN0YWtlZFRpbWVCeVR5cGVBc3NldElkQW5kT3duZXIDBQpEVUNLUFJFRklYBQphc3NldElkU3RyBQdhZGRyZXNzCQDMCAIJAQtEZWxldGVFbnRyeQEJARRrZXlTdGFrZWREdWNrQnlPd25lcgEFB2FkZHJlc3MFA25pbAFpAQhjbGFpbVJlcwIGYW1vdW50C2xhbmRBc3NldElkAwkBAiE9AgkAkAMBCAUBaQhwYXltZW50cwAACQACAQIlY2xhaW1SZXMgZG9lc24ndCByZXF1aXJlIGFueSBwYXltZW50cwQEYWRkcgkApQgBCAUBaQxvcmlnaW5DYWxsZXIEBWFzc2V0CQEFdmFsdWUBCQDsBwEJANkEAQULbGFuZEFzc2V0SWQDCQEBIQEJAQhjb250YWlucwIIBQVhc3NldARuYW1lBQpMQU5EUFJFRklYCQACAQkArAICCQCsAgICBE5GVCAFCkxBTkRQUkVGSVgCICB0b2tlbiBzaG91bGQgYmUgcGFzc2VkIGFzIHBhcmFtBAd0aW1lS2V5CQEWa2V5U3Rha2VkVGltZUJ5QXNzZXRJZAEFC2xhbmRBc3NldElkBAVvd25lcgkBEUBleHRyTmF0aXZlKDEwNTgpAQkBFWtleUxhbmRBc3NldElkVG9Pd25lcgEFC2xhbmRBc3NldElkAwkBAiE9AgUFb3duZXIFBGFkZHIJAAIBCQCsAgIFCkxBTkRQUkVGSVgCDSBpcyBub3QgeW91cnMEAWQJALUJAggFBWFzc2V0C2Rlc2NyaXB0aW9uAgFfBAhsYW5kU2l6ZQkAkQMCBQFkBQtyZWNMYW5kU2l6ZQQNdGVycmFpbkNvdW50cwkBDWNvdW50VGVycmFpbnMBCQCRAwIFAWQFC3JlY1RlcnJhaW5zBAtkdWNrQXNzZXRJZAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCiCAEJARRrZXlTdGFrZWREdWNrQnlPd25lcgEFBGFkZHICHFlvdSBkb24ndCBoYXZlIGEgZHVjayBzdGFrZWQEC2N1ckxvY2F0aW9uCQELdmFsdWVPckVsc2UCCQCiCAEJAQ9rZXlEdWNrTG9jYXRpb24BBQtkdWNrQXNzZXRJZAUPREVGQVVMVExPQ0FUSU9OBANsb2MJALUJAgkBBXZhbHVlAQULY3VyTG9jYXRpb24CAV8DCQECIT0CCQCRAwIFA2xvYwUKbG9jSWR4VHlwZQIBTAkAAgEJAKwCAgkArAICAhZEdWNrIGxvY2F0aW9uIHR5cGUgaXMgCQCRAwIFA2xvYwUKbG9jSWR4VHlwZQIRLCBidXQgc2hvdWxkIGJlIEwDCQECIT0CCQCRAwIFA2xvYwUIbG9jSWR4SWQFC2xhbmRBc3NldElkCQACAQkArAICCQCsAgIJAKwCAgIURHVjayBsb2NhdGlvbiBpZCBpcyAJAJEDAgUDbG9jBQhsb2NJZHhJZAIQLCBidXQgc2hvdWxkIGJlIAULbGFuZEFzc2V0SWQECXNhdmVkVGltZQkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCfCAEFB3RpbWVLZXkJAKwCAgkArAICAgRORlQgCAUFYXNzZXQEbmFtZQIOIGlzIG5vdCBzdGFrZWQECWRlbHRhVGltZQkAZQIIBQlsYXN0QmxvY2sJdGltZXN0YW1wBQlzYXZlZFRpbWUDCQBmAgAABQlkZWx0YVRpbWUJAAIBCQCsAgIJAKwCAgkArAICAiZTYXZlZCB0aW1lc3RhbXAgaXMgaW4gZnV0dXJlLCBzYXZlZCA9IAkApAMBBQlzYXZlZFRpbWUCDCwgY3VycmVudCA9IAkApAMBCAUJbGFzdEJsb2NrCXRpbWVzdGFtcAQGcGllY2VzCQEPbnVtUGllY2VzQnlTaXplAQUIbGFuZFNpemUEFmRhaWx5UHJvZHVjdGlvbkJ5UGllY2UJAQxhcHBseUJvbnVzZXMBBQtsYW5kQXNzZXRJZAQIYXZhaWxSZXMJAGsDBQlkZWx0YVRpbWUJAGgCBRZkYWlseVByb2R1Y3Rpb25CeVBpZWNlBQZwaWVjZXMFCURBWU1JTExJUwMJAGYCBQZhbW91bnQFCGF2YWlsUmVzCQACAQkArAICCQCsAgIJAKwCAgIiTm90IGVub3VnaCByZXNvdXJjZXMsIGF2YWlsYWJsZSA9IAkApAMBBQhhdmFpbFJlcwIOLCByZXF1ZXN0ZWQgPSAJAKQDAQUGYW1vdW50BAxuZXdEZWx0YVRpbWUJAGsDCQBlAgUIYXZhaWxSZXMFBmFtb3VudAUJREFZTUlMTElTCQBoAgUWZGFpbHlQcm9kdWN0aW9uQnlQaWVjZQUGcGllY2VzBAxuZXdUaW1lc3RhbXAJAGUCCAUJbGFzdEJsb2NrCXRpbWVzdGFtcAUMbmV3RGVsdGFUaW1lBAVicEtleQkBEWtleUJhY2twYWNrQnlEdWNrAQULZHVja0Fzc2V0SWQEC2N1cnJlbnRQYWNrCQELZ2V0QmFja3BhY2sBBQVicEtleQQKY3VycmVudFJlcwkAtQkCCQCRAwIFC2N1cnJlbnRQYWNrBQhicElkeFJlcwIBXwQFYnBSZXMJAQZhZGRSZXMFBQpjdXJyZW50UmVzBQ10ZXJyYWluQ291bnRzCQBlAgUJZGVsdGFUaW1lBQxuZXdEZWx0YVRpbWUJAGkCBQZwaWVjZXMAGQUWZGFpbHlQcm9kdWN0aW9uQnlQaWVjZQQHbmV3UGFjawkAuQkCCQDMCAIJAJEDAgULY3VycmVudFBhY2sFCmJwSWR4TGV2ZWwJAMwIAgUFYnBSZXMJAMwIAgkAkQMCBQtjdXJyZW50UGFjawUIYnBJZHhNYXQJAMwIAgkAkQMCBQtjdXJyZW50UGFjawUJYnBJZHhQcm9kBQNuaWwCAToJAJQKAgkAzAgCCQELU3RyaW5nRW50cnkCBQVicEtleQUHbmV3UGFjawkAzAgCCQEMSW50ZWdlckVudHJ5AgUHdGltZUtleQUMbmV3VGltZXN0YW1wCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEia2V5U3Rha2VkVGltZUJ5VHlwZUFzc2V0SWRBbmRPd25lcgMFCkxBTkRQUkVGSVgFC2xhbmRBc3NldElkBQVvd25lcgUMbmV3VGltZXN0YW1wBQNuaWwFBWJwUmVzAWkBBmZsaWdodAIHbWVzc2FnZQNzaWcDCQEBIQEJAMQTAwUHbWVzc2FnZQUDc2lnBQNwdWIJAAIBAhhzaWduYXR1cmUgZG9lcyBub3QgbWF0Y2gDCQECIT0CCQCQAwEIBQFpCHBheW1lbnRzAAAJAAIBAiNmbGlnaHQgZG9lc24ndCByZXF1aXJlIGFueSBwYXltZW50cwQFcGFydHMJALUJAgkAsAkBBQdtZXNzYWdlAgE7BAJocAkAtQkCCQCRAwIJALUJAgkAkQMCBQVwYXJ0cwAAAgF8AAACAV8EBWN1ckhQCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUCaHAAAAQFbmV3SFAJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQJocAABBA1uZXdMb2NBbmRUaW1lCQC1CQIJAJEDAgUFcGFydHMAAQIBOgQLbmV3TG9jYXRpb24JAJEDAgUNbmV3TG9jQW5kVGltZQAABAR0aW1lCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUNbmV3TG9jQW5kVGltZQABAwMJAGYCBQR0aW1lCQBkAggFCWxhc3RCbG9jawl0aW1lc3RhbXAFEUZJVkVNSU5VVEVTTUlMTElTBgkAZgIJAGUCCAUJbGFzdEJsb2NrCXRpbWVzdGFtcAURRklWRU1JTlVURVNNSUxMSVMFBHRpbWUJAAIBAhJzaWduYXR1cmUgb3V0ZGF0ZWQEC2R1Y2tBc3NldElkCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKIIAQkBFGtleVN0YWtlZER1Y2tCeU93bmVyAQkApQgBCAUBaQZjYWxsZXICHFlvdSBkb24ndCBoYXZlIGEgZHVjayBzdGFrZWQECWtleUhlYWx0aAkBDWtleUR1Y2tIZWFsdGgBBQtkdWNrQXNzZXRJZAQMb2xkRnJvbVN0YXRlCQELdmFsdWVPckVsc2UCCQCfCAEFCWtleUhlYWx0aABkAwkBAiE9AgUMb2xkRnJvbVN0YXRlBQVjdXJIUAkAAgEJAKwCAgkArAICCQCsAgICCm9sZEhlYWx0aD0JAKQDAQkBC3ZhbHVlT3JFbHNlAgkAnwgBBQlrZXlIZWFsdGgAZAIvIGZyb20gc3RhdGUgZG9lcyBub3QgbWF0Y2ggb25lIGZyb20gZmxpZ2h0IGxvZz0JAKQDAQUFY3VySFADCQBnAgAABQVjdXJIUAkAAgECHllvdSBjYW4ndCBmbHkgd2l0aCB6ZXJvIGhlYWx0aAQGbG9jS2V5CQEPa2V5RHVja0xvY2F0aW9uAQULZHVja0Fzc2V0SWQEC2N1ckxvY2F0aW9uCQELdmFsdWVPckVsc2UCCQCiCAEFBmxvY0tleQUPREVGQVVMVExPQ0FUSU9OAwkAAAIFC25ld0xvY2F0aW9uBQtjdXJMb2NhdGlvbgkAAgECIllvdSBjYW4ndCBmbHkgdG8gdGhlIHNhbWUgbG9jYXRpb24JAJQKAgkAzAgCCQELU3RyaW5nRW50cnkCBQZsb2NLZXkDCQBmAgUFbmV3SFAAAAULbmV3TG9jYXRpb24FC2N1ckxvY2F0aW9uCQDMCAIJAQxJbnRlZ2VyRW50cnkCBQlrZXlIZWFsdGgFBW5ld0hQBQNuaWwFBHVuaXQBaQEJc2V0SGVhbHRoAgZoZWFsdGgLZHVja0Fzc2V0SWQDAwkAZgIAAAUGaGVhbHRoBgkAZgIFBmhlYWx0aABkCQACAQIaSFAgc2hvdWxkIGJlIHdpdGhpbiAwLi4xMDAJAMwIAgkBDEludGVnZXJFbnRyeQIJAQ1rZXlEdWNrSGVhbHRoAQULZHVja0Fzc2V0SWQFBmhlYWx0aAUDbmlsAWkBBGhlYWwCB21hdFR5cGUGYW1vdW50AwMJAGYCAAAFB21hdFR5cGUGCQBnAgUHbWF0VHlwZQUGTlVNUkVTCQACAQkArAICAhJVbmtub3duIG1hdGVyaWFsOiAJAKQDAQUHbWF0VHlwZQMJAGcCAAAFBmFtb3VudAkAAgEJAKwCAgIbQW1vdW50IHNob3VsZCBiZSBwb3NpdGl2ZSEgCQCkAwEFBmFtb3VudAQLZHVja0Fzc2V0SWQJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAoggBCQEUa2V5U3Rha2VkRHVja0J5T3duZXIBCQClCAEIBQFpBmNhbGxlcgIcWW91IGRvbid0IGhhdmUgYSBkdWNrIHN0YWtlZAQJa2V5SGVhbHRoCQENa2V5RHVja0hlYWx0aAEFC2R1Y2tBc3NldElkBAlvbGRIZWFsdGgJAQt2YWx1ZU9yRWxzZQIJAJ8IAQUJa2V5SGVhbHRoAGQDCQBnAgUJb2xkSGVhbHRoAGQJAAIBAhpIUCBzaG91bGQgYmUgPCAxMDAgdG8gaGVhbAQFYnBLZXkJARFrZXlCYWNrcGFja0J5RHVjawEFC2R1Y2tBc3NldElkBAtjdXJyZW50UGFjawkBC2dldEJhY2twYWNrAQUFYnBLZXkEBW1MaXN0CQC1CQIJAJEDAgULY3VycmVudFBhY2sFCGJwSWR4TWF0AgFfBA1jdXJyZW50QW1vdW50CQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUFbUxpc3QFB21hdFR5cGUEC2RlbHRhSGVhbHRoCQCXAwEJAMwIAgkAaQIFBmFtb3VudAUISEVBTENPU1QJAMwIAgkAZQIAZAUJb2xkSGVhbHRoBQNuaWwEC3NwZW5kQW1vdW50CQBoAgULZGVsdGFIZWFsdGgFCEhFQUxDT1NUAwkAZgIFC3NwZW5kQW1vdW50BQ1jdXJyZW50QW1vdW50CQACAQkArAICCQCsAgIJAKwCAgkArAICCQCsAgICCVlvdSBuZWVkIAkApAMBBQtzcGVuZEFtb3VudAIEIG9mIAkAkQMCBQhtYXRUeXBlcwUHbWF0VHlwZQIkIHRvIGhlYWwsIGJ1dCB5b3UgYmFja3BhY2sgY29udGFpbnMgCQCkAwEFDWN1cnJlbnRBbW91bnQEBm5ld01hdAkBDHN1Yk9uZUluTGlzdAMFBW1MaXN0BQdtYXRUeXBlBQtzcGVuZEFtb3VudAkAzAgCCQEMSW50ZWdlckVudHJ5AgUJa2V5SGVhbHRoCQBkAgUJb2xkSGVhbHRoBQtkZWx0YUhlYWx0aAkAzAgCCQELU3RyaW5nRW50cnkCBQVicEtleQkAuQkCCQDMCAIJAJEDAgULY3VycmVudFBhY2sFCmJwSWR4TGV2ZWwJAMwIAgkAkQMCBQtjdXJyZW50UGFjawUIYnBJZHhSZXMJAMwIAgUGbmV3TWF0CQDMCAIJAJEDAgULY3VycmVudFBhY2sFCWJwSWR4UHJvZAUDbmlsAgE6BQNuaWwBaQEOdXBkYXRlQmFja3BhY2sCC2R1Y2tBc3NldElkB25ld1BhY2sDCQECIT0CCAUBaQZjYWxsZXIFC2Vjb25vbXlBZGRyCQACAQIRcGVybWlzc2lvbiBkZW5pZWQJAJQKAgkAzAgCCQELU3RyaW5nRW50cnkCCQERa2V5QmFja3BhY2tCeUR1Y2sBBQtkdWNrQXNzZXRJZAUHbmV3UGFjawUDbmlsBQduZXdQYWNrAWkBDWV4cGVkaXRpb25CdXkCB21lc3NhZ2UDc2lnAwkBAiE9AgkAkAMBCAUBaQhwYXltZW50cwABCQACAQIcRXhhY3RseSBvbmUgcGF5bWVudCByZXF1aXJlZAQDcG10CQEFdmFsdWUBCQCRAwIIBQFpCHBheW1lbnRzAAADCQECIT0CCAUDcG10B2Fzc2V0SWQFC3VzZG5Bc3NldElkCQACAQIaQWxsb3dlZCBVU0ROIHBheW1lbnQgb25seSEDCQECIT0CCAUDcG10BmFtb3VudAUHRVhQVVNETgkAAgEJAKwCAgIbUGF5bWVudCBhdHRhY2hlZCBzaG91bGQgYmUgCQCkAwEFB0VYUFVTRE4JARBleHBlZGl0aW9uQ29tbW9uBQcIBQFpBmNhbGxlcggFAWkNdHJhbnNhY3Rpb25JZAUHbWVzc2FnZQUDc2lnAWkBCmV4cGVkaXRpb24CB21lc3NhZ2UDc2lnAwkBAiE9AgkAkAMBCAUBaQhwYXltZW50cwAACQACAQInZXhwZWRpdGlvbiBkb2Vzbid0IHJlcXVpcmUgYW55IHBheW1lbnRzCQEQZXhwZWRpdGlvbkNvbW1vbgUGCAUBaQZjYWxsZXIIBQFpDXRyYW5zYWN0aW9uSWQFB21lc3NhZ2UFA3NpZwFpAQx1cGdyYWRlSW5mcmEBC2xhbmRBc3NldElkAwkBAiE9AgkAkAMBCAUBaQhwYXltZW50cwAACQACAQIzSW5mcmFzdHJ1Y3R1cmUgdXBncmFkZSBkb2Vzbid0IHJlcXVpcmUgYW55IHBheW1lbnRzCQENdXBJbmZyYUNvbW1vbgMGCAUBaQZjYWxsZXIFC2xhbmRBc3NldElkAWkBEHVwZ3JhZGVJbmZyYVVzZG4BC2xhbmRBc3NldElkAwkBAiE9AgkAkAMBCAUBaQhwYXltZW50cwABCQACAQIcRXhhY3RseSBvbmUgcGF5bWVudCByZXF1aXJlZAQDcG10CQEFdmFsdWUBCQCRAwIIBQFpCHBheW1lbnRzAAADCQECIT0CCAUDcG10B2Fzc2V0SWQFC3VzZG5Bc3NldElkCQACAQIaQWxsb3dlZCBVU0ROIHBheW1lbnQgb25seSEECG5ld0xldmVsCQBkAgkBC3ZhbHVlT3JFbHNlAgkAnwgBCQEWa2V5SW5mcmFMZXZlbEJ5QXNzZXRJZAEFC2xhbmRBc3NldElkAAAAAQQFYXNzZXQJAQV2YWx1ZQEJAOwHAQkA2QQBBQtsYW5kQXNzZXRJZAQBZAkAtQkCCAUFYXNzZXQLZGVzY3JpcHRpb24CAV8EBGNvc3QJAGsDBRVJbmZyYVVwZ3JhZGVDb3N0U1VzZG4JAGgCCQEPbnVtUGllY2VzQnlTaXplAQkAkQMCBQFkBQtyZWNMYW5kU2l6ZQUIbmV3TGV2ZWwAGQMJAQIhPQIIBQNwbXQGYW1vdW50BQRjb3N0CQACAQkArAICAhtQYXltZW50IGF0dGFjaGVkIHNob3VsZCBiZSAJAKQDAQUEY29zdAkBDXVwSW5mcmFDb21tb24DBwgFAWkGY2FsbGVyBQtsYW5kQXNzZXRJZACrEgUf", "height": 2387871, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: B2WvBBewuyAuWfpZ9GxoG5bjbm73RWJdx3SK5jMRJT9w Next: G9cZG4s1GLBifyWweMPkziN9RE5V324pQQMCntsectAE Diff:
OldNewDifferences
9595 else throw("Unknown chain")
9696 }
9797
98+let PresaleArtifactActivationTime = match chain {
99+ case _ =>
100+ if (("W" == $match0))
101+ then 1673136000000
102+ else if (("T" == $match0))
103+ then 1672790400000
104+ else throw("Unknown chain")
105+}
106+
98107 let MULT6 = 1000000
99108
100109 let FIVEX = toBigInt(5)
132141
133142
134143 func keyInfraLevelByAssetId (assetId) = ("infraLevel_" + assetId)
144+
145+
146+func keypresaleArtActivatedByAssetId (assetId) = ("presaleArtActivated_" + assetId)
135147
136148
137149 func keyStakedDuckByOwner (ownerAddr) = ("stakedDuckByOwner_" + ownerAddr)
316328 }
317329
318330
319-func addRes (currentRes,terrainCounts,deltaTime,landSizeIndex) = {
331+func addRes (currentRes,terrainCounts,deltaTime,landSizeIndex,dailyByPieceWithBonuses) = {
320332 func adder (acc,i) = {
321- let resOfType = ((fraction(deltaTime, DAILYRESBYPIECE, DAYMILLIS) * terrainCounts[i]) * landSizeIndex)
333+ let resOfType = ((fraction(deltaTime, dailyByPieceWithBonuses, DAYMILLIS) * terrainCounts[i]) * landSizeIndex)
322334 (acc :+ toString((parseIntValue(currentRes[i]) + resOfType)))
323335 }
324336
487499 }
488500
489501
502+func applyBonuses (landAssetId) = {
503+ let infraLevel = valueOrElse(getInteger(keyInfraLevelByAssetId(landAssetId)), 0)
504+ let presaleBonus = if (valueOrElse(getBoolean(keypresaleArtActivatedByAssetId(landAssetId)), false))
505+ then 3
506+ else 0
507+ ((DAILYRESBYPIECE + fraction(DAILYRESBYPIECE, infraLevel, 4)) + fraction(DAILYRESBYPIECE, presaleBonus, 20))
508+ }
509+
510+
490511 @Callable(i)
491512 func stakeLand () = {
492513 let pmt = value(i.payments[0])
507528 else if (contains(landNumSize, "XL"))
508529 then dropRight(landNumSize, 2)
509530 else dropRight(landNumSize, 1)
510- if (!(isDefined(parseInt(landNum))))
511- then throw(("Cannot parse land number from " + asset.name))
531+ let landNumInt = valueOrErrorMessage(parseInt(landNum), ("Cannot parse land number from " + asset.name))
532+ let landAssetId = toBase58String(assetId)
533+ let timeKey = keyStakedTimeByAssetId(landAssetId)
534+ if (isDefined(getInteger(timeKey)))
535+ then throw((("NFT " + asset.name) + " is already staked"))
512536 else {
513- let timeKey = keyStakedTimeByAssetId(toBase58String(assetId))
514- if (isDefined(getInteger(timeKey)))
515- then throw((("NFT " + asset.name) + " is already staked"))
516- else {
517- let d = split(asset.description, "_")
518- let terrainCounts = countTerrains(d[recTerrains])
519- let props = updateProportions(terrainCounts, (numPiecesBySize(d[recLandSize]) / 25), 1)
520-[IntegerEntry(timeKey, lastBlock.timestamp), IntegerEntry(keyStakedTimeByTypeAssetIdAndOwner(LANDPREFIX, toBase58String(assetId), address), lastBlock.timestamp), StringEntry(keyLandAssetIdToOwner(toBase58String(assetId)), address), StringEntry(keyLandNumToOwner(landNum), address), StringEntry(keyResProportions(), props)]
521- }
537+ let d = split(asset.description, "_")
538+ let terrainCounts = countTerrains(d[recTerrains])
539+ let props = updateProportions(terrainCounts, (numPiecesBySize(d[recLandSize]) / 25), 1)
540+ let presaleActive = if ((500 >= landNumInt))
541+ then (lastBlock.timestamp > PresaleArtifactActivationTime)
542+ else false
543+[IntegerEntry(timeKey, lastBlock.timestamp), BooleanEntry(keypresaleArtActivatedByAssetId(landAssetId), presaleActive), IntegerEntry(keyStakedTimeByTypeAssetIdAndOwner(LANDPREFIX, landAssetId, address), lastBlock.timestamp), StringEntry(keyLandAssetIdToOwner(landAssetId), address), StringEntry(keyLandNumToOwner(landNum), address), StringEntry(keyResProportions(), props)]
522544 }
523545 }
524546 }
661683 then throw(((("Saved timestamp is in future, saved = " + toString(savedTime)) + ", current = ") + toString(lastBlock.timestamp)))
662684 else {
663685 let pieces = numPiecesBySize(landSize)
664- let infraLevel = valueOrElse(getInteger(keyInfraLevelByAssetId(landAssetId)), 0)
665- let availRes = (fraction((deltaTime + fraction(deltaTime, infraLevel, 4)), DAILYRESBYPIECE, DAYMILLIS) * pieces)
686+ let dailyProductionByPiece = applyBonuses(landAssetId)
687+ let availRes = fraction(deltaTime, (dailyProductionByPiece * pieces), DAYMILLIS)
666688 if ((amount > availRes))
667689 then throw(((("Not enough resources, available = " + toString(availRes)) + ", requested = ") + toString(amount)))
668690 else {
669- let newDeltaTime = fraction((availRes - amount), DAYMILLIS, (pieces * DAILYRESBYPIECE))
691+ let newDeltaTime = fraction((availRes - amount), DAYMILLIS, (dailyProductionByPiece * pieces))
670692 let newTimestamp = (lastBlock.timestamp - newDeltaTime)
671693 let bpKey = keyBackpackByDuck(duckAssetId)
672694 let currentPack = getBackpack(bpKey)
673695 let currentRes = split(currentPack[bpIdxRes], "_")
674- let bpRes = addRes(currentRes, terrainCounts, ((deltaTime - newDeltaTime) + fraction((deltaTime - newDeltaTime), infraLevel, 4)), (pieces / 25))
696+ let bpRes = addRes(currentRes, terrainCounts, (deltaTime - newDeltaTime), (pieces / 25), dailyProductionByPiece)
675697 let newPack = makeString([currentPack[bpIdxLevel], bpRes, currentPack[bpIdxMat], currentPack[bpIdxProd]], ":")
676698 $Tuple2([StringEntry(bpKey, newPack), IntegerEntry(timeKey, newTimestamp), IntegerEntry(keyStakedTimeByTypeAssetIdAndOwner(LANDPREFIX, landAssetId, owner), newTimestamp)], bpRes)
677699 }
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
5353
5454 let DAILYRESBYPIECE = 3456000
5555
5656 let DAYMILLIS = 86400000
5757
5858 let FIVEMINUTESMILLIS = 300000
5959
6060 let RESOURCEPRICEMIN = 158549
6161
6262 let InfraUpgradeCostS = match chain {
6363 case _ =>
6464 if (("W" == $match0))
6565 then 18921595217
6666 else if (("T" == $match0))
6767 then 189215952
6868 else throw("Unknown chain")
6969 }
7070
7171 let InfraUpgradeCostSUsdn = match chain {
7272 case _ =>
7373 if (("W" == $match0))
7474 then 120000000
7575 else if (("T" == $match0))
7676 then 1200000
7777 else throw("Unknown chain")
7878 }
7979
8080 let EXPMATERIALS = match chain {
8181 case _ =>
8282 if (("W" == $match0))
8383 then 157679960139
8484 else if (("T" == $match0))
8585 then 1576799601
8686 else throw("Unknown chain")
8787 }
8888
8989 let EXPUSDN = match chain {
9090 case _ =>
9191 if (("W" == $match0))
9292 then 1000000000
9393 else if (("T" == $match0))
9494 then 10000000
9595 else throw("Unknown chain")
9696 }
9797
98+let PresaleArtifactActivationTime = match chain {
99+ case _ =>
100+ if (("W" == $match0))
101+ then 1673136000000
102+ else if (("T" == $match0))
103+ then 1672790400000
104+ else throw("Unknown chain")
105+}
106+
98107 let MULT6 = 1000000
99108
100109 let FIVEX = toBigInt(5)
101110
102111 let TWENTYX = toBigInt(20)
103112
104113 let TWENTY2X = toBigInt((20 * 20))
105114
106115 let TWENTY3X = toBigInt(((20 * 20) * 20))
107116
108117 let TWENTY4X = toBigInt((((20 * 20) * 20) * 20))
109118
110119 let TWENTY5X = toBigInt(((((20 * 20) * 20) * 20) * 20))
111120
112121 let matTypes = ["Fuel", "Metal", "Plank", "Glass", "Plastic", "Protein"]
113122
114123 let continents = ["Asia", "Europe", "Americas", "Oceania", "Africa"]
115124
116125 func keyNextFreeLandNum () = "nextLandNum"
117126
118127
119128 func keyLandToAssetId (landNum) = ("landToAsset_" + landNum)
120129
121130
122131 func keyNftName (landNum,landSize) = ((LANDPREFIX + landNum) + landSize)
123132
124133
125134 func keyLandAssetIdToOwner (assetId) = ("nftOwner_" + assetId)
126135
127136
128137 func keyDuckIdToOwner (assetId) = ("duckOwner_" + assetId)
129138
130139
131140 func keyStakedTimeByAssetId (assetId) = ("stakedTime_" + assetId)
132141
133142
134143 func keyInfraLevelByAssetId (assetId) = ("infraLevel_" + assetId)
144+
145+
146+func keypresaleArtActivatedByAssetId (assetId) = ("presaleArtActivated_" + assetId)
135147
136148
137149 func keyStakedDuckByOwner (ownerAddr) = ("stakedDuckByOwner_" + ownerAddr)
138150
139151
140152 func keyStakedTimeByTypeAssetIdAndOwner (nftType,assetId,ownerAddr) = ((((("stakedTimeByTypeAssetIdAndOwner_" + nftType) + "_") + assetId) + "_") + ownerAddr)
141153
142154
143155 func keyLandNumToOwner (landNum) = ("landOwner_" + landNum)
144156
145157
146158 func keyBackpackByDuck (duckAssetId) = ("backPack_" + duckAssetId)
147159
148160
149161 func keyDuckLocation (duckAssetId) = ("duckLocation_" + duckAssetId)
150162
151163
152164 func keyDuckHealth (duckAssetId) = ("duckHealth_" + duckAssetId)
153165
154166
155167 func keyResProportions () = "resTypesProportions"
156168
157169
158170 let recLandNum = 0
159171
160172 let recLandSize = 1
161173
162174 let recTerrains = 2
163175
164176 let recContinent = 3
165177
166178 let locIdxContinent = 0
167179
168180 let locIdxType = 1
169181
170182 let locIdxId = 2
171183
172184 let bpIdxLevel = 0
173185
174186 let bpIdxRes = 1
175187
176188 let bpIdxMat = 2
177189
178190 let bpIdxProd = 3
179191
180192 func asString (v) = match v {
181193 case s: String =>
182194 s
183195 case _ =>
184196 throw("fail to cast into String")
185197 }
186198
187199
188200 func getNeededMaterials (total) = {
189201 let props = split(value(getString(keyResProportions())), "_")
190202 if ((size(props) != NUMRES))
191203 then throw("Wrong proportions data")
192204 else {
193205 let r = [parseIntValue(props[0]), parseIntValue(props[1]), parseIntValue(props[2]), parseIntValue(props[3]), parseIntValue(props[4]), parseIntValue(props[5])]
194206 let sum = (((((r[0] + r[1]) + r[2]) + r[3]) + r[4]) + r[5])
195207 if ((0 >= sum))
196208 then throw("No lands staked")
197209 else {
198210 let norm6 = fraction(total, MULT6, sum)
199211 func normalizer (acc,elem) = (acc :+ fraction(elem, norm6, MULT6))
200212
201213 let $l = r
202214 let $s = size($l)
203215 let $acc0 = nil
204216 func $f0_1 ($a,$i) = if (($i >= $s))
205217 then $a
206218 else normalizer($a, $l[$i])
207219
208220 func $f0_2 ($a,$i) = if (($i >= $s))
209221 then $a
210222 else throw("List size exceeds 6")
211223
212224 $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6)
213225 }
214226 }
215227 }
216228
217229
218230 func subtractMaterials (shouldUseMat,has,totalNeed) = {
219231 let need = getNeededMaterials(totalNeed)
220232 func subtractor (acc,idx) = {
221233 let result = (parseIntValue(has[idx]) - need[idx])
222234 if ((0 > result))
223235 then throw(((((("Not enough material idx=" + toString(idx)) + ", you have ") + has[idx]) + ", but need ") + toString(need[idx])))
224236 else (acc :+ toString(result))
225237 }
226238
227239 if (shouldUseMat)
228240 then {
229241 let $l = [0, 1, 2, 3, 4, 5]
230242 let $s = size($l)
231243 let $acc0 = nil
232244 func $f0_1 ($a,$i) = if (($i >= $s))
233245 then $a
234246 else subtractor($a, $l[$i])
235247
236248 func $f0_2 ($a,$i) = if (($i >= $s))
237249 then $a
238250 else throw("List size exceeds 6")
239251
240252 $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6)
241253 }
242254 else has
243255 }
244256
245257
246258 func updateProportions (terrainCounts,landSizeIndex,sign) = {
247259 let props = split(valueOrElse(getString(keyResProportions()), "0_0_0_0_0_0"), "_")
248260 if ((size(props) != NUMRES))
249261 then throw("Wrong proportions data")
250262 else {
251263 func updater (acc,i) = {
252264 let result = (parseIntValue(props[i]) + ((sign * terrainCounts[i]) * landSizeIndex))
253265 if ((0 > result))
254266 then throw(((((((("Panic! Pieces of type=" + toString(i)) + ", sign=") + toString(sign)) + ", terrainCounts[i]=") + toString(terrainCounts[i])) + ", landSizeIndex=") + toString(landSizeIndex)))
255267 else (acc :+ toString(result))
256268 }
257269
258270 let r = {
259271 let $l = [0, 1, 2, 3, 4, 5]
260272 let $s = size($l)
261273 let $acc0 = nil
262274 func $f0_1 ($a,$i) = if (($i >= $s))
263275 then $a
264276 else updater($a, $l[$i])
265277
266278 func $f0_2 ($a,$i) = if (($i >= $s))
267279 then $a
268280 else throw("List size exceeds 6")
269281
270282 $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6)
271283 }
272284 makeString(r, "_")
273285 }
274286 }
275287
276288
277289 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)]
278290
279291
280292 func numPiecesBySize (landSize) = match landSize {
281293 case _ =>
282294 if (("S" == $match0))
283295 then 25
284296 else if (("M" == $match0))
285297 then 100
286298 else if (("L" == $match0))
287299 then 225
288300 else if (("XL" == $match0))
289301 then 400
290302 else if (("XXL" == $match0))
291303 then 625
292304 else throw("Unknown land size")
293305 }
294306
295307
296308 func subOneInList (aList,idx,amount) = {
297309 func subber (acc,i) = (acc :+ (if ((i == idx))
298310 then toString((parseIntValue(aList[i]) - amount))
299311 else aList[i]))
300312
301313 let r = {
302314 let $l = [0, 1, 2, 3, 4, 5]
303315 let $s = size($l)
304316 let $acc0 = nil
305317 func $f0_1 ($a,$i) = if (($i >= $s))
306318 then $a
307319 else subber($a, $l[$i])
308320
309321 func $f0_2 ($a,$i) = if (($i >= $s))
310322 then $a
311323 else throw("List size exceeds 6")
312324
313325 $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6)
314326 }
315327 makeString(r, "_")
316328 }
317329
318330
319-func addRes (currentRes,terrainCounts,deltaTime,landSizeIndex) = {
331+func addRes (currentRes,terrainCounts,deltaTime,landSizeIndex,dailyByPieceWithBonuses) = {
320332 func adder (acc,i) = {
321- let resOfType = ((fraction(deltaTime, DAILYRESBYPIECE, DAYMILLIS) * terrainCounts[i]) * landSizeIndex)
333+ let resOfType = ((fraction(deltaTime, dailyByPieceWithBonuses, DAYMILLIS) * terrainCounts[i]) * landSizeIndex)
322334 (acc :+ toString((parseIntValue(currentRes[i]) + resOfType)))
323335 }
324336
325337 let r = {
326338 let $l = [0, 1, 2, 3, 4, 5]
327339 let $s = size($l)
328340 let $acc0 = nil
329341 func $f0_1 ($a,$i) = if (($i >= $s))
330342 then $a
331343 else adder($a, $l[$i])
332344
333345 func $f0_2 ($a,$i) = if (($i >= $s))
334346 then $a
335347 else throw("List size exceeds 6")
336348
337349 $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6)
338350 }
339351 makeString(r, "_")
340352 }
341353
342354
343355 func abs (x) = if ((x >= toBigInt(0)))
344356 then x
345357 else -(x)
346358
347359
348360 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]]
349361
350362 func genChar (n,freqs) = {
351363 let rem = toInt((n % TWENTYX))
352364 let letter = if ((freqs[0] > rem))
353365 then "A"
354366 else if ((freqs[1] > rem))
355367 then "B"
356368 else if ((freqs[2] > rem))
357369 then "C"
358370 else if ((freqs[3] > rem))
359371 then "D"
360372 else if ((freqs[4] > rem))
361373 then "E"
362374 else "F"
363375 letter
364376 }
365377
366378
367379 func getBackpack (bpKey) = {
368380 let p = split(valueOrElse(getString(bpKey), "0:0_0_0_0_0_0:0_0_0_0_0_0:"), ":")
369381 [toString(valueOrElse(parseInt(p[bpIdxLevel]), 0)), if ((size(split(p[bpIdxRes], "_")) == NUMRES))
370382 then p[bpIdxRes]
371383 else "0_0_0_0_0_0", if ((size(split(p[bpIdxMat], "_")) == NUMRES))
372384 then p[bpIdxMat]
373385 else "0_0_0_0_0_0", p[bpIdxProd]]
374386 }
375387
376388
377389 func expeditionCommon (shouldUseMat,caller,txId,message,sig) = if (!(sigVerify_8Kb(message, sig, pub)))
378390 then throw("signature does not match")
379391 else {
380392 let parts = split(toUtf8String(message), ";")
381393 let hp = split(split(parts[0], "|")[0], "_")
382394 let curHP = parseIntValue(hp[0])
383395 let newHP = parseIntValue(hp[1])
384396 let locAndTime = split(parts[1], ":")
385397 let targetLocation = split(locAndTime[0], "_")
386398 if ((targetLocation[1] != "E"))
387399 then throw("expedition target location type should be E")
388400 else {
389401 let time = parseIntValue(locAndTime[1])
390402 if (if ((time > (lastBlock.timestamp + FIVEMINUTESMILLIS)))
391403 then true
392404 else ((lastBlock.timestamp - FIVEMINUTESMILLIS) > time))
393405 then throw("signature outdated")
394406 else {
395407 let userAddr = toString(caller)
396408 let duckAssetId = valueOrErrorMessage(getString(keyStakedDuckByOwner(userAddr)), "You don't have a duck staked")
397409 let keyHealth = keyDuckHealth(duckAssetId)
398410 let oldFromState = valueOrElse(getInteger(keyHealth), 100)
399411 if ((oldFromState != curHP))
400412 then throw(((("oldHealth=" + toString(valueOrElse(getInteger(keyHealth), 100))) + " from state does not match one from flight log=") + toString(curHP)))
401413 else if ((0 >= curHP))
402414 then throw("You can't fly with zero health")
403415 else if ((0 >= newHP))
404416 then throw("Your duck health is zero, expedition failed")
405417 else {
406418 let bpKey = keyBackpackByDuck(duckAssetId)
407419 let currentPack = getBackpack(bpKey)
408420 let mList = split(currentPack[bpIdxMat], "_")
409421 let newMat = makeString(subtractMaterials(shouldUseMat, mList, EXPMATERIALS), "_")
410422 let bigNum = abs(toBigInt(txId))
411423 let freeNum = valueOrElse(getInteger(keyNextFreeLandNum()), 501)
412424 let landNum = toString(freeNum)
413425 let continentIdx = toInt((bigNum % FIVEX))
414426 let f = freq[continentIdx]
415427 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))
416428
417429 let t = {
418430 let $l = [1, 2, 3, 4, 5]
419431 let $s = size($l)
420432 let $acc0 = $Tuple2("", (bigNum / FIVEX))
421433 func $f0_1 ($a,$i) = if (($i >= $s))
422434 then $a
423435 else terrainGenerator($a, $l[$i])
424436
425437 func $f0_2 ($a,$i) = if (($i >= $s))
426438 then $a
427439 else throw("List size exceeds 5")
428440
429441 $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5)
430442 }
431443 let continent = continents[continentIdx]
432444 let issue = Issue(keyNftName(landNum, "S"), makeString([landNum, "S", t._1, continent], "_"), 1, 0, false)
433445 let assetId = calculateAssetId(issue)
434446 let id = toBase58String(assetId)
435447 $Tuple2([IntegerEntry(keyNextFreeLandNum(), (freeNum + 1)), issue, StringEntry(keyLandToAssetId(landNum), id), StringEntry(keyLandAssetIdToOwner(id), userAddr), StringEntry(keyLandNumToOwner(landNum), userAddr), IntegerEntry(keyInfraLevelByAssetId(id), 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]], ":"))], unit)
436448 }
437449 }
438450 }
439451 }
440452
441453
442454 func upInfraCommon (shouldUseMat,caller,landAssetId) = {
443455 let addr = toString(caller)
444456 let infraKey = keyInfraLevelByAssetId(landAssetId)
445457 let curLevel = valueOrElse(getInteger(infraKey), 0)
446458 if ((curLevel >= 3))
447459 then throw("Currently max infrastructure level = 3")
448460 else {
449461 let newLevel = (curLevel + 1)
450462 let asset = value(assetInfo(fromBase58String(landAssetId)))
451463 if (!(contains(asset.name, LANDPREFIX)))
452464 then throw((("NFT " + LANDPREFIX) + " token should be passed as param"))
453465 else {
454466 let timeKey = keyStakedTimeByAssetId(landAssetId)
455467 let owner = getStringValue(keyLandAssetIdToOwner(landAssetId))
456468 if ((owner != addr))
457469 then throw((LANDPREFIX + " is not yours"))
458470 else {
459471 let d = split(asset.description, "_")
460472 let landSize = d[recLandSize]
461473 let pieces = numPiecesBySize(landSize)
462474 let duckAssetId = valueOrErrorMessage(getString(keyStakedDuckByOwner(addr)), "You don't have a duck staked")
463475 let curLocation = valueOrElse(getString(keyDuckLocation(duckAssetId)), DEFAULTLOCATION)
464476 let loc = split(value(curLocation), "_")
465477 if ((loc[locIdxType] != "L"))
466478 then throw((("Duck location type is " + loc[locIdxType]) + ", but should be L"))
467479 else if ((loc[locIdxId] != landAssetId))
468480 then throw(((("Duck location id is " + loc[locIdxId]) + ", but should be ") + landAssetId))
469481 else {
470482 let bpKey = keyBackpackByDuck(duckAssetId)
471483 let currentPack = getBackpack(bpKey)
472484 let mList = split(currentPack[bpIdxMat], "_")
473485 let newMat = makeString(subtractMaterials(shouldUseMat, mList, fraction(InfraUpgradeCostS, (pieces * newLevel), 25)), "_")
474486 let savedTime = valueOrErrorMessage(getInteger(timeKey), (("NFT " + asset.name) + " is not staked"))
475487 let deltaTime = (lastBlock.timestamp - savedTime)
476488 if ((0 > deltaTime))
477489 then throw(((("Saved timestamp is in future, saved = " + toString(savedTime)) + ", current = ") + toString(lastBlock.timestamp)))
478490 else {
479491 let availRes = (fraction(deltaTime, DAILYRESBYPIECE, DAYMILLIS) * pieces)
480492 let newRes = asString(invoke(this, "claimRes", [availRes, landAssetId], nil))
481493 $Tuple2([IntegerEntry(infraKey, newLevel), StringEntry(bpKey, makeString([currentPack[bpIdxLevel], newRes, newMat, currentPack[bpIdxProd]], ":"))], newLevel)
482494 }
483495 }
484496 }
485497 }
486498 }
487499 }
488500
489501
502+func applyBonuses (landAssetId) = {
503+ let infraLevel = valueOrElse(getInteger(keyInfraLevelByAssetId(landAssetId)), 0)
504+ let presaleBonus = if (valueOrElse(getBoolean(keypresaleArtActivatedByAssetId(landAssetId)), false))
505+ then 3
506+ else 0
507+ ((DAILYRESBYPIECE + fraction(DAILYRESBYPIECE, infraLevel, 4)) + fraction(DAILYRESBYPIECE, presaleBonus, 20))
508+ }
509+
510+
490511 @Callable(i)
491512 func stakeLand () = {
492513 let pmt = value(i.payments[0])
493514 let assetId = value(pmt.assetId)
494515 let address = toString(i.caller)
495516 if ((pmt.amount != 1))
496517 then throw((("NFT " + LANDPREFIX) + " token should be attached as payment"))
497518 else {
498519 let asset = value(assetInfo(assetId))
499520 if ((asset.issuer != this))
500521 then throw("Unknown issuer of token")
501522 else if (!(contains(asset.name, LANDPREFIX)))
502523 then throw((("Only NFT " + LANDPREFIX) + " tokens are accepted"))
503524 else {
504525 let landNumSize = drop(asset.name, 4)
505526 let landNum = if (contains(landNumSize, "XXL"))
506527 then dropRight(landNumSize, 3)
507528 else if (contains(landNumSize, "XL"))
508529 then dropRight(landNumSize, 2)
509530 else dropRight(landNumSize, 1)
510- if (!(isDefined(parseInt(landNum))))
511- then throw(("Cannot parse land number from " + asset.name))
531+ let landNumInt = valueOrErrorMessage(parseInt(landNum), ("Cannot parse land number from " + asset.name))
532+ let landAssetId = toBase58String(assetId)
533+ let timeKey = keyStakedTimeByAssetId(landAssetId)
534+ if (isDefined(getInteger(timeKey)))
535+ then throw((("NFT " + asset.name) + " is already staked"))
512536 else {
513- let timeKey = keyStakedTimeByAssetId(toBase58String(assetId))
514- if (isDefined(getInteger(timeKey)))
515- then throw((("NFT " + asset.name) + " is already staked"))
516- else {
517- let d = split(asset.description, "_")
518- let terrainCounts = countTerrains(d[recTerrains])
519- let props = updateProportions(terrainCounts, (numPiecesBySize(d[recLandSize]) / 25), 1)
520-[IntegerEntry(timeKey, lastBlock.timestamp), IntegerEntry(keyStakedTimeByTypeAssetIdAndOwner(LANDPREFIX, toBase58String(assetId), address), lastBlock.timestamp), StringEntry(keyLandAssetIdToOwner(toBase58String(assetId)), address), StringEntry(keyLandNumToOwner(landNum), address), StringEntry(keyResProportions(), props)]
521- }
537+ let d = split(asset.description, "_")
538+ let terrainCounts = countTerrains(d[recTerrains])
539+ let props = updateProportions(terrainCounts, (numPiecesBySize(d[recLandSize]) / 25), 1)
540+ let presaleActive = if ((500 >= landNumInt))
541+ then (lastBlock.timestamp > PresaleArtifactActivationTime)
542+ else false
543+[IntegerEntry(timeKey, lastBlock.timestamp), BooleanEntry(keypresaleArtActivatedByAssetId(landAssetId), presaleActive), IntegerEntry(keyStakedTimeByTypeAssetIdAndOwner(LANDPREFIX, landAssetId, address), lastBlock.timestamp), StringEntry(keyLandAssetIdToOwner(landAssetId), address), StringEntry(keyLandNumToOwner(landNum), address), StringEntry(keyResProportions(), props)]
522544 }
523545 }
524546 }
525547 }
526548
527549
528550
529551 @Callable(i)
530552 func unstakeLand (landAssetId) = if ((size(i.payments) != 0))
531553 then throw("unstake doesn't require any payments")
532554 else {
533555 let assetId = fromBase58String(landAssetId)
534556 let address = toString(i.caller)
535557 let asset = value(assetInfo(assetId))
536558 if ((asset.issuer != this))
537559 then throw("Unknown issuer of token")
538560 else if (!(contains(asset.name, LANDPREFIX)))
539561 then throw((("Only NFT " + LANDPREFIX) + " tokens can be unstaked"))
540562 else {
541563 let timeKey = keyStakedTimeByAssetId(landAssetId)
542564 if (!(isDefined(timeKey)))
543565 then throw((("NFT " + asset.name) + " is not staked"))
544566 else {
545567 let owner = valueOrErrorMessage(getString(keyLandAssetIdToOwner(landAssetId)), (("NFT " + asset.name) + " is orphaned"))
546568 if ((owner != address))
547569 then throw("Staked NFT is not yours")
548570 else {
549571 let d = split(asset.description, "_")
550572 let terrainCounts = countTerrains(d[recTerrains])
551573 let props = updateProportions(terrainCounts, (numPiecesBySize(d[recLandSize]) / 25), -1)
552574 [ScriptTransfer(i.caller, 1, assetId), DeleteEntry(timeKey), DeleteEntry(keyStakedTimeByTypeAssetIdAndOwner(LANDPREFIX, landAssetId, address)), StringEntry(keyResProportions(), props)]
553575 }
554576 }
555577 }
556578 }
557579
558580
559581
560582 @Callable(i)
561583 func stakeDuck () = {
562584 let pmt = value(i.payments[0])
563585 let assetId = value(pmt.assetId)
564586 let address = toString(i.caller)
565587 if ((pmt.amount != 1))
566588 then throw((("NFT " + DUCKPREFIX) + " token should be attached as payment"))
567589 else {
568590 let asset = value(assetInfo(assetId))
569591 if (if ((asset.issuer != incubatorAddr))
570592 then (asset.issuer != breederAddr)
571593 else false)
572594 then throw((("Unknown issuer of " + DUCKPREFIX) + " token"))
573595 else if (!(contains(asset.name, DUCKPREFIX)))
574596 then throw((("Only NFT " + DUCKPREFIX) + " tokens are accepted"))
575597 else {
576598 let assetIdStr = toBase58String(assetId)
577599 let timeKey = keyStakedTimeByAssetId(assetIdStr)
578600 if (isDefined(getInteger(timeKey)))
579601 then throw((("NFT " + asset.name) + " is already staked"))
580602 else if (isDefined(getString(keyStakedDuckByOwner(address))))
581603 then throw(("You already staked one duck: " + asset.name))
582604 else {
583605 let locKey = keyDuckLocation(assetIdStr)
584606 let location = getString(locKey)
585607 let keyHealth = keyDuckHealth(assetIdStr)
586608 let health = getInteger(keyHealth)
587609 let bpKey = keyBackpackByDuck(assetIdStr)
588610 let backpack = getString(bpKey)
589611 ([IntegerEntry(timeKey, lastBlock.timestamp), IntegerEntry(keyStakedTimeByTypeAssetIdAndOwner(DUCKPREFIX, toBase58String(assetId), address), lastBlock.timestamp), StringEntry(keyDuckIdToOwner(assetIdStr), address), StringEntry(keyStakedDuckByOwner(address), assetIdStr)] ++ (if (isDefined(location))
590612 then nil
591613 else ([StringEntry(locKey, DEFAULTLOCATION)] ++ (if (isDefined(health))
592614 then nil
593615 else ([IntegerEntry(keyHealth, 100)] ++ (if (isDefined(backpack))
594616 then nil
595617 else [StringEntry(bpKey, "0:0_0_0_0_0_0:0_0_0_0_0_0:")]))))))
596618 }
597619 }
598620 }
599621 }
600622
601623
602624
603625 @Callable(i)
604626 func unstakeDuck (assetIdStr) = if ((size(i.payments) != 0))
605627 then throw("unstake doesn't require any payments")
606628 else {
607629 let assetId = fromBase58String(assetIdStr)
608630 let address = toString(i.caller)
609631 let asset = value(assetInfo(assetId))
610632 if (if ((asset.issuer != incubatorAddr))
611633 then (asset.issuer != breederAddr)
612634 else false)
613635 then throw((("Unknown issuer of " + DUCKPREFIX) + " token"))
614636 else if (!(contains(asset.name, DUCKPREFIX)))
615637 then throw((("Only NFT " + DUCKPREFIX) + " tokens can be unstaked"))
616638 else {
617639 let timeKey = keyStakedTimeByAssetId(toBase58String(assetId))
618640 if (!(isDefined(timeKey)))
619641 then throw((("NFT " + asset.name) + " is not staked"))
620642 else if (!(isDefined(keyStakedDuckByOwner(address))))
621643 then throw((("The duck " + asset.name) + " is not staked"))
622644 else {
623645 let owner = valueOrErrorMessage(getString(keyDuckIdToOwner(toBase58String(assetId))), (("NFT " + asset.name) + " is orphaned"))
624646 if ((owner != address))
625647 then throw("Staked NFT is not yours")
626648 else [ScriptTransfer(i.caller, 1, assetId), DeleteEntry(timeKey), DeleteEntry(keyDuckLocation(assetIdStr)), DeleteEntry(keyStakedTimeByTypeAssetIdAndOwner(DUCKPREFIX, assetIdStr, address)), DeleteEntry(keyStakedDuckByOwner(address))]
627649 }
628650 }
629651 }
630652
631653
632654
633655 @Callable(i)
634656 func claimRes (amount,landAssetId) = if ((size(i.payments) != 0))
635657 then throw("claimRes doesn't require any payments")
636658 else {
637659 let addr = toString(i.originCaller)
638660 let asset = value(assetInfo(fromBase58String(landAssetId)))
639661 if (!(contains(asset.name, LANDPREFIX)))
640662 then throw((("NFT " + LANDPREFIX) + " token should be passed as param"))
641663 else {
642664 let timeKey = keyStakedTimeByAssetId(landAssetId)
643665 let owner = getStringValue(keyLandAssetIdToOwner(landAssetId))
644666 if ((owner != addr))
645667 then throw((LANDPREFIX + " is not yours"))
646668 else {
647669 let d = split(asset.description, "_")
648670 let landSize = d[recLandSize]
649671 let terrainCounts = countTerrains(d[recTerrains])
650672 let duckAssetId = valueOrErrorMessage(getString(keyStakedDuckByOwner(addr)), "You don't have a duck staked")
651673 let curLocation = valueOrElse(getString(keyDuckLocation(duckAssetId)), DEFAULTLOCATION)
652674 let loc = split(value(curLocation), "_")
653675 if ((loc[locIdxType] != "L"))
654676 then throw((("Duck location type is " + loc[locIdxType]) + ", but should be L"))
655677 else if ((loc[locIdxId] != landAssetId))
656678 then throw(((("Duck location id is " + loc[locIdxId]) + ", but should be ") + landAssetId))
657679 else {
658680 let savedTime = valueOrErrorMessage(getInteger(timeKey), (("NFT " + asset.name) + " is not staked"))
659681 let deltaTime = (lastBlock.timestamp - savedTime)
660682 if ((0 > deltaTime))
661683 then throw(((("Saved timestamp is in future, saved = " + toString(savedTime)) + ", current = ") + toString(lastBlock.timestamp)))
662684 else {
663685 let pieces = numPiecesBySize(landSize)
664- let infraLevel = valueOrElse(getInteger(keyInfraLevelByAssetId(landAssetId)), 0)
665- let availRes = (fraction((deltaTime + fraction(deltaTime, infraLevel, 4)), DAILYRESBYPIECE, DAYMILLIS) * pieces)
686+ let dailyProductionByPiece = applyBonuses(landAssetId)
687+ let availRes = fraction(deltaTime, (dailyProductionByPiece * pieces), DAYMILLIS)
666688 if ((amount > availRes))
667689 then throw(((("Not enough resources, available = " + toString(availRes)) + ", requested = ") + toString(amount)))
668690 else {
669- let newDeltaTime = fraction((availRes - amount), DAYMILLIS, (pieces * DAILYRESBYPIECE))
691+ let newDeltaTime = fraction((availRes - amount), DAYMILLIS, (dailyProductionByPiece * pieces))
670692 let newTimestamp = (lastBlock.timestamp - newDeltaTime)
671693 let bpKey = keyBackpackByDuck(duckAssetId)
672694 let currentPack = getBackpack(bpKey)
673695 let currentRes = split(currentPack[bpIdxRes], "_")
674- let bpRes = addRes(currentRes, terrainCounts, ((deltaTime - newDeltaTime) + fraction((deltaTime - newDeltaTime), infraLevel, 4)), (pieces / 25))
696+ let bpRes = addRes(currentRes, terrainCounts, (deltaTime - newDeltaTime), (pieces / 25), dailyProductionByPiece)
675697 let newPack = makeString([currentPack[bpIdxLevel], bpRes, currentPack[bpIdxMat], currentPack[bpIdxProd]], ":")
676698 $Tuple2([StringEntry(bpKey, newPack), IntegerEntry(timeKey, newTimestamp), IntegerEntry(keyStakedTimeByTypeAssetIdAndOwner(LANDPREFIX, landAssetId, owner), newTimestamp)], bpRes)
677699 }
678700 }
679701 }
680702 }
681703 }
682704 }
683705
684706
685707
686708 @Callable(i)
687709 func flight (message,sig) = if (!(sigVerify_8Kb(message, sig, pub)))
688710 then throw("signature does not match")
689711 else if ((size(i.payments) != 0))
690712 then throw("flight doesn't require any payments")
691713 else {
692714 let parts = split(toUtf8String(message), ";")
693715 let hp = split(split(parts[0], "|")[0], "_")
694716 let curHP = parseIntValue(hp[0])
695717 let newHP = parseIntValue(hp[1])
696718 let newLocAndTime = split(parts[1], ":")
697719 let newLocation = newLocAndTime[0]
698720 let time = parseIntValue(newLocAndTime[1])
699721 if (if ((time > (lastBlock.timestamp + FIVEMINUTESMILLIS)))
700722 then true
701723 else ((lastBlock.timestamp - FIVEMINUTESMILLIS) > time))
702724 then throw("signature outdated")
703725 else {
704726 let duckAssetId = valueOrErrorMessage(getString(keyStakedDuckByOwner(toString(i.caller))), "You don't have a duck staked")
705727 let keyHealth = keyDuckHealth(duckAssetId)
706728 let oldFromState = valueOrElse(getInteger(keyHealth), 100)
707729 if ((oldFromState != curHP))
708730 then throw(((("oldHealth=" + toString(valueOrElse(getInteger(keyHealth), 100))) + " from state does not match one from flight log=") + toString(curHP)))
709731 else if ((0 >= curHP))
710732 then throw("You can't fly with zero health")
711733 else {
712734 let locKey = keyDuckLocation(duckAssetId)
713735 let curLocation = valueOrElse(getString(locKey), DEFAULTLOCATION)
714736 if ((newLocation == curLocation))
715737 then throw("You can't fly to the same location")
716738 else $Tuple2([StringEntry(locKey, if ((newHP > 0))
717739 then newLocation
718740 else curLocation), IntegerEntry(keyHealth, newHP)], unit)
719741 }
720742 }
721743 }
722744
723745
724746
725747 @Callable(i)
726748 func setHealth (health,duckAssetId) = if (if ((0 > health))
727749 then true
728750 else (health > 100))
729751 then throw("HP should be within 0..100")
730752 else [IntegerEntry(keyDuckHealth(duckAssetId), health)]
731753
732754
733755
734756 @Callable(i)
735757 func heal (matType,amount) = if (if ((0 > matType))
736758 then true
737759 else (matType >= NUMRES))
738760 then throw(("Unknown material: " + toString(matType)))
739761 else if ((0 >= amount))
740762 then throw(("Amount should be positive! " + toString(amount)))
741763 else {
742764 let duckAssetId = valueOrErrorMessage(getString(keyStakedDuckByOwner(toString(i.caller))), "You don't have a duck staked")
743765 let keyHealth = keyDuckHealth(duckAssetId)
744766 let oldHealth = valueOrElse(getInteger(keyHealth), 100)
745767 if ((oldHealth >= 100))
746768 then throw("HP should be < 100 to heal")
747769 else {
748770 let bpKey = keyBackpackByDuck(duckAssetId)
749771 let currentPack = getBackpack(bpKey)
750772 let mList = split(currentPack[bpIdxMat], "_")
751773 let currentAmount = parseIntValue(mList[matType])
752774 let deltaHealth = min([(amount / HEALCOST), (100 - oldHealth)])
753775 let spendAmount = (deltaHealth * HEALCOST)
754776 if ((spendAmount > currentAmount))
755777 then throw(((((("You need " + toString(spendAmount)) + " of ") + matTypes[matType]) + " to heal, but you backpack contains ") + toString(currentAmount)))
756778 else {
757779 let newMat = subOneInList(mList, matType, spendAmount)
758780 [IntegerEntry(keyHealth, (oldHealth + deltaHealth)), StringEntry(bpKey, makeString([currentPack[bpIdxLevel], currentPack[bpIdxRes], newMat, currentPack[bpIdxProd]], ":"))]
759781 }
760782 }
761783 }
762784
763785
764786
765787 @Callable(i)
766788 func updateBackpack (duckAssetId,newPack) = if ((i.caller != economyAddr))
767789 then throw("permission denied")
768790 else $Tuple2([StringEntry(keyBackpackByDuck(duckAssetId), newPack)], newPack)
769791
770792
771793
772794 @Callable(i)
773795 func expeditionBuy (message,sig) = if ((size(i.payments) != 1))
774796 then throw("Exactly one payment required")
775797 else {
776798 let pmt = value(i.payments[0])
777799 if ((pmt.assetId != usdnAssetId))
778800 then throw("Allowed USDN payment only!")
779801 else if ((pmt.amount != EXPUSDN))
780802 then throw(("Payment attached should be " + toString(EXPUSDN)))
781803 else expeditionCommon(false, i.caller, i.transactionId, message, sig)
782804 }
783805
784806
785807
786808 @Callable(i)
787809 func expedition (message,sig) = if ((size(i.payments) != 0))
788810 then throw("expedition doesn't require any payments")
789811 else expeditionCommon(true, i.caller, i.transactionId, message, sig)
790812
791813
792814
793815 @Callable(i)
794816 func upgradeInfra (landAssetId) = if ((size(i.payments) != 0))
795817 then throw("Infrastructure upgrade doesn't require any payments")
796818 else upInfraCommon(true, i.caller, landAssetId)
797819
798820
799821
800822 @Callable(i)
801823 func upgradeInfraUsdn (landAssetId) = if ((size(i.payments) != 1))
802824 then throw("Exactly one payment required")
803825 else {
804826 let pmt = value(i.payments[0])
805827 if ((pmt.assetId != usdnAssetId))
806828 then throw("Allowed USDN payment only!")
807829 else {
808830 let newLevel = (valueOrElse(getInteger(keyInfraLevelByAssetId(landAssetId)), 0) + 1)
809831 let asset = value(assetInfo(fromBase58String(landAssetId)))
810832 let d = split(asset.description, "_")
811833 let cost = fraction(InfraUpgradeCostSUsdn, (numPiecesBySize(d[recLandSize]) * newLevel), 25)
812834 if ((pmt.amount != cost))
813835 then throw(("Payment attached should be " + toString(cost)))
814836 else upInfraCommon(false, i.caller, landAssetId)
815837 }
816838 }
817839
818840

github/deemru/w8io/026f985 
89.73 ms