tx · 7xFZNz985VKPzaYDyMqb8ESKpoCmugPRbvKHGek6khZg

3N3kKNoJohjVQYNLTrYTGTesr3nq3PZNh37:  -0.02100000 Waves

2024.05.15 13:06 [3106994] smart account 3N3kKNoJohjVQYNLTrYTGTesr3nq3PZNh37 > SELF 0.00000000 Waves

{ "type": 13, "id": "7xFZNz985VKPzaYDyMqb8ESKpoCmugPRbvKHGek6khZg", "fee": 2100000, "feeAssetId": null, "timestamp": 1715767583851, "version": 2, "chainId": 84, "sender": "3N3kKNoJohjVQYNLTrYTGTesr3nq3PZNh37", "senderPublicKey": "vmMXxwQAMUAoisvL193ptPiTtaWQqL5YNu2zs1ouTbY", "proofs": [ "3rEXec2NpD63N4NxzdrUjZpvmPSHCs5kAFkV4gGn8XdXdzCuPLyRVQ8VVB4o35PJ81pd1yokuwjwjhSvCCNARUsy" ], "script": "base64:BwI9CAISAwoBCBIECgICGBIECgICGBIECgICGBIECgICGBIECgICGBIECgICGBIECgICGBIECgICGBIECgICGFMACXNlcGFyYXRvcgICX18AB2NoYWluSWQJAMkBAgkAygECCAUEdGhpcwVieXRlcwABAAEACGNoYWluSWRXAQFXABBjb250cmFjdEZpbGVuYW1lAhdmdXR1cmVzX2NhbGN1bGF0b3IucmlkZQAFbXVsdDgAgMLXLwAMbXVsdDE4QmlnSW50CQC2AgEAgICQu7rWrfANAA13YXZlc0RlY2ltYWxzAAgADHVzZHREZWNpbWFscwAGAAt3YXZlc1N0cmluZwIFV0FWRVMADXF1ZXVlSXRlbVNpemUAIAAEYmlnMAkAtgIBAAAACWtNdWx0aXNpZwIMJXNfX211bHRpc2lnAQdrU3RhdHVzAgRkYXBwBHR4SWQJALkJAgkAzAgCAgolc19fc3RhdHVzCQDMCAIFBGRhcHAJAMwIAgUEdHhJZAUDbmlsBQlzZXBhcmF0b3IACWtTaHV0ZG93bgIMJXNfX3NodXRkb3duAAtrUHVibGljS2V5cwIOJXNfX3B1YmxpY0tleXMAEWtNYXRjaGVyUHVibGljS2V5AhQlc19fbWF0Y2hlclB1YmxpY0tleQEFdG9YMTgCB29yaWdWYWwNb3JpZ1NjYWxlTXVsdAkAvAIDCQC2AgEFB29yaWdWYWwFDG11bHQxOEJpZ0ludAkAtgIBBQ1vcmlnU2NhbGVNdWx0AQdmcm9tWDE4AgN2YWwPcmVzdWx0U2NhbGVNdWx0CQCgAwEJALwCAwUDdmFsCQC2AgEFD3Jlc3VsdFNjYWxlTXVsdAUMbXVsdDE4QmlnSW50AQ92YWxpZGF0ZUFkZHJlc3MBB2FkZHJlc3MJAQlpc0RlZmluZWQBCQCmCAEFB2FkZHJlc3MBB3dyYXBFcnIBAXMJAKwCAgkArAICBRBjb250cmFjdEZpbGVuYW1lAgI6IAUBcwEIdGhyb3dFcnIBAXMJAAIBCQEHd3JhcEVycgEFAXMBDHBhcnNlQXNzZXRJZAEFaW5wdXQDCQAAAgUFaW5wdXQFC3dhdmVzU3RyaW5nBQR1bml0CQDZBAEFBWlucHV0AQ9hc3NldElkVG9TdHJpbmcBBWlucHV0AwkAAAIFBWlucHV0BQR1bml0BQt3YXZlc1N0cmluZwkA2AQBCQEFdmFsdWUBBQVpbnB1dAESZ2V0QXNzZXRJbmZvT3JGYWlsAQdhc3NldElkCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAOwHAQUHYXNzZXRJZAkBB3dyYXBFcnIBAhJpbnZhbGlkIGFzc2V0IGluZm8BFmdldEFzc2V0RGVjaW1hbHNPckZhaWwBB2Fzc2V0SWQEByRtYXRjaDAFB2Fzc2V0SWQDCQABAgUHJG1hdGNoMAIEVW5pdAUNd2F2ZXNEZWNpbWFscwMJAAECBQckbWF0Y2gwAgpCeXRlVmVjdG9yBAdhc3NldElkBQckbWF0Y2gwCAkBEmdldEFzc2V0SW5mb09yRmFpbAEFB2Fzc2V0SWQIZGVjaW1hbHMJAAIBAgtNYXRjaCBlcnJvcgEFcG93MTABAW4JAGwGAAoAAAUBbgAAAAAFBERPV04BDXBvdzEwRGVjaW1hbHMBB2Fzc2V0SWQJAQVwb3cxMAEJARZnZXRBc3NldERlY2ltYWxzT3JGYWlsAQUHYXNzZXRJZAAPa0ZhY3RvcnlBZGRyZXNzAhIlc19fZmFjdG9yeUFkZHJlc3MAFGZhY3RvcnlBZGRyZXNzT3B0aW9uBAckbWF0Y2gwCQCdCAIFBHRoaXMFD2tGYWN0b3J5QWRkcmVzcwMJAAECBQckbWF0Y2gwAgZTdHJpbmcEAXMFByRtYXRjaDAJAKYIAQUBcwMJAAECBQckbWF0Y2gwAgRVbml0BQR1bml0CQACAQILTWF0Y2ggZXJyb3IADmZhY3RvcnlBZGRyZXNzCQETdmFsdWVPckVycm9yTWVzc2FnZQIFFGZhY3RvcnlBZGRyZXNzT3B0aW9uCQEHd3JhcEVycgECF2ludmFsaWQgZmFjdG9yeSBhZGRyZXNzAAxrVXNkdEFzc2V0SWQCDyVzX191c2R0QXNzZXRJZAARdXNkdEFzc2V0SWRPcHRpb24EByRtYXRjaDAJAJ0IAgUEdGhpcwUMa1VzZHRBc3NldElkAwkAAQIFByRtYXRjaDACBlN0cmluZwQBcwUHJG1hdGNoMAkBDHBhcnNlQXNzZXRJZAEFAXMDCQABAgUHJG1hdGNoMAIEVW5pdAUEdW5pdAkAAgECC01hdGNoIGVycm9yAAt1c2R0QXNzZXRJZAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCBRF1c2R0QXNzZXRJZE9wdGlvbgkBB3dyYXBFcnIBAhVpbnZhbGlkIHVzZHQgYXNzZXQgaWQADmtQcmljZXNBZGRyZXNzAhUlc19fY2FsY3VsYXRvckFkZHJlc3MACHNodXRkb3duCQELdmFsdWVPckVsc2UCCQCbCAIFDmZhY3RvcnlBZGRyZXNzBQlrU2h1dGRvd24HAQttdXN0QWRkcmVzcwIGY2FsbGVyB2FkZHJlc3MDCQAAAgUGY2FsbGVyBQdhZGRyZXNzBgkBCHRocm93RXJyAQIRcGVybWlzc2lvbiBkZW5pZWQBCG11c3RUaGlzAQZjYWxsZXIJAQttdXN0QWRkcmVzcwIFBmNhbGxlcgUEdGhpcwELbXVzdEZhY3RvcnkBBmNhbGxlcgkBC211c3RBZGRyZXNzAgUGY2FsbGVyBQ5mYWN0b3J5QWRkcmVzcwEJbXVzdEFkbWluAQ9jYWxsZXJQdWJsaWNLZXkECG11bHRpc2lnCQERQGV4dHJOYXRpdmUoMTA2MikBCQERQGV4dHJOYXRpdmUoMTA1MykCBQ5mYWN0b3J5QWRkcmVzcwUJa011bHRpc2lnBA5wdWJsaWNLZXlzTGlzdAkAtQkCCQERQGV4dHJOYXRpdmUoMTA1MykCBQhtdWx0aXNpZwULa1B1YmxpY0tleXMFCXNlcGFyYXRvcgMJAQ9jb250YWluc0VsZW1lbnQCBQ5wdWJsaWNLZXlzTGlzdAkA2AQBBQ9jYWxsZXJQdWJsaWNLZXkGCQEIdGhyb3dFcnIBAgtub3QgYWxsb3dlZAAOa0FjY291bnRTY3JpcHQCESVzX19hY2NvdW50U2NyaXB0AQ1hY2NvdW50U2NyaXB0AAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCcCAIFDmZhY3RvcnlBZGRyZXNzBQ5rQWNjb3VudFNjcmlwdAkBB3dyYXBFcnIBAhlhY2NvdW50IHNjcmlwdCBpcyBub3Qgc2V0AA1rUmV3YXJkQW1vdW50AhAlc19fcmV3YXJkQW1vdW50AQxyZXdhcmRBbW91bnQACQETdmFsdWVPckVycm9yTWVzc2FnZQIJAJoIAgUOZmFjdG9yeUFkZHJlc3MFDWtSZXdhcmRBbW91bnQJAQd3cmFwRXJyAQIYcmV3YXJkIGFtb3VudCBpcyBub3Qgc2V0AA5rQWNjb3VudHNMaW1pdAIRJXNfX2FjY291bnRzTGltaXQAFGFjY291bnRzTGltaXREZWZhdWx0ABQBDWFjY291bnRzTGltaXQACQELdmFsdWVPckVsc2UCCQCaCAIFDmZhY3RvcnlBZGRyZXNzBQ5rQWNjb3VudHNMaW1pdAUUYWNjb3VudHNMaW1pdERlZmF1bHQBCmtEZXBvc2l0ZWQBDmFjY291bnRBZGRyZXNzCQC5CQIJAMwIAgIEJXMlcwkAzAgCAglkZXBvc2l0ZWQJAMwIAgkApQgBBQ5hY2NvdW50QWRkcmVzcwUDbmlsBQlzZXBhcmF0b3IBD2RlcG9zaXRlZE9wdGlvbgEOYWNjb3VudEFkZHJlc3MJAJoIAgUOZmFjdG9yeUFkZHJlc3MJAQprRGVwb3NpdGVkAQUOYWNjb3VudEFkZHJlc3MBB2tDcmVkaXQCDmFjY291bnRBZGRyZXNzB2Fzc2V0SWQJALkJAgkAzAgCAgYlcyVzJXMJAMwIAgIGY3JlZGl0CQDMCAIJAKUIAQUOYWNjb3VudEFkZHJlc3MJAMwIAgkBD2Fzc2V0SWRUb1N0cmluZwEFB2Fzc2V0SWQFA25pbAUJc2VwYXJhdG9yAQlrTGV2ZXJhZ2UBDmFjY291bnRBZGRyZXNzCQC5CQIJAMwIAgIEJXMlcwkAzAgCAghsZXZlcmFnZQkAzAgCCQClCAEFDmFjY291bnRBZGRyZXNzBQNuaWwFCXNlcGFyYXRvcgERa1N5bnRoZXRpY0Fzc2V0SWQBC2Jhc2VBc3NldElkCQC5CQIJAMwIAgIEJXMlcwkAzAgCAhBzeW50aGV0aWNBc3NldElkCQDMCAIJAQ9hc3NldElkVG9TdHJpbmcBBQtiYXNlQXNzZXRJZAUDbmlsBQlzZXBhcmF0b3IBDGtCYXNlQXNzZXRJZAEQc3ludGhldGljQXNzZXRJZAkAuQkCCQDMCAICBCVzJXMJAMwIAgILYmFzZUFzc2V0SWQJAMwIAgkBD2Fzc2V0SWRUb1N0cmluZwEFEHN5bnRoZXRpY0Fzc2V0SWQFA25pbAUJc2VwYXJhdG9yABRSRVFVRVNUX1NUQVRVU19FTVBUWQAAABRSRVFVRVNUX1NUQVRVU19SRUFEWQABAQ5rUmVxdWVzdFN0YXR1cwEJcmVxdWVzdElkCQC5CQIJAMwIAgIEJXMlcwkAzAgCCQDYBAEFCXJlcXVlc3RJZAkAzAgCAgZzdGF0dXMFA25pbAUJc2VwYXJhdG9yARhrQWNjb3VudENyZWF0b3JQdWJsaWNLZXkBDmFjY291bnRBZGRyZXNzCQC5CQIJAMwIAgIEJXMlcwkAzAgCCQClCAEFDmFjY291bnRBZGRyZXNzCQDMCAICEGNyZWF0b3JQdWJsaWNLZXkFA25pbAUJc2VwYXJhdG9yARZrUmVxdWVzdE93bmVyUHVibGljS2V5AQlyZXF1ZXN0SWQJALkJAgkAzAgCAgQlcyVzCQDMCAIJANgEAQUJcmVxdWVzdElkCQDMCAICDm93bmVyUHVibGljS2V5BQNuaWwFCXNlcGFyYXRvcgEVa1JlcXVlc3RBbW91bnRBc3NldElkAQlyZXF1ZXN0SWQJALkJAgkAzAgCAgQlcyVzCQDMCAIJANgEAQUJcmVxdWVzdElkCQDMCAICDWFtb3VudEFzc2V0SWQFA25pbAUJc2VwYXJhdG9yARRrUmVxdWVzdFByaWNlQXNzZXRJZAEJcmVxdWVzdElkCQC5CQIJAMwIAgIEJXMlcwkAzAgCCQDYBAEFCXJlcXVlc3RJZAkAzAgCAgxwcmljZUFzc2V0SWQFA25pbAUJc2VwYXJhdG9yARxrUmVxdWVzdElkVG9BY2NvdW50UHVibGljS2V5AQlyZXF1ZXN0SWQJALkJAgkAzAgCAgQlcyVzCQDMCAIJANgEAQUJcmVxdWVzdElkCQDMCAICG3JlcXVlc3RJZFRvQWNjb3VudFB1YmxpY0tleQUDbmlsBQlzZXBhcmF0b3IBGmtBY2NvdW50QWRkcmVzc1RvUmVxdWVzdElkAQ5hY2NvdW50QWRkcmVzcwkAuQkCCQDMCAICBCVzJXMJAMwIAgkApQgBBQ5hY2NvdW50QWRkcmVzcwkAzAgCAhlhY2NvdW50QWRkcmVzc1RvUmVxdWVzdElkBQNuaWwFCXNlcGFyYXRvcgEOa1JlcXVlc3RzUXVldWUACQC5CQIJAMwIAgICJXMJAMwIAgINcmVxdWVzdHNRdWV1ZQUDbmlsBQlzZXBhcmF0b3IBDXJlcXVlc3RzUXVldWUACQELdmFsdWVPckVsc2UCCQCcCAIFDmZhY3RvcnlBZGRyZXNzCQEOa1JlcXVlc3RzUXVldWUAAQABDmtBY2NvdW50c1F1ZXVlAAkAuQkCCQDMCAICAiVzCQDMCAICDWFjY291bnRzUXVldWUFA25pbAUJc2VwYXJhdG9yAQ1hY2NvdW50c1F1ZXVlAAkBC3ZhbHVlT3JFbHNlAgkAnAgCBQ5mYWN0b3J5QWRkcmVzcwkBDmtBY2NvdW50c1F1ZXVlAAEAARBrUmVxdWVzdHNCeU93bmVyAQxvd25lckFkZHJlc3MJALkJAgkAzAgCAgQlcyVzCQDMCAICCHJlcXVlc3RzCQDMCAIJAKUIAQUMb3duZXJBZGRyZXNzBQNuaWwFCXNlcGFyYXRvcgEPcmVxdWVzdHNCeU93bmVyAQxvd25lckFkZHJlc3MJAQt2YWx1ZU9yRWxzZQIJAJwIAgUOZmFjdG9yeUFkZHJlc3MJARBrUmVxdWVzdHNCeU93bmVyAQUMb3duZXJBZGRyZXNzAQABDGtQYWlyQWxsb3dlZAINYW1vdW50QXNzZXRJZAxwcmljZUFzc2V0SWQJALkJAgkAzAgCAgYlcyVzJXMJAMwIAgkBD2Fzc2V0SWRUb1N0cmluZwEFDWFtb3VudEFzc2V0SWQJAMwIAgkBD2Fzc2V0SWRUb1N0cmluZwEFDHByaWNlQXNzZXRJZAkAzAgCAgtwYWlyQWxsb3dlZAUDbmlsBQlzZXBhcmF0b3IBC3BhaXJBbGxvd2VkAg1hbW91bnRBc3NldElkDHByaWNlQXNzZXRJZAkBC3ZhbHVlT3JFbHNlAgkAmwgCBQ5mYWN0b3J5QWRkcmVzcwkBDGtQYWlyQWxsb3dlZAIFDWFtb3VudEFzc2V0SWQFDHByaWNlQXNzZXRJZAcBBmtQcmljZQEHYXNzZXRJZAkAuQkCCQDMCAICAiVzCQDMCAIJAQ9hc3NldElkVG9TdHJpbmcBBQdhc3NldElkBQNuaWwFCXNlcGFyYXRvcgEPZ2V0Q3VycmVudFByaWNlAQdhc3NldElkBBBtYXRjaGVyUHVibGljS2V5CQDZBAEJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAnQgCBQ5mYWN0b3J5QWRkcmVzcwURa01hdGNoZXJQdWJsaWNLZXkJAQd3cmFwRXJyAQIaaW52YWxpZCBtYXRjaGVyIHB1YmxpYyBrZXkEDm1hdGNoZXJBZGRyZXNzCQCnCAEFEG1hdGNoZXJQdWJsaWNLZXkEBXByaWNlCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAJoIAgUObWF0Y2hlckFkZHJlc3MJAQZrUHJpY2UBBQdhc3NldElkCQEHd3JhcEVycgEJAKwCAgIZaW52YWxpZCBwcmljZSwgYXNzZXRJZCA9IAkBD2Fzc2V0SWRUb1N0cmluZwEFB2Fzc2V0SWQFBXByaWNlAQ9jYWxjVG90YWxDcmVkaXQDB2NyZWRpdEEHY3JlZGl0QgxjdXJyZW50UHJpY2UJALcCAgkAvAIDBQdjcmVkaXRBBQxjdXJyZW50UHJpY2UFDG11bHQxOEJpZ0ludAUHY3JlZGl0QgEQY2FsY1RvdGFsQmFsYW5jZQMIYmFsYW5jZUEIYmFsYW5jZUIMY3VycmVudFByaWNlCQC3AgIJALwCAwUIYmFsYW5jZUEFDGN1cnJlbnRQcmljZQUMbXVsdDE4QmlnSW50BQhiYWxhbmNlQgEHY2FsY1BubAIMdG90YWxCYWxhbmNlC3RvdGFsQ3JlZGl0CQC4AgIFDHRvdGFsQmFsYW5jZQULdG90YWxDcmVkaXQBE2NhbGNDcmVkaXRBdmFpbGFibGUDB2RlcG9zaXQIbGV2ZXJhZ2ULdG90YWxDcmVkaXQJALgCAgkAvAIDBQdkZXBvc2l0BQhsZXZlcmFnZQUMbXVsdDE4QmlnSW50BQt0b3RhbENyZWRpdAEQY2FsY1JlYWxJbkNyZWRpdAIGY3JlZGl0B2JhbGFuY2UDCQC/AgIFBmNyZWRpdAUEYmlnMAkAuAICBQZjcmVkaXQFB2JhbGFuY2UFBGJpZzABCGNhbGNGcmVlAgZjcmVkaXQHYmFsYW5jZQMJAL8CAgUGY3JlZGl0BQRiaWcwCQC4AgIFB2JhbGFuY2UFBmNyZWRpdAUEYmlnMAEOY2FsY1Nob3J0UHJpY2UCBGZyZWUMcmVhbEluQ3JlZGl0AwkAvwICBQxyZWFsSW5DcmVkaXQFBGJpZzAJAJgDAQkAzAgCBQRiaWcwCQDMCAIJALwCAwUEZnJlZQUMbXVsdDE4QmlnSW50BQxyZWFsSW5DcmVkaXQFA25pbAUEYmlnMAENY2FsY0xvbmdQcmljZQIEZnJlZQxyZWFsSW5DcmVkaXQDCQC/AgIFDHJlYWxJbkNyZWRpdAUEYmlnMAkAmAMBCQDMCAIFBGJpZzAJAMwIAgkAvAIDBQxyZWFsSW5DcmVkaXQFDG11bHQxOEJpZ0ludAUEZnJlZQUDbmlsBQRiaWcwAQ9jYWxjU3RhcnRNYXJnaW4EDXJlYWxJbkNyZWRpdEENcmVhbEluQ3JlZGl0QgxjdXJyZW50UHJpY2UOc2V0dGluZ3NNYXJnaW4JALwCAwkAtwICCQC8AgMFDXJlYWxJbkNyZWRpdEEFDGN1cnJlbnRQcmljZQUMbXVsdDE4QmlnSW50BQ1yZWFsSW5DcmVkaXRCBQ5zZXR0aW5nc01hcmdpbgUMbXVsdDE4QmlnSW50ARBjYWxjTWFyZ2luU3VwcGx5AxRzZXR0aW5nc01hcmdpblN1cHBseQ5zZXR0aW5nc01hcmdpbgtzdGFydE1hcmdpbgkAvAIDBRRzZXR0aW5nc01hcmdpblN1cHBseQULc3RhcnRNYXJnaW4FDnNldHRpbmdzTWFyZ2luARRjYWxjTGlxdWlkYXRpb25QcmljZQYHZGVwb3NpdAxtYXJnaW5TdXBwbHkNcmVhbEluQ3JlZGl0QQ1yZWFsSW5DcmVkaXRCCnNob3J0UHJpY2UJbG9uZ1ByaWNlBBFsaXF1aWRhdGlvblByaWNlQQMJAGYCBQ1yZWFsSW5DcmVkaXRBAAAJAGQCCQBpAgkAZQIFB2RlcG9zaXQFDG1hcmdpblN1cHBseQUNcmVhbEluQ3JlZGl0QQUKc2hvcnRQcmljZQAABBFsaXF1aWRhdGlvblByaWNlQgMJAGYCBQ1yZWFsSW5DcmVkaXRCAAAJAGUCBQlsb25nUHJpY2UJAGkCCQBlAgUHZGVwb3NpdAUMbWFyZ2luU3VwcGx5CQBpAgUNcmVhbEluQ3JlZGl0QQUJbG9uZ1ByaWNlAAAJAGQCBRFsaXF1aWRhdGlvblByaWNlQQURbGlxdWlkYXRpb25QcmljZUIBGWdldEFzc2V0c0J5QWNjb3VudEFkZHJlc3MBDmFjY291bnRBZGRyZXNzBAlyZXF1ZXN0SWQJANkEAQkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCdCAIFDmZhY3RvcnlBZGRyZXNzCQEaa0FjY291bnRBZGRyZXNzVG9SZXF1ZXN0SWQBBQ5hY2NvdW50QWRkcmVzcwkBB3dyYXBFcnIBAhdpbnZhbGlkIGFjY291bnQgYWRkcmVzcwQNYW1vdW50QXNzZXRJZAkBDHBhcnNlQXNzZXRJZAEJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAnQgCBQ5mYWN0b3J5QWRkcmVzcwkBFWtSZXF1ZXN0QW1vdW50QXNzZXRJZAEFCXJlcXVlc3RJZAkBB3dyYXBFcnIBAhdpbnZhbGlkIGFtb3VudCBhc3NldCBpZAQMcHJpY2VBc3NldElkCQEMcGFyc2VBc3NldElkAQkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCdCAIFDmZhY3RvcnlBZGRyZXNzCQEUa1JlcXVlc3RQcmljZUFzc2V0SWQBBQlyZXF1ZXN0SWQJAQd3cmFwRXJyAQIXaW52YWxpZCBhbW91bnQgcHJpY2UgaWQJAJQKAgUNYW1vdW50QXNzZXRJZAUMcHJpY2VBc3NldElkCgFpAQRpbml0ARFmYWN0b3J5QWRkcmVzc1N0cgQLY2hlY2tDYWxsZXIJAQhtdXN0VGhpcwEIBQFpBmNhbGxlcgMJAAACBQtjaGVja0NhbGxlcgULY2hlY2tDYWxsZXIJAJQKAgkAzAgCCQELU3RyaW5nRW50cnkCBQ9rRmFjdG9yeUFkZHJlc3MFEWZhY3RvcnlBZGRyZXNzU3RyBQNuaWwFBHVuaXQJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQEOcmVxdWVzdEFjY291bnQCD2NhbGxlclB1YmxpY0tleQRhcmdzBAZja2Vja3MJAMwIAgMJAQEhAQUIc2h1dGRvd24GCQEIdGhyb3dFcnIBAgtub3QgYWxsb3dlZAkAzAgCCQELbXVzdEZhY3RvcnkBCAUBaQZjYWxsZXIFA25pbAMJAAACBQZja2Vja3MFBmNrZWNrcwQQYW1vdW50QXNzZXRJZFN0cgkAkQMCBQRhcmdzAAAED3ByaWNlQXNzZXRJZFN0cgkAkQMCBQRhcmdzAAEEC3VzZXJBZGRyZXNzCQCnCAEFD2NhbGxlclB1YmxpY0tleQQJcmVxdWVzdElkCQD3AwEJAMsBAgkAywECCAULdXNlckFkZHJlc3MFYnl0ZXMJANkEAQUQYW1vdW50QXNzZXRJZFN0cgkA2QQBBQ9wcmljZUFzc2V0SWRTdHIEDWFtb3VudEFzc2V0SWQJAQxwYXJzZUFzc2V0SWQBBRBhbW91bnRBc3NldElkU3RyBAxwcmljZUFzc2V0SWQJAQxwYXJzZUFzc2V0SWQBBQ9wcmljZUFzc2V0SWRTdHIEEnVzZXJSZXF1ZXN0c051bWJlcgkAaQIJALECAQkBEGtSZXF1ZXN0c0J5T3duZXIBBQt1c2VyQWRkcmVzcwUNcXVldWVJdGVtU2l6ZQQGY2hlY2tzCQDMCAIDCQAAAgkAkAMBCAUBaQhwYXltZW50cwABBgkBCHRocm93RXJyAQIVMSBwYXltZW50IGlzIHJlcXVpcmVkCQDMCAIDCQAAAggJAJEDAggFAWkIcGF5bWVudHMAAAdhc3NldElkBQR1bml0BgkBCHRocm93RXJyAQINaW52YWxpZCBhc3NldAkAzAgCAwkAAAIICQCRAwIIBQFpCHBheW1lbnRzAAAGYW1vdW50CQEMcmV3YXJkQW1vdW50AAYJAQh0aHJvd0VycgECDmludmFsaWQgYW1vdW50CQDMCAIDCQELcGFpckFsbG93ZWQCBQ1hbW91bnRBc3NldElkBQxwcmljZUFzc2V0SWQGCQEIdGhyb3dFcnIBAhNwYWlyIGlzIG5vdCBhbGxvd2VkCQDMCAIDCQAAAgkAmggCBQ5mYWN0b3J5QWRkcmVzcwkBDmtSZXF1ZXN0U3RhdHVzAQUJcmVxdWVzdElkBQR1bml0BgkBCHRocm93RXJyAQIZYWNjb3VudCBpcyBhbHJlYWR5IGV4aXN0cwkAzAgCAwkAZgIJAQ1hY2NvdW50c0xpbWl0AAUSdXNlclJlcXVlc3RzTnVtYmVyBgkBCHRocm93RXJyAQkArAICAhJhY2NvdW50cyBsaW1pdCBpcyAJAKQDAQkBDWFjY291bnRzTGltaXQABQNuaWwDCQAAAgUGY2hlY2tzBQZjaGVja3MEDSR0MDEwNzQ3MTIxMDMDCQAAAgkAyAEBCQENYWNjb3VudHNRdWV1ZQAAAAkAlAoCCQDMCAIJAQ5TY3JpcHRUcmFuc2ZlcgMFDmZhY3RvcnlBZGRyZXNzCQEMcmV3YXJkQW1vdW50AAUEdW5pdAUDbmlsCQDMCAIJAPwHBAUOZmFjdG9yeUFkZHJlc3MCDGludGVnZXJFbnRyeQkAzAgCCQEOa1JlcXVlc3RTdGF0dXMBBQlyZXF1ZXN0SWQJAMwIAgUUUkVRVUVTVF9TVEFUVVNfRU1QVFkFA25pbAUDbmlsCQDMCAIJAPwHBAUOZmFjdG9yeUFkZHJlc3MCC2JpbmFyeUVudHJ5CQDMCAIJAQ5rUmVxdWVzdHNRdWV1ZQAJAMwIAgkAywECCQENcmVxdWVzdHNRdWV1ZQAFCXJlcXVlc3RJZAUDbmlsBQNuaWwFA25pbAQQYWNjb3VudFB1YmxpY0tleQkAyQECCQENYWNjb3VudHNRdWV1ZQAFDXF1ZXVlSXRlbVNpemUEDmFjY291bnRBZGRyZXNzCQCnCAEFEGFjY291bnRQdWJsaWNLZXkEDmNyZWF0b3JBZGRyZXNzCQCnCAEJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAnAgCBQ5mYWN0b3J5QWRkcmVzcwkBGGtBY2NvdW50Q3JlYXRvclB1YmxpY0tleQEFDmFjY291bnRBZGRyZXNzCQEHd3JhcEVycgECGmludmFsaWQgY3JlYXRvciBwdWJsaWMga2V5CQCUCgIJAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwUOY3JlYXRvckFkZHJlc3MJAQxyZXdhcmRBbW91bnQABQR1bml0BQNuaWwJAMwIAgkA/AcEBQ5mYWN0b3J5QWRkcmVzcwILYmluYXJ5RW50cnkJAMwIAgkBDmtBY2NvdW50c1F1ZXVlAAkAzAgCCQDKAQIJAQ1hY2NvdW50c1F1ZXVlAAUNcXVldWVJdGVtU2l6ZQUDbmlsBQNuaWwJAMwIAgkA/AcEBQ5mYWN0b3J5QWRkcmVzcwIMaW50ZWdlckVudHJ5CQDMCAIJAQ5rUmVxdWVzdFN0YXR1cwEFCXJlcXVlc3RJZAkAzAgCBRRSRVFVRVNUX1NUQVRVU19SRUFEWQUDbmlsBQNuaWwJAMwIAgkA/AcEBQ5mYWN0b3J5QWRkcmVzcwILYmluYXJ5RW50cnkJAMwIAgkBHGtSZXF1ZXN0SWRUb0FjY291bnRQdWJsaWNLZXkBBQlyZXF1ZXN0SWQJAMwIAgUQYWNjb3VudFB1YmxpY0tleQUDbmlsBQNuaWwJAMwIAgkA/AcEBQ5mYWN0b3J5QWRkcmVzcwILc3RyaW5nRW50cnkJAMwIAgkBGmtBY2NvdW50QWRkcmVzc1RvUmVxdWVzdElkAQUOYWNjb3VudEFkZHJlc3MJAMwIAgkA2AQBBQlyZXF1ZXN0SWQFA25pbAUDbmlsBQNuaWwEB2FjdGlvbnMIBQ0kdDAxMDc0NzEyMTAzAl8xBA5mYWN0b3J5QWN0aW9ucwgFDSR0MDEwNzQ3MTIxMDMCXzIJAJQKAgUHYWN0aW9ucwkAzggCBQ5mYWN0b3J5QWN0aW9ucwkAzAgCCQD8BwQFDmZhY3RvcnlBZGRyZXNzAgtiaW5hcnlFbnRyeQkAzAgCCQEWa1JlcXVlc3RPd25lclB1YmxpY0tleQEFCXJlcXVlc3RJZAkAzAgCBQ9jYWxsZXJQdWJsaWNLZXkFA25pbAUDbmlsCQDMCAIJAPwHBAUOZmFjdG9yeUFkZHJlc3MCC2JpbmFyeUVudHJ5CQDMCAIJARBrUmVxdWVzdHNCeU93bmVyAQULdXNlckFkZHJlc3MJAMwIAgkAywECCQEPcmVxdWVzdHNCeU93bmVyAQULdXNlckFkZHJlc3MFCXJlcXVlc3RJZAUDbmlsBQNuaWwJAMwIAgkA/AcEBQ5mYWN0b3J5QWRkcmVzcwILc3RyaW5nRW50cnkJAMwIAgkBFWtSZXF1ZXN0QW1vdW50QXNzZXRJZAEFCXJlcXVlc3RJZAkAzAgCBRBhbW91bnRBc3NldElkU3RyBQNuaWwFA25pbAkAzAgCCQD8BwQFDmZhY3RvcnlBZGRyZXNzAgtzdHJpbmdFbnRyeQkAzAgCCQEUa1JlcXVlc3RQcmljZUFzc2V0SWQBBQlyZXF1ZXN0SWQJAMwIAgUPcHJpY2VBc3NldElkU3RyBQNuaWwFA25pbAUDbmlsCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBCmFkZEFjY291bnQCD2NhbGxlclB1YmxpY0tleQRhcmdzBAZja2Vja3MJAMwIAgMJAQEhAQUIc2h1dGRvd24GCQEIdGhyb3dFcnIBAgtub3QgYWxsb3dlZAkAzAgCCQELbXVzdEZhY3RvcnkBCAUBaQZjYWxsZXIFA25pbAMJAAACBQZja2Vja3MFBmNrZWNrcwQQY3JlYXRvclB1YmxpY0tleQkA2QQBCQCRAwIFBGFyZ3MAAAQQYWNjb3VudFB1YmxpY0tleQUPY2FsbGVyUHVibGljS2V5BA5hY2NvdW50QWRkcmVzcwkApwgBBQ9jYWxsZXJQdWJsaWNLZXkEDmNyZWF0b3JBZGRyZXNzCQCnCAEFEGNyZWF0b3JQdWJsaWNLZXkEBmNoZWNrcwkAzAgCAwkAAAIJAJwIAgUOZmFjdG9yeUFkZHJlc3MJARhrQWNjb3VudENyZWF0b3JQdWJsaWNLZXkBBQ5hY2NvdW50QWRkcmVzcwUEdW5pdAYJAQh0aHJvd0VycgECGWFjY291bnQgaXMgYWxyZWFkeSBleGlzdHMJAMwIAgMEByRtYXRjaDAJAPEHAQUOYWNjb3VudEFkZHJlc3MDCQABAgUHJG1hdGNoMAIKQnl0ZVZlY3RvcgQBYgUHJG1hdGNoMAkAAAIFAWIJAPEVAQkBDWFjY291bnRTY3JpcHQABwYJAQh0aHJvd0VycgECDmludmFsaWQgc2NyaXB0BQNuaWwDCQAAAgUGY2hlY2tzBQZjaGVja3MEDSR0MDEzMzU4MTQzNjADCQAAAgkAyAEBCQENcmVxdWVzdHNRdWV1ZQAAAAkAlAoCBQNuaWwJAMwIAgkA/AcEBQ5mYWN0b3J5QWRkcmVzcwILYmluYXJ5RW50cnkJAMwIAgkBDmtBY2NvdW50c1F1ZXVlAAkAzAgCCQDLAQIJAQ1hY2NvdW50c1F1ZXVlAAUQYWNjb3VudFB1YmxpY0tleQUDbmlsBQNuaWwFA25pbAQJcmVxdWVzdElkCQDJAQIJAQ1yZXF1ZXN0c1F1ZXVlAAUNcXVldWVJdGVtU2l6ZQkAlAoCBQNuaWwJAMwIAgkA/AcEBQ5mYWN0b3J5QWRkcmVzcwIMaW50ZWdlckVudHJ5CQDMCAIJAQ5rUmVxdWVzdFN0YXR1cwEFCXJlcXVlc3RJZAkAzAgCBRRSRVFVRVNUX1NUQVRVU19SRUFEWQUDbmlsBQNuaWwJAMwIAgkA/AcEBQ5mYWN0b3J5QWRkcmVzcwILYmluYXJ5RW50cnkJAMwIAgkBHGtSZXF1ZXN0SWRUb0FjY291bnRQdWJsaWNLZXkBBQlyZXF1ZXN0SWQJAMwIAgUQYWNjb3VudFB1YmxpY0tleQUDbmlsBQNuaWwJAMwIAgkA/AcEBQ5mYWN0b3J5QWRkcmVzcwILYmluYXJ5RW50cnkJAMwIAgkBDmtSZXF1ZXN0c1F1ZXVlAAkAzAgCCQDKAQIJAQ1yZXF1ZXN0c1F1ZXVlAAUNcXVldWVJdGVtU2l6ZQUDbmlsBQNuaWwJAMwIAgkA/AcEBQ5mYWN0b3J5QWRkcmVzcwILc3RyaW5nRW50cnkJAMwIAgkBGmtBY2NvdW50QWRkcmVzc1RvUmVxdWVzdElkAQUOYWNjb3VudEFkZHJlc3MJAMwIAgkA2AQBBQlyZXF1ZXN0SWQFA25pbAUDbmlsCQDMCAIJAPwHBAUOZmFjdG9yeUFkZHJlc3MCDXRyYW5zZmVyV2F2ZXMJAMwIAggFDmNyZWF0b3JBZGRyZXNzBWJ5dGVzCQDMCAIJAQxyZXdhcmRBbW91bnQABQNuaWwFA25pbAUDbmlsBAdhY3Rpb25zCAUNJHQwMTMzNTgxNDM2MAJfMQQOZmFjdG9yeUFjdGlvbnMIBQ0kdDAxMzM1ODE0MzYwAl8yCQCUCgIFB2FjdGlvbnMJAM4IAgUOZmFjdG9yeUFjdGlvbnMJAMwIAgkA/AcEBQ5mYWN0b3J5QWRkcmVzcwILYmluYXJ5RW50cnkJAMwIAgkBGGtBY2NvdW50Q3JlYXRvclB1YmxpY0tleQEFDmFjY291bnRBZGRyZXNzCQDMCAIFEGNyZWF0b3JQdWJsaWNLZXkFA25pbAUDbmlsBQNuaWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQEHZGVwb3NpdAIPY2FsbGVyUHVibGljS2V5BGFyZ3MEB3BheW1lbnQJAJEDAggFAWkIcGF5bWVudHMAAAQGY2tlY2tzCQDMCAIDCQEBIQEFCHNodXRkb3duBgkBCHRocm93RXJyAQILbm90IGFsbG93ZWQJAMwIAgkBC211c3RGYWN0b3J5AQgFAWkGY2FsbGVyCQDMCAIDCQAAAgkAkAMBCAUBaQhwYXltZW50cwABBgkBCHRocm93RXJyAQIVMSBwYXltZW50IGlzIHJlcXVpcmVkCQDMCAIDCQAAAggFB3BheW1lbnQHYXNzZXRJZAULdXNkdEFzc2V0SWQGCQEIdGhyb3dFcnIBAg1pbnZhbGlkIGFzc2V0BQNuaWwDCQAAAgUGY2tlY2tzBQZja2Vja3MEDmFjY291bnRBZGRyZXNzCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKYIAQkAkQMCBQRhcmdzAAAJAQd3cmFwRXJyAQIXaW52YWxpZCBhY2NvdW50IGFkZHJlc3MEB2FjdGlvbnMJAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwUOYWNjb3VudEFkZHJlc3MIBQdwYXltZW50BmFtb3VudAgFB3BheW1lbnQHYXNzZXRJZAUDbmlsBA5mYWN0b3J5QWN0aW9ucwkAzAgCCQD8BwQFDmZhY3RvcnlBZGRyZXNzAgxpbnRlZ2VyRW50cnkJAMwIAgkBCmtEZXBvc2l0ZWQBBQ5hY2NvdW50QWRkcmVzcwkAzAgCCQBkAgkBC3ZhbHVlT3JFbHNlAgkBD2RlcG9zaXRlZE9wdGlvbgEFDmFjY291bnRBZGRyZXNzAAAIBQdwYXltZW50BmFtb3VudAUDbmlsBQNuaWwFA25pbAkAlAoCBQdhY3Rpb25zBQ5mYWN0b3J5QWN0aW9ucwkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpAQh3aXRoZHJhdwIPY2FsbGVyUHVibGljS2V5BGFyZ3MEBmNrZWNrcwkAzAgCAwkBASEBBQhzaHV0ZG93bgYJAQh0aHJvd0VycgECC25vdCBhbGxvd2VkCQDMCAIJAQttdXN0RmFjdG9yeQEIBQFpBmNhbGxlcgUDbmlsAwkAAAIFBmNrZWNrcwUGY2tlY2tzBAt1c2VyQWRkcmVzcwkApwgBBQ9jYWxsZXJQdWJsaWNLZXkEDmFjY291bnRBZGRyZXNzCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKYIAQkAkQMCBQRhcmdzAAAJAQd3cmFwRXJyAQIXaW52YWxpZCBhY2NvdW50IGFkZHJlc3MEBmFtb3VudAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQC2CQEJAJEDAgUEYXJncwABCQEHd3JhcEVycgECDmludmFsaWQgYW1vdW50BAdhc3NldElkCQEMcGFyc2VBc3NldElkAQkAkQMCBQRhcmdzAAIEC2ludm9jYXRpb25zCQDMCAIJAPwHBAUOYWNjb3VudEFkZHJlc3MCDXRyYW5zZmVyQXNzZXQJAMwIAggFC3VzZXJBZGRyZXNzBWJ5dGVzCQDMCAIFBmFtb3VudAkAzAgCBQdhc3NldElkBQNuaWwFA25pbAUDbmlsCQCUCgIFA25pbAULaW52b2NhdGlvbnMJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQEGYm9ycm93Ag9jYWxsZXJQdWJsaWNLZXkEYXJncwQGY2tlY2tzCQDMCAIDCQEBIQEFCHNodXRkb3duBgkBCHRocm93RXJyAQILbm90IGFsbG93ZWQJAMwIAgkBC211c3RGYWN0b3J5AQgFAWkGY2FsbGVyBQNuaWwDCQAAAgUGY2tlY2tzBQZja2Vja3MEDmFjY291bnRBZGRyZXNzCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKYIAQkAkQMCBQRhcmdzAAAJAQd3cmFwRXJyAQIXaW52YWxpZCBhY2NvdW50IGFkZHJlc3MEB2Fzc2V0SWQJAQxwYXJzZUFzc2V0SWQBCQCRAwIFBGFyZ3MAAQQJYW1vdW50UmF3CQC2CQEJAJEDAgUEYXJncwACBA0kdDAxNjQzNTE2NTEyCQEZZ2V0QXNzZXRzQnlBY2NvdW50QWRkcmVzcwEFDmFjY291bnRBZGRyZXNzBA1hbW91bnRBc3NldElkCAUNJHQwMTY0MzUxNjUxMgJfMQQMcHJpY2VBc3NldElkCAUNJHQwMTY0MzUxNjUxMgJfMgQJZGVwb3NpdGVkCQEFdG9YMTgCCQELdmFsdWVPckVsc2UCCQEPZGVwb3NpdGVkT3B0aW9uAQUOYWNjb3VudEFkZHJlc3MAAAkBDXBvdzEwRGVjaW1hbHMBBQxwcmljZUFzc2V0SWQEDGN1cnJlbnRQcmljZQkBBXRvWDE4AgkBD2dldEN1cnJlbnRQcmljZQEFDWFtb3VudEFzc2V0SWQJAQ1wb3cxMERlY2ltYWxzAQULdXNkdEFzc2V0SWQEB2NyZWRpdEEJAQV0b1gxOAIJAQt2YWx1ZU9yRWxzZQIJAJoIAgUOZmFjdG9yeUFkZHJlc3MJAQdrQ3JlZGl0AgUOYWNjb3VudEFkZHJlc3MFDWFtb3VudEFzc2V0SWQAAAkBDXBvdzEwRGVjaW1hbHMBBQ1hbW91bnRBc3NldElkBAdjcmVkaXRCCQEFdG9YMTgCCQELdmFsdWVPckVsc2UCCQCaCAIFDmZhY3RvcnlBZGRyZXNzCQEHa0NyZWRpdAIFDmFjY291bnRBZGRyZXNzBQxwcmljZUFzc2V0SWQAAAkBDXBvdzEwRGVjaW1hbHMBBQxwcmljZUFzc2V0SWQEC3RvdGFsQ3JlZGl0CQEPY2FsY1RvdGFsQ3JlZGl0AwUHY3JlZGl0QQUHY3JlZGl0QgUMY3VycmVudFByaWNlBA9sZXZlcmFnZURlZmF1bHQAAwQIbGV2ZXJhZ2UJAQV0b1gxOAIJAQt2YWx1ZU9yRWxzZQIJAJoIAgUOZmFjdG9yeUFkZHJlc3MJAQlrTGV2ZXJhZ2UBBQ5hY2NvdW50QWRkcmVzcwUPbGV2ZXJhZ2VEZWZhdWx0AAEED2NyZWRpdEF2YWlsYWJsZQkBE2NhbGNDcmVkaXRBdmFpbGFibGUDBQlkZXBvc2l0ZWQFCGxldmVyYWdlBQt0b3RhbENyZWRpdAkAlAoCBQNuaWwJAMwIAgkBB2Zyb21YMTgCBQ9jcmVkaXRBdmFpbGFibGUJAQ1wb3cxMERlY2ltYWxzAQUMcHJpY2VBc3NldElkBQNuaWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQEFcmVwYXkCD2NhbGxlclB1YmxpY0tleQRhcmdzBAZja2Vja3MJAMwIAgMJAQEhAQUIc2h1dGRvd24GCQEIdGhyb3dFcnIBAgtub3QgYWxsb3dlZAkAzAgCCQELbXVzdEZhY3RvcnkBCAUBaQZjYWxsZXIFA25pbAMJAAACBQZja2Vja3MFBmNrZWNrcwkAlAoCBQNuaWwFBHVuaXQJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQEQc2V0UGFpckFsbG93YW5jZQIPY2FsbGVyUHVibGljS2V5BGFyZ3MEBmNrZWNrcwkAzAgCAwkBASEBBQhzaHV0ZG93bgYJAQh0aHJvd0VycgECC25vdCBhbGxvd2VkCQDMCAIJAQttdXN0RmFjdG9yeQEIBQFpBmNhbGxlcgkAzAgCCQEJbXVzdEFkbWluAQUPY2FsbGVyUHVibGljS2V5BQNuaWwDCQAAAgUGY2tlY2tzBQZja2Vja3MEEGFtb3VudEFzc2V0SWRTdHIJAJEDAgUEYXJncwAABA9wcmljZUFzc2V0SWRTdHIJAJEDAgUEYXJncwABBAhhbGxvd1N0cgkAkQMCBQRhcmdzAAIEDWFtb3VudEFzc2V0SWQJAQxwYXJzZUFzc2V0SWQBBRBhbW91bnRBc3NldElkU3RyBAxwcmljZUFzc2V0SWQJAQxwYXJzZUFzc2V0SWQBBQ9wcmljZUFzc2V0SWRTdHIEBWFsbG93CQAAAgUIYWxsb3dTdHICBHRydWUEC2ludm9jYXRpb25zCQDMCAIJAPwHBAUOZmFjdG9yeUFkZHJlc3MCDGJvb2xlYW5FbnRyeQkAzAgCCQEMa1BhaXJBbGxvd2VkAgUNYW1vdW50QXNzZXRJZAUMcHJpY2VBc3NldElkCQDMCAIFBWFsbG93BQNuaWwFA25pbAUDbmlsCQCUCgIFA25pbAULaW52b2NhdGlvbnMJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQERYWRkU3ludGhldGljQXNzZXQCD2NhbGxlclB1YmxpY0tleQRhcmdzBA5iYXNlQXNzZXRJZFN0cgkAkQMCBQRhcmdzAAAEC2Jhc2VBc3NldElkCQEMcGFyc2VBc3NldElkAQUOYmFzZUFzc2V0SWRTdHIEEHN5bnRoZXRpY0Fzc2V0SWQICQCRAwIIBQFpCHBheW1lbnRzAAAHYXNzZXRJZAQGY2tlY2tzCQDMCAIDCQEBIQEFCHNodXRkb3duBgkBCHRocm93RXJyAQILbm90IGFsbG93ZWQJAMwIAgkBC211c3RGYWN0b3J5AQgFAWkGY2FsbGVyCQDMCAIJAQltdXN0QWRtaW4BBQ9jYWxsZXJQdWJsaWNLZXkJAMwIAgMJAAACCQCdCAIFDmZhY3RvcnlBZGRyZXNzCQERa1N5bnRoZXRpY0Fzc2V0SWQBBQtiYXNlQXNzZXRJZAUEdW5pdAYJAQh0aHJvd0VycgECEmludmFsaWQgYmFzZSBhc3NldAkAzAgCAwkAAAIJAJADAQgFAWkIcGF5bWVudHMAAQYJAQh0aHJvd0VycgECEGludmFsaWQgcGF5bWVudHMJAMwIAgMJAAACCQCdCAIFDmZhY3RvcnlBZGRyZXNzCQEMa0Jhc2VBc3NldElkAQUQc3ludGhldGljQXNzZXRJZAUEdW5pdAYJAQh0aHJvd0VycgECF2ludmFsaWQgc3ludGhldGljIGFzc2V0BQNuaWwDCQAAAgUGY2tlY2tzBQZja2Vja3MEC2ludm9jYXRpb25zCQDMCAIJAPwHBAUOZmFjdG9yeUFkZHJlc3MCC3N0cmluZ0VudHJ5CQDMCAIJARFrU3ludGhldGljQXNzZXRJZAEFC2Jhc2VBc3NldElkCQDMCAIJAQ9hc3NldElkVG9TdHJpbmcBBRBzeW50aGV0aWNBc3NldElkBQNuaWwFA25pbAkAzAgCCQD8BwQFDmZhY3RvcnlBZGRyZXNzAgtzdHJpbmdFbnRyeQkAzAgCCQEMa0Jhc2VBc3NldElkAQUQc3ludGhldGljQXNzZXRJZAkAzAgCCQEPYXNzZXRJZFRvU3RyaW5nAQULYmFzZUFzc2V0SWQFA25pbAUDbmlsBQNuaWwJAJQKAgUDbmlsBQtpbnZvY2F0aW9ucwkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpAQpkb1NodXRkb3duAg9jYWxsZXJQdWJsaWNLZXkEYXJncwQGY2hlY2tzCQDMCAIJAQttdXN0RmFjdG9yeQEIBQFpBmNhbGxlcgkAzAgCCQEJbXVzdEFkbWluAQUPY2FsbGVyUHVibGljS2V5BQNuaWwDCQAAAgUGY2hlY2tzBQZjaGVja3MEC2ludm9jYXRpb25zCQDMCAIJAPwHBAUOZmFjdG9yeUFkZHJlc3MCDGJvb2xlYW5FbnRyeQkAzAgCBQlrU2h1dGRvd24JAMwIAgYFA25pbAUDbmlsBQNuaWwJAJQKAgUDbmlsBQtpbnZvY2F0aW9ucwkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgECdHgBBnZlcmlmeQADAwkBCWlzRGVmaW5lZAEFFGZhY3RvcnlBZGRyZXNzT3B0aW9uCQEJaXNEZWZpbmVkAQkAnQgCBQ5mYWN0b3J5QWRkcmVzcwUJa011bHRpc2lnBwQHJG1hdGNoMAkAnQgCBQ5mYWN0b3J5QWRkcmVzcwUJa011bHRpc2lnAwkAAQIFByRtYXRjaDACBlN0cmluZwQIbXVsdGlzaWcFByRtYXRjaDAECXN0YXR1c0tleQkBB2tTdGF0dXMCCQClCAEFBHRoaXMJANgEAQgFAnR4AmlkBAZzdGF0dXMJAQt2YWx1ZU9yRWxzZQIJAJsIAgkBEUBleHRyTmF0aXZlKDEwNjIpAQUIbXVsdGlzaWcFCXN0YXR1c0tleQcFBnN0YXR1cwcJAPQDAwgFAnR4CWJvZHlCeXRlcwkAkQMCCAUCdHgGcHJvb2ZzAAAIBQJ0eA9zZW5kZXJQdWJsaWNLZXkQm8b/", "height": 3106994, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: 59XkgwYmq5mHKfEiwAkDae3jNdFQgF8gfUfxuAgAXJf8 Next: CD5g85vYA2m5vvcK62RtTKu1afc3XFYE1UFzpK4KHEit Diff:
OldNewDifferences
2020 let wavesString = "WAVES"
2121
2222 let queueItemSize = 32
23+
24+let big0 = toBigInt(0)
2325
2426 let kMultisig = "%s__multisig"
2527
5557 func assetIdToString (input) = if ((input == unit))
5658 then wavesString
5759 else toBase58String(value(input))
60+
61+
62+func getAssetInfoOrFail (assetId) = valueOrErrorMessage(assetInfo(assetId), wrapErr("invalid asset info"))
63+
64+
65+func getAssetDecimalsOrFail (assetId) = match assetId {
66+ case _: Unit =>
67+ wavesDecimals
68+ case assetId: ByteVector =>
69+ getAssetInfoOrFail(assetId).decimals
70+ case _ =>
71+ throw("Match error")
72+}
73+
74+
75+func pow10 (n) = pow(10, 0, n, 0, 0, DOWN)
76+
77+
78+func pow10Decimals (assetId) = pow10(getAssetDecimalsOrFail(assetId))
5879
5980
6081 let kFactoryAddress = "%s__factoryAddress"
202223 }
203224
204225
205-func calcTotalCredit (creditA,creditB,currentPrice) = ((creditA * currentPrice) + creditB)
226+func calcTotalCredit (creditA,creditB,currentPrice) = (fraction(creditA, currentPrice, mult18BigInt) + creditB)
206227
207228
208-func calcTotalBalance (balanceA,balanceB,currentPrice) = ((balanceA * currentPrice) + balanceB)
229+func calcTotalBalance (balanceA,balanceB,currentPrice) = (fraction(balanceA, currentPrice, mult18BigInt) + balanceB)
209230
210231
211232 func calcPnl (totalBalance,totalCredit) = (totalBalance - totalCredit)
212233
213234
214-func calcCreditAvailable (deposit,leverage,totalCredit) = ((deposit * leverage) - totalCredit)
235+func calcCreditAvailable (deposit,leverage,totalCredit) = (fraction(deposit, leverage, mult18BigInt) - totalCredit)
215236
216237
217-func calcRealInCredit (credit,balance) = if ((credit > 0))
238+func calcRealInCredit (credit,balance) = if ((credit > big0))
218239 then (credit - balance)
219- else 0
240+ else big0
220241
221242
222-func calcFree (credit,balance) = if ((credit > 0))
243+func calcFree (credit,balance) = if ((credit > big0))
223244 then (balance - credit)
224- else 0
245+ else big0
225246
226247
227-func calcShortPrice (free,realInCredit) = if ((realInCredit > 0))
228- then max([0, (free / realInCredit)])
229- else 0
248+func calcShortPrice (free,realInCredit) = if ((realInCredit > big0))
249+ then max([big0, fraction(free, mult18BigInt, realInCredit)])
250+ else big0
230251
231252
232-func calcLongPrice (free,realInCredit) = if ((realInCredit > 0))
233- then max([0, (realInCredit / free)])
234- else 0
253+func calcLongPrice (free,realInCredit) = if ((realInCredit > big0))
254+ then max([big0, fraction(realInCredit, mult18BigInt, free)])
255+ else big0
235256
236257
237-func calcStartMargin (realInCreditA,realInCreditB,currentPrice,settingsMargin) = (((realInCreditA * currentPrice) + realInCreditB) * settingsMargin)
258+func calcStartMargin (realInCreditA,realInCreditB,currentPrice,settingsMargin) = fraction((fraction(realInCreditA, currentPrice, mult18BigInt) + realInCreditB), settingsMargin, mult18BigInt)
238259
239260
240-func calcMarginSupply (settingsMarginSupply,settingsMargin,startMargin) = ((settingsMarginSupply / settingsMargin) * startMargin)
261+func calcMarginSupply (settingsMarginSupply,settingsMargin,startMargin) = fraction(settingsMarginSupply, startMargin, settingsMargin)
241262
242263
243264 func calcLiquidationPrice (deposit,marginSupply,realInCreditA,realInCreditB,shortPrice,longPrice) = {
298319 else throwErr(("accounts limit is " + toString(accountsLimit())))]
299320 if ((checks == checks))
300321 then {
301- let $t01000311359 = if ((size(accountsQueue()) == 0))
322+ let $t01074712103 = if ((size(accountsQueue()) == 0))
302323 then $Tuple2([ScriptTransfer(factoryAddress, rewardAmount(), unit)], [invoke(factoryAddress, "integerEntry", [kRequestStatus(requestId), REQUEST_STATUS_EMPTY], nil), invoke(factoryAddress, "binaryEntry", [kRequestsQueue(), (requestsQueue() + requestId)], nil)])
303324 else {
304325 let accountPublicKey = take(accountsQueue(), queueItemSize)
306327 let creatorAddress = addressFromPublicKey(valueOrErrorMessage(getBinary(factoryAddress, kAccountCreatorPublicKey(accountAddress)), wrapErr("invalid creator public key")))
307328 $Tuple2([ScriptTransfer(creatorAddress, rewardAmount(), unit)], [invoke(factoryAddress, "binaryEntry", [kAccountsQueue(), drop(accountsQueue(), queueItemSize)], nil), invoke(factoryAddress, "integerEntry", [kRequestStatus(requestId), REQUEST_STATUS_READY], nil), invoke(factoryAddress, "binaryEntry", [kRequestIdToAccountPublicKey(requestId), accountPublicKey], nil), invoke(factoryAddress, "stringEntry", [kAccountAddressToRequestId(accountAddress), toBase58String(requestId)], nil)])
308329 }
309- let actions = $t01000311359._1
310- let factoryActions = $t01000311359._2
330+ let actions = $t01074712103._1
331+ let factoryActions = $t01074712103._2
311332 $Tuple2(actions, (factoryActions ++ [invoke(factoryAddress, "binaryEntry", [kRequestOwnerPublicKey(requestId), callerPublicKey], nil), invoke(factoryAddress, "binaryEntry", [kRequestsByOwner(userAddress), (requestsByOwner(userAddress) + requestId)], nil), invoke(factoryAddress, "stringEntry", [kRequestAmountAssetId(requestId), amountAssetIdStr], nil), invoke(factoryAddress, "stringEntry", [kRequestPriceAssetId(requestId), priceAssetIdStr], nil)]))
312333 }
313334 else throw("Strict value is not equal to itself.")
340361 else throwErr("invalid script")]
341362 if ((checks == checks))
342363 then {
343- let $t01261413616 = if ((size(requestsQueue()) == 0))
364+ let $t01335814360 = if ((size(requestsQueue()) == 0))
344365 then $Tuple2(nil, [invoke(factoryAddress, "binaryEntry", [kAccountsQueue(), (accountsQueue() + accountPublicKey)], nil)])
345366 else {
346367 let requestId = take(requestsQueue(), queueItemSize)
347368 $Tuple2(nil, [invoke(factoryAddress, "integerEntry", [kRequestStatus(requestId), REQUEST_STATUS_READY], nil), invoke(factoryAddress, "binaryEntry", [kRequestIdToAccountPublicKey(requestId), accountPublicKey], nil), invoke(factoryAddress, "binaryEntry", [kRequestsQueue(), drop(requestsQueue(), queueItemSize)], nil), invoke(factoryAddress, "stringEntry", [kAccountAddressToRequestId(accountAddress), toBase58String(requestId)], nil), invoke(factoryAddress, "transferWaves", [creatorAddress.bytes, rewardAmount()], nil)])
348369 }
349- let actions = $t01261413616._1
350- let factoryActions = $t01261413616._2
370+ let actions = $t01335814360._1
371+ let factoryActions = $t01335814360._2
351372 $Tuple2(actions, (factoryActions ++ [invoke(factoryAddress, "binaryEntry", [kAccountCreatorPublicKey(accountAddress), creatorPublicKey], nil)]))
352373 }
353374 else throw("Strict value is not equal to itself.")
408429 let accountAddress = valueOrErrorMessage(addressFromString(args[0]), wrapErr("invalid account address"))
409430 let assetId = parseAssetId(args[1])
410431 let amountRaw = parseInt(args[2])
411- let deposited = valueOrElse(depositedOption(accountAddress), 0)
412- let $t01575615833 = getAssetsByAccountAddress(accountAddress)
413- let amountAssetId = $t01575615833._1
414- let priceAssetId = $t01575615833._2
415- let currentPrice = getCurrentPrice(amountAssetId)
416- let creditA = valueOrElse(getInteger(factoryAddress, kCredit(accountAddress, amountAssetId)), 0)
417- let creditB = valueOrElse(getInteger(factoryAddress, kCredit(accountAddress, priceAssetId)), 0)
432+ let $t01643516512 = getAssetsByAccountAddress(accountAddress)
433+ let amountAssetId = $t01643516512._1
434+ let priceAssetId = $t01643516512._2
435+ let deposited = toX18(valueOrElse(depositedOption(accountAddress), 0), pow10Decimals(priceAssetId))
436+ let currentPrice = toX18(getCurrentPrice(amountAssetId), pow10Decimals(usdtAssetId))
437+ let creditA = toX18(valueOrElse(getInteger(factoryAddress, kCredit(accountAddress, amountAssetId)), 0), pow10Decimals(amountAssetId))
438+ let creditB = toX18(valueOrElse(getInteger(factoryAddress, kCredit(accountAddress, priceAssetId)), 0), pow10Decimals(priceAssetId))
418439 let totalCredit = calcTotalCredit(creditA, creditB, currentPrice)
419440 let leverageDefault = 3
420- let leverage = valueOrElse(getInteger(factoryAddress, kLeverage(accountAddress)), leverageDefault)
441+ let leverage = toX18(valueOrElse(getInteger(factoryAddress, kLeverage(accountAddress)), leverageDefault), 1)
421442 let creditAvailable = calcCreditAvailable(deposited, leverage, totalCredit)
422- $Tuple2(nil, [creditAvailable])
443+ $Tuple2(nil, [fromX18(creditAvailable, pow10Decimals(priceAssetId))])
423444 }
424445 else throw("Strict value is not equal to itself.")
425446 }
Full:
OldNewDifferences
11 {-# STDLIB_VERSION 7 #-}
22 {-# SCRIPT_TYPE ACCOUNT #-}
33 {-# CONTENT_TYPE DAPP #-}
44 let separator = "__"
55
66 let chainId = take(drop(this.bytes, 1), 1)
77
88 let chainIdW = base58'2W'
99
1010 let contractFilename = "futures_calculator.ride"
1111
1212 let mult8 = 100000000
1313
1414 let mult18BigInt = toBigInt(1000000000000000000)
1515
1616 let wavesDecimals = 8
1717
1818 let usdtDecimals = 6
1919
2020 let wavesString = "WAVES"
2121
2222 let queueItemSize = 32
23+
24+let big0 = toBigInt(0)
2325
2426 let kMultisig = "%s__multisig"
2527
2628 func kStatus (dapp,txId) = makeString(["%s__status", dapp, txId], separator)
2729
2830
2931 let kShutdown = "%s__shutdown"
3032
3133 let kPublicKeys = "%s__publicKeys"
3234
3335 let kMatcherPublicKey = "%s__matcherPublicKey"
3436
3537 func toX18 (origVal,origScaleMult) = fraction(toBigInt(origVal), mult18BigInt, toBigInt(origScaleMult))
3638
3739
3840 func fromX18 (val,resultScaleMult) = toInt(fraction(val, toBigInt(resultScaleMult), mult18BigInt))
3941
4042
4143 func validateAddress (address) = isDefined(addressFromString(address))
4244
4345
4446 func wrapErr (s) = ((contractFilename + ": ") + s)
4547
4648
4749 func throwErr (s) = throw(wrapErr(s))
4850
4951
5052 func parseAssetId (input) = if ((input == wavesString))
5153 then unit
5254 else fromBase58String(input)
5355
5456
5557 func assetIdToString (input) = if ((input == unit))
5658 then wavesString
5759 else toBase58String(value(input))
60+
61+
62+func getAssetInfoOrFail (assetId) = valueOrErrorMessage(assetInfo(assetId), wrapErr("invalid asset info"))
63+
64+
65+func getAssetDecimalsOrFail (assetId) = match assetId {
66+ case _: Unit =>
67+ wavesDecimals
68+ case assetId: ByteVector =>
69+ getAssetInfoOrFail(assetId).decimals
70+ case _ =>
71+ throw("Match error")
72+}
73+
74+
75+func pow10 (n) = pow(10, 0, n, 0, 0, DOWN)
76+
77+
78+func pow10Decimals (assetId) = pow10(getAssetDecimalsOrFail(assetId))
5879
5980
6081 let kFactoryAddress = "%s__factoryAddress"
6182
6283 let factoryAddressOption = match getString(this, kFactoryAddress) {
6384 case s: String =>
6485 addressFromString(s)
6586 case _: Unit =>
6687 unit
6788 case _ =>
6889 throw("Match error")
6990 }
7091
7192 let factoryAddress = valueOrErrorMessage(factoryAddressOption, wrapErr("invalid factory address"))
7293
7394 let kUsdtAssetId = "%s__usdtAssetId"
7495
7596 let usdtAssetIdOption = match getString(this, kUsdtAssetId) {
7697 case s: String =>
7798 parseAssetId(s)
7899 case _: Unit =>
79100 unit
80101 case _ =>
81102 throw("Match error")
82103 }
83104
84105 let usdtAssetId = valueOrErrorMessage(usdtAssetIdOption, wrapErr("invalid usdt asset id"))
85106
86107 let kPricesAddress = "%s__calculatorAddress"
87108
88109 let shutdown = valueOrElse(getBoolean(factoryAddress, kShutdown), false)
89110
90111 func mustAddress (caller,address) = if ((caller == address))
91112 then true
92113 else throwErr("permission denied")
93114
94115
95116 func mustThis (caller) = mustAddress(caller, this)
96117
97118
98119 func mustFactory (caller) = mustAddress(caller, factoryAddress)
99120
100121
101122 func mustAdmin (callerPublicKey) = {
102123 let multisig = addressFromStringValue(getStringValue(factoryAddress, kMultisig))
103124 let publicKeysList = split(getStringValue(multisig, kPublicKeys), separator)
104125 if (containsElement(publicKeysList, toBase58String(callerPublicKey)))
105126 then true
106127 else throwErr("not allowed")
107128 }
108129
109130
110131 let kAccountScript = "%s__accountScript"
111132
112133 func accountScript () = valueOrErrorMessage(getBinary(factoryAddress, kAccountScript), wrapErr("account script is not set"))
113134
114135
115136 let kRewardAmount = "%s__rewardAmount"
116137
117138 func rewardAmount () = valueOrErrorMessage(getInteger(factoryAddress, kRewardAmount), wrapErr("reward amount is not set"))
118139
119140
120141 let kAccountsLimit = "%s__accountsLimit"
121142
122143 let accountsLimitDefault = 20
123144
124145 func accountsLimit () = valueOrElse(getInteger(factoryAddress, kAccountsLimit), accountsLimitDefault)
125146
126147
127148 func kDeposited (accountAddress) = makeString(["%s%s", "deposited", toString(accountAddress)], separator)
128149
129150
130151 func depositedOption (accountAddress) = getInteger(factoryAddress, kDeposited(accountAddress))
131152
132153
133154 func kCredit (accountAddress,assetId) = makeString(["%s%s%s", "credit", toString(accountAddress), assetIdToString(assetId)], separator)
134155
135156
136157 func kLeverage (accountAddress) = makeString(["%s%s", "leverage", toString(accountAddress)], separator)
137158
138159
139160 func kSyntheticAssetId (baseAssetId) = makeString(["%s%s", "syntheticAssetId", assetIdToString(baseAssetId)], separator)
140161
141162
142163 func kBaseAssetId (syntheticAssetId) = makeString(["%s%s", "baseAssetId", assetIdToString(syntheticAssetId)], separator)
143164
144165
145166 let REQUEST_STATUS_EMPTY = 0
146167
147168 let REQUEST_STATUS_READY = 1
148169
149170 func kRequestStatus (requestId) = makeString(["%s%s", toBase58String(requestId), "status"], separator)
150171
151172
152173 func kAccountCreatorPublicKey (accountAddress) = makeString(["%s%s", toString(accountAddress), "creatorPublicKey"], separator)
153174
154175
155176 func kRequestOwnerPublicKey (requestId) = makeString(["%s%s", toBase58String(requestId), "ownerPublicKey"], separator)
156177
157178
158179 func kRequestAmountAssetId (requestId) = makeString(["%s%s", toBase58String(requestId), "amountAssetId"], separator)
159180
160181
161182 func kRequestPriceAssetId (requestId) = makeString(["%s%s", toBase58String(requestId), "priceAssetId"], separator)
162183
163184
164185 func kRequestIdToAccountPublicKey (requestId) = makeString(["%s%s", toBase58String(requestId), "requestIdToAccountPublicKey"], separator)
165186
166187
167188 func kAccountAddressToRequestId (accountAddress) = makeString(["%s%s", toString(accountAddress), "accountAddressToRequestId"], separator)
168189
169190
170191 func kRequestsQueue () = makeString(["%s", "requestsQueue"], separator)
171192
172193
173194 func requestsQueue () = valueOrElse(getBinary(factoryAddress, kRequestsQueue()), base58'')
174195
175196
176197 func kAccountsQueue () = makeString(["%s", "accountsQueue"], separator)
177198
178199
179200 func accountsQueue () = valueOrElse(getBinary(factoryAddress, kAccountsQueue()), base58'')
180201
181202
182203 func kRequestsByOwner (ownerAddress) = makeString(["%s%s", "requests", toString(ownerAddress)], separator)
183204
184205
185206 func requestsByOwner (ownerAddress) = valueOrElse(getBinary(factoryAddress, kRequestsByOwner(ownerAddress)), base58'')
186207
187208
188209 func kPairAllowed (amountAssetId,priceAssetId) = makeString(["%s%s%s", assetIdToString(amountAssetId), assetIdToString(priceAssetId), "pairAllowed"], separator)
189210
190211
191212 func pairAllowed (amountAssetId,priceAssetId) = valueOrElse(getBoolean(factoryAddress, kPairAllowed(amountAssetId, priceAssetId)), false)
192213
193214
194215 func kPrice (assetId) = makeString(["%s", assetIdToString(assetId)], separator)
195216
196217
197218 func getCurrentPrice (assetId) = {
198219 let matcherPublicKey = fromBase58String(valueOrErrorMessage(getString(factoryAddress, kMatcherPublicKey), wrapErr("invalid matcher public key")))
199220 let matcherAddress = addressFromPublicKey(matcherPublicKey)
200221 let price = valueOrErrorMessage(getInteger(matcherAddress, kPrice(assetId)), wrapErr(("invalid price, assetId = " + assetIdToString(assetId))))
201222 price
202223 }
203224
204225
205-func calcTotalCredit (creditA,creditB,currentPrice) = ((creditA * currentPrice) + creditB)
226+func calcTotalCredit (creditA,creditB,currentPrice) = (fraction(creditA, currentPrice, mult18BigInt) + creditB)
206227
207228
208-func calcTotalBalance (balanceA,balanceB,currentPrice) = ((balanceA * currentPrice) + balanceB)
229+func calcTotalBalance (balanceA,balanceB,currentPrice) = (fraction(balanceA, currentPrice, mult18BigInt) + balanceB)
209230
210231
211232 func calcPnl (totalBalance,totalCredit) = (totalBalance - totalCredit)
212233
213234
214-func calcCreditAvailable (deposit,leverage,totalCredit) = ((deposit * leverage) - totalCredit)
235+func calcCreditAvailable (deposit,leverage,totalCredit) = (fraction(deposit, leverage, mult18BigInt) - totalCredit)
215236
216237
217-func calcRealInCredit (credit,balance) = if ((credit > 0))
238+func calcRealInCredit (credit,balance) = if ((credit > big0))
218239 then (credit - balance)
219- else 0
240+ else big0
220241
221242
222-func calcFree (credit,balance) = if ((credit > 0))
243+func calcFree (credit,balance) = if ((credit > big0))
223244 then (balance - credit)
224- else 0
245+ else big0
225246
226247
227-func calcShortPrice (free,realInCredit) = if ((realInCredit > 0))
228- then max([0, (free / realInCredit)])
229- else 0
248+func calcShortPrice (free,realInCredit) = if ((realInCredit > big0))
249+ then max([big0, fraction(free, mult18BigInt, realInCredit)])
250+ else big0
230251
231252
232-func calcLongPrice (free,realInCredit) = if ((realInCredit > 0))
233- then max([0, (realInCredit / free)])
234- else 0
253+func calcLongPrice (free,realInCredit) = if ((realInCredit > big0))
254+ then max([big0, fraction(realInCredit, mult18BigInt, free)])
255+ else big0
235256
236257
237-func calcStartMargin (realInCreditA,realInCreditB,currentPrice,settingsMargin) = (((realInCreditA * currentPrice) + realInCreditB) * settingsMargin)
258+func calcStartMargin (realInCreditA,realInCreditB,currentPrice,settingsMargin) = fraction((fraction(realInCreditA, currentPrice, mult18BigInt) + realInCreditB), settingsMargin, mult18BigInt)
238259
239260
240-func calcMarginSupply (settingsMarginSupply,settingsMargin,startMargin) = ((settingsMarginSupply / settingsMargin) * startMargin)
261+func calcMarginSupply (settingsMarginSupply,settingsMargin,startMargin) = fraction(settingsMarginSupply, startMargin, settingsMargin)
241262
242263
243264 func calcLiquidationPrice (deposit,marginSupply,realInCreditA,realInCreditB,shortPrice,longPrice) = {
244265 let liquidationPriceA = if ((realInCreditA > 0))
245266 then (((deposit - marginSupply) / realInCreditA) + shortPrice)
246267 else 0
247268 let liquidationPriceB = if ((realInCreditB > 0))
248269 then (longPrice - ((deposit - marginSupply) / (realInCreditA / longPrice)))
249270 else 0
250271 (liquidationPriceA + liquidationPriceB)
251272 }
252273
253274
254275 func getAssetsByAccountAddress (accountAddress) = {
255276 let requestId = fromBase58String(valueOrErrorMessage(getString(factoryAddress, kAccountAddressToRequestId(accountAddress)), wrapErr("invalid account address")))
256277 let amountAssetId = parseAssetId(valueOrErrorMessage(getString(factoryAddress, kRequestAmountAssetId(requestId)), wrapErr("invalid amount asset id")))
257278 let priceAssetId = parseAssetId(valueOrErrorMessage(getString(factoryAddress, kRequestPriceAssetId(requestId)), wrapErr("invalid amount price id")))
258279 $Tuple2(amountAssetId, priceAssetId)
259280 }
260281
261282
262283 @Callable(i)
263284 func init (factoryAddressStr) = {
264285 let checkCaller = mustThis(i.caller)
265286 if ((checkCaller == checkCaller))
266287 then $Tuple2([StringEntry(kFactoryAddress, factoryAddressStr)], unit)
267288 else throw("Strict value is not equal to itself.")
268289 }
269290
270291
271292
272293 @Callable(i)
273294 func requestAccount (callerPublicKey,args) = {
274295 let ckecks = [if (!(shutdown))
275296 then true
276297 else throwErr("not allowed"), mustFactory(i.caller)]
277298 if ((ckecks == ckecks))
278299 then {
279300 let amountAssetIdStr = args[0]
280301 let priceAssetIdStr = args[1]
281302 let userAddress = addressFromPublicKey(callerPublicKey)
282303 let requestId = sha256(((userAddress.bytes + fromBase58String(amountAssetIdStr)) + fromBase58String(priceAssetIdStr)))
283304 let amountAssetId = parseAssetId(amountAssetIdStr)
284305 let priceAssetId = parseAssetId(priceAssetIdStr)
285306 let userRequestsNumber = (size(kRequestsByOwner(userAddress)) / queueItemSize)
286307 let checks = [if ((size(i.payments) == 1))
287308 then true
288309 else throwErr("1 payment is required"), if ((i.payments[0].assetId == unit))
289310 then true
290311 else throwErr("invalid asset"), if ((i.payments[0].amount == rewardAmount()))
291312 then true
292313 else throwErr("invalid amount"), if (pairAllowed(amountAssetId, priceAssetId))
293314 then true
294315 else throwErr("pair is not allowed"), if ((getInteger(factoryAddress, kRequestStatus(requestId)) == unit))
295316 then true
296317 else throwErr("account is already exists"), if ((accountsLimit() > userRequestsNumber))
297318 then true
298319 else throwErr(("accounts limit is " + toString(accountsLimit())))]
299320 if ((checks == checks))
300321 then {
301- let $t01000311359 = if ((size(accountsQueue()) == 0))
322+ let $t01074712103 = if ((size(accountsQueue()) == 0))
302323 then $Tuple2([ScriptTransfer(factoryAddress, rewardAmount(), unit)], [invoke(factoryAddress, "integerEntry", [kRequestStatus(requestId), REQUEST_STATUS_EMPTY], nil), invoke(factoryAddress, "binaryEntry", [kRequestsQueue(), (requestsQueue() + requestId)], nil)])
303324 else {
304325 let accountPublicKey = take(accountsQueue(), queueItemSize)
305326 let accountAddress = addressFromPublicKey(accountPublicKey)
306327 let creatorAddress = addressFromPublicKey(valueOrErrorMessage(getBinary(factoryAddress, kAccountCreatorPublicKey(accountAddress)), wrapErr("invalid creator public key")))
307328 $Tuple2([ScriptTransfer(creatorAddress, rewardAmount(), unit)], [invoke(factoryAddress, "binaryEntry", [kAccountsQueue(), drop(accountsQueue(), queueItemSize)], nil), invoke(factoryAddress, "integerEntry", [kRequestStatus(requestId), REQUEST_STATUS_READY], nil), invoke(factoryAddress, "binaryEntry", [kRequestIdToAccountPublicKey(requestId), accountPublicKey], nil), invoke(factoryAddress, "stringEntry", [kAccountAddressToRequestId(accountAddress), toBase58String(requestId)], nil)])
308329 }
309- let actions = $t01000311359._1
310- let factoryActions = $t01000311359._2
330+ let actions = $t01074712103._1
331+ let factoryActions = $t01074712103._2
311332 $Tuple2(actions, (factoryActions ++ [invoke(factoryAddress, "binaryEntry", [kRequestOwnerPublicKey(requestId), callerPublicKey], nil), invoke(factoryAddress, "binaryEntry", [kRequestsByOwner(userAddress), (requestsByOwner(userAddress) + requestId)], nil), invoke(factoryAddress, "stringEntry", [kRequestAmountAssetId(requestId), amountAssetIdStr], nil), invoke(factoryAddress, "stringEntry", [kRequestPriceAssetId(requestId), priceAssetIdStr], nil)]))
312333 }
313334 else throw("Strict value is not equal to itself.")
314335 }
315336 else throw("Strict value is not equal to itself.")
316337 }
317338
318339
319340
320341 @Callable(i)
321342 func addAccount (callerPublicKey,args) = {
322343 let ckecks = [if (!(shutdown))
323344 then true
324345 else throwErr("not allowed"), mustFactory(i.caller)]
325346 if ((ckecks == ckecks))
326347 then {
327348 let creatorPublicKey = fromBase58String(args[0])
328349 let accountPublicKey = callerPublicKey
329350 let accountAddress = addressFromPublicKey(callerPublicKey)
330351 let creatorAddress = addressFromPublicKey(creatorPublicKey)
331352 let checks = [if ((getBinary(factoryAddress, kAccountCreatorPublicKey(accountAddress)) == unit))
332353 then true
333354 else throwErr("account is already exists"), if ( match scriptHash(accountAddress) {
334355 case b: ByteVector =>
335356 (b == blake2b256_32Kb(accountScript()))
336357 case _ =>
337358 false
338359 })
339360 then true
340361 else throwErr("invalid script")]
341362 if ((checks == checks))
342363 then {
343- let $t01261413616 = if ((size(requestsQueue()) == 0))
364+ let $t01335814360 = if ((size(requestsQueue()) == 0))
344365 then $Tuple2(nil, [invoke(factoryAddress, "binaryEntry", [kAccountsQueue(), (accountsQueue() + accountPublicKey)], nil)])
345366 else {
346367 let requestId = take(requestsQueue(), queueItemSize)
347368 $Tuple2(nil, [invoke(factoryAddress, "integerEntry", [kRequestStatus(requestId), REQUEST_STATUS_READY], nil), invoke(factoryAddress, "binaryEntry", [kRequestIdToAccountPublicKey(requestId), accountPublicKey], nil), invoke(factoryAddress, "binaryEntry", [kRequestsQueue(), drop(requestsQueue(), queueItemSize)], nil), invoke(factoryAddress, "stringEntry", [kAccountAddressToRequestId(accountAddress), toBase58String(requestId)], nil), invoke(factoryAddress, "transferWaves", [creatorAddress.bytes, rewardAmount()], nil)])
348369 }
349- let actions = $t01261413616._1
350- let factoryActions = $t01261413616._2
370+ let actions = $t01335814360._1
371+ let factoryActions = $t01335814360._2
351372 $Tuple2(actions, (factoryActions ++ [invoke(factoryAddress, "binaryEntry", [kAccountCreatorPublicKey(accountAddress), creatorPublicKey], nil)]))
352373 }
353374 else throw("Strict value is not equal to itself.")
354375 }
355376 else throw("Strict value is not equal to itself.")
356377 }
357378
358379
359380
360381 @Callable(i)
361382 func deposit (callerPublicKey,args) = {
362383 let payment = i.payments[0]
363384 let ckecks = [if (!(shutdown))
364385 then true
365386 else throwErr("not allowed"), mustFactory(i.caller), if ((size(i.payments) == 1))
366387 then true
367388 else throwErr("1 payment is required"), if ((payment.assetId == usdtAssetId))
368389 then true
369390 else throwErr("invalid asset")]
370391 if ((ckecks == ckecks))
371392 then {
372393 let accountAddress = valueOrErrorMessage(addressFromString(args[0]), wrapErr("invalid account address"))
373394 let actions = [ScriptTransfer(accountAddress, payment.amount, payment.assetId)]
374395 let factoryActions = [invoke(factoryAddress, "integerEntry", [kDeposited(accountAddress), (valueOrElse(depositedOption(accountAddress), 0) + payment.amount)], nil)]
375396 $Tuple2(actions, factoryActions)
376397 }
377398 else throw("Strict value is not equal to itself.")
378399 }
379400
380401
381402
382403 @Callable(i)
383404 func withdraw (callerPublicKey,args) = {
384405 let ckecks = [if (!(shutdown))
385406 then true
386407 else throwErr("not allowed"), mustFactory(i.caller)]
387408 if ((ckecks == ckecks))
388409 then {
389410 let userAddress = addressFromPublicKey(callerPublicKey)
390411 let accountAddress = valueOrErrorMessage(addressFromString(args[0]), wrapErr("invalid account address"))
391412 let amount = valueOrErrorMessage(parseInt(args[1]), wrapErr("invalid amount"))
392413 let assetId = parseAssetId(args[2])
393414 let invocations = [invoke(accountAddress, "transferAsset", [userAddress.bytes, amount, assetId], nil)]
394415 $Tuple2(nil, invocations)
395416 }
396417 else throw("Strict value is not equal to itself.")
397418 }
398419
399420
400421
401422 @Callable(i)
402423 func borrow (callerPublicKey,args) = {
403424 let ckecks = [if (!(shutdown))
404425 then true
405426 else throwErr("not allowed"), mustFactory(i.caller)]
406427 if ((ckecks == ckecks))
407428 then {
408429 let accountAddress = valueOrErrorMessage(addressFromString(args[0]), wrapErr("invalid account address"))
409430 let assetId = parseAssetId(args[1])
410431 let amountRaw = parseInt(args[2])
411- let deposited = valueOrElse(depositedOption(accountAddress), 0)
412- let $t01575615833 = getAssetsByAccountAddress(accountAddress)
413- let amountAssetId = $t01575615833._1
414- let priceAssetId = $t01575615833._2
415- let currentPrice = getCurrentPrice(amountAssetId)
416- let creditA = valueOrElse(getInteger(factoryAddress, kCredit(accountAddress, amountAssetId)), 0)
417- let creditB = valueOrElse(getInteger(factoryAddress, kCredit(accountAddress, priceAssetId)), 0)
432+ let $t01643516512 = getAssetsByAccountAddress(accountAddress)
433+ let amountAssetId = $t01643516512._1
434+ let priceAssetId = $t01643516512._2
435+ let deposited = toX18(valueOrElse(depositedOption(accountAddress), 0), pow10Decimals(priceAssetId))
436+ let currentPrice = toX18(getCurrentPrice(amountAssetId), pow10Decimals(usdtAssetId))
437+ let creditA = toX18(valueOrElse(getInteger(factoryAddress, kCredit(accountAddress, amountAssetId)), 0), pow10Decimals(amountAssetId))
438+ let creditB = toX18(valueOrElse(getInteger(factoryAddress, kCredit(accountAddress, priceAssetId)), 0), pow10Decimals(priceAssetId))
418439 let totalCredit = calcTotalCredit(creditA, creditB, currentPrice)
419440 let leverageDefault = 3
420- let leverage = valueOrElse(getInteger(factoryAddress, kLeverage(accountAddress)), leverageDefault)
441+ let leverage = toX18(valueOrElse(getInteger(factoryAddress, kLeverage(accountAddress)), leverageDefault), 1)
421442 let creditAvailable = calcCreditAvailable(deposited, leverage, totalCredit)
422- $Tuple2(nil, [creditAvailable])
443+ $Tuple2(nil, [fromX18(creditAvailable, pow10Decimals(priceAssetId))])
423444 }
424445 else throw("Strict value is not equal to itself.")
425446 }
426447
427448
428449
429450 @Callable(i)
430451 func repay (callerPublicKey,args) = {
431452 let ckecks = [if (!(shutdown))
432453 then true
433454 else throwErr("not allowed"), mustFactory(i.caller)]
434455 if ((ckecks == ckecks))
435456 then $Tuple2(nil, unit)
436457 else throw("Strict value is not equal to itself.")
437458 }
438459
439460
440461
441462 @Callable(i)
442463 func setPairAllowance (callerPublicKey,args) = {
443464 let ckecks = [if (!(shutdown))
444465 then true
445466 else throwErr("not allowed"), mustFactory(i.caller), mustAdmin(callerPublicKey)]
446467 if ((ckecks == ckecks))
447468 then {
448469 let amountAssetIdStr = args[0]
449470 let priceAssetIdStr = args[1]
450471 let allowStr = args[2]
451472 let amountAssetId = parseAssetId(amountAssetIdStr)
452473 let priceAssetId = parseAssetId(priceAssetIdStr)
453474 let allow = (allowStr == "true")
454475 let invocations = [invoke(factoryAddress, "booleanEntry", [kPairAllowed(amountAssetId, priceAssetId), allow], nil)]
455476 $Tuple2(nil, invocations)
456477 }
457478 else throw("Strict value is not equal to itself.")
458479 }
459480
460481
461482
462483 @Callable(i)
463484 func addSyntheticAsset (callerPublicKey,args) = {
464485 let baseAssetIdStr = args[0]
465486 let baseAssetId = parseAssetId(baseAssetIdStr)
466487 let syntheticAssetId = i.payments[0].assetId
467488 let ckecks = [if (!(shutdown))
468489 then true
469490 else throwErr("not allowed"), mustFactory(i.caller), mustAdmin(callerPublicKey), if ((getString(factoryAddress, kSyntheticAssetId(baseAssetId)) == unit))
470491 then true
471492 else throwErr("invalid base asset"), if ((size(i.payments) == 1))
472493 then true
473494 else throwErr("invalid payments"), if ((getString(factoryAddress, kBaseAssetId(syntheticAssetId)) == unit))
474495 then true
475496 else throwErr("invalid synthetic asset")]
476497 if ((ckecks == ckecks))
477498 then {
478499 let invocations = [invoke(factoryAddress, "stringEntry", [kSyntheticAssetId(baseAssetId), assetIdToString(syntheticAssetId)], nil), invoke(factoryAddress, "stringEntry", [kBaseAssetId(syntheticAssetId), assetIdToString(baseAssetId)], nil)]
479500 $Tuple2(nil, invocations)
480501 }
481502 else throw("Strict value is not equal to itself.")
482503 }
483504
484505
485506
486507 @Callable(i)
487508 func doShutdown (callerPublicKey,args) = {
488509 let checks = [mustFactory(i.caller), mustAdmin(callerPublicKey)]
489510 if ((checks == checks))
490511 then {
491512 let invocations = [invoke(factoryAddress, "booleanEntry", [kShutdown, true], nil)]
492513 $Tuple2(nil, invocations)
493514 }
494515 else throw("Strict value is not equal to itself.")
495516 }
496517
497518
498519 @Verifier(tx)
499520 func verify () = if (if (isDefined(factoryAddressOption))
500521 then isDefined(getString(factoryAddress, kMultisig))
501522 else false)
502523 then match getString(factoryAddress, kMultisig) {
503524 case multisig: String =>
504525 let statusKey = kStatus(toString(this), toBase58String(tx.id))
505526 let status = valueOrElse(getBoolean(addressFromStringValue(multisig), statusKey), false)
506527 status
507528 case _ =>
508529 false
509530 }
510531 else sigVerify(tx.bodyBytes, tx.proofs[0], tx.senderPublicKey)
511532

github/deemru/w8io/3ef1775 
323.46 ms