tx · EWbphkhY6NbbuezqiPaYC3aVbUXB9C94t2kLetQdLB8R

3MrMbQwr3cpCvWMWCFjqUZzqRgxg8En6Jd5:  -0.03700000 Waves

2022.11.17 00:39 [2320226] smart account 3MrMbQwr3cpCvWMWCFjqUZzqRgxg8En6Jd5 > SELF 0.00000000 Waves

{ "type": 13, "id": "EWbphkhY6NbbuezqiPaYC3aVbUXB9C94t2kLetQdLB8R", "fee": 3700000, "feeAssetId": null, "timestamp": 1668634849052, "version": 2, "chainId": 84, "sender": "3MrMbQwr3cpCvWMWCFjqUZzqRgxg8En6Jd5", "senderPublicKey": "8WTLBzi1s9cZm76TPZ9czV6poaHGWvpZ7sCBeTBaa7uh", "proofs": [ "657KrNmcitumekg7z3SGmTzN3a2eYraKMAKSwgrfxEL4ZLXUXTpocqoMeSD22vzNyAYZjniYudcz2XMJeNprMLj5" ], "script": "base64:BgJhCAISBAoCCAgSAwoBCBIAEgUKAwgIARIFCgMICAESBgoECAgIARIFCgMICAgSBQoDCAgBEgQKAggIEgMKAQgSBAoCCAESBQoDCAgBEgQKAggBEgQKAggBEgMKAQgSAwoBCGAAE2tfdG90YWxGZWVzSW5QZXJpb2QCE2tfdG90YWxGZWVzSW5QZXJpb2QAGGtfdG90YWxBc3NldEZlZXNJblBlcmlvZAIYa190b3RhbEFzc2V0RmVlc0luUGVyaW9kABRrX3RyYWRlckZlZXNJblBlcmlvZAIUa190cmFkZXJGZWVzSW5QZXJpb2QADmtfdHJhZGVyVm9sdW1lAg5rX3RyYWRlclZvbHVtZQAYa190cmFkZXJDdW11bGF0aXZlVm9sdW1lAhhrX3RyYWRlckN1bXVsYXRpdmVWb2x1bWUACmtfZmVlVGllcnMCCmtfZmVlVGllcnMADmtfbGFzdE5vdGlvbmFsAg5rX2xhc3ROb3Rpb25hbAAUa190b3RhbFNjb3JlSW5QZXJpb2QCFGtfdG90YWxTY29yZUluUGVyaW9kABVrX3RyYWRlclNjb3JlSW5QZXJpb2QCFWtfdHJhZGVyU2NvcmVJblBlcmlvZAAfa190cmFkZXJBdmVyYWdlTm90aW9uYWxJblBlcmlvZAIfa190cmFkZXJBdmVyYWdlTm90aW9uYWxJblBlcmlvZAAPa19hbW1SZXdhcmRSYXRlAg9rX2FtbVJld2FyZFJhdGUAGWtfYXNzZXRNYXhBbW91bnRQZXJQZXJpb2QCGWtfYXNzZXRNYXhBbW91bnRQZXJQZXJpb2QAEGtfcmV3YXJkQXNzZXRJZHMCEGtfcmV3YXJkQXNzZXRJZHMABmtfYW1tcwIGa19hbW1zABdrX2NsYWltZWRBc3NldEFuZFBlcmlvZAIXa19jbGFpbWVkQXNzZXRBbmRQZXJpb2QAD2tfb3JhY2xlQWRkcmVzcwIPa19vcmFjbGVBZGRyZXNzAA1rX29yYWNsZVByaWNlAgVwcmljZQAfa190b3RhbENsYWltZWRGb3JUcmFkZXJBbmRBc3NldAIfa190b3RhbENsYWltZWRGb3JUcmFkZXJBbmRBc3NldAAXa19hbW1NYXhBbW91bnRQZXJQZXJpb2QCF2tfYW1tTWF4QW1vdW50UGVyUGVyaW9kAA1rX2luaXRpYWxpemVkAg1rX2luaXRpYWxpemVkABRrX2Nvb3JkaW5hdG9yQWRkcmVzcwIUa19jb29yZGluYXRvckFkZHJlc3MAEmtfZ292ZXJuYW5jZV9hc3NldAILa19nb3ZfYXNzZXQADWtfcXVvdGVfYXNzZXQCDWtfcXVvdGVfYXNzZXQAEmtfYWRtaW5fcHVibGljX2tleQISa19hZG1pbl9wdWJsaWNfa2V5AA9rX2FkbWluX2FkZHJlc3MCD2tfYWRtaW5fYWRkcmVzcwAFa19hbW0CBWtfYW1tAAxERUNJTUFMX1VOSVQJAGgCAAEJAGgCCQBoAgkAaAIJAGgCCQBoAgkAaAIJAGgCAAoACgAKAAoACgAKAAoACgABQQCAu7AhAApNU19JTl9XRUVLCQBoAgDoBwCA9SQACU1TX0lOX0RBWQkAaAIA6AcAgKMFAAtOT19ESVNDT1VOVAkAaQIFDERFQ0lNQUxfVU5JVABkAQlsaXN0VG9TdHIBBV9saXN0CgEFX2pvaW4CC2FjY3VtdWxhdG9yA3ZhbAkArAICCQCsAgIFC2FjY3VtdWxhdG9yBQN2YWwCASwECm5ld0xpc3RTdHIKAAIkbAUFX2xpc3QKAAIkcwkAkAMBBQIkbAoABSRhY2MwAgAKAQUkZjBfMQICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkBBV9qb2luAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGYwXzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhVMaXN0IHNpemUgZXhjZWVkcyAxMDAJAQUkZjBfMgIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYABwAIAAkACgALAAwADQAOAA8AEAARABIAEwAUABUAFgAXABgAGQAaABsAHAAdAB4AHwAgACEAIgAjACQAJQAmACcAKAApACoAKwAsAC0ALgAvADAAMQAyADMANAA1ADYANwA4ADkAOgA7ADwAPQA+AD8AQABBAEIAQwBEAEUARgBHAEgASQBKAEsATABNAE4ATwBQAFEAUgBTAFQAVQBWAFcAWABZAFoAWwBcAF0AXgBfAGAAYQBiAGMAZAQLbmV3TGlzdFN0clUJALMCAgUKbmV3TGlzdFN0cgABBAtuZXdMaXN0U3RyUgMJAAACCQCvAgIFC25ld0xpc3RTdHJVAAECASwJALACAgULbmV3TGlzdFN0clUAAQULbmV3TGlzdFN0clUFC25ld0xpc3RTdHJSAQlzdHJUb0xpc3QBBF9zdHIDCQAAAgUEX3N0cgIABQNuaWwJALUJAgUEX3N0cgIBLAEEZGl2ZAICX3gCX3kJAG4EBQJfeAUMREVDSU1BTF9VTklUBQJfeQUISEFMRkVWRU4BBG11bGQCAl94Al95CQBuBAUCX3gFAl95BQxERUNJTUFMX1VOSVQFCEhBTEZFVkVOAQRwb3dkAgJfeAJfeQkAbAYFAl94AAgFAl95AAgACAUISEFMRkVWRU4BA2FicwECX3gDCQBmAgUCX3gAAAUCX3gJAQEtAQUCX3gBBG1pbnYCAl94Al95AwkAZgIFAl94BQJfeQUCX3kFAl94AQ50b0NvbXBvc2l0ZUtleQIEX2tleQhfYWRkcmVzcwkArAICCQCsAgIFBF9rZXkCAV8FCF9hZGRyZXNzAAR0aGF0BQR0aGlzAQtjb29yZGluYXRvcgAJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkApggBCQERQGV4dHJOYXRpdmUoMTA1MykCBQR0aGF0BRRrX2Nvb3JkaW5hdG9yQWRkcmVzcwITQ29vcmRpbmF0b3Igbm90IHNldAEOYWRtaW5QdWJsaWNLZXkACQDZBAEJARFAZXh0ck5hdGl2ZSgxMDUzKQIJAQtjb29yZGluYXRvcgAFEmtfYWRtaW5fcHVibGljX2tleQEMYWRtaW5BZGRyZXNzAAkApggBCQERQGV4dHJOYXRpdmUoMTA1MykCCQELY29vcmRpbmF0b3IABQ9rX2FkbWluX2FkZHJlc3MBC2lzV2hpdGVsaXN0AQhfYWRkcmVzcwkBC3ZhbHVlT3JFbHNlAgkAmwgCCQELY29vcmRpbmF0b3IACQEOdG9Db21wb3NpdGVLZXkCBQVrX2FtbQUIX2FkZHJlc3MHAQNpbnQBAWsJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAmggCBQR0aGF0BQFrCQCsAgICDW5vIHZhbHVlIGZvciAFAWsBBGludDABAWsJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhhdAUBawAAAQtpbml0aWFsaXplZAAJAQt2YWx1ZU9yRWxzZQIJAJsIAgUEdGhhdAUNa19pbml0aWFsaXplZAcBEWdldFJld2FyZEFzc2V0SWRzAAkBCXN0clRvTGlzdAEJAQt2YWx1ZU9yRWxzZQIJAJ0IAgUEdGhhdAUQa19yZXdhcmRBc3NldElkcwIAAARUSU1FCAUJbGFzdEJsb2NrCXRpbWVzdGFtcAESZ2V0VHJhZGVyVm9sdW1lS2V5AgdfdHJhZGVyBl9kYXlJZAkArAICCQCsAgIJAKwCAgkArAICBQ5rX3RyYWRlclZvbHVtZQIBXwUHX3RyYWRlcgIBXwkApAMBBQZfZGF5SWQBHGdldFRyYWRlckN1bXVsYXRpdmVWb2x1bWVLZXkBB190cmFkZXIJAKwCAgkArAICBRhrX3RyYWRlckN1bXVsYXRpdmVWb2x1bWUCAV8FB190cmFkZXIBGGdldFRyYWRlckZlZXNJblBlcmlvZEtleQMEX2FtbQdfdHJhZGVyB193ZWVrSWQJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgIFFGtfdHJhZGVyRmVlc0luUGVyaW9kAgFfBQRfYW1tAgFfBQdfdHJhZGVyAgFfCQCkAwEFB193ZWVrSWQBGmdldFRvdGFsQW1tRmVlc0luUGVyaW9kS2V5AgRfYW1tB193ZWVrSWQJAKwCAgkArAICCQCsAgIJAKwCAgUTa190b3RhbEZlZXNJblBlcmlvZAIBXwUEX2FtbQIBXwkApAMBBQdfd2Vla0lkARxnZXRUb3RhbEFzc2V0RmVlc0luUGVyaW9kS2V5AghfYXNzZXRJZAdfd2Vla0lkCQCsAgIJAKwCAgkArAICCQCsAgIFGGtfdG90YWxBc3NldEZlZXNJblBlcmlvZAIBXwUIX2Fzc2V0SWQCAV8JAKQDAQUHX3dlZWtJZAESZ2V0TGFzdE5vdGlvbmFsS2V5AgRfYW1tB190cmFkZXIJAKwCAgkArAICCQCsAgIJAKwCAgUOa19sYXN0Tm90aW9uYWwCAV8FBF9hbW0CAV8FB190cmFkZXIBGWdldFRyYWRlclNjb3JlSW5QZXJpb2RLZXkDBF9hbW0HX3RyYWRlcgdfd2Vla0lkCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICBRVrX3RyYWRlclNjb3JlSW5QZXJpb2QCAV8FBF9hbW0CAV8FB190cmFkZXICAV8JAKQDAQUHX3dlZWtJZAEYZ2V0VG90YWxTY29yZUluUGVyaW9kS2V5AgRfYW1tB193ZWVrSWQJAKwCAgkArAICCQCsAgIJAKwCAgUUa190b3RhbFNjb3JlSW5QZXJpb2QCAV8FBF9hbW0CAV8JAKQDAQUHX3dlZWtJZAEjZ2V0VHJhZGVyQXZlcmFnZU5vdGlvbmFsSW5QZXJpb2RLZXkDBF9hbW0HX3RyYWRlcgdfd2Vla0lkCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICBR9rX3RyYWRlckF2ZXJhZ2VOb3Rpb25hbEluUGVyaW9kAgFfBQRfYW1tAgFfBQdfdHJhZGVyAgFfCQCkAwEFB193ZWVrSWQBE2dldEFtbVJld2FyZFJhdGVLZXkCBF9hbW0IX2Fzc2V0SWQJAKwCAgkArAICCQCsAgIJAKwCAgUPa19hbW1SZXdhcmRSYXRlAgFfBQRfYW1tAgFfBQhfYXNzZXRJZAEdZ2V0QXNzZXRNYXhBbW91bnRQZXJQZXJpb2RLZXkBCF9hc3NldElkCQCsAgIJAKwCAgUZa19hc3NldE1heEFtb3VudFBlclBlcmlvZAIBXwUIX2Fzc2V0SWQBHmdldENsYWltZWRUcmFkZXJBc3NldFBlcmlvZEtleQMHX3RyYWRlcghfYXNzZXRJZAdfcGVyaW9kCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICBRdrX2NsYWltZWRBc3NldEFuZFBlcmlvZAIBXwUHX3RyYWRlcgIBXwUIX2Fzc2V0SWQCAV8JAKQDAQUHX3BlcmlvZAERZ2V0T3JhY2xlUHJpY2VLZXkCCF9hc3NldElkB19wZXJpb2QJAKwCAgkArAICCQCsAgIJAKwCAgUNa19vcmFjbGVQcmljZQIBXwkApAMBBQdfcGVyaW9kAgFfBQhfYXNzZXRJZAEjZ2V0VG90YWxDbGFpbWVkRm9yVHJhZGVyQW5kQXNzZXRLZXkCB190cmFkZXIIX2Fzc2V0SWQJAKwCAgkArAICCQCsAgIJAKwCAgUfa190b3RhbENsYWltZWRGb3JUcmFkZXJBbmRBc3NldAIBXwUHX3RyYWRlcgIBXwUIX2Fzc2V0SWQBG2dldEFtbU1heEFtb3VudFBlclBlcmlvZEtleQIEX2FtbQhfYXNzZXRJZAkArAICCQCsAgIJAKwCAgkArAICBRdrX2FtbU1heEFtb3VudFBlclBlcmlvZAIBXwUEX2FtbQIBXwUIX2Fzc2V0SWQBDnVzZG5Ub0RlY2ltYWxzAQdfYW1vdW50CQBoAgUHX2Ftb3VudABkAQxnZXRXZWVrU3RhcnQBB193ZWVrSWQJAGgCBQdfd2Vla0lkBQpNU19JTl9XRUVLAQpnZXRXZWVrRW5kAQdfd2Vla0lkCQBoAgkAZAIFB193ZWVrSWQAAQUKTVNfSU5fV0VFSwEJZ2V0V2Vla0lkAQNfdHMJAGkCBQNfdHMFCk1TX0lOX1dFRUsBCGdldERheUlkAQNfdHMJAGkCBQNfdHMFCU1TX0lOX0RBWQELZ2V0RmVlVGllcnMABAtzdG9yZWRUaWVycwkBC3ZhbHVlT3JFbHNlAgkAnQgCBQR0aGlzBQprX2ZlZVRpZXJzAgADCQAAAgULc3RvcmVkVGllcnMCAAUDbmlsBAV0aWVycwkAtQkCCQELdmFsdWVPckVsc2UCCQCdCAIFBHRoaXMFCmtfZmVlVGllcnMCAAIBLAoBCXRvRmVlVGllcgIEX2FjYwVfdGllcgQJdGllclNwbGl0CQC1CQIFBV90aWVyAgE6BBNtaW5DdW11bGF0aXZlVm9sdW1lCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUJdGllclNwbGl0AAAECGRpc2NvdW50CQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUJdGllclNwbGl0AAEJAM0IAgUEX2FjYwkAlAoCBRNtaW5DdW11bGF0aXZlVm9sdW1lBQhkaXNjb3VudAoAAiRsBQV0aWVycwoAAiRzCQCQAwEFAiRsCgAFJGFjYzAFA25pbAoBBSRmMF8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQEJdG9GZWVUaWVyAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGYwXzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhRMaXN0IHNpemUgZXhjZWVkcyAxMAkBBSRmMF8yAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgUFJGFjYzAAAAABAAIAAwAEAAUABgAHAAgACQAKAQ9nZXRUcmFkZXJWb2x1bWUCB190cmFkZXIGX2RheUlkBANrZXkJARJnZXRUcmFkZXJWb2x1bWVLZXkCBQdfdHJhZGVyBQZfZGF5SWQJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwUDa2V5AAABGWdldFRyYWRlckN1bXVsYXRpdmVWb2x1bWUBB190cmFkZXIEA2tleQkBHGdldFRyYWRlckN1bXVsYXRpdmVWb2x1bWVLZXkBBQdfdHJhZGVyCQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMFA2tleQAAAQ9nZXRGZWVzSW5QZXJpb2QDBF9hbW0HX3RyYWRlcgdfd2Vla0lkBANrZXkJARhnZXRUcmFkZXJGZWVzSW5QZXJpb2RLZXkDBQRfYW1tBQdfdHJhZGVyBQdfd2Vla0lkCQEEaW50MAEFA2tleQEUZ2V0VG90YWxGZWVzSW5QZXJpb2QCBF9hbW0HX3dlZWtJZAQDa2V5CQEaZ2V0VG90YWxBbW1GZWVzSW5QZXJpb2RLZXkCBQRfYW1tBQdfd2Vla0lkCQEEaW50MAEFA2tleQEZZ2V0VG90YWxBc3NldEZlZXNJblBlcmlvZAIIX2Fzc2V0SWQHX3dlZWtJZAQDa2V5CQEcZ2V0VG90YWxBc3NldEZlZXNJblBlcmlvZEtleQIFCF9hc3NldElkBQdfd2Vla0lkCQEEaW50MAEFA2tleQEPZ2V0TGFzdE5vdGlvbmFsAgRfYW1tB190cmFkZXIEA2tleQkBEmdldExhc3ROb3Rpb25hbEtleQIFBF9hbW0FB190cmFkZXIJAQRpbnQwAQUDa2V5ARZnZXRUcmFkZXJTY29yZUluUGVyaW9kAwRfYW1tB190cmFkZXIHX3dlZWtJZAQDa2V5CQEZZ2V0VHJhZGVyU2NvcmVJblBlcmlvZEtleQMFBF9hbW0FB190cmFkZXIFB193ZWVrSWQJAQRpbnQwAQUDa2V5ARVnZXRUb3RhbFNjb3JlSW5QZXJpb2QCBF9hbW0HX3dlZWtJZAQDa2V5CQEYZ2V0VG90YWxTY29yZUluUGVyaW9kS2V5AgUEX2FtbQUHX3dlZWtJZAkBBGludDABBQNrZXkBB2dldEFtbXMACQEJc3RyVG9MaXN0AQkBC3ZhbHVlT3JFbHNlAgkAnQgCBQR0aGF0BQZrX2FtbXMCAAEQZ2V0QW1tUmV3YXJkUmF0ZQIEX2FtbQhfYXNzZXRJZAQDa2V5CQETZ2V0QW1tUmV3YXJkUmF0ZUtleQIFBF9hbW0FCF9hc3NldElkCQEEaW50MAEFA2tleQEaZ2V0QXNzZXRNYXhBbW91bnRQZXJQZXJpb2QBCF9hc3NldElkBANrZXkJAR1nZXRBc3NldE1heEFtb3VudFBlclBlcmlvZEtleQEFCF9hc3NldElkCQEEaW50MAEFA2tleQEgZ2V0VG90YWxDbGFpbWVkRm9yVHJhZGVyQW5kQXNzZXQCB190cmFkZXIIX2Fzc2V0SWQEA2tleQkBI2dldFRvdGFsQ2xhaW1lZEZvclRyYWRlckFuZEFzc2V0S2V5AgUHX3RyYWRlcgUIX2Fzc2V0SWQJAQRpbnQwAQUDa2V5ARNnZXRSZXdhcmRBc3NldFByaWNlAghfYXNzZXRJZAdfd2Vla0lkBBBvcmFjbGVBZGRyZXNzU3RyCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAJ0IAgUEdGhhdAUPa19vcmFjbGVBZGRyZXNzAg5PcmFjbGUgbm90IHNldAQNb3JhY2xlQWRkcmVzcwkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCmCAEFEG9yYWNsZUFkZHJlc3NTdHICFkludmFsaWQgb3JhY2xlIGFkZHJlc3MECHByaWNlS2V5CQERZ2V0T3JhY2xlUHJpY2VLZXkCBQhfYXNzZXRJZAUHX3dlZWtJZAkBDnVzZG5Ub0RlY2ltYWxzAQkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCaCAIFDW9yYWNsZUFkZHJlc3MFCHByaWNlS2V5CQCsAgIJAKwCAgkArAICAhpObyBvcmFjbGUgcHJpY2UgZm9yIGFzc2V0IAUIX2Fzc2V0SWQCCCBwZXJpb2QgCQCkAwEFB193ZWVrSWQBH2dldE1heEFtb3VudE9mQXNzZXRUb0Rpc3RyaWJ1dGUDBF9hbW0IX2Fzc2V0SWQHX3dlZWtJZAQRdG90YWxGZWVzSW5QZXJpb2QJARRnZXRUb3RhbEZlZXNJblBlcmlvZAIFBF9hbW0FB193ZWVrSWQEFnRvdGFsQXNzZXRGZWVzSW5QZXJpb2QJARlnZXRUb3RhbEFzc2V0RmVlc0luUGVyaW9kAgUIX2Fzc2V0SWQFB193ZWVrSWQDCQAAAgUWdG90YWxBc3NldEZlZXNJblBlcmlvZAAABANrZXkJARtnZXRBbW1NYXhBbW91bnRQZXJQZXJpb2RLZXkCBQRfYW1tBQhfYXNzZXRJZAkBBGludDABBQNrZXkEEG1heEFtb3VudE9mQXNzZXQJARpnZXRBc3NldE1heEFtb3VudFBlclBlcmlvZAEFCF9hc3NldElkBBxtYXhBbW91bnRPZkFzc2V0VG9EaXN0cmlidXRlCQEEbXVsZAIJAQRkaXZkAgURdG90YWxGZWVzSW5QZXJpb2QFFnRvdGFsQXNzZXRGZWVzSW5QZXJpb2QFEG1heEFtb3VudE9mQXNzZXQFHG1heEFtb3VudE9mQXNzZXRUb0Rpc3RyaWJ1dGUBHnJld2FyZEZvclRyYWRlckluQXNzZXRJblBlcmlvZAQEX2FtbQdfdHJhZGVyCF9hc3NldElkB193ZWVrSWQED3Jld2FyZEFzc2V0UmF0ZQkBEGdldEFtbVJld2FyZFJhdGUCBQRfYW1tBQhfYXNzZXRJZAMJAAACBQ9yZXdhcmRBc3NldFJhdGUAAAAABBF0b3RhbEZlZXNJblBlcmlvZAkBFGdldFRvdGFsRmVlc0luUGVyaW9kAgUEX2FtbQUHX3dlZWtJZAQQcmV3YXJkQXNzZXRQcmljZQkBE2dldFJld2FyZEFzc2V0UHJpY2UCBQhfYXNzZXRJZAUHX3dlZWtJZAQcbWF4QW1vdW50T2ZBc3NldFRvRGlzdHJpYnV0ZQkBH2dldE1heEFtb3VudE9mQXNzZXRUb0Rpc3RyaWJ1dGUDBQRfYW1tBQhfYXNzZXRJZAUHX3dlZWtJZAQLdHJhZGVyU2NvcmUJARZnZXRUcmFkZXJTY29yZUluUGVyaW9kAwUEX2FtbQUHX3RyYWRlcgUHX3dlZWtJZAQQdG90YWxUcmFkZXJTY29yZQkBFWdldFRvdGFsU2NvcmVJblBlcmlvZAIFBF9hbW0FB193ZWVrSWQDCQAAAgUQdG90YWxUcmFkZXJTY29yZQAAAAAEFnRvdGFsQXNzZXRUb0Rpc3RyaWJ1dGUJAQRkaXZkAgkBBG11bGQCBRF0b3RhbEZlZXNJblBlcmlvZAUPcmV3YXJkQXNzZXRSYXRlBRByZXdhcmRBc3NldFByaWNlBBxhY3R1YWxUb3RhbEFzc2V0VG9EaXN0cmlidXRlCQEEbWludgIFFnRvdGFsQXNzZXRUb0Rpc3RyaWJ1dGUFHG1heEFtb3VudE9mQXNzZXRUb0Rpc3RyaWJ1dGUEFHRyYWRlclNoYXJlSW5SZXdhcmRzCQEEZGl2ZAIJAQRtdWxkAgUcYWN0dWFsVG90YWxBc3NldFRvRGlzdHJpYnV0ZQULdHJhZGVyU2NvcmUFEHRvdGFsVHJhZGVyU2NvcmUFFHRyYWRlclNoYXJlSW5SZXdhcmRzARtyZXdhcmRGb3JBbW1JbkFzc2V0SW5QZXJpb2QDBF9hbW0IX2Fzc2V0SWQHX3dlZWtJZAQPcmV3YXJkQXNzZXRSYXRlCQEQZ2V0QW1tUmV3YXJkUmF0ZQIFBF9hbW0FCF9hc3NldElkAwkAAAIFD3Jld2FyZEFzc2V0UmF0ZQAAAAAEEXRvdGFsRmVlc0luUGVyaW9kCQEUZ2V0VG90YWxGZWVzSW5QZXJpb2QCBQRfYW1tBQdfd2Vla0lkBBByZXdhcmRBc3NldFByaWNlCQETZ2V0UmV3YXJkQXNzZXRQcmljZQIFCF9hc3NldElkBQdfd2Vla0lkBBxtYXhBbW91bnRPZkFzc2V0VG9EaXN0cmlidXRlCQEfZ2V0TWF4QW1vdW50T2ZBc3NldFRvRGlzdHJpYnV0ZQMFBF9hbW0FCF9hc3NldElkBQdfd2Vla0lkBBZ0b3RhbEFzc2V0VG9EaXN0cmlidXRlCQEEZGl2ZAIJAQRtdWxkAgURdG90YWxGZWVzSW5QZXJpb2QFD3Jld2FyZEFzc2V0UmF0ZQUQcmV3YXJkQXNzZXRQcmljZQQcYWN0dWFsVG90YWxBc3NldFRvRGlzdHJpYnV0ZQkBBG1pbnYCBRZ0b3RhbEFzc2V0VG9EaXN0cmlidXRlBRxtYXhBbW91bnRPZkFzc2V0VG9EaXN0cmlidXRlBRxhY3R1YWxUb3RhbEFzc2V0VG9EaXN0cmlidXRlASN0b3RhbFJld2FyZEZvclRyYWRlckluQXNzZXRJblBlcmlvZAMHX3RyYWRlcghfYXNzZXRJZAdfd2Vla0lkBARhbW1zCQEHZ2V0QW1tcwAKAQdjb21wdXRlAgRfYWNjBF9hbW0JAGQCBQRfYWNjCQEecmV3YXJkRm9yVHJhZGVySW5Bc3NldEluUGVyaW9kBAUEX2FtbQUHX3RyYWRlcgUIX2Fzc2V0SWQFB193ZWVrSWQKAAIkbAUEYW1tcwoAAiRzCQCQAwEFAiRsCgAFJGFjYzAAAAoBBSRmMF8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQEHY29tcHV0ZQIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmMF8yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQIUTGlzdCBzaXplIGV4Y2VlZHMgMjAJAQUkZjBfMgIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYABwAIAAkACgALAAwADQAOAA8AEAARABIAEwAUARt0b3RhbFJld2FyZEZvclRyYWRlckluQXNzZXQDB190cmFkZXIIX2Fzc2V0SWQIX3BlcmlvZHMKAQdjb21wdXRlAgRfYWNjB193ZWVrSWQJAGQCBQRfYWNjCQEjdG90YWxSZXdhcmRGb3JUcmFkZXJJbkFzc2V0SW5QZXJpb2QDBQdfdHJhZGVyBQhfYXNzZXRJZAUHX3dlZWtJZAoAAiRsBQhfcGVyaW9kcwoAAiRzCQCQAwEFAiRsCgAFJGFjYzAAAAoBBSRmMF8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQEHY29tcHV0ZQIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmMF8yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQIUTGlzdCBzaXplIGV4Y2VlZHMgMTIJAQUkZjBfMgIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYABwAIAAkACgALAAwBIGdldFRyYWRlckF2ZXJhZ2VOb3Rpb25hbEluUGVyaW9kBARfYW1tB190cmFkZXIHX3dlZWtJZA1fZGVmYXVsdFZhbHVlBANrZXkJASNnZXRUcmFkZXJBdmVyYWdlTm90aW9uYWxJblBlcmlvZEtleQMFBF9hbW0FB190cmFkZXIFB193ZWVrSWQJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhhdAUDa2V5BQ1fZGVmYXVsdFZhbHVlAQlpc0NsYWltZWQDB190cmFkZXIIX2Fzc2V0SWQHX3BlcmlvZAQDa2V5CQEeZ2V0Q2xhaW1lZFRyYWRlckFzc2V0UGVyaW9kS2V5AwUHX3RyYWRlcgUIX2Fzc2V0SWQFB19wZXJpb2QJAQt2YWx1ZU9yRWxzZQIJAJsIAgUEdGhhdAUDa2V5BwEGYWRqdXN0AgdfYW1vdW50CF9hc3NldElkBAVhc3NldAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQDsBwEJANkEAQUIX2Fzc2V0SWQCEEludmFsaWQgYXNzZXQgaWQECGRlY2ltYWxzCAUFYXNzZXQIZGVjaW1hbHMDCQAAAgUIZGVjaW1hbHMABgkAaQIFB19hbW91bnQAZAUHX2Ftb3VudAEgY2xhaW1BbGxSZXdhcmRGb3JQZXJpb2RGb3JUcmFkZXIDB190cmFkZXIIX2Fzc2V0SWQIX3BlcmlvZHMEB3BlcmlvZHMJAQlzdHJUb0xpc3QBBQhfcGVyaW9kcwoBEGNoZWNrQW5kRmlsdGVyRm4CBF9hY2MFX25leHQEBnBlcmlvZAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQC2CQEFBV9uZXh0CQCsAgICEEludmFsaWQgcGVyaW9kOiAFBV9uZXh0AwMJAQ9jb250YWluc0VsZW1lbnQCBQRfYWNjBQZwZXJpb2QGCQEJaXNDbGFpbWVkAwUHX3RyYWRlcgUIX2Fzc2V0SWQFBnBlcmlvZAUEX2FjYwkAzQgCBQRfYWNjBQZwZXJpb2QEDHZhbGlkUGVyaW9kcwoAAiRsBQdwZXJpb2RzCgACJHMJAJADAQUCJGwKAAUkYWNjMAUDbmlsCgEFJGYwXzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJARBjaGVja0FuZEZpbHRlckZuAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGYwXzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhRMaXN0IHNpemUgZXhjZWVkcyAxMgkBBSRmMF8yAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgUFJGFjYzAAAAABAAIAAwAEAAUABgAHAAgACQAKAAsADAoBEm1hcmtQZXJpb2RBc0RvbmVGbgIEX2FjYwdfcGVyaW9kCQDNCAIFBF9hY2MJAQxCb29sZWFuRW50cnkCCQEeZ2V0Q2xhaW1lZFRyYWRlckFzc2V0UGVyaW9kS2V5AwUHX3RyYWRlcgUIX2Fzc2V0SWQFB19wZXJpb2QGBBRtYXJrUGVyaW9kc0FzQ2xhaW1lZAoAAiRsBQx2YWxpZFBlcmlvZHMKAAIkcwkAkAMBBQIkbAoABSRhY2MwBQNuaWwKAQUkZjFfMQICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkBEm1hcmtQZXJpb2RBc0RvbmVGbgIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmMV8yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQIUTGlzdCBzaXplIGV4Y2VlZHMgMTYJAQUkZjFfMgIJAQUkZjFfMQIJAQUkZjFfMQIJAQUkZjFfMQIJAQUkZjFfMQIJAQUkZjFfMQIJAQUkZjFfMQIJAQUkZjFfMQIJAQUkZjFfMQIJAQUkZjFfMQIJAQUkZjFfMQIJAQUkZjFfMQIJAQUkZjFfMQIJAQUkZjFfMQIJAQUkZjFfMQIJAQUkZjFfMQIJAQUkZjFfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYABwAIAAkACgALAAwADQAOAA8AEAQGYW1vdW50CQEbdG90YWxSZXdhcmRGb3JUcmFkZXJJbkFzc2V0AwUHX3RyYWRlcgUIX2Fzc2V0SWQFDHZhbGlkUGVyaW9kcwkAlAoCBQZhbW91bnQJAM4IAgkAzAgCCQEOU2NyaXB0VHJhbnNmZXIDCQERQGV4dHJOYXRpdmUoMTA2MikBBQdfdHJhZGVyCQEGYWRqdXN0AgUGYW1vdW50BQhfYXNzZXRJZAkA2QQBBQhfYXNzZXRJZAkAzAgCCQEMSW50ZWdlckVudHJ5AgkBI2dldFRvdGFsQ2xhaW1lZEZvclRyYWRlckFuZEFzc2V0S2V5AgUHX3RyYWRlcgUIX2Fzc2V0SWQJAGQCCQEgZ2V0VG90YWxDbGFpbWVkRm9yVHJhZGVyQW5kQXNzZXQCBQdfdHJhZGVyBQhfYXNzZXRJZAUGYW1vdW50BQNuaWwFFG1hcmtQZXJpb2RzQXNDbGFpbWVkARJ1cGRhdGVUcmFkZXJWb2x1bWUDB190cmFkZXIGX2RheUlkEF9nZW5lcmF0ZWRWb2x1bWUED2FjdHVhbERheVZvbHVtZQkAZAIJAQ9nZXRUcmFkZXJWb2x1bWUCBQdfdHJhZGVyBQZfZGF5SWQFEF9nZW5lcmF0ZWRWb2x1bWUECmRheXNCZWZvcmUJAMwIAgABCQDMCAIAAgkAzAgCAAMJAMwIAgAECQDMCAIABQkAzAgCAAYJAMwIAgAHCQDMCAIACAkAzAgCAAkJAMwIAgAKCQDMCAIACwkAzAgCAAwJAMwIAgANCQDMCAIADgkAzAgCAA8JAMwIAgAQCQDMCAIAEQkAzAgCABIJAMwIAgATCQDMCAIAFAkAzAgCABUJAMwIAgAWCQDMCAIAFwkAzAgCABgJAMwIAgAZCQDMCAIAGgkAzAgCABsJAMwIAgAcCQDMCAIAHQkAzAgCAB4FA25pbAoBFnVwZGF0ZUN1bXVsYXRpdmVWb2x1bWUCBF9hY2MJX21pbnVzRGF5CQBkAgUEX2FjYwkBD2dldFRyYWRlclZvbHVtZQIFB190cmFkZXIJAGUCBQZfZGF5SWQFCV9taW51c0RheQQQY3VtdWxhdGl2ZVZvbHVtZQoAAiRsBQpkYXlzQmVmb3JlCgACJHMJAJADAQUCJGwKAAUkYWNjMAAACgEFJGYwXzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJARZ1cGRhdGVDdW11bGF0aXZlVm9sdW1lAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGYwXzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhRMaXN0IHNpemUgZXhjZWVkcyAzMAkBBSRmMF8yAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgUFJGFjYzAAAAABAAIAAwAEAAUABgAHAAgACQAKAAsADAANAA4ADwAQABEAEgATABQAFQAWABcAGAAZABoAGwAcAB0AHgkAzAgCCQEMSW50ZWdlckVudHJ5AgkBEmdldFRyYWRlclZvbHVtZUtleQIFB190cmFkZXIFBl9kYXlJZAUPYWN0dWFsRGF5Vm9sdW1lCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEcZ2V0VHJhZGVyQ3VtdWxhdGl2ZVZvbHVtZUtleQEFB190cmFkZXIJAGQCBRBjdW11bGF0aXZlVm9sdW1lBQ9hY3R1YWxEYXlWb2x1bWUFA25pbAENdXBkYXRlQW1tRmVlcwQEX2FtbQdfdHJhZGVyB193ZWVrSWQKX2FjdHVhbEZlZQQNdHJhZGVyRmVlc0tleQkBGGdldFRyYWRlckZlZXNJblBlcmlvZEtleQMFBF9hbW0FB190cmFkZXIFB193ZWVrSWQEDHRvdGFsRmVlc0tleQkBGmdldFRvdGFsQW1tRmVlc0luUGVyaW9kS2V5AgUEX2FtbQUHX3dlZWtJZAQMcmV3YXJkQXNzZXRzCQERZ2V0UmV3YXJkQXNzZXRJZHMABAxmZWVzSW5QZXJpb2QJAQ9nZXRGZWVzSW5QZXJpb2QDBQRfYW1tBQdfdHJhZGVyBQdfd2Vla0lkBBF0b3RhbEZlZXNJblBlcmlvZAkBFGdldFRvdGFsRmVlc0luUGVyaW9kAgUEX2FtbQUHX3dlZWtJZAQPbmV3RmVlc0luUGVyaW9kCQBkAgUMZmVlc0luUGVyaW9kBQpfYWN0dWFsRmVlBBRuZXdUb3RhbEZlZXNJblBlcmlvZAkAZAIFEXRvdGFsRmVlc0luUGVyaW9kBQpfYWN0dWFsRmVlCgEVZG9IYW5kbGVSZXdhcmRBc3NldElkAgRfYWNjCF9hc3NldElkBANrZXkJARNnZXRBbW1SZXdhcmRSYXRlS2V5AgUEX2FtbQUIX2Fzc2V0SWQDCQBmAgkBBGludDABBQNrZXkAAAQRdG90YWxBc3NldEZlZXNLZXkJARxnZXRUb3RhbEFzc2V0RmVlc0luUGVyaW9kS2V5AgUIX2Fzc2V0SWQFB193ZWVrSWQJAM0IAgUEX2FjYwkBDEludGVnZXJFbnRyeQIFEXRvdGFsQXNzZXRGZWVzS2V5CQBkAgkBGWdldFRvdGFsQXNzZXRGZWVzSW5QZXJpb2QCBQhfYXNzZXRJZAUHX3dlZWtJZAUKX2FjdHVhbEZlZQUEX2FjYwQPdXBkYXRlQXNzZXRGZWVzCgACJGwFDHJld2FyZEFzc2V0cwoAAiRzCQCQAwEFAiRsCgAFJGFjYzAFA25pbAoBBSRmMF8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQEVZG9IYW5kbGVSZXdhcmRBc3NldElkAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGYwXzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhRMaXN0IHNpemUgZXhjZWVkcyAxMAkBBSRmMF8yAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgUFJGFjYzAAAAABAAIAAwAEAAUABgAHAAgACQAKCQDOCAIJAMwIAgkBDEludGVnZXJFbnRyeQIFDXRyYWRlckZlZXNLZXkFD25ld0ZlZXNJblBlcmlvZAkAzAgCCQEMSW50ZWdlckVudHJ5AgUMdG90YWxGZWVzS2V5BRRuZXdUb3RhbEZlZXNJblBlcmlvZAUDbmlsBQ91cGRhdGVBc3NldEZlZXMBDXVwZGF0ZUFtbURhdGEHBF9hbW0HX3RyYWRlcgdfd2Vla0lkDl90cmFkZXJBdmVyYWdlE190cmFkZXJMYXN0Tm90aW9uYWwMX3RyYWRlclNjb3JlC190b3RhbFNjb3JlBBV0b3RhbFNjb3JlSW5QZXJpb2RLZXkJARhnZXRUb3RhbFNjb3JlSW5QZXJpb2RLZXkCBQRfYW1tBQdfd2Vla0lkBBZ0cmFkZXJTY29yZUluUGVyaW9kS2V5CQEZZ2V0VHJhZGVyU2NvcmVJblBlcmlvZEtleQMFBF9hbW0FB190cmFkZXIFB193ZWVrSWQED2xhc3ROb3Rpb25hbEtleQkBEmdldExhc3ROb3Rpb25hbEtleQIFBF9hbW0FB190cmFkZXIEIHRyYWRlckF2ZXJhZ2VOb3Rpb25hbEluUGVyaW9kS2V5CQEjZ2V0VHJhZGVyQXZlcmFnZU5vdGlvbmFsSW5QZXJpb2RLZXkDBQRfYW1tBQdfdHJhZGVyBQdfd2Vla0lkCQDMCAIJAQxJbnRlZ2VyRW50cnkCBRV0b3RhbFNjb3JlSW5QZXJpb2RLZXkFC190b3RhbFNjb3JlCQDMCAIJAQxJbnRlZ2VyRW50cnkCBRZ0cmFkZXJTY29yZUluUGVyaW9kS2V5BQxfdHJhZGVyU2NvcmUJAMwIAgkBDEludGVnZXJFbnRyeQIFD2xhc3ROb3Rpb25hbEtleQUTX3RyYWRlckxhc3ROb3Rpb25hbAkAzAgCCQEMSW50ZWdlckVudHJ5AgUgdHJhZGVyQXZlcmFnZU5vdGlvbmFsSW5QZXJpb2RLZXkFDl90cmFkZXJBdmVyYWdlBQNuaWwBDmdldEZlZURpc2NvdW50AQdfdHJhZGVyBAV0aWVycwkBC2dldEZlZVRpZXJzAAQQY3VtdWxhdGl2ZVZvbHVtZQkBGWdldFRyYWRlckN1bXVsYXRpdmVWb2x1bWUBBQdfdHJhZGVyCgEHZmluZEZlZQIEX2FjYwVfdGllcgQNJHQwMTY0NDUxNjQ4OAUFX3RpZXIEE21pbkN1bXVsYXRpdmVWb2x1bWUIBQ0kdDAxNjQ0NTE2NDg4Al8xBAhkaXNjb3VudAgFDSR0MDE2NDQ1MTY0ODgCXzIDCQBnAgUQY3VtdWxhdGl2ZVZvbHVtZQUTbWluQ3VtdWxhdGl2ZVZvbHVtZQkAzAgCBQhkaXNjb3VudAUDbmlsBQRfYWNjBApyZXN1bHRMaXN0CgACJGwFBXRpZXJzCgACJHMJAJADAQUCJGwKAAUkYWNjMAkAzAgCBQtOT19ESVNDT1VOVAUDbmlsCgEFJGYwXzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAQdmaW5kRmVlAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGYwXzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhNMaXN0IHNpemUgZXhjZWVkcyA1CQEFJGYwXzICCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECBQUkYWNjMAAAAAEAAgADAAQABQkAkQMCBQpyZXN1bHRMaXN0AAAQAWkBCmluaXRpYWxpemUCDF9jb29yZGluYXRvcgdfb3JhY2xlAwkBC2luaXRpYWxpemVkAAkAAgECE0FscmVhZHkgaW5pdGlhbGl6ZWQJAMwIAgkBC1N0cmluZ0VudHJ5AgUUa19jb29yZGluYXRvckFkZHJlc3MFDF9jb29yZGluYXRvcgkAzAgCCQELU3RyaW5nRW50cnkCBQ9rX29yYWNsZUFkZHJlc3MFB19vcmFjbGUJAMwIAgkBDEJvb2xlYW5FbnRyeQIFDWtfaW5pdGlhbGl6ZWQGBQNuaWwBaQEQc2V0T3JhY2xlQWRkcmVzcwEHX29yYWNsZQMDCQEBIQEJAQtpbml0aWFsaXplZAAGCQECIT0CCAUBaQZjYWxsZXIJAQxhZG1pbkFkZHJlc3MACQACAQIjSW52YWxpZCBzZXRPcmFjbGVBZGRyZXNzIHBhcmFtZXRlcnMJAMwIAgkBC1N0cmluZ0VudHJ5AgUPa19vcmFjbGVBZGRyZXNzBQdfb3JhY2xlBQNuaWwBaQEOdmlld19nZXRQZXJpb2QABAZ3ZWVrSWQJAQlnZXRXZWVrSWQBBQRUSU1FBAl3ZWVrU3RhcnQJAQxnZXRXZWVrU3RhcnQBBQZ3ZWVrSWQEB3dlZWtFbmQJAQpnZXRXZWVrRW5kAQUGd2Vla0lkCQACAQkArAICCQCsAgIJAKwCAgkArAICCQCkAwEFCXdlZWtTdGFydAIBLAkApAMBBQd3ZWVrRW5kAgEsCQCkAwEFBFRJTUUBaQEkdmlld19nZXRNYXhBbW91bnRPZkFzc2V0VG9EaXN0cmlidXRlAwRfYW1tCF9hc3NldElkB193ZWVrSWQJAAIBCQCkAwEJAR9nZXRNYXhBbW91bnRPZkFzc2V0VG9EaXN0cmlidXRlAwUEX2FtbQUIX2Fzc2V0SWQFB193ZWVrSWQBaQERdmlld19jbGFpbVJld2FyZHMDB190cmFkZXIIX2Fzc2V0SWQHX3BlcmlvZAkAAgEJAKQDAQkBG3RvdGFsUmV3YXJkRm9yVHJhZGVySW5Bc3NldAMFB190cmFkZXIFCF9hc3NldElkCQDMCAIFB19wZXJpb2QFA25pbAFpAQ92aWV3X2NhbGNSZXdhcmQEB190cmFkZXIEX2FtbQhfYXNzZXRJZAdfcGVyaW9kCQACAQkApAMBCQEecmV3YXJkRm9yVHJhZGVySW5Bc3NldEluUGVyaW9kBAUEX2FtbQUIX2Fzc2V0SWQFB190cmFkZXIFB19wZXJpb2QBaQEUdmlld19jbGFpbUFsbFJld2FyZHMDB190cmFkZXIIX2Fzc2V0SWQIX3BlcmlvZHMEBnJlc3VsdAkBIGNsYWltQWxsUmV3YXJkRm9yUGVyaW9kRm9yVHJhZGVyAwUHX3RyYWRlcgUIX2Fzc2V0SWQFCF9wZXJpb2RzCQACAQkArAICCQCsAgIJAKQDAQgFBnJlc3VsdAJfMQIBLAkApAMBCQEgZ2V0VG90YWxDbGFpbWVkRm9yVHJhZGVyQW5kQXNzZXQCBQdfdHJhZGVyBQhfYXNzZXRJZAFpARJ2aWV3X2Vhcm5lZFJld2FyZHMDBF9hbW0IX2Fzc2V0SWQHX3BlcmlvZAQGcmVzdWx0CQEbcmV3YXJkRm9yQW1tSW5Bc3NldEluUGVyaW9kAwUEX2FtbQUIX2Fzc2V0SWQFB19wZXJpb2QJAAIBCQCkAwEFBnJlc3VsdAFpAQ9jbGFpbUFsbFJld2FyZHMCCF9hc3NldElkCF9wZXJpb2RzBAZ0cmFkZXIJAKUIAQgFAWkGY2FsbGVyAwkBCGNvbnRhaW5zAgUIX3BlcmlvZHMJAKQDAQkBCWdldFdlZWtJZAEFBFRJTUUJAAIBAiZDYW4gbm90IGNsYWltIHJld2FyZHMgZm9yIGN1cnJlbnQgd2VlawQNJHQwMTg5MDcxODk5MAkBIGNsYWltQWxsUmV3YXJkRm9yUGVyaW9kRm9yVHJhZGVyAwUGdHJhZGVyBQhfYXNzZXRJZAUIX3BlcmlvZHMEBmFtb3VudAgFDSR0MDE4OTA3MTg5OTACXzEEBnJlc3VsdAgFDSR0MDE4OTA3MTg5OTACXzIDCQAAAgUGYW1vdW50AAAJAAIBAhBOb3RoaW5nIHRvIGNsYWltBQZyZXN1bHQBaQETc2V0RmVlRGlzY291bnRUaWVycwEKX2Rpc2NvdW50cwMDCQEBIQEJAQtpbml0aWFsaXplZAAGCQECIT0CCAUBaQZjYWxsZXIJAQxhZG1pbkFkZHJlc3MACQACAQIiSW52YWxpZCBzZXRGZWVEaXNjb3VudFRpZXJzIHBhcmFtcwkAzAgCCQELU3RyaW5nRW50cnkCBQprX2ZlZVRpZXJzBQpfZGlzY291bnRzBQNuaWwBaQERYXR0YWNoUmV3YXJkQXNzZXQCCF9hc3NldElkE19tYXhBbW91bnRQZXJQZXJpb2QDAwkBASEBCQELaW5pdGlhbGl6ZWQABgkBAiE9AggFAWkGY2FsbGVyCQEMYWRtaW5BZGRyZXNzAAkAAgECIEludmFsaWQgYXR0YWNoUmV3YXJkQXNzZXQgcGFyYW1zBARhbW1zCQEHZ2V0QW1tcwAEDnJld2FyZEFzc2V0SWRzCQERZ2V0UmV3YXJkQXNzZXRJZHMABBFuZXdSZXdhcmRBc3NldElkcwMJAQ9jb250YWluc0VsZW1lbnQCBQ5yZXdhcmRBc3NldElkcwUIX2Fzc2V0SWQFDnJld2FyZEFzc2V0SWRzCQDNCAIFDnJld2FyZEFzc2V0SWRzBQhfYXNzZXRJZAkAzAgCCQEMSW50ZWdlckVudHJ5AgkBHWdldEFzc2V0TWF4QW1vdW50UGVyUGVyaW9kS2V5AQUIX2Fzc2V0SWQFE19tYXhBbW91bnRQZXJQZXJpb2QJAMwIAgkBC1N0cmluZ0VudHJ5AgUQa19yZXdhcmRBc3NldElkcwkBCWxpc3RUb1N0cgEFEW5ld1Jld2FyZEFzc2V0SWRzBQNuaWwBaQENYXR0YWNoUmV3YXJkcwMEX2FtbQhfYXNzZXRJZAtfcmV3YXJkUmF0ZQMDAwkBASEBCQELaW5pdGlhbGl6ZWQABgkBAiE9AggFAWkGY2FsbGVyCQEMYWRtaW5BZGRyZXNzAAYJAQEhAQkBC2lzV2hpdGVsaXN0AQUEX2FtbQkAAgECHEludmFsaWQgYXR0YWNoUmV3YXJkcyBwYXJhbXMEBGFtbXMJAQdnZXRBbW1zAAQOcmV3YXJkQXNzZXRJZHMJARFnZXRSZXdhcmRBc3NldElkcwAEB25ld0FtbXMDCQEPY29udGFpbnNFbGVtZW50AgUEYW1tcwUEX2FtbQUEYW1tcwkAzQgCBQRhbW1zBQRfYW1tBBFuZXdSZXdhcmRBc3NldElkcwMJAQ9jb250YWluc0VsZW1lbnQCBQ5yZXdhcmRBc3NldElkcwUIX2Fzc2V0SWQFDnJld2FyZEFzc2V0SWRzCQDNCAIFDnJld2FyZEFzc2V0SWRzBQhfYXNzZXRJZAkAzAgCCQEMSW50ZWdlckVudHJ5AgkBE2dldEFtbVJld2FyZFJhdGVLZXkCBQRfYW1tBQhfYXNzZXRJZAULX3Jld2FyZFJhdGUJAMwIAgkBC1N0cmluZ0VudHJ5AgUGa19hbW1zCQEJbGlzdFRvU3RyAQUHbmV3QW1tcwkAzAgCCQELU3RyaW5nRW50cnkCBRBrX3Jld2FyZEFzc2V0SWRzCQEJbGlzdFRvU3RyAQURbmV3UmV3YXJkQXNzZXRJZHMFA25pbAFpAQpub3RpZnlGZWVzAgdfdHJhZGVyBF9mZWUEA2FtbQkApQgBCAUBaQZjYWxsZXIDAwkBASEBCQELaXNXaGl0ZWxpc3QBBQNhbW0GCQEBIQEJAQtpbml0aWFsaXplZAAJAAIBAhlJbnZhbGlkIG5vdGlmeUZlZXMgcGFyYW1zBAlhY3R1YWxGZWUJAQ51c2RuVG9EZWNpbWFscwEFBF9mZWUEBndlZWtJZAkBCWdldFdlZWtJZAEFBFRJTUUJAQ11cGRhdGVBbW1GZWVzBAUDYW1tBQdfdHJhZGVyBQZ3ZWVrSWQFCWFjdHVhbEZlZQFpAQ5ub3RpZnlOb3Rpb25hbAIHX3RyYWRlcglfbm90aW9uYWwEA2FtbQkApQgBCAUBaQZjYWxsZXIDAwkBASEBCQELaXNXaGl0ZWxpc3QBBQNhbW0GCQEBIQEJAQtpbml0aWFsaXplZAAJAAIBAh1JbnZhbGlkIG5vdGlmeU5vdGlvbmFsIHBhcmFtcwQOYWN0dWFsTm90aW9uYWwJAQ51c2RuVG9EZWNpbWFscwEFCV9ub3Rpb25hbAQMbGFzdE5vdGlvbmFsCQEPZ2V0TGFzdE5vdGlvbmFsAgUDYW1tBQdfdHJhZGVyBAZ3ZWVrSWQJAQlnZXRXZWVrSWQBBQRUSU1FBAVkYXlJZAkBCGdldERheUlkAQUEVElNRQQJd2Vla1N0YXJ0CQEMZ2V0V2Vla1N0YXJ0AQUGd2Vla0lkBAd3ZWVrRW5kCQEKZ2V0V2Vla0VuZAEFBndlZWtJZAQBdAkAZQIFB3dlZWtFbmQFCXdlZWtTdGFydAQRb2xkUnVubmluZ0F2ZXJhZ2UJASBnZXRUcmFkZXJBdmVyYWdlTm90aW9uYWxJblBlcmlvZAQFA2FtbQUHX3RyYWRlcgUGd2Vla0lkBQxsYXN0Tm90aW9uYWwEAXcJAQRkaXZkAgkAZQIFB3dlZWtFbmQFBFRJTUUFAXQEEW9sZFRyYWRlckFtbVNjb3JlCQEWZ2V0VHJhZGVyU2NvcmVJblBlcmlvZAMFA2FtbQUHX3RyYWRlcgUGd2Vla0lkBBBvbGRUb3RhbEFtbVNjb3JlCQEVZ2V0VG90YWxTY29yZUluUGVyaW9kAgUDYW1tBQZ3ZWVrSWQEBGZlZXMJAQ9nZXRGZWVzSW5QZXJpb2QDBQNhbW0FB190cmFkZXIFBndlZWtJZAQRbmV3UnVubmluZ0F2ZXJhZ2UJAGUCCQBkAgURb2xkUnVubmluZ0F2ZXJhZ2UJAQRtdWxkAgUOYWN0dWFsTm90aW9uYWwFAXcJAQRtdWxkAgUMbGFzdE5vdGlvbmFsBQF3BBFuZXdUcmFkZXJBbW1TY29yZQkBBG11bGQCCQEEcG93ZAIFBGZlZXMFAUEJAQRwb3dkAgURbmV3UnVubmluZ0F2ZXJhZ2UJAGUCBQxERUNJTUFMX1VOSVQFAUEEGG5ld1RvdGFsQW1tU2NvcmVJblBlcmlvZAkAZAIJAGUCBRBvbGRUb3RhbEFtbVNjb3JlBRFvbGRUcmFkZXJBbW1TY29yZQURbmV3VHJhZGVyQW1tU2NvcmUJAM4IAgkBDXVwZGF0ZUFtbURhdGEHBQNhbW0FB190cmFkZXIFBndlZWtJZAURbmV3UnVubmluZ0F2ZXJhZ2UFDmFjdHVhbE5vdGlvbmFsBRFuZXdUcmFkZXJBbW1TY29yZQUYbmV3VG90YWxBbW1TY29yZUluUGVyaW9kCQESdXBkYXRlVHJhZGVyVm9sdW1lAwUHX3RyYWRlcgUFZGF5SWQJAQNhYnMBCQBlAgUMbGFzdE5vdGlvbmFsBQ5hY3R1YWxOb3Rpb25hbAFpARJjb21wdXRlRmVlRGlzY291bnQBB190cmFkZXIEBnJlc3VsdAkBDmdldEZlZURpc2NvdW50AQUHX3RyYWRlcgkAlAoCBQNuaWwFBnJlc3VsdAFpARd2aWV3X2NvbXB1dGVGZWVEaXNjb3VudAEHX3RyYWRlcgQGcmVzdWx0CQEOZ2V0RmVlRGlzY291bnQBBQdfdHJhZGVyCQACAQkApAMBBQZyZXN1bHQBAnR4AQZ2ZXJpZnkACQD0AwMIBQJ0eAlib2R5Qnl0ZXMJAJEDAggFAnR4BnByb29mcwAACQEOYWRtaW5QdWJsaWNLZXkA3++/jg==", "height": 2320226, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: EDrsrCohnbqjcYv1twZd3muUK2gx5Mm9sA5ifkbWPa1e Next: DXj6csFNKmpdJqa7tq74Av6XU1rjhv83vKH4USbxesXU Diff:
OldNewDifferences
66 let k_totalAssetFeesInPeriod = "k_totalAssetFeesInPeriod"
77
88 let k_traderFeesInPeriod = "k_traderFeesInPeriod"
9+
10+let k_traderVolume = "k_traderVolume"
11+
12+let k_traderCumulativeVolume = "k_traderCumulativeVolume"
13+
14+let k_feeTiers = "k_feeTiers"
915
1016 let k_lastNotional = "k_lastNotional"
1117
5258 let A = 70000000
5359
5460 let MS_IN_WEEK = (1000 * 604800)
61+
62+let MS_IN_DAY = (1000 * 86400)
63+
64+let NO_DISCOUNT = (DECIMAL_UNIT / 100)
5565
5666 func listToStr (_list) = {
5767 func _join (accumulator,val) = ((accumulator + val) + ",")
133143
134144 let TIME = lastBlock.timestamp
135145
146+func getTraderVolumeKey (_trader,_dayId) = ((((k_traderVolume + "_") + _trader) + "_") + toString(_dayId))
147+
148+
149+func getTraderCumulativeVolumeKey (_trader) = ((k_traderCumulativeVolume + "_") + _trader)
150+
151+
136152 func getTraderFeesInPeriodKey (_amm,_trader,_weekId) = ((((((k_traderFeesInPeriod + "_") + _amm) + "_") + _trader) + "_") + toString(_weekId))
137153
138154
182198
183199
184200 func getWeekId (_ts) = (_ts / MS_IN_WEEK)
201+
202+
203+func getDayId (_ts) = (_ts / MS_IN_DAY)
204+
205+
206+func getFeeTiers () = {
207+ let storedTiers = valueOrElse(getString(this, k_feeTiers), "")
208+ if ((storedTiers == ""))
209+ then nil
210+ else {
211+ let tiers = split(valueOrElse(getString(this, k_feeTiers), ""), ",")
212+ func toFeeTier (_acc,_tier) = {
213+ let tierSplit = split(_tier, ":")
214+ let minCumulativeVolume = parseIntValue(tierSplit[0])
215+ let discount = parseIntValue(tierSplit[1])
216+ (_acc :+ $Tuple2(minCumulativeVolume, discount))
217+ }
218+
219+ let $l = tiers
220+ let $s = size($l)
221+ let $acc0 = nil
222+ func $f0_1 ($a,$i) = if (($i >= $s))
223+ then $a
224+ else toFeeTier($a, $l[$i])
225+
226+ func $f0_2 ($a,$i) = if (($i >= $s))
227+ then $a
228+ else throw("List size exceeds 10")
229+
230+ $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
231+ }
232+ }
233+
234+
235+func getTraderVolume (_trader,_dayId) = {
236+ let key = getTraderVolumeKey(_trader, _dayId)
237+ valueOrElse(getInteger(this, key), 0)
238+ }
239+
240+
241+func getTraderCumulativeVolume (_trader) = {
242+ let key = getTraderCumulativeVolumeKey(_trader)
243+ valueOrElse(getInteger(this, key), 0)
244+ }
185245
186246
187247 func getFeesInPeriod (_amm,_trader,_weekId) = {
283343 let traderShareInRewards = divd(muld(actualTotalAssetToDistribute, traderScore), totalTraderScore)
284344 traderShareInRewards
285345 }
346+ }
347+ }
348+
349+
350+func rewardForAmmInAssetInPeriod (_amm,_assetId,_weekId) = {
351+ let rewardAssetRate = getAmmRewardRate(_amm, _assetId)
352+ if ((rewardAssetRate == 0))
353+ then 0
354+ else {
355+ let totalFeesInPeriod = getTotalFeesInPeriod(_amm, _weekId)
356+ let rewardAssetPrice = getRewardAssetPrice(_assetId, _weekId)
357+ let maxAmountOfAssetToDistribute = getMaxAmountOfAssetToDistribute(_amm, _assetId, _weekId)
358+ let totalAssetToDistribute = divd(muld(totalFeesInPeriod, rewardAssetRate), rewardAssetPrice)
359+ let actualTotalAssetToDistribute = minv(totalAssetToDistribute, maxAmountOfAssetToDistribute)
360+ actualTotalAssetToDistribute
286361 }
287362 }
288363
391466 }
392467
393468
469+func updateTraderVolume (_trader,_dayId,_generatedVolume) = {
470+ let actualDayVolume = (getTraderVolume(_trader, _dayId) + _generatedVolume)
471+ let daysBefore = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30]
472+ func updateCumulativeVolume (_acc,_minusDay) = (_acc + getTraderVolume(_trader, (_dayId - _minusDay)))
473+
474+ let cumulativeVolume = {
475+ let $l = daysBefore
476+ let $s = size($l)
477+ let $acc0 = 0
478+ func $f0_1 ($a,$i) = if (($i >= $s))
479+ then $a
480+ else updateCumulativeVolume($a, $l[$i])
481+
482+ func $f0_2 ($a,$i) = if (($i >= $s))
483+ then $a
484+ else throw("List size exceeds 30")
485+
486+ $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10), 11), 12), 13), 14), 15), 16), 17), 18), 19), 20), 21), 22), 23), 24), 25), 26), 27), 28), 29), 30)
487+ }
488+[IntegerEntry(getTraderVolumeKey(_trader, _dayId), actualDayVolume), IntegerEntry(getTraderCumulativeVolumeKey(_trader), (cumulativeVolume + actualDayVolume))]
489+ }
490+
491+
394492 func updateAmmFees (_amm,_trader,_weekId,_actualFee) = {
395493 let traderFeesKey = getTraderFeesInPeriodKey(_amm, _trader, _weekId)
396494 let totalFeesKey = getTotalAmmFeesInPeriodKey(_amm, _weekId)
433531 let lastNotionalKey = getLastNotionalKey(_amm, _trader)
434532 let traderAverageNotionalInPeriodKey = getTraderAverageNotionalInPeriodKey(_amm, _trader, _weekId)
435533 [IntegerEntry(totalScoreInPeriodKey, _totalScore), IntegerEntry(traderScoreInPeriodKey, _traderScore), IntegerEntry(lastNotionalKey, _traderLastNotional), IntegerEntry(traderAverageNotionalInPeriodKey, _traderAverage)]
534+ }
535+
536+
537+func getFeeDiscount (_trader) = {
538+ let tiers = getFeeTiers()
539+ let cumulativeVolume = getTraderCumulativeVolume(_trader)
540+ func findFee (_acc,_tier) = {
541+ let $t01644516488 = _tier
542+ let minCumulativeVolume = $t01644516488._1
543+ let discount = $t01644516488._2
544+ if ((cumulativeVolume >= minCumulativeVolume))
545+ then [discount]
546+ else _acc
547+ }
548+
549+ let resultList = {
550+ let $l = tiers
551+ let $s = size($l)
552+ let $acc0 = [NO_DISCOUNT]
553+ func $f0_1 ($a,$i) = if (($i >= $s))
554+ then $a
555+ else findFee($a, $l[$i])
556+
557+ func $f0_2 ($a,$i) = if (($i >= $s))
558+ then $a
559+ else throw("List size exceeds 5")
560+
561+ $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5)
562+ }
563+resultList[0]
436564 }
437565
438566
486614
487615
488616 @Callable(i)
617+func view_earnedRewards (_amm,_assetId,_period) = {
618+ let result = rewardForAmmInAssetInPeriod(_amm, _assetId, _period)
619+ throw(toString(result))
620+ }
621+
622+
623+
624+@Callable(i)
489625 func claimAllRewards (_assetId,_periods) = {
490626 let trader = toString(i.caller)
491627 if (contains(_periods, toString(getWeekId(TIME))))
492628 then throw("Can not claim rewards for current week")
493629 else {
494- let $t01543815521 = claimAllRewardForPeriodForTrader(trader, _assetId, _periods)
495- let amount = $t01543815521._1
496- let result = $t01543815521._2
630+ let $t01890718990 = claimAllRewardForPeriodForTrader(trader, _assetId, _periods)
631+ let amount = $t01890718990._1
632+ let result = $t01890718990._2
497633 if ((amount == 0))
498634 then throw("Nothing to claim")
499635 else result
500636 }
501637 }
638+
639+
640+
641+@Callable(i)
642+func setFeeDiscountTiers (_discounts) = if (if (!(initialized()))
643+ then true
644+ else (i.caller != adminAddress()))
645+ then throw("Invalid setFeeDiscountTiers params")
646+ else [StringEntry(k_feeTiers, _discounts)]
502647
503648
504649
566711 let actualNotional = usdnToDecimals(_notional)
567712 let lastNotional = getLastNotional(amm, _trader)
568713 let weekId = getWeekId(TIME)
714+ let dayId = getDayId(TIME)
569715 let weekStart = getWeekStart(weekId)
570716 let weekEnd = getWeekEnd(weekId)
571717 let t = (weekEnd - weekStart)
577723 let newRunningAverage = ((oldRunningAverage + muld(actualNotional, w)) - muld(lastNotional, w))
578724 let newTraderAmmScore = muld(powd(fees, A), powd(newRunningAverage, (DECIMAL_UNIT - A)))
579725 let newTotalAmmScoreInPeriod = ((oldTotalAmmScore - oldTraderAmmScore) + newTraderAmmScore)
580- updateAmmData(amm, _trader, weekId, newRunningAverage, actualNotional, newTraderAmmScore, newTotalAmmScoreInPeriod)
726+ (updateAmmData(amm, _trader, weekId, newRunningAverage, actualNotional, newTraderAmmScore, newTotalAmmScoreInPeriod) ++ updateTraderVolume(_trader, dayId, abs((lastNotional - actualNotional))))
581727 }
728+ }
729+
730+
731+
732+@Callable(i)
733+func computeFeeDiscount (_trader) = {
734+ let result = getFeeDiscount(_trader)
735+ $Tuple2(nil, result)
736+ }
737+
738+
739+
740+@Callable(i)
741+func view_computeFeeDiscount (_trader) = {
742+ let result = getFeeDiscount(_trader)
743+ throw(toString(result))
582744 }
583745
584746
Full:
OldNewDifferences
11 {-# STDLIB_VERSION 6 #-}
22 {-# SCRIPT_TYPE ACCOUNT #-}
33 {-# CONTENT_TYPE DAPP #-}
44 let k_totalFeesInPeriod = "k_totalFeesInPeriod"
55
66 let k_totalAssetFeesInPeriod = "k_totalAssetFeesInPeriod"
77
88 let k_traderFeesInPeriod = "k_traderFeesInPeriod"
9+
10+let k_traderVolume = "k_traderVolume"
11+
12+let k_traderCumulativeVolume = "k_traderCumulativeVolume"
13+
14+let k_feeTiers = "k_feeTiers"
915
1016 let k_lastNotional = "k_lastNotional"
1117
1218 let k_totalScoreInPeriod = "k_totalScoreInPeriod"
1319
1420 let k_traderScoreInPeriod = "k_traderScoreInPeriod"
1521
1622 let k_traderAverageNotionalInPeriod = "k_traderAverageNotionalInPeriod"
1723
1824 let k_ammRewardRate = "k_ammRewardRate"
1925
2026 let k_assetMaxAmountPerPeriod = "k_assetMaxAmountPerPeriod"
2127
2228 let k_rewardAssetIds = "k_rewardAssetIds"
2329
2430 let k_amms = "k_amms"
2531
2632 let k_claimedAssetAndPeriod = "k_claimedAssetAndPeriod"
2733
2834 let k_oracleAddress = "k_oracleAddress"
2935
3036 let k_oraclePrice = "price"
3137
3238 let k_totalClaimedForTraderAndAsset = "k_totalClaimedForTraderAndAsset"
3339
3440 let k_ammMaxAmountPerPeriod = "k_ammMaxAmountPerPeriod"
3541
3642 let k_initialized = "k_initialized"
3743
3844 let k_coordinatorAddress = "k_coordinatorAddress"
3945
4046 let k_governance_asset = "k_gov_asset"
4147
4248 let k_quote_asset = "k_quote_asset"
4349
4450 let k_admin_public_key = "k_admin_public_key"
4551
4652 let k_admin_address = "k_admin_address"
4753
4854 let k_amm = "k_amm"
4955
5056 let DECIMAL_UNIT = (1 * (((((((10 * 10) * 10) * 10) * 10) * 10) * 10) * 10))
5157
5258 let A = 70000000
5359
5460 let MS_IN_WEEK = (1000 * 604800)
61+
62+let MS_IN_DAY = (1000 * 86400)
63+
64+let NO_DISCOUNT = (DECIMAL_UNIT / 100)
5565
5666 func listToStr (_list) = {
5767 func _join (accumulator,val) = ((accumulator + val) + ",")
5868
5969 let newListStr = {
6070 let $l = _list
6171 let $s = size($l)
6272 let $acc0 = ""
6373 func $f0_1 ($a,$i) = if (($i >= $s))
6474 then $a
6575 else _join($a, $l[$i])
6676
6777 func $f0_2 ($a,$i) = if (($i >= $s))
6878 then $a
6979 else throw("List size exceeds 100")
7080
7181 $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10), 11), 12), 13), 14), 15), 16), 17), 18), 19), 20), 21), 22), 23), 24), 25), 26), 27), 28), 29), 30), 31), 32), 33), 34), 35), 36), 37), 38), 39), 40), 41), 42), 43), 44), 45), 46), 47), 48), 49), 50), 51), 52), 53), 54), 55), 56), 57), 58), 59), 60), 61), 62), 63), 64), 65), 66), 67), 68), 69), 70), 71), 72), 73), 74), 75), 76), 77), 78), 79), 80), 81), 82), 83), 84), 85), 86), 87), 88), 89), 90), 91), 92), 93), 94), 95), 96), 97), 98), 99), 100)
7282 }
7383 let newListStrU = dropRight(newListStr, 1)
7484 let newListStrR = if ((take(newListStrU, 1) == ","))
7585 then drop(newListStrU, 1)
7686 else newListStrU
7787 newListStrR
7888 }
7989
8090
8191 func strToList (_str) = if ((_str == ""))
8292 then nil
8393 else split(_str, ",")
8494
8595
8696 func divd (_x,_y) = fraction(_x, DECIMAL_UNIT, _y, HALFEVEN)
8797
8898
8999 func muld (_x,_y) = fraction(_x, _y, DECIMAL_UNIT, HALFEVEN)
90100
91101
92102 func powd (_x,_y) = pow(_x, 8, _y, 8, 8, HALFEVEN)
93103
94104
95105 func abs (_x) = if ((_x > 0))
96106 then _x
97107 else -(_x)
98108
99109
100110 func minv (_x,_y) = if ((_x > _y))
101111 then _y
102112 else _x
103113
104114
105115 func toCompositeKey (_key,_address) = ((_key + "_") + _address)
106116
107117
108118 let that = this
109119
110120 func coordinator () = valueOrErrorMessage(addressFromString(getStringValue(that, k_coordinatorAddress)), "Coordinator not set")
111121
112122
113123 func adminPublicKey () = fromBase58String(getStringValue(coordinator(), k_admin_public_key))
114124
115125
116126 func adminAddress () = addressFromString(getStringValue(coordinator(), k_admin_address))
117127
118128
119129 func isWhitelist (_address) = valueOrElse(getBoolean(coordinator(), toCompositeKey(k_amm, _address)), false)
120130
121131
122132 func int (k) = valueOrErrorMessage(getInteger(that, k), ("no value for " + k))
123133
124134
125135 func int0 (k) = valueOrElse(getInteger(that, k), 0)
126136
127137
128138 func initialized () = valueOrElse(getBoolean(that, k_initialized), false)
129139
130140
131141 func getRewardAssetIds () = strToList(valueOrElse(getString(that, k_rewardAssetIds), ""))
132142
133143
134144 let TIME = lastBlock.timestamp
135145
146+func getTraderVolumeKey (_trader,_dayId) = ((((k_traderVolume + "_") + _trader) + "_") + toString(_dayId))
147+
148+
149+func getTraderCumulativeVolumeKey (_trader) = ((k_traderCumulativeVolume + "_") + _trader)
150+
151+
136152 func getTraderFeesInPeriodKey (_amm,_trader,_weekId) = ((((((k_traderFeesInPeriod + "_") + _amm) + "_") + _trader) + "_") + toString(_weekId))
137153
138154
139155 func getTotalAmmFeesInPeriodKey (_amm,_weekId) = ((((k_totalFeesInPeriod + "_") + _amm) + "_") + toString(_weekId))
140156
141157
142158 func getTotalAssetFeesInPeriodKey (_assetId,_weekId) = ((((k_totalAssetFeesInPeriod + "_") + _assetId) + "_") + toString(_weekId))
143159
144160
145161 func getLastNotionalKey (_amm,_trader) = ((((k_lastNotional + "_") + _amm) + "_") + _trader)
146162
147163
148164 func getTraderScoreInPeriodKey (_amm,_trader,_weekId) = ((((((k_traderScoreInPeriod + "_") + _amm) + "_") + _trader) + "_") + toString(_weekId))
149165
150166
151167 func getTotalScoreInPeriodKey (_amm,_weekId) = ((((k_totalScoreInPeriod + "_") + _amm) + "_") + toString(_weekId))
152168
153169
154170 func getTraderAverageNotionalInPeriodKey (_amm,_trader,_weekId) = ((((((k_traderAverageNotionalInPeriod + "_") + _amm) + "_") + _trader) + "_") + toString(_weekId))
155171
156172
157173 func getAmmRewardRateKey (_amm,_assetId) = ((((k_ammRewardRate + "_") + _amm) + "_") + _assetId)
158174
159175
160176 func getAssetMaxAmountPerPeriodKey (_assetId) = ((k_assetMaxAmountPerPeriod + "_") + _assetId)
161177
162178
163179 func getClaimedTraderAssetPeriodKey (_trader,_assetId,_period) = ((((((k_claimedAssetAndPeriod + "_") + _trader) + "_") + _assetId) + "_") + toString(_period))
164180
165181
166182 func getOraclePriceKey (_assetId,_period) = ((((k_oraclePrice + "_") + toString(_period)) + "_") + _assetId)
167183
168184
169185 func getTotalClaimedForTraderAndAssetKey (_trader,_assetId) = ((((k_totalClaimedForTraderAndAsset + "_") + _trader) + "_") + _assetId)
170186
171187
172188 func getAmmMaxAmountPerPeriodKey (_amm,_assetId) = ((((k_ammMaxAmountPerPeriod + "_") + _amm) + "_") + _assetId)
173189
174190
175191 func usdnToDecimals (_amount) = (_amount * 100)
176192
177193
178194 func getWeekStart (_weekId) = (_weekId * MS_IN_WEEK)
179195
180196
181197 func getWeekEnd (_weekId) = ((_weekId + 1) * MS_IN_WEEK)
182198
183199
184200 func getWeekId (_ts) = (_ts / MS_IN_WEEK)
201+
202+
203+func getDayId (_ts) = (_ts / MS_IN_DAY)
204+
205+
206+func getFeeTiers () = {
207+ let storedTiers = valueOrElse(getString(this, k_feeTiers), "")
208+ if ((storedTiers == ""))
209+ then nil
210+ else {
211+ let tiers = split(valueOrElse(getString(this, k_feeTiers), ""), ",")
212+ func toFeeTier (_acc,_tier) = {
213+ let tierSplit = split(_tier, ":")
214+ let minCumulativeVolume = parseIntValue(tierSplit[0])
215+ let discount = parseIntValue(tierSplit[1])
216+ (_acc :+ $Tuple2(minCumulativeVolume, discount))
217+ }
218+
219+ let $l = tiers
220+ let $s = size($l)
221+ let $acc0 = nil
222+ func $f0_1 ($a,$i) = if (($i >= $s))
223+ then $a
224+ else toFeeTier($a, $l[$i])
225+
226+ func $f0_2 ($a,$i) = if (($i >= $s))
227+ then $a
228+ else throw("List size exceeds 10")
229+
230+ $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
231+ }
232+ }
233+
234+
235+func getTraderVolume (_trader,_dayId) = {
236+ let key = getTraderVolumeKey(_trader, _dayId)
237+ valueOrElse(getInteger(this, key), 0)
238+ }
239+
240+
241+func getTraderCumulativeVolume (_trader) = {
242+ let key = getTraderCumulativeVolumeKey(_trader)
243+ valueOrElse(getInteger(this, key), 0)
244+ }
185245
186246
187247 func getFeesInPeriod (_amm,_trader,_weekId) = {
188248 let key = getTraderFeesInPeriodKey(_amm, _trader, _weekId)
189249 int0(key)
190250 }
191251
192252
193253 func getTotalFeesInPeriod (_amm,_weekId) = {
194254 let key = getTotalAmmFeesInPeriodKey(_amm, _weekId)
195255 int0(key)
196256 }
197257
198258
199259 func getTotalAssetFeesInPeriod (_assetId,_weekId) = {
200260 let key = getTotalAssetFeesInPeriodKey(_assetId, _weekId)
201261 int0(key)
202262 }
203263
204264
205265 func getLastNotional (_amm,_trader) = {
206266 let key = getLastNotionalKey(_amm, _trader)
207267 int0(key)
208268 }
209269
210270
211271 func getTraderScoreInPeriod (_amm,_trader,_weekId) = {
212272 let key = getTraderScoreInPeriodKey(_amm, _trader, _weekId)
213273 int0(key)
214274 }
215275
216276
217277 func getTotalScoreInPeriod (_amm,_weekId) = {
218278 let key = getTotalScoreInPeriodKey(_amm, _weekId)
219279 int0(key)
220280 }
221281
222282
223283 func getAmms () = strToList(valueOrElse(getString(that, k_amms), ""))
224284
225285
226286 func getAmmRewardRate (_amm,_assetId) = {
227287 let key = getAmmRewardRateKey(_amm, _assetId)
228288 int0(key)
229289 }
230290
231291
232292 func getAssetMaxAmountPerPeriod (_assetId) = {
233293 let key = getAssetMaxAmountPerPeriodKey(_assetId)
234294 int0(key)
235295 }
236296
237297
238298 func getTotalClaimedForTraderAndAsset (_trader,_assetId) = {
239299 let key = getTotalClaimedForTraderAndAssetKey(_trader, _assetId)
240300 int0(key)
241301 }
242302
243303
244304 func getRewardAssetPrice (_assetId,_weekId) = {
245305 let oracleAddressStr = valueOrErrorMessage(getString(that, k_oracleAddress), "Oracle not set")
246306 let oracleAddress = valueOrErrorMessage(addressFromString(oracleAddressStr), "Invalid oracle address")
247307 let priceKey = getOraclePriceKey(_assetId, _weekId)
248308 usdnToDecimals(valueOrErrorMessage(getInteger(oracleAddress, priceKey), ((("No oracle price for asset " + _assetId) + " period ") + toString(_weekId))))
249309 }
250310
251311
252312 func getMaxAmountOfAssetToDistribute (_amm,_assetId,_weekId) = {
253313 let totalFeesInPeriod = getTotalFeesInPeriod(_amm, _weekId)
254314 let totalAssetFeesInPeriod = getTotalAssetFeesInPeriod(_assetId, _weekId)
255315 if ((totalAssetFeesInPeriod == 0))
256316 then {
257317 let key = getAmmMaxAmountPerPeriodKey(_amm, _assetId)
258318 int0(key)
259319 }
260320 else {
261321 let maxAmountOfAsset = getAssetMaxAmountPerPeriod(_assetId)
262322 let maxAmountOfAssetToDistribute = muld(divd(totalFeesInPeriod, totalAssetFeesInPeriod), maxAmountOfAsset)
263323 maxAmountOfAssetToDistribute
264324 }
265325 }
266326
267327
268328 func rewardForTraderInAssetInPeriod (_amm,_trader,_assetId,_weekId) = {
269329 let rewardAssetRate = getAmmRewardRate(_amm, _assetId)
270330 if ((rewardAssetRate == 0))
271331 then 0
272332 else {
273333 let totalFeesInPeriod = getTotalFeesInPeriod(_amm, _weekId)
274334 let rewardAssetPrice = getRewardAssetPrice(_assetId, _weekId)
275335 let maxAmountOfAssetToDistribute = getMaxAmountOfAssetToDistribute(_amm, _assetId, _weekId)
276336 let traderScore = getTraderScoreInPeriod(_amm, _trader, _weekId)
277337 let totalTraderScore = getTotalScoreInPeriod(_amm, _weekId)
278338 if ((totalTraderScore == 0))
279339 then 0
280340 else {
281341 let totalAssetToDistribute = divd(muld(totalFeesInPeriod, rewardAssetRate), rewardAssetPrice)
282342 let actualTotalAssetToDistribute = minv(totalAssetToDistribute, maxAmountOfAssetToDistribute)
283343 let traderShareInRewards = divd(muld(actualTotalAssetToDistribute, traderScore), totalTraderScore)
284344 traderShareInRewards
285345 }
346+ }
347+ }
348+
349+
350+func rewardForAmmInAssetInPeriod (_amm,_assetId,_weekId) = {
351+ let rewardAssetRate = getAmmRewardRate(_amm, _assetId)
352+ if ((rewardAssetRate == 0))
353+ then 0
354+ else {
355+ let totalFeesInPeriod = getTotalFeesInPeriod(_amm, _weekId)
356+ let rewardAssetPrice = getRewardAssetPrice(_assetId, _weekId)
357+ let maxAmountOfAssetToDistribute = getMaxAmountOfAssetToDistribute(_amm, _assetId, _weekId)
358+ let totalAssetToDistribute = divd(muld(totalFeesInPeriod, rewardAssetRate), rewardAssetPrice)
359+ let actualTotalAssetToDistribute = minv(totalAssetToDistribute, maxAmountOfAssetToDistribute)
360+ actualTotalAssetToDistribute
286361 }
287362 }
288363
289364
290365 func totalRewardForTraderInAssetInPeriod (_trader,_assetId,_weekId) = {
291366 let amms = getAmms()
292367 func compute (_acc,_amm) = (_acc + rewardForTraderInAssetInPeriod(_amm, _trader, _assetId, _weekId))
293368
294369 let $l = amms
295370 let $s = size($l)
296371 let $acc0 = 0
297372 func $f0_1 ($a,$i) = if (($i >= $s))
298373 then $a
299374 else compute($a, $l[$i])
300375
301376 func $f0_2 ($a,$i) = if (($i >= $s))
302377 then $a
303378 else throw("List size exceeds 20")
304379
305380 $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10), 11), 12), 13), 14), 15), 16), 17), 18), 19), 20)
306381 }
307382
308383
309384 func totalRewardForTraderInAsset (_trader,_assetId,_periods) = {
310385 func compute (_acc,_weekId) = (_acc + totalRewardForTraderInAssetInPeriod(_trader, _assetId, _weekId))
311386
312387 let $l = _periods
313388 let $s = size($l)
314389 let $acc0 = 0
315390 func $f0_1 ($a,$i) = if (($i >= $s))
316391 then $a
317392 else compute($a, $l[$i])
318393
319394 func $f0_2 ($a,$i) = if (($i >= $s))
320395 then $a
321396 else throw("List size exceeds 12")
322397
323398 $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10), 11), 12)
324399 }
325400
326401
327402 func getTraderAverageNotionalInPeriod (_amm,_trader,_weekId,_defaultValue) = {
328403 let key = getTraderAverageNotionalInPeriodKey(_amm, _trader, _weekId)
329404 valueOrElse(getInteger(that, key), _defaultValue)
330405 }
331406
332407
333408 func isClaimed (_trader,_assetId,_period) = {
334409 let key = getClaimedTraderAssetPeriodKey(_trader, _assetId, _period)
335410 valueOrElse(getBoolean(that, key), false)
336411 }
337412
338413
339414 func adjust (_amount,_assetId) = {
340415 let asset = valueOrErrorMessage(assetInfo(fromBase58String(_assetId)), "Invalid asset id")
341416 let decimals = asset.decimals
342417 if ((decimals == 6))
343418 then (_amount / 100)
344419 else _amount
345420 }
346421
347422
348423 func claimAllRewardForPeriodForTrader (_trader,_assetId,_periods) = {
349424 let periods = strToList(_periods)
350425 func checkAndFilterFn (_acc,_next) = {
351426 let period = valueOrErrorMessage(parseInt(_next), ("Invalid period: " + _next))
352427 if (if (containsElement(_acc, period))
353428 then true
354429 else isClaimed(_trader, _assetId, period))
355430 then _acc
356431 else (_acc :+ period)
357432 }
358433
359434 let validPeriods = {
360435 let $l = periods
361436 let $s = size($l)
362437 let $acc0 = nil
363438 func $f0_1 ($a,$i) = if (($i >= $s))
364439 then $a
365440 else checkAndFilterFn($a, $l[$i])
366441
367442 func $f0_2 ($a,$i) = if (($i >= $s))
368443 then $a
369444 else throw("List size exceeds 12")
370445
371446 $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10), 11), 12)
372447 }
373448 func markPeriodAsDoneFn (_acc,_period) = (_acc :+ BooleanEntry(getClaimedTraderAssetPeriodKey(_trader, _assetId, _period), true))
374449
375450 let markPeriodsAsClaimed = {
376451 let $l = validPeriods
377452 let $s = size($l)
378453 let $acc0 = nil
379454 func $f1_1 ($a,$i) = if (($i >= $s))
380455 then $a
381456 else markPeriodAsDoneFn($a, $l[$i])
382457
383458 func $f1_2 ($a,$i) = if (($i >= $s))
384459 then $a
385460 else throw("List size exceeds 16")
386461
387462 $f1_2($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10), 11), 12), 13), 14), 15), 16)
388463 }
389464 let amount = totalRewardForTraderInAsset(_trader, _assetId, validPeriods)
390465 $Tuple2(amount, ([ScriptTransfer(addressFromStringValue(_trader), adjust(amount, _assetId), fromBase58String(_assetId)), IntegerEntry(getTotalClaimedForTraderAndAssetKey(_trader, _assetId), (getTotalClaimedForTraderAndAsset(_trader, _assetId) + amount))] ++ markPeriodsAsClaimed))
391466 }
392467
393468
469+func updateTraderVolume (_trader,_dayId,_generatedVolume) = {
470+ let actualDayVolume = (getTraderVolume(_trader, _dayId) + _generatedVolume)
471+ let daysBefore = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30]
472+ func updateCumulativeVolume (_acc,_minusDay) = (_acc + getTraderVolume(_trader, (_dayId - _minusDay)))
473+
474+ let cumulativeVolume = {
475+ let $l = daysBefore
476+ let $s = size($l)
477+ let $acc0 = 0
478+ func $f0_1 ($a,$i) = if (($i >= $s))
479+ then $a
480+ else updateCumulativeVolume($a, $l[$i])
481+
482+ func $f0_2 ($a,$i) = if (($i >= $s))
483+ then $a
484+ else throw("List size exceeds 30")
485+
486+ $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10), 11), 12), 13), 14), 15), 16), 17), 18), 19), 20), 21), 22), 23), 24), 25), 26), 27), 28), 29), 30)
487+ }
488+[IntegerEntry(getTraderVolumeKey(_trader, _dayId), actualDayVolume), IntegerEntry(getTraderCumulativeVolumeKey(_trader), (cumulativeVolume + actualDayVolume))]
489+ }
490+
491+
394492 func updateAmmFees (_amm,_trader,_weekId,_actualFee) = {
395493 let traderFeesKey = getTraderFeesInPeriodKey(_amm, _trader, _weekId)
396494 let totalFeesKey = getTotalAmmFeesInPeriodKey(_amm, _weekId)
397495 let rewardAssets = getRewardAssetIds()
398496 let feesInPeriod = getFeesInPeriod(_amm, _trader, _weekId)
399497 let totalFeesInPeriod = getTotalFeesInPeriod(_amm, _weekId)
400498 let newFeesInPeriod = (feesInPeriod + _actualFee)
401499 let newTotalFeesInPeriod = (totalFeesInPeriod + _actualFee)
402500 func doHandleRewardAssetId (_acc,_assetId) = {
403501 let key = getAmmRewardRateKey(_amm, _assetId)
404502 if ((int0(key) > 0))
405503 then {
406504 let totalAssetFeesKey = getTotalAssetFeesInPeriodKey(_assetId, _weekId)
407505 (_acc :+ IntegerEntry(totalAssetFeesKey, (getTotalAssetFeesInPeriod(_assetId, _weekId) + _actualFee)))
408506 }
409507 else _acc
410508 }
411509
412510 let updateAssetFees = {
413511 let $l = rewardAssets
414512 let $s = size($l)
415513 let $acc0 = nil
416514 func $f0_1 ($a,$i) = if (($i >= $s))
417515 then $a
418516 else doHandleRewardAssetId($a, $l[$i])
419517
420518 func $f0_2 ($a,$i) = if (($i >= $s))
421519 then $a
422520 else throw("List size exceeds 10")
423521
424522 $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
425523 }
426524 ([IntegerEntry(traderFeesKey, newFeesInPeriod), IntegerEntry(totalFeesKey, newTotalFeesInPeriod)] ++ updateAssetFees)
427525 }
428526
429527
430528 func updateAmmData (_amm,_trader,_weekId,_traderAverage,_traderLastNotional,_traderScore,_totalScore) = {
431529 let totalScoreInPeriodKey = getTotalScoreInPeriodKey(_amm, _weekId)
432530 let traderScoreInPeriodKey = getTraderScoreInPeriodKey(_amm, _trader, _weekId)
433531 let lastNotionalKey = getLastNotionalKey(_amm, _trader)
434532 let traderAverageNotionalInPeriodKey = getTraderAverageNotionalInPeriodKey(_amm, _trader, _weekId)
435533 [IntegerEntry(totalScoreInPeriodKey, _totalScore), IntegerEntry(traderScoreInPeriodKey, _traderScore), IntegerEntry(lastNotionalKey, _traderLastNotional), IntegerEntry(traderAverageNotionalInPeriodKey, _traderAverage)]
534+ }
535+
536+
537+func getFeeDiscount (_trader) = {
538+ let tiers = getFeeTiers()
539+ let cumulativeVolume = getTraderCumulativeVolume(_trader)
540+ func findFee (_acc,_tier) = {
541+ let $t01644516488 = _tier
542+ let minCumulativeVolume = $t01644516488._1
543+ let discount = $t01644516488._2
544+ if ((cumulativeVolume >= minCumulativeVolume))
545+ then [discount]
546+ else _acc
547+ }
548+
549+ let resultList = {
550+ let $l = tiers
551+ let $s = size($l)
552+ let $acc0 = [NO_DISCOUNT]
553+ func $f0_1 ($a,$i) = if (($i >= $s))
554+ then $a
555+ else findFee($a, $l[$i])
556+
557+ func $f0_2 ($a,$i) = if (($i >= $s))
558+ then $a
559+ else throw("List size exceeds 5")
560+
561+ $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5)
562+ }
563+resultList[0]
436564 }
437565
438566
439567 @Callable(i)
440568 func initialize (_coordinator,_oracle) = if (initialized())
441569 then throw("Already initialized")
442570 else [StringEntry(k_coordinatorAddress, _coordinator), StringEntry(k_oracleAddress, _oracle), BooleanEntry(k_initialized, true)]
443571
444572
445573
446574 @Callable(i)
447575 func setOracleAddress (_oracle) = if (if (!(initialized()))
448576 then true
449577 else (i.caller != adminAddress()))
450578 then throw("Invalid setOracleAddress parameters")
451579 else [StringEntry(k_oracleAddress, _oracle)]
452580
453581
454582
455583 @Callable(i)
456584 func view_getPeriod () = {
457585 let weekId = getWeekId(TIME)
458586 let weekStart = getWeekStart(weekId)
459587 let weekEnd = getWeekEnd(weekId)
460588 throw(((((toString(weekStart) + ",") + toString(weekEnd)) + ",") + toString(TIME)))
461589 }
462590
463591
464592
465593 @Callable(i)
466594 func view_getMaxAmountOfAssetToDistribute (_amm,_assetId,_weekId) = throw(toString(getMaxAmountOfAssetToDistribute(_amm, _assetId, _weekId)))
467595
468596
469597
470598 @Callable(i)
471599 func view_claimRewards (_trader,_assetId,_period) = throw(toString(totalRewardForTraderInAsset(_trader, _assetId, [_period])))
472600
473601
474602
475603 @Callable(i)
476604 func view_calcReward (_trader,_amm,_assetId,_period) = throw(toString(rewardForTraderInAssetInPeriod(_amm, _assetId, _trader, _period)))
477605
478606
479607
480608 @Callable(i)
481609 func view_claimAllRewards (_trader,_assetId,_periods) = {
482610 let result = claimAllRewardForPeriodForTrader(_trader, _assetId, _periods)
483611 throw(((toString(result._1) + ",") + toString(getTotalClaimedForTraderAndAsset(_trader, _assetId))))
484612 }
485613
486614
487615
488616 @Callable(i)
617+func view_earnedRewards (_amm,_assetId,_period) = {
618+ let result = rewardForAmmInAssetInPeriod(_amm, _assetId, _period)
619+ throw(toString(result))
620+ }
621+
622+
623+
624+@Callable(i)
489625 func claimAllRewards (_assetId,_periods) = {
490626 let trader = toString(i.caller)
491627 if (contains(_periods, toString(getWeekId(TIME))))
492628 then throw("Can not claim rewards for current week")
493629 else {
494- let $t01543815521 = claimAllRewardForPeriodForTrader(trader, _assetId, _periods)
495- let amount = $t01543815521._1
496- let result = $t01543815521._2
630+ let $t01890718990 = claimAllRewardForPeriodForTrader(trader, _assetId, _periods)
631+ let amount = $t01890718990._1
632+ let result = $t01890718990._2
497633 if ((amount == 0))
498634 then throw("Nothing to claim")
499635 else result
500636 }
501637 }
638+
639+
640+
641+@Callable(i)
642+func setFeeDiscountTiers (_discounts) = if (if (!(initialized()))
643+ then true
644+ else (i.caller != adminAddress()))
645+ then throw("Invalid setFeeDiscountTiers params")
646+ else [StringEntry(k_feeTiers, _discounts)]
502647
503648
504649
505650 @Callable(i)
506651 func attachRewardAsset (_assetId,_maxAmountPerPeriod) = if (if (!(initialized()))
507652 then true
508653 else (i.caller != adminAddress()))
509654 then throw("Invalid attachRewardAsset params")
510655 else {
511656 let amms = getAmms()
512657 let rewardAssetIds = getRewardAssetIds()
513658 let newRewardAssetIds = if (containsElement(rewardAssetIds, _assetId))
514659 then rewardAssetIds
515660 else (rewardAssetIds :+ _assetId)
516661 [IntegerEntry(getAssetMaxAmountPerPeriodKey(_assetId), _maxAmountPerPeriod), StringEntry(k_rewardAssetIds, listToStr(newRewardAssetIds))]
517662 }
518663
519664
520665
521666 @Callable(i)
522667 func attachRewards (_amm,_assetId,_rewardRate) = if (if (if (!(initialized()))
523668 then true
524669 else (i.caller != adminAddress()))
525670 then true
526671 else !(isWhitelist(_amm)))
527672 then throw("Invalid attachRewards params")
528673 else {
529674 let amms = getAmms()
530675 let rewardAssetIds = getRewardAssetIds()
531676 let newAmms = if (containsElement(amms, _amm))
532677 then amms
533678 else (amms :+ _amm)
534679 let newRewardAssetIds = if (containsElement(rewardAssetIds, _assetId))
535680 then rewardAssetIds
536681 else (rewardAssetIds :+ _assetId)
537682 [IntegerEntry(getAmmRewardRateKey(_amm, _assetId), _rewardRate), StringEntry(k_amms, listToStr(newAmms)), StringEntry(k_rewardAssetIds, listToStr(newRewardAssetIds))]
538683 }
539684
540685
541686
542687 @Callable(i)
543688 func notifyFees (_trader,_fee) = {
544689 let amm = toString(i.caller)
545690 if (if (!(isWhitelist(amm)))
546691 then true
547692 else !(initialized()))
548693 then throw("Invalid notifyFees params")
549694 else {
550695 let actualFee = usdnToDecimals(_fee)
551696 let weekId = getWeekId(TIME)
552697 updateAmmFees(amm, _trader, weekId, actualFee)
553698 }
554699 }
555700
556701
557702
558703 @Callable(i)
559704 func notifyNotional (_trader,_notional) = {
560705 let amm = toString(i.caller)
561706 if (if (!(isWhitelist(amm)))
562707 then true
563708 else !(initialized()))
564709 then throw("Invalid notifyNotional params")
565710 else {
566711 let actualNotional = usdnToDecimals(_notional)
567712 let lastNotional = getLastNotional(amm, _trader)
568713 let weekId = getWeekId(TIME)
714+ let dayId = getDayId(TIME)
569715 let weekStart = getWeekStart(weekId)
570716 let weekEnd = getWeekEnd(weekId)
571717 let t = (weekEnd - weekStart)
572718 let oldRunningAverage = getTraderAverageNotionalInPeriod(amm, _trader, weekId, lastNotional)
573719 let w = divd((weekEnd - TIME), t)
574720 let oldTraderAmmScore = getTraderScoreInPeriod(amm, _trader, weekId)
575721 let oldTotalAmmScore = getTotalScoreInPeriod(amm, weekId)
576722 let fees = getFeesInPeriod(amm, _trader, weekId)
577723 let newRunningAverage = ((oldRunningAverage + muld(actualNotional, w)) - muld(lastNotional, w))
578724 let newTraderAmmScore = muld(powd(fees, A), powd(newRunningAverage, (DECIMAL_UNIT - A)))
579725 let newTotalAmmScoreInPeriod = ((oldTotalAmmScore - oldTraderAmmScore) + newTraderAmmScore)
580- updateAmmData(amm, _trader, weekId, newRunningAverage, actualNotional, newTraderAmmScore, newTotalAmmScoreInPeriod)
726+ (updateAmmData(amm, _trader, weekId, newRunningAverage, actualNotional, newTraderAmmScore, newTotalAmmScoreInPeriod) ++ updateTraderVolume(_trader, dayId, abs((lastNotional - actualNotional))))
581727 }
728+ }
729+
730+
731+
732+@Callable(i)
733+func computeFeeDiscount (_trader) = {
734+ let result = getFeeDiscount(_trader)
735+ $Tuple2(nil, result)
736+ }
737+
738+
739+
740+@Callable(i)
741+func view_computeFeeDiscount (_trader) = {
742+ let result = getFeeDiscount(_trader)
743+ throw(toString(result))
582744 }
583745
584746
585747 @Verifier(tx)
586748 func verify () = sigVerify(tx.bodyBytes, tx.proofs[0], adminPublicKey())
587749

github/deemru/w8io/873ac7e 
81.65 ms