tx · GFMy6xZ5gD7imZhtnAWP6ooHWfLwXbpbNW2FXvMdniHT

3MyVvNfXht9piazyf1e5BVFsqv1R7z5cWJL:  -0.02800000 Waves

2022.06.23 13:38 [2108948] smart account 3MyVvNfXht9piazyf1e5BVFsqv1R7z5cWJL > SELF 0.00000000 Waves

{ "type": 13, "id": "GFMy6xZ5gD7imZhtnAWP6ooHWfLwXbpbNW2FXvMdniHT", "fee": 2800000, "feeAssetId": null, "timestamp": 1655980810850, "version": 1, "sender": "3MyVvNfXht9piazyf1e5BVFsqv1R7z5cWJL", "senderPublicKey": "DnPyGWCgpQChvoQrnXQRcC9FtN32mPGrcog2wcKHdkVn", "proofs": [ "1231YRNT3vKh68cv6M8omsYoVGwEjqXGFPjs39K5YNMi1ezkTvoGjF5jU5itxVQ8qLYZ2pYv8dRQ2MtZgbAnnD2Y" ], "script": "base64:BgJbCAISAwoBCBIAEgQKAggBEgcKBQgICAgBEgQKAggIEgUKAwgIARIECgIICBIDCgEBEgMKAQESBAoCCAgSAwoBCBIAEgMKAQESABIECgIICBIECgIICBIECgIICDEACXNlcGFyYXRvcgICX18ADnBvb2xXZWlnaHRNdWx0AIDC1y8AD21heERlcHRoRGVmYXVsdAAKABZmaW5hbGl6YXRpb25TdGFnZVRvdGFsAAAAF2ZpbmFsaXphdGlvblN0YWdlU2hhcmVzAAEADmtleUVwb2NoTGVuZ3RoCQC5CQIJAMwIAgICJXMJAMwIAgILZXBvY2hMZW5ndGgFA25pbAUJc2VwYXJhdG9yAA9rZXlDdXJyZW50RXBvY2gJALkJAgkAzAgCAgIlcwkAzAgCAgxjdXJyZW50RXBvY2gFA25pbAUJc2VwYXJhdG9yAAtrZXlNYXhEZXB0aAkAuQkCCQDMCAICAiVzCQDMCAICCG1heERlcHRoBQNuaWwFCXNlcGFyYXRvcgAia2V5Vm90aW5nRW1pc3Npb25DYW5kaWRhdGVDb250cmFjdAkAuQkCCQDMCAICAiVzCQDMCAICH3ZvdGluZ0VtaXNzaW9uQ2FuZGlkYXRlQ29udHJhY3QFA25pbAUJc2VwYXJhdG9yABJrZXlGYWN0b3J5Q29udHJhY3QJALkJAgkAzAgCAgIlcwkAzAgCAg9mYWN0b3J5Q29udHJhY3QFA25pbAUJc2VwYXJhdG9yABNrZXlCb29zdGluZ0NvbnRyYWN0CQC5CQIJAMwIAgICJXMJAMwIAgIQYm9vc3RpbmdDb250cmFjdAUDbmlsBQlzZXBhcmF0b3IAEmtleVN0YWtpbmdDb250cmFjdAkAuQkCCQDMCAICAiVzCQDMCAICD3N0YWtpbmdDb250cmFjdAUDbmlsBQlzZXBhcmF0b3IAFGtleUZpbmFsaXphdGlvblN0YWdlCQC5CQIJAMwIAgICJXMJAMwIAgIRZmluYWxpemF0aW9uU3RhZ2UFA25pbAUJc2VwYXJhdG9yAAtrZXlOZXh0UG9vbAkAuQkCCQDMCAICAiVzCQDMCAICCG5leHRQb29sBQNuaWwFCXNlcGFyYXRvcgALa2V5TmV4dFVzZXIJALkJAgkAzAgCAgIlcwkAzAgCAghuZXh0VXNlcgUDbmlsBQlzZXBhcmF0b3IADmtleVN0YXJ0SGVpZ2h0CQC5CQIJAMwIAgICJXMJAMwIAgILc3RhcnRIZWlnaHQFA25pbAUJc2VwYXJhdG9yABFrZXlDdXJyZW50RXBvY2hVaQkAuQkCCQDMCAICAiVzCQDMCAICDmN1cnJlbnRFcG9jaFVpBQNuaWwFCXNlcGFyYXRvcgAQa2V5U3RhcnRIZWlnaHRVaQkAuQkCCQDMCAICAiVzCQDMCAICDXN0YXJ0SGVpZ2h0VWkFA25pbAUJc2VwYXJhdG9yARVrZXlTdGFydEhlaWdodEJ5RXBvY2gBBWVwb2NoCQC5CQIJAMwIAgIEJXMlZAkAzAgCAgtzdGFydEhlaWdodAkAzAgCCQCkAwEFBWVwb2NoBQNuaWwFCXNlcGFyYXRvcgEMa2V5RmluYWxpemVkAQVlcG9jaAkAuQkCCQDMCAICBCVzJWQJAMwIAgIJZmluYWxpemVkCQDMCAIJAKQDAQUFZXBvY2gFA25pbAUJc2VwYXJhdG9yAQlrZXlJbkxpc3QBBHBvb2wECyR0MDE0MzYxNDc2BQRwb29sBA1hbW91bnRBc3NldElkCAULJHQwMTQzNjE0NzYCXzEEDHByaWNlQXNzZXRJZAgFCyR0MDE0MzYxNDc2Al8yCQC5CQIJAMwIAgIGJXMlcyVzCQDMCAICBmluTGlzdAkAzAgCBQ1hbW91bnRBc3NldElkCQDMCAIFDHByaWNlQXNzZXRJZAUDbmlsBQlzZXBhcmF0b3IBB2tleVVzZWQCB2FkZHJlc3MFZXBvY2gJALkJAgkAzAgCAgYlcyVzJWQJAMwIAgIEdXNlZAkAzAgCCQClCAEFB2FkZHJlc3MJAMwIAgkApAMBBQVlcG9jaAUDbmlsBQlzZXBhcmF0b3IBB2tleVZvdGUDBHBvb2wHYWRkcmVzcwVlcG9jaAQLJHQwMTc1MDE3OTAFBHBvb2wEDWFtb3VudEFzc2V0SWQIBQskdDAxNzUwMTc5MAJfMQQMcHJpY2VBc3NldElkCAULJHQwMTc1MDE3OTACXzIJALkJAgkAzAgCAgolcyVzJXMlcyVkCQDMCAICBHZvdGUJAMwIAgUNYW1vdW50QXNzZXRJZAkAzAgCBQxwcmljZUFzc2V0SWQJAMwIAgkApQgBBQdhZGRyZXNzCQDMCAIJAKQDAQUFZXBvY2gFA25pbAUJc2VwYXJhdG9yAQ9rZXlWb3RpbmdSZXN1bHQCBHBvb2wFZXBvY2gECyR0MDE5NzIyMDEyBQRwb29sBA1hbW91bnRBc3NldElkCAULJHQwMTk3MjIwMTICXzEEDHByaWNlQXNzZXRJZAgFCyR0MDE5NzIyMDEyAl8yCQC5CQIJAMwIAgIIJXMlcyVzJWQJAMwIAgIMdm90aW5nUmVzdWx0CQDMCAIFDWFtb3VudEFzc2V0SWQJAMwIAgUMcHJpY2VBc3NldElkCQDMCAIJAKQDAQUFZXBvY2gFA25pbAUJc2VwYXJhdG9yAQxrZXlQb29sU2hhcmUCBHBvb2wFZXBvY2gECyR0MDIxNzcyMjE3BQRwb29sBA1hbW91bnRBc3NldElkCAULJHQwMjE3NzIyMTcCXzEEDHByaWNlQXNzZXRJZAgFCyR0MDIxNzcyMjE3Al8yCQC5CQIJAMwIAgIIJXMlcyVzJWQJAMwIAgIJcG9vbFNoYXJlCQDMCAIFDWFtb3VudEFzc2V0SWQJAMwIAgUMcHJpY2VBc3NldElkCQDMCAIJAKQDAQUFZXBvY2gFA25pbAUJc2VwYXJhdG9yAQ1rZXlUb3RhbFZvdGVzAQVlcG9jaAkAuQkCCQDMCAICBCVzJWQJAMwIAgIKdG90YWxWb3RlcwkAzAgCCQCkAwEFBWVwb2NoBQNuaWwFCXNlcGFyYXRvcgEOZ2V0VmFsdWVPckZhaWwDB2FkZHJlc3MDa2V5BHR5cGUEBWVycm9yCQC5CQIJAMwIAgIKbWFuZGF0b3J5IAkAzAgCCQClCAEFB2FkZHJlc3MJAMwIAgIBLgkAzAgCBQNrZXkJAMwIAgIPIGlzIG5vdCBkZWZpbmVkBQNuaWwCAAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCBAckbWF0Y2gwBQR0eXBlAwkAAQIFByRtYXRjaDACBlN0cmluZwQDc3RyBQckbWF0Y2gwCQCdCAIFB2FkZHJlc3MFA2tleQMJAAECBQckbWF0Y2gwAgNJbnQEA2ludAUHJG1hdGNoMAkAmggCBQdhZGRyZXNzBQNrZXkJAAIBAhJpbnZhbGlkIGVudHJ5IHR5cGUFBWVycm9yAQxnZXRTdHJPckZhaWwCB2FkZHJlc3MDa2V5CgABQAkBDmdldFZhbHVlT3JGYWlsAwUHYWRkcmVzcwUDa2V5AgADCQABAgUBQAIGU3RyaW5nBQFACQACAQkArAICCQADAQkBDmdldFZhbHVlT3JGYWlsAwUHYWRkcmVzcwUDa2V5AgACGyBjb3VsZG4ndCBiZSBjYXN0IHRvIFN0cmluZwEMZ2V0SW50T3JGYWlsAgdhZGRyZXNzA2tleQoAAUAJAQ5nZXRWYWx1ZU9yRmFpbAMFB2FkZHJlc3MFA2tleQAAAwkAAQIFAUACA0ludAUBQAkAAgEJAKwCAgkAAwEJAQ5nZXRWYWx1ZU9yRmFpbAMFB2FkZHJlc3MFA2tleQAAAhggY291bGRuJ3QgYmUgY2FzdCB0byBJbnQBDHBvb2xUb1N0cmluZwEEcG9vbAkArAICCQCsAgIIBQRwb29sAl8xBQlzZXBhcmF0b3IIBQRwb29sAl8yAQxzdHJpbmdUb1Bvb2wBA3N0cgQFcGFydHMJALUJAgUDc3RyBQlzZXBhcmF0b3IDCQAAAgkAkAMBBQVwYXJ0cwACCQCUCgIJAJEDAgUFcGFydHMAAAkAkQMCBQVwYXJ0cwABCQACAQITaW52YWxpZCBwb29sIHN0cmluZwEWZ2V0THBBc3NldEJ5UG9vbEFzc2V0cwINYW1vdW50QXNzZXRJZAxwcmljZUFzc2V0SWQKAR9rZXlNYXBwaW5nc0Jhc2VBc3NldDJpbnRlcm5hbElkAQxiYXNlQXNzZXRTdHIJAKwCAgIoJXMlcyVzX19tYXBwaW5nc19fYmFzZUFzc2V0MmludGVybmFsSWRfXwUMYmFzZUFzc2V0U3RyCgEpa2V5TWFwcGluZ1Bvb2xBc3NldHNUb1Bvb2xDb250cmFjdEFkZHJlc3MCGGludGVybmFsQW1vdW50QXNzZXRJZFN0chdpbnRlcm5hbFByaWNlQXNzZXRJZFN0cgkArAICCQCsAgIJAKwCAgkArAICAgolZCVkJXMlc19fCQCkAwEFGGludGVybmFsQW1vdW50QXNzZXRJZFN0cgICX18JAKQDAQUXaW50ZXJuYWxQcmljZUFzc2V0SWRTdHICI19fbWFwcGluZ3NfX3Bvb2xBc3NldHMyUG9vbENvbnRyYWN0CgEfa2V5TWFwcGluZ1Bvb2xDb250cmFjdFRvTFBBc3NldAETcG9vbENvbnRyYWN0QWRkcmVzcwkArAICCQCsAgICCCVzJXMlc19fBRNwb29sQ29udHJhY3RBZGRyZXNzAiBfX21hcHBpbmdzX19wb29sQ29udHJhY3QyTHBBc3NldAQPZmFjdG9yeUNvbnRyYWN0CQERQGV4dHJOYXRpdmUoMTA2MikBCQEMZ2V0U3RyT3JGYWlsAgUEdGhpcwUSa2V5RmFjdG9yeUNvbnRyYWN0BBVhbW91bnRBc3NldEludGVybmFsSWQJAQxnZXRJbnRPckZhaWwCBQ9mYWN0b3J5Q29udHJhY3QJAR9rZXlNYXBwaW5nc0Jhc2VBc3NldDJpbnRlcm5hbElkAQUNYW1vdW50QXNzZXRJZAQUcHJpY2VBc3NldEludGVybmFsSWQJAQxnZXRJbnRPckZhaWwCBQ9mYWN0b3J5Q29udHJhY3QJAR9rZXlNYXBwaW5nc0Jhc2VBc3NldDJpbnRlcm5hbElkAQUMcHJpY2VBc3NldElkBBNwb29sQ29udHJhY3RBZGRyZXNzCQEMZ2V0U3RyT3JGYWlsAgUPZmFjdG9yeUNvbnRyYWN0CQEpa2V5TWFwcGluZ1Bvb2xBc3NldHNUb1Bvb2xDb250cmFjdEFkZHJlc3MCBRVhbW91bnRBc3NldEludGVybmFsSWQFFHByaWNlQXNzZXRJbnRlcm5hbElkBAlscEFzc2V0SWQJAQxnZXRTdHJPckZhaWwCBQ9mYWN0b3J5Q29udHJhY3QJAR9rZXlNYXBwaW5nUG9vbENvbnRyYWN0VG9MUEFzc2V0AQUTcG9vbENvbnRyYWN0QWRkcmVzcwUJbHBBc3NldElkARhjaGVja1d4RW1pc3Npb25Qb29sTGFiZWwBBHBvb2wECyR0MDQ0NTk0NDk5BQRwb29sBA1hbW91bnRBc3NldElkCAULJHQwNDQ1OTQ0OTkCXzEEDHByaWNlQXNzZXRJZAgFCyR0MDQ0NTk0NDk5Al8yBA9mYWN0b3J5Q29udHJhY3QJARFAZXh0ck5hdGl2ZSgxMDYyKQEJAQxnZXRTdHJPckZhaWwCBQR0aGlzBRJrZXlGYWN0b3J5Q29udHJhY3QKAAFACQD8BwQFD2ZhY3RvcnlDb250cmFjdAIYY2hlY2tXeEVtaXNzaW9uUG9vbExhYmVsCQDMCAIFDWFtb3VudEFzc2V0SWQJAMwIAgUMcHJpY2VBc3NldElkBQNuaWwFA25pbAMJAAECBQFAAgdCb29sZWFuBQFACQACAQkArAICCQADAQkA/AcEBQ9mYWN0b3J5Q29udHJhY3QCGGNoZWNrV3hFbWlzc2lvblBvb2xMYWJlbAkAzAgCBQ1hbW91bnRBc3NldElkCQDMCAIFDHByaWNlQXNzZXRJZAUDbmlsBQNuaWwCHCBjb3VsZG4ndCBiZSBjYXN0IHRvIEJvb2xlYW4ADXBvb2xzTGlzdE5hbWUCBXBvb2xzARBnZXRWb3Rlc0xpc3ROYW1lAQRwb29sBAskdDA0ODAwNDg0MAUEcG9vbAQNYW1vdW50QXNzZXRJZAgFCyR0MDQ4MDA0ODQwAl8xBAxwcmljZUFzc2V0SWQIBQskdDA0ODAwNDg0MAJfMgkAuQkCCQDMCAICBXZvdGVzCQDMCAIFDWFtb3VudEFzc2V0SWQJAMwIAgUMcHJpY2VBc3NldElkBQNuaWwFCXNlcGFyYXRvcgELa2V5TGlzdEhlYWQBCGxpc3ROYW1lBARtZXRhAwkAAAIFCGxpc3ROYW1lBQ1wb29sc0xpc3ROYW1lAgQlcyVzAgglcyVzJXMlcwkAuQkCCQDMCAIFBG1ldGEJAMwIAgUIbGlzdE5hbWUJAMwIAgIEaGVhZAUDbmlsBQlzZXBhcmF0b3IBC2tleUxpc3RTaXplAQhsaXN0TmFtZQQEbWV0YQMJAAACBQhsaXN0TmFtZQUNcG9vbHNMaXN0TmFtZQIEJXMlcwIIJXMlcyVzJXMJALkJAgkAzAgCBQRtZXRhCQDMCAIFCGxpc3ROYW1lCQDMCAICBHNpemUFA25pbAUJc2VwYXJhdG9yAQtrZXlMaXN0UHJldgIIbGlzdE5hbWUCaWQEBG1ldGEDCQAAAgUIbGlzdE5hbWUFDXBvb2xzTGlzdE5hbWUCCCVzJXMlcyVzAgolcyVzJXMlcyVzCQC5CQIJAMwIAgUEbWV0YQkAzAgCBQhsaXN0TmFtZQkAzAgCBQJpZAkAzAgCAgRwcmV2BQNuaWwFCXNlcGFyYXRvcgELa2V5TGlzdE5leHQCCGxpc3ROYW1lAmlkBARtZXRhAwkAAAIFCGxpc3ROYW1lBQ1wb29sc0xpc3ROYW1lAgglcyVzJXMlcwIKJXMlcyVzJXMlcwkAuQkCCQDMCAIFBG1ldGEJAMwIAgUIbGlzdE5hbWUJAMwIAgUCaWQJAMwIAgIEbmV4dAUDbmlsBQlzZXBhcmF0b3IBDGNvbnRhaW5zTm9kZQIIbGlzdE5hbWUCaWQECmhlYWRPclVuaXQJAJ0IAgUEdGhpcwkBC2tleUxpc3RIZWFkAQUIbGlzdE5hbWUECnByZXZPclVuaXQJAJ0IAgUEdGhpcwkBC2tleUxpc3RQcmV2AgUIbGlzdE5hbWUFAmlkBApuZXh0T3JVbml0CQCdCAIFBHRoaXMJAQtrZXlMaXN0TmV4dAIFCGxpc3ROYW1lBQJpZAMDCQAAAgUCaWQJAQt2YWx1ZU9yRWxzZQIFCmhlYWRPclVuaXQCAAYJAQIhPQIFCnByZXZPclVuaXQFBHVuaXQGCQECIT0CBQpuZXh0T3JVbml0BQR1bml0ARFpbnNlcnROb2RlQWN0aW9ucwIIbGlzdE5hbWUCaWQECmhlYWRPclVuaXQJAJ0IAgUEdGhpcwkBC2tleUxpc3RIZWFkAQUIbGlzdE5hbWUECGxpc3RTaXplCQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMJAQtrZXlMaXN0U2l6ZQEFCGxpc3ROYW1lAAAECWNoZWNrTm9kZQMJAQEhAQkBDGNvbnRhaW5zTm9kZQIFCGxpc3ROYW1lBQJpZAYJAAIBAgtOb2RlIGV4aXN0cwMJAAACBQljaGVja05vZGUFCWNoZWNrTm9kZQkAzggCCQDOCAIJAMwIAgkBDEludGVnZXJFbnRyeQIJAQtrZXlMaXN0U2l6ZQEFCGxpc3ROYW1lCQBkAgUIbGlzdFNpemUAAQUDbmlsAwkBAiE9AgUKaGVhZE9yVW5pdAUEdW5pdAkAzAgCCQELU3RyaW5nRW50cnkCCQELa2V5TGlzdE5leHQCBQhsaXN0TmFtZQUCaWQJAQV2YWx1ZQEFCmhlYWRPclVuaXQJAMwIAgkBC1N0cmluZ0VudHJ5AgkBC2tleUxpc3RQcmV2AgUIbGlzdE5hbWUJAQV2YWx1ZQEFCmhlYWRPclVuaXQFAmlkBQNuaWwFA25pbAkAzAgCCQELU3RyaW5nRW50cnkCCQELa2V5TGlzdEhlYWQBBQhsaXN0TmFtZQUCaWQFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgERZGVsZXRlTm9kZUFjdGlvbnMCCGxpc3ROYW1lAmlkBApoZWFkT3JVbml0CQCdCAIFBHRoaXMJAQtrZXlMaXN0SGVhZAEFCGxpc3ROYW1lBAhsaXN0U2l6ZQkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzCQELa2V5TGlzdFNpemUBBQhsaXN0TmFtZQAABApwcmV2T3JVbml0CQCdCAIFBHRoaXMJAQtrZXlMaXN0UHJldgIFCGxpc3ROYW1lBQJpZAQKbmV4dE9yVW5pdAkAnQgCBQR0aGlzCQELa2V5TGlzdE5leHQCBQhsaXN0TmFtZQUCaWQJAM4IAgkAzAgCCQEMSW50ZWdlckVudHJ5AgkBC2tleUxpc3RTaXplAQUIbGlzdE5hbWUJAGUCBQhsaXN0U2l6ZQABBQNuaWwDAwkBAiE9AgUKcHJldk9yVW5pdAUEdW5pdAkBAiE9AgUKbmV4dE9yVW5pdAUEdW5pdAcJAMwIAgkBC1N0cmluZ0VudHJ5AgkBC2tleUxpc3ROZXh0AgUIbGlzdE5hbWUJAQV2YWx1ZQEFCnByZXZPclVuaXQJAQV2YWx1ZQEFCm5leHRPclVuaXQJAMwIAgkBC1N0cmluZ0VudHJ5AgkBC2tleUxpc3RQcmV2AgUIbGlzdE5hbWUJAQV2YWx1ZQEFCm5leHRPclVuaXQJAQV2YWx1ZQEFCnByZXZPclVuaXQJAMwIAgkBC0RlbGV0ZUVudHJ5AQkBC2tleUxpc3RQcmV2AgUIbGlzdE5hbWUFAmlkCQDMCAIJAQtEZWxldGVFbnRyeQEJAQtrZXlMaXN0TmV4dAIFCGxpc3ROYW1lBQJpZAUDbmlsAwkBAiE9AgUKbmV4dE9yVW5pdAUEdW5pdAkAzAgCCQELU3RyaW5nRW50cnkCCQELa2V5TGlzdEhlYWQBBQhsaXN0TmFtZQkBBXZhbHVlAQUKbmV4dE9yVW5pdAkAzAgCCQELRGVsZXRlRW50cnkBCQELa2V5TGlzdE5leHQCBQhsaXN0TmFtZQUCaWQJAMwIAgkBC0RlbGV0ZUVudHJ5AQkBC2tleUxpc3RQcmV2AgUIbGlzdE5hbWUJAQV2YWx1ZQEFCm5leHRPclVuaXQFA25pbAMJAQIhPQIFCnByZXZPclVuaXQFBHVuaXQJAMwIAgkBC0RlbGV0ZUVudHJ5AQkBC2tleUxpc3RQcmV2AgUIbGlzdE5hbWUFAmlkCQDMCAIJAQtEZWxldGVFbnRyeQEJAQtrZXlMaXN0TmV4dAIFCGxpc3ROYW1lCQEFdmFsdWUBBQpwcmV2T3JVbml0BQNuaWwDCQAAAgUCaWQJAQt2YWx1ZU9yRWxzZQIFCmhlYWRPclVuaXQCAAkAzAgCCQELRGVsZXRlRW50cnkBCQELa2V5TGlzdEhlYWQBBQhsaXN0TmFtZQUDbmlsCQACAQkArAICCQCsAgIJAKwCAgIOaW52YWxpZCBub2RlOiAFCGxpc3ROYW1lAgEuBQJpZAETa2V5TWFuYWdlclB1YmxpY0tleQACFCVzX19tYW5hZ2VyUHVibGljS2V5ARprZXlQZW5kaW5nTWFuYWdlclB1YmxpY0tleQACGyVzX19wZW5kaW5nTWFuYWdlclB1YmxpY0tleQEWbWFuYWdlclB1YmxpY0tleU9yVW5pdAAEByRtYXRjaDAJAKIIAQkBE2tleU1hbmFnZXJQdWJsaWNLZXkAAwkAAQIFByRtYXRjaDACBlN0cmluZwQBcwUHJG1hdGNoMAkA2QQBBQFzAwkAAQIFByRtYXRjaDACBFVuaXQFBHVuaXQJAAIBAgtNYXRjaCBlcnJvcgEdcGVuZGluZ01hbmFnZXJQdWJsaWNLZXlPclVuaXQABAckbWF0Y2gwCQCiCAEJARprZXlQZW5kaW5nTWFuYWdlclB1YmxpY0tleQADCQABAgUHJG1hdGNoMAIGU3RyaW5nBAFzBQckbWF0Y2gwCQDZBAEFAXMDCQABAgUHJG1hdGNoMAIEVW5pdAUEdW5pdAkAAgECC01hdGNoIGVycm9yABVwZXJtaXNzaW9uRGVuaWVkRXJyb3IJAAIBAhFQZXJtaXNzaW9uIGRlbmllZAEIbXVzdFRoaXMBAWkDCQAAAggFAWkGY2FsbGVyBQR0aGlzBgUVcGVybWlzc2lvbkRlbmllZEVycm9yAQttdXN0TWFuYWdlcgEBaQQHJG1hdGNoMAkBFm1hbmFnZXJQdWJsaWNLZXlPclVuaXQAAwkAAQIFByRtYXRjaDACCkJ5dGVWZWN0b3IEAnBrBQckbWF0Y2gwAwkAAAIIBQFpD2NhbGxlclB1YmxpY0tleQUCcGsGBRVwZXJtaXNzaW9uRGVuaWVkRXJyb3IDCQABAgUHJG1hdGNoMAIEVW5pdAkBCG11c3RUaGlzAQUBaQkAAgECC01hdGNoIGVycm9yEQFpAQpzZXRNYW5hZ2VyARdwZW5kaW5nTWFuYWdlclB1YmxpY0tleQQLY2hlY2tDYWxsZXIJAQttdXN0TWFuYWdlcgEFAWkDCQAAAgULY2hlY2tDYWxsZXIFC2NoZWNrQ2FsbGVyBBVjaGVja01hbmFnZXJQdWJsaWNLZXkJANkEAQUXcGVuZGluZ01hbmFnZXJQdWJsaWNLZXkDCQAAAgUVY2hlY2tNYW5hZ2VyUHVibGljS2V5BRVjaGVja01hbmFnZXJQdWJsaWNLZXkJAMwIAgkBC1N0cmluZ0VudHJ5AgkBGmtleVBlbmRpbmdNYW5hZ2VyUHVibGljS2V5AAUXcGVuZGluZ01hbmFnZXJQdWJsaWNLZXkFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpAQ5jb25maXJtTWFuYWdlcgAEAnBtCQEdcGVuZGluZ01hbmFnZXJQdWJsaWNLZXlPclVuaXQABAVoYXNQTQMJAQlpc0RlZmluZWQBBQJwbQYJAAIBAhJObyBwZW5kaW5nIG1hbmFnZXIDCQAAAgUFaGFzUE0FBWhhc1BNBAdjaGVja1BNAwkAAAIIBQFpD2NhbGxlclB1YmxpY0tleQkBBXZhbHVlAQUCcG0GCQACAQIbWW91IGFyZSBub3QgcGVuZGluZyBtYW5hZ2VyAwkAAAIFB2NoZWNrUE0FB2NoZWNrUE0JAMwIAgkBC1N0cmluZ0VudHJ5AgkBE2tleU1hbmFnZXJQdWJsaWNLZXkACQDYBAEJAQV2YWx1ZQEFAnBtCQDMCAIJAQtEZWxldGVFbnRyeQEJARprZXlQZW5kaW5nTWFuYWdlclB1YmxpY0tleQAFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpARhnZXRVc2VyR3d4QW1vdW50QXRIZWlnaHQCC3VzZXJBZGRyZXNzDHRhcmdldEhlaWdodAQXYm9vc3RpbmdDb250cmFjdEFkZHJlc3MJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkApggBCQEMZ2V0U3RyT3JGYWlsAgUEdGhpcwUTa2V5Qm9vc3RpbmdDb250cmFjdAIhaW52YWxpZCBib29zdGluZyBjb250cmFjdCBhZGRyZXNzCQCUCgIFA25pbAoAAUAJAPwHBAUXYm9vc3RpbmdDb250cmFjdEFkZHJlc3MCIGdldFVzZXJHd3hBbW91bnRBdEhlaWdodFJFQURPTkxZCQDMCAIFC3VzZXJBZGRyZXNzCQDMCAIFDHRhcmdldEhlaWdodAUDbmlsBQNuaWwDCQABAgUBQAIDSW50BQFACQACAQkArAICCQADAQkA/AcEBRdib29zdGluZ0NvbnRyYWN0QWRkcmVzcwIgZ2V0VXNlckd3eEFtb3VudEF0SGVpZ2h0UkVBRE9OTFkJAMwIAgULdXNlckFkZHJlc3MJAMwIAgUMdGFyZ2V0SGVpZ2h0BQNuaWwFA25pbAIYIGNvdWxkbid0IGJlIGNhc3QgdG8gSW50AWkBC2NvbnN0cnVjdG9yBQ9mYWN0b3J5Q29udHJhY3Qfdm90aW5nRW1pc3Npb25DYW5kaWRhdGVDb250cmFjdBBib29zdGluZ0NvbnRyYWN0D3N0YWtpbmdDb250cmFjdAtlcG9jaExlbmd0aAQFY2hla3MJAMwIAgkBC211c3RNYW5hZ2VyAQUBaQkAzAgCAwkBAiE9AgkApggBBQ9mYWN0b3J5Q29udHJhY3QFBHVuaXQGAiBpbnZhbGlkIGZhY3RvcnkgY29udHJhY3QgYWRkcmVzcwkAzAgCAwkBAiE9AgkApggBBR92b3RpbmdFbWlzc2lvbkNhbmRpZGF0ZUNvbnRyYWN0BQR1bml0BgIyaW52YWxpZCB2b3RpbmcgZW1pc3Npb24gY2FuZGlkYXRlIGNvbnRyYWN0IGFkZHJlc3MJAMwIAgMJAQIhPQIJAKYIAQUQYm9vc3RpbmdDb250cmFjdAUEdW5pdAYCIWludmFsaWQgYm9vc3RpbmcgY29udHJhY3QgYWRkcmVzcwkAzAgCAwkBAiE9AgkApggBBQ9zdGFraW5nQ29udHJhY3QFBHVuaXQGAiBpbnZhbGlkIHN0YWtpbmcgY29udHJhY3QgYWRkcmVzcwkAzAgCAwkAZgIFC2Vwb2NoTGVuZ3RoAAAGCQACAQIUaW52YWxpZCBlcG9jaCBsZW5ndGgFA25pbAMJAAACBQVjaGVrcwUFY2hla3MJAJQKAgkAzAgCCQELU3RyaW5nRW50cnkCBRJrZXlGYWN0b3J5Q29udHJhY3QFD2ZhY3RvcnlDb250cmFjdAkAzAgCCQELU3RyaW5nRW50cnkCBSJrZXlWb3RpbmdFbWlzc2lvbkNhbmRpZGF0ZUNvbnRyYWN0BR92b3RpbmdFbWlzc2lvbkNhbmRpZGF0ZUNvbnRyYWN0CQDMCAIJAQtTdHJpbmdFbnRyeQIFE2tleUJvb3N0aW5nQ29udHJhY3QFEGJvb3N0aW5nQ29udHJhY3QJAMwIAgkBC1N0cmluZ0VudHJ5AgUSa2V5U3Rha2luZ0NvbnRyYWN0BQ9zdGFraW5nQ29udHJhY3QJAMwIAgkBDEludGVnZXJFbnRyeQIFDmtleUVwb2NoTGVuZ3RoBQtlcG9jaExlbmd0aAUDbmlsBQR1bml0CQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBBmNyZWF0ZQINYW1vdW50QXNzZXRJZAxwcmljZUFzc2V0SWQEBmNoZWNrcwkAzAgCAwkAAAIJANgEAQgIBQFpBmNhbGxlcgVieXRlcwkBC3ZhbHVlT3JFbHNlAgkAnQgCBQR0aGlzBSJrZXlWb3RpbmdFbWlzc2lvbkNhbmRpZGF0ZUNvbnRyYWN0AgAGCQELbXVzdE1hbmFnZXIBBQFpBQNuaWwDCQAAAgUGY2hlY2tzBQZjaGVja3MEBHBvb2wJAJQKAgUNYW1vdW50QXNzZXRJZAUMcHJpY2VBc3NldElkBA1pbkxpc3RBY3Rpb25zCQDOCAIJAMwIAgkBDEJvb2xlYW5FbnRyeQIJAQlrZXlJbkxpc3QBBQRwb29sBgUDbmlsCQERaW5zZXJ0Tm9kZUFjdGlvbnMCBQ1wb29sc0xpc3ROYW1lCQEMcG9vbFRvU3RyaW5nAQUEcG9vbAQYY3VycmVudEVwb2NoSXNOb3REZWZpbmVkCQAAAgkAmggCBQR0aGlzBQ9rZXlDdXJyZW50RXBvY2gFBHVuaXQEEnN0YXJ0SGVpZ2h0QWN0aW9ucwMFGGN1cnJlbnRFcG9jaElzTm90RGVmaW5lZAQFZXBvY2gAAAkAzAgCCQEMSW50ZWdlckVudHJ5AgUPa2V5Q3VycmVudEVwb2NoBQVlcG9jaAkAzAgCCQEMSW50ZWdlckVudHJ5AgkBFWtleVN0YXJ0SGVpZ2h0QnlFcG9jaAEFBWVwb2NoBQZoZWlnaHQJAMwIAgkBDEludGVnZXJFbnRyeQIFDmtleVN0YXJ0SGVpZ2h0BQZoZWlnaHQJAMwIAgkBDEludGVnZXJFbnRyeQIFEWtleUN1cnJlbnRFcG9jaFVpBQVlcG9jaAkAzAgCCQEMSW50ZWdlckVudHJ5AgUQa2V5U3RhcnRIZWlnaHRVaQUGaGVpZ2h0BQNuaWwFA25pbAkAlAoCCQDOCAIFDWluTGlzdEFjdGlvbnMFEnN0YXJ0SGVpZ2h0QWN0aW9ucwUEdW5pdAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpAQR2b3RlAw1hbW91bnRBc3NldElkDHByaWNlQXNzZXRJZAZhbW91bnQEBHBvb2wJAJQKAgUNYW1vdW50QXNzZXRJZAUMcHJpY2VBc3NldElkBAVlcG9jaAkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzBQ9rZXlDdXJyZW50RXBvY2gAAAQLc3RhcnRIZWlnaHQJAQxnZXRJbnRPckZhaWwCBQR0aGlzCQEVa2V5U3RhcnRIZWlnaHRCeUVwb2NoAQUFZXBvY2gEC2Vwb2NoTGVuZ3RoCQEMZ2V0SW50T3JGYWlsAgUEdGhpcwUOa2V5RXBvY2hMZW5ndGgECWVuZEhlaWdodAkAZAIFC3N0YXJ0SGVpZ2h0BQtlcG9jaExlbmd0aAQXZmluYWxpemF0aW9uU3RhZ2VPclVuaXQJAJoIAgUEdGhpcwUUa2V5RmluYWxpemF0aW9uU3RhZ2UEBHVzZWQJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwkBB2tleVVzZWQCCAUBaQZjYWxsZXIFBWVwb2NoAAAEBHZvdGUJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwkBB2tleVZvdGUDBQRwb29sCAUBaQZjYWxsZXIFBWVwb2NoAAAECnBvb2xSZXN1bHQJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwkBD2tleVZvdGluZ1Jlc3VsdAIFBHBvb2wFBWVwb2NoAAAECnRvdGFsVm90ZXMJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwkBDWtleVRvdGFsVm90ZXMBBQVlcG9jaAAABBNnd3hBbW91bnRBdEVuZFRvdGFsCgABQAkA/AcEBQR0aGlzAhhnZXRVc2VyR3d4QW1vdW50QXRIZWlnaHQJAMwIAgkA2AQBCAgFAWkGY2FsbGVyBWJ5dGVzCQDMCAIFCWVuZEhlaWdodAUDbmlsBQNuaWwDCQABAgUBQAIDSW50BQFACQACAQkArAICCQADAQkA/AcEBQR0aGlzAhhnZXRVc2VyR3d4QW1vdW50QXRIZWlnaHQJAMwIAgkA2AQBCAgFAWkGY2FsbGVyBWJ5dGVzCQDMCAIFCWVuZEhlaWdodAUDbmlsBQNuaWwCGCBjb3VsZG4ndCBiZSBjYXN0IHRvIEludAQJYXZhaWxhYmxlCQBlAgUTZ3d4QW1vdW50QXRFbmRUb3RhbAUEdXNlZAQHbmV3Vm90ZQkAZAIFBHZvdGUFBmFtb3VudAQKd3hFbWlzc2lvbgkBGGNoZWNrV3hFbWlzc2lvblBvb2xMYWJlbAEFBHBvb2wEBmNoZWNrcwkAzAgCAwkBAiE9AgkAoAgBCQEJa2V5SW5MaXN0AQUEcG9vbAUEdW5pdAYJAAIBAg5pbnZhbGlkIGFzc2V0cwkAzAgCAwkAZgIFCWVuZEhlaWdodAUGaGVpZ2h0BgkAAgECDmludmFsaWQgaGVpZ2h0CQDMCAIDCQAAAgUXZmluYWxpemF0aW9uU3RhZ2VPclVuaXQFBHVuaXQGCQACAQIYZmluYWxpemF0aW9uIGluIHByb2dyZXNzCQDMCAIDCQBmAgUTZ3d4QW1vdW50QXRFbmRUb3RhbAAABgkAAgECE3lvdSBkbyBub3QgaGF2ZSBnV1gJAMwIAgMDCQBmAgUGYW1vdW50AAAJAGcCBQlhdmFpbGFibGUFBmFtb3VudAcGCQACAQIOaW52YWxpZCBhbW91bnQJAMwIAgMFCnd4RW1pc3Npb24GCQACAQIdcG9vbCBoYXNuJ3QgV1hfRU1JU1NJT04gbGFiZWwFA25pbAMJAAACBQZjaGVja3MFBmNoZWNrcwQNdm90ZXNMaXN0TmFtZQkBEGdldFZvdGVzTGlzdE5hbWUBBQRwb29sBA51c2VyQWRkcmVzc1N0cgkApQgBCAUBaQZjYWxsZXIEEHZvdGVzTGlzdEFjdGlvbnMDCQEMY29udGFpbnNOb2RlAgUNdm90ZXNMaXN0TmFtZQUOdXNlckFkZHJlc3NTdHIFA25pbAkBEWluc2VydE5vZGVBY3Rpb25zAgUNdm90ZXNMaXN0TmFtZQUOdXNlckFkZHJlc3NTdHIJAJQKAgkAzggCCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEHa2V5VXNlZAIIBQFpBmNhbGxlcgUFZXBvY2gJAGQCBQR1c2VkBQZhbW91bnQJAMwIAgkBDEludGVnZXJFbnRyeQIJAQdrZXlWb3RlAwUEcG9vbAgFAWkGY2FsbGVyBQVlcG9jaAUHbmV3Vm90ZQkAzAgCCQEMSW50ZWdlckVudHJ5AgkBD2tleVZvdGluZ1Jlc3VsdAIFBHBvb2wFBWVwb2NoCQBkAgUKcG9vbFJlc3VsdAUGYW1vdW50CQDMCAIJAQxJbnRlZ2VyRW50cnkCCQENa2V5VG90YWxWb3RlcwEFBWVwb2NoCQBkAgUKdG90YWxWb3RlcwUGYW1vdW50BQNuaWwFEHZvdGVzTGlzdEFjdGlvbnMFBHVuaXQJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQEKY2FuY2VsVm90ZQINYW1vdW50QXNzZXRJZAxwcmljZUFzc2V0SWQEBHBvb2wJAJQKAgUNYW1vdW50QXNzZXRJZAUMcHJpY2VBc3NldElkBAVlcG9jaAkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzBQ9rZXlDdXJyZW50RXBvY2gAAAQLc3RhcnRIZWlnaHQJAQxnZXRJbnRPckZhaWwCBQR0aGlzCQEVa2V5U3RhcnRIZWlnaHRCeUVwb2NoAQUFZXBvY2gEC2Vwb2NoTGVuZ3RoCQEMZ2V0SW50T3JGYWlsAgUEdGhpcwUOa2V5RXBvY2hMZW5ndGgECWVuZEhlaWdodAkAZAIFC3N0YXJ0SGVpZ2h0BQtlcG9jaExlbmd0aAQXZmluYWxpemF0aW9uU3RhZ2VPclVuaXQJAJoIAgUEdGhpcwUUa2V5RmluYWxpemF0aW9uU3RhZ2UEBHVzZWQJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwkBB2tleVVzZWQCCAUBaQZjYWxsZXIFBWVwb2NoAAAEBHZvdGUJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwkBB2tleVZvdGUDBQRwb29sCAUBaQZjYWxsZXIFBWVwb2NoAAAECnBvb2xSZXN1bHQJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwkBD2tleVZvdGluZ1Jlc3VsdAIFBHBvb2wFBWVwb2NoAAAECnRvdGFsVm90ZXMJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwkBDWtleVRvdGFsVm90ZXMBBQVlcG9jaAAABAZjaGVja3MJAMwIAgMJAQIhPQIJAKAIAQkBCWtleUluTGlzdAEFBHBvb2wFBHVuaXQGCQACAQIOaW52YWxpZCBhc3NldHMJAMwIAgMJAGYCBQllbmRIZWlnaHQFBmhlaWdodAYJAAIBAg5pbnZhbGlkIGhlaWdodAkAzAgCAwkAAAIFF2ZpbmFsaXphdGlvblN0YWdlT3JVbml0BQR1bml0BgkAAgECGGZpbmFsaXphdGlvbiBpbiBwcm9ncmVzcwkAzAgCAwkAZgIFBHZvdGUAAAYJAAIBAgdubyB2b3RlBQNuaWwDCQAAAgUGY2hlY2tzBQZjaGVja3MEDXZvdGVzTGlzdE5hbWUJARBnZXRWb3Rlc0xpc3ROYW1lAQUEcG9vbAQOdXNlckFkZHJlc3NTdHIJAKUIAQgFAWkGY2FsbGVyCQCUCgIJAM4IAgkAzAgCCQEMSW50ZWdlckVudHJ5AgkBB2tleVVzZWQCCAUBaQZjYWxsZXIFBWVwb2NoCQCWAwEJAMwIAgkAZQIFBHVzZWQFBHZvdGUJAMwIAgAABQNuaWwJAMwIAgkBC0RlbGV0ZUVudHJ5AQkBB2tleVZvdGUDBQRwb29sCAUBaQZjYWxsZXIFBWVwb2NoCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEPa2V5Vm90aW5nUmVzdWx0AgUEcG9vbAUFZXBvY2gJAGUCBQpwb29sUmVzdWx0BQR2b3RlCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQENa2V5VG90YWxWb3RlcwEFBWVwb2NoCQBlAgUKdG90YWxWb3RlcwUEdm90ZQUDbmlsCQERZGVsZXRlTm9kZUFjdGlvbnMCBQ12b3Rlc0xpc3ROYW1lBQ51c2VyQWRkcmVzc1N0cgUEdW5pdAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpAQ5zZXRFcG9jaExlbmd0aAEObmV3RXBvY2hMZW5ndGgEBWNoZWtzCQDMCAIJAQttdXN0TWFuYWdlcgEFAWkJAMwIAgMJAGYCBQ5uZXdFcG9jaExlbmd0aAAABgkAAgECFGludmFsaWQgZXBvY2ggbGVuZ3RoBQNuaWwDCQAAAgUFY2hla3MFBWNoZWtzCQCUCgIJAMwIAgkBDEludGVnZXJFbnRyeQIFDmtleUVwb2NoTGVuZ3RoBQ5uZXdFcG9jaExlbmd0aAUDbmlsBQR1bml0CQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBC3NldE1heERlcHRoAQtuZXdNYXhEZXB0aAQFY2hla3MJAMwIAgkBC211c3RNYW5hZ2VyAQUBaQkAzAgCAwkAZgIFC25ld01heERlcHRoAAAGCQACAQIRaW52YWxpZCBtYXggZGVwdGgFA25pbAMJAAACBQVjaGVrcwUFY2hla3MJAJQKAgkAzAgCCQEMSW50ZWdlckVudHJ5AgULa2V5TWF4RGVwdGgFC25ld01heERlcHRoBQNuaWwFBHVuaXQJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQETcHJvY2Vzc1ZvdGVJTlRFUk5BTAIHcG9vbFN0cg51c2VyQWRkcmVzc1N0cgQLY2hlY2tDYWxsZXIJAQhtdXN0VGhpcwEFAWkDCQAAAgULY2hlY2tDYWxsZXIFC2NoZWNrQ2FsbGVyBAt1c2VyQWRkcmVzcwkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCmCAEFDnVzZXJBZGRyZXNzU3RyCQCsAgICKnByb2Nlc3NWb3RlSU5URVJOQUw6IGludmFsaWQgdXNlciBhZGRyZXNzIAUOdXNlckFkZHJlc3NTdHIEBWVwb2NoCQEMZ2V0SW50T3JGYWlsAgUEdGhpcwUPa2V5Q3VycmVudEVwb2NoBA1lcG9jaFByZXZpb3VzCQBlAgUFZXBvY2gAAQQLZXBvY2hMZW5ndGgJAQxnZXRJbnRPckZhaWwCBQR0aGlzBQ5rZXlFcG9jaExlbmd0aAQLc3RhcnRIZWlnaHQJAQxnZXRJbnRPckZhaWwCBQR0aGlzCQEVa2V5U3RhcnRIZWlnaHRCeUVwb2NoAQUFZXBvY2gECWVuZEhlaWdodAkAZAIFC3N0YXJ0SGVpZ2h0BQtlcG9jaExlbmd0aAQTc3RhcnRIZWlnaHRQcmV2aW91cwkBDGdldEludE9yRmFpbAIFBHRoaXMJARVrZXlTdGFydEhlaWdodEJ5RXBvY2gBBQ1lcG9jaFByZXZpb3VzBBFlbmRIZWlnaHRQcmV2aW91cwkAZAIFE3N0YXJ0SGVpZ2h0UHJldmlvdXMFC2Vwb2NoTGVuZ3RoBBBjaGVja1RhcmdldEVwb2NoAwkAZwIFDWVwb2NoUHJldmlvdXMAAAYJAAIBAitwcm9jZXNzVm90ZUlOVEVSTkFMOiBpbnZhbGlkIHByZXZpb3VzIGVwb2NoAwkAAAIFEGNoZWNrVGFyZ2V0RXBvY2gFEGNoZWNrVGFyZ2V0RXBvY2gEBHBvb2wJAQxzdHJpbmdUb1Bvb2wBBQdwb29sU3RyBA0kdDAxNzEyNjE3MTY2BQRwb29sBA1hbW91bnRBc3NldElkCAUNJHQwMTcxMjYxNzE2NgJfMQQMcHJpY2VBc3NldElkCAUNJHQwMTcxMjYxNzE2NgJfMgQKd3hFbWlzc2lvbgkBGGNoZWNrV3hFbWlzc2lvblBvb2xMYWJlbAEFBHBvb2wEE2d3eEFtb3VudEF0RW5kVG90YWwKAAFACQD8BwQFBHRoaXMCGGdldFVzZXJHd3hBbW91bnRBdEhlaWdodAkAzAgCBQ51c2VyQWRkcmVzc1N0cgkAzAgCBQllbmRIZWlnaHQFA25pbAUDbmlsAwkAAQIFAUACA0ludAUBQAkAAgEJAKwCAgkAAwEJAPwHBAUEdGhpcwIYZ2V0VXNlckd3eEFtb3VudEF0SGVpZ2h0CQDMCAIFDnVzZXJBZGRyZXNzU3RyCQDMCAIFCWVuZEhlaWdodAUDbmlsBQNuaWwCGCBjb3VsZG4ndCBiZSBjYXN0IHRvIEludAQbZ3d4QW1vdW50QXRFbmRUb3RhbFByZXZpb3VzCgABQAkA/AcEBQR0aGlzAhhnZXRVc2VyR3d4QW1vdW50QXRIZWlnaHQJAMwIAgUOdXNlckFkZHJlc3NTdHIJAMwIAgURZW5kSGVpZ2h0UHJldmlvdXMFA25pbAUDbmlsAwkAAQIFAUACA0ludAUBQAkAAgEJAKwCAgkAAwEJAPwHBAUEdGhpcwIYZ2V0VXNlckd3eEFtb3VudEF0SGVpZ2h0CQDMCAIFDnVzZXJBZGRyZXNzU3RyCQDMCAIFEWVuZEhlaWdodFByZXZpb3VzBQNuaWwFA25pbAIYIGNvdWxkbid0IGJlIGNhc3QgdG8gSW50BAp0b3RhbFZvdGVzCQELdmFsdWVPckVsc2UCCQCfCAEJAQ1rZXlUb3RhbFZvdGVzAQUFZXBvY2gAAAQMdm90aW5nUmVzdWx0CQELdmFsdWVPckVsc2UCCQCfCAEJAQ9rZXlWb3RpbmdSZXN1bHQCBQRwb29sBQVlcG9jaAAABAx2b3RlUHJldmlvdXMJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAnwgBCQEHa2V5Vm90ZQMFBHBvb2wFC3VzZXJBZGRyZXNzBQ1lcG9jaFByZXZpb3VzCQCsAgIJAKwCAgkArAICCQCsAgICFHByb2Nlc3NWb3RlSU5URVJOQUwgBQdwb29sU3RyAgEgBQ51c2VyQWRkcmVzc1N0cgISOiBubyBwcmV2aW91cyB2b3RlBAR1c2VkCQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMJAQdrZXlVc2VkAgULdXNlckFkZHJlc3MFBWVwb2NoAAAEB25ld1ZvdGUJAGsDBQx2b3RlUHJldmlvdXMFE2d3eEFtb3VudEF0RW5kVG90YWwFG2d3eEFtb3VudEF0RW5kVG90YWxQcmV2aW91cwQHYWN0aW9ucwMDCQBmAgUHbmV3Vm90ZQAABQp3eEVtaXNzaW9uBwkAzAgCCQEMSW50ZWdlckVudHJ5AgkBB2tleVZvdGUDBQRwb29sBQt1c2VyQWRkcmVzcwUFZXBvY2gFB25ld1ZvdGUJAMwIAgkBDEludGVnZXJFbnRyeQIJAQ1rZXlUb3RhbFZvdGVzAQUFZXBvY2gJAGQCBQp0b3RhbFZvdGVzBQduZXdWb3RlCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEPa2V5Vm90aW5nUmVzdWx0AgUEcG9vbAUFZXBvY2gJAGQCBQx2b3RpbmdSZXN1bHQFB25ld1ZvdGUJAMwIAgkBDEludGVnZXJFbnRyeQIJAQdrZXlVc2VkAgULdXNlckFkZHJlc3MFBWVwb2NoCQBkAgUEdXNlZAUHbmV3Vm90ZQUDbmlsCQERZGVsZXRlTm9kZUFjdGlvbnMCCQEQZ2V0Vm90ZXNMaXN0TmFtZQEFBHBvb2wFDnVzZXJBZGRyZXNzU3RyCQCUCgIFB2FjdGlvbnMFBHVuaXQJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQETcHJvY2Vzc1Bvb2xJTlRFUk5BTAEHcG9vbFN0cgQLY2hlY2tDYWxsZXIJAQhtdXN0VGhpcwEFAWkDCQAAAgULY2hlY2tDYWxsZXIFC2NoZWNrQ2FsbGVyBAt0YXJnZXRFcG9jaAkAZQIJAQxnZXRJbnRPckZhaWwCBQR0aGlzBQ9rZXlDdXJyZW50RXBvY2gAAQQQY2hlY2tUYXJnZXRFcG9jaAMJAGcCBQt0YXJnZXRFcG9jaAAABgkAAgECKXByb2Nlc3NQb29sSU5URVJOQUw6IGludmFsaWQgdGFyZ2V0IGVwb2NoAwkAAAIFEGNoZWNrVGFyZ2V0RXBvY2gFEGNoZWNrVGFyZ2V0RXBvY2gEBHBvb2wJAQxzdHJpbmdUb1Bvb2wBBQdwb29sU3RyBA0kdDAxODY4MzE4NzIzBQRwb29sBA1hbW91bnRBc3NldElkCAUNJHQwMTg2ODMxODcyMwJfMQQMcHJpY2VBc3NldElkCAUNJHQwMTg2ODMxODcyMwJfMgQPc3Rha2luZ0NvbnRyYWN0CQERQGV4dHJOYXRpdmUoMTA2MikBCQEMZ2V0U3RyT3JGYWlsAgUEdGhpcwUSa2V5U3Rha2luZ0NvbnRyYWN0BA9mYWN0b3J5Q29udHJhY3QJARFAZXh0ck5hdGl2ZSgxMDYyKQEJAQxnZXRTdHJPckZhaWwCBQR0aGlzBRJrZXlGYWN0b3J5Q29udHJhY3QECWxwQXNzZXRJZAkBFmdldExwQXNzZXRCeVBvb2xBc3NldHMCBQ1hbW91bnRBc3NldElkBQxwcmljZUFzc2V0SWQEAXIKAAFACQD8BwQFD3N0YWtpbmdDb250cmFjdAISdXNlcnNMaXN0VHJhdmVyc2FsCQDMCAIFCWxwQXNzZXRJZAUDbmlsBQNuaWwDCQABAgUBQAIHQm9vbGVhbgUBQAkAAgEJAKwCAgkAAwEJAPwHBAUPc3Rha2luZ0NvbnRyYWN0AhJ1c2Vyc0xpc3RUcmF2ZXJzYWwJAMwIAgUJbHBBc3NldElkBQNuaWwFA25pbAIcIGNvdWxkbid0IGJlIGNhc3QgdG8gQm9vbGVhbgMJAAACBQFyBQFyAwUBcgkAlAoCBQNuaWwGBAp3eEVtaXNzaW9uCQEYY2hlY2tXeEVtaXNzaW9uUG9vbExhYmVsAQUEcG9vbAQKdG90YWxWb3RlcwkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzCQENa2V5VG90YWxWb3RlcwEFC3RhcmdldEVwb2NoAAAEDHZvdGluZ1Jlc3VsdAkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzCQEPa2V5Vm90aW5nUmVzdWx0AgUEcG9vbAULdGFyZ2V0RXBvY2gAAAQFc2hhcmUDAwkAAAIFCnRvdGFsVm90ZXMAAAYJAQEhAQUKd3hFbWlzc2lvbgAACQBrAwUMdm90aW5nUmVzdWx0BQ5wb29sV2VpZ2h0TXVsdAUKdG90YWxWb3RlcwQPbW9kaWZ5V2VpZ2h0SW52CQD8BwQFD2ZhY3RvcnlDb250cmFjdAIMbW9kaWZ5V2VpZ2h0CQDMCAIFCWxwQXNzZXRJZAkAzAgCBQVzaGFyZQUDbmlsBQNuaWwDCQAAAgUPbW9kaWZ5V2VpZ2h0SW52BQ9tb2RpZnlXZWlnaHRJbnYEEHBvb2xzTGlzdEFjdGlvbnMDBQp3eEVtaXNzaW9uBQNuaWwJAM4IAgkAzAgCCQELRGVsZXRlRW50cnkBCQEJa2V5SW5MaXN0AQUEcG9vbAUDbmlsCQERZGVsZXRlTm9kZUFjdGlvbnMCBQ1wb29sc0xpc3ROYW1lBQdwb29sU3RyCQCUCgIJAM4IAgkAzAgCCQEMSW50ZWdlckVudHJ5AgkBDGtleVBvb2xTaGFyZQIFBHBvb2wFC3RhcmdldEVwb2NoBQVzaGFyZQUDbmlsBRBwb29sc0xpc3RBY3Rpb25zBwkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpAQ5maW5hbGl6ZUhlbHBlcgAEBWVwb2NoCQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMFD2tleUN1cnJlbnRFcG9jaAAABA1wcmV2aW91c0Vwb2NoCQBlAgUFZXBvY2gAAQQLc3RhcnRIZWlnaHQJAQxnZXRJbnRPckZhaWwCBQR0aGlzCQEVa2V5U3RhcnRIZWlnaHRCeUVwb2NoAQUFZXBvY2gEC2Vwb2NoTGVuZ3RoCQEMZ2V0SW50T3JGYWlsAgUEdGhpcwUOa2V5RXBvY2hMZW5ndGgECWVuZEhlaWdodAkAZAIFC3N0YXJ0SGVpZ2h0BQtlcG9jaExlbmd0aAQXZmluYWxpemF0aW9uU3RhZ2VPclVuaXQJAJoIAgUEdGhpcwUUa2V5RmluYWxpemF0aW9uU3RhZ2UDCQBnAgUGaGVpZ2h0BQllbmRIZWlnaHQECG5ld0Vwb2NoCQBkAgUFZXBvY2gAAQkAlAoCCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEVa2V5U3RhcnRIZWlnaHRCeUVwb2NoAQUIbmV3RXBvY2gFBmhlaWdodAkAzAgCCQEMSW50ZWdlckVudHJ5AgUOa2V5U3RhcnRIZWlnaHQFBmhlaWdodAkAzAgCCQEMSW50ZWdlckVudHJ5AgUPa2V5Q3VycmVudEVwb2NoBQhuZXdFcG9jaAkAzAgCCQEMSW50ZWdlckVudHJ5AgUUa2V5RmluYWxpemF0aW9uU3RhZ2UFFmZpbmFsaXphdGlvblN0YWdlVG90YWwFA25pbAYDCQAAAgUXZmluYWxpemF0aW9uU3RhZ2VPclVuaXQFBHVuaXQJAJQKAgUDbmlsBwMJAAACBRdmaW5hbGl6YXRpb25TdGFnZU9yVW5pdAUWZmluYWxpemF0aW9uU3RhZ2VUb3RhbAQKcG9vbE9yVW5pdAkAoggBBQtrZXlOZXh0UG9vbAQKdXNlck9yVW5pdAkAoggBBQtrZXlOZXh0VXNlcgQHJG1hdGNoMAUKcG9vbE9yVW5pdAMJAAECBQckbWF0Y2gwAgRVbml0BAckbWF0Y2gxCQCiCAEJAQtrZXlMaXN0SGVhZAEFDXBvb2xzTGlzdE5hbWUDCQABAgUHJG1hdGNoMQIEVW5pdAkAlAoCCQDMCAIJAQxJbnRlZ2VyRW50cnkCBRRrZXlGaW5hbGl6YXRpb25TdGFnZQUXZmluYWxpemF0aW9uU3RhZ2VTaGFyZXMJAMwIAgkBC0RlbGV0ZUVudHJ5AQULa2V5TmV4dFBvb2wJAMwIAgkBC0RlbGV0ZUVudHJ5AQULa2V5TmV4dFVzZXIFA25pbAYDCQABAgUHJG1hdGNoMQIGU3RyaW5nBAxwb29sc0hlYWRTdHIFByRtYXRjaDEJAJQKAgkAzAgCCQELU3RyaW5nRW50cnkCBQtrZXlOZXh0UG9vbAUMcG9vbHNIZWFkU3RyBQNuaWwGCQACAQILTWF0Y2ggZXJyb3IDCQABAgUHJG1hdGNoMAIGU3RyaW5nBAdwb29sU3RyBQckbWF0Y2gwBARwb29sCQEMc3RyaW5nVG9Qb29sAQUHcG9vbFN0cgQObmV4dFVzZXJPclVuaXQEByRtYXRjaDEFCnVzZXJPclVuaXQDCQABAgUHJG1hdGNoMQIEVW5pdAkAoggBCQELa2V5TGlzdEhlYWQBCQEQZ2V0Vm90ZXNMaXN0TmFtZQEFBHBvb2wDCQABAgUHJG1hdGNoMQIGU3RyaW5nBAR1c2VyBQckbWF0Y2gxBA5wcm9jZXNzVm90ZUludgkA/AcEBQR0aGlzAhNwcm9jZXNzVm90ZUlOVEVSTkFMCQDMCAIFB3Bvb2xTdHIJAMwIAgUEdXNlcgUDbmlsBQNuaWwDCQAAAgUOcHJvY2Vzc1ZvdGVJbnYFDnByb2Nlc3NWb3RlSW52CQCiCAEJAQtrZXlMaXN0TmV4dAIJARBnZXRWb3Rlc0xpc3ROYW1lAQUEcG9vbAUEdXNlcgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECC01hdGNoIGVycm9yBAckbWF0Y2gxBQ5uZXh0VXNlck9yVW5pdAMJAAECBQckbWF0Y2gxAgRVbml0BA5uZXh0UG9vbE9yVW5pdAkAoggBCQELa2V5TGlzdE5leHQCBQ1wb29sc0xpc3ROYW1lBQdwb29sU3RyBAckbWF0Y2gyBQ5uZXh0UG9vbE9yVW5pdAMJAAECBQckbWF0Y2gyAgRVbml0CQCUCgIJAMwIAgkBDEludGVnZXJFbnRyeQIFFGtleUZpbmFsaXphdGlvblN0YWdlBRdmaW5hbGl6YXRpb25TdGFnZVNoYXJlcwkAzAgCCQELRGVsZXRlRW50cnkBBQtrZXlOZXh0UG9vbAkAzAgCCQELRGVsZXRlRW50cnkBBQtrZXlOZXh0VXNlcgUDbmlsBgMJAAECBQckbWF0Y2gyAgZTdHJpbmcEAXMFByRtYXRjaDIJAJQKAgkAzAgCCQELU3RyaW5nRW50cnkCBQtrZXlOZXh0UG9vbAUBcwkAzAgCCQELRGVsZXRlRW50cnkBBQtrZXlOZXh0VXNlcgUDbmlsBgkAAgECC01hdGNoIGVycm9yAwkAAQIFByRtYXRjaDECBlN0cmluZwQIbmV4dFVzZXIFByRtYXRjaDEJAJQKAgkAzAgCCQELU3RyaW5nRW50cnkCBQtrZXlOZXh0VXNlcgUIbmV4dFVzZXIFA25pbAYJAAIBAgtNYXRjaCBlcnJvcgkAAgECC01hdGNoIGVycm9yAwkAAAIFF2ZpbmFsaXphdGlvblN0YWdlT3JVbml0BRdmaW5hbGl6YXRpb25TdGFnZVNoYXJlcwQKcG9vbE9yVW5pdAkAoggBBQtrZXlOZXh0UG9vbAQHJG1hdGNoMAUKcG9vbE9yVW5pdAMJAAECBQckbWF0Y2gwAgRVbml0BAckbWF0Y2gxCQCiCAEJAQtrZXlMaXN0SGVhZAEFDXBvb2xzTGlzdE5hbWUDCQABAgUHJG1hdGNoMQIEVW5pdAkAlAoCCQDMCAIJAQtEZWxldGVFbnRyeQEFFGtleUZpbmFsaXphdGlvblN0YWdlCQDMCAIJAQxCb29sZWFuRW50cnkCCQEMa2V5RmluYWxpemVkAQUNcHJldmlvdXNFcG9jaAYJAMwIAgkBDEludGVnZXJFbnRyeQIFEWtleUN1cnJlbnRFcG9jaFVpBQVlcG9jaAkAzAgCCQEMSW50ZWdlckVudHJ5AgUQa2V5U3RhcnRIZWlnaHRVaQULc3RhcnRIZWlnaHQFA25pbAYDCQABAgUHJG1hdGNoMQIGU3RyaW5nBAtuZXh0UG9vbFN0cgUHJG1hdGNoMQkAlAoCCQDMCAIJAQtTdHJpbmdFbnRyeQIFC2tleU5leHRQb29sBQtuZXh0UG9vbFN0cgUDbmlsBgkAAgECC01hdGNoIGVycm9yAwkAAQIFByRtYXRjaDACBlN0cmluZwQHcG9vbFN0cgUHJG1hdGNoMAQBcgoAAUAJAPwHBAUEdGhpcwITcHJvY2Vzc1Bvb2xJTlRFUk5BTAkAzAgCBQdwb29sU3RyBQNuaWwFA25pbAMJAAECBQFAAgdCb29sZWFuBQFACQACAQkArAICCQADAQkA/AcEBQR0aGlzAhNwcm9jZXNzUG9vbElOVEVSTkFMCQDMCAIFB3Bvb2xTdHIFA25pbAUDbmlsAhwgY291bGRuJ3QgYmUgY2FzdCB0byBCb29sZWFuAwkAAAIFAXIFAXIDBQFyCQCUCgIFA25pbAYEDm5leHRQb29sT3JVbml0CQCiCAEJAQtrZXlMaXN0TmV4dAIFDXBvb2xzTGlzdE5hbWUFB3Bvb2xTdHIEByRtYXRjaDEFDm5leHRQb29sT3JVbml0AwkAAQIFByRtYXRjaDECBFVuaXQJAJQKAgkAzAgCCQELRGVsZXRlRW50cnkBBRRrZXlGaW5hbGl6YXRpb25TdGFnZQkAzAgCCQEMQm9vbGVhbkVudHJ5AgkBDGtleUZpbmFsaXplZAEFDXByZXZpb3VzRXBvY2gGCQDMCAIJAQxJbnRlZ2VyRW50cnkCBRFrZXlDdXJyZW50RXBvY2hVaQUFZXBvY2gJAMwIAgkBDEludGVnZXJFbnRyeQIFEGtleVN0YXJ0SGVpZ2h0VWkFC3N0YXJ0SGVpZ2h0CQDMCAIJAQtEZWxldGVFbnRyeQEFC2tleU5leHRQb29sBQNuaWwGAwkAAQIFByRtYXRjaDECBlN0cmluZwQLbmV4dFBvb2xTdHIFByRtYXRjaDEJAJQKAgkAzAgCCQELU3RyaW5nRW50cnkCBQtrZXlOZXh0UG9vbAULbmV4dFBvb2xTdHIFA25pbAYJAAIBAgtNYXRjaCBlcnJvcgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECC01hdGNoIGVycm9yCQACAQIWZmluYWxpemF0aW9uIGlzIGJyb2tlbgFpAQ9maW5hbGl6ZVdyYXBwZXIBB2NvdW50ZXIEBnJlc3VsdAoAAUAJAPwHBAUEdGhpcwIOZmluYWxpemVIZWxwZXIFA25pbAUDbmlsAwkAAQIFAUACB0Jvb2xlYW4FAUAJAAIBCQCsAgIJAAMBCQD8BwQFBHRoaXMCDmZpbmFsaXplSGVscGVyBQNuaWwFA25pbAIcIGNvdWxkbid0IGJlIGNhc3QgdG8gQm9vbGVhbgMJAAACBQZyZXN1bHQFBnJlc3VsdAMJAQEhAQUGcmVzdWx0AwkAAAIFB2NvdW50ZXIAAAkAAgECHkN1cnJlbnQgdm90aW5nIGlzIG5vdCBvdmVyIHlldAkAlAoCBQNuaWwFBHVuaXQECG1heERlcHRoCQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMFC2tleU1heERlcHRoBQ9tYXhEZXB0aERlZmF1bHQDCQBmAgUIbWF4RGVwdGgFB2NvdW50ZXIEA2ludgkA/AcEBQR0aGlzAg9maW5hbGl6ZVdyYXBwZXIJAMwIAgkAZAIFB2NvdW50ZXIAAQUDbmlsBQNuaWwDCQAAAgUDaW52BQNpbnYJAJQKAgUDbmlsBQR1bml0CQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQCUCgIFA25pbAUEdW5pdAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpAQhmaW5hbGl6ZQAEA2ludgkA/AcEBQR0aGlzAg9maW5hbGl6ZVdyYXBwZXIJAMwIAgAABQNuaWwFA25pbAMJAAACBQNpbnYFA2ludgkAlAoCBQNuaWwFBHVuaXQJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQEUY29udGFpbnNOb2RlUkVBRE9OTFkCCGxpc3ROYW1lAmlkCQCUCgIFA25pbAkBDGNvbnRhaW5zTm9kZQIFCGxpc3ROYW1lBQJpZAFpAQppbnNlcnROb2RlAghsaXN0TmFtZQJpZAQLY2hlY2tDYWxsZXIJAQttdXN0TWFuYWdlcgEFAWkDCQAAAgULY2hlY2tDYWxsZXIFC2NoZWNrQ2FsbGVyCQCUCgIJARFpbnNlcnROb2RlQWN0aW9ucwIFCGxpc3ROYW1lBQJpZAUEdW5pdAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpAQpkZWxldGVOb2RlAghsaXN0TmFtZQJpZAQLY2hlY2tDYWxsZXIJAQttdXN0TWFuYWdlcgEFAWkDCQAAAgULY2hlY2tDYWxsZXIFC2NoZWNrQ2FsbGVyCQCUCgIJARFkZWxldGVOb2RlQWN0aW9ucwIFCGxpc3ROYW1lBQJpZAUEdW5pdAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgECdHgBBnZlcmlmeQAED3RhcmdldFB1YmxpY0tleQQHJG1hdGNoMAkBFm1hbmFnZXJQdWJsaWNLZXlPclVuaXQAAwkAAQIFByRtYXRjaDACCkJ5dGVWZWN0b3IEAnBrBQckbWF0Y2gwBQJwawMJAAECBQckbWF0Y2gwAgRVbml0CAUCdHgPc2VuZGVyUHVibGljS2V5CQACAQILTWF0Y2ggZXJyb3IJAPQDAwgFAnR4CWJvZHlCeXRlcwkAkQMCCAUCdHgGcHJvb2ZzAAAFD3RhcmdldFB1YmxpY0tleZ/L8iE=", "chainId": 84, "height": 2108948, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: AXzJC9BUQaA72N1C1gr4GTjq79rfc4Xrgevf5Zt8QNGy Next: GvuF2Yy9orGrMbEDXR5znjDYGTHVTLhSMYqecRHSpKeR Diff:
OldNewDifferences
2525
2626 let keyStakingContract = makeString(["%s", "stakingContract"], separator)
2727
28-let keyAssetsStoreContract = makeString(["%s", "assetsStoreContract"], separator)
29-
3028 let keyFinalizationStage = makeString(["%s", "finalizationStage"], separator)
3129
3230 let keyNextPool = makeString(["%s", "nextPool"], separator)
4644
4745
4846 func keyInList (pool) = {
49- let $t015171557 = pool
50- let amountAssetId = $t015171557._1
51- let priceAssetId = $t015171557._2
47+ let $t014361476 = pool
48+ let amountAssetId = $t014361476._1
49+ let priceAssetId = $t014361476._2
5250 makeString(["%s%s%s", "inList", amountAssetId, priceAssetId], separator)
5351 }
5452
5755
5856
5957 func keyVote (pool,address,epoch) = {
60- let $t018311871 = pool
61- let amountAssetId = $t018311871._1
62- let priceAssetId = $t018311871._2
58+ let $t017501790 = pool
59+ let amountAssetId = $t017501790._1
60+ let priceAssetId = $t017501790._2
6361 makeString(["%s%s%s%s%d", "vote", amountAssetId, priceAssetId, toString(address), toString(epoch)], separator)
6462 }
6563
6664
6765 func keyVotingResult (pool,epoch) = {
68- let $t020532093 = pool
69- let amountAssetId = $t020532093._1
70- let priceAssetId = $t020532093._2
66+ let $t019722012 = pool
67+ let amountAssetId = $t019722012._1
68+ let priceAssetId = $t019722012._2
7169 makeString(["%s%s%s%d", "votingResult", amountAssetId, priceAssetId, toString(epoch)], separator)
7270 }
7371
7472
7573 func keyPoolShare (pool,epoch) = {
76- let $t022582298 = pool
77- let amountAssetId = $t022582298._1
78- let priceAssetId = $t022582298._2
74+ let $t021772217 = pool
75+ let amountAssetId = $t021772217._1
76+ let priceAssetId = $t021772217._2
7977 makeString(["%s%s%s%d", "poolShare", amountAssetId, priceAssetId, toString(epoch)], separator)
8078 }
8179
139137 }
140138
141139
142-func isAssetVerified (assetId) = {
143- let assetsStoreContract = addressFromStringValue(getStrOrFail(this, keyAssetsStoreContract))
144- let isVerified = {
145- let @ = invoke(assetsStoreContract, "isVerifiedREADONLY", [assetId], nil)
146- if ($isInstanceOf(@, "Boolean"))
147- then @
148- else throw(($getType(invoke(assetsStoreContract, "isVerifiedREADONLY", [assetId], nil)) + " couldn't be cast to Boolean"))
149- }
150- isVerified
140+func checkWxEmissionPoolLabel (pool) = {
141+ let $t044594499 = pool
142+ let amountAssetId = $t044594499._1
143+ let priceAssetId = $t044594499._2
144+ let factoryContract = addressFromStringValue(getStrOrFail(this, keyFactoryContract))
145+ let @ = invoke(factoryContract, "checkWxEmissionPoolLabel", [amountAssetId, priceAssetId], nil)
146+ if ($isInstanceOf(@, "Boolean"))
147+ then @
148+ else throw(($getType(invoke(factoryContract, "checkWxEmissionPoolLabel", [amountAssetId, priceAssetId], nil)) + " couldn't be cast to Boolean"))
151149 }
152150
153151
154152 let poolsListName = "pools"
155153
156154 func getVotesListName (pool) = {
157- let $t048384878 = pool
158- let amountAssetId = $t048384878._1
159- let priceAssetId = $t048384878._2
155+ let $t048004840 = pool
156+ let amountAssetId = $t048004840._1
157+ let priceAssetId = $t048004840._2
160158 makeString(["votes", amountAssetId, priceAssetId], separator)
161159 }
162160
332330
333331
334332 @Callable(i)
335-func constructor (factoryContract,votingEmissionCandidateContract,boostingContract,stakingContract,assetsStoreContract,epochLength) = {
333+func constructor (factoryContract,votingEmissionCandidateContract,boostingContract,stakingContract,epochLength) = {
336334 let cheks = [mustManager(i), if ((addressFromString(factoryContract) != unit))
337335 then true
338336 else "invalid factory contract address", if ((addressFromString(votingEmissionCandidateContract) != unit))
341339 then true
342340 else "invalid boosting contract address", if ((addressFromString(stakingContract) != unit))
343341 then true
344- else "invalid staking contract address", if ((addressFromString(assetsStoreContract) != unit))
345- then true
346- else "invalid assets store contract address", if ((epochLength > 0))
342+ else "invalid staking contract address", if ((epochLength > 0))
347343 then true
348344 else throw("invalid epoch length")]
349345 if ((cheks == cheks))
350- then $Tuple2([StringEntry(keyFactoryContract, factoryContract), StringEntry(keyVotingEmissionCandidateContract, votingEmissionCandidateContract), StringEntry(keyBoostingContract, boostingContract), StringEntry(keyStakingContract, stakingContract), StringEntry(keyAssetsStoreContract, assetsStoreContract), IntegerEntry(keyEpochLength, epochLength)], unit)
346+ then $Tuple2([StringEntry(keyFactoryContract, factoryContract), StringEntry(keyVotingEmissionCandidateContract, votingEmissionCandidateContract), StringEntry(keyBoostingContract, boostingContract), StringEntry(keyStakingContract, stakingContract), IntegerEntry(keyEpochLength, epochLength)], unit)
351347 else throw("Strict value is not equal to itself.")
352348 }
353349
396392 }
397393 let available = (gwxAmountAtEndTotal - used)
398394 let newVote = (vote + amount)
399- let isAmountAssetVerified = isAssetVerified(amountAssetId)
395+ let wxEmission = checkWxEmissionPoolLabel(pool)
400396 let checks = [if ((getBoolean(keyInList(pool)) != unit))
401397 then true
402398 else throw("invalid assets"), if ((endHeight > height))
409405 then (available >= amount)
410406 else false)
411407 then true
412- else throw("invalid amount"), if (isAmountAssetVerified)
408+ else throw("invalid amount"), if (wxEmission)
413409 then true
414- else throw("amount asset is not verified")]
410+ else throw("pool hasn't WX_EMISSION label")]
415411 if ((checks == checks))
416412 then {
417413 let votesListName = getVotesListName(pool)
501497 if ((checkTargetEpoch == checkTargetEpoch))
502498 then {
503499 let pool = stringToPool(poolStr)
504- let $t01741817458 = pool
505- let amountAssetId = $t01741817458._1
506- let priceAssetId = $t01741817458._2
507- let isAmountAssetVerified = isAssetVerified(amountAssetId)
500+ let $t01712617166 = pool
501+ let amountAssetId = $t01712617166._1
502+ let priceAssetId = $t01712617166._2
503+ let wxEmission = checkWxEmissionPoolLabel(pool)
508504 let gwxAmountAtEndTotal = {
509505 let @ = invoke(this, "getUserGwxAmountAtHeight", [userAddressStr, endHeight], nil)
510506 if ($isInstanceOf(@, "Int"))
523519 let used = valueOrElse(getInteger(this, keyUsed(userAddress, epoch)), 0)
524520 let newVote = fraction(votePrevious, gwxAmountAtEndTotal, gwxAmountAtEndTotalPrevious)
525521 let actions = if (if ((newVote > 0))
526- then isAmountAssetVerified
522+ then wxEmission
527523 else false)
528524 then [IntegerEntry(keyVote(pool, userAddress, epoch), newVote), IntegerEntry(keyTotalVotes(epoch), (totalVotes + newVote)), IntegerEntry(keyVotingResult(pool, epoch), (votingResult + newVote)), IntegerEntry(keyUsed(userAddress, epoch), (used + newVote))]
529525 else deleteNodeActions(getVotesListName(pool), userAddressStr)
548544 if ((checkTargetEpoch == checkTargetEpoch))
549545 then {
550546 let pool = stringToPool(poolStr)
551- let $t01899719037 = pool
552- let amountAssetId = $t01899719037._1
553- let priceAssetId = $t01899719037._2
547+ let $t01868318723 = pool
548+ let amountAssetId = $t01868318723._1
549+ let priceAssetId = $t01868318723._2
554550 let stakingContract = addressFromStringValue(getStrOrFail(this, keyStakingContract))
555551 let factoryContract = addressFromStringValue(getStrOrFail(this, keyFactoryContract))
556552 let lpAssetId = getLpAssetByPoolAssets(amountAssetId, priceAssetId)
564560 then if (r)
565561 then $Tuple2(nil, true)
566562 else {
567- let isAmountAssetVerified = isAssetVerified(amountAssetId)
563+ let wxEmission = checkWxEmissionPoolLabel(pool)
568564 let totalVotes = valueOrElse(getInteger(this, keyTotalVotes(targetEpoch)), 0)
569565 let votingResult = valueOrElse(getInteger(this, keyVotingResult(pool, targetEpoch)), 0)
570566 let share = if (if ((totalVotes == 0))
571567 then true
572- else !(isAmountAssetVerified))
568+ else !(wxEmission))
573569 then 0
574570 else fraction(votingResult, poolWeightMult, totalVotes)
575571 let modifyWeightInv = invoke(factoryContract, "modifyWeight", [lpAssetId, share], nil)
576572 if ((modifyWeightInv == modifyWeightInv))
577573 then {
578- let poolsListActions = if (isAmountAssetVerified)
574+ let poolsListActions = if (wxEmission)
579575 then nil
580576 else ([DeleteEntry(keyInList(pool))] ++ deleteNodeActions(poolsListName, poolStr))
581577 $Tuple2(([IntegerEntry(keyPoolShare(pool, targetEpoch), share)] ++ poolsListActions), false)
737733
738734
739735 @Callable(i)
740-func onVerificationLoss (assetId) = $Tuple2(nil, unit)
741-
742-
743-
744-@Callable(i)
745736 func containsNodeREADONLY (listName,id) = $Tuple2(nil, containsNode(listName, id))
746737
747738
Full:
OldNewDifferences
11 {-# STDLIB_VERSION 6 #-}
22 {-# SCRIPT_TYPE ACCOUNT #-}
33 {-# CONTENT_TYPE DAPP #-}
44 let separator = "__"
55
66 let poolWeightMult = 100000000
77
88 let maxDepthDefault = 10
99
1010 let finalizationStageTotal = 0
1111
1212 let finalizationStageShares = 1
1313
1414 let keyEpochLength = makeString(["%s", "epochLength"], separator)
1515
1616 let keyCurrentEpoch = makeString(["%s", "currentEpoch"], separator)
1717
1818 let keyMaxDepth = makeString(["%s", "maxDepth"], separator)
1919
2020 let keyVotingEmissionCandidateContract = makeString(["%s", "votingEmissionCandidateContract"], separator)
2121
2222 let keyFactoryContract = makeString(["%s", "factoryContract"], separator)
2323
2424 let keyBoostingContract = makeString(["%s", "boostingContract"], separator)
2525
2626 let keyStakingContract = makeString(["%s", "stakingContract"], separator)
2727
28-let keyAssetsStoreContract = makeString(["%s", "assetsStoreContract"], separator)
29-
3028 let keyFinalizationStage = makeString(["%s", "finalizationStage"], separator)
3129
3230 let keyNextPool = makeString(["%s", "nextPool"], separator)
3331
3432 let keyNextUser = makeString(["%s", "nextUser"], separator)
3533
3634 let keyStartHeight = makeString(["%s", "startHeight"], separator)
3735
3836 let keyCurrentEpochUi = makeString(["%s", "currentEpochUi"], separator)
3937
4038 let keyStartHeightUi = makeString(["%s", "startHeightUi"], separator)
4139
4240 func keyStartHeightByEpoch (epoch) = makeString(["%s%d", "startHeight", toString(epoch)], separator)
4341
4442
4543 func keyFinalized (epoch) = makeString(["%s%d", "finalized", toString(epoch)], separator)
4644
4745
4846 func keyInList (pool) = {
49- let $t015171557 = pool
50- let amountAssetId = $t015171557._1
51- let priceAssetId = $t015171557._2
47+ let $t014361476 = pool
48+ let amountAssetId = $t014361476._1
49+ let priceAssetId = $t014361476._2
5250 makeString(["%s%s%s", "inList", amountAssetId, priceAssetId], separator)
5351 }
5452
5553
5654 func keyUsed (address,epoch) = makeString(["%s%s%d", "used", toString(address), toString(epoch)], separator)
5755
5856
5957 func keyVote (pool,address,epoch) = {
60- let $t018311871 = pool
61- let amountAssetId = $t018311871._1
62- let priceAssetId = $t018311871._2
58+ let $t017501790 = pool
59+ let amountAssetId = $t017501790._1
60+ let priceAssetId = $t017501790._2
6361 makeString(["%s%s%s%s%d", "vote", amountAssetId, priceAssetId, toString(address), toString(epoch)], separator)
6462 }
6563
6664
6765 func keyVotingResult (pool,epoch) = {
68- let $t020532093 = pool
69- let amountAssetId = $t020532093._1
70- let priceAssetId = $t020532093._2
66+ let $t019722012 = pool
67+ let amountAssetId = $t019722012._1
68+ let priceAssetId = $t019722012._2
7169 makeString(["%s%s%s%d", "votingResult", amountAssetId, priceAssetId, toString(epoch)], separator)
7270 }
7371
7472
7573 func keyPoolShare (pool,epoch) = {
76- let $t022582298 = pool
77- let amountAssetId = $t022582298._1
78- let priceAssetId = $t022582298._2
74+ let $t021772217 = pool
75+ let amountAssetId = $t021772217._1
76+ let priceAssetId = $t021772217._2
7977 makeString(["%s%s%s%d", "poolShare", amountAssetId, priceAssetId, toString(epoch)], separator)
8078 }
8179
8280
8381 func keyTotalVotes (epoch) = makeString(["%s%d", "totalVotes", toString(epoch)], separator)
8482
8583
8684 func getValueOrFail (address,key,type) = {
8785 let error = makeString(["mandatory ", toString(address), ".", key, " is not defined"], "")
8886 valueOrErrorMessage( match type {
8987 case str: String =>
9088 getString(address, key)
9189 case int: Int =>
9290 getInteger(address, key)
9391 case _ =>
9492 throw("invalid entry type")
9593 }, error)
9694 }
9795
9896
9997 func getStrOrFail (address,key) = {
10098 let @ = getValueOrFail(address, key, "")
10199 if ($isInstanceOf(@, "String"))
102100 then @
103101 else throw(($getType(getValueOrFail(address, key, "")) + " couldn't be cast to String"))
104102 }
105103
106104
107105 func getIntOrFail (address,key) = {
108106 let @ = getValueOrFail(address, key, 0)
109107 if ($isInstanceOf(@, "Int"))
110108 then @
111109 else throw(($getType(getValueOrFail(address, key, 0)) + " couldn't be cast to Int"))
112110 }
113111
114112
115113 func poolToString (pool) = ((pool._1 + separator) + pool._2)
116114
117115
118116 func stringToPool (str) = {
119117 let parts = split(str, separator)
120118 if ((size(parts) == 2))
121119 then $Tuple2(parts[0], parts[1])
122120 else throw("invalid pool string")
123121 }
124122
125123
126124 func getLpAssetByPoolAssets (amountAssetId,priceAssetId) = {
127125 func keyMappingsBaseAsset2internalId (baseAssetStr) = ("%s%s%s__mappings__baseAsset2internalId__" + baseAssetStr)
128126
129127 func keyMappingPoolAssetsToPoolContractAddress (internalAmountAssetIdStr,internalPriceAssetIdStr) = (((("%d%d%s%s__" + toString(internalAmountAssetIdStr)) + "__") + toString(internalPriceAssetIdStr)) + "__mappings__poolAssets2PoolContract")
130128
131129 func keyMappingPoolContractToLPAsset (poolContractAddress) = (("%s%s%s__" + poolContractAddress) + "__mappings__poolContract2LpAsset")
132130
133131 let factoryContract = addressFromStringValue(getStrOrFail(this, keyFactoryContract))
134132 let amountAssetInternalId = getIntOrFail(factoryContract, keyMappingsBaseAsset2internalId(amountAssetId))
135133 let priceAssetInternalId = getIntOrFail(factoryContract, keyMappingsBaseAsset2internalId(priceAssetId))
136134 let poolContractAddress = getStrOrFail(factoryContract, keyMappingPoolAssetsToPoolContractAddress(amountAssetInternalId, priceAssetInternalId))
137135 let lpAssetId = getStrOrFail(factoryContract, keyMappingPoolContractToLPAsset(poolContractAddress))
138136 lpAssetId
139137 }
140138
141139
142-func isAssetVerified (assetId) = {
143- let assetsStoreContract = addressFromStringValue(getStrOrFail(this, keyAssetsStoreContract))
144- let isVerified = {
145- let @ = invoke(assetsStoreContract, "isVerifiedREADONLY", [assetId], nil)
146- if ($isInstanceOf(@, "Boolean"))
147- then @
148- else throw(($getType(invoke(assetsStoreContract, "isVerifiedREADONLY", [assetId], nil)) + " couldn't be cast to Boolean"))
149- }
150- isVerified
140+func checkWxEmissionPoolLabel (pool) = {
141+ let $t044594499 = pool
142+ let amountAssetId = $t044594499._1
143+ let priceAssetId = $t044594499._2
144+ let factoryContract = addressFromStringValue(getStrOrFail(this, keyFactoryContract))
145+ let @ = invoke(factoryContract, "checkWxEmissionPoolLabel", [amountAssetId, priceAssetId], nil)
146+ if ($isInstanceOf(@, "Boolean"))
147+ then @
148+ else throw(($getType(invoke(factoryContract, "checkWxEmissionPoolLabel", [amountAssetId, priceAssetId], nil)) + " couldn't be cast to Boolean"))
151149 }
152150
153151
154152 let poolsListName = "pools"
155153
156154 func getVotesListName (pool) = {
157- let $t048384878 = pool
158- let amountAssetId = $t048384878._1
159- let priceAssetId = $t048384878._2
155+ let $t048004840 = pool
156+ let amountAssetId = $t048004840._1
157+ let priceAssetId = $t048004840._2
160158 makeString(["votes", amountAssetId, priceAssetId], separator)
161159 }
162160
163161
164162 func keyListHead (listName) = {
165163 let meta = if ((listName == poolsListName))
166164 then "%s%s"
167165 else "%s%s%s%s"
168166 makeString([meta, listName, "head"], separator)
169167 }
170168
171169
172170 func keyListSize (listName) = {
173171 let meta = if ((listName == poolsListName))
174172 then "%s%s"
175173 else "%s%s%s%s"
176174 makeString([meta, listName, "size"], separator)
177175 }
178176
179177
180178 func keyListPrev (listName,id) = {
181179 let meta = if ((listName == poolsListName))
182180 then "%s%s%s%s"
183181 else "%s%s%s%s%s"
184182 makeString([meta, listName, id, "prev"], separator)
185183 }
186184
187185
188186 func keyListNext (listName,id) = {
189187 let meta = if ((listName == poolsListName))
190188 then "%s%s%s%s"
191189 else "%s%s%s%s%s"
192190 makeString([meta, listName, id, "next"], separator)
193191 }
194192
195193
196194 func containsNode (listName,id) = {
197195 let headOrUnit = getString(this, keyListHead(listName))
198196 let prevOrUnit = getString(this, keyListPrev(listName, id))
199197 let nextOrUnit = getString(this, keyListNext(listName, id))
200198 if (if ((id == valueOrElse(headOrUnit, "")))
201199 then true
202200 else (prevOrUnit != unit))
203201 then true
204202 else (nextOrUnit != unit)
205203 }
206204
207205
208206 func insertNodeActions (listName,id) = {
209207 let headOrUnit = getString(this, keyListHead(listName))
210208 let listSize = valueOrElse(getInteger(this, keyListSize(listName)), 0)
211209 let checkNode = if (!(containsNode(listName, id)))
212210 then true
213211 else throw("Node exists")
214212 if ((checkNode == checkNode))
215213 then (([IntegerEntry(keyListSize(listName), (listSize + 1))] ++ (if ((headOrUnit != unit))
216214 then [StringEntry(keyListNext(listName, id), value(headOrUnit)), StringEntry(keyListPrev(listName, value(headOrUnit)), id)]
217215 else nil)) ++ [StringEntry(keyListHead(listName), id)])
218216 else throw("Strict value is not equal to itself.")
219217 }
220218
221219
222220 func deleteNodeActions (listName,id) = {
223221 let headOrUnit = getString(this, keyListHead(listName))
224222 let listSize = valueOrElse(getInteger(this, keyListSize(listName)), 0)
225223 let prevOrUnit = getString(this, keyListPrev(listName, id))
226224 let nextOrUnit = getString(this, keyListNext(listName, id))
227225 ([IntegerEntry(keyListSize(listName), (listSize - 1))] ++ (if (if ((prevOrUnit != unit))
228226 then (nextOrUnit != unit)
229227 else false)
230228 then [StringEntry(keyListNext(listName, value(prevOrUnit)), value(nextOrUnit)), StringEntry(keyListPrev(listName, value(nextOrUnit)), value(prevOrUnit)), DeleteEntry(keyListPrev(listName, id)), DeleteEntry(keyListNext(listName, id))]
231229 else if ((nextOrUnit != unit))
232230 then [StringEntry(keyListHead(listName), value(nextOrUnit)), DeleteEntry(keyListNext(listName, id)), DeleteEntry(keyListPrev(listName, value(nextOrUnit)))]
233231 else if ((prevOrUnit != unit))
234232 then [DeleteEntry(keyListPrev(listName, id)), DeleteEntry(keyListNext(listName, value(prevOrUnit)))]
235233 else if ((id == valueOrElse(headOrUnit, "")))
236234 then [DeleteEntry(keyListHead(listName))]
237235 else throw(((("invalid node: " + listName) + ".") + id))))
238236 }
239237
240238
241239 func keyManagerPublicKey () = "%s__managerPublicKey"
242240
243241
244242 func keyPendingManagerPublicKey () = "%s__pendingManagerPublicKey"
245243
246244
247245 func managerPublicKeyOrUnit () = match getString(keyManagerPublicKey()) {
248246 case s: String =>
249247 fromBase58String(s)
250248 case _: Unit =>
251249 unit
252250 case _ =>
253251 throw("Match error")
254252 }
255253
256254
257255 func pendingManagerPublicKeyOrUnit () = match getString(keyPendingManagerPublicKey()) {
258256 case s: String =>
259257 fromBase58String(s)
260258 case _: Unit =>
261259 unit
262260 case _ =>
263261 throw("Match error")
264262 }
265263
266264
267265 let permissionDeniedError = throw("Permission denied")
268266
269267 func mustThis (i) = if ((i.caller == this))
270268 then true
271269 else permissionDeniedError
272270
273271
274272 func mustManager (i) = match managerPublicKeyOrUnit() {
275273 case pk: ByteVector =>
276274 if ((i.callerPublicKey == pk))
277275 then true
278276 else permissionDeniedError
279277 case _: Unit =>
280278 mustThis(i)
281279 case _ =>
282280 throw("Match error")
283281 }
284282
285283
286284 @Callable(i)
287285 func setManager (pendingManagerPublicKey) = {
288286 let checkCaller = mustManager(i)
289287 if ((checkCaller == checkCaller))
290288 then {
291289 let checkManagerPublicKey = fromBase58String(pendingManagerPublicKey)
292290 if ((checkManagerPublicKey == checkManagerPublicKey))
293291 then [StringEntry(keyPendingManagerPublicKey(), pendingManagerPublicKey)]
294292 else throw("Strict value is not equal to itself.")
295293 }
296294 else throw("Strict value is not equal to itself.")
297295 }
298296
299297
300298
301299 @Callable(i)
302300 func confirmManager () = {
303301 let pm = pendingManagerPublicKeyOrUnit()
304302 let hasPM = if (isDefined(pm))
305303 then true
306304 else throw("No pending manager")
307305 if ((hasPM == hasPM))
308306 then {
309307 let checkPM = if ((i.callerPublicKey == value(pm)))
310308 then true
311309 else throw("You are not pending manager")
312310 if ((checkPM == checkPM))
313311 then [StringEntry(keyManagerPublicKey(), toBase58String(value(pm))), DeleteEntry(keyPendingManagerPublicKey())]
314312 else throw("Strict value is not equal to itself.")
315313 }
316314 else throw("Strict value is not equal to itself.")
317315 }
318316
319317
320318
321319 @Callable(i)
322320 func getUserGwxAmountAtHeight (userAddress,targetHeight) = {
323321 let boostingContractAddress = valueOrErrorMessage(addressFromString(getStrOrFail(this, keyBoostingContract)), "invalid boosting contract address")
324322 $Tuple2(nil, {
325323 let @ = invoke(boostingContractAddress, "getUserGwxAmountAtHeightREADONLY", [userAddress, targetHeight], nil)
326324 if ($isInstanceOf(@, "Int"))
327325 then @
328326 else throw(($getType(invoke(boostingContractAddress, "getUserGwxAmountAtHeightREADONLY", [userAddress, targetHeight], nil)) + " couldn't be cast to Int"))
329327 })
330328 }
331329
332330
333331
334332 @Callable(i)
335-func constructor (factoryContract,votingEmissionCandidateContract,boostingContract,stakingContract,assetsStoreContract,epochLength) = {
333+func constructor (factoryContract,votingEmissionCandidateContract,boostingContract,stakingContract,epochLength) = {
336334 let cheks = [mustManager(i), if ((addressFromString(factoryContract) != unit))
337335 then true
338336 else "invalid factory contract address", if ((addressFromString(votingEmissionCandidateContract) != unit))
339337 then true
340338 else "invalid voting emission candidate contract address", if ((addressFromString(boostingContract) != unit))
341339 then true
342340 else "invalid boosting contract address", if ((addressFromString(stakingContract) != unit))
343341 then true
344- else "invalid staking contract address", if ((addressFromString(assetsStoreContract) != unit))
345- then true
346- else "invalid assets store contract address", if ((epochLength > 0))
342+ else "invalid staking contract address", if ((epochLength > 0))
347343 then true
348344 else throw("invalid epoch length")]
349345 if ((cheks == cheks))
350- then $Tuple2([StringEntry(keyFactoryContract, factoryContract), StringEntry(keyVotingEmissionCandidateContract, votingEmissionCandidateContract), StringEntry(keyBoostingContract, boostingContract), StringEntry(keyStakingContract, stakingContract), StringEntry(keyAssetsStoreContract, assetsStoreContract), IntegerEntry(keyEpochLength, epochLength)], unit)
346+ then $Tuple2([StringEntry(keyFactoryContract, factoryContract), StringEntry(keyVotingEmissionCandidateContract, votingEmissionCandidateContract), StringEntry(keyBoostingContract, boostingContract), StringEntry(keyStakingContract, stakingContract), IntegerEntry(keyEpochLength, epochLength)], unit)
351347 else throw("Strict value is not equal to itself.")
352348 }
353349
354350
355351
356352 @Callable(i)
357353 func create (amountAssetId,priceAssetId) = {
358354 let checks = [if ((toBase58String(i.caller.bytes) == valueOrElse(getString(this, keyVotingEmissionCandidateContract), "")))
359355 then true
360356 else mustManager(i)]
361357 if ((checks == checks))
362358 then {
363359 let pool = $Tuple2(amountAssetId, priceAssetId)
364360 let inListActions = ([BooleanEntry(keyInList(pool), true)] ++ insertNodeActions(poolsListName, poolToString(pool)))
365361 let currentEpochIsNotDefined = (getInteger(this, keyCurrentEpoch) == unit)
366362 let startHeightActions = if (currentEpochIsNotDefined)
367363 then {
368364 let epoch = 0
369365 [IntegerEntry(keyCurrentEpoch, epoch), IntegerEntry(keyStartHeightByEpoch(epoch), height), IntegerEntry(keyStartHeight, height), IntegerEntry(keyCurrentEpochUi, epoch), IntegerEntry(keyStartHeightUi, height)]
370366 }
371367 else nil
372368 $Tuple2((inListActions ++ startHeightActions), unit)
373369 }
374370 else throw("Strict value is not equal to itself.")
375371 }
376372
377373
378374
379375 @Callable(i)
380376 func vote (amountAssetId,priceAssetId,amount) = {
381377 let pool = $Tuple2(amountAssetId, priceAssetId)
382378 let epoch = valueOrElse(getInteger(this, keyCurrentEpoch), 0)
383379 let startHeight = getIntOrFail(this, keyStartHeightByEpoch(epoch))
384380 let epochLength = getIntOrFail(this, keyEpochLength)
385381 let endHeight = (startHeight + epochLength)
386382 let finalizationStageOrUnit = getInteger(this, keyFinalizationStage)
387383 let used = valueOrElse(getInteger(this, keyUsed(i.caller, epoch)), 0)
388384 let vote = valueOrElse(getInteger(this, keyVote(pool, i.caller, epoch)), 0)
389385 let poolResult = valueOrElse(getInteger(this, keyVotingResult(pool, epoch)), 0)
390386 let totalVotes = valueOrElse(getInteger(this, keyTotalVotes(epoch)), 0)
391387 let gwxAmountAtEndTotal = {
392388 let @ = invoke(this, "getUserGwxAmountAtHeight", [toBase58String(i.caller.bytes), endHeight], nil)
393389 if ($isInstanceOf(@, "Int"))
394390 then @
395391 else throw(($getType(invoke(this, "getUserGwxAmountAtHeight", [toBase58String(i.caller.bytes), endHeight], nil)) + " couldn't be cast to Int"))
396392 }
397393 let available = (gwxAmountAtEndTotal - used)
398394 let newVote = (vote + amount)
399- let isAmountAssetVerified = isAssetVerified(amountAssetId)
395+ let wxEmission = checkWxEmissionPoolLabel(pool)
400396 let checks = [if ((getBoolean(keyInList(pool)) != unit))
401397 then true
402398 else throw("invalid assets"), if ((endHeight > height))
403399 then true
404400 else throw("invalid height"), if ((finalizationStageOrUnit == unit))
405401 then true
406402 else throw("finalization in progress"), if ((gwxAmountAtEndTotal > 0))
407403 then true
408404 else throw("you do not have gWX"), if (if ((amount > 0))
409405 then (available >= amount)
410406 else false)
411407 then true
412- else throw("invalid amount"), if (isAmountAssetVerified)
408+ else throw("invalid amount"), if (wxEmission)
413409 then true
414- else throw("amount asset is not verified")]
410+ else throw("pool hasn't WX_EMISSION label")]
415411 if ((checks == checks))
416412 then {
417413 let votesListName = getVotesListName(pool)
418414 let userAddressStr = toString(i.caller)
419415 let votesListActions = if (containsNode(votesListName, userAddressStr))
420416 then nil
421417 else insertNodeActions(votesListName, userAddressStr)
422418 $Tuple2(([IntegerEntry(keyUsed(i.caller, epoch), (used + amount)), IntegerEntry(keyVote(pool, i.caller, epoch), newVote), IntegerEntry(keyVotingResult(pool, epoch), (poolResult + amount)), IntegerEntry(keyTotalVotes(epoch), (totalVotes + amount))] ++ votesListActions), unit)
423419 }
424420 else throw("Strict value is not equal to itself.")
425421 }
426422
427423
428424
429425 @Callable(i)
430426 func cancelVote (amountAssetId,priceAssetId) = {
431427 let pool = $Tuple2(amountAssetId, priceAssetId)
432428 let epoch = valueOrElse(getInteger(this, keyCurrentEpoch), 0)
433429 let startHeight = getIntOrFail(this, keyStartHeightByEpoch(epoch))
434430 let epochLength = getIntOrFail(this, keyEpochLength)
435431 let endHeight = (startHeight + epochLength)
436432 let finalizationStageOrUnit = getInteger(this, keyFinalizationStage)
437433 let used = valueOrElse(getInteger(this, keyUsed(i.caller, epoch)), 0)
438434 let vote = valueOrElse(getInteger(this, keyVote(pool, i.caller, epoch)), 0)
439435 let poolResult = valueOrElse(getInteger(this, keyVotingResult(pool, epoch)), 0)
440436 let totalVotes = valueOrElse(getInteger(this, keyTotalVotes(epoch)), 0)
441437 let checks = [if ((getBoolean(keyInList(pool)) != unit))
442438 then true
443439 else throw("invalid assets"), if ((endHeight > height))
444440 then true
445441 else throw("invalid height"), if ((finalizationStageOrUnit == unit))
446442 then true
447443 else throw("finalization in progress"), if ((vote > 0))
448444 then true
449445 else throw("no vote")]
450446 if ((checks == checks))
451447 then {
452448 let votesListName = getVotesListName(pool)
453449 let userAddressStr = toString(i.caller)
454450 $Tuple2(([IntegerEntry(keyUsed(i.caller, epoch), max([(used - vote), 0])), DeleteEntry(keyVote(pool, i.caller, epoch)), IntegerEntry(keyVotingResult(pool, epoch), (poolResult - vote)), IntegerEntry(keyTotalVotes(epoch), (totalVotes - vote))] ++ deleteNodeActions(votesListName, userAddressStr)), unit)
455451 }
456452 else throw("Strict value is not equal to itself.")
457453 }
458454
459455
460456
461457 @Callable(i)
462458 func setEpochLength (newEpochLength) = {
463459 let cheks = [mustManager(i), if ((newEpochLength > 0))
464460 then true
465461 else throw("invalid epoch length")]
466462 if ((cheks == cheks))
467463 then $Tuple2([IntegerEntry(keyEpochLength, newEpochLength)], unit)
468464 else throw("Strict value is not equal to itself.")
469465 }
470466
471467
472468
473469 @Callable(i)
474470 func setMaxDepth (newMaxDepth) = {
475471 let cheks = [mustManager(i), if ((newMaxDepth > 0))
476472 then true
477473 else throw("invalid max depth")]
478474 if ((cheks == cheks))
479475 then $Tuple2([IntegerEntry(keyMaxDepth, newMaxDepth)], unit)
480476 else throw("Strict value is not equal to itself.")
481477 }
482478
483479
484480
485481 @Callable(i)
486482 func processVoteINTERNAL (poolStr,userAddressStr) = {
487483 let checkCaller = mustThis(i)
488484 if ((checkCaller == checkCaller))
489485 then {
490486 let userAddress = valueOrErrorMessage(addressFromString(userAddressStr), ("processVoteINTERNAL: invalid user address " + userAddressStr))
491487 let epoch = getIntOrFail(this, keyCurrentEpoch)
492488 let epochPrevious = (epoch - 1)
493489 let epochLength = getIntOrFail(this, keyEpochLength)
494490 let startHeight = getIntOrFail(this, keyStartHeightByEpoch(epoch))
495491 let endHeight = (startHeight + epochLength)
496492 let startHeightPrevious = getIntOrFail(this, keyStartHeightByEpoch(epochPrevious))
497493 let endHeightPrevious = (startHeightPrevious + epochLength)
498494 let checkTargetEpoch = if ((epochPrevious >= 0))
499495 then true
500496 else throw("processVoteINTERNAL: invalid previous epoch")
501497 if ((checkTargetEpoch == checkTargetEpoch))
502498 then {
503499 let pool = stringToPool(poolStr)
504- let $t01741817458 = pool
505- let amountAssetId = $t01741817458._1
506- let priceAssetId = $t01741817458._2
507- let isAmountAssetVerified = isAssetVerified(amountAssetId)
500+ let $t01712617166 = pool
501+ let amountAssetId = $t01712617166._1
502+ let priceAssetId = $t01712617166._2
503+ let wxEmission = checkWxEmissionPoolLabel(pool)
508504 let gwxAmountAtEndTotal = {
509505 let @ = invoke(this, "getUserGwxAmountAtHeight", [userAddressStr, endHeight], nil)
510506 if ($isInstanceOf(@, "Int"))
511507 then @
512508 else throw(($getType(invoke(this, "getUserGwxAmountAtHeight", [userAddressStr, endHeight], nil)) + " couldn't be cast to Int"))
513509 }
514510 let gwxAmountAtEndTotalPrevious = {
515511 let @ = invoke(this, "getUserGwxAmountAtHeight", [userAddressStr, endHeightPrevious], nil)
516512 if ($isInstanceOf(@, "Int"))
517513 then @
518514 else throw(($getType(invoke(this, "getUserGwxAmountAtHeight", [userAddressStr, endHeightPrevious], nil)) + " couldn't be cast to Int"))
519515 }
520516 let totalVotes = valueOrElse(getInteger(keyTotalVotes(epoch)), 0)
521517 let votingResult = valueOrElse(getInteger(keyVotingResult(pool, epoch)), 0)
522518 let votePrevious = valueOrErrorMessage(getInteger(keyVote(pool, userAddress, epochPrevious)), (((("processVoteINTERNAL " + poolStr) + " ") + userAddressStr) + ": no previous vote"))
523519 let used = valueOrElse(getInteger(this, keyUsed(userAddress, epoch)), 0)
524520 let newVote = fraction(votePrevious, gwxAmountAtEndTotal, gwxAmountAtEndTotalPrevious)
525521 let actions = if (if ((newVote > 0))
526- then isAmountAssetVerified
522+ then wxEmission
527523 else false)
528524 then [IntegerEntry(keyVote(pool, userAddress, epoch), newVote), IntegerEntry(keyTotalVotes(epoch), (totalVotes + newVote)), IntegerEntry(keyVotingResult(pool, epoch), (votingResult + newVote)), IntegerEntry(keyUsed(userAddress, epoch), (used + newVote))]
529525 else deleteNodeActions(getVotesListName(pool), userAddressStr)
530526 $Tuple2(actions, unit)
531527 }
532528 else throw("Strict value is not equal to itself.")
533529 }
534530 else throw("Strict value is not equal to itself.")
535531 }
536532
537533
538534
539535 @Callable(i)
540536 func processPoolINTERNAL (poolStr) = {
541537 let checkCaller = mustThis(i)
542538 if ((checkCaller == checkCaller))
543539 then {
544540 let targetEpoch = (getIntOrFail(this, keyCurrentEpoch) - 1)
545541 let checkTargetEpoch = if ((targetEpoch >= 0))
546542 then true
547543 else throw("processPoolINTERNAL: invalid target epoch")
548544 if ((checkTargetEpoch == checkTargetEpoch))
549545 then {
550546 let pool = stringToPool(poolStr)
551- let $t01899719037 = pool
552- let amountAssetId = $t01899719037._1
553- let priceAssetId = $t01899719037._2
547+ let $t01868318723 = pool
548+ let amountAssetId = $t01868318723._1
549+ let priceAssetId = $t01868318723._2
554550 let stakingContract = addressFromStringValue(getStrOrFail(this, keyStakingContract))
555551 let factoryContract = addressFromStringValue(getStrOrFail(this, keyFactoryContract))
556552 let lpAssetId = getLpAssetByPoolAssets(amountAssetId, priceAssetId)
557553 let r = {
558554 let @ = invoke(stakingContract, "usersListTraversal", [lpAssetId], nil)
559555 if ($isInstanceOf(@, "Boolean"))
560556 then @
561557 else throw(($getType(invoke(stakingContract, "usersListTraversal", [lpAssetId], nil)) + " couldn't be cast to Boolean"))
562558 }
563559 if ((r == r))
564560 then if (r)
565561 then $Tuple2(nil, true)
566562 else {
567- let isAmountAssetVerified = isAssetVerified(amountAssetId)
563+ let wxEmission = checkWxEmissionPoolLabel(pool)
568564 let totalVotes = valueOrElse(getInteger(this, keyTotalVotes(targetEpoch)), 0)
569565 let votingResult = valueOrElse(getInteger(this, keyVotingResult(pool, targetEpoch)), 0)
570566 let share = if (if ((totalVotes == 0))
571567 then true
572- else !(isAmountAssetVerified))
568+ else !(wxEmission))
573569 then 0
574570 else fraction(votingResult, poolWeightMult, totalVotes)
575571 let modifyWeightInv = invoke(factoryContract, "modifyWeight", [lpAssetId, share], nil)
576572 if ((modifyWeightInv == modifyWeightInv))
577573 then {
578- let poolsListActions = if (isAmountAssetVerified)
574+ let poolsListActions = if (wxEmission)
579575 then nil
580576 else ([DeleteEntry(keyInList(pool))] ++ deleteNodeActions(poolsListName, poolStr))
581577 $Tuple2(([IntegerEntry(keyPoolShare(pool, targetEpoch), share)] ++ poolsListActions), false)
582578 }
583579 else throw("Strict value is not equal to itself.")
584580 }
585581 else throw("Strict value is not equal to itself.")
586582 }
587583 else throw("Strict value is not equal to itself.")
588584 }
589585 else throw("Strict value is not equal to itself.")
590586 }
591587
592588
593589
594590 @Callable(i)
595591 func finalizeHelper () = {
596592 let epoch = valueOrElse(getInteger(this, keyCurrentEpoch), 0)
597593 let previousEpoch = (epoch - 1)
598594 let startHeight = getIntOrFail(this, keyStartHeightByEpoch(epoch))
599595 let epochLength = getIntOrFail(this, keyEpochLength)
600596 let endHeight = (startHeight + epochLength)
601597 let finalizationStageOrUnit = getInteger(this, keyFinalizationStage)
602598 if ((height >= endHeight))
603599 then {
604600 let newEpoch = (epoch + 1)
605601 $Tuple2([IntegerEntry(keyStartHeightByEpoch(newEpoch), height), IntegerEntry(keyStartHeight, height), IntegerEntry(keyCurrentEpoch, newEpoch), IntegerEntry(keyFinalizationStage, finalizationStageTotal)], true)
606602 }
607603 else if ((finalizationStageOrUnit == unit))
608604 then $Tuple2(nil, false)
609605 else if ((finalizationStageOrUnit == finalizationStageTotal))
610606 then {
611607 let poolOrUnit = getString(keyNextPool)
612608 let userOrUnit = getString(keyNextUser)
613609 match poolOrUnit {
614610 case _: Unit =>
615611 match getString(keyListHead(poolsListName)) {
616612 case _: Unit =>
617613 $Tuple2([IntegerEntry(keyFinalizationStage, finalizationStageShares), DeleteEntry(keyNextPool), DeleteEntry(keyNextUser)], true)
618614 case poolsHeadStr: String =>
619615 $Tuple2([StringEntry(keyNextPool, poolsHeadStr)], true)
620616 case _ =>
621617 throw("Match error")
622618 }
623619 case poolStr: String =>
624620 let pool = stringToPool(poolStr)
625621 let nextUserOrUnit = match userOrUnit {
626622 case _: Unit =>
627623 getString(keyListHead(getVotesListName(pool)))
628624 case user: String =>
629625 let processVoteInv = invoke(this, "processVoteINTERNAL", [poolStr, user], nil)
630626 if ((processVoteInv == processVoteInv))
631627 then getString(keyListNext(getVotesListName(pool), user))
632628 else throw("Strict value is not equal to itself.")
633629 case _ =>
634630 throw("Match error")
635631 }
636632 match nextUserOrUnit {
637633 case _: Unit =>
638634 let nextPoolOrUnit = getString(keyListNext(poolsListName, poolStr))
639635 match nextPoolOrUnit {
640636 case _: Unit =>
641637 $Tuple2([IntegerEntry(keyFinalizationStage, finalizationStageShares), DeleteEntry(keyNextPool), DeleteEntry(keyNextUser)], true)
642638 case s: String =>
643639 $Tuple2([StringEntry(keyNextPool, s), DeleteEntry(keyNextUser)], true)
644640 case _ =>
645641 throw("Match error")
646642 }
647643 case nextUser: String =>
648644 $Tuple2([StringEntry(keyNextUser, nextUser)], true)
649645 case _ =>
650646 throw("Match error")
651647 }
652648 case _ =>
653649 throw("Match error")
654650 }
655651 }
656652 else if ((finalizationStageOrUnit == finalizationStageShares))
657653 then {
658654 let poolOrUnit = getString(keyNextPool)
659655 match poolOrUnit {
660656 case _: Unit =>
661657 match getString(keyListHead(poolsListName)) {
662658 case _: Unit =>
663659 $Tuple2([DeleteEntry(keyFinalizationStage), BooleanEntry(keyFinalized(previousEpoch), true), IntegerEntry(keyCurrentEpochUi, epoch), IntegerEntry(keyStartHeightUi, startHeight)], true)
664660 case nextPoolStr: String =>
665661 $Tuple2([StringEntry(keyNextPool, nextPoolStr)], true)
666662 case _ =>
667663 throw("Match error")
668664 }
669665 case poolStr: String =>
670666 let r = {
671667 let @ = invoke(this, "processPoolINTERNAL", [poolStr], nil)
672668 if ($isInstanceOf(@, "Boolean"))
673669 then @
674670 else throw(($getType(invoke(this, "processPoolINTERNAL", [poolStr], nil)) + " couldn't be cast to Boolean"))
675671 }
676672 if ((r == r))
677673 then if (r)
678674 then $Tuple2(nil, true)
679675 else {
680676 let nextPoolOrUnit = getString(keyListNext(poolsListName, poolStr))
681677 match nextPoolOrUnit {
682678 case _: Unit =>
683679 $Tuple2([DeleteEntry(keyFinalizationStage), BooleanEntry(keyFinalized(previousEpoch), true), IntegerEntry(keyCurrentEpochUi, epoch), IntegerEntry(keyStartHeightUi, startHeight), DeleteEntry(keyNextPool)], true)
684680 case nextPoolStr: String =>
685681 $Tuple2([StringEntry(keyNextPool, nextPoolStr)], true)
686682 case _ =>
687683 throw("Match error")
688684 }
689685 }
690686 else throw("Strict value is not equal to itself.")
691687 case _ =>
692688 throw("Match error")
693689 }
694690 }
695691 else throw("finalization is broken")
696692 }
697693
698694
699695
700696 @Callable(i)
701697 func finalizeWrapper (counter) = {
702698 let result = {
703699 let @ = invoke(this, "finalizeHelper", nil, nil)
704700 if ($isInstanceOf(@, "Boolean"))
705701 then @
706702 else throw(($getType(invoke(this, "finalizeHelper", nil, nil)) + " couldn't be cast to Boolean"))
707703 }
708704 if ((result == result))
709705 then if (!(result))
710706 then if ((counter == 0))
711707 then throw("Current voting is not over yet")
712708 else $Tuple2(nil, unit)
713709 else {
714710 let maxDepth = valueOrElse(getInteger(this, keyMaxDepth), maxDepthDefault)
715711 if ((maxDepth > counter))
716712 then {
717713 let inv = invoke(this, "finalizeWrapper", [(counter + 1)], nil)
718714 if ((inv == inv))
719715 then $Tuple2(nil, unit)
720716 else throw("Strict value is not equal to itself.")
721717 }
722718 else $Tuple2(nil, unit)
723719 }
724720 else throw("Strict value is not equal to itself.")
725721 }
726722
727723
728724
729725 @Callable(i)
730726 func finalize () = {
731727 let inv = invoke(this, "finalizeWrapper", [0], nil)
732728 if ((inv == inv))
733729 then $Tuple2(nil, unit)
734730 else throw("Strict value is not equal to itself.")
735731 }
736732
737733
738734
739735 @Callable(i)
740-func onVerificationLoss (assetId) = $Tuple2(nil, unit)
741-
742-
743-
744-@Callable(i)
745736 func containsNodeREADONLY (listName,id) = $Tuple2(nil, containsNode(listName, id))
746737
747738
748739
749740 @Callable(i)
750741 func insertNode (listName,id) = {
751742 let checkCaller = mustManager(i)
752743 if ((checkCaller == checkCaller))
753744 then $Tuple2(insertNodeActions(listName, id), unit)
754745 else throw("Strict value is not equal to itself.")
755746 }
756747
757748
758749
759750 @Callable(i)
760751 func deleteNode (listName,id) = {
761752 let checkCaller = mustManager(i)
762753 if ((checkCaller == checkCaller))
763754 then $Tuple2(deleteNodeActions(listName, id), unit)
764755 else throw("Strict value is not equal to itself.")
765756 }
766757
767758
768759 @Verifier(tx)
769760 func verify () = {
770761 let targetPublicKey = match managerPublicKeyOrUnit() {
771762 case pk: ByteVector =>
772763 pk
773764 case _: Unit =>
774765 tx.senderPublicKey
775766 case _ =>
776767 throw("Match error")
777768 }
778769 sigVerify(tx.bodyBytes, tx.proofs[0], targetPublicKey)
779770 }
780771

github/deemru/w8io/169f3d6 
101.34 ms