tx · 2xsfJgHDmL8p8ipMhrRJpHdQHedjeVJBnits357JDE1G 3N8kvmPeoj7z8PGPDMGmBZT5GvfjxzXP36E: -0.01000000 Waves 2023.09.28 07:54 [2774809] smart account 3N8kvmPeoj7z8PGPDMGmBZT5GvfjxzXP36E > SELF 0.00000000 Waves
{ "type": 13, "id": "2xsfJgHDmL8p8ipMhrRJpHdQHedjeVJBnits357JDE1G", "fee": 1000000, "feeAssetId": null, "timestamp": 1695876930952, "version": 2, "chainId": 84, "sender": "3N8kvmPeoj7z8PGPDMGmBZT5GvfjxzXP36E", "senderPublicKey": "7o6RgieyGuTpujJ7p7Ms7XPWGVMWzinzLwbSpikKMWQE", "proofs": [ "44fKYswCEoE5KZx5cKzm1J6SGbKhv6o75LyrmMmwtSA92JPxam39TycV1LYdjpghnY51zz8ug41KAyuq1ZD9DWt4" ], "script": "base64:BgIYCAISBwoFCAgBCAgSABIDCgEBEgASABIADgAGTVVMVDEwAIDIr6AlAANTRVACAl9fABBpc0NvbnN0cnVjdGVkS2V5Ag5pc19jb25zdHJ1Y3RlZAAXd2l0aGRyYXdhbExvY2tQZXJpb2RLZXkCFndpdGhkcmF3YWxfbG9ja19wZXJpb2QAEHJld2FyZEFzc2V0SWRLZXkCD3Jld2FyZF9hc3NldF9pZAATcG9vbFN0YWtlQXNzZXRJZEtleQITcG9vbF9zdGFrZV9hc3NldF9pZAAWcm9vdENvbnRyYWN0QWRkcmVzc0tleQIVcm9vdF9jb250cmFjdF9hZGRyZXNzAA9hZG1pbkFkZHJlc3NLZXkCEWFkbWluX2FkZHJlc3Nfa2V5ABJ0b3RhbFBvb2xTdGFrZWRLZXkCEnRvdGFsX3Bvb2xfX3N0YWtlZAASdG90YWxQb29sRWFybmVkS2V5AhF0b3RhbF9wb29sX2Vhcm5lZAAVcG9vbEN1cnJlbnRDbGFpbUlkS2V5AhVwb29sX2N1cnJlbnRfY2xhaW1faWQAKHBvb2xDdXJyZW50VW5jbGFpbWVkQWRkaXRpb25hbFJld2FyZHNLZXkCKXBvb2xfY3VycmVudF91bmNsYWltZWRfYWRkaXRpb25hbF9yZXdhcmRzAQlhc1BheW1lbnQBAXYEByRtYXRjaDAFAXYDCQABAgUHJG1hdGNoMAIPQXR0YWNoZWRQYXltZW50BAFwBQckbWF0Y2gwBQFwCQACAQIhZmFpbCB0byBjYXN0IGludG8gQXR0YWNoZWRQYXltZW50ARppc1VzZXJIYXZlVW5jbGFpbWVkUmV3YXJkcwEHYWRkcmVzcwMJAQEhAQkBCWlzRGVmaW5lZAEJAKIIAQUHYWRkcmVzcwcEEmN1cnJlbnRQb29sQ2xhaW1JZAkBEUBleHRyTmF0aXZlKDEwNTUpAQUVcG9vbEN1cnJlbnRDbGFpbUlkS2V5BAh1c2VyRGF0YQkAtQkCCQERQGV4dHJOYXRpdmUoMTA1OCkBBQdhZGRyZXNzBQNTRVAEI3VzZXJMYXN0Q2xhaW1lZFJld2FyZHNBdFBvb2xDbGFpbUlkCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUIdXNlckRhdGEAAgkAZgIFEmN1cnJlbnRQb29sQ2xhaW1JZAUjdXNlckxhc3RDbGFpbWVkUmV3YXJkc0F0UG9vbENsYWltSWQGAWkBC2NvbnN0cnVjdG9yBQ1yZXdhcmRBc3NldElkEHBvb2xTdGFrZUFzc2V0SWQUd2l0aGRyYXdhbExvY2tQZXJpb2QMcm9vdENvbnRyYWN0DWFkbWluQ29udHJhY3QDCQEJaXNEZWZpbmVkAQkAoAgBBRBpc0NvbnN0cnVjdGVkS2V5CQACAQIiQ29uc3RydWN0b3IgY2FuIGJlIGNhbGxlZCBvbmUgdGltZQkAzAgCCQEMQm9vbGVhbkVudHJ5AgUQaXNDb25zdHJ1Y3RlZEtleQYJAMwIAgkBDEludGVnZXJFbnRyeQIFKHBvb2xDdXJyZW50VW5jbGFpbWVkQWRkaXRpb25hbFJld2FyZHNLZXkAAAkAzAgCCQELU3RyaW5nRW50cnkCBRByZXdhcmRBc3NldElkS2V5BQ1yZXdhcmRBc3NldElkCQDMCAIJAQtTdHJpbmdFbnRyeQIFE3Bvb2xTdGFrZUFzc2V0SWRLZXkFEHBvb2xTdGFrZUFzc2V0SWQJAMwIAgkBC1N0cmluZ0VudHJ5AgUWcm9vdENvbnRyYWN0QWRkcmVzc0tleQUMcm9vdENvbnRyYWN0CQDMCAIJAQtTdHJpbmdFbnRyeQIFD2FkbWluQWRkcmVzc0tleQUNYWRtaW5Db250cmFjdAkAzAgCCQEMSW50ZWdlckVudHJ5AgUSdG90YWxQb29sRWFybmVkS2V5AAAJAMwIAgkBDEludGVnZXJFbnRyeQIFFXBvb2xDdXJyZW50Q2xhaW1JZEtleQAACQDMCAIJAQxJbnRlZ2VyRW50cnkCBRJ0b3RhbFBvb2xTdGFrZWRLZXkAAAkAzAgCCQEMSW50ZWdlckVudHJ5AgUXd2l0aGRyYXdhbExvY2tQZXJpb2RLZXkFFHdpdGhkcmF3YWxMb2NrUGVyaW9kBQNuaWwBaQEFc3Rha2UAAwkBAiE9AgkAkAMBCAUBaQhwYXltZW50cwABCQACAQIUT25lIFBheW1lbnQgZXhwZWN0ZWQEDWNhbGxlckFkZHJlc3MJANgEAQgIBQFpBmNhbGxlcgVieXRlcwQHcGF5bWVudAkBCWFzUGF5bWVudAEJAJEDAggFAWkIcGF5bWVudHMAAAQQcG9vbFN0YWtlQXNzZXRJZAkA2QQBCQERQGV4dHJOYXRpdmUoMTA1OCkBBRNwb29sU3Rha2VBc3NldElkS2V5AwMJAQIhPQIIBQdwYXltZW50B2Fzc2V0SWQFEHBvb2xTdGFrZUFzc2V0SWQGCQBnAgAACAUHcGF5bWVudAZhbW91bnQJAAIBAiFXcm9uZyBhc3NldCBpZCBvciBuZWdhdGl2ZSBhbW91bnQDCQEaaXNVc2VySGF2ZVVuY2xhaW1lZFJld2FyZHMBBQ1jYWxsZXJBZGRyZXNzCQACAQI4WW91IGhhdmUgdW5jbGFpbWVkIHJld2FyZHMgb24gY29udHJhY3QsIGNsYWltIHRoZW0gZmlyc3QEEmN1cnJlbnRQb29sQ2xhaW1JZAkBEUBleHRyTmF0aXZlKDEwNTUpAQUVcG9vbEN1cnJlbnRDbGFpbUlkS2V5BBZjdXJyZW50VG90YWxQb29sU3Rha2VkCQERQGV4dHJOYXRpdmUoMTA1NSkBBRJ0b3RhbFBvb2xTdGFrZWRLZXkELWN1cnJlbnRUb3RhbFBvb2xSZXdhcmRzRWFybmVkRm9yT25lU3Rha2VUb2tlbgkBEUBleHRyTmF0aXZlKDEwNTUpAQUSdG90YWxQb29sRWFybmVkS2V5BBNyb290Q29udHJhY3RBZGRyZXNzCQERQGV4dHJOYXRpdmUoMTA1OCkBBRZyb290Q29udHJhY3RBZGRyZXNzS2V5BAZyZXN1bHQDCQBmAgkAsQIBBRNyb290Q29udHJhY3RBZGRyZXNzAAAJAPwHBAkBB0FkZHJlc3MBCQDZBAEFE3Jvb3RDb250cmFjdEFkZHJlc3MCDHN0YWtlUG9vbExwcwUDbmlsCQDMCAIFB3BheW1lbnQFA25pbAUEdW5pdAMJAAACBQZyZXN1bHQFBnJlc3VsdAQLdXNlckRhdGFTdHIJAQt2YWx1ZU9yRWxzZQIJAKIIAQUNY2FsbGVyQWRkcmVzcwIABAh1c2VyRGF0YQMJAGYCCQCxAgEFC3VzZXJEYXRhU3RyAAAECHVzZXJEYXRhCQC1CQIFC3VzZXJEYXRhU3RyBQNTRVAEFXVzZXJUb3RhbFN0YWtlZEFtb3VudAkBDXBhcnNlSW50VmFsdWUBCQCRAwIFCHVzZXJEYXRhAAAJALkJAgkAzAgCCQCkAwEJAGQCBRV1c2VyVG90YWxTdGFrZWRBbW91bnQIBQdwYXltZW50BmFtb3VudAkAzAgCCQCRAwIFCHVzZXJEYXRhAAEJAMwIAgkAkQMCBQh1c2VyRGF0YQACCQDMCAIJAJEDAgUIdXNlckRhdGEAAwkAzAgCCQCkAwEFBmhlaWdodAUDbmlsBQNTRVAJALkJAgkAzAgCCQCkAwEIBQdwYXltZW50BmFtb3VudAkAzAgCAgEwCQDMCAIJAKQDAQUSY3VycmVudFBvb2xDbGFpbUlkCQDMCAIJAKQDAQUtY3VycmVudFRvdGFsUG9vbFJld2FyZHNFYXJuZWRGb3JPbmVTdGFrZVRva2VuCQDMCAIJAKQDAQUGaGVpZ2h0BQNuaWwFA1NFUAkAzAgCCQELU3RyaW5nRW50cnkCBQ1jYWxsZXJBZGRyZXNzBQh1c2VyRGF0YQkAzAgCCQEMSW50ZWdlckVudHJ5AgUSdG90YWxQb29sU3Rha2VkS2V5CQBkAgUWY3VycmVudFRvdGFsUG9vbFN0YWtlZAgFB3BheW1lbnQGYW1vdW50BQNuaWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQEId2l0aGRyYXcBBmFtb3VudAMJAGcCAAAFBmFtb3VudAkAAgECF0Ftb3VudCBtdXN0IGJlIHBvc2l0aXZlBA1jYWxsZXJBZGRyZXNzCQDYBAEICAUBaQZjYWxsZXIFYnl0ZXMDCQEaaXNVc2VySGF2ZVVuY2xhaW1lZFJld2FyZHMBBQ1jYWxsZXJBZGRyZXNzCQACAQI4WW91IGhhdmUgdW5jbGFpbWVkIHJld2FyZHMgb24gY29udHJhY3QsIGNsYWltIHRoZW0gZmlyc3QECHVzZXJEYXRhCQC1CQIJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAoggBBQ1jYWxsZXJBZGRyZXNzAg5Vc2VyIG5vdCBmb3VuZAUDU0VQBBV1c2VyVG90YWxTdGFrZWRBbW91bnQJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQh1c2VyRGF0YQAAAwkAZgIFBmFtb3VudAUVdXNlclRvdGFsU3Rha2VkQW1vdW50CQACAQISSW5zdWZmaWNpZW50IGZ1bmRzBBR3aXRoZHJhd2FsTG9ja1BlcmlvZAkBEUBleHRyTmF0aXZlKDEwNTUpAQUXd2l0aGRyYXdhbExvY2tQZXJpb2RLZXkEEnVzZXJMYXN0U3Rha2VCbG9jawkBDXBhcnNlSW50VmFsdWUBCQCRAwIFCHVzZXJEYXRhAAQDAwkAZgIFFHdpdGhkcmF3YWxMb2NrUGVyaW9kAAAJAGYCBRR3aXRoZHJhd2FsTG9ja1BlcmlvZAkAZQIFBmhlaWdodAUSdXNlckxhc3RTdGFrZUJsb2NrBwkAAgEJAKwCAgkArAICAi1UaGlzIHBvb2wgaGF2ZSBsb2NrIHBlcmlvZC4gWW91IG5lZWQgdG8gd2FpdCAJAKQDAQkAZQIFFHdpdGhkcmF3YWxMb2NrUGVyaW9kCQBlAgUGaGVpZ2h0BRJ1c2VyTGFzdFN0YWtlQmxvY2sCByBibG9ja3MEE3Jvb3RDb250cmFjdEFkZHJlc3MJARFAZXh0ck5hdGl2ZSgxMDU4KQEFFnJvb3RDb250cmFjdEFkZHJlc3NLZXkEFmN1cnJlbnRUb3RhbFBvb2xTdGFrZWQJAQt2YWx1ZU9yRWxzZQIJAJ8IAQUSdG90YWxQb29sU3Rha2VkS2V5AAAEEHBvb2xTdGFrZUFzc2V0SWQJARFAZXh0ck5hdGl2ZSgxMDU4KQEFE3Bvb2xTdGFrZUFzc2V0SWRLZXkEBnJlc3VsdAMJAGYCCQCxAgEFE3Jvb3RDb250cmFjdEFkZHJlc3MAAAkA/AcECQEHQWRkcmVzcwEJANkEAQUTcm9vdENvbnRyYWN0QWRkcmVzcwIPd2l0aGRyYXdQb29sTHBzCQDMCAIFBmFtb3VudAUDbmlsBQNuaWwFBHVuaXQDCQAAAgUGcmVzdWx0BQZyZXN1bHQEC25ld1VzZXJEYXRhCQDMCAIJAKQDAQkAZQIFFXVzZXJUb3RhbFN0YWtlZEFtb3VudAUGYW1vdW50CQDRCAIFCHVzZXJEYXRhAAAJAM0IAgkAzAgCCQEMSW50ZWdlckVudHJ5AgUSdG90YWxQb29sU3Rha2VkS2V5CQBlAgUWY3VycmVudFRvdGFsUG9vbFN0YWtlZAUGYW1vdW50CQDMCAIJAQ5TY3JpcHRUcmFuc2ZlcgMJAQdBZGRyZXNzAQgIBQFpBmNhbGxlcgVieXRlcwUGYW1vdW50CQDZBAEFEHBvb2xTdGFrZUFzc2V0SWQFA25pbAMJAAACCQBlAgUVdXNlclRvdGFsU3Rha2VkQW1vdW50BQZhbW91bnQAAAkBC0RlbGV0ZUVudHJ5AQUNY2FsbGVyQWRkcmVzcwkBC1N0cmluZ0VudHJ5AgUNY2FsbGVyQWRkcmVzcwkAuQkCBQtuZXdVc2VyRGF0YQUDU0VQCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBDGNsYWltUmV3YXJkcwAEDWNhbGxlckFkZHJlc3MJANgEAQgIBQFpBmNhbGxlcgVieXRlcwMJAQEhAQkBGmlzVXNlckhhdmVVbmNsYWltZWRSZXdhcmRzAQUNY2FsbGVyQWRkcmVzcwkAAgECI05vdGhpbmcgdG8gY2xhaW0sIG9yIHVzZXIgbm90IGZvdW5kBBJwb29sQ3VycmVudENsYWltSWQJARFAZXh0ck5hdGl2ZSgxMDU1KQEFFXBvb2xDdXJyZW50Q2xhaW1JZEtleQQmdG90YWxQb29sRWFybmVkUmV3YXJkc0Zvck9uZVN0YWtlVG9rZW4JARFAZXh0ck5hdGl2ZSgxMDU1KQEFEnRvdGFsUG9vbEVhcm5lZEtleQQIdXNlckRhdGEJALUJAgkBEUBleHRyTmF0aXZlKDEwNTgpAQUNY2FsbGVyQWRkcmVzcwUDU0VQBA91c2VyVG90YWxTdGFrZWQJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQh1c2VyRGF0YQAABBd1c2VyVG90YWxSZXdhcmRzQ2xhaW1lZAkBDXBhcnNlSW50VmFsdWUBCQCRAwIFCHVzZXJEYXRhAAEEGHVzZXJMYXN0Q2xhaW1Qb29sQ2xhaW1JZAkBDXBhcnNlSW50VmFsdWUBCQCRAwIFCHVzZXJEYXRhAAIEKXVzZXJBbHJlYWR5Q2xhaW1lZFJld2FyZHNGb3JPbmVTdGFrZVRva2VuCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUIdXNlckRhdGEAAwQpdXNlclVuY2xhaW1lZFBvb2xFYXJuaW5nc0Zvck9uZVN0YWtlVG9rZW4JAGUCBSZ0b3RhbFBvb2xFYXJuZWRSZXdhcmRzRm9yT25lU3Rha2VUb2tlbgUpdXNlckFscmVhZHlDbGFpbWVkUmV3YXJkc0Zvck9uZVN0YWtlVG9rZW4ECXVzZXJDbGFpbQkAawMFKXVzZXJVbmNsYWltZWRQb29sRWFybmluZ3NGb3JPbmVTdGFrZVRva2VuBQ91c2VyVG90YWxTdGFrZWQFBk1VTFQxMAQLbmV3VXNlckRhdGEJALkJAgkAzAgCCQCRAwIFCHVzZXJEYXRhAAAJAMwIAgkApAMBCQBkAgUXdXNlclRvdGFsUmV3YXJkc0NsYWltZWQFCXVzZXJDbGFpbQkAzAgCCQCkAwEFEnBvb2xDdXJyZW50Q2xhaW1JZAkAzAgCCQCkAwEJAGQCBSl1c2VyQWxyZWFkeUNsYWltZWRSZXdhcmRzRm9yT25lU3Rha2VUb2tlbgUpdXNlclVuY2xhaW1lZFBvb2xFYXJuaW5nc0Zvck9uZVN0YWtlVG9rZW4JAMwIAgkAkQMCBQh1c2VyRGF0YQAEBQNuaWwFA1NFUAQNcmV3YXJkQXNzZXRJZAkA2QQBCQERQGV4dHJOYXRpdmUoMTA1OCkBBRByZXdhcmRBc3NldElkS2V5CQDMCAIJAQtTdHJpbmdFbnRyeQIFDWNhbGxlckFkZHJlc3MFC25ld1VzZXJEYXRhCQDMCAIJAQ5TY3JpcHRUcmFuc2ZlcgMIBQFpBmNhbGxlcgUJdXNlckNsYWltBQ1yZXdhcmRBc3NldElkBQNuaWwBaQEQY2xhaW1Qb29sUmV3YXJkcwADCQECIT0CCAgFAWkGY2FsbGVyBWJ5dGVzCQDZBAEJARFAZXh0ck5hdGl2ZSgxMDU4KQEFD2FkbWluQWRkcmVzc0tleQkAAgECCkFkbWluIG9ubHkED3RvdGFsUG9vbFN0YWtlZAkBEUBleHRyTmF0aXZlKDEwNTUpAQUSdG90YWxQb29sU3Rha2VkS2V5BA90b3RhbFBvb2xFYXJuZWQJARFAZXh0ck5hdGl2ZSgxMDU1KQEFEnRvdGFsUG9vbEVhcm5lZEtleQQScG9vbEN1cnJlbnRDbGFpbUlkCQERQGV4dHJOYXRpdmUoMTA1NSkBBRVwb29sQ3VycmVudENsYWltSWRLZXkEDXJld2FyZEFzc2V0SWQJANkEAQkBEUBleHRyTmF0aXZlKDEwNTgpAQUQcmV3YXJkQXNzZXRJZEtleQQTcm9vdENvbnRyYWN0QWRkcmVzcwkBEUBleHRyTmF0aXZlKDEwNTgpAQUWcm9vdENvbnRyYWN0QWRkcmVzc0tleQQXY3VycmVudFJld2FyZE9uQ29udHJhY3QJAPAHAgUEdGhpcwUNcmV3YXJkQXNzZXRJZAMJAAACBRdjdXJyZW50UmV3YXJkT25Db250cmFjdAUXY3VycmVudFJld2FyZE9uQ29udHJhY3QEEXJvb3RDb250cmFjdENsYWltAwkAZgIJALECAQUTcm9vdENvbnRyYWN0QWRkcmVzcwAACQD8BwQJAQdBZGRyZXNzAQkA2QQBBRNyb290Q29udHJhY3RBZGRyZXNzAhBjbGFpbVBvb2xSZXdhcmRzBQNuaWwFA25pbAUEdW5pdAMJAAACBRFyb290Q29udHJhY3RDbGFpbQURcm9vdENvbnRyYWN0Q2xhaW0EE25ld1Jld2FyZE9uQ29udHJhY3QJAPAHAgUEdGhpcwUNcmV3YXJkQXNzZXRJZAQhY3VycmVudEFkZGl0aW9uYWxVbmNsYWltZWRSZXdhcmRzCQERQGV4dHJOYXRpdmUoMTA1NSkBBShwb29sQ3VycmVudFVuY2xhaW1lZEFkZGl0aW9uYWxSZXdhcmRzS2V5BBNjbGFpbWVkUmV3YXJkQW1vdW50CQBkAgkAZQIFE25ld1Jld2FyZE9uQ29udHJhY3QFF2N1cnJlbnRSZXdhcmRPbkNvbnRyYWN0BSFjdXJyZW50QWRkaXRpb25hbFVuY2xhaW1lZFJld2FyZHMDCQAAAgUTY2xhaW1lZFJld2FyZEFtb3VudAAABQNuaWwEJmN1cnJlbnRDbGFpbUlkRWFybmluZ3NGb3JPbmVTdGFrZVRva2VuCQBrAwUTY2xhaW1lZFJld2FyZEFtb3VudAUGTVVMVDEwBQ90b3RhbFBvb2xTdGFrZWQJAMwIAgkBDEludGVnZXJFbnRyeQIFFXBvb2xDdXJyZW50Q2xhaW1JZEtleQkAZAIFEnBvb2xDdXJyZW50Q2xhaW1JZAABCQDMCAIJAQxJbnRlZ2VyRW50cnkCBRJ0b3RhbFBvb2xFYXJuZWRLZXkJAGQCBQ90b3RhbFBvb2xFYXJuZWQFJmN1cnJlbnRDbGFpbUlkRWFybmluZ3NGb3JPbmVTdGFrZVRva2VuCQDMCAIJAQxJbnRlZ2VyRW50cnkCBShwb29sQ3VycmVudFVuY2xhaW1lZEFkZGl0aW9uYWxSZXdhcmRzS2V5AAAFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpARdyZWNlaXZlQWRkaXRpb25hbFJld2FyZAADCQECIT0CCQCQAwEIBQFpCHBheW1lbnRzAAEJAAIBAhRPbmUgUGF5bWVudCBleHBlY3RlZAQHcGF5bWVudAkBCWFzUGF5bWVudAEJAJEDAggFAWkIcGF5bWVudHMAAAQNcmV3YXJkQXNzZXRJZAkA2QQBCQERQGV4dHJOYXRpdmUoMTA1OCkBBRByZXdhcmRBc3NldElkS2V5AwMJAQIhPQIIBQdwYXltZW50B2Fzc2V0SWQFDXJld2FyZEFzc2V0SWQGCQBnAgAACAUHcGF5bWVudAZhbW91bnQJAAIBAihXcm9uZyByZXdhcmQgYXNzZXQgaWQgb3IgbmVnYXRpdmUgYW1vdW50BCFjdXJyZW50VW5jbGFpbWVkQWRkaXRpb25hbFJld2FyZHMJARFAZXh0ck5hdGl2ZSgxMDU1KQEFKHBvb2xDdXJyZW50VW5jbGFpbWVkQWRkaXRpb25hbFJld2FyZHNLZXkJAMwIAgkBDEludGVnZXJFbnRyeQIFKHBvb2xDdXJyZW50VW5jbGFpbWVkQWRkaXRpb25hbFJld2FyZHNLZXkJAGQCBSFjdXJyZW50VW5jbGFpbWVkQWRkaXRpb25hbFJld2FyZHMIBQdwYXltZW50BmFtb3VudAUDbmlsAQJ0eAEGdmVyaWZ5AAkA9AMDCAUCdHgJYm9keUJ5dGVzCQCRAwIIBQJ0eAZwcm9vZnMAAAgFAnR4D3NlbmRlclB1YmxpY0tleVL+lcc=", "height": 2774809, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: none Next: none Full:
Old | New | Differences | |
---|---|---|---|
1 | - | # no script | |
1 | + | {-# STDLIB_VERSION 6 #-} | |
2 | + | {-# SCRIPT_TYPE ACCOUNT #-} | |
3 | + | {-# CONTENT_TYPE DAPP #-} | |
4 | + | let MULT10 = 10000000000 | |
5 | + | ||
6 | + | let SEP = "__" | |
7 | + | ||
8 | + | let isConstructedKey = "is_constructed" | |
9 | + | ||
10 | + | let withdrawalLockPeriodKey = "withdrawal_lock_period" | |
11 | + | ||
12 | + | let rewardAssetIdKey = "reward_asset_id" | |
13 | + | ||
14 | + | let poolStakeAssetIdKey = "pool_stake_asset_id" | |
15 | + | ||
16 | + | let rootContractAddressKey = "root_contract_address" | |
17 | + | ||
18 | + | let adminAddressKey = "admin_address_key" | |
19 | + | ||
20 | + | let totalPoolStakedKey = "total_pool__staked" | |
21 | + | ||
22 | + | let totalPoolEarnedKey = "total_pool_earned" | |
23 | + | ||
24 | + | let poolCurrentClaimIdKey = "pool_current_claim_id" | |
25 | + | ||
26 | + | let poolCurrentUnclaimedAdditionalRewardsKey = "pool_current_unclaimed_additional_rewards" | |
27 | + | ||
28 | + | func asPayment (v) = match v { | |
29 | + | case p: AttachedPayment => | |
30 | + | p | |
31 | + | case _ => | |
32 | + | throw("fail to cast into AttachedPayment") | |
33 | + | } | |
34 | + | ||
35 | + | ||
36 | + | func isUserHaveUnclaimedRewards (address) = if (!(isDefined(getString(address)))) | |
37 | + | then false | |
38 | + | else { | |
39 | + | let currentPoolClaimId = getIntegerValue(poolCurrentClaimIdKey) | |
40 | + | let userData = split(getStringValue(address), SEP) | |
41 | + | let userLastClaimedRewardsAtPoolClaimId = parseIntValue(userData[2]) | |
42 | + | (currentPoolClaimId > userLastClaimedRewardsAtPoolClaimId) | |
43 | + | } | |
44 | + | ||
45 | + | ||
46 | + | @Callable(i) | |
47 | + | func constructor (rewardAssetId,poolStakeAssetId,withdrawalLockPeriod,rootContract,adminContract) = if (isDefined(getBoolean(isConstructedKey))) | |
48 | + | then throw("Constructor can be called one time") | |
49 | + | else [BooleanEntry(isConstructedKey, true), IntegerEntry(poolCurrentUnclaimedAdditionalRewardsKey, 0), StringEntry(rewardAssetIdKey, rewardAssetId), StringEntry(poolStakeAssetIdKey, poolStakeAssetId), StringEntry(rootContractAddressKey, rootContract), StringEntry(adminAddressKey, adminContract), IntegerEntry(totalPoolEarnedKey, 0), IntegerEntry(poolCurrentClaimIdKey, 0), IntegerEntry(totalPoolStakedKey, 0), IntegerEntry(withdrawalLockPeriodKey, withdrawalLockPeriod)] | |
50 | + | ||
51 | + | ||
52 | + | ||
53 | + | @Callable(i) | |
54 | + | func stake () = if ((size(i.payments) != 1)) | |
55 | + | then throw("One Payment expected") | |
56 | + | else { | |
57 | + | let callerAddress = toBase58String(i.caller.bytes) | |
58 | + | let payment = asPayment(i.payments[0]) | |
59 | + | let poolStakeAssetId = fromBase58String(getStringValue(poolStakeAssetIdKey)) | |
60 | + | if (if ((payment.assetId != poolStakeAssetId)) | |
61 | + | then true | |
62 | + | else (0 >= payment.amount)) | |
63 | + | then throw("Wrong asset id or negative amount") | |
64 | + | else if (isUserHaveUnclaimedRewards(callerAddress)) | |
65 | + | then throw("You have unclaimed rewards on contract, claim them first") | |
66 | + | else { | |
67 | + | let currentPoolClaimId = getIntegerValue(poolCurrentClaimIdKey) | |
68 | + | let currentTotalPoolStaked = getIntegerValue(totalPoolStakedKey) | |
69 | + | let currentTotalPoolRewardsEarnedForOneStakeToken = getIntegerValue(totalPoolEarnedKey) | |
70 | + | let rootContractAddress = getStringValue(rootContractAddressKey) | |
71 | + | let result = if ((size(rootContractAddress) > 0)) | |
72 | + | then invoke(Address(fromBase58String(rootContractAddress)), "stakePoolLps", nil, [payment]) | |
73 | + | else unit | |
74 | + | if ((result == result)) | |
75 | + | then { | |
76 | + | let userDataStr = valueOrElse(getString(callerAddress), "") | |
77 | + | let userData = if ((size(userDataStr) > 0)) | |
78 | + | then { | |
79 | + | let userData = split(userDataStr, SEP) | |
80 | + | let userTotalStakedAmount = parseIntValue(userData[0]) | |
81 | + | makeString([toString((userTotalStakedAmount + payment.amount)), userData[1], userData[2], userData[3], toString(height)], SEP) | |
82 | + | } | |
83 | + | else makeString([toString(payment.amount), "0", toString(currentPoolClaimId), toString(currentTotalPoolRewardsEarnedForOneStakeToken), toString(height)], SEP) | |
84 | + | [StringEntry(callerAddress, userData), IntegerEntry(totalPoolStakedKey, (currentTotalPoolStaked + payment.amount))] | |
85 | + | } | |
86 | + | else throw("Strict value is not equal to itself.") | |
87 | + | } | |
88 | + | } | |
89 | + | ||
90 | + | ||
91 | + | ||
92 | + | @Callable(i) | |
93 | + | func withdraw (amount) = if ((0 >= amount)) | |
94 | + | then throw("Amount must be positive") | |
95 | + | else { | |
96 | + | let callerAddress = toBase58String(i.caller.bytes) | |
97 | + | if (isUserHaveUnclaimedRewards(callerAddress)) | |
98 | + | then throw("You have unclaimed rewards on contract, claim them first") | |
99 | + | else { | |
100 | + | let userData = split(valueOrErrorMessage(getString(callerAddress), "User not found"), SEP) | |
101 | + | let userTotalStakedAmount = parseIntValue(userData[0]) | |
102 | + | if ((amount > userTotalStakedAmount)) | |
103 | + | then throw("Insufficient funds") | |
104 | + | else { | |
105 | + | let withdrawalLockPeriod = getIntegerValue(withdrawalLockPeriodKey) | |
106 | + | let userLastStakeBlock = parseIntValue(userData[4]) | |
107 | + | if (if ((withdrawalLockPeriod > 0)) | |
108 | + | then (withdrawalLockPeriod > (height - userLastStakeBlock)) | |
109 | + | else false) | |
110 | + | then throw((("This pool have lock period. You need to wait " + toString((withdrawalLockPeriod - (height - userLastStakeBlock)))) + " blocks")) | |
111 | + | else { | |
112 | + | let rootContractAddress = getStringValue(rootContractAddressKey) | |
113 | + | let currentTotalPoolStaked = valueOrElse(getInteger(totalPoolStakedKey), 0) | |
114 | + | let poolStakeAssetId = getStringValue(poolStakeAssetIdKey) | |
115 | + | let result = if ((size(rootContractAddress) > 0)) | |
116 | + | then invoke(Address(fromBase58String(rootContractAddress)), "withdrawPoolLps", [amount], nil) | |
117 | + | else unit | |
118 | + | if ((result == result)) | |
119 | + | then { | |
120 | + | let newUserData = [toString((userTotalStakedAmount - amount)), removeByIndex(userData, 0)] | |
121 | + | ([IntegerEntry(totalPoolStakedKey, (currentTotalPoolStaked - amount)), ScriptTransfer(Address(i.caller.bytes), amount, fromBase58String(poolStakeAssetId))] :+ (if (((userTotalStakedAmount - amount) == 0)) | |
122 | + | then DeleteEntry(callerAddress) | |
123 | + | else StringEntry(callerAddress, makeString(newUserData, SEP)))) | |
124 | + | } | |
125 | + | else throw("Strict value is not equal to itself.") | |
126 | + | } | |
127 | + | } | |
128 | + | } | |
129 | + | } | |
130 | + | ||
131 | + | ||
132 | + | ||
133 | + | @Callable(i) | |
134 | + | func claimRewards () = { | |
135 | + | let callerAddress = toBase58String(i.caller.bytes) | |
136 | + | if (!(isUserHaveUnclaimedRewards(callerAddress))) | |
137 | + | then throw("Nothing to claim, or user not found") | |
138 | + | else { | |
139 | + | let poolCurrentClaimId = getIntegerValue(poolCurrentClaimIdKey) | |
140 | + | let totalPoolEarnedRewardsForOneStakeToken = getIntegerValue(totalPoolEarnedKey) | |
141 | + | let userData = split(getStringValue(callerAddress), SEP) | |
142 | + | let userTotalStaked = parseIntValue(userData[0]) | |
143 | + | let userTotalRewardsClaimed = parseIntValue(userData[1]) | |
144 | + | let userLastClaimPoolClaimId = parseIntValue(userData[2]) | |
145 | + | let userAlreadyClaimedRewardsForOneStakeToken = parseIntValue(userData[3]) | |
146 | + | let userUnclaimedPoolEarningsForOneStakeToken = (totalPoolEarnedRewardsForOneStakeToken - userAlreadyClaimedRewardsForOneStakeToken) | |
147 | + | let userClaim = fraction(userUnclaimedPoolEarningsForOneStakeToken, userTotalStaked, MULT10) | |
148 | + | let newUserData = makeString([userData[0], toString((userTotalRewardsClaimed + userClaim)), toString(poolCurrentClaimId), toString((userAlreadyClaimedRewardsForOneStakeToken + userUnclaimedPoolEarningsForOneStakeToken)), userData[4]], SEP) | |
149 | + | let rewardAssetId = fromBase58String(getStringValue(rewardAssetIdKey)) | |
150 | + | [StringEntry(callerAddress, newUserData), ScriptTransfer(i.caller, userClaim, rewardAssetId)] | |
151 | + | } | |
152 | + | } | |
153 | + | ||
154 | + | ||
155 | + | ||
156 | + | @Callable(i) | |
157 | + | func claimPoolRewards () = if ((i.caller.bytes != fromBase58String(getStringValue(adminAddressKey)))) | |
158 | + | then throw("Admin only") | |
159 | + | else { | |
160 | + | let totalPoolStaked = getIntegerValue(totalPoolStakedKey) | |
161 | + | let totalPoolEarned = getIntegerValue(totalPoolEarnedKey) | |
162 | + | let poolCurrentClaimId = getIntegerValue(poolCurrentClaimIdKey) | |
163 | + | let rewardAssetId = fromBase58String(getStringValue(rewardAssetIdKey)) | |
164 | + | let rootContractAddress = getStringValue(rootContractAddressKey) | |
165 | + | let currentRewardOnContract = assetBalance(this, rewardAssetId) | |
166 | + | if ((currentRewardOnContract == currentRewardOnContract)) | |
167 | + | then { | |
168 | + | let rootContractClaim = if ((size(rootContractAddress) > 0)) | |
169 | + | then invoke(Address(fromBase58String(rootContractAddress)), "claimPoolRewards", nil, nil) | |
170 | + | else unit | |
171 | + | if ((rootContractClaim == rootContractClaim)) | |
172 | + | then { | |
173 | + | let newRewardOnContract = assetBalance(this, rewardAssetId) | |
174 | + | let currentAdditionalUnclaimedRewards = getIntegerValue(poolCurrentUnclaimedAdditionalRewardsKey) | |
175 | + | let claimedRewardAmount = ((newRewardOnContract - currentRewardOnContract) + currentAdditionalUnclaimedRewards) | |
176 | + | if ((claimedRewardAmount == 0)) | |
177 | + | then nil | |
178 | + | else { | |
179 | + | let currentClaimIdEarningsForOneStakeToken = fraction(claimedRewardAmount, MULT10, totalPoolStaked) | |
180 | + | [IntegerEntry(poolCurrentClaimIdKey, (poolCurrentClaimId + 1)), IntegerEntry(totalPoolEarnedKey, (totalPoolEarned + currentClaimIdEarningsForOneStakeToken)), IntegerEntry(poolCurrentUnclaimedAdditionalRewardsKey, 0)] | |
181 | + | } | |
182 | + | } | |
183 | + | else throw("Strict value is not equal to itself.") | |
184 | + | } | |
185 | + | else throw("Strict value is not equal to itself.") | |
186 | + | } | |
187 | + | ||
188 | + | ||
189 | + | ||
190 | + | @Callable(i) | |
191 | + | func receiveAdditionalReward () = if ((size(i.payments) != 1)) | |
192 | + | then throw("One Payment expected") | |
193 | + | else { | |
194 | + | let payment = asPayment(i.payments[0]) | |
195 | + | let rewardAssetId = fromBase58String(getStringValue(rewardAssetIdKey)) | |
196 | + | if (if ((payment.assetId != rewardAssetId)) | |
197 | + | then true | |
198 | + | else (0 >= payment.amount)) | |
199 | + | then throw("Wrong reward asset id or negative amount") | |
200 | + | else { | |
201 | + | let currentUnclaimedAdditionalRewards = getIntegerValue(poolCurrentUnclaimedAdditionalRewardsKey) | |
202 | + | [IntegerEntry(poolCurrentUnclaimedAdditionalRewardsKey, (currentUnclaimedAdditionalRewards + payment.amount))] | |
203 | + | } | |
204 | + | } | |
205 | + | ||
206 | + | ||
207 | + | @Verifier(tx) | |
208 | + | func verify () = sigVerify(tx.bodyBytes, tx.proofs[0], tx.senderPublicKey) | |
209 | + |
github/deemru/w8io/026f985 20.63 ms ◑