tx · FHp4ii2MBEdqZKs3nHvqXqcf1FdTccznikAJVn4ou8MK

3MyX5VcQdUXp3EAvHDNuHSR8mkrBATrmDz4:  -0.01000000 Waves

2021.09.12 17:53 [1699977] smart account 3MyX5VcQdUXp3EAvHDNuHSR8mkrBATrmDz4 > SELF 0.00000000 Waves

{ "type": 13, "id": "FHp4ii2MBEdqZKs3nHvqXqcf1FdTccznikAJVn4ou8MK", "fee": 1000000, "feeAssetId": null, "timestamp": 1631458440482, "version": 2, "chainId": 84, "sender": "3MyX5VcQdUXp3EAvHDNuHSR8mkrBATrmDz4", "senderPublicKey": "85S1dkzzB2SAy54zYp3GwZasDQE4wWWSWu9yCxs9dGsJ", "proofs": [ "S5gc9KC5urwjNX3tjyVR7M29tpsZakN2V3jE6bmPk9wFUpbUzQSU9TNs3E7kG6LZts28hpnfKEjq9ZNA7zPh1QE" ], "script": "base64:AAIFAAAAAAAAACAIAhIAEgMKAQESBAoCAQESABIECgIBARIAEgASAwoBAQAAAEwAAAAAB3ZlcnNpb24CAAAABTIuMC4wAAAAAAhrVmVyc2lvbgIAAAAHdmVyc2lvbgAAAAAHa0FjdGl2ZQIAAAAGYWN0aXZlAAAAAAlrQXNzZXRJZEECAAAACkFfYXNzZXRfaWQAAAAACWtBc3NldElkQgIAAAAKQl9hc3NldF9pZAAAAAAJa0JhbGFuY2VBAgAAAA9BX2Fzc2V0X2JhbGFuY2UAAAAACWtCYWxhbmNlQgIAAAAPQl9hc3NldF9iYWxhbmNlAAAAAA1rU2hhcmVBc3NldElkAgAAAA5zaGFyZV9hc3NldF9pZAAAAAARa1NoYXJlQXNzZXRTdXBwbHkCAAAAEnNoYXJlX2Fzc2V0X3N1cHBseQAAAAAEa0ZlZQIAAAAKY29tbWlzc2lvbgAAAAASa0ZlZVNjYWxlRGVsaW1pdGVyAgAAABpjb21taXNzaW9uX3NjYWxlX2RlbGltaXRlcgAAAAAKa0ludmFyaWFudAIAAAAJaW52YXJpYW50AAAAAAZrQ2F1c2UCAAAADnNodXRkb3duX2NhdXNlAAAAAA9rZXlBZG1pblB1YktleTECAAAAC2FkbWluX3B1Yl8xAAAAAA9rZXlBZG1pblB1YktleTICAAAAC2FkbWluX3B1Yl8yAAAAAA9rZXlBZG1pblB1YktleTMCAAAAC2FkbWluX3B1Yl8zAAAAABRVU0ROVG9XYXZlc0V4Y2hhbmdlcgkBAAAAB0FkZHJlc3MAAAABAQAAABoBV6ugnY67/HaJPzVO8b2xSyoDl1hFH8eK8wAAAAAGb3JhY2xlCQEAAAAHQWRkcmVzcwAAAAEBAAAAGgFXiv8IaJo1ukDNYXTyEjfepjfw+jjO6B44AQAAAAtnZXRBZG1pblB1YgAAAAEAAAALa2V5QWRtaW5QdWIEAAAAByRtYXRjaDAJAAQdAAAAAgUAAAAGb3JhY2xlBQAAAAtrZXlBZG1pblB1YgMJAAABAAAAAgUAAAAHJG1hdGNoMAIAAAAGU3RyaW5nBAAAAAZzdHJpbmcFAAAAByRtYXRjaDAJAAJZAAAAAQUAAAAGc3RyaW5nBAAAAAdub3RoaW5nBQAAAAckbWF0Y2gwCQAAAgAAAAECAAAAGUFkbWlu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AAIFAAAABERPV04JAABsAAAABgkAAGUAAAACBQAAAAJzawUAAAAEYmV0YQUAAAAHZGlnaXRzOAUAAAAFYWxwaGEFAAAAC2FscGhhRGlnaXRzBQAAAAdkaWdpdHM4BQAAAARET1dOBQAAAAZzY2FsZTgBAAAAE2NhbGN1bGF0ZVNlbmRBbW91bnQAAAAEAAAAFWFtb3VudFRvU2VuZEVzdGltYXRlZAAAABVtaW5Ub2tlblJlY2VpdmVBbW91bnQAAAASdG9rZW5SZWNlaXZlQW1vdW50AAAAB3Rva2VuSWQEAAAADXNsaXBwYWdlVmFsdWUJAABlAAAAAgUAAAAGc2NhbGU4CQAAaQAAAAIJAABoAAAAAgUAAAAGc2NhbGU4AAAAAAAAAAABAAAAAAAAmJaABAAAAB5kZWx0YUJldHdlZW5NYXhBbmRNaW5TZW5kVmFsdWUJAABlAAAAAgUAAAAVYW1vdW50VG9TZW5kRXN0aW1hdGVkBQAAABVtaW5Ub2tlblJlY2VpdmVBbW91bnQEAAAAAXgJAABkAAAAAgUAAAAIYmFsYW5jZUEFAAAAEnRva2VuUmVjZWl2ZUFtb3VudAQAAAABeQkAAGQAAAACBQAAAAhiYWxhbmNlQgUAAAASdG9rZW5SZWNlaXZlQW1vdW50BAAAAAxpbnZhcmlhbnROZXcDCQAAAAAAAAIFAAAAB3Rva2VuSWQFAAAACGFzc2V0SWRBCQEAAAANaW52YXJpYW50Q2FsYwAAAAIFAAAAAXgJAABlAAAAAgUAAAAIYmFsYW5jZUIFAAAAFWFtb3VudFRvU2VuZEVzdGltYXRlZAMJAAAAAAAAAgUAAAAHdG9rZW5JZAUAAAAIYXNzZXRJZEIJAQAAAA1pbnZhcmlhbnRDYWxjAAAAAgkAAGUAAAACBQAAAAhiYWxhbmNlQQUAAAAVYW1vdW50VG9TZW5kRXN0aW1hdGVkBQAAAAF5CQAAAgAAAAECAAAAFldyb25nIGFzc2V0IGluIHBheW1lbnQEAAAAF2ludmFyaWFudEVzdGltYXRlZFJhdGlvCQAAawAAAAMFAAAABnNjYWxlOAUAAAAJaW52YXJpYW50BQAAAAxpbnZhcmlhbnROZXcKAQAAAA1nZXRTdGVwQW1vdW50AAAAAgAAAANhY2MAAAAEc3RlcAMJAAAAAAAAAgUAAAADYWNjAP//////////BAAAAAxhbW91bnRUb1NlbmQJAABlAAAAAgUAAAAVYW1vdW50VG9TZW5kRXN0aW1hdGVkCQAAaQAAAAIJAABoAAAAAgUAAAAEc3RlcAUAAAAeZGVsdGFCZXR3ZWVuTWF4QW5kTWluU2VuZFZhbHVlAAAAAAAAAAAFBAAAAA1zdGVwSW52YXJpYW50AwkAAAAAAAACBQAAAAd0b2tlbklkBQAAAAhhc3NldElkQQkBAAAADWludmFyaWFudENhbGMAAAACBQAAAAF4CQAAZQAAAAIFAAAACGJhbGFuY2VCBQAAAAxhbW91bnRUb1NlbmQJAQAAAA1pbnZhcmlhbnRDYWxjAAAAAgkAAGUAAAACBQAAAAhiYWxhbmNlQQUAAAAMYW1vdW50VG9TZW5kBQAAAAF5AwkAAGYAAAACBQAAAA1zdGVwSW52YXJpYW50BQAAAAlpbnZhcmlhbnQFAAAADGFtb3VudFRvU2VuZAD//////////wUAAAADYWNjBAAAAApzdGVwQW1vdW50BAAAAA0kbGlzdDYwNDk2MDkyCQAETAAAAAIAAAAAAAAAAAEJAARMAAAAAgAAAAAAAAAAAgkABEwAAAACAAAAAAAAAAADCQAETAAAAAIAAAAAAAAAAAQJAARMAAAAAgAAAAAAAAAABQUAAAADbmlsBAAAAA0kc2l6ZTYwNDk2MDkyCQABkAAAAAEFAAAADSRsaXN0NjA0OTYwOTIEAAAADSRhY2MwNjA0OTYwOTIA//////////8DCQAAAAAAAAIFAAAADSRzaXplNjA0OTYwOTIAAAAAAAAAAAAFAAAADSRhY2MwNjA0OTYwOTIEAAAADSRhY2MxNjA0OTYwOTIJAQAAAA1nZXRTdGVwQW1vdW50AAAAAgUAAAANJGFjYzA2MDQ5NjA5MgkAAZEAAAACBQAAAA0kbGlzdDYwNDk2MDkyAAAAAAAAAAAAAwkAAAAAAAACBQAAAA0kc2l6ZTYwNDk2MDkyAAAAAAAAAAABBQAAAA0kYWNjMTYwNDk2MDkyBAAAAA0kYWNjMjYwNDk2MDkyCQEAAAANZ2V0U3RlcEFtb3VudAAAAAIFAAAADSRhY2MxNjA0OTYwOTIJAAGRAAAAAgUAAAANJGxpc3Q2MDQ5NjA5MgAAAAAAAAAAAQMJAAAAAAAAAgUAAAANJHNpemU2MDQ5NjA5MgAAAAAAAAAAAgUAAAANJGFjYzI2MDQ5NjA5MgQAAAANJGFjYzM2MDQ5NjA5MgkBAAAADWdldFN0ZXBBbW91bnQAAAACBQAAAA0kYWNjMjYwNDk2MDkyCQABkQAAAAIFAAAADSRsaXN0NjA0OTYwOTIAAAAAAAAAAAIDCQAAAAAAAAIFAAAADSRzaXplNjA0OTYwOTIAAAAAAAAAAAMFAAAADSRhY2MzNjA0OTYwOTIEAAAADSRhY2M0NjA0OTYwOTIJAQAAAA1nZXRTdGVwQW1vdW50AAAAAgUAAAANJGFjYzM2MDQ5NjA5MgkAAZEAAAACBQAAAA0kbGlzdDYwNDk2MDkyAAAAAAAAAAADAwkAAAAAAAACBQAAAA0kc2l6ZTYwNDk2MDkyAAAAAAAAAAAEBQAAAA0kYWNjNDYwNDk2MDkyBAAAAA0kYWNjNTYwNDk2MDkyCQEAAAANZ2V0U3RlcEFtb3VudAAAAAIFAAAADSRhY2M0NjA0OTYwOTIJAAGRAAAAAgUAAAANJGxpc3Q2MDQ5NjA5MgAAAAAAAAAABAMJAAAAAAAAAgUAAAANJHNpemU2MDQ5NjA5MgAAAAAAAAAABQUAAAANJGFjYzU2MDQ5NjA5MgQAAAANJGFjYzY2MDQ5NjA5MgkBAAAADWdldFN0ZXBBbW91bnQAAAACBQAAAA0kYWNjNTYwNDk2MDkyCQABkQAAAAIFAAAADSRsaXN0NjA0OTYwOTIAAAAAAAAAAAUJAAACAAAAAQIAAAASTGlzdCBzaXplIGV4Y2VlZCA1AwkAAGYAAAACAAAAAAAAAAAABQAAAApzdGVwQW1vdW50CQAAAgAAAAECAAAANHNvbWV0aGluZyB3ZW50IHdyb25nIHdoaWxlIHdvcmtpbmcgd2l0aCBhbW91bnRUb1NlbmQDAwkAAGYAAAACBQAAABdpbnZhcmlhbnRFc3RpbWF0ZWRSYXRpbwUAAAANc2xpcHBhZ2VWYWx1ZQkAAGYAAAACBQAAAAxpbnZhcmlhbnROZXcFAAAACWludmFyaWFudAcFAAAAFWFtb3VudFRvU2VuZEVzdGltYXRlZAUAAAAKc3RlcEFtb3VudAEAAAAMZ2V0QXNzZXRJbmZvAAAAAQAAAAdhc3NldElkBAAAAAckbWF0Y2gwBQAAAAdhc3Nl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YWxzBgQAAAAMc2hhcmVJc3N1ZUlkCQAEOAAAAAEFAAAACnNoYXJlSXNzdWUEAAAAE2ludmFyaWFudENhbGN1bGF0ZWQJAQAAAA1pbnZhcmlhbnRDYWxjAAAAAgUAAAAKcG10QW1vdW50QQUAAAAKcG10QW1vdW50QgkABEwAAAACCQEAAAALU3RyaW5nRW50cnkAAAACBQAAAAhrVmVyc2lvbgUAAAAHdmVyc2lvbgkABEwAAAACCQEAAAAMQm9vbGVhbkVudHJ5AAAAAgUAAAAHa0FjdGl2ZQYJAARMAAAAAgkBAAAAC1N0cmluZ0VudHJ5AAAAAgUAAAAJa0Fzc2V0SWRBBQAAAA5wbXRTdHJBc3NldElkQQkABEwAAAACCQEAAAALU3RyaW5nRW50cnkAAAACBQAAAAlrQXNzZXRJZEIFAAAADnBtdFN0ckFzc2V0SWRCCQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACBQAAAAlrQmFsYW5jZUEFAAAACnBtdEFtb3VudEEJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAIFAAAACWtCYWxhbmNlQgUAAAAKcG10QW1vdW50QgkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgUAAAAKa0ludmFyaWFudAUAAAATaW52YXJpYW50Q2FsY3VsYXRlZAkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgUAAAAEa0ZlZQUAAAADZmVlCQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACBQAAABJrRmVlU2NhbGVEZWxpbWl0ZXIFAAAACWZlZVNjYWxlNgkABEwAAAACBQAAAApzaGFyZUlzc3VlCQAETAAAAAIJAQAAAAtTdHJpbmdFbnRyeQAAAAIFAAAADWtTaGFyZUFzc2V0SWQJAAJYAAAAAQUAAAAMc2hhcmVJc3N1ZUlkCQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACBQAAABFrU2hhcmVBc3NldFN1cHBseQUAAAASc2hhcmVJbml0aWFsU3VwcGx5CQAETAAAAAIJAQAAAA5TY3JpcHRUcmFuc2ZlcgAAAAMIBQAAAAFpAAAABmNhbGxlcgUAAAASc2hhcmVJbml0aWFsU3VwcGx5BQAAAAxzaGFyZUlzc3VlSWQFAAAAA25pbAAAAAFpAQAAABZyZXBsZW5pc2hXaXRoVHdvVG9rZW5zAAAAAQAAABFzbGlwcGFnZVRvbGVyYW5jZQQAAAALcG10QXNzZXRJZEEICQABkQAAAAIIBQAAAAFpAAAACHBheW1lbnRzAAAAAAAAAAAAAAAAB2Fzc2V0SWQEAAAAC3BtdEFzc2V0SWRCCAkAAZEAAAACCAUAAAABaQAAAAhwYXltZW50cwAAAAAAAAAAAQAAAAdhc3NldElkBAAAAApwbXRBbW91bnRBCQEAAAAQZGVkdWN0U3Rha2luZ0ZlZQAAAAIICQABkQAAAAIIBQAAAAFpAAAACHBheW1lbnRzAAAAAAAAAAAAAAAABmFtb3VudAUAAAALcG10QXNzZXRJZEEEAAAACnBtdEFtb3VudEIJAQAAABBkZWR1Y3RTdGFraW5nRmVlAAAAAggJAAGRAAAAAggFAAAAAWkAAAAIcGF5bWVudHMAAAAAAAAAAAEAAAAGYW1vdW50BQAAAAtwbXRBc3NldElkQgQAAAAKdG9rZW5SYXRpbwkAAGsAAAADCQAAawAAAAMFAAAABnNjYWxlOAUAAAAIYmFsYW5jZUEFAAAACnBtdEFtb3VudEEFAAAABnNjYWxlMwkAAGsAAAADBQAAAAZzY2FsZTgFAAAACGJhbGFuY2VCBQAAAApwbXRBbW91bnRCBAAAABNyYXRpb1NoYXJlVG9rZW5zSW5BCQAAawAAAAMFAAAABnNjYWxlOAUAAAAKcG10QW1vdW50QQUAAAAIYmFsYW5jZUEEAAAAE3JhdGlvU2hhcmVUb2tlbnNJbkIJAABrAAAAAwUAAAAGc2NhbGU4BQAAAApwbXRBbW91bnRCBQAAAAhiYWxhbmNlQgQAAAAVc2hhcmVUb2tlblRvUGF5QW1vdW50CQAAawAAAAMJAAGXAAAAAQkABEwAAAACBQAAABNyYXRpb1NoYXJlVG9rZW5zSW5BCQAETAAAAAIFAAAAE3JhdGlvU2hhcmVUb2tlbnNJbkIFAAAAA25pbAUAAAAQc2hhcmVBc3NldFN1cHBseQUAAAAGc2NhbGU4BAAAABNpbnZhcmlhbnRDYWxjdWxhdGVkCQEAAAANaW52YXJpYW50Q2FsYwAAAAIJAABkAAAAAgUAAAAIYmFsYW5jZUEFAAAACnBtdEFtb3VudEEJAABkAAAAAgUAAAAIYmFsYW5jZUIFAAAACnBtdEFtb3VudEIDCQEAAAABIQAAAAEFAAAACGlzQWN0aXZlCQEAAAAPdGhyb3dJc0luYWN0aXZlAAAAAAMDCQAAZgAAAAIAAAAAAAAAAAAFAAAAEXNsaXBwYWdlVG9sZXJhbmNlBgkAAGYAAAACBQAAABFzbGlwcGFnZVRvbGVyYW5jZQAAAAAAAAAACgkAAAIAAAABAgAAACBTbGlwcGFnZSB0b2xlcmFuY2UgbXVzdCBiZSA8PSAxJQMJAQAAAAIhPQAAAAIJAAGQAAAAAQgFAAAAAWkAAAAIcGF5bWVudHMAAAAAAAAAAAIJAAACAAAAAQIAAAAcVHdvIGF0dGFjaGVkIGFzc2V0cyBleHBlY3RlZAMDCQEAAAACIT0AAAACBQAAAAtwbXRBc3NldElkQQUAAAAIYXNzZXRJZEEGCQEAAAACIT0AAAACBQAAAAtwbXRBc3NldElkQgUAAAAIYXNzZXRJZEIJAQAAAAt0aHJvd0Fzc2V0cwAAAAADAwkAAGYAAAACCQAAaQAAAAIJAABoAAAAAgUAAAAGc2NhbGUzCQAAZQAAAAIFAAAADnNsaXBwYWdlU2NhbGUzBQAAABFzbGlwcGFnZVRvbGVyYW5jZQUAAAAOc2xpcHBhZ2VTY2FsZTMFAAAACnRva2VuUmF0aW8GCQAAZgAAAAIFAAAACnRva2VuUmF0aW8JAABpAAAAAgkAAGgAAAACBQAAAAZzY2FsZTMJAABkAAAAAgUAAAAOc2xpcHBhZ2VTY2FsZTMFAAAAEXNsaXBwYWdlVG9sZXJhbmNlBQAAAA5zbGlwcGFnZVNjYWxlMwkAAAIAAAABAgAAAD1JbmNvcnJlY3QgYXNzZXRzIGFtb3VudDogYW1vdW50cyBtdXN0IGhhdmUgdGhlIGNvbnRyYWN0IHJhdGlvAwkAAAAAAAACBQAAABVzaGFyZVRva2VuVG9QYXlBbW91bnQAAAAAAAAAAAAJAAACAAAAAQIAAAAdVG9vIHNtYWxsIGFtb3VudCB0byByZXBsZW5pc2gDCQEAAAABIQAAAAEFAAAAEGhhc0Vub3VnaEJhbGFuY2UJAAROAAAAAgkABEwAAAACCQEAAAAOU2NyaXB0VHJhbnNmZXIAAAADCAUAAAABaQAAAAZjYWxsZXIFAAAACnBtdEFtb3VudEEFAAAAC3BtdEFzc2V0SWRBCQAETAAAAAIJAQAAAA5TY3JpcHRUcmFuc2ZlcgAAAAMIBQAAAAFpAAAABmNhbGxlcgUAAAAKcG10QW1vdW50QgUAAAALcG10QXNzZXRJZEIFAAAAA25pbAkBAAAAEXN1c3BlbmRTdXNwaWNpb3VzAAAAAAkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgUAAAAJa0JhbGFuY2VBCQAAZAAAAAIFAAAACGJhbGFuY2VBBQAAAApwbXRBbW91bnRBCQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACBQAAAAlrQmFsYW5jZUIJAABkAAAAAgUAAAAIYmFsYW5jZUIFAAAACnBtdEFtb3VudEIJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAIFAAAAEWtTaGFyZUFzc2V0U3VwcGx5CQAAZAAAAAIFAAAAEHNoYXJlQXNzZXRTdXBwbHkFAAAAFXNoYXJlVG9rZW5Ub1BheUFtb3VudAkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgUAAAAKa0ludmFyaWFudAUAAAATaW52YXJpYW50Q2FsY3VsYXRlZAkABEwAAAACCQEAAAAHUmVpc3N1ZQAAAAMFAAAADHNoYXJlQXNzZXRJZAUAAAAVc2hhcmVUb2tlblRvUGF5QW1vdW50BgkABEwAAAACCQEAAAAOU2NyaXB0VHJhbnNmZXIAAAADCAUAAAABaQAAAAZjYWxsZXIFAAAAFXNoYXJlVG9rZW5Ub1BheUFtb3VudAUAAAAMc2hhcmVBc3NldElkBQAAAANuaWwAAAABaQEAAAAVcmVwbGVuaXNoV2l0aE9uZVRva2VuAAAAAgAAABN2aXJ0dWFsU3dhcFRva2VuUGF5AAAAE3ZpcnR1YWxTd2FwVG9rZW5HZXQEAAAADSR0MDEzNDM0MTM1MDkJAAUUAAAAAggJAAGRAAAAAggFAAAAAWkAAAAIcGF5bWVudHMAAAAAAAAAAAAAAAAGYW1vdW50CAkAAZEAAAACCAUAAAABaQAAAAhwYXltZW50cwAAAAAAAAAAAAAAAAdhc3NldElkBAAAAAlwbXRBbW91bnQIBQAAAA0kdDAxMzQzNDEzNTA5AAAAAl8xBAAAAApwbXRBc3NldElkCAUAAAANJHQwMTM0MzQxMzUwOQAAAAJfMgQAAAAPcG10TWluVGhyZXNob2xkAAAAAAAATEtABAAAAB10aHJlc2hvbGRWYWx1ZUZvck1pblRvbGVyYW5jZQAAAAAAAvrwgAQAAAAJdG9sZXJhbmNlAwkAAGYAAAACBQAAAB10aHJlc2hvbGRWYWx1ZUZvck1pblRvbGVyYW5jZQUAAAAJcG10QW1vdW50AAAAAAAAAYagAAAAAAAAAAABBAAAABxzbGlwcGFnZVZhbHVlTWluRm9yUmVwbGVuaXNoCQAAZQAAAAIFAAAABnNjYWxlOAkAAGkAAAACCQAAaAAAAAIFAAAABnNjYWxlOAUAAAAJdG9sZXJhbmNlAAAAAAAAmJaABAAAABxzbGlwcGFnZVZhbHVlTWF4Rm9yUmVwbGVuaXNoCQAAZAAAAAIFAAAABnNjYWxlOAkAAGkAAAACCQAAaAAAAAIFAAAABnNjYWxlOAUAAAAJdG9sZXJhbmNlAAAAAAAAmJaABAAAABdzbGlwcGFnZVZhbHVlTWluRm9yU3dhcAkAAGUAAAACBQAAAAZzY2FsZTgJAABpAAAAAgkAAGgAAAACBQAAAAZzY2FsZTgAAAAAAAAAAAEAAAAAAACYloADCQEAAAABIQAAAAEFAAAACGlzQWN0aXZlCQEAAAAPdGhyb3dJc0luYWN0aXZlAAAAAAMJAABmAAAAAgUAAAAPcG10TWluVGhyZXNob2xkBQAAAAlwbXRBbW91bnQJAAACAAAAAQkAASwAAAACCQABLAAAAAIJAAEsAAAAAgkAASwAAAACAgAAAA9QYXltZW50IGFtb3VudCAJAAGkAAAAAQUAAAAJcG10QW1vdW50AgAAACcgZG9lcyBub3QgZXhjZWVkIHRoZSBtaW5pbXVtIGFtb3VudCBvZiAJAAGkAAAAAQUAAAAPcG10TWluVGhyZXNob2xkAgAAAAcgdG9rZW5zAwkBAAAAAiE9AAAAAgkAAZAAAAABCAUAAAABaQAAAAhwYXltZW50cwAAAAAAAAAAAQkAAAIAAAABAgAAAB1PbmUgYXR0YWNoZWQgcGF5bWVudCBleHBlY3RlZAMJAQAAAAEhAAAAAQUAAAAQaGFzRW5vdWdoQmFsYW5jZQkABE4AAAACCQAETAAAAAIJAQAAAA5TY3JpcHRUcmFuc2ZlcgAAAAMIBQAAAAFpAAAABmNhbGxlcgUAAAAJcG10QW1vdW50BQAAAApwbXRBc3NldElkBQAAAANuaWwJAQAAABFzdXNwZW5kU3VzcGljaW91cwAAAAADAwkBAAAAAiE9AAAAAgUAAAAKcG10QXNzZXRJZAUAAAAIYXNzZXRJZEEJAQAAAAIhPQAAAAIFAAAACnBtdEFzc2V0SWQFAAAACGFzc2V0SWRCBwkBAAAAC3Rocm93QXNzZXRzAAAAAAQAAAANJHQwMTQ1MjExNTI4NgMJAAAAAAAAAgUAAAAKcG10QXNzZXRJZAUAAAAIYXNzZXRJZEEJAAUZAAAABwkAAGUAAAACBQAAAAlwbXRBbW91bnQFAAAAE3ZpcnR1YWxTd2FwVG9rZW5QYXkFAAAAE3ZpcnR1YWxTd2FwVG9rZW5HZXQJAABkAAAAAgUAAAAIYmFsYW5jZUEFAAAAE3ZpcnR1YWxTd2FwVG9rZW5QYXkJAABlAAAAAgUAAAAIYmFsYW5jZUIFAAAAE3ZpcnR1YWxTd2FwVG9rZW5HZXQJAQAAAA1pbnZhcmlhbnRDYWxjAAAAAgkAAGQAAAACBQAAAAhiYWxhbmNlQQUAAAAJcG10QW1vdW50BQAAAAhiYWxhbmNlQgkAAGQAAAACBQAAAAhiYWxhbmNlQQUAAAAJcG10QW1vdW50BQAAAAhiYWxhbmNlQgkABRkAAAAHBQAAABN2aXJ0dWFsU3dhcFRva2VuR2V0CQAAZQAAAAIFAAAACXBtdEFtb3VudAUAAAATdmlydHVhbFN3YXBUb2tlblBheQkAAGUAAAACBQAAAAhiYWxhbmNlQQUAAAATdmlydHVhbFN3YXBUb2tlbkdldAkAAGQAAAACBQAAAAhiYWxhbmNlQgUAAAATdmlydHVhbFN3YXBUb2tlblBheQkBAAAADWludmFyaWFudENhbGMAAAACBQAAAAhiYWxhbmNlQQkAAGQAAAACBQAAAAhiYWxhbmNlQgUAAAAJcG10QW1vdW50BQAAAAhiYWxhbmNlQQkAAGQAAAACBQAAAAhiYWxhbmNlQgUAAAAJcG10QW1vdW50BAAAABF2aXJ0dWFsUmVwbGVuaXNoQQgFAAAADSR0MDE0NTIxMTUyODYAAAACXzEEAAAAEXZpcnR1YWxSZXBsZW5pc2hCCAUAAAANJHQwMTQ1MjExNTI4NgAAAAJfMgQAAAARYmFsYW5jZUFmdGVyU3dhcEEIBQAAAA0kdDAxNDUyMTE1Mjg2AAAAAl8zBAAAABFiYWxhbmNlQWZ0ZXJTd2FwQggFAAAADSR0MDE0NTIxMTUyODYAAAACXzQEAAAAE2ludmFyaWFudENhbGN1bGF0ZWQIBQAAAA0kdDAxNDUyMTE1Mjg2AAAAAl81BAAAAAtuZXdCYWxhbmNlQQgFAAAADSR0MDE0NTIxMTUyODYAAAACXzYEAAAAC25ld0JhbGFuY2VCCAUAAAANJHQwMTQ1MjExNTI4NgAAAAJfNwQAAAAPbmV3QmFsYW5jZUVudHJ5AwkAAAAAAAACBQAAAApwbXRBc3NldElkBQAAAAhhc3NldElkQQkBAAAADEludGVnZXJFbnRyeQAAAAIFAAAACWtCYWxhbmNlQQUAAAALbmV3QmFsYW5jZUEJAQAAAAxJbnRlZ2VyRW50cnkAAAACBQAAAAlrQmFsYW5jZUIFAAAAC25ld0JhbGFuY2VCBAAAAAxpbnZhcmlhbnROZXcJAQAAAA1pbnZhcmlhbnRDYWxjAAAAAgUAAAARYmFsYW5jZUFmdGVyU3dhcEEFAAAAEWJhbGFuY2VBZnRlclN3YXBCBAAAABdpbnZhcmlhbnRFc3RpbWF0ZWRSYXRpbwkAAGsAAAADBQAAAAZzY2FsZTgFAAAACWludmFyaWFudAUAAAAMaW52YXJpYW50TmV3BAAAACVyYXRpb1ZpcnR1YWxCYWxhbmNlVG9WaXJ0dWFsUmVwbGVuaXNoCQAAaQAAAAIJAABrAAAAAwkAAGgAAAACBQAAAAZzY2FsZTgFAAAABnNjYWxlOAUAAAARYmFsYW5jZUFmdGVyU3dhcEEFAAAAEWJhbGFuY2VBZnRlclN3YXBCCQAAawAAAAMFAAAABnNjYWxlOAUAAAARdmlydHVhbFJlcGxlbmlzaEEFAAAAEXZpcnR1YWxSZXBsZW5pc2hCBAAAABNkQXBwVGhyZXNob2xkQW1vdW50CQAAawAAAAMJAABkAAAAAgUAAAALbmV3QmFsYW5jZUEFAAAAC25ld0JhbGFuY2VCBQAAAA1kQXBwVGhyZXNob2xkCQAAaAAAAAIAAAAAAAAAAAIFAAAAE2RBcHBUaHJlc2hvbGRTY2FsZTIDAwkAAGcAAAACBQAAABdzbGlwcGFnZVZhbHVlTWluRm9yU3dhcAUAAAAXaW52YXJpYW50RXN0aW1hdGVkUmF0aW8GCQAAZgAAAAIFAAAACWludmFyaWFudAUAAAAMaW52YXJpYW50TmV3CQAAAgAAAAECAAAAOkluY29ycmVjdCB2aXJ0dWFsU3dhcFRva2VuUGF5IG9yIHZpcnR1YWxTd2FwVG9rZW5HZXQgdmFsdWUDAwkAAGYAAAACBQAAABxzbGlwcGFnZVZhbHVlTWluRm9yUmVwbGVuaXNoBQAAACVyYXRpb1ZpcnR1YWxCYWxhbmNlVG9WaXJ0dWFsUmVwbGVuaXNoBgkAAGYAAAACBQAAACVyYXRpb1ZpcnR1YWxCYWxhbmNlVG9WaXJ0dWFsUmVwbGVuaXNoBQAAABxzbGlwcGFnZVZhbHVlTWF4Rm9yUmVwbGVuaXNoCQAAAgAAAAECAAAAbFN3YXAgd2l0aCB2aXJ0dWFsU3dhcFRva2VuUGF5IGFuZCB2aXJ0dWFsU3dhcFRva2VuR2V0IGlzIHBvc3NpYmxlLCBidXQgcmF0aW8gYWZ0ZXIgdmlydHVhbCBzd2FwIGlzIGluY29ycmVjdAMDCQAAZgAAAAIFAAAAE2RBcHBUaHJlc2hvbGRBbW91bnQFAAAAC25ld0JhbGFuY2VBBgkAAGYAAAACBQAAABNkQXBwVGhyZXNob2xkQW1vdW50BQAAAAtuZXdCYWxhbmNlQgkBAAAADnRocm93VGhyZXNob2xkAAAAAwUAAAATZEFwcFRocmVzaG9sZEFtb3VudAUAAAALbmV3QmFsYW5jZUEFAAAAC25ld0JhbGFuY2VCBAAAABNyYXRpb1NoYXJlVG9rZW5zSW5BCQAAawAAAAMJAQAAABBkZWR1Y3RTdGFraW5nRmVlAAAAAgUAAAARdmlydHVhbFJlcGxlbmlzaEEFAAAACGFzc2V0SWRBBQAAAAZzY2FsZTgFAAAAEWJhbGFuY2VBZnRlclN3YXBBBAAAABNyYXRpb1NoYXJlVG9rZW5zSW5CCQAAawAAAAMJAQAAABBkZWR1Y3RTdGFraW5nRmVlAAAAAgUAAAARdmlydHVhbFJlcGxlbmlzaEIFAAAACGFzc2V0SWRCBQAAAAZzY2FsZTgFAAAAEWJhbGFuY2VBZnRlclN3YXBCBAAAABVzaGFyZVRva2VuVG9QYXlBbW91bnQJAABrAAAAAwkAAZcAAAABCQAETAAAAAIFAAAAE3JhdGlvU2hhcmVUb2tlbnNJbkEJAARMAAAAAgUAAAATcmF0aW9TaGFyZVRva2Vuc0luQgUAAAADbmlsBQAAABBzaGFyZUFzc2V0U3VwcGx5BQAAAAZzY2FsZTgJAARMAAAAAgkBAAAAB1JlaXNzdWUAAAADBQAAAAxzaGFyZUFzc2V0SWQFAAAAFXNoYXJlVG9rZW5Ub1BheUFtb3VudAYJAARMAAAAAgkBAAAADlNjcmlwdFRyYW5zZmVyAAAAAwgFAAAAAWkAAAAGY2FsbGVyBQAAABVzaGFyZVRva2VuVG9QYXlBbW91bnQFAAAADHNoYXJlQXNzZXRJZAkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgUAAAARa1NoYXJlQXNzZXRTdXBwbHkJAABkAAAAAgUAAAAQc2hhcmVBc3NldFN1cHBseQUAAAAVc2hhcmVUb2tlblRvUGF5QW1vdW50CQAETAAAAAIFAAAAD25ld0JhbGFuY2VFbnRyeQkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgUAAAAKa0ludmFyaWFudAUAAAATaW52YXJpYW50Q2FsY3VsYXRlZAUAAAADbmlsAAAAAWkBAAAACHdpdGhkcmF3AAAAAAQAAAANJHQwMTc0MzExNzU3NAkABRQAAAACCAkAAZEAAAACCAUAAAABaQAAAAhwYXltZW50cwAAAAAAAAAAAAAAAAZhbW91bnQICQABkQAAAAIIBQAAAAFpAAAACHBheW1lbnRzAAAAAAAAAAAAAAAAB2Fzc2V0SWQEAAAACXBtdEFtb3VudAgFAAAADSR0MDE3NDMxMTc1NzQAAAACXzEEAAAACnBtdEFzc2V0SWQIBQAAAA0kdDAxNzQzMTE3NTc0AAAAAl8yBAAAAAxhbW91bnRUb1BheUEJAQAAABBkZWR1Y3RTdGFraW5nRmVlAAAAAgkAAGsAAAADBQAAAAlwbXRBbW91bnQFAAAACGJhbGFuY2VBBQAAABBzaGFyZUFzc2V0U3VwcGx5BQAAAAhhc3NldElkQQQAAAAMYW1vdW50VG9QYXlCCQEAAAAQZGVkdWN0U3Rha2luZ0ZlZQAAAAIJAABrAAAAAwUAAAAJcG10QW1vdW50BQAAAAhiYWxhbmNlQgUAAAAQc2hhcmVBc3NldFN1cHBseQUAAAAIYXNzZXRJZEIEAAAAE2ludmFyaWFudENhbGN1bGF0ZWQJAQAAAA1pbnZhcmlhbnRDYWxjAAAAAgkAAGUAAAACBQAAAAhiYWxhbmNlQQUAAAAMYW1vdW50VG9QYXlBCQAAZQAAAAIFAAAACGJhbGFuY2VCBQAAAAxhbW91bnRUb1BheUIDCQEAAAABIQAAAAEFAAAACGlzQWN0aXZlCQEAAAAPdGhyb3dJc0luYWN0aXZlAAAAAAMJAQAAAAIhPQAAAAIJAAGQAAAAAQgFAAAAAWkAAAAIcGF5bWVudHMAAAAAAAAAAAEJAAACAAAAAQIAAAAdT25lIGF0dGFjaGVkIHBheW1lbnQgZXhwZWN0ZWQDCQEAAAACIT0AAAACBQAAAApwbXRBc3NldElkBQAAAAxzaGFyZUFzc2V0SWQJAAACAAAAAQkAASwAAAACAgAAACRJbmNvcnJlY3QgYXNzZXQgYXR0YWNoZWQuIEV4cGVjdGVkOiAJAAJYAAAAAQUAAAAMc2hhcmVBc3NldElkAwkBAAAAASEAAAABBQAAABBoYXNFbm91Z2hCYWxhbmNlCQAETgAAAAIJAARMAAAAAgkBAAAADlNjcmlwdFRyYW5zZmVyAAAAAwgFAAAAAWkAAAAGY2FsbGVyBQAAAAlwbXRBbW91bnQFAAAACnBtdEFzc2V0SWQFAAAAA25pbAkBAAAAEXN1c3BlbmRTdXNwaWNpb3VzAAAAAAMDCQAAZgAAAAIFAAAADGFtb3VudFRvUGF5QQUAAAARYXZhaWxhYmxlQmFsYW5jZUEGCQAAZgAAAAIFAAAADGFtb3VudFRvUGF5QgUAAAARYXZhaWxhYmxlQmFsYW5jZUIJAQAAACJ0aHJvd0luc3VmZmljaWVudEF2YWlsYWJsZUJhbGFuY2VzAAAAAgUAAAAMYW1vdW50VG9QYXlBBQAAAAxhbW91bnRUb1BheUIJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAIFAAAACWtCYWxhbmNlQQkAAGUAAAACBQAAAAhiYWxhbmNlQQUAAAAMYW1vdW50VG9QYXlBCQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACBQAAAAlrQmFsYW5jZUIJAABlAAAAAgUAAAAIYmFsYW5jZUIFAAAADGFtb3VudFRvUGF5QgkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgUAAAARa1NoYXJlQXNzZXRTdXBwbHkJAABlAAAAAgUAAAAQc2hhcmVBc3NldFN1cHBseQUAAAAJcG10QW1vdW50CQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACBQAAAAprSW52YXJpYW50BQAAABNpbnZhcmlhbnRDYWxjdWxhdGVkCQAETAAAAAIJAQAAAARCdXJuAAAAAgUAAAAMc2hhcmVBc3NldElkBQAAAAlwbXRBbW91bnQJAARMAAAAAgkBAAAADlNjcmlwdFRyYW5zZmVyAAAAAwgFAAAAAWkAAAAGY2FsbGVyBQAAAAxhbW91bnRUb1BheUEFAAAACGFzc2V0SWRBCQAETAAAAAIJAQAAAA5TY3JpcHRUcmFuc2ZlcgAAAAMIBQAAAAFpAAAABmNhbGxlcgUAAAAMYW1vdW50VG9QYXlCBQAAAAhhc3NldElkQgUAAAADbmlsAAAAAWkBAAAACGV4Y2hhbmdlAAAAAgAAABhlc3RpbWF0ZWRBbW91bnRUb1JlY2VpdmUAAAASbWluQW1vdW50VG9SZWNlaXZlBAAAAA0kdDAxODkzMjE5MDA3CQAFFAAAAAIICQABkQAAAAIIBQAAAAFpAAAACHBheW1lbnRzAAAAAAAAAAAAAAAABmFtb3VudAgJAAGRAAAAAggFAAAAAWkAAAAIcGF5bWVudHMAAAAAAAAAAAAAAAAHYXNzZXRJZAQAAAAJcG10QW1vdW50CAUAAAANJHQwMTg5MzIxOTAwNwAAAAJfMQQAAAAKcG10QXNzZXRJZAgFAAAADSR0MDE4OTMyMTkwMDcAAAACXzIDCQEAAAABIQAAAAEFAAAACGlzQWN0aXZlCQEAAAAPdGhyb3dJc0luYWN0aXZlAAAAAAMJAABnAAAAAgAAAAAAAAAAAAUAAAAYZXN0aW1hdGVkQW1vdW50VG9SZWNlaXZlCQAAAgAAAAEJAAEsAAAAAgIAAAArRXN0aW1hdGVkIGFtb3VudCBtdXN0IGJlIHBvc2l0aXZlLiBBY3R1YWw6IAkAAaQAAAABBQAAABhlc3RpbWF0ZWRBbW91bnRUb1JlY2VpdmUDCQAAZgAAAAIFAAAAEm1pbkFtb3VudFRvUmVjZWl2ZQUAAAAYZXN0aW1hdGVkQW1vdW50VG9SZWNlaXZlCQAAAgAAAAEJAAEsAAAAAgkAASwAAAACCQABLAAAAAICAAAAO01pbmltYWwgYW1vdW50IGNhbid0IGJlIGdyZWF0ZXIgdGhhbiBlc3RpbWF0ZWQuIEVzdGltYXRlZDogCQABpAAAAAEFAAAAGGVzdGltYXRlZEFtb3VudFRvUmVjZWl2ZQIAAAALLiBNaW5pbWFsOiAJAAGkAAAAAQUAAAASbWluQW1vdW50VG9SZWNlaXZlAwkBAAAAAiE9AAAAAgkAAZAAAAABCAUAAAABaQAAAAhwYXltZW50cwAAAAAAAAAAAQkAAAIAAAABAgAAAB1PbmUgYXR0YWNoZWQgcGF5bWVudCBleHBlY3RlZAMJAQAAAAEhAAAAAQUAAAAQaGFzRW5vdWdoQmFsYW5jZQkABE4AAAACCQAETAAAAAIJAQAAAA5TY3JpcHRUcmFuc2ZlcgAAAAMIBQAAAAFpAAAABmNhbGxlcgUAAAAJcG10QW1vdW50BQAAAApwbXRBc3NldElkBQAAAANuaWwJAQAAABFzdXNwZW5kU3VzcGljaW91cwAAAAADAwkBAAAAAiE9AAAAAgUAAAAKcG10QXNzZXRJZAUAAAAIYXNzZXRJZEEJAQAAAAIhPQAAAAIFAAAACnBtdEFzc2V0SWQFAAAACGFzc2V0SWRCBwkBAAAAC3Rocm93QXNzZXRzAAAAAAMJAABmAAAAAgAAAAAAAJiWgAUAAAAJcG10QW1vdW50CQAAAgAAAAECAAAAME9ubHkgc3dhcCBvZiAxMC4wMDAwMDAgb3IgbW9yZSB0b2tlbnMgaXMgYWxsb3dlZAMDCQAAZgAAAAIFAAAAFWV4Y2hhbmdlUmF0aW9MaW1pdE1pbgkAAGsAAAADBQAAAAZzY2FsZTgFAAAAEm1pbkFtb3VudFRvUmVjZWl2ZQUAAAAJcG10QW1vdW50BgkAAGYAAAACCQAAawAAAAMFAAAABnNjYWxlOAUAAAAYZXN0aW1hdGVkQW1vdW50VG9SZWNlaXZlBQAAAAlwbXRBbW91bnQFAAAAFWV4Y2hhbmdlUmF0aW9MaW1pdE1heAkAAAIAAAABAgAAABxJbmNvcnJlY3QgYXJncyBhbmQgcG10IHJhdGlvBAAAAAtzZW5kQXNzZXRJZAMJAAAAAAAAAgUAAAAKcG10QXNzZXRJZAUAAAAIYXNzZXRJZEEFAAAACGFzc2V0SWRCBQAAAAhhc3NldElkQQQAAAAGYW1vdW50CQEAAAATY2FsY3VsYXRlU2VuZEFtb3VudAAAAAQFAAAAGGVzdGltYXRlZEFtb3VudFRvUmVjZWl2ZQUAAAASbWluQW1vdW50VG9SZWNlaXZlBQAAAAlwbXRBbW91bnQFAAAACnBtdEFzc2V0SWQEAAAAEGdvdmVybmFuY2VSZXdhcmQJAABrAAAAAwUAAAAGYW1vdW50BQAAAA1mZWVHb3Zlcm5hbmNlBQAAAAlmZWVTY2FsZTYEAAAADmFtb3VudE1pbnVzRmVlCQAAawAAAAMFAAAABmFtb3VudAkAAGUAAAACBQAAAAlmZWVTY2FsZTYFAAAAA2ZlZQUAAAAJZmVlU2NhbGU2BAAAAA0kdDAyMDQyOTIwNjkxAwkAAAAAAAACBQAAAApwbXRBc3NldElkBQAAAAhhc3NldElkQQkABRQAAAACCQAAZAAAAAIFAAAACGJhbGFuY2VBBQAAAAlwbXRBbW91bnQJAABlAAAAAgkAAGUAAAACBQAAAAhiYWxhbmNlQgUAAAAOYW1vdW50TWludXNGZWUFAAAAEGdvdmVybmFuY2VSZXdhcmQJAAUUAAAAAgkAAGUAAAACCQAAZQAAAAIFAAAACGJhbGFuY2VBBQAAAA5hbW91bnRNaW51c0ZlZQUAAAAQZ292ZXJuYW5jZVJld2FyZAkAAGQAAAACBQAAAAhiYWxhbmNlQgUAAAAJcG10QW1vdW50BAAAAAtuZXdCYWxhbmNlQQgFAAAADSR0MDIwNDI5MjA2OTEAAAACXzEEAAAAC25ld0JhbGFuY2VCCAUAAAANJHQwMjA0MjkyMDY5MQAAAAJfMgQAAAATZEFwcFRocmVzaG9sZEFtb3VudAkAAGsAAAADCQAAZAAAAAIFAAAAC25ld0JhbGFuY2VBBQAAAAtuZXdCYWxhbmNlQgUAAAANZEFwcFRocmVzaG9sZAkAAGgAAAACAAAAAAAAAAACBQAAABNkQXBwVGhyZXNob2xkU2NhbGUyAwMJAABmAAAAAgUAAAATZEFwcFRocmVzaG9sZEFtb3VudAUAAAALbmV3QmFsYW5jZUEGCQAAZgAAAAIFAAAAE2RBcHBUaHJlc2hvbGRBbW91bnQFAAAAC25ld0JhbGFuY2VCCQEAAAAOdGhyb3dUaHJlc2hvbGQAAAADBQAAABNkQXBwVGhyZXNob2xkQW1vdW50BQAAAAtuZXdCYWxhbmNlQQUAAAALbmV3QmFsYW5jZUIDAwMJAAAAAAAAAgUAAAAIYXNzZXRJZEEFAAAABFVTRE4JAAAAAAAAAgUAAAALc2VuZEFzc2V0SWQFAAAACGFzc2V0SWRBBwkAAGcAAAACBQAAABBzdGFrZWRBbW91bnRVU0ROBQAAAAtuZXdCYWxhbmNlQQcJAQAAACF0aHJvd0luc3VmZmljaWVudEF2YWlsYWJsZUJhbGFuY2UAAAADBQAAAA5hbW91bnRNaW51c0ZlZQUAAAARYXZhaWxhYmxlQmFsYW5jZUEFAAAACmFzc2V0TmFtZUEDAwMJAAAAAAAAAgUAAAAIYXNzZXRJZEIFAAAABFVTRE4JAAAAAAAAAgUAAAALc2VuZEFzc2V0SWQFAAAACGFzc2V0SWRCBwkAAGcAAAACBQAAABBzdGFrZWRBbW91bnRVU0ROBQAAAAtuZXdCYWxhbmNlQgcJAQAAACF0aHJvd0luc3VmZmljaWVudEF2YWlsYWJsZUJhbGFuY2UAAAADBQAAAA5hbW91bnRNaW51c0ZlZQUAAAARYXZhaWxhYmxlQmFsYW5jZUIFAAAACmFzc2V0TmFtZUIJAAUUAAAAAgkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgUAAAAJa0JhbGFuY2VBBQAAAAtuZXdCYWxhbmNlQQkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgUAAAAJa0JhbGFuY2VCBQAAAAtuZXdCYWxhbmNlQgkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgUAAAAKa0ludmFyaWFudAkBAAAADWludmFyaWFudENhbGMAAAACBQAAAAtuZXdCYWxhbmNlQQUAAAALbmV3QmFsYW5jZUIJAARMAAAAAgkBAAAADlNjcmlwdFRyYW5zZmVyAAAAAwgFAAAAAWkAAAAGY2FsbGVyBQAAAA5hbW91bnRNaW51c0ZlZQUAAAALc2VuZEFzc2V0SWQJAARMAAAAAgkBAAAADlNjcmlwdFRyYW5z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bGxCCQAAAgAAAAECAAAAFVRvbyBsYXJnZSBhbW91bnRMZWF2ZQkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgUAAAAKa0ludmFyaWFudAUAAAAMaW52YXJpYW50TmV3CQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACBQAAAAlrQmFsYW5jZUEJAABkAAAAAgUAAAAIYmFsYW5jZUEFAAAADWFtb3VudEVucm9sbEEJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAIFAAAACWtCYWxhbmNlQgkAAGQAAAACBQAAAAhiYWxhbmNlQgUAAAANYW1vdW50RW5yb2xsQgkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgkAASwAAAACAgAAAAxsYXN0X2luY29tZV8FAAAAC3N0ckFzc2V0SWRBBQAAAA1hbW91bnRFbnJvbGxBCQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACCQABLAAAAAICAAAADGxhc3RfaW5jb21lXwUAAAALc3RyQXNzZXRJZEIFAAAADWFtb3VudEVucm9sbEIFAAAAA25pbAAAAAAqk6a/", "height": 1699977, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: 7RHab9qLoyJjAs2UDGBBAM3ncuJHS95DXRMcfWWcvwrx Next: none Diff:
OldNewDifferences
11 {-# STDLIB_VERSION 5 #-}
22 {-# SCRIPT_TYPE ACCOUNT #-}
33 {-# CONTENT_TYPE DAPP #-}
4-let version = "1.0.0"
4+let version = "2.0.0"
55
6-let keyVersion = "version"
6+let kVersion = "version"
77
8-let keyActive = "active"
8+let kActive = "active"
99
10-let keyAssetIdA = "A_asset_id"
10+let kAssetIdA = "A_asset_id"
1111
12-let keyAssetIdB = "B_asset_id"
12+let kAssetIdB = "B_asset_id"
1313
14-let keyBalanceA = "A_asset_balance"
14+let kBalanceA = "A_asset_balance"
1515
16-let keyBalanceB = "B_asset_balance"
16+let kBalanceB = "B_asset_balance"
1717
18-let keyBalanceInitA = "A_asset_init"
18+let kShareAssetId = "share_asset_id"
1919
20-let keyBalanceInitB = "B_asset_init"
20+let kShareAssetSupply = "share_asset_supply"
2121
22-let keyShareAssetId = "share_asset_id"
22+let kFee = "commission"
2323
24-let keyShareAssetSupply = "share_asset_supply"
24+let kFeeScaleDelimiter = "commission_scale_delimiter"
2525
26-let keyCommission = "commission"
26+let kInvariant = "invariant"
2727
28-let keyCommissionScaleDelimiter = "commission_scale_delimiter"
29-
30-let keyCause = "shutdown_cause"
31-
32-let keyFirstHarvest = "first_harvest"
33-
34-let keyFirstHarvestHeight = "first_harvest_height"
35-
36-let kShareLimit = "share_limit_on_first_harvest"
37-
38-let kBasePeriod = "base_period"
39-
40-let kPeriodLength = "period_length"
41-
42-let kStartHeight = "start_height"
43-
44-let kFirstHarvestHeight = "first_harvest_height"
28+let kCause = "shutdown_cause"
4529
4630 let keyAdminPubKey1 = "admin_pub_1"
4731
4832 let keyAdminPubKey2 = "admin_pub_2"
4933
5034 let keyAdminPubKey3 = "admin_pub_3"
35+
36+let USDNToWavesExchanger = Address(base58'3PHaNgomBkrvEL2QnuJarQVJa71wjw9qiqG')
5137
5238 let oracle = Address(base58'3PEbqViERCoKnmcSULh6n2aiMvUdSQdCsom')
5339
6551
6652 let adminPubKey3 = getAdminPub(keyAdminPubKey3)
6753
68-let adminPubKeyStartStop = base58'EtVkT6ed8GtbUiVVEqdmEqsp2J4qbb3rre2HFgxeVYdg'
54+let admStartStop = base58'EtVkT6ed8GtbUiVVEqdmEqsp2J4qbb3rre2HFgxeVYdg'
6955
70-let adminPubKeyStaking = base58'Czn4yoAuUZCVCLJDRfskn8URfkwpknwBTZDbs1wFrY7h'
56+let admStaking = base58'Czn4yoAuUZCVCLJDRfskn8URfkwpknwBTZDbs1wFrY7h'
7157
72-let walletAddress = Address(base58'3N7cz2aJBxu3DpGVZnaHj8J479JBiEhdqsw')
58+let govAddr = Address(base58'3P6J84oH51DzY6xk2mT5TheXRbrCwBMxonp')
7359
74-let votingAddress = Address(base58'3N7cz2aJBxu3DpGVZnaHj8J479JBiEhdqsw')
60+let stakingAddress = Address(base58'3PNikM6yp4NqcSU8guxQtmR5onr2D4e8yTJ')
7561
7662 let USDN = base58'DG2xFkPdDwKUoBkzGAhQtLpSGzfXLiCYPEzeKH2Ad24p'
7763
78-let NSBT = base58'6nSpVyNH7yM69eg446wrQR94ipbbcmZMU1ENPwanC97g'
79-
80-let SWOP = base58'Ehie5xYpeN8op1Cctc6aGUrqx8jq3jtf1DSjXDbfm7aT'
81-
82-let EURN = base58'DUk2YTxhRoAqMJLus4G2b3fR8hMHVh6eiyFx5r29VR6t'
83-
84-let stakingUSDNNSBTAddress = Address(base58'3PNikM6yp4NqcSU8guxQtmR5onr2D4e8yTJ')
85-
86-let stakingEURNAddress = Address(base58'3PFhcMmEZoQTQ6ohA844c7C9M8ZJ18P8dDj')
87-
88-let USDNToWavesExchanger = Address(base58'3PHaNgomBkrvEL2QnuJarQVJa71wjw9qiqG')
89-
90-let USDNToNSBTExchanger = Address(base58'3P2V63Xd6BviDkeMzxhUw2SJyojByRz8a8m')
91-
9264 let stakingFeeInUSDN = 270000
9365
94-let stakingFeeInEURN = 234000
66+let isActive = getBooleanValue(this, kActive)
9567
96-let basePeriod = valueOrErrorMessage(getInteger(votingAddress, kBasePeriod), "Empty kBasePeriod")
68+let strAssetIdA = getStringValue(this, kAssetIdA)
9769
98-let startHeight = valueOrErrorMessage(getInteger(votingAddress, kStartHeight), "Empty kStartHeight")
99-
100-let periodLength = valueOrErrorMessage(getInteger(votingAddress, kPeriodLength), "Empty kPeriodLength")
101-
102-let firstHarvestEndPeriod = ((basePeriod + ((height - startHeight) / periodLength)) + 3)
103-
104-let isActive = getBooleanValue(this, keyActive)
105-
106-let strAssetIdA = getStringValue(this, keyAssetIdA)
107-
108-let strAssetIdB = getStringValue(this, keyAssetIdB)
70+let strAssetIdB = getStringValue(this, kAssetIdB)
10971
11072 let assetIdA = if ((strAssetIdA == "WAVES"))
11173 then unit
13395 throw("Match error")
13496 }
13597
136-let balanceA = getIntegerValue(this, keyBalanceA)
98+let balanceA = getIntegerValue(this, kBalanceA)
13799
138-let balanceB = getIntegerValue(this, keyBalanceB)
100+let balanceB = getIntegerValue(this, kBalanceB)
139101
140-let shareAssetId = fromBase58String(getStringValue(this, keyShareAssetId))
102+let shareAssetId = fromBase58String(getStringValue(this, kShareAssetId))
141103
142-let shareAssetSupply = getIntegerValue(this, keyShareAssetSupply)
104+let shareAssetSupply = getIntegerValue(this, kShareAssetSupply)
143105
144-let commission = 3000
106+let invariant = getIntegerValue(this, kInvariant)
145107
146-let commissionGovernance = 1200
108+let fee = 500
147109
148-let commissionScaleDelimiter = 1000000
110+let feeGovernance = 200
149111
150-let scaleValue3 = 1000
112+let feeScale6 = 1000000
151113
152-let scaleValue8 = 100000000
114+let scale3 = 1000
153115
154-let slippageToleranceDelimiter = 1000
116+let scale8 = 100000000
155117
156-let scaleValue8Digits = 8
118+let scale12 = 1000000000000
119+
120+let slippageScale3 = 1000
121+
122+let digits8 = 8
123+
124+let dAppThreshold = 50
125+
126+let dAppThresholdScale2 = 100
127+
128+let exchangeRatioLimitMin = 90000000
129+
130+let exchangeRatioLimitMax = 110000000
131+
132+let alpha = 50
133+
134+let alphaDigits = 2
135+
136+let beta = 46000000
157137
158138 func accountBalance (assetId) = match assetId {
159139 case id: ByteVector =>
165145 }
166146
167147
168-func stakedAmount (assetId) = {
169- let stakedAmountCalculated = match assetId {
170- case aId: ByteVector =>
171- if (if ((aId == USDN))
172- then true
173- else (aId == NSBT))
174- then getInteger(stakingUSDNNSBTAddress, ((("rpd_balance_" + toBase58String(aId)) + "_") + toString(this)))
175- else if ((aId == EURN))
176- then getInteger(stakingEURNAddress, ((("%s%s%s__stakingBalance__" + toBase58String(aId)) + "__") + toString(this)))
177- else 0
178- case _: Unit =>
179- 0
180- case _ =>
181- throw("Match error")
182- }
183- match stakedAmountCalculated {
184- case i: Int =>
185- i
186- case _ =>
187- 0
188- }
189- }
148+let stakedAmountUSDN = match getInteger(stakingAddress, ((("rpd_balance_" + toBase58String(USDN)) + "_") + toString(this))) {
149+ case staked: Int =>
150+ staked
151+ case nothing: Unit =>
152+ 0
153+ case _ =>
154+ throw("Match error")
155+}
190156
157+let availableBalanceA = (balanceA - (if ((assetIdA == USDN))
158+ then stakedAmountUSDN
159+ else 0))
191160
192-let stakedAmountA = stakedAmount(assetIdA)
161+let availableBalanceB = (balanceB - (if ((assetIdB == USDN))
162+ then stakedAmountUSDN
163+ else 0))
193164
194-let stakedAmountB = stakedAmount(assetIdB)
165+let accountBalanceWithStakedA = (accountBalance(assetIdA) + (if ((assetIdA == USDN))
166+ then stakedAmountUSDN
167+ else 0))
195168
196-let assetInitA = getIntegerValue(this, keyBalanceInitA)
197-
198-let assetInitB = getIntegerValue(this, keyBalanceInitB)
199-
200-let availableBalanceA = (balanceA - stakedAmountA)
201-
202-let availableBalanceB = (balanceB - stakedAmountB)
203-
204-let accountBalanceWithStakedA = (accountBalance(assetIdA) + stakedAmountA)
205-
206-let accountBalanceWithStakedB = (accountBalance(assetIdB) + stakedAmountB)
169+let accountBalanceWithStakedB = (accountBalance(assetIdB) + (if ((assetIdB == USDN))
170+ then stakedAmountUSDN
171+ else 0))
207172
208173 let hasEnoughBalance = if ((accountBalanceWithStakedA >= balanceA))
209174 then (accountBalanceWithStakedB >= balanceB)
210175 else false
176+
177+func skewness (x,y) = (((fraction(scale12, x, y) + fraction(scale12, y, x)) / 2) / 10000)
178+
179+
180+func invariantCalc (x,y) = {
181+ let sk = skewness(x, y)
182+ (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)))
183+ }
184+
185+
186+func calculateSendAmount (amountToSendEstimated,minTokenReceiveAmount,tokenReceiveAmount,tokenId) = {
187+ let slippageValue = (scale8 - ((scale8 * 1) / 10000000))
188+ let deltaBetweenMaxAndMinSendValue = (amountToSendEstimated - minTokenReceiveAmount)
189+ let x = (balanceA + tokenReceiveAmount)
190+ let y = (balanceB + tokenReceiveAmount)
191+ let invariantNew = if ((tokenId == assetIdA))
192+ then invariantCalc(x, (balanceB - amountToSendEstimated))
193+ else if ((tokenId == assetIdB))
194+ then invariantCalc((balanceA - amountToSendEstimated), y)
195+ else throw("Wrong asset in payment")
196+ let invariantEstimatedRatio = fraction(scale8, invariant, invariantNew)
197+ func getStepAmount (acc,step) = if ((acc == -1))
198+ then {
199+ let amountToSend = (amountToSendEstimated - ((step * deltaBetweenMaxAndMinSendValue) / 5))
200+ let stepInvariant = if ((tokenId == assetIdA))
201+ then invariantCalc(x, (balanceB - amountToSend))
202+ else invariantCalc((balanceA - amountToSend), y)
203+ if ((stepInvariant > invariant))
204+ then amountToSend
205+ else -1
206+ }
207+ else acc
208+
209+ let stepAmount = {
210+ let $list60496092 = [1, 2, 3, 4, 5]
211+ let $size60496092 = size($list60496092)
212+ let $acc060496092 = -1
213+ if (($size60496092 == 0))
214+ then $acc060496092
215+ else {
216+ let $acc160496092 = getStepAmount($acc060496092, $list60496092[0])
217+ if (($size60496092 == 1))
218+ then $acc160496092
219+ else {
220+ let $acc260496092 = getStepAmount($acc160496092, $list60496092[1])
221+ if (($size60496092 == 2))
222+ then $acc260496092
223+ else {
224+ let $acc360496092 = getStepAmount($acc260496092, $list60496092[2])
225+ if (($size60496092 == 3))
226+ then $acc360496092
227+ else {
228+ let $acc460496092 = getStepAmount($acc360496092, $list60496092[3])
229+ if (($size60496092 == 4))
230+ then $acc460496092
231+ else {
232+ let $acc560496092 = getStepAmount($acc460496092, $list60496092[4])
233+ if (($size60496092 == 5))
234+ then $acc560496092
235+ else {
236+ let $acc660496092 = getStepAmount($acc560496092, $list60496092[5])
237+ throw("List size exceed 5")
238+ }
239+ }
240+ }
241+ }
242+ }
243+ }
244+ }
245+ if ((0 > stepAmount))
246+ then throw("something went wrong while working with amountToSend")
247+ else if (if ((invariantEstimatedRatio > slippageValue))
248+ then (invariantNew > invariant)
249+ else false)
250+ then amountToSendEstimated
251+ else stepAmount
252+ }
253+
211254
212255 func getAssetInfo (assetId) = match assetId {
213256 case id: ByteVector =>
221264 }
222265
223266
224-func getAssetInfoFromString (assetStr) = if ((assetStr == "WAVES"))
225- then $Tuple3("WAVES", "WAVES", 8)
226- else {
227- let stringId = assetStr
228- let id = fromBase58String(assetStr)
229- let info = valueOrErrorMessage(assetInfo(id), (("Asset " + stringId) + " doesn't exist"))
230- $Tuple3(stringId, info.name, info.decimals)
231- }
267+func suspend (cause) = [BooleanEntry(kActive, false), StringEntry(kCause, cause)]
232268
233269
234-func suspend (cause) = [BooleanEntry(keyActive, false), StringEntry(keyCause, cause)]
235-
236-
237-func deductStakingFee (amount,assetId,secondAssetId) = if (if ((assetId == USDN))
238- then true
239- else (assetId == EURN))
270+func deductStakingFee (amount,assetId) = if ((assetId == USDN))
240271 then {
241- let stakinFee = if ((assetId == USDN))
242- then (stakingFeeInUSDN * (if ((secondAssetId == NSBT))
243- then 2
244- else 1))
245- else if ((assetId == EURN))
246- then stakingFeeInEURN
247- else 0
248- let result = (amount - stakinFee)
272+ let result = (amount - stakingFeeInUSDN)
249273 if ((0 >= result))
250- then throw((((("Insufficient amount " + toString(amount)) + " to deduct staking fee ") + toString(stakinFee)) + "USDN/EURN"))
274+ then throw((((("Insufficient amount " + toString(amount)) + " to deduct staking fee ") + toString(stakingFeeInUSDN)) + " USD-N"))
251275 else result
252276 }
253277 else amount
254278
255279
256-func getStakingFee (assetId,secondAssetId) = if ((assetId == USDN))
257- then (stakingFeeInUSDN * (if ((secondAssetId == NSBT))
258- then 2
259- else 1))
260- else if ((assetId == EURN))
261- then stakingFeeInEURN
262- else 0
280+func throwIsActive () = throw("DApp is already active")
281+
282+
283+func throwIsInactive () = throw("DApp is inactive at this moment")
284+
285+
286+func throwOnlyAdmin () = throw("Only admin can call this function")
287+
288+
289+func throwAssets () = throw(((("Incorrect assets attached. Expected: " + strAssetIdA) + " and ") + strAssetIdB))
290+
291+
292+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))
263293
264294
265295 func throwInsufficientAvailableBalance (amount,available,assetName) = throw((((((((("Insufficient DApp balance to pay " + toString(amount)) + " ") + assetName) + " due to staking. Available: ") + toString(available)) + " ") + assetName) + ". Please contact support in Telegram: https://t.me/swopfisupport"))
268298 func throwInsufficientAvailableBalances (amountA,amountB) = throw((((((((((((((((("Insufficient DApp balance to pay " + toString(amountA)) + " ") + assetNameA) + " and ") + toString(amountB)) + " ") + assetNameB) + " due to staking. Available: ") + toString(availableBalanceA)) + " ") + assetNameA) + " and ") + toString(availableBalanceB)) + " ") + assetNameB) + ". Please contact support in Telegram: https://t.me/swopfisupport"))
269299
270300
271-func suspendSuspicious () = suspend(((((((((((((((("Suspicious state. Actual balances: " + toString(accountBalanceWithStakedA)) + " ") + assetNameA) + ", ") + toString(accountBalanceWithStakedB)) + " ") + assetNameB) + ". State: ") + toString(balanceA)) + " ") + assetNameA) + ", ") + toString(balanceB)) + " ") + assetNameB))
301+func suspendSuspicious () = suspend(((((((((((((((("Suspicious state. Actual balances: " + toString(balanceA)) + " ") + assetNameA) + ", ") + toString(balanceB)) + " ") + assetNameB) + ". State: ") + toString(accountBalance(assetIdA))) + " ") + assetNameA) + ", ") + toString(accountBalance(assetIdB))) + " ") + assetNameB))
272302
273303
274304 @Callable(i)
275-func init (firstHarvest) = {
276- let $t080008077 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
277- let pmtAmountA = $t080008077._1
278- let pmtAssetIdA = $t080008077._2
279- let $t080828159 = $Tuple2(i.payments[1].amount, i.payments[1].assetId)
280- let pmtAmountB = $t080828159._1
281- let pmtAssetIdB = $t080828159._2
282- let $t081648241 = getAssetInfo(pmtAssetIdA)
283- let pmtStrAssetIdA = $t081648241._1
284- let pmtAssetNameA = $t081648241._2
285- let pmtDecimalsA = $t081648241._3
286- let $t082468502 = getAssetInfo(pmtAssetIdB)
287- let pmtStrAssetIdB = $t082468502._1
288- let pmtAssetNameB = $t082468502._2
289- let pmtDecimalsB = $t082468502._3
290- if (isDefined(getBoolean(this, keyActive)))
291- then throw("DApp is already active")
305+func init () = {
306+ let $t087688845 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
307+ let pmtAmountA = $t087688845._1
308+ let pmtAssetIdA = $t087688845._2
309+ let $t088508927 = $Tuple2(i.payments[1].amount, i.payments[1].assetId)
310+ let pmtAmountB = $t088508927._1
311+ let pmtAssetIdB = $t088508927._2
312+ let $t089329009 = getAssetInfo(pmtAssetIdA)
313+ let pmtStrAssetIdA = $t089329009._1
314+ let pmtAssetNameA = $t089329009._2
315+ let pmtDecimalsA = $t089329009._3
316+ let $t090149091 = getAssetInfo(pmtAssetIdB)
317+ let pmtStrAssetIdB = $t090149091._1
318+ let pmtAssetNameB = $t090149091._2
319+ let pmtDecimalsB = $t090149091._3
320+ if (isDefined(getBoolean(this, kActive)))
321+ then throwIsActive()
292322 else if ((pmtAssetIdA == pmtAssetIdB))
293323 then throw("Assets must be different")
294324 else {
295325 let shareName = ((("s" + take(pmtAssetNameA, 7)) + "_") + take(pmtAssetNameB, 7))
296326 let shareDescription = ((((("ShareToken of SwopFi protocol for " + pmtAssetNameA) + " and ") + pmtAssetNameB) + " at address ") + toString(this))
297327 let shareDecimals = ((pmtDecimalsA + pmtDecimalsB) / 2)
298- let arg1 = pow(pmtAmountA, pmtDecimalsA, 5, 1, pmtDecimalsA, DOWN)
299- let arg2 = pow(pmtAmountB, pmtDecimalsB, 5, 1, pmtDecimalsB, DOWN)
300- let arg3 = pow(10, 0, shareDecimals, 0, 0, DOWN)
301- let shareInitialSupply = fraction(arg1, arg2, arg3)
328+ let shareInitialSupply = fraction(pow(pmtAmountA, pmtDecimalsA, 5, 1, pmtDecimalsA, DOWN), pow(pmtAmountB, pmtDecimalsB, 5, 1, pmtDecimalsB, DOWN), pow(10, 0, shareDecimals, 0, 0, DOWN))
302329 let shareIssue = Issue(shareName, shareDescription, shareInitialSupply, shareDecimals, true)
303330 let shareIssueId = calculateAssetId(shareIssue)
304- let baseEntry = [StringEntry(keyVersion, version), BooleanEntry(keyActive, true), StringEntry(keyAssetIdA, pmtStrAssetIdA), StringEntry(keyAssetIdB, pmtStrAssetIdB), IntegerEntry(keyBalanceA, pmtAmountA), IntegerEntry(keyBalanceB, pmtAmountB), IntegerEntry(keyCommission, commission), IntegerEntry(keyCommissionScaleDelimiter, commissionScaleDelimiter), shareIssue, StringEntry(keyShareAssetId, toBase58String(shareIssueId)), IntegerEntry(keyShareAssetSupply, shareInitialSupply), ScriptTransfer(i.caller, shareInitialSupply, shareIssueId)]
305- if (firstHarvest)
306- then (baseEntry ++ [BooleanEntry(keyFirstHarvest, firstHarvest), IntegerEntry(keyFirstHarvestHeight, (startHeight + (firstHarvestEndPeriod * periodLength)))])
307- else baseEntry
331+ let invariantCalculated = invariantCalc(pmtAmountA, pmtAmountB)
332+[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)]
308333 }
309334 }
310-
311-
312-
313-@Callable(i)
314-func initWithInitRatio (amtAssetA,amtAssetB,strAssetIdA,strAssetIdB,firstHarvest) = {
315- let $t01057910666 = getAssetInfoFromString(strAssetIdA)
316- let pmtStrAssetIdA = $t01057910666._1
317- let pmtAssetNameA = $t01057910666._2
318- let pmtDecimalsA = $t01057910666._3
319- let $t01067110758 = getAssetInfoFromString(strAssetIdB)
320- let pmtStrAssetIdB = $t01067110758._1
321- let pmtAssetNameB = $t01067110758._2
322- let pmtDecimalsB = $t01067110758._3
323- if (!(containsElement([adminPubKey1, adminPubKey2, adminPubKey3, adminPubKeyStaking], i.callerPublicKey)))
324- then throw("Only admin can call this function")
325- else if (isDefined(getBoolean(this, keyActive)))
326- then throw("DApp is already active")
327- else if ((strAssetIdA == strAssetIdB))
328- then throw("Assets must be different")
329- else {
330- let shareName = ((("s" + take(pmtAssetNameA, 7)) + "_") + take(pmtAssetNameB, 7))
331- let shareDescription = ((((("ShareToken of SwopFi protocol for " + pmtAssetNameA) + " and ") + pmtAssetNameB) + " at address ") + toString(this))
332- let shareDecimals = ((pmtDecimalsA + pmtDecimalsB) / 2)
333- let shareInitialSupply = 0
334- let shareIssue = Issue(shareName, shareDescription, shareInitialSupply, shareDecimals, true)
335- let shareIssueId = calculateAssetId(shareIssue)
336- let baseEntry = [StringEntry(keyVersion, version), BooleanEntry(keyActive, true), StringEntry(keyAssetIdA, pmtStrAssetIdA), StringEntry(keyAssetIdB, pmtStrAssetIdB), IntegerEntry(keyBalanceInitA, amtAssetA), IntegerEntry(keyBalanceInitB, amtAssetB), IntegerEntry(keyBalanceA, 0), IntegerEntry(keyBalanceB, 0), IntegerEntry(keyCommission, commission), IntegerEntry(keyCommissionScaleDelimiter, commissionScaleDelimiter), shareIssue, StringEntry(keyShareAssetId, toBase58String(shareIssueId)), IntegerEntry(keyShareAssetSupply, shareInitialSupply)]
337- if (firstHarvest)
338- then (baseEntry ++ [BooleanEntry(keyFirstHarvest, firstHarvest), IntegerEntry(keyFirstHarvestHeight, (startHeight + (firstHarvestEndPeriod * periodLength)))])
339- else baseEntry
340- }
341- }
342-
343-
344-
345-@Callable(i)
346-func keepLimitForFirstHarvest (shareLimit) = if (!(isActive))
347- then throw("DApp is inactive at this moment")
348- else if (!(containsElement([adminPubKey1, adminPubKey2, adminPubKey3, adminPubKeyStaking], i.callerPublicKey)))
349- then throw("Only admin can call this function")
350- else [IntegerEntry(kShareLimit, shareLimit)]
351335
352336
353337
355339 func replenishWithTwoTokens (slippageTolerance) = {
356340 let pmtAssetIdA = i.payments[0].assetId
357341 let pmtAssetIdB = i.payments[1].assetId
358- let pmtAmountA = deductStakingFee(i.payments[0].amount, pmtAssetIdA, pmtAssetIdB)
359- let pmtAmountB = deductStakingFee(i.payments[1].amount, pmtAssetIdB, pmtAssetIdA)
360- if (if ((balanceA == 0))
361- then (balanceB == 0)
362- else false)
363- then {
364- let $t01346913546 = getAssetInfo(pmtAssetIdA)
365- let pmtStrAssetIdA = $t01346913546._1
366- let pmtAssetNameA = $t01346913546._2
367- let pmtDecimalsA = $t01346913546._3
368- let $t01355513632 = getAssetInfo(pmtAssetIdB)
369- let pmtStrAssetIdB = $t01355513632._1
370- let pmtAssetNameB = $t01355513632._2
371- let pmtDecimalsB = $t01355513632._3
372- let tokenRatio = fraction(fraction(assetInitA, scaleValue8, pmtAmountA), scaleValue3, fraction(assetInitB, scaleValue8, pmtAmountB))
373- if ((pmtAssetIdA == pmtAssetIdB))
374- then throw("Assets must be different")
375- else {
376- let shareDecimals = ((pmtDecimalsA + pmtDecimalsB) / 2)
377- let shareInitialSupply = fraction(pow(pmtAmountA, pmtDecimalsA, 5, 1, pmtDecimalsA, DOWN), pow(pmtAmountB, pmtDecimalsB, 5, 1, pmtDecimalsB, DOWN), pow(10, 0, shareDecimals, 0, 0, DOWN))
378- if (!(isActive))
379- then throw("DApp is inactive at this moment")
380- else if (if ((0 > slippageTolerance))
381- then true
382- else (slippageTolerance > slippageToleranceDelimiter))
383- then throw(((("Slippage tolerance must be between 0 and " + toString(slippageToleranceDelimiter)) + " inclusively. Actual: ") + toString(slippageTolerance)))
384- else if ((size(i.payments) != 2))
385- then throw("Two attached assets expected")
386- else if (if ((((scaleValue3 * (slippageToleranceDelimiter - slippageTolerance)) / slippageToleranceDelimiter) > tokenRatio))
342+ let pmtAmountA = deductStakingFee(i.payments[0].amount, pmtAssetIdA)
343+ let pmtAmountB = deductStakingFee(i.payments[1].amount, pmtAssetIdB)
344+ let tokenRatio = fraction(fraction(scale8, balanceA, pmtAmountA), scale3, fraction(scale8, balanceB, pmtAmountB))
345+ let ratioShareTokensInA = fraction(scale8, pmtAmountA, balanceA)
346+ let ratioShareTokensInB = fraction(scale8, pmtAmountB, balanceB)
347+ let shareTokenToPayAmount = fraction(min([ratioShareTokensInA, ratioShareTokensInB]), shareAssetSupply, scale8)
348+ let invariantCalculated = invariantCalc((balanceA + pmtAmountA), (balanceB + pmtAmountB))
349+ if (!(isActive))
350+ then throwIsInactive()
351+ else if (if ((0 > slippageTolerance))
352+ then true
353+ else (slippageTolerance > 10))
354+ then throw("Slippage tolerance must be <= 1%")
355+ else if ((size(i.payments) != 2))
356+ then throw("Two attached assets expected")
357+ else if (if ((pmtAssetIdA != assetIdA))
358+ then true
359+ else (pmtAssetIdB != assetIdB))
360+ then throwAssets()
361+ else if (if ((((scale3 * (slippageScale3 - slippageTolerance)) / slippageScale3) > tokenRatio))
362+ then true
363+ else (tokenRatio > ((scale3 * (slippageScale3 + slippageTolerance)) / slippageScale3)))
364+ then throw("Incorrect assets amount: amounts must have the contract ratio")
365+ else if ((shareTokenToPayAmount == 0))
366+ then throw("Too small amount to replenish")
367+ else if (!(hasEnoughBalance))
368+ then ([ScriptTransfer(i.caller, pmtAmountA, pmtAssetIdA), ScriptTransfer(i.caller, pmtAmountB, pmtAssetIdB)] ++ suspendSuspicious())
369+ else [IntegerEntry(kBalanceA, (balanceA + pmtAmountA)), IntegerEntry(kBalanceB, (balanceB + pmtAmountB)), IntegerEntry(kShareAssetSupply, (shareAssetSupply + shareTokenToPayAmount)), IntegerEntry(kInvariant, invariantCalculated), Reissue(shareAssetId, shareTokenToPayAmount, true), ScriptTransfer(i.caller, shareTokenToPayAmount, shareAssetId)]
370+ }
371+
372+
373+
374+@Callable(i)
375+func replenishWithOneToken (virtualSwapTokenPay,virtualSwapTokenGet) = {
376+ let $t01343413509 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
377+ let pmtAmount = $t01343413509._1
378+ let pmtAssetId = $t01343413509._2
379+ let pmtMinThreshold = 5000000
380+ let thresholdValueForMinTolerance = 50000000
381+ let tolerance = if ((thresholdValueForMinTolerance > pmtAmount))
382+ then 100000
383+ else 1
384+ let slippageValueMinForReplenish = (scale8 - ((scale8 * tolerance) / 10000000))
385+ let slippageValueMaxForReplenish = (scale8 + ((scale8 * tolerance) / 10000000))
386+ let slippageValueMinForSwap = (scale8 - ((scale8 * 1) / 10000000))
387+ if (!(isActive))
388+ then throwIsInactive()
389+ else if ((pmtMinThreshold > pmtAmount))
390+ then throw((((("Payment amount " + toString(pmtAmount)) + " does not exceed the minimum amount of ") + toString(pmtMinThreshold)) + " tokens"))
391+ else if ((size(i.payments) != 1))
392+ then throw("One attached payment expected")
393+ else if (!(hasEnoughBalance))
394+ then ([ScriptTransfer(i.caller, pmtAmount, pmtAssetId)] ++ suspendSuspicious())
395+ else if (if ((pmtAssetId != assetIdA))
396+ then (pmtAssetId != assetIdB)
397+ else false)
398+ then throwAssets()
399+ else {
400+ let $t01452115286 = if ((pmtAssetId == assetIdA))
401+ then $Tuple7((pmtAmount - virtualSwapTokenPay), virtualSwapTokenGet, (balanceA + virtualSwapTokenPay), (balanceB - virtualSwapTokenGet), invariantCalc((balanceA + pmtAmount), balanceB), (balanceA + pmtAmount), balanceB)
402+ else $Tuple7(virtualSwapTokenGet, (pmtAmount - virtualSwapTokenPay), (balanceA - virtualSwapTokenGet), (balanceB + virtualSwapTokenPay), invariantCalc(balanceA, (balanceB + pmtAmount)), balanceA, (balanceB + pmtAmount))
403+ let virtualReplenishA = $t01452115286._1
404+ let virtualReplenishB = $t01452115286._2
405+ let balanceAfterSwapA = $t01452115286._3
406+ let balanceAfterSwapB = $t01452115286._4
407+ let invariantCalculated = $t01452115286._5
408+ let newBalanceA = $t01452115286._6
409+ let newBalanceB = $t01452115286._7
410+ let newBalanceEntry = if ((pmtAssetId == assetIdA))
411+ then IntegerEntry(kBalanceA, newBalanceA)
412+ else IntegerEntry(kBalanceB, newBalanceB)
413+ let invariantNew = invariantCalc(balanceAfterSwapA, balanceAfterSwapB)
414+ let invariantEstimatedRatio = fraction(scale8, invariant, invariantNew)
415+ let ratioVirtualBalanceToVirtualReplenish = (fraction((scale8 * scale8), balanceAfterSwapA, balanceAfterSwapB) / fraction(scale8, virtualReplenishA, virtualReplenishB))
416+ let dAppThresholdAmount = fraction((newBalanceA + newBalanceB), dAppThreshold, (2 * dAppThresholdScale2))
417+ if (if ((slippageValueMinForSwap >= invariantEstimatedRatio))
418+ then true
419+ else (invariant > invariantNew))
420+ then throw("Incorrect virtualSwapTokenPay or virtualSwapTokenGet value")
421+ else if (if ((slippageValueMinForReplenish > ratioVirtualBalanceToVirtualReplenish))
387422 then true
388- else (tokenRatio > ((scaleValue3 * (slippageToleranceDelimiter + slippageTolerance)) / slippageToleranceDelimiter)))
389- then throw("Incorrect assets amount: amounts must have the contract ratio")
390- else if (if ((pmtAssetIdA != assetIdA))
423+ else (ratioVirtualBalanceToVirtualReplenish > slippageValueMaxForReplenish))
424+ then throw("Swap with virtualSwapTokenPay and virtualSwapTokenGet is possible, but ratio after virtual swap is incorrect")
425+ else if (if ((dAppThresholdAmount > newBalanceA))
391426 then true
392- else (pmtAssetIdB != assetIdB))
393- then throw(((("Incorrect assets attached. Expected: " + strAssetIdA) + " and ") + strAssetIdB))
394- else if ((shareInitialSupply == 0))
395- then throw("Too small amount to replenish")
396- else if (!(hasEnoughBalance))
397- then ([ScriptTransfer(i.caller, pmtAmountA, pmtAssetIdA), ScriptTransfer(i.caller, pmtAmountB, pmtAssetIdB)] ++ suspendSuspicious())
398- else [Reissue(shareAssetId, shareInitialSupply, true), IntegerEntry(keyBalanceA, pmtAmountA), IntegerEntry(keyBalanceB, pmtAmountB), IntegerEntry(keyShareAssetSupply, shareInitialSupply), ScriptTransfer(i.caller, shareInitialSupply, shareAssetId)]
399- }
400- }
401- else {
402- let tokenRatio = fraction(fraction(balanceA, scaleValue8, pmtAmountA), scaleValue3, fraction(balanceB, scaleValue8, pmtAmountB))
403- let ratioShareTokensInA = fraction(pmtAmountA, scaleValue8, balanceA)
404- let ratioShareTokensInB = fraction(pmtAmountB, scaleValue8, balanceB)
405- let shareTokenToPayAmount = fraction(min([ratioShareTokensInA, ratioShareTokensInB]), shareAssetSupply, scaleValue8)
406- if (!(isActive))
407- then throw("DApp is inactive at this moment")
408- else if (if ((0 > slippageTolerance))
409- then true
410- else (slippageTolerance > slippageToleranceDelimiter))
411- then throw(((("Slippage tolerance must be between 0 and " + toString(slippageToleranceDelimiter)) + " inclusively. Actual: ") + toString(slippageTolerance)))
412- else if ((size(i.payments) != 2))
413- then throw("Two attached assets expected")
414- else if (if ((pmtAssetIdA != assetIdA))
415- then true
416- else (pmtAssetIdB != assetIdB))
417- then throw(((("Incorrect assets attached. Expected: " + strAssetIdA) + " and ") + strAssetIdB))
418- else if (if ((((scaleValue3 * (slippageToleranceDelimiter - slippageTolerance)) / slippageToleranceDelimiter) > tokenRatio))
419- then true
420- else (tokenRatio > ((scaleValue3 * (slippageToleranceDelimiter + slippageTolerance)) / slippageToleranceDelimiter)))
421- then throw("Incorrect assets amount: amounts must have the contract ratio")
422- else if ((shareTokenToPayAmount == 0))
423- then throw("Too small amount to replenish")
424- else if (!(hasEnoughBalance))
425- then ([ScriptTransfer(i.caller, pmtAmountA, pmtAssetIdA), ScriptTransfer(i.caller, pmtAmountB, pmtAssetIdB)] ++ suspendSuspicious())
426- else [IntegerEntry(keyBalanceA, (balanceA + pmtAmountA)), IntegerEntry(keyBalanceB, (balanceB + pmtAmountB)), IntegerEntry(keyShareAssetSupply, (shareAssetSupply + shareTokenToPayAmount)), Reissue(shareAssetId, shareTokenToPayAmount, true), ScriptTransfer(i.caller, shareTokenToPayAmount, shareAssetId)]
427- }
427+ else (dAppThresholdAmount > newBalanceB))
428+ then throwThreshold(dAppThresholdAmount, newBalanceA, newBalanceB)
429+ else {
430+ let ratioShareTokensInA = fraction(deductStakingFee(virtualReplenishA, assetIdA), scale8, balanceAfterSwapA)
431+ let ratioShareTokensInB = fraction(deductStakingFee(virtualReplenishB, assetIdB), scale8, balanceAfterSwapB)
432+ let shareTokenToPayAmount = fraction(min([ratioShareTokensInA, ratioShareTokensInB]), shareAssetSupply, scale8)
433+[Reissue(shareAssetId, shareTokenToPayAmount, true), ScriptTransfer(i.caller, shareTokenToPayAmount, shareAssetId), IntegerEntry(kShareAssetSupply, (shareAssetSupply + shareTokenToPayAmount)), newBalanceEntry, IntegerEntry(kInvariant, invariantCalculated)]
434+ }
435+ }
428436 }
429437
430438
431439
432440 @Callable(i)
433441 func withdraw () = {
434- let $t01803118181 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
435- let pmtAmount = $t01803118181._1
436- let pmtAssetId = $t01803118181._2
437- let amountToPayA = deductStakingFee(fraction(pmtAmount, balanceA, shareAssetSupply), assetIdA, assetIdB)
438- let amountToPayB = deductStakingFee(fraction(pmtAmount, balanceB, shareAssetSupply), assetIdB, assetIdA)
442+ let $t01743117574 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
443+ let pmtAmount = $t01743117574._1
444+ let pmtAssetId = $t01743117574._2
445+ let amountToPayA = deductStakingFee(fraction(pmtAmount, balanceA, shareAssetSupply), assetIdA)
446+ let amountToPayB = deductStakingFee(fraction(pmtAmount, balanceB, shareAssetSupply), assetIdB)
447+ let invariantCalculated = invariantCalc((balanceA - amountToPayA), (balanceB - amountToPayB))
439448 if (!(isActive))
440- then throw("DApp is inactive at this moment")
449+ then throwIsInactive()
441450 else if ((size(i.payments) != 1))
442451 then throw("One attached payment expected")
443452 else if ((pmtAssetId != shareAssetId))
448457 then true
449458 else (amountToPayB > availableBalanceB))
450459 then throwInsufficientAvailableBalances(amountToPayA, amountToPayB)
451- else [IntegerEntry(keyBalanceA, (balanceA - amountToPayA)), IntegerEntry(keyBalanceB, (balanceB - amountToPayB)), IntegerEntry(keyShareAssetSupply, (shareAssetSupply - pmtAmount)), Burn(shareAssetId, pmtAmount), ScriptTransfer(i.caller, amountToPayA, assetIdA), ScriptTransfer(i.caller, amountToPayB, assetIdB)]
460+ else [IntegerEntry(kBalanceA, (balanceA - amountToPayA)), IntegerEntry(kBalanceB, (balanceB - amountToPayB)), IntegerEntry(kShareAssetSupply, (shareAssetSupply - pmtAmount)), IntegerEntry(kInvariant, invariantCalculated), Burn(shareAssetId, pmtAmount), ScriptTransfer(i.caller, amountToPayA, assetIdA), ScriptTransfer(i.caller, amountToPayB, assetIdB)]
452461 }
453462
454463
455464
456465 @Callable(i)
457-func exchange (minAmountToReceive) = {
458- let $t01940719482 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
459- let pmtAmount = $t01940719482._1
460- let pmtAssetId = $t01940719482._2
461- func calculateFees (tokenFrom,tokenTo) = {
462- let amountWithoutFee = fraction(tokenTo, pmtAmount, (pmtAmount + tokenFrom))
463- let amountWithFee = fraction(amountWithoutFee, (commissionScaleDelimiter - commission), commissionScaleDelimiter)
464- let governanceReward = fraction(amountWithoutFee, commissionGovernance, commissionScaleDelimiter)
465- if ((minAmountToReceive > amountWithFee))
466- then throw(((("Calculated amount to receive " + toString(amountWithFee)) + " is less than specified minimum ") + toString(minAmountToReceive)))
467- else $Tuple3(amountWithoutFee, amountWithFee, governanceReward)
468- }
469-
466+func exchange (estimatedAmountToReceive,minAmountToReceive) = {
467+ let $t01893219007 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
468+ let pmtAmount = $t01893219007._1
469+ let pmtAssetId = $t01893219007._2
470470 if (!(isActive))
471- then throw("DApp is inactive at this moment")
472- else if (if ((balanceA == 0))
473- then true
474- else (balanceB == 0))
475- then throw("Can't exchange with zero balance")
476- else if ((0 >= minAmountToReceive))
477- then throw(("Minimal amount to receive must be positive. Actual: " + toString(minAmountToReceive)))
471+ then throwIsInactive()
472+ else if ((0 >= estimatedAmountToReceive))
473+ then throw(("Estimated amount must be positive. Actual: " + toString(estimatedAmountToReceive)))
474+ else if ((minAmountToReceive > estimatedAmountToReceive))
475+ then throw(((("Minimal amount can't be greater than estimated. Estimated: " + toString(estimatedAmountToReceive)) + ". Minimal: ") + toString(minAmountToReceive)))
478476 else if ((size(i.payments) != 1))
479477 then throw("One attached payment expected")
480478 else if (!(hasEnoughBalance))
481479 then ([ScriptTransfer(i.caller, pmtAmount, pmtAssetId)] ++ suspendSuspicious())
482- else if ((pmtAssetId == assetIdA))
483- then {
484- let assetIdSend = assetIdB
485- let $t02075620847 = calculateFees(balanceA, balanceB)
486- let amountWithoutFee = $t02075620847._1
487- let amountWithFee = $t02075620847._2
488- let governanceReward = $t02075620847._3
489- let newBalanceA = (balanceA + pmtAmount)
490- let newBalanceB = ((balanceB - amountWithFee) - governanceReward)
491- if (if ((stakedAmountA >= newBalanceA))
480+ else if (if ((pmtAssetId != assetIdA))
481+ then (pmtAssetId != assetIdB)
482+ else false)
483+ then throwAssets()
484+ else if ((10000000 > pmtAmount))
485+ then throw("Only swap of 10.000000 or more tokens is allowed")
486+ else if (if ((exchangeRatioLimitMin > fraction(scale8, minAmountToReceive, pmtAmount)))
492487 then true
493- else (stakedAmountB >= newBalanceB))
494- then throwInsufficientAvailableBalance(amountWithFee, availableBalanceB, assetNameB)
495- else $Tuple2([IntegerEntry(keyBalanceA, newBalanceA), IntegerEntry(keyBalanceB, newBalanceB), ScriptTransfer(i.caller, amountWithFee, assetIdSend), ScriptTransfer(walletAddress, governanceReward, assetIdSend)], $Tuple2(amountWithFee, assetIdSend))
496- }
497- else if ((pmtAssetId == assetIdB))
498- then {
499- let assetIdSend = assetIdA
500- let $t02170921800 = calculateFees(balanceB, balanceA)
501- let amountWithoutFee = $t02170921800._1
502- let amountWithFee = $t02170921800._2
503- let governanceReward = $t02170921800._3
504- let newBalanceA = ((balanceA - amountWithFee) - governanceReward)
505- let newBalanceB = (balanceB + pmtAmount)
506- if (if ((stakedAmountA >= newBalanceA))
507- then true
508- else (stakedAmountB >= newBalanceB))
509- then throwInsufficientAvailableBalance(amountWithFee, availableBalanceA, assetNameA)
510- else $Tuple2([IntegerEntry(keyBalanceA, newBalanceA), IntegerEntry(keyBalanceB, newBalanceB), ScriptTransfer(i.caller, amountWithFee, assetIdSend), ScriptTransfer(walletAddress, governanceReward, assetIdSend)], $Tuple2(amountWithFee, assetIdSend))
511- }
512- else throw(((("Incorrect asset attached. Expected: " + strAssetIdA) + " or ") + strAssetIdB))
488+ else (fraction(scale8, estimatedAmountToReceive, pmtAmount) > exchangeRatioLimitMax))
489+ then throw("Incorrect args and pmt ratio")
490+ else {
491+ let sendAssetId = if ((pmtAssetId == assetIdA))
492+ then assetIdB
493+ else assetIdA
494+ let amount = calculateSendAmount(estimatedAmountToReceive, minAmountToReceive, pmtAmount, pmtAssetId)
495+ let governanceReward = fraction(amount, feeGovernance, feeScale6)
496+ let amountMinusFee = fraction(amount, (feeScale6 - fee), feeScale6)
497+ let $t02042920691 = if ((pmtAssetId == assetIdA))
498+ then $Tuple2((balanceA + pmtAmount), ((balanceB - amountMinusFee) - governanceReward))
499+ else $Tuple2(((balanceA - amountMinusFee) - governanceReward), (balanceB + pmtAmount))
500+ let newBalanceA = $t02042920691._1
501+ let newBalanceB = $t02042920691._2
502+ let dAppThresholdAmount = fraction((newBalanceA + newBalanceB), dAppThreshold, (2 * dAppThresholdScale2))
503+ if (if ((dAppThresholdAmount > newBalanceA))
504+ then true
505+ else (dAppThresholdAmount > newBalanceB))
506+ then throwThreshold(dAppThresholdAmount, newBalanceA, newBalanceB)
507+ else if (if (if ((assetIdA == USDN))
508+ then (sendAssetId == assetIdA)
509+ else false)
510+ then (stakedAmountUSDN >= newBalanceA)
511+ else false)
512+ then throwInsufficientAvailableBalance(amountMinusFee, availableBalanceA, assetNameA)
513+ else if (if (if ((assetIdB == USDN))
514+ then (sendAssetId == assetIdB)
515+ else false)
516+ then (stakedAmountUSDN >= newBalanceB)
517+ else false)
518+ then throwInsufficientAvailableBalance(amountMinusFee, availableBalanceB, assetNameB)
519+ else $Tuple2([IntegerEntry(kBalanceA, newBalanceA), IntegerEntry(kBalanceB, newBalanceB), IntegerEntry(kInvariant, invariantCalc(newBalanceA, newBalanceB)), ScriptTransfer(i.caller, amountMinusFee, sendAssetId), ScriptTransfer(govAddr, governanceReward, sendAssetId)], $Tuple2(amountMinusFee, sendAssetId))
520+ }
513521 }
514522
515523
516524
517525 @Callable(i)
518526 func shutdown () = if (!(isActive))
519- then throw(("DApp is already suspended. Cause: " + valueOrElse(getString(this, keyCause), "the cause wasn't specified")))
520- else if (!(containsElement([adminPubKey1, adminPubKey2, adminPubKey3, adminPubKeyStartStop], i.callerPublicKey)))
521- then throw("Only admin can call this function")
527+ then throw(("DApp is already suspended. Cause: " + valueOrElse(getString(this, kCause), "the cause wasn't specified")))
528+ else if (!(containsElement([adminPubKey1, adminPubKey2, adminPubKey3, admStartStop], i.callerPublicKey)))
529+ then throwOnlyAdmin()
522530 else suspend("Paused by admin")
523531
524532
525533
526534 @Callable(i)
527535 func activate () = if (isActive)
528- then throw("DApp is already active")
529- else if (!(containsElement([adminPubKey1, adminPubKey2, adminPubKey3, adminPubKeyStartStop], i.callerPublicKey)))
530- then throw("Only admin can call this function")
531- else [BooleanEntry(keyActive, true), DeleteEntry(keyCause)]
536+ then throwIsActive()
537+ else if (!(containsElement([adminPubKey1, adminPubKey2, adminPubKey3, admStartStop], i.callerPublicKey)))
538+ then throwOnlyAdmin()
539+ else [BooleanEntry(kActive, true), DeleteEntry(kCause)]
532540
533541
534542
535543 @Callable(i)
536544 func takeIntoAccountExtraFunds (amountLeave) = {
537- let uncountableAmountEnrollAssetA = (accountBalanceWithStakedA - balanceA)
538- let uncountableAmountEnrollAssetB = (accountBalanceWithStakedB - balanceB)
539- let amountEnrollA = (uncountableAmountEnrollAssetA - (if ((assetIdA == unit))
545+ let uncountableA = (accountBalanceWithStakedA - balanceA)
546+ let uncountableB = (accountBalanceWithStakedB - balanceB)
547+ let amountEnrollA = (uncountableA - (if ((assetIdA == unit))
540548 then amountLeave
541549 else 0))
542- let amountEnrollB = (uncountableAmountEnrollAssetB - (if ((assetIdB == unit))
550+ let amountEnrollB = (uncountableB - (if ((assetIdB == unit))
543551 then amountLeave
544552 else 0))
553+ let invariantNew = invariantCalc((balanceA + amountEnrollA), (balanceB + amountEnrollB))
545554 if (!(isActive))
546- then throw("DApp is inactive at this moment")
555+ then throwIsInactive()
547556 else if ((i.caller != this))
548- then throw("Only the DApp itself can call this function")
557+ then throwOnlyAdmin()
549558 else if ((0 > amountLeave))
550559 then throw(("Argument 'amountLeave' cannot be negative. Actual: " + toString(amountLeave)))
551- else if (if ((0 > uncountableAmountEnrollAssetA))
560+ else if (if ((0 > uncountableA))
552561 then true
553- else (0 > uncountableAmountEnrollAssetB))
562+ else (0 > uncountableB))
554563 then suspend("Enroll amount negative")
555564 else if (if ((0 > amountEnrollA))
556565 then true
557566 else (0 > amountEnrollB))
558567 then throw("Too large amountLeave")
559- else [IntegerEntry(keyBalanceA, (balanceA + amountEnrollA)), IntegerEntry(keyBalanceB, (balanceB + amountEnrollB)), IntegerEntry(("last_income_" + strAssetIdA), amountEnrollA), IntegerEntry(("last_income_" + strAssetIdB), amountEnrollB)]
568+ else [IntegerEntry(kInvariant, invariantNew), IntegerEntry(kBalanceA, (balanceA + amountEnrollA)), IntegerEntry(kBalanceB, (balanceB + amountEnrollB)), IntegerEntry(("last_income_" + strAssetIdA), amountEnrollA), IntegerEntry(("last_income_" + strAssetIdB), amountEnrollB)]
560569 }
561570
562571
Full:
OldNewDifferences
11 {-# STDLIB_VERSION 5 #-}
22 {-# SCRIPT_TYPE ACCOUNT #-}
33 {-# CONTENT_TYPE DAPP #-}
4-let version = "1.0.0"
4+let version = "2.0.0"
55
6-let keyVersion = "version"
6+let kVersion = "version"
77
8-let keyActive = "active"
8+let kActive = "active"
99
10-let keyAssetIdA = "A_asset_id"
10+let kAssetIdA = "A_asset_id"
1111
12-let keyAssetIdB = "B_asset_id"
12+let kAssetIdB = "B_asset_id"
1313
14-let keyBalanceA = "A_asset_balance"
14+let kBalanceA = "A_asset_balance"
1515
16-let keyBalanceB = "B_asset_balance"
16+let kBalanceB = "B_asset_balance"
1717
18-let keyBalanceInitA = "A_asset_init"
18+let kShareAssetId = "share_asset_id"
1919
20-let keyBalanceInitB = "B_asset_init"
20+let kShareAssetSupply = "share_asset_supply"
2121
22-let keyShareAssetId = "share_asset_id"
22+let kFee = "commission"
2323
24-let keyShareAssetSupply = "share_asset_supply"
24+let kFeeScaleDelimiter = "commission_scale_delimiter"
2525
26-let keyCommission = "commission"
26+let kInvariant = "invariant"
2727
28-let keyCommissionScaleDelimiter = "commission_scale_delimiter"
29-
30-let keyCause = "shutdown_cause"
31-
32-let keyFirstHarvest = "first_harvest"
33-
34-let keyFirstHarvestHeight = "first_harvest_height"
35-
36-let kShareLimit = "share_limit_on_first_harvest"
37-
38-let kBasePeriod = "base_period"
39-
40-let kPeriodLength = "period_length"
41-
42-let kStartHeight = "start_height"
43-
44-let kFirstHarvestHeight = "first_harvest_height"
28+let kCause = "shutdown_cause"
4529
4630 let keyAdminPubKey1 = "admin_pub_1"
4731
4832 let keyAdminPubKey2 = "admin_pub_2"
4933
5034 let keyAdminPubKey3 = "admin_pub_3"
35+
36+let USDNToWavesExchanger = Address(base58'3PHaNgomBkrvEL2QnuJarQVJa71wjw9qiqG')
5137
5238 let oracle = Address(base58'3PEbqViERCoKnmcSULh6n2aiMvUdSQdCsom')
5339
5440 func getAdminPub (keyAdminPub) = match getString(oracle, keyAdminPub) {
5541 case string: String =>
5642 fromBase58String(string)
5743 case nothing =>
5844 throw("Admin public key is empty")
5945 }
6046
6147
6248 let adminPubKey1 = getAdminPub(keyAdminPubKey1)
6349
6450 let adminPubKey2 = getAdminPub(keyAdminPubKey2)
6551
6652 let adminPubKey3 = getAdminPub(keyAdminPubKey3)
6753
68-let adminPubKeyStartStop = base58'EtVkT6ed8GtbUiVVEqdmEqsp2J4qbb3rre2HFgxeVYdg'
54+let admStartStop = base58'EtVkT6ed8GtbUiVVEqdmEqsp2J4qbb3rre2HFgxeVYdg'
6955
70-let adminPubKeyStaking = base58'Czn4yoAuUZCVCLJDRfskn8URfkwpknwBTZDbs1wFrY7h'
56+let admStaking = base58'Czn4yoAuUZCVCLJDRfskn8URfkwpknwBTZDbs1wFrY7h'
7157
72-let walletAddress = Address(base58'3N7cz2aJBxu3DpGVZnaHj8J479JBiEhdqsw')
58+let govAddr = Address(base58'3P6J84oH51DzY6xk2mT5TheXRbrCwBMxonp')
7359
74-let votingAddress = Address(base58'3N7cz2aJBxu3DpGVZnaHj8J479JBiEhdqsw')
60+let stakingAddress = Address(base58'3PNikM6yp4NqcSU8guxQtmR5onr2D4e8yTJ')
7561
7662 let USDN = base58'DG2xFkPdDwKUoBkzGAhQtLpSGzfXLiCYPEzeKH2Ad24p'
7763
78-let NSBT = base58'6nSpVyNH7yM69eg446wrQR94ipbbcmZMU1ENPwanC97g'
79-
80-let SWOP = base58'Ehie5xYpeN8op1Cctc6aGUrqx8jq3jtf1DSjXDbfm7aT'
81-
82-let EURN = base58'DUk2YTxhRoAqMJLus4G2b3fR8hMHVh6eiyFx5r29VR6t'
83-
84-let stakingUSDNNSBTAddress = Address(base58'3PNikM6yp4NqcSU8guxQtmR5onr2D4e8yTJ')
85-
86-let stakingEURNAddress = Address(base58'3PFhcMmEZoQTQ6ohA844c7C9M8ZJ18P8dDj')
87-
88-let USDNToWavesExchanger = Address(base58'3PHaNgomBkrvEL2QnuJarQVJa71wjw9qiqG')
89-
90-let USDNToNSBTExchanger = Address(base58'3P2V63Xd6BviDkeMzxhUw2SJyojByRz8a8m')
91-
9264 let stakingFeeInUSDN = 270000
9365
94-let stakingFeeInEURN = 234000
66+let isActive = getBooleanValue(this, kActive)
9567
96-let basePeriod = valueOrErrorMessage(getInteger(votingAddress, kBasePeriod), "Empty kBasePeriod")
68+let strAssetIdA = getStringValue(this, kAssetIdA)
9769
98-let startHeight = valueOrErrorMessage(getInteger(votingAddress, kStartHeight), "Empty kStartHeight")
99-
100-let periodLength = valueOrErrorMessage(getInteger(votingAddress, kPeriodLength), "Empty kPeriodLength")
101-
102-let firstHarvestEndPeriod = ((basePeriod + ((height - startHeight) / periodLength)) + 3)
103-
104-let isActive = getBooleanValue(this, keyActive)
105-
106-let strAssetIdA = getStringValue(this, keyAssetIdA)
107-
108-let strAssetIdB = getStringValue(this, keyAssetIdB)
70+let strAssetIdB = getStringValue(this, kAssetIdB)
10971
11072 let assetIdA = if ((strAssetIdA == "WAVES"))
11173 then unit
11274 else fromBase58String(strAssetIdA)
11375
11476 let assetIdB = if ((strAssetIdB == "WAVES"))
11577 then unit
11678 else fromBase58String(strAssetIdB)
11779
11880 let assetNameA = match assetIdA {
11981 case id: ByteVector =>
12082 value(assetInfo(id)).name
12183 case waves: Unit =>
12284 "WAVES"
12385 case _ =>
12486 throw("Match error")
12587 }
12688
12789 let assetNameB = match assetIdB {
12890 case id: ByteVector =>
12991 value(assetInfo(id)).name
13092 case waves: Unit =>
13193 "WAVES"
13294 case _ =>
13395 throw("Match error")
13496 }
13597
136-let balanceA = getIntegerValue(this, keyBalanceA)
98+let balanceA = getIntegerValue(this, kBalanceA)
13799
138-let balanceB = getIntegerValue(this, keyBalanceB)
100+let balanceB = getIntegerValue(this, kBalanceB)
139101
140-let shareAssetId = fromBase58String(getStringValue(this, keyShareAssetId))
102+let shareAssetId = fromBase58String(getStringValue(this, kShareAssetId))
141103
142-let shareAssetSupply = getIntegerValue(this, keyShareAssetSupply)
104+let shareAssetSupply = getIntegerValue(this, kShareAssetSupply)
143105
144-let commission = 3000
106+let invariant = getIntegerValue(this, kInvariant)
145107
146-let commissionGovernance = 1200
108+let fee = 500
147109
148-let commissionScaleDelimiter = 1000000
110+let feeGovernance = 200
149111
150-let scaleValue3 = 1000
112+let feeScale6 = 1000000
151113
152-let scaleValue8 = 100000000
114+let scale3 = 1000
153115
154-let slippageToleranceDelimiter = 1000
116+let scale8 = 100000000
155117
156-let scaleValue8Digits = 8
118+let scale12 = 1000000000000
119+
120+let slippageScale3 = 1000
121+
122+let digits8 = 8
123+
124+let dAppThreshold = 50
125+
126+let dAppThresholdScale2 = 100
127+
128+let exchangeRatioLimitMin = 90000000
129+
130+let exchangeRatioLimitMax = 110000000
131+
132+let alpha = 50
133+
134+let alphaDigits = 2
135+
136+let beta = 46000000
157137
158138 func accountBalance (assetId) = match assetId {
159139 case id: ByteVector =>
160140 assetBalance(this, id)
161141 case waves: Unit =>
162142 wavesBalance(this).available
163143 case _ =>
164144 throw("Match error")
165145 }
166146
167147
168-func stakedAmount (assetId) = {
169- let stakedAmountCalculated = match assetId {
170- case aId: ByteVector =>
171- if (if ((aId == USDN))
172- then true
173- else (aId == NSBT))
174- then getInteger(stakingUSDNNSBTAddress, ((("rpd_balance_" + toBase58String(aId)) + "_") + toString(this)))
175- else if ((aId == EURN))
176- then getInteger(stakingEURNAddress, ((("%s%s%s__stakingBalance__" + toBase58String(aId)) + "__") + toString(this)))
177- else 0
178- case _: Unit =>
179- 0
180- case _ =>
181- throw("Match error")
182- }
183- match stakedAmountCalculated {
184- case i: Int =>
185- i
186- case _ =>
187- 0
188- }
189- }
148+let stakedAmountUSDN = match getInteger(stakingAddress, ((("rpd_balance_" + toBase58String(USDN)) + "_") + toString(this))) {
149+ case staked: Int =>
150+ staked
151+ case nothing: Unit =>
152+ 0
153+ case _ =>
154+ throw("Match error")
155+}
190156
157+let availableBalanceA = (balanceA - (if ((assetIdA == USDN))
158+ then stakedAmountUSDN
159+ else 0))
191160
192-let stakedAmountA = stakedAmount(assetIdA)
161+let availableBalanceB = (balanceB - (if ((assetIdB == USDN))
162+ then stakedAmountUSDN
163+ else 0))
193164
194-let stakedAmountB = stakedAmount(assetIdB)
165+let accountBalanceWithStakedA = (accountBalance(assetIdA) + (if ((assetIdA == USDN))
166+ then stakedAmountUSDN
167+ else 0))
195168
196-let assetInitA = getIntegerValue(this, keyBalanceInitA)
197-
198-let assetInitB = getIntegerValue(this, keyBalanceInitB)
199-
200-let availableBalanceA = (balanceA - stakedAmountA)
201-
202-let availableBalanceB = (balanceB - stakedAmountB)
203-
204-let accountBalanceWithStakedA = (accountBalance(assetIdA) + stakedAmountA)
205-
206-let accountBalanceWithStakedB = (accountBalance(assetIdB) + stakedAmountB)
169+let accountBalanceWithStakedB = (accountBalance(assetIdB) + (if ((assetIdB == USDN))
170+ then stakedAmountUSDN
171+ else 0))
207172
208173 let hasEnoughBalance = if ((accountBalanceWithStakedA >= balanceA))
209174 then (accountBalanceWithStakedB >= balanceB)
210175 else false
176+
177+func skewness (x,y) = (((fraction(scale12, x, y) + fraction(scale12, y, x)) / 2) / 10000)
178+
179+
180+func invariantCalc (x,y) = {
181+ let sk = skewness(x, y)
182+ (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)))
183+ }
184+
185+
186+func calculateSendAmount (amountToSendEstimated,minTokenReceiveAmount,tokenReceiveAmount,tokenId) = {
187+ let slippageValue = (scale8 - ((scale8 * 1) / 10000000))
188+ let deltaBetweenMaxAndMinSendValue = (amountToSendEstimated - minTokenReceiveAmount)
189+ let x = (balanceA + tokenReceiveAmount)
190+ let y = (balanceB + tokenReceiveAmount)
191+ let invariantNew = if ((tokenId == assetIdA))
192+ then invariantCalc(x, (balanceB - amountToSendEstimated))
193+ else if ((tokenId == assetIdB))
194+ then invariantCalc((balanceA - amountToSendEstimated), y)
195+ else throw("Wrong asset in payment")
196+ let invariantEstimatedRatio = fraction(scale8, invariant, invariantNew)
197+ func getStepAmount (acc,step) = if ((acc == -1))
198+ then {
199+ let amountToSend = (amountToSendEstimated - ((step * deltaBetweenMaxAndMinSendValue) / 5))
200+ let stepInvariant = if ((tokenId == assetIdA))
201+ then invariantCalc(x, (balanceB - amountToSend))
202+ else invariantCalc((balanceA - amountToSend), y)
203+ if ((stepInvariant > invariant))
204+ then amountToSend
205+ else -1
206+ }
207+ else acc
208+
209+ let stepAmount = {
210+ let $list60496092 = [1, 2, 3, 4, 5]
211+ let $size60496092 = size($list60496092)
212+ let $acc060496092 = -1
213+ if (($size60496092 == 0))
214+ then $acc060496092
215+ else {
216+ let $acc160496092 = getStepAmount($acc060496092, $list60496092[0])
217+ if (($size60496092 == 1))
218+ then $acc160496092
219+ else {
220+ let $acc260496092 = getStepAmount($acc160496092, $list60496092[1])
221+ if (($size60496092 == 2))
222+ then $acc260496092
223+ else {
224+ let $acc360496092 = getStepAmount($acc260496092, $list60496092[2])
225+ if (($size60496092 == 3))
226+ then $acc360496092
227+ else {
228+ let $acc460496092 = getStepAmount($acc360496092, $list60496092[3])
229+ if (($size60496092 == 4))
230+ then $acc460496092
231+ else {
232+ let $acc560496092 = getStepAmount($acc460496092, $list60496092[4])
233+ if (($size60496092 == 5))
234+ then $acc560496092
235+ else {
236+ let $acc660496092 = getStepAmount($acc560496092, $list60496092[5])
237+ throw("List size exceed 5")
238+ }
239+ }
240+ }
241+ }
242+ }
243+ }
244+ }
245+ if ((0 > stepAmount))
246+ then throw("something went wrong while working with amountToSend")
247+ else if (if ((invariantEstimatedRatio > slippageValue))
248+ then (invariantNew > invariant)
249+ else false)
250+ then amountToSendEstimated
251+ else stepAmount
252+ }
253+
211254
212255 func getAssetInfo (assetId) = match assetId {
213256 case id: ByteVector =>
214257 let stringId = toBase58String(id)
215258 let info = valueOrErrorMessage(assetInfo(id), (("Asset " + stringId) + " doesn't exist"))
216259 $Tuple3(stringId, info.name, info.decimals)
217260 case waves: Unit =>
218261 $Tuple3("WAVES", "WAVES", 8)
219262 case _ =>
220263 throw("Match error")
221264 }
222265
223266
224-func getAssetInfoFromString (assetStr) = if ((assetStr == "WAVES"))
225- then $Tuple3("WAVES", "WAVES", 8)
226- else {
227- let stringId = assetStr
228- let id = fromBase58String(assetStr)
229- let info = valueOrErrorMessage(assetInfo(id), (("Asset " + stringId) + " doesn't exist"))
230- $Tuple3(stringId, info.name, info.decimals)
231- }
267+func suspend (cause) = [BooleanEntry(kActive, false), StringEntry(kCause, cause)]
232268
233269
234-func suspend (cause) = [BooleanEntry(keyActive, false), StringEntry(keyCause, cause)]
235-
236-
237-func deductStakingFee (amount,assetId,secondAssetId) = if (if ((assetId == USDN))
238- then true
239- else (assetId == EURN))
270+func deductStakingFee (amount,assetId) = if ((assetId == USDN))
240271 then {
241- let stakinFee = if ((assetId == USDN))
242- then (stakingFeeInUSDN * (if ((secondAssetId == NSBT))
243- then 2
244- else 1))
245- else if ((assetId == EURN))
246- then stakingFeeInEURN
247- else 0
248- let result = (amount - stakinFee)
272+ let result = (amount - stakingFeeInUSDN)
249273 if ((0 >= result))
250- then throw((((("Insufficient amount " + toString(amount)) + " to deduct staking fee ") + toString(stakinFee)) + "USDN/EURN"))
274+ then throw((((("Insufficient amount " + toString(amount)) + " to deduct staking fee ") + toString(stakingFeeInUSDN)) + " USD-N"))
251275 else result
252276 }
253277 else amount
254278
255279
256-func getStakingFee (assetId,secondAssetId) = if ((assetId == USDN))
257- then (stakingFeeInUSDN * (if ((secondAssetId == NSBT))
258- then 2
259- else 1))
260- else if ((assetId == EURN))
261- then stakingFeeInEURN
262- else 0
280+func throwIsActive () = throw("DApp is already active")
281+
282+
283+func throwIsInactive () = throw("DApp is inactive at this moment")
284+
285+
286+func throwOnlyAdmin () = throw("Only admin can call this function")
287+
288+
289+func throwAssets () = throw(((("Incorrect assets attached. Expected: " + strAssetIdA) + " and ") + strAssetIdB))
290+
291+
292+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))
263293
264294
265295 func throwInsufficientAvailableBalance (amount,available,assetName) = throw((((((((("Insufficient DApp balance to pay " + toString(amount)) + " ") + assetName) + " due to staking. Available: ") + toString(available)) + " ") + assetName) + ". Please contact support in Telegram: https://t.me/swopfisupport"))
266296
267297
268298 func throwInsufficientAvailableBalances (amountA,amountB) = throw((((((((((((((((("Insufficient DApp balance to pay " + toString(amountA)) + " ") + assetNameA) + " and ") + toString(amountB)) + " ") + assetNameB) + " due to staking. Available: ") + toString(availableBalanceA)) + " ") + assetNameA) + " and ") + toString(availableBalanceB)) + " ") + assetNameB) + ". Please contact support in Telegram: https://t.me/swopfisupport"))
269299
270300
271-func suspendSuspicious () = suspend(((((((((((((((("Suspicious state. Actual balances: " + toString(accountBalanceWithStakedA)) + " ") + assetNameA) + ", ") + toString(accountBalanceWithStakedB)) + " ") + assetNameB) + ". State: ") + toString(balanceA)) + " ") + assetNameA) + ", ") + toString(balanceB)) + " ") + assetNameB))
301+func suspendSuspicious () = suspend(((((((((((((((("Suspicious state. Actual balances: " + toString(balanceA)) + " ") + assetNameA) + ", ") + toString(balanceB)) + " ") + assetNameB) + ". State: ") + toString(accountBalance(assetIdA))) + " ") + assetNameA) + ", ") + toString(accountBalance(assetIdB))) + " ") + assetNameB))
272302
273303
274304 @Callable(i)
275-func init (firstHarvest) = {
276- let $t080008077 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
277- let pmtAmountA = $t080008077._1
278- let pmtAssetIdA = $t080008077._2
279- let $t080828159 = $Tuple2(i.payments[1].amount, i.payments[1].assetId)
280- let pmtAmountB = $t080828159._1
281- let pmtAssetIdB = $t080828159._2
282- let $t081648241 = getAssetInfo(pmtAssetIdA)
283- let pmtStrAssetIdA = $t081648241._1
284- let pmtAssetNameA = $t081648241._2
285- let pmtDecimalsA = $t081648241._3
286- let $t082468502 = getAssetInfo(pmtAssetIdB)
287- let pmtStrAssetIdB = $t082468502._1
288- let pmtAssetNameB = $t082468502._2
289- let pmtDecimalsB = $t082468502._3
290- if (isDefined(getBoolean(this, keyActive)))
291- then throw("DApp is already active")
305+func init () = {
306+ let $t087688845 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
307+ let pmtAmountA = $t087688845._1
308+ let pmtAssetIdA = $t087688845._2
309+ let $t088508927 = $Tuple2(i.payments[1].amount, i.payments[1].assetId)
310+ let pmtAmountB = $t088508927._1
311+ let pmtAssetIdB = $t088508927._2
312+ let $t089329009 = getAssetInfo(pmtAssetIdA)
313+ let pmtStrAssetIdA = $t089329009._1
314+ let pmtAssetNameA = $t089329009._2
315+ let pmtDecimalsA = $t089329009._3
316+ let $t090149091 = getAssetInfo(pmtAssetIdB)
317+ let pmtStrAssetIdB = $t090149091._1
318+ let pmtAssetNameB = $t090149091._2
319+ let pmtDecimalsB = $t090149091._3
320+ if (isDefined(getBoolean(this, kActive)))
321+ then throwIsActive()
292322 else if ((pmtAssetIdA == pmtAssetIdB))
293323 then throw("Assets must be different")
294324 else {
295325 let shareName = ((("s" + take(pmtAssetNameA, 7)) + "_") + take(pmtAssetNameB, 7))
296326 let shareDescription = ((((("ShareToken of SwopFi protocol for " + pmtAssetNameA) + " and ") + pmtAssetNameB) + " at address ") + toString(this))
297327 let shareDecimals = ((pmtDecimalsA + pmtDecimalsB) / 2)
298- let arg1 = pow(pmtAmountA, pmtDecimalsA, 5, 1, pmtDecimalsA, DOWN)
299- let arg2 = pow(pmtAmountB, pmtDecimalsB, 5, 1, pmtDecimalsB, DOWN)
300- let arg3 = pow(10, 0, shareDecimals, 0, 0, DOWN)
301- let shareInitialSupply = fraction(arg1, arg2, arg3)
328+ let shareInitialSupply = fraction(pow(pmtAmountA, pmtDecimalsA, 5, 1, pmtDecimalsA, DOWN), pow(pmtAmountB, pmtDecimalsB, 5, 1, pmtDecimalsB, DOWN), pow(10, 0, shareDecimals, 0, 0, DOWN))
302329 let shareIssue = Issue(shareName, shareDescription, shareInitialSupply, shareDecimals, true)
303330 let shareIssueId = calculateAssetId(shareIssue)
304- let baseEntry = [StringEntry(keyVersion, version), BooleanEntry(keyActive, true), StringEntry(keyAssetIdA, pmtStrAssetIdA), StringEntry(keyAssetIdB, pmtStrAssetIdB), IntegerEntry(keyBalanceA, pmtAmountA), IntegerEntry(keyBalanceB, pmtAmountB), IntegerEntry(keyCommission, commission), IntegerEntry(keyCommissionScaleDelimiter, commissionScaleDelimiter), shareIssue, StringEntry(keyShareAssetId, toBase58String(shareIssueId)), IntegerEntry(keyShareAssetSupply, shareInitialSupply), ScriptTransfer(i.caller, shareInitialSupply, shareIssueId)]
305- if (firstHarvest)
306- then (baseEntry ++ [BooleanEntry(keyFirstHarvest, firstHarvest), IntegerEntry(keyFirstHarvestHeight, (startHeight + (firstHarvestEndPeriod * periodLength)))])
307- else baseEntry
331+ let invariantCalculated = invariantCalc(pmtAmountA, pmtAmountB)
332+[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)]
308333 }
309334 }
310-
311-
312-
313-@Callable(i)
314-func initWithInitRatio (amtAssetA,amtAssetB,strAssetIdA,strAssetIdB,firstHarvest) = {
315- let $t01057910666 = getAssetInfoFromString(strAssetIdA)
316- let pmtStrAssetIdA = $t01057910666._1
317- let pmtAssetNameA = $t01057910666._2
318- let pmtDecimalsA = $t01057910666._3
319- let $t01067110758 = getAssetInfoFromString(strAssetIdB)
320- let pmtStrAssetIdB = $t01067110758._1
321- let pmtAssetNameB = $t01067110758._2
322- let pmtDecimalsB = $t01067110758._3
323- if (!(containsElement([adminPubKey1, adminPubKey2, adminPubKey3, adminPubKeyStaking], i.callerPublicKey)))
324- then throw("Only admin can call this function")
325- else if (isDefined(getBoolean(this, keyActive)))
326- then throw("DApp is already active")
327- else if ((strAssetIdA == strAssetIdB))
328- then throw("Assets must be different")
329- else {
330- let shareName = ((("s" + take(pmtAssetNameA, 7)) + "_") + take(pmtAssetNameB, 7))
331- let shareDescription = ((((("ShareToken of SwopFi protocol for " + pmtAssetNameA) + " and ") + pmtAssetNameB) + " at address ") + toString(this))
332- let shareDecimals = ((pmtDecimalsA + pmtDecimalsB) / 2)
333- let shareInitialSupply = 0
334- let shareIssue = Issue(shareName, shareDescription, shareInitialSupply, shareDecimals, true)
335- let shareIssueId = calculateAssetId(shareIssue)
336- let baseEntry = [StringEntry(keyVersion, version), BooleanEntry(keyActive, true), StringEntry(keyAssetIdA, pmtStrAssetIdA), StringEntry(keyAssetIdB, pmtStrAssetIdB), IntegerEntry(keyBalanceInitA, amtAssetA), IntegerEntry(keyBalanceInitB, amtAssetB), IntegerEntry(keyBalanceA, 0), IntegerEntry(keyBalanceB, 0), IntegerEntry(keyCommission, commission), IntegerEntry(keyCommissionScaleDelimiter, commissionScaleDelimiter), shareIssue, StringEntry(keyShareAssetId, toBase58String(shareIssueId)), IntegerEntry(keyShareAssetSupply, shareInitialSupply)]
337- if (firstHarvest)
338- then (baseEntry ++ [BooleanEntry(keyFirstHarvest, firstHarvest), IntegerEntry(keyFirstHarvestHeight, (startHeight + (firstHarvestEndPeriod * periodLength)))])
339- else baseEntry
340- }
341- }
342-
343-
344-
345-@Callable(i)
346-func keepLimitForFirstHarvest (shareLimit) = if (!(isActive))
347- then throw("DApp is inactive at this moment")
348- else if (!(containsElement([adminPubKey1, adminPubKey2, adminPubKey3, adminPubKeyStaking], i.callerPublicKey)))
349- then throw("Only admin can call this function")
350- else [IntegerEntry(kShareLimit, shareLimit)]
351335
352336
353337
354338 @Callable(i)
355339 func replenishWithTwoTokens (slippageTolerance) = {
356340 let pmtAssetIdA = i.payments[0].assetId
357341 let pmtAssetIdB = i.payments[1].assetId
358- let pmtAmountA = deductStakingFee(i.payments[0].amount, pmtAssetIdA, pmtAssetIdB)
359- let pmtAmountB = deductStakingFee(i.payments[1].amount, pmtAssetIdB, pmtAssetIdA)
360- if (if ((balanceA == 0))
361- then (balanceB == 0)
362- else false)
363- then {
364- let $t01346913546 = getAssetInfo(pmtAssetIdA)
365- let pmtStrAssetIdA = $t01346913546._1
366- let pmtAssetNameA = $t01346913546._2
367- let pmtDecimalsA = $t01346913546._3
368- let $t01355513632 = getAssetInfo(pmtAssetIdB)
369- let pmtStrAssetIdB = $t01355513632._1
370- let pmtAssetNameB = $t01355513632._2
371- let pmtDecimalsB = $t01355513632._3
372- let tokenRatio = fraction(fraction(assetInitA, scaleValue8, pmtAmountA), scaleValue3, fraction(assetInitB, scaleValue8, pmtAmountB))
373- if ((pmtAssetIdA == pmtAssetIdB))
374- then throw("Assets must be different")
375- else {
376- let shareDecimals = ((pmtDecimalsA + pmtDecimalsB) / 2)
377- let shareInitialSupply = fraction(pow(pmtAmountA, pmtDecimalsA, 5, 1, pmtDecimalsA, DOWN), pow(pmtAmountB, pmtDecimalsB, 5, 1, pmtDecimalsB, DOWN), pow(10, 0, shareDecimals, 0, 0, DOWN))
378- if (!(isActive))
379- then throw("DApp is inactive at this moment")
380- else if (if ((0 > slippageTolerance))
381- then true
382- else (slippageTolerance > slippageToleranceDelimiter))
383- then throw(((("Slippage tolerance must be between 0 and " + toString(slippageToleranceDelimiter)) + " inclusively. Actual: ") + toString(slippageTolerance)))
384- else if ((size(i.payments) != 2))
385- then throw("Two attached assets expected")
386- else if (if ((((scaleValue3 * (slippageToleranceDelimiter - slippageTolerance)) / slippageToleranceDelimiter) > tokenRatio))
342+ let pmtAmountA = deductStakingFee(i.payments[0].amount, pmtAssetIdA)
343+ let pmtAmountB = deductStakingFee(i.payments[1].amount, pmtAssetIdB)
344+ let tokenRatio = fraction(fraction(scale8, balanceA, pmtAmountA), scale3, fraction(scale8, balanceB, pmtAmountB))
345+ let ratioShareTokensInA = fraction(scale8, pmtAmountA, balanceA)
346+ let ratioShareTokensInB = fraction(scale8, pmtAmountB, balanceB)
347+ let shareTokenToPayAmount = fraction(min([ratioShareTokensInA, ratioShareTokensInB]), shareAssetSupply, scale8)
348+ let invariantCalculated = invariantCalc((balanceA + pmtAmountA), (balanceB + pmtAmountB))
349+ if (!(isActive))
350+ then throwIsInactive()
351+ else if (if ((0 > slippageTolerance))
352+ then true
353+ else (slippageTolerance > 10))
354+ then throw("Slippage tolerance must be <= 1%")
355+ else if ((size(i.payments) != 2))
356+ then throw("Two attached assets expected")
357+ else if (if ((pmtAssetIdA != assetIdA))
358+ then true
359+ else (pmtAssetIdB != assetIdB))
360+ then throwAssets()
361+ else if (if ((((scale3 * (slippageScale3 - slippageTolerance)) / slippageScale3) > tokenRatio))
362+ then true
363+ else (tokenRatio > ((scale3 * (slippageScale3 + slippageTolerance)) / slippageScale3)))
364+ then throw("Incorrect assets amount: amounts must have the contract ratio")
365+ else if ((shareTokenToPayAmount == 0))
366+ then throw("Too small amount to replenish")
367+ else if (!(hasEnoughBalance))
368+ then ([ScriptTransfer(i.caller, pmtAmountA, pmtAssetIdA), ScriptTransfer(i.caller, pmtAmountB, pmtAssetIdB)] ++ suspendSuspicious())
369+ else [IntegerEntry(kBalanceA, (balanceA + pmtAmountA)), IntegerEntry(kBalanceB, (balanceB + pmtAmountB)), IntegerEntry(kShareAssetSupply, (shareAssetSupply + shareTokenToPayAmount)), IntegerEntry(kInvariant, invariantCalculated), Reissue(shareAssetId, shareTokenToPayAmount, true), ScriptTransfer(i.caller, shareTokenToPayAmount, shareAssetId)]
370+ }
371+
372+
373+
374+@Callable(i)
375+func replenishWithOneToken (virtualSwapTokenPay,virtualSwapTokenGet) = {
376+ let $t01343413509 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
377+ let pmtAmount = $t01343413509._1
378+ let pmtAssetId = $t01343413509._2
379+ let pmtMinThreshold = 5000000
380+ let thresholdValueForMinTolerance = 50000000
381+ let tolerance = if ((thresholdValueForMinTolerance > pmtAmount))
382+ then 100000
383+ else 1
384+ let slippageValueMinForReplenish = (scale8 - ((scale8 * tolerance) / 10000000))
385+ let slippageValueMaxForReplenish = (scale8 + ((scale8 * tolerance) / 10000000))
386+ let slippageValueMinForSwap = (scale8 - ((scale8 * 1) / 10000000))
387+ if (!(isActive))
388+ then throwIsInactive()
389+ else if ((pmtMinThreshold > pmtAmount))
390+ then throw((((("Payment amount " + toString(pmtAmount)) + " does not exceed the minimum amount of ") + toString(pmtMinThreshold)) + " tokens"))
391+ else if ((size(i.payments) != 1))
392+ then throw("One attached payment expected")
393+ else if (!(hasEnoughBalance))
394+ then ([ScriptTransfer(i.caller, pmtAmount, pmtAssetId)] ++ suspendSuspicious())
395+ else if (if ((pmtAssetId != assetIdA))
396+ then (pmtAssetId != assetIdB)
397+ else false)
398+ then throwAssets()
399+ else {
400+ let $t01452115286 = if ((pmtAssetId == assetIdA))
401+ then $Tuple7((pmtAmount - virtualSwapTokenPay), virtualSwapTokenGet, (balanceA + virtualSwapTokenPay), (balanceB - virtualSwapTokenGet), invariantCalc((balanceA + pmtAmount), balanceB), (balanceA + pmtAmount), balanceB)
402+ else $Tuple7(virtualSwapTokenGet, (pmtAmount - virtualSwapTokenPay), (balanceA - virtualSwapTokenGet), (balanceB + virtualSwapTokenPay), invariantCalc(balanceA, (balanceB + pmtAmount)), balanceA, (balanceB + pmtAmount))
403+ let virtualReplenishA = $t01452115286._1
404+ let virtualReplenishB = $t01452115286._2
405+ let balanceAfterSwapA = $t01452115286._3
406+ let balanceAfterSwapB = $t01452115286._4
407+ let invariantCalculated = $t01452115286._5
408+ let newBalanceA = $t01452115286._6
409+ let newBalanceB = $t01452115286._7
410+ let newBalanceEntry = if ((pmtAssetId == assetIdA))
411+ then IntegerEntry(kBalanceA, newBalanceA)
412+ else IntegerEntry(kBalanceB, newBalanceB)
413+ let invariantNew = invariantCalc(balanceAfterSwapA, balanceAfterSwapB)
414+ let invariantEstimatedRatio = fraction(scale8, invariant, invariantNew)
415+ let ratioVirtualBalanceToVirtualReplenish = (fraction((scale8 * scale8), balanceAfterSwapA, balanceAfterSwapB) / fraction(scale8, virtualReplenishA, virtualReplenishB))
416+ let dAppThresholdAmount = fraction((newBalanceA + newBalanceB), dAppThreshold, (2 * dAppThresholdScale2))
417+ if (if ((slippageValueMinForSwap >= invariantEstimatedRatio))
418+ then true
419+ else (invariant > invariantNew))
420+ then throw("Incorrect virtualSwapTokenPay or virtualSwapTokenGet value")
421+ else if (if ((slippageValueMinForReplenish > ratioVirtualBalanceToVirtualReplenish))
387422 then true
388- else (tokenRatio > ((scaleValue3 * (slippageToleranceDelimiter + slippageTolerance)) / slippageToleranceDelimiter)))
389- then throw("Incorrect assets amount: amounts must have the contract ratio")
390- else if (if ((pmtAssetIdA != assetIdA))
423+ else (ratioVirtualBalanceToVirtualReplenish > slippageValueMaxForReplenish))
424+ then throw("Swap with virtualSwapTokenPay and virtualSwapTokenGet is possible, but ratio after virtual swap is incorrect")
425+ else if (if ((dAppThresholdAmount > newBalanceA))
391426 then true
392- else (pmtAssetIdB != assetIdB))
393- then throw(((("Incorrect assets attached. Expected: " + strAssetIdA) + " and ") + strAssetIdB))
394- else if ((shareInitialSupply == 0))
395- then throw("Too small amount to replenish")
396- else if (!(hasEnoughBalance))
397- then ([ScriptTransfer(i.caller, pmtAmountA, pmtAssetIdA), ScriptTransfer(i.caller, pmtAmountB, pmtAssetIdB)] ++ suspendSuspicious())
398- else [Reissue(shareAssetId, shareInitialSupply, true), IntegerEntry(keyBalanceA, pmtAmountA), IntegerEntry(keyBalanceB, pmtAmountB), IntegerEntry(keyShareAssetSupply, shareInitialSupply), ScriptTransfer(i.caller, shareInitialSupply, shareAssetId)]
399- }
400- }
401- else {
402- let tokenRatio = fraction(fraction(balanceA, scaleValue8, pmtAmountA), scaleValue3, fraction(balanceB, scaleValue8, pmtAmountB))
403- let ratioShareTokensInA = fraction(pmtAmountA, scaleValue8, balanceA)
404- let ratioShareTokensInB = fraction(pmtAmountB, scaleValue8, balanceB)
405- let shareTokenToPayAmount = fraction(min([ratioShareTokensInA, ratioShareTokensInB]), shareAssetSupply, scaleValue8)
406- if (!(isActive))
407- then throw("DApp is inactive at this moment")
408- else if (if ((0 > slippageTolerance))
409- then true
410- else (slippageTolerance > slippageToleranceDelimiter))
411- then throw(((("Slippage tolerance must be between 0 and " + toString(slippageToleranceDelimiter)) + " inclusively. Actual: ") + toString(slippageTolerance)))
412- else if ((size(i.payments) != 2))
413- then throw("Two attached assets expected")
414- else if (if ((pmtAssetIdA != assetIdA))
415- then true
416- else (pmtAssetIdB != assetIdB))
417- then throw(((("Incorrect assets attached. Expected: " + strAssetIdA) + " and ") + strAssetIdB))
418- else if (if ((((scaleValue3 * (slippageToleranceDelimiter - slippageTolerance)) / slippageToleranceDelimiter) > tokenRatio))
419- then true
420- else (tokenRatio > ((scaleValue3 * (slippageToleranceDelimiter + slippageTolerance)) / slippageToleranceDelimiter)))
421- then throw("Incorrect assets amount: amounts must have the contract ratio")
422- else if ((shareTokenToPayAmount == 0))
423- then throw("Too small amount to replenish")
424- else if (!(hasEnoughBalance))
425- then ([ScriptTransfer(i.caller, pmtAmountA, pmtAssetIdA), ScriptTransfer(i.caller, pmtAmountB, pmtAssetIdB)] ++ suspendSuspicious())
426- else [IntegerEntry(keyBalanceA, (balanceA + pmtAmountA)), IntegerEntry(keyBalanceB, (balanceB + pmtAmountB)), IntegerEntry(keyShareAssetSupply, (shareAssetSupply + shareTokenToPayAmount)), Reissue(shareAssetId, shareTokenToPayAmount, true), ScriptTransfer(i.caller, shareTokenToPayAmount, shareAssetId)]
427- }
427+ else (dAppThresholdAmount > newBalanceB))
428+ then throwThreshold(dAppThresholdAmount, newBalanceA, newBalanceB)
429+ else {
430+ let ratioShareTokensInA = fraction(deductStakingFee(virtualReplenishA, assetIdA), scale8, balanceAfterSwapA)
431+ let ratioShareTokensInB = fraction(deductStakingFee(virtualReplenishB, assetIdB), scale8, balanceAfterSwapB)
432+ let shareTokenToPayAmount = fraction(min([ratioShareTokensInA, ratioShareTokensInB]), shareAssetSupply, scale8)
433+[Reissue(shareAssetId, shareTokenToPayAmount, true), ScriptTransfer(i.caller, shareTokenToPayAmount, shareAssetId), IntegerEntry(kShareAssetSupply, (shareAssetSupply + shareTokenToPayAmount)), newBalanceEntry, IntegerEntry(kInvariant, invariantCalculated)]
434+ }
435+ }
428436 }
429437
430438
431439
432440 @Callable(i)
433441 func withdraw () = {
434- let $t01803118181 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
435- let pmtAmount = $t01803118181._1
436- let pmtAssetId = $t01803118181._2
437- let amountToPayA = deductStakingFee(fraction(pmtAmount, balanceA, shareAssetSupply), assetIdA, assetIdB)
438- let amountToPayB = deductStakingFee(fraction(pmtAmount, balanceB, shareAssetSupply), assetIdB, assetIdA)
442+ let $t01743117574 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
443+ let pmtAmount = $t01743117574._1
444+ let pmtAssetId = $t01743117574._2
445+ let amountToPayA = deductStakingFee(fraction(pmtAmount, balanceA, shareAssetSupply), assetIdA)
446+ let amountToPayB = deductStakingFee(fraction(pmtAmount, balanceB, shareAssetSupply), assetIdB)
447+ let invariantCalculated = invariantCalc((balanceA - amountToPayA), (balanceB - amountToPayB))
439448 if (!(isActive))
440- then throw("DApp is inactive at this moment")
449+ then throwIsInactive()
441450 else if ((size(i.payments) != 1))
442451 then throw("One attached payment expected")
443452 else if ((pmtAssetId != shareAssetId))
444453 then throw(("Incorrect asset attached. Expected: " + toBase58String(shareAssetId)))
445454 else if (!(hasEnoughBalance))
446455 then ([ScriptTransfer(i.caller, pmtAmount, pmtAssetId)] ++ suspendSuspicious())
447456 else if (if ((amountToPayA > availableBalanceA))
448457 then true
449458 else (amountToPayB > availableBalanceB))
450459 then throwInsufficientAvailableBalances(amountToPayA, amountToPayB)
451- else [IntegerEntry(keyBalanceA, (balanceA - amountToPayA)), IntegerEntry(keyBalanceB, (balanceB - amountToPayB)), IntegerEntry(keyShareAssetSupply, (shareAssetSupply - pmtAmount)), Burn(shareAssetId, pmtAmount), ScriptTransfer(i.caller, amountToPayA, assetIdA), ScriptTransfer(i.caller, amountToPayB, assetIdB)]
460+ else [IntegerEntry(kBalanceA, (balanceA - amountToPayA)), IntegerEntry(kBalanceB, (balanceB - amountToPayB)), IntegerEntry(kShareAssetSupply, (shareAssetSupply - pmtAmount)), IntegerEntry(kInvariant, invariantCalculated), Burn(shareAssetId, pmtAmount), ScriptTransfer(i.caller, amountToPayA, assetIdA), ScriptTransfer(i.caller, amountToPayB, assetIdB)]
452461 }
453462
454463
455464
456465 @Callable(i)
457-func exchange (minAmountToReceive) = {
458- let $t01940719482 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
459- let pmtAmount = $t01940719482._1
460- let pmtAssetId = $t01940719482._2
461- func calculateFees (tokenFrom,tokenTo) = {
462- let amountWithoutFee = fraction(tokenTo, pmtAmount, (pmtAmount + tokenFrom))
463- let amountWithFee = fraction(amountWithoutFee, (commissionScaleDelimiter - commission), commissionScaleDelimiter)
464- let governanceReward = fraction(amountWithoutFee, commissionGovernance, commissionScaleDelimiter)
465- if ((minAmountToReceive > amountWithFee))
466- then throw(((("Calculated amount to receive " + toString(amountWithFee)) + " is less than specified minimum ") + toString(minAmountToReceive)))
467- else $Tuple3(amountWithoutFee, amountWithFee, governanceReward)
468- }
469-
466+func exchange (estimatedAmountToReceive,minAmountToReceive) = {
467+ let $t01893219007 = $Tuple2(i.payments[0].amount, i.payments[0].assetId)
468+ let pmtAmount = $t01893219007._1
469+ let pmtAssetId = $t01893219007._2
470470 if (!(isActive))
471- then throw("DApp is inactive at this moment")
472- else if (if ((balanceA == 0))
473- then true
474- else (balanceB == 0))
475- then throw("Can't exchange with zero balance")
476- else if ((0 >= minAmountToReceive))
477- then throw(("Minimal amount to receive must be positive. Actual: " + toString(minAmountToReceive)))
471+ then throwIsInactive()
472+ else if ((0 >= estimatedAmountToReceive))
473+ then throw(("Estimated amount must be positive. Actual: " + toString(estimatedAmountToReceive)))
474+ else if ((minAmountToReceive > estimatedAmountToReceive))
475+ then throw(((("Minimal amount can't be greater than estimated. Estimated: " + toString(estimatedAmountToReceive)) + ". Minimal: ") + toString(minAmountToReceive)))
478476 else if ((size(i.payments) != 1))
479477 then throw("One attached payment expected")
480478 else if (!(hasEnoughBalance))
481479 then ([ScriptTransfer(i.caller, pmtAmount, pmtAssetId)] ++ suspendSuspicious())
482- else if ((pmtAssetId == assetIdA))
483- then {
484- let assetIdSend = assetIdB
485- let $t02075620847 = calculateFees(balanceA, balanceB)
486- let amountWithoutFee = $t02075620847._1
487- let amountWithFee = $t02075620847._2
488- let governanceReward = $t02075620847._3
489- let newBalanceA = (balanceA + pmtAmount)
490- let newBalanceB = ((balanceB - amountWithFee) - governanceReward)
491- if (if ((stakedAmountA >= newBalanceA))
480+ else if (if ((pmtAssetId != assetIdA))
481+ then (pmtAssetId != assetIdB)
482+ else false)
483+ then throwAssets()
484+ else if ((10000000 > pmtAmount))
485+ then throw("Only swap of 10.000000 or more tokens is allowed")
486+ else if (if ((exchangeRatioLimitMin > fraction(scale8, minAmountToReceive, pmtAmount)))
492487 then true
493- else (stakedAmountB >= newBalanceB))
494- then throwInsufficientAvailableBalance(amountWithFee, availableBalanceB, assetNameB)
495- else $Tuple2([IntegerEntry(keyBalanceA, newBalanceA), IntegerEntry(keyBalanceB, newBalanceB), ScriptTransfer(i.caller, amountWithFee, assetIdSend), ScriptTransfer(walletAddress, governanceReward, assetIdSend)], $Tuple2(amountWithFee, assetIdSend))
496- }
497- else if ((pmtAssetId == assetIdB))
498- then {
499- let assetIdSend = assetIdA
500- let $t02170921800 = calculateFees(balanceB, balanceA)
501- let amountWithoutFee = $t02170921800._1
502- let amountWithFee = $t02170921800._2
503- let governanceReward = $t02170921800._3
504- let newBalanceA = ((balanceA - amountWithFee) - governanceReward)
505- let newBalanceB = (balanceB + pmtAmount)
506- if (if ((stakedAmountA >= newBalanceA))
507- then true
508- else (stakedAmountB >= newBalanceB))
509- then throwInsufficientAvailableBalance(amountWithFee, availableBalanceA, assetNameA)
510- else $Tuple2([IntegerEntry(keyBalanceA, newBalanceA), IntegerEntry(keyBalanceB, newBalanceB), ScriptTransfer(i.caller, amountWithFee, assetIdSend), ScriptTransfer(walletAddress, governanceReward, assetIdSend)], $Tuple2(amountWithFee, assetIdSend))
511- }
512- else throw(((("Incorrect asset attached. Expected: " + strAssetIdA) + " or ") + strAssetIdB))
488+ else (fraction(scale8, estimatedAmountToReceive, pmtAmount) > exchangeRatioLimitMax))
489+ then throw("Incorrect args and pmt ratio")
490+ else {
491+ let sendAssetId = if ((pmtAssetId == assetIdA))
492+ then assetIdB
493+ else assetIdA
494+ let amount = calculateSendAmount(estimatedAmountToReceive, minAmountToReceive, pmtAmount, pmtAssetId)
495+ let governanceReward = fraction(amount, feeGovernance, feeScale6)
496+ let amountMinusFee = fraction(amount, (feeScale6 - fee), feeScale6)
497+ let $t02042920691 = if ((pmtAssetId == assetIdA))
498+ then $Tuple2((balanceA + pmtAmount), ((balanceB - amountMinusFee) - governanceReward))
499+ else $Tuple2(((balanceA - amountMinusFee) - governanceReward), (balanceB + pmtAmount))
500+ let newBalanceA = $t02042920691._1
501+ let newBalanceB = $t02042920691._2
502+ let dAppThresholdAmount = fraction((newBalanceA + newBalanceB), dAppThreshold, (2 * dAppThresholdScale2))
503+ if (if ((dAppThresholdAmount > newBalanceA))
504+ then true
505+ else (dAppThresholdAmount > newBalanceB))
506+ then throwThreshold(dAppThresholdAmount, newBalanceA, newBalanceB)
507+ else if (if (if ((assetIdA == USDN))
508+ then (sendAssetId == assetIdA)
509+ else false)
510+ then (stakedAmountUSDN >= newBalanceA)
511+ else false)
512+ then throwInsufficientAvailableBalance(amountMinusFee, availableBalanceA, assetNameA)
513+ else if (if (if ((assetIdB == USDN))
514+ then (sendAssetId == assetIdB)
515+ else false)
516+ then (stakedAmountUSDN >= newBalanceB)
517+ else false)
518+ then throwInsufficientAvailableBalance(amountMinusFee, availableBalanceB, assetNameB)
519+ else $Tuple2([IntegerEntry(kBalanceA, newBalanceA), IntegerEntry(kBalanceB, newBalanceB), IntegerEntry(kInvariant, invariantCalc(newBalanceA, newBalanceB)), ScriptTransfer(i.caller, amountMinusFee, sendAssetId), ScriptTransfer(govAddr, governanceReward, sendAssetId)], $Tuple2(amountMinusFee, sendAssetId))
520+ }
513521 }
514522
515523
516524
517525 @Callable(i)
518526 func shutdown () = if (!(isActive))
519- then throw(("DApp is already suspended. Cause: " + valueOrElse(getString(this, keyCause), "the cause wasn't specified")))
520- else if (!(containsElement([adminPubKey1, adminPubKey2, adminPubKey3, adminPubKeyStartStop], i.callerPublicKey)))
521- then throw("Only admin can call this function")
527+ then throw(("DApp is already suspended. Cause: " + valueOrElse(getString(this, kCause), "the cause wasn't specified")))
528+ else if (!(containsElement([adminPubKey1, adminPubKey2, adminPubKey3, admStartStop], i.callerPublicKey)))
529+ then throwOnlyAdmin()
522530 else suspend("Paused by admin")
523531
524532
525533
526534 @Callable(i)
527535 func activate () = if (isActive)
528- then throw("DApp is already active")
529- else if (!(containsElement([adminPubKey1, adminPubKey2, adminPubKey3, adminPubKeyStartStop], i.callerPublicKey)))
530- then throw("Only admin can call this function")
531- else [BooleanEntry(keyActive, true), DeleteEntry(keyCause)]
536+ then throwIsActive()
537+ else if (!(containsElement([adminPubKey1, adminPubKey2, adminPubKey3, admStartStop], i.callerPublicKey)))
538+ then throwOnlyAdmin()
539+ else [BooleanEntry(kActive, true), DeleteEntry(kCause)]
532540
533541
534542
535543 @Callable(i)
536544 func takeIntoAccountExtraFunds (amountLeave) = {
537- let uncountableAmountEnrollAssetA = (accountBalanceWithStakedA - balanceA)
538- let uncountableAmountEnrollAssetB = (accountBalanceWithStakedB - balanceB)
539- let amountEnrollA = (uncountableAmountEnrollAssetA - (if ((assetIdA == unit))
545+ let uncountableA = (accountBalanceWithStakedA - balanceA)
546+ let uncountableB = (accountBalanceWithStakedB - balanceB)
547+ let amountEnrollA = (uncountableA - (if ((assetIdA == unit))
540548 then amountLeave
541549 else 0))
542- let amountEnrollB = (uncountableAmountEnrollAssetB - (if ((assetIdB == unit))
550+ let amountEnrollB = (uncountableB - (if ((assetIdB == unit))
543551 then amountLeave
544552 else 0))
553+ let invariantNew = invariantCalc((balanceA + amountEnrollA), (balanceB + amountEnrollB))
545554 if (!(isActive))
546- then throw("DApp is inactive at this moment")
555+ then throwIsInactive()
547556 else if ((i.caller != this))
548- then throw("Only the DApp itself can call this function")
557+ then throwOnlyAdmin()
549558 else if ((0 > amountLeave))
550559 then throw(("Argument 'amountLeave' cannot be negative. Actual: " + toString(amountLeave)))
551- else if (if ((0 > uncountableAmountEnrollAssetA))
560+ else if (if ((0 > uncountableA))
552561 then true
553- else (0 > uncountableAmountEnrollAssetB))
562+ else (0 > uncountableB))
554563 then suspend("Enroll amount negative")
555564 else if (if ((0 > amountEnrollA))
556565 then true
557566 else (0 > amountEnrollB))
558567 then throw("Too large amountLeave")
559- else [IntegerEntry(keyBalanceA, (balanceA + amountEnrollA)), IntegerEntry(keyBalanceB, (balanceB + amountEnrollB)), IntegerEntry(("last_income_" + strAssetIdA), amountEnrollA), IntegerEntry(("last_income_" + strAssetIdB), amountEnrollB)]
568+ else [IntegerEntry(kInvariant, invariantNew), IntegerEntry(kBalanceA, (balanceA + amountEnrollA)), IntegerEntry(kBalanceB, (balanceB + amountEnrollB)), IntegerEntry(("last_income_" + strAssetIdA), amountEnrollA), IntegerEntry(("last_income_" + strAssetIdB), amountEnrollB)]
560569 }
561570
562571

github/deemru/w8io/c3f4982 
96.92 ms