2021.12.28 15:02 [2919121] smart account 3P8KMyAJCPWNcyedqrmymxaeWonvmkhGauz > SELF 0.00000000 Waves

{ "type": 13, "id": "GEAQ19Spx5sb5koR83Ly6JAfGGJVoAidgaAcSEKg48zo", "fee": 1400000, "feeAssetId": null, "timestamp": 1640693021939, "version": 1, "sender": "3P8KMyAJCPWNcyedqrmymxaeWonvmkhGauz", "senderPublicKey": "DxhbzFs9BZTiN6kcnyybxmqPTV8xReD6Z5gWQ5AgRX8w", "proofs": [ "EU1T5dzxqvUpgSUjwHh8MTyLozLuJ5WdUWoE22gdmPu1yu6nSVvbqY5rjWEHqJ4wscVtKjJoyRQhyejSDTcbaPg" ], "script": "base64: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AAAIc2xpcHBhZ2UJAAUUAAAAAgUAAAAGcGFzc2VkCQABmQAAAAEJAARMAAAAAgUAAAAHcmVhbEFtdAkABEwAAAACBQAAAAtleHBlY3RlZEFtdAUAAAADbmlsAQAAABBwcml2YXRlQ2FsY1ByaWNlAAAABAAAAAphbUFzc2V0RGNtAAAACnByQXNzZXREY20AAAAFYW1BbXQAAAAFcHJBbXQEAAAAC2FtdEFzQW10WDE4CQEAAAAFdG9YMTgAAAACBQAAAAVhbUFtdAUAAAAKYW1Bc3NldERjbQQAAAAKcHJBc0FtdFgxOAkBAAAABXRvWDE4AAAAAgUAAAAFcHJBbXQFAAAACnByQXNzZXREY20JAQAAAA9jYWxjUHJpY2VCaWdJbnQAAAACBQAAAApwckFzQW10WDE4BQAAAAthbXRBc0FtdFgxOAEAAAAKY2FsY1ByaWNlcwAAAAMAAAAFYW1BbXQAAAAFcHJBbXQAAAAFbHBBbXQEAAAAA2NmZwkBAAAADWdldFBvb2xDb25maWcAAAAABAAAAAhhbXRBc0RjbQkBAAAADXBhcnNlSW50VmFsdWUAAAABCQABkQAAAAIFAAAAA2NmZwUAAAALaWR4QW10QXNEY20EAAAAB3ByQXNEY20JAQAAAA1wYXJzZUludFZhbHVlAAAAAQkAAZEAAAACBQAAAANjZmcFAAAADWlkeFByaWNlQXNEY20EAAAACHByaWNlWDE4CQEAAAAQcHJpdmF0ZUNhbGNQcmljZQAAAAQFAAAACGFtdEFzRGNtBQAAAAdwckFzRGNtBQAAAAVhbUFtdAUAAAAFcHJBbXQEAAAACGFtQW10WDE4CQEAAAAFdG9YMTgAAAACBQAAAAVhbUFtdAUAAAAIYW10QXNEY20EAAAACHByQW10WDE4CQEAAAAFdG9YMTgAAAACBQAAAAVwckFtdAUAAAAHcHJBc0RjbQQAAAAIbHBBbXRYMTgJAQAAAAV0b1gxOAAAAAIFAAAABWxwQW10BQAAAAZzY2FsZTgEAAAADWxwUHJJbkFtQXNYMTgJAQAAAA9jYWxjUHJpY2VCaWdJbnQAAAACBQAAAAhhbUFtdFgxOAUAAAAIbHBBbXRYMTgEAAAADWxwUHJJblByQXNYMTgJAQAAAA9jYWxjUHJpY2VCaWdJbnQAAAACBQAAAAhwckFtdFgxOAUAAAAIbHBBbXRYMTgJAARMAAAAAgUAAAAIcHJpY2VYMTgJAARMAAAAAgUAAAANbHBQckluQW1Bc1gxOAkABEwAAAACBQAAAA1scFBySW5QckFzWDE4BQAAAANuaWwBAAAAD2NhbGN1bGF0ZVByaWNlcwAAAAMAAAAFYW1BbXQAAAAFcHJBbXQAAAAFbHBBbXQEAAAABnByaWNlcwkBAAAACmNhbGNQcmljZXMAAAADBQAAAAVhbUFtdAUAAAAFcHJBbXQFAAAABWxwQW10CQAETAAAAAIJAQAAAAdmcm9tWDE4AAAAAgkAAZEAAAACBQAAAAZwcmljZXMAAAAAAAAAAAAFAAAABnNjYWxlOAkABEwAAAACCQEAAAAHZnJvbVgxOAAAAAIJAAGRAAAAAgUAAAAGcHJpY2VzAAAAAAAAAAABBQAAAAZzY2FsZTgJAARMAAAAAgkBAAAAB2Zyb21YMTgAAAACCQABkQAAAAIFAAAABnByaWNlcwAAAAAAAAAAAgUAAAAGc2NhbGU4BQAAAANuaWwBAAAAFGVzdGltYXRlR2V0T3BlcmF0aW9uAAAABAAAAAZ0eElkNTgAAAAKcG10QXNzZXRJZAAAAAhwbXRMcEFtdAAAAAt1c2VyQWRkcmVzcwQAAAADY2ZnCQEAAAANZ2V0UG9vbENvbmZpZwAAAAAEAAAABGxwSWQJAAGRAAAAAgUAAAADY2ZnBQAAAAlpZHhMUEFzSWQEAAAABGFtSWQJAAGRAAAAAgUAAAADY2ZnBQAAAAlpZHhBbUFzSWQEAAAABHBySWQJAAGRAAAAAgUAAAADY2ZnBQAAAAlpZHhQckFzSWQEAAAABWFtRGNtCQEAAAANcGFyc2VJbnRWYWx1ZQAAAAEJAAGRAAAAAgUAAAADY2ZnBQAAAAtpZHhBbXRBc0RjbQQAAAAFcHJEY20JAQAAAA1wYXJzZUludFZhbHVlAAAAAQkAAZEAAAACBQAAAANjZmcFAAAADWlkeFByaWNlQXNEY20EAAAACnBvb2xTdGF0dXMJAAGRAAAAAgUAAAADY2ZnBQAAAAlpZHhQb29sU3QEAAAACmxwRW1pc3Npb24ICQEAAAATdmFsdWVPckVycm9yTWVzc2FnZQAAAAIJAAPsAAAAAQkAAlkAAAABBQAAAARscElkAgAAAA1JbnZhbGlkIExQIGlkAAAACHF1YW50aXR5AwkBAAAAAiE9AAAAAgUAAAAEbHBJZAUAAAAKcG10QXNzZXRJZAkAAAIAAAABAgAAABFJbnZhbGlkIHBtdCBhc3NldAQAAAAJYW1CYWxhbmNlCQEAAAANZ2V0QWNjQmFsYW5jZQAAAAEFAAAABGFtSWQEAAAADGFtQmFsYW5jZVgxOAkBAAAABXRvWDE4AAAAAgUAAAAJYW1CYWxhbmNlBQAAAAVhbURjbQQAAAAJcHJCYWxhbmNlCQEAAAANZ2V0QWNjQmFsYW5jZQAAAAEFAAAABHBySWQEAAAADHByQmFsYW5jZVgxOAkBAAAABXRvWDE4AAAAAgUAAAAJcHJCYWxhbmNlBQAAAAVwckRjbQQAAAALY3VyUHJpY2VYMTgJAQAAAA9jYWxjUHJpY2VCaWdJbnQAAAACBQAAAAxwckJhbGFuY2VYMTgFAAAADGFtQmFsYW5jZVgxOAQAAAAIY3VyUHJpY2UJAQAAAAdmcm9tWDE4AAAAAgUAAAALY3VyUHJpY2VYMTgFAAAABnNjYWxlOAQAAAALcG10THBBbXRYMTgJAQAAAAV0b1gxOAAAAAIFAAAACHBtdExwQW10BQAAAAZzY2FsZTgEAAAADWxwRW1pc3Npb25YMTgJAQAAAAV0b1gxOAAAAAIFAAAACmxwRW1pc3Npb24FAAAABnNjYWxlOAQAAAALb3V0QW1BbXRYMTgJAAE8AAAAAwUAAAAMYW1CYWxhbmNlWDE4BQAAAAtwbXRMcEFtdFgxOAUAAAANbHBFbWlzc2lvblgxOAQAAAALb3V0UHJBbXRYMTgJAAE8AAAAAwUAAAAMcHJCYWxhbmNlWDE4BQAAAAtwbXRMcEFtdFgxOAUAAAANbHBFbWlzc2lvblgxOAQAAAAIb3V0QW1BbXQJAQAAAAdmcm9tWDE4AAAAAgUAAAALb3V0QW1BbXRYMTgFAAAABWFtRGNtBAAAAAhvdXRQckFtdAkBAAAAB2Zyb21YMTgAAAACBQAAAAtvdXRQckFtdFgxOAUAAAAFcHJEY20EAAAABXN0YXRlAwkAAAAAAAACBQAAAAZ0eElkNTgCAAAAAAUAAAADbmlsCQAETAAAAAIJAQAAAA5TY3JpcHRUcmFuc2ZlcgAAAAMFAAAAC3VzZXJBZGRyZXNzBQAAAAhvdXRBbUFtdAMJAAAAAAAAAgUAAAAEYW1JZAIAAAAFV0FWRVMFAAAABHVuaXQJAAJZAAAAAQUAAAAEYW1JZAkABEwAAAACCQEAAAAOU2NyaXB0VHJhbnNmZXIAAAADBQAAAAt1c2VyQWRkcmVzcwUAAAAIb3V0UHJBbXQDCQAAAAAAAAIFAAAABHBySWQCAAAABVdBVkVTBQAAAAR1bml0CQACWQAAAAEFAAAABHBySWQJAARMAAAAAgkBAAAAC1N0cmluZ0VudHJ5AAAAAgkBAAAAEmtleUdldEFjdGlvbkJ5VXNlcgAAAAIJAAQlAAAAAQUAAAALdXNlckFkZHJlc3MFAAAABnR4SWQ1OAkBAAAAEWRhdGFHZXRBY3Rpb25JbmZvAAAABgUAAAAIb3V0QW1BbXQFAAAACG91dFByQW10BQAAAAhwbXRMcEFtdAUAAAAIY3VyUHJpY2UFAAAABmhlaWdodAgFAAAACWxhc3RCbG9jawAAAAl0aW1lc3RhbXAJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAIJAQAAAAxrZXlQcmljZUxhc3QAAAAABQAAAAhjdXJQcmljZQkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgkBAAAAD2tleVByaWNlSGlzdG9yeQAAAAIFAAAABmhlaWdodAgFAAAACWxhc3RCbG9jawAAAAl0aW1lc3RhbXAFAAAACGN1clByaWNlBQAAAANuaWwJAAUcAAAACgUAAAAIb3V0QW1BbXQFAAAACG91dFByQW10BQAAAARhbUlkBQAAAARwcklkBQAAAAlhbUJhbGFuY2UFAAAACXByQmFsYW5jZQUAAAAKbHBFbWlzc2lvbgUAAAALY3VyUHJpY2VYMTgFAAAACnBvb2xTdGF0dXMFAAAABXN0YXRlAQAAABRlc3RpbWF0ZVB1dE9wZXJhdGlvbgAAAAwAAAAGdHhJZDU4AAAACHNsaXBwYWdlAAAAB2luQW1BbXQAAAAGaW5BbUlkAAAAB2luUHJBbXQAAAAGaW5QcklkAAAAC3VzZXJBZGRyZXNzAAAABmlzRXZhbAAAAAZlbWl0THAAAAAKaXNPbmVBc3NldAAAAAZwbXRBbXQAAAAFcG10SWQEAAAAA2NmZwkBAAAADWdldFBvb2xDb25maWcAAAAABAAAAARscElkCQACWQAAAAEJAAGRAAAAAgUAAAADY2ZnBQAAAAlpZHhMUEFzSWQEAAAAB2FtSWRTdHIJAAGRAAAAAgUAAAADY2ZnBQAAAAlpZHhBbUFzSWQEAAAAB3BySWRTdHIJAAGRAAAAAgUAAAADY2ZnBQAAAAlpZHhQckFzSWQEAAAACWluQW1JZFN0cgkAAZEAAAACBQAAAANjZmcFAAAAC2lkeElBbXRBc0lkBAAAAAlpblBySWRTdHIJAAGRAAAAAgUAAAADY2ZnBQAAAA1pZHhJUHJpY2VBc0lkBAAAAAZhbXREY20JAQAAAA1wYXJzZUludFZhbHVlAAAAAQkAAZEAAAACBQAAAANjZmcFAAAAC2lkeEFtdEFzRGNtBAAAAAhwcmljZURjbQkBAAAADXBhcnNlSW50VmFsdWUAAAABCQABkQAAAAIFAAAAA2NmZwUAAAANaWR4UHJpY2VBc0RjbQQAAAAKcG9vbFN0YXR1cwkAAZEAAAACBQAAAANjZmcFAAAACWlkeFBvb2xTdAQAAAAEbHBFbQgJAQAAABN2YWx1ZU9yRXJyb3JNZXNzYWdlAAAAAgkAA+wAAAABBQAAAARscElkAgAAAAhXciBscCBhcwAAAAhxdWFudGl0eQQAAAAJYW1CYWxhbmNlAwUAAAAGaXNFdmFsCQEAAAANZ2V0QWNjQmFsYW5jZQAAAAEFAAAAB2FtSWRTdHIDAwUAAAAKaXNPbmVBc3NldAkAAAAAAAACBQAAAAVwbXRJZAUAAAAHYW1JZFN0cgcJAABlAAAAAgkBAAAADWdldEFjY0JhbGFuY2UAAAABBQAAAAdhbUlkU3RyBQAAAAZwbXRBbXQDBQAAAAppc09uZUFzc2V0CQEAAAANZ2V0QWNjQmFsYW5jZQAAAAEFAAAAB2FtSWRTdHIJAABlAAAAAgkBAAAADWdldEFjY0JhbGFuY2UAAAABBQAAAAdhbUlkU3RyBQAAAAdpbkFtQW10BAAAAAlwckJhbGFuY2UDBQAAAAZpc0V2YWwJAQAAAA1nZXRBY2NCYWxhbmNlAAAAAQUAAAAHcHJJZFN0cgMDBQAAAAppc09uZUFzc2V0CQAAAAAAAAIFAAAABXBtdElkBQAAAAdwcklkU3RyBwkAAGUAAAACCQEAAAANZ2V0QWNjQmFsYW5jZQAAAAEFAAAAB3BySWRTdHIFAAAABnBtdEFtdAMFAAAACmlzT25lQXNzZXQJAQAAAA1nZXRBY2NCYWxhbmNlAAAAAQUAAAAHcHJJZFN0cgkAAGUAAAACCQEAAAANZ2V0QWNjQmFsYW5jZQAAAAEFAAAAB3BySWRTdHIFAAAAB2luUHJBbXQEAAAAD2luQW1Bc3NldEFtdFgxOAkBAAAABXRvWDE4AAAAAgUAAAAHaW5BbUFtdAUAAAAGYW10RGNtBAAAAA9pblByQXNzZXRBbXRYMTgJAQAAAAV0b1gxOAAAAAIFAAAAB2luUHJBbXQFAAAACHByaWNlRGNtBAAAAAx1c2VyUHJpY2VYMTgJAQAAAA9jYWxjUHJpY2VCaWdJbnQAAAACBQAAAA9pblByQXNzZXRBbXRYMTgFAAAAD2luQW1Bc3NldEFtdFgxOAQAAAAMYW1CYWxhbmNlWDE4CQEAAAAFdG9YMTgAAAACBQAAAAlhbUJhbGFuY2UFAAAABmFtdERjbQQAAAAMcHJCYWxhbmNlWDE4CQEAAAAFdG9YMTgAAAACBQAAAAlwckJhbGFuY2UFAAAACHByaWNlRGNtBAAAAANyZXMDCQAAAAAAAAIFAAAABGxwRW0AAAAAAAAAAAAEAAAAC2N1clByaWNlWDE4BQAAAAp6ZXJvQmlnSW50BAAAAAtzbGlwcGFnZVgxOAUAAAAKemVyb0JpZ0ludAQAAAAIbHBBbXRYMTgJAAB2AAAABgkAATkAAAACBQAAAA9pbkFtQXNzZXRBbXRYMTgFAAAAD2luUHJBc3NldEFtdFgxOAAAAAAAAAAAAAkAATYAAAABAAAAAAAAAAAFAAAAAAAAAAABAAAAAAAAAAAABQAAAARET1dOCQAFFwAAAAUJAQAAAAdmcm9tWDE4AAAAAgUAAAAIbHBBbXRYMTgFAAAABnNjYWxlOAkBAAAAB2Zyb21YMTgAAAACBQAAAA9pbkFtQXNzZXRBbXRYMTgFAAAABmFtdERjbQkBAAAAB2Zyb21YMTgAAAACBQAAAA9pblByQXNzZXRBbXRYMTgFAAAACHByaWNlRGNtCQEAAAAPY2FsY1ByaWNlQmlnSW50AAAAAgkAATcAAAACBQAAAAxwckJhbGFuY2VYMTgFAAAAD2luUHJBc3NldEFtdFgxOAkAATcAAAACBQAAAAxhbUJhbGFuY2VYMTgFAAAAD2luQW1Bc3NldEFtdFgxOAUAAAALc2xpcHBhZ2VYMTgEAAAAC2N1clByaWNlWDE4CQEAAAAPY2FsY1ByaWNlQmlnSW50AAAAAgUAAAAMcHJCYWxhbmNlWDE4BQAAAAxhbUJhbGFuY2VYMTgEAAAAD3NsaXBwYWdlUmVhbFgxOAkAATwAAAADCQEAAAADYWJzAAAAAQkAATgAAAACBQAAAAtjdXJQcmljZVgxOAUAAAAMdXNlclByaWNlWDE4BQAAAAdzY2FsZTE4BQAAAAtjdXJQcmljZVgxOAQAAAALc2xpcHBhZ2VYMTgJAQAAAAV0b1gxOAAAAAIFAAAACHNsaXBwYWdlBQAAAAZzY2FsZTgDAwkBAAAAAiE9AAAAAgUAAAALY3VyUHJpY2VYMTgFAAAACnplcm9CaWdJbnQJAAE/AAAAAgUAAAAPc2xpcHBhZ2VSZWFsWDE4BQAAAAtzbGlwcGFnZVgxOAcJAAACAAAAAQkAASwAAAACCQABLAAAAAIJAAEsAAAAAgIAAAAPUHJpY2Ugc2xpcHBhZ2UgCQABpgAAAAEFAAAAD3NsaXBwYWdlUmVhbFgxOAIAAAADID4gCQABpgAAAAEFAAAAC3NsaXBwYWdlWDE4BAAAAA1scEVtaXNzaW9uWDE4CQEAAAAFdG9YMTgAAAACBQAAAARscEVtBQAAAAZzY2FsZTgEAAAACnByVmlhQW1YMTgJAAE8AAAAAwUAAAAPaW5BbUFzc2V0QW10WDE4BQAAAAtjdXJQcmljZVgxOAUAAAAHc2NhbGUxOAQAAAAKYW1WaWFQclgxOAkAATwAAAADBQAAAA9pblByQXNzZXRBbXRYMTgFAAAAB3NjYWxlMTgFAAAAC2N1clByaWNlWDE4BAAAAAxleHBlY3RlZEFtdHMDCQABPwAAAAIFAAAACnByVmlhQW1YMTgFAAAAD2luUHJBc3NldEFtdFgxOAkABRQAAAACBQAAAAphbVZpYVByWDE4BQAAAA9pblByQXNzZXRBbXRYMTgJAAUUAAAAAgUAAAAPaW5BbUFzc2V0QW10WDE4BQAAAApwclZpYUFtWDE4BAAAABFleHBBbXRBc3NldEFtdFgxOAgFAAAADGV4cGVjdGVkQW10cwAAAAJfMQQAAAATZXhwUHJpY2VBc3NldEFtdFgxOAgFAAAADGV4cGVjdGVkQW10cwAAAAJfMgQAAAAIbHBBbXRYMTgJAAE8AAAAAwUAAAANbHBFbWlzc2lvblgxOAUAAAATZXhwUHJpY2VBc3NldEFtdFgxOAUAAAAMcHJCYWxhbmNlWDE4CQAFFwAAAAUJAQAAAAdmcm9tWDE4AAAAAgUAAAAIbHBBbXRYMTgFAAAABnNjYWxlOAkBAAAAB2Zyb21YMTgAAAACBQAAABFleHBBbXRBc3NldEFtdFgxOAUAAAAGYW10RGNtCQEAAAAHZnJvbVgxOAAAAAIFAAAAE2V4cFByaWNlQXNzZXRBbXRYMTgFAAAACHByaWNlRGNtBQAAAAtjdXJQcmljZVgxOAUAAAALc2xpcHBhZ2VYMTgEAAAACWNhbGNMcEFtdAgFAAAAA3JlcwAAAAJfMQQAAAAOY2FsY0FtQXNzZXRQbXQIBQAAAANyZXMAAAACXzIEAAAADmNhbGNQckFzc2V0UG10CAUAAAADcmVzAAAAAl8zBAAAAAhjdXJQcmljZQkBAAAAB2Zyb21YMTgAAAACCAUAAAADcmVzAAAAAl80BQAAAAZzY2FsZTgEAAAADHNsaXBwYWdlQ2FsYwkBAAAAB2Zyb21YMTgAAAACCAUAAAADcmVzAAAAAl81BQAAAAZzY2FsZTgDCQAAZwAAAAIAAAAAAAAAAAAFAAAACWNhbGNMcEFtdAkAAAIAAAABAgAAAAdMUCA8PSAwBAAAAAllbWl0THBBbXQDCQEAAAABIQAAAAEFAAAABmVtaXRMcAAAAAAAAAAAAAUAAAAJY2FsY0xwQW10BAAAAAZhbURpZmYJAABlAAAAAgUAAAAHaW5BbUFtdAUAAAAOY2FsY0FtQXNzZXRQbXQEAAAABnByRGlmZgkAAGUAAAACBQAAAAdpblByQW10BQAAAA5jYWxjUHJBc3NldFBtdAQAAAANJHQwMTU2NDIxNTk4OAMDBQAAAAppc09uZUFzc2V0CQAAAAAAAAIFAAAABXBtdElkBQAAAAdhbUlkU3RyBwkABRQAAAACBQAAAAZwbXRBbXQAAAAAAAAAAAADAwUAAAAKaXNPbmVBc3NldAkAAAAAAAACBQAAAAVwbXRJZAUAAAAHcHJJZFN0cgcJAAUUAAAAAgAAAAAAAAAAAAUAAAAGcG10QW10CQAFFAAAAAIFAAAADmNhbGNBbUFzc2V0UG10BQAAAA5jYWxjUHJBc3NldFBtdAQAAAAKd3JpdGVBbUFtdAgFAAAADSR0MDE1NjQyMTU5ODgAAAACXzEEAAAACndyaXRlUHJBbXQIBQAAAA0kdDAxNTY0MjE1OTg4AAAAAl8yBAAAAAtjb21tb25TdGF0ZQkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgkBAAAADGtleVByaWNlTGFzdAAAAAAFAAAACGN1clByaWNlCQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACCQEAAAAPa2V5UHJpY2VIaXN0b3J5AAAAAgUAAAAGaGVpZ2h0CAUAAAAJbGFzdEJsb2NrAAAACXRpbWVzdGFtcAUAAAAIY3VyUHJpY2UJAARMAAAAAgkBAAAAC1N0cmluZ0VudHJ5AAAAAgkBAAAAEmtleVB1dEFjdGlvbkJ5VXNlcgAAAAIFAAAAC3VzZXJBZGRyZXNzBQAAAAZ0eElkNTgJAQAAABFkYXRhUHV0QWN0aW9uSW5mbwAAAAoFAAAACndyaXRlQW1BbXQFAAAACndyaXRlUHJBbXQFAAAACWVtaXRMcEFtdAUAAAAIY3VyUHJpY2UFAAAACHNsaXBwYWdlBQAAAAxzbGlwcGFnZUNhbGMFAAAABmhlaWdodAgFAAAACWxhc3RCbG9jawAAAAl0aW1lc3RhbXAFAAAABmFtRGlmZgUAAAAGcHJEaWZmBQAAAANuaWwJAAUfAAAADQUAAAAJY2FsY0xwQW10BQAAAAllbWl0THBBbXQFAAAACGN1clByaWNlBQAAAAlhbUJhbGFuY2UFAAAACXByQmFsYW5jZQUAAAAEbHBFbQUAAAAEbHBJZAUAAAAKcG9vbFN0YXR1cwUAAAALY29tbW9uU3RhdGUFAAAABmFtRGlmZgUAAAAGcHJEaWZmBQAAAAZpbkFtSWQFAAAABmluUHJJZAEAAAAbdmFsaWRhdGVNYXRjaGVyT3JkZXJBbGxvd2VkAAAAAQAAAAVvcmRlcgQAAAADY2ZnCQEAAAANZ2V0UG9vbENvbmZpZwAAAAAEAAAAB2FtdEFzSWQJAAGRAAAAAgUAAAADY2ZnBQAAAAlpZHhBbUFzSWQEAAAABnByQXNJZAkAAZEAAAACBQAAAANjZmcFAAAACWlkeFByQXNJZAQAAAAKcG9vbFN0YXR1cwkBAAAADXBhcnNlSW50VmFsdWUAAAABCQABkQAAAAIFAAAAA2NmZwUAAAAJaWR4UG9vbFN0BAAAAAhhbXRBc0RjbQkBAAAADXBhcnNlSW50VmFsdWUAAAABCQABkQAAAAIFAAAAA2NmZwUAAAALaWR4QW10QXNEY20EAAAAB3ByQXNEY20JAQAAAA1wYXJzZUludFZhbHVlAAAAAQkAAZEAAAACBQAAAANjZmcFAAAADWlkeFByaWNlQXNEY20EAAAAD2FjY0FtdEFzQmFsYW5jZQkBAAAADWdldEFjY0JhbGFuY2UAAAABBQAAAAdhbXRBc0lkBAAAAA5hY2NQckFzQmFsYW5jZQkBAAAADWdldEFjY0JhbGFuY2UAAAABBQAAAAZwckFzSWQEAAAAC2N1clByaWNlWDE4AwkAAAAAAAACCAUAAAAFb3JkZXIAAAAJb3JkZXJUeXBlBQAAAANCdXkJAQAAABBwcml2YXRlQ2FsY1ByaWNlAAAABAUAAAAIYW10QXNEY20FAAAAB3ByQXNEY20JAABkAAAAAgUAAAAPYWNjQW10QXNCYWxhbmNlCAUAAAAFb3JkZXIAAAAGYW1vdW50BQAAAA5hY2NQckFzQmFsYW5jZQkBAAAAEHByaXZhdGVDYWxjUHJpY2UAAAAEBQAAAAhhbXRBc0RjbQUAAAAHcHJBc0RjbQkAAGUAAAACBQAAAA9hY2NBbXRBc0JhbGFuY2UIBQAAAAVvcmRlcgAAAAZhbW91bnQFAAAADmFjY1ByQXNCYWxhbmNlBAAAAAhjdXJQcmljZQkBAAAAB2Zyb21YMTgAAAACBQAAAAtjdXJQcmljZVgxOAUAAAAGc2NhbGU4AwMDCQEAAAAQaXNHbG9iYWxTaHV0ZG93bgAAAAAGCQAAAAAAAAIFAAAACnBvb2xTdGF0dXMFAAAADlBvb2xNYXRjaGVyRGlzBgkAAAAAAAACBQAAAApwb29sU3RhdHVzBQAAAAxQb29sU2h1dGRvd24JAAACAAAAAQIAAAANQWRtaW4gYmxvY2tlZAQAAAAKb3JBbXRBc3NldAgIBQAAAAVvcmRlcgAAAAlhc3NldFBhaXIAAAALYW1vdW50QXNzZXQEAAAACm9yQW10QXNTdHIDCQAAAAAAAAIFAAAACm9yQW10QXNzZXQFAAAABHVuaXQCAAAABVdBVkVTCQACWAAAAAEJAQAAAAV2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pgAAAAEJAAGRAAAAAgUAAAAGcHJpY2VzAAAAAAAAAAACBQAAAANuaWwAAAABaQEAAAAWZnJvbVgxOFdyYXBwZXJSRUFET05MWQAAAAIAAAADdmFsAAAAD3Jlc3VsdFNjYWxlTXVsdAkABRQAAAACBQAAAANuaWwJAQAAAAdmcm9tWDE4AAAAAgkAAacAAAABBQAAAAN2YWwFAAAAD3Jlc3VsdFNjYWxlTXVsdAAAAAFpAQAAABR0b1gxOFdyYXBwZXJSRUFET05MWQAAAAIAAAAHb3JpZ1ZhbAAAAA1vcmlnU2NhbGVNdWx0CQAFFAAAAAIFAAAAA25pbAkAAaYAAAABCQEAAAAFdG9YMTgAAAACBQAAAAdvcmlnVmFsBQAAAA1vcmlnU2NhbGVNdWx0AAAAAWkBAAAAHmNhbGNQcmljZUJpZ0ludFdyYXBwZXJSRUFET05MWQAAAAIAAAAIcHJBbXRYMTgAAAAIYW1BbXRYMTgJAAUUAAAAAgUAAAADbmlsCQABpgAAAAEJAQAAAA9jYWxjUHJpY2VCaWdJbnQAAAACCQABpwAAAAEFAAAACHByQW10WDE4CQABpwAAAAEFAAAACGFtQW10WDE4AAAAAWkBAAAAI2VzdGltYXRlUHV0T3BlcmF0aW9uV3JhcHBlclJFQURPTkxZAAAACQAAAAZ0eElkNTgAAAAIc2xpcHBhZ2UAAAAHaW5BbUFtdAAAAAZpbkFtSWQAAAAHaW5QckFtdAAAAAZpblBySWQAAAAHdXNyQWRkcgAAAAZpc0V2YWwAAAAGZW1pdExwCQAFFAAAAAIFAAAAA25pbAkBAAAAFGVzdGltYXRlUHV0T3BlcmF0aW9uAAAADAUAAAAGdHhJZDU4BQAAAAhzbGlwcGFnZQUAAAAHaW5BbUFtdAUAAAAGaW5BbUlkBQAAAAdpblByQW10BQAAAAZpblBySWQFAAAAB3VzckFkZHIFAAAABmlzRXZhbAUAAAAGZW1pdExwBwAAAAAAAAAAAAIAAAAAAAAAAWkBAAAAI2VzdGltYXRlR2V0T3BlcmF0aW9uV3JhcHBlclJFQURPTkxZAAAABAAAAAZ0eElkNTgAAAAHcG10QXNJZAAAAAhwbXRMcEFtdAAAAAd1c3JBZGRyBAAAAANyZXMJAQAAABRlc3RpbWF0ZUdldE9wZXJhdGlvbgAAAAQFAAAABnR4SWQ1OAUAAAAHcG10QXNJZAUAAAAIcG10THBBbXQJAQAAABFAZXh0ck5hdGl2ZSgxMDYyKQAAAAEFAAAAB3VzckFkZHIJAAUUAAAAAgUAAAADbmlsCQAFHAAAAAoIBQAAAANyZXMAAAACXzEIBQAAAANyZXMAAAACXzIIBQAAAANyZXMAAAACXzMIBQAAAANyZXMAAAACXzQIBQAAAANyZXMAAAACXzUIBQAAAANyZXMAAAACXzYIBQAAAANyZXMAAAACXzcJAAGmAAAAAQgFAAAAA3JlcwAAAAJfOAgFAAAAA3JlcwAAAAJfOQgFAAAAA3JlcwAAAANfMTAAAAABAAAAAnR4AQAAAAZ2ZXJpZnkAAAAABAAAAAckbWF0Y2gwBQAAAAJ0eAMJAAABAAAAAgUAAAAHJG1hdGNoMAIAAAAFT3JkZXIEAAAABW9yZGVyBQAAAAckbWF0Y2gwBAAAAAdtdGNoUHViCQEAAAATZ2V0TWF0Y2hlclB1Yk9yRmFpbAAAAAAEAAAAA29yVgkBAAAAG3ZhbGlkYXRlTWF0Y2hlck9yZGVyQWxsb3dlZAAAAAEFAAAABW9yZGVyBAAAAAVzbmRyVgkAAfQAAAADCAUAAAAFb3JkZXIAAAAJYm9keUJ5dGVzCQABkQAAAAIIBQAAAAVvcmRlcgAAAAZwcm9vZnMAAAAAAAAAAAAIBQAAAAVvcmRlcgAAAA9zZW5kZXJQdWJsaWNLZXkEAAAABW10Y2hWCQAB9AAAAAMIBQAAAAVvcmRlcgAAAAlib2R5Qnl0ZXMJAAGRAAAAAggFAAAABW9yZGVyAAAABnByb29mcwAAAAAAAAAAAQUAAAAHbXRjaFB1YgMDAwUAAAADb3JWBQAAAAVzbmRyVgcFAAAABW10Y2hWBwYJAQAAAA90aHJvd09yZGVyRXJyb3IAAAADBQAAAANvclYFAAAABXNuZHJWBQAAAAVtdGNoVgQAAAAFYWRtaW4JAQAAAAt2YWx1ZU9yRWxzZQAAAAIJAAQdAAAAAgUAAAAEdGhpcwkBAAAADGtleU1hblB1YktleQAAAAAFAAAABUVNUFRZAwkAAAAAAAACBQAAAAVhZG1pbgUAAAAFRU1QVFkJAAH0AAAAAwgFAAAAAnR4AAAACWJvZHlCeXRlcwkAAZEAAAACCAUAAAACdHgAAAAGcHJvb2ZzAAAAAAAAAAAACAUAAAACdHgAAAAPc2VuZGVyUHVibGljS2V5CQAB9AAAAAMIBQAAAAJ0eAAAAAlib2R5Qnl0ZXMJAAGRAAAAAggFAAAAAnR4AAAABnByb29mcwAAAAAAAAAAAAkAAlkAAAABBQAAAAVhZG1pbqgYABQ=", "chainId": 87, "height": 2919121, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: E6gH5tHCsgXUAofVLUbYB34BL6fEDvGGQUkHHaDEKvjF Next: D8EbQFYLuXk36ceeHddo5JbDsoVBKLpMZWYxL77UjoT7 Diff:
OldNewDifferences
11 {-# STDLIB_VERSION 5 #-}
22 {-# SCRIPT_TYPE ACCOUNT #-}
33 {-# CONTENT_TYPE DAPP #-}
4-let lPdecimals = 8
5-
64 let scale8 = 100000000
75
86 let scale8BigInt = toBigInt(100000000)
119
1210 let zeroBigInt = toBigInt(0)
1311
12+let oneBigInt = toBigInt(1)
13+
14+let Amult = "100"
15+
16+let Dconv = "1"
17+
1418 let SEP = "__"
1519
1620 let EMPTY = ""
1721
1822 let PoolActive = 1
1923
20-let PoolPutDisabled = 2
24+let PoolPutDis = 2
2125
22-let PoolMatcherDisabled = 3
26+let PoolMatcherDis = 3
2327
2428 let PoolShutdown = 4
2529
2630 let idxPoolAddress = 1
2731
28-let idxPoolStatus = 2
32+let idxPoolSt = 2
2933
30-let idxPoolLPAssetId = 3
34+let idxLPAsId = 3
3135
32-let idxAmtAssetId = 4
36+let idxAmAsId = 4
3337
34-let idxPriceAssetId = 5
38+let idxPrAsId = 5
3539
36-let idxAmtAssetDcm = 6
40+let idxAmtAsDcm = 6
3741
38-let idxPriceAssetDcm = 7
42+let idxPriceAsDcm = 7
3943
40-let idxIAmtAssetId = 8
44+let idxIAmtAsId = 8
4145
42-let idxIPriceAssetId = 9
46+let idxIPriceAsId = 9
4347
44-let idxLPAssetDcm = 10
48+let idxFactStakCntr = 1
4549
46-let idxPoolAmtAssetAmt = 1
50+let idxFactSlippCntr = 7
4751
48-let idxPoolPriceAssetAmt = 2
49-
50-let idxPoolLPAssetAmt = 3
51-
52-let idxFactoryStakingContract = 1
53-
54-let idxFactorySlippageContract = 7
52+let idxFactGwxRewCntr = 10
5553
5654 func toX18 (origVal,origScaleMult) = fraction(toBigInt(origVal), scale18, toBigInt(origScaleMult))
5755
6765 else val
6866
6967
70-func keyFactoryContract () = "%s__factoryContract"
68+func keyFactCntr () = "%s__factoryContract"
7169
7270
73-func keyManagerPublicKey () = "%s__managerPublicKey"
71+func keyManPubKey () = "%s__managerPublicKey"
7472
7573
7674 func keyPriceLast () = "%s%s__price__last"
7775
7876
79-func keyPriceHistory (h,timestamp) = makeString(["%s%s%d%d__price__history", toString(h), toString(timestamp)], SEP)
77+func keyPriceHistory (h,t) = makeString(["%s%s%d%d__price__history", toString(h), toString(t)], SEP)
8078
8179
82-func keyPutActionByUser (userAddress,txId) = ((("%s%s%s__P__" + userAddress) + "__") + txId)
80+func keyPutActionByUser (ua,txId) = ((("%s%s%s__P__" + ua) + "__") + txId)
8381
8482
85-func keyGetActionByUser (userAddress,txId) = ((("%s%s%s__G__" + userAddress) + "__") + txId)
83+func keyGetActionByUser (ua,txId) = ((("%s%s%s__G__" + ua) + "__") + txId)
8684
8785
8886 func keyAmtAsset () = "%s__amountAsset"
9189 func keyPriceAsset () = "%s__priceAsset"
9290
9391
94-func keyKHistoric (h,timestamp) = makeString(["%s%s%d%d__K_history", toString(h), toString(timestamp)], SEP)
92+func keyAmplificator () = "%s__amp"
9593
9694
9795 func keyFactoryConfig () = "%s__factoryConfig"
10098 func keyMatcherPub () = "%s%s__matcher__publicKey"
10199
102100
103-func keyMappingPoolContractAddressToPoolAssets (poolContractAddress) = (("%s%s%s__" + poolContractAddress) + "__mappings__poolContract2LpAsset")
101+func keyPoolConfig (iAmtAs,iPrAs) = (((("%d%d%s__" + iAmtAs) + "__") + iPrAs) + "__config")
104102
105103
106-func keyPoolConfig (iAmtAsset,iPriceAsset) = (((("%d%d%s__" + iAmtAsset) + "__") + iPriceAsset) + "__config")
107-
108-
109-func keyMappingsBaseAsset2internalId (baseAssetStr) = ("%s%s%s__mappings__baseAsset2internalId__" + baseAssetStr)
104+func keyMappingsBaseAsset2internalId (bAStr) = ("%s%s%s__mappings__baseAsset2internalId__" + bAStr)
110105
111106
112107 func keyAllPoolsShutdown () = "%s__shutdown"
113108
114109
115-func keyPoolWeight (contractAddress) = ("%s%s__poolWeight__" + contractAddress)
110+func keyPoolWeight (p) = ("%s%s__poolWeight__" + p)
116111
117112
118-func throwOrderError (orderValid,senderValid,matcherValid) = throw(((((("order validation failed: orderValid=" + toString(orderValid)) + " senderValid=") + toString(senderValid)) + " matcherValid=") + toString(matcherValid)))
113+func throwOrderError (orV,sendrV,matchV) = throw(((((("Failed: orderValid=" + toString(orV)) + " senderValid=") + toString(sendrV)) + " matcherValid=") + toString(matchV)))
119114
120115
121-func getStringOrFail (address,key) = valueOrErrorMessage(getString(address, key), makeString(["mandatory ", toString(address), ".", key, " is not defined"], ""))
116+func asString (val) = match val {
117+ case valStr: String =>
118+ valStr
119+ case _ =>
120+ throw("fail cast to String")
121+}
122122
123123
124-func getIntOrFail (address,key) = valueOrErrorMessage(getInteger(address, key), makeString(["mandatory ", toString(address), ".", key, " is not defined"], ""))
124+func getStringOrFail (addr,key) = valueOrErrorMessage(getString(addr, key), makeString(["mandatory ", toString(addr), ".", key, " is not defined"], ""))
125125
126126
127-let factoryContract = addressFromStringValue(getStringOrFail(this, keyFactoryContract()))
127+func getIntOrFail (addr,key) = valueOrErrorMessage(getInteger(addr, key), makeString(["mandatory ", toString(addr), ".", key, " is not defined"], ""))
128+
129+
130+let factoryContract = addressFromStringValue(getStringOrFail(this, keyFactCntr()))
131+
132+let A = getStringOrFail(this, keyAmplificator())
128133
129134 func isGlobalShutdown () = valueOrElse(getBoolean(factoryContract, keyAllPoolsShutdown()), false)
130135
133138
134139
135140 func getPoolConfig () = {
136- let amtAsset = getStringOrFail(this, keyAmtAsset())
137- let priceAsset = getStringOrFail(this, keyPriceAsset())
138- let iPriceAsset = getIntOrFail(factoryContract, keyMappingsBaseAsset2internalId(priceAsset))
139- let iAmtAsset = getIntOrFail(factoryContract, keyMappingsBaseAsset2internalId(amtAsset))
140- split(getStringOrFail(factoryContract, keyPoolConfig(toString(iAmtAsset), toString(iPriceAsset))), SEP)
141+ let amtAs = getStringOrFail(this, keyAmtAsset())
142+ let priceAs = getStringOrFail(this, keyPriceAsset())
143+ let iPriceAs = getIntOrFail(factoryContract, keyMappingsBaseAsset2internalId(priceAs))
144+ let iAmtAs = getIntOrFail(factoryContract, keyMappingsBaseAsset2internalId(amtAs))
145+ split(getStringOrFail(factoryContract, keyPoolConfig(toString(iAmtAs), toString(iPriceAs))), SEP)
141146 }
142147
143148
144149 func getFactoryConfig () = split(getStringOrFail(factoryContract, keyFactoryConfig()), SEP)
145150
146151
147-func dataPutActionInfo (inAmtAssetAmt,inPriceAssetAmt,outLpAmt,price,slippageTolerancePassedByUser,slippageToleranceReal,txHeight,txTimestamp,slipageAmtAssetAmt,slipagePriceAssetAmt) = makeString(["%d%d%d%d%d%d%d%d%d%d", toString(inAmtAssetAmt), toString(inPriceAssetAmt), toString(outLpAmt), toString(price), toString(slippageTolerancePassedByUser), toString(slippageToleranceReal), toString(txHeight), toString(txTimestamp), toString(slipageAmtAssetAmt), toString(slipagePriceAssetAmt)], SEP)
152+func dataPutActionInfo (inAmtAssetAmt,inPriceAssetAmt,outLpAmt,price,slipByUser,slippageReal,txHeight,txTimestamp,slipageAmAmt,slipagePrAmt) = makeString(["%d%d%d%d%d%d%d%d%d%d", toString(inAmtAssetAmt), toString(inPriceAssetAmt), toString(outLpAmt), toString(price), toString(slipByUser), toString(slippageReal), toString(txHeight), toString(txTimestamp), toString(slipageAmAmt), toString(slipagePrAmt)], SEP)
148153
149154
150155 func dataGetActionInfo (outAmtAssetAmt,outPriceAssetAmt,inLpAmt,price,txHeight,txTimestamp) = makeString(["%d%d%d%d%d%d", toString(outAmtAssetAmt), toString(outPriceAssetAmt), toString(inLpAmt), toString(price), toString(txHeight), toString(txTimestamp)], SEP)
158163 func calcPriceBigInt (prAmtX18,amAmtX18) = fraction(prAmtX18, scale18, amAmtX18)
159164
160165
166+func validateAbsDiff (realAmt,expectedAmt,slippage) = {
167+ let diff = fraction((realAmt - expectedAmt), scale8BigInt, expectedAmt)
168+ let passed = ((slippage - abs(diff)) > zeroBigInt)
169+ if (!(passed))
170+ then throw(((("Too big slippage: " + toString(diff)) + " vs ") + toString(slippage)))
171+ else $Tuple2(passed, min([realAmt, expectedAmt]))
172+ }
173+
174+
161175 func privateCalcPrice (amAssetDcm,prAssetDcm,amAmt,prAmt) = {
162- let amtAssetAmtX18 = toX18(amAmt, amAssetDcm)
163- let priceAssetAmtX18 = toX18(prAmt, prAssetDcm)
164- calcPriceBigInt(priceAssetAmtX18, amtAssetAmtX18)
176+ let amtAsAmtX18 = toX18(amAmt, amAssetDcm)
177+ let prAsAmtX18 = toX18(prAmt, prAssetDcm)
178+ calcPriceBigInt(prAsAmtX18, amtAsAmtX18)
165179 }
166180
167181
168182 func calcPrices (amAmt,prAmt,lpAmt) = {
169183 let cfg = getPoolConfig()
170- let amtAssetDcm = parseIntValue(cfg[idxAmtAssetDcm])
171- let priceAssetDcm = parseIntValue(cfg[idxPriceAssetDcm])
172- let priceX18 = privateCalcPrice(amtAssetDcm, priceAssetDcm, amAmt, prAmt)
173- let amAmtX18 = toX18(amAmt, amtAssetDcm)
174- let prAmtX18 = toX18(prAmt, priceAssetDcm)
184+ let amtAsDcm = parseIntValue(cfg[idxAmtAsDcm])
185+ let prAsDcm = parseIntValue(cfg[idxPriceAsDcm])
186+ let priceX18 = privateCalcPrice(amtAsDcm, prAsDcm, amAmt, prAmt)
187+ let amAmtX18 = toX18(amAmt, amtAsDcm)
188+ let prAmtX18 = toX18(prAmt, prAsDcm)
175189 let lpAmtX18 = toX18(lpAmt, scale8)
176- let lpPriceInAmAssetX18 = calcPriceBigInt(amAmtX18, lpAmtX18)
177- let lpPriceInPrAssetX18 = calcPriceBigInt(prAmtX18, lpAmtX18)
178-[priceX18, lpPriceInAmAssetX18, lpPriceInPrAssetX18]
190+ let lpPrInAmAsX18 = calcPriceBigInt(amAmtX18, lpAmtX18)
191+ let lpPrInPrAsX18 = calcPriceBigInt(prAmtX18, lpAmtX18)
192+[priceX18, lpPrInAmAsX18, lpPrInPrAsX18]
179193 }
180194
181195
187201
188202 func estimateGetOperation (txId58,pmtAssetId,pmtLpAmt,userAddress) = {
189203 let cfg = getPoolConfig()
190- let lpAssetId = cfg[idxPoolLPAssetId]
191- let amAssetId = cfg[idxAmtAssetId]
192- let prAssetId = cfg[idxPriceAssetId]
193- let amAssetDcm = parseIntValue(cfg[idxAmtAssetDcm])
194- let prAssetDcm = parseIntValue(cfg[idxPriceAssetDcm])
195- let poolStatus = cfg[idxPoolStatus]
196- let lpEmission = valueOrErrorMessage(assetInfo(fromBase58String(lpAssetId)), (("Asset " + lpAssetId) + " doesn't exist")).quantity
197- if ((lpAssetId != pmtAssetId))
198- then throw("Invalid asset passed.")
204+ let lpId = cfg[idxLPAsId]
205+ let amId = cfg[idxAmAsId]
206+ let prId = cfg[idxPrAsId]
207+ let amDcm = parseIntValue(cfg[idxAmtAsDcm])
208+ let prDcm = parseIntValue(cfg[idxPriceAsDcm])
209+ let poolStatus = cfg[idxPoolSt]
210+ let lpEmission = valueOrErrorMessage(assetInfo(fromBase58String(lpId)), "Invalid LP id").quantity
211+ if ((lpId != pmtAssetId))
212+ then throw("Invalid pmt asset")
199213 else {
200- let amBalance = getAccBalance(amAssetId)
201- let amBalanceX18 = toX18(amBalance, amAssetDcm)
202- let prBalance = getAccBalance(prAssetId)
203- let prBalanceX18 = toX18(prBalance, prAssetDcm)
214+ let amBalance = getAccBalance(amId)
215+ let amBalanceX18 = toX18(amBalance, amDcm)
216+ let prBalance = getAccBalance(prId)
217+ let prBalanceX18 = toX18(prBalance, prDcm)
204218 let curPriceX18 = calcPriceBigInt(prBalanceX18, amBalanceX18)
205219 let curPrice = fromX18(curPriceX18, scale8)
206220 let pmtLpAmtX18 = toX18(pmtLpAmt, scale8)
207221 let lpEmissionX18 = toX18(lpEmission, scale8)
208222 let outAmAmtX18 = fraction(amBalanceX18, pmtLpAmtX18, lpEmissionX18)
209223 let outPrAmtX18 = fraction(prBalanceX18, pmtLpAmtX18, lpEmissionX18)
210- let outAmAmt = fromX18(outAmAmtX18, amAssetDcm)
211- let outPrAmt = fromX18(outPrAmtX18, prAssetDcm)
224+ let outAmAmt = fromX18(outAmAmtX18, amDcm)
225+ let outPrAmt = fromX18(outPrAmtX18, prDcm)
212226 let state = if ((txId58 == ""))
213227 then nil
214- else [ScriptTransfer(userAddress, outAmAmt, if ((amAssetId == "WAVES"))
228+ else [ScriptTransfer(userAddress, outAmAmt, if ((amId == "WAVES"))
215229 then unit
216- else fromBase58String(amAssetId)), ScriptTransfer(userAddress, outPrAmt, if ((prAssetId == "WAVES"))
230+ else fromBase58String(amId)), ScriptTransfer(userAddress, outPrAmt, if ((prId == "WAVES"))
217231 then unit
218- else fromBase58String(prAssetId)), StringEntry(keyGetActionByUser(toString(userAddress), txId58), dataGetActionInfo(outAmAmt, outPrAmt, pmtLpAmt, curPrice, height, lastBlock.timestamp)), IntegerEntry(keyPriceLast(), curPrice), IntegerEntry(keyPriceHistory(height, lastBlock.timestamp), curPrice)]
219- $Tuple10(outAmAmt, outPrAmt, amAssetId, prAssetId, amBalance, prBalance, lpEmission, curPriceX18, poolStatus, state)
232+ else fromBase58String(prId)), StringEntry(keyGetActionByUser(toString(userAddress), txId58), dataGetActionInfo(outAmAmt, outPrAmt, pmtLpAmt, curPrice, height, lastBlock.timestamp)), IntegerEntry(keyPriceLast(), curPrice), IntegerEntry(keyPriceHistory(height, lastBlock.timestamp), curPrice)]
233+ $Tuple10(outAmAmt, outPrAmt, amId, prId, amBalance, prBalance, lpEmission, curPriceX18, poolStatus, state)
220234 }
221235 }
222236
223237
224-func estimatePutOperation (txId58,slippageTolerance,inAmAssetAmt,inAmAssetId,inPrAssetAmt,inPrAssetId,userAddress,isEvaluate,emitLp) = {
238+func estimatePutOperation (txId58,slippage,inAmAmt,inAmId,inPrAmt,inPrId,userAddress,isEval,emitLp,isOneAsset,pmtAmt,pmtId) = {
225239 let cfg = getPoolConfig()
226- let lpAssetId = fromBase58String(cfg[idxPoolLPAssetId])
227- let amAssetIdStr = cfg[idxAmtAssetId]
228- let prAssetIdStr = cfg[idxPriceAssetId]
229- let iAmtAssetId = cfg[idxIAmtAssetId]
230- let iPriceAssetId = cfg[idxIPriceAssetId]
231- let amtAssetDcm = parseIntValue(cfg[idxAmtAssetDcm])
232- let priceAssetDcm = parseIntValue(cfg[idxPriceAssetDcm])
233- let poolStatus = cfg[idxPoolStatus]
234- let lpEmission = valueOrErrorMessage(assetInfo(lpAssetId), (("Asset " + toBase58String(lpAssetId)) + " doesn't exist")).quantity
235- let inAmAssetIdStr = toBase58String(valueOrElse(inAmAssetId, fromBase58String("WAVES")))
236- let inPrAssetIdStr = toBase58String(valueOrElse(inPrAssetId, fromBase58String("WAVES")))
237- if (if ((amAssetIdStr != inAmAssetIdStr))
238- then true
239- else (prAssetIdStr != inPrAssetIdStr))
240- then throw("Invalid amt or price asset passed.")
240+ let lpId = fromBase58String(cfg[idxLPAsId])
241+ let amIdStr = cfg[idxAmAsId]
242+ let prIdStr = cfg[idxPrAsId]
243+ let inAmIdStr = cfg[idxIAmtAsId]
244+ let inPrIdStr = cfg[idxIPriceAsId]
245+ let amtDcm = parseIntValue(cfg[idxAmtAsDcm])
246+ let priceDcm = parseIntValue(cfg[idxPriceAsDcm])
247+ let poolStatus = cfg[idxPoolSt]
248+ let lpEm = valueOrErrorMessage(assetInfo(lpId), "Wr lp as").quantity
249+ let amBalance = if (isEval)
250+ then getAccBalance(amIdStr)
251+ else if (if (isOneAsset)
252+ then (pmtId == amIdStr)
253+ else false)
254+ then (getAccBalance(amIdStr) - pmtAmt)
255+ else if (isOneAsset)
256+ then getAccBalance(amIdStr)
257+ else (getAccBalance(amIdStr) - inAmAmt)
258+ let prBalance = if (isEval)
259+ then getAccBalance(prIdStr)
260+ else if (if (isOneAsset)
261+ then (pmtId == prIdStr)
262+ else false)
263+ then (getAccBalance(prIdStr) - pmtAmt)
264+ else if (isOneAsset)
265+ then getAccBalance(prIdStr)
266+ else (getAccBalance(prIdStr) - inPrAmt)
267+ let inAmAssetAmtX18 = toX18(inAmAmt, amtDcm)
268+ let inPrAssetAmtX18 = toX18(inPrAmt, priceDcm)
269+ let userPriceX18 = calcPriceBigInt(inPrAssetAmtX18, inAmAssetAmtX18)
270+ let amBalanceX18 = toX18(amBalance, amtDcm)
271+ let prBalanceX18 = toX18(prBalance, priceDcm)
272+ let res = if ((lpEm == 0))
273+ then {
274+ let curPriceX18 = zeroBigInt
275+ let slippageX18 = zeroBigInt
276+ let lpAmtX18 = pow((inAmAssetAmtX18 * inPrAssetAmtX18), 0, toBigInt(5), 1, 0, DOWN)
277+ $Tuple5(fromX18(lpAmtX18, scale8), fromX18(inAmAssetAmtX18, amtDcm), fromX18(inPrAssetAmtX18, priceDcm), calcPriceBigInt((prBalanceX18 + inPrAssetAmtX18), (amBalanceX18 + inAmAssetAmtX18)), slippageX18)
278+ }
241279 else {
242- let amBalance = if (isEvaluate)
243- then getAccBalance(amAssetIdStr)
244- else (getAccBalance(amAssetIdStr) - inAmAssetAmt)
245- let prBalance = if (isEvaluate)
246- then getAccBalance(prAssetIdStr)
247- else (getAccBalance(prAssetIdStr) - inPrAssetAmt)
248- let inAmAssetAmtX18 = toX18(inAmAssetAmt, amtAssetDcm)
249- let inPrAssetAmtX18 = toX18(inPrAssetAmt, priceAssetDcm)
250- let userPriceX18 = calcPriceBigInt(inPrAssetAmtX18, inAmAssetAmtX18)
251- let amBalanceX18 = toX18(amBalance, amtAssetDcm)
252- let prBalanceX18 = toX18(prBalance, priceAssetDcm)
253- let res = if ((lpEmission == 0))
254- then {
255- let curPriceX18 = zeroBigInt
256- let slippageX18 = zeroBigInt
257- let lpAmtX18 = pow((inAmAssetAmtX18 * inPrAssetAmtX18), 0, toBigInt(5), 1, 0, DOWN)
258- $Tuple5(fromX18(lpAmtX18, scale8), fromX18(inAmAssetAmtX18, amtAssetDcm), fromX18(inPrAssetAmtX18, priceAssetDcm), calcPriceBigInt((prBalanceX18 + inPrAssetAmtX18), (amBalanceX18 + inAmAssetAmtX18)), slippageX18)
280+ let curPriceX18 = calcPriceBigInt(prBalanceX18, amBalanceX18)
281+ let slippageRealX18 = fraction(abs((curPriceX18 - userPriceX18)), scale18, curPriceX18)
282+ let slippageX18 = toX18(slippage, scale8)
283+ if (if ((curPriceX18 != zeroBigInt))
284+ then (slippageRealX18 > slippageX18)
285+ else false)
286+ then throw(((("Price slippage " + toString(slippageRealX18)) + " > ") + toString(slippageX18)))
287+ else {
288+ let lpEmissionX18 = toX18(lpEm, scale8)
289+ let prViaAmX18 = fraction(inAmAssetAmtX18, curPriceX18, scale18)
290+ let amViaPrX18 = fraction(inPrAssetAmtX18, scale18, curPriceX18)
291+ let expectedAmts = if ((prViaAmX18 > inPrAssetAmtX18))
292+ then $Tuple2(amViaPrX18, inPrAssetAmtX18)
293+ else $Tuple2(inAmAssetAmtX18, prViaAmX18)
294+ let expAmtAssetAmtX18 = expectedAmts._1
295+ let expPriceAssetAmtX18 = expectedAmts._2
296+ let lpAmtX18 = fraction(lpEmissionX18, expPriceAssetAmtX18, prBalanceX18)
297+ $Tuple5(fromX18(lpAmtX18, scale8), fromX18(expAmtAssetAmtX18, amtDcm), fromX18(expPriceAssetAmtX18, priceDcm), curPriceX18, slippageX18)
259298 }
260- else {
261- let curPriceX18 = calcPriceBigInt(prBalanceX18, amBalanceX18)
262- let slippageX18 = fraction(abs((curPriceX18 - userPriceX18)), scale18, curPriceX18)
263- let slippageToleranceX18 = toX18(slippageTolerance, scale8)
264- if (if ((curPriceX18 != zeroBigInt))
265- then (slippageX18 > slippageToleranceX18)
266- else false)
267- then throw(((("Price slippage " + toString(slippageX18)) + " exceeded the passed limit of ") + toString(slippageToleranceX18)))
268- else {
269- let lpEmissionX18 = toX18(lpEmission, scale8)
270- let prViaAmX18 = fraction(inAmAssetAmtX18, curPriceX18, scale18)
271- let amViaPrX18 = fraction(inPrAssetAmtX18, scale18, curPriceX18)
272- let expectedAmts = if ((prViaAmX18 > inPrAssetAmtX18))
273- then $Tuple2(amViaPrX18, inPrAssetAmtX18)
274- else $Tuple2(inAmAssetAmtX18, prViaAmX18)
275- let expAmtAssetAmtX18 = expectedAmts._1
276- let expPriceAssetAmtX18 = expectedAmts._2
277- let lpAmtX18 = fraction(lpEmissionX18, expPriceAssetAmtX18, prBalanceX18)
278- $Tuple5(fromX18(lpAmtX18, scale8), fromX18(expAmtAssetAmtX18, amtAssetDcm), fromX18(expPriceAssetAmtX18, priceAssetDcm), curPriceX18, slippageX18)
279- }
280- }
281- let calcLpAmt = res._1
282- let calcAmAssetPmt = res._2
283- let calcPrAssetPmt = res._3
284- let curPrice = fromX18(res._4, scale8)
285- let slippageCalc = fromX18(res._5, scale8)
286- if ((0 >= calcLpAmt))
287- then throw("Invalid calculations. LP calculated is less than zero.")
288- else {
289- let emitLpAmt = if (!(emitLp))
290- then 0
291- else calcLpAmt
292- let amDiff = (inAmAssetAmt - calcAmAssetPmt)
293- let prDiff = (inPrAssetAmt - calcPrAssetPmt)
294- let commonState = [IntegerEntry(keyPriceLast(), curPrice), IntegerEntry(keyPriceHistory(height, lastBlock.timestamp), curPrice), StringEntry(keyPutActionByUser(userAddress, txId58), dataPutActionInfo(calcAmAssetPmt, calcPrAssetPmt, emitLpAmt, curPrice, slippageTolerance, slippageCalc, height, lastBlock.timestamp, amDiff, prDiff))]
295- $Tuple13(calcLpAmt, emitLpAmt, curPrice, amBalance, prBalance, lpEmission, lpAssetId, poolStatus, commonState, amDiff, prDiff, inAmAssetId, inPrAssetId)
296- }
299+ }
300+ let calcLpAmt = res._1
301+ let calcAmAssetPmt = res._2
302+ let calcPrAssetPmt = res._3
303+ let curPrice = fromX18(res._4, scale8)
304+ let slippageCalc = fromX18(res._5, scale8)
305+ if ((0 >= calcLpAmt))
306+ then throw("LP <= 0")
307+ else {
308+ let emitLpAmt = if (!(emitLp))
309+ then 0
310+ else calcLpAmt
311+ let amDiff = (inAmAmt - calcAmAssetPmt)
312+ let prDiff = (inPrAmt - calcPrAssetPmt)
313+ let $t01564215988 = if (if (isOneAsset)
314+ then (pmtId == amIdStr)
315+ else false)
316+ then $Tuple2(pmtAmt, 0)
317+ else if (if (isOneAsset)
318+ then (pmtId == prIdStr)
319+ else false)
320+ then $Tuple2(0, pmtAmt)
321+ else $Tuple2(calcAmAssetPmt, calcPrAssetPmt)
322+ let writeAmAmt = $t01564215988._1
323+ let writePrAmt = $t01564215988._2
324+ let commonState = [IntegerEntry(keyPriceLast(), curPrice), IntegerEntry(keyPriceHistory(height, lastBlock.timestamp), curPrice), StringEntry(keyPutActionByUser(userAddress, txId58), dataPutActionInfo(writeAmAmt, writePrAmt, emitLpAmt, curPrice, slippage, slippageCalc, height, lastBlock.timestamp, amDiff, prDiff))]
325+ $Tuple13(calcLpAmt, emitLpAmt, curPrice, amBalance, prBalance, lpEm, lpId, poolStatus, commonState, amDiff, prDiff, inAmId, inPrId)
297326 }
298327 }
299328
300329
301330 func validateMatcherOrderAllowed (order) = {
302331 let cfg = getPoolConfig()
303- let amtAssetId = cfg[idxAmtAssetId]
304- let priceAssetId = cfg[idxPriceAssetId]
305- let poolStatus = parseIntValue(cfg[idxPoolStatus])
306- let amtAssetDcm = parseIntValue(cfg[idxAmtAssetDcm])
307- let priceAssetDcm = parseIntValue(cfg[idxPriceAssetDcm])
308- let accAmtAssetBalance = getAccBalance(amtAssetId)
309- let accPriceAssetBalance = getAccBalance(priceAssetId)
332+ let amtAsId = cfg[idxAmAsId]
333+ let prAsId = cfg[idxPrAsId]
334+ let poolStatus = parseIntValue(cfg[idxPoolSt])
335+ let amtAsDcm = parseIntValue(cfg[idxAmtAsDcm])
336+ let prAsDcm = parseIntValue(cfg[idxPriceAsDcm])
337+ let accAmtAsBalance = getAccBalance(amtAsId)
338+ let accPrAsBalance = getAccBalance(prAsId)
310339 let curPriceX18 = if ((order.orderType == Buy))
311- then privateCalcPrice(amtAssetDcm, priceAssetDcm, (accAmtAssetBalance + order.amount), accPriceAssetBalance)
312- else privateCalcPrice(amtAssetDcm, priceAssetDcm, (accAmtAssetBalance - order.amount), accPriceAssetBalance)
340+ then privateCalcPrice(amtAsDcm, prAsDcm, (accAmtAsBalance + order.amount), accPrAsBalance)
341+ else privateCalcPrice(amtAsDcm, prAsDcm, (accAmtAsBalance - order.amount), accPrAsBalance)
313342 let curPrice = fromX18(curPriceX18, scale8)
314343 if (if (if (isGlobalShutdown())
315344 then true
316- else (poolStatus == PoolMatcherDisabled))
345+ else (poolStatus == PoolMatcherDis))
317346 then true
318347 else (poolStatus == PoolShutdown))
319- then throw("Exchange operations disabled")
348+ then throw("Admin blocked")
320349 else {
321- let orderAmtAsset = order.assetPair.amountAsset
322- let orderAmtAssetStr = if ((orderAmtAsset == unit))
350+ let orAmtAsset = order.assetPair.amountAsset
351+ let orAmtAsStr = if ((orAmtAsset == unit))
323352 then "WAVES"
324- else toBase58String(value(orderAmtAsset))
325- let orderPriceAsset = order.assetPair.priceAsset
326- let orderPriceAssetStr = if ((orderPriceAsset == unit))
353+ else toBase58String(value(orAmtAsset))
354+ let orPrAsset = order.assetPair.priceAsset
355+ let orPrAsStr = if ((orPrAsset == unit))
327356 then "WAVES"
328- else toBase58String(value(orderPriceAsset))
329- if (if ((orderAmtAssetStr != amtAssetId))
357+ else toBase58String(value(orPrAsset))
358+ if (if ((orAmtAsStr != amtAsId))
330359 then true
331- else (orderPriceAssetStr != priceAssetId))
332- then throw("Wrong order assets.")
360+ else (orPrAsStr != prAsId))
361+ then throw("Wr assets")
333362 else {
334363 let orderPrice = order.price
335- let priceDcm = fraction(scale8, priceAssetDcm, amtAssetDcm)
336- let castedOrderPrice = toScale(orderPrice, scale8, priceDcm)
364+ let priceDcm = fraction(scale8, prAsDcm, amtAsDcm)
365+ let castOrderPrice = toScale(orderPrice, scale8, priceDcm)
337366 let isOrderPriceValid = if ((order.orderType == Buy))
338- then (curPrice >= castedOrderPrice)
339- else (castedOrderPrice >= curPrice)
367+ then (curPrice >= castOrderPrice)
368+ else (castOrderPrice >= curPrice)
340369 true
341370 }
342371 }
344373
345374
346375 func commonGet (i) = if ((size(i.payments) != 1))
347- then throw("exactly 1 payment is expected")
376+ then throw("1 pmnt exp")
348377 else {
349378 let pmt = value(i.payments[0])
350379 let pmtAssetId = value(pmt.assetId)
357386 if (if (isGlobalShutdown())
358387 then true
359388 else (poolStatus == PoolShutdown))
360- then throw(("Get operation is blocked by admin. Status = " + toString(poolStatus)))
389+ then throw(("Admin blocked: " + toString(poolStatus)))
361390 else $Tuple5(outAmAmt, outPrAmt, pmtAmt, pmtAssetId, state)
362391 }
363392
364393
365-func commonPut (i,slippageTolerance,emitLp) = if ((size(i.payments) != 2))
366- then throw("exactly 2 payments are expected")
367- else {
368- let amAssetPmt = value(i.payments[0])
369- let prAssetPmt = value(i.payments[1])
370- let estPut = estimatePutOperation(toBase58String(i.transactionId), slippageTolerance, amAssetPmt.amount, amAssetPmt.assetId, prAssetPmt.amount, prAssetPmt.assetId, toString(i.caller), false, emitLp)
371- let poolStatus = parseIntValue(estPut._8)
372- if (if (if (isGlobalShutdown())
373- then true
374- else (poolStatus == PoolPutDisabled))
375- then true
376- else (poolStatus == PoolShutdown))
377- then throw(("Put operation is blocked by admin. Status = " + toString(poolStatus)))
378- else estPut
379- }
394+func commonPut (caller,txId,amAsPmt,prAsPmt,slippage,emitLp,isOneAsset,pmtAmt,pmtId) = {
395+ let r = estimatePutOperation(txId, slippage, value(amAsPmt).amount, value(amAsPmt).assetId, value(prAsPmt).amount, value(prAsPmt).assetId, caller, false, emitLp, isOneAsset, pmtAmt, pmtId)
396+ let status = parseIntValue(r._8)
397+ if (if (if (isGlobalShutdown())
398+ then true
399+ else (status == PoolPutDis))
400+ then true
401+ else (status == PoolShutdown))
402+ then throw(("Admin blocked: " + toString(status)))
403+ else r
404+ }
380405
381406
382407 @Callable(i)
383408 func constructor (factoryContract,managerPublicKey) = if ((i.caller != this))
384- then throw("permissions denied")
385- else [StringEntry(keyFactoryContract(), factoryContract), StringEntry(keyManagerPublicKey(), managerPublicKey)]
409+ then throw("denied")
410+ else [StringEntry(keyFactCntr(), factoryContract), StringEntry(keyManPubKey(), managerPublicKey)]
386411
387412
388413
389414 @Callable(i)
390-func put (slippageTolerance,shouldAutoStake) = {
391- let factoryCfg = getFactoryConfig()
392- let stakingContract = valueOrErrorMessage(addressFromString(factoryCfg[idxFactoryStakingContract]), "Error. Incorrect staking address.")
393- let slippageContract = valueOrErrorMessage(addressFromString(factoryCfg[idxFactorySlippageContract]), "Error. Incorrect slippage contract address.")
394- if ((0 > slippageTolerance))
395- then throw("Invalid slippageTolerance passed")
396- else {
397- let estPut = commonPut(i, slippageTolerance, true)
398- let emitLpAmt = estPut._2
399- let lpAssetId = estPut._7
400- let state = estPut._9
401- let amDiff = estPut._10
402- let prDiff = estPut._11
403- let amId = estPut._12
404- let prId = estPut._13
405- let emitInv = invoke(factoryContract, "emit", [emitLpAmt], nil)
406- if ((emitInv == emitInv))
407- then {
408- let slippageAInv = if ((amDiff > 0))
409- then invoke(slippageContract, "put", nil, [AttachedPayment(amId, amDiff)])
410- else nil
411- if ((slippageAInv == slippageAInv))
412- then {
413- let slippagePInv = if ((prDiff > 0))
414- then invoke(slippageContract, "put", nil, [AttachedPayment(prId, prDiff)])
415- else nil
416- if ((slippagePInv == slippagePInv))
417- then {
418- let lpTransfer = if (shouldAutoStake)
419- then {
420- let slpStakeInv = invoke(stakingContract, "stake", nil, [AttachedPayment(lpAssetId, emitLpAmt)])
421- if ((slpStakeInv == slpStakeInv))
422- then nil
423- else throw("Strict value is not equal to itself.")
424- }
425- else [ScriptTransfer(i.caller, emitLpAmt, lpAssetId)]
426- (state ++ lpTransfer)
427- }
428- else throw("Strict value is not equal to itself.")
429- }
430- else throw("Strict value is not equal to itself.")
431- }
432- else throw("Strict value is not equal to itself.")
433- }
415+func put (slip,autoStake) = {
416+ let factCfg = getFactoryConfig()
417+ let stakingCntr = valueOrErrorMessage(addressFromString(factCfg[idxFactStakCntr]), "Wr st addr")
418+ let slipCntr = valueOrErrorMessage(addressFromString(factCfg[idxFactSlippCntr]), "Wr sl addr")
419+ if ((0 > slip))
420+ then throw("Invalid slippage")
421+ else if ((size(i.payments) != 2))
422+ then throw("2 pmnts expected")
423+ else {
424+ let estPut = commonPut(toString(i.caller), toBase58String(i.transactionId), AttachedPayment(value(i.payments[0]).assetId, value(i.payments[0]).amount), i.payments[1], slip, true, false, 0, "")
425+ let emitLpAmt = estPut._2
426+ let lpAssetId = estPut._7
427+ let state = estPut._9
428+ let amDiff = estPut._10
429+ let prDiff = estPut._11
430+ let amId = estPut._12
431+ let prId = estPut._13
432+ let emitInv = invoke(factoryContract, "emit", [emitLpAmt], nil)
433+ if ((emitInv == emitInv))
434+ then {
435+ let slippageAInv = if ((amDiff > 0))
436+ then invoke(slipCntr, "put", nil, [AttachedPayment(amId, amDiff)])
437+ else nil
438+ if ((slippageAInv == slippageAInv))
439+ then {
440+ let slippagePInv = if ((prDiff > 0))
441+ then invoke(slipCntr, "put", nil, [AttachedPayment(prId, prDiff)])
442+ else nil
443+ if ((slippagePInv == slippagePInv))
444+ then {
445+ let lpTrnsfr = if (autoStake)
446+ then {
447+ let slpStakeInv = invoke(stakingCntr, "stake", nil, [AttachedPayment(lpAssetId, emitLpAmt)])
448+ if ((slpStakeInv == slpStakeInv))
449+ then nil
450+ else throw("Strict value is not equal to itself.")
451+ }
452+ else [ScriptTransfer(i.caller, emitLpAmt, lpAssetId)]
453+ (state ++ lpTrnsfr)
454+ }
455+ else throw("Strict value is not equal to itself.")
456+ }
457+ else throw("Strict value is not equal to itself.")
458+ }
459+ else throw("Strict value is not equal to itself.")
460+ }
461+ }
462+
463+
464+
465+@Callable(i)
466+func putOneTkn (amAssetPart,prAssetPart,outLp,slippage,autoStake) = {
467+ let cfg = getFactoryConfig()
468+ let stakingCntr = valueOrErrorMessage(addressFromString(cfg[idxFactStakCntr]), "Wr st addr")
469+ let slipCntr = valueOrErrorMessage(addressFromString(cfg[idxFactSlippCntr]), "Wr sl addr")
470+ let gwxCntr = valueOrErrorMessage(addressFromString(cfg[idxFactGwxRewCntr]), "Wr gwx addr")
471+ let poolCfg = getPoolConfig()
472+ let amId = poolCfg[idxAmAsId]
473+ let prId = poolCfg[idxPrAsId]
474+ let amDcm = parseIntValue(poolCfg[idxAmtAsDcm])
475+ let prDcm = parseIntValue(poolCfg[idxPriceAsDcm])
476+ if (if (if (if ((0 >= slippage))
477+ then true
478+ else (0 >= amAssetPart))
479+ then true
480+ else (0 >= prAssetPart))
481+ then true
482+ else (0 >= outLp))
483+ then throw("Wrong params")
484+ else if ((size(i.payments) != 1))
485+ then throw("1 pmnt expected")
486+ else {
487+ let pmt = value(i.payments[0])
488+ let pmtAssetId = toBase58String(value(pmt.assetId))
489+ let pmtAmt = pmt.amount
490+ let amBalance = getAccBalance(amId)
491+ let prBalance = getAccBalance(prId)
492+ let $t02366124041 = if ((pmtAssetId == amId))
493+ then $Tuple6((amBalance - pmtAmt), prBalance, (pmtAmt - amAssetPart), prAssetPart, 0, 0)
494+ else if ((pmtAssetId == prId))
495+ then $Tuple6(amBalance, (prBalance - pmtAmt), 0, 0, (pmtAmt - prAssetPart), amAssetPart)
496+ else throw("wrong pmtAssetId")
497+ let amBalanceNow = $t02366124041._1
498+ let prBalanceNow = $t02366124041._2
499+ let virtSwapInAm = $t02366124041._3
500+ let virtSwapOutPr = $t02366124041._4
501+ let virtSwapInPr = $t02366124041._5
502+ let virtSwapOutAm = $t02366124041._6
503+ let D0 = invoke(gwxCntr, "calcD", [toString(amBalanceNow), toString(prBalanceNow), A, Amult, Dconv], nil)
504+ let D1 = invoke(gwxCntr, "calcD", [toString(toBigInt(((amBalanceNow + virtSwapInAm) - virtSwapOutAm))), toString(toBigInt(((prBalanceNow + virtSwapInPr) - virtSwapOutPr))), A, Amult, Dconv], nil)
505+ let D0vsD1 = validateAbsDiff(parseBigIntValue(asString(D1)), parseBigIntValue(asString(D0)), toBigInt(1000))
506+ if ((D0vsD1 == D0vsD1))
507+ then {
508+ let estPut = commonPut(toString(i.caller), toBase58String(i.transactionId), AttachedPayment(fromBase58String(amId), amAssetPart), AttachedPayment(fromBase58String(prId), prAssetPart), 50000000000, true, true, pmtAmt, pmtAssetId)
509+ let estimLP = estPut._2
510+ let lpAssetId = estPut._7
511+ let state = estPut._9
512+ let amDiff = estPut._10
513+ let prDiff = estPut._11
514+ let lpCalcRes = validateAbsDiff(toBigInt(estimLP), toBigInt(outLp), toBigInt(slippage))
515+ let emitLpAmt = toInt(lpCalcRes._2)
516+ let emitInv = invoke(factoryContract, "emit", [emitLpAmt], nil)
517+ if ((emitInv == emitInv))
518+ then {
519+ let slippageAInv = if ((amDiff > 0))
520+ then invoke(slipCntr, "put", nil, [AttachedPayment(fromBase58String(amId), amDiff)])
521+ else nil
522+ if ((slippageAInv == slippageAInv))
523+ then {
524+ let slippagePInv = if ((prDiff > 0))
525+ then invoke(slipCntr, "put", nil, [AttachedPayment(fromBase58String(prId), prDiff)])
526+ else nil
527+ if ((slippagePInv == slippagePInv))
528+ then {
529+ let lpTrnsfr = if (autoStake)
530+ then {
531+ let slpStakeInv = invoke(stakingCntr, "stake", nil, [AttachedPayment(lpAssetId, emitLpAmt)])
532+ if ((slpStakeInv == slpStakeInv))
533+ then nil
534+ else throw("Strict value is not equal to itself.")
535+ }
536+ else [ScriptTransfer(i.caller, emitLpAmt, lpAssetId)]
537+ (state ++ lpTrnsfr)
538+ }
539+ else throw("Strict value is not equal to itself.")
540+ }
541+ else throw("Strict value is not equal to itself.")
542+ }
543+ else throw("Strict value is not equal to itself.")
544+ }
545+ else throw("Strict value is not equal to itself.")
546+ }
434547 }
435548
436549
437550
438551 @Callable(i)
439552 func putForFree (maxSlippage) = if ((0 > maxSlippage))
440- then throw("Invalid value passed")
441- else {
442- let estPut = commonPut(i, maxSlippage, false)
443- estPut._9
444- }
553+ then throw("Invalid slippage")
554+ else if ((size(i.payments) != 2))
555+ then throw("2 pmnts expected")
556+ else {
557+ let estPut = commonPut(toString(i.caller), toBase58String(i.transactionId), AttachedPayment(value(i.payments[0]).assetId, value(i.payments[0]).amount), i.payments[1], maxSlippage, false, false, 0, "")
558+ estPut._9
559+ }
445560
446561
447562
462577
463578
464579 @Callable(i)
580+func getOneTkn (amAssetSwap,prAssetSwap,outAmount,outAssetId,slippage) = if ((size(i.payments) != 1))
581+ then throw("1 pmnt expected")
582+ else {
583+ let cfg = getPoolConfig()
584+ let lpId = cfg[idxLPAsId]
585+ let amId = cfg[idxAmAsId]
586+ let prId = cfg[idxPrAsId]
587+ let amDcm = parseIntValue(cfg[idxAmtAsDcm])
588+ let prDcm = parseIntValue(cfg[idxPriceAsDcm])
589+ let poolStatus = cfg[idxPoolSt]
590+ let fcfg = getFactoryConfig()
591+ let gwxCntr = valueOrErrorMessage(addressFromString(fcfg[idxFactGwxRewCntr]), "Wr sl addr")
592+ let pmt = value(i.payments[0])
593+ let userAddress = i.caller
594+ let txId58 = toBase58String(i.transactionId)
595+ let pmtAssetId = value(pmt.assetId)
596+ let pmtAmt = pmt.amount
597+ if (if (if (if ((0 > slippage))
598+ then true
599+ else (0 > amAssetSwap))
600+ then true
601+ else (0 > prAssetSwap))
602+ then true
603+ else (0 > outAmount))
604+ then throw("Wrong params")
605+ else if ((lpId != toBase58String(pmtAssetId)))
606+ then throw("Invalid LP")
607+ else {
608+ let r = estimateGetOperation(toBase58String(i.transactionId), toBase58String(pmtAssetId), pmtAmt, i.caller)
609+ let estimAmAmt = r._1
610+ let estimPrAmt = r._2
611+ let amBalance = getAccBalance(amId)
612+ let prBalance = getAccBalance(prId)
613+ let $t02849828982 = if ((outAssetId == amId))
614+ then $Tuple7((amBalance - estimAmAmt), (prBalance - estimPrAmt), (outAmount - estimAmAmt), prAssetSwap, 0, 0, (estimAmAmt + amAssetSwap))
615+ else if ((outAssetId == prId))
616+ then $Tuple7((amBalance - estimAmAmt), (prBalance - estimPrAmt), 0, 0, (outAmount - estimPrAmt), amAssetSwap, (estimPrAmt + prAssetSwap))
617+ else throw("wrong outAssetId")
618+ let amBalanceNow = $t02849828982._1
619+ let prBalanceNow = $t02849828982._2
620+ let virtSwapInAm = $t02849828982._3
621+ let virtSwapOutPr = $t02849828982._4
622+ let virtSwapInPr = $t02849828982._5
623+ let virtSwapOutAm = $t02849828982._6
624+ let totalGet = $t02849828982._7
625+ let D0 = invoke(gwxCntr, "calcD", [toString(amBalanceNow), toString(prBalanceNow), A, Amult, Dconv], nil)
626+ let D1 = invoke(gwxCntr, "calcD", [toString(((amBalanceNow - virtSwapInAm) + virtSwapOutAm)), toString(((prBalanceNow + virtSwapOutPr) - virtSwapInPr)), A, Amult, Dconv], nil)
627+ let D0vsD1 = validateAbsDiff(parseBigIntValue(asString(D1)), parseBigIntValue(asString(D0)), toBigInt(1000))
628+ if ((D0vsD1 == D0vsD1))
629+ then {
630+ let amount2Return = validateAbsDiff(toBigInt(totalGet), toBigInt(outAmount), toBigInt(slippage))
631+ if ((amount2Return == amount2Return))
632+ then {
633+ let $t02965829772 = if ((outAssetId == amId))
634+ then $Tuple2(toInt(amount2Return._2), 0)
635+ else $Tuple2(0, toInt(amount2Return._2))
636+ let outAm = $t02965829772._1
637+ let outPr = $t02965829772._2
638+ let curPriceX18 = calcPriceBigInt(toX18(prBalance, prDcm), toX18(amBalance, amDcm))
639+ let curPrice = fromX18(curPriceX18, scale8)
640+ let state = [ScriptTransfer(userAddress, (outAm + outPr), if ((outAssetId == "WAVES"))
641+ then unit
642+ else fromBase58String(outAssetId)), StringEntry(keyGetActionByUser(toString(userAddress), txId58), dataGetActionInfo(outAm, outPr, pmtAmt, curPrice, height, lastBlock.timestamp)), IntegerEntry(keyPriceLast(), curPrice), IntegerEntry(keyPriceHistory(height, lastBlock.timestamp), curPrice)]
643+ if ((state == state))
644+ then {
645+ let burn = invoke(factoryContract, "burn", [pmtAmt], [AttachedPayment(pmtAssetId, pmtAmt)])
646+ if ((burn == burn))
647+ then state
648+ else throw("Strict value is not equal to itself.")
649+ }
650+ else throw("Strict value is not equal to itself.")
651+ }
652+ else throw("Strict value is not equal to itself.")
653+ }
654+ else throw("Strict value is not equal to itself.")
655+ }
656+ }
657+
658+
659+
660+@Callable(i)
465661 func getNoLess (noLessThenAmtAsset,noLessThenPriceAsset) = {
466662 let res = commonGet(i)
467663 let outAmAmt = res._1
470666 let pmtAssetId = res._4
471667 let state = res._5
472668 if ((noLessThenAmtAsset > outAmAmt))
473- then throw(((("noLessThenAmtAsset failed: " + toString(outAmAmt)) + " < ") + toString(noLessThenAmtAsset)))
669+ then throw(((("Failed: " + toString(outAmAmt)) + " < ") + toString(noLessThenAmtAsset)))
474670 else if ((noLessThenPriceAsset > outPrAmt))
475- then throw(((("noLessThenPriceAsset failed: " + toString(outPrAmt)) + " < ") + toString(noLessThenPriceAsset)))
671+ then throw(((("Failed: " + toString(outPrAmt)) + " < ") + toString(noLessThenPriceAsset)))
476672 else {
477673 let burnLPAssetOnFactory = invoke(factoryContract, "burn", [pmtAmt], [AttachedPayment(pmtAssetId, pmtAmt)])
478674 if ((burnLPAssetOnFactory == burnLPAssetOnFactory))
486682 @Callable(i)
487683 func unstakeAndGet (amount) = {
488684 let checkPayments = if ((size(i.payments) != 0))
489- then throw("No payments are expected")
685+ then throw("No pmnts expected")
490686 else true
491687 if ((checkPayments == checkPayments))
492688 then {
493689 let cfg = getPoolConfig()
494690 let factoryCfg = getFactoryConfig()
495- let lpAssetId = fromBase58String(cfg[idxPoolLPAssetId])
496- let stakingContract = valueOrErrorMessage(addressFromString(factoryCfg[idxFactoryStakingContract]), "Error. Incorrect staking address.")
691+ let lpAssetId = fromBase58String(cfg[idxLPAsId])
692+ let stakingContract = valueOrErrorMessage(addressFromString(factoryCfg[idxFactStakCntr]), "Wr st addr")
497693 let unstakeInv = invoke(stakingContract, "unstake", [toBase58String(lpAssetId), amount], nil)
498694 if ((unstakeInv == unstakeInv))
499695 then {
500- let res = estimateGetOperation(toBase58String(i.transactionId), toBase58String(lpAssetId), amount, i.caller)
501- let poolStatus = parseIntValue(res._9)
502- let state = res._10
696+ let r = estimateGetOperation(toBase58String(i.transactionId), toBase58String(lpAssetId), amount, i.caller)
697+ let poolStatus = parseIntValue(r._9)
698+ let state = r._10
503699 let checkPoolStatus = if (if (isGlobalShutdown())
504700 then true
505701 else (poolStatus == PoolShutdown))
506- then throw(("Get operation is blocked by admin. Status = " + toString(poolStatus)))
702+ then throw(("Blocked: " + toString(poolStatus)))
507703 else true
508704 if ((checkPoolStatus == checkPoolStatus))
509705 then {
523719
524720 @Callable(i)
525721 func activate (amtAssetStr,priceAssetStr) = if ((toString(i.caller) != toString(factoryContract)))
526- then throw("permissions denied")
722+ then throw("denied")
527723 else $Tuple2([StringEntry(keyAmtAsset(), amtAssetStr), StringEntry(keyPriceAsset(), priceAssetStr)], "success")
528724
529725
547743
548744
549745 @Callable(i)
550-func toX18WrapperREADONLY (origVal,origScaleMult) = $Tuple2(nil, toString(toX18(origVal, origScaleMult)))
746+func fromX18WrapperREADONLY (val,resultScaleMult) = $Tuple2(nil, fromX18(parseBigIntValue(val), resultScaleMult))
551747
552748
553749
554750 @Callable(i)
555-func fromX18WrapperREADONLY (val,resultScaleMult) = $Tuple2(nil, fromX18(parseBigIntValue(val), resultScaleMult))
751+func toX18WrapperREADONLY (origVal,origScaleMult) = $Tuple2(nil, toString(toX18(origVal, origScaleMult)))
556752
557753
558754
562758
563759
564760 @Callable(i)
565-func estimatePutOperationWrapperREADONLY (txId58,slippageTolerance,inAmAssetAmt,inAmAssetId,inPrAssetAmt,inPrAssetId,userAddress,isEvaluate,emitLp) = $Tuple2(nil, estimatePutOperation(txId58, slippageTolerance, inAmAssetAmt, inAmAssetId, inPrAssetAmt, inPrAssetId, userAddress, isEvaluate, emitLp))
761+func estimatePutOperationWrapperREADONLY (txId58,slippage,inAmAmt,inAmId,inPrAmt,inPrId,usrAddr,isEval,emitLp) = $Tuple2(nil, estimatePutOperation(txId58, slippage, inAmAmt, inAmId, inPrAmt, inPrId, usrAddr, isEval, emitLp, false, 0, ""))
566762
567763
568764
569765 @Callable(i)
570-func estimateGetOperationWrapperREADONLY (txId58,pmtAssetId,pmtLpAmt,userAddress) = {
571- let res = estimateGetOperation(txId58, pmtAssetId, pmtLpAmt, addressFromStringValue(userAddress))
766+func estimateGetOperationWrapperREADONLY (txId58,pmtAsId,pmtLpAmt,usrAddr) = {
767+ let res = estimateGetOperation(txId58, pmtAsId, pmtLpAmt, addressFromStringValue(usrAddr))
572768 $Tuple2(nil, $Tuple10(res._1, res._2, res._3, res._4, res._5, res._6, res._7, toString(res._8), res._9, res._10))
573- }
574-
575-
576-
577-@Callable(i)
578-func statsREADONLY () = {
579- let cfg = getPoolConfig()
580- let lpAssetId = fromBase58String(cfg[idxPoolLPAssetId])
581- let amtAssetId = cfg[idxAmtAssetId]
582- let priceAssetId = cfg[idxPriceAssetId]
583- let iAmtAssetId = cfg[idxIAmtAssetId]
584- let iPriceAssetId = cfg[idxIPriceAssetId]
585- let amtAssetDcm = parseIntValue(cfg[idxAmtAssetDcm])
586- let priceAssetDcm = parseIntValue(cfg[idxPriceAssetDcm])
587- let poolLPBalance = valueOrErrorMessage(assetInfo(lpAssetId), (("Asset " + toBase58String(lpAssetId)) + " doesn't exist")).quantity
588- let accAmtAssetBalance = getAccBalance(amtAssetId)
589- let accPriceAssetBalance = getAccBalance(priceAssetId)
590- let pricesList = if ((poolLPBalance == 0))
591- then [zeroBigInt, zeroBigInt, zeroBigInt]
592- else calcPrices(accAmtAssetBalance, accPriceAssetBalance, poolLPBalance)
593- let curPrice = 0
594- let lpAmtAssetShare = fromX18(pricesList[1], scale8)
595- let lpPriceAssetShare = fromX18(pricesList[2], scale8)
596- let poolWeight = value(getInteger(factoryContract, keyPoolWeight(toString(this))))
597- $Tuple2(nil, makeString(["%d%d%d%d%d%d%d", toString(accAmtAssetBalance), toString(accPriceAssetBalance), toString(poolLPBalance), toString(curPrice), toString(lpAmtAssetShare), toString(lpPriceAssetShare), toString(poolWeight)], SEP))
598- }
599-
600-
601-
602-@Callable(i)
603-func evaluatePutByAmountAssetREADONLY (inAmAssetAmt) = {
604- let cfg = getPoolConfig()
605- let lpAssetId = fromBase58String(cfg[idxPoolLPAssetId])
606- let amAssetIdStr = cfg[idxAmtAssetId]
607- let amAssetId = fromBase58String(amAssetIdStr)
608- let prAssetIdStr = cfg[idxPriceAssetId]
609- let prAssetId = fromBase58String(prAssetIdStr)
610- let amtAssetDcm = parseIntValue(cfg[idxAmtAssetDcm])
611- let priceAssetDcm = parseIntValue(cfg[idxPriceAssetDcm])
612- let poolStatus = cfg[idxPoolStatus]
613- let poolLPBalance = valueOrErrorMessage(assetInfo(lpAssetId), (("Asset " + toBase58String(lpAssetId)) + " doesn't exist")).quantity
614- let accAmtAssetBalance = getAccBalance(amAssetIdStr)
615- let accPriceAssetBalance = getAccBalance(prAssetIdStr)
616- let amtAssetAmtX18 = toX18(accAmtAssetBalance, amtAssetDcm)
617- let priceAssetAmtX18 = toX18(accPriceAssetBalance, priceAssetDcm)
618- let curPriceX18 = if ((poolLPBalance == 0))
619- then zeroBigInt
620- else calcPriceBigInt(priceAssetAmtX18, amtAssetAmtX18)
621- let inAmAssetAmtX18 = toX18(inAmAssetAmt, amtAssetDcm)
622- let inPrAssetAmtX18 = fraction(inAmAssetAmtX18, curPriceX18, scale18)
623- let inPrAssetAmt = fromX18(inPrAssetAmtX18, priceAssetDcm)
624- let estPut = estimatePutOperation("", 500000, inAmAssetAmt, amAssetId, inPrAssetAmt, prAssetId, "", true, false)
625- let calcLpAmt = estPut._1
626- let curPriceCalc = estPut._3
627- let amBalance = estPut._4
628- let prBalance = estPut._5
629- let lpEmission = estPut._6
630- $Tuple2(nil, makeString(["%d%d%d%d%d%d%d%d", toString(calcLpAmt), toString(fromX18(curPriceX18, scale8)), toString(amBalance), toString(prBalance), toString(lpEmission), poolStatus, toString(inAmAssetAmt), toString(inPrAssetAmt)], SEP))
631- }
632-
633-
634-
635-@Callable(i)
636-func evaluatePutByPriceAssetREADONLY (inPrAssetAmt) = {
637- let cfg = getPoolConfig()
638- let lpAssetId = fromBase58String(cfg[idxPoolLPAssetId])
639- let amAssetIdStr = cfg[idxAmtAssetId]
640- let amAssetId = fromBase58String(amAssetIdStr)
641- let prAssetIdStr = cfg[idxPriceAssetId]
642- let prAssetId = fromBase58String(prAssetIdStr)
643- let amtAssetDcm = parseIntValue(cfg[idxAmtAssetDcm])
644- let priceAssetDcm = parseIntValue(cfg[idxPriceAssetDcm])
645- let poolStatus = cfg[idxPoolStatus]
646- let poolLPBalance = valueOrErrorMessage(assetInfo(lpAssetId), (("Asset " + toBase58String(lpAssetId)) + " doesn't exist")).quantity
647- let amBalanceRaw = getAccBalance(amAssetIdStr)
648- let prBalanceRaw = getAccBalance(prAssetIdStr)
649- let amBalanceRawX18 = toX18(amBalanceRaw, amtAssetDcm)
650- let prBalanceRawX18 = toX18(prBalanceRaw, priceAssetDcm)
651- let curPriceX18 = if ((poolLPBalance == 0))
652- then zeroBigInt
653- else calcPriceBigInt(prBalanceRawX18, amBalanceRawX18)
654- let inPrAssetAmtX18 = toX18(inPrAssetAmt, priceAssetDcm)
655- let inAmAssetAmtX18 = fraction(inPrAssetAmtX18, scale18, curPriceX18)
656- let inAmAssetAmt = fromX18(inAmAssetAmtX18, amtAssetDcm)
657- let estPut = estimatePutOperation("", 500000, inAmAssetAmt, amAssetId, inPrAssetAmt, prAssetId, "", true, false)
658- let calcLpAmt = estPut._1
659- let curPriceCalc = estPut._3
660- let amBalance = estPut._4
661- let prBalance = estPut._5
662- let lpEmission = estPut._6
663- $Tuple2(nil, makeString(["%d%d%d%d%d%d%d%d", toString(calcLpAmt), toString(fromX18(curPriceX18, scale8)), toString(amBalance), toString(prBalance), toString(lpEmission), poolStatus, toString(inAmAssetAmt), toString(inPrAssetAmt)], SEP))
664- }
665-
666-
667-
668-@Callable(i)
669-func evaluateGetREADONLY (paymentLpAssetId,paymentLpAmt) = {
670- let res = estimateGetOperation("", paymentLpAssetId, paymentLpAmt, this)
671- let outAmAmt = res._1
672- let outPrAmt = res._2
673- let amBalance = res._5
674- let prBalance = res._6
675- let lpEmission = res._7
676- let curPrice = res._8
677- let poolStatus = parseIntValue(res._9)
678- $Tuple2(nil, makeString(["%d%d%d%d%d%d%d", toString(outAmAmt), toString(outPrAmt), toString(amBalance), toString(prBalance), toString(lpEmission), toString(curPrice), toString(poolStatus)], SEP))
679769 }
680770
681771
682772 @Verifier(tx)
683773 func verify () = match tx {
684774 case order: Order =>
685- let matcherPub = getMatcherPubOrFail()
686- let orderValid = validateMatcherOrderAllowed(order)
687- let senderValid = sigVerify(order.bodyBytes, order.proofs[0], order.senderPublicKey)
688- let matcherValid = sigVerify(order.bodyBytes, order.proofs[1], matcherPub)
689- if (if (if (orderValid)
690- then senderValid
775+ let mtchPub = getMatcherPubOrFail()
776+ let orV = validateMatcherOrderAllowed(order)
777+ let sndrV = sigVerify(order.bodyBytes, order.proofs[0], order.senderPublicKey)
778+ let mtchV = sigVerify(order.bodyBytes, order.proofs[1], mtchPub)
779+ if (if (if (orV)
780+ then sndrV
691781 else false)
692- then matcherValid
782+ then mtchV
693783 else false)
694784 then true
695- else throwOrderError(orderValid, senderValid, matcherValid)
785+ else throwOrderError(orV, sndrV, mtchV)
696786 case _ =>
697- let managerPublic = valueOrElse(getString(this, keyManagerPublicKey()), EMPTY)
698- if ((managerPublic == EMPTY))
787+ let admin = valueOrElse(getString(this, keyManPubKey()), EMPTY)
788+ if ((admin == EMPTY))
699789 then sigVerify(tx.bodyBytes, tx.proofs[0], tx.senderPublicKey)
700- else sigVerify(tx.bodyBytes, tx.proofs[0], fromBase58String(managerPublic))
790+ else sigVerify(tx.bodyBytes, tx.proofs[0], fromBase58String(admin))
701791 }
702792
Full:
OldNewDifferences
11 {-# STDLIB_VERSION 5 #-}
22 {-# SCRIPT_TYPE ACCOUNT #-}
33 {-# CONTENT_TYPE DAPP #-}
4-let lPdecimals = 8
5-
64 let scale8 = 100000000
75
86 let scale8BigInt = toBigInt(100000000)
97
108 let scale18 = toBigInt(1000000000000000000)
119
1210 let zeroBigInt = toBigInt(0)
1311
12+let oneBigInt = toBigInt(1)
13+
14+let Amult = "100"
15+
16+let Dconv = "1"
17+
1418 let SEP = "__"
1519
1620 let EMPTY = ""
1721
1822 let PoolActive = 1
1923
20-let PoolPutDisabled = 2
24+let PoolPutDis = 2
2125
22-let PoolMatcherDisabled = 3
26+let PoolMatcherDis = 3
2327
2428 let PoolShutdown = 4
2529
2630 let idxPoolAddress = 1
2731
28-let idxPoolStatus = 2
32+let idxPoolSt = 2
2933
30-let idxPoolLPAssetId = 3
34+let idxLPAsId = 3
3135
32-let idxAmtAssetId = 4
36+let idxAmAsId = 4
3337
34-let idxPriceAssetId = 5
38+let idxPrAsId = 5
3539
36-let idxAmtAssetDcm = 6
40+let idxAmtAsDcm = 6
3741
38-let idxPriceAssetDcm = 7
42+let idxPriceAsDcm = 7
3943
40-let idxIAmtAssetId = 8
44+let idxIAmtAsId = 8
4145
42-let idxIPriceAssetId = 9
46+let idxIPriceAsId = 9
4347
44-let idxLPAssetDcm = 10
48+let idxFactStakCntr = 1
4549
46-let idxPoolAmtAssetAmt = 1
50+let idxFactSlippCntr = 7
4751
48-let idxPoolPriceAssetAmt = 2
49-
50-let idxPoolLPAssetAmt = 3
51-
52-let idxFactoryStakingContract = 1
53-
54-let idxFactorySlippageContract = 7
52+let idxFactGwxRewCntr = 10
5553
5654 func toX18 (origVal,origScaleMult) = fraction(toBigInt(origVal), scale18, toBigInt(origScaleMult))
5755
5856
5957 func fromX18 (val,resultScaleMult) = toInt(fraction(val, toBigInt(resultScaleMult), scale18))
6058
6159
6260 func toScale (amt,resScale,curScale) = fraction(amt, resScale, curScale)
6361
6462
6563 func abs (val) = if ((zeroBigInt > val))
6664 then -(val)
6765 else val
6866
6967
70-func keyFactoryContract () = "%s__factoryContract"
68+func keyFactCntr () = "%s__factoryContract"
7169
7270
73-func keyManagerPublicKey () = "%s__managerPublicKey"
71+func keyManPubKey () = "%s__managerPublicKey"
7472
7573
7674 func keyPriceLast () = "%s%s__price__last"
7775
7876
79-func keyPriceHistory (h,timestamp) = makeString(["%s%s%d%d__price__history", toString(h), toString(timestamp)], SEP)
77+func keyPriceHistory (h,t) = makeString(["%s%s%d%d__price__history", toString(h), toString(t)], SEP)
8078
8179
82-func keyPutActionByUser (userAddress,txId) = ((("%s%s%s__P__" + userAddress) + "__") + txId)
80+func keyPutActionByUser (ua,txId) = ((("%s%s%s__P__" + ua) + "__") + txId)
8381
8482
85-func keyGetActionByUser (userAddress,txId) = ((("%s%s%s__G__" + userAddress) + "__") + txId)
83+func keyGetActionByUser (ua,txId) = ((("%s%s%s__G__" + ua) + "__") + txId)
8684
8785
8886 func keyAmtAsset () = "%s__amountAsset"
8987
9088
9189 func keyPriceAsset () = "%s__priceAsset"
9290
9391
94-func keyKHistoric (h,timestamp) = makeString(["%s%s%d%d__K_history", toString(h), toString(timestamp)], SEP)
92+func keyAmplificator () = "%s__amp"
9593
9694
9795 func keyFactoryConfig () = "%s__factoryConfig"
9896
9997
10098 func keyMatcherPub () = "%s%s__matcher__publicKey"
10199
102100
103-func keyMappingPoolContractAddressToPoolAssets (poolContractAddress) = (("%s%s%s__" + poolContractAddress) + "__mappings__poolContract2LpAsset")
101+func keyPoolConfig (iAmtAs,iPrAs) = (((("%d%d%s__" + iAmtAs) + "__") + iPrAs) + "__config")
104102
105103
106-func keyPoolConfig (iAmtAsset,iPriceAsset) = (((("%d%d%s__" + iAmtAsset) + "__") + iPriceAsset) + "__config")
107-
108-
109-func keyMappingsBaseAsset2internalId (baseAssetStr) = ("%s%s%s__mappings__baseAsset2internalId__" + baseAssetStr)
104+func keyMappingsBaseAsset2internalId (bAStr) = ("%s%s%s__mappings__baseAsset2internalId__" + bAStr)
110105
111106
112107 func keyAllPoolsShutdown () = "%s__shutdown"
113108
114109
115-func keyPoolWeight (contractAddress) = ("%s%s__poolWeight__" + contractAddress)
110+func keyPoolWeight (p) = ("%s%s__poolWeight__" + p)
116111
117112
118-func throwOrderError (orderValid,senderValid,matcherValid) = throw(((((("order validation failed: orderValid=" + toString(orderValid)) + " senderValid=") + toString(senderValid)) + " matcherValid=") + toString(matcherValid)))
113+func throwOrderError (orV,sendrV,matchV) = throw(((((("Failed: orderValid=" + toString(orV)) + " senderValid=") + toString(sendrV)) + " matcherValid=") + toString(matchV)))
119114
120115
121-func getStringOrFail (address,key) = valueOrErrorMessage(getString(address, key), makeString(["mandatory ", toString(address), ".", key, " is not defined"], ""))
116+func asString (val) = match val {
117+ case valStr: String =>
118+ valStr
119+ case _ =>
120+ throw("fail cast to String")
121+}
122122
123123
124-func getIntOrFail (address,key) = valueOrErrorMessage(getInteger(address, key), makeString(["mandatory ", toString(address), ".", key, " is not defined"], ""))
124+func getStringOrFail (addr,key) = valueOrErrorMessage(getString(addr, key), makeString(["mandatory ", toString(addr), ".", key, " is not defined"], ""))
125125
126126
127-let factoryContract = addressFromStringValue(getStringOrFail(this, keyFactoryContract()))
127+func getIntOrFail (addr,key) = valueOrErrorMessage(getInteger(addr, key), makeString(["mandatory ", toString(addr), ".", key, " is not defined"], ""))
128+
129+
130+let factoryContract = addressFromStringValue(getStringOrFail(this, keyFactCntr()))
131+
132+let A = getStringOrFail(this, keyAmplificator())
128133
129134 func isGlobalShutdown () = valueOrElse(getBoolean(factoryContract, keyAllPoolsShutdown()), false)
130135
131136
132137 func getMatcherPubOrFail () = fromBase58String(getStringOrFail(factoryContract, keyMatcherPub()))
133138
134139
135140 func getPoolConfig () = {
136- let amtAsset = getStringOrFail(this, keyAmtAsset())
137- let priceAsset = getStringOrFail(this, keyPriceAsset())
138- let iPriceAsset = getIntOrFail(factoryContract, keyMappingsBaseAsset2internalId(priceAsset))
139- let iAmtAsset = getIntOrFail(factoryContract, keyMappingsBaseAsset2internalId(amtAsset))
140- split(getStringOrFail(factoryContract, keyPoolConfig(toString(iAmtAsset), toString(iPriceAsset))), SEP)
141+ let amtAs = getStringOrFail(this, keyAmtAsset())
142+ let priceAs = getStringOrFail(this, keyPriceAsset())
143+ let iPriceAs = getIntOrFail(factoryContract, keyMappingsBaseAsset2internalId(priceAs))
144+ let iAmtAs = getIntOrFail(factoryContract, keyMappingsBaseAsset2internalId(amtAs))
145+ split(getStringOrFail(factoryContract, keyPoolConfig(toString(iAmtAs), toString(iPriceAs))), SEP)
141146 }
142147
143148
144149 func getFactoryConfig () = split(getStringOrFail(factoryContract, keyFactoryConfig()), SEP)
145150
146151
147-func dataPutActionInfo (inAmtAssetAmt,inPriceAssetAmt,outLpAmt,price,slippageTolerancePassedByUser,slippageToleranceReal,txHeight,txTimestamp,slipageAmtAssetAmt,slipagePriceAssetAmt) = makeString(["%d%d%d%d%d%d%d%d%d%d", toString(inAmtAssetAmt), toString(inPriceAssetAmt), toString(outLpAmt), toString(price), toString(slippageTolerancePassedByUser), toString(slippageToleranceReal), toString(txHeight), toString(txTimestamp), toString(slipageAmtAssetAmt), toString(slipagePriceAssetAmt)], SEP)
152+func dataPutActionInfo (inAmtAssetAmt,inPriceAssetAmt,outLpAmt,price,slipByUser,slippageReal,txHeight,txTimestamp,slipageAmAmt,slipagePrAmt) = makeString(["%d%d%d%d%d%d%d%d%d%d", toString(inAmtAssetAmt), toString(inPriceAssetAmt), toString(outLpAmt), toString(price), toString(slipByUser), toString(slippageReal), toString(txHeight), toString(txTimestamp), toString(slipageAmAmt), toString(slipagePrAmt)], SEP)
148153
149154
150155 func dataGetActionInfo (outAmtAssetAmt,outPriceAssetAmt,inLpAmt,price,txHeight,txTimestamp) = makeString(["%d%d%d%d%d%d", toString(outAmtAssetAmt), toString(outPriceAssetAmt), toString(inLpAmt), toString(price), toString(txHeight), toString(txTimestamp)], SEP)
151156
152157
153158 func getAccBalance (assetId) = if ((assetId == "WAVES"))
154159 then wavesBalance(this).available
155160 else assetBalance(this, fromBase58String(assetId))
156161
157162
158163 func calcPriceBigInt (prAmtX18,amAmtX18) = fraction(prAmtX18, scale18, amAmtX18)
159164
160165
166+func validateAbsDiff (realAmt,expectedAmt,slippage) = {
167+ let diff = fraction((realAmt - expectedAmt), scale8BigInt, expectedAmt)
168+ let passed = ((slippage - abs(diff)) > zeroBigInt)
169+ if (!(passed))
170+ then throw(((("Too big slippage: " + toString(diff)) + " vs ") + toString(slippage)))
171+ else $Tuple2(passed, min([realAmt, expectedAmt]))
172+ }
173+
174+
161175 func privateCalcPrice (amAssetDcm,prAssetDcm,amAmt,prAmt) = {
162- let amtAssetAmtX18 = toX18(amAmt, amAssetDcm)
163- let priceAssetAmtX18 = toX18(prAmt, prAssetDcm)
164- calcPriceBigInt(priceAssetAmtX18, amtAssetAmtX18)
176+ let amtAsAmtX18 = toX18(amAmt, amAssetDcm)
177+ let prAsAmtX18 = toX18(prAmt, prAssetDcm)
178+ calcPriceBigInt(prAsAmtX18, amtAsAmtX18)
165179 }
166180
167181
168182 func calcPrices (amAmt,prAmt,lpAmt) = {
169183 let cfg = getPoolConfig()
170- let amtAssetDcm = parseIntValue(cfg[idxAmtAssetDcm])
171- let priceAssetDcm = parseIntValue(cfg[idxPriceAssetDcm])
172- let priceX18 = privateCalcPrice(amtAssetDcm, priceAssetDcm, amAmt, prAmt)
173- let amAmtX18 = toX18(amAmt, amtAssetDcm)
174- let prAmtX18 = toX18(prAmt, priceAssetDcm)
184+ let amtAsDcm = parseIntValue(cfg[idxAmtAsDcm])
185+ let prAsDcm = parseIntValue(cfg[idxPriceAsDcm])
186+ let priceX18 = privateCalcPrice(amtAsDcm, prAsDcm, amAmt, prAmt)
187+ let amAmtX18 = toX18(amAmt, amtAsDcm)
188+ let prAmtX18 = toX18(prAmt, prAsDcm)
175189 let lpAmtX18 = toX18(lpAmt, scale8)
176- let lpPriceInAmAssetX18 = calcPriceBigInt(amAmtX18, lpAmtX18)
177- let lpPriceInPrAssetX18 = calcPriceBigInt(prAmtX18, lpAmtX18)
178-[priceX18, lpPriceInAmAssetX18, lpPriceInPrAssetX18]
190+ let lpPrInAmAsX18 = calcPriceBigInt(amAmtX18, lpAmtX18)
191+ let lpPrInPrAsX18 = calcPriceBigInt(prAmtX18, lpAmtX18)
192+[priceX18, lpPrInAmAsX18, lpPrInPrAsX18]
179193 }
180194
181195
182196 func calculatePrices (amAmt,prAmt,lpAmt) = {
183197 let prices = calcPrices(amAmt, prAmt, lpAmt)
184198 [fromX18(prices[0], scale8), fromX18(prices[1], scale8), fromX18(prices[2], scale8)]
185199 }
186200
187201
188202 func estimateGetOperation (txId58,pmtAssetId,pmtLpAmt,userAddress) = {
189203 let cfg = getPoolConfig()
190- let lpAssetId = cfg[idxPoolLPAssetId]
191- let amAssetId = cfg[idxAmtAssetId]
192- let prAssetId = cfg[idxPriceAssetId]
193- let amAssetDcm = parseIntValue(cfg[idxAmtAssetDcm])
194- let prAssetDcm = parseIntValue(cfg[idxPriceAssetDcm])
195- let poolStatus = cfg[idxPoolStatus]
196- let lpEmission = valueOrErrorMessage(assetInfo(fromBase58String(lpAssetId)), (("Asset " + lpAssetId) + " doesn't exist")).quantity
197- if ((lpAssetId != pmtAssetId))
198- then throw("Invalid asset passed.")
204+ let lpId = cfg[idxLPAsId]
205+ let amId = cfg[idxAmAsId]
206+ let prId = cfg[idxPrAsId]
207+ let amDcm = parseIntValue(cfg[idxAmtAsDcm])
208+ let prDcm = parseIntValue(cfg[idxPriceAsDcm])
209+ let poolStatus = cfg[idxPoolSt]
210+ let lpEmission = valueOrErrorMessage(assetInfo(fromBase58String(lpId)), "Invalid LP id").quantity
211+ if ((lpId != pmtAssetId))
212+ then throw("Invalid pmt asset")
199213 else {
200- let amBalance = getAccBalance(amAssetId)
201- let amBalanceX18 = toX18(amBalance, amAssetDcm)
202- let prBalance = getAccBalance(prAssetId)
203- let prBalanceX18 = toX18(prBalance, prAssetDcm)
214+ let amBalance = getAccBalance(amId)
215+ let amBalanceX18 = toX18(amBalance, amDcm)
216+ let prBalance = getAccBalance(prId)
217+ let prBalanceX18 = toX18(prBalance, prDcm)
204218 let curPriceX18 = calcPriceBigInt(prBalanceX18, amBalanceX18)
205219 let curPrice = fromX18(curPriceX18, scale8)
206220 let pmtLpAmtX18 = toX18(pmtLpAmt, scale8)
207221 let lpEmissionX18 = toX18(lpEmission, scale8)
208222 let outAmAmtX18 = fraction(amBalanceX18, pmtLpAmtX18, lpEmissionX18)
209223 let outPrAmtX18 = fraction(prBalanceX18, pmtLpAmtX18, lpEmissionX18)
210- let outAmAmt = fromX18(outAmAmtX18, amAssetDcm)
211- let outPrAmt = fromX18(outPrAmtX18, prAssetDcm)
224+ let outAmAmt = fromX18(outAmAmtX18, amDcm)
225+ let outPrAmt = fromX18(outPrAmtX18, prDcm)
212226 let state = if ((txId58 == ""))
213227 then nil
214- else [ScriptTransfer(userAddress, outAmAmt, if ((amAssetId == "WAVES"))
228+ else [ScriptTransfer(userAddress, outAmAmt, if ((amId == "WAVES"))
215229 then unit
216- else fromBase58String(amAssetId)), ScriptTransfer(userAddress, outPrAmt, if ((prAssetId == "WAVES"))
230+ else fromBase58String(amId)), ScriptTransfer(userAddress, outPrAmt, if ((prId == "WAVES"))
217231 then unit
218- else fromBase58String(prAssetId)), StringEntry(keyGetActionByUser(toString(userAddress), txId58), dataGetActionInfo(outAmAmt, outPrAmt, pmtLpAmt, curPrice, height, lastBlock.timestamp)), IntegerEntry(keyPriceLast(), curPrice), IntegerEntry(keyPriceHistory(height, lastBlock.timestamp), curPrice)]
219- $Tuple10(outAmAmt, outPrAmt, amAssetId, prAssetId, amBalance, prBalance, lpEmission, curPriceX18, poolStatus, state)
232+ else fromBase58String(prId)), StringEntry(keyGetActionByUser(toString(userAddress), txId58), dataGetActionInfo(outAmAmt, outPrAmt, pmtLpAmt, curPrice, height, lastBlock.timestamp)), IntegerEntry(keyPriceLast(), curPrice), IntegerEntry(keyPriceHistory(height, lastBlock.timestamp), curPrice)]
233+ $Tuple10(outAmAmt, outPrAmt, amId, prId, amBalance, prBalance, lpEmission, curPriceX18, poolStatus, state)
220234 }
221235 }
222236
223237
224-func estimatePutOperation (txId58,slippageTolerance,inAmAssetAmt,inAmAssetId,inPrAssetAmt,inPrAssetId,userAddress,isEvaluate,emitLp) = {
238+func estimatePutOperation (txId58,slippage,inAmAmt,inAmId,inPrAmt,inPrId,userAddress,isEval,emitLp,isOneAsset,pmtAmt,pmtId) = {
225239 let cfg = getPoolConfig()
226- let lpAssetId = fromBase58String(cfg[idxPoolLPAssetId])
227- let amAssetIdStr = cfg[idxAmtAssetId]
228- let prAssetIdStr = cfg[idxPriceAssetId]
229- let iAmtAssetId = cfg[idxIAmtAssetId]
230- let iPriceAssetId = cfg[idxIPriceAssetId]
231- let amtAssetDcm = parseIntValue(cfg[idxAmtAssetDcm])
232- let priceAssetDcm = parseIntValue(cfg[idxPriceAssetDcm])
233- let poolStatus = cfg[idxPoolStatus]
234- let lpEmission = valueOrErrorMessage(assetInfo(lpAssetId), (("Asset " + toBase58String(lpAssetId)) + " doesn't exist")).quantity
235- let inAmAssetIdStr = toBase58String(valueOrElse(inAmAssetId, fromBase58String("WAVES")))
236- let inPrAssetIdStr = toBase58String(valueOrElse(inPrAssetId, fromBase58String("WAVES")))
237- if (if ((amAssetIdStr != inAmAssetIdStr))
238- then true
239- else (prAssetIdStr != inPrAssetIdStr))
240- then throw("Invalid amt or price asset passed.")
240+ let lpId = fromBase58String(cfg[idxLPAsId])
241+ let amIdStr = cfg[idxAmAsId]
242+ let prIdStr = cfg[idxPrAsId]
243+ let inAmIdStr = cfg[idxIAmtAsId]
244+ let inPrIdStr = cfg[idxIPriceAsId]
245+ let amtDcm = parseIntValue(cfg[idxAmtAsDcm])
246+ let priceDcm = parseIntValue(cfg[idxPriceAsDcm])
247+ let poolStatus = cfg[idxPoolSt]
248+ let lpEm = valueOrErrorMessage(assetInfo(lpId), "Wr lp as").quantity
249+ let amBalance = if (isEval)
250+ then getAccBalance(amIdStr)
251+ else if (if (isOneAsset)
252+ then (pmtId == amIdStr)
253+ else false)
254+ then (getAccBalance(amIdStr) - pmtAmt)
255+ else if (isOneAsset)
256+ then getAccBalance(amIdStr)
257+ else (getAccBalance(amIdStr) - inAmAmt)
258+ let prBalance = if (isEval)
259+ then getAccBalance(prIdStr)
260+ else if (if (isOneAsset)
261+ then (pmtId == prIdStr)
262+ else false)
263+ then (getAccBalance(prIdStr) - pmtAmt)
264+ else if (isOneAsset)
265+ then getAccBalance(prIdStr)
266+ else (getAccBalance(prIdStr) - inPrAmt)
267+ let inAmAssetAmtX18 = toX18(inAmAmt, amtDcm)
268+ let inPrAssetAmtX18 = toX18(inPrAmt, priceDcm)
269+ let userPriceX18 = calcPriceBigInt(inPrAssetAmtX18, inAmAssetAmtX18)
270+ let amBalanceX18 = toX18(amBalance, amtDcm)
271+ let prBalanceX18 = toX18(prBalance, priceDcm)
272+ let res = if ((lpEm == 0))
273+ then {
274+ let curPriceX18 = zeroBigInt
275+ let slippageX18 = zeroBigInt
276+ let lpAmtX18 = pow((inAmAssetAmtX18 * inPrAssetAmtX18), 0, toBigInt(5), 1, 0, DOWN)
277+ $Tuple5(fromX18(lpAmtX18, scale8), fromX18(inAmAssetAmtX18, amtDcm), fromX18(inPrAssetAmtX18, priceDcm), calcPriceBigInt((prBalanceX18 + inPrAssetAmtX18), (amBalanceX18 + inAmAssetAmtX18)), slippageX18)
278+ }
241279 else {
242- let amBalance = if (isEvaluate)
243- then getAccBalance(amAssetIdStr)
244- else (getAccBalance(amAssetIdStr) - inAmAssetAmt)
245- let prBalance = if (isEvaluate)
246- then getAccBalance(prAssetIdStr)
247- else (getAccBalance(prAssetIdStr) - inPrAssetAmt)
248- let inAmAssetAmtX18 = toX18(inAmAssetAmt, amtAssetDcm)
249- let inPrAssetAmtX18 = toX18(inPrAssetAmt, priceAssetDcm)
250- let userPriceX18 = calcPriceBigInt(inPrAssetAmtX18, inAmAssetAmtX18)
251- let amBalanceX18 = toX18(amBalance, amtAssetDcm)
252- let prBalanceX18 = toX18(prBalance, priceAssetDcm)
253- let res = if ((lpEmission == 0))
254- then {
255- let curPriceX18 = zeroBigInt
256- let slippageX18 = zeroBigInt
257- let lpAmtX18 = pow((inAmAssetAmtX18 * inPrAssetAmtX18), 0, toBigInt(5), 1, 0, DOWN)
258- $Tuple5(fromX18(lpAmtX18, scale8), fromX18(inAmAssetAmtX18, amtAssetDcm), fromX18(inPrAssetAmtX18, priceAssetDcm), calcPriceBigInt((prBalanceX18 + inPrAssetAmtX18), (amBalanceX18 + inAmAssetAmtX18)), slippageX18)
280+ let curPriceX18 = calcPriceBigInt(prBalanceX18, amBalanceX18)
281+ let slippageRealX18 = fraction(abs((curPriceX18 - userPriceX18)), scale18, curPriceX18)
282+ let slippageX18 = toX18(slippage, scale8)
283+ if (if ((curPriceX18 != zeroBigInt))
284+ then (slippageRealX18 > slippageX18)
285+ else false)
286+ then throw(((("Price slippage " + toString(slippageRealX18)) + " > ") + toString(slippageX18)))
287+ else {
288+ let lpEmissionX18 = toX18(lpEm, scale8)
289+ let prViaAmX18 = fraction(inAmAssetAmtX18, curPriceX18, scale18)
290+ let amViaPrX18 = fraction(inPrAssetAmtX18, scale18, curPriceX18)
291+ let expectedAmts = if ((prViaAmX18 > inPrAssetAmtX18))
292+ then $Tuple2(amViaPrX18, inPrAssetAmtX18)
293+ else $Tuple2(inAmAssetAmtX18, prViaAmX18)
294+ let expAmtAssetAmtX18 = expectedAmts._1
295+ let expPriceAssetAmtX18 = expectedAmts._2
296+ let lpAmtX18 = fraction(lpEmissionX18, expPriceAssetAmtX18, prBalanceX18)
297+ $Tuple5(fromX18(lpAmtX18, scale8), fromX18(expAmtAssetAmtX18, amtDcm), fromX18(expPriceAssetAmtX18, priceDcm), curPriceX18, slippageX18)
259298 }
260- else {
261- let curPriceX18 = calcPriceBigInt(prBalanceX18, amBalanceX18)
262- let slippageX18 = fraction(abs((curPriceX18 - userPriceX18)), scale18, curPriceX18)
263- let slippageToleranceX18 = toX18(slippageTolerance, scale8)
264- if (if ((curPriceX18 != zeroBigInt))
265- then (slippageX18 > slippageToleranceX18)
266- else false)
267- then throw(((("Price slippage " + toString(slippageX18)) + " exceeded the passed limit of ") + toString(slippageToleranceX18)))
268- else {
269- let lpEmissionX18 = toX18(lpEmission, scale8)
270- let prViaAmX18 = fraction(inAmAssetAmtX18, curPriceX18, scale18)
271- let amViaPrX18 = fraction(inPrAssetAmtX18, scale18, curPriceX18)
272- let expectedAmts = if ((prViaAmX18 > inPrAssetAmtX18))
273- then $Tuple2(amViaPrX18, inPrAssetAmtX18)
274- else $Tuple2(inAmAssetAmtX18, prViaAmX18)
275- let expAmtAssetAmtX18 = expectedAmts._1
276- let expPriceAssetAmtX18 = expectedAmts._2
277- let lpAmtX18 = fraction(lpEmissionX18, expPriceAssetAmtX18, prBalanceX18)
278- $Tuple5(fromX18(lpAmtX18, scale8), fromX18(expAmtAssetAmtX18, amtAssetDcm), fromX18(expPriceAssetAmtX18, priceAssetDcm), curPriceX18, slippageX18)
279- }
280- }
281- let calcLpAmt = res._1
282- let calcAmAssetPmt = res._2
283- let calcPrAssetPmt = res._3
284- let curPrice = fromX18(res._4, scale8)
285- let slippageCalc = fromX18(res._5, scale8)
286- if ((0 >= calcLpAmt))
287- then throw("Invalid calculations. LP calculated is less than zero.")
288- else {
289- let emitLpAmt = if (!(emitLp))
290- then 0
291- else calcLpAmt
292- let amDiff = (inAmAssetAmt - calcAmAssetPmt)
293- let prDiff = (inPrAssetAmt - calcPrAssetPmt)
294- let commonState = [IntegerEntry(keyPriceLast(), curPrice), IntegerEntry(keyPriceHistory(height, lastBlock.timestamp), curPrice), StringEntry(keyPutActionByUser(userAddress, txId58), dataPutActionInfo(calcAmAssetPmt, calcPrAssetPmt, emitLpAmt, curPrice, slippageTolerance, slippageCalc, height, lastBlock.timestamp, amDiff, prDiff))]
295- $Tuple13(calcLpAmt, emitLpAmt, curPrice, amBalance, prBalance, lpEmission, lpAssetId, poolStatus, commonState, amDiff, prDiff, inAmAssetId, inPrAssetId)
296- }
299+ }
300+ let calcLpAmt = res._1
301+ let calcAmAssetPmt = res._2
302+ let calcPrAssetPmt = res._3
303+ let curPrice = fromX18(res._4, scale8)
304+ let slippageCalc = fromX18(res._5, scale8)
305+ if ((0 >= calcLpAmt))
306+ then throw("LP <= 0")
307+ else {
308+ let emitLpAmt = if (!(emitLp))
309+ then 0
310+ else calcLpAmt
311+ let amDiff = (inAmAmt - calcAmAssetPmt)
312+ let prDiff = (inPrAmt - calcPrAssetPmt)
313+ let $t01564215988 = if (if (isOneAsset)
314+ then (pmtId == amIdStr)
315+ else false)
316+ then $Tuple2(pmtAmt, 0)
317+ else if (if (isOneAsset)
318+ then (pmtId == prIdStr)
319+ else false)
320+ then $Tuple2(0, pmtAmt)
321+ else $Tuple2(calcAmAssetPmt, calcPrAssetPmt)
322+ let writeAmAmt = $t01564215988._1
323+ let writePrAmt = $t01564215988._2
324+ let commonState = [IntegerEntry(keyPriceLast(), curPrice), IntegerEntry(keyPriceHistory(height, lastBlock.timestamp), curPrice), StringEntry(keyPutActionByUser(userAddress, txId58), dataPutActionInfo(writeAmAmt, writePrAmt, emitLpAmt, curPrice, slippage, slippageCalc, height, lastBlock.timestamp, amDiff, prDiff))]
325+ $Tuple13(calcLpAmt, emitLpAmt, curPrice, amBalance, prBalance, lpEm, lpId, poolStatus, commonState, amDiff, prDiff, inAmId, inPrId)
297326 }
298327 }
299328
300329
301330 func validateMatcherOrderAllowed (order) = {
302331 let cfg = getPoolConfig()
303- let amtAssetId = cfg[idxAmtAssetId]
304- let priceAssetId = cfg[idxPriceAssetId]
305- let poolStatus = parseIntValue(cfg[idxPoolStatus])
306- let amtAssetDcm = parseIntValue(cfg[idxAmtAssetDcm])
307- let priceAssetDcm = parseIntValue(cfg[idxPriceAssetDcm])
308- let accAmtAssetBalance = getAccBalance(amtAssetId)
309- let accPriceAssetBalance = getAccBalance(priceAssetId)
332+ let amtAsId = cfg[idxAmAsId]
333+ let prAsId = cfg[idxPrAsId]
334+ let poolStatus = parseIntValue(cfg[idxPoolSt])
335+ let amtAsDcm = parseIntValue(cfg[idxAmtAsDcm])
336+ let prAsDcm = parseIntValue(cfg[idxPriceAsDcm])
337+ let accAmtAsBalance = getAccBalance(amtAsId)
338+ let accPrAsBalance = getAccBalance(prAsId)
310339 let curPriceX18 = if ((order.orderType == Buy))
311- then privateCalcPrice(amtAssetDcm, priceAssetDcm, (accAmtAssetBalance + order.amount), accPriceAssetBalance)
312- else privateCalcPrice(amtAssetDcm, priceAssetDcm, (accAmtAssetBalance - order.amount), accPriceAssetBalance)
340+ then privateCalcPrice(amtAsDcm, prAsDcm, (accAmtAsBalance + order.amount), accPrAsBalance)
341+ else privateCalcPrice(amtAsDcm, prAsDcm, (accAmtAsBalance - order.amount), accPrAsBalance)
313342 let curPrice = fromX18(curPriceX18, scale8)
314343 if (if (if (isGlobalShutdown())
315344 then true
316- else (poolStatus == PoolMatcherDisabled))
345+ else (poolStatus == PoolMatcherDis))
317346 then true
318347 else (poolStatus == PoolShutdown))
319- then throw("Exchange operations disabled")
348+ then throw("Admin blocked")
320349 else {
321- let orderAmtAsset = order.assetPair.amountAsset
322- let orderAmtAssetStr = if ((orderAmtAsset == unit))
350+ let orAmtAsset = order.assetPair.amountAsset
351+ let orAmtAsStr = if ((orAmtAsset == unit))
323352 then "WAVES"
324- else toBase58String(value(orderAmtAsset))
325- let orderPriceAsset = order.assetPair.priceAsset
326- let orderPriceAssetStr = if ((orderPriceAsset == unit))
353+ else toBase58String(value(orAmtAsset))
354+ let orPrAsset = order.assetPair.priceAsset
355+ let orPrAsStr = if ((orPrAsset == unit))
327356 then "WAVES"
328- else toBase58String(value(orderPriceAsset))
329- if (if ((orderAmtAssetStr != amtAssetId))
357+ else toBase58String(value(orPrAsset))
358+ if (if ((orAmtAsStr != amtAsId))
330359 then true
331- else (orderPriceAssetStr != priceAssetId))
332- then throw("Wrong order assets.")
360+ else (orPrAsStr != prAsId))
361+ then throw("Wr assets")
333362 else {
334363 let orderPrice = order.price
335- let priceDcm = fraction(scale8, priceAssetDcm, amtAssetDcm)
336- let castedOrderPrice = toScale(orderPrice, scale8, priceDcm)
364+ let priceDcm = fraction(scale8, prAsDcm, amtAsDcm)
365+ let castOrderPrice = toScale(orderPrice, scale8, priceDcm)
337366 let isOrderPriceValid = if ((order.orderType == Buy))
338- then (curPrice >= castedOrderPrice)
339- else (castedOrderPrice >= curPrice)
367+ then (curPrice >= castOrderPrice)
368+ else (castOrderPrice >= curPrice)
340369 true
341370 }
342371 }
343372 }
344373
345374
346375 func commonGet (i) = if ((size(i.payments) != 1))
347- then throw("exactly 1 payment is expected")
376+ then throw("1 pmnt exp")
348377 else {
349378 let pmt = value(i.payments[0])
350379 let pmtAssetId = value(pmt.assetId)
351380 let pmtAmt = pmt.amount
352381 let res = estimateGetOperation(toBase58String(i.transactionId), toBase58String(pmtAssetId), pmtAmt, i.caller)
353382 let outAmAmt = res._1
354383 let outPrAmt = res._2
355384 let poolStatus = parseIntValue(res._9)
356385 let state = res._10
357386 if (if (isGlobalShutdown())
358387 then true
359388 else (poolStatus == PoolShutdown))
360- then throw(("Get operation is blocked by admin. Status = " + toString(poolStatus)))
389+ then throw(("Admin blocked: " + toString(poolStatus)))
361390 else $Tuple5(outAmAmt, outPrAmt, pmtAmt, pmtAssetId, state)
362391 }
363392
364393
365-func commonPut (i,slippageTolerance,emitLp) = if ((size(i.payments) != 2))
366- then throw("exactly 2 payments are expected")
367- else {
368- let amAssetPmt = value(i.payments[0])
369- let prAssetPmt = value(i.payments[1])
370- let estPut = estimatePutOperation(toBase58String(i.transactionId), slippageTolerance, amAssetPmt.amount, amAssetPmt.assetId, prAssetPmt.amount, prAssetPmt.assetId, toString(i.caller), false, emitLp)
371- let poolStatus = parseIntValue(estPut._8)
372- if (if (if (isGlobalShutdown())
373- then true
374- else (poolStatus == PoolPutDisabled))
375- then true
376- else (poolStatus == PoolShutdown))
377- then throw(("Put operation is blocked by admin. Status = " + toString(poolStatus)))
378- else estPut
379- }
394+func commonPut (caller,txId,amAsPmt,prAsPmt,slippage,emitLp,isOneAsset,pmtAmt,pmtId) = {
395+ let r = estimatePutOperation(txId, slippage, value(amAsPmt).amount, value(amAsPmt).assetId, value(prAsPmt).amount, value(prAsPmt).assetId, caller, false, emitLp, isOneAsset, pmtAmt, pmtId)
396+ let status = parseIntValue(r._8)
397+ if (if (if (isGlobalShutdown())
398+ then true
399+ else (status == PoolPutDis))
400+ then true
401+ else (status == PoolShutdown))
402+ then throw(("Admin blocked: " + toString(status)))
403+ else r
404+ }
380405
381406
382407 @Callable(i)
383408 func constructor (factoryContract,managerPublicKey) = if ((i.caller != this))
384- then throw("permissions denied")
385- else [StringEntry(keyFactoryContract(), factoryContract), StringEntry(keyManagerPublicKey(), managerPublicKey)]
409+ then throw("denied")
410+ else [StringEntry(keyFactCntr(), factoryContract), StringEntry(keyManPubKey(), managerPublicKey)]
386411
387412
388413
389414 @Callable(i)
390-func put (slippageTolerance,shouldAutoStake) = {
391- let factoryCfg = getFactoryConfig()
392- let stakingContract = valueOrErrorMessage(addressFromString(factoryCfg[idxFactoryStakingContract]), "Error. Incorrect staking address.")
393- let slippageContract = valueOrErrorMessage(addressFromString(factoryCfg[idxFactorySlippageContract]), "Error. Incorrect slippage contract address.")
394- if ((0 > slippageTolerance))
395- then throw("Invalid slippageTolerance passed")
396- else {
397- let estPut = commonPut(i, slippageTolerance, true)
398- let emitLpAmt = estPut._2
399- let lpAssetId = estPut._7
400- let state = estPut._9
401- let amDiff = estPut._10
402- let prDiff = estPut._11
403- let amId = estPut._12
404- let prId = estPut._13
405- let emitInv = invoke(factoryContract, "emit", [emitLpAmt], nil)
406- if ((emitInv == emitInv))
407- then {
408- let slippageAInv = if ((amDiff > 0))
409- then invoke(slippageContract, "put", nil, [AttachedPayment(amId, amDiff)])
410- else nil
411- if ((slippageAInv == slippageAInv))
412- then {
413- let slippagePInv = if ((prDiff > 0))
414- then invoke(slippageContract, "put", nil, [AttachedPayment(prId, prDiff)])
415- else nil
416- if ((slippagePInv == slippagePInv))
417- then {
418- let lpTransfer = if (shouldAutoStake)
419- then {
420- let slpStakeInv = invoke(stakingContract, "stake", nil, [AttachedPayment(lpAssetId, emitLpAmt)])
421- if ((slpStakeInv == slpStakeInv))
422- then nil
423- else throw("Strict value is not equal to itself.")
424- }
425- else [ScriptTransfer(i.caller, emitLpAmt, lpAssetId)]
426- (state ++ lpTransfer)
427- }
428- else throw("Strict value is not equal to itself.")
429- }
430- else throw("Strict value is not equal to itself.")
431- }
432- else throw("Strict value is not equal to itself.")
433- }
415+func put (slip,autoStake) = {
416+ let factCfg = getFactoryConfig()
417+ let stakingCntr = valueOrErrorMessage(addressFromString(factCfg[idxFactStakCntr]), "Wr st addr")
418+ let slipCntr = valueOrErrorMessage(addressFromString(factCfg[idxFactSlippCntr]), "Wr sl addr")
419+ if ((0 > slip))
420+ then throw("Invalid slippage")
421+ else if ((size(i.payments) != 2))
422+ then throw("2 pmnts expected")
423+ else {
424+ let estPut = commonPut(toString(i.caller), toBase58String(i.transactionId), AttachedPayment(value(i.payments[0]).assetId, value(i.payments[0]).amount), i.payments[1], slip, true, false, 0, "")
425+ let emitLpAmt = estPut._2
426+ let lpAssetId = estPut._7
427+ let state = estPut._9
428+ let amDiff = estPut._10
429+ let prDiff = estPut._11
430+ let amId = estPut._12
431+ let prId = estPut._13
432+ let emitInv = invoke(factoryContract, "emit", [emitLpAmt], nil)
433+ if ((emitInv == emitInv))
434+ then {
435+ let slippageAInv = if ((amDiff > 0))
436+ then invoke(slipCntr, "put", nil, [AttachedPayment(amId, amDiff)])
437+ else nil
438+ if ((slippageAInv == slippageAInv))
439+ then {
440+ let slippagePInv = if ((prDiff > 0))
441+ then invoke(slipCntr, "put", nil, [AttachedPayment(prId, prDiff)])
442+ else nil
443+ if ((slippagePInv == slippagePInv))
444+ then {
445+ let lpTrnsfr = if (autoStake)
446+ then {
447+ let slpStakeInv = invoke(stakingCntr, "stake", nil, [AttachedPayment(lpAssetId, emitLpAmt)])
448+ if ((slpStakeInv == slpStakeInv))
449+ then nil
450+ else throw("Strict value is not equal to itself.")
451+ }
452+ else [ScriptTransfer(i.caller, emitLpAmt, lpAssetId)]
453+ (state ++ lpTrnsfr)
454+ }
455+ else throw("Strict value is not equal to itself.")
456+ }
457+ else throw("Strict value is not equal to itself.")
458+ }
459+ else throw("Strict value is not equal to itself.")
460+ }
461+ }
462+
463+
464+
465+@Callable(i)
466+func putOneTkn (amAssetPart,prAssetPart,outLp,slippage,autoStake) = {
467+ let cfg = getFactoryConfig()
468+ let stakingCntr = valueOrErrorMessage(addressFromString(cfg[idxFactStakCntr]), "Wr st addr")
469+ let slipCntr = valueOrErrorMessage(addressFromString(cfg[idxFactSlippCntr]), "Wr sl addr")
470+ let gwxCntr = valueOrErrorMessage(addressFromString(cfg[idxFactGwxRewCntr]), "Wr gwx addr")
471+ let poolCfg = getPoolConfig()
472+ let amId = poolCfg[idxAmAsId]
473+ let prId = poolCfg[idxPrAsId]
474+ let amDcm = parseIntValue(poolCfg[idxAmtAsDcm])
475+ let prDcm = parseIntValue(poolCfg[idxPriceAsDcm])
476+ if (if (if (if ((0 >= slippage))
477+ then true
478+ else (0 >= amAssetPart))
479+ then true
480+ else (0 >= prAssetPart))
481+ then true
482+ else (0 >= outLp))
483+ then throw("Wrong params")
484+ else if ((size(i.payments) != 1))
485+ then throw("1 pmnt expected")
486+ else {
487+ let pmt = value(i.payments[0])
488+ let pmtAssetId = toBase58String(value(pmt.assetId))
489+ let pmtAmt = pmt.amount
490+ let amBalance = getAccBalance(amId)
491+ let prBalance = getAccBalance(prId)
492+ let $t02366124041 = if ((pmtAssetId == amId))
493+ then $Tuple6((amBalance - pmtAmt), prBalance, (pmtAmt - amAssetPart), prAssetPart, 0, 0)
494+ else if ((pmtAssetId == prId))
495+ then $Tuple6(amBalance, (prBalance - pmtAmt), 0, 0, (pmtAmt - prAssetPart), amAssetPart)
496+ else throw("wrong pmtAssetId")
497+ let amBalanceNow = $t02366124041._1
498+ let prBalanceNow = $t02366124041._2
499+ let virtSwapInAm = $t02366124041._3
500+ let virtSwapOutPr = $t02366124041._4
501+ let virtSwapInPr = $t02366124041._5
502+ let virtSwapOutAm = $t02366124041._6
503+ let D0 = invoke(gwxCntr, "calcD", [toString(amBalanceNow), toString(prBalanceNow), A, Amult, Dconv], nil)
504+ let D1 = invoke(gwxCntr, "calcD", [toString(toBigInt(((amBalanceNow + virtSwapInAm) - virtSwapOutAm))), toString(toBigInt(((prBalanceNow + virtSwapInPr) - virtSwapOutPr))), A, Amult, Dconv], nil)
505+ let D0vsD1 = validateAbsDiff(parseBigIntValue(asString(D1)), parseBigIntValue(asString(D0)), toBigInt(1000))
506+ if ((D0vsD1 == D0vsD1))
507+ then {
508+ let estPut = commonPut(toString(i.caller), toBase58String(i.transactionId), AttachedPayment(fromBase58String(amId), amAssetPart), AttachedPayment(fromBase58String(prId), prAssetPart), 50000000000, true, true, pmtAmt, pmtAssetId)
509+ let estimLP = estPut._2
510+ let lpAssetId = estPut._7
511+ let state = estPut._9
512+ let amDiff = estPut._10
513+ let prDiff = estPut._11
514+ let lpCalcRes = validateAbsDiff(toBigInt(estimLP), toBigInt(outLp), toBigInt(slippage))
515+ let emitLpAmt = toInt(lpCalcRes._2)
516+ let emitInv = invoke(factoryContract, "emit", [emitLpAmt], nil)
517+ if ((emitInv == emitInv))
518+ then {
519+ let slippageAInv = if ((amDiff > 0))
520+ then invoke(slipCntr, "put", nil, [AttachedPayment(fromBase58String(amId), amDiff)])
521+ else nil
522+ if ((slippageAInv == slippageAInv))
523+ then {
524+ let slippagePInv = if ((prDiff > 0))
525+ then invoke(slipCntr, "put", nil, [AttachedPayment(fromBase58String(prId), prDiff)])
526+ else nil
527+ if ((slippagePInv == slippagePInv))
528+ then {
529+ let lpTrnsfr = if (autoStake)
530+ then {
531+ let slpStakeInv = invoke(stakingCntr, "stake", nil, [AttachedPayment(lpAssetId, emitLpAmt)])
532+ if ((slpStakeInv == slpStakeInv))
533+ then nil
534+ else throw("Strict value is not equal to itself.")
535+ }
536+ else [ScriptTransfer(i.caller, emitLpAmt, lpAssetId)]
537+ (state ++ lpTrnsfr)
538+ }
539+ else throw("Strict value is not equal to itself.")
540+ }
541+ else throw("Strict value is not equal to itself.")
542+ }
543+ else throw("Strict value is not equal to itself.")
544+ }
545+ else throw("Strict value is not equal to itself.")
546+ }
434547 }
435548
436549
437550
438551 @Callable(i)
439552 func putForFree (maxSlippage) = if ((0 > maxSlippage))
440- then throw("Invalid value passed")
441- else {
442- let estPut = commonPut(i, maxSlippage, false)
443- estPut._9
444- }
553+ then throw("Invalid slippage")
554+ else if ((size(i.payments) != 2))
555+ then throw("2 pmnts expected")
556+ else {
557+ let estPut = commonPut(toString(i.caller), toBase58String(i.transactionId), AttachedPayment(value(i.payments[0]).assetId, value(i.payments[0]).amount), i.payments[1], maxSlippage, false, false, 0, "")
558+ estPut._9
559+ }
445560
446561
447562
448563 @Callable(i)
449564 func get () = {
450565 let res = commonGet(i)
451566 let outAmtAmt = res._1
452567 let outPrAmt = res._2
453568 let pmtAmt = res._3
454569 let pmtAssetId = res._4
455570 let state = res._5
456571 let burnLPAssetOnFactory = invoke(factoryContract, "burn", [pmtAmt], [AttachedPayment(pmtAssetId, pmtAmt)])
457572 if ((burnLPAssetOnFactory == burnLPAssetOnFactory))
458573 then state
459574 else throw("Strict value is not equal to itself.")
460575 }
461576
462577
463578
464579 @Callable(i)
580+func getOneTkn (amAssetSwap,prAssetSwap,outAmount,outAssetId,slippage) = if ((size(i.payments) != 1))
581+ then throw("1 pmnt expected")
582+ else {
583+ let cfg = getPoolConfig()
584+ let lpId = cfg[idxLPAsId]
585+ let amId = cfg[idxAmAsId]
586+ let prId = cfg[idxPrAsId]
587+ let amDcm = parseIntValue(cfg[idxAmtAsDcm])
588+ let prDcm = parseIntValue(cfg[idxPriceAsDcm])
589+ let poolStatus = cfg[idxPoolSt]
590+ let fcfg = getFactoryConfig()
591+ let gwxCntr = valueOrErrorMessage(addressFromString(fcfg[idxFactGwxRewCntr]), "Wr sl addr")
592+ let pmt = value(i.payments[0])
593+ let userAddress = i.caller
594+ let txId58 = toBase58String(i.transactionId)
595+ let pmtAssetId = value(pmt.assetId)
596+ let pmtAmt = pmt.amount
597+ if (if (if (if ((0 > slippage))
598+ then true
599+ else (0 > amAssetSwap))
600+ then true
601+ else (0 > prAssetSwap))
602+ then true
603+ else (0 > outAmount))
604+ then throw("Wrong params")
605+ else if ((lpId != toBase58String(pmtAssetId)))
606+ then throw("Invalid LP")
607+ else {
608+ let r = estimateGetOperation(toBase58String(i.transactionId), toBase58String(pmtAssetId), pmtAmt, i.caller)
609+ let estimAmAmt = r._1
610+ let estimPrAmt = r._2
611+ let amBalance = getAccBalance(amId)
612+ let prBalance = getAccBalance(prId)
613+ let $t02849828982 = if ((outAssetId == amId))
614+ then $Tuple7((amBalance - estimAmAmt), (prBalance - estimPrAmt), (outAmount - estimAmAmt), prAssetSwap, 0, 0, (estimAmAmt + amAssetSwap))
615+ else if ((outAssetId == prId))
616+ then $Tuple7((amBalance - estimAmAmt), (prBalance - estimPrAmt), 0, 0, (outAmount - estimPrAmt), amAssetSwap, (estimPrAmt + prAssetSwap))
617+ else throw("wrong outAssetId")
618+ let amBalanceNow = $t02849828982._1
619+ let prBalanceNow = $t02849828982._2
620+ let virtSwapInAm = $t02849828982._3
621+ let virtSwapOutPr = $t02849828982._4
622+ let virtSwapInPr = $t02849828982._5
623+ let virtSwapOutAm = $t02849828982._6
624+ let totalGet = $t02849828982._7
625+ let D0 = invoke(gwxCntr, "calcD", [toString(amBalanceNow), toString(prBalanceNow), A, Amult, Dconv], nil)
626+ let D1 = invoke(gwxCntr, "calcD", [toString(((amBalanceNow - virtSwapInAm) + virtSwapOutAm)), toString(((prBalanceNow + virtSwapOutPr) - virtSwapInPr)), A, Amult, Dconv], nil)
627+ let D0vsD1 = validateAbsDiff(parseBigIntValue(asString(D1)), parseBigIntValue(asString(D0)), toBigInt(1000))
628+ if ((D0vsD1 == D0vsD1))
629+ then {
630+ let amount2Return = validateAbsDiff(toBigInt(totalGet), toBigInt(outAmount), toBigInt(slippage))
631+ if ((amount2Return == amount2Return))
632+ then {
633+ let $t02965829772 = if ((outAssetId == amId))
634+ then $Tuple2(toInt(amount2Return._2), 0)
635+ else $Tuple2(0, toInt(amount2Return._2))
636+ let outAm = $t02965829772._1
637+ let outPr = $t02965829772._2
638+ let curPriceX18 = calcPriceBigInt(toX18(prBalance, prDcm), toX18(amBalance, amDcm))
639+ let curPrice = fromX18(curPriceX18, scale8)
640+ let state = [ScriptTransfer(userAddress, (outAm + outPr), if ((outAssetId == "WAVES"))
641+ then unit
642+ else fromBase58String(outAssetId)), StringEntry(keyGetActionByUser(toString(userAddress), txId58), dataGetActionInfo(outAm, outPr, pmtAmt, curPrice, height, lastBlock.timestamp)), IntegerEntry(keyPriceLast(), curPrice), IntegerEntry(keyPriceHistory(height, lastBlock.timestamp), curPrice)]
643+ if ((state == state))
644+ then {
645+ let burn = invoke(factoryContract, "burn", [pmtAmt], [AttachedPayment(pmtAssetId, pmtAmt)])
646+ if ((burn == burn))
647+ then state
648+ else throw("Strict value is not equal to itself.")
649+ }
650+ else throw("Strict value is not equal to itself.")
651+ }
652+ else throw("Strict value is not equal to itself.")
653+ }
654+ else throw("Strict value is not equal to itself.")
655+ }
656+ }
657+
658+
659+
660+@Callable(i)
465661 func getNoLess (noLessThenAmtAsset,noLessThenPriceAsset) = {
466662 let res = commonGet(i)
467663 let outAmAmt = res._1
468664 let outPrAmt = res._2
469665 let pmtAmt = res._3
470666 let pmtAssetId = res._4
471667 let state = res._5
472668 if ((noLessThenAmtAsset > outAmAmt))
473- then throw(((("noLessThenAmtAsset failed: " + toString(outAmAmt)) + " < ") + toString(noLessThenAmtAsset)))
669+ then throw(((("Failed: " + toString(outAmAmt)) + " < ") + toString(noLessThenAmtAsset)))
474670 else if ((noLessThenPriceAsset > outPrAmt))
475- then throw(((("noLessThenPriceAsset failed: " + toString(outPrAmt)) + " < ") + toString(noLessThenPriceAsset)))
671+ then throw(((("Failed: " + toString(outPrAmt)) + " < ") + toString(noLessThenPriceAsset)))
476672 else {
477673 let burnLPAssetOnFactory = invoke(factoryContract, "burn", [pmtAmt], [AttachedPayment(pmtAssetId, pmtAmt)])
478674 if ((burnLPAssetOnFactory == burnLPAssetOnFactory))
479675 then state
480676 else throw("Strict value is not equal to itself.")
481677 }
482678 }
483679
484680
485681
486682 @Callable(i)
487683 func unstakeAndGet (amount) = {
488684 let checkPayments = if ((size(i.payments) != 0))
489- then throw("No payments are expected")
685+ then throw("No pmnts expected")
490686 else true
491687 if ((checkPayments == checkPayments))
492688 then {
493689 let cfg = getPoolConfig()
494690 let factoryCfg = getFactoryConfig()
495- let lpAssetId = fromBase58String(cfg[idxPoolLPAssetId])
496- let stakingContract = valueOrErrorMessage(addressFromString(factoryCfg[idxFactoryStakingContract]), "Error. Incorrect staking address.")
691+ let lpAssetId = fromBase58String(cfg[idxLPAsId])
692+ let stakingContract = valueOrErrorMessage(addressFromString(factoryCfg[idxFactStakCntr]), "Wr st addr")
497693 let unstakeInv = invoke(stakingContract, "unstake", [toBase58String(lpAssetId), amount], nil)
498694 if ((unstakeInv == unstakeInv))
499695 then {
500- let res = estimateGetOperation(toBase58String(i.transactionId), toBase58String(lpAssetId), amount, i.caller)
501- let poolStatus = parseIntValue(res._9)
502- let state = res._10
696+ let r = estimateGetOperation(toBase58String(i.transactionId), toBase58String(lpAssetId), amount, i.caller)
697+ let poolStatus = parseIntValue(r._9)
698+ let state = r._10
503699 let checkPoolStatus = if (if (isGlobalShutdown())
504700 then true
505701 else (poolStatus == PoolShutdown))
506- then throw(("Get operation is blocked by admin. Status = " + toString(poolStatus)))
702+ then throw(("Blocked: " + toString(poolStatus)))
507703 else true
508704 if ((checkPoolStatus == checkPoolStatus))
509705 then {
510706 let burnLPAssetOnFactory = invoke(factoryContract, "burn", [amount], [AttachedPayment(lpAssetId, amount)])
511707 if ((burnLPAssetOnFactory == burnLPAssetOnFactory))
512708 then state
513709 else throw("Strict value is not equal to itself.")
514710 }
515711 else throw("Strict value is not equal to itself.")
516712 }
517713 else throw("Strict value is not equal to itself.")
518714 }
519715 else throw("Strict value is not equal to itself.")
520716 }
521717
522718
523719
524720 @Callable(i)
525721 func activate (amtAssetStr,priceAssetStr) = if ((toString(i.caller) != toString(factoryContract)))
526- then throw("permissions denied")
722+ then throw("denied")
527723 else $Tuple2([StringEntry(keyAmtAsset(), amtAssetStr), StringEntry(keyPriceAsset(), priceAssetStr)], "success")
528724
529725
530726
531727 @Callable(i)
532728 func getPoolConfigWrapperREADONLY () = $Tuple2(nil, getPoolConfig())
533729
534730
535731
536732 @Callable(i)
537733 func getAccBalanceWrapperREADONLY (assetId) = $Tuple2(nil, getAccBalance(assetId))
538734
539735
540736
541737 @Callable(i)
542738 func calcPricesWrapperREADONLY (amAmt,prAmt,lpAmt) = {
543739 let prices = calcPrices(amAmt, prAmt, lpAmt)
544740 $Tuple2(nil, [toString(prices[0]), toString(prices[1]), toString(prices[2])])
545741 }
546742
547743
548744
549745 @Callable(i)
550-func toX18WrapperREADONLY (origVal,origScaleMult) = $Tuple2(nil, toString(toX18(origVal, origScaleMult)))
746+func fromX18WrapperREADONLY (val,resultScaleMult) = $Tuple2(nil, fromX18(parseBigIntValue(val), resultScaleMult))
551747
552748
553749
554750 @Callable(i)
555-func fromX18WrapperREADONLY (val,resultScaleMult) = $Tuple2(nil, fromX18(parseBigIntValue(val), resultScaleMult))
751+func toX18WrapperREADONLY (origVal,origScaleMult) = $Tuple2(nil, toString(toX18(origVal, origScaleMult)))
556752
557753
558754
559755 @Callable(i)
560756 func calcPriceBigIntWrapperREADONLY (prAmtX18,amAmtX18) = $Tuple2(nil, toString(calcPriceBigInt(parseBigIntValue(prAmtX18), parseBigIntValue(amAmtX18))))
561757
562758
563759
564760 @Callable(i)
565-func estimatePutOperationWrapperREADONLY (txId58,slippageTolerance,inAmAssetAmt,inAmAssetId,inPrAssetAmt,inPrAssetId,userAddress,isEvaluate,emitLp) = $Tuple2(nil, estimatePutOperation(txId58, slippageTolerance, inAmAssetAmt, inAmAssetId, inPrAssetAmt, inPrAssetId, userAddress, isEvaluate, emitLp))
761+func estimatePutOperationWrapperREADONLY (txId58,slippage,inAmAmt,inAmId,inPrAmt,inPrId,usrAddr,isEval,emitLp) = $Tuple2(nil, estimatePutOperation(txId58, slippage, inAmAmt, inAmId, inPrAmt, inPrId, usrAddr, isEval, emitLp, false, 0, ""))
566762
567763
568764
569765 @Callable(i)
570-func estimateGetOperationWrapperREADONLY (txId58,pmtAssetId,pmtLpAmt,userAddress) = {
571- let res = estimateGetOperation(txId58, pmtAssetId, pmtLpAmt, addressFromStringValue(userAddress))
766+func estimateGetOperationWrapperREADONLY (txId58,pmtAsId,pmtLpAmt,usrAddr) = {
767+ let res = estimateGetOperation(txId58, pmtAsId, pmtLpAmt, addressFromStringValue(usrAddr))
572768 $Tuple2(nil, $Tuple10(res._1, res._2, res._3, res._4, res._5, res._6, res._7, toString(res._8), res._9, res._10))
573- }
574-
575-
576-
577-@Callable(i)
578-func statsREADONLY () = {
579- let cfg = getPoolConfig()
580- let lpAssetId = fromBase58String(cfg[idxPoolLPAssetId])
581- let amtAssetId = cfg[idxAmtAssetId]
582- let priceAssetId = cfg[idxPriceAssetId]
583- let iAmtAssetId = cfg[idxIAmtAssetId]
584- let iPriceAssetId = cfg[idxIPriceAssetId]
585- let amtAssetDcm = parseIntValue(cfg[idxAmtAssetDcm])
586- let priceAssetDcm = parseIntValue(cfg[idxPriceAssetDcm])
587- let poolLPBalance = valueOrErrorMessage(assetInfo(lpAssetId), (("Asset " + toBase58String(lpAssetId)) + " doesn't exist")).quantity
588- let accAmtAssetBalance = getAccBalance(amtAssetId)
589- let accPriceAssetBalance = getAccBalance(priceAssetId)
590- let pricesList = if ((poolLPBalance == 0))
591- then [zeroBigInt, zeroBigInt, zeroBigInt]
592- else calcPrices(accAmtAssetBalance, accPriceAssetBalance, poolLPBalance)
593- let curPrice = 0
594- let lpAmtAssetShare = fromX18(pricesList[1], scale8)
595- let lpPriceAssetShare = fromX18(pricesList[2], scale8)
596- let poolWeight = value(getInteger(factoryContract, keyPoolWeight(toString(this))))
597- $Tuple2(nil, makeString(["%d%d%d%d%d%d%d", toString(accAmtAssetBalance), toString(accPriceAssetBalance), toString(poolLPBalance), toString(curPrice), toString(lpAmtAssetShare), toString(lpPriceAssetShare), toString(poolWeight)], SEP))
598- }
599-
600-
601-
602-@Callable(i)
603-func evaluatePutByAmountAssetREADONLY (inAmAssetAmt) = {
604- let cfg = getPoolConfig()
605- let lpAssetId = fromBase58String(cfg[idxPoolLPAssetId])
606- let amAssetIdStr = cfg[idxAmtAssetId]
607- let amAssetId = fromBase58String(amAssetIdStr)
608- let prAssetIdStr = cfg[idxPriceAssetId]
609- let prAssetId = fromBase58String(prAssetIdStr)
610- let amtAssetDcm = parseIntValue(cfg[idxAmtAssetDcm])
611- let priceAssetDcm = parseIntValue(cfg[idxPriceAssetDcm])
612- let poolStatus = cfg[idxPoolStatus]
613- let poolLPBalance = valueOrErrorMessage(assetInfo(lpAssetId), (("Asset " + toBase58String(lpAssetId)) + " doesn't exist")).quantity
614- let accAmtAssetBalance = getAccBalance(amAssetIdStr)
615- let accPriceAssetBalance = getAccBalance(prAssetIdStr)
616- let amtAssetAmtX18 = toX18(accAmtAssetBalance, amtAssetDcm)
617- let priceAssetAmtX18 = toX18(accPriceAssetBalance, priceAssetDcm)
618- let curPriceX18 = if ((poolLPBalance == 0))
619- then zeroBigInt
620- else calcPriceBigInt(priceAssetAmtX18, amtAssetAmtX18)
621- let inAmAssetAmtX18 = toX18(inAmAssetAmt, amtAssetDcm)
622- let inPrAssetAmtX18 = fraction(inAmAssetAmtX18, curPriceX18, scale18)
623- let inPrAssetAmt = fromX18(inPrAssetAmtX18, priceAssetDcm)
624- let estPut = estimatePutOperation("", 500000, inAmAssetAmt, amAssetId, inPrAssetAmt, prAssetId, "", true, false)
625- let calcLpAmt = estPut._1
626- let curPriceCalc = estPut._3
627- let amBalance = estPut._4
628- let prBalance = estPut._5
629- let lpEmission = estPut._6
630- $Tuple2(nil, makeString(["%d%d%d%d%d%d%d%d", toString(calcLpAmt), toString(fromX18(curPriceX18, scale8)), toString(amBalance), toString(prBalance), toString(lpEmission), poolStatus, toString(inAmAssetAmt), toString(inPrAssetAmt)], SEP))
631- }
632-
633-
634-
635-@Callable(i)
636-func evaluatePutByPriceAssetREADONLY (inPrAssetAmt) = {
637- let cfg = getPoolConfig()
638- let lpAssetId = fromBase58String(cfg[idxPoolLPAssetId])
639- let amAssetIdStr = cfg[idxAmtAssetId]
640- let amAssetId = fromBase58String(amAssetIdStr)
641- let prAssetIdStr = cfg[idxPriceAssetId]
642- let prAssetId = fromBase58String(prAssetIdStr)
643- let amtAssetDcm = parseIntValue(cfg[idxAmtAssetDcm])
644- let priceAssetDcm = parseIntValue(cfg[idxPriceAssetDcm])
645- let poolStatus = cfg[idxPoolStatus]
646- let poolLPBalance = valueOrErrorMessage(assetInfo(lpAssetId), (("Asset " + toBase58String(lpAssetId)) + " doesn't exist")).quantity
647- let amBalanceRaw = getAccBalance(amAssetIdStr)
648- let prBalanceRaw = getAccBalance(prAssetIdStr)
649- let amBalanceRawX18 = toX18(amBalanceRaw, amtAssetDcm)
650- let prBalanceRawX18 = toX18(prBalanceRaw, priceAssetDcm)
651- let curPriceX18 = if ((poolLPBalance == 0))
652- then zeroBigInt
653- else calcPriceBigInt(prBalanceRawX18, amBalanceRawX18)
654- let inPrAssetAmtX18 = toX18(inPrAssetAmt, priceAssetDcm)
655- let inAmAssetAmtX18 = fraction(inPrAssetAmtX18, scale18, curPriceX18)
656- let inAmAssetAmt = fromX18(inAmAssetAmtX18, amtAssetDcm)
657- let estPut = estimatePutOperation("", 500000, inAmAssetAmt, amAssetId, inPrAssetAmt, prAssetId, "", true, false)
658- let calcLpAmt = estPut._1
659- let curPriceCalc = estPut._3
660- let amBalance = estPut._4
661- let prBalance = estPut._5
662- let lpEmission = estPut._6
663- $Tuple2(nil, makeString(["%d%d%d%d%d%d%d%d", toString(calcLpAmt), toString(fromX18(curPriceX18, scale8)), toString(amBalance), toString(prBalance), toString(lpEmission), poolStatus, toString(inAmAssetAmt), toString(inPrAssetAmt)], SEP))
664- }
665-
666-
667-
668-@Callable(i)
669-func evaluateGetREADONLY (paymentLpAssetId,paymentLpAmt) = {
670- let res = estimateGetOperation("", paymentLpAssetId, paymentLpAmt, this)
671- let outAmAmt = res._1
672- let outPrAmt = res._2
673- let amBalance = res._5
674- let prBalance = res._6
675- let lpEmission = res._7
676- let curPrice = res._8
677- let poolStatus = parseIntValue(res._9)
678- $Tuple2(nil, makeString(["%d%d%d%d%d%d%d", toString(outAmAmt), toString(outPrAmt), toString(amBalance), toString(prBalance), toString(lpEmission), toString(curPrice), toString(poolStatus)], SEP))
679769 }
680770
681771
682772 @Verifier(tx)
683773 func verify () = match tx {
684774 case order: Order =>
685- let matcherPub = getMatcherPubOrFail()
686- let orderValid = validateMatcherOrderAllowed(order)
687- let senderValid = sigVerify(order.bodyBytes, order.proofs[0], order.senderPublicKey)
688- let matcherValid = sigVerify(order.bodyBytes, order.proofs[1], matcherPub)
689- if (if (if (orderValid)
690- then senderValid
775+ let mtchPub = getMatcherPubOrFail()
776+ let orV = validateMatcherOrderAllowed(order)
777+ let sndrV = sigVerify(order.bodyBytes, order.proofs[0], order.senderPublicKey)
778+ let mtchV = sigVerify(order.bodyBytes, order.proofs[1], mtchPub)
779+ if (if (if (orV)
780+ then sndrV
691781 else false)
692- then matcherValid
782+ then mtchV
693783 else false)
694784 then true
695- else throwOrderError(orderValid, senderValid, matcherValid)
785+ else throwOrderError(orV, sndrV, mtchV)
696786 case _ =>
697- let managerPublic = valueOrElse(getString(this, keyManagerPublicKey()), EMPTY)
698- if ((managerPublic == EMPTY))
787+ let admin = valueOrElse(getString(this, keyManPubKey()), EMPTY)
788+ if ((admin == EMPTY))
699789 then sigVerify(tx.bodyBytes, tx.proofs[0], tx.senderPublicKey)
700- else sigVerify(tx.bodyBytes, tx.proofs[0], fromBase58String(managerPublic))
790+ else sigVerify(tx.bodyBytes, tx.proofs[0], fromBase58String(admin))
701791 }
702792

github/deemru/w8io/786bc32 
427.14 ms