2024.04.17 09:31 [3066416] smart account 3MptKi7f3jwXjzqhHpvLLzsSpEQdZiwAo5c > SELF 0.00000000 Waves

{ "type": 13, "id": "FnfizKJtJXAhfpiuG6NBbist5MdxsKYrY1SW1YjKT3FZ", "fee": 2400000, "feeAssetId": null, "timestamp": 1713335488627, "version": 2, "chainId": 84, "sender": "3MptKi7f3jwXjzqhHpvLLzsSpEQdZiwAo5c", "senderPublicKey": "44kjsoExo76qSrM51NMhbG8FtdLkcPtyJxEDrwDyT8kz", "proofs": [ "4pMZ4cSkzAH2rNkHe3LVquYR8L3GYFwHhmZypwRXANJwMd8oHKw1bAdJpHzQX2LKiTuFFZ67cjEFJ2fzFSPtVeQK" ], "script": "base64:BgL0JQgCEgkKBwEBAQEBCAESABIECgIICBIDCgEIEgMKARgSBAoCCAgSBAoCCAgiD2dldFN0cmluZ09yRmFpbCIDa2V5IgNTRVAiCEJVRlNDQUxFIgZzY2FsZTgiCHRocm93RXJyIgNtc2ciCGFzU3RyaW5nIgN2YWwiByRtYXRjaDAiBnZhbFN0ciIdY29udmVydFByaWNlQXNzZXRJbnRvSWRvQXNzZXQiEHByaWNlQXNzZXRBbW91bnQiDnByaWNlQXNzZXRNVUxUIgVwcmljZSIJcHJpY2VNVUxUIgxpZG9Bc3NldE1VTFQiD2JQcmljZUFzc2V0TVVMVCINYklkb0Fzc2V0TVVMVCIOYlByaWNlQXNzZXRCVUYiD2JBbW91bnRBc3NldEJVRiIOSWR4Q2ZnSWRvU3RhcnQiEUlkeENmZ0lkb0R1cmF0aW9uIhBJZHhDZmdDbGFpbVN0YXJ0IhNJZHhDZmdDbGFpbUR1cmF0aW9uIgtJZHhDZmdQcmljZSIPSWR4Q2ZnUHJpY2VNdWx0IhBJZHhDZmdJZG9Bc3NldElkIhJJZHhDZmdJZG9Bc3NldE11bHQiEklkeENmZ1ByaWNlQXNzZXRJZCIUSWR4Q2ZnUHJpY2VBc3NldE11bHQiFUlkeENmZ01pbkludmVzdEFtb3VudCINZnJvbWF0Q29uZmlnUyIIaWRvU3RhcnQiC2lkb0R1cmF0aW9uIgpjbGFpbVN0YXJ0Ig1jbGFpbUR1cmF0aW9uIglwcmljZU11bHQiDGlkb0Fzc2V0SWQ1OCIMaWRvQXNzZXRNdWx0Ig5wcmljZUFzc2V0SWQ1OCIOcHJpY2VBc3NldE11bHQiD21pbkludmVzdEFtb3VudCITdG90YWxJZG9Bc3NldFRvU2VsbCIMZnJvbWF0Q29uZmlnIhFJZHhJbnZUb3RhbEFtb3VudCIVSWR4SW52UmVtYWluaW5nQW1vdW50Ih1JZHhJbnZDbGFpbWVkUHJpY2VBc3NldEFtb3VudCIbSWR4SW52Q2xhaW1lZElkb0Fzc2V0QW1vdW50IhdJZHhJbnZMYXN0Q2xhaW1lZEhlaWdodCIPZm9ybWF0SW52ZXN0b3JTIgt0b3RhbEFtb3VudCIPcmVtYWluaW5nQW1vdW50IhdjbGFpbWVkUHJpY2VBc3NldEFtb3VudCIVY2xhaW1lZElkb0Fzc2V0QW1vdW50IhFsYXN0Q2xhaW1lZEhlaWdodCIOZm9ybWF0SW52ZXN0b3IiE2Zvcm1hdEhpc3RvcnlSZWNvcmQiDmlkb0Fzc2V0QW1vdW50IglrZXlDb25maWciC2tleUludmVzdG9yIgt1c2VyQWRkcmVzcyIJa2V5VG90YWxzIhlrZXlPcGVyYXRpb25IaXN0b3J5UmVjb3JkIgR0eXBlIgZ0eElkNTgiFGtleVVTRE5DbGFpbURpc2FibGVkIhVrZXlVU0ROQ2xhaW1FbmRIZWlnaHQiD2tleVBlcmlvZExlbmd0aCIQa2V5Q3VycmVudFBlcmlvZCIUa2V5UGVyaW9kU3RhcnRIZWlnaHQiCXBlcmlvZE51bSISa2V5UGVyaW9kRW5kSGVpZ2h0Ih9rZXlVc2R0UHJpY2VBc3NldEFsbG93YWJsZVJhdGlvIhdrZXlUb3RhbFBlcmlvZEFsbG93YW5jZSIHYXNzZXRJZCIWa2V5VXNlclBlcmlvZEFsbG93YW5jZSIea2V5UGVyaW9kVG90YWxBdmFpbGFibGVUb0NsYWltIh1rZXlQZXJpb2RVc2VyQXZhaWxhYmxlVG9DbGFpbSIba2V5VXNkdFByaWNlQXNzZXRTdGFibGVQb29sIg5rZXlVc2R0QXNzZXRJZCIUa2V5UHJpY2VBc3NldEJhbGFuY2UiB2FkZHJlc3MiGmtleUludmVzdG9yUmVtYWluaW5nQW1vdW50IhdrZXlUb3RhbFJlbWFpbmluZ0Ftb3VudCITa2V5TWFuYWdlclB1YmxpY0tleSIWa2V5TWFuYWdlclZhdWx0QWRkcmVzcyIVa2V5Q2xhaW1DbG9zaW5nSGVpZ2h0IhJjbGFpbUNsb3NpbmdIZWlnaHQiD3JlYWRDb25maWdBcnJheSIjcmVhZFRvdGFsc0FycmF5T3JEZWZhdWx0QnlDdXN0b21LZXkiCWN1c3RvbUtleSIYcmVhZFRvdGFsc0FycmF5T3JEZWZhdWx0IhpyZWFkSW52ZXN0b3JBcnJheU9yRGVmYXVsdCIXcmVhZEludmVzdG9yQXJyYXlPckZhaWwiHGdldE1hbmFnZXJWYXVsdEFkZHJlc3NPclRoaXMiAXMiFUlkeERpZmZUb3RhbEluY3JlbWVudCIkSWR4RGlmZlJlbWFpbmluZ1ByaWNlQW1vdW50SW5jcmVtZW50IiJJZHhEaWZmQ2xhaW1lZFByaWNlQW1vdW50SW5jcmVtZW50IiVJZHhEaWZmQ2xhaW1lZElkb0Fzc2V0QW1vdW50SW5jcmVtZW50IgtUb3RhbHNFbnRyeSIJb3JpZ0FycmF5Ig1pbmNyZW1lbnREaWZmIhRuZXdMYXN0Q2xhaW1lZEhlaWdodCIRcHJpY2VBc3NldEJhbGFuY2UiDm5ld1RvdGFsQW1vdW50IhJuZXdSZW1haW5pbmdBbW91bnQiCGNmZ0FycmF5IhJwcmljZUFzc2V0RGVjaW1hbHMiI3ByaWNlQXNzZXRCYWxhbmNlUHJpY2VBc3NldERlY2ltYWxzIhpuZXdDbGFpbWVkUHJpY2VBc3NldEFtb3VudCIYbmV3Q2xhaW1lZElkb0Fzc2V0QW1vdW50IgdlbnRyaWVzIgRkaWZmIhduZXdMb2dpY1JlbWFpbmluZ0Ftb3VudCIbSW52ZXN0T3BlcmF0aW9uSGlzdG9yeUVudHJ5IgR0eElkIhpDbGFpbU9wZXJhdGlvbkhpc3RvcnlFbnRyeSINaW50ZXJuYWxDbGFpbSIQY2xhaW1lZEFzc2V0SWQ1OCIIY2xhaW1FbmQiCmlkb0Fzc2V0SWQiDHByaWNlQXNzZXRJZCINdXNlckFkZHJlc3M1OCIPb3JpZ0ludmVzdEFycmF5IhFpbnZlc3RUb3RhbEFtb3VudCIaaW52ZXN0TGFzdENsYWltZWRIZWlnaHRUTVAiF2ludmVzdExhc3RDbGFpbWVkSGVpZ2h0IhRuZXdDbGFpbVBlcmlvZEhlaWdodCIOY2xhaW1pbmdCbG9ja3MiGGNsYWltaW5nUHJpY2VBc3NldEFtb3VudCIWY2xhaW1pbmdJZG9Bc3NldEFtb3VudCIGaXNVU0ROIhNpc1VTRE5DbGFpbURpc2FibGVkIgZjaGVja3MiD2ludGVybmFsQ2xhaW1WMiIJb3V0QW1vdW50Ihl0b3RhbFVzZXJBdmFpbGFibGVUb0NsYWltIh50b3RhbFBlcmlvZFByaWNlQXNzZXRBbGxvd2FuY2UiHXVzZXJQZXJpb2RQcmljZUFzc2V0QWxsb3dhbmNlIgxwZXJpb2RMZW5ndGgiDWN1cnJlbnRQZXJpb2QiG3plcm9QZXJpb2RFbmRIZWlnaElzRGVmaW5lZCINJHQwMTMyNzQxNTE0NCIVbGFzdFBlcmlvZFN0YXJ0SGVpZ2h0IhNsYXN0UGVyaW9kRW5kSGVpZ2h0Ig0kdDAxMzUzNDE0MjM5IhR1cGRhdGVkQ3VycmVudFBlcmlvZCILcGVyaW9kU3RhcnQiF2Jsb2Nrc1RvTGFzdFBlcmlvZFN0YXJ0IglwZXJpb2RFbmQiFXplcm9QZXJpb2RTdGFydEhlaWdodCITemVyb1BlcmlvZEVuZEhlaWdodCINJHQwMTQ0OTQxNDg3NiIbcGVyaW9kVG90YWxBdmFpbGFibGVUb0NsYWltIhpwZXJpb2RVc2VyQXZhaWxhYmxlVG9DbGFpbSIZcGVyaW9kTWluQXZhaWxhYmxlVG9DbGFpbSIcdXNkdFByaWNlQXNzZXRBbGxvd2FibGVSYXRpbyIbcHV0T25lVGtuVjJQcmljZUFzc2V0QW1vdW50Ig0kdDAxNTg5OTE2MTUyIgFAIgVib251cyIJZmVlQW1vdW50IghscEFtb3VudCILdXNkdEFzc2V0SWQiDSR0MDE2MjE0MTY0MzIiFGdldE9uZVRrblYyRmVlQW1vdW50Igp1c2R0QW1vdW50IhpjdXJyZW50VXNkdFByaWNlQXNzZXRSYXRpbyITZW5kUGVyaW9kQmxvY2tzTGVmdCIWbWFuYWdlclB1YmxpY0tleU9yVW5pdCITbWFuYWdlclZhdWx0QWRkcmVzcyILbXVzdE1hbmFnZXIiAWkiAnBkIgJwayISZ2V0Q2xhaW1Gb3JBY3Rpb25zIghmYWxsYmFjayIIaW52ZXN0b3IiE2ludmVzdG9yVG90YWxBbW91bnQiF2ludmVzdG9yUmVtYWluaW5nQW1vdW50IhlpbnZlc3RvclByaWNlQXNzZXRCYWxhbmNlIhdpbnZlc3Rvcklkb0Fzc2V0QmFsYW5jZSIZaW52ZXN0b3JMYXN0Q2xhaW1lZEhlaWdodCIRcHJpY2VBc3NldEFjdGlvbnMiGmludmVzdG9yS2V5UmVtYWluaW5nQW1vdW50IhtpbnZlc3RvcktleVJlbWFpbmluZ0FjdGlvbnMiF3RvdGFsSWRvQXNzZXRTZW5kQW1vdW50Ihx0b3RhbElkb0Fzc2V0Rm9ySW52ZXN0b3JEYXRhIgtuZXdJbnZlc3RvciITaW52ZXN0b3JEYXRhQWN0aW9ucyITc2VuZElkb0Fzc2V0QWN0aW9ucyIGaWRvRW5kIgNwbXQiDGlkb0Fzc2V0SW5mbyIOcHJpY2VBc3NldEluZm8iD29yaWdUb3RhbHNBcnJheSIKdG90YWxzRGlmZiIObWluSXZlc3RBbW91bnQiCnBtdEFzc2V0SWQiCXBtdEFtb3VudCIRb3JpZ0ludmVzdG9yQXJyYXkiE25ld1ByaWNlVG90YWxBbW91bnQiFnJlcXVpcmVkSWRvQXNzZXRBbW91bnQiD2NhbGxlckFkZHJlc3M1OCIQY2xhaW1SZXN1bHRUdXBsZSIKb3V0QXNzZXRJZCIaY2xhaW1lZFByaWNlQW1vdW50RnJvbURpZmYiHWNsYWltZWRJZG9Bc3NldEFtb3VudEZyb21EaWZmIg0kdDAyNDU2MjI1MDA2IiJ1cGRhdGVkUGVyaW9kVG90YWxBdmFpbGFibGVUb0NsYWltIiF1cGRhdGVkUGVyaW9kVXNlckF2YWlsYWJsZVRvQ2xhaW0iDmV2YWx1YXRlUmVzdWx0IhthdmFpbGFibGVQcmljZUFtb3VudFRvQ2xhaW0iEGxhc3RDbGFpbUVudHJpZXMiDm5ld0ludmVzdEFycmF5IgZ0b3RhbHMiEXRvdGFsc1RvdGFsQW1vdW50IhV0b3RhbHNSZW1haW5pbmdBbW91bnQiHXRvdGFsc0NsYWltZWRQcmljZUFzc2V0QW1vdW50Iht0b3RhbHNDbGFpbWVkSWRvQXNzZXRBbW91bnQiF3RvdGFsc0xhc3RDbGFpbWVkSGVpZ2h0IhhuZXdUb3RhbHNSZW1haW5pbmdBbW91bnQiDW5ld1RvdGFsQXJyYXkiF25ld1RvdGFsUmVtYWluaW5nQW1vdW50Ihh1cGRhdGVkUHJpY2VBc3NldEJhbGFuY2UiHHByaWNlQXNzZXRCYWxhbmNlSWRvRGVjaW1hbHMiFGNoZWNrVW5jbGFpbWVkQXNzZXRzIhxpbnZlc3RvclJlbWFpbmluZ0Ftb3VudENoZWNrIgluZXdUb3RhbHMiCHVzZXJMaXN0IgZoZWxwZXIiA2FjYyIEdXNlciINJHQwMzQ3NDUzNDc4NyIKYWxsQWN0aW9ucyIIdG90YWxTdW0iCGFkZHJMaXN0Ig0kdDAzNDc5MjM0OTI0Igt1c2VyQWN0aW9ucyIGYWRkU3VtIgJjaCINJHQwMzUxNjIzNTIyOSICJGwiAiRzIgUkYWNjMCIFJGYwXzEiAiRhIgIkaSIFJGYwXzIiA3N1bSICX2EiDHRvdGFsc0FjdGlvbiIVYXZhaWxhYmxlVG9DbGFpbUFycmF5IhlhdmFpbGFibGVJZG9BbW91bnRUb0NsYWltIi5hdmFpbGFibGVJZG9BbW91bnRUb0NsYWltV2l0aFByaWNlQXNzZXRCYWxhbmNlIg0kdDAzNzE5MTM3NjAzIhZjdXJyZW50UGVyaW9kRW5kSGVpZ2h0Ihp1c2VyVG90YWxQcmljZUFzc2V0Q2xhaW1lZCIMcmVzdWx0U3RyaW5nIgxwZXJpb2RMZW5naHQiE3VzZXJQZXJpb2RBbGxvd2FuY2UiFHRvdGFsUGVyaW9kQWxsb3dhbmNlIgJ0eCIGdmVyaWZ5Ig90YXJnZXRQdWJsaWNLZXlGAQFhAQFiCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKIIAQUBYgkArAICCQCsAgICD21hbmRhdG9yeSB0aGlzLgUBYgIPIGlzIG5vdCBkZWZpbmVkAAFjAgJfXwABZAkAtgIBAICAkLu61q3wDQABZQCAwtcvAQFmAQFnCQACAQkAuQkCCQDMCAICCWlkby5yaWRlOgkAzAgCBQFnBQNuaWwCASABAWgBAWkEAWoFAWkDCQABAgUBagIGU3RyaW5nBAFrBQFqBQFrCQACAQIYZmFpbCB0byBjYXN0IGludG8gU3RyaW5nAQFsBQFtAW4BbwFwAXEEAXIJALYCAQUBbgQBcwkAtgIBBQFxBAF0CQC8AgMJALYCAQUBbQUBZAUBcgQBdQkAvAIDBQF0CQC2AgEFAXAJALYCAQUBbwkAoAMBCQC8AgMFAXUJALYCAQUBcQUBZAABdgABAAF3AAIAAXgAAwABeQAEAAF6AAUAAUEABgABQgAHAAFDAAgAAUQACQABRQAKAAFGAAsBAUcMAUgBSQFKAUsBbwFMAU0BTgFPAVABUQFSCQC5CQIJAMwIAgIYJWQlZCVkJWQlZCVkJXMlZCVzJWQlZCVkCQDMCAIFAUgJAMwIAgUBSQkAzAgCBQFKCQDMCAIFAUsJAMwIAgUBbwkAzAgCBQFMCQDMCAIFAU0JAMwIAgUBTgkAzAgCBQFPCQDMCAIFAVAJAMwIAgUBUQkAzAgCBQFSBQNuaWwFAWMBAVMMAUgBSQFKAUsBbwFMAU0BTgFPAVABUQFSCQEBRwwJAKQDAQUBSAkApAMBBQFJCQCkAwEFAUoJAKQDAQUBSwkApAMBBQFvCQCkAwEFAUwFAU0JAKQDAQUBTgUBTwkApAMBBQFQCQCkAwEFAVEJAKQDAQUBUgABVAABAAFVAAIAAVYAAwABVwAEAAFYAAUBAVkFAVoCYWECYWICYWMCYWQJALkJAgkAzAgCAgolZCVkJWQlZCVkCQDMCAIFAVoJAMwIAgUCYWEJAMwIAgUCYWIJAMwIAgUCYWMJAMwIAgUCYWQFA25pbAUBYwECYWUFAVoCYWECYWICYWMCYWQJAQFZBQkApAMBBQFaCQCkAwEFAmFhCQCkAwEFAmFiCQCkAwEFAmFjCQCkAwEFAmFkAQJhZgIBbQJhZwkAuQkCCQDMCAICCCVkJWQlZCVkCQDMCAIJAKQDAQUGaGVpZ2h0CQDMCAIJAKQDAQgFCWxhc3RCbG9jawl0aW1lc3RhbXAJAMwIAgkApAMBBQFtCQDMCAIJAKQDAQUCYWcFA25pbAUBYwECYWgAAgolc19fY29uZmlnAQJhaQECYWoJAKwCAgIEJXNfXwUCYWoBAmFrAAIKJXNfX3RvdGFscwECYWwDAmFtAmFqAmFuCQC5CQIJAMwIAgIRJXMlcyVzJXNfX2hpc3RvcnkJAMwIAgUCYW0JAMwIAgUCYWoJAMwIAgUCYW4FA25pbAUBYwECYW8AAhUlc19fdXNkbkNsYWltRGlzYWJsZWQBAmFwAAIWJXNfX3VzZG5DbGFpbUVuZEhlaWdodAECYXEACQC5CQIJAMwIAgICJXMJAMwIAgIMcGVyaW9kTGVuZ3RoBQNuaWwFAWMBAmFyAAkAuQkCCQDMCAICAiVzCQDMCAICDWN1cnJlbnRQZXJpb2QFA25pbAUBYwECYXMBAmF0CQC5CQIJAMwIAgIEJXMlcwkAzAgCAhFwZXJpb2RTdGFydEhlaWdodAkAzAgCCQCkAwEFAmF0BQNuaWwFAWMBAmF1AQJhdAkAuQkCCQDMCAICBCVzJXMJAMwIAgIPcGVyaW9kRW5kSGVpZ2h0CQDMCAIJAKQDAQUCYXQFA25pbAUBYwECYXYACQC5CQIJAMwIAgICJXMJAMwIAgIcdXNkdFByaWNlQXNzZXRBbGxvd2FibGVSYXRpbwUDbmlsBQFjAQJhdwECYXgJALkJAgkAzAgCAgQlcyVzCQDMCAICFHRvdGFsUGVyaW9kQWxsb3dhbmNlCQDMCAIFAmF4BQNuaWwFAWMBAmF5AQJheAkAuQkCCQDMCAICBCVzJXMJAMwIAgITdXNlclBlcmlvZEFsbG93YW5jZQkAzAgCBQJheAUDbmlsBQFjAQJhegICYXgCYXQJALkJAgkAzAgCAgYlcyVzJXMJAMwIAgIbcGVyaW9kVG90YWxBdmFpbGFibGVUb0NsYWltCQDMCAIFAmF4CQDMCAIJAKQDAQUCYXQFA25pbAUBYwECYUEDAmF4AmF0AmFqCQC5CQIJAMwIAgIIJXMlcyVzJXMJAMwIAgIacGVyaW9kVXNlckF2YWlsYWJsZVRvQ2xhaW0JAMwIAgUCYXgJAMwIAgkApAMBBQJhdAkAzAgCBQJhagUDbmlsBQFjAQJhQgAJALkJAgkAzAgCAgIlcwkAzAgCAhh1c2R0UHJpY2VBc3NldFN0YWJsZVBvb2wFA25pbAUBYwECYUMACQC5CQIJAMwIAgICJXMJAMwIAgILdXNkdEFzc2V0SWQFA25pbAUBYwECYUQBAmFFCQC5CQIJAMwIAgIEJXMlcwkAzAgCAhFwcmljZUFzc2V0QmFsYW5jZQkAzAgCBQJhRQUDbmlsBQFjAQJhRgECYUUJALkJAgkAzAgCAgQlcyVzCQDMCAICF2ludmVzdG9yUmVtYWluaW5nQW1vdW50CQDMCAIFAmFFBQNuaWwFAWMBAmFHAAkAuQkCCQDMCAICAiVzCQDMCAICFHRvdGFsUmVtYWluaW5nQW1vdW50BQNuaWwFAWMBAmFIAAIUJXNfX21hbmFnZXJQdWJsaWNLZXkBAmFJAAIXJXNfX21hbmFnZXJWYXVsdEFkZHJlc3MBAmFKAAIWJXNfX2NsYWltQ2xvc2luZ0hlaWdodAACYUsJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwkBAmFKAAAAAQJhTAAJALUJAgkBAWEBCQECYWgABQFjAQJhTQECYU4JALUJAgkBC3ZhbHVlT3JFbHNlAgkAoggBBQJhTgkBAVkFAgEwAgEwAgEwAgEwAgEwBQFjAQJhTwAJAQJhTQEJAQJhawABAmFQAQJhagkBAmFNAQkBAmFpAQUCYWoBAmFRAQJhagkAtQkCCQEBYQEJAQJhaQEFAmFqBQFjAQJhUgAEAWoJAKIIAQkBAmFJAAMJAAECBQFqAgZTdHJpbmcEAmFTBQFqCQERQGV4dHJOYXRpdmUoMTA2MikBBQJhUwUEdGhpcwACYVQAAAACYVUAAQACYVYAAgACYVcAAwECYVgFAWICYVkCYVoCYmECYmIEAVoJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQJhWQUBVAQCYWEJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQJhWQUBVQQCYWIJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQJhWQUBVgQCYWMJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQJhWQUBVwQCYWQJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQJhWQUBWAQCYmMJAGQCBQFaCQCRAwIFAmFaBQJhVAQCYmQJAGQCBQJhYQkAkQMCBQJhWgUCYVUEAmJlCQECYUwABAFPCQCRAwIFAmJlBQFEBAJiZggJAQV2YWx1ZQEJAOwHAQkA2QQBBQFPCGRlY2ltYWxzBAJiZwkAawMFAmJiBQFlCQBsBgAKAAAFAmJmAAAAAAUERE9XTgQCYmgJAGUCCQBkAgUCYWIJAJEDAgUCYVoFAmFWBQJiYgQCYmkJAGQCCQBkAgUCYWMJAJEDAgUCYVoFAmFXBQJiZwQCYmoDCQBmAgAABQJiZAQCYmsJAGUCCQBlAgUCYmMFAmJoBQJiaQQCYmwDCQBmAgAABQJiawAABQJiawkBC1N0cmluZ0VudHJ5AgUBYgkBAmFlBQUCYmMFAmJsBQJiaAUCYmkFAmJhCQELU3RyaW5nRW50cnkCBQFiCQECYWUFBQJiYwUCYmQFAmJoBQJiaQUCYmEFAmJqAQJibQQCYWoBbQJhZwJibgkBC1N0cmluZ0VudHJ5AgkBAmFsAwIGaW52ZXN0BQJhagkA2AQBBQJibgkBAmFmAgUBbQUCYWcBAmJvBAJhagFtAmFnAmJuCQELU3RyaW5nRW50cnkCCQECYWwDAgVjbGFpbQUCYWoJANgEAQUCYm4JAQJhZgIFAW0FAmFnAQJicAMCYnECYWoCYm4EAmJlCQECYUwABAFKCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUCYmUFAXgEAUsJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQJiZQUBeQQCYnIJAGQCBQFKBQFLBAFvCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUCYmUFAXoEAUwJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQJiZQUBQQQBTQkAkQMCBQJiZQUBQgQCYnMJANkEAQUBTQQBTgkBDXBhcnNlSW50VmFsdWUBCQCRAwIFAmJlBQFDBAFPCQCRAwIFAmJlBQFEBAJidAkA2QQBBQFPBAFQCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUCYmUFAUUEAmJ1CQClCAEFAmFqBAJidgkBAmFRAQUCYnUEAmJ3CQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUCYnYFAVQEAmJ4CQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUCYnYFAVgEAmJ5AwkAZwIFAUoFAmJ4BQFKBQJieAQCYnoDCQBmAgUGaGVpZ2h0BQJicgUCYnIDCQBmAgUBSgUGaGVpZ2h0BQFKBQZoZWlnaHQEAmJBCQBlAgUCYnoFAmJ5BAJiQgkAawMFAmJ3BQJiQQUBSwQCYkMJAQFsBQUCYkIFAVAFAW8FAUwFAU4EAmJECQAAAgUCYnEFAU8EAmJFCQELdmFsdWVPckVsc2UCCQCgCAEJAQJhbwAHBAJiRgkAzAgCAwkBASEBAwUCYkQFAmJFBwYJAAIBAhZVU0ROIGNsYWltIGlzIGRpc2FibGVkBQNuaWwDCQAAAgUCYkYFAmJGAwkAAAIFAmJxBQFPCQCYCgYJAMwIAgAACQDMCAIJAQEtAQUCYkIJAMwIAgUCYkIJAMwIAgAABQNuaWwFAmJCBQJidAUCYnYFAmJ6CQDMCAIFAmJCCQDMCAIFAmJDBQNuaWwDCQAAAgUCYnEFAU0JAJgKBgkAzAgCAAAJAMwIAgkBAS0BBQJiQgkAzAgCAAAJAMwIAgUCYkMFA25pbAUCYkMFAmJzBQJidgUCYnoJAMwIAgUCYkIJAMwIAgUCYkMFA25pbAkAAgEJAKwCAgIVdW5zdXBwb3J0ZWQgYXNzZXRJZDogBQJicQkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgECYkcEAU8CYnUCYkgCYkkEAmJKCQEFdmFsdWUBCQCfCAEJAQJhdwEFAU8EAmJLCQEFdmFsdWUBCQCfCAEJAQJheQEFAU8EAmJMCQEFdmFsdWUBCQCfCAEJAQJhcQAEAmJNCQELdmFsdWVPckVsc2UCCQCfCAEJAQJhcgAAAAQCYk4JAQlpc0RlZmluZWQBCQCfCAEJAQJhdQEAAAQCYk8DCQBmAgUCYk0AAAQCYlAJAQV2YWx1ZQEJAJ8IAQkBAmFzAQUCYk0EAmJRCQEFdmFsdWUBCQCfCAEJAQJhdQEFAmJNBAJiUgMJAGYCBQZoZWlnaHQFAmJRBAJiUwkAZAIFAmJNAAEEAmJUAwkAZgIFBmhlaWdodAkAZAIFAmJRBQJiTAQCYlUJAGoCCQBlAgUGaGVpZ2h0BQJiUQUCYkwDCQAAAgUCYlUAAAkAZAIJAGUCBQZoZWlnaHQFAmJMAAEJAGUCBQZoZWlnaHQFAmJVCQBkAgUCYlEAAQQCYlYJAGUCCQBkAgUCYlQFAmJMAAEJAJUKAwUCYlMFAmJUBQJiVgkAlQoDBQJiTQUCYlAFAmJRBAJiUwgFAmJSAl8xBAJiVAgFAmJSAl8yBAJiVggFAmJSAl8zCQCVCgMFAmJTBQJiVAUCYlYDBQJiTgQCYlcJAQV2YWx1ZQEJAJ8IAQkBAmFzAQAABAJiWAkBBXZhbHVlAQkAnwgBCQECYXUBAAAEAmJZAwkAZgIFBmhlaWdodAUCYlgEAmJTCQBkAgUCYk0AAQQCYlQJAGQCBQJiWAABBAJiVgkAZQIJAGQCBQJiVAUCYkwAAQkAlQoDBQJiUwUCYlQFAmJWCQCVCgMFAmJNBQJiVwUCYlgEAmJTCAUCYlkCXzEEAmJUCAUCYlkCXzIEAmJWCAUCYlkCXzMJAJUKAwUCYlMFAmJUBQJiVgkAlQoDBQJiTQkBC3ZhbHVlT3JFbHNlAgkAnwgBCQECYXMBBQJiTQUGaGVpZ2h0CQELdmFsdWVPckVsc2UCCQCfCAEJAQJhdQEFAmJNCQBlAgkAZAIFBmhlaWdodAUCYkwAAQQCYlMIBQJiTwJfMQQCYlQIBQJiTwJfMgQCYlYIBQJiTwJfMwQCYloJAQt2YWx1ZU9yRWxzZQIJAJ8IAQkBAmF6AgUBTwUCYlMFAmJKBAJjYQkBC3ZhbHVlT3JFbHNlAgkAnwgBCQECYUEDBQFPBQJiUwUCYnUFAmJLBAJiYgkBC3ZhbHVlT3JFbHNlAgkAnwgBCQECYUQBBQJidQAABAJjYgkAlwMBCQDMCAIJAGQCBQJiSAUCYmIJAMwIAgUCYloJAMwIAgUCY2EFA25pbAQCY2MJAQV2YWx1ZQEJAJ8IAQkBAmF2AAQCY2QFAWUEAmNlCgACY2YJAPwHBAkBEUBleHRyTmF0aXZlKDEwNjIpAQkBBXZhbHVlAQkAoggBCQECYUIAAiFwdXRPbmVUa25WMldpdGhvdXRUYWtlRmVlUkVBRE9OTFkJAMwIAgUCY2QJAMwIAgUBTwUDbmlsBQNuaWwDCQABAgUCY2YCDyhJbnQsIEludCwgSW50KQUCY2YJAAIBCQCsAgIJAAMBBQJjZgIkIGNvdWxkbid0IGJlIGNhc3QgdG8gKEludCwgSW50LCBJbnQpAwkAAAIFAmNlBQJjZQQCY2cIBQJjZQJfMwQCY2gIBQJjZQJfMgQCY2kIBQJjZQJfMQQCY2oJAQV2YWx1ZQEJAKIIAQkBAmFDAAQCY2sKAAJjZgkA/AcECQERQGV4dHJOYXRpdmUoMTA2MikBCQEFdmFsdWUBCQCiCAEJAQJhQgACE2dldE9uZVRrblYyUkVBRE9OTFkJAMwIAgUCY2oJAMwIAgUCY2kFA25pbAUDbmlsAwkAAQIFAmNmAgooSW50LCBJbnQpBQJjZgkAAgEJAKwCAgkAAwEFAmNmAh8gY291bGRuJ3QgYmUgY2FzdCB0byAoSW50LCBJbnQpAwkAAAIFAmNrBQJjawQCY2wIBQJjawJfMgQCY20IBQJjawJfMQQCY24JAGsDBQJjZAUBZQUCY20EAmNvCQBlAgUCYlYFBmhlaWdodAkAnAoKBQJjYgUCYloFAmNhBQJiSQUCY2MFAmNuBQJjbwUCYlMFAmJUBQJiVgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgECY3AABAJjcQkBAmFSAAQBagkAnQgCBQJjcQkBAmFIAAMJAAECBQFqAgZTdHJpbmcEAmFTBQFqCQDZBAEFAmFTAwkAAQIFAWoCBFVuaXQFBHVuaXQJAAIBAgtNYXRjaCBlcnJvcgECY3IBAmNzBAJjdAkAAgECEVBlcm1pc3Npb24gZGVuaWVkBAFqCQECY3AAAwkAAQIFAWoCCkJ5dGVWZWN0b3IEAmN1BQFqAwkAAAIIBQJjcw9jYWxsZXJQdWJsaWNLZXkFAmN1BgUCY3QDCQABAgUBagIEVW5pdAMJAAACCAUCY3MGY2FsbGVyBQR0aGlzBgUCY3QJAAIBAgtNYXRjaCBlcnJvcgECY3YCAmJ1AmJuBAFNCQCRAwIJAQJhTAAFAUIEAmN3CQC5CQIJAMwIAgIKJWQlZCVkJWQlZAkAzAgCAgEwCQDMCAICATAJAMwIAgIBMAkAzAgCAgEwCQDMCAICATAFA25pbAUBYwQCY3gJALUJAgkBC3ZhbHVlT3JFbHNlAgkAoggBCQECYWkBBQJidQUCY3cFAWMEAmN5CQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUCY3gFAVQEAmN6CQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUCY3gFAVUEAmNBCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUCY3gFAVYEAmNCCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUCY3gFAVcEAmNDCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUCY3gFAVgEAW0JAQt2YWx1ZU9yRWxzZQIJAJ8IAQkBAmFEAQUCYnUAAAQCY0QDCQECIT0CBQFtAAAJAMwIAgkBDEludGVnZXJFbnRyeQIJAQJhRAEFAmJ1AAAFA25pbAUDbmlsBAJjRQkBDXBhcnNlSW50VmFsdWUBCQELdmFsdWVPckVsc2UCCQCiCAEJAQJhRgEFAmJ1AgEwBAJjRgMJAQIhPQIFAmNFAAAJAMwIAgkBC1N0cmluZ0VudHJ5AgkBAmFGAQUCYnUCATAFA25pbAUDbmlsBAJjRwkAaAIJAGQCCQBkAgUCY3oFAW0FAmNFAGQEAmNICQBoAgkAZAIFAmN6BQJjRQBkBAJjSQkAuQkCCQDMCAICCiVkJWQlZCVkJWQJAMwIAgkApAMBBQJjeQkAzAgCAgEwCQDMCAIJAKQDAQUCY0EJAMwIAgkApAMBCQBkAgUCY0IFAmNICQDMCAIJAKQDAQUGaGVpZ2h0BQNuaWwFAWMEAmNKAwkBAiE9AgUCY0gAAAkAzAgCCQELU3RyaW5nRW50cnkCCQECYWkBBQJidQUCY0kFA25pbAUDbmlsBAJjSwMJAQIhPQIFAmNHAAAJAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwkBEUBleHRyTmF0aXZlKDEwNjIpAQUCYnUFAmNHCQDZBAEFAU0JAMwIAgkBAmJvBAUCYnUAAAUCY0cFAmJuBQNuaWwFA25pbAkAlgoEBQJjegUBbQUCY0UJAM4IAgkAzggCCQDOCAIFAmNLBQJjSgUCY0YFAmNEBwJjcwELY29uc3RydWN0b3IHAUgBSQFKAUsBbwFPAVEEAUwJAGgCCQBoAgBkAOgHAOgHBAJjTAkAZAIFAUgFAUkDCQEJaXNEZWZpbmVkAQkAoggBCQECYWgACQACAQITYWxyZWFkeSBpbml0aWFsaXplZAMJAQIhPQICIzNQTUVITHgxajZ6ZXJhclpUWWZzR3FEZWVacVFvTXB4cTVTCQClCAEIBQJjcwZjYWxsZXIJAAIBAg5ub3QgYXV0aG9yaXplZAMJAQIhPQIJAJADAQgFAmNzCHBheW1lbnRzAAEJAAIBAiJleGFjdGx5IDEgcGF5bWVudCBtdXN0IGJlIGF0dGFjaGVkAwkAZwIFAmNMBQFKCQACAQImY2xhaW1TdGFydCBtdXN0IGJlIGdyZWF0ZXIgdGhhbiBpZG9FbmQEAmNNCQEFdmFsdWUBCQCRAwIIBQJjcwhwYXltZW50cwAABAJicwkBBXZhbHVlAQgFAmNNB2Fzc2V0SWQEAmNOCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAOwHAQUCYnMCG2ZhaWwgdG8gbG9hZCBpZG8gYXNzZXQgaW5mbwQBTQkA2AQBBQJicwQBTgkAbAYACgAACAUCY04IZGVjaW1hbHMAAAAABQRET1dOBAJidAkA2QQBBQFPBAJjTwkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQDsBwEFAmJ0Ah1mYWlsIHRvIGxvYWQgcHJpY2UgYXNzZXQgaW5mbwQBUAkAbAYACgAACAUCY08IZGVjaW1hbHMAAAAABQRET1dOBAJjUAkBAmFPAAQCY1EJAMwIAgAACQDMCAIAAAkAzAgCAAAJAMwIAgAABQNuaWwJAMwIAgkBC1N0cmluZ0VudHJ5AgkBAmFoAAkBAVMMBQFIBQFJBQFKBQFLBQFvBQFMBQFNBQFOBQFPBQFQBQFRCAUCY00GYW1vdW50CQDMCAIJAQJhWAUJAQJhawAFAmNQBQJjUQUBSgAABQNuaWwCY3MBBmludmVzdAAEAmJlCQECYUwABAFICQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUCYmUFAXYEAUkJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQJiZQUBdwQCY0wJAGQCBQFIBQFJBAFKCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUCYmUFAXgEAUsJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQJiZQUBeQQBbwkBDXBhcnNlSW50VmFsdWUBCQCRAwIFAmJlBQF6BAFMCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUCYmUFAUEEAU0JAJEDAgUCYmUFAUIEAmJzCQDZBAEFAU0EAU4JAQ1wYXJzZUludFZhbHVlAQkAkQMCBQJiZQUBQwQBTwkAkQMCBQJiZQUBRAQCYnQJANkEAQUBTwQBUAkBDXBhcnNlSW50VmFsdWUBCQCRAwIFAmJlBQFFBAJjUgkBDXBhcnNlSW50VmFsdWUBCQCRAwIFAmJlBQFGBAJhagkApQgBCAUCY3MGY2FsbGVyAwkAZgIFAUgFBmhlaWdodAkAAgECHGlkbyBoYXMgbm90IGJlZW4gc3RhcnRlZCB5ZXQDCQBmAgUGaGVpZ2h0BQJjTAkAAgECGmlkbyBoYXMgYmVlbiBhbHJlYWR5IGVuZGVkAwkBAiE9AgkAkAMBCAUCY3MIcGF5bWVudHMAAQkAAgECHWV4YWN0bHkgMSBwYXltZW50IGlzIGV4cGVjdGVkBAJjTQkBBXZhbHVlAQkAkQMCCAUCY3MIcGF5bWVudHMAAAQCY1MJAQV2YWx1ZQEIBQJjTQdhc3NldElkBAJjVAgFAmNNBmFtb3VudAMJAQIhPQIFAmNTBQJidAkAAgEJAKwCAgkArAICAhppbnZhbGlkIHBheW1lbnQgYXNzZXQgaWQ6IAkA2AQBBQJjUwIMIGlzIGV4cGVjdGVkBAJjVQkBAmFQAQUCYWoEAmNQCQECYU8ABAJjVgkAZAIJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQJjUAUBVAUCY1QEAmNXCQBoAgUCY1YAZAMJAGYCBQJjVwkA8AcCBQR0aGlzBQJicwkAAgECOUlETyBhc3NldCBoYXMgYmVlbiAtIHNvbGQgY29uc2lkZXIgdG8gdXNlIHNtYWxsZXIgcGF5bWVudAQCY1EJAMwIAgUCY1QJAMwIAgUCY1QJAMwIAgAACQDMCAIAAAUDbmlsCQDMCAIJAQJhWAUJAQJhaQEFAmFqBQJjVQUCY1EFAUoAAAkAzAgCCQECYVgFCQECYWsABQJjUAUCY1EFAUoAAAkAzAgCCQECYm0EBQJhagUCY1QAAAgFAmNzDXRyYW5zYWN0aW9uSWQFA25pbAJjcwEFY2xhaW0CAmJxAmJ1BAJjWAkApQgBCAUCY3MGY2FsbGVyAwkBAiE9AgUCYnUFAmNYCQACAQIObm90IGF1dGhvcml6ZWQEAmJlCQECYUwABAFPCQCRAwIFAmJlBQFEBAJjWQkBAmJwAwUCYnEIBQJjcwZjYWxsZXIIBQJjcw10cmFuc2FjdGlvbklkBAJjUQgFAmNZAl8xBAJiSAgFAmNZAl8yBAJjWggFAmNZAl8zBAJidggFAmNZAl80BAJieggFAmNZAl81BAJkYQkAkQMCBQJjUQUCYVYEAmRiCQCRAwIFAmNRBQJhVwQCYmIJAQt2YWx1ZU9yRWxzZQIJAJ8IAQkBAmFEAQUCYnUAAAQCYmYICQEFdmFsdWUBCQDsBwEJANkEAQUBTwhkZWNpbWFscwQCYmoDCQAAAgUCYnEFAU8EAmRjCQECYkcEBQFPBQJidQUCYkgJAJEDAgUCY1EFAmFWBAJjYggFAmRjAl8xBAJiWggFAmRjAl8yBAJjYQgFAmRjAl8zBAJiSQgFAmRjAl80BAJjYwgFAmRjAl81BAJjbggFAmRjAl82BAJjbwgFAmRjAl83BAJiUwgFAmRjAl84BAJiVAgFAmRjAl85BAJiVggFAmRjA18xMAQCYkYJAMwIAgMJAGYCBQJjYQAABgkBAWYBAjp1bmF2YWlsYWJsZSB0byBjbGFpbSBiZWNhdXNlIHVzZXIgcGVyaW9kIGFsbG93YW5jZSByZWFjaGVkCQDMCAIDCQBmAgUCYloAAAYJAQFmAQI7dW5hdmFpbGFibGUgdG8gY2xhaW0gYmVjYXVzZSB0b3RhbCBwZXJpb2QgYWxsb3dhbmNlIHJlYWNoZWQJAMwIAgMJAGYCBQJjYgAABgkBAWYBAhBub3RoaW5nIHRvIGNsYWltCQDMCAIDCQBmAgUCY2MFAmNuBgkBAWYBAk91bmF2YWlsYWJsZSB0byBjbGFpbSBiZWNhdXNlIHVzZG4gcHJpY2UgbG93ZXIgdGhhbiB1c2R0UHJpY2VBc3NldEFsbG93YWJsZVJhdGlvCQDMCAIDAwMJAQIhPQIFAmJxBQFPBgkAAAIFAmFLAAAGCQBmAgUCYUsFBmhlaWdodAYJAQFmAQIRQ2xhaW0gaXMgZGlzYWJsZWQFA25pbAMJAAACBQJiRgUCYkYEAmRkCQBlAgUCYloFAmNiBAJkZQkAZQIFAmNhBQJjYgQCYmoDCQBmAgUCYmIFAmNiCQDMCAIJAQ5TY3JpcHRUcmFuc2ZlcgMIBQJjcwZjYWxsZXIFAmNiBQJjWgkAzAgCCQEMSW50ZWdlckVudHJ5AgkBAmFEAQUCYnUJAGUCBQJiYgUCY2IFA25pbAQCZGYJALUJAgkBAWgBCQD8BwQFBHRoaXMCDWNsYWltUkVBRE9OTFkJAMwIAgUBTwkAzAgCBQJidQUDbmlsBQNuaWwFAWMDCQAAAgUCZGYFAmRmBAJkZwkBDXBhcnNlSW50VmFsdWUBCQCRAwIFAmRmAAMEAmRoAwkAAAIFAmRnBQJjYgQCY3kJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQJidgUBVAQCY3oJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQJidgUBVQQCY0EJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQJidgUBVgQCY0IJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQJidgUBVwQCY0MJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQJidgUBWAQCZGkJAMwIAgkApAMBBQJjeQkAzAgCAgEwCQDMCAIJAKQDAQUCY0EJAMwIAgkApAMBBQJjQgkAzAgCCQCkAwEFAmNDBQNuaWwEAmRqCQECYU8ABAJkawkBDXBhcnNlSW50VmFsdWUBCQCRAwIFAmRqBQFUBAJkbAkBDXBhcnNlSW50VmFsdWUBCQCRAwIFAmRqBQFVBAJkbQkBDXBhcnNlSW50VmFsdWUBCQCRAwIFAmRqBQFWBAJkbgkBDXBhcnNlSW50VmFsdWUBCQCRAwIFAmRqBQFXBAJkbwkBDXBhcnNlSW50VmFsdWUBCQCRAwIFAmRqBQFYBAJkcAkAZQIFAmRsBQJjegQCZHEJAMwIAgkApAMBBQJkawkAzAgCCQCkAwEFAmRwCQDMCAIJAKQDAQUCZG0JAMwIAgkApAMBBQJkbgkAzAgCCQCkAwEFAmRvBQNuaWwEAmRyCQBkAgkBC3ZhbHVlT3JFbHNlAgkAnwgBCQECYUcAAAAFAmN6CQDMCAIJAQtTdHJpbmdFbnRyeQIJAQJhRgEFAmJ1CQCkAwEFAmN6CQDMCAIJAQtTdHJpbmdFbnRyeQIJAQJhRwAJAKQDAQUCZHIJAMwIAgkBAmFYBQkBAmFpAQUCYnUFAmRpBQJjUQUCYnoAAAkAzAgCCQECYVgFCQECYWsABQJkcQUCY1EFAmJ6AAAFA25pbAkAzAgCCQECYVgFCQECYWkBBQJidQUCYnYFAmNRBQJiegAACQDMCAIJAQJhWAUJAQJhawAJAQJhTwAFAmNRBQJiegAABQNuaWwEAmRzCQBlAgkAZAIFAmJiBQJiSAUCY2IJAM4IAgkAzAgCCQEOU2NyaXB0VHJhbnNmZXIDCAUCY3MGY2FsbGVyBQJjYgUCY1oJAMwIAgkBDEludGVnZXJFbnRyeQIJAQJhRAEFAmJ1BQJkcwUDbmlsBQJkaAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAlAoCCQDOCAIJAMwIAgkBDEludGVnZXJFbnRyeQIJAQJhcgAFAmJTCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQECYXMBBQJiUwUCYlQJAMwIAgkBDEludGVnZXJFbnRyeQIJAQJhdQEFAmJTBQJiVgkAzAgCCQEMSW50ZWdlckVudHJ5AgkBAmF6AgUBTwUCYlMFAmRkCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQECYUEDBQFPBQJiUwUCYnUFAmRlCQDMCAIJAQJibwQFAmJ1BQJjYgUCZGIIBQJjcw10cmFuc2FjdGlvbklkBQNuaWwFAmJqBQR1bml0CQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuBAJkdAkAawMFAmJiBQFlCQBsBgAKAAAFAmJmAAAAAAUERE9XTgkAlAoCCQDMCAIJAQ5TY3JpcHRUcmFuc2ZlcgMIBQJjcwZjYWxsZXIJAGQCBQJiSAUCZHQFAmNaCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQECYUQBBQJidQAACQDMCAIJAQJhWAUJAQJhaQEFAmJ1BQJidgUCY1EFAmJ6BQJiYgkAzAgCCQECYVgFCQECYWsACQECYU8ABQJjUQUCYnoFAmJiCQDMCAIJAQJibwQFAmJ1BQJkYQkAZAIFAmRiBQJkdAgFAmNzDXRyYW5zYWN0aW9uSWQFA25pbAUEdW5pdAUCYmoCY3MBEmNsZWFuUmVtYWluZ0Ftb3VudAECYnUEAU8JAJEDAgkBAmFMAAUBRAQCZGYJALUJAgkBAWgBCQD8BwQFBHRoaXMCDWNsYWltUkVBRE9OTFkJAMwIAgUBTwkAzAgCBQJidQUDbmlsBQNuaWwFAWMDCQAAAgUCZGYFAmRmBAJkZwkBDXBhcnNlSW50VmFsdWUBCQCRAwIFAmRmAAIEAmR1AwkAAAIFAmRnAAAGCQEBZgECGnVzZXIgaGF2ZSB1bmNsYWltZWQgYXNzZXRzAwkAAAIFAmR1BQJkdQQCY3gJALUJAgkBBXZhbHVlAQkAoggBCQECYWkBBQJidQUBYwQCY3kJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQJjeAUBVAQCY3oJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQJjeAUBVQQCY0EJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQJjeAUBVgQCY0IJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQJjeAUBVwQCY0MJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQJjeAUBWAQCZHYDCQECIT0CBQJjegAABgkBAWYBAiRpbnZlc3RvclJlbWFpbmluZ0Ftb3VudCBhbHJlYWR5IHplcm8DCQAAAgUCZHYFAmR2BAJjSQkAuQkCCQDMCAICCiVkJWQlZCVkJWQJAMwIAgkApAMBBQJjeQkAzAgCAgEwCQDMCAIJAKQDAQUCY0EJAMwIAgkApAMBBQJjQgkAzAgCCQCkAwEFAmNDBQNuaWwFAWMEAmRqCQC1CQIJAQV2YWx1ZQEJAKIIAQkBAmFrAAUBYwQCZGsJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQJkagUBVAQCZGwJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQJkagUBVQQCZG0JAQ1wYXJzZUludFZhbHVlAQkAkQMCBQJkagUBVgQCZG4JAQ1wYXJzZUludFZhbHVlAQkAkQMCBQJkagUBVwQCZG8JAQ1wYXJzZUludFZhbHVlAQkAkQMCBQJkagUBWAQCZHcJALkJAgkAzAgCAgolZCVkJWQlZCVkCQDMCAIJAKQDAQUCZGsJAMwIAgkApAMBCQBlAgUCZGwFAmN6CQDMCAIJAKQDAQUCZG0JAMwIAgkApAMBBQJkbgkAzAgCCQCkAwEFAmRvBQNuaWwFAWMEAmRyCQBkAgkBC3ZhbHVlT3JFbHNlAgkAnwgBCQECYUcAAAAFAmN6CQDMCAIJAQtTdHJpbmdFbnRyeQIJAQJhRgEFAmJ1CQCkAwEFAmN6CQDMCAIJAQtTdHJpbmdFbnRyeQIJAQJhRwAJAKQDAQUCZHIJAMwIAgkBC1N0cmluZ0VudHJ5AgkBAmFpAQUCYnUFAmNJCQDMCAIJAQtTdHJpbmdFbnRyeQIJAQJhawAFAmR3BQNuaWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4CY3MBCGNsYWltRm9yAQJkeAoBAmR5AgJkegJkQQQCZEIFAmR6BAJkQwgFAmRCAl8xBAJkRAgFAmRCAl8yBAJkRQgFAmRCAl8zBAJkRgkBAmN2AgUCZEEIBQJjcw10cmFuc2FjdGlvbklkBAJjeggFAmRGAl8xBAFtCAUCZEYCXzIEAmNFCAUCZEYCXzMEAmRHCAUCZEYCXzQEAmRICQBkAgUCY3oFAmNFBAJkSQMJAQEhAQkBD2NvbnRhaW5zRWxlbWVudAIFAmRFBQJkQQYJAQFmAQIZZHVwbGljYXRlIGFkZHJlc3MgaW4gbGlzdAMJAAACBQJkSQUCZEkJAJUKAwkAzggCBQJkQwUCZEcJAGQCBQJkRAUCZEgJAM0IAgUCZEUFAmRBCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuBAJkSgoAAmRLBQJkeAoAAmRMCQCQAwEFAmRLCgACZE0JAJUKAwUDbmlsAAAFA25pbAoBAmROAgJkTwJkUAMJAGcCBQJkUAUCZEwFAmRPCQECZHkCBQJkTwkAkQMCBQJkSwUCZFAKAQJkUQICZE8CZFADCQBnAgUCZFAFAmRMBQJkTwkAAgECFExpc3Qgc2l6ZSBleGNlZWRzIDE5CQECZFECCQECZE4CCQECZE4CCQECZE4CCQECZE4CCQECZE4CCQECZE4CCQECZE4CCQECZE4CCQECZE4CCQECZE4CCQECZE4CCQECZE4CCQECZE4CCQECZE4CCQECZE4CCQECZE4CCQECZE4CCQECZE4CCQECZE4CBQJkTQAAAAEAAgADAAQABQAGAAcACAAJAAoACwAMAA0ADgAPABAAEQASABMEAmRDCAUCZEoCXzEEAmRSCAUCZEoCXzIEAmRTCAUCZEoCXzMEAmRUAwkBAiE9AgUCZFIAAAkAzAgCCQECYVgFCQECYWsACQECYU8ACQDMCAIAAAkAzAgCCQEBLQEFAmRSCQDMCAIAAAkAzAgCBQJkUgUDbmlsBQZoZWlnaHQAAAUDbmlsBQNuaWwJAM4IAgUCZEMFAmRUAmNzAQ1jbGFpbVJFQURPTkxZAgJicQJidQQCY1kJAQJicAMFAmJxCQERQGV4dHJOYXRpdmUoMTA2MikBBQJidQkA2QQBAgAEAmNRCAUCY1kCXzEEAmJICAUCY1kCXzIEAmNaCAUCY1kCXzMEAmJ2CAUCY1kCXzQEAmJ6CAUCY1kCXzUEAmRVCAUCY1kCXzYEAmRnCQCRAwIFAmRVAAAEAmRWCQCRAwIFAmRVAAEJAJQKAgUDbmlsCQC5CQIJAMwIAgIGJXMlZCVkCQDMCAIFAmJ1CQDMCAIJAKQDAQUCZGcJAMwIAgkApAMBBQJkVgUDbmlsBQFjAmNzAQ9jbGFpbVYyUkVBRE9OTFkCAmJxAmJ1BAJjWQkBAmJwAwUCYnEJARFAZXh0ck5hdGl2ZSgxMDYyKQEFAmJ1CQDZBAECAAQCY1EIBQJjWQJfMQQCYkgIBQJjWQJfMgQCY1oIBQJjWQJfMwQCYnYIBQJjWQJfNAQCYnoIBQJjWQJfNQQCZFUIBQJjWQJfNgQCZGcJAJEDAgUCZFUAAAQCZFYJAJEDAgUCZFUAAQQCYmUJAQJhTAAEAU8JAJEDAgUCYmUFAUQEAmJiCQELdmFsdWVPckVsc2UCCQCfCAEJAQJhRAEFAmJ1AAAEAmR0CQBoAgUCYmIAZAQCZFcJAGQCBQJkVgUCZHQEAmRYCQECYkcEBQFPBQJidQUCYkgJAJEDAgUCY1EFAmFWBAJjYggFAmRYAl8xBAJiWggFAmRYAl8yBAJjYQgFAmRYAl8zBAJiSQgFAmRYAl80BAJjYwgFAmRYAl81BAJjbggFAmRYAl82BAJjbwgFAmRYAl83BAJiUwgFAmRYAl84BAJiVAgFAmRYAl85BAJiVggFAmRYA18xMAQCZFkJAQt2YWx1ZU9yRWxzZQIJAJ8IAQkBAmF1AQUCYlMAAAQCZFoJAGUCCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgkBAmFRAQUCYnUFAVYFAmJiBAJlYQMJAGYCBQZoZWlnaHQFAmRZBAJlYgkBBXZhbHVlAQkAnwgBCQECYXEABAJlYwkBBXZhbHVlAQkAnwgBCQECYXkBBQFPBAJlZAkBBXZhbHVlAQkAnwgBCQECYXcBBQFPCQC5CQIJAMwIAgIMJWQlZCVkJWQlZCVkCQDMCAIJAKQDAQUCZFcJAMwIAgkApAMBBQJlYwkAzAgCCQCkAwEFAmVkCQDMCAIJAKQDAQUCY2MJAMwIAgkApAMBBQJjbgkAzAgCCQCkAwEFAmViCQDMCAIJAKQDAQUCZFoFA25pbAUBYwkAuQkCCQDMCAICDCVkJWQlZCVkJWQlZAkAzAgCCQCkAwEFAmRXCQDMCAIJAKQDAQUCY2IJAMwIAgkApAMBBQJiWgkAzAgCCQCkAwEFAmNjCQDMCAIJAKQDAQUCY24JAMwIAgkApAMBBQJjbwkAzAgCCQCkAwEFAmRaBQNuaWwFAWMJAJQKAgUDbmlsBQJlYQECZWUBAmVmAAQCZWcEAWoJAQJjcAADCQABAgUBagIKQnl0ZVZlY3RvcgQCY3UFAWoFAmN1AwkAAQIFAWoCBFVuaXQIBQJlZQ9zZW5kZXJQdWJsaWNLZXkJAAIBAgtNYXRjaCBlcnJvcgkA9AMDCAUCZWUJYm9keUJ5dGVzCQCRAwIIBQJlZQZwcm9vZnMAAAUCZWcQcATg", "height": 3066416, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: 4h8gLRqk1176MfcahPVr6jC9Vc57ZHyyiXfJgJ66q6kL Next: none Full:
OldNewDifferences
11 {-# STDLIB_VERSION 6 #-}
22 {-# SCRIPT_TYPE ACCOUNT #-}
33 {-# CONTENT_TYPE DAPP #-}
44 func getStringOrFail (key) = valueOrErrorMessage(getString(key), (("mandatory this." + key) + " is not defined"))
55
66
77 let SEP = "__"
88
99 let BUFSCALE = toBigInt(1000000000000000000)
1010
1111 let scale8 = 100000000
1212
1313 func throwErr (msg) = throw(makeString(["ido.ride:", msg], " "))
1414
1515
1616 func asString (val) = match val {
1717 case valStr: String =>
1818 valStr
1919 case _ =>
2020 throw("fail to cast into String")
2121 }
2222
2323
2424 func convertPriceAssetIntoIdoAsset (priceAssetAmount,priceAssetMULT,price,priceMULT,idoAssetMULT) = {
2525 let bPriceAssetMULT = toBigInt(priceAssetMULT)
2626 let bIdoAssetMULT = toBigInt(idoAssetMULT)
2727 let bPriceAssetBUF = fraction(toBigInt(priceAssetAmount), BUFSCALE, bPriceAssetMULT)
2828 let bAmountAssetBUF = fraction(bPriceAssetBUF, toBigInt(priceMULT), toBigInt(price))
2929 toInt(fraction(bAmountAssetBUF, toBigInt(idoAssetMULT), BUFSCALE))
3030 }
3131
3232
3333 let IdxCfgIdoStart = 1
3434
3535 let IdxCfgIdoDuration = 2
3636
3737 let IdxCfgClaimStart = 3
3838
3939 let IdxCfgClaimDuration = 4
4040
4141 let IdxCfgPrice = 5
4242
4343 let IdxCfgPriceMult = 6
4444
4545 let IdxCfgIdoAssetId = 7
4646
4747 let IdxCfgIdoAssetMult = 8
4848
4949 let IdxCfgPriceAssetId = 9
5050
5151 let IdxCfgPriceAssetMult = 10
5252
5353 let IdxCfgMinInvestAmount = 11
5454
5555 func fromatConfigS (idoStart,idoDuration,claimStart,claimDuration,price,priceMult,idoAssetId58,idoAssetMult,priceAssetId58,priceAssetMult,minInvestAmount,totalIdoAssetToSell) = makeString(["%d%d%d%d%d%d%s%d%s%d%d%d", idoStart, idoDuration, claimStart, claimDuration, price, priceMult, idoAssetId58, idoAssetMult, priceAssetId58, priceAssetMult, minInvestAmount, totalIdoAssetToSell], SEP)
5656
5757
5858 func fromatConfig (idoStart,idoDuration,claimStart,claimDuration,price,priceMult,idoAssetId58,idoAssetMult,priceAssetId58,priceAssetMult,minInvestAmount,totalIdoAssetToSell) = fromatConfigS(toString(idoStart), toString(idoDuration), toString(claimStart), toString(claimDuration), toString(price), toString(priceMult), idoAssetId58, toString(idoAssetMult), priceAssetId58, toString(priceAssetMult), toString(minInvestAmount), toString(totalIdoAssetToSell))
5959
6060
6161 let IdxInvTotalAmount = 1
6262
6363 let IdxInvRemainingAmount = 2
6464
6565 let IdxInvClaimedPriceAssetAmount = 3
6666
6767 let IdxInvClaimedIdoAssetAmount = 4
6868
6969 let IdxInvLastClaimedHeight = 5
7070
7171 func formatInvestorS (totalAmount,remainingAmount,claimedPriceAssetAmount,claimedIdoAssetAmount,lastClaimedHeight) = makeString(["%d%d%d%d%d", totalAmount, remainingAmount, claimedPriceAssetAmount, claimedIdoAssetAmount, lastClaimedHeight], SEP)
7272
7373
7474 func formatInvestor (totalAmount,remainingAmount,claimedPriceAssetAmount,claimedIdoAssetAmount,lastClaimedHeight) = formatInvestorS(toString(totalAmount), toString(remainingAmount), toString(claimedPriceAssetAmount), toString(claimedIdoAssetAmount), toString(lastClaimedHeight))
7575
7676
7777 func formatHistoryRecord (priceAssetAmount,idoAssetAmount) = makeString(["%d%d%d%d", toString(height), toString(lastBlock.timestamp), toString(priceAssetAmount), toString(idoAssetAmount)], SEP)
7878
7979
8080 func keyConfig () = "%s__config"
8181
8282
8383 func keyInvestor (userAddress) = ("%s__" + userAddress)
8484
8585
8686 func keyTotals () = "%s__totals"
8787
8888
8989 func keyOperationHistoryRecord (type,userAddress,txId58) = makeString(["%s%s%s%s__history", type, userAddress, txId58], SEP)
9090
9191
9292 func keyUSDNClaimDisabled () = "%s__usdnClaimDisabled"
9393
9494
9595 func keyUSDNClaimEndHeight () = "%s__usdnClaimEndHeight"
9696
9797
9898 func keyPeriodLength () = makeString(["%s", "periodLength"], SEP)
9999
100100
101101 func keyCurrentPeriod () = makeString(["%s", "currentPeriod"], SEP)
102102
103103
104104 func keyPeriodStartHeight (periodNum) = makeString(["%s%s", "periodStartHeight", toString(periodNum)], SEP)
105105
106106
107107 func keyPeriodEndHeight (periodNum) = makeString(["%s%s", "periodEndHeight", toString(periodNum)], SEP)
108108
109109
110110 func keyUsdtPriceAssetAllowableRatio () = makeString(["%s", "usdtPriceAssetAllowableRatio"], SEP)
111111
112112
113113 func keyTotalPeriodAllowance (assetId) = makeString(["%s%s", "totalPeriodAllowance", assetId], SEP)
114114
115115
116116 func keyUserPeriodAllowance (assetId) = makeString(["%s%s", "userPeriodAllowance", assetId], SEP)
117117
118118
119119 func keyPeriodTotalAvailableToClaim (assetId,periodNum) = makeString(["%s%s%s", "periodTotalAvailableToClaim", assetId, toString(periodNum)], SEP)
120120
121121
122122 func keyPeriodUserAvailableToClaim (assetId,periodNum,userAddress) = makeString(["%s%s%s%s", "periodUserAvailableToClaim", assetId, toString(periodNum), userAddress], SEP)
123123
124124
125125 func keyUsdtPriceAssetStablePool () = makeString(["%s", "usdtPriceAssetStablePool"], SEP)
126126
127127
128128 func keyUsdtAssetId () = makeString(["%s", "usdtAssetId"], SEP)
129129
130130
131131 func keyPriceAssetBalance (address) = makeString(["%s%s", "priceAssetBalance", address], SEP)
132132
133133
134134 func keyInvestorRemainingAmount (address) = makeString(["%s%s", "investorRemainingAmount", address], SEP)
135135
136136
137137 func keyTotalRemainingAmount () = makeString(["%s", "totalRemainingAmount"], SEP)
138138
139139
140140 func keyManagerPublicKey () = "%s__managerPublicKey"
141141
142142
143143 func keyManagerVaultAddress () = "%s__managerVaultAddress"
144144
145145
146146 func keyClaimClosingHeight () = "%s__claimClosingHeight"
147147
148148
149149 let claimClosingHeight = valueOrElse(getInteger(this, keyClaimClosingHeight()), 0)
150150
151151 func readConfigArray () = split(getStringOrFail(keyConfig()), SEP)
152152
153153
154154 func readTotalsArrayOrDefaultByCustomKey (customKey) = split(valueOrElse(getString(customKey), formatInvestorS("0", "0", "0", "0", "0")), SEP)
155155
156156
157157 func readTotalsArrayOrDefault () = readTotalsArrayOrDefaultByCustomKey(keyTotals())
158158
159159
160160 func readInvestorArrayOrDefault (userAddress) = readTotalsArrayOrDefaultByCustomKey(keyInvestor(userAddress))
161161
162162
163163 func readInvestorArrayOrFail (userAddress) = split(getStringOrFail(keyInvestor(userAddress)), SEP)
164164
165165
166166 func getManagerVaultAddressOrThis () = match getString(keyManagerVaultAddress()) {
167167 case s: String =>
168168 addressFromStringValue(s)
169169 case _ =>
170170 this
171171 }
172172
173173
174174 let IdxDiffTotalIncrement = 0
175175
176176 let IdxDiffRemainingPriceAmountIncrement = 1
177177
178178 let IdxDiffClaimedPriceAmountIncrement = 2
179179
180180 let IdxDiffClaimedIdoAssetAmountIncrement = 3
181181
182182 func TotalsEntry (key,origArray,incrementDiff,newLastClaimedHeight,priceAssetBalance) = {
183183 let totalAmount = parseIntValue(origArray[IdxInvTotalAmount])
184184 let remainingAmount = parseIntValue(origArray[IdxInvRemainingAmount])
185185 let claimedPriceAssetAmount = parseIntValue(origArray[IdxInvClaimedPriceAssetAmount])
186186 let claimedIdoAssetAmount = parseIntValue(origArray[IdxInvClaimedIdoAssetAmount])
187187 let lastClaimedHeight = parseIntValue(origArray[IdxInvLastClaimedHeight])
188188 let newTotalAmount = (totalAmount + incrementDiff[IdxDiffTotalIncrement])
189189 let newRemainingAmount = (remainingAmount + incrementDiff[IdxDiffRemainingPriceAmountIncrement])
190190 let cfgArray = readConfigArray()
191191 let priceAssetId58 = cfgArray[IdxCfgPriceAssetId]
192192 let priceAssetDecimals = value(assetInfo(fromBase58String(priceAssetId58))).decimals
193193 let priceAssetBalancePriceAssetDecimals = fraction(priceAssetBalance, scale8, pow(10, 0, priceAssetDecimals, 0, 0, DOWN))
194194 let newClaimedPriceAssetAmount = ((claimedPriceAssetAmount + incrementDiff[IdxDiffClaimedPriceAmountIncrement]) - priceAssetBalance)
195195 let newClaimedIdoAssetAmount = ((claimedIdoAssetAmount + incrementDiff[IdxDiffClaimedIdoAssetAmountIncrement]) + priceAssetBalancePriceAssetDecimals)
196196 let entries = if ((0 > newRemainingAmount))
197197 then {
198198 let diff = ((newTotalAmount - newClaimedPriceAssetAmount) - newClaimedIdoAssetAmount)
199199 let newLogicRemainingAmount = if ((0 > diff))
200200 then 0
201201 else diff
202202 StringEntry(key, formatInvestor(newTotalAmount, newLogicRemainingAmount, newClaimedPriceAssetAmount, newClaimedIdoAssetAmount, newLastClaimedHeight))
203203 }
204204 else StringEntry(key, formatInvestor(newTotalAmount, newRemainingAmount, newClaimedPriceAssetAmount, newClaimedIdoAssetAmount, newLastClaimedHeight))
205205 entries
206206 }
207207
208208
209209 func InvestOperationHistoryEntry (userAddress,priceAssetAmount,idoAssetAmount,txId) = StringEntry(keyOperationHistoryRecord("invest", userAddress, toBase58String(txId)), formatHistoryRecord(priceAssetAmount, idoAssetAmount))
210210
211211
212212 func ClaimOperationHistoryEntry (userAddress,priceAssetAmount,idoAssetAmount,txId) = StringEntry(keyOperationHistoryRecord("claim", userAddress, toBase58String(txId)), formatHistoryRecord(priceAssetAmount, idoAssetAmount))
213213
214214
215215 func internalClaim (claimedAssetId58,userAddress,txId) = {
216216 let cfgArray = readConfigArray()
217217 let claimStart = parseIntValue(cfgArray[IdxCfgClaimStart])
218218 let claimDuration = parseIntValue(cfgArray[IdxCfgClaimDuration])
219219 let claimEnd = (claimStart + claimDuration)
220220 let price = parseIntValue(cfgArray[IdxCfgPrice])
221221 let priceMult = parseIntValue(cfgArray[IdxCfgPriceMult])
222222 let idoAssetId58 = cfgArray[IdxCfgIdoAssetId]
223223 let idoAssetId = fromBase58String(idoAssetId58)
224224 let idoAssetMult = parseIntValue(cfgArray[IdxCfgIdoAssetMult])
225225 let priceAssetId58 = cfgArray[IdxCfgPriceAssetId]
226226 let priceAssetId = fromBase58String(priceAssetId58)
227227 let priceAssetMult = parseIntValue(cfgArray[IdxCfgPriceAssetMult])
228228 let userAddress58 = toString(userAddress)
229229 let origInvestArray = readInvestorArrayOrFail(userAddress58)
230230 let investTotalAmount = parseIntValue(origInvestArray[IdxInvTotalAmount])
231231 let investLastClaimedHeightTMP = parseIntValue(origInvestArray[IdxInvLastClaimedHeight])
232232 let investLastClaimedHeight = if ((claimStart >= investLastClaimedHeightTMP))
233233 then claimStart
234234 else investLastClaimedHeightTMP
235235 let newClaimPeriodHeight = if ((height > claimEnd))
236236 then claimEnd
237237 else if ((claimStart > height))
238238 then claimStart
239239 else height
240240 let claimingBlocks = (newClaimPeriodHeight - investLastClaimedHeight)
241241 let claimingPriceAssetAmount = fraction(investTotalAmount, claimingBlocks, claimDuration)
242242 let claimingIdoAssetAmount = convertPriceAssetIntoIdoAsset(claimingPriceAssetAmount, priceAssetMult, price, priceMult, idoAssetMult)
243243 let isUSDN = (claimedAssetId58 == priceAssetId58)
244244 let isUSDNClaimDisabled = valueOrElse(getBoolean(keyUSDNClaimDisabled()), false)
245245 let checks = [if (!(if (isUSDN)
246246 then isUSDNClaimDisabled
247247 else false))
248248 then true
249249 else throw("USDN claim is disabled")]
250250 if ((checks == checks))
251251 then if ((claimedAssetId58 == priceAssetId58))
252252 then $Tuple6([0, -(claimingPriceAssetAmount), claimingPriceAssetAmount, 0], claimingPriceAssetAmount, priceAssetId, origInvestArray, newClaimPeriodHeight, [claimingPriceAssetAmount, claimingIdoAssetAmount])
253253 else if ((claimedAssetId58 == idoAssetId58))
254254 then $Tuple6([0, -(claimingPriceAssetAmount), 0, claimingIdoAssetAmount], claimingIdoAssetAmount, idoAssetId, origInvestArray, newClaimPeriodHeight, [claimingPriceAssetAmount, claimingIdoAssetAmount])
255255 else throw(("unsupported assetId: " + claimedAssetId58))
256256 else throw("Strict value is not equal to itself.")
257257 }
258258
259259
260260 func internalClaimV2 (priceAssetId58,userAddress58,outAmount,totalUserAvailableToClaim) = {
261261 let totalPeriodPriceAssetAllowance = value(getInteger(keyTotalPeriodAllowance(priceAssetId58)))
262262 let userPeriodPriceAssetAllowance = value(getInteger(keyUserPeriodAllowance(priceAssetId58)))
263263 let periodLength = value(getInteger(keyPeriodLength()))
264264 let currentPeriod = valueOrElse(getInteger(keyCurrentPeriod()), 0)
265265 let zeroPeriodEndHeighIsDefined = isDefined(getInteger(keyPeriodEndHeight(0)))
266266 let $t01327415144 = if ((currentPeriod > 0))
267267 then {
268268 let lastPeriodStartHeight = value(getInteger(keyPeriodStartHeight(currentPeriod)))
269269 let lastPeriodEndHeight = value(getInteger(keyPeriodEndHeight(currentPeriod)))
270270 let $t01353414239 = if ((height > lastPeriodEndHeight))
271271 then {
272272 let updatedCurrentPeriod = (currentPeriod + 1)
273273 let periodStart = if ((height > (lastPeriodEndHeight + periodLength)))
274274 then {
275275 let blocksToLastPeriodStart = ((height - lastPeriodEndHeight) % periodLength)
276276 if ((blocksToLastPeriodStart == 0))
277277 then ((height - periodLength) + 1)
278278 else (height - blocksToLastPeriodStart)
279279 }
280280 else (lastPeriodEndHeight + 1)
281281 let periodEnd = ((periodStart + periodLength) - 1)
282282 $Tuple3(updatedCurrentPeriod, periodStart, periodEnd)
283283 }
284284 else $Tuple3(currentPeriod, lastPeriodStartHeight, lastPeriodEndHeight)
285285 let updatedCurrentPeriod = $t01353414239._1
286286 let periodStart = $t01353414239._2
287287 let periodEnd = $t01353414239._3
288288 $Tuple3(updatedCurrentPeriod, periodStart, periodEnd)
289289 }
290290 else if (zeroPeriodEndHeighIsDefined)
291291 then {
292292 let zeroPeriodStartHeight = value(getInteger(keyPeriodStartHeight(0)))
293293 let zeroPeriodEndHeight = value(getInteger(keyPeriodEndHeight(0)))
294294 let $t01449414876 = if ((height > zeroPeriodEndHeight))
295295 then {
296296 let updatedCurrentPeriod = (currentPeriod + 1)
297297 let periodStart = (zeroPeriodEndHeight + 1)
298298 let periodEnd = ((periodStart + periodLength) - 1)
299299 $Tuple3(updatedCurrentPeriod, periodStart, periodEnd)
300300 }
301301 else $Tuple3(currentPeriod, zeroPeriodStartHeight, zeroPeriodEndHeight)
302302 let updatedCurrentPeriod = $t01449414876._1
303303 let periodStart = $t01449414876._2
304304 let periodEnd = $t01449414876._3
305305 $Tuple3(updatedCurrentPeriod, periodStart, periodEnd)
306306 }
307307 else $Tuple3(currentPeriod, valueOrElse(getInteger(keyPeriodStartHeight(currentPeriod)), height), valueOrElse(getInteger(keyPeriodEndHeight(currentPeriod)), ((height + periodLength) - 1)))
308308 let updatedCurrentPeriod = $t01327415144._1
309309 let periodStart = $t01327415144._2
310310 let periodEnd = $t01327415144._3
311311 let periodTotalAvailableToClaim = valueOrElse(getInteger(keyPeriodTotalAvailableToClaim(priceAssetId58, updatedCurrentPeriod)), totalPeriodPriceAssetAllowance)
312312 let periodUserAvailableToClaim = valueOrElse(getInteger(keyPeriodUserAvailableToClaim(priceAssetId58, updatedCurrentPeriod, userAddress58)), userPeriodPriceAssetAllowance)
313313 let priceAssetBalance = valueOrElse(getInteger(keyPriceAssetBalance(userAddress58)), 0)
314314 let periodMinAvailableToClaim = min([(outAmount + priceAssetBalance), periodTotalAvailableToClaim, periodUserAvailableToClaim])
315315 let usdtPriceAssetAllowableRatio = value(getInteger(keyUsdtPriceAssetAllowableRatio()))
316316 let putOneTknV2PriceAssetAmount = scale8
317317 let $t01589916152 = {
318318 let @ = invoke(addressFromStringValue(value(getString(keyUsdtPriceAssetStablePool()))), "putOneTknV2WithoutTakeFeeREADONLY", [putOneTknV2PriceAssetAmount, priceAssetId58], nil)
319319 if ($isInstanceOf(@, "(Int, Int, Int)"))
320320 then @
321321 else throw(($getType(@) + " couldn't be cast to (Int, Int, Int)"))
322322 }
323323 if (($t01589916152 == $t01589916152))
324324 then {
325325 let bonus = $t01589916152._3
326326 let feeAmount = $t01589916152._2
327327 let lpAmount = $t01589916152._1
328328 let usdtAssetId = value(getString(keyUsdtAssetId()))
329329 let $t01621416432 = {
330330 let @ = invoke(addressFromStringValue(value(getString(keyUsdtPriceAssetStablePool()))), "getOneTknV2READONLY", [usdtAssetId, lpAmount], nil)
331331 if ($isInstanceOf(@, "(Int, Int)"))
332332 then @
333333 else throw(($getType(@) + " couldn't be cast to (Int, Int)"))
334334 }
335335 if (($t01621416432 == $t01621416432))
336336 then {
337337 let getOneTknV2FeeAmount = $t01621416432._2
338338 let usdtAmount = $t01621416432._1
339339 let currentUsdtPriceAssetRatio = fraction(putOneTknV2PriceAssetAmount, scale8, usdtAmount)
340340 let endPeriodBlocksLeft = (periodEnd - height)
341341 $Tuple10(periodMinAvailableToClaim, periodTotalAvailableToClaim, periodUserAvailableToClaim, totalUserAvailableToClaim, usdtPriceAssetAllowableRatio, currentUsdtPriceAssetRatio, endPeriodBlocksLeft, updatedCurrentPeriod, periodStart, periodEnd)
342342 }
343343 else throw("Strict value is not equal to itself.")
344344 }
345345 else throw("Strict value is not equal to itself.")
346346 }
347347
348348
349349 func managerPublicKeyOrUnit () = {
350350 let managerVaultAddress = getManagerVaultAddressOrThis()
351351 match getString(managerVaultAddress, keyManagerPublicKey()) {
352352 case s: String =>
353353 fromBase58String(s)
354354 case _: Unit =>
355355 unit
356356 case _ =>
357357 throw("Match error")
358358 }
359359 }
360360
361361
362362 func mustManager (i) = {
363363 let pd = throw("Permission denied")
364364 match managerPublicKeyOrUnit() {
365365 case pk: ByteVector =>
366366 if ((i.callerPublicKey == pk))
367367 then true
368368 else pd
369369 case _: Unit =>
370370 if ((i.caller == this))
371371 then true
372372 else pd
373373 case _ =>
374374 throw("Match error")
375375 }
376376 }
377377
378378
379379 func getClaimForActions (userAddress58,txId) = {
380380 let idoAssetId58 = readConfigArray()[IdxCfgIdoAssetId]
381381 let fallback = makeString(["%d%d%d%d%d", "0", "0", "0", "0", "0"], SEP)
382382 let investor = split(valueOrElse(getString(keyInvestor(userAddress58)), fallback), SEP)
383383 let investorTotalAmount = parseIntValue(investor[IdxInvTotalAmount])
384384 let investorRemainingAmount = parseIntValue(investor[IdxInvRemainingAmount])
385385 let investorPriceAssetBalance = parseIntValue(investor[IdxInvClaimedPriceAssetAmount])
386386 let investorIdoAssetBalance = parseIntValue(investor[IdxInvClaimedIdoAssetAmount])
387387 let investorLastClaimedHeight = parseIntValue(investor[IdxInvLastClaimedHeight])
388388 let priceAssetAmount = valueOrElse(getInteger(keyPriceAssetBalance(userAddress58)), 0)
389389 let priceAssetActions = if ((priceAssetAmount != 0))
390390 then [IntegerEntry(keyPriceAssetBalance(userAddress58), 0)]
391391 else nil
392392 let investorKeyRemainingAmount = parseIntValue(valueOrElse(getString(keyInvestorRemainingAmount(userAddress58)), "0"))
393393 let investorKeyRemainingActions = if ((investorKeyRemainingAmount != 0))
394394 then [StringEntry(keyInvestorRemainingAmount(userAddress58), "0")]
395395 else nil
396396 let totalIdoAssetSendAmount = (((investorRemainingAmount + priceAssetAmount) + investorKeyRemainingAmount) * 100)
397397 let totalIdoAssetForInvestorData = ((investorRemainingAmount + investorKeyRemainingAmount) * 100)
398398 let newInvestor = makeString(["%d%d%d%d%d", toString(investorTotalAmount), "0", toString(investorPriceAssetBalance), toString((investorIdoAssetBalance + totalIdoAssetForInvestorData)), toString(height)], SEP)
399399 let investorDataActions = if ((totalIdoAssetForInvestorData != 0))
400400 then [StringEntry(keyInvestor(userAddress58), newInvestor)]
401401 else nil
402402 let sendIdoAssetActions = if ((totalIdoAssetSendAmount != 0))
403403 then [ScriptTransfer(addressFromStringValue(userAddress58), totalIdoAssetSendAmount, fromBase58String(idoAssetId58)), ClaimOperationHistoryEntry(userAddress58, 0, totalIdoAssetSendAmount, txId)]
404404 else nil
405405 $Tuple4(investorRemainingAmount, priceAssetAmount, investorKeyRemainingAmount, (((sendIdoAssetActions ++ investorDataActions) ++ investorKeyRemainingActions) ++ priceAssetActions))
406406 }
407407
408408
409409 @Callable(i)
410410 func constructor (idoStart,idoDuration,claimStart,claimDuration,price,priceAssetId58,minInvestAmount) = {
411411 let priceMult = ((100 * 1000) * 1000)
412412 let idoEnd = (idoStart + idoDuration)
413413 if (isDefined(getString(keyConfig())))
414414 then throw("already initialized")
415415 else if (("3PMEHLx1j6zerarZTYfsGqDeeZqQoMpxq5S" != toString(i.caller)))
416416 then throw("not authorized")
417417 else if ((size(i.payments) != 1))
418418 then throw("exactly 1 payment must be attached")
419419 else if ((idoEnd >= claimStart))
420420 then throw("claimStart must be greater than idoEnd")
421421 else {
422422 let pmt = value(i.payments[0])
423423 let idoAssetId = value(pmt.assetId)
424424 let idoAssetInfo = valueOrErrorMessage(assetInfo(idoAssetId), "fail to load ido asset info")
425425 let idoAssetId58 = toBase58String(idoAssetId)
426426 let idoAssetMult = pow(10, 0, idoAssetInfo.decimals, 0, 0, DOWN)
427427 let priceAssetId = fromBase58String(priceAssetId58)
428428 let priceAssetInfo = valueOrErrorMessage(assetInfo(priceAssetId), "fail to load price asset info")
429429 let priceAssetMult = pow(10, 0, priceAssetInfo.decimals, 0, 0, DOWN)
430430 let origTotalsArray = readTotalsArrayOrDefault()
431431 let totalsDiff = [0, 0, 0, 0]
432432 [StringEntry(keyConfig(), fromatConfig(idoStart, idoDuration, claimStart, claimDuration, price, priceMult, idoAssetId58, idoAssetMult, priceAssetId58, priceAssetMult, minInvestAmount, pmt.amount)), TotalsEntry(keyTotals(), origTotalsArray, totalsDiff, claimStart, 0)]
433433 }
434434 }
435435
436436
437437
438438 @Callable(i)
439439 func invest () = {
440440 let cfgArray = readConfigArray()
441441 let idoStart = parseIntValue(cfgArray[IdxCfgIdoStart])
442442 let idoDuration = parseIntValue(cfgArray[IdxCfgIdoDuration])
443443 let idoEnd = (idoStart + idoDuration)
444444 let claimStart = parseIntValue(cfgArray[IdxCfgClaimStart])
445445 let claimDuration = parseIntValue(cfgArray[IdxCfgClaimDuration])
446446 let price = parseIntValue(cfgArray[IdxCfgPrice])
447447 let priceMult = parseIntValue(cfgArray[IdxCfgPriceMult])
448448 let idoAssetId58 = cfgArray[IdxCfgIdoAssetId]
449449 let idoAssetId = fromBase58String(idoAssetId58)
450450 let idoAssetMult = parseIntValue(cfgArray[IdxCfgIdoAssetMult])
451451 let priceAssetId58 = cfgArray[IdxCfgPriceAssetId]
452452 let priceAssetId = fromBase58String(priceAssetId58)
453453 let priceAssetMult = parseIntValue(cfgArray[IdxCfgPriceAssetMult])
454454 let minIvestAmount = parseIntValue(cfgArray[IdxCfgMinInvestAmount])
455455 let userAddress = toString(i.caller)
456456 if ((idoStart > height))
457457 then throw("ido has not been started yet")
458458 else if ((height > idoEnd))
459459 then throw("ido has been already ended")
460460 else if ((size(i.payments) != 1))
461461 then throw("exactly 1 payment is expected")
462462 else {
463463 let pmt = value(i.payments[0])
464464 let pmtAssetId = value(pmt.assetId)
465465 let pmtAmount = pmt.amount
466466 if ((pmtAssetId != priceAssetId))
467467 then throw((("invalid payment asset id: " + toBase58String(pmtAssetId)) + " is expected"))
468468 else {
469469 let origInvestorArray = readInvestorArrayOrDefault(userAddress)
470470 let origTotalsArray = readTotalsArrayOrDefault()
471471 let newPriceTotalAmount = (parseIntValue(origTotalsArray[IdxInvTotalAmount]) + pmtAmount)
472472 let requiredIdoAssetAmount = (newPriceTotalAmount * 100)
473473 if ((requiredIdoAssetAmount > assetBalance(this, idoAssetId)))
474474 then throw("IDO asset has been - sold consider to use smaller payment")
475475 else {
476476 let totalsDiff = [pmtAmount, pmtAmount, 0, 0]
477477 [TotalsEntry(keyInvestor(userAddress), origInvestorArray, totalsDiff, claimStart, 0), TotalsEntry(keyTotals(), origTotalsArray, totalsDiff, claimStart, 0), InvestOperationHistoryEntry(userAddress, pmtAmount, 0, i.transactionId)]
478478 }
479479 }
480480 }
481481 }
482482
483483
484484
485485 @Callable(i)
486486 func claim (claimedAssetId58,userAddress58) = {
487487 let callerAddress58 = toString(i.caller)
488488 if ((userAddress58 != callerAddress58))
489489 then throw("not authorized")
490490 else {
491491 let cfgArray = readConfigArray()
492492 let priceAssetId58 = cfgArray[IdxCfgPriceAssetId]
493493 let claimResultTuple = internalClaim(claimedAssetId58, i.caller, i.transactionId)
494494 let totalsDiff = claimResultTuple._1
495495 let outAmount = claimResultTuple._2
496496 let outAssetId = claimResultTuple._3
497497 let origInvestArray = claimResultTuple._4
498498 let newClaimPeriodHeight = claimResultTuple._5
499499 let claimedPriceAmountFromDiff = totalsDiff[IdxDiffClaimedPriceAmountIncrement]
500500 let claimedIdoAssetAmountFromDiff = totalsDiff[IdxDiffClaimedIdoAssetAmountIncrement]
501501 let priceAssetBalance = valueOrElse(getInteger(keyPriceAssetBalance(userAddress58)), 0)
502502 let priceAssetDecimals = value(assetInfo(fromBase58String(priceAssetId58))).decimals
503503 let entries = if ((claimedAssetId58 == priceAssetId58))
504504 then {
505505 let $t02456225006 = internalClaimV2(priceAssetId58, userAddress58, outAmount, totalsDiff[IdxDiffClaimedPriceAmountIncrement])
506506 let periodMinAvailableToClaim = $t02456225006._1
507507 let periodTotalAvailableToClaim = $t02456225006._2
508508 let periodUserAvailableToClaim = $t02456225006._3
509509 let totalUserAvailableToClaim = $t02456225006._4
510510 let usdtPriceAssetAllowableRatio = $t02456225006._5
511511 let currentUsdtPriceAssetRatio = $t02456225006._6
512512 let endPeriodBlocksLeft = $t02456225006._7
513513 let updatedCurrentPeriod = $t02456225006._8
514514 let periodStart = $t02456225006._9
515515 let periodEnd = $t02456225006._10
516516 let checks = [if ((periodUserAvailableToClaim > 0))
517517 then true
518518 else throwErr("unavailable to claim because user period allowance reached"), if ((periodTotalAvailableToClaim > 0))
519519 then true
520520 else throwErr("unavailable to claim because total period allowance reached"), if ((periodMinAvailableToClaim > 0))
521521 then true
522522 else throwErr("nothing to claim"), if ((usdtPriceAssetAllowableRatio > currentUsdtPriceAssetRatio))
523523 then true
524524 else throwErr("unavailable to claim because usdn price lower than usdtPriceAssetAllowableRatio"), if (if (if ((claimedAssetId58 != priceAssetId58))
525525 then true
526526 else (claimClosingHeight == 0))
527527 then true
528528 else (claimClosingHeight > height))
529529 then true
530530 else throwErr("Claim is disabled")]
531531 if ((checks == checks))
532532 then {
533533 let updatedPeriodTotalAvailableToClaim = (periodTotalAvailableToClaim - periodMinAvailableToClaim)
534534 let updatedPeriodUserAvailableToClaim = (periodUserAvailableToClaim - periodMinAvailableToClaim)
535535 let entries = if ((priceAssetBalance > periodMinAvailableToClaim))
536536 then [ScriptTransfer(i.caller, periodMinAvailableToClaim, outAssetId), IntegerEntry(keyPriceAssetBalance(userAddress58), (priceAssetBalance - periodMinAvailableToClaim))]
537537 else {
538538 let evaluateResult = split(asString(invoke(this, "claimREADONLY", [priceAssetId58, userAddress58], nil)), SEP)
539539 if ((evaluateResult == evaluateResult))
540540 then {
541541 let availablePriceAmountToClaim = parseIntValue(evaluateResult[3])
542542 let lastClaimEntries = if ((availablePriceAmountToClaim == periodMinAvailableToClaim))
543543 then {
544544 let investorTotalAmount = parseIntValue(origInvestArray[IdxInvTotalAmount])
545545 let investorRemainingAmount = parseIntValue(origInvestArray[IdxInvRemainingAmount])
546546 let investorPriceAssetBalance = parseIntValue(origInvestArray[IdxInvClaimedPriceAssetAmount])
547547 let investorIdoAssetBalance = parseIntValue(origInvestArray[IdxInvClaimedIdoAssetAmount])
548548 let investorLastClaimedHeight = parseIntValue(origInvestArray[IdxInvLastClaimedHeight])
549549 let newInvestArray = [toString(investorTotalAmount), "0", toString(investorPriceAssetBalance), toString(investorIdoAssetBalance), toString(investorLastClaimedHeight)]
550550 let totals = readTotalsArrayOrDefault()
551551 let totalsTotalAmount = parseIntValue(totals[IdxInvTotalAmount])
552552 let totalsRemainingAmount = parseIntValue(totals[IdxInvRemainingAmount])
553553 let totalsClaimedPriceAssetAmount = parseIntValue(totals[IdxInvClaimedPriceAssetAmount])
554554 let totalsClaimedIdoAssetAmount = parseIntValue(totals[IdxInvClaimedIdoAssetAmount])
555555 let totalsLastClaimedHeight = parseIntValue(totals[IdxInvLastClaimedHeight])
556556 let newTotalsRemainingAmount = (totalsRemainingAmount - investorRemainingAmount)
557557 let newTotalArray = [toString(totalsTotalAmount), toString(newTotalsRemainingAmount), toString(totalsClaimedPriceAssetAmount), toString(totalsClaimedIdoAssetAmount), toString(totalsLastClaimedHeight)]
558558 let newTotalRemainingAmount = (valueOrElse(getInteger(keyTotalRemainingAmount()), 0) + investorRemainingAmount)
559559 [StringEntry(keyInvestorRemainingAmount(userAddress58), toString(investorRemainingAmount)), StringEntry(keyTotalRemainingAmount(), toString(newTotalRemainingAmount)), TotalsEntry(keyInvestor(userAddress58), newInvestArray, totalsDiff, newClaimPeriodHeight, 0), TotalsEntry(keyTotals(), newTotalArray, totalsDiff, newClaimPeriodHeight, 0)]
560560 }
561561 else [TotalsEntry(keyInvestor(userAddress58), origInvestArray, totalsDiff, newClaimPeriodHeight, 0), TotalsEntry(keyTotals(), readTotalsArrayOrDefault(), totalsDiff, newClaimPeriodHeight, 0)]
562562 let updatedPriceAssetBalance = ((priceAssetBalance + outAmount) - periodMinAvailableToClaim)
563563 ([ScriptTransfer(i.caller, periodMinAvailableToClaim, outAssetId), IntegerEntry(keyPriceAssetBalance(userAddress58), updatedPriceAssetBalance)] ++ lastClaimEntries)
564564 }
565565 else throw("Strict value is not equal to itself.")
566566 }
567567 $Tuple2(([IntegerEntry(keyCurrentPeriod(), updatedCurrentPeriod), IntegerEntry(keyPeriodStartHeight(updatedCurrentPeriod), periodStart), IntegerEntry(keyPeriodEndHeight(updatedCurrentPeriod), periodEnd), IntegerEntry(keyPeriodTotalAvailableToClaim(priceAssetId58, updatedCurrentPeriod), updatedPeriodTotalAvailableToClaim), IntegerEntry(keyPeriodUserAvailableToClaim(priceAssetId58, updatedCurrentPeriod, userAddress58), updatedPeriodUserAvailableToClaim), ClaimOperationHistoryEntry(userAddress58, periodMinAvailableToClaim, claimedIdoAssetAmountFromDiff, i.transactionId)] ++ entries), unit)
568568 }
569569 else throw("Strict value is not equal to itself.")
570570 }
571571 else {
572572 let priceAssetBalanceIdoDecimals = fraction(priceAssetBalance, scale8, pow(10, 0, priceAssetDecimals, 0, 0, DOWN))
573573 $Tuple2([ScriptTransfer(i.caller, (outAmount + priceAssetBalanceIdoDecimals), outAssetId), IntegerEntry(keyPriceAssetBalance(userAddress58), 0), TotalsEntry(keyInvestor(userAddress58), origInvestArray, totalsDiff, newClaimPeriodHeight, priceAssetBalance), TotalsEntry(keyTotals(), readTotalsArrayOrDefault(), totalsDiff, newClaimPeriodHeight, priceAssetBalance), ClaimOperationHistoryEntry(userAddress58, claimedPriceAmountFromDiff, (claimedIdoAssetAmountFromDiff + priceAssetBalanceIdoDecimals), i.transactionId)], unit)
574574 }
575575 entries
576576 }
577577 }
578578
579579
580580
581581 @Callable(i)
582582 func cleanRemaingAmount (userAddress58) = {
583583 let priceAssetId58 = readConfigArray()[IdxCfgPriceAssetId]
584584 let evaluateResult = split(asString(invoke(this, "claimREADONLY", [priceAssetId58, userAddress58], nil)), SEP)
585585 if ((evaluateResult == evaluateResult))
586586 then {
587587 let availablePriceAmountToClaim = parseIntValue(evaluateResult[2])
588588 let checkUnclaimedAssets = if ((availablePriceAmountToClaim == 0))
589589 then true
590590 else throwErr("user have unclaimed assets")
591591 if ((checkUnclaimedAssets == checkUnclaimedAssets))
592592 then {
593593 let investor = split(value(getString(keyInvestor(userAddress58))), SEP)
594594 let investorTotalAmount = parseIntValue(investor[IdxInvTotalAmount])
595595 let investorRemainingAmount = parseIntValue(investor[IdxInvRemainingAmount])
596596 let investorPriceAssetBalance = parseIntValue(investor[IdxInvClaimedPriceAssetAmount])
597597 let investorIdoAssetBalance = parseIntValue(investor[IdxInvClaimedIdoAssetAmount])
598598 let investorLastClaimedHeight = parseIntValue(investor[IdxInvLastClaimedHeight])
599599 let investorRemainingAmountCheck = if ((investorRemainingAmount != 0))
600600 then true
601601 else throwErr("investorRemainingAmount already zero")
602602 if ((investorRemainingAmountCheck == investorRemainingAmountCheck))
603603 then {
604604 let newInvestor = makeString(["%d%d%d%d%d", toString(investorTotalAmount), "0", toString(investorPriceAssetBalance), toString(investorIdoAssetBalance), toString(investorLastClaimedHeight)], SEP)
605605 let totals = split(value(getString(keyTotals())), SEP)
606606 let totalsTotalAmount = parseIntValue(totals[IdxInvTotalAmount])
607607 let totalsRemainingAmount = parseIntValue(totals[IdxInvRemainingAmount])
608608 let totalsClaimedPriceAssetAmount = parseIntValue(totals[IdxInvClaimedPriceAssetAmount])
609609 let totalsClaimedIdoAssetAmount = parseIntValue(totals[IdxInvClaimedIdoAssetAmount])
610610 let totalsLastClaimedHeight = parseIntValue(totals[IdxInvLastClaimedHeight])
611611 let newTotals = makeString(["%d%d%d%d%d", toString(totalsTotalAmount), toString((totalsRemainingAmount - investorRemainingAmount)), toString(totalsClaimedPriceAssetAmount), toString(totalsClaimedIdoAssetAmount), toString(totalsLastClaimedHeight)], SEP)
612612 let newTotalRemainingAmount = (valueOrElse(getInteger(keyTotalRemainingAmount()), 0) + investorRemainingAmount)
613613 [StringEntry(keyInvestorRemainingAmount(userAddress58), toString(investorRemainingAmount)), StringEntry(keyTotalRemainingAmount(), toString(newTotalRemainingAmount)), StringEntry(keyInvestor(userAddress58), newInvestor), StringEntry(keyTotals(), newTotals)]
614614 }
615615 else throw("Strict value is not equal to itself.")
616616 }
617617 else throw("Strict value is not equal to itself.")
618618 }
619619 else throw("Strict value is not equal to itself.")
620620 }
621621
622622
623623
624624 @Callable(i)
625625 func claimFor (userList) = {
626626 func helper (acc,user) = {
627627 let $t03474534787 = acc
628628 let allActions = $t03474534787._1
629629 let totalSum = $t03474534787._2
630630 let addrList = $t03474534787._3
631631 let $t03479234924 = getClaimForActions(user, i.transactionId)
632632 let investorRemainingAmount = $t03479234924._1
633633 let priceAssetAmount = $t03479234924._2
634634 let investorKeyRemainingAmount = $t03479234924._3
635635 let userActions = $t03479234924._4
636636 let addSum = (investorRemainingAmount + investorKeyRemainingAmount)
637637 let ch = if (!(containsElement(addrList, user)))
638638 then true
639639 else throwErr("duplicate address in list")
640640 if ((ch == ch))
641641 then $Tuple3((allActions ++ userActions), (totalSum + addSum), (addrList :+ user))
642642 else throw("Strict value is not equal to itself.")
643643 }
644644
645645 let $t03516235229 = {
646646 let $l = userList
647647 let $s = size($l)
648648 let $acc0 = $Tuple3(nil, 0, nil)
649649 func $f0_1 ($a,$i) = if (($i >= $s))
650650 then $a
651651 else helper($a, $l[$i])
652652
653653 func $f0_2 ($a,$i) = if (($i >= $s))
654654 then $a
655655 else throw("List size exceeds 19")
656656
657657 $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($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), 11), 12), 13), 14), 15), 16), 17), 18), 19)
658658 }
659659 let allActions = $t03516235229._1
660660 let sum = $t03516235229._2
661661 let _a = $t03516235229._3
662662 let totalsAction = if ((sum != 0))
663663 then [TotalsEntry(keyTotals(), readTotalsArrayOrDefault(), [0, -(sum), 0, sum], height, 0)]
664664 else nil
665665 (allActions ++ totalsAction)
666666 }
667667
668668
669669
670670 @Callable(i)
671671 func claimREADONLY (claimedAssetId58,userAddress58) = {
672672 let claimResultTuple = internalClaim(claimedAssetId58, addressFromStringValue(userAddress58), fromBase58String(""))
673673 let totalsDiff = claimResultTuple._1
674674 let outAmount = claimResultTuple._2
675675 let outAssetId = claimResultTuple._3
676676 let origInvestArray = claimResultTuple._4
677677 let newClaimPeriodHeight = claimResultTuple._5
678678 let availableToClaimArray = claimResultTuple._6
679679 let availablePriceAmountToClaim = availableToClaimArray[0]
680680 let availableIdoAmountToClaim = availableToClaimArray[1]
681681 $Tuple2(nil, makeString(["%s%d%d", userAddress58, toString(availablePriceAmountToClaim), toString(availableIdoAmountToClaim)], SEP))
682682 }
683683
684684
685685
686686 @Callable(i)
687687 func claimV2READONLY (claimedAssetId58,userAddress58) = {
688688 let claimResultTuple = internalClaim(claimedAssetId58, addressFromStringValue(userAddress58), fromBase58String(""))
689689 let totalsDiff = claimResultTuple._1
690690 let outAmount = claimResultTuple._2
691691 let outAssetId = claimResultTuple._3
692692 let origInvestArray = claimResultTuple._4
693693 let newClaimPeriodHeight = claimResultTuple._5
694694 let availableToClaimArray = claimResultTuple._6
695695 let availablePriceAmountToClaim = availableToClaimArray[0]
696696 let availableIdoAmountToClaim = availableToClaimArray[1]
697697 let cfgArray = readConfigArray()
698698 let priceAssetId58 = cfgArray[IdxCfgPriceAssetId]
699699 let priceAssetBalance = valueOrElse(getInteger(keyPriceAssetBalance(userAddress58)), 0)
700700 let priceAssetBalanceIdoDecimals = (priceAssetBalance * 100)
701701 let availableIdoAmountToClaimWithPriceAssetBalance = (availableIdoAmountToClaim + priceAssetBalanceIdoDecimals)
702702 let $t03719137603 = internalClaimV2(priceAssetId58, userAddress58, outAmount, totalsDiff[IdxDiffClaimedPriceAmountIncrement])
703703 let periodMinAvailableToClaim = $t03719137603._1
704704 let periodTotalAvailableToClaim = $t03719137603._2
705705 let periodUserAvailableToClaim = $t03719137603._3
706706 let totalUserAvailableToClaim = $t03719137603._4
707707 let usdtPriceAssetAllowableRatio = $t03719137603._5
708708 let currentUsdtPriceAssetRatio = $t03719137603._6
709709 let endPeriodBlocksLeft = $t03719137603._7
710710 let updatedCurrentPeriod = $t03719137603._8
711711 let periodStart = $t03719137603._9
712712 let periodEnd = $t03719137603._10
713713 let currentPeriodEndHeight = valueOrElse(getInteger(keyPeriodEndHeight(updatedCurrentPeriod)), 0)
714714 let userTotalPriceAssetClaimed = (parseIntValue(readInvestorArrayOrFail(userAddress58)[IdxInvClaimedPriceAssetAmount]) - priceAssetBalance)
715715 let resultString = if ((height > currentPeriodEndHeight))
716716 then {
717717 let periodLenght = value(getInteger(keyPeriodLength()))
718718 let userPeriodAllowance = value(getInteger(keyUserPeriodAllowance(priceAssetId58)))
719719 let totalPeriodAllowance = value(getInteger(keyTotalPeriodAllowance(priceAssetId58)))
720720 makeString(["%d%d%d%d%d%d", toString(availableIdoAmountToClaimWithPriceAssetBalance), toString(userPeriodAllowance), toString(totalPeriodAllowance), toString(usdtPriceAssetAllowableRatio), toString(currentUsdtPriceAssetRatio), toString(periodLenght), toString(userTotalPriceAssetClaimed)], SEP)
721721 }
722722 else makeString(["%d%d%d%d%d%d", toString(availableIdoAmountToClaimWithPriceAssetBalance), toString(periodMinAvailableToClaim), toString(periodTotalAvailableToClaim), toString(usdtPriceAssetAllowableRatio), toString(currentUsdtPriceAssetRatio), toString(endPeriodBlocksLeft), toString(userTotalPriceAssetClaimed)], SEP)
723723 $Tuple2(nil, resultString)
724724 }
725725
726726
727727 @Verifier(tx)
728728 func verify () = {
729729 let targetPublicKey = match managerPublicKeyOrUnit() {
730730 case pk: ByteVector =>
731731 pk
732732 case _: Unit =>
733733 tx.senderPublicKey
734734 case _ =>
735735 throw("Match error")
736736 }
737737 sigVerify(tx.bodyBytes, tx.proofs[0], targetPublicKey)
738738 }
739739

github/deemru/w8io/786bc32 
71.60 ms