tx · EPoD491YiKmNYUpGDA1idnsXELhKdTpSKBpKmtEeYc2J

3MDmxL68ZGfA6KBA3jZRc2Bavcut6nELKjG:  -0.05500000 Waves

2026.04.14 14:46 [355484] smart account 3MDmxL68ZGfA6KBA3jZRc2Bavcut6nELKjG > SELF 0.00000000 Waves

{ "type": 13, "id": "EPoD491YiKmNYUpGDA1idnsXELhKdTpSKBpKmtEeYc2J", "fee": 5500000, "feeAssetId": null, "timestamp": 1776167169755, "version": 2, "chainId": 82, "sender": "3MDmxL68ZGfA6KBA3jZRc2Bavcut6nELKjG", "senderPublicKey": "AKwfv7V32bj7tHan4qkt4HVEK9nzokZFrFmWG5gP67Bo", "proofs": [ "2h3MQaKvtynPZHDHcMzkF8tpTmKXdZkDE4L5VZ7EWoRGFJf4S9DRQ3moTxFUovSVTLmDijAP7zqAgGQQ3rzTvPYU" ], "script": "base64:BgKgAQgCEgASBAoCCAESBAoCCAESABIDCgEIEgQKAggBEgMKAQgSBAoCCAESBAoCCAESABIGCgQICAgIEgYKBAgICAgSBAoCCAgSBAoCCAgSAwoBBBIDCgEIEgMKAQQSCAoGBAgBCAgIEgUKAwQICBIGCgQECAQIEgMKAQQSBAoCCAQSBAoCCAQSAwoBBBIDCgEEEgMKAQgSAwoBCBIDCgEIEgAsAA1DT05UUkFDVF9UWVBFAg5MRU5ELUxQLU1BUktFVAAHVkVSU0lPTgIJUExQLTEuMS4xARNnZXRBZGRyZXNzRnJvbVN0YXRlAQNrZXkJAQt2YWx1ZU9yRWxzZQIJAKYIAQkBC3ZhbHVlT3JFbHNlAgkAnQgCBQR0aGlzCQCsAgICDnNldHVwX2FkZHJlc3NfBQNrZXkCIzNQRXdSY1lOQVV0b0Z2S3BCaEtvaXdham5aZmRvRFI2aDRoCQEHQWRkcmVzcwEBGgFXjrNqi19PmtPLr8EF1shiHDBcMjzmTCG+ARVnZXRBZGRyZXNzZXNGcm9tU3RhdGUBA2tleQoBAWYCBWFjY3VtBG5leHQJAM4IAgUFYWNjdW0JAMwIAgkBC3ZhbHVlT3JFbHNlAgkApggBBQRuZXh0CQEHQWRkcmVzcwEBGgFXjrNqi19PmtPLr8EF1shiHDBcMjzmTCG+BQNuaWwKAAIkbAkAvAkCCQELdmFsdWVPckVsc2UCCQCdCAIFBHRoaXMJAKwCAgIOc2V0dXBfYWRkcmVzc18FA2tleQIjM1BFd1JjWU5BVXRvRnZLcEJoS29pd2FqblpmZG9EUjZoNGgCASwKAAIkcwkAkAMBBQIkbAoABSRhY2MwBQNuaWwKAQUkZjBfMQICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkBAWYCBQIkYQkAkQMCBQIkbAUCJGkKAQUkZjBfMgICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkAAgECFExpc3Qgc2l6ZSBleGNlZWRzIDE1CQEFJGYwXzICCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECBQUkYWNjMAAAAAEAAgADAAQABQAGAAcACAAJAAoACwAMAA0ADgAPABJyZXNlcnZlRnVuZEFkZHJlc3MJARNnZXRBZGRyZXNzRnJvbVN0YXRlAQILcmVzZXJ2ZUZ1bmQADW9yYWNsZUFkZHJlc3MJARNnZXRBZGRyZXNzRnJvbVN0YXRlAQIGb3JhY2xlABFhZ2dyZWdhdG9yQWRkcmVzcwkBE2dldEFkZHJlc3NGcm9tU3RhdGUBAgphZ2dyZWdhdG9yAAxhZG1pbkFkZHJlc3MJARNnZXRBZGRyZXNzRnJvbVN0YXRlAQIFYWRtaW4AEXN0YWJsZUZ1bmRBZGRyZXNzCQETZ2V0QWRkcmVzc0Zyb21TdGF0ZQECCnN0YWJsZUZ1bmQAEXNodXRkb3duV2hpdGVsaXN0CQEVZ2V0QWRkcmVzc2VzRnJvbVN0YXRlAQIPc2h1dGRvd25DYWxsZXJzABRsaXF1aWRhdG9yc1doaXRlbGlzdAkBFWdldEFkZHJlc3Nlc0Zyb21TdGF0ZQECC2xpcXVpZGF0b3JzARZ2ZXJpZnlMaXF1aWRhdG9yUmlnaHRzAQdhZGRyZXNzCQECIT0CCQDPCAIFFGxpcXVpZGF0b3JzV2hpdGVsaXN0BQdhZGRyZXNzBQR1bml0AAtyZXNlcnZlRnVuZAkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzAhRzZXR1cF9yZXNlcnZlRnVuZEZlZQAUAAxzdGFibGVzSWRTdHIJALUJAgkBC3ZhbHVlT3JFbHNlAgkAnQgCBQR0aGlzAhBzZXR1cF9zdGFibGVzSWRzAlk5d2MzTFhOQTRURUJzWHlLdG9MRTltcmJERDdXTUhYdlhyQ2padmFiTEFzaSxIR2dhYlRxVVM4V3RWRlVKemZtclRETWdFY2NKdVpMQlBoRmdRRnh2bnNvVwIBLAEMZ2V0UmF0ZUN1cnZlAQphc3NldElkU3RyBA5jdXJ2ZVJhdGVTdHJMaQkAtQkCCQELdmFsdWVPckVsc2UCCQCdCAIFBHRoaXMJAKwCAgIQc2V0dXBfcmF0ZUN1cnZlXwUKYXNzZXRJZFN0cgIlMjAwMDAwMDAsMTAwMDAwMDAwLDYwMDAwMDAwLDQwMDAwMDAwMAIBLAkAlgoECQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUOY3VydmVSYXRlU3RyTGkAAAkBDXBhcnNlSW50VmFsdWUBCQCRAwIFDmN1cnZlUmF0ZVN0ckxpAAEJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQ5jdXJ2ZVJhdGVTdHJMaQACCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUOY3VydmVSYXRlU3RyTGkAAwETZ2V0UmV3YXJkc1NwbGl0dGluZwEKYXNzZXRJZFN0cgQVcmV3YXJkc1NwbGl0dGluZ1N0ckxpCQC1CQIJAQt2YWx1ZU9yRWxzZQIJAJ0IAgUEdGhpcwkArAICAhdzZXR1cF9yZXdhcmRzU3BsaXR0aW5nXwUKYXNzZXRJZFN0cgIIMzAsNTAsMjACASwJAJUKAwkBDXBhcnNlSW50VmFsdWUBCQCRAwIFFXJld2FyZHNTcGxpdHRpbmdTdHJMaQAACQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUVcmV3YXJkc1NwbGl0dGluZ1N0ckxpAAEJAQ1wYXJzZUludFZhbHVlAQkAkQMCBRVyZXdhcmRzU3BsaXR0aW5nU3RyTGkAAgAJc2VudGluZWxzCQDMCAIJAQdBZGRyZXNzAQEaAVfX4SNRjnyriFrV1yiXddiIddOPriMFpuEJAMwIAgkBB0FkZHJlc3MBARoBV/j6+gImwFGL7Go7RjNJ0hxxsHWL+aTKmgkAzAgCCQEHQWRkcmVzcwEBGgFXSQEY9kN/P0xs4Wd15bfkly/eUC2yg93xCQDMCAIJAQdBZGRyZXNzAQEaAVdLw2zO+zNYQ1hDURDu7+4hEBdL8njLfDIFA25pbAAGU2NhbGU4AIDC1y8AB1NjYWxlMTAAgMivoCUAB1NjYWxlMTYJAGgCBQZTY2FsZTgFBlNjYWxlOAAJZGF5QmxvY2tzAKALABV3aXRoZHJhd2FsTGltaXRCbG9ja3MJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwIbc2V0dXBfd2l0aGRyYXdhbExpbWl0QmxvY2tzAGQBCmxpSW50VG9TdHIBAmxpCgEBZgIFYWNjdW0EbmV4dAkArAICCQCsAgIFBWFjY3VtCQCkAwEFBG5leHQCASwKAAIkbAUCbGkKAAIkcwkAkAMBBQIkbAoABSRhY2MwAgAKAQUkZjBfMQICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkBAWYCBQIkYQkAkQMCBQIkbAUCJGkKAQUkZjBfMgICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkAAgECFExpc3Qgc2l6ZSBleGNlZWRzIDEyCQEFJGYwXzICCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECBQUkYWNjMAAAAAEAAgADAAQABQAGAAcACAAJAAoACwAMAQ10cnlHZXRJbnRlZ2VyAQNrZXkEByRtYXRjaDAJAJoIAgUEdGhpcwUDa2V5AwkAAQIFByRtYXRjaDACA0ludAQBYgUHJG1hdGNoMAUBYgAAAQ10cnlHZXRCb29sZWFuAQNrZXkEByRtYXRjaDAJAJsIAgUEdGhpcwUDa2V5AwkAAQIFByRtYXRjaDACB0Jvb2xlYW4EAWIFByRtYXRjaDAFAWIHAQx0cnlHZXRTdHJpbmcBA2tleQQHJG1hdGNoMAkAnQgCBQR0aGlzBQNrZXkDCQABAgUHJG1hdGNoMAIGU3RyaW5nBAFiBQckbWF0Y2gwBQFiAgABDHRyeUdldEJpbmFyeQEDa2V5BAckbWF0Y2gwCQCcCAIFBHRoaXMFA2tleQMJAAECBQckbWF0Y2gwAgpCeXRlVmVjdG9yBAFiBQckbWF0Y2gwBQFiAQABDmdldEFzc2V0U3RyaW5nAQdhc3NldElkBAckbWF0Y2gwBQdhc3NldElkAwkAAQIFByRtYXRjaDACCkJ5dGVWZWN0b3IEAWIFByRtYXRjaDAJANgEAQUBYgIFV0FWRVMBDWdldEFzc2V0Qnl0ZXMBCmFzc2V0SWRTdHIDCQAAAgUKYXNzZXRJZFN0cgIFV0FWRVMFBHVuaXQJANkEAQUKYXNzZXRJZFN0cgEKZ2V0QmFsYW5jZQEKYXNzZXRJZFN0cgMJAAACBQphc3NldElkU3RyAgVXQVZFUwgJAO8HAQUEdGhpcwlhdmFpbGFibGUJAPAHAgUEdGhpcwkA2QQBBQphc3NldElkU3RyAQ9nZXRNYXJrZXRBc3NldHMACQC1CQIJAQx0cnlHZXRTdHJpbmcBAgxzZXR1cF90b2tlbnMCASwBDWdldE91dGRhdGVkVXIBCmFzc2V0SWRTdHIEBGRvd24JAGsDCQENdHJ5R2V0SW50ZWdlcgEJAKwCAgIPdG90YWxfc3VwcGxpZWRfBQphc3NldElkU3RyCQENdHJ5R2V0SW50ZWdlcgEJAKwCAgUKYXNzZXRJZFN0cgIGX3NSYXRlBQdTY2FsZTE2AwkAAAIFBGRvd24AAAAACQBrAwUGU2NhbGU4CQBrAwkBDXRyeUdldEludGVnZXIBCQCsAgICD3RvdGFsX2JvcnJvd2VkXwUKYXNzZXRJZFN0cgkBDXRyeUdldEludGVnZXIBCQCsAgIFCmFzc2V0SWRTdHICBl9iUmF0ZQUHU2NhbGUxNgUEZG93bgELZ2V0SW50ZXJlc3QBCmFzc2V0SWRTdHIEAnVyCQENZ2V0T3V0ZGF0ZWRVcgEFCmFzc2V0SWRTdHIEBWN1cnZlCQEMZ2V0UmF0ZUN1cnZlAQUKYXNzZXRJZFN0cgQEcmF0ZQkAZAIIBQVjdXJ2ZQJfMQMJAGcCCAUFY3VydmUCXzMFAnVyCQBrAwUCdXIIBQVjdXJ2ZQJfMggFBWN1cnZlAl8zCQBkAggFBWN1cnZlAl8yCQBrAwkAZQIFAnVyCAUFY3VydmUCXzMIBQVjdXJ2ZQJfNAkAZQIAgMLXLwgFBWN1cnZlAl8zCQCWAwEJAMwIAgkAawMFBHJhdGUFBlNjYWxlOAkAaAIFCWRheUJsb2NrcwDtAgkAzAgCAAEFA25pbAEQdG9rZW5SYXRlc1JlY2FsYwEKYXNzZXRJZFN0cgQIaW50ZXJlc3QJAQtnZXRJbnRlcmVzdAEFCmFzc2V0SWRTdHIEAnVyCQENZ2V0T3V0ZGF0ZWRVcgEFCmFzc2V0SWRTdHIEEGxhc3RSZWNhbGNIZWlnaHQJAQ10cnlHZXRJbnRlZ2VyAQIObGFzdFJhdGVIZWlnaHQECWxhc3RCUmF0ZQkAlgMBCQDMCAIJAQ10cnlHZXRJbnRlZ2VyAQkArAICBQphc3NldElkU3RyAgZfYlJhdGUJAMwIAgUHU2NhbGUxNgUDbmlsBAhuZXdCUmF0ZQkAZAIFCWxhc3RCUmF0ZQkAaAIJAGUCBQZoZWlnaHQFEGxhc3RSZWNhbGNIZWlnaHQFCGludGVyZXN0BAlsYXN0U1JhdGUJAJYDAQkAzAgCCQENdHJ5R2V0SW50ZWdlcgEJAKwCAgUKYXNzZXRJZFN0cgIGX3NSYXRlCQDMCAIFB1NjYWxlMTYFA25pbAQIbmV3U1JhdGUJAGQCBQlsYXN0U1JhdGUJAGkCCQBoAgkAaAIJAGUCBQZoZWlnaHQFEGxhc3RSZWNhbGNIZWlnaHQJAGsDBQhpbnRlcmVzdAUCdXIFBlNjYWxlOAkAZQIAZAULcmVzZXJ2ZUZ1bmQAZAkAzAgCCQEMSW50ZWdlckVudHJ5AgkArAICBQphc3NldElkU3RyAgZfc1JhdGUFCG5ld1NSYXRlCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQCsAgIFCmFzc2V0SWRTdHICBl9iUmF0ZQUIbmV3QlJhdGUJAMwIAgkBDEludGVnZXJFbnRyeQICDmxhc3RSYXRlSGVpZ2h0BQZoZWlnaHQFA25pbAENZ2V0QWN0dWFsUmF0ZQIKYXNzZXRJZFN0cghyYXRlVHlwZQoBAWYCBWFjY3VtBXRva2VuBAZyZWNhbGMJARB0b2tlblJhdGVzUmVjYWxjAQUFdG9rZW4JAJQKAgMJAQIhPQIFBXRva2VuBQphc3NldElkU3RyCAUFYWNjdW0CXzEDCQAAAgUIcmF0ZVR5cGUCBXNSYXRlCAkAkQMCBQZyZWNhbGMAAAV2YWx1ZQgJAJEDAgUGcmVjYWxjAAEFdmFsdWUJAM4IAggFBWFjY3VtAl8yBQZyZWNhbGMKAAIkbAkBD2dldE1hcmtldEFzc2V0cwAKAAIkcwkAkAMBBQIkbAoABSRhY2MwCQCUCgIAAAUDbmlsCgEFJGYwXzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAQFmAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGYwXzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhRMaXN0IHNpemUgZXhjZWVkcyAxMgkBBSRmMF8yAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgUFJGFjYzAAAAABAAIAAwAEAAUABgAHAAgACQAKAAsADAEFZ2V0VXIBCmFzc2V0SWRTdHIEBXJhdGVzCQEQdG9rZW5SYXRlc1JlY2FsYwEFCmFzc2V0SWRTdHIEBGRvd24JAGsDCQENdHJ5R2V0SW50ZWdlcgEJAKwCAgIPdG90YWxfc3VwcGxpZWRfBQphc3NldElkU3RyCAkAkQMCBQVyYXRlcwAABXZhbHVlBQdTY2FsZTE2CQBrAwUGU2NhbGU4CQBrAwkBDXRyeUdldEludGVnZXIBCQCsAgICD3RvdGFsX2JvcnJvd2VkXwUKYXNzZXRJZFN0cggJAJEDAgUFcmF0ZXMAAQV2YWx1ZQUHU2NhbGUxNgUEZG93bgELcmF0ZXNSZWNhbGMACgEBZgIFYWNjdW0FdG9rZW4JAM4IAgUFYWNjdW0JARB0b2tlblJhdGVzUmVjYWxjAQUFdG9rZW4KAAIkbAkBD2dldE1hcmtldEFzc2V0cwAKAAIkcwkAkAMBBQIkbAoABSRhY2MwBQNuaWwKAQUkZjBfMQICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkBAWYCBQIkYQkAkQMCBQIkbAUCJGkKAQUkZjBfMgICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkAAgECFExpc3Qgc2l6ZSBleGNlZWRzIDEyCQEFJGYwXzICCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECBQUkYWNjMAAAAAEAAgADAAQABQAGAAcACAAJAAoACwAMARVnZXRUb2tlblByaWNlV2l0aFJpc2sCCmFzc2V0SWRTdHIMcmlza0F2ZXJzaXR5AwkBAiE9AgkAzwgCBQxzdGFibGVzSWRTdHIFCmFzc2V0SWRTdHIFBHVuaXQJAJQKAgDAhD0AwIQ9BAVwcmljZQkBEUBleHRyTmF0aXZlKDEwNTApAgUNb3JhY2xlQWRkcmVzcwkArAICBQphc3NldElkU3RyAgdfdHdhcDVCBAlyaXNrTGV2ZWwJARFAZXh0ck5hdGl2ZSgxMDUwKQIFDW9yYWNsZUFkZHJlc3MJAKwCAgUKYXNzZXRJZFN0cgIKX3Jpc2tMZXZlbAMJAGcCBQxyaXNrQXZlcnNpdHkFCXJpc2tMZXZlbAkAlAoCBQVwcmljZQUFcHJpY2UJAAIBCQCsAgIJAKwCAgIbb3JhY2xlIHByaWNlcyBkb24ndCBtYXRjaDogCQCkAwEFBXByaWNlAiMgaXMgdGhlIHByaWNlLCBidXQgcmlzayBpcyB0b28gaGlnaAENZ2V0VG9rZW5QcmljZQEKYXNzZXRJZFN0cgkBFWdldFRva2VuUHJpY2VXaXRoUmlzawIFCmFzc2V0SWRTdHIAAwETZ2V0VG9rZW5QcmljZUNhcHBlZAEKYXNzZXRJZFN0cgQLJHQwNzg1Njc5MTkJARVnZXRUb2tlblByaWNlV2l0aFJpc2sCBQphc3NldElkU3RyAAMECG1pblByaWNlCAULJHQwNzg1Njc5MTkCXzEECG1heFByaWNlCAULJHQwNzg1Njc5MTkCXzIED21heEFsbG93ZWRQcmljZQkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzCQCsAgICD3NldHVwX21heFByaWNlXwUKYXNzZXRJZFN0cgD///////////8BBA9taW5BbGxvd2VkUHJpY2UJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwkArAICAg9zZXR1cF9taW5QcmljZV8FCmFzc2V0SWRTdHIA////////////AQMDCQECIT0CBQ9tYXhBbGxvd2VkUHJpY2UA////////////AQkAZgIFCG1heFByaWNlBQ9tYXhBbGxvd2VkUHJpY2UHCQCUCgIFD21heEFsbG93ZWRQcmljZQUPbWF4QWxsb3dlZFByaWNlAwMJAQIhPQIFD21pbkFsbG93ZWRQcmljZQD///////////8BCQBmAgUPbWluQWxsb3dlZFByaWNlBQhtaW5QcmljZQcJAJQKAgUPbWluQWxsb3dlZFByaWNlBQ9taW5BbGxvd2VkUHJpY2UJAJQKAgUIbWluUHJpY2UFCG1heFByaWNlAQ5jYWxjQXNzZXRTY2FsZQEKYXNzZXRJZFN0cgQIZGVjaW1hbHMDCQAAAgUKYXNzZXRJZFN0cgIFV0FWRVMACAgJAQV2YWx1ZQEJAOwHAQkA2QQBBQphc3NldElkU3RyCGRlY2ltYWxzCQBsBgAKAAAFCGRlY2ltYWxzAAAAAAUERE9XTgESY2FsY1VzZXJDb2xsYXRlcmFsAQdhZGRyZXNzBBR1c2VyQ29sbGF0ZXJhbEludm9rZQkA/AcEBQR0aGlzAhFnZXRVc2VyQ29sbGF0ZXJhbAkAzAgCBwkAzAgCBQdhZGRyZXNzCQDMCAIGCQDMCAICAAUDbmlsBQNuaWwDCQAAAgUUdXNlckNvbGxhdGVyYWxJbnZva2UFFHVzZXJDb2xsYXRlcmFsSW52b2tlBBN1c2VyQ29sbGF0ZXJhbFZhbHVlBAckbWF0Y2gwBRR1c2VyQ29sbGF0ZXJhbEludm9rZQMJAAECBQckbWF0Y2gwAgNJbnQEAXgFByRtYXRjaDAFAXgJAAIBAiRpc3N1ZSB3aGlsZSBkb2luZyBpbi1kYXBwIGludm9jYXRpb24DCQAAAgUTdXNlckNvbGxhdGVyYWxWYWx1ZQUTdXNlckNvbGxhdGVyYWxWYWx1ZQUTdXNlckNvbGxhdGVyYWxWYWx1ZQkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgEUY2hlY2tXaXRoZHJhd2FsTGltaXQEB2FkZHJlc3MKYXNzZXRJZFN0cg5hbW91bnRJbnRlcm5hbAVzUmF0ZQQPd2l0aGRyYXdhbExpbWl0CQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMJAKwCAgkArAICAgZzZXR1cF8FCmFzc2V0SWRTdHICE19tYXhXaXRoZHJhd1BlcjEwMEIA////////////AQMJAAACBQ93aXRoZHJhd2FsTGltaXQA////////////AQUDbmlsBA10b3RhbFN1cHBsaWVkCQENdHJ5R2V0SW50ZWdlcgEJAKwCAgIPdG90YWxfc3VwcGxpZWRfBQphc3NldElkU3RyBAhsaW1pdENhcAkAawMFDXRvdGFsU3VwcGxpZWQFD3dpdGhkcmF3YWxMaW1pdABkBAVsYXN0SAkBDXRyeUdldEludGVnZXIBCQCsAgIJAKwCAgUHYWRkcmVzcwIVX3dpdGhkcmF3TGltaXRIZWlnaHRfBQphc3NldElkU3RyBAdlbGFwc2VkCQBlAgUGaGVpZ2h0BQVsYXN0SAQNd2luZG93RXhwaXJlZAkAZgIFB2VsYXBzZWQFFXdpdGhkcmF3YWxMaW1pdEJsb2NrcwQLY3VycmVudFVzZWQDBQ13aW5kb3dFeHBpcmVkAAAJAQ10cnlHZXRJbnRlZ2VyAQkArAICCQCsAgIFB2FkZHJlc3MCE193aXRoZHJhd0xpbWl0VXNlZF8FCmFzc2V0SWRTdHIEDWJsb2Nrc1RvUmVzZXQDBQ13aW5kb3dFeHBpcmVkBRV3aXRoZHJhd2FsTGltaXRCbG9ja3MJAGUCBRV3aXRoZHJhd2FsTGltaXRCbG9ja3MFB2VsYXBzZWQECWF2YWlsYWJsZQkAZQIFCGxpbWl0Q2FwBQtjdXJyZW50VXNlZAQPYXZhaWxhYmxlU2NhbGVkCQBuBAUJYXZhaWxhYmxlBQVzUmF0ZQUHU2NhbGUxNgUHQ0VJTElORwMJAGYCBQ5hbW91bnRJbnRlcm5hbAUJYXZhaWxhYmxlCQACAQkArAICCQCsAgIJAKwCAgkArAICCQCsAgICHndpdGhkcmF3YWwgbGltaXQgZXhjZWVkZWQgZm9yIAUKYXNzZXRJZFN0cgINLCBhdmFpbGFibGU6IAkApAMBBQ9hdmFpbGFibGVTY2FsZWQCEywgYmxvY2tzIHRvIHJlc2V0OiAJAKQDAQUNYmxvY2tzVG9SZXNldAkAzggCAwUNd2luZG93RXhwaXJlZAkAzAgCCQEMSW50ZWdlckVudHJ5AgkArAICCQCsAgIFB2FkZHJlc3MCFV93aXRoZHJhd0xpbWl0SGVpZ2h0XwUKYXNzZXRJZFN0cgUGaGVpZ2h0BQNuaWwFA25pbAkAzAgCCQEMSW50ZWdlckVudHJ5AgkArAICCQCsAgIFB2FkZHJlc3MCE193aXRoZHJhd0xpbWl0VXNlZF8FCmFzc2V0SWRTdHIJAGQCBQtjdXJyZW50VXNlZAUOYW1vdW50SW50ZXJuYWwFA25pbAEQY2hlY2tCb3Jyb3dMaW1pdAQHYWRkcmVzcwphc3NldElkU3RyDmFtb3VudEludGVybmFsBWJSYXRlBAtib3Jyb3dMaW1pdAkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzCQCsAgIJAKwCAgIGc2V0dXBfBQphc3NldElkU3RyAhFfbWF4Qm9ycm93UGVyMTAwQgD///////////8BAwkAAAIFC2JvcnJvd0xpbWl0AP///////////wEFA25pbAQNdG90YWxTdXBwbGllZAkBDXRyeUdldEludGVnZXIBCQCsAgICD3RvdGFsX3N1cHBsaWVkXwUKYXNzZXRJZFN0cgQIbGltaXRDYXAJAGsDBQ10b3RhbFN1cHBsaWVkBQtib3Jyb3dMaW1pdABkBAVsYXN0SAkBDXRyeUdldEludGVnZXIBCQCsAgIJAKwCAgUHYWRkcmVzcwITX2JvcnJvd0xpbWl0SGVpZ2h0XwUKYXNzZXRJZFN0cgQHZWxhcHNlZAkAZQIFBmhlaWdodAUFbGFzdEgEDXdpbmRvd0V4cGlyZWQJAGYCBQdlbGFwc2VkBRV3aXRoZHJhd2FsTGltaXRCbG9ja3MEC2N1cnJlbnRVc2VkAwUNd2luZG93RXhwaXJlZAAACQENdHJ5R2V0SW50ZWdlcgEJAKwCAgkArAICBQdhZGRyZXNzAhFfYm9ycm93TGltaXRVc2VkXwUKYXNzZXRJZFN0cgQNYmxvY2tzVG9SZXNldAMFDXdpbmRvd0V4cGlyZWQFFXdpdGhkcmF3YWxMaW1pdEJsb2NrcwkAZQIFFXdpdGhkcmF3YWxMaW1pdEJsb2NrcwUHZWxhcHNlZAQJYXZhaWxhYmxlCQBlAgUIbGltaXRDYXAFC2N1cnJlbnRVc2VkBA9hdmFpbGFibGVTY2FsZWQJAG4EBQlhdmFpbGFibGUFBWJSYXRlBQdTY2FsZTE2BQdDRUlMSU5HAwkAZgIFDmFtb3VudEludGVybmFsBQlhdmFpbGFibGUJAAIBCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgIaYm9ycm93IGxpbWl0IGV4Y2VlZGVkIGZvciAFCmFzc2V0SWRTdHICDSwgYXZhaWxhYmxlOiAJAKQDAQUPYXZhaWxhYmxlU2NhbGVkAhMsIGJsb2NrcyB0byByZXNldDogCQCkAwEFDWJsb2Nrc1RvUmVzZXQJAM4IAgMFDXdpbmRvd0V4cGlyZWQJAMwIAgkBDEludGVnZXJFbnRyeQIJAKwCAgkArAICBQdhZGRyZXNzAhNfYm9ycm93TGltaXRIZWlnaHRfBQphc3NldElkU3RyBQZoZWlnaHQFA25pbAUDbmlsCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQCsAgIJAKwCAgUHYWRkcmVzcwIRX2JvcnJvd0xpbWl0VXNlZF8FCmFzc2V0SWRTdHIJAGQCBQtjdXJyZW50VXNlZAUOYW1vdW50SW50ZXJuYWwFA25pbB0BaQEGc3VwcGx5AAMJAQEhAQkBDXRyeUdldEJvb2xlYW4BAgxzZXR1cF9hY3RpdmUJAAIBAhFtYXJrZXQgaXMgc3RvcHBlZAMDCQECIT0CCQCQAwEIBQFpCHBheW1lbnRzAAEGCQAAAggJAJEDAggFAWkIcGF5bWVudHMAAAZhbW91bnQAAAkAAgECHDEgcGF5bWVudCBoYXMgdG8gYmUgYXR0YWNoZWQECmFzc2V0SWRTdHIJAQ5nZXRBc3NldFN0cmluZwEICQCRAwIIBQFpCHBheW1lbnRzAAAHYXNzZXRJZAQLYXNzZXRBbW91bnQICQCRAwIIBQFpCHBheW1lbnRzAAAGYW1vdW50BA0kdDAxMTgyMzExODkwCQENZ2V0QWN0dWFsUmF0ZQIFCmFzc2V0SWRTdHICBXNSYXRlBAVzUmF0ZQgFDSR0MDExODIzMTE4OTACXzEEEXJhdGVzUmVjYWxjUmVzdWx0CAUNJHQwMTE4MjMxMTg5MAJfMgQGYW1vdW50CQBuBAULYXNzZXRBbW91bnQFB1NjYWxlMTYFBXNSYXRlBQRET1dOBAdhZGRyZXNzCQClCAEIBQFpBmNhbGxlcgQJbWF4U3VwcGx5BAckbWF0Y2gwCQCiCAEJAKwCAgIQc2V0dXBfbWF4U3VwcGx5XwUKYXNzZXRJZFN0cgMJAAECBQckbWF0Y2gwAgZTdHJpbmcEAXgFByRtYXRjaDAJAQ1wYXJzZUludFZhbHVlAQUBeAkBDXRyeUdldEludGVnZXIBCQCsAgICEHNldHVwX21heFN1cHBseV8FCmFzc2V0SWRTdHIECmFzc2V0UHJpY2UJARNnZXRUb2tlblByaWNlQ2FwcGVkAQUKYXNzZXRJZFN0cgQSbmV3QWRkcmVzc1N1cHBsaWVkCQBkAgkBDXRyeUdldEludGVnZXIBCQCsAgIJAKwCAgUHYWRkcmVzcwIKX3N1cHBsaWVkXwUKYXNzZXRJZFN0cgUGYW1vdW50BBBuZXdUb3RhbFN1cHBsaWVkCQBkAgkBDXRyeUdldEludGVnZXIBCQCsAgICD3RvdGFsX3N1cHBsaWVkXwUKYXNzZXRJZFN0cgUGYW1vdW50BARyYXRlCAkBDWdldEFjdHVhbFJhdGUCBQphc3NldElkU3RyAgVzUmF0ZQJfMQQKYXNzZXRTY2FsZQkBDmNhbGNBc3NldFNjYWxlAQUKYXNzZXRJZFN0cgQTbmV3VG90YWxTdXBwbGllZFVzZAkAawMJAGsDBRBuZXdUb3RhbFN1cHBsaWVkBQRyYXRlBQdTY2FsZTE2CAUKYXNzZXRQcmljZQJfMQUKYXNzZXRTY2FsZQMJAAACCQCzCQIJAQx0cnlHZXRTdHJpbmcBAgxzZXR1cF90b2tlbnMFCmFzc2V0SWRTdHIFBHVuaXQJAAIBAil0aGlzIGFzc2V0IGlzIG5vdCBzdXBwb3J0ZWQgYnkgdGhlIG1hcmtldAMDCQECIT0CBQltYXhTdXBwbHkAAAkAZgIFE25ld1RvdGFsU3VwcGxpZWRVc2QFCW1heFN1cHBseQcJAAIBAjNtYXggdG90YWwgc3VwcGx5IGZvciB0aGlzIHRva2VuIHJlYWNoZWQgaW4gdGhlIHBvb2wDCQBmAgkBDXRyeUdldEludGVnZXIBCQCsAgICDXNldHVwX3BhdXNlZF8FCmFzc2V0SWRTdHIAAAkAAgECKHRoaXMgYXNzZXQgY2FuJ3QgYmUgc3VwcGxpZWQgb3IgYm9ycm93ZWQEA2ludgMJAQIhPQIJAQx0cnlHZXRTdHJpbmcBCQCsAgICEHNldHVwX2F1dG9zdGFrZV8FCmFzc2V0SWRTdHICAAkA/AcEBQR0aGlzAgpzdGFrZVRva2VuCQDMCAIFCmFzc2V0SWRTdHIJAMwIAgULYXNzZXRBbW91bnQFA25pbAUDbmlsBQR1bml0AwkAAAIFA2ludgUDaW52CQDOCAIJAMwIAgkBDEludGVnZXJFbnRyeQIJAKwCAgkArAICBQdhZGRyZXNzAgpfc3VwcGxpZWRfBQphc3NldElkU3RyBRJuZXdBZGRyZXNzU3VwcGxpZWQJAMwIAgkBDEludGVnZXJFbnRyeQIJAKwCAgIPdG90YWxfc3VwcGxpZWRfBQphc3NldElkU3RyBRBuZXdUb3RhbFN1cHBsaWVkBQNuaWwFEXJhdGVzUmVjYWxjUmVzdWx0CQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBCHdpdGhkcmF3Agphc3NldElkU3RyC2Fzc2V0QW1vdW50BA0kdDAxMzQ1NzEzNTI0CQENZ2V0QWN0dWFsUmF0ZQIFCmFzc2V0SWRTdHICBXNSYXRlBAVzUmF0ZQgFDSR0MDEzNDU3MTM1MjQCXzEEEXJhdGVzUmVjYWxjUmVzdWx0CAUNJHQwMTM0NTcxMzUyNAJfMgQGYW1vdW50CQBuBAULYXNzZXRBbW91bnQFB1NjYWxlMTYFBXNSYXRlBQdDRUlMSU5HBAdhZGRyZXNzCQClCAEIBQFpBmNhbGxlcgQNYXNzZXRTdXBwbGllZAkBDXRyeUdldEludGVnZXIBCQCsAgICD3RvdGFsX3N1cHBsaWVkXwUKYXNzZXRJZFN0cgQNYXNzZXRCb3Jyb3dlZAkBDXRyeUdldEludGVnZXIBCQCsAgICD3RvdGFsX2JvcnJvd2VkXwUKYXNzZXRJZFN0cgQRdXNlckFzc2V0U3VwcGxpZWQJAQ10cnlHZXRJbnRlZ2VyAQkArAICCQCsAgIFB2FkZHJlc3MCCl9zdXBwbGllZF8FCmFzc2V0SWRTdHIEEXVzZXJBc3NldEJvcnJvd2VkCQENdHJ5R2V0SW50ZWdlcgEJAKwCAgkArAICBQdhZGRyZXNzAgpfYm9ycm93ZWRfBQphc3NldElkU3RyBBJjb2xsYXRlcmFsVmFsdWVJbnYJAPwHBAUEdGhpcwIRZ2V0VXNlckNvbGxhdGVyYWwJAMwIAgcJAMwIAgUHYWRkcmVzcwkAzAgCBgkAzAgCCQCsAgIJAKwCAgUKYXNzZXRJZFN0cgIKLHN1cHBsaWVkLAkApAMBCQEBLQEFBmFtb3VudAUDbmlsBQNuaWwDCQAAAgUSY29sbGF0ZXJhbFZhbHVlSW52BRJjb2xsYXRlcmFsVmFsdWVJbnYED2NvbGxhdGVyYWxWYWx1ZQQHJG1hdGNoMAUSY29sbGF0ZXJhbFZhbHVlSW52AwkAAQIFByRtYXRjaDACA0ludAQBeAUHJG1hdGNoMAUBeAkAAgECH2Nhbid0IGdldCB1c2VyIGNvbGxhdGVyYWwgdmFsdWUDCQEBIQEJAQ10cnlHZXRCb29sZWFuAQIMc2V0dXBfYWN0aXZlCQACAQIRbWFya2V0IGlzIHN0b3BwZWQDCQBmAgAABQ9jb2xsYXRlcmFsVmFsdWUJAAIBAjJ5b3UgZG9udCBoYXZlIGVub3VnaCBjb2xsYXRlcmFsIGZvciB0aGlzIG9wZXJhdGlvbgMJAGYCBQZhbW91bnQJAGUCBQ1hc3NldFN1cHBsaWVkBQ1hc3NldEJvcnJvd2VkCQACAQIqdGhpcyBhbW91bnQgaXMgbm90IGF2YWlsYWJsZSBvbiB0aGUgbWFya2V0AwkAZgIFBmFtb3VudAkAZQIFEXVzZXJBc3NldFN1cHBsaWVkBRF1c2VyQXNzZXRCb3Jyb3dlZAkAAgECKnRoaXMgYW1vdW50IGlzIG5vdCBhdmFpbGFibGUgZm9yIHRoaXMgdXNlcgQDaW52AwkBAiE9AgkBDHRyeUdldFN0cmluZwEJAKwCAgIQc2V0dXBfYXV0b3N0YWtlXwUKYXNzZXRJZFN0cgIACQD8BwQFBHRoaXMCDHVuc3Rha2VUb2tlbgkAzAgCBQphc3NldElkU3RyCQDMCAIFC2Fzc2V0QW1vdW50BQNuaWwFA25pbAUEdW5pdAMJAAACBQNpbnYFA2ludgQRbGltaXRDaGVja0FjdGlvbnMJARRjaGVja1dpdGhkcmF3YWxMaW1pdAQFB2FkZHJlc3MFCmFzc2V0SWRTdHIFBmFtb3VudAUFc1JhdGUDCQAAAgURbGltaXRDaGVja0FjdGlvbnMFEWxpbWl0Q2hlY2tBY3Rpb25zCQDOCAIJAM4IAgkAzAgCCQEMSW50ZWdlckVudHJ5AgkArAICCQCsAgIFB2FkZHJlc3MCCl9zdXBwbGllZF8FCmFzc2V0SWRTdHIJAGUCCQENdHJ5R2V0SW50ZWdlcgEJAKwCAgkArAICBQdhZGRyZXNzAgpfc3VwcGxpZWRfBQphc3NldElkU3RyBQZhbW91bnQJAMwIAgkBDEludGVnZXJFbnRyeQIJAKwCAgIPdG90YWxfc3VwcGxpZWRfBQphc3NldElkU3RyCQBlAgkBDXRyeUdldEludGVnZXIBCQCsAgICD3RvdGFsX3N1cHBsaWVkXwUKYXNzZXRJZFN0cgUGYW1vdW50CQDMCAIJAQ5TY3JpcHRUcmFuc2ZlcgMIBQFpBmNhbGxlcgULYXNzZXRBbW91bnQJAQ1nZXRBc3NldEJ5dGVzAQUKYXNzZXRJZFN0cgUDbmlsBRFyYXRlc1JlY2FsY1Jlc3VsdAURbGltaXRDaGVja0FjdGlvbnMJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQEGYm9ycm93Agphc3NldElkU3RyC2Fzc2V0QW1vdW50BAdhZGRyZXNzCQClCAEIBQFpBmNhbGxlcgQNJHQwMTUyODgxNTM1NQkBDWdldEFjdHVhbFJhdGUCBQphc3NldElkU3RyAgViUmF0ZQQFYlJhdGUIBQ0kdDAxNTI4ODE1MzU1Al8xBBFyYXRlc1JlY2FsY1Jlc3VsdAgFDSR0MDE1Mjg4MTUzNTUCXzIEBmFtb3VudAkAbgQFC2Fzc2V0QW1vdW50BQdTY2FsZTE2BQViUmF0ZQUHQ0VJTElORwQSY29sbGF0ZXJhbFZhbHVlSW52CQD8BwQFBHRoaXMCEWdldFVzZXJDb2xsYXRlcmFsCQDMCAIHCQDMCAIFB2FkZHJlc3MJAMwIAgYJAMwIAgkArAICCQCsAgIFCmFzc2V0SWRTdHICCixib3Jyb3dlZCwJAKQDAQUGYW1vdW50BQNuaWwFA25pbAMJAAACBRJjb2xsYXRlcmFsVmFsdWVJbnYFEmNvbGxhdGVyYWxWYWx1ZUludgQPY29sbGF0ZXJhbFZhbHVlBAckbWF0Y2gwBRJjb2xsYXRlcmFsVmFsdWVJbnYDCQABAgUHJG1hdGNoMAIDSW50BAF4BQckbWF0Y2gwBQF4CQACAQIfY2FuJ3QgZ2V0IHVzZXIgY29sbGF0ZXJhbCB2YWx1ZQMJAQEhAQkBDXRyeUdldEJvb2xlYW4BAgxzZXR1cF9hY3RpdmUJAAIBAhFtYXJrZXQgaXMgc3RvcHBlZAMJAGYCAAAFD2NvbGxhdGVyYWxWYWx1ZQkAAgECIXlvdSBoYXZlIHRvIHN1cHBseSBtb3JlIHRvIGJvcnJvdwMJAAACCQENdHJ5R2V0SW50ZWdlcgEJAKwCAgIUc2V0dXBfYm9ycm93RW5hYmxlZF8FCmFzc2V0SWRTdHIAAAkAAgECHHRoaXMgYXNzZXQgY2FuJ3QgYmUgYm9ycm93ZWQDCQBmAgkBDXRyeUdldEludGVnZXIBCQCsAgICDXNldHVwX3BhdXNlZF8FCmFzc2V0SWRTdHIAAAkAAgECKHRoaXMgYXNzZXQgY2FuJ3QgYmUgc3VwcGxpZWQgb3IgYm9ycm93ZWQEDWFzc2V0U3VwcGxpZWQJAQ10cnlHZXRJbnRlZ2VyAQkArAICAg90b3RhbF9zdXBwbGllZF8FCmFzc2V0SWRTdHIEDWFzc2V0Qm9ycm93ZWQJAQ10cnlHZXRJbnRlZ2VyAQkArAICAg90b3RhbF9ib3Jyb3dlZF8FCmFzc2V0SWRTdHIEEXVzZXJBc3NldEJvcnJvd2VkCQENdHJ5R2V0SW50ZWdlcgEJAKwCAgkArAICBQdhZGRyZXNzAgpfYm9ycm93ZWRfBQphc3NldElkU3RyAwkAZgIFBmFtb3VudAkAZQIFDWFzc2V0U3VwcGxpZWQFDWFzc2V0Qm9ycm93ZWQJAAIBAhx0aGlzIGFtb3VudCBpcyBub3QgYXZhaWxhYmxlBANpbnYDCQECIT0CCQEMdHJ5R2V0U3RyaW5nAQkArAICAhBzZXR1cF9hdXRvc3Rha2VfBQphc3NldElkU3RyAgAJAPwHBAUEdGhpcwIMdW5zdGFrZVRva2VuCQDMCAIFCmFzc2V0SWRTdHIJAMwIAgULYXNzZXRBbW91bnQFA25pbAUDbmlsBQR1bml0AwkAAAIFA2ludgUDaW52BBFsaW1pdENoZWNrQWN0aW9ucwkBEGNoZWNrQm9ycm93TGltaXQEBQdhZGRyZXNzBQphc3NldElkU3RyBQZhbW91bnQFBWJSYXRlAwkAAAIFEWxpbWl0Q2hlY2tBY3Rpb25zBRFsaW1pdENoZWNrQWN0aW9ucwkAzggCCQDOCAIJAMwIAgkBDEludGVnZXJFbnRyeQIJAKwCAgkArAICBQdhZGRyZXNzAgpfYm9ycm93ZWRfBQphc3NldElkU3RyCQBkAgURdXNlckFzc2V0Qm9ycm93ZWQFBmFtb3VudAkAzAgCCQEMSW50ZWdlckVudHJ5AgkArAICAg90b3RhbF9ib3Jyb3dlZF8FCmFzc2V0SWRTdHIJAGQCBQ1hc3NldEJvcnJvd2VkBQZhbW91bnQJAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwgFAWkGY2FsbGVyBQthc3NldEFtb3VudAkBDWdldEFzc2V0Qnl0ZXMBBQphc3NldElkU3RyBQNuaWwFEXJhdGVzUmVjYWxjUmVzdWx0BRFsaW1pdENoZWNrQWN0aW9ucwkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpAQVyZXBheQADCQEBIQEJAQ10cnlHZXRCb29sZWFuAQIMc2V0dXBfYWN0aXZlCQACAQIRbWFya2V0IGlzIHN0b3BwZWQDAwkBAiE9AgkAkAMBCAUBaQhwYXltZW50cwABBgkAAAIICQCRAwIIBQFpCHBheW1lbnRzAAAGYW1vdW50AAAJAAIBAhwxIHBheW1lbnQgaGFzIHRvIGJlIGF0dGFjaGVkBAphc3NldElkU3RyCQEOZ2V0QXNzZXRTdHJpbmcBCAkAkQMCCAUBaQhwYXltZW50cwAAB2Fzc2V0SWQEC2Fzc2V0QW1vdW50CAkAkQMCCAUBaQhwYXltZW50cwAABmFtb3VudAQNJHQwMTczNDkxNzQxNgkBDWdldEFjdHVhbFJhdGUCBQphc3NldElkU3RyAgViUmF0ZQQFYlJhdGUIBQ0kdDAxNzM0OTE3NDE2Al8xBBFyYXRlc1JlY2FsY1Jlc3VsdAgFDSR0MDE3MzQ5MTc0MTYCXzIEBmFtb3VudAkAbgQFC2Fzc2V0QW1vdW50BQdTY2FsZTE2BQViUmF0ZQUHQ0VJTElORwQHYWRkcmVzcwkApQgBCAUBaQZjYWxsZXIEDWFzc2V0U3VwcGxpZWQJAQ10cnlHZXRJbnRlZ2VyAQkArAICAg90b3RhbF9zdXBwbGllZF8FCmFzc2V0SWRTdHIEDWFzc2V0Qm9ycm93ZWQJAQ10cnlHZXRJbnRlZ2VyAQkArAICAg90b3RhbF9ib3Jyb3dlZF8FCmFzc2V0SWRTdHIEEXVzZXJBc3NldEJvcnJvd2VkCQENdHJ5R2V0SW50ZWdlcgEJAKwCAgkArAICBQdhZGRyZXNzAgpfYm9ycm93ZWRfBQphc3NldElkU3RyBAphbW91bnRMZWZ0CQBlAgURdXNlckFzc2V0Qm9ycm93ZWQFBmFtb3VudAQLcmVwYXlBbW91bnQDCQBnAgUKYW1vdW50TGVmdAAABQZhbW91bnQFEXVzZXJBc3NldEJvcnJvd2VkAwkAAAIJALMJAgkBDHRyeUdldFN0cmluZwECDHNldHVwX3Rva2VucwUKYXNzZXRJZFN0cgUEdW5pdAkAAgECKXRoaXMgYXNzZXQgaXMgbm90IHN1cHBvcnRlZCBieSB0aGUgbWFya2V0BANpbnYDCQECIT0CCQEMdHJ5R2V0U3RyaW5nAQkArAICAhBzZXR1cF9hdXRvc3Rha2VfBQphc3NldElkU3RyAgAJAPwHBAUEdGhpcwIKc3Rha2VUb2tlbgkAzAgCBQphc3NldElkU3RyCQDMCAIFC2Fzc2V0QW1vdW50BQNuaWwFA25pbAUEdW5pdAMJAAACBQNpbnYFA2ludgQMZXhjZXNzVG9rZW5zCQBlAgULYXNzZXRBbW91bnQJAGsDBQtyZXBheUFtb3VudAUFYlJhdGUFB1NjYWxlMTYJAM4IAgkAzggCCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQCsAgIJAKwCAgUHYWRkcmVzcwIKX2JvcnJvd2VkXwUKYXNzZXRJZFN0cgkAZQIFEXVzZXJBc3NldEJvcnJvd2VkBQtyZXBheUFtb3VudAkAzAgCCQEMSW50ZWdlckVudHJ5AgkArAICAg90b3RhbF9ib3Jyb3dlZF8FCmFzc2V0SWRTdHIJAGUCBQ1hc3NldEJvcnJvd2VkBQtyZXBheUFtb3VudAUDbmlsBRFyYXRlc1JlY2FsY1Jlc3VsdAMJAGcCBQphbW91bnRMZWZ0AAAFA25pbAkAzAgCCQEOU2NyaXB0VHJhbnNmZXIDCAUBaQZjYWxsZXIFDGV4Y2Vzc1Rva2VucwgJAJEDAggFAWkIcGF5bWVudHMAAAdhc3NldElkBQNuaWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQEIcmVwYXlGb3IBB2FkZHJlc3MDCQEBIQEJAQ10cnlHZXRCb29sZWFuAQIMc2V0dXBfYWN0aXZlCQACAQIRbWFya2V0IGlzIHN0b3BwZWQDCQECIT0CCAUBaQZjYWxsZXIFEnJlc2VydmVGdW5kQWRkcmVzcwkAAgECJ2F2YWlsYWJsZSBvbmx5IGZvciByZXNlcnZlIGZ1bmQgYWRkcmVzcwMJAAACBQdhZGRyZXNzAgZnbG9iYWwJAAIBAiB5b3UgY2FuJ3QgcmVwYXkgZm9yIGV2ZXJ5b25lIDpfKQMDCQECIT0CCQCQAwEIBQFpCHBheW1lbnRzAAEGCQAAAggJAJEDAggFAWkIcGF5bWVudHMAAAZhbW91bnQAAAkAAgECHDEgcGF5bWVudCBoYXMgdG8gYmUgYXR0YWNoZWQECmFzc2V0SWRTdHIJAQ5nZXRBc3NldFN0cmluZwEICQCRAwIIBQFpCHBheW1lbnRzAAAHYXNzZXRJZAQLYXNzZXRBbW91bnQICQCRAwIIBQFpCHBheW1lbnRzAAAGYW1vdW50BA0kdDAxOTA5MjE5MTU5CQENZ2V0QWN0dWFsUmF0ZQIFCmFzc2V0SWRTdHICBWJSYXRlBAViUmF0ZQgFDSR0MDE5MDkyMTkxNTkCXzEEEXJhdGVzUmVjYWxjUmVzdWx0CAUNJHQwMTkwOTIxOTE1OQJfMgQGYW1vdW50CQBuBAULYXNzZXRBbW91bnQFB1NjYWxlMTYFBWJSYXRlBQdDRUlMSU5HBA1hc3NldFN1cHBsaWVkCQENdHJ5R2V0SW50ZWdlcgEJAKwCAgIPdG90YWxfc3VwcGxpZWRfBQphc3NldElkU3RyBA1hc3NldEJvcnJvd2VkCQENdHJ5R2V0SW50ZWdlcgEJAKwCAgIPdG90YWxfYm9ycm93ZWRfBQphc3NldElkU3RyBBF1c2VyQXNzZXRCb3Jyb3dlZAkBDXRyeUdldEludGVnZXIBCQCsAgIJAKwCAgUHYWRkcmVzcwIKX2JvcnJvd2VkXwUKYXNzZXRJZFN0cgQKYW1vdW50TGVmdAkAZQIFEXVzZXJBc3NldEJvcnJvd2VkBQZhbW91bnQEC3JlcGF5QW1vdW50AwkAZwIFCmFtb3VudExlZnQAAAUGYW1vdW50BRF1c2VyQXNzZXRCb3Jyb3dlZAMJAAACCQCzCQIJAQx0cnlHZXRTdHJpbmcBAgxzZXR1cF90b2tlbnMFCmFzc2V0SWRTdHIFBHVuaXQJAAIBAil0aGlzIGFzc2V0IGlzIG5vdCBzdXBwb3J0ZWQgYnkgdGhlIG1hcmtldAQDaW52AwkBAiE9AgkBDHRyeUdldFN0cmluZwEJAKwCAgIQc2V0dXBfYXV0b3N0YWtlXwUKYXNzZXRJZFN0cgIACQD8BwQFBHRoaXMCCnN0YWtlVG9rZW4JAMwIAgUKYXNzZXRJZFN0cgkAzAgCBQthc3NldEFtb3VudAUDbmlsBQNuaWwFBHVuaXQDCQAAAgUDaW52BQNpbnYEDGV4Y2Vzc1Rva2VucwkAZQIFC2Fzc2V0QW1vdW50CQBrAwULcmVwYXlBbW91bnQFBWJSYXRlBQdTY2FsZTE2CQDOCAIJAM4IAgkAzAgCCQEMSW50ZWdlckVudHJ5AgkArAICCQCsAgIFB2FkZHJlc3MCCl9ib3Jyb3dlZF8FCmFzc2V0SWRTdHIJAGUCBRF1c2VyQXNzZXRCb3Jyb3dlZAULcmVwYXlBbW91bnQJAMwIAgkBDEludGVnZXJFbnRyeQIJAKwCAgIPdG90YWxfYm9ycm93ZWRfBQphc3NldElkU3RyCQBlAgUNYXNzZXRCb3Jyb3dlZAULcmVwYXlBbW91bnQFA25pbAURcmF0ZXNSZWNhbGNSZXN1bHQDCQBnAgUKYW1vdW50TGVmdAAABQNuaWwJAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwgFAWkGY2FsbGVyBQxleGNlc3NUb2tlbnMICQCRAwIIBQFpCHBheW1lbnRzAAAHYXNzZXRJZAUDbmlsCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBCnN0YWtlVG9rZW4CCmFzc2V0SWRTdHIGYW1vdW50BBBhdXRvc3Rha2VBZGRyZXNzCQELdmFsdWVPckVsc2UCCQCmCAEJAQx0cnlHZXRTdHJpbmcBCQCsAgICEHNldHVwX2F1dG9zdGFrZV8FCmFzc2V0SWRTdHIJAQdBZGRyZXNzAQEaAVd7yaj+ldYrLGCmdmD5UyPFihBaDe9eqNsEFXN0YWtlclN1cHBvcnRlZEFzc2V0cwkBEUBleHRyTmF0aXZlKDEwNTMpAgUQYXV0b3N0YWtlQWRkcmVzcwIVc2V0dXBfc3VwcG9ydGVkQXNzZXRzAwkBAiE9AggFAWkGY2FsbGVyBQR0aGlzCQACAQIsb25seSBmb3IgaW50ZXJuYWwgc21hcnQgY29udHJhY3QgaW52b2NhdGlvbnMDCQAAAgkAswkCBRVzdGFrZXJTdXBwb3J0ZWRBc3NldHMFCmFzc2V0SWRTdHIFBHVuaXQFA25pbAQMYW1vdW50U3Rha2VkCQENdHJ5R2V0SW50ZWdlcgEJAKwCAgIRYXV0b3N0YWtlX2Ftb3VudF8FCmFzc2V0SWRTdHIECHN0YWtlSW52CQD9BwQFEGF1dG9zdGFrZUFkZHJlc3MCB3N0YWtlTFAFA25pbAkAzAgCCQEPQXR0YWNoZWRQYXltZW50AgkBDWdldEFzc2V0Qnl0ZXMBBQphc3NldElkU3RyBQZhbW91bnQFA25pbAMJAAACBQhzdGFrZUludgUIc3Rha2VJbnYJAMwIAgkBDEludGVnZXJFbnRyeQIJAKwCAgIRYXV0b3N0YWtlX2Ftb3VudF8FCmFzc2V0SWRTdHIJAGQCBQxhbW91bnRTdGFrZWQFBmFtb3VudAUDbmlsCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBDXN0YWtlVG9rZW5BbGwBCmFzc2V0SWRTdHIDCQECIT0CCAUBaQZjYWxsZXIFBHRoaXMJAAIBAixvbmx5IGZvciBpbnRlcm5hbCBzbWFydCBjb250cmFjdCBpbnZvY2F0aW9ucwQGYW1vdW50CQEKZ2V0QmFsYW5jZQEFCmFzc2V0SWRTdHIEA2ludgkA/QcEBQR0aGlzAgpzdGFrZVRva2VuCQDMCAIFCmFzc2V0SWRTdHIJAMwIAgUGYW1vdW50BQNuaWwFA25pbAMJAAACBQNpbnYFA2ludgUDbmlsCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBDHVuc3Rha2VUb2tlbgIKYXNzZXRJZFN0cgZhbW91bnQEEGF1dG9zdGFrZUFkZHJlc3MJAQt2YWx1ZU9yRWxzZQIJAKYIAQkBDHRyeUdldFN0cmluZwEJAKwCAgIQc2V0dXBfYXV0b3N0YWtlXwUKYXNzZXRJZFN0cgkBB0FkZHJlc3MBARoBV3vJqP6V1issYKZ2YPlTI8WKEFoN716o2wQVc3Rha2VyU3VwcG9ydGVkQXNzZXRzCQERQGV4dHJOYXRpdmUoMTA1MykCBRBhdXRvc3Rha2VBZGRyZXNzAhVzZXR1cF9zdXBwb3J0ZWRBc3NldHMDCQECIT0CCAUBaQZjYWxsZXIFBHRoaXMJAAIBAixvbmx5IGZvciBpbnRlcm5hbCBzbWFydCBjb250cmFjdCBpbnZvY2F0aW9ucwMJAAACCQCzCQIFFXN0YWtlclN1cHBvcnRlZEFzc2V0cwUKYXNzZXRJZFN0cgUEdW5pdAUDbmlsBAxhbW91bnRTdGFrZWQJAQ10cnlHZXRJbnRlZ2VyAQkArAICAhFhdXRvc3Rha2VfYW1vdW50XwUKYXNzZXRJZFN0cgQIc3Rha2VJbnYJAP0HBAUQYXV0b3N0YWtlQWRkcmVzcwIJdW5zdGFrZUxQCQDMCAIFCmFzc2V0SWRTdHIJAMwIAgUGYW1vdW50BQNuaWwFA25pbAMJAAACBQhzdGFrZUludgUIc3Rha2VJbnYJAMwIAgkBDEludGVnZXJFbnRyeQIJAKwCAgIRYXV0b3N0YWtlX2Ftb3VudF8FCmFzc2V0SWRTdHIJAGUCBQxhbW91bnRTdGFrZWQFBmFtb3VudAUDbmlsCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBC2FkZEludGVyZXN0Agphc3NldElkU3RyBmFtb3VudAMJAQIhPQIIBQFpBmNhbGxlcgUEdGhpcwkAAgECGG9ubHkgZm9yIHNlbGYgaW52b2NhdGlvbgQGZWFybmVkCQENdHJ5R2V0SW50ZWdlcgEJAKwCAgIVYXV0b3N0YWtlX2xhc3RFYXJuZWRfBQphc3NldElkU3RyBApsYXN0SGVpZ2h0CQENdHJ5R2V0SW50ZWdlcgEJAKwCAgIUYXV0b3N0YWtlX2xhc3RCbG9ja18FCmFzc2V0SWRTdHIEC2NsZWFuQW1vdW50CQBrAwUGYW1vdW50AFAAZAQMc3RhdGVDaGFuZ2VzAwMJAAACBQpsYXN0SGVpZ2h0BQZoZWlnaHQGCQAAAgUGYW1vdW50AAAFA25pbAkAzAgCCQEMSW50ZWdlckVudHJ5AgkArAICAhhhdXRvc3Rha2VfcHJlTGFzdEVhcm5lZF8FCmFzc2V0SWRTdHIFBmVhcm5lZAkAzAgCCQEMSW50ZWdlckVudHJ5AgkArAICAhdhdXRvc3Rha2VfcHJlTGFzdEJsb2NrXwUKYXNzZXRJZFN0cgUKbGFzdEhlaWdodAkAzAgCCQEMSW50ZWdlckVudHJ5AgkArAICAhVhdXRvc3Rha2VfbGFzdEVhcm5lZF8FCmFzc2V0SWRTdHIJAGQCBQZlYXJuZWQFC2NsZWFuQW1vdW50CQDMCAIJAQxJbnRlZ2VyRW50cnkCCQCsAgICFGF1dG9zdGFrZV9sYXN0QmxvY2tfBQphc3NldElkU3RyBQZoZWlnaHQFA25pbAkAzggCBQxzdGF0ZUNoYW5nZXMJAMwIAgkBDEludGVnZXJFbnRyeQIJAKwCAgUKYXNzZXRJZFN0cgIGX3NSYXRlCQBkAgkBDXRyeUdldEludGVnZXIBCQCsAgIFCmFzc2V0SWRTdHICBl9zUmF0ZQkAawMFB1NjYWxlMTYFC2NsZWFuQW1vdW50CQENdHJ5R2V0SW50ZWdlcgEJAKwCAgIPdG90YWxfc3VwcGxpZWRfBQphc3NldElkU3RyBQNuaWwBaQETYWRkSW50ZXJlc3RFWFRFUk5BTAAEB2Fzc2V0SWQICQCRAwIIBQFpCHBheW1lbnRzAAAHYXNzZXRJZAQKYXNzZXRJZFN0cgkBDmdldEFzc2V0U3RyaW5nAQUHYXNzZXRJZAQJc3BsaXR0aW5nCQETZ2V0UmV3YXJkc1NwbGl0dGluZwEFCmFzc2V0SWRTdHIEBmFtb3VudAkAawMICQCRAwIIBQFpCHBheW1lbnRzAAAGYW1vdW50CAUJc3BsaXR0aW5nAl8yAGQEBmVhcm5lZAkBDXRyeUdldEludGVnZXIBCQCsAgICFWF1dG9zdGFrZV9sYXN0RWFybmVkXwUKYXNzZXRJZFN0cgQKbGFzdEhlaWdodAkBDXRyeUdldEludGVnZXIBCQCsAgICFGF1dG9zdGFrZV9sYXN0QmxvY2tfBQphc3NldElkU3RyBAxzdGF0ZUNoYW5nZXMDAwkAAAIFCmxhc3RIZWlnaHQFBmhlaWdodAYJAAACBQZhbW91bnQAAAUDbmlsCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQCsAgICGGF1dG9zdGFrZV9wcmVMYXN0RWFybmVkXwUKYXNzZXRJZFN0cgUGZWFybmVkCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQCsAgICF2F1dG9zdGFrZV9wcmVMYXN0QmxvY2tfBQphc3NldElkU3RyBQpsYXN0SGVpZ2h0CQDMCAIJAQxJbnRlZ2VyRW50cnkCCQCsAgICFWF1dG9zdGFrZV9sYXN0RWFybmVkXwUKYXNzZXRJZFN0cgkAZAIFBmVhcm5lZAUGYW1vdW50CQDMCAIJAQxJbnRlZ2VyRW50cnkCCQCsAgICFGF1dG9zdGFrZV9sYXN0QmxvY2tfBQphc3NldElkU3RyBQZoZWlnaHQFA25pbAkAzggCBQxzdGF0ZUNoYW5nZXMJAMwIAgkBDEludGVnZXJFbnRyeQIJAKwCAgUKYXNzZXRJZFN0cgIGX3NSYXRlCQBkAgkBDXRyeUdldEludGVnZXIBCQCsAgIFCmFzc2V0SWRTdHICBl9zUmF0ZQkAawMFB1NjYWxlMTYFBmFtb3VudAkBDXRyeUdldEludGVnZXIBCQCsAgICD3RvdGFsX3N1cHBsaWVkXwUKYXNzZXRJZFN0cgkAzAgCCQEOU2NyaXB0VHJhbnNmZXIDBRFzdGFibGVGdW5kQWRkcmVzcwkAawMICQCRAwIIBQFpCHBheW1lbnRzAAAGYW1vdW50CAUJc3BsaXR0aW5nAl8xAGQFB2Fzc2V0SWQFA25pbAFpAQdwcmVJbml0BAZ0b2tlbnMEbHR2cwNsdHMJcGVuYWx0aWVzCgEBZgIFYWNjdW0FdG9rZW4JAM4IAgUFYWNjdW0JAMwIAgkBDEludGVnZXJFbnRyeQIJAKwCAgUFdG9rZW4CBl9iUmF0ZQUHU2NhbGUxNgkAzAgCCQEMSW50ZWdlckVudHJ5AgkArAICBQV0b2tlbgIGX3NSYXRlBQdTY2FsZTE2BQNuaWwDCQECIT0CCAUBaQZjYWxsZXIFBHRoaXMJAAIBAgphZG1pbiBvbmx5BAVyYXRlcwoAAiRsCQC1CQIFBnRva2VucwIBLAoAAiRzCQCQAwEFAiRsCgAFJGFjYzAFA25pbAoBBSRmMF8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQEBZgIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmMF8yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQIUTGlzdCBzaXplIGV4Y2VlZHMgMTIJAQUkZjBfMgIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYABwAIAAkACgALAAwJAM4IAgkAzAgCCQELU3RyaW5nRW50cnkCAgxzZXR1cF90b2tlbnMFBnRva2VucwkAzAgCCQELU3RyaW5nRW50cnkCAgpzZXR1cF9sdHZzBQRsdHZzCQDMCAIJAQtTdHJpbmdFbnRyeQICCXNldHVwX2x0cwUDbHRzCQDMCAIJAQtTdHJpbmdFbnRyeQICD3NldHVwX3BlbmFsdGllcwUJcGVuYWx0aWVzCQDMCAIJAQxCb29sZWFuRW50cnkCAgxzZXR1cF9hY3RpdmUGBQNuaWwFBXJhdGVzAWkBDGluaXROZXdUb2tlbgQFdG9rZW4DbHR2Amx0B3BlbmFsdHkDCQECIT0CCAUBaQZjYWxsZXIFBHRoaXMJAAIBAgphZG1pbiBvbmx5CQDMCAIJAQtTdHJpbmdFbnRyeQICDHNldHVwX3Rva2VucwkArAICCQCsAgIJAQx0cnlHZXRTdHJpbmcBAgxzZXR1cF90b2tlbnMCASwFBXRva2VuCQDMCAIJAQtTdHJpbmdFbnRyeQICCnNldHVwX2x0dnMJAKwCAgkArAICCQEMdHJ5R2V0U3RyaW5nAQIKc2V0dXBfbHR2cwIBLAUDbHR2CQDMCAIJAQtTdHJpbmdFbnRyeQICCXNldHVwX2x0cwkArAICCQCsAgIJAQx0cnlHZXRTdHJpbmcBAglzZXR1cF9sdHMCASwFAmx0CQDMCAIJAQtTdHJpbmdFbnRyeQICD3NldHVwX3BlbmFsdGllcwkArAICCQCsAgIJAQx0cnlHZXRTdHJpbmcBAg9zZXR1cF9wZW5hbHRpZXMCASwFB3BlbmFsdHkJAMwIAgkBDEludGVnZXJFbnRyeQIJAKwCAgUFdG9rZW4CBl9iUmF0ZQUHU2NhbGUxNgkAzAgCCQEMSW50ZWdlckVudHJ5AgkArAICBQV0b2tlbgIGX3NSYXRlBQdTY2FsZTE2BQNuaWwBaQEPdXBkYXRlUGFyYW1ldGVyAgNrZXkDdmFsAwMJAQIhPQIIBQFpBmNhbGxlcgUEdGhpcwkBAiE9AggFAWkGY2FsbGVyBQxhZG1pbkFkZHJlc3MHCQACAQIKYWRtaW4gb25seQkAzAgCCQEMSW50ZWdlckVudHJ5AgUDa2V5CQENcGFyc2VJbnRWYWx1ZQEFA3ZhbAUDbmlsAWkBDHVwZGF0ZVN0cmluZwIDa2V5A3ZhbAMDCQECIT0CCAUBaQZjYWxsZXIFBHRoaXMJAQIhPQIIBQFpBmNhbGxlcgUMYWRtaW5BZGRyZXNzBwkAAgECCmFkbWluIG9ubHkJAMwIAgkBC1N0cmluZ0VudHJ5AgUDa2V5BQN2YWwFA25pbAFpARJjbGFpbVRvUmVzZXJ2ZUZ1bmQBBWRlYnVnBAZhc3NldHMJAQ9nZXRNYXJrZXRBc3NldHMABAVyYXRlcwgJAQ1nZXRBY3R1YWxSYXRlAgkAkQMCBQZhc3NldHMAAAIFc1JhdGUCXzIEAmxpCQDMCAIAAAkAzAgCAAEJAMwIAgACCQDMCAIAAwkAzAgCAAQJAMwIAgAFCQDMCAIABgkAzAgCAAcJAMwIAgAICQDMCAIACQkAzAgCAAoJAMwIAgALBQNuaWwKAQFmAgVhY2N1bQFuAwkAZwIFAW4JAJADAQUGYXNzZXRzBQVhY2N1bQQKYXNzZXRJZFN0cgkAkQMCBQZhc3NldHMFAW4ED2F1dG9zdGFrZUFtb3VudAkBDHRyeUdldFN0cmluZwEJAKwCAgIRYXV0b3N0YWtlX2Ftb3VudF8FCmFzc2V0SWRTdHIEBmFtb3VudAkAZQIJAGQCCQBkAgkAZAIJAQpnZXRCYWxhbmNlAQUKYXNzZXRJZFN0cgkBDXRyeUdldEludGVnZXIBCQCsAgICEWF1dG9zdGFrZV9hbW91bnRfBQphc3NldElkU3RyAwkBAiE9AgUPYXV0b3N0YWtlQW1vdW50AgAJAQ1wYXJzZUludFZhbHVlAQUPYXV0b3N0YWtlQW1vdW50AAAJAGsDCQENdHJ5R2V0SW50ZWdlcgEJAKwCAgIPdG90YWxfYm9ycm93ZWRfBQphc3NldElkU3RyCAkAkQMCBQVyYXRlcwkAZAIJAGgCBQFuAAMAAQV2YWx1ZQUHU2NhbGUxNgkAawMJAQ10cnlHZXRJbnRlZ2VyAQkArAICAg90b3RhbF9zdXBwbGllZF8FCmFzc2V0SWRTdHIICQCRAwIFBXJhdGVzCQBoAgUBbgADBXZhbHVlBQdTY2FsZTE2BANpbnYDCQECIT0CCQEMdHJ5R2V0U3RyaW5nAQkArAICAhBzZXR1cF9hdXRvc3Rha2VfBQphc3NldElkU3RyAgAJAPwHBAUEdGhpcwIMdW5zdGFrZVRva2VuCQDMCAIFCmFzc2V0SWRTdHIJAMwIAgUGYW1vdW50BQNuaWwFA25pbAUEdW5pdAMJAAACBQNpbnYFA2ludgkAzggCBQVhY2N1bQkAzAgCBQZhbW91bnQFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgQJcGFyYW1ldGVyCgACJGwFAmxpCgACJHMJAJADAQUCJGwKAAUkYWNjMAUDbmlsCgEFJGYwXzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAQFmAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGYwXzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhRMaXN0IHNpemUgZXhjZWVkcyAxMgkBBSRmMF8yAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgUFJGFjYzAAAAABAAIAAwAEAAUABgAHAAgACQAKAAsADAoBAmYyAgVhY2N1bQFuAwkAZwIFAW4JAJADAQUGYXNzZXRzBQVhY2N1bQQKYXNzZXRJZFN0cgkAkQMCBQZhc3NldHMFAW4JAM4IAgUFYWNjdW0JAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwUScmVzZXJ2ZUZ1bmRBZGRyZXNzCQCWAwEJAMwIAgkAkQMCBQlwYXJhbWV0ZXIFAW4JAMwIAgAABQNuaWwJAQ1nZXRBc3NldEJ5dGVzAQUKYXNzZXRJZFN0cgUDbmlsAwUFZGVidWcJAAIBCQEKbGlJbnRUb1N0cgEFCXBhcmFtZXRlcgkAlAoCCgACJGwFAmxpCgACJHMJAJADAQUCJGwKAAUkYWNjMAUDbmlsCgEFJGYxXzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAQJmMgIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmMV8yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQIUTGlzdCBzaXplIGV4Y2VlZHMgMTIJAQUkZjFfMgIJAQUkZjFfMQIJAQUkZjFfMQIJAQUkZjFfMQIJAQUkZjFfMQIJAQUkZjFfMQIJAQUkZjFfMQIJAQUkZjFfMQIJAQUkZjFfMQIJAQUkZjFfMQIJAQUkZjFfMQIJAQUkZjFfMQIJAQUkZjFfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYABwAIAAkACgALAAwFCXBhcmFtZXRlcgFpAQdyZVNldHVwAQphc3NldElkU3RyBAtsYXN0UmVzZXR1cAkBDXRyeUdldEludGVnZXIBAhJyZXNldHVwX2xhc3RVcGRhdGUDCQBmAgUJZGF5QmxvY2tzCQBlAgUGaGVpZ2h0BQtsYXN0UmVzZXR1cAkAAgECIGNhbiBiZSB1cGRhdGVkIG9ubHkgb25jZSBwZXIgZGF5BANsdHMJALUJAgkBDHRyeUdldFN0cmluZwECCXNldHVwX2x0cwIBLAQGYXNzZXRzCQEPZ2V0TWFya2V0QXNzZXRzAAQCdXIJAQVnZXRVcgEFCmFzc2V0SWRTdHIEBnRlbXBMVAkBDXRyeUdldEludGVnZXIBCQCsAgIJAKwCAgIGc2V0dXBfBQphc3NldElkU3RyAgdfdGVtcExUBAJsdAkBDXBhcnNlSW50VmFsdWUBCQCRAwIFBmFzc2V0cwkBBXZhbHVlAQkAzwgCBQZhc3NldHMFCmFzc2V0SWRTdHIDCQBmAgUCdXIAgJX1KgkAzAgCCQEMSW50ZWdlckVudHJ5AgkArAICCQCsAgICBnNldHVwXwUKYXNzZXRJZFN0cgIHX3RlbXBMVAkAawMFBnRlbXBMVAD3TQCQTgUDbmlsAwMJAGYCBQJsdAUGdGVtcExUCQBmAgCAlfUqBQJ1cgcJAMwIAgkBDEludGVnZXJFbnRyeQIJAKwCAgkArAICAgZzZXR1cF8FCmFzc2V0SWRTdHICB190ZW1wTFQJAGsDBQZ0ZW1wTFQAqU4AkE4FA25pbAUDbmlsAWkBCHNodXRkb3duAQhzaHV0ZG93bgMJAAACCQDPCAIFEXNodXRkb3duV2hpdGVsaXN0CAUBaQZjYWxsZXIFBHVuaXQJAAIBAhd1c2VyIG5vdCBpbiBhIHdoaXRlbGlzdAkAzAgCCQEMQm9vbGVhbkVudHJ5AgIMc2V0dXBfYWN0aXZlCQEBIQEFCHNodXRkb3duBQNuaWwBaQEJbGlxdWlkYXRlBgVkZWJ1ZwdhZGRyZXNzC2Fzc2V0QW1vdW50C3NBc3NldElkU3RyC2JBc3NldElkU3RyCHJvdXRlU3RyAwkBASEBCQEWdmVyaWZ5TGlxdWlkYXRvclJpZ2h0cwEIBQFpBmNhbGxlcgkAAgECKHRlbXBvcmFyaWx5IGF2YWlsYWJsZSBmb3Igd2hpdGVsaXN0IG9ubHkDCQEBIQEJAQ10cnlHZXRCb29sZWFuAQIMc2V0dXBfYWN0aXZlCQACAQIRbWFya2V0IGlzIHN0b3BwZWQEDnVzZXJDb2xsYXRlcmFsCQESY2FsY1VzZXJDb2xsYXRlcmFsAQUHYWRkcmVzcwMJAAACBQ51c2VyQ29sbGF0ZXJhbAUOdXNlckNvbGxhdGVyYWwEDSR0MDI4MzYwMjg0MjIJAQ1nZXRBY3R1YWxSYXRlAgULc0Fzc2V0SWRTdHICBXNSYXRlBAVzUmF0ZQgFDSR0MDI4MzYwMjg0MjICXzEEC3JhdGVzUmVzdWx0CAUNJHQwMjgzNjAyODQyMgJfMgQNJHQwMjg0MjcyODQ5NgkBDWdldEFjdHVhbFJhdGUCBQtiQXNzZXRJZFN0cgIFYlJhdGUEBWJSYXRlCAUNJHQwMjg0MjcyODQ5NgJfMQQScmF0ZXNSZWNhbGNSZXN1bHQyCAUNJHQwMjg0MjcyODQ5NgJfMgQMc0Fzc2V0QW1vdW50CQBrAwULYXNzZXRBbW91bnQFB1NjYWxlMTYFBXNSYXRlBBBjdXJyZW50U1Bvc2l0aW9uCQENdHJ5R2V0SW50ZWdlcgEJAKwCAgkArAICBQdhZGRyZXNzAgpfc3VwcGxpZWRfBQtzQXNzZXRJZFN0cgQTY3VycmVudEJQb3NpdGlvblZhbAkBDXRyeUdldEludGVnZXIBCQCsAgIJAKwCAgUHYWRkcmVzcwIKX2JvcnJvd2VkXwULYkFzc2V0SWRTdHIEEGN1cnJlbnRCUG9zaXRpb24DCQBmAgUTY3VycmVudEJQb3NpdGlvblZhbAAABRNjdXJyZW50QlBvc2l0aW9uVmFsCQACAQIgdXNlciBoYXMgbm8gYm9ycm93IGluIHRoaXMgdG9rZW4DCQBmAgUOdXNlckNvbGxhdGVyYWwAAAkAAgECGHVzZXIgY2FuJ3QgYmUgbGlxdWlkYXRlZAMJAGYCBQxzQXNzZXRBbW91bnQFEGN1cnJlbnRTUG9zaXRpb24JAAIBAjJwb3NpdGlvbiB0byBsaXF1aWRhdGUgaXMgYmlnZ2VyIHRoYW4gdXNlcidzIHN1cHBseQQDaW52AwkBAiE9AgkBDHRyeUdldFN0cmluZwEJAKwCAgIQc2V0dXBfYXV0b3N0YWtlXwULc0Fzc2V0SWRTdHICAAkA/AcEBQR0aGlzAgx1bnN0YWtlVG9rZW4JAMwIAgULc0Fzc2V0SWRTdHIJAMwIAgUMc0Fzc2V0QW1vdW50BQNuaWwFA25pbAUEdW5pdAMJAAACBQNpbnYFA2ludgQOYmFsYW5jZTBCZWZvcmUJAQpnZXRCYWxhbmNlAQULc0Fzc2V0SWRTdHIDCQAAAgUOYmFsYW5jZTBCZWZvcmUFDmJhbGFuY2UwQmVmb3JlBA5iYWxhbmNlMUJlZm9yZQkBCmdldEJhbGFuY2UBBQtiQXNzZXRJZFN0cgMJAAACBQ5iYWxhbmNlMUJlZm9yZQUOYmFsYW5jZTFCZWZvcmUEDmV4Y2hhbmdlSW52b2tlCQD8BwQFEWFnZ3JlZ2F0b3JBZGRyZXNzAgRzd2FwCQDMCAIFCHJvdXRlU3RyCQDMCAIAAAUDbmlsCQDMCAIJAQ9BdHRhY2hlZFBheW1lbnQCCQENZ2V0QXNzZXRCeXRlcwEFC3NBc3NldElkU3RyBQthc3NldEFtb3VudAUDbmlsAwkAAAIFDmV4Y2hhbmdlSW52b2tlBQ5leGNoYW5nZUludm9rZQQKYXNzZXQwU29sZAkAZQIFDmJhbGFuY2UwQmVmb3JlCQEKZ2V0QmFsYW5jZQEFC3NBc3NldElkU3RyAwkAAAIFCmFzc2V0MFNvbGQFCmFzc2V0MFNvbGQEDGFzc2V0MUJvdWdodAkAZQIJAQpnZXRCYWxhbmNlAQULYkFzc2V0SWRTdHIFDmJhbGFuY2UxQmVmb3JlAwkAAAIFDGFzc2V0MUJvdWdodAUMYXNzZXQxQm91Z2h0BAthc3NldDBQcmljZQgJARNnZXRUb2tlblByaWNlQ2FwcGVkAQULc0Fzc2V0SWRTdHICXzEEC2Fzc2V0MFNjYWxlCQEOY2FsY0Fzc2V0U2NhbGUBBQtzQXNzZXRJZFN0cgQJYXNzZXQwVXNkCQBrAwUKYXNzZXQwU29sZAULYXNzZXQwUHJpY2UFC2Fzc2V0MFNjYWxlBAthc3NldDFQcmljZQgJARNnZXRUb2tlblByaWNlQ2FwcGVkAQULYkFzc2V0SWRTdHICXzIEC2Fzc2V0MVNjYWxlCQEOY2FsY0Fzc2V0U2NhbGUBBQtiQXNzZXRJZFN0cgQJYXNzZXQxVXNkCQBrAwUMYXNzZXQxQm91Z2h0BQthc3NldDFQcmljZQULYXNzZXQxU2NhbGUEB3BlbmFsdHkJAQ1wYXJzZUludFZhbHVlAQkAkQMCCQC1CQIJAQx0cnlHZXRTdHJpbmcBAg9zZXR1cF9wZW5hbHRpZXMCASwJAQV2YWx1ZQEJAM8IAgkBD2dldE1hcmtldEFzc2V0cwAFC2JBc3NldElkU3RyBBFsaXF1aWRhdGlvblByb2ZpdAkAZQIFCWFzc2V0MVVzZAkAawMFCWFzc2V0MFVzZAkAZQIFBlNjYWxlOAUHcGVuYWx0eQUGU2NhbGU4BAxzQXNzZXRDaGFuZ2UJAGsDBQphc3NldDBTb2xkBQdTY2FsZTE2BQVzUmF0ZQQMYkFzc2V0Q2hhbmdlCQBrAwkAawMFDGFzc2V0MUJvdWdodAUHU2NhbGUxNgUFYlJhdGUJAGUCBQZTY2FsZTgJAGsDBRFsaXF1aWRhdGlvblByb2ZpdAUGU2NhbGU4BQlhc3NldDFVc2QFBlNjYWxlOAMJAGYCBQphc3NldDBTb2xkBQthc3NldEFtb3VudAkAAgECI21vcmUgYXNzZXRzIGV4Y2hhbmdlZCB0aGFuIGV4cGVjdGVkAwkAZgIAAAURbGlxdWlkYXRpb25Qcm9maXQJAAIBAi9wcmljZSBpbXBhY3QgaXMgYmlnZ2VyIHRoYW4gbGlxdWlkYXRpb24gcGVuYWx0eQkAzAgCCQEMSW50ZWdlckVudHJ5AgkArAICCQCsAgIFB2FkZHJlc3MCCl9zdXBwbGllZF8FC3NBc3NldElkU3RyCQBlAgUQY3VycmVudFNQb3NpdGlvbgUMc0Fzc2V0Q2hhbmdlCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQCsAgIJAKwCAgUHYWRkcmVzcwIKX2JvcnJvd2VkXwULYkFzc2V0SWRTdHIJAGUCBRBjdXJyZW50QlBvc2l0aW9uBQxiQXNzZXRDaGFuZ2UJAMwIAgkBDEludGVnZXJFbnRyeQIJAKwCAgIPdG90YWxfc3VwcGxpZWRfBQtzQXNzZXRJZFN0cgkAZQIJAQ10cnlHZXRJbnRlZ2VyAQkArAICAg90b3RhbF9zdXBwbGllZF8FC3NBc3NldElkU3RyBQxzQXNzZXRDaGFuZ2UJAMwIAgkBDEludGVnZXJFbnRyeQIJAKwCAgIPdG90YWxfYm9ycm93ZWRfBQtiQXNzZXRJZFN0cgkAZQIJAQ10cnlHZXRJbnRlZ2VyAQkArAICAg90b3RhbF9ib3Jyb3dlZF8FC2JBc3NldElkU3RyBQxiQXNzZXRDaGFuZ2UFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpAQtsaXF1aWRhdGVWMgMFZGVidWcHYWRkcmVzcwtzQXNzZXRJZFN0cgMJAQEhAQkBFnZlcmlmeUxpcXVpZGF0b3JSaWdodHMBCAUBaQZjYWxsZXIJAAIBAih0ZW1wb3JhcmlseSBhdmFpbGFibGUgZm9yIHdoaXRlbGlzdCBvbmx5AwkBASEBCQENdHJ5R2V0Qm9vbGVhbgECDHNldHVwX2FjdGl2ZQkAAgECEW1hcmtldCBpcyBzdG9wcGVkBAhiQXNzZXRJZAgJAJEDAggFAWkIcGF5bWVudHMAAAdhc3NldElkBAtiQXNzZXRJZFN0cgkBDmdldEFzc2V0U3RyaW5nAQUIYkFzc2V0SWQEDGJBc3NldEFtb3VudAgJAJEDAggFAWkIcGF5bWVudHMAAAZhbW91bnQEDnVzZXJDb2xsYXRlcmFsCQESY2FsY1VzZXJDb2xsYXRlcmFsAQUHYWRkcmVzcwMJAAACBQ51c2VyQ29sbGF0ZXJhbAUOdXNlckNvbGxhdGVyYWwDCQBmAgUOdXNlckNvbGxhdGVyYWwAAAkAAgECGHVzZXIgY2FuJ3QgYmUgbGlxdWlkYXRlZAQMbWFya2V0QXNzZXRzCQEPZ2V0TWFya2V0QXNzZXRzAAQJYXNzZXQxTnVtCQEFdmFsdWUBCQDPCAIFDG1hcmtldEFzc2V0cwULYkFzc2V0SWRTdHIECWFzc2V0ME51bQkBBXZhbHVlAQkAzwgCBQxtYXJrZXRBc3NldHMFC3NBc3NldElkU3RyBA0kdDAzMTgzNzMxODk5CQENZ2V0QWN0dWFsUmF0ZQIFC2JBc3NldElkU3RyAgViUmF0ZQQFYlJhdGUIBQ0kdDAzMTgzNzMxODk5Al8xBAtyYXRlc1Jlc3VsdAgFDSR0MDMxODM3MzE4OTkCXzIEC2Fzc2V0MVByaWNlCAkBE2dldFRva2VuUHJpY2VDYXBwZWQBBQtiQXNzZXRJZFN0cgJfMgQLYXNzZXQxU2NhbGUJAQ5jYWxjQXNzZXRTY2FsZQEFC2JBc3NldElkU3RyBApiQW1vdW50VXNkCQBrAwUMYkFzc2V0QW1vdW50BQthc3NldDFQcmljZQULYXNzZXQxU2NhbGUEB3BlbmFsdHkJAQ1wYXJzZUludFZhbHVlAQkBBXZhbHVlAQkAkQMCCQC1CQIJAQx0cnlHZXRTdHJpbmcBAg9zZXR1cF9wZW5hbHRpZXMCASwFCWFzc2V0MU51bQQLYXNzZXQwUHJpY2UICQETZ2V0VG9rZW5QcmljZUNhcHBlZAEFC3NBc3NldElkU3RyAl8xBAthc3NldDBTY2FsZQkBDmNhbGNBc3NldFNjYWxlAQULc0Fzc2V0SWRTdHIECnNBbW91bnRVc2QJAGsDBQpiQW1vdW50VXNkCQBkAgUGU2NhbGU4BQdwZW5hbHR5BQZTY2FsZTgEDHNBc3NldEFtb3VudAkAawMFCnNBbW91bnRVc2QFC2Fzc2V0MFNjYWxlBQthc3NldDBQcmljZQQHYkFtb3VudAkAawMFDGJBc3NldEFtb3VudAUHU2NhbGUxNgUFYlJhdGUEB3NBbW91bnQJAGsDBQxzQXNzZXRBbW91bnQFB1NjYWxlMTYICQCRAwIFC3JhdGVzUmVzdWx0CQBoAgUJYXNzZXQwTnVtAAMFdmFsdWUEEGN1cnJlbnRTUG9zaXRpb24JAQ10cnlHZXRJbnRlZ2VyAQkArAICCQCsAgIFB2FkZHJlc3MCCl9zdXBwbGllZF8FC3NBc3NldElkU3RyBBNjdXJyZW50QlBvc2l0aW9uVmFsCQENdHJ5R2V0SW50ZWdlcgEJAKwCAgkArAICBQdhZGRyZXNzAgpfYm9ycm93ZWRfBQtiQXNzZXRJZFN0cgQQY3VycmVudEJQb3NpdGlvbgMJAGYCBRNjdXJyZW50QlBvc2l0aW9uVmFsAAAFE2N1cnJlbnRCUG9zaXRpb25WYWwJAAIBAiB1c2VyIGhhcyBubyBib3Jyb3cgaW4gdGhpcyB0b2tlbgMJAGYCBQdzQW1vdW50BRBjdXJyZW50U1Bvc2l0aW9uCQACAQIycG9zaXRpb24gdG8gbGlxdWlkYXRlIGlzIGJpZ2dlciB0aGFuIHVzZXIncyBzdXBwbHkEA2ludgMJAQIhPQIJAQx0cnlHZXRTdHJpbmcBCQCsAgICEHNldHVwX2F1dG9zdGFrZV8FC3NBc3NldElkU3RyAgAJAPwHBAUEdGhpcwIMdW5zdGFrZVRva2VuCQDMCAIFC3NBc3NldElkU3RyCQDMCAIFDHNBc3NldEFtb3VudAUDbmlsBQNuaWwFBHVuaXQDCQAAAgUDaW52BQNpbnYDBQVkZWJ1ZwkAAgECFWxpcXVpZGF0aW9uIHdpbGwgcGFzcwkAzggCCQDMCAIJAQ5TY3JpcHRUcmFuc2ZlcgMIBQFpBmNhbGxlcgUMc0Fzc2V0QW1vdW50CQENZ2V0QXNzZXRCeXRlcwEFC3NBc3NldElkU3RyCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQCsAgIJAKwCAgUHYWRkcmVzcwIKX3N1cHBsaWVkXwULc0Fzc2V0SWRTdHIJAGUCBRBjdXJyZW50U1Bvc2l0aW9uBQdzQW1vdW50CQDMCAIJAQxJbnRlZ2VyRW50cnkCCQCsAgIJAKwCAgUHYWRkcmVzcwIKX2JvcnJvd2VkXwULYkFzc2V0SWRTdHIJAGUCBRBjdXJyZW50QlBvc2l0aW9uBQdiQW1vdW50CQDMCAIJAQxJbnRlZ2VyRW50cnkCCQCsAgICD3RvdGFsX3N1cHBsaWVkXwULc0Fzc2V0SWRTdHIJAGUCCQENdHJ5R2V0SW50ZWdlcgEJAKwCAgIPdG90YWxfc3VwcGxpZWRfBQtzQXNzZXRJZFN0cgUHc0Ftb3VudAkAzAgCCQEMSW50ZWdlckVudHJ5AgkArAICAg90b3RhbF9ib3Jyb3dlZF8FC2JBc3NldElkU3RyCQBlAgkBDXRyeUdldEludGVnZXIBCQCsAgICD3RvdGFsX2JvcnJvd2VkXwULYkFzc2V0SWRTdHIFB2JBbW91bnQFA25pbAULcmF0ZXNSZXN1bHQJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQERZ2V0VXNlckNvbGxhdGVyYWwEBWRlYnVnB2FkZHJlc3MNbWludXNCb3Jyb3dlZAthZnRlckNoYW5nZQQGYXNzZXRzCQEPZ2V0TWFya2V0QXNzZXRzAAQEbHR2cwkAtQkCCQEMdHJ5R2V0U3RyaW5nAQIKc2V0dXBfbHR2cwIBLAQDbHRzCQC1CQIJAQx0cnlHZXRTdHJpbmcBAglzZXR1cF9sdHMCASwEBXJhdGVzCAkBDWdldEFjdHVhbFJhdGUCCQCRAwIFBmFzc2V0cwAAAgVzUmF0ZQJfMgQNY2hhbmdlSGFuZGxlcgkAtQkCBQthZnRlckNoYW5nZQIBLAoBAWYCBWFjY3VtBG5leHQDCQBnAgUEbmV4dAkAkAMBBQZhc3NldHMFBWFjY3VtBAx1c2VyU3VwcGxpZWQJAQ10cnlHZXRJbnRlZ2VyAQkArAICCQCsAgIFB2FkZHJlc3MCCl9zdXBwbGllZF8JAJEDAgUGYXNzZXRzBQRuZXh0BAx1c2VyQm9ycm93ZWQJAQ10cnlHZXRJbnRlZ2VyAQkArAICCQCsAgIFB2FkZHJlc3MCCl9ib3Jyb3dlZF8JAJEDAgUGYXNzZXRzBQRuZXh0BBNuZWVkVG9rZW5BY2NvdW50aW5nAwkAAAIFC2FmdGVyQ2hhbmdlAgADAwkBAiE9AgUMdXNlckJvcnJvd2VkAAAGCQECIT0CBQx1c2VyU3VwcGxpZWQAAAYHBgMFE25lZWRUb2tlbkFjY291bnRpbmcECmFzc2V0U2NhbGUJAQ5jYWxjQXNzZXRTY2FsZQEJAJEDAgUGYXNzZXRzBQRuZXh0BAphc3NldFByaWNlCQETZ2V0VG9rZW5QcmljZUNhcHBlZAEJAJEDAgUGYXNzZXRzBQRuZXh0CQBlAgkAZAIFBWFjY3VtCQBrAwkAawMJAGsDCQBkAgUMdXNlclN1cHBsaWVkAwMDCQECIT0CBQthZnRlckNoYW5nZQIACQAAAgkAkQMCBQ1jaGFuZ2VIYW5kbGVyAAAJAJEDAgUGYXNzZXRzBQRuZXh0BwkAAAIJAJEDAgUNY2hhbmdlSGFuZGxlcgABAghzdXBwbGllZAcJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQ1jaGFuZ2VIYW5kbGVyAAIAAAgJAJEDAgUFcmF0ZXMJAGgCBQRuZXh0AAMFdmFsdWUFB1NjYWxlMTYJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQRsdHZzBQRuZXh0BQZTY2FsZTgIBQphc3NldFByaWNlAl8xBQphc3NldFNjYWxlAwUNbWludXNCb3Jyb3dlZAkAawMJAGsDCQBrAwkAZAIFDHVzZXJCb3Jyb3dlZAMDAwkBAiE9AgULYWZ0ZXJDaGFuZ2UCAAkAAAIJAJEDAgUNY2hhbmdlSGFuZGxlcgAACQCRAwIFBmFzc2V0cwUEbmV4dAcJAAACCQCRAwIFDWNoYW5nZUhhbmRsZXIAAQIIYm9ycm93ZWQHCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUNY2hhbmdlSGFuZGxlcgACAAAICQCRAwIFBXJhdGVzCQBkAgkAaAIFBG5leHQAAwABBXZhbHVlBQdTY2FsZTE2BQZTY2FsZTgJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQNsdHMFBG5leHQIBQphc3NldFByaWNlAl8yBQphc3NldFNjYWxlAAAFBWFjY3VtBAZyZXN1bHQKAAIkbAkAzAgCAAAJAMwIAgABCQDMCAIAAgkAzAgCAAMJAMwIAgAECQDMCAIABQkAzAgCAAYJAMwIAgAHCQDMCAIACAkAzAgCAAkJAMwIAgAKCQDMCAIACwUDbmlsCgACJHMJAJADAQUCJGwKAAUkYWNjMAAACgEFJGYwXzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAQFmAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGYwXzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhRMaXN0IHNpemUgZXhjZWVkcyAxMgkBBSRmMF8yAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgUFJGFjYzAAAAABAAIAAwAEAAUABgAHAAgACQAKAAsADAMFBWRlYnVnCQACAQkApAMBBQZyZXN1bHQJAJQKAgUFcmF0ZXMFBnJlc3VsdAFpAQlnZXRQcmljZXMBBWRlYnVnBAZhc3NldHMJAQ9nZXRNYXJrZXRBc3NldHMACgEBZgIFYWNjdW0EbmV4dAMJAGcCBQRuZXh0CQCQAwEFBmFzc2V0cwUFYWNjdW0ECmFzc2V0UHJpY2UJARVnZXRUb2tlblByaWNlV2l0aFJpc2sCCQCRAwIFBmFzc2V0cwUEbmV4dAADCQCsAgIJAKwCAgkArAICCQCsAgIFBWFjY3VtCQCkAwEIBQphc3NldFByaWNlAl8xAgEsCQCkAwEIBQphc3NldFByaWNlAl8yAgF8BAZyZXN1bHQKAAIkbAkAzAgCAAAJAMwIAgABCQDMCAIAAgkAzAgCAAMJAMwIAgAECQDMCAIABQkAzAgCAAYJAMwIAgAHCQDMCAIACAkAzAgCAAkJAMwIAgAKCQDMCAIACwUDbmlsCgACJHMJAJADAQUCJGwKAAUkYWNjMAIACgEFJGYwXzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAQFmAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGYwXzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhRMaXN0IHNpemUgZXhjZWVkcyAxMgkBBSRmMF8yAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgUFJGFjYzAAAAABAAIAAwAEAAUABgAHAAgACQAKAAsADAMFBWRlYnVnCQACAQUGcmVzdWx0CQCUCgIFA25pbAUGcmVzdWx0AWkBGWNhbGN1bGF0ZVV0aWxpemF0aW9uUmF0aW8CCmFzc2V0SWRTdHIFZGVidWcDBQVkZWJ1ZwkAAgEJAKQDAQkBBWdldFVyAQUKYXNzZXRJZFN0cgkAlAoCBQNuaWwJAQVnZXRVcgEFCmFzc2V0SWRTdHIBaQETY2FsY3VsYXRlT3V0ZGF0ZWRVUgIKYXNzZXRJZFN0cgVkZWJ1ZwMFBWRlYnVnCQACAQkApAMBCQENZ2V0T3V0ZGF0ZWRVcgEFCmFzc2V0SWRTdHIJAJQKAgUDbmlsCQENZ2V0T3V0ZGF0ZWRVcgEFCmFzc2V0SWRTdHIBaQETY2FsY3VsYXRlVG9rZW5SYXRlcwEFZGVidWcKAQFmAgVhY2N1bQphc3NldElkU3RyBAVyYXRlcwkBEHRva2VuUmF0ZXNSZWNhbGMBBQphc3NldElkU3RyCQCUCgIJAKwCAgkArAICCQCsAgIJAKwCAggFBWFjY3VtAl8xCQCkAwEICQCRAwIFBXJhdGVzAAEFdmFsdWUCAXwJAKQDAQgJAJEDAgUFcmF0ZXMAAAV2YWx1ZQIBLAkAzggCCAUFYWNjdW0CXzIFBXJhdGVzBAlwYXJhbWV0ZXIKAAIkbAkBD2dldE1hcmtldEFzc2V0cwAKAAIkcwkAkAMBBQIkbAoABSRhY2MwCQCUCgICAAUDbmlsCgEFJGYwXzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAQFmAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGYwXzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhRMaXN0IHNpemUgZXhjZWVkcyAxMgkBBSRmMF8yAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgUFJGFjYzAAAAABAAIAAwAEAAUABgAHAAgACQAKAAsADAMFBWRlYnVnCQACAQgFCXBhcmFtZXRlcgJfMQkAlAoCCAUJcGFyYW1ldGVyAl8yCAUJcGFyYW1ldGVyAl8xAWkBF2NhbGN1bGF0ZVRva2Vuc0ludGVyZXN0AQVkZWJ1ZwoBAWYCBWFjY3VtCmFzc2V0SWRTdHIEBHJhdGUJAGsDCQELZ2V0SW50ZXJlc3QBBQphc3NldElkU3RyBQlkYXlCbG9ja3MFBlNjYWxlOAkArAICCQCsAgIFBWFjY3VtCQCkAwEFBHJhdGUCASwECXBhcmFtZXRlcgoAAiRsCQEPZ2V0TWFya2V0QXNzZXRzAAoAAiRzCQCQAwEFAiRsCgAFJGFjYzACAAoBBSRmMF8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQEBZgIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmMF8yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQIUTGlzdCBzaXplIGV4Y2VlZHMgMTIJAQUkZjBfMgIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYABwAIAAkACgALAAwDBQVkZWJ1ZwkAAgEFCXBhcmFtZXRlcgkAlAoCBQNuaWwFCXBhcmFtZXRlcgFpARJzZXRBcHByb3ZlckFkZHJlc3MBD2FwcHJvdmVyQWRkcmVzcwQGaXNTZWxmAwkAAAIIBQFpBmNhbGxlcgUEdGhpcwYJAAIBAhBPbmx5IHNlbGYgaW52b2tlAwkAAAIFBmlzU2VsZgUGaXNTZWxmBBBfYXBwcm92ZXJBZGRyZXNzCQCmCAEFD2FwcHJvdmVyQWRkcmVzcwQKYXBwcm92ZXJPawQHJG1hdGNoMAUQX2FwcHJvdmVyQWRkcmVzcwMJAAECBQckbWF0Y2gwAgdBZGRyZXNzBAF0BQckbWF0Y2gwBgcEDmNhblNldEFwcHJvdmVyAwMFCmFwcHJvdmVyT2sGCQAAAgUPYXBwcm92ZXJBZGRyZXNzAgAGCQACAQIWV3JvbmcgYXBwcm92ZXIgYWRkcmVzcwMJAAACBQ5jYW5TZXRBcHByb3ZlcgUOY2FuU2V0QXBwcm92ZXIECGlzSW5pdGVkCQELdmFsdWVPckVsc2UCCQCbCAIJAQV2YWx1ZQEFEF9hcHByb3ZlckFkZHJlc3MCBklOSVRFRAcECWhhc0FkbWlucwkBAiE9AgkBC3ZhbHVlT3JFbHNlAgkAnQgCCQEFdmFsdWUBBRBfYXBwcm92ZXJBZGRyZXNzAgtBRE1JTlNfUEJLUwIAAgAEEmlzQXBwcm92ZXJDb250cmFjdAMDCQAAAgUPYXBwcm92ZXJBZGRyZXNzAgAGAwUIaXNJbml0ZWQFCWhhc0FkbWlucwcGCQACAQIgQWRkcmVzcyBpcyBub3QgYXBwcm92ZXIgY29udHJhY3QDCQAAAgUSaXNBcHByb3ZlckNvbnRyYWN0BRJpc0FwcHJvdmVyQ29udHJhY3QJAMwIAgkBC1N0cmluZ0VudHJ5AgIQQVBQUk9WRVJfQUREUkVTUwUPYXBwcm92ZXJBZGRyZXNzBQNuaWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQENaW5pdE5ld01hc3RlcgEGbWFzdGVyBAlhZGRyZXNzT0sEByRtYXRjaDAJAKYIAQUGbWFzdGVyAwkAAQIFByRtYXRjaDACB0FkZHJlc3MEAWEFByRtYXRjaDAGBwMJAQEhAQUJYWRkcmVzc09LCQACAQkArAICAhJpbmNvcnJlY3QgYWRkcmVzcyAFBm1hc3RlcgMJAQIhPQIIBQFpBmNhbGxlcgUEdGhpcwkAAgECHGF2YWlsYWJsZSBmb3Igc2VsZiBjYWxsIG9ubHkJAMwIAgkBC1N0cmluZ0VudHJ5AgIPdmVyaWZpZXJfbWFzdGVyBQZtYXN0ZXIFA25pbAFpARByZXF1ZXN0TmV3TWFzdGVyAQluZXdNYXN0ZXIECWFkZHJlc3NPSwQHJG1hdGNoMAkApggBBQluZXdNYXN0ZXIDCQABAgUHJG1hdGNoMAIHQWRkcmVzcwQBYQUHJG1hdGNoMAYHAwkBASEBBQlhZGRyZXNzT0sJAAIBCQCsAgICEmluY29ycmVjdCBhZGRyZXNzIAUJbmV3TWFzdGVyAwkAAAIJAM8IAgUJc2VudGluZWxzCAUBaQZjYWxsZXIFBHVuaXQJAAIBAg53aGl0ZWxpc3Qgb25seQkAzAgCCQELU3RyaW5nRW50cnkCAhJ2ZXJpZmllcl9uZXdNYXN0ZXIFCW5ld01hc3RlcgkAzAgCCQEMSW50ZWdlckVudHJ5AgIfdmVyaWZpZXJfbmV3TWFzdGVyRWxpZ2libGVBZnRlcgkAZAIFBmhlaWdodACQTgUDbmlsAWkBEWFjdGl2YXRlTmV3TWFzdGVyAAQOZWxpZ2libGVIZWlnaHQJARFAZXh0ck5hdGl2ZSgxMDUwKQIFBHRoaXMCH3ZlcmlmaWVyX25ld01hc3RlckVsaWdpYmxlQWZ0ZXIECW5ld01hc3RlcgkBEUBleHRyTmF0aXZlKDEwNTMpAgUEdGhpcwISdmVyaWZpZXJfbmV3TWFzdGVyAwkAAAIJAM8IAgUJc2VudGluZWxzCAUBaQZjYWxsZXIFBHVuaXQJAAIBAg53aGl0ZWxpc3Qgb25seQMJAGYCBQ5lbGlnaWJsZUhlaWdodAUGaGVpZ2h0CQACAQIibmV3IG1hc3RlciBjYW5ub3QgYmUgYWN0aXZhdGVkIHlldAkAzAgCCQELRGVsZXRlRW50cnkBAhJ2ZXJpZmllcl9uZXdNYXN0ZXIJAMwIAgkBC0RlbGV0ZUVudHJ5AQIfdmVyaWZpZXJfbmV3TWFzdGVyRWxpZ2libGVBZnRlcgkAzAgCCQELU3RyaW5nRW50cnkCAg92ZXJpZmllcl9tYXN0ZXIFCW5ld01hc3RlcgUDbmlsAQJ0eAEGdmVyaWZ5AAQLbXVsdGlzaWdTdHIJAQt2YWx1ZU9yRWxzZQIJAKIIAQIQQVBQUk9WRVJfQUREUkVTUwIABA9tdWx0aXNpZ0FkZHJlc3MJAKYIAQULbXVsdGlzaWdTdHIECm11bHRpc2lnT2sEByRtYXRjaDAFD211bHRpc2lnQWRkcmVzcwMJAAECBQckbWF0Y2gwAgdBZGRyZXNzBAF0BQckbWF0Y2gwBgcECGlzSW5pdGVkAwUKbXVsdGlzaWdPawkBC3ZhbHVlT3JFbHNlAgkAmwgCCQEFdmFsdWUBBQ9tdWx0aXNpZ0FkZHJlc3MCBklOSVRFRAcHBAloYXNBZG1pbnMDBQptdWx0aXNpZ09rCQECIT0CCQELdmFsdWVPckVsc2UCCQCdCAIJAQV2YWx1ZQEFD211bHRpc2lnQWRkcmVzcwILQURNSU5TX1BCS1MCAAIABwMDAwUKbXVsdGlzaWdPawUIaXNJbml0ZWQHBQloYXNBZG1pbnMHBAckbWF0Y2gwBQJ0eAMJAAECBQckbWF0Y2gwAhRTZXRTY3JpcHRUcmFuc2FjdGlvbgQDdHR4BQckbWF0Y2gwBAckbWF0Y2gxCAUDdHR4BnNjcmlwdAMJAAECBQckbWF0Y2gxAgpCeXRlVmVjdG9yBAZzY3JpcHQFByRtYXRjaDEEC3NjcmlwdEhhc2hhCQDYBAEJAPYDAQUGc2NyaXB0BAl2YWxpZEZyb20JARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAmggCCQEFdmFsdWUBBQ9tdWx0aXNpZ0FkZHJlc3MJAKwCAgkArAICCQCsAgIJAKwCAgIIc2NyaXB0JSUFDUNPTlRSQUNUX1RZUEUCAiUlBQtzY3JpcHRIYXNoYQILJSV2YWxpZEZyb20CEXZhbGlkRnJvbSBub3Qgc2V0BAd2YWxpZFRvCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAJoIAgkBBXZhbHVlAQUPbXVsdGlzaWdBZGRyZXNzCQCsAgIJAKwCAgkArAICCQCsAgICCHNjcmlwdCUlBQ1DT05UUkFDVF9UWVBFAgIlJQULc2NyaXB0SGFzaGECCSUldmFsaWRUbwIPdmFsaWRUbyBub3Qgc2V0AwkAZwIFBmhlaWdodAUJdmFsaWRGcm9tCQBnAgUHdmFsaWRUbwUGaGVpZ2h0BwcEA290eAUHJG1hdGNoMAQGdGFza0lkCQCsAgIJAKwCAgkArAICAgN0eF8JAKUIAQUEdGhpcwIBXwkA2AQBCAUDb3R4AmlkBAppc0FwcHJvdmVkCQELdmFsdWVPckVsc2UCCQCbCAIJAQV2YWx1ZQEFD211bHRpc2lnQWRkcmVzcwkArAICCQCsAgIJAKwCAgkApQgBBQR0aGlzAgFfCQDYBAEIBQNvdHgCaWQCCl9fYXBwcm92ZWQHBAxhcHByb3ZlZEZyb20JAQt2YWx1ZU9yRWxzZQIJAJoIAgkBBXZhbHVlAQUPbXVsdGlzaWdBZGRyZXNzCQCsAgIFBnRhc2tJZAIOX19hcHByb3ZlZEZyb20AAAMFCmlzQXBwcm92ZWQJAGcCBQZoZWlnaHQFDGFwcHJvdmVkRnJvbQcEDW1hc3RlckFkZHJlc3MJAKIIAQIPdmVyaWZpZXJfbWFzdGVyBBBhcHByb3ZlZEJ5TWFzdGVyBAckbWF0Y2gwBQ1tYXN0ZXJBZGRyZXNzAwkAAQIFByRtYXRjaDACBlN0cmluZwQBeAUHJG1hdGNoMAQHJG1hdGNoMQkAmggCCQERQGV4dHJOYXRpdmUoMTA2MikBBQF4CQCsAgICC2FwcHJvdmVkVHhfCQDYBAEIBQJ0eAJpZAMJAAECBQckbWF0Y2gxAgNJbnQEAXkFByRtYXRjaDEFAXkAAAABAwkA9AMDCAUCdHgJYm9keUJ5dGVzCQCRAwIIBQJ0eAZwcm9vZnMAAAgFAnR4D3NlbmRlclB1YmxpY0tleQkAZgIFEGFwcHJvdmVkQnlNYXN0ZXIAAAefOaqB", "height": 355484, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: none Next: none Full:
OldNewDifferences
1-# no script
1+{-# STDLIB_VERSION 6 #-}
2+{-# SCRIPT_TYPE ACCOUNT #-}
3+{-# CONTENT_TYPE DAPP #-}
4+let CONTRACT_TYPE = "LEND-LP-MARKET"
5+
6+let VERSION = "PLP-1.1.1"
7+
8+func getAddressFromState (key) = valueOrElse(addressFromString(valueOrElse(getString(this, ("setup_address_" + key)), "3PEwRcYNAUtoFvKpBhKoiwajnZfdoDR6h4h")), Address(base58'3PEwRcYNAUtoFvKpBhKoiwajnZfdoDR6h4h'))
9+
10+
11+func getAddressesFromState (key) = {
12+ func f (accum,next) = (accum ++ [valueOrElse(addressFromString(next), Address(base58'3PEwRcYNAUtoFvKpBhKoiwajnZfdoDR6h4h'))])
13+
14+ let $l = split_4C(valueOrElse(getString(this, ("setup_address_" + key)), "3PEwRcYNAUtoFvKpBhKoiwajnZfdoDR6h4h"), ",")
15+ let $s = size($l)
16+ let $acc0 = nil
17+ func $f0_1 ($a,$i) = if (($i >= $s))
18+ then $a
19+ else f($a, $l[$i])
20+
21+ func $f0_2 ($a,$i) = if (($i >= $s))
22+ then $a
23+ else throw("List size exceeds 15")
24+
25+ $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($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10), 11), 12), 13), 14), 15)
26+ }
27+
28+
29+let reserveFundAddress = getAddressFromState("reserveFund")
30+
31+let oracleAddress = getAddressFromState("oracle")
32+
33+let aggregatorAddress = getAddressFromState("aggregator")
34+
35+let adminAddress = getAddressFromState("admin")
36+
37+let stableFundAddress = getAddressFromState("stableFund")
38+
39+let shutdownWhitelist = getAddressesFromState("shutdownCallers")
40+
41+let liquidatorsWhitelist = getAddressesFromState("liquidators")
42+
43+func verifyLiquidatorRights (address) = (indexOf(liquidatorsWhitelist, address) != unit)
44+
45+
46+let reserveFund = valueOrElse(getInteger(this, "setup_reserveFundFee"), 20)
47+
48+let stablesIdStr = split(valueOrElse(getString(this, "setup_stablesIds"), "9wc3LXNA4TEBsXyKtoLE9mrbDD7WMHXvXrCjZvabLAsi,HGgabTqUS8WtVFUJzfmrTDMgEccJuZLBPhFgQFxvnsoW"), ",")
49+
50+func getRateCurve (assetIdStr) = {
51+ let curveRateStrLi = split(valueOrElse(getString(this, ("setup_rateCurve_" + assetIdStr)), "20000000,100000000,60000000,400000000"), ",")
52+ $Tuple4(parseIntValue(curveRateStrLi[0]), parseIntValue(curveRateStrLi[1]), parseIntValue(curveRateStrLi[2]), parseIntValue(curveRateStrLi[3]))
53+ }
54+
55+
56+func getRewardsSplitting (assetIdStr) = {
57+ let rewardsSplittingStrLi = split(valueOrElse(getString(this, ("setup_rewardsSplitting_" + assetIdStr)), "30,50,20"), ",")
58+ $Tuple3(parseIntValue(rewardsSplittingStrLi[0]), parseIntValue(rewardsSplittingStrLi[1]), parseIntValue(rewardsSplittingStrLi[2]))
59+ }
60+
61+
62+let sentinels = [Address(base58'3PMcMiMEs6w56NRGacksXtFG5zS7doE9fpL'), Address(base58'3PQdNxynJy5mche2kxMVc5shXWzK8Gstq3o'), Address(base58'3P8auNWJkxxByyJtwErFXaxiXcGM45qQ1hA'), Address(base58'3P8qVX189qpoTJZQQQdKS9endHK5sxWsvrd')]
63+
64+let Scale8 = 100000000
65+
66+let Scale10 = 10000000000
67+
68+let Scale16 = (Scale8 * Scale8)
69+
70+let dayBlocks = 1440
71+
72+let withdrawalLimitBlocks = valueOrElse(getInteger(this, "setup_withdrawalLimitBlocks"), 100)
73+
74+func liIntToStr (li) = {
75+ func f (accum,next) = ((accum + toString(next)) + ",")
76+
77+ let $l = li
78+ let $s = size($l)
79+ let $acc0 = ""
80+ func $f0_1 ($a,$i) = if (($i >= $s))
81+ then $a
82+ else f($a, $l[$i])
83+
84+ func $f0_2 ($a,$i) = if (($i >= $s))
85+ then $a
86+ else throw("List size exceeds 12")
87+
88+ $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)
89+ }
90+
91+
92+func tryGetInteger (key) = match getInteger(this, key) {
93+ case b: Int =>
94+ b
95+ case _ =>
96+ 0
97+}
98+
99+
100+func tryGetBoolean (key) = match getBoolean(this, key) {
101+ case b: Boolean =>
102+ b
103+ case _ =>
104+ false
105+}
106+
107+
108+func tryGetString (key) = match getString(this, key) {
109+ case b: String =>
110+ b
111+ case _ =>
112+ ""
113+}
114+
115+
116+func tryGetBinary (key) = match getBinary(this, key) {
117+ case b: ByteVector =>
118+ b
119+ case _ =>
120+ base58''
121+}
122+
123+
124+func getAssetString (assetId) = match assetId {
125+ case b: ByteVector =>
126+ toBase58String(b)
127+ case _ =>
128+ "WAVES"
129+}
130+
131+
132+func getAssetBytes (assetIdStr) = if ((assetIdStr == "WAVES"))
133+ then unit
134+ else fromBase58String(assetIdStr)
135+
136+
137+func getBalance (assetIdStr) = if ((assetIdStr == "WAVES"))
138+ then wavesBalance(this).available
139+ else assetBalance(this, fromBase58String(assetIdStr))
140+
141+
142+func getMarketAssets () = split(tryGetString("setup_tokens"), ",")
143+
144+
145+func getOutdatedUr (assetIdStr) = {
146+ let down = fraction(tryGetInteger(("total_supplied_" + assetIdStr)), tryGetInteger((assetIdStr + "_sRate")), Scale16)
147+ if ((down == 0))
148+ then 0
149+ else fraction(Scale8, fraction(tryGetInteger(("total_borrowed_" + assetIdStr)), tryGetInteger((assetIdStr + "_bRate")), Scale16), down)
150+ }
151+
152+
153+func getInterest (assetIdStr) = {
154+ let ur = getOutdatedUr(assetIdStr)
155+ let curve = getRateCurve(assetIdStr)
156+ let rate = (curve._1 + (if ((curve._3 >= ur))
157+ then fraction(ur, curve._2, curve._3)
158+ else (curve._2 + fraction((ur - curve._3), curve._4, (100000000 - curve._3)))))
159+ max([fraction(rate, Scale8, (dayBlocks * 365)), 1])
160+ }
161+
162+
163+func tokenRatesRecalc (assetIdStr) = {
164+ let interest = getInterest(assetIdStr)
165+ let ur = getOutdatedUr(assetIdStr)
166+ let lastRecalcHeight = tryGetInteger("lastRateHeight")
167+ let lastBRate = max([tryGetInteger((assetIdStr + "_bRate")), Scale16])
168+ let newBRate = (lastBRate + ((height - lastRecalcHeight) * interest))
169+ let lastSRate = max([tryGetInteger((assetIdStr + "_sRate")), Scale16])
170+ let newSRate = (lastSRate + ((((height - lastRecalcHeight) * fraction(interest, ur, Scale8)) * (100 - reserveFund)) / 100))
171+[IntegerEntry((assetIdStr + "_sRate"), newSRate), IntegerEntry((assetIdStr + "_bRate"), newBRate), IntegerEntry("lastRateHeight", height)]
172+ }
173+
174+
175+func getActualRate (assetIdStr,rateType) = {
176+ func f (accum,token) = {
177+ let recalc = tokenRatesRecalc(token)
178+ $Tuple2(if ((token != assetIdStr))
179+ then accum._1
180+ else if ((rateType == "sRate"))
181+ then recalc[0].value
182+ else recalc[1].value, (accum._2 ++ recalc))
183+ }
184+
185+ let $l = getMarketAssets()
186+ let $s = size($l)
187+ let $acc0 = $Tuple2(0, nil)
188+ func $f0_1 ($a,$i) = if (($i >= $s))
189+ then $a
190+ else f($a, $l[$i])
191+
192+ func $f0_2 ($a,$i) = if (($i >= $s))
193+ then $a
194+ else throw("List size exceeds 12")
195+
196+ $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)
197+ }
198+
199+
200+func getUr (assetIdStr) = {
201+ let rates = tokenRatesRecalc(assetIdStr)
202+ let down = fraction(tryGetInteger(("total_supplied_" + assetIdStr)), rates[0].value, Scale16)
203+ fraction(Scale8, fraction(tryGetInteger(("total_borrowed_" + assetIdStr)), rates[1].value, Scale16), down)
204+ }
205+
206+
207+func ratesRecalc () = {
208+ func f (accum,token) = (accum ++ tokenRatesRecalc(token))
209+
210+ let $l = getMarketAssets()
211+ let $s = size($l)
212+ let $acc0 = nil
213+ func $f0_1 ($a,$i) = if (($i >= $s))
214+ then $a
215+ else f($a, $l[$i])
216+
217+ func $f0_2 ($a,$i) = if (($i >= $s))
218+ then $a
219+ else throw("List size exceeds 12")
220+
221+ $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)
222+ }
223+
224+
225+func getTokenPriceWithRisk (assetIdStr,riskAversity) = if ((indexOf(stablesIdStr, assetIdStr) != unit))
226+ then $Tuple2(1000000, 1000000)
227+ else {
228+ let price = getIntegerValue(oracleAddress, (assetIdStr + "_twap5B"))
229+ let riskLevel = getIntegerValue(oracleAddress, (assetIdStr + "_riskLevel"))
230+ if ((riskAversity >= riskLevel))
231+ then $Tuple2(price, price)
232+ else throw((("oracle prices don't match: " + toString(price)) + " is the price, but risk is too high"))
233+ }
234+
235+
236+func getTokenPrice (assetIdStr) = getTokenPriceWithRisk(assetIdStr, 3)
237+
238+
239+func getTokenPriceCapped (assetIdStr) = {
240+ let $t078567919 = getTokenPriceWithRisk(assetIdStr, 3)
241+ let minPrice = $t078567919._1
242+ let maxPrice = $t078567919._2
243+ let maxAllowedPrice = valueOrElse(getInteger(this, ("setup_maxPrice_" + assetIdStr)), -1)
244+ let minAllowedPrice = valueOrElse(getInteger(this, ("setup_minPrice_" + assetIdStr)), -1)
245+ if (if ((maxAllowedPrice != -1))
246+ then (maxPrice > maxAllowedPrice)
247+ else false)
248+ then $Tuple2(maxAllowedPrice, maxAllowedPrice)
249+ else if (if ((minAllowedPrice != -1))
250+ then (minAllowedPrice > minPrice)
251+ else false)
252+ then $Tuple2(minAllowedPrice, minAllowedPrice)
253+ else $Tuple2(minPrice, maxPrice)
254+ }
255+
256+
257+func calcAssetScale (assetIdStr) = {
258+ let decimals = if ((assetIdStr == "WAVES"))
259+ then 8
260+ else value(assetInfo(fromBase58String(assetIdStr))).decimals
261+ pow(10, 0, decimals, 0, 0, DOWN)
262+ }
263+
264+
265+func calcUserCollateral (address) = {
266+ let userCollateralInvoke = invoke(this, "getUserCollateral", [false, address, true, ""], nil)
267+ if ((userCollateralInvoke == userCollateralInvoke))
268+ then {
269+ let userCollateralValue = match userCollateralInvoke {
270+ case x: Int =>
271+ x
272+ case _ =>
273+ throw("issue while doing in-dapp invocation")
274+ }
275+ if ((userCollateralValue == userCollateralValue))
276+ then userCollateralValue
277+ else throw("Strict value is not equal to itself.")
278+ }
279+ else throw("Strict value is not equal to itself.")
280+ }
281+
282+
283+func checkWithdrawalLimit (address,assetIdStr,amountInternal,sRate) = {
284+ let withdrawalLimit = valueOrElse(getInteger(this, (("setup_" + assetIdStr) + "_maxWithdrawPer100B")), -1)
285+ if ((withdrawalLimit == -1))
286+ then nil
287+ else {
288+ let totalSupplied = tryGetInteger(("total_supplied_" + assetIdStr))
289+ let limitCap = fraction(totalSupplied, withdrawalLimit, 100)
290+ let lastH = tryGetInteger(((address + "_withdrawLimitHeight_") + assetIdStr))
291+ let elapsed = (height - lastH)
292+ let windowExpired = (elapsed > withdrawalLimitBlocks)
293+ let currentUsed = if (windowExpired)
294+ then 0
295+ else tryGetInteger(((address + "_withdrawLimitUsed_") + assetIdStr))
296+ let blocksToReset = if (windowExpired)
297+ then withdrawalLimitBlocks
298+ else (withdrawalLimitBlocks - elapsed)
299+ let available = (limitCap - currentUsed)
300+ let availableScaled = fraction(available, sRate, Scale16, CEILING)
301+ if ((amountInternal > available))
302+ then throw(((((("withdrawal limit exceeded for " + assetIdStr) + ", available: ") + toString(availableScaled)) + ", blocks to reset: ") + toString(blocksToReset)))
303+ else ((if (windowExpired)
304+ then [IntegerEntry(((address + "_withdrawLimitHeight_") + assetIdStr), height)]
305+ else nil) ++ [IntegerEntry(((address + "_withdrawLimitUsed_") + assetIdStr), (currentUsed + amountInternal))])
306+ }
307+ }
308+
309+
310+func checkBorrowLimit (address,assetIdStr,amountInternal,bRate) = {
311+ let borrowLimit = valueOrElse(getInteger(this, (("setup_" + assetIdStr) + "_maxBorrowPer100B")), -1)
312+ if ((borrowLimit == -1))
313+ then nil
314+ else {
315+ let totalSupplied = tryGetInteger(("total_supplied_" + assetIdStr))
316+ let limitCap = fraction(totalSupplied, borrowLimit, 100)
317+ let lastH = tryGetInteger(((address + "_borrowLimitHeight_") + assetIdStr))
318+ let elapsed = (height - lastH)
319+ let windowExpired = (elapsed > withdrawalLimitBlocks)
320+ let currentUsed = if (windowExpired)
321+ then 0
322+ else tryGetInteger(((address + "_borrowLimitUsed_") + assetIdStr))
323+ let blocksToReset = if (windowExpired)
324+ then withdrawalLimitBlocks
325+ else (withdrawalLimitBlocks - elapsed)
326+ let available = (limitCap - currentUsed)
327+ let availableScaled = fraction(available, bRate, Scale16, CEILING)
328+ if ((amountInternal > available))
329+ then throw(((((("borrow limit exceeded for " + assetIdStr) + ", available: ") + toString(availableScaled)) + ", blocks to reset: ") + toString(blocksToReset)))
330+ else ((if (windowExpired)
331+ then [IntegerEntry(((address + "_borrowLimitHeight_") + assetIdStr), height)]
332+ else nil) ++ [IntegerEntry(((address + "_borrowLimitUsed_") + assetIdStr), (currentUsed + amountInternal))])
333+ }
334+ }
335+
336+
337+@Callable(i)
338+func supply () = if (!(tryGetBoolean("setup_active")))
339+ then throw("market is stopped")
340+ else if (if ((size(i.payments) != 1))
341+ then true
342+ else (i.payments[0].amount == 0))
343+ then throw("1 payment has to be attached")
344+ else {
345+ let assetIdStr = getAssetString(i.payments[0].assetId)
346+ let assetAmount = i.payments[0].amount
347+ let $t01182311890 = getActualRate(assetIdStr, "sRate")
348+ let sRate = $t01182311890._1
349+ let ratesRecalcResult = $t01182311890._2
350+ let amount = fraction(assetAmount, Scale16, sRate, DOWN)
351+ let address = toString(i.caller)
352+ let maxSupply = match getString(("setup_maxSupply_" + assetIdStr)) {
353+ case x: String =>
354+ parseIntValue(x)
355+ case _ =>
356+ tryGetInteger(("setup_maxSupply_" + assetIdStr))
357+ }
358+ let assetPrice = getTokenPriceCapped(assetIdStr)
359+ let newAddressSupplied = (tryGetInteger(((address + "_supplied_") + assetIdStr)) + amount)
360+ let newTotalSupplied = (tryGetInteger(("total_supplied_" + assetIdStr)) + amount)
361+ let rate = getActualRate(assetIdStr, "sRate")._1
362+ let assetScale = calcAssetScale(assetIdStr)
363+ let newTotalSuppliedUsd = fraction(fraction(newTotalSupplied, rate, Scale16), assetPrice._1, assetScale)
364+ if ((indexOf(tryGetString("setup_tokens"), assetIdStr) == unit))
365+ then throw("this asset is not supported by the market")
366+ else if (if ((maxSupply != 0))
367+ then (newTotalSuppliedUsd > maxSupply)
368+ else false)
369+ then throw("max total supply for this token reached in the pool")
370+ else if ((tryGetInteger(("setup_paused_" + assetIdStr)) > 0))
371+ then throw("this asset can't be supplied or borrowed")
372+ else {
373+ let inv = if ((tryGetString(("setup_autostake_" + assetIdStr)) != ""))
374+ then invoke(this, "stakeToken", [assetIdStr, assetAmount], nil)
375+ else unit
376+ if ((inv == inv))
377+ then ([IntegerEntry(((address + "_supplied_") + assetIdStr), newAddressSupplied), IntegerEntry(("total_supplied_" + assetIdStr), newTotalSupplied)] ++ ratesRecalcResult)
378+ else throw("Strict value is not equal to itself.")
379+ }
380+ }
381+
382+
383+
384+@Callable(i)
385+func withdraw (assetIdStr,assetAmount) = {
386+ let $t01345713524 = getActualRate(assetIdStr, "sRate")
387+ let sRate = $t01345713524._1
388+ let ratesRecalcResult = $t01345713524._2
389+ let amount = fraction(assetAmount, Scale16, sRate, CEILING)
390+ let address = toString(i.caller)
391+ let assetSupplied = tryGetInteger(("total_supplied_" + assetIdStr))
392+ let assetBorrowed = tryGetInteger(("total_borrowed_" + assetIdStr))
393+ let userAssetSupplied = tryGetInteger(((address + "_supplied_") + assetIdStr))
394+ let userAssetBorrowed = tryGetInteger(((address + "_borrowed_") + assetIdStr))
395+ let collateralValueInv = invoke(this, "getUserCollateral", [false, address, true, ((assetIdStr + ",supplied,") + toString(-(amount)))], nil)
396+ if ((collateralValueInv == collateralValueInv))
397+ then {
398+ let collateralValue = match collateralValueInv {
399+ case x: Int =>
400+ x
401+ case _ =>
402+ throw("can't get user collateral value")
403+ }
404+ if (!(tryGetBoolean("setup_active")))
405+ then throw("market is stopped")
406+ else if ((0 > collateralValue))
407+ then throw("you dont have enough collateral for this operation")
408+ else if ((amount > (assetSupplied - assetBorrowed)))
409+ then throw("this amount is not available on the market")
410+ else if ((amount > (userAssetSupplied - userAssetBorrowed)))
411+ then throw("this amount is not available for this user")
412+ else {
413+ let inv = if ((tryGetString(("setup_autostake_" + assetIdStr)) != ""))
414+ then invoke(this, "unstakeToken", [assetIdStr, assetAmount], nil)
415+ else unit
416+ if ((inv == inv))
417+ then {
418+ let limitCheckActions = checkWithdrawalLimit(address, assetIdStr, amount, sRate)
419+ if ((limitCheckActions == limitCheckActions))
420+ then (([IntegerEntry(((address + "_supplied_") + assetIdStr), (tryGetInteger(((address + "_supplied_") + assetIdStr)) - amount)), IntegerEntry(("total_supplied_" + assetIdStr), (tryGetInteger(("total_supplied_" + assetIdStr)) - amount)), ScriptTransfer(i.caller, assetAmount, getAssetBytes(assetIdStr))] ++ ratesRecalcResult) ++ limitCheckActions)
421+ else throw("Strict value is not equal to itself.")
422+ }
423+ else throw("Strict value is not equal to itself.")
424+ }
425+ }
426+ else throw("Strict value is not equal to itself.")
427+ }
428+
429+
430+
431+@Callable(i)
432+func borrow (assetIdStr,assetAmount) = {
433+ let address = toString(i.caller)
434+ let $t01528815355 = getActualRate(assetIdStr, "bRate")
435+ let bRate = $t01528815355._1
436+ let ratesRecalcResult = $t01528815355._2
437+ let amount = fraction(assetAmount, Scale16, bRate, CEILING)
438+ let collateralValueInv = invoke(this, "getUserCollateral", [false, address, true, ((assetIdStr + ",borrowed,") + toString(amount))], nil)
439+ if ((collateralValueInv == collateralValueInv))
440+ then {
441+ let collateralValue = match collateralValueInv {
442+ case x: Int =>
443+ x
444+ case _ =>
445+ throw("can't get user collateral value")
446+ }
447+ if (!(tryGetBoolean("setup_active")))
448+ then throw("market is stopped")
449+ else if ((0 > collateralValue))
450+ then throw("you have to supply more to borrow")
451+ else if ((tryGetInteger(("setup_borrowEnabled_" + assetIdStr)) == 0))
452+ then throw("this asset can't be borrowed")
453+ else if ((tryGetInteger(("setup_paused_" + assetIdStr)) > 0))
454+ then throw("this asset can't be supplied or borrowed")
455+ else {
456+ let assetSupplied = tryGetInteger(("total_supplied_" + assetIdStr))
457+ let assetBorrowed = tryGetInteger(("total_borrowed_" + assetIdStr))
458+ let userAssetBorrowed = tryGetInteger(((address + "_borrowed_") + assetIdStr))
459+ if ((amount > (assetSupplied - assetBorrowed)))
460+ then throw("this amount is not available")
461+ else {
462+ let inv = if ((tryGetString(("setup_autostake_" + assetIdStr)) != ""))
463+ then invoke(this, "unstakeToken", [assetIdStr, assetAmount], nil)
464+ else unit
465+ if ((inv == inv))
466+ then {
467+ let limitCheckActions = checkBorrowLimit(address, assetIdStr, amount, bRate)
468+ if ((limitCheckActions == limitCheckActions))
469+ then (([IntegerEntry(((address + "_borrowed_") + assetIdStr), (userAssetBorrowed + amount)), IntegerEntry(("total_borrowed_" + assetIdStr), (assetBorrowed + amount)), ScriptTransfer(i.caller, assetAmount, getAssetBytes(assetIdStr))] ++ ratesRecalcResult) ++ limitCheckActions)
470+ else throw("Strict value is not equal to itself.")
471+ }
472+ else throw("Strict value is not equal to itself.")
473+ }
474+ }
475+ }
476+ else throw("Strict value is not equal to itself.")
477+ }
478+
479+
480+
481+@Callable(i)
482+func repay () = if (!(tryGetBoolean("setup_active")))
483+ then throw("market is stopped")
484+ else if (if ((size(i.payments) != 1))
485+ then true
486+ else (i.payments[0].amount == 0))
487+ then throw("1 payment has to be attached")
488+ else {
489+ let assetIdStr = getAssetString(i.payments[0].assetId)
490+ let assetAmount = i.payments[0].amount
491+ let $t01734917416 = getActualRate(assetIdStr, "bRate")
492+ let bRate = $t01734917416._1
493+ let ratesRecalcResult = $t01734917416._2
494+ let amount = fraction(assetAmount, Scale16, bRate, CEILING)
495+ let address = toString(i.caller)
496+ let assetSupplied = tryGetInteger(("total_supplied_" + assetIdStr))
497+ let assetBorrowed = tryGetInteger(("total_borrowed_" + assetIdStr))
498+ let userAssetBorrowed = tryGetInteger(((address + "_borrowed_") + assetIdStr))
499+ let amountLeft = (userAssetBorrowed - amount)
500+ let repayAmount = if ((amountLeft >= 0))
501+ then amount
502+ else userAssetBorrowed
503+ if ((indexOf(tryGetString("setup_tokens"), assetIdStr) == unit))
504+ then throw("this asset is not supported by the market")
505+ else {
506+ let inv = if ((tryGetString(("setup_autostake_" + assetIdStr)) != ""))
507+ then invoke(this, "stakeToken", [assetIdStr, assetAmount], nil)
508+ else unit
509+ if ((inv == inv))
510+ then {
511+ let excessTokens = (assetAmount - fraction(repayAmount, bRate, Scale16))
512+ (([IntegerEntry(((address + "_borrowed_") + assetIdStr), (userAssetBorrowed - repayAmount)), IntegerEntry(("total_borrowed_" + assetIdStr), (assetBorrowed - repayAmount))] ++ ratesRecalcResult) ++ (if ((amountLeft >= 0))
513+ then nil
514+ else [ScriptTransfer(i.caller, excessTokens, i.payments[0].assetId)]))
515+ }
516+ else throw("Strict value is not equal to itself.")
517+ }
518+ }
519+
520+
521+
522+@Callable(i)
523+func repayFor (address) = if (!(tryGetBoolean("setup_active")))
524+ then throw("market is stopped")
525+ else if ((i.caller != reserveFundAddress))
526+ then throw("available only for reserve fund address")
527+ else if ((address == "global"))
528+ then throw("you can't repay for everyone :_)")
529+ else if (if ((size(i.payments) != 1))
530+ then true
531+ else (i.payments[0].amount == 0))
532+ then throw("1 payment has to be attached")
533+ else {
534+ let assetIdStr = getAssetString(i.payments[0].assetId)
535+ let assetAmount = i.payments[0].amount
536+ let $t01909219159 = getActualRate(assetIdStr, "bRate")
537+ let bRate = $t01909219159._1
538+ let ratesRecalcResult = $t01909219159._2
539+ let amount = fraction(assetAmount, Scale16, bRate, CEILING)
540+ let assetSupplied = tryGetInteger(("total_supplied_" + assetIdStr))
541+ let assetBorrowed = tryGetInteger(("total_borrowed_" + assetIdStr))
542+ let userAssetBorrowed = tryGetInteger(((address + "_borrowed_") + assetIdStr))
543+ let amountLeft = (userAssetBorrowed - amount)
544+ let repayAmount = if ((amountLeft >= 0))
545+ then amount
546+ else userAssetBorrowed
547+ if ((indexOf(tryGetString("setup_tokens"), assetIdStr) == unit))
548+ then throw("this asset is not supported by the market")
549+ else {
550+ let inv = if ((tryGetString(("setup_autostake_" + assetIdStr)) != ""))
551+ then invoke(this, "stakeToken", [assetIdStr, assetAmount], nil)
552+ else unit
553+ if ((inv == inv))
554+ then {
555+ let excessTokens = (assetAmount - fraction(repayAmount, bRate, Scale16))
556+ (([IntegerEntry(((address + "_borrowed_") + assetIdStr), (userAssetBorrowed - repayAmount)), IntegerEntry(("total_borrowed_" + assetIdStr), (assetBorrowed - repayAmount))] ++ ratesRecalcResult) ++ (if ((amountLeft >= 0))
557+ then nil
558+ else [ScriptTransfer(i.caller, excessTokens, i.payments[0].assetId)]))
559+ }
560+ else throw("Strict value is not equal to itself.")
561+ }
562+ }
563+
564+
565+
566+@Callable(i)
567+func stakeToken (assetIdStr,amount) = {
568+ let autostakeAddress = valueOrElse(addressFromString(tryGetString(("setup_autostake_" + assetIdStr))), Address(base58'3PDDRRS5gKyDQRpJskzWTdxREHGu1FNpdwg'))
569+ let stakerSupportedAssets = getStringValue(autostakeAddress, "setup_supportedAssets")
570+ if ((i.caller != this))
571+ then throw("only for internal smart contract invocations")
572+ else if ((indexOf(stakerSupportedAssets, assetIdStr) == unit))
573+ then nil
574+ else {
575+ let amountStaked = tryGetInteger(("autostake_amount_" + assetIdStr))
576+ let stakeInv = reentrantInvoke(autostakeAddress, "stakeLP", nil, [AttachedPayment(getAssetBytes(assetIdStr), amount)])
577+ if ((stakeInv == stakeInv))
578+ then [IntegerEntry(("autostake_amount_" + assetIdStr), (amountStaked + amount))]
579+ else throw("Strict value is not equal to itself.")
580+ }
581+ }
582+
583+
584+
585+@Callable(i)
586+func stakeTokenAll (assetIdStr) = if ((i.caller != this))
587+ then throw("only for internal smart contract invocations")
588+ else {
589+ let amount = getBalance(assetIdStr)
590+ let inv = reentrantInvoke(this, "stakeToken", [assetIdStr, amount], nil)
591+ if ((inv == inv))
592+ then nil
593+ else throw("Strict value is not equal to itself.")
594+ }
595+
596+
597+
598+@Callable(i)
599+func unstakeToken (assetIdStr,amount) = {
600+ let autostakeAddress = valueOrElse(addressFromString(tryGetString(("setup_autostake_" + assetIdStr))), Address(base58'3PDDRRS5gKyDQRpJskzWTdxREHGu1FNpdwg'))
601+ let stakerSupportedAssets = getStringValue(autostakeAddress, "setup_supportedAssets")
602+ if ((i.caller != this))
603+ then throw("only for internal smart contract invocations")
604+ else if ((indexOf(stakerSupportedAssets, assetIdStr) == unit))
605+ then nil
606+ else {
607+ let amountStaked = tryGetInteger(("autostake_amount_" + assetIdStr))
608+ let stakeInv = reentrantInvoke(autostakeAddress, "unstakeLP", [assetIdStr, amount], nil)
609+ if ((stakeInv == stakeInv))
610+ then [IntegerEntry(("autostake_amount_" + assetIdStr), (amountStaked - amount))]
611+ else throw("Strict value is not equal to itself.")
612+ }
613+ }
614+
615+
616+
617+@Callable(i)
618+func addInterest (assetIdStr,amount) = if ((i.caller != this))
619+ then throw("only for self invocation")
620+ else {
621+ let earned = tryGetInteger(("autostake_lastEarned_" + assetIdStr))
622+ let lastHeight = tryGetInteger(("autostake_lastBlock_" + assetIdStr))
623+ let cleanAmount = fraction(amount, 80, 100)
624+ let stateChanges = if (if ((lastHeight == height))
625+ then true
626+ else (amount == 0))
627+ then nil
628+ else [IntegerEntry(("autostake_preLastEarned_" + assetIdStr), earned), IntegerEntry(("autostake_preLastBlock_" + assetIdStr), lastHeight), IntegerEntry(("autostake_lastEarned_" + assetIdStr), (earned + cleanAmount)), IntegerEntry(("autostake_lastBlock_" + assetIdStr), height)]
629+ (stateChanges ++ [IntegerEntry((assetIdStr + "_sRate"), (tryGetInteger((assetIdStr + "_sRate")) + fraction(Scale16, cleanAmount, tryGetInteger(("total_supplied_" + assetIdStr)))))])
630+ }
631+
632+
633+
634+@Callable(i)
635+func addInterestEXTERNAL () = {
636+ let assetId = i.payments[0].assetId
637+ let assetIdStr = getAssetString(assetId)
638+ let splitting = getRewardsSplitting(assetIdStr)
639+ let amount = fraction(i.payments[0].amount, splitting._2, 100)
640+ let earned = tryGetInteger(("autostake_lastEarned_" + assetIdStr))
641+ let lastHeight = tryGetInteger(("autostake_lastBlock_" + assetIdStr))
642+ let stateChanges = if (if ((lastHeight == height))
643+ then true
644+ else (amount == 0))
645+ then nil
646+ else [IntegerEntry(("autostake_preLastEarned_" + assetIdStr), earned), IntegerEntry(("autostake_preLastBlock_" + assetIdStr), lastHeight), IntegerEntry(("autostake_lastEarned_" + assetIdStr), (earned + amount)), IntegerEntry(("autostake_lastBlock_" + assetIdStr), height)]
647+ (stateChanges ++ [IntegerEntry((assetIdStr + "_sRate"), (tryGetInteger((assetIdStr + "_sRate")) + fraction(Scale16, amount, tryGetInteger(("total_supplied_" + assetIdStr))))), ScriptTransfer(stableFundAddress, fraction(i.payments[0].amount, splitting._1, 100), assetId)])
648+ }
649+
650+
651+
652+@Callable(i)
653+func preInit (tokens,ltvs,lts,penalties) = {
654+ func f (accum,token) = (accum ++ [IntegerEntry((token + "_bRate"), Scale16), IntegerEntry((token + "_sRate"), Scale16)])
655+
656+ if ((i.caller != this))
657+ then throw("admin only")
658+ else {
659+ let rates = {
660+ let $l = split(tokens, ",")
661+ let $s = size($l)
662+ let $acc0 = nil
663+ func $f0_1 ($a,$i) = if (($i >= $s))
664+ then $a
665+ else f($a, $l[$i])
666+
667+ func $f0_2 ($a,$i) = if (($i >= $s))
668+ then $a
669+ else throw("List size exceeds 12")
670+
671+ $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)
672+ }
673+ ([StringEntry("setup_tokens", tokens), StringEntry("setup_ltvs", ltvs), StringEntry("setup_lts", lts), StringEntry("setup_penalties", penalties), BooleanEntry("setup_active", true)] ++ rates)
674+ }
675+ }
676+
677+
678+
679+@Callable(i)
680+func initNewToken (token,ltv,lt,penalty) = if ((i.caller != this))
681+ then throw("admin only")
682+ else [StringEntry("setup_tokens", ((tryGetString("setup_tokens") + ",") + token)), StringEntry("setup_ltvs", ((tryGetString("setup_ltvs") + ",") + ltv)), StringEntry("setup_lts", ((tryGetString("setup_lts") + ",") + lt)), StringEntry("setup_penalties", ((tryGetString("setup_penalties") + ",") + penalty)), IntegerEntry((token + "_bRate"), Scale16), IntegerEntry((token + "_sRate"), Scale16)]
683+
684+
685+
686+@Callable(i)
687+func updateParameter (key,val) = if (if ((i.caller != this))
688+ then (i.caller != adminAddress)
689+ else false)
690+ then throw("admin only")
691+ else [IntegerEntry(key, parseIntValue(val))]
692+
693+
694+
695+@Callable(i)
696+func updateString (key,val) = if (if ((i.caller != this))
697+ then (i.caller != adminAddress)
698+ else false)
699+ then throw("admin only")
700+ else [StringEntry(key, val)]
701+
702+
703+
704+@Callable(i)
705+func claimToReserveFund (debug) = {
706+ let assets = getMarketAssets()
707+ let rates = getActualRate(assets[0], "sRate")._2
708+ let li = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
709+ func f (accum,n) = if ((n >= size(assets)))
710+ then accum
711+ else {
712+ let assetIdStr = assets[n]
713+ let autostakeAmount = tryGetString(("autostake_amount_" + assetIdStr))
714+ let amount = ((((getBalance(assetIdStr) + tryGetInteger(("autostake_amount_" + assetIdStr))) + (if ((autostakeAmount != ""))
715+ then parseIntValue(autostakeAmount)
716+ else 0)) + fraction(tryGetInteger(("total_borrowed_" + assetIdStr)), rates[((n * 3) + 1)].value, Scale16)) - fraction(tryGetInteger(("total_supplied_" + assetIdStr)), rates[(n * 3)].value, Scale16))
717+ let inv = if ((tryGetString(("setup_autostake_" + assetIdStr)) != ""))
718+ then invoke(this, "unstakeToken", [assetIdStr, amount], nil)
719+ else unit
720+ if ((inv == inv))
721+ then (accum ++ [amount])
722+ else throw("Strict value is not equal to itself.")
723+ }
724+
725+ let parameter = {
726+ let $l = li
727+ let $s = size($l)
728+ let $acc0 = nil
729+ func $f0_1 ($a,$i) = if (($i >= $s))
730+ then $a
731+ else f($a, $l[$i])
732+
733+ func $f0_2 ($a,$i) = if (($i >= $s))
734+ then $a
735+ else throw("List size exceeds 12")
736+
737+ $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)
738+ }
739+ func f2 (accum,n) = if ((n >= size(assets)))
740+ then accum
741+ else {
742+ let assetIdStr = assets[n]
743+ (accum ++ [ScriptTransfer(reserveFundAddress, max([parameter[n], 0]), getAssetBytes(assetIdStr))])
744+ }
745+
746+ if (debug)
747+ then throw(liIntToStr(parameter))
748+ else $Tuple2({
749+ let $l = li
750+ let $s = size($l)
751+ let $acc0 = nil
752+ func $f1_1 ($a,$i) = if (($i >= $s))
753+ then $a
754+ else f2($a, $l[$i])
755+
756+ func $f1_2 ($a,$i) = if (($i >= $s))
757+ then $a
758+ else throw("List size exceeds 12")
759+
760+ $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($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10), 11), 12)
761+ }, parameter)
762+ }
763+
764+
765+
766+@Callable(i)
767+func reSetup (assetIdStr) = {
768+ let lastResetup = tryGetInteger("resetup_lastUpdate")
769+ if ((dayBlocks > (height - lastResetup)))
770+ then throw("can be updated only once per day")
771+ else {
772+ let lts = split(tryGetString("setup_lts"), ",")
773+ let assets = getMarketAssets()
774+ let ur = getUr(assetIdStr)
775+ let tempLT = tryGetInteger((("setup_" + assetIdStr) + "_tempLT"))
776+ let lt = parseIntValue(assets[value(indexOf(assets, assetIdStr))])
777+ if ((ur > 90000000))
778+ then [IntegerEntry((("setup_" + assetIdStr) + "_tempLT"), fraction(tempLT, 9975, 10000))]
779+ else if (if ((lt > tempLT))
780+ then (90000000 > ur)
781+ else false)
782+ then [IntegerEntry((("setup_" + assetIdStr) + "_tempLT"), fraction(tempLT, 10025, 10000))]
783+ else nil
784+ }
785+ }
786+
787+
788+
789+@Callable(i)
790+func shutdown (shutdown) = if ((indexOf(shutdownWhitelist, i.caller) == unit))
791+ then throw("user not in a whitelist")
792+ else [BooleanEntry("setup_active", !(shutdown))]
793+
794+
795+
796+@Callable(i)
797+func liquidate (debug,address,assetAmount,sAssetIdStr,bAssetIdStr,routeStr) = if (!(verifyLiquidatorRights(i.caller)))
798+ then throw("temporarily available for whitelist only")
799+ else if (!(tryGetBoolean("setup_active")))
800+ then throw("market is stopped")
801+ else {
802+ let userCollateral = calcUserCollateral(address)
803+ if ((userCollateral == userCollateral))
804+ then {
805+ let $t02836028422 = getActualRate(sAssetIdStr, "sRate")
806+ let sRate = $t02836028422._1
807+ let ratesResult = $t02836028422._2
808+ let $t02842728496 = getActualRate(bAssetIdStr, "bRate")
809+ let bRate = $t02842728496._1
810+ let ratesRecalcResult2 = $t02842728496._2
811+ let sAssetAmount = fraction(assetAmount, Scale16, sRate)
812+ let currentSPosition = tryGetInteger(((address + "_supplied_") + sAssetIdStr))
813+ let currentBPositionVal = tryGetInteger(((address + "_borrowed_") + bAssetIdStr))
814+ let currentBPosition = if ((currentBPositionVal > 0))
815+ then currentBPositionVal
816+ else throw("user has no borrow in this token")
817+ if ((userCollateral > 0))
818+ then throw("user can't be liquidated")
819+ else if ((sAssetAmount > currentSPosition))
820+ then throw("position to liquidate is bigger than user's supply")
821+ else {
822+ let inv = if ((tryGetString(("setup_autostake_" + sAssetIdStr)) != ""))
823+ then invoke(this, "unstakeToken", [sAssetIdStr, sAssetAmount], nil)
824+ else unit
825+ if ((inv == inv))
826+ then {
827+ let balance0Before = getBalance(sAssetIdStr)
828+ if ((balance0Before == balance0Before))
829+ then {
830+ let balance1Before = getBalance(bAssetIdStr)
831+ if ((balance1Before == balance1Before))
832+ then {
833+ let exchangeInvoke = invoke(aggregatorAddress, "swap", [routeStr, 0], [AttachedPayment(getAssetBytes(sAssetIdStr), assetAmount)])
834+ if ((exchangeInvoke == exchangeInvoke))
835+ then {
836+ let asset0Sold = (balance0Before - getBalance(sAssetIdStr))
837+ if ((asset0Sold == asset0Sold))
838+ then {
839+ let asset1Bought = (getBalance(bAssetIdStr) - balance1Before)
840+ if ((asset1Bought == asset1Bought))
841+ then {
842+ let asset0Price = getTokenPriceCapped(sAssetIdStr)._1
843+ let asset0Scale = calcAssetScale(sAssetIdStr)
844+ let asset0Usd = fraction(asset0Sold, asset0Price, asset0Scale)
845+ let asset1Price = getTokenPriceCapped(bAssetIdStr)._2
846+ let asset1Scale = calcAssetScale(bAssetIdStr)
847+ let asset1Usd = fraction(asset1Bought, asset1Price, asset1Scale)
848+ let penalty = parseIntValue(split(tryGetString("setup_penalties"), ",")[value(indexOf(getMarketAssets(), bAssetIdStr))])
849+ let liquidationProfit = (asset1Usd - fraction(asset0Usd, (Scale8 - penalty), Scale8))
850+ let sAssetChange = fraction(asset0Sold, Scale16, sRate)
851+ let bAssetChange = fraction(fraction(asset1Bought, Scale16, bRate), (Scale8 - fraction(liquidationProfit, Scale8, asset1Usd)), Scale8)
852+ if ((asset0Sold > assetAmount))
853+ then throw("more assets exchanged than expected")
854+ else if ((0 > liquidationProfit))
855+ then throw("price impact is bigger than liquidation penalty")
856+ else [IntegerEntry(((address + "_supplied_") + sAssetIdStr), (currentSPosition - sAssetChange)), IntegerEntry(((address + "_borrowed_") + bAssetIdStr), (currentBPosition - bAssetChange)), IntegerEntry(("total_supplied_" + sAssetIdStr), (tryGetInteger(("total_supplied_" + sAssetIdStr)) - sAssetChange)), IntegerEntry(("total_borrowed_" + bAssetIdStr), (tryGetInteger(("total_borrowed_" + bAssetIdStr)) - bAssetChange))]
857+ }
858+ else throw("Strict value is not equal to itself.")
859+ }
860+ else throw("Strict value is not equal to itself.")
861+ }
862+ else throw("Strict value is not equal to itself.")
863+ }
864+ else throw("Strict value is not equal to itself.")
865+ }
866+ else throw("Strict value is not equal to itself.")
867+ }
868+ else throw("Strict value is not equal to itself.")
869+ }
870+ }
871+ else throw("Strict value is not equal to itself.")
872+ }
873+
874+
875+
876+@Callable(i)
877+func liquidateV2 (debug,address,sAssetIdStr) = if (!(verifyLiquidatorRights(i.caller)))
878+ then throw("temporarily available for whitelist only")
879+ else if (!(tryGetBoolean("setup_active")))
880+ then throw("market is stopped")
881+ else {
882+ let bAssetId = i.payments[0].assetId
883+ let bAssetIdStr = getAssetString(bAssetId)
884+ let bAssetAmount = i.payments[0].amount
885+ let userCollateral = calcUserCollateral(address)
886+ if ((userCollateral == userCollateral))
887+ then if ((userCollateral > 0))
888+ then throw("user can't be liquidated")
889+ else {
890+ let marketAssets = getMarketAssets()
891+ let asset1Num = value(indexOf(marketAssets, bAssetIdStr))
892+ let asset0Num = value(indexOf(marketAssets, sAssetIdStr))
893+ let $t03183731899 = getActualRate(bAssetIdStr, "bRate")
894+ let bRate = $t03183731899._1
895+ let ratesResult = $t03183731899._2
896+ let asset1Price = getTokenPriceCapped(bAssetIdStr)._2
897+ let asset1Scale = calcAssetScale(bAssetIdStr)
898+ let bAmountUsd = fraction(bAssetAmount, asset1Price, asset1Scale)
899+ let penalty = parseIntValue(value(split(tryGetString("setup_penalties"), ",")[asset1Num]))
900+ let asset0Price = getTokenPriceCapped(sAssetIdStr)._1
901+ let asset0Scale = calcAssetScale(sAssetIdStr)
902+ let sAmountUsd = fraction(bAmountUsd, (Scale8 + penalty), Scale8)
903+ let sAssetAmount = fraction(sAmountUsd, asset0Scale, asset0Price)
904+ let bAmount = fraction(bAssetAmount, Scale16, bRate)
905+ let sAmount = fraction(sAssetAmount, Scale16, ratesResult[(asset0Num * 3)].value)
906+ let currentSPosition = tryGetInteger(((address + "_supplied_") + sAssetIdStr))
907+ let currentBPositionVal = tryGetInteger(((address + "_borrowed_") + bAssetIdStr))
908+ let currentBPosition = if ((currentBPositionVal > 0))
909+ then currentBPositionVal
910+ else throw("user has no borrow in this token")
911+ if ((sAmount > currentSPosition))
912+ then throw("position to liquidate is bigger than user's supply")
913+ else {
914+ let inv = if ((tryGetString(("setup_autostake_" + sAssetIdStr)) != ""))
915+ then invoke(this, "unstakeToken", [sAssetIdStr, sAssetAmount], nil)
916+ else unit
917+ if ((inv == inv))
918+ then if (debug)
919+ then throw("liquidation will pass")
920+ else ([ScriptTransfer(i.caller, sAssetAmount, getAssetBytes(sAssetIdStr)), IntegerEntry(((address + "_supplied_") + sAssetIdStr), (currentSPosition - sAmount)), IntegerEntry(((address + "_borrowed_") + bAssetIdStr), (currentBPosition - bAmount)), IntegerEntry(("total_supplied_" + sAssetIdStr), (tryGetInteger(("total_supplied_" + sAssetIdStr)) - sAmount)), IntegerEntry(("total_borrowed_" + bAssetIdStr), (tryGetInteger(("total_borrowed_" + bAssetIdStr)) - bAmount))] ++ ratesResult)
921+ else throw("Strict value is not equal to itself.")
922+ }
923+ }
924+ else throw("Strict value is not equal to itself.")
925+ }
926+
927+
928+
929+@Callable(i)
930+func getUserCollateral (debug,address,minusBorrowed,afterChange) = {
931+ let assets = getMarketAssets()
932+ let ltvs = split(tryGetString("setup_ltvs"), ",")
933+ let lts = split(tryGetString("setup_lts"), ",")
934+ let rates = getActualRate(assets[0], "sRate")._2
935+ let changeHandler = split(afterChange, ",")
936+ func f (accum,next) = if ((next >= size(assets)))
937+ then accum
938+ else {
939+ let userSupplied = tryGetInteger(((address + "_supplied_") + assets[next]))
940+ let userBorrowed = tryGetInteger(((address + "_borrowed_") + assets[next]))
941+ let needTokenAccounting = if ((afterChange == ""))
942+ then if (if ((userBorrowed != 0))
943+ then true
944+ else (userSupplied != 0))
945+ then true
946+ else false
947+ else true
948+ if (needTokenAccounting)
949+ then {
950+ let assetScale = calcAssetScale(assets[next])
951+ let assetPrice = getTokenPriceCapped(assets[next])
952+ ((accum + fraction(fraction(fraction((userSupplied + (if (if (if ((afterChange != ""))
953+ then (changeHandler[0] == assets[next])
954+ else false)
955+ then (changeHandler[1] == "supplied")
956+ else false)
957+ then parseIntValue(changeHandler[2])
958+ else 0)), rates[(next * 3)].value, Scale16), parseIntValue(ltvs[next]), Scale8), assetPrice._1, assetScale)) - (if (minusBorrowed)
959+ then fraction(fraction(fraction((userBorrowed + (if (if (if ((afterChange != ""))
960+ then (changeHandler[0] == assets[next])
961+ else false)
962+ then (changeHandler[1] == "borrowed")
963+ else false)
964+ then parseIntValue(changeHandler[2])
965+ else 0)), rates[((next * 3) + 1)].value, Scale16), Scale8, parseIntValue(lts[next])), assetPrice._2, assetScale)
966+ else 0))
967+ }
968+ else accum
969+ }
970+
971+ let result = {
972+ let $l = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
973+ let $s = size($l)
974+ let $acc0 = 0
975+ func $f0_1 ($a,$i) = if (($i >= $s))
976+ then $a
977+ else f($a, $l[$i])
978+
979+ func $f0_2 ($a,$i) = if (($i >= $s))
980+ then $a
981+ else throw("List size exceeds 12")
982+
983+ $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)
984+ }
985+ if (debug)
986+ then throw(toString(result))
987+ else $Tuple2(rates, result)
988+ }
989+
990+
991+
992+@Callable(i)
993+func getPrices (debug) = {
994+ let assets = getMarketAssets()
995+ func f (accum,next) = if ((next >= size(assets)))
996+ then accum
997+ else {
998+ let assetPrice = getTokenPriceWithRisk(assets[next], 3)
999+ ((((accum + toString(assetPrice._1)) + ",") + toString(assetPrice._2)) + "|")
1000+ }
1001+
1002+ let result = {
1003+ let $l = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
1004+ let $s = size($l)
1005+ let $acc0 = ""
1006+ func $f0_1 ($a,$i) = if (($i >= $s))
1007+ then $a
1008+ else f($a, $l[$i])
1009+
1010+ func $f0_2 ($a,$i) = if (($i >= $s))
1011+ then $a
1012+ else throw("List size exceeds 12")
1013+
1014+ $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)
1015+ }
1016+ if (debug)
1017+ then throw(result)
1018+ else $Tuple2(nil, result)
1019+ }
1020+
1021+
1022+
1023+@Callable(i)
1024+func calculateUtilizationRatio (assetIdStr,debug) = if (debug)
1025+ then throw(toString(getUr(assetIdStr)))
1026+ else $Tuple2(nil, getUr(assetIdStr))
1027+
1028+
1029+
1030+@Callable(i)
1031+func calculateOutdatedUR (assetIdStr,debug) = if (debug)
1032+ then throw(toString(getOutdatedUr(assetIdStr)))
1033+ else $Tuple2(nil, getOutdatedUr(assetIdStr))
1034+
1035+
1036+
1037+@Callable(i)
1038+func calculateTokenRates (debug) = {
1039+ func f (accum,assetIdStr) = {
1040+ let rates = tokenRatesRecalc(assetIdStr)
1041+ $Tuple2(((((accum._1 + toString(rates[1].value)) + "|") + toString(rates[0].value)) + ","), (accum._2 ++ rates))
1042+ }
1043+
1044+ let parameter = {
1045+ let $l = getMarketAssets()
1046+ let $s = size($l)
1047+ let $acc0 = $Tuple2("", nil)
1048+ func $f0_1 ($a,$i) = if (($i >= $s))
1049+ then $a
1050+ else f($a, $l[$i])
1051+
1052+ func $f0_2 ($a,$i) = if (($i >= $s))
1053+ then $a
1054+ else throw("List size exceeds 12")
1055+
1056+ $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)
1057+ }
1058+ if (debug)
1059+ then throw(parameter._1)
1060+ else $Tuple2(parameter._2, parameter._1)
1061+ }
1062+
1063+
1064+
1065+@Callable(i)
1066+func calculateTokensInterest (debug) = {
1067+ func f (accum,assetIdStr) = {
1068+ let rate = fraction(getInterest(assetIdStr), dayBlocks, Scale8)
1069+ ((accum + toString(rate)) + ",")
1070+ }
1071+
1072+ let parameter = {
1073+ let $l = getMarketAssets()
1074+ let $s = size($l)
1075+ let $acc0 = ""
1076+ func $f0_1 ($a,$i) = if (($i >= $s))
1077+ then $a
1078+ else f($a, $l[$i])
1079+
1080+ func $f0_2 ($a,$i) = if (($i >= $s))
1081+ then $a
1082+ else throw("List size exceeds 12")
1083+
1084+ $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)
1085+ }
1086+ if (debug)
1087+ then throw(parameter)
1088+ else $Tuple2(nil, parameter)
1089+ }
1090+
1091+
1092+
1093+@Callable(i)
1094+func setApproverAddress (approverAddress) = {
1095+ let isSelf = if ((i.caller == this))
1096+ then true
1097+ else throw("Only self invoke")
1098+ if ((isSelf == isSelf))
1099+ then {
1100+ let _approverAddress = addressFromString(approverAddress)
1101+ let approverOk = match _approverAddress {
1102+ case t: Address =>
1103+ true
1104+ case _ =>
1105+ false
1106+ }
1107+ let canSetApprover = if (if (approverOk)
1108+ then true
1109+ else (approverAddress == ""))
1110+ then true
1111+ else throw("Wrong approver address")
1112+ if ((canSetApprover == canSetApprover))
1113+ then {
1114+ let isInited = valueOrElse(getBoolean(value(_approverAddress), "INITED"), false)
1115+ let hasAdmins = (valueOrElse(getString(value(_approverAddress), "ADMINS_PBKS"), "") != "")
1116+ let isApproverContract = if (if ((approverAddress == ""))
1117+ then true
1118+ else if (isInited)
1119+ then hasAdmins
1120+ else false)
1121+ then true
1122+ else throw("Address is not approver contract")
1123+ if ((isApproverContract == isApproverContract))
1124+ then [StringEntry("APPROVER_ADDRESS", approverAddress)]
1125+ else throw("Strict value is not equal to itself.")
1126+ }
1127+ else throw("Strict value is not equal to itself.")
1128+ }
1129+ else throw("Strict value is not equal to itself.")
1130+ }
1131+
1132+
1133+
1134+@Callable(i)
1135+func initNewMaster (master) = {
1136+ let addressOK = match addressFromString(master) {
1137+ case a: Address =>
1138+ true
1139+ case _ =>
1140+ false
1141+ }
1142+ if (!(addressOK))
1143+ then throw(("incorrect address " + master))
1144+ else if ((i.caller != this))
1145+ then throw("available for self call only")
1146+ else [StringEntry("verifier_master", master)]
1147+ }
1148+
1149+
1150+
1151+@Callable(i)
1152+func requestNewMaster (newMaster) = {
1153+ let addressOK = match addressFromString(newMaster) {
1154+ case a: Address =>
1155+ true
1156+ case _ =>
1157+ false
1158+ }
1159+ if (!(addressOK))
1160+ then throw(("incorrect address " + newMaster))
1161+ else if ((indexOf(sentinels, i.caller) == unit))
1162+ then throw("whitelist only")
1163+ else [StringEntry("verifier_newMaster", newMaster), IntegerEntry("verifier_newMasterEligibleAfter", (height + 10000))]
1164+ }
1165+
1166+
1167+
1168+@Callable(i)
1169+func activateNewMaster () = {
1170+ let eligibleHeight = getIntegerValue(this, "verifier_newMasterEligibleAfter")
1171+ let newMaster = getStringValue(this, "verifier_newMaster")
1172+ if ((indexOf(sentinels, i.caller) == unit))
1173+ then throw("whitelist only")
1174+ else if ((eligibleHeight > height))
1175+ then throw("new master cannot be activated yet")
1176+ else [DeleteEntry("verifier_newMaster"), DeleteEntry("verifier_newMasterEligibleAfter"), StringEntry("verifier_master", newMaster)]
1177+ }
1178+
1179+
1180+@Verifier(tx)
1181+func verify () = {
1182+ let multisigStr = valueOrElse(getString("APPROVER_ADDRESS"), "")
1183+ let multisigAddress = addressFromString(multisigStr)
1184+ let multisigOk = match multisigAddress {
1185+ case t: Address =>
1186+ true
1187+ case _ =>
1188+ false
1189+ }
1190+ let isInited = if (multisigOk)
1191+ then valueOrElse(getBoolean(value(multisigAddress), "INITED"), false)
1192+ else false
1193+ let hasAdmins = if (multisigOk)
1194+ then (valueOrElse(getString(value(multisigAddress), "ADMINS_PBKS"), "") != "")
1195+ else false
1196+ if (if (if (multisigOk)
1197+ then isInited
1198+ else false)
1199+ then hasAdmins
1200+ else false)
1201+ then match tx {
1202+ case ttx: SetScriptTransaction =>
1203+ match ttx.script {
1204+ case script: ByteVector =>
1205+ let scriptHasha = toBase58String(blake2b256(script))
1206+ let validFrom = valueOrErrorMessage(getInteger(value(multisigAddress), (((("script%%" + CONTRACT_TYPE) + "%%") + scriptHasha) + "%%validFrom")), "validFrom not set")
1207+ let validTo = valueOrErrorMessage(getInteger(value(multisigAddress), (((("script%%" + CONTRACT_TYPE) + "%%") + scriptHasha) + "%%validTo")), "validTo not set")
1208+ if ((height >= validFrom))
1209+ then (validTo >= height)
1210+ else false
1211+ case _ =>
1212+ false
1213+ }
1214+ case otx =>
1215+ let taskId = ((("tx_" + toString(this)) + "_") + toBase58String(otx.id))
1216+ let isApproved = valueOrElse(getBoolean(value(multisigAddress), (((toString(this) + "_") + toBase58String(otx.id)) + "__approved")), false)
1217+ let approvedFrom = valueOrElse(getInteger(value(multisigAddress), (taskId + "__approvedFrom")), 0)
1218+ if (isApproved)
1219+ then (height >= approvedFrom)
1220+ else false
1221+ }
1222+ else {
1223+ let masterAddress = getString("verifier_master")
1224+ let approvedByMaster = match masterAddress {
1225+ case x: String =>
1226+ match getInteger(addressFromStringValue(x), ("approvedTx_" + toBase58String(tx.id))) {
1227+ case y: Int =>
1228+ y
1229+ case _ =>
1230+ 0
1231+ }
1232+ case _ =>
1233+ 1
1234+ }
1235+ if (sigVerify(tx.bodyBytes, tx.proofs[0], tx.senderPublicKey))
1236+ then (approvedByMaster > 0)
1237+ else false
1238+ }
1239+ }
1240+

github/deemru/w8io
125.97 ms