tx · F9LfofbxB5P6x84nL3gW9izaVb6Fhac6jQHeEi8csYYR

3ML8v5bA4ibAejHraDqtkGY7JKjLd74SwWd:  -0.02850000 Waves

2025.10.25 02:32 [552316] smart account 3ML8v5bA4ibAejHraDqtkGY7JKjLd74SwWd > SELF 0.00000000 Waves

{ "type": 13, "id": "F9LfofbxB5P6x84nL3gW9izaVb6Fhac6jQHeEi8csYYR", "fee": 2850000, "feeAssetId": null, "timestamp": 1761348736579, "version": 2, "chainId": 82, "sender": "3ML8v5bA4ibAejHraDqtkGY7JKjLd74SwWd", "senderPublicKey": "8a6Cr1eDo69NC8zPFzzzEjkvpQWDZMd5638LmEz2nZbd", "proofs": [ "4Y2qzp1D6jf7J3BBzdsnCvwGy8YKnBdkVWtaunNra2TPzZgvgbWRuY2pG2HtYpbGqcjzPjFPgRNawfoBXXDDPbRS" ], "script": "base64:BgJZCAISBQoDGAEBEgMKAQgSAwoBCBIDCgEIEgMKAQgSAwoBARIICgYICAgICAgSAwoBCBIDCgEIEgMKAQgSCQoHCAgIAQgICBIDCgEIEgMKAQgSAwoBCBIAEgAbAAdWRVJTSU9OAgUxLjAuMAADU0VQAgFfAAZCSUdTRVACAl9fAAhrX0FETUlOUwILQURNSU5TX1BCS1MACmtfTUFOQUdFUlMCDU1BTkFHRVJTX1BCS1MAB2tfTElNSVQCDFZPVEVTX1FVT1JVTQAOa19TQ1JJUFRfVFlQRVMCDFNDUklQVF9UWVBFUwALa19JVEVSQVRJT04CCUlURVJBVElPTgAQa19BUFBST1ZFRF9DT1VOVAIOQVBQUk9WRURfQ09VTlQADGtfc2NyaXB0VHlwZQIKc2NyaXB0VHlwZQAMa19zY3JpcHRIYXNoAgpzY3JpcHRIYXNoABBrX3N0b3JhZ2VBZGRyZXNzAg5zdG9yYWdlQWRkcmVzcwAGa19kZXNjAgRkZXNjAAZrX2l0ZXICCWl0ZXJhdGlvbgALa19pbml0aWF0b3ICCWluaXRpYXRvcgAPa19jb25maXJtYXRpb25zAg1jb25maXJtYXRpb25zAA1rX3Jhd0NvZGVIYXNoAgtyYXdDb2RlSGFzaAEMX3ZhbGlkYXRlUGJrAQNwYmsEB2FkZHJlc3MJAKcIAQkA2QQBBQNwYmsDCQAAAgUHYWRkcmVzcwUHYWRkcmVzcwQKYWRkcmVzc1N0cgkApQgBBQdhZGRyZXNzAwkAAAIFCmFkZHJlc3NTdHIFCmFkZHJlc3NTdHIGCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuARBfdmFsaWRhdGVBZGRyZXNzAQdhZGRyZXNzBARhZGRyCQERQGV4dHJOYXRpdmUoMTA2MikBBQdhZGRyZXNzAwkAAAIFBGFkZHIFBGFkZHIGCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAQtfdmFsaWRhdGVUcwECdHMEBmN1cnJUcwQHJG1hdGNoMAkA7QcBBQZoZWlnaHQDCQABAgUHJG1hdGNoMAIJQmxvY2tJbmZvBAVibG9jawUHJG1hdGNoMAgFBWJsb2NrCXRpbWVzdGFtcAkAAgECEENhbid0IGZpbmQgYmxvY2sEB29uZUhvdXIJAGgCCQBoAgA8ADwA6AcEBW1pblRzCQBlAgUGY3VyclRzBQdvbmVIb3VyCQBnAgUCdHMFBW1pblRzAQxpc1R4QXBwcm92ZWQBA2ludgkBC3ZhbHVlT3JFbHNlAgkAmwgCCQEFdmFsdWUBBQR0aGlzCQCsAgIJAKwCAgkArAICCQClCAEFBHRoaXMCAV8JANgEAQgFA2ludg10cmFuc2FjdGlvbklkAgpfX2FwcHJvdmVkBwEJX2dldExpbWl0AAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCfCAEFB2tfTElNSVQCGFF1b3J1bSBsaW1pdCBub3QgZGVmaW5lZAERX2dldEFwcHJvdmVkQ291bnQACQETdmFsdWVPckVycm9yTWVzc2FnZQIJAJ8IAQUQa19BUFBST1ZFRF9DT1VOVAI1QW1vdW50IG9mIHNpbXVsdGFuZW91c2x5IGFwcHJvdmVkIHNjcmlwdHMgbm90IGRlZmluZWQBCF9pc0FkbWluAQNwYmsECWFkbWluc1N0cgkBC3ZhbHVlT3JFbHNlAgkAoggBBQhrX0FETUlOUwIABAZhZG1pbnMJALUJAgUJYWRtaW5zU3RyAgEsCQECIT0CCQDPCAIFBmFkbWlucwUDcGJrBQR1bml0AQpfaXNNYW5hZ2VyAQNwYmsEC21hbmFnZXJzU3RyCQELdmFsdWVPckVsc2UCCQCiCAEFCmtfTUFOQUdFUlMCAAQIbWFuYWdlcnMJALUJAgULbWFuYWdlcnNTdHICASwJAQIhPQIJAM8IAgUIbWFuYWdlcnMFA3BiawUEdW5pdAEQX2lzVmFsaWRPcGVyYXRvcgEDcGJrBAttYW5hZ2Vyc1N0cgkBC3ZhbHVlT3JFbHNlAgkAoggBBQprX01BTkFHRVJTAgAECG1hbmFnZXJzCQC1CQIFC21hbmFnZXJzU3RyAgEsBAdpc0FkbWluCQEIX2lzQWRtaW4BBQNwYmsECWlzTWFuYWdlcgkBCl9pc01hbmFnZXIBBQNwYmsDBQdpc0FkbWluBgUJaXNNYW5hZ2VyAQpzYXZlVHhEYXRhAgZ0YXNrSWQEZGF0YQQHaW5kaWNlcwkAzAgCAAEJAMwIAgACCQDMCAIAAwkAzAgCAAQJAMwIAgAFCQDMCAIABgkAzAgCAAcJAMwIAgAICQDMCAIACQkAzAgCAAoFA25pbAQIZGF0YVNpemUJALECAQUEZGF0YQQKaXNOb3RFbXB0eQMJAQIhPQIFCGRhdGFTaXplAAAGCQACAQIdc2F2ZVR4RGF0YTogRW1wdHkgZGF0YSBwYXNzZWQDCQAAAgUKaXNOb3RFbXB0eQUKaXNOb3RFbXB0eQQJY2h1bmtTaXplALDqAQQLY2h1bmtzQ291bnQDCQAAAgkAagIFCGRhdGFTaXplBQljaHVua1NpemUAAAkAaQIFCGRhdGFTaXplBQljaHVua1NpemUJAGQCCQBpAgUIZGF0YVNpemUFCWNodW5rU2l6ZQABCgEKbWFrZUNodW5rcwIFYWNjdW0FaW5kZXgEBWNodW5rCQCvAgIIBQVhY2N1bQJfMQUJY2h1bmtTaXplAwkAAAIJALECAQUFY2h1bmsAAAUFYWNjdW0ECG5leHREYXRhCQCwAgIIBQVhY2N1bQJfMQUJY2h1bmtTaXplCQCUCgIFCG5leHREYXRhCQDNCAIIBQVhY2N1bQJfMgkBC1N0cmluZ0VudHJ5AgkArAICCQCsAgIFBnRhc2tJZAIJX190eGRhdGFfCQCkAwEFBWluZGV4BQVjaHVuawQHZW50cmllcwoAAiRsBQdpbmRpY2VzCgACJHMJAJADAQUCJGwKAAUkYWNjMAkAlAoCBQRkYXRhCQDMCAIJAQtTdHJpbmdFbnRyeQIJAKwCAgUGdGFza0lkAg9fX3R4ZGF0YV9jaHVua3MJAKQDAQULY2h1bmtzQ291bnQFA25pbAoBBSRmMF8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQEKbWFrZUNodW5rcwIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmMF8yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQIUTGlzdCBzaXplIGV4Y2VlZHMgMTAJAQUkZjBfMgIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYABwAIAAkACggFB2VudHJpZXMCXzIJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4QAWkBBGluaXQDC2FkbWluc19wYmtzBWxpbWl0DWFwcHJvdmVkQ291bnQDCQECIT0CCAUBaQZjYWxsZXIFBHRoaXMJAAIBAg5TZWxmIGNhbGwgb25seQQLc2l6ZV9hZG1pbnMDCQECIT0CCQCQAwEFC2FkbWluc19wYmtzAAAGCQACAQInQXQgbGVhc3Qgb25lIGFkbWluIHBiayBzaG91bGQgYmUgcGFzc2VkAwkAAAIFC3NpemVfYWRtaW5zBQtzaXplX2FkbWlucwQMY2hlY2tfYWRtaW5zAwkBASEBCQEJaXNEZWZpbmVkAQkAoggBBQhrX0FETUlOUwYJAAIBAg5BbHJlYWR5IGluaXRlZAMJAAACBQxjaGVja19hZG1pbnMFDGNoZWNrX2FkbWlucwQJemVyb0xpbWl0AwkAZgIFBWxpbWl0AAAGCQACAQITTGltaXQgc2hvdWxkIGJlID4gMAMJAAACBQl6ZXJvTGltaXQFCXplcm9MaW1pdAQIbGltaXRfb2sDCQBmAgkAkAMBBQthZG1pbnNfcGJrcwUFbGltaXQGCQACAQkArAICCQCsAgIJAKwCAgI5TGltaXQgcXVvcnVtIHNob3VsZCBiZSA8PSBzaXplIG9mIGxpc3Qgb2YgYWRtaW5zLCBsaW1pdDogCQCkAwEFBWxpbWl0AhAsIGN1cnJlbnQgc2l6ZTogCQCkAwEJAJADAQULYWRtaW5zX3Bia3MDCQAAAgUIbGltaXRfb2sFCGxpbWl0X29rCgEIdmFsaWRhdGUCBWFjY3VtBG5leHQJAQxfdmFsaWRhdGVQYmsBBQRuZXh0BAh2YWxpZFJlcwoAAiRsBQthZG1pbnNfcGJrcwoAAiRzCQCQAwEFAiRsCgAFJGFjYzACAAoBBSRmMF8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQEIdmFsaWRhdGUCBQIkYQkAkQMCBQIkbAUCJGkKAQUkZjBfMgICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkAAgECFExpc3Qgc2l6ZSBleGNlZWRzIDEwCQEFJGYwXzICCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECBQUkYWNjMAAAAAEAAgADAAQABQAGAAcACAAJAAoDCQAAAgUIdmFsaWRSZXMFCHZhbGlkUmVzBAlhZG1pbnNTdHIJALkJAgULYWRtaW5zX3Bia3MCASwJAMwIAgkBC1N0cmluZ0VudHJ5AgUIa19BRE1JTlMFCWFkbWluc1N0cgkAzAgCCQEMSW50ZWdlckVudHJ5AgUHa19MSU1JVAUFbGltaXQJAMwIAgkBDEludGVnZXJFbnRyeQIFEGtfQVBQUk9WRURfQ09VTlQFDWFwcHJvdmVkQ291bnQFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpAQhhZGRBZG1pbgEDcGJrBAljYWxsZXJQYmsJANgEAQgFAWkPY2FsbGVyUHVibGljS2V5BAZpc1NlbGYDCQAAAgkApwgBCAUBaQ9jYWxsZXJQdWJsaWNLZXkFBHRoaXMGCQACAQIQT25seSBzZWxmIGludm9rZQMJAAACBQZpc1NlbGYFBmlzU2VsZgQHaXNWYWxpZAMJAQxfdmFsaWRhdGVQYmsBBQNwYmsGCQACAQIRSW52YWxpZCBhZG1pbiBwYmsDCQAAAgUHaXNWYWxpZAUHaXNWYWxpZAQMbmV3QWRtaW5zU3RyCQCsAgIJAKwCAgkBEUBleHRyTmF0aXZlKDEwNTgpAQUIa19BRE1JTlMCASwFA3BiawkAzAgCCQELU3RyaW5nRW50cnkCBQhrX0FETUlOUwUMbmV3QWRtaW5zU3RyBQNuaWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQELcmVtb3ZlQWRtaW4BA3BiawQJY2FsbGVyUGJrCQDYBAEIBQFpD2NhbGxlclB1YmxpY0tleQQGaXNTZWxmAwkAAAIJAKcIAQgFAWkPY2FsbGVyUHVibGljS2V5BQR0aGlzBgkAAgECEE9ubHkgc2VsZiBpbnZva2UDCQAAAgUGaXNTZWxmBQZpc1NlbGYEB2lzVmFsaWQDCQEMX3ZhbGlkYXRlUGJrAQUDcGJrBgkAAgECEUludmFsaWQgYWRtaW4gcGJrAwkAAAIFB2lzVmFsaWQFB2lzVmFsaWQEDG9sZEFkbWluc1N0cgkBEUBleHRyTmF0aXZlKDEwNTgpAQUIa19BRE1JTlMECW9sZEFkbWlucwkAtQkCBQxvbGRBZG1pbnNTdHICASwECmNoZWNrQ291bnQDCQBnAgABCQCQAwEFCW9sZEFkbWlucwkAAgECL0Nhbm5vdCByZW1vdmUsIGF0IGxlYXN0IG9uZSBhZG1pbiBzaG91bGQgcmVtYWluBgMJAAACBQpjaGVja0NvdW50BQpjaGVja0NvdW50BAVpbmRleAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQDPCAIFCW9sZEFkbWlucwUDcGJrAhhUaGlzIHBiayBpcyBub3QgYW4gYWRtaW4ECW5ld0FkbWlucwkA0QgCBQlvbGRBZG1pbnMFBWluZGV4BAxuZXdBZG1pbnNTdHIJALkJAgUJbmV3QWRtaW5zAgEsCQDMCAIJAQtTdHJpbmdFbnRyeQIFCGtfQURNSU5TBQxuZXdBZG1pbnNTdHIFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpAQ1hZGRTY3JpcHRUeXBlAQpzY3JpcHRUeXBlBAljYWxsZXJQYmsJANgEAQgFAWkPY2FsbGVyUHVibGljS2V5BAZpc1NlbGYDCQAAAgkApwgBCAUBaQ9jYWxsZXJQdWJsaWNLZXkFBHRoaXMGCQACAQIQT25seSBzZWxmIGludm9rZQMJAAACBQZpc1NlbGYFBmlzU2VsZgQKY2hlY2tFbXB0eQMJAAACCQCxAgEFCnNjcmlwdFR5cGUAAAkAAgECHFNjcmlwdCB0eXBlIGNhbiBub3QgYmUgZW1wdHkGAwkAAAIFCmNoZWNrRW1wdHkFCmNoZWNrRW1wdHkEDnNjcmlwdFR5cGVzU3RyCQELdmFsdWVPckVsc2UCCQCiCAEFDmtfU0NSSVBUX1RZUEVTAgAEC3NjcmlwdFR5cGVzCQC8CQIFDnNjcmlwdFR5cGVzU3RyAgEsBAtjaGVja0V4aXN0cwMJAQIhPQIJAM8IAgULc2NyaXB0VHlwZXMFCnNjcmlwdFR5cGUFBHVuaXQJAAIBCQCsAgIJAKwCAgINU2NyaXB0IHR5cGUgPAUKc2NyaXB0VHlwZQIPPiBhbHJlYWR5IGFkZGVkBgMJAAACBQtjaGVja0V4aXN0cwULY2hlY2tFeGlzdHMEDm5ld1NjcmlwdFR5cGVzAwkBAiE9AgUOc2NyaXB0VHlwZXNTdHICAAkAzQgCBQtzY3JpcHRUeXBlcwUKc2NyaXB0VHlwZQkAzAgCBQpzY3JpcHRUeXBlBQNuaWwEEW5ld1NjcmlwdFR5cGVzU3RyCQC5CQIFDm5ld1NjcmlwdFR5cGVzAgEsCQDMCAIJAQtTdHJpbmdFbnRyeQIFDmtfU0NSSVBUX1RZUEVTBRFuZXdTY3JpcHRUeXBlc1N0cgUDbmlsCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBEHJlbW92ZVNjcmlwdFR5cGUBCnNjcmlwdFR5cGUECWNhbGxlclBiawkA2AQBCAUBaQ9jYWxsZXJQdWJsaWNLZXkEBmlzU2VsZgMJAAACCQCnCAEIBQFpD2NhbGxlclB1YmxpY0tleQUEdGhpcwYJAAIBAhBPbmx5IHNlbGYgaW52b2tlAwkAAAIFBmlzU2VsZgUGaXNTZWxmBA5zY3JpcHRUeXBlc1N0cgkBC3ZhbHVlT3JFbHNlAgkAoggBBQ5rX1NDUklQVF9UWVBFUwIABAtzY3JpcHRUeXBlcwkAvAkCBQ5zY3JpcHRUeXBlc1N0cgIBLAQFaW5kZXgJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAzwgCBQtzY3JpcHRUeXBlcwUKc2NyaXB0VHlwZQkArAICCQCsAgICDVNjcmlwdCB0eXBlIDwFCnNjcmlwdFR5cGUCED4gaXMgbm90IHByZXNlbnQEDm5ld1NjcmlwdFR5cGVzCQDRCAIFC3NjcmlwdFR5cGVzBQVpbmRleAQRbmV3U2NyaXB0VHlwZXNTdHIJALkJAgUObmV3U2NyaXB0VHlwZXMCASwJAMwIAgkBC1N0cmluZ0VudHJ5AgUOa19TQ1JJUFRfVFlQRVMFEW5ld1NjcmlwdFR5cGVzU3RyBQNuaWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQEIc2V0TGltaXQBBWxpbWl0BAljYWxsZXJQYmsJANgEAQgFAWkPY2FsbGVyUHVibGljS2V5BAZpc1NlbGYDCQAAAgkApwgBCAUBaQ9jYWxsZXJQdWJsaWNLZXkFBHRoaXMGCQACAQIQT25seSBzZWxmIGludm9rZQMJAAACBQZpc1NlbGYFBmlzU2VsZgQJemVyb0xpbWl0AwkAZgIFBWxpbWl0AAAGCQACAQITTGltaXQgc2hvdWxkIGJlID4gMAMJAAACBQl6ZXJvTGltaXQFCXplcm9MaW1pdAQGYWRtaW5zCQERQGV4dHJOYXRpdmUoMTA1OCkBBQhrX0FETUlOUwMJAGYCBQVsaW1pdAkAsQIBBQZhZG1pbnMJAAIBCQCsAgIJAKwCAgkArAICAjlMaW1pdCBxdW9ydW0gc2hvdWxkIGJlIDw9IHNpemUgb2YgbGlzdCBvZiBhZG1pbnMsIGxpbWl0OiAJAKQDAQUFbGltaXQCECwgY3VycmVudCBzaXplOiAJAKQDAQkAsQIBBQZhZG1pbnMJAMwIAgkBDEludGVnZXJFbnRyeQIFB2tfTElNSVQFBWxpbWl0BQNuaWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQEJYWRkU2NyaXB0BgpzY3JpcHRUeXBlDnN0b3JhZ2VBZGRyZXNzC19zY3JpcHRIYXNoBGRlc2MMaW5pdGlhdG9yQWRyC3Jhd0NvZGVIYXNoBAljYWxsZXJQYmsJANgEAQgFAWkPY2FsbGVyUHVibGljS2V5AwkBASEBCQEQX2lzVmFsaWRPcGVyYXRvcgEFCWNhbGxlclBiawkAAgECC05vdCBhbGxvd2VkBBFzdG9yYWdlU2NyaXB0SGFzaAkA2AQBCQEFdmFsdWUBCQDxBwEJARFAZXh0ck5hdGl2ZSgxMDYyKQEFDnN0b3JhZ2VBZGRyZXNzBA5zY3JpcHRUeXBlc1N0cgkBEUBleHRyTmF0aXZlKDEwNTgpAQUOa19TQ1JJUFRfVFlQRVMEEV9jaGVja1NjcmlwdFR5cGVzAwkAAAIJALMJAgUOc2NyaXB0VHlwZXNTdHIFCnNjcmlwdFR5cGUFBHVuaXQJAAIBCQCsAgICNWludmFsaWQgc2NyaXB0IHR5cGUgb3IgaXQgaXMgbm90IHByZXNlbnQgaW4gc3RvcmFnZTogBQpzY3JpcHRUeXBlBgMJAAACBRFfY2hlY2tTY3JpcHRUeXBlcwURX2NoZWNrU2NyaXB0VHlwZXMEEF9zY3JpcHRUeXBlQ2hlY2sDCQECIT0CBRFzdG9yYWdlU2NyaXB0SGFzaAULX3NjcmlwdEhhc2gJAAIBAjRTdG9yZWQgYW5kIHBhc3NlZCBhcyBhcmd1bWVudCBzY3JpcHRIYXNoZXMgbm90IG1hdGNoBgMJAAACBRBfc2NyaXB0VHlwZUNoZWNrBRBfc2NyaXB0VHlwZUNoZWNrBApfZGVzY0NoZWNrAwkAAAIJALECAQUEZGVzYwAACQACAQIaRGVzY3JpcHRpb24gY2FuJ3QgYmUgZW1wdHkGAwkAAAIFCl9kZXNjQ2hlY2sFCl9kZXNjQ2hlY2sED19pbml0aWF0b3JDaGVjawMJAQIhPQIJAKUIAQkApwgBCAUBaQ9jYWxsZXJQdWJsaWNLZXkFDGluaXRpYXRvckFkcgkAAgECJkluaXRpYXRvciBhZGRyZXNzIGRvZXNuJ3QgbWF0Y2ggY2FsbGVyBgMJAAACBQ9faW5pdGlhdG9yQ2hlY2sFD19pbml0aWF0b3JDaGVjawQJaXRlcmF0aW9uCQBkAgkBC3ZhbHVlT3JFbHNlAgkAnwgBCQCsAgIJAKwCAgULa19JVEVSQVRJT04FA1NFUAUKc2NyaXB0VHlwZQAAAAEECHNjcmlwdElkCQCsAgIJAKwCAgkArAICAghzY3JpcHQlJQUKc2NyaXB0VHlwZQICJSUFC19zY3JpcHRIYXNoCQDMCAIJAQtTdHJpbmdFbnRyeQIJAKwCAgkArAICBQhzY3JpcHRJZAUGQklHU0VQBQxrX3NjcmlwdFR5cGUFCnNjcmlwdFR5cGUJAMwIAgkBC1N0cmluZ0VudHJ5AgkArAICCQCsAgIFCHNjcmlwdElkBQZCSUdTRVAFEGtfc3RvcmFnZUFkZHJlc3MFDnN0b3JhZ2VBZGRyZXNzCQDMCAIJAQtTdHJpbmdFbnRyeQIJAKwCAgkArAICBQhzY3JpcHRJZAUGQklHU0VQBQxrX3NjcmlwdEhhc2gFEXN0b3JhZ2VTY3JpcHRIYXNoCQDMCAIJAQtTdHJpbmdFbnRyeQIJAKwCAgkArAICBQhzY3JpcHRJZAUGQklHU0VQBQZrX2Rlc2MFBGRlc2MJAMwIAgkBDEludGVnZXJFbnRyeQIJAKwCAgkArAICBQhzY3JpcHRJZAUGQklHU0VQBQZrX2l0ZXIFCWl0ZXJhdGlvbgkAzAgCCQELU3RyaW5nRW50cnkCCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgUKc2NyaXB0VHlwZQUGQklHU0VQBQZrX2l0ZXIFBkJJR1NFUAkApAMBBQlpdGVyYXRpb24CBl9faGFzaAULX3NjcmlwdEhhc2gJAMwIAgkBC1N0cmluZ0VudHJ5AgkArAICCQCsAgIFCHNjcmlwdElkBQZCSUdTRVAFC2tfaW5pdGlhdG9yBQxpbml0aWF0b3JBZHIJAMwIAgkBC1N0cmluZ0VudHJ5AgkArAICCQCsAgIFCHNjcmlwdElkBQZCSUdTRVAFDWtfcmF3Q29kZUhhc2gFC3Jhd0NvZGVIYXNoCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQCsAgIJAKwCAgULa19JVEVSQVRJT04FA1NFUAUKc2NyaXB0VHlwZQUJaXRlcmF0aW9uBQNuaWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQEMcmVtb3ZlU2NyaXB0AQhzY3JpcHRJZAQJY2FsbGVyUGJrCQDYBAEIBQFpD2NhbGxlclB1YmxpY0tleQMJAQEhAQkBEF9pc1ZhbGlkT3BlcmF0b3IBBQljYWxsZXJQYmsJAAIBAgtOb3QgYWxsb3dlZAQMaW5pdGlhdG9yQWRyCQERQGV4dHJOYXRpdmUoMTA1OCkBCQCsAgIFCHNjcmlwdElkAgtfX2luaXRpYXRvcgMJAQIhPQIFDGluaXRpYXRvckFkcgkApQgBCQCnCAEIBQFpD2NhbGxlclB1YmxpY0tleQkAAgECF09ubHkgY3JlYXRvciBjYW4gcmVtb3ZlBApzY3JpcHRUeXBlCQERQGV4dHJOYXRpdmUoMTA1OCkBCQCsAgIJAKwCAgUIc2NyaXB0SWQFBkJJR1NFUAUMa19zY3JpcHRUeXBlBAtfc2NyaXB0SGFzaAkBEUBleHRyTmF0aXZlKDEwNTgpAQkArAICCQCsAgIFCHNjcmlwdElkBQZCSUdTRVAFDGtfc2NyaXB0SGFzaAQEaXRlcgkBEUBleHRyTmF0aXZlKDEwNTUpAQkArAICCQCsAgIFCHNjcmlwdElkBQZCSUdTRVAFBmtfaXRlcgQOYXBwcm92ZWRIYXNoZXMJAQt2YWx1ZU9yRWxzZQIJAKIIAQkArAICCQCsAgICB3NjcmlwdF8FCnNjcmlwdFR5cGUCCl9fYXBwcm92ZWQCAAQOX2NoZWNrQXBwcm92ZWQDCQECIT0CCQCzCQIFDmFwcHJvdmVkSGFzaGVzBQtfc2NyaXB0SGFzaAUEdW5pdAkAAgECJ0NhbnQgcmVtb3ZlIGFwcHJvdmVkIHNjcmlwdCwgdXNlIHJldm9rZQYDCQAAAgUOX2NoZWNrQXBwcm92ZWQFDl9jaGVja0FwcHJvdmVkCQDMCAIJAQtEZWxldGVFbnRyeQEJAKwCAgkArAICBQhzY3JpcHRJZAUGQklHU0VQBQxrX3NjcmlwdFR5cGUJAMwIAgkBC0RlbGV0ZUVudHJ5AQkArAICCQCsAgIFCHNjcmlwdElkBQZCSUdTRVAFEGtfc3RvcmFnZUFkZHJlc3MJAMwIAgkBC0RlbGV0ZUVudHJ5AQkArAICCQCsAgIFCHNjcmlwdElkBQZCSUdTRVAFDGtfc2NyaXB0SGFzaAkAzAgCCQELRGVsZXRlRW50cnkBCQCsAgIJAKwCAgUIc2NyaXB0SWQFBkJJR1NFUAUGa19kZXNjCQDMCAIJAQtEZWxldGVFbnRyeQEJAKwCAgkArAICBQhzY3JpcHRJZAUGQklHU0VQBQZrX2l0ZXIJAMwIAgkBC0RlbGV0ZUVudHJ5AQkArAICCQCsAgIJAKwCAgUKc2NyaXB0VHlwZQINX19pdGVyYXRpb25fXwkApAMBBQRpdGVyAgZfX2hhc2gJAMwIAgkBC0RlbGV0ZUVudHJ5AQkArAICCQCsAgIFCHNjcmlwdElkBQZCSUdTRVAFC2tfaW5pdGlhdG9yCQDMCAIJAQtEZWxldGVFbnRyeQEJAKwCAgkArAICBQhzY3JpcHRJZAUGQklHU0VQBQ1rX3Jhd0NvZGVIYXNoCQDMCAIJAQtEZWxldGVFbnRyeQEJAKwCAgkArAICBQhzY3JpcHRJZAUGQklHU0VQBQ9rX2NvbmZpcm1hdGlvbnMFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpARVhZGRDb25maXJtYXRpb25TY3JpcHQBCHNjcmlwdElkBAljYWxsZXJQYmsJANgEAQgFAWkPY2FsbGVyUHVibGljS2V5BAVsaW1pdAkBCV9nZXRMaW1pdAADCQEBIQEJAQhfaXNBZG1pbgEFCWNhbGxlclBiawkAAgECF09ubHkgYWRtaW5zIGNhbiBjb25maXJtBAtfc2NyaXB0SGFzaAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCiCAEJAKwCAgUIc2NyaXB0SWQCDF9fc2NyaXB0SGFzaAIPSXZhbGlkIHNjcmlwdElkAwkAAAIFC19zY3JpcHRIYXNoBQtfc2NyaXB0SGFzaAQKc2NyaXB0VHlwZQkBEUBleHRyTmF0aXZlKDEwNTgpAQkArAICBQhzY3JpcHRJZAIMX19zY3JpcHRUeXBlBBFhcHByb3ZlZEhhc2hlc1N0cgkBC3ZhbHVlT3JFbHNlAgkAoggBCQCsAgIJAKwCAgIHc2NyaXB0XwUKc2NyaXB0VHlwZQIKX19hcHByb3ZlZAIABA5fY2hlY2tBcHByb3ZlZAMJAQIhPQIJALMJAgURYXBwcm92ZWRIYXNoZXNTdHIFC19zY3JpcHRIYXNoBQR1bml0CQACAQIfVGhpcyBzY3JpcHQgaXMgYXBwcm92ZWQgYWxyZWFkeQYDCQAAAgUOX2NoZWNrQXBwcm92ZWQFDl9jaGVja0FwcHJvdmVkBA9nbG9iYWxJdGVyYXRpb24JAQt2YWx1ZU9yRWxzZQIJAJ8IAQkArAICCQCsAgIFC2tfSVRFUkFUSU9OBQNTRVAFCnNjcmlwdFR5cGUAAAQNdGhpc0l0ZXJhdGlvbgkBBXZhbHVlAQkAnwgBCQCsAgIFCHNjcmlwdElkAgtfX2l0ZXJhdGlvbgQQY29uZmlybWF0aW9uc1N0cgkBC3ZhbHVlT3JFbHNlAgkAoggBCQCsAgIFCHNjcmlwdElkAg9fX2NvbmZpcm1hdGlvbnMCAAQNY29uZmlybWF0aW9ucwkAtQkCBRBjb25maXJtYXRpb25zU3RyAgEsAwkBAiE9AgkAzwgCBQ1jb25maXJtYXRpb25zBQljYWxsZXJQYmsFBHVuaXQJAAIBAiFZb3UgYWxyZWFkeSBjb25maXJtZWQgdGhpcyBzY3JpcHQEB25ld0xpc3QDCQECIT0CBRBjb25maXJtYXRpb25zU3RyAgAJAM0IAgUNY29uZmlybWF0aW9ucwUJY2FsbGVyUGJrCQDMCAIFCWNhbGxlclBiawUDbmlsBApuZXdMaXN0U3RyCQC5CQIFB25ld0xpc3QCASwECGFwcHJvdmVkCQBnAgkAkAMBBQduZXdMaXN0BQVsaW1pdAQGcmVzdWx0AwUIYXBwcm92ZWQEDWFwcHJvdmVkQ291bnQJARFfZ2V0QXBwcm92ZWRDb3VudAAEDmFwcHJvdmVkSGFzaGVzCQC8CQIFEWFwcHJvdmVkSGFzaGVzU3RyAgEsBBFhcHByb3ZlZEhhc2hlc05ldwMJAQIhPQIFEWFwcHJvdmVkSGFzaGVzU3RyAgAJAM0IAgUOYXBwcm92ZWRIYXNoZXMFC19zY3JpcHRIYXNoCQDMCAIFC19zY3JpcHRIYXNoBQNuaWwDCQBmAgkAkAMBBRFhcHByb3ZlZEhhc2hlc05ldwUNYXBwcm92ZWRDb3VudAQMaGFzaFRvUmVtb3ZlCQCRAwIFEWFwcHJvdmVkSGFzaGVzTmV3AAAEEHNjcmlwdFRvUmVtb3ZlSWQJAKwCAgkArAICCQCsAgICCHNjcmlwdCUlBQpzY3JpcHRUeXBlAgIlJQULX3NjcmlwdEhhc2gEFmFwcHJvdmVkSGFzaGVzU3RyaXBwZWQJANEIAgURYXBwcm92ZWRIYXNoZXNOZXcAAAkAzAgCCQELU3RyaW5nRW50cnkCCQCsAgIJAKwCAgIHc2NyaXB0XwUKc2NyaXB0VHlwZQIKX19hcHByb3ZlZAkAugkCBRZhcHByb3ZlZEhhc2hlc1N0cmlwcGVkAgEsCQDMCAIJAQtTdHJpbmdFbnRyeQIJAKwCAgkArAICBRBzY3JpcHRUb1JlbW92ZUlkBQZCSUdTRVAFD2tfY29uZmlybWF0aW9ucwIABQNuaWwJAMwIAgkBC1N0cmluZ0VudHJ5AgkArAICCQCsAgICB3NjcmlwdF8FCnNjcmlwdFR5cGUCCl9fYXBwcm92ZWQJALoJAgURYXBwcm92ZWRIYXNoZXNOZXcCASwFA25pbAUDbmlsCQDOCAIFBnJlc3VsdAkAzAgCCQELU3RyaW5nRW50cnkCCQCsAgIFCHNjcmlwdElkAg9fX2NvbmZpcm1hdGlvbnMFCm5ld0xpc3RTdHIFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpARhyZXZva2VDb25maXJtYXRpb25TY3JpcHQBCHNjcmlwdElkBAljYWxsZXJQYmsJANgEAQgFAWkPY2FsbGVyUHVibGljS2V5BAVsaW1pdAkBCV9nZXRMaW1pdAADCQEBIQEJAQhfaXNBZG1pbgEFCWNhbGxlclBiawkAAgECFk9ubHkgYWRtaW5zIGNhbiByZXZva2UEC19zY3JpcHRIYXNoCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKIIAQkArAICBQhzY3JpcHRJZAIMX19zY3JpcHRIYXNoAhBJbnZhbGlkIHNjcmlwdElkAwkAAAIFC19zY3JpcHRIYXNoBQtfc2NyaXB0SGFzaAQKc2NyaXB0VHlwZQkBEUBleHRyTmF0aXZlKDEwNTgpAQkArAICBQhzY3JpcHRJZAIMX19zY3JpcHRUeXBlBBFhcHByb3ZlZEhhc2hlc1N0cgkBC3ZhbHVlT3JFbHNlAgkAoggBCQCsAgIJAKwCAgIHc2NyaXB0XwUKc2NyaXB0VHlwZQIKX19hcHByb3ZlZAIABA5hcHByb3ZlZEhhc2hlcwkAvAkCBRFhcHByb3ZlZEhhc2hlc1N0cgIBLAQQY29uZmlybWF0aW9uc1N0cgkBC3ZhbHVlT3JFbHNlAgkAoggBCQCsAgIFCHNjcmlwdElkAg9fX2NvbmZpcm1hdGlvbnMCAAQNY29uZmlybWF0aW9ucwkAtQkCBRBjb25maXJtYXRpb25zU3RyAgEsBAxjb25maXJtSW5kZXgJAM8IAgUNY29uZmlybWF0aW9ucwUJY2FsbGVyUGJrAwkAAAIFDGNvbmZpcm1JbmRleAUEdW5pdAkAAgECMVlvdSBkaWRuJ3QgY29uZmlybSB0aGlzIHNjcmlwdCwgbm90aGluZyB0byByZXZva2UEEG5ld0NvbmZpcm1hdGlvbnMJANEIAgUNY29uZmlybWF0aW9ucwkBBXZhbHVlAQUMY29uZmlybUluZGV4BBNuZXdDb25maXJtYXRpb25zU3RyCQC5CQIFEG5ld0NvbmZpcm1hdGlvbnMCASwEC3dhc0FwcHJvdmVkCQECIT0CCQDPCAIFDmFwcHJvdmVkSGFzaGVzBQtfc2NyaXB0SGFzaAUEdW5pdAQNc3RpbGxBcHByb3ZlZAkAZwIJAJADAQUQbmV3Q29uZmlybWF0aW9ucwUFbGltaXQEDHN0YXRlQ2hhbmdlcwMDBQt3YXNBcHByb3ZlZAkBASEBBQ1zdGlsbEFwcHJvdmVkBwQPc2NyaXB0SGFzaEluZGV4CQEFdmFsdWUBCQDPCAIFDmFwcHJvdmVkSGFzaGVzBQtfc2NyaXB0SGFzaAQRbmV3QXBwcm92ZWRIYXNoZXMJANEIAgUOYXBwcm92ZWRIYXNoZXMFD3NjcmlwdEhhc2hJbmRleAQUbmV3QXBwcm92ZWRIYXNoZXNTdHIJALkJAgURbmV3QXBwcm92ZWRIYXNoZXMCASwJAMwIAgkBC1N0cmluZ0VudHJ5AgkArAICCQCsAgICB3NjcmlwdF8FCnNjcmlwdFR5cGUCCl9fYXBwcm92ZWQFFG5ld0FwcHJvdmVkSGFzaGVzU3RyBQNuaWwFA25pbAkAzggCBQxzdGF0ZUNoYW5nZXMJAMwIAgkBC1N0cmluZ0VudHJ5AgkArAICBQhzY3JpcHRJZAIPX19jb25maXJtYXRpb25zBRNuZXdDb25maXJtYXRpb25zU3RyBQNuaWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQEHYWRkVGFzawcEbmFtZQRkYXBwBHR4aWQJZXhlY3V0ZVRzBGRlc2MMaW5pdGlhdG9yQWRyBnR4ZGF0YQQJY2FsbGVyUGJrCQDYBAEIBQFpD2NhbGxlclB1YmxpY0tleQMJAQEhAQkBEF9pc1ZhbGlkT3BlcmF0b3IBBQljYWxsZXJQYmsJAAIBAgtOb3QgYWxsb3dlZAQKX25hbWVDaGVjawMJAAACCQCxAgEFBG5hbWUAAAkAAgECE05hbWUgY2FuJ3QgYmUgZW1wdHkGAwkAAAIFCl9uYW1lQ2hlY2sFCl9uYW1lQ2hlY2sECl9kYXBwQ2hlY2sDCQEBIQEJARBfdmFsaWRhdGVBZGRyZXNzAQUEZGFwcAkAAgECDkluY29ycmVjdCBkYXBwBgMJAAACBQpfZGFwcENoZWNrBQpfZGFwcENoZWNrBApfdHhpZENoZWNrAwkAAAIJALECAQUEdHhpZAAACQACAQITdHhpZCBjYW4ndCBiZSBlbXB0eQYDCQAAAgUKX3R4aWRDaGVjawUKX3R4aWRDaGVjawQPX3RpbWVzdGFtcENoZWNrAwkBASEBCQELX3ZhbGlkYXRlVHMBBQlleGVjdXRlVHMJAAIBAkRJbnZhbGlkIGV4ZWN1dGlvbiB0aW1lc3RhbXAgLSBjYW5ub3QgYmUgbW9yZSB0aGFuIDEgaG91ciBpbiB0aGUgcGFzdAYDCQAAAgUPX3RpbWVzdGFtcENoZWNrBQ9fdGltZXN0YW1wQ2hlY2sECl9kZXNjQ2hlY2sDCQAAAgkAsQIBBQRkZXNjAAAJAAIBAhpEZXNjcmlwdGlvbiBjYW4ndCBiZSBlbXB0eQYDCQAAAgUKX2Rlc2NDaGVjawUKX2Rlc2NDaGVjawQPX2luaXRpYXRvckNoZWNrAwkBAiE9AgkApQgBCQCnCAEIBQFpD2NhbGxlclB1YmxpY0tleQUMaW5pdGlhdG9yQWRyCQACAQImSW5pdGlhdG9yIGFkZHJlc3MgZG9lc24ndCBtYXRjaCBjYWxsZXIGAwkAAAIFD19pbml0aWF0b3JDaGVjawUPX2luaXRpYXRvckNoZWNrBAxfdHhkYXRhQ2hlY2sDCQAAAgkAsQIBBQZ0eGRhdGEAAAkAAgECFlR4IGRhdGEgY2FuJ3QgYmUgZW1wdHkGAwkAAAIFDF90eGRhdGFDaGVjawUMX3R4ZGF0YUNoZWNrBAZ0YXNrSWQJAKwCAgkArAICCQCsAgICA3R4XwUEZGFwcAUDU0VQBQR0eGlkCQDMCAIJAQtTdHJpbmdFbnRyeQIJAKwCAgUGdGFza0lkAgZfX25hbWUFBG5hbWUJAMwIAgkBC1N0cmluZ0VudHJ5AgkArAICBQZ0YXNrSWQCBl9fZGFwcAUEZGFwcAkAzAgCCQELU3RyaW5nRW50cnkCCQCsAgIFBnRhc2tJZAIGX190eElkBQR0eGlkCQDMCAIJAQtTdHJpbmdFbnRyeQIJAKwCAgUGdGFza0lkAgZfX2Rlc2MFBGRlc2MJAMwIAgkBC1N0cmluZ0VudHJ5AgkArAICBQZ0YXNrSWQCCF9fdHhkYXRhBQZ0eGRhdGEJAMwIAgkBC1N0cmluZ0VudHJ5AgkArAICBQZ0YXNrSWQCC19faW5pdGlhdG9yBQxpbml0aWF0b3JBZHIJAMwIAgkBDEludGVnZXJFbnRyeQIJAKwCAgUGdGFza0lkAgRfX3RzBQlleGVjdXRlVHMFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpAQpyZW1vdmVUYXNrAQZ0YXNrSWQECWNhbGxlclBiawkA2AQBCAUBaQ9jYWxsZXJQdWJsaWNLZXkDCQEBIQEJARBfaXNWYWxpZE9wZXJhdG9yAQUJY2FsbGVyUGJrCQACAQILTm90IGFsbG93ZWQEDGluaXRpYXRvckFkcgkBEUBleHRyTmF0aXZlKDEwNTgpAQkArAICBQZ0YXNrSWQCC19faW5pdGlhdG9yAwkBAiE9AgUMaW5pdGlhdG9yQWRyCQClCAEJAKcIAQgFAWkPY2FsbGVyUHVibGljS2V5CQACAQIXT25seSBjcmVhdG9yIGNhbiByZW1vdmUEBHR4SWQJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAoggBCQCsAgIFBnRhc2tJZAIGX190eElkAgtJdmFsaWQgdGFzawMJAAACBQR0eElkBQR0eElkBARkYXBwCQERQGV4dHJOYXRpdmUoMTA1OCkBCQCsAgIFBnRhc2tJZAIGX19kYXBwCQDMCAIJAQtEZWxldGVFbnRyeQEJAKwCAgUGdGFza0lkAgZfX25hbWUJAMwIAgkBC0RlbGV0ZUVudHJ5AQkArAICBQZ0YXNrSWQCBl9fZGFwcAkAzAgCCQELRGVsZXRlRW50cnkBCQCsAgIFBnRhc2tJZAIGX190eElkCQDMCAIJAQtEZWxldGVFbnRyeQEJAKwCAgUGdGFza0lkAgZfX2Rlc2MJAMwIAgkBC0RlbGV0ZUVudHJ5AQkArAICBQZ0YXNrSWQCCF9fdHhkYXRhCQDMCAIJAQtEZWxldGVFbnRyeQEJAKwCAgUGdGFza0lkAgtfX2luaXRpYXRvcgkAzAgCCQELRGVsZXRlRW50cnkBCQCsAgIFBnRhc2tJZAIEX190cwkAzAgCCQELRGVsZXRlRW50cnkBCQCsAgIFBnRhc2tJZAIPX19jb25maXJtYXRpb25zCQDMCAIJAQtEZWxldGVFbnRyeQEJAKwCAgkArAICCQCsAgIFBGRhcHAFA1NFUAUEdHhJZAIKX19hcHByb3ZlZAUDbmlsCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBD2FkZENvbmZpcm1hdGlvbgEGdGFza0lkBAljYWxsZXJQYmsJANgEAQgFAWkPY2FsbGVyUHVibGljS2V5BAVsaW1pdAkBCV9nZXRMaW1pdAADCQEBIQEJAQhfaXNBZG1pbgEFCWNhbGxlclBiawkAAgECF09ubHkgYWRtaW5zIGNhbiBjb25maXJtBAR0eElkCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKIIAQkArAICBQZ0YXNrSWQCBl9fdHhJZAILSXZhbGlkIHRhc2sDCQAAAgUEdHhJZAUEdHhJZAQEZGFwcAkBEUBleHRyTmF0aXZlKDEwNTgpAQkArAICBQZ0YXNrSWQCBl9fZGFwcAQQY29uZmlybWF0aW9uc1N0cgkBC3ZhbHVlT3JFbHNlAgkAoggBCQCsAgIFBnRhc2tJZAIPX19jb25maXJtYXRpb25zAgAEDWNvbmZpcm1hdGlvbnMJALUJAgUQY29uZmlybWF0aW9uc1N0cgIBLAMJAQIhPQIJAM8IAgUNY29uZmlybWF0aW9ucwUJY2FsbGVyUGJrBQR1bml0CQACAQIfWW91IGFscmVhZHkgY29uZmlybWVkIHRoaXMgdGFzawQHbmV3TGlzdAMJAQIhPQIFEGNvbmZpcm1hdGlvbnNTdHICAAkAzQgCBQ1jb25maXJtYXRpb25zBQljYWxsZXJQYmsJAMwIAgUJY2FsbGVyUGJrBQNuaWwECm5ld0xpc3RTdHIJALkJAgUHbmV3TGlzdAIBLAQIYXBwcm92ZWQJAGcCCQCQAwEFB25ld0xpc3QFBWxpbWl0CQDMCAIJAQtTdHJpbmdFbnRyeQIJAKwCAgUGdGFza0lkAg9fX2NvbmZpcm1hdGlvbnMFCm5ld0xpc3RTdHIJAMwIAgkBDEJvb2xlYW5FbnRyeQIJAKwCAgkArAICCQCsAgIFBGRhcHAFA1NFUAUEdHhJZAIKX19hcHByb3ZlZAUIYXBwcm92ZWQFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpAQpyZXZva2VUYXNrAQZ0YXNrSWQECWNhbGxlclBiawkA2AQBCAUBaQ9jYWxsZXJQdWJsaWNLZXkEBWxpbWl0CQEJX2dldExpbWl0AAMJAQEhAQkBCF9pc0FkbWluAQUJY2FsbGVyUGJrCQACAQIUT25seSBhZG1pbnMgY2FuIGNhbGwEBHR4SWQJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAoggBCQCsAgIFBnRhc2tJZAIGX190eElkAgtJdmFsaWQgdGFzawMJAAACBQR0eElkBQR0eElkBBBjb25maXJtYXRpb25zU3RyCQELdmFsdWVPckVsc2UCCQCiCAEJAKwCAgUGdGFza0lkAg9fX2NvbmZpcm1hdGlvbnMCAAQNY29uZmlybWF0aW9ucwkAtQkCBRBjb25maXJtYXRpb25zU3RyAgEsBAdpbmRleE15CQDPCAIFDWNvbmZpcm1hdGlvbnMFCWNhbGxlclBiawMJAAACBQdpbmRleE15BQR1bml0CQACAQIwWW91IGRpZCBub3QgY29uZmlybSB0aGlzIHRhc2ssIG5vdGhpbmcgdG8gcmV2b2tlBARkYXBwCQERQGV4dHJOYXRpdmUoMTA1OCkBCQCsAgIFBnRhc2tJZAIGX19kYXBwBAduZXdMaXN0CQDRCAIFDWNvbmZpcm1hdGlvbnMJAQV2YWx1ZQEFB2luZGV4TXkECm5ld0xpc3RTdHIJALkJAgUHbmV3TGlzdAIBLAQIYXBwcm92ZWQJAGcCCQCQAwEFB25ld0xpc3QFBWxpbWl0CQDMCAIJAQtTdHJpbmdFbnRyeQIJAKwCAgUGdGFza0lkAg9fX2NvbmZpcm1hdGlvbnMFCm5ld0xpc3RTdHIJAMwIAgkBDEJvb2xlYW5FbnRyeQIJAKwCAgkArAICCQCsAgIFBGRhcHAFA1NFUAUEdHhJZAIKX19hcHByb3ZlZAUIYXBwcm92ZWQFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpAQR0ZXN0AAQBeAQHJG1hdGNoMAkA7QcBBQZoZWlnaHQDCQABAgUHJG1hdGNoMAIJQmxvY2tJbmZvBAVibG9jawUHJG1hdGNoMAkAAgEJAKQDAQgFBWJsb2NrCXRpbWVzdGFtcAkAAgECEENhbid0IGZpbmQgYmxvY2sDCQAAAgUBeAUBeAUDbmlsCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBCmNsZWFyX3Rlc3QABAdpbmRpY2VzCQDMCAIAAQkAzAgCAAIJAMwIAgADCQDMCAIABAkAzAgCAAUJAMwIAgAGCQDMCAIABwkAzAgCAAgJAMwIAgAJCQDMCAIACgUDbmlsCgEMcmVtb3ZlQ2h1bmtzAgVhY2N1bQVpbmRleAkAzQgCBQVhY2N1bQkBC0RlbGV0ZUVudHJ5AQkArAICCQCsAgICCHRlc3R0YXNrAglfX3R4ZGF0YV8JAKQDAQUFaW5kZXgEB2VudHJpZXMKAAIkbAUHaW5kaWNlcwoAAiRzCQCQAwEFAiRsCgAFJGFjYzAJAMwIAgkBC0RlbGV0ZUVudHJ5AQkArAICAgh0ZXN0dGFzawIPX190eGRhdGFfY2h1bmtzBQNuaWwKAQUkZjBfMQICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkBDHJlbW92ZUNodW5rcwIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmMF8yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQIUTGlzdCBzaXplIGV4Y2VlZHMgMTAJAQUkZjBfMgIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYABwAIAAkACgUHZW50cmllcwECdHgBBnZlcmlmeQAEEE1VTFRJU0lHX0FERFJFU1MJAKYIAQIjM003dXpEOHJUNTRmS1FjUDRzNDE3aWYxVktVOHlyb21FUDIEDUNPTlRSQUNUX1RZUEUCEUFQUFJPVkVSX0NPTlRSQUNUAwkBAiE9AgUQTVVMVElTSUdfQUREUkVTUwUEdW5pdAQHJG1hdGNoMAUCdHgDCQABAgUHJG1hdGNoMAIUU2V0U2NyaXB0VHJhbnNhY3Rpb24EA3R0eAUHJG1hdGNoMAQLc2NyaXB0SGFzaGEJANgEAQkBBXZhbHVlAQkA9gMBCQEFdmFsdWUBCAUDdHR4BnNjcmlwdAQOYXBwcm92ZWRIYXNoZXMJAQV2YWx1ZQEJAJ0IAgkBBXZhbHVlAQUQTVVMVElTSUdfQUREUkVTUwkArAICCQCsAgICB3NjcmlwdF8FDUNPTlRSQUNUX1RZUEUCCl9fYXBwcm92ZWQJAQIhPQIJALMJAgUOYXBwcm92ZWRIYXNoZXMFC3NjcmlwdEhhc2hhBQR1bml0BANvdHgFByRtYXRjaDAJAQt2YWx1ZU9yRWxzZQIJAJsIAgkBBXZhbHVlAQUEdGhpcwkArAICCQCsAgIJAKwCAgkApQgBBQR0aGlzAgFfCQDYBAEIBQNvdHgCaWQCCl9fYXBwcm92ZWQHCQD0AwMIBQJ0eAlib2R5Qnl0ZXMJAJEDAggFAnR4BnByb29mcwAACAUCdHgPc2VuZGVyUHVibGljS2V5ThK2wQ==", "height": 552316, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: none Next: none Full:
OldNewDifferences
1-# no script
1+{-# STDLIB_VERSION 6 #-}
2+{-# SCRIPT_TYPE ACCOUNT #-}
3+{-# CONTENT_TYPE DAPP #-}
4+let VERSION = "1.0.0"
5+
6+let SEP = "_"
7+
8+let BIGSEP = "__"
9+
10+let k_ADMINS = "ADMINS_PBKS"
11+
12+let k_MANAGERS = "MANAGERS_PBKS"
13+
14+let k_LIMIT = "VOTES_QUORUM"
15+
16+let k_SCRIPT_TYPES = "SCRIPT_TYPES"
17+
18+let k_ITERATION = "ITERATION"
19+
20+let k_APPROVED_COUNT = "APPROVED_COUNT"
21+
22+let k_scriptType = "scriptType"
23+
24+let k_scriptHash = "scriptHash"
25+
26+let k_storageAddress = "storageAddress"
27+
28+let k_desc = "desc"
29+
30+let k_iter = "iteration"
31+
32+let k_initiator = "initiator"
33+
34+let k_confirmations = "confirmations"
35+
36+let k_rawCodeHash = "rawCodeHash"
37+
38+func _validatePbk (pbk) = {
39+ let address = addressFromPublicKey(fromBase58String(pbk))
40+ if ((address == address))
41+ then {
42+ let addressStr = toString(address)
43+ if ((addressStr == addressStr))
44+ then true
45+ else throw("Strict value is not equal to itself.")
46+ }
47+ else throw("Strict value is not equal to itself.")
48+ }
49+
50+
51+func _validateAddress (address) = {
52+ let addr = addressFromStringValue(address)
53+ if ((addr == addr))
54+ then true
55+ else throw("Strict value is not equal to itself.")
56+ }
57+
58+
59+func _validateTs (ts) = {
60+ let currTs = match blockInfoByHeight(height) {
61+ case block: BlockInfo =>
62+ block.timestamp
63+ case _ =>
64+ throw("Can't find block")
65+ }
66+ let oneHour = ((60 * 60) * 1000)
67+ let minTs = (currTs - oneHour)
68+ (ts >= minTs)
69+ }
70+
71+
72+func isTxApproved (inv) = valueOrElse(getBoolean(value(this), (((toString(this) + "_") + toBase58String(inv.transactionId)) + "__approved")), false)
73+
74+
75+func _getLimit () = valueOrErrorMessage(getInteger(k_LIMIT), "Quorum limit not defined")
76+
77+
78+func _getApprovedCount () = valueOrErrorMessage(getInteger(k_APPROVED_COUNT), "Amount of simultaneously approved scripts not defined")
79+
80+
81+func _isAdmin (pbk) = {
82+ let adminsStr = valueOrElse(getString(k_ADMINS), "")
83+ let admins = split(adminsStr, ",")
84+ (indexOf(admins, pbk) != unit)
85+ }
86+
87+
88+func _isManager (pbk) = {
89+ let managersStr = valueOrElse(getString(k_MANAGERS), "")
90+ let managers = split(managersStr, ",")
91+ (indexOf(managers, pbk) != unit)
92+ }
93+
94+
95+func _isValidOperator (pbk) = {
96+ let managersStr = valueOrElse(getString(k_MANAGERS), "")
97+ let managers = split(managersStr, ",")
98+ let isAdmin = _isAdmin(pbk)
99+ let isManager = _isManager(pbk)
100+ if (isAdmin)
101+ then true
102+ else isManager
103+ }
104+
105+
106+func saveTxData (taskId,data) = {
107+ let indices = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
108+ let dataSize = size(data)
109+ let isNotEmpty = if ((dataSize != 0))
110+ then true
111+ else throw("saveTxData: Empty data passed")
112+ if ((isNotEmpty == isNotEmpty))
113+ then {
114+ let chunkSize = 30000
115+ let chunksCount = if (((dataSize % chunkSize) == 0))
116+ then (dataSize / chunkSize)
117+ else ((dataSize / chunkSize) + 1)
118+ func makeChunks (accum,index) = {
119+ let chunk = take(accum._1, chunkSize)
120+ if ((size(chunk) == 0))
121+ then accum
122+ else {
123+ let nextData = drop(accum._1, chunkSize)
124+ $Tuple2(nextData, (accum._2 :+ StringEntry(((taskId + "__txdata_") + toString(index)), chunk)))
125+ }
126+ }
127+
128+ let entries = {
129+ let $l = indices
130+ let $s = size($l)
131+ let $acc0 = $Tuple2(data, [StringEntry((taskId + "__txdata_chunks"), toString(chunksCount))])
132+ func $f0_1 ($a,$i) = if (($i >= $s))
133+ then $a
134+ else makeChunks($a, $l[$i])
135+
136+ func $f0_2 ($a,$i) = if (($i >= $s))
137+ then $a
138+ else throw("List size exceeds 10")
139+
140+ $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
141+ }
142+ entries._2
143+ }
144+ else throw("Strict value is not equal to itself.")
145+ }
146+
147+
148+@Callable(i)
149+func init (admins_pbks,limit,approvedCount) = if ((i.caller != this))
150+ then throw("Self call only")
151+ else {
152+ let size_admins = if ((size(admins_pbks) != 0))
153+ then true
154+ else throw("At least one admin pbk should be passed")
155+ if ((size_admins == size_admins))
156+ then {
157+ let check_admins = if (!(isDefined(getString(k_ADMINS))))
158+ then true
159+ else throw("Already inited")
160+ if ((check_admins == check_admins))
161+ then {
162+ let zeroLimit = if ((limit > 0))
163+ then true
164+ else throw("Limit should be > 0")
165+ if ((zeroLimit == zeroLimit))
166+ then {
167+ let limit_ok = if ((size(admins_pbks) > limit))
168+ then true
169+ else throw(((("Limit quorum should be <= size of list of admins, limit: " + toString(limit)) + ", current size: ") + toString(size(admins_pbks))))
170+ if ((limit_ok == limit_ok))
171+ then {
172+ func validate (accum,next) = _validatePbk(next)
173+
174+ let validRes = {
175+ let $l = admins_pbks
176+ let $s = size($l)
177+ let $acc0 = ""
178+ func $f0_1 ($a,$i) = if (($i >= $s))
179+ then $a
180+ else validate($a, $l[$i])
181+
182+ func $f0_2 ($a,$i) = if (($i >= $s))
183+ then $a
184+ else throw("List size exceeds 10")
185+
186+ $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
187+ }
188+ if ((validRes == validRes))
189+ then {
190+ let adminsStr = makeString(admins_pbks, ",")
191+[StringEntry(k_ADMINS, adminsStr), IntegerEntry(k_LIMIT, limit), IntegerEntry(k_APPROVED_COUNT, approvedCount)]
192+ }
193+ else throw("Strict value is not equal to itself.")
194+ }
195+ else throw("Strict value is not equal to itself.")
196+ }
197+ else throw("Strict value is not equal to itself.")
198+ }
199+ else throw("Strict value is not equal to itself.")
200+ }
201+ else throw("Strict value is not equal to itself.")
202+ }
203+
204+
205+
206+@Callable(i)
207+func addAdmin (pbk) = {
208+ let callerPbk = toBase58String(i.callerPublicKey)
209+ let isSelf = if ((addressFromPublicKey(i.callerPublicKey) == this))
210+ then true
211+ else throw("Only self invoke")
212+ if ((isSelf == isSelf))
213+ then {
214+ let isValid = if (_validatePbk(pbk))
215+ then true
216+ else throw("Invalid admin pbk")
217+ if ((isValid == isValid))
218+ then {
219+ let newAdminsStr = ((getStringValue(k_ADMINS) + ",") + pbk)
220+[StringEntry(k_ADMINS, newAdminsStr)]
221+ }
222+ else throw("Strict value is not equal to itself.")
223+ }
224+ else throw("Strict value is not equal to itself.")
225+ }
226+
227+
228+
229+@Callable(i)
230+func removeAdmin (pbk) = {
231+ let callerPbk = toBase58String(i.callerPublicKey)
232+ let isSelf = if ((addressFromPublicKey(i.callerPublicKey) == this))
233+ then true
234+ else throw("Only self invoke")
235+ if ((isSelf == isSelf))
236+ then {
237+ let isValid = if (_validatePbk(pbk))
238+ then true
239+ else throw("Invalid admin pbk")
240+ if ((isValid == isValid))
241+ then {
242+ let oldAdminsStr = getStringValue(k_ADMINS)
243+ let oldAdmins = split(oldAdminsStr, ",")
244+ let checkCount = if ((1 >= size(oldAdmins)))
245+ then throw("Cannot remove, at least one admin should remain")
246+ else true
247+ if ((checkCount == checkCount))
248+ then {
249+ let index = valueOrErrorMessage(indexOf(oldAdmins, pbk), "This pbk is not an admin")
250+ let newAdmins = removeByIndex(oldAdmins, index)
251+ let newAdminsStr = makeString(newAdmins, ",")
252+[StringEntry(k_ADMINS, newAdminsStr)]
253+ }
254+ else throw("Strict value is not equal to itself.")
255+ }
256+ else throw("Strict value is not equal to itself.")
257+ }
258+ else throw("Strict value is not equal to itself.")
259+ }
260+
261+
262+
263+@Callable(i)
264+func addScriptType (scriptType) = {
265+ let callerPbk = toBase58String(i.callerPublicKey)
266+ let isSelf = if ((addressFromPublicKey(i.callerPublicKey) == this))
267+ then true
268+ else throw("Only self invoke")
269+ if ((isSelf == isSelf))
270+ then {
271+ let checkEmpty = if ((size(scriptType) == 0))
272+ then throw("Script type can not be empty")
273+ else true
274+ if ((checkEmpty == checkEmpty))
275+ then {
276+ let scriptTypesStr = valueOrElse(getString(k_SCRIPT_TYPES), "")
277+ let scriptTypes = split_4C(scriptTypesStr, ",")
278+ let checkExists = if ((indexOf(scriptTypes, scriptType) != unit))
279+ then throw((("Script type <" + scriptType) + "> already added"))
280+ else true
281+ if ((checkExists == checkExists))
282+ then {
283+ let newScriptTypes = if ((scriptTypesStr != ""))
284+ then (scriptTypes :+ scriptType)
285+ else [scriptType]
286+ let newScriptTypesStr = makeString(newScriptTypes, ",")
287+[StringEntry(k_SCRIPT_TYPES, newScriptTypesStr)]
288+ }
289+ else throw("Strict value is not equal to itself.")
290+ }
291+ else throw("Strict value is not equal to itself.")
292+ }
293+ else throw("Strict value is not equal to itself.")
294+ }
295+
296+
297+
298+@Callable(i)
299+func removeScriptType (scriptType) = {
300+ let callerPbk = toBase58String(i.callerPublicKey)
301+ let isSelf = if ((addressFromPublicKey(i.callerPublicKey) == this))
302+ then true
303+ else throw("Only self invoke")
304+ if ((isSelf == isSelf))
305+ then {
306+ let scriptTypesStr = valueOrElse(getString(k_SCRIPT_TYPES), "")
307+ let scriptTypes = split_4C(scriptTypesStr, ",")
308+ let index = valueOrErrorMessage(indexOf(scriptTypes, scriptType), (("Script type <" + scriptType) + "> is not present"))
309+ let newScriptTypes = removeByIndex(scriptTypes, index)
310+ let newScriptTypesStr = makeString(newScriptTypes, ",")
311+[StringEntry(k_SCRIPT_TYPES, newScriptTypesStr)]
312+ }
313+ else throw("Strict value is not equal to itself.")
314+ }
315+
316+
317+
318+@Callable(i)
319+func setLimit (limit) = {
320+ let callerPbk = toBase58String(i.callerPublicKey)
321+ let isSelf = if ((addressFromPublicKey(i.callerPublicKey) == this))
322+ then true
323+ else throw("Only self invoke")
324+ if ((isSelf == isSelf))
325+ then {
326+ let zeroLimit = if ((limit > 0))
327+ then true
328+ else throw("Limit should be > 0")
329+ if ((zeroLimit == zeroLimit))
330+ then {
331+ let admins = getStringValue(k_ADMINS)
332+ if ((limit > size(admins)))
333+ then throw(((("Limit quorum should be <= size of list of admins, limit: " + toString(limit)) + ", current size: ") + toString(size(admins))))
334+ else [IntegerEntry(k_LIMIT, limit)]
335+ }
336+ else throw("Strict value is not equal to itself.")
337+ }
338+ else throw("Strict value is not equal to itself.")
339+ }
340+
341+
342+
343+@Callable(i)
344+func addScript (scriptType,storageAddress,_scriptHash,desc,initiatorAdr,rawCodeHash) = {
345+ let callerPbk = toBase58String(i.callerPublicKey)
346+ if (!(_isValidOperator(callerPbk)))
347+ then throw("Not allowed")
348+ else {
349+ let storageScriptHash = toBase58String(value(scriptHash(addressFromStringValue(storageAddress))))
350+ let scriptTypesStr = getStringValue(k_SCRIPT_TYPES)
351+ let _checkScriptTypes = if ((indexOf(scriptTypesStr, scriptType) == unit))
352+ then throw(("invalid script type or it is not present in storage: " + scriptType))
353+ else true
354+ if ((_checkScriptTypes == _checkScriptTypes))
355+ then {
356+ let _scriptTypeCheck = if ((storageScriptHash != _scriptHash))
357+ then throw("Stored and passed as argument scriptHashes not match")
358+ else true
359+ if ((_scriptTypeCheck == _scriptTypeCheck))
360+ then {
361+ let _descCheck = if ((size(desc) == 0))
362+ then throw("Description can't be empty")
363+ else true
364+ if ((_descCheck == _descCheck))
365+ then {
366+ let _initiatorCheck = if ((toString(addressFromPublicKey(i.callerPublicKey)) != initiatorAdr))
367+ then throw("Initiator address doesn't match caller")
368+ else true
369+ if ((_initiatorCheck == _initiatorCheck))
370+ then {
371+ let iteration = (valueOrElse(getInteger(((k_ITERATION + SEP) + scriptType)), 0) + 1)
372+ let scriptId = ((("script%%" + scriptType) + "%%") + _scriptHash)
373+[StringEntry(((scriptId + BIGSEP) + k_scriptType), scriptType), StringEntry(((scriptId + BIGSEP) + k_storageAddress), storageAddress), StringEntry(((scriptId + BIGSEP) + k_scriptHash), storageScriptHash), StringEntry(((scriptId + BIGSEP) + k_desc), desc), IntegerEntry(((scriptId + BIGSEP) + k_iter), iteration), StringEntry((((((scriptType + BIGSEP) + k_iter) + BIGSEP) + toString(iteration)) + "__hash"), _scriptHash), StringEntry(((scriptId + BIGSEP) + k_initiator), initiatorAdr), StringEntry(((scriptId + BIGSEP) + k_rawCodeHash), rawCodeHash), IntegerEntry(((k_ITERATION + SEP) + scriptType), iteration)]
374+ }
375+ else throw("Strict value is not equal to itself.")
376+ }
377+ else throw("Strict value is not equal to itself.")
378+ }
379+ else throw("Strict value is not equal to itself.")
380+ }
381+ else throw("Strict value is not equal to itself.")
382+ }
383+ }
384+
385+
386+
387+@Callable(i)
388+func removeScript (scriptId) = {
389+ let callerPbk = toBase58String(i.callerPublicKey)
390+ if (!(_isValidOperator(callerPbk)))
391+ then throw("Not allowed")
392+ else {
393+ let initiatorAdr = getStringValue((scriptId + "__initiator"))
394+ if ((initiatorAdr != toString(addressFromPublicKey(i.callerPublicKey))))
395+ then throw("Only creator can remove")
396+ else {
397+ let scriptType = getStringValue(((scriptId + BIGSEP) + k_scriptType))
398+ let _scriptHash = getStringValue(((scriptId + BIGSEP) + k_scriptHash))
399+ let iter = getIntegerValue(((scriptId + BIGSEP) + k_iter))
400+ let approvedHashes = valueOrElse(getString((("script_" + scriptType) + "__approved")), "")
401+ let _checkApproved = if ((indexOf(approvedHashes, _scriptHash) != unit))
402+ then throw("Cant remove approved script, use revoke")
403+ else true
404+ if ((_checkApproved == _checkApproved))
405+ then [DeleteEntry(((scriptId + BIGSEP) + k_scriptType)), DeleteEntry(((scriptId + BIGSEP) + k_storageAddress)), DeleteEntry(((scriptId + BIGSEP) + k_scriptHash)), DeleteEntry(((scriptId + BIGSEP) + k_desc)), DeleteEntry(((scriptId + BIGSEP) + k_iter)), DeleteEntry((((scriptType + "__iteration__") + toString(iter)) + "__hash")), DeleteEntry(((scriptId + BIGSEP) + k_initiator)), DeleteEntry(((scriptId + BIGSEP) + k_rawCodeHash)), DeleteEntry(((scriptId + BIGSEP) + k_confirmations))]
406+ else throw("Strict value is not equal to itself.")
407+ }
408+ }
409+ }
410+
411+
412+
413+@Callable(i)
414+func addConfirmationScript (scriptId) = {
415+ let callerPbk = toBase58String(i.callerPublicKey)
416+ let limit = _getLimit()
417+ if (!(_isAdmin(callerPbk)))
418+ then throw("Only admins can confirm")
419+ else {
420+ let _scriptHash = valueOrErrorMessage(getString((scriptId + "__scriptHash")), "Ivalid scriptId")
421+ if ((_scriptHash == _scriptHash))
422+ then {
423+ let scriptType = getStringValue((scriptId + "__scriptType"))
424+ let approvedHashesStr = valueOrElse(getString((("script_" + scriptType) + "__approved")), "")
425+ let _checkApproved = if ((indexOf(approvedHashesStr, _scriptHash) != unit))
426+ then throw("This script is approved already")
427+ else true
428+ if ((_checkApproved == _checkApproved))
429+ then {
430+ let globalIteration = valueOrElse(getInteger(((k_ITERATION + SEP) + scriptType)), 0)
431+ let thisIteration = value(getInteger((scriptId + "__iteration")))
432+ let confirmationsStr = valueOrElse(getString((scriptId + "__confirmations")), "")
433+ let confirmations = split(confirmationsStr, ",")
434+ if ((indexOf(confirmations, callerPbk) != unit))
435+ then throw("You already confirmed this script")
436+ else {
437+ let newList = if ((confirmationsStr != ""))
438+ then (confirmations :+ callerPbk)
439+ else [callerPbk]
440+ let newListStr = makeString(newList, ",")
441+ let approved = (size(newList) >= limit)
442+ let result = if (approved)
443+ then {
444+ let approvedCount = _getApprovedCount()
445+ let approvedHashes = split_4C(approvedHashesStr, ",")
446+ let approvedHashesNew = if ((approvedHashesStr != ""))
447+ then (approvedHashes :+ _scriptHash)
448+ else [_scriptHash]
449+ if ((size(approvedHashesNew) > approvedCount))
450+ then {
451+ let hashToRemove = approvedHashesNew[0]
452+ let scriptToRemoveId = ((("script%%" + scriptType) + "%%") + _scriptHash)
453+ let approvedHashesStripped = removeByIndex(approvedHashesNew, 0)
454+[StringEntry((("script_" + scriptType) + "__approved"), makeString_2C(approvedHashesStripped, ",")), StringEntry(((scriptToRemoveId + BIGSEP) + k_confirmations), "")]
455+ }
456+ else [StringEntry((("script_" + scriptType) + "__approved"), makeString_2C(approvedHashesNew, ","))]
457+ }
458+ else nil
459+ (result ++ [StringEntry((scriptId + "__confirmations"), newListStr)])
460+ }
461+ }
462+ else throw("Strict value is not equal to itself.")
463+ }
464+ else throw("Strict value is not equal to itself.")
465+ }
466+ }
467+
468+
469+
470+@Callable(i)
471+func revokeConfirmationScript (scriptId) = {
472+ let callerPbk = toBase58String(i.callerPublicKey)
473+ let limit = _getLimit()
474+ if (!(_isAdmin(callerPbk)))
475+ then throw("Only admins can revoke")
476+ else {
477+ let _scriptHash = valueOrErrorMessage(getString((scriptId + "__scriptHash")), "Invalid scriptId")
478+ if ((_scriptHash == _scriptHash))
479+ then {
480+ let scriptType = getStringValue((scriptId + "__scriptType"))
481+ let approvedHashesStr = valueOrElse(getString((("script_" + scriptType) + "__approved")), "")
482+ let approvedHashes = split_4C(approvedHashesStr, ",")
483+ let confirmationsStr = valueOrElse(getString((scriptId + "__confirmations")), "")
484+ let confirmations = split(confirmationsStr, ",")
485+ let confirmIndex = indexOf(confirmations, callerPbk)
486+ if ((confirmIndex == unit))
487+ then throw("You didn't confirm this script, nothing to revoke")
488+ else {
489+ let newConfirmations = removeByIndex(confirmations, value(confirmIndex))
490+ let newConfirmationsStr = makeString(newConfirmations, ",")
491+ let wasApproved = (indexOf(approvedHashes, _scriptHash) != unit)
492+ let stillApproved = (size(newConfirmations) >= limit)
493+ let stateChanges = if (if (wasApproved)
494+ then !(stillApproved)
495+ else false)
496+ then {
497+ let scriptHashIndex = value(indexOf(approvedHashes, _scriptHash))
498+ let newApprovedHashes = removeByIndex(approvedHashes, scriptHashIndex)
499+ let newApprovedHashesStr = makeString(newApprovedHashes, ",")
500+[StringEntry((("script_" + scriptType) + "__approved"), newApprovedHashesStr)]
501+ }
502+ else nil
503+ (stateChanges ++ [StringEntry((scriptId + "__confirmations"), newConfirmationsStr)])
504+ }
505+ }
506+ else throw("Strict value is not equal to itself.")
507+ }
508+ }
509+
510+
511+
512+@Callable(i)
513+func addTask (name,dapp,txid,executeTs,desc,initiatorAdr,txdata) = {
514+ let callerPbk = toBase58String(i.callerPublicKey)
515+ if (!(_isValidOperator(callerPbk)))
516+ then throw("Not allowed")
517+ else {
518+ let _nameCheck = if ((size(name) == 0))
519+ then throw("Name can't be empty")
520+ else true
521+ if ((_nameCheck == _nameCheck))
522+ then {
523+ let _dappCheck = if (!(_validateAddress(dapp)))
524+ then throw("Incorrect dapp")
525+ else true
526+ if ((_dappCheck == _dappCheck))
527+ then {
528+ let _txidCheck = if ((size(txid) == 0))
529+ then throw("txid can't be empty")
530+ else true
531+ if ((_txidCheck == _txidCheck))
532+ then {
533+ let _timestampCheck = if (!(_validateTs(executeTs)))
534+ then throw("Invalid execution timestamp - cannot be more than 1 hour in the past")
535+ else true
536+ if ((_timestampCheck == _timestampCheck))
537+ then {
538+ let _descCheck = if ((size(desc) == 0))
539+ then throw("Description can't be empty")
540+ else true
541+ if ((_descCheck == _descCheck))
542+ then {
543+ let _initiatorCheck = if ((toString(addressFromPublicKey(i.callerPublicKey)) != initiatorAdr))
544+ then throw("Initiator address doesn't match caller")
545+ else true
546+ if ((_initiatorCheck == _initiatorCheck))
547+ then {
548+ let _txdataCheck = if ((size(txdata) == 0))
549+ then throw("Tx data can't be empty")
550+ else true
551+ if ((_txdataCheck == _txdataCheck))
552+ then {
553+ let taskId = ((("tx_" + dapp) + SEP) + txid)
554+[StringEntry((taskId + "__name"), name), StringEntry((taskId + "__dapp"), dapp), StringEntry((taskId + "__txId"), txid), StringEntry((taskId + "__desc"), desc), StringEntry((taskId + "__txdata"), txdata), StringEntry((taskId + "__initiator"), initiatorAdr), IntegerEntry((taskId + "__ts"), executeTs)]
555+ }
556+ else throw("Strict value is not equal to itself.")
557+ }
558+ else throw("Strict value is not equal to itself.")
559+ }
560+ else throw("Strict value is not equal to itself.")
561+ }
562+ else throw("Strict value is not equal to itself.")
563+ }
564+ else throw("Strict value is not equal to itself.")
565+ }
566+ else throw("Strict value is not equal to itself.")
567+ }
568+ else throw("Strict value is not equal to itself.")
569+ }
570+ }
571+
572+
573+
574+@Callable(i)
575+func removeTask (taskId) = {
576+ let callerPbk = toBase58String(i.callerPublicKey)
577+ if (!(_isValidOperator(callerPbk)))
578+ then throw("Not allowed")
579+ else {
580+ let initiatorAdr = getStringValue((taskId + "__initiator"))
581+ if ((initiatorAdr != toString(addressFromPublicKey(i.callerPublicKey))))
582+ then throw("Only creator can remove")
583+ else {
584+ let txId = valueOrErrorMessage(getString((taskId + "__txId")), "Ivalid task")
585+ if ((txId == txId))
586+ then {
587+ let dapp = getStringValue((taskId + "__dapp"))
588+[DeleteEntry((taskId + "__name")), DeleteEntry((taskId + "__dapp")), DeleteEntry((taskId + "__txId")), DeleteEntry((taskId + "__desc")), DeleteEntry((taskId + "__txdata")), DeleteEntry((taskId + "__initiator")), DeleteEntry((taskId + "__ts")), DeleteEntry((taskId + "__confirmations")), DeleteEntry((((dapp + SEP) + txId) + "__approved"))]
589+ }
590+ else throw("Strict value is not equal to itself.")
591+ }
592+ }
593+ }
594+
595+
596+
597+@Callable(i)
598+func addConfirmation (taskId) = {
599+ let callerPbk = toBase58String(i.callerPublicKey)
600+ let limit = _getLimit()
601+ if (!(_isAdmin(callerPbk)))
602+ then throw("Only admins can confirm")
603+ else {
604+ let txId = valueOrErrorMessage(getString((taskId + "__txId")), "Ivalid task")
605+ if ((txId == txId))
606+ then {
607+ let dapp = getStringValue((taskId + "__dapp"))
608+ let confirmationsStr = valueOrElse(getString((taskId + "__confirmations")), "")
609+ let confirmations = split(confirmationsStr, ",")
610+ if ((indexOf(confirmations, callerPbk) != unit))
611+ then throw("You already confirmed this task")
612+ else {
613+ let newList = if ((confirmationsStr != ""))
614+ then (confirmations :+ callerPbk)
615+ else [callerPbk]
616+ let newListStr = makeString(newList, ",")
617+ let approved = (size(newList) >= limit)
618+[StringEntry((taskId + "__confirmations"), newListStr), BooleanEntry((((dapp + SEP) + txId) + "__approved"), approved)]
619+ }
620+ }
621+ else throw("Strict value is not equal to itself.")
622+ }
623+ }
624+
625+
626+
627+@Callable(i)
628+func revokeTask (taskId) = {
629+ let callerPbk = toBase58String(i.callerPublicKey)
630+ let limit = _getLimit()
631+ if (!(_isAdmin(callerPbk)))
632+ then throw("Only admins can call")
633+ else {
634+ let txId = valueOrErrorMessage(getString((taskId + "__txId")), "Ivalid task")
635+ if ((txId == txId))
636+ then {
637+ let confirmationsStr = valueOrElse(getString((taskId + "__confirmations")), "")
638+ let confirmations = split(confirmationsStr, ",")
639+ let indexMy = indexOf(confirmations, callerPbk)
640+ if ((indexMy == unit))
641+ then throw("You did not confirm this task, nothing to revoke")
642+ else {
643+ let dapp = getStringValue((taskId + "__dapp"))
644+ let newList = removeByIndex(confirmations, value(indexMy))
645+ let newListStr = makeString(newList, ",")
646+ let approved = (size(newList) >= limit)
647+[StringEntry((taskId + "__confirmations"), newListStr), BooleanEntry((((dapp + SEP) + txId) + "__approved"), approved)]
648+ }
649+ }
650+ else throw("Strict value is not equal to itself.")
651+ }
652+ }
653+
654+
655+
656+@Callable(i)
657+func test () = {
658+ let x = match blockInfoByHeight(height) {
659+ case block: BlockInfo =>
660+ throw(toString(block.timestamp))
661+ case _ =>
662+ throw("Can't find block")
663+ }
664+ if ((x == x))
665+ then nil
666+ else throw("Strict value is not equal to itself.")
667+ }
668+
669+
670+
671+@Callable(i)
672+func clear_test () = {
673+ let indices = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
674+ func removeChunks (accum,index) = (accum :+ DeleteEntry((("testtask" + "__txdata_") + toString(index))))
675+
676+ let entries = {
677+ let $l = indices
678+ let $s = size($l)
679+ let $acc0 = [DeleteEntry(("testtask" + "__txdata_chunks"))]
680+ func $f0_1 ($a,$i) = if (($i >= $s))
681+ then $a
682+ else removeChunks($a, $l[$i])
683+
684+ func $f0_2 ($a,$i) = if (($i >= $s))
685+ then $a
686+ else throw("List size exceeds 10")
687+
688+ $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
689+ }
690+ entries
691+ }
692+
693+
694+@Verifier(tx)
695+func verify () = {
696+ let MULTISIG_ADDRESS = addressFromString("3M7uzD8rT54fKQcP4s417if1VKU8yromEP2")
697+ let CONTRACT_TYPE = "APPROVER_CONTRACT"
698+ if ((MULTISIG_ADDRESS != unit))
699+ then match tx {
700+ case ttx: SetScriptTransaction =>
701+ let scriptHasha = toBase58String(value(blake2b256(value(ttx.script))))
702+ let approvedHashes = value(getString(value(MULTISIG_ADDRESS), (("script_" + CONTRACT_TYPE) + "__approved")))
703+ (indexOf(approvedHashes, scriptHasha) != unit)
704+ case otx =>
705+ valueOrElse(getBoolean(value(this), (((toString(this) + "_") + toBase58String(otx.id)) + "__approved")), false)
706+ }
707+ else sigVerify(tx.bodyBytes, tx.proofs[0], tx.senderPublicKey)
708+ }
709+

github/deemru/w8io
38.14 ms