tx · 6KC4SoaVhtXtoMyjezydzWkdQQh6T6fsVYY6GCfteiPB

3MzNgrEUhroThbrRs5DXGbo7x8nu84NqPfU:  -0.03000000 Waves

2022.09.14 17:33 [2228898] smart account 3MzNgrEUhroThbrRs5DXGbo7x8nu84NqPfU > SELF 0.00000000 Waves

{ "type": 13, "id": "6KC4SoaVhtXtoMyjezydzWkdQQh6T6fsVYY6GCfteiPB", "fee": 3000000, "feeAssetId": null, "timestamp": 1663166035599, "version": 2, "chainId": 84, "sender": "3MzNgrEUhroThbrRs5DXGbo7x8nu84NqPfU", "senderPublicKey": "9rfquow4nYxXdYLnj2FRCVCi9ZUa2BSBci3YMueg53DF", "proofs": [ "5tgqBwu6pBBRL7sUuFDr9wyPddvkPE7N6g7n8cBcd8EjcTM9E2S9NmgAVnWimBpbbks1sEpxgo5KMca5QFoCF6UR", "4utCt9fQYfofkBh6kCznS6keWSShGbJF8hGv7eHbm92xjB2etAZhdEHdtUhD8qqV1mvfL3ocpapPb7pacJxdVFUt" ], "script": "base64:BgIpCAISAwoBBBIAEgQKAgEBEgASBAoCAQESABIAEgASAwoBARIFCgMEAQhhAAd2ZXJzaW9uAgUyLjAuMAAIa1ZlcnNpb24CB3ZlcnNpb24AB2tBY3RpdmUCBmFjdGl2ZQAJa0Fzc2V0SWRBAgpBX2Fzc2V0X2lkAAlrQXNzZXRJZEICCkJfYXNzZXRfaWQACWtCYWxhbmNlQQIPQV9hc3NldF9iYWxhbmNlAAlrQmFsYW5jZUICD0JfYXNzZXRfYmFsYW5jZQANa1NoYXJlQXNzZXRJZAIOc2hhcmVfYXNzZXRfaWQAEWtTaGFyZUFzc2V0U3VwcGx5AhJzaGFyZV9hc3NldF9zdXBwbHkABGtGZWUCCmNvbW1pc3Npb24ACmtJbnZhcmlhbnQCCWludmFyaWFudAAGa0NhdXNlAg5zaHV0ZG93bl9jYXVzZQAMa1VTRE5BZGRyZXNzAhhzdGFraW5nX3VzZG5uc2J0X2FkZHJlc3MADGtFVVJOQWRkcmVzcwIUc3Rha2luZ19ldXJuX2FkZHJlc3MACmtEaXNjb3VudHMCCWRpc2NvdW50cwAPa0Rpc2NvdW50VmFsdWVzAg9kaXNjb3VudF92YWx1ZXMADmtVc2VyU3dvcEluR292AgxfU1dPUF9hbW91bnQADWtGaXJzdEhhcnZlc3QCDWZpcnN0X2hhcnZlc3QAE2tGaXJzdEhhcnZlc3RIZWlnaHQCFGZpcnN0X2hhcnZlc3RfaGVpZ2h0AAtrU2hhcmVMaW1pdAIcc2hhcmVfbGltaXRfb25fZmlyc3RfaGFydmVzdAALa0Jhc2VQZXJpb2QCC2Jhc2VfcGVyaW9kAA1rUGVyaW9kTGVuZ3RoAg1wZXJpb2RfbGVuZ3RoAAxrU3RhcnRIZWlnaHQCDHN0YXJ0X2hlaWdodAANa0FkbWluUHViS2V5MQILYWRtaW5fcHViXzEADWtBZG1pblB1YktleTICC2FkbWluX3B1Yl8yAA1rQWRtaW5QdWJLZXkzAgthZG1pbl9wdWJfMwASa0FkbWluSW52b2tlUHViS2V5AhBhZG1pbl9pbnZva2VfcHViABBrTW9uZXlCb3hBZGRyZXNzAhFtb25leV9ib3hfYWRkcmVzcwALa0dvdkFkZHJlc3MCEmdvdmVybmFuY2VfYWRkcmVzcwAOa1ZvdGluZ0FkZHJlc3MCDnZvdGluZ19hZGRyZXNzAAZvcmFjbGUJAQdBZGRyZXNzAQEaAVTpRaoekC86rvG6DuYumpJfGpiE4fNiswgBE2dldEJhc2U1OEZyb21PcmFjbGUBA2tleQQHJG1hdGNoMAkAnQgCBQZvcmFjbGUFA2tleQMJAAECBQckbWF0Y2gwAgZTdHJpbmcEBnN0cmluZwUHJG1hdGNoMAkA2QQBBQZzdHJpbmcEB25vdGhpbmcFByRtYXRjaDAJAAIBCQCsAgIFA2tleQIIaXMgZW1wdHkADGFkbWluUHViS2V5MQkBE2dldEJhc2U1OEZyb21PcmFjbGUBBQ1rQWRtaW5QdWJLZXkxAAxhZG1pblB1YktleTIJARNnZXRCYXNlNThGcm9tT3JhY2xlAQUNa0FkbWluUHViS2V5MgAMYWRtaW5QdWJLZXkzCQETZ2V0QmFzZTU4RnJvbU9yYWNsZQEFDWtBZG1pblB1YktleTMAEWFkbWluUHViS2V5SW52b2tlCQETZ2V0QmFzZTU4RnJvbU9yYWNsZQEFEmtBZG1pbkludm9rZVB1YktleQAPbW9uZXlCb3hBZGRyZXNzCQEHQWRkcmVzcwEJARNnZXRCYXNlNThGcm9tT3JhY2xlAQUQa01vbmV5Qm94QWRkcmVzcwAKZ292QWRkcmVzcwkBB0FkZHJlc3MBCQETZ2V0QmFzZTU4RnJvbU9yYWNsZQEFC2tHb3ZBZGRyZXNzABJzdGFraW5nVVNETkFkZHJlc3MJAQdBZGRyZXNzAQkBE2dldEJhc2U1OEZyb21PcmFjbGUBBQxrVVNETkFkZHJlc3MADXZvdGluZ0FkZHJlc3MJAQdBZGRyZXNzAQkBE2dldEJhc2U1OEZyb21PcmFjbGUBBQ5rVm90aW5nQWRkcmVzcwAEVVNETgEgbySjyqsw3FIpmOgsYVruWn8jTcItdbvpnapU4NLQB8EADXN0YWtpbmdBc3NldHMJAMwIAgkA2AQBBQRVU0ROBQNuaWwACmJhc2VQZXJpb2QJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAmggCBQ12b3RpbmdBZGRyZXNzBQtrQmFzZVBlcmlvZAIRRW1wdHkga0Jhc2VQZXJpb2QAC3N0YXJ0SGVpZ2h0CQETdmFsdWVPckVycm9yTWVzc2FnZQIJAJoIAgUNdm90aW5nQWRkcmVzcwUMa1N0YXJ0SGVpZ2h0AhJFbXB0eSBrU3RhcnRIZWlnaHQADHBlcmlvZExlbmd0aAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCaCAIFDXZvdGluZ0FkZHJlc3MFDWtQZXJpb2RMZW5ndGgCE0VtcHR5IGtQZXJpb2RMZW5ndGgAFWZpcnN0SGFydmVzdEVuZFBlcmlvZAkAZAIJAGQCBQpiYXNlUGVyaW9kCQBpAgkAZQIFBmhlaWdodAULc3RhcnRIZWlnaHQFDHBlcmlvZExlbmd0aAADAAZhY3RpdmUJARFAZXh0ck5hdGl2ZSgxMDUxKQIFBHRoaXMFB2tBY3RpdmUAC3N0ckFzc2V0SWRBCQERQGV4dHJOYXRpdmUoMTA1MykCBQR0aGlzBQlrQXNzZXRJZEEAC3N0ckFzc2V0SWRCCQERQGV4dHJOYXRpdmUoMTA1MykCBQR0aGlzBQlrQXNzZXRJZEIACGFzc2V0SWRBAwkAAAIFC3N0ckFzc2V0SWRBAgVXQVZFUwUEdW5pdAkA2QQBBQtzdHJBc3NldElkQQAIYXNzZXRJZEIDCQAAAgULc3RyQXNzZXRJZEICBVdBVkVTBQR1bml0CQDZBAEFC3N0ckFzc2V0SWRCAAphc3NldE5hbWVBBAckbWF0Y2gwBQhhc3NldElkQQMJAAECBQckbWF0Y2gwAgpCeXRlVmVjdG9yBAJpZAUHJG1hdGNoMAgJAQV2YWx1ZQEJAOwHAQUCaWQEbmFtZQMJAAECBQckbWF0Y2gwAgRVbml0BAV3YXZlcwUHJG1hdGNoMAIFV0FWRVMJAAIBAgtNYXRjaCBlcnJvcgAKYXNzZXROYW1lQgQHJG1hdGNoMAUIYXNzZXRJZEIDCQABAgUHJG1hdGNoMAIKQnl0ZVZlY3RvcgQCaWQFByRtYXRjaDAICQEFdmFsdWUBCQDsBwEFAmlkBG5hbWUDCQABAgUHJG1hdGNoMAIEVW5pdAQFd2F2ZXMFByRtYXRjaDACBVdBVkVTCQACAQILTWF0Y2ggZXJyb3IACGJhbGFuY2VBCQERQGV4dHJOYXRpdmUoMTA1MCkCBQR0aGlzBQlrQmFsYW5jZUEACGJhbGFuY2VCCQERQGV4dHJOYXRpdmUoMTA1MCkCBQR0aGlzBQlrQmFsYW5jZUIADHNoYXJlQXNzZXRJZAkA2QQBCQERQGV4dHJOYXRpdmUoMTA1MykCBQR0aGlzBQ1rU2hhcmVBc3NldElkABBzaGFyZUFzc2V0U3VwcGx5CQERQGV4dHJOYXRpdmUoMTA1MCkCBQR0aGlzBRFrU2hhcmVBc3NldFN1cHBseQAJaW52YXJpYW50CQERQGV4dHJOYXRpdmUoMTA1MCkCBQR0aGlzBQprSW52YXJpYW50AANmZWUJARFAZXh0ck5hdGl2ZSgxMDUwKQIFBHRoaXMFBGtGZWUADWZlZUdvdmVybmFuY2UJAGsDBQNmZWUAKABkAAlmZWVTY2FsZTYAwIQ9AAZzY2FsZTMA6AcABnNjYWxlOACAwtcvAAdzY2FsZTE2AICAhP6m3uERAA5zbGlwcGFnZVNjYWxlMwDoBwAHZGlnaXRzOAAIAA1kQXBwVGhyZXNob2xkADIAE2RBcHBUaHJlc2hvbGRTY2FsZTIAZAAVZXhjaGFuZ2VSYXRpb0xpbWl0TWluAICV9SoAFWV4Y2hhbmdlUmF0aW9MaW1pdE1heACA77k0AAVhbHBoYQAyAAthbHBoYURpZ2l0cwACAARiZXRhAICA3q/P9ZUIAQ5hY2NvdW50QmFsYW5jZQEHYXNzZXRJZAQHJG1hdGNoMAUHYXNzZXRJZAMJAAECBQckbWF0Y2gwAgpCeXRlVmVjdG9yBAJpZAUHJG1hdGNoMAkA8AcCBQR0aGlzBQJpZAMJAAECBQckbWF0Y2gwAgRVbml0BAV3YXZlcwUHJG1hdGNoMAgJAO8HAQUEdGhpcwlhdmFpbGFibGUJAAIBAgtNYXRjaCBlcnJvcgEMc3Rha2VkQW1vdW50AQdhc3NldElkBBZzdGFrZWRBbW91bnRDYWxjdWxhdGVkBAckbWF0Y2gwBQdhc3NldElkAwkAAQIFByRtYXRjaDACCkJ5dGVWZWN0b3IEA2FJZAUHJG1hdGNoMAMJAAACBQNhSWQFBFVTRE4JAJoIAgUSc3Rha2luZ1VTRE5BZGRyZXNzCQCsAgIJAKwCAgkArAICAgxycGRfYmFsYW5jZV8JANgEAQUDYUlkAgFfCQClCAEFBHRoaXMAAAMJAAECBQckbWF0Y2gwAgRVbml0AAAJAAIBAgtNYXRjaCBlcnJvcgQHJG1hdGNoMAUWc3Rha2VkQW1vdW50Q2FsY3VsYXRlZAMJAAECBQckbWF0Y2gwAgNJbnQEAWkFByRtYXRjaDAFAWkAAAANc3Rha2VkQW1vdW50QQkBDHN0YWtlZEFtb3VudAEFCGFzc2V0SWRBAA1zdGFrZWRBbW91bnRCCQEMc3Rha2VkQW1vdW50AQUIYXNzZXRJZEIAEWF2YWlsYWJsZUJhbGFuY2VBCQBlAgUIYmFsYW5jZUEFDXN0YWtlZEFtb3VudEEAEWF2YWlsYWJsZUJhbGFuY2VCCQBlAgUIYmFsYW5jZUIFDXN0YWtlZEFtb3VudEIAGWFjY291bnRCYWxhbmNlV2l0aFN0YWtlZEEJAGQCCQEOYWNjb3VudEJhbGFuY2UBBQhhc3NldElkQQUNc3Rha2VkQW1vdW50QQAZYWNjb3VudEJhbGFuY2VXaXRoU3Rha2VkQgkAZAIJAQ5hY2NvdW50QmFsYW5jZQEFCGFzc2V0SWRCBQ1zdGFrZWRBbW91bnRCABBoYXNFbm91Z2hCYWxhbmNlAwkAZwIFGWFjY291bnRCYWxhbmNlV2l0aFN0YWtlZEEFCGJhbGFuY2VBCQBnAgUZYWNjb3VudEJhbGFuY2VXaXRoU3Rha2VkQgUIYmFsYW5jZUIHAQhza2V3bmVzcwIBeAF5CQBpAgkAZAIJAGsDBQdzY2FsZTE2BQF4BQF5CQBrAwUHc2NhbGUxNgUBeQUBeAACAQ1pbnZhcmlhbnRDYWxjAgF4AXkEAnNrCQEIc2tld25lc3MCBQF4BQF5CQBkAgkAawMJAGQCBQF4BQF5BQdzY2FsZTE2CQBsBgUCc2sFB2RpZ2l0czgFBWFscGhhBQthbHBoYURpZ2l0cwUHZGlnaXRzOAUHQ0VJTElORwkAaAIAAgkAawMJAKADAQkAdgYJALwCAwkAtgIBBQF4CQC2AgEFAXkJALYCAQUGc2NhbGU4AAAJALYCAQAFAAEJAGkCBQdkaWdpdHM4AAIFBERPV04JAGwGCQBlAgUCc2sFBGJldGEFB2RpZ2l0czgFBWFscGhhBQthbHBoYURpZ2l0cwUHZGlnaXRzOAUERE9XTgUGc2NhbGU4ARNjYWxjdWxhdGVTZW5kQW1vdW50BBVhbW91bnRUb1NlbmRFc3RpbWF0ZWQVbWluVG9rZW5SZWNlaXZlQW1vdW50EnRva2VuUmVjZWl2ZUFtb3VudAd0b2tlbklkBB13b3JzdEFsbG93ZWROZXdJbnZhcmlhbnRSYXRpbwkAZQIFB3NjYWxlMTYJAGkCCQBoAgUHc2NhbGUxNgABAICt4gQEHmRlbHRhQmV0d2Vlbk1heEFuZE1pblNlbmRWYWx1ZQkAZQIFFWFtb3VudFRvU2VuZEVzdGltYXRlZAUVbWluVG9rZW5SZWNlaXZlQW1vdW50BAF4CQBkAgUIYmFsYW5jZUEFEnRva2VuUmVjZWl2ZUFtb3VudAQBeQkAZAIFCGJhbGFuY2VCBRJ0b2tlblJlY2VpdmVBbW91bnQKAQ1nZXRTdGVwQW1vdW50AgNhY2MEc3RlcAMJAAACCAUDYWNjAl8xAP///////////wEEDGFtb3VudFRvU2VuZAkAZQIFFWFtb3VudFRvU2VuZEVzdGltYXRlZAkAaQIJAGkCCQBoAgUEc3RlcAUeZGVsdGFCZXR3ZWVuTWF4QW5kTWluU2VuZFZhbHVlAAMFBnNjYWxlMwQNc3RlcEludmFyaWFudAMJAAACBQd0b2tlbklkBQhhc3NldElkQQkBDWludmFyaWFudENhbGMCBQF4CQBlAgUIYmFsYW5jZUIFDGFtb3VudFRvU2VuZAkBDWludmFyaWFudENhbGMCCQBlAgUIYmFsYW5jZUEFDGFtb3VudFRvU2VuZAUBeQMJAGYCBQ1zdGVwSW52YXJpYW50BQlpbnZhcmlhbnQJAJQKAgUMYW1vdW50VG9TZW5kBQ1zdGVwSW52YXJpYW50CQCUCgIA////////////AQAABQNhY2MED2Ftb3VudFRvU2VuZE1pbgkBDWdldFN0ZXBBbW91bnQCCQCUCgIA////////////AQAAALgXAwkAZgIAAAgFD2Ftb3VudFRvU2VuZE1pbgJfMQkAAgECH1ByaWNlIGlzIHdvcnNlIHRoYW4gbWluUmVjZWl2ZWQEDGludkVzdGltYXRlZAMJAAACBQd0b2tlbklkBQhhc3NldElkQQkBDWludmFyaWFudENhbGMCBQF4CQBlAgUIYmFsYW5jZUIFFWFtb3VudFRvU2VuZEVzdGltYXRlZAMJAAACBQd0b2tlbklkBQhhc3NldElkQgkBDWludmFyaWFudENhbGMCCQBlAgUIYmFsYW5jZUEFFWFtb3VudFRvU2VuZEVzdGltYXRlZAUBeQkAAgECFldyb25nIGFzc2V0IGluIHBheW1lbnQDCQBmAgUJaW52YXJpYW50BQxpbnZFc3RpbWF0ZWQDCQBnAgUdd29yc3RBbGxvd2VkTmV3SW52YXJpYW50UmF0aW8JAGsDBQdzY2FsZTE2BQlpbnZhcmlhbnQFDGludkVzdGltYXRlZAkAAgECMlRoZSByZXF1ZXN0ZWQgcHJpY2UgaXMgdG9vIG5vdCBwcm9maXRhYmxlIGZvciB1c2VyBAFhCgACJGwJAMwIAgAZCQDMCAIAyAEJAMwIAgD0AwUDbmlsCgACJHMJAJADAQUCJGwKAAUkYWNjMAkAlAoCAP///////////wEAAAoBBSRmMF8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQENZ2V0U3RlcEFtb3VudAIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmMF8yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQITTGlzdCBzaXplIGV4Y2VlZHMgMwkBBSRmMF8yAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgUFJGFjYzAAAAABAAIAAwMJAGYCAAAIBQFhAl8xCAUPYW1vdW50VG9TZW5kTWluAl8xCAUBYQJfMQQBYQoAAiRsCQDMCAIAjPz/////////AQkAzAgCALj+/////////wEJAMwIAgDn//////////8BBQNuaWwKAAIkcwkAkAMBBQIkbAoABSRhY2MwCQCUCgIA////////////AQAACgEFJGYwXzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAQ1nZXRTdGVwQW1vdW50AgUCJGEJAJEDAgUCJGwFAiRpCgEFJGYwXzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhNMaXN0IHNpemUgZXhjZWVkcyAzCQEFJGYwXzICCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECBQUkYWNjMAAAAAEAAgADBA90dXBsZVNlbmRCZXR0ZXIDCQBmAgAACAUBYQJfMQkAlAoCBRVhbW91bnRUb1NlbmRFc3RpbWF0ZWQFDGludkVzdGltYXRlZAUBYQMJAGcCBR13b3JzdEFsbG93ZWROZXdJbnZhcmlhbnRSYXRpbwkAawMFB3NjYWxlMTYFCWludmFyaWFudAgFD3R1cGxlU2VuZEJldHRlcgJfMgkAAgECMlRoZSByZXF1ZXN0ZWQgcHJpY2UgaXMgdG9vIG5vdCBwcm9maXRhYmxlIGZvciB1c2VyCAUPdHVwbGVTZW5kQmV0dGVyAl8xAQxnZXRBc3NldEluZm8BB2Fzc2V0SWQEByRtYXRjaDAFB2Fzc2V0SWQDCQABAgUHJG1hdGNoMAIKQnl0ZVZlY3RvcgQCaWQFByRtYXRjaDAECHN0cmluZ0lkCQDYBAEFAmlkBARpbmZvCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAOwHAQUCaWQJAKwCAgkArAICAgZBc3NldCAFCHN0cmluZ0lkAg4gZG9lc24ndCBleGlzdAkAlQoDBQhzdHJpbmdJZAgFBGluZm8EbmFtZQgFBGluZm8IZGVjaW1hbHMDCQABAgUHJG1hdGNoMAIEVW5pdAQFd2F2ZXMFByRtYXRjaDAJAJUKAwIFV0FWRVMCBVdBVkVTAAgJAAIBAgtNYXRjaCBlcnJvcgEHc3VzcGVuZAEFY2F1c2UJAMwIAgkBDEJvb2xlYW5FbnRyeQIFB2tBY3RpdmUHCQDMCAIJAQtTdHJpbmdFbnRyeQIFBmtDYXVzZQUFY2F1c2UFA25pbAENdGhyb3dJc0FjdGl2ZQAJAAIBAhZEQXBwIGlzIGFscmVhZHkgYWN0aXZlAQhpc0FjdGl2ZQADBQZhY3RpdmUFBHVuaXQJAAIBAh9EQXBwIGlzIGluYWN0aXZlIGF0IHRoaXMgbW9tZW50AQtpc0FkbWluQ2FsbAEBaQMJAQ9jb250YWluc0VsZW1lbnQCCQDMCAIFDGFkbWluUHViS2V5MQkAzAgCBQxhZG1pblB1YktleTIJAMwIAgUMYWRtaW5QdWJLZXkzBQNuaWwIBQFpD2NhbGxlclB1YmxpY0tleQUEdW5pdAkAAgECIU9ubHkgYWRtaW4gY2FuIGNhbGwgdGhpcyBmdW5jdGlvbgELdGhyb3dBc3NldHMACQACAQkArAICCQCsAgIJAKwCAgIlSW5jb3JyZWN0IGFzc2V0cyBhdHRhY2hlZC4gRXhwZWN0ZWQ6IAULc3RyQXNzZXRJZEECBSBhbmQgBQtzdHJBc3NldElkQgEPdGhyb3dPbmVQYXltZW50AAkAAgECHU9uZSBhdHRhY2hlZCBwYXltZW50IGV4cGVjdGVkAQ50aHJvd1RocmVzaG9sZAMJdGhyZXNob2xkB2Ftb3VudEEHYW1vdW50QgkAAgEJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgICOU5ldyBiYWxhbmNlIGluIGFzc2V0cyBvZiB0aGUgREFwcCBpcyBsZXNzIHRoYW4gdGhyZXNob2xkIAkApAMBBQl0aHJlc2hvbGQCAjogCQCkAwEFB2Ftb3VudEECASAFCmFzc2V0TmFtZUECAiwgCQCkAwEFB2Ftb3VudEICASAFCmFzc2V0TmFtZUIBEXN1c3BlbmRTdXNwaWNpb3VzAAkBB3N1c3BlbmQBCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICAiNTdXNwaWNpb3VzIHN0YXRlLiBBY3R1YWwgYmFsYW5jZXM6IAkApAMBBQhiYWxhbmNlQQIBIAUKYXNzZXROYW1lQQICLCAJAKQDAQUIYmFsYW5jZUICASAFCmFzc2V0TmFtZUICCS4gU3RhdGU6IAkApAMBCQEOYWNjb3VudEJhbGFuY2UBBQhhc3NldElkQQIBIAUKYXNzZXROYW1lQQICLCAJAKQDAQkBDmFjY291bnRCYWxhbmNlAQUIYXNzZXRJZEICASAFCmFzc2V0TmFtZUIBGGNhbGNTdGFraW5nRnVuY0FuZEFkZHJlcwIFc3Rha2UHYXNzZXRJZAMFBXN0YWtlCQCUCgICDGxvY2tOZXV0cmlubwUSc3Rha2luZ1VTRE5BZGRyZXNzCQCUCgICDnVubG9ja05ldXRyaW5vBRJzdGFraW5nVVNETkFkZHJlc3MBEWNhbGNTdGFraW5nUGFyYW1zAwVzdGFrZQZhbW91bnQHYXNzZXRJZAMFBXN0YWtlBA0kdDAxMDA2NDEwMTMwCQEYY2FsY1N0YWtpbmdGdW5jQW5kQWRkcmVzAgUFc3Rha2UFB2Fzc2V0SWQEBGNhbGwIBQ0kdDAxMDA2NDEwMTMwAl8xBAtzdGFraW5nQWRkcggFDSR0MDEwMDY0MTAxMzACXzIJAJYKBAUEY2FsbAULc3Rha2luZ0FkZHIFA25pbAkAzAgCCQEPQXR0YWNoZWRQYXltZW50AgUHYXNzZXRJZAUGYW1vdW50BQNuaWwEDSR0MDEwMjE2MTAyODIJARhjYWxjU3Rha2luZ0Z1bmNBbmRBZGRyZXMCBQVzdGFrZQUHYXNzZXRJZAQEY2FsbAgFDSR0MDEwMjE2MTAyODICXzEEC3N0YWtpbmdBZGRyCAUNJHQwMTAyMTYxMDI4MgJfMgkAlgoEBQRjYWxsBQtzdGFraW5nQWRkcgkAzAgCBQZhbW91bnQJAMwIAgkA2AQBBQdhc3NldElkBQNuaWwFA25pbAEUY2FsY3VsYXRlRmVlRGlzY291bnQBCHVzZXJBZGRyBApzd29wQW1vdW50CQELdmFsdWVPckVsc2UCCQCaCAIFCmdvdkFkZHJlc3MJAKwCAgkApQgBBQh1c2VyQWRkcgUOa1VzZXJTd29wSW5Hb3YAAAQOZGlzY291bnRWYWx1ZXMJALUJAgkBEUBleHRyTmF0aXZlKDEwNTMpAgUGb3JhY2xlBQ9rRGlzY291bnRWYWx1ZXMCASwECWRpc2NvdW50cwkAtQkCCQERQGV4dHJOYXRpdmUoMTA1MykCBQZvcmFjbGUFCmtEaXNjb3VudHMCASwDAwkAZwIFCnN3b3BBbW91bnQJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQ5kaXNjb3VudFZhbHVlcwAACQBmAgkBDXBhcnNlSW50VmFsdWUBCQCRAwIFDmRpc2NvdW50VmFsdWVzAAEFCnN3b3BBbW91bnQHCQBlAgUJZmVlU2NhbGU2CQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUJZGlzY291bnRzAAADAwkAZwIFCnN3b3BBbW91bnQJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQ5kaXNjb3VudFZhbHVlcwABCQBmAgkBDXBhcnNlSW50VmFsdWUBCQCRAwIFDmRpc2NvdW50VmFsdWVzAAIFCnN3b3BBbW91bnQHCQBlAgUJZmVlU2NhbGU2CQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUJZGlzY291bnRzAAEDAwkAZwIFCnN3b3BBbW91bnQJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQ5kaXNjb3VudFZhbHVlcwACCQBmAgkBDXBhcnNlSW50VmFsdWUBCQCRAwIFDmRpc2NvdW50VmFsdWVzAAMFCnN3b3BBbW91bnQHCQBlAgUJZmVlU2NhbGU2CQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUJZGlzY291bnRzAAIDAwkAZwIFCnN3b3BBbW91bnQJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQ5kaXNjb3VudFZhbHVlcwADCQBmAgkBDXBhcnNlSW50VmFsdWUBCQCRAwIFDmRpc2NvdW50VmFsdWVzAAQFCnN3b3BBbW91bnQHCQBlAgUJZmVlU2NhbGU2CQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUJZGlzY291bnRzAAMDCQBnAgUKc3dvcEFtb3VudAkBDXBhcnNlSW50VmFsdWUBCQCRAwIFDmRpc2NvdW50VmFsdWVzAAQJAGUCBQlmZWVTY2FsZTYJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQlkaXNjb3VudHMABAUJZmVlU2NhbGU2CgFpAQRpbml0AQxmaXJzdEhhcnZlc3QEDSR0MDExNDc1MTE1NTIJAJQKAggJAJEDAggFAWkIcGF5bWVudHMAAAZhbW91bnQICQCRAwIIBQFpCHBheW1lbnRzAAAHYXNzZXRJZAQKcG10QW1vdW50QQgFDSR0MDExNDc1MTE1NTICXzEEC3BtdEFzc2V0SWRBCAUNJHQwMTE0NzUxMTU1MgJfMgQNJHQwMTE1NTcxMTYzNAkAlAoCCAkAkQMCCAUBaQhwYXltZW50cwABBmFtb3VudAgJAJEDAggFAWkIcGF5bWVudHMAAQdhc3NldElkBApwbXRBbW91bnRCCAUNJHQwMTE1NTcxMTYzNAJfMQQLcG10QXNzZXRJZEIIBQ0kdDAxMTU1NzExNjM0Al8yBA0kdDAxMTYzOTExNzE2CQEMZ2V0QXNzZXRJbmZvAQULcG10QXNzZXRJZEEEDnBtdFN0ckFzc2V0SWRBCAUNJHQwMTE2MzkxMTcxNgJfMQQNcG10QXNzZXROYW1lQQgFDSR0MDExNjM5MTE3MTYCXzIEDHBtdERlY2ltYWxzQQgFDSR0MDExNjM5MTE3MTYCXzMEDSR0MDExNzIxMTE3OTgJAQxnZXRBc3NldEluZm8BBQtwbXRBc3NldElkQgQOcG10U3RyQXNzZXRJZEIIBQ0kdDAxMTcyMTExNzk4Al8xBA1wbXRBc3NldE5hbWVCCAUNJHQwMTE3MjExMTc5OAJfMgQMcG10RGVjaW1hbHNCCAUNJHQwMTE3MjExMTc5OAJfMwMJAQlpc0RlZmluZWQBCQCbCAIFBHRoaXMFB2tBY3RpdmUJAQ10aHJvd0lzQWN0aXZlAAMJAAACBQtwbXRBc3NldElkQQULcG10QXNzZXRJZEIJAAIBAhhBc3NldHMgbXVzdCBiZSBkaWZmZXJlbnQECXNoYXJlTmFtZQkArAICCQCsAgIJAKwCAgIBcwkArwICBQ1wbXRBc3NldE5hbWVBAAcCAV8JAK8CAgUNcG10QXNzZXROYW1lQgAHBBBzaGFyZURlc2NyaXB0aW9uCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgIiU2hhcmVUb2tlbiBvZiBTd29wRmkgcHJvdG9jb2wgZm9yIAUNcG10QXNzZXROYW1lQQIFIGFuZCAFDXBtdEFzc2V0TmFtZUICDCBhdCBhZGRyZXNzIAkApQgBBQR0aGlzBA1zaGFyZURlY2ltYWxzCQBpAgkAZAIFDHBtdERlY2ltYWxzQQUMcG10RGVjaW1hbHNCAAIEEnNoYXJlSW5pdGlhbFN1cHBseQkAawMJAGwGBQpwbXRBbW91bnRBBQxwbXREZWNpbWFsc0EABQABBQxwbXREZWNpbWFsc0EFBERPV04JAGwGBQpwbXRBbW91bnRCBQxwbXREZWNpbWFsc0IABQABBQxwbXREZWNpbWFsc0IFBERPV04JAGwGAAoAAAUNc2hhcmVEZWNpbWFscwAAAAAFBERPV04ECnNoYXJlSXNzdWUJAMIIBQUJc2hhcmVOYW1lBRBzaGFyZURlc2NyaXB0aW9uBRJzaGFyZUluaXRpYWxTdXBwbHkFDXNoYXJlRGVjaW1hbHMGBAxzaGFyZUlzc3VlSWQJALgIAQUKc2hhcmVJc3N1ZQQTaW52YXJpYW50Q2FsY3VsYXRlZAkBDWludmFyaWFudENhbGMCBQpwbXRBbW91bnRBBQpwbXRBbW91bnRCBAZzdGFrZTEDCQEPY29udGFpbnNFbGVtZW50AgUNc3Rha2luZ0Fzc2V0cwUOcG10U3RyQXNzZXRJZEEJAPwHBAUEdGhpcwIMc3Rha2VVbnN0YWtlCQDMCAIGCQDMCAIFCnBtdEFtb3VudEEJAMwIAgUOcG10U3RyQXNzZXRJZEEFA25pbAUDbmlsAAADCQAAAgUGc3Rha2UxBQZzdGFrZTEEBnN0YWtlMgMJAQ9jb250YWluc0VsZW1lbnQCBQ1zdGFraW5nQXNzZXRzBQ5wbXRTdHJBc3NldElkQgkA/AcEBQR0aGlzAgxzdGFrZVVuc3Rha2UJAMwIAgYJAMwIAgUKcG10QW1vdW50QgkAzAgCBQ5wbXRTdHJBc3NldElkQgUDbmlsBQNuaWwAAAMJAAACBQZzdGFrZTIFBnN0YWtlMgQJYmFzZUVudHJ5CQDMCAIJAQtTdHJpbmdFbnRyeQIFCGtWZXJzaW9uBQd2ZXJzaW9uCQDMCAIJAQxCb29sZWFuRW50cnkCBQdrQWN0aXZlBgkAzAgCCQELU3RyaW5nRW50cnkCBQlrQXNzZXRJZEEFDnBtdFN0ckFzc2V0SWRBCQDMCAIJAQtTdHJpbmdFbnRyeQIFCWtBc3NldElkQgUOcG10U3RyQXNzZXRJZEIJAMwIAgkBDEludGVnZXJFbnRyeQIFCWtCYWxhbmNlQQUKcG10QW1vdW50QQkAzAgCCQEMSW50ZWdlckVudHJ5AgUJa0JhbGFuY2VCBQpwbXRBbW91bnRCCQDMCAIJAQxJbnRlZ2VyRW50cnkCBQprSW52YXJpYW50BRNpbnZhcmlhbnRDYWxjdWxhdGVkCQDMCAIJAQxJbnRlZ2VyRW50cnkCBQRrRmVlCQERQGV4dHJOYXRpdmUoMTA1MCkCBQZvcmFjbGUCDWJhc2VfZmVlX2ZsYXQJAMwIAgUKc2hhcmVJc3N1ZQkAzAgCCQELU3RyaW5nRW50cnkCBQ1rU2hhcmVBc3NldElkCQDYBAEFDHNoYXJlSXNzdWVJZAkAzAgCCQEMSW50ZWdlckVudHJ5AgURa1NoYXJlQXNzZXRTdXBwbHkFEnNoYXJlSW5pdGlhbFN1cHBseQkAzAgCCQEOU2NyaXB0VHJhbnNmZXIDCAUBaQZjYWxsZXIFEnNoYXJlSW5pdGlhbFN1cHBseQUMc2hhcmVJc3N1ZUlkBQNuaWwDBQxmaXJzdEhhcnZlc3QJAM4IAgUJYmFzZUVudHJ5CQDMCAIJAQxCb29sZWFuRW50cnkCBQ1rRmlyc3RIYXJ2ZXN0BQxmaXJzdEhhcnZlc3QJAMwIAgkBDEludGVnZXJFbnRyeQIFE2tGaXJzdEhhcnZlc3RIZWlnaHQJAGQCBQtzdGFydEhlaWdodAkAaAIFFWZpcnN0SGFydmVzdEVuZFBlcmlvZAUMcGVyaW9kTGVuZ3RoBQNuaWwFCWJhc2VFbnRyeQkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpARZyZXBsZW5pc2hXaXRoVHdvVG9rZW5zAAkBC3ZhbHVlT3JFbHNlAgkBCGlzQWN0aXZlAAQLcG10QXNzZXRJZEEICQCRAwIIBQFpCHBheW1lbnRzAAAHYXNzZXRJZAQLcG10QXNzZXRJZEIICQCRAwIIBQFpCHBheW1lbnRzAAEHYXNzZXRJZAQTcmF0aW9TaGFyZVRva2Vuc0luQQkAawMFBnNjYWxlOAgJAJEDAggFAWkIcGF5bWVudHMAAAZhbW91bnQFCGJhbGFuY2VBBBNyYXRpb1NoYXJlVG9rZW5zSW5CCQBrAwUGc2NhbGU4CAkAkQMCCAUBaQhwYXltZW50cwABBmFtb3VudAUIYmFsYW5jZUIEDSR0MDE0NzQ2MTQ4MjMJAQxnZXRBc3NldEluZm8BBQtwbXRBc3NldElkQQQOcG10U3RyQXNzZXRJZEEIBQ0kdDAxNDc0NjE0ODIzAl8xBA1wbXRBc3NldE5hbWVBCAUNJHQwMTQ3NDYxNDgyMwJfMgQMcG10RGVjaW1hbHNBCAUNJHQwMTQ3NDYxNDgyMwJfMwQNJHQwMTQ4MjgxNDk0NQkBDGdldEFzc2V0SW5mbwEFC3BtdEFzc2V0SWRCBA5wbXRTdHJBc3NldElkQggFDSR0MDE0ODI4MTQ5NDUCXzEEDXBtdEFzc2V0TmFtZUIIBQ0kdDAxNDgyODE0OTQ1Al8yBAxwbXREZWNpbWFsc0IIBQ0kdDAxNDgyODE0OTQ1Al8zBA0kdDAxNDk1MDE1NDU0AwkAZgIFE3JhdGlvU2hhcmVUb2tlbnNJbkIFE3JhdGlvU2hhcmVUb2tlbnNJbkEEA3BtdAkAbgQFCGJhbGFuY2VCBRNyYXRpb1NoYXJlVG9rZW5zSW5BBQZzY2FsZTgFB0NFSUxJTkcJAJcKBQgJAJEDAggFAWkIcGF5bWVudHMAAAZhbW91bnQFA3BtdAkAZQIICQCRAwIIBQFpCHBheW1lbnRzAAEGYW1vdW50BQNwbXQFC3BtdEFzc2V0SWRCBRNyYXRpb1NoYXJlVG9rZW5zSW5BBANwbXQJAG4EBQhiYWxhbmNlQQUTcmF0aW9TaGFyZVRva2Vuc0luQgUGc2NhbGU4BQdDRUlMSU5HCQCXCgUFA3BtdAgJAJEDAggFAWkIcGF5bWVudHMAAQZhbW91bnQJAGUCCAkAkQMCCAUBaQhwYXltZW50cwAABmFtb3VudAUDcG10BQtwbXRBc3NldElkQQUTcmF0aW9TaGFyZVRva2Vuc0luQgQKcG10QW1vdW50QQgFDSR0MDE0OTUwMTU0NTQCXzEECnBtdEFtb3VudEIIBQ0kdDAxNDk1MDE1NDU0Al8yBAZjaGFuZ2UIBQ0kdDAxNDk1MDE1NDU0Al8zBA1jaGFuZ2VBc3NldElkCAUNJHQwMTQ5NTAxNTQ1NAJfNAQPc2hhcmVUb2tlblJhdGlvCAUNJHQwMTQ5NTAxNTQ1NAJfNQQVc2hhcmVUb2tlblRvUGF5QW1vdW50CQBrAwUPc2hhcmVUb2tlblJhdGlvBRBzaGFyZUFzc2V0U3VwcGx5BQZzY2FsZTgDCQECIT0CCQCQAwEIBQFpCHBheW1lbnRzAAIJAAIBAhxUd28gYXR0YWNoZWQgYXNzZXRzIGV4cGVjdGVkAwMJAQIhPQIFC3BtdEFzc2V0SWRBBQhhc3NldElkQQYJAQIhPQIFC3BtdEFzc2V0SWRCBQhhc3NldElkQgkBC3Rocm93QXNzZXRzAAMJAAACBRVzaGFyZVRva2VuVG9QYXlBbW91bnQAAAkAAgECHVRvbyBzbWFsbCBhbW91bnQgdG8gcmVwbGVuaXNoAwkAZgIAAAUGY2hhbmdlCQACAQIKQ2hhbmdlIDwgMAMJAQEhAQUQaGFzRW5vdWdoQmFsYW5jZQkAzggCCQDMCAIJAQ5TY3JpcHRUcmFuc2ZlcgMIBQFpBmNhbGxlcgUKcG10QW1vdW50QQULcG10QXNzZXRJZEEJAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwgFAWkGY2FsbGVyBQpwbXRBbW91bnRCBQtwbXRBc3NldElkQgUDbmlsCQERc3VzcGVuZFN1c3BpY2lvdXMABAZzdGFrZTEDCQEPY29udGFpbnNFbGVtZW50AgUNc3Rha2luZ0Fzc2V0cwUOcG10U3RyQXNzZXRJZEEJAPwHBAUEdGhpcwIMc3Rha2VVbnN0YWtlCQDMCAIGCQDMCAIFCnBtdEFtb3VudEEJAMwIAgUOcG10U3RyQXNzZXRJZEEFA25pbAUDbmlsAAADCQAAAgUGc3Rha2UxBQZzdGFrZTEEBnN0YWtlMgMJAQ9jb250YWluc0VsZW1lbnQCBQ1zdGFraW5nQXNzZXRzBQ5wbXRTdHJBc3NldElkQgkA/AcEBQR0aGlzAgxzdGFrZVVuc3Rha2UJAMwIAgYJAMwIAgUKcG10QW1vdW50QgkAzAgCBQ5wbXRTdHJBc3NldElkQgUDbmlsBQNuaWwAAAMJAAACBQZzdGFrZTIFBnN0YWtlMgkAzAgCCQEMSW50ZWdlckVudHJ5AgUJa0JhbGFuY2VBCQBkAgUIYmFsYW5jZUEFCnBtdEFtb3VudEEJAMwIAgkBDEludGVnZXJFbnRyeQIFCWtCYWxhbmNlQgkAZAIFCGJhbGFuY2VCBQpwbXRBbW91bnRCCQDMCAIJAQxJbnRlZ2VyRW50cnkCBRFrU2hhcmVBc3NldFN1cHBseQkAZAIFEHNoYXJlQXNzZXRTdXBwbHkFFXNoYXJlVG9rZW5Ub1BheUFtb3VudAkAzAgCCQEMSW50ZWdlckVudHJ5AgUKa0ludmFyaWFudAkBDWludmFyaWFudENhbGMCCQBkAgUIYmFsYW5jZUEFCnBtdEFtb3VudEEJAGQCBQhiYWxhbmNlQgUKcG10QW1vdW50QgkAzAgCCQEHUmVpc3N1ZQMFDHNoYXJlQXNzZXRJZAUVc2hhcmVUb2tlblRvUGF5QW1vdW50BgkAzAgCCQEOU2NyaXB0VHJhbnNmZXIDCAUBaQZjYWxsZXIFFXNoYXJlVG9rZW5Ub1BheUFtb3VudAUMc2hhcmVBc3NldElkCQDMCAIJAQ5TY3JpcHRUcmFuc2ZlcgMIBQFpBmNhbGxlcgUGY2hhbmdlBQ1jaGFuZ2VBc3NldElkBQNuaWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQEVcmVwbGVuaXNoV2l0aE9uZVRva2VuAhN2aXJ0dWFsU3dhcFRva2VuUGF5E3ZpcnR1YWxTd2FwVG9rZW5HZXQJAQt2YWx1ZU9yRWxzZQIJAQhpc0FjdGl2ZQAEDSR0MDE3MTg3MTcyNjIJAJQKAggJAJEDAggFAWkIcGF5bWVudHMAAAZhbW91bnQICQCRAwIIBQFpCHBheW1lbnRzAAAHYXNzZXRJZAQJcG10QW1vdW50CAUNJHQwMTcxODcxNzI2MgJfMQQKcG10QXNzZXRJZAgFDSR0MDE3MTg3MTcyNjICXzIEDSR0MDE3MjY3MTczNDAJAQxnZXRBc3NldEluZm8BBQpwbXRBc3NldElkBA1wbXRTdHJBc3NldElkCAUNJHQwMTcyNjcxNzM0MAJfMQQMcG10QXNzZXROYW1lCAUNJHQwMTcyNjcxNzM0MAJfMgQLcG10RGVjaW1hbHMIBQ0kdDAxNzI2NzE3MzQwAl8zBA9wbXRNaW5UaHJlc2hvbGQAwJaxAgQddGhyZXNob2xkVmFsdWVGb3JNaW5Ub2xlcmFuY2UAgOHrFwQJdG9sZXJhbmNlAwkAZgIFHXRocmVzaG9sZFZhbHVlRm9yTWluVG9sZXJhbmNlBQlwbXRBbW91bnQAoI0GAAEEHHNsaXBwYWdlVmFsdWVNaW5Gb3JSZXBsZW5pc2gJAGUCBQZzY2FsZTgJAGkCCQBoAgUGc2NhbGU4BQl0b2xlcmFuY2UAgK3iBAQcc2xpcHBhZ2VWYWx1ZU1heEZvclJlcGxlbmlzaAkAZAIFBnNjYWxlOAkAaQIJAGgCBQZzY2FsZTgFCXRvbGVyYW5jZQCAreIEBBdzbGlwcGFnZVZhbHVlTWluRm9yU3dhcAkAZQIFBnNjYWxlOAkAaQIJAGgCBQZzY2FsZTgAAQCAreIEAwkAZgIFD3BtdE1pblRocmVzaG9sZAUJcG10QW1vdW50CQACAQkArAICCQCsAgIJAKwCAgkArAICAg9QYXltZW50IGFtb3VudCAJAKQDAQUJcG10QW1vdW50AicgZG9lcyBub3QgZXhjZWVkIHRoZSBtaW5pbXVtIGFtb3VudCBvZiAJAKQDAQUPcG10TWluVGhyZXNob2xkAgcgdG9rZW5zAwkBAiE9AgkAkAMBCAUBaQhwYXltZW50cwABCQEPdGhyb3dPbmVQYXltZW50AAMJAQEhAQUQaGFzRW5vdWdoQmFsYW5jZQkAzggCCQDMCAIJAQ5TY3JpcHRUcmFuc2ZlcgMIBQFpBmNhbGxlcgUJcG10QW1vdW50BQpwbXRBc3NldElkBQNuaWwJARFzdXNwZW5kU3VzcGljaW91cwADAwkBAiE9AgUKcG10QXNzZXRJZAUIYXNzZXRJZEEJAQIhPQIFCnBtdEFzc2V0SWQFCGFzc2V0SWRCBwkBC3Rocm93QXNzZXRzAAQNJHQwMTgzMTgxODk2MAMJAAACBQpwbXRBc3NldElkBQhhc3NldElkQQkAmAoGCQBlAgUJcG10QW1vdW50BRN2aXJ0dWFsU3dhcFRva2VuUGF5BRN2aXJ0dWFsU3dhcFRva2VuR2V0CQBkAgUIYmFsYW5jZUEFE3ZpcnR1YWxTd2FwVG9rZW5QYXkJAGUCBQhiYWxhbmNlQgUTdmlydHVhbFN3YXBUb2tlbkdldAkAZAIFCGJhbGFuY2VBBQlwbXRBbW91bnQFCGJhbGFuY2VCCQCYCgYFE3ZpcnR1YWxTd2FwVG9rZW5HZXQJAGUCBQlwbXRBbW91bnQFE3ZpcnR1YWxTd2FwVG9rZW5QYXkJAGUCBQhiYWxhbmNlQQUTdmlydHVhbFN3YXBUb2tlbkdldAkAZAIFCGJhbGFuY2VCBRN2aXJ0dWFsU3dhcFRva2VuUGF5BQhiYWxhbmNlQQkAZAIFCGJhbGFuY2VCBQlwbXRBbW91bnQEEXZpcnR1YWxSZXBsZW5pc2hBCAUNJHQwMTgzMTgxODk2MAJfMQQRdmlydHVhbFJlcGxlbmlzaEIIBQ0kdDAxODMxODE4OTYwAl8yBBFiYWxhbmNlQWZ0ZXJTd2FwQQgFDSR0MDE4MzE4MTg5NjACXzMEEWJhbGFuY2VBZnRlclN3YXBCCAUNJHQwMTgzMTgxODk2MAJfNAQLbmV3QmFsYW5jZUEIBQ0kdDAxODMxODE4OTYwAl81BAtuZXdCYWxhbmNlQggFDSR0MDE4MzE4MTg5NjACXzYEDGludmFyaWFudE5ldwkBDWludmFyaWFudENhbGMCBRFiYWxhbmNlQWZ0ZXJTd2FwQQURYmFsYW5jZUFmdGVyU3dhcEIEJXJhdGlvVmlydHVhbEJhbGFuY2VUb1ZpcnR1YWxSZXBsZW5pc2gJAGkCCQBrAwUHc2NhbGUxNgURYmFsYW5jZUFmdGVyU3dhcEEFEWJhbGFuY2VBZnRlclN3YXBCCQBrAwUGc2NhbGU4BRF2aXJ0dWFsUmVwbGVuaXNoQQURdmlydHVhbFJlcGxlbmlzaEIEE2RBcHBUaHJlc2hvbGRBbW91bnQJAGsDCQBkAgULbmV3QmFsYW5jZUEFC25ld0JhbGFuY2VCBQ1kQXBwVGhyZXNob2xkCQBoAgACBRNkQXBwVGhyZXNob2xkU2NhbGUyAwMJAGcCBRdzbGlwcGFnZVZhbHVlTWluRm9yU3dhcAkAawMFBnNjYWxlOAUJaW52YXJpYW50BQxpbnZhcmlhbnROZXcGCQBmAgUJaW52YXJpYW50BQxpbnZhcmlhbnROZXcJAAIBAjpJbmNvcnJlY3QgdmlydHVhbFN3YXBUb2tlblBheSBvciB2aXJ0dWFsU3dhcFRva2VuR2V0IHZhbHVlAwMJAGYCBRxzbGlwcGFnZVZhbHVlTWluRm9yUmVwbGVuaXNoBSVyYXRpb1ZpcnR1YWxCYWxhbmNlVG9WaXJ0dWFsUmVwbGVuaXNoBgkAZgIFJXJhdGlvVmlydHVhbEJhbGFuY2VUb1ZpcnR1YWxSZXBsZW5pc2gFHHNsaXBwYWdlVmFsdWVNYXhGb3JSZXBsZW5pc2gJAAIBAmxTd2FwIHdpdGggdmlydHVhbFN3YXBUb2tlblBheSBhbmQgdmlydHVhbFN3YXBUb2tlbkdldCBpcyBwb3NzaWJsZSwgYnV0IHJhdGlvIGFmdGVyIHZpcnR1YWwgc3dhcCBpcyBpbmNvcnJlY3QDAwkAZgIFE2RBcHBUaHJlc2hvbGRBbW91bnQFC25ld0JhbGFuY2VBBgkAZgIFE2RBcHBUaHJlc2hvbGRBbW91bnQFC25ld0JhbGFuY2VCCQEOdGhyb3dUaHJlc2hvbGQDBRNkQXBwVGhyZXNob2xkQW1vdW50BQtuZXdCYWxhbmNlQQULbmV3QmFsYW5jZUIEE3JhdGlvU2hhcmVUb2tlbnNJbkEJAGsDBRF2aXJ0dWFsUmVwbGVuaXNoQQUGc2NhbGU4BRFiYWxhbmNlQWZ0ZXJTd2FwQQQTcmF0aW9TaGFyZVRva2Vuc0luQgkAawMFEXZpcnR1YWxSZXBsZW5pc2hCBQZzY2FsZTgFEWJhbGFuY2VBZnRlclN3YXBCBBVzaGFyZVRva2VuVG9QYXlBbW91bnQJAGsDCQCXAwEJAMwIAgUTcmF0aW9TaGFyZVRva2Vuc0luQQkAzAgCBRNyYXRpb1NoYXJlVG9rZW5zSW5CBQNuaWwFEHNoYXJlQXNzZXRTdXBwbHkFBnNjYWxlOAQdc2hhcmVUb2tlblRvUGF5QW1vdW50QWZ0ZXJGZWUJAGsDBRVzaGFyZVRva2VuVG9QYXlBbW91bnQJAGUCBQlmZWVTY2FsZTYJAGkCBQNmZWUAAgUJZmVlU2NhbGU2BBpzaGFyZVRva2VuR292ZXJuYW5jZVJld2FyZAkAawMFFXNoYXJlVG9rZW5Ub1BheUFtb3VudAkAaQIFDWZlZUdvdmVybmFuY2UAAgUJZmVlU2NhbGU2BBZnb3Zlcm5hbmNlUmV3YXJkVG9rZW5BCQBrAwUac2hhcmVUb2tlbkdvdmVybmFuY2VSZXdhcmQFCGJhbGFuY2VBBRBzaGFyZUFzc2V0U3VwcGx5BBZnb3Zlcm5hbmNlUmV3YXJkVG9rZW5CCQBrAwUac2hhcmVUb2tlbkdvdmVybmFuY2VSZXdhcmQFCGJhbGFuY2VCBRBzaGFyZUFzc2V0U3VwcGx5BA0kdDAyMDk0NzIxMjQyAwkAAAIFDXBtdFN0ckFzc2V0SWQFC3N0ckFzc2V0SWRBCQCVCgMJAGUCBQlwbXRBbW91bnQFFmdvdmVybmFuY2VSZXdhcmRUb2tlbkEFFmdvdmVybmFuY2VSZXdhcmRUb2tlbkIFC3N0ckFzc2V0SWRCCQCVCgMJAGUCBQlwbXRBbW91bnQFFmdvdmVybmFuY2VSZXdhcmRUb2tlbkIFFmdvdmVybmFuY2VSZXdhcmRUb2tlbkEFC3N0ckFzc2V0SWRBBAtzdGFrZUFtb3VudAgFDSR0MDIwOTQ3MjEyNDICXzEEDXVuc3Rha2VBbW91bnQIBQ0kdDAyMDk0NzIxMjQyAl8yBAx1bnN0YWtlQXNzZXQIBQ0kdDAyMDk0NzIxMjQyAl8zBAZzdGFrZTEDCQEPY29udGFpbnNFbGVtZW50AgUNc3Rha2luZ0Fzc2V0cwUNcG10U3RyQXNzZXRJZAkA/AcEBQR0aGlzAgxzdGFrZVVuc3Rha2UJAMwIAgYJAMwIAgULc3Rha2VBbW91bnQJAMwIAgUNcG10U3RyQXNzZXRJZAUDbmlsBQNuaWwAAAMJAAACBQZzdGFrZTEFBnN0YWtlMQQGc3Rha2UyAwkBD2NvbnRhaW5zRWxlbWVudAIFDXN0YWtpbmdBc3NldHMFDHVuc3Rha2VBc3NldAkA/AcEBQR0aGlzAgxzdGFrZVVuc3Rha2UJAMwIAgcJAMwIAgUNdW5zdGFrZUFtb3VudAkAzAgCBQx1bnN0YWtlQXNzZXQFA25pbAUDbmlsAAADCQAAAgUGc3Rha2UyBQZzdGFrZTIJAMwIAgkBB1JlaXNzdWUDBQxzaGFyZUFzc2V0SWQFHXNoYXJlVG9rZW5Ub1BheUFtb3VudEFmdGVyRmVlBgkAzAgCCQEOU2NyaXB0VHJhbnNmZXIDCAUBaQZjYWxsZXIFHXNoYXJlVG9rZW5Ub1BheUFtb3VudEFmdGVyRmVlBQxzaGFyZUFzc2V0SWQJAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwUPbW9uZXlCb3hBZGRyZXNzBRZnb3Zlcm5hbmNlUmV3YXJkVG9rZW5BBQhhc3NldElkQQkAzAgCCQEOU2NyaXB0VHJhbnNmZXIDBQ9tb25leUJveEFkZHJlc3MFFmdvdmVybmFuY2VSZXdhcmRUb2tlbkIFCGFzc2V0SWRCCQDMCAIJAQxJbnRlZ2VyRW50cnkCBQlrQmFsYW5jZUEJAGUCBQtuZXdCYWxhbmNlQQUWZ292ZXJuYW5jZVJld2FyZFRva2VuQQkAzAgCCQEMSW50ZWdlckVudHJ5AgUJa0JhbGFuY2VCCQBlAgULbmV3QmFsYW5jZUIFFmdvdmVybmFuY2VSZXdhcmRUb2tlbkIJAMwIAgkBDEludGVnZXJFbnRyeQIFEWtTaGFyZUFzc2V0U3VwcGx5CQBkAgUQc2hhcmVBc3NldFN1cHBseQUdc2hhcmVUb2tlblRvUGF5QW1vdW50QWZ0ZXJGZWUJAMwIAgkBDEludGVnZXJFbnRyeQIFCmtJbnZhcmlhbnQJAQ1pbnZhcmlhbnRDYWxjAgkAZQIFC25ld0JhbGFuY2VBBRZnb3Zlcm5hbmNlUmV3YXJkVG9rZW5BCQBlAgULbmV3QmFsYW5jZUIFFmdvdmVybmFuY2VSZXdhcmRUb2tlbkIFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpAQh3aXRoZHJhdwAJAQt2YWx1ZU9yRWxzZQIJAQhpc0FjdGl2ZQAEDSR0MDIyNTI5MjI2MDQJAJQKAggJAJEDAggFAWkIcGF5bWVudHMAAAZhbW91bnQICQCRAwIIBQFpCHBheW1lbnRzAAAHYXNzZXRJZAQJcG10QW1vdW50CAUNJHQwMjI1MjkyMjYwNAJfMQQKcG10QXNzZXRJZAgFDSR0MDIyNTI5MjI2MDQCXzIEDGFtb3VudFRvUGF5QQkAawMFCXBtdEFtb3VudAUIYmFsYW5jZUEFEHNoYXJlQXNzZXRTdXBwbHkEDGFtb3VudFRvUGF5QgkAawMFCXBtdEFtb3VudAUIYmFsYW5jZUIFEHNoYXJlQXNzZXRTdXBwbHkEE2ludmFyaWFudENhbGN1bGF0ZWQJAQ1pbnZhcmlhbnRDYWxjAgkAZQIFCGJhbGFuY2VBBQxhbW91bnRUb1BheUEJAGUCBQhiYWxhbmNlQgUMYW1vdW50VG9QYXlCAwkBAiE9AgkAkAMBCAUBaQhwYXltZW50cwABCQEPdGhyb3dPbmVQYXltZW50AAMJAQIhPQIFCnBtdEFzc2V0SWQFDHNoYXJlQXNzZXRJZAkAAgEJAKwCAgIkSW5jb3JyZWN0IGFzc2V0IGF0dGFjaGVkLiBFeHBlY3RlZDogCQDYBAEFDHNoYXJlQXNzZXRJZAMJAQEhAQUQaGFzRW5vdWdoQmFsYW5jZQkAzggCCQDMCAIJAQ5TY3JpcHRUcmFuc2ZlcgMIBQFpBmNhbGxlcgUJcG10QW1vdW50BQpwbXRBc3NldElkBQNuaWwJARFzdXNwZW5kU3VzcGljaW91cwAEBnN0YWtlMQMJAQ9jb250YWluc0VsZW1lbnQCBQ1zdGFraW5nQXNzZXRzBQtzdHJBc3NldElkQQkA/AcEBQR0aGlzAgxzdGFrZVVuc3Rha2UJAMwIAgcJAMwIAgUMYW1vdW50VG9QYXlBCQDMCAIFC3N0ckFzc2V0SWRBBQNuaWwFA25pbAAAAwkAAAIFBnN0YWtlMQUGc3Rha2UxBAZzdGFrZTIDCQEPY29udGFpbnNFbGVtZW50AgUNc3Rha2luZ0Fzc2V0cwULc3RyQXNzZXRJZEIJAPwHBAUEdGhpcwIMc3Rha2VVbnN0YWtlCQDMCAIHCQDMCAIFDGFtb3VudFRvUGF5QgkAzAgCBQtzdHJBc3NldElkQgUDbmlsBQNuaWwAAAMJAAACBQZzdGFrZTIFBnN0YWtlMgkAzAgCCQEMSW50ZWdlckVudHJ5AgUJa0JhbGFuY2VBCQBlAgUIYmFsYW5jZUEFDGFtb3VudFRvUGF5QQkAzAgCCQEMSW50ZWdlckVudHJ5AgUJa0JhbGFuY2VCCQBlAgUIYmFsYW5jZUIFDGFtb3VudFRvUGF5QgkAzAgCCQEMSW50ZWdlckVudHJ5AgURa1NoYXJlQXNzZXRTdXBwbHkJAGUCBRBzaGFyZUFzc2V0U3VwcGx5BQlwbXRBbW91bnQJAMwIAgkBDEludGVnZXJFbnRyeQIFCmtJbnZhcmlhbnQFE2ludmFyaWFudENhbGN1bGF0ZWQJAMwIAgkBBEJ1cm4CBQxzaGFyZUFzc2V0SWQFCXBtdEFtb3VudAkAzAgCCQEOU2NyaXB0VHJhbnNmZXIDCAUBaQZjYWxsZXIFDGFtb3VudFRvUGF5QQUIYXNzZXRJZEEJAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwgFAWkGY2FsbGVyBQxhbW91bnRUb1BheUIFCGFzc2V0SWRCBQNuaWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQEIZXhjaGFuZ2UCGGVzdGltYXRlZEFtb3VudFRvUmVjZWl2ZRJtaW5BbW91bnRUb1JlY2VpdmUJAQt2YWx1ZU9yRWxzZQIJAQhpc0FjdGl2ZQAEDSR0MDI0MTU1MjQyMzAJAJQKAggJAJEDAggFAWkIcGF5bWVudHMAAAZhbW91bnQICQCRAwIIBQFpCHBheW1lbnRzAAAHYXNzZXRJZAQJcG10QW1vdW50CAUNJHQwMjQxNTUyNDIzMAJfMQQKcG10QXNzZXRJZAgFDSR0MDI0MTU1MjQyMzACXzIDCQBnAgAABRhlc3RpbWF0ZWRBbW91bnRUb1JlY2VpdmUJAAIBCQCsAgICK0VzdGltYXRlZCBhbW91bnQgbXVzdCBiZSBwb3NpdGl2ZS4gQWN0dWFsOiAJAKQDAQUYZXN0aW1hdGVkQW1vdW50VG9SZWNlaXZlAwkAZgIFEm1pbkFtb3VudFRvUmVjZWl2ZQUYZXN0aW1hdGVkQW1vdW50VG9SZWNlaXZlCQACAQIvTWluaW1hbCBhbW91bnQgY2FuJ3QgYmUgZ3JlYXRlciB0aGFuIGVzdGltYXRlZC4DCQECIT0CCQCQAwEIBQFpCHBheW1lbnRzAAEJAQ90aHJvd09uZVBheW1lbnQAAwkBASEBBRBoYXNFbm91Z2hCYWxhbmNlCQDOCAIJAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwgFAWkGY2FsbGVyBQlwbXRBbW91bnQFCnBtdEFzc2V0SWQFA25pbAkBEXN1c3BlbmRTdXNwaWNpb3VzAAMDCQECIT0CBQpwbXRBc3NldElkBQhhc3NldElkQQkBAiE9AgUKcG10QXNzZXRJZAUIYXNzZXRJZEIHCQELdGhyb3dBc3NldHMAAwkAZgIAgK3iBAUJcG10QW1vdW50CQACAQIwT25seSBzd2FwIG9mIDEwLjAwMDAwMCBvciBtb3JlIHRva2VucyBpcyBhbGxvd2VkAwMJAGYCBRVleGNoYW5nZVJhdGlvTGltaXRNaW4JAGsDBQZzY2FsZTgFEm1pbkFtb3VudFRvUmVjZWl2ZQUJcG10QW1vdW50BgkAZgIJAGsDBQZzY2FsZTgFGGVzdGltYXRlZEFtb3VudFRvUmVjZWl2ZQUJcG10QW1vdW50BRVleGNoYW5nZVJhdGlvTGltaXRNYXgJAAIBAhxJbmNvcnJlY3QgYXJncyBhbmQgcG10IHJhdGlvBAtzZW5kQXNzZXRJZAMJAAACBQpwbXRBc3NldElkBQhhc3NldElkQQUIYXNzZXRJZEIFCGFzc2V0SWRBBAZhbW91bnQJARNjYWxjdWxhdGVTZW5kQW1vdW50BAUYZXN0aW1hdGVkQW1vdW50VG9SZWNlaXZlBRJtaW5BbW91bnRUb1JlY2VpdmUFCXBtdEFtb3VudAUKcG10QXNzZXRJZAQLZmVlRGlzY291bnQJARRjYWxjdWxhdGVGZWVEaXNjb3VudAEIBQFpDG9yaWdpbkNhbGxlcgQQZ292ZXJuYW5jZVJld2FyZAkAawMFBmFtb3VudAkAbgQFDWZlZUdvdmVybmFuY2UFC2ZlZURpc2NvdW50BQlmZWVTY2FsZTYFB0NFSUxJTkcFCWZlZVNjYWxlNgQOYW1vdW50TWludXNGZWUJAGsDBQZhbW91bnQJAGUCBQlmZWVTY2FsZTYJAG4EBQNmZWUFC2ZlZURpc2NvdW50BQlmZWVTY2FsZTYFB0NFSUxJTkcFCWZlZVNjYWxlNgQNJHQwMjU2ODMyNTk0NQMJAAACBQpwbXRBc3NldElkBQhhc3NldElkQQkAlAoCCQBkAgUIYmFsYW5jZUEFCXBtdEFtb3VudAkAZQIJAGUCBQhiYWxhbmNlQgUOYW1vdW50TWludXNGZWUFEGdvdmVybmFuY2VSZXdhcmQJAJQKAgkAZQIJAGUCBQhiYWxhbmNlQQUOYW1vdW50TWludXNGZWUFEGdvdmVybmFuY2VSZXdhcmQJAGQCBQhiYWxhbmNlQgUJcG10QW1vdW50BAtuZXdCYWxhbmNlQQgFDSR0MDI1NjgzMjU5NDUCXzEEC25ld0JhbGFuY2VCCAUNJHQwMjU2ODMyNTk0NQJfMgQTZEFwcFRocmVzaG9sZEFtb3VudAkAawMJAGQCBQtuZXdCYWxhbmNlQQULbmV3QmFsYW5jZUIFDWRBcHBUaHJlc2hvbGQJAGgCAAIFE2RBcHBUaHJlc2hvbGRTY2FsZTIDAwkAZgIFE2RBcHBUaHJlc2hvbGRBbW91bnQFC25ld0JhbGFuY2VBBgkAZgIFE2RBcHBUaHJlc2hvbGRBbW91bnQFC25ld0JhbGFuY2VCCQEOdGhyb3dUaHJlc2hvbGQDBRNkQXBwVGhyZXNob2xkQW1vdW50BQtuZXdCYWxhbmNlQQULbmV3QmFsYW5jZUIEDSR0MDI2MjQ0MjYzMTcJAQxnZXRBc3NldEluZm8BBQpwbXRBc3NldElkBA1wbXRTdHJBc3NldElkCAUNJHQwMjYyNDQyNjMxNwJfMQQMcG10QXNzZXROYW1lCAUNJHQwMjYyNDQyNjMxNwJfMgQLcG10RGVjaW1hbHMIBQ0kdDAyNjI0NDI2MzE3Al8zBA0kdDAyNjMzMDI2NDA3CQEMZ2V0QXNzZXRJbmZvAQULc2VuZEFzc2V0SWQEDnNlbmRTdHJBc3NldElkCAUNJHQwMjYzMzAyNjQwNwJfMQQNc2VuZEFzc2V0TmFtZQgFDSR0MDI2MzMwMjY0MDcCXzIEDHNlbmREZWNpbWFscwgFDSR0MDI2MzMwMjY0MDcCXzMEBnN0YWtlMQMJAQ9jb250YWluc0VsZW1lbnQCBQ1zdGFraW5nQXNzZXRzBQ1wbXRTdHJBc3NldElkCQD8BwQFBHRoaXMCDHN0YWtlVW5zdGFrZQkAzAgCBgkAzAgCBQlwbXRBbW91bnQJAMwIAgUNcG10U3RyQXNzZXRJZAUDbmlsBQNuaWwAAAMJAAACBQZzdGFrZTEFBnN0YWtlMQQGc3Rha2UyAwkBD2NvbnRhaW5zRWxlbWVudAIFDXN0YWtpbmdBc3NldHMFDnNlbmRTdHJBc3NldElkCQD8BwQFBHRoaXMCDHN0YWtlVW5zdGFrZQkAzAgCBwkAzAgCCQBkAgUOYW1vdW50TWludXNGZWUFEGdvdmVybmFuY2VSZXdhcmQJAMwIAgUOc2VuZFN0ckFzc2V0SWQFA25pbAUDbmlsAAADCQAAAgUGc3Rha2UyBQZzdGFrZTIJAJQKAgkAzAgCCQEMSW50ZWdlckVudHJ5AgUJa0JhbGFuY2VBBQtuZXdCYWxhbmNlQQkAzAgCCQEMSW50ZWdlckVudHJ5AgUJa0JhbGFuY2VCBQtuZXdCYWxhbmNlQgkAzAgCCQEMSW50ZWdlckVudHJ5AgUKa0ludmFyaWFudAkBDWludmFyaWFudENhbGMCBQtuZXdCYWxhbmNlQQULbmV3QmFsYW5jZUIJAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwgFAWkGY2FsbGVyBQ5hbW91bnRNaW51c0ZlZQULc2VuZEFzc2V0SWQJAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwUPbW9uZXlCb3hBZGRyZXNzBRBnb3Zlcm5hbmNlUmV3YXJkBQtzZW5kQXNzZXRJZAUDbmlsCQDMCAIFDmFtb3VudE1pbnVzRmVlCQDMCAIFC3NlbmRBc3NldElkBQNuaWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQEIc2h1dGRvd24ACQELdmFsdWVPckVsc2UCCQELaXNBZG1pbkNhbGwBBQFpAwkBASEBBQZhY3RpdmUJAAIBCQCsAgICIkRBcHAgaXMgYWxyZWFkeSBzdXNwZW5kZWQuIENhdXNlOiAJAQt2YWx1ZU9yRWxzZQIJAJ0IAgUEdGhpcwUGa0NhdXNlAhp0aGUgY2F1c2Ugd2Fzbid0IHNwZWNpZmllZAkBB3N1c3BlbmQBAg9QYXVzZWQgYnkgYWRtaW4BaQEIYWN0aXZhdGUACQELdmFsdWVPckVsc2UCCQELaXNBZG1pbkNhbGwBBQFpAwUGYWN0aXZlCQENdGhyb3dJc0FjdGl2ZQAJAMwIAgkBDEJvb2xlYW5FbnRyeQIFB2tBY3RpdmUGCQDMCAIJAQtEZWxldGVFbnRyeQEFBmtDYXVzZQUDbmlsAWkBGXRha2VJbnRvQWNjb3VudEV4dHJhRnVuZHMACQELdmFsdWVPckVsc2UCCQEIaXNBY3RpdmUABA1hbW91bnRFbnJvbGxBCQBlAgUZYWNjb3VudEJhbGFuY2VXaXRoU3Rha2VkQQUIYmFsYW5jZUEEDWFtb3VudEVucm9sbEIJAGUCBRlhY2NvdW50QmFsYW5jZVdpdGhTdGFrZWRCBQhiYWxhbmNlQgQMaW52YXJpYW50TmV3CQENaW52YXJpYW50Q2FsYwIJAGQCBQhiYWxhbmNlQQUNYW1vdW50RW5yb2xsQQkAZAIFCGJhbGFuY2VCBQ1hbW91bnRFbnJvbGxCAwkBAiE9AggFAWkGY2FsbGVyBQ9tb25leUJveEFkZHJlc3MJAAIBAilPbmx5IHRoZSBtb25leSBib3ggY2FuIGNhbGwgdGhpcyBmdW5jdGlvbgMDCQBmAgAABQ1hbW91bnRFbnJvbGxBBgkAZgIAAAUNYW1vdW50RW5yb2xsQgkBB3N1c3BlbmQBAhZFbnJvbGwgYW1vdW50IG5lZ2F0aXZlAwMJAAACBQ1hbW91bnRFbnJvbGxBAAAJAAACBQ1hbW91bnRFbnJvbGxCAAAHCQACAQIQTm8gbW9uZXkgdG8gdGFrZQQGc3Rha2UxAwMJAQ9jb250YWluc0VsZW1lbnQCBQ1zdGFraW5nQXNzZXRzBQtzdHJBc3NldElkQQkAZgIFDWFtb3VudEVucm9sbEEAAAcJAPwHBAUEdGhpcwIMc3Rha2VVbnN0YWtlCQDMCAIGCQDMCAIFDWFtb3VudEVucm9sbEEJAMwIAgULc3RyQXNzZXRJZEEFA25pbAUDbmlsAAADCQAAAgUGc3Rha2UxBQZzdGFrZTEEBnN0YWtlMgMDCQEPY29udGFpbnNFbGVtZW50AgUNc3Rha2luZ0Fzc2V0cwULc3RyQXNzZXRJZEIJAGYCBQ1hbW91bnRFbnJvbGxCAAAHCQD8BwQFBHRoaXMCDHN0YWtlVW5zdGFrZQkAzAgCBgkAzAgCBQ1hbW91bnRFbnJvbGxCCQDMCAIFC3N0ckFzc2V0SWRCBQNuaWwFA25pbAAAAwkAAAIFBnN0YWtlMgUGc3Rha2UyCQDMCAIJAQxJbnRlZ2VyRW50cnkCBQprSW52YXJpYW50BQxpbnZhcmlhbnROZXcJAMwIAgkBDEludGVnZXJFbnRyeQIFCWtCYWxhbmNlQQkAZAIFCGJhbGFuY2VBBQ1hbW91bnRFbnJvbGxBCQDMCAIJAQxJbnRlZ2VyRW50cnkCBQlrQmFsYW5jZUIJAGQCBQhiYWxhbmNlQgUNYW1vdW50RW5yb2xsQgUDbmlsCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBGGtlZXBMaW1pdEZvckZpcnN0SGFydmVzdAEKc2hhcmVMaW1pdAkBC3ZhbHVlT3JFbHNlAgkBCGlzQWN0aXZlAAkBC3ZhbHVlT3JFbHNlAgkBC2lzQWRtaW5DYWxsAQUBaQkAzAgCCQEMSW50ZWdlckVudHJ5AgULa1NoYXJlTGltaXQFCnNoYXJlTGltaXQFA25pbAFpAQxzdGFrZVVuc3Rha2UDBXN0YWtlBmFtb3VudA1hc3NldElkU3RyaW5nAwkBAiE9AggFAWkGY2FsbGVyBQR0aGlzCQACAQItT25seSBjb250cmFjdCBpdHNlbGYgY2FuIGludm9rZSB0aGlzIGZ1bmN0aW9uBA0kdDAyOTYxNDI5NzE3CQERY2FsY1N0YWtpbmdQYXJhbXMDBQVzdGFrZQUGYW1vdW50CQDZBAEFDWFzc2V0SWRTdHJpbmcEBGNhbGwIBQ0kdDAyOTYxNDI5NzE3Al8xBARhZGRyCAUNJHQwMjk2MTQyOTcxNwJfMgQGcGFyYW1zCAUNJHQwMjk2MTQyOTcxNwJfMwQIcGF5bWVudHMIBQ0kdDAyOTYxNDI5NzE3Al80BANpbnYJAPwHBAUEYWRkcgUEY2FsbAUGcGFyYW1zBQhwYXltZW50cwMJAAACBQNpbnYFA2ludgUDbmlsCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAQJ0eAEGdmVyaWZ5AAQTbXVsdGlTaWduZWRCeUFkbWlucwQSYWRtaW5QdWJLZXkxU2lnbmVkAwkA9AMDCAUCdHgJYm9keUJ5dGVzCQCRAwIIBQJ0eAZwcm9vZnMAAAUMYWRtaW5QdWJLZXkxAAEAAAQSYWRtaW5QdWJLZXkyU2lnbmVkAwkA9AMDCAUCdHgJYm9keUJ5dGVzCQCRAwIIBQJ0eAZwcm9vZnMAAQUMYWRtaW5QdWJLZXkyAAEAAAQSYWRtaW5QdWJLZXkzU2lnbmVkAwkA9AMDCAUCdHgJYm9keUJ5dGVzCQCRAwIIBQJ0eAZwcm9vZnMAAgUMYWRtaW5QdWJLZXkzAAEAAAkAZwIJAGQCCQBkAgUSYWRtaW5QdWJLZXkxU2lnbmVkBRJhZG1pblB1YktleTJTaWduZWQFEmFkbWluUHViS2V5M1NpZ25lZAACBAckbWF0Y2gwBQJ0eAMJAAECBQckbWF0Y2gwAhdJbnZva2VTY3JpcHRUcmFuc2FjdGlvbgQDaW52BQckbWF0Y2gwBBNjYWxsVGFrZUludG9BY2NvdW50AwkAAAIIBQNpbnYEZEFwcAUEdGhpcwkAAAIIBQNpbnYIZnVuY3Rpb24CGXRha2VJbnRvQWNjb3VudEV4dHJhRnVuZHMHBA1zaWduZWRCeUFkbWluAwMDCQD0AwMIBQJ0eAlib2R5Qnl0ZXMJAJEDAggFAnR4BnByb29mcwAABQxhZG1pblB1YktleTEGCQD0AwMIBQJ0eAlib2R5Qnl0ZXMJAJEDAggFAnR4BnByb29mcwAABQxhZG1pblB1YktleTIGCQD0AwMIBQJ0eAlib2R5Qnl0ZXMJAJEDAggFAnR4BnByb29mcwAABQxhZG1pblB1YktleTMGCQD0AwMIBQJ0eAlib2R5Qnl0ZXMJAJEDAggFAnR4BnByb29mcwAABRFhZG1pblB1YktleUludm9rZQMDBRNjYWxsVGFrZUludG9BY2NvdW50BQ1zaWduZWRCeUFkbWluBwYFE211bHRpU2lnbmVkQnlBZG1pbnMFE211bHRpU2lnbmVkQnlBZG1pbnMV5lzM", "height": 2228898, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: CTvrV6qhmSxiMpCsBQPY4gXacNQpyhtuynMb88Ua5kLD Next: none Diff:
OldNewDifferences
1-{-# STDLIB_VERSION 5 #-}
1+{-# STDLIB_VERSION 6 #-}
22 {-# SCRIPT_TYPE ACCOUNT #-}
33 {-# CONTENT_TYPE DAPP #-}
44 let version = "2.0.0"
3535
3636 let kUserSwopInGov = "_SWOP_amount"
3737
38+let kFirstHarvest = "first_harvest"
39+
40+let kFirstHarvestHeight = "first_harvest_height"
41+
42+let kShareLimit = "share_limit_on_first_harvest"
43+
44+let kBasePeriod = "base_period"
45+
46+let kPeriodLength = "period_length"
47+
48+let kStartHeight = "start_height"
49+
3850 let kAdminPubKey1 = "admin_pub_1"
3951
4052 let kAdminPubKey2 = "admin_pub_2"
4658 let kMoneyBoxAddress = "money_box_address"
4759
4860 let kGovAddress = "governance_address"
61+
62+let kVotingAddress = "voting_address"
4963
5064 let oracle = Address(base58'3NBBWfzZtZtszaXbitTKnrB2xXwv26Bn7H9')
5165
7185
7286 let stakingUSDNAddress = Address(getBase58FromOracle(kUSDNAddress))
7387
88+let votingAddress = Address(getBase58FromOracle(kVotingAddress))
89+
7490 let USDN = base58'8UrfDVd5GreeUwm7uPk7eYz1eMv376kzR52C6sANPkwS'
7591
7692 let stakingAssets = [toBase58String(USDN)]
93+
94+let basePeriod = valueOrErrorMessage(getInteger(votingAddress, kBasePeriod), "Empty kBasePeriod")
95+
96+let startHeight = valueOrErrorMessage(getInteger(votingAddress, kStartHeight), "Empty kStartHeight")
97+
98+let periodLength = valueOrErrorMessage(getInteger(votingAddress, kPeriodLength), "Empty kPeriodLength")
99+
100+let firstHarvestEndPeriod = ((basePeriod + ((height - startHeight) / periodLength)) + 3)
77101
78102 let active = getBooleanValue(this, kActive)
79103
323347
324348 func calcStakingParams (stake,amount,assetId) = if (stake)
325349 then {
326- let $t093469412 = calcStakingFuncAndAddres(stake, assetId)
327- let call = $t093469412._1
328- let stakingAddr = $t093469412._2
350+ let $t01006410130 = calcStakingFuncAndAddres(stake, assetId)
351+ let call = $t01006410130._1
352+ let stakingAddr = $t01006410130._2
329353 $Tuple4(call, stakingAddr, nil, [AttachedPayment(assetId, amount)])
330354 }
331355 else {
332- let $t094989564 = calcStakingFuncAndAddres(stake, assetId)
333- let call = $t094989564._1
334- let stakingAddr = $t094989564._2
356+ let $t01021610282 = calcStakingFuncAndAddres(stake, assetId)
357+ let call = $t01021610282._1
358+ let stakingAddr = $t01021610282._2
335359 $Tuple4(call, stakingAddr, [amount, toBase58String(assetId)], nil)
336360 }
337361
363387
364388
365389 @Callable(i)
366-func init () = {
367- let $t01073610813 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
368- let pmtAmountA = $t01073610813._1
369- let pmtAssetIdA = $t01073610813._2
370- let $t01081810895 = $Tuple2(i.payments[1].amount, i.payments[1].assetId)
371- let pmtAmountB = $t01081810895._1
372- let pmtAssetIdB = $t01081810895._2
373- let $t01090010977 = getAssetInfo(pmtAssetIdA)
374- let pmtStrAssetIdA = $t01090010977._1
375- let pmtAssetNameA = $t01090010977._2
376- let pmtDecimalsA = $t01090010977._3
377- let $t01098211059 = getAssetInfo(pmtAssetIdB)
378- let pmtStrAssetIdB = $t01098211059._1
379- let pmtAssetNameB = $t01098211059._2
380- let pmtDecimalsB = $t01098211059._3
390+func init (firstHarvest) = {
391+ let $t01147511552 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
392+ let pmtAmountA = $t01147511552._1
393+ let pmtAssetIdA = $t01147511552._2
394+ let $t01155711634 = $Tuple2(i.payments[1].amount, i.payments[1].assetId)
395+ let pmtAmountB = $t01155711634._1
396+ let pmtAssetIdB = $t01155711634._2
397+ let $t01163911716 = getAssetInfo(pmtAssetIdA)
398+ let pmtStrAssetIdA = $t01163911716._1
399+ let pmtAssetNameA = $t01163911716._2
400+ let pmtDecimalsA = $t01163911716._3
401+ let $t01172111798 = getAssetInfo(pmtAssetIdB)
402+ let pmtStrAssetIdB = $t01172111798._1
403+ let pmtAssetNameB = $t01172111798._2
404+ let pmtDecimalsB = $t01172111798._3
381405 if (isDefined(getBoolean(this, kActive)))
382406 then throwIsActive()
383407 else if ((pmtAssetIdA == pmtAssetIdB))
399423 then invoke(this, "stakeUnstake", [true, pmtAmountB, pmtStrAssetIdB], nil)
400424 else 0
401425 if ((stake2 == stake2))
402- then [StringEntry(kVersion, version), BooleanEntry(kActive, true), StringEntry(kAssetIdA, pmtStrAssetIdA), StringEntry(kAssetIdB, pmtStrAssetIdB), IntegerEntry(kBalanceA, pmtAmountA), IntegerEntry(kBalanceB, pmtAmountB), IntegerEntry(kInvariant, invariantCalculated), IntegerEntry(kFee, getIntegerValue(oracle, "base_fee_flat")), shareIssue, StringEntry(kShareAssetId, toBase58String(shareIssueId)), IntegerEntry(kShareAssetSupply, shareInitialSupply), ScriptTransfer(i.caller, shareInitialSupply, shareIssueId)]
426+ then {
427+ let baseEntry = [StringEntry(kVersion, version), BooleanEntry(kActive, true), StringEntry(kAssetIdA, pmtStrAssetIdA), StringEntry(kAssetIdB, pmtStrAssetIdB), IntegerEntry(kBalanceA, pmtAmountA), IntegerEntry(kBalanceB, pmtAmountB), IntegerEntry(kInvariant, invariantCalculated), IntegerEntry(kFee, getIntegerValue(oracle, "base_fee_flat")), shareIssue, StringEntry(kShareAssetId, toBase58String(shareIssueId)), IntegerEntry(kShareAssetSupply, shareInitialSupply), ScriptTransfer(i.caller, shareInitialSupply, shareIssueId)]
428+ if (firstHarvest)
429+ then (baseEntry ++ [BooleanEntry(kFirstHarvest, firstHarvest), IntegerEntry(kFirstHarvestHeight, (startHeight + (firstHarvestEndPeriod * periodLength)))])
430+ else baseEntry
431+ }
403432 else throw("Strict value is not equal to itself.")
404433 }
405434 else throw("Strict value is not equal to itself.")
414443 let pmtAssetIdB = i.payments[1].assetId
415444 let ratioShareTokensInA = fraction(scale8, i.payments[0].amount, balanceA)
416445 let ratioShareTokensInB = fraction(scale8, i.payments[1].amount, balanceB)
417- let $t01370713784 = getAssetInfo(pmtAssetIdA)
418- let pmtStrAssetIdA = $t01370713784._1
419- let pmtAssetNameA = $t01370713784._2
420- let pmtDecimalsA = $t01370713784._3
421- let $t01378913906 = getAssetInfo(pmtAssetIdB)
422- let pmtStrAssetIdB = $t01378913906._1
423- let pmtAssetNameB = $t01378913906._2
424- let pmtDecimalsB = $t01378913906._3
425- let $t01391114415 = if ((ratioShareTokensInB > ratioShareTokensInA))
446+ let $t01474614823 = getAssetInfo(pmtAssetIdA)
447+ let pmtStrAssetIdA = $t01474614823._1
448+ let pmtAssetNameA = $t01474614823._2
449+ let pmtDecimalsA = $t01474614823._3
450+ let $t01482814945 = getAssetInfo(pmtAssetIdB)
451+ let pmtStrAssetIdB = $t01482814945._1
452+ let pmtAssetNameB = $t01482814945._2
453+ let pmtDecimalsB = $t01482814945._3
454+ let $t01495015454 = if ((ratioShareTokensInB > ratioShareTokensInA))
426455 then {
427456 let pmt = fraction(balanceB, ratioShareTokensInA, scale8, CEILING)
428457 $Tuple5(i.payments[0].amount, pmt, (i.payments[1].amount - pmt), pmtAssetIdB, ratioShareTokensInA)
431460 let pmt = fraction(balanceA, ratioShareTokensInB, scale8, CEILING)
432461 $Tuple5(pmt, i.payments[1].amount, (i.payments[0].amount - pmt), pmtAssetIdA, ratioShareTokensInB)
433462 }
434- let pmtAmountA = $t01391114415._1
435- let pmtAmountB = $t01391114415._2
436- let change = $t01391114415._3
437- let changeAssetId = $t01391114415._4
438- let shareTokenRatio = $t01391114415._5
463+ let pmtAmountA = $t01495015454._1
464+ let pmtAmountB = $t01495015454._2
465+ let change = $t01495015454._3
466+ let changeAssetId = $t01495015454._4
467+ let shareTokenRatio = $t01495015454._5
439468 let shareTokenToPayAmount = fraction(shareTokenRatio, shareAssetSupply, scale8)
440469 if ((size(i.payments) != 2))
441470 then throw("Two attached assets expected")
470499
471500 @Callable(i)
472501 func replenishWithOneToken (virtualSwapTokenPay,virtualSwapTokenGet) = valueOrElse(isActive(), {
473- let $t01614816223 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
474- let pmtAmount = $t01614816223._1
475- let pmtAssetId = $t01614816223._2
476- let $t01622816301 = getAssetInfo(pmtAssetId)
477- let pmtStrAssetId = $t01622816301._1
478- let pmtAssetName = $t01622816301._2
479- let pmtDecimals = $t01622816301._3
502+ let $t01718717262 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
503+ let pmtAmount = $t01718717262._1
504+ let pmtAssetId = $t01718717262._2
505+ let $t01726717340 = getAssetInfo(pmtAssetId)
506+ let pmtStrAssetId = $t01726717340._1
507+ let pmtAssetName = $t01726717340._2
508+ let pmtDecimals = $t01726717340._3
480509 let pmtMinThreshold = 5000000
481510 let thresholdValueForMinTolerance = 50000000
482511 let tolerance = if ((thresholdValueForMinTolerance > pmtAmount))
496525 else false)
497526 then throwAssets()
498527 else {
499- let $t01727917921 = if ((pmtAssetId == assetIdA))
528+ let $t01831818960 = if ((pmtAssetId == assetIdA))
500529 then $Tuple6((pmtAmount - virtualSwapTokenPay), virtualSwapTokenGet, (balanceA + virtualSwapTokenPay), (balanceB - virtualSwapTokenGet), (balanceA + pmtAmount), balanceB)
501530 else $Tuple6(virtualSwapTokenGet, (pmtAmount - virtualSwapTokenPay), (balanceA - virtualSwapTokenGet), (balanceB + virtualSwapTokenPay), balanceA, (balanceB + pmtAmount))
502- let virtualReplenishA = $t01727917921._1
503- let virtualReplenishB = $t01727917921._2
504- let balanceAfterSwapA = $t01727917921._3
505- let balanceAfterSwapB = $t01727917921._4
506- let newBalanceA = $t01727917921._5
507- let newBalanceB = $t01727917921._6
531+ let virtualReplenishA = $t01831818960._1
532+ let virtualReplenishB = $t01831818960._2
533+ let balanceAfterSwapA = $t01831818960._3
534+ let balanceAfterSwapB = $t01831818960._4
535+ let newBalanceA = $t01831818960._5
536+ let newBalanceB = $t01831818960._6
508537 let invariantNew = invariantCalc(balanceAfterSwapA, balanceAfterSwapB)
509538 let ratioVirtualBalanceToVirtualReplenish = (fraction(scale16, balanceAfterSwapA, balanceAfterSwapB) / fraction(scale8, virtualReplenishA, virtualReplenishB))
510539 let dAppThresholdAmount = fraction((newBalanceA + newBalanceB), dAppThreshold, (2 * dAppThresholdScale2))
528557 let shareTokenGovernanceReward = fraction(shareTokenToPayAmount, (feeGovernance / 2), feeScale6)
529558 let governanceRewardTokenA = fraction(shareTokenGovernanceReward, balanceA, shareAssetSupply)
530559 let governanceRewardTokenB = fraction(shareTokenGovernanceReward, balanceB, shareAssetSupply)
531- let $t01990820203 = if ((pmtStrAssetId == strAssetIdA))
560+ let $t02094721242 = if ((pmtStrAssetId == strAssetIdA))
532561 then $Tuple3((pmtAmount - governanceRewardTokenA), governanceRewardTokenB, strAssetIdB)
533562 else $Tuple3((pmtAmount - governanceRewardTokenB), governanceRewardTokenA, strAssetIdA)
534- let stakeAmount = $t01990820203._1
535- let unstakeAmount = $t01990820203._2
536- let unstakeAsset = $t01990820203._3
563+ let stakeAmount = $t02094721242._1
564+ let unstakeAmount = $t02094721242._2
565+ let unstakeAsset = $t02094721242._3
537566 let stake1 = if (containsElement(stakingAssets, pmtStrAssetId))
538567 then invoke(this, "stakeUnstake", [true, stakeAmount, pmtStrAssetId], nil)
539568 else 0
555584
556585 @Callable(i)
557586 func withdraw () = valueOrElse(isActive(), {
558- let $t02149021565 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
559- let pmtAmount = $t02149021565._1
560- let pmtAssetId = $t02149021565._2
587+ let $t02252922604 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
588+ let pmtAmount = $t02252922604._1
589+ let pmtAssetId = $t02252922604._2
561590 let amountToPayA = fraction(pmtAmount, balanceA, shareAssetSupply)
562591 let amountToPayB = fraction(pmtAmount, balanceB, shareAssetSupply)
563592 let invariantCalculated = invariantCalc((balanceA - amountToPayA), (balanceB - amountToPayB))
588617
589618 @Callable(i)
590619 func exchange (estimatedAmountToReceive,minAmountToReceive) = valueOrElse(isActive(), {
591- let $t02311623191 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
592- let pmtAmount = $t02311623191._1
593- let pmtAssetId = $t02311623191._2
620+ let $t02415524230 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
621+ let pmtAmount = $t02415524230._1
622+ let pmtAssetId = $t02415524230._2
594623 if ((0 >= estimatedAmountToReceive))
595624 then throw(("Estimated amount must be positive. Actual: " + toString(estimatedAmountToReceive)))
596625 else if ((minAmountToReceive > estimatedAmountToReceive))
617646 let feeDiscount = calculateFeeDiscount(i.originCaller)
618647 let governanceReward = fraction(amount, fraction(feeGovernance, feeDiscount, feeScale6, CEILING), feeScale6)
619648 let amountMinusFee = fraction(amount, (feeScale6 - fraction(fee, feeDiscount, feeScale6, CEILING)), feeScale6)
620- let $t02464424906 = if ((pmtAssetId == assetIdA))
649+ let $t02568325945 = if ((pmtAssetId == assetIdA))
621650 then $Tuple2((balanceA + pmtAmount), ((balanceB - amountMinusFee) - governanceReward))
622651 else $Tuple2(((balanceA - amountMinusFee) - governanceReward), (balanceB + pmtAmount))
623- let newBalanceA = $t02464424906._1
624- let newBalanceB = $t02464424906._2
652+ let newBalanceA = $t02568325945._1
653+ let newBalanceB = $t02568325945._2
625654 let dAppThresholdAmount = fraction((newBalanceA + newBalanceB), dAppThreshold, (2 * dAppThresholdScale2))
626655 if (if ((dAppThresholdAmount > newBalanceA))
627656 then true
628657 else (dAppThresholdAmount > newBalanceB))
629658 then throwThreshold(dAppThresholdAmount, newBalanceA, newBalanceB)
630659 else {
631- let $t02520525278 = getAssetInfo(pmtAssetId)
632- let pmtStrAssetId = $t02520525278._1
633- let pmtAssetName = $t02520525278._2
634- let pmtDecimals = $t02520525278._3
635- let $t02529125368 = getAssetInfo(sendAssetId)
636- let sendStrAssetId = $t02529125368._1
637- let sendAssetName = $t02529125368._2
638- let sendDecimals = $t02529125368._3
660+ let $t02624426317 = getAssetInfo(pmtAssetId)
661+ let pmtStrAssetId = $t02624426317._1
662+ let pmtAssetName = $t02624426317._2
663+ let pmtDecimals = $t02624426317._3
664+ let $t02633026407 = getAssetInfo(sendAssetId)
665+ let sendStrAssetId = $t02633026407._1
666+ let sendAssetName = $t02633026407._2
667+ let sendDecimals = $t02633026407._3
639668 let stake1 = if (containsElement(stakingAssets, pmtStrAssetId))
640669 then invoke(this, "stakeUnstake", [true, pmtAmount, pmtStrAssetId], nil)
641670 else 0
645674 then invoke(this, "stakeUnstake", [false, (amountMinusFee + governanceReward), sendStrAssetId], nil)
646675 else 0
647676 if ((stake2 == stake2))
648- then $Tuple2([IntegerEntry(kBalanceA, newBalanceA), IntegerEntry(kBalanceB, newBalanceB), IntegerEntry(kInvariant, invariantCalc(newBalanceA, newBalanceB)), ScriptTransfer(i.caller, amountMinusFee, sendAssetId), ScriptTransfer(moneyBoxAddress, governanceReward, sendAssetId)], $Tuple2(amountMinusFee, sendAssetId))
677+ then $Tuple2([IntegerEntry(kBalanceA, newBalanceA), IntegerEntry(kBalanceB, newBalanceB), IntegerEntry(kInvariant, invariantCalc(newBalanceA, newBalanceB)), ScriptTransfer(i.caller, amountMinusFee, sendAssetId), ScriptTransfer(moneyBoxAddress, governanceReward, sendAssetId)], [amountMinusFee, sendAssetId])
649678 else throw("Strict value is not equal to itself.")
650679 }
651680 else throw("Strict value is not equal to itself.")
708737
709738
710739 @Callable(i)
740+func keepLimitForFirstHarvest (shareLimit) = valueOrElse(isActive(), valueOrElse(isAdminCall(i), [IntegerEntry(kShareLimit, shareLimit)]))
741+
742+
743+
744+@Callable(i)
711745 func stakeUnstake (stake,amount,assetIdString) = if ((i.caller != this))
712746 then throw("Only contract itself can invoke this function")
713747 else {
714- let $t02837228475 = calcStakingParams(stake, amount, fromBase58String(assetIdString))
715- let call = $t02837228475._1
716- let addr = $t02837228475._2
717- let params = $t02837228475._3
718- let payments = $t02837228475._4
748+ let $t02961429717 = calcStakingParams(stake, amount, fromBase58String(assetIdString))
749+ let call = $t02961429717._1
750+ let addr = $t02961429717._2
751+ let params = $t02961429717._3
752+ let payments = $t02961429717._4
719753 let inv = invoke(addr, call, params, payments)
720754 if ((inv == inv))
721755 then nil
722756 else throw("Strict value is not equal to itself.")
723757 }
724-
725-
726-
727-@Callable(i)
728-func toBigIntInvariant () = valueOrElse(isAdminCall(i), [IntegerEntry(kInvariant, invariantCalc(balanceA, balanceB))])
729758
730759
731760 @Verifier(tx)
Full:
OldNewDifferences
1-{-# STDLIB_VERSION 5 #-}
1+{-# STDLIB_VERSION 6 #-}
22 {-# SCRIPT_TYPE ACCOUNT #-}
33 {-# CONTENT_TYPE DAPP #-}
44 let version = "2.0.0"
55
66 let kVersion = "version"
77
88 let kActive = "active"
99
1010 let kAssetIdA = "A_asset_id"
1111
1212 let kAssetIdB = "B_asset_id"
1313
1414 let kBalanceA = "A_asset_balance"
1515
1616 let kBalanceB = "B_asset_balance"
1717
1818 let kShareAssetId = "share_asset_id"
1919
2020 let kShareAssetSupply = "share_asset_supply"
2121
2222 let kFee = "commission"
2323
2424 let kInvariant = "invariant"
2525
2626 let kCause = "shutdown_cause"
2727
2828 let kUSDNAddress = "staking_usdnnsbt_address"
2929
3030 let kEURNAddress = "staking_eurn_address"
3131
3232 let kDiscounts = "discounts"
3333
3434 let kDiscountValues = "discount_values"
3535
3636 let kUserSwopInGov = "_SWOP_amount"
3737
38+let kFirstHarvest = "first_harvest"
39+
40+let kFirstHarvestHeight = "first_harvest_height"
41+
42+let kShareLimit = "share_limit_on_first_harvest"
43+
44+let kBasePeriod = "base_period"
45+
46+let kPeriodLength = "period_length"
47+
48+let kStartHeight = "start_height"
49+
3850 let kAdminPubKey1 = "admin_pub_1"
3951
4052 let kAdminPubKey2 = "admin_pub_2"
4153
4254 let kAdminPubKey3 = "admin_pub_3"
4355
4456 let kAdminInvokePubKey = "admin_invoke_pub"
4557
4658 let kMoneyBoxAddress = "money_box_address"
4759
4860 let kGovAddress = "governance_address"
61+
62+let kVotingAddress = "voting_address"
4963
5064 let oracle = Address(base58'3NBBWfzZtZtszaXbitTKnrB2xXwv26Bn7H9')
5165
5266 func getBase58FromOracle (key) = match getString(oracle, key) {
5367 case string: String =>
5468 fromBase58String(string)
5569 case nothing =>
5670 throw((key + "is empty"))
5771 }
5872
5973
6074 let adminPubKey1 = getBase58FromOracle(kAdminPubKey1)
6175
6276 let adminPubKey2 = getBase58FromOracle(kAdminPubKey2)
6377
6478 let adminPubKey3 = getBase58FromOracle(kAdminPubKey3)
6579
6680 let adminPubKeyInvoke = getBase58FromOracle(kAdminInvokePubKey)
6781
6882 let moneyBoxAddress = Address(getBase58FromOracle(kMoneyBoxAddress))
6983
7084 let govAddress = Address(getBase58FromOracle(kGovAddress))
7185
7286 let stakingUSDNAddress = Address(getBase58FromOracle(kUSDNAddress))
7387
88+let votingAddress = Address(getBase58FromOracle(kVotingAddress))
89+
7490 let USDN = base58'8UrfDVd5GreeUwm7uPk7eYz1eMv376kzR52C6sANPkwS'
7591
7692 let stakingAssets = [toBase58String(USDN)]
93+
94+let basePeriod = valueOrErrorMessage(getInteger(votingAddress, kBasePeriod), "Empty kBasePeriod")
95+
96+let startHeight = valueOrErrorMessage(getInteger(votingAddress, kStartHeight), "Empty kStartHeight")
97+
98+let periodLength = valueOrErrorMessage(getInteger(votingAddress, kPeriodLength), "Empty kPeriodLength")
99+
100+let firstHarvestEndPeriod = ((basePeriod + ((height - startHeight) / periodLength)) + 3)
77101
78102 let active = getBooleanValue(this, kActive)
79103
80104 let strAssetIdA = getStringValue(this, kAssetIdA)
81105
82106 let strAssetIdB = getStringValue(this, kAssetIdB)
83107
84108 let assetIdA = if ((strAssetIdA == "WAVES"))
85109 then unit
86110 else fromBase58String(strAssetIdA)
87111
88112 let assetIdB = if ((strAssetIdB == "WAVES"))
89113 then unit
90114 else fromBase58String(strAssetIdB)
91115
92116 let assetNameA = match assetIdA {
93117 case id: ByteVector =>
94118 value(assetInfo(id)).name
95119 case waves: Unit =>
96120 "WAVES"
97121 case _ =>
98122 throw("Match error")
99123 }
100124
101125 let assetNameB = match assetIdB {
102126 case id: ByteVector =>
103127 value(assetInfo(id)).name
104128 case waves: Unit =>
105129 "WAVES"
106130 case _ =>
107131 throw("Match error")
108132 }
109133
110134 let balanceA = getIntegerValue(this, kBalanceA)
111135
112136 let balanceB = getIntegerValue(this, kBalanceB)
113137
114138 let shareAssetId = fromBase58String(getStringValue(this, kShareAssetId))
115139
116140 let shareAssetSupply = getIntegerValue(this, kShareAssetSupply)
117141
118142 let invariant = getIntegerValue(this, kInvariant)
119143
120144 let fee = getIntegerValue(this, kFee)
121145
122146 let feeGovernance = fraction(fee, 40, 100)
123147
124148 let feeScale6 = 1000000
125149
126150 let scale3 = 1000
127151
128152 let scale8 = 100000000
129153
130154 let scale16 = 10000000000000000
131155
132156 let slippageScale3 = 1000
133157
134158 let digits8 = 8
135159
136160 let dAppThreshold = 50
137161
138162 let dAppThresholdScale2 = 100
139163
140164 let exchangeRatioLimitMin = 90000000
141165
142166 let exchangeRatioLimitMax = 110000000
143167
144168 let alpha = 50
145169
146170 let alphaDigits = 2
147171
148172 let beta = 4600000000000000
149173
150174 func accountBalance (assetId) = match assetId {
151175 case id: ByteVector =>
152176 assetBalance(this, id)
153177 case waves: Unit =>
154178 wavesBalance(this).available
155179 case _ =>
156180 throw("Match error")
157181 }
158182
159183
160184 func stakedAmount (assetId) = {
161185 let stakedAmountCalculated = match assetId {
162186 case aId: ByteVector =>
163187 if ((aId == USDN))
164188 then getInteger(stakingUSDNAddress, ((("rpd_balance_" + toBase58String(aId)) + "_") + toString(this)))
165189 else 0
166190 case _: Unit =>
167191 0
168192 case _ =>
169193 throw("Match error")
170194 }
171195 match stakedAmountCalculated {
172196 case i: Int =>
173197 i
174198 case _ =>
175199 0
176200 }
177201 }
178202
179203
180204 let stakedAmountA = stakedAmount(assetIdA)
181205
182206 let stakedAmountB = stakedAmount(assetIdB)
183207
184208 let availableBalanceA = (balanceA - stakedAmountA)
185209
186210 let availableBalanceB = (balanceB - stakedAmountB)
187211
188212 let accountBalanceWithStakedA = (accountBalance(assetIdA) + stakedAmountA)
189213
190214 let accountBalanceWithStakedB = (accountBalance(assetIdB) + stakedAmountB)
191215
192216 let hasEnoughBalance = if ((accountBalanceWithStakedA >= balanceA))
193217 then (accountBalanceWithStakedB >= balanceB)
194218 else false
195219
196220 func skewness (x,y) = ((fraction(scale16, x, y) + fraction(scale16, y, x)) / 2)
197221
198222
199223 func invariantCalc (x,y) = {
200224 let sk = skewness(x, y)
201225 (fraction((x + y), scale16, pow(sk, digits8, alpha, alphaDigits, digits8, CEILING)) + (2 * fraction(toInt(pow(fraction(toBigInt(x), toBigInt(y), toBigInt(scale8)), 0, toBigInt(5), 1, (digits8 / 2), DOWN)), pow((sk - beta), digits8, alpha, alphaDigits, digits8, DOWN), scale8)))
202226 }
203227
204228
205229 func calculateSendAmount (amountToSendEstimated,minTokenReceiveAmount,tokenReceiveAmount,tokenId) = {
206230 let worstAllowedNewInvariantRatio = (scale16 - ((scale16 * 1) / 10000000))
207231 let deltaBetweenMaxAndMinSendValue = (amountToSendEstimated - minTokenReceiveAmount)
208232 let x = (balanceA + tokenReceiveAmount)
209233 let y = (balanceB + tokenReceiveAmount)
210234 func getStepAmount (acc,step) = if ((acc._1 == -1))
211235 then {
212236 let amountToSend = (amountToSendEstimated - (((step * deltaBetweenMaxAndMinSendValue) / 3) / scale3))
213237 let stepInvariant = if ((tokenId == assetIdA))
214238 then invariantCalc(x, (balanceB - amountToSend))
215239 else invariantCalc((balanceA - amountToSend), y)
216240 if ((stepInvariant > invariant))
217241 then $Tuple2(amountToSend, stepInvariant)
218242 else $Tuple2(-1, 0)
219243 }
220244 else acc
221245
222246 let amountToSendMin = getStepAmount($Tuple2(-1, 0), 3000)
223247 if ((0 > amountToSendMin._1))
224248 then throw("Price is worse than minReceived")
225249 else {
226250 let invEstimated = if ((tokenId == assetIdA))
227251 then invariantCalc(x, (balanceB - amountToSendEstimated))
228252 else if ((tokenId == assetIdB))
229253 then invariantCalc((balanceA - amountToSendEstimated), y)
230254 else throw("Wrong asset in payment")
231255 if ((invariant > invEstimated))
232256 then if ((worstAllowedNewInvariantRatio >= fraction(scale16, invariant, invEstimated)))
233257 then throw("The requested price is too not profitable for user")
234258 else {
235259 let a = {
236260 let $l = [25, 200, 500]
237261 let $s = size($l)
238262 let $acc0 = $Tuple2(-1, 0)
239263 func $f0_1 ($a,$i) = if (($i >= $s))
240264 then $a
241265 else getStepAmount($a, $l[$i])
242266
243267 func $f0_2 ($a,$i) = if (($i >= $s))
244268 then $a
245269 else throw("List size exceeds 3")
246270
247271 $f0_2($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3)
248272 }
249273 if ((0 > a._1))
250274 then amountToSendMin._1
251275 else a._1
252276 }
253277 else {
254278 let a = {
255279 let $l = [-500, -200, -25]
256280 let $s = size($l)
257281 let $acc0 = $Tuple2(-1, 0)
258282 func $f0_1 ($a,$i) = if (($i >= $s))
259283 then $a
260284 else getStepAmount($a, $l[$i])
261285
262286 func $f0_2 ($a,$i) = if (($i >= $s))
263287 then $a
264288 else throw("List size exceeds 3")
265289
266290 $f0_2($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3)
267291 }
268292 let tupleSendBetter = if ((0 > a._1))
269293 then $Tuple2(amountToSendEstimated, invEstimated)
270294 else a
271295 if ((worstAllowedNewInvariantRatio >= fraction(scale16, invariant, tupleSendBetter._2)))
272296 then throw("The requested price is too not profitable for user")
273297 else tupleSendBetter._1
274298 }
275299 }
276300 }
277301
278302
279303 func getAssetInfo (assetId) = match assetId {
280304 case id: ByteVector =>
281305 let stringId = toBase58String(id)
282306 let info = valueOrErrorMessage(assetInfo(id), (("Asset " + stringId) + " doesn't exist"))
283307 $Tuple3(stringId, info.name, info.decimals)
284308 case waves: Unit =>
285309 $Tuple3("WAVES", "WAVES", 8)
286310 case _ =>
287311 throw("Match error")
288312 }
289313
290314
291315 func suspend (cause) = [BooleanEntry(kActive, false), StringEntry(kCause, cause)]
292316
293317
294318 func throwIsActive () = throw("DApp is already active")
295319
296320
297321 func isActive () = if (active)
298322 then unit
299323 else throw("DApp is inactive at this moment")
300324
301325
302326 func isAdminCall (i) = if (containsElement([adminPubKey1, adminPubKey2, adminPubKey3], i.callerPublicKey))
303327 then unit
304328 else throw("Only admin can call this function")
305329
306330
307331 func throwAssets () = throw(((("Incorrect assets attached. Expected: " + strAssetIdA) + " and ") + strAssetIdB))
308332
309333
310334 func throwOnePayment () = throw("One attached payment expected")
311335
312336
313337 func throwThreshold (threshold,amountA,amountB) = throw(((((((((("New balance in assets of the DApp is less than threshold " + toString(threshold)) + ": ") + toString(amountA)) + " ") + assetNameA) + ", ") + toString(amountB)) + " ") + assetNameB))
314338
315339
316340 func suspendSuspicious () = suspend(((((((((((((((("Suspicious state. Actual balances: " + toString(balanceA)) + " ") + assetNameA) + ", ") + toString(balanceB)) + " ") + assetNameB) + ". State: ") + toString(accountBalance(assetIdA))) + " ") + assetNameA) + ", ") + toString(accountBalance(assetIdB))) + " ") + assetNameB))
317341
318342
319343 func calcStakingFuncAndAddres (stake,assetId) = if (stake)
320344 then $Tuple2("lockNeutrino", stakingUSDNAddress)
321345 else $Tuple2("unlockNeutrino", stakingUSDNAddress)
322346
323347
324348 func calcStakingParams (stake,amount,assetId) = if (stake)
325349 then {
326- let $t093469412 = calcStakingFuncAndAddres(stake, assetId)
327- let call = $t093469412._1
328- let stakingAddr = $t093469412._2
350+ let $t01006410130 = calcStakingFuncAndAddres(stake, assetId)
351+ let call = $t01006410130._1
352+ let stakingAddr = $t01006410130._2
329353 $Tuple4(call, stakingAddr, nil, [AttachedPayment(assetId, amount)])
330354 }
331355 else {
332- let $t094989564 = calcStakingFuncAndAddres(stake, assetId)
333- let call = $t094989564._1
334- let stakingAddr = $t094989564._2
356+ let $t01021610282 = calcStakingFuncAndAddres(stake, assetId)
357+ let call = $t01021610282._1
358+ let stakingAddr = $t01021610282._2
335359 $Tuple4(call, stakingAddr, [amount, toBase58String(assetId)], nil)
336360 }
337361
338362
339363 func calculateFeeDiscount (userAddr) = {
340364 let swopAmount = valueOrElse(getInteger(govAddress, (toString(userAddr) + kUserSwopInGov)), 0)
341365 let discountValues = split(getStringValue(oracle, kDiscountValues), ",")
342366 let discounts = split(getStringValue(oracle, kDiscounts), ",")
343367 if (if ((swopAmount >= parseIntValue(discountValues[0])))
344368 then (parseIntValue(discountValues[1]) > swopAmount)
345369 else false)
346370 then (feeScale6 - parseIntValue(discounts[0]))
347371 else if (if ((swopAmount >= parseIntValue(discountValues[1])))
348372 then (parseIntValue(discountValues[2]) > swopAmount)
349373 else false)
350374 then (feeScale6 - parseIntValue(discounts[1]))
351375 else if (if ((swopAmount >= parseIntValue(discountValues[2])))
352376 then (parseIntValue(discountValues[3]) > swopAmount)
353377 else false)
354378 then (feeScale6 - parseIntValue(discounts[2]))
355379 else if (if ((swopAmount >= parseIntValue(discountValues[3])))
356380 then (parseIntValue(discountValues[4]) > swopAmount)
357381 else false)
358382 then (feeScale6 - parseIntValue(discounts[3]))
359383 else if ((swopAmount >= parseIntValue(discountValues[4])))
360384 then (feeScale6 - parseIntValue(discounts[4]))
361385 else feeScale6
362386 }
363387
364388
365389 @Callable(i)
366-func init () = {
367- let $t01073610813 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
368- let pmtAmountA = $t01073610813._1
369- let pmtAssetIdA = $t01073610813._2
370- let $t01081810895 = $Tuple2(i.payments[1].amount, i.payments[1].assetId)
371- let pmtAmountB = $t01081810895._1
372- let pmtAssetIdB = $t01081810895._2
373- let $t01090010977 = getAssetInfo(pmtAssetIdA)
374- let pmtStrAssetIdA = $t01090010977._1
375- let pmtAssetNameA = $t01090010977._2
376- let pmtDecimalsA = $t01090010977._3
377- let $t01098211059 = getAssetInfo(pmtAssetIdB)
378- let pmtStrAssetIdB = $t01098211059._1
379- let pmtAssetNameB = $t01098211059._2
380- let pmtDecimalsB = $t01098211059._3
390+func init (firstHarvest) = {
391+ let $t01147511552 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
392+ let pmtAmountA = $t01147511552._1
393+ let pmtAssetIdA = $t01147511552._2
394+ let $t01155711634 = $Tuple2(i.payments[1].amount, i.payments[1].assetId)
395+ let pmtAmountB = $t01155711634._1
396+ let pmtAssetIdB = $t01155711634._2
397+ let $t01163911716 = getAssetInfo(pmtAssetIdA)
398+ let pmtStrAssetIdA = $t01163911716._1
399+ let pmtAssetNameA = $t01163911716._2
400+ let pmtDecimalsA = $t01163911716._3
401+ let $t01172111798 = getAssetInfo(pmtAssetIdB)
402+ let pmtStrAssetIdB = $t01172111798._1
403+ let pmtAssetNameB = $t01172111798._2
404+ let pmtDecimalsB = $t01172111798._3
381405 if (isDefined(getBoolean(this, kActive)))
382406 then throwIsActive()
383407 else if ((pmtAssetIdA == pmtAssetIdB))
384408 then throw("Assets must be different")
385409 else {
386410 let shareName = ((("s" + take(pmtAssetNameA, 7)) + "_") + take(pmtAssetNameB, 7))
387411 let shareDescription = ((((("ShareToken of SwopFi protocol for " + pmtAssetNameA) + " and ") + pmtAssetNameB) + " at address ") + toString(this))
388412 let shareDecimals = ((pmtDecimalsA + pmtDecimalsB) / 2)
389413 let shareInitialSupply = fraction(pow(pmtAmountA, pmtDecimalsA, 5, 1, pmtDecimalsA, DOWN), pow(pmtAmountB, pmtDecimalsB, 5, 1, pmtDecimalsB, DOWN), pow(10, 0, shareDecimals, 0, 0, DOWN))
390414 let shareIssue = Issue(shareName, shareDescription, shareInitialSupply, shareDecimals, true)
391415 let shareIssueId = calculateAssetId(shareIssue)
392416 let invariantCalculated = invariantCalc(pmtAmountA, pmtAmountB)
393417 let stake1 = if (containsElement(stakingAssets, pmtStrAssetIdA))
394418 then invoke(this, "stakeUnstake", [true, pmtAmountA, pmtStrAssetIdA], nil)
395419 else 0
396420 if ((stake1 == stake1))
397421 then {
398422 let stake2 = if (containsElement(stakingAssets, pmtStrAssetIdB))
399423 then invoke(this, "stakeUnstake", [true, pmtAmountB, pmtStrAssetIdB], nil)
400424 else 0
401425 if ((stake2 == stake2))
402- then [StringEntry(kVersion, version), BooleanEntry(kActive, true), StringEntry(kAssetIdA, pmtStrAssetIdA), StringEntry(kAssetIdB, pmtStrAssetIdB), IntegerEntry(kBalanceA, pmtAmountA), IntegerEntry(kBalanceB, pmtAmountB), IntegerEntry(kInvariant, invariantCalculated), IntegerEntry(kFee, getIntegerValue(oracle, "base_fee_flat")), shareIssue, StringEntry(kShareAssetId, toBase58String(shareIssueId)), IntegerEntry(kShareAssetSupply, shareInitialSupply), ScriptTransfer(i.caller, shareInitialSupply, shareIssueId)]
426+ then {
427+ let baseEntry = [StringEntry(kVersion, version), BooleanEntry(kActive, true), StringEntry(kAssetIdA, pmtStrAssetIdA), StringEntry(kAssetIdB, pmtStrAssetIdB), IntegerEntry(kBalanceA, pmtAmountA), IntegerEntry(kBalanceB, pmtAmountB), IntegerEntry(kInvariant, invariantCalculated), IntegerEntry(kFee, getIntegerValue(oracle, "base_fee_flat")), shareIssue, StringEntry(kShareAssetId, toBase58String(shareIssueId)), IntegerEntry(kShareAssetSupply, shareInitialSupply), ScriptTransfer(i.caller, shareInitialSupply, shareIssueId)]
428+ if (firstHarvest)
429+ then (baseEntry ++ [BooleanEntry(kFirstHarvest, firstHarvest), IntegerEntry(kFirstHarvestHeight, (startHeight + (firstHarvestEndPeriod * periodLength)))])
430+ else baseEntry
431+ }
403432 else throw("Strict value is not equal to itself.")
404433 }
405434 else throw("Strict value is not equal to itself.")
406435 }
407436 }
408437
409438
410439
411440 @Callable(i)
412441 func replenishWithTwoTokens () = valueOrElse(isActive(), {
413442 let pmtAssetIdA = i.payments[0].assetId
414443 let pmtAssetIdB = i.payments[1].assetId
415444 let ratioShareTokensInA = fraction(scale8, i.payments[0].amount, balanceA)
416445 let ratioShareTokensInB = fraction(scale8, i.payments[1].amount, balanceB)
417- let $t01370713784 = getAssetInfo(pmtAssetIdA)
418- let pmtStrAssetIdA = $t01370713784._1
419- let pmtAssetNameA = $t01370713784._2
420- let pmtDecimalsA = $t01370713784._3
421- let $t01378913906 = getAssetInfo(pmtAssetIdB)
422- let pmtStrAssetIdB = $t01378913906._1
423- let pmtAssetNameB = $t01378913906._2
424- let pmtDecimalsB = $t01378913906._3
425- let $t01391114415 = if ((ratioShareTokensInB > ratioShareTokensInA))
446+ let $t01474614823 = getAssetInfo(pmtAssetIdA)
447+ let pmtStrAssetIdA = $t01474614823._1
448+ let pmtAssetNameA = $t01474614823._2
449+ let pmtDecimalsA = $t01474614823._3
450+ let $t01482814945 = getAssetInfo(pmtAssetIdB)
451+ let pmtStrAssetIdB = $t01482814945._1
452+ let pmtAssetNameB = $t01482814945._2
453+ let pmtDecimalsB = $t01482814945._3
454+ let $t01495015454 = if ((ratioShareTokensInB > ratioShareTokensInA))
426455 then {
427456 let pmt = fraction(balanceB, ratioShareTokensInA, scale8, CEILING)
428457 $Tuple5(i.payments[0].amount, pmt, (i.payments[1].amount - pmt), pmtAssetIdB, ratioShareTokensInA)
429458 }
430459 else {
431460 let pmt = fraction(balanceA, ratioShareTokensInB, scale8, CEILING)
432461 $Tuple5(pmt, i.payments[1].amount, (i.payments[0].amount - pmt), pmtAssetIdA, ratioShareTokensInB)
433462 }
434- let pmtAmountA = $t01391114415._1
435- let pmtAmountB = $t01391114415._2
436- let change = $t01391114415._3
437- let changeAssetId = $t01391114415._4
438- let shareTokenRatio = $t01391114415._5
463+ let pmtAmountA = $t01495015454._1
464+ let pmtAmountB = $t01495015454._2
465+ let change = $t01495015454._3
466+ let changeAssetId = $t01495015454._4
467+ let shareTokenRatio = $t01495015454._5
439468 let shareTokenToPayAmount = fraction(shareTokenRatio, shareAssetSupply, scale8)
440469 if ((size(i.payments) != 2))
441470 then throw("Two attached assets expected")
442471 else if (if ((pmtAssetIdA != assetIdA))
443472 then true
444473 else (pmtAssetIdB != assetIdB))
445474 then throwAssets()
446475 else if ((shareTokenToPayAmount == 0))
447476 then throw("Too small amount to replenish")
448477 else if ((0 > change))
449478 then throw("Change < 0")
450479 else if (!(hasEnoughBalance))
451480 then ([ScriptTransfer(i.caller, pmtAmountA, pmtAssetIdA), ScriptTransfer(i.caller, pmtAmountB, pmtAssetIdB)] ++ suspendSuspicious())
452481 else {
453482 let stake1 = if (containsElement(stakingAssets, pmtStrAssetIdA))
454483 then invoke(this, "stakeUnstake", [true, pmtAmountA, pmtStrAssetIdA], nil)
455484 else 0
456485 if ((stake1 == stake1))
457486 then {
458487 let stake2 = if (containsElement(stakingAssets, pmtStrAssetIdB))
459488 then invoke(this, "stakeUnstake", [true, pmtAmountB, pmtStrAssetIdB], nil)
460489 else 0
461490 if ((stake2 == stake2))
462491 then [IntegerEntry(kBalanceA, (balanceA + pmtAmountA)), IntegerEntry(kBalanceB, (balanceB + pmtAmountB)), IntegerEntry(kShareAssetSupply, (shareAssetSupply + shareTokenToPayAmount)), IntegerEntry(kInvariant, invariantCalc((balanceA + pmtAmountA), (balanceB + pmtAmountB))), Reissue(shareAssetId, shareTokenToPayAmount, true), ScriptTransfer(i.caller, shareTokenToPayAmount, shareAssetId), ScriptTransfer(i.caller, change, changeAssetId)]
463492 else throw("Strict value is not equal to itself.")
464493 }
465494 else throw("Strict value is not equal to itself.")
466495 }
467496 })
468497
469498
470499
471500 @Callable(i)
472501 func replenishWithOneToken (virtualSwapTokenPay,virtualSwapTokenGet) = valueOrElse(isActive(), {
473- let $t01614816223 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
474- let pmtAmount = $t01614816223._1
475- let pmtAssetId = $t01614816223._2
476- let $t01622816301 = getAssetInfo(pmtAssetId)
477- let pmtStrAssetId = $t01622816301._1
478- let pmtAssetName = $t01622816301._2
479- let pmtDecimals = $t01622816301._3
502+ let $t01718717262 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
503+ let pmtAmount = $t01718717262._1
504+ let pmtAssetId = $t01718717262._2
505+ let $t01726717340 = getAssetInfo(pmtAssetId)
506+ let pmtStrAssetId = $t01726717340._1
507+ let pmtAssetName = $t01726717340._2
508+ let pmtDecimals = $t01726717340._3
480509 let pmtMinThreshold = 5000000
481510 let thresholdValueForMinTolerance = 50000000
482511 let tolerance = if ((thresholdValueForMinTolerance > pmtAmount))
483512 then 100000
484513 else 1
485514 let slippageValueMinForReplenish = (scale8 - ((scale8 * tolerance) / 10000000))
486515 let slippageValueMaxForReplenish = (scale8 + ((scale8 * tolerance) / 10000000))
487516 let slippageValueMinForSwap = (scale8 - ((scale8 * 1) / 10000000))
488517 if ((pmtMinThreshold > pmtAmount))
489518 then throw((((("Payment amount " + toString(pmtAmount)) + " does not exceed the minimum amount of ") + toString(pmtMinThreshold)) + " tokens"))
490519 else if ((size(i.payments) != 1))
491520 then throwOnePayment()
492521 else if (!(hasEnoughBalance))
493522 then ([ScriptTransfer(i.caller, pmtAmount, pmtAssetId)] ++ suspendSuspicious())
494523 else if (if ((pmtAssetId != assetIdA))
495524 then (pmtAssetId != assetIdB)
496525 else false)
497526 then throwAssets()
498527 else {
499- let $t01727917921 = if ((pmtAssetId == assetIdA))
528+ let $t01831818960 = if ((pmtAssetId == assetIdA))
500529 then $Tuple6((pmtAmount - virtualSwapTokenPay), virtualSwapTokenGet, (balanceA + virtualSwapTokenPay), (balanceB - virtualSwapTokenGet), (balanceA + pmtAmount), balanceB)
501530 else $Tuple6(virtualSwapTokenGet, (pmtAmount - virtualSwapTokenPay), (balanceA - virtualSwapTokenGet), (balanceB + virtualSwapTokenPay), balanceA, (balanceB + pmtAmount))
502- let virtualReplenishA = $t01727917921._1
503- let virtualReplenishB = $t01727917921._2
504- let balanceAfterSwapA = $t01727917921._3
505- let balanceAfterSwapB = $t01727917921._4
506- let newBalanceA = $t01727917921._5
507- let newBalanceB = $t01727917921._6
531+ let virtualReplenishA = $t01831818960._1
532+ let virtualReplenishB = $t01831818960._2
533+ let balanceAfterSwapA = $t01831818960._3
534+ let balanceAfterSwapB = $t01831818960._4
535+ let newBalanceA = $t01831818960._5
536+ let newBalanceB = $t01831818960._6
508537 let invariantNew = invariantCalc(balanceAfterSwapA, balanceAfterSwapB)
509538 let ratioVirtualBalanceToVirtualReplenish = (fraction(scale16, balanceAfterSwapA, balanceAfterSwapB) / fraction(scale8, virtualReplenishA, virtualReplenishB))
510539 let dAppThresholdAmount = fraction((newBalanceA + newBalanceB), dAppThreshold, (2 * dAppThresholdScale2))
511540 if (if ((slippageValueMinForSwap >= fraction(scale8, invariant, invariantNew)))
512541 then true
513542 else (invariant > invariantNew))
514543 then throw("Incorrect virtualSwapTokenPay or virtualSwapTokenGet value")
515544 else if (if ((slippageValueMinForReplenish > ratioVirtualBalanceToVirtualReplenish))
516545 then true
517546 else (ratioVirtualBalanceToVirtualReplenish > slippageValueMaxForReplenish))
518547 then throw("Swap with virtualSwapTokenPay and virtualSwapTokenGet is possible, but ratio after virtual swap is incorrect")
519548 else if (if ((dAppThresholdAmount > newBalanceA))
520549 then true
521550 else (dAppThresholdAmount > newBalanceB))
522551 then throwThreshold(dAppThresholdAmount, newBalanceA, newBalanceB)
523552 else {
524553 let ratioShareTokensInA = fraction(virtualReplenishA, scale8, balanceAfterSwapA)
525554 let ratioShareTokensInB = fraction(virtualReplenishB, scale8, balanceAfterSwapB)
526555 let shareTokenToPayAmount = fraction(min([ratioShareTokensInA, ratioShareTokensInB]), shareAssetSupply, scale8)
527556 let shareTokenToPayAmountAfterFee = fraction(shareTokenToPayAmount, (feeScale6 - (fee / 2)), feeScale6)
528557 let shareTokenGovernanceReward = fraction(shareTokenToPayAmount, (feeGovernance / 2), feeScale6)
529558 let governanceRewardTokenA = fraction(shareTokenGovernanceReward, balanceA, shareAssetSupply)
530559 let governanceRewardTokenB = fraction(shareTokenGovernanceReward, balanceB, shareAssetSupply)
531- let $t01990820203 = if ((pmtStrAssetId == strAssetIdA))
560+ let $t02094721242 = if ((pmtStrAssetId == strAssetIdA))
532561 then $Tuple3((pmtAmount - governanceRewardTokenA), governanceRewardTokenB, strAssetIdB)
533562 else $Tuple3((pmtAmount - governanceRewardTokenB), governanceRewardTokenA, strAssetIdA)
534- let stakeAmount = $t01990820203._1
535- let unstakeAmount = $t01990820203._2
536- let unstakeAsset = $t01990820203._3
563+ let stakeAmount = $t02094721242._1
564+ let unstakeAmount = $t02094721242._2
565+ let unstakeAsset = $t02094721242._3
537566 let stake1 = if (containsElement(stakingAssets, pmtStrAssetId))
538567 then invoke(this, "stakeUnstake", [true, stakeAmount, pmtStrAssetId], nil)
539568 else 0
540569 if ((stake1 == stake1))
541570 then {
542571 let stake2 = if (containsElement(stakingAssets, unstakeAsset))
543572 then invoke(this, "stakeUnstake", [false, unstakeAmount, unstakeAsset], nil)
544573 else 0
545574 if ((stake2 == stake2))
546575 then [Reissue(shareAssetId, shareTokenToPayAmountAfterFee, true), ScriptTransfer(i.caller, shareTokenToPayAmountAfterFee, shareAssetId), ScriptTransfer(moneyBoxAddress, governanceRewardTokenA, assetIdA), ScriptTransfer(moneyBoxAddress, governanceRewardTokenB, assetIdB), IntegerEntry(kBalanceA, (newBalanceA - governanceRewardTokenA)), IntegerEntry(kBalanceB, (newBalanceB - governanceRewardTokenB)), IntegerEntry(kShareAssetSupply, (shareAssetSupply + shareTokenToPayAmountAfterFee)), IntegerEntry(kInvariant, invariantCalc((newBalanceA - governanceRewardTokenA), (newBalanceB - governanceRewardTokenB)))]
547576 else throw("Strict value is not equal to itself.")
548577 }
549578 else throw("Strict value is not equal to itself.")
550579 }
551580 }
552581 })
553582
554583
555584
556585 @Callable(i)
557586 func withdraw () = valueOrElse(isActive(), {
558- let $t02149021565 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
559- let pmtAmount = $t02149021565._1
560- let pmtAssetId = $t02149021565._2
587+ let $t02252922604 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
588+ let pmtAmount = $t02252922604._1
589+ let pmtAssetId = $t02252922604._2
561590 let amountToPayA = fraction(pmtAmount, balanceA, shareAssetSupply)
562591 let amountToPayB = fraction(pmtAmount, balanceB, shareAssetSupply)
563592 let invariantCalculated = invariantCalc((balanceA - amountToPayA), (balanceB - amountToPayB))
564593 if ((size(i.payments) != 1))
565594 then throwOnePayment()
566595 else if ((pmtAssetId != shareAssetId))
567596 then throw(("Incorrect asset attached. Expected: " + toBase58String(shareAssetId)))
568597 else if (!(hasEnoughBalance))
569598 then ([ScriptTransfer(i.caller, pmtAmount, pmtAssetId)] ++ suspendSuspicious())
570599 else {
571600 let stake1 = if (containsElement(stakingAssets, strAssetIdA))
572601 then invoke(this, "stakeUnstake", [false, amountToPayA, strAssetIdA], nil)
573602 else 0
574603 if ((stake1 == stake1))
575604 then {
576605 let stake2 = if (containsElement(stakingAssets, strAssetIdB))
577606 then invoke(this, "stakeUnstake", [false, amountToPayB, strAssetIdB], nil)
578607 else 0
579608 if ((stake2 == stake2))
580609 then [IntegerEntry(kBalanceA, (balanceA - amountToPayA)), IntegerEntry(kBalanceB, (balanceB - amountToPayB)), IntegerEntry(kShareAssetSupply, (shareAssetSupply - pmtAmount)), IntegerEntry(kInvariant, invariantCalculated), Burn(shareAssetId, pmtAmount), ScriptTransfer(i.caller, amountToPayA, assetIdA), ScriptTransfer(i.caller, amountToPayB, assetIdB)]
581610 else throw("Strict value is not equal to itself.")
582611 }
583612 else throw("Strict value is not equal to itself.")
584613 }
585614 })
586615
587616
588617
589618 @Callable(i)
590619 func exchange (estimatedAmountToReceive,minAmountToReceive) = valueOrElse(isActive(), {
591- let $t02311623191 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
592- let pmtAmount = $t02311623191._1
593- let pmtAssetId = $t02311623191._2
620+ let $t02415524230 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
621+ let pmtAmount = $t02415524230._1
622+ let pmtAssetId = $t02415524230._2
594623 if ((0 >= estimatedAmountToReceive))
595624 then throw(("Estimated amount must be positive. Actual: " + toString(estimatedAmountToReceive)))
596625 else if ((minAmountToReceive > estimatedAmountToReceive))
597626 then throw("Minimal amount can't be greater than estimated.")
598627 else if ((size(i.payments) != 1))
599628 then throwOnePayment()
600629 else if (!(hasEnoughBalance))
601630 then ([ScriptTransfer(i.caller, pmtAmount, pmtAssetId)] ++ suspendSuspicious())
602631 else if (if ((pmtAssetId != assetIdA))
603632 then (pmtAssetId != assetIdB)
604633 else false)
605634 then throwAssets()
606635 else if ((10000000 > pmtAmount))
607636 then throw("Only swap of 10.000000 or more tokens is allowed")
608637 else if (if ((exchangeRatioLimitMin > fraction(scale8, minAmountToReceive, pmtAmount)))
609638 then true
610639 else (fraction(scale8, estimatedAmountToReceive, pmtAmount) > exchangeRatioLimitMax))
611640 then throw("Incorrect args and pmt ratio")
612641 else {
613642 let sendAssetId = if ((pmtAssetId == assetIdA))
614643 then assetIdB
615644 else assetIdA
616645 let amount = calculateSendAmount(estimatedAmountToReceive, minAmountToReceive, pmtAmount, pmtAssetId)
617646 let feeDiscount = calculateFeeDiscount(i.originCaller)
618647 let governanceReward = fraction(amount, fraction(feeGovernance, feeDiscount, feeScale6, CEILING), feeScale6)
619648 let amountMinusFee = fraction(amount, (feeScale6 - fraction(fee, feeDiscount, feeScale6, CEILING)), feeScale6)
620- let $t02464424906 = if ((pmtAssetId == assetIdA))
649+ let $t02568325945 = if ((pmtAssetId == assetIdA))
621650 then $Tuple2((balanceA + pmtAmount), ((balanceB - amountMinusFee) - governanceReward))
622651 else $Tuple2(((balanceA - amountMinusFee) - governanceReward), (balanceB + pmtAmount))
623- let newBalanceA = $t02464424906._1
624- let newBalanceB = $t02464424906._2
652+ let newBalanceA = $t02568325945._1
653+ let newBalanceB = $t02568325945._2
625654 let dAppThresholdAmount = fraction((newBalanceA + newBalanceB), dAppThreshold, (2 * dAppThresholdScale2))
626655 if (if ((dAppThresholdAmount > newBalanceA))
627656 then true
628657 else (dAppThresholdAmount > newBalanceB))
629658 then throwThreshold(dAppThresholdAmount, newBalanceA, newBalanceB)
630659 else {
631- let $t02520525278 = getAssetInfo(pmtAssetId)
632- let pmtStrAssetId = $t02520525278._1
633- let pmtAssetName = $t02520525278._2
634- let pmtDecimals = $t02520525278._3
635- let $t02529125368 = getAssetInfo(sendAssetId)
636- let sendStrAssetId = $t02529125368._1
637- let sendAssetName = $t02529125368._2
638- let sendDecimals = $t02529125368._3
660+ let $t02624426317 = getAssetInfo(pmtAssetId)
661+ let pmtStrAssetId = $t02624426317._1
662+ let pmtAssetName = $t02624426317._2
663+ let pmtDecimals = $t02624426317._3
664+ let $t02633026407 = getAssetInfo(sendAssetId)
665+ let sendStrAssetId = $t02633026407._1
666+ let sendAssetName = $t02633026407._2
667+ let sendDecimals = $t02633026407._3
639668 let stake1 = if (containsElement(stakingAssets, pmtStrAssetId))
640669 then invoke(this, "stakeUnstake", [true, pmtAmount, pmtStrAssetId], nil)
641670 else 0
642671 if ((stake1 == stake1))
643672 then {
644673 let stake2 = if (containsElement(stakingAssets, sendStrAssetId))
645674 then invoke(this, "stakeUnstake", [false, (amountMinusFee + governanceReward), sendStrAssetId], nil)
646675 else 0
647676 if ((stake2 == stake2))
648- then $Tuple2([IntegerEntry(kBalanceA, newBalanceA), IntegerEntry(kBalanceB, newBalanceB), IntegerEntry(kInvariant, invariantCalc(newBalanceA, newBalanceB)), ScriptTransfer(i.caller, amountMinusFee, sendAssetId), ScriptTransfer(moneyBoxAddress, governanceReward, sendAssetId)], $Tuple2(amountMinusFee, sendAssetId))
677+ then $Tuple2([IntegerEntry(kBalanceA, newBalanceA), IntegerEntry(kBalanceB, newBalanceB), IntegerEntry(kInvariant, invariantCalc(newBalanceA, newBalanceB)), ScriptTransfer(i.caller, amountMinusFee, sendAssetId), ScriptTransfer(moneyBoxAddress, governanceReward, sendAssetId)], [amountMinusFee, sendAssetId])
649678 else throw("Strict value is not equal to itself.")
650679 }
651680 else throw("Strict value is not equal to itself.")
652681 }
653682 }
654683 })
655684
656685
657686
658687 @Callable(i)
659688 func shutdown () = valueOrElse(isAdminCall(i), if (!(active))
660689 then throw(("DApp is already suspended. Cause: " + valueOrElse(getString(this, kCause), "the cause wasn't specified")))
661690 else suspend("Paused by admin"))
662691
663692
664693
665694 @Callable(i)
666695 func activate () = valueOrElse(isAdminCall(i), if (active)
667696 then throwIsActive()
668697 else [BooleanEntry(kActive, true), DeleteEntry(kCause)])
669698
670699
671700
672701 @Callable(i)
673702 func takeIntoAccountExtraFunds () = valueOrElse(isActive(), {
674703 let amountEnrollA = (accountBalanceWithStakedA - balanceA)
675704 let amountEnrollB = (accountBalanceWithStakedB - balanceB)
676705 let invariantNew = invariantCalc((balanceA + amountEnrollA), (balanceB + amountEnrollB))
677706 if ((i.caller != moneyBoxAddress))
678707 then throw("Only the money box can call this function")
679708 else if (if ((0 > amountEnrollA))
680709 then true
681710 else (0 > amountEnrollB))
682711 then suspend("Enroll amount negative")
683712 else if (if ((amountEnrollA == 0))
684713 then (amountEnrollB == 0)
685714 else false)
686715 then throw("No money to take")
687716 else {
688717 let stake1 = if (if (containsElement(stakingAssets, strAssetIdA))
689718 then (amountEnrollA > 0)
690719 else false)
691720 then invoke(this, "stakeUnstake", [true, amountEnrollA, strAssetIdA], nil)
692721 else 0
693722 if ((stake1 == stake1))
694723 then {
695724 let stake2 = if (if (containsElement(stakingAssets, strAssetIdB))
696725 then (amountEnrollB > 0)
697726 else false)
698727 then invoke(this, "stakeUnstake", [true, amountEnrollB, strAssetIdB], nil)
699728 else 0
700729 if ((stake2 == stake2))
701730 then [IntegerEntry(kInvariant, invariantNew), IntegerEntry(kBalanceA, (balanceA + amountEnrollA)), IntegerEntry(kBalanceB, (balanceB + amountEnrollB))]
702731 else throw("Strict value is not equal to itself.")
703732 }
704733 else throw("Strict value is not equal to itself.")
705734 }
706735 })
707736
708737
709738
710739 @Callable(i)
740+func keepLimitForFirstHarvest (shareLimit) = valueOrElse(isActive(), valueOrElse(isAdminCall(i), [IntegerEntry(kShareLimit, shareLimit)]))
741+
742+
743+
744+@Callable(i)
711745 func stakeUnstake (stake,amount,assetIdString) = if ((i.caller != this))
712746 then throw("Only contract itself can invoke this function")
713747 else {
714- let $t02837228475 = calcStakingParams(stake, amount, fromBase58String(assetIdString))
715- let call = $t02837228475._1
716- let addr = $t02837228475._2
717- let params = $t02837228475._3
718- let payments = $t02837228475._4
748+ let $t02961429717 = calcStakingParams(stake, amount, fromBase58String(assetIdString))
749+ let call = $t02961429717._1
750+ let addr = $t02961429717._2
751+ let params = $t02961429717._3
752+ let payments = $t02961429717._4
719753 let inv = invoke(addr, call, params, payments)
720754 if ((inv == inv))
721755 then nil
722756 else throw("Strict value is not equal to itself.")
723757 }
724-
725-
726-
727-@Callable(i)
728-func toBigIntInvariant () = valueOrElse(isAdminCall(i), [IntegerEntry(kInvariant, invariantCalc(balanceA, balanceB))])
729758
730759
731760 @Verifier(tx)
732761 func verify () = {
733762 let multiSignedByAdmins = {
734763 let adminPubKey1Signed = if (sigVerify(tx.bodyBytes, tx.proofs[0], adminPubKey1))
735764 then 1
736765 else 0
737766 let adminPubKey2Signed = if (sigVerify(tx.bodyBytes, tx.proofs[1], adminPubKey2))
738767 then 1
739768 else 0
740769 let adminPubKey3Signed = if (sigVerify(tx.bodyBytes, tx.proofs[2], adminPubKey3))
741770 then 1
742771 else 0
743772 (((adminPubKey1Signed + adminPubKey2Signed) + adminPubKey3Signed) >= 2)
744773 }
745774 match tx {
746775 case inv: InvokeScriptTransaction =>
747776 let callTakeIntoAccount = if ((inv.dApp == this))
748777 then (inv.function == "takeIntoAccountExtraFunds")
749778 else false
750779 let signedByAdmin = if (if (if (sigVerify(tx.bodyBytes, tx.proofs[0], adminPubKey1))
751780 then true
752781 else sigVerify(tx.bodyBytes, tx.proofs[0], adminPubKey2))
753782 then true
754783 else sigVerify(tx.bodyBytes, tx.proofs[0], adminPubKey3))
755784 then true
756785 else sigVerify(tx.bodyBytes, tx.proofs[0], adminPubKeyInvoke)
757786 if (if (callTakeIntoAccount)
758787 then signedByAdmin
759788 else false)
760789 then true
761790 else multiSignedByAdmins
762791 case _ =>
763792 multiSignedByAdmins
764793 }
765794 }
766795

github/deemru/w8io/873ac7e 
178.11 ms