tx · 9C4HTgHCm2aiszNAco7KsKfjb2gqaFwqaREHJbdTzXCs

3PMuo96quEzPpQxoCEXHjw1UgKVwZjDdXdC:  -0.01600000 Waves

2023.12.22 16:38 [3963882] smart account 3PMuo96quEzPpQxoCEXHjw1UgKVwZjDdXdC > SELF 0.00000000 Waves

{ "type": 13, "id": "9C4HTgHCm2aiszNAco7KsKfjb2gqaFwqaREHJbdTzXCs", "fee": 1600000, "feeAssetId": null, "timestamp": 1703252312748, "version": 2, "chainId": 87, "sender": "3PMuo96quEzPpQxoCEXHjw1UgKVwZjDdXdC", "senderPublicKey": "HNmzFMJbxf9XZhQKkC4gpbgzH53RdtAGZznwdL58DgsP", "proofs": [ "Mo22VwCugc8gqJjS2jCj2hSNh5iuoAThCcZowyPi6zw2QLe1QzNCiVHDCcrJ6DwHy9EYmfWcU2HV8GCBPBBMUWh" ], "script": "base64:BgJNCAISABIDCgEBEgASAwoBARIAEgMKAQgSBAoCCAgSBAoCCAgSAwoBCBIAEgkKBwgICAEBCAgSAwoBCBIDCgEEEgASAwoBCBIAEgMKAQgxAAtNQVhfUkVXQVJEUwAFAAVvd25lcgkBEUBleHRyTmF0aXZlKDEwNjIpAQkBEUBleHRyTmF0aXZlKDEwNTMpAgUEdGhpcwIFb3duZXIADXJvb3RfY29udHJhY3QJAQt2YWx1ZU9yRWxzZQIJAJ0IAgUEdGhpcwINcm9vdF9jb250cmFjdAIAAAV0b2tlbgkBEUBleHRyTmF0aXZlKDEwNTMpAgUEdGhpcwIFdG9rZW4AB3Jld2FyZHMJARFAZXh0ck5hdGl2ZSgxMDUzKQIFBHRoaXMCB3Jld2FyZHMADHJld2FyZHNfbGlzdAkAtQkCBQdyZXdhcmRzAgEsAAZwZXJpb2QJARFAZXh0ck5hdGl2ZSgxMDUwKQIFBHRoaXMCBnBlcmlvZAAJaXNfa2lsbGVkCQERQGV4dHJOYXRpdmUoMTA1MSkCBQR0aGlzAglpc19raWxsZWQABHR3YXAJAQt2YWx1ZU9yRWxzZQIJAJ0IAgUEdGhpcwIEdHdhcAIAAA1oZWlnaHRBZGRyZXNzCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKYIAQkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCdCAIFBHRoaXMCDWhlaWdodEFkZHJlc3MCE25vIHNldHRpbmdzIGRlZmluZWQCFGJhZCBzZXR0aW5ncyBhZGRyZXNzAAZIRUlHSFQFBmhlaWdodAAPc3luY19oZWlnaHRfa2V5AgtzeW5jX2hlaWdodAALc3luY19oZWlnaHQJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwUPc3luY19oZWlnaHRfa2V5AAAAEHRva2VuX2Ftb3VudF9rZXkCBnRva2VucwAMdG9rZW5fYW1vdW50CQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMFEHRva2VuX2Ftb3VudF9rZXkAAAEPdXNlcl9hbW91bnRfa2V5AQR1c2VyCQCsAgIFBHVzZXICB19hbW91bnQBC3VzZXJfYW1vdW50AQR1c2VyCQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMJAQ91c2VyX2Ftb3VudF9rZXkBBQR1c2VyAAAAF3Rva2VuX2xvY2tlZF9hbW91bnRfa2V5Ag10b2tlbnNfbG9ja2VkABN0b2tlbl9sb2NrZWRfYW1vdW50CQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMFF3Rva2VuX2xvY2tlZF9hbW91bnRfa2V5AAAADWxvY2tlZF9wZXJpb2QJARFAZXh0ck5hdGl2ZSgxMDUwKQIFBHRoaXMCDWxvY2tlZF9wZXJpb2QBD3VzZXJfbG9ja2VkX2tleQEEdXNlcgkArAICBQR1c2VyAgdfbG9ja2VkARJ1c2VyX2xvY2tlZF92YWx1ZXMBBHVzZXIEAWwJALUJAgkBC3ZhbHVlT3JFbHNlAgkAnQgCBQR0aGlzCQEPdXNlcl9sb2NrZWRfa2V5AQUEdXNlcgIFMF8wXzACAV8JAJUKAwkBDXBhcnNlSW50VmFsdWUBCQCRAwIFAWwAAAkBDXBhcnNlSW50VmFsdWUBCQCRAwIFAWwAAQkBDXBhcnNlSW50VmFsdWUBCQCRAwIFAWwAAgEXdXNlcl9hc3NldF9hZGp1c3RlZF9rZXkCBHVzZXIFYXNzZXQJAKwCAgkArAICCQCsAgIFBHVzZXICAV8FBWFzc2V0AglfYWRqdXN0ZWQBE3VzZXJfYXNzZXRfYWRqdXN0ZWQCBHVzZXIFYXNzZXQJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwkBF3VzZXJfYXNzZXRfYWRqdXN0ZWRfa2V5AgUEdXNlcgUFYXNzZXQAAAEWdXNlcl9hc3NldF9jbGFpbWVkX2tleQIEdXNlcgVhc3NldAkArAICCQCsAgIJAKwCAgUEdXNlcgIBXwUFYXNzZXQCCF9jbGFpbWVkARJ1c2VyX2Fzc2V0X2NsYWltZWQCBHVzZXIFYXNzZXQJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwkBFnVzZXJfYXNzZXRfY2xhaW1lZF9rZXkCBQR1c2VyBQVhc3NldAAAARBhc3NldF9yZXdhcmRfa2V5AQVhc3NldAkArAICBQVhc3NldAIHX3Jld2FyZAEMYXNzZXRfcmV3YXJkAQVhc3NldAkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzCQEQYXNzZXRfcmV3YXJkX2tleQEFBWFzc2V0AAABD2Fzc2V0X3NwZWVkX2tleQEFYXNzZXQJAKwCAgUFYXNzZXQCBl9zcGVlZAELYXNzZXRfc3BlZWQBBWFzc2V0CQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMJAQ9hc3NldF9zcGVlZF9rZXkBBQVhc3NldAAAAQ5hc3NldF9sZWZ0X2tleQEFYXNzZXQJAKwCAgUFYXNzZXQCBV9sZWZ0AQphc3NldF9sZWZ0AQVhc3NldAkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzCQEOYXNzZXRfbGVmdF9rZXkBBQVhc3NldAAAARFhc3NldF9jb250cm9sX2tleQEFYXNzZXQJAKwCAgUFYXNzZXQCCF9jb250cm9sAQ1hc3NldF9jb250cm9sAQVhc3NldAkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzCQERYXNzZXRfY29udHJvbF9rZXkBBQVhc3NldAAAAQxjaGVja0FkZHJlc3MBA2E1OAQBYQkBEUBleHRyTmF0aXZlKDEwNjIpAQUDYTU4CQClCAEFAWEBEWdldEFkZHJlc3NPckFsaWFzAQZzdHJpbmcEByRtYXRjaDAJAKYIAQUGc3RyaW5nAwkAAQIFByRtYXRjaDACB0FkZHJlc3MEAWEFByRtYXRjaDAFAWEJAQVBbGlhcwEFBnN0cmluZwETY2hlY2tBZGRyZXNzT3JBbGlhcwEGc3RyaW5nBAdhZGRyZXNzBAckbWF0Y2gwCQCmCAEFBnN0cmluZwMJAAECBQckbWF0Y2gwAgdBZGRyZXNzBAFhBQckbWF0Y2gwBQFhCQCkCAEJAQVBbGlhcwEFBnN0cmluZwMJAAACBQdhZGRyZXNzBQdhZGRyZXNzBQZzdHJpbmcJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BCmNoZWNrQXNzZXQBB2Fzc2V0NTgDCQAAAgUHYXNzZXQ1OAIFV0FWRVMCBVdBVkVTBAVhc3NldAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQDZBAEFB2Fzc2V0NTgJAKwCAgIWd3JvbmcgYXNzZXQgZW5jb2Rpbmc6IAUHYXNzZXQ1OAQEaW5mbwkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQDsBwEFBWFzc2V0CQCsAgICEndyb25nIGFzc2V0IGluZm86IAUHYXNzZXQ1OAMJAAACBQRpbmZvBQRpbmZvBQdhc3NldDU4CQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAQVhc3NldAEBYQMJAAACBQFhAgVXQVZFUwUEdW5pdAkA2QQBBQFhAQxhc3NldF9zdHJpbmcBAWEEByRtYXRjaDAFAWEDCQABAgUHJG1hdGNoMAIKQnl0ZVZlY3RvcgQBYgUHJG1hdGNoMAkA2AQBBQFiAgVXQVZFUwENYXNzZXRfYmFsYW5jZQEBYQMJAAACBQFhAgVXQVZFUwgJAO8HAQUEdGhpcwlhdmFpbGFibGUJAPAHAgUEdGhpcwkA2QQBBQFhAQ9hY2NvdW50X3Jld2FyZHMCBWFzc2V0BmFtb3VudAMJAAACBQR0d2FwAgAFA25pbAkA/AcECQERZ2V0QWRkcmVzc09yQWxpYXMBBQR0d2FwAgRwdXNoCQDMCAIFBWFzc2V0CQDMCAIFBXRva2VuCQDMCAIFBmFtb3VudAkAzAgCBQx0b2tlbl9hbW91bnQJAMwIAgIBJQUDbmlsBQNuaWwBDHN0b3BfcmV3YXJkcwAKAQRmb2xkAgNhY2MFYXNzZXQJAM4IAgUDYWNjCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEPYXNzZXRfc3BlZWRfa2V5AQUFYXNzZXQAAAUDbmlsCgACJGwFDHJld2FyZHNfbGlzdAoAAiRzCQCQAwEFAiRsCgAFJGFjYzAFA25pbAoBBSRmMF8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQEEZm9sZAIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmMF8yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQITTGlzdCBzaXplIGV4Y2VlZHMgNQkBBSRmMF8yAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgUFJGFjYzAAAAABAAIAAwAEAAUBEGNoZWNrcG9pbnRfYXNzZXQCA2FjYwVhc3NldAQNX2Fzc2V0X3Jld2FyZAkBDGFzc2V0X3Jld2FyZAEFBWFzc2V0BAxfYXNzZXRfc3BlZWQJAQthc3NldF9zcGVlZAEFBWFzc2V0BAtfYXNzZXRfbGVmdAkBCmFzc2V0X2xlZnQBBQVhc3NldAQPZXN0aW1hdGVfcmV3YXJkCQBoAgkAZQIFBkhFSUdIVAULc3luY19oZWlnaHQFDF9hc3NldF9zcGVlZAQLcmVhbF9yZXdhcmQDCQBmAgUPZXN0aW1hdGVfcmV3YXJkBQtfYXNzZXRfbGVmdAULX2Fzc2V0X2xlZnQFD2VzdGltYXRlX3Jld2FyZAQSY2xhaW1fYXNzZXRfcmV3YXJkCQBkAgUNX2Fzc2V0X3Jld2FyZAULcmVhbF9yZXdhcmQEEGNsYWltX2Fzc2V0X2xlZnQJAGUCBQtfYXNzZXRfbGVmdAULcmVhbF9yZXdhcmQEEWNsYWltX2Fzc2V0X3NwZWVkAwkAZgIFEGNsYWltX2Fzc2V0X2xlZnQAAAUMX2Fzc2V0X3NwZWVkAAAEDXJld2FyZF9hY3Rpb24DCQAAAgUSY2xhaW1fYXNzZXRfcmV3YXJkBQ1fYXNzZXRfcmV3YXJkBQNuaWwJAMwIAgkBDEludGVnZXJFbnRyeQIJARBhc3NldF9yZXdhcmRfa2V5AQUFYXNzZXQFEmNsYWltX2Fzc2V0X3Jld2FyZAUDbmlsBA5fYXNzZXRfYmFsYW5jZQkBDWFzc2V0X2JhbGFuY2UBBQVhc3NldAQOX2Fzc2V0X2NvbnRyb2wJAQ1hc3NldF9jb250cm9sAQUFYXNzZXQDCQBmAgUOX2Fzc2V0X2NvbnRyb2wFDl9hc3NldF9iYWxhbmNlCQACAQkArAICCQCsAgIJAKwCAgkArAICBQVhc3NldAIbIGJhbGFuY2UgbGVha2FnZSBkZXRlY3RlZDogCQCkAwEFDl9hc3NldF9jb250cm9sAgMgPiAJAKQDAQUOX2Fzc2V0X2JhbGFuY2UEEnBlcmlvZF9uZXdfYmFsYW5jZQkAZQIFDl9hc3NldF9iYWxhbmNlBQ5fYXNzZXRfY29udHJvbAQUcGVyaW9kX2Fzc2V0X2JhbGFuY2UJAGQCBRBjbGFpbV9hc3NldF9sZWZ0BRJwZXJpb2RfbmV3X2JhbGFuY2UEEnBlcmlvZF9hc3NldF9zcGVlZAkAaQIFFHBlcmlvZF9hc3NldF9iYWxhbmNlBQZwZXJpb2QDAwkAZwIFEWNsYWltX2Fzc2V0X3NwZWVkBRJwZXJpb2RfYXNzZXRfc3BlZWQJAGcCBRBjbGFpbV9hc3NldF9sZWZ0BRJwZXJpb2RfbmV3X2JhbGFuY2UHBAxzcGVlZF9hY3Rpb24DCQAAAgURY2xhaW1fYXNzZXRfc3BlZWQFDF9hc3NldF9zcGVlZAUDbmlsCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEPYXNzZXRfc3BlZWRfa2V5AQUFYXNzZXQFEWNsYWltX2Fzc2V0X3NwZWVkBQNuaWwEC2xlZnRfYWN0aW9uAwkAAAIFEGNsYWltX2Fzc2V0X2xlZnQFC19hc3NldF9sZWZ0BQNuaWwJAMwIAgkBDEludGVnZXJFbnRyeQIJAQ5hc3NldF9sZWZ0X2tleQEFBWFzc2V0BRBjbGFpbV9hc3NldF9sZWZ0BQNuaWwJAM4IAgkAzggCCQDOCAIFA2FjYwUNcmV3YXJkX2FjdGlvbgUMc3BlZWRfYWN0aW9uBQtsZWZ0X2FjdGlvbgQRcGVyaW9kX2Fzc2V0X2xlZnQJAGgCBRJwZXJpb2RfYXNzZXRfc3BlZWQFBnBlcmlvZAQRcGVyaW9kX2Fzc2V0X2R1c3QJAGUCBRRwZXJpb2RfYXNzZXRfYmFsYW5jZQURcGVyaW9kX2Fzc2V0X2xlZnQEE3BlcmlvZF9hc3NldF9jb250b2wJAGUCBQ5fYXNzZXRfYmFsYW5jZQURcGVyaW9kX2Fzc2V0X2R1c3QEB2FjY291bnQJAQ9hY2NvdW50X3Jld2FyZHMCBQVhc3NldAkAZQIFEnBlcmlvZF9uZXdfYmFsYW5jZQURcGVyaW9kX2Fzc2V0X2R1c3QDCQAAAgUHYWNjb3VudAUHYWNjb3VudAkAzggCCQDOCAIFA2FjYwUNcmV3YXJkX2FjdGlvbgkAzAgCCQEMSW50ZWdlckVudHJ5AgkBD2Fzc2V0X3NwZWVkX2tleQEFBWFzc2V0BRJwZXJpb2RfYXNzZXRfc3BlZWQJAMwIAgkBDEludGVnZXJFbnRyeQIJAQ5hc3NldF9sZWZ0X2tleQEFBWFzc2V0BRFwZXJpb2RfYXNzZXRfbGVmdAkAzAgCCQEMSW50ZWdlckVudHJ5AgkBEWFzc2V0X2NvbnRyb2xfa2V5AQUFYXNzZXQFE3BlcmlvZF9hc3NldF9jb250b2wFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgEEc3luYwADBQlpc19raWxsZWQFA25pbAkA/AcEBQR0aGlzAgpjaGVja3BvaW50BQNuaWwFA25pbAESY2hlY2twb2ludF9hY3Rpb25zAAQLc3luY19hY3Rpb24DCQAAAgULc3luY19oZWlnaHQFBkhFSUdIVAUDbmlsCQDMCAIJAQxJbnRlZ2VyRW50cnkCBQ9zeW5jX2hlaWdodF9rZXkFBkhFSUdIVAUDbmlsCQDOCAIFC3N5bmNfYWN0aW9uCgACJGwFDHJld2FyZHNfbGlzdAoAAiRzCQCQAwEFAiRsCgAFJGFjYzAFA25pbAoBBSRmMF8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQEQY2hlY2twb2ludF9hc3NldAIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmMF8yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQITTGlzdCBzaXplIGV4Y2VlZHMgNQkBBSRmMF8yAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgUFJGFjYzAAAAABAAIAAwAEAAUBC3VwZGF0ZV91c2VyAgR1c2VyBmNoYW5nZQQPbmV3X3VzZXJfYW1vdW50CQBkAgkBC3VzZXJfYW1vdW50AQUEdXNlcgUGY2hhbmdlAwkAZgIAAAUPbmV3X3VzZXJfYW1vdW50CQACAQkArAICCQCsAgIJAKwCAgIMYmFkIGFtb3VudDogCQCkAwEJAQEtAQUGY2hhbmdlAhQsIGF2YWlsYWJsZSBhbW91bnQ6IAkApAMBCQELdXNlcl9hbW91bnQBBQR1c2VyBBBuZXdfdG9rZW5fYW1vdW50CQBkAgUMdG9rZW5fYW1vdW50BQZjaGFuZ2UDAwkAZgIJAGQCBRBuZXdfdG9rZW5fYW1vdW50BRN0b2tlbl9sb2NrZWRfYW1vdW50CQENYXNzZXRfYmFsYW5jZQEFBXRva2VuCQAAAgUNcm9vdF9jb250cmFjdAIABwkAAgEJAKwCAgkArAICCQCsAgICIHRva2VuIGJhbGFuY2UgbGVha2FnZSBkZXRlY3RlZDogCQCkAwEFEG5ld190b2tlbl9hbW91bnQCAyA+IAkApAMBCQENYXNzZXRfYmFsYW5jZQEFBXRva2VuBAFzAwkAZgIFDHRva2VuX2Ftb3VudAAACQEEc3luYwAFA25pbAMJAAACBQFzBQFzCgEEZm9sZAIDYWNjBWFzc2V0CQDOCAIFA2FjYwQNX2Fzc2V0X3Jld2FyZAkBDGFzc2V0X3Jld2FyZAEFBWFzc2V0BBRfdXNlcl9hc3NldF9hZGp1c3RlZAkBE3VzZXJfYXNzZXRfYWRqdXN0ZWQCBQR1c2VyBQVhc3NldAQQbmV3X2Fzc2V0X3Jld2FyZAMJAAACBQx0b2tlbl9hbW91bnQAAAUNX2Fzc2V0X3Jld2FyZAkAawMFDV9hc3NldF9yZXdhcmQFEG5ld190b2tlbl9hbW91bnQFDHRva2VuX2Ftb3VudAQXbmV3X3VzZXJfYXNzZXRfYWRqdXN0ZWQJAGQCBRRfdXNlcl9hc3NldF9hZGp1c3RlZAMJAAACBRBuZXdfdG9rZW5fYW1vdW50AAAFDV9hc3NldF9yZXdhcmQJAQEtAQkAawMFEG5ld19hc3NldF9yZXdhcmQFBmNoYW5nZQUQbmV3X3Rva2VuX2Ftb3VudAQNcmV3YXJkX2FjdGlvbgMJAAACBQ1fYXNzZXRfcmV3YXJkBRBuZXdfYXNzZXRfcmV3YXJkBQNuaWwJAMwIAgkBDEludGVnZXJFbnRyeQIJARBhc3NldF9yZXdhcmRfa2V5AQUFYXNzZXQFEG5ld19hc3NldF9yZXdhcmQFA25pbAQNYWRqdXN0X2FjdGlvbgMJAAACBRRfdXNlcl9hc3NldF9hZGp1c3RlZAUXbmV3X3VzZXJfYXNzZXRfYWRqdXN0ZWQFA25pbAkAzAgCCQEMSW50ZWdlckVudHJ5AgkBF3VzZXJfYXNzZXRfYWRqdXN0ZWRfa2V5AgUEdXNlcgUFYXNzZXQFF25ld191c2VyX2Fzc2V0X2FkanVzdGVkBQNuaWwJAM4IAgUNcmV3YXJkX2FjdGlvbgUNYWRqdXN0X2FjdGlvbgQaZmlyc3RfcG9vbF9kZXBvc2l0X2FjdGlvbnMDCQEJaXNEZWZpbmVkAQkAmggCBQR0aGlzAhRmaXJzdF9kZXBvc2l0X2hlaWdodAUDbmlsCQDMCAIJAQxJbnRlZ2VyRW50cnkCAhRmaXJzdF9kZXBvc2l0X2hlaWdodAUGSEVJR0hUBQNuaWwEDHN0b3BfYWN0aW9ucwMJAAACBRBuZXdfdG9rZW5fYW1vdW50AAAJAQxzdG9wX3Jld2FyZHMABQNuaWwJAM4IAgkAzggCCQDOCAIJAMwIAgkBDEludGVnZXJFbnRyeQIFEHRva2VuX2Ftb3VudF9rZXkFEG5ld190b2tlbl9hbW91bnQJAMwIAgkBDEludGVnZXJFbnRyeQIJAQ91c2VyX2Ftb3VudF9rZXkBBQR1c2VyBQ9uZXdfdXNlcl9hbW91bnQFA25pbAoAAiRsBQxyZXdhcmRzX2xpc3QKAAIkcwkAkAMBBQIkbAoABSRhY2MwBQNuaWwKAQUkZjBfMQICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkBBGZvbGQCBQIkYQkAkQMCBQIkbAUCJGkKAQUkZjBfMgICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkAAgECE0xpc3Qgc2l6ZSBleGNlZWRzIDUJAQUkZjBfMgIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIFBSRhY2MwAAAAAQACAAMABAAFBQxzdG9wX2FjdGlvbnMFGmZpcnN0X3Bvb2xfZGVwb3NpdF9hY3Rpb25zCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuARJ1cGRhdGVfdXNlcl9sb2NrZWQCBmNhbGxlcgZjaGFuZ2UEBHVzZXIJAKUIAQUGY2FsbGVyBAskdDA5NDY2OTUyNAkBEnVzZXJfbG9ja2VkX3ZhbHVlcwEFBHVzZXIEBmxvY2tlZAgFCyR0MDk0NjY5NTI0Al8xBAVzdGFydAgFCyR0MDk0NjY5NTI0Al8yBAZmaW5pc2gIBQskdDA5NDY2OTUyNAJfMwMJAAACBQZjaGFuZ2UA////////////AQQFc3BlZWQJAGsDBQZsb2NrZWQFDWxvY2tlZF9wZXJpb2QJAGUCBQZmaW5pc2gFBXN0YXJ0BAh1bmxvY2tlZAkAawMFBXNwZWVkCQBlAgUGSEVJR0hUBQVzdGFydAUNbG9ja2VkX3BlcmlvZAQJYXZhaWxhYmxlCQCXAwEJAMwIAgUIdW5sb2NrZWQJAMwIAgUGbG9ja2VkBQNuaWwDAwkAZwIAAAUGbG9ja2VkBgkAZwIAAAUJYXZhaWxhYmxlCQACAQIQbm90aGluZyB0byBjbGFpbQQKbmV3X2xvY2tlZAkAZQIFBmxvY2tlZAUJYXZhaWxhYmxlBAluZXdfc3RhcnQFBkhFSUdIVAQKbmV3X2ZpbmlzaAUGZmluaXNoCQDOCAIJAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwUGY2FsbGVyBQlhdmFpbGFibGUJAQVhc3NldAEFBXRva2VuCQDMCAIJAQxJbnRlZ2VyRW50cnkCBRd0b2tlbl9sb2NrZWRfYW1vdW50X2tleQkAZQIFE3Rva2VuX2xvY2tlZF9hbW91bnQFCWF2YWlsYWJsZQUDbmlsCQDMCAIDCQAAAgUKbmV3X2xvY2tlZAAACQELRGVsZXRlRW50cnkBCQEPdXNlcl9sb2NrZWRfa2V5AQUEdXNlcgkBC1N0cmluZ0VudHJ5AgkBD3VzZXJfbG9ja2VkX2tleQEFBHVzZXIJAKwCAgkArAICCQCsAgIJAKwCAgkApAMBBQpuZXdfbG9ja2VkAgFfCQCkAwEFCW5ld19zdGFydAIBXwkApAMBBQpuZXdfZmluaXNoBQNuaWwECm5ld19sb2NrZWQJAGQCBQZsb2NrZWQFBmNoYW5nZQQJbmV3X3N0YXJ0BQZIRUlHSFQECm5ld19maW5pc2gJAGQCBQZIRUlHSFQFDWxvY2tlZF9wZXJpb2QJAMwIAgkBDEludGVnZXJFbnRyeQIFF3Rva2VuX2xvY2tlZF9hbW91bnRfa2V5CQBkAgUTdG9rZW5fbG9ja2VkX2Ftb3VudAUGY2hhbmdlCQDMCAIJAQtTdHJpbmdFbnRyeQIJAQ91c2VyX2xvY2tlZF9rZXkBBQR1c2VyCQCsAgIJAKwCAgkArAICCQCsAgIJAKQDAQUKbmV3X2xvY2tlZAIBXwkApAMBBQluZXdfc3RhcnQCAV8JAKQDAQUKbmV3X2ZpbmlzaAUDbmlsARBjaGVja1Jld2FyZHNMaXN0AghfcmV3YXJkcwZfdG9rZW4EDV9yZXdhcmRzX2xpc3QJALUJAgUIX3Jld2FyZHMCASwDCQBmAgkAkAMBBQ1fcmV3YXJkc19saXN0BQtNQVhfUkVXQVJEUwkAAgECEHRvbyBtYW55IHJld2FyZHMKAQRmb2xkAgNhY2MFYXNzZXQDCQAAAgkBCmNoZWNrQXNzZXQBBQVhc3NldAUGX3Rva2VuCQACAQIacmV3YXJkIGNhbm5vdCBiZSB0aGUgdG9rZW4DCQEPY29udGFpbnNFbGVtZW50AgUDYWNjBQVhc3NldAkAAgECGWR1cGxpY2F0ZWQgcmV3YXJkIGluIGxpc3QJAM4IAgUDYWNjCQDMCAIFBWFzc2V0BQNuaWwJALkJAgoAAiRsBQ1fcmV3YXJkc19saXN0CgACJHMJAJADAQUCJGwKAAUkYWNjMAUDbmlsCgEFJGYwXzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAQRmb2xkAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGYwXzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhNMaXN0IHNpemUgZXhjZWVkcyA1CQEFJGYwXzICCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECBQUkYWNjMAAAAAEAAgADAAQABQIBLBEDbXNnAQdkZXBvc2l0AAMJAQIhPQIJAJADAQgFA21zZwhwYXltZW50cwABCQACAQIjd3JvbmcgcGF5bWVudHMsIHNob3VsZCBiZSAxIHBheW1lbnQEB3BheW1lbnQJAJEDAggFA21zZwhwYXltZW50cwAAAwkBAiE9AgkBDGFzc2V0X3N0cmluZwEIBQdwYXltZW50B2Fzc2V0SWQFBXRva2VuCQACAQkArAICCQCsAgIJAKwCAgINd3JvbmcgdG9rZW46IAkBDGFzc2V0X3N0cmluZwEIBQdwYXltZW50B2Fzc2V0SWQCBCAhPSAFBXRva2VuAwkAZwIAAAgFB3BheW1lbnQGYW1vdW50CQACAQIgd3JvbmcgYW1vdW50LCBzaG91bGQgYmUgcG9zaXRpdmUEEnJvb3RfaW52b2tlX3Jlc3VsdAMJAAACBQ1yb290X2NvbnRyYWN0AgAFA25pbAkA/AcECQERZ2V0QWRkcmVzc09yQWxpYXMBBQ1yb290X2NvbnRyYWN0AgxzdGFrZVBvb2xMcHMFA25pbAkAzAgCBQdwYXltZW50BQNuaWwDCQAAAgUScm9vdF9pbnZva2VfcmVzdWx0BRJyb290X2ludm9rZV9yZXN1bHQJAQt1cGRhdGVfdXNlcgIJAKUIAQgFA21zZwZjYWxsZXIIBQdwYXltZW50BmFtb3VudAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgNtc2cBBnVubG9jawEGYW1vdW50AwkBAiE9AgkAkAMBCAUDbXNnCHBheW1lbnRzAAAJAAIBAh93cm9uZyBwYXltZW50cywgc2hvdWxkIGJlIGVtcHR5AwkAZwIAAAUGYW1vdW50CQACAQIgd3JvbmcgYW1vdW50LCBzaG91bGQgYmUgcG9zaXRpdmUEGHJvb3RfY29udHJhY3Rfd2l0aGRyYXdhbAMJAAACBQ1yb290X2NvbnRyYWN0AgAFA25pbAkA/AcECQERZ2V0QWRkcmVzc09yQWxpYXMBBQ1yb290X2NvbnRyYWN0Ag93aXRoZHJhd1Bvb2xMcHMJAMwIAgUGYW1vdW50BQNuaWwFA25pbAMJAAACBRhyb290X2NvbnRyYWN0X3dpdGhkcmF3YWwFGHJvb3RfY29udHJhY3Rfd2l0aGRyYXdhbAkAzggCCQELdXBkYXRlX3VzZXICCQClCAEIBQNtc2cGY2FsbGVyCQEBLQEFBmFtb3VudAkBEnVwZGF0ZV91c2VyX2xvY2tlZAIIBQNtc2cGY2FsbGVyBQZhbW91bnQJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4DbXNnAQ5jbGFpbV91bmxvY2tlZAADCQECIT0CCQCQAwEIBQNtc2cIcGF5bWVudHMAAAkAAgECH3dyb25nIHBheW1lbnRzLCBzaG91bGQgYmUgZW1wdHkJARJ1cGRhdGVfdXNlcl9sb2NrZWQCCAUDbXNnBmNhbGxlcgD///////////8BA21zZwEId2l0aGRyYXcBBmFtb3VudAMJAQIhPQIJAJADAQgFA21zZwhwYXltZW50cwAACQACAQIfd3JvbmcgcGF5bWVudHMsIHNob3VsZCBiZSBlbXB0eQMJAGcCAAAFBmFtb3VudAkAAgECIHdyb25nIGFtb3VudCwgc2hvdWxkIGJlIHBvc2l0aXZlAwkBAiE9AgUNbG9ja2VkX3BlcmlvZAAACQACAQI3dXNlIHVubG9jaygpL2NsYWltX3VubG9ja2VkKCkgd2hpbGUgbG9ja2luZ19wZXJpb2QgIT0gMAQYcm9vdF9jb250cmFjdF93aXRoZHJhd2FsAwkAAAIFDXJvb3RfY29udHJhY3QCAAUDbmlsCQD8BwQJARFnZXRBZGRyZXNzT3JBbGlhcwEFDXJvb3RfY29udHJhY3QCD3dpdGhkcmF3UG9vbExwcwkAzAgCBQZhbW91bnQFA25pbAUDbmlsAwkAAAIFGHJvb3RfY29udHJhY3Rfd2l0aGRyYXdhbAUYcm9vdF9jb250cmFjdF93aXRoZHJhd2FsCQDOCAIJAQt1cGRhdGVfdXNlcgIJAKUIAQgFA21zZwZjYWxsZXIJAQEtAQUGYW1vdW50CQDMCAIJAQ5TY3JpcHRUcmFuc2ZlcgMIBQNtc2cGY2FsbGVyBQZhbW91bnQJAQVhc3NldAEFBXRva2VuBQNuaWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4DbXNnAQVjbGFpbQADCQECIT0CCQCQAwEIBQNtc2cIcGF5bWVudHMAAAkAAgECH3dyb25nIHBheW1lbnRzLCBzaG91bGQgYmUgZW1wdHkEE3Jvb3RfY29udHJhY3RfY2xhaW0DCQAAAgUNcm9vdF9jb250cmFjdAIABQNuaWwJAPwHBAkBEWdldEFkZHJlc3NPckFsaWFzAQUNcm9vdF9jb250cmFjdAIQY2xhaW1Qb29sUmV3YXJkcwkAzAgCCQDYBAEIBQR0aGlzBWJ5dGVzBQNuaWwFA25pbAMJAAACBRNyb290X2NvbnRyYWN0X2NsYWltBRNyb290X2NvbnRyYWN0X2NsYWltBAFzAwkAZgIFDHRva2VuX2Ftb3VudAAACQEEc3luYwAFA25pbAMJAAACBQFzBQFzBAR1c2VyCQClCAEIBQNtc2cGY2FsbGVyCgEEZm9sZAIDYWNjBWFzc2V0CQDOCAIFA2FjYwQNX2Fzc2V0X3Jld2FyZAkBDGFzc2V0X3Jld2FyZAEFBWFzc2V0BAthY2N1bXVsYXRlZAkAZAIJARN1c2VyX2Fzc2V0X2FkanVzdGVkAgUEdXNlcgUFYXNzZXQDCQAAAgUMdG9rZW5fYW1vdW50AAAAAAkAawMFDV9hc3NldF9yZXdhcmQJAQt1c2VyX2Ftb3VudAEFBHVzZXIFDHRva2VuX2Ftb3VudAQHY2xhaW1lZAkBEnVzZXJfYXNzZXRfY2xhaW1lZAIFBHVzZXIFBWFzc2V0BAZhbW91bnQJAGUCBQthY2N1bXVsYXRlZAUHY2xhaW1lZAMJAAACBQZhbW91bnQAAAUDbmlsAwkAZgIAAAUGYW1vdW50CQACAQkArAICCQCsAgIFBWFzc2V0AhwgYmFkIGNsYWltIGFtb3VudCBkZXRlY3RlZDogCQCkAwEFBmFtb3VudAQOX2Fzc2V0X2NvbnRyb2wJAQ1hc3NldF9jb250cm9sAQUFYXNzZXQJAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwgFA21zZwZjYWxsZXIFBmFtb3VudAkBBWFzc2V0AQUFYXNzZXQJAMwIAgkBDEludGVnZXJFbnRyeQIJARZ1c2VyX2Fzc2V0X2NsYWltZWRfa2V5AgUEdXNlcgUFYXNzZXQJAGQCBQdjbGFpbWVkBQZhbW91bnQJAMwIAgkBDEludGVnZXJFbnRyeQIJARFhc3NldF9jb250cm9sX2tleQEFBWFzc2V0CQBlAgUOX2Fzc2V0X2NvbnRyb2wFBmFtb3VudAUDbmlsBA1jbGFpbV9hY3Rpb25zCgACJGwFDHJld2FyZHNfbGlzdAoAAiRzCQCQAwEFAiRsCgAFJGFjYzAFA25pbAoBBSRmMF8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQEEZm9sZAIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmMF8yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQITTGlzdCBzaXplIGV4Y2VlZHMgNQkBBSRmMF8yAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgUFJGFjYzAAAAABAAIAAwAEAAUDCQAAAgkAkAMBBQ1jbGFpbV9hY3Rpb25zAAAJAAIBAhBub3RoaW5nIHRvIGNsYWltBQ1jbGFpbV9hY3Rpb25zCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuA21zZwEQY2xhaW1hYmxlX3Rva2VucwEEdXNlcgkAlAoCBQNuaWwJAQt1c2VyX2Ftb3VudAEFBHVzZXIDbXNnAQ5jbGFpbWVkX3Jld2FyZAIEdXNlcgVhc3NldAkAlAoCBQNuaWwJARJ1c2VyX2Fzc2V0X2NsYWltZWQCBQR1c2VyBQVhc3NldANtc2cBEGNsYWltYWJsZV9yZXdhcmQCBHVzZXIFYXNzZXQEAXMDCQBmAgUMdG9rZW5fYW1vdW50AAAJAQRzeW5jAAUDbmlsAwkAAAIFAXMFAXMEDV9hc3NldF9yZXdhcmQJAQxhc3NldF9yZXdhcmQBBQVhc3NldAQLYWNjdW11bGF0ZWQJAGQCCQETdXNlcl9hc3NldF9hZGp1c3RlZAIFBHVzZXIFBWFzc2V0AwkAAAIFDHRva2VuX2Ftb3VudAAAAAAJAGsDBQ1fYXNzZXRfcmV3YXJkCQELdXNlcl9hbW91bnQBBQR1c2VyBQx0b2tlbl9hbW91bnQEB2NsYWltZWQJARJ1c2VyX2Fzc2V0X2NsYWltZWQCBQR1c2VyBQVhc3NldAQGYW1vdW50CQBlAgULYWNjdW11bGF0ZWQFB2NsYWltZWQJAJQKAgUDbmlsBQZhbW91bnQJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4DbXNnARR1c2VyX2xvY2tlZF9yZWFkb25seQEEdXNlcgQNJHQwMTU0MzcxNTQ5NQkBEnVzZXJfbG9ja2VkX3ZhbHVlcwEFBHVzZXIEBmxvY2tlZAgFDSR0MDE1NDM3MTU0OTUCXzEEBXN0YXJ0CAUNJHQwMTU0MzcxNTQ5NQJfMgQGZmluaXNoCAUNJHQwMTU0MzcxNTQ5NQJfMwQFc3BlZWQJAGsDBQZsb2NrZWQFDWxvY2tlZF9wZXJpb2QJAGUCBQZmaW5pc2gFBXN0YXJ0BAh1bmxvY2tlZAkAawMFBXNwZWVkCQBlAgUGSEVJR0hUBQVzdGFydAUNbG9ja2VkX3BlcmlvZAQJYXZhaWxhYmxlCQCXAwEJAMwIAgUIdW5sb2NrZWQJAMwIAgUGbG9ja2VkBQNuaWwJAJQKAgUDbmlsCQCsAgIJAKwCAgkApAMBBQZsb2NrZWQCAV8JAKQDAQUJYXZhaWxhYmxlA21zZwEKY2hlY2twb2ludAADBQlpc19raWxsZWQJAAIBAhRjaGVja3BvaW50IGlzIGtpbGxlZAMDCQAAAgUMdG9rZW5fYW1vdW50AAAJAQIhPQIIBQNtc2cGY2FsbGVyBQR0aGlzBwkAAgECFmNoZWNrcG9pbnQgdW5hdmFpbGFibGUJARJjaGVja3BvaW50X2FjdGlvbnMAA21zZwEEaW5pdAcGX293bmVyBl90b2tlbghfcmV3YXJkcwdfcGVyaW9kDl9sb2NrZWRfcGVyaW9kBV90d2FwDl9yb290X2NvbnRyYWN0AwkBCWlzRGVmaW5lZAEJAJ0IAgUEdGhpcwIFdG9rZW4JAAIBAhNhbHJlYWR5IGluaXRpYWxpemVkAwkBAiE9AggFA21zZwZjYWxsZXIFBHRoaXMJAAIBAhhzZWxmIGluaXRpYWxpemF0aW9uIG9ubHkDCQBnAgAABQdfcGVyaW9kCQACAQIKYmFkIHBlcmlvZAMJAGYCAAAFDl9sb2NrZWRfcGVyaW9kCQACAQIRYmFkIGxvY2tlZF9wZXJpb2QJAMwIAgkBC1N0cmluZ0VudHJ5AgIFb3duZXIJAQxjaGVja0FkZHJlc3MBBQZfb3duZXIJAMwIAgkBC1N0cmluZ0VudHJ5AgIFdG9rZW4JAQpjaGVja0Fzc2V0AQUGX3Rva2VuCQDMCAIJAQtTdHJpbmdFbnRyeQICB3Jld2FyZHMJARBjaGVja1Jld2FyZHNMaXN0AgUIX3Jld2FyZHMFBl90b2tlbgkAzAgCCQEMSW50ZWdlckVudHJ5AgIGcGVyaW9kBQdfcGVyaW9kCQDMCAIJAQxJbnRlZ2VyRW50cnkCAg1sb2NrZWRfcGVyaW9kBQ5fbG9ja2VkX3BlcmlvZAkAzAgCCQELU3RyaW5nRW50cnkCAg1yb290X2NvbnRyYWN0AwkAAAIFDl9yb290X2NvbnRyYWN0AgACAAkBE2NoZWNrQWRkcmVzc09yQWxpYXMBBQ5fcm9vdF9jb250cmFjdAkAzAgCCQELU3RyaW5nRW50cnkCAgR0d2FwAwkAAAIFBV90d2FwAgACAAkBE2NoZWNrQWRkcmVzc09yQWxpYXMBBQVfdHdhcAkAzAgCCQEMQm9vbGVhbkVudHJ5AgIJaXNfa2lsbGVkBwUDbmlsA21zZwEKYWRkX3Jld2FyZAEGcmV3YXJkAwkBAiE9AggFA21zZwZjYWxsZXIFBW93bmVyCQACAQIKb25seSBvd25lcgkAzAgCCQELU3RyaW5nRW50cnkCAgdyZXdhcmRzCQEQY2hlY2tSZXdhcmRzTGlzdAIJAKwCAgkArAICBQdyZXdhcmRzAgEsBQZyZXdhcmQFBXRva2VuBQNuaWwDbXNnAQpzZXRfa2lsbGVkAQpfaXNfa2lsbGVkAwkBAiE9AggFA21zZwZjYWxsZXIFBW93bmVyCQACAQIKb25seSBvd25lcgMJAAACBQlpc19raWxsZWQFCl9pc19raWxsZWQJAAIBAgpzYW1lIHN0YXRlBAxzdG9wX2FjdGlvbnMDBQpfaXNfa2lsbGVkCQEMc3RvcF9yZXdhcmRzAAUDbmlsCQDOCAIJAMwIAgkBDEJvb2xlYW5FbnRyeQICCWlzX2tpbGxlZAUKX2lzX2tpbGxlZAUDbmlsBQxzdG9wX2FjdGlvbnMDbXNnAThjbGFpbV9yZXdhcmRzX2FuZF93aXRoZHJhd19hbGxfdG9rZW5zX2Zyb21fcm9vdF9jb250cmFjdAADCQECIT0CCAUDbXNnBmNhbGxlcgUFb3duZXIJAAIBAgpvbmx5IG93bmVyAwkAAAIFDHRva2VuX2Ftb3VudAAACQACAQIQbm90aGluZyB0byBjbGFpbQQYcm9vdF9jb250cmFjdF93aXRoZHJhd2FsAwkAAAIFDXJvb3RfY29udHJhY3QCAAUDbmlsCQD8BwQJARFnZXRBZGRyZXNzT3JBbGlhcwEFDXJvb3RfY29udHJhY3QCD3dpdGhkcmF3UG9vbExwcwkAzAgCBQx0b2tlbl9hbW91bnQFA25pbAUDbmlsAwkAAAIFGHJvb3RfY29udHJhY3Rfd2l0aGRyYXdhbAUYcm9vdF9jb250cmFjdF93aXRoZHJhd2FsCQDMCAIJAQtTdHJpbmdFbnRyeQICDXJvb3RfY29udHJhY3QCAAUDbmlsCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuA21zZwESc2V0X2hlaWdodF9hZGRyZXNzAQ5faGVpZ2h0QWRkcmVzcwMJAQIhPQIIBQNtc2cGY2FsbGVyBQVvd25lcgkAAgECCm9ubHkgb3duZXIJAMwIAgkBC1N0cmluZ0VudHJ5AgINaGVpZ2h0QWRkcmVzcwkBDGNoZWNrQWRkcmVzcwEFDl9oZWlnaHRBZGRyZXNzBQNuaWwDbXNnASNpbnZhbGlkYXRlX3Jvb3RfY29udHJhY3RfY29ubmVjdGlvbgADCQAAAgUNcm9vdF9jb250cmFjdAIACQACAQIYcm9vdCBjb250cmFjdCBpcyBub3Qgc2V0AwkBAiE9AggFA21zZwZjYWxsZXIJARFnZXRBZGRyZXNzT3JBbGlhcwEFDXJvb3RfY29udHJhY3QJAAIBAhJvbmx5IHJvb3QgY29udHJhY3QJAMwIAgkBC1N0cmluZ0VudHJ5AgINcm9vdF9jb250cmFjdAIABQNuaWwBaQEMc2V0X3ZlcmlmaWVyAQh2ZXJpZmllcgMJAQIhPQIIBQFpBmNhbGxlcgUEdGhpcwkAAgECDnNlbGYgY2FsbCBvbmx5BAlhZGRyZXNzT0sEByRtYXRjaDAJAKYIAQUIdmVyaWZpZXIDCQABAgUHJG1hdGNoMAIHQWRkcmVzcwQBYQUHJG1hdGNoMAYHAwkBASEBBQlhZGRyZXNzT0sJAAIBCQCsAgICF3ZlcmlmaWVyIHdyb25nIGFkZHJlc3MgBQh2ZXJpZmllcgMJAQlpc0RlZmluZWQBCQCdCAIFBHRoaXMCCHZlcmlmaWVyCQACAQIYdmVyaWZpZXIgYWxyZWFkeSBkZWZpbmVkCQDMCAIJAQtTdHJpbmdFbnRyeQICCHZlcmlmaWVyBQh2ZXJpZmllcgUDbmlsAQJ0eAEGdmVyaWZ5AAQHJG1hdGNoMAkAnQgCBQR0aGlzAgh2ZXJpZmllcgMJAAECBQckbWF0Y2gwAgZTdHJpbmcECHZlcmlmaWVyBQckbWF0Y2gwCQELdmFsdWVPckVsc2UCCQCbCAIJARFAZXh0ck5hdGl2ZSgxMDYyKQEFCHZlcmlmaWVyCQCsAgIJAKwCAgkArAICAgdzdGF0dXNfCQClCAEFBHRoaXMCAV8JANgEAQgFAnR4AmlkBwkA9AMDCAUCdHgJYm9keUJ5dGVzCQCRAwIIBQJ0eAZwcm9vZnMAAAgFAnR4D3NlbmRlclB1YmxpY0tleb2rU94=", "height": 3963882, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: none Next: 53M5WNX1HunzzNRMGF28gzGb9oZscTNcSQnwwoMhXjU9 Full:
OldNewDifferences
1-# no script
1+{-# STDLIB_VERSION 6 #-}
2+{-# SCRIPT_TYPE ACCOUNT #-}
3+{-# CONTENT_TYPE DAPP #-}
4+let MAX_REWARDS = 5
5+
6+let owner = addressFromStringValue(getStringValue(this, "owner"))
7+
8+let root_contract = valueOrElse(getString(this, "root_contract"), "")
9+
10+let token = getStringValue(this, "token")
11+
12+let rewards = getStringValue(this, "rewards")
13+
14+let rewards_list = split(rewards, ",")
15+
16+let period = getIntegerValue(this, "period")
17+
18+let is_killed = getBooleanValue(this, "is_killed")
19+
20+let twap = valueOrElse(getString(this, "twap"), "")
21+
22+let heightAddress = valueOrErrorMessage(addressFromString(valueOrErrorMessage(getString(this, "heightAddress"), "no settings defined")), "bad settings address")
23+
24+let HEIGHT = height
25+
26+let sync_height_key = "sync_height"
27+
28+let sync_height = valueOrElse(getInteger(this, sync_height_key), 0)
29+
30+let token_amount_key = "tokens"
31+
32+let token_amount = valueOrElse(getInteger(this, token_amount_key), 0)
33+
34+func user_amount_key (user) = (user + "_amount")
35+
36+
37+func user_amount (user) = valueOrElse(getInteger(this, user_amount_key(user)), 0)
38+
39+
40+let token_locked_amount_key = "tokens_locked"
41+
42+let token_locked_amount = valueOrElse(getInteger(this, token_locked_amount_key), 0)
43+
44+let locked_period = getIntegerValue(this, "locked_period")
45+
46+func user_locked_key (user) = (user + "_locked")
47+
48+
49+func user_locked_values (user) = {
50+ let l = split(valueOrElse(getString(this, user_locked_key(user)), "0_0_0"), "_")
51+ $Tuple3(parseIntValue(l[0]), parseIntValue(l[1]), parseIntValue(l[2]))
52+ }
53+
54+
55+func user_asset_adjusted_key (user,asset) = (((user + "_") + asset) + "_adjusted")
56+
57+
58+func user_asset_adjusted (user,asset) = valueOrElse(getInteger(this, user_asset_adjusted_key(user, asset)), 0)
59+
60+
61+func user_asset_claimed_key (user,asset) = (((user + "_") + asset) + "_claimed")
62+
63+
64+func user_asset_claimed (user,asset) = valueOrElse(getInteger(this, user_asset_claimed_key(user, asset)), 0)
65+
66+
67+func asset_reward_key (asset) = (asset + "_reward")
68+
69+
70+func asset_reward (asset) = valueOrElse(getInteger(this, asset_reward_key(asset)), 0)
71+
72+
73+func asset_speed_key (asset) = (asset + "_speed")
74+
75+
76+func asset_speed (asset) = valueOrElse(getInteger(this, asset_speed_key(asset)), 0)
77+
78+
79+func asset_left_key (asset) = (asset + "_left")
80+
81+
82+func asset_left (asset) = valueOrElse(getInteger(this, asset_left_key(asset)), 0)
83+
84+
85+func asset_control_key (asset) = (asset + "_control")
86+
87+
88+func asset_control (asset) = valueOrElse(getInteger(this, asset_control_key(asset)), 0)
89+
90+
91+func checkAddress (a58) = {
92+ let a = addressFromStringValue(a58)
93+ toString(a)
94+ }
95+
96+
97+func getAddressOrAlias (string) = match addressFromString(string) {
98+ case a: Address =>
99+ a
100+ case _ =>
101+ Alias(string)
102+}
103+
104+
105+func checkAddressOrAlias (string) = {
106+ let address = match addressFromString(string) {
107+ case a: Address =>
108+ a
109+ case _ =>
110+ addressFromRecipient(Alias(string))
111+ }
112+ if ((address == address))
113+ then string
114+ else throw("Strict value is not equal to itself.")
115+ }
116+
117+
118+func checkAsset (asset58) = if ((asset58 == "WAVES"))
119+ then "WAVES"
120+ else {
121+ let asset = valueOrErrorMessage(fromBase58String(asset58), ("wrong asset encoding: " + asset58))
122+ let info = valueOrErrorMessage(assetInfo(asset), ("wrong asset info: " + asset58))
123+ if ((info == info))
124+ then asset58
125+ else throw("Strict value is not equal to itself.")
126+ }
127+
128+
129+func asset (a) = if ((a == "WAVES"))
130+ then unit
131+ else fromBase58String(a)
132+
133+
134+func asset_string (a) = match a {
135+ case b: ByteVector =>
136+ toBase58String(b)
137+ case _ =>
138+ "WAVES"
139+}
140+
141+
142+func asset_balance (a) = if ((a == "WAVES"))
143+ then wavesBalance(this).available
144+ else assetBalance(this, fromBase58String(a))
145+
146+
147+func account_rewards (asset,amount) = if ((twap == ""))
148+ then nil
149+ else invoke(getAddressOrAlias(twap), "push", [asset, token, amount, token_amount, "%"], nil)
150+
151+
152+func stop_rewards () = {
153+ func fold (acc,asset) = (acc ++ [IntegerEntry(asset_speed_key(asset), 0)])
154+
155+ let $l = rewards_list
156+ let $s = size($l)
157+ let $acc0 = nil
158+ func $f0_1 ($a,$i) = if (($i >= $s))
159+ then $a
160+ else fold($a, $l[$i])
161+
162+ func $f0_2 ($a,$i) = if (($i >= $s))
163+ then $a
164+ else throw("List size exceeds 5")
165+
166+ $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5)
167+ }
168+
169+
170+func checkpoint_asset (acc,asset) = {
171+ let _asset_reward = asset_reward(asset)
172+ let _asset_speed = asset_speed(asset)
173+ let _asset_left = asset_left(asset)
174+ let estimate_reward = ((HEIGHT - sync_height) * _asset_speed)
175+ let real_reward = if ((estimate_reward > _asset_left))
176+ then _asset_left
177+ else estimate_reward
178+ let claim_asset_reward = (_asset_reward + real_reward)
179+ let claim_asset_left = (_asset_left - real_reward)
180+ let claim_asset_speed = if ((claim_asset_left > 0))
181+ then _asset_speed
182+ else 0
183+ let reward_action = if ((claim_asset_reward == _asset_reward))
184+ then nil
185+ else [IntegerEntry(asset_reward_key(asset), claim_asset_reward)]
186+ let _asset_balance = asset_balance(asset)
187+ let _asset_control = asset_control(asset)
188+ if ((_asset_control > _asset_balance))
189+ then throw(((((asset + " balance leakage detected: ") + toString(_asset_control)) + " > ") + toString(_asset_balance)))
190+ else {
191+ let period_new_balance = (_asset_balance - _asset_control)
192+ let period_asset_balance = (claim_asset_left + period_new_balance)
193+ let period_asset_speed = (period_asset_balance / period)
194+ if (if ((claim_asset_speed >= period_asset_speed))
195+ then (claim_asset_left >= period_new_balance)
196+ else false)
197+ then {
198+ let speed_action = if ((claim_asset_speed == _asset_speed))
199+ then nil
200+ else [IntegerEntry(asset_speed_key(asset), claim_asset_speed)]
201+ let left_action = if ((claim_asset_left == _asset_left))
202+ then nil
203+ else [IntegerEntry(asset_left_key(asset), claim_asset_left)]
204+ (((acc ++ reward_action) ++ speed_action) ++ left_action)
205+ }
206+ else {
207+ let period_asset_left = (period_asset_speed * period)
208+ let period_asset_dust = (period_asset_balance - period_asset_left)
209+ let period_asset_contol = (_asset_balance - period_asset_dust)
210+ let account = account_rewards(asset, (period_new_balance - period_asset_dust))
211+ if ((account == account))
212+ then ((acc ++ reward_action) ++ [IntegerEntry(asset_speed_key(asset), period_asset_speed), IntegerEntry(asset_left_key(asset), period_asset_left), IntegerEntry(asset_control_key(asset), period_asset_contol)])
213+ else throw("Strict value is not equal to itself.")
214+ }
215+ }
216+ }
217+
218+
219+func sync () = if (is_killed)
220+ then nil
221+ else invoke(this, "checkpoint", nil, nil)
222+
223+
224+func checkpoint_actions () = {
225+ let sync_action = if ((sync_height == HEIGHT))
226+ then nil
227+ else [IntegerEntry(sync_height_key, HEIGHT)]
228+ (sync_action ++ {
229+ let $l = rewards_list
230+ let $s = size($l)
231+ let $acc0 = nil
232+ func $f0_1 ($a,$i) = if (($i >= $s))
233+ then $a
234+ else checkpoint_asset($a, $l[$i])
235+
236+ func $f0_2 ($a,$i) = if (($i >= $s))
237+ then $a
238+ else throw("List size exceeds 5")
239+
240+ $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5)
241+ })
242+ }
243+
244+
245+func update_user (user,change) = {
246+ let new_user_amount = (user_amount(user) + change)
247+ if ((0 > new_user_amount))
248+ then throw(((("bad amount: " + toString(-(change))) + ", available amount: ") + toString(user_amount(user))))
249+ else {
250+ let new_token_amount = (token_amount + change)
251+ if (if (((new_token_amount + token_locked_amount) > asset_balance(token)))
252+ then (root_contract == "")
253+ else false)
254+ then throw(((("token balance leakage detected: " + toString(new_token_amount)) + " > ") + toString(asset_balance(token))))
255+ else {
256+ let s = if ((token_amount > 0))
257+ then sync()
258+ else nil
259+ if ((s == s))
260+ then {
261+ func fold (acc,asset) = (acc ++ {
262+ let _asset_reward = asset_reward(asset)
263+ let _user_asset_adjusted = user_asset_adjusted(user, asset)
264+ let new_asset_reward = if ((token_amount == 0))
265+ then _asset_reward
266+ else fraction(_asset_reward, new_token_amount, token_amount)
267+ let new_user_asset_adjusted = (_user_asset_adjusted + (if ((new_token_amount == 0))
268+ then _asset_reward
269+ else -(fraction(new_asset_reward, change, new_token_amount))))
270+ let reward_action = if ((_asset_reward == new_asset_reward))
271+ then nil
272+ else [IntegerEntry(asset_reward_key(asset), new_asset_reward)]
273+ let adjust_action = if ((_user_asset_adjusted == new_user_asset_adjusted))
274+ then nil
275+ else [IntegerEntry(user_asset_adjusted_key(user, asset), new_user_asset_adjusted)]
276+ (reward_action ++ adjust_action)
277+ })
278+
279+ let first_pool_deposit_actions = if (isDefined(getInteger(this, "first_deposit_height")))
280+ then nil
281+ else [IntegerEntry("first_deposit_height", HEIGHT)]
282+ let stop_actions = if ((new_token_amount == 0))
283+ then stop_rewards()
284+ else nil
285+ ((([IntegerEntry(token_amount_key, new_token_amount), IntegerEntry(user_amount_key(user), new_user_amount)] ++ {
286+ let $l = rewards_list
287+ let $s = size($l)
288+ let $acc0 = nil
289+ func $f0_1 ($a,$i) = if (($i >= $s))
290+ then $a
291+ else fold($a, $l[$i])
292+
293+ func $f0_2 ($a,$i) = if (($i >= $s))
294+ then $a
295+ else throw("List size exceeds 5")
296+
297+ $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5)
298+ }) ++ stop_actions) ++ first_pool_deposit_actions)
299+ }
300+ else throw("Strict value is not equal to itself.")
301+ }
302+ }
303+ }
304+
305+
306+func update_user_locked (caller,change) = {
307+ let user = toString(caller)
308+ let $t094669524 = user_locked_values(user)
309+ let locked = $t094669524._1
310+ let start = $t094669524._2
311+ let finish = $t094669524._3
312+ if ((change == -1))
313+ then {
314+ let speed = fraction(locked, locked_period, (finish - start))
315+ let unlocked = fraction(speed, (HEIGHT - start), locked_period)
316+ let available = min([unlocked, locked])
317+ if (if ((0 >= locked))
318+ then true
319+ else (0 >= available))
320+ then throw("nothing to claim")
321+ else {
322+ let new_locked = (locked - available)
323+ let new_start = HEIGHT
324+ let new_finish = finish
325+ ([ScriptTransfer(caller, available, asset(token)), IntegerEntry(token_locked_amount_key, (token_locked_amount - available))] ++ [if ((new_locked == 0))
326+ then DeleteEntry(user_locked_key(user))
327+ else StringEntry(user_locked_key(user), ((((toString(new_locked) + "_") + toString(new_start)) + "_") + toString(new_finish)))])
328+ }
329+ }
330+ else {
331+ let new_locked = (locked + change)
332+ let new_start = HEIGHT
333+ let new_finish = (HEIGHT + locked_period)
334+[IntegerEntry(token_locked_amount_key, (token_locked_amount + change)), StringEntry(user_locked_key(user), ((((toString(new_locked) + "_") + toString(new_start)) + "_") + toString(new_finish)))]
335+ }
336+ }
337+
338+
339+func checkRewardsList (_rewards,_token) = {
340+ let _rewards_list = split(_rewards, ",")
341+ if ((size(_rewards_list) > MAX_REWARDS))
342+ then throw("too many rewards")
343+ else {
344+ func fold (acc,asset) = if ((checkAsset(asset) == _token))
345+ then throw("reward cannot be the token")
346+ else if (containsElement(acc, asset))
347+ then throw("duplicated reward in list")
348+ else (acc ++ [asset])
349+
350+ makeString({
351+ let $l = _rewards_list
352+ let $s = size($l)
353+ let $acc0 = nil
354+ func $f0_1 ($a,$i) = if (($i >= $s))
355+ then $a
356+ else fold($a, $l[$i])
357+
358+ func $f0_2 ($a,$i) = if (($i >= $s))
359+ then $a
360+ else throw("List size exceeds 5")
361+
362+ $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5)
363+ }, ",")
364+ }
365+ }
366+
367+
368+@Callable(msg)
369+func deposit () = if ((size(msg.payments) != 1))
370+ then throw("wrong payments, should be 1 payment")
371+ else {
372+ let payment = msg.payments[0]
373+ if ((asset_string(payment.assetId) != token))
374+ then throw(((("wrong token: " + asset_string(payment.assetId)) + " != ") + token))
375+ else if ((0 >= payment.amount))
376+ then throw("wrong amount, should be positive")
377+ else {
378+ let root_invoke_result = if ((root_contract == ""))
379+ then nil
380+ else invoke(getAddressOrAlias(root_contract), "stakePoolLps", nil, [payment])
381+ if ((root_invoke_result == root_invoke_result))
382+ then update_user(toString(msg.caller), payment.amount)
383+ else throw("Strict value is not equal to itself.")
384+ }
385+ }
386+
387+
388+
389+@Callable(msg)
390+func unlock (amount) = if ((size(msg.payments) != 0))
391+ then throw("wrong payments, should be empty")
392+ else if ((0 >= amount))
393+ then throw("wrong amount, should be positive")
394+ else {
395+ let root_contract_withdrawal = if ((root_contract == ""))
396+ then nil
397+ else invoke(getAddressOrAlias(root_contract), "withdrawPoolLps", [amount], nil)
398+ if ((root_contract_withdrawal == root_contract_withdrawal))
399+ then (update_user(toString(msg.caller), -(amount)) ++ update_user_locked(msg.caller, amount))
400+ else throw("Strict value is not equal to itself.")
401+ }
402+
403+
404+
405+@Callable(msg)
406+func claim_unlocked () = if ((size(msg.payments) != 0))
407+ then throw("wrong payments, should be empty")
408+ else update_user_locked(msg.caller, -1)
409+
410+
411+
412+@Callable(msg)
413+func withdraw (amount) = if ((size(msg.payments) != 0))
414+ then throw("wrong payments, should be empty")
415+ else if ((0 >= amount))
416+ then throw("wrong amount, should be positive")
417+ else if ((locked_period != 0))
418+ then throw("use unlock()/claim_unlocked() while locking_period != 0")
419+ else {
420+ let root_contract_withdrawal = if ((root_contract == ""))
421+ then nil
422+ else invoke(getAddressOrAlias(root_contract), "withdrawPoolLps", [amount], nil)
423+ if ((root_contract_withdrawal == root_contract_withdrawal))
424+ then (update_user(toString(msg.caller), -(amount)) ++ [ScriptTransfer(msg.caller, amount, asset(token))])
425+ else throw("Strict value is not equal to itself.")
426+ }
427+
428+
429+
430+@Callable(msg)
431+func claim () = if ((size(msg.payments) != 0))
432+ then throw("wrong payments, should be empty")
433+ else {
434+ let root_contract_claim = if ((root_contract == ""))
435+ then nil
436+ else invoke(getAddressOrAlias(root_contract), "claimPoolRewards", [toBase58String(this.bytes)], nil)
437+ if ((root_contract_claim == root_contract_claim))
438+ then {
439+ let s = if ((token_amount > 0))
440+ then sync()
441+ else nil
442+ if ((s == s))
443+ then {
444+ let user = toString(msg.caller)
445+ func fold (acc,asset) = (acc ++ {
446+ let _asset_reward = asset_reward(asset)
447+ let accumulated = (user_asset_adjusted(user, asset) + (if ((token_amount == 0))
448+ then 0
449+ else fraction(_asset_reward, user_amount(user), token_amount)))
450+ let claimed = user_asset_claimed(user, asset)
451+ let amount = (accumulated - claimed)
452+ if ((amount == 0))
453+ then nil
454+ else if ((0 > amount))
455+ then throw(((asset + " bad claim amount detected: ") + toString(amount)))
456+ else {
457+ let _asset_control = asset_control(asset)
458+[ScriptTransfer(msg.caller, amount, asset(asset)), IntegerEntry(user_asset_claimed_key(user, asset), (claimed + amount)), IntegerEntry(asset_control_key(asset), (_asset_control - amount))]
459+ }
460+ })
461+
462+ let claim_actions = {
463+ let $l = rewards_list
464+ let $s = size($l)
465+ let $acc0 = nil
466+ func $f0_1 ($a,$i) = if (($i >= $s))
467+ then $a
468+ else fold($a, $l[$i])
469+
470+ func $f0_2 ($a,$i) = if (($i >= $s))
471+ then $a
472+ else throw("List size exceeds 5")
473+
474+ $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5)
475+ }
476+ if ((size(claim_actions) == 0))
477+ then throw("nothing to claim")
478+ else claim_actions
479+ }
480+ else throw("Strict value is not equal to itself.")
481+ }
482+ else throw("Strict value is not equal to itself.")
483+ }
484+
485+
486+
487+@Callable(msg)
488+func claimable_tokens (user) = $Tuple2(nil, user_amount(user))
489+
490+
491+
492+@Callable(msg)
493+func claimed_reward (user,asset) = $Tuple2(nil, user_asset_claimed(user, asset))
494+
495+
496+
497+@Callable(msg)
498+func claimable_reward (user,asset) = {
499+ let s = if ((token_amount > 0))
500+ then sync()
501+ else nil
502+ if ((s == s))
503+ then {
504+ let _asset_reward = asset_reward(asset)
505+ let accumulated = (user_asset_adjusted(user, asset) + (if ((token_amount == 0))
506+ then 0
507+ else fraction(_asset_reward, user_amount(user), token_amount)))
508+ let claimed = user_asset_claimed(user, asset)
509+ let amount = (accumulated - claimed)
510+ $Tuple2(nil, amount)
511+ }
512+ else throw("Strict value is not equal to itself.")
513+ }
514+
515+
516+
517+@Callable(msg)
518+func user_locked_readonly (user) = {
519+ let $t01543715495 = user_locked_values(user)
520+ let locked = $t01543715495._1
521+ let start = $t01543715495._2
522+ let finish = $t01543715495._3
523+ let speed = fraction(locked, locked_period, (finish - start))
524+ let unlocked = fraction(speed, (HEIGHT - start), locked_period)
525+ let available = min([unlocked, locked])
526+ $Tuple2(nil, ((toString(locked) + "_") + toString(available)))
527+ }
528+
529+
530+
531+@Callable(msg)
532+func checkpoint () = if (is_killed)
533+ then throw("checkpoint is killed")
534+ else if (if ((token_amount == 0))
535+ then (msg.caller != this)
536+ else false)
537+ then throw("checkpoint unavailable")
538+ else checkpoint_actions()
539+
540+
541+
542+@Callable(msg)
543+func init (_owner,_token,_rewards,_period,_locked_period,_twap,_root_contract) = if (isDefined(getString(this, "token")))
544+ then throw("already initialized")
545+ else if ((msg.caller != this))
546+ then throw("self initialization only")
547+ else if ((0 >= _period))
548+ then throw("bad period")
549+ else if ((0 > _locked_period))
550+ then throw("bad locked_period")
551+ else [StringEntry("owner", checkAddress(_owner)), StringEntry("token", checkAsset(_token)), StringEntry("rewards", checkRewardsList(_rewards, _token)), IntegerEntry("period", _period), IntegerEntry("locked_period", _locked_period), StringEntry("root_contract", if ((_root_contract == ""))
552+ then ""
553+ else checkAddressOrAlias(_root_contract)), StringEntry("twap", if ((_twap == ""))
554+ then ""
555+ else checkAddressOrAlias(_twap)), BooleanEntry("is_killed", false)]
556+
557+
558+
559+@Callable(msg)
560+func add_reward (reward) = if ((msg.caller != owner))
561+ then throw("only owner")
562+ else [StringEntry("rewards", checkRewardsList(((rewards + ",") + reward), token))]
563+
564+
565+
566+@Callable(msg)
567+func set_killed (_is_killed) = if ((msg.caller != owner))
568+ then throw("only owner")
569+ else if ((is_killed == _is_killed))
570+ then throw("same state")
571+ else {
572+ let stop_actions = if (_is_killed)
573+ then stop_rewards()
574+ else nil
575+ ([BooleanEntry("is_killed", _is_killed)] ++ stop_actions)
576+ }
577+
578+
579+
580+@Callable(msg)
581+func claim_rewards_and_withdraw_all_tokens_from_root_contract () = if ((msg.caller != owner))
582+ then throw("only owner")
583+ else if ((token_amount == 0))
584+ then throw("nothing to claim")
585+ else {
586+ let root_contract_withdrawal = if ((root_contract == ""))
587+ then nil
588+ else invoke(getAddressOrAlias(root_contract), "withdrawPoolLps", [token_amount], nil)
589+ if ((root_contract_withdrawal == root_contract_withdrawal))
590+ then [StringEntry("root_contract", "")]
591+ else throw("Strict value is not equal to itself.")
592+ }
593+
594+
595+
596+@Callable(msg)
597+func set_height_address (_heightAddress) = if ((msg.caller != owner))
598+ then throw("only owner")
599+ else [StringEntry("heightAddress", checkAddress(_heightAddress))]
600+
601+
602+
603+@Callable(msg)
604+func invalidate_root_contract_connection () = if ((root_contract == ""))
605+ then throw("root contract is not set")
606+ else if ((msg.caller != getAddressOrAlias(root_contract)))
607+ then throw("only root contract")
608+ else [StringEntry("root_contract", "")]
609+
610+
611+
612+@Callable(i)
613+func set_verifier (verifier) = if ((i.caller != this))
614+ then throw("self call only")
615+ else {
616+ let addressOK = match addressFromString(verifier) {
617+ case a: Address =>
618+ true
619+ case _ =>
620+ false
621+ }
622+ if (!(addressOK))
623+ then throw(("verifier wrong address " + verifier))
624+ else if (isDefined(getString(this, "verifier")))
625+ then throw("verifier already defined")
626+ else [StringEntry("verifier", verifier)]
627+ }
628+
629+
630+@Verifier(tx)
631+func verify () = match getString(this, "verifier") {
632+ case verifier: String =>
633+ valueOrElse(getBoolean(addressFromStringValue(verifier), ((("status_" + toString(this)) + "_") + toBase58String(tx.id))), false)
634+ case _ =>
635+ sigVerify(tx.bodyBytes, tx.proofs[0], tx.senderPublicKey)
636+}
637+

github/deemru/w8io/3ef1775 
32.50 ms