tx · 9w14o88xk9cNysrre79geypArSGrMpg72tMVQV2JDjto

3PNi1BJendWYYe2CRnqpfLoYxUZ6UTcx3LF:  -0.01400000 Waves

2022.05.08 13:06 [3108037] smart account 3PNi1BJendWYYe2CRnqpfLoYxUZ6UTcx3LF > SELF 0.00000000 Waves

{ "type": 13, "id": "9w14o88xk9cNysrre79geypArSGrMpg72tMVQV2JDjto", "fee": 1400000, "feeAssetId": null, "timestamp": 1652003641217, "version": 2, "chainId": 87, "sender": "3PNi1BJendWYYe2CRnqpfLoYxUZ6UTcx3LF", "senderPublicKey": "DPiPHjYxH29a4J8cyZDKwgtLKxH17JvT7nwm6ugnSEm7", "proofs": [ "", "wBUnTovaXxRPtKVVFqwFwTzUCFLMYG4vambryyut4ojdJgCi4dDLdPcm2WSrDDkbr6zWGqPWBirzHpFb6dSHXBx", "3anRPmzoQqdZdBpiJJhYANxiENVSY94hDPnMKUxcvXBg8A2TXvzv6W2G1ECfMkFZ6ByHbnmGfoxrPGmukvYy6GVo" ], "script": "base64:AAIFAAAAAAAAACMIAhIAEgASBAoCAQESABIECgIBARIAEgASABIFCgMEAQgSAAAAAE8AAAAAB3ZlcnNpb24CAAAABTIuMC4wAAAAAAhrVmVyc2lvbgIAAAAHdmVyc2lvbgAAAAAHa0FjdGl2ZQIAAAAGYWN0aXZlAAAAAAlrQXNzZXRJZEECAAAACkFfYXNzZXRfaWQAAAAACWtBc3NldElkQgIAAAAKQl9hc3NldF9pZAAAAAAJa0JhbGFuY2VBAgAAAA9BX2Fzc2V0X2JhbGFuY2UAAAAACWtCYWxhbmNlQgIAAAAPQl9hc3NldF9iYWxhbmNlAAAAAA1rU2hhcmVBc3NldElkAgAAAA5zaGFyZV9hc3NldF9pZAAAAAARa1NoYXJlQXNzZXRTdXBwbHkCAAAAEnNoYXJlX2Fzc2V0X3N1cHBseQAAAAAEa0ZlZQIAAAAKY29tbWlzc2lvbgAAAAAKa0ludmFyaWFudAIAAAAJaW52YXJpYW50AAAAAAZrQ2F1c2UCAAAADnNodXRkb3duX2NhdXNlAAAAAAxrVVNETkFkZHJlc3MCAAAAGHN0YWtpbmdfdXNkbm5zYnRfYWRkcmVzcwAAAAAMa0VVUk5BZGRyZXNzAgAAABRzdGFraW5nX2V1cm5fYWRkcmVzcwAAAAANa0FkbWluUHViS2V5MQIAAAALYWRtaW5fcHViXzEAAAAADWtBZG1pblB1YktleTICAAAAC2FkbWluX3B1Yl8yAAAAAA1rQWRtaW5QdWJLZXkzAgAAAAthZG1pbl9wdWJfMwAAAAASa0FkbWluSW52b2tlUHViS2V5AgAAABBhZG1pbl9pbnZva2VfcHViAAAAABBrTW9uZXlCb3hBZGRyZXNzAgAAABFtb25leV9ib3hfYWRkcmVzcwAAAAAGb3JhY2xlCQEAAAAHQWRkcmVzcwAAAAEBAAAAGgFXiv8IaJo1ukDNYXTyEjfepjfw+jjO6B44AQAAABNnZXRCYXNlNThGcm9tT3JhY2xlAAAAAQAAAANrZXkEAAAAByRtYXRjaDAJAAQdAAAAAgUAAAAGb3JhY2xlBQAAAANrZXkDCQAAAQAAAAIFAAAAByRtYXRjaDACAAAABlN0cmluZwQAAAAGc3RyaW5nBQAAAAckbWF0Y2gwCQACWQAAAAEFAAAABnN0cmluZwQAAAAHbm90aGluZwUAAAAHJG1hdGNoMAkAAAIAAAABCQABLAAAAAIFAAAAA2tleQIAAAAIaXMgZW1wdHkAAAAADGFkbWluUHViS2V5MQkBAAAAE2dldEJhc2U1OEZyb21PcmFjbGUAAAABBQAAAA1rQWRtaW5QdWJLZXkxAAAAAAxhZG1pblB1YktleTIJAQAAABNnZXRCYXNlNThGcm9tT3JhY2xlAAAAAQUAAAANa0FkbWluUHViS2V5MgAAAAAMYWRtaW5QdWJLZXkzCQEAAAATZ2V0QmFzZTU4RnJvbU9yYWNsZQAAAAEFAAAADWtBZG1pblB1YktleTMAAAAAEWFkbWluUHViS2V5SW52b2tlCQEAAAATZ2V0QmFzZTU4RnJvbU9yYWNsZQAAAAEFAAAAEmtBZG1pbkludm9rZVB1YktleQAAAAAPbW9uZXlCb3hBZGRyZXNzCQEAAAAHQWRkcmVzcwAAAAEJAQAAABNnZXRCYXNlNThGcm9tT3JhY2xlAAAAAQUAAAAQa01vbmV5Qm94QWRkcmVzcwAAAAASc3Rha2luZ1VTRE5BZGRyZXNzCQEAAAAHQWRkcmVzcwAAAAEJAQAAABNnZXRCYXNlNThGcm9tT3JhY2xlAAAAAQUAAAAMa1VTRE5BZGRyZXNzAAAAAARVU0ROAQAAACC2JinDBPXOU5GkDkt1JC9kjFGx+t+vVCm9SNIdKrKq0QAAAAANc3Rha2luZ0Fzc2V0cwkABEwAAAACCQACWAAAAAEFAAAABFVTRE4FAAAAA25pbAAAAAAGYWN0aXZlCQEAAAARQGV4dHJOYXRpdmUoMTA1MSkAAAACBQAAAAR0aGlzBQAAAAdrQWN0aXZlAAAAAAtzdHJBc3NldElkQQkBAAAAEUBleHRyTmF0aXZlKDEwNTMpAAAAAgUAAAAEdGhpcwUAAAAJa0Fzc2V0SWRBAAAAAAtzdHJBc3NldElkQgkBAAAAEUBleHRyTmF0aXZlKDEwNTMpAAAAAgUAAAAEdGhpcwUAAAAJa0Fzc2V0SWRCAAAAAAhhc3NldElkQQMJAAAAAAAAAgUAAAALc3RyQXNzZXRJZEECAAAABVdBVkVTBQAAAAR1bml0CQACWQAAAAEFAAAAC3N0ckFzc2V0SWRBAAAAAAhhc3NldElkQgMJAAAAAAAAAgUAAAALc3RyQXNzZXRJ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AgkBAAAAC1N0cmluZ0VudHJ5AAAAAgUAAAAJa0Fzc2V0SWRBBQAAAA5wbXRTdHJBc3NldElkQQkABEwAAAACCQEAAAALU3RyaW5nRW50cnkAAAACBQAAAAlrQXNzZXRJZEIFAAAADnBtdFN0ckFzc2V0SWRCCQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACBQAAAAlrQmFsYW5jZUEFAAAACnBtdEFtb3VudEEJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAIFAAAACWtCYWxhbmNlQgUAAAAKcG10QW1vdW50QgkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgUAAAAKa0ludmFyaWFudAUAAAATaW52YXJpYW50Q2FsY3VsYXRlZAkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgUAAAAEa0ZlZQkBAAAAEUBleHRyTmF0aXZlKDEwNTApAAAAAgUAAAAGb3JhY2xlAgAAAA1iYXNlX2ZlZV9mbGF0CQAETAAAAAIFAAAACnNoYXJlSXNzdWUJAARMAAAAAgkBAAAAC1N0cmluZ0VudHJ5AAAAAgUAAAANa1NoYXJlQXNzZXRJZAkAAlgAAAABBQAAAAxzaGFyZUlzc3VlSWQJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAIFAAAAEWtTaGFyZUFzc2V0U3VwcGx5BQAAABJzaGFyZUluaXRpYWxTdXBwbHkJAARMAAAAAgkBAAAADlNjcmlwdFRyYW5zZmVyAAAAAwgFAAAAAWkAAAAGY2FsbGVyBQAAABJzaGFyZUluaXRpYWxTdXBwbHkFAAAADHNoYXJlSXNzdWVJZAUAAAADbmlsCQAAAgAAAAECAAAAJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAAIAAAABAgAAACRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4AAAABaQEAAAAWcmVwbGVuaXNoV2l0aFR3b1Rva2VucwAAAAAJAQAAAAt2YWx1ZU9yRWxzZQAAAAIJAQAAAAhpc0FjdGl2ZQAAAAAEAAAAC3BtdEFzc2V0SWRBCAkAAZEAAAACCAUAAAABaQAAAAhwYXltZW50cwAAAAAAAAAAAAAAAAdhc3NldElkBAAAAAtwbXRBc3NldElkQggJAAGRAAAAAggFAAAAAWkAAAAIcGF5bWVudHMAAAAAAAAAAAEAAAAHYXNzZXRJZAQAAAATcmF0aW9TaGFyZVRva2Vuc0luQQkAAGsAAAADBQAAAAZzY2FsZTgICQABkQAAAAIIBQAAAAFpAAAACHBheW1lbnRzAAAAAAAAAAAAAAAABmFtb3VudAUAAAAIYmFsYW5jZUEEAAAAE3JhdGlvU2hhcmVUb2tlbnNJbkIJAABrAAAAAwUAAAAGc2NhbGU4CAkAAZEAAAACCAUAAAABaQAAAAhwYXltZW50cwAAAAAAAAAAAQAAAAZhbW91bnQFAAAACGJhbGFuY2VCBAAAAA0kdDAxMjQzNTEyNTEyCQEAAAAMZ2V0QXNzZXRJbmZvAAAAAQUAAAALcG10QXNzZXRJZEEEAAAADnBtdFN0ckFzc2V0SWRBCAUAAAANJHQwMTI0MzUxMjUxMgAAAAJfMQQAAAANcG10QXNzZXROYW1lQQgFAAAADSR0MDEyNDM1MTI1MTIAAAACXzIEAAAADHBtdERlY2ltYWxzQQgFAAAADSR0MDEyNDM1MTI1MTIAAAACXzMEAAAADSR0MDEyNTE3MTI2MzQJAQAAAAxnZXRBc3NldEluZm8AAAABBQAAAAtwbXRBc3NldElkQgQAAAAOcG10U3RyQXNzZXRJZEIIBQAAAA0kdDAxMjUxNzEyNjM0AAAAAl8xBAAAAA1wbXRBc3NldE5hbWVCCAUAAAANJHQwMTI1MTcxMjYzNAAAAAJfMgQAAAAMcG10RGVjaW1hbHNCCAUAAAANJHQwMTI1MTcxMjYzNAAAAAJfMwQAAAANJHQwMTI2MzkxMzE0MwMJAABmAAAAAgUAAAATcmF0aW9TaGFyZVRva2Vuc0luQgUAAAATcmF0aW9TaGFyZVRva2Vuc0luQQQAAAADcG10CQEAAAAIZnJhY3Rpb24AAAAEBQAAAAhiYWxhbmNlQgUAAAATcmF0aW9TaGFyZVRva2Vuc0luQQUAAAAGc2NhbGU4BQAAAAdDRUlMSU5HCQAFFwAAAAUICQABkQAAAAIIBQAAAAFpAAAACHBheW1lbnRzAAAAAAAAAAAAAAAABmFtb3VudAUAAAADcG10CQAAZQAAAAIICQABkQAAAAIIBQAAAAFpAAAACHBheW1l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AAxJbnRlZ2VyRW50cnkAAAACBQAAABFrU2hhcmVBc3NldFN1cHBseQkAAGQAAAACBQAAABBzaGFyZUFzc2V0U3VwcGx5BQAAABVzaGFyZVRva2VuVG9QYXlBbW91bnQJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAIFAAAACmtJbnZhcmlhbnQJAQAAAA1pbnZhcmlhbnRDYWxjAAAAAgkAAGQAAAACBQAAAAhiYWxhbmNlQQUAAAAKcG10QW1vdW50QQkAAGQAAAACBQAAAAhiYWxhbmNlQgUAAAAKcG10QW1vdW50QgkABEwAAAACCQEAAAAHUmVpc3N1ZQAAAAMFAAAADHNoYXJlQXNzZXRJZAUAAAAVc2hhcmVUb2tlblRvUGF5QW1vdW50BgkABEwAAAACCQEAAAAOU2NyaXB0VHJhbnNmZXIAAAADCAUAAAABaQAAAAZjYWxsZXIFAAAAFXNoYXJlVG9rZW5Ub1BheUFtb3VudAUAAAAMc2hhcmVBc3NldElkCQAETAAAAAIJAQAAAA5TY3JpcHRUcmFuc2ZlcgAAAAMIBQAAAAFpAAAABmNhbGxlcgUAAAAGY2hhbmdlBQAAAA1jaGFuZ2VBc3NldElkBQAAAANuaWwJAAACAAAAAQIAAAAkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQAAAgAAAAECAAAAJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgAAAAFpAQAAABVyZXBsZW5pc2hXaXRoT25lVG9rZW4AAAACAAAAE3ZpcnR1YWxTd2FwVG9rZW5QYXkAAAATdmlydHVhbFN3YXBUb2tlbkdldAkBAAAAC3ZhbHVlT3JFbHNlAAAAAgkBAAAACGlzQWN0aXZlAAAAAAQAAAANJHQwMTQ4NzYxNDk1MQkABRQAAAACCAkAAZEAAAACCAUAAAABaQAAAAhwYXltZW50cwAAAAAAAAAAAAAAAAZhbW91bnQICQABkQAAAAIIBQAAAAFpAAAACHBheW1lbnRzAAAAAAAAAAAAAAAAB2Fzc2V0SWQEAAAACXBtdEFtb3VudAgFAAAADSR0MDE0ODc2MTQ5NTEAAAACXzEEAAAACnBtdEFzc2V0SWQIBQAAAA0kdDAxNDg3NjE0OTUxAAAAAl8yBAAAAA0kdDAxNDk1NjE1MDI5CQEAAAAMZ2V0QXNzZXRJbmZvAAAAAQUAAAAKcG10QXNzZXRJZAQAAAANcG10U3RyQXNzZXRJZAgFAAAADSR0MDE0OTU2MTUwMjkAAAACXzEEAAAADHBtdEFzc2V0TmFtZQgFAAAADSR0MDE0OTU2MTUwMjkAAAACXzIEAAAAC3BtdERlY2ltYWxzCAUAAAANJHQwMTQ5NTYxNTAyOQAAAAJfMwQAAAAPcG10TWluVGhyZXNob2xkAAAAAAAATEtABAAAAB10aHJlc2hvbGRWYWx1ZUZvck1pblRvbGVyYW5jZQAAAAAAAvrwgAQAAAAJdG9sZXJhbmNlAwkAAGYAAAACBQAAAB10aHJlc2hvbGRWYWx1ZUZvck1pblRvbGVyYW5jZQUAAAAJcG10QW1vdW50AAAAAAAAAYagAAAAAAAAAAABBAAAABxzbGlwcGFnZVZhbHVlTWluRm9yUmVwbGVuaXNoCQAAZQAAAAIFAAAABnNjYWxlOAkAAGkAAAACCQAAaAAAAAIFAAAABnNjYWxlOAUAAAAJdG9sZXJhbmNlAAAAAAAAmJaABAAAABxzbGlwcGFnZVZhbHVlTWF4Rm9yUmVwbGVuaXNoCQAAZAAAAAIFAAAABnNjYWxlOAkAAGkAAAACCQAAaAAAAAIFAAAABnNjYWxlOAUAAAAJdG9sZXJhbmNlAAAAAAAAmJaABAAAABdzbGlwcGFnZVZhbHVlTWluRm9yU3dhcAkAAGUAAAACBQAAAAZzY2FsZTgJAABpAAAAAgkAAGgAAAACBQAAAAZzY2FsZTgAAAAAAAAAAAEAAAAAAACYloADCQAAZgAAAAIFAAAAD3BtdE1pblRocmVzaG9sZAUAAAAJcG10QW1vdW50CQAAAgAAAAEJAAEsAAAAAgkAASwAAAACCQABLAAAAAIJAAEsAAAAAgIAAAAPUGF5bWVudCBhbW91bnQgCQABpAAAAAEFAAAACXBtdEFtb3VudAIAAAAnIGRvZXMgbm90IGV4Y2VlZCB0aGUgbWluaW11bSBhbW91bnQgb2YgCQABpAAAAAEFAAAAD3BtdE1pblRocmVzaG9sZAIAAAAHIHRva2VucwMJAQAAAAIhPQAAAAIJAAGQAAAAAQgFAAAAAWkAAAAIcGF5bWVudHMAAAAAAAAAAAEJAQAAAA90aHJvd09uZVBheW1lbnQAAAAAAwkBAAAAASEAAAABBQAAABBoYXNFbm91Z2hCYWxhbmNlCQAETgAAAAIJAARMAAAAAgkBAAAADlNjcmlwdFRyYW5zZmVyAAAAAwgFAAAAAWkAAAAGY2FsbGVyBQAAAAlwbXRBbW91bnQFAAAACnBtdEFzc2V0SWQFAAAAA25pbAkBAAAAEXN1c3BlbmRTdXNwaWNpb3VzAAAAAAMDCQEAAAACIT0AAAACBQAAAApwbXRBc3NldElkBQAAAAhhc3NldElkQQkBAAAAAiE9AAAAAgUAAAAKcG10QXNzZXRJZAUAAAAIYXNzZXRJZEIHCQEAAAALdGhyb3dBc3NldHMAAAAABAAAAA0kdDAxNjAwNzE2NjQ5AwkAAAAAAAACBQAAAApwbXRBc3NldElkBQAAAAhhc3NldElkQQkABRgAAAAGCQAAZQAAAAIFAAAACXBtdEFtb3VudAUAAAATdmlydHVhbFN3YXBUb2tlblBheQUAAAATdmlydHVhbFN3YXBUb2tlbkdldAkAAGQAAAACBQAAAAhiYWxhbmNlQQUAAAATdmlydHVhbFN3YXBUb2tlblBheQkAAGUAAAACBQAAAAhiYWxhbmNlQgUAAAATdmlydHVhbFN3YXBUb2tlbkdldAkAAGQAAAACBQAAAAhiYWxhbmNlQQUAAAAJcG10QW1vdW50BQAAAAhiYWxhbmNlQgkABRgAAAAGBQAAABN2aXJ0dWFsU3dhcFRva2VuR2V0CQAAZQAAAAIFAAAACXBtdEFtb3VudAUAAAATdmlydHVhbFN3YXBUb2tlblBheQkAAGUAAAACBQAAAAhiYWxhbmNlQQUAAAATdmlydHVhbFN3YXBUb2tlbkdldAkAAGQAAAACBQAAAAhiYWxhbmNlQgUAAAATdmlydHVhbFN3YXBUb2tlblBheQUAAAAIYmFsYW5jZUEJAABkAAAAAgUAAAAIYmFsYW5jZUIFAAAACXBtdEFtb3VudAQAAAARdmlydHVhbFJlcGxlbmlzaEEIBQAAAA0kdDAxNjAwNzE2NjQ5AAAAAl8xBAAAABF2aXJ0dWFsUmVwbGVuaXNoQggFAAAADSR0MDE2MDA3MTY2NDkAAAACXzIEAAAAEWJhbGFuY2VBZnRlclN3YXBBCAUAAAANJHQwMTYwMDcxNjY0OQAAAAJfMwQAAAARYmFsYW5jZUFmdGVyU3dhcEIIBQAAAA0kdDAxNjAwNzE2NjQ5AAAAAl80BAAAAAtuZXdCYWxhbmNlQQgFAAAADSR0MDE2MDA3MTY2NDkAAAACXzUEAAAAC25ld0JhbGFuY2VCCAUAAAANJHQwMTYwMDcxNjY0OQAAAAJfNgQAAAAMaW52YXJpYW50TmV3CQEAAAANaW52YXJpYW50Q2FsYwAAAAIFAAAAEWJhbGFuY2VBZnRlclN3YXBBBQAAABFiYWxhbmNlQWZ0ZXJTd2FwQgQAAAAlcmF0aW9WaXJ0dWFsQmFsYW5jZVRvVmlydHVhbFJlcGxlbmlzaAkAAGkAAAACCQAAawAAAAMFAAAAB3NjYWxlMTYFAAAAEWJhbGFuY2VBZnRlclN3YXBBBQAAABFiYWxhbmNlQWZ0ZXJTd2FwQgkAAGsAAAADBQAAAAZzY2FsZTgFAAAAEXZpcnR1YWxSZXBsZW5pc2hBBQAAABF2aXJ0dWFsUmVwbGVuaXNoQgQAAAATZEFwcFRocmVzaG9sZEFtb3VudAkAAGsAAAADCQAAZAAAAAIFAAAAC25ld0JhbGFuY2VBBQAAAAtuZXdCYWxhbmNlQgUAAAANZEFwcFRocmVzaG9sZAkAAGgAAAACAAAAAAAAAAACBQAAABNkQXBwVGhyZXNob2xkU2NhbGUyAwMJAABnAAAAAgUAAAAXc2xpcHBhZ2VWYWx1ZU1pbkZvclN3YXAJAABrAAAAAwUAAAAGc2NhbGU4BQAAAAlpbnZhcmlhbnQFAAAADGludmFyaWFudE5ldwYJAABmAAAAAgUAAAAJaW52YXJpYW50BQAAAAxpbnZhcmlhbnROZXcJAAACAAAAAQIAAAA6SW5jb3JyZWN0IHZpcnR1YWxTd2FwVG9rZW5QYXkgb3IgdmlydHVhbFN3YXBUb2tlbkdldCB2YWx1ZQMDCQAAZgAAAAIFAAAAHHNsaXBwYWdlVmFsdWVNaW5Gb3JSZXBsZW5pc2gFAAAAJXJhdGlvVmlydHVhbEJhbGFuY2VUb1ZpcnR1YWxSZXBsZW5pc2gGCQAAZgAAAAIFAAAAJXJhdGlvVmlydHVhbEJhbGFuY2VUb1ZpcnR1YWxSZXBsZW5pc2gFAAAAHHNsaXBwYWdlVmFsdWVNYXhGb3JSZXBsZW5pc2gJAAACAAAAAQIAAABsU3dhcCB3aXRoIHZpcnR1YWxTd2FwVG9rZW5QYXkgYW5kIHZpcnR1YWxTd2FwVG9rZW5HZXQgaXMgcG9zc2libGUsIGJ1dCByYXRpbyBhZnRlciB2aXJ0dWFsIHN3YXAgaXMgaW5jb3JyZWN0AwMJAABmAAAAAgUAAAATZEFwcFRocmVzaG9sZEFtb3VudAUAAAALbmV3QmFsYW5jZUEGCQAAZgAAAAIFAAAAE2RBcHBUaHJlc2hvbGRBbW91bnQFAAAAC25ld0JhbGFuY2VCCQEAAAAOdGhyb3dUaHJlc2hvbGQAAAADBQAAABNkQXBwVGhyZXNob2xkQW1vdW50BQAAAAtuZXdCYWxhbmNlQQUAAAALbmV3QmFsYW5jZUIEAAAAE3JhdGlvU2hhcmVUb2tlbnNJbkEJAABrAAAAAwUAAAARdmlydHVhbFJlcGxlbmlzaEEFAAAABnNjYWxlOAUAAAARYmFsYW5jZUFmdGVyU3dhcEEEAAAAE3JhdGlvU2hhcmVUb2tlbnNJbkIJAABrAAAAAwUAAAARdmlydHVhbFJlcGxlbmlzaEIFAAAABnNjYWxlOAUAAAARYmFsYW5jZUFmdGVyU3dhcEIEAAAAFXNoYXJlVG9rZW5Ub1BheUFtb3VudAkAAGsAAAADCQABlwAAAAEJAARMAAAAAgUAAAATcmF0aW9TaGFyZVRva2Vuc0luQQkABEwAAAACBQAAABNyYXRpb1NoYXJlVG9rZW5zSW5CBQAAAANuaWwFAAAAEHNoYXJlQXNzZXRTdXBwbHkFAAAABnNjYWxlOAQAAAAdc2hhcmVUb2tlblRvUGF5QW1vdW50QWZ0ZXJGZWUJAABrAAAAAwUAAAAVc2hhcmVUb2tlblRvUGF5QW1vdW50CQAAZQAAAAIFAAAACWZlZVNjYWxlNgkAAGkAAAACBQAAAANmZWUAAAAAAAAAAAIFAAAACWZlZVNjYWxlNgQAAAAac2hhcmVUb2tlbkdvdmVybmFuY2VSZXdhcmQJAABrAAAAAwUAAAAVc2hhcmVUb2tlblRvUGF5QW1vdW50CQAAaQAAAAIFAAAADWZlZUdvdmVybmFuY2UAAAAAAAAAAAIFAAAACWZlZVNjYWxlNgQAAAAWZ292ZXJuYW5jZVJld2FyZFRva2VuQQkAAGsAAAADBQAAABpzaGFyZVRva2VuR292ZXJuYW5jZVJld2FyZAUAAAAIYmFsYW5jZUEFAAAAEHNoYXJlQXNzZXRTdXBwbHkEAAAAFmdvdmVybmFuY2VSZXdhcmRUb2tlbkIJAABrAAAAAwUAAAAac2hhcmVUb2tlbkdvdmVybmFuY2VSZXdhcmQFAAAACGJhbGFuY2VCBQAAABBzaGFyZUFzc2V0U3VwcGx5BAAAAA0kdDAxODYzNjE4OTMxAwkAAAAAAAACBQAAAA1wbXRTdHJBc3NldElkBQAAAAtzdHJBc3NldElkQQkABRUAAAADCQAAZQAAAAIFAAAACXBtdEFtb3VudAUAAAAWZ292ZXJuYW5jZVJld2FyZFRva2VuQQUAAAAWZ292ZXJuYW5jZVJld2FyZFRva2VuQgUAAAALc3RyQXNzZXRJZEIJAAUVAAAAAwkAAGUAAAACBQAAAAlwbXRBbW91bnQFAAAAFmdvdmVybmFuY2VSZXdhcmRUb2tlbkIFAAAAFmdvdmVybmFuY2VSZXdhcmRUb2tlbkEFAAAAC3N0ckFzc2V0SWRBBAAAAAtzdGFrZUFtb3VudAgFAAAADSR0MDE4NjM2MTg5MzEAAAACXzEEAAAADXVuc3Rha2VBbW91bnQIBQAAAA0kdDAxODYzNjE4OTMxAAAAAl8yBAAAAAx1bnN0YWtlQXNzZXQIBQAAAA0kdDAxODYzNjE4OTMxAAAAAl8zBAAAAAZzdGFrZTEDCQEAAAAPY29udGFpbnNFbGVtZW50AAAAAgUAAAANc3Rha2luZ0Fzc2V0cwUAAAANcG10U3RyQXNzZXRJZAkAA/wAAAAEBQAAAAR0aGlzAgAAAAxzdGFrZVVuc3Rha2UJAARMAAAAAgYJAARMAAAAAgUAAAALc3Rha2VBbW91bnQJAARMAAAAAgUAAAANcG10U3RyQXNzZXRJZAUAAAADbmlsBQAAAANuaWwAAAAAAAAAAAADCQAAAAAAAAIFAAAABnN0YWtlMQUAAAAGc3Rha2UxBAAAAAZzdGFrZTIDCQEAAAAPY29udGFpbnNFbGVtZW50AAAAAgUAAAANc3Rha2luZ0Fzc2V0cwUAAAAMdW5zdGFrZUFzc2V0CQAD/AAAAAQFAAAABHRoaXMCAAAADHN0YWtlVW5zdGFrZQkABEwAAAACBwkABEwAAAACBQAAAA11bnN0YWtlQW1vdW50CQAETAAAAAIFAAAADHVuc3Rha2VBc3NldAUAAAADbmlsBQAAAANuaWwAAAAAAAAAAAADCQAAAAAAAAIFAAAABnN0YWtlMgUAAAAGc3Rha2UyCQAETAAAAAIJAQAAAAdSZWlzc3VlAAAAAwUAAAAMc2hhcmVBc3NldElkBQAAAB1zaGFyZVRva2VuVG9QYXlBbW91bnRBZnRlckZlZQYJAARMAAAAAgkBAAAADlNjcmlwdFRyYW5zZmVyAAAAAwgFAAAAAWkAAAAGY2FsbGVyBQAAAB1zaGFyZVRva2VuVG9QYXlBbW91bnRBZnRlckZlZQUAAAAMc2hhcmVBc3NldElkCQAETAAAAAIJAQAAAA5TY3JpcHRUcmFuc2ZlcgAAAAMFAAAAD21vbmV5Qm94QWRkcmVzcwUAAAAWZ292ZXJuYW5jZVJld2FyZFRva2VuQQUAAAAIYXNzZXRJZEEJAARMAAAAAgkBAAAADlNjcmlwdFRyYW5zZmVyAAAAAwUAAAAPbW9uZXlCb3hBZGRyZXNzBQAAABZnb3Zlcm5hbmNlUmV3YXJkVG9rZW5CBQAAAAhhc3NldElkQgkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgUAAAAJa0JhbGFuY2VBCQAAZQAAAAIFAAAAC25ld0JhbGFuY2VBBQAAABZnb3Zlcm5hbmNlUmV3YXJkVG9rZW5BCQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACBQAAAAlrQmFsYW5jZUIJAABlAAAAAgUAAAALbmV3QmFsYW5jZUIFAAAAFmdvdmVybmFuY2VSZXdhcmRUb2tlbkIJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAIFAAAAEWtTaGFyZUFzc2V0U3VwcGx5CQAAZAAAAAIFAAAAEHNoYXJlQXNzZXRTdXBwbHkFAAAAHXNoYXJlVG9rZW5Ub1BheUFtb3VudEFmdGVyRmVlCQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACBQAAAAprSW52YXJpYW50CQEAAAANaW52YXJpYW50Q2FsYwAAAAIJAABlAAAAAgUAAAALbmV3QmFsYW5jZUEFAAAAFmdvdmVybmFuY2VSZXdhcmRUb2tlbkEJAABlAAAAAgUAAAALbmV3QmFsYW5jZUIF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bgAAAAIFAAAADHNoYXJlQXNzZXRJZAUAAAAJcG10QW1vdW50CQAETAAAAAIJAQAAAA5TY3JpcHRUcmFuc2ZlcgAAAAMIBQAAAAFpAAAABmNhbGxlcgUAAAAMYW1vdW50VG9QYXlBBQAAAAhhc3NldElkQQkABEwAAAACCQEAAAAOU2NyaXB0VHJhbnNmZXIAAAADCAUAAAABaQAAAAZjYWxsZXIFAAAADGFtb3VudFRvUGF5QgUAAAAIYXNzZXRJZEIFAAAAA25pbAkAAAIAAAABAgAAACRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAACAAAAAQIAAAAkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAAAAAWkBAAAACGV4Y2hhbmdlAAAAAgAAABhlc3RpbWF0ZWRBbW91bnRUb1JlY2VpdmUAAAASbWluQW1vdW50VG9SZWNlaXZlCQEAAAALdmFsdWVPckVsc2UAAAACCQEAAAAIaXNBY3RpdmUAAAAABAAAAA0kdDAyMTg0NDIxOTE5CQAFFAAAAAIICQABkQAAAAIIBQAAAAFpAAAACHBheW1lbnRzAAAAAAAAAAAAAAAABmFtb3VudAgJAAGRAAAAAggFAAAAAWkAAAAIcGF5bWVudHMAAAAAAAAAAAAAAAAHYXNzZXRJZAQAAAAJcG10QW1vdW50CAUAAAANJHQwMjE4NDQyMTkxOQAAAAJfMQQAAAAKcG10QXNzZXRJZAgFAAAADSR0MDIxODQ0MjE5MTkAAAACXzIDCQAAZwAAAAIAAAAAAAAAAAAFAAAAGGVzdGltYXRlZEFtb3VudFRvUmVjZWl2ZQkAAAIAAAABCQABLAAAAAICAAAAK0VzdGltYXRlZCBhbW91bnQgbXVzdCBiZSBwb3NpdGl2ZS4gQWN0dWFsOiAJAAGkAAAAAQUAAAAYZXN0aW1hdGVkQW1vdW50VG9SZWNlaXZlAwkAAGYAAAACBQAAABJtaW5BbW91bnRUb1JlY2VpdmUFAAAAGGVzdGltYXRlZEFtb3VudFRvUmVjZWl2ZQkAAAIAAAABAgAAAC9NaW5pbWFsIGFtb3VudCBjYW4ndCBiZSBncmVhdGVyIHRoYW4gZXN0aW1hdGVkLgMJAQAAAAIhPQAAAAIJAAGQAAAAAQgFAAAAAWkAAAAIcGF5bWVudHMAAAAAAAAAAAEJAQAAAA90aHJvd09uZVBheW1lbnQAAAAAAwkBAAAAASEAAAABBQAAABBoYXNFbm91Z2hCYWxhbmNlCQAETgAAAAIJAARMAAAAAgkBAAAADlNjcmlwdFRyYW5zZmVyAAAAAwgFAAAAAWkAAAAGY2FsbGVyBQAAAAlwbXRBbW91bnQFAAAACnBtdEFzc2V0SWQFAAAAA25pbAkBAAAAEXN1c3BlbmRTdXNwaWNpb3VzAAAAAAMDCQEAAAACIT0AAAACBQAAAApwbXRBc3NldElkBQAAAAhhc3NldElkQQkBAAAAAiE9AAAAAgUAAAAKcG10QXNzZXRJZAUAAAAIYXNzZXRJZEIHCQEAAAALdGhyb3dBc3NldHMAAAAAAwkAAGYAAAACAAAAAAAAmJaABQAAAAlwbXRBbW91bnQJAAACAAAAAQIAAAAwT25seSBzd2FwIG9mIDEwLjAwMDAwMCBvciBtb3JlIHRva2VucyBpcyBhbGxvd2VkAwMJAABmAAAAAgUAAAAVZXhjaGFuZ2VSYXRpb0xpbWl0TWluCQAAawAAAAMFAAAABnNjYWxlOAUAAAASbWluQW1vdW50VG9SZWNlaXZlBQAAAAlwbXRBbW91bnQGCQAAZgAAAAIJAABrAAAAAwUAAAAGc2NhbGU4BQAAABhlc3RpbWF0ZWRBbW91bnRUb1JlY2VpdmUFAAAACXBtdEFtb3VudAUAAAAVZXhjaGFuZ2VSYXRpb0xpbWl0TWF4CQAAAgAAAAECAAAAHEluY29ycmVjdCBhcmdzIGFuZCBwbXQgcmF0aW8EAAAAC3NlbmRBc3NldElkAwkAAAAAAAACBQAAAApwbXRBc3NldElkBQAAAAhhc3NldElkQQUAAAAIYXNzZXRJZEIFAAAACGFzc2V0SWRBBAAAAAZhbW91bnQJAQAAABNjYWxjdWxhdGVTZW5kQW1vdW50AAAABAUAAAAYZXN0aW1hdGVkQW1vdW50VG9SZWNlaXZlBQAAABJtaW5BbW91bnRUb1JlY2VpdmUFAAAACXBtdEFtb3VudAUAAAAKcG10QXNzZXRJZAQAAAAQZ292ZXJuYW5jZVJld2FyZAkAAGsAAAADBQAAAAZhbW91bnQFAAAADWZlZUdvdmVybmFuY2UFAAAACWZlZVNjYWxlNgQAAAAOYW1vdW50TWludXNGZWUJAABrAAAAAwUAAAAGYW1vdW50CQAAZQAAAAIFAAAACWZlZVNjYWxlNgUAAAADZmVlBQAAAAlmZWVTY2FsZTYEAAAADSR0MDIzMjI1MjM0ODcDCQAAAAAAAAIFAAAACnBtdEFzc2V0SWQFAAAACGFzc2V0SWRBCQAFFAAAAAIJAABkAAAAAgUAAAAIYmFsYW5jZUEFAAAACXBtdEFtb3VudAkAAGUAAAACCQAAZQAAAAIFAAAACGJhbGFuY2VCBQAAAA5hbW91bnRNaW51c0ZlZQUAAAAQZ292ZXJuYW5jZVJld2FyZAkABRQAAAACCQAAZQAAAAIJAABlAAAAAgUAAAAIYmFsYW5jZUEFAAAADmFtb3VudE1pbnVzRmVlBQAAABBnb3Zlcm5hbmNlUmV3YXJkCQAAZAAAAAIFAAAACGJhbGFuY2VCBQAAAAlwbXRBbW91bnQEAAAAC25ld0JhbGFuY2VBCAUAAAANJHQwMjMyMjUyMzQ4NwAAAAJfMQQAAAALbmV3QmFsYW5jZUIIBQAAAA0kdDAyMzIyNTIzNDg3AAAAAl8yBAAAABNkQXBwVGhyZXNob2xkQW1vdW50CQAAawAAAAMJAABkAAAAAgUAAAALbmV3QmFsYW5jZUEFAAAAC25ld0JhbGFuY2VCBQAAAA1kQXBwVGhyZXNob2xkCQAAaAAAAAIAAAAAAAAAAAIFAAAAE2RBcHBUaHJlc2hvbGRTY2FsZTIDAwkAAGYAAAACBQAAABNkQXBwVGhyZXNob2xkQW1vdW50BQAAAAtuZXdCYWxhbmNlQQYJAABmAAAAAgUAAAATZEFwcFRocmVzaG9sZEFtb3VudAUAAAALbmV3QmFsYW5jZUIJAQAAAA50aHJvd1RocmVzaG9sZAAAAAMFAAAAE2RBcHBUaHJlc2hvbGRBbW91bnQFAAAAC25ld0JhbGFuY2VBBQAAAAtuZXdCYWxhbmNlQgQAAAANJHQwMjM3ODYyMzg1OQkBAAAADGdldEFzc2V0SW5mbwAAAAEFAAAACnBtdEFzc2V0SWQEAAAADXBtdFN0ckFzc2V0SWQIBQAAAA0kdDAyMzc4NjIzODU5AAAAAl8xBAAAAAxwbXRBc3NldE5hbWUIBQAAAA0kdDAyMzc4NjIzODU5AAAAAl8y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", "height": 3108037, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: EjBT3rMGvfYtReKQ8WfT3VFiKxNz3x3ghFwqaXusYiuM Next: 23E2C29NFgPR5zpYCTXRNsrzRKRUUUDDX1wre9ErZVZY Diff:
OldNewDifferences
2121
2222 let kFee = "commission"
2323
24-let kFeeScaleDelimiter = "commission_scale_delimiter"
25-
2624 let kInvariant = "invariant"
2725
2826 let kCause = "shutdown_cause"
2927
30-let keyUSDNNSBTAddress = "staking_usdnnsbt_address"
28+let kUSDNAddress = "staking_usdnnsbt_address"
3129
32-let keyEURNAddress = "staking_eurn_address"
30+let kEURNAddress = "staking_eurn_address"
3331
34-let keyAdminPubKey1 = "admin_pub_1"
32+let kAdminPubKey1 = "admin_pub_1"
3533
36-let keyAdminPubKey2 = "admin_pub_2"
34+let kAdminPubKey2 = "admin_pub_2"
3735
38-let keyAdminPubKey3 = "admin_pub_3"
36+let kAdminPubKey3 = "admin_pub_3"
3937
40-let USDNToWavesExchanger = Address(base58'3PHaNgomBkrvEL2QnuJarQVJa71wjw9qiqG')
38+let kAdminInvokePubKey = "admin_invoke_pub"
39+
40+let kMoneyBoxAddress = "money_box_address"
4141
4242 let oracle = Address(base58'3PEbqViERCoKnmcSULh6n2aiMvUdSQdCsom')
4343
44-func getAdminPub (keyAdminPub) = match getString(oracle, keyAdminPub) {
44+func getBase58FromOracle (key) = match getString(oracle, key) {
4545 case string: String =>
4646 fromBase58String(string)
4747 case nothing =>
48- throw("Admin public key is empty")
48+ throw((key + "is empty"))
4949 }
5050
5151
52-let adminPubKey1 = getAdminPub(keyAdminPubKey1)
52+let adminPubKey1 = getBase58FromOracle(kAdminPubKey1)
5353
54-let adminPubKey2 = getAdminPub(keyAdminPubKey2)
54+let adminPubKey2 = getBase58FromOracle(kAdminPubKey2)
5555
56-let adminPubKey3 = getAdminPub(keyAdminPubKey3)
56+let adminPubKey3 = getBase58FromOracle(kAdminPubKey3)
5757
58-let admStartStop = base58'EtVkT6ed8GtbUiVVEqdmEqsp2J4qbb3rre2HFgxeVYdg'
58+let adminPubKeyInvoke = getBase58FromOracle(kAdminInvokePubKey)
5959
60-let admStaking = base58'Czn4yoAuUZCVCLJDRfskn8URfkwpknwBTZDbs1wFrY7h'
60+let moneyBoxAddress = Address(getBase58FromOracle(kMoneyBoxAddress))
6161
62-let walletAddress = Address(base58'3P6J84oH51DzY6xk2mT5TheXRbrCwBMxonp')
62+let stakingUSDNAddress = Address(getBase58FromOracle(kUSDNAddress))
6363
6464 let USDN = base58'DG2xFkPdDwKUoBkzGAhQtLpSGzfXLiCYPEzeKH2Ad24p'
6565
66-let EURN = base58'DUk2YTxhRoAqMJLus4G2b3fR8hMHVh6eiyFx5r29VR6t'
66+let stakingAssets = [toBase58String(USDN)]
6767
68-let stakingAssets = [toBase58String(USDN), toBase58String(EURN)]
69-
70-let stakingUSDNNSBTAddress = Address(fromBase58String(valueOrErrorMessage(getString(oracle, keyUSDNNSBTAddress), "no usdn staking address")))
71-
72-let stakingEURNAddress = Address(fromBase58String(valueOrErrorMessage(getString(oracle, keyEURNAddress), "no usdn staking address")))
73-
74-let isActive = getBooleanValue(this, kActive)
68+let active = getBooleanValue(this, kActive)
7569
7670 let strAssetIdA = getStringValue(this, kAssetIdA)
7771
113107
114108 let invariant = getIntegerValue(this, kInvariant)
115109
116-let fee = 500
110+let fee = getIntegerValue(this, kFee)
117111
118-let feeGovernance = 200
112+let feeGovernance = fraction(fee, 40, 100)
119113
120114 let feeScale6 = 1000000
121115
123117
124118 let scale8 = 100000000
125119
126-let scale12 = 1000000000000
120+let scale16 = 10000000000000000
127121
128122 let slippageScale3 = 1000
129123
141135
142136 let alphaDigits = 2
143137
144-let beta = 46000000
138+let beta = 4600000000000000
145139
146140 func accountBalance (assetId) = match assetId {
147141 case id: ByteVector =>
157151 let stakedAmountCalculated = match assetId {
158152 case aId: ByteVector =>
159153 if ((aId == USDN))
160- then getInteger(stakingUSDNNSBTAddress, ((("rpd_balance_" + toBase58String(aId)) + "_") + toString(this)))
161- else if ((aId == EURN))
162- then getInteger(stakingEURNAddress, ((("%s%s%s__stakingBalance__" + toBase58String(aId)) + "__") + toString(this)))
163- else 0
154+ then getInteger(stakingUSDNAddress, ((("rpd_balance_" + toBase58String(aId)) + "_") + toString(this)))
155+ else 0
164156 case _: Unit =>
165157 0
166158 case _ =>
191183 then (accountBalanceWithStakedB >= balanceB)
192184 else false
193185
194-func skewness (x,y) = (((fraction(scale12, x, y) + fraction(scale12, y, x)) / 2) / 10000)
186+func skewness (x,y) = ((fraction(scale16, x, y) + fraction(scale16, y, x)) / 2)
195187
196188
197189 func invariantCalc (x,y) = {
198190 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)))
191+ (fraction((x + y), scale16, pow(sk, digits8, alpha, alphaDigits, digits8, CEILING)) + (2 * fraction(toInt(pow(fraction(toBigInt(x), toBigInt(y), toBigInt(scale8)), 0, toBigInt(5), 1, (digits8 / 2), DOWN)), pow((sk - beta), digits8, alpha, alphaDigits, digits8, DOWN), scale8)))
200192 }
201193
202194
203195 func calculateSendAmount (amountToSendEstimated,minTokenReceiveAmount,tokenReceiveAmount,tokenId) = {
204- let slippageValue = (scale8 - ((scale8 * 1) / 10000000))
196+ let worstAllowedNewInvariantRatio = (scale16 - ((scale16 * 1) / 10000000))
205197 let deltaBetweenMaxAndMinSendValue = (amountToSendEstimated - minTokenReceiveAmount)
206198 let x = (balanceA + tokenReceiveAmount)
207199 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))
200+ func getStepAmount (acc,step) = if ((acc._1 == -1))
215201 then {
216- let amountToSend = (amountToSendEstimated - ((step * deltaBetweenMaxAndMinSendValue) / 5))
202+ let amountToSend = (amountToSendEstimated - (((step * deltaBetweenMaxAndMinSendValue) / 3) / scale3))
217203 let stepInvariant = if ((tokenId == assetIdA))
218204 then invariantCalc(x, (balanceB - amountToSend))
219205 else invariantCalc((balanceA - amountToSend), y)
220206 if ((stepInvariant > invariant))
221- then amountToSend
222- else -1
207+ then $Tuple2(amountToSend, stepInvariant)
208+ else $Tuple2(-1, 0)
223209 }
224210 else acc
225211
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])
212+ let amountToSendMin = getStepAmount($Tuple2(-1, 0), 3000)
213+ if ((0 > amountToSendMin._1))
214+ then throw("Price is worse than minReceived")
215+ else {
216+ let invEstimated = if ((tokenId == assetIdA))
217+ then invariantCalc(x, (balanceB - amountToSendEstimated))
218+ else if ((tokenId == assetIdB))
219+ then invariantCalc((balanceA - amountToSendEstimated), y)
220+ else throw("Wrong asset in payment")
221+ if ((invariant > invEstimated))
222+ then if ((worstAllowedNewInvariantRatio >= fraction(scale16, invariant, invEstimated)))
223+ then throw("The requested price is too not profitable for user")
224+ else {
225+ let a = {
226+ let $l = [25, 200, 500]
227+ let $s = size($l)
228+ let $acc0 = $Tuple2(-1, 0)
229+ func $f0_1 ($a,$i) = if (($i >= $s))
230+ then $a
231+ else getStepAmount($a, $l[$i])
233232
234- func $f0_2 ($a,$i) = if (($i >= $s))
235- then $a
236- else throw("List size exceeds 5")
233+ func $f0_2 ($a,$i) = if (($i >= $s))
234+ then $a
235+ else throw("List size exceeds 3")
237236
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
237+ $f0_2($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3)
238+ }
239+ if ((0 > a._1))
240+ then amountToSendMin._1
241+ else a._1
242+ }
243+ else {
244+ let a = {
245+ let $l = [-500, -200, -25]
246+ let $s = size($l)
247+ let $acc0 = $Tuple2(-1, 0)
248+ func $f0_1 ($a,$i) = if (($i >= $s))
249+ then $a
250+ else getStepAmount($a, $l[$i])
251+
252+ func $f0_2 ($a,$i) = if (($i >= $s))
253+ then $a
254+ else throw("List size exceeds 3")
255+
256+ $f0_2($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3)
257+ }
258+ let tupleSendBetter = if ((0 > a._1))
259+ then $Tuple2(amountToSendEstimated, invEstimated)
260+ else a
261+ if ((worstAllowedNewInvariantRatio >= fraction(scale16, invariant, tupleSendBetter._2)))
262+ then throw("The requested price is too not profitable for user")
263+ else tupleSendBetter._1
264+ }
265+ }
247266 }
248267
249268
265284 func throwIsActive () = throw("DApp is already active")
266285
267286
268-func throwIsInactive () = throw("DApp is inactive at this moment")
287+func isActive () = if (active)
288+ then unit
289+ else throw("DApp is inactive at this moment")
269290
270291
271-func throwOnlyAdmin () = throw("Only admin can call this function")
292+func isAdminCall (i) = if (containsElement([adminPubKey1, adminPubKey2, adminPubKey3], i.callerPublicKey))
293+ then unit
294+ else throw("Only admin can call this function")
272295
273296
274297 func throwAssets () = throw(((("Incorrect assets attached. Expected: " + strAssetIdA) + " and ") + strAssetIdB))
298+
299+
300+func throwOnePayment () = throw("One attached payment expected")
275301
276302
277303 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))
281307
282308
283309 func calcStakingFuncAndAddres (stake,assetId) = if (stake)
284- then if ((assetId == USDN))
285- then $Tuple2("lockNeutrino", stakingUSDNNSBTAddress)
286- else $Tuple2("startStaking", stakingEURNAddress)
287- else if ((assetId == USDN))
288- then $Tuple2("unlockNeutrino", stakingUSDNNSBTAddress)
289- else $Tuple2("stopStaking", stakingEURNAddress)
310+ then $Tuple2("lockNeutrino", stakingUSDNAddress)
311+ else $Tuple2("unlockNeutrino", stakingUSDNAddress)
290312
291313
292314 func calcStakingParams (stake,amount,assetId) = if (stake)
293315 then {
294- let $t087608826 = calcStakingFuncAndAddres(stake, assetId)
295- let call = $t087608826._1
296- let stakingAddr = $t087608826._2
316+ let $t091419207 = calcStakingFuncAndAddres(stake, assetId)
317+ let call = $t091419207._1
318+ let stakingAddr = $t091419207._2
297319 $Tuple4(call, stakingAddr, nil, [AttachedPayment(assetId, amount)])
298320 }
299321 else {
300- let $t089128978 = calcStakingFuncAndAddres(stake, assetId)
301- let call = $t089128978._1
302- let stakingAddr = $t089128978._2
322+ let $t092939359 = calcStakingFuncAndAddres(stake, assetId)
323+ let call = $t092939359._1
324+ let stakingAddr = $t092939359._2
303325 $Tuple4(call, stakingAddr, [amount, toBase58String(assetId)], nil)
304326 }
305327
306328
307329 @Callable(i)
308330 func init () = {
309- let $t090839160 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
310- let pmtAmountA = $t090839160._1
311- let pmtAssetIdA = $t090839160._2
312- let $t091659242 = $Tuple2(i.payments[1].amount, i.payments[1].assetId)
313- let pmtAmountB = $t091659242._1
314- let pmtAssetIdB = $t091659242._2
315- let $t092479324 = getAssetInfo(pmtAssetIdA)
316- let pmtStrAssetIdA = $t092479324._1
317- let pmtAssetNameA = $t092479324._2
318- let pmtDecimalsA = $t092479324._3
319- let $t093299406 = getAssetInfo(pmtAssetIdB)
320- let pmtStrAssetIdB = $t093299406._1
321- let pmtAssetNameB = $t093299406._2
322- let pmtDecimalsB = $t093299406._3
331+ let $t094649541 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
332+ let pmtAmountA = $t094649541._1
333+ let pmtAssetIdA = $t094649541._2
334+ let $t095469623 = $Tuple2(i.payments[1].amount, i.payments[1].assetId)
335+ let pmtAmountB = $t095469623._1
336+ let pmtAssetIdB = $t095469623._2
337+ let $t096289705 = getAssetInfo(pmtAssetIdA)
338+ let pmtStrAssetIdA = $t096289705._1
339+ let pmtAssetNameA = $t096289705._2
340+ let pmtDecimalsA = $t096289705._3
341+ let $t097109787 = getAssetInfo(pmtAssetIdB)
342+ let pmtStrAssetIdB = $t097109787._1
343+ let pmtAssetNameB = $t097109787._2
344+ let pmtDecimalsB = $t097109787._3
323345 if (isDefined(getBoolean(this, kActive)))
324346 then throwIsActive()
325347 else if ((pmtAssetIdA == pmtAssetIdB))
341363 then invoke(this, "stakeUnstake", [true, pmtAmountB, pmtStrAssetIdB], nil)
342364 else 0
343365 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)]
366+ then [StringEntry(kVersion, version), BooleanEntry(kActive, true), StringEntry(kAssetIdA, pmtStrAssetIdA), StringEntry(kAssetIdB, pmtStrAssetIdB), IntegerEntry(kBalanceA, pmtAmountA), IntegerEntry(kBalanceB, pmtAmountB), IntegerEntry(kInvariant, invariantCalculated), IntegerEntry(kFee, getIntegerValue(oracle, "base_fee_flat")), shareIssue, StringEntry(kShareAssetId, toBase58String(shareIssueId)), IntegerEntry(kShareAssetSupply, shareInitialSupply), ScriptTransfer(i.caller, shareInitialSupply, shareIssueId)]
345367 else throw("Strict value is not equal to itself.")
346368 }
347369 else throw("Strict value is not equal to itself.")
351373
352374
353375 @Callable(i)
354-func replenishWithTwoTokens (slippageTolerance) = {
376+func replenishWithTwoTokens () = valueOrElse(isActive(), {
355377 let pmtAssetIdA = i.payments[0].assetId
356378 let pmtAssetIdB = i.payments[1].assetId
357- let pmtAmountA = i.payments[0].amount
358- let pmtAmountB = i.payments[1].amount
359- let $t01192211999 = getAssetInfo(pmtAssetIdA)
360- let pmtStrAssetIdA = $t01192211999._1
361- let pmtAssetNameA = $t01192211999._2
362- let pmtDecimalsA = $t01192211999._3
363- let $t01200412198 = getAssetInfo(pmtAssetIdB)
364- let pmtStrAssetIdB = $t01200412198._1
365- let pmtAssetNameB = $t01200412198._2
366- let pmtDecimalsB = $t01200412198._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))
379+ let ratioShareTokensInA = fraction(scale8, i.payments[0].amount, balanceA)
380+ let ratioShareTokensInB = fraction(scale8, i.payments[1].amount, balanceB)
381+ let $t01243512512 = getAssetInfo(pmtAssetIdA)
382+ let pmtStrAssetIdA = $t01243512512._1
383+ let pmtAssetNameA = $t01243512512._2
384+ let pmtDecimalsA = $t01243512512._3
385+ let $t01251712634 = getAssetInfo(pmtAssetIdB)
386+ let pmtStrAssetIdB = $t01251712634._1
387+ let pmtAssetNameB = $t01251712634._2
388+ let pmtDecimalsB = $t01251712634._3
389+ let $t01263913143 = if ((ratioShareTokensInB > ratioShareTokensInA))
390+ then {
391+ let pmt = fraction(balanceB, ratioShareTokensInA, scale8, CEILING)
392+ $Tuple5(i.payments[0].amount, pmt, (i.payments[1].amount - pmt), pmtAssetIdB, ratioShareTokensInA)
393+ }
394+ else {
395+ let pmt = fraction(balanceA, ratioShareTokensInB, scale8, CEILING)
396+ $Tuple5(pmt, i.payments[1].amount, (i.payments[0].amount - pmt), pmtAssetIdA, ratioShareTokensInB)
397+ }
398+ let pmtAmountA = $t01263913143._1
399+ let pmtAmountB = $t01263913143._2
400+ let change = $t01263913143._3
401+ let changeAssetId = $t01263913143._4
402+ let shareTokenRatio = $t01263913143._5
403+ let shareTokenToPayAmount = fraction(shareTokenRatio, shareAssetSupply, scale8)
404+ if ((size(i.payments) != 2))
405+ then throw("Two attached assets expected")
406+ else if (if ((pmtAssetIdA != assetIdA))
375407 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)
408+ else (pmtAssetIdB != assetIdB))
409+ then throwAssets()
410+ else if ((shareTokenToPayAmount == 0))
411+ then throw("Too small amount to replenish")
412+ else if ((0 > change))
413+ then throw("Change < 0")
414+ else if (!(hasEnoughBalance))
415+ then ([ScriptTransfer(i.caller, pmtAmountA, pmtAssetIdA), ScriptTransfer(i.caller, pmtAmountB, pmtAssetIdB)] ++ suspendSuspicious())
416+ else {
417+ let stake1 = if (containsElement(stakingAssets, pmtStrAssetIdA))
418+ then invoke(this, "stakeUnstake", [true, pmtAmountA, pmtStrAssetIdA], nil)
419+ else 0
420+ if ((stake1 == stake1))
421+ then {
422+ let stake2 = if (containsElement(stakingAssets, pmtStrAssetIdB))
423+ then invoke(this, "stakeUnstake", [true, pmtAmountB, pmtStrAssetIdB], nil)
395424 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- }
425+ if ((stake2 == stake2))
426+ then [IntegerEntry(kBalanceA, (balanceA + pmtAmountA)), IntegerEntry(kBalanceB, (balanceB + pmtAmountB)), IntegerEntry(kShareAssetSupply, (shareAssetSupply + shareTokenToPayAmount)), IntegerEntry(kInvariant, invariantCalc((balanceA + pmtAmountA), (balanceB + pmtAmountB))), Reissue(shareAssetId, shareTokenToPayAmount, true), ScriptTransfer(i.caller, shareTokenToPayAmount, shareAssetId), ScriptTransfer(i.caller, change, changeAssetId)]
405427 else throw("Strict value is not equal to itself.")
406428 }
407- }
429+ else throw("Strict value is not equal to itself.")
430+ }
431+ })
408432
409433
410434
411435 @Callable(i)
412-func replenishWithOneToken (virtualSwapTokenPay,virtualSwapTokenGet) = {
413- let $t01449714572 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
414- let pmtAmount = $t01449714572._1
415- let pmtAssetId = $t01449714572._2
416- let $t01457714650 = getAssetInfo(pmtAssetId)
417- let pmtStrAssetId = $t01457714650._1
418- let pmtAssetName = $t01457714650._2
419- let pmtDecimals = $t01457714650._3
436+func replenishWithOneToken (virtualSwapTokenPay,virtualSwapTokenGet) = valueOrElse(isActive(), {
437+ let $t01487614951 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
438+ let pmtAmount = $t01487614951._1
439+ let pmtAssetId = $t01487614951._2
440+ let $t01495615029 = getAssetInfo(pmtAssetId)
441+ let pmtStrAssetId = $t01495615029._1
442+ let pmtAssetName = $t01495615029._2
443+ let pmtDecimals = $t01495615029._3
420444 let pmtMinThreshold = 5000000
421445 let thresholdValueForMinTolerance = 50000000
422446 let tolerance = if ((thresholdValueForMinTolerance > pmtAmount))
425449 let slippageValueMinForReplenish = (scale8 - ((scale8 * tolerance) / 10000000))
426450 let slippageValueMaxForReplenish = (scale8 + ((scale8 * tolerance) / 10000000))
427451 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"))
452+ if ((pmtMinThreshold > pmtAmount))
453+ then throw((((("Payment amount " + toString(pmtAmount)) + " does not exceed the minimum amount of ") + toString(pmtMinThreshold)) + " tokens"))
454+ else if ((size(i.payments) != 1))
455+ then throwOnePayment()
456+ else if (!(hasEnoughBalance))
457+ then ([ScriptTransfer(i.caller, pmtAmount, pmtAssetId)] ++ suspendSuspicious())
458+ else if (if ((pmtAssetId != assetIdA))
459+ then (pmtAssetId != assetIdB)
460+ else false)
461+ then throwAssets()
462+ else {
463+ let $t01600716649 = if ((pmtAssetId == assetIdA))
464+ then $Tuple6((pmtAmount - virtualSwapTokenPay), virtualSwapTokenGet, (balanceA + virtualSwapTokenPay), (balanceB - virtualSwapTokenGet), (balanceA + pmtAmount), balanceB)
465+ else $Tuple6(virtualSwapTokenGet, (pmtAmount - virtualSwapTokenPay), (balanceA - virtualSwapTokenGet), (balanceB + virtualSwapTokenPay), balanceA, (balanceB + pmtAmount))
466+ let virtualReplenishA = $t01600716649._1
467+ let virtualReplenishB = $t01600716649._2
468+ let balanceAfterSwapA = $t01600716649._3
469+ let balanceAfterSwapB = $t01600716649._4
470+ let newBalanceA = $t01600716649._5
471+ let newBalanceB = $t01600716649._6
472+ let invariantNew = invariantCalc(balanceAfterSwapA, balanceAfterSwapB)
473+ let ratioVirtualBalanceToVirtualReplenish = (fraction(scale16, balanceAfterSwapA, balanceAfterSwapB) / fraction(scale8, virtualReplenishA, virtualReplenishB))
474+ let dAppThresholdAmount = fraction((newBalanceA + newBalanceB), dAppThreshold, (2 * dAppThresholdScale2))
475+ if (if ((slippageValueMinForSwap >= fraction(scale8, invariant, invariantNew)))
476+ then true
477+ else (invariant > invariantNew))
478+ then throw("Incorrect virtualSwapTokenPay or virtualSwapTokenGet value")
479+ else if (if ((slippageValueMinForReplenish > ratioVirtualBalanceToVirtualReplenish))
480+ then true
481+ else (ratioVirtualBalanceToVirtualReplenish > slippageValueMaxForReplenish))
482+ then throw("Swap with virtualSwapTokenPay and virtualSwapTokenGet is possible, but ratio after virtual swap is incorrect")
483+ else if (if ((dAppThresholdAmount > newBalanceA))
484+ then true
485+ else (dAppThresholdAmount > newBalanceB))
486+ then throwThreshold(dAppThresholdAmount, newBalanceA, newBalanceB)
487+ else {
488+ let ratioShareTokensInA = fraction(virtualReplenishA, scale8, balanceAfterSwapA)
489+ let ratioShareTokensInB = fraction(virtualReplenishB, scale8, balanceAfterSwapB)
490+ let shareTokenToPayAmount = fraction(min([ratioShareTokensInA, ratioShareTokensInB]), shareAssetSupply, scale8)
491+ let shareTokenToPayAmountAfterFee = fraction(shareTokenToPayAmount, (feeScale6 - (fee / 2)), feeScale6)
492+ let shareTokenGovernanceReward = fraction(shareTokenToPayAmount, (feeGovernance / 2), feeScale6)
493+ let governanceRewardTokenA = fraction(shareTokenGovernanceReward, balanceA, shareAssetSupply)
494+ let governanceRewardTokenB = fraction(shareTokenGovernanceReward, balanceB, shareAssetSupply)
495+ let $t01863618931 = if ((pmtStrAssetId == strAssetIdA))
496+ then $Tuple3((pmtAmount - governanceRewardTokenA), governanceRewardTokenB, strAssetIdB)
497+ else $Tuple3((pmtAmount - governanceRewardTokenB), governanceRewardTokenA, strAssetIdA)
498+ let stakeAmount = $t01863618931._1
499+ let unstakeAmount = $t01863618931._2
500+ let unstakeAsset = $t01863618931._3
501+ let stake1 = if (containsElement(stakingAssets, pmtStrAssetId))
502+ then invoke(this, "stakeUnstake", [true, stakeAmount, pmtStrAssetId], nil)
503+ else 0
504+ if ((stake1 == stake1))
505+ then {
506+ let stake2 = if (containsElement(stakingAssets, unstakeAsset))
507+ then invoke(this, "stakeUnstake", [false, unstakeAmount, unstakeAsset], nil)
508+ else 0
509+ if ((stake2 == stake2))
510+ then [Reissue(shareAssetId, shareTokenToPayAmountAfterFee, true), ScriptTransfer(i.caller, shareTokenToPayAmountAfterFee, shareAssetId), ScriptTransfer(moneyBoxAddress, governanceRewardTokenA, assetIdA), ScriptTransfer(moneyBoxAddress, governanceRewardTokenB, assetIdB), IntegerEntry(kBalanceA, (newBalanceA - governanceRewardTokenA)), IntegerEntry(kBalanceB, (newBalanceB - governanceRewardTokenB)), IntegerEntry(kShareAssetSupply, (shareAssetSupply + shareTokenToPayAmountAfterFee)), IntegerEntry(kInvariant, invariantCalc((newBalanceA - governanceRewardTokenA), (newBalanceB - governanceRewardTokenB)))]
511+ else throw("Strict value is not equal to itself.")
512+ }
513+ else throw("Strict value is not equal to itself.")
514+ }
515+ }
516+ })
517+
518+
519+
520+@Callable(i)
521+func withdraw () = valueOrElse(isActive(), {
522+ let $t02021820293 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
523+ let pmtAmount = $t02021820293._1
524+ let pmtAssetId = $t02021820293._2
525+ let amountToPayA = fraction(pmtAmount, balanceA, shareAssetSupply)
526+ let amountToPayB = fraction(pmtAmount, balanceB, shareAssetSupply)
527+ let invariantCalculated = invariantCalc((balanceA - amountToPayA), (balanceB - amountToPayB))
528+ if ((size(i.payments) != 1))
529+ then throwOnePayment()
530+ else if ((pmtAssetId != shareAssetId))
531+ then throw(("Incorrect asset attached. Expected: " + toBase58String(shareAssetId)))
532+ else if (!(hasEnoughBalance))
533+ then ([ScriptTransfer(i.caller, pmtAmount, pmtAssetId)] ++ suspendSuspicious())
534+ else {
535+ let stake1 = if (containsElement(stakingAssets, strAssetIdA))
536+ then invoke(this, "stakeUnstake", [false, amountToPayA, strAssetIdA], nil)
537+ else 0
538+ if ((stake1 == stake1))
539+ then {
540+ let stake2 = if (containsElement(stakingAssets, strAssetIdB))
541+ then invoke(this, "stakeUnstake", [false, amountToPayB, strAssetIdB], nil)
542+ else 0
543+ if ((stake2 == stake2))
544+ 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)]
545+ else throw("Strict value is not equal to itself.")
546+ }
547+ else throw("Strict value is not equal to itself.")
548+ }
549+ })
550+
551+
552+
553+@Callable(i)
554+func exchange (estimatedAmountToReceive,minAmountToReceive) = valueOrElse(isActive(), {
555+ let $t02184421919 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
556+ let pmtAmount = $t02184421919._1
557+ let pmtAssetId = $t02184421919._2
558+ if ((0 >= estimatedAmountToReceive))
559+ then throw(("Estimated amount must be positive. Actual: " + toString(estimatedAmountToReceive)))
560+ else if ((minAmountToReceive > estimatedAmountToReceive))
561+ then throw("Minimal amount can't be greater than estimated.")
432562 else if ((size(i.payments) != 1))
433- then throw("One attached payment expected")
563+ then throwOnePayment()
434564 else if (!(hasEnoughBalance))
435565 then ([ScriptTransfer(i.caller, pmtAmount, pmtAssetId)] ++ suspendSuspicious())
436566 else if (if ((pmtAssetId != assetIdA))
437567 then (pmtAssetId != assetIdB)
438568 else false)
439569 then throwAssets()
440- else {
441- let $t01566216427 = 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 = $t01566216427._1
445- let virtualReplenishB = $t01566216427._2
446- let balanceAfterSwapA = $t01566216427._3
447- let balanceAfterSwapB = $t01566216427._4
448- let invariantCalculated = $t01566216427._5
449- let newBalanceA = $t01566216427._6
450- let newBalanceB = $t01566216427._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))
570+ else if ((10000000 > pmtAmount))
571+ then throw("Only swap of 10.000000 or more tokens is allowed")
572+ else if (if ((exchangeRatioLimitMin > fraction(scale8, minAmountToReceive, pmtAmount)))
459573 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))
574+ else (fraction(scale8, estimatedAmountToReceive, pmtAmount) > exchangeRatioLimitMax))
575+ then throw("Incorrect args and pmt ratio")
576+ else {
577+ let sendAssetId = if ((pmtAssetId == assetIdA))
578+ then assetIdB
579+ else assetIdA
580+ let amount = calculateSendAmount(estimatedAmountToReceive, minAmountToReceive, pmtAmount, pmtAssetId)
581+ let governanceReward = fraction(amount, feeGovernance, feeScale6)
582+ let amountMinusFee = fraction(amount, (feeScale6 - fee), feeScale6)
583+ let $t02322523487 = if ((pmtAssetId == assetIdA))
584+ then $Tuple2((balanceA + pmtAmount), ((balanceB - amountMinusFee) - governanceReward))
585+ else $Tuple2(((balanceA - amountMinusFee) - governanceReward), (balanceB + pmtAmount))
586+ let newBalanceA = $t02322523487._1
587+ let newBalanceB = $t02322523487._2
588+ let dAppThresholdAmount = fraction((newBalanceA + newBalanceB), dAppThreshold, (2 * dAppThresholdScale2))
589+ if (if ((dAppThresholdAmount > newBalanceA))
467590 then true
468591 else (dAppThresholdAmount > newBalanceB))
469592 then throwThreshold(dAppThresholdAmount, newBalanceA, newBalanceB)
470593 else {
594+ let $t02378623859 = getAssetInfo(pmtAssetId)
595+ let pmtStrAssetId = $t02378623859._1
596+ let pmtAssetName = $t02378623859._2
597+ let pmtDecimals = $t02378623859._3
598+ let $t02387223949 = getAssetInfo(sendAssetId)
599+ let sendStrAssetId = $t02387223949._1
600+ let sendAssetName = $t02387223949._2
601+ let sendDecimals = $t02387223949._3
471602 let stake1 = if (containsElement(stakingAssets, pmtStrAssetId))
472603 then invoke(this, "stakeUnstake", [true, pmtAmount, pmtStrAssetId], nil)
473604 else 0
474605 if ((stake1 == stake1))
475606 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)]
607+ let stake2 = if (containsElement(stakingAssets, sendStrAssetId))
608+ then invoke(this, "stakeUnstake", [false, (amountMinusFee + governanceReward), sendStrAssetId], nil)
609+ else 0
610+ if ((stake2 == stake2))
611+ then $Tuple2([IntegerEntry(kBalanceA, newBalanceA), IntegerEntry(kBalanceB, newBalanceB), IntegerEntry(kInvariant, invariantCalc(newBalanceA, newBalanceB)), ScriptTransfer(i.caller, amountMinusFee, sendAssetId), ScriptTransfer(moneyBoxAddress, governanceReward, sendAssetId)], $Tuple2(amountMinusFee, sendAssetId))
612+ else throw("Strict value is not equal to itself.")
480613 }
481614 else throw("Strict value is not equal to itself.")
482615 }
483- }
484- }
616+ }
617+ })
485618
486619
487620
488621 @Callable(i)
489-func withdraw () = {
490- let $t01865318796 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
491- let pmtAmount = $t01865318796._1
492- let pmtAssetId = $t01865318796._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)
512- else 0
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)]
515- else throw("Strict value is not equal to itself.")
516- }
517- else throw("Strict value is not equal to itself.")
518- }
519- }
622+func shutdown () = valueOrElse(isAdminCall(i), if (!(active))
623+ then throw(("DApp is already suspended. Cause: " + valueOrElse(getString(this, kCause), "the cause wasn't specified")))
624+ else suspend("Paused by admin"))
520625
521626
522627
523628 @Callable(i)
524-func exchange (estimatedAmountToReceive,minAmountToReceive) = {
525- let $t02031020385 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
526- let pmtAmount = $t02031020385._1
527- let pmtAssetId = $t02031020385._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 $t02180722069 = if ((pmtAssetId == assetIdA))
556- then $Tuple2((balanceA + pmtAmount), ((balanceB - amountMinusFee) - governanceReward))
557- else $Tuple2(((balanceA - amountMinusFee) - governanceReward), (balanceB + pmtAmount))
558- let newBalanceA = $t02180722069._1
559- let newBalanceB = $t02180722069._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 $t02236722440 = getAssetInfo(pmtAssetId)
567- let pmtStrAssetId = $t02236722440._1
568- let pmtAssetName = $t02236722440._2
569- let pmtDecimals = $t02236722440._3
570- let $t02245322530 = getAssetInfo(sendAssetId)
571- let sendStrAssetId = $t02245322530._1
572- let sendAssetName = $t02245322530._2
573- let sendDecimals = $t02245322530._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- }
629+func activate () = valueOrElse(isAdminCall(i), if (active)
630+ then throwIsActive()
631+ else [BooleanEntry(kActive, true), DeleteEntry(kCause)])
590632
591633
592634
593635 @Callable(i)
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()
598- else suspend("Paused by admin")
599-
600-
601-
602-@Callable(i)
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)]
608-
609-
610-
611-@Callable(i)
612-func takeIntoAccountExtraFunds () = {
636+func takeIntoAccountExtraFunds () = valueOrElse(isActive(), {
613637 let amountEnrollA = (accountBalanceWithStakedA - balanceA)
614638 let amountEnrollB = (accountBalanceWithStakedB - balanceB)
615639 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- }
640+ if ((i.caller != moneyBoxAddress))
641+ then throw("Only the money box can call this function")
642+ else if (if ((0 > amountEnrollA))
643+ then true
644+ else (0 > amountEnrollB))
645+ then suspend("Enroll amount negative")
646+ else if (if ((amountEnrollA == 0))
647+ then (amountEnrollB == 0)
648+ else false)
649+ then throw("No money to take")
650+ else {
651+ let stake1 = if (if (containsElement(stakingAssets, strAssetIdA))
652+ then (amountEnrollA > 0)
653+ else false)
654+ then invoke(this, "stakeUnstake", [true, amountEnrollA, strAssetIdA], nil)
655+ else 0
656+ if ((stake1 == stake1))
657+ then {
658+ let stake2 = if (if (containsElement(stakingAssets, strAssetIdB))
659+ then (amountEnrollB > 0)
660+ else false)
661+ then invoke(this, "stakeUnstake", [true, amountEnrollB, strAssetIdB], nil)
662+ else 0
663+ if ((stake2 == stake2))
664+ then [IntegerEntry(kInvariant, invariantNew), IntegerEntry(kBalanceA, (balanceA + amountEnrollA)), IntegerEntry(kBalanceB, (balanceB + amountEnrollB))]
665+ else throw("Strict value is not equal to itself.")
666+ }
667+ else throw("Strict value is not equal to itself.")
668+ }
669+ })
648670
649671
650672
652674 func stakeUnstake (stake,amount,assetIdString) = if ((i.caller != this))
653675 then throw("Only contract itself can invoke this function")
654676 else {
655- let $t02559225695 = calcStakingParams(stake, amount, fromBase58String(assetIdString))
656- let call = $t02559225695._1
657- let addr = $t02559225695._2
658- let params = $t02559225695._3
659- let payments = $t02559225695._4
677+ let $t02695327056 = calcStakingParams(stake, amount, fromBase58String(assetIdString))
678+ let call = $t02695327056._1
679+ let addr = $t02695327056._2
680+ let params = $t02695327056._3
681+ let payments = $t02695327056._4
660682 let inv = invoke(addr, call, params, payments)
661683 if ((inv == inv))
662684 then nil
666688
667689
668690 @Callable(i)
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- }
691+func toBigIntInvariant () = valueOrElse(isAdminCall(i), [IntegerEntry(kInvariant, invariantCalc(balanceA, balanceB))])
698692
699693
700694 @Verifier(tx)
722716 then true
723717 else sigVerify(tx.bodyBytes, tx.proofs[0], adminPubKey3))
724718 then true
725- else sigVerify(tx.bodyBytes, tx.proofs[0], admStaking)
719+ else sigVerify(tx.bodyBytes, tx.proofs[0], adminPubKeyInvoke)
726720 if (if (callTakeIntoAccount)
727721 then signedByAdmin
728722 else false)
Full:
OldNewDifferences
11 {-# STDLIB_VERSION 5 #-}
22 {-# SCRIPT_TYPE ACCOUNT #-}
33 {-# CONTENT_TYPE DAPP #-}
44 let version = "2.0.0"
55
66 let kVersion = "version"
77
88 let kActive = "active"
99
1010 let kAssetIdA = "A_asset_id"
1111
1212 let kAssetIdB = "B_asset_id"
1313
1414 let kBalanceA = "A_asset_balance"
1515
1616 let kBalanceB = "B_asset_balance"
1717
1818 let kShareAssetId = "share_asset_id"
1919
2020 let kShareAssetSupply = "share_asset_supply"
2121
2222 let kFee = "commission"
2323
24-let kFeeScaleDelimiter = "commission_scale_delimiter"
25-
2624 let kInvariant = "invariant"
2725
2826 let kCause = "shutdown_cause"
2927
30-let keyUSDNNSBTAddress = "staking_usdnnsbt_address"
28+let kUSDNAddress = "staking_usdnnsbt_address"
3129
32-let keyEURNAddress = "staking_eurn_address"
30+let kEURNAddress = "staking_eurn_address"
3331
34-let keyAdminPubKey1 = "admin_pub_1"
32+let kAdminPubKey1 = "admin_pub_1"
3533
36-let keyAdminPubKey2 = "admin_pub_2"
34+let kAdminPubKey2 = "admin_pub_2"
3735
38-let keyAdminPubKey3 = "admin_pub_3"
36+let kAdminPubKey3 = "admin_pub_3"
3937
40-let USDNToWavesExchanger = Address(base58'3PHaNgomBkrvEL2QnuJarQVJa71wjw9qiqG')
38+let kAdminInvokePubKey = "admin_invoke_pub"
39+
40+let kMoneyBoxAddress = "money_box_address"
4141
4242 let oracle = Address(base58'3PEbqViERCoKnmcSULh6n2aiMvUdSQdCsom')
4343
44-func getAdminPub (keyAdminPub) = match getString(oracle, keyAdminPub) {
44+func getBase58FromOracle (key) = match getString(oracle, key) {
4545 case string: String =>
4646 fromBase58String(string)
4747 case nothing =>
48- throw("Admin public key is empty")
48+ throw((key + "is empty"))
4949 }
5050
5151
52-let adminPubKey1 = getAdminPub(keyAdminPubKey1)
52+let adminPubKey1 = getBase58FromOracle(kAdminPubKey1)
5353
54-let adminPubKey2 = getAdminPub(keyAdminPubKey2)
54+let adminPubKey2 = getBase58FromOracle(kAdminPubKey2)
5555
56-let adminPubKey3 = getAdminPub(keyAdminPubKey3)
56+let adminPubKey3 = getBase58FromOracle(kAdminPubKey3)
5757
58-let admStartStop = base58'EtVkT6ed8GtbUiVVEqdmEqsp2J4qbb3rre2HFgxeVYdg'
58+let adminPubKeyInvoke = getBase58FromOracle(kAdminInvokePubKey)
5959
60-let admStaking = base58'Czn4yoAuUZCVCLJDRfskn8URfkwpknwBTZDbs1wFrY7h'
60+let moneyBoxAddress = Address(getBase58FromOracle(kMoneyBoxAddress))
6161
62-let walletAddress = Address(base58'3P6J84oH51DzY6xk2mT5TheXRbrCwBMxonp')
62+let stakingUSDNAddress = Address(getBase58FromOracle(kUSDNAddress))
6363
6464 let USDN = base58'DG2xFkPdDwKUoBkzGAhQtLpSGzfXLiCYPEzeKH2Ad24p'
6565
66-let EURN = base58'DUk2YTxhRoAqMJLus4G2b3fR8hMHVh6eiyFx5r29VR6t'
66+let stakingAssets = [toBase58String(USDN)]
6767
68-let stakingAssets = [toBase58String(USDN), toBase58String(EURN)]
69-
70-let stakingUSDNNSBTAddress = Address(fromBase58String(valueOrErrorMessage(getString(oracle, keyUSDNNSBTAddress), "no usdn staking address")))
71-
72-let stakingEURNAddress = Address(fromBase58String(valueOrErrorMessage(getString(oracle, keyEURNAddress), "no usdn staking address")))
73-
74-let isActive = getBooleanValue(this, kActive)
68+let active = getBooleanValue(this, kActive)
7569
7670 let strAssetIdA = getStringValue(this, kAssetIdA)
7771
7872 let strAssetIdB = getStringValue(this, kAssetIdB)
7973
8074 let assetIdA = if ((strAssetIdA == "WAVES"))
8175 then unit
8276 else fromBase58String(strAssetIdA)
8377
8478 let assetIdB = if ((strAssetIdB == "WAVES"))
8579 then unit
8680 else fromBase58String(strAssetIdB)
8781
8882 let assetNameA = match assetIdA {
8983 case id: ByteVector =>
9084 value(assetInfo(id)).name
9185 case waves: Unit =>
9286 "WAVES"
9387 case _ =>
9488 throw("Match error")
9589 }
9690
9791 let assetNameB = match assetIdB {
9892 case id: ByteVector =>
9993 value(assetInfo(id)).name
10094 case waves: Unit =>
10195 "WAVES"
10296 case _ =>
10397 throw("Match error")
10498 }
10599
106100 let balanceA = getIntegerValue(this, kBalanceA)
107101
108102 let balanceB = getIntegerValue(this, kBalanceB)
109103
110104 let shareAssetId = fromBase58String(getStringValue(this, kShareAssetId))
111105
112106 let shareAssetSupply = getIntegerValue(this, kShareAssetSupply)
113107
114108 let invariant = getIntegerValue(this, kInvariant)
115109
116-let fee = 500
110+let fee = getIntegerValue(this, kFee)
117111
118-let feeGovernance = 200
112+let feeGovernance = fraction(fee, 40, 100)
119113
120114 let feeScale6 = 1000000
121115
122116 let scale3 = 1000
123117
124118 let scale8 = 100000000
125119
126-let scale12 = 1000000000000
120+let scale16 = 10000000000000000
127121
128122 let slippageScale3 = 1000
129123
130124 let digits8 = 8
131125
132126 let dAppThreshold = 50
133127
134128 let dAppThresholdScale2 = 100
135129
136130 let exchangeRatioLimitMin = 90000000
137131
138132 let exchangeRatioLimitMax = 110000000
139133
140134 let alpha = 50
141135
142136 let alphaDigits = 2
143137
144-let beta = 46000000
138+let beta = 4600000000000000
145139
146140 func accountBalance (assetId) = match assetId {
147141 case id: ByteVector =>
148142 assetBalance(this, id)
149143 case waves: Unit =>
150144 wavesBalance(this).available
151145 case _ =>
152146 throw("Match error")
153147 }
154148
155149
156150 func stakedAmount (assetId) = {
157151 let stakedAmountCalculated = match assetId {
158152 case aId: ByteVector =>
159153 if ((aId == USDN))
160- then getInteger(stakingUSDNNSBTAddress, ((("rpd_balance_" + toBase58String(aId)) + "_") + toString(this)))
161- else if ((aId == EURN))
162- then getInteger(stakingEURNAddress, ((("%s%s%s__stakingBalance__" + toBase58String(aId)) + "__") + toString(this)))
163- else 0
154+ then getInteger(stakingUSDNAddress, ((("rpd_balance_" + toBase58String(aId)) + "_") + toString(this)))
155+ else 0
164156 case _: Unit =>
165157 0
166158 case _ =>
167159 throw("Match error")
168160 }
169161 match stakedAmountCalculated {
170162 case i: Int =>
171163 i
172164 case _ =>
173165 0
174166 }
175167 }
176168
177169
178170 let stakedAmountA = stakedAmount(assetIdA)
179171
180172 let stakedAmountB = stakedAmount(assetIdB)
181173
182174 let availableBalanceA = (balanceA - stakedAmountA)
183175
184176 let availableBalanceB = (balanceB - stakedAmountB)
185177
186178 let accountBalanceWithStakedA = (accountBalance(assetIdA) + stakedAmountA)
187179
188180 let accountBalanceWithStakedB = (accountBalance(assetIdB) + stakedAmountB)
189181
190182 let hasEnoughBalance = if ((accountBalanceWithStakedA >= balanceA))
191183 then (accountBalanceWithStakedB >= balanceB)
192184 else false
193185
194-func skewness (x,y) = (((fraction(scale12, x, y) + fraction(scale12, y, x)) / 2) / 10000)
186+func skewness (x,y) = ((fraction(scale16, x, y) + fraction(scale16, y, x)) / 2)
195187
196188
197189 func invariantCalc (x,y) = {
198190 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)))
191+ (fraction((x + y), scale16, pow(sk, digits8, alpha, alphaDigits, digits8, CEILING)) + (2 * fraction(toInt(pow(fraction(toBigInt(x), toBigInt(y), toBigInt(scale8)), 0, toBigInt(5), 1, (digits8 / 2), DOWN)), pow((sk - beta), digits8, alpha, alphaDigits, digits8, DOWN), scale8)))
200192 }
201193
202194
203195 func calculateSendAmount (amountToSendEstimated,minTokenReceiveAmount,tokenReceiveAmount,tokenId) = {
204- let slippageValue = (scale8 - ((scale8 * 1) / 10000000))
196+ let worstAllowedNewInvariantRatio = (scale16 - ((scale16 * 1) / 10000000))
205197 let deltaBetweenMaxAndMinSendValue = (amountToSendEstimated - minTokenReceiveAmount)
206198 let x = (balanceA + tokenReceiveAmount)
207199 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))
200+ func getStepAmount (acc,step) = if ((acc._1 == -1))
215201 then {
216- let amountToSend = (amountToSendEstimated - ((step * deltaBetweenMaxAndMinSendValue) / 5))
202+ let amountToSend = (amountToSendEstimated - (((step * deltaBetweenMaxAndMinSendValue) / 3) / scale3))
217203 let stepInvariant = if ((tokenId == assetIdA))
218204 then invariantCalc(x, (balanceB - amountToSend))
219205 else invariantCalc((balanceA - amountToSend), y)
220206 if ((stepInvariant > invariant))
221- then amountToSend
222- else -1
207+ then $Tuple2(amountToSend, stepInvariant)
208+ else $Tuple2(-1, 0)
223209 }
224210 else acc
225211
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])
212+ let amountToSendMin = getStepAmount($Tuple2(-1, 0), 3000)
213+ if ((0 > amountToSendMin._1))
214+ then throw("Price is worse than minReceived")
215+ else {
216+ let invEstimated = if ((tokenId == assetIdA))
217+ then invariantCalc(x, (balanceB - amountToSendEstimated))
218+ else if ((tokenId == assetIdB))
219+ then invariantCalc((balanceA - amountToSendEstimated), y)
220+ else throw("Wrong asset in payment")
221+ if ((invariant > invEstimated))
222+ then if ((worstAllowedNewInvariantRatio >= fraction(scale16, invariant, invEstimated)))
223+ then throw("The requested price is too not profitable for user")
224+ else {
225+ let a = {
226+ let $l = [25, 200, 500]
227+ let $s = size($l)
228+ let $acc0 = $Tuple2(-1, 0)
229+ func $f0_1 ($a,$i) = if (($i >= $s))
230+ then $a
231+ else getStepAmount($a, $l[$i])
233232
234- func $f0_2 ($a,$i) = if (($i >= $s))
235- then $a
236- else throw("List size exceeds 5")
233+ func $f0_2 ($a,$i) = if (($i >= $s))
234+ then $a
235+ else throw("List size exceeds 3")
237236
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
237+ $f0_2($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3)
238+ }
239+ if ((0 > a._1))
240+ then amountToSendMin._1
241+ else a._1
242+ }
243+ else {
244+ let a = {
245+ let $l = [-500, -200, -25]
246+ let $s = size($l)
247+ let $acc0 = $Tuple2(-1, 0)
248+ func $f0_1 ($a,$i) = if (($i >= $s))
249+ then $a
250+ else getStepAmount($a, $l[$i])
251+
252+ func $f0_2 ($a,$i) = if (($i >= $s))
253+ then $a
254+ else throw("List size exceeds 3")
255+
256+ $f0_2($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3)
257+ }
258+ let tupleSendBetter = if ((0 > a._1))
259+ then $Tuple2(amountToSendEstimated, invEstimated)
260+ else a
261+ if ((worstAllowedNewInvariantRatio >= fraction(scale16, invariant, tupleSendBetter._2)))
262+ then throw("The requested price is too not profitable for user")
263+ else tupleSendBetter._1
264+ }
265+ }
247266 }
248267
249268
250269 func getAssetInfo (assetId) = match assetId {
251270 case id: ByteVector =>
252271 let stringId = toBase58String(id)
253272 let info = valueOrErrorMessage(assetInfo(id), (("Asset " + stringId) + " doesn't exist"))
254273 $Tuple3(stringId, info.name, info.decimals)
255274 case waves: Unit =>
256275 $Tuple3("WAVES", "WAVES", 8)
257276 case _ =>
258277 throw("Match error")
259278 }
260279
261280
262281 func suspend (cause) = [BooleanEntry(kActive, false), StringEntry(kCause, cause)]
263282
264283
265284 func throwIsActive () = throw("DApp is already active")
266285
267286
268-func throwIsInactive () = throw("DApp is inactive at this moment")
287+func isActive () = if (active)
288+ then unit
289+ else throw("DApp is inactive at this moment")
269290
270291
271-func throwOnlyAdmin () = throw("Only admin can call this function")
292+func isAdminCall (i) = if (containsElement([adminPubKey1, adminPubKey2, adminPubKey3], i.callerPublicKey))
293+ then unit
294+ else throw("Only admin can call this function")
272295
273296
274297 func throwAssets () = throw(((("Incorrect assets attached. Expected: " + strAssetIdA) + " and ") + strAssetIdB))
298+
299+
300+func throwOnePayment () = throw("One attached payment expected")
275301
276302
277303 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))
278304
279305
280306 func suspendSuspicious () = suspend(((((((((((((((("Suspicious state. Actual balances: " + toString(balanceA)) + " ") + assetNameA) + ", ") + toString(balanceB)) + " ") + assetNameB) + ". State: ") + toString(accountBalance(assetIdA))) + " ") + assetNameA) + ", ") + toString(accountBalance(assetIdB))) + " ") + assetNameB))
281307
282308
283309 func calcStakingFuncAndAddres (stake,assetId) = if (stake)
284- then if ((assetId == USDN))
285- then $Tuple2("lockNeutrino", stakingUSDNNSBTAddress)
286- else $Tuple2("startStaking", stakingEURNAddress)
287- else if ((assetId == USDN))
288- then $Tuple2("unlockNeutrino", stakingUSDNNSBTAddress)
289- else $Tuple2("stopStaking", stakingEURNAddress)
310+ then $Tuple2("lockNeutrino", stakingUSDNAddress)
311+ else $Tuple2("unlockNeutrino", stakingUSDNAddress)
290312
291313
292314 func calcStakingParams (stake,amount,assetId) = if (stake)
293315 then {
294- let $t087608826 = calcStakingFuncAndAddres(stake, assetId)
295- let call = $t087608826._1
296- let stakingAddr = $t087608826._2
316+ let $t091419207 = calcStakingFuncAndAddres(stake, assetId)
317+ let call = $t091419207._1
318+ let stakingAddr = $t091419207._2
297319 $Tuple4(call, stakingAddr, nil, [AttachedPayment(assetId, amount)])
298320 }
299321 else {
300- let $t089128978 = calcStakingFuncAndAddres(stake, assetId)
301- let call = $t089128978._1
302- let stakingAddr = $t089128978._2
322+ let $t092939359 = calcStakingFuncAndAddres(stake, assetId)
323+ let call = $t092939359._1
324+ let stakingAddr = $t092939359._2
303325 $Tuple4(call, stakingAddr, [amount, toBase58String(assetId)], nil)
304326 }
305327
306328
307329 @Callable(i)
308330 func init () = {
309- let $t090839160 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
310- let pmtAmountA = $t090839160._1
311- let pmtAssetIdA = $t090839160._2
312- let $t091659242 = $Tuple2(i.payments[1].amount, i.payments[1].assetId)
313- let pmtAmountB = $t091659242._1
314- let pmtAssetIdB = $t091659242._2
315- let $t092479324 = getAssetInfo(pmtAssetIdA)
316- let pmtStrAssetIdA = $t092479324._1
317- let pmtAssetNameA = $t092479324._2
318- let pmtDecimalsA = $t092479324._3
319- let $t093299406 = getAssetInfo(pmtAssetIdB)
320- let pmtStrAssetIdB = $t093299406._1
321- let pmtAssetNameB = $t093299406._2
322- let pmtDecimalsB = $t093299406._3
331+ let $t094649541 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
332+ let pmtAmountA = $t094649541._1
333+ let pmtAssetIdA = $t094649541._2
334+ let $t095469623 = $Tuple2(i.payments[1].amount, i.payments[1].assetId)
335+ let pmtAmountB = $t095469623._1
336+ let pmtAssetIdB = $t095469623._2
337+ let $t096289705 = getAssetInfo(pmtAssetIdA)
338+ let pmtStrAssetIdA = $t096289705._1
339+ let pmtAssetNameA = $t096289705._2
340+ let pmtDecimalsA = $t096289705._3
341+ let $t097109787 = getAssetInfo(pmtAssetIdB)
342+ let pmtStrAssetIdB = $t097109787._1
343+ let pmtAssetNameB = $t097109787._2
344+ let pmtDecimalsB = $t097109787._3
323345 if (isDefined(getBoolean(this, kActive)))
324346 then throwIsActive()
325347 else if ((pmtAssetIdA == pmtAssetIdB))
326348 then throw("Assets must be different")
327349 else {
328350 let shareName = ((("s" + take(pmtAssetNameA, 7)) + "_") + take(pmtAssetNameB, 7))
329351 let shareDescription = ((((("ShareToken of SwopFi protocol for " + pmtAssetNameA) + " and ") + pmtAssetNameB) + " at address ") + toString(this))
330352 let shareDecimals = ((pmtDecimalsA + pmtDecimalsB) / 2)
331353 let shareInitialSupply = fraction(pow(pmtAmountA, pmtDecimalsA, 5, 1, pmtDecimalsA, DOWN), pow(pmtAmountB, pmtDecimalsB, 5, 1, pmtDecimalsB, DOWN), pow(10, 0, shareDecimals, 0, 0, DOWN))
332354 let shareIssue = Issue(shareName, shareDescription, shareInitialSupply, shareDecimals, true)
333355 let shareIssueId = calculateAssetId(shareIssue)
334356 let invariantCalculated = invariantCalc(pmtAmountA, pmtAmountB)
335357 let stake1 = if (containsElement(stakingAssets, pmtStrAssetIdA))
336358 then invoke(this, "stakeUnstake", [true, pmtAmountA, pmtStrAssetIdA], nil)
337359 else 0
338360 if ((stake1 == stake1))
339361 then {
340362 let stake2 = if (containsElement(stakingAssets, pmtStrAssetIdB))
341363 then invoke(this, "stakeUnstake", [true, pmtAmountB, pmtStrAssetIdB], nil)
342364 else 0
343365 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)]
366+ then [StringEntry(kVersion, version), BooleanEntry(kActive, true), StringEntry(kAssetIdA, pmtStrAssetIdA), StringEntry(kAssetIdB, pmtStrAssetIdB), IntegerEntry(kBalanceA, pmtAmountA), IntegerEntry(kBalanceB, pmtAmountB), IntegerEntry(kInvariant, invariantCalculated), IntegerEntry(kFee, getIntegerValue(oracle, "base_fee_flat")), shareIssue, StringEntry(kShareAssetId, toBase58String(shareIssueId)), IntegerEntry(kShareAssetSupply, shareInitialSupply), ScriptTransfer(i.caller, shareInitialSupply, shareIssueId)]
345367 else throw("Strict value is not equal to itself.")
346368 }
347369 else throw("Strict value is not equal to itself.")
348370 }
349371 }
350372
351373
352374
353375 @Callable(i)
354-func replenishWithTwoTokens (slippageTolerance) = {
376+func replenishWithTwoTokens () = valueOrElse(isActive(), {
355377 let pmtAssetIdA = i.payments[0].assetId
356378 let pmtAssetIdB = i.payments[1].assetId
357- let pmtAmountA = i.payments[0].amount
358- let pmtAmountB = i.payments[1].amount
359- let $t01192211999 = getAssetInfo(pmtAssetIdA)
360- let pmtStrAssetIdA = $t01192211999._1
361- let pmtAssetNameA = $t01192211999._2
362- let pmtDecimalsA = $t01192211999._3
363- let $t01200412198 = getAssetInfo(pmtAssetIdB)
364- let pmtStrAssetIdB = $t01200412198._1
365- let pmtAssetNameB = $t01200412198._2
366- let pmtDecimalsB = $t01200412198._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))
379+ let ratioShareTokensInA = fraction(scale8, i.payments[0].amount, balanceA)
380+ let ratioShareTokensInB = fraction(scale8, i.payments[1].amount, balanceB)
381+ let $t01243512512 = getAssetInfo(pmtAssetIdA)
382+ let pmtStrAssetIdA = $t01243512512._1
383+ let pmtAssetNameA = $t01243512512._2
384+ let pmtDecimalsA = $t01243512512._3
385+ let $t01251712634 = getAssetInfo(pmtAssetIdB)
386+ let pmtStrAssetIdB = $t01251712634._1
387+ let pmtAssetNameB = $t01251712634._2
388+ let pmtDecimalsB = $t01251712634._3
389+ let $t01263913143 = if ((ratioShareTokensInB > ratioShareTokensInA))
390+ then {
391+ let pmt = fraction(balanceB, ratioShareTokensInA, scale8, CEILING)
392+ $Tuple5(i.payments[0].amount, pmt, (i.payments[1].amount - pmt), pmtAssetIdB, ratioShareTokensInA)
393+ }
394+ else {
395+ let pmt = fraction(balanceA, ratioShareTokensInB, scale8, CEILING)
396+ $Tuple5(pmt, i.payments[1].amount, (i.payments[0].amount - pmt), pmtAssetIdA, ratioShareTokensInB)
397+ }
398+ let pmtAmountA = $t01263913143._1
399+ let pmtAmountB = $t01263913143._2
400+ let change = $t01263913143._3
401+ let changeAssetId = $t01263913143._4
402+ let shareTokenRatio = $t01263913143._5
403+ let shareTokenToPayAmount = fraction(shareTokenRatio, shareAssetSupply, scale8)
404+ if ((size(i.payments) != 2))
405+ then throw("Two attached assets expected")
406+ else if (if ((pmtAssetIdA != assetIdA))
375407 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)
408+ else (pmtAssetIdB != assetIdB))
409+ then throwAssets()
410+ else if ((shareTokenToPayAmount == 0))
411+ then throw("Too small amount to replenish")
412+ else if ((0 > change))
413+ then throw("Change < 0")
414+ else if (!(hasEnoughBalance))
415+ then ([ScriptTransfer(i.caller, pmtAmountA, pmtAssetIdA), ScriptTransfer(i.caller, pmtAmountB, pmtAssetIdB)] ++ suspendSuspicious())
416+ else {
417+ let stake1 = if (containsElement(stakingAssets, pmtStrAssetIdA))
418+ then invoke(this, "stakeUnstake", [true, pmtAmountA, pmtStrAssetIdA], nil)
419+ else 0
420+ if ((stake1 == stake1))
421+ then {
422+ let stake2 = if (containsElement(stakingAssets, pmtStrAssetIdB))
423+ then invoke(this, "stakeUnstake", [true, pmtAmountB, pmtStrAssetIdB], nil)
395424 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- }
425+ if ((stake2 == stake2))
426+ then [IntegerEntry(kBalanceA, (balanceA + pmtAmountA)), IntegerEntry(kBalanceB, (balanceB + pmtAmountB)), IntegerEntry(kShareAssetSupply, (shareAssetSupply + shareTokenToPayAmount)), IntegerEntry(kInvariant, invariantCalc((balanceA + pmtAmountA), (balanceB + pmtAmountB))), Reissue(shareAssetId, shareTokenToPayAmount, true), ScriptTransfer(i.caller, shareTokenToPayAmount, shareAssetId), ScriptTransfer(i.caller, change, changeAssetId)]
405427 else throw("Strict value is not equal to itself.")
406428 }
407- }
429+ else throw("Strict value is not equal to itself.")
430+ }
431+ })
408432
409433
410434
411435 @Callable(i)
412-func replenishWithOneToken (virtualSwapTokenPay,virtualSwapTokenGet) = {
413- let $t01449714572 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
414- let pmtAmount = $t01449714572._1
415- let pmtAssetId = $t01449714572._2
416- let $t01457714650 = getAssetInfo(pmtAssetId)
417- let pmtStrAssetId = $t01457714650._1
418- let pmtAssetName = $t01457714650._2
419- let pmtDecimals = $t01457714650._3
436+func replenishWithOneToken (virtualSwapTokenPay,virtualSwapTokenGet) = valueOrElse(isActive(), {
437+ let $t01487614951 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
438+ let pmtAmount = $t01487614951._1
439+ let pmtAssetId = $t01487614951._2
440+ let $t01495615029 = getAssetInfo(pmtAssetId)
441+ let pmtStrAssetId = $t01495615029._1
442+ let pmtAssetName = $t01495615029._2
443+ let pmtDecimals = $t01495615029._3
420444 let pmtMinThreshold = 5000000
421445 let thresholdValueForMinTolerance = 50000000
422446 let tolerance = if ((thresholdValueForMinTolerance > pmtAmount))
423447 then 100000
424448 else 1
425449 let slippageValueMinForReplenish = (scale8 - ((scale8 * tolerance) / 10000000))
426450 let slippageValueMaxForReplenish = (scale8 + ((scale8 * tolerance) / 10000000))
427451 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"))
452+ if ((pmtMinThreshold > pmtAmount))
453+ then throw((((("Payment amount " + toString(pmtAmount)) + " does not exceed the minimum amount of ") + toString(pmtMinThreshold)) + " tokens"))
454+ else if ((size(i.payments) != 1))
455+ then throwOnePayment()
456+ else if (!(hasEnoughBalance))
457+ then ([ScriptTransfer(i.caller, pmtAmount, pmtAssetId)] ++ suspendSuspicious())
458+ else if (if ((pmtAssetId != assetIdA))
459+ then (pmtAssetId != assetIdB)
460+ else false)
461+ then throwAssets()
462+ else {
463+ let $t01600716649 = if ((pmtAssetId == assetIdA))
464+ then $Tuple6((pmtAmount - virtualSwapTokenPay), virtualSwapTokenGet, (balanceA + virtualSwapTokenPay), (balanceB - virtualSwapTokenGet), (balanceA + pmtAmount), balanceB)
465+ else $Tuple6(virtualSwapTokenGet, (pmtAmount - virtualSwapTokenPay), (balanceA - virtualSwapTokenGet), (balanceB + virtualSwapTokenPay), balanceA, (balanceB + pmtAmount))
466+ let virtualReplenishA = $t01600716649._1
467+ let virtualReplenishB = $t01600716649._2
468+ let balanceAfterSwapA = $t01600716649._3
469+ let balanceAfterSwapB = $t01600716649._4
470+ let newBalanceA = $t01600716649._5
471+ let newBalanceB = $t01600716649._6
472+ let invariantNew = invariantCalc(balanceAfterSwapA, balanceAfterSwapB)
473+ let ratioVirtualBalanceToVirtualReplenish = (fraction(scale16, balanceAfterSwapA, balanceAfterSwapB) / fraction(scale8, virtualReplenishA, virtualReplenishB))
474+ let dAppThresholdAmount = fraction((newBalanceA + newBalanceB), dAppThreshold, (2 * dAppThresholdScale2))
475+ if (if ((slippageValueMinForSwap >= fraction(scale8, invariant, invariantNew)))
476+ then true
477+ else (invariant > invariantNew))
478+ then throw("Incorrect virtualSwapTokenPay or virtualSwapTokenGet value")
479+ else if (if ((slippageValueMinForReplenish > ratioVirtualBalanceToVirtualReplenish))
480+ then true
481+ else (ratioVirtualBalanceToVirtualReplenish > slippageValueMaxForReplenish))
482+ then throw("Swap with virtualSwapTokenPay and virtualSwapTokenGet is possible, but ratio after virtual swap is incorrect")
483+ else if (if ((dAppThresholdAmount > newBalanceA))
484+ then true
485+ else (dAppThresholdAmount > newBalanceB))
486+ then throwThreshold(dAppThresholdAmount, newBalanceA, newBalanceB)
487+ else {
488+ let ratioShareTokensInA = fraction(virtualReplenishA, scale8, balanceAfterSwapA)
489+ let ratioShareTokensInB = fraction(virtualReplenishB, scale8, balanceAfterSwapB)
490+ let shareTokenToPayAmount = fraction(min([ratioShareTokensInA, ratioShareTokensInB]), shareAssetSupply, scale8)
491+ let shareTokenToPayAmountAfterFee = fraction(shareTokenToPayAmount, (feeScale6 - (fee / 2)), feeScale6)
492+ let shareTokenGovernanceReward = fraction(shareTokenToPayAmount, (feeGovernance / 2), feeScale6)
493+ let governanceRewardTokenA = fraction(shareTokenGovernanceReward, balanceA, shareAssetSupply)
494+ let governanceRewardTokenB = fraction(shareTokenGovernanceReward, balanceB, shareAssetSupply)
495+ let $t01863618931 = if ((pmtStrAssetId == strAssetIdA))
496+ then $Tuple3((pmtAmount - governanceRewardTokenA), governanceRewardTokenB, strAssetIdB)
497+ else $Tuple3((pmtAmount - governanceRewardTokenB), governanceRewardTokenA, strAssetIdA)
498+ let stakeAmount = $t01863618931._1
499+ let unstakeAmount = $t01863618931._2
500+ let unstakeAsset = $t01863618931._3
501+ let stake1 = if (containsElement(stakingAssets, pmtStrAssetId))
502+ then invoke(this, "stakeUnstake", [true, stakeAmount, pmtStrAssetId], nil)
503+ else 0
504+ if ((stake1 == stake1))
505+ then {
506+ let stake2 = if (containsElement(stakingAssets, unstakeAsset))
507+ then invoke(this, "stakeUnstake", [false, unstakeAmount, unstakeAsset], nil)
508+ else 0
509+ if ((stake2 == stake2))
510+ then [Reissue(shareAssetId, shareTokenToPayAmountAfterFee, true), ScriptTransfer(i.caller, shareTokenToPayAmountAfterFee, shareAssetId), ScriptTransfer(moneyBoxAddress, governanceRewardTokenA, assetIdA), ScriptTransfer(moneyBoxAddress, governanceRewardTokenB, assetIdB), IntegerEntry(kBalanceA, (newBalanceA - governanceRewardTokenA)), IntegerEntry(kBalanceB, (newBalanceB - governanceRewardTokenB)), IntegerEntry(kShareAssetSupply, (shareAssetSupply + shareTokenToPayAmountAfterFee)), IntegerEntry(kInvariant, invariantCalc((newBalanceA - governanceRewardTokenA), (newBalanceB - governanceRewardTokenB)))]
511+ else throw("Strict value is not equal to itself.")
512+ }
513+ else throw("Strict value is not equal to itself.")
514+ }
515+ }
516+ })
517+
518+
519+
520+@Callable(i)
521+func withdraw () = valueOrElse(isActive(), {
522+ let $t02021820293 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
523+ let pmtAmount = $t02021820293._1
524+ let pmtAssetId = $t02021820293._2
525+ let amountToPayA = fraction(pmtAmount, balanceA, shareAssetSupply)
526+ let amountToPayB = fraction(pmtAmount, balanceB, shareAssetSupply)
527+ let invariantCalculated = invariantCalc((balanceA - amountToPayA), (balanceB - amountToPayB))
528+ if ((size(i.payments) != 1))
529+ then throwOnePayment()
530+ else if ((pmtAssetId != shareAssetId))
531+ then throw(("Incorrect asset attached. Expected: " + toBase58String(shareAssetId)))
532+ else if (!(hasEnoughBalance))
533+ then ([ScriptTransfer(i.caller, pmtAmount, pmtAssetId)] ++ suspendSuspicious())
534+ else {
535+ let stake1 = if (containsElement(stakingAssets, strAssetIdA))
536+ then invoke(this, "stakeUnstake", [false, amountToPayA, strAssetIdA], nil)
537+ else 0
538+ if ((stake1 == stake1))
539+ then {
540+ let stake2 = if (containsElement(stakingAssets, strAssetIdB))
541+ then invoke(this, "stakeUnstake", [false, amountToPayB, strAssetIdB], nil)
542+ else 0
543+ if ((stake2 == stake2))
544+ 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)]
545+ else throw("Strict value is not equal to itself.")
546+ }
547+ else throw("Strict value is not equal to itself.")
548+ }
549+ })
550+
551+
552+
553+@Callable(i)
554+func exchange (estimatedAmountToReceive,minAmountToReceive) = valueOrElse(isActive(), {
555+ let $t02184421919 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
556+ let pmtAmount = $t02184421919._1
557+ let pmtAssetId = $t02184421919._2
558+ if ((0 >= estimatedAmountToReceive))
559+ then throw(("Estimated amount must be positive. Actual: " + toString(estimatedAmountToReceive)))
560+ else if ((minAmountToReceive > estimatedAmountToReceive))
561+ then throw("Minimal amount can't be greater than estimated.")
432562 else if ((size(i.payments) != 1))
433- then throw("One attached payment expected")
563+ then throwOnePayment()
434564 else if (!(hasEnoughBalance))
435565 then ([ScriptTransfer(i.caller, pmtAmount, pmtAssetId)] ++ suspendSuspicious())
436566 else if (if ((pmtAssetId != assetIdA))
437567 then (pmtAssetId != assetIdB)
438568 else false)
439569 then throwAssets()
440- else {
441- let $t01566216427 = 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 = $t01566216427._1
445- let virtualReplenishB = $t01566216427._2
446- let balanceAfterSwapA = $t01566216427._3
447- let balanceAfterSwapB = $t01566216427._4
448- let invariantCalculated = $t01566216427._5
449- let newBalanceA = $t01566216427._6
450- let newBalanceB = $t01566216427._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))
570+ else if ((10000000 > pmtAmount))
571+ then throw("Only swap of 10.000000 or more tokens is allowed")
572+ else if (if ((exchangeRatioLimitMin > fraction(scale8, minAmountToReceive, pmtAmount)))
459573 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))
574+ else (fraction(scale8, estimatedAmountToReceive, pmtAmount) > exchangeRatioLimitMax))
575+ then throw("Incorrect args and pmt ratio")
576+ else {
577+ let sendAssetId = if ((pmtAssetId == assetIdA))
578+ then assetIdB
579+ else assetIdA
580+ let amount = calculateSendAmount(estimatedAmountToReceive, minAmountToReceive, pmtAmount, pmtAssetId)
581+ let governanceReward = fraction(amount, feeGovernance, feeScale6)
582+ let amountMinusFee = fraction(amount, (feeScale6 - fee), feeScale6)
583+ let $t02322523487 = if ((pmtAssetId == assetIdA))
584+ then $Tuple2((balanceA + pmtAmount), ((balanceB - amountMinusFee) - governanceReward))
585+ else $Tuple2(((balanceA - amountMinusFee) - governanceReward), (balanceB + pmtAmount))
586+ let newBalanceA = $t02322523487._1
587+ let newBalanceB = $t02322523487._2
588+ let dAppThresholdAmount = fraction((newBalanceA + newBalanceB), dAppThreshold, (2 * dAppThresholdScale2))
589+ if (if ((dAppThresholdAmount > newBalanceA))
467590 then true
468591 else (dAppThresholdAmount > newBalanceB))
469592 then throwThreshold(dAppThresholdAmount, newBalanceA, newBalanceB)
470593 else {
594+ let $t02378623859 = getAssetInfo(pmtAssetId)
595+ let pmtStrAssetId = $t02378623859._1
596+ let pmtAssetName = $t02378623859._2
597+ let pmtDecimals = $t02378623859._3
598+ let $t02387223949 = getAssetInfo(sendAssetId)
599+ let sendStrAssetId = $t02387223949._1
600+ let sendAssetName = $t02387223949._2
601+ let sendDecimals = $t02387223949._3
471602 let stake1 = if (containsElement(stakingAssets, pmtStrAssetId))
472603 then invoke(this, "stakeUnstake", [true, pmtAmount, pmtStrAssetId], nil)
473604 else 0
474605 if ((stake1 == stake1))
475606 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)]
607+ let stake2 = if (containsElement(stakingAssets, sendStrAssetId))
608+ then invoke(this, "stakeUnstake", [false, (amountMinusFee + governanceReward), sendStrAssetId], nil)
609+ else 0
610+ if ((stake2 == stake2))
611+ then $Tuple2([IntegerEntry(kBalanceA, newBalanceA), IntegerEntry(kBalanceB, newBalanceB), IntegerEntry(kInvariant, invariantCalc(newBalanceA, newBalanceB)), ScriptTransfer(i.caller, amountMinusFee, sendAssetId), ScriptTransfer(moneyBoxAddress, governanceReward, sendAssetId)], $Tuple2(amountMinusFee, sendAssetId))
612+ else throw("Strict value is not equal to itself.")
480613 }
481614 else throw("Strict value is not equal to itself.")
482615 }
483- }
484- }
616+ }
617+ })
485618
486619
487620
488621 @Callable(i)
489-func withdraw () = {
490- let $t01865318796 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
491- let pmtAmount = $t01865318796._1
492- let pmtAssetId = $t01865318796._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)
512- else 0
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)]
515- else throw("Strict value is not equal to itself.")
516- }
517- else throw("Strict value is not equal to itself.")
518- }
519- }
622+func shutdown () = valueOrElse(isAdminCall(i), if (!(active))
623+ then throw(("DApp is already suspended. Cause: " + valueOrElse(getString(this, kCause), "the cause wasn't specified")))
624+ else suspend("Paused by admin"))
520625
521626
522627
523628 @Callable(i)
524-func exchange (estimatedAmountToReceive,minAmountToReceive) = {
525- let $t02031020385 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
526- let pmtAmount = $t02031020385._1
527- let pmtAssetId = $t02031020385._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 $t02180722069 = if ((pmtAssetId == assetIdA))
556- then $Tuple2((balanceA + pmtAmount), ((balanceB - amountMinusFee) - governanceReward))
557- else $Tuple2(((balanceA - amountMinusFee) - governanceReward), (balanceB + pmtAmount))
558- let newBalanceA = $t02180722069._1
559- let newBalanceB = $t02180722069._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 $t02236722440 = getAssetInfo(pmtAssetId)
567- let pmtStrAssetId = $t02236722440._1
568- let pmtAssetName = $t02236722440._2
569- let pmtDecimals = $t02236722440._3
570- let $t02245322530 = getAssetInfo(sendAssetId)
571- let sendStrAssetId = $t02245322530._1
572- let sendAssetName = $t02245322530._2
573- let sendDecimals = $t02245322530._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- }
629+func activate () = valueOrElse(isAdminCall(i), if (active)
630+ then throwIsActive()
631+ else [BooleanEntry(kActive, true), DeleteEntry(kCause)])
590632
591633
592634
593635 @Callable(i)
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()
598- else suspend("Paused by admin")
599-
600-
601-
602-@Callable(i)
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)]
608-
609-
610-
611-@Callable(i)
612-func takeIntoAccountExtraFunds () = {
636+func takeIntoAccountExtraFunds () = valueOrElse(isActive(), {
613637 let amountEnrollA = (accountBalanceWithStakedA - balanceA)
614638 let amountEnrollB = (accountBalanceWithStakedB - balanceB)
615639 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- }
640+ if ((i.caller != moneyBoxAddress))
641+ then throw("Only the money box can call this function")
642+ else if (if ((0 > amountEnrollA))
643+ then true
644+ else (0 > amountEnrollB))
645+ then suspend("Enroll amount negative")
646+ else if (if ((amountEnrollA == 0))
647+ then (amountEnrollB == 0)
648+ else false)
649+ then throw("No money to take")
650+ else {
651+ let stake1 = if (if (containsElement(stakingAssets, strAssetIdA))
652+ then (amountEnrollA > 0)
653+ else false)
654+ then invoke(this, "stakeUnstake", [true, amountEnrollA, strAssetIdA], nil)
655+ else 0
656+ if ((stake1 == stake1))
657+ then {
658+ let stake2 = if (if (containsElement(stakingAssets, strAssetIdB))
659+ then (amountEnrollB > 0)
660+ else false)
661+ then invoke(this, "stakeUnstake", [true, amountEnrollB, strAssetIdB], nil)
662+ else 0
663+ if ((stake2 == stake2))
664+ then [IntegerEntry(kInvariant, invariantNew), IntegerEntry(kBalanceA, (balanceA + amountEnrollA)), IntegerEntry(kBalanceB, (balanceB + amountEnrollB))]
665+ else throw("Strict value is not equal to itself.")
666+ }
667+ else throw("Strict value is not equal to itself.")
668+ }
669+ })
648670
649671
650672
651673 @Callable(i)
652674 func stakeUnstake (stake,amount,assetIdString) = if ((i.caller != this))
653675 then throw("Only contract itself can invoke this function")
654676 else {
655- let $t02559225695 = calcStakingParams(stake, amount, fromBase58String(assetIdString))
656- let call = $t02559225695._1
657- let addr = $t02559225695._2
658- let params = $t02559225695._3
659- let payments = $t02559225695._4
677+ let $t02695327056 = calcStakingParams(stake, amount, fromBase58String(assetIdString))
678+ let call = $t02695327056._1
679+ let addr = $t02695327056._2
680+ let params = $t02695327056._3
681+ let payments = $t02695327056._4
660682 let inv = invoke(addr, call, params, payments)
661683 if ((inv == inv))
662684 then nil
663685 else throw("Strict value is not equal to itself.")
664686 }
665687
666688
667689
668690 @Callable(i)
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- }
691+func toBigIntInvariant () = valueOrElse(isAdminCall(i), [IntegerEntry(kInvariant, invariantCalc(balanceA, balanceB))])
698692
699693
700694 @Verifier(tx)
701695 func verify () = {
702696 let multiSignedByAdmins = {
703697 let adminPubKey1Signed = if (sigVerify(tx.bodyBytes, tx.proofs[0], adminPubKey1))
704698 then 1
705699 else 0
706700 let adminPubKey2Signed = if (sigVerify(tx.bodyBytes, tx.proofs[1], adminPubKey2))
707701 then 1
708702 else 0
709703 let adminPubKey3Signed = if (sigVerify(tx.bodyBytes, tx.proofs[2], adminPubKey3))
710704 then 1
711705 else 0
712706 (((adminPubKey1Signed + adminPubKey2Signed) + adminPubKey3Signed) >= 2)
713707 }
714708 match tx {
715709 case inv: InvokeScriptTransaction =>
716710 let callTakeIntoAccount = if ((inv.dApp == this))
717711 then (inv.function == "takeIntoAccountExtraFunds")
718712 else false
719713 let signedByAdmin = if (if (if (sigVerify(tx.bodyBytes, tx.proofs[0], adminPubKey1))
720714 then true
721715 else sigVerify(tx.bodyBytes, tx.proofs[0], adminPubKey2))
722716 then true
723717 else sigVerify(tx.bodyBytes, tx.proofs[0], adminPubKey3))
724718 then true
725- else sigVerify(tx.bodyBytes, tx.proofs[0], admStaking)
719+ else sigVerify(tx.bodyBytes, tx.proofs[0], adminPubKeyInvoke)
726720 if (if (callTakeIntoAccount)
727721 then signedByAdmin
728722 else false)
729723 then true
730724 else multiSignedByAdmins
731725 case _ =>
732726 multiSignedByAdmins
733727 }
734728 }
735729

github/deemru/w8io/6500d08 
120.30 ms