tx · 72X4sHx16affzyHvvNdt4qZEYHcfEp45XZHQbHMUhN5X 3PCq2VqxGMmEyB8gLoUi8KuV9tYSD3VMC74: -0.01400000 Waves 2022.05.18 21:21 [3122948] smart account 3PCq2VqxGMmEyB8gLoUi8KuV9tYSD3VMC74 > SELF 0.00000000 Waves
{ "type": 13, "id": "72X4sHx16affzyHvvNdt4qZEYHcfEp45XZHQbHMUhN5X", "fee": 1400000, "feeAssetId": null, "timestamp": 1652898142345, "version": 2, "chainId": 87, "sender": "3PCq2VqxGMmEyB8gLoUi8KuV9tYSD3VMC74", "senderPublicKey": "AgEaeJWmKzbxoJ1uBK5S4nbSdPPPeYKWktd6MhFM2MGY", "proofs": [ "SM96RXE6nhKHeCtno7BFu61SWFaLughrUURdHzU4D67Fh3jKmjg5ycuLtTSM9cP2S78PtBzH4XizsacZDemgRSC" ], "script": "base64:AAIFAAAAAAAAACkIAhIICgYICAgICAESABIAEgMKAQQSABIDCgEBEgASAwoBBBIECgIIAQAAACkAAAAAC3VzZG5Bc3NldElkAQAAACC2JinDBPXOU5GkDkt1JC9kjFGx+t+vVCm9SNIdKrKq0QAAAAANcHV6emxlQXNzZXRJZAEAAAAg8Rr+Jf72mTj0aSrE3+ES1keyxsoOujcJr3dtH46i5WMAAAAADW1hc3RlckFkZHJlc3MJAQAAAAdBZGRyZXNzAAAAAQEAAAAaAVfOV/Mk0Qeks07+0rriKKzFkJbWitFtBe4AAAAADG1hc3RlclB1YktleQEAAAAgOzVNbj+fvvhUnJZEB4BWqy/iE2BFxHvyPxdD9EIFJl0BAAAADXRyeUdldEludGVnZXIAAAABAAAAA2tleQQAAAAHJG1hdGNoMAkABBoAAAACBQAAAAR0aGlzBQAAAANrZXkDCQAAAQAAAAIFAAAAByRtYXRjaDACAAAAA0ludAQAAAABYgUAAAAHJG1hdGNoMAUAAAABYgAAAAAAAAAAAAEAAAAMdHJ5R2V0QmluYXJ5AAAAAQAAAANrZXkEAAAAByRtYXRjaDAJAAQcAAAAAgUAAAAEdGhpcwUAAAADa2V5AwkAAAEAAAACBQAAAAckbWF0Y2gwAgAAAApCeXRlVmVjdG9yBAAAAAFiBQAAAAckbWF0Y2gwBQAAAAFiAQAAAAABAAAADHRyeUdldFN0cmluZwAAAAEAAAADa2V5BAAAAAckbWF0Y2gwCQAEHQAAAAIFAAAABHRoaXMFAAAAA2tleQMJAAABAAAAAgUAAAAHJG1hdGNoMAIAAAAGU3RyaW5nBAAAAAFiBQAAAAckbWF0Y2gwBQAAAAFiAgAAAAABAAAADmdldEFzc2V0U3RyaW5nAAAAAQAAAAdhc3NldElkBAAAAAckbWF0Y2gwBQAAAAdhc3NldElkAwkAAAEAAAACBQAAAAckbWF0Y2gwAgAAAApCeXRlVmVjdG9yBAAAAAFiBQAAAAckbWF0Y2gwCQACWAAAAAEFAAAAAWICAAAABVdBVkVTAQAAAA1nZXRBc3NldEJ5dGVzAAAAAQAAAAphc3NldElkU3RyAwkAAAAAAAACBQAAAAphc3NldElkU3RyAgAAAAVXQVZFUwUAAAAEdW5pdAkAAlkAAAABBQAAAAphc3NldElkU3RyAQAAABNhZGRBc3NldEJ5dGVzVG9MaXN0AAAAAgAAAAVhY2N1bQAAAARpdGVtCQAETgAAAAIFAAAABWFjY3VtCQAETAAAAAIJAQAAAA1nZXRBc3NldEJ5dGVzAAAAAQUAAAAEaXRlbQUAAAADbmlsAQAAABRhZGRBc3NldFdlaWdodFRvTGlzdAAAAAIAAAAFYWNjdW0AAAAEaXRlbQkABE4AAAACBQAAAAVhY2N1bQkABEwAAAACCQEAAAANdHJ5R2V0SW50ZWdlcgAAAAEJAAEsAAAAAgkAASwAAAACAgAAAAdzdGF0aWNfCQEAAAAOZ2V0QXNzZXRTdHJpbmcAAAABBQAAAARpdGVtAgAAAAdfd2VpZ2h0BQAAAANuaWwBAAAAFmFkZEFzc2V0RGVjaW1hbHNUb0xpc3QAAAACAAAABWFjY3VtAAAABGl0ZW0JAAROAAAAAgUAAAAFYWNjdW0JAARMAAAAAgkBAAAADXRyeUdldEludGVnZXIAAAABCQABLAAAAAIJAAEsAAAAAgIAAAAHc3RhdGljXwkBAAAADmdldEFzc2V0U3RyaW5nAAAAAQUAAAAEaXRlbQIAAAAJX2RlY2ltYWxzBQAAAANuaWwBAAAAE2FkZEFzc2V0U2NhbGVUb0xpc3QAAAACAAAABWFjY3VtAAAABGl0ZW0JAAROAAAAAgUAAAAFYWNjdW0JAARMAAAAAgkBAAAADXRyeUdldEludGVnZXIAAAABCQABLAAAAAIJAAEsAAAAAgIAAAAHc3RhdGljXwkBAAAADmdldEFzc2V0U3RyaW5nAAAAAQUAAAAEaXRlbQIAAAAGX3NjYWxlBQAAAANuaWwBAAAADGFkZEludFRvTGlzdAAAAAIAAAAFYWNjdW0AAAAEaXRlbQkABE4AAAACBQAAAAVhY2N1bQkABEwAAAACCQEAAAANcGFyc2VJbnRWYWx1ZQAAAAEFAAAABGl0ZW0FAAAAA25pbAAAAAABVAkBAAAADXRyeUdldEludGVnZXIAAAABAgAAABNzdGF0aWNfdG9rZW5zQW1vdW50AAAAAAhhc3NldElkcwoAAAAAAiRsCQAEtQAAAAIJAQAAAAx0cnlHZXRTdHJpbmcAAAABAgAAAA9zdGF0aWNfdG9rZW5JZHMCAAAAASwKAAAAAAIkcwkAAZAAAAABBQAAAAIkbAoAAAAABSRhY2MwBQAAAANuaWwKAQAAAAUkZjBfMQAAAAIAAAACJGEAAAACJGkDCQAAZwAAAAIFAAAAAiRpBQAAAAIkcwUAAAACJGEJAQAAABNhZGRBc3NldEJ5dGVzVG9MaXN0AAAAAgUAAAACJGEJAAGRAAAAAgUAAAACJGwFAAAAAiRpCgEAAAAFJGYwXzIAAAACAAAAAiRhAAAAAiRpAwkAAGcAAAACBQAAAAIkaQUAAAACJHMFAAAAAiRhCQAAAgAAAAECAAAAFExpc3Qgc2l6ZSBleGNlZWRzIDEwCQEAAAAFJGYwXzIAAAACCQEAAAAFJGYwXzEAAAACCQEAAAAFJGYwXzEAAAACCQEAAAAFJGYwXzEAAAACCQEAAAAFJGYwXzEAAAACCQEAAAAFJGYwXzEAAAACCQEAAAAFJGYwXzEAAAACCQEAAAAFJGYwXzEAAAACCQEAAAAFJGYwXzEAAAACCQEAAAAFJGYwXzEAAAACCQEAAAAFJGYwXzEAAAACBQAAAAUkYWNjMAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAgAAAAAAAAAAAwAAAAAAAAAABAAAAAAAAAAABQAAAAAAAAAABgAAAAAAAAAABwAAAAAAAAAACAAAAAAAAAAACQAAAAAAAAAACgAAAAANQXNzZXRzV2VpZ2h0cwoAAAAAAiRsBQAAAAhhc3NldElkcwoAAAAAAiRzCQABkAAAAAEFAAAAAiRsCgAAAAAFJGFjYzAFAAAAA25pbAoBAAAABSRmMV8xAAAAAgAAAAIkYQAAAAIkaQMJAABnAAAAAgUAAAACJGkFAAAAAiRzBQAAAAIkYQkBAAAAFGFkZEFzc2V0V2VpZ2h0VG9MaXN0AAAAAgUAAAACJGEJAAGRAAAAAgUAAAACJGwFAAAAAiRpCgEAAAAFJGYxXzIAAAACAAAAAiRhAAAAAiRpAwkAAGcAAAACBQAAAAIkaQUAAAACJHMFAAAAAiRhCQAAAgAAAAECAAAAFExpc3Qgc2l6ZSBleGNlZWRzIDEwCQEAAAAFJGYxXzIAAAACCQEAAAAFJGYxXzEAAAACCQEAAAAFJGYxXzEAAAACCQEAAAAFJGYxXzEAAAACCQEAAAAFJGYxXzEAAAACCQEAAAAFJGYxXzEAAAACCQEAAAAFJGYxXzEAAAACCQEAAAAFJGYxXzEAAAACCQEAAAAFJGYxXzEAAAACCQEAAAAFJGYxXzEAAAACCQEAAAAFJGYxXzEAAAACBQAAAAUkYWNjMAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAgAAAAAAAAAAAwAAAAAAAAAABAAAAAAAAAAABQAAAAAAAAAABgAAAAAAAAAABwAAAAAAAAAACAAAAAAAAAAACQAAAAAAAAAACgAAAAAIRGVjaW1hbHMKAAAAAAIkbAUAAAAIYXNzZXRJZHMKAAAAAAIkcwkAAZAAAAABBQAAAAIkbAoAAAAABSRhY2MwBQAAAANuaWwKAQAAAAUkZjJfMQAAAAIAAAACJGEAAAACJGkDCQAAZwAAAAIFAAAAAiRpBQAAAAIkcwUAAAACJGEJAQAAABZhZGRBc3NldERlY2ltYWxzVG9MaXN0AAAAAgUAAAACJGEJAAGRAAAAAgUAAAACJGwFAAAAAiRpCgEAAAAFJGYyXzIAAAACAAAAAiRhAAAAAiRpAwkAAGcAAAACBQAAAAIkaQUAAAACJHMFAAAAAiRhCQAAAgAAAAECAAAAFExpc3Qgc2l6ZSBleGNlZWRzIDEwCQEAAAAFJGYyXzIAAAACCQEAAAAFJGYyXzEAAAACCQEAAAAFJGYyXzEAAAACCQEAAAAFJGYyXzEAAAACCQEAAAAFJGYyXzEAAAACCQEAAAAFJGYyXzEAAAACCQEAAAAFJGYyXzEAAAACCQEAAAAFJGYyXzEAAAACCQEAAAAFJGYyXzEAAAACCQEAAAAFJGYyXzEAAAACCQEAAAAFJGYyXzEAAAACBQAAAAUkYWNjMAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAgAAAAAAAAAAAwAAAAAAAAAABAAAAAAAAAAABQAAAAAAAAAABgAAAAAAAAAABwAAAAAAAAAACAAAAAAAAAAACQAAAAAAAAAACgAAAAAGU2NhbGVzCgAAAAACJGwFAAAACGFzc2V0SWRzCgAAAAACJHMJAAGQAAAAAQUAAAACJGwKAAAAAAUkYWNjMAUAAAADbmlsCgEAAAAFJGYzXzEAAAACAAAAAiRhAAAAAiRpAwkAAGcAAAACBQAAAAIkaQUAAAACJHMFAAAAAiRhCQEAAAATYWRkQXNzZXRTY2FsZVRvTGlzdAAAAAIFAAAAAiRhCQABkQAAAAIFAAAAAiRsBQAAAAIkaQoBAAAABSRmM18yAAAAAgAAAAIkYQAAAAIkaQMJAABnAAAAAgUAAAACJGkFAAAAAiRzBQAAAAIkYQkAAAIAAAABAgAAABRMaXN0IHNpemUgZXhjZWVkcyAxMAkBAAAABSRmM18yAAAAAgkBAAAABSRmM18xAAAAAgkBAAAABSRmM18xAAAAAgkBAAAABSRmM18xAAAAAgkBAAAABSRmM18xAAAAAgkBAAAABSRmM18xAAAAAgkBAAAABSRmM18xAAAAAgkBAAAABSRmM18xAAAAAgkBAAAABSRmM18xAAAAAgkBAAAABSRmM18xAAAAAgkBAAAABSRmM18xAAAAAgUAAAAFJGFjYzAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAIAAAAAAAAAAAMAAAAAAAAAAAQAAAAAAAAAAAUAAAAAAAAAAAYAAAAAAAAAAAcAAAAAAAAAAAgAAAAAAAAAAAkAAAAAAAAAAAoAAAAAA0ZlZQkBAAAADXRyeUdldEludGVnZXIAAAABAgAAAApzdGF0aWNfZmVlAAAAABVBc3NldHNXZWlnaHRzRGVjaW1hbHMAAAAAAAAAAAQAAAAABVNjYWxlAAAAAAAAACcQAAAAAAZTY2FsZTgAAAAAAAX14QAAAAAACEZlZVNjYWxlAAAAAAAAACcQAAAAABFQb29sVG9rZW5EZWNpbWFscwAAAAAAAAAACAAAAAAOUG9vbFRva2VuU2NhbGUJAABsAAAABgAAAAAAAAAACgAAAAAAAAAAAAUAAAARUG9vbFRva2VuRGVjaW1hbHMAAAAAAAAAAAAAAAAAAAAAAAAFAAAABkhBTEZVUAAAAAAMZWFybmVkQXNzZXRzBQAAAAhhc3NldElkcwEAAAAKaXNTaHV0ZG93bgAAAAAEAAAAByRtYXRjaDAJAAQbAAAAAgkBAAAAB0FkZHJlc3MAAAABAQAAABoBV414U3qfFdI9lTSLgnlk2BnTJx6b8jVaqAIAAAALaXNfc2h1dGRvd24DCQAAAQAAAAIFAAAAByRtYXRjaDACAAAAB0Jvb2xlYW4EAAAAAXgFAAAAByRtYXRjaDAFAAAAAXgHAQAAABZnZXRDdXJyZW50VG9rZW5CYWxhbmNlAAAAAQAAAAl0b2tlblR5cGUEAAAAB3Rva2VuSWQJAQAAAA5nZXRBc3NldFN0cmluZwAAAAEJAAGRAAAAAgUAAAAIYXNzZXRJZHMFAAAACXRva2VuVHlwZQkBAAAADXRyeUdldEludGVnZXIAAAABCQABLAAAAAIJAAEsAAAAAgIAAAAHZ2xvYmFsXwUAAAAHdG9rZW5JZAIAAAAIX2JhbGFuY2UBAAAAEGNhbGN1bGF0ZVBJc3N1ZWQAAAACAAAABmFtb3VudAAAAAd0b2tlbklkBAAAAAdQc3VwcGx5CQEAAAANdHJ5R2V0SW50ZWdlcgAAAAECAAAAF2dsb2JhbF9wb29sVG9rZW5fYW1vdW50BAAAAAdCYWxhbmNlCQEAAAANdHJ5R2V0SW50ZWdlcgAAAAEJAAEsAAAAAgkAASwAAAACAgAAAAdnbG9iYWxfCQEAAAAOZ2V0QXNzZXRTdHJpbmcAAAABBQAAAAd0b2tlbklkAgAAAAhfYmFsYW5jZQkBAAAACGZyYWN0aW9uAAAABAUAAAAGYW1vdW50BQAAAAdQc3VwcGx5BQAAAAdCYWxhbmNlBQAAAARET1dOAQAAAA1nZXRNaW5QSXNzdWVkAAAAAQAAAAhwYXltZW50cwoBAAAAB2hhbmRsZXIAAAACAAAABWFjY3VtAAAAB2N1cnJlbnQEAAAAB1BJc3N1ZWQJAQAAABBjYWxjdWxhdGVQSXNzdWVkAAAAAggFAAAAB2N1cnJlbnQAAAAGYW1vdW50CAUAAAAHY3VycmVudAAAAAdhc3NldElkAwkAAAAAAAACBQAAAAdQSXNzdWVkAAAAAAAAAAAACQAAAgAAAAECAAAAJG9uZSBvZiB0aGUgdG9rZW5zIGFtb3VudHMgaXMgdG9vIGxvdwMDCQAAAAAAAAIFAAAABWFjY3VtAAAAAAAAAAAABgkAAGYAAAACBQAAAAVhY2N1bQUAAAAHUElzc3VlZAUAAAAHUElzc3VlZAUAAAAFYWNjdW0EAAAACW1pblBJc3NlZAoAAAAAAiRsBQAAAAhwYXltZW50cwoAAAAAAiRzCQABkAAAAAEFAAAAAiRsCgAAAAAFJGFjYzAAAAAAAAAAAAAKAQAAAAUkZjRfMQAAAAIAAAACJGEAAAACJGkDCQAAZwAAAAIFAAAAAiRpBQAAAAIkcwUAAAACJGEJAQAAAAdoYW5kbGVyAAAAAgUAAAACJGEJAAGRAAAAAgUAAAACJGwFAAAAAiRpCgEAAAAFJGY0XzIAAAACAAAAAiRhAAAAAiRpAwkAAGcAAAACBQAAAAIkaQUAAAACJHMFAAAAAiRhCQAAAgAAAAECAAAAFExpc3Qgc2l6ZSBleGNlZWRzIDEwCQEAAAAFJGY0XzIAAAACCQEAAAAFJGY0XzEAAAACCQEAAAAFJGY0XzEAAAACCQEAAAAFJGY0XzEAAAACCQEAAAAFJGY0XzEAAAACCQEAAAAFJGY0XzEAAAACCQEAAAAFJGY0XzEAAAACCQEAAAAFJGY0XzEAAAACCQEAAAAFJGY0XzEAAAACCQEAAAAFJGY0XzEAAAACCQEAAAAFJGY0XzEAAAACBQAAAAUkYWNjMAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAgAAAAAAAAAAAwAAAAAAAAAABAAAAAAAAAAABQAAAAAAAAAABgAAAAAAAAAABwAAAAAAAAAACAAAAAAAAAAACQAAAAAAAAAACgUAAAAJbWluUElzc2VkAQAAABJjYWxjdWxhdGVVc2RuVmFsdWUAAAAEAAAAB2Fzc2V0SWQAAAAGYW1vdW50AAAACGFCYWxhbmNlAAAAEGdpdmVuVXNkbkJhbGFuY2UEAAAACnVzZG5XZWlnaHQJAAGRAAAAAgUAAAANQXNzZXRzV2VpZ2h0cwkBAAAABXZhbHVlAAAAAQkABE8AAAACBQAAAAhhc3NldElkcwUAAAALdXNkbkFzc2V0SWQEAAAAC2Fzc2V0V2VpZ2h0CQABkQAAAAIFAAAADUFzc2V0c1dlaWdodHMJAQAAAAV2YWx1ZQAAAAEJAARPAAAAAgUAAAAIYXNzZXRJZHMFAAAAB2Fzc2V0SWQEAAAAC3VzZG5CYWxhbmNlBAAAAAckbWF0Y2gwBQAAABBnaXZlblVzZG5CYWxhbmNlAwkAAAEAAAACBQAAAAckbWF0Y2gwAgAAAANJbnQEAAAAAXgFAAAAByRtYXRjaDAFAAAAEGdpdmVuVXNkbkJhbGFuY2UJAQAAAA10cnlHZXRJbnRlZ2VyAAAAAQkAASwAAAACCQABLAAAAAICAAAAB2dsb2JhbF8JAQAAAA5nZXRBc3NldFN0cmluZwAAAAEFAAAAC3VzZG5Bc3NldElkAgAAAAhfYmFsYW5jZQkAAGsAAAADBQAAAAZhbW91bnQJAABpAAAAAgkBAAAABXZhbHVlAAAAAQUAAAALdXNkbkJhbGFuY2UFAAAACnVzZG5XZWlnaHQJAABpAAAAAgUAAAAIYUJhbGFuY2UFAAAAC2Fzc2V0V2VpZ2h0AQAAABNjaGVja1Rva2Vuc1ZhbGlkaXR5AAAAAQAAAAhwYXltZW50cwoBAAAACGhhbmRsZXIxAAAAAgAAAAVhY2N1bQAAAAdwYXltZW50CQAETgAAAAIFAAAABWFjY3VtCQAETAAAAAIIBQAAAAdwYXltZW50AAAAB2Fzc2V0SWQFAAAAA25pbAQAAAADaWRzCgAAAAACJGwFAAAACHBheW1lbnRzCgAAAAACJHMJAAGQAAAAAQUAAAACJGwKAAAAAAUkYWNjMAUAAAADbmlsCgEAAAAFJGY0XzEAAAACAAAAAiRhAAAAAiRpAwkAAGcAAAACBQAAAAIkaQUAAAACJHMFAAAAAiRhCQEAAAAIaGFuZGxlcjEAAAACBQAAAAIkYQkAAZEAAAACBQAAAAIkbAUAAAACJGkKAQAAAAUkZjRfMgAAAAIAAAACJGEAAAACJGkDCQAAZwAAAAIFAAAAAiRpBQAAAAIkcwUAAAACJGEJAAACAAAAAQIAAAAUTGlzdCBzaXplIGV4Y2VlZHMgMTAJAQAAAAUkZjRfMgAAAAIJAQAAAAUkZjRfMQAAAAIJAQAAAAUkZjRfMQAAAAIJAQAAAAUkZjRfMQAAAAIJAQAAAAUkZjRfMQAAAAIJAQAAAAUkZjRfMQAAAAIJAQAAAAUkZjRfMQAAAAIJAQAAAAUkZjRfMQAAAAIJAQAAAAUkZjRfMQAAAAIJAQAAAAUkZjRfMQAAAAIJAQAAAAUkZjRfMQAAAAIFAAAABSRhY2MwAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAACAAAAAAAAAAADAAAAAAAAAAAEAAAAAAAAAAAFAAAAAAAAAAAGAAAAAAAAAAAHAAAAAAAAAAAIAAAAAAAAAAAJAAAAAAAAAAAKAwkAAAAAAAACBQAAAANpZHMFAAAAA2lkcwoBAAAACGhhbmRsZXIyAAAAAgAAAAVhY2N1bQAAAAdhc3NldElkAwkBAAAAAiE9AAAAAgkABE8AAAACBQAAAANpZHMFAAAAB2Fzc2V0SWQFAAAABHVuaXQJAABkAAAAAgUAAAAFYWNjdW0AAAAAAAAAAAEJAAACAAAAAQkAASwAAAACAgAAABRhc3NldCBub3QgYXR0YWNoZWQ6IAkBAAAADmdldEFzc2V0U3RyaW5nAAAAAQUAAAAHYXNzZXRJZAQAAAAGY2hlY2tzCgAAAAACJGwFAAAACGFzc2V0SWRzCgAAAAACJHMJAAGQAAAAAQUAAAACJGwKAAAAAAUkYWNjMAAAAAAAAAAAAAoBAAAABSRmNV8xAAAAAgAAAAIkYQAAAAIkaQMJAABnAAAAAgUAAAACJGkFAAAAAiRzBQAAAAIkYQkBAAAACGhhbmRsZXIyAAAAAgUAAAACJGEJAAGRAAAAAgUAAAACJGwFAAAAAiRpCgEAAAAFJGY1XzIAAAACAAAAAiRhAAAAAiRpAwkAAGcAAAACBQAAAAIkaQUAAAACJHMFAAAAAiRhCQAAAgAAAAECAAAAFExpc3Qgc2l6ZSBleGNlZWRzIDEwCQEAAAAFJGY1XzIAAAACCQEAAAAFJGY1XzEAAAACCQEAAAAFJGY1XzEAAAACCQEAAAAFJGY1XzEAAAACCQEAAAAFJGY1XzEAAAACCQEAAAAFJGY1XzEAAAACCQEAAAAFJGY1XzEAAAACCQEAAAAFJGY1XzEAAAACCQEAAAAFJGY1XzEAAAACCQEAAAAFJGY1XzEAAAACCQEAAAAFJGY1XzEAAAACBQAAAAUkYWNjMAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAgAAAAAAAAAAAwAAAAAAAAAABAAAAAAAAAAABQAAAAAAAAAABgAAAAAAAAAABwAAAAAAAAAACAAAAAAAAAAACQAAAAAAAAAACgMJAAAAAAAAAgUAAAAGY2hlY2tzBQAAAAZjaGVja3MGCQAAAgAAAAECAAAAJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAAIAAAABAgAAACRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BAAAAE2hhbmRsZVBvb2xUb2tlbnNBZGQAAAAEAAAAB1BJc3N1ZWQAAAAIcGF5bWVudHMAAAALdXNlckFkZHJlc3MAAAAKbmVlZENoYW5nZQoBAAAAFWdldFRva2VuUGF5bWVudEFtb3VudAAAAAEAAAAHdG9rZW5JZAoBAAAAB2hhbmRsZXIAAAACAAAABWFjY3VtAAAAB3BheW1lbnQDCQAAAAAAAAIIBQAAAAdwYXltZW50AAAAB2Fzc2V0SWQFAAAAB3Rva2VuSWQIBQAAAAdwYXltZW50AAAABmFtb3VudAUAAAAFYWNjdW0KAAAAAAIkbAUAAAAIcGF5bWVudHMKAAAAAAIkcwkAAZAAAAABBQAAAAIkbAoAAAAABSRhY2MwAAAAAAAAAAAACgEAAAAFJGY0XzEAAAACAAAAAiRhAAAAAiRpAwkAAGcAAAACBQAAAAIkaQUAAAACJHMFAAAAAiRhCQEAAAAHaGFuZGxlcgAAAAIFAAAAAiRhCQABkQAAAAIFAAAAAiRsBQAAAAIkaQoBAAAABSRmNF8yAAAAAgAAAAIkYQAAAAIkaQMJAABnAAAAAgUAAAACJGkFAAAAAiRzBQAAAAIkYQkAAAIAAAABAgAAABRMaXN0IHNpemUgZXhjZWVkcyAxMAkBAAAABSRmNF8yAAAAAgkBAAAABSRmNF8xAAAAAgkBAAAABSRmNF8xAAAAAgkBAAAABSRmNF8xAAAAAgkBAAAABSRmNF8xAAAAAgkBAAAABSRmNF8xAAAAAgkBAAAABSRmNF8xAAAAAgkBAAAABSRmNF8xAAAAAgkBAAAABSRmNF8xAAAAAgkBAAAABSRmNF8xAAAAAgkBAAAABSRmNF8xAAAAAgUAAAAFJGFjYzAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAIAAAAAAAAAAAMAAAAAAAAAAAQAAAAAAAAAAAUAAAAAAAAAAAYAAAAAAAAAAAcAAAAAAAAAAAgAAAAAAAAAAAkAAAAAAAAAAAoKAQAAABFoYW5kbGVUb2tlbkNoYW5nZQAAAAIAAAAFYWNjdW0AAAAHdG9rZW5JZAQAAAACQmsJAQAAAA10cnlHZXRJbnRlZ2VyAAAAAQkAASwAAAACCQABLAAAAAICAAAAB2dsb2JhbF8JAQAAAA5nZXRBc3NldFN0cmluZwAAAAEFAAAAB3Rva2VuSWQCAAAACF9iYWxhbmNlBAAAAAdQU3VwcGx5CQEAAAANdHJ5R2V0SW50ZWdlcgAAAAECAAAAF2dsb2JhbF9wb29sVG9rZW5fYW1vdW50BAAAAA10b2tlbkRlY2ltYWxzCQEAAAANdHJ5R2V0SW50ZWdlcgAAAAEJAAEsAAAAAgkAASwAAAACAgAAAAdzdGF0aWNfCQEAAAAOZ2V0QXNzZXRTdHJpbmcAAAABBQAAAAd0b2tlbklkAgAAAAZfc2NhbGUEAAAAAkRrCQEAAAAIZnJhY3Rpb24AAAAECQAAZQAAAAIJAQAAAAhmcmFjdGlvbgAAAAQJAABkAAAAAgUAAAAHUFN1cHBseQUAAAAHUElzc3VlZAUAAAANdG9rZW5EZWNpbWFscwUAAAAHUFN1cHBseQUAAAAHQ0VJTElORwUAAAANdG9rZW5EZWNpbWFscwUAAAACQmsFAAAADXRva2VuRGVjaW1hbHMFAAAAB0NFSUxJTkcEAAAADXBheW1lbnRBbW91bnQJAQAAABVnZXRUb2tlblBheW1lbnRBbW91bnQAAAABBQAAAAd0b2tlbklkBAAAAAh0b1JldHVybgkAAGUAAAACAwkBAAAAAiE9AAAAAgUAAAANcGF5bWVudEFtb3VudAAAAAAAAAAAAAUAAAANcGF5bWVudEFtb3VudAAAAAAAAAAAAAUAAAACRGsEAAAAAXQDAwUAAAAKbmVlZENoYW5nZQkAAGYAAAACBQAAAAh0b1JldHVybgAAAAAAAAAAAAcJAARMAAAAAgkBAAAADlNjcmlwdFRyYW5zZmVyAAAAAwUAAAALdXNlckFkZHJlc3MFAAAACHRvUmV0dXJuBQAAAAd0b2tlbklkBQAAAANuaWwFAAAAA25pbAkABE4AAAACCQAETgAAAAIFAAAABWFjY3VtBQAAAAF0CQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACCQABLAAAAAIJAAEsAAAAAgIAAAAHZ2xvYmFsXwkBAAAADmdldEFzc2V0U3RyaW5nAAAAAQUAAAAHdG9rZW5JZAIAAAAIX2JhbGFuY2UJAABkAAAAAgUAAAACQmsFAAAAAkRrBQAAAANuaWwKAAAAAAIkbAUAAAAIYXNzZXRJZHMKAAAAAAIkcwkAAZAAAAABBQAAAAIkbAoAAAAABSRhY2MwBQAAAANuaWwKAQAAAAUkZjRfMQAAAAIAAAACJGEAAAACJGkDCQAAZwAAAAIFAAAAAiRpBQAAAAIkcwUAAAACJGEJAQAAABFoYW5kbGVUb2tlbkNoYW5nZQAAAAIFAAAAAiRhCQABkQAAAAIFAAAAAiRsBQAAAAIkaQoBAAAABSRmNF8yAAAAAgAAAAIkYQAAAAIkaQMJAABnAAAAAgUAAAACJGkFAAAAAiRzBQAAAAIkYQkAAAIAAAABAgAAABRMaXN0IHNpemUgZXhjZWVkcyAxMAkBAAAABSRmNF8yAAAAAgkBAAAABSRmNF8xAAAAAgkBAAAABSRmNF8xAAAAAgkBAAAABSRmNF8xAAAAAgkBAAAABSRmNF8xAAAAAgkBAAAABSRmNF8xAAAAAgkBAAAABSRmNF8xAAAAAgkBAAAABSRmNF8xAAAAAgkBAAAABSRmNF8xAAAAAgkBAAAABSRmNF8xAAAAAgkBAAAABSRmNF8xAAAAAgUAAAAFJGFjYzAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAIAAAAAAAAAAAMAAAAAAAAAAAQAAAAAAAAAAAUAAAAAAAAAAAYAAAAAAAAAAAcAAAAAAAAAAAgAAAAAAAAAAAkAAAAAAAAAAAoBAAAAFmhhbmRsZVBvb2xUb2tlbnNSZWRlZW0AAAACAAAACVBSZWRlZW1lZAAAAAt1c2VyQWRkcmVzcwoBAAAAEWhhbmRsZVRva2VuUmVkZWVtAAAAAgAAAAVhY2N1bQAAAAd0b2tlbklkBAAAAAJCawkBAAAADXRyeUdldEludGVnZXIAAAABCQABLAAAAAIJAAEsAAAAAgIAAAAHZ2xvYmFsXwkBAAAADmdldEFzc2V0U3RyaW5nAAAAAQUAAAAHdG9rZW5JZAIAAAAIX2JhbGFuY2UEAAAAB1BTdXBwbHkJAQAAAA10cnlHZXRJbnRlZ2VyAAAAAQIAAAAXZ2xvYmFsX3Bvb2xUb2tlbl9hbW91bnQEAAAADXRva2VuRGVjaW1hbHMJAQAAAA10cnlHZXRJbnRlZ2VyAAAAAQkAASwAAAACCQABLAAAAAICAAAAB3N0YXRpY18JAQAAAA5nZXRBc3NldFN0cmluZwAAAAEFAAAAB3Rva2VuSWQCAAAABl9zY2FsZQQAAAAGYW1vdW50CQABoAAAAAEJAAE9AAAABAkAATgAAAACCQABNgAAAAEFAAAABlNjYWxlOAkAAT0AAAAECQABNgAAAAEJAABlAAAAAgUAAAAHUFN1cHBseQUAAAAJUFJlZGVlbWVkCQABNgAAAAEFAAAABlNjYWxlOAkAATYAAAABBQAAAAdQU3VwcGx5BQAAAAdDRUlMSU5HCQABNgAAAAEFAAAAAkJrCQABNgAAAAEFAAAABlNjYWxlOAUAAAAERE9XTgkABE4AAAACBQAAAAVhY2N1bQkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgkAASwAAAACCQABLAAAAAICAAAAB2dsb2JhbF8JAQAAAA5nZXRBc3NldFN0cmluZwAAAAEFAAAAB3Rva2VuSWQCAAAACF9iYWxhbmNlCQAAZQAAAAIFAAAAAkJrBQAAAAZhbW91bnQJAARMAAAAAgkBAAAADlNjcmlwdFRyYW5zZmVyAAAAAwUAAAALdXNlckFkZHJlc3MFAAAABmFtb3VudAUAAAAHdG9rZW5JZAUAAAADbmlsCgAAAAACJGwFAAAACGFzc2V0SWRzCgAAAAACJHMJAAGQAAAAAQUAAAACJGwKAAAAAAUkYWNjMAUAAAADbmlsCgEAAAAFJGY0XzEAAAACAAAAAiRhAAAAAiRpAwkAAGcAAAACBQAAAAIkaQUAAAACJHMFAAAAAiRhCQEAAAARaGFuZGxlVG9rZW5SZWRlZW0AAAACBQAAAAIkYQkAAZEAAAACBQAAAAIkbAUAAAACJGkKAQAAAAUkZjRfMgAAAAIAAAACJGEAAAACJGkDCQAAZwAAAAIFAAAAAiRpBQAAAAIkcwUAAAACJGEJAAACAAAAAQIAAAAUTGlzdCBzaXplIGV4Y2VlZHMgMTAJAQAAAAUkZjRfMgAAAAIJAQAAAAUkZjRfMQAAAAIJAQAAAAUkZjRfMQAAAAIJAQAAAAUkZjRfMQAAAAIJAQAAAAUkZjRfMQAAAAIJAQAAAAUkZjRfMQAAAAIJAQAAAAUkZjRfMQAAAAIJAQAAAAUkZjRfMQAAAAIJAQAAAAUkZjRfMQAAAAIJAQAAAAUkZjRfMQAAAAIJAQAAAAUkZjRfMQAAAAIFAAAABSRhY2MwAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAACAAAAAAAAAAADAAAAAAAAAAAEAAAAAAAAAAAFAAAAAAAAAAAGAAAAAAAAAAAHAAAAAAAAAAAIAAAAAAAAAAAJAAAAAAAAAAAKAQAAABJjYWxjdWxhdGVPdXRBbW91bnQAAAAFAAAACEFtb3VudEluAAAAB2Fzc2V0SW4AAAAIYXNzZXRPdXQAAAAJQmFsYW5jZUluAAAACkJhbGFuY2VPdXQEAAAAB0luZGV4SW4JAQAAAAV2YWx1ZQAAAAEJAARPAAAAAgUAAAAIYXNzZXRJZHMFAAAAB2Fzc2V0SW4EAAAACEluZGV4T3V0CQEAAAAFdmFsdWUAAAABCQAETwAAAAIFAAAACGFzc2V0SWRzBQAAAAhhc3NldE91dAMJAAAAAAAAAgUAAAAHSW5kZXhJbgUAAAAISW5kZXhPdXQFAAAACEFtb3VudEluCQEAAAAIZnJhY3Rpb24AAAAEBQAAAApCYWxhbmNlT3V0CQAAZQAAAAIJAABoAAAAAgUAAAAGU2NhbGU4BQAAAAZTY2FsZTgJAAGgAAAAAQkAAHYAAAAGCQABPQAAAAQJAAE2AAAAAQUAAAAJQmFsYW5jZUluCQABNgAAAAEJAABoAAAAAgUAAAAGU2NhbGU4BQAAAAZTY2FsZTgJAAE2AAAAAQkAAGQAAAACBQAAAAlCYWxhbmNlSW4FAAAACEFtb3VudEluBQAAAAZIQUxGVVAAAAAAAAAAABAJAAE2AAAAAQkAAGsAAAADCQABkQAAAAIFAAAADUFzc2V0c1dlaWdodHMFAAAAB0luZGV4SW4AAAAAAAAAJxAJAAGRAAAAAgUAAAANQXNzZXRzV2VpZ2h0cwUAAAAISW5kZXhPdXQAAAAAAAAAAAQAAAAAAAAAABAFAAAAB0NFSUxJTkcJAABoAAAAAgUAAAAGU2NhbGU4BQAAAAZTY2FsZTgFAAAABERPV04BAAAAD2dldFRva2VuQmFsYW5jZQAAAAEAAAAHYXNzZXRJZAQAAAAHJG1hdGNoMAUAAAAHYXNzZXRJZAMJAAABAAAAAgUAAAAHJG1hdGNoMAIAAAAKQnl0ZVZlY3RvcgQAAAABdAUAAAAHJG1hdGNoMAkAA/AAAAACBQAAAAR0aGlzBQAAAAF0CAkAA+8AAAABBQAAAAR0aGlzAAAACWF2YWlsYWJsZQEAAAAdY2FsY3VsYXRlQ3VycmVudEFzc2V0SW50ZXJlc3QAAAAEAAAAB2Fzc2V0SWQAAAAKYXNzZXRJZFN0cgAAAAhhQmFsYW5jZQAAABZ0b2tlbkVhcm5pbmdzTGFzdENoZWNrBAAAAAt0b3RhbFN0YWtlZAkBAAAADXRyeUdldEludGVnZXIAAAABAgAAABJnbG9iYWxfaW5kZXhTdGFrZWQEAAAAFXRva2VuQmFsYW5jZUxhc3RDaGVjawUAAAAWdG9rZW5FYXJuaW5nc0xhc3RDaGVjawQAAAATY3VycmVudEJhbGFuY2VEZWx0YQkAAGUAAAACCQEAAAAPZ2V0VG9rZW5CYWxhbmNlAAAAAQUAAAAHYXNzZXRJZAUAAAAIYUJhbGFuY2UEAAAAFGN1cnJlbnRUb2tlbkVhcm5pbmdzAwkAAGYAAAACBQAAABNjdXJyZW50QmFsYW5jZURlbHRhBQAAABV0b2tlbkJhbGFuY2VMYXN0Q2hlY2sFAAAAE2N1cnJlbnRCYWxhbmNlRGVsdGEFAAAAFXRva2VuQmFsYW5jZUxhc3RDaGVjawQAAAALbmV3RWFybmluZ3MJAABlAAAAAgUAAAAUY3VycmVudFRva2VuRWFybmluZ3MFAAAAFXRva2VuQmFsYW5jZUxhc3RDaGVjawQAAAALbmV3SW50ZXJlc3QDCQAAAAAAAAIFAAAAC3RvdGFsU3Rha2VkAAAAAAAAAAAAAAAAAAAAAAAACQAAawAAAAMFAAAAC25ld0Vhcm5pbmdzBQAAAAZTY2FsZTgFAAAAC3RvdGFsU3Rha2VkBAAAABFsYXN0Q2hlY2tJbnRlcmVzdAkBAAAADXRyeUdldEludGVnZXIAAAABCQABLAAAAAIJAAEsAAAAAgIAAAARZ2xvYmFsX2xhc3RDaGVja18FAAAACmFzc2V0SWRTdHICAAAACV9pbnRlcmVzdAkAAGQAAAACBQAAABFsYXN0Q2hlY2tJbnRlcmVzdAUAAAALbmV3SW50ZXJlc3QBAAAAC2NsYWltUmVzdWx0AAAAAQAAAAdhZGRyZXNzBAAAAAphZGRyZXNzU3RyCQAEJQAAAAEFAAAAB2FkZHJlc3MEAAAADHB1enpsZUFtb3VudAkBAAAADXRyeUdldEludGVnZXIAAAABCQABLAAAAAIFAAAACmFkZHJlc3NTdHICAAAADF9pbmRleFN0YWtlZAoBAAAAB2hhbmRsZXIAAAACAAAABWFjY3VtAAAAB2Fzc2V0SWQEAAAACmFzc2V0SWRTdHIJAQAAAA5nZXRBc3NldFN0cmluZwAAAAEFAAAAB2Fzc2V0SWQEAAAACGFCYWxhbmNlCQEAAAANdHJ5R2V0SW50ZWdlcgAAAAEJAAEsAAAAAgkAASwAAAACAgAAAAdnbG9iYWxfCQEAAAAOZ2V0QXNzZXRTdHJpbmcAAAABBQAAAAdhc3NldElkAgAAAAhfYmFsYW5jZQQAAAAWdG9rZW5FYXJuaW5nc0xhc3RDaGVjawkBAAAADXRyeUdldEludGVnZXIAAAABCQABLAAAAAIJAAEsAAAAAgIAAAARZ2xvYmFsX2xhc3RDaGVja18FAAAACmFzc2V0SWRTdHICAAAACV9lYXJuaW5ncwQAAAAUY3VycmVudFRva2VuSW50ZXJlc3QJAQAAAB1jYWxjdWxhdGVDdXJyZW50QXNzZXRJbnRlcmVzdAAAAAQFAAAAB2Fzc2V0SWQFAAAACmFzc2V0SWRTdHIFAAAACGFCYWxhbmNlBQAAABZ0b2tlbkVhcm5pbmdzTGFzdENoZWNrBAAAABRjdXJyZW50VG9rZW5FYXJuaW5ncwkAAZYAAAABCQAETAAAAAIFAAAAFnRva2VuRWFybmluZ3NMYXN0Q2hlY2sJAARMAAAAAgkAAGUAAAACCQEAAAAPZ2V0VG9rZW5CYWxhbmNlAAAAAQUAAAAHYXNzZXRJZAUAAAAIYUJhbGFuY2UFAAAAA25pbAQAAAAMcmV3YXJkQW1vdW50CQAAawAAAAMFAAAADHB1enpsZUFtb3VudAkAAGUAAAACBQAAABRjdXJyZW50VG9rZW5JbnRlcmVzdAkBAAAADXRyeUdldEludGVnZXIAAAABCQABLAAAAAIJAAEsAAAAAgkAASwAAAACBQAAAAphZGRyZXNzU3RyAgAAAAtfbGFzdENoZWNrXwUAAAAKYXNzZXRJZFN0cgIAAAAJX2ludGVyZXN0BQAAAAZTY2FsZTgEAAAACHRyYW5zZmVyAwkAAAAAAAACBQAAAAxyZXdhcmRBbW91bnQAAAAAAAAAAAAFAAAAA25pbAkABEwAAAACCQEAAAAOU2NyaXB0VHJhbnNmZXIAAAADBQAAAAdhZGRyZXNzBQAAAAxyZXdhcmRBbW91bnQFAAAAB2Fzc2V0SWQFAAAAA25pbAkABRQAAAACCQAETgAAAAIJAAROAAAAAggFAAAABWFjY3VtAAAAAl8xBQAAAAh0cmFuc2ZlcgkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgkAASwAAAACCQABLAAAAAICAAAAEWdsb2JhbF9sYXN0Q2hlY2tfBQAAAAphc3NldElkU3RyAgAAAAlfZWFybmluZ3MJ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ZWQgYSBiaWdnZXIgdG9rZW5zIGFtb3VudCB0byBsYXVuY2ggdGhlIHBvb2wEAAAADnBvb2xUb2tlbklzc3VlCQAEQwAAAAcJAAEsAAAAAgIAAAADUFogCQEAAAAMdHJ5R2V0U3RyaW5nAAAAAQIAAAARc3RhdGljX3Bvb2xEb21haW4CAAAAHVB1enpsZSBTd2FwOiBwb29sIGluZGV4IHRva2VuBQAAABFpbml0aWFsUG9vbFRva2VucwUAAAARUG9vbFRva2VuRGVjaW1hbHMGBQAAAAR1bml0AAAAAAAAAAAABAAAAAtwb29sVG9rZW5JZAkABDgAAAABBQAAAA5wb29sVG9rZW5Jc3N1ZQkABE4AAAACCQEAAAALcHJlcGFyZUxpc3QAAAAACQAETAAAAAIFAAAADnBvb2xUb2tlbklzc3VlCQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACAgAAABdnbG9iYWxfcG9vbFRva2VuX2Ftb3VudAUAAAARaW5pdGlhbFBvb2xUb2tlbnMJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAICAAAAEGdsb2JhbF93YXNJbml0ZWQAAAAAAAAAAAEJAARMAAAAAgkBAAAAC0JpbmFyeUVudHJ5AAAAAgIAAAATZ2xvYmFsX3Bvb2xUb2tlbl9pZAUAAAALcG9vbFRva2VuSWQJAARMAAAAAgkBAAAAC1N0cmluZ0VudHJ5AAAAAgIAAAAWc3RhdGljX3Bvb2xUb2tlbl9pZFN0cgkBAAAADmdldEFzc2V0U3RyaW5nAAAAAQUAAAALcG9vbFRva2VuSWQJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAIJAAEsAAAAAgkABCUAAAABCAUAAAABaQAAAAZjYWxsZXICAAAADF9pbmRleFN0YWtlZAUAAAARaW5pdGlhbFBvb2xUb2tlbnMJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAICAAAAEmdsb2JhbF9pbmRleFN0YWtlZAUAAAARaW5pdGlhbFBvb2xUb2tlbnMFAAAAA25pbAAAAAFpAQAAAA1nZW5lcmF0ZUluZGV4AAAAAQAAAApuZWVkQ2hhbmdlAwkBAAAAAiE9AAAAAgkAAZAAAAABCAUAAAABaQAAAAhwYXltZW50cwUAAAABVAkAAAIAAAABCQABLAAAAAICAAAAO3lvdSBuZWVkIHRvIGF0dGFjaCBhbGwgcG9vbCB0b2tlbnMuIGFtb3VudCBvZiBwb29sIHRva2VuczogCQABpAAAAAEFAAAAAVQDCQEAAAABIQAAAAEJAQAAABNjaGVja1Rva2Vuc1ZhbGlkaXR5AAAAAQgFAAAAAWkAAAAIcGF5bWVudHMJAAACAAAAAQIAAAAVd3JvbmcgYXNzZXRzIGF0dGFjaGVkBAAAAAdQSXNzdWVkCQEAAAANZ2V0TWluUElzc3VlZAAAAAEIBQAAAAFpAAAACHBheW1lbnRzBAAAAAdyZWlzc3VlCQEAAAAHUmVpc3N1ZQAAAAMJAQAAABFAZXh0ck5hdGl2ZSgxMDU3KQAAAAECAAAAE2dsb2JhbF9wb29sVG9rZW5faWQFAAAAB1BJc3N1ZWQGBAAAAAZyZXN1bHQJAQAAABNoYW5kbGVQb29sVG9rZW5zQWRkAAAABAUAAAAHUElzc3VlZAgFAAAAAWkAAAAIcGF5bWVudHMIBQAAAAFpAAAADG9yaWdpbkNhbGxlcgUAAAAKbmVlZENoYW5nZQkABRQAAAACCQAETgAAAAIFAAAABnJlc3VsdAkABEwAAAACCQEAAAAOU2NyaXB0VHJhbnNmZXIAAAADCAUAAAABaQAAAAZjYWxsZXIFAAAAB1BJc3N1ZWQJAQAAAAx0cnlHZXRCaW5hcnkAAAABAgAAABNnbG9iYWxfcG9vbFRva2VuX2lkCQAETAAAAAIFAAAAB3JlaXNzdWUJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAICAAAAF2dsb2JhbF9wb29sVG9rZW5fYW1vdW50CQAAZAAAAAIJAQAAAA10cnlHZXRJbnRlZ2VyAAAAAQIAAAAXZ2xvYmFsX3Bvb2xUb2tlbl9hbW91bnQFAAAAB1BJc3N1ZWQFAAAAA25pbAUAAAAHUElzc3VlZAAAAAFpAQAAAApzdGFrZUluZGV4AAAAAAQAAAAKYWRkcmVzc1N0cgkABCUAAAABCAUAAAABaQAAAAxvcmlnaW5DYWxsZXIEAAAAA3BtdAkAAZEAAAACCAUAAAABaQAAAAhwYXltZW50cwAAAAAAAAAAAAMJAQAAAAIhPQAAAAIJAQAAAAV2YWx1ZQAAAAEIBQAAAANwbXQAAAAHYXNzZXRJZAkBAAAADHRyeUdldEJpbmFyeQAAAAECAAAAE2dsb2JhbF9wb29sVG9rZW5faWQJAAACAAAAAQIAAAAUd3JvbmcgYXNzZXQgYXR0YWNoZWQJAQAAABBpbmRleFN0YWtlUmVzdWx0AAAAAgUAAAAKYWRkcmVzc1N0cggFAAAAA3BtdAAAAAZhbW91bnQAAAABaQEAAAAMdW5zdGFrZUluZGV4AAAAAQAAAAxwdXp6bGVBbW91bnQEAAAACmFkZHJlc3NTdHIJAAQlAAAAAQgFAAAAAWkAAAAMb3JpZ2luQ2FsbGVyBAAAAA9wdXp6bGVBdmFpbGFibGUJAQAAAA10cnlHZXRJbnRlZ2VyAAAAAQkAASwAAAACBQAAAAphZGRyZXNzU3RyAgAAAAxfaW5kZXhTdGFrZWQDCQAAZgAAAAIFAAAADHB1enpsZUFtb3VudAUAAAAPcHV6emxlQXZhaWxhYmxlCQAAAgAAAAECAAAAJXlvdSBkb24ndCBoYXZlIGluZGV4IHRva2VucyBhdmFpbGFibGUDCQEAAAAKaXNTaHV0ZG93bgAAAAAJAAACAAAAAQIAAAATY29udHJhY3QgaXMgb24gc3RvcAkABE4AAAACCQEAAAALY2xhaW1SZXN1bHQAAAABCAUAAAABaQAAAAxvcmlnaW5DYWxsZXIJAARMAAAAAgkBAAAADEludGVnZXJFbnRyeQAAAAIJAAEsAAAAAgUAAAAKYWRkcmVzc1N0cgIAAAAMX2luZGV4U3Rha2VkCQAAZQAAAAIFAAAAD3B1enpsZUF2YWlsYWJsZQUAAAAMcHV6emxlQW1vdW50CQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACAgAAABJnbG9iYWxfaW5kZXhTdGFrZWQJAABlAAAAAgkBAAAADXRyeUdldEludGVnZXIAAAABAgAAABJnbG9iYWxfaW5kZXhTdGFrZWQFAAAADHB1enpsZUFtb3VudAkABEwAAAACCQEAAAAOU2NyaXB0VHJhbnNmZXIAAAADCAUAAAABaQAAAAZjYWxsZXIFAAAADHB1enpsZUFtb3VudAkBAAAAEUBleHRyTmF0aXZlKDEwNTcpAAAAAQIAAAATZ2xvYmFsX3Bvb2xUb2tlbl9pZAUAAAADbmlsAAAAAWkBAAAAEWNsYWltSW5kZXhSZXdhcmRzAAAAAAMJAQAAAAppc1NodXRkb3duAAAAAAkAAAIAAAABAgAAABNjb250cmFjdCBpcyBvbiBzdG9wCQEAAAALY2xhaW1SZXN1bHQAAAABCAUAAAABaQAAAAZjYWxsZXIAAAABaQEAAAALcmVkZWVtSW5kZXgAAAABAAAADHNlbmRUb09yaWdpbgQAAAADcG10CQABkQAAAAIIBQAAAAFpAAAACHBheW1lbnRzAAAAAAAAAAAAAwkBAAAAAiE9AAAAAggFAAAAA3BtdAAAAAdhc3NldElkCQEAAAAMdHJ5R2V0QmluYXJ5AAAAAQIAAAATZ2xvYmFsX3Bvb2xUb2tlbl9pZAkAAAIAAAABAgAAAB5wbGVhc2UgYXR0YWNoIHBvb2wgc2hhcmUgdG9rZW4DCQEAAAAKaXNTaHV0ZG93bgAAAAAJAAACAAAAAQIAAAATY29udHJhY3QgaXMgb24gc3RvcAQAAAAJUFJlZGVlbWVkCAUAAAADcG10AAAABmFtb3VudAQAAAAGcmVzdWx0CQEAAAAWaGFuZGxlUG9vbFRva2Vuc1JlZGVlbQAAAAIFAAAACVBSZWRlZW1lZAMFAAAADHNlbmRUb09yaWdpbggFAAAAAWkAAAAMb3JpZ2luQ2FsbGVyCAUAAAABaQAAAAZjYWxsZXIJAAROAAAAAgUAAAAGcmVzdWx0CQAETAAAAAIJAQAAAARCdXJuAAAAAgkBAAAADHRyeUdldEJpbmFyeQAAAAECAAAAE2dsb2JhbF9wb29sVG9rZW5faWQFAAAACVBSZWRlZW1lZAkABEwAAAACCQEAAAAMSW50ZWdlckVudHJ5AAAAAgIAAAAXZ2xvYmFsX3Bvb2xUb2tlbl9hbW91bnQJAABlAAAAAgkBAAAADXRyeUdldEludGVnZXIAAAABAgAAABdnbG9iYWxfcG9vbFRva2VuX2Ftb3VudAUAAAAJUFJlZGVlbWVkBQAAAANuaWwAAAABaQEAAAAEc3dhcAAAAAIAAAAIYXNzZXRPdXQAAAAHbWluaW11bQQAAAADcG10CQEAAAAFdmFsdWUAAAABCQABkQAAAAIIBQAAAAFpAAAACHBheW1lbnRzAAAAAAAAAAAABAAAAAhBbW91bnRJbgkBAAAABXZhbHVlAAAAAQgJAAGRAAAAAggFAAAAAWkAAAAIcGF5bWVudHMAAAAAAAAAAAAAAAAGYW1vdW50BAAAAAdBc3NldEluCAUAAAADcG10AAAAB2Fzc2V0SWQEAAAACEFzc2V0T3V0CQEAAAANZ2V0QXNzZXRCeXRlcwAAAAEFAAAACGFzc2V0T3V0BAAAAApmZWVBc3NldEluBQAAAAdBc3NldEluBAAAAAtmZWVBc3NldE91dAUAAAALdXNkbkFzc2V0SWQEAAAADkFzc2V0SW5CYWxhbmNlCQEAAAANdHJ5R2V0SW50ZWdlcgAAAAEJAAEsAAAAAgkAASwAAAACAgAAAAdnbG9iYWxfCQEAAAAOZ2V0QXNzZXRTdHJpbmcAAAABBQAAAAdBc3NldEluAgAAAAhfYmFsYW5jZQQAAAAPQXNzZXRPdXRCYWxhbmNlCQEAAAANdHJ5R2V0SW50ZWdlcgAAAAEJAAEsAAAAAgkAASwAAAACAgAAAAdnbG9iYWxfBQAAAAhhc3NldE91dAIAAAAIX2JhbGFuY2UEAAAAEmZlZUFzc2V0T3V0QmFsYW5jZQkBAAAADXRyeUdldEludGVnZXIAAAABCQABLAAAAAIJAAEsAAAAAgIAAAAHZ2xvYmFsXwkBAAAADmdldEFzc2V0U3RyaW5nAAAAAQUAAAALZmVlQXNzZXRPdXQCAAAACF9iYWxhbmNlBAAAAAtmZWVBbW91bnRJbgkAAGsAAAADBQAAAAhBbW91bnRJbgUAAAADRmVlBQAAAAhGZWVTY2FsZQQAAAANY2xlYW5BbW91bnRJbgkAAGUAAAACBQAAAAhBbW91bnRJbgUAAAALZmVlQW1vdW50SW4EAAAACUFtb3VudE91dAkBAAAAEmNhbGN1bGF0ZU91dEFtb3VudAAAAAUFAAAADWNsZWFuQW1vdW50SW4FAAAAB0Fzc2V0SW4FAAAACEFzc2V0T3V0BQAAAA5Bc3NldEluQmFsYW5jZQUAAAAPQXNzZXRPdXRCYWxhbmNlBAAAAAxmZWVBbW91bnRPdXQJAQAAABJjYWxjdWxhdGVPdXRBbW91bnQAAAAFBQAAAAtmZWVBbW91bnRJbgUAAAAHQXNzZXRJbgUAAAALZmVlQXNzZXRPdXQFAAAADkFzc2V0SW5CYWxhbmNlBQAAABJmZWVBc3NldE91dEJhbGFuY2UEAAAACmNyZWF0b3JGZWUJAABrAAAAAwUAAAAMZmVlQW1vdW50T3V0AAAAAAAAAAABAAAAAAAAAAAKBAAAAAtwcm90b2NvbEZlZQkAAGsAAAADBQAAAAxmZWVBbW91bnRPdXQAAAAAAAAAAAQAAAAAAAAAAAoEAAAADHN0YWtpbmdUb3BVcAkAA/0AAAAECQEAAAAHQWRkcmVzcwAAAAEBAAAAGgFXlGiM+e6iuaqf1vWOvKmPZxqcBvQWKYm7AgAAAAt0b3BVcFJld2FyZAUAAAADbmlsCQAETAAAAAIJAQAAAA9BdHRhY2hlZFBheW1lbnQAAAACBQAAAAtmZWVBc3NldE91dAUAAAALcHJvdG9jb2xGZWUFAAAAA25pbAMJAAAAAAAAAgUAAAAMc3Rha2luZ1RvcFVwBQAAAAxzdGFraW5nVG9wVXADCQAAZgAAAAIFAAAAB21pbmltdW0FAAAACUFtb3VudE91dAkAAAIAAAABCQABLAAAAAICAAAAK2Ftb3VudCB0byByZWNpZXZlIGlzIGxvd2VyIHRoYW4gZ2l2ZW4gb25lOiAJAAGkAAAAAQUAAAAJQW1vdW50T3V0AwkAAGYAAAACAAAAAAAAAAAACQAAZQAAAAIFAAAAD0Fzc2V0T3V0QmFsYW5jZQUAAAAJQW1vdW50T3V0CQAAAgAAAAECAAAAG2NvbnRyYWN0IGlzIG91dCBvZiByZXNlcnZlcwMJAQAAAAppc1NodXRkb3duAAAAAAkAAAIAAAABAgAAABNjb250cmFjdCBpcyBvbiBzdG9wBAAAAAxuZXdCYWxhbmNlSW4JAABkAAAAAgUAAAAOQXNzZXRJbkJhbGFuY2UFAAAACEFtb3VudEluBAAAAA1uZXdCYWxhbmNlT3V0CQAAZQAAAAIFAAAAD0Fzc2V0T3V0QmFsYW5jZQUAAAAJQW1vdW50T3V0BAAAABJuZXdCYWxhbmNlRmVlQXNzZXQDAwkBAAAAAiE9AAAAAgUAAAALZmVlQXNzZXRPdXQFAAAAB0Fzc2V0SW4JAQAAAAIhPQAAAAIFAAAAC2ZlZUFzc2V0T3V0BQAAAAhBc3NldE91dAcJAABlAAAAAgUAAAASZmVlQXNzZXRPdXRCYWxhbmNlBQAAAAxmZWVBbW91bnRPdXQFAAAABHVuaXQEAAAADWFzc2V0SW5DaGFuZ2UJAQAAAAxJbnRlZ2VyRW50cnkAAAACCQABLAAAAAIJAAEsAAAAAgIAAAAHZ2xvYmFsXwkBAAAADmdldEFzc2V0U3RyaW5nAAAAAQUAAAAHQXNzZXRJbgIAAAAIX2JhbGFuY2UFAAAADG5ld0JhbGFuY2VJbgQAAAAOYXNzZXRPdXRDaGFuZ2UJAQAAAAxJbnRlZ2VyRW50cnkAAAACCQABLAAAAAIJAAEsAAAAAgIAAAAHZ2xvYmFsXwUAAAAIYXNzZXRPdXQCAAAACF9iYWxhbmNlBQAAAA1uZXdCYWxhbmNlT3V0BAAAABFmZWVBc3NldE91dENoYW5nZQMJAQAAAAIhPQAAAAIFAAAAEm5ld0JhbGFuY2VGZWVBc3NldAUAAAAEdW5pdAkBAAAADEludGVnZXJFbnRyeQAAAAIJAAEsAAAAAgkAASwAAAACAgAAAAdnbG9iYWxfCQEAAAAOZ2V0QXNzZXRTdHJpbmcAAAABBQAAAAtmZWVBc3NldE91dAIAAAAIX2JhbGFuY2UFAAAAEmZlZUFzc2V0T3V0QmFsYW5jZQkBAAAAC1N0cmluZ0VudHJ5AAAAAgIAAAAFaGVsbG8CAAAABXdvcmxkCQAFFAAAAAIJAARMAAAAAgUAAAANYXNzZXRJbkNoYW5nZQkABEwAAAACBQAAAA5hc3NldE91dENoYW5nZQkABEwAAAACBQAAABFmZWVBc3NldE91dENoYW5nZQkABEwAAAACCQEAAAAOU2NyaXB0VHJhbnNmZXIAAAADCAUAAAABaQAAAAZjYWxsZXIFAAAACUFtb3VudE91dAUAAAAIQXNzZXRPdXQJAARMAAAAAgkBAAAADlNjcmlwdFRyYW5zZmVyAAAAAwkBAAAAEUBleHRyTmF0aXZlKDEwNjIpAAAAAQkBAAAADHRyeUdldFN0cmluZwAAAAECAAAAEHN0YXRpY19wb29sT3duZXIFAAAACmNyZWF0b3JGZWUFAAAAC2ZlZUFzc2V0T3V0CQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACAgAAABRnbG9iYWxfZWFybmVkQnlPd25lcgkAAGQAAAACCQEAAAANdHJ5R2V0SW50ZWdlcgAAAAECAAAAFGdsb2JhbF9lYXJuZWRCeU93bmVyBQAAAApjcmVhdG9yRmVlCQAETAAAAAIJAQAAAAxJbnRlZ2VyRW50cnkAAAACAgAAAA1nbG9iYWxfdm9sdW1lCQAAZAAAAAIJAQAAAA10cnlHZXRJbnRlZ2VyAAAAAQIAAAANZ2xvYmFsX3ZvbHVtZQkBAAAAEmNhbGN1bGF0ZVVzZG5WYWx1ZQAAAAQFAAAAB0Fzc2V0SW4FAAAACEFtb3VudEluBQAAAA5Bc3NldEluQmFsYW5jZQUAAAASZmVlQXNzZXRPdXRCYWxhbmNlBQAAAANuaWwFAAAACUFtb3VudE91dAkAAAIAAAABAgAAACRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4AAAABAAAAAnR4AQAAAAZ2ZXJpZnkAAAAAAwkBAAAACmlzU2h1dGRvd24AAAAABwMJAAH0AAAAAwgFAAAAAnR4AAAACWJvZHlCeXRlcwkAAZEAAAACCAUAAAACdHgAAAAGcHJvb2ZzAAAAAAAAAAAACAUAAAACdHgAAAAPc2VuZGVyUHVibGljS2V5BgkAAfQAAAADCAUAAAACdHgAAAAJYm9keUJ5dGVzCQABkQAAAAIIBQAAAAJ0eAAAAAZwcm9vZnMAAAAAAAAAAAAFAAAADG1hc3RlclB1YktleaECHGY=", "height": 3122948, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: EiRjPBcNHQ2QzBUTGeM6tiUHUW86Aj3zfBjXdtSWujXv Next: 9yMrUotRGh4pHC8ykKude1oAi3aGG5TrsxajBppwma5M Diff:
Old | New | Differences | |
---|---|---|---|
1 | 1 | {-# STDLIB_VERSION 5 #-} | |
2 | 2 | {-# SCRIPT_TYPE ACCOUNT #-} | |
3 | 3 | {-# CONTENT_TYPE DAPP #-} | |
4 | + | let usdnAssetId = base58'DG2xFkPdDwKUoBkzGAhQtLpSGzfXLiCYPEzeKH2Ad24p' | |
5 | + | ||
6 | + | let puzzleAssetId = base58'HEB8Qaw9xrWpWs8tHsiATYGBWDBtP2S7kcPALrMu43AS' | |
7 | + | ||
8 | + | let masterAddress = Address(base58'3PLjwHcz9NEuaTo63NZR9B9okQiKQxZSbmf') | |
9 | + | ||
10 | + | let masterPubKey = base58'4z8CKSYQBKkzx7PBb5uBP1YPa6YAHRNTApW1sQVHT5eU' | |
11 | + | ||
4 | 12 | func tryGetInteger (key) = match getInteger(this, key) { | |
5 | 13 | case b: Int => | |
6 | 14 | b | |
117 | 125 | ||
118 | 126 | let Fee = tryGetInteger("static_fee") | |
119 | 127 | ||
120 | - | let AssetsWeightsDecimals = | |
128 | + | let AssetsWeightsDecimals = 4 | |
121 | 129 | ||
122 | 130 | let Scale = 10000 | |
123 | 131 | ||
182 | 190 | } | |
183 | 191 | ||
184 | 192 | ||
185 | - | func calculateUsdnValue (assetId,amount,aBalance) = { | |
186 | - | let usdnId = base58'DG2xFkPdDwKUoBkzGAhQtLpSGzfXLiCYPEzeKH2Ad24p' | |
187 | - | let usdnWeight = AssetsWeights[value(indexOf(assetIds, usdnId))] | |
193 | + | func calculateUsdnValue (assetId,amount,aBalance,givenUsdnBalance) = { | |
194 | + | let usdnWeight = AssetsWeights[value(indexOf(assetIds, usdnAssetId))] | |
188 | 195 | let assetWeight = AssetsWeights[value(indexOf(assetIds, assetId))] | |
189 | - | let usdnBalance = tryGetInteger((("global_" + getAssetString(usdnId)) + "_balance")) | |
190 | - | fraction(amount, (usdnBalance / usdnWeight), (aBalance / assetWeight)) | |
196 | + | let usdnBalance = match givenUsdnBalance { | |
197 | + | case x: Int => | |
198 | + | givenUsdnBalance | |
199 | + | case _ => | |
200 | + | tryGetInteger((("global_" + getAssetString(usdnAssetId)) + "_balance")) | |
201 | + | } | |
202 | + | fraction(amount, (value(usdnBalance) / usdnWeight), (aBalance / assetWeight)) | |
191 | 203 | } | |
192 | 204 | ||
193 | 205 | ||
316 | 328 | let IndexIn = value(indexOf(assetIds, assetIn)) | |
317 | 329 | let IndexOut = value(indexOf(assetIds, assetOut)) | |
318 | 330 | if ((IndexIn == IndexOut)) | |
319 | - | then | |
331 | + | then AmountIn | |
320 | 332 | else fraction(BalanceOut, ((Scale8 * Scale8) - toInt(pow(fraction(toBigInt(BalanceIn), toBigInt((Scale8 * Scale8)), toBigInt((BalanceIn + AmountIn)), HALFUP), 16, toBigInt(fraction(AssetsWeights[IndexIn], 10000, AssetsWeights[IndexOut])), 4, 16, CEILING))), (Scale8 * Scale8), DOWN) | |
321 | 333 | } | |
322 | 334 | ||
358 | 370 | let transfer = if ((rewardAmount == 0)) | |
359 | 371 | then nil | |
360 | 372 | else [ScriptTransfer(address, rewardAmount, assetId)] | |
361 | - | $Tuple2(((accum._1 ++ transfer) ++ [IntegerEntry((("global_lastCheck_" + assetIdStr) + "_earnings"), (currentTokenEarnings - rewardAmount)), IntegerEntry((("global_lastCheck_" + assetIdStr) + "_interest"), currentTokenInterest), IntegerEntry((((addressStr + "_lastCheck_") + assetIdStr) + "_interest"), currentTokenInterest)]), (accum._2 + calculateUsdnValue(assetId, rewardAmount, aBalance))) | |
373 | + | $Tuple2(((accum._1 ++ transfer) ++ [IntegerEntry((("global_lastCheck_" + assetIdStr) + "_earnings"), (currentTokenEarnings - rewardAmount)), IntegerEntry((("global_lastCheck_" + assetIdStr) + "_interest"), currentTokenInterest), IntegerEntry((((addressStr + "_lastCheck_") + assetIdStr) + "_interest"), currentTokenInterest)]), (accum._2 + calculateUsdnValue(assetId, rewardAmount, aBalance, unit))) | |
362 | 374 | } | |
363 | 375 | ||
364 | 376 | let accum = { | |
389 | 401 | ||
390 | 402 | ||
391 | 403 | @Callable(i) | |
392 | - | func preInit (assetIdsStr,assetWeightsStr,baseTokenIdStr,poolDomain) = if ((this != i.caller)) | |
393 | - | then throw("admin only") | |
394 | - | else if ((size(poolDomain) > 13)) | |
395 | - | then throw("too large pool domain") | |
396 | - | else { | |
397 | - | let assetIdsStrLi = split(assetIdsStr, ",") | |
398 | - | let assetIdsLi = { | |
399 | - | let $l = assetIdsStrLi | |
400 | - | let $s = size($l) | |
401 | - | let $acc0 = nil | |
402 | - | func $f4_1 ($a,$i) = if (($i >= $s)) | |
403 | - | then $a | |
404 | - | else addAssetBytesToList($a, $l[$i]) | |
404 | + | func preInit (assetIdsStr,assetWeightsStr,baseTokenIdStr,poolDomain,poolOwner,fee) = { | |
405 | + | let poolOwnerAddress = Address(fromBase58String(poolOwner)) | |
406 | + | if ((this != i.caller)) | |
407 | + | then throw("admin only") | |
408 | + | else if ((size(poolDomain) > 13)) | |
409 | + | then throw("too large pool domain") | |
410 | + | else if (if ((fee > 500)) | |
411 | + | then true | |
412 | + | else (50 > fee)) | |
413 | + | then throw("fee value must be between 50 and 500 (0.5-5%)") | |
414 | + | else { | |
415 | + | let assetIdsStrLi = split(assetIdsStr, ",") | |
416 | + | let assetIdsLi = { | |
417 | + | let $l = assetIdsStrLi | |
418 | + | let $s = size($l) | |
419 | + | let $acc0 = nil | |
420 | + | func $f4_1 ($a,$i) = if (($i >= $s)) | |
421 | + | then $a | |
422 | + | else addAssetBytesToList($a, $l[$i]) | |
405 | 423 | ||
406 | - | func $f4_2 ($a,$i) = if (($i >= $s)) | |
407 | - | then $a | |
408 | - | else throw("List size exceeds 10") | |
424 | + | func $f4_2 ($a,$i) = if (($i >= $s)) | |
425 | + | then $a | |
426 | + | else throw("List size exceeds 10") | |
409 | 427 | ||
410 | - | $f4_2($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10) | |
411 | - | } | |
412 | - | let assetWeightsStrLi = split(assetWeightsStr, ",") | |
413 | - | let assetWeightsSum = { | |
414 | - | let $l = assetWeightsStrLi | |
415 | - | let $s = size($l) | |
416 | - | let $acc0 = 0 | |
417 | - | func $f5_1 ($a,$i) = if (($i >= $s)) | |
418 | - | then $a | |
419 | - | else sum($a, $l[$i]) | |
428 | + | $f4_2($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10) | |
429 | + | } | |
430 | + | let assetWeightsStrLi = split(assetWeightsStr, ",") | |
431 | + | let assetWeightsSum = { | |
432 | + | let $l = assetWeightsStrLi | |
433 | + | let $s = size($l) | |
434 | + | let $acc0 = 0 | |
435 | + | func $f5_1 ($a,$i) = if (($i >= $s)) | |
436 | + | then $a | |
437 | + | else sum($a, $l[$i]) | |
420 | 438 | ||
421 | - | func $f5_2 ($a,$i) = if (($i >= $s)) | |
422 | - | then $a | |
423 | - | else throw("List size exceeds 10") | |
439 | + | func $f5_2 ($a,$i) = if (($i >= $s)) | |
440 | + | then $a | |
441 | + | else throw("List size exceeds 10") | |
424 | 442 | ||
425 | - | $f5_2($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10) | |
426 | - | } | |
427 | - | func addTokenDataEntries (accum,assetNum) = if ((assetNum >= size(assetIdsLi))) | |
428 | - | then accum | |
429 | - | else { | |
430 | - | let assetDecimals = match assetIdsLi[assetNum] { | |
431 | - | case x: ByteVector => | |
432 | - | value(assetInfo(x)).decimals | |
433 | - | case _ => | |
434 | - | 8 | |
443 | + | $f5_2($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10) | |
444 | + | } | |
445 | + | func addTokenDataEntries (accum,assetNum) = if ((assetNum >= size(assetIdsLi))) | |
446 | + | then accum | |
447 | + | else { | |
448 | + | let assetDecimals = match assetIdsLi[assetNum] { | |
449 | + | case x: ByteVector => | |
450 | + | value(assetInfo(x)).decimals | |
451 | + | case _ => | |
452 | + | 8 | |
453 | + | } | |
454 | + | (accum ++ [IntegerEntry((("static_" + assetIdsStrLi[assetNum]) + "_scale"), pow(10, 0, assetDecimals, 0, 0, DOWN)), IntegerEntry((("static_" + assetIdsStrLi[assetNum]) + "_decimals"), assetDecimals), IntegerEntry((("static_" + assetIdsStrLi[assetNum]) + "_weight"), value(parseInt(assetWeightsStrLi[assetNum])))]) | |
455 | + | } | |
456 | + | ||
457 | + | if ((assetWeightsSum != 10000)) | |
458 | + | then throw("sum of token weights must be equal to 10000") | |
459 | + | else ({ | |
460 | + | let $l = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] | |
461 | + | let $s = size($l) | |
462 | + | let $acc0 = nil | |
463 | + | func $f6_1 ($a,$i) = if (($i >= $s)) | |
464 | + | then $a | |
465 | + | else addTokenDataEntries($a, $l[$i]) | |
466 | + | ||
467 | + | func $f6_2 ($a,$i) = if (($i >= $s)) | |
468 | + | then $a | |
469 | + | else throw("List size exceeds 10") | |
470 | + | ||
471 | + | $f6_2($f6_1($f6_1($f6_1($f6_1($f6_1($f6_1($f6_1($f6_1($f6_1($f6_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10) | |
472 | + | } ++ [StringEntry("static_tokenIds", assetIdsStr), StringEntry("static_tokenWeights", assetWeightsStr), IntegerEntry("static_tokensAmount", size(assetIdsLi)), StringEntry("static_poolDomain", poolDomain), StringEntry("static_baseTokenId", baseTokenIdStr), StringEntry("static_poolOwner", poolOwner), IntegerEntry("static_fee", fee)]) | |
435 | 473 | } | |
436 | - | (accum ++ [IntegerEntry((("static_" + assetIdsStrLi[assetNum]) + "_scale"), pow(10, 0, assetDecimals, 0, 0, DOWN)), IntegerEntry((("static_" + assetIdsStrLi[assetNum]) + "_decimals"), assetDecimals), IntegerEntry((("static_" + assetIdsStrLi[assetNum]) + "_weight"), value(parseInt(assetWeightsStrLi[assetNum])))]) | |
437 | - | } | |
438 | - | ||
439 | - | if ((assetWeightsSum != 100)) | |
440 | - | then throw("sum of token weights must be equal to 100") | |
441 | - | else ({ | |
442 | - | let $l = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] | |
443 | - | let $s = size($l) | |
444 | - | let $acc0 = nil | |
445 | - | func $f6_1 ($a,$i) = if (($i >= $s)) | |
446 | - | then $a | |
447 | - | else addTokenDataEntries($a, $l[$i]) | |
448 | - | ||
449 | - | func $f6_2 ($a,$i) = if (($i >= $s)) | |
450 | - | then $a | |
451 | - | else throw("List size exceeds 10") | |
452 | - | ||
453 | - | $f6_2($f6_1($f6_1($f6_1($f6_1($f6_1($f6_1($f6_1($f6_1($f6_1($f6_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10) | |
454 | - | } ++ [StringEntry("static_tokenIds", assetIdsStr), StringEntry("static_tokenWeights", assetWeightsStr), IntegerEntry("static_tokensAmount", size(assetIdsLi)), StringEntry("static_poolDomain", poolDomain), StringEntry("static_baseTokenId", baseTokenIdStr), IntegerEntry("static_fee", 200)]) | |
455 | - | } | |
474 | + | } | |
456 | 475 | ||
457 | 476 | ||
458 | 477 | ||
529 | 548 | else { | |
530 | 549 | let poolTokenIssue = Issue(("PZ " + tryGetString("static_poolDomain")), "Puzzle Swap: pool index token", initialPoolTokens, PoolTokenDecimals, true, unit, 0) | |
531 | 550 | let poolTokenId = calculateAssetId(poolTokenIssue) | |
532 | - | (prepareList() ++ [poolTokenIssue, IntegerEntry("global_poolToken_amount", initialPoolTokens), IntegerEntry("global_wasInited", 1), BinaryEntry("global_poolToken_id", poolTokenId), StringEntry("static_poolToken_idStr", getAssetString(poolTokenId)), | |
551 | + | (prepareList() ++ [poolTokenIssue, IntegerEntry("global_poolToken_amount", initialPoolTokens), IntegerEntry("global_wasInited", 1), BinaryEntry("global_poolToken_id", poolTokenId), StringEntry("static_poolToken_idStr", getAssetString(poolTokenId)), IntegerEntry((toString(i.caller) + "_indexStaked"), initialPoolTokens), IntegerEntry("global_indexStaked", initialPoolTokens)]) | |
533 | 552 | } | |
534 | 553 | } | |
535 | 554 | } | |
567 | 586 | let puzzleAvailable = tryGetInteger((addressStr + "_indexStaked")) | |
568 | 587 | if ((puzzleAmount > puzzleAvailable)) | |
569 | 588 | then throw("you don't have index tokens available") | |
570 | - | else (claimResult(i.originCaller) ++ [IntegerEntry((addressStr + "_indexStaked"), (puzzleAvailable - puzzleAmount)), IntegerEntry("global_indexStaked", (tryGetInteger("global_indexStaked") - puzzleAmount)), ScriptTransfer(i.caller, puzzleAmount, getBinaryValue("global_poolToken_id"))]) | |
589 | + | else if (isShutdown()) | |
590 | + | then throw("contract is on stop") | |
591 | + | else (claimResult(i.originCaller) ++ [IntegerEntry((addressStr + "_indexStaked"), (puzzleAvailable - puzzleAmount)), IntegerEntry("global_indexStaked", (tryGetInteger("global_indexStaked") - puzzleAmount)), ScriptTransfer(i.caller, puzzleAmount, getBinaryValue("global_poolToken_id"))]) | |
571 | 592 | } | |
572 | 593 | ||
573 | 594 | ||
574 | 595 | ||
575 | 596 | @Callable(i) | |
576 | - | func claimIndexRewards () = claimResult(i.caller) | |
597 | + | func claimIndexRewards () = if (isShutdown()) | |
598 | + | then throw("contract is on stop") | |
599 | + | else claimResult(i.caller) | |
577 | 600 | ||
578 | 601 | ||
579 | 602 | ||
582 | 605 | let pmt = i.payments[0] | |
583 | 606 | if ((pmt.assetId != tryGetBinary("global_poolToken_id"))) | |
584 | 607 | then throw("please attach pool share token") | |
585 | - | else { | |
586 | - | let PRedeemed = pmt.amount | |
587 | - | let result = handlePoolTokensRedeem(PRedeemed, if (sendToOrigin) | |
588 | - | then i.originCaller | |
589 | - | else i.caller) | |
590 | - | (result ++ [Burn(tryGetBinary("global_poolToken_id"), PRedeemed), IntegerEntry("global_poolToken_amount", (tryGetInteger("global_poolToken_amount") - PRedeemed))]) | |
591 | - | } | |
608 | + | else if (isShutdown()) | |
609 | + | then throw("contract is on stop") | |
610 | + | else { | |
611 | + | let PRedeemed = pmt.amount | |
612 | + | let result = handlePoolTokensRedeem(PRedeemed, if (sendToOrigin) | |
613 | + | then i.originCaller | |
614 | + | else i.caller) | |
615 | + | (result ++ [Burn(tryGetBinary("global_poolToken_id"), PRedeemed), IntegerEntry("global_poolToken_amount", (tryGetInteger("global_poolToken_amount") - PRedeemed))]) | |
616 | + | } | |
592 | 617 | } | |
593 | 618 | ||
594 | 619 | ||
599 | 624 | let AmountIn = value(i.payments[0].amount) | |
600 | 625 | let AssetIn = pmt.assetId | |
601 | 626 | let AssetOut = getAssetBytes(assetOut) | |
627 | + | let feeAssetIn = AssetIn | |
628 | + | let feeAssetOut = usdnAssetId | |
602 | 629 | let AssetInBalance = tryGetInteger((("global_" + getAssetString(AssetIn)) + "_balance")) | |
603 | 630 | let AssetOutBalance = tryGetInteger((("global_" + assetOut) + "_balance")) | |
604 | - | let AmountOut = calculateOutAmount(AmountIn, AssetIn, AssetOut, AssetInBalance, AssetOutBalance) | |
605 | - | let feeAmount = fraction(AmountOut, Fee, FeeScale) | |
606 | - | let cleanAmountOut = (AmountOut - feeAmount) | |
607 | - | if ((minimum > cleanAmountOut)) | |
608 | - | then throw(("amount to recieve is lower than given one: " + toString(cleanAmountOut))) | |
609 | - | else if ((0 > (AssetOutBalance - AmountOut))) | |
610 | - | then throw("contract is out of reserves") | |
611 | - | else { | |
612 | - | let newBalanceIn = (AssetInBalance + AmountIn) | |
613 | - | let newBalanceOut = (AssetOutBalance - AmountOut) | |
614 | - | let usdnAssetId = base58'DG2xFkPdDwKUoBkzGAhQtLpSGzfXLiCYPEzeKH2Ad24p' | |
615 | - | if ((usdnAssetId == AssetOut)) | |
616 | - | then { | |
617 | - | let usdnFeeAmount = feeAmount | |
618 | - | let protocolUsdnFee = fraction(usdnFeeAmount, 4, 10) | |
619 | - | let stakingTopUp = reentrantInvoke(Address(base58'3PFTbywqxtFfukX3HyT881g4iW5K4QL3FAS'), "topUpReward", nil, [AttachedPayment(usdnAssetId, protocolUsdnFee)]) | |
620 | - | if ((stakingTopUp == stakingTopUp)) | |
621 | - | then $Tuple2([IntegerEntry((("global_" + assetOut) + "_balance"), newBalanceOut), IntegerEntry((("global_" + getAssetString(AssetIn)) + "_balance"), newBalanceIn), ScriptTransfer(i.caller, cleanAmountOut, AssetOut), IntegerEntry("global_volume", (tryGetInteger("global_volume") + calculateUsdnValue(AssetIn, AmountIn, AssetInBalance)))], cleanAmountOut) | |
622 | - | else throw("Strict value is not equal to itself.") | |
631 | + | let feeAssetOutBalance = tryGetInteger((("global_" + getAssetString(feeAssetOut)) + "_balance")) | |
632 | + | let feeAmountIn = fraction(AmountIn, Fee, FeeScale) | |
633 | + | let cleanAmountIn = (AmountIn - feeAmountIn) | |
634 | + | let AmountOut = calculateOutAmount(cleanAmountIn, AssetIn, AssetOut, AssetInBalance, AssetOutBalance) | |
635 | + | let feeAmountOut = calculateOutAmount(feeAmountIn, AssetIn, feeAssetOut, AssetInBalance, feeAssetOutBalance) | |
636 | + | let creatorFee = fraction(feeAmountOut, 1, 10) | |
637 | + | let protocolFee = fraction(feeAmountOut, 4, 10) | |
638 | + | let stakingTopUp = reentrantInvoke(Address(base58'3PFTbywqxtFfukX3HyT881g4iW5K4QL3FAS'), "topUpReward", nil, [AttachedPayment(feeAssetOut, protocolFee)]) | |
639 | + | if ((stakingTopUp == stakingTopUp)) | |
640 | + | then if ((minimum > AmountOut)) | |
641 | + | then throw(("amount to recieve is lower than given one: " + toString(AmountOut))) | |
642 | + | else if ((0 > (AssetOutBalance - AmountOut))) | |
643 | + | then throw("contract is out of reserves") | |
644 | + | else if (isShutdown()) | |
645 | + | then throw("contract is on stop") | |
646 | + | else { | |
647 | + | let newBalanceIn = (AssetInBalance + AmountIn) | |
648 | + | let newBalanceOut = (AssetOutBalance - AmountOut) | |
649 | + | let newBalanceFeeAsset = if (if ((feeAssetOut != AssetIn)) | |
650 | + | then (feeAssetOut != AssetOut) | |
651 | + | else false) | |
652 | + | then (feeAssetOutBalance - feeAmountOut) | |
653 | + | else unit | |
654 | + | let assetInChange = IntegerEntry((("global_" + getAssetString(AssetIn)) + "_balance"), newBalanceIn) | |
655 | + | let assetOutChange = IntegerEntry((("global_" + assetOut) + "_balance"), newBalanceOut) | |
656 | + | let feeAssetOutChange = if ((newBalanceFeeAsset != unit)) | |
657 | + | then IntegerEntry((("global_" + getAssetString(feeAssetOut)) + "_balance"), feeAssetOutBalance) | |
658 | + | else StringEntry("hello", "world") | |
659 | + | $Tuple2([assetInChange, assetOutChange, feeAssetOutChange, ScriptTransfer(i.caller, AmountOut, AssetOut), ScriptTransfer(addressFromStringValue(tryGetString("static_poolOwner")), creatorFee, feeAssetOut), IntegerEntry("global_earnedByOwner", (tryGetInteger("global_earnedByOwner") + creatorFee)), IntegerEntry("global_volume", (tryGetInteger("global_volume") + calculateUsdnValue(AssetIn, AmountIn, AssetInBalance, feeAssetOutBalance)))], AmountOut) | |
623 | 660 | } | |
624 | - | else { | |
625 | - | let usdnBalance = if ((AssetIn == usdnAssetId)) | |
626 | - | then newBalanceIn | |
627 | - | else tryGetInteger((("global_" + getAssetString(usdnAssetId)) + "_balance")) | |
628 | - | let usdnFeeAmount = calculateOutAmount(feeAmount, AssetOut, usdnAssetId, newBalanceOut, usdnBalance) | |
629 | - | let protocolUsdnFee = fraction(usdnFeeAmount, 4, 10) | |
630 | - | let stakingTopUp = reentrantInvoke(Address(base58'3PFTbywqxtFfukX3HyT881g4iW5K4QL3FAS'), "topUpReward", nil, [AttachedPayment(usdnAssetId, protocolUsdnFee)]) | |
631 | - | if ((stakingTopUp == stakingTopUp)) | |
632 | - | then { | |
633 | - | let usdnBalanceChangeEntry = IntegerEntry((("global_" + toBase58String(usdnAssetId)) + "_balance"), (usdnBalance - usdnFeeAmount)) | |
634 | - | let balanceChanges = if ((AssetIn == usdnAssetId)) | |
635 | - | then [usdnBalanceChangeEntry] | |
636 | - | else [usdnBalanceChangeEntry, IntegerEntry((("global_" + getAssetString(AssetIn)) + "_balance"), newBalanceIn)] | |
637 | - | $Tuple2(([IntegerEntry((("global_" + assetOut) + "_balance"), (newBalanceOut + feeAmount)), ScriptTransfer(i.caller, cleanAmountOut, AssetOut), IntegerEntry("global_volume", (tryGetInteger("global_volume") + calculateUsdnValue(AssetIn, AmountIn, AssetInBalance)))] ++ balanceChanges), cleanAmountOut) | |
638 | - | } | |
639 | - | else throw("Strict value is not equal to itself.") | |
640 | - | } | |
641 | - | } | |
642 | - | } | |
643 | - | ||
644 | - | ||
645 | - | ||
646 | - | @Callable(i) | |
647 | - | func flashLoan (assetIdStr,amount,actionsStr) = { | |
648 | - | let actions = split(actionsStr, "|") | |
649 | - | nil | |
661 | + | else throw("Strict value is not equal to itself.") | |
650 | 662 | } | |
651 | 663 | ||
652 | 664 | ||
653 | 665 | @Verifier(tx) | |
654 | 666 | func verify () = if (isShutdown()) | |
655 | 667 | then false | |
656 | - | else sigVerify(tx.bodyBytes, tx.proofs[0], tx.senderPublicKey) | |
668 | + | else if (sigVerify(tx.bodyBytes, tx.proofs[0], tx.senderPublicKey)) | |
669 | + | then true | |
670 | + | else sigVerify(tx.bodyBytes, tx.proofs[0], masterPubKey) | |
657 | 671 |
Old | New | Differences | |
---|---|---|---|
1 | 1 | {-# STDLIB_VERSION 5 #-} | |
2 | 2 | {-# SCRIPT_TYPE ACCOUNT #-} | |
3 | 3 | {-# CONTENT_TYPE DAPP #-} | |
4 | + | let usdnAssetId = base58'DG2xFkPdDwKUoBkzGAhQtLpSGzfXLiCYPEzeKH2Ad24p' | |
5 | + | ||
6 | + | let puzzleAssetId = base58'HEB8Qaw9xrWpWs8tHsiATYGBWDBtP2S7kcPALrMu43AS' | |
7 | + | ||
8 | + | let masterAddress = Address(base58'3PLjwHcz9NEuaTo63NZR9B9okQiKQxZSbmf') | |
9 | + | ||
10 | + | let masterPubKey = base58'4z8CKSYQBKkzx7PBb5uBP1YPa6YAHRNTApW1sQVHT5eU' | |
11 | + | ||
4 | 12 | func tryGetInteger (key) = match getInteger(this, key) { | |
5 | 13 | case b: Int => | |
6 | 14 | b | |
7 | 15 | case _ => | |
8 | 16 | 0 | |
9 | 17 | } | |
10 | 18 | ||
11 | 19 | ||
12 | 20 | func tryGetBinary (key) = match getBinary(this, key) { | |
13 | 21 | case b: ByteVector => | |
14 | 22 | b | |
15 | 23 | case _ => | |
16 | 24 | base58'' | |
17 | 25 | } | |
18 | 26 | ||
19 | 27 | ||
20 | 28 | func tryGetString (key) = match getString(this, key) { | |
21 | 29 | case b: String => | |
22 | 30 | b | |
23 | 31 | case _ => | |
24 | 32 | "" | |
25 | 33 | } | |
26 | 34 | ||
27 | 35 | ||
28 | 36 | func getAssetString (assetId) = match assetId { | |
29 | 37 | case b: ByteVector => | |
30 | 38 | toBase58String(b) | |
31 | 39 | case _ => | |
32 | 40 | "WAVES" | |
33 | 41 | } | |
34 | 42 | ||
35 | 43 | ||
36 | 44 | func getAssetBytes (assetIdStr) = if ((assetIdStr == "WAVES")) | |
37 | 45 | then unit | |
38 | 46 | else fromBase58String(assetIdStr) | |
39 | 47 | ||
40 | 48 | ||
41 | 49 | func addAssetBytesToList (accum,item) = (accum ++ [getAssetBytes(item)]) | |
42 | 50 | ||
43 | 51 | ||
44 | 52 | func addAssetWeightToList (accum,item) = (accum ++ [tryGetInteger((("static_" + getAssetString(item)) + "_weight"))]) | |
45 | 53 | ||
46 | 54 | ||
47 | 55 | func addAssetDecimalsToList (accum,item) = (accum ++ [tryGetInteger((("static_" + getAssetString(item)) + "_decimals"))]) | |
48 | 56 | ||
49 | 57 | ||
50 | 58 | func addAssetScaleToList (accum,item) = (accum ++ [tryGetInteger((("static_" + getAssetString(item)) + "_scale"))]) | |
51 | 59 | ||
52 | 60 | ||
53 | 61 | func addIntToList (accum,item) = (accum ++ [parseIntValue(item)]) | |
54 | 62 | ||
55 | 63 | ||
56 | 64 | let T = tryGetInteger("static_tokensAmount") | |
57 | 65 | ||
58 | 66 | let assetIds = { | |
59 | 67 | let $l = split(tryGetString("static_tokenIds"), ",") | |
60 | 68 | let $s = size($l) | |
61 | 69 | let $acc0 = nil | |
62 | 70 | func $f0_1 ($a,$i) = if (($i >= $s)) | |
63 | 71 | then $a | |
64 | 72 | else addAssetBytesToList($a, $l[$i]) | |
65 | 73 | ||
66 | 74 | func $f0_2 ($a,$i) = if (($i >= $s)) | |
67 | 75 | then $a | |
68 | 76 | else throw("List size exceeds 10") | |
69 | 77 | ||
70 | 78 | $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10) | |
71 | 79 | } | |
72 | 80 | ||
73 | 81 | let AssetsWeights = { | |
74 | 82 | let $l = assetIds | |
75 | 83 | let $s = size($l) | |
76 | 84 | let $acc0 = nil | |
77 | 85 | func $f1_1 ($a,$i) = if (($i >= $s)) | |
78 | 86 | then $a | |
79 | 87 | else addAssetWeightToList($a, $l[$i]) | |
80 | 88 | ||
81 | 89 | func $f1_2 ($a,$i) = if (($i >= $s)) | |
82 | 90 | then $a | |
83 | 91 | else throw("List size exceeds 10") | |
84 | 92 | ||
85 | 93 | $f1_2($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10) | |
86 | 94 | } | |
87 | 95 | ||
88 | 96 | let Decimals = { | |
89 | 97 | let $l = assetIds | |
90 | 98 | let $s = size($l) | |
91 | 99 | let $acc0 = nil | |
92 | 100 | func $f2_1 ($a,$i) = if (($i >= $s)) | |
93 | 101 | then $a | |
94 | 102 | else addAssetDecimalsToList($a, $l[$i]) | |
95 | 103 | ||
96 | 104 | func $f2_2 ($a,$i) = if (($i >= $s)) | |
97 | 105 | then $a | |
98 | 106 | else throw("List size exceeds 10") | |
99 | 107 | ||
100 | 108 | $f2_2($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10) | |
101 | 109 | } | |
102 | 110 | ||
103 | 111 | let Scales = { | |
104 | 112 | let $l = assetIds | |
105 | 113 | let $s = size($l) | |
106 | 114 | let $acc0 = nil | |
107 | 115 | func $f3_1 ($a,$i) = if (($i >= $s)) | |
108 | 116 | then $a | |
109 | 117 | else addAssetScaleToList($a, $l[$i]) | |
110 | 118 | ||
111 | 119 | func $f3_2 ($a,$i) = if (($i >= $s)) | |
112 | 120 | then $a | |
113 | 121 | else throw("List size exceeds 10") | |
114 | 122 | ||
115 | 123 | $f3_2($f3_1($f3_1($f3_1($f3_1($f3_1($f3_1($f3_1($f3_1($f3_1($f3_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10) | |
116 | 124 | } | |
117 | 125 | ||
118 | 126 | let Fee = tryGetInteger("static_fee") | |
119 | 127 | ||
120 | - | let AssetsWeightsDecimals = | |
128 | + | let AssetsWeightsDecimals = 4 | |
121 | 129 | ||
122 | 130 | let Scale = 10000 | |
123 | 131 | ||
124 | 132 | let Scale8 = 100000000 | |
125 | 133 | ||
126 | 134 | let FeeScale = 10000 | |
127 | 135 | ||
128 | 136 | let PoolTokenDecimals = 8 | |
129 | 137 | ||
130 | 138 | let PoolTokenScale = pow(10, 0, PoolTokenDecimals, 0, 0, HALFUP) | |
131 | 139 | ||
132 | 140 | let earnedAssets = assetIds | |
133 | 141 | ||
134 | 142 | func isShutdown () = match getBoolean(Address(base58'3PEpv9hRFWEEBU22WRnLsw1bH4YGtcU728o'), "is_shutdown") { | |
135 | 143 | case x: Boolean => | |
136 | 144 | x | |
137 | 145 | case _ => | |
138 | 146 | false | |
139 | 147 | } | |
140 | 148 | ||
141 | 149 | ||
142 | 150 | func getCurrentTokenBalance (tokenType) = { | |
143 | 151 | let tokenId = getAssetString(assetIds[tokenType]) | |
144 | 152 | tryGetInteger((("global_" + tokenId) + "_balance")) | |
145 | 153 | } | |
146 | 154 | ||
147 | 155 | ||
148 | 156 | func calculatePIssued (amount,tokenId) = { | |
149 | 157 | let Psupply = tryGetInteger("global_poolToken_amount") | |
150 | 158 | let Balance = tryGetInteger((("global_" + getAssetString(tokenId)) + "_balance")) | |
151 | 159 | fraction(amount, Psupply, Balance, DOWN) | |
152 | 160 | } | |
153 | 161 | ||
154 | 162 | ||
155 | 163 | func getMinPIssued (payments) = { | |
156 | 164 | func handler (accum,current) = { | |
157 | 165 | let PIssued = calculatePIssued(current.amount, current.assetId) | |
158 | 166 | if ((PIssued == 0)) | |
159 | 167 | then throw("one of the tokens amounts is too low") | |
160 | 168 | else if (if ((accum == 0)) | |
161 | 169 | then true | |
162 | 170 | else (accum > PIssued)) | |
163 | 171 | then PIssued | |
164 | 172 | else accum | |
165 | 173 | } | |
166 | 174 | ||
167 | 175 | let minPIssed = { | |
168 | 176 | let $l = payments | |
169 | 177 | let $s = size($l) | |
170 | 178 | let $acc0 = 0 | |
171 | 179 | func $f4_1 ($a,$i) = if (($i >= $s)) | |
172 | 180 | then $a | |
173 | 181 | else handler($a, $l[$i]) | |
174 | 182 | ||
175 | 183 | func $f4_2 ($a,$i) = if (($i >= $s)) | |
176 | 184 | then $a | |
177 | 185 | else throw("List size exceeds 10") | |
178 | 186 | ||
179 | 187 | $f4_2($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10) | |
180 | 188 | } | |
181 | 189 | minPIssed | |
182 | 190 | } | |
183 | 191 | ||
184 | 192 | ||
185 | - | func calculateUsdnValue (assetId,amount,aBalance) = { | |
186 | - | let usdnId = base58'DG2xFkPdDwKUoBkzGAhQtLpSGzfXLiCYPEzeKH2Ad24p' | |
187 | - | let usdnWeight = AssetsWeights[value(indexOf(assetIds, usdnId))] | |
193 | + | func calculateUsdnValue (assetId,amount,aBalance,givenUsdnBalance) = { | |
194 | + | let usdnWeight = AssetsWeights[value(indexOf(assetIds, usdnAssetId))] | |
188 | 195 | let assetWeight = AssetsWeights[value(indexOf(assetIds, assetId))] | |
189 | - | let usdnBalance = tryGetInteger((("global_" + getAssetString(usdnId)) + "_balance")) | |
190 | - | fraction(amount, (usdnBalance / usdnWeight), (aBalance / assetWeight)) | |
196 | + | let usdnBalance = match givenUsdnBalance { | |
197 | + | case x: Int => | |
198 | + | givenUsdnBalance | |
199 | + | case _ => | |
200 | + | tryGetInteger((("global_" + getAssetString(usdnAssetId)) + "_balance")) | |
201 | + | } | |
202 | + | fraction(amount, (value(usdnBalance) / usdnWeight), (aBalance / assetWeight)) | |
191 | 203 | } | |
192 | 204 | ||
193 | 205 | ||
194 | 206 | func checkTokensValidity (payments) = { | |
195 | 207 | func handler1 (accum,payment) = (accum ++ [payment.assetId]) | |
196 | 208 | ||
197 | 209 | let ids = { | |
198 | 210 | let $l = payments | |
199 | 211 | let $s = size($l) | |
200 | 212 | let $acc0 = nil | |
201 | 213 | func $f4_1 ($a,$i) = if (($i >= $s)) | |
202 | 214 | then $a | |
203 | 215 | else handler1($a, $l[$i]) | |
204 | 216 | ||
205 | 217 | func $f4_2 ($a,$i) = if (($i >= $s)) | |
206 | 218 | then $a | |
207 | 219 | else throw("List size exceeds 10") | |
208 | 220 | ||
209 | 221 | $f4_2($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10) | |
210 | 222 | } | |
211 | 223 | if ((ids == ids)) | |
212 | 224 | then { | |
213 | 225 | func handler2 (accum,assetId) = if ((indexOf(ids, assetId) != unit)) | |
214 | 226 | then (accum + 1) | |
215 | 227 | else throw(("asset not attached: " + getAssetString(assetId))) | |
216 | 228 | ||
217 | 229 | let checks = { | |
218 | 230 | let $l = assetIds | |
219 | 231 | let $s = size($l) | |
220 | 232 | let $acc0 = 0 | |
221 | 233 | func $f5_1 ($a,$i) = if (($i >= $s)) | |
222 | 234 | then $a | |
223 | 235 | else handler2($a, $l[$i]) | |
224 | 236 | ||
225 | 237 | func $f5_2 ($a,$i) = if (($i >= $s)) | |
226 | 238 | then $a | |
227 | 239 | else throw("List size exceeds 10") | |
228 | 240 | ||
229 | 241 | $f5_2($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10) | |
230 | 242 | } | |
231 | 243 | if ((checks == checks)) | |
232 | 244 | then true | |
233 | 245 | else throw("Strict value is not equal to itself.") | |
234 | 246 | } | |
235 | 247 | else throw("Strict value is not equal to itself.") | |
236 | 248 | } | |
237 | 249 | ||
238 | 250 | ||
239 | 251 | func handlePoolTokensAdd (PIssued,payments,userAddress,needChange) = { | |
240 | 252 | func getTokenPaymentAmount (tokenId) = { | |
241 | 253 | func handler (accum,payment) = if ((payment.assetId == tokenId)) | |
242 | 254 | then payment.amount | |
243 | 255 | else accum | |
244 | 256 | ||
245 | 257 | let $l = payments | |
246 | 258 | let $s = size($l) | |
247 | 259 | let $acc0 = 0 | |
248 | 260 | func $f4_1 ($a,$i) = if (($i >= $s)) | |
249 | 261 | then $a | |
250 | 262 | else handler($a, $l[$i]) | |
251 | 263 | ||
252 | 264 | func $f4_2 ($a,$i) = if (($i >= $s)) | |
253 | 265 | then $a | |
254 | 266 | else throw("List size exceeds 10") | |
255 | 267 | ||
256 | 268 | $f4_2($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10) | |
257 | 269 | } | |
258 | 270 | ||
259 | 271 | func handleTokenChange (accum,tokenId) = { | |
260 | 272 | let Bk = tryGetInteger((("global_" + getAssetString(tokenId)) + "_balance")) | |
261 | 273 | let PSupply = tryGetInteger("global_poolToken_amount") | |
262 | 274 | let tokenDecimals = tryGetInteger((("static_" + getAssetString(tokenId)) + "_scale")) | |
263 | 275 | let Dk = fraction((fraction((PSupply + PIssued), tokenDecimals, PSupply, CEILING) - tokenDecimals), Bk, tokenDecimals, CEILING) | |
264 | 276 | let paymentAmount = getTokenPaymentAmount(tokenId) | |
265 | 277 | let toReturn = ((if ((paymentAmount != 0)) | |
266 | 278 | then paymentAmount | |
267 | 279 | else 0) - Dk) | |
268 | 280 | let t = if (if (needChange) | |
269 | 281 | then (toReturn > 0) | |
270 | 282 | else false) | |
271 | 283 | then [ScriptTransfer(userAddress, toReturn, tokenId)] | |
272 | 284 | else nil | |
273 | 285 | ((accum ++ t) ++ [IntegerEntry((("global_" + getAssetString(tokenId)) + "_balance"), (Bk + Dk))]) | |
274 | 286 | } | |
275 | 287 | ||
276 | 288 | let $l = assetIds | |
277 | 289 | let $s = size($l) | |
278 | 290 | let $acc0 = nil | |
279 | 291 | func $f4_1 ($a,$i) = if (($i >= $s)) | |
280 | 292 | then $a | |
281 | 293 | else handleTokenChange($a, $l[$i]) | |
282 | 294 | ||
283 | 295 | func $f4_2 ($a,$i) = if (($i >= $s)) | |
284 | 296 | then $a | |
285 | 297 | else throw("List size exceeds 10") | |
286 | 298 | ||
287 | 299 | $f4_2($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10) | |
288 | 300 | } | |
289 | 301 | ||
290 | 302 | ||
291 | 303 | func handlePoolTokensRedeem (PRedeemed,userAddress) = { | |
292 | 304 | func handleTokenRedeem (accum,tokenId) = { | |
293 | 305 | let Bk = tryGetInteger((("global_" + getAssetString(tokenId)) + "_balance")) | |
294 | 306 | let PSupply = tryGetInteger("global_poolToken_amount") | |
295 | 307 | let tokenDecimals = tryGetInteger((("static_" + getAssetString(tokenId)) + "_scale")) | |
296 | 308 | let amount = toInt(fraction((toBigInt(Scale8) - fraction(toBigInt((PSupply - PRedeemed)), toBigInt(Scale8), toBigInt(PSupply), CEILING)), toBigInt(Bk), toBigInt(Scale8), DOWN)) | |
297 | 309 | (accum ++ [IntegerEntry((("global_" + getAssetString(tokenId)) + "_balance"), (Bk - amount)), ScriptTransfer(userAddress, amount, tokenId)]) | |
298 | 310 | } | |
299 | 311 | ||
300 | 312 | let $l = assetIds | |
301 | 313 | let $s = size($l) | |
302 | 314 | let $acc0 = nil | |
303 | 315 | func $f4_1 ($a,$i) = if (($i >= $s)) | |
304 | 316 | then $a | |
305 | 317 | else handleTokenRedeem($a, $l[$i]) | |
306 | 318 | ||
307 | 319 | func $f4_2 ($a,$i) = if (($i >= $s)) | |
308 | 320 | then $a | |
309 | 321 | else throw("List size exceeds 10") | |
310 | 322 | ||
311 | 323 | $f4_2($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10) | |
312 | 324 | } | |
313 | 325 | ||
314 | 326 | ||
315 | 327 | func calculateOutAmount (AmountIn,assetIn,assetOut,BalanceIn,BalanceOut) = { | |
316 | 328 | let IndexIn = value(indexOf(assetIds, assetIn)) | |
317 | 329 | let IndexOut = value(indexOf(assetIds, assetOut)) | |
318 | 330 | if ((IndexIn == IndexOut)) | |
319 | - | then | |
331 | + | then AmountIn | |
320 | 332 | else fraction(BalanceOut, ((Scale8 * Scale8) - toInt(pow(fraction(toBigInt(BalanceIn), toBigInt((Scale8 * Scale8)), toBigInt((BalanceIn + AmountIn)), HALFUP), 16, toBigInt(fraction(AssetsWeights[IndexIn], 10000, AssetsWeights[IndexOut])), 4, 16, CEILING))), (Scale8 * Scale8), DOWN) | |
321 | 333 | } | |
322 | 334 | ||
323 | 335 | ||
324 | 336 | func getTokenBalance (assetId) = match assetId { | |
325 | 337 | case t: ByteVector => | |
326 | 338 | assetBalance(this, t) | |
327 | 339 | case _ => | |
328 | 340 | wavesBalance(this).available | |
329 | 341 | } | |
330 | 342 | ||
331 | 343 | ||
332 | 344 | func calculateCurrentAssetInterest (assetId,assetIdStr,aBalance,tokenEarningsLastCheck) = { | |
333 | 345 | let totalStaked = tryGetInteger("global_indexStaked") | |
334 | 346 | let tokenBalanceLastCheck = tokenEarningsLastCheck | |
335 | 347 | let currentBalanceDelta = (getTokenBalance(assetId) - aBalance) | |
336 | 348 | let currentTokenEarnings = if ((currentBalanceDelta > tokenBalanceLastCheck)) | |
337 | 349 | then currentBalanceDelta | |
338 | 350 | else tokenBalanceLastCheck | |
339 | 351 | let newEarnings = (currentTokenEarnings - tokenBalanceLastCheck) | |
340 | 352 | let newInterest = if ((totalStaked == 0)) | |
341 | 353 | then 0 | |
342 | 354 | else fraction(newEarnings, Scale8, totalStaked) | |
343 | 355 | let lastCheckInterest = tryGetInteger((("global_lastCheck_" + assetIdStr) + "_interest")) | |
344 | 356 | (lastCheckInterest + newInterest) | |
345 | 357 | } | |
346 | 358 | ||
347 | 359 | ||
348 | 360 | func claimResult (address) = { | |
349 | 361 | let addressStr = toString(address) | |
350 | 362 | let puzzleAmount = tryGetInteger((addressStr + "_indexStaked")) | |
351 | 363 | func handler (accum,assetId) = { | |
352 | 364 | let assetIdStr = getAssetString(assetId) | |
353 | 365 | let aBalance = tryGetInteger((("global_" + getAssetString(assetId)) + "_balance")) | |
354 | 366 | let tokenEarningsLastCheck = tryGetInteger((("global_lastCheck_" + assetIdStr) + "_earnings")) | |
355 | 367 | let currentTokenInterest = calculateCurrentAssetInterest(assetId, assetIdStr, aBalance, tokenEarningsLastCheck) | |
356 | 368 | let currentTokenEarnings = max([tokenEarningsLastCheck, (getTokenBalance(assetId) - aBalance)]) | |
357 | 369 | let rewardAmount = fraction(puzzleAmount, (currentTokenInterest - tryGetInteger((((addressStr + "_lastCheck_") + assetIdStr) + "_interest"))), Scale8) | |
358 | 370 | let transfer = if ((rewardAmount == 0)) | |
359 | 371 | then nil | |
360 | 372 | else [ScriptTransfer(address, rewardAmount, assetId)] | |
361 | - | $Tuple2(((accum._1 ++ transfer) ++ [IntegerEntry((("global_lastCheck_" + assetIdStr) + "_earnings"), (currentTokenEarnings - rewardAmount)), IntegerEntry((("global_lastCheck_" + assetIdStr) + "_interest"), currentTokenInterest), IntegerEntry((((addressStr + "_lastCheck_") + assetIdStr) + "_interest"), currentTokenInterest)]), (accum._2 + calculateUsdnValue(assetId, rewardAmount, aBalance))) | |
373 | + | $Tuple2(((accum._1 ++ transfer) ++ [IntegerEntry((("global_lastCheck_" + assetIdStr) + "_earnings"), (currentTokenEarnings - rewardAmount)), IntegerEntry((("global_lastCheck_" + assetIdStr) + "_interest"), currentTokenInterest), IntegerEntry((((addressStr + "_lastCheck_") + assetIdStr) + "_interest"), currentTokenInterest)]), (accum._2 + calculateUsdnValue(assetId, rewardAmount, aBalance, unit))) | |
362 | 374 | } | |
363 | 375 | ||
364 | 376 | let accum = { | |
365 | 377 | let $l = earnedAssets | |
366 | 378 | let $s = size($l) | |
367 | 379 | let $acc0 = $Tuple2(nil, 0) | |
368 | 380 | func $f4_1 ($a,$i) = if (($i >= $s)) | |
369 | 381 | then $a | |
370 | 382 | else handler($a, $l[$i]) | |
371 | 383 | ||
372 | 384 | func $f4_2 ($a,$i) = if (($i >= $s)) | |
373 | 385 | then $a | |
374 | 386 | else throw("List size exceeds 10") | |
375 | 387 | ||
376 | 388 | $f4_2($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10) | |
377 | 389 | } | |
378 | 390 | (accum._1 ++ [IntegerEntry((addressStr + "_claimedRewardValue"), (tryGetInteger((addressStr + "_claimedRewardValue")) + accum._2)), IntegerEntry((addressStr + "_lastClaim"), lastBlock.timestamp)]) | |
379 | 391 | } | |
380 | 392 | ||
381 | 393 | ||
382 | 394 | func indexStakeResult (addressStr,amount) = { | |
383 | 395 | let li = claimResult(addressFromStringValue(addressStr)) | |
384 | 396 | (li ++ [IntegerEntry((addressStr + "_indexStaked"), (tryGetInteger((addressStr + "_indexStaked")) + amount)), IntegerEntry("global_indexStaked", (tryGetInteger("global_indexStaked") + amount))]) | |
385 | 397 | } | |
386 | 398 | ||
387 | 399 | ||
388 | 400 | func sum (accum,n) = (accum + parseIntValue(n)) | |
389 | 401 | ||
390 | 402 | ||
391 | 403 | @Callable(i) | |
392 | - | func preInit (assetIdsStr,assetWeightsStr,baseTokenIdStr,poolDomain) = if ((this != i.caller)) | |
393 | - | then throw("admin only") | |
394 | - | else if ((size(poolDomain) > 13)) | |
395 | - | then throw("too large pool domain") | |
396 | - | else { | |
397 | - | let assetIdsStrLi = split(assetIdsStr, ",") | |
398 | - | let assetIdsLi = { | |
399 | - | let $l = assetIdsStrLi | |
400 | - | let $s = size($l) | |
401 | - | let $acc0 = nil | |
402 | - | func $f4_1 ($a,$i) = if (($i >= $s)) | |
403 | - | then $a | |
404 | - | else addAssetBytesToList($a, $l[$i]) | |
404 | + | func preInit (assetIdsStr,assetWeightsStr,baseTokenIdStr,poolDomain,poolOwner,fee) = { | |
405 | + | let poolOwnerAddress = Address(fromBase58String(poolOwner)) | |
406 | + | if ((this != i.caller)) | |
407 | + | then throw("admin only") | |
408 | + | else if ((size(poolDomain) > 13)) | |
409 | + | then throw("too large pool domain") | |
410 | + | else if (if ((fee > 500)) | |
411 | + | then true | |
412 | + | else (50 > fee)) | |
413 | + | then throw("fee value must be between 50 and 500 (0.5-5%)") | |
414 | + | else { | |
415 | + | let assetIdsStrLi = split(assetIdsStr, ",") | |
416 | + | let assetIdsLi = { | |
417 | + | let $l = assetIdsStrLi | |
418 | + | let $s = size($l) | |
419 | + | let $acc0 = nil | |
420 | + | func $f4_1 ($a,$i) = if (($i >= $s)) | |
421 | + | then $a | |
422 | + | else addAssetBytesToList($a, $l[$i]) | |
405 | 423 | ||
406 | - | func $f4_2 ($a,$i) = if (($i >= $s)) | |
407 | - | then $a | |
408 | - | else throw("List size exceeds 10") | |
424 | + | func $f4_2 ($a,$i) = if (($i >= $s)) | |
425 | + | then $a | |
426 | + | else throw("List size exceeds 10") | |
409 | 427 | ||
410 | - | $f4_2($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10) | |
411 | - | } | |
412 | - | let assetWeightsStrLi = split(assetWeightsStr, ",") | |
413 | - | let assetWeightsSum = { | |
414 | - | let $l = assetWeightsStrLi | |
415 | - | let $s = size($l) | |
416 | - | let $acc0 = 0 | |
417 | - | func $f5_1 ($a,$i) = if (($i >= $s)) | |
418 | - | then $a | |
419 | - | else sum($a, $l[$i]) | |
428 | + | $f4_2($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10) | |
429 | + | } | |
430 | + | let assetWeightsStrLi = split(assetWeightsStr, ",") | |
431 | + | let assetWeightsSum = { | |
432 | + | let $l = assetWeightsStrLi | |
433 | + | let $s = size($l) | |
434 | + | let $acc0 = 0 | |
435 | + | func $f5_1 ($a,$i) = if (($i >= $s)) | |
436 | + | then $a | |
437 | + | else sum($a, $l[$i]) | |
420 | 438 | ||
421 | - | func $f5_2 ($a,$i) = if (($i >= $s)) | |
422 | - | then $a | |
423 | - | else throw("List size exceeds 10") | |
439 | + | func $f5_2 ($a,$i) = if (($i >= $s)) | |
440 | + | then $a | |
441 | + | else throw("List size exceeds 10") | |
424 | 442 | ||
425 | - | $f5_2($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10) | |
426 | - | } | |
427 | - | func addTokenDataEntries (accum,assetNum) = if ((assetNum >= size(assetIdsLi))) | |
428 | - | then accum | |
429 | - | else { | |
430 | - | let assetDecimals = match assetIdsLi[assetNum] { | |
431 | - | case x: ByteVector => | |
432 | - | value(assetInfo(x)).decimals | |
433 | - | case _ => | |
434 | - | 8 | |
443 | + | $f5_2($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($f5_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10) | |
444 | + | } | |
445 | + | func addTokenDataEntries (accum,assetNum) = if ((assetNum >= size(assetIdsLi))) | |
446 | + | then accum | |
447 | + | else { | |
448 | + | let assetDecimals = match assetIdsLi[assetNum] { | |
449 | + | case x: ByteVector => | |
450 | + | value(assetInfo(x)).decimals | |
451 | + | case _ => | |
452 | + | 8 | |
453 | + | } | |
454 | + | (accum ++ [IntegerEntry((("static_" + assetIdsStrLi[assetNum]) + "_scale"), pow(10, 0, assetDecimals, 0, 0, DOWN)), IntegerEntry((("static_" + assetIdsStrLi[assetNum]) + "_decimals"), assetDecimals), IntegerEntry((("static_" + assetIdsStrLi[assetNum]) + "_weight"), value(parseInt(assetWeightsStrLi[assetNum])))]) | |
455 | + | } | |
456 | + | ||
457 | + | if ((assetWeightsSum != 10000)) | |
458 | + | then throw("sum of token weights must be equal to 10000") | |
459 | + | else ({ | |
460 | + | let $l = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] | |
461 | + | let $s = size($l) | |
462 | + | let $acc0 = nil | |
463 | + | func $f6_1 ($a,$i) = if (($i >= $s)) | |
464 | + | then $a | |
465 | + | else addTokenDataEntries($a, $l[$i]) | |
466 | + | ||
467 | + | func $f6_2 ($a,$i) = if (($i >= $s)) | |
468 | + | then $a | |
469 | + | else throw("List size exceeds 10") | |
470 | + | ||
471 | + | $f6_2($f6_1($f6_1($f6_1($f6_1($f6_1($f6_1($f6_1($f6_1($f6_1($f6_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10) | |
472 | + | } ++ [StringEntry("static_tokenIds", assetIdsStr), StringEntry("static_tokenWeights", assetWeightsStr), IntegerEntry("static_tokensAmount", size(assetIdsLi)), StringEntry("static_poolDomain", poolDomain), StringEntry("static_baseTokenId", baseTokenIdStr), StringEntry("static_poolOwner", poolOwner), IntegerEntry("static_fee", fee)]) | |
435 | 473 | } | |
436 | - | (accum ++ [IntegerEntry((("static_" + assetIdsStrLi[assetNum]) + "_scale"), pow(10, 0, assetDecimals, 0, 0, DOWN)), IntegerEntry((("static_" + assetIdsStrLi[assetNum]) + "_decimals"), assetDecimals), IntegerEntry((("static_" + assetIdsStrLi[assetNum]) + "_weight"), value(parseInt(assetWeightsStrLi[assetNum])))]) | |
437 | - | } | |
438 | - | ||
439 | - | if ((assetWeightsSum != 100)) | |
440 | - | then throw("sum of token weights must be equal to 100") | |
441 | - | else ({ | |
442 | - | let $l = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] | |
443 | - | let $s = size($l) | |
444 | - | let $acc0 = nil | |
445 | - | func $f6_1 ($a,$i) = if (($i >= $s)) | |
446 | - | then $a | |
447 | - | else addTokenDataEntries($a, $l[$i]) | |
448 | - | ||
449 | - | func $f6_2 ($a,$i) = if (($i >= $s)) | |
450 | - | then $a | |
451 | - | else throw("List size exceeds 10") | |
452 | - | ||
453 | - | $f6_2($f6_1($f6_1($f6_1($f6_1($f6_1($f6_1($f6_1($f6_1($f6_1($f6_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10) | |
454 | - | } ++ [StringEntry("static_tokenIds", assetIdsStr), StringEntry("static_tokenWeights", assetWeightsStr), IntegerEntry("static_tokensAmount", size(assetIdsLi)), StringEntry("static_poolDomain", poolDomain), StringEntry("static_baseTokenId", baseTokenIdStr), IntegerEntry("static_fee", 200)]) | |
455 | - | } | |
474 | + | } | |
456 | 475 | ||
457 | 476 | ||
458 | 477 | ||
459 | 478 | @Callable(i) | |
460 | 479 | func deInit () = if ((i.caller != this)) | |
461 | 480 | then throw("admin only") | |
462 | 481 | else [IntegerEntry("global_wasInited", 0)] | |
463 | 482 | ||
464 | 483 | ||
465 | 484 | ||
466 | 485 | @Callable(i) | |
467 | 486 | func init () = { | |
468 | 487 | func prepareList () = { | |
469 | 488 | func handler (accum,n) = (accum ++ [IntegerEntry((("global_" + getAssetString(n.assetId)) + "_balance"), n.amount)]) | |
470 | 489 | ||
471 | 490 | let $l = i.payments | |
472 | 491 | let $s = size($l) | |
473 | 492 | let $acc0 = nil | |
474 | 493 | func $f4_1 ($a,$i) = if (($i >= $s)) | |
475 | 494 | then $a | |
476 | 495 | else handler($a, $l[$i]) | |
477 | 496 | ||
478 | 497 | func $f4_2 ($a,$i) = if (($i >= $s)) | |
479 | 498 | then $a | |
480 | 499 | else throw("List size exceeds 10") | |
481 | 500 | ||
482 | 501 | $f4_2($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10) | |
483 | 502 | } | |
484 | 503 | ||
485 | 504 | func calculatePoolTokensAmount (payments) = { | |
486 | 505 | func handler (accum,pmt) = { | |
487 | 506 | let assetId = pmt.assetId | |
488 | 507 | func handler2 (accum,n) = if ((n == assetId)) | |
489 | 508 | then value(indexOf(assetIds, n)) | |
490 | 509 | else accum | |
491 | 510 | ||
492 | 511 | let Token = { | |
493 | 512 | let $l = assetIds | |
494 | 513 | let $s = size($l) | |
495 | 514 | let $acc0 = 1 | |
496 | 515 | func $f4_1 ($a,$i) = if (($i >= $s)) | |
497 | 516 | then $a | |
498 | 517 | else handler2($a, $l[$i]) | |
499 | 518 | ||
500 | 519 | func $f4_2 ($a,$i) = if (($i >= $s)) | |
501 | 520 | then $a | |
502 | 521 | else throw("List size exceeds 10") | |
503 | 522 | ||
504 | 523 | $f4_2($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10) | |
505 | 524 | } | |
506 | 525 | fraction(accum, pow(pmt.amount, Decimals[Token], AssetsWeights[Token], AssetsWeightsDecimals, 8, FLOOR), Scale8) | |
507 | 526 | } | |
508 | 527 | ||
509 | 528 | let $l = payments | |
510 | 529 | let $s = size($l) | |
511 | 530 | let $acc0 = PoolTokenScale | |
512 | 531 | func $f4_1 ($a,$i) = if (($i >= $s)) | |
513 | 532 | then $a | |
514 | 533 | else handler($a, $l[$i]) | |
515 | 534 | ||
516 | 535 | func $f4_2 ($a,$i) = if (($i >= $s)) | |
517 | 536 | then $a | |
518 | 537 | else throw("List size exceeds 10") | |
519 | 538 | ||
520 | 539 | $f4_2($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($f4_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10) | |
521 | 540 | } | |
522 | 541 | ||
523 | 542 | if ((tryGetInteger("global_wasInited") > 0)) | |
524 | 543 | then throw("pool already inited") | |
525 | 544 | else { | |
526 | 545 | let initialPoolTokens = calculatePoolTokensAmount(i.payments) | |
527 | 546 | if ((initialPoolTokens == 0)) | |
528 | 547 | then throw("you need a bigger tokens amount to launch the pool") | |
529 | 548 | else { | |
530 | 549 | let poolTokenIssue = Issue(("PZ " + tryGetString("static_poolDomain")), "Puzzle Swap: pool index token", initialPoolTokens, PoolTokenDecimals, true, unit, 0) | |
531 | 550 | let poolTokenId = calculateAssetId(poolTokenIssue) | |
532 | - | (prepareList() ++ [poolTokenIssue, IntegerEntry("global_poolToken_amount", initialPoolTokens), IntegerEntry("global_wasInited", 1), BinaryEntry("global_poolToken_id", poolTokenId), StringEntry("static_poolToken_idStr", getAssetString(poolTokenId)), | |
551 | + | (prepareList() ++ [poolTokenIssue, IntegerEntry("global_poolToken_amount", initialPoolTokens), IntegerEntry("global_wasInited", 1), BinaryEntry("global_poolToken_id", poolTokenId), StringEntry("static_poolToken_idStr", getAssetString(poolTokenId)), IntegerEntry((toString(i.caller) + "_indexStaked"), initialPoolTokens), IntegerEntry("global_indexStaked", initialPoolTokens)]) | |
533 | 552 | } | |
534 | 553 | } | |
535 | 554 | } | |
536 | 555 | ||
537 | 556 | ||
538 | 557 | ||
539 | 558 | @Callable(i) | |
540 | 559 | func generateIndex (needChange) = if ((size(i.payments) != T)) | |
541 | 560 | then throw(("you need to attach all pool tokens. amount of pool tokens: " + toString(T))) | |
542 | 561 | else if (!(checkTokensValidity(i.payments))) | |
543 | 562 | then throw("wrong assets attached") | |
544 | 563 | else { | |
545 | 564 | let PIssued = getMinPIssued(i.payments) | |
546 | 565 | let reissue = Reissue(getBinaryValue("global_poolToken_id"), PIssued, true) | |
547 | 566 | let result = handlePoolTokensAdd(PIssued, i.payments, i.originCaller, needChange) | |
548 | 567 | $Tuple2((result ++ [ScriptTransfer(i.caller, PIssued, tryGetBinary("global_poolToken_id")), reissue, IntegerEntry("global_poolToken_amount", (tryGetInteger("global_poolToken_amount") + PIssued))]), PIssued) | |
549 | 568 | } | |
550 | 569 | ||
551 | 570 | ||
552 | 571 | ||
553 | 572 | @Callable(i) | |
554 | 573 | func stakeIndex () = { | |
555 | 574 | let addressStr = toString(i.originCaller) | |
556 | 575 | let pmt = i.payments[0] | |
557 | 576 | if ((value(pmt.assetId) != tryGetBinary("global_poolToken_id"))) | |
558 | 577 | then throw("wrong asset attached") | |
559 | 578 | else indexStakeResult(addressStr, pmt.amount) | |
560 | 579 | } | |
561 | 580 | ||
562 | 581 | ||
563 | 582 | ||
564 | 583 | @Callable(i) | |
565 | 584 | func unstakeIndex (puzzleAmount) = { | |
566 | 585 | let addressStr = toString(i.originCaller) | |
567 | 586 | let puzzleAvailable = tryGetInteger((addressStr + "_indexStaked")) | |
568 | 587 | if ((puzzleAmount > puzzleAvailable)) | |
569 | 588 | then throw("you don't have index tokens available") | |
570 | - | else (claimResult(i.originCaller) ++ [IntegerEntry((addressStr + "_indexStaked"), (puzzleAvailable - puzzleAmount)), IntegerEntry("global_indexStaked", (tryGetInteger("global_indexStaked") - puzzleAmount)), ScriptTransfer(i.caller, puzzleAmount, getBinaryValue("global_poolToken_id"))]) | |
589 | + | else if (isShutdown()) | |
590 | + | then throw("contract is on stop") | |
591 | + | else (claimResult(i.originCaller) ++ [IntegerEntry((addressStr + "_indexStaked"), (puzzleAvailable - puzzleAmount)), IntegerEntry("global_indexStaked", (tryGetInteger("global_indexStaked") - puzzleAmount)), ScriptTransfer(i.caller, puzzleAmount, getBinaryValue("global_poolToken_id"))]) | |
571 | 592 | } | |
572 | 593 | ||
573 | 594 | ||
574 | 595 | ||
575 | 596 | @Callable(i) | |
576 | - | func claimIndexRewards () = claimResult(i.caller) | |
597 | + | func claimIndexRewards () = if (isShutdown()) | |
598 | + | then throw("contract is on stop") | |
599 | + | else claimResult(i.caller) | |
577 | 600 | ||
578 | 601 | ||
579 | 602 | ||
580 | 603 | @Callable(i) | |
581 | 604 | func redeemIndex (sendToOrigin) = { | |
582 | 605 | let pmt = i.payments[0] | |
583 | 606 | if ((pmt.assetId != tryGetBinary("global_poolToken_id"))) | |
584 | 607 | then throw("please attach pool share token") | |
585 | - | else { | |
586 | - | let PRedeemed = pmt.amount | |
587 | - | let result = handlePoolTokensRedeem(PRedeemed, if (sendToOrigin) | |
588 | - | then i.originCaller | |
589 | - | else i.caller) | |
590 | - | (result ++ [Burn(tryGetBinary("global_poolToken_id"), PRedeemed), IntegerEntry("global_poolToken_amount", (tryGetInteger("global_poolToken_amount") - PRedeemed))]) | |
591 | - | } | |
608 | + | else if (isShutdown()) | |
609 | + | then throw("contract is on stop") | |
610 | + | else { | |
611 | + | let PRedeemed = pmt.amount | |
612 | + | let result = handlePoolTokensRedeem(PRedeemed, if (sendToOrigin) | |
613 | + | then i.originCaller | |
614 | + | else i.caller) | |
615 | + | (result ++ [Burn(tryGetBinary("global_poolToken_id"), PRedeemed), IntegerEntry("global_poolToken_amount", (tryGetInteger("global_poolToken_amount") - PRedeemed))]) | |
616 | + | } | |
592 | 617 | } | |
593 | 618 | ||
594 | 619 | ||
595 | 620 | ||
596 | 621 | @Callable(i) | |
597 | 622 | func swap (assetOut,minimum) = { | |
598 | 623 | let pmt = value(i.payments[0]) | |
599 | 624 | let AmountIn = value(i.payments[0].amount) | |
600 | 625 | let AssetIn = pmt.assetId | |
601 | 626 | let AssetOut = getAssetBytes(assetOut) | |
627 | + | let feeAssetIn = AssetIn | |
628 | + | let feeAssetOut = usdnAssetId | |
602 | 629 | let AssetInBalance = tryGetInteger((("global_" + getAssetString(AssetIn)) + "_balance")) | |
603 | 630 | let AssetOutBalance = tryGetInteger((("global_" + assetOut) + "_balance")) | |
604 | - | let AmountOut = calculateOutAmount(AmountIn, AssetIn, AssetOut, AssetInBalance, AssetOutBalance) | |
605 | - | let feeAmount = fraction(AmountOut, Fee, FeeScale) | |
606 | - | let cleanAmountOut = (AmountOut - feeAmount) | |
607 | - | if ((minimum > cleanAmountOut)) | |
608 | - | then throw(("amount to recieve is lower than given one: " + toString(cleanAmountOut))) | |
609 | - | else if ((0 > (AssetOutBalance - AmountOut))) | |
610 | - | then throw("contract is out of reserves") | |
611 | - | else { | |
612 | - | let newBalanceIn = (AssetInBalance + AmountIn) | |
613 | - | let newBalanceOut = (AssetOutBalance - AmountOut) | |
614 | - | let usdnAssetId = base58'DG2xFkPdDwKUoBkzGAhQtLpSGzfXLiCYPEzeKH2Ad24p' | |
615 | - | if ((usdnAssetId == AssetOut)) | |
616 | - | then { | |
617 | - | let usdnFeeAmount = feeAmount | |
618 | - | let protocolUsdnFee = fraction(usdnFeeAmount, 4, 10) | |
619 | - | let stakingTopUp = reentrantInvoke(Address(base58'3PFTbywqxtFfukX3HyT881g4iW5K4QL3FAS'), "topUpReward", nil, [AttachedPayment(usdnAssetId, protocolUsdnFee)]) | |
620 | - | if ((stakingTopUp == stakingTopUp)) | |
621 | - | then $Tuple2([IntegerEntry((("global_" + assetOut) + "_balance"), newBalanceOut), IntegerEntry((("global_" + getAssetString(AssetIn)) + "_balance"), newBalanceIn), ScriptTransfer(i.caller, cleanAmountOut, AssetOut), IntegerEntry("global_volume", (tryGetInteger("global_volume") + calculateUsdnValue(AssetIn, AmountIn, AssetInBalance)))], cleanAmountOut) | |
622 | - | else throw("Strict value is not equal to itself.") | |
631 | + | let feeAssetOutBalance = tryGetInteger((("global_" + getAssetString(feeAssetOut)) + "_balance")) | |
632 | + | let feeAmountIn = fraction(AmountIn, Fee, FeeScale) | |
633 | + | let cleanAmountIn = (AmountIn - feeAmountIn) | |
634 | + | let AmountOut = calculateOutAmount(cleanAmountIn, AssetIn, AssetOut, AssetInBalance, AssetOutBalance) | |
635 | + | let feeAmountOut = calculateOutAmount(feeAmountIn, AssetIn, feeAssetOut, AssetInBalance, feeAssetOutBalance) | |
636 | + | let creatorFee = fraction(feeAmountOut, 1, 10) | |
637 | + | let protocolFee = fraction(feeAmountOut, 4, 10) | |
638 | + | let stakingTopUp = reentrantInvoke(Address(base58'3PFTbywqxtFfukX3HyT881g4iW5K4QL3FAS'), "topUpReward", nil, [AttachedPayment(feeAssetOut, protocolFee)]) | |
639 | + | if ((stakingTopUp == stakingTopUp)) | |
640 | + | then if ((minimum > AmountOut)) | |
641 | + | then throw(("amount to recieve is lower than given one: " + toString(AmountOut))) | |
642 | + | else if ((0 > (AssetOutBalance - AmountOut))) | |
643 | + | then throw("contract is out of reserves") | |
644 | + | else if (isShutdown()) | |
645 | + | then throw("contract is on stop") | |
646 | + | else { | |
647 | + | let newBalanceIn = (AssetInBalance + AmountIn) | |
648 | + | let newBalanceOut = (AssetOutBalance - AmountOut) | |
649 | + | let newBalanceFeeAsset = if (if ((feeAssetOut != AssetIn)) | |
650 | + | then (feeAssetOut != AssetOut) | |
651 | + | else false) | |
652 | + | then (feeAssetOutBalance - feeAmountOut) | |
653 | + | else unit | |
654 | + | let assetInChange = IntegerEntry((("global_" + getAssetString(AssetIn)) + "_balance"), newBalanceIn) | |
655 | + | let assetOutChange = IntegerEntry((("global_" + assetOut) + "_balance"), newBalanceOut) | |
656 | + | let feeAssetOutChange = if ((newBalanceFeeAsset != unit)) | |
657 | + | then IntegerEntry((("global_" + getAssetString(feeAssetOut)) + "_balance"), feeAssetOutBalance) | |
658 | + | else StringEntry("hello", "world") | |
659 | + | $Tuple2([assetInChange, assetOutChange, feeAssetOutChange, ScriptTransfer(i.caller, AmountOut, AssetOut), ScriptTransfer(addressFromStringValue(tryGetString("static_poolOwner")), creatorFee, feeAssetOut), IntegerEntry("global_earnedByOwner", (tryGetInteger("global_earnedByOwner") + creatorFee)), IntegerEntry("global_volume", (tryGetInteger("global_volume") + calculateUsdnValue(AssetIn, AmountIn, AssetInBalance, feeAssetOutBalance)))], AmountOut) | |
623 | 660 | } | |
624 | - | else { | |
625 | - | let usdnBalance = if ((AssetIn == usdnAssetId)) | |
626 | - | then newBalanceIn | |
627 | - | else tryGetInteger((("global_" + getAssetString(usdnAssetId)) + "_balance")) | |
628 | - | let usdnFeeAmount = calculateOutAmount(feeAmount, AssetOut, usdnAssetId, newBalanceOut, usdnBalance) | |
629 | - | let protocolUsdnFee = fraction(usdnFeeAmount, 4, 10) | |
630 | - | let stakingTopUp = reentrantInvoke(Address(base58'3PFTbywqxtFfukX3HyT881g4iW5K4QL3FAS'), "topUpReward", nil, [AttachedPayment(usdnAssetId, protocolUsdnFee)]) | |
631 | - | if ((stakingTopUp == stakingTopUp)) | |
632 | - | then { | |
633 | - | let usdnBalanceChangeEntry = IntegerEntry((("global_" + toBase58String(usdnAssetId)) + "_balance"), (usdnBalance - usdnFeeAmount)) | |
634 | - | let balanceChanges = if ((AssetIn == usdnAssetId)) | |
635 | - | then [usdnBalanceChangeEntry] | |
636 | - | else [usdnBalanceChangeEntry, IntegerEntry((("global_" + getAssetString(AssetIn)) + "_balance"), newBalanceIn)] | |
637 | - | $Tuple2(([IntegerEntry((("global_" + assetOut) + "_balance"), (newBalanceOut + feeAmount)), ScriptTransfer(i.caller, cleanAmountOut, AssetOut), IntegerEntry("global_volume", (tryGetInteger("global_volume") + calculateUsdnValue(AssetIn, AmountIn, AssetInBalance)))] ++ balanceChanges), cleanAmountOut) | |
638 | - | } | |
639 | - | else throw("Strict value is not equal to itself.") | |
640 | - | } | |
641 | - | } | |
642 | - | } | |
643 | - | ||
644 | - | ||
645 | - | ||
646 | - | @Callable(i) | |
647 | - | func flashLoan (assetIdStr,amount,actionsStr) = { | |
648 | - | let actions = split(actionsStr, "|") | |
649 | - | nil | |
661 | + | else throw("Strict value is not equal to itself.") | |
650 | 662 | } | |
651 | 663 | ||
652 | 664 | ||
653 | 665 | @Verifier(tx) | |
654 | 666 | func verify () = if (isShutdown()) | |
655 | 667 | then false | |
656 | - | else sigVerify(tx.bodyBytes, tx.proofs[0], tx.senderPublicKey) | |
668 | + | else if (sigVerify(tx.bodyBytes, tx.proofs[0], tx.senderPublicKey)) | |
669 | + | then true | |
670 | + | else sigVerify(tx.bodyBytes, tx.proofs[0], masterPubKey) | |
657 | 671 |
github/deemru/w8io/3ef1775 91.45 ms ◑