tx · Gs9RGRoENsG9EAY85ErKQ4cG5LnaPz33754fHbqqCp1J

3MsXpzisJAwnzUr7XrEoW1BZo4U6rw4tsYK:  -0.05000000 Waves

2022.10.25 17:43 [2288049] smart account 3MsXpzisJAwnzUr7XrEoW1BZo4U6rw4tsYK > SELF 0.00000000 Waves

{ "type": 13, "id": "Gs9RGRoENsG9EAY85ErKQ4cG5LnaPz33754fHbqqCp1J", "fee": 5000000, "feeAssetId": null, "timestamp": 1666708980056, "version": 2, "chainId": 84, "sender": "3MsXpzisJAwnzUr7XrEoW1BZo4U6rw4tsYK", "senderPublicKey": "FFdBua5rzzMkZebvsvmN7sAdU7XhFK8QNJ3hiwwxAYRA", "proofs": [ "3e6hUXtZ8z4du4zqJjwee4cM9QpjK4vWW48VxHsK2n4ihawa194HUzJfUdLWFoCyhnT64GmNmywSu8NecSw5WK45", "4rEyTSAMZ9EHJoo3Z49koF9xNxXnpoGb1svCZHt8wPNqAC5QoPd7vpkYaywsfncXBAhJZbZqK8mj9ogrUuSya6Vv" ], "script": "base64:BgJmCAISBAoCEQESBQoDCAEBEgUKAwEEARIECgIRCBIDCgEBEgYKBAgIAQgSBAoCCAESAwoBERIECgIRARIFCgMBCAgSBAoCCAESBQoDCAEBEgASABIECgIRBBIECgIBARIAEgASABIAWAAJUFJFQ0lTSU9OAMCEPQAFTUFYX0EAwIQ9AAxNQVhfQV9DSEFOR0UACgAIREVDSU1BTFMABgANTUlOX1JBTVBfVElNRQkAaQIAgKMFADwAB3ZlcnNpb24CBTMuMC4wAAhrVmVyc2lvbgIHdmVyc2lvbgAHa0Fzc2V0cwIJYXNzZXRfaWRzAA1rQXNzZXRCYWxhbmNlAghfYmFsYW5jZQAHa0FjdGl2ZQIGYWN0aXZlAAZrQ2F1c2UCDnNodXRkb3duX2NhdXNlAA1rU2hhcmVBc3NldElkAg5zaGFyZV9hc3NldF9pZAARa1NoYXJlQXNzZXRTdXBwbHkCEnNoYXJlX2Fzc2V0X3N1cHBseQAEa0ZlZQIKY29tbWlzc2lvbgASa0RBcHBUaHJlc2hvbGRDb2VmAhFkQXBwVGhyZXNob2xkQ29lZgAMa1VTRE5BZGRyZXNzAhhzdGFraW5nX3VzZG5uc2J0X2FkZHJlc3MACmtEaXNjb3VudHMCCWRpc2NvdW50cwAPa0Rpc2NvdW50VmFsdWVzAg9kaXNjb3VudF92YWx1ZXMADmtVc2VyU3dvcEluR292AgxfU1dPUF9hbW91bnQAD2tVc2VyR1N3b3BJbkdvdgINX0dTd29wX2Ftb3VudAANa0FkbWluUHViS2V5MQILYWRtaW5fcHViXzEADWtBZG1pblB1YktleTICC2FkbWluX3B1Yl8yAA1rQWRtaW5QdWJLZXkzAgthZG1pbl9wdWJfMwASa0FkbWluSW52b2tlUHViS2V5AhBhZG1pbl9pbnZva2VfcHViABBrTW9uZXlCb3hBZGRyZXNzAhFtb25leV9ib3hfYWRkcmVzcwALa0dvdkFkZHJlc3MCEmdvdmVybmFuY2VfYWRkcmVzcwAOa1ZvdGluZ0FkZHJlc3MCDnZvdGluZ19hZGRyZXNzAA9rRmFybWluZ0FkZHJlc3MCD2Zhcm1pbmdfYWRkcmVzcwARa0xQRmFybWluZ0FkZHJlc3MCCmxwX2Zhcm1pbmcABm9yYWNsZQkBB0FkZHJlc3MBARoBVEgTlwzA0zPMJTKAtin3p2RogKvjzHtLmQETZ2V0QmFzZTU4RnJvbU9yYWNsZQEDa2V5BAckbWF0Y2gwCQCdCAIFBm9yYWNsZQUDa2V5AwkAAQIFByRtYXRjaDACBlN0cmluZwQGc3RyaW5nBQckbWF0Y2gwCQDZBAEFBnN0cmluZwQHbm90aGluZwUHJG1hdGNoMAkAAgEJAKwCAgUDa2V5AghpcyBlbXB0eQAMYWRtaW5QdWJLZXkxCQETZ2V0QmFzZTU4RnJvbU9yYWNsZQEFDWtBZG1pblB1YktleTEADGFkbWluUHViS2V5MgkBE2dldEJhc2U1OEZyb21PcmFjbGUBBQ1rQWRtaW5QdWJLZXkyAAxhZG1pblB1YktleTMJARNnZXRCYXNlNThGcm9tT3JhY2xlAQUNa0FkbWluUHViS2V5MwARYWRtaW5QdWJLZXlJbnZva2UJARNnZXRCYXNlNThGcm9tT3JhY2xlAQUSa0FkbWluSW52b2tlUHViS2V5AA9tb25leUJveEFkZHJlc3MJAQdBZGRyZXNzAQkBE2dldEJhc2U1OEZyb21PcmFjbGUBBRBrTW9uZXlCb3hBZGRyZXNzAApnb3ZBZGRyZXNzCQEHQWRkcmVzcwEJARNnZXRCYXNlNThGcm9tT3JhY2xlAQULa0dvdkFkZHJlc3MAEnN0YWtpbmdVU0ROQWRkcmVzcwkBB0FkZHJlc3MBCQETZ2V0QmFzZTU4RnJvbU9yYWNsZQEFDGtVU0ROQWRkcmVzcwANdm90aW5nQWRkcmVzcwkBB0FkZHJlc3MBCQETZ2V0QmFzZTU4RnJvbU9yYWNsZQEFDmtWb3RpbmdBZGRyZXNzAA5mYXJtaW5nQWRkcmVzcwkBB0FkZHJlc3MBCQETZ2V0QmFzZTU4RnJvbU9yYWNsZQEFD2tGYXJtaW5nQWRkcmVzcwAQbHBGYXJtaW5nQWRkcmVzcwkBB0FkZHJlc3MBCQETZ2V0QmFzZTU4RnJvbU9yYWNsZQEFEWtMUEZhcm1pbmdBZGRyZXNzAARVU0ROASC2JinDBPXOU5GkDkt1JC9kjFGx+t+vVCm9SNIdKrKq0QANc3Rha2luZ0Fzc2V0cwkAzAgCCQDYBAEFBFVTRE4FA25pbAAGYWN0aXZlCQERQGV4dHJOYXRpdmUoMTA1MSkCBQR0aGlzBQdrQWN0aXZlAAxzaGFyZUFzc2V0SWQJANkEAQkBEUBleHRyTmF0aXZlKDEwNTMpAgUEdGhpcwUNa1NoYXJlQXNzZXRJZAALc2hhcmVTdXBwbHkJARFAZXh0ck5hdGl2ZSgxMDUwKQIFBHRoaXMFEWtTaGFyZUFzc2V0U3VwcGx5AAlmZWVTY2FsZTYAwIQ9AANmZWUJARFAZXh0ck5hdGl2ZSgxMDUwKQIFBHRoaXMFBGtGZWUADWZlZUdvdmVybmFuY2UJAGsDACgFCWZlZVNjYWxlNgBkAAlpbml0aWFsX0EJARFAZXh0ck5hdGl2ZSgxMDUwKQIFBHRoaXMCCWluaXRpYWxfQQAIZnV0dXJlX0EJARFAZXh0ck5hdGl2ZSgxMDUwKQIFBHRoaXMCCGZ1dHVyZV9BAA5pbml0aWFsX0FfdGltZQkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzAg5pbml0aWFsX0FfdGltZQAAAA1mdXR1cmVfQV90aW1lCQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMCDWZ1dHVyZV9BX3RpbWUAAAAIYXNzZXRJZHMJALUJAgkBEUBleHRyTmF0aXZlKDEwNTMpAgUEdGhpcwUHa0Fzc2V0cwIBLAAGbkNvaW5zCQCQAwEFCGFzc2V0SWRzAQdzdXNwZW5kAQVjYXVzZQkAzAgCCQEMQm9vbGVhbkVudHJ5AgUHa0FjdGl2ZQcJAMwIAgkBC1N0cmluZ0VudHJ5AgUGa0NhdXNlBQVjYXVzZQUDbmlsAQ10aHJvd0lzQWN0aXZlAAkAAgECFkRBcHAgaXMgYWxyZWFkeSBhY3RpdmUBCGlzQWN0aXZlAAMFBmFjdGl2ZQUEdW5pdAkAAgECH0RBcHAgaXMgaW5hY3RpdmUgYXQgdGhpcyBtb21lbnQBC2lzQWRtaW5DYWxsAQFpAwkBD2NvbnRhaW5zRWxlbWVudAIJAMwIAgUMYWRtaW5QdWJLZXkxCQDMCAIFDGFkbWluUHViS2V5MgkAzAgCBQxhZG1pblB1YktleTMFA25pbAgFAWkPY2FsbGVyUHVibGljS2V5BQR1bml0CQACAQIhT25seSBhZG1pbiBjYW4gY2FsbCB0aGlzIGZ1bmN0aW9uAQppc1NlbGZDYWxsAQFpAwkAAAIFBHRoaXMIBQFpBmNhbGxlcgUEdW5pdAkAAgECK09ubHkgY29udHJhY3QgaXRzZWxmIGNhbiBjYWxsIHRoaXMgZnVuY3Rpb24ABGJpZzIJALYCAQACAAZpdGVyMTAJAMwIAgAACQDMCAIAAQkAzAgCAAIJAMwIAgADCQDMCAIABAkAzAgCAAUJAMwIAgAGCQDMCAIABwkAzAgCAAgJAMwIAgAJBQNuaWwABml0ZXIxNQkAzAgCAAAJAMwIAgABCQDMCAIAAgkAzAgCAAMJAMwIAgAECQDMCAIABQkAzAgCAAYJAMwIAgAHCQDMCAIACAkAzAgCAAkJAMwIAgAKCQDMCAIACwkAzAgCAAwJAMwIAgANCQDMCAIADgUDbmlsAAZpdGVyMTYJAMwIAgAACQDMCAIAAQkAzAgCAAIJAMwIAgADCQDMCAIABAkAzAgCAAUJAMwIAgAGCQDMCAIABwkAzAgCAAgJAMwIAgAJCQDMCAIACgkAzAgCAAsJAMwIAgAMCQDMCAIADQkAzAgCAA4JAMwIAgAPBQNuaWwADmJsb2NrVGltZXN0YW1wBQZoZWlnaHQBBmFzc2VydAEBYQMFAWEHBgEUY2FsY3VsYXRlRmVlRGlzY291bnQBCHVzZXJBZGRyBAR1c2VyBAckbWF0Y2gwBQh1c2VyQWRkcgMJAAECBQckbWF0Y2gwAgdBZGRyZXNzBAF1BQckbWF0Y2gwCQClCAEFAXUDCQABAgUHJG1hdGNoMAIGU3RyaW5nBAF1BQckbWF0Y2gwBQF1CQACAQIYVW5rbm93IHR5cGUgb2YgdXNlciBBZGRyBApzd29wQW1vdW50CQELdmFsdWVPckVsc2UCCQCaCAIFCmdvdkFkZHJlc3MJAKwCAgUEdXNlcgUPa1VzZXJHU3dvcEluR292AAAEC2dTd29wQW1vdW50CQELdmFsdWVPckVsc2UCCQCaCAIFCmdvdkFkZHJlc3MJAKwCAgUEdXNlcgUPa1VzZXJHU3dvcEluR292BQpzd29wQW1vdW50BA5kaXNjb3VudFZhbHVlcwkAtQkCCQERQGV4dHJOYXRpdmUoMTA1MykCBQZvcmFjbGUFD2tEaXNjb3VudFZhbHVlcwIBLAQJZGlzY291bnRzCQC1CQIJARFAZXh0ck5hdGl2ZSgxMDUzKQIFBm9yYWNsZQUKa0Rpc2NvdW50cwIBLAMDCQBnAgULZ1N3b3BBbW91bnQJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQ5kaXNjb3VudFZhbHVlcwAACQBmAgkBDXBhcnNlSW50VmFsdWUBCQCRAwIFDmRpc2NvdW50VmFsdWVzAAEFC2dTd29wQW1vdW50BwkAZQIFCWZlZVNjYWxlNgkBDXBhcnNlSW50VmFsdWUBCQCRAwIFCWRpc2NvdW50cwAAAwMJAGcCBQtnU3dvcEFtb3VudAkBDXBhcnNlSW50VmFsdWUBCQCRAwIFDmRpc2NvdW50VmFsdWVzAAEJAGYCCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUOZGlzY291bnRWYWx1ZXMAAgULZ1N3b3BBbW91bnQHCQBlAgUJZmVlU2NhbGU2CQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUJZGlzY291bnRzAAEDAwkAZwIFC2dTd29wQW1vdW50CQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUOZGlzY291bnRWYWx1ZXMAAgkAZgIJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQ5kaXNjb3VudFZhbHVlcwADBQtnU3dvcEFtb3VudAcJAGUCBQlmZWVTY2FsZTYJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQlkaXNjb3VudHMAAgMDCQBnAgULZ1N3b3BBbW91bnQJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQ5kaXNjb3VudFZhbHVlcwADCQBmAgkBDXBhcnNlSW50VmFsdWUBCQCRAwIFDmRpc2NvdW50VmFsdWVzAAQFC2dTd29wQW1vdW50BwkAZQIFCWZlZVNjYWxlNgkBDXBhcnNlSW50VmFsdWUBCQCRAwIFCWRpc2NvdW50cwADAwkAZwIFC2dTd29wQW1vdW50CQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUOZGlzY291bnRWYWx1ZXMABAkAZQIFCWZlZVNjYWxlNgkBDXBhcnNlSW50VmFsdWUBCQCRAwIFCWRpc2NvdW50cwAEBQlmZWVTY2FsZTYBAl9BAAQCdDEFDWZ1dHVyZV9BX3RpbWUEAkExBQhmdXR1cmVfQQMJAGYCBQJ0MQUOYmxvY2tUaW1lc3RhbXAEAkEwBQlpbml0aWFsX0EEAnQwBQ5pbml0aWFsX0FfdGltZQMJAGYCBQJBMQUCQTAJAGQCBQJBMAkAaQIJAGgCCQBlAgUCQTEFAkEwCQBlAgUOYmxvY2tUaW1lc3RhbXAFAnQwCQBlAgUCdDEFAnQwCQBlAgUCQTAJAGkCCQBoAgkAZQIFAkEwBQJBMQkAZQIFDmJsb2NrVGltZXN0YW1wBQJ0MAkAZQIFAnQxBQJ0MAUCQTEBA194cAAKAQ1hc3NldEJhbGFuY2VzAgNhY2MHYXNzZXRJZAkAzQgCBQNhY2MJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwkArAICBQdhc3NldElkBQ1rQXNzZXRCYWxhbmNlAAAKAAIkbAUIYXNzZXRJZHMKAAIkcwkAkAMBBQIkbAoABSRhY2MwBQNuaWwKAQUkZjBfMQICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkBDWFzc2V0QmFsYW5jZXMCBQIkYQkAkQMCBQIkbAUCJGkKAQUkZjBfMgICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkAAgECFExpc3Qgc2l6ZSBleGNlZWRzIDEwCQEFJGYwXzICCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECBQUkYWNjMAAAAAEAAgADAAQABQAGAAcACAAJAAoBB194cF9tZW0BAnhwBQJ4cAEHc3VtTGlzdAIDYWNjB2VsZW1lbnQJAGQCBQNhY2MFB2VsZW1lbnQBBWdldF9EAgJ4cANhbXAKAAFACQD8BwQFBHRoaXMCAUQJAMwIAgUCeHAJAMwIAgUDYW1wBQNuaWwFA25pbAMJAAECBQFAAgNJbnQFAUAJAAIBCQCsAgIJAAMBBQFAAhggY291bGRuJ3QgYmUgY2FzdCB0byBJbnQBDmdldF9EX2ludGVybmFsAgJ4cANhbXAEAVMKAAIkbAUCeHAKAAIkcwkAkAMBBQIkbAoABSRhY2MwAAAKAQUkZjBfMQICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkBB3N1bUxpc3QCBQIkYQkAkQMCBQIkbAUCJGkKAQUkZjBfMgICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkAAgECFExpc3Qgc2l6ZSBleGNlZWRzIDEwCQEFJGYwXzICCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECBQUkYWNjMAAAAAEAAgADAAQABQAGAAcACAAJAAoDCQAAAgUBUwAAAAAEA0FubgkAaAIFA2FtcAUGbkNvaW5zBARBbm5TCQC5AgIJALYCAQUDQW5uCQC2AgEFAVMEBEFubjEJALYCAQkAZQIFA0FubgABCgEFRHByb2MCA2FjYwFpAwkAAAIIBQNhY2MCXzIGBQNhY2MEBURwcmV2CAUDYWNjAl8xCgEHRF9QUHJvYwIDRF9QAWkDCQBmAgUGbkNvaW5zBQFpCQC6AgIJALkCAgUDRF9QBQVEcHJldgkAuQICCQC2AgEJAJEDAgUCeHAFAWkJALYCAQUGbkNvaW5zBQNEX1AEA0RfUAoAAiRsBQZpdGVyMTAKAAIkcwkAkAMBBQIkbAoABSRhY2MwBQVEcHJldgoBBSRmMV8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQEHRF9QUHJvYwIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmMV8yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQIUTGlzdCBzaXplIGV4Y2VlZHMgMTAJAQUkZjFfMgIJAQUkZjFfMQIJAQUkZjFfMQIJAQUkZjFfMQIJAQUkZjFfMQIJAQUkZjFfMQIJAQUkZjFfMQIJAQUkZjFfMQIJAQUkZjFfMQIJAQUkZjFfMQIJAQUkZjFfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYABwAIAAkACgQBRAkAvAIDCQC3AgIFBEFublMJALkCAgkAtgIBBQZuQ29pbnMFA0RfUAUFRHByZXYJALcCAgkAuQICBQRBbm4xBQVEcHJldgkAuQICCQC2AgEJAGQCBQZuQ29pbnMAAQUDRF9QAwkAvwICBQFEBQVEcHJldgMJAGcCAAEJAKADAQkAuAICBQFEBQVEcHJldgkAlAoCBQFEBgkAlAoCBQFEBwMJAGcCAAEJAKADAQkAuAICBQVEcHJldgUBRAkAlAoCBQFEBgkAlAoCBQFEBwQLJHQwNjQ2MTY1MjcKAAIkbAUGaXRlcjE1CgACJHMJAJADAQUCJGwKAAUkYWNjMAkAlAoCCQC2AgEFAVMHCgEFJGYxXzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAQVEcHJvYwIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmMV8yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQIUTGlzdCBzaXplIGV4Y2VlZHMgMTUJAQUkZjFfMgIJAQUkZjFfMQIJAQUkZjFfMQIJAQUkZjFfMQIJAQUkZjFfMQIJAQUkZjFfMQIJAQUkZjFfMQIJAQUkZjFfMQIJAQUkZjFfMQIJAQUkZjFfMQIJAQUkZjFfMQIJAQUkZjFfMQIJAQUkZjFfMQIJAQUkZjFfMQIJAQUkZjFfMQIJAQUkZjFfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYABwAIAAkACgALAAwADQAOAA8EAUQIBQskdDA2NDYxNjUyNwJfMQQIZmluaXNoZWQIBQskdDA2NDYxNjUyNwJfMgMJAAACBQhmaW5pc2hlZAcJAAIBCQCsAgICGmdldF9EKCkgbm90IGZpbmlzaGVkIHdpdGggCQCmAwEFAUQJAKADAQUBRAEHZ2V0RE1lbQICeHADYW1wCQEFZ2V0X0QCCQEHX3hwX21lbQEFAnhwBQNhbXABBGdldFkEAmluA291dAF4A3hwXwMJAQZhc3NlcnQBCQECIT0CBQJpbgUDb3V0CQACAQIJc2FtZSBjb2luAwkBBmFzc2VydAEDCQBnAgUDb3V0AAAJAGcCBQJpbgAABwkAAgECCmJlbG93IHplcm8DCQEGYXNzZXJ0AQMJAGYCBQZuQ29pbnMFA291dAkAZgIFBm5Db2lucwUCaW4HCQACAQINYWJvdmUgTl9DT0lOUwQDYW1wCQECX0EABAFECQEFZ2V0X0QCBQN4cF8FA2FtcAQDQW5uCQBoAgUDYW1wBQZuQ29pbnMKAQNTX2MCA2FjYwFpBAskdDA3MDk4NzExNQUDYWNjBAJTXwgFCyR0MDcwOTg3MTE1Al8xBAFjCAULJHQwNzA5ODcxMTUCXzIEAnhfAwkAAAIFAmluBQFpBQF4CQCRAwIFA3hwXwUBaQMDCQECIT0CBQFpBQNvdXQJAGYCBQZuQ29pbnMFAWkHCQCUCgIJAGQCBQJTXwUCeF8JALwCAwUBYwkAtgIBBQFECQC2AgEJAGgCBQJ4XwUGbkNvaW5zCQCUCgIFAlNfBQFjBAskdDA3MzIzNzM3OAoAAiRsBQZpdGVyMTAKAAIkcwkAkAMBBQIkbAoABSRhY2MwCQCUCgIAAAkAtgIBBQFECgEFJGYwXzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAQNTX2MCBQIkYQkAkQMCBQIkbAUCJGkKAQUkZjBfMgICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkAAgECFExpc3Qgc2l6ZSBleGNlZWRzIDEwCQEFJGYwXzICCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECBQUkYWNjMAAAAAEAAgADAAQABQAGAAcACAAJAAoEAlNfCAULJHQwNzMyMzczNzgCXzEEAmNfCAULJHQwNzMyMzczNzgCXzIEAWMJALwCAwUCY18JALYCAQUBRAkAtgIBCQBoAgUDQW5uBQZuQ29pbnMEAmJECQC2AgEJAGUCCQBkAgUCU18JAGkCBQFEBQNBbm4FAUQKAQZ5X3Byb2MCA2FjYwJfaQMJAAACCAUDYWNjAl8yBgUDYWNjBAZ5X3ByZXYIBQNhY2MCXzEEAXkJALoCAgkAtwICCQC5AgIFBnlfcHJldgUGeV9wcmV2BQFjCQC3AgIJALkCAgUEYmlnMgUGeV9wcmV2BQJiRAMJAL8CAgUBeQUGeV9wcmV2AwkAZwIAAQkAoAMBCQC4AgIFAXkFBnlfcHJldgkAlAoCBQF5BgkAlAoCBQF5BwMJAGcCAAEJAKADAQkAuAICBQZ5X3ByZXYFAXkJAJQKAgUBeQYJAJQKAgUBeQcECyR0MDc4NjA3OTI3CgACJGwFBml0ZXIxNgoAAiRzCQCQAwEFAiRsCgAFJGFjYzAJAJQKAgkAtgIBBQFEBwoBBSRmMV8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQEGeV9wcm9jAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGYxXzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhRMaXN0IHNpemUgZXhjZWVkcyAxNgkBBSRmMV8yAgkBBSRmMV8xAgkBBSRmMV8xAgkBBSRmMV8xAgkBBSRmMV8xAgkBBSRmMV8xAgkBBSRmMV8xAgkBBSRmMV8xAgkBBSRmMV8xAgkBBSRmMV8xAgkBBSRmMV8xAgkBBSRmMV8xAgkBBSRmMV8xAgkBBSRmMV8xAgkBBSRmMV8xAgkBBSRmMV8xAgkBBSRmMV8xAgUFJGFjYzAAAAABAAIAAwAEAAUABgAHAAgACQAKAAsADAANAA4ADwAQBAF5CAULJHQwNzg2MDc5MjcCXzEECGZpbmlzaGVkCAULJHQwNzg2MDc5MjcCXzIDCQAAAgUIZmluaXNoZWQHCQACAQkArAICAhlnZXRZKCkgbm90IGZpbmlzaGVkIHdpdGggCQCmAwEFAXkJAKADAQUBeQEHZ2V0X3lfRAQCQV8CaW4CeHABRAMJAQZhc3NlcnQBCQBnAgUCaW4AAAkAAgECDGkgYmVsb3cgemVybwMJAQZhc3NlcnQBCQBmAgUGbkNvaW5zBQJpbgkAAgECD2kgYWJvdmUgTl9DT0lOUwQDQW5uCQBoAgUCQV8FBm5Db2lucwoBA1NfYwIDYWNjAWkECyR0MDgzMDY4MzIzBQNhY2MEAlNfCAULJHQwODMwNjgzMjMCXzEEAWMIBQskdDA4MzA2ODMyMwJfMgQCeF8DAwkBAiE9AgUCaW4FAWkJAGYCBQZuQ29pbnMFAWkHCQCRAwIFAnhwBQFpAAADAwkAZgIFBm5Db2lucwUBaQkBAiE9AgUCaW4FAWkHCQCUCgIJAGQCBQJTXwUCeF8JALwCAwUBYwkAtgIBBQFECQC2AgEJAGgCBQJ4XwUGbkNvaW5zCQCUCgIFAlNfBQFjBAskdDA4NTQzODU5OAoAAiRsBQZpdGVyMTAKAAIkcwkAkAMBBQIkbAoABSRhY2MwCQCUCgIAAAkAtgIBBQFECgEFJGYwXzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAQNTX2MCBQIkYQkAkQMCBQIkbAUCJGkKAQUkZjBfMgICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkAAgECFExpc3Qgc2l6ZSBleGNlZWRzIDEwCQEFJGYwXzICCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECBQUkYWNjMAAAAAEAAgADAAQABQAGAAcACAAJAAoEAlNfCAULJHQwODU0Mzg1OTgCXzEEAmNfCAULJHQwODU0Mzg1OTgCXzIEAWMJALwCAwUCY18JALYCAQUBRAkAtgIBCQBoAgUDQW5uBQZuQ29pbnMEAmJECQC2AgEJAGUCCQBkAgUCU18JAGkCBQFEBQNBbm4FAUQKAQh5X0RfcHJvYwIDYWNjAWkDCQAAAggFA2FjYwJfMgYFA2FjYwQGeV9wcmV2CAUDYWNjAl8xBAF5CQC6AgIJALcCAgkAuQICBQZ5X3ByZXYFBnlfcHJldgUBYwkAtwICCQC5AgIFBGJpZzIFBnlfcHJldgUCYkQDCQC/AgIFAXkFBnlfcHJldgMJAGcCAAEJAKADAQkAuAICBQF5BQZ5X3ByZXYJAJQKAgUBeQYJAJQKAgUBeQcDCQBnAgABCQCgAwEJALgCAgUGeV9wcmV2BQF5CQCUCgIFAXkGCQCUCgIFAXkHBAskdDA5MDgxOTE1MAoAAiRsBQZpdGVyMTYKAAIkcwkAkAMBBQIkbAoABSRhY2MwCQCUCgIJALYCAQUBRAcKAQUkZjFfMQICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkBCHlfRF9wcm9jAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGYxXzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhRMaXN0IHNpemUgZXhjZWVkcyAxNgkBBSRmMV8yAgkBBSRmMV8xAgkBBSRmMV8xAgkBBSRmMV8xAgkBBSRmMV8xAgkBBSRmMV8xAgkBBSRmMV8xAgkBBSRmMV8xAgkBBSRmMV8xAgkBBSRmMV8xAgkBBSRmMV8xAgkBBSRmMV8xAgkBBSRmMV8xAgkBBSRmMV8xAgkBBSRmMV8xAgkBBSRmMV8xAgkBBSRmMV8xAgUFJGFjYzAAAAABAAIAAwAEAAUABgAHAAgACQAKAAsADAANAA4ADwAQBAF5CAULJHQwOTA4MTkxNTACXzEECGZpbmlzaGVkCAULJHQwOTA4MTkxNTACXzIDCQAAAgUIZmluaXNoZWQHCQACAQkArAICAhxnZXRfeV9EKCkgbm90IGZpbmlzaGVkIHdpdGggCQCmAwEFAXkJAKADAQUBeQEUX2NhbGNXaXRoZHJhd09uZUNvaW4EAnhwDV90b2tlbl9hbW91bnQBaQZjYWxsZXIEC2ZlZURpc2NvdW50CQEUY2FsY3VsYXRlRmVlRGlzY291bnQBBQZjYWxsZXIEA2FtcAkBAl9BAAQEX2ZlZQkAaQIJAGgCCQBuBAUDZmVlBQtmZWVEaXNjb3VudAUJZmVlU2NhbGU2BQdDRUlMSU5HBQZuQ29pbnMJAGgCAAQJAGUCBQZuQ29pbnMAAQQMdG90YWxfc3VwcGx5BQtzaGFyZVN1cHBseQQCRDAJAQVnZXRfRAIFAnhwBQNhbXAEAkQxCQBlAgUCRDAJAGsDBQ1fdG9rZW5fYW1vdW50BQJEMAUMdG90YWxfc3VwcGx5BAVuZXdfeQkBB2dldF95X0QEBQNhbXAFAWkFAnhwBQJEMQQEZHlfMAkAZQIJAJEDAgUCeHAFAWkFBW5ld195CgEPeHBfcmVkdWNlZF9wcm9jAgNhY2MEeHBfagQLJHQwOTc5MTk4MjAFA2FjYwQKeHBfcmVkdWNlZAgFCyR0MDk3OTE5ODIwAl8xBAVpbmRleAgFCyR0MDk3OTE5ODIwAl8yBAtkeF9leHBlY3RlZAMJAAACBQVpbmRleAUBaQkAZQIJAGsDBQR4cF9qBQJEMQUCRDAFBW5ld195CQBlAgUEeHBfagkAawMFBHhwX2oFAkQxBQJEMAkAlAoCCQDNCAIFCnhwX3JlZHVjZWQJAGUCBQR4cF9qCQBrAwUEX2ZlZQULZHhfZXhwZWN0ZWQFCWZlZVNjYWxlNgkAZAIFBWluZGV4AAEEDSR0MDEwMDgyMTAxNDYKAAIkbAUCeHAKAAIkcwkAkAMBBQIkbAoABSRhY2MwCQCUCgIFA25pbAAACgEFJGYwXzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAQ94cF9yZWR1Y2VkX3Byb2MCBQIkYQkAkQMCBQIkbAUCJGkKAQUkZjBfMgICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkAAgECFExpc3Qgc2l6ZSBleGNlZWRzIDEwCQEFJGYwXzICCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECBQUkYWNjMAAAAAEAAgADAAQABQAGAAcACAAJAAoECnhwX3JlZHVjZWQIBQ0kdDAxMDA4MjEwMTQ2Al8xBAVpbmRleAgFDSR0MDEwMDgyMTAxNDYCXzIEDHhwX3JlZHVjZWRfaQkAkQMCBQp4cF9yZWR1Y2VkBQFpBAJkeQkAZQIJAGUCBQx4cF9yZWR1Y2VkX2kJAQdnZXRfeV9EBAUDYW1wBQFpBQp4cF9yZWR1Y2VkBQJEMQABCQCUCgIFAmR5CQBlAgUEZHlfMAUCZHkBDWdldFN0ckFzc2V0SWQBB2Fzc2V0SWQEByRtYXRjaDAFB2Fzc2V0SWQDCQABAgUHJG1hdGNoMAIKQnl0ZVZlY3RvcgQCaWQFByRtYXRjaDAJANgEAQUCaWQDCQABAgUHJG1hdGNoMAIEVW5pdAQFd2F2ZXMFByRtYXRjaDACBVdBVkVTCQACAQILTWF0Y2ggZXJyb3IBGGNhbGNTdGFraW5nRnVuY0FuZEFkZHJlcwIFc3Rha2UHYXNzZXRJZAMFBXN0YWtlCQCUCgICDGxvY2tOZXV0cmlubwUSc3Rha2luZ1VTRE5BZGRyZXNzCQCUCgICDnVubG9ja05ldXRyaW5vBRJzdGFraW5nVVNETkFkZHJlc3MBEWNhbGNTdGFraW5nUGFyYW1zAwVzdGFrZQZhbW91bnQHYXNzZXRJZAMFBXN0YWtlBA0kdDAxMDcxMDEwNzc2CQEYY2FsY1N0YWtpbmdGdW5jQW5kQWRkcmVzAgUFc3Rha2UFB2Fzc2V0SWQEBGNhbGwIBQ0kdDAxMDcxMDEwNzc2Al8xBAtzdGFraW5nQWRkcggFDSR0MDEwNzEwMTA3NzYCXzIJAJYKBAUEY2FsbAULc3Rha2luZ0FkZHIFA25pbAkAzAgCCQEPQXR0YWNoZWRQYXltZW50AgUHYXNzZXRJZAUGYW1vdW50BQNuaWwEDSR0MDEwODYyMTA5MjgJARhjYWxjU3Rha2luZ0Z1bmNBbmRBZGRyZXMCBQVzdGFrZQUHYXNzZXRJZAQEY2FsbAgFDSR0MDEwODYyMTA5MjgCXzEEC3N0YWtpbmdBZGRyCAUNJHQwMTA4NjIxMDkyOAJfMgkAlgoEBQRjYWxsBQtzdGFraW5nQWRkcgkAzAgCBQZhbW91bnQJAMwIAgkA2AQBBQdhc3NldElkBQNuaWwFA25pbAEFc3Rha2UCBmFtb3VudA1hc3NldElkU3RyaW5nAwkBD2NvbnRhaW5zRWxlbWVudAIFDXN0YWtpbmdBc3NldHMFDWFzc2V0SWRTdHJpbmcEDSR0MDExMTE1MTEyMTcJARFjYWxjU3Rha2luZ1BhcmFtcwMGBQZhbW91bnQJANkEAQUNYXNzZXRJZFN0cmluZwQEY2FsbAgFDSR0MDExMTE1MTEyMTcCXzEEBGFkZHIIBQ0kdDAxMTExNTExMjE3Al8yBAZwYXJhbXMIBQ0kdDAxMTExNTExMjE3Al8zBAhwYXltZW50cwgFDSR0MDExMTE1MTEyMTcCXzQJAPwHBAUEYWRkcgUEY2FsbAUGcGFyYW1zBQhwYXltZW50cwAAAQd1bnN0YWtlAgZhbW91bnQNYXNzZXRJZFN0cmluZwMJAQ9jb250YWluc0VsZW1lbnQCBQ1zdGFraW5nQXNzZXRzBQ1hc3NldElkU3RyaW5nBA0kdDAxMTQwMjExNTA1CQERY2FsY1N0YWtpbmdQYXJhbXMDBwUGYW1vdW50CQDZBAEFDWFzc2V0SWRTdHJpbmcEBGNhbGwIBQ0kdDAxMTQwMjExNTA1Al8xBARhZGRyCAUNJHQwMTE0MDIxMTUwNQJfMgQGcGFyYW1zCAUNJHQwMTE0MDIxMTUwNQJfMwQIcGF5bWVudHMIBQ0kdDAxMTQwMjExNTA1Al80CQD8BwQFBGFkZHIFBGNhbGwFBnBhcmFtcwUIcGF5bWVudHMAAAEMc3Rha2VkQW1vdW50AQdhc3NldElkBBZzdGFrZWRBbW91bnRDYWxjdWxhdGVkBAckbWF0Y2gwBQdhc3NldElkAwkAAQIFByRtYXRjaDACCkJ5dGVWZWN0b3IEA2FJZAUHJG1hdGNoMAMJAAACBQNhSWQFBFVTRE4JAJoIAgUSc3Rha2luZ1VTRE5BZGRyZXNzCQCsAgIJAKwCAgkArAICAgxycGRfYmFsYW5jZV8JANgEAQUDYUlkAgFfCQClCAEFBHRoaXMAAAMJAAECBQckbWF0Y2gwAgRVbml0AAAJAAIBAgtNYXRjaCBlcnJvcgQHJG1hdGNoMAUWc3Rha2VkQW1vdW50Q2FsY3VsYXRlZAMJAAECBQckbWF0Y2gwAgNJbnQEAWkFByRtYXRjaDAFAWkAAAEPY2hlY2tTdXNwaWNpb3VzAAQQY29udHJhY3RCYWxhbmNlcwkBA194cAAKAQxjaGVja0JhbGFuY2UCA2FjYwdhc3NldElkBA0kdDAxMjExNjEyMTQxBQNhY2MECnN1c3BpY2lvdXMIBQ0kdDAxMjExNjEyMTQxAl8xBAFpCAUNJHQwMTIxMTYxMjE0MQJfMgMFCnN1c3BpY2lvdXMJAJQKAgUKc3VzcGljaW91cwUBaQQIYUJhbGFuY2UJAGQCCQDwBwIFBHRoaXMJANkEAQUHYXNzZXRJZAkBDHN0YWtlZEFtb3VudAEJANkEAQUHYXNzZXRJZAMJAGYCCQCRAwIFEGNvbnRyYWN0QmFsYW5jZXMFAWkFCGFCYWxhbmNlCQCUCgIGBQFpCQCUCgIHCQBkAgUBaQABCgACJGwFCGFzc2V0SWRzCgACJHMJAJADAQUCJGwKAAUkYWNjMAkAlAoCBwAACgEFJGYwXzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAQxjaGVja0JhbGFuY2UCBQIkYQkAkQMCBQIkbAUCJGkKAQUkZjBfMgICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkAAgECFExpc3Qgc2l6ZSBleGNlZWRzIDEwCQEFJGYwXzICCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECBQUkYWNjMAAAAAEAAgADAAQABQAGAAcACAAJAAoBEXN1c3BlbmRTdXNwaWNpb3VzAQFpCQEHc3VzcGVuZAEJAKwCAgIdU3VzcGljaW91cyBzdGF0ZSB3aXRoIGFzc2V0OiAJAJEDAgUIYXNzZXRJZHMFAWkBDnJldHVyblBheW1lbnRzAgZjYWxsZXIIcGF5bWVudHMKAQ1wYXJzZVBheW1lbnRzAgNhY2MHcGF5bWVudAkAzQgCBQNhY2MJAQ5TY3JpcHRUcmFuc2ZlcgMFBmNhbGxlcggFB3BheW1lbnQGYW1vdW50CAUHcGF5bWVudAdhc3NldElkCgACJGwFCHBheW1lbnRzCgACJHMJAJADAQUCJGwKAAUkYWNjMAUDbmlsCgEFJGYwXzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAQ1wYXJzZVBheW1lbnRzAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGYwXzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhRMaXN0IHNpemUgZXhjZWVkcyAxMAkBBSRmMF8yAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgUFJGFjYzAAAAABAAIAAwAEAAUABgAHAAgACQAKARJjaGVja0RBcHBUaHJlc2hvbGQBC25ld0JhbGFuY2VzBBFkQXBwVGhyZXNob2xkQ29lZgkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCaCAIFBHRoaXMFEmtEQXBwVGhyZXNob2xkQ29lZgIYTm8gZEFwcFRocmVzaG9sZENvZWYga2V5BA50aHJlc2hvbGRTY2FsZQCQTgQKbWF4QmFsYW5jZQkAlgMBBQtuZXdCYWxhbmNlcwQKbWluQmFsYW5jZQkAlwMBBQtuZXdCYWxhbmNlcwQFcmF0aW8JAGsDBQptYXhCYWxhbmNlBQ50aHJlc2hvbGRTY2FsZQUKbWluQmFsYW5jZQMJAGYCBQVyYXRpbwkAaAIFEWRBcHBUaHJlc2hvbGRDb2VmBQ50aHJlc2hvbGRTY2FsZQkAAgECOE5ldyBiYWxhbmNlIGluIGFzc2V0cyBvZiB0aGUgREFwcCBpcyBsZXNzIHRoYW4gdGhyZXNob2xkBwEKY2hlY2tDb2lucwEIYXNzZXRJZHMEBWNvaW5zCQC1CQIFCGFzc2V0SWRzAgEsAwkAZgIJAJADAQUFY29pbnMACgkAAgECIFRvIG1hbnkgY29pbnMsIG1heCBjb2lucyBzaXplIDEwCgEJY2hlY2tDb2luAgVlcnJvcgdhc3NldElkBAVhc3NldAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQDZBAEFB2Fzc2V0SWQJAKwCAgISZnJvbUJhc2U1OFN0cmluZzogBQdhc3NldElkBAhkZWNpbWFscwgJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkA7AcBBQVhc3NldAkArAICAgthc3NldEluZm86IAUHYXNzZXRJZAhkZWNpbWFscwMJAQIhPQIFCGRlY2ltYWxzBQhERUNJTUFMUwkAAgECDndyb25nIGRlY2ltYWxzBwoAAiRsBQVjb2lucwoAAiRzCQCQAwEFAiRsCgAFJGFjYzAHCgEFJGYwXzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAQljaGVja0NvaW4CBQIkYQkAkQMCBQIkbAUCJGkKAQUkZjBfMgICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkAAgECFExpc3Qgc2l6ZSBleGNlZWRzIDEwCQEFJGYwXzICCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECBQUkYWNjMAAAAAEAAgADAAQABQAGAAcACAAJAAoUA21zZwEBRAICeHADYW1wBAFECQEOZ2V0X0RfaW50ZXJuYWwCBQJ4cAUDYW1wCQCUCgIJAMwIAgkBDEludGVnZXJFbnRyeQICAUQFAUQFA25pbAUBRANtc2cBBGluaXQDCGFzc2V0SWRzAl9BEl9kQXBwVGhyZXNob2xkQ29lZgMJAQEhAQkAnggBBQR0aGlzCQACAQITQWxyZWFkeSBpbml0aWFsaXplZAMJAGcCAAAFAl9BCQACAQIUQW1wIG11c3QgYmUgbXVzdCA+IDADCQBnAgAABRJfZEFwcFRocmVzaG9sZENvZWYJAAIBAh9kQXBwIFRocmVzaG9sZCBDb2VmIG11c3QgYmUgPiAwBAlzaGFyZU5hbWUCC3NfTXVsdGlfVVNEBBBzaGFyZURlc2NyaXB0aW9uCQCsAgICQlNoYXJlVG9rZW4gb2YgU3dvcEZpIHByb3RvY29sIGZvciBNdWx0aVN0YWJsZSBVU0QgcG9vbCBhdCBhZGRyZXNzIAkApQgBBQR0aGlzBAppc3N1ZVRva2VuCQDCCAUFCXNoYXJlTmFtZQUQc2hhcmVEZXNjcmlwdGlvbgAAAAYGBAd0b2tlbklkCQC4CAEFCmlzc3VlVG9rZW4DCQEKY2hlY2tDb2lucwEFCGFzc2V0SWRzCQEFdGhyb3cACQDMCAIJAQtTdHJpbmdFbnRyeQIFCGtWZXJzaW9uBQd2ZXJzaW9uCQDMCAIJAQtTdHJpbmdFbnRyeQIFB2tBc3NldHMFCGFzc2V0SWRzCQDMCAIJAQxJbnRlZ2VyRW50cnkCAglpbml0aWFsX0EFAl9BCQDMCAIJAQxJbnRlZ2VyRW50cnkCAghmdXR1cmVfQQUCX0EJAMwIAgkBDEludGVnZXJFbnRyeQIFBGtGZWUJARFAZXh0ck5hdGl2ZSgxMDUwKQIFBm9yYWNsZQINYmFzZV9mZWVfZmxhdAkAzAgCCQELU3RyaW5nRW50cnkCBQ1rU2hhcmVBc3NldElkCQDYBAEFB3Rva2VuSWQJAMwIAgkBDEludGVnZXJFbnRyeQIFEWtTaGFyZUFzc2V0U3VwcGx5AAAJAMwIAgkBDEludGVnZXJFbnRyeQIFEmtEQXBwVGhyZXNob2xkQ29lZgUSX2RBcHBUaHJlc2hvbGRDb2VmCQDMCAIJAQxCb29sZWFuRW50cnkCBQdrQWN0aXZlBgkAzAgCBQppc3N1ZVRva2VuBQNuaWwDbXNnAQxhZGRMaXF1aWRpdHkDDW1pbk1pbnRBbW91bnQMc3Rha2VGYXJtaW5nCGxvY2tUeXBlCQELdmFsdWVPckVsc2UCCQEIaXNBY3RpdmUABANhbXAJAQJfQQAEAnhwCQEDX3hwAAQCRDADCQAAAgULc2hhcmVTdXBwbHkAAAAACQEHZ2V0RE1lbQIFAnhwBQNhbXAEDSR0MDE1MzQ5MTU2MDQDAwkAZgIFCGxvY2tUeXBlAAAJAAACCAkAkQMCCAUDbXNnCHBheW1lbnRzCQBlAgkAkAMBCAUDbXNnCHBheW1lbnRzAAEHYXNzZXRJZAUEdW5pdAcJAJQKAgkA0QgCCAUDbXNnCHBheW1lbnRzCQBlAgkAkAMBCAUDbXNnCHBheW1lbnRzAAEJAMwIAgkAkQMCCAUDbXNnCHBheW1lbnRzCQBlAgkAkAMBCAUDbXNnCHBheW1lbnRzAAEFA25pbAkAlAoCCAUDbXNnCHBheW1lbnRzBQNuaWwECHBheW1lbnRzCAUNJHQwMTUzNDkxNTYwNAJfMQQHbG9ja0ZlZQgFDSR0MDE1MzQ5MTU2MDQCXzIEDHBheW1lbnRzU2l6ZQkAkAMBBQhwYXltZW50cwoBDXZhbGlkUGF5bWVudHMBAW4DCQBmAgUMcGF5bWVudHNTaXplBQZuQ29pbnMJAAIBCQCsAgICEHBheW1lbnRzIHNpemUgPiAJAKQDAQUGbkNvaW5zAwkAZgIAAQUMcGF5bWVudHNTaXplCQACAQIRcGF5bWVudHMgc2l6ZSA8IDEDAwkAAAIFC3NoYXJlU3VwcGx5AAAJAQIhPQIFBm5Db2lucwUMcGF5bWVudHNTaXplBwkAAgECImluaXRpYWwgZGVwb3NpdCByZXF1aXJlcyBhbGwgY29pbnMKAQxwYXltYW50VmFsaWQCA2FjYwdwYXltZW50AwkBD2NvbnRhaW5zRWxlbWVudAIFCGFzc2V0SWRzCQENZ2V0U3RyQXNzZXRJZAEIBQdwYXltZW50B2Fzc2V0SWQGCQACAQIYSW52YWxpZCBhc3NldCBpbiBwYXltZW50CgACJGwFCHBheW1lbnRzCgACJHMJAJADAQUCJGwKAAUkYWNjMAcKAQUkZjBfMQICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkBDHBheW1hbnRWYWxpZAIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmMF8yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQIUTGlzdCBzaXplIGV4Y2VlZHMgMTAJAQUkZjBfMgIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYABwAIAAkACgMJAQEhAQkBDXZhbGlkUGF5bWVudHMBBQxwYXltZW50c1NpemUJAQV0aHJvdwAECnN1c3BpY2lvdXMJAQ9jaGVja1N1c3BpY2lvdXMAAwgFCnN1c3BpY2lvdXMCXzEJAM4IAgkBEXN1c3BlbmRTdXNwaWNpb3VzAQgFCnN1c3BpY2lvdXMCXzIJAQ5yZXR1cm5QYXltZW50cwIIBQNtc2cGY2FsbGVyBQhwYXltZW50cwoBDXBhcnNlUGF5bWVudHMCA2FjYwdhc3NldElkBA0kdDAxNjQ3NDE2NTAwBQNhY2MEC25ld0JhbGFuY2VzCAUNJHQwMTY0NzQxNjUwMAJfMQQBaQgFDSR0MDE2NDc0MTY1MDACXzIKAQxwYXJzZVBheW1lbnQCCm5ld0JhbGFuY2UHcGF5bWVudAMJAAACCQENZ2V0U3RyQXNzZXRJZAEIBQdwYXltZW50B2Fzc2V0SWQFB2Fzc2V0SWQJAGQCBQpuZXdCYWxhbmNlCAUHcGF5bWVudAZhbW91bnQFCm5ld0JhbGFuY2UECW5ld0JhbGFjZQoAAiRsBQhwYXltZW50cwoAAiRzCQCQAwEFAiRsCgAFJGFjYzAJAJEDAgUCeHAFAWkKAQUkZjBfMQICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkBDHBhcnNlUGF5bWVudAIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmMF8yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQIUTGlzdCBzaXplIGV4Y2VlZHMgMTAJAQUkZjBfMgIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYABwAIAAkACgkAlAoCCQDNCAIFC25ld0JhbGFuY2VzBQluZXdCYWxhY2UJAGQCBQFpAAEEDSR0MDE2ODUwMTY5MTcKAAIkbAUIYXNzZXRJZHMKAAIkcwkAkAMBBQIkbAoABSRhY2MwCQCUCgIFA25pbAAACgEFJGYwXzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAQ1wYXJzZVBheW1lbnRzAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGYwXzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhRMaXN0IHNpemUgZXhjZWVkcyAxMAkBBSRmMF8yAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgUFJGFjYzAAAAABAAIAAwAEAAUABgAHAAgACQAKBAtuZXdCYWxhbmNlcwgFDSR0MDE2ODUwMTY5MTcCXzEEAWsIBQ0kdDAxNjg1MDE2OTE3Al8yAwkBEmNoZWNrREFwcFRocmVzaG9sZAEFC25ld0JhbGFuY2VzCQEFdGhyb3cABAJEMQkBB2dldERNZW0CBQtuZXdCYWxhbmNlcwUDYW1wAwkBBmFzc2VydAEJAGYCBQJEMQUCRDAJAAIBAgdEMSA+IEQwBAtmZWVEaXNjb3VudAkBFGNhbGN1bGF0ZUZlZURpc2NvdW50AQgFA21zZwZjYWxsZXIKARFjYWxjU2NyaXB0QWN0aW9ucwIDYWNjCm5ld0JhbGFuY2UEDSR0MDE3MjM3MTcyNzgFA2FjYwQLaW52QmFsYW5jZXMIBQ0kdDAxNzIzNzE3Mjc4Al8xBA1zY3JpcHRBY3Rpb25zCAUNJHQwMTcyMzcxNzI3OAJfMgQBaQgFDSR0MDE3MjM3MTcyNzgCXzMDCQBmAgULc2hhcmVTdXBwbHkAAAQEX2ZlZQkAaQIJAGgCCQBuBAUDZmVlBQtmZWVEaXNjb3VudAUJZmVlU2NhbGU2BQdDRUlMSU5HBQZuQ29pbnMJAGgCAAQJAGUCBQZuQ29pbnMAAQQEZmVlcwQMaWRlYWxCYWxhbmNlCQBrAwUCRDEJAJEDAgUCeHAFAWkFAkQwBApkaWZmZXJlbmNlAwkAZgIFDGlkZWFsQmFsYW5jZQUKbmV3QmFsYW5jZQkAZQIFDGlkZWFsQmFsYW5jZQUKbmV3QmFsYW5jZQkAZQIFCm5ld0JhbGFuY2UFDGlkZWFsQmFsYW5jZQkAawMFBF9mZWUFCmRpZmZlcmVuY2UFCWZlZVNjYWxlNgQOZ292ZXJuYW5jZUZlZXMJAGsDBQRmZWVzBQ1mZWVHb3Zlcm5hbmNlBQlmZWVTY2FsZTYEDGZpbmFsQmFsYW5jZQkAZQIFCm5ld0JhbGFuY2UFBGZlZXMEEGludmFyaWFudEJhbGFuY2UJAGUCBQpuZXdCYWxhbmNlBQRmZWVzBANwbXQJAGUCBQpuZXdCYWxhbmNlCQCRAwIFAnhwBQFpBAZscEZlZXMJAGUCBQRmZWVzBQ5nb3Zlcm5hbmNlRmVlcwQDaW52AwkAZgIFA3BtdAAACQEFc3Rha2UCCQBlAgUDcG10BQRmZWVzCQCRAwIFCGFzc2V0SWRzBQFpCQEHdW5zdGFrZQIFBGZlZXMJAJEDAgUIYXNzZXRJZHMFAWkDCQAAAgUDaW52BQNpbnYEB2FpcmRyb3ADCQBmAgUGbHBGZWVzAAAJAPwHBAUQbHBGYXJtaW5nQWRkcmVzcwIHYWlyRHJvcAUDbmlsCQDMCAIJAQ9BdHRhY2hlZFBheW1lbnQCCQDZBAEJAJEDAgUIYXNzZXRJZHMFAWkFBmxwRmVlcwUDbmlsAAADCQAAAgUHYWlyZHJvcAUHYWlyZHJvcAkAlQoDCQDNCAIFC2ludkJhbGFuY2VzBRBpbnZhcmlhbnRCYWxhbmNlCQDOCAIFDXNjcmlwdEFjdGlvbnMJAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwUPbW9uZXlCb3hBZGRyZXNzBQ5nb3Zlcm5hbmNlRmVlcwkA2QQBCQCRAwIFCGFzc2V0SWRzBQFpCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQCsAgIJAJEDAgUIYXNzZXRJZHMFAWkFDWtBc3NldEJhbGFuY2UFDGZpbmFsQmFsYW5jZQUDbmlsCQBkAgUBaQABCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuBANpbnYJAQVzdGFrZQIFCm5ld0JhbGFuY2UJAJEDAgUIYXNzZXRJZHMFAWkDCQAAAgUDaW52BQNpbnYJAJUKAwkAzQgCBQtpbnZCYWxhbmNlcwUKbmV3QmFsYW5jZQkAzQgCBQ1zY3JpcHRBY3Rpb25zCQEMSW50ZWdlckVudHJ5AgkArAICCQCRAwIFCGFzc2V0SWRzBQFpBQ1rQXNzZXRCYWxhbmNlBQpuZXdCYWxhbmNlCQBkAgUBaQABCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuBA0kdDAxODk4MzE5MDcxCgACJGwFC25ld0JhbGFuY2VzCgACJHMJAJADAQUCJGwKAAUkYWNjMAkAlQoDBQNuaWwFA25pbAAACgEFJGYxXzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJARFjYWxjU2NyaXB0QWN0aW9ucwIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmMV8yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQIUTGlzdCBzaXplIGV4Y2VlZHMgMTAJAQUkZjFfMgIJAQUkZjFfMQIJAQUkZjFfMQIJAQUkZjFfMQIJAQUkZjFfMQIJAQUkZjFfMQIJAQUkZjFfMQIJAQUkZjFfMQIJAQUkZjFfMQIJAQUkZjFfMQIJAQUkZjFfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYABwAIAAkACgQLaW52QmFsYW5jZXMIBQ0kdDAxODk4MzE5MDcxAl8xBA1zY3JpcHRBY3Rpb25zCAUNJHQwMTg5ODMxOTA3MQJfMgQCRDIJAQdnZXRETWVtAgULaW52QmFsYW5jZXMFA2FtcAQLbWludF9hbW91bnQDCQAAAgULc2hhcmVTdXBwbHkAAAUCRDEJAGsDBQtzaGFyZVN1cHBseQkAZQIFAkQyBQJEMAUCRDADCQEGYXNzZXJ0AQkAZwIFC21pbnRfYW1vdW50BQ1taW5NaW50QW1vdW50CQACAQIUU2xpcHBhZ2Ugc2NyZXdlZCB5b3UDBQxzdGFrZUZhcm1pbmcEAnJlCQD8BwQFBHRoaXMCDHJlaXNzdWVTaGFyZQkAzAgCBQttaW50X2Ftb3VudAUDbmlsBQNuaWwDCQAAAgUCcmUFAnJlBAFzCQD8BwQFDmZhcm1pbmdBZGRyZXNzAg9sb2NrU2hhcmVUb2tlbnMJAMwIAgkApQgBBQR0aGlzCQDMCAIFCGxvY2tUeXBlBQNuaWwJAM4IAgkAzAgCCQEPQXR0YWNoZWRQYXltZW50AgUMc2hhcmVBc3NldElkBQttaW50X2Ftb3VudAUDbmlsBQdsb2NrRmVlAwkAAAIFAXMFAXMJAM0IAgUNc2NyaXB0QWN0aW9ucwkBDEludGVnZXJFbnRyeQIFEWtTaGFyZUFzc2V0U3VwcGx5CQBkAgULc2hhcmVTdXBwbHkFC21pbnRfYW1vdW50CQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQDOCAIFDXNjcmlwdEFjdGlvbnMJAMwIAgkBB1JlaXNzdWUDBQxzaGFyZUFzc2V0SWQFC21pbnRfYW1vdW50BgkAzAgCCQEOU2NyaXB0VHJhbnNmZXIDCAUDbXNnBmNhbGxlcgULbWludF9hbW91bnQFDHNoYXJlQXNzZXRJZAkAzAgCCQEMSW50ZWdlckVudHJ5AgURa1NoYXJlQXNzZXRTdXBwbHkJAGQCBQtzaGFyZVN1cHBseQULbWludF9hbW91bnQFA25pbANtc2cBDmNhbGNNaW50QW1vdW50AgtuZXdCYWxhbmNlcwR1c2VyBANhbXAJAQJfQQAEAnhwCQEDX3hwAAQCRDEJAQdnZXRETWVtAgULbmV3QmFsYW5jZXMFA2FtcAMJAAACBQtzaGFyZVN1cHBseQAACQCUCgIFA25pbAUCRDEEAkQwCQEHZ2V0RE1lbQIFAnhwBQNhbXAEC2ZlZURpc2NvdW50CQEUY2FsY3VsYXRlRmVlRGlzY291bnQBBQR1c2VyCgEPY2FsY0ludkJhbGFuY2VzAgNhY2MKbmV3QmFsYW5jZQQNJHQwMjAzMjEyMDM0NwUDYWNjBAtpbnZCYWxhbmNlcwgFDSR0MDIwMzIxMjAzNDcCXzEEAWkIBQ0kdDAyMDMyMTIwMzQ3Al8yBARfZmVlCQBpAgkAaAIJAG4EBQNmZWUFC2ZlZURpc2NvdW50BQlmZWVTY2FsZTYFB0NFSUxJTkcFBm5Db2lucwkAaAIABAkAZQIFBm5Db2lucwABBARmZWVzBAxpZGVhbEJhbGFuY2UJAGsDBQJEMQkAkQMCBQJ4cAUBaQUCRDAECmRpZmZlcmVuY2UDCQBmAgUMaWRlYWxCYWxhbmNlBQpuZXdCYWxhbmNlCQBlAgUMaWRlYWxCYWxhbmNlBQpuZXdCYWxhbmNlCQBlAgUKbmV3QmFsYW5jZQUMaWRlYWxCYWxhbmNlCQBrAwUEX2ZlZQUKZGlmZmVyZW5jZQUJZmVlU2NhbGU2BBBpbnZhcmlhbnRCYWxhbmNlCQBlAgUKbmV3QmFsYW5jZQUEZmVlcwkAlAoCCQDNCAIFC2ludkJhbGFuY2VzBRBpbnZhcmlhbnRCYWxhbmNlCQBkAgUBaQABBA0kdDAyMDk0OTIxMDE5CgACJGwFC25ld0JhbGFuY2VzCgACJHMJAJADAQUCJGwKAAUkYWNjMAkAlAoCBQNuaWwAAAoBBSRmMF8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQEPY2FsY0ludkJhbGFuY2VzAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGYwXzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhRMaXN0IHNpemUgZXhjZWVkcyAxMAkBBSRmMF8yAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgUFJGFjYzAAAAABAAIAAwAEAAUABgAHAAgACQAKBAtpbnZCYWxhbmNlcwgFDSR0MDIwOTQ5MjEwMTkCXzEEAWsIBQ0kdDAyMDk0OTIxMDE5Al8yBAJEMgkBB2dldERNZW0CBQtpbnZCYWxhbmNlcwUDYW1wBAptaW50QW1vdW50CQBrAwULc2hhcmVTdXBwbHkJAGUCBQJEMgUCRDAFAkQwCQCUCgIFA25pbAUKbWludEFtb3VudANtc2cBDHJlaXNzdWVTaGFyZQEGYW1vdW50CQELdmFsdWVPckVsc2UCCQEKaXNTZWxmQ2FsbAEFA21zZwkAzAgCCQEHUmVpc3N1ZQMFDHNoYXJlQXNzZXRJZAUGYW1vdW50BgUDbmlsA21zZwEFZ2V0RHkECWFzc2V0RnJvbQdhc3NldFRvAmR4C3VzZXJBZGRyZXNzBAJ4cAkBA194cAAECWZyb21JbmRleAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQDPCAIFCGFzc2V0SWRzBQlhc3NldEZyb20CEHVua25vd24gdG9rZW4gaW4EB3RvSW5kZXgJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAzwgCBQhhc3NldElkcwUHYXNzZXRUbwIRdW5rbm93biB0b2tlbiBvdXQEAXgJAGQCCQCRAwIFAnhwBQlmcm9tSW5kZXgFAmR4BAF5CQEEZ2V0WQQFCWZyb21JbmRleAUHdG9JbmRleAUBeAUCeHAEAmR5CQBlAgkAZQIJAJEDAgUCeHAFB3RvSW5kZXgFAXkAAQQLZmVlRGlzY291bnQJARRjYWxjdWxhdGVGZWVEaXNjb3VudAEJAQdBZGRyZXNzAQkA2QQBBQt1c2VyQWRkcmVzcwQEX2ZlZQkAawMJAG4EBQNmZWUFC2ZlZURpc2NvdW50BQlmZWVTY2FsZTYFB0NFSUxJTkcFAmR5BQlmZWVTY2FsZTYJAJQKAgUDbmlsCQCUCgIJAGUCBQJkeQUEX2ZlZQUEX2ZlZQNtc2cBCGV4Y2hhbmdlAgh0b2tlbk91dAZtaW5fZHkJAQt2YWx1ZU9yRWxzZQIJAQhpc0FjdGl2ZQADCQECIT0CCQCQAwEIBQNtc2cIcGF5bWVudHMAAQkAAgECE3NpemUocGF5bWVudHMpICE9IDEECnN1c3BpY2lvdXMJAQ9jaGVja1N1c3BpY2lvdXMAAwgFCnN1c3BpY2lvdXMCXzEJAM4IAgkBEXN1c3BlbmRTdXNwaWNpb3VzAQgFCnN1c3BpY2lvdXMCXzIJAQ5yZXR1cm5QYXltZW50cwIIBQNtc2cGY2FsbGVyCAUDbXNnCHBheW1lbnRzBAdwYXltZW50CQCRAwIIBQNtc2cIcGF5bWVudHMAAAQHdG9rZW5JbgkBDWdldFN0ckFzc2V0SWQBCAUHcGF5bWVudAdhc3NldElkBAt0b2tlbk91dEI1OAkA2QQBBQh0b2tlbk91dAQCZHgIBQdwYXltZW50BmFtb3VudAQJZnJvbUluZGV4CQETdmFsdWVPckVycm9yTWVzc2FnZQIJAM8IAgUIYXNzZXRJZHMFB3Rva2VuSW4CEHVua25vd24gdG9rZW4gaW4EB3RvSW5kZXgJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAzwgCBQhhc3NldElkcwUIdG9rZW5PdXQCEXVua25vd24gdG9rZW4gb3V0BAJ4cAkBA194cAAEAXgJAGQCCQCRAwIFAnhwBQlmcm9tSW5kZXgFAmR4BAF5CQEEZ2V0WQQFCWZyb21JbmRleAUHdG9JbmRleAUBeAUCeHAEA19keQkAZQIJAGUCCQCRAwIFAnhwBQd0b0luZGV4BQF5AAEEC2ZlZURpc2NvdW50CQEUY2FsY3VsYXRlRmVlRGlzY291bnQBCAUDbXNnDG9yaWdpbkNhbGxlcgQEX2ZlZQkAawMFA19keQkAbgQFA2ZlZQULZmVlRGlzY291bnQFCWZlZVNjYWxlNgUHQ0VJTElORwUJZmVlU2NhbGU2BAJkeQkAZQIFA19keQUEX2ZlZQQOZ292ZXJuYW5jZUZlZXMJAGsDBQRfZmVlBQ1mZWVHb3Zlcm5hbmNlBQlmZWVTY2FsZTYDCQEGYXNzZXJ0AQkAZwIFAmR5BQZtaW5fZHkJAAIBAi5FeGNoYW5nZSByZXN1bHRlZCBpbiBmZXdlciBjb2lucyB0aGFuIGV4cGVjdGVkCgEPbWFrZU5ld0JhbGFuY2VzAgNhY2MMdG9rZW5CYWxhbmNlBA0kdDAyMzA2MDIzMDg2BQNhY2MEC25ld0JhbGFuY2VzCAUNJHQwMjMwNjAyMzA4NgJfMQQBaQgFDSR0MDIzMDYwMjMwODYCXzIDCQAAAgUBaQUJZnJvbUluZGV4CQCUCgIJAM0IAgULbmV3QmFsYW5jZXMJAGQCBQx0b2tlbkJhbGFuY2UFAmR4CQBkAgUBaQABAwkAAAIFAWkFB3RvSW5kZXgJAJQKAgkAzQgCBQtuZXdCYWxhbmNlcwkAZQIFDHRva2VuQmFsYW5jZQUDX2R5CQBkAgUBaQABCQCUCgIJAM0IAgULbmV3QmFsYW5jZXMFDHRva2VuQmFsYW5jZQkAZAIFAWkAAQQNJHQwMjMzMzcyMzM5OAoAAiRsBQJ4cAoAAiRzCQCQAwEFAiRsCgAFJGFjYzAJAJQKAgUDbmlsAAAKAQUkZjBfMQICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkBD21ha2VOZXdCYWxhbmNlcwIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmMF8yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQIUTGlzdCBzaXplIGV4Y2VlZHMgMTAJAQUkZjBfMgIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYABwAIAAkACgQLbmV3QmFsYW5jZXMIBQ0kdDAyMzMzNzIzMzk4Al8xBAFpCAUNJHQwMjMzMzcyMzM5OAJfMgMJARJjaGVja0RBcHBUaHJlc2hvbGQBBQtuZXdCYWxhbmNlcwkBBXRocm93AAQBcwkBBXN0YWtlAggFB3BheW1lbnQGYW1vdW50CQENZ2V0U3RyQXNzZXRJZAEIBQdwYXltZW50B2Fzc2V0SWQDCQAAAgUBcwUBcwQCdXMJAQd1bnN0YWtlAgUDX2R5BQh0b2tlbk91dAMJAAACBQJ1cwUCdXMEBmxwRmVlcwkAZQIFBF9mZWUFDmdvdmVybmFuY2VGZWVzBAdhaXJkcm9wAwkAZgIFBmxwRmVlcwAACQD8BwQFEGxwRmFybWluZ0FkZHJlc3MCB2FpckRyb3AFA25pbAkAzAgCCQEPQXR0YWNoZWRQYXltZW50AgULdG9rZW5PdXRCNTgFBmxwRmVlcwUDbmlsAAADCQAAAgUHYWlyZHJvcAUHYWlyZHJvcAkAlAoCCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQCsAgIFB3Rva2VuSW4FDWtBc3NldEJhbGFuY2UFAXgJAMwIAgkBDEludGVnZXJFbnRyeQIJAKwCAgUIdG9rZW5PdXQFDWtBc3NldEJhbGFuY2UJAGUCCQCRAwIFAnhwBQd0b0luZGV4BQNfZHkJAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwgFA21zZwZjYWxsZXIFAmR5BQt0b2tlbk91dEI1OAkAzAgCCQEOU2NyaXB0VHJhbnNmZXIDBQ9tb25leUJveEFkZHJlc3MFDmdvdmVybmFuY2VGZWVzBQt0b2tlbk91dEI1OAUDbmlsCQDMCAIFAmR5CQDMCAIFC3Rva2VuT3V0QjU4BQNuaWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4DbXNnAQh3aXRoZHJhdwEKbWluQW1vdW50cwkBC3ZhbHVlT3JFbHNlAgkBCGlzQWN0aXZlAAMJAQIhPQIJAJADAQgFA21zZwhwYXltZW50cwABCQACAQITc2l6ZShwYXltZW50cykgIT0gMQQJcG10QW1vdW50CAkAkQMCCAUDbXNnCHBheW1lbnRzAAAGYW1vdW50BApwbXRBc3NldElkCAkAkQMCCAUDbXNnCHBheW1lbnRzAAAHYXNzZXRJZAMJAQIhPQIFDHNoYXJlQXNzZXRJZAUKcG10QXNzZXRJZAkAAgECFXVua25vd24gcGF5bWVudCB0b2tlbgQKc3VzcGljaW91cwkBD2NoZWNrU3VzcGljaW91cwADCAUKc3VzcGljaW91cwJfMQkAzggCCQERc3VzcGVuZFN1c3BpY2lvdXMBCAUKc3VzcGljaW91cwJfMgkBDnJldHVyblBheW1lbnRzAggFA21zZwxvcmlnaW5DYWxsZXIIBQNtc2cIcGF5bWVudHMKARFjYWxjU2NyaXB0QWN0aW9ucwIDYWNjB2JhbGFuY2UEDSR0MDI0Njg5MjQ3MTcFA2FjYwQNc2NyaXB0QWN0aW9ucwgFDSR0MDI0Njg5MjQ3MTcCXzEEAWkIBQ0kdDAyNDY4OTI0NzE3Al8yBAd3QW1vdW50CQBrAwUHYmFsYW5jZQUJcG10QW1vdW50BQtzaGFyZVN1cHBseQMJAQZhc3NlcnQBCQBnAgUHd0Ftb3VudAkAkQMCBQptaW5BbW91bnRzBQFpCQACAQIwV2l0aGRyYXdhbCByZXN1bHRlZCBpbiBmZXdlciBjb2lucyB0aGFuIGV4cGVjdGVkBAJ1cwkBB3Vuc3Rha2UCBQd3QW1vdW50CQCRAwIFCGFzc2V0SWRzBQFpAwkAAAIFAnVzBQJ1cwkAlAoCCQDOCAIFDXNjcmlwdEFjdGlvbnMJAMwIAgkBDEludGVnZXJFbnRyeQIJAKwCAgkAkQMCBQhhc3NldElkcwUBaQUNa0Fzc2V0QmFsYW5jZQkAZQIFB2JhbGFuY2UFB3dBbW91bnQJAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwgFA21zZwxvcmlnaW5DYWxsZXIFB3dBbW91bnQJANkEAQkAkQMCBQhhc3NldElkcwUBaQUDbmlsCQBkAgUBaQABCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuBA0kdDAyNTIwNzI1Mjc1CgACJGwJAQNfeHAACgACJHMJAJADAQUCJGwKAAUkYWNjMAkAlAoCBQNuaWwAAAoBBSRmMF8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQERY2FsY1NjcmlwdEFjdGlvbnMCBQIkYQkAkQMCBQIkbAUCJGkKAQUkZjBfMgICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkAAgECFExpc3Qgc2l6ZSBleGNlZWRzIDEwCQEFJGYwXzICCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECBQUkYWNjMAAAAAEAAgADAAQABQAGAAcACAAJAAoEDXNjcmlwdEFjdGlvbnMIBQ0kdDAyNTIwNzI1Mjc1Al8xBAFpCAUNJHQwMjUyMDcyNTI3NQJfMgkAzggCBQ1zY3JpcHRBY3Rpb25zCQDMCAIJAQRCdXJuAgUMc2hhcmVBc3NldElkBQlwbXRBbW91bnQJAMwIAgkBDEludGVnZXJFbnRyeQIFEWtTaGFyZUFzc2V0U3VwcGx5CQBlAgULc2hhcmVTdXBwbHkFCXBtdEFtb3VudAUDbmlsA21zZwESd2l0aGRyYXdXaXRoVW5sb2NrAgptaW5BbW91bnRzDHVubG9ja0Ftb3VudAkBC3ZhbHVlT3JFbHNlAgkBCGlzQWN0aXZlAAMJAGcCAAAFDHVubG9ja0Ftb3VudAkAAgECHlVubG9jayBhbW91bnQgbXVzdCBiZSBwb3NpdGl2ZQQKc3VzcGljaW91cwkBD2NoZWNrU3VzcGljaW91cwADCAUKc3VzcGljaW91cwJfMQkAzggCCQERc3VzcGVuZFN1c3BpY2lvdXMBCAUKc3VzcGljaW91cwJfMgkBDnJldHVyblBheW1lbnRzAggFA21zZwZjYWxsZXIIBQNtc2cIcGF5bWVudHMECXBtdEFtb3VudAMJAGYCCQCQAwEIBQNtc2cIcGF5bWVudHMAAAMJAQIhPQIJAJADAQgFA21zZwhwYXltZW50cwABCQACAQITc2l6ZShwYXltZW50cykgIT0gMQQKcG10QXNzZXRJZAgJAJEDAggFA21zZwhwYXltZW50cwAAB2Fzc2V0SWQDCQECIT0CBQxzaGFyZUFzc2V0SWQFCnBtdEFzc2V0SWQJAAIBAhV1bmtub3duIHBheW1lbnQgdG9rZW4ICQCRAwIIBQNtc2cIcGF5bWVudHMAAAZhbW91bnQAAAQGdW5sb2NrCQD8BwQFDmZhcm1pbmdBZGRyZXNzAhN3aXRoZHJhd1NoYXJlVG9rZW5zCQDMCAIJAKUIAQUEdGhpcwkAzAgCBQx1bmxvY2tBbW91bnQFA25pbAUDbmlsAwkAAAIFBnVubG9jawUGdW5sb2NrBA53aXRoZHJhd0Ftb3VudAkAZAIFCXBtdEFtb3VudAUMdW5sb2NrQW1vdW50BANpbnYJAPwHBAUEdGhpcwIId2l0aGRyYXcJAMwIAgUKbWluQW1vdW50cwUDbmlsCQDMCAIJAQ9BdHRhY2hlZFBheW1lbnQCBQxzaGFyZUFzc2V0SWQFDndpdGhkcmF3QW1vdW50BQNuaWwDCQAAAgUDaW52BQNpbnYFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgNtc2cBE2NhbGNXaXRoZHJhd09uZUNvaW4DC3Rva2VuQW1vdW50CHRva2VuT3V0BHVzZXIDCQBnAgAABQt0b2tlbkFtb3VudAkAAgECF0Ftb3VudCBtdXN0IGJlIHBvc2l0aXZlBAFpCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAM8IAgUIYXNzZXRJZHMFCHRva2VuT3V0AhF1bmtub3duIHRva2VuIG91dAkAlAoCBQNuaWwICQEUX2NhbGNXaXRoZHJhd09uZUNvaW4ECQEDX3hwAAULdG9rZW5BbW91bnQFAWkJAQdBZGRyZXNzAQkA2QQBBQR1c2VyAl8xA21zZwEPd2l0aGRyYXdPbmVDb2luAgh0b2tlbk91dAltaW5BbW91bnQJAQt2YWx1ZU9yRWxzZQIJAQhpc0FjdGl2ZQADCQECIT0CCQCQAwEIBQNtc2cIcGF5bWVudHMAAQkAAgECE3NpemUocGF5bWVudHMpICE9IDEECnN1c3BpY2lvdXMJAQ9jaGVja1N1c3BpY2lvdXMAAwgFCnN1c3BpY2lvdXMCXzEJAM4IAgkBEXN1c3BlbmRTdXNwaWNpb3VzAQgFCnN1c3BpY2lvdXMCXzIJAQ5yZXR1cm5QYXltZW50cwIIBQNtc2cMb3JpZ2luQ2FsbGVyCAUDbXNnCHBheW1lbnRzBAlwbXRBbW91bnQICQCRAwIIBQNtc2cIcGF5bWVudHMAAAZhbW91bnQECnBtdEFzc2V0SWQICQCRAwIIBQNtc2cIcGF5bWVudHMAAAdhc3NldElkAwkBAiE9AgUKcG10QXNzZXRJZAUMc2hhcmVBc3NldElkCQACAQINdW5rbm93biB0b2tlbgQIb3V0SW5kZXgJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAzwgCBQhhc3NldElkcwUIdG9rZW5PdXQCEXVua25vd24gdG9rZW4gb3V0BAt0b2tlbk91dEI1OAkA2QQBBQh0b2tlbk91dAQCeHAJAQNfeHAABA0kdDAyNzMwNzI3Mzg5CQEUX2NhbGNXaXRoZHJhd09uZUNvaW4EBQJ4cAUJcG10QW1vdW50BQhvdXRJbmRleAgFA21zZwxvcmlnaW5DYWxsZXIEAmR5CAUNJHQwMjczMDcyNzM4OQJfMQQGZHlfZmVlCAUNJHQwMjczMDcyNzM4OQJfMgMJAQZhc3NlcnQBCQBnAgUCZHkFCW1pbkFtb3VudAkAAgECGE5vdCBlbm91Z2ggY29pbnMgcmVtb3ZlZAQOZ292ZXJuYW5jZUZlZXMJAGsDBQZkeV9mZWUFDWZlZUdvdmVybmFuY2UFCWZlZVNjYWxlNgQKZHlfYW5kX2ZlZQkAZAIFAmR5BQZkeV9mZWUKAQ9tYWtlTmV3QmFsYW5jZXMCA2FjYwx0b2tlbkJhbGFuY2UEDSR0MDI3NjQ3Mjc2NzMFA2FjYwQLbmV3QmFsYW5jZXMIBQ0kdDAyNzY0NzI3NjczAl8xBAFpCAUNJHQwMjc2NDcyNzY3MwJfMgMJAAACBQFpBQhvdXRJbmRleAkAlAoCCQDNCAIFC25ld0JhbGFuY2VzCQBlAgUMdG9rZW5CYWxhbmNlBQpkeV9hbmRfZmVlCQBkAgUBaQABCQCUCgIJAM0IAgULbmV3QmFsYW5jZXMFDHRva2VuQmFsYW5jZQkAZAIFAWkAAQQNJHQwMjc4NDAyNzkwMQoAAiRsBQJ4cAoAAiRzCQCQAwEFAiRsCgAFJGFjYzAJAJQKAgUDbmlsAAAKAQUkZjBfMQICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkBD21ha2VOZXdCYWxhbmNlcwIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmMF8yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQIUTGlzdCBzaXplIGV4Y2VlZHMgMTAJAQUkZjBfMgIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYABwAIAAkACgQLbmV3QmFsYW5jZXMIBQ0kdDAyNzg0MDI3OTAxAl8xBAF2CAUNJHQwMjc4NDAyNzkwMQJfMgMJARJjaGVja0RBcHBUaHJlc2hvbGQBBQtuZXdCYWxhbmNlcwkBBXRocm93AAQCdXMJAQd1bnN0YWtlAgUKZHlfYW5kX2ZlZQUIdG9rZW5PdXQDCQAAAgUCdXMFAnVzBAZscEZlZXMJAGUCBQZkeV9mZWUFDmdvdmVybmFuY2VGZWVzBAdhaXJkcm9wAwkAZgIFBmxwRmVlcwAACQD8BwQFEGxwRmFybWluZ0FkZHJlc3MCB2FpckRyb3AFA25pbAkAzAgCCQEPQXR0YWNoZWRQYXltZW50AgULdG9rZW5PdXRCNTgFBmxwRmVlcwUDbmlsAAADCQAAAgUHYWlyZHJvcAUHYWlyZHJvcAkAzAgCCQEOU2NyaXB0VHJhbnNmZXIDCAUDbXNnDG9yaWdpbkNhbGxlcgUCZHkFC3Rva2VuT3V0QjU4CQDMCAIJAQxJbnRlZ2VyRW50cnkCCQCsAgIJAJEDAgUIYXNzZXRJZHMFCG91dEluZGV4BQ1rQXNzZXRCYWxhbmNlCQBlAgkAkQMCBQJ4cAUIb3V0SW5kZXgFCmR5X2FuZF9mZWUJAMwIAgkBBEJ1cm4CBQxzaGFyZUFzc2V0SWQFCXBtdEFtb3VudAkAzAgCCQEOU2NyaXB0VHJhbnNmZXIDBQ9tb25leUJveEFkZHJlc3MFDmdvdmVybmFuY2VGZWVzBQt0b2tlbk91dEI1OAkAzAgCCQEMSW50ZWdlckVudHJ5AgURa1NoYXJlQXNzZXRTdXBwbHkJAGUCBQtzaGFyZVN1cHBseQUJcG10QW1vdW50BQNuaWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4DbXNnARl3aXRoZHJhd09uZUNvaW5XaXRoVW5sb2NrAwh0b2tlbk91dAltaW5BbW91bnQMdW5sb2NrQW1vdW50CQELdmFsdWVPckVsc2UCCQEIaXNBY3RpdmUAAwkAZwIAAAUMdW5sb2NrQW1vdW50CQACAQIeVW5sb2NrIGFtb3VudCBtdXN0IGJlIHBvc2l0aXZlBApzdXNwaWNpb3VzCQEPY2hlY2tTdXNwaWNpb3VzAAMIBQpzdXNwaWNpb3VzAl8xCQDOCAIJARFzdXNwZW5kU3VzcGljaW91cwEIBQpzdXNwaWNpb3VzAl8yCQEOcmV0dXJuUGF5bWVudHMCCAUDbXNnBmNhbGxlcggFA21zZwhwYXltZW50cwQJcG10QW1vdW50AwkAZgIJAJADAQgFA21zZwhwYXltZW50cwAAAwkBAiE9AgkAkAMBCAUDbXNnCHBheW1lbnRzAAEJAAIBAhNzaXplKHBheW1lbnRzKSAhPSAxBApwbXRBc3NldElkCAkAkQMCCAUDbXNnCHBheW1lbnRzAAAHYXNzZXRJZAMJAQIhPQIFDHNoYXJlQXNzZXRJZAUKcG10QXNzZXRJZAkAAgECFXVua25vd24gcGF5bWVudCB0b2tlbggJAJEDAggFA21zZwhwYXltZW50cwAABmFtb3VudAAABAZ1bmxvY2sJAPwHBAUOZmFybWluZ0FkZHJlc3MCE3dpdGhkcmF3U2hhcmVUb2tlbnMJAMwIAgkApQgBBQR0aGlzCQDMCAIFDHVubG9ja0Ftb3VudAUDbmlsBQNuaWwDCQAAAgUGdW5sb2NrBQZ1bmxvY2sEDndpdGhkcmF3QW1vdW50CQBkAgUJcG10QW1vdW50BQx1bmxvY2tBbW91bnQEA2ludgkA/AcEBQR0aGlzAg93aXRoZHJhd09uZUNvaW4JAMwIAgUIdG9rZW5PdXQJAMwIAgUJbWluQW1vdW50BQNuaWwJAMwIAgkBD0F0dGFjaGVkUGF5bWVudAIFDHNoYXJlQXNzZXRJZAUOd2l0aGRyYXdBbW91bnQFA25pbAMJAAACBQNpbnYFA2ludgUDbmlsCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuA21zZwEBQQAJAJQKAgUDbmlsCQECX0EAA21zZwEPZ2V0VmlydHVhbFByaWNlAAQBRAkBBWdldF9EAgkBA194cAAJAQJfQQAJAJQKAgUDbmlsCQBrAwUBRAUJUFJFQ0lTSU9OBQtzaGFyZVN1cHBseQNtc2cBD2NhbGNUb2tlbkFtb3VudAIHYW1vdW50cwdkZXBvc2l0BANhbXAJAQJfQQAECGJhbGFuY2VzCQEDX3hwAAQCRDAJAQdnZXRETWVtAgUIYmFsYW5jZXMFA2FtcAoBD2NhbGNOZXdCYWxhbmNlcwIDYWNjB2JhbGFuY2UEDSR0MDI5OTE4Mjk5NDQFA2FjYwQLbmV3QmFsYW5jZXMIBQ0kdDAyOTkxODI5OTQ0Al8xBAFpCAUNJHQwMjk5MTgyOTk0NAJfMgQKbmV3QmFsYW5jZQkAZAIFB2JhbGFuY2UDBQdkZXBvc2l0CQCRAwIFB2Ftb3VudHMFAWkJAQEtAQkAkQMCBQdhbW91bnRzBQFpCQCUCgIJAM0IAgULbmV3QmFsYW5jZXMFCm5ld0JhbGFuY2UJAGQCBQFpAAEEC25ld0JhbGFuY2VzCAoAAiRsBQhiYWxhbmNlcwoAAiRzCQCQAwEFAiRsCgAFJGFjYzAJAJQKAgUDbmlsAAAKAQUkZjBfMQICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkBD2NhbGNOZXdCYWxhbmNlcwIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmMF8yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQIUTGlzdCBzaXplIGV4Y2VlZHMgMTAJAQUkZjBfMgIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYABwAIAAkACgJfMQQCRDEJAQdnZXRETWVtAgULbmV3QmFsYW5jZXMFA2FtcAQEZGlmZgMFB2RlcG9zaXQJAGUCBQJEMQUCRDAJAGUCBQJEMAUCRDEJAJQKAgUDbmlsCQBrAwUEZGlmZgULc2hhcmVTdXBwbHkFAkQwA21zZwEFcmFtcEECCF9mdXR1cmVBC19mdXR1cmVUaW1lCQELdmFsdWVPckVsc2UCCQEIaXNBY3RpdmUACQELdmFsdWVPckVsc2UCCQELaXNBZG1pbkNhbGwBBQNtc2cDCQEGYXNzZXJ0AQkAZwIFDmJsb2NrVGltZXN0YW1wCQBkAgUOaW5pdGlhbF9BX3RpbWUFDU1JTl9SQU1QX1RJTUUJAAIBAgl0b28gb2Z0ZW4DCQEGYXNzZXJ0AQkAZwIFC19mdXR1cmVUaW1lCQBkAgUOYmxvY2tUaW1lc3RhbXAFDU1JTl9SQU1QX1RJTUUJAAIBAhFpbnN1ZmZpY2llbnQgdGltZQQKX2luaXRpYWxfQQkBAl9BAAMJAQZhc3NlcnQBAwkAZgIFCF9mdXR1cmVBAAAJAGYCBQVNQVhfQQUIX2Z1dHVyZUEHCQACAQIRb3V0IG9mIGJhc2UgcmFuZ2UDCQEGYXNzZXJ0AQMDCQBnAgUIX2Z1dHVyZUEFCl9pbml0aWFsX0EJAGcCCQBoAgUKX2luaXRpYWxfQQUMTUFYX0FfQ0hBTkdFBQhfZnV0dXJlQQcGAwkAZgIFCl9pbml0aWFsX0EFCF9mdXR1cmVBCQBnAgkAaAIFCF9mdXR1cmVBBQxNQVhfQV9DSEFOR0UFCl9pbml0aWFsX0EHCQACAQIMb3V0IG9mIHJhbmdlCQDMCAIJAQxJbnRlZ2VyRW50cnkCAglpbml0aWFsX0EFCl9pbml0aWFsX0EJAMwIAgkBDEludGVnZXJFbnRyeQICCGZ1dHVyZV9BBQhfZnV0dXJlQQkAzAgCCQEMSW50ZWdlckVudHJ5AgIOaW5pdGlhbF9BX3RpbWUFDmJsb2NrVGltZXN0YW1wCQDMCAIJAQxJbnRlZ2VyRW50cnkCAg1mdXR1cmVfQV90aW1lBQtfZnV0dXJlVGltZQUDbmlsA21zZwEJc3RvcFJhbXBBAAkBC3ZhbHVlT3JFbHNlAgkBCGlzQWN0aXZlAAkBC3ZhbHVlT3JFbHNlAgkBC2lzQWRtaW5DYWxsAQUDbXNnBAhjdXJyZW50QQkBAl9BAAkAzAgCCQEMSW50ZWdlckVudHJ5AgIJaW5pdGlhbF9BBQhjdXJyZW50QQkAzAgCCQEMSW50ZWdlckVudHJ5AgIIZnV0dXJlX0EFCGN1cnJlbnRBCQDMCAIJAQxJbnRlZ2VyRW50cnkCAg5pbml0aWFsX0FfdGltZQUOYmxvY2tUaW1lc3RhbXAJAMwIAgkBDEludGVnZXJFbnRyeQICDWZ1dHVyZV9BX3RpbWUFDmJsb2NrVGltZXN0YW1wBQNuaWwDbXNnAQhzaHV0ZG93bgAJAQt2YWx1ZU9yRWxzZQIJAQtpc0FkbWluQ2FsbAEFA21zZwMJAQEhAQUGYWN0aXZlCQACAQkArAICAiJEQXBwIGlzIGFscmVhZHkgc3VzcGVuZGVkLiBDYXVzZTogCQELdmFsdWVPckVsc2UCCQCdCAIFBHRoaXMFBmtDYXVzZQIadGhlIGNhdXNlIHdhc24ndCBzcGVjaWZpZWQJAQdzdXNwZW5kAQIPUGF1c2VkIGJ5IGFkbWluA21zZwEIYWN0aXZhdGUACQELdmFsdWVPckVsc2UCCQELaXNBZG1pbkNhbGwBBQNtc2cDBQZhY3RpdmUJAQ10aHJvd0lzQWN0aXZlAAkAzAgCCQEMQm9vbGVhbkVudHJ5AgUHa0FjdGl2ZQYJAMwIAgkBC0RlbGV0ZUVudHJ5AQUGa0NhdXNlBQNuaWwDbXNnARl0YWtlSW50b0FjY291bnRFeHRyYUZ1bmRzAAkBC3ZhbHVlT3JFbHNlAgkBCGlzQWN0aXZlAAMJAQIhPQIIBQNtc2cGY2FsbGVyBQ9tb25leUJveEFkZHJlc3MJAAIBAiZPbmx5IHRoZSB3YWxsZXQgY2FuIGNhbGwgdGhpcyBmdW5jdGlvbgQIYmFsYW5jZXMJAQNfeHAACgEOdGFrZUV4dHJhRnVuZHMCA2FjYwdhc3NldElkBA0kdDAzMjI4NjMyMzA0BQNhY2MEA3N1bQgFDSR0MDMyMjg2MzIzMDQCXzEEAWkIBQ0kdDAzMjI4NjMyMzA0Al8yBAh0b2tlbkI1OAkA2QQBBQdhc3NldElkBAhyQmFsYW5jZQkAZAIJAPAHAgUEdGhpcwUIdG9rZW5CNTgJAQxzdGFrZWRBbW91bnQBBQh0b2tlbkI1OAQMZW5yb2xsQW1vdW50CQBlAgUIckJhbGFuY2UJAJEDAgUIYmFsYW5jZXMFAWkDCQBmAgAABQxlbnJvbGxBbW91bnQJAQdzdXNwZW5kAQkArAICAiBFbnJvbGwgYW1vdW50IG5lZ2F0aXZlIGZvciBhc3NldAUHYXNzZXRJZAQHYWlyZHJvcAMJAGYCBQxlbnJvbGxBbW91bnQAAAkA/AcEBRBscEZhcm1pbmdBZGRyZXNzAgdhaXJEcm9wBQNuaWwJAMwIAgkBD0F0dGFjaGVkUGF5bWVudAIFCHRva2VuQjU4BQxlbnJvbGxBbW91bnQFA25pbAAAAwkAAAIFB2FpcmRyb3AFB2FpcmRyb3AJAJQKAgkAZAIFA3N1bQUMZW5yb2xsQW1vdW50CQBkAgUBaQABCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuBAFrCgACJGwFCGFzc2V0SWRzCgACJHMJAJADAQUCJGwKAAUkYWNjMAkAlAoCAAAAAAoBBSRmMF8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQEOdGFrZUV4dHJhRnVuZHMCBQIkYQkAkQMCBQIkbAUCJGkKAQUkZjBfMgICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkAAgECFExpc3Qgc2l6ZSBleGNlZWRzIDEwCQEFJGYwXzICCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECBQUkYWNjMAAAAAEAAgADAAQABQAGAAcACAAJAAoDCQAAAggFAWsCXzEAAAkAAgECEE5vIG1vbmV5IHRvIHRha2UFA25pbAECdHgBBnZlcmlmeQAEE211bHRpU2lnbmVkQnlBZG1pbnMEEmFkbWluUHViS2V5MVNpZ25lZAMJAPQDAwgFAnR4CWJvZHlCeXRlcwkAkQMCCAUCdHgGcHJvb2ZzAAAFDGFkbWluUHViS2V5MQABAAAEEmFkbWluUHViS2V5MlNpZ25lZAMJAPQDAwgFAnR4CWJvZHlCeXRlcwkAkQMCCAUCdHgGcHJvb2ZzAAEFDGFkbWluUHViS2V5MgABAAAEEmFkbWluUHViS2V5M1NpZ25lZAMJAPQDAwgFAnR4CWJvZHlCeXRlcwkAkQMCCAUCdHgGcHJvb2ZzAAIFDGFkbWluUHViS2V5MwABAAAJAGcCCQBkAgkAZAIFEmFkbWluUHViS2V5MVNpZ25lZAUSYWRtaW5QdWJLZXkyU2lnbmVkBRJhZG1pblB1YktleTNTaWduZWQAAgQHJG1hdGNoMAUCdHgDCQABAgUHJG1hdGNoMAIXSW52b2tlU2NyaXB0VHJhbnNhY3Rpb24EA2ludgUHJG1hdGNoMAQTY2FsbFRha2VJbnRvQWNjb3VudAMJAAACCAUDaW52BGRBcHAFBHRoaXMJAAACCAUDaW52CGZ1bmN0aW9uAhl0YWtlSW50b0FjY291bnRFeHRyYUZ1bmRzBwQNc2lnbmVkQnlBZG1pbgMDAwkA9AMDCAUCdHgJYm9keUJ5dGVzCQCRAwIIBQJ0eAZwcm9vZnMAAAUMYWRtaW5QdWJLZXkxBgkA9AMDCAUCdHgJYm9keUJ5dGVzCQCRAwIIBQJ0eAZwcm9vZnMAAAUMYWRtaW5QdWJLZXkyBgkA9AMDCAUCdHgJYm9keUJ5dGVzCQCRAwIIBQJ0eAZwcm9vZnMAAAUMYWRtaW5QdWJLZXkzBgkA9AMDCAUCdHgJYm9keUJ5dGVzCQCRAwIIBQJ0eAZwcm9vZnMAAAURYWRtaW5QdWJLZXlJbnZva2UDAwUTY2FsbFRha2VJbnRvQWNjb3VudAUNc2lnbmVkQnlBZG1pbgcGBRNtdWx0aVNpZ25lZEJ5QWRtaW5zBRNtdWx0aVNpZ25lZEJ5QWRtaW5zd7UmCg==", "height": 2288049, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: 9r6q9uHzeFeefwaZa5uNC57M1SAfhYzTpqJAeV2XQ3XW Next: 5URz3rJ5QufQvyiZQKoRFhgyyBdtv2KNmW9N7WYrzVtx Diff:
OldNewDifferences
11 {-# STDLIB_VERSION 6 #-}
22 {-# SCRIPT_TYPE ACCOUNT #-}
33 {-# CONTENT_TYPE DAPP #-}
4+let PRECISION = 1000000
5+
6+let MAX_A = 1000000
7+
8+let MAX_A_CHANGE = 10
9+
10+let DECIMALS = 6
11+
12+let MIN_RAMP_TIME = (86400 / 60)
13+
14+let version = "3.0.0"
15+
16+let kVersion = "version"
17+
18+let kAssets = "asset_ids"
19+
20+let kAssetBalance = "_balance"
21+
422 let kActive = "active"
5-
6-let kActiveGlob = "active_all_contracts"
723
824 let kCause = "shutdown_cause"
925
10-let kRewardPoolFractionCurrent = "_current_pool_fraction_reward"
26+let kShareAssetId = "share_asset_id"
1127
12-let kRewardPoolFractionPrevious = "_previous_pool_fraction_reward"
28+let kShareAssetSupply = "share_asset_supply"
1329
14-let kHeightPoolFraction = "_pool_reward_update_height"
30+let kFee = "commission"
1531
16-let kTotalRewardPerBlockCurrent = "total_reward_per_block_current"
32+let kDAppThresholdCoef = "dAppThresholdCoef"
1733
18-let kTotalRewardPerBlockPrevious = "total_reward_per_block_previous"
34+let kUSDNAddress = "staking_usdnnsbt_address"
1935
20-let kRewardUpdateHeight = "reward_update_height"
36+let kDiscounts = "discounts"
2137
22-let kUserShareTokensStaked = "_share_tokens_locked"
38+let kDiscountValues = "discount_values"
2339
24-let kUserShareTokensLocked = "_share_tokens_blocked"
40+let kUserSwopInGov = "_SWOP_amount"
2541
26-let kUserShareTokensLockedType = "_share_tokens_blocked_type"
27-
28-let kUserShareTokensLockedHeight = "_share_tokens_blocked_height"
29-
30-let kUserShareTokensVirtual = "_share_tokens_virtual"
31-
32-let kShareTotalShareTokens = "_total_share_tokens_locked"
33-
34-let kShareTokensVirtual = "_total_share_tokens_virtual"
35-
36-let kLockParams = "_lock_params"
37-
38-let kLockWavesFee = "lock_waves_fee"
39-
40-let kPoolBoostCoef = "_boost_coef"
41-
42-let kFarmLastInterest = "_last_interest"
43-
44-let kFarmUserLastInterest = "_last_interest"
45-
46-let kBoostLastInterest = "_last_interest_b"
47-
48-let kBoostUserLastInterest = "_last_interest_u_b"
49-
50-let kBoostLPLastInterest = "_last_interest_lpb"
51-
52-let kBoostLPUserLastInterest = "_last_interest_u_lpb"
53-
54-let kLastInterestHeight = "_last_interest_height"
55-
56-let kSWOPid = "SWOP_id"
57-
58-let kAvailableSWOP = "_available_SWOP"
59-
60-let kSwopYearEmission = "swop_year_emission"
61-
62-let kHarvestPoolVote = "_harvest_pool_vote_gSWOP"
63-
64-let kPoolVote = "_pool_vote_gSWOP"
65-
66-let kUserPoolVote = "_user_vote_gSWOP"
67-
68-let kHarvestUserPoolVote = "_harvest_user_pool_vote_gSWOP"
69-
70-let kBasePeriod = "base_period"
71-
72-let kPeriodLength = "period_length"
73-
74-let kStartHeight = "start_height"
75-
76-let kFirstHarvestHeight = "first_harvest_height"
77-
78-let kShareLimitFH = "share_limit_on_first_harvest"
42+let kUserGSwopInGov = "_GSwop_amount"
7943
8044 let kAdminPubKey1 = "admin_pub_1"
8145
8751
8852 let kMoneyBoxAddress = "money_box_address"
8953
54+let kGovAddress = "governance_address"
55+
9056 let kVotingAddress = "voting_address"
9157
92-let kGovAddress = "governance_address"
58+let kFarmingAddress = "farming_address"
9359
9460 let kLPFarmingAddress = "lp_farming"
9561
96-let kFarmingTreasureAddr = "farming_treasure"
97-
9862 let oracle = Address(base58'3MvVBtsXroQpy1tsPw21TU2ET9A8WfmrNjz')
99-
100-let totalVoteShare = 10000000000
101-
102-let scaleValue8 = 100000000
103-
104-let lockBoostCoefScale = 1000
105-
106-let defPoolBoostCoef = 500
10763
10864 func getBase58FromOracle (key) = match getString(oracle, key) {
10965 case string: String =>
11975
12076 let adminPubKey3 = getBase58FromOracle(kAdminPubKey3)
12177
78+let adminPubKeyInvoke = getBase58FromOracle(kAdminInvokePubKey)
79+
12280 let moneyBoxAddress = Address(getBase58FromOracle(kMoneyBoxAddress))
81+
82+let govAddress = Address(getBase58FromOracle(kGovAddress))
83+
84+let stakingUSDNAddress = Address(getBase58FromOracle(kUSDNAddress))
12385
12486 let votingAddress = Address(getBase58FromOracle(kVotingAddress))
12587
126-let govAddress = Address(getBase58FromOracle(kGovAddress))
127-
128-let adminInvokePubKey = getBase58FromOracle(kAdminInvokePubKey)
88+let farmingAddress = Address(getBase58FromOracle(kFarmingAddress))
12989
13090 let lpFarmingAddress = Address(getBase58FromOracle(kLPFarmingAddress))
13191
132-let farmingTreasureAddr = Address(getBase58FromOracle(kFarmingTreasureAddr))
92+let USDN = base58'DG2xFkPdDwKUoBkzGAhQtLpSGzfXLiCYPEzeKH2Ad24p'
13393
134-let basePeriod = valueOrErrorMessage(getInteger(votingAddress, kBasePeriod), "Empty kBasePeriod")
135-
136-let startHeight = valueOrErrorMessage(getInteger(votingAddress, kStartHeight), "Empty kStartHeight")
137-
138-let periodLength = valueOrErrorMessage(getInteger(votingAddress, kPeriodLength), "Empty kPeriodLength")
139-
140-let currPeriod = (basePeriod + ((height - startHeight) / periodLength))
94+let stakingAssets = [toBase58String(USDN)]
14195
14296 let active = getBooleanValue(this, kActive)
14397
144-let activeGlob = valueOrElse(getBoolean(oracle, kActiveGlob), true)
98+let shareAssetId = fromBase58String(getStringValue(this, kShareAssetId))
14599
146-let SwopYearEmission = getIntegerValue(this, kSwopYearEmission)
100+let shareSupply = getIntegerValue(this, kShareAssetSupply)
147101
148-let SWOP = fromBase58String(getStringValue(this, kSWOPid))
102+let feeScale6 = 1000000
149103
150-func getHeightFirstHarvest (pool) = valueOrElse(getInteger(Address(fromBase58String(pool)), kFirstHarvestHeight), 0)
104+let fee = getIntegerValue(this, kFee)
151105
106+let feeGovernance = fraction(40, feeScale6, 100)
152107
153-func getFHShareLimitToken (pool) = valueOrErrorMessage(getInteger(pool, kShareLimitFH), ("No data on the key: " + kShareLimitFH))
108+let initial_A = getIntegerValue(this, "initial_A")
154109
110+let future_A = getIntegerValue(this, "future_A")
155111
156-func getTotalShareToken (pool) = valueOrErrorMessage(getInteger(this, (pool + kShareTotalShareTokens)), (("No data on the key: " + pool) + kShareTotalShareTokens))
112+let initial_A_time = valueOrElse(getInteger(this, "initial_A_time"), 0)
157113
114+let future_A_time = valueOrElse(getInteger(this, "future_A_time"), 0)
158115
159-func getPoolVoted (pool) = valueOrElse(getInteger(votingAddress, (pool + kPoolVote)), 0)
116+let assetIds = split(getStringValue(this, kAssets), ",")
160117
161-
162-func getUserPoolVoted (pool,user) = valueOrElse(getInteger(votingAddress, (((user + "_") + pool) + kPoolVote)), 0)
163-
164-
165-func getShareAssetId (pool) = fromBase58String(getStringValue(value(addressFromString(pool)), "share_asset_id"))
166-
167-
168-func accountBalance (assetId) = match assetId {
169- case id: ByteVector =>
170- assetBalance(this, id)
171- case waves: Unit =>
172- wavesBalance(this).available
173- case _ =>
174- throw("Match error")
175-}
176-
177-
178-func getAssetInfo (assetId) = match assetId {
179- case id: ByteVector =>
180- let stringId = toBase58String(id)
181- let info = valueOrErrorMessage(assetInfo(id), (("Asset " + stringId) + " doesn't exist"))
182- $Tuple3(stringId, info.name, info.decimals)
183- case waves: Unit =>
184- $Tuple3("WAVES", "WAVES", 8)
185- case _ =>
186- throw("Match error")
187-}
188-
189-
190-func calcScaleValue (assetId1,assetId2) = {
191- let assetId1Decimals = value(assetInfo(assetId1)).decimals
192- let assetId2Decimals = value(assetInfo(assetId2)).decimals
193- let scaleDigits = ((assetId2Decimals - assetId1Decimals) + 8)
194- pow(10, 0, scaleDigits, 0, 0, DOWN)
195- }
196-
197-
198-func userAvailableSWOP (pool,user) = valueOrElse(getInteger(this, (((pool + "_") + toString(user)) + kAvailableSWOP)), 0)
199-
200-
201-func rewardInfo (pool) = {
202- let totalRewardPerBlockCurrent = valueOrErrorMessage(getInteger(govAddress, kTotalRewardPerBlockCurrent), ((("No data on the key: " + kTotalRewardPerBlockCurrent) + " at address ") + toString(govAddress)))
203- let totalRewardPerBlockPrevious = valueOrErrorMessage(getInteger(govAddress, kTotalRewardPerBlockPrevious), ((("No data on the key: " + kTotalRewardPerBlockPrevious) + " at address ") + toString(govAddress)))
204- let rewardPoolFractionCurrent = valueOrErrorMessage(getInteger(govAddress, (pool + kRewardPoolFractionCurrent)), (((("No data on the key: " + pool) + kRewardPoolFractionCurrent) + " at address ") + toString(govAddress)))
205- let rewardUpdateHeight = valueOrErrorMessage(getInteger(govAddress, kRewardUpdateHeight), ((("No data on the key: " + kRewardUpdateHeight) + " at address ") + toString(govAddress)))
206- let poolRewardUpdateHeight = valueOrElse(getInteger(govAddress, (pool + kHeightPoolFraction)), rewardUpdateHeight)
207- let rewardPoolFractionPrevious = valueOrErrorMessage(getInteger(govAddress, (pool + kRewardPoolFractionPrevious)), (((("No data on the key: " + pool) + kRewardPoolFractionPrevious) + " at address ") + toString(govAddress)))
208- let rewardPoolCurrent = fraction(totalRewardPerBlockCurrent, rewardPoolFractionCurrent, totalVoteShare)
209- let rewardPoolPrevious = fraction(totalRewardPerBlockCurrent, rewardPoolFractionPrevious, totalVoteShare)
210- if (if ((rewardPoolCurrent > totalRewardPerBlockCurrent))
211- then true
212- else (rewardPoolPrevious > totalRewardPerBlockPrevious))
213- then throw("rewardPoolCurrent > totalRewardPerBlockCurrent or rewardPoolPrevious > totalRewardPerBlockPrevious")
214- else $Tuple4(rewardPoolCurrent, rewardUpdateHeight, rewardPoolPrevious, poolRewardUpdateHeight)
215- }
216-
217-
218-func getLastInterestInfo (pool) = {
219- let farmInterest = valueOrErrorMessage(getInteger(this, (pool + kFarmLastInterest)), (("No data on the key: " + pool) + kFarmLastInterest))
220- let boostInterest = valueOrErrorMessage(getInteger(this, (pool + kFarmLastInterest)), (("No data on the key: " + pool) + kBoostLastInterest))
221- let boostLPInterest = valueOrErrorMessage(getInteger(this, (pool + kFarmLastInterest)), (("No data on the key: " + pool) + kBoostLPLastInterest))
222- let lastInterestHeight = valueOrElse(getInteger(this, (pool + kLastInterestHeight)), height)
223- $Tuple4(lastInterestHeight, farmInterest, boostInterest, boostLPInterest)
224- }
225-
226-
227-func calcFarmRwd (pool,curTotalReward) = {
228- let poolBoostCoef = valueOrElse(getInteger(this, (pool + kPoolBoostCoef)), defPoolBoostCoef)
229- ((curTotalReward / (poolBoostCoef + 1000)) / lockBoostCoefScale)
230- }
231-
232-
233-func calcBoostRwd (pool,curTotalReward) = {
234- let poolBoostCoef = valueOrElse(getInteger(this, (pool + kPoolBoostCoef)), defPoolBoostCoef)
235- (fraction(curTotalReward, poolBoostCoef, (poolBoostCoef + 1000)) / lockBoostCoefScale)
236- }
237-
238-
239-func calcInterest (pool,lastInterestHeight,rewardUpdateHeight,poolRewardUpdateHeight,farmInterest,boostInterest,poolVoted,boostLpInterest,currentRewardPerBlock,shareTokenLocked,previousRewardPerBlock,scaleValue) = if ((shareTokenLocked == 0))
240- then $Tuple3(0, 0, 0)
241- else if (if ((rewardUpdateHeight > height))
242- then (rewardUpdateHeight == poolRewardUpdateHeight)
243- else false)
244- then {
245- let reward = (previousRewardPerBlock * (height - lastInterestHeight))
246- let newFarmInterest = (farmInterest + fraction(calcFarmRwd(pool, reward), scaleValue, shareTokenLocked))
247- let newBoostInterest = (boostInterest + (if ((poolVoted > 0))
248- then fraction(calcBoostRwd(pool, reward), scaleValue8, poolVoted)
249- else 0))
250- let newBoostLPInterest = (boostLpInterest + (if (if ((poolVoted > 0))
251- then (shareTokenLocked > 0)
252- else false)
253- then fraction(fraction(calcBoostRwd(pool, reward), scaleValue8, shareTokenLocked), scaleValue8, poolVoted)
254- else 0))
255- $Tuple3(newFarmInterest, newBoostInterest, newBoostLPInterest)
256- }
257- else if (if ((height > rewardUpdateHeight))
258- then (rewardUpdateHeight != poolRewardUpdateHeight)
259- else false)
260- then {
261- let reward = (previousRewardPerBlock * (height - lastInterestHeight))
262- let newFarmInterest = (farmInterest + fraction(calcFarmRwd(pool, reward), scaleValue, shareTokenLocked))
263- let newBoostInterest = (boostInterest + (if ((poolVoted > 0))
264- then fraction(calcBoostRwd(pool, reward), scaleValue8, poolVoted)
265- else 0))
266- let newBoostLPInterest = (boostLpInterest + (if (if ((poolVoted > 0))
267- then (shareTokenLocked > 0)
268- else false)
269- then fraction(fraction(calcBoostRwd(pool, reward), scaleValue8, shareTokenLocked), scaleValue8, poolVoted)
270- else 0))
271- $Tuple3(newFarmInterest, newBoostInterest, newBoostLPInterest)
272- }
273- else if (if (if ((height > rewardUpdateHeight))
274- then (rewardUpdateHeight == poolRewardUpdateHeight)
275- else false)
276- then (lastInterestHeight > rewardUpdateHeight)
277- else false)
278- then {
279- let reward = (currentRewardPerBlock * (height - lastInterestHeight))
280- let newFarmInterest = (farmInterest + fraction(calcFarmRwd(pool, reward), scaleValue, shareTokenLocked))
281- let newBoostInterest = (boostInterest + (if ((poolVoted > 0))
282- then fraction(calcBoostRwd(pool, reward), scaleValue8, poolVoted)
283- else 0))
284- let newBoostLPInterest = (boostLpInterest + (if (if ((poolVoted > 0))
285- then (shareTokenLocked > 0)
286- else false)
287- then fraction(fraction(calcBoostRwd(pool, reward), scaleValue8, shareTokenLocked), scaleValue8, poolVoted)
288- else 0))
289- $Tuple3(newFarmInterest, newBoostInterest, newBoostLPInterest)
290- }
291- else {
292- let rwdBfrUpd = (previousRewardPerBlock * (rewardUpdateHeight - lastInterestHeight))
293- let framIntrAftrUp = (farmInterest + fraction(calcFarmRwd(pool, rwdBfrUpd), scaleValue, shareTokenLocked))
294- let boostIntrAftrUp = (boostInterest + (if ((poolVoted > 0))
295- then fraction(calcBoostRwd(pool, rwdBfrUpd), scaleValue, poolVoted)
296- else 0))
297- let bostLPIntrAftrUp = (farmInterest + (if (if ((poolVoted > 0))
298- then (shareTokenLocked > 0)
299- else false)
300- then fraction(calcBoostRwd(pool, rwdBfrUpd), scaleValue, poolVoted)
301- else 0))
302- let reward = (currentRewardPerBlock * (height - rewardUpdateHeight))
303- let newFarmInterest = (framIntrAftrUp + fraction(calcFarmRwd(pool, reward), scaleValue, shareTokenLocked))
304- let newBoostInterest = (boostIntrAftrUp + (if ((poolVoted > 0))
305- then fraction(calcBoostRwd(pool, reward), scaleValue8, poolVoted)
306- else 0))
307- let newBoostLPInterest = (bostLPIntrAftrUp + (if (if ((poolVoted > 0))
308- then (shareTokenLocked > 0)
309- else false)
310- then fraction(fraction(calcBoostRwd(pool, reward), scaleValue8, shareTokenLocked), scaleValue8, poolVoted)
311- else 0))
312- $Tuple3(newFarmInterest, newBoostInterest, newBoostLPInterest)
313- }
314-
315-
316-func claimCalc (pool,user) = {
317- let scaleValue = calcScaleValue(SWOP, getShareAssetId(pool))
318- let poolVoted = getPoolVoted(pool)
319- let uPoolVoted = getUserPoolVoted(pool, user)
320- let shareToken = getTotalShareToken(pool)
321- let totalShareVirtual = valueOrElse(getInteger(this, (pool + kShareTokensVirtual)), shareToken)
322- let $t01440614504 = getLastInterestInfo(pool)
323- let lastInterestHeight = $t01440614504._1
324- let farmInterest = $t01440614504._2
325- let boostInterest = $t01440614504._3
326- let boostLPInterest = $t01440614504._4
327- let $t01450914623 = rewardInfo(pool)
328- let currentRewardPerBlock = $t01450914623._1
329- let rewardUpdateHeight = $t01450914623._2
330- let previousRewardPerBlock = $t01450914623._3
331- let poolRewardUpdateHeight = $t01450914623._4
332- let uFarmInterest = valueOrElse(getInteger(this, (((pool + "_") + user) + kFarmUserLastInterest)), farmInterest)
333- let uBoostInterest = valueOrElse(getInteger(this, (((pool + "_") + user) + kBoostUserLastInterest)), boostInterest)
334- let uBoostLPInterest = valueOrElse(getInteger(this, (((pool + "_") + user) + kBoostLPUserLastInterest)), boostLPInterest)
335- let uShareTokensStaked = valueOrElse(getInteger(this, (((pool + "_") + user) + kUserShareTokensStaked)), 0)
336- let uShareTokensVirt = valueOrElse(getInteger(this, (((pool + "_") + user) + kUserShareTokensVirtual)), uShareTokensStaked)
337- let $t01519115584 = calcInterest(pool, lastInterestHeight, rewardUpdateHeight, poolRewardUpdateHeight, farmInterest, boostInterest, poolVoted, boostLPInterest, currentRewardPerBlock, totalShareVirtual, previousRewardPerBlock, scaleValue)
338- let newFarmInterest = $t01519115584._1
339- let newBoostInterest = $t01519115584._2
340- let newBoostLPInterest = $t01519115584._3
341- let claimFarming = fraction(uShareTokensVirt, (newFarmInterest - uFarmInterest), scaleValue)
342- let claimBoostingMax = fraction(uPoolVoted, (newBoostInterest - uBoostInterest), scaleValue8)
343- let claimBoosting = (fraction((uShareTokensVirt * uPoolVoted), (newBoostLPInterest - uBoostLPInterest), scaleValue8) / scaleValue8)
344- let toTreasury = (claimBoostingMax - claimBoosting)
345- $Tuple5(newFarmInterest, newBoostInterest, newBoostLPInterest, (claimFarming + claimBoosting), toTreasury)
346- }
347-
348-
349-func canLockInFirstHarvest (pool,user,userShareTokensStaked,pmtAmount,lockType) = if ((getHeightFirstHarvest(pool) > height))
350- then {
351- let totalVoteAmount = valueOrElse(getInteger(votingAddress, (pool + kHarvestPoolVote)), 0)
352- let userVoteAmount = valueOrElse(getInteger(votingAddress, (((user + "_") + pool) + kHarvestPoolVote)), 0)
353- let FHShareTokenLimit = getFHShareLimitToken(addressFromStringValue(pool))
354- let FHShareTokenUserLimit = (fraction(FHShareTokenLimit, userVoteAmount, totalVoteAmount) - userShareTokensStaked)
355- if ((lockType > 0))
356- then throw("You can't lock shareTokens till first harvest end.")
357- else if ((userVoteAmount == 0))
358- then 0
359- else if ((pmtAmount >= FHShareTokenUserLimit))
360- then (pmtAmount - FHShareTokenUserLimit)
361- else 0
362- }
363- else 0
364-
365-
366-func getLockParams (type) = {
367- let lockParams = split(valueOrErrorMessage(getString(this, (toString(type) + kLockParams)), ("There are no key for lock type" + toString(type))), "_")
368- $Tuple2(parseIntValue(lockParams[0]), parseIntValue(lockParams[1]))
369- }
370-
118+let nCoins = size(assetIds)
371119
372120 func suspend (cause) = [BooleanEntry(kActive, false), StringEntry(kCause, cause)]
373121
374122
375-func isActive () = if (if (active)
376- then activeGlob
377- else false)
123+func throwIsActive () = throw("DApp is already active")
124+
125+
126+func isActive () = if (active)
378127 then unit
379128 else throw("DApp is inactive at this moment")
380129
384133 else throw("Only admin can call this function")
385134
386135
387-@Callable(i)
388-func init (earlyLP) = if (isDefined(getString(this, kSWOPid)))
389- then throw("SWOP already initialized")
136+func isSelfCall (i) = if ((this == i.caller))
137+ then unit
138+ else throw("Only contract itself can call this function")
139+
140+
141+let big2 = toBigInt(2)
142+
143+let iter10 = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
144+
145+let iter15 = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
146+
147+let iter16 = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
148+
149+let blockTimestamp = height
150+
151+func assert (a) = if (a)
152+ then false
153+ else true
154+
155+
156+func calculateFeeDiscount (userAddr) = {
157+ let user = match userAddr {
158+ case u: Address =>
159+ toString(u)
160+ case u: String =>
161+ u
162+ case _ =>
163+ throw("Unknow type of user Addr")
164+ }
165+ let swopAmount = valueOrElse(getInteger(govAddress, (user + kUserGSwopInGov)), 0)
166+ let gSwopAmount = valueOrElse(getInteger(govAddress, (user + kUserGSwopInGov)), swopAmount)
167+ let discountValues = split(getStringValue(oracle, kDiscountValues), ",")
168+ let discounts = split(getStringValue(oracle, kDiscounts), ",")
169+ if (if ((gSwopAmount >= parseIntValue(discountValues[0])))
170+ then (parseIntValue(discountValues[1]) > gSwopAmount)
171+ else false)
172+ then (feeScale6 - parseIntValue(discounts[0]))
173+ else if (if ((gSwopAmount >= parseIntValue(discountValues[1])))
174+ then (parseIntValue(discountValues[2]) > gSwopAmount)
175+ else false)
176+ then (feeScale6 - parseIntValue(discounts[1]))
177+ else if (if ((gSwopAmount >= parseIntValue(discountValues[2])))
178+ then (parseIntValue(discountValues[3]) > gSwopAmount)
179+ else false)
180+ then (feeScale6 - parseIntValue(discounts[2]))
181+ else if (if ((gSwopAmount >= parseIntValue(discountValues[3])))
182+ then (parseIntValue(discountValues[4]) > gSwopAmount)
183+ else false)
184+ then (feeScale6 - parseIntValue(discounts[3]))
185+ else if ((gSwopAmount >= parseIntValue(discountValues[4])))
186+ then (feeScale6 - parseIntValue(discounts[4]))
187+ else feeScale6
188+ }
189+
190+
191+func _A () = {
192+ let t1 = future_A_time
193+ let A1 = future_A
194+ if ((t1 > blockTimestamp))
195+ then {
196+ let A0 = initial_A
197+ let t0 = initial_A_time
198+ if ((A1 > A0))
199+ then (A0 + (((A1 - A0) * (blockTimestamp - t0)) / (t1 - t0)))
200+ else (A0 - (((A0 - A1) * (blockTimestamp - t0)) / (t1 - t0)))
201+ }
202+ else A1
203+ }
204+
205+
206+func _xp () = {
207+ func assetBalances (acc,assetId) = (acc :+ valueOrElse(getInteger(this, (assetId + kAssetBalance)), 0))
208+
209+ let $l = assetIds
210+ let $s = size($l)
211+ let $acc0 = nil
212+ func $f0_1 ($a,$i) = if (($i >= $s))
213+ then $a
214+ else assetBalances($a, $l[$i])
215+
216+ func $f0_2 ($a,$i) = if (($i >= $s))
217+ then $a
218+ else throw("List size exceeds 10")
219+
220+ $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
221+ }
222+
223+
224+func _xp_mem (xp) = xp
225+
226+
227+func sumList (acc,element) = (acc + element)
228+
229+
230+func get_D (xp,amp) = {
231+ let @ = invoke(this, "D", [xp, amp], nil)
232+ if ($isInstanceOf(@, "Int"))
233+ then @
234+ else throw(($getType(@) + " couldn't be cast to Int"))
235+ }
236+
237+
238+func get_D_internal (xp,amp) = {
239+ let S = {
240+ let $l = xp
241+ let $s = size($l)
242+ let $acc0 = 0
243+ func $f0_1 ($a,$i) = if (($i >= $s))
244+ then $a
245+ else sumList($a, $l[$i])
246+
247+ func $f0_2 ($a,$i) = if (($i >= $s))
248+ then $a
249+ else throw("List size exceeds 10")
250+
251+ $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
252+ }
253+ if ((S == 0))
254+ then 0
255+ else {
256+ let Ann = (amp * nCoins)
257+ let AnnS = (toBigInt(Ann) * toBigInt(S))
258+ let Ann1 = toBigInt((Ann - 1))
259+ func Dproc (acc,i) = if ((acc._2 == true))
260+ then acc
261+ else {
262+ let Dprev = acc._1
263+ func D_PProc (D_P,i) = if ((nCoins > i))
264+ then ((D_P * Dprev) / (toBigInt(xp[i]) * toBigInt(nCoins)))
265+ else D_P
266+
267+ let D_P = {
268+ let $l = iter10
269+ let $s = size($l)
270+ let $acc0 = Dprev
271+ func $f1_1 ($a,$i) = if (($i >= $s))
272+ then $a
273+ else D_PProc($a, $l[$i])
274+
275+ func $f1_2 ($a,$i) = if (($i >= $s))
276+ then $a
277+ else throw("List size exceeds 10")
278+
279+ $f1_2($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
280+ }
281+ let D = fraction((AnnS + (toBigInt(nCoins) * D_P)), Dprev, ((Ann1 * Dprev) + (toBigInt((nCoins + 1)) * D_P)))
282+ if ((D > Dprev))
283+ then if ((1 >= toInt((D - Dprev))))
284+ then $Tuple2(D, true)
285+ else $Tuple2(D, false)
286+ else if ((1 >= toInt((Dprev - D))))
287+ then $Tuple2(D, true)
288+ else $Tuple2(D, false)
289+ }
290+
291+ let $t064616527 = {
292+ let $l = iter15
293+ let $s = size($l)
294+ let $acc0 = $Tuple2(toBigInt(S), false)
295+ func $f1_1 ($a,$i) = if (($i >= $s))
296+ then $a
297+ else Dproc($a, $l[$i])
298+
299+ func $f1_2 ($a,$i) = if (($i >= $s))
300+ then $a
301+ else throw("List size exceeds 15")
302+
303+ $f1_2($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10), 11), 12), 13), 14), 15)
304+ }
305+ let D = $t064616527._1
306+ let finished = $t064616527._2
307+ if ((finished == false))
308+ then throw(("get_D() not finished with " + toString(D)))
309+ else toInt(D)
310+ }
311+ }
312+
313+
314+func getDMem (xp,amp) = get_D(_xp_mem(xp), amp)
315+
316+
317+func getY (in,out,x,xp_) = if (assert((in != out)))
318+ then throw("same coin")
319+ else if (assert(if ((out >= 0))
320+ then (in >= 0)
321+ else false))
322+ then throw("below zero")
323+ else if (assert(if ((nCoins > out))
324+ then (nCoins > in)
325+ else false))
326+ then throw("above N_COINS")
327+ else {
328+ let amp = _A()
329+ let D = get_D(xp_, amp)
330+ let Ann = (amp * nCoins)
331+ func S_c (acc,i) = {
332+ let $t070987115 = acc
333+ let S_ = $t070987115._1
334+ let c = $t070987115._2
335+ let x_ = if ((in == i))
336+ then x
337+ else xp_[i]
338+ if (if ((i != out))
339+ then (nCoins > i)
340+ else false)
341+ then $Tuple2((S_ + x_), fraction(c, toBigInt(D), toBigInt((x_ * nCoins))))
342+ else $Tuple2(S_, c)
343+ }
344+
345+ let $t073237378 = {
346+ let $l = iter10
347+ let $s = size($l)
348+ let $acc0 = $Tuple2(0, toBigInt(D))
349+ func $f0_1 ($a,$i) = if (($i >= $s))
350+ then $a
351+ else S_c($a, $l[$i])
352+
353+ func $f0_2 ($a,$i) = if (($i >= $s))
354+ then $a
355+ else throw("List size exceeds 10")
356+
357+ $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
358+ }
359+ let S_ = $t073237378._1
360+ let c_ = $t073237378._2
361+ let c = fraction(c_, toBigInt(D), toBigInt((Ann * nCoins)))
362+ let bD = toBigInt(((S_ + (D / Ann)) - D))
363+ func y_proc (acc,_i) = if ((acc._2 == true))
364+ then acc
365+ else {
366+ let y_prev = acc._1
367+ let y = (((y_prev * y_prev) + c) / ((big2 * y_prev) + bD))
368+ if ((y > y_prev))
369+ then if ((1 >= toInt((y - y_prev))))
370+ then $Tuple2(y, true)
371+ else $Tuple2(y, false)
372+ else if ((1 >= toInt((y_prev - y))))
373+ then $Tuple2(y, true)
374+ else $Tuple2(y, false)
375+ }
376+
377+ let $t078607927 = {
378+ let $l = iter16
379+ let $s = size($l)
380+ let $acc0 = $Tuple2(toBigInt(D), false)
381+ func $f1_1 ($a,$i) = if (($i >= $s))
382+ then $a
383+ else y_proc($a, $l[$i])
384+
385+ func $f1_2 ($a,$i) = if (($i >= $s))
386+ then $a
387+ else throw("List size exceeds 16")
388+
389+ $f1_2($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10), 11), 12), 13), 14), 15), 16)
390+ }
391+ let y = $t078607927._1
392+ let finished = $t078607927._2
393+ if ((finished == false))
394+ then throw(("getY() not finished with " + toString(y)))
395+ else toInt(y)
396+ }
397+
398+
399+func get_y_D (A_,in,xp,D) = if (assert((in >= 0)))
400+ then throw("i below zero")
401+ else if (assert((nCoins > in)))
402+ then throw("i above N_COINS")
403+ else {
404+ let Ann = (A_ * nCoins)
405+ func S_c (acc,i) = {
406+ let $t083068323 = acc
407+ let S_ = $t083068323._1
408+ let c = $t083068323._2
409+ let x_ = if (if ((in != i))
410+ then (nCoins > i)
411+ else false)
412+ then xp[i]
413+ else 0
414+ if (if ((nCoins > i))
415+ then (in != i)
416+ else false)
417+ then $Tuple2((S_ + x_), fraction(c, toBigInt(D), toBigInt((x_ * nCoins))))
418+ else $Tuple2(S_, c)
419+ }
420+
421+ let $t085438598 = {
422+ let $l = iter10
423+ let $s = size($l)
424+ let $acc0 = $Tuple2(0, toBigInt(D))
425+ func $f0_1 ($a,$i) = if (($i >= $s))
426+ then $a
427+ else S_c($a, $l[$i])
428+
429+ func $f0_2 ($a,$i) = if (($i >= $s))
430+ then $a
431+ else throw("List size exceeds 10")
432+
433+ $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
434+ }
435+ let S_ = $t085438598._1
436+ let c_ = $t085438598._2
437+ let c = fraction(c_, toBigInt(D), toBigInt((Ann * nCoins)))
438+ let bD = toBigInt(((S_ + (D / Ann)) - D))
439+ func y_D_proc (acc,i) = if ((acc._2 == true))
440+ then acc
441+ else {
442+ let y_prev = acc._1
443+ let y = (((y_prev * y_prev) + c) / ((big2 * y_prev) + bD))
444+ if ((y > y_prev))
445+ then if ((1 >= toInt((y - y_prev))))
446+ then $Tuple2(y, true)
447+ else $Tuple2(y, false)
448+ else if ((1 >= toInt((y_prev - y))))
449+ then $Tuple2(y, true)
450+ else $Tuple2(y, false)
451+ }
452+
453+ let $t090819150 = {
454+ let $l = iter16
455+ let $s = size($l)
456+ let $acc0 = $Tuple2(toBigInt(D), false)
457+ func $f1_1 ($a,$i) = if (($i >= $s))
458+ then $a
459+ else y_D_proc($a, $l[$i])
460+
461+ func $f1_2 ($a,$i) = if (($i >= $s))
462+ then $a
463+ else throw("List size exceeds 16")
464+
465+ $f1_2($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10), 11), 12), 13), 14), 15), 16)
466+ }
467+ let y = $t090819150._1
468+ let finished = $t090819150._2
469+ if ((finished == false))
470+ then throw(("get_y_D() not finished with " + toString(y)))
471+ else toInt(y)
472+ }
473+
474+
475+func _calcWithdrawOneCoin (xp,_token_amount,i,caller) = {
476+ let feeDiscount = calculateFeeDiscount(caller)
477+ let amp = _A()
478+ let _fee = ((fraction(fee, feeDiscount, feeScale6, CEILING) * nCoins) / (4 * (nCoins - 1)))
479+ let total_supply = shareSupply
480+ let D0 = get_D(xp, amp)
481+ let D1 = (D0 - fraction(_token_amount, D0, total_supply))
482+ let new_y = get_y_D(amp, i, xp, D1)
483+ let dy_0 = (xp[i] - new_y)
484+ func xp_reduced_proc (acc,xp_j) = {
485+ let $t097919820 = acc
486+ let xp_reduced = $t097919820._1
487+ let index = $t097919820._2
488+ let dx_expected = if ((index == i))
489+ then (fraction(xp_j, D1, D0) - new_y)
490+ else (xp_j - fraction(xp_j, D1, D0))
491+ $Tuple2((xp_reduced :+ (xp_j - fraction(_fee, dx_expected, feeScale6))), (index + 1))
492+ }
493+
494+ let $t01008210146 = {
495+ let $l = xp
496+ let $s = size($l)
497+ let $acc0 = $Tuple2(nil, 0)
498+ func $f0_1 ($a,$i) = if (($i >= $s))
499+ then $a
500+ else xp_reduced_proc($a, $l[$i])
501+
502+ func $f0_2 ($a,$i) = if (($i >= $s))
503+ then $a
504+ else throw("List size exceeds 10")
505+
506+ $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
507+ }
508+ let xp_reduced = $t01008210146._1
509+ let index = $t01008210146._2
510+ let xp_reduced_i = xp_reduced[i]
511+ let dy = ((xp_reduced_i - get_y_D(amp, i, xp_reduced, D1)) - 1)
512+ $Tuple2(dy, (dy_0 - dy))
513+ }
514+
515+
516+func getStrAssetId (assetId) = match assetId {
517+ case id: ByteVector =>
518+ toBase58String(id)
519+ case waves: Unit =>
520+ "WAVES"
521+ case _ =>
522+ throw("Match error")
523+}
524+
525+
526+func calcStakingFuncAndAddres (stake,assetId) = if (stake)
527+ then $Tuple2("lockNeutrino", stakingUSDNAddress)
528+ else $Tuple2("unlockNeutrino", stakingUSDNAddress)
529+
530+
531+func calcStakingParams (stake,amount,assetId) = if (stake)
532+ then {
533+ let $t01071010776 = calcStakingFuncAndAddres(stake, assetId)
534+ let call = $t01071010776._1
535+ let stakingAddr = $t01071010776._2
536+ $Tuple4(call, stakingAddr, nil, [AttachedPayment(assetId, amount)])
537+ }
390538 else {
391- let initAmount = 100000000000000
392- let SWOPissue = Issue("SWOP", "SWOP protocol token", initAmount, 8, true)
393- let SWOPid = calculateAssetId(SWOPissue)
394-[BooleanEntry(kActive, true), Issue("SWOP", "SWOP protocol token", initAmount, 8, true), StringEntry(kSWOPid, toBase58String(SWOPid))]
539+ let $t01086210928 = calcStakingFuncAndAddres(stake, assetId)
540+ let call = $t01086210928._1
541+ let stakingAddr = $t01086210928._2
542+ $Tuple4(call, stakingAddr, [amount, toBase58String(assetId)], nil)
395543 }
396544
397545
546+func stake (amount,assetIdString) = if (containsElement(stakingAssets, assetIdString))
547+ then {
548+ let $t01111511217 = calcStakingParams(true, amount, fromBase58String(assetIdString))
549+ let call = $t01111511217._1
550+ let addr = $t01111511217._2
551+ let params = $t01111511217._3
552+ let payments = $t01111511217._4
553+ invoke(addr, call, params, payments)
554+ }
555+ else 0
398556
399-@Callable(i)
400-func initPoolShareFarming (pool) = valueOrElse(isAdminCall(i), [IntegerEntry((pool + kShareTotalShareTokens), 0), IntegerEntry((pool + kFarmLastInterest), 0), IntegerEntry((pool + kBoostLastInterest), 0), IntegerEntry((pool + kBoostLPLastInterest), 0), IntegerEntry((pool + kLastInterestHeight), height)])
557+
558+func unstake (amount,assetIdString) = if (containsElement(stakingAssets, assetIdString))
559+ then {
560+ let $t01140211505 = calcStakingParams(false, amount, fromBase58String(assetIdString))
561+ let call = $t01140211505._1
562+ let addr = $t01140211505._2
563+ let params = $t01140211505._3
564+ let payments = $t01140211505._4
565+ invoke(addr, call, params, payments)
566+ }
567+ else 0
568+
569+
570+func stakedAmount (assetId) = {
571+ let stakedAmountCalculated = match assetId {
572+ case aId: ByteVector =>
573+ if ((aId == USDN))
574+ then getInteger(stakingUSDNAddress, ((("rpd_balance_" + toBase58String(aId)) + "_") + toString(this)))
575+ else 0
576+ case _: Unit =>
577+ 0
578+ case _ =>
579+ throw("Match error")
580+ }
581+ match stakedAmountCalculated {
582+ case i: Int =>
583+ i
584+ case _ =>
585+ 0
586+ }
587+ }
588+
589+
590+func checkSuspicious () = {
591+ let contractBalances = _xp()
592+ func checkBalance (acc,assetId) = {
593+ let $t01211612141 = acc
594+ let suspicious = $t01211612141._1
595+ let i = $t01211612141._2
596+ if (suspicious)
597+ then $Tuple2(suspicious, i)
598+ else {
599+ let aBalance = (assetBalance(this, fromBase58String(assetId)) + stakedAmount(fromBase58String(assetId)))
600+ if ((contractBalances[i] > aBalance))
601+ then $Tuple2(true, i)
602+ else $Tuple2(false, (i + 1))
603+ }
604+ }
605+
606+ let $l = assetIds
607+ let $s = size($l)
608+ let $acc0 = $Tuple2(false, 0)
609+ func $f0_1 ($a,$i) = if (($i >= $s))
610+ then $a
611+ else checkBalance($a, $l[$i])
612+
613+ func $f0_2 ($a,$i) = if (($i >= $s))
614+ then $a
615+ else throw("List size exceeds 10")
616+
617+ $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
618+ }
619+
620+
621+func suspendSuspicious (i) = suspend(("Suspicious state with asset: " + assetIds[i]))
622+
623+
624+func returnPayments (caller,payments) = {
625+ func parsePayments (acc,payment) = (acc :+ ScriptTransfer(caller, payment.amount, payment.assetId))
626+
627+ let $l = payments
628+ let $s = size($l)
629+ let $acc0 = nil
630+ func $f0_1 ($a,$i) = if (($i >= $s))
631+ then $a
632+ else parsePayments($a, $l[$i])
633+
634+ func $f0_2 ($a,$i) = if (($i >= $s))
635+ then $a
636+ else throw("List size exceeds 10")
637+
638+ $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
639+ }
640+
641+
642+func checkDAppThreshold (newBalances) = {
643+ let dAppThresholdCoef = valueOrErrorMessage(getInteger(this, kDAppThresholdCoef), "No dAppThresholdCoef key")
644+ let thresholdScale = 10000
645+ let maxBalance = max(newBalances)
646+ let minBalance = min(newBalances)
647+ let ratio = fraction(maxBalance, thresholdScale, minBalance)
648+ if ((ratio > (dAppThresholdCoef * thresholdScale)))
649+ then throw("New balance in assets of the DApp is less than threshold")
650+ else false
651+ }
652+
653+
654+func checkCoins (assetIds) = {
655+ let coins = split(assetIds, ",")
656+ if ((size(coins) > 10))
657+ then throw("To many coins, max coins size 10")
658+ else {
659+ func checkCoin (error,assetId) = {
660+ let asset = valueOrErrorMessage(fromBase58String(assetId), ("fromBase58String: " + assetId))
661+ let decimals = valueOrErrorMessage(assetInfo(asset), ("assetInfo: " + assetId)).decimals
662+ if ((decimals != DECIMALS))
663+ then throw("wrong decimals")
664+ else false
665+ }
666+
667+ let $l = coins
668+ let $s = size($l)
669+ let $acc0 = false
670+ func $f0_1 ($a,$i) = if (($i >= $s))
671+ then $a
672+ else checkCoin($a, $l[$i])
673+
674+ func $f0_2 ($a,$i) = if (($i >= $s))
675+ then $a
676+ else throw("List size exceeds 10")
677+
678+ $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
679+ }
680+ }
681+
682+
683+@Callable(msg)
684+func D (xp,amp) = {
685+ let D = get_D_internal(xp, amp)
686+ $Tuple2([IntegerEntry("D", D)], D)
687+ }
401688
402689
403690
404-@Callable(i)
405-func updatePoolInterest (pool) = valueOrElse(isActive(), if ((i.caller != govAddress))
406- then throw("Only Governance can call this function")
407- else {
408- let user = toString(addressFromPublicKey(adminInvokePubKey))
409- let $t01861718691 = claimCalc(pool, user)
410- let farmInterest = $t01861718691._1
411- let boostInterest = $t01861718691._2
412- let boostLPinterest = $t01861718691._3
413-[IntegerEntry((pool + kFarmLastInterest), farmInterest), IntegerEntry((pool + kBoostLastInterest), boostInterest), IntegerEntry((pool + kBoostLPLastInterest), boostLPinterest), IntegerEntry((pool + kLastInterestHeight), height)]
414- })
691+@Callable(msg)
692+func init (assetIds,_A,_dAppThresholdCoef) = if (!(isDataStorageUntouched(this)))
693+ then throw("Already initialized")
694+ else if ((0 >= _A))
695+ then throw("Amp must be must > 0")
696+ else if ((0 >= _dAppThresholdCoef))
697+ then throw("dApp Threshold Coef must be > 0")
698+ else {
699+ let shareName = "s_Multi_USD"
700+ let shareDescription = ("ShareToken of SwopFi protocol for MultiStable USD pool at address " + toString(this))
701+ let issueToken = Issue(shareName, shareDescription, 0, 6, true)
702+ let tokenId = calculateAssetId(issueToken)
703+ if (checkCoins(assetIds))
704+ then throw()
705+ else [StringEntry(kVersion, version), StringEntry(kAssets, assetIds), IntegerEntry("initial_A", _A), IntegerEntry("future_A", _A), IntegerEntry(kFee, getIntegerValue(oracle, "base_fee_flat")), StringEntry(kShareAssetId, toBase58String(tokenId)), IntegerEntry(kShareAssetSupply, 0), IntegerEntry(kDAppThresholdCoef, _dAppThresholdCoef), BooleanEntry(kActive, true), issueToken]
706+ }
415707
416708
417709
418-@Callable(i)
419-func lockShareTokens (pool,lockType) = valueOrElse(isActive(), {
420- let shareAssetId = getShareAssetId(pool)
421- let user = toString(i.originCaller)
422- let totalShare = getTotalShareToken(pool)
423- let totalShareVirtual = valueOrElse(getInteger(this, (pool + kShareTokensVirtual)), totalShare)
424- let userStakedAmount = valueOrElse(getInteger(this, (((pool + "_") + user) + kUserShareTokensStaked)), 0)
425- let userLockedHeigt = valueOrElse(getInteger(this, (((pool + "_") + user) + kUserShareTokensLockedHeight)), 0)
426- let userLockedAmount = valueOrElse(getInteger(this, (((pool + "_") + user) + kUserShareTokensLocked)), 0)
427- let userAmountVirtual = valueOrElse(getInteger(this, (((pool + "_") + user) + kUserShareTokensVirtual)), userStakedAmount)
428- let totalUserShareTokens = ((userStakedAmount + userLockedAmount) + i.payments[0].amount)
429- let $t01980019852 = getLockParams(lockType)
430- let lockPeriod = $t01980019852._1
431- let lockCoef = $t01980019852._2
432- let lockWavesFee = getIntegerValue(this, kLockWavesFee)
433- if ((i.payments[0].assetId != shareAssetId))
434- then throw("Wrong sharetoken in payment")
435- else if ((0 >= i.payments[0].amount))
436- then throw("Payment amount must be greater than 0")
437- else if ((0 > lockType))
438- then throw("lockType must be >= 0")
710+@Callable(msg)
711+func addLiquidity (minMintAmount,stakeFarming,lockType) = valueOrElse(isActive(), {
712+ let amp = _A()
713+ let xp = _xp()
714+ let D0 = if ((shareSupply == 0))
715+ then 0
716+ else getDMem(xp, amp)
717+ let $t01534915604 = if (if ((lockType > 0))
718+ then (msg.payments[(size(msg.payments) - 1)].assetId == unit)
719+ else false)
720+ then $Tuple2(removeByIndex(msg.payments, (size(msg.payments) - 1)), [msg.payments[(size(msg.payments) - 1)]])
721+ else $Tuple2(msg.payments, nil)
722+ let payments = $t01534915604._1
723+ let lockFee = $t01534915604._2
724+ let paymentsSize = size(payments)
725+ func validPayments (n) = if ((paymentsSize > nCoins))
726+ then throw(("payments size > " + toString(nCoins)))
727+ else if ((1 > paymentsSize))
728+ then throw("payments size < 1")
729+ else if (if ((shareSupply == 0))
730+ then (nCoins != paymentsSize)
731+ else false)
732+ then throw("initial deposit requires all coins")
439733 else {
440- let shareTokensChangeOnFH = canLockInFirstHarvest(pool, user, userStakedAmount, i.payments[0].amount, lockType)
441- if ((shareTokensChangeOnFH == shareTokensChangeOnFH))
442- then {
443- let $t02027922124 = if ((lockType == 0))
444- then {
445- let userAmountVirtualNew = ((userAmountVirtual + i.payments[0].amount) - shareTokensChangeOnFH)
446- $Tuple2([IntegerEntry((((pool + "_") + user) + kUserShareTokensStaked), ((userStakedAmount + i.payments[0].amount) - shareTokensChangeOnFH)), IntegerEntry((pool + kShareTokensVirtual), ((totalShareVirtual + i.payments[0].amount) - shareTokensChangeOnFH)), ScriptTransfer(i.originCaller, shareTokensChangeOnFH, i.payments[0].assetId)], ((totalShare + i.payments[0].amount) - shareTokensChangeOnFH))
447- }
448- else if (if ((userLockedHeigt == 0))
449- then if (if ((2 > size(i.payments)))
450- then true
451- else (i.payments[1].assetId != unit))
452- then true
453- else (lockWavesFee > i.payments[1].amount)
454- else false)
455- then throw((("You need to pay additional waves comission " + toString(lockWavesFee)) + "WAVES"))
456- else if ((userLockedHeigt > (height + lockPeriod)))
457- then throw("You cannot lock sharetokens for a period less than what you have already locked")
458- else {
459- let userLockedAmountNew = (userLockedAmount + i.payments[0].amount)
460- let userLockedHeigtNew = (height + lockPeriod)
461- let userAmountVirtualNew = (fraction(userLockedAmountNew, lockCoef, lockBoostCoefScale) + userStakedAmount)
462- $Tuple2([IntegerEntry((((pool + "_") + user) + kUserShareTokensLocked), userLockedAmountNew), IntegerEntry((((pool + "_") + user) + kUserShareTokensLockedHeight), userLockedHeigtNew), IntegerEntry((((pool + "_") + user) + kUserShareTokensLockedType), lockType), IntegerEntry((((pool + "_") + user) + kUserShareTokensVirtual), userAmountVirtualNew), IntegerEntry((pool + kShareTokensVirtual), ((totalShareVirtual - userAmountVirtual) + userAmountVirtualNew))], (totalShare + i.payments[0].amount))
463- }
464- let lockEntries = $t02027922124._1
465- let totalShareNew = $t02027922124._2
466- if ((accountBalance(shareAssetId) > totalShareNew))
467- then throw("Balance of share-token is lower than totalAmount")
734+ func paymantValid (acc,payment) = if (containsElement(assetIds, getStrAssetId(payment.assetId)))
735+ then true
736+ else throw("Invalid asset in payment")
737+
738+ let $l = payments
739+ let $s = size($l)
740+ let $acc0 = false
741+ func $f0_1 ($a,$i) = if (($i >= $s))
742+ then $a
743+ else paymantValid($a, $l[$i])
744+
745+ func $f0_2 ($a,$i) = if (($i >= $s))
746+ then $a
747+ else throw("List size exceeds 10")
748+
749+ $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
750+ }
751+
752+ if (!(validPayments(paymentsSize)))
753+ then throw()
754+ else {
755+ let suspicious = checkSuspicious()
756+ if (suspicious._1)
757+ then (suspendSuspicious(suspicious._2) ++ returnPayments(msg.caller, payments))
758+ else {
759+ func parsePayments (acc,assetId) = {
760+ let $t01647416500 = acc
761+ let newBalances = $t01647416500._1
762+ let i = $t01647416500._2
763+ func parsePayment (newBalance,payment) = if ((getStrAssetId(payment.assetId) == assetId))
764+ then (newBalance + payment.amount)
765+ else newBalance
766+
767+ let newBalace = {
768+ let $l = payments
769+ let $s = size($l)
770+ let $acc0 = xp[i]
771+ func $f0_1 ($a,$i) = if (($i >= $s))
772+ then $a
773+ else parsePayment($a, $l[$i])
774+
775+ func $f0_2 ($a,$i) = if (($i >= $s))
776+ then $a
777+ else throw("List size exceeds 10")
778+
779+ $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
780+ }
781+ $Tuple2((newBalances :+ newBalace), (i + 1))
782+ }
783+
784+ let $t01685016917 = {
785+ let $l = assetIds
786+ let $s = size($l)
787+ let $acc0 = $Tuple2(nil, 0)
788+ func $f0_1 ($a,$i) = if (($i >= $s))
789+ then $a
790+ else parsePayments($a, $l[$i])
791+
792+ func $f0_2 ($a,$i) = if (($i >= $s))
793+ then $a
794+ else throw("List size exceeds 10")
795+
796+ $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
797+ }
798+ let newBalances = $t01685016917._1
799+ let k = $t01685016917._2
800+ if (checkDAppThreshold(newBalances))
801+ then throw()
802+ else {
803+ let D1 = getDMem(newBalances, amp)
804+ if (assert((D1 > D0)))
805+ then throw("D1 > D0")
468806 else {
469- let $t02224922348 = claimCalc(pool, user)
470- let farmInterest = $t02224922348._1
471- let boostInterest = $t02224922348._2
472- let boostLPinterest = $t02224922348._3
473- let claimAmount = $t02224922348._4
474- let toTreasure = $t02224922348._5
475- let availableFundsNew = (userAvailableSWOP(pool, i.originCaller) + claimAmount)
476- let uplp = if ((getString(Address(fromBase58String(pool)), "version") == "3.0.0"))
477- then invoke(lpFarmingAddress, "updateUserInterest", [pool, totalUserShareTokens], nil)
478- else 0
479- if ((uplp == uplp))
480- then ([IntegerEntry((((pool + "_") + user) + kFarmUserLastInterest), farmInterest), IntegerEntry((((pool + "_") + user) + kBoostUserLastInterest), boostInterest), IntegerEntry((((pool + "_") + user) + kBoostLPLastInterest), boostLPinterest), IntegerEntry((pool + kFarmLastInterest), farmInterest), IntegerEntry((pool + kBoostLastInterest), boostInterest), IntegerEntry((pool + kBoostLPLastInterest), boostLPinterest), IntegerEntry((pool + kLastInterestHeight), height), IntegerEntry((pool + kShareTotalShareTokens), totalShareNew), IntegerEntry((((pool + "_") + user) + kAvailableSWOP), availableFundsNew), Reissue(SWOP, toTreasure, true), ScriptTransfer(farmingTreasureAddr, toTreasure, SWOP)] ++ lockEntries)
481- else throw("Strict value is not equal to itself.")
807+ let feeDiscount = calculateFeeDiscount(msg.caller)
808+ func calcScriptActions (acc,newBalance) = {
809+ let $t01723717278 = acc
810+ let invBalances = $t01723717278._1
811+ let scriptActions = $t01723717278._2
812+ let i = $t01723717278._3
813+ if ((shareSupply > 0))
814+ then {
815+ let _fee = ((fraction(fee, feeDiscount, feeScale6, CEILING) * nCoins) / (4 * (nCoins - 1)))
816+ let fees = {
817+ let idealBalance = fraction(D1, xp[i], D0)
818+ let difference = if ((idealBalance > newBalance))
819+ then (idealBalance - newBalance)
820+ else (newBalance - idealBalance)
821+ fraction(_fee, difference, feeScale6)
822+ }
823+ let governanceFees = fraction(fees, feeGovernance, feeScale6)
824+ let finalBalance = (newBalance - fees)
825+ let invariantBalance = (newBalance - fees)
826+ let pmt = (newBalance - xp[i])
827+ let lpFees = (fees - governanceFees)
828+ let inv = if ((pmt > 0))
829+ then stake((pmt - fees), assetIds[i])
830+ else unstake(fees, assetIds[i])
831+ if ((inv == inv))
832+ then {
833+ let airdrop = if ((lpFees > 0))
834+ then invoke(lpFarmingAddress, "airDrop", nil, [AttachedPayment(fromBase58String(assetIds[i]), lpFees)])
835+ else 0
836+ if ((airdrop == airdrop))
837+ then $Tuple3((invBalances :+ invariantBalance), (scriptActions ++ [ScriptTransfer(moneyBoxAddress, governanceFees, fromBase58String(assetIds[i])), IntegerEntry((assetIds[i] + kAssetBalance), finalBalance)]), (i + 1))
838+ else throw("Strict value is not equal to itself.")
839+ }
840+ else throw("Strict value is not equal to itself.")
841+ }
842+ else {
843+ let inv = stake(newBalance, assetIds[i])
844+ if ((inv == inv))
845+ then $Tuple3((invBalances :+ newBalance), (scriptActions :+ IntegerEntry((assetIds[i] + kAssetBalance), newBalance)), (i + 1))
846+ else throw("Strict value is not equal to itself.")
847+ }
848+ }
849+
850+ let $t01898319071 = {
851+ let $l = newBalances
852+ let $s = size($l)
853+ let $acc0 = $Tuple3(nil, nil, 0)
854+ func $f1_1 ($a,$i) = if (($i >= $s))
855+ then $a
856+ else calcScriptActions($a, $l[$i])
857+
858+ func $f1_2 ($a,$i) = if (($i >= $s))
859+ then $a
860+ else throw("List size exceeds 10")
861+
862+ $f1_2($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
863+ }
864+ let invBalances = $t01898319071._1
865+ let scriptActions = $t01898319071._2
866+ let D2 = getDMem(invBalances, amp)
867+ let mint_amount = if ((shareSupply == 0))
868+ then D1
869+ else fraction(shareSupply, (D2 - D0), D0)
870+ if (assert((mint_amount >= minMintAmount)))
871+ then throw("Slippage screwed you")
872+ else if (stakeFarming)
873+ then {
874+ let re = invoke(this, "reissueShare", [mint_amount], nil)
875+ if ((re == re))
876+ then {
877+ let s = invoke(farmingAddress, "lockShareTokens", [toString(this), lockType], ([AttachedPayment(shareAssetId, mint_amount)] ++ lockFee))
878+ if ((s == s))
879+ then (scriptActions :+ IntegerEntry(kShareAssetSupply, (shareSupply + mint_amount)))
880+ else throw("Strict value is not equal to itself.")
881+ }
882+ else throw("Strict value is not equal to itself.")
883+ }
884+ else (scriptActions ++ [Reissue(shareAssetId, mint_amount, true), ScriptTransfer(msg.caller, mint_amount, shareAssetId), IntegerEntry(kShareAssetSupply, (shareSupply + mint_amount))])
482885 }
483886 }
484- else throw("Strict value is not equal to itself.")
485887 }
486- })
487-
488-
489-
490-@Callable(i)
491-func lockStakedShareTokens (pool,lockType,lockAmount) = valueOrElse(isActive(), {
492- let shareAssetId = getShareAssetId(pool)
493- let user = toString(i.originCaller)
494- let totalShare = getTotalShareToken(pool)
495- let totalShareVirtual = valueOrElse(getInteger(this, (pool + kShareTokensVirtual)), totalShare)
496- let userStakedAmount = valueOrElse(getInteger(this, (((pool + "_") + user) + kUserShareTokensStaked)), 0)
497- let userLockedHeigt = valueOrElse(getInteger(this, (((pool + "_") + user) + kUserShareTokensLockedHeight)), 0)
498- let userLockedAmount = valueOrElse(getInteger(this, (((pool + "_") + user) + kUserShareTokensLocked)), 0)
499- let userAmountVirtual = valueOrElse(getInteger(this, (((pool + "_") + user) + kUserShareTokensVirtual)), userStakedAmount)
500- let totalUserShareTokens = (userStakedAmount + userLockedAmount)
501- let $t02425624308 = getLockParams(lockType)
502- let lockPeriod = $t02425624308._1
503- let lockCoef = $t02425624308._2
504- let lockWavesFee = getIntegerValue(this, kLockWavesFee)
505- if ((getHeightFirstHarvest(pool) > height))
506- then throw("You can't lock shareTokens till first harvest end.")
507- else if ((0 >= lockType))
508- then throw("lockType must be > 0")
509- else if ((lockAmount > userStakedAmount))
510- then throw(("You can't lock more than " + toString(userStakedAmount)))
511- else if ((accountBalance(shareAssetId) > totalShare))
512- then throw("Balance of share-token is lower than totalAmount")
513- else if (if ((userLockedHeigt == 0))
514- then if (if ((1 > size(i.payments)))
515- then true
516- else (i.payments[0].assetId != unit))
517- then true
518- else (lockWavesFee > i.payments[0].amount)
519- else false)
520- then throw((("You need to pay additional waves comission " + toString(lockWavesFee)) + "WAVES"))
521- else if (if ((userLockedHeigt == 0))
522- then (0 >= lockAmount)
523- else false)
524- then throw("lockAmount must be greater than 0")
525- else if ((0 > lockAmount))
526- then throw("lockAmount must be positive")
527- else if ((userLockedHeigt > (height + lockPeriod)))
528- then throw("You cannot lock sharetokens for a period less than what you have already locked")
529- else {
530- let userLockedAmountNew = (userLockedAmount + lockAmount)
531- let userStakedAmountNew = (userStakedAmount - lockAmount)
532- let userLockedHeigtNew = (height + lockPeriod)
533- let userAmountVirtualNew = (fraction(userLockedAmountNew, lockCoef, lockBoostCoefScale) + userStakedAmount)
534- let $t02559525694 = claimCalc(pool, user)
535- let farmInterest = $t02559525694._1
536- let boostInterest = $t02559525694._2
537- let boostLPinterest = $t02559525694._3
538- let claimAmount = $t02559525694._4
539- let toTreasure = $t02559525694._5
540- let availableFundsNew = (userAvailableSWOP(pool, i.originCaller) + claimAmount)
541-[IntegerEntry((((pool + "_") + user) + kUserShareTokensStaked), userStakedAmountNew), IntegerEntry((((pool + "_") + user) + kUserShareTokensLocked), userLockedAmountNew), IntegerEntry((((pool + "_") + user) + kUserShareTokensLockedHeight), userLockedHeigtNew), IntegerEntry((((pool + "_") + user) + kUserShareTokensLockedType), lockType), IntegerEntry((((pool + "_") + user) + kUserShareTokensVirtual), userAmountVirtualNew), IntegerEntry((pool + kShareTokensVirtual), ((totalShareVirtual - userAmountVirtual) + userAmountVirtualNew)), IntegerEntry((((pool + "_") + user) + kFarmUserLastInterest), farmInterest), IntegerEntry((((pool + "_") + user) + kBoostUserLastInterest), boostInterest), IntegerEntry((((pool + "_") + user) + kBoostLPLastInterest), boostLPinterest), IntegerEntry((pool + kFarmLastInterest), farmInterest), IntegerEntry((pool + kBoostLastInterest), boostInterest), IntegerEntry((pool + kBoostLPLastInterest), boostLPinterest), IntegerEntry((pool + kLastInterestHeight), height), IntegerEntry((((pool + "_") + user) + kAvailableSWOP), availableFundsNew), Reissue(SWOP, toTreasure, true), ScriptTransfer(farmingTreasureAddr, toTreasure, SWOP)]
542- }
543- })
544-
545-
546-
547-@Callable(i)
548-func unlockUserLock (pool,user) = valueOrElse(isActive(), {
549- let lockWavesFee = getIntegerValue(this, kLockWavesFee)
550- let userLockedHeigt = valueOrErrorMessage(getInteger(this, (((pool + "_") + user) + kUserShareTokensLockedHeight)), (((("There is no pool " + pool) + " or user ") + user) + "with lock"))
551- let totalShareVirtual = getIntegerValue(this, (pool + kShareTokensVirtual))
552- let userStakedAmount = valueOrElse(getInteger(this, (((pool + "_") + user) + kUserShareTokensStaked)), 0)
553- let userLockedAmount = valueOrElse(getInteger(this, (((pool + "_") + user) + kUserShareTokensLocked)), 0)
554- let userAmountVirtual = valueOrElse(getInteger(this, (((pool + "_") + user) + kUserShareTokensVirtual)), userStakedAmount)
555- if ((userLockedHeigt > height))
556- then throw(("You can't unlock sharetokens till " + toString(userLockedHeigt)))
557- else {
558- let userStakedAmountNew = (userStakedAmount + userLockedAmount)
559- let $t02793028029 = claimCalc(pool, user)
560- let farmInterest = $t02793028029._1
561- let boostInterest = $t02793028029._2
562- let boostLPinterest = $t02793028029._3
563- let claimAmount = $t02793028029._4
564- let toTreasure = $t02793028029._5
565- let availableFundsNew = (userAvailableSWOP(pool, i.originCaller) + claimAmount)
566-[IntegerEntry((((pool + "_") + user) + kFarmUserLastInterest), farmInterest), IntegerEntry((((pool + "_") + user) + kBoostUserLastInterest), boostInterest), IntegerEntry((((pool + "_") + user) + kBoostLPLastInterest), boostLPinterest), IntegerEntry((pool + kFarmLastInterest), farmInterest), IntegerEntry((pool + kBoostLastInterest), boostInterest), IntegerEntry((pool + kBoostLPLastInterest), boostLPinterest), IntegerEntry((pool + kLastInterestHeight), height), IntegerEntry((((pool + "_") + user) + kUserShareTokensStaked), userStakedAmountNew), IntegerEntry((((pool + "_") + user) + kUserShareTokensVirtual), userStakedAmountNew), IntegerEntry((pool + kShareTokensVirtual), ((totalShareVirtual - userAmountVirtual) + userStakedAmountNew)), DeleteEntry((((pool + "_") + user) + kUserShareTokensLocked)), DeleteEntry((((pool + "_") + user) + kUserShareTokensLockedHeight)), DeleteEntry((((pool + "_") + user) + kUserShareTokensLockedType)), Reissue(SWOP, toTreasure, true), ScriptTransfer(farmingTreasureAddr, toTreasure, SWOP), ScriptTransfer(i.caller, lockWavesFee, unit)]
567888 }
568889 })
569890
570891
571892
572-@Callable(i)
573-func withdrawShareTokens (pool,shareTokensWithdrawAmount) = valueOrElse(isActive(), {
574- let shareTokensId = fromBase58String(getStringValue(value(addressFromString(pool)), "share_asset_id"))
575- let user = toString(i.originCaller)
576- let $t02953329632 = claimCalc(pool, user)
577- let farmInterest = $t02953329632._1
578- let boostInterest = $t02953329632._2
579- let boostLPinterest = $t02953329632._3
580- let claimAmount = $t02953329632._4
581- let toTreasure = $t02953329632._5
582- let userStakedAmount = valueOrElse(getInteger(this, (((pool + "_") + user) + kUserShareTokensStaked)), 0)
583- let userLockedAmount = valueOrElse(getInteger(this, (((pool + "_") + user) + kUserShareTokensLocked)), 0)
584- let userAmountVirtual = valueOrElse(getInteger(this, (((pool + "_") + user) + kUserShareTokensVirtual)), userStakedAmount)
585- let userStakedAmountNew = (userStakedAmount - shareTokensWithdrawAmount)
586- let availableFundsNew = (userAvailableSWOP(pool, i.originCaller) + claimAmount)
587- let totalShareAmount = getTotalShareToken(pool)
588- let totalShareVirtual = valueOrElse(getInteger(this, (pool + kShareTokensVirtual)), totalShareAmount)
589- let totalShareAmountNew = (totalShareAmount - shareTokensWithdrawAmount)
590- let totalShareVirtualNew = (totalShareVirtual - shareTokensWithdrawAmount)
591- let userAmountVirtualNew = (userAmountVirtual - shareTokensWithdrawAmount)
592- if ((shareTokensWithdrawAmount > userStakedAmount))
593- then throw("Withdraw amount more then user locked amount")
594- else if ((accountBalance(shareTokensId) > totalShareAmount))
595- then throw("Balance of share-token is lower than totalAmount")
596- else {
597- let uplp = if ((getString(Address(fromBase58String(pool)), "version") == "3.0.0"))
598- then invoke(lpFarmingAddress, "updateUserInterest", [pool, (userStakedAmount + userLockedAmount)], nil)
599- else 0
600- if ((uplp == uplp))
601- then [IntegerEntry((((pool + "_") + user) + kFarmUserLastInterest), farmInterest), IntegerEntry((((pool + "_") + user) + kBoostUserLastInterest), boostInterest), IntegerEntry((((pool + "_") + user) + kBoostLPLastInterest), boostLPinterest), IntegerEntry((pool + kFarmLastInterest), farmInterest), IntegerEntry((pool + kBoostLastInterest), boostInterest), IntegerEntry((pool + kBoostLPLastInterest), boostLPinterest), IntegerEntry((pool + kLastInterestHeight), height), IntegerEntry((((pool + "_") + user) + kUserShareTokensStaked), userStakedAmountNew), IntegerEntry((((pool + "_") + user) + kUserShareTokensVirtual), userAmountVirtualNew), IntegerEntry((pool + kShareTotalShareTokens), totalShareAmountNew), IntegerEntry((pool + kShareTokensVirtual), totalShareVirtualNew), IntegerEntry((((pool + "_") + user) + kAvailableSWOP), availableFundsNew), Reissue(SWOP, toTreasure, true), ScriptTransfer(farmingTreasureAddr, toTreasure, SWOP), ScriptTransfer(i.caller, shareTokensWithdrawAmount, shareTokensId)]
602- else throw("Strict value is not equal to itself.")
893+@Callable(msg)
894+func calcMintAmount (newBalances,user) = {
895+ let amp = _A()
896+ let xp = _xp()
897+ let D1 = getDMem(newBalances, amp)
898+ if ((shareSupply == 0))
899+ then $Tuple2(nil, D1)
900+ else {
901+ let D0 = getDMem(xp, amp)
902+ let feeDiscount = calculateFeeDiscount(user)
903+ func calcInvBalances (acc,newBalance) = {
904+ let $t02032120347 = acc
905+ let invBalances = $t02032120347._1
906+ let i = $t02032120347._2
907+ let _fee = ((fraction(fee, feeDiscount, feeScale6, CEILING) * nCoins) / (4 * (nCoins - 1)))
908+ let fees = {
909+ let idealBalance = fraction(D1, xp[i], D0)
910+ let difference = if ((idealBalance > newBalance))
911+ then (idealBalance - newBalance)
912+ else (newBalance - idealBalance)
913+ fraction(_fee, difference, feeScale6)
914+ }
915+ let invariantBalance = (newBalance - fees)
916+ $Tuple2((invBalances :+ invariantBalance), (i + 1))
603917 }
604- })
918+
919+ let $t02094921019 = {
920+ let $l = newBalances
921+ let $s = size($l)
922+ let $acc0 = $Tuple2(nil, 0)
923+ func $f0_1 ($a,$i) = if (($i >= $s))
924+ then $a
925+ else calcInvBalances($a, $l[$i])
926+
927+ func $f0_2 ($a,$i) = if (($i >= $s))
928+ then $a
929+ else throw("List size exceeds 10")
930+
931+ $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
932+ }
933+ let invBalances = $t02094921019._1
934+ let k = $t02094921019._2
935+ let D2 = getDMem(invBalances, amp)
936+ let mintAmount = fraction(shareSupply, (D2 - D0), D0)
937+ $Tuple2(nil, mintAmount)
938+ }
939+ }
605940
606941
607942
608-@Callable(i)
609-func claim (pool) = valueOrElse(isActive(), {
610- let shareTokensId = fromBase58String(getStringValue(value(addressFromString(pool)), "share_asset_id"))
611- let user = toString(i.caller)
612- let shareTokenLocked = getTotalShareToken(pool)
613- let $t03230132400 = claimCalc(pool, user)
614- let farmInterest = $t03230132400._1
615- let boostInterest = $t03230132400._2
616- let boostLPinterest = $t03230132400._3
617- let claimAmount = $t03230132400._4
618- let toTreasure = $t03230132400._5
619- let availableFund = (userAvailableSWOP(pool, i.caller) + claimAmount)
620- if ((availableFund == 0))
621- then throw("You have 0 available SWOP")
622- else if ((accountBalance(shareTokensId) > shareTokenLocked))
623- then throw("Balance of share-token is lower than totalAmount")
624- else $Tuple2([IntegerEntry((((pool + "_") + user) + kFarmUserLastInterest), farmInterest), IntegerEntry((((pool + "_") + user) + kBoostUserLastInterest), boostInterest), IntegerEntry((((pool + "_") + user) + kBoostLPLastInterest), boostLPinterest), IntegerEntry((pool + kFarmLastInterest), farmInterest), IntegerEntry((pool + kBoostLastInterest), boostInterest), IntegerEntry((pool + kBoostLPLastInterest), boostLPinterest), IntegerEntry((pool + kLastInterestHeight), height), IntegerEntry((((pool + "_") + user) + kAvailableSWOP), 0), Reissue(SWOP, (toTreasure + availableFund), true), ScriptTransfer(farmingTreasureAddr, toTreasure, SWOP), ScriptTransfer(i.caller, availableFund, SWOP)], availableFund)
625- })
943+@Callable(msg)
944+func reissueShare (amount) = valueOrElse(isSelfCall(msg), [Reissue(shareAssetId, amount, true)])
626945
627946
628947
629-@Callable(i)
630-func claimAndStake (pool) = valueOrElse(isActive(), {
631- let claimAmount = {
632- let @ = invoke(this, "claim", [pool], nil)
633- if ($isInstanceOf(@, "Int"))
634- then @
635- else throw(($getType(@) + " couldn't be cast to Int"))
636- }
637- if ((claimAmount == claimAmount))
638- then {
639- let stakeToGov = invoke(govAddress, "lockSWOPFromFarming", nil, [AttachedPayment(SWOP, claimAmount)])
640- if ((stakeToGov == stakeToGov))
641- then nil
642- else throw("Strict value is not equal to itself.")
643- }
644- else throw("Strict value is not equal to itself.")
645- })
948+@Callable(msg)
949+func getDy (assetFrom,assetTo,dx,userAddress) = {
950+ let xp = _xp()
951+ let fromIndex = valueOrErrorMessage(indexOf(assetIds, assetFrom), "unknown token in")
952+ let toIndex = valueOrErrorMessage(indexOf(assetIds, assetTo), "unknown token out")
953+ let x = (xp[fromIndex] + dx)
954+ let y = getY(fromIndex, toIndex, x, xp)
955+ let dy = ((xp[toIndex] - y) - 1)
956+ let feeDiscount = calculateFeeDiscount(Address(fromBase58String(userAddress)))
957+ let _fee = fraction(fraction(fee, feeDiscount, feeScale6, CEILING), dy, feeScale6)
958+ $Tuple2(nil, $Tuple2((dy - _fee), _fee))
959+ }
646960
647961
648962
649-@Callable(i)
650-func claimAll (pools) = valueOrElse(isActive(), {
651- func claimInv (claimTotal,pool) = {
652- let claimAmount = {
653- let @ = invoke(this, "claim", [pool], nil)
654- if ($isInstanceOf(@, "Int"))
655- then @
656- else throw(($getType(@) + " couldn't be cast to Int"))
657- }
658- if ((claimAmount == claimAmount))
659- then (claimTotal + claimAmount)
660- else throw("Strict value is not equal to itself.")
661- }
963+@Callable(msg)
964+func exchange (tokenOut,min_dy) = valueOrElse(isActive(), if ((size(msg.payments) != 1))
965+ then throw("size(payments) != 1")
966+ else {
967+ let suspicious = checkSuspicious()
968+ if (suspicious._1)
969+ then (suspendSuspicious(suspicious._2) ++ returnPayments(msg.caller, msg.payments))
970+ else {
971+ let payment = msg.payments[0]
972+ let tokenIn = getStrAssetId(payment.assetId)
973+ let tokenOutB58 = fromBase58String(tokenOut)
974+ let dx = payment.amount
975+ let fromIndex = valueOrErrorMessage(indexOf(assetIds, tokenIn), "unknown token in")
976+ let toIndex = valueOrErrorMessage(indexOf(assetIds, tokenOut), "unknown token out")
977+ let xp = _xp()
978+ let x = (xp[fromIndex] + dx)
979+ let y = getY(fromIndex, toIndex, x, xp)
980+ let _dy = ((xp[toIndex] - y) - 1)
981+ let feeDiscount = calculateFeeDiscount(msg.originCaller)
982+ let _fee = fraction(_dy, fraction(fee, feeDiscount, feeScale6, CEILING), feeScale6)
983+ let dy = (_dy - _fee)
984+ let governanceFees = fraction(_fee, feeGovernance, feeScale6)
985+ if (assert((dy >= min_dy)))
986+ then throw("Exchange resulted in fewer coins than expected")
987+ else {
988+ func makeNewBalances (acc,tokenBalance) = {
989+ let $t02306023086 = acc
990+ let newBalances = $t02306023086._1
991+ let i = $t02306023086._2
992+ if ((i == fromIndex))
993+ then $Tuple2((newBalances :+ (tokenBalance + dx)), (i + 1))
994+ else if ((i == toIndex))
995+ then $Tuple2((newBalances :+ (tokenBalance - _dy)), (i + 1))
996+ else $Tuple2((newBalances :+ tokenBalance), (i + 1))
997+ }
662998
663- let claimTotal = {
664- let $l = pools
665- let $s = size($l)
666- let $acc0 = 0
667- func $f0_1 ($a,$i) = if (($i >= $s))
668- then $a
669- else claimInv($a, $l[$i])
999+ let $t02333723398 = {
1000+ let $l = xp
1001+ let $s = size($l)
1002+ let $acc0 = $Tuple2(nil, 0)
1003+ func $f0_1 ($a,$i) = if (($i >= $s))
1004+ then $a
1005+ else makeNewBalances($a, $l[$i])
6701006
671- func $f0_2 ($a,$i) = if (($i >= $s))
672- then $a
673- else throw("List size exceeds 60")
1007+ func $f0_2 ($a,$i) = if (($i >= $s))
1008+ then $a
1009+ else throw("List size exceeds 10")
6741010
675- $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($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($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($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), 20), 21), 22), 23), 24), 25), 26), 27), 28), 29), 30), 31), 32), 33), 34), 35), 36), 37), 38), 39), 40), 41), 42), 43), 44), 45), 46), 47), 48), 49), 50), 51), 52), 53), 54), 55), 56), 57), 58), 59), 60)
676- }
677- if ((claimTotal == 0))
678- then throw("You have 0 available SWOP")
679- else [ScriptTransfer(i.caller, claimTotal, SWOP)]
680- })
681-
682-
683-
684-@Callable(i)
685-func claimAllAndStake (pools) = valueOrElse(isActive(), {
686- func claimInv (claimTotal,pool) = {
687- let claimAmount = {
688- let @ = invoke(this, "claim", [pool], nil)
689- if ($isInstanceOf(@, "Int"))
690- then @
691- else throw(($getType(@) + " couldn't be cast to Int"))
692- }
693- if ((claimAmount == claimAmount))
694- then (claimTotal + claimAmount)
695- else throw("Strict value is not equal to itself.")
696- }
697-
698- let claimTotal = {
699- let $l = pools
700- let $s = size($l)
701- let $acc0 = 0
702- func $f0_1 ($a,$i) = if (($i >= $s))
703- then $a
704- else claimInv($a, $l[$i])
705-
706- func $f0_2 ($a,$i) = if (($i >= $s))
707- then $a
708- else throw("List size exceeds 60")
709-
710- $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($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($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($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), 20), 21), 22), 23), 24), 25), 26), 27), 28), 29), 30), 31), 32), 33), 34), 35), 36), 37), 38), 39), 40), 41), 42), 43), 44), 45), 46), 47), 48), 49), 50), 51), 52), 53), 54), 55), 56), 57), 58), 59), 60)
711- }
712- if ((claimTotal == 0))
713- then throw("You have 0 available SWOP")
714- else {
715- let stakeToGov = invoke(govAddress, "lockSWOPFromFarming", nil, [AttachedPayment(SWOP, claimTotal)])
716- if ((stakeToGov == stakeToGov))
717- then nil
718- else throw("Strict value is not equal to itself.")
719- }
720- })
721-
722-
723-
724-@Callable(i)
725-func updateUserBoostInterest (pool,user) = valueOrElse(isActive(), if ((i.caller != votingAddress))
726- then throw("Only voiting can call this function")
727- else {
728- let $t03478034879 = claimCalc(pool, user)
729- let farmInterest = $t03478034879._1
730- let boostInterest = $t03478034879._2
731- let boostLPinterest = $t03478034879._3
732- let claimAmount = $t03478034879._4
733- let toTreasure = $t03478034879._5
734- let availableFundsNew = (userAvailableSWOP(pool, i.originCaller) + claimAmount)
735-[IntegerEntry((((pool + "_") + user) + kFarmUserLastInterest), farmInterest), IntegerEntry((((pool + "_") + user) + kBoostUserLastInterest), boostInterest), IntegerEntry((((pool + "_") + user) + kBoostLPLastInterest), boostLPinterest), IntegerEntry((pool + kFarmLastInterest), farmInterest), IntegerEntry((pool + kBoostLastInterest), boostInterest), IntegerEntry((pool + kBoostLPLastInterest), boostLPinterest), IntegerEntry((pool + kLastInterestHeight), height), IntegerEntry((((pool + "_") + user) + kAvailableSWOP), availableFundsNew), Reissue(SWOP, toTreasure, true), ScriptTransfer(farmingTreasureAddr, toTreasure, SWOP)]
1011+ $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
1012+ }
1013+ let newBalances = $t02333723398._1
1014+ let i = $t02333723398._2
1015+ if (checkDAppThreshold(newBalances))
1016+ then throw()
1017+ else {
1018+ let s = stake(payment.amount, getStrAssetId(payment.assetId))
1019+ if ((s == s))
1020+ then {
1021+ let us = unstake(_dy, tokenOut)
1022+ if ((us == us))
1023+ then {
1024+ let lpFees = (_fee - governanceFees)
1025+ let airdrop = if ((lpFees > 0))
1026+ then invoke(lpFarmingAddress, "airDrop", nil, [AttachedPayment(tokenOutB58, lpFees)])
1027+ else 0
1028+ if ((airdrop == airdrop))
1029+ then $Tuple2([IntegerEntry((tokenIn + kAssetBalance), x), IntegerEntry((tokenOut + kAssetBalance), (xp[toIndex] - _dy)), ScriptTransfer(msg.caller, dy, tokenOutB58), ScriptTransfer(moneyBoxAddress, governanceFees, tokenOutB58)], [dy, tokenOutB58])
1030+ else throw("Strict value is not equal to itself.")
1031+ }
1032+ else throw("Strict value is not equal to itself.")
1033+ }
1034+ else throw("Strict value is not equal to itself.")
1035+ }
1036+ }
1037+ }
7361038 })
7371039
7381040
7391041
740-@Callable(i)
741-func shutdown () = valueOrElse(isAdminCall(i), if (!(active))
1042+@Callable(msg)
1043+func withdraw (minAmounts) = valueOrElse(isActive(), if ((size(msg.payments) != 1))
1044+ then throw("size(payments) != 1")
1045+ else {
1046+ let pmtAmount = msg.payments[0].amount
1047+ let pmtAssetId = msg.payments[0].assetId
1048+ if ((shareAssetId != pmtAssetId))
1049+ then throw("unknown payment token")
1050+ else {
1051+ let suspicious = checkSuspicious()
1052+ if (suspicious._1)
1053+ then (suspendSuspicious(suspicious._2) ++ returnPayments(msg.originCaller, msg.payments))
1054+ else {
1055+ func calcScriptActions (acc,balance) = {
1056+ let $t02468924717 = acc
1057+ let scriptActions = $t02468924717._1
1058+ let i = $t02468924717._2
1059+ let wAmount = fraction(balance, pmtAmount, shareSupply)
1060+ if (assert((wAmount >= minAmounts[i])))
1061+ then throw("Withdrawal resulted in fewer coins than expected")
1062+ else {
1063+ let us = unstake(wAmount, assetIds[i])
1064+ if ((us == us))
1065+ then $Tuple2((scriptActions ++ [IntegerEntry((assetIds[i] + kAssetBalance), (balance - wAmount)), ScriptTransfer(msg.originCaller, wAmount, fromBase58String(assetIds[i]))]), (i + 1))
1066+ else throw("Strict value is not equal to itself.")
1067+ }
1068+ }
1069+
1070+ let $t02520725275 = {
1071+ let $l = _xp()
1072+ let $s = size($l)
1073+ let $acc0 = $Tuple2(nil, 0)
1074+ func $f0_1 ($a,$i) = if (($i >= $s))
1075+ then $a
1076+ else calcScriptActions($a, $l[$i])
1077+
1078+ func $f0_2 ($a,$i) = if (($i >= $s))
1079+ then $a
1080+ else throw("List size exceeds 10")
1081+
1082+ $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
1083+ }
1084+ let scriptActions = $t02520725275._1
1085+ let i = $t02520725275._2
1086+ (scriptActions ++ [Burn(shareAssetId, pmtAmount), IntegerEntry(kShareAssetSupply, (shareSupply - pmtAmount))])
1087+ }
1088+ }
1089+ })
1090+
1091+
1092+
1093+@Callable(msg)
1094+func withdrawWithUnlock (minAmounts,unlockAmount) = valueOrElse(isActive(), if ((0 >= unlockAmount))
1095+ then throw("Unlock amount must be positive")
1096+ else {
1097+ let suspicious = checkSuspicious()
1098+ if (suspicious._1)
1099+ then (suspendSuspicious(suspicious._2) ++ returnPayments(msg.caller, msg.payments))
1100+ else {
1101+ let pmtAmount = if ((size(msg.payments) > 0))
1102+ then if ((size(msg.payments) != 1))
1103+ then throw("size(payments) != 1")
1104+ else {
1105+ let pmtAssetId = msg.payments[0].assetId
1106+ if ((shareAssetId != pmtAssetId))
1107+ then throw("unknown payment token")
1108+ else msg.payments[0].amount
1109+ }
1110+ else 0
1111+ let unlock = invoke(farmingAddress, "withdrawShareTokens", [toString(this), unlockAmount], nil)
1112+ if ((unlock == unlock))
1113+ then {
1114+ let withdrawAmount = (pmtAmount + unlockAmount)
1115+ let inv = invoke(this, "withdraw", [minAmounts], [AttachedPayment(shareAssetId, withdrawAmount)])
1116+ if ((inv == inv))
1117+ then nil
1118+ else throw("Strict value is not equal to itself.")
1119+ }
1120+ else throw("Strict value is not equal to itself.")
1121+ }
1122+ })
1123+
1124+
1125+
1126+@Callable(msg)
1127+func calcWithdrawOneCoin (tokenAmount,tokenOut,user) = if ((0 >= tokenAmount))
1128+ then throw("Amount must be positive")
1129+ else {
1130+ let i = valueOrErrorMessage(indexOf(assetIds, tokenOut), "unknown token out")
1131+ $Tuple2(nil, _calcWithdrawOneCoin(_xp(), tokenAmount, i, Address(fromBase58String(user)))._1)
1132+ }
1133+
1134+
1135+
1136+@Callable(msg)
1137+func withdrawOneCoin (tokenOut,minAmount) = valueOrElse(isActive(), if ((size(msg.payments) != 1))
1138+ then throw("size(payments) != 1")
1139+ else {
1140+ let suspicious = checkSuspicious()
1141+ if (suspicious._1)
1142+ then (suspendSuspicious(suspicious._2) ++ returnPayments(msg.originCaller, msg.payments))
1143+ else {
1144+ let pmtAmount = msg.payments[0].amount
1145+ let pmtAssetId = msg.payments[0].assetId
1146+ if ((pmtAssetId != shareAssetId))
1147+ then throw("unknown token")
1148+ else {
1149+ let outIndex = valueOrErrorMessage(indexOf(assetIds, tokenOut), "unknown token out")
1150+ let tokenOutB58 = fromBase58String(tokenOut)
1151+ let xp = _xp()
1152+ let $t02730727389 = _calcWithdrawOneCoin(xp, pmtAmount, outIndex, msg.originCaller)
1153+ let dy = $t02730727389._1
1154+ let dy_fee = $t02730727389._2
1155+ if (assert((dy >= minAmount)))
1156+ then throw("Not enough coins removed")
1157+ else {
1158+ let governanceFees = fraction(dy_fee, feeGovernance, feeScale6)
1159+ let dy_and_fee = (dy + dy_fee)
1160+ func makeNewBalances (acc,tokenBalance) = {
1161+ let $t02764727673 = acc
1162+ let newBalances = $t02764727673._1
1163+ let i = $t02764727673._2
1164+ if ((i == outIndex))
1165+ then $Tuple2((newBalances :+ (tokenBalance - dy_and_fee)), (i + 1))
1166+ else $Tuple2((newBalances :+ tokenBalance), (i + 1))
1167+ }
1168+
1169+ let $t02784027901 = {
1170+ let $l = xp
1171+ let $s = size($l)
1172+ let $acc0 = $Tuple2(nil, 0)
1173+ func $f0_1 ($a,$i) = if (($i >= $s))
1174+ then $a
1175+ else makeNewBalances($a, $l[$i])
1176+
1177+ func $f0_2 ($a,$i) = if (($i >= $s))
1178+ then $a
1179+ else throw("List size exceeds 10")
1180+
1181+ $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
1182+ }
1183+ let newBalances = $t02784027901._1
1184+ let v = $t02784027901._2
1185+ if (checkDAppThreshold(newBalances))
1186+ then throw()
1187+ else {
1188+ let us = unstake(dy_and_fee, tokenOut)
1189+ if ((us == us))
1190+ then {
1191+ let lpFees = (dy_fee - governanceFees)
1192+ let airdrop = if ((lpFees > 0))
1193+ then invoke(lpFarmingAddress, "airDrop", nil, [AttachedPayment(tokenOutB58, lpFees)])
1194+ else 0
1195+ if ((airdrop == airdrop))
1196+ then [ScriptTransfer(msg.originCaller, dy, tokenOutB58), IntegerEntry((assetIds[outIndex] + kAssetBalance), (xp[outIndex] - dy_and_fee)), Burn(shareAssetId, pmtAmount), ScriptTransfer(moneyBoxAddress, governanceFees, tokenOutB58), IntegerEntry(kShareAssetSupply, (shareSupply - pmtAmount))]
1197+ else throw("Strict value is not equal to itself.")
1198+ }
1199+ else throw("Strict value is not equal to itself.")
1200+ }
1201+ }
1202+ }
1203+ }
1204+ })
1205+
1206+
1207+
1208+@Callable(msg)
1209+func withdrawOneCoinWithUnlock (tokenOut,minAmount,unlockAmount) = valueOrElse(isActive(), if ((0 >= unlockAmount))
1210+ then throw("Unlock amount must be positive")
1211+ else {
1212+ let suspicious = checkSuspicious()
1213+ if (suspicious._1)
1214+ then (suspendSuspicious(suspicious._2) ++ returnPayments(msg.caller, msg.payments))
1215+ else {
1216+ let pmtAmount = if ((size(msg.payments) > 0))
1217+ then if ((size(msg.payments) != 1))
1218+ then throw("size(payments) != 1")
1219+ else {
1220+ let pmtAssetId = msg.payments[0].assetId
1221+ if ((shareAssetId != pmtAssetId))
1222+ then throw("unknown payment token")
1223+ else msg.payments[0].amount
1224+ }
1225+ else 0
1226+ let unlock = invoke(farmingAddress, "withdrawShareTokens", [toString(this), unlockAmount], nil)
1227+ if ((unlock == unlock))
1228+ then {
1229+ let withdrawAmount = (pmtAmount + unlockAmount)
1230+ let inv = invoke(this, "withdrawOneCoin", [tokenOut, minAmount], [AttachedPayment(shareAssetId, withdrawAmount)])
1231+ if ((inv == inv))
1232+ then nil
1233+ else throw("Strict value is not equal to itself.")
1234+ }
1235+ else throw("Strict value is not equal to itself.")
1236+ }
1237+ })
1238+
1239+
1240+
1241+@Callable(msg)
1242+func A () = $Tuple2(nil, _A())
1243+
1244+
1245+
1246+@Callable(msg)
1247+func getVirtualPrice () = {
1248+ let D = get_D(_xp(), _A())
1249+ $Tuple2(nil, fraction(D, PRECISION, shareSupply))
1250+ }
1251+
1252+
1253+
1254+@Callable(msg)
1255+func calcTokenAmount (amounts,deposit) = {
1256+ let amp = _A()
1257+ let balances = _xp()
1258+ let D0 = getDMem(balances, amp)
1259+ func calcNewBalances (acc,balance) = {
1260+ let $t02991829944 = acc
1261+ let newBalances = $t02991829944._1
1262+ let i = $t02991829944._2
1263+ let newBalance = (balance + (if (deposit)
1264+ then amounts[i]
1265+ else -(amounts[i])))
1266+ $Tuple2((newBalances :+ newBalance), (i + 1))
1267+ }
1268+
1269+ let newBalances = ( let $l = balances
1270+ let $s = size($l)
1271+ let $acc0 = $Tuple2(nil, 0)
1272+ func $f0_1 ($a,$i) = if (($i >= $s))
1273+ then $a
1274+ else calcNewBalances($a, $l[$i])
1275+
1276+ func $f0_2 ($a,$i) = if (($i >= $s))
1277+ then $a
1278+ else throw("List size exceeds 10")
1279+
1280+ $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10))._1
1281+ let D1 = getDMem(newBalances, amp)
1282+ let diff = if (deposit)
1283+ then (D1 - D0)
1284+ else (D0 - D1)
1285+ $Tuple2(nil, fraction(diff, shareSupply, D0))
1286+ }
1287+
1288+
1289+
1290+@Callable(msg)
1291+func rampA (_futureA,_futureTime) = valueOrElse(isActive(), valueOrElse(isAdminCall(msg), if (assert((blockTimestamp >= (initial_A_time + MIN_RAMP_TIME))))
1292+ then throw("too often")
1293+ else if (assert((_futureTime >= (blockTimestamp + MIN_RAMP_TIME))))
1294+ then throw("insufficient time")
1295+ else {
1296+ let _initial_A = _A()
1297+ if (assert(if ((_futureA > 0))
1298+ then (MAX_A > _futureA)
1299+ else false))
1300+ then throw("out of base range")
1301+ else if (assert(if (if ((_futureA >= _initial_A))
1302+ then ((_initial_A * MAX_A_CHANGE) >= _futureA)
1303+ else false)
1304+ then true
1305+ else if ((_initial_A > _futureA))
1306+ then ((_futureA * MAX_A_CHANGE) >= _initial_A)
1307+ else false))
1308+ then throw("out of range")
1309+ else [IntegerEntry("initial_A", _initial_A), IntegerEntry("future_A", _futureA), IntegerEntry("initial_A_time", blockTimestamp), IntegerEntry("future_A_time", _futureTime)]
1310+ }))
1311+
1312+
1313+
1314+@Callable(msg)
1315+func stopRampA () = valueOrElse(isActive(), valueOrElse(isAdminCall(msg), {
1316+ let currentA = _A()
1317+[IntegerEntry("initial_A", currentA), IntegerEntry("future_A", currentA), IntegerEntry("initial_A_time", blockTimestamp), IntegerEntry("future_A_time", blockTimestamp)]
1318+ }))
1319+
1320+
1321+
1322+@Callable(msg)
1323+func shutdown () = valueOrElse(isAdminCall(msg), if (!(active))
7421324 then throw(("DApp is already suspended. Cause: " + valueOrElse(getString(this, kCause), "the cause wasn't specified")))
7431325 else suspend("Paused by admin"))
7441326
7451327
7461328
747-@Callable(i)
748-func activate () = valueOrElse(isAdminCall(i), if (active)
749- then throw("DApp is already active")
1329+@Callable(msg)
1330+func activate () = valueOrElse(isAdminCall(msg), if (active)
1331+ then throwIsActive()
7501332 else [BooleanEntry(kActive, true), DeleteEntry(kCause)])
7511333
7521334
1335+
1336+@Callable(msg)
1337+func takeIntoAccountExtraFunds () = valueOrElse(isActive(), if ((msg.caller != moneyBoxAddress))
1338+ then throw("Only the wallet can call this function")
1339+ else {
1340+ let balances = _xp()
1341+ func takeExtraFunds (acc,assetId) = {
1342+ let $t03228632304 = acc
1343+ let sum = $t03228632304._1
1344+ let i = $t03228632304._2
1345+ let tokenB58 = fromBase58String(assetId)
1346+ let rBalance = (assetBalance(this, tokenB58) + stakedAmount(tokenB58))
1347+ let enrollAmount = (rBalance - balances[i])
1348+ if ((0 > enrollAmount))
1349+ then suspend(("Enroll amount negative for asset" + assetId))
1350+ else {
1351+ let airdrop = if ((enrollAmount > 0))
1352+ then invoke(lpFarmingAddress, "airDrop", nil, [AttachedPayment(tokenB58, enrollAmount)])
1353+ else 0
1354+ if ((airdrop == airdrop))
1355+ then $Tuple2((sum + enrollAmount), (i + 1))
1356+ else throw("Strict value is not equal to itself.")
1357+ }
1358+ }
1359+
1360+ let k = {
1361+ let $l = assetIds
1362+ let $s = size($l)
1363+ let $acc0 = $Tuple2(0, 0)
1364+ func $f0_1 ($a,$i) = if (($i >= $s))
1365+ then $a
1366+ else takeExtraFunds($a, $l[$i])
1367+
1368+ func $f0_2 ($a,$i) = if (($i >= $s))
1369+ then $a
1370+ else throw("List size exceeds 10")
1371+
1372+ $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
1373+ }
1374+ if ((k._1 == 0))
1375+ then throw("No money to take")
1376+ else nil
1377+ })
1378+
1379+
7531380 @Verifier(tx)
754-func verify () = match tx {
755- case _ =>
1381+func verify () = {
1382+ let multiSignedByAdmins = {
7561383 let adminPubKey1Signed = if (sigVerify(tx.bodyBytes, tx.proofs[0], adminPubKey1))
7571384 then 1
7581385 else 0
7631390 then 1
7641391 else 0
7651392 (((adminPubKey1Signed + adminPubKey2Signed) + adminPubKey3Signed) >= 2)
766-}
1393+ }
1394+ match tx {
1395+ case inv: InvokeScriptTransaction =>
1396+ let callTakeIntoAccount = if ((inv.dApp == this))
1397+ then (inv.function == "takeIntoAccountExtraFunds")
1398+ else false
1399+ let signedByAdmin = if (if (if (sigVerify(tx.bodyBytes, tx.proofs[0], adminPubKey1))
1400+ then true
1401+ else sigVerify(tx.bodyBytes, tx.proofs[0], adminPubKey2))
1402+ then true
1403+ else sigVerify(tx.bodyBytes, tx.proofs[0], adminPubKey3))
1404+ then true
1405+ else sigVerify(tx.bodyBytes, tx.proofs[0], adminPubKeyInvoke)
1406+ if (if (callTakeIntoAccount)
1407+ then signedByAdmin
1408+ else false)
1409+ then true
1410+ else multiSignedByAdmins
1411+ case _ =>
1412+ multiSignedByAdmins
1413+ }
1414+ }
7671415
Full:
OldNewDifferences
11 {-# STDLIB_VERSION 6 #-}
22 {-# SCRIPT_TYPE ACCOUNT #-}
33 {-# CONTENT_TYPE DAPP #-}
4+let PRECISION = 1000000
5+
6+let MAX_A = 1000000
7+
8+let MAX_A_CHANGE = 10
9+
10+let DECIMALS = 6
11+
12+let MIN_RAMP_TIME = (86400 / 60)
13+
14+let version = "3.0.0"
15+
16+let kVersion = "version"
17+
18+let kAssets = "asset_ids"
19+
20+let kAssetBalance = "_balance"
21+
422 let kActive = "active"
5-
6-let kActiveGlob = "active_all_contracts"
723
824 let kCause = "shutdown_cause"
925
10-let kRewardPoolFractionCurrent = "_current_pool_fraction_reward"
26+let kShareAssetId = "share_asset_id"
1127
12-let kRewardPoolFractionPrevious = "_previous_pool_fraction_reward"
28+let kShareAssetSupply = "share_asset_supply"
1329
14-let kHeightPoolFraction = "_pool_reward_update_height"
30+let kFee = "commission"
1531
16-let kTotalRewardPerBlockCurrent = "total_reward_per_block_current"
32+let kDAppThresholdCoef = "dAppThresholdCoef"
1733
18-let kTotalRewardPerBlockPrevious = "total_reward_per_block_previous"
34+let kUSDNAddress = "staking_usdnnsbt_address"
1935
20-let kRewardUpdateHeight = "reward_update_height"
36+let kDiscounts = "discounts"
2137
22-let kUserShareTokensStaked = "_share_tokens_locked"
38+let kDiscountValues = "discount_values"
2339
24-let kUserShareTokensLocked = "_share_tokens_blocked"
40+let kUserSwopInGov = "_SWOP_amount"
2541
26-let kUserShareTokensLockedType = "_share_tokens_blocked_type"
27-
28-let kUserShareTokensLockedHeight = "_share_tokens_blocked_height"
29-
30-let kUserShareTokensVirtual = "_share_tokens_virtual"
31-
32-let kShareTotalShareTokens = "_total_share_tokens_locked"
33-
34-let kShareTokensVirtual = "_total_share_tokens_virtual"
35-
36-let kLockParams = "_lock_params"
37-
38-let kLockWavesFee = "lock_waves_fee"
39-
40-let kPoolBoostCoef = "_boost_coef"
41-
42-let kFarmLastInterest = "_last_interest"
43-
44-let kFarmUserLastInterest = "_last_interest"
45-
46-let kBoostLastInterest = "_last_interest_b"
47-
48-let kBoostUserLastInterest = "_last_interest_u_b"
49-
50-let kBoostLPLastInterest = "_last_interest_lpb"
51-
52-let kBoostLPUserLastInterest = "_last_interest_u_lpb"
53-
54-let kLastInterestHeight = "_last_interest_height"
55-
56-let kSWOPid = "SWOP_id"
57-
58-let kAvailableSWOP = "_available_SWOP"
59-
60-let kSwopYearEmission = "swop_year_emission"
61-
62-let kHarvestPoolVote = "_harvest_pool_vote_gSWOP"
63-
64-let kPoolVote = "_pool_vote_gSWOP"
65-
66-let kUserPoolVote = "_user_vote_gSWOP"
67-
68-let kHarvestUserPoolVote = "_harvest_user_pool_vote_gSWOP"
69-
70-let kBasePeriod = "base_period"
71-
72-let kPeriodLength = "period_length"
73-
74-let kStartHeight = "start_height"
75-
76-let kFirstHarvestHeight = "first_harvest_height"
77-
78-let kShareLimitFH = "share_limit_on_first_harvest"
42+let kUserGSwopInGov = "_GSwop_amount"
7943
8044 let kAdminPubKey1 = "admin_pub_1"
8145
8246 let kAdminPubKey2 = "admin_pub_2"
8347
8448 let kAdminPubKey3 = "admin_pub_3"
8549
8650 let kAdminInvokePubKey = "admin_invoke_pub"
8751
8852 let kMoneyBoxAddress = "money_box_address"
8953
54+let kGovAddress = "governance_address"
55+
9056 let kVotingAddress = "voting_address"
9157
92-let kGovAddress = "governance_address"
58+let kFarmingAddress = "farming_address"
9359
9460 let kLPFarmingAddress = "lp_farming"
9561
96-let kFarmingTreasureAddr = "farming_treasure"
97-
9862 let oracle = Address(base58'3MvVBtsXroQpy1tsPw21TU2ET9A8WfmrNjz')
99-
100-let totalVoteShare = 10000000000
101-
102-let scaleValue8 = 100000000
103-
104-let lockBoostCoefScale = 1000
105-
106-let defPoolBoostCoef = 500
10763
10864 func getBase58FromOracle (key) = match getString(oracle, key) {
10965 case string: String =>
11066 fromBase58String(string)
11167 case nothing =>
11268 throw((key + "is empty"))
11369 }
11470
11571
11672 let adminPubKey1 = getBase58FromOracle(kAdminPubKey1)
11773
11874 let adminPubKey2 = getBase58FromOracle(kAdminPubKey2)
11975
12076 let adminPubKey3 = getBase58FromOracle(kAdminPubKey3)
12177
78+let adminPubKeyInvoke = getBase58FromOracle(kAdminInvokePubKey)
79+
12280 let moneyBoxAddress = Address(getBase58FromOracle(kMoneyBoxAddress))
81+
82+let govAddress = Address(getBase58FromOracle(kGovAddress))
83+
84+let stakingUSDNAddress = Address(getBase58FromOracle(kUSDNAddress))
12385
12486 let votingAddress = Address(getBase58FromOracle(kVotingAddress))
12587
126-let govAddress = Address(getBase58FromOracle(kGovAddress))
127-
128-let adminInvokePubKey = getBase58FromOracle(kAdminInvokePubKey)
88+let farmingAddress = Address(getBase58FromOracle(kFarmingAddress))
12989
13090 let lpFarmingAddress = Address(getBase58FromOracle(kLPFarmingAddress))
13191
132-let farmingTreasureAddr = Address(getBase58FromOracle(kFarmingTreasureAddr))
92+let USDN = base58'DG2xFkPdDwKUoBkzGAhQtLpSGzfXLiCYPEzeKH2Ad24p'
13393
134-let basePeriod = valueOrErrorMessage(getInteger(votingAddress, kBasePeriod), "Empty kBasePeriod")
135-
136-let startHeight = valueOrErrorMessage(getInteger(votingAddress, kStartHeight), "Empty kStartHeight")
137-
138-let periodLength = valueOrErrorMessage(getInteger(votingAddress, kPeriodLength), "Empty kPeriodLength")
139-
140-let currPeriod = (basePeriod + ((height - startHeight) / periodLength))
94+let stakingAssets = [toBase58String(USDN)]
14195
14296 let active = getBooleanValue(this, kActive)
14397
144-let activeGlob = valueOrElse(getBoolean(oracle, kActiveGlob), true)
98+let shareAssetId = fromBase58String(getStringValue(this, kShareAssetId))
14599
146-let SwopYearEmission = getIntegerValue(this, kSwopYearEmission)
100+let shareSupply = getIntegerValue(this, kShareAssetSupply)
147101
148-let SWOP = fromBase58String(getStringValue(this, kSWOPid))
102+let feeScale6 = 1000000
149103
150-func getHeightFirstHarvest (pool) = valueOrElse(getInteger(Address(fromBase58String(pool)), kFirstHarvestHeight), 0)
104+let fee = getIntegerValue(this, kFee)
151105
106+let feeGovernance = fraction(40, feeScale6, 100)
152107
153-func getFHShareLimitToken (pool) = valueOrErrorMessage(getInteger(pool, kShareLimitFH), ("No data on the key: " + kShareLimitFH))
108+let initial_A = getIntegerValue(this, "initial_A")
154109
110+let future_A = getIntegerValue(this, "future_A")
155111
156-func getTotalShareToken (pool) = valueOrErrorMessage(getInteger(this, (pool + kShareTotalShareTokens)), (("No data on the key: " + pool) + kShareTotalShareTokens))
112+let initial_A_time = valueOrElse(getInteger(this, "initial_A_time"), 0)
157113
114+let future_A_time = valueOrElse(getInteger(this, "future_A_time"), 0)
158115
159-func getPoolVoted (pool) = valueOrElse(getInteger(votingAddress, (pool + kPoolVote)), 0)
116+let assetIds = split(getStringValue(this, kAssets), ",")
160117
161-
162-func getUserPoolVoted (pool,user) = valueOrElse(getInteger(votingAddress, (((user + "_") + pool) + kPoolVote)), 0)
163-
164-
165-func getShareAssetId (pool) = fromBase58String(getStringValue(value(addressFromString(pool)), "share_asset_id"))
166-
167-
168-func accountBalance (assetId) = match assetId {
169- case id: ByteVector =>
170- assetBalance(this, id)
171- case waves: Unit =>
172- wavesBalance(this).available
173- case _ =>
174- throw("Match error")
175-}
176-
177-
178-func getAssetInfo (assetId) = match assetId {
179- case id: ByteVector =>
180- let stringId = toBase58String(id)
181- let info = valueOrErrorMessage(assetInfo(id), (("Asset " + stringId) + " doesn't exist"))
182- $Tuple3(stringId, info.name, info.decimals)
183- case waves: Unit =>
184- $Tuple3("WAVES", "WAVES", 8)
185- case _ =>
186- throw("Match error")
187-}
188-
189-
190-func calcScaleValue (assetId1,assetId2) = {
191- let assetId1Decimals = value(assetInfo(assetId1)).decimals
192- let assetId2Decimals = value(assetInfo(assetId2)).decimals
193- let scaleDigits = ((assetId2Decimals - assetId1Decimals) + 8)
194- pow(10, 0, scaleDigits, 0, 0, DOWN)
195- }
196-
197-
198-func userAvailableSWOP (pool,user) = valueOrElse(getInteger(this, (((pool + "_") + toString(user)) + kAvailableSWOP)), 0)
199-
200-
201-func rewardInfo (pool) = {
202- let totalRewardPerBlockCurrent = valueOrErrorMessage(getInteger(govAddress, kTotalRewardPerBlockCurrent), ((("No data on the key: " + kTotalRewardPerBlockCurrent) + " at address ") + toString(govAddress)))
203- let totalRewardPerBlockPrevious = valueOrErrorMessage(getInteger(govAddress, kTotalRewardPerBlockPrevious), ((("No data on the key: " + kTotalRewardPerBlockPrevious) + " at address ") + toString(govAddress)))
204- let rewardPoolFractionCurrent = valueOrErrorMessage(getInteger(govAddress, (pool + kRewardPoolFractionCurrent)), (((("No data on the key: " + pool) + kRewardPoolFractionCurrent) + " at address ") + toString(govAddress)))
205- let rewardUpdateHeight = valueOrErrorMessage(getInteger(govAddress, kRewardUpdateHeight), ((("No data on the key: " + kRewardUpdateHeight) + " at address ") + toString(govAddress)))
206- let poolRewardUpdateHeight = valueOrElse(getInteger(govAddress, (pool + kHeightPoolFraction)), rewardUpdateHeight)
207- let rewardPoolFractionPrevious = valueOrErrorMessage(getInteger(govAddress, (pool + kRewardPoolFractionPrevious)), (((("No data on the key: " + pool) + kRewardPoolFractionPrevious) + " at address ") + toString(govAddress)))
208- let rewardPoolCurrent = fraction(totalRewardPerBlockCurrent, rewardPoolFractionCurrent, totalVoteShare)
209- let rewardPoolPrevious = fraction(totalRewardPerBlockCurrent, rewardPoolFractionPrevious, totalVoteShare)
210- if (if ((rewardPoolCurrent > totalRewardPerBlockCurrent))
211- then true
212- else (rewardPoolPrevious > totalRewardPerBlockPrevious))
213- then throw("rewardPoolCurrent > totalRewardPerBlockCurrent or rewardPoolPrevious > totalRewardPerBlockPrevious")
214- else $Tuple4(rewardPoolCurrent, rewardUpdateHeight, rewardPoolPrevious, poolRewardUpdateHeight)
215- }
216-
217-
218-func getLastInterestInfo (pool) = {
219- let farmInterest = valueOrErrorMessage(getInteger(this, (pool + kFarmLastInterest)), (("No data on the key: " + pool) + kFarmLastInterest))
220- let boostInterest = valueOrErrorMessage(getInteger(this, (pool + kFarmLastInterest)), (("No data on the key: " + pool) + kBoostLastInterest))
221- let boostLPInterest = valueOrErrorMessage(getInteger(this, (pool + kFarmLastInterest)), (("No data on the key: " + pool) + kBoostLPLastInterest))
222- let lastInterestHeight = valueOrElse(getInteger(this, (pool + kLastInterestHeight)), height)
223- $Tuple4(lastInterestHeight, farmInterest, boostInterest, boostLPInterest)
224- }
225-
226-
227-func calcFarmRwd (pool,curTotalReward) = {
228- let poolBoostCoef = valueOrElse(getInteger(this, (pool + kPoolBoostCoef)), defPoolBoostCoef)
229- ((curTotalReward / (poolBoostCoef + 1000)) / lockBoostCoefScale)
230- }
231-
232-
233-func calcBoostRwd (pool,curTotalReward) = {
234- let poolBoostCoef = valueOrElse(getInteger(this, (pool + kPoolBoostCoef)), defPoolBoostCoef)
235- (fraction(curTotalReward, poolBoostCoef, (poolBoostCoef + 1000)) / lockBoostCoefScale)
236- }
237-
238-
239-func calcInterest (pool,lastInterestHeight,rewardUpdateHeight,poolRewardUpdateHeight,farmInterest,boostInterest,poolVoted,boostLpInterest,currentRewardPerBlock,shareTokenLocked,previousRewardPerBlock,scaleValue) = if ((shareTokenLocked == 0))
240- then $Tuple3(0, 0, 0)
241- else if (if ((rewardUpdateHeight > height))
242- then (rewardUpdateHeight == poolRewardUpdateHeight)
243- else false)
244- then {
245- let reward = (previousRewardPerBlock * (height - lastInterestHeight))
246- let newFarmInterest = (farmInterest + fraction(calcFarmRwd(pool, reward), scaleValue, shareTokenLocked))
247- let newBoostInterest = (boostInterest + (if ((poolVoted > 0))
248- then fraction(calcBoostRwd(pool, reward), scaleValue8, poolVoted)
249- else 0))
250- let newBoostLPInterest = (boostLpInterest + (if (if ((poolVoted > 0))
251- then (shareTokenLocked > 0)
252- else false)
253- then fraction(fraction(calcBoostRwd(pool, reward), scaleValue8, shareTokenLocked), scaleValue8, poolVoted)
254- else 0))
255- $Tuple3(newFarmInterest, newBoostInterest, newBoostLPInterest)
256- }
257- else if (if ((height > rewardUpdateHeight))
258- then (rewardUpdateHeight != poolRewardUpdateHeight)
259- else false)
260- then {
261- let reward = (previousRewardPerBlock * (height - lastInterestHeight))
262- let newFarmInterest = (farmInterest + fraction(calcFarmRwd(pool, reward), scaleValue, shareTokenLocked))
263- let newBoostInterest = (boostInterest + (if ((poolVoted > 0))
264- then fraction(calcBoostRwd(pool, reward), scaleValue8, poolVoted)
265- else 0))
266- let newBoostLPInterest = (boostLpInterest + (if (if ((poolVoted > 0))
267- then (shareTokenLocked > 0)
268- else false)
269- then fraction(fraction(calcBoostRwd(pool, reward), scaleValue8, shareTokenLocked), scaleValue8, poolVoted)
270- else 0))
271- $Tuple3(newFarmInterest, newBoostInterest, newBoostLPInterest)
272- }
273- else if (if (if ((height > rewardUpdateHeight))
274- then (rewardUpdateHeight == poolRewardUpdateHeight)
275- else false)
276- then (lastInterestHeight > rewardUpdateHeight)
277- else false)
278- then {
279- let reward = (currentRewardPerBlock * (height - lastInterestHeight))
280- let newFarmInterest = (farmInterest + fraction(calcFarmRwd(pool, reward), scaleValue, shareTokenLocked))
281- let newBoostInterest = (boostInterest + (if ((poolVoted > 0))
282- then fraction(calcBoostRwd(pool, reward), scaleValue8, poolVoted)
283- else 0))
284- let newBoostLPInterest = (boostLpInterest + (if (if ((poolVoted > 0))
285- then (shareTokenLocked > 0)
286- else false)
287- then fraction(fraction(calcBoostRwd(pool, reward), scaleValue8, shareTokenLocked), scaleValue8, poolVoted)
288- else 0))
289- $Tuple3(newFarmInterest, newBoostInterest, newBoostLPInterest)
290- }
291- else {
292- let rwdBfrUpd = (previousRewardPerBlock * (rewardUpdateHeight - lastInterestHeight))
293- let framIntrAftrUp = (farmInterest + fraction(calcFarmRwd(pool, rwdBfrUpd), scaleValue, shareTokenLocked))
294- let boostIntrAftrUp = (boostInterest + (if ((poolVoted > 0))
295- then fraction(calcBoostRwd(pool, rwdBfrUpd), scaleValue, poolVoted)
296- else 0))
297- let bostLPIntrAftrUp = (farmInterest + (if (if ((poolVoted > 0))
298- then (shareTokenLocked > 0)
299- else false)
300- then fraction(calcBoostRwd(pool, rwdBfrUpd), scaleValue, poolVoted)
301- else 0))
302- let reward = (currentRewardPerBlock * (height - rewardUpdateHeight))
303- let newFarmInterest = (framIntrAftrUp + fraction(calcFarmRwd(pool, reward), scaleValue, shareTokenLocked))
304- let newBoostInterest = (boostIntrAftrUp + (if ((poolVoted > 0))
305- then fraction(calcBoostRwd(pool, reward), scaleValue8, poolVoted)
306- else 0))
307- let newBoostLPInterest = (bostLPIntrAftrUp + (if (if ((poolVoted > 0))
308- then (shareTokenLocked > 0)
309- else false)
310- then fraction(fraction(calcBoostRwd(pool, reward), scaleValue8, shareTokenLocked), scaleValue8, poolVoted)
311- else 0))
312- $Tuple3(newFarmInterest, newBoostInterest, newBoostLPInterest)
313- }
314-
315-
316-func claimCalc (pool,user) = {
317- let scaleValue = calcScaleValue(SWOP, getShareAssetId(pool))
318- let poolVoted = getPoolVoted(pool)
319- let uPoolVoted = getUserPoolVoted(pool, user)
320- let shareToken = getTotalShareToken(pool)
321- let totalShareVirtual = valueOrElse(getInteger(this, (pool + kShareTokensVirtual)), shareToken)
322- let $t01440614504 = getLastInterestInfo(pool)
323- let lastInterestHeight = $t01440614504._1
324- let farmInterest = $t01440614504._2
325- let boostInterest = $t01440614504._3
326- let boostLPInterest = $t01440614504._4
327- let $t01450914623 = rewardInfo(pool)
328- let currentRewardPerBlock = $t01450914623._1
329- let rewardUpdateHeight = $t01450914623._2
330- let previousRewardPerBlock = $t01450914623._3
331- let poolRewardUpdateHeight = $t01450914623._4
332- let uFarmInterest = valueOrElse(getInteger(this, (((pool + "_") + user) + kFarmUserLastInterest)), farmInterest)
333- let uBoostInterest = valueOrElse(getInteger(this, (((pool + "_") + user) + kBoostUserLastInterest)), boostInterest)
334- let uBoostLPInterest = valueOrElse(getInteger(this, (((pool + "_") + user) + kBoostLPUserLastInterest)), boostLPInterest)
335- let uShareTokensStaked = valueOrElse(getInteger(this, (((pool + "_") + user) + kUserShareTokensStaked)), 0)
336- let uShareTokensVirt = valueOrElse(getInteger(this, (((pool + "_") + user) + kUserShareTokensVirtual)), uShareTokensStaked)
337- let $t01519115584 = calcInterest(pool, lastInterestHeight, rewardUpdateHeight, poolRewardUpdateHeight, farmInterest, boostInterest, poolVoted, boostLPInterest, currentRewardPerBlock, totalShareVirtual, previousRewardPerBlock, scaleValue)
338- let newFarmInterest = $t01519115584._1
339- let newBoostInterest = $t01519115584._2
340- let newBoostLPInterest = $t01519115584._3
341- let claimFarming = fraction(uShareTokensVirt, (newFarmInterest - uFarmInterest), scaleValue)
342- let claimBoostingMax = fraction(uPoolVoted, (newBoostInterest - uBoostInterest), scaleValue8)
343- let claimBoosting = (fraction((uShareTokensVirt * uPoolVoted), (newBoostLPInterest - uBoostLPInterest), scaleValue8) / scaleValue8)
344- let toTreasury = (claimBoostingMax - claimBoosting)
345- $Tuple5(newFarmInterest, newBoostInterest, newBoostLPInterest, (claimFarming + claimBoosting), toTreasury)
346- }
347-
348-
349-func canLockInFirstHarvest (pool,user,userShareTokensStaked,pmtAmount,lockType) = if ((getHeightFirstHarvest(pool) > height))
350- then {
351- let totalVoteAmount = valueOrElse(getInteger(votingAddress, (pool + kHarvestPoolVote)), 0)
352- let userVoteAmount = valueOrElse(getInteger(votingAddress, (((user + "_") + pool) + kHarvestPoolVote)), 0)
353- let FHShareTokenLimit = getFHShareLimitToken(addressFromStringValue(pool))
354- let FHShareTokenUserLimit = (fraction(FHShareTokenLimit, userVoteAmount, totalVoteAmount) - userShareTokensStaked)
355- if ((lockType > 0))
356- then throw("You can't lock shareTokens till first harvest end.")
357- else if ((userVoteAmount == 0))
358- then 0
359- else if ((pmtAmount >= FHShareTokenUserLimit))
360- then (pmtAmount - FHShareTokenUserLimit)
361- else 0
362- }
363- else 0
364-
365-
366-func getLockParams (type) = {
367- let lockParams = split(valueOrErrorMessage(getString(this, (toString(type) + kLockParams)), ("There are no key for lock type" + toString(type))), "_")
368- $Tuple2(parseIntValue(lockParams[0]), parseIntValue(lockParams[1]))
369- }
370-
118+let nCoins = size(assetIds)
371119
372120 func suspend (cause) = [BooleanEntry(kActive, false), StringEntry(kCause, cause)]
373121
374122
375-func isActive () = if (if (active)
376- then activeGlob
377- else false)
123+func throwIsActive () = throw("DApp is already active")
124+
125+
126+func isActive () = if (active)
378127 then unit
379128 else throw("DApp is inactive at this moment")
380129
381130
382131 func isAdminCall (i) = if (containsElement([adminPubKey1, adminPubKey2, adminPubKey3], i.callerPublicKey))
383132 then unit
384133 else throw("Only admin can call this function")
385134
386135
387-@Callable(i)
388-func init (earlyLP) = if (isDefined(getString(this, kSWOPid)))
389- then throw("SWOP already initialized")
136+func isSelfCall (i) = if ((this == i.caller))
137+ then unit
138+ else throw("Only contract itself can call this function")
139+
140+
141+let big2 = toBigInt(2)
142+
143+let iter10 = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
144+
145+let iter15 = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
146+
147+let iter16 = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
148+
149+let blockTimestamp = height
150+
151+func assert (a) = if (a)
152+ then false
153+ else true
154+
155+
156+func calculateFeeDiscount (userAddr) = {
157+ let user = match userAddr {
158+ case u: Address =>
159+ toString(u)
160+ case u: String =>
161+ u
162+ case _ =>
163+ throw("Unknow type of user Addr")
164+ }
165+ let swopAmount = valueOrElse(getInteger(govAddress, (user + kUserGSwopInGov)), 0)
166+ let gSwopAmount = valueOrElse(getInteger(govAddress, (user + kUserGSwopInGov)), swopAmount)
167+ let discountValues = split(getStringValue(oracle, kDiscountValues), ",")
168+ let discounts = split(getStringValue(oracle, kDiscounts), ",")
169+ if (if ((gSwopAmount >= parseIntValue(discountValues[0])))
170+ then (parseIntValue(discountValues[1]) > gSwopAmount)
171+ else false)
172+ then (feeScale6 - parseIntValue(discounts[0]))
173+ else if (if ((gSwopAmount >= parseIntValue(discountValues[1])))
174+ then (parseIntValue(discountValues[2]) > gSwopAmount)
175+ else false)
176+ then (feeScale6 - parseIntValue(discounts[1]))
177+ else if (if ((gSwopAmount >= parseIntValue(discountValues[2])))
178+ then (parseIntValue(discountValues[3]) > gSwopAmount)
179+ else false)
180+ then (feeScale6 - parseIntValue(discounts[2]))
181+ else if (if ((gSwopAmount >= parseIntValue(discountValues[3])))
182+ then (parseIntValue(discountValues[4]) > gSwopAmount)
183+ else false)
184+ then (feeScale6 - parseIntValue(discounts[3]))
185+ else if ((gSwopAmount >= parseIntValue(discountValues[4])))
186+ then (feeScale6 - parseIntValue(discounts[4]))
187+ else feeScale6
188+ }
189+
190+
191+func _A () = {
192+ let t1 = future_A_time
193+ let A1 = future_A
194+ if ((t1 > blockTimestamp))
195+ then {
196+ let A0 = initial_A
197+ let t0 = initial_A_time
198+ if ((A1 > A0))
199+ then (A0 + (((A1 - A0) * (blockTimestamp - t0)) / (t1 - t0)))
200+ else (A0 - (((A0 - A1) * (blockTimestamp - t0)) / (t1 - t0)))
201+ }
202+ else A1
203+ }
204+
205+
206+func _xp () = {
207+ func assetBalances (acc,assetId) = (acc :+ valueOrElse(getInteger(this, (assetId + kAssetBalance)), 0))
208+
209+ let $l = assetIds
210+ let $s = size($l)
211+ let $acc0 = nil
212+ func $f0_1 ($a,$i) = if (($i >= $s))
213+ then $a
214+ else assetBalances($a, $l[$i])
215+
216+ func $f0_2 ($a,$i) = if (($i >= $s))
217+ then $a
218+ else throw("List size exceeds 10")
219+
220+ $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
221+ }
222+
223+
224+func _xp_mem (xp) = xp
225+
226+
227+func sumList (acc,element) = (acc + element)
228+
229+
230+func get_D (xp,amp) = {
231+ let @ = invoke(this, "D", [xp, amp], nil)
232+ if ($isInstanceOf(@, "Int"))
233+ then @
234+ else throw(($getType(@) + " couldn't be cast to Int"))
235+ }
236+
237+
238+func get_D_internal (xp,amp) = {
239+ let S = {
240+ let $l = xp
241+ let $s = size($l)
242+ let $acc0 = 0
243+ func $f0_1 ($a,$i) = if (($i >= $s))
244+ then $a
245+ else sumList($a, $l[$i])
246+
247+ func $f0_2 ($a,$i) = if (($i >= $s))
248+ then $a
249+ else throw("List size exceeds 10")
250+
251+ $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
252+ }
253+ if ((S == 0))
254+ then 0
255+ else {
256+ let Ann = (amp * nCoins)
257+ let AnnS = (toBigInt(Ann) * toBigInt(S))
258+ let Ann1 = toBigInt((Ann - 1))
259+ func Dproc (acc,i) = if ((acc._2 == true))
260+ then acc
261+ else {
262+ let Dprev = acc._1
263+ func D_PProc (D_P,i) = if ((nCoins > i))
264+ then ((D_P * Dprev) / (toBigInt(xp[i]) * toBigInt(nCoins)))
265+ else D_P
266+
267+ let D_P = {
268+ let $l = iter10
269+ let $s = size($l)
270+ let $acc0 = Dprev
271+ func $f1_1 ($a,$i) = if (($i >= $s))
272+ then $a
273+ else D_PProc($a, $l[$i])
274+
275+ func $f1_2 ($a,$i) = if (($i >= $s))
276+ then $a
277+ else throw("List size exceeds 10")
278+
279+ $f1_2($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
280+ }
281+ let D = fraction((AnnS + (toBigInt(nCoins) * D_P)), Dprev, ((Ann1 * Dprev) + (toBigInt((nCoins + 1)) * D_P)))
282+ if ((D > Dprev))
283+ then if ((1 >= toInt((D - Dprev))))
284+ then $Tuple2(D, true)
285+ else $Tuple2(D, false)
286+ else if ((1 >= toInt((Dprev - D))))
287+ then $Tuple2(D, true)
288+ else $Tuple2(D, false)
289+ }
290+
291+ let $t064616527 = {
292+ let $l = iter15
293+ let $s = size($l)
294+ let $acc0 = $Tuple2(toBigInt(S), false)
295+ func $f1_1 ($a,$i) = if (($i >= $s))
296+ then $a
297+ else Dproc($a, $l[$i])
298+
299+ func $f1_2 ($a,$i) = if (($i >= $s))
300+ then $a
301+ else throw("List size exceeds 15")
302+
303+ $f1_2($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10), 11), 12), 13), 14), 15)
304+ }
305+ let D = $t064616527._1
306+ let finished = $t064616527._2
307+ if ((finished == false))
308+ then throw(("get_D() not finished with " + toString(D)))
309+ else toInt(D)
310+ }
311+ }
312+
313+
314+func getDMem (xp,amp) = get_D(_xp_mem(xp), amp)
315+
316+
317+func getY (in,out,x,xp_) = if (assert((in != out)))
318+ then throw("same coin")
319+ else if (assert(if ((out >= 0))
320+ then (in >= 0)
321+ else false))
322+ then throw("below zero")
323+ else if (assert(if ((nCoins > out))
324+ then (nCoins > in)
325+ else false))
326+ then throw("above N_COINS")
327+ else {
328+ let amp = _A()
329+ let D = get_D(xp_, amp)
330+ let Ann = (amp * nCoins)
331+ func S_c (acc,i) = {
332+ let $t070987115 = acc
333+ let S_ = $t070987115._1
334+ let c = $t070987115._2
335+ let x_ = if ((in == i))
336+ then x
337+ else xp_[i]
338+ if (if ((i != out))
339+ then (nCoins > i)
340+ else false)
341+ then $Tuple2((S_ + x_), fraction(c, toBigInt(D), toBigInt((x_ * nCoins))))
342+ else $Tuple2(S_, c)
343+ }
344+
345+ let $t073237378 = {
346+ let $l = iter10
347+ let $s = size($l)
348+ let $acc0 = $Tuple2(0, toBigInt(D))
349+ func $f0_1 ($a,$i) = if (($i >= $s))
350+ then $a
351+ else S_c($a, $l[$i])
352+
353+ func $f0_2 ($a,$i) = if (($i >= $s))
354+ then $a
355+ else throw("List size exceeds 10")
356+
357+ $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
358+ }
359+ let S_ = $t073237378._1
360+ let c_ = $t073237378._2
361+ let c = fraction(c_, toBigInt(D), toBigInt((Ann * nCoins)))
362+ let bD = toBigInt(((S_ + (D / Ann)) - D))
363+ func y_proc (acc,_i) = if ((acc._2 == true))
364+ then acc
365+ else {
366+ let y_prev = acc._1
367+ let y = (((y_prev * y_prev) + c) / ((big2 * y_prev) + bD))
368+ if ((y > y_prev))
369+ then if ((1 >= toInt((y - y_prev))))
370+ then $Tuple2(y, true)
371+ else $Tuple2(y, false)
372+ else if ((1 >= toInt((y_prev - y))))
373+ then $Tuple2(y, true)
374+ else $Tuple2(y, false)
375+ }
376+
377+ let $t078607927 = {
378+ let $l = iter16
379+ let $s = size($l)
380+ let $acc0 = $Tuple2(toBigInt(D), false)
381+ func $f1_1 ($a,$i) = if (($i >= $s))
382+ then $a
383+ else y_proc($a, $l[$i])
384+
385+ func $f1_2 ($a,$i) = if (($i >= $s))
386+ then $a
387+ else throw("List size exceeds 16")
388+
389+ $f1_2($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10), 11), 12), 13), 14), 15), 16)
390+ }
391+ let y = $t078607927._1
392+ let finished = $t078607927._2
393+ if ((finished == false))
394+ then throw(("getY() not finished with " + toString(y)))
395+ else toInt(y)
396+ }
397+
398+
399+func get_y_D (A_,in,xp,D) = if (assert((in >= 0)))
400+ then throw("i below zero")
401+ else if (assert((nCoins > in)))
402+ then throw("i above N_COINS")
403+ else {
404+ let Ann = (A_ * nCoins)
405+ func S_c (acc,i) = {
406+ let $t083068323 = acc
407+ let S_ = $t083068323._1
408+ let c = $t083068323._2
409+ let x_ = if (if ((in != i))
410+ then (nCoins > i)
411+ else false)
412+ then xp[i]
413+ else 0
414+ if (if ((nCoins > i))
415+ then (in != i)
416+ else false)
417+ then $Tuple2((S_ + x_), fraction(c, toBigInt(D), toBigInt((x_ * nCoins))))
418+ else $Tuple2(S_, c)
419+ }
420+
421+ let $t085438598 = {
422+ let $l = iter10
423+ let $s = size($l)
424+ let $acc0 = $Tuple2(0, toBigInt(D))
425+ func $f0_1 ($a,$i) = if (($i >= $s))
426+ then $a
427+ else S_c($a, $l[$i])
428+
429+ func $f0_2 ($a,$i) = if (($i >= $s))
430+ then $a
431+ else throw("List size exceeds 10")
432+
433+ $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
434+ }
435+ let S_ = $t085438598._1
436+ let c_ = $t085438598._2
437+ let c = fraction(c_, toBigInt(D), toBigInt((Ann * nCoins)))
438+ let bD = toBigInt(((S_ + (D / Ann)) - D))
439+ func y_D_proc (acc,i) = if ((acc._2 == true))
440+ then acc
441+ else {
442+ let y_prev = acc._1
443+ let y = (((y_prev * y_prev) + c) / ((big2 * y_prev) + bD))
444+ if ((y > y_prev))
445+ then if ((1 >= toInt((y - y_prev))))
446+ then $Tuple2(y, true)
447+ else $Tuple2(y, false)
448+ else if ((1 >= toInt((y_prev - y))))
449+ then $Tuple2(y, true)
450+ else $Tuple2(y, false)
451+ }
452+
453+ let $t090819150 = {
454+ let $l = iter16
455+ let $s = size($l)
456+ let $acc0 = $Tuple2(toBigInt(D), false)
457+ func $f1_1 ($a,$i) = if (($i >= $s))
458+ then $a
459+ else y_D_proc($a, $l[$i])
460+
461+ func $f1_2 ($a,$i) = if (($i >= $s))
462+ then $a
463+ else throw("List size exceeds 16")
464+
465+ $f1_2($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10), 11), 12), 13), 14), 15), 16)
466+ }
467+ let y = $t090819150._1
468+ let finished = $t090819150._2
469+ if ((finished == false))
470+ then throw(("get_y_D() not finished with " + toString(y)))
471+ else toInt(y)
472+ }
473+
474+
475+func _calcWithdrawOneCoin (xp,_token_amount,i,caller) = {
476+ let feeDiscount = calculateFeeDiscount(caller)
477+ let amp = _A()
478+ let _fee = ((fraction(fee, feeDiscount, feeScale6, CEILING) * nCoins) / (4 * (nCoins - 1)))
479+ let total_supply = shareSupply
480+ let D0 = get_D(xp, amp)
481+ let D1 = (D0 - fraction(_token_amount, D0, total_supply))
482+ let new_y = get_y_D(amp, i, xp, D1)
483+ let dy_0 = (xp[i] - new_y)
484+ func xp_reduced_proc (acc,xp_j) = {
485+ let $t097919820 = acc
486+ let xp_reduced = $t097919820._1
487+ let index = $t097919820._2
488+ let dx_expected = if ((index == i))
489+ then (fraction(xp_j, D1, D0) - new_y)
490+ else (xp_j - fraction(xp_j, D1, D0))
491+ $Tuple2((xp_reduced :+ (xp_j - fraction(_fee, dx_expected, feeScale6))), (index + 1))
492+ }
493+
494+ let $t01008210146 = {
495+ let $l = xp
496+ let $s = size($l)
497+ let $acc0 = $Tuple2(nil, 0)
498+ func $f0_1 ($a,$i) = if (($i >= $s))
499+ then $a
500+ else xp_reduced_proc($a, $l[$i])
501+
502+ func $f0_2 ($a,$i) = if (($i >= $s))
503+ then $a
504+ else throw("List size exceeds 10")
505+
506+ $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
507+ }
508+ let xp_reduced = $t01008210146._1
509+ let index = $t01008210146._2
510+ let xp_reduced_i = xp_reduced[i]
511+ let dy = ((xp_reduced_i - get_y_D(amp, i, xp_reduced, D1)) - 1)
512+ $Tuple2(dy, (dy_0 - dy))
513+ }
514+
515+
516+func getStrAssetId (assetId) = match assetId {
517+ case id: ByteVector =>
518+ toBase58String(id)
519+ case waves: Unit =>
520+ "WAVES"
521+ case _ =>
522+ throw("Match error")
523+}
524+
525+
526+func calcStakingFuncAndAddres (stake,assetId) = if (stake)
527+ then $Tuple2("lockNeutrino", stakingUSDNAddress)
528+ else $Tuple2("unlockNeutrino", stakingUSDNAddress)
529+
530+
531+func calcStakingParams (stake,amount,assetId) = if (stake)
532+ then {
533+ let $t01071010776 = calcStakingFuncAndAddres(stake, assetId)
534+ let call = $t01071010776._1
535+ let stakingAddr = $t01071010776._2
536+ $Tuple4(call, stakingAddr, nil, [AttachedPayment(assetId, amount)])
537+ }
390538 else {
391- let initAmount = 100000000000000
392- let SWOPissue = Issue("SWOP", "SWOP protocol token", initAmount, 8, true)
393- let SWOPid = calculateAssetId(SWOPissue)
394-[BooleanEntry(kActive, true), Issue("SWOP", "SWOP protocol token", initAmount, 8, true), StringEntry(kSWOPid, toBase58String(SWOPid))]
539+ let $t01086210928 = calcStakingFuncAndAddres(stake, assetId)
540+ let call = $t01086210928._1
541+ let stakingAddr = $t01086210928._2
542+ $Tuple4(call, stakingAddr, [amount, toBase58String(assetId)], nil)
395543 }
396544
397545
546+func stake (amount,assetIdString) = if (containsElement(stakingAssets, assetIdString))
547+ then {
548+ let $t01111511217 = calcStakingParams(true, amount, fromBase58String(assetIdString))
549+ let call = $t01111511217._1
550+ let addr = $t01111511217._2
551+ let params = $t01111511217._3
552+ let payments = $t01111511217._4
553+ invoke(addr, call, params, payments)
554+ }
555+ else 0
398556
399-@Callable(i)
400-func initPoolShareFarming (pool) = valueOrElse(isAdminCall(i), [IntegerEntry((pool + kShareTotalShareTokens), 0), IntegerEntry((pool + kFarmLastInterest), 0), IntegerEntry((pool + kBoostLastInterest), 0), IntegerEntry((pool + kBoostLPLastInterest), 0), IntegerEntry((pool + kLastInterestHeight), height)])
557+
558+func unstake (amount,assetIdString) = if (containsElement(stakingAssets, assetIdString))
559+ then {
560+ let $t01140211505 = calcStakingParams(false, amount, fromBase58String(assetIdString))
561+ let call = $t01140211505._1
562+ let addr = $t01140211505._2
563+ let params = $t01140211505._3
564+ let payments = $t01140211505._4
565+ invoke(addr, call, params, payments)
566+ }
567+ else 0
568+
569+
570+func stakedAmount (assetId) = {
571+ let stakedAmountCalculated = match assetId {
572+ case aId: ByteVector =>
573+ if ((aId == USDN))
574+ then getInteger(stakingUSDNAddress, ((("rpd_balance_" + toBase58String(aId)) + "_") + toString(this)))
575+ else 0
576+ case _: Unit =>
577+ 0
578+ case _ =>
579+ throw("Match error")
580+ }
581+ match stakedAmountCalculated {
582+ case i: Int =>
583+ i
584+ case _ =>
585+ 0
586+ }
587+ }
588+
589+
590+func checkSuspicious () = {
591+ let contractBalances = _xp()
592+ func checkBalance (acc,assetId) = {
593+ let $t01211612141 = acc
594+ let suspicious = $t01211612141._1
595+ let i = $t01211612141._2
596+ if (suspicious)
597+ then $Tuple2(suspicious, i)
598+ else {
599+ let aBalance = (assetBalance(this, fromBase58String(assetId)) + stakedAmount(fromBase58String(assetId)))
600+ if ((contractBalances[i] > aBalance))
601+ then $Tuple2(true, i)
602+ else $Tuple2(false, (i + 1))
603+ }
604+ }
605+
606+ let $l = assetIds
607+ let $s = size($l)
608+ let $acc0 = $Tuple2(false, 0)
609+ func $f0_1 ($a,$i) = if (($i >= $s))
610+ then $a
611+ else checkBalance($a, $l[$i])
612+
613+ func $f0_2 ($a,$i) = if (($i >= $s))
614+ then $a
615+ else throw("List size exceeds 10")
616+
617+ $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
618+ }
619+
620+
621+func suspendSuspicious (i) = suspend(("Suspicious state with asset: " + assetIds[i]))
622+
623+
624+func returnPayments (caller,payments) = {
625+ func parsePayments (acc,payment) = (acc :+ ScriptTransfer(caller, payment.amount, payment.assetId))
626+
627+ let $l = payments
628+ let $s = size($l)
629+ let $acc0 = nil
630+ func $f0_1 ($a,$i) = if (($i >= $s))
631+ then $a
632+ else parsePayments($a, $l[$i])
633+
634+ func $f0_2 ($a,$i) = if (($i >= $s))
635+ then $a
636+ else throw("List size exceeds 10")
637+
638+ $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
639+ }
640+
641+
642+func checkDAppThreshold (newBalances) = {
643+ let dAppThresholdCoef = valueOrErrorMessage(getInteger(this, kDAppThresholdCoef), "No dAppThresholdCoef key")
644+ let thresholdScale = 10000
645+ let maxBalance = max(newBalances)
646+ let minBalance = min(newBalances)
647+ let ratio = fraction(maxBalance, thresholdScale, minBalance)
648+ if ((ratio > (dAppThresholdCoef * thresholdScale)))
649+ then throw("New balance in assets of the DApp is less than threshold")
650+ else false
651+ }
652+
653+
654+func checkCoins (assetIds) = {
655+ let coins = split(assetIds, ",")
656+ if ((size(coins) > 10))
657+ then throw("To many coins, max coins size 10")
658+ else {
659+ func checkCoin (error,assetId) = {
660+ let asset = valueOrErrorMessage(fromBase58String(assetId), ("fromBase58String: " + assetId))
661+ let decimals = valueOrErrorMessage(assetInfo(asset), ("assetInfo: " + assetId)).decimals
662+ if ((decimals != DECIMALS))
663+ then throw("wrong decimals")
664+ else false
665+ }
666+
667+ let $l = coins
668+ let $s = size($l)
669+ let $acc0 = false
670+ func $f0_1 ($a,$i) = if (($i >= $s))
671+ then $a
672+ else checkCoin($a, $l[$i])
673+
674+ func $f0_2 ($a,$i) = if (($i >= $s))
675+ then $a
676+ else throw("List size exceeds 10")
677+
678+ $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
679+ }
680+ }
681+
682+
683+@Callable(msg)
684+func D (xp,amp) = {
685+ let D = get_D_internal(xp, amp)
686+ $Tuple2([IntegerEntry("D", D)], D)
687+ }
401688
402689
403690
404-@Callable(i)
405-func updatePoolInterest (pool) = valueOrElse(isActive(), if ((i.caller != govAddress))
406- then throw("Only Governance can call this function")
407- else {
408- let user = toString(addressFromPublicKey(adminInvokePubKey))
409- let $t01861718691 = claimCalc(pool, user)
410- let farmInterest = $t01861718691._1
411- let boostInterest = $t01861718691._2
412- let boostLPinterest = $t01861718691._3
413-[IntegerEntry((pool + kFarmLastInterest), farmInterest), IntegerEntry((pool + kBoostLastInterest), boostInterest), IntegerEntry((pool + kBoostLPLastInterest), boostLPinterest), IntegerEntry((pool + kLastInterestHeight), height)]
414- })
691+@Callable(msg)
692+func init (assetIds,_A,_dAppThresholdCoef) = if (!(isDataStorageUntouched(this)))
693+ then throw("Already initialized")
694+ else if ((0 >= _A))
695+ then throw("Amp must be must > 0")
696+ else if ((0 >= _dAppThresholdCoef))
697+ then throw("dApp Threshold Coef must be > 0")
698+ else {
699+ let shareName = "s_Multi_USD"
700+ let shareDescription = ("ShareToken of SwopFi protocol for MultiStable USD pool at address " + toString(this))
701+ let issueToken = Issue(shareName, shareDescription, 0, 6, true)
702+ let tokenId = calculateAssetId(issueToken)
703+ if (checkCoins(assetIds))
704+ then throw()
705+ else [StringEntry(kVersion, version), StringEntry(kAssets, assetIds), IntegerEntry("initial_A", _A), IntegerEntry("future_A", _A), IntegerEntry(kFee, getIntegerValue(oracle, "base_fee_flat")), StringEntry(kShareAssetId, toBase58String(tokenId)), IntegerEntry(kShareAssetSupply, 0), IntegerEntry(kDAppThresholdCoef, _dAppThresholdCoef), BooleanEntry(kActive, true), issueToken]
706+ }
415707
416708
417709
418-@Callable(i)
419-func lockShareTokens (pool,lockType) = valueOrElse(isActive(), {
420- let shareAssetId = getShareAssetId(pool)
421- let user = toString(i.originCaller)
422- let totalShare = getTotalShareToken(pool)
423- let totalShareVirtual = valueOrElse(getInteger(this, (pool + kShareTokensVirtual)), totalShare)
424- let userStakedAmount = valueOrElse(getInteger(this, (((pool + "_") + user) + kUserShareTokensStaked)), 0)
425- let userLockedHeigt = valueOrElse(getInteger(this, (((pool + "_") + user) + kUserShareTokensLockedHeight)), 0)
426- let userLockedAmount = valueOrElse(getInteger(this, (((pool + "_") + user) + kUserShareTokensLocked)), 0)
427- let userAmountVirtual = valueOrElse(getInteger(this, (((pool + "_") + user) + kUserShareTokensVirtual)), userStakedAmount)
428- let totalUserShareTokens = ((userStakedAmount + userLockedAmount) + i.payments[0].amount)
429- let $t01980019852 = getLockParams(lockType)
430- let lockPeriod = $t01980019852._1
431- let lockCoef = $t01980019852._2
432- let lockWavesFee = getIntegerValue(this, kLockWavesFee)
433- if ((i.payments[0].assetId != shareAssetId))
434- then throw("Wrong sharetoken in payment")
435- else if ((0 >= i.payments[0].amount))
436- then throw("Payment amount must be greater than 0")
437- else if ((0 > lockType))
438- then throw("lockType must be >= 0")
710+@Callable(msg)
711+func addLiquidity (minMintAmount,stakeFarming,lockType) = valueOrElse(isActive(), {
712+ let amp = _A()
713+ let xp = _xp()
714+ let D0 = if ((shareSupply == 0))
715+ then 0
716+ else getDMem(xp, amp)
717+ let $t01534915604 = if (if ((lockType > 0))
718+ then (msg.payments[(size(msg.payments) - 1)].assetId == unit)
719+ else false)
720+ then $Tuple2(removeByIndex(msg.payments, (size(msg.payments) - 1)), [msg.payments[(size(msg.payments) - 1)]])
721+ else $Tuple2(msg.payments, nil)
722+ let payments = $t01534915604._1
723+ let lockFee = $t01534915604._2
724+ let paymentsSize = size(payments)
725+ func validPayments (n) = if ((paymentsSize > nCoins))
726+ then throw(("payments size > " + toString(nCoins)))
727+ else if ((1 > paymentsSize))
728+ then throw("payments size < 1")
729+ else if (if ((shareSupply == 0))
730+ then (nCoins != paymentsSize)
731+ else false)
732+ then throw("initial deposit requires all coins")
439733 else {
440- let shareTokensChangeOnFH = canLockInFirstHarvest(pool, user, userStakedAmount, i.payments[0].amount, lockType)
441- if ((shareTokensChangeOnFH == shareTokensChangeOnFH))
442- then {
443- let $t02027922124 = if ((lockType == 0))
444- then {
445- let userAmountVirtualNew = ((userAmountVirtual + i.payments[0].amount) - shareTokensChangeOnFH)
446- $Tuple2([IntegerEntry((((pool + "_") + user) + kUserShareTokensStaked), ((userStakedAmount + i.payments[0].amount) - shareTokensChangeOnFH)), IntegerEntry((pool + kShareTokensVirtual), ((totalShareVirtual + i.payments[0].amount) - shareTokensChangeOnFH)), ScriptTransfer(i.originCaller, shareTokensChangeOnFH, i.payments[0].assetId)], ((totalShare + i.payments[0].amount) - shareTokensChangeOnFH))
447- }
448- else if (if ((userLockedHeigt == 0))
449- then if (if ((2 > size(i.payments)))
450- then true
451- else (i.payments[1].assetId != unit))
452- then true
453- else (lockWavesFee > i.payments[1].amount)
454- else false)
455- then throw((("You need to pay additional waves comission " + toString(lockWavesFee)) + "WAVES"))
456- else if ((userLockedHeigt > (height + lockPeriod)))
457- then throw("You cannot lock sharetokens for a period less than what you have already locked")
458- else {
459- let userLockedAmountNew = (userLockedAmount + i.payments[0].amount)
460- let userLockedHeigtNew = (height + lockPeriod)
461- let userAmountVirtualNew = (fraction(userLockedAmountNew, lockCoef, lockBoostCoefScale) + userStakedAmount)
462- $Tuple2([IntegerEntry((((pool + "_") + user) + kUserShareTokensLocked), userLockedAmountNew), IntegerEntry((((pool + "_") + user) + kUserShareTokensLockedHeight), userLockedHeigtNew), IntegerEntry((((pool + "_") + user) + kUserShareTokensLockedType), lockType), IntegerEntry((((pool + "_") + user) + kUserShareTokensVirtual), userAmountVirtualNew), IntegerEntry((pool + kShareTokensVirtual), ((totalShareVirtual - userAmountVirtual) + userAmountVirtualNew))], (totalShare + i.payments[0].amount))
463- }
464- let lockEntries = $t02027922124._1
465- let totalShareNew = $t02027922124._2
466- if ((accountBalance(shareAssetId) > totalShareNew))
467- then throw("Balance of share-token is lower than totalAmount")
734+ func paymantValid (acc,payment) = if (containsElement(assetIds, getStrAssetId(payment.assetId)))
735+ then true
736+ else throw("Invalid asset in payment")
737+
738+ let $l = payments
739+ let $s = size($l)
740+ let $acc0 = false
741+ func $f0_1 ($a,$i) = if (($i >= $s))
742+ then $a
743+ else paymantValid($a, $l[$i])
744+
745+ func $f0_2 ($a,$i) = if (($i >= $s))
746+ then $a
747+ else throw("List size exceeds 10")
748+
749+ $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
750+ }
751+
752+ if (!(validPayments(paymentsSize)))
753+ then throw()
754+ else {
755+ let suspicious = checkSuspicious()
756+ if (suspicious._1)
757+ then (suspendSuspicious(suspicious._2) ++ returnPayments(msg.caller, payments))
758+ else {
759+ func parsePayments (acc,assetId) = {
760+ let $t01647416500 = acc
761+ let newBalances = $t01647416500._1
762+ let i = $t01647416500._2
763+ func parsePayment (newBalance,payment) = if ((getStrAssetId(payment.assetId) == assetId))
764+ then (newBalance + payment.amount)
765+ else newBalance
766+
767+ let newBalace = {
768+ let $l = payments
769+ let $s = size($l)
770+ let $acc0 = xp[i]
771+ func $f0_1 ($a,$i) = if (($i >= $s))
772+ then $a
773+ else parsePayment($a, $l[$i])
774+
775+ func $f0_2 ($a,$i) = if (($i >= $s))
776+ then $a
777+ else throw("List size exceeds 10")
778+
779+ $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
780+ }
781+ $Tuple2((newBalances :+ newBalace), (i + 1))
782+ }
783+
784+ let $t01685016917 = {
785+ let $l = assetIds
786+ let $s = size($l)
787+ let $acc0 = $Tuple2(nil, 0)
788+ func $f0_1 ($a,$i) = if (($i >= $s))
789+ then $a
790+ else parsePayments($a, $l[$i])
791+
792+ func $f0_2 ($a,$i) = if (($i >= $s))
793+ then $a
794+ else throw("List size exceeds 10")
795+
796+ $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
797+ }
798+ let newBalances = $t01685016917._1
799+ let k = $t01685016917._2
800+ if (checkDAppThreshold(newBalances))
801+ then throw()
802+ else {
803+ let D1 = getDMem(newBalances, amp)
804+ if (assert((D1 > D0)))
805+ then throw("D1 > D0")
468806 else {
469- let $t02224922348 = claimCalc(pool, user)
470- let farmInterest = $t02224922348._1
471- let boostInterest = $t02224922348._2
472- let boostLPinterest = $t02224922348._3
473- let claimAmount = $t02224922348._4
474- let toTreasure = $t02224922348._5
475- let availableFundsNew = (userAvailableSWOP(pool, i.originCaller) + claimAmount)
476- let uplp = if ((getString(Address(fromBase58String(pool)), "version") == "3.0.0"))
477- then invoke(lpFarmingAddress, "updateUserInterest", [pool, totalUserShareTokens], nil)
478- else 0
479- if ((uplp == uplp))
480- then ([IntegerEntry((((pool + "_") + user) + kFarmUserLastInterest), farmInterest), IntegerEntry((((pool + "_") + user) + kBoostUserLastInterest), boostInterest), IntegerEntry((((pool + "_") + user) + kBoostLPLastInterest), boostLPinterest), IntegerEntry((pool + kFarmLastInterest), farmInterest), IntegerEntry((pool + kBoostLastInterest), boostInterest), IntegerEntry((pool + kBoostLPLastInterest), boostLPinterest), IntegerEntry((pool + kLastInterestHeight), height), IntegerEntry((pool + kShareTotalShareTokens), totalShareNew), IntegerEntry((((pool + "_") + user) + kAvailableSWOP), availableFundsNew), Reissue(SWOP, toTreasure, true), ScriptTransfer(farmingTreasureAddr, toTreasure, SWOP)] ++ lockEntries)
481- else throw("Strict value is not equal to itself.")
807+ let feeDiscount = calculateFeeDiscount(msg.caller)
808+ func calcScriptActions (acc,newBalance) = {
809+ let $t01723717278 = acc
810+ let invBalances = $t01723717278._1
811+ let scriptActions = $t01723717278._2
812+ let i = $t01723717278._3
813+ if ((shareSupply > 0))
814+ then {
815+ let _fee = ((fraction(fee, feeDiscount, feeScale6, CEILING) * nCoins) / (4 * (nCoins - 1)))
816+ let fees = {
817+ let idealBalance = fraction(D1, xp[i], D0)
818+ let difference = if ((idealBalance > newBalance))
819+ then (idealBalance - newBalance)
820+ else (newBalance - idealBalance)
821+ fraction(_fee, difference, feeScale6)
822+ }
823+ let governanceFees = fraction(fees, feeGovernance, feeScale6)
824+ let finalBalance = (newBalance - fees)
825+ let invariantBalance = (newBalance - fees)
826+ let pmt = (newBalance - xp[i])
827+ let lpFees = (fees - governanceFees)
828+ let inv = if ((pmt > 0))
829+ then stake((pmt - fees), assetIds[i])
830+ else unstake(fees, assetIds[i])
831+ if ((inv == inv))
832+ then {
833+ let airdrop = if ((lpFees > 0))
834+ then invoke(lpFarmingAddress, "airDrop", nil, [AttachedPayment(fromBase58String(assetIds[i]), lpFees)])
835+ else 0
836+ if ((airdrop == airdrop))
837+ then $Tuple3((invBalances :+ invariantBalance), (scriptActions ++ [ScriptTransfer(moneyBoxAddress, governanceFees, fromBase58String(assetIds[i])), IntegerEntry((assetIds[i] + kAssetBalance), finalBalance)]), (i + 1))
838+ else throw("Strict value is not equal to itself.")
839+ }
840+ else throw("Strict value is not equal to itself.")
841+ }
842+ else {
843+ let inv = stake(newBalance, assetIds[i])
844+ if ((inv == inv))
845+ then $Tuple3((invBalances :+ newBalance), (scriptActions :+ IntegerEntry((assetIds[i] + kAssetBalance), newBalance)), (i + 1))
846+ else throw("Strict value is not equal to itself.")
847+ }
848+ }
849+
850+ let $t01898319071 = {
851+ let $l = newBalances
852+ let $s = size($l)
853+ let $acc0 = $Tuple3(nil, nil, 0)
854+ func $f1_1 ($a,$i) = if (($i >= $s))
855+ then $a
856+ else calcScriptActions($a, $l[$i])
857+
858+ func $f1_2 ($a,$i) = if (($i >= $s))
859+ then $a
860+ else throw("List size exceeds 10")
861+
862+ $f1_2($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
863+ }
864+ let invBalances = $t01898319071._1
865+ let scriptActions = $t01898319071._2
866+ let D2 = getDMem(invBalances, amp)
867+ let mint_amount = if ((shareSupply == 0))
868+ then D1
869+ else fraction(shareSupply, (D2 - D0), D0)
870+ if (assert((mint_amount >= minMintAmount)))
871+ then throw("Slippage screwed you")
872+ else if (stakeFarming)
873+ then {
874+ let re = invoke(this, "reissueShare", [mint_amount], nil)
875+ if ((re == re))
876+ then {
877+ let s = invoke(farmingAddress, "lockShareTokens", [toString(this), lockType], ([AttachedPayment(shareAssetId, mint_amount)] ++ lockFee))
878+ if ((s == s))
879+ then (scriptActions :+ IntegerEntry(kShareAssetSupply, (shareSupply + mint_amount)))
880+ else throw("Strict value is not equal to itself.")
881+ }
882+ else throw("Strict value is not equal to itself.")
883+ }
884+ else (scriptActions ++ [Reissue(shareAssetId, mint_amount, true), ScriptTransfer(msg.caller, mint_amount, shareAssetId), IntegerEntry(kShareAssetSupply, (shareSupply + mint_amount))])
482885 }
483886 }
484- else throw("Strict value is not equal to itself.")
485887 }
486- })
487-
488-
489-
490-@Callable(i)
491-func lockStakedShareTokens (pool,lockType,lockAmount) = valueOrElse(isActive(), {
492- let shareAssetId = getShareAssetId(pool)
493- let user = toString(i.originCaller)
494- let totalShare = getTotalShareToken(pool)
495- let totalShareVirtual = valueOrElse(getInteger(this, (pool + kShareTokensVirtual)), totalShare)
496- let userStakedAmount = valueOrElse(getInteger(this, (((pool + "_") + user) + kUserShareTokensStaked)), 0)
497- let userLockedHeigt = valueOrElse(getInteger(this, (((pool + "_") + user) + kUserShareTokensLockedHeight)), 0)
498- let userLockedAmount = valueOrElse(getInteger(this, (((pool + "_") + user) + kUserShareTokensLocked)), 0)
499- let userAmountVirtual = valueOrElse(getInteger(this, (((pool + "_") + user) + kUserShareTokensVirtual)), userStakedAmount)
500- let totalUserShareTokens = (userStakedAmount + userLockedAmount)
501- let $t02425624308 = getLockParams(lockType)
502- let lockPeriod = $t02425624308._1
503- let lockCoef = $t02425624308._2
504- let lockWavesFee = getIntegerValue(this, kLockWavesFee)
505- if ((getHeightFirstHarvest(pool) > height))
506- then throw("You can't lock shareTokens till first harvest end.")
507- else if ((0 >= lockType))
508- then throw("lockType must be > 0")
509- else if ((lockAmount > userStakedAmount))
510- then throw(("You can't lock more than " + toString(userStakedAmount)))
511- else if ((accountBalance(shareAssetId) > totalShare))
512- then throw("Balance of share-token is lower than totalAmount")
513- else if (if ((userLockedHeigt == 0))
514- then if (if ((1 > size(i.payments)))
515- then true
516- else (i.payments[0].assetId != unit))
517- then true
518- else (lockWavesFee > i.payments[0].amount)
519- else false)
520- then throw((("You need to pay additional waves comission " + toString(lockWavesFee)) + "WAVES"))
521- else if (if ((userLockedHeigt == 0))
522- then (0 >= lockAmount)
523- else false)
524- then throw("lockAmount must be greater than 0")
525- else if ((0 > lockAmount))
526- then throw("lockAmount must be positive")
527- else if ((userLockedHeigt > (height + lockPeriod)))
528- then throw("You cannot lock sharetokens for a period less than what you have already locked")
529- else {
530- let userLockedAmountNew = (userLockedAmount + lockAmount)
531- let userStakedAmountNew = (userStakedAmount - lockAmount)
532- let userLockedHeigtNew = (height + lockPeriod)
533- let userAmountVirtualNew = (fraction(userLockedAmountNew, lockCoef, lockBoostCoefScale) + userStakedAmount)
534- let $t02559525694 = claimCalc(pool, user)
535- let farmInterest = $t02559525694._1
536- let boostInterest = $t02559525694._2
537- let boostLPinterest = $t02559525694._3
538- let claimAmount = $t02559525694._4
539- let toTreasure = $t02559525694._5
540- let availableFundsNew = (userAvailableSWOP(pool, i.originCaller) + claimAmount)
541-[IntegerEntry((((pool + "_") + user) + kUserShareTokensStaked), userStakedAmountNew), IntegerEntry((((pool + "_") + user) + kUserShareTokensLocked), userLockedAmountNew), IntegerEntry((((pool + "_") + user) + kUserShareTokensLockedHeight), userLockedHeigtNew), IntegerEntry((((pool + "_") + user) + kUserShareTokensLockedType), lockType), IntegerEntry((((pool + "_") + user) + kUserShareTokensVirtual), userAmountVirtualNew), IntegerEntry((pool + kShareTokensVirtual), ((totalShareVirtual - userAmountVirtual) + userAmountVirtualNew)), IntegerEntry((((pool + "_") + user) + kFarmUserLastInterest), farmInterest), IntegerEntry((((pool + "_") + user) + kBoostUserLastInterest), boostInterest), IntegerEntry((((pool + "_") + user) + kBoostLPLastInterest), boostLPinterest), IntegerEntry((pool + kFarmLastInterest), farmInterest), IntegerEntry((pool + kBoostLastInterest), boostInterest), IntegerEntry((pool + kBoostLPLastInterest), boostLPinterest), IntegerEntry((pool + kLastInterestHeight), height), IntegerEntry((((pool + "_") + user) + kAvailableSWOP), availableFundsNew), Reissue(SWOP, toTreasure, true), ScriptTransfer(farmingTreasureAddr, toTreasure, SWOP)]
542- }
543- })
544-
545-
546-
547-@Callable(i)
548-func unlockUserLock (pool,user) = valueOrElse(isActive(), {
549- let lockWavesFee = getIntegerValue(this, kLockWavesFee)
550- let userLockedHeigt = valueOrErrorMessage(getInteger(this, (((pool + "_") + user) + kUserShareTokensLockedHeight)), (((("There is no pool " + pool) + " or user ") + user) + "with lock"))
551- let totalShareVirtual = getIntegerValue(this, (pool + kShareTokensVirtual))
552- let userStakedAmount = valueOrElse(getInteger(this, (((pool + "_") + user) + kUserShareTokensStaked)), 0)
553- let userLockedAmount = valueOrElse(getInteger(this, (((pool + "_") + user) + kUserShareTokensLocked)), 0)
554- let userAmountVirtual = valueOrElse(getInteger(this, (((pool + "_") + user) + kUserShareTokensVirtual)), userStakedAmount)
555- if ((userLockedHeigt > height))
556- then throw(("You can't unlock sharetokens till " + toString(userLockedHeigt)))
557- else {
558- let userStakedAmountNew = (userStakedAmount + userLockedAmount)
559- let $t02793028029 = claimCalc(pool, user)
560- let farmInterest = $t02793028029._1
561- let boostInterest = $t02793028029._2
562- let boostLPinterest = $t02793028029._3
563- let claimAmount = $t02793028029._4
564- let toTreasure = $t02793028029._5
565- let availableFundsNew = (userAvailableSWOP(pool, i.originCaller) + claimAmount)
566-[IntegerEntry((((pool + "_") + user) + kFarmUserLastInterest), farmInterest), IntegerEntry((((pool + "_") + user) + kBoostUserLastInterest), boostInterest), IntegerEntry((((pool + "_") + user) + kBoostLPLastInterest), boostLPinterest), IntegerEntry((pool + kFarmLastInterest), farmInterest), IntegerEntry((pool + kBoostLastInterest), boostInterest), IntegerEntry((pool + kBoostLPLastInterest), boostLPinterest), IntegerEntry((pool + kLastInterestHeight), height), IntegerEntry((((pool + "_") + user) + kUserShareTokensStaked), userStakedAmountNew), IntegerEntry((((pool + "_") + user) + kUserShareTokensVirtual), userStakedAmountNew), IntegerEntry((pool + kShareTokensVirtual), ((totalShareVirtual - userAmountVirtual) + userStakedAmountNew)), DeleteEntry((((pool + "_") + user) + kUserShareTokensLocked)), DeleteEntry((((pool + "_") + user) + kUserShareTokensLockedHeight)), DeleteEntry((((pool + "_") + user) + kUserShareTokensLockedType)), Reissue(SWOP, toTreasure, true), ScriptTransfer(farmingTreasureAddr, toTreasure, SWOP), ScriptTransfer(i.caller, lockWavesFee, unit)]
567888 }
568889 })
569890
570891
571892
572-@Callable(i)
573-func withdrawShareTokens (pool,shareTokensWithdrawAmount) = valueOrElse(isActive(), {
574- let shareTokensId = fromBase58String(getStringValue(value(addressFromString(pool)), "share_asset_id"))
575- let user = toString(i.originCaller)
576- let $t02953329632 = claimCalc(pool, user)
577- let farmInterest = $t02953329632._1
578- let boostInterest = $t02953329632._2
579- let boostLPinterest = $t02953329632._3
580- let claimAmount = $t02953329632._4
581- let toTreasure = $t02953329632._5
582- let userStakedAmount = valueOrElse(getInteger(this, (((pool + "_") + user) + kUserShareTokensStaked)), 0)
583- let userLockedAmount = valueOrElse(getInteger(this, (((pool + "_") + user) + kUserShareTokensLocked)), 0)
584- let userAmountVirtual = valueOrElse(getInteger(this, (((pool + "_") + user) + kUserShareTokensVirtual)), userStakedAmount)
585- let userStakedAmountNew = (userStakedAmount - shareTokensWithdrawAmount)
586- let availableFundsNew = (userAvailableSWOP(pool, i.originCaller) + claimAmount)
587- let totalShareAmount = getTotalShareToken(pool)
588- let totalShareVirtual = valueOrElse(getInteger(this, (pool + kShareTokensVirtual)), totalShareAmount)
589- let totalShareAmountNew = (totalShareAmount - shareTokensWithdrawAmount)
590- let totalShareVirtualNew = (totalShareVirtual - shareTokensWithdrawAmount)
591- let userAmountVirtualNew = (userAmountVirtual - shareTokensWithdrawAmount)
592- if ((shareTokensWithdrawAmount > userStakedAmount))
593- then throw("Withdraw amount more then user locked amount")
594- else if ((accountBalance(shareTokensId) > totalShareAmount))
595- then throw("Balance of share-token is lower than totalAmount")
596- else {
597- let uplp = if ((getString(Address(fromBase58String(pool)), "version") == "3.0.0"))
598- then invoke(lpFarmingAddress, "updateUserInterest", [pool, (userStakedAmount + userLockedAmount)], nil)
599- else 0
600- if ((uplp == uplp))
601- then [IntegerEntry((((pool + "_") + user) + kFarmUserLastInterest), farmInterest), IntegerEntry((((pool + "_") + user) + kBoostUserLastInterest), boostInterest), IntegerEntry((((pool + "_") + user) + kBoostLPLastInterest), boostLPinterest), IntegerEntry((pool + kFarmLastInterest), farmInterest), IntegerEntry((pool + kBoostLastInterest), boostInterest), IntegerEntry((pool + kBoostLPLastInterest), boostLPinterest), IntegerEntry((pool + kLastInterestHeight), height), IntegerEntry((((pool + "_") + user) + kUserShareTokensStaked), userStakedAmountNew), IntegerEntry((((pool + "_") + user) + kUserShareTokensVirtual), userAmountVirtualNew), IntegerEntry((pool + kShareTotalShareTokens), totalShareAmountNew), IntegerEntry((pool + kShareTokensVirtual), totalShareVirtualNew), IntegerEntry((((pool + "_") + user) + kAvailableSWOP), availableFundsNew), Reissue(SWOP, toTreasure, true), ScriptTransfer(farmingTreasureAddr, toTreasure, SWOP), ScriptTransfer(i.caller, shareTokensWithdrawAmount, shareTokensId)]
602- else throw("Strict value is not equal to itself.")
893+@Callable(msg)
894+func calcMintAmount (newBalances,user) = {
895+ let amp = _A()
896+ let xp = _xp()
897+ let D1 = getDMem(newBalances, amp)
898+ if ((shareSupply == 0))
899+ then $Tuple2(nil, D1)
900+ else {
901+ let D0 = getDMem(xp, amp)
902+ let feeDiscount = calculateFeeDiscount(user)
903+ func calcInvBalances (acc,newBalance) = {
904+ let $t02032120347 = acc
905+ let invBalances = $t02032120347._1
906+ let i = $t02032120347._2
907+ let _fee = ((fraction(fee, feeDiscount, feeScale6, CEILING) * nCoins) / (4 * (nCoins - 1)))
908+ let fees = {
909+ let idealBalance = fraction(D1, xp[i], D0)
910+ let difference = if ((idealBalance > newBalance))
911+ then (idealBalance - newBalance)
912+ else (newBalance - idealBalance)
913+ fraction(_fee, difference, feeScale6)
914+ }
915+ let invariantBalance = (newBalance - fees)
916+ $Tuple2((invBalances :+ invariantBalance), (i + 1))
603917 }
604- })
918+
919+ let $t02094921019 = {
920+ let $l = newBalances
921+ let $s = size($l)
922+ let $acc0 = $Tuple2(nil, 0)
923+ func $f0_1 ($a,$i) = if (($i >= $s))
924+ then $a
925+ else calcInvBalances($a, $l[$i])
926+
927+ func $f0_2 ($a,$i) = if (($i >= $s))
928+ then $a
929+ else throw("List size exceeds 10")
930+
931+ $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
932+ }
933+ let invBalances = $t02094921019._1
934+ let k = $t02094921019._2
935+ let D2 = getDMem(invBalances, amp)
936+ let mintAmount = fraction(shareSupply, (D2 - D0), D0)
937+ $Tuple2(nil, mintAmount)
938+ }
939+ }
605940
606941
607942
608-@Callable(i)
609-func claim (pool) = valueOrElse(isActive(), {
610- let shareTokensId = fromBase58String(getStringValue(value(addressFromString(pool)), "share_asset_id"))
611- let user = toString(i.caller)
612- let shareTokenLocked = getTotalShareToken(pool)
613- let $t03230132400 = claimCalc(pool, user)
614- let farmInterest = $t03230132400._1
615- let boostInterest = $t03230132400._2
616- let boostLPinterest = $t03230132400._3
617- let claimAmount = $t03230132400._4
618- let toTreasure = $t03230132400._5
619- let availableFund = (userAvailableSWOP(pool, i.caller) + claimAmount)
620- if ((availableFund == 0))
621- then throw("You have 0 available SWOP")
622- else if ((accountBalance(shareTokensId) > shareTokenLocked))
623- then throw("Balance of share-token is lower than totalAmount")
624- else $Tuple2([IntegerEntry((((pool + "_") + user) + kFarmUserLastInterest), farmInterest), IntegerEntry((((pool + "_") + user) + kBoostUserLastInterest), boostInterest), IntegerEntry((((pool + "_") + user) + kBoostLPLastInterest), boostLPinterest), IntegerEntry((pool + kFarmLastInterest), farmInterest), IntegerEntry((pool + kBoostLastInterest), boostInterest), IntegerEntry((pool + kBoostLPLastInterest), boostLPinterest), IntegerEntry((pool + kLastInterestHeight), height), IntegerEntry((((pool + "_") + user) + kAvailableSWOP), 0), Reissue(SWOP, (toTreasure + availableFund), true), ScriptTransfer(farmingTreasureAddr, toTreasure, SWOP), ScriptTransfer(i.caller, availableFund, SWOP)], availableFund)
625- })
943+@Callable(msg)
944+func reissueShare (amount) = valueOrElse(isSelfCall(msg), [Reissue(shareAssetId, amount, true)])
626945
627946
628947
629-@Callable(i)
630-func claimAndStake (pool) = valueOrElse(isActive(), {
631- let claimAmount = {
632- let @ = invoke(this, "claim", [pool], nil)
633- if ($isInstanceOf(@, "Int"))
634- then @
635- else throw(($getType(@) + " couldn't be cast to Int"))
636- }
637- if ((claimAmount == claimAmount))
638- then {
639- let stakeToGov = invoke(govAddress, "lockSWOPFromFarming", nil, [AttachedPayment(SWOP, claimAmount)])
640- if ((stakeToGov == stakeToGov))
641- then nil
642- else throw("Strict value is not equal to itself.")
643- }
644- else throw("Strict value is not equal to itself.")
645- })
948+@Callable(msg)
949+func getDy (assetFrom,assetTo,dx,userAddress) = {
950+ let xp = _xp()
951+ let fromIndex = valueOrErrorMessage(indexOf(assetIds, assetFrom), "unknown token in")
952+ let toIndex = valueOrErrorMessage(indexOf(assetIds, assetTo), "unknown token out")
953+ let x = (xp[fromIndex] + dx)
954+ let y = getY(fromIndex, toIndex, x, xp)
955+ let dy = ((xp[toIndex] - y) - 1)
956+ let feeDiscount = calculateFeeDiscount(Address(fromBase58String(userAddress)))
957+ let _fee = fraction(fraction(fee, feeDiscount, feeScale6, CEILING), dy, feeScale6)
958+ $Tuple2(nil, $Tuple2((dy - _fee), _fee))
959+ }
646960
647961
648962
649-@Callable(i)
650-func claimAll (pools) = valueOrElse(isActive(), {
651- func claimInv (claimTotal,pool) = {
652- let claimAmount = {
653- let @ = invoke(this, "claim", [pool], nil)
654- if ($isInstanceOf(@, "Int"))
655- then @
656- else throw(($getType(@) + " couldn't be cast to Int"))
657- }
658- if ((claimAmount == claimAmount))
659- then (claimTotal + claimAmount)
660- else throw("Strict value is not equal to itself.")
661- }
963+@Callable(msg)
964+func exchange (tokenOut,min_dy) = valueOrElse(isActive(), if ((size(msg.payments) != 1))
965+ then throw("size(payments) != 1")
966+ else {
967+ let suspicious = checkSuspicious()
968+ if (suspicious._1)
969+ then (suspendSuspicious(suspicious._2) ++ returnPayments(msg.caller, msg.payments))
970+ else {
971+ let payment = msg.payments[0]
972+ let tokenIn = getStrAssetId(payment.assetId)
973+ let tokenOutB58 = fromBase58String(tokenOut)
974+ let dx = payment.amount
975+ let fromIndex = valueOrErrorMessage(indexOf(assetIds, tokenIn), "unknown token in")
976+ let toIndex = valueOrErrorMessage(indexOf(assetIds, tokenOut), "unknown token out")
977+ let xp = _xp()
978+ let x = (xp[fromIndex] + dx)
979+ let y = getY(fromIndex, toIndex, x, xp)
980+ let _dy = ((xp[toIndex] - y) - 1)
981+ let feeDiscount = calculateFeeDiscount(msg.originCaller)
982+ let _fee = fraction(_dy, fraction(fee, feeDiscount, feeScale6, CEILING), feeScale6)
983+ let dy = (_dy - _fee)
984+ let governanceFees = fraction(_fee, feeGovernance, feeScale6)
985+ if (assert((dy >= min_dy)))
986+ then throw("Exchange resulted in fewer coins than expected")
987+ else {
988+ func makeNewBalances (acc,tokenBalance) = {
989+ let $t02306023086 = acc
990+ let newBalances = $t02306023086._1
991+ let i = $t02306023086._2
992+ if ((i == fromIndex))
993+ then $Tuple2((newBalances :+ (tokenBalance + dx)), (i + 1))
994+ else if ((i == toIndex))
995+ then $Tuple2((newBalances :+ (tokenBalance - _dy)), (i + 1))
996+ else $Tuple2((newBalances :+ tokenBalance), (i + 1))
997+ }
662998
663- let claimTotal = {
664- let $l = pools
665- let $s = size($l)
666- let $acc0 = 0
667- func $f0_1 ($a,$i) = if (($i >= $s))
668- then $a
669- else claimInv($a, $l[$i])
999+ let $t02333723398 = {
1000+ let $l = xp
1001+ let $s = size($l)
1002+ let $acc0 = $Tuple2(nil, 0)
1003+ func $f0_1 ($a,$i) = if (($i >= $s))
1004+ then $a
1005+ else makeNewBalances($a, $l[$i])
6701006
671- func $f0_2 ($a,$i) = if (($i >= $s))
672- then $a
673- else throw("List size exceeds 60")
1007+ func $f0_2 ($a,$i) = if (($i >= $s))
1008+ then $a
1009+ else throw("List size exceeds 10")
6741010
675- $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($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($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($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), 20), 21), 22), 23), 24), 25), 26), 27), 28), 29), 30), 31), 32), 33), 34), 35), 36), 37), 38), 39), 40), 41), 42), 43), 44), 45), 46), 47), 48), 49), 50), 51), 52), 53), 54), 55), 56), 57), 58), 59), 60)
676- }
677- if ((claimTotal == 0))
678- then throw("You have 0 available SWOP")
679- else [ScriptTransfer(i.caller, claimTotal, SWOP)]
680- })
681-
682-
683-
684-@Callable(i)
685-func claimAllAndStake (pools) = valueOrElse(isActive(), {
686- func claimInv (claimTotal,pool) = {
687- let claimAmount = {
688- let @ = invoke(this, "claim", [pool], nil)
689- if ($isInstanceOf(@, "Int"))
690- then @
691- else throw(($getType(@) + " couldn't be cast to Int"))
692- }
693- if ((claimAmount == claimAmount))
694- then (claimTotal + claimAmount)
695- else throw("Strict value is not equal to itself.")
696- }
697-
698- let claimTotal = {
699- let $l = pools
700- let $s = size($l)
701- let $acc0 = 0
702- func $f0_1 ($a,$i) = if (($i >= $s))
703- then $a
704- else claimInv($a, $l[$i])
705-
706- func $f0_2 ($a,$i) = if (($i >= $s))
707- then $a
708- else throw("List size exceeds 60")
709-
710- $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($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($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($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), 20), 21), 22), 23), 24), 25), 26), 27), 28), 29), 30), 31), 32), 33), 34), 35), 36), 37), 38), 39), 40), 41), 42), 43), 44), 45), 46), 47), 48), 49), 50), 51), 52), 53), 54), 55), 56), 57), 58), 59), 60)
711- }
712- if ((claimTotal == 0))
713- then throw("You have 0 available SWOP")
714- else {
715- let stakeToGov = invoke(govAddress, "lockSWOPFromFarming", nil, [AttachedPayment(SWOP, claimTotal)])
716- if ((stakeToGov == stakeToGov))
717- then nil
718- else throw("Strict value is not equal to itself.")
719- }
720- })
721-
722-
723-
724-@Callable(i)
725-func updateUserBoostInterest (pool,user) = valueOrElse(isActive(), if ((i.caller != votingAddress))
726- then throw("Only voiting can call this function")
727- else {
728- let $t03478034879 = claimCalc(pool, user)
729- let farmInterest = $t03478034879._1
730- let boostInterest = $t03478034879._2
731- let boostLPinterest = $t03478034879._3
732- let claimAmount = $t03478034879._4
733- let toTreasure = $t03478034879._5
734- let availableFundsNew = (userAvailableSWOP(pool, i.originCaller) + claimAmount)
735-[IntegerEntry((((pool + "_") + user) + kFarmUserLastInterest), farmInterest), IntegerEntry((((pool + "_") + user) + kBoostUserLastInterest), boostInterest), IntegerEntry((((pool + "_") + user) + kBoostLPLastInterest), boostLPinterest), IntegerEntry((pool + kFarmLastInterest), farmInterest), IntegerEntry((pool + kBoostLastInterest), boostInterest), IntegerEntry((pool + kBoostLPLastInterest), boostLPinterest), IntegerEntry((pool + kLastInterestHeight), height), IntegerEntry((((pool + "_") + user) + kAvailableSWOP), availableFundsNew), Reissue(SWOP, toTreasure, true), ScriptTransfer(farmingTreasureAddr, toTreasure, SWOP)]
1011+ $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
1012+ }
1013+ let newBalances = $t02333723398._1
1014+ let i = $t02333723398._2
1015+ if (checkDAppThreshold(newBalances))
1016+ then throw()
1017+ else {
1018+ let s = stake(payment.amount, getStrAssetId(payment.assetId))
1019+ if ((s == s))
1020+ then {
1021+ let us = unstake(_dy, tokenOut)
1022+ if ((us == us))
1023+ then {
1024+ let lpFees = (_fee - governanceFees)
1025+ let airdrop = if ((lpFees > 0))
1026+ then invoke(lpFarmingAddress, "airDrop", nil, [AttachedPayment(tokenOutB58, lpFees)])
1027+ else 0
1028+ if ((airdrop == airdrop))
1029+ then $Tuple2([IntegerEntry((tokenIn + kAssetBalance), x), IntegerEntry((tokenOut + kAssetBalance), (xp[toIndex] - _dy)), ScriptTransfer(msg.caller, dy, tokenOutB58), ScriptTransfer(moneyBoxAddress, governanceFees, tokenOutB58)], [dy, tokenOutB58])
1030+ else throw("Strict value is not equal to itself.")
1031+ }
1032+ else throw("Strict value is not equal to itself.")
1033+ }
1034+ else throw("Strict value is not equal to itself.")
1035+ }
1036+ }
1037+ }
7361038 })
7371039
7381040
7391041
740-@Callable(i)
741-func shutdown () = valueOrElse(isAdminCall(i), if (!(active))
1042+@Callable(msg)
1043+func withdraw (minAmounts) = valueOrElse(isActive(), if ((size(msg.payments) != 1))
1044+ then throw("size(payments) != 1")
1045+ else {
1046+ let pmtAmount = msg.payments[0].amount
1047+ let pmtAssetId = msg.payments[0].assetId
1048+ if ((shareAssetId != pmtAssetId))
1049+ then throw("unknown payment token")
1050+ else {
1051+ let suspicious = checkSuspicious()
1052+ if (suspicious._1)
1053+ then (suspendSuspicious(suspicious._2) ++ returnPayments(msg.originCaller, msg.payments))
1054+ else {
1055+ func calcScriptActions (acc,balance) = {
1056+ let $t02468924717 = acc
1057+ let scriptActions = $t02468924717._1
1058+ let i = $t02468924717._2
1059+ let wAmount = fraction(balance, pmtAmount, shareSupply)
1060+ if (assert((wAmount >= minAmounts[i])))
1061+ then throw("Withdrawal resulted in fewer coins than expected")
1062+ else {
1063+ let us = unstake(wAmount, assetIds[i])
1064+ if ((us == us))
1065+ then $Tuple2((scriptActions ++ [IntegerEntry((assetIds[i] + kAssetBalance), (balance - wAmount)), ScriptTransfer(msg.originCaller, wAmount, fromBase58String(assetIds[i]))]), (i + 1))
1066+ else throw("Strict value is not equal to itself.")
1067+ }
1068+ }
1069+
1070+ let $t02520725275 = {
1071+ let $l = _xp()
1072+ let $s = size($l)
1073+ let $acc0 = $Tuple2(nil, 0)
1074+ func $f0_1 ($a,$i) = if (($i >= $s))
1075+ then $a
1076+ else calcScriptActions($a, $l[$i])
1077+
1078+ func $f0_2 ($a,$i) = if (($i >= $s))
1079+ then $a
1080+ else throw("List size exceeds 10")
1081+
1082+ $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
1083+ }
1084+ let scriptActions = $t02520725275._1
1085+ let i = $t02520725275._2
1086+ (scriptActions ++ [Burn(shareAssetId, pmtAmount), IntegerEntry(kShareAssetSupply, (shareSupply - pmtAmount))])
1087+ }
1088+ }
1089+ })
1090+
1091+
1092+
1093+@Callable(msg)
1094+func withdrawWithUnlock (minAmounts,unlockAmount) = valueOrElse(isActive(), if ((0 >= unlockAmount))
1095+ then throw("Unlock amount must be positive")
1096+ else {
1097+ let suspicious = checkSuspicious()
1098+ if (suspicious._1)
1099+ then (suspendSuspicious(suspicious._2) ++ returnPayments(msg.caller, msg.payments))
1100+ else {
1101+ let pmtAmount = if ((size(msg.payments) > 0))
1102+ then if ((size(msg.payments) != 1))
1103+ then throw("size(payments) != 1")
1104+ else {
1105+ let pmtAssetId = msg.payments[0].assetId
1106+ if ((shareAssetId != pmtAssetId))
1107+ then throw("unknown payment token")
1108+ else msg.payments[0].amount
1109+ }
1110+ else 0
1111+ let unlock = invoke(farmingAddress, "withdrawShareTokens", [toString(this), unlockAmount], nil)
1112+ if ((unlock == unlock))
1113+ then {
1114+ let withdrawAmount = (pmtAmount + unlockAmount)
1115+ let inv = invoke(this, "withdraw", [minAmounts], [AttachedPayment(shareAssetId, withdrawAmount)])
1116+ if ((inv == inv))
1117+ then nil
1118+ else throw("Strict value is not equal to itself.")
1119+ }
1120+ else throw("Strict value is not equal to itself.")
1121+ }
1122+ })
1123+
1124+
1125+
1126+@Callable(msg)
1127+func calcWithdrawOneCoin (tokenAmount,tokenOut,user) = if ((0 >= tokenAmount))
1128+ then throw("Amount must be positive")
1129+ else {
1130+ let i = valueOrErrorMessage(indexOf(assetIds, tokenOut), "unknown token out")
1131+ $Tuple2(nil, _calcWithdrawOneCoin(_xp(), tokenAmount, i, Address(fromBase58String(user)))._1)
1132+ }
1133+
1134+
1135+
1136+@Callable(msg)
1137+func withdrawOneCoin (tokenOut,minAmount) = valueOrElse(isActive(), if ((size(msg.payments) != 1))
1138+ then throw("size(payments) != 1")
1139+ else {
1140+ let suspicious = checkSuspicious()
1141+ if (suspicious._1)
1142+ then (suspendSuspicious(suspicious._2) ++ returnPayments(msg.originCaller, msg.payments))
1143+ else {
1144+ let pmtAmount = msg.payments[0].amount
1145+ let pmtAssetId = msg.payments[0].assetId
1146+ if ((pmtAssetId != shareAssetId))
1147+ then throw("unknown token")
1148+ else {
1149+ let outIndex = valueOrErrorMessage(indexOf(assetIds, tokenOut), "unknown token out")
1150+ let tokenOutB58 = fromBase58String(tokenOut)
1151+ let xp = _xp()
1152+ let $t02730727389 = _calcWithdrawOneCoin(xp, pmtAmount, outIndex, msg.originCaller)
1153+ let dy = $t02730727389._1
1154+ let dy_fee = $t02730727389._2
1155+ if (assert((dy >= minAmount)))
1156+ then throw("Not enough coins removed")
1157+ else {
1158+ let governanceFees = fraction(dy_fee, feeGovernance, feeScale6)
1159+ let dy_and_fee = (dy + dy_fee)
1160+ func makeNewBalances (acc,tokenBalance) = {
1161+ let $t02764727673 = acc
1162+ let newBalances = $t02764727673._1
1163+ let i = $t02764727673._2
1164+ if ((i == outIndex))
1165+ then $Tuple2((newBalances :+ (tokenBalance - dy_and_fee)), (i + 1))
1166+ else $Tuple2((newBalances :+ tokenBalance), (i + 1))
1167+ }
1168+
1169+ let $t02784027901 = {
1170+ let $l = xp
1171+ let $s = size($l)
1172+ let $acc0 = $Tuple2(nil, 0)
1173+ func $f0_1 ($a,$i) = if (($i >= $s))
1174+ then $a
1175+ else makeNewBalances($a, $l[$i])
1176+
1177+ func $f0_2 ($a,$i) = if (($i >= $s))
1178+ then $a
1179+ else throw("List size exceeds 10")
1180+
1181+ $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
1182+ }
1183+ let newBalances = $t02784027901._1
1184+ let v = $t02784027901._2
1185+ if (checkDAppThreshold(newBalances))
1186+ then throw()
1187+ else {
1188+ let us = unstake(dy_and_fee, tokenOut)
1189+ if ((us == us))
1190+ then {
1191+ let lpFees = (dy_fee - governanceFees)
1192+ let airdrop = if ((lpFees > 0))
1193+ then invoke(lpFarmingAddress, "airDrop", nil, [AttachedPayment(tokenOutB58, lpFees)])
1194+ else 0
1195+ if ((airdrop == airdrop))
1196+ then [ScriptTransfer(msg.originCaller, dy, tokenOutB58), IntegerEntry((assetIds[outIndex] + kAssetBalance), (xp[outIndex] - dy_and_fee)), Burn(shareAssetId, pmtAmount), ScriptTransfer(moneyBoxAddress, governanceFees, tokenOutB58), IntegerEntry(kShareAssetSupply, (shareSupply - pmtAmount))]
1197+ else throw("Strict value is not equal to itself.")
1198+ }
1199+ else throw("Strict value is not equal to itself.")
1200+ }
1201+ }
1202+ }
1203+ }
1204+ })
1205+
1206+
1207+
1208+@Callable(msg)
1209+func withdrawOneCoinWithUnlock (tokenOut,minAmount,unlockAmount) = valueOrElse(isActive(), if ((0 >= unlockAmount))
1210+ then throw("Unlock amount must be positive")
1211+ else {
1212+ let suspicious = checkSuspicious()
1213+ if (suspicious._1)
1214+ then (suspendSuspicious(suspicious._2) ++ returnPayments(msg.caller, msg.payments))
1215+ else {
1216+ let pmtAmount = if ((size(msg.payments) > 0))
1217+ then if ((size(msg.payments) != 1))
1218+ then throw("size(payments) != 1")
1219+ else {
1220+ let pmtAssetId = msg.payments[0].assetId
1221+ if ((shareAssetId != pmtAssetId))
1222+ then throw("unknown payment token")
1223+ else msg.payments[0].amount
1224+ }
1225+ else 0
1226+ let unlock = invoke(farmingAddress, "withdrawShareTokens", [toString(this), unlockAmount], nil)
1227+ if ((unlock == unlock))
1228+ then {
1229+ let withdrawAmount = (pmtAmount + unlockAmount)
1230+ let inv = invoke(this, "withdrawOneCoin", [tokenOut, minAmount], [AttachedPayment(shareAssetId, withdrawAmount)])
1231+ if ((inv == inv))
1232+ then nil
1233+ else throw("Strict value is not equal to itself.")
1234+ }
1235+ else throw("Strict value is not equal to itself.")
1236+ }
1237+ })
1238+
1239+
1240+
1241+@Callable(msg)
1242+func A () = $Tuple2(nil, _A())
1243+
1244+
1245+
1246+@Callable(msg)
1247+func getVirtualPrice () = {
1248+ let D = get_D(_xp(), _A())
1249+ $Tuple2(nil, fraction(D, PRECISION, shareSupply))
1250+ }
1251+
1252+
1253+
1254+@Callable(msg)
1255+func calcTokenAmount (amounts,deposit) = {
1256+ let amp = _A()
1257+ let balances = _xp()
1258+ let D0 = getDMem(balances, amp)
1259+ func calcNewBalances (acc,balance) = {
1260+ let $t02991829944 = acc
1261+ let newBalances = $t02991829944._1
1262+ let i = $t02991829944._2
1263+ let newBalance = (balance + (if (deposit)
1264+ then amounts[i]
1265+ else -(amounts[i])))
1266+ $Tuple2((newBalances :+ newBalance), (i + 1))
1267+ }
1268+
1269+ let newBalances = ( let $l = balances
1270+ let $s = size($l)
1271+ let $acc0 = $Tuple2(nil, 0)
1272+ func $f0_1 ($a,$i) = if (($i >= $s))
1273+ then $a
1274+ else calcNewBalances($a, $l[$i])
1275+
1276+ func $f0_2 ($a,$i) = if (($i >= $s))
1277+ then $a
1278+ else throw("List size exceeds 10")
1279+
1280+ $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10))._1
1281+ let D1 = getDMem(newBalances, amp)
1282+ let diff = if (deposit)
1283+ then (D1 - D0)
1284+ else (D0 - D1)
1285+ $Tuple2(nil, fraction(diff, shareSupply, D0))
1286+ }
1287+
1288+
1289+
1290+@Callable(msg)
1291+func rampA (_futureA,_futureTime) = valueOrElse(isActive(), valueOrElse(isAdminCall(msg), if (assert((blockTimestamp >= (initial_A_time + MIN_RAMP_TIME))))
1292+ then throw("too often")
1293+ else if (assert((_futureTime >= (blockTimestamp + MIN_RAMP_TIME))))
1294+ then throw("insufficient time")
1295+ else {
1296+ let _initial_A = _A()
1297+ if (assert(if ((_futureA > 0))
1298+ then (MAX_A > _futureA)
1299+ else false))
1300+ then throw("out of base range")
1301+ else if (assert(if (if ((_futureA >= _initial_A))
1302+ then ((_initial_A * MAX_A_CHANGE) >= _futureA)
1303+ else false)
1304+ then true
1305+ else if ((_initial_A > _futureA))
1306+ then ((_futureA * MAX_A_CHANGE) >= _initial_A)
1307+ else false))
1308+ then throw("out of range")
1309+ else [IntegerEntry("initial_A", _initial_A), IntegerEntry("future_A", _futureA), IntegerEntry("initial_A_time", blockTimestamp), IntegerEntry("future_A_time", _futureTime)]
1310+ }))
1311+
1312+
1313+
1314+@Callable(msg)
1315+func stopRampA () = valueOrElse(isActive(), valueOrElse(isAdminCall(msg), {
1316+ let currentA = _A()
1317+[IntegerEntry("initial_A", currentA), IntegerEntry("future_A", currentA), IntegerEntry("initial_A_time", blockTimestamp), IntegerEntry("future_A_time", blockTimestamp)]
1318+ }))
1319+
1320+
1321+
1322+@Callable(msg)
1323+func shutdown () = valueOrElse(isAdminCall(msg), if (!(active))
7421324 then throw(("DApp is already suspended. Cause: " + valueOrElse(getString(this, kCause), "the cause wasn't specified")))
7431325 else suspend("Paused by admin"))
7441326
7451327
7461328
747-@Callable(i)
748-func activate () = valueOrElse(isAdminCall(i), if (active)
749- then throw("DApp is already active")
1329+@Callable(msg)
1330+func activate () = valueOrElse(isAdminCall(msg), if (active)
1331+ then throwIsActive()
7501332 else [BooleanEntry(kActive, true), DeleteEntry(kCause)])
7511333
7521334
1335+
1336+@Callable(msg)
1337+func takeIntoAccountExtraFunds () = valueOrElse(isActive(), if ((msg.caller != moneyBoxAddress))
1338+ then throw("Only the wallet can call this function")
1339+ else {
1340+ let balances = _xp()
1341+ func takeExtraFunds (acc,assetId) = {
1342+ let $t03228632304 = acc
1343+ let sum = $t03228632304._1
1344+ let i = $t03228632304._2
1345+ let tokenB58 = fromBase58String(assetId)
1346+ let rBalance = (assetBalance(this, tokenB58) + stakedAmount(tokenB58))
1347+ let enrollAmount = (rBalance - balances[i])
1348+ if ((0 > enrollAmount))
1349+ then suspend(("Enroll amount negative for asset" + assetId))
1350+ else {
1351+ let airdrop = if ((enrollAmount > 0))
1352+ then invoke(lpFarmingAddress, "airDrop", nil, [AttachedPayment(tokenB58, enrollAmount)])
1353+ else 0
1354+ if ((airdrop == airdrop))
1355+ then $Tuple2((sum + enrollAmount), (i + 1))
1356+ else throw("Strict value is not equal to itself.")
1357+ }
1358+ }
1359+
1360+ let k = {
1361+ let $l = assetIds
1362+ let $s = size($l)
1363+ let $acc0 = $Tuple2(0, 0)
1364+ func $f0_1 ($a,$i) = if (($i >= $s))
1365+ then $a
1366+ else takeExtraFunds($a, $l[$i])
1367+
1368+ func $f0_2 ($a,$i) = if (($i >= $s))
1369+ then $a
1370+ else throw("List size exceeds 10")
1371+
1372+ $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
1373+ }
1374+ if ((k._1 == 0))
1375+ then throw("No money to take")
1376+ else nil
1377+ })
1378+
1379+
7531380 @Verifier(tx)
754-func verify () = match tx {
755- case _ =>
1381+func verify () = {
1382+ let multiSignedByAdmins = {
7561383 let adminPubKey1Signed = if (sigVerify(tx.bodyBytes, tx.proofs[0], adminPubKey1))
7571384 then 1
7581385 else 0
7591386 let adminPubKey2Signed = if (sigVerify(tx.bodyBytes, tx.proofs[1], adminPubKey2))
7601387 then 1
7611388 else 0
7621389 let adminPubKey3Signed = if (sigVerify(tx.bodyBytes, tx.proofs[2], adminPubKey3))
7631390 then 1
7641391 else 0
7651392 (((adminPubKey1Signed + adminPubKey2Signed) + adminPubKey3Signed) >= 2)
766-}
1393+ }
1394+ match tx {
1395+ case inv: InvokeScriptTransaction =>
1396+ let callTakeIntoAccount = if ((inv.dApp == this))
1397+ then (inv.function == "takeIntoAccountExtraFunds")
1398+ else false
1399+ let signedByAdmin = if (if (if (sigVerify(tx.bodyBytes, tx.proofs[0], adminPubKey1))
1400+ then true
1401+ else sigVerify(tx.bodyBytes, tx.proofs[0], adminPubKey2))
1402+ then true
1403+ else sigVerify(tx.bodyBytes, tx.proofs[0], adminPubKey3))
1404+ then true
1405+ else sigVerify(tx.bodyBytes, tx.proofs[0], adminPubKeyInvoke)
1406+ if (if (callTakeIntoAccount)
1407+ then signedByAdmin
1408+ else false)
1409+ then true
1410+ else multiSignedByAdmins
1411+ case _ =>
1412+ multiSignedByAdmins
1413+ }
1414+ }
7671415

github/deemru/w8io/169f3d6 
181.48 ms