tx · 33B4aXoJrYxwesjnGr9MhWABXSLY7J3LXbRer7cdEaZu

3PEC6NWG5h1NjWpTsBq1b5RF7NN1UbFsoy9:  -0.02600000 Waves

2023.03.02 15:39 [3537923] smart account 3PEC6NWG5h1NjWpTsBq1b5RF7NN1UbFsoy9 > SELF 0.00000000 Waves

{ "type": 13, "id": "33B4aXoJrYxwesjnGr9MhWABXSLY7J3LXbRer7cdEaZu", "fee": 2600000, "feeAssetId": null, "timestamp": 1677760894878, "version": 1, "sender": "3PEC6NWG5h1NjWpTsBq1b5RF7NN1UbFsoy9", "senderPublicKey": "CnEx6woaCe8kVcywJXVxsfdsGsEsCJuyzJVmaqc9htzj", "proofs": [ "WoSzzeWjSk85AH7aBDp9SSvRyWY3RL6pAovBJ2xcgRubYDzMQtrTwvzeBDFdUNBYk91MqF99tEfVmbyQM9XpC2H" ], "script": "base64:BgJYCAISBAoCAQQSBQoDCAEBEgUKAwgBARIDCgEIEgMKAQgSBAoCCAESBQoDCAEIEgUKAwgBCBIFCgMIAQgSABIDCgEBEgMKAQESBAoCAQESAwoBARIECgIBAXUABkVVTEVSOADWic+BAQAFTVVMVDYAwIQ9AAZNVUxUWDYJALYCAQDAhD0ABU1VTFQ4AIDC1y8ABk1VTFRYOAkAtgIBAIDC1y8AB01VTFRYMTAJALYCAQCAyK+gJQAGTVVMVDEyAICglKWNHQAHTVVMVFgxNgkAtgIBAICAhP6m3uERAAZNVUxUMTgJALYCAQCAgJC7utat8A0AA1NFUAICX18AB0xJU1RTRVACAToAEURFRkFVTFRTV0FQRkVFTjJXAIgnABFERUZBVUxUU1dBUEZFRVcyTgCgnAEAC0JSUFJPVEVDVEVEAKCNBgAHV0FWRVNJRAkA2QQBAgVXQVZFUwAJREFZTUlMTElTAIC4mSkBEmtleU5ldXRyaW5vQXNzZXRJZAACEW5ldXRyaW5vX2Fzc2V0X2lkAQ5rZXlOc2J0QXNzZXRJZAACDWJvbmRfYXNzZXRfaWQBDmtleVN1cmZBc3NldElkAAINc3VyZl9hc3NldF9pZAETa2V5U3dhcEFtb3VudEFQYXJhbQACGCVzJXNfX2NvbmZpZ19fc3dhcEFQYXJhbQETa2V5U3dhcEFtb3VudEJQYXJhbQACGCVzJXNfX2NvbmZpZ19fc3dhcEJQYXJhbQEXa2V5VXNkblN3YXBBbW91bnRBUGFyYW0AAhwlcyVzX19jb25maWdfX3VzZG5Td2FwQVBhcmFtARdrZXlVc2RuU3dhcEFtb3VudEJQYXJhbQACHCVzJXNfX2NvbmZpZ19fdXNkblN3YXBCUGFyYW0BE2tleU5zYnRMb2NrQ29udHJhY3QAAhQlc19fbnNidExvY2tDb250cmFjdAEPa2V5TWF0aENvbnRyYWN0AAIQJXNfX21hdGhDb250cmFjdAEPYmFza2V0QXNzZXRzS2V5AAIaJXMlc19fY29tbW9uX19iYXNrZXRBc3NldHMBCmJhc2tldERLZXkAAhUlcyVzX19jb21tb25fX2Jhc2tldEQBCmJhc2tldEJLZXkAAhUlcyVzX19jb21tb25fX2Jhc2tldEIBEmJhc2tldExvZ2JEZWx0YUtleQACHSVzJXNfX2NvbW1vbl9fYmFza2V0TG9nYkRlbHRhARZiYXNrZXRXZWlnaHRCeUFzc2V0S2V5AQdhc3NldElkCQCsAgICHyVzJXMlc19fY29tbW9uX193ZWlnaHRCeUFzc2V0X18FB2Fzc2V0SWQBCGtleVByaWNlAAIFcHJpY2UBD2tleVByaWNlQnlBc3NldAEHYXNzZXRJZAkArAICAh4lcyVzJXNfX2NvbW1vbl9fcHJpY2VCeUFzc2V0X18FB2Fzc2V0SWQBFmtleUxvY2tQYXJhbVN0YXJ0QmxvY2sBC3VzZXJBZGRyZXNzCQC5CQIJAMwIAgIGJXMlcyVzCQDMCAICC3BhcmFtQnlVc2VyCQDMCAIFC3VzZXJBZGRyZXNzCQDMCAICBXN0YXJ0BQNuaWwFA1NFUAELa2V5SGFsZkxpZmUAAgwlc19faGFsZkxpZmUBEGtleU1pbkxvY2tBbW91bnQAAhElc19fbWluTG9ja0Ftb3VudAEVa2V5TWluV2F2ZXNGb3JOc2J0QnV5AAISbWluX3dhdmVzX25zYnRfYnV5AQ5rZXlNaW5Oc2J0U2VsbAACDW1pbl9uc2J0X3NlbGwBF2tleVN0YXRzRGVwb3NpdEFtdEJ5RGF5AQl0aW1lc3RhbXAJALkJAgkAzAgCAgYlcyVzJWQJAMwIAgIFc3RhdHMJAMwIAgIPZGVwb3NpdEFtdEJ5RGF5CQDMCAIJAKQDAQUJdGltZXN0YW1wBQNuaWwFA1NFUAEMdG9TdGFydE9mRGF5AQl0aW1lc3RhbXAJAGgCCQBpAgUJdGltZXN0YW1wBQlEQVlNSUxMSVMFCURBWU1JTExJUwEPZ2V0U3RyaW5nT3JGYWlsAgdhZGRyZXNzA2tleQkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCdCAIFB2FkZHJlc3MFA2tleQkAuQkCCQDMCAICCm1hbmRhdG9yeSAJAMwIAgkApQgBBQdhZGRyZXNzCQDMCAICAS4JAMwIAgUDa2V5CQDMCAICDyBpcyBub3QgZGVmaW5lZAUDbmlsAgABDGdldEludE9yRmFpbAIHYWRkcmVzcwNrZXkJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAmggCBQdhZGRyZXNzBQNrZXkJALkJAgkAzAgCAgptYW5kYXRvcnkgCQDMCAIJAKUIAQUHYWRkcmVzcwkAzAgCAgEuCQDMCAIFA2tleQkAzAgCAg8gaXMgbm90IGRlZmluZWQFA25pbAIAAQ1nZXRCb29sT3JGYWlsAgdhZGRyZXNzA2tleQkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCbCAIFB2FkZHJlc3MFA2tleQkAuQkCCQDMCAICCm1hbmRhdG9yeSAJAMwIAgkApQgBBQdhZGRyZXNzCQDMCAICAS4JAMwIAgUDa2V5CQDMCAICDyBpcyBub3QgZGVmaW5lZAUDbmlsAgABDGdldEludE9yRWxzZQMHYWRkcmVzcwNrZXkKZGVmYXVsdFZhbAkBC3ZhbHVlT3JFbHNlAgkAmggCBQdhZGRyZXNzBQNrZXkFCmRlZmF1bHRWYWwBDGdldFN0ck9yRWxzZQMHYWRkcmVzcwNrZXkKZGVmYXVsdFZhbAkBC3ZhbHVlT3JFbHNlAgkAnQgCBQdhZGRyZXNzBQNrZXkFCmRlZmF1bHRWYWwBFmNvbnZlcnROZXV0cmlub1RvV2F2ZXMCBmFtb3VudAVwcmljZQkAawMFBmFtb3VudAUFTVVMVDgFBXByaWNlARFjb252ZXJ0VG9rZW5Ub1VzZAIGYW1vdW50BXByaWNlCQBrAwUGYW1vdW50BQVwcmljZQUFTVVMVDgBCWFzQW55TGlzdAEDdmFsBAckbWF0Y2gwBQN2YWwDCQABAgUHJG1hdGNoMAIJTGlzdFtBbnldBAp2YWxBbnlMaXN0BQckbWF0Y2gwBQp2YWxBbnlMaXN0CQACAQIbZmFpbCB0byBjYXN0IGludG8gTGlzdFtBbnldAQVhc0ludAEDdmFsBAckbWF0Y2gwBQN2YWwDCQABAgUHJG1hdGNoMAIDSW50BAZ2YWxJbnQFByRtYXRjaDAFBnZhbEludAkAAgECFWZhaWwgdG8gY2FzdCBpbnRvIEludAEIYXNTdHJpbmcBA3ZhbAQHJG1hdGNoMAUDdmFsAwkAAQIFByRtYXRjaDACBlN0cmluZwQGdmFsU3RyBQckbWF0Y2gwBQZ2YWxTdHIJAAIBAhhmYWlsIHRvIGNhc3QgaW50byBTdHJpbmcBDGFzVHVwbGUySW50cwEDdmFsBAckbWF0Y2gwBQN2YWwDCQABAgUHJG1hdGNoMAIKKEludCwgSW50KQQBdgUHJG1hdGNoMAUBdgkAAgECHWZhaWwgdG8gY2FzdCBpbnRvIFR1cGxlMiBpbnRzARJhc1N3YXBQYXJhbXNTVFJVQ1QBA3ZhbAQHJG1hdGNoMAUDdmFsAwkAAQIFByRtYXRjaDACIyhJbnQsIEludCwgSW50LCBJbnQsIEludCwgSW50LCBJbnQpBAZzdHJ1Y3QFByRtYXRjaDAFBnN0cnVjdAkAAgECImZhaWwgdG8gY2FzdCBpbnRvIFN3YXBQYXJhbXNTVFJVQ1QBFmFzV2l0aGRyYXdSZXN1bHRTVFJVQ1QBA3ZhbAQHJG1hdGNoMAUDdmFsAwMJAAECBQckbWF0Y2gwAjEoSW50LCBVbml0LCBJbnQsIEludCwgSW50LCBJbnQsIEludCwgSW50LCBTdHJpbmcpBgkAAQIFByRtYXRjaDACNyhJbnQsIEJ5dGVWZWN0b3IsIEludCwgSW50LCBJbnQsIEludCwgSW50LCBJbnQsIFN0cmluZykEBnN0cnVjdAUHJG1hdGNoMAUGc3RydWN0CQACAQIgZmFpbCB0byBjYXN0IGludG8gV2l0aGRyYXdSZXN1bHQBC3RvVGltZXN0YW1wAQVzdGFydAMJAGYCAAAFBXN0YXJ0AP///////////wEEByRtYXRjaDAJAO0HAQUFc3RhcnQDCQABAgUHJG1hdGNoMAIJQmxvY2tJbmZvBAVibG9jawUHJG1hdGNoMAgFBWJsb2NrCXRpbWVzdGFtcAD///////////8BAQV0b1gxOAIHb3JpZ1ZhbA1vcmlnU2NhbGVNdWx0CQC8AgMJALYCAQUHb3JpZ1ZhbAUGTVVMVDE4CQC2AgEFDW9yaWdTY2FsZU11bHQBB2Zyb21YMTgCA3ZhbA9yZXN1bHRTY2FsZU11bHQJAKADAQkAvAIDBQN2YWwJALYCAQUPcmVzdWx0U2NhbGVNdWx0BQZNVUxUMTgAD25NZXRyaWNJZHhQcmljZQAAABtuTWV0cmljSWR4VXNkbkxvY2tlZEJhbGFuY2UAAQAcbk1ldHJpY0lkeFdhdmVzTG9ja2VkQmFsYW5jZQACABFuTWV0cmljSWR4UmVzZXJ2ZQADABduTWV0cmljSWR4UmVzZXJ2ZUluVXNkbgAEABRuTWV0cmljSWR4VXNkblN1cHBseQAFABFuTWV0cmljSWR4U3VycGx1cwAGABhuTWV0cmljSWR4U3VycGx1c1BlcmNlbnQABwAMbk1ldHJpY0lkeEJSAAgAFG5NZXRyaWNJZHhOc2J0U3VwcGx5AAkAF25NZXRyaWNJZHhNYXhOc2J0U3VwcGx5AAoAFG5NZXRyaWNJZHhTdXJmU3VwcGx5AAsAEm5NZXRyaWNVc2RuVXNkdFBlZwAMABZuTWV0cmljQ3VycmVudFByaWNlQWRqAA0AEW5NZXRyaWNCYXNrZXRJbmZvAA4AFG5NZXRyaWNXZWlnaHRlZFByaWNlAA8AF25NZXRyaWNUb3RhbFJlc2VydmVzVXNkABAAGUlkeENvbnRyb2xDZmdOZXV0cmlub0RhcHAAAQAYSWR4Q29udHJvbENmZ0F1Y3Rpb25EYXBwAAIAFElkeENvbnRyb2xDZmdScGREYXBwAAMAFUlkeENvbnRyb2xDZmdNYXRoRGFwcAAEABxJZHhDb250cm9sQ2ZnTGlxdWlkYXRpb25EYXBwAAUAFUlkeENvbnRyb2xDZmdSZXN0RGFwcAAGAB1JZHhDb250cm9sQ2ZnTm9kZVJlZ2lzdHJ5RGFwcAAHABxJZHhDb250cm9sQ2ZnTnNidFN0YWtpbmdEYXBwAAgAGUlkeENvbnRyb2xDZmdNZWRpYXRvckRhcHAACQAcSWR4Q29udHJvbENmZ1N1cmZTdGFraW5nRGFwcAAKACBJZHhDb250cm9sQ2ZnR25zYnRDb250cm9sbGVyRGFwcAALAAxiRnVuY0lkeFN1cmYAAAANYkZ1bmNJZHhXYXZlcwABAAxiRnVuY0lkeFVzZG4AAgAUYkZ1bmNJZHhSZXNlcnZlU3RhcnQAAwATYkZ1bmNJZHhTdXBwbHlTdGFydAAEAA9iRnVuY0lkeEJSU3RhcnQABQASYkZ1bmNJZHhSZXNlcnZlRW5kAAYAEWJGdW5jSWR4U3VwcGx5RW5kAAcADWJGdW5jSWR4QlJFbmQACAAMYkZ1bmNJZHhSZXN0AAkAEmJGdW5jSWR4V2F2ZXNQcmljZQAKARFrZXlDb250cm9sQWRkcmVzcwACHCVzJXNfX2NvbmZpZ19fY29udHJvbEFkZHJlc3MBDWtleUNvbnRyb2xDZmcAAhElc19fY29udHJvbENvbmZpZwEUcmVhZENvbnRyb2xDZmdPckZhaWwBB2NvbnRyb2wJALwJAgkBD2dldFN0cmluZ09yRmFpbAIFB2NvbnRyb2wJAQ1rZXlDb250cm9sQ2ZnAAUDU0VQARhnZXRDb250cmFjdEFkZHJlc3NPckZhaWwCCmNvbnRyb2xDZmcDaWR4CQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKYIAQkAkQMCBQpjb250cm9sQ2ZnBQNpZHgJAKwCAgItQ29udHJvbCBjZmcgZG9lc24ndCBjb250YWluIGFkZHJlc3MgYXQgaW5kZXggCQCkAwEFA2lkeAAPY29udHJvbENvbnRyYWN0CQERQGV4dHJOYXRpdmUoMTA2MikBCQELdmFsdWVPckVsc2UCCQCdCAIFBHRoaXMJARFrZXlDb250cm9sQWRkcmVzcwACIzNQNUJmZDU4UFBmTnZCTTJIeThRZmJjRHFNZU50emc3S2ZQAApjb250cm9sQ2ZnCQEUcmVhZENvbnRyb2xDZmdPckZhaWwBBQ9jb250cm9sQ29udHJhY3QADG1hdGhDb250cmFjdAkBGGdldENvbnRyYWN0QWRkcmVzc09yRmFpbAIFCmNvbnRyb2xDZmcFFUlkeENvbnRyb2xDZmdNYXRoRGFwcAAQbmV1dHJpbm9Db250cmFjdAkBGGdldENvbnRyYWN0QWRkcmVzc09yRmFpbAIFCmNvbnRyb2xDZmcFGUlkeENvbnRyb2xDZmdOZXV0cmlub0RhcHAAD2F1Y3Rpb25Db250cmFjdAkBGGdldENvbnRyYWN0QWRkcmVzc09yRmFpbAIFCmNvbnRyb2xDZmcFGElkeENvbnRyb2xDZmdBdWN0aW9uRGFwcAATbGlxdWlkYXRpb25Db250cmFjdAkBGGdldENvbnRyYWN0QWRkcmVzc09yRmFpbAIFCmNvbnRyb2xDZmcFHElkeENvbnRyb2xDZmdMaXF1aWRhdGlvbkRhcHAAC3JwZENvbnRyYWN0CQEYZ2V0Q29udHJhY3RBZGRyZXNzT3JGYWlsAgUKY29udHJvbENmZwUUSWR4Q29udHJvbENmZ1JwZERhcHAAE25zYnRTdGFraW5nQ29udHJhY3QJARhnZXRDb250cmFjdEFkZHJlc3NPckZhaWwCBQpjb250cm9sQ2ZnBRxJZHhDb250cm9sQ2ZnTnNidFN0YWtpbmdEYXBwABNzdXJmU3Rha2luZ0NvbnRyYWN0CQEYZ2V0Q29udHJhY3RBZGRyZXNzT3JGYWlsAgUKY29udHJvbENmZwUcSWR4Q29udHJvbENmZ1N1cmZTdGFraW5nRGFwcAAXZ25zYnRDb250cm9sbGVyQ29udHJhY3QJARhnZXRDb250cmFjdEFkZHJlc3NPckZhaWwCBQpjb250cm9sQ2ZnBSBJZHhDb250cm9sQ2ZnR25zYnRDb250cm9sbGVyRGFwcAAVbmV1dHJpbm9Bc3NldElkU3RyaW5nCQEPZ2V0U3RyaW5nT3JGYWlsAgUQbmV1dHJpbm9Db250cmFjdAkBEmtleU5ldXRyaW5vQXNzZXRJZAAAD25ldXRyaW5vQXNzZXRJZAkA2QQBBRVuZXV0cmlub0Fzc2V0SWRTdHJpbmcADm5zYnRBc3NldElkU3RyCQERQGV4dHJOYXRpdmUoMTA1MykCBRBuZXV0cmlub0NvbnRyYWN0CQEOa2V5TnNidEFzc2V0SWQAAAtuc2J0QXNzZXRJZAkA2QQBBQ5uc2J0QXNzZXRJZFN0cgAOc3VyZkFzc2V0SWRTdHIJARFAZXh0ck5hdGl2ZSgxMDUzKQIFD2F1Y3Rpb25Db250cmFjdAkBDmtleVN1cmZBc3NldElkAAALc3VyZkFzc2V0SWQJANkEAQUOc3VyZkFzc2V0SWRTdHIBFHJlYWRVc2RuSW5jb21lRm9yRGF5AwpzdGFraW5nQWNjE3N0YXJ0T2ZEYXlUaW1lc3RhbXAPbmV1dHJpbm9NZXRyaWNzBAthbXRCeURheUtFWQkBF2tleVN0YXRzRGVwb3NpdEFtdEJ5RGF5AQUTc3RhcnRPZkRheVRpbWVzdGFtcAQJaW5jb21lU3RyCQEMZ2V0U3RyT3JFbHNlAwUKc3Rha2luZ0FjYwULYW10QnlEYXlLRVkCCiVzJXNfXzBfXzAEC2luY29tZUFycmF5CQC1CQIFCWluY29tZVN0cgUDU0VQBAh3YXZlc0FtdAkBDXBhcnNlSW50VmFsdWUBCQCRAwIFC2luY29tZUFycmF5AAEEB3VzZG5BbXQJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQtpbmNvbWVBcnJheQACBAxjdXJyZW50UHJpY2UJAQVhc0ludAEJAJEDAgUPbmV1dHJpbm9NZXRyaWNzBQ9uTWV0cmljSWR4UHJpY2UEDndhdmVzQXNVc2RuQW10CQBrAwUId2F2ZXNBbXQFDGN1cnJlbnRQcmljZQUFTVVMVDgJAGQCBQ53YXZlc0FzVXNkbkFtdAUHdXNkbkFtdAEXY2FsY1VzZG5JbmNvbWVGb3JQZXJpb2QCCnN0YWtpbmdBY2MEZGF5cwQPbmV1dHJpbm9NZXRyaWNzCQEJYXNBbnlMaXN0AQkA/AcEBQxtYXRoQ29udHJhY3QCGmNhbGNOZXV0aW5vTWV0cmljc1JFQURPTkxZBQNuaWwFA25pbAQOY3VyclN0YXJ0T2ZEYXkJAQx0b1N0YXJ0T2ZEYXkBCAUJbGFzdEJsb2NrCXRpbWVzdGFtcAQOc3RhcnRUaW1lc3RhbXAJAGUCBQ5jdXJyU3RhcnRPZkRheQkAaAIFCURBWU1JTExJUwkAZAIFBGRheXMAAQQMZW5kVGltZXN0YW1wCQBlAgUOY3VyclN0YXJ0T2ZEYXkFCURBWU1JTExJUwQPc3RhcnRVc2RuQW10VE1QCQEUcmVhZFVzZG5JbmNvbWVGb3JEYXkDBQpzdGFraW5nQWNjBQ5zdGFydFRpbWVzdGFtcAUPbmV1dHJpbm9NZXRyaWNzBAplbmRVc2RuQW10CQEUcmVhZFVzZG5JbmNvbWVGb3JEYXkDBQpzdGFraW5nQWNjBQxlbmRUaW1lc3RhbXAFD25ldXRyaW5vTWV0cmljcwQMc3RhcnRVc2RuQW10AwkAAAIFD3N0YXJ0VXNkbkFtdFRNUAAABQplbmRVc2RuQW10BQ9zdGFydFVzZG5BbXRUTVAJAGUCBQplbmRVc2RuQW10BQxzdGFydFVzZG5BbXQBB2NhbGNBcHIECnN0YWtpbmdBY2MMcGVyaW9kSW5EYXlzD2luY29tZUZvclBlcmlvZBlzdGFraW5nQXNzZXRQcmljZVRvVXNkblg2BAt0b3RhbFN0YWtlZAkBDGdldEludE9yRWxzZQMFCnN0YWtpbmdBY2MCHiVzJXNfX3N0YXRzX19hY3RpdmVUb3RhbExvY2tlZAABBBF0b3RhbFN0YWtlZEluVXNkbgkAawMFC3RvdGFsU3Rha2VkBRlzdGFraW5nQXNzZXRQcmljZVRvVXNkblg2BQVNVUxUNgMJAGYCAAAFD2luY29tZUZvclBlcmlvZAAACQBrAwkAaAIFD2luY29tZUZvclBlcmlvZAUFTVVMVDYA7QIJAGgCBRF0b3RhbFN0YWtlZEluVXNkbgUMcGVyaW9kSW5EYXlzDwFpARhyZXZlcnNlU3dhcExpbWl0UkVBRE9OTFkCA2xpbQppc091dE11bHRpBAJCUgkBBWFzSW50AQkAkQMCCQEJYXNBbnlMaXN0AQkA/AcEBQxtYXRoQ29udHJhY3QCGmNhbGNOZXV0aW5vTWV0cmljc1JFQURPTkxZBQNuaWwFA25pbAUMbk1ldHJpY0lkeEJSBAVnTnNidAMJAGcCAAAFA2xpbQAABAhhUGFyYW1YOAkAtgIBCQEMZ2V0SW50T3JGYWlsAgUMbWF0aENvbnRyYWN0AwUKaXNPdXRNdWx0aQkBF2tleVVzZG5Td2FwQW1vdW50QVBhcmFtAAkBE2tleVN3YXBBbW91bnRBUGFyYW0ABAliUGFyYW1YMTYJALYCAQkBDGdldEludE9yRmFpbAIFDG1hdGhDb250cmFjdAMFCmlzT3V0TXVsdGkJARdrZXlVc2RuU3dhcEFtb3VudEJQYXJhbQAJARNrZXlTd2FwQW1vdW50QlBhcmFtAAQJbGltRGl2QVg4AwUKaXNPdXRNdWx0aQkAvAIDCQC8AgMJALYCAQUDbGltBQdNVUxUWDEwBQhhUGFyYW1YOAUGTVVMVFg2CQC2AgEFAkJSCQC8AgMJALYCAQUDbGltBQdNVUxUWDEwBQhhUGFyYW1YOAQHcmV2QlgxNgkAvAIDBQdNVUxUWDE2BQdNVUxUWDE2BQliUGFyYW1YMTYJAKADAQkAdgYFCWxpbURpdkFYOAAIBQdyZXZCWDE2ABAABgUHQ0VJTElORwkAlAoCBQNuaWwFBWdOc2J0AWkBEWduc2J0SW5mb0lOVEVSTkFMAxV1c2VyQWRkcmVzc1N0ck9yRW1wdHkbYWRkaXRpb25hbE5zYnRUb1N0YWtlT3JaZXJvG2FkZGl0aW9uYWxTdXJmVG9TdGFrZU9yWmVybwQRdXNlckFkZHJlc3NPclRoaXMDCQECIT0CBRV1c2VyQWRkcmVzc1N0ck9yRW1wdHkCAAkBEUBleHRyTmF0aXZlKDEwNjIpAQUVdXNlckFkZHJlc3NTdHJPckVtcHR5BQR0aGlzBAxjdXJyZW50UHJpY2UJARFAZXh0ck5hdGl2ZSgxMDUwKQIFD2NvbnRyb2xDb250cmFjdAkBCGtleVByaWNlAAQRZ25zYnRGcm9tTnNidERpZmYFG2FkZGl0aW9uYWxOc2J0VG9TdGFrZU9yWmVybwQRZ25zYnRGcm9tU3VyZkRpZmYJAQVhc0ludAEJAPwHBAUTc3VyZlN0YWtpbmdDb250cmFjdAIYZ25zYnRGcm9tU3VyZlNZU1JFQURPTkxZCQDMCAIFG2FkZGl0aW9uYWxTdXJmVG9TdGFrZU9yWmVybwUDbmlsBQNuaWwECWdOc2J0RGlmZgkAZAIFEWduc2J0RnJvbU5zYnREaWZmBRFnbnNidEZyb21TdXJmRGlmZgQPc3dhcFBhcmFtc1R1cGxlCQESYXNTd2FwUGFyYW1zU1RSVUNUAQkA/AcEBRBuZXV0cmlub0NvbnRyYWN0Ahtzd2FwUGFyYW1zQnlVc2VyU1lTUkVBRE9OTFkJAMwIAgUVdXNlckFkZHJlc3NTdHJPckVtcHR5CQDMCAIAAAUDbmlsBQNuaWwEEGxpbWl0TWF4VG9rZW5Vc2QIBQ9zd2FwUGFyYW1zVHVwbGUCXzEEDmJsY2tzMkxtdFJlc2V0CAUPc3dhcFBhcmFtc1R1cGxlAl8zBAhnbnNidEFtdAgFD3N3YXBQYXJhbXNUdXBsZQJfNAQNZ25zYnRBbXRUb3RhbAgFD3N3YXBQYXJhbXNUdXBsZQJfNQQMbGltaXRNYXhVc2RuCAUPc3dhcFBhcmFtc1R1cGxlAl83BBJzd2FwUGFyYW1zVHVwbGVORVcJARJhc1N3YXBQYXJhbXNTVFJVQ1QBCQD8BwQFEG5ldXRyaW5vQ29udHJhY3QCG3N3YXBQYXJhbXNCeVVzZXJTWVNSRUFET05MWQkAzAgCBRV1c2VyQWRkcmVzc1N0ck9yRW1wdHkJAMwIAgUJZ05zYnREaWZmBQNuaWwFA25pbAQTbGltaXRNYXhUb2tlblVzZE5FVwgFEnN3YXBQYXJhbXNUdXBsZU5FVwJfMQQRYmxja3MyTG10UmVzZXRORVcIBRJzd2FwUGFyYW1zVHVwbGVORVcCXzMEC2duc2J0QW10TkVXCAUSc3dhcFBhcmFtc1R1cGxlTkVXAl80BBBnbnNidEFtdFRvdGFsTkVXCAUSc3dhcFBhcmFtc1R1cGxlTkVXAl81BA9saW1pdE1heFVzZG5ORVcIBRJzd2FwUGFyYW1zVHVwbGVORVcCXzcEC25zYnRCYWxhbmNlAwkBAiE9AgUVdXNlckFkZHJlc3NTdHJPckVtcHR5AgAJAPAHAgURdXNlckFkZHJlc3NPclRoaXMFC25zYnRBc3NldElkAAAEC3N1cmZCYWxhbmNlAwkBAiE9AgUVdXNlckFkZHJlc3NTdHJPckVtcHR5AgAJAPAHAgURdXNlckFkZHJlc3NPclRoaXMFC3N1cmZBc3NldElkAAAED25zYnRCYWxhbmNlRGlmZgMJAGcCBRthZGRpdGlvbmFsTnNidFRvU3Rha2VPclplcm8AAAUbYWRkaXRpb25hbE5zYnRUb1N0YWtlT3JaZXJvBBFuc2J0VW5zdGFraW5nRGF0YQkBCWFzQW55TGlzdAEJAPwHBAUTbnNidFN0YWtpbmdDb250cmFjdAIYbnNidFVuc3Rha2luZ1NZU1JFQURPTkxZCQDMCAIFFXVzZXJBZGRyZXNzU3RyT3JFbXB0eQkAzAgCCQBoAgD///////////8BBRthZGRpdGlvbmFsTnNidFRvU3Rha2VPclplcm8FA25pbAUDbmlsBBFuc2J0UmVjZWl2ZUFtb3VudAkBBWFzSW50AQkAkQMCBRFuc2J0VW5zdGFraW5nRGF0YQACBAZyZXN1bHQJAQEtAQURbnNidFJlY2VpdmVBbW91bnQFBnJlc3VsdAQObnNidEJhbGFuY2VOZXcJAGUCBQtuc2J0QmFsYW5jZQUPbnNidEJhbGFuY2VEaWZmBA5zdXJmQmFsYW5jZU5ldwkAZQIFC3N1cmZCYWxhbmNlBRthZGRpdGlvbmFsU3VyZlRvU3Rha2VPclplcm8ECWduc2J0RGF0YQkBCWFzQW55TGlzdAEJAPwHBAUXZ25zYnRDb250cm9sbGVyQ29udHJhY3QCFGduc2J0SW5mb1NZU1JFQURPTkxZCQDMCAIFFXVzZXJBZGRyZXNzU3RyT3JFbXB0eQkAzAgCBRthZGRpdGlvbmFsTnNidFRvU3Rha2VPclplcm8JAMwIAgUbYWRkaXRpb25hbFN1cmZUb1N0YWtlT3JaZXJvBQNuaWwFA25pbAQJZ25zYnRVc2VyCQEFYXNJbnQBCQCRAwIFCWduc2J0RGF0YQAABApnbnNidFRvdGFsCQEFYXNJbnQBCQCRAwIFCWduc2J0RGF0YQABBAhuc2J0RGF0YQkBCWFzQW55TGlzdAEJAJEDAgUJZ25zYnREYXRhAAIECHN1cmZEYXRhCQEJYXNBbnlMaXN0AQkAkQMCBQlnbnNidERhdGEAAwQRdnBFZmZlY3RpdmVIZWlnaHQJAQVhc0ludAEJAJEDAgUJZ25zYnREYXRhAAQEFHZwRWZmZWN0aXZlSGVpZ2h0TkVXCQEFYXNJbnQBCQCRAwIFCWduc2J0RGF0YQAFBBBnbnNidEFtdEZyb21Oc2J0CQEFYXNJbnQBCQCRAwIFCG5zYnREYXRhAAIEEGduc2J0QW10RnJvbVN1cmYJAQVhc0ludAEJAJEDAgUIc3VyZkRhdGEAAgQTZ25zYnRBbXRGcm9tTnNidE5FVwkAZAIFEGduc2J0QW10RnJvbU5zYnQFEWduc2J0RnJvbU5zYnREaWZmBBNnbnNidEFtdEZyb21TdXJmTkVXCQBkAgUQZ25zYnRBbXRGcm9tU3VyZgURZ25zYnRGcm9tU3VyZkRpZmYEEmduc2J0RnJvbU5zYnRUb3RhbAkBBWFzSW50AQkAkQMCBQhuc2J0RGF0YQADBBJnbnNidEZyb21TdXJmVG90YWwJAQVhc0ludAEJAJEDAgUIc3VyZkRhdGEAAwQYZ25zYnRGcm9tU3VyZkFjdGl2ZVRvdGFsAAAEGGduc2J0RnJvbVN1cmZGcm96ZW5Ub3RhbAUSZ25zYnRGcm9tU3VyZlRvdGFsBBVnbnNidEZyb21Oc2J0VG90YWxORVcJAGQCBRJnbnNidEZyb21Oc2J0VG90YWwFEWduc2J0RnJvbU5zYnREaWZmBBVnbnNidEZyb21TdXJmVG90YWxORVcJAGQCBRJnbnNidEZyb21TdXJmVG90YWwFEWduc2J0RnJvbVN1cmZEaWZmBBtnbnNidEZyb21TdXJmRnJvemVuVG90YWxORVcFFWduc2J0RnJvbVN1cmZUb3RhbE5FVwQLdm90aW5nUG93ZXIJAGsDBRBnbnNidEFtdEZyb21Oc2J0BQVNVUxUOAkAZAIFEmduc2J0RnJvbU5zYnRUb3RhbAUYZ25zYnRGcm9tU3VyZkFjdGl2ZVRvdGFsBA52b3RpbmdQb3dlck5ldwkAawMFE2duc2J0QW10RnJvbU5zYnRORVcFBU1VTFQ4CQBkAgUVZ25zYnRGcm9tTnNidFRvdGFsTkVXBRhnbnNidEZyb21TdXJmQWN0aXZlVG90YWwEDnZvdGluZ1Bvd2VyTWF4CQBrAwkAZAIFEGduc2J0QW10RnJvbU5zYnQFEGduc2J0QW10RnJvbVN1cmYFBU1VTFQ4CQBkAgkAZAIFEmduc2J0RnJvbU5zYnRUb3RhbAUYZ25zYnRGcm9tU3VyZkFjdGl2ZVRvdGFsBRhnbnNidEZyb21TdXJmRnJvemVuVG90YWwEEXZvdGluZ1Bvd2VyTWF4TmV3CQBrAwkAZAIFE2duc2J0QW10RnJvbU5zYnRORVcFE2duc2J0QW10RnJvbVN1cmZORVcFBU1VTFQ4CQBkAgkAZAIFFWduc2J0RnJvbU5zYnRUb3RhbE5FVwUYZ25zYnRGcm9tU3VyZkFjdGl2ZVRvdGFsBRtnbnNidEZyb21TdXJmRnJvemVuVG90YWxORVcEDnZvdGluZ1Bvd2VyRXRhAwkAAAIFEXZwRWZmZWN0aXZlSGVpZ2h0AAAFBmhlaWdodAURdnBFZmZlY3RpdmVIZWlnaHQEEXZvdGluZ1Bvd2VyRXRhTmV3AwkAAAIFFHZwRWZmZWN0aXZlSGVpZ2h0TkVXAAAFBmhlaWdodAUUdnBFZmZlY3RpdmVIZWlnaHRORVcJAJQKAgUDbmlsCQDMCAIAAAkAzAgCBQtuc2J0QmFsYW5jZQkAzAgCBQtzdXJmQmFsYW5jZQkAzAgCBQ5uc2J0QmFsYW5jZU5ldwkAzAgCBQ5zdXJmQmFsYW5jZU5ldwkAzAgCBRBnbnNidEFtdEZyb21Oc2J0CQDMCAIFEGduc2J0QW10RnJvbVN1cmYJAMwIAgUTZ25zYnRBbXRGcm9tTnNidE5FVwkAzAgCBRNnbnNidEFtdEZyb21TdXJmTkVXCQDMCAIFEmduc2J0RnJvbU5zYnRUb3RhbAkAzAgCBRJnbnNidEZyb21TdXJmVG90YWwJAMwIAgUVZ25zYnRGcm9tTnNidFRvdGFsTkVXCQDMCAIFFWduc2J0RnJvbVN1cmZUb3RhbE5FVwkAzAgCBQxsaW1pdE1heFVzZG4JAMwIAgUQbGltaXRNYXhUb2tlblVzZAkAzAgCBQ9saW1pdE1heFVzZG5ORVcJAMwIAgUTbGltaXRNYXhUb2tlblVzZE5FVwkAzAgCBQ5ibGNrczJMbXRSZXNldAkAzAgCBRFibGNrczJMbXRSZXNldE5FVwkAzAgCBQt2b3RpbmdQb3dlcgkAzAgCBQ52b3RpbmdQb3dlck5ldwkAzAgCBQ52b3RpbmdQb3dlck1heAkAzAgCBRF2b3RpbmdQb3dlck1heE5ldwkAzAgCBQ52b3RpbmdQb3dlckV0YQkAzAgCBRF2b3RpbmdQb3dlckV0YU5ldwUDbmlsAWkBEWduc2J0SW5mb1JFQURPTkxZAxV1c2VyQWRkcmVzc1N0ck9yRW1wdHkbYWRkaXRpb25hbE5zYnRUb1N0YWtlT3JaZXJvG2FkZGl0aW9uYWxTdXJmVG9TdGFrZU9yWmVybwQNZ25zYnRJbmZvREFUQQkBCWFzQW55TGlzdAEJAPwHBAUEdGhpcwIRZ25zYnRJbmZvSU5URVJOQUwJAMwIAgUVdXNlckFkZHJlc3NTdHJPckVtcHR5CQDMCAIFG2FkZGl0aW9uYWxOc2J0VG9TdGFrZU9yWmVybwkAzAgCBRthZGRpdGlvbmFsU3VyZlRvU3Rha2VPclplcm8FA25pbAUDbmlsCQCUCgIFA25pbAkAuQkCCQDMCAICMCVkJWQlZCVkJWQlZCVkJWQlZCVkJWQlZCVkJWQlZCVkJWQlZCVkJWQlZCVkJWQlZAkAzAgCCQCkAwEJAQVhc0ludAEJAJEDAgUNZ25zYnRJbmZvREFUQQABCQDMCAIJAKQDAQkBBWFzSW50AQkAkQMCBQ1nbnNidEluZm9EQVRBAAIJAMwIAgkApAMBCQEFYXNJbnQBCQCRAwIFDWduc2J0SW5mb0RBVEEAAwkAzAgCCQCkAwEJAQVhc0ludAEJAJEDAgUNZ25zYnRJbmZvREFUQQAECQDMCAIJAKQDAQkBBWFzSW50AQkAkQMCBQ1nbnNidEluZm9EQVRBAAUJAMwIAgkApAMBCQEFYXNJbnQBCQCRAwIFDWduc2J0SW5mb0RBVEEABgkAzAgCCQCkAwEJAQVhc0ludAEJAJEDAgUNZ25zYnRJbmZvREFUQQAHCQDMCAIJAKQDAQkBBWFzSW50AQkAkQMCBQ1nbnNidEluZm9EQVRBAAgJAMwIAgkApAMBCQEFYXNJbnQBCQCRAwIFDWduc2J0SW5mb0RBVEEACQkAzAgCCQCkAwEJAQVhc0ludAEJAJEDAgUNZ25zYnRJbmZvREFUQQAKCQDMCAIJAKQDAQkBBWFzSW50AQkAkQMCBQ1nbnNidEluZm9EQVRBAAsJAMwIAgkApAMBCQEFYXNJbnQBCQCRAwIFDWduc2J0SW5mb0RBVEEADAkAzAgCCQCkAwEJAQVhc0ludAEJAJEDAgUNZ25zYnRJbmZvREFUQQANCQDMCAIJAKQDAQkBBWFzSW50AQkAkQMCBQ1nbnNidEluZm9EQVRBAA4JAMwIAgkApAMBCQEFYXNJbnQBCQCRAwIFDWduc2J0SW5mb0RBVEEADwkAzAgCCQCkAwEJAQVhc0ludAEJAJEDAgUNZ25zYnRJbmZvREFUQQAQCQDMCAIJAKQDAQkBBWFzSW50AQkAkQMCBQ1nbnNidEluZm9EQVRBABEJAMwIAgkApAMBCQEFYXNJbnQBCQCRAwIFDWduc2J0SW5mb0RBVEEAEgkAzAgCCQCkAwEJAQVhc0ludAEJAJEDAgUNZ25zYnRJbmZvREFUQQATCQDMCAIJAKQDAQkBBWFzSW50AQkAkQMCBQ1nbnNidEluZm9EQVRBABQJAMwIAgkApAMBCQEFYXNJbnQBCQCRAwIFDWduc2J0SW5mb0RBVEEAFQkAzAgCCQCkAwEJAQVhc0ludAEJAJEDAgUNZ25zYnRJbmZvREFUQQAWCQDMCAIJAKQDAQkBBWFzSW50AQkAkQMCBQ1nbnNidEluZm9EQVRBABcJAMwIAgkApAMBCQEFYXNJbnQBCQCRAwIFDWduc2J0SW5mb0RBVEEAGAUDbmlsBQNTRVABaQEWZ25zYnRFZmZlY3RpdmVSRUFET05MWQEVdXNlckFkZHJlc3NTdHJPckVtcHR5BAlnbnNidERhdGEJAQlhc0FueUxpc3QBCQD8BwQFF2duc2J0Q29udHJvbGxlckNvbnRyYWN0AhRnbnNidEluZm9TWVNSRUFET05MWQkAzAgCBRV1c2VyQWRkcmVzc1N0ck9yRW1wdHkJAMwIAgAACQDMCAIAAAUDbmlsBQNuaWwECG5zYnREYXRhCQEJYXNBbnlMaXN0AQkAkQMCBQlnbnNidERhdGEAAgQMdXNlckZyb21Oc2J0CQEFYXNJbnQBCQCRAwIFCG5zYnREYXRhAAIEDXRvdGFsRnJvbU5zYnQJAQVhc0ludAEJAJEDAgUIbnNidERhdGEAAwQSdXNlck1hdHVyZUZyb21TdXJmCQEFYXNJbnQBCQCRAwIFCWduc2J0RGF0YQAJBBN0b3RhbE1hdHVyZUZyb21TdXJmCQEFYXNJbnQBCQCRAwIFCWduc2J0RGF0YQAGCQCUCgIFA25pbAkAuQkCCQDMCAICBCVkJWQJAMwIAgkApAMBCQBkAgUNdG90YWxGcm9tTnNidAUTdG90YWxNYXR1cmVGcm9tU3VyZgkAzAgCCQCkAwEJAGQCBQx1c2VyRnJvbU5zYnQFEnVzZXJNYXR1cmVGcm9tU3VyZgUDbmlsBQNTRVABaQEScmV3YXJkSW5mb1JFQURPTkxZARV1c2VyQWRkcmVzc1N0ck9yRW1wdHkEC3Jld2FyZHNEYXRhCQEJYXNBbnlMaXN0AQkA/AcEBRdnbnNidENvbnRyb2xsZXJDb250cmFjdAIXZ25zYnRSZXdhcmRzU1lTUkVBRE9OTFkJAMwIAgUVdXNlckFkZHJlc3NTdHJPckVtcHR5BQNuaWwFA25pbAQLdXNkblJld2FyZHMJAQhhc1N0cmluZwEJAPwHBAULcnBkQ29udHJhY3QCGHVuY2xhaW1lZFJld2FyZHNSRUFET05MWQkAzAgCBRV1c2VyQWRkcmVzc1N0ck9yRW1wdHkFA25pbAUDbmlsCQCUCgIFA25pbAkAuQkCCQDMCAICBiVzJXMlcwkAzAgCCQEIYXNTdHJpbmcBCQCRAwIFC3Jld2FyZHNEYXRhAAAJAMwIAgkBCGFzU3RyaW5nAQkAkQMCBQtyZXdhcmRzRGF0YQABCQDMCAIFC3VzZG5SZXdhcmRzBQNuaWwFA1NFUAFpARFtZXJnZU5zYnRSRUFET05MWQIUdXNlckFkZHJlc3NNYW5kYXRvcnkJbmV3QW1vdW50BAhuc2J0RGF0YQkBCWFzQW55TGlzdAEJAPwHBAUTbnNidFN0YWtpbmdDb250cmFjdAIWbnNidFN0YWtpbmdTWVNSRUFET05MWQkAzAgCBRR1c2VyQWRkcmVzc01hbmRhdG9yeQkAzAgCBQluZXdBbW91bnQFA25pbAUDbmlsBAdhbW91bnQwCQEFYXNJbnQBCQCRAwIFCG5zYnREYXRhAAAEC3N0YXJ0SGVpZ2h0AwkAZwIAAAUHYW1vdW50MAD///////////8BCQEFYXNJbnQBCQCRAwIFCG5zYnREYXRhAAIEDnN0YXJ0VGltZXN0YW1wCQELdG9UaW1lc3RhbXABBQtzdGFydEhlaWdodAQOc3RhcnRIZWlnaHROZXcDCQBnAgAABQluZXdBbW91bnQFC3N0YXJ0SGVpZ2h0AwkAZwIAAAUHYW1vdW50MAUGaGVpZ2h0BAhoYWxmTGlmZQkBDGdldEludE9yRmFpbAIFE25zYnRTdGFraW5nQ29udHJhY3QJAQtrZXlIYWxmTGlmZQAJAQVhc0ludAEJAPwHBAUMbWF0aENvbnRyYWN0AhNtZXJnZVN0YWtlc1JFQURPTkxZCQDMCAIFB2Ftb3VudDAJAMwIAgULc3RhcnRIZWlnaHQJAMwIAgUJbmV3QW1vdW50CQDMCAIFBmhlaWdodAkAzAgCBQhoYWxmTGlmZQUDbmlsBQNuaWwEEXN0YXJ0VGltZXN0YW1wTmV3CQELdG9UaW1lc3RhbXABBQ5zdGFydEhlaWdodE5ldwkAlAoCBQNuaWwJALkJAgkAzAgCAgglZCVkJWQlZAkAzAgCCQCkAwEFC3N0YXJ0SGVpZ2h0CQDMCAIJAKQDAQUOc3RhcnRUaW1lc3RhbXAJAMwIAgkApAMBBQ5zdGFydEhlaWdodE5ldwkAzAgCCQCkAwEFEXN0YXJ0VGltZXN0YW1wTmV3BQNuaWwFA1NFUAFpARtzd2FwTGltaXRDYWxjdWxhdG9yUkVBRE9OTFkDEXVzZXJBZGRyZXNzU3RyT3B0C2xpbWl0V2FudGVkCmFzc2V0SWRTdHIEDGdOc2J0Q3VycmVudAMJAAACBRF1c2VyQWRkcmVzc1N0ck9wdAIAAAAJAQVhc0ludAEICQESYXNTd2FwUGFyYW1zU1RSVUNUAQkA/AcEBRBuZXV0cmlub0NvbnRyYWN0Ahtzd2FwUGFyYW1zQnlVc2VyU1lTUkVBRE9OTFkJAMwIAgURdXNlckFkZHJlc3NTdHJPcHQJAMwIAgAABQNuaWwFA25pbAJfNAQFcHJpY2UJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAmggCBQ9jb250cm9sQ29udHJhY3QJAQ9rZXlQcmljZUJ5QXNzZXQBBQphc3NldElkU3RyCQCsAgICE05vIHByaWNlIGZvciBhc3NldCAFCmFzc2V0SWRTdHIECmlzT3V0TXVsdGkJAAACBQphc3NldElkU3RyBRVuZXV0cmlub0Fzc2V0SWRTdHJpbmcED2xpbWl0V2FudGVkVXNkbgMFCmlzT3V0TXVsdGkFC2xpbWl0V2FudGVkCQERY29udmVydFRva2VuVG9Vc2QCBQtsaW1pdFdhbnRlZAUFcHJpY2UEC2dOc2J0TmVlZGVkCQEFYXNJbnQBCQD8BwQFBHRoaXMCGHJldmVyc2VTd2FwTGltaXRSRUFET05MWQkAzAgCBQ9saW1pdFdhbnRlZFVzZG4JAMwIAgUKaXNPdXRNdWx0aQUDbmlsBQNuaWwECmdOc2J0RGVsdGEJAGUCBQtnTnNidE5lZWRlZAUMZ05zYnRDdXJyZW50CQCUCgIFA25pbAkAuQkCCQDMCAICBCVzJXMJAMwIAgkApAMBBQxnTnNidEN1cnJlbnQJAMwIAgkApAMBBQpnTnNidERlbHRhBQNuaWwFA1NFUAFpARBzd2FwSW5mb1JFQURPTkxZAxV1c2VyQWRkcmVzc1N0ck9yRW1wdHkGYW1vdW50CmFzc2V0SWRTdHIED25ldXRyaW5vTWV0cmljcwkBCWFzQW55TGlzdAEJAPwHBAUMbWF0aENvbnRyYWN0AhpjYWxjTmV1dGlub01ldHJpY3NSRUFET05MWQUDbmlsBQNuaWwEBXByaWNlCQEFYXNJbnQBCQCRAwIFD25ldXRyaW5vTWV0cmljcwUPbk1ldHJpY0lkeFByaWNlBA9zd2FwUGFyYW1zVHVwbGUJARJhc1N3YXBQYXJhbXNTVFJVQ1QBCQD8BwQFEG5ldXRyaW5vQ29udHJhY3QCG3N3YXBQYXJhbXNCeVVzZXJTWVNSRUFET05MWQkAzAgCBRV1c2VyQWRkcmVzc1N0ck9yRW1wdHkJAMwIAgAABQNuaWwFA25pbAQSbGltaXRNYXhUb2tlbkluVXNkCAUPc3dhcFBhcmFtc1R1cGxlAl8xBA5ibGNrczJMbXRSZXNldAgFD3N3YXBQYXJhbXNUdXBsZQJfMwQMbGltaXRNYXhVc2RuCAUPc3dhcFBhcmFtc1R1cGxlAl83BAdhc3NldElkCQDZBAEFCmFzc2V0SWRTdHIEDGJhc2tldEFzc2V0cwkBC3ZhbHVlT3JFbHNlAgkAnQgCBRBuZXV0cmlub0NvbnRyYWN0CQEPYmFza2V0QXNzZXRzS2V5AAIFV0FWRVMECHN3YXBUeXBlAwkBCGNvbnRhaW5zAgUMYmFza2V0QXNzZXRzBQphc3NldElkU3RyAgtvdXROZXV0cmlubwMJAAACBQdhc3NldElkBQ9uZXV0cmlub0Fzc2V0SWQCCG91dE11bHRpCQACAQkArAICAhNDYW4ndCBzd2FwIGFzc2V0SWQ9BQphc3NldElkU3RyBA13aXRoZHJhd1R1cGxlCQEWYXNXaXRoZHJhd1Jlc3VsdFNUUlVDVAEJAPwHBAUQbmV1dHJpbm9Db250cmFjdAIdY2FsY1dpdGhkcmF3UmVzdWx0U1lTUkVBRE9OTFkJAMwIAgUIc3dhcFR5cGUJAMwIAgUGYW1vdW50CQDMCAIFBXByaWNlCQDMCAIFCmFzc2V0SWRTdHIFA25pbAUDbmlsBAxvdXROZXRBbW91bnQIBQ13aXRoZHJhd1R1cGxlAl8xBApvdXRTdXJmQW10CAUNd2l0aGRyYXdUdXBsZQJfMwQPaW5BbXRUb1N1cmZQYXJ0CAUNd2l0aGRyYXdUdXBsZQJfNAQMb3V0RmVlQW1vdW50CAUNd2l0aGRyYXdUdXBsZQJfNgQLb3V0QW10R3Jvc3MIBQ13aXRoZHJhd1R1cGxlAl83BA13aXRoZHJhd1ByaWNlCAUNd2l0aGRyYXdUdXBsZQJfOAkAlAoCBQNuaWwJALkJAgkAzAgCAhAlZCVkJWQlZCVkJWQlZCVkCQDMCAIJAKQDAQUMb3V0TmV0QW1vdW50CQDMCAIJAKQDAQUKb3V0U3VyZkFtdAkAzAgCCQCkAwEFDG91dEZlZUFtb3VudAkAzAgCCQCkAwEFDXdpdGhkcmF3UHJpY2UJAMwIAgkApAMBBQ5ibGNrczJMbXRSZXNldAkAzAgCCQCkAwEFEmxpbWl0TWF4VG9rZW5JblVzZAkAzAgCCQCkAwEFDGxpbWl0TWF4VXNkbgkAzAgCCQCkAwEFD2luQW10VG9TdXJmUGFydAUDbmlsBQNTRVABaQESc3dhcEluZm9WMlJFQURPTkxZAxV1c2VyQWRkcmVzc1N0ck9yRW1wdHkGYW1vdW50CmFzc2V0SWRTdHIED25ldXRyaW5vTWV0cmljcwkBCWFzQW55TGlzdAEJAPwHBAUMbWF0aENvbnRyYWN0AhpjYWxjTmV1dGlub01ldHJpY3NSRUFET05MWQUDbmlsBQNuaWwEBXByaWNlCQEFYXNJbnQBCQCRAwIFD25ldXRyaW5vTWV0cmljcwUPbk1ldHJpY0lkeFByaWNlBA9zd2FwUGFyYW1zVHVwbGUJARJhc1N3YXBQYXJhbXNTVFJVQ1QBCQD8BwQFEG5ldXRyaW5vQ29udHJhY3QCG3N3YXBQYXJhbXNCeVVzZXJTWVNSRUFET05MWQkAzAgCBRV1c2VyQWRkcmVzc1N0ck9yRW1wdHkJAMwIAgAABQNuaWwFA25pbAQSbGltaXRNYXhUb2tlbkluVXNkCAUPc3dhcFBhcmFtc1R1cGxlAl8xBA5ibGNrczJMbXRSZXNldAgFD3N3YXBQYXJhbXNUdXBsZQJfMwQMbGltaXRNYXhVc2RuCAUPc3dhcFBhcmFtc1R1cGxlAl83BAdhc3NldElkCQDZBAEFCmFzc2V0SWRTdHIEDGJhc2tldEFzc2V0cwkBC3ZhbHVlT3JFbHNlAgkAnQgCBRBuZXV0cmlub0NvbnRyYWN0CQEPYmFza2V0QXNzZXRzS2V5AAIFV0FWRVMECHN3YXBUeXBlAwkBCGNvbnRhaW5zAgUMYmFza2V0QXNzZXRzBQphc3NldElkU3RyAgtvdXROZXV0cmlubwMJAAACBQdhc3NldElkBQ9uZXV0cmlub0Fzc2V0SWQCCG91dE11bHRpCQACAQkArAICAhNDYW4ndCBzd2FwIGFzc2V0SWQ9BQphc3NldElkU3RyBA13aXRoZHJhd1R1cGxlCQEWYXNXaXRoZHJhd1Jlc3VsdFNUUlVDVAEJAPwHBAUQbmV1dHJpbm9Db250cmFjdAIdY2FsY1dpdGhkcmF3UmVzdWx0U1lTUkVBRE9OTFkJAMwIAgUIc3dhcFR5cGUJAMwIAgUGYW1vdW50CQDMCAIFBXByaWNlCQDMCAIFCmFzc2V0SWRTdHIFA25pbAUDbmlsBA9vdXROZXV0cmlub0luZm8JALkJAgkAzAgCBRVuZXV0cmlub0Fzc2V0SWRTdHJpbmcJAMwIAgkApAMBCAUNd2l0aGRyYXdUdXBsZQJfOAkAzAgCCQCkAwEIBQ13aXRoZHJhd1R1cGxlAl8xCQDMCAIJAKQDAQgFDXdpdGhkcmF3VHVwbGUCXzYJAMwIAgIHMTAwMDAwMAUDbmlsBQdMSVNUU0VQBA53aXRoZHJhd0Jhc2tldAMJAAACBQhzd2FwVHlwZQILb3V0TmV1dHJpbm8FD291dE5ldXRyaW5vSW5mbwgFDXdpdGhkcmF3VHVwbGUCXzkJAJQKAgUDbmlsCQC6CQIJAMwIAgIIJWQlZCVkJXMJAMwIAgkApAMBBQ5ibGNrczJMbXRSZXNldAkAzAgCCQCkAwEFEmxpbWl0TWF4VG9rZW5JblVzZAkAzAgCCQCkAwEFDGxpbWl0TWF4VXNkbgkAzAgCBQ53aXRoZHJhd0Jhc2tldAUDbmlsBQNTRVABaQESYmFza2V0SW5mb1JFQURPTkxZAAQPbmV1dHJpbm9NZXRyaWNzCQEJYXNBbnlMaXN0AQkA/AcEBQxtYXRoQ29udHJhY3QCGmNhbGNOZXV0aW5vTWV0cmljc1JFQURPTkxZBQNuaWwFA25pbAQKYmFza2V0SW5mbwkBCGFzU3RyaW5nAQkAkQMCBQ9uZXV0cmlub01ldHJpY3MFEW5NZXRyaWNCYXNrZXRJbmZvBAZiYXNrZXQJALwJAgUKYmFza2V0SW5mbwIBXwoBBm1vZGlmeQIDYWNjBGl0ZW0EBXBhcnRzCQC1CQIFBGl0ZW0FB0xJU1RTRVAEB2Fzc2V0SWQJAJEDAgUFcGFydHMAAAQFZGxvZzYJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAmggCBRBuZXV0cmlub0NvbnRyYWN0CQESYmFza2V0TG9nYkRlbHRhS2V5AAIebG9nKGIsIGRlbHRhKSBrZXkgaXMgdW5kZWZpbmVkBAJENgkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCaCAIFEG5ldXRyaW5vQ29udHJhY3QJAQpiYXNrZXRES2V5AAISRCBrZXkgaXMgdW5kZWZpbmVkBAJiNgkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCaCAIFEG5ldXRyaW5vQ29udHJhY3QJAQpiYXNrZXRCS2V5AAISYiBrZXkgaXMgdW5kZWZpbmVkBAJ3NgkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCaCAIFEG5ldXRyaW5vQ29udHJhY3QJARZiYXNrZXRXZWlnaHRCeUFzc2V0S2V5AQUHYXNzZXRJZAkArAICCQCsAgICGFRhcmdldCB3ZWlnaHQgZm9yIGFzc2V0IAUHYXNzZXRJZAINIGlzIHVuZGVmaW5lZAQCcDYJAGQCCQBlAgUFZGxvZzYFAnc2CQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUFcGFydHMAAQQBZAkAZQIFAkQ2CQBsBgUCYjYABgUCcDYABgAGBQZIQUxGVVAJAM0IAgUDYWNjCQC5CQIJAM0IAgkAzQgCBQVwYXJ0cwkApAMBBQJ3NgkApAMBBQFkBQdMSVNUU0VQBAFiCgACJGwFBmJhc2tldAoAAiRzCQCQAwEFAiRsCgAFJGFjYzAFA25pbAoBBSRmMF8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQEGbW9kaWZ5AgUCJGEJAJEDAgUCJGwFAiRpCgEFJGYwXzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhRMaXN0IHNpemUgZXhjZWVkcyAxMAkBBSRmMF8yAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgUFJGFjYzAAAAABAAIAAwAEAAUABgAHAAgACQAKCQCUCgIFA25pbAkArAICAgQlc19fCQC6CQIFAWICAV8BaQEWdXNkblN0YWtpbmdBcHJSRUFET05MWQEEZGF5cwQHdG1wRGF5cwABBA9uZXV0cmlub01ldHJpY3MJAQlhc0FueUxpc3QBCQD8BwQFDG1hdGhDb250cmFjdAIaY2FsY05ldXRpbm9NZXRyaWNzUkVBRE9OTFkFA25pbAUDbmlsBAxjdXJyZW50UHJpY2UJAQVhc0ludAEJAJEDAgUPbmV1dHJpbm9NZXRyaWNzBQ9uTWV0cmljSWR4UHJpY2UEC3dhdmVzSW5jb21lCQBoAgAABQVNVUxUOAQPaW5jb21lRm9yUGVyaW9kCQBrAwULd2F2ZXNJbmNvbWUFDGN1cnJlbnRQcmljZQUFTVVMVDgEA2FwcgkBB2NhbGNBcHIEBQtycGRDb250cmFjdAUHdG1wRGF5cwUPaW5jb21lRm9yUGVyaW9kBQVNVUxUNgkAlAoCBQNuaWwJAKwCAgIEJWRfXwkApAMBBQNhcHIBaQEWc3VyZlN0YWtpbmdBcHJSRUFET05MWQEEZGF5cwQHdG1wRGF5cwADBA9pbmNvbWVGb3JQZXJpb2QJARdjYWxjVXNkbkluY29tZUZvclBlcmlvZAIFE3N1cmZTdGFraW5nQ29udHJhY3QFB3RtcERheXMEEXN1cmZQcmljZVRvVXNkblg2AICjBQQDYXByCQEHY2FsY0FwcgQFE3N1cmZTdGFraW5nQ29udHJhY3QFB3RtcERheXMFD2luY29tZUZvclBlcmlvZAURc3VyZlByaWNlVG9Vc2RuWDYJAJQKAgUDbmlsCQCsAgICBCVkX18JAKQDAQUDYXByAWkBGHN1cmZTdGFraW5nQXByVjJSRUFET05MWQIEZGF5cw9zdXJmVXNkblByaWNlWDYEB3RtcERheXMAAwQPaW5jb21lRm9yUGVyaW9kCQEXY2FsY1VzZG5JbmNvbWVGb3JQZXJpb2QCBRNzdXJmU3Rha2luZ0NvbnRyYWN0BQd0bXBEYXlzBANhcHIJAQdjYWxjQXByBAUTc3VyZlN0YWtpbmdDb250cmFjdAUHdG1wRGF5cwUPaW5jb21lRm9yUGVyaW9kBQ9zdXJmVXNkblByaWNlWDYJAJQKAgUDbmlsCQCsAgICBCVkX18JAKQDAQUDYXByAWkBFm5zYnRTdGFraW5nQXByUkVBRE9OTFkBBGRheXMEB3RtcERheXMAAwQRbnNidFByaWNlVG9Vc2RuWDYAgKToAwQPaW5jb21lRm9yUGVyaW9kCQEXY2FsY1VzZG5JbmNvbWVGb3JQZXJpb2QCBRNuc2J0U3Rha2luZ0NvbnRyYWN0BQd0bXBEYXlzBANhcHIJAQdjYWxjQXByBAUTbnNidFN0YWtpbmdDb250cmFjdAUHdG1wRGF5cwUPaW5jb21lRm9yUGVyaW9kBRFuc2J0UHJpY2VUb1VzZG5YNgkAlAoCBQNuaWwJAKwCAgIEJWRfXwkApAMBBQNhcHIBaQEYbnNidFN0YWtpbmdBcHJWMlJFQURPTkxZAgRkYXlzD25zYnRVc2RuUHJpY2VYNgQHdG1wRGF5cwADBA9pbmNvbWVGb3JQZXJpb2QJARdjYWxjVXNkbkluY29tZUZvclBlcmlvZAIFE25zYnRTdGFraW5nQ29udHJhY3QFB3RtcERheXMEA2FwcgkBB2NhbGNBcHIEBRNuc2J0U3Rha2luZ0NvbnRyYWN0BQd0bXBEYXlzBQ9pbmNvbWVGb3JQZXJpb2QFD25zYnRVc2RuUHJpY2VYNgkAlAoCBQNuaWwJAKwCAgIEJWRfXwkApAMBBQNhcHIACt6f4Q==", "chainId": 87, "height": 3537923, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: 2GSxVtz6TgSZuUkBrTQvnJRkcdKapnAAC2AveN8ZaWyG Next: 8LvB1UxWywiiUJxt2hR6Gr3jAYyqDScKVAk23XWNzGUF Diff:
OldNewDifferences
2121
2222 let SEP = "__"
2323
24+let LISTSEP = ":"
25+
2426 let DEFAULTSWAPFEEN2W = 5000
2527
2628 let DEFAULTSWAPFEEW2N = 20000
3840
3941
4042 func keySurfAssetId () = "surf_asset_id"
41-
42-
43-func keyBalanceLocked () = "balance_lock_"
44-
45-
46-func keyWavesLockedBalance () = (keyBalanceLocked() + "waves")
47-
48-
49-func keyNeutrinoLockedBalance () = (keyBalanceLocked() + "neutrino")
50-
51-
52-func keyMinWavesSwapAmount () = "min_waves_swap_amount"
53-
54-
55-func keyMinNeutrinoSwapAmount () = "min_neutrino_swap_amount"
56-
57-
58-func keyWavesOutFeePart () = "wavesOut_swap_feePart"
59-
60-
61-func keyNeutrinoOutFeePart () = "neutrinoOut_swap_feePart"
6243
6344
6445 func keySwapAmountAParam () = "%s%s__config__swapAParam"
7960 func keyMathContract () = "%s__mathContract"
8061
8162
82-func keyBalanceWavesLockInterval () = "balance_waves_lock_interval"
63+func basketAssetsKey () = "%s%s__common__basketAssets"
8364
8465
85-func keyBalanceNeutrinoLockInterval () = "balance_neutrino_lock_interval"
66+func basketDKey () = "%s%s__common__basketD"
67+
68+
69+func basketBKey () = "%s%s__common__basketB"
70+
71+
72+func basketLogbDeltaKey () = "%s%s__common__basketLogbDelta"
73+
74+
75+func basketWeightByAssetKey (assetId) = ("%s%s%s__common__weightByAsset__" + assetId)
8676
8777
8878 func keyPrice () = "price"
79+
80+
81+func keyPriceByAsset (assetId) = ("%s%s%s__common__priceByAsset__" + assetId)
8982
9083
9184 func keyLockParamStartBlock (userAddress) = makeString(["%s%s%s", "paramByUser", userAddress, "start"], SEP)
127120 func convertNeutrinoToWaves (amount,price) = fraction(amount, MULT8, price)
128121
129122
130-func convertWavesToNeutrino (amount,price) = fraction(amount, price, MULT8)
123+func convertTokenToUsd (amount,price) = fraction(amount, price, MULT8)
131124
132125
133126 func asAnyList (val) = match val {
171164
172165
173166 func asWithdrawResultSTRUCT (val) = match val {
174- case struct: (Int, Unit, Int, Int, Int, Int, Int, Int)|(Int, ByteVector, Int, Int, Int, Int, Int, Int) =>
167+ case struct: (Int, Unit, Int, Int, Int, Int, Int, Int, String)|(Int, ByteVector, Int, Int, Int, Int, Int, Int, String) =>
175168 struct
176169 case _ =>
177170 throw("fail to cast into WithdrawResult")
217210 let nMetricIdxMaxNsbtSupply = 10
218211
219212 let nMetricIdxSurfSupply = 11
213+
214+let nMetricUsdnUsdtPeg = 12
215+
216+let nMetricCurrentPriceAdj = 13
217+
218+let nMetricBasketInfo = 14
219+
220+let nMetricWeightedPrice = 15
221+
222+let nMetricTotalReservesUsd = 16
220223
221224 let IdxControlCfgNeutrinoDapp = 1
222225
342345
343346
344347 @Callable(i)
345-func reverseSwapLimitREADONLY (lim,isWavesSwap) = {
348+func reverseSwapLimitREADONLY (lim,isOutMulti) = {
346349 let BR = asInt(asAnyList(invoke(mathContract, "calcNeutinoMetricsREADONLY", nil, nil))[nMetricIdxBR])
347350 let gNsbt = if ((0 >= lim))
348351 then 0
349352 else {
350- let aParamX8 = toBigInt(getIntOrFail(mathContract, if (isWavesSwap)
351- then keySwapAmountAParam()
352- else keyUsdnSwapAmountAParam()))
353- let bParamX16 = toBigInt(getIntOrFail(mathContract, if (isWavesSwap)
354- then keySwapAmountBParam()
355- else keyUsdnSwapAmountBParam()))
356- let limDivAX8 = if (isWavesSwap)
357- then fraction(toBigInt(lim), MULTX10, aParamX8)
358- else fraction(fraction(toBigInt(lim), MULTX10, aParamX8), MULTX6, toBigInt(BR))
353+ let aParamX8 = toBigInt(getIntOrFail(mathContract, if (isOutMulti)
354+ then keyUsdnSwapAmountAParam()
355+ else keySwapAmountAParam()))
356+ let bParamX16 = toBigInt(getIntOrFail(mathContract, if (isOutMulti)
357+ then keyUsdnSwapAmountBParam()
358+ else keySwapAmountBParam()))
359+ let limDivAX8 = if (isOutMulti)
360+ then fraction(fraction(toBigInt(lim), MULTX10, aParamX8), MULTX6, toBigInt(BR))
361+ else fraction(toBigInt(lim), MULTX10, aParamX8)
359362 let revBX16 = fraction(MULTX16, MULTX16, bParamX16)
360363 toInt(pow(limDivAX8, 8, revBX16, 16, 6, CEILING))
361364 }
374377 let gnsbtFromSurfDiff = asInt(invoke(surfStakingContract, "gnsbtFromSurfSYSREADONLY", [additionalSurfToStakeOrZero], nil))
375378 let gNsbtDiff = (gnsbtFromNsbtDiff + gnsbtFromSurfDiff)
376379 let swapParamsTuple = asSwapParamsSTRUCT(invoke(neutrinoContract, "swapParamsByUserSYSREADONLY", [userAddressStrOrEmpty, 0], nil))
380+ let limitMaxTokenUsd = swapParamsTuple._1
377381 let blcks2LmtReset = swapParamsTuple._3
378382 let gnsbtAmt = swapParamsTuple._4
379383 let gnsbtAmtTotal = swapParamsTuple._5
380- let limitMaxWaves = swapParamsTuple._6
381384 let limitMaxUsdn = swapParamsTuple._7
382385 let swapParamsTupleNEW = asSwapParamsSTRUCT(invoke(neutrinoContract, "swapParamsByUserSYSREADONLY", [userAddressStrOrEmpty, gNsbtDiff], nil))
386+ let limitMaxTokenUsdNEW = swapParamsTupleNEW._1
383387 let blcks2LmtResetNEW = swapParamsTupleNEW._3
384388 let gnsbtAmtNEW = swapParamsTupleNEW._4
385389 let gnsbtAmtTotalNEW = swapParamsTupleNEW._5
386- let limitMaxWavesNEW = swapParamsTupleNEW._6
387390 let limitMaxUsdnNEW = swapParamsTupleNEW._7
388391 let nsbtBalance = if ((userAddressStrOrEmpty != ""))
389392 then assetBalance(userAddressOrThis, nsbtAssetId)
429432 let votingPowerEtaNew = if ((vpEffectiveHeightNEW == 0))
430433 then height
431434 else vpEffectiveHeightNEW
432- $Tuple2(nil, [0, nsbtBalance, surfBalance, nsbtBalanceNew, surfBalanceNew, gnsbtAmtFromNsbt, gnsbtAmtFromSurf, gnsbtAmtFromNsbtNEW, gnsbtAmtFromSurfNEW, gnsbtFromNsbtTotal, gnsbtFromSurfTotal, gnsbtFromNsbtTotalNEW, gnsbtFromSurfTotalNEW, limitMaxUsdn, limitMaxWaves, limitMaxUsdnNEW, limitMaxWavesNEW, blcks2LmtReset, blcks2LmtResetNEW, votingPower, votingPowerNew, votingPowerMax, votingPowerMaxNew, votingPowerEta, votingPowerEtaNew])
435+ $Tuple2(nil, [0, nsbtBalance, surfBalance, nsbtBalanceNew, surfBalanceNew, gnsbtAmtFromNsbt, gnsbtAmtFromSurf, gnsbtAmtFromNsbtNEW, gnsbtAmtFromSurfNEW, gnsbtFromNsbtTotal, gnsbtFromSurfTotal, gnsbtFromNsbtTotalNEW, gnsbtFromSurfTotalNEW, limitMaxUsdn, limitMaxTokenUsd, limitMaxUsdnNEW, limitMaxTokenUsdNEW, blcks2LmtReset, blcks2LmtResetNEW, votingPower, votingPowerNew, votingPowerMax, votingPowerMaxNew, votingPowerEta, votingPowerEtaNew])
433436 }
434437
435438
491494 let gNsbtCurrent = if ((userAddressStrOpt == ""))
492495 then 0
493496 else asInt(asSwapParamsSTRUCT(invoke(neutrinoContract, "swapParamsByUserSYSREADONLY", [userAddressStrOpt, 0], nil))._4)
494- let limitWantedUsdn = if ((assetIdStr == "WAVES"))
495- then convertWavesToNeutrino(limitWanted, getIntegerValue(controlContract, keyPrice()))
496- else limitWanted
497- let gNsbtNeeded = asInt(invoke(this, "reverseSwapLimitREADONLY", [limitWantedUsdn, (assetIdStr == "WAVES")], nil))
497+ let price = valueOrErrorMessage(getInteger(controlContract, keyPriceByAsset(assetIdStr)), ("No price for asset " + assetIdStr))
498+ let isOutMulti = (assetIdStr == neutrinoAssetIdString)
499+ let limitWantedUsdn = if (isOutMulti)
500+ then limitWanted
501+ else convertTokenToUsd(limitWanted, price)
502+ let gNsbtNeeded = asInt(invoke(this, "reverseSwapLimitREADONLY", [limitWantedUsdn, isOutMulti], nil))
498503 let gNsbtDelta = (gNsbtNeeded - gNsbtCurrent)
499504 $Tuple2(nil, makeString(["%s%s", toString(gNsbtCurrent), toString(gNsbtDelta)], SEP))
500505 }
506511 let neutrinoMetrics = asAnyList(invoke(mathContract, "calcNeutinoMetricsREADONLY", nil, nil))
507512 let price = asInt(neutrinoMetrics[nMetricIdxPrice])
508513 let swapParamsTuple = asSwapParamsSTRUCT(invoke(neutrinoContract, "swapParamsByUserSYSREADONLY", [userAddressStrOrEmpty, 0], nil))
514+ let limitMaxTokenInUsd = swapParamsTuple._1
509515 let blcks2LmtReset = swapParamsTuple._3
510- let limitMaxWaves = swapParamsTuple._6
511516 let limitMaxUsdn = swapParamsTuple._7
512517 let assetId = fromBase58String(assetIdStr)
513- let swapType = if ((assetId == WAVESID))
514- then "waves"
518+ let basketAssets = valueOrElse(getString(neutrinoContract, basketAssetsKey()), "WAVES")
519+ let swapType = if (contains(basketAssets, assetIdStr))
520+ then "outNeutrino"
515521 else if ((assetId == neutrinoAssetId))
516- then "neutrino"
522+ then "outMulti"
517523 else throw(("Can't swap assetId=" + assetIdStr))
518- let withdrawTuple = asWithdrawResultSTRUCT(invoke(neutrinoContract, "calcWithdrawResultSYSREADONLY", [swapType, amount, price], nil))
524+ let withdrawTuple = asWithdrawResultSTRUCT(invoke(neutrinoContract, "calcWithdrawResultSYSREADONLY", [swapType, amount, price, assetIdStr], nil))
519525 let outNetAmount = withdrawTuple._1
520- let outAssetId = withdrawTuple._2
521526 let outSurfAmt = withdrawTuple._3
522527 let inAmtToSurfPart = withdrawTuple._4
523- let unleaseAmt = withdrawTuple._5
524528 let outFeeAmount = withdrawTuple._6
525529 let outAmtGross = withdrawTuple._7
526530 let withdrawPrice = withdrawTuple._8
527- $Tuple2(nil, makeString(["%d%d%d%d%d%d%d%d", toString(outNetAmount), toString(outSurfAmt), toString(outFeeAmount), toString(withdrawPrice), toString(blcks2LmtReset), toString(limitMaxWaves), toString(limitMaxUsdn), toString(inAmtToSurfPart)], SEP))
531+ $Tuple2(nil, makeString(["%d%d%d%d%d%d%d%d", toString(outNetAmount), toString(outSurfAmt), toString(outFeeAmount), toString(withdrawPrice), toString(blcks2LmtReset), toString(limitMaxTokenInUsd), toString(limitMaxUsdn), toString(inAmtToSurfPart)], SEP))
532+ }
533+
534+
535+
536+@Callable(i)
537+func swapInfoV2READONLY (userAddressStrOrEmpty,amount,assetIdStr) = {
538+ let neutrinoMetrics = asAnyList(invoke(mathContract, "calcNeutinoMetricsREADONLY", nil, nil))
539+ let price = asInt(neutrinoMetrics[nMetricIdxPrice])
540+ let swapParamsTuple = asSwapParamsSTRUCT(invoke(neutrinoContract, "swapParamsByUserSYSREADONLY", [userAddressStrOrEmpty, 0], nil))
541+ let limitMaxTokenInUsd = swapParamsTuple._1
542+ let blcks2LmtReset = swapParamsTuple._3
543+ let limitMaxUsdn = swapParamsTuple._7
544+ let assetId = fromBase58String(assetIdStr)
545+ let basketAssets = valueOrElse(getString(neutrinoContract, basketAssetsKey()), "WAVES")
546+ let swapType = if (contains(basketAssets, assetIdStr))
547+ then "outNeutrino"
548+ else if ((assetId == neutrinoAssetId))
549+ then "outMulti"
550+ else throw(("Can't swap assetId=" + assetIdStr))
551+ let withdrawTuple = asWithdrawResultSTRUCT(invoke(neutrinoContract, "calcWithdrawResultSYSREADONLY", [swapType, amount, price, assetIdStr], nil))
552+ let outNeutrinoInfo = makeString([neutrinoAssetIdString, toString(withdrawTuple._8), toString(withdrawTuple._1), toString(withdrawTuple._6), "1000000"], LISTSEP)
553+ let withdrawBasket = if ((swapType == "outNeutrino"))
554+ then outNeutrinoInfo
555+ else withdrawTuple._9
556+ $Tuple2(nil, makeString_2C(["%d%d%d%s", toString(blcks2LmtReset), toString(limitMaxTokenInUsd), toString(limitMaxUsdn), withdrawBasket], SEP))
557+ }
558+
559+
560+
561+@Callable(i)
562+func basketInfoREADONLY () = {
563+ let neutrinoMetrics = asAnyList(invoke(mathContract, "calcNeutinoMetricsREADONLY", nil, nil))
564+ let basketInfo = asString(neutrinoMetrics[nMetricBasketInfo])
565+ let basket = split_4C(basketInfo, "_")
566+ func modify (acc,item) = {
567+ let parts = split(item, LISTSEP)
568+ let assetId = parts[0]
569+ let dlog6 = valueOrErrorMessage(getInteger(neutrinoContract, basketLogbDeltaKey()), "log(b, delta) key is undefined")
570+ let D6 = valueOrErrorMessage(getInteger(neutrinoContract, basketDKey()), "D key is undefined")
571+ let b6 = valueOrErrorMessage(getInteger(neutrinoContract, basketBKey()), "b key is undefined")
572+ let w6 = valueOrErrorMessage(getInteger(neutrinoContract, basketWeightByAssetKey(assetId)), (("Target weight for asset " + assetId) + " is undefined"))
573+ let p6 = ((dlog6 - w6) + parseIntValue(parts[1]))
574+ let d = (D6 - pow(b6, 6, p6, 6, 6, HALFUP))
575+ (acc :+ makeString(((parts :+ toString(w6)) :+ toString(d)), LISTSEP))
576+ }
577+
578+ let b = {
579+ let $l = basket
580+ let $s = size($l)
581+ let $acc0 = nil
582+ func $f0_1 ($a,$i) = if (($i >= $s))
583+ then $a
584+ else modify($a, $l[$i])
585+
586+ func $f0_2 ($a,$i) = if (($i >= $s))
587+ then $a
588+ else throw("List size exceeds 10")
589+
590+ $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
591+ }
592+ $Tuple2(nil, ("%s__" + makeString_2C(b, "_")))
528593 }
529594
530595
Full:
OldNewDifferences
11 {-# STDLIB_VERSION 6 #-}
22 {-# SCRIPT_TYPE ACCOUNT #-}
33 {-# CONTENT_TYPE DAPP #-}
44 let EULER8 = 271828182
55
66 let MULT6 = 1000000
77
88 let MULTX6 = toBigInt(1000000)
99
1010 let MULT8 = 100000000
1111
1212 let MULTX8 = toBigInt(100000000)
1313
1414 let MULTX10 = toBigInt(10000000000)
1515
1616 let MULT12 = 1000000000000
1717
1818 let MULTX16 = toBigInt(10000000000000000)
1919
2020 let MULT18 = toBigInt(1000000000000000000)
2121
2222 let SEP = "__"
2323
24+let LISTSEP = ":"
25+
2426 let DEFAULTSWAPFEEN2W = 5000
2527
2628 let DEFAULTSWAPFEEW2N = 20000
2729
2830 let BRPROTECTED = 100000
2931
3032 let WAVESID = fromBase58String("WAVES")
3133
3234 let DAYMILLIS = 86400000
3335
3436 func keyNeutrinoAssetId () = "neutrino_asset_id"
3537
3638
3739 func keyNsbtAssetId () = "bond_asset_id"
3840
3941
4042 func keySurfAssetId () = "surf_asset_id"
41-
42-
43-func keyBalanceLocked () = "balance_lock_"
44-
45-
46-func keyWavesLockedBalance () = (keyBalanceLocked() + "waves")
47-
48-
49-func keyNeutrinoLockedBalance () = (keyBalanceLocked() + "neutrino")
50-
51-
52-func keyMinWavesSwapAmount () = "min_waves_swap_amount"
53-
54-
55-func keyMinNeutrinoSwapAmount () = "min_neutrino_swap_amount"
56-
57-
58-func keyWavesOutFeePart () = "wavesOut_swap_feePart"
59-
60-
61-func keyNeutrinoOutFeePart () = "neutrinoOut_swap_feePart"
6243
6344
6445 func keySwapAmountAParam () = "%s%s__config__swapAParam"
6546
6647
6748 func keySwapAmountBParam () = "%s%s__config__swapBParam"
6849
6950
7051 func keyUsdnSwapAmountAParam () = "%s%s__config__usdnSwapAParam"
7152
7253
7354 func keyUsdnSwapAmountBParam () = "%s%s__config__usdnSwapBParam"
7455
7556
7657 func keyNsbtLockContract () = "%s__nsbtLockContract"
7758
7859
7960 func keyMathContract () = "%s__mathContract"
8061
8162
82-func keyBalanceWavesLockInterval () = "balance_waves_lock_interval"
63+func basketAssetsKey () = "%s%s__common__basketAssets"
8364
8465
85-func keyBalanceNeutrinoLockInterval () = "balance_neutrino_lock_interval"
66+func basketDKey () = "%s%s__common__basketD"
67+
68+
69+func basketBKey () = "%s%s__common__basketB"
70+
71+
72+func basketLogbDeltaKey () = "%s%s__common__basketLogbDelta"
73+
74+
75+func basketWeightByAssetKey (assetId) = ("%s%s%s__common__weightByAsset__" + assetId)
8676
8777
8878 func keyPrice () = "price"
79+
80+
81+func keyPriceByAsset (assetId) = ("%s%s%s__common__priceByAsset__" + assetId)
8982
9083
9184 func keyLockParamStartBlock (userAddress) = makeString(["%s%s%s", "paramByUser", userAddress, "start"], SEP)
9285
9386
9487 func keyHalfLife () = "%s__halfLife"
9588
9689
9790 func keyMinLockAmount () = "%s__minLockAmount"
9891
9992
10093 func keyMinWavesForNsbtBuy () = "min_waves_nsbt_buy"
10194
10295
10396 func keyMinNsbtSell () = "min_nsbt_sell"
10497
10598
10699 func keyStatsDepositAmtByDay (timestamp) = makeString(["%s%s%d", "stats", "depositAmtByDay", toString(timestamp)], SEP)
107100
108101
109102 func toStartOfDay (timestamp) = ((timestamp / DAYMILLIS) * DAYMILLIS)
110103
111104
112105 func getStringOrFail (address,key) = valueOrErrorMessage(getString(address, key), makeString(["mandatory ", toString(address), ".", key, " is not defined"], ""))
113106
114107
115108 func getIntOrFail (address,key) = valueOrErrorMessage(getInteger(address, key), makeString(["mandatory ", toString(address), ".", key, " is not defined"], ""))
116109
117110
118111 func getBoolOrFail (address,key) = valueOrErrorMessage(getBoolean(address, key), makeString(["mandatory ", toString(address), ".", key, " is not defined"], ""))
119112
120113
121114 func getIntOrElse (address,key,defaultVal) = valueOrElse(getInteger(address, key), defaultVal)
122115
123116
124117 func getStrOrElse (address,key,defaultVal) = valueOrElse(getString(address, key), defaultVal)
125118
126119
127120 func convertNeutrinoToWaves (amount,price) = fraction(amount, MULT8, price)
128121
129122
130-func convertWavesToNeutrino (amount,price) = fraction(amount, price, MULT8)
123+func convertTokenToUsd (amount,price) = fraction(amount, price, MULT8)
131124
132125
133126 func asAnyList (val) = match val {
134127 case valAnyList: List[Any] =>
135128 valAnyList
136129 case _ =>
137130 throw("fail to cast into List[Any]")
138131 }
139132
140133
141134 func asInt (val) = match val {
142135 case valInt: Int =>
143136 valInt
144137 case _ =>
145138 throw("fail to cast into Int")
146139 }
147140
148141
149142 func asString (val) = match val {
150143 case valStr: String =>
151144 valStr
152145 case _ =>
153146 throw("fail to cast into String")
154147 }
155148
156149
157150 func asTuple2Ints (val) = match val {
158151 case v: (Int, Int) =>
159152 v
160153 case _ =>
161154 throw("fail to cast into Tuple2 ints")
162155 }
163156
164157
165158 func asSwapParamsSTRUCT (val) = match val {
166159 case struct: (Int, Int, Int, Int, Int, Int, Int) =>
167160 struct
168161 case _ =>
169162 throw("fail to cast into SwapParamsSTRUCT")
170163 }
171164
172165
173166 func asWithdrawResultSTRUCT (val) = match val {
174- case struct: (Int, Unit, Int, Int, Int, Int, Int, Int)|(Int, ByteVector, Int, Int, Int, Int, Int, Int) =>
167+ case struct: (Int, Unit, Int, Int, Int, Int, Int, Int, String)|(Int, ByteVector, Int, Int, Int, Int, Int, Int, String) =>
175168 struct
176169 case _ =>
177170 throw("fail to cast into WithdrawResult")
178171 }
179172
180173
181174 func toTimestamp (start) = if ((0 > start))
182175 then -1
183176 else match blockInfoByHeight(start) {
184177 case block: BlockInfo =>
185178 block.timestamp
186179 case _ =>
187180 -1
188181 }
189182
190183
191184 func toX18 (origVal,origScaleMult) = fraction(toBigInt(origVal), MULT18, toBigInt(origScaleMult))
192185
193186
194187 func fromX18 (val,resultScaleMult) = toInt(fraction(val, toBigInt(resultScaleMult), MULT18))
195188
196189
197190 let nMetricIdxPrice = 0
198191
199192 let nMetricIdxUsdnLockedBalance = 1
200193
201194 let nMetricIdxWavesLockedBalance = 2
202195
203196 let nMetricIdxReserve = 3
204197
205198 let nMetricIdxReserveInUsdn = 4
206199
207200 let nMetricIdxUsdnSupply = 5
208201
209202 let nMetricIdxSurplus = 6
210203
211204 let nMetricIdxSurplusPercent = 7
212205
213206 let nMetricIdxBR = 8
214207
215208 let nMetricIdxNsbtSupply = 9
216209
217210 let nMetricIdxMaxNsbtSupply = 10
218211
219212 let nMetricIdxSurfSupply = 11
213+
214+let nMetricUsdnUsdtPeg = 12
215+
216+let nMetricCurrentPriceAdj = 13
217+
218+let nMetricBasketInfo = 14
219+
220+let nMetricWeightedPrice = 15
221+
222+let nMetricTotalReservesUsd = 16
220223
221224 let IdxControlCfgNeutrinoDapp = 1
222225
223226 let IdxControlCfgAuctionDapp = 2
224227
225228 let IdxControlCfgRpdDapp = 3
226229
227230 let IdxControlCfgMathDapp = 4
228231
229232 let IdxControlCfgLiquidationDapp = 5
230233
231234 let IdxControlCfgRestDapp = 6
232235
233236 let IdxControlCfgNodeRegistryDapp = 7
234237
235238 let IdxControlCfgNsbtStakingDapp = 8
236239
237240 let IdxControlCfgMediatorDapp = 9
238241
239242 let IdxControlCfgSurfStakingDapp = 10
240243
241244 let IdxControlCfgGnsbtControllerDapp = 11
242245
243246 let bFuncIdxSurf = 0
244247
245248 let bFuncIdxWaves = 1
246249
247250 let bFuncIdxUsdn = 2
248251
249252 let bFuncIdxReserveStart = 3
250253
251254 let bFuncIdxSupplyStart = 4
252255
253256 let bFuncIdxBRStart = 5
254257
255258 let bFuncIdxReserveEnd = 6
256259
257260 let bFuncIdxSupplyEnd = 7
258261
259262 let bFuncIdxBREnd = 8
260263
261264 let bFuncIdxRest = 9
262265
263266 let bFuncIdxWavesPrice = 10
264267
265268 func keyControlAddress () = "%s%s__config__controlAddress"
266269
267270
268271 func keyControlCfg () = "%s__controlConfig"
269272
270273
271274 func readControlCfgOrFail (control) = split_4C(getStringOrFail(control, keyControlCfg()), SEP)
272275
273276
274277 func getContractAddressOrFail (controlCfg,idx) = valueOrErrorMessage(addressFromString(controlCfg[idx]), ("Control cfg doesn't contain address at index " + toString(idx)))
275278
276279
277280 let controlContract = addressFromStringValue(valueOrElse(getString(this, keyControlAddress()), "3P5Bfd58PPfNvBM2Hy8QfbcDqMeNtzg7KfP"))
278281
279282 let controlCfg = readControlCfgOrFail(controlContract)
280283
281284 let mathContract = getContractAddressOrFail(controlCfg, IdxControlCfgMathDapp)
282285
283286 let neutrinoContract = getContractAddressOrFail(controlCfg, IdxControlCfgNeutrinoDapp)
284287
285288 let auctionContract = getContractAddressOrFail(controlCfg, IdxControlCfgAuctionDapp)
286289
287290 let liquidationContract = getContractAddressOrFail(controlCfg, IdxControlCfgLiquidationDapp)
288291
289292 let rpdContract = getContractAddressOrFail(controlCfg, IdxControlCfgRpdDapp)
290293
291294 let nsbtStakingContract = getContractAddressOrFail(controlCfg, IdxControlCfgNsbtStakingDapp)
292295
293296 let surfStakingContract = getContractAddressOrFail(controlCfg, IdxControlCfgSurfStakingDapp)
294297
295298 let gnsbtControllerContract = getContractAddressOrFail(controlCfg, IdxControlCfgGnsbtControllerDapp)
296299
297300 let neutrinoAssetIdString = getStringOrFail(neutrinoContract, keyNeutrinoAssetId())
298301
299302 let neutrinoAssetId = fromBase58String(neutrinoAssetIdString)
300303
301304 let nsbtAssetIdStr = getStringValue(neutrinoContract, keyNsbtAssetId())
302305
303306 let nsbtAssetId = fromBase58String(nsbtAssetIdStr)
304307
305308 let surfAssetIdStr = getStringValue(auctionContract, keySurfAssetId())
306309
307310 let surfAssetId = fromBase58String(surfAssetIdStr)
308311
309312 func readUsdnIncomeForDay (stakingAcc,startOfDayTimestamp,neutrinoMetrics) = {
310313 let amtByDayKEY = keyStatsDepositAmtByDay(startOfDayTimestamp)
311314 let incomeStr = getStrOrElse(stakingAcc, amtByDayKEY, "%s%s__0__0")
312315 let incomeArray = split(incomeStr, SEP)
313316 let wavesAmt = parseIntValue(incomeArray[1])
314317 let usdnAmt = parseIntValue(incomeArray[2])
315318 let currentPrice = asInt(neutrinoMetrics[nMetricIdxPrice])
316319 let wavesAsUsdnAmt = fraction(wavesAmt, currentPrice, MULT8)
317320 (wavesAsUsdnAmt + usdnAmt)
318321 }
319322
320323
321324 func calcUsdnIncomeForPeriod (stakingAcc,days) = {
322325 let neutrinoMetrics = asAnyList(invoke(mathContract, "calcNeutinoMetricsREADONLY", nil, nil))
323326 let currStartOfDay = toStartOfDay(lastBlock.timestamp)
324327 let startTimestamp = (currStartOfDay - (DAYMILLIS * (days + 1)))
325328 let endTimestamp = (currStartOfDay - DAYMILLIS)
326329 let startUsdnAmtTMP = readUsdnIncomeForDay(stakingAcc, startTimestamp, neutrinoMetrics)
327330 let endUsdnAmt = readUsdnIncomeForDay(stakingAcc, endTimestamp, neutrinoMetrics)
328331 let startUsdnAmt = if ((startUsdnAmtTMP == 0))
329332 then endUsdnAmt
330333 else startUsdnAmtTMP
331334 (endUsdnAmt - startUsdnAmt)
332335 }
333336
334337
335338 func calcApr (stakingAcc,periodInDays,incomeForPeriod,stakingAssetPriceToUsdnX6) = {
336339 let totalStaked = getIntOrElse(stakingAcc, "%s%s__stats__activeTotalLocked", 1)
337340 let totalStakedInUsdn = fraction(totalStaked, stakingAssetPriceToUsdnX6, MULT6)
338341 if ((0 > incomeForPeriod))
339342 then 0
340343 else fraction((incomeForPeriod * MULT6), 365, (totalStakedInUsdn * periodInDays))
341344 }
342345
343346
344347 @Callable(i)
345-func reverseSwapLimitREADONLY (lim,isWavesSwap) = {
348+func reverseSwapLimitREADONLY (lim,isOutMulti) = {
346349 let BR = asInt(asAnyList(invoke(mathContract, "calcNeutinoMetricsREADONLY", nil, nil))[nMetricIdxBR])
347350 let gNsbt = if ((0 >= lim))
348351 then 0
349352 else {
350- let aParamX8 = toBigInt(getIntOrFail(mathContract, if (isWavesSwap)
351- then keySwapAmountAParam()
352- else keyUsdnSwapAmountAParam()))
353- let bParamX16 = toBigInt(getIntOrFail(mathContract, if (isWavesSwap)
354- then keySwapAmountBParam()
355- else keyUsdnSwapAmountBParam()))
356- let limDivAX8 = if (isWavesSwap)
357- then fraction(toBigInt(lim), MULTX10, aParamX8)
358- else fraction(fraction(toBigInt(lim), MULTX10, aParamX8), MULTX6, toBigInt(BR))
353+ let aParamX8 = toBigInt(getIntOrFail(mathContract, if (isOutMulti)
354+ then keyUsdnSwapAmountAParam()
355+ else keySwapAmountAParam()))
356+ let bParamX16 = toBigInt(getIntOrFail(mathContract, if (isOutMulti)
357+ then keyUsdnSwapAmountBParam()
358+ else keySwapAmountBParam()))
359+ let limDivAX8 = if (isOutMulti)
360+ then fraction(fraction(toBigInt(lim), MULTX10, aParamX8), MULTX6, toBigInt(BR))
361+ else fraction(toBigInt(lim), MULTX10, aParamX8)
359362 let revBX16 = fraction(MULTX16, MULTX16, bParamX16)
360363 toInt(pow(limDivAX8, 8, revBX16, 16, 6, CEILING))
361364 }
362365 $Tuple2(nil, gNsbt)
363366 }
364367
365368
366369
367370 @Callable(i)
368371 func gnsbtInfoINTERNAL (userAddressStrOrEmpty,additionalNsbtToStakeOrZero,additionalSurfToStakeOrZero) = {
369372 let userAddressOrThis = if ((userAddressStrOrEmpty != ""))
370373 then addressFromStringValue(userAddressStrOrEmpty)
371374 else this
372375 let currentPrice = getIntegerValue(controlContract, keyPrice())
373376 let gnsbtFromNsbtDiff = additionalNsbtToStakeOrZero
374377 let gnsbtFromSurfDiff = asInt(invoke(surfStakingContract, "gnsbtFromSurfSYSREADONLY", [additionalSurfToStakeOrZero], nil))
375378 let gNsbtDiff = (gnsbtFromNsbtDiff + gnsbtFromSurfDiff)
376379 let swapParamsTuple = asSwapParamsSTRUCT(invoke(neutrinoContract, "swapParamsByUserSYSREADONLY", [userAddressStrOrEmpty, 0], nil))
380+ let limitMaxTokenUsd = swapParamsTuple._1
377381 let blcks2LmtReset = swapParamsTuple._3
378382 let gnsbtAmt = swapParamsTuple._4
379383 let gnsbtAmtTotal = swapParamsTuple._5
380- let limitMaxWaves = swapParamsTuple._6
381384 let limitMaxUsdn = swapParamsTuple._7
382385 let swapParamsTupleNEW = asSwapParamsSTRUCT(invoke(neutrinoContract, "swapParamsByUserSYSREADONLY", [userAddressStrOrEmpty, gNsbtDiff], nil))
386+ let limitMaxTokenUsdNEW = swapParamsTupleNEW._1
383387 let blcks2LmtResetNEW = swapParamsTupleNEW._3
384388 let gnsbtAmtNEW = swapParamsTupleNEW._4
385389 let gnsbtAmtTotalNEW = swapParamsTupleNEW._5
386- let limitMaxWavesNEW = swapParamsTupleNEW._6
387390 let limitMaxUsdnNEW = swapParamsTupleNEW._7
388391 let nsbtBalance = if ((userAddressStrOrEmpty != ""))
389392 then assetBalance(userAddressOrThis, nsbtAssetId)
390393 else 0
391394 let surfBalance = if ((userAddressStrOrEmpty != ""))
392395 then assetBalance(userAddressOrThis, surfAssetId)
393396 else 0
394397 let nsbtBalanceDiff = if ((additionalNsbtToStakeOrZero >= 0))
395398 then additionalNsbtToStakeOrZero
396399 else {
397400 let nsbtUnstakingData = asAnyList(invoke(nsbtStakingContract, "nsbtUnstakingSYSREADONLY", [userAddressStrOrEmpty, (-1 * additionalNsbtToStakeOrZero)], nil))
398401 let nsbtReceiveAmount = asInt(nsbtUnstakingData[2])
399402 let result = -(nsbtReceiveAmount)
400403 result
401404 }
402405 let nsbtBalanceNew = (nsbtBalance - nsbtBalanceDiff)
403406 let surfBalanceNew = (surfBalance - additionalSurfToStakeOrZero)
404407 let gnsbtData = asAnyList(invoke(gnsbtControllerContract, "gnsbtInfoSYSREADONLY", [userAddressStrOrEmpty, additionalNsbtToStakeOrZero, additionalSurfToStakeOrZero], nil))
405408 let gnsbtUser = asInt(gnsbtData[0])
406409 let gnsbtTotal = asInt(gnsbtData[1])
407410 let nsbtData = asAnyList(gnsbtData[2])
408411 let surfData = asAnyList(gnsbtData[3])
409412 let vpEffectiveHeight = asInt(gnsbtData[4])
410413 let vpEffectiveHeightNEW = asInt(gnsbtData[5])
411414 let gnsbtAmtFromNsbt = asInt(nsbtData[2])
412415 let gnsbtAmtFromSurf = asInt(surfData[2])
413416 let gnsbtAmtFromNsbtNEW = (gnsbtAmtFromNsbt + gnsbtFromNsbtDiff)
414417 let gnsbtAmtFromSurfNEW = (gnsbtAmtFromSurf + gnsbtFromSurfDiff)
415418 let gnsbtFromNsbtTotal = asInt(nsbtData[3])
416419 let gnsbtFromSurfTotal = asInt(surfData[3])
417420 let gnsbtFromSurfActiveTotal = 0
418421 let gnsbtFromSurfFrozenTotal = gnsbtFromSurfTotal
419422 let gnsbtFromNsbtTotalNEW = (gnsbtFromNsbtTotal + gnsbtFromNsbtDiff)
420423 let gnsbtFromSurfTotalNEW = (gnsbtFromSurfTotal + gnsbtFromSurfDiff)
421424 let gnsbtFromSurfFrozenTotalNEW = gnsbtFromSurfTotalNEW
422425 let votingPower = fraction(gnsbtAmtFromNsbt, MULT8, (gnsbtFromNsbtTotal + gnsbtFromSurfActiveTotal))
423426 let votingPowerNew = fraction(gnsbtAmtFromNsbtNEW, MULT8, (gnsbtFromNsbtTotalNEW + gnsbtFromSurfActiveTotal))
424427 let votingPowerMax = fraction((gnsbtAmtFromNsbt + gnsbtAmtFromSurf), MULT8, ((gnsbtFromNsbtTotal + gnsbtFromSurfActiveTotal) + gnsbtFromSurfFrozenTotal))
425428 let votingPowerMaxNew = fraction((gnsbtAmtFromNsbtNEW + gnsbtAmtFromSurfNEW), MULT8, ((gnsbtFromNsbtTotalNEW + gnsbtFromSurfActiveTotal) + gnsbtFromSurfFrozenTotalNEW))
426429 let votingPowerEta = if ((vpEffectiveHeight == 0))
427430 then height
428431 else vpEffectiveHeight
429432 let votingPowerEtaNew = if ((vpEffectiveHeightNEW == 0))
430433 then height
431434 else vpEffectiveHeightNEW
432- $Tuple2(nil, [0, nsbtBalance, surfBalance, nsbtBalanceNew, surfBalanceNew, gnsbtAmtFromNsbt, gnsbtAmtFromSurf, gnsbtAmtFromNsbtNEW, gnsbtAmtFromSurfNEW, gnsbtFromNsbtTotal, gnsbtFromSurfTotal, gnsbtFromNsbtTotalNEW, gnsbtFromSurfTotalNEW, limitMaxUsdn, limitMaxWaves, limitMaxUsdnNEW, limitMaxWavesNEW, blcks2LmtReset, blcks2LmtResetNEW, votingPower, votingPowerNew, votingPowerMax, votingPowerMaxNew, votingPowerEta, votingPowerEtaNew])
435+ $Tuple2(nil, [0, nsbtBalance, surfBalance, nsbtBalanceNew, surfBalanceNew, gnsbtAmtFromNsbt, gnsbtAmtFromSurf, gnsbtAmtFromNsbtNEW, gnsbtAmtFromSurfNEW, gnsbtFromNsbtTotal, gnsbtFromSurfTotal, gnsbtFromNsbtTotalNEW, gnsbtFromSurfTotalNEW, limitMaxUsdn, limitMaxTokenUsd, limitMaxUsdnNEW, limitMaxTokenUsdNEW, blcks2LmtReset, blcks2LmtResetNEW, votingPower, votingPowerNew, votingPowerMax, votingPowerMaxNew, votingPowerEta, votingPowerEtaNew])
433436 }
434437
435438
436439
437440 @Callable(i)
438441 func gnsbtInfoREADONLY (userAddressStrOrEmpty,additionalNsbtToStakeOrZero,additionalSurfToStakeOrZero) = {
439442 let gnsbtInfoDATA = asAnyList(invoke(this, "gnsbtInfoINTERNAL", [userAddressStrOrEmpty, additionalNsbtToStakeOrZero, additionalSurfToStakeOrZero], nil))
440443 $Tuple2(nil, makeString(["%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d", toString(asInt(gnsbtInfoDATA[1])), toString(asInt(gnsbtInfoDATA[2])), toString(asInt(gnsbtInfoDATA[3])), toString(asInt(gnsbtInfoDATA[4])), toString(asInt(gnsbtInfoDATA[5])), toString(asInt(gnsbtInfoDATA[6])), toString(asInt(gnsbtInfoDATA[7])), toString(asInt(gnsbtInfoDATA[8])), toString(asInt(gnsbtInfoDATA[9])), toString(asInt(gnsbtInfoDATA[10])), toString(asInt(gnsbtInfoDATA[11])), toString(asInt(gnsbtInfoDATA[12])), toString(asInt(gnsbtInfoDATA[13])), toString(asInt(gnsbtInfoDATA[14])), toString(asInt(gnsbtInfoDATA[15])), toString(asInt(gnsbtInfoDATA[16])), toString(asInt(gnsbtInfoDATA[17])), toString(asInt(gnsbtInfoDATA[18])), toString(asInt(gnsbtInfoDATA[19])), toString(asInt(gnsbtInfoDATA[20])), toString(asInt(gnsbtInfoDATA[21])), toString(asInt(gnsbtInfoDATA[22])), toString(asInt(gnsbtInfoDATA[23])), toString(asInt(gnsbtInfoDATA[24]))], SEP))
441444 }
442445
443446
444447
445448 @Callable(i)
446449 func gnsbtEffectiveREADONLY (userAddressStrOrEmpty) = {
447450 let gnsbtData = asAnyList(invoke(gnsbtControllerContract, "gnsbtInfoSYSREADONLY", [userAddressStrOrEmpty, 0, 0], nil))
448451 let nsbtData = asAnyList(gnsbtData[2])
449452 let userFromNsbt = asInt(nsbtData[2])
450453 let totalFromNsbt = asInt(nsbtData[3])
451454 let userMatureFromSurf = asInt(gnsbtData[9])
452455 let totalMatureFromSurf = asInt(gnsbtData[6])
453456 $Tuple2(nil, makeString(["%d%d", toString((totalFromNsbt + totalMatureFromSurf)), toString((userFromNsbt + userMatureFromSurf))], SEP))
454457 }
455458
456459
457460
458461 @Callable(i)
459462 func rewardInfoREADONLY (userAddressStrOrEmpty) = {
460463 let rewardsData = asAnyList(invoke(gnsbtControllerContract, "gnsbtRewardsSYSREADONLY", [userAddressStrOrEmpty], nil))
461464 let usdnRewards = asString(invoke(rpdContract, "unclaimedRewardsREADONLY", [userAddressStrOrEmpty], nil))
462465 $Tuple2(nil, makeString(["%s%s%s", asString(rewardsData[0]), asString(rewardsData[1]), usdnRewards], SEP))
463466 }
464467
465468
466469
467470 @Callable(i)
468471 func mergeNsbtREADONLY (userAddressMandatory,newAmount) = {
469472 let nsbtData = asAnyList(invoke(nsbtStakingContract, "nsbtStakingSYSREADONLY", [userAddressMandatory, newAmount], nil))
470473 let amount0 = asInt(nsbtData[0])
471474 let startHeight = if ((0 >= amount0))
472475 then -1
473476 else asInt(nsbtData[2])
474477 let startTimestamp = toTimestamp(startHeight)
475478 let startHeightNew = if ((0 >= newAmount))
476479 then startHeight
477480 else if ((0 >= amount0))
478481 then height
479482 else {
480483 let halfLife = getIntOrFail(nsbtStakingContract, keyHalfLife())
481484 asInt(invoke(mathContract, "mergeStakesREADONLY", [amount0, startHeight, newAmount, height, halfLife], nil))
482485 }
483486 let startTimestampNew = toTimestamp(startHeightNew)
484487 $Tuple2(nil, makeString(["%d%d%d%d", toString(startHeight), toString(startTimestamp), toString(startHeightNew), toString(startTimestampNew)], SEP))
485488 }
486489
487490
488491
489492 @Callable(i)
490493 func swapLimitCalculatorREADONLY (userAddressStrOpt,limitWanted,assetIdStr) = {
491494 let gNsbtCurrent = if ((userAddressStrOpt == ""))
492495 then 0
493496 else asInt(asSwapParamsSTRUCT(invoke(neutrinoContract, "swapParamsByUserSYSREADONLY", [userAddressStrOpt, 0], nil))._4)
494- let limitWantedUsdn = if ((assetIdStr == "WAVES"))
495- then convertWavesToNeutrino(limitWanted, getIntegerValue(controlContract, keyPrice()))
496- else limitWanted
497- let gNsbtNeeded = asInt(invoke(this, "reverseSwapLimitREADONLY", [limitWantedUsdn, (assetIdStr == "WAVES")], nil))
497+ let price = valueOrErrorMessage(getInteger(controlContract, keyPriceByAsset(assetIdStr)), ("No price for asset " + assetIdStr))
498+ let isOutMulti = (assetIdStr == neutrinoAssetIdString)
499+ let limitWantedUsdn = if (isOutMulti)
500+ then limitWanted
501+ else convertTokenToUsd(limitWanted, price)
502+ let gNsbtNeeded = asInt(invoke(this, "reverseSwapLimitREADONLY", [limitWantedUsdn, isOutMulti], nil))
498503 let gNsbtDelta = (gNsbtNeeded - gNsbtCurrent)
499504 $Tuple2(nil, makeString(["%s%s", toString(gNsbtCurrent), toString(gNsbtDelta)], SEP))
500505 }
501506
502507
503508
504509 @Callable(i)
505510 func swapInfoREADONLY (userAddressStrOrEmpty,amount,assetIdStr) = {
506511 let neutrinoMetrics = asAnyList(invoke(mathContract, "calcNeutinoMetricsREADONLY", nil, nil))
507512 let price = asInt(neutrinoMetrics[nMetricIdxPrice])
508513 let swapParamsTuple = asSwapParamsSTRUCT(invoke(neutrinoContract, "swapParamsByUserSYSREADONLY", [userAddressStrOrEmpty, 0], nil))
514+ let limitMaxTokenInUsd = swapParamsTuple._1
509515 let blcks2LmtReset = swapParamsTuple._3
510- let limitMaxWaves = swapParamsTuple._6
511516 let limitMaxUsdn = swapParamsTuple._7
512517 let assetId = fromBase58String(assetIdStr)
513- let swapType = if ((assetId == WAVESID))
514- then "waves"
518+ let basketAssets = valueOrElse(getString(neutrinoContract, basketAssetsKey()), "WAVES")
519+ let swapType = if (contains(basketAssets, assetIdStr))
520+ then "outNeutrino"
515521 else if ((assetId == neutrinoAssetId))
516- then "neutrino"
522+ then "outMulti"
517523 else throw(("Can't swap assetId=" + assetIdStr))
518- let withdrawTuple = asWithdrawResultSTRUCT(invoke(neutrinoContract, "calcWithdrawResultSYSREADONLY", [swapType, amount, price], nil))
524+ let withdrawTuple = asWithdrawResultSTRUCT(invoke(neutrinoContract, "calcWithdrawResultSYSREADONLY", [swapType, amount, price, assetIdStr], nil))
519525 let outNetAmount = withdrawTuple._1
520- let outAssetId = withdrawTuple._2
521526 let outSurfAmt = withdrawTuple._3
522527 let inAmtToSurfPart = withdrawTuple._4
523- let unleaseAmt = withdrawTuple._5
524528 let outFeeAmount = withdrawTuple._6
525529 let outAmtGross = withdrawTuple._7
526530 let withdrawPrice = withdrawTuple._8
527- $Tuple2(nil, makeString(["%d%d%d%d%d%d%d%d", toString(outNetAmount), toString(outSurfAmt), toString(outFeeAmount), toString(withdrawPrice), toString(blcks2LmtReset), toString(limitMaxWaves), toString(limitMaxUsdn), toString(inAmtToSurfPart)], SEP))
531+ $Tuple2(nil, makeString(["%d%d%d%d%d%d%d%d", toString(outNetAmount), toString(outSurfAmt), toString(outFeeAmount), toString(withdrawPrice), toString(blcks2LmtReset), toString(limitMaxTokenInUsd), toString(limitMaxUsdn), toString(inAmtToSurfPart)], SEP))
532+ }
533+
534+
535+
536+@Callable(i)
537+func swapInfoV2READONLY (userAddressStrOrEmpty,amount,assetIdStr) = {
538+ let neutrinoMetrics = asAnyList(invoke(mathContract, "calcNeutinoMetricsREADONLY", nil, nil))
539+ let price = asInt(neutrinoMetrics[nMetricIdxPrice])
540+ let swapParamsTuple = asSwapParamsSTRUCT(invoke(neutrinoContract, "swapParamsByUserSYSREADONLY", [userAddressStrOrEmpty, 0], nil))
541+ let limitMaxTokenInUsd = swapParamsTuple._1
542+ let blcks2LmtReset = swapParamsTuple._3
543+ let limitMaxUsdn = swapParamsTuple._7
544+ let assetId = fromBase58String(assetIdStr)
545+ let basketAssets = valueOrElse(getString(neutrinoContract, basketAssetsKey()), "WAVES")
546+ let swapType = if (contains(basketAssets, assetIdStr))
547+ then "outNeutrino"
548+ else if ((assetId == neutrinoAssetId))
549+ then "outMulti"
550+ else throw(("Can't swap assetId=" + assetIdStr))
551+ let withdrawTuple = asWithdrawResultSTRUCT(invoke(neutrinoContract, "calcWithdrawResultSYSREADONLY", [swapType, amount, price, assetIdStr], nil))
552+ let outNeutrinoInfo = makeString([neutrinoAssetIdString, toString(withdrawTuple._8), toString(withdrawTuple._1), toString(withdrawTuple._6), "1000000"], LISTSEP)
553+ let withdrawBasket = if ((swapType == "outNeutrino"))
554+ then outNeutrinoInfo
555+ else withdrawTuple._9
556+ $Tuple2(nil, makeString_2C(["%d%d%d%s", toString(blcks2LmtReset), toString(limitMaxTokenInUsd), toString(limitMaxUsdn), withdrawBasket], SEP))
557+ }
558+
559+
560+
561+@Callable(i)
562+func basketInfoREADONLY () = {
563+ let neutrinoMetrics = asAnyList(invoke(mathContract, "calcNeutinoMetricsREADONLY", nil, nil))
564+ let basketInfo = asString(neutrinoMetrics[nMetricBasketInfo])
565+ let basket = split_4C(basketInfo, "_")
566+ func modify (acc,item) = {
567+ let parts = split(item, LISTSEP)
568+ let assetId = parts[0]
569+ let dlog6 = valueOrErrorMessage(getInteger(neutrinoContract, basketLogbDeltaKey()), "log(b, delta) key is undefined")
570+ let D6 = valueOrErrorMessage(getInteger(neutrinoContract, basketDKey()), "D key is undefined")
571+ let b6 = valueOrErrorMessage(getInteger(neutrinoContract, basketBKey()), "b key is undefined")
572+ let w6 = valueOrErrorMessage(getInteger(neutrinoContract, basketWeightByAssetKey(assetId)), (("Target weight for asset " + assetId) + " is undefined"))
573+ let p6 = ((dlog6 - w6) + parseIntValue(parts[1]))
574+ let d = (D6 - pow(b6, 6, p6, 6, 6, HALFUP))
575+ (acc :+ makeString(((parts :+ toString(w6)) :+ toString(d)), LISTSEP))
576+ }
577+
578+ let b = {
579+ let $l = basket
580+ let $s = size($l)
581+ let $acc0 = nil
582+ func $f0_1 ($a,$i) = if (($i >= $s))
583+ then $a
584+ else modify($a, $l[$i])
585+
586+ func $f0_2 ($a,$i) = if (($i >= $s))
587+ then $a
588+ else throw("List size exceeds 10")
589+
590+ $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
591+ }
592+ $Tuple2(nil, ("%s__" + makeString_2C(b, "_")))
528593 }
529594
530595
531596
532597 @Callable(i)
533598 func usdnStakingAprREADONLY (days) = {
534599 let tmpDays = 1
535600 let neutrinoMetrics = asAnyList(invoke(mathContract, "calcNeutinoMetricsREADONLY", nil, nil))
536601 let currentPrice = asInt(neutrinoMetrics[nMetricIdxPrice])
537602 let wavesIncome = (0 * MULT8)
538603 let incomeForPeriod = fraction(wavesIncome, currentPrice, MULT8)
539604 let apr = calcApr(rpdContract, tmpDays, incomeForPeriod, MULT6)
540605 $Tuple2(nil, ("%d__" + toString(apr)))
541606 }
542607
543608
544609
545610 @Callable(i)
546611 func surfStakingAprREADONLY (days) = {
547612 let tmpDays = 3
548613 let incomeForPeriod = calcUsdnIncomeForPeriod(surfStakingContract, tmpDays)
549614 let surfPriceToUsdnX6 = 86400
550615 let apr = calcApr(surfStakingContract, tmpDays, incomeForPeriod, surfPriceToUsdnX6)
551616 $Tuple2(nil, ("%d__" + toString(apr)))
552617 }
553618
554619
555620
556621 @Callable(i)
557622 func surfStakingAprV2READONLY (days,surfUsdnPriceX6) = {
558623 let tmpDays = 3
559624 let incomeForPeriod = calcUsdnIncomeForPeriod(surfStakingContract, tmpDays)
560625 let apr = calcApr(surfStakingContract, tmpDays, incomeForPeriod, surfUsdnPriceX6)
561626 $Tuple2(nil, ("%d__" + toString(apr)))
562627 }
563628
564629
565630
566631 @Callable(i)
567632 func nsbtStakingAprREADONLY (days) = {
568633 let tmpDays = 3
569634 let nsbtPriceToUsdnX6 = 8000000
570635 let incomeForPeriod = calcUsdnIncomeForPeriod(nsbtStakingContract, tmpDays)
571636 let apr = calcApr(nsbtStakingContract, tmpDays, incomeForPeriod, nsbtPriceToUsdnX6)
572637 $Tuple2(nil, ("%d__" + toString(apr)))
573638 }
574639
575640
576641
577642 @Callable(i)
578643 func nsbtStakingAprV2READONLY (days,nsbtUsdnPriceX6) = {
579644 let tmpDays = 3
580645 let incomeForPeriod = calcUsdnIncomeForPeriod(nsbtStakingContract, tmpDays)
581646 let apr = calcApr(nsbtStakingContract, tmpDays, incomeForPeriod, nsbtUsdnPriceX6)
582647 $Tuple2(nil, ("%d__" + toString(apr)))
583648 }
584649
585650

github/deemru/w8io/3ef1775 
78.71 ms