tx · FLmu9AAdpsEPykecoWP1TzWHaJBwuPGVBo7yUvnbMdHZ

3N5Xd7QVQZWntaJwha9Kg42is626GUPjtUW:  -0.01400000 Waves

2022.03.04 17:29 [1949350] smart account 3N5Xd7QVQZWntaJwha9Kg42is626GUPjtUW > SELF 0.00000000 Waves

{ "type": 13, "id": "FLmu9AAdpsEPykecoWP1TzWHaJBwuPGVBo7yUvnbMdHZ", "fee": 1400000, "feeAssetId": null, "timestamp": 1646404219523, "version": 2, "chainId": 84, "sender": "3N5Xd7QVQZWntaJwha9Kg42is626GUPjtUW", "senderPublicKey": "DfbjpZJBbZwnUKysUkxCbWTE1ZWuoUb6Y6BZdu5iAE8j", "proofs": [ "iTpESaMHH7gkLDcHm8zzjNTApSrfw6tbfg8mtEXGiZjR7ErkFwGZgYGFq2cMRSsf9FTe34vT5hoSNskF5zkhMvj", "Tzei6YmL6AZTAoJEzPW2G6YK9d7RnFM5fanX7PoifU17GZm1by4nHHQ2hFZytc31YmxCGhWXG8FcvhBANcjwe69" ], "script": "base64:AAIFAAAAAAAAACEIAhIAEgASBAoCAQESABIECgIBARIAEgASABIFCgMEAQgAAABSAAAAAAd2ZXJzaW9uAgAAAAUyLjAuMAAAAAAIa1ZlcnNpb24CAAAAB3ZlcnNpb24AAAAAB2tBY3RpdmUCAAAABmFjdGl2ZQAAAAAJa0Fzc2V0SWRBAgAAAApBX2Fzc2V0X2lkAAAAAAlrQXNzZXRJZEICAAAACkJfYXNzZXRfaWQAAAAACWtCYWxhbmNlQQIAAAAPQV9hc3NldF9iYWxhbmNlAAAAAAlrQmFsYW5jZUICAAAAD0JfYXNzZXRfYmFsYW5jZQAAAAANa1NoYXJlQXNzZXRJZAIAAAAOc2hhcmVfYXNzZXRfaWQAAAAAEWtTaGFyZUFzc2V0U3VwcGx5AgAAABJzaGFyZV9hc3NldF9zdXBwbHkAAAAABGtGZWUCAAAACmNvbW1pc3Npb24AAAAAEmtGZWVTY2FsZURlbGltaXRlcgIAAAAaY29tbWlzc2lvbl9zY2FsZV9kZWxpbWl0ZXIAAAAACmtJbnZhcmlhbnQCAAAACWludmFyaWFudAAAAAAGa0NhdXNlAgAAAA5zaHV0ZG93bl9jYXVzZQAAAAASa2V5VVNETk5TQlRBZGRyZXNzAgAAABhzdGFraW5nX3VzZG5uc2J0X2FkZHJlc3MAAAAADmtleUVVUk5BZGRyZXNzAgAAABRzdGFraW5nX2V1cm5fYWRkcmVzcwAAAAAPa2V5QWRtaW5QdWJLZXkxAgAAAAthZG1pbl9wdWJfMQAAAAAPa2V5QWRtaW5QdWJLZXkyAgAAAAthZG1pbl9wdWJfMgAAAAAPa2V5QWRtaW5QdWJLZXkzAgAAAAthZG1pbl9wdWJfMwAAAAAUVVNETlRvV2F2ZXNFeGNoYW5nZXIJAQAAAAdBZGRyZXNzAAAAAQEAAAAaAVS8ryzsOdh8IBeszy751tH1xSIv8ZigJPIAAAAABm9yYWNsZQkBAAAAB0FkZHJlc3MAAAABAQAAABoBVOlFqh6QLzqu8boO5i6akl8amITh82KzCAEAAAALZ2V0QWRtaW5QdWIAAAABAAAAC2tleUFkbWluUHViBAAAAAckbWF0Y2gwCQAEHQAAAAIFAAAABm9yYWNsZQUAAAALa2V5QWRtaW5QdWIDCQAAAQAAAAIFAAAAByRtYXRj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QmFsYW5jZQAAAAEFAAAACGFzc2V0SWRCAgAAAAEgBQAAAAphc3NldE5hbWVCAQAAABhjYWxjU3Rha2luZ0Z1bmNBbmRBZGRyZXMAAAACAAAABXN0YWtlAAAAB2Fzc2V0SWQDBQAAAAVzdGFrZQMJAAAAAAAAAgUAAAAHYXNzZXRJZAUAAAAEVVNETgkABRQAAAACAgAAAAxsb2NrTmV1dHJpbm8FAAAAFnN0YWtpbmdVU0ROTlNCVEFkZHJlc3MJAAUUAAAAAgIAAAAMc3RhcnRTdGFraW5nBQAAABJzdGFraW5nRVVSTkFkZHJlc3MDCQAAAAAAAAIFAAAAB2Fzc2V0SWQFAAAABFVTRE4JAAUUAAAAAgIAAAAOdW5sb2NrTmV1dHJpbm8FAAAAFnN0YWtpbmdVU0ROTlNCVEFkZHJlc3MJAAUUAAAAAgIAAAALc3RvcFN0YWtpbmcFAAAAEnN0YWtpbmdFVVJOQWRkcmVzcwEAAAARY2FsY1N0YWtpbmdQYXJhbXMAAAADAAAABXN0YWtlAAAABmFtb3VudAAAAAdhc3NldElkAwUAAAAFc3Rha2UEAAAACyR0MDk3MTE5Nzc3CQEAAAAYY2FsY1N0YWtpbmdGdW5jQW5kQWRkcmVzAAAAAgUAAAAFc3Rha2UFAAAAB2Fzc2V0SWQEAAAABGNhbGwIBQAAAAskdDA5NzExOTc3NwAAAAJfMQQAAAALc3Rha2luZ0FkZHIIBQAAAAskdDA5NzExOTc3NwAAAAJfMgkABRYAAAAEBQAAAARjYWxsBQAAAAtzdGFraW5nQWRkcgUAAAADbmlsCQAETAAAAAIJAQAAAA9BdHRhY2hlZFBheW1lbnQAAAACBQAAAAdhc3NldElkBQAAAAZhbW91bnQFAAAAA25pbAQAAAALJHQwOTg2Mzk5MjkJAQAAABhjYWxjU3Rha2luZ0Z1bmNBbmRBZGRyZXMAAAACBQAAAAVzdGFrZQUAAAAHYXNzZXRJZAQAAAAEY2FsbAgFAAAACyR0MDk4NjM5OTI5AAAAAl8xBAAAAAtzdGFraW5nQWRkcggFAAAACyR0MDk4NjM5OTI5AAAAAl8yCQAFFgAAAAQFAAAABGNhbGwFAAAAC3N0YWtpbmdBZGRyCQAETAAAAAIFAAAABmFtb3VudAkABEwAAAACCQACWAAAAAEFAAAA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QW1vdW50BgkABEwAAAACCQEAAAAOU2NyaXB0VHJhbnNmZXIAAAADCAUAAAABaQAAAAZjYWxsZXIFAAAAFXNoYXJlVG9rZW5Ub1BheUFtb3VudAUAAAAMc2hhcmVBc3NldElkCQAETAAAAAIJAQAAAA5TY3JpcHRUcmFuc2ZlcgAAAAMIBQAAAAFpAAAABmNhbGxlcgUAAAAGY2hhbmdlBQAAAA1jaGFuZ2VBc3NldElkBQAAAANuaWwJAAACAAAAAQIAAAAkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQAAAgAAAAECAAAAJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgAAAAFpAQAAABVyZXBsZW5pc2hXaXRoT25lVG9rZW4AAAACAAAAE3ZpcnR1YWxTd2FwVG9rZW5QYXkAAAATdmlydHVhbFN3YXBUb2tlbkdldAkBAAAAC3ZhbHVlT3JFbHNlAAAAAgkBAAAACGlzQWN0aXZlAAAAAAQAAAANJHQwMTUyOTUxNTM3MAkABRQAAAACCAkAAZEAAAACCAUAAAABaQAAAAhwYXltZW50cwAAAAAAAAAAAAAAAAZhbW91bnQICQABkQAAAAIIBQAAAAFpAAAACHBheW1lbnRzAAAAAAAAAAAAAAAAB2Fzc2V0SWQEAAAACXBtdEFtb3VudAgFAAAADSR0MDE1Mjk1MTUzNzAAAAACXzEEAAAACnBtdEFzc2V0SWQIBQAAAA0kdDAxNTI5NTE1MzcwAAAAAl8yBAAAAA0kdDAxNTM3NTE1NDQ4CQEAAAAMZ2V0QXNzZXRJbmZvAAAAAQUAAAAKcG10QXNzZXRJZAQAAAANcG10U3RyQXNzZXRJZAgFAAAADSR0MDE1Mzc1MTU0NDgAAAACXzEEAAAADHBtdEFzc2V0TmFtZQgFAAAADSR0MDE1Mzc1MTU0NDgAAAACXzIEAAAAC3BtdERlY2ltYWxzCAUAAAANJHQwMTUzNzUxNTQ0OAAAAAJfMwQAAAAPcG10TWluVGhyZXNob2xkAAAAAAAATEtABAAAAB10aHJlc2hvbGRWYWx1ZUZvck1pblRvbGVyYW5jZQAAAAAAAvrwgAQAAAAJdG9sZXJhbmNlAwkAAGYAAAACBQAAAB10aHJlc2hvbGRWYWx1ZUZvck1pblRvbGVyYW5jZQUAAAAJcG10QW1vdW50AAAAAAAAAYagAAAAAAAAAAABBAAAABxzbGlwcGFnZVZhbHVlTWluRm9yUmVwbGVuaXNoCQAAZQAAAAIFAAAABnNjYWxlOAkAAGkAAAACCQAAaAAAAAIFAAAABnNjYWxlOAUAAAAJdG9sZXJhbmNlAAAAAAAAmJaABAAAABxzbGlwcGFnZVZhbHVlTWF4Rm9yUmVwbGVuaXNoCQAAZAAAAAIFAAAABnNjYWxlOAkAAGkAAAACCQAAaAAAAAIFAAAABnNjYWxlOAUAAAAJdG9sZXJhbmNlAAAAAAAAmJaABAAAABdzbGlwcGFnZVZhbHVlTWluRm9yU3dhcAkAAGUAAAACBQAAAAZzY2FsZTgJAABpAAAAAgkAAGgAAAACBQAAAAZzY2FsZTgAAAAAAAAAAAEAAAAAAACYloADCQAAZgAAAAIFAAAAD3BtdE1pblRocmVzaG9sZAUAAAAJcG10QW1vdW50CQAAAgAAAAEJAAEsAAAAAgkAASwAAAACCQABLAAAAAIJAAEsAAAAAgIAAAAPUGF5bWVudCBhbW91bnQgCQABpAAAAAEFAAAACXBtdEFtb3VudAIAAAAnIGRvZXMgbm90IGV4Y2VlZCB0aGUgbWluaW11bSBhbW91bnQgb2YgCQABpAAAAAEFAAAAD3BtdE1pblRocmVzaG9sZAIAAAAHIHRva2VucwMJAQAAAAIhPQAAAAIJAAGQAAAAAQgFAAAAAWkAAAAIcGF5bWVudHMAAAAAAAAAAAEJAQAAAA90aHJvd09uZVBheW1lbnQAAAAAAwkBAAAAASEAAAABBQAAABBoYXNFbm91Z2hCYWxhbmNlCQAETgAAAAIJAARMAAAAAgkBAAAADlNjcmlwdFRyYW5zZmVyAAAAAwgFAAAAAWkAAAAGY2FsbGVyBQAAAAlwbXRBbW91bnQFAAAACnBtdEFzc2V0SWQFAAAAA25pbAkBAAAAEXN1c3BlbmRTdXNwaWNpb3VzAAAAAAMDCQEAAAACIT0AAAACBQAAAApwbXRBc3NldElkBQAAAAhhc3NldElkQQkBAAAAAiE9AAAAAgUAAAAKcG10QXNzZXRJZAUAAAAIYXNzZXRJZEIHCQEAAAALdGhyb3dBc3NldHMAAAAABAAAAA0kdDAxNjM4NjE3MTUxAwkAAAAAAAACBQAAAApwbXRBc3NldElkBQAAAAhhc3NldElkQQkABRkAAAAHCQAAZQAAAAIFAAAACXBtdEFtb3VudAUAAAATdmlydHVhbFN3YXBUb2tlblBheQUAAAATdmlydHVhbFN3YXBUb2tlbkdldAkAAGQAAAACBQAAAAhiYWxhbmNlQQUAAAATdmlydHVhbFN3YXBUb2tlblBheQkAAGUAAAACBQAAAAhiYWxhbmNlQgUAAAATdmlydHVhbFN3YXBUb2tlbkdldAkBAAAADWludmFyaWFudENhbGMAAAACCQAAZAAAAAIFAAAACGJhbGFuY2VBBQAAAAlwbXRBbW91bnQFAAAACGJhbGFuY2VCCQAAZAAAAAIFAAAACGJhbGFuY2VBBQAAAAlwbXRBbW91bnQFAAAACGJhbGFuY2VCCQAFGQAAAAcFAAAAE3ZpcnR1YWxTd2FwVG9rZW5HZXQJAABlAAAAAgUAAAAJcG10QW1vdW50BQAAABN2aXJ0dWFsU3dhcFRva2VuUGF5CQAAZQAAAAIFAAAACGJhbGFuY2VBBQAAABN2aXJ0dWFsU3dhcFRva2VuR2V0CQAAZAAAAAIFAAAACGJhbGFuY2VCBQAAABN2aXJ0dWFsU3dhcFRva2VuUGF5CQEAAAANaW52YXJpYW50Q2FsYwAAAAIFAAAACGJhbGFuY2VBCQAAZAAAAAIFAAAACGJhbGFuY2VCBQAAAAlwbXRBbW91bnQFAAAACGJhbGFuY2VBCQAAZAAAAAIFAAAACGJhbGFuY2VCBQAAAAlwbXRBbW91bnQEAAAAEXZpcnR1YWxSZXBsZW5pc2hBCAUAAAANJHQwMTYzODYxNzE1MQAAAAJfMQQAAAARdmlydHVhbFJlcGxlbmlzaEIIBQAAAA0kdDAxNjM4NjE3MTUxAAAAAl8yBAAAABFiYWxhbmNlQWZ0ZXJTd2FwQQgFAAAADSR0MDE2Mzg2MTcxNTEAAAACXzMEAAAAEWJhbGFuY2VBZnRlclN3YXBCCAUAAAANJHQwMTYzODYxNzE1MQAAAAJfNAQAAAATaW52YXJpYW50Q2FsY3VsYXRlZAgFAAAADSR0MDE2Mzg2MTcxNTEAAAACXzUEAAAAC25ld0JhbGFuY2VBCAUAAAANJHQwMTYzODYxNzE1MQAAAAJfNgQAAAALbmV3QmFsYW5jZUIIBQAAAA0kdDAxNjM4NjE3MTUxAAAAAl83BAAAAA9uZXdCYWxhbmNlRW50cnkDCQAAAAAAAAIFAAAACnBtdEFzc2V0SWQFAAAACGFzc2V0SWRBCQEAAAAMSW50ZWdlckVudHJ5AAAAAgUAAAAJa0JhbGFuY2VBBQAAAAtuZXdCYWxhbmNlQQkBAAAADEludGVnZXJFbnRyeQAAAAIFAAAACWtCYWxhbmNlQgUAAAALbmV3QmFsYW5jZUIEAAAADGludmFyaWFudE5ldwkBAAAADWludmFyaWFudENhbGMAAAACBQAAABFiYWxhbmNlQWZ0ZXJTd2FwQQUAAAARYmFsYW5jZUFmdGVyU3dhcEIEAAAAF2ludmFyaWFudEVzdGltYXRlZFJhdGlvCQAAawAAAAMFAAAABnNjYWxlOAUAAAAJaW52YXJpYW50BQAAAAxpbnZhcmlhbnROZXcEAAAAJXJhdGlvVmlydHVhbEJhbGFuY2VUb1ZpcnR1YWxSZXBsZW5pc2gJAABpAAAAAgkAAGsAAAADCQAAaAAAAAIFAAAABnNjYWxlOAUAAAAGc2NhbGU4BQAAABFiYWxhbmNlQWZ0ZXJTd2FwQQUAAAARYmFsYW5jZUFmdGVyU3dhcEIJAABrAAAAAwUAAAAGc2NhbGU4BQAAABF2aXJ0dWFsUmVwbGVuaXNoQQUAAAARdmlydHVhbFJlcGxlbmlzaEIEAAAAE2RBcHBUaHJlc2hvbGRBbW91bnQJAABrAAAAAwkAAGQAAAACBQAAAAtuZXdCYWxhbmNlQQUAAAALbmV3QmFsYW5jZUIFAAAADWRBcHBUaHJlc2hvbGQJAABoAAAAAgAAAAAAAAAAAgUAAAATZEFwcFRocmVzaG9sZFNjYWxlMgMDCQAAZwAAAAIFAAAAF3NsaXBwYWdlVmFsdWVNaW5Gb3JTd2FwBQAAABdpbnZhcmlhbnRFc3RpbWF0ZWRSYXRpbwYJAABmAAAAAgUAAAAJaW52YXJpYW50BQAAAAxpbnZhcmlhbnROZXcJAAACAAAAAQIAAAA6SW5jb3JyZWN0IHZpcnR1YWxTd2FwVG9rZW5QYXkgb3IgdmlydHVhbFN3YXBUb2tlbkdldCB2YWx1ZQMDCQAAZgAAAAIFAAAAHHNsaXBwYWdlVmFsdWVNaW5Gb3JSZXBsZW5pc2gFAAAAJXJhdGlvVmlydHVhbEJhbGFuY2VUb1ZpcnR1YWxSZXBsZW5pc2gGCQAAZgAAAAIFAAAAJXJhdGlvVmlydHVhbEJhbGFuY2VUb1ZpcnR1YWxSZXBsZW5pc2gFAAAAHHNsaXBwYWdlVmFsdWVNYXhGb3JSZXBsZW5pc2gJAAACAAAAAQIAAABsU3dhcCB3aXRoIHZpcnR1YWxTd2FwVG9rZW5QYXkgYW5kIHZpcnR1YWxTd2FwVG9rZW5HZXQgaXMgcG9zc2libGUsIGJ1dCByYXRpbyBhZnRlciB2aXJ0dWFsIHN3YXAgaXMgaW5jb3JyZWN0AwMJAABmAAAAAgUAAAATZEFwcFRocmVzaG9sZEFtb3VudAUAAAALbmV3QmFsYW5jZUEGCQAAZgAAAAIFAAAAE2RBcHBUaHJlc2hvbGRBbW91bnQFAAAAC25ld0JhbGFuY2VCCQEAAAAOdGhyb3dUaHJlc2hvbGQAAAADBQAAABNkQXBwVGhyZXNob2xkQW1vdW50BQAAAAtuZXdCYWxhbmNlQQUAAAALbmV3QmFsYW5jZUIEAAAABnN0YWtlMQMJAQAAAA9jb250YWluc0VsZW1lbnQAAAACBQAAAA1zdGFraW5nQXNzZXRzBQAAAA1wbXRTdHJBc3NldElkCQAD/AAAAAQFAAAABHRoaXMCAAAADHN0YWtlVW5zdGFrZQkABEwAAAACBgkABEwAAAACBQAAAAlwbXRBbW91bnQJAARMAAAAAgUAAAANcG10U3RyQXNzZXRJZAUAAAADbmlsBQAAAANuaWwAAAAAAAAAAAADCQAAAAAAAAIFAAAABnN0YWtlMQUAAAAGc3Rha2UxBAAAABNyYXRpb1NoYXJlVG9rZW5zSW5BCQAAawAAAAMFAAAAEXZpcnR1YWxSZXBsZW5pc2hBBQAAAAZzY2FsZTgFAAAAEWJhbGFuY2VBZnRlclN3YXBBBAAAABNyYXRpb1NoYXJlVG9rZW5zSW5CCQAAawAAAAMFAAAAEXZpcnR1YWxSZXBsZW5pc2hCBQAAAAZzY2FsZTgFAAAAEWJhbGFuY2VBZnRlclN3YXBCBAAAABVzaGFyZVRva2VuVG9QYXlBbW91bnQJAABrAAAAAwkAAZcAAAABCQAETAAAAAIFAAAAE3JhdGlvU2hhcmVUb2tlbnNJbkEJAARMAAAAAgUAAAATcmF0aW9TaGFyZVRva2Vuc0luQgUAAAADbmlsBQAAABBzaGFyZUFzc2V0U3VwcGx5BQAAAAZzY2FsZTgJAARMAAAAAgkBAAAAB1JlaXNzdWUAAAADBQAAAAxzaGFyZUFzc2V0SWQFAAAAFXNoYXJlVG9rZW5Ub1BheUFtb3VudAYJAARMAAAAAgkBAAAADlNjcmlwdFRyYW5zZmVyAAAAAwgFAAAAAWkAAAAGY2FsbGVyBQAAABVzaGFyZVRva2VuVG9QYXlBbW91bnQFAAAADHNoYXJlQXNzZXRJZAkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgUAAAARa1NoYXJlQXNzZXRTdXBwbHkJAABkAAAAAgUAAAAQc2hhcmVBc3NldFN1cHBseQUAAAAVc2hhcmVUb2tlblRvUGF5QW1vdW50CQAETAAAAAIFAAAAD25ld0JhbGFuY2VFbnRyeQkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgUAAAAKa0ludmFyaWFudAUAAAATaW52YXJpYW50Q2FsY3VsYXRlZAUAAAADbmlsCQAAAgAAAAECAAAAJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgAAAAFpAQAAAAh3aXRoZHJhdwAAAAAJAQAAAAt2YWx1ZU9yRWxzZQAAAAIJAQAAAAhpc0FjdGl2ZQAAAAAEAAAADSR0MDE5NDAxMTk1NDQJAAUUAAAAAggJAAGRAAAAAggFAAAAAWkAAAAIcGF5bWVudHMAAAAAAAAAAAAAAAAGYW1vdW50CAkAAZEAAAACCAUAAAABaQAAAAhwYXltZW50cwAAAAAAAAAAAAAAAAdhc3NldElkBAAAAAlwbXRBbW91bnQIBQAAAA0kdDAxOTQwMTE5NTQ0AAAAAl8xBAAAAApwbXRBc3NldElkCAUAAAANJHQwMTk0MDExOTU0NAAAAAJfMgQAAAAMYW1vdW50VG9QYXlBCQAAawAAAAMFAAAACXBtdEFtb3VudAUAAAAIYmFsYW5jZUEFAAAAEHNoYXJlQXNzZXRTdXBwbHkEAAAADGFtb3VudFRvUGF5QgkAAGsAAAADBQAAAAlwbXRBbW91bnQFAAAACGJhbGFuY2VCBQAAABBzaGFyZUFzc2V0U3VwcGx5BAAAABNpbnZhcmlhbnRDYWxjdWxhdGVkCQEAAAANaW52YXJpYW50Q2FsYwAAAAIJAABlAAAAAgUAAAAIYmFsYW5jZUEFAAAADGFtb3VudFRvUGF5QQkAAGUAAAACBQAAAAhiYWxhbmNlQgUAAAAMYW1vdW50VG9QYXlCAwkBAAAAAiE9AAAAAgkAAZAAAAABCAUAAAABaQAAAAhwYXltZW50cwAAAAAAAAAAAQkBAAAAD3Rocm93T25lUGF5bWVudAAAAAADCQEAAAACIT0AAAACBQAAAApwbXRBc3NldElkBQAAAAxzaGFyZUFzc2V0SWQJAAACAAAAAQkAASwAAAACAgAAACRJbmNvcnJlY3QgYXNzZXQgYXR0YWNoZWQuIEV4cGVjdGVkOiAJAAJYAAAAAQUAAAAMc2hhcmVBc3NldElkAwkBAAAAASEAAAABBQAAABBoYXNFbm91Z2hCYWxhbmNlCQAETgAAAAIJAARMAAAAAgkBAAAADlNjcmlwdFRyYW5zZmVyAAAAAwgFAAAAAWkAAAAGY2FsbGVyBQAAAAlwbXRBbW91bnQFAAAACnBtdEFzc2V0SWQFAAAAA25pbAkBAAAAEXN1c3BlbmRTdXNwaWNpb3VzAAAAAAQAAAAGc3Rha2UxAwkBAAAAD2NvbnRhaW5zRWxlbWVudAAAAAIFAAAADXN0YWtpbmdBc3NldHMFAAAAC3N0ckFzc2V0SWRBCQAD/AAAAAQFAAAABHRoaXMCAAAADHN0YWtlVW5zdGFrZQkABEwAAAACBwkABEwAAAACBQAAAAxhbW91bnRUb1BheUEJAARMAAAAAgUAAAALc3RyQXNzZXRJZEEFAAAAA25pbAUAAAADbmlsAAAAAAAAAAAAAwkAAAAAAAACBQAAAAZzdGFrZTEFAAAABnN0YWtlMQQAAAAGc3Rha2UyAwkBAAAAD2NvbnRhaW5zRWxlbWVudAAAAAIFAAAADXN0YWtpbmdBc3NldHMFAAAAC3N0ckFzc2V0SWRCCQAD/AAAAAQFAAAABHRoaXMCAAAADHN0YWtlVW5zdGFrZQkABEwAAAACBwkABEwAAAACBQAAAAxhbW91bnRUb1BheUIJAARMAAAAAgUAAAALc3RyQXNzZXRJZEIFAAAAA25pbAUAAAADbmlsAAAAAAAAAAAAAwkAAAAAAAACBQAAAAZzdGFrZTIFAAAABnN0YWtlMgkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgUAAAAJa0JhbGFuY2VBCQAAZQAAAAIFAAAACGJhbGFuY2VBBQAAAAxhbW91bnRUb1BheUEJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAIFAAAACWtCYWxhbmNlQgkAAGUAAAACBQAAAAhiYWxhbmNlQgUAAAAMYW1vdW50VG9QYXlCCQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACBQAAABFrU2hhcmVBc3NldFN1cHBseQkAAGUAAAACBQAAABBzaGFyZUFzc2V0U3VwcGx5BQAAAAlwbXRBbW91bnQJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAIFAAAACmtJbnZhcmlhbnQFAAAAE2ludmFyaWFudENhbGN1bGF0ZWQJAARMAAAAAgkBAAAABEJ1cm4AAAACBQAAAAxzaGFyZUFzc2V0SWQFAAAACXBtdEFtb3VudAkABEwAAAACCQEAAAAOU2NyaXB0VHJhbnNmZXIAAAADCAUAAAABaQAAAAZjYWxsZXIFAAAADGFtb3VudFRvUGF5QQUAAAAIYXNzZXRJZEEJAARMAAAAAgkBAAAADlNjcmlwdFRyYW5zZmVyAAAAAwgFAAAAAWkAAAAGY2FsbGVyBQAAAAxhbW91bnRUb1BheUIFAAAACGFzc2V0SWRCBQAAAANuaWwJAAACAAAAAQIAAAAkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQAAAgAAAAECAAAAJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgAAAAFpAQAAAAhleGNoYW5nZQAAAAIAAAAYZXN0aW1hdGVkQW1vdW50VG9SZWNlaXZlAAAAEm1pbkFtb3VudFRvUmVjZWl2ZQkBAAAAC3ZhbHVlT3JFbHNlAAAAAgkBAAAACGlzQWN0aXZlAAAAAAQAAAANJHQwMjEwMDcyMTA4MgkABRQAAAACCAkAAZEAAAACCAUAAAABaQAAAAhwYXltZW50cwAAAAAAAAAAAAAAAAZhbW91bnQICQABkQAAAAIIBQAAAAFpAAAACHBheW1lbnRzAAAAAAAAAAAAAAAAB2Fzc2V0SWQEAAAACXBtdEFtb3VudAgFAAAADSR0MDIxMDA3MjEwODIAAAACXzEEAAAACnBtdEFzc2V0SWQIBQAAAA0kdDAyMTAwNzIxMDgyAAAAAl8yAwkAAGcAAAACAAAAAAAAAAAABQAAABhlc3RpbWF0ZWRBbW91bnRUb1JlY2VpdmUJAAACAAAAAQkAASwAAAACAgAAACtFc3RpbWF0ZWQgYW1vdW50IG11c3QgYmUgcG9zaXRpdmUuIEFjdHVhbDogCQABpAAAAAEFAAAAGGVzdGltYXRlZEFtb3VudFRvUmVjZWl2ZQMJAABmAAAAAgUAAAASbWluQW1vdW50VG9SZWNlaXZlBQAAABhlc3RpbWF0ZWRBbW91bnRUb1JlY2VpdmUJAAACAAAAAQkAASwAAAACCQABLAAAAAIJAAEsAAAAAgIAAAA7TWluaW1hbCBhbW91bnQgY2FuJ3QgYmUgZ3JlYXRlciB0aGFuIGVzdGltYXRlZC4gRXN0aW1hdGVkOiAJAAGkAAAAAQUAAAAYZXN0aW1hdGVkQW1vdW50VG9SZWNlaXZlAgAAAAsuIE1pbmltYWw6IAkAAaQAAAABBQAAABJtaW5BbW91bnRUb1JlY2VpdmUDCQEAAAACIT0AAAACCQABkAAAAAEIBQAAAAFpAAAACHBheW1lbnRzAAAAAAAAAAABCQEAAAAPdGhyb3dPbmVQYXltZW50AAAAAAMJAQAAAAEhAAAAAQUAAAAQaGFzRW5vdWdoQmFsYW5jZQkABE4AAAACCQAETAAAAAIJAQAAAA5TY3JpcHRUcmFuc2ZlcgAAAAMIBQAAAAFpAAAABmNhbGxlcgUAAAAJcG10QW1vdW50BQAAAApwbXRBc3NldElkBQAAAANuaWwJAQAAABFzdXNwZW5kU3VzcGljaW91cwAAAAADAwkBAAAAAiE9AAAAAgUAAAAKcG10QXNzZXRJZAUAAAAIYXNzZXRJZEEJAQAAAAIhPQAAAAIFAAAACnBtdEFzc2V0SWQFAAAACGFzc2V0SWRCBwkBAAAAC3Rocm93QXNzZXRzAAAAAAMJAABmAAAAAgAAAAAAAJiWgAUAAAAJcG10QW1vdW50CQAAAgAAAAECAAAAME9ubHkgc3dhcCBvZiAxMC4wMDAwMDAgb3IgbW9yZSB0b2tlbnMgaXMgYWxsb3dlZAMDCQAAZgAAAAIFAAAAFWV4Y2hhbmdlUmF0aW9MaW1pdE1pbgkAAGsAAAADBQAAAAZzY2FsZTgFAAAAEm1pbkFtb3VudFRvUmVjZWl2ZQUAAAAJcG10QW1vdW50BgkAAGYAAAACCQAAawAAAAMFAAAABnNjYWxlOAUAAAAYZXN0aW1hdGVkQW1vdW50VG9SZWNlaXZlBQAAAAlwbXRBbW91bnQFAAAAFWV4Y2hhbmdlUmF0aW9MaW1pdE1heAkAAAIAAAABAgAAABxJbmNvcnJlY3QgYXJncyBhbmQgcG10IHJhdGlvBAAAAAtzZW5kQXNzZXRJZAMJAAAAAAAAAgUAAAAKcG10QXNzZXRJZAUAAAAIYXNzZXRJZEEFAAAACGFzc2V0SWRCBQAAAAhhc3NldElkQQQAAAANJHQwMjIxNzMyMjI5MgkBAAAAE2NhbGN1bGF0ZVNlbmRBbW91bnQAAAAEBQAAABhlc3RpbWF0ZWRBbW91bnRUb1JlY2VpdmUFAAAAEm1pbkFtb3VudFRvUmVjZWl2ZQUAAAAJcG10QW1vdW50BQAAAApwbXRBc3NldElkBAAAAAZhbW91bnQIBQAAAA0kdDAyMjE3MzIyMjkyAAAAAl8xBAAAAA5hbW91bnRJbnZhcmlhbggFAAAADSR0MDIyMTczMjIyOTIAAAACXzIEAAAAEGdvdmVybmFuY2VSZXdhcmQJAABrAAAAAwUAAAAGYW1vdW50BQAAAA1mZWVHb3Zlcm5hbmNlBQAAAAlmZWVTY2FsZTYEAAAADmFtb3VudE1pbnVzRmVlCQAAawAAAAMFAAAABmFtb3VudAkAAGUAAAACBQAAAAlmZWVTY2FsZTYFAAAAA2ZlZQUAAAAJZmVlU2NhbGU2BAAAAA0kdDAyMjQ0ODIyNzEwAwkAAAAAAAACBQAAAApwbXRBc3NldElkBQAAAAhhc3NldElkQQkABRQAAAACCQAAZAAAAAIFAAAACGJhbGFuY2VBBQAAAAlwbXRBbW91bnQJAABlAAAAAgkAAGUAAAACBQAAAAhiYWxhbmNlQgUAAAAOYW1vdW50TWludXNGZWUFAAAAEGdvdmVybmFuY2VSZXdhcmQJAAUUAAAAAgkAAGUAAAACCQAAZQAAAAIFAAAACGJhbGFuY2VBBQAAAA5hbW91bnRNaW51c0ZlZQUAAAAQZ292ZXJuYW5jZVJld2FyZAkAAGQAAAACBQAAAAhiYWxhbmNlQgUAAAAJcG10QW1vdW50BAAAAAtuZXdCYWxhbmNlQQgFAAAADSR0MDIyNDQ4MjI3MTAAAAACXzEEAAAAC25ld0JhbGFuY2VCCAUAAAANJHQwMjI0NDgyMjcxMAAAAAJfMgQAAAATZEFwcFRocmVzaG9sZEFtb3VudAkAAGsAAAADCQAAZAAAAAIFAAAAC25ld0JhbGFuY2VBBQAAAAtuZXdCYWxhbmNlQgUAAAANZEFwcFRocmVzaG9sZAkAAGgAAAACAAAAAAAAAAACBQAAABNkQXBwVGhyZXNob2xkU2NhbGUyAwMJAABmAAAAAgUAAAATZEFwcFRocmVzaG9sZEFtb3VudAUAAAALbmV3QmFsYW5jZUEGCQAAZgAAAAIFAAAAE2RBcHBUaHJlc2hvbGRBbW91bnQFAAAAC25ld0JhbGFuY2VCCQEAAAAOdGhyb3dUaHJlc2hvbGQAAAADBQAAABNkQXBwVGhyZXNob2xkQW1vdW50BQAAAAtuZXdCYWxhbmNlQQUAAAALbmV3QmFsYW5jZUIEAAAADSR0MDIzMDA4MjMwODEJAQAAAAxnZXRBc3NldEluZm8AAAABBQAAAApwbXRBc3NldElkBAAAAA1wbXRTdHJBc3NldElkCAUAAAANJHQwMjMwMDgyMzA4MQAAAAJfMQQAAAAMcG10QXNzZXROYW1lCAUAAAANJHQwMjMwMDgyMzA4MQAAAAJfMgQAAAALcG10RGVjaW1hbHMIBQAAAA0kdDAyMzAwODIzMDgxAAAAAl8zBAAAAA0kdDAyMzA5NDIzMTcxCQEAAAAMZ2V0QXNzZXRJbmZvAAAAAQUAAAALc2VuZEFzc2V0SWQEAAAADnNlbmRTdHJBc3NldElkCAUAAAANJHQwMjMwOTQyMzE3MQAAAAJfMQQAAAANc2VuZEFzc2V0TmFtZQgFAAAADSR0MDIzMDk0MjMxNzEAAAACXzIEAAAADHNlbmREZWNpbWFscwgFAAAADSR0MDIzMDk0MjMxNzEAAAACXzMEAAAABnN0YWtlMQMJAQAAAA9jb250YWluc0VsZW1lbnQAAAACBQAAAA1zdGFraW5nQXNzZXRzBQAAAA1wbXRTdHJBc3NldElkCQAD/AAAAAQFAAAABHRoaXMCAAAADHN0YWtlVW5zdGFrZQkABEwAAAACBgkABEwAAAACBQAAAAlwbXRBbW91bnQJAARMAAAAAgUAAAANcG10U3RyQXNzZXRJZAUAAAADbmlsBQAAAANuaWwAAAAAAAAAAAADCQAAAAAAAAIFAAAABnN0YWtlMQUAAAAGc3Rha2UxBAAAAAZzdGFrZTIDCQEAAAAPY29udGFpbnNFbGVtZW50AAAAAgUAAAANc3Rha2luZ0Fzc2V0cwUAAAAOc2VuZFN0ckFzc2V0SWQJAAP8AAAABAUAAAAEdGhpcwIAAAAMc3Rha2VVbnN0YWtlCQAETAAAAAIHCQAETAAAAAIJAABkAAAAAgUAAAAOYW1vdW50TWludXNGZWUFAAAAEGdvdmVybmFuY2VSZXdhcmQJAARMAAAAAgUAAAAOc2VuZFN0ckFzc2V0SWQFAAAAA25pbAUAAAADbmlsAAAAAAAAAAAAAwkAAAAAAAACBQAAAAZzdGFrZTIFAAAABnN0YWtlMgkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgUAAAAJa0JhbGFuY2VBBQAAAAtuZXdCYWxhbmNlQQkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgUAAAAJa0JhbGFuY2VCBQAAAAtuZXdCYWxhbmNlQgkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgUAAAAKa0ludmFyaWFudAUAAAAOYW1vdW50SW52YXJpYW4JAARMAAAAAgkBAAAADlNjcmlwdFRyYW5zZmVyAAAAAwgFAAAAAWkAAAAGY2FsbGVyBQAAAA5hbW91bnRNaW51c0ZlZQUAAAALc2VuZEFzc2V0SWQJAARMAAAAAgkBAAAADlNjcmlwdFRyYW5zZmVyAAAAAwUAAAANd2FsbGV0QWRkcmVzcwUAAAAQZ292ZXJuYW5jZVJld2FyZAUAAAALc2VuZEFzc2V0SWQFAAAAA25pbAkAAAIAAAABAgAAACRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAACAAAAAQIAAAAkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAAAAAWkBAAAACHNodXRkb3duAAAAAAkBAAAAC3ZhbHVlT3JFbHNlAAAAAgkBAAAAC2lzQWRtaW5DYWxsAAAAAQUAAAABaQMJAQAAAAEhAAAAAQUAAAAGYWN0aXZlCQAAAgAAAAEJAAEsAAAAAgIAAAAiREFwcCBpcyBhbHJlYWR5IHN1c3BlbmRlZC4gQ2F1c2U6IAkBAAAAC3ZhbHVlT3JFbHNlAAAAAgkABB0AAAACBQAAAAR0aGlzBQAAAAZrQ2F1c2UCAAAAGnRoZSBjYXVzZSB3YXNuJ3Qgc3BlY2lmaWVkCQEAAAAHc3VzcGVuZAAAAAECAAAAD1BhdXNlZCBieSBhZG1pbgAAAAFpAQAAAAhhY3RpdmF0ZQAAAAAJAQAAAAt2YWx1ZU9yRWxzZQAAAAIJAQAAAAtpc0FkbWluQ2FsbAAAAAEFAAAAAWkDBQAAAAZhY3RpdmUJAQAAAA10aHJvd0lzQWN0aXZlAAAAAAkABEwAAAACCQEAAAAMQm9vbGVhbkVudHJ5AAAAAgUAAAAHa0FjdGl2ZQYJAARMAAAAAgkBAAAAC0RlbGV0ZUVudHJ5AAAAAQUAAAAGa0NhdXNlBQAAAANuaWwAAAABaQEAAAAZdGFrZUludG9BY2NvdW50RXh0cmFGdW5kcwAAAAAJAQAAAAt2YWx1ZU9yRWxzZQAAAAIJAQAAAAhpc0FjdGl2ZQAAAAAEAAAADWFtb3VudEVucm9sbEEJAABlAAAAAgUAAAAZYWNjb3VudEJhbGFuY2VXaXRoU3Rha2VkQQUAAAAIYmFsYW5jZUEEAAAADWFtb3VudEVucm9sbEIJAABlAAAAAgUAAAAZYWNjb3VudEJhbGFuY2VXaXRoU3Rha2VkQgUAAAAIYmFsYW5jZUIEAAAADGludmFyaWFudE5ldwkBAAAADWludmFyaWFudENhbGMAAAACCQAAZAAAAAIFAAAACGJhbGFuY2VBBQAAAA1hbW91bnRFbnJvbGxBCQAAZAAAAAIFAAAACGJhbGFuY2VCBQAAAA1hbW91bnRFbnJvbGxCAwkBAAAAAiE9AAAAAggFAAAAAWkAAAAGY2FsbGVyBQAAAA13YWxsZXRBZGRyZXNzCQAAAgAAAAECAAAAJk9ubHkgdGhlIHdhbGxldCBjYW4gY2FsbCB0aGlzIGZ1bmN0aW9uAwMJAABmAAAAAgAAAAAAAAAAAAUAAAANYW1vdW50RW5yb2xsQQYJAABmAAAAAgAAAAAAAAAAAAUAAAANYW1vdW50RW5yb2xsQgkBAAAAB3N1c3BlbmQAAAABAgAAABZFbnJvbGwgYW1vdW50IG5lZ2F0aXZlAwMJAAAAAAAAAgUAAAANYW1vdW50RW5yb2xsQQAAAAAAAAAAAAkAAAAAAAACBQAAAA1hbW91bnRFbnJvbGxCAAAAAAAAAAAABwkAAAIAAAABAgAAABBObyBtb25leSB0byB0YWtlBAAAAAZzdGFrZTEDAwkBAAAAD2NvbnRhaW5zRWxlbWVudAAAAAIFAAAADXN0YWtpbmdBc3NldHMFAAAAC3N0ckFzc2V0SWRBCQAAZgAAAAIFAAAADWFtb3VudEVucm9sbEEAAAAAAAAAAAAHCQAD/AAAAAQFAAAABHRoaXMCAAAADHN0YWtlVW5zdGFrZQkABEwAAAACBgkABEwAAAACBQAAAA1hbW91bnRFbnJvbGxBCQAETAAAAAIFAAAAC3N0ckFzc2V0SWRBBQAAAANuaWwFAAAAA25pbAAAAAAAAAAAAAMJAAAAAAAAAgUAAAAGc3Rha2UxBQAAAAZzdGFrZTEEAAAABnN0YWtlMgMDCQEAAAAPY29udGFpbnNFbGVtZW50AAAAAgUAAAANc3Rha2luZ0Fzc2V0cwUAAAALc3RyQXNzZXRJZEIJAABmAAAAAgUAAAANYW1vdW50RW5yb2xsQgAAAAAAAAAAAAcJAAP8AAAABAUAAAAEdGhpcwIAAAAMc3Rha2VVbnN0YWtlCQAETAAAAAIGCQAETAAAAAIFAAAADWFtb3VudEVucm9sbEIJAARMAAAAAgUAAAALc3RyQXNzZXRJZEIFAAAAA25pbAUAAAADbmlsAAAAAAAAAAAAAwkAAAAAAAACBQAAAAZzdGFrZTIFAAAABnN0YWtlMgkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgUAAAAKa0ludmFyaWFudAUAAAAMaW52YXJpYW50TmV3CQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACBQAAAAlrQmFsYW5jZUEJAABkAAAAAgUAAAAIYmFsYW5jZUEFAAAADWFtb3VudEVucm9sbEEJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAIFAAAACWtCYWxhbmNlQgkAAGQAAAACBQAAAAhiYWxhbmNlQgUAAAANYW1vdW50RW5yb2xsQgkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgkAASwAAAACAgAAAAxsYXN0X2luY29tZV8FAAAAC3N0ckFzc2V0SWRBBQAAAA1hbW91bnRFbnJvbGxBCQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACCQABLAAAAAICAAAADGxhc3RfaW5jb21lXwUAAAALc3RyQXNzZXRJZEIFAAAADWFtb3VudEVucm9sbEIFAAAAA25pbAkAAAIAAAABAgAAACRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAACAAAAAQIAAAAkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAAAAAWkBAAAADHN0YWtlVW5zdGFrZQAAAAMAAAAFc3Rha2UAAAAGYW1vdW50AAAADWFzc2V0SWRTdHJpbmcDCQEAAAACIT0AAAACCAUAAAABaQAAAAZjYWxsZXIFAAAABHRoaXMJAAACAAAAAQIAAAAtT25seSBjb250cmFjdCBpdHNlbGYgY2FuIGludm9rZSB0aGlzIGZ1bmN0aW9uBAAAAA0kdDAyNTk1ODI2MDYxCQEAAAARY2FsY1N0YWtpbmdQYXJhbXMAAAADBQAAAAVzdGFrZQUAAAAGYW1vdW50CQACWQAAAAEFAAAADWFzc2V0SWRTdHJpbmcEAAAABGNhbGwIBQAAAA0kdDAyNTk1ODI2MDYxAAAAAl8xBAAAAARhZGRyCAUAAAANJHQwMjU5NTgyNjA2MQAAAAJfMgQAAAAGcGFyYW1zCAUAAAANJHQwMjU5NTgyNjA2MQAAAAJfMwQAAAAIcGF5bWVudHMIBQAAAA0kdDAyNTk1ODI2MDYxAAAAAl80BAAAAANpbnYJAAP8AAAABAUAAAAEYWRkcgUAAAAEY2FsbAUAAAAGcGFyYW1zBQAAAAhwYXltZW50cwMJAAAAAAAAAgUAAAADaW52BQAAAANpbnYFAAAAA25pbAkAAAIAAAABAgAAACRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4AAAABAAAAAnR4AQAAAAZ2ZXJpZnkAAAAABAAAABNtdWx0aVNpZ25lZEJ5QWRtaW5zBAAAABJhZG1pblB1YktleTFTaWduZWQDCQAB9AAAAAMIBQAAAAJ0eAAAAAlib2R5Qnl0ZXMJAAGRAAAAAggFAAAAAnR4AAAABnByb29mcwAAAAAAAAAAAAUAAAAMYWRtaW5QdWJLZXkxAAAAAAAAAAABAAAAAAAAAAAABAAAABJhZG1pblB1YktleTJTaWduZWQDCQAB9AAAAAMIBQAAAAJ0eAAAAAlib2R5Qnl0ZXMJAAGRAAAAAggFAAAAAnR4AAAABnByb29mcwAAAAAAAAAAAQUAAAAMYWRtaW5QdWJLZXkyAAAAAAAAAAABAAAAAAAAAAAABAAAABJhZG1pblB1YktleTNTaWduZWQDCQAB9AAAAAMIBQAAAAJ0eAAAAAlib2R5Qnl0ZXMJAAGRAAAAAggFAAAAAnR4AAAABnByb29mcwAAAAAAAAAAAgUAAAAMYWRtaW5QdWJLZXkzAAAAAAAAAAABAAAAAAAAAAAACQAAZwAAAAIJAABkAAAAAgkAAGQAAAACBQAAABJhZG1pblB1YktleTFTaWduZWQFAAAAEmFkbWluUHViS2V5MlNpZ25lZAUAAAASYWRtaW5QdWJLZXkzU2lnbmVkAAAAAAAAAAACBAAAAAckbWF0Y2gwBQAAAAJ0eAMJAAABAAAAAgUAAAAHJG1hdGNoMAIAAAAXSW52b2tlU2NyaXB0VHJhbnNhY3Rpb24EAAAAA2ludgUAAAAHJG1hdGNoMAQAAAATY2FsbFRha2VJbnRvQWNjb3VudAMJAAAAAAAAAggFAAAAA2ludgAAAARkQXBwBQAAAAR0aGlzCQAAAAAAAAIIBQAAAANpbnYAAAAIZnVuY3Rpb24CAAAAGXRha2VJbnRvQWNjb3VudEV4dHJhRnVuZHMHBAAAAA1zaWduZWRCeUFkbWluAwMDCQAB9AAAAAMIBQAAAAJ0eAAAAAlib2R5Qnl0ZXMJAAGRAAAAAggFAAAAAnR4AAAABnByb29mcwAAAAAAAAAAAAUAAAAMYWRtaW5QdWJLZXkxBgkAAfQAAAADCAUAAAACdHgAAAAJYm9keUJ5dGVzCQABkQAAAAIIBQAAAAJ0eAAAAAZwcm9vZnMAAAAAAAAAAAAFAAAADGFkbWluUHViS2V5MgYJAAH0AAAAAwgFAAAAAnR4AAAACWJvZHlCeXRlcwkAAZEAAAACCAUAAAACdHgAAAAGcHJvb2ZzAAAAAAAAAAAABQAAAAxhZG1pblB1YktleTMGCQAB9AAAAAMIBQAAAAJ0eAAAAAlib2R5Qnl0ZXMJAAGRAAAAAggFAAAAAnR4AAAABnByb29mcwAAAAAAAAAAAAUAAAAKYWRtU3Rha2luZwMDBQAAABNjYWxsVGFrZUludG9BY2NvdW50BQAAAA1zaWduZWRCeUFkbWluBwYFAAAAE211bHRpU2lnbmVkQnlBZG1pbnMFAAAAE211bHRpU2lnbmVkQnlBZG1pbnNEFBpX", "height": 1949350, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: 6QnjJjju7RfGB8wdbdNbJbiiGQuzpWLKNzrZxUoZZ27x Next: G7LYSbhrEcqsFwWV3yGWYNTLVN53ZSvpxXTauQKpoLnv Diff:
OldNewDifferences
2727
2828 let kCause = "shutdown_cause"
2929
30-let kFirstHarvest = "first_harvest"
30+let keyUSDNNSBTAddress = "staking_usdnnsbt_address"
3131
32-let kFirstHarvestHeight = "first_harvest_height"
33-
34-let kShareLimit = "share_limit_on_first_harvest"
35-
36-let kBasePeriod = "base_period"
37-
38-let kPeriodLength = "period_length"
39-
40-let kStartHeight = "start_height"
41-
42-let kOracleAssetPriority = "asset_priority_"
43-
44-let kOracleScriptHash = "script_hash_flat"
45-
46-let kInitPoolHeight = "init_pool_height_"
32+let keyEURNAddress = "staking_eurn_address"
4733
4834 let keyAdminPubKey1 = "admin_pub_1"
4935
5440 let USDNToWavesExchanger = Address(base58'3N77kfPbQyjXWpDALX3xjKw3iEGMWEctV37')
5541
5642 let oracle = Address(base58'3NBBWfzZtZtszaXbitTKnrB2xXwv26Bn7H9')
57-
58-let walletAddress = Address(base58'3NAGTtZz6WpupSN89NZD5rMZwwziZEg4Kx4')
59-
60-let votingAddress = Address(base58'3MrJgdL1GniipErHy44YF9idzLaUL2iX5DQ')
6143
6244 func getAdminPub (keyAdminPub) = match getString(oracle, keyAdminPub) {
6345 case string: String =>
7759
7860 let admStaking = base58'Kn7NpzaG12dLZgcHf2ipUftU6hbJygmrhFqQYE4B7ZK'
7961
80-let basePeriod = valueOrErrorMessage(getInteger(votingAddress, kBasePeriod), "Empty kBasePeriod")
81-
82-let startHeight = valueOrErrorMessage(getInteger(votingAddress, kStartHeight), "Empty kStartHeight")
83-
84-let periodLength = valueOrErrorMessage(getInteger(votingAddress, kPeriodLength), "Empty kPeriodLength")
85-
86-let firstHarvestEndPeriod = ((basePeriod + ((height - startHeight) / periodLength)) + 1)
87-
88-let stakingAddress = Address(base58'3N6q7sCGSSLBUXDdjBdYGTJbZGZfhhh8cNg')
62+let walletAddress = Address(base58'3NAGTtZz6WpupSN89NZD5rMZwwziZEg4Kx4')
8963
9064 let USDN = base58'8UrfDVd5GreeUwm7uPk7eYz1eMv376kzR52C6sANPkwS'
9165
92-let SWOP = base58'2HAJrwa8q4SxBx9cHYaBTQdBjdk5wwqdof7ccpAx2uhZ'
66+let EURN = base58'ECBCkHS68DckpBrzLeoRgYbFg7sCVqR176mPqbXsj9pA'
9367
94-let stakingFeeInUSDN = 270000
68+let stakingAssets = [toBase58String(USDN), toBase58String(EURN)]
9569
96-let isActive = getBooleanValue(this, kActive)
70+let stakingUSDNNSBTAddress = Address(fromBase58String(valueOrErrorMessage(getString(oracle, keyUSDNNSBTAddress), "no usdn staking address")))
71+
72+let stakingEURNAddress = Address(fromBase58String(valueOrErrorMessage(getString(oracle, keyEURNAddress), "no usdn staking address")))
73+
74+let active = getBooleanValue(this, kActive)
9775
9876 let strAssetIdA = getStringValue(this, kAssetIdA)
9977
141119
142120 let feeScale6 = 1000000
143121
144-let comissionForInitalization = 1000000000
145-
146122 let scale3 = 1000
147123
148124 let scale8 = 100000000
149125
150-let scale12 = 1000000000000
126+let scale16 = 10000000000000000
151127
152128 let slippageScale3 = 1000
153129
165141
166142 let alphaDigits = 2
167143
168-let beta = 46000000
144+let beta = 4600000000000000
169145
170146 func accountBalance (assetId) = match assetId {
171147 case id: ByteVector =>
177153 }
178154
179155
180-let stakedAmountUSDN = match getInteger(stakingAddress, ((("rpd_balance_" + toBase58String(USDN)) + "_") + toString(this))) {
181- case staked: Int =>
182- staked
183- case nothing: Unit =>
184- 0
185- case _ =>
186- throw("Match error")
187-}
188-
189-func isAllowedAsset (assetId) = match assetId {
190- case id: ByteVector =>
191- if ((id == USDN))
192- then true
193- else false
194- case waves: Unit =>
195- false
196- case _ =>
197- throw("Match error")
198-}
156+func stakedAmount (assetId) = {
157+ let stakedAmountCalculated = match assetId {
158+ case aId: ByteVector =>
159+ if ((aId == USDN))
160+ then getInteger(stakingUSDNNSBTAddress, ((("rpd_balance_" + toBase58String(aId)) + "_") + toString(this)))
161+ else if ((aId == EURN))
162+ then getInteger(stakingEURNAddress, ((("%s%s%s__stakingBalance__" + toBase58String(aId)) + "__") + toString(this)))
163+ else 0
164+ case _: Unit =>
165+ 0
166+ case _ =>
167+ throw("Match error")
168+ }
169+ match stakedAmountCalculated {
170+ case i: Int =>
171+ i
172+ case _ =>
173+ 0
174+ }
175+ }
199176
200177
201-let availableBalanceA = (balanceA - (if ((assetIdA == USDN))
202- then stakedAmountUSDN
203- else 0))
178+let stakedAmountA = stakedAmount(assetIdA)
204179
205-let availableBalanceB = (balanceB - (if ((assetIdB == USDN))
206- then stakedAmountUSDN
207- else 0))
180+let stakedAmountB = stakedAmount(assetIdB)
208181
209-let accountBalanceWithStakedA = (accountBalance(assetIdA) + (if ((assetIdA == USDN))
210- then stakedAmountUSDN
211- else 0))
182+let availableBalanceA = (balanceA - stakedAmountA)
212183
213-let accountBalanceWithStakedB = (accountBalance(assetIdB) + (if ((assetIdB == USDN))
214- then stakedAmountUSDN
215- else 0))
184+let availableBalanceB = (balanceB - stakedAmountB)
185+
186+let accountBalanceWithStakedA = (accountBalance(assetIdA) + stakedAmountA)
187+
188+let accountBalanceWithStakedB = (accountBalance(assetIdB) + stakedAmountB)
216189
217190 let hasEnoughBalance = if ((accountBalanceWithStakedA >= balanceA))
218191 then (accountBalanceWithStakedB >= balanceB)
219192 else false
220193
221-func skewness (x,y) = (((fraction(scale12, x, y) + fraction(scale12, y, x)) / 2) / 10000)
194+func skewness (x,y) = ((fraction(scale16, x, y) + fraction(scale16, y, x)) / 2)
222195
223196
224197 func invariantCalc (x,y) = {
225198 let sk = skewness(x, y)
226- (fraction((x + y), scale8, pow(sk, digits8, alpha, alphaDigits, digits8, CEILING)) + (2 * fraction(pow(fraction(x, y, scale8), 0, 5, 1, (digits8 / 2), DOWN), pow((sk - beta), digits8, alpha, alphaDigits, digits8, DOWN), scale8)))
199+ (fraction((x + y), scale16, pow(sk, digits8, alpha, alphaDigits, digits8, CEILING)) + (2 * fraction(toInt(pow(fraction(toBigInt(x), toBigInt(y), toBigInt(scale8)), 0, toBigInt(5), 1, (digits8 / 2), DOWN)), pow((sk - beta), digits8, alpha, alphaDigits, digits8, DOWN), scale8)))
227200 }
228201
229202
230203 func calculateSendAmount (amountToSendEstimated,minTokenReceiveAmount,tokenReceiveAmount,tokenId) = {
231- let slippageValue = (scale8 - ((scale8 * 1) / 10000000))
204+ let worstAllowedNewInvariantRatio = (scale8 - ((scale8 * 1) / 10000000))
232205 let deltaBetweenMaxAndMinSendValue = (amountToSendEstimated - minTokenReceiveAmount)
233206 let x = (balanceA + tokenReceiveAmount)
234207 let y = (balanceB + tokenReceiveAmount)
235- let invariantNew = if ((tokenId == assetIdA))
236- then invariantCalc(x, (balanceB - amountToSendEstimated))
237- else if ((tokenId == assetIdB))
238- then invariantCalc((balanceA - amountToSendEstimated), y)
239- else throw("Wrong asset in payment")
240- let invariantEstimatedRatio = fraction(scale8, invariant, invariantNew)
241- func getStepAmount (acc,step) = if ((acc == -1))
208+ func getStepAmount (acc,step) = if ((acc._1 == -1))
242209 then {
243- let amountToSend = (amountToSendEstimated - ((step * deltaBetweenMaxAndMinSendValue) / 5))
210+ let amountToSend = (amountToSendEstimated - (((step * deltaBetweenMaxAndMinSendValue) / 3) / scale3))
244211 let stepInvariant = if ((tokenId == assetIdA))
245212 then invariantCalc(x, (balanceB - amountToSend))
246213 else invariantCalc((balanceA - amountToSend), y)
247214 if ((stepInvariant > invariant))
248- then amountToSend
249- else -1
215+ then $Tuple2(amountToSend, stepInvariant)
216+ else $Tuple2(-1, 0)
250217 }
251218 else acc
252219
253- let stepAmount = {
254- let $list71887231 = [1, 2, 3, 4, 5]
255- let $size71887231 = size($list71887231)
256- let $acc071887231 = -1
257- if (($size71887231 == 0))
258- then $acc071887231
259- else {
260- let $acc171887231 = getStepAmount($acc071887231, $list71887231[0])
261- if (($size71887231 == 1))
262- then $acc171887231
220+ let amountToSendMin = getStepAmount($Tuple2(-1, 0), 3000)
221+ if ((0 > amountToSendMin._1))
222+ then throw("Price is worse than minReceived")
223+ else {
224+ let invEstimated = if ((tokenId == assetIdA))
225+ then invariantCalc(x, (balanceB - amountToSendEstimated))
226+ else if ((tokenId == assetIdB))
227+ then invariantCalc((balanceA - amountToSendEstimated), y)
228+ else throw("Wrong asset in payment")
229+ let amountToSendBest = if ((invariant > invEstimated))
230+ then if ((worstAllowedNewInvariantRatio >= fraction(scale8, invariant, invEstimated)))
231+ then throw("Bad estimation provided 1")
263232 else {
264- let $acc271887231 = getStepAmount($acc171887231, $list71887231[1])
265- if (($size71887231 == 2))
266- then $acc271887231
267- else {
268- let $acc371887231 = getStepAmount($acc271887231, $list71887231[2])
269- if (($size71887231 == 3))
270- then $acc371887231
271- else {
272- let $acc471887231 = getStepAmount($acc371887231, $list71887231[3])
273- if (($size71887231 == 4))
274- then $acc471887231
275- else {
276- let $acc571887231 = getStepAmount($acc471887231, $list71887231[4])
277- if (($size71887231 == 5))
278- then $acc571887231
279- else {
280- let $acc671887231 = getStepAmount($acc571887231, $list71887231[5])
281- throw("List size exceed 5")
282- }
283- }
284- }
285- }
233+ let a = {
234+ let $l = [25, 200, 500]
235+ let $s = size($l)
236+ let $acc0 = $Tuple2(-1, 0)
237+ func $f0_1 ($a,$i) = if (($i >= $s))
238+ then $a
239+ else getStepAmount($a, $l[$i])
240+
241+ func $f0_2 ($a,$i) = if (($i >= $s))
242+ then $a
243+ else throw("List size exceeds 3")
244+
245+ $f0_2($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3)
246+ }
247+ if ((0 > a._1))
248+ then amountToSendMin
249+ else a
286250 }
287- }
288- }
289- if ((0 > stepAmount))
290- then throw("something went wrong while working with amountToSend")
291- else if (if ((invariantEstimatedRatio > slippageValue))
292- then (invariantNew > invariant)
293- else false)
294- then amountToSendEstimated
295- else stepAmount
251+ else {
252+ let a = {
253+ let $l = [-500, -200, -25]
254+ let $s = size($l)
255+ let $acc0 = $Tuple2(-1, 0)
256+ func $f0_1 ($a,$i) = if (($i >= $s))
257+ then $a
258+ else getStepAmount($a, $l[$i])
259+
260+ func $f0_2 ($a,$i) = if (($i >= $s))
261+ then $a
262+ else throw("List size exceeds 3")
263+
264+ $f0_2($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3)
265+ }
266+ let tupleSendBetter = if ((0 > a._1))
267+ then $Tuple2(amountToSendEstimated, invEstimated)
268+ else a
269+ if ((worstAllowedNewInvariantRatio >= fraction(scale8, invariant, tupleSendBetter._2)))
270+ then throw("Bad estimation provided 2")
271+ else tupleSendBetter
272+ }
273+ amountToSendBest
274+ }
296275 }
297276
298277
311290 func suspend (cause) = [BooleanEntry(kActive, false), StringEntry(kCause, cause)]
312291
313292
314-func deductStakingFee (amount,assetId) = if ((assetId == USDN))
315- then {
316- let result = (amount - stakingFeeInUSDN)
317- if ((0 >= result))
318- then throw((((("Insufficient amount " + toString(amount)) + " to deduct staking fee ") + toString(stakingFeeInUSDN)) + " USD-N"))
319- else result
320- }
321- else amount
322-
323-
324293 func throwIsActive () = throw("DApp is already active")
325294
326295
327-func throwIsInactive () = throw("DApp is inactive at this moment")
296+func isActive () = if (active)
297+ then unit
298+ else throw("DApp is inactive at this moment")
328299
329300
330-func throwOnlyAdmin () = throw("Only admin can call this function")
301+func isAdminCall (i) = if (containsElement([adminPubKey1, adminPubKey2, adminPubKey3], i.callerPublicKey))
302+ then unit
303+ else throw("Only admin can call this function")
331304
332305
333306 func throwAssets () = throw(((("Incorrect assets attached. Expected: " + strAssetIdA) + " and ") + strAssetIdB))
334307
335308
336-func throwThreshold (threshold,amountA,amountB) = throw(((((((((("New balance in assets of the DApp is less than threshold " + toString(threshold)) + ": ") + toString(amountA)) + " ") + assetNameA) + ", ") + toString(amountB)) + " ") + assetNameB))
309+func throwOnePayment () = throw("One attached payment expected")
337310
338311
339-func throwInsufficientAvailableBalance (amount,available,assetName) = throw((((((((("Insufficient DApp balance to pay " + toString(amount)) + " ") + assetName) + " due to staking. Available: ") + toString(available)) + " ") + assetName) + ". Please contact support in Telegram: https://t.me/swopfisupport"))
340-
341-
342-func throwInsufficientAvailableBalances (amountA,amountB) = throw((((((((((((((((("Insufficient DApp balance to pay " + toString(amountA)) + " ") + assetNameA) + " and ") + toString(amountB)) + " ") + assetNameB) + " due to staking. Available: ") + toString(availableBalanceA)) + " ") + assetNameA) + " and ") + toString(availableBalanceB)) + " ") + assetNameB) + ". Please contact support in Telegram: https://t.me/swopfisupport"))
312+func throwThreshold (threshold,amountA,amountB) = throw(((((((((("New balance in assets of the DApp is less than threshold " + toString(threshold)) + ": ") + toString(amountA)) + " ") + assetNameA) + ", ") + toString(amountB)) + " ") + assetNameB))
343313
344314
345315 func suspendSuspicious () = suspend(((((((((((((((("Suspicious state. Actual balances: " + toString(balanceA)) + " ") + assetNameA) + ", ") + toString(balanceB)) + " ") + assetNameB) + ". State: ") + toString(accountBalance(assetIdA))) + " ") + assetNameA) + ", ") + toString(accountBalance(assetIdB))) + " ") + assetNameB))
346316
347317
318+func calcStakingFuncAndAddres (stake,assetId) = if (stake)
319+ then if ((assetId == USDN))
320+ then $Tuple2("lockNeutrino", stakingUSDNNSBTAddress)
321+ else $Tuple2("startStaking", stakingEURNAddress)
322+ else if ((assetId == USDN))
323+ then $Tuple2("unlockNeutrino", stakingUSDNNSBTAddress)
324+ else $Tuple2("stopStaking", stakingEURNAddress)
325+
326+
327+func calcStakingParams (stake,amount,assetId) = if (stake)
328+ then {
329+ let $t097119777 = calcStakingFuncAndAddres(stake, assetId)
330+ let call = $t097119777._1
331+ let stakingAddr = $t097119777._2
332+ $Tuple4(call, stakingAddr, nil, [AttachedPayment(assetId, amount)])
333+ }
334+ else {
335+ let $t098639929 = calcStakingFuncAndAddres(stake, assetId)
336+ let call = $t098639929._1
337+ let stakingAddr = $t098639929._2
338+ $Tuple4(call, stakingAddr, [amount, toBase58String(assetId)], nil)
339+ }
340+
341+
348342 @Callable(i)
349-func init (userAddressStr) = {
350- let $t0992910006 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
351- let pmtAmount1 = $t0992910006._1
352- let pmtAssetId1 = $t0992910006._2
353- let $t01001110088 = $Tuple2(i.payments[1].amount, i.payments[1].assetId)
354- let pmtAmount2 = $t01001110088._1
355- let pmtAssetId2 = $t01001110088._2
356- let $t01009310176 = $Tuple2(i.payments[2].amount, i.payments[2].assetId)
357- let pmtAmountSWOP = $t01009310176._1
358- let pmtAssetIdSWOP = $t01009310176._2
359- let check = isDataStorageUntouched(this)
360- let userScriptHash = scriptHash(this)
361- let userAddress = addressFromStringValue(userAddressStr)
362- if ((i.caller == this))
363- then throw("You can't call yourself")
364- else if (if ((pmtAssetIdSWOP != SWOP))
365- then true
366- else (pmtAmountSWOP != comissionForInitalization))
367- then throw("You need to attach 10 SWOP tokens")
368- else if (if (!(isAllowedAsset(pmtAssetId1)))
369- then !(isAllowedAsset(pmtAssetId2))
370- else false)
371- then throw("One of assets must be USDN, WAVES or SWOP")
372- else if (if ((userScriptHash != value(getBinary(oracle, kOracleScriptHash))))
373- then true
374- else !(check))
375- then throw("Unexpected script was found.")
376- else if (isDefined(getBoolean(this, kActive)))
377- then throwIsActive()
378- else if ((pmtAssetId1 == pmtAssetId2))
379- then throw("Assets must be different")
380- else {
381- let pmtStrAssetId1 = match pmtAssetId1 {
382- case id: ByteVector =>
383- toBase58String(id)
384- case waves: Unit =>
385- "WAVES"
386- case _ =>
387- throw("Match error")
388- }
389- let pmtStrAssetId2 = match pmtAssetId2 {
390- case id: ByteVector =>
391- toBase58String(id)
392- case waves: Unit =>
393- "WAVES"
394- case _ =>
395- throw("Match error")
396- }
397- let asset1Priority = valueOrElse(getInteger(oracle, (kOracleAssetPriority + pmtStrAssetId1)), 999999)
398- let asset2Priority = valueOrElse(getInteger(oracle, (kOracleAssetPriority + pmtStrAssetId2)), 999999)
399- let $t01151111738 = if ((asset2Priority > asset1Priority))
400- then $Tuple4(pmtAmount2, pmtAssetId2, pmtAmount1, pmtAssetId1)
401- else $Tuple4(pmtAmount1, pmtAssetId1, pmtAmount2, pmtAssetId2)
402- let pmtAmountA = $t01151111738._1
403- let pmtAssetIdA = $t01151111738._2
404- let pmtAmountB = $t01151111738._3
405- let pmtAssetIdB = $t01151111738._4
406- let $t01174711824 = getAssetInfo(pmtAssetIdA)
407- let pmtStrAssetIdA = $t01174711824._1
408- let pmtAssetNameA = $t01174711824._2
409- let pmtDecimalsA = $t01174711824._3
410- let $t01183311910 = getAssetInfo(pmtAssetIdB)
411- let pmtStrAssetIdB = $t01183311910._1
412- let pmtAssetNameB = $t01183311910._2
413- let pmtDecimalsB = $t01183311910._3
414- let shareName = ((("s" + take(pmtAssetNameA, 7)) + "_") + take(pmtAssetNameB, 7))
415- let shareDescription = ((((("ShareToken of SwopFi protocol for " + pmtAssetNameA) + " and ") + pmtAssetNameB) + " at address ") + toString(this))
416- let shareDecimals = ((pmtDecimalsA + pmtDecimalsB) / 2)
417- let shareInitialSupply = fraction(pow(pmtAmountA, pmtDecimalsA, 5, 1, pmtDecimalsA, DOWN), pow(pmtAmountB, pmtDecimalsB, 5, 1, pmtDecimalsB, DOWN), pow(10, 0, shareDecimals, 0, 0, DOWN))
418- let shareIssue = Issue(shareName, shareDescription, shareInitialSupply, shareDecimals, true)
419- let shareIssueId = calculateAssetId(shareIssue)
420- let invariantCalculated = invariantCalc(pmtAmountA, pmtAmountB)
421-[StringEntry(kVersion, version), BooleanEntry(kActive, true), StringEntry(kAssetIdA, pmtStrAssetIdA), StringEntry(kAssetIdB, pmtStrAssetIdB), IntegerEntry(kBalanceA, pmtAmountA), IntegerEntry(kBalanceB, pmtAmountB), IntegerEntry(kInvariant, invariantCalculated), IntegerEntry(kFee, fee), IntegerEntry(kFeeScaleDelimiter, feeScale6), IntegerEntry(kInitPoolHeight, height), shareIssue, StringEntry(kShareAssetId, toBase58String(shareIssueId)), IntegerEntry(kShareAssetSupply, shareInitialSupply), ScriptTransfer(userAddress, shareInitialSupply, shareIssueId), ScriptTransfer(walletAddress, comissionForInitalization, SWOP)]
422- }
343+func init () = {
344+ let $t01003410111 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
345+ let pmtAmountA = $t01003410111._1
346+ let pmtAssetIdA = $t01003410111._2
347+ let $t01011610193 = $Tuple2(i.payments[1].amount, i.payments[1].assetId)
348+ let pmtAmountB = $t01011610193._1
349+ let pmtAssetIdB = $t01011610193._2
350+ let $t01019810275 = getAssetInfo(pmtAssetIdA)
351+ let pmtStrAssetIdA = $t01019810275._1
352+ let pmtAssetNameA = $t01019810275._2
353+ let pmtDecimalsA = $t01019810275._3
354+ let $t01028010357 = getAssetInfo(pmtAssetIdB)
355+ let pmtStrAssetIdB = $t01028010357._1
356+ let pmtAssetNameB = $t01028010357._2
357+ let pmtDecimalsB = $t01028010357._3
358+ if (isDefined(getBoolean(this, kActive)))
359+ then throwIsActive()
360+ else if ((pmtAssetIdA == pmtAssetIdB))
361+ then throw("Assets must be different")
362+ else {
363+ let shareName = ((("s" + take(pmtAssetNameA, 7)) + "_") + take(pmtAssetNameB, 7))
364+ let shareDescription = ((((("ShareToken of SwopFi protocol for " + pmtAssetNameA) + " and ") + pmtAssetNameB) + " at address ") + toString(this))
365+ let shareDecimals = ((pmtDecimalsA + pmtDecimalsB) / 2)
366+ let shareInitialSupply = fraction(pow(pmtAmountA, pmtDecimalsA, 5, 1, pmtDecimalsA, DOWN), pow(pmtAmountB, pmtDecimalsB, 5, 1, pmtDecimalsB, DOWN), pow(10, 0, shareDecimals, 0, 0, DOWN))
367+ let shareIssue = Issue(shareName, shareDescription, shareInitialSupply, shareDecimals, true)
368+ let shareIssueId = calculateAssetId(shareIssue)
369+ let invariantCalculated = invariantCalc(pmtAmountA, pmtAmountB)
370+ let stake1 = if (containsElement(stakingAssets, pmtStrAssetIdA))
371+ then invoke(this, "stakeUnstake", [true, pmtAmountA, pmtStrAssetIdA], nil)
372+ else 0
373+ if ((stake1 == stake1))
374+ then {
375+ let stake2 = if (containsElement(stakingAssets, pmtStrAssetIdB))
376+ then invoke(this, "stakeUnstake", [true, pmtAmountB, pmtStrAssetIdB], nil)
377+ else 0
378+ if ((stake2 == stake2))
379+ then [StringEntry(kVersion, version), BooleanEntry(kActive, true), StringEntry(kAssetIdA, pmtStrAssetIdA), StringEntry(kAssetIdB, pmtStrAssetIdB), IntegerEntry(kBalanceA, pmtAmountA), IntegerEntry(kBalanceB, pmtAmountB), IntegerEntry(kInvariant, invariantCalculated), IntegerEntry(kFee, fee), IntegerEntry(kFeeScaleDelimiter, feeScale6), shareIssue, StringEntry(kShareAssetId, toBase58String(shareIssueId)), IntegerEntry(kShareAssetSupply, shareInitialSupply), ScriptTransfer(i.caller, shareInitialSupply, shareIssueId)]
380+ else throw("Strict value is not equal to itself.")
381+ }
382+ else throw("Strict value is not equal to itself.")
383+ }
423384 }
424385
425386
426387
427388 @Callable(i)
428-func keepLimitForFirstHarvest (shareLimit) = if (!(isActive))
429- then throw("DApp is inactive at this moment")
430- else if (!(containsElement([adminPubKey1, adminPubKey2, adminPubKey3, admStaking], i.callerPublicKey)))
431- then throw("Only admin can call this function")
432- else [IntegerEntry(kShareLimit, shareLimit)]
389+func replenishWithTwoTokens () = valueOrElse(isActive(), {
390+ let pmtAssetIdA = i.payments[0].assetId
391+ let pmtAssetIdB = i.payments[1].assetId
392+ let ratioShareTokensInA = fraction(scale8, i.payments[0].amount, balanceA)
393+ let ratioShareTokensInB = fraction(scale8, i.payments[1].amount, balanceB)
394+ let $t01293813015 = getAssetInfo(pmtAssetIdA)
395+ let pmtStrAssetIdA = $t01293813015._1
396+ let pmtAssetNameA = $t01293813015._2
397+ let pmtDecimalsA = $t01293813015._3
398+ let $t01302013137 = getAssetInfo(pmtAssetIdB)
399+ let pmtStrAssetIdB = $t01302013137._1
400+ let pmtAssetNameB = $t01302013137._2
401+ let pmtDecimalsB = $t01302013137._3
402+ let $t01314213646 = if ((ratioShareTokensInB > ratioShareTokensInA))
403+ then {
404+ let pmt = fraction(balanceB, ratioShareTokensInA, scale8, CEILING)
405+ $Tuple5(i.payments[0].amount, pmt, (i.payments[1].amount - pmt), pmtAssetIdB, ratioShareTokensInA)
406+ }
407+ else {
408+ let pmt = fraction(balanceB, ratioShareTokensInA, scale8, CEILING)
409+ $Tuple5(pmt, i.payments[1].amount, (i.payments[0].amount - pmt), pmtAssetIdA, ratioShareTokensInB)
410+ }
411+ let pmtAmountA = $t01314213646._1
412+ let pmtAmountB = $t01314213646._2
413+ let change = $t01314213646._3
414+ let changeAssetId = $t01314213646._4
415+ let shareTokenRatio = $t01314213646._5
416+ let shareTokenToPayAmount = fraction(shareTokenRatio, shareAssetSupply, scale8)
417+ if ((size(i.payments) != 2))
418+ then throw("Two attached assets expected")
419+ else if (if ((pmtAssetIdA != assetIdA))
420+ then true
421+ else (pmtAssetIdB != assetIdB))
422+ then throwAssets()
423+ else if ((shareTokenToPayAmount == 0))
424+ then throw("Too small amount to replenish")
425+ else if ((0 > change))
426+ then throw("Change < 0")
427+ else if (!(hasEnoughBalance))
428+ then ([ScriptTransfer(i.caller, pmtAmountA, pmtAssetIdA), ScriptTransfer(i.caller, pmtAmountB, pmtAssetIdB)] ++ suspendSuspicious())
429+ else {
430+ let stake1 = if (containsElement(stakingAssets, pmtStrAssetIdA))
431+ then invoke(this, "stakeUnstake", [true, pmtAmountA, pmtStrAssetIdA], nil)
432+ else 0
433+ if ((stake1 == stake1))
434+ then {
435+ let stake2 = if (containsElement(stakingAssets, pmtStrAssetIdB))
436+ then invoke(this, "stakeUnstake", [true, pmtAmountB, pmtStrAssetIdB], nil)
437+ else 0
438+ if ((stake2 == stake2))
439+ then [IntegerEntry(kBalanceA, (balanceA + pmtAmountA)), IntegerEntry(kBalanceB, (balanceB + pmtAmountB)), IntegerEntry(kShareAssetSupply, (shareAssetSupply + shareTokenToPayAmount)), IntegerEntry(kInvariant, invariantCalc((balanceA + pmtAmountA), (balanceB + pmtAmountB))), Reissue(shareAssetId, shareTokenToPayAmount, true), ScriptTransfer(i.caller, shareTokenToPayAmount, shareAssetId), ScriptTransfer(i.caller, change, changeAssetId)]
440+ else throw("Strict value is not equal to itself.")
441+ }
442+ else throw("Strict value is not equal to itself.")
443+ }
444+ })
433445
434446
435447
436448 @Callable(i)
437-func replenishWithTwoTokens (slippageTolerance) = {
438- let pmtAssetIdA = i.payments[0].assetId
439- let pmtAssetIdB = i.payments[1].assetId
440- let pmtAmountA = deductStakingFee(i.payments[0].amount, pmtAssetIdA)
441- let pmtAmountB = deductStakingFee(i.payments[1].amount, pmtAssetIdB)
442- let tokenRatio = fraction(fraction(scale8, balanceA, pmtAmountA), scale3, fraction(scale8, balanceB, pmtAmountB))
443- let ratioShareTokensInA = fraction(scale8, pmtAmountA, balanceA)
444- let ratioShareTokensInB = fraction(scale8, pmtAmountB, balanceB)
445- let shareTokenToPayAmount = fraction(min([ratioShareTokensInA, ratioShareTokensInB]), shareAssetSupply, scale8)
446- let invariantCalculated = invariantCalc((balanceA + pmtAmountA), (balanceB + pmtAmountB))
447- if (!(isActive))
448- then throwIsInactive()
449- else if (if ((0 > slippageTolerance))
450- then true
451- else (slippageTolerance > 10))
452- then throw("Slippage tolerance must be <= 1%")
453- else if ((size(i.payments) != 2))
454- then throw("Two attached assets expected")
455- else if (if ((pmtAssetIdA != assetIdA))
456- then true
457- else (pmtAssetIdB != assetIdB))
458- then throwAssets()
459- else if (if ((((scale3 * (slippageScale3 - slippageTolerance)) / slippageScale3) > tokenRatio))
460- then true
461- else (tokenRatio > ((scale3 * (slippageScale3 + slippageTolerance)) / slippageScale3)))
462- then throw("Incorrect assets amount: amounts must have the contract ratio")
463- else if ((shareTokenToPayAmount == 0))
464- then throw("Too small amount to replenish")
465- else if (!(hasEnoughBalance))
466- then ([ScriptTransfer(i.caller, pmtAmountA, pmtAssetIdA), ScriptTransfer(i.caller, pmtAmountB, pmtAssetIdB)] ++ suspendSuspicious())
467- else [IntegerEntry(kBalanceA, (balanceA + pmtAmountA)), IntegerEntry(kBalanceB, (balanceB + pmtAmountB)), IntegerEntry(kShareAssetSupply, (shareAssetSupply + shareTokenToPayAmount)), IntegerEntry(kInvariant, invariantCalculated), Reissue(shareAssetId, shareTokenToPayAmount, true), ScriptTransfer(i.caller, shareTokenToPayAmount, shareAssetId)]
468- }
469-
470-
471-
472-@Callable(i)
473-func replenishWithOneToken (virtualSwapTokenPay,virtualSwapTokenGet) = {
474- let $t01658816663 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
475- let pmtAmount = $t01658816663._1
476- let pmtAssetId = $t01658816663._2
449+func replenishWithOneToken (virtualSwapTokenPay,virtualSwapTokenGet) = valueOrElse(isActive(), {
450+ let $t01529515370 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
451+ let pmtAmount = $t01529515370._1
452+ let pmtAssetId = $t01529515370._2
453+ let $t01537515448 = getAssetInfo(pmtAssetId)
454+ let pmtStrAssetId = $t01537515448._1
455+ let pmtAssetName = $t01537515448._2
456+ let pmtDecimals = $t01537515448._3
477457 let pmtMinThreshold = 5000000
478458 let thresholdValueForMinTolerance = 50000000
479459 let tolerance = if ((thresholdValueForMinTolerance > pmtAmount))
482462 let slippageValueMinForReplenish = (scale8 - ((scale8 * tolerance) / 10000000))
483463 let slippageValueMaxForReplenish = (scale8 + ((scale8 * tolerance) / 10000000))
484464 let slippageValueMinForSwap = (scale8 - ((scale8 * 1) / 10000000))
485- if (!(isActive))
486- then throwIsInactive()
487- else if ((pmtMinThreshold > pmtAmount))
488- then throw((((("Payment amount " + toString(pmtAmount)) + " does not exceed the minimum amount of ") + toString(pmtMinThreshold)) + " tokens"))
465+ if ((pmtMinThreshold > pmtAmount))
466+ then throw((((("Payment amount " + toString(pmtAmount)) + " does not exceed the minimum amount of ") + toString(pmtMinThreshold)) + " tokens"))
467+ else if ((size(i.payments) != 1))
468+ then throwOnePayment()
469+ else if (!(hasEnoughBalance))
470+ then ([ScriptTransfer(i.caller, pmtAmount, pmtAssetId)] ++ suspendSuspicious())
471+ else if (if ((pmtAssetId != assetIdA))
472+ then (pmtAssetId != assetIdB)
473+ else false)
474+ then throwAssets()
475+ else {
476+ let $t01638617151 = if ((pmtAssetId == assetIdA))
477+ then $Tuple7((pmtAmount - virtualSwapTokenPay), virtualSwapTokenGet, (balanceA + virtualSwapTokenPay), (balanceB - virtualSwapTokenGet), invariantCalc((balanceA + pmtAmount), balanceB), (balanceA + pmtAmount), balanceB)
478+ else $Tuple7(virtualSwapTokenGet, (pmtAmount - virtualSwapTokenPay), (balanceA - virtualSwapTokenGet), (balanceB + virtualSwapTokenPay), invariantCalc(balanceA, (balanceB + pmtAmount)), balanceA, (balanceB + pmtAmount))
479+ let virtualReplenishA = $t01638617151._1
480+ let virtualReplenishB = $t01638617151._2
481+ let balanceAfterSwapA = $t01638617151._3
482+ let balanceAfterSwapB = $t01638617151._4
483+ let invariantCalculated = $t01638617151._5
484+ let newBalanceA = $t01638617151._6
485+ let newBalanceB = $t01638617151._7
486+ let newBalanceEntry = if ((pmtAssetId == assetIdA))
487+ then IntegerEntry(kBalanceA, newBalanceA)
488+ else IntegerEntry(kBalanceB, newBalanceB)
489+ let invariantNew = invariantCalc(balanceAfterSwapA, balanceAfterSwapB)
490+ let invariantEstimatedRatio = fraction(scale8, invariant, invariantNew)
491+ let ratioVirtualBalanceToVirtualReplenish = (fraction((scale8 * scale8), balanceAfterSwapA, balanceAfterSwapB) / fraction(scale8, virtualReplenishA, virtualReplenishB))
492+ let dAppThresholdAmount = fraction((newBalanceA + newBalanceB), dAppThreshold, (2 * dAppThresholdScale2))
493+ if (if ((slippageValueMinForSwap >= invariantEstimatedRatio))
494+ then true
495+ else (invariant > invariantNew))
496+ then throw("Incorrect virtualSwapTokenPay or virtualSwapTokenGet value")
497+ else if (if ((slippageValueMinForReplenish > ratioVirtualBalanceToVirtualReplenish))
498+ then true
499+ else (ratioVirtualBalanceToVirtualReplenish > slippageValueMaxForReplenish))
500+ then throw("Swap with virtualSwapTokenPay and virtualSwapTokenGet is possible, but ratio after virtual swap is incorrect")
501+ else if (if ((dAppThresholdAmount > newBalanceA))
502+ then true
503+ else (dAppThresholdAmount > newBalanceB))
504+ then throwThreshold(dAppThresholdAmount, newBalanceA, newBalanceB)
505+ else {
506+ let stake1 = if (containsElement(stakingAssets, pmtStrAssetId))
507+ then invoke(this, "stakeUnstake", [true, pmtAmount, pmtStrAssetId], nil)
508+ else 0
509+ if ((stake1 == stake1))
510+ then {
511+ let ratioShareTokensInA = fraction(virtualReplenishA, scale8, balanceAfterSwapA)
512+ let ratioShareTokensInB = fraction(virtualReplenishB, scale8, balanceAfterSwapB)
513+ let shareTokenToPayAmount = fraction(min([ratioShareTokensInA, ratioShareTokensInB]), shareAssetSupply, scale8)
514+[Reissue(shareAssetId, shareTokenToPayAmount, true), ScriptTransfer(i.caller, shareTokenToPayAmount, shareAssetId), IntegerEntry(kShareAssetSupply, (shareAssetSupply + shareTokenToPayAmount)), newBalanceEntry, IntegerEntry(kInvariant, invariantCalculated)]
515+ }
516+ else throw("Strict value is not equal to itself.")
517+ }
518+ }
519+ })
520+
521+
522+
523+@Callable(i)
524+func withdraw () = valueOrElse(isActive(), {
525+ let $t01940119544 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
526+ let pmtAmount = $t01940119544._1
527+ let pmtAssetId = $t01940119544._2
528+ let amountToPayA = fraction(pmtAmount, balanceA, shareAssetSupply)
529+ let amountToPayB = fraction(pmtAmount, balanceB, shareAssetSupply)
530+ let invariantCalculated = invariantCalc((balanceA - amountToPayA), (balanceB - amountToPayB))
531+ if ((size(i.payments) != 1))
532+ then throwOnePayment()
533+ else if ((pmtAssetId != shareAssetId))
534+ then throw(("Incorrect asset attached. Expected: " + toBase58String(shareAssetId)))
535+ else if (!(hasEnoughBalance))
536+ then ([ScriptTransfer(i.caller, pmtAmount, pmtAssetId)] ++ suspendSuspicious())
537+ else {
538+ let stake1 = if (containsElement(stakingAssets, strAssetIdA))
539+ then invoke(this, "stakeUnstake", [false, amountToPayA, strAssetIdA], nil)
540+ else 0
541+ if ((stake1 == stake1))
542+ then {
543+ let stake2 = if (containsElement(stakingAssets, strAssetIdB))
544+ then invoke(this, "stakeUnstake", [false, amountToPayB, strAssetIdB], nil)
545+ else 0
546+ if ((stake2 == stake2))
547+ then [IntegerEntry(kBalanceA, (balanceA - amountToPayA)), IntegerEntry(kBalanceB, (balanceB - amountToPayB)), IntegerEntry(kShareAssetSupply, (shareAssetSupply - pmtAmount)), IntegerEntry(kInvariant, invariantCalculated), Burn(shareAssetId, pmtAmount), ScriptTransfer(i.caller, amountToPayA, assetIdA), ScriptTransfer(i.caller, amountToPayB, assetIdB)]
548+ else throw("Strict value is not equal to itself.")
549+ }
550+ else throw("Strict value is not equal to itself.")
551+ }
552+ })
553+
554+
555+
556+@Callable(i)
557+func exchange (estimatedAmountToReceive,minAmountToReceive) = valueOrElse(isActive(), {
558+ let $t02100721082 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
559+ let pmtAmount = $t02100721082._1
560+ let pmtAssetId = $t02100721082._2
561+ if ((0 >= estimatedAmountToReceive))
562+ then throw(("Estimated amount must be positive. Actual: " + toString(estimatedAmountToReceive)))
563+ else if ((minAmountToReceive > estimatedAmountToReceive))
564+ then throw(((("Minimal amount can't be greater than estimated. Estimated: " + toString(estimatedAmountToReceive)) + ". Minimal: ") + toString(minAmountToReceive)))
489565 else if ((size(i.payments) != 1))
490- then throw("One attached payment expected")
566+ then throwOnePayment()
491567 else if (!(hasEnoughBalance))
492568 then ([ScriptTransfer(i.caller, pmtAmount, pmtAssetId)] ++ suspendSuspicious())
493569 else if (if ((pmtAssetId != assetIdA))
494570 then (pmtAssetId != assetIdB)
495571 else false)
496572 then throwAssets()
497- else {
498- let $t01767518440 = if ((pmtAssetId == assetIdA))
499- then $Tuple7((pmtAmount - virtualSwapTokenPay), virtualSwapTokenGet, (balanceA + virtualSwapTokenPay), (balanceB - virtualSwapTokenGet), invariantCalc((balanceA + pmtAmount), balanceB), (balanceA + pmtAmount), balanceB)
500- else $Tuple7(virtualSwapTokenGet, (pmtAmount - virtualSwapTokenPay), (balanceA - virtualSwapTokenGet), (balanceB + virtualSwapTokenPay), invariantCalc(balanceA, (balanceB + pmtAmount)), balanceA, (balanceB + pmtAmount))
501- let virtualReplenishA = $t01767518440._1
502- let virtualReplenishB = $t01767518440._2
503- let balanceAfterSwapA = $t01767518440._3
504- let balanceAfterSwapB = $t01767518440._4
505- let invariantCalculated = $t01767518440._5
506- let newBalanceA = $t01767518440._6
507- let newBalanceB = $t01767518440._7
508- let newBalanceEntry = if ((pmtAssetId == assetIdA))
509- then IntegerEntry(kBalanceA, newBalanceA)
510- else IntegerEntry(kBalanceB, newBalanceB)
511- let invariantNew = invariantCalc(balanceAfterSwapA, balanceAfterSwapB)
512- let invariantEstimatedRatio = fraction(scale8, invariant, invariantNew)
513- let ratioVirtualBalanceToVirtualReplenish = (fraction((scale8 * scale8), balanceAfterSwapA, balanceAfterSwapB) / fraction(scale8, virtualReplenishA, virtualReplenishB))
514- let dAppThresholdAmount = fraction((newBalanceA + newBalanceB), dAppThreshold, (2 * dAppThresholdScale2))
515- if (if ((slippageValueMinForSwap >= invariantEstimatedRatio))
573+ else if ((10000000 > pmtAmount))
574+ then throw("Only swap of 10.000000 or more tokens is allowed")
575+ else if (if ((exchangeRatioLimitMin > fraction(scale8, minAmountToReceive, pmtAmount)))
516576 then true
517- else (invariant > invariantNew))
518- then throw("Incorrect virtualSwapTokenPay or virtualSwapTokenGet value")
519- else if (if ((slippageValueMinForReplenish > ratioVirtualBalanceToVirtualReplenish))
520- then true
521- else (ratioVirtualBalanceToVirtualReplenish > slippageValueMaxForReplenish))
522- then throw("Swap with virtualSwapTokenPay and virtualSwapTokenGet is possible, but ratio after virtual swap is incorrect")
523- else if (if ((dAppThresholdAmount > newBalanceA))
577+ else (fraction(scale8, estimatedAmountToReceive, pmtAmount) > exchangeRatioLimitMax))
578+ then throw("Incorrect args and pmt ratio")
579+ else {
580+ let sendAssetId = if ((pmtAssetId == assetIdA))
581+ then assetIdB
582+ else assetIdA
583+ let $t02217322292 = calculateSendAmount(estimatedAmountToReceive, minAmountToReceive, pmtAmount, pmtAssetId)
584+ let amount = $t02217322292._1
585+ let amountInvarian = $t02217322292._2
586+ let governanceReward = fraction(amount, feeGovernance, feeScale6)
587+ let amountMinusFee = fraction(amount, (feeScale6 - fee), feeScale6)
588+ let $t02244822710 = if ((pmtAssetId == assetIdA))
589+ then $Tuple2((balanceA + pmtAmount), ((balanceB - amountMinusFee) - governanceReward))
590+ else $Tuple2(((balanceA - amountMinusFee) - governanceReward), (balanceB + pmtAmount))
591+ let newBalanceA = $t02244822710._1
592+ let newBalanceB = $t02244822710._2
593+ let dAppThresholdAmount = fraction((newBalanceA + newBalanceB), dAppThreshold, (2 * dAppThresholdScale2))
594+ if (if ((dAppThresholdAmount > newBalanceA))
524595 then true
525596 else (dAppThresholdAmount > newBalanceB))
526597 then throwThreshold(dAppThresholdAmount, newBalanceA, newBalanceB)
527598 else {
528- let ratioShareTokensInA = fraction(deductStakingFee(virtualReplenishA, assetIdA), scale8, balanceAfterSwapA)
529- let ratioShareTokensInB = fraction(deductStakingFee(virtualReplenishB, assetIdB), scale8, balanceAfterSwapB)
530- let shareTokenToPayAmount = fraction(min([ratioShareTokensInA, ratioShareTokensInB]), shareAssetSupply, scale8)
531-[Reissue(shareAssetId, shareTokenToPayAmount, true), ScriptTransfer(i.caller, shareTokenToPayAmount, shareAssetId), IntegerEntry(kShareAssetSupply, (shareAssetSupply + shareTokenToPayAmount)), newBalanceEntry, IntegerEntry(kInvariant, invariantCalculated)]
599+ let $t02300823081 = getAssetInfo(pmtAssetId)
600+ let pmtStrAssetId = $t02300823081._1
601+ let pmtAssetName = $t02300823081._2
602+ let pmtDecimals = $t02300823081._3
603+ let $t02309423171 = getAssetInfo(sendAssetId)
604+ let sendStrAssetId = $t02309423171._1
605+ let sendAssetName = $t02309423171._2
606+ let sendDecimals = $t02309423171._3
607+ let stake1 = if (containsElement(stakingAssets, pmtStrAssetId))
608+ then invoke(this, "stakeUnstake", [true, pmtAmount, pmtStrAssetId], nil)
609+ else 0
610+ if ((stake1 == stake1))
611+ then {
612+ let stake2 = if (containsElement(stakingAssets, sendStrAssetId))
613+ then invoke(this, "stakeUnstake", [false, (amountMinusFee + governanceReward), sendStrAssetId], nil)
614+ else 0
615+ if ((stake2 == stake2))
616+ then [IntegerEntry(kBalanceA, newBalanceA), IntegerEntry(kBalanceB, newBalanceB), IntegerEntry(kInvariant, amountInvarian), ScriptTransfer(i.caller, amountMinusFee, sendAssetId), ScriptTransfer(walletAddress, governanceReward, sendAssetId)]
617+ else throw("Strict value is not equal to itself.")
618+ }
619+ else throw("Strict value is not equal to itself.")
532620 }
533- }
534- }
621+ }
622+ })
535623
536624
537625
538626 @Callable(i)
539-func withdraw () = {
540- let $t02058520728 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
541- let pmtAmount = $t02058520728._1
542- let pmtAssetId = $t02058520728._2
543- let amountToPayA = deductStakingFee(fraction(pmtAmount, balanceA, shareAssetSupply), assetIdA)
544- let amountToPayB = deductStakingFee(fraction(pmtAmount, balanceB, shareAssetSupply), assetIdB)
545- let invariantCalculated = invariantCalc((balanceA - amountToPayA), (balanceB - amountToPayB))
546- if (!(isActive))
547- then throwIsInactive()
548- else if ((size(i.payments) != 1))
549- then throw("One attached payment expected")
550- else if ((pmtAssetId != shareAssetId))
551- then throw(("Incorrect asset attached. Expected: " + toBase58String(shareAssetId)))
552- else if (!(hasEnoughBalance))
553- then ([ScriptTransfer(i.caller, pmtAmount, pmtAssetId)] ++ suspendSuspicious())
554- else if (if ((amountToPayA > availableBalanceA))
555- then true
556- else (amountToPayB > availableBalanceB))
557- then throwInsufficientAvailableBalances(amountToPayA, amountToPayB)
558- else [IntegerEntry(kBalanceA, (balanceA - amountToPayA)), IntegerEntry(kBalanceB, (balanceB - amountToPayB)), IntegerEntry(kShareAssetSupply, (shareAssetSupply - pmtAmount)), IntegerEntry(kInvariant, invariantCalculated), Burn(shareAssetId, pmtAmount), ScriptTransfer(i.caller, amountToPayA, assetIdA), ScriptTransfer(i.caller, amountToPayB, assetIdB)]
559- }
627+func shutdown () = valueOrElse(isAdminCall(i), if (!(active))
628+ then throw(("DApp is already suspended. Cause: " + valueOrElse(getString(this, kCause), "the cause wasn't specified")))
629+ else suspend("Paused by admin"))
560630
561631
562632
563633 @Callable(i)
564-func exchange (estimatedAmountToReceive,minAmountToReceive) = {
565- let $t02208622161 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
566- let pmtAmount = $t02208622161._1
567- let pmtAssetId = $t02208622161._2
568- if (!(isActive))
569- then throwIsInactive()
570- else if ((0 >= estimatedAmountToReceive))
571- then throw(("Estimated amount must be positive. Actual: " + toString(estimatedAmountToReceive)))
572- else if ((minAmountToReceive > estimatedAmountToReceive))
573- then throw(((("Minimal amount can't be greater than estimated. Estimated: " + toString(estimatedAmountToReceive)) + ". Minimal: ") + toString(minAmountToReceive)))
574- else if ((size(i.payments) != 1))
575- then throw("One attached payment expected")
576- else if (!(hasEnoughBalance))
577- then ([ScriptTransfer(i.caller, pmtAmount, pmtAssetId)] ++ suspendSuspicious())
578- else if (if ((pmtAssetId != assetIdA))
579- then (pmtAssetId != assetIdB)
580- else false)
581- then throwAssets()
582- else if ((10000000 > pmtAmount))
583- then throw("Only swap of 10.000000 or more tokens is allowed")
584- else if (if ((exchangeRatioLimitMin > fraction(scale8, minAmountToReceive, pmtAmount)))
585- then true
586- else (fraction(scale8, estimatedAmountToReceive, pmtAmount) > exchangeRatioLimitMax))
587- then throw("Incorrect args and pmt ratio")
588- else {
589- let sendAssetId = if ((pmtAssetId == assetIdA))
590- then assetIdB
591- else assetIdA
592- let amount = calculateSendAmount(estimatedAmountToReceive, minAmountToReceive, pmtAmount, pmtAssetId)
593- let governanceReward = fraction(amount, feeGovernance, feeScale6)
594- let amountMinusFee = fraction(amount, (feeScale6 - fee), feeScale6)
595- let $t02358323845 = if ((pmtAssetId == assetIdA))
596- then $Tuple2((balanceA + pmtAmount), ((balanceB - amountMinusFee) - governanceReward))
597- else $Tuple2(((balanceA - amountMinusFee) - governanceReward), (balanceB + pmtAmount))
598- let newBalanceA = $t02358323845._1
599- let newBalanceB = $t02358323845._2
600- let dAppThresholdAmount = fraction((newBalanceA + newBalanceB), dAppThreshold, (2 * dAppThresholdScale2))
601- if (if ((dAppThresholdAmount > newBalanceA))
602- then true
603- else (dAppThresholdAmount > newBalanceB))
604- then throwThreshold(dAppThresholdAmount, newBalanceA, newBalanceB)
605- else if (if (if ((assetIdA == USDN))
606- then (sendAssetId == assetIdA)
607- else false)
608- then (stakedAmountUSDN >= newBalanceA)
609- else false)
610- then throwInsufficientAvailableBalance(amountMinusFee, availableBalanceA, assetNameA)
611- else if (if (if ((assetIdB == USDN))
612- then (sendAssetId == assetIdB)
613- else false)
614- then (stakedAmountUSDN >= newBalanceB)
615- else false)
616- then throwInsufficientAvailableBalance(amountMinusFee, availableBalanceB, assetNameB)
617- else [IntegerEntry(kBalanceA, newBalanceA), IntegerEntry(kBalanceB, newBalanceB), IntegerEntry(kInvariant, invariantCalc(newBalanceA, newBalanceB)), ScriptTransfer(i.caller, amountMinusFee, sendAssetId), ScriptTransfer(walletAddress, governanceReward, sendAssetId)]
618- }
619- }
634+func activate () = valueOrElse(isAdminCall(i), if (active)
635+ then throwIsActive()
636+ else [BooleanEntry(kActive, true), DeleteEntry(kCause)])
620637
621638
622639
623640 @Callable(i)
624-func shutdown () = if (!(isActive))
625- then throw(("DApp is already suspended. Cause: " + valueOrElse(getString(this, kCause), "the cause wasn't specified")))
626- else if (!(containsElement([adminPubKey1, adminPubKey2, adminPubKey3, admStartStop], i.callerPublicKey)))
627- then throwOnlyAdmin()
628- else suspend("Paused by admin")
641+func takeIntoAccountExtraFunds () = valueOrElse(isActive(), {
642+ let amountEnrollA = (accountBalanceWithStakedA - balanceA)
643+ let amountEnrollB = (accountBalanceWithStakedB - balanceB)
644+ let invariantNew = invariantCalc((balanceA + amountEnrollA), (balanceB + amountEnrollB))
645+ if ((i.caller != walletAddress))
646+ then throw("Only the wallet can call this function")
647+ else if (if ((0 > amountEnrollA))
648+ then true
649+ else (0 > amountEnrollB))
650+ then suspend("Enroll amount negative")
651+ else if (if ((amountEnrollA == 0))
652+ then (amountEnrollB == 0)
653+ else false)
654+ then throw("No money to take")
655+ else {
656+ let stake1 = if (if (containsElement(stakingAssets, strAssetIdA))
657+ then (amountEnrollA > 0)
658+ else false)
659+ then invoke(this, "stakeUnstake", [true, amountEnrollA, strAssetIdA], nil)
660+ else 0
661+ if ((stake1 == stake1))
662+ then {
663+ let stake2 = if (if (containsElement(stakingAssets, strAssetIdB))
664+ then (amountEnrollB > 0)
665+ else false)
666+ then invoke(this, "stakeUnstake", [true, amountEnrollB, strAssetIdB], nil)
667+ else 0
668+ if ((stake2 == stake2))
669+ then [IntegerEntry(kInvariant, invariantNew), IntegerEntry(kBalanceA, (balanceA + amountEnrollA)), IntegerEntry(kBalanceB, (balanceB + amountEnrollB)), IntegerEntry(("last_income_" + strAssetIdA), amountEnrollA), IntegerEntry(("last_income_" + strAssetIdB), amountEnrollB)]
670+ else throw("Strict value is not equal to itself.")
671+ }
672+ else throw("Strict value is not equal to itself.")
673+ }
674+ })
629675
630676
631677
632678 @Callable(i)
633-func activate () = if (isActive)
634- then throwIsActive()
635- else if (!(containsElement([adminPubKey1, adminPubKey2, adminPubKey3, admStartStop], i.callerPublicKey)))
636- then throwOnlyAdmin()
637- else [BooleanEntry(kActive, true), DeleteEntry(kCause)]
638-
639-
640-
641-@Callable(i)
642-func enableFirstHarvest () = [BooleanEntry(kFirstHarvest, true), IntegerEntry(kFirstHarvestHeight, (startHeight + (firstHarvestEndPeriod * periodLength)))]
643-
644-
645-
646-@Callable(i)
647-func takeIntoAccountExtraFunds (amountLeave) = {
648- let uncountableA = (accountBalanceWithStakedA - balanceA)
649- let uncountableB = (accountBalanceWithStakedB - balanceB)
650- let amountEnrollA = (uncountableA - (if ((assetIdA == unit))
651- then amountLeave
652- else 0))
653- let amountEnrollB = (uncountableB - (if ((assetIdB == unit))
654- then amountLeave
655- else 0))
656- let invariantNew = invariantCalc((balanceA + amountEnrollA), (balanceB + amountEnrollB))
657- if (!(isActive))
658- then throwIsInactive()
659- else if ((i.caller != this))
660- then throwOnlyAdmin()
661- else if ((0 > amountLeave))
662- then throw(("Argument 'amountLeave' cannot be negative. Actual: " + toString(amountLeave)))
663- else if (if ((0 > uncountableA))
664- then true
665- else (0 > uncountableB))
666- then suspend("Enroll amount negative")
667- else if (if ((0 > amountEnrollA))
668- then true
669- else (0 > amountEnrollB))
670- then throw("Too large amountLeave")
671- else [IntegerEntry(kInvariant, invariantNew), IntegerEntry(kBalanceA, (balanceA + amountEnrollA)), IntegerEntry(kBalanceB, (balanceB + amountEnrollB)), IntegerEntry(("last_income_" + strAssetIdA), amountEnrollA), IntegerEntry(("last_income_" + strAssetIdB), amountEnrollB)]
672- }
679+func stakeUnstake (stake,amount,assetIdString) = if ((i.caller != this))
680+ then throw("Only contract itself can invoke this function")
681+ else {
682+ let $t02595826061 = calcStakingParams(stake, amount, fromBase58String(assetIdString))
683+ let call = $t02595826061._1
684+ let addr = $t02595826061._2
685+ let params = $t02595826061._3
686+ let payments = $t02595826061._4
687+ let inv = invoke(addr, call, params, payments)
688+ if ((inv == inv))
689+ then nil
690+ else throw("Strict value is not equal to itself.")
691+ }
673692
674693
675694 @Verifier(tx)
691710 let callTakeIntoAccount = if ((inv.dApp == this))
692711 then (inv.function == "takeIntoAccountExtraFunds")
693712 else false
694- let callEnableFirstHarvest = if ((inv.dApp == this))
695- then (inv.function == "enableFirstHarvest")
696- else false
697- let callStaking = if ((inv.dApp == stakingAddress))
698- then if (if (if ((inv.function == "lockNeutrino"))
699- then (size(inv.payments) == 1)
700- else false)
701- then (inv.payments[0].assetId == USDN)
702- else false)
703- then true
704- else if ((inv.function == "unlockNeutrino"))
705- then (size(inv.payments) == 0)
706- else false
707- else false
708- let exchangeToWaves = if (if (if ((inv.dApp == USDNToWavesExchanger))
709- then (inv.function == "exchange")
710- else false)
711- then (assetIdA == USDN)
712- else false)
713- then true
714- else if (if ((assetIdB == USDN))
715- then (size(inv.payments) == 1)
716- else false)
717- then (inv.payments[0].assetId == USDN)
718- else false
719713 let signedByAdmin = if (if (if (sigVerify(tx.bodyBytes, tx.proofs[0], adminPubKey1))
720714 then true
721715 else sigVerify(tx.bodyBytes, tx.proofs[0], adminPubKey2))
723717 else sigVerify(tx.bodyBytes, tx.proofs[0], adminPubKey3))
724718 then true
725719 else sigVerify(tx.bodyBytes, tx.proofs[0], admStaking)
726- if (if (if (if (if (callTakeIntoAccount)
727- then true
728- else callEnableFirstHarvest)
729- then true
730- else callStaking)
731- then true
732- else exchangeToWaves)
720+ if (if (callTakeIntoAccount)
733721 then signedByAdmin
734722 else false)
735723 then true
Full:
OldNewDifferences
11 {-# STDLIB_VERSION 5 #-}
22 {-# SCRIPT_TYPE ACCOUNT #-}
33 {-# CONTENT_TYPE DAPP #-}
44 let version = "2.0.0"
55
66 let kVersion = "version"
77
88 let kActive = "active"
99
1010 let kAssetIdA = "A_asset_id"
1111
1212 let kAssetIdB = "B_asset_id"
1313
1414 let kBalanceA = "A_asset_balance"
1515
1616 let kBalanceB = "B_asset_balance"
1717
1818 let kShareAssetId = "share_asset_id"
1919
2020 let kShareAssetSupply = "share_asset_supply"
2121
2222 let kFee = "commission"
2323
2424 let kFeeScaleDelimiter = "commission_scale_delimiter"
2525
2626 let kInvariant = "invariant"
2727
2828 let kCause = "shutdown_cause"
2929
30-let kFirstHarvest = "first_harvest"
30+let keyUSDNNSBTAddress = "staking_usdnnsbt_address"
3131
32-let kFirstHarvestHeight = "first_harvest_height"
33-
34-let kShareLimit = "share_limit_on_first_harvest"
35-
36-let kBasePeriod = "base_period"
37-
38-let kPeriodLength = "period_length"
39-
40-let kStartHeight = "start_height"
41-
42-let kOracleAssetPriority = "asset_priority_"
43-
44-let kOracleScriptHash = "script_hash_flat"
45-
46-let kInitPoolHeight = "init_pool_height_"
32+let keyEURNAddress = "staking_eurn_address"
4733
4834 let keyAdminPubKey1 = "admin_pub_1"
4935
5036 let keyAdminPubKey2 = "admin_pub_2"
5137
5238 let keyAdminPubKey3 = "admin_pub_3"
5339
5440 let USDNToWavesExchanger = Address(base58'3N77kfPbQyjXWpDALX3xjKw3iEGMWEctV37')
5541
5642 let oracle = Address(base58'3NBBWfzZtZtszaXbitTKnrB2xXwv26Bn7H9')
57-
58-let walletAddress = Address(base58'3NAGTtZz6WpupSN89NZD5rMZwwziZEg4Kx4')
59-
60-let votingAddress = Address(base58'3MrJgdL1GniipErHy44YF9idzLaUL2iX5DQ')
6143
6244 func getAdminPub (keyAdminPub) = match getString(oracle, keyAdminPub) {
6345 case string: String =>
6446 fromBase58String(string)
6547 case nothing =>
6648 throw("Admin public key is empty")
6749 }
6850
6951
7052 let adminPubKey1 = getAdminPub(keyAdminPubKey1)
7153
7254 let adminPubKey2 = getAdminPub(keyAdminPubKey2)
7355
7456 let adminPubKey3 = getAdminPub(keyAdminPubKey3)
7557
7658 let admStartStop = base58'Kn7NpzaG12dLZgcHf2ipUftU6hbJygmrhFqQYE4B7ZK'
7759
7860 let admStaking = base58'Kn7NpzaG12dLZgcHf2ipUftU6hbJygmrhFqQYE4B7ZK'
7961
80-let basePeriod = valueOrErrorMessage(getInteger(votingAddress, kBasePeriod), "Empty kBasePeriod")
81-
82-let startHeight = valueOrErrorMessage(getInteger(votingAddress, kStartHeight), "Empty kStartHeight")
83-
84-let periodLength = valueOrErrorMessage(getInteger(votingAddress, kPeriodLength), "Empty kPeriodLength")
85-
86-let firstHarvestEndPeriod = ((basePeriod + ((height - startHeight) / periodLength)) + 1)
87-
88-let stakingAddress = Address(base58'3N6q7sCGSSLBUXDdjBdYGTJbZGZfhhh8cNg')
62+let walletAddress = Address(base58'3NAGTtZz6WpupSN89NZD5rMZwwziZEg4Kx4')
8963
9064 let USDN = base58'8UrfDVd5GreeUwm7uPk7eYz1eMv376kzR52C6sANPkwS'
9165
92-let SWOP = base58'2HAJrwa8q4SxBx9cHYaBTQdBjdk5wwqdof7ccpAx2uhZ'
66+let EURN = base58'ECBCkHS68DckpBrzLeoRgYbFg7sCVqR176mPqbXsj9pA'
9367
94-let stakingFeeInUSDN = 270000
68+let stakingAssets = [toBase58String(USDN), toBase58String(EURN)]
9569
96-let isActive = getBooleanValue(this, kActive)
70+let stakingUSDNNSBTAddress = Address(fromBase58String(valueOrErrorMessage(getString(oracle, keyUSDNNSBTAddress), "no usdn staking address")))
71+
72+let stakingEURNAddress = Address(fromBase58String(valueOrErrorMessage(getString(oracle, keyEURNAddress), "no usdn staking address")))
73+
74+let active = getBooleanValue(this, kActive)
9775
9876 let strAssetIdA = getStringValue(this, kAssetIdA)
9977
10078 let strAssetIdB = getStringValue(this, kAssetIdB)
10179
10280 let assetIdA = if ((strAssetIdA == "WAVES"))
10381 then unit
10482 else fromBase58String(strAssetIdA)
10583
10684 let assetIdB = if ((strAssetIdB == "WAVES"))
10785 then unit
10886 else fromBase58String(strAssetIdB)
10987
11088 let assetNameA = match assetIdA {
11189 case id: ByteVector =>
11290 value(assetInfo(id)).name
11391 case waves: Unit =>
11492 "WAVES"
11593 case _ =>
11694 throw("Match error")
11795 }
11896
11997 let assetNameB = match assetIdB {
12098 case id: ByteVector =>
12199 value(assetInfo(id)).name
122100 case waves: Unit =>
123101 "WAVES"
124102 case _ =>
125103 throw("Match error")
126104 }
127105
128106 let balanceA = getIntegerValue(this, kBalanceA)
129107
130108 let balanceB = getIntegerValue(this, kBalanceB)
131109
132110 let shareAssetId = fromBase58String(getStringValue(this, kShareAssetId))
133111
134112 let shareAssetSupply = getIntegerValue(this, kShareAssetSupply)
135113
136114 let invariant = getIntegerValue(this, kInvariant)
137115
138116 let fee = 500
139117
140118 let feeGovernance = 200
141119
142120 let feeScale6 = 1000000
143121
144-let comissionForInitalization = 1000000000
145-
146122 let scale3 = 1000
147123
148124 let scale8 = 100000000
149125
150-let scale12 = 1000000000000
126+let scale16 = 10000000000000000
151127
152128 let slippageScale3 = 1000
153129
154130 let digits8 = 8
155131
156132 let dAppThreshold = 50
157133
158134 let dAppThresholdScale2 = 100
159135
160136 let exchangeRatioLimitMin = 90000000
161137
162138 let exchangeRatioLimitMax = 110000000
163139
164140 let alpha = 50
165141
166142 let alphaDigits = 2
167143
168-let beta = 46000000
144+let beta = 4600000000000000
169145
170146 func accountBalance (assetId) = match assetId {
171147 case id: ByteVector =>
172148 assetBalance(this, id)
173149 case waves: Unit =>
174150 wavesBalance(this).available
175151 case _ =>
176152 throw("Match error")
177153 }
178154
179155
180-let stakedAmountUSDN = match getInteger(stakingAddress, ((("rpd_balance_" + toBase58String(USDN)) + "_") + toString(this))) {
181- case staked: Int =>
182- staked
183- case nothing: Unit =>
184- 0
185- case _ =>
186- throw("Match error")
187-}
188-
189-func isAllowedAsset (assetId) = match assetId {
190- case id: ByteVector =>
191- if ((id == USDN))
192- then true
193- else false
194- case waves: Unit =>
195- false
196- case _ =>
197- throw("Match error")
198-}
156+func stakedAmount (assetId) = {
157+ let stakedAmountCalculated = match assetId {
158+ case aId: ByteVector =>
159+ if ((aId == USDN))
160+ then getInteger(stakingUSDNNSBTAddress, ((("rpd_balance_" + toBase58String(aId)) + "_") + toString(this)))
161+ else if ((aId == EURN))
162+ then getInteger(stakingEURNAddress, ((("%s%s%s__stakingBalance__" + toBase58String(aId)) + "__") + toString(this)))
163+ else 0
164+ case _: Unit =>
165+ 0
166+ case _ =>
167+ throw("Match error")
168+ }
169+ match stakedAmountCalculated {
170+ case i: Int =>
171+ i
172+ case _ =>
173+ 0
174+ }
175+ }
199176
200177
201-let availableBalanceA = (balanceA - (if ((assetIdA == USDN))
202- then stakedAmountUSDN
203- else 0))
178+let stakedAmountA = stakedAmount(assetIdA)
204179
205-let availableBalanceB = (balanceB - (if ((assetIdB == USDN))
206- then stakedAmountUSDN
207- else 0))
180+let stakedAmountB = stakedAmount(assetIdB)
208181
209-let accountBalanceWithStakedA = (accountBalance(assetIdA) + (if ((assetIdA == USDN))
210- then stakedAmountUSDN
211- else 0))
182+let availableBalanceA = (balanceA - stakedAmountA)
212183
213-let accountBalanceWithStakedB = (accountBalance(assetIdB) + (if ((assetIdB == USDN))
214- then stakedAmountUSDN
215- else 0))
184+let availableBalanceB = (balanceB - stakedAmountB)
185+
186+let accountBalanceWithStakedA = (accountBalance(assetIdA) + stakedAmountA)
187+
188+let accountBalanceWithStakedB = (accountBalance(assetIdB) + stakedAmountB)
216189
217190 let hasEnoughBalance = if ((accountBalanceWithStakedA >= balanceA))
218191 then (accountBalanceWithStakedB >= balanceB)
219192 else false
220193
221-func skewness (x,y) = (((fraction(scale12, x, y) + fraction(scale12, y, x)) / 2) / 10000)
194+func skewness (x,y) = ((fraction(scale16, x, y) + fraction(scale16, y, x)) / 2)
222195
223196
224197 func invariantCalc (x,y) = {
225198 let sk = skewness(x, y)
226- (fraction((x + y), scale8, pow(sk, digits8, alpha, alphaDigits, digits8, CEILING)) + (2 * fraction(pow(fraction(x, y, scale8), 0, 5, 1, (digits8 / 2), DOWN), pow((sk - beta), digits8, alpha, alphaDigits, digits8, DOWN), scale8)))
199+ (fraction((x + y), scale16, pow(sk, digits8, alpha, alphaDigits, digits8, CEILING)) + (2 * fraction(toInt(pow(fraction(toBigInt(x), toBigInt(y), toBigInt(scale8)), 0, toBigInt(5), 1, (digits8 / 2), DOWN)), pow((sk - beta), digits8, alpha, alphaDigits, digits8, DOWN), scale8)))
227200 }
228201
229202
230203 func calculateSendAmount (amountToSendEstimated,minTokenReceiveAmount,tokenReceiveAmount,tokenId) = {
231- let slippageValue = (scale8 - ((scale8 * 1) / 10000000))
204+ let worstAllowedNewInvariantRatio = (scale8 - ((scale8 * 1) / 10000000))
232205 let deltaBetweenMaxAndMinSendValue = (amountToSendEstimated - minTokenReceiveAmount)
233206 let x = (balanceA + tokenReceiveAmount)
234207 let y = (balanceB + tokenReceiveAmount)
235- let invariantNew = if ((tokenId == assetIdA))
236- then invariantCalc(x, (balanceB - amountToSendEstimated))
237- else if ((tokenId == assetIdB))
238- then invariantCalc((balanceA - amountToSendEstimated), y)
239- else throw("Wrong asset in payment")
240- let invariantEstimatedRatio = fraction(scale8, invariant, invariantNew)
241- func getStepAmount (acc,step) = if ((acc == -1))
208+ func getStepAmount (acc,step) = if ((acc._1 == -1))
242209 then {
243- let amountToSend = (amountToSendEstimated - ((step * deltaBetweenMaxAndMinSendValue) / 5))
210+ let amountToSend = (amountToSendEstimated - (((step * deltaBetweenMaxAndMinSendValue) / 3) / scale3))
244211 let stepInvariant = if ((tokenId == assetIdA))
245212 then invariantCalc(x, (balanceB - amountToSend))
246213 else invariantCalc((balanceA - amountToSend), y)
247214 if ((stepInvariant > invariant))
248- then amountToSend
249- else -1
215+ then $Tuple2(amountToSend, stepInvariant)
216+ else $Tuple2(-1, 0)
250217 }
251218 else acc
252219
253- let stepAmount = {
254- let $list71887231 = [1, 2, 3, 4, 5]
255- let $size71887231 = size($list71887231)
256- let $acc071887231 = -1
257- if (($size71887231 == 0))
258- then $acc071887231
259- else {
260- let $acc171887231 = getStepAmount($acc071887231, $list71887231[0])
261- if (($size71887231 == 1))
262- then $acc171887231
220+ let amountToSendMin = getStepAmount($Tuple2(-1, 0), 3000)
221+ if ((0 > amountToSendMin._1))
222+ then throw("Price is worse than minReceived")
223+ else {
224+ let invEstimated = if ((tokenId == assetIdA))
225+ then invariantCalc(x, (balanceB - amountToSendEstimated))
226+ else if ((tokenId == assetIdB))
227+ then invariantCalc((balanceA - amountToSendEstimated), y)
228+ else throw("Wrong asset in payment")
229+ let amountToSendBest = if ((invariant > invEstimated))
230+ then if ((worstAllowedNewInvariantRatio >= fraction(scale8, invariant, invEstimated)))
231+ then throw("Bad estimation provided 1")
263232 else {
264- let $acc271887231 = getStepAmount($acc171887231, $list71887231[1])
265- if (($size71887231 == 2))
266- then $acc271887231
267- else {
268- let $acc371887231 = getStepAmount($acc271887231, $list71887231[2])
269- if (($size71887231 == 3))
270- then $acc371887231
271- else {
272- let $acc471887231 = getStepAmount($acc371887231, $list71887231[3])
273- if (($size71887231 == 4))
274- then $acc471887231
275- else {
276- let $acc571887231 = getStepAmount($acc471887231, $list71887231[4])
277- if (($size71887231 == 5))
278- then $acc571887231
279- else {
280- let $acc671887231 = getStepAmount($acc571887231, $list71887231[5])
281- throw("List size exceed 5")
282- }
283- }
284- }
285- }
233+ let a = {
234+ let $l = [25, 200, 500]
235+ let $s = size($l)
236+ let $acc0 = $Tuple2(-1, 0)
237+ func $f0_1 ($a,$i) = if (($i >= $s))
238+ then $a
239+ else getStepAmount($a, $l[$i])
240+
241+ func $f0_2 ($a,$i) = if (($i >= $s))
242+ then $a
243+ else throw("List size exceeds 3")
244+
245+ $f0_2($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3)
246+ }
247+ if ((0 > a._1))
248+ then amountToSendMin
249+ else a
286250 }
287- }
288- }
289- if ((0 > stepAmount))
290- then throw("something went wrong while working with amountToSend")
291- else if (if ((invariantEstimatedRatio > slippageValue))
292- then (invariantNew > invariant)
293- else false)
294- then amountToSendEstimated
295- else stepAmount
251+ else {
252+ let a = {
253+ let $l = [-500, -200, -25]
254+ let $s = size($l)
255+ let $acc0 = $Tuple2(-1, 0)
256+ func $f0_1 ($a,$i) = if (($i >= $s))
257+ then $a
258+ else getStepAmount($a, $l[$i])
259+
260+ func $f0_2 ($a,$i) = if (($i >= $s))
261+ then $a
262+ else throw("List size exceeds 3")
263+
264+ $f0_2($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3)
265+ }
266+ let tupleSendBetter = if ((0 > a._1))
267+ then $Tuple2(amountToSendEstimated, invEstimated)
268+ else a
269+ if ((worstAllowedNewInvariantRatio >= fraction(scale8, invariant, tupleSendBetter._2)))
270+ then throw("Bad estimation provided 2")
271+ else tupleSendBetter
272+ }
273+ amountToSendBest
274+ }
296275 }
297276
298277
299278 func getAssetInfo (assetId) = match assetId {
300279 case id: ByteVector =>
301280 let stringId = toBase58String(id)
302281 let info = valueOrErrorMessage(assetInfo(id), (("Asset " + stringId) + " doesn't exist"))
303282 $Tuple3(stringId, info.name, info.decimals)
304283 case waves: Unit =>
305284 $Tuple3("WAVES", "WAVES", 8)
306285 case _ =>
307286 throw("Match error")
308287 }
309288
310289
311290 func suspend (cause) = [BooleanEntry(kActive, false), StringEntry(kCause, cause)]
312291
313292
314-func deductStakingFee (amount,assetId) = if ((assetId == USDN))
315- then {
316- let result = (amount - stakingFeeInUSDN)
317- if ((0 >= result))
318- then throw((((("Insufficient amount " + toString(amount)) + " to deduct staking fee ") + toString(stakingFeeInUSDN)) + " USD-N"))
319- else result
320- }
321- else amount
322-
323-
324293 func throwIsActive () = throw("DApp is already active")
325294
326295
327-func throwIsInactive () = throw("DApp is inactive at this moment")
296+func isActive () = if (active)
297+ then unit
298+ else throw("DApp is inactive at this moment")
328299
329300
330-func throwOnlyAdmin () = throw("Only admin can call this function")
301+func isAdminCall (i) = if (containsElement([adminPubKey1, adminPubKey2, adminPubKey3], i.callerPublicKey))
302+ then unit
303+ else throw("Only admin can call this function")
331304
332305
333306 func throwAssets () = throw(((("Incorrect assets attached. Expected: " + strAssetIdA) + " and ") + strAssetIdB))
334307
335308
336-func throwThreshold (threshold,amountA,amountB) = throw(((((((((("New balance in assets of the DApp is less than threshold " + toString(threshold)) + ": ") + toString(amountA)) + " ") + assetNameA) + ", ") + toString(amountB)) + " ") + assetNameB))
309+func throwOnePayment () = throw("One attached payment expected")
337310
338311
339-func throwInsufficientAvailableBalance (amount,available,assetName) = throw((((((((("Insufficient DApp balance to pay " + toString(amount)) + " ") + assetName) + " due to staking. Available: ") + toString(available)) + " ") + assetName) + ". Please contact support in Telegram: https://t.me/swopfisupport"))
340-
341-
342-func throwInsufficientAvailableBalances (amountA,amountB) = throw((((((((((((((((("Insufficient DApp balance to pay " + toString(amountA)) + " ") + assetNameA) + " and ") + toString(amountB)) + " ") + assetNameB) + " due to staking. Available: ") + toString(availableBalanceA)) + " ") + assetNameA) + " and ") + toString(availableBalanceB)) + " ") + assetNameB) + ". Please contact support in Telegram: https://t.me/swopfisupport"))
312+func throwThreshold (threshold,amountA,amountB) = throw(((((((((("New balance in assets of the DApp is less than threshold " + toString(threshold)) + ": ") + toString(amountA)) + " ") + assetNameA) + ", ") + toString(amountB)) + " ") + assetNameB))
343313
344314
345315 func suspendSuspicious () = suspend(((((((((((((((("Suspicious state. Actual balances: " + toString(balanceA)) + " ") + assetNameA) + ", ") + toString(balanceB)) + " ") + assetNameB) + ". State: ") + toString(accountBalance(assetIdA))) + " ") + assetNameA) + ", ") + toString(accountBalance(assetIdB))) + " ") + assetNameB))
346316
347317
318+func calcStakingFuncAndAddres (stake,assetId) = if (stake)
319+ then if ((assetId == USDN))
320+ then $Tuple2("lockNeutrino", stakingUSDNNSBTAddress)
321+ else $Tuple2("startStaking", stakingEURNAddress)
322+ else if ((assetId == USDN))
323+ then $Tuple2("unlockNeutrino", stakingUSDNNSBTAddress)
324+ else $Tuple2("stopStaking", stakingEURNAddress)
325+
326+
327+func calcStakingParams (stake,amount,assetId) = if (stake)
328+ then {
329+ let $t097119777 = calcStakingFuncAndAddres(stake, assetId)
330+ let call = $t097119777._1
331+ let stakingAddr = $t097119777._2
332+ $Tuple4(call, stakingAddr, nil, [AttachedPayment(assetId, amount)])
333+ }
334+ else {
335+ let $t098639929 = calcStakingFuncAndAddres(stake, assetId)
336+ let call = $t098639929._1
337+ let stakingAddr = $t098639929._2
338+ $Tuple4(call, stakingAddr, [amount, toBase58String(assetId)], nil)
339+ }
340+
341+
348342 @Callable(i)
349-func init (userAddressStr) = {
350- let $t0992910006 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
351- let pmtAmount1 = $t0992910006._1
352- let pmtAssetId1 = $t0992910006._2
353- let $t01001110088 = $Tuple2(i.payments[1].amount, i.payments[1].assetId)
354- let pmtAmount2 = $t01001110088._1
355- let pmtAssetId2 = $t01001110088._2
356- let $t01009310176 = $Tuple2(i.payments[2].amount, i.payments[2].assetId)
357- let pmtAmountSWOP = $t01009310176._1
358- let pmtAssetIdSWOP = $t01009310176._2
359- let check = isDataStorageUntouched(this)
360- let userScriptHash = scriptHash(this)
361- let userAddress = addressFromStringValue(userAddressStr)
362- if ((i.caller == this))
363- then throw("You can't call yourself")
364- else if (if ((pmtAssetIdSWOP != SWOP))
365- then true
366- else (pmtAmountSWOP != comissionForInitalization))
367- then throw("You need to attach 10 SWOP tokens")
368- else if (if (!(isAllowedAsset(pmtAssetId1)))
369- then !(isAllowedAsset(pmtAssetId2))
370- else false)
371- then throw("One of assets must be USDN, WAVES or SWOP")
372- else if (if ((userScriptHash != value(getBinary(oracle, kOracleScriptHash))))
373- then true
374- else !(check))
375- then throw("Unexpected script was found.")
376- else if (isDefined(getBoolean(this, kActive)))
377- then throwIsActive()
378- else if ((pmtAssetId1 == pmtAssetId2))
379- then throw("Assets must be different")
380- else {
381- let pmtStrAssetId1 = match pmtAssetId1 {
382- case id: ByteVector =>
383- toBase58String(id)
384- case waves: Unit =>
385- "WAVES"
386- case _ =>
387- throw("Match error")
388- }
389- let pmtStrAssetId2 = match pmtAssetId2 {
390- case id: ByteVector =>
391- toBase58String(id)
392- case waves: Unit =>
393- "WAVES"
394- case _ =>
395- throw("Match error")
396- }
397- let asset1Priority = valueOrElse(getInteger(oracle, (kOracleAssetPriority + pmtStrAssetId1)), 999999)
398- let asset2Priority = valueOrElse(getInteger(oracle, (kOracleAssetPriority + pmtStrAssetId2)), 999999)
399- let $t01151111738 = if ((asset2Priority > asset1Priority))
400- then $Tuple4(pmtAmount2, pmtAssetId2, pmtAmount1, pmtAssetId1)
401- else $Tuple4(pmtAmount1, pmtAssetId1, pmtAmount2, pmtAssetId2)
402- let pmtAmountA = $t01151111738._1
403- let pmtAssetIdA = $t01151111738._2
404- let pmtAmountB = $t01151111738._3
405- let pmtAssetIdB = $t01151111738._4
406- let $t01174711824 = getAssetInfo(pmtAssetIdA)
407- let pmtStrAssetIdA = $t01174711824._1
408- let pmtAssetNameA = $t01174711824._2
409- let pmtDecimalsA = $t01174711824._3
410- let $t01183311910 = getAssetInfo(pmtAssetIdB)
411- let pmtStrAssetIdB = $t01183311910._1
412- let pmtAssetNameB = $t01183311910._2
413- let pmtDecimalsB = $t01183311910._3
414- let shareName = ((("s" + take(pmtAssetNameA, 7)) + "_") + take(pmtAssetNameB, 7))
415- let shareDescription = ((((("ShareToken of SwopFi protocol for " + pmtAssetNameA) + " and ") + pmtAssetNameB) + " at address ") + toString(this))
416- let shareDecimals = ((pmtDecimalsA + pmtDecimalsB) / 2)
417- let shareInitialSupply = fraction(pow(pmtAmountA, pmtDecimalsA, 5, 1, pmtDecimalsA, DOWN), pow(pmtAmountB, pmtDecimalsB, 5, 1, pmtDecimalsB, DOWN), pow(10, 0, shareDecimals, 0, 0, DOWN))
418- let shareIssue = Issue(shareName, shareDescription, shareInitialSupply, shareDecimals, true)
419- let shareIssueId = calculateAssetId(shareIssue)
420- let invariantCalculated = invariantCalc(pmtAmountA, pmtAmountB)
421-[StringEntry(kVersion, version), BooleanEntry(kActive, true), StringEntry(kAssetIdA, pmtStrAssetIdA), StringEntry(kAssetIdB, pmtStrAssetIdB), IntegerEntry(kBalanceA, pmtAmountA), IntegerEntry(kBalanceB, pmtAmountB), IntegerEntry(kInvariant, invariantCalculated), IntegerEntry(kFee, fee), IntegerEntry(kFeeScaleDelimiter, feeScale6), IntegerEntry(kInitPoolHeight, height), shareIssue, StringEntry(kShareAssetId, toBase58String(shareIssueId)), IntegerEntry(kShareAssetSupply, shareInitialSupply), ScriptTransfer(userAddress, shareInitialSupply, shareIssueId), ScriptTransfer(walletAddress, comissionForInitalization, SWOP)]
422- }
343+func init () = {
344+ let $t01003410111 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
345+ let pmtAmountA = $t01003410111._1
346+ let pmtAssetIdA = $t01003410111._2
347+ let $t01011610193 = $Tuple2(i.payments[1].amount, i.payments[1].assetId)
348+ let pmtAmountB = $t01011610193._1
349+ let pmtAssetIdB = $t01011610193._2
350+ let $t01019810275 = getAssetInfo(pmtAssetIdA)
351+ let pmtStrAssetIdA = $t01019810275._1
352+ let pmtAssetNameA = $t01019810275._2
353+ let pmtDecimalsA = $t01019810275._3
354+ let $t01028010357 = getAssetInfo(pmtAssetIdB)
355+ let pmtStrAssetIdB = $t01028010357._1
356+ let pmtAssetNameB = $t01028010357._2
357+ let pmtDecimalsB = $t01028010357._3
358+ if (isDefined(getBoolean(this, kActive)))
359+ then throwIsActive()
360+ else if ((pmtAssetIdA == pmtAssetIdB))
361+ then throw("Assets must be different")
362+ else {
363+ let shareName = ((("s" + take(pmtAssetNameA, 7)) + "_") + take(pmtAssetNameB, 7))
364+ let shareDescription = ((((("ShareToken of SwopFi protocol for " + pmtAssetNameA) + " and ") + pmtAssetNameB) + " at address ") + toString(this))
365+ let shareDecimals = ((pmtDecimalsA + pmtDecimalsB) / 2)
366+ let shareInitialSupply = fraction(pow(pmtAmountA, pmtDecimalsA, 5, 1, pmtDecimalsA, DOWN), pow(pmtAmountB, pmtDecimalsB, 5, 1, pmtDecimalsB, DOWN), pow(10, 0, shareDecimals, 0, 0, DOWN))
367+ let shareIssue = Issue(shareName, shareDescription, shareInitialSupply, shareDecimals, true)
368+ let shareIssueId = calculateAssetId(shareIssue)
369+ let invariantCalculated = invariantCalc(pmtAmountA, pmtAmountB)
370+ let stake1 = if (containsElement(stakingAssets, pmtStrAssetIdA))
371+ then invoke(this, "stakeUnstake", [true, pmtAmountA, pmtStrAssetIdA], nil)
372+ else 0
373+ if ((stake1 == stake1))
374+ then {
375+ let stake2 = if (containsElement(stakingAssets, pmtStrAssetIdB))
376+ then invoke(this, "stakeUnstake", [true, pmtAmountB, pmtStrAssetIdB], nil)
377+ else 0
378+ if ((stake2 == stake2))
379+ then [StringEntry(kVersion, version), BooleanEntry(kActive, true), StringEntry(kAssetIdA, pmtStrAssetIdA), StringEntry(kAssetIdB, pmtStrAssetIdB), IntegerEntry(kBalanceA, pmtAmountA), IntegerEntry(kBalanceB, pmtAmountB), IntegerEntry(kInvariant, invariantCalculated), IntegerEntry(kFee, fee), IntegerEntry(kFeeScaleDelimiter, feeScale6), shareIssue, StringEntry(kShareAssetId, toBase58String(shareIssueId)), IntegerEntry(kShareAssetSupply, shareInitialSupply), ScriptTransfer(i.caller, shareInitialSupply, shareIssueId)]
380+ else throw("Strict value is not equal to itself.")
381+ }
382+ else throw("Strict value is not equal to itself.")
383+ }
423384 }
424385
425386
426387
427388 @Callable(i)
428-func keepLimitForFirstHarvest (shareLimit) = if (!(isActive))
429- then throw("DApp is inactive at this moment")
430- else if (!(containsElement([adminPubKey1, adminPubKey2, adminPubKey3, admStaking], i.callerPublicKey)))
431- then throw("Only admin can call this function")
432- else [IntegerEntry(kShareLimit, shareLimit)]
389+func replenishWithTwoTokens () = valueOrElse(isActive(), {
390+ let pmtAssetIdA = i.payments[0].assetId
391+ let pmtAssetIdB = i.payments[1].assetId
392+ let ratioShareTokensInA = fraction(scale8, i.payments[0].amount, balanceA)
393+ let ratioShareTokensInB = fraction(scale8, i.payments[1].amount, balanceB)
394+ let $t01293813015 = getAssetInfo(pmtAssetIdA)
395+ let pmtStrAssetIdA = $t01293813015._1
396+ let pmtAssetNameA = $t01293813015._2
397+ let pmtDecimalsA = $t01293813015._3
398+ let $t01302013137 = getAssetInfo(pmtAssetIdB)
399+ let pmtStrAssetIdB = $t01302013137._1
400+ let pmtAssetNameB = $t01302013137._2
401+ let pmtDecimalsB = $t01302013137._3
402+ let $t01314213646 = if ((ratioShareTokensInB > ratioShareTokensInA))
403+ then {
404+ let pmt = fraction(balanceB, ratioShareTokensInA, scale8, CEILING)
405+ $Tuple5(i.payments[0].amount, pmt, (i.payments[1].amount - pmt), pmtAssetIdB, ratioShareTokensInA)
406+ }
407+ else {
408+ let pmt = fraction(balanceB, ratioShareTokensInA, scale8, CEILING)
409+ $Tuple5(pmt, i.payments[1].amount, (i.payments[0].amount - pmt), pmtAssetIdA, ratioShareTokensInB)
410+ }
411+ let pmtAmountA = $t01314213646._1
412+ let pmtAmountB = $t01314213646._2
413+ let change = $t01314213646._3
414+ let changeAssetId = $t01314213646._4
415+ let shareTokenRatio = $t01314213646._5
416+ let shareTokenToPayAmount = fraction(shareTokenRatio, shareAssetSupply, scale8)
417+ if ((size(i.payments) != 2))
418+ then throw("Two attached assets expected")
419+ else if (if ((pmtAssetIdA != assetIdA))
420+ then true
421+ else (pmtAssetIdB != assetIdB))
422+ then throwAssets()
423+ else if ((shareTokenToPayAmount == 0))
424+ then throw("Too small amount to replenish")
425+ else if ((0 > change))
426+ then throw("Change < 0")
427+ else if (!(hasEnoughBalance))
428+ then ([ScriptTransfer(i.caller, pmtAmountA, pmtAssetIdA), ScriptTransfer(i.caller, pmtAmountB, pmtAssetIdB)] ++ suspendSuspicious())
429+ else {
430+ let stake1 = if (containsElement(stakingAssets, pmtStrAssetIdA))
431+ then invoke(this, "stakeUnstake", [true, pmtAmountA, pmtStrAssetIdA], nil)
432+ else 0
433+ if ((stake1 == stake1))
434+ then {
435+ let stake2 = if (containsElement(stakingAssets, pmtStrAssetIdB))
436+ then invoke(this, "stakeUnstake", [true, pmtAmountB, pmtStrAssetIdB], nil)
437+ else 0
438+ if ((stake2 == stake2))
439+ then [IntegerEntry(kBalanceA, (balanceA + pmtAmountA)), IntegerEntry(kBalanceB, (balanceB + pmtAmountB)), IntegerEntry(kShareAssetSupply, (shareAssetSupply + shareTokenToPayAmount)), IntegerEntry(kInvariant, invariantCalc((balanceA + pmtAmountA), (balanceB + pmtAmountB))), Reissue(shareAssetId, shareTokenToPayAmount, true), ScriptTransfer(i.caller, shareTokenToPayAmount, shareAssetId), ScriptTransfer(i.caller, change, changeAssetId)]
440+ else throw("Strict value is not equal to itself.")
441+ }
442+ else throw("Strict value is not equal to itself.")
443+ }
444+ })
433445
434446
435447
436448 @Callable(i)
437-func replenishWithTwoTokens (slippageTolerance) = {
438- let pmtAssetIdA = i.payments[0].assetId
439- let pmtAssetIdB = i.payments[1].assetId
440- let pmtAmountA = deductStakingFee(i.payments[0].amount, pmtAssetIdA)
441- let pmtAmountB = deductStakingFee(i.payments[1].amount, pmtAssetIdB)
442- let tokenRatio = fraction(fraction(scale8, balanceA, pmtAmountA), scale3, fraction(scale8, balanceB, pmtAmountB))
443- let ratioShareTokensInA = fraction(scale8, pmtAmountA, balanceA)
444- let ratioShareTokensInB = fraction(scale8, pmtAmountB, balanceB)
445- let shareTokenToPayAmount = fraction(min([ratioShareTokensInA, ratioShareTokensInB]), shareAssetSupply, scale8)
446- let invariantCalculated = invariantCalc((balanceA + pmtAmountA), (balanceB + pmtAmountB))
447- if (!(isActive))
448- then throwIsInactive()
449- else if (if ((0 > slippageTolerance))
450- then true
451- else (slippageTolerance > 10))
452- then throw("Slippage tolerance must be <= 1%")
453- else if ((size(i.payments) != 2))
454- then throw("Two attached assets expected")
455- else if (if ((pmtAssetIdA != assetIdA))
456- then true
457- else (pmtAssetIdB != assetIdB))
458- then throwAssets()
459- else if (if ((((scale3 * (slippageScale3 - slippageTolerance)) / slippageScale3) > tokenRatio))
460- then true
461- else (tokenRatio > ((scale3 * (slippageScale3 + slippageTolerance)) / slippageScale3)))
462- then throw("Incorrect assets amount: amounts must have the contract ratio")
463- else if ((shareTokenToPayAmount == 0))
464- then throw("Too small amount to replenish")
465- else if (!(hasEnoughBalance))
466- then ([ScriptTransfer(i.caller, pmtAmountA, pmtAssetIdA), ScriptTransfer(i.caller, pmtAmountB, pmtAssetIdB)] ++ suspendSuspicious())
467- else [IntegerEntry(kBalanceA, (balanceA + pmtAmountA)), IntegerEntry(kBalanceB, (balanceB + pmtAmountB)), IntegerEntry(kShareAssetSupply, (shareAssetSupply + shareTokenToPayAmount)), IntegerEntry(kInvariant, invariantCalculated), Reissue(shareAssetId, shareTokenToPayAmount, true), ScriptTransfer(i.caller, shareTokenToPayAmount, shareAssetId)]
468- }
469-
470-
471-
472-@Callable(i)
473-func replenishWithOneToken (virtualSwapTokenPay,virtualSwapTokenGet) = {
474- let $t01658816663 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
475- let pmtAmount = $t01658816663._1
476- let pmtAssetId = $t01658816663._2
449+func replenishWithOneToken (virtualSwapTokenPay,virtualSwapTokenGet) = valueOrElse(isActive(), {
450+ let $t01529515370 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
451+ let pmtAmount = $t01529515370._1
452+ let pmtAssetId = $t01529515370._2
453+ let $t01537515448 = getAssetInfo(pmtAssetId)
454+ let pmtStrAssetId = $t01537515448._1
455+ let pmtAssetName = $t01537515448._2
456+ let pmtDecimals = $t01537515448._3
477457 let pmtMinThreshold = 5000000
478458 let thresholdValueForMinTolerance = 50000000
479459 let tolerance = if ((thresholdValueForMinTolerance > pmtAmount))
480460 then 100000
481461 else 1
482462 let slippageValueMinForReplenish = (scale8 - ((scale8 * tolerance) / 10000000))
483463 let slippageValueMaxForReplenish = (scale8 + ((scale8 * tolerance) / 10000000))
484464 let slippageValueMinForSwap = (scale8 - ((scale8 * 1) / 10000000))
485- if (!(isActive))
486- then throwIsInactive()
487- else if ((pmtMinThreshold > pmtAmount))
488- then throw((((("Payment amount " + toString(pmtAmount)) + " does not exceed the minimum amount of ") + toString(pmtMinThreshold)) + " tokens"))
465+ if ((pmtMinThreshold > pmtAmount))
466+ then throw((((("Payment amount " + toString(pmtAmount)) + " does not exceed the minimum amount of ") + toString(pmtMinThreshold)) + " tokens"))
467+ else if ((size(i.payments) != 1))
468+ then throwOnePayment()
469+ else if (!(hasEnoughBalance))
470+ then ([ScriptTransfer(i.caller, pmtAmount, pmtAssetId)] ++ suspendSuspicious())
471+ else if (if ((pmtAssetId != assetIdA))
472+ then (pmtAssetId != assetIdB)
473+ else false)
474+ then throwAssets()
475+ else {
476+ let $t01638617151 = if ((pmtAssetId == assetIdA))
477+ then $Tuple7((pmtAmount - virtualSwapTokenPay), virtualSwapTokenGet, (balanceA + virtualSwapTokenPay), (balanceB - virtualSwapTokenGet), invariantCalc((balanceA + pmtAmount), balanceB), (balanceA + pmtAmount), balanceB)
478+ else $Tuple7(virtualSwapTokenGet, (pmtAmount - virtualSwapTokenPay), (balanceA - virtualSwapTokenGet), (balanceB + virtualSwapTokenPay), invariantCalc(balanceA, (balanceB + pmtAmount)), balanceA, (balanceB + pmtAmount))
479+ let virtualReplenishA = $t01638617151._1
480+ let virtualReplenishB = $t01638617151._2
481+ let balanceAfterSwapA = $t01638617151._3
482+ let balanceAfterSwapB = $t01638617151._4
483+ let invariantCalculated = $t01638617151._5
484+ let newBalanceA = $t01638617151._6
485+ let newBalanceB = $t01638617151._7
486+ let newBalanceEntry = if ((pmtAssetId == assetIdA))
487+ then IntegerEntry(kBalanceA, newBalanceA)
488+ else IntegerEntry(kBalanceB, newBalanceB)
489+ let invariantNew = invariantCalc(balanceAfterSwapA, balanceAfterSwapB)
490+ let invariantEstimatedRatio = fraction(scale8, invariant, invariantNew)
491+ let ratioVirtualBalanceToVirtualReplenish = (fraction((scale8 * scale8), balanceAfterSwapA, balanceAfterSwapB) / fraction(scale8, virtualReplenishA, virtualReplenishB))
492+ let dAppThresholdAmount = fraction((newBalanceA + newBalanceB), dAppThreshold, (2 * dAppThresholdScale2))
493+ if (if ((slippageValueMinForSwap >= invariantEstimatedRatio))
494+ then true
495+ else (invariant > invariantNew))
496+ then throw("Incorrect virtualSwapTokenPay or virtualSwapTokenGet value")
497+ else if (if ((slippageValueMinForReplenish > ratioVirtualBalanceToVirtualReplenish))
498+ then true
499+ else (ratioVirtualBalanceToVirtualReplenish > slippageValueMaxForReplenish))
500+ then throw("Swap with virtualSwapTokenPay and virtualSwapTokenGet is possible, but ratio after virtual swap is incorrect")
501+ else if (if ((dAppThresholdAmount > newBalanceA))
502+ then true
503+ else (dAppThresholdAmount > newBalanceB))
504+ then throwThreshold(dAppThresholdAmount, newBalanceA, newBalanceB)
505+ else {
506+ let stake1 = if (containsElement(stakingAssets, pmtStrAssetId))
507+ then invoke(this, "stakeUnstake", [true, pmtAmount, pmtStrAssetId], nil)
508+ else 0
509+ if ((stake1 == stake1))
510+ then {
511+ let ratioShareTokensInA = fraction(virtualReplenishA, scale8, balanceAfterSwapA)
512+ let ratioShareTokensInB = fraction(virtualReplenishB, scale8, balanceAfterSwapB)
513+ let shareTokenToPayAmount = fraction(min([ratioShareTokensInA, ratioShareTokensInB]), shareAssetSupply, scale8)
514+[Reissue(shareAssetId, shareTokenToPayAmount, true), ScriptTransfer(i.caller, shareTokenToPayAmount, shareAssetId), IntegerEntry(kShareAssetSupply, (shareAssetSupply + shareTokenToPayAmount)), newBalanceEntry, IntegerEntry(kInvariant, invariantCalculated)]
515+ }
516+ else throw("Strict value is not equal to itself.")
517+ }
518+ }
519+ })
520+
521+
522+
523+@Callable(i)
524+func withdraw () = valueOrElse(isActive(), {
525+ let $t01940119544 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
526+ let pmtAmount = $t01940119544._1
527+ let pmtAssetId = $t01940119544._2
528+ let amountToPayA = fraction(pmtAmount, balanceA, shareAssetSupply)
529+ let amountToPayB = fraction(pmtAmount, balanceB, shareAssetSupply)
530+ let invariantCalculated = invariantCalc((balanceA - amountToPayA), (balanceB - amountToPayB))
531+ if ((size(i.payments) != 1))
532+ then throwOnePayment()
533+ else if ((pmtAssetId != shareAssetId))
534+ then throw(("Incorrect asset attached. Expected: " + toBase58String(shareAssetId)))
535+ else if (!(hasEnoughBalance))
536+ then ([ScriptTransfer(i.caller, pmtAmount, pmtAssetId)] ++ suspendSuspicious())
537+ else {
538+ let stake1 = if (containsElement(stakingAssets, strAssetIdA))
539+ then invoke(this, "stakeUnstake", [false, amountToPayA, strAssetIdA], nil)
540+ else 0
541+ if ((stake1 == stake1))
542+ then {
543+ let stake2 = if (containsElement(stakingAssets, strAssetIdB))
544+ then invoke(this, "stakeUnstake", [false, amountToPayB, strAssetIdB], nil)
545+ else 0
546+ if ((stake2 == stake2))
547+ then [IntegerEntry(kBalanceA, (balanceA - amountToPayA)), IntegerEntry(kBalanceB, (balanceB - amountToPayB)), IntegerEntry(kShareAssetSupply, (shareAssetSupply - pmtAmount)), IntegerEntry(kInvariant, invariantCalculated), Burn(shareAssetId, pmtAmount), ScriptTransfer(i.caller, amountToPayA, assetIdA), ScriptTransfer(i.caller, amountToPayB, assetIdB)]
548+ else throw("Strict value is not equal to itself.")
549+ }
550+ else throw("Strict value is not equal to itself.")
551+ }
552+ })
553+
554+
555+
556+@Callable(i)
557+func exchange (estimatedAmountToReceive,minAmountToReceive) = valueOrElse(isActive(), {
558+ let $t02100721082 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
559+ let pmtAmount = $t02100721082._1
560+ let pmtAssetId = $t02100721082._2
561+ if ((0 >= estimatedAmountToReceive))
562+ then throw(("Estimated amount must be positive. Actual: " + toString(estimatedAmountToReceive)))
563+ else if ((minAmountToReceive > estimatedAmountToReceive))
564+ then throw(((("Minimal amount can't be greater than estimated. Estimated: " + toString(estimatedAmountToReceive)) + ". Minimal: ") + toString(minAmountToReceive)))
489565 else if ((size(i.payments) != 1))
490- then throw("One attached payment expected")
566+ then throwOnePayment()
491567 else if (!(hasEnoughBalance))
492568 then ([ScriptTransfer(i.caller, pmtAmount, pmtAssetId)] ++ suspendSuspicious())
493569 else if (if ((pmtAssetId != assetIdA))
494570 then (pmtAssetId != assetIdB)
495571 else false)
496572 then throwAssets()
497- else {
498- let $t01767518440 = if ((pmtAssetId == assetIdA))
499- then $Tuple7((pmtAmount - virtualSwapTokenPay), virtualSwapTokenGet, (balanceA + virtualSwapTokenPay), (balanceB - virtualSwapTokenGet), invariantCalc((balanceA + pmtAmount), balanceB), (balanceA + pmtAmount), balanceB)
500- else $Tuple7(virtualSwapTokenGet, (pmtAmount - virtualSwapTokenPay), (balanceA - virtualSwapTokenGet), (balanceB + virtualSwapTokenPay), invariantCalc(balanceA, (balanceB + pmtAmount)), balanceA, (balanceB + pmtAmount))
501- let virtualReplenishA = $t01767518440._1
502- let virtualReplenishB = $t01767518440._2
503- let balanceAfterSwapA = $t01767518440._3
504- let balanceAfterSwapB = $t01767518440._4
505- let invariantCalculated = $t01767518440._5
506- let newBalanceA = $t01767518440._6
507- let newBalanceB = $t01767518440._7
508- let newBalanceEntry = if ((pmtAssetId == assetIdA))
509- then IntegerEntry(kBalanceA, newBalanceA)
510- else IntegerEntry(kBalanceB, newBalanceB)
511- let invariantNew = invariantCalc(balanceAfterSwapA, balanceAfterSwapB)
512- let invariantEstimatedRatio = fraction(scale8, invariant, invariantNew)
513- let ratioVirtualBalanceToVirtualReplenish = (fraction((scale8 * scale8), balanceAfterSwapA, balanceAfterSwapB) / fraction(scale8, virtualReplenishA, virtualReplenishB))
514- let dAppThresholdAmount = fraction((newBalanceA + newBalanceB), dAppThreshold, (2 * dAppThresholdScale2))
515- if (if ((slippageValueMinForSwap >= invariantEstimatedRatio))
573+ else if ((10000000 > pmtAmount))
574+ then throw("Only swap of 10.000000 or more tokens is allowed")
575+ else if (if ((exchangeRatioLimitMin > fraction(scale8, minAmountToReceive, pmtAmount)))
516576 then true
517- else (invariant > invariantNew))
518- then throw("Incorrect virtualSwapTokenPay or virtualSwapTokenGet value")
519- else if (if ((slippageValueMinForReplenish > ratioVirtualBalanceToVirtualReplenish))
520- then true
521- else (ratioVirtualBalanceToVirtualReplenish > slippageValueMaxForReplenish))
522- then throw("Swap with virtualSwapTokenPay and virtualSwapTokenGet is possible, but ratio after virtual swap is incorrect")
523- else if (if ((dAppThresholdAmount > newBalanceA))
577+ else (fraction(scale8, estimatedAmountToReceive, pmtAmount) > exchangeRatioLimitMax))
578+ then throw("Incorrect args and pmt ratio")
579+ else {
580+ let sendAssetId = if ((pmtAssetId == assetIdA))
581+ then assetIdB
582+ else assetIdA
583+ let $t02217322292 = calculateSendAmount(estimatedAmountToReceive, minAmountToReceive, pmtAmount, pmtAssetId)
584+ let amount = $t02217322292._1
585+ let amountInvarian = $t02217322292._2
586+ let governanceReward = fraction(amount, feeGovernance, feeScale6)
587+ let amountMinusFee = fraction(amount, (feeScale6 - fee), feeScale6)
588+ let $t02244822710 = if ((pmtAssetId == assetIdA))
589+ then $Tuple2((balanceA + pmtAmount), ((balanceB - amountMinusFee) - governanceReward))
590+ else $Tuple2(((balanceA - amountMinusFee) - governanceReward), (balanceB + pmtAmount))
591+ let newBalanceA = $t02244822710._1
592+ let newBalanceB = $t02244822710._2
593+ let dAppThresholdAmount = fraction((newBalanceA + newBalanceB), dAppThreshold, (2 * dAppThresholdScale2))
594+ if (if ((dAppThresholdAmount > newBalanceA))
524595 then true
525596 else (dAppThresholdAmount > newBalanceB))
526597 then throwThreshold(dAppThresholdAmount, newBalanceA, newBalanceB)
527598 else {
528- let ratioShareTokensInA = fraction(deductStakingFee(virtualReplenishA, assetIdA), scale8, balanceAfterSwapA)
529- let ratioShareTokensInB = fraction(deductStakingFee(virtualReplenishB, assetIdB), scale8, balanceAfterSwapB)
530- let shareTokenToPayAmount = fraction(min([ratioShareTokensInA, ratioShareTokensInB]), shareAssetSupply, scale8)
531-[Reissue(shareAssetId, shareTokenToPayAmount, true), ScriptTransfer(i.caller, shareTokenToPayAmount, shareAssetId), IntegerEntry(kShareAssetSupply, (shareAssetSupply + shareTokenToPayAmount)), newBalanceEntry, IntegerEntry(kInvariant, invariantCalculated)]
599+ let $t02300823081 = getAssetInfo(pmtAssetId)
600+ let pmtStrAssetId = $t02300823081._1
601+ let pmtAssetName = $t02300823081._2
602+ let pmtDecimals = $t02300823081._3
603+ let $t02309423171 = getAssetInfo(sendAssetId)
604+ let sendStrAssetId = $t02309423171._1
605+ let sendAssetName = $t02309423171._2
606+ let sendDecimals = $t02309423171._3
607+ let stake1 = if (containsElement(stakingAssets, pmtStrAssetId))
608+ then invoke(this, "stakeUnstake", [true, pmtAmount, pmtStrAssetId], nil)
609+ else 0
610+ if ((stake1 == stake1))
611+ then {
612+ let stake2 = if (containsElement(stakingAssets, sendStrAssetId))
613+ then invoke(this, "stakeUnstake", [false, (amountMinusFee + governanceReward), sendStrAssetId], nil)
614+ else 0
615+ if ((stake2 == stake2))
616+ then [IntegerEntry(kBalanceA, newBalanceA), IntegerEntry(kBalanceB, newBalanceB), IntegerEntry(kInvariant, amountInvarian), ScriptTransfer(i.caller, amountMinusFee, sendAssetId), ScriptTransfer(walletAddress, governanceReward, sendAssetId)]
617+ else throw("Strict value is not equal to itself.")
618+ }
619+ else throw("Strict value is not equal to itself.")
532620 }
533- }
534- }
621+ }
622+ })
535623
536624
537625
538626 @Callable(i)
539-func withdraw () = {
540- let $t02058520728 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
541- let pmtAmount = $t02058520728._1
542- let pmtAssetId = $t02058520728._2
543- let amountToPayA = deductStakingFee(fraction(pmtAmount, balanceA, shareAssetSupply), assetIdA)
544- let amountToPayB = deductStakingFee(fraction(pmtAmount, balanceB, shareAssetSupply), assetIdB)
545- let invariantCalculated = invariantCalc((balanceA - amountToPayA), (balanceB - amountToPayB))
546- if (!(isActive))
547- then throwIsInactive()
548- else if ((size(i.payments) != 1))
549- then throw("One attached payment expected")
550- else if ((pmtAssetId != shareAssetId))
551- then throw(("Incorrect asset attached. Expected: " + toBase58String(shareAssetId)))
552- else if (!(hasEnoughBalance))
553- then ([ScriptTransfer(i.caller, pmtAmount, pmtAssetId)] ++ suspendSuspicious())
554- else if (if ((amountToPayA > availableBalanceA))
555- then true
556- else (amountToPayB > availableBalanceB))
557- then throwInsufficientAvailableBalances(amountToPayA, amountToPayB)
558- else [IntegerEntry(kBalanceA, (balanceA - amountToPayA)), IntegerEntry(kBalanceB, (balanceB - amountToPayB)), IntegerEntry(kShareAssetSupply, (shareAssetSupply - pmtAmount)), IntegerEntry(kInvariant, invariantCalculated), Burn(shareAssetId, pmtAmount), ScriptTransfer(i.caller, amountToPayA, assetIdA), ScriptTransfer(i.caller, amountToPayB, assetIdB)]
559- }
627+func shutdown () = valueOrElse(isAdminCall(i), if (!(active))
628+ then throw(("DApp is already suspended. Cause: " + valueOrElse(getString(this, kCause), "the cause wasn't specified")))
629+ else suspend("Paused by admin"))
560630
561631
562632
563633 @Callable(i)
564-func exchange (estimatedAmountToReceive,minAmountToReceive) = {
565- let $t02208622161 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
566- let pmtAmount = $t02208622161._1
567- let pmtAssetId = $t02208622161._2
568- if (!(isActive))
569- then throwIsInactive()
570- else if ((0 >= estimatedAmountToReceive))
571- then throw(("Estimated amount must be positive. Actual: " + toString(estimatedAmountToReceive)))
572- else if ((minAmountToReceive > estimatedAmountToReceive))
573- then throw(((("Minimal amount can't be greater than estimated. Estimated: " + toString(estimatedAmountToReceive)) + ". Minimal: ") + toString(minAmountToReceive)))
574- else if ((size(i.payments) != 1))
575- then throw("One attached payment expected")
576- else if (!(hasEnoughBalance))
577- then ([ScriptTransfer(i.caller, pmtAmount, pmtAssetId)] ++ suspendSuspicious())
578- else if (if ((pmtAssetId != assetIdA))
579- then (pmtAssetId != assetIdB)
580- else false)
581- then throwAssets()
582- else if ((10000000 > pmtAmount))
583- then throw("Only swap of 10.000000 or more tokens is allowed")
584- else if (if ((exchangeRatioLimitMin > fraction(scale8, minAmountToReceive, pmtAmount)))
585- then true
586- else (fraction(scale8, estimatedAmountToReceive, pmtAmount) > exchangeRatioLimitMax))
587- then throw("Incorrect args and pmt ratio")
588- else {
589- let sendAssetId = if ((pmtAssetId == assetIdA))
590- then assetIdB
591- else assetIdA
592- let amount = calculateSendAmount(estimatedAmountToReceive, minAmountToReceive, pmtAmount, pmtAssetId)
593- let governanceReward = fraction(amount, feeGovernance, feeScale6)
594- let amountMinusFee = fraction(amount, (feeScale6 - fee), feeScale6)
595- let $t02358323845 = if ((pmtAssetId == assetIdA))
596- then $Tuple2((balanceA + pmtAmount), ((balanceB - amountMinusFee) - governanceReward))
597- else $Tuple2(((balanceA - amountMinusFee) - governanceReward), (balanceB + pmtAmount))
598- let newBalanceA = $t02358323845._1
599- let newBalanceB = $t02358323845._2
600- let dAppThresholdAmount = fraction((newBalanceA + newBalanceB), dAppThreshold, (2 * dAppThresholdScale2))
601- if (if ((dAppThresholdAmount > newBalanceA))
602- then true
603- else (dAppThresholdAmount > newBalanceB))
604- then throwThreshold(dAppThresholdAmount, newBalanceA, newBalanceB)
605- else if (if (if ((assetIdA == USDN))
606- then (sendAssetId == assetIdA)
607- else false)
608- then (stakedAmountUSDN >= newBalanceA)
609- else false)
610- then throwInsufficientAvailableBalance(amountMinusFee, availableBalanceA, assetNameA)
611- else if (if (if ((assetIdB == USDN))
612- then (sendAssetId == assetIdB)
613- else false)
614- then (stakedAmountUSDN >= newBalanceB)
615- else false)
616- then throwInsufficientAvailableBalance(amountMinusFee, availableBalanceB, assetNameB)
617- else [IntegerEntry(kBalanceA, newBalanceA), IntegerEntry(kBalanceB, newBalanceB), IntegerEntry(kInvariant, invariantCalc(newBalanceA, newBalanceB)), ScriptTransfer(i.caller, amountMinusFee, sendAssetId), ScriptTransfer(walletAddress, governanceReward, sendAssetId)]
618- }
619- }
634+func activate () = valueOrElse(isAdminCall(i), if (active)
635+ then throwIsActive()
636+ else [BooleanEntry(kActive, true), DeleteEntry(kCause)])
620637
621638
622639
623640 @Callable(i)
624-func shutdown () = if (!(isActive))
625- then throw(("DApp is already suspended. Cause: " + valueOrElse(getString(this, kCause), "the cause wasn't specified")))
626- else if (!(containsElement([adminPubKey1, adminPubKey2, adminPubKey3, admStartStop], i.callerPublicKey)))
627- then throwOnlyAdmin()
628- else suspend("Paused by admin")
641+func takeIntoAccountExtraFunds () = valueOrElse(isActive(), {
642+ let amountEnrollA = (accountBalanceWithStakedA - balanceA)
643+ let amountEnrollB = (accountBalanceWithStakedB - balanceB)
644+ let invariantNew = invariantCalc((balanceA + amountEnrollA), (balanceB + amountEnrollB))
645+ if ((i.caller != walletAddress))
646+ then throw("Only the wallet can call this function")
647+ else if (if ((0 > amountEnrollA))
648+ then true
649+ else (0 > amountEnrollB))
650+ then suspend("Enroll amount negative")
651+ else if (if ((amountEnrollA == 0))
652+ then (amountEnrollB == 0)
653+ else false)
654+ then throw("No money to take")
655+ else {
656+ let stake1 = if (if (containsElement(stakingAssets, strAssetIdA))
657+ then (amountEnrollA > 0)
658+ else false)
659+ then invoke(this, "stakeUnstake", [true, amountEnrollA, strAssetIdA], nil)
660+ else 0
661+ if ((stake1 == stake1))
662+ then {
663+ let stake2 = if (if (containsElement(stakingAssets, strAssetIdB))
664+ then (amountEnrollB > 0)
665+ else false)
666+ then invoke(this, "stakeUnstake", [true, amountEnrollB, strAssetIdB], nil)
667+ else 0
668+ if ((stake2 == stake2))
669+ then [IntegerEntry(kInvariant, invariantNew), IntegerEntry(kBalanceA, (balanceA + amountEnrollA)), IntegerEntry(kBalanceB, (balanceB + amountEnrollB)), IntegerEntry(("last_income_" + strAssetIdA), amountEnrollA), IntegerEntry(("last_income_" + strAssetIdB), amountEnrollB)]
670+ else throw("Strict value is not equal to itself.")
671+ }
672+ else throw("Strict value is not equal to itself.")
673+ }
674+ })
629675
630676
631677
632678 @Callable(i)
633-func activate () = if (isActive)
634- then throwIsActive()
635- else if (!(containsElement([adminPubKey1, adminPubKey2, adminPubKey3, admStartStop], i.callerPublicKey)))
636- then throwOnlyAdmin()
637- else [BooleanEntry(kActive, true), DeleteEntry(kCause)]
638-
639-
640-
641-@Callable(i)
642-func enableFirstHarvest () = [BooleanEntry(kFirstHarvest, true), IntegerEntry(kFirstHarvestHeight, (startHeight + (firstHarvestEndPeriod * periodLength)))]
643-
644-
645-
646-@Callable(i)
647-func takeIntoAccountExtraFunds (amountLeave) = {
648- let uncountableA = (accountBalanceWithStakedA - balanceA)
649- let uncountableB = (accountBalanceWithStakedB - balanceB)
650- let amountEnrollA = (uncountableA - (if ((assetIdA == unit))
651- then amountLeave
652- else 0))
653- let amountEnrollB = (uncountableB - (if ((assetIdB == unit))
654- then amountLeave
655- else 0))
656- let invariantNew = invariantCalc((balanceA + amountEnrollA), (balanceB + amountEnrollB))
657- if (!(isActive))
658- then throwIsInactive()
659- else if ((i.caller != this))
660- then throwOnlyAdmin()
661- else if ((0 > amountLeave))
662- then throw(("Argument 'amountLeave' cannot be negative. Actual: " + toString(amountLeave)))
663- else if (if ((0 > uncountableA))
664- then true
665- else (0 > uncountableB))
666- then suspend("Enroll amount negative")
667- else if (if ((0 > amountEnrollA))
668- then true
669- else (0 > amountEnrollB))
670- then throw("Too large amountLeave")
671- else [IntegerEntry(kInvariant, invariantNew), IntegerEntry(kBalanceA, (balanceA + amountEnrollA)), IntegerEntry(kBalanceB, (balanceB + amountEnrollB)), IntegerEntry(("last_income_" + strAssetIdA), amountEnrollA), IntegerEntry(("last_income_" + strAssetIdB), amountEnrollB)]
672- }
679+func stakeUnstake (stake,amount,assetIdString) = if ((i.caller != this))
680+ then throw("Only contract itself can invoke this function")
681+ else {
682+ let $t02595826061 = calcStakingParams(stake, amount, fromBase58String(assetIdString))
683+ let call = $t02595826061._1
684+ let addr = $t02595826061._2
685+ let params = $t02595826061._3
686+ let payments = $t02595826061._4
687+ let inv = invoke(addr, call, params, payments)
688+ if ((inv == inv))
689+ then nil
690+ else throw("Strict value is not equal to itself.")
691+ }
673692
674693
675694 @Verifier(tx)
676695 func verify () = {
677696 let multiSignedByAdmins = {
678697 let adminPubKey1Signed = if (sigVerify(tx.bodyBytes, tx.proofs[0], adminPubKey1))
679698 then 1
680699 else 0
681700 let adminPubKey2Signed = if (sigVerify(tx.bodyBytes, tx.proofs[1], adminPubKey2))
682701 then 1
683702 else 0
684703 let adminPubKey3Signed = if (sigVerify(tx.bodyBytes, tx.proofs[2], adminPubKey3))
685704 then 1
686705 else 0
687706 (((adminPubKey1Signed + adminPubKey2Signed) + adminPubKey3Signed) >= 2)
688707 }
689708 match tx {
690709 case inv: InvokeScriptTransaction =>
691710 let callTakeIntoAccount = if ((inv.dApp == this))
692711 then (inv.function == "takeIntoAccountExtraFunds")
693712 else false
694- let callEnableFirstHarvest = if ((inv.dApp == this))
695- then (inv.function == "enableFirstHarvest")
696- else false
697- let callStaking = if ((inv.dApp == stakingAddress))
698- then if (if (if ((inv.function == "lockNeutrino"))
699- then (size(inv.payments) == 1)
700- else false)
701- then (inv.payments[0].assetId == USDN)
702- else false)
703- then true
704- else if ((inv.function == "unlockNeutrino"))
705- then (size(inv.payments) == 0)
706- else false
707- else false
708- let exchangeToWaves = if (if (if ((inv.dApp == USDNToWavesExchanger))
709- then (inv.function == "exchange")
710- else false)
711- then (assetIdA == USDN)
712- else false)
713- then true
714- else if (if ((assetIdB == USDN))
715- then (size(inv.payments) == 1)
716- else false)
717- then (inv.payments[0].assetId == USDN)
718- else false
719713 let signedByAdmin = if (if (if (sigVerify(tx.bodyBytes, tx.proofs[0], adminPubKey1))
720714 then true
721715 else sigVerify(tx.bodyBytes, tx.proofs[0], adminPubKey2))
722716 then true
723717 else sigVerify(tx.bodyBytes, tx.proofs[0], adminPubKey3))
724718 then true
725719 else sigVerify(tx.bodyBytes, tx.proofs[0], admStaking)
726- if (if (if (if (if (callTakeIntoAccount)
727- then true
728- else callEnableFirstHarvest)
729- then true
730- else callStaking)
731- then true
732- else exchangeToWaves)
720+ if (if (callTakeIntoAccount)
733721 then signedByAdmin
734722 else false)
735723 then true
736724 else multiSignedByAdmins
737725 case _ =>
738726 multiSignedByAdmins
739727 }
740728 }
741729

github/deemru/w8io/169f3d6 
99.27 ms