tx · B5Ss9LnJrASTnXX9Zi1sKjMcGwzEL4hCr4krakArSVBE

3MM6826GKXHd1srj1Cr72odPbxnc54EJieA:  -0.03000000 Waves

2025.10.26 02:14 [560551] smart account 3MM6826GKXHd1srj1Cr72odPbxnc54EJieA > SELF 0.00000000 Waves

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

github/deemru/w8io
30.59 ms