tx · F8nF3fqiPxFb8dqYxXqkZLHnqG3eGug9kpPvQTUBEiCQ

3N43aBk5aqHBop72haz2xQTTv9ATSmR4UEL:  -0.01400000 Waves

2022.01.18 13:59 [1884289] smart account 3N43aBk5aqHBop72haz2xQTTv9ATSmR4UEL > SELF 0.00000000 Waves

{ "type": 13, "id": "F8nF3fqiPxFb8dqYxXqkZLHnqG3eGug9kpPvQTUBEiCQ", "fee": 1400000, "feeAssetId": null, "timestamp": 1642503571845, "version": 2, "chainId": 84, "sender": "3N43aBk5aqHBop72haz2xQTTv9ATSmR4UEL", "senderPublicKey": "CDcEP1otXnBCVTs5MNPuC1q1bxR3CETiDTb5diL4TZna", "proofs": [ "67JEk12Vb9kbyitnTBEVop4H7PDqWksrHKCMHScbH7UscgnjiHiKyynWey5AyoPjHw8owMVjzqVPYmUedrKJuEv8", "5oQfG4d83zFhMdx45XdSCWxBmffz85NYJgzPwaP93ikjhXyvHy5uc9XkegEhtUj7kceGjec4DuhToAr253FVkemY" ], "script": "base64:AAIFAAAAAAAAACYIAhIAEgMKAQESBAoCAQESABIECgIBARIAEgASABIFCgMEAQgSAAAAAFEAAAAAB3ZlcnNpb24CAAAABTIuMC4wAAAAAAhrVmVyc2lvbgIAAAAHdmVyc2lvbgAAAAAHa0FjdGl2ZQIAAAAGYWN0aXZlAAAAAAlrQXNzZXRJZEECAAAACkFfYXNzZXRfaWQAAAAACWtBc3NldElkQgIAAAAKQl9hc3NldF9pZAAAAAAJa0JhbGFuY2VBAgAAAA9BX2Fzc2V0X2JhbGFuY2UAAAAACWtCYWxhbmNlQgIAAAAPQl9hc3NldF9iYWxhbmNlAAAAAA1rU2hhcmVBc3NldElkAgAAAA5zaGFyZV9hc3NldF9pZAAAAAARa1NoYXJlQXNzZXRTdXBwbHkCAAAAEnNoYXJlX2Fzc2V0X3N1cHBseQAAAAAEa0ZlZQIAAAAKY29tbWlzc2lvbgAAAAASa0ZlZVNjYWxlRGVsaW1pdGVyAgAAABpjb21taXNzaW9uX3NjYWxlX2RlbGltaXRlcgAAAAAKa0ludmFyaWFudAIAAAAJaW52YXJpYW50AAAAAAZrQ2F1c2UCAAAADnNodXRkb3duX2NhdXNlAAAAABJrZXlVU0ROTlNCVEFkZHJlc3MCAAAAGHN0YWtpbmdfdXNkbm5zYnRfYWRkcmVzcwAAAAAOa2V5RVVSTkFkZHJlc3MCAAAAFHN0YWtpbmdfZXVybl9hZGRyZXNzAAAAAA9rZXlBZG1pblB1YktleTECAAAAC2FkbWluX3B1Yl8xAAAAAA9rZXlBZG1pblB1YktleTICAAAAC2FkbWluX3B1Yl8yAAAAAA9rZXlBZG1pblB1YktleTMCAAAAC2FkbWluX3B1Yl8zAAAAABRVU0ROVG9XYXZlc0V4Y2hhbmdlcgkBAAAAB0FkZHJlc3MAAAABAQAAABoBVMqWqf/XBTJ3J/JFLr/QiofqrY4qyL+FtAAAAAAGb3JhY2xlCQEAAAAHQWRkcmVzcwAAAAEBAAAAGgFU6UWqHpAvOq7xug7mLpqSXxqYhOHzYrMIAQAAAAtnZXRBZG1pblB1YgAAAAEAAAALa2V5QWRtaW5QdWIEAAAAByRtYXRjaDAJAAQdAAAAAgUAAAAGb3JhY2xlBQAAAAtrZXlBZG1pblB1YgMJAAABAAAAAgUAAAAH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AA1zbGlwcGFnZVZhbHVlCQAAZQAAAAIFAAAABnNjYWxlOAkAAGkAAAACCQAAaAAAAAIFAAAABnNjYWxlOAAAAAAAAAAAAQAAAAAAAJiWgAQAAAAeZGVsdGFCZXR3ZWVuTWF4QW5kTWluU2VuZFZhbHVlCQAAZQAAAAIFAAAAFWFtb3VudFRvU2VuZEVzdGltYXRlZAUAAAAVbWluVG9rZW5SZWNlaXZlQW1vdW50BAAAAAF4CQAAZAAAAAIFAAAACGJhbGFuY2VBBQAAABJ0b2tlblJlY2VpdmVBbW91bnQEAAAAAXkJAABkAAAAAgUAAAAIYmFsYW5jZUIFAAAAEnRva2VuUmVjZWl2ZUFtb3VudAQAAAAMaW52YXJpYW50TmV3AwkAAAAAAAACBQAAAAd0b2tlbklkBQAAAAhhc3NldElkQQkBAAAADWludmFyaWFudENhbGMAAAACBQAAAAF4CQAAZQAAAAIFAAAACGJhbGFuY2VCBQAAABVhbW91bnRUb1NlbmRFc3RpbWF0ZWQDCQAAAAAAAAIFAAAAB3Rva2VuSWQFAAAACGFzc2V0SWRCCQEAAAANaW52YXJpYW50Q2FsYwAAAAIJAABlAAAAAgUAAAAIYmFsYW5jZUEFAAAAFWFtb3VudFRvU2VuZEVzdGltYXRlZAUAAAABeQkAAAIAAAABAgAAABZXcm9uZyBhc3NldCBpbiBwYXltZW50BAAAABdpbnZhcmlhbnRFc3RpbWF0ZWRSYXRpbwkAAGsAAAADBQAAAAZzY2FsZTgFAAAACWludmFyaWFudAUAAAAMaW52YXJpYW50TmV3CgEAAAANZ2V0U3RlcEFtb3VudAAAAAIAAAADYWNjAAAABHN0ZXADCQAAAAAAAAIFAAAAA2FjYwD//////////wQAAAAMYW1vdW50VG9TZW5kCQAAZQAAAAIFAAAAFWFtb3VudFRvU2VuZEVzdGltYXRlZAkAAGkAAAACCQAAaAAAAAIFAAAABHN0ZXAFAAAAHmRlbHRhQmV0d2Vlbk1heEFuZE1pblNlbmRWYWx1ZQAAAAAAAAAABQQAAAANc3RlcEludmFyaWFudAMJAAAAAAAAAgUAAAAHdG9rZW5JZAUAAAAIYXNzZXRJZEEJAQAAAA1pbnZhcmlhbnRDYWxjAAAAAgUAAAABeAkAAGUAAAACBQAA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bnRlZ2VyRW50cnkAAAACBQAAABFrU2hhcmVBc3NldFN1cHBseQUAAAASc2hhcmVJbml0aWFsU3VwcGx5CQAETAAAAAIJAQAAAA5TY3JpcHRUcmFuc2ZlcgAAAAMIBQAAAAFpAAAABmNhbGxlcgUAAAASc2hhcmVJbml0aWFsU3VwcGx5BQAAAAxzaGFyZUlzc3VlSWQFAAAAA25pbAkAAAIAAAABAgAAACRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAACAAAAAQIAAAAkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAAAAAWkBAAAAFnJlcGxlbmlzaFdpdGhUd29Ub2tlbnMAAAABAAAAEXNsaXBwYWdlVG9sZXJhbmNlBAAAAAtwbXRBc3NldElkQQgJAAGRAAAAAggFAAAAAWkAAAAIcGF5bWVudHMAAAAAAAAAAAAAAAAHYXNzZXRJZAQAAAALcG10QXNzZXRJZEIICQABkQAAAAIIBQAAAAFpAAAACHBheW1lbnRzAAAAAAAAAAABAAAAB2Fzc2V0SWQEAAAACnBtdEFtb3VudEEICQABkQAAAAIIBQAAAAFpAAAACHBheW1lbnRzAAAAAAAAAAAAAAAABmFtb3VudAQAAAAKcG10QW1vdW50QggJAAGRAAAAAggFAAAAAWkAAAAIcGF5bWVudHMAAAAAAAAAAAEAAAAGYW1vdW50BAAAAA0kdDAxMTkyMTExOTk4CQEAAAAMZ2V0QXNzZXRJbmZvAAAAAQUAAAALcG10QXNzZXRJZEEEAAAADnBtdFN0ckFzc2V0SWRBCAUAAAANJHQwMTE5MjExMTk5OAAAAAJfMQQAAAANcG10QXNzZXROYW1lQQgFAAAADSR0MDExOTIxMTE5OTgAAAACXzIEAAAADHBtdERlY2ltYWxzQQgFAAAADSR0MDExOTIxMTE5OTgAAAACXzMEAAAADSR0MDEyMDAzMTIxOTcJAQAAAAxnZXRBc3NldEluZm8AAAABBQAAAAtwbXRBc3NldElkQgQAAAAOcG10U3RyQXNzZXRJZEIIBQAAAA0kdDAxMjAwMzEyMTk3AAAAAl8xBAAAAA1wbXRBc3NldE5hbWVCCAUAAAANJHQwMTIwMDMxMjE5NwAAAAJfMgQAAAAMcG10RGVjaW1hbHNCCAUAAAANJHQwMTIwMDMxMjE5NwAAAAJfMwQAAAAKdG9rZW5SYXRpbwkAAGsAAAADCQAAawAAAAMFAAAABnNjYWxlOAUAAAAIYmFsYW5jZUEFAAAACnBtdEFtb3VudEEFAAAABnNjYWxlMwkAAGsAAAADBQAAAAZzY2FsZTgFAAAACGJhbGFuY2VCBQAAAApwbXRBbW91bnRCBAAAABNyYXRpb1NoYXJlVG9rZW5zSW5BCQAAawAAAAMFAAAABnNjYWxlOAUAAAAKcG10QW1vdW50QQUAAAAIYmFsYW5jZUEEAAAAE3JhdGlvU2hhcmVUb2tlbnNJbkIJAABrAAAAAwUAAAAGc2NhbGU4BQAAAApwbXRBbW91bnRCBQAAAAhiYWxhbmNlQgQAAAAVc2hhcmVUb2tlblRvUGF5QW1vdW50CQAAawAAAAMJAAGXAAAAAQkABEwAAAACBQAAABNyYXRpb1NoYXJlVG9rZW5zSW5BCQAETAAAAAIFAAAAE3JhdGlvU2hhcmVUb2tlbnNJbkIFAAAAA25pbAUAAAAQc2hhcmVBc3NldFN1cHBseQUAAAAGc2NhbGU4BAAAABNpbnZhcmlhbnRDYWxjdWxhdGVkCQEAAAANaW52YXJpYW50Q2FsYwAAAAIJAABkAAAAAgUAAAAIYmFsYW5jZUEFAAAACnBtdEFtb3VudEEJAABkAAAAAgUAAAAIYmFsYW5jZUIFAAAACnBtdEFtb3VudEIDCQEAAAABIQAAAAEFAAAACGlzQWN0aXZlCQEAAAAPdGhyb3dJc0luYWN0aXZlAAAAAAMDCQAAZgAAAAIAAAAAAAAAAAAFAAAAEXNsaXBwYWdlVG9sZXJhbmNlBgkAAGYAAAACBQAAABFzbGlwcGFnZVRvbGVyYW5jZQAAAAAAAAAACgkAAAIAAAABAgAAACBTbGlwcGFnZSB0b2xlcmFuY2UgbXVzdCBiZSA8PSAxJQMJAQAAAAIhPQAAAAIJAAGQAAAAAQgFAAAAAWkAAAAIcGF5bWVudHMAAAAAAAAAAAIJAAACAAAAAQIAAAAcVHdvIGF0dGFjaGVkIGFzc2V0cyBleHBlY3RlZAMDCQEAAAACIT0AAAACBQAAAAtwbXRBc3NldElkQQUAAAAIYXNzZXRJZEEGCQEAAAACIT0AAAACBQAAAAtwbXRBc3NldElkQgUAAAAIYXNzZXRJZEIJAQAAAAt0aHJvd0Fzc2V0cwAAAAADAwkAAGYAAAACCQAAaQAAAAIJAABoAAAAAgUAAAAGc2NhbGUzCQAAZQAAAAIFAAAADnNsaXBwYWdlU2NhbGUzBQAAABFzbGlwcGFnZVRvbGVyYW5jZQUAAAAOc2xpcHBhZ2VTY2FsZTMFAAAACnRva2VuUmF0aW8GCQAAZgAAAAIFAAAACnRva2VuUmF0aW8JAABpAAAAAgkAAGgAAAACBQAAAAZzY2FsZTMJAABkAAAAAgUAAAAOc2xpcHBhZ2VTY2FsZTMFAAAAEXNsaXBwYWdlVG9sZXJhbmNlBQAAAA5zbGlwcGFnZVNjYWxlMwkAAAIAAAABAgAAAD1JbmNvcnJlY3QgYXNzZXRzIGFtb3VudDogYW1vdW50cyBtdXN0IGhhdmUgdGhlIGNvbnRyYWN0IHJhdGlvAwkAAAAAAAACBQAAABVzaGFyZVRva2VuVG9QYXlBbW91bnQAAAAAAAAAAAAJAAACAAAAAQIAAAAdVG9vIHNtYWxsIGFtb3VudCB0byByZXBsZW5pc2gDCQEAAAABIQAAAAEFAAAAEGhhc0Vub3VnaEJhbGFuY2UJAAROAAAAAgkABEwAAAACCQEAAAAOU2NyaXB0VHJhbnNmZXIAAAADCAUAAAABaQAAAAZjYWxsZXIFAAAACnBtdEFtb3VudEEFAAAAC3BtdEFzc2V0SWRBCQAETAAAAAIJAQAAAA5TY3JpcHRUcmFuc2ZlcgAAAAMIBQAAAAFpAAAABmNhbGxlcgUAAAAKcG10QW1vdW50QgUAAAALcG10QXNzZXRJZEIFAAAAA25pbAkBAAAAEXN1c3BlbmRTdXNwaWNpb3VzAAAAAAQAAAAGc3Rha2UxAwkBAAAAD2NvbnRhaW5zRWxlbWVudAAAAAIFAAAADXN0YWtpbmdBc3NldHMFAAAADnBtdFN0ckFzc2V0SWRBCQAD/AAAAAQFAAAABHRoaXMCAAAADHN0YWtlVW5zdGFrZQkABEwAAAACBgkABEwAAAACBQAAAApwbXRBbW91bnRBCQAETAAAAAIFAAAADnBtdFN0ckFzc2V0SWRBBQAAAANuaWwFAAAAA25pbAAAAAAAAAAAAAMJAAAAAAAAAgUAAAAGc3Rha2UxBQAAAAZzdGFrZTEEAAAABnN0YWtlMgMJAQAAAA9jb250YWluc0VsZW1lbnQAAAACBQAAAA1zdGFraW5nQXNzZXRzBQAAAA5wbXRTdHJBc3NldElkQgkAA/wAAAAEBQAAAAR0aGlzAgAAAAxzdGFrZVVuc3Rha2UJAARMAAAAAgYJAARMAAAAAgUAAAAKcG10QW1vdW50QgkABEwAAAACBQAAAA5wbXRTdHJBc3NldElkQgUAAAADbmlsBQAAAANuaWwAAAAAAAAAAAADCQAAAAAAAAIFAAAABnN0YWtlMgUAAAAGc3Rha2UyCQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACBQAAAAlrQmFsYW5jZUEJAABkAAAAAgUAAAAIYmFsYW5jZUEFAAAACnBtdEFtb3VudEEJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAIFAAAACWtCYWxhbmNlQgkAAGQAAAACBQAAAAhiYWxhbmNlQgUAAAAKcG10QW1vdW50QgkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgUAAAARa1NoYXJlQXNzZXRTdXBwbHkJAABkAAAAAgUAAAAQc2hhcmVBc3NldFN1cHBseQUAAAAVc2hhcmVUb2tlblRvUGF5QW1vdW50CQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACBQAAAAprSW52YXJpYW50BQAAABNpbnZhcmlhbnRDYWxjdWxhdGVkCQAETAAAAAIJAQAAAAdSZWlzc3VlAAAAAwUAAAAMc2hhcmVBc3NldElkBQAAABVzaGFyZVRva2VuVG9QYXlBbW91bnQGCQAETAAAAAIJAQAAAA5TY3JpcHRUcmFuc2ZlcgAAAAMIBQAAAAFpAAAABmNhbGxlcgUAAAAVc2hhcmVUb2tlblRvUGF5QW1vdW50BQAAAAxzaGFyZUFzc2V0SWQFAAAAA25pbAkAAAIAAAABAgAAACRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAACAAAAAQIAAAAkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAAAAAWkBAAAAFXJlcGxlbmlzaFdpdGhPbmVUb2tlbgAAAAIAAAATdmlydHVhbFN3YXBUb2tlblBheQAAABN2aXJ0dWFsU3dhcFRv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AAcFAAAAE3ZpcnR1YWxTd2FwVG9rZW5HZXQJAABlAAAAAgUAAAAJcG10QW1vdW50BQAAABN2aXJ0dWFsU3dhcFRva2VuUGF5CQAAZQAAAAIFAAAACGJhbGFuY2VBBQAAABN2aXJ0dWFsU3dhcFRva2VuR2V0CQAAZAAAAAIFAAAACGJhbGFuY2VCBQAAABN2aXJ0dWFsU3dhcFRva2VuUGF5CQEAAAANaW52YXJpYW50Q2FsYwAAAAIFAAAACGJhbGFuY2VBCQAAZAAAAAIFAAAACGJhbGFuY2VCBQAAAAlwbXRBbW91bnQFAAAACGJhbGFuY2VBCQAAZAAAAAIFAAAACGJhbGFuY2VCBQAAAAlwbXRBbW91bnQEAAAAEXZpcnR1YWxSZXBsZW5pc2hBCAUAAAANJHQwMTU2NjExNjQyNgAAAAJfMQQAAAARdmlydHVhbFJlcGxlbmlzaEIIBQAAAA0kdDAxNTY2MTE2NDI2AAAAAl8yBAAAABFiYWxhbmNlQWZ0ZXJTd2FwQQgFAAAADSR0MDE1NjYxMTY0MjYAAAACXzMEAAAAEWJhbGFuY2VBZnRlclN3YXBCCAUAAAANJHQwMTU2NjExNjQyNgAAAAJfNAQAAAATaW52YXJpYW50Q2FsY3VsYXRlZAgFAAAADSR0MDE1NjYxMTY0MjYAAAACXzUEAAAAC25ld0JhbGFuY2VBCAUAAAANJHQwMTU2NjExNjQyNgAAAAJfNgQAAAALbmV3QmFsYW5jZUIIBQAAAA0kdDAxNTY2MTE2NDI2AAAAAl83BAAAAA9uZXdCYWxhbmNlRW50cnkDCQAAAAAAAAIFAAAACnBtdEFzc2V0SWQFAAAACGFzc2V0SWRBCQEAAAAMSW50ZWdlckVudHJ5AAAAAgUAAAAJa0JhbGFuY2VBBQAAAAtuZXdCYWxhbmNlQQkBAAAADEludGVnZXJFbnRyeQAAAAIFAAAACWtCYWxhbmNlQgUAAAALbmV3QmFsYW5jZUIEAAAADGludmFyaWFudE5ldwkBAAAADWludmFyaWFudENhbGMAAAACBQAAABFiYWxhbmNlQWZ0ZXJTd2FwQQUAAAARYmFsYW5jZUFmdGVyU3dhcEIEAAAAF2ludmFyaWFudEVzdGltYXRlZFJhdGlvCQAAawAAAAMFAAAABnNjYWxlOAUAAAAJaW52YXJpYW50BQAAAAxpbnZhcmlhbnROZXcEAAAAJXJhdGlvVmlydHVhbEJhbGFuY2VUb1ZpcnR1YWxSZXBsZW5pc2gJAABpAAAAAgkAAGsAAAADCQAAaAAAAAIFAAAABnNjYWxlOAUAAAAGc2NhbGU4BQAAABFiYWxhbmNlQWZ0ZXJTd2FwQQUAAAARYmFsYW5jZUFmdGVyU3dhcEIJAABrAAAAAwUAAAAGc2NhbGU4BQAAABF2aXJ0dWFsUmVwbGVuaXNoQQUAAAARdmlydHVhbFJlcGxlbmlzaEIEAAAAE2RBcHBUaHJlc2hvbGRBbW91bnQJAABrAAAAAwkAAGQAAAACBQAAAAtuZXdCYWxhbmNlQQUAAAALbmV3QmFsYW5jZUIFAAAADWRBcHBUaHJlc2hvbGQJAABoAAAAAgAAAAAAAAAAAgUAAAATZEFwcFRocmVzaG9sZFNjYWxlMgMDCQAAZwAAAAIFAAAAF3NsaXBwYWdlVmFsdWVNaW5Gb3JTd2FwBQAAABdpbnZhcmlhbnRFc3RpbWF0ZWRSYXRpbwYJAABmAAAAAgUAAAAJaW52YXJpYW50BQAAAAxpbnZhcmlhbnROZXcJAAACAAAAAQIAAAA6SW5jb3JyZWN0IHZpcnR1YWxTd2FwVG9rZW5QYXkgb3IgdmlydHVhbFN3YXBUb2tlbkdldCB2YWx1ZQMDCQAAZgAAAAIFAAAAHHNsaXBwYWdlVmFsdWVNaW5Gb3JSZXBsZW5pc2gFAAAAJXJhdGlvVmlydHVhbEJhbGFuY2VUb1ZpcnR1YWxSZXBsZW5pc2gGCQAAZgAAAAIFAAAAJXJhdGlvVmlydHVhbEJhbGFuY2VUb1ZpcnR1YWxSZXBsZW5pc2gFAAAAHHNsaXBwYWdlVmFsdWVNYXhGb3JSZXBsZW5pc2gJAAACAAAAAQIAAABsU3dhcCB3aXRoIHZpcnR1YWxTd2FwVG9rZW5QYXkgYW5kIHZpcnR1YWxTd2FwVG9rZW5HZXQgaXMgcG9zc2libGUsIGJ1dCByYXRpbyBhZnRlciB2aXJ0dWFsIHN3YXAgaXMgaW5jb3JyZWN0AwMJAABmAAAAAgUAAAATZEFwcFRocmVzaG9sZEFtb3VudAUAAAALbmV3QmFsYW5jZUEGCQAAZgAAAAIFAAAAE2RBcHBUaHJlc2hvbGRBbW91bnQFAAAAC25ld0JhbGFuY2VCCQEAAAAOdGhyb3dUaHJlc2hvbGQAAAADBQAAABNkQXBwVGhyZXNob2xkQW1vdW50BQAAAAtuZXdCYWxhbmNlQQUAAAALbmV3QmFsYW5jZUIEAAAABnN0YWtlMQMJAQAAAA9jb250YWluc0VsZW1lbnQAAAACBQAAAA1zdGFraW5nQXNzZXRzBQAAAA1wbXRTdHJBc3NldElkCQAD/AAAAAQFAAAABHRoaXMCAAAADHN0YWtlVW5zdGFrZQkABEwAAAACBgkABEwAAAACBQAAAAlwbXRBbW91bnQJAARMAAAAAgUAAAANcG10U3RyQXNzZXRJZAUAAAADbmlsBQAAAANuaWwAAAAAAAAAAAADCQAAAAAAAAIFAAAABnN0YWtlMQUAAAAGc3Rha2UxBAAAABNyYXRpb1NoYXJlVG9rZW5zSW5BCQAAawAAAAMFAAAAEXZpcnR1YWxSZXBsZW5pc2hBBQAAAAZzY2FsZTgFAAAAEWJhbGFuY2VBZnRlclN3YXBBBAAAABNyYXRpb1NoYXJlVG9rZW5zSW5CCQAAawAAAAMFAAAAEXZpcnR1YWxSZXBsZW5pc2hCBQAAAAZzY2FsZTgFAAAAEWJhbGFuY2VBZnRlclN3YXBCBAAAABVzaGFyZVRva2VuVG9QYXlBbW91bnQJAABrAAAAAwkAAZcAAAABCQAETAAAAAIFAAAAE3JhdGlvU2hhcmVUb2tlbnNJbkEJAARMAAAAAgUAAAATcmF0aW9TaGFyZVRva2Vuc0luQgUAAAADbmlsBQAAABBzaGFyZUFzc2V0U3VwcGx5BQAAAAZzY2FsZTgJAARMAAAAAgkBAAAAB1JlaXNzdWUAAAADBQAAAAxzaGFyZUFzc2V0SWQFAAAAFXNoYXJlVG9rZW5Ub1BheUFtb3VudAYJAARMAAAAAgkBAAAADlNjcmlwdFRyYW5zZmVyAAAAAwgFAAAAAWkAAAAGY2FsbGVyBQAAABVzaGFyZVRva2VuVG9QYXlBbW91bnQFAAAADHNoYXJlQXNzZXRJZAkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgUAAAARa1NoYXJlQXNzZXRTdXBwbHkJAABkAAAAAgUAAAAQc2hhcmVBc3NldFN1cHBseQUAAAAVc2hhcmVUb2tlblRvUGF5QW1v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AAprSW52YXJpYW50BQAAABNpbnZhcmlhbnRDYWxjdWxhdGVkCQAETAAAAAIJAQAAAARCdXJuAAAAAgUAAAAMc2hhcmVBc3NldElkBQAAAAlwbXRBbW91bnQJAARMAAAAAgkBAAAADlNjcmlwdFRyYW5zZmVyAAAAAwgFAAAAAWkAAAAGY2FsbGVyBQAAAAxhbW91bnRUb1BheUEFAAAACGFzc2V0SWRBCQAETAAAAAIJAQAAAA5TY3JpcHRUcmFuc2ZlcgAAAAMIBQAAAAFpAAAABmNhbGxlcgUAAAAMYW1vdW50VG9QYXlCBQAAAAhhc3NldElkQgUAAAADbmlsCQAAAgAAAAECAAAAJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAAIAAAABAgAAACRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4AAAABaQEAAAAIZXhjaGFuZ2UAAAACAAAAGGVzdGltYXRlZEFtb3VudFRvUmVjZWl2ZQAAABJtaW5BbW91bnRUb1JlY2VpdmUEAAAADSR0MDIwMzA5MjAzODQJAAUUAAAAAggJAAGRAAAAAggFAAAAAWkAAAAIcGF5bWVudHMAAAAAAAAAAAAAAAAGYW1vdW50CAkAAZEAAAACCAUAAAABaQAAAAhwYXltZW50cwAAAAAAAAAAAAAAAAdhc3NldElkBAAAAAlwbXRBbW91bnQIBQAAAA0kdDAyMDMwOTIwMzg0AAAAAl8xBAAAAApwbXRBc3NldElkCAUAAAANJHQwMjAzMDkyMDM4NAAAAAJfMgMJAQAAAAEhAAAAAQUAAAAIaXNBY3RpdmUJAQAAAA90aHJvd0lzSW5hY3RpdmUAAAAAAwkAAGcAAAACAAAAAAAAAAAABQAAABhlc3RpbWF0ZWRBbW91bnRUb1JlY2VpdmUJAAACAAAAAQkAASwAAAACAgAAACtFc3RpbWF0ZWQgYW1vdW50IG11c3QgYmUgcG9zaXRpdmUuIEFjdHVhbDogCQABpAAAAAEFAAAAGGVzdGltYXRlZEFtb3VudFRvUmVjZWl2ZQMJAABmAAAAAgUAAAASbWluQW1vdW50VG9SZWNlaXZlBQAAABhlc3RpbWF0ZWRBbW91bnRUb1JlY2VpdmUJAAACAAAAAQkAASwAAAACCQABLAAAAAIJAAEsAAAAAgIAAAA7TWluaW1hbCBhbW91bnQgY2FuJ3QgYmUgZ3JlYXRlciB0aGFuIGVzdGltYXRlZC4gRXN0aW1hdGVkOiAJAAGkAAAAAQUAAAAYZXN0aW1hdGVkQW1vdW50VG9SZWNlaXZlAgAAAAsuIE1pbmltYWw6IAkAAaQAAAABBQAAABJtaW5BbW91bnRUb1JlY2VpdmUDCQEAAAACIT0AAAACCQABkAAAAAEIBQAAAAFpAAAACHBheW1lbnRzAAAAAAAAAAABCQAAAgAAAAECAAAAHU9uZSBhdHRhY2hlZCBwYXltZW50IGV4cGVjdGVkAwkBAAAAASEAAAABBQAAABBoYXNFbm91Z2hCYWxhbmNlCQAETgAAAAIJAARMAAAAAgkBAAAADlNjcmlwdFRyYW5zZmVyAAAAAwgFAAAAAWkAAAAGY2FsbGVyBQAAAAlwbXRBbW91bnQFAAAACnBtdEFzc2V0SWQFAAAAA25pbAkBAAAAEXN1c3BlbmRTdXNwaWNpb3VzAAAAAAMDCQEAAAACIT0AAAACBQAAAApwbXRBc3NldElkBQAAAAhhc3NldElkQQkBAAAAAiE9AAAAAgUAAAAKcG10QXNzZXRJZAUAAAAIYXNzZXRJZEIHCQEAAAALdGhyb3dBc3NldHMAAAAAAwkAAGYAAAACAAAAAAAAmJaABQAAAAlwbXRBbW91bnQJAAACAAAAAQIAAAAwT25seSBzd2FwIG9mIDEwLjAwMDAwMCBvciBtb3JlIHRva2VucyBpcyBhbGxvd2VkAwMJAABmAAAAAgUAAAAVZXhjaGFuZ2VSYXRpb0xpbWl0TWluCQAAawAAAAMFAAAABnNjYWxlOAUAAAASbWluQW1vdW50VG9SZWNlaXZlBQAAAAlwbXRBbW91bnQGCQAAZgAAAAIJAABrAAAAAwUAAAAGc2NhbGU4BQAAABhlc3RpbWF0ZWRBbW91bnRUb1JlY2VpdmUFAAAACXBtdEFtb3VudAUAAAAVZXhjaGFuZ2VSYXRpb0xpbWl0TWF4CQAAAgAAAAECAAAAHEluY29ycmVjdCBhcmdzIGFuZCBwbXQgcmF0aW8EAAAAC3NlbmRBc3NldElkAwkAAAAAAAACBQAAAApwbXRBc3NldElkBQAAAAhhc3NldElkQQUAAAAIYXNzZXRJZEIFAAAACGFzc2V0SWRBBAAAAAZhbW91bnQJAQAAABNjYWxjdWxhdGVTZW5kQW1vdW50AAAABAUAAAAYZXN0aW1hdGVkQW1vdW50VG9SZWNlaXZlBQAAABJtaW5BbW91bnRUb1JlY2VpdmUFAAAACXBtdEFtb3VudAUAAAAKcG10QXNzZXRJZAQAAAAQZ292ZXJuYW5jZVJld2FyZAkAAGsAAAADBQAAAAZhbW91bnQFAAAADWZlZUdvdmVybmFuY2UFAAAACWZlZVNjYWxlNgQAAAAOYW1vdW50TWludXNGZWUJAABrAAAAAwUAAAAGYW1vdW50CQAAZQAAAAIFAAAACWZlZVNjYWxlNgUAAAADZmVlBQAAAAlmZWVTY2FsZTYEAAAADSR0MDIxODA2MjIwNjgDCQAAAAAAAAIFAAAACnBtdEFzc2V0SWQFAAAACGFzc2V0SWRBCQAFFAAAAAIJAABkAAAAAgUAAAAIYmFsYW5jZUEFAAAACXBtdEFtb3VudAkAAGUAAAACCQAAZQAAAAIFAAAACGJhbGFuY2VCBQAAAA5hbW91bnRNaW51c0ZlZQUAAAAQZ292ZXJuYW5jZVJld2FyZAkABRQAAAACCQAAZQAAAAIJAABlAAAAAgUAAAAIYmFsYW5jZUEFAAAADmFtb3VudE1pbnVzRmVlBQAAABBnb3Zlcm5hbmNlUmV3YXJkCQAAZAAAAAIFAAAACGJhbGFuY2VCBQAAAAlwbXRBbW91bnQEAAAAC25ld0JhbGFuY2VBCAUAAAANJHQwMjE4MDYyMjA2OAAAAAJfMQQAAAALbmV3QmFsYW5jZUIIBQAAAA0kdDAyMTgwNjIyMDY4AAAAAl8yBAAAABNkQXBwVGhyZXNob2xkQW1vdW50CQAAawAAAAMJAABkAAAAAgUAAAALbmV3QmFsYW5jZUEFAAAAC25ld0JhbGFuY2VCBQAAAA1kQXBwVGhyZXNob2xkCQAAaAAAAAIAAAAAAAAAAAIFAAAAE2RBcHBUaHJlc2hvbGRTY2FsZTIDAwkAAGYAAAACBQAAABNkQXBwVGhyZXNob2xkQW1vdW50BQAAAAtuZXdCYWxhbmNlQQYJAABmAAAAAgUAAAATZEFwcFRocmVzaG9sZEFtb3VudAUAAAALbmV3QmFsYW5jZUIJAQAAAA50aHJvd1RocmVzaG9sZAAAAAMFAAAAE2RBcHBUaHJlc2hvbGRBbW91bnQFAAAAC25ld0JhbGFuY2VBBQAAAAtuZXdCYWxhbmNlQgQAAAANJHQwMjIzNjYyMjQzOQkBAAAADGdldEFzc2V0SW5mbwAAAAEFAAAACnBtdEFzc2V0SWQEAAAADXBtdFN0ckFzc2V0SWQIBQAAAA0kdDAyMjM2NjIyNDM5AAAAAl8xBAAAAAxwbXRBc3NldE5hbWUIBQAAAA0kdDAyMjM2NjIyNDM5AAAAAl8yBAAAAAtwbXREZWNpbWFscwgFAAAADSR0MDIyMzY2MjI0MzkAAAACXzMEAAAADSR0MDIyNDUyMjI1MjkJAQAAAAxnZXRBc3NldEluZm8AAAABBQAAAAtzZW5kQXNzZXRJZAQAAAAOc2VuZFN0ckFzc2V0SWQIBQAAAA0kdDAyMjQ1MjIyNTI5AAAAAl8xBAAAAA1zZW5kQXNzZXROYW1lCAUAAAANJHQwMjI0NTIyMjUyOQAAAAJfMgQAAAAMc2VuZERlY2ltYWxzCAUAAAANJHQwMjI0NTIyMjUyOQAAAAJfMwQAAAAGc3Rha2UxAwkBAAAAD2NvbnRhaW5zRWxlbWVudAAAAAIFAAAADXN0YWtpbmdBc3NldHMFAAAADXBtdFN0ckFzc2V0SWQJAAP8AAAABAUAAAAEdGhpcwIAAAAMc3Rha2VVbnN0YWtlCQAETAAAAAIGCQAETAAAAAIFAAAACXBtdEFtb3VudAkABEwAAAACBQAAAA1wbXRTdHJBc3NldElkBQAAAANuaWwFAAAAA25pbAAAAAAAAAAAAAMJAAAAAAAAAgUAAAAGc3Rha2UxBQAAAAZzdGFrZTEEAAAABnN0YWtlMgMJAQAAAA9jb250YWluc0VsZW1lbnQAAAACBQAAAA1zdGFraW5nQXNzZXRzBQAAAA5zZW5kU3RyQXNzZXRJZAkAA/wAAAAEBQAAAAR0aGlzAgAAAAxzdGFrZVVuc3Rha2UJAARMAAAAAgcJAARMAAAAAgkAAGQAAAACBQAAAA5hbW91bnRNaW51c0ZlZQUAAAAQZ292ZXJuYW5jZVJld2FyZAkABEwAAAACBQAAAA5zZW5kU3RyQXNzZXRJZAUAAAADbmlsBQAAAANuaWwAAAAAAAAAAAADCQAAAAAAAAIFAAAABnN0YWtlMgUAAAAGc3Rha2UyCQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACBQAAAAlrQmFsYW5jZUEFAAAAC25ld0JhbGFuY2VBCQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACBQAAAAlrQmFsYW5jZUIFAAAAC25ld0JhbGFuY2VCCQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACBQAAAAprSW52YXJpYW50CQEAAAANaW52YXJpYW50Q2FsYwAAAAIFAAAAC25ld0JhbGFuY2VBBQAAAAtuZXdCYWxhbmNlQgkABEwAAAACCQEAAAAOU2NyaXB0VHJhbnNmZXIAAAADCAUAAAABaQAAAAZjYWxsZXIFAAAADmFtb3VudE1pbnVzRmVlBQAAAAtzZW5kQXNzZXRJZAkABEwAAAACCQEAAAAOU2NyaXB0VHJhbnNmZXIAAAADBQAAAA13YWxsZXRBZGRyZXNzBQAAABBnb3Zlcm5hbmNlUmV3YXJkBQAAAAtzZW5kQXNzZXRJZAUAAAADbmlsCQAAAgAAAAECAAAAJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAAIAAAABAgAAACRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4AAAABaQEAAAAIc2h1dGRvd24AAAAAAwkBAAAAASEAAAABBQAAAAhpc0FjdGl2ZQkAAAIAAAABCQABLAAAAAICAAAAIkRBcHAgaXMgYWxyZWFkeSBzdXNwZW5kZWQuIENhdXNlOiAJAQAAAAt2YWx1ZU9yRWxzZQAAAAIJAAQdAAAAAgUAAAAEdGhpcwUAAAAGa0NhdXNlAgAAABp0aGUgY2F1c2Ugd2Fzbid0IHNwZWNpZmllZAMJAQAAAAEhAAAAAQkBAAAAD2NvbnRhaW5zRWxlbWVudAAAAAIJAARMAAAAAgUAAAAMYWRtaW5QdWJLZXkxCQAETAAAAAIFAAAADGFkbWluUHViS2V5MgkABEwAAAACBQAAAAxhZG1pblB1YktleTMJAARMAAAAAgUAAAAMYWRtU3RhcnRTdG9wBQAAAANuaWwIBQAAAAFpAAAAD2NhbGxlclB1YmxpY0tleQkBAAAADnRocm93T25seUFkbWluAAAAAAkBAAAAB3N1c3BlbmQAAAABAgAAAA9QYXVzZWQgYnkgYWRtaW4AAAABaQEAAAAIYWN0aXZhdGUAAAAAAwUAAAAIaXNBY3RpdmUJAQAAAA10aHJvd0lzQWN0aXZlAAAAAAMJAQAAAAEhAAAAAQkBAAAAD2NvbnRhaW5zRWxlbWVudAAAAAIJAARMAAAAAgUAAAAMYWRtaW5QdWJLZXkxCQAETAAAAAIFAAAADGFkbWluUHViS2V5MgkABEwAAAACBQAAAAxhZG1pblB1YktleTMJAARMAAAAAgUAAAAMYWRtU3RhcnRTdG9wBQAAAANuaWwIBQAAAAFpAAAAD2NhbGxlclB1YmxpY0tleQkBAAAADnRocm93T25seUFkbWluAAAAAAkABEwAAAACCQEAAAAMQm9vbGVhbkVudHJ5AAAAAgUAAAAHa0FjdGl2ZQYJAARMAAAAAgkBAAAAC0RlbGV0ZUVudHJ5AAAAAQUAAAAGa0NhdXNlBQAAAANuaWwAAAABaQEAAAAZdGFrZUludG9BY2NvdW50RXh0cmFGdW5kcwAAAAAEAAAADWFtb3VudEVucm9sbEEJAABlAAAAAgUAAAAZYWNjb3VudEJhbGFuY2VXaXRoU3Rha2VkQQUAAAAIYmFsYW5jZUEEAAAADWFtb3VudEVucm9sbEIJAABlAAAAAgUAAAAZYWNjb3VudEJhbGFuY2VXaXRoU3Rha2VkQgUAAAAIYmFsYW5jZUIEAAAADGludmFyaWFudE5ldwkBAAAADWludmFyaWFudENhbGMAAAACCQAAZAAAAAIFAAAACGJhbGFuY2VBBQAAAA1hbW91bnRFbnJvbGxBCQAAZAAAAAIFAAAACGJhbGFuY2VCBQAAAA1hbW91bnRFbnJvbGxCAwkBAAAAASEAAAABBQAAAAhpc0FjdGl2ZQkBAAAAD3Rocm93SXNJbmFjdGl2ZQAAAAADCQEAAAACIT0AAAACCAUAAAABaQAAAAZjYWxsZXIFAAAADXdhbGxldEFkZHJlc3MJAAACAAAAAQIAAAAmT25seSB0aGUgd2FsbGV0IGNhbiBjYWxsIHRoaXMgZnVuY3Rpb24DAwkAAGYAAAACAAAAAAAAAAAABQAAAA1hbW91bnRFbnJvbGxBBgkAAGYAAAACAAAAAAAAAAAABQAAAA1hbW91bnRFbnJvbGxCCQEAAAAHc3VzcGVuZAAAAAECAAAAFkVu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", "height": 1884289, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: F86jSxc3DhGaMp39H6RLNfzNRz25ZK9sd4vT4pCXzZKS Next: none Diff:
OldNewDifferences
11 {-# STDLIB_VERSION 5 #-}
22 {-# SCRIPT_TYPE ACCOUNT #-}
33 {-# CONTENT_TYPE DAPP #-}
4-let version = "1.0.0"
4+let version = "2.0.0"
55
6-let keyVersion = "version"
6+let kVersion = "version"
77
8-let keyActive = "active"
8+let kActive = "active"
99
10-let keyAssetIdA = "A_asset_id"
10+let kAssetIdA = "A_asset_id"
1111
12-let keyAssetIdB = "B_asset_id"
12+let kAssetIdB = "B_asset_id"
1313
14-let keyBalanceA = "A_asset_balance"
14+let kBalanceA = "A_asset_balance"
1515
16-let keyBalanceB = "B_asset_balance"
16+let kBalanceB = "B_asset_balance"
1717
18-let keyBalanceInitA = "A_asset_init"
18+let kShareAssetId = "share_asset_id"
1919
20-let keyBalanceInitB = "B_asset_init"
20+let kShareAssetSupply = "share_asset_supply"
2121
22-let keyShareAssetId = "share_asset_id"
22+let kFee = "commission"
2323
24-let keyShareAssetSupply = "share_asset_supply"
24+let kFeeScaleDelimiter = "commission_scale_delimiter"
2525
26-let keyCommission = "commission"
26+let kInvariant = "invariant"
2727
28-let keyCommissionScaleDelimiter = "commission_scale_delimiter"
29-
30-let keyCause = "shutdown_cause"
31-
32-let keyFirstHarvest = "first_harvest"
33-
34-let keyFirstHarvestHeight = "first_harvest_height"
35-
36-let kShareLimit = "share_limit_on_first_harvest"
37-
38-let kBasePeriod = "base_period"
39-
40-let kPeriodLength = "period_length"
41-
42-let kStartHeight = "start_height"
43-
44-let kFirstHarvestHeight = "first_harvest_height"
28+let kCause = "shutdown_cause"
4529
4630 let keyUSDNNSBTAddress = "staking_usdnnsbt_address"
4731
4832 let keyEURNAddress = "staking_eurn_address"
49-
50-let keyLeasingPool = "leasing_address"
51-
52-let keyLeasingAmount = "leasing_amount"
53-
54-let keyLeasingId = "leasing_id"
5533
5634 let keyAdminPubKey1 = "admin_pub_1"
5735
5836 let keyAdminPubKey2 = "admin_pub_2"
5937
6038 let keyAdminPubKey3 = "admin_pub_3"
39+
40+let USDNToWavesExchanger = Address(base58'3N8PGkzXhbtTvEwEQTtE2xiTJmsDEQ9XfoZ')
6141
6242 let oracle = Address(base58'3NBBWfzZtZtszaXbitTKnrB2xXwv26Bn7H9')
6343
7555
7656 let adminPubKey3 = getAdminPub(keyAdminPubKey3)
7757
78-let adminPubKeyStartStop = base58'Kn7NpzaG12dLZgcHf2ipUftU6hbJygmrhFqQYE4B7ZK'
58+let admStartStop = base58'Kn7NpzaG12dLZgcHf2ipUftU6hbJygmrhFqQYE4B7ZK'
7959
80-let adminPubKeyStaking = base58'Kn7NpzaG12dLZgcHf2ipUftU6hbJygmrhFqQYE4B7ZK'
60+let admStaking = base58'Kn7NpzaG12dLZgcHf2ipUftU6hbJygmrhFqQYE4B7ZK'
8161
8262 let walletAddress = Address(base58'3NAGTtZz6WpupSN89NZD5rMZwwziZEg4Kx4')
8363
84-let votingAddress = Address(base58'3MrJgdL1GniipErHy44YF9idzLaUL2iX5DQ')
85-
8664 let USDN = base58'8UrfDVd5GreeUwm7uPk7eYz1eMv376kzR52C6sANPkwS'
87-
88-let NSBT = base58'36mg8NZTaFRDygiVwb8uBnLR51hetJruUCZcxhaVcHj9'
89-
90-let SWOP = base58'2HAJrwa8q4SxBx9cHYaBTQdBjdk5wwqdof7ccpAx2uhZ'
9165
9266 let EURN = base58'ECBCkHS68DckpBrzLeoRgYbFg7sCVqR176mPqbXsj9pA'
9367
94-let stakingAssets = ["WAVES", toBase58String(USDN), toBase58String(NSBT), toBase58String(EURN)]
68+let stakingAssets = [toBase58String(USDN), toBase58String(EURN)]
9569
9670 let stakingUSDNNSBTAddress = Address(fromBase58String(valueOrErrorMessage(getString(oracle, keyUSDNNSBTAddress), "no usdn staking address")))
9771
98-let stakingEURNAddress = Address(fromBase58String(valueOrErrorMessage(getString(oracle, keyEURNAddress), "no eurn staking address")))
72+let stakingEURNAddress = Address(fromBase58String(valueOrErrorMessage(getString(oracle, keyEURNAddress), "no usdn staking address")))
9973
100-let USDNToWavesExchanger = Address(base58'3N8PGkzXhbtTvEwEQTtE2xiTJmsDEQ9XfoZ')
74+let isActive = getBooleanValue(this, kActive)
10175
102-let USDNToNSBTExchanger = Address(base58'3MqW1t2cxdYy2emEMk3YtZkRwQPhHaTfWRe')
76+let strAssetIdA = getStringValue(this, kAssetIdA)
10377
104-let basePeriod = valueOrErrorMessage(getInteger(votingAddress, kBasePeriod), "Empty kBasePeriod")
105-
106-let startHeight = valueOrErrorMessage(getInteger(votingAddress, kStartHeight), "Empty kStartHeight")
107-
108-let periodLength = valueOrErrorMessage(getInteger(votingAddress, kPeriodLength), "Empty kPeriodLength")
109-
110-let firstHarvestEndPeriod = ((basePeriod + ((height - startHeight) / periodLength)) + 3)
111-
112-let active = getBooleanValue(this, keyActive)
113-
114-let strAssetIdA = getStringValue(this, keyAssetIdA)
115-
116-let strAssetIdB = getStringValue(this, keyAssetIdB)
78+let strAssetIdB = getStringValue(this, kAssetIdB)
11779
11880 let assetIdA = if ((strAssetIdA == "WAVES"))
11981 then unit
141103 throw("Match error")
142104 }
143105
144-let balanceA = getIntegerValue(this, keyBalanceA)
106+let balanceA = getIntegerValue(this, kBalanceA)
145107
146-let balanceB = getIntegerValue(this, keyBalanceB)
108+let balanceB = getIntegerValue(this, kBalanceB)
147109
148-let shareAssetId = fromBase58String(getStringValue(this, keyShareAssetId))
110+let shareAssetId = fromBase58String(getStringValue(this, kShareAssetId))
149111
150-let shareAssetSupply = getIntegerValue(this, keyShareAssetSupply)
112+let shareAssetSupply = getIntegerValue(this, kShareAssetSupply)
151113
152-let commission = 3000
114+let invariant = getIntegerValue(this, kInvariant)
153115
154-let commissionGovernance = 1200
116+let fee = 500
155117
156-let commissionScaleDelimiter = 1000000
118+let feeGovernance = 200
157119
158-let scaleValue3 = 1000
120+let feeScale6 = 1000000
159121
160-let scaleValue8 = 100000000
122+let scale3 = 1000
161123
162-let slippageToleranceDelimiter = 1000
124+let scale8 = 100000000
163125
164-let scaleValue8Digits = 8
126+let scale12 = 1000000000000
127+
128+let slippageScale3 = 1000
129+
130+let digits8 = 8
131+
132+let dAppThreshold = 50
133+
134+let dAppThresholdScale2 = 100
135+
136+let exchangeRatioLimitMin = 90000000
137+
138+let exchangeRatioLimitMax = 110000000
139+
140+let alpha = 50
141+
142+let alphaDigits = 2
143+
144+let beta = 46000000
165145
166146 func accountBalance (assetId) = match assetId {
167147 case id: ByteVector =>
176156 func stakedAmount (assetId) = {
177157 let stakedAmountCalculated = match assetId {
178158 case aId: ByteVector =>
179- if (if ((aId == USDN))
180- then true
181- else (aId == NSBT))
159+ if ((aId == USDN))
182160 then getInteger(stakingUSDNNSBTAddress, ((("rpd_balance_" + toBase58String(aId)) + "_") + toString(this)))
183161 else if ((aId == EURN))
184162 then getInteger(stakingEURNAddress, ((("%s%s%s__stakingBalance__" + toBase58String(aId)) + "__") + toString(this)))
185163 else 0
186164 case _: Unit =>
187- valueOrElse(getInteger(this, keyLeasingAmount), 0)
165+ 0
188166 case _ =>
189167 throw("Match error")
190168 }
201179
202180 let stakedAmountB = stakedAmount(assetIdB)
203181
204-let assetInitA = getIntegerValue(this, keyBalanceInitA)
205-
206-let assetInitB = getIntegerValue(this, keyBalanceInitB)
207-
208182 let availableBalanceA = (balanceA - stakedAmountA)
209183
210184 let availableBalanceB = (balanceB - stakedAmountB)
216190 let hasEnoughBalance = if ((accountBalanceWithStakedA >= balanceA))
217191 then (accountBalanceWithStakedB >= balanceB)
218192 else false
193+
194+func skewness (x,y) = (((fraction(scale12, x, y) + fraction(scale12, y, x)) / 2) / 10000)
195+
196+
197+func invariantCalc (x,y) = {
198+ let sk = skewness(x, y)
199+ (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)))
200+ }
201+
202+
203+func calculateSendAmount (amountToSendEstimated,minTokenReceiveAmount,tokenReceiveAmount,tokenId) = {
204+ let slippageValue = (scale8 - ((scale8 * 1) / 10000000))
205+ let deltaBetweenMaxAndMinSendValue = (amountToSendEstimated - minTokenReceiveAmount)
206+ let x = (balanceA + tokenReceiveAmount)
207+ let y = (balanceB + tokenReceiveAmount)
208+ let invariantNew = if ((tokenId == assetIdA))
209+ then invariantCalc(x, (balanceB - amountToSendEstimated))
210+ else if ((tokenId == assetIdB))
211+ then invariantCalc((balanceA - amountToSendEstimated), y)
212+ else throw("Wrong asset in payment")
213+ let invariantEstimatedRatio = fraction(scale8, invariant, invariantNew)
214+ func getStepAmount (acc,step) = if ((acc == -1))
215+ then {
216+ let amountToSend = (amountToSendEstimated - ((step * deltaBetweenMaxAndMinSendValue) / 5))
217+ let stepInvariant = if ((tokenId == assetIdA))
218+ then invariantCalc(x, (balanceB - amountToSend))
219+ else invariantCalc((balanceA - amountToSend), y)
220+ if ((stepInvariant > invariant))
221+ then amountToSend
222+ else -1
223+ }
224+ else acc
225+
226+ let stepAmount = {
227+ let $l = [1, 2, 3, 4, 5]
228+ let $s = size($l)
229+ let $acc0 = -1
230+ func $f0_1 ($a,$i) = if (($i >= $s))
231+ then $a
232+ else getStepAmount($a, $l[$i])
233+
234+ func $f0_2 ($a,$i) = if (($i >= $s))
235+ then $a
236+ else throw("List size exceeds 5")
237+
238+ $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5)
239+ }
240+ if ((0 > stepAmount))
241+ then throw("something went wrong while working with amountToSend")
242+ else if (if ((invariantEstimatedRatio > slippageValue))
243+ then (invariantNew > invariant)
244+ else false)
245+ then amountToSendEstimated
246+ else stepAmount
247+ }
248+
219249
220250 func getAssetInfo (assetId) = match assetId {
221251 case id: ByteVector =>
229259 }
230260
231261
232-func getAssetInfoFromString (assetStr) = if ((assetStr == "WAVES"))
233- then $Tuple3("WAVES", "WAVES", 8)
234- else {
235- let stringId = assetStr
236- let id = fromBase58String(assetStr)
237- let info = valueOrErrorMessage(assetInfo(id), (("Asset " + stringId) + " doesn't exist"))
238- $Tuple3(stringId, info.name, info.decimals)
239- }
262+func suspend (cause) = [BooleanEntry(kActive, false), StringEntry(kCause, cause)]
240263
241264
242-func suspend (cause) = [BooleanEntry(keyActive, false), StringEntry(keyCause, cause)]
265+func throwIsActive () = throw("DApp is already active")
266+
267+
268+func throwIsInactive () = throw("DApp is inactive at this moment")
269+
270+
271+func throwOnlyAdmin () = throw("Only admin can call this function")
272+
273+
274+func throwAssets () = throw(((("Incorrect assets attached. Expected: " + strAssetIdA) + " and ") + strAssetIdB))
275+
276+
277+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))
278+
279+
280+func suspendSuspicious () = suspend(((((((((((((((("Suspicious state. Actual balances: " + toString(balanceA)) + " ") + assetNameA) + ", ") + toString(balanceB)) + " ") + assetNameB) + ". State: ") + toString(accountBalance(assetIdA))) + " ") + assetNameA) + ", ") + toString(accountBalance(assetIdB))) + " ") + assetNameB))
243281
244282
245283 func calcStakingFuncAndAddres (stake,assetId) = if (stake)
246284 then if ((assetId == USDN))
247285 then $Tuple2("lockNeutrino", stakingUSDNNSBTAddress)
248- else if ((assetId == NSBT))
249- then $Tuple2("lockNsbt", stakingUSDNNSBTAddress)
250- else $Tuple2("startStaking", stakingEURNAddress)
286+ else $Tuple2("startStaking", stakingEURNAddress)
251287 else if ((assetId == USDN))
252288 then $Tuple2("unlockNeutrino", stakingUSDNNSBTAddress)
253- else if ((assetId == NSBT))
254- then $Tuple2("unlockNsbt", stakingUSDNNSBTAddress)
255- else $Tuple2("stopStaking", stakingEURNAddress)
289+ else $Tuple2("stopStaking", stakingEURNAddress)
256290
257291
258292 func calcStakingParams (stake,amount,assetId) = if (stake)
259293 then {
260- let $t069226988 = calcStakingFuncAndAddres(stake, assetId)
261- let call = $t069226988._1
262- let stakingAddr = $t069226988._2
294+ let $t087598825 = calcStakingFuncAndAddres(stake, assetId)
295+ let call = $t087598825._1
296+ let stakingAddr = $t087598825._2
263297 $Tuple4(call, stakingAddr, nil, [AttachedPayment(assetId, amount)])
264298 }
265299 else {
266- let $t070747140 = calcStakingFuncAndAddres(stake, assetId)
267- let call = $t070747140._1
268- let stakingAddr = $t070747140._2
300+ let $t089118977 = calcStakingFuncAndAddres(stake, assetId)
301+ let call = $t089118977._1
302+ let stakingAddr = $t089118977._2
269303 $Tuple4(call, stakingAddr, [amount, toBase58String(assetId)], nil)
270304 }
271305
272306
273-func calculateFees (pmtAmount,minAmountToReceive,tokenFrom,tokenTo) = {
274- let amountWithoutFee = fraction(tokenTo, pmtAmount, (pmtAmount + tokenFrom))
275- let amountWithFee = fraction(amountWithoutFee, (commissionScaleDelimiter - commission), commissionScaleDelimiter)
276- let governanceReward = fraction(amountWithoutFee, commissionGovernance, commissionScaleDelimiter)
277- if ((minAmountToReceive > amountWithFee))
278- then throw(((("Calculated amount to receive " + toString(amountWithFee)) + " is less than specified minimum ") + toString(minAmountToReceive)))
279- else $Tuple3(amountWithoutFee, amountWithFee, governanceReward)
280- }
281-
282-
283-func suspendSuspicious () = suspend(((((((((((((((("Suspicious state. Actual balances: " + toString(accountBalanceWithStakedA)) + " ") + assetNameA) + ", ") + toString(accountBalanceWithStakedB)) + " ") + assetNameB) + ". State: ") + toString(balanceA)) + " ") + assetNameA) + ", ") + toString(balanceB)) + " ") + assetNameB))
284-
285-
286-func isActive () = if (active)
287- then unit
288- else throw("DApp is inactive at this moment")
289-
290-
291307 @Callable(i)
292-func init (firstHarvest) = {
293- let $t083108387 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
294- let pmtAmountA = $t083108387._1
295- let pmtAssetIdA = $t083108387._2
296- let $t083928469 = $Tuple2(i.payments[1].amount, i.payments[1].assetId)
297- let pmtAmountB = $t083928469._1
298- let pmtAssetIdB = $t083928469._2
299- let $t084748551 = getAssetInfo(pmtAssetIdA)
300- let pmtStrAssetIdA = $t084748551._1
301- let pmtAssetNameA = $t084748551._2
302- let pmtDecimalsA = $t084748551._3
303- let $t085568633 = getAssetInfo(pmtAssetIdB)
304- let pmtStrAssetIdB = $t085568633._1
305- let pmtAssetNameB = $t085568633._2
306- let pmtDecimalsB = $t085568633._3
307- if (!(containsElement([adminPubKey1, adminPubKey2, adminPubKey3, adminPubKeyStaking], i.callerPublicKey)))
308- then throw("Only admin can call this function")
309- else if (isDefined(getBoolean(this, keyActive)))
310- then throw("DApp is already active")
311- else if ((pmtAssetIdA == pmtAssetIdB))
312- then throw("Assets must be different")
313- else {
314- let shareName = ((("s" + take(pmtAssetNameA, 7)) + "_") + take(pmtAssetNameB, 7))
315- let shareDescription = ((((("ShareToken of SwopFi protocol for " + pmtAssetNameA) + " and ") + pmtAssetNameB) + " at address ") + toString(this))
316- let shareDecimals = ((pmtDecimalsA + pmtDecimalsB) / 2)
317- let arg1 = pow(pmtAmountA, pmtDecimalsA, 5, 1, pmtDecimalsA, DOWN)
318- let arg2 = pow(pmtAmountB, pmtDecimalsB, 5, 1, pmtDecimalsB, DOWN)
319- let arg3 = pow(10, 0, shareDecimals, 0, 0, DOWN)
320- let shareInitialSupply = fraction(arg1, arg2, arg3)
321- let shareIssue = Issue(shareName, shareDescription, shareInitialSupply, shareDecimals, true)
322- let shareIssueId = calculateAssetId(shareIssue)
323- let stake1 = if (containsElement(stakingAssets, pmtStrAssetIdA))
324- then invoke(this, "stakeUnstake", [true, pmtAmountA, pmtStrAssetIdA], nil)
325- else 0
326- if ((stake1 == stake1))
327- then {
328- let stake2 = if (containsElement(stakingAssets, pmtStrAssetIdB))
329- then invoke(this, "stakeUnstake", [true, pmtAmountB, pmtStrAssetIdB], nil)
330- else 0
331- if ((stake2 == stake2))
332- then {
333- let baseEntry = [StringEntry(keyVersion, version), BooleanEntry(keyActive, true), StringEntry(keyAssetIdA, pmtStrAssetIdA), StringEntry(keyAssetIdB, pmtStrAssetIdB), IntegerEntry(keyBalanceA, pmtAmountA), IntegerEntry(keyBalanceB, pmtAmountB), IntegerEntry(keyCommission, commission), IntegerEntry(keyCommissionScaleDelimiter, commissionScaleDelimiter), shareIssue, StringEntry(keyShareAssetId, toBase58String(shareIssueId)), IntegerEntry(keyShareAssetSupply, shareInitialSupply), ScriptTransfer(i.caller, shareInitialSupply, shareIssueId)]
334- if (firstHarvest)
335- then (baseEntry ++ [BooleanEntry(keyFirstHarvest, firstHarvest), IntegerEntry(keyFirstHarvestHeight, (startHeight + (firstHarvestEndPeriod * periodLength)))])
336- else baseEntry
337- }
338- else throw("Strict value is not equal to itself.")
339- }
340- else throw("Strict value is not equal to itself.")
341- }
308+func init () = {
309+ let $t090829159 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
310+ let pmtAmountA = $t090829159._1
311+ let pmtAssetIdA = $t090829159._2
312+ let $t091649241 = $Tuple2(i.payments[1].amount, i.payments[1].assetId)
313+ let pmtAmountB = $t091649241._1
314+ let pmtAssetIdB = $t091649241._2
315+ let $t092469323 = getAssetInfo(pmtAssetIdA)
316+ let pmtStrAssetIdA = $t092469323._1
317+ let pmtAssetNameA = $t092469323._2
318+ let pmtDecimalsA = $t092469323._3
319+ let $t093289405 = getAssetInfo(pmtAssetIdB)
320+ let pmtStrAssetIdB = $t093289405._1
321+ let pmtAssetNameB = $t093289405._2
322+ let pmtDecimalsB = $t093289405._3
323+ if (isDefined(getBoolean(this, kActive)))
324+ then throwIsActive()
325+ else if ((pmtAssetIdA == pmtAssetIdB))
326+ then throw("Assets must be different")
327+ else {
328+ let shareName = ((("s" + take(pmtAssetNameA, 7)) + "_") + take(pmtAssetNameB, 7))
329+ let shareDescription = ((((("ShareToken of SwopFi protocol for " + pmtAssetNameA) + " and ") + pmtAssetNameB) + " at address ") + toString(this))
330+ let shareDecimals = ((pmtDecimalsA + pmtDecimalsB) / 2)
331+ let shareInitialSupply = fraction(pow(pmtAmountA, pmtDecimalsA, 5, 1, pmtDecimalsA, DOWN), pow(pmtAmountB, pmtDecimalsB, 5, 1, pmtDecimalsB, DOWN), pow(10, 0, shareDecimals, 0, 0, DOWN))
332+ let shareIssue = Issue(shareName, shareDescription, shareInitialSupply, shareDecimals, true)
333+ let shareIssueId = calculateAssetId(shareIssue)
334+ let invariantCalculated = invariantCalc(pmtAmountA, pmtAmountB)
335+ let stake1 = if (containsElement(stakingAssets, pmtStrAssetIdA))
336+ then invoke(this, "stakeUnstake", [true, pmtAmountA, pmtStrAssetIdA], nil)
337+ else 0
338+ if ((stake1 == stake1))
339+ then {
340+ let stake2 = if (containsElement(stakingAssets, pmtStrAssetIdB))
341+ then invoke(this, "stakeUnstake", [true, pmtAmountB, pmtStrAssetIdB], nil)
342+ else 0
343+ if ((stake2 == stake2))
344+ 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)]
345+ else throw("Strict value is not equal to itself.")
346+ }
347+ else throw("Strict value is not equal to itself.")
348+ }
342349 }
343350
344351
345352
346353 @Callable(i)
347-func initWithInitRatio (amtAssetA,amtAssetB,strAssetIdA,strAssetIdB,firstHarvest) = {
348- let $t01122211309 = getAssetInfoFromString(strAssetIdA)
349- let pmtStrAssetIdA = $t01122211309._1
350- let pmtAssetNameA = $t01122211309._2
351- let pmtDecimalsA = $t01122211309._3
352- let $t01131411401 = getAssetInfoFromString(strAssetIdB)
353- let pmtStrAssetIdB = $t01131411401._1
354- let pmtAssetNameB = $t01131411401._2
355- let pmtDecimalsB = $t01131411401._3
356- if (!(containsElement([adminPubKey1, adminPubKey2, adminPubKey3, adminPubKeyStaking], i.callerPublicKey)))
357- then throw("Only admin can call this function")
358- else if (isDefined(getBoolean(this, keyActive)))
359- then throw("DApp is already active")
360- else if ((strAssetIdA == strAssetIdB))
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 = 0
367- let shareIssue = Issue(shareName, shareDescription, shareInitialSupply, shareDecimals, true)
368- let shareIssueId = calculateAssetId(shareIssue)
369- let baseEntry = [StringEntry(keyVersion, version), BooleanEntry(keyActive, true), StringEntry(keyAssetIdA, pmtStrAssetIdA), StringEntry(keyAssetIdB, pmtStrAssetIdB), IntegerEntry(keyBalanceInitA, amtAssetA), IntegerEntry(keyBalanceInitB, amtAssetB), IntegerEntry(keyBalanceA, 0), IntegerEntry(keyBalanceB, 0), IntegerEntry(keyCommission, commission), IntegerEntry(keyCommissionScaleDelimiter, commissionScaleDelimiter), shareIssue, StringEntry(keyShareAssetId, toBase58String(shareIssueId)), IntegerEntry(keyShareAssetSupply, shareInitialSupply)]
370- if (firstHarvest)
371- then (baseEntry ++ [BooleanEntry(keyFirstHarvest, firstHarvest), IntegerEntry(keyFirstHarvestHeight, (startHeight + (firstHarvestEndPeriod * periodLength)))])
372- else baseEntry
373- }
354+func replenishWithTwoTokens (slippageTolerance) = {
355+ let pmtAssetIdA = i.payments[0].assetId
356+ let pmtAssetIdB = i.payments[1].assetId
357+ let pmtAmountA = i.payments[0].amount
358+ let pmtAmountB = i.payments[1].amount
359+ let $t01192111998 = getAssetInfo(pmtAssetIdA)
360+ let pmtStrAssetIdA = $t01192111998._1
361+ let pmtAssetNameA = $t01192111998._2
362+ let pmtDecimalsA = $t01192111998._3
363+ let $t01200312197 = getAssetInfo(pmtAssetIdB)
364+ let pmtStrAssetIdB = $t01200312197._1
365+ let pmtAssetNameB = $t01200312197._2
366+ let pmtDecimalsB = $t01200312197._3
367+ let tokenRatio = fraction(fraction(scale8, balanceA, pmtAmountA), scale3, fraction(scale8, balanceB, pmtAmountB))
368+ let ratioShareTokensInA = fraction(scale8, pmtAmountA, balanceA)
369+ let ratioShareTokensInB = fraction(scale8, pmtAmountB, balanceB)
370+ let shareTokenToPayAmount = fraction(min([ratioShareTokensInA, ratioShareTokensInB]), shareAssetSupply, scale8)
371+ let invariantCalculated = invariantCalc((balanceA + pmtAmountA), (balanceB + pmtAmountB))
372+ if (!(isActive))
373+ then throwIsInactive()
374+ else if (if ((0 > slippageTolerance))
375+ then true
376+ else (slippageTolerance > 10))
377+ then throw("Slippage tolerance must be <= 1%")
378+ else if ((size(i.payments) != 2))
379+ then throw("Two attached assets expected")
380+ else if (if ((pmtAssetIdA != assetIdA))
381+ then true
382+ else (pmtAssetIdB != assetIdB))
383+ then throwAssets()
384+ else if (if ((((scale3 * (slippageScale3 - slippageTolerance)) / slippageScale3) > tokenRatio))
385+ then true
386+ else (tokenRatio > ((scale3 * (slippageScale3 + slippageTolerance)) / slippageScale3)))
387+ then throw("Incorrect assets amount: amounts must have the contract ratio")
388+ else if ((shareTokenToPayAmount == 0))
389+ then throw("Too small amount to replenish")
390+ else if (!(hasEnoughBalance))
391+ then ([ScriptTransfer(i.caller, pmtAmountA, pmtAssetIdA), ScriptTransfer(i.caller, pmtAmountB, pmtAssetIdB)] ++ suspendSuspicious())
392+ else {
393+ let stake1 = if (containsElement(stakingAssets, pmtStrAssetIdA))
394+ then invoke(this, "stakeUnstake", [true, pmtAmountA, pmtStrAssetIdA], nil)
395+ else 0
396+ if ((stake1 == stake1))
397+ then {
398+ let stake2 = if (containsElement(stakingAssets, pmtStrAssetIdB))
399+ then invoke(this, "stakeUnstake", [true, pmtAmountB, pmtStrAssetIdB], nil)
400+ else 0
401+ if ((stake2 == stake2))
402+ then [IntegerEntry(kBalanceA, (balanceA + pmtAmountA)), IntegerEntry(kBalanceB, (balanceB + pmtAmountB)), IntegerEntry(kShareAssetSupply, (shareAssetSupply + shareTokenToPayAmount)), IntegerEntry(kInvariant, invariantCalculated), Reissue(shareAssetId, shareTokenToPayAmount, true), ScriptTransfer(i.caller, shareTokenToPayAmount, shareAssetId)]
403+ else throw("Strict value is not equal to itself.")
404+ }
405+ else throw("Strict value is not equal to itself.")
406+ }
374407 }
375408
376409
377410
378411 @Callable(i)
379-func keepLimitForFirstHarvest (shareLimit) = valueOrElse(isActive(), if (!(containsElement([adminPubKey1, adminPubKey2, adminPubKey3, adminPubKeyStaking], i.callerPublicKey)))
380- then throw("Only admin can call this function")
381- else [IntegerEntry(kShareLimit, shareLimit)])
412+func replenishWithOneToken (virtualSwapTokenPay,virtualSwapTokenGet) = {
413+ let $t01449614571 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
414+ let pmtAmount = $t01449614571._1
415+ let pmtAssetId = $t01449614571._2
416+ let $t01457614649 = getAssetInfo(pmtAssetId)
417+ let pmtStrAssetId = $t01457614649._1
418+ let pmtAssetName = $t01457614649._2
419+ let pmtDecimals = $t01457614649._3
420+ let pmtMinThreshold = 5000000
421+ let thresholdValueForMinTolerance = 50000000
422+ let tolerance = if ((thresholdValueForMinTolerance > pmtAmount))
423+ then 100000
424+ else 1
425+ let slippageValueMinForReplenish = (scale8 - ((scale8 * tolerance) / 10000000))
426+ let slippageValueMaxForReplenish = (scale8 + ((scale8 * tolerance) / 10000000))
427+ let slippageValueMinForSwap = (scale8 - ((scale8 * 1) / 10000000))
428+ if (!(isActive))
429+ then throwIsInactive()
430+ else if ((pmtMinThreshold > pmtAmount))
431+ then throw((((("Payment amount " + toString(pmtAmount)) + " does not exceed the minimum amount of ") + toString(pmtMinThreshold)) + " tokens"))
432+ else if ((size(i.payments) != 1))
433+ then throw("One attached payment expected")
434+ else if (!(hasEnoughBalance))
435+ then ([ScriptTransfer(i.caller, pmtAmount, pmtAssetId)] ++ suspendSuspicious())
436+ else if (if ((pmtAssetId != assetIdA))
437+ then (pmtAssetId != assetIdB)
438+ else false)
439+ then throwAssets()
440+ else {
441+ let $t01566116426 = if ((pmtAssetId == assetIdA))
442+ then $Tuple7((pmtAmount - virtualSwapTokenPay), virtualSwapTokenGet, (balanceA + virtualSwapTokenPay), (balanceB - virtualSwapTokenGet), invariantCalc((balanceA + pmtAmount), balanceB), (balanceA + pmtAmount), balanceB)
443+ else $Tuple7(virtualSwapTokenGet, (pmtAmount - virtualSwapTokenPay), (balanceA - virtualSwapTokenGet), (balanceB + virtualSwapTokenPay), invariantCalc(balanceA, (balanceB + pmtAmount)), balanceA, (balanceB + pmtAmount))
444+ let virtualReplenishA = $t01566116426._1
445+ let virtualReplenishB = $t01566116426._2
446+ let balanceAfterSwapA = $t01566116426._3
447+ let balanceAfterSwapB = $t01566116426._4
448+ let invariantCalculated = $t01566116426._5
449+ let newBalanceA = $t01566116426._6
450+ let newBalanceB = $t01566116426._7
451+ let newBalanceEntry = if ((pmtAssetId == assetIdA))
452+ then IntegerEntry(kBalanceA, newBalanceA)
453+ else IntegerEntry(kBalanceB, newBalanceB)
454+ let invariantNew = invariantCalc(balanceAfterSwapA, balanceAfterSwapB)
455+ let invariantEstimatedRatio = fraction(scale8, invariant, invariantNew)
456+ let ratioVirtualBalanceToVirtualReplenish = (fraction((scale8 * scale8), balanceAfterSwapA, balanceAfterSwapB) / fraction(scale8, virtualReplenishA, virtualReplenishB))
457+ let dAppThresholdAmount = fraction((newBalanceA + newBalanceB), dAppThreshold, (2 * dAppThresholdScale2))
458+ if (if ((slippageValueMinForSwap >= invariantEstimatedRatio))
459+ then true
460+ else (invariant > invariantNew))
461+ then throw("Incorrect virtualSwapTokenPay or virtualSwapTokenGet value")
462+ else if (if ((slippageValueMinForReplenish > ratioVirtualBalanceToVirtualReplenish))
463+ then true
464+ else (ratioVirtualBalanceToVirtualReplenish > slippageValueMaxForReplenish))
465+ then throw("Swap with virtualSwapTokenPay and virtualSwapTokenGet is possible, but ratio after virtual swap is incorrect")
466+ else if (if ((dAppThresholdAmount > newBalanceA))
467+ then true
468+ else (dAppThresholdAmount > newBalanceB))
469+ then throwThreshold(dAppThresholdAmount, newBalanceA, newBalanceB)
470+ else {
471+ let stake1 = if (containsElement(stakingAssets, pmtStrAssetId))
472+ then invoke(this, "stakeUnstake", [true, pmtAmount, pmtStrAssetId], nil)
473+ else 0
474+ if ((stake1 == stake1))
475+ then {
476+ let ratioShareTokensInA = fraction(virtualReplenishA, scale8, balanceAfterSwapA)
477+ let ratioShareTokensInB = fraction(virtualReplenishB, scale8, balanceAfterSwapB)
478+ let shareTokenToPayAmount = fraction(min([ratioShareTokensInA, ratioShareTokensInB]), shareAssetSupply, scale8)
479+[Reissue(shareAssetId, shareTokenToPayAmount, true), ScriptTransfer(i.caller, shareTokenToPayAmount, shareAssetId), IntegerEntry(kShareAssetSupply, (shareAssetSupply + shareTokenToPayAmount)), newBalanceEntry, IntegerEntry(kInvariant, invariantCalculated)]
480+ }
481+ else throw("Strict value is not equal to itself.")
482+ }
483+ }
484+ }
382485
383486
384487
385488 @Callable(i)
386-func replenishWithTwoTokens (slippageTolerance) = valueOrElse(isActive(), {
387- let pmtAssetIdA = i.payments[0].assetId
388- let pmtAssetIdB = i.payments[1].assetId
389- let pmtAmountA = i.payments[0].amount
390- let pmtAmountB = i.payments[1].amount
391- let $t01386913946 = getAssetInfo(pmtAssetIdA)
392- let pmtStrAssetIdA = $t01386913946._1
393- let pmtAssetNameA = $t01386913946._2
394- let pmtDecimalsA = $t01386913946._3
395- let $t01395114028 = getAssetInfo(pmtAssetIdB)
396- let pmtStrAssetIdB = $t01395114028._1
397- let pmtAssetNameB = $t01395114028._2
398- let pmtDecimalsB = $t01395114028._3
399- let inital = if (if ((balanceA == 0))
400- then (balanceB == 0)
401- else false)
402- then true
403- else false
404- let tokenRatio = if (inital)
405- then fraction(fraction(assetInitA, scaleValue8, pmtAmountA), scaleValue3, fraction(assetInitB, scaleValue8, pmtAmountB))
406- else fraction(fraction(balanceA, scaleValue8, pmtAmountA), scaleValue3, fraction(balanceB, scaleValue8, pmtAmountB))
407- let shareDecimals = ((pmtDecimalsA + pmtDecimalsB) / 2)
408- let shareTokenToPayAmount = if (inital)
409- then fraction(pow(pmtAmountA, pmtDecimalsA, 5, 1, pmtDecimalsA, DOWN), pow(pmtAmountB, pmtDecimalsB, 5, 1, pmtDecimalsB, DOWN), pow(10, 0, shareDecimals, 0, 0, DOWN))
410- else fraction(min([fraction(pmtAmountA, scaleValue8, balanceA), fraction(pmtAmountB, scaleValue8, balanceB)]), shareAssetSupply, scaleValue8)
411- if (if ((0 > slippageTolerance))
412- then true
413- else (slippageTolerance > slippageToleranceDelimiter))
414- then throw(((("Slippage tolerance must be between 0 and " + toString(slippageToleranceDelimiter)) + " inclusively. Actual: ") + toString(slippageTolerance)))
415- else if ((size(i.payments) != 2))
416- then throw("Two attached assets expected")
417- else if (if ((pmtAssetIdA != assetIdA))
418- then true
419- else (pmtAssetIdB != assetIdB))
420- then throw(((("Incorrect assets attached. Expected: " + strAssetIdA) + " and ") + strAssetIdB))
421- else if (if ((((scaleValue3 * (slippageToleranceDelimiter - slippageTolerance)) / slippageToleranceDelimiter) > tokenRatio))
422- then true
423- else (tokenRatio > ((scaleValue3 * (slippageToleranceDelimiter + slippageTolerance)) / slippageToleranceDelimiter)))
424- then throw("Incorrect assets amount: amounts must have the contract ratio")
425- else if ((shareTokenToPayAmount == 0))
426- then throw("Too small amount to replenish")
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)
489+func withdraw () = {
490+ let $t01865218795 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
491+ let pmtAmount = $t01865218795._1
492+ let pmtAssetId = $t01865218795._2
493+ let amountToPayA = fraction(pmtAmount, balanceA, shareAssetSupply)
494+ let amountToPayB = fraction(pmtAmount, balanceB, shareAssetSupply)
495+ let invariantCalculated = invariantCalc((balanceA - amountToPayA), (balanceB - amountToPayB))
496+ if (!(isActive))
497+ then throwIsInactive()
498+ else if ((size(i.payments) != 1))
499+ then throw("One attached payment expected")
500+ else if ((pmtAssetId != shareAssetId))
501+ then throw(("Incorrect asset attached. Expected: " + toBase58String(shareAssetId)))
502+ else if (!(hasEnoughBalance))
503+ then ([ScriptTransfer(i.caller, pmtAmount, pmtAssetId)] ++ suspendSuspicious())
504+ else {
505+ let stake1 = if (containsElement(stakingAssets, strAssetIdA))
506+ then invoke(this, "stakeUnstake", [false, amountToPayA, strAssetIdA], nil)
507+ else 0
508+ if ((stake1 == stake1))
509+ then {
510+ let stake2 = if (containsElement(stakingAssets, strAssetIdB))
511+ then invoke(this, "stakeUnstake", [false, amountToPayB, strAssetIdB], nil)
432512 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 [Reissue(shareAssetId, shareTokenToPayAmount, true), IntegerEntry(keyBalanceA, (balanceA + pmtAmountA)), IntegerEntry(keyBalanceB, (balanceB + pmtAmountB)), IntegerEntry(keyShareAssetSupply, (shareAssetSupply + shareTokenToPayAmount)), ScriptTransfer(i.caller, shareTokenToPayAmount, shareAssetId)]
440- else throw("Strict value is not equal to itself.")
441- }
513+ if ((stake2 == stake2))
514+ 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)]
442515 else throw("Strict value is not equal to itself.")
443516 }
444- })
517+ else throw("Strict value is not equal to itself.")
518+ }
519+ }
445520
446521
447522
448523 @Callable(i)
449-func withdraw () = valueOrElse(isActive(), {
450- let $t01683416909 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
451- let pmtAmount = $t01683416909._1
452- let pmtAssetId = $t01683416909._2
453- let amountToPayA = fraction(pmtAmount, balanceA, shareAssetSupply)
454- let amountToPayB = fraction(pmtAmount, balanceB, shareAssetSupply)
455- if ((size(i.payments) != 1))
456- then throw("One attached payment expected")
457- else if ((pmtAssetId != shareAssetId))
458- then throw(("Incorrect asset attached. Expected: " + toBase58String(shareAssetId)))
459- else if (!(hasEnoughBalance))
460- then ([ScriptTransfer(i.caller, pmtAmount, pmtAssetId)] ++ suspendSuspicious())
461- else {
462- let stake1 = if (containsElement(stakingAssets, strAssetIdA))
463- then invoke(this, "stakeUnstake", [false, amountToPayA, strAssetIdA], nil)
464- else 0
465- if ((stake1 == stake1))
466- then {
467- let stake2 = if (containsElement(stakingAssets, strAssetIdB))
468- then invoke(this, "stakeUnstake", [false, amountToPayB, strAssetIdB], nil)
469- else 0
470- if ((stake2 == stake2))
471- then [IntegerEntry(keyBalanceA, (balanceA - amountToPayA)), IntegerEntry(keyBalanceB, (balanceB - amountToPayB)), IntegerEntry(keyShareAssetSupply, (shareAssetSupply - pmtAmount)), Burn(shareAssetId, pmtAmount), ScriptTransfer(i.caller, amountToPayA, assetIdA), ScriptTransfer(i.caller, amountToPayB, assetIdB)]
472- else throw("Strict value is not equal to itself.")
473- }
474- else throw("Strict value is not equal to itself.")
475- }
476- })
524+func exchange (estimatedAmountToReceive,minAmountToReceive) = {
525+ let $t02030920384 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
526+ let pmtAmount = $t02030920384._1
527+ let pmtAssetId = $t02030920384._2
528+ if (!(isActive))
529+ then throwIsInactive()
530+ else if ((0 >= estimatedAmountToReceive))
531+ then throw(("Estimated amount must be positive. Actual: " + toString(estimatedAmountToReceive)))
532+ else if ((minAmountToReceive > estimatedAmountToReceive))
533+ then throw(((("Minimal amount can't be greater than estimated. Estimated: " + toString(estimatedAmountToReceive)) + ". Minimal: ") + toString(minAmountToReceive)))
534+ else if ((size(i.payments) != 1))
535+ then throw("One attached payment expected")
536+ else if (!(hasEnoughBalance))
537+ then ([ScriptTransfer(i.caller, pmtAmount, pmtAssetId)] ++ suspendSuspicious())
538+ else if (if ((pmtAssetId != assetIdA))
539+ then (pmtAssetId != assetIdB)
540+ else false)
541+ then throwAssets()
542+ else if ((10000000 > pmtAmount))
543+ then throw("Only swap of 10.000000 or more tokens is allowed")
544+ else if (if ((exchangeRatioLimitMin > fraction(scale8, minAmountToReceive, pmtAmount)))
545+ then true
546+ else (fraction(scale8, estimatedAmountToReceive, pmtAmount) > exchangeRatioLimitMax))
547+ then throw("Incorrect args and pmt ratio")
548+ else {
549+ let sendAssetId = if ((pmtAssetId == assetIdA))
550+ then assetIdB
551+ else assetIdA
552+ let amount = calculateSendAmount(estimatedAmountToReceive, minAmountToReceive, pmtAmount, pmtAssetId)
553+ let governanceReward = fraction(amount, feeGovernance, feeScale6)
554+ let amountMinusFee = fraction(amount, (feeScale6 - fee), feeScale6)
555+ let $t02180622068 = if ((pmtAssetId == assetIdA))
556+ then $Tuple2((balanceA + pmtAmount), ((balanceB - amountMinusFee) - governanceReward))
557+ else $Tuple2(((balanceA - amountMinusFee) - governanceReward), (balanceB + pmtAmount))
558+ let newBalanceA = $t02180622068._1
559+ let newBalanceB = $t02180622068._2
560+ let dAppThresholdAmount = fraction((newBalanceA + newBalanceB), dAppThreshold, (2 * dAppThresholdScale2))
561+ if (if ((dAppThresholdAmount > newBalanceA))
562+ then true
563+ else (dAppThresholdAmount > newBalanceB))
564+ then throwThreshold(dAppThresholdAmount, newBalanceA, newBalanceB)
565+ else {
566+ let $t02236622439 = getAssetInfo(pmtAssetId)
567+ let pmtStrAssetId = $t02236622439._1
568+ let pmtAssetName = $t02236622439._2
569+ let pmtDecimals = $t02236622439._3
570+ let $t02245222529 = getAssetInfo(sendAssetId)
571+ let sendStrAssetId = $t02245222529._1
572+ let sendAssetName = $t02245222529._2
573+ let sendDecimals = $t02245222529._3
574+ let stake1 = if (containsElement(stakingAssets, pmtStrAssetId))
575+ then invoke(this, "stakeUnstake", [true, pmtAmount, pmtStrAssetId], nil)
576+ else 0
577+ if ((stake1 == stake1))
578+ then {
579+ let stake2 = if (containsElement(stakingAssets, sendStrAssetId))
580+ then invoke(this, "stakeUnstake", [false, (amountMinusFee + governanceReward), sendStrAssetId], nil)
581+ else 0
582+ if ((stake2 == stake2))
583+ then [IntegerEntry(kBalanceA, newBalanceA), IntegerEntry(kBalanceB, newBalanceB), IntegerEntry(kInvariant, invariantCalc(newBalanceA, newBalanceB)), ScriptTransfer(i.caller, amountMinusFee, sendAssetId), ScriptTransfer(walletAddress, governanceReward, sendAssetId)]
584+ else throw("Strict value is not equal to itself.")
585+ }
586+ else throw("Strict value is not equal to itself.")
587+ }
588+ }
589+ }
477590
478591
479592
480593 @Callable(i)
481-func exchange (minAmountToReceive) = valueOrElse(isActive(), {
482- let $t01821518290 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
483- let pmtAmount = $t01821518290._1
484- let pmtAssetId = $t01821518290._2
485- if (if ((balanceA == 0))
486- then true
487- else (balanceB == 0))
488- then throw("Can't exchange with zero balance")
489- else if ((0 >= minAmountToReceive))
490- then throw(("Minimal amount to receive must be positive. Actual: " + toString(minAmountToReceive)))
491- else if ((size(i.payments) != 1))
492- then throw("One attached payment expected")
493- else if (!(hasEnoughBalance))
494- then ([ScriptTransfer(i.caller, pmtAmount, pmtAssetId)] ++ suspendSuspicious())
495- else if ((pmtAssetId == assetIdA))
496- then {
497- let assetIdSend = assetIdB
498- let $t01884518967 = calculateFees(pmtAmount, minAmountToReceive, balanceA, balanceB)
499- let amountWithoutFee = $t01884518967._1
500- let amountWithFee = $t01884518967._2
501- let governanceReward = $t01884518967._3
502- let newBalanceA = (balanceA + pmtAmount)
503- let newBalanceB = ((balanceB - amountWithFee) - governanceReward)
504- let stake1 = if (containsElement(stakingAssets, strAssetIdA))
505- then invoke(this, "stakeUnstake", [true, pmtAmount, strAssetIdA], nil)
506- else 0
507- if ((stake1 == stake1))
508- then {
509- let stake2 = if (containsElement(stakingAssets, strAssetIdB))
510- then invoke(this, "stakeUnstake", [false, (amountWithFee + governanceReward), strAssetIdB], nil)
511- else 0
512- if ((stake2 == stake2))
513- then [IntegerEntry(keyBalanceA, newBalanceA), IntegerEntry(keyBalanceB, newBalanceB), ScriptTransfer(i.caller, amountWithFee, assetIdSend), ScriptTransfer(walletAddress, governanceReward, assetIdSend)]
514- else throw("Strict value is not equal to itself.")
515- }
516- else throw("Strict value is not equal to itself.")
517- }
518- else if ((pmtAssetId == assetIdB))
519- then {
520- let assetIdSend = assetIdA
521- let $t01992220044 = calculateFees(pmtAmount, minAmountToReceive, balanceB, balanceA)
522- let amountWithoutFee = $t01992220044._1
523- let amountWithFee = $t01992220044._2
524- let governanceReward = $t01992220044._3
525- let newBalanceA = ((balanceA - amountWithFee) - governanceReward)
526- let newBalanceB = (balanceB + pmtAmount)
527- let stake1 = if (containsElement(stakingAssets, strAssetIdA))
528- then invoke(this, "stakeUnstake", [false, (amountWithFee + governanceReward), strAssetIdA], nil)
529- else 0
530- if ((stake1 == stake1))
531- then {
532- let stake2 = if (containsElement(stakingAssets, strAssetIdB))
533- then invoke(this, "stakeUnstake", [true, pmtAmount, strAssetIdB], nil)
534- else 0
535- if ((stake2 == stake2))
536- then [IntegerEntry(keyBalanceA, newBalanceA), IntegerEntry(keyBalanceB, newBalanceB), ScriptTransfer(i.caller, amountWithFee, assetIdSend), ScriptTransfer(walletAddress, governanceReward, assetIdSend)]
537- else throw("Strict value is not equal to itself.")
538- }
539- else throw("Strict value is not equal to itself.")
540- }
541- else throw(((("Incorrect asset attached. Expected: " + strAssetIdA) + " or ") + strAssetIdB))
542- })
543-
544-
545-
546-@Callable(i)
547-func shutdown () = if (!(active))
548- then throw(("DApp is already suspended. Cause: " + valueOrElse(getString(this, keyCause), "the cause wasn't specified")))
549- else if (!(containsElement([adminPubKey1, adminPubKey2, adminPubKey3, adminPubKeyStartStop], i.callerPublicKey)))
550- then throw("Only admin can call this function")
594+func shutdown () = if (!(isActive))
595+ then throw(("DApp is already suspended. Cause: " + valueOrElse(getString(this, kCause), "the cause wasn't specified")))
596+ else if (!(containsElement([adminPubKey1, adminPubKey2, adminPubKey3, admStartStop], i.callerPublicKey)))
597+ then throwOnlyAdmin()
551598 else suspend("Paused by admin")
552599
553600
554601
555602 @Callable(i)
556-func activate () = if (active)
557- then throw("DApp is already active")
558- else if (!(containsElement([adminPubKey1, adminPubKey2, adminPubKey3, adminPubKeyStartStop], i.callerPublicKey)))
559- then throw("Only admin can call this function")
560- else [BooleanEntry(keyActive, true), DeleteEntry(keyCause)]
603+func activate () = if (isActive)
604+ then throwIsActive()
605+ else if (!(containsElement([adminPubKey1, adminPubKey2, adminPubKey3, admStartStop], i.callerPublicKey)))
606+ then throwOnlyAdmin()
607+ else [BooleanEntry(kActive, true), DeleteEntry(kCause)]
561608
562609
563610
564611 @Callable(i)
565-func takeIntoAccountExtraFunds () = valueOrElse(isActive(), {
612+func takeIntoAccountExtraFunds () = {
566613 let amountEnrollA = (accountBalanceWithStakedA - balanceA)
567614 let amountEnrollB = (accountBalanceWithStakedB - balanceB)
568- if ((i.caller != walletAddress))
569- then throw("Only the wallet can call this function")
570- else if (if ((0 > amountEnrollA))
571- then true
572- else (0 > amountEnrollB))
573- then suspend("Enroll amount negative")
574- else if (if ((amountEnrollA == 0))
575- then (amountEnrollB == 0)
576- else false)
577- then throw("No money to take")
578- else {
579- let stake1 = if (containsElement(stakingAssets, strAssetIdA))
580- then invoke(this, "stakeUnstake", [true, amountEnrollA, strAssetIdA], nil)
581- else 0
582- if ((stake1 == stake1))
583- then {
584- let stake2 = if (containsElement(stakingAssets, strAssetIdB))
585- then invoke(this, "stakeUnstake", [true, amountEnrollB, strAssetIdB], nil)
586- else 0
587- if ((stake2 == stake2))
588- then [IntegerEntry(keyBalanceA, (balanceA + amountEnrollA)), IntegerEntry(keyBalanceB, (balanceB + amountEnrollB)), IntegerEntry(("last_income_" + strAssetIdA), amountEnrollA), IntegerEntry(("last_income_" + strAssetIdB), amountEnrollB)]
589- else throw("Strict value is not equal to itself.")
590- }
591- else throw("Strict value is not equal to itself.")
592- }
593- })
615+ let invariantNew = invariantCalc((balanceA + amountEnrollA), (balanceB + amountEnrollB))
616+ if (!(isActive))
617+ then throwIsInactive()
618+ else if ((i.caller != walletAddress))
619+ then throw("Only the wallet can call this function")
620+ else if (if ((0 > amountEnrollA))
621+ then true
622+ else (0 > amountEnrollB))
623+ then suspend("Enroll amount negative")
624+ else if (if ((amountEnrollA == 0))
625+ then (amountEnrollB == 0)
626+ else false)
627+ then throw("No money to take")
628+ else {
629+ let stake1 = if (if (containsElement(stakingAssets, strAssetIdA))
630+ then (amountEnrollA > 0)
631+ else false)
632+ then invoke(this, "stakeUnstake", [true, amountEnrollA, strAssetIdA], nil)
633+ else 0
634+ if ((stake1 == stake1))
635+ then {
636+ let stake2 = if (if (containsElement(stakingAssets, strAssetIdB))
637+ then (amountEnrollB > 0)
638+ else false)
639+ then invoke(this, "stakeUnstake", [true, amountEnrollB, strAssetIdB], nil)
640+ else 0
641+ if ((stake2 == stake2))
642+ then [IntegerEntry(kInvariant, invariantNew), IntegerEntry(kBalanceA, (balanceA + amountEnrollA)), IntegerEntry(kBalanceB, (balanceB + amountEnrollB)), IntegerEntry(("last_income_" + strAssetIdA), amountEnrollA), IntegerEntry(("last_income_" + strAssetIdB), amountEnrollB)]
643+ else throw("Strict value is not equal to itself.")
644+ }
645+ else throw("Strict value is not equal to itself.")
646+ }
647+ }
594648
595649
596650
597651 @Callable(i)
598652 func stakeUnstake (stake,amount,assetIdString) = if ((i.caller != this))
599653 then throw("Only contract itself can invoke this function")
600- else if ((assetIdString == "WAVES"))
601- then {
602- let pool = addressFromStringValue(valueOrErrorMessage(getString(oracle, keyLeasingPool), "No leasing pool in oracle"))
603- let leasingId = getBinary(this, keyLeasingId)
604- let leasingAmount = valueOrElse(getInteger(this, keyLeasingAmount), 0)
605- let newLeaseAmount = if (stake)
606- then (leasingAmount + amount)
607- else (leasingAmount - amount)
608- let newLease = Lease(pool, newLeaseAmount)
609- let newLeaseId = calculateLeaseId(newLease)
610- let baseEtry = [newLease, BinaryEntry(keyLeasingId, newLeaseId), IntegerEntry(keyLeasingAmount, newLeaseAmount)]
611- match leasingId {
612- case lId: ByteVector =>
613- ([LeaseCancel(lId)] ++ baseEtry)
614- case _ =>
615- baseEtry
616- }
617- }
618- else {
619- let $t02377823881 = calcStakingParams(stake, amount, fromBase58String(assetIdString))
620- let call = $t02377823881._1
621- let addr = $t02377823881._2
622- let params = $t02377823881._3
623- let payments = $t02377823881._4
624- let inv = invoke(addr, call, params, payments)
625- if ((inv == inv))
626- then nil
627- else throw("Strict value is not equal to itself.")
628- }
654+ else {
655+ let $t02559125694 = calcStakingParams(stake, amount, fromBase58String(assetIdString))
656+ let call = $t02559125694._1
657+ let addr = $t02559125694._2
658+ let params = $t02559125694._3
659+ let payments = $t02559125694._4
660+ let inv = invoke(addr, call, params, payments)
661+ if ((inv == inv))
662+ then nil
663+ else throw("Strict value is not equal to itself.")
664+ }
629665
630666
631667
632668 @Callable(i)
633-func stakeAll () = valueOrElse(isActive(), if (!(containsElement([adminPubKey1, adminPubKey2, adminPubKey3, adminPubKeyStartStop], i.callerPublicKey)))
634- then throw("Only admin can call this function")
635- else {
636- let stake1 = if (containsElement(stakingAssets, strAssetIdA))
637- then {
638- let amountA = (balanceA - stakedAmountA)
639- if ((amountA > 0))
640- then invoke(this, "stakeUnstake", [true, amountA, strAssetIdA], nil)
641- else 0
642- }
643- else 0
644- if ((stake1 == stake1))
645- then {
646- let stake2 = if (containsElement(stakingAssets, strAssetIdB))
647- then {
648- let amountB = (balanceB - stakedAmountB)
649- if ((amountB > 0))
650- then invoke(this, "stakeUnstake", [true, amountB, strAssetIdB], nil)
651- else 0
652- }
653- else 0
654- if ((stake2 == stake2))
655- then nil
656- else throw("Strict value is not equal to itself.")
657- }
658- else throw("Strict value is not equal to itself.")
659- })
669+func stakeAll () = if (!(isActive))
670+ then throw("DApp is inactive at this moment")
671+ else if (!(containsElement([adminPubKey1, adminPubKey2, adminPubKey3, admStartStop], i.callerPublicKey)))
672+ then throw("Only admin can call this function")
673+ else {
674+ let stake1 = if (containsElement(stakingAssets, strAssetIdA))
675+ then {
676+ let amountA = (balanceA - stakedAmountA)
677+ if ((amountA > 0))
678+ then invoke(this, "stakeUnstake", [true, amountA, strAssetIdA], nil)
679+ else 0
680+ }
681+ else 0
682+ if ((stake1 == stake1))
683+ then {
684+ let stake2 = if (containsElement(stakingAssets, strAssetIdB))
685+ then {
686+ let amountB = (balanceB - stakedAmountB)
687+ if ((amountB > 0))
688+ then invoke(this, "stakeUnstake", [true, amountB, strAssetIdB], nil)
689+ else 0
690+ }
691+ else 0
692+ if ((stake2 == stake2))
693+ then nil
694+ else throw("Strict value is not equal to itself.")
695+ }
696+ else throw("Strict value is not equal to itself.")
697+ }
660698
661699
662700 @Verifier(tx)
678716 let callTakeIntoAccount = if ((inv.dApp == this))
679717 then (inv.function == "takeIntoAccountExtraFunds")
680718 else false
681- let exchangeToWaves = if (if (if ((inv.dApp == USDNToWavesExchanger))
682- then (inv.function == "exchange")
683- else false)
684- then (assetIdA == USDN)
685- else false)
686- then true
687- else if (if ((assetIdB == USDN))
688- then (size(inv.payments) == 1)
689- else false)
690- then (inv.payments[0].assetId == USDN)
691- else false
692- let exchangeToNSBTs = if (if (if ((inv.dApp == USDNToNSBTExchanger))
693- then (inv.function == "exchange")
694- else false)
695- then (assetIdA == NSBT)
696- else false)
697- then true
698- else if (if ((assetIdB == NSBT))
699- then (size(inv.payments) == 1)
700- else false)
701- then (inv.payments[0].assetId == USDN)
702- else false
703719 let signedByAdmin = if (if (if (sigVerify(tx.bodyBytes, tx.proofs[0], adminPubKey1))
704720 then true
705721 else sigVerify(tx.bodyBytes, tx.proofs[0], adminPubKey2))
706722 then true
707723 else sigVerify(tx.bodyBytes, tx.proofs[0], adminPubKey3))
708724 then true
709- else sigVerify(tx.bodyBytes, tx.proofs[0], adminPubKeyStaking)
710- if (if (if (if (callTakeIntoAccount)
711- then true
712- else exchangeToWaves)
713- then true
714- else exchangeToNSBTs)
725+ else sigVerify(tx.bodyBytes, tx.proofs[0], admStaking)
726+ if (if (callTakeIntoAccount)
715727 then signedByAdmin
716728 else false)
717729 then true
Full:
OldNewDifferences
11 {-# STDLIB_VERSION 5 #-}
22 {-# SCRIPT_TYPE ACCOUNT #-}
33 {-# CONTENT_TYPE DAPP #-}
4-let version = "1.0.0"
4+let version = "2.0.0"
55
6-let keyVersion = "version"
6+let kVersion = "version"
77
8-let keyActive = "active"
8+let kActive = "active"
99
10-let keyAssetIdA = "A_asset_id"
10+let kAssetIdA = "A_asset_id"
1111
12-let keyAssetIdB = "B_asset_id"
12+let kAssetIdB = "B_asset_id"
1313
14-let keyBalanceA = "A_asset_balance"
14+let kBalanceA = "A_asset_balance"
1515
16-let keyBalanceB = "B_asset_balance"
16+let kBalanceB = "B_asset_balance"
1717
18-let keyBalanceInitA = "A_asset_init"
18+let kShareAssetId = "share_asset_id"
1919
20-let keyBalanceInitB = "B_asset_init"
20+let kShareAssetSupply = "share_asset_supply"
2121
22-let keyShareAssetId = "share_asset_id"
22+let kFee = "commission"
2323
24-let keyShareAssetSupply = "share_asset_supply"
24+let kFeeScaleDelimiter = "commission_scale_delimiter"
2525
26-let keyCommission = "commission"
26+let kInvariant = "invariant"
2727
28-let keyCommissionScaleDelimiter = "commission_scale_delimiter"
29-
30-let keyCause = "shutdown_cause"
31-
32-let keyFirstHarvest = "first_harvest"
33-
34-let keyFirstHarvestHeight = "first_harvest_height"
35-
36-let kShareLimit = "share_limit_on_first_harvest"
37-
38-let kBasePeriod = "base_period"
39-
40-let kPeriodLength = "period_length"
41-
42-let kStartHeight = "start_height"
43-
44-let kFirstHarvestHeight = "first_harvest_height"
28+let kCause = "shutdown_cause"
4529
4630 let keyUSDNNSBTAddress = "staking_usdnnsbt_address"
4731
4832 let keyEURNAddress = "staking_eurn_address"
49-
50-let keyLeasingPool = "leasing_address"
51-
52-let keyLeasingAmount = "leasing_amount"
53-
54-let keyLeasingId = "leasing_id"
5533
5634 let keyAdminPubKey1 = "admin_pub_1"
5735
5836 let keyAdminPubKey2 = "admin_pub_2"
5937
6038 let keyAdminPubKey3 = "admin_pub_3"
39+
40+let USDNToWavesExchanger = Address(base58'3N8PGkzXhbtTvEwEQTtE2xiTJmsDEQ9XfoZ')
6141
6242 let oracle = Address(base58'3NBBWfzZtZtszaXbitTKnrB2xXwv26Bn7H9')
6343
6444 func getAdminPub (keyAdminPub) = match getString(oracle, keyAdminPub) {
6545 case string: String =>
6646 fromBase58String(string)
6747 case nothing =>
6848 throw("Admin public key is empty")
6949 }
7050
7151
7252 let adminPubKey1 = getAdminPub(keyAdminPubKey1)
7353
7454 let adminPubKey2 = getAdminPub(keyAdminPubKey2)
7555
7656 let adminPubKey3 = getAdminPub(keyAdminPubKey3)
7757
78-let adminPubKeyStartStop = base58'Kn7NpzaG12dLZgcHf2ipUftU6hbJygmrhFqQYE4B7ZK'
58+let admStartStop = base58'Kn7NpzaG12dLZgcHf2ipUftU6hbJygmrhFqQYE4B7ZK'
7959
80-let adminPubKeyStaking = base58'Kn7NpzaG12dLZgcHf2ipUftU6hbJygmrhFqQYE4B7ZK'
60+let admStaking = base58'Kn7NpzaG12dLZgcHf2ipUftU6hbJygmrhFqQYE4B7ZK'
8161
8262 let walletAddress = Address(base58'3NAGTtZz6WpupSN89NZD5rMZwwziZEg4Kx4')
8363
84-let votingAddress = Address(base58'3MrJgdL1GniipErHy44YF9idzLaUL2iX5DQ')
85-
8664 let USDN = base58'8UrfDVd5GreeUwm7uPk7eYz1eMv376kzR52C6sANPkwS'
87-
88-let NSBT = base58'36mg8NZTaFRDygiVwb8uBnLR51hetJruUCZcxhaVcHj9'
89-
90-let SWOP = base58'2HAJrwa8q4SxBx9cHYaBTQdBjdk5wwqdof7ccpAx2uhZ'
9165
9266 let EURN = base58'ECBCkHS68DckpBrzLeoRgYbFg7sCVqR176mPqbXsj9pA'
9367
94-let stakingAssets = ["WAVES", toBase58String(USDN), toBase58String(NSBT), toBase58String(EURN)]
68+let stakingAssets = [toBase58String(USDN), toBase58String(EURN)]
9569
9670 let stakingUSDNNSBTAddress = Address(fromBase58String(valueOrErrorMessage(getString(oracle, keyUSDNNSBTAddress), "no usdn staking address")))
9771
98-let stakingEURNAddress = Address(fromBase58String(valueOrErrorMessage(getString(oracle, keyEURNAddress), "no eurn staking address")))
72+let stakingEURNAddress = Address(fromBase58String(valueOrErrorMessage(getString(oracle, keyEURNAddress), "no usdn staking address")))
9973
100-let USDNToWavesExchanger = Address(base58'3N8PGkzXhbtTvEwEQTtE2xiTJmsDEQ9XfoZ')
74+let isActive = getBooleanValue(this, kActive)
10175
102-let USDNToNSBTExchanger = Address(base58'3MqW1t2cxdYy2emEMk3YtZkRwQPhHaTfWRe')
76+let strAssetIdA = getStringValue(this, kAssetIdA)
10377
104-let basePeriod = valueOrErrorMessage(getInteger(votingAddress, kBasePeriod), "Empty kBasePeriod")
105-
106-let startHeight = valueOrErrorMessage(getInteger(votingAddress, kStartHeight), "Empty kStartHeight")
107-
108-let periodLength = valueOrErrorMessage(getInteger(votingAddress, kPeriodLength), "Empty kPeriodLength")
109-
110-let firstHarvestEndPeriod = ((basePeriod + ((height - startHeight) / periodLength)) + 3)
111-
112-let active = getBooleanValue(this, keyActive)
113-
114-let strAssetIdA = getStringValue(this, keyAssetIdA)
115-
116-let strAssetIdB = getStringValue(this, keyAssetIdB)
78+let strAssetIdB = getStringValue(this, kAssetIdB)
11779
11880 let assetIdA = if ((strAssetIdA == "WAVES"))
11981 then unit
12082 else fromBase58String(strAssetIdA)
12183
12284 let assetIdB = if ((strAssetIdB == "WAVES"))
12385 then unit
12486 else fromBase58String(strAssetIdB)
12587
12688 let assetNameA = match assetIdA {
12789 case id: ByteVector =>
12890 value(assetInfo(id)).name
12991 case waves: Unit =>
13092 "WAVES"
13193 case _ =>
13294 throw("Match error")
13395 }
13496
13597 let assetNameB = match assetIdB {
13698 case id: ByteVector =>
13799 value(assetInfo(id)).name
138100 case waves: Unit =>
139101 "WAVES"
140102 case _ =>
141103 throw("Match error")
142104 }
143105
144-let balanceA = getIntegerValue(this, keyBalanceA)
106+let balanceA = getIntegerValue(this, kBalanceA)
145107
146-let balanceB = getIntegerValue(this, keyBalanceB)
108+let balanceB = getIntegerValue(this, kBalanceB)
147109
148-let shareAssetId = fromBase58String(getStringValue(this, keyShareAssetId))
110+let shareAssetId = fromBase58String(getStringValue(this, kShareAssetId))
149111
150-let shareAssetSupply = getIntegerValue(this, keyShareAssetSupply)
112+let shareAssetSupply = getIntegerValue(this, kShareAssetSupply)
151113
152-let commission = 3000
114+let invariant = getIntegerValue(this, kInvariant)
153115
154-let commissionGovernance = 1200
116+let fee = 500
155117
156-let commissionScaleDelimiter = 1000000
118+let feeGovernance = 200
157119
158-let scaleValue3 = 1000
120+let feeScale6 = 1000000
159121
160-let scaleValue8 = 100000000
122+let scale3 = 1000
161123
162-let slippageToleranceDelimiter = 1000
124+let scale8 = 100000000
163125
164-let scaleValue8Digits = 8
126+let scale12 = 1000000000000
127+
128+let slippageScale3 = 1000
129+
130+let digits8 = 8
131+
132+let dAppThreshold = 50
133+
134+let dAppThresholdScale2 = 100
135+
136+let exchangeRatioLimitMin = 90000000
137+
138+let exchangeRatioLimitMax = 110000000
139+
140+let alpha = 50
141+
142+let alphaDigits = 2
143+
144+let beta = 46000000
165145
166146 func accountBalance (assetId) = match assetId {
167147 case id: ByteVector =>
168148 assetBalance(this, id)
169149 case waves: Unit =>
170150 wavesBalance(this).available
171151 case _ =>
172152 throw("Match error")
173153 }
174154
175155
176156 func stakedAmount (assetId) = {
177157 let stakedAmountCalculated = match assetId {
178158 case aId: ByteVector =>
179- if (if ((aId == USDN))
180- then true
181- else (aId == NSBT))
159+ if ((aId == USDN))
182160 then getInteger(stakingUSDNNSBTAddress, ((("rpd_balance_" + toBase58String(aId)) + "_") + toString(this)))
183161 else if ((aId == EURN))
184162 then getInteger(stakingEURNAddress, ((("%s%s%s__stakingBalance__" + toBase58String(aId)) + "__") + toString(this)))
185163 else 0
186164 case _: Unit =>
187- valueOrElse(getInteger(this, keyLeasingAmount), 0)
165+ 0
188166 case _ =>
189167 throw("Match error")
190168 }
191169 match stakedAmountCalculated {
192170 case i: Int =>
193171 i
194172 case _ =>
195173 0
196174 }
197175 }
198176
199177
200178 let stakedAmountA = stakedAmount(assetIdA)
201179
202180 let stakedAmountB = stakedAmount(assetIdB)
203181
204-let assetInitA = getIntegerValue(this, keyBalanceInitA)
205-
206-let assetInitB = getIntegerValue(this, keyBalanceInitB)
207-
208182 let availableBalanceA = (balanceA - stakedAmountA)
209183
210184 let availableBalanceB = (balanceB - stakedAmountB)
211185
212186 let accountBalanceWithStakedA = (accountBalance(assetIdA) + stakedAmountA)
213187
214188 let accountBalanceWithStakedB = (accountBalance(assetIdB) + stakedAmountB)
215189
216190 let hasEnoughBalance = if ((accountBalanceWithStakedA >= balanceA))
217191 then (accountBalanceWithStakedB >= balanceB)
218192 else false
193+
194+func skewness (x,y) = (((fraction(scale12, x, y) + fraction(scale12, y, x)) / 2) / 10000)
195+
196+
197+func invariantCalc (x,y) = {
198+ let sk = skewness(x, y)
199+ (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)))
200+ }
201+
202+
203+func calculateSendAmount (amountToSendEstimated,minTokenReceiveAmount,tokenReceiveAmount,tokenId) = {
204+ let slippageValue = (scale8 - ((scale8 * 1) / 10000000))
205+ let deltaBetweenMaxAndMinSendValue = (amountToSendEstimated - minTokenReceiveAmount)
206+ let x = (balanceA + tokenReceiveAmount)
207+ let y = (balanceB + tokenReceiveAmount)
208+ let invariantNew = if ((tokenId == assetIdA))
209+ then invariantCalc(x, (balanceB - amountToSendEstimated))
210+ else if ((tokenId == assetIdB))
211+ then invariantCalc((balanceA - amountToSendEstimated), y)
212+ else throw("Wrong asset in payment")
213+ let invariantEstimatedRatio = fraction(scale8, invariant, invariantNew)
214+ func getStepAmount (acc,step) = if ((acc == -1))
215+ then {
216+ let amountToSend = (amountToSendEstimated - ((step * deltaBetweenMaxAndMinSendValue) / 5))
217+ let stepInvariant = if ((tokenId == assetIdA))
218+ then invariantCalc(x, (balanceB - amountToSend))
219+ else invariantCalc((balanceA - amountToSend), y)
220+ if ((stepInvariant > invariant))
221+ then amountToSend
222+ else -1
223+ }
224+ else acc
225+
226+ let stepAmount = {
227+ let $l = [1, 2, 3, 4, 5]
228+ let $s = size($l)
229+ let $acc0 = -1
230+ func $f0_1 ($a,$i) = if (($i >= $s))
231+ then $a
232+ else getStepAmount($a, $l[$i])
233+
234+ func $f0_2 ($a,$i) = if (($i >= $s))
235+ then $a
236+ else throw("List size exceeds 5")
237+
238+ $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5)
239+ }
240+ if ((0 > stepAmount))
241+ then throw("something went wrong while working with amountToSend")
242+ else if (if ((invariantEstimatedRatio > slippageValue))
243+ then (invariantNew > invariant)
244+ else false)
245+ then amountToSendEstimated
246+ else stepAmount
247+ }
248+
219249
220250 func getAssetInfo (assetId) = match assetId {
221251 case id: ByteVector =>
222252 let stringId = toBase58String(id)
223253 let info = valueOrErrorMessage(assetInfo(id), (("Asset " + stringId) + " doesn't exist"))
224254 $Tuple3(stringId, info.name, info.decimals)
225255 case waves: Unit =>
226256 $Tuple3("WAVES", "WAVES", 8)
227257 case _ =>
228258 throw("Match error")
229259 }
230260
231261
232-func getAssetInfoFromString (assetStr) = if ((assetStr == "WAVES"))
233- then $Tuple3("WAVES", "WAVES", 8)
234- else {
235- let stringId = assetStr
236- let id = fromBase58String(assetStr)
237- let info = valueOrErrorMessage(assetInfo(id), (("Asset " + stringId) + " doesn't exist"))
238- $Tuple3(stringId, info.name, info.decimals)
239- }
262+func suspend (cause) = [BooleanEntry(kActive, false), StringEntry(kCause, cause)]
240263
241264
242-func suspend (cause) = [BooleanEntry(keyActive, false), StringEntry(keyCause, cause)]
265+func throwIsActive () = throw("DApp is already active")
266+
267+
268+func throwIsInactive () = throw("DApp is inactive at this moment")
269+
270+
271+func throwOnlyAdmin () = throw("Only admin can call this function")
272+
273+
274+func throwAssets () = throw(((("Incorrect assets attached. Expected: " + strAssetIdA) + " and ") + strAssetIdB))
275+
276+
277+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))
278+
279+
280+func suspendSuspicious () = suspend(((((((((((((((("Suspicious state. Actual balances: " + toString(balanceA)) + " ") + assetNameA) + ", ") + toString(balanceB)) + " ") + assetNameB) + ". State: ") + toString(accountBalance(assetIdA))) + " ") + assetNameA) + ", ") + toString(accountBalance(assetIdB))) + " ") + assetNameB))
243281
244282
245283 func calcStakingFuncAndAddres (stake,assetId) = if (stake)
246284 then if ((assetId == USDN))
247285 then $Tuple2("lockNeutrino", stakingUSDNNSBTAddress)
248- else if ((assetId == NSBT))
249- then $Tuple2("lockNsbt", stakingUSDNNSBTAddress)
250- else $Tuple2("startStaking", stakingEURNAddress)
286+ else $Tuple2("startStaking", stakingEURNAddress)
251287 else if ((assetId == USDN))
252288 then $Tuple2("unlockNeutrino", stakingUSDNNSBTAddress)
253- else if ((assetId == NSBT))
254- then $Tuple2("unlockNsbt", stakingUSDNNSBTAddress)
255- else $Tuple2("stopStaking", stakingEURNAddress)
289+ else $Tuple2("stopStaking", stakingEURNAddress)
256290
257291
258292 func calcStakingParams (stake,amount,assetId) = if (stake)
259293 then {
260- let $t069226988 = calcStakingFuncAndAddres(stake, assetId)
261- let call = $t069226988._1
262- let stakingAddr = $t069226988._2
294+ let $t087598825 = calcStakingFuncAndAddres(stake, assetId)
295+ let call = $t087598825._1
296+ let stakingAddr = $t087598825._2
263297 $Tuple4(call, stakingAddr, nil, [AttachedPayment(assetId, amount)])
264298 }
265299 else {
266- let $t070747140 = calcStakingFuncAndAddres(stake, assetId)
267- let call = $t070747140._1
268- let stakingAddr = $t070747140._2
300+ let $t089118977 = calcStakingFuncAndAddres(stake, assetId)
301+ let call = $t089118977._1
302+ let stakingAddr = $t089118977._2
269303 $Tuple4(call, stakingAddr, [amount, toBase58String(assetId)], nil)
270304 }
271305
272306
273-func calculateFees (pmtAmount,minAmountToReceive,tokenFrom,tokenTo) = {
274- let amountWithoutFee = fraction(tokenTo, pmtAmount, (pmtAmount + tokenFrom))
275- let amountWithFee = fraction(amountWithoutFee, (commissionScaleDelimiter - commission), commissionScaleDelimiter)
276- let governanceReward = fraction(amountWithoutFee, commissionGovernance, commissionScaleDelimiter)
277- if ((minAmountToReceive > amountWithFee))
278- then throw(((("Calculated amount to receive " + toString(amountWithFee)) + " is less than specified minimum ") + toString(minAmountToReceive)))
279- else $Tuple3(amountWithoutFee, amountWithFee, governanceReward)
280- }
281-
282-
283-func suspendSuspicious () = suspend(((((((((((((((("Suspicious state. Actual balances: " + toString(accountBalanceWithStakedA)) + " ") + assetNameA) + ", ") + toString(accountBalanceWithStakedB)) + " ") + assetNameB) + ". State: ") + toString(balanceA)) + " ") + assetNameA) + ", ") + toString(balanceB)) + " ") + assetNameB))
284-
285-
286-func isActive () = if (active)
287- then unit
288- else throw("DApp is inactive at this moment")
289-
290-
291307 @Callable(i)
292-func init (firstHarvest) = {
293- let $t083108387 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
294- let pmtAmountA = $t083108387._1
295- let pmtAssetIdA = $t083108387._2
296- let $t083928469 = $Tuple2(i.payments[1].amount, i.payments[1].assetId)
297- let pmtAmountB = $t083928469._1
298- let pmtAssetIdB = $t083928469._2
299- let $t084748551 = getAssetInfo(pmtAssetIdA)
300- let pmtStrAssetIdA = $t084748551._1
301- let pmtAssetNameA = $t084748551._2
302- let pmtDecimalsA = $t084748551._3
303- let $t085568633 = getAssetInfo(pmtAssetIdB)
304- let pmtStrAssetIdB = $t085568633._1
305- let pmtAssetNameB = $t085568633._2
306- let pmtDecimalsB = $t085568633._3
307- if (!(containsElement([adminPubKey1, adminPubKey2, adminPubKey3, adminPubKeyStaking], i.callerPublicKey)))
308- then throw("Only admin can call this function")
309- else if (isDefined(getBoolean(this, keyActive)))
310- then throw("DApp is already active")
311- else if ((pmtAssetIdA == pmtAssetIdB))
312- then throw("Assets must be different")
313- else {
314- let shareName = ((("s" + take(pmtAssetNameA, 7)) + "_") + take(pmtAssetNameB, 7))
315- let shareDescription = ((((("ShareToken of SwopFi protocol for " + pmtAssetNameA) + " and ") + pmtAssetNameB) + " at address ") + toString(this))
316- let shareDecimals = ((pmtDecimalsA + pmtDecimalsB) / 2)
317- let arg1 = pow(pmtAmountA, pmtDecimalsA, 5, 1, pmtDecimalsA, DOWN)
318- let arg2 = pow(pmtAmountB, pmtDecimalsB, 5, 1, pmtDecimalsB, DOWN)
319- let arg3 = pow(10, 0, shareDecimals, 0, 0, DOWN)
320- let shareInitialSupply = fraction(arg1, arg2, arg3)
321- let shareIssue = Issue(shareName, shareDescription, shareInitialSupply, shareDecimals, true)
322- let shareIssueId = calculateAssetId(shareIssue)
323- let stake1 = if (containsElement(stakingAssets, pmtStrAssetIdA))
324- then invoke(this, "stakeUnstake", [true, pmtAmountA, pmtStrAssetIdA], nil)
325- else 0
326- if ((stake1 == stake1))
327- then {
328- let stake2 = if (containsElement(stakingAssets, pmtStrAssetIdB))
329- then invoke(this, "stakeUnstake", [true, pmtAmountB, pmtStrAssetIdB], nil)
330- else 0
331- if ((stake2 == stake2))
332- then {
333- let baseEntry = [StringEntry(keyVersion, version), BooleanEntry(keyActive, true), StringEntry(keyAssetIdA, pmtStrAssetIdA), StringEntry(keyAssetIdB, pmtStrAssetIdB), IntegerEntry(keyBalanceA, pmtAmountA), IntegerEntry(keyBalanceB, pmtAmountB), IntegerEntry(keyCommission, commission), IntegerEntry(keyCommissionScaleDelimiter, commissionScaleDelimiter), shareIssue, StringEntry(keyShareAssetId, toBase58String(shareIssueId)), IntegerEntry(keyShareAssetSupply, shareInitialSupply), ScriptTransfer(i.caller, shareInitialSupply, shareIssueId)]
334- if (firstHarvest)
335- then (baseEntry ++ [BooleanEntry(keyFirstHarvest, firstHarvest), IntegerEntry(keyFirstHarvestHeight, (startHeight + (firstHarvestEndPeriod * periodLength)))])
336- else baseEntry
337- }
338- else throw("Strict value is not equal to itself.")
339- }
340- else throw("Strict value is not equal to itself.")
341- }
308+func init () = {
309+ let $t090829159 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
310+ let pmtAmountA = $t090829159._1
311+ let pmtAssetIdA = $t090829159._2
312+ let $t091649241 = $Tuple2(i.payments[1].amount, i.payments[1].assetId)
313+ let pmtAmountB = $t091649241._1
314+ let pmtAssetIdB = $t091649241._2
315+ let $t092469323 = getAssetInfo(pmtAssetIdA)
316+ let pmtStrAssetIdA = $t092469323._1
317+ let pmtAssetNameA = $t092469323._2
318+ let pmtDecimalsA = $t092469323._3
319+ let $t093289405 = getAssetInfo(pmtAssetIdB)
320+ let pmtStrAssetIdB = $t093289405._1
321+ let pmtAssetNameB = $t093289405._2
322+ let pmtDecimalsB = $t093289405._3
323+ if (isDefined(getBoolean(this, kActive)))
324+ then throwIsActive()
325+ else if ((pmtAssetIdA == pmtAssetIdB))
326+ then throw("Assets must be different")
327+ else {
328+ let shareName = ((("s" + take(pmtAssetNameA, 7)) + "_") + take(pmtAssetNameB, 7))
329+ let shareDescription = ((((("ShareToken of SwopFi protocol for " + pmtAssetNameA) + " and ") + pmtAssetNameB) + " at address ") + toString(this))
330+ let shareDecimals = ((pmtDecimalsA + pmtDecimalsB) / 2)
331+ let shareInitialSupply = fraction(pow(pmtAmountA, pmtDecimalsA, 5, 1, pmtDecimalsA, DOWN), pow(pmtAmountB, pmtDecimalsB, 5, 1, pmtDecimalsB, DOWN), pow(10, 0, shareDecimals, 0, 0, DOWN))
332+ let shareIssue = Issue(shareName, shareDescription, shareInitialSupply, shareDecimals, true)
333+ let shareIssueId = calculateAssetId(shareIssue)
334+ let invariantCalculated = invariantCalc(pmtAmountA, pmtAmountB)
335+ let stake1 = if (containsElement(stakingAssets, pmtStrAssetIdA))
336+ then invoke(this, "stakeUnstake", [true, pmtAmountA, pmtStrAssetIdA], nil)
337+ else 0
338+ if ((stake1 == stake1))
339+ then {
340+ let stake2 = if (containsElement(stakingAssets, pmtStrAssetIdB))
341+ then invoke(this, "stakeUnstake", [true, pmtAmountB, pmtStrAssetIdB], nil)
342+ else 0
343+ if ((stake2 == stake2))
344+ 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)]
345+ else throw("Strict value is not equal to itself.")
346+ }
347+ else throw("Strict value is not equal to itself.")
348+ }
342349 }
343350
344351
345352
346353 @Callable(i)
347-func initWithInitRatio (amtAssetA,amtAssetB,strAssetIdA,strAssetIdB,firstHarvest) = {
348- let $t01122211309 = getAssetInfoFromString(strAssetIdA)
349- let pmtStrAssetIdA = $t01122211309._1
350- let pmtAssetNameA = $t01122211309._2
351- let pmtDecimalsA = $t01122211309._3
352- let $t01131411401 = getAssetInfoFromString(strAssetIdB)
353- let pmtStrAssetIdB = $t01131411401._1
354- let pmtAssetNameB = $t01131411401._2
355- let pmtDecimalsB = $t01131411401._3
356- if (!(containsElement([adminPubKey1, adminPubKey2, adminPubKey3, adminPubKeyStaking], i.callerPublicKey)))
357- then throw("Only admin can call this function")
358- else if (isDefined(getBoolean(this, keyActive)))
359- then throw("DApp is already active")
360- else if ((strAssetIdA == strAssetIdB))
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 = 0
367- let shareIssue = Issue(shareName, shareDescription, shareInitialSupply, shareDecimals, true)
368- let shareIssueId = calculateAssetId(shareIssue)
369- let baseEntry = [StringEntry(keyVersion, version), BooleanEntry(keyActive, true), StringEntry(keyAssetIdA, pmtStrAssetIdA), StringEntry(keyAssetIdB, pmtStrAssetIdB), IntegerEntry(keyBalanceInitA, amtAssetA), IntegerEntry(keyBalanceInitB, amtAssetB), IntegerEntry(keyBalanceA, 0), IntegerEntry(keyBalanceB, 0), IntegerEntry(keyCommission, commission), IntegerEntry(keyCommissionScaleDelimiter, commissionScaleDelimiter), shareIssue, StringEntry(keyShareAssetId, toBase58String(shareIssueId)), IntegerEntry(keyShareAssetSupply, shareInitialSupply)]
370- if (firstHarvest)
371- then (baseEntry ++ [BooleanEntry(keyFirstHarvest, firstHarvest), IntegerEntry(keyFirstHarvestHeight, (startHeight + (firstHarvestEndPeriod * periodLength)))])
372- else baseEntry
373- }
354+func replenishWithTwoTokens (slippageTolerance) = {
355+ let pmtAssetIdA = i.payments[0].assetId
356+ let pmtAssetIdB = i.payments[1].assetId
357+ let pmtAmountA = i.payments[0].amount
358+ let pmtAmountB = i.payments[1].amount
359+ let $t01192111998 = getAssetInfo(pmtAssetIdA)
360+ let pmtStrAssetIdA = $t01192111998._1
361+ let pmtAssetNameA = $t01192111998._2
362+ let pmtDecimalsA = $t01192111998._3
363+ let $t01200312197 = getAssetInfo(pmtAssetIdB)
364+ let pmtStrAssetIdB = $t01200312197._1
365+ let pmtAssetNameB = $t01200312197._2
366+ let pmtDecimalsB = $t01200312197._3
367+ let tokenRatio = fraction(fraction(scale8, balanceA, pmtAmountA), scale3, fraction(scale8, balanceB, pmtAmountB))
368+ let ratioShareTokensInA = fraction(scale8, pmtAmountA, balanceA)
369+ let ratioShareTokensInB = fraction(scale8, pmtAmountB, balanceB)
370+ let shareTokenToPayAmount = fraction(min([ratioShareTokensInA, ratioShareTokensInB]), shareAssetSupply, scale8)
371+ let invariantCalculated = invariantCalc((balanceA + pmtAmountA), (balanceB + pmtAmountB))
372+ if (!(isActive))
373+ then throwIsInactive()
374+ else if (if ((0 > slippageTolerance))
375+ then true
376+ else (slippageTolerance > 10))
377+ then throw("Slippage tolerance must be <= 1%")
378+ else if ((size(i.payments) != 2))
379+ then throw("Two attached assets expected")
380+ else if (if ((pmtAssetIdA != assetIdA))
381+ then true
382+ else (pmtAssetIdB != assetIdB))
383+ then throwAssets()
384+ else if (if ((((scale3 * (slippageScale3 - slippageTolerance)) / slippageScale3) > tokenRatio))
385+ then true
386+ else (tokenRatio > ((scale3 * (slippageScale3 + slippageTolerance)) / slippageScale3)))
387+ then throw("Incorrect assets amount: amounts must have the contract ratio")
388+ else if ((shareTokenToPayAmount == 0))
389+ then throw("Too small amount to replenish")
390+ else if (!(hasEnoughBalance))
391+ then ([ScriptTransfer(i.caller, pmtAmountA, pmtAssetIdA), ScriptTransfer(i.caller, pmtAmountB, pmtAssetIdB)] ++ suspendSuspicious())
392+ else {
393+ let stake1 = if (containsElement(stakingAssets, pmtStrAssetIdA))
394+ then invoke(this, "stakeUnstake", [true, pmtAmountA, pmtStrAssetIdA], nil)
395+ else 0
396+ if ((stake1 == stake1))
397+ then {
398+ let stake2 = if (containsElement(stakingAssets, pmtStrAssetIdB))
399+ then invoke(this, "stakeUnstake", [true, pmtAmountB, pmtStrAssetIdB], nil)
400+ else 0
401+ if ((stake2 == stake2))
402+ then [IntegerEntry(kBalanceA, (balanceA + pmtAmountA)), IntegerEntry(kBalanceB, (balanceB + pmtAmountB)), IntegerEntry(kShareAssetSupply, (shareAssetSupply + shareTokenToPayAmount)), IntegerEntry(kInvariant, invariantCalculated), Reissue(shareAssetId, shareTokenToPayAmount, true), ScriptTransfer(i.caller, shareTokenToPayAmount, shareAssetId)]
403+ else throw("Strict value is not equal to itself.")
404+ }
405+ else throw("Strict value is not equal to itself.")
406+ }
374407 }
375408
376409
377410
378411 @Callable(i)
379-func keepLimitForFirstHarvest (shareLimit) = valueOrElse(isActive(), if (!(containsElement([adminPubKey1, adminPubKey2, adminPubKey3, adminPubKeyStaking], i.callerPublicKey)))
380- then throw("Only admin can call this function")
381- else [IntegerEntry(kShareLimit, shareLimit)])
412+func replenishWithOneToken (virtualSwapTokenPay,virtualSwapTokenGet) = {
413+ let $t01449614571 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
414+ let pmtAmount = $t01449614571._1
415+ let pmtAssetId = $t01449614571._2
416+ let $t01457614649 = getAssetInfo(pmtAssetId)
417+ let pmtStrAssetId = $t01457614649._1
418+ let pmtAssetName = $t01457614649._2
419+ let pmtDecimals = $t01457614649._3
420+ let pmtMinThreshold = 5000000
421+ let thresholdValueForMinTolerance = 50000000
422+ let tolerance = if ((thresholdValueForMinTolerance > pmtAmount))
423+ then 100000
424+ else 1
425+ let slippageValueMinForReplenish = (scale8 - ((scale8 * tolerance) / 10000000))
426+ let slippageValueMaxForReplenish = (scale8 + ((scale8 * tolerance) / 10000000))
427+ let slippageValueMinForSwap = (scale8 - ((scale8 * 1) / 10000000))
428+ if (!(isActive))
429+ then throwIsInactive()
430+ else if ((pmtMinThreshold > pmtAmount))
431+ then throw((((("Payment amount " + toString(pmtAmount)) + " does not exceed the minimum amount of ") + toString(pmtMinThreshold)) + " tokens"))
432+ else if ((size(i.payments) != 1))
433+ then throw("One attached payment expected")
434+ else if (!(hasEnoughBalance))
435+ then ([ScriptTransfer(i.caller, pmtAmount, pmtAssetId)] ++ suspendSuspicious())
436+ else if (if ((pmtAssetId != assetIdA))
437+ then (pmtAssetId != assetIdB)
438+ else false)
439+ then throwAssets()
440+ else {
441+ let $t01566116426 = if ((pmtAssetId == assetIdA))
442+ then $Tuple7((pmtAmount - virtualSwapTokenPay), virtualSwapTokenGet, (balanceA + virtualSwapTokenPay), (balanceB - virtualSwapTokenGet), invariantCalc((balanceA + pmtAmount), balanceB), (balanceA + pmtAmount), balanceB)
443+ else $Tuple7(virtualSwapTokenGet, (pmtAmount - virtualSwapTokenPay), (balanceA - virtualSwapTokenGet), (balanceB + virtualSwapTokenPay), invariantCalc(balanceA, (balanceB + pmtAmount)), balanceA, (balanceB + pmtAmount))
444+ let virtualReplenishA = $t01566116426._1
445+ let virtualReplenishB = $t01566116426._2
446+ let balanceAfterSwapA = $t01566116426._3
447+ let balanceAfterSwapB = $t01566116426._4
448+ let invariantCalculated = $t01566116426._5
449+ let newBalanceA = $t01566116426._6
450+ let newBalanceB = $t01566116426._7
451+ let newBalanceEntry = if ((pmtAssetId == assetIdA))
452+ then IntegerEntry(kBalanceA, newBalanceA)
453+ else IntegerEntry(kBalanceB, newBalanceB)
454+ let invariantNew = invariantCalc(balanceAfterSwapA, balanceAfterSwapB)
455+ let invariantEstimatedRatio = fraction(scale8, invariant, invariantNew)
456+ let ratioVirtualBalanceToVirtualReplenish = (fraction((scale8 * scale8), balanceAfterSwapA, balanceAfterSwapB) / fraction(scale8, virtualReplenishA, virtualReplenishB))
457+ let dAppThresholdAmount = fraction((newBalanceA + newBalanceB), dAppThreshold, (2 * dAppThresholdScale2))
458+ if (if ((slippageValueMinForSwap >= invariantEstimatedRatio))
459+ then true
460+ else (invariant > invariantNew))
461+ then throw("Incorrect virtualSwapTokenPay or virtualSwapTokenGet value")
462+ else if (if ((slippageValueMinForReplenish > ratioVirtualBalanceToVirtualReplenish))
463+ then true
464+ else (ratioVirtualBalanceToVirtualReplenish > slippageValueMaxForReplenish))
465+ then throw("Swap with virtualSwapTokenPay and virtualSwapTokenGet is possible, but ratio after virtual swap is incorrect")
466+ else if (if ((dAppThresholdAmount > newBalanceA))
467+ then true
468+ else (dAppThresholdAmount > newBalanceB))
469+ then throwThreshold(dAppThresholdAmount, newBalanceA, newBalanceB)
470+ else {
471+ let stake1 = if (containsElement(stakingAssets, pmtStrAssetId))
472+ then invoke(this, "stakeUnstake", [true, pmtAmount, pmtStrAssetId], nil)
473+ else 0
474+ if ((stake1 == stake1))
475+ then {
476+ let ratioShareTokensInA = fraction(virtualReplenishA, scale8, balanceAfterSwapA)
477+ let ratioShareTokensInB = fraction(virtualReplenishB, scale8, balanceAfterSwapB)
478+ let shareTokenToPayAmount = fraction(min([ratioShareTokensInA, ratioShareTokensInB]), shareAssetSupply, scale8)
479+[Reissue(shareAssetId, shareTokenToPayAmount, true), ScriptTransfer(i.caller, shareTokenToPayAmount, shareAssetId), IntegerEntry(kShareAssetSupply, (shareAssetSupply + shareTokenToPayAmount)), newBalanceEntry, IntegerEntry(kInvariant, invariantCalculated)]
480+ }
481+ else throw("Strict value is not equal to itself.")
482+ }
483+ }
484+ }
382485
383486
384487
385488 @Callable(i)
386-func replenishWithTwoTokens (slippageTolerance) = valueOrElse(isActive(), {
387- let pmtAssetIdA = i.payments[0].assetId
388- let pmtAssetIdB = i.payments[1].assetId
389- let pmtAmountA = i.payments[0].amount
390- let pmtAmountB = i.payments[1].amount
391- let $t01386913946 = getAssetInfo(pmtAssetIdA)
392- let pmtStrAssetIdA = $t01386913946._1
393- let pmtAssetNameA = $t01386913946._2
394- let pmtDecimalsA = $t01386913946._3
395- let $t01395114028 = getAssetInfo(pmtAssetIdB)
396- let pmtStrAssetIdB = $t01395114028._1
397- let pmtAssetNameB = $t01395114028._2
398- let pmtDecimalsB = $t01395114028._3
399- let inital = if (if ((balanceA == 0))
400- then (balanceB == 0)
401- else false)
402- then true
403- else false
404- let tokenRatio = if (inital)
405- then fraction(fraction(assetInitA, scaleValue8, pmtAmountA), scaleValue3, fraction(assetInitB, scaleValue8, pmtAmountB))
406- else fraction(fraction(balanceA, scaleValue8, pmtAmountA), scaleValue3, fraction(balanceB, scaleValue8, pmtAmountB))
407- let shareDecimals = ((pmtDecimalsA + pmtDecimalsB) / 2)
408- let shareTokenToPayAmount = if (inital)
409- then fraction(pow(pmtAmountA, pmtDecimalsA, 5, 1, pmtDecimalsA, DOWN), pow(pmtAmountB, pmtDecimalsB, 5, 1, pmtDecimalsB, DOWN), pow(10, 0, shareDecimals, 0, 0, DOWN))
410- else fraction(min([fraction(pmtAmountA, scaleValue8, balanceA), fraction(pmtAmountB, scaleValue8, balanceB)]), shareAssetSupply, scaleValue8)
411- if (if ((0 > slippageTolerance))
412- then true
413- else (slippageTolerance > slippageToleranceDelimiter))
414- then throw(((("Slippage tolerance must be between 0 and " + toString(slippageToleranceDelimiter)) + " inclusively. Actual: ") + toString(slippageTolerance)))
415- else if ((size(i.payments) != 2))
416- then throw("Two attached assets expected")
417- else if (if ((pmtAssetIdA != assetIdA))
418- then true
419- else (pmtAssetIdB != assetIdB))
420- then throw(((("Incorrect assets attached. Expected: " + strAssetIdA) + " and ") + strAssetIdB))
421- else if (if ((((scaleValue3 * (slippageToleranceDelimiter - slippageTolerance)) / slippageToleranceDelimiter) > tokenRatio))
422- then true
423- else (tokenRatio > ((scaleValue3 * (slippageToleranceDelimiter + slippageTolerance)) / slippageToleranceDelimiter)))
424- then throw("Incorrect assets amount: amounts must have the contract ratio")
425- else if ((shareTokenToPayAmount == 0))
426- then throw("Too small amount to replenish")
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)
489+func withdraw () = {
490+ let $t01865218795 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
491+ let pmtAmount = $t01865218795._1
492+ let pmtAssetId = $t01865218795._2
493+ let amountToPayA = fraction(pmtAmount, balanceA, shareAssetSupply)
494+ let amountToPayB = fraction(pmtAmount, balanceB, shareAssetSupply)
495+ let invariantCalculated = invariantCalc((balanceA - amountToPayA), (balanceB - amountToPayB))
496+ if (!(isActive))
497+ then throwIsInactive()
498+ else if ((size(i.payments) != 1))
499+ then throw("One attached payment expected")
500+ else if ((pmtAssetId != shareAssetId))
501+ then throw(("Incorrect asset attached. Expected: " + toBase58String(shareAssetId)))
502+ else if (!(hasEnoughBalance))
503+ then ([ScriptTransfer(i.caller, pmtAmount, pmtAssetId)] ++ suspendSuspicious())
504+ else {
505+ let stake1 = if (containsElement(stakingAssets, strAssetIdA))
506+ then invoke(this, "stakeUnstake", [false, amountToPayA, strAssetIdA], nil)
507+ else 0
508+ if ((stake1 == stake1))
509+ then {
510+ let stake2 = if (containsElement(stakingAssets, strAssetIdB))
511+ then invoke(this, "stakeUnstake", [false, amountToPayB, strAssetIdB], nil)
432512 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 [Reissue(shareAssetId, shareTokenToPayAmount, true), IntegerEntry(keyBalanceA, (balanceA + pmtAmountA)), IntegerEntry(keyBalanceB, (balanceB + pmtAmountB)), IntegerEntry(keyShareAssetSupply, (shareAssetSupply + shareTokenToPayAmount)), ScriptTransfer(i.caller, shareTokenToPayAmount, shareAssetId)]
440- else throw("Strict value is not equal to itself.")
441- }
513+ if ((stake2 == stake2))
514+ 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)]
442515 else throw("Strict value is not equal to itself.")
443516 }
444- })
517+ else throw("Strict value is not equal to itself.")
518+ }
519+ }
445520
446521
447522
448523 @Callable(i)
449-func withdraw () = valueOrElse(isActive(), {
450- let $t01683416909 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
451- let pmtAmount = $t01683416909._1
452- let pmtAssetId = $t01683416909._2
453- let amountToPayA = fraction(pmtAmount, balanceA, shareAssetSupply)
454- let amountToPayB = fraction(pmtAmount, balanceB, shareAssetSupply)
455- if ((size(i.payments) != 1))
456- then throw("One attached payment expected")
457- else if ((pmtAssetId != shareAssetId))
458- then throw(("Incorrect asset attached. Expected: " + toBase58String(shareAssetId)))
459- else if (!(hasEnoughBalance))
460- then ([ScriptTransfer(i.caller, pmtAmount, pmtAssetId)] ++ suspendSuspicious())
461- else {
462- let stake1 = if (containsElement(stakingAssets, strAssetIdA))
463- then invoke(this, "stakeUnstake", [false, amountToPayA, strAssetIdA], nil)
464- else 0
465- if ((stake1 == stake1))
466- then {
467- let stake2 = if (containsElement(stakingAssets, strAssetIdB))
468- then invoke(this, "stakeUnstake", [false, amountToPayB, strAssetIdB], nil)
469- else 0
470- if ((stake2 == stake2))
471- then [IntegerEntry(keyBalanceA, (balanceA - amountToPayA)), IntegerEntry(keyBalanceB, (balanceB - amountToPayB)), IntegerEntry(keyShareAssetSupply, (shareAssetSupply - pmtAmount)), Burn(shareAssetId, pmtAmount), ScriptTransfer(i.caller, amountToPayA, assetIdA), ScriptTransfer(i.caller, amountToPayB, assetIdB)]
472- else throw("Strict value is not equal to itself.")
473- }
474- else throw("Strict value is not equal to itself.")
475- }
476- })
524+func exchange (estimatedAmountToReceive,minAmountToReceive) = {
525+ let $t02030920384 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
526+ let pmtAmount = $t02030920384._1
527+ let pmtAssetId = $t02030920384._2
528+ if (!(isActive))
529+ then throwIsInactive()
530+ else if ((0 >= estimatedAmountToReceive))
531+ then throw(("Estimated amount must be positive. Actual: " + toString(estimatedAmountToReceive)))
532+ else if ((minAmountToReceive > estimatedAmountToReceive))
533+ then throw(((("Minimal amount can't be greater than estimated. Estimated: " + toString(estimatedAmountToReceive)) + ". Minimal: ") + toString(minAmountToReceive)))
534+ else if ((size(i.payments) != 1))
535+ then throw("One attached payment expected")
536+ else if (!(hasEnoughBalance))
537+ then ([ScriptTransfer(i.caller, pmtAmount, pmtAssetId)] ++ suspendSuspicious())
538+ else if (if ((pmtAssetId != assetIdA))
539+ then (pmtAssetId != assetIdB)
540+ else false)
541+ then throwAssets()
542+ else if ((10000000 > pmtAmount))
543+ then throw("Only swap of 10.000000 or more tokens is allowed")
544+ else if (if ((exchangeRatioLimitMin > fraction(scale8, minAmountToReceive, pmtAmount)))
545+ then true
546+ else (fraction(scale8, estimatedAmountToReceive, pmtAmount) > exchangeRatioLimitMax))
547+ then throw("Incorrect args and pmt ratio")
548+ else {
549+ let sendAssetId = if ((pmtAssetId == assetIdA))
550+ then assetIdB
551+ else assetIdA
552+ let amount = calculateSendAmount(estimatedAmountToReceive, minAmountToReceive, pmtAmount, pmtAssetId)
553+ let governanceReward = fraction(amount, feeGovernance, feeScale6)
554+ let amountMinusFee = fraction(amount, (feeScale6 - fee), feeScale6)
555+ let $t02180622068 = if ((pmtAssetId == assetIdA))
556+ then $Tuple2((balanceA + pmtAmount), ((balanceB - amountMinusFee) - governanceReward))
557+ else $Tuple2(((balanceA - amountMinusFee) - governanceReward), (balanceB + pmtAmount))
558+ let newBalanceA = $t02180622068._1
559+ let newBalanceB = $t02180622068._2
560+ let dAppThresholdAmount = fraction((newBalanceA + newBalanceB), dAppThreshold, (2 * dAppThresholdScale2))
561+ if (if ((dAppThresholdAmount > newBalanceA))
562+ then true
563+ else (dAppThresholdAmount > newBalanceB))
564+ then throwThreshold(dAppThresholdAmount, newBalanceA, newBalanceB)
565+ else {
566+ let $t02236622439 = getAssetInfo(pmtAssetId)
567+ let pmtStrAssetId = $t02236622439._1
568+ let pmtAssetName = $t02236622439._2
569+ let pmtDecimals = $t02236622439._3
570+ let $t02245222529 = getAssetInfo(sendAssetId)
571+ let sendStrAssetId = $t02245222529._1
572+ let sendAssetName = $t02245222529._2
573+ let sendDecimals = $t02245222529._3
574+ let stake1 = if (containsElement(stakingAssets, pmtStrAssetId))
575+ then invoke(this, "stakeUnstake", [true, pmtAmount, pmtStrAssetId], nil)
576+ else 0
577+ if ((stake1 == stake1))
578+ then {
579+ let stake2 = if (containsElement(stakingAssets, sendStrAssetId))
580+ then invoke(this, "stakeUnstake", [false, (amountMinusFee + governanceReward), sendStrAssetId], nil)
581+ else 0
582+ if ((stake2 == stake2))
583+ then [IntegerEntry(kBalanceA, newBalanceA), IntegerEntry(kBalanceB, newBalanceB), IntegerEntry(kInvariant, invariantCalc(newBalanceA, newBalanceB)), ScriptTransfer(i.caller, amountMinusFee, sendAssetId), ScriptTransfer(walletAddress, governanceReward, sendAssetId)]
584+ else throw("Strict value is not equal to itself.")
585+ }
586+ else throw("Strict value is not equal to itself.")
587+ }
588+ }
589+ }
477590
478591
479592
480593 @Callable(i)
481-func exchange (minAmountToReceive) = valueOrElse(isActive(), {
482- let $t01821518290 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
483- let pmtAmount = $t01821518290._1
484- let pmtAssetId = $t01821518290._2
485- if (if ((balanceA == 0))
486- then true
487- else (balanceB == 0))
488- then throw("Can't exchange with zero balance")
489- else if ((0 >= minAmountToReceive))
490- then throw(("Minimal amount to receive must be positive. Actual: " + toString(minAmountToReceive)))
491- else if ((size(i.payments) != 1))
492- then throw("One attached payment expected")
493- else if (!(hasEnoughBalance))
494- then ([ScriptTransfer(i.caller, pmtAmount, pmtAssetId)] ++ suspendSuspicious())
495- else if ((pmtAssetId == assetIdA))
496- then {
497- let assetIdSend = assetIdB
498- let $t01884518967 = calculateFees(pmtAmount, minAmountToReceive, balanceA, balanceB)
499- let amountWithoutFee = $t01884518967._1
500- let amountWithFee = $t01884518967._2
501- let governanceReward = $t01884518967._3
502- let newBalanceA = (balanceA + pmtAmount)
503- let newBalanceB = ((balanceB - amountWithFee) - governanceReward)
504- let stake1 = if (containsElement(stakingAssets, strAssetIdA))
505- then invoke(this, "stakeUnstake", [true, pmtAmount, strAssetIdA], nil)
506- else 0
507- if ((stake1 == stake1))
508- then {
509- let stake2 = if (containsElement(stakingAssets, strAssetIdB))
510- then invoke(this, "stakeUnstake", [false, (amountWithFee + governanceReward), strAssetIdB], nil)
511- else 0
512- if ((stake2 == stake2))
513- then [IntegerEntry(keyBalanceA, newBalanceA), IntegerEntry(keyBalanceB, newBalanceB), ScriptTransfer(i.caller, amountWithFee, assetIdSend), ScriptTransfer(walletAddress, governanceReward, assetIdSend)]
514- else throw("Strict value is not equal to itself.")
515- }
516- else throw("Strict value is not equal to itself.")
517- }
518- else if ((pmtAssetId == assetIdB))
519- then {
520- let assetIdSend = assetIdA
521- let $t01992220044 = calculateFees(pmtAmount, minAmountToReceive, balanceB, balanceA)
522- let amountWithoutFee = $t01992220044._1
523- let amountWithFee = $t01992220044._2
524- let governanceReward = $t01992220044._3
525- let newBalanceA = ((balanceA - amountWithFee) - governanceReward)
526- let newBalanceB = (balanceB + pmtAmount)
527- let stake1 = if (containsElement(stakingAssets, strAssetIdA))
528- then invoke(this, "stakeUnstake", [false, (amountWithFee + governanceReward), strAssetIdA], nil)
529- else 0
530- if ((stake1 == stake1))
531- then {
532- let stake2 = if (containsElement(stakingAssets, strAssetIdB))
533- then invoke(this, "stakeUnstake", [true, pmtAmount, strAssetIdB], nil)
534- else 0
535- if ((stake2 == stake2))
536- then [IntegerEntry(keyBalanceA, newBalanceA), IntegerEntry(keyBalanceB, newBalanceB), ScriptTransfer(i.caller, amountWithFee, assetIdSend), ScriptTransfer(walletAddress, governanceReward, assetIdSend)]
537- else throw("Strict value is not equal to itself.")
538- }
539- else throw("Strict value is not equal to itself.")
540- }
541- else throw(((("Incorrect asset attached. Expected: " + strAssetIdA) + " or ") + strAssetIdB))
542- })
543-
544-
545-
546-@Callable(i)
547-func shutdown () = if (!(active))
548- then throw(("DApp is already suspended. Cause: " + valueOrElse(getString(this, keyCause), "the cause wasn't specified")))
549- else if (!(containsElement([adminPubKey1, adminPubKey2, adminPubKey3, adminPubKeyStartStop], i.callerPublicKey)))
550- then throw("Only admin can call this function")
594+func shutdown () = if (!(isActive))
595+ then throw(("DApp is already suspended. Cause: " + valueOrElse(getString(this, kCause), "the cause wasn't specified")))
596+ else if (!(containsElement([adminPubKey1, adminPubKey2, adminPubKey3, admStartStop], i.callerPublicKey)))
597+ then throwOnlyAdmin()
551598 else suspend("Paused by admin")
552599
553600
554601
555602 @Callable(i)
556-func activate () = if (active)
557- then throw("DApp is already active")
558- else if (!(containsElement([adminPubKey1, adminPubKey2, adminPubKey3, adminPubKeyStartStop], i.callerPublicKey)))
559- then throw("Only admin can call this function")
560- else [BooleanEntry(keyActive, true), DeleteEntry(keyCause)]
603+func activate () = if (isActive)
604+ then throwIsActive()
605+ else if (!(containsElement([adminPubKey1, adminPubKey2, adminPubKey3, admStartStop], i.callerPublicKey)))
606+ then throwOnlyAdmin()
607+ else [BooleanEntry(kActive, true), DeleteEntry(kCause)]
561608
562609
563610
564611 @Callable(i)
565-func takeIntoAccountExtraFunds () = valueOrElse(isActive(), {
612+func takeIntoAccountExtraFunds () = {
566613 let amountEnrollA = (accountBalanceWithStakedA - balanceA)
567614 let amountEnrollB = (accountBalanceWithStakedB - balanceB)
568- if ((i.caller != walletAddress))
569- then throw("Only the wallet can call this function")
570- else if (if ((0 > amountEnrollA))
571- then true
572- else (0 > amountEnrollB))
573- then suspend("Enroll amount negative")
574- else if (if ((amountEnrollA == 0))
575- then (amountEnrollB == 0)
576- else false)
577- then throw("No money to take")
578- else {
579- let stake1 = if (containsElement(stakingAssets, strAssetIdA))
580- then invoke(this, "stakeUnstake", [true, amountEnrollA, strAssetIdA], nil)
581- else 0
582- if ((stake1 == stake1))
583- then {
584- let stake2 = if (containsElement(stakingAssets, strAssetIdB))
585- then invoke(this, "stakeUnstake", [true, amountEnrollB, strAssetIdB], nil)
586- else 0
587- if ((stake2 == stake2))
588- then [IntegerEntry(keyBalanceA, (balanceA + amountEnrollA)), IntegerEntry(keyBalanceB, (balanceB + amountEnrollB)), IntegerEntry(("last_income_" + strAssetIdA), amountEnrollA), IntegerEntry(("last_income_" + strAssetIdB), amountEnrollB)]
589- else throw("Strict value is not equal to itself.")
590- }
591- else throw("Strict value is not equal to itself.")
592- }
593- })
615+ let invariantNew = invariantCalc((balanceA + amountEnrollA), (balanceB + amountEnrollB))
616+ if (!(isActive))
617+ then throwIsInactive()
618+ else if ((i.caller != walletAddress))
619+ then throw("Only the wallet can call this function")
620+ else if (if ((0 > amountEnrollA))
621+ then true
622+ else (0 > amountEnrollB))
623+ then suspend("Enroll amount negative")
624+ else if (if ((amountEnrollA == 0))
625+ then (amountEnrollB == 0)
626+ else false)
627+ then throw("No money to take")
628+ else {
629+ let stake1 = if (if (containsElement(stakingAssets, strAssetIdA))
630+ then (amountEnrollA > 0)
631+ else false)
632+ then invoke(this, "stakeUnstake", [true, amountEnrollA, strAssetIdA], nil)
633+ else 0
634+ if ((stake1 == stake1))
635+ then {
636+ let stake2 = if (if (containsElement(stakingAssets, strAssetIdB))
637+ then (amountEnrollB > 0)
638+ else false)
639+ then invoke(this, "stakeUnstake", [true, amountEnrollB, strAssetIdB], nil)
640+ else 0
641+ if ((stake2 == stake2))
642+ then [IntegerEntry(kInvariant, invariantNew), IntegerEntry(kBalanceA, (balanceA + amountEnrollA)), IntegerEntry(kBalanceB, (balanceB + amountEnrollB)), IntegerEntry(("last_income_" + strAssetIdA), amountEnrollA), IntegerEntry(("last_income_" + strAssetIdB), amountEnrollB)]
643+ else throw("Strict value is not equal to itself.")
644+ }
645+ else throw("Strict value is not equal to itself.")
646+ }
647+ }
594648
595649
596650
597651 @Callable(i)
598652 func stakeUnstake (stake,amount,assetIdString) = if ((i.caller != this))
599653 then throw("Only contract itself can invoke this function")
600- else if ((assetIdString == "WAVES"))
601- then {
602- let pool = addressFromStringValue(valueOrErrorMessage(getString(oracle, keyLeasingPool), "No leasing pool in oracle"))
603- let leasingId = getBinary(this, keyLeasingId)
604- let leasingAmount = valueOrElse(getInteger(this, keyLeasingAmount), 0)
605- let newLeaseAmount = if (stake)
606- then (leasingAmount + amount)
607- else (leasingAmount - amount)
608- let newLease = Lease(pool, newLeaseAmount)
609- let newLeaseId = calculateLeaseId(newLease)
610- let baseEtry = [newLease, BinaryEntry(keyLeasingId, newLeaseId), IntegerEntry(keyLeasingAmount, newLeaseAmount)]
611- match leasingId {
612- case lId: ByteVector =>
613- ([LeaseCancel(lId)] ++ baseEtry)
614- case _ =>
615- baseEtry
616- }
617- }
618- else {
619- let $t02377823881 = calcStakingParams(stake, amount, fromBase58String(assetIdString))
620- let call = $t02377823881._1
621- let addr = $t02377823881._2
622- let params = $t02377823881._3
623- let payments = $t02377823881._4
624- let inv = invoke(addr, call, params, payments)
625- if ((inv == inv))
626- then nil
627- else throw("Strict value is not equal to itself.")
628- }
654+ else {
655+ let $t02559125694 = calcStakingParams(stake, amount, fromBase58String(assetIdString))
656+ let call = $t02559125694._1
657+ let addr = $t02559125694._2
658+ let params = $t02559125694._3
659+ let payments = $t02559125694._4
660+ let inv = invoke(addr, call, params, payments)
661+ if ((inv == inv))
662+ then nil
663+ else throw("Strict value is not equal to itself.")
664+ }
629665
630666
631667
632668 @Callable(i)
633-func stakeAll () = valueOrElse(isActive(), if (!(containsElement([adminPubKey1, adminPubKey2, adminPubKey3, adminPubKeyStartStop], i.callerPublicKey)))
634- then throw("Only admin can call this function")
635- else {
636- let stake1 = if (containsElement(stakingAssets, strAssetIdA))
637- then {
638- let amountA = (balanceA - stakedAmountA)
639- if ((amountA > 0))
640- then invoke(this, "stakeUnstake", [true, amountA, strAssetIdA], nil)
641- else 0
642- }
643- else 0
644- if ((stake1 == stake1))
645- then {
646- let stake2 = if (containsElement(stakingAssets, strAssetIdB))
647- then {
648- let amountB = (balanceB - stakedAmountB)
649- if ((amountB > 0))
650- then invoke(this, "stakeUnstake", [true, amountB, strAssetIdB], nil)
651- else 0
652- }
653- else 0
654- if ((stake2 == stake2))
655- then nil
656- else throw("Strict value is not equal to itself.")
657- }
658- else throw("Strict value is not equal to itself.")
659- })
669+func stakeAll () = if (!(isActive))
670+ then throw("DApp is inactive at this moment")
671+ else if (!(containsElement([adminPubKey1, adminPubKey2, adminPubKey3, admStartStop], i.callerPublicKey)))
672+ then throw("Only admin can call this function")
673+ else {
674+ let stake1 = if (containsElement(stakingAssets, strAssetIdA))
675+ then {
676+ let amountA = (balanceA - stakedAmountA)
677+ if ((amountA > 0))
678+ then invoke(this, "stakeUnstake", [true, amountA, strAssetIdA], nil)
679+ else 0
680+ }
681+ else 0
682+ if ((stake1 == stake1))
683+ then {
684+ let stake2 = if (containsElement(stakingAssets, strAssetIdB))
685+ then {
686+ let amountB = (balanceB - stakedAmountB)
687+ if ((amountB > 0))
688+ then invoke(this, "stakeUnstake", [true, amountB, strAssetIdB], nil)
689+ else 0
690+ }
691+ else 0
692+ if ((stake2 == stake2))
693+ then nil
694+ else throw("Strict value is not equal to itself.")
695+ }
696+ else throw("Strict value is not equal to itself.")
697+ }
660698
661699
662700 @Verifier(tx)
663701 func verify () = {
664702 let multiSignedByAdmins = {
665703 let adminPubKey1Signed = if (sigVerify(tx.bodyBytes, tx.proofs[0], adminPubKey1))
666704 then 1
667705 else 0
668706 let adminPubKey2Signed = if (sigVerify(tx.bodyBytes, tx.proofs[1], adminPubKey2))
669707 then 1
670708 else 0
671709 let adminPubKey3Signed = if (sigVerify(tx.bodyBytes, tx.proofs[2], adminPubKey3))
672710 then 1
673711 else 0
674712 (((adminPubKey1Signed + adminPubKey2Signed) + adminPubKey3Signed) >= 2)
675713 }
676714 match tx {
677715 case inv: InvokeScriptTransaction =>
678716 let callTakeIntoAccount = if ((inv.dApp == this))
679717 then (inv.function == "takeIntoAccountExtraFunds")
680718 else false
681- let exchangeToWaves = if (if (if ((inv.dApp == USDNToWavesExchanger))
682- then (inv.function == "exchange")
683- else false)
684- then (assetIdA == USDN)
685- else false)
686- then true
687- else if (if ((assetIdB == USDN))
688- then (size(inv.payments) == 1)
689- else false)
690- then (inv.payments[0].assetId == USDN)
691- else false
692- let exchangeToNSBTs = if (if (if ((inv.dApp == USDNToNSBTExchanger))
693- then (inv.function == "exchange")
694- else false)
695- then (assetIdA == NSBT)
696- else false)
697- then true
698- else if (if ((assetIdB == NSBT))
699- then (size(inv.payments) == 1)
700- else false)
701- then (inv.payments[0].assetId == USDN)
702- else false
703719 let signedByAdmin = if (if (if (sigVerify(tx.bodyBytes, tx.proofs[0], adminPubKey1))
704720 then true
705721 else sigVerify(tx.bodyBytes, tx.proofs[0], adminPubKey2))
706722 then true
707723 else sigVerify(tx.bodyBytes, tx.proofs[0], adminPubKey3))
708724 then true
709- else sigVerify(tx.bodyBytes, tx.proofs[0], adminPubKeyStaking)
710- if (if (if (if (callTakeIntoAccount)
711- then true
712- else exchangeToWaves)
713- then true
714- else exchangeToNSBTs)
725+ else sigVerify(tx.bodyBytes, tx.proofs[0], admStaking)
726+ if (if (callTakeIntoAccount)
715727 then signedByAdmin
716728 else false)
717729 then true
718730 else multiSignedByAdmins
719731 case _ =>
720732 multiSignedByAdmins
721733 }
722734 }
723735

github/deemru/w8io/169f3d6 
101.45 ms