tx · FgEFR76dKziUVmoiVZAmv74D6YtFhGG2nrJJTfs8H1f

3NBEuUXKfGqe1ZKUfx8b8YsguJKYLhy2bTJ:  -0.03700000 Waves

2023.05.23 14:06 [2590541] smart account 3NBEuUXKfGqe1ZKUfx8b8YsguJKYLhy2bTJ > SELF 0.00000000 Waves

{ "type": 13, "id": "FgEFR76dKziUVmoiVZAmv74D6YtFhGG2nrJJTfs8H1f", "fee": 3700000, "feeAssetId": null, "timestamp": 1684840021137, "version": 2, "chainId": 84, "sender": "3NBEuUXKfGqe1ZKUfx8b8YsguJKYLhy2bTJ", "senderPublicKey": "2NgVCitn1k18yzwhrzdQXHDEygzSkjbXS4A1koTt14db", "proofs": [ "4V3HbUCdPaMH3rEpkg31xsqBsvYaHMYU19xjZWVMiE6Ri4CdvaZS31bHwGoMYPa3jLAJZJD6aSw6iESkZbn7m9CB" ], "script": "base64:BgIzCAISBQoDCAgBEgASAwoBARIAEgASABIDCgEBEgMKAQESABIAEgMKAQgSAwoBCBIDCgEIXwANa190b3RhbFN1cHBseQINa190b3RhbFN1cHBseQAPa19yZXdhcmRCYWxhbmNlAg9rX3Jld2FyZEJhbGFuY2UAD2tfbG9ja2VkQmFsYW5jZQIPa19sb2NrZWRCYWxhbmNlAA1rX2ZyZWVCYWxhbmNlAg1rX2ZyZWVCYWxhbmNlAA9rX2V4Y2Vzc0JhbGFuY2UCD2tfZXhjZXNzQmFsYW5jZQAMa192YXVsdEFzc2V0AgxrX3ZhdWx0QXNzZXQAFGtfdmF1bHRBc3NldERlY2ltYWxzAhRrX3ZhdWx0QXNzZXREZWNpbWFscwAUa19tYXhTcG90VXRpbGl6YXRpb24CFGtfbWF4U3BvdFV0aWxpemF0aW9uAAZrX3JhdGUCBmtfcmF0ZQAQa19sYXN0VXBkYXRlVGltZQIQa19sYXN0VXBkYXRlVGltZQAWa19yZXdhcmRQZXJUb2tlblN0b3JlZAIWa19yZXdhcmRQZXJUb2tlblN0b3JlZAAMa19yZXdhcmRSYXRlAgxrX3Jld2FyZFJhdGUADmtfcGVyaW9kRmluaXNoAg5rX3BlcmlvZEZpbmlzaAAUa191c2VyUmV3YXJkUGVyVG9rZW4CFGtfdXNlclJld2FyZFBlclRva2VuAAxrX3VzZXJSZXdhcmQCDGtfdXNlclJld2FyZAAJa19iYWxhbmNlAglrX2JhbGFuY2UADmtfYXZlcmFnZV9yYXRlAg5rX2F2ZXJhZ2VfcmF0ZQAQa193aXRoZHJhd19saW1pdAIQa193aXRoZHJhd19saW1pdAAUa19sYXN0X3dpdGhkcmF3X2RhdGUCFGtfbGFzdF93aXRoZHJhd19kYXRlABRrX3dpdGhkcmF3X2luX3BlcmlvZAIUa193aXRoZHJhd19pbl9wZXJpb2QADWtfaW5pdGlhbGl6ZWQCDWtfaW5pdGlhbGl6ZWQAFGtfY29vcmRpbmF0b3JBZGRyZXNzAhRrX2Nvb3JkaW5hdG9yQWRkcmVzcwAFa19hbW0CBWtfYW1tABJrX2dvdmVybmFuY2VfYXNzZXQCC2tfZ292X2Fzc2V0AA1rX3F1b3RlX2Fzc2V0Ag1rX3F1b3RlX2Fzc2V0AA9rX2FkbWluX2FkZHJlc3MCD2tfYWRtaW5fYWRkcmVzcwARa19tYW5hZ2VyX2FkZHJlc3MCEWtfbWFuYWdlcl9hZGRyZXNzAA5rX3Nwb3RfYWRkcmVzcwIOa19zcG90X2FkZHJlc3MAFGtfY29sbGF0ZXJhbF9hZGRyZXNzAhRrX2NvbGxhdGVyYWxfYWRkcmVzcwEOdG9Db21wb3NpdGVLZXkCBF9rZXkIX2FkZHJlc3MJAKwCAgkArAICBQRfa2V5AgFfBQhfYWRkcmVzcwELY29vcmRpbmF0b3IACQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKYIAQkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCdCAIFBHRoaXMFFGtfY29vcmRpbmF0b3JBZGRyZXNzAhNDb29yZGluYXRvciBub3Qgc2V0AhtDb29yZGluYXRvciBhZGRyZXNzIGludmFsaWQBDGFkbWluQWRkcmVzcwAJAKYIAQkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCdCAIJAQtjb29yZGluYXRvcgAFD2tfYWRtaW5fYWRkcmVzcwIVQWRtaW4gYWRkcmVzcyBub3Qgc2V0AQtpc1doaXRlbGlzdAEIX2FkZHJlc3MJAQt2YWx1ZU9yRWxzZQIJAJsIAgkBC2Nvb3JkaW5hdG9yAAkBDnRvQ29tcG9zaXRlS2V5AgUFa19hbW0FCF9hZGRyZXNzBwEPZ292ZXJuYW5jZUFzc2V0AAkA2QQBCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAJ0IAgkBC2Nvb3JkaW5hdG9yAAUSa19nb3Zlcm5hbmNlX2Fzc2V0AhhHb3Zlcm5hbmNlIGFzc2V0IG5vdCBzZXQBCnF1b3RlQXNzZXQACQDZBAEJARFAZXh0ck5hdGl2ZSgxMDUzKQIJAQtjb29yZGluYXRvcgAFDWtfcXVvdGVfYXNzZXQBDXZhdWx0QXNzZXRTdHIACQETdmFsdWVPckVycm9yTWVzc2FnZQIJAJ0IAgUEdGhpcwUMa192YXVsdEFzc2V0AhNWYXVsdCBhc3NldCBub3Qgc2V0AQp2YXVsdEFzc2V0AAQLX2Fzc2V0SWRTdHIJAQ12YXVsdEFzc2V0U3RyAAMJAAACBQtfYXNzZXRJZFN0cgIFV0FWRVMFBHVuaXQJANkEAQULX2Fzc2V0SWRTdHIBEnZhdWx0QXNzZXREZWNpbWFscwAJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAmggCBQR0aGlzBRRrX3ZhdWx0QXNzZXREZWNpbWFscwIcVmF1bHQgYXNzZXQgZGVjaW1hbHMgbm90IHNldAEObWFuYWdlckFkZHJlc3MACQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKYIAQkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCdCAIJAQtjb29yZGluYXRvcgAFEWtfbWFuYWdlcl9hZGRyZXNzAhdNYW5hZ2VyIGFkZHJlc3Mgbm90IHNldAIXTWFuYWdlciBhZGRyZXNzIGludmFsaWQADERFQ0lNQUxfVU5JVAkAaAIAAQkAaAIJAGgCCQBoAgkAaAIJAGgCCQBoAgkAaAIACgAKAAoACgAKAAoACgAKAAhEVVJBVElPTgkAaAIJAGgCCQBoAgAHADwAPAAYAApOT19BRERSRVNTAgAACU5PX1NUQUtFUgAAARFhc3NldEZyb21EZWNpbWFscwEHX2Ftb3VudAQNYXNzZXREZWNpbWFscwkBEnZhdWx0QXNzZXREZWNpbWFscwADCQAAAgUNYXNzZXREZWNpbWFscwAGCQBpAgUHX2Ftb3VudABkAwkAAAIFDWFzc2V0RGVjaW1hbHMACAUHX2Ftb3VudAkAAgECFkludmFsaWQgYXNzZXQgZGVjaW1hbHMBD2Fzc2V0VG9EZWNpbWFscwEHX2Ftb3VudAQNYXNzZXREZWNpbWFscwkBEnZhdWx0QXNzZXREZWNpbWFscwADCQAAAgUNYXNzZXREZWNpbWFscwAGCQBoAgUHX2Ftb3VudABkAwkAAAIFDWFzc2V0RGVjaW1hbHMACAUHX2Ftb3VudAkAAgECFkludmFsaWQgYXNzZXQgZGVjaW1hbHMBBGRpdmQCAl94Al95CQBuBAUCX3gFDERFQ0lNQUxfVU5JVAUCX3kFCEhBTEZFVkVOAQRtdWxkAgJfeAJfeQkAbgQFAl94BQJfeQUMREVDSU1BTF9VTklUBQhIQUxGRVZFTgEDYWJzAQJfeAMJAGYCBQJfeAAABQJfeAkBAS0BBQJfeAEEbWludgICX3gCX3kDCQBmAgUCX3gFAl95BQJfeQUCX3gAD1dJVEhEUkFXX1BFUklPRAkAaAIAgKMFAOgHABNXSVRIRFJBV19QRVJfUEVSSU9ECQEEZGl2ZAIJAGgCAAEFDERFQ0lNQUxfVU5JVAkAaAIABAUMREVDSU1BTF9VTklUAQNpbnQBAWsJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAmggCBQR0aGlzBQFrCQCsAgICDW5vIHZhbHVlIGZvciAFAWsBBGludDABAWsJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwUBawAAAQRpbnQxAQFrCQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMFAWsFDERFQ0lNQUxfVU5JVAELdG90YWxTdXBwbHkACQEEaW50MAEFDWtfdG90YWxTdXBwbHkBBHJhdGUACQEEaW50MQEFBmtfcmF0ZQEJYmFsYW5jZU9mAQdfc3Rha2VyCQEEaW50MAEJAQ50b0NvbXBvc2l0ZUtleQIFCWtfYmFsYW5jZQUHX3N0YWtlcgELYXZlcmFnZVJhdGUBB19zdGFrZXIJAQRpbnQwAQkBDnRvQ29tcG9zaXRlS2V5AgUOa19hdmVyYWdlX3JhdGUFB19zdGFrZXIBDXdpdGhkcmF3TGltaXQBB19zdGFrZXIJAQRpbnQwAQkBDnRvQ29tcG9zaXRlS2V5AgUQa193aXRoZHJhd19saW1pdAUHX3N0YWtlcgERd2l0aGRyYXduSW5QZXJpb2QBB19zdGFrZXIJAQRpbnQwAQkBDnRvQ29tcG9zaXRlS2V5AgUUa193aXRoZHJhd19pbl9wZXJpb2QFB19zdGFrZXIBEWxhc3RXaXRoZHJhd25EYXRlAQdfc3Rha2VyCQEEaW50MAEJAQ50b0NvbXBvc2l0ZUtleQIFFGtfbGFzdF93aXRoZHJhd19kYXRlBQdfc3Rha2VyAQtmcmVlQmFsYW5jZQAJAQRpbnQwAQUNa19mcmVlQmFsYW5jZQENbG9ja2VkQmFsYW5jZQAJAQRpbnQwAQUPa19sb2NrZWRCYWxhbmNlAQ1leGNlc3NCYWxhbmNlAAkBBGludDABBQ9rX2V4Y2Vzc0JhbGFuY2UBFHJld2FyZFBlclRva2VuU3RvcmVkAAkBBGludDABBRZrX3Jld2FyZFBlclRva2VuU3RvcmVkAQ5sYXN0VXBkYXRlVGltZQAJAQRpbnQwAQUQa19sYXN0VXBkYXRlVGltZQEKcmV3YXJkUmF0ZQAJAQRpbnQwAQUMa19yZXdhcmRSYXRlAQxwZXJpb2RGaW5pc2gACQEEaW50MAEFDmtfcGVyaW9kRmluaXNoAQ1yZXdhcmRCYWxhbmNlAAkBBGludDABBQ9rX3Jld2FyZEJhbGFuY2UBB3Jld2FyZHMBB19zdGFrZXIJAQRpbnQwAQkBDnRvQ29tcG9zaXRlS2V5AgUMa191c2VyUmV3YXJkBQdfc3Rha2VyARZ1c2VyUmV3YXJkUGVyVG9rZW5QYWlkAQdfc3Rha2VyCQEEaW50MAEJAQ50b0NvbXBvc2l0ZUtleQIFFGtfdXNlclJld2FyZFBlclRva2VuBQdfc3Rha2VyARJtYXhTcG90VXRpbGl6YXRpb24ACQEEaW50MAEFFGtfbWF4U3BvdFV0aWxpemF0aW9uAQtpbml0aWFsaXplZAAJAQt2YWx1ZU9yRWxzZQIJAJsIAgUEdGhpcwUNa19pbml0aWFsaXplZAcBEGN1cnJlbnRUaW1lc3RhbXAACAUJbGFzdEJsb2NrCXRpbWVzdGFtcAETY3VycmVudFRpbWVzdGFtcFNlYwAJAGkCCQEQY3VycmVudFRpbWVzdGFtcAAA6AcBFGdldFdpdGhkcmF3TGltaXRMZWZ0AQdfc3Rha2VyBAtjdXJyZW50RGF0ZQkBEGN1cnJlbnRUaW1lc3RhbXAABBBsYXN0V2l0aGRyYXdEYXRlCQERbGFzdFdpdGhkcmF3bkRhdGUBBQdfc3Rha2VyBAskdDA2MjY3NjU4OAMJAGYCCQBlAgULY3VycmVudERhdGUFEGxhc3RXaXRoZHJhd0RhdGUFD1dJVEhEUkFXX1BFUklPRAkAlQoDBQtjdXJyZW50RGF0ZQkBDXdpdGhkcmF3TGltaXQBBQdfc3Rha2VyAAAJAJUKAwUQbGFzdFdpdGhkcmF3RGF0ZQkAZQIJAQ13aXRoZHJhd0xpbWl0AQUHX3N0YWtlcgkBEXdpdGhkcmF3bkluUGVyaW9kAQUHX3N0YWtlcgkBEXdpdGhkcmF3bkluUGVyaW9kAQUHX3N0YWtlcgQUbmV3TGFzdFdpdGhkcmF3bkRhdGUIBQskdDA2MjY3NjU4OAJfMQQRd2l0aGRyYXdMaW1pdExlZnQIBQskdDA2MjY3NjU4OAJfMgQYYWxyZWFkeVdpdGhkcmF3bkluUGVyaW9kCAULJHQwNjI2NzY1ODgCXzMJAJUKAwUUbmV3TGFzdFdpdGhkcmF3bkRhdGUFEXdpdGhkcmF3TGltaXRMZWZ0BRhhbHJlYWR5V2l0aGRyYXduSW5QZXJpb2QBDmNvbXB1dGVOZXdSYXRlARNfYW1vdW50T2ZRdW90ZUFzc2V0BAduZXdSYXRlAwkAZgIJAQt0b3RhbFN1cHBseQAAAAkBBGRpdmQCCQBkAgkBC2ZyZWVCYWxhbmNlAAUTX2Ftb3VudE9mUXVvdGVBc3NldAkBC3RvdGFsU3VwcGx5AAUMREVDSU1BTF9VTklUBQduZXdSYXRlARhsYXN0VGltZVJld2FyZEFwcGxpY2FibGUACQEEbWludgIJARNjdXJyZW50VGltZXN0YW1wU2VjAAkBDHBlcmlvZEZpbmlzaAABDnJld2FyZFBlclRva2VuAQ1fYmFsYW5jZURlbHRhAwkAAAIJAGQCCQELdG90YWxTdXBwbHkABQ1fYmFsYW5jZURlbHRhAAAJARRyZXdhcmRQZXJUb2tlblN0b3JlZAAEDHRpbWVJbnRlcnZhbAkAZQIJARhsYXN0VGltZVJld2FyZEFwcGxpY2FibGUACQEObGFzdFVwZGF0ZVRpbWUABBJhY3R1YWxUaW1lSW50ZXJ2YWwDCQBmAgAABQx0aW1lSW50ZXJ2YWwAAAUMdGltZUludGVydmFsBARkaWZmCQEEZGl2ZAIJAGgCCQEKcmV3YXJkUmF0ZQAFEmFjdHVhbFRpbWVJbnRlcnZhbAkAZAIJAQt0b3RhbFN1cHBseQAFDV9iYWxhbmNlRGVsdGEJAGQCCQEUcmV3YXJkUGVyVG9rZW5TdG9yZWQABQRkaWZmAQZlYXJuZWQCB19zdGFrZXINX2JhbGFuY2VEZWx0YQQLcmV3YXJkRGVsdGEJAGUCCQEOcmV3YXJkUGVyVG9rZW4BBQ1fYmFsYW5jZURlbHRhCQEWdXNlclJld2FyZFBlclRva2VuUGFpZAEFB19zdGFrZXIJAGQCCQEEbXVsZAIJAGQCCQEJYmFsYW5jZU9mAQUHX3N0YWtlcgUNX2JhbGFuY2VEZWx0YQULcmV3YXJkRGVsdGEJAQdyZXdhcmRzAQUHX3N0YWtlcgEMdXBkYXRlUmV3YXJkAgdfc3Rha2VyDV9iYWxhbmNlRGVsdGEEF25ld1Jld2FyZFBlclRva2VuU3RvcmVkCQEOcmV3YXJkUGVyVG9rZW4BBQ1fYmFsYW5jZURlbHRhBBFuZXdMYXN0VXBkYXRlVGltZQkBE2N1cnJlbnRUaW1lc3RhbXBTZWMABAskdDA3ODEwODAwMgMJAQIhPQIFB19zdGFrZXICAAkAlAoCCQEGZWFybmVkAgUHX3N0YWtlcgUNX2JhbGFuY2VEZWx0YQUXbmV3UmV3YXJkUGVyVG9rZW5TdG9yZWQJAJQKAgAAAAAEDHN0YWtlckVhcm5lZAgFCyR0MDc4MTA4MDAyAl8xBBhzdGFrZXJSZXdhcmRQZXJUb2tlblBhaWQIBQskdDA3ODEwODAwMgJfMgkAlgoEBRduZXdSZXdhcmRQZXJUb2tlblN0b3JlZAURbmV3TGFzdFVwZGF0ZVRpbWUFDHN0YWtlckVhcm5lZAUYc3Rha2VyUmV3YXJkUGVyVG9rZW5QYWlkARF1cGRhdGVVc2VyQmFsYW5jZQIFX3VzZXIHX2NoYW5nZQMJAGcCCQBkAgkBCWJhbGFuY2VPZgEFBV91c2VyBQdfY2hhbmdlAAAJAMwIAgkBDEludGVnZXJFbnRyeQIJAQ50b0NvbXBvc2l0ZUtleQIFCWtfYmFsYW5jZQUFX3VzZXIJAGQCCQEJYmFsYW5jZU9mAQUFX3VzZXIFB19jaGFuZ2UFA25pbAkAAgEJAKwCAgkArAICCQCsAgICLVZhdWx0OiBjYW4gbm90IHVwZGF0ZSB1c2VyIGJhbGFuY2UuIEJhbGFuY2U6IAkApAMBCQEJYmFsYW5jZU9mAQUFX3VzZXICCSBjaGFuZ2U6IAkApAMBBQdfY2hhbmdlARRzZXRVc2VyV2l0aGRyYXdMaW1pdAIFX3VzZXIFX3JhdGUJAMwIAgkBDEludGVnZXJFbnRyeQIJAQ50b0NvbXBvc2l0ZUtleQIFEGtfd2l0aGRyYXdfbGltaXQFBV91c2VyBQVfcmF0ZQUDbmlsARJzZXRVc2VyQXZlcmFnZVJhdGUCBV91c2VyBV9yYXRlCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEOdG9Db21wb3NpdGVLZXkCBQ5rX2F2ZXJhZ2VfcmF0ZQUFX3VzZXIFBV9yYXRlBQNuaWwBEXVwZGF0ZUZyZWVCYWxhbmNlAQdfY2hhbmdlBAdiYWxhbmNlCQELZnJlZUJhbGFuY2UAAwkAZwIJAGQCBQdiYWxhbmNlBQdfY2hhbmdlAAAJAMwIAgkBDEludGVnZXJFbnRyeQIFDWtfZnJlZUJhbGFuY2UJAGQCBQdiYWxhbmNlBQdfY2hhbmdlBQNuaWwJAAIBCQCsAgIJAKwCAgkArAICAi1WYXVsdDogY2FuIG5vdCB1cGRhdGUgZnJlZSBiYWxhbmNlLiBCYWxhbmNlOiAJAKQDAQUHYmFsYW5jZQIJIGNoYW5nZTogCQCkAwEFB19jaGFuZ2UBE3VwZGF0ZUxvY2tlZEJhbGFuY2UBB19jaGFuZ2UEB2JhbGFuY2UJAQ1sb2NrZWRCYWxhbmNlAAMJAGcCCQBkAgUHYmFsYW5jZQUHX2NoYW5nZQAACQDMCAIJAQxJbnRlZ2VyRW50cnkCBQ9rX2xvY2tlZEJhbGFuY2UJAGQCBQdiYWxhbmNlBQdfY2hhbmdlBQNuaWwJAAIBCQCsAgIJAKwCAgkArAICAi9WYXVsdDogY2FuIG5vdCB1cGRhdGUgbG9ja2VkIGJhbGFuY2UuIEJhbGFuY2U6IAkApAMBBQdiYWxhbmNlAgkgY2hhbmdlOiAJAKQDAQUHX2NoYW5nZQETdXBkYXRlRXhjZXNzQmFsYW5jZQEHX2NoYW5nZQQMbmV3SW1iYWxhbmNlCQBkAgkBDWV4Y2Vzc0JhbGFuY2UABQdfY2hhbmdlBA91dGlsaXphdGlvblJhdGUJAQRkaXZkAgkBA2FicwEFDG5ld0ltYmFsYW5jZQkBC2ZyZWVCYWxhbmNlAAMJAGYCCQESbWF4U3BvdFV0aWxpemF0aW9uAAUPdXRpbGl6YXRpb25SYXRlCQDMCAIJAQxJbnRlZ2VyRW50cnkCBQ9rX2V4Y2Vzc0JhbGFuY2UFDG5ld0ltYmFsYW5jZQUDbmlsCQACAQkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICAi9WYXVsdDogY2FuIG5vdCB1cGRhdGUgZXhjZXNzIGJhbGFuY2UuIEJhbGFuY2U6IAkApAMBCQENZXhjZXNzQmFsYW5jZQACCSBjaGFuZ2U6IAkApAMBBQdfY2hhbmdlAhMgdXRpbGl6YXRpb24gcmF0ZTogCQCkAwEFD3V0aWxpemF0aW9uUmF0ZQIXIG1heCB1dGlsaXphdGlvbiByYXRlOiAJAKQDAQkBEm1heFNwb3RVdGlsaXphdGlvbgABEXVwZGF0ZVRvdGFsU3VwcGx5AQdfY2hhbmdlCQDMCAIJAQxJbnRlZ2VyRW50cnkCBQ1rX3RvdGFsU3VwcGx5CQBkAgkBC3RvdGFsU3VwcGx5AAUHX2NoYW5nZQUDbmlsAQp1cGRhdGVSYXRlAQVfcmF0ZQkAzAgCCQEMSW50ZWdlckVudHJ5AgUGa19yYXRlBQVfcmF0ZQUDbmlsARVzZXRVc2VyV2l0aGRyYXdQYXJhbXMDBV91c2VyEV9sYXN0V2l0aGRyYXdEYXRlCl93aXRoZHJhd24JAMwIAgkBDEludGVnZXJFbnRyeQIJAQ50b0NvbXBvc2l0ZUtleQIFFGtfbGFzdF93aXRoZHJhd19kYXRlBQVfdXNlcgURX2xhc3RXaXRoZHJhd0RhdGUJAMwIAgkBDEludGVnZXJFbnRyeQIJAQ50b0NvbXBvc2l0ZUtleQIFFGtfd2l0aGRyYXdfaW5fcGVyaW9kBQVfdXNlcgUKX3dpdGhkcmF3bgUDbmlsARN1cGRhdGVSZXdhcmRCYWxhbmNlAQZfZGVsdGEJAMwIAgkBDEludGVnZXJFbnRyeQIFD2tfcmV3YXJkQmFsYW5jZQkAZAIJAQ1yZXdhcmRCYWxhbmNlAAUGX2RlbHRhBQNuaWwBEHVwZGF0ZVJld2FyZFJhdGUBC19yZXdhcmRSYXRlCQDMCAIJAQxJbnRlZ2VyRW50cnkCBQxrX3Jld2FyZFJhdGUFC19yZXdhcmRSYXRlBQNuaWwBCnVwZGF0ZVRpbWUCD19sYXN0VXBkYXRlVGltZQ1fcGVyaW9kRmluaXNoCQDMCAIJAQxJbnRlZ2VyRW50cnkCBRBrX2xhc3RVcGRhdGVUaW1lBQ9fbGFzdFVwZGF0ZVRpbWUJAMwIAgkBDEludGVnZXJFbnRyeQIFDmtfcGVyaW9kRmluaXNoBQ1fcGVyaW9kRmluaXNoBQNuaWwBGnVwZGF0ZVJld2FyZFBlclRva2VuU3RvcmVkARVfcmV3YXJkUGVyVG9rZW5TdG9yZWQJAMwIAgkBDEludGVnZXJFbnRyeQIFFmtfcmV3YXJkUGVyVG9rZW5TdG9yZWQFFV9yZXdhcmRQZXJUb2tlblN0b3JlZAUDbmlsARF1cGRhdGVVc2VyUmV3YXJkcwMHX3N0YWtlcgdfcmV3YXJkE191c2VyUmV3YXJkUGVyVG9rZW4JAMwIAgkBDEludGVnZXJFbnRyeQIJAQ50b0NvbXBvc2l0ZUtleQIFDGtfdXNlclJld2FyZAUHX3N0YWtlcgUHX3Jld2FyZAkAzAgCCQEMSW50ZWdlckVudHJ5AgkBDnRvQ29tcG9zaXRlS2V5AgUUa191c2VyUmV3YXJkUGVyVG9rZW4FB19zdGFrZXIFE191c2VyUmV3YXJkUGVyVG9rZW4FA25pbA0BaQEKaW5pdGlhbGl6ZQMMX2Nvb3JkaW5hdG9yC192YXVsdEFzc2V0E19tYXhTcG90VXRpbGl6YXRpb24DAwMDCQELaW5pdGlhbGl6ZWQABgkBAiE9AggFAWkGY2FsbGVyBQR0aGlzBgkAZgIAAAUTX21heFNwb3RVdGlsaXphdGlvbgYJAGYCBRNfbWF4U3BvdFV0aWxpemF0aW9uBQxERUNJTUFMX1VOSVQJAAIBAhRVbmFibGUgdG8gaW5pdGlhbGl6ZQQNYXNzZXREZWNpbWFscwMJAAACBQtfdmF1bHRBc3NldAIFV0FWRVMACAQEaW5mbwkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQDsBwEJANkEAQULX3ZhdWx0QXNzZXQJAKwCAgISSW52YWxpZCB0b2tlbiBpZDogBQtfdmF1bHRBc3NldAgFBGluZm8IZGVjaW1hbHMJAMwIAgkBC1N0cmluZ0VudHJ5AgUUa19jb29yZGluYXRvckFkZHJlc3MJAKUIAQkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCmCAEFDF9jb29yZGluYXRvcgIbSW52YWxpZCBjb29yZGluYXRvciBhZGRyZXNzCQDMCAIJAQtTdHJpbmdFbnRyeQIFDGtfdmF1bHRBc3NldAULX3ZhdWx0QXNzZXQJAMwIAgkBDEludGVnZXJFbnRyeQIFFGtfdmF1bHRBc3NldERlY2ltYWxzBQ1hc3NldERlY2ltYWxzCQDMCAIJAQxJbnRlZ2VyRW50cnkCBRRrX21heFNwb3RVdGlsaXphdGlvbgUTX21heFNwb3RVdGlsaXphdGlvbgkAzAgCCQEMQm9vbGVhbkVudHJ5AgUNa19pbml0aWFsaXplZAYFA25pbAFpAQVzdGFrZQAEB19zdGFrZXIJAKUIAQgFAWkGY2FsbGVyBAdfYW1vdW50CQEPYXNzZXRUb0RlY2ltYWxzAQgJAJEDAggFAWkIcGF5bWVudHMAAAZhbW91bnQDAwMJAQIhPQIICQCRAwIIBQFpCHBheW1lbnRzAAAHYXNzZXRJZAkBCnZhdWx0QXNzZXQABgkBAiE9AgkAkAMBCAUBaQhwYXltZW50cwABBgkBASEBCQELaW5pdGlhbGl6ZWQACQACAQIVSW52YWxpZCBjYWxsIHRvIHN0YWtlBA0kdDAxMjUzNzEyNzY2CQEMdXBkYXRlUmV3YXJkAgUHX3N0YWtlcgAABBduZXdSZXdhcmRQZXJUb2tlblN0b3JlZAgFDSR0MDEyNTM3MTI3NjYCXzEEEW5ld0xhc3RVcGRhdGVUaW1lCAUNJHQwMTI1MzcxMjc2NgJfMgQMc3Rha2VyRWFybmVkCAUNJHQwMTI1MzcxMjc2NgJfMwQYc3Rha2VyUmV3YXJkUGVyVG9rZW5QYWlkCAUNJHQwMTI1MzcxMjc2NgJfNAQLY3VycmVudFJhdGUJAQRyYXRlAAQPcHJldkF2ZXJhZ2VSYXRlCQELYXZlcmFnZVJhdGUBBQdfc3Rha2VyBAd2QW1vdW50CQEEZGl2ZAIFB19hbW91bnQFC2N1cnJlbnRSYXRlBA5uZXdBdmVyYWdlUmF0ZQkBBGRpdmQCCQBkAgkBBG11bGQCBQd2QW1vdW50BQtjdXJyZW50UmF0ZQkBBG11bGQCCQEJYmFsYW5jZU9mAQUHX3N0YWtlcgUPcHJldkF2ZXJhZ2VSYXRlCQBkAgUHdkFtb3VudAkBCWJhbGFuY2VPZgEFB19zdGFrZXIED25ld1RvdGFsQmFsYW5jZQkAZAIFB3ZBbW91bnQJAQliYWxhbmNlT2YBBQdfc3Rha2VyBBBuZXdXaXRoZHJhd0xpbWl0CQEEbXVsZAIFD25ld1RvdGFsQmFsYW5jZQUTV0lUSERSQVdfUEVSX1BFUklPRAQFc3Rha2UJAPwHBAkBDm1hbmFnZXJBZGRyZXNzAAIHZGVwb3NpdAUDbmlsCQDMCAIJAQ9BdHRhY2hlZFBheW1lbnQCCQEKdmF1bHRBc3NldAAJARFhc3NldEZyb21EZWNpbWFscwEFB19hbW91bnQFA25pbAMJAAACBQVzdGFrZQUFc3Rha2UJAM4IAgkAzggCCQDOCAIJAM4IAgkAzggCCQDOCAIJAM4IAgkBEXVwZGF0ZVVzZXJSZXdhcmRzAwUHX3N0YWtlcgUMc3Rha2VyRWFybmVkBRhzdGFrZXJSZXdhcmRQZXJUb2tlblBhaWQJARp1cGRhdGVSZXdhcmRQZXJUb2tlblN0b3JlZAEFF25ld1Jld2FyZFBlclRva2VuU3RvcmVkCQEKdXBkYXRlVGltZQIFEW5ld0xhc3RVcGRhdGVUaW1lCQEMcGVyaW9kRmluaXNoAAkBEXVwZGF0ZUZyZWVCYWxhbmNlAQUHX2Ftb3VudAkBEXVwZGF0ZVVzZXJCYWxhbmNlAgUHX3N0YWtlcgUHdkFtb3VudAkBEnNldFVzZXJBdmVyYWdlUmF0ZQIFB19zdGFrZXIFDm5ld0F2ZXJhZ2VSYXRlCQEUc2V0VXNlcldpdGhkcmF3TGltaXQCBQdfc3Rha2VyBRBuZXdXaXRoZHJhd0xpbWl0CQERdXBkYXRlVG90YWxTdXBwbHkBBQd2QW1vdW50CQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBB3VuU3Rha2UBB19hbW91bnQEB19zdGFrZXIJAKUIAQgFAWkGY2FsbGVyBBJhbW91bnRPZlF1b3RlQXNzZXQJAQ9hc3NldFRvRGVjaW1hbHMBBQdfYW1vdW50AwMDCQECIT0CCAUBaQhwYXltZW50cwUDbmlsBgkAZwIAAAUSYW1vdW50T2ZRdW90ZUFzc2V0BgkBASEBCQELaW5pdGlhbGl6ZWQACQACAQIXSW52YWxpZCBjYWxsIHRvIHVuU3Rha2UEDSR0MDE0Mjc0MTQ0OTAJAQx1cGRhdGVSZXdhcmQCBQdfc3Rha2VyAAAEF25ld1Jld2FyZFBlclRva2VuU3RvcmVkCAUNJHQwMTQyNzQxNDQ5MAJfMQQRbmV3TGFzdFVwZGF0ZVRpbWUIBQ0kdDAxNDI3NDE0NDkwAl8yBAxzdGFrZXJFYXJuZWQIBQ0kdDAxNDI3NDE0NDkwAl8zBBhzdGFrZXJSZXdhcmRQZXJUb2tlblBhaWQIBQ0kdDAxNDI3NDE0NDkwAl80BA0kdDAxNDQ5NzE0NjY0CQEUZ2V0V2l0aGRyYXdMaW1pdExlZnQBBQdfc3Rha2VyBBRuZXdMYXN0V2l0aGRyYXduRGF0ZQgFDSR0MDE0NDk3MTQ2NjQCXzEEEXdpdGhkcmF3TGltaXRMZWZ0CAUNJHQwMTQ0OTcxNDY2NAJfMgQYYWxyZWFkeVdpdGhkcmF3bkluUGVyaW9kCAUNJHQwMTQ0OTcxNDY2NAJfMwQHdkFtb3VudAkBBGRpdmQCBRJhbW91bnRPZlF1b3RlQXNzZXQJAQRyYXRlAAMJAGYCBQd2QW1vdW50BRF3aXRoZHJhd0xpbWl0TGVmdAkAAgECLEludmFsaWQgY2FsbCB0byB1blN0YWtlOiB3aXRoZHJhdyBvdmVyIGxpbWl0BBRuZXdXaXRoZHJhd25JblBlcmlvZAkAZAIFGGFscmVhZHlXaXRoZHJhd25JblBlcmlvZAUHdkFtb3VudAMJAGYCBRJhbW91bnRPZlF1b3RlQXNzZXQJAQtmcmVlQmFsYW5jZQAJAAIBAihJbnZhbGlkIGNhbGwgdG8gdW5TdGFrZTogYmFsYW5jZSB0b28gbG93BAd1bnN0YWtlCQD8BwQJAQ5tYW5hZ2VyQWRkcmVzcwACCHdpdGhkcmF3CQDMCAIJAQ12YXVsdEFzc2V0U3RyAAkAzAgCCQERYXNzZXRGcm9tRGVjaW1hbHMBBRJhbW91bnRPZlF1b3RlQXNzZXQFA25pbAUDbmlsAwkAAAIFB3Vuc3Rha2UFB3Vuc3Rha2UJAM4IAgkAzggCCQDOCAIJAM4IAgkAzggCCQDOCAIJAM4IAgkBEXVwZGF0ZVVzZXJSZXdhcmRzAwUHX3N0YWtlcgUMc3Rha2VyRWFybmVkBRhzdGFrZXJSZXdhcmRQZXJUb2tlblBhaWQJARp1cGRhdGVSZXdhcmRQZXJUb2tlblN0b3JlZAEFF25ld1Jld2FyZFBlclRva2VuU3RvcmVkCQEKdXBkYXRlVGltZQIFEW5ld0xhc3RVcGRhdGVUaW1lCQEMcGVyaW9kRmluaXNoAAkBEXVwZGF0ZUZyZWVCYWxhbmNlAQkBAS0BBRJhbW91bnRPZlF1b3RlQXNzZXQJARF1cGRhdGVVc2VyQmFsYW5jZQIFB19zdGFrZXIJAQEtAQUHdkFtb3VudAkBEXVwZGF0ZVRvdGFsU3VwcGx5AQkBAS0BBQd2QW1vdW50CQEVc2V0VXNlcldpdGhkcmF3UGFyYW1zAwUHX3N0YWtlcgUUbmV3TGFzdFdpdGhkcmF3bkRhdGUFFG5ld1dpdGhkcmF3bkluUGVyaW9kCQDMCAIJAQ5TY3JpcHRUcmFuc2ZlcgMIBQFpBmNhbGxlcgkBEWFzc2V0RnJvbURlY2ltYWxzAQUSYW1vdW50T2ZRdW90ZUFzc2V0CQEKdmF1bHRBc3NldAAFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpAQ93aXRoZHJhd1Jld2FyZHMABAdfc3Rha2VyCQClCAEIBQFpBmNhbGxlcgQNJHQwMTYxODExNjMyNgkBDHVwZGF0ZVJld2FyZAIFB19zdGFrZXIAAAQXbmV3UmV3YXJkUGVyVG9rZW5TdG9yZWQIBQ0kdDAxNjE4MTE2MzI2Al8xBBFuZXdMYXN0VXBkYXRlVGltZQgFDSR0MDE2MTgxMTYzMjYCXzIEDHN0YWtlckVhcm5lZAgFDSR0MDE2MTgxMTYzMjYCXzMEGHN0YWtlclJld2FyZFBlclRva2VuUGFpZAgFDSR0MDE2MTgxMTYzMjYCXzQDAwkAZwIAAAUMc3Rha2VyRWFybmVkBgkBASEBCQELaW5pdGlhbGl6ZWQACQACAQIQTm8gcmV3YXJkOiBWYXVsdAkAzggCCQDOCAIJAM4IAgkAzggCCQERdXBkYXRlVXNlclJld2FyZHMDBQdfc3Rha2VyAAAFGHN0YWtlclJld2FyZFBlclRva2VuUGFpZAkBGnVwZGF0ZVJld2FyZFBlclRva2VuU3RvcmVkAQUXbmV3UmV3YXJkUGVyVG9rZW5TdG9yZWQJAQp1cGRhdGVUaW1lAgURbmV3TGFzdFVwZGF0ZVRpbWUJAQxwZXJpb2RGaW5pc2gACQETdXBkYXRlUmV3YXJkQmFsYW5jZQEJAQEtAQUMc3Rha2VyRWFybmVkCQDMCAIJAQ5TY3JpcHRUcmFuc2ZlcgMIBQFpBmNhbGxlcgUMc3Rha2VyRWFybmVkCQEPZ292ZXJuYW5jZUFzc2V0AAUDbmlsAWkBB2FkZEZyZWUABAdfYW1vdW50CQEPYXNzZXRUb0RlY2ltYWxzAQgJAJEDAggFAWkIcGF5bWVudHMAAAZhbW91bnQDAwMDCQECIT0CCAkAkQMCCAUBaQhwYXltZW50cwAAB2Fzc2V0SWQJAQp2YXVsdEFzc2V0AAYJAQIhPQIJAJADAQgFAWkIcGF5bWVudHMAAQYJAQEhAQkBC2luaXRpYWxpemVkAAYJAQEhAQMJAQtpc1doaXRlbGlzdAEJAKUIAQgFAWkGY2FsbGVyBgkAAAIIBQFpBmNhbGxlcgkBDGFkbWluQWRkcmVzcwAJAAIBAhZJbnZhbGlkIGFkZEZyZWUgcGFyYW1zBAduZXdSYXRlCQEOY29tcHV0ZU5ld1JhdGUBBQdfYW1vdW50BAVzdGFrZQkA/AcECQEObWFuYWdlckFkZHJlc3MAAgdkZXBvc2l0BQNuaWwJAMwIAgkBD0F0dGFjaGVkUGF5bWVudAIJAQp2YXVsdEFzc2V0AAkBEWFzc2V0RnJvbURlY2ltYWxzAQUHX2Ftb3VudAUDbmlsAwkAAAIFBXN0YWtlBQVzdGFrZQkAzggCCQERdXBkYXRlRnJlZUJhbGFuY2UBBQdfYW1vdW50CQEKdXBkYXRlUmF0ZQEFB25ld1JhdGUJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQEJYWRkTG9ja2VkAAQHX2Ftb3VudAkBD2Fzc2V0VG9EZWNpbWFscwEICQCRAwIIBQFpCHBheW1lbnRzAAAGYW1vdW50AwMDAwkBAiE9AggJAJEDAggFAWkIcGF5bWVudHMAAAdhc3NldElkCQEKdmF1bHRBc3NldAAGCQECIT0CCQCQAwEIBQFpCHBheW1lbnRzAAEGCQEBIQEJAQtpbml0aWFsaXplZAAGCQEBIQEDCQELaXNXaGl0ZWxpc3QBCQClCAEIBQFpBmNhbGxlcgYJAAACCAUBaQZjYWxsZXIJAQxhZG1pbkFkZHJlc3MACQACAQIYSW52YWxpZCBhZGRMb2NrZWQgcGFyYW1zBAd1bnN0YWtlCQD8BwQJAQ5tYW5hZ2VyQWRkcmVzcwACB2RlcG9zaXQFA25pbAkAzAgCCQEPQXR0YWNoZWRQYXltZW50AgkBCnZhdWx0QXNzZXQACQERYXNzZXRGcm9tRGVjaW1hbHMBBQdfYW1vdW50BQNuaWwDCQAAAgUHdW5zdGFrZQUHdW5zdGFrZQkBE3VwZGF0ZUxvY2tlZEJhbGFuY2UBBQdfYW1vdW50CQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBFWV4Y2hhbmdlRnJlZUFuZExvY2tlZAEHX2Ftb3VudAMDCQEBIQEJAQtpbml0aWFsaXplZAAGAwkBASEBCQELaXNXaGl0ZWxpc3QBCQClCAEIBQFpBmNhbGxlcgkBAiE9AggFAWkGY2FsbGVyCQEMYWRtaW5BZGRyZXNzAAcJAAIBAiRJbnZhbGlkIGV4Y2hhbmdlRnJlZUFuZExvY2tlZCBwYXJhbXMEEmFtb3VudE9mUXVvdGVBc3NldAkBD2Fzc2V0VG9EZWNpbWFscwEFB19hbW91bnQEB25ld1JhdGUJAQ5jb21wdXRlTmV3UmF0ZQEJAQEtAQUSYW1vdW50T2ZRdW90ZUFzc2V0CQDOCAIJAM4IAgkBE3VwZGF0ZUxvY2tlZEJhbGFuY2UBBRJhbW91bnRPZlF1b3RlQXNzZXQJARF1cGRhdGVGcmVlQmFsYW5jZQEJAQEtAQUSYW1vdW50T2ZRdW90ZUFzc2V0CQEKdXBkYXRlUmF0ZQEFB25ld1JhdGUBaQEOd2l0aGRyYXdMb2NrZWQBB19hbW91bnQDAwMJAQEhAQkBC2luaXRpYWxpemVkAAYJAGcCAAAFB19hbW91bnQGCQEBIQEJAQtpc1doaXRlbGlzdAEJAKUIAQgFAWkGY2FsbGVyCQACAQIdSW52YWxpZCB3aXRoZHJhd0xvY2tlZCBwYXJhbXMEEmFtb3VudE9mUXVvdGVBc3NldAkBD2Fzc2V0VG9EZWNpbWFscwEFB19hbW91bnQEB3Vuc3Rha2UJAPwHBAkBDm1hbmFnZXJBZGRyZXNzAAIId2l0aGRyYXcJAMwIAgkBDXZhdWx0QXNzZXRTdHIACQDMCAIJARFhc3NldEZyb21EZWNpbWFscwEFEmFtb3VudE9mUXVvdGVBc3NldAUDbmlsBQNuaWwDCQAAAgUHdW5zdGFrZQUHdW5zdGFrZQkAzggCCQETdXBkYXRlTG9ja2VkQmFsYW5jZQEJAQEtAQUSYW1vdW50T2ZRdW90ZUFzc2V0CQDMCAIJAQ5TY3JpcHRUcmFuc2ZlcgMIBQFpBmNhbGxlcgkBEWFzc2V0RnJvbURlY2ltYWxzAQUSYW1vdW50T2ZRdW90ZUFzc2V0CQEKdmF1bHRBc3NldAAFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpAQphZGRSZXdhcmRzAAMDAwkBAiE9AggJAJEDAggFAWkIcGF5bWVudHMAAAdhc3NldElkCQEPZ292ZXJuYW5jZUFzc2V0AAYJAQIhPQIJAJADAQgFAWkIcGF5bWVudHMAAQYJAQEhAQkBC2luaXRpYWxpemVkAAkAAgECGUludmFsaWQgYWRkUmV3YXJkcyBwYXJhbXMEB19yZXdhcmQICQCRAwIIBQFpCHBheW1lbnRzAAAGYW1vdW50BBduZXdSZXdhcmRQZXJUb2tlblN0b3JlZAgJAQx1cGRhdGVSZXdhcmQCBQpOT19BRERSRVNTBQlOT19TVEFLRVICXzEECXRpbWVzdGFtcAkBE2N1cnJlbnRUaW1lc3RhbXBTZWMABA1uZXdSZXdhcmRSYXRlAwkAZgIFCXRpbWVzdGFtcAkBDHBlcmlvZEZpbmlzaAAJAGkCBQdfcmV3YXJkBQhEVVJBVElPTgQNcmVtYWluaW5nVGltZQkAZQIJAQxwZXJpb2RGaW5pc2gABQl0aW1lc3RhbXAECGxlZnRvdmVyCQBoAgkBCnJld2FyZFJhdGUABQ1yZW1haW5pbmdUaW1lCQBpAgkAZAIFB19yZXdhcmQFCGxlZnRvdmVyBQhEVVJBVElPTgkAzggCCQDOCAIJAM4IAgkBEHVwZGF0ZVJld2FyZFJhdGUBBQ1uZXdSZXdhcmRSYXRlCQEadXBkYXRlUmV3YXJkUGVyVG9rZW5TdG9yZWQBBRduZXdSZXdhcmRQZXJUb2tlblN0b3JlZAkBE3VwZGF0ZVJld2FyZEJhbGFuY2UBBQdfcmV3YXJkCQEKdXBkYXRlVGltZQIFCXRpbWVzdGFtcAkAZAIFCXRpbWVzdGFtcAUIRFVSQVRJT04BaQEKYWNrUmV3YXJkcwAECnByb2ZpdFJlc3AJAPwHBAkBDm1hbmFnZXJBZGRyZXNzAAILY2xhaW1Qcm9maXQJAMwIAgkBDXZhdWx0QXNzZXRTdHIABQNuaWwFA25pbAMJAAACBQpwcm9maXRSZXNwBQpwcm9maXRSZXNwBAZwcm9maXQEByRtYXRjaDAFCnByb2ZpdFJlc3ADCQABAgUHJG1hdGNoMAIDSW50BAFwBQckbWF0Y2gwCQEPYXNzZXRUb0RlY2ltYWxzAQUBcAkAAgECHEludmFsaWQgY2xhaW1Qcm9maXQgcmVzcG9uc2UEBnJlc3VsdAMJAGYCBQZwcm9maXQAAAQHbmV3UmF0ZQkBDmNvbXB1dGVOZXdSYXRlAQUGcHJvZml0BAVzdGFrZQkA/AcECQEObWFuYWdlckFkZHJlc3MAAgdkZXBvc2l0BQNuaWwJAMwIAgkBD0F0dGFjaGVkUGF5bWVudAIJAQp2YXVsdEFzc2V0AAkBEWFzc2V0RnJvbURlY2ltYWxzAQUGcHJvZml0BQNuaWwDCQAAAgUFc3Rha2UFBXN0YWtlCQDOCAIJARF1cGRhdGVGcmVlQmFsYW5jZQEFBnByb2ZpdAkBCnVwZGF0ZVJhdGUBBQduZXdSYXRlCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuBQNuaWwDCQAAAgUGcmVzdWx0BQZyZXN1bHQFBnJlc3VsdAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpAQt2aWV3X3Jld2FyZAEHX3N0YWtlcgQHYmFsYW5jZQkBCWJhbGFuY2VPZgEFB19zdGFrZXIED2RlcG9zaXRlZEFtb3VudAkBBG11bGQCCQELYXZlcmFnZVJhdGUBBQdfc3Rha2VyBQdiYWxhbmNlBA1jdXJyZW50QW1vdW50CQEEbXVsZAIJAQRyYXRlAAUHYmFsYW5jZQQLZWFybmVkUXVvdGUJAGUCBQ1jdXJyZW50QW1vdW50BQ9kZXBvc2l0ZWRBbW91bnQJAAIBCQCkAwEFC2Vhcm5lZFF1b3RlAWkBEnZpZXdfc3Rha2luZ1Jld2FyZAEHX3N0YWtlcgQMc3Rha2VyRWFybmVkCAkBDHVwZGF0ZVJld2FyZAIFB19zdGFrZXIAAAJfMwkAAgEJAKQDAQkBEWFzc2V0RnJvbURlY2ltYWxzAQUMc3Rha2VyRWFybmVkAWkBEnZpZXdfd2l0aGRyYXdMaW1pdAEHX3N0YWtlcgQRd2l0aGRyYXdMaW1pdExlZnQICQEUZ2V0V2l0aGRyYXdMaW1pdExlZnQBBQdfc3Rha2VyAl8yBAxsaW1pdEluQXNzZXQJARFhc3NldEZyb21EZWNpbWFscwEJAQRtdWxkAgURd2l0aGRyYXdMaW1pdExlZnQJAQRyYXRlAAkAAgEJAKQDAQUMbGltaXRJbkFzc2V0AQJ0eAEGdmVyaWZ5AAQOY29vcmRpbmF0b3JTdHIJAJ0IAgUEdGhpcwUUa19jb29yZGluYXRvckFkZHJlc3MDCQEJaXNEZWZpbmVkAQUOY29vcmRpbmF0b3JTdHIEBWFkbWluCQCdCAIJARFAZXh0ck5hdGl2ZSgxMDYyKQEJAQV2YWx1ZQEFDmNvb3JkaW5hdG9yU3RyBQ9rX2FkbWluX2FkZHJlc3MDCQEJaXNEZWZpbmVkAQUFYWRtaW4JAQt2YWx1ZU9yRWxzZQIJAJsIAgkBEUBleHRyTmF0aXZlKDEwNjIpAQkBBXZhbHVlAQUFYWRtaW4JAKwCAgkArAICCQCsAgICB3N0YXR1c18JAKUIAQUEdGhpcwIBXwkA2AQBCAUCdHgCaWQHCQACAQIudW5hYmxlIHRvIHZlcmlmeTogYWRtaW4gbm90IHNldCBpbiBjb29yZGluYXRvcgkA9AMDCAUCdHgJYm9keUJ5dGVzCQCRAwIIBQJ0eAZwcm9vZnMAAAgFAnR4D3NlbmRlclB1YmxpY0tleQ8opKU=", "height": 2590541, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: 2QoWuWcA2umuD9Yu51yKg4ebM7PwtNseQGWN3tSmTdMY Next: 4Q8aTwvsuvBCZwaVPcpBpxNRzQVB8Ga495FPtbZjN6o7 Diff:
OldNewDifferences
88 let k_lockedBalance = "k_lockedBalance"
99
1010 let k_freeBalance = "k_freeBalance"
11+
12+let k_excessBalance = "k_excessBalance"
13+
14+let k_vaultAsset = "k_vaultAsset"
15+
16+let k_vaultAssetDecimals = "k_vaultAssetDecimals"
17+
18+let k_maxSpotUtilization = "k_maxSpotUtilization"
1119
1220 let k_rate = "k_rate"
1321
4755
4856 let k_manager_address = "k_manager_address"
4957
58+let k_spot_address = "k_spot_address"
59+
5060 let k_collateral_address = "k_collateral_address"
5161
5262 func toCompositeKey (_key,_address) = ((_key + "_") + _address)
6474 func governanceAsset () = fromBase58String(valueOrErrorMessage(getString(coordinator(), k_governance_asset), "Governance asset not set"))
6575
6676
67-func quoteAsset () = fromBase58String(valueOrErrorMessage(getString(coordinator(), k_quote_asset), "Quote asset not set"))
77+func quoteAsset () = fromBase58String(getStringValue(coordinator(), k_quote_asset))
78+
79+
80+func vaultAssetStr () = valueOrErrorMessage(getString(this, k_vaultAsset), "Vault asset not set")
81+
82+
83+func vaultAsset () = {
84+ let _assetIdStr = vaultAssetStr()
85+ if ((_assetIdStr == "WAVES"))
86+ then unit
87+ else fromBase58String(_assetIdStr)
88+ }
89+
90+
91+func vaultAssetDecimals () = valueOrErrorMessage(getInteger(this, k_vaultAssetDecimals), "Vault asset decimals not set")
6892
6993
7094 func managerAddress () = valueOrErrorMessage(addressFromString(valueOrErrorMessage(getString(coordinator(), k_manager_address), "Manager address not set")), "Manager address invalid")
78102
79103 let NO_STAKER = 0
80104
81-func usdnFromDecimals (_amount) = (_amount / 100)
105+func assetFromDecimals (_amount) = {
106+ let assetDecimals = vaultAssetDecimals()
107+ if ((assetDecimals == 6))
108+ then (_amount / 100)
109+ else if ((assetDecimals == 8))
110+ then _amount
111+ else throw("Invalid asset decimals")
112+ }
82113
83114
84-func usdnToDecimals (_amount) = (_amount * 100)
115+func assetToDecimals (_amount) = {
116+ let assetDecimals = vaultAssetDecimals()
117+ if ((assetDecimals == 6))
118+ then (_amount * 100)
119+ else if ((assetDecimals == 8))
120+ then _amount
121+ else throw("Invalid asset decimals")
122+ }
85123
86124
87125 func divd (_x,_y) = fraction(_x, DECIMAL_UNIT, _y, HALFEVEN)
140178 func lockedBalance () = int0(k_lockedBalance)
141179
142180
181+func excessBalance () = int0(k_excessBalance)
182+
183+
143184 func rewardPerTokenStored () = int0(k_rewardPerTokenStored)
144185
145186
161202 func userRewardPerTokenPaid (_staker) = int0(toCompositeKey(k_userRewardPerToken, _staker))
162203
163204
205+func maxSpotUtilization () = int0(k_maxSpotUtilization)
206+
207+
164208 func initialized () = valueOrElse(getBoolean(this, k_initialized), false)
165209
166210
173217 func getWithdrawLimitLeft (_staker) = {
174218 let currentDate = currentTimestamp()
175219 let lastWithdrawDate = lastWithdrawnDate(_staker)
176- let $t049895310 = if (((currentDate - lastWithdrawDate) > WITHDRAW_PERIOD))
220+ let $t062676588 = if (((currentDate - lastWithdrawDate) > WITHDRAW_PERIOD))
177221 then $Tuple3(currentDate, withdrawLimit(_staker), 0)
178222 else $Tuple3(lastWithdrawDate, (withdrawLimit(_staker) - withdrawnInPeriod(_staker)), withdrawnInPeriod(_staker))
179- let newLastWithdrawnDate = $t049895310._1
180- let withdrawLimitLeft = $t049895310._2
181- let alreadyWithdrawnInPeriod = $t049895310._3
223+ let newLastWithdrawnDate = $t062676588._1
224+ let withdrawLimitLeft = $t062676588._2
225+ let alreadyWithdrawnInPeriod = $t062676588._3
182226 $Tuple3(newLastWithdrawnDate, withdrawLimitLeft, alreadyWithdrawnInPeriod)
183227 }
184228
215259 func updateReward (_staker,_balanceDelta) = {
216260 let newRewardPerTokenStored = rewardPerToken(_balanceDelta)
217261 let newLastUpdateTime = currentTimestampSec()
218- let $t065326724 = if ((_staker != ""))
262+ let $t078108002 = if ((_staker != ""))
219263 then $Tuple2(earned(_staker, _balanceDelta), newRewardPerTokenStored)
220264 else $Tuple2(0, 0)
221- let stakerEarned = $t065326724._1
222- let stakerRewardPerTokenPaid = $t065326724._2
265+ let stakerEarned = $t078108002._1
266+ let stakerRewardPerTokenPaid = $t078108002._2
223267 $Tuple4(newRewardPerTokenStored, newLastUpdateTime, stakerEarned, stakerRewardPerTokenPaid)
224268 }
225269
251295 }
252296
253297
298+func updateExcessBalance (_change) = {
299+ let newImbalance = (excessBalance() + _change)
300+ let utilizationRate = divd(abs(newImbalance), freeBalance())
301+ if ((maxSpotUtilization() > utilizationRate))
302+ then [IntegerEntry(k_excessBalance, newImbalance)]
303+ else throw(((((((("Vault: can not update excess balance. Balance: " + toString(excessBalance())) + " change: ") + toString(_change)) + " utilization rate: ") + toString(utilizationRate)) + " max utilization rate: ") + toString(maxSpotUtilization())))
304+ }
305+
306+
254307 func updateTotalSupply (_change) = [IntegerEntry(k_totalSupply, (totalSupply() + _change))]
255308
256309
276329
277330
278331 @Callable(i)
279-func initialize (_coordinator) = if (if (initialized())
332+func initialize (_coordinator,_vaultAsset,_maxSpotUtilization) = if (if (if (if (initialized())
280333 then true
281334 else (i.caller != this))
335+ then true
336+ else (0 > _maxSpotUtilization))
337+ then true
338+ else (_maxSpotUtilization > DECIMAL_UNIT))
282339 then throw("Unable to initialize")
283- else [StringEntry(k_coordinatorAddress, toString(valueOrErrorMessage(addressFromString(_coordinator), "Invalid coordinator address"))), BooleanEntry(k_initialized, true)]
340+ else {
341+ let assetDecimals = if ((_vaultAsset == "WAVES"))
342+ then 8
343+ else {
344+ let info = valueOrErrorMessage(assetInfo(fromBase58String(_vaultAsset)), ("Invalid token id: " + _vaultAsset))
345+ info.decimals
346+ }
347+[StringEntry(k_coordinatorAddress, toString(valueOrErrorMessage(addressFromString(_coordinator), "Invalid coordinator address"))), StringEntry(k_vaultAsset, _vaultAsset), IntegerEntry(k_vaultAssetDecimals, assetDecimals), IntegerEntry(k_maxSpotUtilization, _maxSpotUtilization), BooleanEntry(k_initialized, true)]
348+ }
284349
285350
286351
287352 @Callable(i)
288353 func stake () = {
289354 let _staker = toString(i.caller)
290- let _amount = usdnToDecimals(i.payments[0].amount)
291- if (if (if ((i.payments[0].assetId != quoteAsset()))
355+ let _amount = assetToDecimals(i.payments[0].amount)
356+ if (if (if ((i.payments[0].assetId != vaultAsset()))
292357 then true
293358 else (size(i.payments) != 1))
294359 then true
295360 else !(initialized()))
296361 then throw("Invalid call to stake")
297362 else {
298- let $t01017610405 = updateReward(_staker, 0)
299- let newRewardPerTokenStored = $t01017610405._1
300- let newLastUpdateTime = $t01017610405._2
301- let stakerEarned = $t01017610405._3
302- let stakerRewardPerTokenPaid = $t01017610405._4
363+ let $t01253712766 = updateReward(_staker, 0)
364+ let newRewardPerTokenStored = $t01253712766._1
365+ let newLastUpdateTime = $t01253712766._2
366+ let stakerEarned = $t01253712766._3
367+ let stakerRewardPerTokenPaid = $t01253712766._4
303368 let currentRate = rate()
304369 let prevAverageRate = averageRate(_staker)
305370 let vAmount = divd(_amount, currentRate)
306371 let newAverageRate = divd((muld(vAmount, currentRate) + muld(balanceOf(_staker), prevAverageRate)), (vAmount + balanceOf(_staker)))
307372 let newTotalBalance = (vAmount + balanceOf(_staker))
308373 let newWithdrawLimit = muld(newTotalBalance, WITHDRAW_PER_PERIOD)
309- let stake = invoke(managerAddress(), "deposit", nil, [AttachedPayment(quoteAsset(), usdnFromDecimals(_amount))])
374+ let stake = invoke(managerAddress(), "deposit", nil, [AttachedPayment(vaultAsset(), assetFromDecimals(_amount))])
310375 if ((stake == stake))
311376 then (((((((updateUserRewards(_staker, stakerEarned, stakerRewardPerTokenPaid) ++ updateRewardPerTokenStored(newRewardPerTokenStored)) ++ updateTime(newLastUpdateTime, periodFinish())) ++ updateFreeBalance(_amount)) ++ updateUserBalance(_staker, vAmount)) ++ setUserAverageRate(_staker, newAverageRate)) ++ setUserWithdrawLimit(_staker, newWithdrawLimit)) ++ updateTotalSupply(vAmount))
312377 else throw("Strict value is not equal to itself.")
318383 @Callable(i)
319384 func unStake (_amount) = {
320385 let _staker = toString(i.caller)
321- let amountOfQuoteAsset = usdnToDecimals(_amount)
386+ let amountOfQuoteAsset = assetToDecimals(_amount)
322387 if (if (if ((i.payments != nil))
323388 then true
324389 else (0 >= amountOfQuoteAsset))
326391 else !(initialized()))
327392 then throw("Invalid call to unStake")
328393 else {
329- let $t01175811974 = updateReward(_staker, 0)
330- let newRewardPerTokenStored = $t01175811974._1
331- let newLastUpdateTime = $t01175811974._2
332- let stakerEarned = $t01175811974._3
333- let stakerRewardPerTokenPaid = $t01175811974._4
334- let $t01198112148 = getWithdrawLimitLeft(_staker)
335- let newLastWithdrawnDate = $t01198112148._1
336- let withdrawLimitLeft = $t01198112148._2
337- let alreadyWithdrawnInPeriod = $t01198112148._3
394+ let $t01427414490 = updateReward(_staker, 0)
395+ let newRewardPerTokenStored = $t01427414490._1
396+ let newLastUpdateTime = $t01427414490._2
397+ let stakerEarned = $t01427414490._3
398+ let stakerRewardPerTokenPaid = $t01427414490._4
399+ let $t01449714664 = getWithdrawLimitLeft(_staker)
400+ let newLastWithdrawnDate = $t01449714664._1
401+ let withdrawLimitLeft = $t01449714664._2
402+ let alreadyWithdrawnInPeriod = $t01449714664._3
338403 let vAmount = divd(amountOfQuoteAsset, rate())
339404 if ((vAmount > withdrawLimitLeft))
340405 then throw("Invalid call to unStake: withdraw over limit")
343408 if ((amountOfQuoteAsset > freeBalance()))
344409 then throw("Invalid call to unStake: balance too low")
345410 else {
346- let unstake = invoke(managerAddress(), "withdraw", [toBase58String(quoteAsset()), usdnFromDecimals(amountOfQuoteAsset)], nil)
411+ let unstake = invoke(managerAddress(), "withdraw", [vaultAssetStr(), assetFromDecimals(amountOfQuoteAsset)], nil)
347412 if ((unstake == unstake))
348- then (((((((updateUserRewards(_staker, stakerEarned, stakerRewardPerTokenPaid) ++ updateRewardPerTokenStored(newRewardPerTokenStored)) ++ updateTime(newLastUpdateTime, periodFinish())) ++ updateFreeBalance(-(amountOfQuoteAsset))) ++ updateUserBalance(_staker, -(vAmount))) ++ updateTotalSupply(-(vAmount))) ++ setUserWithdrawParams(_staker, newLastWithdrawnDate, newWithdrawnInPeriod)) ++ [ScriptTransfer(i.caller, usdnFromDecimals(amountOfQuoteAsset), quoteAsset())])
413+ then (((((((updateUserRewards(_staker, stakerEarned, stakerRewardPerTokenPaid) ++ updateRewardPerTokenStored(newRewardPerTokenStored)) ++ updateTime(newLastUpdateTime, periodFinish())) ++ updateFreeBalance(-(amountOfQuoteAsset))) ++ updateUserBalance(_staker, -(vAmount))) ++ updateTotalSupply(-(vAmount))) ++ setUserWithdrawParams(_staker, newLastWithdrawnDate, newWithdrawnInPeriod)) ++ [ScriptTransfer(i.caller, assetFromDecimals(amountOfQuoteAsset), vaultAsset())])
349414 else throw("Strict value is not equal to itself.")
350415 }
351416 }
357422 @Callable(i)
358423 func withdrawRewards () = {
359424 let _staker = toString(i.caller)
360- let $t01348413629 = updateReward(_staker, 0)
361- let newRewardPerTokenStored = $t01348413629._1
362- let newLastUpdateTime = $t01348413629._2
363- let stakerEarned = $t01348413629._3
364- let stakerRewardPerTokenPaid = $t01348413629._4
425+ let $t01618116326 = updateReward(_staker, 0)
426+ let newRewardPerTokenStored = $t01618116326._1
427+ let newLastUpdateTime = $t01618116326._2
428+ let stakerEarned = $t01618116326._3
429+ let stakerRewardPerTokenPaid = $t01618116326._4
365430 if (if ((0 >= stakerEarned))
366431 then true
367432 else !(initialized()))
373438
374439 @Callable(i)
375440 func addFree () = {
376- let _amount = usdnToDecimals(i.payments[0].amount)
377- if (if (if (if ((i.payments[0].assetId != quoteAsset()))
441+ let _amount = assetToDecimals(i.payments[0].amount)
442+ if (if (if (if ((i.payments[0].assetId != vaultAsset()))
378443 then true
379444 else (size(i.payments) != 1))
380445 then true
386451 then throw("Invalid addFree params")
387452 else {
388453 let newRate = computeNewRate(_amount)
389- let stake = invoke(managerAddress(), "deposit", nil, [AttachedPayment(quoteAsset(), usdnFromDecimals(_amount))])
454+ let stake = invoke(managerAddress(), "deposit", nil, [AttachedPayment(vaultAsset(), assetFromDecimals(_amount))])
390455 if ((stake == stake))
391456 then (updateFreeBalance(_amount) ++ updateRate(newRate))
392457 else throw("Strict value is not equal to itself.")
397462
398463 @Callable(i)
399464 func addLocked () = {
400- let _amount = usdnToDecimals(i.payments[0].amount)
401- if (if (if (if ((i.payments[0].assetId != quoteAsset()))
465+ let _amount = assetToDecimals(i.payments[0].amount)
466+ if (if (if (if ((i.payments[0].assetId != vaultAsset()))
402467 then true
403468 else (size(i.payments) != 1))
404469 then true
409474 else (i.caller == adminAddress())))
410475 then throw("Invalid addLocked params")
411476 else {
412- let unstake = invoke(managerAddress(), "deposit", nil, [AttachedPayment(quoteAsset(), usdnFromDecimals(_amount))])
477+ let unstake = invoke(managerAddress(), "deposit", nil, [AttachedPayment(vaultAsset(), assetFromDecimals(_amount))])
413478 if ((unstake == unstake))
414479 then updateLockedBalance(_amount)
415480 else throw("Strict value is not equal to itself.")
426491 else false)
427492 then throw("Invalid exchangeFreeAndLocked params")
428493 else {
429- let amountOfQuoteAsset = usdnToDecimals(_amount)
494+ let amountOfQuoteAsset = assetToDecimals(_amount)
430495 let newRate = computeNewRate(-(amountOfQuoteAsset))
431496 ((updateLockedBalance(amountOfQuoteAsset) ++ updateFreeBalance(-(amountOfQuoteAsset))) ++ updateRate(newRate))
432497 }
441506 else !(isWhitelist(toString(i.caller))))
442507 then throw("Invalid withdrawLocked params")
443508 else {
444- let amountOfQuoteAsset = usdnToDecimals(_amount)
445- let unstake = invoke(managerAddress(), "withdraw", [toBase58String(quoteAsset()), usdnFromDecimals(amountOfQuoteAsset)], nil)
509+ let amountOfQuoteAsset = assetToDecimals(_amount)
510+ let unstake = invoke(managerAddress(), "withdraw", [vaultAssetStr(), assetFromDecimals(amountOfQuoteAsset)], nil)
446511 if ((unstake == unstake))
447- then (updateLockedBalance(-(amountOfQuoteAsset)) ++ [ScriptTransfer(i.caller, usdnFromDecimals(amountOfQuoteAsset), quoteAsset())])
512+ then (updateLockedBalance(-(amountOfQuoteAsset)) ++ [ScriptTransfer(i.caller, assetFromDecimals(amountOfQuoteAsset), vaultAsset())])
448513 else throw("Strict value is not equal to itself.")
449514 }
450515
475540
476541 @Callable(i)
477542 func ackRewards () = {
478- let profitResp = invoke(managerAddress(), "claimProfit", [toBase58String(quoteAsset())], nil)
543+ let profitResp = invoke(managerAddress(), "claimProfit", [vaultAssetStr()], nil)
479544 if ((profitResp == profitResp))
480545 then {
481546 let profit = match profitResp {
482547 case p: Int =>
483- usdnToDecimals(p)
548+ assetToDecimals(p)
484549 case _ =>
485550 throw("Invalid claimProfit response")
486551 }
487552 let result = if ((profit > 0))
488553 then {
489554 let newRate = computeNewRate(profit)
490- let stake = invoke(managerAddress(), "deposit", nil, [AttachedPayment(quoteAsset(), usdnFromDecimals(profit))])
555+ let stake = invoke(managerAddress(), "deposit", nil, [AttachedPayment(vaultAsset(), assetFromDecimals(profit))])
491556 if ((stake == stake))
492557 then (updateFreeBalance(profit) ++ updateRate(newRate))
493558 else throw("Strict value is not equal to itself.")
516581 @Callable(i)
517582 func view_stakingReward (_staker) = {
518583 let stakerEarned = updateReward(_staker, 0)._3
519- throw(toString(usdnFromDecimals(stakerEarned)))
584+ throw(toString(assetFromDecimals(stakerEarned)))
520585 }
521586
522587
524589 @Callable(i)
525590 func view_withdrawLimit (_staker) = {
526591 let withdrawLimitLeft = getWithdrawLimitLeft(_staker)._2
527- let limitInUsdn = usdnFromDecimals(muld(withdrawLimitLeft, rate()))
528- throw(toString(limitInUsdn))
592+ let limitInAsset = assetFromDecimals(muld(withdrawLimitLeft, rate()))
593+ throw(toString(limitInAsset))
529594 }
530595
531596
Full:
OldNewDifferences
11 {-# STDLIB_VERSION 6 #-}
22 {-# SCRIPT_TYPE ACCOUNT #-}
33 {-# CONTENT_TYPE DAPP #-}
44 let k_totalSupply = "k_totalSupply"
55
66 let k_rewardBalance = "k_rewardBalance"
77
88 let k_lockedBalance = "k_lockedBalance"
99
1010 let k_freeBalance = "k_freeBalance"
11+
12+let k_excessBalance = "k_excessBalance"
13+
14+let k_vaultAsset = "k_vaultAsset"
15+
16+let k_vaultAssetDecimals = "k_vaultAssetDecimals"
17+
18+let k_maxSpotUtilization = "k_maxSpotUtilization"
1119
1220 let k_rate = "k_rate"
1321
1422 let k_lastUpdateTime = "k_lastUpdateTime"
1523
1624 let k_rewardPerTokenStored = "k_rewardPerTokenStored"
1725
1826 let k_rewardRate = "k_rewardRate"
1927
2028 let k_periodFinish = "k_periodFinish"
2129
2230 let k_userRewardPerToken = "k_userRewardPerToken"
2331
2432 let k_userReward = "k_userReward"
2533
2634 let k_balance = "k_balance"
2735
2836 let k_average_rate = "k_average_rate"
2937
3038 let k_withdraw_limit = "k_withdraw_limit"
3139
3240 let k_last_withdraw_date = "k_last_withdraw_date"
3341
3442 let k_withdraw_in_period = "k_withdraw_in_period"
3543
3644 let k_initialized = "k_initialized"
3745
3846 let k_coordinatorAddress = "k_coordinatorAddress"
3947
4048 let k_amm = "k_amm"
4149
4250 let k_governance_asset = "k_gov_asset"
4351
4452 let k_quote_asset = "k_quote_asset"
4553
4654 let k_admin_address = "k_admin_address"
4755
4856 let k_manager_address = "k_manager_address"
4957
58+let k_spot_address = "k_spot_address"
59+
5060 let k_collateral_address = "k_collateral_address"
5161
5262 func toCompositeKey (_key,_address) = ((_key + "_") + _address)
5363
5464
5565 func coordinator () = valueOrErrorMessage(addressFromString(valueOrErrorMessage(getString(this, k_coordinatorAddress), "Coordinator not set")), "Coordinator address invalid")
5666
5767
5868 func adminAddress () = addressFromString(valueOrErrorMessage(getString(coordinator(), k_admin_address), "Admin address not set"))
5969
6070
6171 func isWhitelist (_address) = valueOrElse(getBoolean(coordinator(), toCompositeKey(k_amm, _address)), false)
6272
6373
6474 func governanceAsset () = fromBase58String(valueOrErrorMessage(getString(coordinator(), k_governance_asset), "Governance asset not set"))
6575
6676
67-func quoteAsset () = fromBase58String(valueOrErrorMessage(getString(coordinator(), k_quote_asset), "Quote asset not set"))
77+func quoteAsset () = fromBase58String(getStringValue(coordinator(), k_quote_asset))
78+
79+
80+func vaultAssetStr () = valueOrErrorMessage(getString(this, k_vaultAsset), "Vault asset not set")
81+
82+
83+func vaultAsset () = {
84+ let _assetIdStr = vaultAssetStr()
85+ if ((_assetIdStr == "WAVES"))
86+ then unit
87+ else fromBase58String(_assetIdStr)
88+ }
89+
90+
91+func vaultAssetDecimals () = valueOrErrorMessage(getInteger(this, k_vaultAssetDecimals), "Vault asset decimals not set")
6892
6993
7094 func managerAddress () = valueOrErrorMessage(addressFromString(valueOrErrorMessage(getString(coordinator(), k_manager_address), "Manager address not set")), "Manager address invalid")
7195
7296
7397 let DECIMAL_UNIT = (1 * (((((((10 * 10) * 10) * 10) * 10) * 10) * 10) * 10))
7498
7599 let DURATION = (((7 * 60) * 60) * 24)
76100
77101 let NO_ADDRESS = ""
78102
79103 let NO_STAKER = 0
80104
81-func usdnFromDecimals (_amount) = (_amount / 100)
105+func assetFromDecimals (_amount) = {
106+ let assetDecimals = vaultAssetDecimals()
107+ if ((assetDecimals == 6))
108+ then (_amount / 100)
109+ else if ((assetDecimals == 8))
110+ then _amount
111+ else throw("Invalid asset decimals")
112+ }
82113
83114
84-func usdnToDecimals (_amount) = (_amount * 100)
115+func assetToDecimals (_amount) = {
116+ let assetDecimals = vaultAssetDecimals()
117+ if ((assetDecimals == 6))
118+ then (_amount * 100)
119+ else if ((assetDecimals == 8))
120+ then _amount
121+ else throw("Invalid asset decimals")
122+ }
85123
86124
87125 func divd (_x,_y) = fraction(_x, DECIMAL_UNIT, _y, HALFEVEN)
88126
89127
90128 func muld (_x,_y) = fraction(_x, _y, DECIMAL_UNIT, HALFEVEN)
91129
92130
93131 func abs (_x) = if ((_x > 0))
94132 then _x
95133 else -(_x)
96134
97135
98136 func minv (_x,_y) = if ((_x > _y))
99137 then _y
100138 else _x
101139
102140
103141 let WITHDRAW_PERIOD = (86400 * 1000)
104142
105143 let WITHDRAW_PER_PERIOD = divd((1 * DECIMAL_UNIT), (4 * DECIMAL_UNIT))
106144
107145 func int (k) = valueOrErrorMessage(getInteger(this, k), ("no value for " + k))
108146
109147
110148 func int0 (k) = valueOrElse(getInteger(this, k), 0)
111149
112150
113151 func int1 (k) = valueOrElse(getInteger(this, k), DECIMAL_UNIT)
114152
115153
116154 func totalSupply () = int0(k_totalSupply)
117155
118156
119157 func rate () = int1(k_rate)
120158
121159
122160 func balanceOf (_staker) = int0(toCompositeKey(k_balance, _staker))
123161
124162
125163 func averageRate (_staker) = int0(toCompositeKey(k_average_rate, _staker))
126164
127165
128166 func withdrawLimit (_staker) = int0(toCompositeKey(k_withdraw_limit, _staker))
129167
130168
131169 func withdrawnInPeriod (_staker) = int0(toCompositeKey(k_withdraw_in_period, _staker))
132170
133171
134172 func lastWithdrawnDate (_staker) = int0(toCompositeKey(k_last_withdraw_date, _staker))
135173
136174
137175 func freeBalance () = int0(k_freeBalance)
138176
139177
140178 func lockedBalance () = int0(k_lockedBalance)
141179
142180
181+func excessBalance () = int0(k_excessBalance)
182+
183+
143184 func rewardPerTokenStored () = int0(k_rewardPerTokenStored)
144185
145186
146187 func lastUpdateTime () = int0(k_lastUpdateTime)
147188
148189
149190 func rewardRate () = int0(k_rewardRate)
150191
151192
152193 func periodFinish () = int0(k_periodFinish)
153194
154195
155196 func rewardBalance () = int0(k_rewardBalance)
156197
157198
158199 func rewards (_staker) = int0(toCompositeKey(k_userReward, _staker))
159200
160201
161202 func userRewardPerTokenPaid (_staker) = int0(toCompositeKey(k_userRewardPerToken, _staker))
162203
163204
205+func maxSpotUtilization () = int0(k_maxSpotUtilization)
206+
207+
164208 func initialized () = valueOrElse(getBoolean(this, k_initialized), false)
165209
166210
167211 func currentTimestamp () = lastBlock.timestamp
168212
169213
170214 func currentTimestampSec () = (currentTimestamp() / 1000)
171215
172216
173217 func getWithdrawLimitLeft (_staker) = {
174218 let currentDate = currentTimestamp()
175219 let lastWithdrawDate = lastWithdrawnDate(_staker)
176- let $t049895310 = if (((currentDate - lastWithdrawDate) > WITHDRAW_PERIOD))
220+ let $t062676588 = if (((currentDate - lastWithdrawDate) > WITHDRAW_PERIOD))
177221 then $Tuple3(currentDate, withdrawLimit(_staker), 0)
178222 else $Tuple3(lastWithdrawDate, (withdrawLimit(_staker) - withdrawnInPeriod(_staker)), withdrawnInPeriod(_staker))
179- let newLastWithdrawnDate = $t049895310._1
180- let withdrawLimitLeft = $t049895310._2
181- let alreadyWithdrawnInPeriod = $t049895310._3
223+ let newLastWithdrawnDate = $t062676588._1
224+ let withdrawLimitLeft = $t062676588._2
225+ let alreadyWithdrawnInPeriod = $t062676588._3
182226 $Tuple3(newLastWithdrawnDate, withdrawLimitLeft, alreadyWithdrawnInPeriod)
183227 }
184228
185229
186230 func computeNewRate (_amountOfQuoteAsset) = {
187231 let newRate = if ((totalSupply() > 0))
188232 then divd((freeBalance() + _amountOfQuoteAsset), totalSupply())
189233 else DECIMAL_UNIT
190234 newRate
191235 }
192236
193237
194238 func lastTimeRewardApplicable () = minv(currentTimestampSec(), periodFinish())
195239
196240
197241 func rewardPerToken (_balanceDelta) = if (((totalSupply() + _balanceDelta) == 0))
198242 then rewardPerTokenStored()
199243 else {
200244 let timeInterval = (lastTimeRewardApplicable() - lastUpdateTime())
201245 let actualTimeInterval = if ((0 > timeInterval))
202246 then 0
203247 else timeInterval
204248 let diff = divd((rewardRate() * actualTimeInterval), (totalSupply() + _balanceDelta))
205249 (rewardPerTokenStored() + diff)
206250 }
207251
208252
209253 func earned (_staker,_balanceDelta) = {
210254 let rewardDelta = (rewardPerToken(_balanceDelta) - userRewardPerTokenPaid(_staker))
211255 (muld((balanceOf(_staker) + _balanceDelta), rewardDelta) + rewards(_staker))
212256 }
213257
214258
215259 func updateReward (_staker,_balanceDelta) = {
216260 let newRewardPerTokenStored = rewardPerToken(_balanceDelta)
217261 let newLastUpdateTime = currentTimestampSec()
218- let $t065326724 = if ((_staker != ""))
262+ let $t078108002 = if ((_staker != ""))
219263 then $Tuple2(earned(_staker, _balanceDelta), newRewardPerTokenStored)
220264 else $Tuple2(0, 0)
221- let stakerEarned = $t065326724._1
222- let stakerRewardPerTokenPaid = $t065326724._2
265+ let stakerEarned = $t078108002._1
266+ let stakerRewardPerTokenPaid = $t078108002._2
223267 $Tuple4(newRewardPerTokenStored, newLastUpdateTime, stakerEarned, stakerRewardPerTokenPaid)
224268 }
225269
226270
227271 func updateUserBalance (_user,_change) = if (((balanceOf(_user) + _change) >= 0))
228272 then [IntegerEntry(toCompositeKey(k_balance, _user), (balanceOf(_user) + _change))]
229273 else throw(((("Vault: can not update user balance. Balance: " + toString(balanceOf(_user))) + " change: ") + toString(_change)))
230274
231275
232276 func setUserWithdrawLimit (_user,_rate) = [IntegerEntry(toCompositeKey(k_withdraw_limit, _user), _rate)]
233277
234278
235279 func setUserAverageRate (_user,_rate) = [IntegerEntry(toCompositeKey(k_average_rate, _user), _rate)]
236280
237281
238282 func updateFreeBalance (_change) = {
239283 let balance = freeBalance()
240284 if (((balance + _change) >= 0))
241285 then [IntegerEntry(k_freeBalance, (balance + _change))]
242286 else throw(((("Vault: can not update free balance. Balance: " + toString(balance)) + " change: ") + toString(_change)))
243287 }
244288
245289
246290 func updateLockedBalance (_change) = {
247291 let balance = lockedBalance()
248292 if (((balance + _change) >= 0))
249293 then [IntegerEntry(k_lockedBalance, (balance + _change))]
250294 else throw(((("Vault: can not update locked balance. Balance: " + toString(balance)) + " change: ") + toString(_change)))
251295 }
252296
253297
298+func updateExcessBalance (_change) = {
299+ let newImbalance = (excessBalance() + _change)
300+ let utilizationRate = divd(abs(newImbalance), freeBalance())
301+ if ((maxSpotUtilization() > utilizationRate))
302+ then [IntegerEntry(k_excessBalance, newImbalance)]
303+ else throw(((((((("Vault: can not update excess balance. Balance: " + toString(excessBalance())) + " change: ") + toString(_change)) + " utilization rate: ") + toString(utilizationRate)) + " max utilization rate: ") + toString(maxSpotUtilization())))
304+ }
305+
306+
254307 func updateTotalSupply (_change) = [IntegerEntry(k_totalSupply, (totalSupply() + _change))]
255308
256309
257310 func updateRate (_rate) = [IntegerEntry(k_rate, _rate)]
258311
259312
260313 func setUserWithdrawParams (_user,_lastWithdrawDate,_withdrawn) = [IntegerEntry(toCompositeKey(k_last_withdraw_date, _user), _lastWithdrawDate), IntegerEntry(toCompositeKey(k_withdraw_in_period, _user), _withdrawn)]
261314
262315
263316 func updateRewardBalance (_delta) = [IntegerEntry(k_rewardBalance, (rewardBalance() + _delta))]
264317
265318
266319 func updateRewardRate (_rewardRate) = [IntegerEntry(k_rewardRate, _rewardRate)]
267320
268321
269322 func updateTime (_lastUpdateTime,_periodFinish) = [IntegerEntry(k_lastUpdateTime, _lastUpdateTime), IntegerEntry(k_periodFinish, _periodFinish)]
270323
271324
272325 func updateRewardPerTokenStored (_rewardPerTokenStored) = [IntegerEntry(k_rewardPerTokenStored, _rewardPerTokenStored)]
273326
274327
275328 func updateUserRewards (_staker,_reward,_userRewardPerToken) = [IntegerEntry(toCompositeKey(k_userReward, _staker), _reward), IntegerEntry(toCompositeKey(k_userRewardPerToken, _staker), _userRewardPerToken)]
276329
277330
278331 @Callable(i)
279-func initialize (_coordinator) = if (if (initialized())
332+func initialize (_coordinator,_vaultAsset,_maxSpotUtilization) = if (if (if (if (initialized())
280333 then true
281334 else (i.caller != this))
335+ then true
336+ else (0 > _maxSpotUtilization))
337+ then true
338+ else (_maxSpotUtilization > DECIMAL_UNIT))
282339 then throw("Unable to initialize")
283- else [StringEntry(k_coordinatorAddress, toString(valueOrErrorMessage(addressFromString(_coordinator), "Invalid coordinator address"))), BooleanEntry(k_initialized, true)]
340+ else {
341+ let assetDecimals = if ((_vaultAsset == "WAVES"))
342+ then 8
343+ else {
344+ let info = valueOrErrorMessage(assetInfo(fromBase58String(_vaultAsset)), ("Invalid token id: " + _vaultAsset))
345+ info.decimals
346+ }
347+[StringEntry(k_coordinatorAddress, toString(valueOrErrorMessage(addressFromString(_coordinator), "Invalid coordinator address"))), StringEntry(k_vaultAsset, _vaultAsset), IntegerEntry(k_vaultAssetDecimals, assetDecimals), IntegerEntry(k_maxSpotUtilization, _maxSpotUtilization), BooleanEntry(k_initialized, true)]
348+ }
284349
285350
286351
287352 @Callable(i)
288353 func stake () = {
289354 let _staker = toString(i.caller)
290- let _amount = usdnToDecimals(i.payments[0].amount)
291- if (if (if ((i.payments[0].assetId != quoteAsset()))
355+ let _amount = assetToDecimals(i.payments[0].amount)
356+ if (if (if ((i.payments[0].assetId != vaultAsset()))
292357 then true
293358 else (size(i.payments) != 1))
294359 then true
295360 else !(initialized()))
296361 then throw("Invalid call to stake")
297362 else {
298- let $t01017610405 = updateReward(_staker, 0)
299- let newRewardPerTokenStored = $t01017610405._1
300- let newLastUpdateTime = $t01017610405._2
301- let stakerEarned = $t01017610405._3
302- let stakerRewardPerTokenPaid = $t01017610405._4
363+ let $t01253712766 = updateReward(_staker, 0)
364+ let newRewardPerTokenStored = $t01253712766._1
365+ let newLastUpdateTime = $t01253712766._2
366+ let stakerEarned = $t01253712766._3
367+ let stakerRewardPerTokenPaid = $t01253712766._4
303368 let currentRate = rate()
304369 let prevAverageRate = averageRate(_staker)
305370 let vAmount = divd(_amount, currentRate)
306371 let newAverageRate = divd((muld(vAmount, currentRate) + muld(balanceOf(_staker), prevAverageRate)), (vAmount + balanceOf(_staker)))
307372 let newTotalBalance = (vAmount + balanceOf(_staker))
308373 let newWithdrawLimit = muld(newTotalBalance, WITHDRAW_PER_PERIOD)
309- let stake = invoke(managerAddress(), "deposit", nil, [AttachedPayment(quoteAsset(), usdnFromDecimals(_amount))])
374+ let stake = invoke(managerAddress(), "deposit", nil, [AttachedPayment(vaultAsset(), assetFromDecimals(_amount))])
310375 if ((stake == stake))
311376 then (((((((updateUserRewards(_staker, stakerEarned, stakerRewardPerTokenPaid) ++ updateRewardPerTokenStored(newRewardPerTokenStored)) ++ updateTime(newLastUpdateTime, periodFinish())) ++ updateFreeBalance(_amount)) ++ updateUserBalance(_staker, vAmount)) ++ setUserAverageRate(_staker, newAverageRate)) ++ setUserWithdrawLimit(_staker, newWithdrawLimit)) ++ updateTotalSupply(vAmount))
312377 else throw("Strict value is not equal to itself.")
313378 }
314379 }
315380
316381
317382
318383 @Callable(i)
319384 func unStake (_amount) = {
320385 let _staker = toString(i.caller)
321- let amountOfQuoteAsset = usdnToDecimals(_amount)
386+ let amountOfQuoteAsset = assetToDecimals(_amount)
322387 if (if (if ((i.payments != nil))
323388 then true
324389 else (0 >= amountOfQuoteAsset))
325390 then true
326391 else !(initialized()))
327392 then throw("Invalid call to unStake")
328393 else {
329- let $t01175811974 = updateReward(_staker, 0)
330- let newRewardPerTokenStored = $t01175811974._1
331- let newLastUpdateTime = $t01175811974._2
332- let stakerEarned = $t01175811974._3
333- let stakerRewardPerTokenPaid = $t01175811974._4
334- let $t01198112148 = getWithdrawLimitLeft(_staker)
335- let newLastWithdrawnDate = $t01198112148._1
336- let withdrawLimitLeft = $t01198112148._2
337- let alreadyWithdrawnInPeriod = $t01198112148._3
394+ let $t01427414490 = updateReward(_staker, 0)
395+ let newRewardPerTokenStored = $t01427414490._1
396+ let newLastUpdateTime = $t01427414490._2
397+ let stakerEarned = $t01427414490._3
398+ let stakerRewardPerTokenPaid = $t01427414490._4
399+ let $t01449714664 = getWithdrawLimitLeft(_staker)
400+ let newLastWithdrawnDate = $t01449714664._1
401+ let withdrawLimitLeft = $t01449714664._2
402+ let alreadyWithdrawnInPeriod = $t01449714664._3
338403 let vAmount = divd(amountOfQuoteAsset, rate())
339404 if ((vAmount > withdrawLimitLeft))
340405 then throw("Invalid call to unStake: withdraw over limit")
341406 else {
342407 let newWithdrawnInPeriod = (alreadyWithdrawnInPeriod + vAmount)
343408 if ((amountOfQuoteAsset > freeBalance()))
344409 then throw("Invalid call to unStake: balance too low")
345410 else {
346- let unstake = invoke(managerAddress(), "withdraw", [toBase58String(quoteAsset()), usdnFromDecimals(amountOfQuoteAsset)], nil)
411+ let unstake = invoke(managerAddress(), "withdraw", [vaultAssetStr(), assetFromDecimals(amountOfQuoteAsset)], nil)
347412 if ((unstake == unstake))
348- then (((((((updateUserRewards(_staker, stakerEarned, stakerRewardPerTokenPaid) ++ updateRewardPerTokenStored(newRewardPerTokenStored)) ++ updateTime(newLastUpdateTime, periodFinish())) ++ updateFreeBalance(-(amountOfQuoteAsset))) ++ updateUserBalance(_staker, -(vAmount))) ++ updateTotalSupply(-(vAmount))) ++ setUserWithdrawParams(_staker, newLastWithdrawnDate, newWithdrawnInPeriod)) ++ [ScriptTransfer(i.caller, usdnFromDecimals(amountOfQuoteAsset), quoteAsset())])
413+ then (((((((updateUserRewards(_staker, stakerEarned, stakerRewardPerTokenPaid) ++ updateRewardPerTokenStored(newRewardPerTokenStored)) ++ updateTime(newLastUpdateTime, periodFinish())) ++ updateFreeBalance(-(amountOfQuoteAsset))) ++ updateUserBalance(_staker, -(vAmount))) ++ updateTotalSupply(-(vAmount))) ++ setUserWithdrawParams(_staker, newLastWithdrawnDate, newWithdrawnInPeriod)) ++ [ScriptTransfer(i.caller, assetFromDecimals(amountOfQuoteAsset), vaultAsset())])
349414 else throw("Strict value is not equal to itself.")
350415 }
351416 }
352417 }
353418 }
354419
355420
356421
357422 @Callable(i)
358423 func withdrawRewards () = {
359424 let _staker = toString(i.caller)
360- let $t01348413629 = updateReward(_staker, 0)
361- let newRewardPerTokenStored = $t01348413629._1
362- let newLastUpdateTime = $t01348413629._2
363- let stakerEarned = $t01348413629._3
364- let stakerRewardPerTokenPaid = $t01348413629._4
425+ let $t01618116326 = updateReward(_staker, 0)
426+ let newRewardPerTokenStored = $t01618116326._1
427+ let newLastUpdateTime = $t01618116326._2
428+ let stakerEarned = $t01618116326._3
429+ let stakerRewardPerTokenPaid = $t01618116326._4
365430 if (if ((0 >= stakerEarned))
366431 then true
367432 else !(initialized()))
368433 then throw("No reward: Vault")
369434 else ((((updateUserRewards(_staker, 0, stakerRewardPerTokenPaid) ++ updateRewardPerTokenStored(newRewardPerTokenStored)) ++ updateTime(newLastUpdateTime, periodFinish())) ++ updateRewardBalance(-(stakerEarned))) ++ [ScriptTransfer(i.caller, stakerEarned, governanceAsset())])
370435 }
371436
372437
373438
374439 @Callable(i)
375440 func addFree () = {
376- let _amount = usdnToDecimals(i.payments[0].amount)
377- if (if (if (if ((i.payments[0].assetId != quoteAsset()))
441+ let _amount = assetToDecimals(i.payments[0].amount)
442+ if (if (if (if ((i.payments[0].assetId != vaultAsset()))
378443 then true
379444 else (size(i.payments) != 1))
380445 then true
381446 else !(initialized()))
382447 then true
383448 else !(if (isWhitelist(toString(i.caller)))
384449 then true
385450 else (i.caller == adminAddress())))
386451 then throw("Invalid addFree params")
387452 else {
388453 let newRate = computeNewRate(_amount)
389- let stake = invoke(managerAddress(), "deposit", nil, [AttachedPayment(quoteAsset(), usdnFromDecimals(_amount))])
454+ let stake = invoke(managerAddress(), "deposit", nil, [AttachedPayment(vaultAsset(), assetFromDecimals(_amount))])
390455 if ((stake == stake))
391456 then (updateFreeBalance(_amount) ++ updateRate(newRate))
392457 else throw("Strict value is not equal to itself.")
393458 }
394459 }
395460
396461
397462
398463 @Callable(i)
399464 func addLocked () = {
400- let _amount = usdnToDecimals(i.payments[0].amount)
401- if (if (if (if ((i.payments[0].assetId != quoteAsset()))
465+ let _amount = assetToDecimals(i.payments[0].amount)
466+ if (if (if (if ((i.payments[0].assetId != vaultAsset()))
402467 then true
403468 else (size(i.payments) != 1))
404469 then true
405470 else !(initialized()))
406471 then true
407472 else !(if (isWhitelist(toString(i.caller)))
408473 then true
409474 else (i.caller == adminAddress())))
410475 then throw("Invalid addLocked params")
411476 else {
412- let unstake = invoke(managerAddress(), "deposit", nil, [AttachedPayment(quoteAsset(), usdnFromDecimals(_amount))])
477+ let unstake = invoke(managerAddress(), "deposit", nil, [AttachedPayment(vaultAsset(), assetFromDecimals(_amount))])
413478 if ((unstake == unstake))
414479 then updateLockedBalance(_amount)
415480 else throw("Strict value is not equal to itself.")
416481 }
417482 }
418483
419484
420485
421486 @Callable(i)
422487 func exchangeFreeAndLocked (_amount) = if (if (!(initialized()))
423488 then true
424489 else if (!(isWhitelist(toString(i.caller))))
425490 then (i.caller != adminAddress())
426491 else false)
427492 then throw("Invalid exchangeFreeAndLocked params")
428493 else {
429- let amountOfQuoteAsset = usdnToDecimals(_amount)
494+ let amountOfQuoteAsset = assetToDecimals(_amount)
430495 let newRate = computeNewRate(-(amountOfQuoteAsset))
431496 ((updateLockedBalance(amountOfQuoteAsset) ++ updateFreeBalance(-(amountOfQuoteAsset))) ++ updateRate(newRate))
432497 }
433498
434499
435500
436501 @Callable(i)
437502 func withdrawLocked (_amount) = if (if (if (!(initialized()))
438503 then true
439504 else (0 >= _amount))
440505 then true
441506 else !(isWhitelist(toString(i.caller))))
442507 then throw("Invalid withdrawLocked params")
443508 else {
444- let amountOfQuoteAsset = usdnToDecimals(_amount)
445- let unstake = invoke(managerAddress(), "withdraw", [toBase58String(quoteAsset()), usdnFromDecimals(amountOfQuoteAsset)], nil)
509+ let amountOfQuoteAsset = assetToDecimals(_amount)
510+ let unstake = invoke(managerAddress(), "withdraw", [vaultAssetStr(), assetFromDecimals(amountOfQuoteAsset)], nil)
446511 if ((unstake == unstake))
447- then (updateLockedBalance(-(amountOfQuoteAsset)) ++ [ScriptTransfer(i.caller, usdnFromDecimals(amountOfQuoteAsset), quoteAsset())])
512+ then (updateLockedBalance(-(amountOfQuoteAsset)) ++ [ScriptTransfer(i.caller, assetFromDecimals(amountOfQuoteAsset), vaultAsset())])
448513 else throw("Strict value is not equal to itself.")
449514 }
450515
451516
452517
453518 @Callable(i)
454519 func addRewards () = if (if (if ((i.payments[0].assetId != governanceAsset()))
455520 then true
456521 else (size(i.payments) != 1))
457522 then true
458523 else !(initialized()))
459524 then throw("Invalid addRewards params")
460525 else {
461526 let _reward = i.payments[0].amount
462527 let newRewardPerTokenStored = updateReward(NO_ADDRESS, NO_STAKER)._1
463528 let timestamp = currentTimestampSec()
464529 let newRewardRate = if ((timestamp > periodFinish()))
465530 then (_reward / DURATION)
466531 else {
467532 let remainingTime = (periodFinish() - timestamp)
468533 let leftover = (rewardRate() * remainingTime)
469534 ((_reward + leftover) / DURATION)
470535 }
471536 (((updateRewardRate(newRewardRate) ++ updateRewardPerTokenStored(newRewardPerTokenStored)) ++ updateRewardBalance(_reward)) ++ updateTime(timestamp, (timestamp + DURATION)))
472537 }
473538
474539
475540
476541 @Callable(i)
477542 func ackRewards () = {
478- let profitResp = invoke(managerAddress(), "claimProfit", [toBase58String(quoteAsset())], nil)
543+ let profitResp = invoke(managerAddress(), "claimProfit", [vaultAssetStr()], nil)
479544 if ((profitResp == profitResp))
480545 then {
481546 let profit = match profitResp {
482547 case p: Int =>
483- usdnToDecimals(p)
548+ assetToDecimals(p)
484549 case _ =>
485550 throw("Invalid claimProfit response")
486551 }
487552 let result = if ((profit > 0))
488553 then {
489554 let newRate = computeNewRate(profit)
490- let stake = invoke(managerAddress(), "deposit", nil, [AttachedPayment(quoteAsset(), usdnFromDecimals(profit))])
555+ let stake = invoke(managerAddress(), "deposit", nil, [AttachedPayment(vaultAsset(), assetFromDecimals(profit))])
491556 if ((stake == stake))
492557 then (updateFreeBalance(profit) ++ updateRate(newRate))
493558 else throw("Strict value is not equal to itself.")
494559 }
495560 else nil
496561 if ((result == result))
497562 then result
498563 else throw("Strict value is not equal to itself.")
499564 }
500565 else throw("Strict value is not equal to itself.")
501566 }
502567
503568
504569
505570 @Callable(i)
506571 func view_reward (_staker) = {
507572 let balance = balanceOf(_staker)
508573 let depositedAmount = muld(averageRate(_staker), balance)
509574 let currentAmount = muld(rate(), balance)
510575 let earnedQuote = (currentAmount - depositedAmount)
511576 throw(toString(earnedQuote))
512577 }
513578
514579
515580
516581 @Callable(i)
517582 func view_stakingReward (_staker) = {
518583 let stakerEarned = updateReward(_staker, 0)._3
519- throw(toString(usdnFromDecimals(stakerEarned)))
584+ throw(toString(assetFromDecimals(stakerEarned)))
520585 }
521586
522587
523588
524589 @Callable(i)
525590 func view_withdrawLimit (_staker) = {
526591 let withdrawLimitLeft = getWithdrawLimitLeft(_staker)._2
527- let limitInUsdn = usdnFromDecimals(muld(withdrawLimitLeft, rate()))
528- throw(toString(limitInUsdn))
592+ let limitInAsset = assetFromDecimals(muld(withdrawLimitLeft, rate()))
593+ throw(toString(limitInAsset))
529594 }
530595
531596
532597 @Verifier(tx)
533598 func verify () = {
534599 let coordinatorStr = getString(this, k_coordinatorAddress)
535600 if (isDefined(coordinatorStr))
536601 then {
537602 let admin = getString(addressFromStringValue(value(coordinatorStr)), k_admin_address)
538603 if (isDefined(admin))
539604 then valueOrElse(getBoolean(addressFromStringValue(value(admin)), ((("status_" + toString(this)) + "_") + toBase58String(tx.id))), false)
540605 else throw("unable to verify: admin not set in coordinator")
541606 }
542607 else sigVerify(tx.bodyBytes, tx.proofs[0], tx.senderPublicKey)
543608 }
544609

github/deemru/w8io/169f3d6 
92.55 ms