2023.01.25 16:15 [3486058] smart account 3PFraDBNUFry9mgcfMo3hGcr3dm43TuYmN6 > SELF 0.00000000 Waves

{ "type": 13, "id": "2N8TP2xw4ARr3rNpaYQdDZRTjcougncPR9PPteqv1REi", "fee": 1800000, "feeAssetId": null, "timestamp": 1674652565533, "version": 1, "sender": "3PFraDBNUFry9mgcfMo3hGcr3dm43TuYmN6", "senderPublicKey": "C7QLmUucg9PUNVtaRsoDoMmJwLv4gGcxrEPNrorLjg2f", "proofs": [ "38uRAT4YSSXBwZp5W9eexbiPd7qysvtKBuUwDJLgNTsb7RvwJ52FdPdVQqXUi4XBQyU3wH2Z1EdsxgVW8e1rYh6R" ], "script": "base64:BgIyCAISBAoCCAgSAwoBCBIAEgASBAoCCAESBAoCCAgSBQoDCAgBEgUKAwgICBIFCgMICAgzAQRnZXRJAQNrZXkJAJoIAgUEdGhpcwUDa2V5AQRnZXRTAQNrZXkJAJ0IAgUEdGhpcwUDa2V5AQVnZXRTVgEDa2V5CQETdmFsdWVPckVycm9yTWVzc2FnZQIJAJ0IAgUEdGhpcwUDa2V5CQCsAgIJAKwCAgkArAICAhhubyBzdHJpbmcgdmFsdWUgZm9yIGtleSAFA2tleQIMIGF0IGFkZHJlc3MgCQClCAEFBHRoaXMBBmFzSW50MgEFdmFsdWUEByRtYXRjaDAFBXZhbHVlAwkAAQIFByRtYXRjaDACCihJbnQsIEludCkEAXgFByRtYXRjaDAFAXgEAXQFByRtYXRjaDAJAAIBAhp3cm9uZyB0eXBlLCBleHBlY3RlZDogSW50MgEHdGhyb3dJZgIJY29uZGl0aW9uBWVycm9yAwUJY29uZGl0aW9uCQACAQUFZXJyb3IGAQh3cml0ZUludAIDa2V5BXZhbHVlAwkAZgIAAAUFdmFsdWUJAAIBCQCsAgIJAKwCAgkArAICAhd3cml0aW5nIG5lZ2F0aXZlIHZhbHVlIAkApAMBBQV2YWx1ZQIJIGZvciBrZXkgBQNrZXkJAQxJbnRlZ2VyRW50cnkCBQNrZXkFBXZhbHVlAQVhc0ludAEFdmFsdWUEByRtYXRjaDAFBXZhbHVlAwkAAQIFByRtYXRjaDACA0ludAQDaW50BQckbWF0Y2gwBQNpbnQJAAIBAgVscGw6MQEIY2hhbmdlQnkCA2tleQV2YWx1ZQkBCHdyaXRlSW50AgUDa2V5CQBkAgkBC3ZhbHVlT3JFbHNlAgkBBGdldEkBBQNrZXkAAAUFdmFsdWUBEHdyaXRlQ29uc3RTdHJpbmcCA2tleQV2YWx1ZQMJAQEhAQkBCWlzRGVmaW5lZAEJAJ0IAgUEdGhpcwUDa2V5CQELU3RyaW5nRW50cnkCBQNrZXkFBXZhbHVlCQACAQkArAICAhVhbHJlYWR5IGluaXRpYWxpemVkOiAFA2tleQANQmxvY2tzUGVyWWVhcgCgiiAAC2ZhY3RvcnNCYXNlAOgHAQxmcmFjdGlvbkNlaWwDBXZhbHVlCW51bWVyYXRvcgtkZW5vbWluYXRvcgQEY2FuZAkAawMFBXZhbHVlBQludW1lcmF0b3IFC2Rlbm9taW5hdG9yBAFEALPmk6gLBAVleGFjdAkAAAIJAGoCCQBoAgkAagIFBGNhbmQFAUQJAGoCBQtkZW5vbWluYXRvcgUBRAUBRAkAagIJAGgCCQBqAgUFdmFsdWUFAUQJAGoCBQludW1lcmF0b3IFAUQFAUQDBQVleGFjdAUEY2FuZAkAZAIFBGNhbmQAAQALY29uZmlnU3RvcmUCBmNvbmZpZwANY29uZmlnQWRkcmVzcwkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCmCAEJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAnQgCBQR0aGlzBQtjb25maWdTdG9yZQIScmVzZXJ2ZTogbm8gY29uZmlnAhZpbnZhbGlkIGNvbmZpZyBhZGRyZXNzABFyZXdhcmRSZXNlcnZlc1N0cgkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCdCAIFDWNvbmZpZ0FkZHJlc3MCE3Jld2FyZGFibGVfcmVzZXJ2ZXMCK2xwLWxvY2tlcjogbm8gcmV3YXJkYWJsZV9yZXNlcnZlcyBpbiBjb25maWcAFXplcm9SZXdhcmRSZXNlcnZlc1N0cgkBC3ZhbHVlT3JFbHNlAgkAnQgCBQ1jb25maWdBZGRyZXNzAhh6ZXJvX3Jld2FyZGFibGVfcmVzZXJ2ZXMCAAAOcmV3YXJkUmVzZXJ2ZXMJALwJAgURcmV3YXJkUmVzZXJ2ZXNTdHICAXwBCW9wQWxsb3dlZAICb3AJbHBBc3NldElkBAckbWF0Y2gwCQD8BwQFDWNvbmZpZ0FkZHJlc3MCCW9wQWxsb3dlZAkAzAgCBQlscEFzc2V0SWQJAMwIAgUCb3AFA25pbAUDbmlsAwkAAQIFByRtYXRjaDACB0Jvb2xlYW4EAWIFByRtYXRjaDADBQFiBgkAAgECC25vdCBhbGxvd2VkCQACAQIhb3BBbGxvd2VkOiB1bmV4cGVjdGVkIHJlc3VsdCB0eXBlAQ91c2VyQW1vdW50U3RvcmUCB2FkZHJlc3MFYXNzZXQJAKwCAgkArAICCQCsAgIFB2FkZHJlc3MCAV8FBWFzc2V0AgRfYW10ARV1c2VyVW5sb2NrSGVpZ2h0U3RvcmUCB2FkZHJlc3MFYXNzZXQJAKwCAgkArAICCQCsAgIFB2FkZHJlc3MCAV8FBWFzc2V0Ag1fdW5sb2NrSGVpZ2h0ARV1c2VyV2VpZ2h0RmFjdG9yU3RvcmUCB2FkZHJlc3MFYXNzZXQJAKwCAgkArAICCQCsAgIFB2FkZHJlc3MCAV8FBWFzc2V0Ag1fd2VpZ2h0RmFjdG9yAQ91c2VyV2VpZ2h0U3RvcmUCB2FkZHJlc3MFYXNzZXQJAKwCAgkArAICCQCsAgIFB2FkZHJlc3MCAV8FBWFzc2V0Agdfd2VpZ2h0ARV0b3RhbEFzc2V0TG9ja2VkU3RvcmUBBWFzc2V0CQCsAgIFBWFzc2V0AgxfdG90YWxMb2NrZWQBHXRvdGFsV2VpZ2h0ZWRBc3NldExvY2tlZFN0b3JlAQVhc3NldAkArAICBQVhc3NldAIUX3RvdGFsV2VpZ2h0ZWRMb2NrZWQBCnVzZXJBbW91bnQCB2FkZHJlc3MFYXNzZXQJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwkBD3VzZXJBbW91bnRTdG9yZQIFB2FkZHJlc3MFBWFzc2V0AAABEHVzZXJVbmxvY2tIZWlnaHQCB2FkZHJlc3MFYXNzZXQJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwkBFXVzZXJVbmxvY2tIZWlnaHRTdG9yZQIFB2FkZHJlc3MFBWFzc2V0AAABEHVzZXJXZWlnaHRGYWN0b3ICB2FkZHJlc3MFYXNzZXQJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwkBFXVzZXJXZWlnaHRGYWN0b3JTdG9yZQIFB2FkZHJlc3MFBWFzc2V0AAABCnVzZXJXZWlnaHQCB2FkZHJlc3MFYXNzZXQJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwkBD3VzZXJXZWlnaHRTdG9yZQIFB2FkZHJlc3MFBWFzc2V0AAABEHRvdGFsQXNzZXRMb2NrZWQBBWFzc2V0CQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMJARV0b3RhbEFzc2V0TG9ja2VkU3RvcmUBBQVhc3NldAAAARh0b3RhbFdlaWdodGVkQXNzZXRMb2NrZWQBBWFzc2V0CQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMJAR10b3RhbFdlaWdodGVkQXNzZXRMb2NrZWRTdG9yZQEFBWFzc2V0AAAAEm1heWJlT3JhY2xlQWRkcmVzcwQHJG1hdGNoMAkAnQgCBQ1jb25maWdBZGRyZXNzAg5vcmFjbGVfYWRkcmVzcwMJAAECBQckbWF0Y2gwAgZTdHJpbmcEAXMFByRtYXRjaDAJAKYIAQUBcwUEdW5pdAELb3JhY2xlUHJpY2UBB2Fzc2V0SWQEByRtYXRjaDAJAPwHBAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCBRJtYXliZU9yYWNsZUFkZHJlc3MCCW5vIG9yYWNsZQIFcHJpY2UJAMwIAgUHYXNzZXRJZAUDbmlsBQNuaWwDCQABAgUHJG1hdGNoMAIDSW50BAFpBQckbWF0Y2gwBQFpCQACAQIPYmFkIG9yYWNsZSBkYXRhAAZIRUlHSFQFBmhlaWdodAEIbWFpbk9ubHkBAWkDCQEIY29udGFpbnMCCQERQGV4dHJOYXRpdmUoMTA1MykCBQ1jb25maWdBZGRyZXNzAgRtYWluCQClCAEIBQFpBmNhbGxlcgYJAAIBAhBvbmx5IG1haW4gY2FuIGRvAApzdGFydGVkS2V5AgdzdGFydGVkAQ9zeW5jSGVpZ2h0U3RvcmUBB2Fzc2V0SWQJAKwCAgUHYXNzZXRJZAINX3N5bmNlZEhlaWdodAEKc3BlZWRTdG9yZQEHYXNzZXRJZAkArAICBQdhc3NldElkAgZfc3BlZWQBC3Jld2FyZFN0b3JlAQdhc3NldElkCQCsAgIFB2Fzc2V0SWQCB19yZXdhcmQBEHVzZXJDbGFpbWVkU3RvcmUCB2Fzc2V0SWQEdXNlcgkArAICCQCsAgIFBHVzZXICCV9jbGFpbWVkXwUHYXNzZXRJZAESdXNlclJld2FyZEFkalN0b3JlAgdhc3NldElkBHVzZXIJAKwCAgkArAICBQR1c2VyAg9fdXNlclJld2FyZEFkal8FB2Fzc2V0SWQBCnN5bmNIZWlnaHQBBWFzc2V0CQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMJAQ9zeW5jSGVpZ2h0U3RvcmUBBQVhc3NldAAAAQVwb3cxMAEBbgMJAAACBQFuAAYAwIQ9AwkAAAIFAW4ACACAwtcvCQACAQkArAICAg5iYWQgZGVjaW1hbHM6IAkApAMBBQFuAAt2aXJlc01pbnRlcgkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCmCAEJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAnQgCBQ1jb25maWdBZGRyZXNzAgx2aXJlc19taW50ZXICIXZpcmVzLWRpc3RyaWJ1dG9yOiBubyB2aXJlc01pbnRlcgITaW52YWxpZCB2aXJlc01pbnRlcgAKdmlyZXNJZFN0cgkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCdCAIFC3ZpcmVzTWludGVyAgdhc3NldElkAid2aXJlcy1kaXN0cmlidXRvcjogbm8gdmlyZXNBc3NldElkU3RvcmUADHZpcmVzQXNzZXRJZAkA2QQBBQp2aXJlc0lkU3RyAAdzdGFydGVkCQEJaXNEZWZpbmVkAQkAmggCBQR0aGlzBQpzdGFydGVkS2V5AQ1jdXJyZW50UmV3YXJkAQdhc3NldElkBAFoCQEKc3luY0hlaWdodAEFB2Fzc2V0SWQEDHN0b3JlZFJld2FyZAkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzCQELcmV3YXJkU3RvcmUBBQdhc3NldElkAAADCQAAAgUBaAUGSEVJR0hUBQxzdG9yZWRSZXdhcmQEBXNwZWVkCQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMJAQpzcGVlZFN0b3JlAQUHYXNzZXRJZAAABBFhY2N1bXVsYXRlZFJld2FyZAkAaAIJAGUCBQZIRUlHSFQFAWgFBXNwZWVkCQBkAgUMc3RvcmVkUmV3YXJkBRFhY2N1bXVsYXRlZFJld2FyZAETY3VycmVudFJld2FyZHNTcGVlZAAKAQVmb2xkMgIBbAdyZXNlcnZlBAdhc3NldElkCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAJ0IAgkBEUBleHRyTmF0aXZlKDEwNjIpAQUHcmVzZXJ2ZQIIYVRva2VuSWQCC25vIGFUb2tlbklkCQCsAgIJAKwCAgkArAICCQCsAgIFAWwFB2Fzc2V0SWQCAT0JAKQDAQkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzCQEKc3BlZWRTdG9yZQEFB2Fzc2V0SWQAAAICLCAKAAIkbAUOcmV3YXJkUmVzZXJ2ZXMKAAIkcwkAkAMBBQIkbAoABSRhY2MwAgAKAQUkZjBfMQICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkBBWZvbGQyAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGYwXzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhRMaXN0IHNpemUgZXhjZWVkcyAyMAkBBSRmMF8yAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgUFJGFjYzAAAAABAAIAAwAEAAUABgAHAAgACQAKAAsADAANAA4ADwAQABEAEgATABQBEXVzZXJSZXdhcmRCYWxhbmNlAgdhc3NldElkBHVzZXIEEGN1clRvdGFsV2VpZ2h0ZWQJARh0b3RhbFdlaWdodGVkQXNzZXRMb2NrZWQBBQdhc3NldElkBAx1c2VyV2VpZ2h0ZWQJAGsDCQEKdXNlckFtb3VudAIFBHVzZXIFB2Fzc2V0SWQJARB1c2VyV2VpZ2h0RmFjdG9yAgUEdXNlcgUHYXNzZXRJZAULZmFjdG9yc0Jhc2UEC3RvdGFsUmV3YXJkCQENY3VycmVudFJld2FyZAEFB2Fzc2V0SWQEB3VzZXJBZGoJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwkBEnVzZXJSZXdhcmRBZGpTdG9yZQIFB2Fzc2V0SWQFBHVzZXIAAAQDYWNjCQBkAgUHdXNlckFkagMJAAACBRBjdXJUb3RhbFdlaWdodGVkAAAAAAkAawMFC3RvdGFsUmV3YXJkBQx1c2VyV2VpZ2h0ZWQFEGN1clRvdGFsV2VpZ2h0ZWQEB2NsYWltZWQJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwkBEHVzZXJDbGFpbWVkU3RvcmUCBQdhc3NldElkBQR1c2VyAAAJAJQKAgUDYWNjBQdjbGFpbWVkARB1cGRhdGVSZXdhcmREYXRhAwdhZGRyZXNzB2Fzc2V0SWQKdXNlckNoYW5nZQQJcHJldlRvdGFsCQEYdG90YWxXZWlnaHRlZEFzc2V0TG9ja2VkAQUHYXNzZXRJZAQKcHJldlJld2FyZAkBDWN1cnJlbnRSZXdhcmQBBQdhc3NldElkBAtwcmV2VXNlckFkagkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzCQESdXNlclJld2FyZEFkalN0b3JlAgUHYXNzZXRJZAUHYWRkcmVzcwAABAhuZXdUb3RhbAkAZAIFCXByZXZUb3RhbAUKdXNlckNoYW5nZQQQbmV3UmVzZXJ2ZVJld2FyZAMJAAACBQlwcmV2VG90YWwAAAUKcHJldlJld2FyZAkAawMFCnByZXZSZXdhcmQFCG5ld1RvdGFsBQlwcmV2VG90YWwEEG5ld1VzZXJSZXdhcmRBZGoDCQAAAgUIbmV3VG90YWwAAAkAZAIFC3ByZXZVc2VyQWRqBQpwcmV2UmV3YXJkCQBlAgULcHJldlVzZXJBZGoJAGsDBRBuZXdSZXNlcnZlUmV3YXJkBQp1c2VyQ2hhbmdlBQhuZXdUb3RhbAkAzAgCCQEMSW50ZWdlckVudHJ5AgkBC3Jld2FyZFN0b3JlAQUHYXNzZXRJZAUQbmV3UmVzZXJ2ZVJld2FyZAkAzAgCCQEMSW50ZWdlckVudHJ5AgkBEnVzZXJSZXdhcmRBZGpTdG9yZQIFB2Fzc2V0SWQFB2FkZHJlc3MFEG5ld1VzZXJSZXdhcmRBZGoJAMwIAgkBDEludGVnZXJFbnRyeQIJAQ9zeW5jSGVpZ2h0U3RvcmUBBQdhc3NldElkBQZIRUlHSFQFA25pbAEiYm9ycm93ZWRWYWx1ZUJ5SW5kZXhBbmRUb3RhbEJvcnJvdwAKAQRmb2xkAgNhY2MBYQQHYWRkcmVzcwkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCmCAEFAWEJAKwCAgIMYmFkIGFkZHJlc3MgBQFhBAxhc3NldERlYnRVc2QDCQEIY29udGFpbnMCBRV6ZXJvUmV3YXJkUmVzZXJ2ZXNTdHIFAWEAAAQHYXNzZXRJZAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCdCAIFB2FkZHJlc3MCB2Fzc2V0SWQJAKwCAgIdYXNzZXRJZCBub3QgZm91bmQgaW4gcmVzZXJ2ZSAFAWEEDWFzc2V0RGVjaW1hbHMDCQAAAgUHYXNzZXRJZAIFV0FWRVMACAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCaCAIFB2FkZHJlc3MCDmFUb2tlbkRlY2ltYWxzCQCsAgICJGFUb2tlbkRlY2ltYWxzIG5vdCBmb3VuZCBpbiByZXNlcnZlIAUBYQQJYXNzZXREZWJ0CAkBBmFzSW50MgEJAPwHBAUHYWRkcmVzcwITc3RvcmVkRGVwb3NpdEJvcnJvdwUDbmlsBQNuaWwCXzIJAGsDBQlhc3NldERlYnQJAQtvcmFjbGVQcmljZQEFB2Fzc2V0SWQJAQVwb3cxMAEFDWFzc2V0RGVjaW1hbHMECyR0MDc4Mzk3ODU4BQNhY2MEA2xzdAgFCyR0MDc4Mzk3ODU4Al8xBANhZ2cIBQskdDA3ODM5Nzg1OAJfMgkAlAoCCQDOCAIFA2xzdAkAzAgCBQxhc3NldERlYnRVc2QFA25pbAkAZAIFA2FnZwUMYXNzZXREZWJ0VXNkCgACJGwFDnJld2FyZFJlc2VydmVzCgACJHMJAJADAQUCJGwKAAUkYWNjMAkAlAoCBQNuaWwAAAoBBSRmMF8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQEEZm9sZAIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmMF8yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQIUTGlzdCBzaXplIGV4Y2VlZHMgMjAJAQUkZjBfMgIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYABwAIAAkACgALAAwADQAOAA8AEAARABIAEwAUCQFpAQphZHZpc2VVc2VyAgR1c2VyB2Fzc2V0SWQEEGN1clRvdGFsV2VpZ2h0ZWQJARh0b3RhbFdlaWdodGVkQXNzZXRMb2NrZWQBBQdhc3NldElkBAp1c2VyRmFjdG9yCQEQdXNlcldlaWdodEZhY3RvcgIFBHVzZXIFB2Fzc2V0SWQEB3VzZXJBbXQJAQp1c2VyQW1vdW50AgUEdXNlcgUHYXNzZXRJZAQMdXNlcldlaWdodGVkCQBrAwUHdXNlckFtdAUKdXNlckZhY3RvcgULZmFjdG9yc0Jhc2UEDHVubG9ja0hlaWdodAkBEHVzZXJVbmxvY2tIZWlnaHQCBQR1c2VyBQdhc3NldElkBAt0b3RhbFJld2FyZAkBDWN1cnJlbnRSZXdhcmQBBQdhc3NldElkBAd1c2VyQWRqCQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMJARJ1c2VyUmV3YXJkQWRqU3RvcmUCBQdhc3NldElkBQR1c2VyAAAEA3BpZQMJAAACBRBjdXJUb3RhbFdlaWdodGVkAAAAAAkAawMFC3RvdGFsUmV3YXJkBQx1c2VyV2VpZ2h0ZWQFEGN1clRvdGFsV2VpZ2h0ZWQEA2FjYwkAZAIFB3VzZXJBZGoFA3BpZQQHY2xhaW1lZAkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzCQEQdXNlckNsYWltZWRTdG9yZQIFB2Fzc2V0SWQFBHVzZXIAAAQXdG90YWxSZXdhcmRzQWNjdW11bGF0ZWQJAJYDAQkAzAgCAAAJAMwIAgUDYWNjBQNuaWwEEHJld2FyZHNBdmFpbGFibGUJAJYDAQkAzAgCAAAJAMwIAgkAZQIFF3RvdGFsUmV3YXJkc0FjY3VtdWxhdGVkBQdjbGFpbWVkBQNuaWwJAJQKAgUDbmlsCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgIXbHBfcmV3YXJkc0FjY3VtdWxhdGVkOiAJAKQDAQUXdG90YWxSZXdhcmRzQWNjdW11bGF0ZWQCFywgbHBfcmV3YXJkc0F2YWlsYWJsZTogCQCkAwEFEHJld2FyZHNBdmFpbGFibGUCFSwgbHBfcmV3YXJkc0NsYWltZWQ6IAkApAMBBQdjbGFpbWVkAg4sIGxwX3VzZXJBZGo6IAkApAMBBQd1c2VyQWRqAgosIGxwX3BpZTogCQCkAwEFA3BpZQINLCBscF9sb2NrZWQ6IAkApAMBBQd1c2VyQW10AhEsIGxwX3VzZXJGYWN0b3I6IAkApAMBBQp1c2VyRmFjdG9yAhMsIGxwX3VubG9ja0hlaWdodDogCQCkAwEFDHVubG9ja0hlaWdodAINLCBscF93ZWlnaHQ6IAkApAMBBQx1c2VyV2VpZ2h0ZWQBaQEKaW5pdGlhbGl6ZQECY2EJAMwIAgkBEHdyaXRlQ29uc3RTdHJpbmcCBQtjb25maWdTdG9yZQUCY2EFA25pbAFpAQVzdGFydAADCQECIT0CCAUBaQZjYWxsZXIFBHRoaXMJAAIBAhBvbmx5IHNlbGYgY2FuIGRvAwUHc3RhcnRlZAkAAgECD2FscmVhZHkgc3RhcnRlZAoBBGZvbGQCAWwHcmVzZXJ2ZQQHYXNzZXRJZAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCdCAIJARFAZXh0ck5hdGl2ZSgxMDYyKQEFB3Jlc2VydmUCCGFUb2tlbklkAhdsb2NrLWRpc3RyOiBubyBhVG9rZW5JZAkAzggCBQFsCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEKc3BlZWRTdG9yZQEFB2Fzc2V0SWQAAAkAzAgCCQEMSW50ZWdlckVudHJ5AgkBC3Jld2FyZFN0b3JlAQUHYXNzZXRJZAAACQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEPc3luY0hlaWdodFN0b3JlAQUHYXNzZXRJZAUGSEVJR0hUBQNuaWwKAAIkbAUOcmV3YXJkUmVzZXJ2ZXMKAAIkcwkAkAMBBQIkbAoABSRhY2MwCQDMCAIJAQxJbnRlZ2VyRW50cnkCBQpzdGFydGVkS2V5BQZIRUlHSFQFA25pbAoBBSRmMF8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQEEZm9sZAIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmMF8yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQIUTGlzdCBzaXplIGV4Y2VlZHMgMjAJAQUkZjBfMgIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYABwAIAAkACgALAAwADQAOAA8AEAARABIAEwAUAWkBB3JlYWxsb2MAAwkBASEBBQdzdGFydGVkCQACAQILbm90IHN0YXJ0ZWQDCQEBIQEJAQlvcEFsbG93ZWQCAg9scF9sb2NrX3JlYWxsb2MFCnZpcmVzSWRTdHIJAAIBAg5yZWFsbG9jIHBhdXNlZAQKdG90YWxTcGVlZAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCaCAIFDWNvbmZpZ0FkZHJlc3MCE2xwX2xvY2tfdG90YWxfc3BlZWQCGW5vIHRvdGFsIGFsbG9jYXRpb24gc3BlZWQEDXRvdGFsUmVzZXJ2ZXMJAJADAQUOcmV3YXJkUmVzZXJ2ZXMEDSR0MDEwMzQ1MTA0MjIJASJib3Jyb3dlZFZhbHVlQnlJbmRleEFuZFRvdGFsQm9ycm93AAQUYm9ycm93ZWRWYWx1ZUJ5SW5kZXgIBQ0kdDAxMDM0NTEwNDIyAl8xBAt0b3RhbEJvcnJvdwgFDSR0MDEwMzQ1MTA0MjICXzIKAQRmb2xkAgFsBWluZGV4AwkAZwIFBWluZGV4BQ10b3RhbFJlc2VydmVzBQFsBAdyZXNlcnZlCQCRAwIFDnJld2FyZFJlc2VydmVzBQVpbmRleAQHYXNzZXRJZAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCdCAIJARFAZXh0ck5hdGl2ZSgxMDYyKQEFB3Jlc2VydmUCCGFUb2tlbklkAhZiYWQgcmVzZXJ2ZSBpbiByZWFsbG9jBAphc3NldFNwZWVkAwkAAAIFC3RvdGFsQm9ycm93AAAAAAkAawMFCnRvdGFsU3BlZWQJAJEDAgUUYm9ycm93ZWRWYWx1ZUJ5SW5kZXgFBWluZGV4BQt0b3RhbEJvcnJvdwQCY3IJAQ1jdXJyZW50UmV3YXJkAQUHYXNzZXRJZAkAzggCBQFsCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEKc3BlZWRTdG9yZQEFB2Fzc2V0SWQFCmFzc2V0U3BlZWQJAMwIAgkBDEludGVnZXJFbnRyeQIJAQtyZXdhcmRTdG9yZQEFB2Fzc2V0SWQFAmNyCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEPc3luY0hlaWdodFN0b3JlAQUHYXNzZXRJZAUGSEVJR0hUBQNuaWwKAAIkbAkAzAgCAAAJAMwIAgABCQDMCAIAAgkAzAgCAAMJAMwIAgAECQDMCAIABQkAzAgCAAYJAMwIAgAHCQDMCAIACAkAzAgCAAkJAMwIAgAKCQDMCAIACwkAzAgCAAwJAMwIAgANCQDMCAIADgkAzAgCAA8JAMwIAgAQCQDMCAIAEQkAzAgCABIJAMwIAgATBQNuaWwKAAIkcwkAkAMBBQIkbAoABSRhY2MwBQNuaWwKAQUkZjBfMQICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkBBGZvbGQCBQIkYQkAkQMCBQIkbAUCJGkKAQUkZjBfMgICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkAAgECFExpc3Qgc2l6ZSBleGNlZWRzIDIwCQEFJGYwXzICCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECBQUkYWNjMAAAAAEAAgADAAQABQAGAAcACAAJAAoACwAMAA0ADgAPABAAEQASABMAFAFpAQZsb2NrTFACB2FkZHJlc3MOZHVyYXRpb25CbG9ja3MECWFkZHJDaGVjawkBEUBleHRyTmF0aXZlKDEwNjIpAQUHYWRkcmVzcwMJAAACBQlhZGRyQ2hlY2sFCWFkZHJDaGVjawMJAQEhAQUHc3RhcnRlZAkAAgECC25vdCBzdGFydGVkAwkAAAIJAJADAQgFAWkIcGF5bWVudHMAAAkAlAoCBQNuaWwAAAQHYXNzZXRJZAkA2AQBCQEFdmFsdWUBCAkAkQMCCAUBaQhwYXltZW50cwAAB2Fzc2V0SWQEBmNoZWNrcwMJAQhtYWluT25seQEFAWkJAQlvcEFsbG93ZWQCAgdsb2NrX2xwBQdhc3NldElkBwMJAAACBQZjaGVja3MFBmNoZWNrcwQDYW10CAkAkQMCCAUBaQhwYXltZW50cwAABmFtb3VudAQJbWluQW1vdW50CQETdmFsdWVPckVycm9yTWVzc2FnZQIJAJoIAgUNY29uZmlnQWRkcmVzcwkArAICAhBsb2NrX21pbl9hbW91bnRfBQdhc3NldElkCQCsAgICEW5vIG1pbl9hbW91bnQgZm9yBQdhc3NldElkBApwcmV2QXNzZXRzCQEKdXNlckFtb3VudAIFB2FkZHJlc3MFB2Fzc2V0SWQDCQBmAgUJbWluQW1vdW50CQBkAgUKcHJldkFzc2V0cwUDYW10CQACAQkArAICCQCsAgIJAKwCAgIWbG9ja2luZyBsZXNzIHRoYW4gbWluIAkApAMBBQltaW5BbW91bnQCBCBvZiAFB2Fzc2V0SWQEEHByZXZXZWlnaHRGYWN0b3IJARB1c2VyV2VpZ2h0RmFjdG9yAgUHYWRkcmVzcwUHYXNzZXRJZAQOcHJldlVzZXJXZWlnaHQJAQp1c2VyV2VpZ2h0AgUHYWRkcmVzcwUHYXNzZXRJZAQQcHJldlVubG9ja0hlaWdodAkBEHVzZXJVbmxvY2tIZWlnaHQCBQdhZGRyZXNzBQdhc3NldElkBAx3ZWlnaHRGYWN0b3IJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAmggCBQ1jb25maWdBZGRyZXNzCQCsAgICE2xvY2tfd2VpZ2h0X2ZhY3Rvcl8JAKQDAQUOZHVyYXRpb25CbG9ja3MJAKwCAgIjbm8gd2VpZ2h0RmFjdG9yIGZvciBkdXJhdGlvbkJsb2NrcyAJAKQDAQUOZHVyYXRpb25CbG9ja3MDAwkAZgIFEHByZXZXZWlnaHRGYWN0b3IFDHdlaWdodEZhY3RvcgkAZgIFEHByZXZVbmxvY2tIZWlnaHQFBkhFSUdIVAcJAAIBAi9jYW4ndCBkZWNyZWFzZSB3ZWlnaHRGYWN0b3IgaWYgbm90IHVubG9ja2VkIHlldAQNbmV3VXNlcldlaWdodAkAawMJAGQCBQpwcmV2QXNzZXRzBQNhbXQFDHdlaWdodEZhY3RvcgULZmFjdG9yc0Jhc2UEEHVzZXJXZWlnaHRDaGFuZ2UJAGUCBQ1uZXdVc2VyV2VpZ2h0BQ5wcmV2VXNlcldlaWdodAQKdG9rZW5zRGF0YQkAzAgCCQEIY2hhbmdlQnkCCQEPdXNlckFtb3VudFN0b3JlAgUHYWRkcmVzcwUHYXNzZXRJZAUDYW10CQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEVdXNlclVubG9ja0hlaWdodFN0b3JlAgUHYWRkcmVzcwUHYXNzZXRJZAkAZAIFBkhFSUdIVAUOZHVyYXRpb25CbG9ja3MJAMwIAgkBDEludGVnZXJFbnRyeQIJARV1c2VyV2VpZ2h0RmFjdG9yU3RvcmUCBQdhZGRyZXNzBQdhc3NldElkBQx3ZWlnaHRGYWN0b3IJAMwIAgkBDEludGVnZXJFbnRyeQIJAQ91c2VyV2VpZ2h0U3RvcmUCBQdhZGRyZXNzBQdhc3NldElkBQ1uZXdVc2VyV2VpZ2h0CQDMCAIJAQhjaGFuZ2VCeQIJARV0b3RhbEFzc2V0TG9ja2VkU3RvcmUBBQdhc3NldElkBQNhbXQJAMwIAgkBCGNoYW5nZUJ5AgkBHXRvdGFsV2VpZ2h0ZWRBc3NldExvY2tlZFN0b3JlAQUHYXNzZXRJZAUQdXNlcldlaWdodENoYW5nZQUDbmlsCQDOCAIFCnRva2Vuc0RhdGEJARB1cGRhdGVSZXdhcmREYXRhAwUHYWRkcmVzcwUHYXNzZXRJZAUQdXNlcldlaWdodENoYW5nZQkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpARZjbGVhblVwRGlzdHJpYnV0aW9uRm9yAgdhZGRyZXNzB2Fzc2V0SWQECWFkZHJDaGVjawkBEUBleHRyTmF0aXZlKDEwNjIpAQUHYWRkcmVzcwMJAAACBQlhZGRyQ2hlY2sFCWFkZHJDaGVjawMJAQEhAQUHc3RhcnRlZAkAAgECC25vdCBzdGFydGVkBAZjaGVja3MJAQlvcEFsbG93ZWQCAh1zdG9wX2Rpc3RyaWJ1dGlvbl91bmxvY2tlZF9scAUHYXNzZXRJZAMJAAACBQZjaGVja3MFBmNoZWNrcwQMdW5sb2NrSGVpZ2h0CQEQdXNlclVubG9ja0hlaWdodAIFB2FkZHJlc3MFB2Fzc2V0SWQDCQAAAgUMdW5sb2NrSGVpZ2h0AAAFA25pbAQQdXNlckFtb3VudENoYW5nZQkBAS0BCQEKdXNlckFtb3VudAIFB2FkZHJlc3MFB2Fzc2V0SWQEEHVzZXJXZWlnaHRDaGFuZ2UJAQEtAQkBCnVzZXJXZWlnaHQCBQdhZGRyZXNzBQdhc3NldElkBBRleGNlcHRpb25FYXJseVVubG9jawkBCGNvbnRhaW5zAgkBC3ZhbHVlT3JFbHNlAgkAnQgCBQ1jb25maWdBZGRyZXNzAhlscF91bmxvY2tfZnJlZV9hdG9rZW5faWRzAgAFB2Fzc2V0SWQDAwkAZwIFBkhFSUdIVAUMdW5sb2NrSGVpZ2h0BgUUZXhjZXB0aW9uRWFybHlVbmxvY2sECnRva2Vuc0RhdGEJAMwIAgkBC0RlbGV0ZUVudHJ5AQkBFXVzZXJVbmxvY2tIZWlnaHRTdG9yZQIFB2FkZHJlc3MFB2Fzc2V0SWQJAMwIAgkBC0RlbGV0ZUVudHJ5AQkBFXVzZXJXZWlnaHRGYWN0b3JTdG9yZQIFB2FkZHJlc3MFB2Fzc2V0SWQJAMwIAgkBC0RlbGV0ZUVudHJ5AQkBD3VzZXJXZWlnaHRTdG9yZQIFB2FkZHJlc3MFB2Fzc2V0SWQJAMwIAgkBCGNoYW5nZUJ5AgkBHXRvdGFsV2VpZ2h0ZWRBc3NldExvY2tlZFN0b3JlAQUHYXNzZXRJZAUQdXNlcldlaWdodENoYW5nZQUDbmlsCQDOCAIFCnRva2Vuc0RhdGEJARB1cGRhdGVSZXdhcmREYXRhAwUHYWRkcmVzcwUHYXNzZXRJZAUQdXNlcldlaWdodENoYW5nZQkAAgECD25vdCBhbGxvd2VkIHlldAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpARBjbGFpbUxwUmV3YXJkRm9yAwR1c2VyB2Fzc2V0SWQGYW1vdW50BAlhZGRyQ2hlY2sJARFAZXh0ck5hdGl2ZSgxMDYyKQEFBHVzZXIDCQAAAgUJYWRkckNoZWNrBQlhZGRyQ2hlY2sDCQECIT0CBQZhbW91bnQA////////////AQkAAgECEmxwOiBjbGFpbSBhbGwgb25seQMJAQEhAQUHc3RhcnRlZAkAAgECC25vdCBzdGFydGVkBAZjaGVja3MDCQEIbWFpbk9ubHkBBQFpCQEJb3BBbGxvd2VkAgIOY2xhaW1fdmlyZXNfbHAFB2Fzc2V0SWQHAwkAAAIFBmNoZWNrcwUGY2hlY2tzBA0kdDAxNDUyNDE0NTg1CQERdXNlclJld2FyZEJhbGFuY2UCBQdhc3NldElkBQR1c2VyBAthY2N1bXVsYXRlZAgFDSR0MDE0NTI0MTQ1ODUCXzEEB2NsYWltZWQIBQ0kdDAxNDUyNDE0NTg1Al8yBAlhdmFpbGFibGUJAGUCBQthY2N1bXVsYXRlZAUHY2xhaW1lZAMJAGcCAAAFCWF2YWlsYWJsZQkAlAoCBQNuaWwAAAQEbWludAkA/AcEBQt2aXJlc01pbnRlcgIMbHBMb2NrZXJNaW50CQDMCAIJAKUIAQgFAWkGY2FsbGVyCQDMCAIFCWF2YWlsYWJsZQUDbmlsBQNuaWwDCQAAAgUEbWludAUEbWludAkAlAoCCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEQdXNlckNsYWltZWRTdG9yZQIFB2Fzc2V0SWQFBHVzZXIJAGQCBQdjbGFpbWVkBQlhdmFpbGFibGUFA25pbAUJYXZhaWxhYmxlCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBCHdpdGhkcmF3AwRmcm9tB2Fzc2V0SWQCdG8ECWFkZHJDaGVjawkBEUBleHRyTmF0aXZlKDEwNjIpAQUEZnJvbQMJAAACBQlhZGRyQ2hlY2sFCWFkZHJDaGVjawMJAQEhAQUHc3RhcnRlZAkAAgECC25vdCBzdGFydGVkBAZjaGVja3MDCQEIbWFpbk9ubHkBBQFpCQEJb3BBbGxvd2VkAgIUd2l0aGRyYXdfdW5sb2NrZWRfbHAFB2Fzc2V0SWQHAwkAAAIFBmNoZWNrcwUGY2hlY2tzAwkBAiE9AgkBEHVzZXJVbmxvY2tIZWlnaHQCBQRmcm9tBQdhc3NldElkAAAJAAIBAh9kaXN0cmlidXRpb24gbm90IGNsZWFuZWQgdXAgeWV0BANhbXQJAQp1c2VyQW1vdW50AgUEZnJvbQUHYXNzZXRJZAkAlAoCCQDMCAIJAQtEZWxldGVFbnRyeQEJAQ91c2VyQW1vdW50U3RvcmUCBQRmcm9tBQdhc3NldElkCQDMCAIJAQhjaGFuZ2VCeQIJARV0b3RhbEFzc2V0TG9ja2VkU3RvcmUBBQdhc3NldElkCQEBLQEFA2FtdAkAzAgCCQEOU2NyaXB0VHJhbnNmZXIDCQERQGV4dHJOYXRpdmUoMTA2MikBBQJ0bwUDYW10CQDZBAEFB2Fzc2V0SWQFA25pbAUDYW10CQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBD3dpdGhkcmF3U2xhc2hlZAMEZnJvbQdhc3NldElkAnRvBAlhZGRyQ2hlY2sJARFAZXh0ck5hdGl2ZSgxMDYyKQEFBGZyb20DCQAAAgUJYWRkckNoZWNrBQlhZGRyQ2hlY2sDCQEBIQEFB3N0YXJ0ZWQJAAIBAgtub3Qgc3RhcnRlZAQGY2hlY2tzAwkBCG1haW5Pbmx5AQUBaQkBCW9wQWxsb3dlZAICE3dpdGhkcmF3X3NsYXNoZWRfbHAFB2Fzc2V0SWQHAwkAAAIFBmNoZWNrcwUGY2hlY2tzAwkAZgIFBkhFSUdIVAkBEHVzZXJVbmxvY2tIZWlnaHQCBQRmcm9tBQdhc3NldElkCQACAQImYWxyZWFkeSB1bmxvY2tlZCwgdXNlIHJlZ3VsYXIgd2l0aGRyYXcECnNsYXNoUGFyYW0JARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAmggCBQ1jb25maWdBZGRyZXNzAhVlYXJseV91bmxvY2tfc2xhc2hpbmcCF3NsYXNoaW5nIG5vdCBjb25maWd1cmVkBANhbXQJAQp1c2VyQW1vdW50AgUEZnJvbQUHYXNzZXRJZAQQdXNlcldlaWdodENoYW5nZQkBAS0BCQEKdXNlcldlaWdodAIFBGZyb20FB2Fzc2V0SWQEAndkCQBrAwUDYW10CQBlAgULZmFjdG9yc0Jhc2UFCnNsYXNoUGFyYW0FC2ZhY3RvcnNCYXNlBAdzbGFzaGVkCQBlAgUDYW10BQJ3ZAQKdG9rZW5zRGF0YQkAzAgCCQELRGVsZXRlRW50cnkBCQEVdXNlclVubG9ja0hlaWdodFN0b3JlAgUEZnJvbQUHYXNzZXRJZAkAzAgCCQELRGVsZXRlRW50cnkBCQEVdXNlcldlaWdodEZhY3RvclN0b3JlAgUEZnJvbQUHYXNzZXRJZAkAzAgCCQELRGVsZXRlRW50cnkBCQEPdXNlcldlaWdodFN0b3JlAgUEZnJvbQUHYXNzZXRJZAkAzAgCCQELRGVsZXRlRW50cnkBCQEPdXNlckFtb3VudFN0b3JlAgUEZnJvbQUHYXNzZXRJZAkAzAgCCQEIY2hhbmdlQnkCCQEVdG90YWxBc3NldExvY2tlZFN0b3JlAQUHYXNzZXRJZAkBAS0BBQNhbXQJAMwIAgkBCGNoYW5nZUJ5AgkBHXRvdGFsV2VpZ2h0ZWRBc3NldExvY2tlZFN0b3JlAQUHYXNzZXRJZAUQdXNlcldlaWdodENoYW5nZQkAzAgCCQEOU2NyaXB0VHJhbnNmZXIDCQERQGV4dHJOYXRpdmUoMTA2MikBBQJ0bwUCd2QJANkEAQUHYXNzZXRJZAkAzAgCCQEOU2NyaXB0VHJhbnNmZXIDCAUBaQZjYWxsZXIFB3NsYXNoZWQJANkEAQUHYXNzZXRJZAUDbmlsCQCUCgIJAM4IAgUKdG9rZW5zRGF0YQkBEHVwZGF0ZVJld2FyZERhdGEDBQRmcm9tBQdhc3NldElkBRB1c2VyV2VpZ2h0Q2hhbmdlCQCUCgIFAndkBQdzbGFzaGVkCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAQJ0eAEGdmVyaWZ5AAQEQkFTRQDoBwQLcXVvcnVtUmF0aW8JARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAmggCBQ1jb25maWdBZGRyZXNzAhVwcm9wb3NhbF9xdW9ydW1fcmF0aW8CInByb3Bvc2FsUXVvcnVtUmF0aW8gaXMgbm90IGRlZmluZWQEC3Bhc3NlZFJhdGlvCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAJoIAgUNY29uZmlnQWRkcmVzcwIVcHJvcG9zYWxfcGFzc2VkX3JhdGlvAiVwcm9wb3NhbFRocmVzaG9sZFJhdGlvIGlzIG5vdCBkZWZpbmVkBA5nVmlyZXNDb250cmFjdAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCmCAEJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAnQgCBQ1jb25maWdBZGRyZXNzAhJkaXZpZGVuZHNfY29udHJhY3QCFW5vIGRpdmlkZW5kc19jb250cmFjdAIaaW52YWxpZCBkaXZpZGVuZHNfY29udHJhY3QEDnZvdGluZ0NvbnRyYWN0CQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKYIAQkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCdCAIFDWNvbmZpZ0FkZHJlc3MCD3ZvdGluZ19jb250cmFjdAISbm8gdm90aW5nX2NvbnRyYWN0AhdpbnZhbGlkIHZvdGluZ19jb250cmFjdAQCaWQJANgEAQgFAnR4AmlkBAh2b3Rlc1llcwkBC3ZhbHVlT3JFbHNlAgkAmggCBQ52b3RpbmdDb250cmFjdAkArAICAg1wcm9wb3NhbF95ZXNfBQJpZAAABAd2b3Rlc05vCQELdmFsdWVPckVsc2UCCQCaCAIFDnZvdGluZ0NvbnRyYWN0CQCsAgICDHByb3Bvc2FsX25vXwUCaWQAAAQOcHJvcG9zYWxIZWlnaHQJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAmggCBQ52b3RpbmdDb250cmFjdAkArAICAhBwcm9wb3NhbF9oZWlnaHRfBQJpZAIXcHJvcG9zYWwgbm90IHJlZ2lzdGVyZWQECmFwcGx5U3RhcnQJAQt2YWx1ZU9yRWxzZQIJAJoIAgUOdm90aW5nQ29udHJhY3QJAKwCAgIUcHJvcG9zYWxfYXBwbHlzdGFydF8FAmlkAAAECGFwcGx5RW5kCQELdmFsdWVPckVsc2UCCQCaCAIFDnZvdGluZ0NvbnRyYWN0CQCsAgICEnByb3Bvc2FsX2FwcGx5ZW5kXwUCaWQAAAQLdG90YWxHVmlyZXMJAQt2YWx1ZU9yRWxzZQIJAJoIAgUOdm90aW5nQ29udHJhY3QJAKwCAgIQcHJvcG9zYWxfZ3ZpcmVzXwUCaWQAAAQHZW5hYmxlZAkBC3ZhbHVlT3JFbHNlAgkAmwgCBQ1jb25maWdBZGRyZXNzAh1vcF9nb3Zlcm5hbmNlX2FwcGx5X3R4X3BhdXNlZAcEB3ZvdGVZZXMFCHZvdGVzWWVzBAZ2b3RlTm8FB3ZvdGVzTm8ECnRvdGFsVm90ZXMJAGQCBQd2b3RlWWVzBQZ2b3RlTm8ECWhhc1F1b3J1bQkAZwIJAGkCCQBoAgUKdG90YWxWb3RlcwUEQkFTRQULdG90YWxHVmlyZXMFC3F1b3J1bVJhdGlvBAloYXNQYXNzZWQJAGcCCQBpAgkAaAIFB3ZvdGVZZXMFBEJBU0UFCnRvdGFsVm90ZXMFC3Bhc3NlZFJhdGlvBAh0b29FYXJseQkAZwIFCmFwcGx5U3RhcnQFBkhFSUdIVAQHdG9vTGF0ZQkAZwIFBkhFSUdIVAUIYXBwbHlFbmQECXRpbWVEZWJ1ZwkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICAhFwcm9wb3NhbEhlaWdodCA9IAkApAMBBQ5wcm9wb3NhbEhlaWdodAIPLCBhcHBseVN0YXJ0ID0gCQCkAwEFCmFwcGx5U3RhcnQCDSwgYXBwbHlFbmQgPSAJAKQDAQUIYXBwbHlFbmQCCywgSEVJR0hUID0gCQCkAwEFBkhFSUdIVAQIYnlWb3RpbmcDCQEBIQEFB2VuYWJsZWQJAAIBAit0eCBhcHBsaWNhdGlvbiB0aHJvdyBnb3Zlcm5hbmNlIG5vdCBlbmFibGVkAwUIdG9vRWFybHkJAAIBCQCsAgICLnByb3Bvc2FsIGNhbid0IGJlIGV4ZWN1dGVkIGFzIGl0J3MgdG9vIGVhcmx5OiAFCXRpbWVEZWJ1ZwMFB3Rvb0xhdGUJAAIBCQCsAgICLHByb3Bvc2FsIGNhbid0IGJlIGV4ZWN1dGVkIGFzIGl0J3MgdG9vIGxhdGU6BQl0aW1lRGVidWcDCQEBIQEFCWhhc1F1b3J1bQkAAgEJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgICC25vIHF1b3J1bTogAgx0b3RhbFZvdGVzOiAJAKQDAQUKdG90YWxWb3RlcwIPLCB0b3RhbEdWaXJlczogCQCkAwEFC3RvdGFsR1ZpcmVzAg8sIHF1b3J1bVJhdGlvOiAJAKQDAQULcXVvcnVtUmF0aW8DCQEBIQEFCWhhc1Bhc3NlZAkAAgEJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgICF25vIHRocmVzaG9sZCBhY2hpZXZlZDogAgl2b3RlWWVzOiAJAKQDAQUHdm90ZVllcwIKLCB2b3RlTm86IAkApAMBBQZ2b3RlTm8CDywgcGFzc2VkUmF0aW86IAkApAMBBQtwYXNzZWRSYXRpbwYDCQD0AwMIBQJ0eAlib2R5Qnl0ZXMJAJEDAggFAnR4BnByb29mcwAACAUCdHgPc2VuZGVyUHVibGljS2V5BgUIYnlWb3RpbmfaD97Y", "chainId": 87, "height": 3486058, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: VUGgJvzy9wiikCnKDBvP9djXYZ7UCf2sCRbVE2NUtS9 Next: none Diff:
OldNewDifferences
523523 }
524524
525525
526+@Verifier(tx)
527+func verify () = {
528+ let BASE = 1000
529+ let quorumRatio = valueOrErrorMessage(getInteger(configAddress, "proposal_quorum_ratio"), "proposalQuorumRatio is not defined")
530+ let passedRatio = valueOrErrorMessage(getInteger(configAddress, "proposal_passed_ratio"), "proposalThresholdRatio is not defined")
531+ let gViresContract = valueOrErrorMessage(addressFromString(valueOrErrorMessage(getString(configAddress, "dividends_contract"), "no dividends_contract")), "invalid dividends_contract")
532+ let votingContract = valueOrErrorMessage(addressFromString(valueOrErrorMessage(getString(configAddress, "voting_contract"), "no voting_contract")), "invalid voting_contract")
533+ let id = toBase58String(tx.id)
534+ let votesYes = valueOrElse(getInteger(votingContract, ("proposal_yes_" + id)), 0)
535+ let votesNo = valueOrElse(getInteger(votingContract, ("proposal_no_" + id)), 0)
536+ let proposalHeight = valueOrErrorMessage(getInteger(votingContract, ("proposal_height_" + id)), "proposal not registered")
537+ let applyStart = valueOrElse(getInteger(votingContract, ("proposal_applystart_" + id)), 0)
538+ let applyEnd = valueOrElse(getInteger(votingContract, ("proposal_applyend_" + id)), 0)
539+ let totalGVires = valueOrElse(getInteger(votingContract, ("proposal_gvires_" + id)), 0)
540+ let enabled = valueOrElse(getBoolean(configAddress, "op_governance_apply_tx_paused"), false)
541+ let voteYes = votesYes
542+ let voteNo = votesNo
543+ let totalVotes = (voteYes + voteNo)
544+ let hasQuorum = (((totalVotes * BASE) / totalGVires) >= quorumRatio)
545+ let hasPassed = (((voteYes * BASE) / totalVotes) >= passedRatio)
546+ let tooEarly = (applyStart >= HEIGHT)
547+ let tooLate = (HEIGHT >= applyEnd)
548+ let timeDebug = ((((((("proposalHeight = " + toString(proposalHeight)) + ", applyStart = ") + toString(applyStart)) + ", applyEnd = ") + toString(applyEnd)) + ", HEIGHT = ") + toString(HEIGHT))
549+ let byVoting = if (!(enabled))
550+ then throw("tx application throw governance not enabled")
551+ else if (tooEarly)
552+ then throw(("proposal can't be executed as it's too early: " + timeDebug))
553+ else if (tooLate)
554+ then throw(("proposal can't be executed as it's too late:" + timeDebug))
555+ else if (!(hasQuorum))
556+ then throw((((((("no quorum: " + "totalVotes: ") + toString(totalVotes)) + ", totalGVires: ") + toString(totalGVires)) + ", quorumRatio: ") + toString(quorumRatio)))
557+ else if (!(hasPassed))
558+ then throw((((((("no threshold achieved: " + "voteYes: ") + toString(voteYes)) + ", voteNo: ") + toString(voteNo)) + ", passedRatio: ") + toString(passedRatio)))
559+ else true
560+ if (sigVerify(tx.bodyBytes, tx.proofs[0], tx.senderPublicKey))
561+ then true
562+ else byVoting
563+ }
564+
Full:
OldNewDifferences
11 {-# STDLIB_VERSION 6 #-}
22 {-# SCRIPT_TYPE ACCOUNT #-}
33 {-# CONTENT_TYPE DAPP #-}
44 func getI (key) = getInteger(this, key)
55
66
77 func getS (key) = getString(this, key)
88
99
1010 func getSV (key) = valueOrErrorMessage(getString(this, key), ((("no string value for key " + key) + " at address ") + toString(this)))
1111
1212
1313 func asInt2 (value) = match value {
1414 case x: (Int, Int) =>
1515 x
1616 case t =>
1717 throw("wrong type, expected: Int2")
1818 }
1919
2020
2121 func throwIf (condition,error) = if (condition)
2222 then throw(error)
2323 else true
2424
2525
2626 func writeInt (key,value) = if ((0 > value))
2727 then throw(((("writing negative value " + toString(value)) + " for key ") + key))
2828 else IntegerEntry(key, value)
2929
3030
3131 func asInt (value) = match value {
3232 case int: Int =>
3333 int
3434 case _ =>
3535 throw("lpl:1")
3636 }
3737
3838
3939 func changeBy (key,value) = writeInt(key, (valueOrElse(getI(key), 0) + value))
4040
4141
4242 func writeConstString (key,value) = if (!(isDefined(getString(this, key))))
4343 then StringEntry(key, value)
4444 else throw(("already initialized: " + key))
4545
4646
4747 let BlocksPerYear = 525600
4848
4949 let factorsBase = 1000
5050
5151 func fractionCeil (value,numerator,denominator) = {
5252 let cand = fraction(value, numerator, denominator)
5353 let D = 3037000499
5454 let exact = ((((cand % D) * (denominator % D)) % D) == (((value % D) * (numerator % D)) % D))
5555 if (exact)
5656 then cand
5757 else (cand + 1)
5858 }
5959
6060
6161 let configStore = "config"
6262
6363 let configAddress = valueOrErrorMessage(addressFromString(valueOrErrorMessage(getString(this, configStore), "reserve: no config")), "invalid config address")
6464
6565 let rewardReservesStr = valueOrErrorMessage(getString(configAddress, "rewardable_reserves"), "lp-locker: no rewardable_reserves in config")
6666
6767 let zeroRewardReservesStr = valueOrElse(getString(configAddress, "zero_rewardable_reserves"), "")
6868
6969 let rewardReserves = split_4C(rewardReservesStr, "|")
7070
7171 func opAllowed (op,lpAssetId) = match invoke(configAddress, "opAllowed", [lpAssetId, op], nil) {
7272 case b: Boolean =>
7373 if (b)
7474 then true
7575 else throw("not allowed")
7676 case _ =>
7777 throw("opAllowed: unexpected result type")
7878 }
7979
8080
8181 func userAmountStore (address,asset) = (((address + "_") + asset) + "_amt")
8282
8383
8484 func userUnlockHeightStore (address,asset) = (((address + "_") + asset) + "_unlockHeight")
8585
8686
8787 func userWeightFactorStore (address,asset) = (((address + "_") + asset) + "_weightFactor")
8888
8989
9090 func userWeightStore (address,asset) = (((address + "_") + asset) + "_weight")
9191
9292
9393 func totalAssetLockedStore (asset) = (asset + "_totalLocked")
9494
9595
9696 func totalWeightedAssetLockedStore (asset) = (asset + "_totalWeightedLocked")
9797
9898
9999 func userAmount (address,asset) = valueOrElse(getInteger(this, userAmountStore(address, asset)), 0)
100100
101101
102102 func userUnlockHeight (address,asset) = valueOrElse(getInteger(this, userUnlockHeightStore(address, asset)), 0)
103103
104104
105105 func userWeightFactor (address,asset) = valueOrElse(getInteger(this, userWeightFactorStore(address, asset)), 0)
106106
107107
108108 func userWeight (address,asset) = valueOrElse(getInteger(this, userWeightStore(address, asset)), 0)
109109
110110
111111 func totalAssetLocked (asset) = valueOrElse(getInteger(this, totalAssetLockedStore(asset)), 0)
112112
113113
114114 func totalWeightedAssetLocked (asset) = valueOrElse(getInteger(this, totalWeightedAssetLockedStore(asset)), 0)
115115
116116
117117 let maybeOracleAddress = match getString(configAddress, "oracle_address") {
118118 case s: String =>
119119 addressFromString(s)
120120 case _ =>
121121 unit
122122 }
123123
124124 func oraclePrice (assetId) = match invoke(valueOrErrorMessage(maybeOracleAddress, "no oracle"), "price", [assetId], nil) {
125125 case i: Int =>
126126 i
127127 case _ =>
128128 throw("bad oracle data")
129129 }
130130
131131
132132 let HEIGHT = height
133133
134134 func mainOnly (i) = if (contains(getStringValue(configAddress, "main"), toString(i.caller)))
135135 then true
136136 else throw("only main can do")
137137
138138
139139 let startedKey = "started"
140140
141141 func syncHeightStore (assetId) = (assetId + "_syncedHeight")
142142
143143
144144 func speedStore (assetId) = (assetId + "_speed")
145145
146146
147147 func rewardStore (assetId) = (assetId + "_reward")
148148
149149
150150 func userClaimedStore (assetId,user) = ((user + "_claimed_") + assetId)
151151
152152
153153 func userRewardAdjStore (assetId,user) = ((user + "_userRewardAdj_") + assetId)
154154
155155
156156 func syncHeight (asset) = valueOrElse(getInteger(this, syncHeightStore(asset)), 0)
157157
158158
159159 func pow10 (n) = if ((n == 6))
160160 then 1000000
161161 else if ((n == 8))
162162 then 100000000
163163 else throw(("bad decimals: " + toString(n)))
164164
165165
166166 let viresMinter = valueOrErrorMessage(addressFromString(valueOrErrorMessage(getString(configAddress, "vires_minter"), "vires-distributor: no viresMinter")), "invalid viresMinter")
167167
168168 let viresIdStr = valueOrErrorMessage(getString(viresMinter, "assetId"), "vires-distributor: no viresAssetIdStore")
169169
170170 let viresAssetId = fromBase58String(viresIdStr)
171171
172172 let started = isDefined(getInteger(this, startedKey))
173173
174174 func currentReward (assetId) = {
175175 let h = syncHeight(assetId)
176176 let storedReward = valueOrElse(getInteger(this, rewardStore(assetId)), 0)
177177 if ((h == HEIGHT))
178178 then storedReward
179179 else {
180180 let speed = valueOrElse(getInteger(this, speedStore(assetId)), 0)
181181 let accumulatedReward = ((HEIGHT - h) * speed)
182182 (storedReward + accumulatedReward)
183183 }
184184 }
185185
186186
187187 func currentRewardsSpeed () = {
188188 func fold2 (l,reserve) = {
189189 let assetId = valueOrErrorMessage(getString(addressFromStringValue(reserve), "aTokenId"), "no aTokenId")
190190 ((((l + assetId) + "=") + toString(valueOrElse(getInteger(this, speedStore(assetId)), 0))) + ", ")
191191 }
192192
193193 let $l = rewardReserves
194194 let $s = size($l)
195195 let $acc0 = ""
196196 func $f0_1 ($a,$i) = if (($i >= $s))
197197 then $a
198198 else fold2($a, $l[$i])
199199
200200 func $f0_2 ($a,$i) = if (($i >= $s))
201201 then $a
202202 else throw("List size exceeds 20")
203203
204204 $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($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), 11), 12), 13), 14), 15), 16), 17), 18), 19), 20)
205205 }
206206
207207
208208 func userRewardBalance (assetId,user) = {
209209 let curTotalWeighted = totalWeightedAssetLocked(assetId)
210210 let userWeighted = fraction(userAmount(user, assetId), userWeightFactor(user, assetId), factorsBase)
211211 let totalReward = currentReward(assetId)
212212 let userAdj = valueOrElse(getInteger(this, userRewardAdjStore(assetId, user)), 0)
213213 let acc = (userAdj + (if ((curTotalWeighted == 0))
214214 then 0
215215 else fraction(totalReward, userWeighted, curTotalWeighted)))
216216 let claimed = valueOrElse(getInteger(this, userClaimedStore(assetId, user)), 0)
217217 $Tuple2(acc, claimed)
218218 }
219219
220220
221221 func updateRewardData (address,assetId,userChange) = {
222222 let prevTotal = totalWeightedAssetLocked(assetId)
223223 let prevReward = currentReward(assetId)
224224 let prevUserAdj = valueOrElse(getInteger(this, userRewardAdjStore(assetId, address)), 0)
225225 let newTotal = (prevTotal + userChange)
226226 let newReserveReward = if ((prevTotal == 0))
227227 then prevReward
228228 else fraction(prevReward, newTotal, prevTotal)
229229 let newUserRewardAdj = if ((newTotal == 0))
230230 then (prevUserAdj + prevReward)
231231 else (prevUserAdj - fraction(newReserveReward, userChange, newTotal))
232232 [IntegerEntry(rewardStore(assetId), newReserveReward), IntegerEntry(userRewardAdjStore(assetId, address), newUserRewardAdj), IntegerEntry(syncHeightStore(assetId), HEIGHT)]
233233 }
234234
235235
236236 func borrowedValueByIndexAndTotalBorrow () = {
237237 func fold (acc,a) = {
238238 let address = valueOrErrorMessage(addressFromString(a), ("bad address " + a))
239239 let assetDebtUsd = if (contains(zeroRewardReservesStr, a))
240240 then 0
241241 else {
242242 let assetId = valueOrErrorMessage(getString(address, "assetId"), ("assetId not found in reserve " + a))
243243 let assetDecimals = if ((assetId == "WAVES"))
244244 then 8
245245 else valueOrErrorMessage(getInteger(address, "aTokenDecimals"), ("aTokenDecimals not found in reserve " + a))
246246 let assetDebt = asInt2(invoke(address, "storedDepositBorrow", nil, nil))._2
247247 fraction(assetDebt, oraclePrice(assetId), pow10(assetDecimals))
248248 }
249249 let $t078397858 = acc
250250 let lst = $t078397858._1
251251 let agg = $t078397858._2
252252 $Tuple2((lst ++ [assetDebtUsd]), (agg + assetDebtUsd))
253253 }
254254
255255 let $l = rewardReserves
256256 let $s = size($l)
257257 let $acc0 = $Tuple2(nil, 0)
258258 func $f0_1 ($a,$i) = if (($i >= $s))
259259 then $a
260260 else fold($a, $l[$i])
261261
262262 func $f0_2 ($a,$i) = if (($i >= $s))
263263 then $a
264264 else throw("List size exceeds 20")
265265
266266 $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($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), 11), 12), 13), 14), 15), 16), 17), 18), 19), 20)
267267 }
268268
269269
270270 @Callable(i)
271271 func adviseUser (user,assetId) = {
272272 let curTotalWeighted = totalWeightedAssetLocked(assetId)
273273 let userFactor = userWeightFactor(user, assetId)
274274 let userAmt = userAmount(user, assetId)
275275 let userWeighted = fraction(userAmt, userFactor, factorsBase)
276276 let unlockHeight = userUnlockHeight(user, assetId)
277277 let totalReward = currentReward(assetId)
278278 let userAdj = valueOrElse(getInteger(this, userRewardAdjStore(assetId, user)), 0)
279279 let pie = if ((curTotalWeighted == 0))
280280 then 0
281281 else fraction(totalReward, userWeighted, curTotalWeighted)
282282 let acc = (userAdj + pie)
283283 let claimed = valueOrElse(getInteger(this, userClaimedStore(assetId, user)), 0)
284284 let totalRewardsAccumulated = max([0, acc])
285285 let rewardsAvailable = max([0, (totalRewardsAccumulated - claimed)])
286286 $Tuple2(nil, ((((((((((((((((("lp_rewardsAccumulated: " + toString(totalRewardsAccumulated)) + ", lp_rewardsAvailable: ") + toString(rewardsAvailable)) + ", lp_rewardsClaimed: ") + toString(claimed)) + ", lp_userAdj: ") + toString(userAdj)) + ", lp_pie: ") + toString(pie)) + ", lp_locked: ") + toString(userAmt)) + ", lp_userFactor: ") + toString(userFactor)) + ", lp_unlockHeight: ") + toString(unlockHeight)) + ", lp_weight: ") + toString(userWeighted)))
287287 }
288288
289289
290290
291291 @Callable(i)
292292 func initialize (ca) = [writeConstString(configStore, ca)]
293293
294294
295295
296296 @Callable(i)
297297 func start () = if ((i.caller != this))
298298 then throw("only self can do")
299299 else if (started)
300300 then throw("already started")
301301 else {
302302 func fold (l,reserve) = {
303303 let assetId = valueOrErrorMessage(getString(addressFromStringValue(reserve), "aTokenId"), "lock-distr: no aTokenId")
304304 (l ++ [IntegerEntry(speedStore(assetId), 0), IntegerEntry(rewardStore(assetId), 0), IntegerEntry(syncHeightStore(assetId), HEIGHT)])
305305 }
306306
307307 let $l = rewardReserves
308308 let $s = size($l)
309309 let $acc0 = [IntegerEntry(startedKey, HEIGHT)]
310310 func $f0_1 ($a,$i) = if (($i >= $s))
311311 then $a
312312 else fold($a, $l[$i])
313313
314314 func $f0_2 ($a,$i) = if (($i >= $s))
315315 then $a
316316 else throw("List size exceeds 20")
317317
318318 $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($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), 11), 12), 13), 14), 15), 16), 17), 18), 19), 20)
319319 }
320320
321321
322322
323323 @Callable(i)
324324 func realloc () = if (!(started))
325325 then throw("not started")
326326 else if (!(opAllowed("lp_lock_realloc", viresIdStr)))
327327 then throw("realloc paused")
328328 else {
329329 let totalSpeed = valueOrErrorMessage(getInteger(configAddress, "lp_lock_total_speed"), "no total allocation speed")
330330 let totalReserves = size(rewardReserves)
331331 let $t01034510422 = borrowedValueByIndexAndTotalBorrow()
332332 let borrowedValueByIndex = $t01034510422._1
333333 let totalBorrow = $t01034510422._2
334334 func fold (l,index) = if ((index >= totalReserves))
335335 then l
336336 else {
337337 let reserve = rewardReserves[index]
338338 let assetId = valueOrErrorMessage(getString(addressFromStringValue(reserve), "aTokenId"), "bad reserve in realloc")
339339 let assetSpeed = if ((totalBorrow == 0))
340340 then 0
341341 else fraction(totalSpeed, borrowedValueByIndex[index], totalBorrow)
342342 let cr = currentReward(assetId)
343343 (l ++ [IntegerEntry(speedStore(assetId), assetSpeed), IntegerEntry(rewardStore(assetId), cr), IntegerEntry(syncHeightStore(assetId), HEIGHT)])
344344 }
345345
346346 let $l = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
347347 let $s = size($l)
348348 let $acc0 = nil
349349 func $f0_1 ($a,$i) = if (($i >= $s))
350350 then $a
351351 else fold($a, $l[$i])
352352
353353 func $f0_2 ($a,$i) = if (($i >= $s))
354354 then $a
355355 else throw("List size exceeds 20")
356356
357357 $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($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), 11), 12), 13), 14), 15), 16), 17), 18), 19), 20)
358358 }
359359
360360
361361
362362 @Callable(i)
363363 func lockLP (address,durationBlocks) = {
364364 let addrCheck = addressFromStringValue(address)
365365 if ((addrCheck == addrCheck))
366366 then if (!(started))
367367 then throw("not started")
368368 else if ((size(i.payments) == 0))
369369 then $Tuple2(nil, 0)
370370 else {
371371 let assetId = toBase58String(value(i.payments[0].assetId))
372372 let checks = if (mainOnly(i))
373373 then opAllowed("lock_lp", assetId)
374374 else false
375375 if ((checks == checks))
376376 then {
377377 let amt = i.payments[0].amount
378378 let minAmount = valueOrErrorMessage(getInteger(configAddress, ("lock_min_amount_" + assetId)), ("no min_amount for" + assetId))
379379 let prevAssets = userAmount(address, assetId)
380380 if ((minAmount > (prevAssets + amt)))
381381 then throw(((("locking less than min " + toString(minAmount)) + " of ") + assetId))
382382 else {
383383 let prevWeightFactor = userWeightFactor(address, assetId)
384384 let prevUserWeight = userWeight(address, assetId)
385385 let prevUnlockHeight = userUnlockHeight(address, assetId)
386386 let weightFactor = valueOrErrorMessage(getInteger(configAddress, ("lock_weight_factor_" + toString(durationBlocks))), ("no weightFactor for durationBlocks " + toString(durationBlocks)))
387387 if (if ((prevWeightFactor > weightFactor))
388388 then (prevUnlockHeight > HEIGHT)
389389 else false)
390390 then throw("can't decrease weightFactor if not unlocked yet")
391391 else {
392392 let newUserWeight = fraction((prevAssets + amt), weightFactor, factorsBase)
393393 let userWeightChange = (newUserWeight - prevUserWeight)
394394 let tokensData = [changeBy(userAmountStore(address, assetId), amt), IntegerEntry(userUnlockHeightStore(address, assetId), (HEIGHT + durationBlocks)), IntegerEntry(userWeightFactorStore(address, assetId), weightFactor), IntegerEntry(userWeightStore(address, assetId), newUserWeight), changeBy(totalAssetLockedStore(assetId), amt), changeBy(totalWeightedAssetLockedStore(assetId), userWeightChange)]
395395 (tokensData ++ updateRewardData(address, assetId, userWeightChange))
396396 }
397397 }
398398 }
399399 else throw("Strict value is not equal to itself.")
400400 }
401401 else throw("Strict value is not equal to itself.")
402402 }
403403
404404
405405
406406 @Callable(i)
407407 func cleanUpDistributionFor (address,assetId) = {
408408 let addrCheck = addressFromStringValue(address)
409409 if ((addrCheck == addrCheck))
410410 then if (!(started))
411411 then throw("not started")
412412 else {
413413 let checks = opAllowed("stop_distribution_unlocked_lp", assetId)
414414 if ((checks == checks))
415415 then {
416416 let unlockHeight = userUnlockHeight(address, assetId)
417417 if ((unlockHeight == 0))
418418 then nil
419419 else {
420420 let userAmountChange = -(userAmount(address, assetId))
421421 let userWeightChange = -(userWeight(address, assetId))
422422 let exceptionEarlyUnlock = contains(valueOrElse(getString(configAddress, "lp_unlock_free_atoken_ids"), ""), assetId)
423423 if (if ((HEIGHT >= unlockHeight))
424424 then true
425425 else exceptionEarlyUnlock)
426426 then {
427427 let tokensData = [DeleteEntry(userUnlockHeightStore(address, assetId)), DeleteEntry(userWeightFactorStore(address, assetId)), DeleteEntry(userWeightStore(address, assetId)), changeBy(totalWeightedAssetLockedStore(assetId), userWeightChange)]
428428 (tokensData ++ updateRewardData(address, assetId, userWeightChange))
429429 }
430430 else throw("not allowed yet")
431431 }
432432 }
433433 else throw("Strict value is not equal to itself.")
434434 }
435435 else throw("Strict value is not equal to itself.")
436436 }
437437
438438
439439
440440 @Callable(i)
441441 func claimLpRewardFor (user,assetId,amount) = {
442442 let addrCheck = addressFromStringValue(user)
443443 if ((addrCheck == addrCheck))
444444 then if ((amount != -1))
445445 then throw("lp: claim all only")
446446 else if (!(started))
447447 then throw("not started")
448448 else {
449449 let checks = if (mainOnly(i))
450450 then opAllowed("claim_vires_lp", assetId)
451451 else false
452452 if ((checks == checks))
453453 then {
454454 let $t01452414585 = userRewardBalance(assetId, user)
455455 let accumulated = $t01452414585._1
456456 let claimed = $t01452414585._2
457457 let available = (accumulated - claimed)
458458 if ((0 >= available))
459459 then $Tuple2(nil, 0)
460460 else {
461461 let mint = invoke(viresMinter, "lpLockerMint", [toString(i.caller), available], nil)
462462 if ((mint == mint))
463463 then $Tuple2([IntegerEntry(userClaimedStore(assetId, user), (claimed + available))], available)
464464 else throw("Strict value is not equal to itself.")
465465 }
466466 }
467467 else throw("Strict value is not equal to itself.")
468468 }
469469 else throw("Strict value is not equal to itself.")
470470 }
471471
472472
473473
474474 @Callable(i)
475475 func withdraw (from,assetId,to) = {
476476 let addrCheck = addressFromStringValue(from)
477477 if ((addrCheck == addrCheck))
478478 then if (!(started))
479479 then throw("not started")
480480 else {
481481 let checks = if (mainOnly(i))
482482 then opAllowed("withdraw_unlocked_lp", assetId)
483483 else false
484484 if ((checks == checks))
485485 then if ((userUnlockHeight(from, assetId) != 0))
486486 then throw("distribution not cleaned up yet")
487487 else {
488488 let amt = userAmount(from, assetId)
489489 $Tuple2([DeleteEntry(userAmountStore(from, assetId)), changeBy(totalAssetLockedStore(assetId), -(amt)), ScriptTransfer(addressFromStringValue(to), amt, fromBase58String(assetId))], amt)
490490 }
491491 else throw("Strict value is not equal to itself.")
492492 }
493493 else throw("Strict value is not equal to itself.")
494494 }
495495
496496
497497
498498 @Callable(i)
499499 func withdrawSlashed (from,assetId,to) = {
500500 let addrCheck = addressFromStringValue(from)
501501 if ((addrCheck == addrCheck))
502502 then if (!(started))
503503 then throw("not started")
504504 else {
505505 let checks = if (mainOnly(i))
506506 then opAllowed("withdraw_slashed_lp", assetId)
507507 else false
508508 if ((checks == checks))
509509 then if ((HEIGHT > userUnlockHeight(from, assetId)))
510510 then throw("already unlocked, use regular withdraw")
511511 else {
512512 let slashParam = valueOrErrorMessage(getInteger(configAddress, "early_unlock_slashing"), "slashing not configured")
513513 let amt = userAmount(from, assetId)
514514 let userWeightChange = -(userWeight(from, assetId))
515515 let wd = fraction(amt, (factorsBase - slashParam), factorsBase)
516516 let slashed = (amt - wd)
517517 let tokensData = [DeleteEntry(userUnlockHeightStore(from, assetId)), DeleteEntry(userWeightFactorStore(from, assetId)), DeleteEntry(userWeightStore(from, assetId)), DeleteEntry(userAmountStore(from, assetId)), changeBy(totalAssetLockedStore(assetId), -(amt)), changeBy(totalWeightedAssetLockedStore(assetId), userWeightChange), ScriptTransfer(addressFromStringValue(to), wd, fromBase58String(assetId)), ScriptTransfer(i.caller, slashed, fromBase58String(assetId))]
518518 $Tuple2((tokensData ++ updateRewardData(from, assetId, userWeightChange)), $Tuple2(wd, slashed))
519519 }
520520 else throw("Strict value is not equal to itself.")
521521 }
522522 else throw("Strict value is not equal to itself.")
523523 }
524524
525525
526+@Verifier(tx)
527+func verify () = {
528+ let BASE = 1000
529+ let quorumRatio = valueOrErrorMessage(getInteger(configAddress, "proposal_quorum_ratio"), "proposalQuorumRatio is not defined")
530+ let passedRatio = valueOrErrorMessage(getInteger(configAddress, "proposal_passed_ratio"), "proposalThresholdRatio is not defined")
531+ let gViresContract = valueOrErrorMessage(addressFromString(valueOrErrorMessage(getString(configAddress, "dividends_contract"), "no dividends_contract")), "invalid dividends_contract")
532+ let votingContract = valueOrErrorMessage(addressFromString(valueOrErrorMessage(getString(configAddress, "voting_contract"), "no voting_contract")), "invalid voting_contract")
533+ let id = toBase58String(tx.id)
534+ let votesYes = valueOrElse(getInteger(votingContract, ("proposal_yes_" + id)), 0)
535+ let votesNo = valueOrElse(getInteger(votingContract, ("proposal_no_" + id)), 0)
536+ let proposalHeight = valueOrErrorMessage(getInteger(votingContract, ("proposal_height_" + id)), "proposal not registered")
537+ let applyStart = valueOrElse(getInteger(votingContract, ("proposal_applystart_" + id)), 0)
538+ let applyEnd = valueOrElse(getInteger(votingContract, ("proposal_applyend_" + id)), 0)
539+ let totalGVires = valueOrElse(getInteger(votingContract, ("proposal_gvires_" + id)), 0)
540+ let enabled = valueOrElse(getBoolean(configAddress, "op_governance_apply_tx_paused"), false)
541+ let voteYes = votesYes
542+ let voteNo = votesNo
543+ let totalVotes = (voteYes + voteNo)
544+ let hasQuorum = (((totalVotes * BASE) / totalGVires) >= quorumRatio)
545+ let hasPassed = (((voteYes * BASE) / totalVotes) >= passedRatio)
546+ let tooEarly = (applyStart >= HEIGHT)
547+ let tooLate = (HEIGHT >= applyEnd)
548+ let timeDebug = ((((((("proposalHeight = " + toString(proposalHeight)) + ", applyStart = ") + toString(applyStart)) + ", applyEnd = ") + toString(applyEnd)) + ", HEIGHT = ") + toString(HEIGHT))
549+ let byVoting = if (!(enabled))
550+ then throw("tx application throw governance not enabled")
551+ else if (tooEarly)
552+ then throw(("proposal can't be executed as it's too early: " + timeDebug))
553+ else if (tooLate)
554+ then throw(("proposal can't be executed as it's too late:" + timeDebug))
555+ else if (!(hasQuorum))
556+ then throw((((((("no quorum: " + "totalVotes: ") + toString(totalVotes)) + ", totalGVires: ") + toString(totalGVires)) + ", quorumRatio: ") + toString(quorumRatio)))
557+ else if (!(hasPassed))
558+ then throw((((((("no threshold achieved: " + "voteYes: ") + toString(voteYes)) + ", voteNo: ") + toString(voteNo)) + ", passedRatio: ") + toString(passedRatio)))
559+ else true
560+ if (sigVerify(tx.bodyBytes, tx.proofs[0], tx.senderPublicKey))
561+ then true
562+ else byVoting
563+ }
564+

github/deemru/w8io/786bc32 
57.55 ms