tx · AQ4Dq8yYnHsESS1yVgtbL8Wi82HLgq386LihfFiBHd87

3PAhiMXAxNJYs2589bmHMnpMD2B4uAWX9d3:  -0.05000000 Waves

2023.12.15 16:43 [3953781] smart account 3PAhiMXAxNJYs2589bmHMnpMD2B4uAWX9d3 > SELF 0.00000000 Waves

{ "type": 13, "id": "AQ4Dq8yYnHsESS1yVgtbL8Wi82HLgq386LihfFiBHd87", "fee": 5000000, "feeAssetId": null, "timestamp": 1702647686512, "version": 2, "chainId": 87, "sender": "3PAhiMXAxNJYs2589bmHMnpMD2B4uAWX9d3", "senderPublicKey": "FLxkCqoEQggc6HCfKNw8VSprMjHgUSk74eN1Djco3bcw", "proofs": [ "5UWqYKAUcudDEYcqQKEMK2EfekKHbcq4hLFfBBiPsd8jwVPNZQrDymwjjBWkzLNxNF6JFGSXU5JCGBpLcReqNAFv" ], "script": "base64:BgJWCAISCAoGCAgICAgBEgASABIDCgEEEgMKAQQSABIDCgEIEgMKAQESABIDCgEIEgQKAggBEgUKAwgIARIDCgEIEgcKBQgICAEBEgASAwoBCBIFCgMICAhJAAdWRVJTSU9OAg1QWi0xLjAuOCBQUk9EABVBc3NldHNXZWlnaHRzRGVjaW1hbHMABAAFU2NhbGUAkE4ABlNjYWxlOACAwtcvAAdTY2FsZTE2AICAhP6m3uERAAhGZWVTY2FsZQCQTgARUG9vbFRva2VuRGVjaW1hbHMACAAOUG9vbFRva2VuU2NhbGUJAGwGAAoAAAURUG9vbFRva2VuRGVjaW1hbHMAAAAABQZIQUxGVVAAEE1JTl9TVEVQU19BTU9VTlQAAQAQTUFYX1NURVBTX0FNT1VOVAD0AwASTUlOX1NURVBTX0lOVEVSVkFMAAEAEk1BWF9TVEVQU19JTlRFUlZBTACQTgENdHJ5R2V0SW50ZWdlcgEDa2V5BAckbWF0Y2gwCQCaCAIFBHRoaXMFA2tleQMJAAECBQckbWF0Y2gwAgNJbnQEAWIFByRtYXRjaDAFAWIAAAEMdHJ5R2V0QmluYXJ5AQNrZXkEByRtYXRjaDAJAJwIAgUEdGhpcwUDa2V5AwkAAQIFByRtYXRjaDACCkJ5dGVWZWN0b3IEAWIFByRtYXRjaDAFAWIBAAEMdHJ5R2V0U3RyaW5nAQNrZXkEByRtYXRjaDAJAJ0IAgUEdGhpcwUDa2V5AwkAAQIFByRtYXRjaDACBlN0cmluZwQBYgUHJG1hdGNoMAUBYgIAARN0cnlHZXRTdHJpbmdPclRocm93AQNrZXkEByRtYXRjaDAJAJ0IAgUEdGhpcwUDa2V5AwkAAQIFByRtYXRjaDACBlN0cmluZwQBYgUHJG1hdGNoMAUBYgkAAgEJAKwCAgIdbm8gc3VjaCBrZXkgaW4gZGF0YSBzdG9yYWdlOiAFA2tleQEOZ2V0QXNzZXRTdHJpbmcBB2Fzc2V0SWQEByRtYXRjaDAFB2Fzc2V0SWQDCQABAgUHJG1hdGNoMAIKQnl0ZVZlY3RvcgQBYgUHJG1hdGNoMAkA2AQBBQFiAgVXQVZFUwENZ2V0QXNzZXRCeXRlcwEKYXNzZXRJZFN0cgMJAAACBQphc3NldElkU3RyAgVXQVZFUwUEdW5pdAkA2QQBBQphc3NldElkU3RyAQ9nZXRUb2tlbkJhbGFuY2UBB2Fzc2V0SWQEByRtYXRjaDAFB2Fzc2V0SWQDCQABAgUHJG1hdGNoMAIKQnl0ZVZlY3RvcgQBdAUHJG1hdGNoMAkA8AcCBQR0aGlzBQF0CAkA7wcBBQR0aGlzCWF2YWlsYWJsZQETYWRkQXNzZXRCeXRlc1RvTGlzdAIFYWNjdW0EaXRlbQkAzggCBQVhY2N1bQkAzAgCCQENZ2V0QXNzZXRCeXRlcwEFBGl0ZW0FA25pbAEUYWRkQXNzZXRXZWlnaHRUb0xpc3QCBWFjY3VtBGl0ZW0JAM4IAgUFYWNjdW0JAMwIAgkBDXRyeUdldEludGVnZXIBCQCsAgIJAKwCAgIHc3RhdGljXwkBDmdldEFzc2V0U3RyaW5nAQUEaXRlbQIHX3dlaWdodAUDbmlsARdhZGRBc3NldFdlaWdodFRvU3RyTGlzdAIFYWNjdW0EaXRlbQkAzggCBQVhY2N1bQkAzAgCCQCkAwEJAQ10cnlHZXRJbnRlZ2VyAQkArAICCQCsAgICB3N0YXRpY18FBGl0ZW0CB193ZWlnaHQFA25pbAEWYWRkQXNzZXREZWNpbWFsc1RvTGlzdAIFYWNjdW0EaXRlbQkAzggCBQVhY2N1bQkAzAgCCQENdHJ5R2V0SW50ZWdlcgEJAKwCAgkArAICAgdzdGF0aWNfCQEOZ2V0QXNzZXRTdHJpbmcBBQRpdGVtAglfZGVjaW1hbHMFA25pbAETYWRkQXNzZXRTY2FsZVRvTGlzdAIFYWNjdW0EaXRlbQkAzggCBQVhY2N1bQkAzAgCCQENdHJ5R2V0SW50ZWdlcgEJAKwCAgkArAICAgdzdGF0aWNfCQEOZ2V0QXNzZXRTdHJpbmcBBQRpdGVtAgZfc2NhbGUFA25pbAEMYWRkSW50VG9MaXN0AgVhY2N1bQRpdGVtCQDOCAIFBWFjY3VtCQDMCAIJAQ1wYXJzZUludFZhbHVlAQUEaXRlbQUDbmlsAAt1c2RuQXNzZXRJZAEgtiYpwwT1zlORpA5LdSQvZIxRsfrfr1QpvUjSHSqyqtEADXB1enpsZUFzc2V0SWQBIPEa/iX+9pk49GkqxN/hEtZHssbKDro3Ca93bR+OouVjAAt1c2R0QXNzZXRJZAEgHpQHE1J2oSWV/chhqIJfEH/fOk8pu/yaRj9a/TZPn5EADnVzZHRQcHRBc3NldElkASCE2nqyCAM/TtG7yo7ui5O8yYLdC136B5ao1CP5qA//uQAMd2F2ZXNBc3NldElkBQR1bml0AA51c2RuQXNzZXRJZFN0cgIsREcyeEZrUGREd0tVb0JrekdBaFF0THBTR3pmWExpQ1lQRXplS0gyQWQyNHAAEHB1enpsZUFzc2V0SWRTdHICLEhFQjhRYXc5eHJXcFdzOHRIc2lBVFlHQldEQnRQMlM3a2NQQUxyTXU0M0FTAA51c2R0QXNzZXRJZFN0cgIsMzROOVljRUVUTFduOTNxWVE2NEVzUDF4ODl0U3J1SlU0NFJyRU1TWFhFUEoAEXVzZHRQcHRBc3NldElkU3RyAiw5d2MzTFhOQTRURUJzWHlLdG9MRTltcmJERDdXTUhYdlhyQ2padmFiTEFzaQAPd2F2ZXNBc3NldElkU3RyAgVXQVZFUwAVc3VwcG9ydGVkRmVlQXNzZXRzU3RyCQDMCAICLERHMnhGa1BkRHdLVW9Ca3pHQWhRdExwU0d6ZlhMaUNZUEV6ZUtIMkFkMjRwCQDMCAICLEhFQjhRYXc5eHJXcFdzOHRIc2lBVFlHQldEQnRQMlM3a2NQQUxyTXU0M0FTCQDMCAICLDM0TjlZY0VFVExXbjkzcVlRNjRFc1AxeDg5dFNydUpVNDRSckVNU1hYRVBKCQDMCAICLDl3YzNMWE5BNFRFQnNYeUt0b0xFOW1yYkREN1dNSFh2WHJDalp2YWJMQXNpCQDMCAICBVdBVkVTBQNuaWwADG1hc3RlclB1YktleQEgOzVNbj+fvvhUnJZEB4BWqy/iE2BFxHvyPxdD9EIFJl0AEXBhcmVudFBvb2xBZGRyZXNzCQEHQWRkcmVzcwEBGgFXkcbqKep5Zw/ZhO8ydpSzwHVC5DWDwdNYAA1tYXN0ZXJBZGRyZXNzCQEHQWRkcmVzcwEBGgFXzlfzJNEHpLNO/tK64iisxZCW1orRbQXuAA1vcmFjbGVBZGRyZXNzCQEHQWRkcmVzcwEBGgFXSWbQy/OK9Vd6rfwhb3HFW4mIK9CBs7F/AA5zdGFraW5nQWRkcmVzcwkBB0FkZHJlc3MBARoBV5RojPnuormqn9b1jrypj2canAb0FimJuwALZmVlc0FkZHJlc3MJAQdBZGRyZXNzAQEaAVce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AgIJAKwCAgIHZ2xvYmFsXwUKdG9rZW5JZFN0cgIIX2JhbGFuY2UBCGdldEtNdWx0AAQHJG1hdGNoMAkAnwgBAgxzdGF0aWNfS011bHQDCQABAgUHJG1hdGNoMAIDSW50BAF4BQckbWF0Y2gwBQF4BQdTY2FsZTE2ARJzYXZlQ3VycmVudFdlaWdodHMABAphc3NldElkc0xpCQC1CQIJAQx0cnlHZXRTdHJpbmcBAg9zdGF0aWNfdG9rZW5JZHMCASwKAQFzAgVhY2N1bQdhc3NldElkCQDOCAIFBWFjY3VtCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQCsAgICFnJlYmFsYW5jZV9zdGFydFdlaWdodF8FB2Fzc2V0SWQJAQ10cnlHZXRJbnRlZ2VyAQkArAICCQCsAgICB3N0YXRpY18FB2Fzc2V0SWQCB193ZWlnaHQFA25pbAoAAiRsBQphc3NldElkc0xpCgACJHMJAJADAQUCJGwKAAUkYWNjMAUDbmlsCgEFJGY0XzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAQFzAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGY0XzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhRMaXN0IHNpemUgZXhjZWVkcyAxMAkBBSRmNF8yAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgUFJGFjYzAAAAABAAIAAwAEAAUABgAHAAgACQAKARlnZXRWaXJ0dWFsUG9vbFRva2VuQW1vdW50AAkAawMJAQ10cnlHZXRJbnRlZ2VyAQIXZ2xvYmFsX3Bvb2xUb2tlbl9hbW91bnQJAQhnZXRLTXVsdAAFB1NjYWxlMTYBEGNhbGN1bGF0ZVBJc3N1ZWQCBmFtb3VudAd0b2tlbklkBAdQc3VwcGx5CQEZZ2V0VmlydHVhbFBvb2xUb2tlbkFtb3VudAAEB0JhbGFuY2UJAQ10cnlHZXRJbnRlZ2VyAQkArAICCQCsAgICB2dsb2JhbF8JAQ5nZXRBc3NldFN0cmluZwEFB3Rva2VuSWQCCF9iYWxhbmNlBAJ0MQkAbgQFBmFtb3VudAUHUHN1cHBseQUHQmFsYW5jZQUERE9XTgUCdDEBDWdldE1pblBJc3N1ZWQBCHBheW1lbnRzCgEHaGFuZGxlcgIFYWNjdW0HY3VycmVudAQHUElzc3VlZAkBEGNhbGN1bGF0ZVBJc3N1ZWQCCAUHY3VycmVudAZhbW91bnQIBQdjdXJyZW50B2Fzc2V0SWQDCQAAAgUHUElzc3VlZAAACQACAQIkb25lIG9mIHRoZSB0b2tlbnMgYW1vdW50cyBpcyB0b28gbG93AwMJAAACBQVhY2N1bQAABgkAZgIFBWFjY3VtBQdQSXNzdWVkBQdQSXNzdWVkBQVhY2N1bQQJbWluUElzc2VkCgACJGwFCHBheW1lbnRzCgACJHMJAJADAQUCJGwKAAUkYWNjMAAACgEFJGY0XzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAQdoYW5kbGVyAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGY0XzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhRMaXN0IHNpemUgZXhjZWVkcyAxMAkBBSRmNF8yAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgUFJGFjYzAAAAABAAIAAwAEAAUABgAHAAgACQAKBQltaW5QSXNzZWQBEmNhbGN1bGF0ZVVzZG5WYWx1ZQQHYXNzZXRJZAZhbW91bnQIYUJhbGFuY2UQZ2l2ZW5Vc2RuQmFsYW5jZQQKdXNkbkluUG9vbAkAzwgCBQhhc3NldElkcwULdXNkbkFzc2V0SWQEDHB1enpsZUluUG9vbAkAzwgCBQhhc3NldElkcwUNcHV6emxlQXNzZXRJZAQKdXNkdEluUG9vbAkAzwgCBQhhc3NldElkcwULdXNkdEFzc2V0SWQEDXVzZHRQcHRJblBvb2wJAM8IAgUIYXNzZXRJZHMFDnVzZHRQcHRBc3NldElkBAt3YXZlc0luUG9vbAkAzwgCBQhhc3NldElkcwUEdW5pdAQLYXNzZXRXZWlnaHQJAQ10cnlHZXRJbnRlZ2VyAQkArAICCQCsAgICB3N0YXRpY18JAQ5nZXRBc3NldFN0cmluZwEFB2Fzc2V0SWQCB193ZWlnaHQEC2ZlZUFzc2V0U3RyCQEMdHJ5R2V0U3RyaW5nAQIPc3RhdGljX2ZlZVRva2VuAwkAAAIFC2ZlZUFzc2V0U3RyBRBwdXp6bGVBc3NldElkU3RyBAxwdXp6bGVXZWlnaHQJAJEDAgUNQXNzZXRzV2VpZ2h0cwkBBXZhbHVlAQkAzwgCBQhhc3NldElkcwUNcHV6emxlQXNzZXRJZAQNcHV6emxlQmFsYW5jZQkBDXRyeUdldEludGVnZXIBCQCsAgIJAKwCAgIHZ2xvYmFsXwUQcHV6emxlQXNzZXRJZFN0cgIIX2JhbGFuY2UEDmFtb3VudEluUHV6emxlCQBrAwUGYW1vdW50CQBpAgUNcHV6emxlQmFsYW5jZQUMcHV6emxlV2VpZ2h0CQBpAgUIYUJhbGFuY2UFC2Fzc2V0V2VpZ2h0BAtwdXp6bGVQcmljZQkBEUBleHRyTmF0aXZlKDEwNTApAgURcGFyZW50UG9vbEFkZHJlc3MCFmdsb2JhbF9sYXN0UHV6emxlUHJpY2UJAGsDCQBoAgUOYW1vdW50SW5QdXp6bGUFC3B1enpsZVByaWNlAAEFBlNjYWxlOAMJAAACBQtmZWVBc3NldFN0cgUOdXNkdEFzc2V0SWRTdHIECnVzZHRXZWlnaHQJAJEDAgUNQXNzZXRzV2VpZ2h0cwkBBXZhbHVlAQUKdXNkdEluUG9vbAQLdXNkdEJhbGFuY2UJAQ10cnlHZXRJbnRlZ2VyAQkArAICCQCsAgICB2dsb2JhbF8FDnVzZHRBc3NldElkU3RyAghfYmFsYW5jZQkAawMFBmFtb3VudAkAaQIFC3VzZHRCYWxhbmNlBQp1c2R0V2VpZ2h0CQBpAgUIYUJhbGFuY2UFC2Fzc2V0V2VpZ2h0AwkAAAIFC2ZlZUFzc2V0U3RyBRF1c2R0UHB0QXNzZXRJZFN0cgQKdXNkdFdlaWdodAkAkQMCBQ1Bc3NldHNXZWlnaHRzCQEFdmFsdWUBBQ11c2R0UHB0SW5Qb29sBAt1c2R0QmFsYW5jZQkBDXRyeUdldEludGVnZXIBCQCsAgIJAKwCAgIHZ2xvYmFsXwURdXNkdFBwdEFzc2V0SWRTdHICCF9iYWxhbmNlCQBrAwUGYW1vdW50CQBpAgULdXNkdEJhbGFuY2UFCnVzZHRXZWlnaHQJAGkCBQhhQmFsYW5jZQULYXNzZXRXZWlnaHQDCQAAAgULZmVlQXNzZXRTdHIFDnVzZG5Bc3NldElkU3RyBAp1c2RuV2VpZ2h0CQCRAwIFDUFzc2V0c1dlaWdodHMJAQV2YWx1ZQEJAM8IAgUIYXNzZXRJZHMFC3VzZG5Bc3NldElkBAt1c2RuQmFsYW5jZQQHJG1hdGNoMAUQZ2l2ZW5Vc2RuQmFsYW5jZQMJAAECBQckbWF0Y2gwAgNJbnQEAXgFByRtYXRjaDAFEGdpdmVuVXNkbkJhbGFuY2UJAQ10cnlHZXRJbnRlZ2VyAQkArAICCQCsAgICB2dsb2JhbF8JAQ5nZXRBc3NldFN0cmluZwEFC3VzZG5Bc3NldElkAghfYmFsYW5jZQkAawMFBmFtb3VudAkAaQIJAQV2YWx1ZQEFC3VzZG5CYWxhbmNlBQp1c2RuV2VpZ2h0CQBpAgUIYUJhbGFuY2UFC2Fzc2V0V2VpZ2h0BAt3YXZlc1dlaWdodAC4FwQId0JhbGFuY2UJAGkCCQENdHJ5R2V0SW50ZWdlcgECFGdsb2JhbF9XQVZFU19iYWxhbmNlADIJAGsDBQZhbW91bnQJAGkCBQh3QmFsYW5jZQULd2F2ZXNXZWlnaHQJAGkCBQhhQmFsYW5jZQULYXNzZXRXZWlnaHQBEmdldFByaWNlRnJvbU9yYWNsZQEKYXNzZXRJZFN0cgQHJG1hdGNoMAkAmggCBQ1vcmFjbGVBZGRyZXNzCQCsAgIFCmFzc2V0SWRTdHICB190d2FwNUIDCQABAgUHJG1hdGNoMAIDSW50BAF4BQckbWF0Y2gwBQF4AAABEWNhbGN1bGF0ZVVzZFZhbHVlAwdhc3NldElkBmFtb3VudAhhQmFsYW5jZQQLYXNzZXRXZWlnaHQJAQ10cnlHZXRJbnRlZ2VyAQkArAICCQCsAgICB3N0YXRpY18JAQ5nZXRBc3NldFN0cmluZwEFB2Fzc2V0SWQCB193ZWlnaHQEC2ZlZUFzc2V0U3RyCQEMdHJ5R2V0U3RyaW5nAQIPc3RhdGljX2ZlZVRva2VuBA1mZWVBc3NldFNjYWxlCQERQGV4dHJOYXRpdmUoMTA1MCkCBQR0aGlzCQCsAgIJAKwCAgIHc3RhdGljXwULZmVlQXNzZXRTdHICBl9zY2FsZQQLZmVlQXNzZXROdW0JAQV2YWx1ZQEJAM8IAgUIYXNzZXRJZHMJAQ1nZXRBc3NldEJ5dGVzAQULZmVlQXNzZXRTdHIEDmZlZUFzc2V0V2VpZ2h0CQCRAwIFDUFzc2V0c1dlaWdodHMFC2ZlZUFzc2V0TnVtBA9mZWVBc3NldEJhbGFuY2UJAQ10cnlHZXRJbnRlZ2VyAQkArAICCQCsAgICB2dsb2JhbF8FC2ZlZUFzc2V0U3RyAghfYmFsYW5jZQQNdmFsSW5GZWVBc3NldAkAawMFBmFtb3VudAkAaQIFD2ZlZUFzc2V0QmFsYW5jZQUOZmVlQXNzZXRXZWlnaHQJAGkCBQhhQmFsYW5jZQULYXNzZXRXZWlnaHQEDWZlZUFzc2V0UHJpY2UJARJnZXRQcmljZUZyb21PcmFjbGUBBQtmZWVBc3NldFN0cgkAawMFDXZhbEluRmVlQXNzZXQFDWZlZUFzc2V0UHJpY2UFDWZlZUFzc2V0U2NhbGUBE2NoZWNrVG9rZW5zVmFsaWRpdHkBCHBheW1lbnRzCgEIaGFuZGxlcjECBWFjY3VtB3BheW1lbnQJAM4IAgUFYWNjdW0JAMwIAggFB3BheW1lbnQHYXNzZXRJZAUDbmlsBANpZHMKAAIkbAUIcGF5bWVudHMKAAIkcwkAkAMBBQIkbAoABSRhY2MwBQNuaWwKAQUkZjRfMQICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkBCGhhbmRsZXIxAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGY0XzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhRMaXN0IHNpemUgZXhjZWVkcyAxMAkBBSRmNF8yAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgUFJGFjYzAAAAABAAIAAwAEAAUABgAHAAgACQAKAwkAAAIFA2lkcwUDaWRzCgEIaGFuZGxlcjICBWFjY3VtB2Fzc2V0SWQDCQECIT0CCQDPCAIFA2lkcwUHYXNzZXRJZAUEdW5pdAkAZAIFBWFjY3VtAAEJAAIBCQCsAgICFGFzc2V0IG5vdCBhdHRhY2hlZDogCQEOZ2V0QXNzZXRTdHJpbmcBBQdhc3NldElkBAZjaGVja3MKAAIkbAUIYXNzZXRJZHMKAAIkcwkAkAMBBQIkbAoABSRhY2MwAAAKAQUkZjVfMQICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkBCGhhbmRsZXIyAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGY1XzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhRMaXN0IHNpemUgZXhjZWVkcyAxMAkBBSRmNV8yAgkBBSRmNV8xAgkBBSRmNV8xAgkBBSRmNV8xAgkBBSRmNV8xAgkBBSRmNV8xAgkBBSRmNV8xAgkBBSRmNV8xAgkBBSRmNV8xAgkBBSRmNV8xAgkBBSRmNV8xAgUFJGFjYzAAAAABAAIAAwAEAAUABgAHAAgACQAKAwkAAAIFBmNoZWNrcwUGY2hlY2tzBgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgETaGFuZGxlUG9vbFRva2Vuc0FkZAQHUElzc3VlZAhwYXltZW50cwt1c2VyQWRkcmVzcwpuZWVkQ2hhbmdlCgEVZ2V0VG9rZW5QYXltZW50QW1vdW50AQd0b2tlbklkCgEHaGFuZGxlcgIFYWNjdW0HcGF5bWVudAMJAAACCAUHcGF5bWVudAdhc3NldElkBQd0b2tlbklkCAUHcGF5bWVudAZhbW91bnQFBWFjY3VtCgACJGwFCHBheW1lbnRzCgACJHMJAJADAQUCJGwKAAUkYWNjMAAACgEFJGY0XzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAQdoYW5kbGVyAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGY0XzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhRMaXN0IHNpemUgZXhjZWVkcyAxMAkBBSRmNF8yAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgUFJGFjYzAAAAABAAIAAwAEAAUABgAHAAgACQAKCgERaGFuZGxlVG9rZW5DaGFuZ2UCBWFjY3VtB3Rva2VuSWQEAkJrCQENdHJ5R2V0SW50ZWdlcgEJAKwCAgkArAICAgdnbG9iYWxfCQEOZ2V0QXNzZXRTdHJpbmcBBQd0b2tlbklkAghfYmFsYW5jZQQHUFN1cHBseQkBGWdldFZpcnR1YWxQb29sVG9rZW5BbW91bnQABA10b2tlbkRlY2ltYWxzCQENdHJ5R2V0SW50ZWdlcgEJAKwCAgkArAICAgdzdGF0aWNfCQEOZ2V0QXNzZXRTdHJpbmcBBQd0b2tlbklkAgZfc2NhbGUEAmExCQC9AgQJALkCAgkAtgIBCQBkAgUHUFN1cHBseQUHUElzc3VlZAkAtgIBBQZTY2FsZTgJALYCAQUNdG9rZW5EZWNpbWFscwkAtgIBBQdQU3VwcGx5BQdDRUlMSU5HBAJEawkAoAMBCQC9AgQJALgCAgUCYTEJALkCAgkAtgIBBQ10b2tlbkRlY2ltYWxzCQC2AgEFBlNjYWxlOAkAtgIBBQJCawkAuQICCQC2AgEFDXRva2VuRGVjaW1hbHMJALYCAQUGU2NhbGU4BQdDRUlMSU5HBA1wYXltZW50QW1vdW50CQEVZ2V0VG9rZW5QYXltZW50QW1vdW50AQUHdG9rZW5JZAQIdG9SZXR1cm4JAGUCBQ1wYXltZW50QW1vdW50BQJEawQBdAMDBQpuZWVkQ2hhbmdlCQBmAgUIdG9SZXR1cm4AAAcJAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwULdXNlckFkZHJlc3MFCHRvUmV0dXJuBQd0b2tlbklkBQNuaWwFA25pbAkAzggCCQDOCAIFBWFjY3VtBQF0CQDMCAIJAQxJbnRlZ2VyRW50cnkCCQCsAgIJAKwCAgIHZ2xvYmFsXwkBDmdldEFzc2V0U3RyaW5nAQUHdG9rZW5JZAIIX2JhbGFuY2UJAGQCBQJCawUCRGsFA25pbAoAAiRsBQhhc3NldElkcwoAAiRzCQCQAwEFAiRsCgAFJGFjYzAFA25pbAoBBSRmNF8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQERaGFuZGxlVG9rZW5DaGFuZ2UCBQIkYQkAkQMCBQIkbAUCJGkKAQUkZjRfMgICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkAAgECFExpc3Qgc2l6ZSBleGNlZWRzIDEwCQEFJGY0XzICCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECBQUkYWNjMAAAAAEAAgADAAQABQAGAAcACAAJAAoBFmhhbmRsZVBvb2xUb2tlbnNSZWRlZW0CCVBSZWRlZW1lZAt1c2VyQWRkcmVzcwoBEWhhbmRsZVRva2VuUmVkZWVtAgVhY2N1bQd0b2tlbklkBAJCawkBDXRyeUdldEludGVnZXIBCQCsAgIJAKwCAgIHZ2xvYmFsXwkBDmdldEFzc2V0U3RyaW5nAQUHdG9rZW5JZAIIX2JhbGFuY2UEB1BTdXBwbHkJARlnZXRWaXJ0dWFsUG9vbFRva2VuQW1vdW50AAQNdG9rZW5EZWNpbWFscwkBDXRyeUdldEludGVnZXIBCQCsAgIJAKwCAgIHc3RhdGljXwkBDmdldEFzc2V0U3RyaW5nAQUHdG9rZW5JZAIGX3NjYWxlBAZwc3VwcGwJAL0CBAkAuQICCQC2AgEJAGUCBQdQU3VwcGx5BQlQUmVkZWVtZWQJALYCAQUGU2NhbGU4CQC2AgEFBlNjYWxlOAkAtgIBBQdQU3VwcGx5BQRET1dOBAZhbW91bnQJAKADAQkAvQIECQC4AgIJALYCAQUHU2NhbGUxNgUGcHN1cHBsCQC2AgEFAkJrCQC2AgEFB1NjYWxlMTYFB0NFSUxJTkcJAM4IAgUFYWNjdW0JAMwIAgkBDEludGVnZXJFbnRyeQIJAKwCAgkArAICAgdnbG9iYWxfCQEOZ2V0QXNzZXRTdHJpbmcBBQd0b2tlbklkAghfYmFsYW5jZQkAZQIFAkJrBQZhbW91bnQJAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwULdXNlckFkZHJlc3MFBmFtb3VudAUHdG9rZW5JZAUDbmlsCgACJGwFCGFzc2V0SWRzCgACJHMJAJADAQUCJGwKAAUkYWNjMAUDbmlsCgEFJGY0XzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJARFoYW5kbGVUb2tlblJlZGVlbQIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmNF8yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQIUTGlzdCBzaXplIGV4Y2VlZHMgMTAJAQUkZjRfMgIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYABwAIAAkACgESY2FsY3VsYXRlT3V0QW1vdW50BQhBbW91bnRJbgdhc3NldEluCGFzc2V0T3V0CUJhbGFuY2VJbgpCYWxhbmNlT3V0BAdJbmRleEluCQEFdmFsdWUBCQDPCAIFCGFzc2V0SWRzBQdhc3NldEluBAhJbmRleE91dAkBBXZhbHVlAQkAzwgCBQhhc3NldElkcwUIYXNzZXRPdXQDCQAAAgUHSW5kZXhJbgUISW5kZXhPdXQFCEFtb3VudEluCQBuBAUKQmFsYW5jZU91dAkAZQIJAGgCBQZTY2FsZTgFBlNjYWxlOAkAoAMBCQB2BgkAvQIECQC2AgEJAGgCBQlCYWxhbmNlSW4AkE4JALYCAQkAaAIFBlNjYWxlOAUGU2NhbGU4CQC2AgEJAGgCCQBkAgUJQmFsYW5jZUluBQhBbW91bnRJbgCQTgUGSEFMRlVQABAJALYCAQkAawMJAJEDAgUNQXNzZXRzV2VpZ2h0cwUHSW5kZXhJbgCAoJSljR0JAJEDAgUNQXNzZXRzV2VpZ2h0cwUISW5kZXhPdXQADAAQBQdDRUlMSU5HCQBoAgUGU2NhbGU4BQZTY2FsZTgFCEhBTEZFVkVOAR1jYWxjdWxhdGVDdXJyZW50QXNzZXRJbnRlcmVzdAQHYXNzZXRJZAphc3NldElkU3RyCGFCYWxhbmNlFnRva2VuRWFybmluZ3NMYXN0Q2hlY2sEC3RvdGFsU3Rha2VkCQENdHJ5R2V0SW50ZWdlcgECEmdsb2JhbF9pbmRleFN0YWtlZAQVdG9rZW5CYWxhbmNlTGFzdENoZWNrBRZ0b2tlbkVhcm5pbmdzTGFzdENoZWNrBBNjdXJyZW50QmFsYW5jZURlbHRhCQBlAgkBD2dldFRva2VuQmFsYW5jZQEFB2Fzc2V0SWQFCGFCYWxhbmNlBBRjdXJyZW50VG9rZW5FYXJuaW5ncwMJAGYCBRNjdXJyZW50QmFsYW5jZURlbHRhBRV0b2tlbkJhbGFuY2VMYXN0Q2hlY2sFE2N1cnJlbnRCYWxhbmNlRGVsdGEFFXRva2VuQmFsYW5jZUxhc3RDaGVjawQLbmV3RWFybmluZ3MJAGUCBRRjdXJyZW50VG9rZW5FYXJuaW5ncwUVdG9rZW5CYWxhbmNlTGFzdENoZWNrBAtuZXdJbnRlcmVzdAMJAAACBQt0b3RhbFN0YWtlZAAAAAAJAGsDBQtuZXdFYXJuaW5ncwUGU2NhbGU4BQt0b3RhbFN0YWtlZAQRbGFzdENoZWNrSW50ZXJlc3QJAQ10cnlHZXRJbnRlZ2VyAQkArAICCQCsAgICEWdsb2JhbF9sYXN0Q2hlY2tfBQphc3NldElkU3RyAglfaW50ZXJlc3QJAGQCBRFsYXN0Q2hlY2tJbnRlcmVzdAULbmV3SW50ZXJlc3QBC2NsYWltUmVzdWx0AQdhZGRyZXNzBAphZGRyZXNzU3RyCQClCAEFB2FkZHJlc3MEDHB1enpsZUFtb3VudAkBDXRyeUdldEludGVnZXIBCQCsAgIFCmFkZHJlc3NTdHICDF9pbmRleFN0YWtlZAoBB2hhbmRsZXICBWFjY3VtB2Fzc2V0SWQECmFzc2V0SWRTdHIJAQ5nZXRBc3NldFN0cmluZwEFB2Fzc2V0SWQECGFCYWxhbmNlCQENdHJ5R2V0SW50ZWdlcgEJAKwCAgkArAICAgdnbG9iYWxfCQEOZ2V0QXNzZXRTdHJpbmcBBQdhc3NldElkAghfYmFsYW5jZQQWdG9rZW5FYXJuaW5nc0xhc3RDaGVjawkBDXRyeUdldEludGVnZXIBCQCsAgIJAKwCAgIRZ2xvYmFsX2xhc3RDaGVja18FCmFzc2V0SWRTdHICCV9lYXJuaW5ncwQUY3VycmVudFRva2VuSW50ZXJlc3QJAR1jYWxjdWxhdGVDdXJyZW50QXNzZXRJbnRlcmVzdAQFB2Fzc2V0SWQFCmFzc2V0SWRTdHIFCGFCYWxhbmNlBRZ0b2tlbkVhcm5pbmdzTGFzdENoZWNrBBRjdXJyZW50VG9rZW5FYXJuaW5ncwkAlgMBCQDMCAIFFnRva2VuRWFybmluZ3NMYXN0Q2hlY2sJAMwIAgkAZQIJAQ9nZXRUb2tlbkJhbGFuY2UBBQdhc3NldElkBQhhQmFsYW5jZQUDbmlsBAxyZXdhcmRBbW91bnQJAGsDBQxwdXp6bGVBbW91bnQJAGUCBRRjdXJyZW50VG9rZW5JbnRlcmVzdAkBDXRyeUdldEludGVnZXIBCQCsAgIJAKwCAgkArAICBQphZGRyZXNzU3RyAgtfbGFzdENoZWNrXwUKYXNzZXRJZFN0cgIJX2ludGVyZXN0BQZTY2FsZTgECHRyYW5zZmVyAwkAAAIFDHJld2FyZEFtb3VudAAABQNuaWwJAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwUHYWRkcmVzcwUMcmV3YXJkQW1vdW50BQdhc3NldElkBQNuaWwJAJQKAgkAzggCCQDOCAIIBQVhY2N1bQJfMQUIdHJhbnNmZXIJAMwIAgkBDEludGVnZXJFbnRyeQIJAKwCAgkArAICAhFnbG9iYWxfbGFzdENoZWNrXwUKYXNzZXRJZFN0cgIJX2Vhcm5pbmdzCQBlAgUUY3VycmVudFRva2VuRWFybmluZ3MFDHJld2FyZEFtb3VudAkAzAgCCQEMSW50ZWdlckVudHJ5AgkArAICCQCsAgICEWdsb2JhbF9sYXN0Q2hlY2tfBQphc3NldElkU3RyAglfaW50ZXJlc3QFFGN1cnJlbnRUb2tlbkludGVyZXN0CQDMCAIJAQxJbnRlZ2VyRW50cnkCCQCsAgIJAKwCAgkArAICBQphZGRyZXNzU3RyAgtfbGFzdENoZWNrXwUKYXNzZXRJZFN0cgIJX2ludGVyZXN0BRRjdXJyZW50VG9rZW5JbnRlcmVzdAUDbmlsCQBkAggFBWFjY3VtAl8yCQERY2FsY3VsYXRlVXNkVmFsdWUDBQdhc3NldElkBQxyZXdhcmRBbW91bnQFCGFCYWxhbmNlBAVhY2N1bQoAAiRsBQxlYXJuZWRBc3NldHMKAAIkcwkAkAMBBQIkbAoABSRhY2MwCQCUCgIFA25pbAAACgEFJGY0XzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAQdoYW5kbGVyAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGY0XzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhRMaXN0IHNpemUgZXhjZWVkcyAxMAkBBSRmNF8yAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgUFJGFjYzAAAAABAAIAAwAEAAUABgAHAAgACQAKCQCUCgIJAM4IAggFBWFjY3VtAl8xCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQCsAgIFCmFkZHJlc3NTdHICE19jbGFpbWVkUmV3YXJkVmFsdWUJAGQCCQENdHJ5R2V0SW50ZWdlcgEJAKwCAgUKYWRkcmVzc1N0cgITX2NsYWltZWRSZXdhcmRWYWx1ZQgFBWFjY3VtAl8yCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQCsAgIFCmFkZHJlc3NTdHICCl9sYXN0Q2xhaW0IBQlsYXN0QmxvY2sJdGltZXN0YW1wBQNuaWwIBQVhY2N1bQJfMgEQaW5kZXhTdGFrZVJlc3VsdAIKYWRkcmVzc1N0cgZhbW91bnQEAmxpCAkBC2NsYWltUmVzdWx0AQkBEUBleHRyTmF0aXZlKDEwNjIpAQUKYWRkcmVzc1N0cgJfMQkAzggCBQJsaQkAzAgCCQEMSW50ZWdlckVudHJ5AgkArAICBQphZGRyZXNzU3RyAgxfaW5kZXhTdGFrZWQJAGQCCQENdHJ5R2V0SW50ZWdlcgEJAKwCAgUKYWRkcmVzc1N0cgIMX2luZGV4U3Rha2VkBQZhbW91bnQJAMwIAgkBDEludGVnZXJFbnRyeQICEmdsb2JhbF9pbmRleFN0YWtlZAkAZAIJAQ10cnlHZXRJbnRlZ2VyAQISZ2xvYmFsX2luZGV4U3Rha2VkBQZhbW91bnQFA25pbAEDc3VtAgVhY2N1bQFuCQBkAgUFYWNjdW0JAQ1wYXJzZUludFZhbHVlAQUBbgENY2hlY2tGZWVBc3NldAIFYWNjdW0EbmV4dAMDCQECIT0CCQDPCAIFFXN1cHBvcnRlZEZlZUFzc2V0c1N0cgUEbmV4dAUEdW5pdAkAAAIFBWFjY3VtAgAHBQRuZXh0BQVhY2N1bQESZ2V0VG1wUmViYWxhbmNlSWRzAQ1uZXdBc3NldElkc0xpBBFjdXJyZW50QXNzZXRJZHNMaQkAtQkCCQEMdHJ5R2V0U3RyaW5nAQIPc3RhdGljX3Rva2VuSWRzAgEsBAZyZXN1bHQFDW5ld0Fzc2V0SWRzTGkKAQFmAgVhY2N1bQdhc3NldElkAwkAAAIJAM8IAgUGcmVzdWx0BQdhc3NldElkBQR1bml0CQDOCAIFBWFj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VG9rZW5JZFN0cgkAzAgCCQELU3RyaW5nRW50cnkCAhBzdGF0aWNfcG9vbE93bmVyBQlwb29sT3duZXIJAMwIAgkBDEludGVnZXJFbnRyeQICCnN0YXRpY19mZWUFA2ZlZQkAzAgCCQEMSW50ZWdlckVudHJ5AgIMc3RhdGljX0tNdWx0BQdTY2FsZTE2BQNuaWwBaQEGZGVJbml0AAMJAQppc1NodXRkb3duAAkAAgECE2NvbnRyYWN0IGlzIG9uIHN0b3ADCQECIT0CCAUBaQZjYWxsZXIFBHRoaXMJAAIBAgphZG1pbiBvbmx5CQDMCAIJAQxJbnRlZ2VyRW50cnkCAhBnbG9iYWxfd2FzSW5pdGVkAAAFA25pbAFpAQRpbml0AAoBC3ByZXBhcmVMaXN0AAoBB2hhbmRsZXICBWFjY3VtAW4JAM4IAgUFYWNjdW0JAMwIAgkBDEludGVnZXJFbnRyeQIJAKwCAgkArAICAgdnbG9iYWxfCQEOZ2V0QXNzZXRTdHJpbmcBCAUBbgdhc3NldElkAghfYmFsYW5jZQgFAW4GYW1vdW50BQNuaWwKAAIkbAgFAWkIcGF5bWVudHMKAAIkcwkAkAMBBQIkbAoABSRhY2MwBQNuaWwKAQUkZjRfMQICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkBB2hhbmRsZXICBQIkYQkAkQMCBQIkbAUCJGkKAQUkZjRfMgICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkAAgECFExpc3Qgc2l6ZSBleGNlZWRzIDEwCQEFJGY0XzICCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECBQUkYWNjMAAAAAEAAgADAAQABQAGAAcACAAJAAoKARljYWxjdWxhdGVQb29sVG9rZW5zQW1vdW50AQhwYXltZW50cwoBB2hhbmRsZXICBWFjY3VtA3BtdAQHYXNzZXRJZAgFA3BtdAdhc3NldElkCgEIaGFuZGxlcjICBWFjY3VtAW4DCQAAAgUBbgUHYXNzZXRJZAkBBXZhbHVlAQkAzwgCBQhhc3NldElkcwUBbgUFYWNjdW0EBVRva2VuCgACJGwFCGFzc2V0SWRzCgACJHMJAJADAQUCJGwKAAUkYWNjMAABCgEFJGY0XzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAQhoYW5kbGVyMgIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmNF8yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQIUTGlzdCBzaXplIGV4Y2VlZHMgMTAJAQUkZjRfMgIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYABwAIAAkACgkAawMFBWFjY3VtCQBsBggFA3BtdAZhbW91bnQJAJEDAgUIRGVjaW1hbHMFBVRva2VuCQCRAwIFDUFzc2V0c1dlaWdodHMFBVRva2VuBRVBc3NldHNXZWlnaHRzRGVjaW1hbHMACAUFRkxPT1IFBlNjYWxlOAoAAiRsBQhwYXltZW50cwoAAiRzCQCQAwEFAiRsCgAFJGFjYzAFDlBvb2xUb2tlblNjYWxlCgEFJGY0XzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAQdoYW5kbGVyAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGY0XzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhRMaXN0IHNpemUgZXhjZWVkcyAxMAkBBSRmNF8yAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgUFJGFjYzAAAAABAAIAAwAEAAUABgAHAAgACQAKAwkBCmlzU2h1dGRvd24ACQACAQITY29udHJhY3QgaXMgb24gc3RvcAMJAGYCCQENdHJ5R2V0SW50ZWdlcgECEGdsb2JhbF93YXNJbml0ZWQAAAkAAgECE3Bvb2wgYWxyZWFkeSBpbml0ZWQEEWluaXRpYWxQb29sVG9rZW5zCQEZY2FsY3VsYXRlUG9vbFRva2Vuc0Ftb3VudAEIBQFpCHBheW1lbnRzAwkAAAIFEWluaXRpYWxQb29sVG9rZW5zAAAJAAIBAjJ5b3UgbmVlZCBhIGJpZ2dlciB0b2tlbnMgYW1vdW50IHRvIGxhdW5jaCB0aGUgcG9vbAQOcG9vbFRva2VuSXNzdWUJAMMIBwkArAICAgNQWiAJAQx0cnlHZXRTdHJpbmcBAhFzdGF0aWNfcG9vbERvbWFpbgIdUHV6emxlIFN3YXA6IHBvb2wgaW5kZXggdG9rZW4FEWluaXRpYWxQb29sVG9rZW5zBRFQb29sVG9rZW5EZWNpbWFscwYFBHVuaXQAAAQLcG9vbFRva2VuSWQJALgIAQUOcG9vbFRva2VuSXNzdWUJAM4IAgkBC3ByZXBhcmVMaXN0AAkAzAgCBQ5wb29sVG9rZW5Jc3N1ZQkAzAgCCQEMSW50ZWdlckVudHJ5AgIXZ2xvYmFsX3Bvb2xUb2tlbl9hbW91bnQFEWluaXRpYWxQb29sVG9rZW5zCQDMCAIJAQxJbnRlZ2VyRW50cnkCAhBnbG9iYWxfd2FzSW5pdGVkAAEJAMwIAgkBC0JpbmFyeUVudHJ5AgITZ2xvYmFsX3Bvb2xUb2tlbl9pZAULcG9vbFRva2VuSWQJAMwIAgkBC1N0cmluZ0VudHJ5AgIWc3RhdGljX3Bvb2xUb2tlbl9pZFN0cgkBDmdldEFzc2V0U3RyaW5nAQULcG9vbFRva2VuSWQJAMwIAgkBDEludGVnZXJFbnRyeQIJAKwCAgkApQgBCAUBaQZjYWxsZXICDF9pbmRleFN0YWtlZAURaW5pdGlhbFBvb2xUb2tlbnMJAMwIAgkBDEludGVnZXJFbnRyeQICEmdsb2JhbF9pbmRleFN0YWtlZAURaW5pdGlhbFBvb2xUb2tlbnMFA25pbAFpAQ1nZW5lcmF0ZUluZGV4AQpuZWVkQ2hhbmdlAwkBAiE9AgkAkAMBCAUBaQhwYXltZW50cwUBVAkAAgEJAKwCAgI7eW91IG5lZWQgdG8gYXR0YWNoIGFsbCBwb29sIHRva2Vucy4gYW1vdW50IG9mIHBvb2wgdG9rZW5zOiAJAKQDAQUBVAMJAQEhAQkBE2NoZWNrVG9rZW5zVmFsaWRpdHkBCAUBaQhwYXltZW50cwkAAgECFXdyb25nIGFzc2V0cyBhdHRhY2hlZAQNUElzc3VlZE5vTXVsdAkBDWdldE1pblBJc3N1ZWQBCAUBaQhwYXltZW50cwQGcmVzdWx0CQETaGFuZGxlUG9vbFRva2Vuc0FkZAQFDVBJc3N1ZWROb011bHQIBQFpCHBheW1lbnRzCAUBaQxvcmlnaW5DYWxsZXIFCm5lZWRDaGFuZ2UED1BJc3N1ZWRXaXRoTXVsdAkAbgQFDVBJc3N1ZWROb011bHQFB1NjYWxlMTYJAQhnZXRLTXVsdAAFBERPV04EB3JlaXNzdWUJAQdSZWlzc3VlAwkBEUBleHRyTmF0aXZlKDEwNTcpAQITZ2xvYmFsX3Bvb2xUb2tlbl9pZAUPUElzc3VlZFdpdGhNdWx0BgkAlAoCCQDOCAIFBnJlc3VsdAkAzAgCBQdyZWlzc3VlCQDMCAIJAQ5TY3JpcHRUcmFuc2ZlcgMIBQFpBmNhbGxlcgUPUElzc3VlZFdpdGhNdWx0CQEMdHJ5R2V0QmluYXJ5AQITZ2xvYmFsX3Bvb2xUb2tlbl9pZAkAzAgCCQEMSW50ZWdlckVudHJ5AgIXZ2xvYmFsX3Bvb2xUb2tlbl9hbW91bnQJAGQCCQENdHJ5R2V0SW50ZWdlcgECF2dsb2JhbF9wb29sVG9rZW5fYW1vdW50BQ9QSXNzdWVkV2l0aE11bHQFA25pbAUPUElzc3VlZFdpdGhNdWx0AWkBC3JlZGVlbUluZGV4AQxzZW5kVG9PcmlnaW4EA3BtdAkAkQMCCAUBaQhwYXltZW50cwAAAwkBAiE9AggFA3BtdAdhc3NldElkCQEMdHJ5R2V0QmluYXJ5AQITZ2xvYmFsX3Bvb2xUb2tlbl9pZAkAAgECHnBsZWFzZSBhdHRhY2ggcG9vbCBzaGFyZSB0b2tlbgMJAQppc1NodXRkb3duAAkAAgECE2NvbnRyYWN0IGlzIG9uIHN0b3AEEVBSZWRlZW1lZFdpdGhNdWx0CAUDcG10BmFtb3VudAQTUFJlZGVlbWVkV2l0aE5vTXVsdAkAbgQFEVBSZWRlZW1lZFdpdGhNdWx0CQEIZ2V0S011bHQABQdTY2FsZTE2BQRET1dOBAZyZXN1bHQJARZoYW5kbGVQb29sVG9rZW5zUmVkZWVtAgUTUFJlZGVlbWVkV2l0aE5vTXVsdAMFDHNlbmRUb09yaWdpbggFAWkMb3JpZ2luQ2FsbGVyCAUBaQZjYWxsZXIJAM4IAgUGcmVzdWx0CQDMCAIJAQRCdXJuAgkBDHRyeUdldEJpbmFyeQECE2dsb2JhbF9wb29sVG9rZW5faWQFEVBSZWRlZW1lZFdpdGhNdWx0CQDMCAIJAQxJbnRlZ2VyRW50cnkCAhdnbG9iYWxfcG9vbFRva2VuX2Ftb3VudAkAZQIJAQ10cnlHZXRJbnRlZ2VyAQIXZ2xvYmFsX3Bvb2xUb2tlbl9hbW91bnQFEVBSZWRlZW1lZFdpdGhNdWx0BQNuaWwBaQEKc3Rha2VJbmRleAAECmFkZHJlc3NTdHIJAKUIAQgFAWkMb3JpZ2luQ2FsbGVyBANwbXQJAJEDAggFAWkIcGF5bWVudHMAAAMJAQIhPQIJAQV2YWx1ZQEIBQNwbXQHYXNzZXRJZAkBDHRyeUdldEJpbmFyeQECE2dsb2JhbF9wb29sVG9rZW5faWQJAAIBAhR3cm9uZyBhc3NldCBhdHRhY2hlZAkBEGluZGV4U3Rha2VSZXN1bHQCBQphZGRyZXNzU3RyCAUDcG10BmFtb3VudAFpAQ1zdGFrZUluZGV4Rm9yAQphZGRyZXNzU3RyBANwbXQJAJEDAggFAWkIcGF5bWVudHMAAAMJAQIhPQIJAQV2YWx1ZQEIBQNwbXQHYXNzZXRJZAkBDHRyeUdldEJpbmFyeQECE2dsb2JhbF9wb29sVG9rZW5faWQJAAIBAhR3cm9uZyBhc3NldCBhdHRhY2hlZAkBEGluZGV4U3Rha2VSZXN1bHQCBQphZGRyZXNzU3RyCAUDcG10BmFtb3VudAFpAQx1bnN0YWtlSW5kZXgBC2luZGV4QW1vdW50BAphZGRyZXNzU3RyCQClCAEIBQFpDG9yaWdpbkNhbGxlcgQOaW5kZXhBdmFpbGFibGUJAQ10cnlHZXRJbnRlZ2VyAQkArAICBQphZGRyZXNzU3RyAgxfaW5kZXhTdGFrZWQDCQEKaXNTaHV0ZG93bgAJAAIBAhNjb250cmFjdCBpcyBvbiBzdG9wAwkAZgIFC2luZGV4QW1vdW50BQ5pbmRleEF2YWlsYWJsZQkAAgECJXlvdSBkb24ndCBoYXZlIGluZGV4IHRva2VucyBhdmFpbGFibGUDCQEKaXNTaHV0ZG93bgAJAAIBAhNjb250cmFjdCBpcyBvbiBzdG9wCQDOCAIICQELY2xhaW1SZXN1bHQBCAUBaQxvcmlnaW5DYWxsZXICXzEJAMwIAgkBDEludGVnZXJFbnRyeQIJAKwCAgUKYWRkcmVzc1N0cgIMX2luZGV4U3Rha2VkCQBlAgUOaW5kZXhBdmFpbGFibGUFC2luZGV4QW1vdW50CQDMCAIJAQxJbnRlZ2VyRW50cnkCAhJnbG9iYWxfaW5kZXhTdGFrZWQJAGUCCQENdHJ5R2V0SW50ZWdlcgECEmdsb2JhbF9pbmRleFN0YWtlZAULaW5kZXhBbW91bnQJAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwgFAWkGY2FsbGVyBQtpbmRleEFtb3VudAkBEUBleHRyTmF0aXZlKDEwNTcpAQITZ2xvYmFsX3Bvb2xUb2tlbl9pZAUDbmlsAWkBEWNsYWltSW5kZXhSZXdhcmRzAAMJAQppc1NodXRkb3duAAkAAgECE2NvbnRyYWN0IGlzIG9uIHN0b3AJAQtjbGFpbVJlc3VsdAEIBQFpBmNhbGxlcgFpAQ1ldmFsdWF0ZUNsYWltAQR1c2VyCQCUCgIFA25pbAgJAQtjbGFpbVJlc3VsdAEJARFAZXh0ck5hdGl2ZSgxMDYyKQEFBHVzZXICXzIBaQEEc3dhcAIIYXNzZXRPdXQHbWluaW11bQQDcG10AwkAAAIJAJADAQgFAWkIcGF5bWVudHMAAQkBBXZhbHVlAQkAkQMCCAUBaQhwYXltZW50cwAACQACAQIhcGxlYXNlIGF0dGFjaCBleGFjdGx5IG9uZSBwYXltZW50BAhBbW91bnRJbgkBBXZhbHVlAQgJAJEDAggFAWkIcGF5bWVudHMAAAZhbW91bnQEB0Fzc2V0SW4IBQNwbXQHYXNzZXRJZAQIQXNzZXRPdXQJAQ1nZXRBc3NldEJ5dGVzAQUIYXNzZXRPdXQEB2Fzc2V0SW4JAQ5nZXRBc3NldFN0cmluZwEFB0Fzc2V0SW4EB3NjYWxlSW4JAGkCBQZTY2FsZTgJAQ10cnlHZXRJbnRlZ2VyAQkArAICCQCsAgICB3N0YXRpY18FB2Fzc2V0SW4CBl9zY2FsZQQIc2NhbGVPdXQJAGkCBQZTY2FsZTgJAQ10cnlHZXRJbnRlZ2VyAQkArAICCQCsAgICB3N0YXRpY18FCGFzc2V0T3V0AgZfc2NhbGUEDmZlZUFzc2V0T3V0U3RyCQEMdHJ5R2V0U3RyaW5nAQIPc3RhdGljX2ZlZVRva2VuBAtmZWVBc3NldE91dAMJAAACBQ5mZWVBc3NldE91dFN0cgIABQt1c2RuQXNzZXRJZAkBDWdldEFzc2V0Qnl0ZXMBBQ5mZWVBc3NldE91dFN0cgQOQXNzZXRJbkJhbGFuY2UJAQ10cnlHZXRJbnRlZ2VyAQkArAICCQCsAgICB2dsb2JhbF8JAQ5nZXRBc3NldFN0cmluZwEFB0Fzc2V0SW4CCF9iYWxhbmNlBA9Bc3NldE91dEJhbGFuY2UJAQ10cnlHZXRJbnRlZ2VyAQkArAICCQCsAgICB2dsb2JhbF8FCGFzc2V0T3V0AghfYmFsYW5jZQQUQXNzZXRJbkJhbGFuY2VTY2FsZWQJAGgCBQ5Bc3NldEluQmFsYW5jZQUHc2NhbGVJbgQVQXNzZXRPdXRCYWxhbmNlU2NhbGVkCQBoAgUPQXNzZXRPdXRCYWxhbmNlBQhzY2FsZU91dAQLZmVlQW1vdW50SW4JAGsDBQhBbW91bnRJbgUDRmVlBQhGZWVTY2FsZQQNY2xlYW5BbW91bnRJbgkAZQIFCEFtb3VudEluBQtmZWVBbW91bnRJbgQTY2xlYW5BbW91bnRJblNjYWxlZAkAaAIFDWNsZWFuQW1vdW50SW4FB3NjYWxlSW4ECkFtb3VudE91dDEJARJjYWxjdWxhdGVPdXRBbW91bnQFBRNjbGVhbkFtb3VudEluU2NhbGVkBQdBc3NldEluBQhBc3NldE91dAUUQXNzZXRJbkJhbGFuY2VTY2FsZWQFFUFzc2V0T3V0QmFsYW5jZVNjYWxlZAQJQW1vdW50T3V0CQBrAwUKQW1vdW50T3V0MQABBQhzY2FsZU91dAQQQXNzZXRPdXRCYWxhbmNlMgkAZQIFD0Fzc2V0T3V0QmFsYW5jZQUJQW1vdW50T3V0BA9Bc3NldEluQmFsYW5jZTIJAGQCBQ5Bc3NldEluQmFsYW5jZQUNY2xlYW5BbW91bnRJbgQSZmVlQXNzZXRPdXRCYWxhbmNlAwkAAAIFC2ZlZUFzc2V0T3V0BQdBc3NldEluBQ9Bc3NldEluQmFsYW5jZTIDCQAAAgULZmVlQXNzZXRPdXQFCEFzc2V0T3V0BRBBc3NldE91dEJhbGFuY2UyCQENdHJ5R2V0SW50ZWdlcgEJAKwCAgkArAICAgdnbG9iYWxfCQEOZ2V0QXNzZXRTdHJpbmcBBQtmZWVBc3NldE91dAIIX2JhbGFuY2UEDGZlZUFtb3VudE91dAkBEmNhbGN1bGF0ZU91dEFtb3VudAUFC2ZlZUFtb3VudEluBQdBc3NldEluBQtmZWVBc3NldE91dAUOQXNzZXRJbkJhbGFuY2UFEmZlZUFzc2V0T3V0QmFsYW5jZQMJAGYCBQdtaW5pbXVtBQlBbW91bnRPdXQJAAIBAilhbW91bnQgdG8gcmVjaWV2ZSBpcyBsb3dlciB0aGFuIGdpdmVuIG9uZQMJAAACBQhBc3NldE91dAUHQXNzZXRJbgkAAgECGHRoaXMgc3dhcCBpcyBub3QgYWxsb3dlZAMJAGYCAAAJAGUCBQ9Bc3NldE91dEJhbGFuY2UFCUFtb3VudE91dAkAAgECG2NvbnRyYWN0IGlzIG91dCBvZiByZXNlcnZlcwMJAQppc1NodXRkb3duAAkAAgECE2NvbnRyYWN0IGlzIG9uIHN0b3AECmNyZWF0b3JGZWUJAGsDBQxmZWVBbW91bnRPdXQAAQAKBAtwcm90b2NvbEZlZQkAawMFDGZlZUFtb3VudE91dAAEAAoEDHN0YWtpbmdUb3BVcAMDCQAAAgULZmVlQXNzZXRPdXQFC3VzZG5Bc3NldElkBgkAAAIFC2ZlZUFzc2V0T3V0BQ1wdXp6bGVBc3NldElkCQD9BwQFDnN0YWtpbmdBZGRyZXNzAgt0b3BVcFJld2FyZAUDbmlsCQDMCAIJAQ9BdHRhY2hlZFBheW1lbnQCBQtmZWVBc3NldE91dAULcHJvdG9jb2xGZWUFA25pbAUEdW5pdAMJAAACBQxzdGFraW5nVG9wVXAFDHN0YWtpbmdUb3BVcAQMbmV3QmFsYW5jZUluBQ9Bc3NldEluQmFsYW5jZTIEDW5ld0JhbGFuY2VPdXQJAGUCBRBBc3NldE91dEJhbGFuY2UyAwkAAAIFCEFzc2V0T3V0BQtmZWVBc3NldE91dAUMZmVlQW1vdW50T3V0AAAEEm5ld0JhbGFuY2VGZWVBc3NldAMDCQECIT0CBQtmZWVBc3NldE91dAUHQXNzZXRJbgkBAiE9AgULZmVlQXNzZXRPdXQFCEFzc2V0T3V0BwkAZQIFEmZlZUFzc2V0T3V0QmFsYW5jZQUMZmVlQW1vdW50T3V0BQR1bml0BA1hc3NldEluQ2hhbmdlCQEMSW50ZWdlckVudHJ5AgkArAICCQCsAgICB2dsb2JhbF8JAQ5nZXRBc3NldFN0cmluZwEFB0Fzc2V0SW4CCF9iYWxhbmNlBQxuZXdCYWxhbmNlSW4EDmFzc2V0T3V0Q2hhbmdlCQEMSW50ZWdlckVudHJ5AgkArAICCQCsAgICB2dsb2JhbF8FCGFzc2V0T3V0AghfYmFsYW5jZQUNbmV3QmFsYW5jZU91dAQRZmVlQXNzZXRPdXRDaGFuZ2UDCQECIT0CBRJuZXdCYWxhbmNlRmVlQXNzZXQFBHVuaXQJAQxJbnRlZ2VyRW50cnkCCQCsAgIJAKwCAgIHZ2xvYmFsXwkBDmdldEFzc2V0U3RyaW5nAQULZmVlQXNzZXRPdXQCCF9iYWxhbmNlCQEFdmFsdWUBBRJuZXdCYWxhbmNlRmVlQXNzZXQJAQtTdHJpbmdFbnRyeQICBWhlbGxvAgV3b3JsZAQMdm9sdW1lVXBkYXRlCQESY2FsY3VsYXRlVXNkblZhbHVlBAUHQXNzZXRJbgUIQW1vdW50SW4FDkFzc2V0SW5CYWxhbmNlBRJmZWVBc3NldE91dEJhbGFuY2UED3ZvbHVtZVVzZFVwZGF0ZQkBEWNhbGN1bGF0ZVVzZFZhbHVlAwUHQXNzZXRJbgUIQW1vdW50SW4FDkFzc2V0SW5CYWxhbmNlCQCUCgIJAM4IAgkAzAgCBQ5hc3NldE91dENoYW5nZQkAzAgCBQ1hc3NldEluQ2hhbmdlCQDMCAIFEWZlZUFzc2V0T3V0Q2hhbmdlCQDMCAIJAQ5TY3JpcHRUcmFuc2ZlcgMIBQFpBmNhbGxlcgUJQW1vdW50T3V0BQhBc3NldE91dAkAzAgCCQEOU2NyaXB0VHJhbnNmZXIDCQERQGV4dHJOYXRpdmUoMTA2MikBCQEMdHJ5R2V0U3RyaW5nAQIQc3RhdGljX3Bvb2xPd25lcgUKY3JlYXRvckZlZQULZmVlQXNzZXRPdXQJAMwIAgkBDEludGVnZXJFbnRyeQICFGdsb2JhbF9lYXJuZWRCeU93bmVyCQBkAgkBDXRyeUdldEludGVnZXIBAhRnbG9iYWxfZWFybmVkQnlPd25lcgUKY3JlYXRvckZlZQkAzAgCCQEMSW50ZWdlckVudHJ5AgINZ2xvYmFsX3ZvbHVtZQkAZAIJAQ10cnlHZXRJbnRlZ2VyAQINZ2xvYmFsX3ZvbHVtZQUMdm9sdW1lVXBkYXRlCQDMCAIJAQxJbnRlZ2VyRW50cnkCAhFnbG9iYWxfdm9sdW1lX3VzZAkAZAIJAQ10cnlHZXRJbnRlZ2VyAQIRZ2xvYmFsX3ZvbHVtZV91c2QFD3ZvbHVtZVVzZFVwZGF0ZQUDbmlsAwkAAAIFDHN0YWtpbmdUb3BVcAUEdW5pdAkAzAgCCQEOU2NyaXB0VHJhbnNmZXIDBQtmZWVzQWRkcmVzcwULcHJvdG9jb2xGZWUFC2ZlZUFzc2V0T3V0BQNuaWwFA25pbAUJQW1vdW50T3V0CQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBDHN3YXBSZWFkT25seQMHYXNzZXRJbghhc3NldE91dAhBbW91bnRJbgQHQXNzZXRJbgkBDWdldEFzc2V0Qnl0ZXMBBQdhc3NldEluBAhBc3NldE91dAkBDWdldEFzc2V0Qnl0ZXMBBQhhc3NldE91dAQHc2NhbGVJbgkAaQIFBlNjYWxlOAkBDXRyeUdldEludGVnZXIBCQCsAgIJAKwCAgIHc3RhdGljXwUHYXNzZXRJbgIGX3NjYWxlBAhzY2FsZU91dAkAaQIFBlNjYWxlOAkBDXRyeUdldEludGVnZXIBCQCsAgIJAKwCAgIHc3RhdGljXwUIYXNzZXRPdXQCBl9zY2FsZQQOZmVlQXNzZXRPdXRTdHIJAQx0cnlHZXRTdHJpbmcBAg9zdGF0aWNfZmVlVG9rZW4EC2ZlZUFzc2V0T3V0AwkAAAIFDmZlZUFzc2V0T3V0U3RyAgAFC3VzZG5Bc3NldElkCQENZ2V0QXNzZXRCeXRlcwEFDmZlZUFzc2V0T3V0U3RyBA5Bc3NldEluQmFsYW5jZQkBDXRyeUdldEludGVnZXIBCQCsAgIJAKwCAgIHZ2xvYmFsXwkBDmdldEFzc2V0U3RyaW5nAQUHQXNzZXRJbgIIX2JhbGFuY2UED0Fzc2V0T3V0QmFsYW5jZQkBDXRyeUdldEludGVnZXIBCQCsAgIJAKwCAgIHZ2xvYmFsXwUIYXNzZXRPdXQCCF9iYWxhbmNlBBRBc3NldEluQmFsYW5jZVNjYWxlZAkAaAIFDkFzc2V0SW5CYWxhbmNlBQdzY2FsZUluBBVBc3NldE91dEJhbGFuY2VTY2FsZWQJAGgCBQ9Bc3NldE91dEJhbGFuY2UFCHNjYWxlT3V0BAtmZWVBbW91bnRJbgkAawMFCEFtb3VudEluBQNGZWUFCEZlZVNjYWxlBA1jbGVhbkFtb3VudEluCQBlAgUIQW1vdW50SW4FC2ZlZUFtb3VudEluBBNjbGVhbkFtb3VudEluU2NhbGVkCQBoAgUNY2xlYW5BbW91bnRJbgUHc2NhbGVJbgQKQW1vdW50T3V0MQkBEmNhbGN1bGF0ZU91dEFtb3VudAUFE2NsZWFuQW1vdW50SW5TY2FsZWQFB0Fzc2V0SW4FCEFzc2V0T3V0BRRBc3NldEluQmFsYW5jZVNjYWxlZAUVQXNzZXRPdXRCYWxhbmNlU2NhbGVkBAlBbW91bnRPdXQJAGsDBQpBbW91bnRPdXQxAAEFCHNjYWxlT3V0BBBBc3NldE91dEJhbGFuY2UyCQBlAgUPQXNzZXRPdXRCYWxhbmNlBQlBbW91bnRPdXQED0Fzc2V0SW5CYWxhbmNlMgkAZAIFDkFzc2V0SW5CYWxhbmNlBQ1jbGVhbkFtb3VudEluBBJmZWVBc3NldE91dEJhbGFuY2UDCQAAAgULZmVlQXNzZXRPdXQFB0Fzc2V0SW4FD0Fzc2V0SW5CYWxhbmNlMgMJAAACBQtmZWVBc3NldE91dAUIQXNzZXRPdXQFEEFzc2V0T3V0QmFsYW5jZTIJAQ10cnlHZXRJbnRlZ2VyAQkArAICCQCsAgICB2dsb2JhbF8JAQ5nZXRBc3NldFN0cmluZwEFC2ZlZUFzc2V0T3V0AghfYmFsYW5jZQQMZmVlQW1vdW50T3V0CQESY2FsY3VsYXRlT3V0QW1vdW50BQULZmVlQW1vdW50SW4FB0Fzc2V0SW4FC2ZlZUFzc2V0T3V0BQ5Bc3NldEluQmFsYW5jZQUSZmVlQXNzZXRPdXRCYWxhbmNlAwkAAAIFCEFzc2V0T3V0BQdBc3NldEluCQACAQIYdGhpcyBzd2FwIGlzIG5vdCBhbGxvd2VkAwkAZgIAAAkAZQIFD0Fzc2V0T3V0QmFsYW5jZQUJQW1vdW50T3V0CQACAQIbY29udHJhY3QgaXMgb3V0IG9mIHJlc2VydmVzAwkBCmlzU2h1dGRvd24ACQACAQITY29udHJhY3QgaXMgb24gc3RvcAkAlAoCBQNuaWwFCUFtb3VudE91dAFpARF0cmFuc2Zlck93bmVyc2hpcAEPbmV3T3duZXJBZGRyZXNzAwkBAiE9AgkApQgBCAUBaQZjYWxsZXIJAQx0cnlHZXRTdHJpbmcBAhBzdGF0aWNfcG9vbE93bmVyCQACAQIndGhpcyBjYWxsIGF2YWlsYWJsZSBvbmx5IGZvciBwb29sIG93bmVyCQDMCAIJAQtTdHJpbmdFbnRyeQICEHN0YXRpY19wb29sT3duZXIFD25ld093bmVyQWRkcmVzcwUDbmlsAWkBEnNldFJlYmFsYW5jaW5nUGxhbgULYXNzZXRJZHNTdHIPYXNzZXRXZWlnaHRzU3RyDmJhc2VUb2tlbklkU3RyC3N0ZXBzQW1vdW50DXN0ZXBzSW50ZXJ2YWwDCQECIT0CCAUBaQZjYWxsZXIJARFAZXh0ck5hdGl2ZSgxMDYyKQEJAQx0cnlHZXRTdHJpbmcBAhBzdGF0aWNfcG9vbE93bmVyCQACAQIndGhpcyBjYWxsIGF2YWlsYWJsZSBvbmx5IGZvciBwb29sIG93bmVyAwkBC3ZhbHVlT3JFbHNlAgkAmwgCBQR0aGlzAhRyZWJhbGFuY2VfaW5Qcm9ncmVzcwcJAAIBAhdyZWJhbGFuY2luZyBpbiBwcm9ncmVzcwQUbmV3QXNzZXRXZWlnaHRzU3RyTGkJALUJAgUPYXNzZXRXZWlnaHRzU3RyAgEsBBBuZXdBc3NldElkc1N0ckxpCQC1CQIFC2Fzc2V0SWRzU3RyAgEsBAtmZWVBc3NldFN0cgoAAiRsBRBuZXdBc3NldElkc1N0ckxpCgACJHMJAJADAQUCJGwKAAUkYWNjMAIACgEFJGY0XzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAQ1jaGVja0ZlZUFzc2V0AgUCJGEJAJEDAgUCJGwFAiRpCgEFJGY0XzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhRMaXN0IHNpemUgZXhjZWVkcyAxMAkBBSRmNF8yAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgkBBSRmNF8xAgUFJGFjYzAAAAABAAIAAwAEAAUABgAHAAgACQAKBA9hc3NldFdlaWdodHNTdW0KAAIkbAUUbmV3QXNzZXRXZWlnaHRzU3RyTGkKAAIkcwkAkAMBBQIkbAoABSRhY2MwAAAKAQUkZjVfMQICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkBA3N1bQIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmNV8yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQIUTGlzdCBzaXplIGV4Y2VlZHMgMTAJAQUkZjVfMgIJAQUkZjVfMQIJAQUkZjVfMQIJAQUkZjVfMQIJAQUkZjVfMQIJAQUkZjVfMQIJAQUkZjVfMQIJAQUkZjVfMQIJAQUkZjVfMQIJAQUkZjVfMQIJAQUkZjVfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYABwAIAAkACgQLb2xkQXNzZXRJZHMJARFAZXh0ck5hdGl2ZSgxMDU4KQECD3N0YXRpY190b2tlbklkcwQNb2xkQXNzZXRJZHNMaQkAtQkCBQtvbGRBc3NldElkcwIBLAoBCWZpbmRBZGRlZAIFYWNjdW0EbmV4dAMJAAACCQDPCAIFDW9sZEFzc2V0SWRzTGkFBG5leHQFBHVuaXQJAM4IAgUFYWNjdW0JAMwIAgUEbmV4dAUDbmlsBQVhY2N1bQoBC2ZpbmRSZW1vdmVkAgVhY2N1bQRuZXh0AwkAAAIJAM8IAgUQbmV3QXNzZXRJZHNTdHJMaQUEbmV4dAUEdW5pdAkAzggCBQVhY2N1bQkAzAgCBQRuZXh0BQNuaWwFBWFjY3VtBAthZGRlZEFzc2V0cwoAAiRsBRBuZXdBc3NldElkc1N0ckxpCgACJHMJAJADAQUCJGwKAAUkYWNjMAUDbmlsCgEFJGY2XzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAQlmaW5kQWRkZWQCBQIkYQkAkQMCBQIkbAUCJGkKAQUkZjZfMgICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkAAgECFExpc3Qgc2l6ZSBleGNlZWRzIDEwCQEFJGY2XzICCQEFJGY2XzECCQEFJGY2XzECCQEFJGY2XzECCQEFJGY2XzECCQEFJGY2XzECCQEFJGY2XzECCQEFJGY2XzECCQEFJGY2XzECCQEFJGY2XzECCQEFJGY2XzECBQUkYWNjMAAAAAEAAgADAAQABQAGAAcACAAJAAoEDXJlbW92ZWRBc3NldHMKAAIkbAUNb2xkQXNzZXRJZHNMaQoAAiRzCQCQAwEFAiRsCgAFJGFjYzAFA25pbAoBBSRmN18xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQELZmluZFJlbW92ZWQCBQIkYQkAkQMCBQIkbAUCJGkKAQUkZjdfMgICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkAAgECFExpc3Qgc2l6ZSBleGNlZWRzIDEwCQEFJGY3XzICCQEFJGY3XzECCQEFJGY3XzECCQEFJGY3XzECCQEFJGY3XzECCQEFJGY3XzECCQEFJGY3XzECCQEFJGY3XzECCQEFJGY3XzECCQEFJGY3XzECCQEFJGY3XzECBQUkYWNjMAAAAAEAAgADAAQABQAGAAcACAAJAAoEDXZhbGlkUGF5bWVudHMJARB2YWxpZGF0ZVBheW1lbnRzAgULYWRkZWRBc3NldHMIBQFpCHBheW1lbnRzAwkBAiE9AgkAkAMBBRBuZXdBc3NldElkc1N0ckxpCQCQAwEFFG5ld0Fzc2V0V2VpZ2h0c1N0ckxpCQACAQIxYXNzZXRJZHMgYW5kIGFzc2V0V2VpZ2h0cyBzaG91bGQgaGF2ZSBzYW1lIGxlbmd0aAMJAAACBQtmZWVBc3NldFN0cgIACQACAQJBcG9vbCBtdXN0IGhhdmUgb25lIG9mIHRoZSBzdXBwb3J0ZWQgZmVlIGFzc2V0cyBpbiB0aGUgY29tcG9zaXRpb24DCQAAAgkAzwgCBRBuZXdBc3NldElkc1N0ckxpBQ5iYXNlVG9rZW5JZFN0cgUEdW5pdAkAAgECKWJhc2VUb2tlbklkIHNob3VsZCBiZSBwcmVzZW50IGluIGFzc2V0SWRzAwMJAGYCBRBNSU5fU1RFUFNfQU1PVU5UBQtzdGVwc0Ftb3VudAYJAGYCBQtzdGVwc0Ftb3VudAUQTUFYX1NURVBTX0FNT1VOVAkAAgEJAKwCAgkArAICCQCsAgICH1N0ZXBzIGFtb3VudCBzaG91bGQgYmUgYmV0d2VlbiAJAKQDAQUQTUlOX1NURVBTX0FNT1VOVAIFIGFuZCAJAKQDAQUQTUFYX1NURVBTX0FNT1VOVAMDCQBmAgUSTUlOX1NURVBTX0lOVEVSVkFMBQ1zdGVwc0ludGVydmFsBgkAZgIFDXN0ZXBzSW50ZXJ2YWwFEk1BWF9TVEVQU19JTlRFUlZBTAkAAgEJAKwCAgkArAICCQCsAgICIVN0ZXBzIGludGVydmFsIHNob3VsZCBiZSBiZXR3ZWVuIAkApAMBBRJNSU5fU1RFUFNfSU5URVJWQUwCBSBhbmQgCQCkAwEFEk1BWF9TVEVQU19JTlRFUlZBTAMJAQIhPQIFD2Fzc2V0V2VpZ2h0c1N1bQCQTgkAAgECK3N1bSBvZiB0b2tlbiB3ZWlnaHRzIG11c3QgYmUgZXF1YWwgdG8gMTAwMDAKAQFmAgVhY2N1bQphc3NldElkU3RyBAlvbGRXZWlnaHQJAQ10cnlHZXRJbnRlZ2VyAQkArAICCQCsAgICB3N0YXRpY18FCmFzc2V0SWRTdHICB193ZWlnaHQECW5ld1dlaWdodAMJAAACCQDPCAIFEG5ld0Fzc2V0SWRzU3RyTGkFCmFzc2V0SWRTdHIFBHVuaXQAAAkBDXBhcnNlSW50VmFsdWUBCQEFdmFsdWUBCQCRAwIFFG5ld0Fzc2V0V2VpZ2h0c1N0ckxpCQEFdmFsdWUBCQDPCAIFEG5ld0Fzc2V0SWRzU3RyTGkFCmFzc2V0SWRTdHIEDGRlbHRhUGVyU3RlcAkAawMJAGUCBQluZXdXZWlnaHQFCW9sZFdlaWdodACQTgULc3RlcHNBbW91bnQJAM4IAgUFYWNjdW0JAMwIAgkApAMBBQxkZWx0YVBlclN0ZXAFA25pbAQNdG1wQXNzZXRJZHNMaQkBEmdldFRtcFJlYmFsYW5jZUlkcwEFEG5ld0Fzc2V0SWRzU3RyTGkEC2Fzc2V0RGVsdGFzCgACJGwFDXRtcEFzc2V0SWRzTGkKAAIkcwkAkAMBBQIkbAoABSRhY2MwBQNuaWwKAQUkZjhfMQICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkBAWYCBQIkYQkAkQMCBQIkbAUCJGkKAQUkZjhfMgICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkAAgECFExpc3Qgc2l6ZSBleGNlZWRzIDEwCQEFJGY4XzICCQEFJGY4XzECCQEFJGY4XzECCQEFJGY4XzECCQEFJGY4XzECCQEFJGY4XzECCQEFJGY4XzECCQEFJGY4XzECCQEFJGY4XzECCQEFJGY4XzECCQEFJGY4XzECBQUkYWNjMAAAAAEAAgADAAQABQAGAAcACAAJAAoEDm5ld1Rva2Vuc0FkZGVkCQBmAgkBEWNoZWNrVG9rZW5zQ2hhbmdlAQUQbmV3QXNzZXRJZHNTdHJMaQAACgEScmVjb3JkQXNzZXRQYXltZW50AgVhY2N1bQRuZXh0CQDOCAIFBWFjY3VtCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQCsAgICGnJlYmFsYW5jZV9hdHRhY2hlZFBheW1lbnRfCQEOZ2V0QXNzZXRTdHJpbmcBCAUEbmV4dAdhc3NldElkCAUEbmV4dAZhbW91bnQFA25pbAQOcGF5bWVudEVudHJpZXMKAAIkbAgFAWkIcGF5bWVudHMKAAIkcwkAkAMBBQIkbAoABSRhY2MwBQNuaWwKAQUkZjlfMQICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkBEnJlY29yZEFzc2V0UGF5bWVudAIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmOV8yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQIUTGlzdCBzaXplIGV4Y2VlZHMgMTAJAQUkZjlfMgIJAQUkZjlfMQIJAQUkZjlfMQIJAQUkZjlfMQIJAQUkZjlfMQIJAQUkZjlfMQIJAQUkZjlfMQIJAQUkZjlfMQIJAQUkZjlfMQIJAQUkZjlfMQIJAQUkZjlfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYABwAIAAkACgQMc3RvcmVXZWlnaHRzCQESc2F2ZUN1cnJlbnRXZWlnaHRzAAQMbm90aWZ5SW52b2tlCQD8BwQFD3Bvb2xzSHViQWRkcmVzcwIQbm90aWZ5UG9vbENoYW5nZQUDbmlsBQNuaWwDCQAAAgUMbm90aWZ5SW52b2tlBQxub3RpZnlJbnZva2UJAM4IAgkAzggCCQDMCAIJAQtTdHJpbmdFbnRyeQICFXJlYmFsYW5jZV9hZGRlZEFzc2V0cwkAuQkCBQthZGRlZEFzc2V0cwIBLAkAzAgCCQELU3RyaW5nRW50cnkCAhdyZWJhbGFuY2VfcmVtb3ZlZEFzc2V0cwkAuQkCBQ1yZW1vdmVkQXNzZXRzAgEsCQDMCAIJAQtTdHJpbmdFbnRyeQICFXRtcF9yZWJhbGFuY2VBc3NldElkcwkAuQkCBQ10bXBBc3NldElkc0xpAgEsCQDMCAIJAQxCb29sZWFuRW50cnkCAhRyZWJhbGFuY2VfaW5Qcm9ncmVzcwYJAMwIAgkBDEJvb2xlYW5FbnRyeQICGHJlYmFsYW5jZV9uZXdUb2tlbnNBZGRlZAUObmV3VG9rZW5zQWRkZWQJAMwIAgkBDEludGVnZXJFbnRyeQICE3JlYmFsYW5jZV9zdGVwc0RvbmUAAAkAzAgCCQEMSW50ZWdlckVudHJ5AgIYcmViYWxhbmNlX2xhc3RTdGVwSGVpZ2h0BQZoZWlnaHQJAMwIAgkBDEludGVnZXJFbnRyeQICFXJlYmFsYW5jZV9zdGVwc0Ftb3VudAULc3RlcHNBbW91bnQJAMwIAgkBDEludGVnZXJFbnRyeQICF3JlYmFsYW5jZV9zdGVwc0ludGVydmFsBQ1zdGVwc0ludGVydmFsCQDMCAIJAQtTdHJpbmdFbnRyeQICEnJlYmFsYW5jZV9hc3NldElkcwULYXNzZXRJZHNTdHIJAMwIAgkBC1N0cmluZ0VudHJ5AgIYcmViYWxhbmNlX25ld0Jhc2VUb2tlbklkBQ5iYXNlVG9rZW5JZFN0cgkAzAgCCQELU3RyaW5nRW50cnkCAhVyZWJhbGFuY2VfYXNzZXREZWx0YXMJALkJAgULYXNzZXREZWx0YXMCASwFA25pbAUOcGF5bWVudEVudHJpZXMFDHN0b3JlV2VpZ2h0cwkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpAQ9zdGVwUmViYWxhbmNpbmcAAwkBASEBCQELdmFsdWVPckVsc2UCCQCbCAIFBHRoaXMCFHJlYmFsYW5jZV9pblByb2dyZXNzBwkAAgECGm5vIHJlYmFsYW5jaW5nIGluIHByb2dyZXNzBA5sYXN0U3RlcEhlaWdodAkBEUBleHRyTmF0aXZlKDEwNTUpAQIYcmViYWxhbmNlX2xhc3RTdGVwSGVpZ2h0BAxzdGVwSW50ZXJ2YWwJARFAZXh0ck5hdGl2ZSgxMDU1KQECF3JlYmFsYW5jZV9zdGVwc0ludGVydmFsBAlzdGVwc0RvbmUJARFAZXh0ck5hdGl2ZSgxMDU1KQECE3JlYmFsYW5jZV9zdGVwc0RvbmUEDm5leHRTdGVwSGVpZ2h0CQBkAgUObGFzdFN0ZXBIZWlnaHQFDHN0ZXBJbnRlcnZhbAMJAGYCBQ5uZXh0U3RlcEhlaWdodAUGaGVpZ2h0CQACAQIRY2FuJ3QgYmUgZG9uZSB5ZXQEC2Fzc2V0RGVsdGFzCQC1CQIJARFAZXh0ck5hdGl2ZSgxMDU4KQECFXJlYmFsYW5jZV9hc3NldERlbHRhcwIBLAQObmV3QXNzZXRJZHNTdHIJARFAZXh0ck5hdGl2ZSgxMDU4KQECFXRtcF9yZWJhbGFuY2VBc3NldElkcwQLbmV3QXNzZXRJZHMJALUJAgUObmV3QXNzZXRJZHNTdHICASwKAQFmAgVhY2N1bQphc3NldElkU3RyCQDOCAIFBWFjY3VtCQDMCAIJAKQDAQkAbgQJAGQCCQBoAgkBC3ZhbHVlT3JFbHNlAgkAnwgBCQCsAgICFnJlYmFsYW5jZV9zdGFydFdlaWdodF8FCmFzc2V0SWRTdHIAAACQTgkAaAIJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQthc3NldERlbHRhcwkBBXZhbHVlAQkAzwgCBQtuZXdBc3NldElkcwUKYXNzZXRJZFN0cgkAZAIFCXN0ZXBzRG9uZQABAAEAkE4FBkhBTEZVUAUDbmlsBAluZXdTaGFyZXMJALkJAgoAAiRsBQtuZXdBc3NldElkcwoAAiRzCQCQAwEFAiRsCgAFJGFjYzAFA25pbAoBBSRmNF8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQEBZgIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmNF8yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQIUTGlzdCBzaXplIGV4Y2VlZHMgMTAJAQUkZjRfMgIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIJAQUkZjRfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYABwAIAAkACgIBLAQObmV3VG9rZW5zQWRkZWQJARFAZXh0ck5hdGl2ZSgxMDU2KQECGHJlYmFsYW5jZV9uZXdUb2tlbnNBZGRlZAQDaW52AwMFDm5ld1Rva2Vuc0FkZGVkCQAAAgUJc3RlcHNEb25lAAAHCQD8BwQFBHRoaXMCGmRvUmViYWxhbmNpbmdXaXRoTmV3VG9rZW5zCQDMCAIFDm5ld0Fzc2V0SWRzU3RyCQDMCAIFCW5ld1NoYXJlcwkAzAgCCQERQGV4dHJOYXRpdmUoMTA1OCkBAhhyZWJhbGFuY2VfbmV3QmFzZVRva2VuSWQFA25pbAUDbmlsCQD8BwQFBHRoaXMCDWRvUmViYWxhbmNpbmcJAMwIAgUJbmV3U2hhcmVzBQNuaWwFA25pbAMJAAACBQNpbnYFA2ludgQMbm90aWZ5SW52b2tlCQD8BwQFD3Bvb2xzSHViQWRkcmVzcwIQbm90aWZ5UG9vbENoYW5nZQUDbmlsBQNuaWwDCQAAAgUMbm90aWZ5SW52b2tlBQxub3RpZnlJbnZva2UECmlzRmluaXNoZWQJAGcCCQBkAgUJc3RlcHNEb25lAAEJARFAZXh0ck5hdGl2ZSgxMDU1KQECFXJlYmFsYW5jZV9zdGVwc0Ftb3VudAQHYWN0aW9ucwkAzAgCCQEMQm9vbGVhbkVudHJ5AgIUcmViYWxhbmNlX2luUHJvZ3Jlc3MJAQEhAQUKaXNGaW5pc2hlZAkAzAgCCQEMSW50ZWdlckVudHJ5AgITcmViYWxhbmNlX3N0ZXBzRG9uZQkAZAIFCXN0ZXBzRG9uZQABCQDMCAIJAQxJbnRlZ2VyRW50cnkCAhhyZWJhbGFuY2VfbGFzdFN0ZXBIZWlnaHQFBmhlaWdodAUDbmlsAwkAAAIFCXN0ZXBzRG9uZQAACQDOCAIFB2FjdGlvbnMJAMwIAgkBC1N0cmluZ0VudHJ5AgIPc3RhdGljX3Rva2VuSWRzBQ5uZXdBc3NldElkc1N0cgUDbmlsAwUKaXNGaW5pc2hlZAQPcmVtb3ZlZEFzc2V0c0xpCQC1CQIJAQx0cnlHZXRTdHJpbmcBAhdyZWJhbGFuY2VfcmVtb3ZlZEFzc2V0cwIBLAoBBnJtRGF0YQIFYWNjdW0HYXNzZXRJZAkAzggCBQVhY2N1bQkAzAgCCQELRGVsZXRlRW50cnkBCQCsAgIJAKwCAgIHc3RhdGljXwUHYXNzZXRJZAIGX3NjYWxlCQDMCAIJAQtEZWxldGVFbnRyeQEJAKwCAgkArAICAgdzdGF0aWNfBQdhc3NldElkAglfZGVjaW1hbHMJAMwIAgkBC0RlbGV0ZUVudHJ5AQkArAICCQCsAgICB3N0YXRpY18FB2Fzc2V0SWQCB193ZWlnaHQJAMwIAgkBC0RlbGV0ZUVudHJ5AQkArAICCQCsAgICB3N0YXRpY18FB2Fzc2V0SWQCCF9iYWxhbmNlBQNuaWwEAnJtCgACJGwFD3JlbW92ZWRBc3NldHNMaQoAAiRzCQCQAwEFAiRsCgAFJGFjYzAFA25pbAoBBSRmNV8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQEGcm1EYXRhAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGY1XzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhRMaXN0IHNpemUgZXhjZWVkcyAxMAkBBSRmNV8yAgkBBSRmNV8xAgkBBSRmNV8xAgkBBSRmNV8xAgkBBSRmNV8xAgkBBSRmNV8xAgkBBSRmNV8xAgkBBSRmNV8xAgkBBSRmNV8xAgkBBSRmNV8xAgkBBSRmNV8xAgUFJGFjYzAAAAABAAIAAwAEAAUABgAHAAgACQAKBBFmaW5hbEFzc2V0c0lkc1N0cgkBDHRyeUdldFN0cmluZwECEnJlYmFsYW5jZV9hc3NldElkcwQQQXNzZXRzV2VpZ2h0c1N0cgoAAiRsCQC1CQIFEWZpbmFsQXNzZXRzSWRzU3RyAgEsCgACJHMJAJADAQUCJGwKAAUkYWNjMAUDbmlsCgEFJGY2XzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJARdhZGRBc3NldFdlaWdodFRvU3RyTGlzdAIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmNl8yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQIUTGlzdCBzaXplIGV4Y2VlZHMgMTAJAQUkZjZfMgIJAQUkZjZfMQIJAQUkZjZfMQIJAQUkZjZfMQIJAQUkZjZfMQIJAQUkZjZfMQIJAQUkZjZfMQIJAQUkZjZfMQIJAQUkZjZfMQIJAQUkZjZfMQIJAQUkZjZfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYABwAIAAkACgkAzggCCQDOCAIFB2FjdGlvbnMFAnJtCQDMCAIJAQtTdHJpbmdFbnRyeQICD3N0YXRpY190b2tlbklkcwURZmluYWxBc3NldHNJZHNTdHIJAMwIAgkBC1N0cmluZ0VudHJ5AgITc3RhdGljX3Rva2VuV2VpZ2h0cwkAuQkCBRBBc3NldHNXZWlnaHRzU3RyAgEsCQDMCAIJAQxJbnRlZ2VyRW50cnkCAhNzdGF0aWNfdG9rZW5zQW1vdW50CQCQAwEJALUJAgURZmluYWxBc3NldHNJZHNTdHICASwFA25pbAUHYWN0aW9ucwkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpAQ1kb1JlYmFsYW5jaW5nAQ9hc3NldFdlaWdodHNTdHIEEWFzc2V0V2VpZ2h0c1N0ckxpCQC1CQIFD2Fzc2V0V2VpZ2h0c1N0cgIBLAQPYXNzZXRXZWlnaHRzU3VtCgACJGwFEWFzc2V0V2VpZ2h0c1N0ckxpCgACJHMJAJADAQUCJGwKAAUkYWNjMAAACgEFJGY0XzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAQNzdW0CBQIkYQkAkQMCBQIkbAUCJGkKAQUkZjRfMgICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkAAgECFExpc3Qgc2l6ZSBleGNlZWRzIDEwCQEFJGY0XzICCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECCQEFJGY0XzECBQUkYWNjMAAAAAEAAgADAAQABQAGAAcACAAJAAoEDWFzc2V0SWRzU3RyTGkJALUJAgkBDHRyeUdldFN0cmluZwECD3N0YXRpY190b2tlbklkcwIBLAMJAQIhPQIIBQFpBmNhbGxlcgUEdGhpcwkAAgECInRoaXMgY2FsbCBhdmFpbGFibGUgb25seSBmb3IgYWRtaW4ECG9sZEtNdWx0CQEIZ2V0S011bHQACgEHaGFuZGxlcgIEcGFycwdhc3NldElkBAVhY2N1bQgFBHBhcnMCXzEECmFzc2V0SWRTdHIJAQ5nZXRBc3NldFN0cmluZwEFB2Fzc2V0SWQKAQhoYW5kbGVyMgIFYWNjdW0BbgMJAAACBQFuBQdhc3NldElkCQEFdmFsdWUBCQDPCAIFCGFzc2V0SWRzBQFuBQVhY2N1bQQFVG9rZW4KAAIkbAUIYXNzZXRJZHMKAAIkcwkAkAMB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BSRmNV8xAgkBBSRmNV8xAgUFJGFjYzAAAAABAAIAAwAEAAUABgAHAAgACQAKBAthZGRlZEFzc2V0cwkAtQkCCQEMdHJ5R2V0U3RyaW5nAQIVcmViYWxhbmNlX2FkZGVkQXNzZXRzAgEsCgEQZmluZEFzc2V0UGF5bWVudAEHYXNzZXRJZAkBC3ZhbHVlT3JFbHNlAgkAnwgBCQCsAgICGnJlYmFsYW5jZV9hdHRhY2hlZFBheW1lbnRfCQEOZ2V0QXNzZXRTdHJpbmcBBQdhc3NldElkAAAKARNhZGRBc3NldEJhbGFuY2VUb0xpAgJsaQdhc3NldElkCQDOCAIFAmxpCQDMCAIJARBmaW5kQXNzZXRQYXltZW50AQUHYXNzZXRJZAUDbmlsBBBhdHRhY2hlZEJhbGFuY2VzCgACJGwFC25ld0Fzc2V0SWRzCgACJHMJAJADAQUCJGwKAAUkYWNjMAUDbmlsCgEFJGY2XzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJARNhZGRBc3NldEJhbGFuY2VUb0xpAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGY2XzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhRMaXN0IHNpemUgZXhjZWVkcyAxMAkBBSRmNl8yAgkBBSRmNl8xAgkBBSRmNl8xAgkBBSRmNl8xAgkBBSRmNl8xAgkBBSRmNl8xAgkBBSRmNl8xAgkBBSRmNl8xAgkBBSRmNl8xAgkBBSRmNl8xAgkBBSRmNl8xAgUFJGFjYzAAAAABAAIAAwAEAAUABgAHAAgACQAKAwkBAiE9AggFAWkGY2FsbGVyBQR0aGlzCQACAQkArAICAiR0aGlzIGNhbGwgYXZhaWxhYmxlIG9ubHkgZm9yIGFkbWluLCAJAKUIAQgFAWkGY2FsbGVyBAhvbGRLTXVsdAkBCGdldEtNdWx0AAQEb2xkSwkBGWdldFZpcnR1YWxQb29sVG9rZW5BbW91bnQACgESbXlsdGlwbHlBc3NldHNGb3JLAgRwYXJzB2Fzc2V0SWQKAQxmaW5kQXNzZXROdW0CBWFjY3VtAW4DCQAAAgUBbgUHYXNzZXRJZAkBBXZhbHVlAQkAzwgCBQtuZXdBc3NldElkcwUBbgUFYWNjdW0ECGN1cnJlbnRLBQRwYXJzBAphc3NldElkU3RyCQEOZ2V0QXNzZXRTdHJpbmcBBQdhc3NldElkBAhUb2tlbk51bQoAAiRsBQtuZXdBc3NldElkcwoAAiRzCQCQAwEFAiRsCgAFJGFjYzAAAQoBBSRmN18xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQEMZmluZEFzc2V0TnVtAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGY3XzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhRMaXN0IHNpemUgZXhjZWVkcyAxMAkBBSRmN18yAgkBBSRmN18xAgkBBSRmN18xAgkBBSRmN18xAgkBBSRmN18xAgkBBSRmN18xAgkBBSRmN18xAgkBBSRmN18xAgkBBSRmN18xAgkBBSRmN18xAgkBBSRmN18xAgUFJGFjYzAAAAABAAIAAwAEAAUABgAHAAgACQAKBAZ3ZWlnaHQJAQ1wYXJzZUludFZhbHVlAQkAkQMCBRRuZXdBc3NldFdlaWdodHNTdHJMaQUIVG9rZW5OdW0EDmJhbGFuY2VJblN0YXRlCQENdHJ5R2V0SW50ZWdlcgEJAKwCAgkArAICAgdnbG9iYWxfBQphc3NldElkU3RyAghfYmFsYW5jZQQQYmFsYW5jZUluUGF5bWVudAkAkQMCBRBhdHRhY2hlZEJhbGFuY2VzBQhUb2tlbk51bQQHYmFsYW5jZQkAZAIFDmJhbGFuY2VJblN0YXRlBRBiYWxhbmNlSW5QYXltZW50BA1hc3NldERlY2ltYWxzAwkAAAIFB2Fzc2V0SWQFBHVuaXQACAgJAQV2YWx1ZQEJAOwHAQkBBXZhbHVlAQUHYXNzZXRJZAhkZWNpbWFscwMJAGcCAAAFB2JhbGFuY2UJAAIBCQCsAgICRHlvdSBuZWVkIHRvIGF0dGFjaCBhbGwgbmV3IGFzc2V0cyBpbiBwYXltZW50LiB0aGlzIGFzc2V0IGlzIG1pc3NlZDogBQphc3NldElkU3RyCQBrAwUIY3VycmVudEsJAGwGBQdiYWxhbmNlBQ1hc3NldERlY2ltYWxzBQZ3ZWlnaHQFFUFzc2V0c1dlaWdodHNEZWNpbWFscwAIBQVGTE9PUgUGU2NhbGU4BARuZXdLCgACJGwFC25ld0Fzc2V0SWRzCgACJHMJAJADAQUCJGwKAAUkYWNjMAUOUG9vbFRva2VuU2NhbGUKAQUkZjdfMQICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkBEm15bHRpcGx5QXNzZXRzRm9ySwIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmN18yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQIUTGlzdCBzaXplIGV4Y2VlZHMgMTAJAQUkZjdfMgIJAQUkZjdfMQIJAQUkZjdfMQIJAQUkZjdfMQIJAQUkZjdfMQIJAQUkZjdfMQIJAQUkZjdfMQIJAQUkZjdfMQIJAQUkZjdfMQIJAQUkZjdfMQIJAQUkZjdfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYABwAIAAkACgQIbmV3S011bHQJAGsDBQhvbGRLTXVsdAUEbmV3SwUEb2xkSwoBE2FkZFRva2VuRGF0YUVudHJpZXMCBWFjY3VtCGFzc2V0TnVtBAphc3NldElkU3RyCQCRAwIFEG5ld0Fzc2V0SWRzU3RyTGkFCGFzc2V0TnVtBAdhc3NldElkCQCRAwIFC25ld0Fzc2V0SWRzBQhhc3NldE51bQQNYXNzZXREZWNpbWFscwMJAAACBQdhc3NldElkBQR1bml0AAgICQEFdmFsdWUBCQDsBwEJAQV2YWx1ZQEFB2Fzc2V0SWQIZGVjaW1hbHMEDG5ld0Fzc2V0RGF0YQMJAQIhPQIJAM8IAgULYWRkZWRBc3NldHMFCmFzc2V0SWRTdHIFBHVuaXQJAMwIAgkBDEludGVnZXJFbnRyeQIJAKwCAgkArAICAgdnbG9iYWxfBQphc3NldElkU3RyAghfYmFsYW5jZQkAkQMCBRBhdHRhY2hlZEJhbGFuY2VzBQhhc3NldE51bQkAzAgCCQEMSW50ZWdlckVudHJ5AgkArAICCQCsAgICB3N0YXRpY18FCmFzc2V0SWRTdHICBl9zY2FsZQkAbAYACgAABQ1hc3NldERlY2ltYWxzAAAAAAUERE9XTgkAzAgCCQEMSW50ZWdlckVudHJ5AgkArAICCQCsAgICB3N0YXRpY18FCmFzc2V0SWRTdHICCV9kZWNpbWFscwUNYXNzZXREZWNpbWFscwUDbmlsBQNuaWwDCQBnAgUIYXNzZXROdW0JAJADAQUUbmV3QXNzZXRXZWlnaHRzU3RyTGkFBWFjY3VtCQDOCAIJAM4IAgUFYWNjdW0JAMwIAgkBDEludGVnZXJFbnRyeQIJAKwCAgkArAICAgdzdGF0aWNfBQphc3NldElkU3RyAgdfd2VpZ2h0CQEFdmFsdWUBCQC2CQEJAJEDAgUUbmV3QXNzZXRXZWlnaHRzU3RyTGkFCGFzc2V0TnVtBQNuaWwFDG5ld0Fzc2V0RGF0YQkAzggCCgACJGwJAMwIAgAACQDMCAIAAQkAzAgCAAIJAMwIAgADCQDMCAIABAkAzAgCAAUJAMwIAgAGCQDMCAIABwkAzAgCAAgJAMwIAgAJBQNuaWwKAAIkcwkAkAMBBQIkbAoABSRhY2MwBQNuaWwKAQUkZjhfMQICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkBE2FkZFRva2VuRGF0YUVudHJpZXMCBQIkYQkAkQMCBQIkbAUCJGkKAQUkZjhfMgICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkAAgECFExpc3Qgc2l6ZSBleGNlZWRzIDEwCQEFJGY4XzICCQEFJGY4XzECCQEFJGY4XzECCQEFJGY4XzECCQEFJGY4XzECCQEFJGY4XzECCQEFJGY4XzECCQEFJGY4XzECCQEFJGY4XzECCQEFJGY4XzECCQEFJGY4XzECBQUkYWNjMAAAAAEAAgADAAQABQAGAAcACAAJAAoJAMwIAgkBC1N0cmluZ0VudHJ5AgIPc3RhdGljX3Rva2VuSWRzBQthc3NldElkc1N0cgkAzAgCCQELU3RyaW5nRW50cnkCAg9zdGF0aWNfZmVlVG9rZW4FC2ZlZUFzc2V0U3RyCQDMCAIJAQtTdHJpbmdFbnRyeQICE3N0YXRpY190b2tlbldlaWdodHMFD2Fzc2V0V2VpZ2h0c1N0cgkAzAgCCQEMSW50ZWdlckVudHJ5AgITc3RhdGljX3Rva2Vuc0Ftb3VudAkAkAMBBQtuZXdBc3NldElkcwkAzAgCCQEMSW50ZWdlckVudHJ5AgIMc3RhdGljX0tNdWx0BQhuZXdLTXVsdAUDbmlsAQJ0eAEGdmVyaWZ5AAMJAQppc1NodXRkb3duAAcDCQD0AwMIBQJ0eAlib2R5Qnl0ZXMJAJEDAggFAnR4BnByb29mcwAACAUCdHgPc2VuZGVyUHVibGljS2V5BgkA9AMDCAUCdHgJYm9keUJ5dGVzCQCRAwIIBQJ0eAZwcm9vZnMAAAUMbWFzdGVyUHViS2V5MQx/5Q==", "height": 3953781, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: 96SGeYwaFyexHGiT5At8NHeMopCH8CRfHZKRHoPWofv8 Next: none Diff:
OldNewDifferences
11 {-# STDLIB_VERSION 6 #-}
22 {-# SCRIPT_TYPE ACCOUNT #-}
33 {-# CONTENT_TYPE DAPP #-}
4-let usdnAssetId = base58'DG2xFkPdDwKUoBkzGAhQtLpSGzfXLiCYPEzeKH2Ad24p'
4+let VERSION = "PZ-1.0.8 PROD"
55
6-let puzzleAssetId = base58'HEB8Qaw9xrWpWs8tHsiATYGBWDBtP2S7kcPALrMu43AS'
6+let AssetsWeightsDecimals = 4
77
8-let usdtAssetId = base58'34N9YcEETLWn93qYQ64EsP1x89tSruJU44RrEMSXXEPJ'
8+let Scale = 10000
99
10-let usdnAssetIdStr = "DG2xFkPdDwKUoBkzGAhQtLpSGzfXLiCYPEzeKH2Ad24p"
10+let Scale8 = 100000000
1111
12-let puzzleAssetIdStr = "HEB8Qaw9xrWpWs8tHsiATYGBWDBtP2S7kcPALrMu43AS"
12+let Scale16 = 10000000000000000
1313
14-let usdtAssetIdStr = "34N9YcEETLWn93qYQ64EsP1x89tSruJU44RrEMSXXEPJ"
14+let FeeScale = 10000
1515
16-let parentPoolAddress = Address(base58'3PFDgzu1UtswAkCMxqqQjbTeHaX4cMab8Kh')
16+let PoolTokenDecimals = 8
1717
18-let masterAddress = Address(base58'3PLjwHcz9NEuaTo63NZR9B9okQiKQxZSbmf')
18+let PoolTokenScale = pow(10, 0, PoolTokenDecimals, 0, 0, HALFUP)
1919
20-let masterPubKey = base58'4z8CKSYQBKkzx7PBb5uBP1YPa6YAHRNTApW1sQVHT5eU'
20+let MIN_STEPS_AMOUNT = 1
21+
22+let MAX_STEPS_AMOUNT = 500
23+
24+let MIN_STEPS_INTERVAL = 1
25+
26+let MAX_STEPS_INTERVAL = 10000
2127
2228 func tryGetInteger (key) = match getInteger(this, key) {
2329 case b: Int =>
4349 }
4450
4551
52+func tryGetStringOrThrow (key) = match getString(this, key) {
53+ case b: String =>
54+ b
55+ case _ =>
56+ throw(("no such key in data storage: " + key))
57+}
58+
59+
4660 func getAssetString (assetId) = match assetId {
4761 case b: ByteVector =>
4862 toBase58String(b)
5670 else fromBase58String(assetIdStr)
5771
5872
73+func getTokenBalance (assetId) = match assetId {
74+ case t: ByteVector =>
75+ assetBalance(this, t)
76+ case _ =>
77+ wavesBalance(this).available
78+}
79+
80+
5981 func addAssetBytesToList (accum,item) = (accum ++ [getAssetBytes(item)])
6082
6183
6284 func addAssetWeightToList (accum,item) = (accum ++ [tryGetInteger((("static_" + getAssetString(item)) + "_weight"))])
85+
86+
87+func addAssetWeightToStrList (accum,item) = (accum ++ [toString(tryGetInteger((("static_" + item) + "_weight")))])
6388
6489
6590 func addAssetDecimalsToList (accum,item) = (accum ++ [tryGetInteger((("static_" + getAssetString(item)) + "_decimals"))])
7095
7196 func addIntToList (accum,item) = (accum ++ [parseIntValue(item)])
7297
98+
99+let usdnAssetId = base58'DG2xFkPdDwKUoBkzGAhQtLpSGzfXLiCYPEzeKH2Ad24p'
100+
101+let puzzleAssetId = base58'HEB8Qaw9xrWpWs8tHsiATYGBWDBtP2S7kcPALrMu43AS'
102+
103+let usdtAssetId = base58'34N9YcEETLWn93qYQ64EsP1x89tSruJU44RrEMSXXEPJ'
104+
105+let usdtPptAssetId = base58'9wc3LXNA4TEBsXyKtoLE9mrbDD7WMHXvXrCjZvabLAsi'
106+
107+let wavesAssetId = unit
108+
109+let usdnAssetIdStr = "DG2xFkPdDwKUoBkzGAhQtLpSGzfXLiCYPEzeKH2Ad24p"
110+
111+let puzzleAssetIdStr = "HEB8Qaw9xrWpWs8tHsiATYGBWDBtP2S7kcPALrMu43AS"
112+
113+let usdtAssetIdStr = "34N9YcEETLWn93qYQ64EsP1x89tSruJU44RrEMSXXEPJ"
114+
115+let usdtPptAssetIdStr = "9wc3LXNA4TEBsXyKtoLE9mrbDD7WMHXvXrCjZvabLAsi"
116+
117+let wavesAssetIdStr = "WAVES"
118+
119+let supportedFeeAssetsStr = ["DG2xFkPdDwKUoBkzGAhQtLpSGzfXLiCYPEzeKH2Ad24p", "HEB8Qaw9xrWpWs8tHsiATYGBWDBtP2S7kcPALrMu43AS", "34N9YcEETLWn93qYQ64EsP1x89tSruJU44RrEMSXXEPJ", "9wc3LXNA4TEBsXyKtoLE9mrbDD7WMHXvXrCjZvabLAsi", "WAVES"]
120+
121+let masterPubKey = base58'4z8CKSYQBKkzx7PBb5uBP1YPa6YAHRNTApW1sQVHT5eU'
122+
123+let parentPoolAddress = Address(base58'3PFDgzu1UtswAkCMxqqQjbTeHaX4cMab8Kh')
124+
125+let masterAddress = Address(base58'3PLjwHcz9NEuaTo63NZR9B9okQiKQxZSbmf')
126+
127+let oracleAddress = Address(base58'3P8d1E1BLKoD52y3bQJ1bDTd2TD1gpaLn9t')
128+
129+let stakingAddress = Address(base58'3PFTbywqxtFfukX3HyT881g4iW5K4QL3FAS')
130+
131+let feesAddress = Address(base58'3P4kBiU4wr2yV1S5gMfu3MdkVvy7kxXHsKe')
132+
133+let poolsHubAddress = Address(base58'3P5YutjDNC3hABBVsveFuZTTbQ5PdtSDBgk')
134+
135+let shutdownAddressStr = "3PEpv9hRFWEEBU22WRnLsw1bH4YGtcU728o'"
73136
74137 let T = tryGetInteger("static_tokensAmount")
75138
135198
136199 let Fee = tryGetInteger("static_fee")
137200
138-let AssetsWeightsDecimals = 4
139-
140-let Scale = 10000
141-
142-let Scale8 = 100000000
143-
144-let FeeScale = 10000
145-
146-let PoolTokenDecimals = 8
147-
148-let PoolTokenScale = pow(10, 0, PoolTokenDecimals, 0, 0, HALFUP)
149-
150201 let earnedAssets = assetIds
151202
152-func isShutdown () = match getBoolean(Address(base58'3PEpv9hRFWEEBU22WRnLsw1bH4YGtcU728o'), "is_shutdown") {
153- case x: Boolean =>
203+func isShutdown () = if ((shutdownAddressStr == ""))
204+ then false
205+ else {
206+ let shutdownAddress = Address(fromBase58String(shutdownAddressStr))
207+ match getBoolean(shutdownAddress, "is_shutdown") {
208+ case x: Boolean =>
209+ x
210+ case _ =>
211+ false
212+ }
213+ }
214+
215+
216+func getCurrentTokenBalance (tokenNum) = {
217+ let tokenIdStr = getAssetString(assetIds[tokenNum])
218+ tryGetInteger((("global_" + tokenIdStr) + "_balance"))
219+ }
220+
221+
222+func getKMult () = match getInteger("static_KMult") {
223+ case x: Int =>
154224 x
155225 case _ =>
156- false
226+ Scale16
157227 }
158228
159229
160-func getCurrentTokenBalance (tokenType) = {
161- let tokenId = getAssetString(assetIds[tokenType])
162- tryGetInteger((("global_" + tokenId) + "_balance"))
230+func saveCurrentWeights () = {
231+ let assetIdsLi = split(tryGetString("static_tokenIds"), ",")
232+ func s (accum,assetId) = (accum ++ [IntegerEntry(("rebalance_startWeight_" + assetId), tryGetInteger((("static_" + assetId) + "_weight")))])
233+
234+ let $l = assetIdsLi
235+ let $s = size($l)
236+ let $acc0 = nil
237+ func $f4_1 ($a,$i) = if (($i >= $s))
238+ then $a
239+ else s($a, $l[$i])
240+
241+ func $f4_2 ($a,$i) = if (($i >= $s))
242+ then $a
243+ else throw("List size exceeds 10")
244+
245+ $f4_2($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
163246 }
164247
165248
249+func getVirtualPoolTokenAmount () = fraction(tryGetInteger("global_poolToken_amount"), getKMult(), Scale16)
250+
251+
166252 func calculatePIssued (amount,tokenId) = {
167- let Psupply = tryGetInteger("global_poolToken_amount")
253+ let Psupply = getVirtualPoolTokenAmount()
168254 let Balance = tryGetInteger((("global_" + getAssetString(tokenId)) + "_balance"))
169- fraction(amount, Psupply, Balance, DOWN)
255+ let t1 = fraction(amount, Psupply, Balance, DOWN)
256+ t1
170257 }
171258
172259
202289
203290 func calculateUsdnValue (assetId,amount,aBalance,givenUsdnBalance) = {
204291 let usdnInPool = indexOf(assetIds, usdnAssetId)
292+ let puzzleInPool = indexOf(assetIds, puzzleAssetId)
205293 let usdtInPool = indexOf(assetIds, usdtAssetId)
206- let assetWeight = AssetsWeights[value(indexOf(assetIds, assetId))]
207- if (if ((usdnInPool == unit))
208- then (usdtInPool == unit)
209- else false)
294+ let usdtPptInPool = indexOf(assetIds, usdtPptAssetId)
295+ let wavesInPool = indexOf(assetIds, unit)
296+ let assetWeight = tryGetInteger((("static_" + getAssetString(assetId)) + "_weight"))
297+ let feeAssetStr = tryGetString("static_feeToken")
298+ if ((feeAssetStr == puzzleAssetIdStr))
210299 then {
211300 let puzzleWeight = AssetsWeights[value(indexOf(assetIds, puzzleAssetId))]
212301 let puzzleBalance = tryGetInteger((("global_" + puzzleAssetIdStr) + "_balance"))
214303 let puzzlePrice = getIntegerValue(parentPoolAddress, "global_lastPuzzlePrice")
215304 fraction((amountInPuzzle * puzzlePrice), 1, Scale8)
216305 }
217- else if ((usdtInPool != unit))
306+ else if ((feeAssetStr == usdtAssetIdStr))
218307 then {
219308 let usdtWeight = AssetsWeights[value(usdtInPool)]
220309 let usdtBalance = tryGetInteger((("global_" + usdtAssetIdStr) + "_balance"))
221310 fraction(amount, (usdtBalance / usdtWeight), (aBalance / assetWeight))
222311 }
223- else {
224- let usdnWeight = AssetsWeights[value(indexOf(assetIds, usdnAssetId))]
225- let usdnBalance = match givenUsdnBalance {
226- case x: Int =>
227- givenUsdnBalance
228- case _ =>
229- tryGetInteger((("global_" + getAssetString(usdnAssetId)) + "_balance"))
230- }
231- fraction(amount, (value(usdnBalance) / usdnWeight), (aBalance / assetWeight))
232- }
312+ else if ((feeAssetStr == usdtPptAssetIdStr))
313+ then {
314+ let usdtWeight = AssetsWeights[value(usdtPptInPool)]
315+ let usdtBalance = tryGetInteger((("global_" + usdtPptAssetIdStr) + "_balance"))
316+ fraction(amount, (usdtBalance / usdtWeight), (aBalance / assetWeight))
317+ }
318+ else if ((feeAssetStr == usdnAssetIdStr))
319+ then {
320+ let usdnWeight = AssetsWeights[value(indexOf(assetIds, usdnAssetId))]
321+ let usdnBalance = match givenUsdnBalance {
322+ case x: Int =>
323+ givenUsdnBalance
324+ case _ =>
325+ tryGetInteger((("global_" + getAssetString(usdnAssetId)) + "_balance"))
326+ }
327+ fraction(amount, (value(usdnBalance) / usdnWeight), (aBalance / assetWeight))
328+ }
329+ else {
330+ let wavesWeight = 3000
331+ let wBalance = (tryGetInteger("global_WAVES_balance") / 50)
332+ fraction(amount, (wBalance / wavesWeight), (aBalance / assetWeight))
333+ }
334+ }
335+
336+
337+func getPriceFromOracle (assetIdStr) = match getInteger(oracleAddress, (assetIdStr + "_twap5B")) {
338+ case x: Int =>
339+ x
340+ case _ =>
341+ 0
342+}
343+
344+
345+func calculateUsdValue (assetId,amount,aBalance) = {
346+ let assetWeight = tryGetInteger((("static_" + getAssetString(assetId)) + "_weight"))
347+ let feeAssetStr = tryGetString("static_feeToken")
348+ let feeAssetScale = getIntegerValue(this, (("static_" + feeAssetStr) + "_scale"))
349+ let feeAssetNum = value(indexOf(assetIds, getAssetBytes(feeAssetStr)))
350+ let feeAssetWeight = AssetsWeights[feeAssetNum]
351+ let feeAssetBalance = tryGetInteger((("global_" + feeAssetStr) + "_balance"))
352+ let valInFeeAsset = fraction(amount, (feeAssetBalance / feeAssetWeight), (aBalance / assetWeight))
353+ let feeAssetPrice = getPriceFromOracle(feeAssetStr)
354+ fraction(valInFeeAsset, feeAssetPrice, feeAssetScale)
233355 }
234356
235357
300422
301423 func handleTokenChange (accum,tokenId) = {
302424 let Bk = tryGetInteger((("global_" + getAssetString(tokenId)) + "_balance"))
303- let PSupply = tryGetInteger("global_poolToken_amount")
425+ let PSupply = getVirtualPoolTokenAmount()
304426 let tokenDecimals = tryGetInteger((("static_" + getAssetString(tokenId)) + "_scale"))
305- let Dk = fraction((fraction((PSupply + PIssued), tokenDecimals, PSupply, CEILING) - tokenDecimals), Bk, tokenDecimals, CEILING)
427+ let a1 = fraction((toBigInt((PSupply + PIssued)) * toBigInt(Scale8)), toBigInt(tokenDecimals), toBigInt(PSupply), CEILING)
428+ let Dk = toInt(fraction((a1 - (toBigInt(tokenDecimals) * toBigInt(Scale8))), toBigInt(Bk), (toBigInt(tokenDecimals) * toBigInt(Scale8)), CEILING))
306429 let paymentAmount = getTokenPaymentAmount(tokenId)
307- let toReturn = ((if ((paymentAmount != 0))
308- then paymentAmount
309- else 0) - Dk)
430+ let toReturn = (paymentAmount - Dk)
310431 let t = if (if (needChange)
311432 then (toReturn > 0)
312433 else false)
333454 func handlePoolTokensRedeem (PRedeemed,userAddress) = {
334455 func handleTokenRedeem (accum,tokenId) = {
335456 let Bk = tryGetInteger((("global_" + getAssetString(tokenId)) + "_balance"))
336- let PSupply = tryGetInteger("global_poolToken_amount")
457+ let PSupply = getVirtualPoolTokenAmount()
337458 let tokenDecimals = tryGetInteger((("static_" + getAssetString(tokenId)) + "_scale"))
338- let amount = toInt(fraction((toBigInt(Scale8) - fraction(toBigInt((PSupply - PRedeemed)), toBigInt(Scale8), toBigInt(PSupply), CEILING)), toBigInt(Bk), toBigInt(Scale8), DOWN))
459+ let psuppl = fraction((toBigInt((PSupply - PRedeemed)) * toBigInt(Scale8)), toBigInt(Scale8), toBigInt(PSupply), DOWN)
460+ let amount = toInt(fraction((toBigInt(Scale16) - psuppl), toBigInt(Bk), toBigInt(Scale16), CEILING))
339461 (accum ++ [IntegerEntry((("global_" + getAssetString(tokenId)) + "_balance"), (Bk - amount)), ScriptTransfer(userAddress, amount, tokenId)])
340462 }
341463
359481 let IndexOut = value(indexOf(assetIds, assetOut))
360482 if ((IndexIn == IndexOut))
361483 then AmountIn
362- else fraction(BalanceOut, ((Scale8 * Scale8) - toInt(pow(fraction(toBigInt(BalanceIn), toBigInt((Scale8 * Scale8)), toBigInt((BalanceIn + AmountIn)), HALFUP), 16, toBigInt(fraction(AssetsWeights[IndexIn], 10000, AssetsWeights[IndexOut])), 4, 16, CEILING))), (Scale8 * Scale8), DOWN)
484+ else fraction(BalanceOut, ((Scale8 * Scale8) - toInt(pow(fraction(toBigInt((BalanceIn * 10000)), toBigInt((Scale8 * Scale8)), toBigInt(((BalanceIn + AmountIn) * 10000)), HALFUP), 16, toBigInt(fraction(AssetsWeights[IndexIn], 1000000000000, AssetsWeights[IndexOut])), 12, 16, CEILING))), (Scale8 * Scale8), HALFEVEN)
363485 }
364-
365-
366-func getTokenBalance (assetId) = match assetId {
367- case t: ByteVector =>
368- assetBalance(this, t)
369- case _ =>
370- wavesBalance(this).available
371-}
372486
373487
374488 func calculateCurrentAssetInterest (assetId,assetIdStr,aBalance,tokenEarningsLastCheck) = {
400514 let transfer = if ((rewardAmount == 0))
401515 then nil
402516 else [ScriptTransfer(address, rewardAmount, assetId)]
403- $Tuple2(((accum._1 ++ transfer) ++ [IntegerEntry((("global_lastCheck_" + assetIdStr) + "_earnings"), (currentTokenEarnings - rewardAmount)), IntegerEntry((("global_lastCheck_" + assetIdStr) + "_interest"), currentTokenInterest), IntegerEntry((((addressStr + "_lastCheck_") + assetIdStr) + "_interest"), currentTokenInterest)]), (accum._2 + calculateUsdnValue(assetId, rewardAmount, aBalance, unit)))
517+ $Tuple2(((accum._1 ++ transfer) ++ [IntegerEntry((("global_lastCheck_" + assetIdStr) + "_earnings"), (currentTokenEarnings - rewardAmount)), IntegerEntry((("global_lastCheck_" + assetIdStr) + "_interest"), currentTokenInterest), IntegerEntry((((addressStr + "_lastCheck_") + assetIdStr) + "_interest"), currentTokenInterest)]), (accum._2 + calculateUsdValue(assetId, rewardAmount, aBalance)))
404518 }
405519
406520 let accum = {
430544 func sum (accum,n) = (accum + parseIntValue(n))
431545
432546
547+func checkFeeAsset (accum,next) = if (if ((indexOf(supportedFeeAssetsStr, next) != unit))
548+ then (accum == "")
549+ else false)
550+ then next
551+ else accum
552+
553+
554+func getTmpRebalanceIds (newAssetIdsLi) = {
555+ let currentAssetIdsLi = split(tryGetString("static_tokenIds"), ",")
556+ let result = newAssetIdsLi
557+ func f (accum,assetId) = if ((indexOf(result, assetId) == unit))
558+ then (accum ++ [assetId])
559+ else accum
560+
561+ let $l = currentAssetIdsLi
562+ let $s = size($l)
563+ let $acc0 = result
564+ func $f4_1 ($a,$i) = if (($i >= $s))
565+ then $a
566+ else f($a, $l[$i])
567+
568+ func $f4_2 ($a,$i) = if (($i >= $s))
569+ then $a
570+ else throw("List size exceeds 10")
571+
572+ $f4_2($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
573+ }
574+
575+
576+func checkTokensChange (newAssetIdsLi) = {
577+ let currentAssetIdsLi = split(tryGetString("static_tokenIds"), ",")
578+ func rem (accum,assetId) = if ((indexOf(newAssetIdsLi, assetId) == unit))
579+ then (accum + 1)
580+ else accum
581+
582+ func add (accum,assetId) = if ((indexOf(currentAssetIdsLi, assetId) == unit))
583+ then (accum + 1)
584+ else accum
585+
586+ let removed = {
587+ let $l = currentAssetIdsLi
588+ let $s = size($l)
589+ let $acc0 = 0
590+ func $f4_1 ($a,$i) = if (($i >= $s))
591+ then $a
592+ else rem($a, $l[$i])
593+
594+ func $f4_2 ($a,$i) = if (($i >= $s))
595+ then $a
596+ else throw("List size exceeds 10")
597+
598+ $f4_2($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
599+ }
600+ let added = {
601+ let $l = newAssetIdsLi
602+ let $s = size($l)
603+ let $acc0 = 0
604+ func $f5_1 ($a,$i) = if (($i >= $s))
605+ then $a
606+ else add($a, $l[$i])
607+
608+ func $f5_2 ($a,$i) = if (($i >= $s))
609+ then $a
610+ else throw("List size exceeds 10")
611+
612+ $f5_2($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
613+ }
614+ (removed + added)
615+ }
616+
617+
618+func validatePayments (assetsList,payments) = {
619+ func getPaymentAssets (accum,next) = if ((0 >= next.amount))
620+ then throw(((("Too low payment amount for " + getAssetString(next.assetId)) + ": ") + toString(next.amount)))
621+ else (accum ++ [getAssetString(next.assetId)])
622+
623+ let paymentList = {
624+ let $l = payments
625+ let $s = size($l)
626+ let $acc0 = nil
627+ func $f4_1 ($a,$i) = if (($i >= $s))
628+ then $a
629+ else getPaymentAssets($a, $l[$i])
630+
631+ func $f4_2 ($a,$i) = if (($i >= $s))
632+ then $a
633+ else throw("List size exceeds 10")
634+
635+ $f4_2($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
636+ }
637+ func f1 (accum,next) = if ((indexOf(assetsList, next) == unit))
638+ then throw(((next + " asset is present in payments, but is not in new assets: ") + makeString(assetsList, ",")))
639+ else accum
640+
641+ func f2 (accum,next) = if ((indexOf(paymentList, next) == unit))
642+ then throw(((next + " asset is present in new assets, but is not in payments: ") + makeString(paymentList, ",")))
643+ else accum
644+
645+ let a1 = {
646+ let $l = paymentList
647+ let $s = size($l)
648+ let $acc0 = 1
649+ func $f5_1 ($a,$i) = if (($i >= $s))
650+ then $a
651+ else f1($a, $l[$i])
652+
653+ func $f5_2 ($a,$i) = if (($i >= $s))
654+ then $a
655+ else throw("List size exceeds 10")
656+
657+ $f5_2($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
658+ }
659+ let a2 = {
660+ let $l = assetsList
661+ let $s = size($l)
662+ let $acc0 = 1
663+ func $f6_1 ($a,$i) = if (($i >= $s))
664+ then $a
665+ else f2($a, $l[$i])
666+
667+ func $f6_2 ($a,$i) = if (($i >= $s))
668+ then $a
669+ else throw("List size exceeds 10")
670+
671+ $f6_2($f6_1($f6_1($f6_1($f6_1($f6_1($f6_1($f6_1($f6_1($f6_1($f6_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
672+ }
673+ (a1 + a2)
674+ }
675+
676+
433677 @Callable(i)
434678 func preInit (assetIdsStr,assetWeightsStr,baseTokenIdStr,poolDomain,poolOwner,fee) = {
435679 let poolOwnerAddress = Address(fromBase58String(poolOwner))
680+ let assetIdsStrLi = split(assetIdsStr, ",")
681+ let assetIdsLi = {
682+ let $l = assetIdsStrLi
683+ let $s = size($l)
684+ let $acc0 = nil
685+ func $f4_1 ($a,$i) = if (($i >= $s))
686+ then $a
687+ else addAssetBytesToList($a, $l[$i])
688+
689+ func $f4_2 ($a,$i) = if (($i >= $s))
690+ then $a
691+ else throw("List size exceeds 10")
692+
693+ $f4_2($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
694+ }
695+ let feeAssetStr = {
696+ let $l = assetIdsStrLi
697+ let $s = size($l)
698+ let $acc0 = ""
699+ func $f5_1 ($a,$i) = if (($i >= $s))
700+ then $a
701+ else checkFeeAsset($a, $l[$i])
702+
703+ func $f5_2 ($a,$i) = if (($i >= $s))
704+ then $a
705+ else throw("List size exceeds 10")
706+
707+ $f5_2($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
708+ }
436709 if (isShutdown())
437710 then throw("contract is on stop")
438711 else if ((this != i.caller))
439712 then throw("admin only")
440- else if ((size(poolDomain) > 13))
441- then throw("too large pool domain")
442- else if (if ((fee > 500))
443- then true
444- else (50 > fee))
445- then throw("fee value must be between 50 and 500 (0.5-5%)")
446- else if (if (if ((indexOf(assetIdsStr, puzzleAssetIdStr) == unit))
447- then (indexOf(assetIdsStr, usdnAssetIdStr) == unit)
448- else false)
449- then (indexOf(assetIdsStr, usdtAssetIdStr) == unit)
450- else false)
451- then throw("pool must have USDT, USDN or PUZZLE in the composition")
713+ else if ((feeAssetStr == ""))
714+ then throw("pool must have one of the supported fee assets in the composition")
715+ else if ((size(poolDomain) > 13))
716+ then throw("too large pool domain")
717+ else if (if ((fee > 500))
718+ then true
719+ else (0 > fee))
720+ then throw("fee value must be between 50 and 500 (0.5-5%)")
452721 else {
453- let assetIdsStrLi = split(assetIdsStr, ",")
454- let assetIdsLi = {
455- let $l = assetIdsStrLi
456- let $s = size($l)
457- let $acc0 = nil
458- func $f4_1 ($a,$i) = if (($i >= $s))
459- then $a
460- else addAssetBytesToList($a, $l[$i])
461-
462- func $f4_2 ($a,$i) = if (($i >= $s))
463- then $a
464- else throw("List size exceeds 10")
465-
466- $f4_2($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
467- }
468722 let assetWeightsStrLi = split(assetWeightsStr, ",")
469723 let assetWeightsSum = {
470724 let $l = assetWeightsStrLi
471725 let $s = size($l)
472726 let $acc0 = 0
473- func $f5_1 ($a,$i) = if (($i >= $s))
727+ func $f6_1 ($a,$i) = if (($i >= $s))
474728 then $a
475729 else sum($a, $l[$i])
476730
477- func $f5_2 ($a,$i) = if (($i >= $s))
731+ func $f6_2 ($a,$i) = if (($i >= $s))
478732 then $a
479733 else throw("List size exceeds 10")
480734
481- $f5_2($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
735+ $f6_2($f6_1($f6_1($f6_1($f6_1($f6_1($f6_1($f6_1($f6_1($f6_1($f6_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
482736 }
483- let feeAssetStr = if ((indexOf(assetIdsStr, usdnAssetIdStr) == unit))
484- then if ((indexOf(assetIdsStr, puzzleAssetIdStr) == unit))
485- then usdtAssetIdStr
486- else puzzleAssetIdStr
487- else usdnAssetIdStr
488737 func addTokenDataEntries (accum,assetNum) = if ((assetNum >= size(assetIdsLi)))
489738 then accum
490739 else {
503752 let $l = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
504753 let $s = size($l)
505754 let $acc0 = nil
506- func $f6_1 ($a,$i) = if (($i >= $s))
755+ func $f7_1 ($a,$i) = if (($i >= $s))
507756 then $a
508757 else addTokenDataEntries($a, $l[$i])
509758
510- func $f6_2 ($a,$i) = if (($i >= $s))
759+ func $f7_2 ($a,$i) = if (($i >= $s))
511760 then $a
512761 else throw("List size exceeds 10")
513762
514- $f6_2($f6_1($f6_1($f6_1($f6_1($f6_1($f6_1($f6_1($f6_1($f6_1($f6_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
515- } ++ [StringEntry("static_tokenIds", assetIdsStr), StringEntry("static_feeToken", feeAssetStr), StringEntry("static_tokenWeights", assetWeightsStr), IntegerEntry("static_tokensAmount", size(assetIdsLi)), StringEntry("static_poolDomain", poolDomain), StringEntry("static_baseTokenId", baseTokenIdStr), StringEntry("static_poolOwner", poolOwner), IntegerEntry("static_fee", fee)])
763+ $f7_2($f7_1($f7_1($f7_1($f7_1($f7_1($f7_1($f7_1($f7_1($f7_1($f7_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
764+ } ++ [StringEntry("static_tokenIds", assetIdsStr), StringEntry("static_feeToken", feeAssetStr), StringEntry("static_tokenWeights", assetWeightsStr), IntegerEntry("static_tokensAmount", size(assetIdsLi)), StringEntry("static_poolDomain", poolDomain), StringEntry("static_baseTokenId", baseTokenIdStr), StringEntry("static_poolOwner", poolOwner), IntegerEntry("static_fee", fee), IntegerEntry("static_KMult", Scale16)])
516765 }
517766 }
518767
603852
604853
605854 @Callable(i)
606-func generateIndex (needChange) = if (isShutdown())
607- then throw("contract is on stop")
608- else if ((size(i.payments) != T))
609- then throw(("you need to attach all pool tokens. amount of pool tokens: " + toString(T)))
610- else if (!(checkTokensValidity(i.payments)))
611- then throw("wrong assets attached")
855+func generateIndex (needChange) = if ((size(i.payments) != T))
856+ then throw(("you need to attach all pool tokens. amount of pool tokens: " + toString(T)))
857+ else if (!(checkTokensValidity(i.payments)))
858+ then throw("wrong assets attached")
859+ else {
860+ let PIssuedNoMult = getMinPIssued(i.payments)
861+ let result = handlePoolTokensAdd(PIssuedNoMult, i.payments, i.originCaller, needChange)
862+ let PIssuedWithMult = fraction(PIssuedNoMult, Scale16, getKMult(), DOWN)
863+ let reissue = Reissue(getBinaryValue("global_poolToken_id"), PIssuedWithMult, true)
864+ $Tuple2((result ++ [reissue, ScriptTransfer(i.caller, PIssuedWithMult, tryGetBinary("global_poolToken_id")), IntegerEntry("global_poolToken_amount", (tryGetInteger("global_poolToken_amount") + PIssuedWithMult))]), PIssuedWithMult)
865+ }
866+
867+
868+
869+@Callable(i)
870+func redeemIndex (sendToOrigin) = {
871+ let pmt = i.payments[0]
872+ if ((pmt.assetId != tryGetBinary("global_poolToken_id")))
873+ then throw("please attach pool share token")
874+ else if (isShutdown())
875+ then throw("contract is on stop")
612876 else {
613- let PIssued = getMinPIssued(i.payments)
614- let reissue = Reissue(getBinaryValue("global_poolToken_id"), PIssued, true)
615- let result = handlePoolTokensAdd(PIssued, i.payments, i.originCaller, needChange)
616- $Tuple2((result ++ [reissue, ScriptTransfer(i.caller, PIssued, tryGetBinary("global_poolToken_id")), IntegerEntry("global_poolToken_amount", (tryGetInteger("global_poolToken_amount") + PIssued))]), PIssued)
877+ let PRedeemedWithMult = pmt.amount
878+ let PRedeemedWithNoMult = fraction(PRedeemedWithMult, getKMult(), Scale16, DOWN)
879+ let result = handlePoolTokensRedeem(PRedeemedWithNoMult, if (sendToOrigin)
880+ then i.originCaller
881+ else i.caller)
882+ (result ++ [Burn(tryGetBinary("global_poolToken_id"), PRedeemedWithMult), IntegerEntry("global_poolToken_amount", (tryGetInteger("global_poolToken_amount") - PRedeemedWithMult))])
617883 }
884+ }
618885
619886
620887
622889 func stakeIndex () = {
623890 let addressStr = toString(i.originCaller)
624891 let pmt = i.payments[0]
625- if (isShutdown())
626- then throw("contract is on stop")
627- else if ((value(pmt.assetId) != tryGetBinary("global_poolToken_id")))
628- then throw("wrong asset attached")
629- else indexStakeResult(addressStr, pmt.amount)
892+ if ((value(pmt.assetId) != tryGetBinary("global_poolToken_id")))
893+ then throw("wrong asset attached")
894+ else indexStakeResult(addressStr, pmt.amount)
630895 }
631896
632897
633898
634899 @Callable(i)
635-func unstakeIndex (puzzleAmount) = {
900+func stakeIndexFor (addressStr) = {
901+ let pmt = i.payments[0]
902+ if ((value(pmt.assetId) != tryGetBinary("global_poolToken_id")))
903+ then throw("wrong asset attached")
904+ else indexStakeResult(addressStr, pmt.amount)
905+ }
906+
907+
908+
909+@Callable(i)
910+func unstakeIndex (indexAmount) = {
636911 let addressStr = toString(i.originCaller)
637- let puzzleAvailable = tryGetInteger((addressStr + "_indexStaked"))
912+ let indexAvailable = tryGetInteger((addressStr + "_indexStaked"))
638913 if (isShutdown())
639914 then throw("contract is on stop")
640- else if ((puzzleAmount > puzzleAvailable))
915+ else if ((indexAmount > indexAvailable))
641916 then throw("you don't have index tokens available")
642917 else if (isShutdown())
643918 then throw("contract is on stop")
644- else (claimResult(i.originCaller)._1 ++ [IntegerEntry((addressStr + "_indexStaked"), (puzzleAvailable - puzzleAmount)), IntegerEntry("global_indexStaked", (tryGetInteger("global_indexStaked") - puzzleAmount)), ScriptTransfer(i.caller, puzzleAmount, getBinaryValue("global_poolToken_id"))])
919+ else (claimResult(i.originCaller)._1 ++ [IntegerEntry((addressStr + "_indexStaked"), (indexAvailable - indexAmount)), IntegerEntry("global_indexStaked", (tryGetInteger("global_indexStaked") - indexAmount)), ScriptTransfer(i.caller, indexAmount, getBinaryValue("global_poolToken_id"))])
645920 }
646921
647922
659934
660935
661936 @Callable(i)
662-func redeemIndex (sendToOrigin) = {
663- let pmt = i.payments[0]
664- if ((pmt.assetId != tryGetBinary("global_poolToken_id")))
665- then throw("please attach pool share token")
666- else if (isShutdown())
667- then throw("contract is on stop")
668- else {
669- let PRedeemed = pmt.amount
670- let result = handlePoolTokensRedeem(PRedeemed, if (sendToOrigin)
671- then i.originCaller
672- else i.caller)
673- (result ++ [Burn(tryGetBinary("global_poolToken_id"), PRedeemed), IntegerEntry("global_poolToken_amount", (tryGetInteger("global_poolToken_amount") - PRedeemed))])
674- }
675- }
676-
677-
678-
679-@Callable(i)
680937 func swap (assetOut,minimum) = {
681938 let pmt = if ((size(i.payments) == 1))
682939 then value(i.payments[0])
684941 let AmountIn = value(i.payments[0].amount)
685942 let AssetIn = pmt.assetId
686943 let AssetOut = getAssetBytes(assetOut)
944+ let assetIn = getAssetString(AssetIn)
945+ let scaleIn = (Scale8 / tryGetInteger((("static_" + assetIn) + "_scale")))
946+ let scaleOut = (Scale8 / tryGetInteger((("static_" + assetOut) + "_scale")))
687947 let feeAssetOutStr = tryGetString("static_feeToken")
688948 let feeAssetOut = if ((feeAssetOutStr == ""))
689949 then usdnAssetId
690- else fromBase58String(feeAssetOutStr)
950+ else getAssetBytes(feeAssetOutStr)
691951 let AssetInBalance = tryGetInteger((("global_" + getAssetString(AssetIn)) + "_balance"))
692952 let AssetOutBalance = tryGetInteger((("global_" + assetOut) + "_balance"))
953+ let AssetInBalanceScaled = (AssetInBalance * scaleIn)
954+ let AssetOutBalanceScaled = (AssetOutBalance * scaleOut)
693955 let feeAmountIn = fraction(AmountIn, Fee, FeeScale)
694956 let cleanAmountIn = (AmountIn - feeAmountIn)
695- let AmountOut = calculateOutAmount(cleanAmountIn, AssetIn, AssetOut, AssetInBalance, AssetOutBalance)
957+ let cleanAmountInScaled = (cleanAmountIn * scaleIn)
958+ let AmountOut1 = calculateOutAmount(cleanAmountInScaled, AssetIn, AssetOut, AssetInBalanceScaled, AssetOutBalanceScaled)
959+ let AmountOut = fraction(AmountOut1, 1, scaleOut)
696960 let AssetOutBalance2 = (AssetOutBalance - AmountOut)
697961 let AssetInBalance2 = (AssetInBalance + cleanAmountIn)
698962 let feeAssetOutBalance = if ((feeAssetOut == AssetIn))
702966 else tryGetInteger((("global_" + getAssetString(feeAssetOut)) + "_balance"))
703967 let feeAmountOut = calculateOutAmount(feeAmountIn, AssetIn, feeAssetOut, AssetInBalance, feeAssetOutBalance)
704968 if ((minimum > AmountOut))
705- then throw(("amount to recieve is lower than given one: " + toString(AmountOut)))
969+ then throw("amount to recieve is lower than given one")
706970 else if ((AssetOut == AssetIn))
707971 then throw("this swap is not allowed")
708972 else if ((0 > (AssetOutBalance - AmountOut)))
712976 else {
713977 let creatorFee = fraction(feeAmountOut, 1, 10)
714978 let protocolFee = fraction(feeAmountOut, 4, 10)
715- let stakingTopUp = if ((feeAssetOut == usdnAssetId))
716- then reentrantInvoke(Address(base58'3PFTbywqxtFfukX3HyT881g4iW5K4QL3FAS'), "topUpReward", nil, [AttachedPayment(feeAssetOut, protocolFee)])
979+ let stakingTopUp = if (if ((feeAssetOut == usdnAssetId))
980+ then true
981+ else (feeAssetOut == puzzleAssetId))
982+ then reentrantInvoke(stakingAddress, "topUpReward", nil, [AttachedPayment(feeAssetOut, protocolFee)])
717983 else unit
718984 if ((stakingTopUp == stakingTopUp))
719985 then {
720- let newBalanceIn = (AssetInBalance2 - (if ((AssetIn == feeAssetOut))
721- then feeAmountOut
722- else 0))
986+ let newBalanceIn = AssetInBalance2
723987 let newBalanceOut = (AssetOutBalance2 - (if ((AssetOut == feeAssetOut))
724988 then feeAmountOut
725989 else 0))
731995 let assetInChange = IntegerEntry((("global_" + getAssetString(AssetIn)) + "_balance"), newBalanceIn)
732996 let assetOutChange = IntegerEntry((("global_" + assetOut) + "_balance"), newBalanceOut)
733997 let feeAssetOutChange = if ((newBalanceFeeAsset != unit))
734- then IntegerEntry((("global_" + getAssetString(feeAssetOut)) + "_balance"), feeAssetOutBalance)
998+ then IntegerEntry((("global_" + getAssetString(feeAssetOut)) + "_balance"), value(newBalanceFeeAsset))
735999 else StringEntry("hello", "world")
736- $Tuple2(([assetOutChange, assetInChange, feeAssetOutChange, ScriptTransfer(i.caller, AmountOut, AssetOut), ScriptTransfer(addressFromStringValue(tryGetString("static_poolOwner")), creatorFee, feeAssetOut), IntegerEntry("global_earnedByOwner", (tryGetInteger("global_earnedByOwner") + creatorFee)), IntegerEntry("global_volume", (tryGetInteger("global_volume") + calculateUsdnValue(AssetIn, AmountIn, AssetInBalance, feeAssetOutBalance)))] ++ (if ((stakingTopUp == unit))
737- then [ScriptTransfer(Address(base58'3P4kBiU4wr2yV1S5gMfu3MdkVvy7kxXHsKe'), protocolFee, feeAssetOut)]
1000+ let volumeUpdate = calculateUsdnValue(AssetIn, AmountIn, AssetInBalance, feeAssetOutBalance)
1001+ let volumeUsdUpdate = calculateUsdValue(AssetIn, AmountIn, AssetInBalance)
1002+ $Tuple2(([assetOutChange, assetInChange, feeAssetOutChange, ScriptTransfer(i.caller, AmountOut, AssetOut), ScriptTransfer(addressFromStringValue(tryGetString("static_poolOwner")), creatorFee, feeAssetOut), IntegerEntry("global_earnedByOwner", (tryGetInteger("global_earnedByOwner") + creatorFee)), IntegerEntry("global_volume", (tryGetInteger("global_volume") + volumeUpdate)), IntegerEntry("global_volume_usd", (tryGetInteger("global_volume_usd") + volumeUsdUpdate))] ++ (if ((stakingTopUp == unit))
1003+ then [ScriptTransfer(feesAddress, protocolFee, feeAssetOut)]
7381004 else nil)), AmountOut)
7391005 }
7401006 else throw("Strict value is not equal to itself.")
7411007 }
1008+ }
1009+
1010+
1011+
1012+@Callable(i)
1013+func swapReadOnly (assetIn,assetOut,AmountIn) = {
1014+ let AssetIn = getAssetBytes(assetIn)
1015+ let AssetOut = getAssetBytes(assetOut)
1016+ let scaleIn = (Scale8 / tryGetInteger((("static_" + assetIn) + "_scale")))
1017+ let scaleOut = (Scale8 / tryGetInteger((("static_" + assetOut) + "_scale")))
1018+ let feeAssetOutStr = tryGetString("static_feeToken")
1019+ let feeAssetOut = if ((feeAssetOutStr == ""))
1020+ then usdnAssetId
1021+ else getAssetBytes(feeAssetOutStr)
1022+ let AssetInBalance = tryGetInteger((("global_" + getAssetString(AssetIn)) + "_balance"))
1023+ let AssetOutBalance = tryGetInteger((("global_" + assetOut) + "_balance"))
1024+ let AssetInBalanceScaled = (AssetInBalance * scaleIn)
1025+ let AssetOutBalanceScaled = (AssetOutBalance * scaleOut)
1026+ let feeAmountIn = fraction(AmountIn, Fee, FeeScale)
1027+ let cleanAmountIn = (AmountIn - feeAmountIn)
1028+ let cleanAmountInScaled = (cleanAmountIn * scaleIn)
1029+ let AmountOut1 = calculateOutAmount(cleanAmountInScaled, AssetIn, AssetOut, AssetInBalanceScaled, AssetOutBalanceScaled)
1030+ let AmountOut = fraction(AmountOut1, 1, scaleOut)
1031+ let AssetOutBalance2 = (AssetOutBalance - AmountOut)
1032+ let AssetInBalance2 = (AssetInBalance + cleanAmountIn)
1033+ let feeAssetOutBalance = if ((feeAssetOut == AssetIn))
1034+ then AssetInBalance2
1035+ else if ((feeAssetOut == AssetOut))
1036+ then AssetOutBalance2
1037+ else tryGetInteger((("global_" + getAssetString(feeAssetOut)) + "_balance"))
1038+ let feeAmountOut = calculateOutAmount(feeAmountIn, AssetIn, feeAssetOut, AssetInBalance, feeAssetOutBalance)
1039+ if ((AssetOut == AssetIn))
1040+ then throw("this swap is not allowed")
1041+ else if ((0 > (AssetOutBalance - AmountOut)))
1042+ then throw("contract is out of reserves")
1043+ else if (isShutdown())
1044+ then throw("contract is on stop")
1045+ else $Tuple2(nil, AmountOut)
1046+ }
1047+
1048+
1049+
1050+@Callable(i)
1051+func transferOwnership (newOwnerAddress) = if ((toString(i.caller) != tryGetString("static_poolOwner")))
1052+ then throw("this call available only for pool owner")
1053+ else [StringEntry("static_poolOwner", newOwnerAddress)]
1054+
1055+
1056+
1057+@Callable(i)
1058+func setRebalancingPlan (assetIdsStr,assetWeightsStr,baseTokenIdStr,stepsAmount,stepsInterval) = if ((i.caller != addressFromStringValue(tryGetString("static_poolOwner"))))
1059+ then throw("this call available only for pool owner")
1060+ else if (valueOrElse(getBoolean(this, "rebalance_inProgress"), false))
1061+ then throw("rebalancing in progress")
1062+ else {
1063+ let newAssetWeightsStrLi = split(assetWeightsStr, ",")
1064+ let newAssetIdsStrLi = split(assetIdsStr, ",")
1065+ let feeAssetStr = {
1066+ let $l = newAssetIdsStrLi
1067+ let $s = size($l)
1068+ let $acc0 = ""
1069+ func $f4_1 ($a,$i) = if (($i >= $s))
1070+ then $a
1071+ else checkFeeAsset($a, $l[$i])
1072+
1073+ func $f4_2 ($a,$i) = if (($i >= $s))
1074+ then $a
1075+ else throw("List size exceeds 10")
1076+
1077+ $f4_2($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
1078+ }
1079+ let assetWeightsSum = {
1080+ let $l = newAssetWeightsStrLi
1081+ let $s = size($l)
1082+ let $acc0 = 0
1083+ func $f5_1 ($a,$i) = if (($i >= $s))
1084+ then $a
1085+ else sum($a, $l[$i])
1086+
1087+ func $f5_2 ($a,$i) = if (($i >= $s))
1088+ then $a
1089+ else throw("List size exceeds 10")
1090+
1091+ $f5_2($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
1092+ }
1093+ let oldAssetIds = getStringValue("static_tokenIds")
1094+ let oldAssetIdsLi = split(oldAssetIds, ",")
1095+ func findAdded (accum,next) = if ((indexOf(oldAssetIdsLi, next) == unit))
1096+ then (accum ++ [next])
1097+ else accum
1098+
1099+ func findRemoved (accum,next) = if ((indexOf(newAssetIdsStrLi, next) == unit))
1100+ then (accum ++ [next])
1101+ else accum
1102+
1103+ let addedAssets = {
1104+ let $l = newAssetIdsStrLi
1105+ let $s = size($l)
1106+ let $acc0 = nil
1107+ func $f6_1 ($a,$i) = if (($i >= $s))
1108+ then $a
1109+ else findAdded($a, $l[$i])
1110+
1111+ func $f6_2 ($a,$i) = if (($i >= $s))
1112+ then $a
1113+ else throw("List size exceeds 10")
1114+
1115+ $f6_2($f6_1($f6_1($f6_1($f6_1($f6_1($f6_1($f6_1($f6_1($f6_1($f6_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
1116+ }
1117+ let removedAssets = {
1118+ let $l = oldAssetIdsLi
1119+ let $s = size($l)
1120+ let $acc0 = nil
1121+ func $f7_1 ($a,$i) = if (($i >= $s))
1122+ then $a
1123+ else findRemoved($a, $l[$i])
1124+
1125+ func $f7_2 ($a,$i) = if (($i >= $s))
1126+ then $a
1127+ else throw("List size exceeds 10")
1128+
1129+ $f7_2($f7_1($f7_1($f7_1($f7_1($f7_1($f7_1($f7_1($f7_1($f7_1($f7_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
1130+ }
1131+ let validPayments = validatePayments(addedAssets, i.payments)
1132+ if ((size(newAssetIdsStrLi) != size(newAssetWeightsStrLi)))
1133+ then throw("assetIds and assetWeights should have same length")
1134+ else if ((feeAssetStr == ""))
1135+ then throw("pool must have one of the supported fee assets in the composition")
1136+ else if ((indexOf(newAssetIdsStrLi, baseTokenIdStr) == unit))
1137+ then throw("baseTokenId should be present in assetIds")
1138+ else if (if ((MIN_STEPS_AMOUNT > stepsAmount))
1139+ then true
1140+ else (stepsAmount > MAX_STEPS_AMOUNT))
1141+ then throw(((("Steps amount should be between " + toString(MIN_STEPS_AMOUNT)) + " and ") + toString(MAX_STEPS_AMOUNT)))
1142+ else if (if ((MIN_STEPS_INTERVAL > stepsInterval))
1143+ then true
1144+ else (stepsInterval > MAX_STEPS_INTERVAL))
1145+ then throw(((("Steps interval should be between " + toString(MIN_STEPS_INTERVAL)) + " and ") + toString(MAX_STEPS_INTERVAL)))
1146+ else if ((assetWeightsSum != 10000))
1147+ then throw("sum of token weights must be equal to 10000")
1148+ else {
1149+ func f (accum,assetIdStr) = {
1150+ let oldWeight = tryGetInteger((("static_" + assetIdStr) + "_weight"))
1151+ let newWeight = if ((indexOf(newAssetIdsStrLi, assetIdStr) == unit))
1152+ then 0
1153+ else parseIntValue(value(newAssetWeightsStrLi[value(indexOf(newAssetIdsStrLi, assetIdStr))]))
1154+ let deltaPerStep = fraction((newWeight - oldWeight), 10000, stepsAmount)
1155+ (accum ++ [toString(deltaPerStep)])
1156+ }
1157+
1158+ let tmpAssetIdsLi = getTmpRebalanceIds(newAssetIdsStrLi)
1159+ let assetDeltas = {
1160+ let $l = tmpAssetIdsLi
1161+ let $s = size($l)
1162+ let $acc0 = nil
1163+ func $f8_1 ($a,$i) = if (($i >= $s))
1164+ then $a
1165+ else f($a, $l[$i])
1166+
1167+ func $f8_2 ($a,$i) = if (($i >= $s))
1168+ then $a
1169+ else throw("List size exceeds 10")
1170+
1171+ $f8_2($f8_1($f8_1($f8_1($f8_1($f8_1($f8_1($f8_1($f8_1($f8_1($f8_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
1172+ }
1173+ let newTokensAdded = (checkTokensChange(newAssetIdsStrLi) > 0)
1174+ func recordAssetPayment (accum,next) = (accum ++ [IntegerEntry(("rebalance_attachedPayment_" + getAssetString(next.assetId)), next.amount)])
1175+
1176+ let paymentEntries = {
1177+ let $l = i.payments
1178+ let $s = size($l)
1179+ let $acc0 = nil
1180+ func $f9_1 ($a,$i) = if (($i >= $s))
1181+ then $a
1182+ else recordAssetPayment($a, $l[$i])
1183+
1184+ func $f9_2 ($a,$i) = if (($i >= $s))
1185+ then $a
1186+ else throw("List size exceeds 10")
1187+
1188+ $f9_2($f9_1($f9_1($f9_1($f9_1($f9_1($f9_1($f9_1($f9_1($f9_1($f9_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
1189+ }
1190+ let storeWeights = saveCurrentWeights()
1191+ let notifyInvoke = invoke(poolsHubAddress, "notifyPoolChange", nil, nil)
1192+ if ((notifyInvoke == notifyInvoke))
1193+ then (([StringEntry("rebalance_addedAssets", makeString(addedAssets, ",")), StringEntry("rebalance_removedAssets", makeString(removedAssets, ",")), StringEntry("tmp_rebalanceAssetIds", makeString(tmpAssetIdsLi, ",")), BooleanEntry("rebalance_inProgress", true), BooleanEntry("rebalance_newTokensAdded", newTokensAdded), IntegerEntry("rebalance_stepsDone", 0), IntegerEntry("rebalance_lastStepHeight", height), IntegerEntry("rebalance_stepsAmount", stepsAmount), IntegerEntry("rebalance_stepsInterval", stepsInterval), StringEntry("rebalance_assetIds", assetIdsStr), StringEntry("rebalance_newBaseTokenId", baseTokenIdStr), StringEntry("rebalance_assetDeltas", makeString(assetDeltas, ","))] ++ paymentEntries) ++ storeWeights)
1194+ else throw("Strict value is not equal to itself.")
1195+ }
1196+ }
1197+
1198+
1199+
1200+@Callable(i)
1201+func stepRebalancing () = if (!(valueOrElse(getBoolean(this, "rebalance_inProgress"), false)))
1202+ then throw("no rebalancing in progress")
1203+ else {
1204+ let lastStepHeight = getIntegerValue("rebalance_lastStepHeight")
1205+ let stepInterval = getIntegerValue("rebalance_stepsInterval")
1206+ let stepsDone = getIntegerValue("rebalance_stepsDone")
1207+ let nextStepHeight = (lastStepHeight + stepInterval)
1208+ if ((nextStepHeight > height))
1209+ then throw("can't be done yet")
1210+ else {
1211+ let assetDeltas = split(getStringValue("rebalance_assetDeltas"), ",")
1212+ let newAssetIdsStr = getStringValue("tmp_rebalanceAssetIds")
1213+ let newAssetIds = split(newAssetIdsStr, ",")
1214+ func f (accum,assetIdStr) = (accum ++ [toString(fraction(((valueOrElse(getInteger(("rebalance_startWeight_" + assetIdStr)), 0) * 10000) + (parseIntValue(assetDeltas[value(indexOf(newAssetIds, assetIdStr))]) * (stepsDone + 1))), 1, 10000, HALFUP))])
1215+
1216+ let newShares = makeString({
1217+ let $l = newAssetIds
1218+ let $s = size($l)
1219+ let $acc0 = nil
1220+ func $f4_1 ($a,$i) = if (($i >= $s))
1221+ then $a
1222+ else f($a, $l[$i])
1223+
1224+ func $f4_2 ($a,$i) = if (($i >= $s))
1225+ then $a
1226+ else throw("List size exceeds 10")
1227+
1228+ $f4_2($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
1229+ }, ",")
1230+ let newTokensAdded = getBooleanValue("rebalance_newTokensAdded")
1231+ let inv = if (if (newTokensAdded)
1232+ then (stepsDone == 0)
1233+ else false)
1234+ then invoke(this, "doRebalancingWithNewTokens", [newAssetIdsStr, newShares, getStringValue("rebalance_newBaseTokenId")], nil)
1235+ else invoke(this, "doRebalancing", [newShares], nil)
1236+ if ((inv == inv))
1237+ then {
1238+ let notifyInvoke = invoke(poolsHubAddress, "notifyPoolChange", nil, nil)
1239+ if ((notifyInvoke == notifyInvoke))
1240+ then {
1241+ let isFinished = ((stepsDone + 1) >= getIntegerValue("rebalance_stepsAmount"))
1242+ let actions = [BooleanEntry("rebalance_inProgress", !(isFinished)), IntegerEntry("rebalance_stepsDone", (stepsDone + 1)), IntegerEntry("rebalance_lastStepHeight", height)]
1243+ if ((stepsDone == 0))
1244+ then (actions ++ [StringEntry("static_tokenIds", newAssetIdsStr)])
1245+ else if (isFinished)
1246+ then {
1247+ let removedAssetsLi = split(tryGetString("rebalance_removedAssets"), ",")
1248+ func rmData (accum,assetId) = (accum ++ [DeleteEntry((("static_" + assetId) + "_scale")), DeleteEntry((("static_" + assetId) + "_decimals")), DeleteEntry((("static_" + assetId) + "_weight")), DeleteEntry((("static_" + assetId) + "_balance"))])
1249+
1250+ let rm = {
1251+ let $l = removedAssetsLi
1252+ let $s = size($l)
1253+ let $acc0 = nil
1254+ func $f5_1 ($a,$i) = if (($i >= $s))
1255+ then $a
1256+ else rmData($a, $l[$i])
1257+
1258+ func $f5_2 ($a,$i) = if (($i >= $s))
1259+ then $a
1260+ else throw("List size exceeds 10")
1261+
1262+ $f5_2($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
1263+ }
1264+ let finalAssetsIdsStr = tryGetString("rebalance_assetIds")
1265+ let AssetsWeightsStr = {
1266+ let $l = split(finalAssetsIdsStr, ",")
1267+ let $s = size($l)
1268+ let $acc0 = nil
1269+ func $f6_1 ($a,$i) = if (($i >= $s))
1270+ then $a
1271+ else addAssetWeightToStrList($a, $l[$i])
1272+
1273+ func $f6_2 ($a,$i) = if (($i >= $s))
1274+ then $a
1275+ else throw("List size exceeds 10")
1276+
1277+ $f6_2($f6_1($f6_1($f6_1($f6_1($f6_1($f6_1($f6_1($f6_1($f6_1($f6_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
1278+ }
1279+ ((actions ++ rm) ++ [StringEntry("static_tokenIds", finalAssetsIdsStr), StringEntry("static_tokenWeights", makeString(AssetsWeightsStr, ",")), IntegerEntry("static_tokensAmount", size(split(finalAssetsIdsStr, ",")))])
1280+ }
1281+ else actions
1282+ }
1283+ else throw("Strict value is not equal to itself.")
1284+ }
1285+ else throw("Strict value is not equal to itself.")
1286+ }
1287+ }
1288+
1289+
1290+
1291+@Callable(i)
1292+func doRebalancing (assetWeightsStr) = {
1293+ let assetWeightsStrLi = split(assetWeightsStr, ",")
1294+ let assetWeightsSum = {
1295+ let $l = assetWeightsStrLi
1296+ let $s = size($l)
1297+ let $acc0 = 0
1298+ func $f4_1 ($a,$i) = if (($i >= $s))
1299+ then $a
1300+ else sum($a, $l[$i])
1301+
1302+ func $f4_2 ($a,$i) = if (($i >= $s))
1303+ then $a
1304+ else throw("List size exceeds 10")
1305+
1306+ $f4_2($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
1307+ }
1308+ let assetIdsStrLi = split(tryGetString("static_tokenIds"), ",")
1309+ if ((i.caller != this))
1310+ then throw("this call available only for admin")
1311+ else {
1312+ let oldKMult = getKMult()
1313+ func handler (pars,assetId) = {
1314+ let accum = pars._1
1315+ let assetIdStr = getAssetString(assetId)
1316+ func handler2 (accum,n) = if ((n == assetId))
1317+ then value(indexOf(assetIds, n))
1318+ else accum
1319+
1320+ let Token = {
1321+ let $l = assetIds
1322+ let $s = size($l)
1323+ let $acc0 = 1
1324+ func $f5_1 ($a,$i) = if (($i >= $s))
1325+ then $a
1326+ else handler2($a, $l[$i])
1327+
1328+ func $f5_2 ($a,$i) = if (($i >= $s))
1329+ then $a
1330+ else throw("List size exceeds 10")
1331+
1332+ $f5_2($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
1333+ }
1334+ let balance = tryGetInteger((("global_" + assetIdStr) + "_balance"))
1335+ let weight = if ((pars._2 == "new"))
1336+ then parseIntValue(assetWeightsStrLi[Token])
1337+ else tryGetInteger((("static_" + assetIdStr) + "_weight"))
1338+ $Tuple2(fraction(accum, pow(balance, Decimals[Token], weight, AssetsWeightsDecimals, 8, FLOOR), Scale8), pars._2)
1339+ }
1340+
1341+ let newK = ( let $l = assetIds
1342+ let $s = size($l)
1343+ let $acc0 = $Tuple2(PoolTokenScale, "new")
1344+ func $f5_1 ($a,$i) = if (($i >= $s))
1345+ then $a
1346+ else handler($a, $l[$i])
1347+
1348+ func $f5_2 ($a,$i) = if (($i >= $s))
1349+ then $a
1350+ else throw("List size exceeds 10")
1351+
1352+ $f5_2($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10))._1
1353+ let oldK = ( let $l = assetIds
1354+ let $s = size($l)
1355+ let $acc0 = $Tuple2(PoolTokenScale, "old")
1356+ func $f6_1 ($a,$i) = if (($i >= $s))
1357+ then $a
1358+ else handler($a, $l[$i])
1359+
1360+ func $f6_2 ($a,$i) = if (($i >= $s))
1361+ then $a
1362+ else throw("List size exceeds 10")
1363+
1364+ $f6_2($f6_1($f6_1($f6_1($f6_1($f6_1($f6_1($f6_1($f6_1($f6_1($f6_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10))._1
1365+ let newKMult = fraction(oldKMult, newK, oldK)
1366+ func addTokenDataEntries (accum,assetNum) = if ((assetNum >= size(assetWeightsStrLi)))
1367+ then accum
1368+ else (accum ++ [IntegerEntry((("static_" + assetIdsStrLi[assetNum]) + "_weight"), value(parseInt(assetWeightsStrLi[assetNum])))])
1369+
1370+ ({
1371+ let $l = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
1372+ let $s = size($l)
1373+ let $acc0 = nil
1374+ func $f7_1 ($a,$i) = if (($i >= $s))
1375+ then $a
1376+ else addTokenDataEntries($a, $l[$i])
1377+
1378+ func $f7_2 ($a,$i) = if (($i >= $s))
1379+ then $a
1380+ else throw("List size exceeds 10")
1381+
1382+ $f7_2($f7_1($f7_1($f7_1($f7_1($f7_1($f7_1($f7_1($f7_1($f7_1($f7_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
1383+ } ++ [IntegerEntry("static_KMult", newKMult)])
1384+ }
1385+ }
1386+
1387+
1388+
1389+@Callable(i)
1390+func doRebalancingWithNewTokens (assetIdsStr,assetWeightsStr,baseTokenIdStr) = {
1391+ let newAssetWeightsStrLi = split(assetWeightsStr, ",")
1392+ let prevAssetIdsStrLi = split(tryGetString("static_tokenIds"), ",")
1393+ let newAssetIdsStrLi = split(assetIdsStr, ",")
1394+ let newAssetIds = {
1395+ let $l = newAssetIdsStrLi
1396+ let $s = size($l)
1397+ let $acc0 = nil
1398+ func $f4_1 ($a,$i) = if (($i >= $s))
1399+ then $a
1400+ else addAssetBytesToList($a, $l[$i])
1401+
1402+ func $f4_2 ($a,$i) = if (($i >= $s))
1403+ then $a
1404+ else throw("List size exceeds 10")
1405+
1406+ $f4_2($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
1407+ }
1408+ let feeAssetStr = {
1409+ let $l = newAssetIdsStrLi
1410+ let $s = size($l)
1411+ let $acc0 = ""
1412+ func $f5_1 ($a,$i) = if (($i >= $s))
1413+ then $a
1414+ else checkFeeAsset($a, $l[$i])
1415+
1416+ func $f5_2 ($a,$i) = if (($i >= $s))
1417+ then $a
1418+ else throw("List size exceeds 10")
1419+
1420+ $f5_2($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
1421+ }
1422+ let addedAssets = split(tryGetString("rebalance_addedAssets"), ",")
1423+ func findAssetPayment (assetId) = valueOrElse(getInteger(("rebalance_attachedPayment_" + getAssetString(assetId))), 0)
1424+
1425+ func addAssetBalanceToLi (li,assetId) = (li ++ [findAssetPayment(assetId)])
1426+
1427+ let attachedBalances = {
1428+ let $l = newAssetIds
1429+ let $s = size($l)
1430+ let $acc0 = nil
1431+ func $f6_1 ($a,$i) = if (($i >= $s))
1432+ then $a
1433+ else addAssetBalanceToLi($a, $l[$i])
1434+
1435+ func $f6_2 ($a,$i) = if (($i >= $s))
1436+ then $a
1437+ else throw("List size exceeds 10")
1438+
1439+ $f6_2($f6_1($f6_1($f6_1($f6_1($f6_1($f6_1($f6_1($f6_1($f6_1($f6_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
1440+ }
1441+ if ((i.caller != this))
1442+ then throw(("this call available only for admin, " + toString(i.caller)))
1443+ else {
1444+ let oldKMult = getKMult()
1445+ let oldK = getVirtualPoolTokenAmount()
1446+ func myltiplyAssetsForK (pars,assetId) = {
1447+ func findAssetNum (accum,n) = if ((n == assetId))
1448+ then value(indexOf(newAssetIds, n))
1449+ else accum
1450+
1451+ let currentK = pars
1452+ let assetIdStr = getAssetString(assetId)
1453+ let TokenNum = {
1454+ let $l = newAssetIds
1455+ let $s = size($l)
1456+ let $acc0 = 1
1457+ func $f7_1 ($a,$i) = if (($i >= $s))
1458+ then $a
1459+ else findAssetNum($a, $l[$i])
1460+
1461+ func $f7_2 ($a,$i) = if (($i >= $s))
1462+ then $a
1463+ else throw("List size exceeds 10")
1464+
1465+ $f7_2($f7_1($f7_1($f7_1($f7_1($f7_1($f7_1($f7_1($f7_1($f7_1($f7_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
1466+ }
1467+ let weight = parseIntValue(newAssetWeightsStrLi[TokenNum])
1468+ let balanceInState = tryGetInteger((("global_" + assetIdStr) + "_balance"))
1469+ let balanceInPayment = attachedBalances[TokenNum]
1470+ let balance = (balanceInState + balanceInPayment)
1471+ let assetDecimals = if ((assetId == unit))
1472+ then 8
1473+ else value(assetInfo(value(assetId))).decimals
1474+ if ((0 >= balance))
1475+ then throw(("you need to attach all new assets in payment. this asset is missed: " + assetIdStr))
1476+ else fraction(currentK, pow(balance, assetDecimals, weight, AssetsWeightsDecimals, 8, FLOOR), Scale8)
1477+ }
1478+
1479+ let newK = {
1480+ let $l = newAssetIds
1481+ let $s = size($l)
1482+ let $acc0 = PoolTokenScale
1483+ func $f7_1 ($a,$i) = if (($i >= $s))
1484+ then $a
1485+ else myltiplyAssetsForK($a, $l[$i])
1486+
1487+ func $f7_2 ($a,$i) = if (($i >= $s))
1488+ then $a
1489+ else throw("List size exceeds 10")
1490+
1491+ $f7_2($f7_1($f7_1($f7_1($f7_1($f7_1($f7_1($f7_1($f7_1($f7_1($f7_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
1492+ }
1493+ let newKMult = fraction(oldKMult, newK, oldK)
1494+ func addTokenDataEntries (accum,assetNum) = {
1495+ let assetIdStr = newAssetIdsStrLi[assetNum]
1496+ let assetId = newAssetIds[assetNum]
1497+ let assetDecimals = if ((assetId == unit))
1498+ then 8
1499+ else value(assetInfo(value(assetId))).decimals
1500+ let newAssetData = if ((indexOf(addedAssets, assetIdStr) != unit))
1501+ then [IntegerEntry((("global_" + assetIdStr) + "_balance"), attachedBalances[assetNum]), IntegerEntry((("static_" + assetIdStr) + "_scale"), pow(10, 0, assetDecimals, 0, 0, DOWN)), IntegerEntry((("static_" + assetIdStr) + "_decimals"), assetDecimals)]
1502+ else nil
1503+ if ((assetNum >= size(newAssetWeightsStrLi)))
1504+ then accum
1505+ else ((accum ++ [IntegerEntry((("static_" + assetIdStr) + "_weight"), value(parseInt(newAssetWeightsStrLi[assetNum])))]) ++ newAssetData)
1506+ }
1507+
1508+ ({
1509+ let $l = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
1510+ let $s = size($l)
1511+ let $acc0 = nil
1512+ func $f8_1 ($a,$i) = if (($i >= $s))
1513+ then $a
1514+ else addTokenDataEntries($a, $l[$i])
1515+
1516+ func $f8_2 ($a,$i) = if (($i >= $s))
1517+ then $a
1518+ else throw("List size exceeds 10")
1519+
1520+ $f8_2($f8_1($f8_1($f8_1($f8_1($f8_1($f8_1($f8_1($f8_1($f8_1($f8_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
1521+ } ++ [StringEntry("static_tokenIds", assetIdsStr), StringEntry("static_feeToken", feeAssetStr), StringEntry("static_tokenWeights", assetWeightsStr), IntegerEntry("static_tokensAmount", size(newAssetIds)), IntegerEntry("static_KMult", newKMult)])
1522+ }
7421523 }
7431524
7441525
Full:
OldNewDifferences
11 {-# STDLIB_VERSION 6 #-}
22 {-# SCRIPT_TYPE ACCOUNT #-}
33 {-# CONTENT_TYPE DAPP #-}
4-let usdnAssetId = base58'DG2xFkPdDwKUoBkzGAhQtLpSGzfXLiCYPEzeKH2Ad24p'
4+let VERSION = "PZ-1.0.8 PROD"
55
6-let puzzleAssetId = base58'HEB8Qaw9xrWpWs8tHsiATYGBWDBtP2S7kcPALrMu43AS'
6+let AssetsWeightsDecimals = 4
77
8-let usdtAssetId = base58'34N9YcEETLWn93qYQ64EsP1x89tSruJU44RrEMSXXEPJ'
8+let Scale = 10000
99
10-let usdnAssetIdStr = "DG2xFkPdDwKUoBkzGAhQtLpSGzfXLiCYPEzeKH2Ad24p"
10+let Scale8 = 100000000
1111
12-let puzzleAssetIdStr = "HEB8Qaw9xrWpWs8tHsiATYGBWDBtP2S7kcPALrMu43AS"
12+let Scale16 = 10000000000000000
1313
14-let usdtAssetIdStr = "34N9YcEETLWn93qYQ64EsP1x89tSruJU44RrEMSXXEPJ"
14+let FeeScale = 10000
1515
16-let parentPoolAddress = Address(base58'3PFDgzu1UtswAkCMxqqQjbTeHaX4cMab8Kh')
16+let PoolTokenDecimals = 8
1717
18-let masterAddress = Address(base58'3PLjwHcz9NEuaTo63NZR9B9okQiKQxZSbmf')
18+let PoolTokenScale = pow(10, 0, PoolTokenDecimals, 0, 0, HALFUP)
1919
20-let masterPubKey = base58'4z8CKSYQBKkzx7PBb5uBP1YPa6YAHRNTApW1sQVHT5eU'
20+let MIN_STEPS_AMOUNT = 1
21+
22+let MAX_STEPS_AMOUNT = 500
23+
24+let MIN_STEPS_INTERVAL = 1
25+
26+let MAX_STEPS_INTERVAL = 10000
2127
2228 func tryGetInteger (key) = match getInteger(this, key) {
2329 case b: Int =>
2430 b
2531 case _ =>
2632 0
2733 }
2834
2935
3036 func tryGetBinary (key) = match getBinary(this, key) {
3137 case b: ByteVector =>
3238 b
3339 case _ =>
3440 base58''
3541 }
3642
3743
3844 func tryGetString (key) = match getString(this, key) {
3945 case b: String =>
4046 b
4147 case _ =>
4248 ""
4349 }
4450
4551
52+func tryGetStringOrThrow (key) = match getString(this, key) {
53+ case b: String =>
54+ b
55+ case _ =>
56+ throw(("no such key in data storage: " + key))
57+}
58+
59+
4660 func getAssetString (assetId) = match assetId {
4761 case b: ByteVector =>
4862 toBase58String(b)
4963 case _ =>
5064 "WAVES"
5165 }
5266
5367
5468 func getAssetBytes (assetIdStr) = if ((assetIdStr == "WAVES"))
5569 then unit
5670 else fromBase58String(assetIdStr)
5771
5872
73+func getTokenBalance (assetId) = match assetId {
74+ case t: ByteVector =>
75+ assetBalance(this, t)
76+ case _ =>
77+ wavesBalance(this).available
78+}
79+
80+
5981 func addAssetBytesToList (accum,item) = (accum ++ [getAssetBytes(item)])
6082
6183
6284 func addAssetWeightToList (accum,item) = (accum ++ [tryGetInteger((("static_" + getAssetString(item)) + "_weight"))])
85+
86+
87+func addAssetWeightToStrList (accum,item) = (accum ++ [toString(tryGetInteger((("static_" + item) + "_weight")))])
6388
6489
6590 func addAssetDecimalsToList (accum,item) = (accum ++ [tryGetInteger((("static_" + getAssetString(item)) + "_decimals"))])
6691
6792
6893 func addAssetScaleToList (accum,item) = (accum ++ [tryGetInteger((("static_" + getAssetString(item)) + "_scale"))])
6994
7095
7196 func addIntToList (accum,item) = (accum ++ [parseIntValue(item)])
7297
98+
99+let usdnAssetId = base58'DG2xFkPdDwKUoBkzGAhQtLpSGzfXLiCYPEzeKH2Ad24p'
100+
101+let puzzleAssetId = base58'HEB8Qaw9xrWpWs8tHsiATYGBWDBtP2S7kcPALrMu43AS'
102+
103+let usdtAssetId = base58'34N9YcEETLWn93qYQ64EsP1x89tSruJU44RrEMSXXEPJ'
104+
105+let usdtPptAssetId = base58'9wc3LXNA4TEBsXyKtoLE9mrbDD7WMHXvXrCjZvabLAsi'
106+
107+let wavesAssetId = unit
108+
109+let usdnAssetIdStr = "DG2xFkPdDwKUoBkzGAhQtLpSGzfXLiCYPEzeKH2Ad24p"
110+
111+let puzzleAssetIdStr = "HEB8Qaw9xrWpWs8tHsiATYGBWDBtP2S7kcPALrMu43AS"
112+
113+let usdtAssetIdStr = "34N9YcEETLWn93qYQ64EsP1x89tSruJU44RrEMSXXEPJ"
114+
115+let usdtPptAssetIdStr = "9wc3LXNA4TEBsXyKtoLE9mrbDD7WMHXvXrCjZvabLAsi"
116+
117+let wavesAssetIdStr = "WAVES"
118+
119+let supportedFeeAssetsStr = ["DG2xFkPdDwKUoBkzGAhQtLpSGzfXLiCYPEzeKH2Ad24p", "HEB8Qaw9xrWpWs8tHsiATYGBWDBtP2S7kcPALrMu43AS", "34N9YcEETLWn93qYQ64EsP1x89tSruJU44RrEMSXXEPJ", "9wc3LXNA4TEBsXyKtoLE9mrbDD7WMHXvXrCjZvabLAsi", "WAVES"]
120+
121+let masterPubKey = base58'4z8CKSYQBKkzx7PBb5uBP1YPa6YAHRNTApW1sQVHT5eU'
122+
123+let parentPoolAddress = Address(base58'3PFDgzu1UtswAkCMxqqQjbTeHaX4cMab8Kh')
124+
125+let masterAddress = Address(base58'3PLjwHcz9NEuaTo63NZR9B9okQiKQxZSbmf')
126+
127+let oracleAddress = Address(base58'3P8d1E1BLKoD52y3bQJ1bDTd2TD1gpaLn9t')
128+
129+let stakingAddress = Address(base58'3PFTbywqxtFfukX3HyT881g4iW5K4QL3FAS')
130+
131+let feesAddress = Address(base58'3P4kBiU4wr2yV1S5gMfu3MdkVvy7kxXHsKe')
132+
133+let poolsHubAddress = Address(base58'3P5YutjDNC3hABBVsveFuZTTbQ5PdtSDBgk')
134+
135+let shutdownAddressStr = "3PEpv9hRFWEEBU22WRnLsw1bH4YGtcU728o'"
73136
74137 let T = tryGetInteger("static_tokensAmount")
75138
76139 let assetIds = {
77140 let $l = split(tryGetString("static_tokenIds"), ",")
78141 let $s = size($l)
79142 let $acc0 = nil
80143 func $f0_1 ($a,$i) = if (($i >= $s))
81144 then $a
82145 else addAssetBytesToList($a, $l[$i])
83146
84147 func $f0_2 ($a,$i) = if (($i >= $s))
85148 then $a
86149 else throw("List size exceeds 10")
87150
88151 $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)
89152 }
90153
91154 let AssetsWeights = {
92155 let $l = assetIds
93156 let $s = size($l)
94157 let $acc0 = nil
95158 func $f1_1 ($a,$i) = if (($i >= $s))
96159 then $a
97160 else addAssetWeightToList($a, $l[$i])
98161
99162 func $f1_2 ($a,$i) = if (($i >= $s))
100163 then $a
101164 else throw("List size exceeds 10")
102165
103166 $f1_2($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)
104167 }
105168
106169 let Decimals = {
107170 let $l = assetIds
108171 let $s = size($l)
109172 let $acc0 = nil
110173 func $f2_1 ($a,$i) = if (($i >= $s))
111174 then $a
112175 else addAssetDecimalsToList($a, $l[$i])
113176
114177 func $f2_2 ($a,$i) = if (($i >= $s))
115178 then $a
116179 else throw("List size exceeds 10")
117180
118181 $f2_2($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
119182 }
120183
121184 let Scales = {
122185 let $l = assetIds
123186 let $s = size($l)
124187 let $acc0 = nil
125188 func $f3_1 ($a,$i) = if (($i >= $s))
126189 then $a
127190 else addAssetScaleToList($a, $l[$i])
128191
129192 func $f3_2 ($a,$i) = if (($i >= $s))
130193 then $a
131194 else throw("List size exceeds 10")
132195
133196 $f3_2($f3_1($f3_1($f3_1($f3_1($f3_1($f3_1($f3_1($f3_1($f3_1($f3_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
134197 }
135198
136199 let Fee = tryGetInteger("static_fee")
137200
138-let AssetsWeightsDecimals = 4
139-
140-let Scale = 10000
141-
142-let Scale8 = 100000000
143-
144-let FeeScale = 10000
145-
146-let PoolTokenDecimals = 8
147-
148-let PoolTokenScale = pow(10, 0, PoolTokenDecimals, 0, 0, HALFUP)
149-
150201 let earnedAssets = assetIds
151202
152-func isShutdown () = match getBoolean(Address(base58'3PEpv9hRFWEEBU22WRnLsw1bH4YGtcU728o'), "is_shutdown") {
153- case x: Boolean =>
203+func isShutdown () = if ((shutdownAddressStr == ""))
204+ then false
205+ else {
206+ let shutdownAddress = Address(fromBase58String(shutdownAddressStr))
207+ match getBoolean(shutdownAddress, "is_shutdown") {
208+ case x: Boolean =>
209+ x
210+ case _ =>
211+ false
212+ }
213+ }
214+
215+
216+func getCurrentTokenBalance (tokenNum) = {
217+ let tokenIdStr = getAssetString(assetIds[tokenNum])
218+ tryGetInteger((("global_" + tokenIdStr) + "_balance"))
219+ }
220+
221+
222+func getKMult () = match getInteger("static_KMult") {
223+ case x: Int =>
154224 x
155225 case _ =>
156- false
226+ Scale16
157227 }
158228
159229
160-func getCurrentTokenBalance (tokenType) = {
161- let tokenId = getAssetString(assetIds[tokenType])
162- tryGetInteger((("global_" + tokenId) + "_balance"))
230+func saveCurrentWeights () = {
231+ let assetIdsLi = split(tryGetString("static_tokenIds"), ",")
232+ func s (accum,assetId) = (accum ++ [IntegerEntry(("rebalance_startWeight_" + assetId), tryGetInteger((("static_" + assetId) + "_weight")))])
233+
234+ let $l = assetIdsLi
235+ let $s = size($l)
236+ let $acc0 = nil
237+ func $f4_1 ($a,$i) = if (($i >= $s))
238+ then $a
239+ else s($a, $l[$i])
240+
241+ func $f4_2 ($a,$i) = if (($i >= $s))
242+ then $a
243+ else throw("List size exceeds 10")
244+
245+ $f4_2($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
163246 }
164247
165248
249+func getVirtualPoolTokenAmount () = fraction(tryGetInteger("global_poolToken_amount"), getKMult(), Scale16)
250+
251+
166252 func calculatePIssued (amount,tokenId) = {
167- let Psupply = tryGetInteger("global_poolToken_amount")
253+ let Psupply = getVirtualPoolTokenAmount()
168254 let Balance = tryGetInteger((("global_" + getAssetString(tokenId)) + "_balance"))
169- fraction(amount, Psupply, Balance, DOWN)
255+ let t1 = fraction(amount, Psupply, Balance, DOWN)
256+ t1
170257 }
171258
172259
173260 func getMinPIssued (payments) = {
174261 func handler (accum,current) = {
175262 let PIssued = calculatePIssued(current.amount, current.assetId)
176263 if ((PIssued == 0))
177264 then throw("one of the tokens amounts is too low")
178265 else if (if ((accum == 0))
179266 then true
180267 else (accum > PIssued))
181268 then PIssued
182269 else accum
183270 }
184271
185272 let minPIssed = {
186273 let $l = payments
187274 let $s = size($l)
188275 let $acc0 = 0
189276 func $f4_1 ($a,$i) = if (($i >= $s))
190277 then $a
191278 else handler($a, $l[$i])
192279
193280 func $f4_2 ($a,$i) = if (($i >= $s))
194281 then $a
195282 else throw("List size exceeds 10")
196283
197284 $f4_2($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
198285 }
199286 minPIssed
200287 }
201288
202289
203290 func calculateUsdnValue (assetId,amount,aBalance,givenUsdnBalance) = {
204291 let usdnInPool = indexOf(assetIds, usdnAssetId)
292+ let puzzleInPool = indexOf(assetIds, puzzleAssetId)
205293 let usdtInPool = indexOf(assetIds, usdtAssetId)
206- let assetWeight = AssetsWeights[value(indexOf(assetIds, assetId))]
207- if (if ((usdnInPool == unit))
208- then (usdtInPool == unit)
209- else false)
294+ let usdtPptInPool = indexOf(assetIds, usdtPptAssetId)
295+ let wavesInPool = indexOf(assetIds, unit)
296+ let assetWeight = tryGetInteger((("static_" + getAssetString(assetId)) + "_weight"))
297+ let feeAssetStr = tryGetString("static_feeToken")
298+ if ((feeAssetStr == puzzleAssetIdStr))
210299 then {
211300 let puzzleWeight = AssetsWeights[value(indexOf(assetIds, puzzleAssetId))]
212301 let puzzleBalance = tryGetInteger((("global_" + puzzleAssetIdStr) + "_balance"))
213302 let amountInPuzzle = fraction(amount, (puzzleBalance / puzzleWeight), (aBalance / assetWeight))
214303 let puzzlePrice = getIntegerValue(parentPoolAddress, "global_lastPuzzlePrice")
215304 fraction((amountInPuzzle * puzzlePrice), 1, Scale8)
216305 }
217- else if ((usdtInPool != unit))
306+ else if ((feeAssetStr == usdtAssetIdStr))
218307 then {
219308 let usdtWeight = AssetsWeights[value(usdtInPool)]
220309 let usdtBalance = tryGetInteger((("global_" + usdtAssetIdStr) + "_balance"))
221310 fraction(amount, (usdtBalance / usdtWeight), (aBalance / assetWeight))
222311 }
223- else {
224- let usdnWeight = AssetsWeights[value(indexOf(assetIds, usdnAssetId))]
225- let usdnBalance = match givenUsdnBalance {
226- case x: Int =>
227- givenUsdnBalance
228- case _ =>
229- tryGetInteger((("global_" + getAssetString(usdnAssetId)) + "_balance"))
230- }
231- fraction(amount, (value(usdnBalance) / usdnWeight), (aBalance / assetWeight))
232- }
312+ else if ((feeAssetStr == usdtPptAssetIdStr))
313+ then {
314+ let usdtWeight = AssetsWeights[value(usdtPptInPool)]
315+ let usdtBalance = tryGetInteger((("global_" + usdtPptAssetIdStr) + "_balance"))
316+ fraction(amount, (usdtBalance / usdtWeight), (aBalance / assetWeight))
317+ }
318+ else if ((feeAssetStr == usdnAssetIdStr))
319+ then {
320+ let usdnWeight = AssetsWeights[value(indexOf(assetIds, usdnAssetId))]
321+ let usdnBalance = match givenUsdnBalance {
322+ case x: Int =>
323+ givenUsdnBalance
324+ case _ =>
325+ tryGetInteger((("global_" + getAssetString(usdnAssetId)) + "_balance"))
326+ }
327+ fraction(amount, (value(usdnBalance) / usdnWeight), (aBalance / assetWeight))
328+ }
329+ else {
330+ let wavesWeight = 3000
331+ let wBalance = (tryGetInteger("global_WAVES_balance") / 50)
332+ fraction(amount, (wBalance / wavesWeight), (aBalance / assetWeight))
333+ }
334+ }
335+
336+
337+func getPriceFromOracle (assetIdStr) = match getInteger(oracleAddress, (assetIdStr + "_twap5B")) {
338+ case x: Int =>
339+ x
340+ case _ =>
341+ 0
342+}
343+
344+
345+func calculateUsdValue (assetId,amount,aBalance) = {
346+ let assetWeight = tryGetInteger((("static_" + getAssetString(assetId)) + "_weight"))
347+ let feeAssetStr = tryGetString("static_feeToken")
348+ let feeAssetScale = getIntegerValue(this, (("static_" + feeAssetStr) + "_scale"))
349+ let feeAssetNum = value(indexOf(assetIds, getAssetBytes(feeAssetStr)))
350+ let feeAssetWeight = AssetsWeights[feeAssetNum]
351+ let feeAssetBalance = tryGetInteger((("global_" + feeAssetStr) + "_balance"))
352+ let valInFeeAsset = fraction(amount, (feeAssetBalance / feeAssetWeight), (aBalance / assetWeight))
353+ let feeAssetPrice = getPriceFromOracle(feeAssetStr)
354+ fraction(valInFeeAsset, feeAssetPrice, feeAssetScale)
233355 }
234356
235357
236358 func checkTokensValidity (payments) = {
237359 func handler1 (accum,payment) = (accum ++ [payment.assetId])
238360
239361 let ids = {
240362 let $l = payments
241363 let $s = size($l)
242364 let $acc0 = nil
243365 func $f4_1 ($a,$i) = if (($i >= $s))
244366 then $a
245367 else handler1($a, $l[$i])
246368
247369 func $f4_2 ($a,$i) = if (($i >= $s))
248370 then $a
249371 else throw("List size exceeds 10")
250372
251373 $f4_2($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
252374 }
253375 if ((ids == ids))
254376 then {
255377 func handler2 (accum,assetId) = if ((indexOf(ids, assetId) != unit))
256378 then (accum + 1)
257379 else throw(("asset not attached: " + getAssetString(assetId)))
258380
259381 let checks = {
260382 let $l = assetIds
261383 let $s = size($l)
262384 let $acc0 = 0
263385 func $f5_1 ($a,$i) = if (($i >= $s))
264386 then $a
265387 else handler2($a, $l[$i])
266388
267389 func $f5_2 ($a,$i) = if (($i >= $s))
268390 then $a
269391 else throw("List size exceeds 10")
270392
271393 $f5_2($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
272394 }
273395 if ((checks == checks))
274396 then true
275397 else throw("Strict value is not equal to itself.")
276398 }
277399 else throw("Strict value is not equal to itself.")
278400 }
279401
280402
281403 func handlePoolTokensAdd (PIssued,payments,userAddress,needChange) = {
282404 func getTokenPaymentAmount (tokenId) = {
283405 func handler (accum,payment) = if ((payment.assetId == tokenId))
284406 then payment.amount
285407 else accum
286408
287409 let $l = payments
288410 let $s = size($l)
289411 let $acc0 = 0
290412 func $f4_1 ($a,$i) = if (($i >= $s))
291413 then $a
292414 else handler($a, $l[$i])
293415
294416 func $f4_2 ($a,$i) = if (($i >= $s))
295417 then $a
296418 else throw("List size exceeds 10")
297419
298420 $f4_2($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
299421 }
300422
301423 func handleTokenChange (accum,tokenId) = {
302424 let Bk = tryGetInteger((("global_" + getAssetString(tokenId)) + "_balance"))
303- let PSupply = tryGetInteger("global_poolToken_amount")
425+ let PSupply = getVirtualPoolTokenAmount()
304426 let tokenDecimals = tryGetInteger((("static_" + getAssetString(tokenId)) + "_scale"))
305- let Dk = fraction((fraction((PSupply + PIssued), tokenDecimals, PSupply, CEILING) - tokenDecimals), Bk, tokenDecimals, CEILING)
427+ let a1 = fraction((toBigInt((PSupply + PIssued)) * toBigInt(Scale8)), toBigInt(tokenDecimals), toBigInt(PSupply), CEILING)
428+ let Dk = toInt(fraction((a1 - (toBigInt(tokenDecimals) * toBigInt(Scale8))), toBigInt(Bk), (toBigInt(tokenDecimals) * toBigInt(Scale8)), CEILING))
306429 let paymentAmount = getTokenPaymentAmount(tokenId)
307- let toReturn = ((if ((paymentAmount != 0))
308- then paymentAmount
309- else 0) - Dk)
430+ let toReturn = (paymentAmount - Dk)
310431 let t = if (if (needChange)
311432 then (toReturn > 0)
312433 else false)
313434 then [ScriptTransfer(userAddress, toReturn, tokenId)]
314435 else nil
315436 ((accum ++ t) ++ [IntegerEntry((("global_" + getAssetString(tokenId)) + "_balance"), (Bk + Dk))])
316437 }
317438
318439 let $l = assetIds
319440 let $s = size($l)
320441 let $acc0 = nil
321442 func $f4_1 ($a,$i) = if (($i >= $s))
322443 then $a
323444 else handleTokenChange($a, $l[$i])
324445
325446 func $f4_2 ($a,$i) = if (($i >= $s))
326447 then $a
327448 else throw("List size exceeds 10")
328449
329450 $f4_2($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
330451 }
331452
332453
333454 func handlePoolTokensRedeem (PRedeemed,userAddress) = {
334455 func handleTokenRedeem (accum,tokenId) = {
335456 let Bk = tryGetInteger((("global_" + getAssetString(tokenId)) + "_balance"))
336- let PSupply = tryGetInteger("global_poolToken_amount")
457+ let PSupply = getVirtualPoolTokenAmount()
337458 let tokenDecimals = tryGetInteger((("static_" + getAssetString(tokenId)) + "_scale"))
338- let amount = toInt(fraction((toBigInt(Scale8) - fraction(toBigInt((PSupply - PRedeemed)), toBigInt(Scale8), toBigInt(PSupply), CEILING)), toBigInt(Bk), toBigInt(Scale8), DOWN))
459+ let psuppl = fraction((toBigInt((PSupply - PRedeemed)) * toBigInt(Scale8)), toBigInt(Scale8), toBigInt(PSupply), DOWN)
460+ let amount = toInt(fraction((toBigInt(Scale16) - psuppl), toBigInt(Bk), toBigInt(Scale16), CEILING))
339461 (accum ++ [IntegerEntry((("global_" + getAssetString(tokenId)) + "_balance"), (Bk - amount)), ScriptTransfer(userAddress, amount, tokenId)])
340462 }
341463
342464 let $l = assetIds
343465 let $s = size($l)
344466 let $acc0 = nil
345467 func $f4_1 ($a,$i) = if (($i >= $s))
346468 then $a
347469 else handleTokenRedeem($a, $l[$i])
348470
349471 func $f4_2 ($a,$i) = if (($i >= $s))
350472 then $a
351473 else throw("List size exceeds 10")
352474
353475 $f4_2($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
354476 }
355477
356478
357479 func calculateOutAmount (AmountIn,assetIn,assetOut,BalanceIn,BalanceOut) = {
358480 let IndexIn = value(indexOf(assetIds, assetIn))
359481 let IndexOut = value(indexOf(assetIds, assetOut))
360482 if ((IndexIn == IndexOut))
361483 then AmountIn
362- else fraction(BalanceOut, ((Scale8 * Scale8) - toInt(pow(fraction(toBigInt(BalanceIn), toBigInt((Scale8 * Scale8)), toBigInt((BalanceIn + AmountIn)), HALFUP), 16, toBigInt(fraction(AssetsWeights[IndexIn], 10000, AssetsWeights[IndexOut])), 4, 16, CEILING))), (Scale8 * Scale8), DOWN)
484+ else fraction(BalanceOut, ((Scale8 * Scale8) - toInt(pow(fraction(toBigInt((BalanceIn * 10000)), toBigInt((Scale8 * Scale8)), toBigInt(((BalanceIn + AmountIn) * 10000)), HALFUP), 16, toBigInt(fraction(AssetsWeights[IndexIn], 1000000000000, AssetsWeights[IndexOut])), 12, 16, CEILING))), (Scale8 * Scale8), HALFEVEN)
363485 }
364-
365-
366-func getTokenBalance (assetId) = match assetId {
367- case t: ByteVector =>
368- assetBalance(this, t)
369- case _ =>
370- wavesBalance(this).available
371-}
372486
373487
374488 func calculateCurrentAssetInterest (assetId,assetIdStr,aBalance,tokenEarningsLastCheck) = {
375489 let totalStaked = tryGetInteger("global_indexStaked")
376490 let tokenBalanceLastCheck = tokenEarningsLastCheck
377491 let currentBalanceDelta = (getTokenBalance(assetId) - aBalance)
378492 let currentTokenEarnings = if ((currentBalanceDelta > tokenBalanceLastCheck))
379493 then currentBalanceDelta
380494 else tokenBalanceLastCheck
381495 let newEarnings = (currentTokenEarnings - tokenBalanceLastCheck)
382496 let newInterest = if ((totalStaked == 0))
383497 then 0
384498 else fraction(newEarnings, Scale8, totalStaked)
385499 let lastCheckInterest = tryGetInteger((("global_lastCheck_" + assetIdStr) + "_interest"))
386500 (lastCheckInterest + newInterest)
387501 }
388502
389503
390504 func claimResult (address) = {
391505 let addressStr = toString(address)
392506 let puzzleAmount = tryGetInteger((addressStr + "_indexStaked"))
393507 func handler (accum,assetId) = {
394508 let assetIdStr = getAssetString(assetId)
395509 let aBalance = tryGetInteger((("global_" + getAssetString(assetId)) + "_balance"))
396510 let tokenEarningsLastCheck = tryGetInteger((("global_lastCheck_" + assetIdStr) + "_earnings"))
397511 let currentTokenInterest = calculateCurrentAssetInterest(assetId, assetIdStr, aBalance, tokenEarningsLastCheck)
398512 let currentTokenEarnings = max([tokenEarningsLastCheck, (getTokenBalance(assetId) - aBalance)])
399513 let rewardAmount = fraction(puzzleAmount, (currentTokenInterest - tryGetInteger((((addressStr + "_lastCheck_") + assetIdStr) + "_interest"))), Scale8)
400514 let transfer = if ((rewardAmount == 0))
401515 then nil
402516 else [ScriptTransfer(address, rewardAmount, assetId)]
403- $Tuple2(((accum._1 ++ transfer) ++ [IntegerEntry((("global_lastCheck_" + assetIdStr) + "_earnings"), (currentTokenEarnings - rewardAmount)), IntegerEntry((("global_lastCheck_" + assetIdStr) + "_interest"), currentTokenInterest), IntegerEntry((((addressStr + "_lastCheck_") + assetIdStr) + "_interest"), currentTokenInterest)]), (accum._2 + calculateUsdnValue(assetId, rewardAmount, aBalance, unit)))
517+ $Tuple2(((accum._1 ++ transfer) ++ [IntegerEntry((("global_lastCheck_" + assetIdStr) + "_earnings"), (currentTokenEarnings - rewardAmount)), IntegerEntry((("global_lastCheck_" + assetIdStr) + "_interest"), currentTokenInterest), IntegerEntry((((addressStr + "_lastCheck_") + assetIdStr) + "_interest"), currentTokenInterest)]), (accum._2 + calculateUsdValue(assetId, rewardAmount, aBalance)))
404518 }
405519
406520 let accum = {
407521 let $l = earnedAssets
408522 let $s = size($l)
409523 let $acc0 = $Tuple2(nil, 0)
410524 func $f4_1 ($a,$i) = if (($i >= $s))
411525 then $a
412526 else handler($a, $l[$i])
413527
414528 func $f4_2 ($a,$i) = if (($i >= $s))
415529 then $a
416530 else throw("List size exceeds 10")
417531
418532 $f4_2($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
419533 }
420534 $Tuple2((accum._1 ++ [IntegerEntry((addressStr + "_claimedRewardValue"), (tryGetInteger((addressStr + "_claimedRewardValue")) + accum._2)), IntegerEntry((addressStr + "_lastClaim"), lastBlock.timestamp)]), accum._2)
421535 }
422536
423537
424538 func indexStakeResult (addressStr,amount) = {
425539 let li = claimResult(addressFromStringValue(addressStr))._1
426540 (li ++ [IntegerEntry((addressStr + "_indexStaked"), (tryGetInteger((addressStr + "_indexStaked")) + amount)), IntegerEntry("global_indexStaked", (tryGetInteger("global_indexStaked") + amount))])
427541 }
428542
429543
430544 func sum (accum,n) = (accum + parseIntValue(n))
431545
432546
547+func checkFeeAsset (accum,next) = if (if ((indexOf(supportedFeeAssetsStr, next) != unit))
548+ then (accum == "")
549+ else false)
550+ then next
551+ else accum
552+
553+
554+func getTmpRebalanceIds (newAssetIdsLi) = {
555+ let currentAssetIdsLi = split(tryGetString("static_tokenIds"), ",")
556+ let result = newAssetIdsLi
557+ func f (accum,assetId) = if ((indexOf(result, assetId) == unit))
558+ then (accum ++ [assetId])
559+ else accum
560+
561+ let $l = currentAssetIdsLi
562+ let $s = size($l)
563+ let $acc0 = result
564+ func $f4_1 ($a,$i) = if (($i >= $s))
565+ then $a
566+ else f($a, $l[$i])
567+
568+ func $f4_2 ($a,$i) = if (($i >= $s))
569+ then $a
570+ else throw("List size exceeds 10")
571+
572+ $f4_2($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
573+ }
574+
575+
576+func checkTokensChange (newAssetIdsLi) = {
577+ let currentAssetIdsLi = split(tryGetString("static_tokenIds"), ",")
578+ func rem (accum,assetId) = if ((indexOf(newAssetIdsLi, assetId) == unit))
579+ then (accum + 1)
580+ else accum
581+
582+ func add (accum,assetId) = if ((indexOf(currentAssetIdsLi, assetId) == unit))
583+ then (accum + 1)
584+ else accum
585+
586+ let removed = {
587+ let $l = currentAssetIdsLi
588+ let $s = size($l)
589+ let $acc0 = 0
590+ func $f4_1 ($a,$i) = if (($i >= $s))
591+ then $a
592+ else rem($a, $l[$i])
593+
594+ func $f4_2 ($a,$i) = if (($i >= $s))
595+ then $a
596+ else throw("List size exceeds 10")
597+
598+ $f4_2($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
599+ }
600+ let added = {
601+ let $l = newAssetIdsLi
602+ let $s = size($l)
603+ let $acc0 = 0
604+ func $f5_1 ($a,$i) = if (($i >= $s))
605+ then $a
606+ else add($a, $l[$i])
607+
608+ func $f5_2 ($a,$i) = if (($i >= $s))
609+ then $a
610+ else throw("List size exceeds 10")
611+
612+ $f5_2($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
613+ }
614+ (removed + added)
615+ }
616+
617+
618+func validatePayments (assetsList,payments) = {
619+ func getPaymentAssets (accum,next) = if ((0 >= next.amount))
620+ then throw(((("Too low payment amount for " + getAssetString(next.assetId)) + ": ") + toString(next.amount)))
621+ else (accum ++ [getAssetString(next.assetId)])
622+
623+ let paymentList = {
624+ let $l = payments
625+ let $s = size($l)
626+ let $acc0 = nil
627+ func $f4_1 ($a,$i) = if (($i >= $s))
628+ then $a
629+ else getPaymentAssets($a, $l[$i])
630+
631+ func $f4_2 ($a,$i) = if (($i >= $s))
632+ then $a
633+ else throw("List size exceeds 10")
634+
635+ $f4_2($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
636+ }
637+ func f1 (accum,next) = if ((indexOf(assetsList, next) == unit))
638+ then throw(((next + " asset is present in payments, but is not in new assets: ") + makeString(assetsList, ",")))
639+ else accum
640+
641+ func f2 (accum,next) = if ((indexOf(paymentList, next) == unit))
642+ then throw(((next + " asset is present in new assets, but is not in payments: ") + makeString(paymentList, ",")))
643+ else accum
644+
645+ let a1 = {
646+ let $l = paymentList
647+ let $s = size($l)
648+ let $acc0 = 1
649+ func $f5_1 ($a,$i) = if (($i >= $s))
650+ then $a
651+ else f1($a, $l[$i])
652+
653+ func $f5_2 ($a,$i) = if (($i >= $s))
654+ then $a
655+ else throw("List size exceeds 10")
656+
657+ $f5_2($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
658+ }
659+ let a2 = {
660+ let $l = assetsList
661+ let $s = size($l)
662+ let $acc0 = 1
663+ func $f6_1 ($a,$i) = if (($i >= $s))
664+ then $a
665+ else f2($a, $l[$i])
666+
667+ func $f6_2 ($a,$i) = if (($i >= $s))
668+ then $a
669+ else throw("List size exceeds 10")
670+
671+ $f6_2($f6_1($f6_1($f6_1($f6_1($f6_1($f6_1($f6_1($f6_1($f6_1($f6_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
672+ }
673+ (a1 + a2)
674+ }
675+
676+
433677 @Callable(i)
434678 func preInit (assetIdsStr,assetWeightsStr,baseTokenIdStr,poolDomain,poolOwner,fee) = {
435679 let poolOwnerAddress = Address(fromBase58String(poolOwner))
680+ let assetIdsStrLi = split(assetIdsStr, ",")
681+ let assetIdsLi = {
682+ let $l = assetIdsStrLi
683+ let $s = size($l)
684+ let $acc0 = nil
685+ func $f4_1 ($a,$i) = if (($i >= $s))
686+ then $a
687+ else addAssetBytesToList($a, $l[$i])
688+
689+ func $f4_2 ($a,$i) = if (($i >= $s))
690+ then $a
691+ else throw("List size exceeds 10")
692+
693+ $f4_2($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
694+ }
695+ let feeAssetStr = {
696+ let $l = assetIdsStrLi
697+ let $s = size($l)
698+ let $acc0 = ""
699+ func $f5_1 ($a,$i) = if (($i >= $s))
700+ then $a
701+ else checkFeeAsset($a, $l[$i])
702+
703+ func $f5_2 ($a,$i) = if (($i >= $s))
704+ then $a
705+ else throw("List size exceeds 10")
706+
707+ $f5_2($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
708+ }
436709 if (isShutdown())
437710 then throw("contract is on stop")
438711 else if ((this != i.caller))
439712 then throw("admin only")
440- else if ((size(poolDomain) > 13))
441- then throw("too large pool domain")
442- else if (if ((fee > 500))
443- then true
444- else (50 > fee))
445- then throw("fee value must be between 50 and 500 (0.5-5%)")
446- else if (if (if ((indexOf(assetIdsStr, puzzleAssetIdStr) == unit))
447- then (indexOf(assetIdsStr, usdnAssetIdStr) == unit)
448- else false)
449- then (indexOf(assetIdsStr, usdtAssetIdStr) == unit)
450- else false)
451- then throw("pool must have USDT, USDN or PUZZLE in the composition")
713+ else if ((feeAssetStr == ""))
714+ then throw("pool must have one of the supported fee assets in the composition")
715+ else if ((size(poolDomain) > 13))
716+ then throw("too large pool domain")
717+ else if (if ((fee > 500))
718+ then true
719+ else (0 > fee))
720+ then throw("fee value must be between 50 and 500 (0.5-5%)")
452721 else {
453- let assetIdsStrLi = split(assetIdsStr, ",")
454- let assetIdsLi = {
455- let $l = assetIdsStrLi
456- let $s = size($l)
457- let $acc0 = nil
458- func $f4_1 ($a,$i) = if (($i >= $s))
459- then $a
460- else addAssetBytesToList($a, $l[$i])
461-
462- func $f4_2 ($a,$i) = if (($i >= $s))
463- then $a
464- else throw("List size exceeds 10")
465-
466- $f4_2($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
467- }
468722 let assetWeightsStrLi = split(assetWeightsStr, ",")
469723 let assetWeightsSum = {
470724 let $l = assetWeightsStrLi
471725 let $s = size($l)
472726 let $acc0 = 0
473- func $f5_1 ($a,$i) = if (($i >= $s))
727+ func $f6_1 ($a,$i) = if (($i >= $s))
474728 then $a
475729 else sum($a, $l[$i])
476730
477- func $f5_2 ($a,$i) = if (($i >= $s))
731+ func $f6_2 ($a,$i) = if (($i >= $s))
478732 then $a
479733 else throw("List size exceeds 10")
480734
481- $f5_2($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
735+ $f6_2($f6_1($f6_1($f6_1($f6_1($f6_1($f6_1($f6_1($f6_1($f6_1($f6_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
482736 }
483- let feeAssetStr = if ((indexOf(assetIdsStr, usdnAssetIdStr) == unit))
484- then if ((indexOf(assetIdsStr, puzzleAssetIdStr) == unit))
485- then usdtAssetIdStr
486- else puzzleAssetIdStr
487- else usdnAssetIdStr
488737 func addTokenDataEntries (accum,assetNum) = if ((assetNum >= size(assetIdsLi)))
489738 then accum
490739 else {
491740 let assetDecimals = match assetIdsLi[assetNum] {
492741 case x: ByteVector =>
493742 value(assetInfo(x)).decimals
494743 case _ =>
495744 8
496745 }
497746 (accum ++ [IntegerEntry((("static_" + assetIdsStrLi[assetNum]) + "_scale"), pow(10, 0, assetDecimals, 0, 0, DOWN)), IntegerEntry((("static_" + assetIdsStrLi[assetNum]) + "_decimals"), assetDecimals), IntegerEntry((("static_" + assetIdsStrLi[assetNum]) + "_weight"), value(parseInt(assetWeightsStrLi[assetNum])))])
498747 }
499748
500749 if ((assetWeightsSum != 10000))
501750 then throw("sum of token weights must be equal to 10000")
502751 else ({
503752 let $l = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
504753 let $s = size($l)
505754 let $acc0 = nil
506- func $f6_1 ($a,$i) = if (($i >= $s))
755+ func $f7_1 ($a,$i) = if (($i >= $s))
507756 then $a
508757 else addTokenDataEntries($a, $l[$i])
509758
510- func $f6_2 ($a,$i) = if (($i >= $s))
759+ func $f7_2 ($a,$i) = if (($i >= $s))
511760 then $a
512761 else throw("List size exceeds 10")
513762
514- $f6_2($f6_1($f6_1($f6_1($f6_1($f6_1($f6_1($f6_1($f6_1($f6_1($f6_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
515- } ++ [StringEntry("static_tokenIds", assetIdsStr), StringEntry("static_feeToken", feeAssetStr), StringEntry("static_tokenWeights", assetWeightsStr), IntegerEntry("static_tokensAmount", size(assetIdsLi)), StringEntry("static_poolDomain", poolDomain), StringEntry("static_baseTokenId", baseTokenIdStr), StringEntry("static_poolOwner", poolOwner), IntegerEntry("static_fee", fee)])
763+ $f7_2($f7_1($f7_1($f7_1($f7_1($f7_1($f7_1($f7_1($f7_1($f7_1($f7_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
764+ } ++ [StringEntry("static_tokenIds", assetIdsStr), StringEntry("static_feeToken", feeAssetStr), StringEntry("static_tokenWeights", assetWeightsStr), IntegerEntry("static_tokensAmount", size(assetIdsLi)), StringEntry("static_poolDomain", poolDomain), StringEntry("static_baseTokenId", baseTokenIdStr), StringEntry("static_poolOwner", poolOwner), IntegerEntry("static_fee", fee), IntegerEntry("static_KMult", Scale16)])
516765 }
517766 }
518767
519768
520769
521770 @Callable(i)
522771 func deInit () = if (isShutdown())
523772 then throw("contract is on stop")
524773 else if ((i.caller != this))
525774 then throw("admin only")
526775 else [IntegerEntry("global_wasInited", 0)]
527776
528777
529778
530779 @Callable(i)
531780 func init () = {
532781 func prepareList () = {
533782 func handler (accum,n) = (accum ++ [IntegerEntry((("global_" + getAssetString(n.assetId)) + "_balance"), n.amount)])
534783
535784 let $l = i.payments
536785 let $s = size($l)
537786 let $acc0 = nil
538787 func $f4_1 ($a,$i) = if (($i >= $s))
539788 then $a
540789 else handler($a, $l[$i])
541790
542791 func $f4_2 ($a,$i) = if (($i >= $s))
543792 then $a
544793 else throw("List size exceeds 10")
545794
546795 $f4_2($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
547796 }
548797
549798 func calculatePoolTokensAmount (payments) = {
550799 func handler (accum,pmt) = {
551800 let assetId = pmt.assetId
552801 func handler2 (accum,n) = if ((n == assetId))
553802 then value(indexOf(assetIds, n))
554803 else accum
555804
556805 let Token = {
557806 let $l = assetIds
558807 let $s = size($l)
559808 let $acc0 = 1
560809 func $f4_1 ($a,$i) = if (($i >= $s))
561810 then $a
562811 else handler2($a, $l[$i])
563812
564813 func $f4_2 ($a,$i) = if (($i >= $s))
565814 then $a
566815 else throw("List size exceeds 10")
567816
568817 $f4_2($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
569818 }
570819 fraction(accum, pow(pmt.amount, Decimals[Token], AssetsWeights[Token], AssetsWeightsDecimals, 8, FLOOR), Scale8)
571820 }
572821
573822 let $l = payments
574823 let $s = size($l)
575824 let $acc0 = PoolTokenScale
576825 func $f4_1 ($a,$i) = if (($i >= $s))
577826 then $a
578827 else handler($a, $l[$i])
579828
580829 func $f4_2 ($a,$i) = if (($i >= $s))
581830 then $a
582831 else throw("List size exceeds 10")
583832
584833 $f4_2($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
585834 }
586835
587836 if (isShutdown())
588837 then throw("contract is on stop")
589838 else if ((tryGetInteger("global_wasInited") > 0))
590839 then throw("pool already inited")
591840 else {
592841 let initialPoolTokens = calculatePoolTokensAmount(i.payments)
593842 if ((initialPoolTokens == 0))
594843 then throw("you need a bigger tokens amount to launch the pool")
595844 else {
596845 let poolTokenIssue = Issue(("PZ " + tryGetString("static_poolDomain")), "Puzzle Swap: pool index token", initialPoolTokens, PoolTokenDecimals, true, unit, 0)
597846 let poolTokenId = calculateAssetId(poolTokenIssue)
598847 (prepareList() ++ [poolTokenIssue, IntegerEntry("global_poolToken_amount", initialPoolTokens), IntegerEntry("global_wasInited", 1), BinaryEntry("global_poolToken_id", poolTokenId), StringEntry("static_poolToken_idStr", getAssetString(poolTokenId)), IntegerEntry((toString(i.caller) + "_indexStaked"), initialPoolTokens), IntegerEntry("global_indexStaked", initialPoolTokens)])
599848 }
600849 }
601850 }
602851
603852
604853
605854 @Callable(i)
606-func generateIndex (needChange) = if (isShutdown())
607- then throw("contract is on stop")
608- else if ((size(i.payments) != T))
609- then throw(("you need to attach all pool tokens. amount of pool tokens: " + toString(T)))
610- else if (!(checkTokensValidity(i.payments)))
611- then throw("wrong assets attached")
855+func generateIndex (needChange) = if ((size(i.payments) != T))
856+ then throw(("you need to attach all pool tokens. amount of pool tokens: " + toString(T)))
857+ else if (!(checkTokensValidity(i.payments)))
858+ then throw("wrong assets attached")
859+ else {
860+ let PIssuedNoMult = getMinPIssued(i.payments)
861+ let result = handlePoolTokensAdd(PIssuedNoMult, i.payments, i.originCaller, needChange)
862+ let PIssuedWithMult = fraction(PIssuedNoMult, Scale16, getKMult(), DOWN)
863+ let reissue = Reissue(getBinaryValue("global_poolToken_id"), PIssuedWithMult, true)
864+ $Tuple2((result ++ [reissue, ScriptTransfer(i.caller, PIssuedWithMult, tryGetBinary("global_poolToken_id")), IntegerEntry("global_poolToken_amount", (tryGetInteger("global_poolToken_amount") + PIssuedWithMult))]), PIssuedWithMult)
865+ }
866+
867+
868+
869+@Callable(i)
870+func redeemIndex (sendToOrigin) = {
871+ let pmt = i.payments[0]
872+ if ((pmt.assetId != tryGetBinary("global_poolToken_id")))
873+ then throw("please attach pool share token")
874+ else if (isShutdown())
875+ then throw("contract is on stop")
612876 else {
613- let PIssued = getMinPIssued(i.payments)
614- let reissue = Reissue(getBinaryValue("global_poolToken_id"), PIssued, true)
615- let result = handlePoolTokensAdd(PIssued, i.payments, i.originCaller, needChange)
616- $Tuple2((result ++ [reissue, ScriptTransfer(i.caller, PIssued, tryGetBinary("global_poolToken_id")), IntegerEntry("global_poolToken_amount", (tryGetInteger("global_poolToken_amount") + PIssued))]), PIssued)
877+ let PRedeemedWithMult = pmt.amount
878+ let PRedeemedWithNoMult = fraction(PRedeemedWithMult, getKMult(), Scale16, DOWN)
879+ let result = handlePoolTokensRedeem(PRedeemedWithNoMult, if (sendToOrigin)
880+ then i.originCaller
881+ else i.caller)
882+ (result ++ [Burn(tryGetBinary("global_poolToken_id"), PRedeemedWithMult), IntegerEntry("global_poolToken_amount", (tryGetInteger("global_poolToken_amount") - PRedeemedWithMult))])
617883 }
884+ }
618885
619886
620887
621888 @Callable(i)
622889 func stakeIndex () = {
623890 let addressStr = toString(i.originCaller)
624891 let pmt = i.payments[0]
625- if (isShutdown())
626- then throw("contract is on stop")
627- else if ((value(pmt.assetId) != tryGetBinary("global_poolToken_id")))
628- then throw("wrong asset attached")
629- else indexStakeResult(addressStr, pmt.amount)
892+ if ((value(pmt.assetId) != tryGetBinary("global_poolToken_id")))
893+ then throw("wrong asset attached")
894+ else indexStakeResult(addressStr, pmt.amount)
630895 }
631896
632897
633898
634899 @Callable(i)
635-func unstakeIndex (puzzleAmount) = {
900+func stakeIndexFor (addressStr) = {
901+ let pmt = i.payments[0]
902+ if ((value(pmt.assetId) != tryGetBinary("global_poolToken_id")))
903+ then throw("wrong asset attached")
904+ else indexStakeResult(addressStr, pmt.amount)
905+ }
906+
907+
908+
909+@Callable(i)
910+func unstakeIndex (indexAmount) = {
636911 let addressStr = toString(i.originCaller)
637- let puzzleAvailable = tryGetInteger((addressStr + "_indexStaked"))
912+ let indexAvailable = tryGetInteger((addressStr + "_indexStaked"))
638913 if (isShutdown())
639914 then throw("contract is on stop")
640- else if ((puzzleAmount > puzzleAvailable))
915+ else if ((indexAmount > indexAvailable))
641916 then throw("you don't have index tokens available")
642917 else if (isShutdown())
643918 then throw("contract is on stop")
644- else (claimResult(i.originCaller)._1 ++ [IntegerEntry((addressStr + "_indexStaked"), (puzzleAvailable - puzzleAmount)), IntegerEntry("global_indexStaked", (tryGetInteger("global_indexStaked") - puzzleAmount)), ScriptTransfer(i.caller, puzzleAmount, getBinaryValue("global_poolToken_id"))])
919+ else (claimResult(i.originCaller)._1 ++ [IntegerEntry((addressStr + "_indexStaked"), (indexAvailable - indexAmount)), IntegerEntry("global_indexStaked", (tryGetInteger("global_indexStaked") - indexAmount)), ScriptTransfer(i.caller, indexAmount, getBinaryValue("global_poolToken_id"))])
645920 }
646921
647922
648923
649924 @Callable(i)
650925 func claimIndexRewards () = if (isShutdown())
651926 then throw("contract is on stop")
652927 else claimResult(i.caller)
653928
654929
655930
656931 @Callable(i)
657932 func evaluateClaim (user) = $Tuple2(nil, claimResult(addressFromStringValue(user))._2)
658933
659934
660935
661936 @Callable(i)
662-func redeemIndex (sendToOrigin) = {
663- let pmt = i.payments[0]
664- if ((pmt.assetId != tryGetBinary("global_poolToken_id")))
665- then throw("please attach pool share token")
666- else if (isShutdown())
667- then throw("contract is on stop")
668- else {
669- let PRedeemed = pmt.amount
670- let result = handlePoolTokensRedeem(PRedeemed, if (sendToOrigin)
671- then i.originCaller
672- else i.caller)
673- (result ++ [Burn(tryGetBinary("global_poolToken_id"), PRedeemed), IntegerEntry("global_poolToken_amount", (tryGetInteger("global_poolToken_amount") - PRedeemed))])
674- }
675- }
676-
677-
678-
679-@Callable(i)
680937 func swap (assetOut,minimum) = {
681938 let pmt = if ((size(i.payments) == 1))
682939 then value(i.payments[0])
683940 else throw("please attach exactly one payment")
684941 let AmountIn = value(i.payments[0].amount)
685942 let AssetIn = pmt.assetId
686943 let AssetOut = getAssetBytes(assetOut)
944+ let assetIn = getAssetString(AssetIn)
945+ let scaleIn = (Scale8 / tryGetInteger((("static_" + assetIn) + "_scale")))
946+ let scaleOut = (Scale8 / tryGetInteger((("static_" + assetOut) + "_scale")))
687947 let feeAssetOutStr = tryGetString("static_feeToken")
688948 let feeAssetOut = if ((feeAssetOutStr == ""))
689949 then usdnAssetId
690- else fromBase58String(feeAssetOutStr)
950+ else getAssetBytes(feeAssetOutStr)
691951 let AssetInBalance = tryGetInteger((("global_" + getAssetString(AssetIn)) + "_balance"))
692952 let AssetOutBalance = tryGetInteger((("global_" + assetOut) + "_balance"))
953+ let AssetInBalanceScaled = (AssetInBalance * scaleIn)
954+ let AssetOutBalanceScaled = (AssetOutBalance * scaleOut)
693955 let feeAmountIn = fraction(AmountIn, Fee, FeeScale)
694956 let cleanAmountIn = (AmountIn - feeAmountIn)
695- let AmountOut = calculateOutAmount(cleanAmountIn, AssetIn, AssetOut, AssetInBalance, AssetOutBalance)
957+ let cleanAmountInScaled = (cleanAmountIn * scaleIn)
958+ let AmountOut1 = calculateOutAmount(cleanAmountInScaled, AssetIn, AssetOut, AssetInBalanceScaled, AssetOutBalanceScaled)
959+ let AmountOut = fraction(AmountOut1, 1, scaleOut)
696960 let AssetOutBalance2 = (AssetOutBalance - AmountOut)
697961 let AssetInBalance2 = (AssetInBalance + cleanAmountIn)
698962 let feeAssetOutBalance = if ((feeAssetOut == AssetIn))
699963 then AssetInBalance2
700964 else if ((feeAssetOut == AssetOut))
701965 then AssetOutBalance2
702966 else tryGetInteger((("global_" + getAssetString(feeAssetOut)) + "_balance"))
703967 let feeAmountOut = calculateOutAmount(feeAmountIn, AssetIn, feeAssetOut, AssetInBalance, feeAssetOutBalance)
704968 if ((minimum > AmountOut))
705- then throw(("amount to recieve is lower than given one: " + toString(AmountOut)))
969+ then throw("amount to recieve is lower than given one")
706970 else if ((AssetOut == AssetIn))
707971 then throw("this swap is not allowed")
708972 else if ((0 > (AssetOutBalance - AmountOut)))
709973 then throw("contract is out of reserves")
710974 else if (isShutdown())
711975 then throw("contract is on stop")
712976 else {
713977 let creatorFee = fraction(feeAmountOut, 1, 10)
714978 let protocolFee = fraction(feeAmountOut, 4, 10)
715- let stakingTopUp = if ((feeAssetOut == usdnAssetId))
716- then reentrantInvoke(Address(base58'3PFTbywqxtFfukX3HyT881g4iW5K4QL3FAS'), "topUpReward", nil, [AttachedPayment(feeAssetOut, protocolFee)])
979+ let stakingTopUp = if (if ((feeAssetOut == usdnAssetId))
980+ then true
981+ else (feeAssetOut == puzzleAssetId))
982+ then reentrantInvoke(stakingAddress, "topUpReward", nil, [AttachedPayment(feeAssetOut, protocolFee)])
717983 else unit
718984 if ((stakingTopUp == stakingTopUp))
719985 then {
720- let newBalanceIn = (AssetInBalance2 - (if ((AssetIn == feeAssetOut))
721- then feeAmountOut
722- else 0))
986+ let newBalanceIn = AssetInBalance2
723987 let newBalanceOut = (AssetOutBalance2 - (if ((AssetOut == feeAssetOut))
724988 then feeAmountOut
725989 else 0))
726990 let newBalanceFeeAsset = if (if ((feeAssetOut != AssetIn))
727991 then (feeAssetOut != AssetOut)
728992 else false)
729993 then (feeAssetOutBalance - feeAmountOut)
730994 else unit
731995 let assetInChange = IntegerEntry((("global_" + getAssetString(AssetIn)) + "_balance"), newBalanceIn)
732996 let assetOutChange = IntegerEntry((("global_" + assetOut) + "_balance"), newBalanceOut)
733997 let feeAssetOutChange = if ((newBalanceFeeAsset != unit))
734- then IntegerEntry((("global_" + getAssetString(feeAssetOut)) + "_balance"), feeAssetOutBalance)
998+ then IntegerEntry((("global_" + getAssetString(feeAssetOut)) + "_balance"), value(newBalanceFeeAsset))
735999 else StringEntry("hello", "world")
736- $Tuple2(([assetOutChange, assetInChange, feeAssetOutChange, ScriptTransfer(i.caller, AmountOut, AssetOut), ScriptTransfer(addressFromStringValue(tryGetString("static_poolOwner")), creatorFee, feeAssetOut), IntegerEntry("global_earnedByOwner", (tryGetInteger("global_earnedByOwner") + creatorFee)), IntegerEntry("global_volume", (tryGetInteger("global_volume") + calculateUsdnValue(AssetIn, AmountIn, AssetInBalance, feeAssetOutBalance)))] ++ (if ((stakingTopUp == unit))
737- then [ScriptTransfer(Address(base58'3P4kBiU4wr2yV1S5gMfu3MdkVvy7kxXHsKe'), protocolFee, feeAssetOut)]
1000+ let volumeUpdate = calculateUsdnValue(AssetIn, AmountIn, AssetInBalance, feeAssetOutBalance)
1001+ let volumeUsdUpdate = calculateUsdValue(AssetIn, AmountIn, AssetInBalance)
1002+ $Tuple2(([assetOutChange, assetInChange, feeAssetOutChange, ScriptTransfer(i.caller, AmountOut, AssetOut), ScriptTransfer(addressFromStringValue(tryGetString("static_poolOwner")), creatorFee, feeAssetOut), IntegerEntry("global_earnedByOwner", (tryGetInteger("global_earnedByOwner") + creatorFee)), IntegerEntry("global_volume", (tryGetInteger("global_volume") + volumeUpdate)), IntegerEntry("global_volume_usd", (tryGetInteger("global_volume_usd") + volumeUsdUpdate))] ++ (if ((stakingTopUp == unit))
1003+ then [ScriptTransfer(feesAddress, protocolFee, feeAssetOut)]
7381004 else nil)), AmountOut)
7391005 }
7401006 else throw("Strict value is not equal to itself.")
7411007 }
1008+ }
1009+
1010+
1011+
1012+@Callable(i)
1013+func swapReadOnly (assetIn,assetOut,AmountIn) = {
1014+ let AssetIn = getAssetBytes(assetIn)
1015+ let AssetOut = getAssetBytes(assetOut)
1016+ let scaleIn = (Scale8 / tryGetInteger((("static_" + assetIn) + "_scale")))
1017+ let scaleOut = (Scale8 / tryGetInteger((("static_" + assetOut) + "_scale")))
1018+ let feeAssetOutStr = tryGetString("static_feeToken")
1019+ let feeAssetOut = if ((feeAssetOutStr == ""))
1020+ then usdnAssetId
1021+ else getAssetBytes(feeAssetOutStr)
1022+ let AssetInBalance = tryGetInteger((("global_" + getAssetString(AssetIn)) + "_balance"))
1023+ let AssetOutBalance = tryGetInteger((("global_" + assetOut) + "_balance"))
1024+ let AssetInBalanceScaled = (AssetInBalance * scaleIn)
1025+ let AssetOutBalanceScaled = (AssetOutBalance * scaleOut)
1026+ let feeAmountIn = fraction(AmountIn, Fee, FeeScale)
1027+ let cleanAmountIn = (AmountIn - feeAmountIn)
1028+ let cleanAmountInScaled = (cleanAmountIn * scaleIn)
1029+ let AmountOut1 = calculateOutAmount(cleanAmountInScaled, AssetIn, AssetOut, AssetInBalanceScaled, AssetOutBalanceScaled)
1030+ let AmountOut = fraction(AmountOut1, 1, scaleOut)
1031+ let AssetOutBalance2 = (AssetOutBalance - AmountOut)
1032+ let AssetInBalance2 = (AssetInBalance + cleanAmountIn)
1033+ let feeAssetOutBalance = if ((feeAssetOut == AssetIn))
1034+ then AssetInBalance2
1035+ else if ((feeAssetOut == AssetOut))
1036+ then AssetOutBalance2
1037+ else tryGetInteger((("global_" + getAssetString(feeAssetOut)) + "_balance"))
1038+ let feeAmountOut = calculateOutAmount(feeAmountIn, AssetIn, feeAssetOut, AssetInBalance, feeAssetOutBalance)
1039+ if ((AssetOut == AssetIn))
1040+ then throw("this swap is not allowed")
1041+ else if ((0 > (AssetOutBalance - AmountOut)))
1042+ then throw("contract is out of reserves")
1043+ else if (isShutdown())
1044+ then throw("contract is on stop")
1045+ else $Tuple2(nil, AmountOut)
1046+ }
1047+
1048+
1049+
1050+@Callable(i)
1051+func transferOwnership (newOwnerAddress) = if ((toString(i.caller) != tryGetString("static_poolOwner")))
1052+ then throw("this call available only for pool owner")
1053+ else [StringEntry("static_poolOwner", newOwnerAddress)]
1054+
1055+
1056+
1057+@Callable(i)
1058+func setRebalancingPlan (assetIdsStr,assetWeightsStr,baseTokenIdStr,stepsAmount,stepsInterval) = if ((i.caller != addressFromStringValue(tryGetString("static_poolOwner"))))
1059+ then throw("this call available only for pool owner")
1060+ else if (valueOrElse(getBoolean(this, "rebalance_inProgress"), false))
1061+ then throw("rebalancing in progress")
1062+ else {
1063+ let newAssetWeightsStrLi = split(assetWeightsStr, ",")
1064+ let newAssetIdsStrLi = split(assetIdsStr, ",")
1065+ let feeAssetStr = {
1066+ let $l = newAssetIdsStrLi
1067+ let $s = size($l)
1068+ let $acc0 = ""
1069+ func $f4_1 ($a,$i) = if (($i >= $s))
1070+ then $a
1071+ else checkFeeAsset($a, $l[$i])
1072+
1073+ func $f4_2 ($a,$i) = if (($i >= $s))
1074+ then $a
1075+ else throw("List size exceeds 10")
1076+
1077+ $f4_2($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
1078+ }
1079+ let assetWeightsSum = {
1080+ let $l = newAssetWeightsStrLi
1081+ let $s = size($l)
1082+ let $acc0 = 0
1083+ func $f5_1 ($a,$i) = if (($i >= $s))
1084+ then $a
1085+ else sum($a, $l[$i])
1086+
1087+ func $f5_2 ($a,$i) = if (($i >= $s))
1088+ then $a
1089+ else throw("List size exceeds 10")
1090+
1091+ $f5_2($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
1092+ }
1093+ let oldAssetIds = getStringValue("static_tokenIds")
1094+ let oldAssetIdsLi = split(oldAssetIds, ",")
1095+ func findAdded (accum,next) = if ((indexOf(oldAssetIdsLi, next) == unit))
1096+ then (accum ++ [next])
1097+ else accum
1098+
1099+ func findRemoved (accum,next) = if ((indexOf(newAssetIdsStrLi, next) == unit))
1100+ then (accum ++ [next])
1101+ else accum
1102+
1103+ let addedAssets = {
1104+ let $l = newAssetIdsStrLi
1105+ let $s = size($l)
1106+ let $acc0 = nil
1107+ func $f6_1 ($a,$i) = if (($i >= $s))
1108+ then $a
1109+ else findAdded($a, $l[$i])
1110+
1111+ func $f6_2 ($a,$i) = if (($i >= $s))
1112+ then $a
1113+ else throw("List size exceeds 10")
1114+
1115+ $f6_2($f6_1($f6_1($f6_1($f6_1($f6_1($f6_1($f6_1($f6_1($f6_1($f6_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
1116+ }
1117+ let removedAssets = {
1118+ let $l = oldAssetIdsLi
1119+ let $s = size($l)
1120+ let $acc0 = nil
1121+ func $f7_1 ($a,$i) = if (($i >= $s))
1122+ then $a
1123+ else findRemoved($a, $l[$i])
1124+
1125+ func $f7_2 ($a,$i) = if (($i >= $s))
1126+ then $a
1127+ else throw("List size exceeds 10")
1128+
1129+ $f7_2($f7_1($f7_1($f7_1($f7_1($f7_1($f7_1($f7_1($f7_1($f7_1($f7_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
1130+ }
1131+ let validPayments = validatePayments(addedAssets, i.payments)
1132+ if ((size(newAssetIdsStrLi) != size(newAssetWeightsStrLi)))
1133+ then throw("assetIds and assetWeights should have same length")
1134+ else if ((feeAssetStr == ""))
1135+ then throw("pool must have one of the supported fee assets in the composition")
1136+ else if ((indexOf(newAssetIdsStrLi, baseTokenIdStr) == unit))
1137+ then throw("baseTokenId should be present in assetIds")
1138+ else if (if ((MIN_STEPS_AMOUNT > stepsAmount))
1139+ then true
1140+ else (stepsAmount > MAX_STEPS_AMOUNT))
1141+ then throw(((("Steps amount should be between " + toString(MIN_STEPS_AMOUNT)) + " and ") + toString(MAX_STEPS_AMOUNT)))
1142+ else if (if ((MIN_STEPS_INTERVAL > stepsInterval))
1143+ then true
1144+ else (stepsInterval > MAX_STEPS_INTERVAL))
1145+ then throw(((("Steps interval should be between " + toString(MIN_STEPS_INTERVAL)) + " and ") + toString(MAX_STEPS_INTERVAL)))
1146+ else if ((assetWeightsSum != 10000))
1147+ then throw("sum of token weights must be equal to 10000")
1148+ else {
1149+ func f (accum,assetIdStr) = {
1150+ let oldWeight = tryGetInteger((("static_" + assetIdStr) + "_weight"))
1151+ let newWeight = if ((indexOf(newAssetIdsStrLi, assetIdStr) == unit))
1152+ then 0
1153+ else parseIntValue(value(newAssetWeightsStrLi[value(indexOf(newAssetIdsStrLi, assetIdStr))]))
1154+ let deltaPerStep = fraction((newWeight - oldWeight), 10000, stepsAmount)
1155+ (accum ++ [toString(deltaPerStep)])
1156+ }
1157+
1158+ let tmpAssetIdsLi = getTmpRebalanceIds(newAssetIdsStrLi)
1159+ let assetDeltas = {
1160+ let $l = tmpAssetIdsLi
1161+ let $s = size($l)
1162+ let $acc0 = nil
1163+ func $f8_1 ($a,$i) = if (($i >= $s))
1164+ then $a
1165+ else f($a, $l[$i])
1166+
1167+ func $f8_2 ($a,$i) = if (($i >= $s))
1168+ then $a
1169+ else throw("List size exceeds 10")
1170+
1171+ $f8_2($f8_1($f8_1($f8_1($f8_1($f8_1($f8_1($f8_1($f8_1($f8_1($f8_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
1172+ }
1173+ let newTokensAdded = (checkTokensChange(newAssetIdsStrLi) > 0)
1174+ func recordAssetPayment (accum,next) = (accum ++ [IntegerEntry(("rebalance_attachedPayment_" + getAssetString(next.assetId)), next.amount)])
1175+
1176+ let paymentEntries = {
1177+ let $l = i.payments
1178+ let $s = size($l)
1179+ let $acc0 = nil
1180+ func $f9_1 ($a,$i) = if (($i >= $s))
1181+ then $a
1182+ else recordAssetPayment($a, $l[$i])
1183+
1184+ func $f9_2 ($a,$i) = if (($i >= $s))
1185+ then $a
1186+ else throw("List size exceeds 10")
1187+
1188+ $f9_2($f9_1($f9_1($f9_1($f9_1($f9_1($f9_1($f9_1($f9_1($f9_1($f9_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
1189+ }
1190+ let storeWeights = saveCurrentWeights()
1191+ let notifyInvoke = invoke(poolsHubAddress, "notifyPoolChange", nil, nil)
1192+ if ((notifyInvoke == notifyInvoke))
1193+ then (([StringEntry("rebalance_addedAssets", makeString(addedAssets, ",")), StringEntry("rebalance_removedAssets", makeString(removedAssets, ",")), StringEntry("tmp_rebalanceAssetIds", makeString(tmpAssetIdsLi, ",")), BooleanEntry("rebalance_inProgress", true), BooleanEntry("rebalance_newTokensAdded", newTokensAdded), IntegerEntry("rebalance_stepsDone", 0), IntegerEntry("rebalance_lastStepHeight", height), IntegerEntry("rebalance_stepsAmount", stepsAmount), IntegerEntry("rebalance_stepsInterval", stepsInterval), StringEntry("rebalance_assetIds", assetIdsStr), StringEntry("rebalance_newBaseTokenId", baseTokenIdStr), StringEntry("rebalance_assetDeltas", makeString(assetDeltas, ","))] ++ paymentEntries) ++ storeWeights)
1194+ else throw("Strict value is not equal to itself.")
1195+ }
1196+ }
1197+
1198+
1199+
1200+@Callable(i)
1201+func stepRebalancing () = if (!(valueOrElse(getBoolean(this, "rebalance_inProgress"), false)))
1202+ then throw("no rebalancing in progress")
1203+ else {
1204+ let lastStepHeight = getIntegerValue("rebalance_lastStepHeight")
1205+ let stepInterval = getIntegerValue("rebalance_stepsInterval")
1206+ let stepsDone = getIntegerValue("rebalance_stepsDone")
1207+ let nextStepHeight = (lastStepHeight + stepInterval)
1208+ if ((nextStepHeight > height))
1209+ then throw("can't be done yet")
1210+ else {
1211+ let assetDeltas = split(getStringValue("rebalance_assetDeltas"), ",")
1212+ let newAssetIdsStr = getStringValue("tmp_rebalanceAssetIds")
1213+ let newAssetIds = split(newAssetIdsStr, ",")
1214+ func f (accum,assetIdStr) = (accum ++ [toString(fraction(((valueOrElse(getInteger(("rebalance_startWeight_" + assetIdStr)), 0) * 10000) + (parseIntValue(assetDeltas[value(indexOf(newAssetIds, assetIdStr))]) * (stepsDone + 1))), 1, 10000, HALFUP))])
1215+
1216+ let newShares = makeString({
1217+ let $l = newAssetIds
1218+ let $s = size($l)
1219+ let $acc0 = nil
1220+ func $f4_1 ($a,$i) = if (($i >= $s))
1221+ then $a
1222+ else f($a, $l[$i])
1223+
1224+ func $f4_2 ($a,$i) = if (($i >= $s))
1225+ then $a
1226+ else throw("List size exceeds 10")
1227+
1228+ $f4_2($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
1229+ }, ",")
1230+ let newTokensAdded = getBooleanValue("rebalance_newTokensAdded")
1231+ let inv = if (if (newTokensAdded)
1232+ then (stepsDone == 0)
1233+ else false)
1234+ then invoke(this, "doRebalancingWithNewTokens", [newAssetIdsStr, newShares, getStringValue("rebalance_newBaseTokenId")], nil)
1235+ else invoke(this, "doRebalancing", [newShares], nil)
1236+ if ((inv == inv))
1237+ then {
1238+ let notifyInvoke = invoke(poolsHubAddress, "notifyPoolChange", nil, nil)
1239+ if ((notifyInvoke == notifyInvoke))
1240+ then {
1241+ let isFinished = ((stepsDone + 1) >= getIntegerValue("rebalance_stepsAmount"))
1242+ let actions = [BooleanEntry("rebalance_inProgress", !(isFinished)), IntegerEntry("rebalance_stepsDone", (stepsDone + 1)), IntegerEntry("rebalance_lastStepHeight", height)]
1243+ if ((stepsDone == 0))
1244+ then (actions ++ [StringEntry("static_tokenIds", newAssetIdsStr)])
1245+ else if (isFinished)
1246+ then {
1247+ let removedAssetsLi = split(tryGetString("rebalance_removedAssets"), ",")
1248+ func rmData (accum,assetId) = (accum ++ [DeleteEntry((("static_" + assetId) + "_scale")), DeleteEntry((("static_" + assetId) + "_decimals")), DeleteEntry((("static_" + assetId) + "_weight")), DeleteEntry((("static_" + assetId) + "_balance"))])
1249+
1250+ let rm = {
1251+ let $l = removedAssetsLi
1252+ let $s = size($l)
1253+ let $acc0 = nil
1254+ func $f5_1 ($a,$i) = if (($i >= $s))
1255+ then $a
1256+ else rmData($a, $l[$i])
1257+
1258+ func $f5_2 ($a,$i) = if (($i >= $s))
1259+ then $a
1260+ else throw("List size exceeds 10")
1261+
1262+ $f5_2($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
1263+ }
1264+ let finalAssetsIdsStr = tryGetString("rebalance_assetIds")
1265+ let AssetsWeightsStr = {
1266+ let $l = split(finalAssetsIdsStr, ",")
1267+ let $s = size($l)
1268+ let $acc0 = nil
1269+ func $f6_1 ($a,$i) = if (($i >= $s))
1270+ then $a
1271+ else addAssetWeightToStrList($a, $l[$i])
1272+
1273+ func $f6_2 ($a,$i) = if (($i >= $s))
1274+ then $a
1275+ else throw("List size exceeds 10")
1276+
1277+ $f6_2($f6_1($f6_1($f6_1($f6_1($f6_1($f6_1($f6_1($f6_1($f6_1($f6_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
1278+ }
1279+ ((actions ++ rm) ++ [StringEntry("static_tokenIds", finalAssetsIdsStr), StringEntry("static_tokenWeights", makeString(AssetsWeightsStr, ",")), IntegerEntry("static_tokensAmount", size(split(finalAssetsIdsStr, ",")))])
1280+ }
1281+ else actions
1282+ }
1283+ else throw("Strict value is not equal to itself.")
1284+ }
1285+ else throw("Strict value is not equal to itself.")
1286+ }
1287+ }
1288+
1289+
1290+
1291+@Callable(i)
1292+func doRebalancing (assetWeightsStr) = {
1293+ let assetWeightsStrLi = split(assetWeightsStr, ",")
1294+ let assetWeightsSum = {
1295+ let $l = assetWeightsStrLi
1296+ let $s = size($l)
1297+ let $acc0 = 0
1298+ func $f4_1 ($a,$i) = if (($i >= $s))
1299+ then $a
1300+ else sum($a, $l[$i])
1301+
1302+ func $f4_2 ($a,$i) = if (($i >= $s))
1303+ then $a
1304+ else throw("List size exceeds 10")
1305+
1306+ $f4_2($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
1307+ }
1308+ let assetIdsStrLi = split(tryGetString("static_tokenIds"), ",")
1309+ if ((i.caller != this))
1310+ then throw("this call available only for admin")
1311+ else {
1312+ let oldKMult = getKMult()
1313+ func handler (pars,assetId) = {
1314+ let accum = pars._1
1315+ let assetIdStr = getAssetString(assetId)
1316+ func handler2 (accum,n) = if ((n == assetId))
1317+ then value(indexOf(assetIds, n))
1318+ else accum
1319+
1320+ let Token = {
1321+ let $l = assetIds
1322+ let $s = size($l)
1323+ let $acc0 = 1
1324+ func $f5_1 ($a,$i) = if (($i >= $s))
1325+ then $a
1326+ else handler2($a, $l[$i])
1327+
1328+ func $f5_2 ($a,$i) = if (($i >= $s))
1329+ then $a
1330+ else throw("List size exceeds 10")
1331+
1332+ $f5_2($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
1333+ }
1334+ let balance = tryGetInteger((("global_" + assetIdStr) + "_balance"))
1335+ let weight = if ((pars._2 == "new"))
1336+ then parseIntValue(assetWeightsStrLi[Token])
1337+ else tryGetInteger((("static_" + assetIdStr) + "_weight"))
1338+ $Tuple2(fraction(accum, pow(balance, Decimals[Token], weight, AssetsWeightsDecimals, 8, FLOOR), Scale8), pars._2)
1339+ }
1340+
1341+ let newK = ( let $l = assetIds
1342+ let $s = size($l)
1343+ let $acc0 = $Tuple2(PoolTokenScale, "new")
1344+ func $f5_1 ($a,$i) = if (($i >= $s))
1345+ then $a
1346+ else handler($a, $l[$i])
1347+
1348+ func $f5_2 ($a,$i) = if (($i >= $s))
1349+ then $a
1350+ else throw("List size exceeds 10")
1351+
1352+ $f5_2($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10))._1
1353+ let oldK = ( let $l = assetIds
1354+ let $s = size($l)
1355+ let $acc0 = $Tuple2(PoolTokenScale, "old")
1356+ func $f6_1 ($a,$i) = if (($i >= $s))
1357+ then $a
1358+ else handler($a, $l[$i])
1359+
1360+ func $f6_2 ($a,$i) = if (($i >= $s))
1361+ then $a
1362+ else throw("List size exceeds 10")
1363+
1364+ $f6_2($f6_1($f6_1($f6_1($f6_1($f6_1($f6_1($f6_1($f6_1($f6_1($f6_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10))._1
1365+ let newKMult = fraction(oldKMult, newK, oldK)
1366+ func addTokenDataEntries (accum,assetNum) = if ((assetNum >= size(assetWeightsStrLi)))
1367+ then accum
1368+ else (accum ++ [IntegerEntry((("static_" + assetIdsStrLi[assetNum]) + "_weight"), value(parseInt(assetWeightsStrLi[assetNum])))])
1369+
1370+ ({
1371+ let $l = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
1372+ let $s = size($l)
1373+ let $acc0 = nil
1374+ func $f7_1 ($a,$i) = if (($i >= $s))
1375+ then $a
1376+ else addTokenDataEntries($a, $l[$i])
1377+
1378+ func $f7_2 ($a,$i) = if (($i >= $s))
1379+ then $a
1380+ else throw("List size exceeds 10")
1381+
1382+ $f7_2($f7_1($f7_1($f7_1($f7_1($f7_1($f7_1($f7_1($f7_1($f7_1($f7_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
1383+ } ++ [IntegerEntry("static_KMult", newKMult)])
1384+ }
1385+ }
1386+
1387+
1388+
1389+@Callable(i)
1390+func doRebalancingWithNewTokens (assetIdsStr,assetWeightsStr,baseTokenIdStr) = {
1391+ let newAssetWeightsStrLi = split(assetWeightsStr, ",")
1392+ let prevAssetIdsStrLi = split(tryGetString("static_tokenIds"), ",")
1393+ let newAssetIdsStrLi = split(assetIdsStr, ",")
1394+ let newAssetIds = {
1395+ let $l = newAssetIdsStrLi
1396+ let $s = size($l)
1397+ let $acc0 = nil
1398+ func $f4_1 ($a,$i) = if (($i >= $s))
1399+ then $a
1400+ else addAssetBytesToList($a, $l[$i])
1401+
1402+ func $f4_2 ($a,$i) = if (($i >= $s))
1403+ then $a
1404+ else throw("List size exceeds 10")
1405+
1406+ $f4_2($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
1407+ }
1408+ let feeAssetStr = {
1409+ let $l = newAssetIdsStrLi
1410+ let $s = size($l)
1411+ let $acc0 = ""
1412+ func $f5_1 ($a,$i) = if (($i >= $s))
1413+ then $a
1414+ else checkFeeAsset($a, $l[$i])
1415+
1416+ func $f5_2 ($a,$i) = if (($i >= $s))
1417+ then $a
1418+ else throw("List size exceeds 10")
1419+
1420+ $f5_2($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
1421+ }
1422+ let addedAssets = split(tryGetString("rebalance_addedAssets"), ",")
1423+ func findAssetPayment (assetId) = valueOrElse(getInteger(("rebalance_attachedPayment_" + getAssetString(assetId))), 0)
1424+
1425+ func addAssetBalanceToLi (li,assetId) = (li ++ [findAssetPayment(assetId)])
1426+
1427+ let attachedBalances = {
1428+ let $l = newAssetIds
1429+ let $s = size($l)
1430+ let $acc0 = nil
1431+ func $f6_1 ($a,$i) = if (($i >= $s))
1432+ then $a
1433+ else addAssetBalanceToLi($a, $l[$i])
1434+
1435+ func $f6_2 ($a,$i) = if (($i >= $s))
1436+ then $a
1437+ else throw("List size exceeds 10")
1438+
1439+ $f6_2($f6_1($f6_1($f6_1($f6_1($f6_1($f6_1($f6_1($f6_1($f6_1($f6_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
1440+ }
1441+ if ((i.caller != this))
1442+ then throw(("this call available only for admin, " + toString(i.caller)))
1443+ else {
1444+ let oldKMult = getKMult()
1445+ let oldK = getVirtualPoolTokenAmount()
1446+ func myltiplyAssetsForK (pars,assetId) = {
1447+ func findAssetNum (accum,n) = if ((n == assetId))
1448+ then value(indexOf(newAssetIds, n))
1449+ else accum
1450+
1451+ let currentK = pars
1452+ let assetIdStr = getAssetString(assetId)
1453+ let TokenNum = {
1454+ let $l = newAssetIds
1455+ let $s = size($l)
1456+ let $acc0 = 1
1457+ func $f7_1 ($a,$i) = if (($i >= $s))
1458+ then $a
1459+ else findAssetNum($a, $l[$i])
1460+
1461+ func $f7_2 ($a,$i) = if (($i >= $s))
1462+ then $a
1463+ else throw("List size exceeds 10")
1464+
1465+ $f7_2($f7_1($f7_1($f7_1($f7_1($f7_1($f7_1($f7_1($f7_1($f7_1($f7_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
1466+ }
1467+ let weight = parseIntValue(newAssetWeightsStrLi[TokenNum])
1468+ let balanceInState = tryGetInteger((("global_" + assetIdStr) + "_balance"))
1469+ let balanceInPayment = attachedBalances[TokenNum]
1470+ let balance = (balanceInState + balanceInPayment)
1471+ let assetDecimals = if ((assetId == unit))
1472+ then 8
1473+ else value(assetInfo(value(assetId))).decimals
1474+ if ((0 >= balance))
1475+ then throw(("you need to attach all new assets in payment. this asset is missed: " + assetIdStr))
1476+ else fraction(currentK, pow(balance, assetDecimals, weight, AssetsWeightsDecimals, 8, FLOOR), Scale8)
1477+ }
1478+
1479+ let newK = {
1480+ let $l = newAssetIds
1481+ let $s = size($l)
1482+ let $acc0 = PoolTokenScale
1483+ func $f7_1 ($a,$i) = if (($i >= $s))
1484+ then $a
1485+ else myltiplyAssetsForK($a, $l[$i])
1486+
1487+ func $f7_2 ($a,$i) = if (($i >= $s))
1488+ then $a
1489+ else throw("List size exceeds 10")
1490+
1491+ $f7_2($f7_1($f7_1($f7_1($f7_1($f7_1($f7_1($f7_1($f7_1($f7_1($f7_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
1492+ }
1493+ let newKMult = fraction(oldKMult, newK, oldK)
1494+ func addTokenDataEntries (accum,assetNum) = {
1495+ let assetIdStr = newAssetIdsStrLi[assetNum]
1496+ let assetId = newAssetIds[assetNum]
1497+ let assetDecimals = if ((assetId == unit))
1498+ then 8
1499+ else value(assetInfo(value(assetId))).decimals
1500+ let newAssetData = if ((indexOf(addedAssets, assetIdStr) != unit))
1501+ then [IntegerEntry((("global_" + assetIdStr) + "_balance"), attachedBalances[assetNum]), IntegerEntry((("static_" + assetIdStr) + "_scale"), pow(10, 0, assetDecimals, 0, 0, DOWN)), IntegerEntry((("static_" + assetIdStr) + "_decimals"), assetDecimals)]
1502+ else nil
1503+ if ((assetNum >= size(newAssetWeightsStrLi)))
1504+ then accum
1505+ else ((accum ++ [IntegerEntry((("static_" + assetIdStr) + "_weight"), value(parseInt(newAssetWeightsStrLi[assetNum])))]) ++ newAssetData)
1506+ }
1507+
1508+ ({
1509+ let $l = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
1510+ let $s = size($l)
1511+ let $acc0 = nil
1512+ func $f8_1 ($a,$i) = if (($i >= $s))
1513+ then $a
1514+ else addTokenDataEntries($a, $l[$i])
1515+
1516+ func $f8_2 ($a,$i) = if (($i >= $s))
1517+ then $a
1518+ else throw("List size exceeds 10")
1519+
1520+ $f8_2($f8_1($f8_1($f8_1($f8_1($f8_1($f8_1($f8_1($f8_1($f8_1($f8_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
1521+ } ++ [StringEntry("static_tokenIds", assetIdsStr), StringEntry("static_feeToken", feeAssetStr), StringEntry("static_tokenWeights", assetWeightsStr), IntegerEntry("static_tokensAmount", size(newAssetIds)), IntegerEntry("static_KMult", newKMult)])
1522+ }
7421523 }
7431524
7441525
7451526 @Verifier(tx)
7461527 func verify () = if (isShutdown())
7471528 then false
7481529 else if (sigVerify(tx.bodyBytes, tx.proofs[0], tx.senderPublicKey))
7491530 then true
7501531 else sigVerify(tx.bodyBytes, tx.proofs[0], masterPubKey)
7511532

github/deemru/w8io/6500d08 
148.37 ms