2022.08.26 13:52 [3266819] smart account 3PGCkrHBxFMi7tz1xqnxgBpeNvn5E4M4g8S > SELF 0.00000000 Waves

{ "type": 13, "id": "CwXCnZktP1z872FPSLhvN2YNM3eQnf9W7KkW8UFtY67r", "fee": 2400000, "feeAssetId": null, "timestamp": 1661511102574, "version": 1, "sender": "3PGCkrHBxFMi7tz1xqnxgBpeNvn5E4M4g8S", "senderPublicKey": "CRRN9T4LWdYfw63q5x9XxR8P93XshdCac31Z65PbE6zv", "proofs": [ "5gFuXgYYbjY3fNCekiGgd9TF1yxmEVzfBW1XDqv3cURihUHSn8AbBHJHAAi86ZETS9WktjTbM4UfDcijRPuYznwV" ], "script": "base64:BgKqAQgCEgASABIDCgEIEgQKAggIEgASAwoBCBIAEgASAwoBARIAEgcKBQgICAgBEgASAwoBCBIDCgEIEgMKAQgSAwoBCBIDCgEBEgMKAQgSBAoCCAQSBAoCCAESBAoCCAESAwoBCBIDCgEIEgMKAQgSBAoCCAESBAoCCAESBQoDCAEIEgMKAQgSBQoDCAgBEgUKAwgIARIDCgEIEgASAwoBCBIECgIIARIDCgEBXgEEZ2V0SQEDa2V5CQCaCAIFBHRoaXMFA2tleQEEZ2V0UwEDa2V5CQCdCAIFBHRoaXMFA2tleQEFZ2V0U1YBA2tleQkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCdCAIFBHRoaXMFA2tleQkArAICCQCsAgIJAKwCAgIYbm8gc3RyaW5nIHZhbHVlIGZvciBrZXkgBQNrZXkCDCBhdCBhZGRyZXNzIAkApQgBBQR0aGlzAQd0aHJvd0lmAgljb25kaXRpb24FZXJyb3IDBQljb25kaXRpb24JAAIBBQVlcnJvcgYBCHdyaXRlSW50AgNrZXkFdmFsdWUDCQBmAgAABQV2YWx1ZQkAAgEJAKwCAgkArAICCQCsAgICF3dyaXRpbmcgbmVnYXRpdmUgdmFsdWUgCQCkAwEFBXZhbHVlAgkgZm9yIGtleSAFA2tleQkBDEludGVnZXJFbnRyeQIFA2tleQUFdmFsdWUBCWVuc3VyZUdFMAEFdmFsdWUDCQBmAgAABQV2YWx1ZQkAAgECFndyaXRpbmcgbmVnYXRpdmUgdmFsdWUFBXZhbHVlAQVhc0ludAEFdmFsdWUEByRtYXRjaDAFBXZhbHVlAwkAAQIFByRtYXRjaDACA0ludAQDaW50BQckbWF0Y2gwBQNpbnQJAAIBAgNyOjEBCGNoYW5nZUJ5AgNrZXkFdmFsdWUJAQh3cml0ZUludAIFA2tleQkAZAIJAQt2YWx1ZU9yRWxzZQIJAQRnZXRJAQUDa2V5AAAFBXZhbHVlAQt3cml0ZVN0cmluZwIDa2V5BXZhbHVlCQELU3RyaW5nRW50cnkCBQNrZXkFBXZhbHVlAQxmcmFjdGlvbkNlaWwDBXZhbHVlCW51bWVyYXRvcgtkZW5vbWluYXRvcgQEY2FuZAkAawMFBXZhbHVlBQludW1lcmF0b3IFC2Rlbm9taW5hdG9yBAFEALPmk6gLBAVleGFjdAkAAAIJAGoCCQBoAgkAagIFBGNhbmQFAUQJAGoCBQtkZW5vbWluYXRvcgUBRAUBRAkAagIJAGgCCQBqAgUFdmFsdWUFAUQJAGoCBQludW1lcmF0b3IFAUQFAUQDBQVleGFjdAUEY2FuZAkAZAIFBGNhbmQAAQANQmxvY2tzUGVyWWVhcgCgiiAABVJCYXNlAICAhP6m3uERAAtmYWN0b3JzQmFzZQDoBwAMYXNzZXRJZFN0b3JlAgdhc3NldElkAAphc3NldElkU3RyCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAQRnZXRTAQUMYXNzZXRJZFN0b3JlAgpubyBhc3NldElkAAdhc3NldElkAwkAAAIFCmFzc2V0SWRTdHICBVdBVkVTBQR1bml0CQDZBAEFCmFzc2V0SWRTdHIAEnJlc2VydmVGYWN0b3JTdG9yZQkArAICBQphc3NldElkU3RyAg5fUmVzZXJ2ZUZhY3RvcgAVY29sbGF0ZXJhbEZhY3RvclN0b3JlCQCsAgIFCmFzc2V0SWRTdHICEV9Db2xsYXRlcmFsRmFjdG9yABlsaXF1aWRhdGlvblRocmVzaG9sZFN0b3JlCQCsAgIFCmFzc2V0SWRTdHICFV9MaXF1aWRhdGlvblRocmVzaG9sZAASb3ZlcmxhcENoYXJnZVN0b3JlAhZhY2NvdW50X2hlYWx0aF9vdmVybGFwABdsaXF1aWRhdGlvblBlbmFsdHlTdG9yZQkArAICBQphc3NldElkU3RyAhNfTGlxdWlkYXRpb25QZW5hbHR5ABJjb25maWdBZGRyZXNzU3RvcmUCDWNvbmZpZ0FkZHJlc3MADWFUb2tlbklkU3RvcmUCCGFUb2tlbklkAA9hVG9rZW5OYW1lU3RvcmUCCmFUb2tlbk5hbWUAFmFUb2tlbkNpcmN1bGF0aW9uU3RvcmUCEWFUb2tlbkNpcmN1bGF0aW9uABNhVG9rZW5EZWNpbWFsc1N0b3JlAg5hVG9rZW5EZWNpbWFscwAScmVzZXJ2ZUdsb2JhbFN0b3JlAhFyZXNlcnZlR2xvYmFsRGF0YQANcmVzZXJ2ZUdsb2JhbAkBC3ZhbHVlT3JFbHNlAgkAoggBBRJyZXNlcnZlR2xvYmFsU3RvcmUCBHx8fHwAEXJlc2VydmVHbG9iYWxEYXRhCQC1CQIFDXJlc2VydmVHbG9iYWwCAXwAEGxhc3RVcGRhdGVIZWlnaHQJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkBC3ZhbHVlT3JFbHNlAgkAtgkBCQCRAwIFEXJlc2VydmVHbG9iYWxEYXRhAAAJAQRnZXRJAQIQbGFzdFVwZGF0ZUhlaWdodAITbm8gbGFzdFVwZGF0ZUhlaWdodAASc3RvcmVkVG90YWxEZXBvc2l0CQELdmFsdWVPckVsc2UCCQC2CQEJAJEDAgURcmVzZXJ2ZUdsb2JhbERhdGEAAQkBC3ZhbHVlT3JFbHNlAgkBBGdldEkBAgx0b3RhbERlcG9zaXQAAAAPc3RvcmVkVG90YWxEZWJ0CQELdmFsdWVPckVsc2UCCQC2CQEJAJEDAgURcmVzZXJ2ZUdsb2JhbERhdGEAAgkBC3ZhbHVlT3JFbHNlAgkBBGdldEkBAgt0b3RhbEJvcnJvdwAAABJzdG9yZWRUb3RhbFJlc2VydmUJAQt2YWx1ZU9yRWxzZQIJALYJAQkAkQMCBRFyZXNlcnZlR2xvYmFsRGF0YQADCQELdmFsdWVPckVsc2UCCQEEZ2V0SQECDHRvdGFsUmVzZXJ2ZQAAAAtzdG9yZWRJbmRleAkBC3ZhbHVlT3JFbHNlAgkAtgkBCQCRAwIFEXJlc2VydmVHbG9iYWxEYXRhAAQJAQt2YWx1ZU9yRWxzZQIJAQRnZXRJAQILc3RvcmVkSW5kZXgFBVJCYXNlARJhVG9rZW5CYWxhbmNlU3RvcmUBC3VzZXJBZGRyZXNzCQCsAgIFC3VzZXJBZGRyZXNzAg5fYVRva2VuQmFsYW5jZQEJZGVidFN0b3JlAQt1c2VyQWRkcmVzcwkArAICBQt1c2VyQWRkcmVzcwIFX2RlYnQBDmRlYnRJbmRleFN0b3JlAQt1c2VyQWRkcmVzcwkArAICBQt1c2VyQWRkcmVzcwIGX2luZGV4ARR1c2VBc0NvbGxhdGVyYWxTdG9yZQELdXNlckFkZHJlc3MJAKwCAgULdXNlckFkZHJlc3MCEF91c2VBc0NvbGxhdGVyYWwBCmdldEJhbGFuY2UCDmFkZHJlc3NPckFsaWFzB2Fzc2V0SWQEByRtYXRjaDAFB2Fzc2V0SWQDCQABAgUHJG1hdGNoMAIKQnl0ZVZlY3RvcgQCYnYFByRtYXRjaDAJAPAHAgUOYWRkcmVzc09yQWxpYXMFAmJ2AwkAAQIFByRtYXRjaDACBFVuaXQEAXUFByRtYXRjaDAICQDvBwEFDmFkZHJlc3NPckFsaWFzCWF2YWlsYWJsZQkAAgECC01hdGNoIGVycm9yAA1hc3NldERlY2ltYWxzCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAQRnZXRJAQUTYVRva2VuRGVjaW1hbHNTdG9yZQIQbm8gYXNzZXREZWNpbWFscwANY29uZmlnQWRkcmVzcwkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCmCAEJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAnQgCBQR0aGlzBRJjb25maWdBZGRyZXNzU3RvcmUCGXJlc2VydmU6IG5vIGNvbmZpZ0FkZHJlc3MCFmludmFsaWQgY29uZmlnIGFkZHJlc3MBCW9wQWxsb3dlZAECb3AEByRtYXRjaDAJAPwHBAUNY29uZmlnQWRkcmVzcwIJb3BBbGxvd2VkCQDMCAIFCmFzc2V0SWRTdHIJAMwIAgUCb3AFA25pbAUDbmlsAwkAAQIFByRtYXRjaDACB0Jvb2xlYW4EAWIFByRtYXRjaDADBQFiBgkAAgECC25vdCBhbGxvd2VkCQACAQIhb3BBbGxvd2VkOiB1bmV4cGVjdGVkIHJlc3VsdCB0eXBlAAxtYWluQ29udHJhY3QJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkApggBCQCRAwIJALUJAgkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCdCAIFDWNvbmZpZ0FkZHJlc3MCBG1haW4CEW5vIG1haW4gaW4gY29uZmlnAgF8AAACFGludmFsaWQgbWFpbiBhZGRyZXNzAQhtYWluT25seQEBaQMJAQhjb250YWlucwIJARFAZXh0ck5hdGl2ZSgxMDUzKQIFDWNvbmZpZ0FkZHJlc3MCBG1haW4JAKUIAQgFAWkGY2FsbGVyBgkAAgECEG9ubHkgbWFpbiBjYW4gZG8BDGRpdkFkbWluT25seQEBaQQJZGl2QWRtaW5zCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAJ0IAgUNY29uZmlnQWRkcmVzcwIJZGl2QWRtaW5zAg1ubyBkaXYgYWRtaW5zAwkBASEBCQEIY29udGFpbnMCBQlkaXZBZG1pbnMJAKUIAQgFAWkGY2FsbGVyCQACAQIVb25seSBkaXYgYWRtaW4gY2FuIGRvBgEQaXNBc3NldElkT3JXYXZlcwEFdmFsdWUDAwkBAiE9AgUFdmFsdWUCBVdBVkVTCQAAAgkA2QQBBQV2YWx1ZQkA2QQBAgAHCQACAQIPaW52YWxpZCBhc3NldElkBgAObm90SW5pdGlhbGl6ZWQJAQd0aHJvd0lmAgkBCWlzRGVmaW5lZAEJAQRnZXRTAQUMYXNzZXRJZFN0b3JlAhNhbHJlYWR5IGluaXRpYWxpemVkABJtYXliZU9yYWNsZUFkZHJlc3MEByRtYXRjaDAJAJ0IAgUNY29uZmlnQWRkcmVzcwIOb3JhY2xlX2FkZHJlc3MDCQABAgUHJG1hdGNoMAIGU3RyaW5nBAFzBQckbWF0Y2gwCQCmCAEFAXMFBHVuaXQAC29yYWNsZVByaWNlBAckbWF0Y2gwCQD8BwQJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgUSbWF5YmVPcmFjbGVBZGRyZXNzAglubyBvcmFjbGUCBXByaWNlCQDMCAIFCmFzc2V0SWRTdHIFA25pbAUDbmlsAwkAAQIFByRtYXRjaDACA0ludAQBaQUHJG1hdGNoMAUBaQkAAgECD2JhZCBvcmFjbGUgZGF0YQAGSEVJR0hUBQZoZWlnaHQACGFUb2tlbklkCQDZBAEJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkBBGdldFMBBQ1hVG9rZW5JZFN0b3JlAgtubyBhVG9rZW5JZAARYVRva2VuQ2lyY3VsYXRpb24JAQt2YWx1ZU9yRWxzZQIJAQRnZXRJAQUWYVRva2VuQ2lyY3VsYXRpb25TdG9yZQAAAA1yZXNlcnZlRmFjdG9yCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAJoIAgUNY29uZmlnQWRkcmVzcwUScmVzZXJ2ZUZhY3RvclN0b3JlAhBubyByZXNlcnZlRmFjdG9yABBjb2xsYXRlcmFsRmFjdG9yCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAJoIAgUNY29uZmlnQWRkcmVzcwUVY29sbGF0ZXJhbEZhY3RvclN0b3JlAhNubyBjb2xsYXRlcmFsRmFjdG9yABRsaXF1aWRhdGlvblRocmVzaG9sZAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCaCAIFDWNvbmZpZ0FkZHJlc3MFGWxpcXVpZGF0aW9uVGhyZXNob2xkU3RvcmUCF25vIGxpcXVpZGF0aW9uVGhyZXNob2xkABRhY2NvdW50SGVhbHRoT3ZlcmxhcAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCaCAIFDWNvbmZpZ0FkZHJlc3MFEm92ZXJsYXBDaGFyZ2VTdG9yZQIQbm8gb3ZlcmxhcENoYXJnZQASbGlxdWlkYXRpb25QZW5hbHR5CQETdmFsdWVPckVycm9yTWVzc2FnZQIJAJoIAgUNY29uZmlnQWRkcmVzcwUXbGlxdWlkYXRpb25QZW5hbHR5U3RvcmUCFW5vIGxpcXVpZGF0aW9uUGVuYWx0eQALdXRpbGl6YXRpb24DCQBmAgUSc3RvcmVkVG90YWxEZXBvc2l0AAAJAJcDAQkAzAgCBQtmYWN0b3JzQmFzZQkAzAgCCQBrAwUPc3RvcmVkVG90YWxEZWJ0BQtmYWN0b3JzQmFzZQUSc3RvcmVkVG90YWxEZXBvc2l0BQNuaWwAAAADYXByBAFhCQERQGV4dHJOYXRpdmUoMTA1MCkCBQ1jb25maWdBZGRyZXNzCQCsAgIFCmFzc2V0SWRTdHICB19BUG9pbnQEAWIJARFAZXh0ck5hdGl2ZSgxMDUwKQIFDWNvbmZpZ0FkZHJlc3MJAKwCAgUKYXNzZXRJZFN0cgIHX0JQb2ludAQBYwkBEUBleHRyTmF0aXZlKDEwNTApAgUNY29uZmlnQWRkcmVzcwkArAICBQphc3NldElkU3RyAgdfQ1BvaW50BAFkCQERQGV4dHJOYXRpdmUoMTA1MCkCBQ1jb25maWdBZGRyZXNzCQCsAgIFCmFzc2V0SWRTdHICB19EUG9pbnQEBmxpbmVBQwkAZAIJAGsDCQBlAgUBYQUBYwULdXRpbGl6YXRpb24JAQEtAQUBYgUBYQQGbGluZUNECQBkAgkAawMJAGUCBQFjBQFkCQBlAgULdXRpbGl6YXRpb24FAWIJAGUCBQFiBQtmYWN0b3JzQmFzZQUBYwMJAAACBQt1dGlsaXphdGlvbgAABQFhAwkAAAIFC3V0aWxpemF0aW9uBQFiBQFjAwMJAGYCBQFiBQt1dGlsaXphdGlvbgYJAAACBQFiBQtmYWN0b3JzQmFzZQUGbGluZUFDBQZsaW5lQ0QAA2FweQMJAAACBRJzdG9yZWRUb3RhbERlcG9zaXQAAAAACQBrAwkAawMFD3N0b3JlZFRvdGFsRGVidAUDYXByBRJzdG9yZWRUb3RhbERlcG9zaXQJAGUCBQtmYWN0b3JzQmFzZQUNcmVzZXJ2ZUZhY3RvcgULZmFjdG9yc0Jhc2UADGN1cnJlbnRJbmRleAMJAAACBQZIRUlHSFQFEGxhc3RVcGRhdGVIZWlnaHQFC3N0b3JlZEluZGV4BANicHIJAQxmcmFjdGlvbkNlaWwDBQNhcHIFBVJCYXNlCQBoAgUNQmxvY2tzUGVyWWVhcgULZmFjdG9yc0Jhc2UJAQxmcmFjdGlvbkNlaWwDBQtzdG9yZWRJbmRleAkAZAIFBVJCYXNlCQBoAgUDYnByCQBlAgUGSEVJR0hUBRBsYXN0VXBkYXRlSGVpZ2h0BQVSQmFzZQAOc3Rha2luZ0VuYWJsZWQJAQt2YWx1ZU9yRWxzZQIJAJsIAgUNY29uZmlnQWRkcmVzcwkArAICAhBzdGFraW5nX2VuYWJsZWRfBQphc3NldElkU3RyBwANYWN0dWFsQmFsYW5jZQQHJG1hdGNoMAUHYXNzZXRJZAMJAAECBQckbWF0Y2gwAgpCeXRlVmVjdG9yBANhaWQFByRtYXRjaDAJAPAHAgUEdGhpcwUDYWlkCAkA7wcBBQR0aGlzCWF2YWlsYWJsZQEObGlxdWlkaXR5Q2hlY2sDBmFtb3VudANtYXgDZXJyAwkAZgIFBmFtb3VudAUDbWF4CQACAQkArAICAhZub3QgZW5vdWdoIGxpcXVpZGl0eTogBQNlcnIGAQ5zdG9yZWRVc2VyRGVidAELdXNlckFkZHJlc3MJAQt2YWx1ZU9yRWxzZQIJAQRnZXRJAQkBCWRlYnRTdG9yZQEFC3VzZXJBZGRyZXNzAAABD2N1cnJlbnRVc2VyRGVidAELdXNlckFkZHJlc3MEAXYJAQ5zdG9yZWRVc2VyRGVidAEFC3VzZXJBZGRyZXNzAwkAAAIFAXYAAAAABA9zdG9yZWRVc2VySW5kZXgJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkBBGdldEkBCQEOZGVidEluZGV4U3RvcmUBBQt1c2VyQWRkcmVzcwIgaGFzIGRlYnQgYnV0IGRvZXMgbm90IGhhdmUgaW5kZXgJAGsDBQF2BQxjdXJyZW50SW5kZXgFD3N0b3JlZFVzZXJJbmRleAAQY3VycmVudFRvdGFsRGVidAkAawMFD3N0b3JlZFRvdGFsRGVidAUMY3VycmVudEluZGV4BQtzdG9yZWRJbmRleAAJYWRkZWREZWJ0CQBlAgUQY3VycmVudFRvdGFsRGVidAUPc3RvcmVkVG90YWxEZWJ0AAxhZGRlZERlcG9zaXQJAGsDBQlhZGRlZERlYnQJAGUCBQtmYWN0b3JzQmFzZQUNcmVzZXJ2ZUZhY3RvcgULZmFjdG9yc0Jhc2UAE2N1cnJlbnRUb3RhbERlcG9zaXQJAGQCBRJzdG9yZWRUb3RhbERlcG9zaXQFDGFkZGVkRGVwb3NpdAATY3VycmVudFRvdGFsUmVzZXJ2ZQkAZQIJAGQCBRJzdG9yZWRUb3RhbFJlc2VydmUFCWFkZGVkRGVidAUMYWRkZWREZXBvc2l0AA5zdGFraW5nQWRkcmVzcwkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCmCAEJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAnQgCBQ1jb25maWdBZGRyZXNzCQCsAgICD3N0YWtpbmdfY29uZmlnXwUKYXNzZXRJZFN0cgkArAICAhdubyBzdGFraW5nIGFkZHJlc3MgZm9yIAUKYXNzZXRJZFN0cgkArAICAhhiYWQgc3Rha2luZyBhZGRyZXNzIGZvciAFCmFzc2V0SWRTdHIAEmNsYWltYWJsZURpdmlkZW5kcwkAlwMBCQDMCAIFE2N1cnJlbnRUb3RhbFJlc2VydmUJAMwIAgMFDnN0YWtpbmdFbmFibGVkCQEFYXNJbnQBCQD8BwQFDnN0YWtpbmdBZGRyZXNzAgRpbmZvBQNuaWwFA25pbAUNYWN0dWFsQmFsYW5jZQUDbmlsAQ1wYXltZW50QW1vdW50AgFpB2Fzc2V0SWQEAXAICQCRAwIIBQFpCHBheW1lbnRzAAAGYW1vdW50AwkAZwIAAAUBcAkAAgEJAKwCAgIpUGF5bWVudCBpcyBsZXNzIHRoYW4gbWluIGFsbG93ZWQgYW1vdW50OiAJAKQDAQUBcAMJAQIhPQIICQCRAwIIBQFpCHBheW1lbnRzAAAHYXNzZXRJZAUHYXNzZXRJZAkAAgEJAKwCAgIeIGJhZCBhc3NldCBhdHRhY2hlZDogcmVxdWlyZWQgBQphc3NldElkU3RyBQFwAQpzeW5jVG90YWxzBBFhZGRpdGlvbmFsRGVwb3NpdA5hZGRpdGlvbmFsRGVidBFhZGRpdGlvbmFsUmVzZXJ2ZQ1rZWVwQXRCYWxhbmNlBA1zdGFraW5nQWN0aW9uAwkAAAIFDWFjdHVhbEJhbGFuY2UFDWtlZXBBdEJhbGFuY2UFBHVuaXQDCQEBIQEFDnN0YWtpbmdFbmFibGVkBQR1bml0AwkAZgIFDWFjdHVhbEJhbGFuY2UFDWtlZXBBdEJhbGFuY2UJAPwHBAUOc3Rha2luZ0FkZHJlc3MCA3B1dAUDbmlsCQDMCAIJAQ9BdHRhY2hlZFBheW1lbnQCBQdhc3NldElkCQBlAgUNYWN0dWFsQmFsYW5jZQUNa2VlcEF0QmFsYW5jZQUDbmlsCQD8BwQFDnN0YWtpbmdBZGRyZXNzAgNnZXQJAMwIAgkAZQIFDWtlZXBBdEJhbGFuY2UFDWFjdHVhbEJhbGFuY2UFA25pbAUDbmlsAwkAAAIFDXN0YWtpbmdBY3Rpb24FDXN0YWtpbmdBY3Rpb24EB2RlcG9zaXQJAQllbnN1cmVHRTABCQBkAgUTY3VycmVudFRvdGFsRGVwb3NpdAURYWRkaXRpb25hbERlcG9zaXQEBGRlYnQJAQllbnN1cmVHRTABCQBkAgUQY3VycmVudFRvdGFsRGVidAUOYWRkaXRpb25hbERlYnQEB3Jlc2VydmUJAQllbnN1cmVHRTABCQBkAgUTY3VycmVudFRvdGFsUmVzZXJ2ZQURYWRkaXRpb25hbFJlc2VydmUJAMwIAgkBC3dyaXRlU3RyaW5nAgUScmVzZXJ2ZUdsb2JhbFN0b3JlCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkApAMBBQZIRUlHSFQCAXwJAKQDAQUHZGVwb3NpdAIBfAkApAMBBQRkZWJ0AgF8CQCkAwEFB3Jlc2VydmUCAXwJAKQDAQUMY3VycmVudEluZGV4BQNuaWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BBXBvdzEwAQFuAwkAAAIFAW4ABgDAhD0DCQAAAgUBbgAIAIDC1y8JAAIBCQCsAgICDmJhZCBkZWNpbWFsczogCQCkAwEFAW4BCmFzc2V0VG9Vc2QBBmFtb3VudAkAawMFBmFtb3VudAULb3JhY2xlUHJpY2UJAQVwb3cxMAEFDWFzc2V0RGVjaW1hbHMBCnVzZFRvQXNzZXQBBmFtb3VudAkAawMFBmFtb3VudAkBBXBvdzEwAQUNYXNzZXREZWNpbWFscwULb3JhY2xlUHJpY2UBDWFUb2tlblRvQXNzZXQBDGFUb2tlbkFtb3VudAMJAAACBQxhVG9rZW5BbW91bnQAAAAAAwkAZgIFEWFUb2tlbkNpcmN1bGF0aW9uAAAJAGsDBQxhVG9rZW5BbW91bnQFE2N1cnJlbnRUb3RhbERlcG9zaXQFEWFUb2tlbkNpcmN1bGF0aW9uBQxhVG9rZW5BbW91bnQBDWFzc2V0VG9BVG9rZW4BC2Fzc2V0QW1vdW50AwkAAAIFC2Fzc2V0QW1vdW50AAAAAAMJAGYCBRFhVG9rZW5DaXJjdWxhdGlvbgAACQBrAwULYXNzZXRBbW91bnQFEWFUb2tlbkNpcmN1bGF0aW9uBRNjdXJyZW50VG90YWxEZXBvc2l0BQthc3NldEFtb3VudAERYXNzZXRUb0FUb2tlbkNlaWwBC2Fzc2V0QW1vdW50AwkAAAIFC2Fzc2V0QW1vdW50AAAAAAMJAGYCBRFhVG9rZW5DaXJjdWxhdGlvbgAACQEMZnJhY3Rpb25DZWlsAwULYXNzZXRBbW91bnQFEWFUb2tlbkNpcmN1bGF0aW9uBRNjdXJyZW50VG90YWxEZXBvc2l0BQthc3NldEFtb3VudAENYVRva2VuQmFsYW5jZQEHYWRkcmVzcwkBC3ZhbHVlT3JFbHNlAgkBBGdldEkBCQESYVRva2VuQmFsYW5jZVN0b3JlAQUHYWRkcmVzcwAAAQllbmFibGVDb2wBBHVzZXIJAQxCb29sZWFuRW50cnkCCQEUdXNlQXNDb2xsYXRlcmFsU3RvcmUBBQR1c2VyBgERZW5hYmxlQ29sSWZOZWVkZWQBBHVzZXIDCQBmAgkBD2N1cnJlbnRVc2VyRGVidAEFBHVzZXIAAAkAzAgCCQEJZW5hYmxlQ29sAQUEdXNlcgUDbmlsBQNuaWwBDGNvbGxhcHNlVXNlcgIHYWRkcmVzcwZhbW91bnQEBGRlYnQJAQ9jdXJyZW50VXNlckRlYnQBBQdhZGRyZXNzBAdkZXBvc2l0CQENYVRva2VuVG9Bc3NldAEJAQ1hVG9rZW5CYWxhbmNlAQUHYWRkcmVzcwQLbWF4UG9zc2libGUJAJcDAQkAzAgCBQRkZWJ0CQDMCAIFB2RlcG9zaXQFA25pbAQDYW10AwkAZgIA////////////AQUGYW1vdW50CQACAQIXaW52YWxpZCBjb2xsYXBzZSBhbW91bnQDAwkAAAIFC21heFBvc3NpYmxlAAAGCQAAAgUGYW1vdW50AAAJAAIBAhNub3RoaW5nIHRvIGNvbGxhcHNlAwMJAAACBQZhbW91bnQA////////////AQYJAGYCBQZhbW91bnQFC21heFBvc3NpYmxlBQttYXhQb3NzaWJsZQUGYW1vdW50BA5yZW1vdmVkQXRva2VucwkBEWFzc2V0VG9BVG9rZW5DZWlsAQUDYW10CQCUCgIJAM4IAgkBCnN5bmNUb3RhbHMECQEBLQEFA2FtdAkBAS0BBQNhbXQAAAAACQDMCAIJAQhjaGFuZ2VCeQIJARJhVG9rZW5CYWxhbmNlU3RvcmUBBQdhZGRyZXNzCQEBLQEFDnJlbW92ZWRBdG9rZW5zCQDMCAIJAQhjaGFuZ2VCeQIFFmFUb2tlbkNpcmN1bGF0aW9uU3RvcmUJAQEtAQUOcmVtb3ZlZEF0b2tlbnMJAMwIAgkBCHdyaXRlSW50AgkBCWRlYnRTdG9yZQEFB2FkZHJlc3MJAGUCBQRkZWJ0BQNhbXQJAMwIAgkBCHdyaXRlSW50AgkBDmRlYnRJbmRleFN0b3JlAQUHYWRkcmVzcwUMY3VycmVudEluZGV4BQNuaWwFA2FtdAEJcmVwYXlVc2VyAgt1c2VyQWRkcmVzcwZhbW91bnQEBmNoZWNrcwkBCW9wQWxsb3dlZAECBXJlcGF5AwkAAAIFBmNoZWNrcwUGY2hlY2tzBAtjdXJyZW50RGVidAkBD2N1cnJlbnRVc2VyRGVidAEFC3VzZXJBZGRyZXNzAwkAAAIFC2N1cnJlbnREZWJ0BQtjdXJyZW50RGVidAQNJHQwMTE3ODMxMjA4NgMJAGYCBQZhbW91bnQFC2N1cnJlbnREZWJ0CQCWCgQAAAkBAS0BBQtjdXJyZW50RGVidAkAZQIFBmFtb3VudAULY3VycmVudERlYnQJAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwkBEUBleHRyTmF0aXZlKDEwNjIpAQULdXNlckFkZHJlc3MJAGUCBQZhbW91bnQFC2N1cnJlbnREZWJ0BQdhc3NldElkBQNuaWwJAJYKBAkAZQIFC2N1cnJlbnREZWJ0BQZhbW91bnQJAQEtAQUGYW1vdW50AAAFA25pbAQHbmV3RGVidAgFDSR0MDExNzgzMTIwODYCXzEED3RvdGFsRGVidFVwZGF0ZQgFDSR0MDExNzgzMTIwODYCXzIEBnBheW91dAgFDSR0MDExNzgzMTIwODYCXzMEB2FjdGlvbnMIBQ0kdDAxMTc4MzEyMDg2Al80BAZyZXBhaWQJAGUCBQZhbW91bnQFBnBheW91dAkAlAoCCQDOCAIJAM4IAgkBCnN5bmNUb3RhbHMEAAAFD3RvdGFsRGVidFVwZGF0ZQAABQZwYXlvdXQFB2FjdGlvbnMJAMwIAgkBCHdyaXRlSW50AgkBCWRlYnRTdG9yZQEFC3VzZXJBZGRyZXNzBQduZXdEZWJ0CQDMCAIJAQh3cml0ZUludAIJAQ5kZWJ0SW5kZXhTdG9yZQEFC3VzZXJBZGRyZXNzBQxjdXJyZW50SW5kZXgFA25pbAUGcmVwYWlkCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAQlnZXRDb25maWcABAFhCQERQGV4dHJOYXRpdmUoMTA1MCkCBQ1jb25maWdBZGRyZXNzCQCsAgIFCmFzc2V0SWRTdHICB19BUG9pbnQEAWIJARFAZXh0ck5hdGl2ZSgxMDUwKQIFDWNvbmZpZ0FkZHJlc3MJAKwCAgUKYXNzZXRJZFN0cgIHX0JQb2ludAQBYwkBEUBleHRyTmF0aXZlKDEwNTApAgUNY29uZmlnQWRkcmVzcwkArAICBQphc3NldElkU3RyAgdfQ1BvaW50BAFkCQERQGV4dHJOYXRpdmUoMTA1MCkCBQ1jb25maWdBZGRyZXNzCQCsAgIFCmFzc2V0SWRTdHICB19EUG9pbnQJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgICBkFCQ0Q6IAkApAMBBQFhAgE7CQCkAwEFAWICATsJAKQDAQUBYwIBOwkApAMBBQFkAhEsIHJlc2VydmVGYWN0b3I6IAkApAMBBQ1yZXNlcnZlRmFjdG9yAhQsIGNvbGxhdGVyYWxGYWN0b3I6IAkApAMBBRBjb2xsYXRlcmFsRmFjdG9yAhgsIGxpcXVpZGF0aW9uVGhyZXNob2xkOiAJAKQDAQUUbGlxdWlkYXRpb25UaHJlc2hvbGQCFiwgbGlxdWlkYXRpb25QZW5hbHR5OiAJAKQDAQUSbGlxdWlkYXRpb25QZW5hbHR5AQhnZXRTdGF0ZQAJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgICFWN1cnJlbnRUb3RhbERlcG9zaXQ6IAkApAMBBRNjdXJyZW50VG90YWxEZXBvc2l0AhYsIHN0b3JlZFRvdGFsRGVwb3NpdDogCQCkAwEFEnN0b3JlZFRvdGFsRGVwb3NpdAIULCBjdXJyZW50VG90YWxEZWJ0OiAJAKQDAQUQY3VycmVudFRvdGFsRGVidAITLCBzdG9yZWRUb3RhbERlYnQ6IAkApAMBBQ9zdG9yZWRUb3RhbERlYnQCFywgY3VycmVudFRvdGFsUmVzZXJ2ZTogCQCkAwEFE2N1cnJlbnRUb3RhbFJlc2VydmUCFiwgc3RvcmVkVG90YWxSZXNlcnZlOiAJAKQDAQUSc3RvcmVkVG90YWxSZXNlcnZlAg8sIGN1cnJlbnRJbmRleDoJAKQDAQUMY3VycmVudEluZGV4Ag8sIHN0b3JlZEluZGV4OiAJAKQDAQULc3RvcmVkSW5kZXgCFCwgbGFzdFVwZGF0ZUhlaWdodDogCQCkAwEFEGxhc3RVcGRhdGVIZWlnaHQCDywgdXRpbGl6YXRpb246IAkApAMBBQt1dGlsaXphdGlvbgIVLCBhVG9rZW5DaXJjdWxhdGlvbjogCQCkAwEFEWFUb2tlbkNpcmN1bGF0aW9uAg8sIGFUb2tlblByaWNlOiAJAKQDAQkBDWFUb2tlblRvQXNzZXQBCQBsBgAKAAAFDWFzc2V0RGVjaW1hbHMAAAAABQVGTE9PUgIHLCBBUFI6IAkApAMBBQNhcHICBywgQVBZOiAJAKQDAQUDYXB5AQxnZXRVc2VyU3RhdGUBBHVzZXIECGFCYWxhbmNlCQENYVRva2VuQmFsYW5jZQEFBHVzZXIEDmFCYWxhbmNlV2FsbGV0CQEKZ2V0QmFsYW5jZQIJARFAZXh0ck5hdGl2ZSgxMDYyKQEFBHVzZXIFCGFUb2tlbklkCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgINY3VycmVudERlYnQ6IAkApAMBCQEPY3VycmVudFVzZXJEZWJ0AQUEdXNlcgIOLCBzdG9yZWREZWJ0OiAJAKQDAQkBC3ZhbHVlT3JFbHNlAgkBBGdldEkBCQEJZGVidFN0b3JlAQUEdXNlcgAAAhIsIGN1cnJlbnREZXBvc2l0OiAJAKQDAQkBDWFUb2tlblRvQXNzZXQBBQhhQmFsYW5jZQIZLCBhVG9rZW5Db250cmFjdEJhbGFuY2U6IAkApAMBBQhhQmFsYW5jZQIXLCBhVG9rZW5XYWxsZXRCYWxhbmNlOiAJAKQDAQUOYUJhbGFuY2VXYWxsZXQCDywgd2FsbGV0U3Rha2U6IAkApAMBCQENYVRva2VuVG9Bc3NldAEFDmFCYWxhbmNlV2FsbGV0AhYsIGFzc2V0V2FsbGV0QmFsYW5jZTogCQCkAwEJAQpnZXRCYWxhbmNlAgkBEUBleHRyTmF0aXZlKDEwNjIpAQUEdXNlcgUHYXNzZXRJZAITLCB1c2VBc0NvbGxhdGVyYWw6IAkApQMBCQELdmFsdWVPckVsc2UCCQCbCAIFBHRoaXMJARR1c2VBc0NvbGxhdGVyYWxTdG9yZQEFBHVzZXIGAg8sIHN0b3JlZEluZGV4OiAJAKQDAQkBC3ZhbHVlT3JFbHNlAgkBBGdldEkBCQEOZGVidEluZGV4U3RvcmUBBQR1c2VyAAABC2RlYnVnVG90YWxzAAkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgICFHN0b3JlZFRvdGFsRGVwb3NpdDogCQCkAwEFEnN0b3JlZFRvdGFsRGVwb3NpdAITLCBzdG9yZWRUb3RhbERlYnQ6IAkApAMBBQ9zdG9yZWRUb3RhbERlYnQCFiwgc3RvcmVkVG90YWxSZXNlcnZlOiAJAKQDAQUSc3RvcmVkVG90YWxSZXNlcnZlAg8sIHN0b3JlZEluZGV4OiAJAKQDAQULc3RvcmVkSW5kZXgCFCwgbGFzdFVwZGF0ZUhlaWdodDogCQCkAwEFEGxhc3RVcGRhdGVIZWlnaHQCFywgY3VycmVudFRvdGFsRGVwb3NpdDogCQCkAwEFE2N1cnJlbnRUb3RhbERlcG9zaXQCFCwgY3VycmVudFRvdGFsRGVidDogCQCkAwEFEGN1cnJlbnRUb3RhbERlYnQCFywgY3VycmVudFRvdGFsUmVzZXJ2ZTogCQCkAwEFE2N1cnJlbnRUb3RhbFJlc2VydmUCECwgY3VycmVudEluZGV4OiAJAKQDAQUMY3VycmVudEluZGV4AhEsIGN1cnJlbnRIZWlnaHQ6IAkApAMBBQZIRUlHSFQCFSwgYVRva2VuQ2lyY3VsYXRpb246IAkApAMBBRFhVG9rZW5DaXJjdWxhdGlvbgIPLCBhVG9rZW5QcmljZTogCQCkAwEJAQ1hVG9rZW5Ub0Fzc2V0AQkAbAYACgAABQ1hc3NldERlY2ltYWxzAAAAAAUFRkxPT1IBCnVzZXJUb3RhbHMBBHVzZXIEB2F0b2tlbnMJAQ1hVG9rZW5CYWxhbmNlAQUEdXNlcgQFYXNzZXQJAQ1hVG9rZW5Ub0Fzc2V0AQUHYXRva2VucwQEZGVidAkBD2N1cnJlbnRVc2VyRGVidAEFBHVzZXIDCQAAAgUGSEVJR0hUBRBsYXN0VXBkYXRlSGVpZ2h0CQCWCgQFEnN0b3JlZFRvdGFsRGVwb3NpdAUPc3RvcmVkVG90YWxEZWJ0BQVhc3NldAUEZGVidAkAlgoEBRNjdXJyZW50VG90YWxEZXBvc2l0BRBjdXJyZW50VG90YWxEZWJ0BQVhc3NldAUEZGVidAEQd2l0aGRyYXdJbnRlcm5hbAQBaQR1c2VyBmFtb3VudAZ0b01haW4EC21heFdpdGhkcmF3CQBlAgkAZAIFEnN0b3JlZFRvdGFsRGVwb3NpdAUSc3RvcmVkVG90YWxSZXNlcnZlBQ9zdG9yZWRUb3RhbERlYnQEBmNoZWNrcwMDAwkBCG1haW5Pbmx5AQUBaQkBDmxpcXVpZGl0eUNoZWNrAwUGYW1vdW50BQttYXhXaXRoZHJhdwkArAICAhJmdW5kcyBpbiB1c2U6IG1heD0JAKQDAQULbWF4V2l0aGRyYXcHCQEHdGhyb3dJZgIJAGYCAP///////////wEFBmFtb3VudAIOaW52YWxpZCBhbW91bnQHCQEJb3BBbGxvd2VkAQIId2l0aGRyYXcHAwkAAAIFBmNoZWNrcwUGY2hlY2tzBA0kdDAxNTk2ODE2MTU5AwkAAAIFBmFtb3VudAD///////////8BBAdhdG9rZW5zCQENYVRva2VuQmFsYW5jZQEFBHVzZXIJAJQKAgUHYXRva2VucwkBDWFUb2tlblRvQXNzZXQBBQdhdG9rZW5zCQCUCgIJARFhc3NldFRvQVRva2VuQ2VpbAEFBmFtb3VudAUGYW1vdW50BA5yZW1vdmVkQXRva2VucwgFDSR0MDE1OTY4MTYxNTkCXzEEDndpdGhkcmF3QW1vdW50CAUNJHQwMTU5NjgxNjE1OQJfMgkAlAoCCQDOCAIJAQpzeW5jVG90YWxzBAkBAS0BBQ53aXRoZHJhd0Ftb3VudAAAAAAFDndpdGhkcmF3QW1vdW50CQDMCAIJAQ5TY3JpcHRUcmFuc2ZlcgMDBQZ0b01haW4FDG1haW5Db250cmFjdAkBEUBleHRyTmF0aXZlKDEwNjIpAQUEdXNlcgUOd2l0aGRyYXdBbW91bnQFB2Fzc2V0SWQJAMwIAgkBCGNoYW5nZUJ5AgkBEmFUb2tlbkJhbGFuY2VTdG9yZQEFBHVzZXIJAQEtAQUOcmVtb3ZlZEF0b2tlbnMJAMwIAgkBCGNoYW5nZUJ5AgUWYVRva2VuQ2lyY3VsYXRpb25TdG9yZQkBAS0BBQ5yZW1vdmVkQXRva2VucwUDbmlsBQ53aXRoZHJhd0Ftb3VudAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgERcmVwbGVuaXNoSW50ZXJuYWwDAm9wBHVzZXIBaQQGY2hlY2tzAwkBCG1haW5Pbmx5AQUBaQkBCW9wQWxsb3dlZAEFAm9wBwMJAAACBQZjaGVja3MFBmNoZWNrcwQMYVRva2VuQW1vdW50CQENcGF5bWVudEFtb3VudAIFAWkFCGFUb2tlbklkCQCUCgIJAM4IAgkAzggCCQEKc3luY1RvdGFscwQAAAAAAAAAAAkAzAgCCQEIY2hhbmdlQnkCCQESYVRva2VuQmFsYW5jZVN0b3JlAQUEdXNlcgUMYVRva2VuQW1vdW50CQDMCAIJAQRCdXJuAgUIYVRva2VuSWQFDGFUb2tlbkFtb3VudAUDbmlsCQERZW5hYmxlQ29sSWZOZWVkZWQBBQR1c2VyCQENYVRva2VuVG9Bc3NldAEFDGFUb2tlbkFtb3VudAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgEMbWludEludGVybmFsBQFpB2FkZHJlc3MMYW1vdW50VG9NaW50AnRvBmFjdGlvbgQRdXNlckFUb2tlbkJhbGFuY2UJAQ1hVG9rZW5CYWxhbmNlAQUHYWRkcmVzcwQGYW1vdW50AwkAAAIFDGFtb3VudFRvTWludAD///////////8BBRF1c2VyQVRva2VuQmFsYW5jZQUMYW1vdW50VG9NaW50BAZjaGVja3MDAwMJAQhtYWluT25seQEFAWkJAQlvcEFsbG93ZWQBBQZhY3Rpb24HCQEHdGhyb3dJZgIJAGYCAP///////////wEFDGFtb3VudFRvTWludAIUaW52YWxpZCBhbW91bnRUb01pbnQHCQEHdGhyb3dJZgIJAGYCBQZhbW91bnQFEXVzZXJBVG9rZW5CYWxhbmNlCQCsAgICKVRyeWluZyB0byBtaW50IG1vcmUgdGhhbiBhdmFpbGFibGUsIG1heDogCQCkAwEFEXVzZXJBVG9rZW5CYWxhbmNlBwMJAAACBQZjaGVja3MFBmNoZWNrcwkAlAoCCQDOCAIJAQpzeW5jVG90YWxzBAAAAAAAAAAACQDMCAIJAQhjaGFuZ2VCeQIJARJhVG9rZW5CYWxhbmNlU3RvcmUBBQdhZGRyZXNzCQEBLQEFBmFtb3VudAkAzAgCCQEHUmVpc3N1ZQMFCGFUb2tlbklkBQZhbW91bnQGCQDMCAIJAQ5TY3JpcHRUcmFuc2ZlcgMJARFAZXh0ck5hdGl2ZSgxMDYyKQEFAnRvBQZhbW91bnQFCGFUb2tlbklkBQNuaWwJAQ1hVG9rZW5Ub0Fzc2V0AQUGYW1vdW50CQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuIwFpARJnZXRSZXNlcnZlRGl2c0luZm8ACQCUCgIFA25pbAkAlQoDBRJjbGFpbWFibGVEaXZpZGVuZHMFCmFzc2V0SWRTdHIJAGUCBRNjdXJyZW50VG90YWxSZXNlcnZlBRJjbGFpbWFibGVEaXZpZGVuZHMBaQETc3RvcmVkRGVwb3NpdEJvcnJvdwAJAJQKAgUDbmlsCQCUCgIFEnN0b3JlZFRvdGFsRGVwb3NpdAUPc3RvcmVkVG90YWxEZWJ0AWkBEGdldEN1cnJlbnRUb3RhbHMBBHVzZXIJAJQKAgUDbmlsCQEKdXNlclRvdGFscwEFBHVzZXIBaQERZ2V0Q3VycmVudFRvdGFsczICBXVzZXIxBXVzZXIyBA0kdDAxNzg0MDE3ODc3CQEKdXNlclRvdGFscwEFBXVzZXIxBAJkMQgFDSR0MDE3ODQwMTc4NzcCXzEEAmQyCAUNJHQwMTc4NDAxNzg3NwJfMgQCZDMIBQ0kdDAxNzg0MDE3ODc3Al8zBAJkNAgFDSR0MDE3ODQwMTc4NzcCXzQEDSR0MDE3ODgyMTc5MTkJAQp1c2VyVG90YWxzAQUFdXNlcjIEAmUxCAUNJHQwMTc4ODIxNzkxOQJfMQQCZTIIBQ0kdDAxNzg4MjE3OTE5Al8yBAJlMwgFDSR0MDE3ODgyMTc5MTkCXzMEAmU0CAUNJHQwMTc4ODIxNzkxOQJfNAkAlAoCBQNuaWwJAJgKBgUCZDEFAmQyBQJkMwUCZDQFAmUzBQJlNAFpAQZhZHZpc2UACQCUCgIFA25pbAkArAICCQCsAgIJAKwCAgkArAICCQCsAgICEHJlc2VydmVBZGRyZXNzOiAJAKUIAQUEdGhpcwICLCAJAQlnZXRDb25maWcAAgIsIAkBCGdldFN0YXRlAAFpAQphZHZpc2VVc2VyAQR1c2VyBA5jdXJyZW50RGVidFVzZAkBCmFzc2V0VG9Vc2QBBRBjdXJyZW50VG90YWxEZWJ0BBFjdXJyZW50RGVwb3NpdFVzZAkBCmFzc2V0VG9Vc2QBBRNjdXJyZW50VG90YWxEZXBvc2l0BAxhc0NvbGxhdGVyYWwJAQt2YWx1ZU9yRWxzZQIJAJsIAgUEdGhpcwkBFHVzZUFzQ29sbGF0ZXJhbFN0b3JlAQUEdXNlcgYEE2VmZmVjdGl2ZURlcG9zaXRVc2QDBQxhc0NvbGxhdGVyYWwFEWN1cnJlbnREZXBvc2l0VXNkAAAECm92ZXJsYXBVc2QJAJcDAQkAzAgCBQ5jdXJyZW50RGVidFVzZAkAzAgCBRNlZmZlY3RpdmVEZXBvc2l0VXNkBQNuaWwEDW92ZXJsYXBDaGFyZ2UJAQxmcmFjdGlvbkNlaWwDBQpvdmVybGFwVXNkBRRhY2NvdW50SGVhbHRoT3ZlcmxhcAULZmFjdG9yc0Jhc2UEAmJwAwkAZgIFDmN1cnJlbnREZWJ0VXNkBRNlZmZlY3RpdmVEZXBvc2l0VXNkAAAJAGsDCQBlAgUTZWZmZWN0aXZlRGVwb3NpdFVzZAUOY3VycmVudERlYnRVc2QFEGNvbGxhdGVyYWxGYWN0b3IFC2ZhY3RvcnNCYXNlBANicHUDCQBmAgUOY3VycmVudERlYnRVc2QFE2VmZmVjdGl2ZURlcG9zaXRVc2QJAGQCCQBrAwkAZQIFDmN1cnJlbnREZWJ0VXNkBRNlZmZlY3RpdmVEZXBvc2l0VXNkBQtmYWN0b3JzQmFzZQUUbGlxdWlkYXRpb25UaHJlc2hvbGQFDW92ZXJsYXBDaGFyZ2UFDW92ZXJsYXBDaGFyZ2UECGVucmljaGVkCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICAhByZXNlcnZlQWRkcmVzczogCQClCAEFBHRoaXMCEiwgY3VycmVudERlYnRVc2Q6IAkApAMBBQ5jdXJyZW50RGVidFVzZAIVLCBjdXJyZW50RGVwb3NpdFVzZDogCQCkAwEFEWN1cnJlbnREZXBvc2l0VXNkAgYsIGJwOiAJAKQDAQUCYnACBywgYnB1OiAJAKQDAQUDYnB1CQCUCgIFA25pbAkArAICCQCsAgIFCGVucmljaGVkAgIsIAkBDGdldFVzZXJTdGF0ZQEFBHVzZXIBaQELYWRkSW50ZXJlc3QAAwkBAiE9AggJAJEDAggFAWkIcGF5bWVudHMAAAdhc3NldElkBQdhc3NldElkCQACAQInY2FuJ3QgYWRkIGludGVyZXN0IHdpdGggdW5yZWxhdGVkIHRva2VuCQEKc3luY1RvdGFscwQICQCRAwIIBQFpCHBheW1lbnRzAAAGYW1vdW50AAAAAAAAAWkBDGFkZFRvUmVzZXJ2ZQADCQECIT0CCAkAkQMCCAUBaQhwYXltZW50cwAAB2Fzc2V0SWQFB2Fzc2V0SWQJAAIBAidjYW4ndCBhZGQgaW50ZXJlc3Qgd2l0aCB1bnJlbGF0ZWQgdG9rZW4JAQpzeW5jVG90YWxzBAAAAAAICQCRAwIIBQFpCHBheW1lbnRzAAAGYW1vdW50AAABaQETd2l0aGRyYXdGcm9tUmVzZXJ2ZQEDYW10BAZjaGVja3MJAQxkaXZBZG1pbk9ubHkBBQFpAwkAAAIFBmNoZWNrcwUGY2hlY2tzBARkaWZmAwkAAAIFA2FtdAD///////////8BBRJjbGFpbWFibGVEaXZpZGVuZHMFA2FtdAkAlAoCCQDOCAIJAQpzeW5jVG90YWxzBAAAAAAJAQEtAQUEZGlmZgUEZGlmZgkAzAgCCQEOU2NyaXB0VHJhbnNmZXIDCAUBaQZjYWxsZXIFBGRpZmYFB2Fzc2V0SWQFA25pbAUEZGlmZgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpAQtmb3JjZVVwZGF0ZQAEBWFkbWluCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAJ0IAgUNY29uZmlnQWRkcmVzcwIFYWRtaW4CGnJlc2VydmU6bm8gYWRtaW4gaW4gY29uZmlnAwkBAiE9AgkApQgBCAUBaQZjYWxsZXIFBWFkbWluCQACAQIRb25seSBhZG1pbiBjYW4gZG8JAQpzeW5jVG90YWxzBAAAAAAAAAAAAWkBCmluaXRpYWxpemUFCmNmZ0FkZHJlc3MOYXNzZXRJZE9yV2F2ZXMKYVRva2VuTmFtZRFhVG9rZW5EZXNjcmlwdGlvbg5hVG9rZW5EZWNpbWFscwQGY2hlY2tzAwUObm90SW5pdGlhbGl6ZWQJARBpc0Fzc2V0SWRPcldhdmVzAQUOYXNzZXRJZE9yV2F2ZXMHAwkAAAIFBmNoZWNrcwUGY2hlY2tzBAZhVG9rZW4JAMIIBQUKYVRva2VuTmFtZQURYVRva2VuRGVzY3JpcHRpb24AAAUOYVRva2VuRGVjaW1hbHMGCQDMCAIFBmFUb2tlbgkAzAgCCQEId3JpdGVJbnQCBRNhVG9rZW5EZWNpbWFsc1N0b3JlBQ5hVG9rZW5EZWNpbWFscwkAzAgCCQELd3JpdGVTdHJpbmcCBQ9hVG9rZW5OYW1lU3RvcmUFCmFUb2tlbk5hbWUJAMwIAgkBC3dyaXRlU3RyaW5nAgUMYXNzZXRJZFN0b3JlBQ5hc3NldElkT3JXYXZlcwkAzAgCCQELd3JpdGVTdHJpbmcCBRJjb25maWdBZGRyZXNzU3RvcmUFCmNmZ0FkZHJlc3MJAMwIAgkBC3dyaXRlU3RyaW5nAgUNYVRva2VuSWRTdG9yZQkA2AQBCQC4CAEFBmFUb2tlbgUDbmlsCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBC2luaXRpYWxpemUyAAMJAQIhPQIIBQFpBmNhbGxlcgUEdGhpcwkAAgECFm9ubHkgc2VsZiBjYW4gY29udGludWUJAMwIAgkBC1N0cmluZ0VudHJ5AgUScmVzZXJ2ZUdsb2JhbFN0b3JlCQCsAgIJAKQDAQUGSEVJR0hUAgR8fHx8BQNuaWwBaQEOdXNlckRlcG9zaXRVU0QBB2FkZHJlc3MJAJQKAgUDbmlsCQEKYXNzZXRUb1VzZAEJAQ1hVG9rZW5Ub0Fzc2V0AQkBDWFUb2tlbkJhbGFuY2UBBQdhZGRyZXNzAWkBC3VzZXJEZWJ0VVNEAQdhZGRyZXNzCQCUCgIFA25pbAkBCmFzc2V0VG9Vc2QBCQEPY3VycmVudFVzZXJEZWJ0AQUHYWRkcmVzcwFpAQt1c2VyQmFsYW5jZQEHYWRkcmVzcwQHYXRva2VucwkBDWFUb2tlbkJhbGFuY2UBBQdhZGRyZXNzBAVhc3NldAkBDWFUb2tlblRvQXNzZXQBBQdhdG9rZW5zBARkZWJ0CQEPY3VycmVudFVzZXJEZWJ0AQUHYWRkcmVzcwkAlAoCBQNuaWwJAJgKBgUHYXRva2VucwUFYXNzZXQJAQphc3NldFRvVXNkAQUFYXNzZXQFBGRlYnQJAQphc3NldFRvVXNkAQUEZGVidAkBC3ZhbHVlT3JFbHNlAgkAmwgCBQR0aGlzCQEUdXNlQXNDb2xsYXRlcmFsU3RvcmUBBQdhZGRyZXNzBgFpAQh1c2VyRGVidAEHYWRkcmVzcwQEZGVidAkBD2N1cnJlbnRVc2VyRGVidAEFB2FkZHJlc3MEB2RlYnRVc2QJAQphc3NldFRvVXNkAQUEZGVidAkAlAoCBQNuaWwJAJQKAgUEZGVidAUHZGVidFVzZAFpAQ1hc3NldFVzZFZhbHVlAQthc3NldEFtb3VudAkAlAoCBQNuaWwJAQphc3NldFRvVXNkAQULYXNzZXRBbW91bnQBaQEIcmVwYXlGb3IBC3VzZXJBZGRyZXNzBAZjaGVja3MJAQhtYWluT25seQEFAWkDCQAAAgUGY2hlY2tzBQZjaGVja3MJAQlyZXBheVVzZXICBQt1c2VyQWRkcmVzcwkBDXBheW1lbnRBbW91bnQCBQFpBQdhc3NldElkCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBCmRlcG9zaXRGb3ICCWRlcG9zaXRvcg91c2VBc0NvbGxhdGVyYWwEBmNoZWNrcwMJAQhtYWluT25seQEFAWkJAQlvcEFsbG93ZWQBAgdkZXBvc2l0BwMJAAACBQZjaGVja3MFBmNoZWNrcwMDCQBmAgkBD2N1cnJlbnRVc2VyRGVidAEFCWRlcG9zaXRvcgAACQEBIQEFD3VzZUFzQ29sbGF0ZXJhbAcJAAIBAjhjYW4ndCBkaXNhYmxlIHVzZSBhcyBjb2xsYXRlcmFsIGZvciBhc3NldCB3aXRoIG9wZW4gZGVidAQGYW1vdW50CQENcGF5bWVudEFtb3VudAIFAWkFB2Fzc2V0SWQEDGFUb2tlbkFtb3VudAkBDWFzc2V0VG9BVG9rZW4BBQZhbW91bnQJAM4IAgkBCnN5bmNUb3RhbHMEBQZhbW91bnQAAAAAAAAJAMwIAgkBCGNoYW5nZUJ5AgUWYVRva2VuQ2lyY3VsYXRpb25TdG9yZQUMYVRva2VuQW1vdW50CQDMCAIJAQhjaGFuZ2VCeQIJARJhVG9rZW5CYWxhbmNlU3RvcmUBBQlkZXBvc2l0b3IFDGFUb2tlbkFtb3VudAkAzAgCCQEMQm9vbGVhbkVudHJ5AgkBFHVzZUFzQ29sbGF0ZXJhbFN0b3JlAQUJZGVwb3NpdG9yBQ91c2VBc0NvbGxhdGVyYWwFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpAQt3aXRoZHJhd0ZvcgIHYWRkcmVzcwZhbW91bnQJARB3aXRoZHJhd0ludGVybmFsBAUBaQUHYWRkcmVzcwUGYW1vdW50BwFpAQ53aXRoZHJhd1RvTWFpbgIEdXNlcgZhbW91bnQDCQECIT0CBQZhbW91bnQA////////////AQkAAgECJnJlc2VydmU6IHdpdGhkcmF3VG9NYWluIGFtb3VudCAtMSBvbmx5CQEQd2l0aGRyYXdJbnRlcm5hbAQFAWkFBHVzZXIFBmFtb3VudAYBaQEWcmVwbGVuaXNoV2l0aEF0b2tlbkZvcgEEdXNlcgkBEXJlcGxlbmlzaEludGVybmFsAwIRcmVwbGVuaXNoX2F0b2tlbnMFBHVzZXIFAWkBaQEecmVwbGVuaXNGb3JVbmxvY2tXaXRoQXRva2VuRm9yAQR1c2VyCQERcmVwbGVuaXNoSW50ZXJuYWwDAhhyZXBsZW5pc2hfYXRva2Vuc191bmxvY2sFBHVzZXIFAWkBaQEecmVwbGVuaXNoRm9yUmVwYXlXaXRoQXRva2VuRm9yAQR1c2VyCQERcmVwbGVuaXNoSW50ZXJuYWwDAg1yZXBheV9hdG9rZW5zBQR1c2VyBQFpAWkBCWJvcnJvd0ZvcgIHYWRkcmVzcw5hbW91bnRUb0JvcnJvdwQGY2hlY2tzAwMJAQhtYWluT25seQEFAWkJAQ5saXF1aWRpdHlDaGVjawMFDmFtb3VudFRvQm9ycm93CQBlAgUSc3RvcmVkVG90YWxEZXBvc2l0BQ9zdG9yZWRUb3RhbERlYnQCGXRvbyBtdWNoIGJvcnJvdyByZXF1ZXN0ZWQHCQEJb3BBbGxvd2VkAQIGYm9ycm93BwMJAAACBQZjaGVja3MFBmNoZWNrcwQLY3VycmVudERlYnQJAQ9jdXJyZW50VXNlckRlYnQBBQdhZGRyZXNzBAduZXdEZWJ0CQBkAgULY3VycmVudERlYnQFDmFtb3VudFRvQm9ycm93CQDOCAIJAQpzeW5jVG90YWxzBAAABQ5hbW91bnRUb0JvcnJvdwAABQ5hbW91bnRUb0JvcnJvdwkAzAgCCQEId3JpdGVJbnQCCQEJZGVidFN0b3JlAQUHYWRkcmVzcwUHbmV3RGVidAkAzAgCCQEJZW5hYmxlQ29sAQUHYWRkcmVzcwkAzAgCCQEId3JpdGVJbnQCCQEOZGVidEluZGV4U3RvcmUBBQdhZGRyZXNzBQxjdXJyZW50SW5kZXgJAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwkBEUBleHRyTmF0aXZlKDEwNjIpAQUHYWRkcmVzcwUOYW1vdW50VG9Cb3Jyb3cFB2Fzc2V0SWQFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpAQ1taW50QXRva2VuRm9yAgdhZGRyZXNzDGFtb3VudFRvTWludAkBDG1pbnRJbnRlcm5hbAUFAWkFB2FkZHJlc3MFDGFtb3VudFRvTWludAUHYWRkcmVzcwIMbWludF9hdG9rZW5zAWkBD21pbnRBdG9rZW5Gb3JUbwMEZnJvbQxhbW91bnRUb01pbnQCdG8JAQxtaW50SW50ZXJuYWwFBQFpBQRmcm9tBQxhbW91bnRUb01pbnQFAnRvAhFsb2NrX21pbnRfYXRva2VucwFpARByZWRlZW1BdG9rZW5zRm9yAQR1c2VyBAZjaGVja3MDCQEIbWFpbk9ubHkBBQFpCQEJb3BBbGxvd2VkAQIOcmVkZWVtX2F0b2tlbnMHAwkAAAIFBmNoZWNrcwUGY2hlY2tzBAxhVG9rZW5BbW91bnQJAQ1wYXltZW50QW1vdW50AgUBaQUIYVRva2VuSWQECW91dEFtb3VudAkBDWFUb2tlblRvQXNzZXQBBQxhVG9rZW5BbW91bnQJAJQKAgkAzggCCQEKc3luY1RvdGFscwQJAQEtAQUJb3V0QW1vdW50AAAAAAUJb3V0QW1vdW50CQDMCAIJAQ5TY3JpcHRUcmFuc2ZlcgMJARFAZXh0ck5hdGl2ZSgxMDYyKQEFBHVzZXIFCW91dEFtb3VudAUHYXNzZXRJZAkAzAgCCQEIY2hhbmdlQnkCBRZhVG9rZW5DaXJjdWxhdGlvblN0b3JlCQEBLQEFDGFUb2tlbkFtb3VudAkAzAgCCQEEQnVybgIFCGFUb2tlbklkBQxhVG9rZW5BbW91bnQFA25pbAUJb3V0QW1vdW50CQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBEnRyYW5zZmVyQVRva2Vuc0ZvcgMEZnJvbQJ0bwh2YWx1ZVVzZAQGY2hlY2tzAwkBCG1haW5Pbmx5AQUBaQkBCW9wQWxsb3dlZAECDXRyYW5zZmVyX2RlYnQHAwkAAAIFBmNoZWNrcwUGY2hlY2tzBAZhc3NldHMJAQp1c2RUb0Fzc2V0AQUIdmFsdWVVc2QEB2F0b2tlbnMJAQ1hc3NldFRvQVRva2VuAQUGYXNzZXRzBAthVG9rZW5zRnJvbQkBDWFUb2tlbkJhbGFuY2UBBQRmcm9tAwkAZgIFB2F0b2tlbnMFC2FUb2tlbnNGcm9tCQACAQkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICAhl0cmFuc2ZlckF0b2tlbnNGb3IgZXJyb3I6AhQgdHJhbnNmZXIudmFsdWVVc2Q6IAkApAMBBQh2YWx1ZVVzZAISIHRyYW5zZmVyLmFzc2V0czogCQCkAwEFBmFzc2V0cwITIHRyYW5zZmVyLmF0b2tlbnM6IAkApAMBBQdhdG9rZW5zAg8gZnJvbS5hdG9rZW5zOiAJAKQDAQULYVRva2Vuc0Zyb20CBCBhdCAJAKUIAQUEdGhpcwkAlAoCCQDOCAIJAM4IAgkBCnN5bmNUb3RhbHMEAAAAAAAAAAAJAMwIAgkBCGNoYW5nZUJ5AgkBEmFUb2tlbkJhbGFuY2VTdG9yZQEFBGZyb20JAQEtAQUHYXRva2VucwkAzAgCCQEIY2hhbmdlQnkCCQESYVRva2VuQmFsYW5jZVN0b3JlAQUCdG8FB2F0b2tlbnMFA25pbAkBEWVuYWJsZUNvbElmTmVlZGVkAQUCdG8JAQ1hVG9rZW5Ub0Fzc2V0AQUHYXRva2VucwkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpAQ90cmFuc2ZlckRlYnRGb3IDBGZyb20CdG8GYW1vdW50BAZjaGVja3MDCQEIbWFpbk9ubHkBBQFpCQEJb3BBbGxvd2VkAQINdHJhbnNmZXJfZGVidAcDCQAAAgUGY2hlY2tzBQZjaGVja3MJAJQKAgkAzggCCQEKc3luY1RvdGFscwQAAAAAAAAAAAkAzAgCCQEId3JpdGVJbnQCCQEJZGVidFN0b3JlAQUEZnJvbQkAZQIJAQ9jdXJyZW50VXNlckRlYnQBBQRmcm9tBQZhbW91bnQJAMwIAgkBCHdyaXRlSW50AgkBCWRlYnRTdG9yZQEFAnRvCQBkAgkBD2N1cnJlbnRVc2VyRGVidAEFAnRvBQZhbW91bnQJAMwIAgkBCHdyaXRlSW50AgkBDmRlYnRJbmRleFN0b3JlAQUEZnJvbQUMY3VycmVudEluZGV4CQDMCAIJAQh3cml0ZUludAIJAQ5kZWJ0SW5kZXhTdG9yZQEFAnRvBQxjdXJyZW50SW5kZXgJAMwIAgkBCWVuYWJsZUNvbAEFAnRvBQNuaWwFBmFtb3VudAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpARlkaXNhYmxlVXNlQXNDb2xsYXRlcmFsRm9yAQdhZGRyZXNzBAZjaGVja3MDCQEIbWFpbk9ubHkBBQFpCQEJb3BBbGxvd2VkAQIKdXNlX2FzX2NvbAcDCQAAAgUGY2hlY2tzBQZjaGVja3MDCQBmAgkBD2N1cnJlbnRVc2VyRGVidAEFB2FkZHJlc3MAAAkAAgECMWNhbid0IGRpc2FibGUgY29sbGF0ZXJhbCBmb3IgYXNzZXQgd2l0aCBvcGVuIGRlYnQJAM4IAgkBCnN5bmNUb3RhbHMEAAAAAAAAAAAJAMwIAgkBDEJvb2xlYW5FbnRyeQIJARR1c2VBc0NvbGxhdGVyYWxTdG9yZQEFB2FkZHJlc3MHBQNuaWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQEVZW5hYmxlVXNlQXNDb2xsYXRlcmFsAAQGY2hlY2tzCQEJb3BBbGxvd2VkAQIKdXNlX2FzX2NvbAMJAAACBQZjaGVja3MFBmNoZWNrcwkAzggCCQEKc3luY1RvdGFscwQAAAAAAAAAAAkAzAgCCQEJZW5hYmxlQ29sAQkApQgBCAUBaQZjYWxsZXIFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpAQtjb2xsYXBzZUZvcgEEdXNlcgQGY2hlY2tzAwkBCG1haW5Pbmx5AQUBaQkBCW9wQWxsb3dlZAECDmZvcmNlX2NvbGxhcHNlBwMJAAACBQZjaGVja3MFBmNoZWNrcwkBDGNvbGxhcHNlVXNlcgIFBHVzZXIA////////////AQkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpARFjb2xsYXBzZUZvckFtb3VudAIEdXNlcgZhbW91bnQEBmNoZWNrcwMJAQhtYWluT25seQEFAWkJAQlvcEFsbG93ZWQBAghjb2xsYXBzZQcDCQAAAgUGY2hlY2tzBQZjaGVja3MJAQxjb2xsYXBzZVVzZXICBQR1c2VyBQZhbW91bnQJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQEHbHBWYWx1ZQEMYVRva2VuQW1vdW50CQCUCgIFA25pbAkBDWFUb2tlblRvQXNzZXQBBQxhVG9rZW5BbW91bnQAJrp8hg==", "chainId": 87, "height": 3266819, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: FweaDLJ5BJoaRrU3UmHndBmK2gU6KcXBP4w9XJ5iqKxg Next: 3oDLAUbtsprgUDnexLwFqwGDtPctfbzJLLP1jLznHudG Diff:
OldNewDifferences
1818 func writeInt (key,value) = if ((0 > value))
1919 then throw(((("writing negative value " + toString(value)) + " for key ") + key))
2020 else IntegerEntry(key, value)
21+
22+
23+func ensureGE0 (value) = if ((0 > value))
24+ then throw("writing negative value")
25+ else value
2126
2227
2328 func asInt (value) = match value {
7681
7782 let aTokenCirculationStore = "aTokenCirculation"
7883
79-let lastUpdateHeightStore = "lastUpdateHeight"
84+let aTokenDecimalsStore = "aTokenDecimals"
8085
81-let totalDebtStore = "totalBorrow"
86+let reserveGlobalStore = "reserveGlobalData"
8287
83-let totalDepositStore = "totalDeposit"
88+let reserveGlobal = valueOrElse(getString(reserveGlobalStore), "||||")
8489
85-let totalReserveStore = "totalReserve"
90+let reserveGlobalData = split(reserveGlobal, "|")
8691
87-let indexStore = "storedIndex"
92+let lastUpdateHeight = valueOrErrorMessage(valueOrElse(parseInt(reserveGlobalData[0]), getI("lastUpdateHeight")), "no lastUpdateHeight")
8893
89-let aTokenDecimalsStore = "aTokenDecimals"
94+let storedTotalDeposit = valueOrElse(parseInt(reserveGlobalData[1]), valueOrElse(getI("totalDeposit"), 0))
95+
96+let storedTotalDebt = valueOrElse(parseInt(reserveGlobalData[2]), valueOrElse(getI("totalBorrow"), 0))
97+
98+let storedTotalReserve = valueOrElse(parseInt(reserveGlobalData[3]), valueOrElse(getI("totalReserve"), 0))
99+
100+let storedIndex = valueOrElse(parseInt(reserveGlobalData[4]), valueOrElse(getI("storedIndex"), RBase))
90101
91102 func aTokenBalanceStore (userAddress) = (userAddress + "_aTokenBalance")
92103
164175
165176 let HEIGHT = height
166177
167-let lastUpdateHeight = valueOrErrorMessage(getI(lastUpdateHeightStore), "no lastUpdateHeight")
168-
169178 let aTokenId = fromBase58String(valueOrErrorMessage(getS(aTokenIdStore), "no aTokenId"))
170179
171180 let aTokenCirculation = valueOrElse(getI(aTokenCirculationStore), 0)
179188 let accountHealthOverlap = valueOrErrorMessage(getInteger(configAddress, overlapChargeStore), "no overlapCharge")
180189
181190 let liquidationPenalty = valueOrErrorMessage(getInteger(configAddress, liquidationPenaltyStore), "no liquidationPenalty")
182-
183-let storedTotalDeposit = valueOrElse(getI(totalDepositStore), 0)
184-
185-let storedTotalReserve = valueOrElse(getI(totalReserveStore), 0)
186-
187-let storedTotalDebt = valueOrElse(getI(totalDebtStore), 0)
188-
189-let storedIndex = valueOrElse(getI(indexStore), RBase)
190191
191192 let utilization = if ((storedTotalDeposit > 0))
192193 then min([factorsBase, fraction(storedTotalDebt, factorsBase, storedTotalDeposit)])
284285 then invoke(stakingAddress, "put", nil, [AttachedPayment(assetId, (actualBalance - keepAtBalance))])
285286 else invoke(stakingAddress, "get", [(keepAtBalance - actualBalance)], nil)
286287 if ((stakingAction == stakingAction))
287- then [writeInt(indexStore, currentIndex), writeInt(lastUpdateHeightStore, HEIGHT), writeInt(totalDepositStore, (currentTotalDeposit + additionalDeposit)), writeInt(totalDebtStore, (currentTotalDebt + additionalDebt)), writeInt(totalReserveStore, (currentTotalReserve + additionalReserve))]
288+ then {
289+ let deposit = ensureGE0((currentTotalDeposit + additionalDeposit))
290+ let debt = ensureGE0((currentTotalDebt + additionalDebt))
291+ let reserve = ensureGE0((currentTotalReserve + additionalReserve))
292+[writeString(reserveGlobalStore, ((((((((toString(HEIGHT) + "|") + toString(deposit)) + "|") + toString(debt)) + "|") + toString(reserve)) + "|") + toString(currentIndex)))]
293+ }
288294 else throw("Strict value is not equal to itself.")
289295 }
290296
361367 let currentDebt = currentUserDebt(userAddress)
362368 if ((currentDebt == currentDebt))
363369 then {
364- let $t01125711560 = if ((amount > currentDebt))
370+ let $t01178312086 = if ((amount > currentDebt))
365371 then $Tuple4(0, -(currentDebt), (amount - currentDebt), [ScriptTransfer(addressFromStringValue(userAddress), (amount - currentDebt), assetId)])
366372 else $Tuple4((currentDebt - amount), -(amount), 0, nil)
367- let newDebt = $t01125711560._1
368- let totalDebtUpdate = $t01125711560._2
369- let payout = $t01125711560._3
370- let actions = $t01125711560._4
373+ let newDebt = $t01178312086._1
374+ let totalDebtUpdate = $t01178312086._2
375+ let payout = $t01178312086._3
376+ let actions = $t01178312086._4
371377 let repaid = (amount - payout)
372378 $Tuple2(((syncTotals(0, totalDebtUpdate, 0, payout) ++ actions) ++ [writeInt(debtStore(userAddress), newDebt), writeInt(debtIndexStore(userAddress), currentIndex)]), repaid)
373379 }
420426 else false
421427 if ((checks == checks))
422428 then {
423- let $t01544215633 = if ((amount == -1))
429+ let $t01596816159 = if ((amount == -1))
424430 then {
425431 let atokens = aTokenBalance(user)
426432 $Tuple2(atokens, aTokenToAsset(atokens))
427433 }
428434 else $Tuple2(assetToATokenCeil(amount), amount)
429- let removedAtokens = $t01544215633._1
430- let withdrawAmount = $t01544215633._2
435+ let removedAtokens = $t01596816159._1
436+ let withdrawAmount = $t01596816159._2
431437 $Tuple2((syncTotals(-(withdrawAmount), 0, 0, withdrawAmount) ++ [ScriptTransfer(if (toMain)
432438 then mainContract
433439 else addressFromStringValue(user), withdrawAmount, assetId), changeBy(aTokenBalanceStore(user), -(removedAtokens)), changeBy(aTokenCirculationStore, -(removedAtokens))]), withdrawAmount)
473479
474480
475481 @Callable(i)
482+func storedDepositBorrow () = $Tuple2(nil, $Tuple2(storedTotalDeposit, storedTotalDebt))
483+
484+
485+
486+@Callable(i)
476487 func getCurrentTotals (user) = $Tuple2(nil, userTotals(user))
477488
478489
479490
480491 @Callable(i)
481492 func getCurrentTotals2 (user1,user2) = {
482- let $t01722717264 = userTotals(user1)
483- let d1 = $t01722717264._1
484- let d2 = $t01722717264._2
485- let d3 = $t01722717264._3
486- let d4 = $t01722717264._4
487- let $t01726917306 = userTotals(user2)
488- let e1 = $t01726917306._1
489- let e2 = $t01726917306._2
490- let e3 = $t01726917306._3
491- let e4 = $t01726917306._4
493+ let $t01784017877 = userTotals(user1)
494+ let d1 = $t01784017877._1
495+ let d2 = $t01784017877._2
496+ let d3 = $t01784017877._3
497+ let d4 = $t01784017877._4
498+ let $t01788217919 = userTotals(user2)
499+ let e1 = $t01788217919._1
500+ let e2 = $t01788217919._2
501+ let e3 = $t01788217919._3
502+ let e4 = $t01788217919._4
492503 $Tuple2(nil, $Tuple6(d1, d2, d3, d4, e3, e4))
493504 }
494505
578589 @Callable(i)
579590 func initialize2 () = if ((i.caller != this))
580591 then throw("only self can continue")
581- else [writeInt(lastUpdateHeightStore, HEIGHT)]
592+ else [StringEntry(reserveGlobalStore, (toString(HEIGHT) + "||||"))]
582593
583594
584595
660671
661672 @Callable(i)
662673 func replenishWithAtokenFor (user) = replenishInternal("replenish_atokens", user, i)
674+
675+
676+
677+@Callable(i)
678+func replenisForUnlockWithAtokenFor (user) = replenishInternal("replenish_atokens_unlock", user, i)
663679
664680
665681
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 throwIf (condition,error) = if (condition)
1414 then throw(error)
1515 else true
1616
1717
1818 func writeInt (key,value) = if ((0 > value))
1919 then throw(((("writing negative value " + toString(value)) + " for key ") + key))
2020 else IntegerEntry(key, value)
21+
22+
23+func ensureGE0 (value) = if ((0 > value))
24+ then throw("writing negative value")
25+ else value
2126
2227
2328 func asInt (value) = match value {
2429 case int: Int =>
2530 int
2631 case _ =>
2732 throw("r:1")
2833 }
2934
3035
3136 func changeBy (key,value) = writeInt(key, (valueOrElse(getI(key), 0) + value))
3237
3338
3439 func writeString (key,value) = StringEntry(key, value)
3540
3641
3742 func fractionCeil (value,numerator,denominator) = {
3843 let cand = fraction(value, numerator, denominator)
3944 let D = 3037000499
4045 let exact = ((((cand % D) * (denominator % D)) % D) == (((value % D) * (numerator % D)) % D))
4146 if (exact)
4247 then cand
4348 else (cand + 1)
4449 }
4550
4651
4752 let BlocksPerYear = 525600
4853
4954 let RBase = 10000000000000000
5055
5156 let factorsBase = 1000
5257
5358 let assetIdStore = "assetId"
5459
5560 let assetIdStr = valueOrErrorMessage(getS(assetIdStore), "no assetId")
5661
5762 let assetId = if ((assetIdStr == "WAVES"))
5863 then unit
5964 else fromBase58String(assetIdStr)
6065
6166 let reserveFactorStore = (assetIdStr + "_ReserveFactor")
6267
6368 let collateralFactorStore = (assetIdStr + "_CollateralFactor")
6469
6570 let liquidationThresholdStore = (assetIdStr + "_LiquidationThreshold")
6671
6772 let overlapChargeStore = "account_health_overlap"
6873
6974 let liquidationPenaltyStore = (assetIdStr + "_LiquidationPenalty")
7075
7176 let configAddressStore = "configAddress"
7277
7378 let aTokenIdStore = "aTokenId"
7479
7580 let aTokenNameStore = "aTokenName"
7681
7782 let aTokenCirculationStore = "aTokenCirculation"
7883
79-let lastUpdateHeightStore = "lastUpdateHeight"
84+let aTokenDecimalsStore = "aTokenDecimals"
8085
81-let totalDebtStore = "totalBorrow"
86+let reserveGlobalStore = "reserveGlobalData"
8287
83-let totalDepositStore = "totalDeposit"
88+let reserveGlobal = valueOrElse(getString(reserveGlobalStore), "||||")
8489
85-let totalReserveStore = "totalReserve"
90+let reserveGlobalData = split(reserveGlobal, "|")
8691
87-let indexStore = "storedIndex"
92+let lastUpdateHeight = valueOrErrorMessage(valueOrElse(parseInt(reserveGlobalData[0]), getI("lastUpdateHeight")), "no lastUpdateHeight")
8893
89-let aTokenDecimalsStore = "aTokenDecimals"
94+let storedTotalDeposit = valueOrElse(parseInt(reserveGlobalData[1]), valueOrElse(getI("totalDeposit"), 0))
95+
96+let storedTotalDebt = valueOrElse(parseInt(reserveGlobalData[2]), valueOrElse(getI("totalBorrow"), 0))
97+
98+let storedTotalReserve = valueOrElse(parseInt(reserveGlobalData[3]), valueOrElse(getI("totalReserve"), 0))
99+
100+let storedIndex = valueOrElse(parseInt(reserveGlobalData[4]), valueOrElse(getI("storedIndex"), RBase))
90101
91102 func aTokenBalanceStore (userAddress) = (userAddress + "_aTokenBalance")
92103
93104
94105 func debtStore (userAddress) = (userAddress + "_debt")
95106
96107
97108 func debtIndexStore (userAddress) = (userAddress + "_index")
98109
99110
100111 func useAsCollateralStore (userAddress) = (userAddress + "_useAsCollateral")
101112
102113
103114 func getBalance (addressOrAlias,assetId) = match assetId {
104115 case bv: ByteVector =>
105116 assetBalance(addressOrAlias, bv)
106117 case u: Unit =>
107118 wavesBalance(addressOrAlias).available
108119 case _ =>
109120 throw("Match error")
110121 }
111122
112123
113124 let assetDecimals = valueOrErrorMessage(getI(aTokenDecimalsStore), "no assetDecimals")
114125
115126 let configAddress = valueOrErrorMessage(addressFromString(valueOrErrorMessage(getString(this, configAddressStore), "reserve: no configAddress")), "invalid config address")
116127
117128 func opAllowed (op) = match invoke(configAddress, "opAllowed", [assetIdStr, op], nil) {
118129 case b: Boolean =>
119130 if (b)
120131 then true
121132 else throw("not allowed")
122133 case _ =>
123134 throw("opAllowed: unexpected result type")
124135 }
125136
126137
127138 let mainContract = valueOrErrorMessage(addressFromString(split(valueOrErrorMessage(getString(configAddress, "main"), "no main in config"), "|")[0]), "invalid main address")
128139
129140 func mainOnly (i) = if (contains(getStringValue(configAddress, "main"), toString(i.caller)))
130141 then true
131142 else throw("only main can do")
132143
133144
134145 func divAdminOnly (i) = {
135146 let divAdmins = valueOrErrorMessage(getString(configAddress, "divAdmins"), "no div admins")
136147 if (!(contains(divAdmins, toString(i.caller))))
137148 then throw("only div admin can do")
138149 else true
139150 }
140151
141152
142153 func isAssetIdOrWaves (value) = if (if ((value != "WAVES"))
143154 then (fromBase58String(value) == fromBase58String(""))
144155 else false)
145156 then throw("invalid assetId")
146157 else true
147158
148159
149160 let notInitialized = throwIf(isDefined(getS(assetIdStore)), "already initialized")
150161
151162 let maybeOracleAddress = match getString(configAddress, "oracle_address") {
152163 case s: String =>
153164 addressFromString(s)
154165 case _ =>
155166 unit
156167 }
157168
158169 let oraclePrice = match invoke(valueOrErrorMessage(maybeOracleAddress, "no oracle"), "price", [assetIdStr], nil) {
159170 case i: Int =>
160171 i
161172 case _ =>
162173 throw("bad oracle data")
163174 }
164175
165176 let HEIGHT = height
166177
167-let lastUpdateHeight = valueOrErrorMessage(getI(lastUpdateHeightStore), "no lastUpdateHeight")
168-
169178 let aTokenId = fromBase58String(valueOrErrorMessage(getS(aTokenIdStore), "no aTokenId"))
170179
171180 let aTokenCirculation = valueOrElse(getI(aTokenCirculationStore), 0)
172181
173182 let reserveFactor = valueOrErrorMessage(getInteger(configAddress, reserveFactorStore), "no reserveFactor")
174183
175184 let collateralFactor = valueOrErrorMessage(getInteger(configAddress, collateralFactorStore), "no collateralFactor")
176185
177186 let liquidationThreshold = valueOrErrorMessage(getInteger(configAddress, liquidationThresholdStore), "no liquidationThreshold")
178187
179188 let accountHealthOverlap = valueOrErrorMessage(getInteger(configAddress, overlapChargeStore), "no overlapCharge")
180189
181190 let liquidationPenalty = valueOrErrorMessage(getInteger(configAddress, liquidationPenaltyStore), "no liquidationPenalty")
182-
183-let storedTotalDeposit = valueOrElse(getI(totalDepositStore), 0)
184-
185-let storedTotalReserve = valueOrElse(getI(totalReserveStore), 0)
186-
187-let storedTotalDebt = valueOrElse(getI(totalDebtStore), 0)
188-
189-let storedIndex = valueOrElse(getI(indexStore), RBase)
190191
191192 let utilization = if ((storedTotalDeposit > 0))
192193 then min([factorsBase, fraction(storedTotalDebt, factorsBase, storedTotalDeposit)])
193194 else 0
194195
195196 let apr = {
196197 let a = getIntegerValue(configAddress, (assetIdStr + "_APoint"))
197198 let b = getIntegerValue(configAddress, (assetIdStr + "_BPoint"))
198199 let c = getIntegerValue(configAddress, (assetIdStr + "_CPoint"))
199200 let d = getIntegerValue(configAddress, (assetIdStr + "_DPoint"))
200201 let lineAC = (fraction((a - c), utilization, -(b)) + a)
201202 let lineCD = (fraction((c - d), (utilization - b), (b - factorsBase)) + c)
202203 if ((utilization == 0))
203204 then a
204205 else if ((utilization == b))
205206 then c
206207 else if (if ((b > utilization))
207208 then true
208209 else (b == factorsBase))
209210 then lineAC
210211 else lineCD
211212 }
212213
213214 let apy = if ((storedTotalDeposit == 0))
214215 then 0
215216 else fraction(fraction(storedTotalDebt, apr, storedTotalDeposit), (factorsBase - reserveFactor), factorsBase)
216217
217218 let currentIndex = if ((HEIGHT == lastUpdateHeight))
218219 then storedIndex
219220 else {
220221 let bpr = fractionCeil(apr, RBase, (BlocksPerYear * factorsBase))
221222 fractionCeil(storedIndex, (RBase + (bpr * (HEIGHT - lastUpdateHeight))), RBase)
222223 }
223224
224225 let stakingEnabled = valueOrElse(getBoolean(configAddress, ("staking_enabled_" + assetIdStr)), false)
225226
226227 let actualBalance = match assetId {
227228 case aid: ByteVector =>
228229 assetBalance(this, aid)
229230 case _ =>
230231 wavesBalance(this).available
231232 }
232233
233234 func liquidityCheck (amount,max,err) = if ((amount > max))
234235 then throw(("not enough liquidity: " + err))
235236 else true
236237
237238
238239 func storedUserDebt (userAddress) = valueOrElse(getI(debtStore(userAddress)), 0)
239240
240241
241242 func currentUserDebt (userAddress) = {
242243 let v = storedUserDebt(userAddress)
243244 if ((v == 0))
244245 then 0
245246 else {
246247 let storedUserIndex = valueOrErrorMessage(getI(debtIndexStore(userAddress)), "has debt but does not have index")
247248 fraction(v, currentIndex, storedUserIndex)
248249 }
249250 }
250251
251252
252253 let currentTotalDebt = fraction(storedTotalDebt, currentIndex, storedIndex)
253254
254255 let addedDebt = (currentTotalDebt - storedTotalDebt)
255256
256257 let addedDeposit = fraction(addedDebt, (factorsBase - reserveFactor), factorsBase)
257258
258259 let currentTotalDeposit = (storedTotalDeposit + addedDeposit)
259260
260261 let currentTotalReserve = ((storedTotalReserve + addedDebt) - addedDeposit)
261262
262263 let stakingAddress = valueOrErrorMessage(addressFromString(valueOrErrorMessage(getString(configAddress, ("staking_config_" + assetIdStr)), ("no staking address for " + assetIdStr))), ("bad staking address for " + assetIdStr))
263264
264265 let claimableDividends = min([currentTotalReserve, if (stakingEnabled)
265266 then asInt(invoke(stakingAddress, "info", nil, nil))
266267 else actualBalance])
267268
268269 func paymentAmount (i,assetId) = {
269270 let p = i.payments[0].amount
270271 if ((0 >= p))
271272 then throw(("Payment is less than min allowed amount: " + toString(p)))
272273 else if ((i.payments[0].assetId != assetId))
273274 then throw((" bad asset attached: required " + assetIdStr))
274275 else p
275276 }
276277
277278
278279 func syncTotals (additionalDeposit,additionalDebt,additionalReserve,keepAtBalance) = {
279280 let stakingAction = if ((actualBalance == keepAtBalance))
280281 then unit
281282 else if (!(stakingEnabled))
282283 then unit
283284 else if ((actualBalance > keepAtBalance))
284285 then invoke(stakingAddress, "put", nil, [AttachedPayment(assetId, (actualBalance - keepAtBalance))])
285286 else invoke(stakingAddress, "get", [(keepAtBalance - actualBalance)], nil)
286287 if ((stakingAction == stakingAction))
287- then [writeInt(indexStore, currentIndex), writeInt(lastUpdateHeightStore, HEIGHT), writeInt(totalDepositStore, (currentTotalDeposit + additionalDeposit)), writeInt(totalDebtStore, (currentTotalDebt + additionalDebt)), writeInt(totalReserveStore, (currentTotalReserve + additionalReserve))]
288+ then {
289+ let deposit = ensureGE0((currentTotalDeposit + additionalDeposit))
290+ let debt = ensureGE0((currentTotalDebt + additionalDebt))
291+ let reserve = ensureGE0((currentTotalReserve + additionalReserve))
292+[writeString(reserveGlobalStore, ((((((((toString(HEIGHT) + "|") + toString(deposit)) + "|") + toString(debt)) + "|") + toString(reserve)) + "|") + toString(currentIndex)))]
293+ }
288294 else throw("Strict value is not equal to itself.")
289295 }
290296
291297
292298 func pow10 (n) = if ((n == 6))
293299 then 1000000
294300 else if ((n == 8))
295301 then 100000000
296302 else throw(("bad decimals: " + toString(n)))
297303
298304
299305 func assetToUsd (amount) = fraction(amount, oraclePrice, pow10(assetDecimals))
300306
301307
302308 func usdToAsset (amount) = fraction(amount, pow10(assetDecimals), oraclePrice)
303309
304310
305311 func aTokenToAsset (aTokenAmount) = if ((aTokenAmount == 0))
306312 then 0
307313 else if ((aTokenCirculation > 0))
308314 then fraction(aTokenAmount, currentTotalDeposit, aTokenCirculation)
309315 else aTokenAmount
310316
311317
312318 func assetToAToken (assetAmount) = if ((assetAmount == 0))
313319 then 0
314320 else if ((aTokenCirculation > 0))
315321 then fraction(assetAmount, aTokenCirculation, currentTotalDeposit)
316322 else assetAmount
317323
318324
319325 func assetToATokenCeil (assetAmount) = if ((assetAmount == 0))
320326 then 0
321327 else if ((aTokenCirculation > 0))
322328 then fractionCeil(assetAmount, aTokenCirculation, currentTotalDeposit)
323329 else assetAmount
324330
325331
326332 func aTokenBalance (address) = valueOrElse(getI(aTokenBalanceStore(address)), 0)
327333
328334
329335 func enableCol (user) = BooleanEntry(useAsCollateralStore(user), true)
330336
331337
332338 func enableColIfNeeded (user) = if ((currentUserDebt(user) > 0))
333339 then [enableCol(user)]
334340 else nil
335341
336342
337343 func collapseUser (address,amount) = {
338344 let debt = currentUserDebt(address)
339345 let deposit = aTokenToAsset(aTokenBalance(address))
340346 let maxPossible = min([debt, deposit])
341347 let amt = if ((-1 > amount))
342348 then throw("invalid collapse amount")
343349 else if (if ((maxPossible == 0))
344350 then true
345351 else (amount == 0))
346352 then throw("nothing to collapse")
347353 else if (if ((amount == -1))
348354 then true
349355 else (amount > maxPossible))
350356 then maxPossible
351357 else amount
352358 let removedAtokens = assetToATokenCeil(amt)
353359 $Tuple2((syncTotals(-(amt), -(amt), 0, 0) ++ [changeBy(aTokenBalanceStore(address), -(removedAtokens)), changeBy(aTokenCirculationStore, -(removedAtokens)), writeInt(debtStore(address), (debt - amt)), writeInt(debtIndexStore(address), currentIndex)]), amt)
354360 }
355361
356362
357363 func repayUser (userAddress,amount) = {
358364 let checks = opAllowed("repay")
359365 if ((checks == checks))
360366 then {
361367 let currentDebt = currentUserDebt(userAddress)
362368 if ((currentDebt == currentDebt))
363369 then {
364- let $t01125711560 = if ((amount > currentDebt))
370+ let $t01178312086 = if ((amount > currentDebt))
365371 then $Tuple4(0, -(currentDebt), (amount - currentDebt), [ScriptTransfer(addressFromStringValue(userAddress), (amount - currentDebt), assetId)])
366372 else $Tuple4((currentDebt - amount), -(amount), 0, nil)
367- let newDebt = $t01125711560._1
368- let totalDebtUpdate = $t01125711560._2
369- let payout = $t01125711560._3
370- let actions = $t01125711560._4
373+ let newDebt = $t01178312086._1
374+ let totalDebtUpdate = $t01178312086._2
375+ let payout = $t01178312086._3
376+ let actions = $t01178312086._4
371377 let repaid = (amount - payout)
372378 $Tuple2(((syncTotals(0, totalDebtUpdate, 0, payout) ++ actions) ++ [writeInt(debtStore(userAddress), newDebt), writeInt(debtIndexStore(userAddress), currentIndex)]), repaid)
373379 }
374380 else throw("Strict value is not equal to itself.")
375381 }
376382 else throw("Strict value is not equal to itself.")
377383 }
378384
379385
380386 func getConfig () = {
381387 let a = getIntegerValue(configAddress, (assetIdStr + "_APoint"))
382388 let b = getIntegerValue(configAddress, (assetIdStr + "_BPoint"))
383389 let c = getIntegerValue(configAddress, (assetIdStr + "_CPoint"))
384390 let d = getIntegerValue(configAddress, (assetIdStr + "_DPoint"))
385391 ((((((((((((((("ABCD: " + toString(a)) + ";") + toString(b)) + ";") + toString(c)) + ";") + toString(d)) + ", reserveFactor: ") + toString(reserveFactor)) + ", collateralFactor: ") + toString(collateralFactor)) + ", liquidationThreshold: ") + toString(liquidationThreshold)) + ", liquidationPenalty: ") + toString(liquidationPenalty))
386392 }
387393
388394
389395 func getState () = ((((((((((((((((((((((((((("currentTotalDeposit: " + toString(currentTotalDeposit)) + ", storedTotalDeposit: ") + toString(storedTotalDeposit)) + ", currentTotalDebt: ") + toString(currentTotalDebt)) + ", storedTotalDebt: ") + toString(storedTotalDebt)) + ", currentTotalReserve: ") + toString(currentTotalReserve)) + ", storedTotalReserve: ") + toString(storedTotalReserve)) + ", currentIndex:") + toString(currentIndex)) + ", storedIndex: ") + toString(storedIndex)) + ", lastUpdateHeight: ") + toString(lastUpdateHeight)) + ", utilization: ") + toString(utilization)) + ", aTokenCirculation: ") + toString(aTokenCirculation)) + ", aTokenPrice: ") + toString(aTokenToAsset(pow(10, 0, assetDecimals, 0, 0, FLOOR)))) + ", APR: ") + toString(apr)) + ", APY: ") + toString(apy))
390396
391397
392398 func getUserState (user) = {
393399 let aBalance = aTokenBalance(user)
394400 let aBalanceWallet = getBalance(addressFromStringValue(user), aTokenId)
395401 ((((((((((((((((("currentDebt: " + toString(currentUserDebt(user))) + ", storedDebt: ") + toString(valueOrElse(getI(debtStore(user)), 0))) + ", currentDeposit: ") + toString(aTokenToAsset(aBalance))) + ", aTokenContractBalance: ") + toString(aBalance)) + ", aTokenWalletBalance: ") + toString(aBalanceWallet)) + ", walletStake: ") + toString(aTokenToAsset(aBalanceWallet))) + ", assetWalletBalance: ") + toString(getBalance(addressFromStringValue(user), assetId))) + ", useAsCollateral: ") + toString(valueOrElse(getBoolean(this, useAsCollateralStore(user)), true))) + ", storedIndex: ") + toString(valueOrElse(getI(debtIndexStore(user)), 0)))
396402 }
397403
398404
399405 func debugTotals () = ((((((((((((((((((((((("storedTotalDeposit: " + toString(storedTotalDeposit)) + ", storedTotalDebt: ") + toString(storedTotalDebt)) + ", storedTotalReserve: ") + toString(storedTotalReserve)) + ", storedIndex: ") + toString(storedIndex)) + ", lastUpdateHeight: ") + toString(lastUpdateHeight)) + ", currentTotalDeposit: ") + toString(currentTotalDeposit)) + ", currentTotalDebt: ") + toString(currentTotalDebt)) + ", currentTotalReserve: ") + toString(currentTotalReserve)) + ", currentIndex: ") + toString(currentIndex)) + ", currentHeight: ") + toString(HEIGHT)) + ", aTokenCirculation: ") + toString(aTokenCirculation)) + ", aTokenPrice: ") + toString(aTokenToAsset(pow(10, 0, assetDecimals, 0, 0, FLOOR))))
400406
401407
402408 func userTotals (user) = {
403409 let atokens = aTokenBalance(user)
404410 let asset = aTokenToAsset(atokens)
405411 let debt = currentUserDebt(user)
406412 if ((HEIGHT == lastUpdateHeight))
407413 then $Tuple4(storedTotalDeposit, storedTotalDebt, asset, debt)
408414 else $Tuple4(currentTotalDeposit, currentTotalDebt, asset, debt)
409415 }
410416
411417
412418 func withdrawInternal (i,user,amount,toMain) = {
413419 let maxWithdraw = ((storedTotalDeposit + storedTotalReserve) - storedTotalDebt)
414420 let checks = if (if (if (mainOnly(i))
415421 then liquidityCheck(amount, maxWithdraw, ("funds in use: max=" + toString(maxWithdraw)))
416422 else false)
417423 then throwIf((-1 > amount), "invalid amount")
418424 else false)
419425 then opAllowed("withdraw")
420426 else false
421427 if ((checks == checks))
422428 then {
423- let $t01544215633 = if ((amount == -1))
429+ let $t01596816159 = if ((amount == -1))
424430 then {
425431 let atokens = aTokenBalance(user)
426432 $Tuple2(atokens, aTokenToAsset(atokens))
427433 }
428434 else $Tuple2(assetToATokenCeil(amount), amount)
429- let removedAtokens = $t01544215633._1
430- let withdrawAmount = $t01544215633._2
435+ let removedAtokens = $t01596816159._1
436+ let withdrawAmount = $t01596816159._2
431437 $Tuple2((syncTotals(-(withdrawAmount), 0, 0, withdrawAmount) ++ [ScriptTransfer(if (toMain)
432438 then mainContract
433439 else addressFromStringValue(user), withdrawAmount, assetId), changeBy(aTokenBalanceStore(user), -(removedAtokens)), changeBy(aTokenCirculationStore, -(removedAtokens))]), withdrawAmount)
434440 }
435441 else throw("Strict value is not equal to itself.")
436442 }
437443
438444
439445 func replenishInternal (op,user,i) = {
440446 let checks = if (mainOnly(i))
441447 then opAllowed(op)
442448 else false
443449 if ((checks == checks))
444450 then {
445451 let aTokenAmount = paymentAmount(i, aTokenId)
446452 $Tuple2(((syncTotals(0, 0, 0, 0) ++ [changeBy(aTokenBalanceStore(user), aTokenAmount), Burn(aTokenId, aTokenAmount)]) ++ enableColIfNeeded(user)), aTokenToAsset(aTokenAmount))
447453 }
448454 else throw("Strict value is not equal to itself.")
449455 }
450456
451457
452458 func mintInternal (i,address,amountToMint,to,action) = {
453459 let userATokenBalance = aTokenBalance(address)
454460 let amount = if ((amountToMint == -1))
455461 then userATokenBalance
456462 else amountToMint
457463 let checks = if (if (if (mainOnly(i))
458464 then opAllowed(action)
459465 else false)
460466 then throwIf((-1 > amountToMint), "invalid amountToMint")
461467 else false)
462468 then throwIf((amount > userATokenBalance), ("Trying to mint more than available, max: " + toString(userATokenBalance)))
463469 else false
464470 if ((checks == checks))
465471 then $Tuple2((syncTotals(0, 0, 0, 0) ++ [changeBy(aTokenBalanceStore(address), -(amount)), Reissue(aTokenId, amount, true), ScriptTransfer(addressFromStringValue(to), amount, aTokenId)]), aTokenToAsset(amount))
466472 else throw("Strict value is not equal to itself.")
467473 }
468474
469475
470476 @Callable(i)
471477 func getReserveDivsInfo () = $Tuple2(nil, $Tuple3(claimableDividends, assetIdStr, (currentTotalReserve - claimableDividends)))
472478
473479
474480
475481 @Callable(i)
482+func storedDepositBorrow () = $Tuple2(nil, $Tuple2(storedTotalDeposit, storedTotalDebt))
483+
484+
485+
486+@Callable(i)
476487 func getCurrentTotals (user) = $Tuple2(nil, userTotals(user))
477488
478489
479490
480491 @Callable(i)
481492 func getCurrentTotals2 (user1,user2) = {
482- let $t01722717264 = userTotals(user1)
483- let d1 = $t01722717264._1
484- let d2 = $t01722717264._2
485- let d3 = $t01722717264._3
486- let d4 = $t01722717264._4
487- let $t01726917306 = userTotals(user2)
488- let e1 = $t01726917306._1
489- let e2 = $t01726917306._2
490- let e3 = $t01726917306._3
491- let e4 = $t01726917306._4
493+ let $t01784017877 = userTotals(user1)
494+ let d1 = $t01784017877._1
495+ let d2 = $t01784017877._2
496+ let d3 = $t01784017877._3
497+ let d4 = $t01784017877._4
498+ let $t01788217919 = userTotals(user2)
499+ let e1 = $t01788217919._1
500+ let e2 = $t01788217919._2
501+ let e3 = $t01788217919._3
502+ let e4 = $t01788217919._4
492503 $Tuple2(nil, $Tuple6(d1, d2, d3, d4, e3, e4))
493504 }
494505
495506
496507
497508 @Callable(i)
498509 func advise () = $Tuple2(nil, ((((("reserveAddress: " + toString(this)) + ", ") + getConfig()) + ", ") + getState()))
499510
500511
501512
502513 @Callable(i)
503514 func adviseUser (user) = {
504515 let currentDebtUsd = assetToUsd(currentTotalDebt)
505516 let currentDepositUsd = assetToUsd(currentTotalDeposit)
506517 let asCollateral = valueOrElse(getBoolean(this, useAsCollateralStore(user)), true)
507518 let effectiveDepositUsd = if (asCollateral)
508519 then currentDepositUsd
509520 else 0
510521 let overlapUsd = min([currentDebtUsd, effectiveDepositUsd])
511522 let overlapCharge = fractionCeil(overlapUsd, accountHealthOverlap, factorsBase)
512523 let bp = if ((currentDebtUsd > effectiveDepositUsd))
513524 then 0
514525 else fraction((effectiveDepositUsd - currentDebtUsd), collateralFactor, factorsBase)
515526 let bpu = if ((currentDebtUsd > effectiveDepositUsd))
516527 then (fraction((currentDebtUsd - effectiveDepositUsd), factorsBase, liquidationThreshold) + overlapCharge)
517528 else overlapCharge
518529 let enriched = ((((((((("reserveAddress: " + toString(this)) + ", currentDebtUsd: ") + toString(currentDebtUsd)) + ", currentDepositUsd: ") + toString(currentDepositUsd)) + ", bp: ") + toString(bp)) + ", bpu: ") + toString(bpu))
519530 $Tuple2(nil, ((enriched + ", ") + getUserState(user)))
520531 }
521532
522533
523534
524535 @Callable(i)
525536 func addInterest () = if ((i.payments[0].assetId != assetId))
526537 then throw("can't add interest with unrelated token")
527538 else syncTotals(i.payments[0].amount, 0, 0, 0)
528539
529540
530541
531542 @Callable(i)
532543 func addToReserve () = if ((i.payments[0].assetId != assetId))
533544 then throw("can't add interest with unrelated token")
534545 else syncTotals(0, 0, i.payments[0].amount, 0)
535546
536547
537548
538549 @Callable(i)
539550 func withdrawFromReserve (amt) = {
540551 let checks = divAdminOnly(i)
541552 if ((checks == checks))
542553 then {
543554 let diff = if ((amt == -1))
544555 then claimableDividends
545556 else amt
546557 $Tuple2((syncTotals(0, 0, -(diff), diff) ++ [ScriptTransfer(i.caller, diff, assetId)]), diff)
547558 }
548559 else throw("Strict value is not equal to itself.")
549560 }
550561
551562
552563
553564 @Callable(i)
554565 func forceUpdate () = {
555566 let admin = valueOrErrorMessage(getString(configAddress, "admin"), "reserve:no admin in config")
556567 if ((toString(i.caller) != admin))
557568 then throw("only admin can do")
558569 else syncTotals(0, 0, 0, 0)
559570 }
560571
561572
562573
563574 @Callable(i)
564575 func initialize (cfgAddress,assetIdOrWaves,aTokenName,aTokenDescription,aTokenDecimals) = {
565576 let checks = if (notInitialized)
566577 then isAssetIdOrWaves(assetIdOrWaves)
567578 else false
568579 if ((checks == checks))
569580 then {
570581 let aToken = Issue(aTokenName, aTokenDescription, 0, aTokenDecimals, true)
571582 [aToken, writeInt(aTokenDecimalsStore, aTokenDecimals), writeString(aTokenNameStore, aTokenName), writeString(assetIdStore, assetIdOrWaves), writeString(configAddressStore, cfgAddress), writeString(aTokenIdStore, toBase58String(calculateAssetId(aToken)))]
572583 }
573584 else throw("Strict value is not equal to itself.")
574585 }
575586
576587
577588
578589 @Callable(i)
579590 func initialize2 () = if ((i.caller != this))
580591 then throw("only self can continue")
581- else [writeInt(lastUpdateHeightStore, HEIGHT)]
592+ else [StringEntry(reserveGlobalStore, (toString(HEIGHT) + "||||"))]
582593
583594
584595
585596 @Callable(i)
586597 func userDepositUSD (address) = $Tuple2(nil, assetToUsd(aTokenToAsset(aTokenBalance(address))))
587598
588599
589600
590601 @Callable(i)
591602 func userDebtUSD (address) = $Tuple2(nil, assetToUsd(currentUserDebt(address)))
592603
593604
594605
595606 @Callable(i)
596607 func userBalance (address) = {
597608 let atokens = aTokenBalance(address)
598609 let asset = aTokenToAsset(atokens)
599610 let debt = currentUserDebt(address)
600611 $Tuple2(nil, $Tuple6(atokens, asset, assetToUsd(asset), debt, assetToUsd(debt), valueOrElse(getBoolean(this, useAsCollateralStore(address)), true)))
601612 }
602613
603614
604615
605616 @Callable(i)
606617 func userDebt (address) = {
607618 let debt = currentUserDebt(address)
608619 let debtUsd = assetToUsd(debt)
609620 $Tuple2(nil, $Tuple2(debt, debtUsd))
610621 }
611622
612623
613624
614625 @Callable(i)
615626 func assetUsdValue (assetAmount) = $Tuple2(nil, assetToUsd(assetAmount))
616627
617628
618629
619630 @Callable(i)
620631 func repayFor (userAddress) = {
621632 let checks = mainOnly(i)
622633 if ((checks == checks))
623634 then repayUser(userAddress, paymentAmount(i, assetId))
624635 else throw("Strict value is not equal to itself.")
625636 }
626637
627638
628639
629640 @Callable(i)
630641 func depositFor (depositor,useAsCollateral) = {
631642 let checks = if (mainOnly(i))
632643 then opAllowed("deposit")
633644 else false
634645 if ((checks == checks))
635646 then if (if ((currentUserDebt(depositor) > 0))
636647 then !(useAsCollateral)
637648 else false)
638649 then throw("can't disable use as collateral for asset with open debt")
639650 else {
640651 let amount = paymentAmount(i, assetId)
641652 let aTokenAmount = assetToAToken(amount)
642653 (syncTotals(amount, 0, 0, 0) ++ [changeBy(aTokenCirculationStore, aTokenAmount), changeBy(aTokenBalanceStore(depositor), aTokenAmount), BooleanEntry(useAsCollateralStore(depositor), useAsCollateral)])
643654 }
644655 else throw("Strict value is not equal to itself.")
645656 }
646657
647658
648659
649660 @Callable(i)
650661 func withdrawFor (address,amount) = withdrawInternal(i, address, amount, false)
651662
652663
653664
654665 @Callable(i)
655666 func withdrawToMain (user,amount) = if ((amount != -1))
656667 then throw("reserve: withdrawToMain amount -1 only")
657668 else withdrawInternal(i, user, amount, true)
658669
659670
660671
661672 @Callable(i)
662673 func replenishWithAtokenFor (user) = replenishInternal("replenish_atokens", user, i)
674+
675+
676+
677+@Callable(i)
678+func replenisForUnlockWithAtokenFor (user) = replenishInternal("replenish_atokens_unlock", user, i)
663679
664680
665681
666682 @Callable(i)
667683 func replenishForRepayWithAtokenFor (user) = replenishInternal("repay_atokens", user, i)
668684
669685
670686
671687 @Callable(i)
672688 func borrowFor (address,amountToBorrow) = {
673689 let checks = if (if (mainOnly(i))
674690 then liquidityCheck(amountToBorrow, (storedTotalDeposit - storedTotalDebt), "too much borrow requested")
675691 else false)
676692 then opAllowed("borrow")
677693 else false
678694 if ((checks == checks))
679695 then {
680696 let currentDebt = currentUserDebt(address)
681697 let newDebt = (currentDebt + amountToBorrow)
682698 (syncTotals(0, amountToBorrow, 0, amountToBorrow) ++ [writeInt(debtStore(address), newDebt), enableCol(address), writeInt(debtIndexStore(address), currentIndex), ScriptTransfer(addressFromStringValue(address), amountToBorrow, assetId)])
683699 }
684700 else throw("Strict value is not equal to itself.")
685701 }
686702
687703
688704
689705 @Callable(i)
690706 func mintAtokenFor (address,amountToMint) = mintInternal(i, address, amountToMint, address, "mint_atokens")
691707
692708
693709
694710 @Callable(i)
695711 func mintAtokenForTo (from,amountToMint,to) = mintInternal(i, from, amountToMint, to, "lock_mint_atokens")
696712
697713
698714
699715 @Callable(i)
700716 func redeemAtokensFor (user) = {
701717 let checks = if (mainOnly(i))
702718 then opAllowed("redeem_atokens")
703719 else false
704720 if ((checks == checks))
705721 then {
706722 let aTokenAmount = paymentAmount(i, aTokenId)
707723 let outAmount = aTokenToAsset(aTokenAmount)
708724 $Tuple2((syncTotals(-(outAmount), 0, 0, outAmount) ++ [ScriptTransfer(addressFromStringValue(user), outAmount, assetId), changeBy(aTokenCirculationStore, -(aTokenAmount)), Burn(aTokenId, aTokenAmount)]), outAmount)
709725 }
710726 else throw("Strict value is not equal to itself.")
711727 }
712728
713729
714730
715731 @Callable(i)
716732 func transferATokensFor (from,to,valueUsd) = {
717733 let checks = if (mainOnly(i))
718734 then opAllowed("transfer_debt")
719735 else false
720736 if ((checks == checks))
721737 then {
722738 let assets = usdToAsset(valueUsd)
723739 let atokens = assetToAToken(assets)
724740 let aTokensFrom = aTokenBalance(from)
725741 if ((atokens > aTokensFrom))
726742 then throw((((((((((("transferAtokensFor error:" + " transfer.valueUsd: ") + toString(valueUsd)) + " transfer.assets: ") + toString(assets)) + " transfer.atokens: ") + toString(atokens)) + " from.atokens: ") + toString(aTokensFrom)) + " at ") + toString(this)))
727743 else $Tuple2(((syncTotals(0, 0, 0, 0) ++ [changeBy(aTokenBalanceStore(from), -(atokens)), changeBy(aTokenBalanceStore(to), atokens)]) ++ enableColIfNeeded(to)), aTokenToAsset(atokens))
728744 }
729745 else throw("Strict value is not equal to itself.")
730746 }
731747
732748
733749
734750 @Callable(i)
735751 func transferDebtFor (from,to,amount) = {
736752 let checks = if (mainOnly(i))
737753 then opAllowed("transfer_debt")
738754 else false
739755 if ((checks == checks))
740756 then $Tuple2((syncTotals(0, 0, 0, 0) ++ [writeInt(debtStore(from), (currentUserDebt(from) - amount)), writeInt(debtStore(to), (currentUserDebt(to) + amount)), writeInt(debtIndexStore(from), currentIndex), writeInt(debtIndexStore(to), currentIndex), enableCol(to)]), amount)
741757 else throw("Strict value is not equal to itself.")
742758 }
743759
744760
745761
746762 @Callable(i)
747763 func disableUseAsCollateralFor (address) = {
748764 let checks = if (mainOnly(i))
749765 then opAllowed("use_as_col")
750766 else false
751767 if ((checks == checks))
752768 then if ((currentUserDebt(address) > 0))
753769 then throw("can't disable collateral for asset with open debt")
754770 else (syncTotals(0, 0, 0, 0) ++ [BooleanEntry(useAsCollateralStore(address), false)])
755771 else throw("Strict value is not equal to itself.")
756772 }
757773
758774
759775
760776 @Callable(i)
761777 func enableUseAsCollateral () = {
762778 let checks = opAllowed("use_as_col")
763779 if ((checks == checks))
764780 then (syncTotals(0, 0, 0, 0) ++ [enableCol(toString(i.caller))])
765781 else throw("Strict value is not equal to itself.")
766782 }
767783
768784
769785
770786 @Callable(i)
771787 func collapseFor (user) = {
772788 let checks = if (mainOnly(i))
773789 then opAllowed("force_collapse")
774790 else false
775791 if ((checks == checks))
776792 then collapseUser(user, -1)
777793 else throw("Strict value is not equal to itself.")
778794 }
779795
780796
781797
782798 @Callable(i)
783799 func collapseForAmount (user,amount) = {
784800 let checks = if (mainOnly(i))
785801 then opAllowed("collapse")
786802 else false
787803 if ((checks == checks))
788804 then collapseUser(user, amount)
789805 else throw("Strict value is not equal to itself.")
790806 }
791807
792808
793809
794810 @Callable(i)
795811 func lpValue (aTokenAmount) = $Tuple2(nil, aTokenToAsset(aTokenAmount))
796812
797813

github/deemru/w8io/786bc32 
108.66 ms