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:
Old | New | Differences | |
---|---|---|---|
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 ◑