tx · CFmF5RQYttpKyuHL7Tm6mCKCG4WKftA6XJweThiqYfhh 3P4YACZAqdzFT1Q1dpmDvz3hHagJ6r9vRKf: -0.01100000 Waves 2022.11.14 17:32 [3382311] smart account 3P4YACZAqdzFT1Q1dpmDvz3hHagJ6r9vRKf > SELF 0.00000000 Waves
{ "type": 13, "id": "CFmF5RQYttpKyuHL7Tm6mCKCG4WKftA6XJweThiqYfhh", "fee": 1100000, "feeAssetId": null, "timestamp": 1668436418000, "version": 1, "sender": "3P4YACZAqdzFT1Q1dpmDvz3hHagJ6r9vRKf", "senderPublicKey": "Ecbo6uH2sySLA4wrfVUbdHFUb6AcAiZAK4jrAg4TqkSa", "proofs": [ "2YqMB1DXFMxCyNLSyPDmWjvnNsgZ5ys11eXDYoNFyVkk8UwvrdW1jBDosnDTmt3fe4EjzqjGyAv4oyaN6rrqZD2w" ], "script": "base64:BgI6CAISABIDCgEBEgASAwoBCBIECgIICBIECgIICBIAEgYKBAgICAESAwoBCBIDCgEEEgMKAQgSAwoBCCYAC01BWF9SRVdBUkRTAAUABW93bmVyCQERQGV4dHJOYXRpdmUoMTA2MikBCQERQGV4dHJOYXRpdmUoMTA1MykCBQR0aGlzAgVvd25lcgAFdG9rZW4JARFAZXh0ck5hdGl2ZSgxMDUzKQIFBHRoaXMCBXRva2VuAAdyZXdhcmRzCQERQGV4dHJOYXRpdmUoMTA1MykCBQR0aGlzAgdyZXdhcmRzAAxyZXdhcmRzX2xpc3QJALUJAgUHcmV3YXJkcwIBLAAGcGVyaW9kCQERQGV4dHJOYXRpdmUoMTA1MCkCBQR0aGlzAgZwZXJpb2QACWlzX2tpbGxlZAkBEUBleHRyTmF0aXZlKDEwNTEpAgUEdGhpcwIJaXNfa2lsbGVkAA1oZWlnaHRBZGRyZXNzCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKYIAQkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCdCAIFBHRoaXMCDWhlaWdodEFkZHJlc3MCE25vIHNldHRpbmdzIGRlZmluZWQCFGJhZCBzZXR0aW5ncyBhZGRyZXNzAAZIRUlHSFQFBmhlaWdodAAPc3luY19oZWlnaHRfa2V5AgtzeW5jX2hlaWdodAALc3luY19oZWlnaHQJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwUPc3luY19oZWlnaHRfa2V5AAAAEHRva2VuX2Ftb3VudF9rZXkCBnRva2VucwAMdG9rZW5fYW1vdW50CQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMFEHRva2VuX2Ftb3VudF9rZXkAAAEPdXNlcl9hbW91bnRfa2V5AQR1c2VyCQCsAgIFBHVzZXICB19hbW91bnQBC3VzZXJfYW1vdW50AQR1c2VyCQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMJAQ91c2VyX2Ftb3VudF9rZXkBBQR1c2VyAAABF3VzZXJfYXNzZXRfYWRqdXN0ZWRfa2V5AgR1c2VyBWFzc2V0CQCsAgIJAKwCAgkArAICBQR1c2VyAgFfBQVhc3NldAIJX2FkanVzdGVkARN1c2VyX2Fzc2V0X2FkanVzdGVkAgR1c2VyBWFzc2V0CQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMJARd1c2VyX2Fzc2V0X2FkanVzdGVkX2tleQIFBHVzZXIFBWFzc2V0AAABFnVzZXJfYXNzZXRfY2xhaW1lZF9rZXkCBHVzZXIFYXNzZXQJAKwCAgkArAICCQCsAgIFBHVzZXICAV8FBWFzc2V0AghfY2xhaW1lZAESdXNlcl9hc3NldF9jbGFpbWVkAgR1c2VyBWFzc2V0CQELdmFsdWVPckVsc2UCCQCaCAIFBHRoaXMJARZ1c2VyX2Fzc2V0X2NsYWltZWRfa2V5AgUEdXNlcgUFYXNzZXQAAAEQYXNzZXRfcmV3YXJkX2tleQEFYXNzZXQJAKwCAgUFYXNzZXQCB19yZXdhcmQBDGFzc2V0X3Jld2FyZAEFYXNzZXQJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwkBEGFzc2V0X3Jld2FyZF9rZXkBBQVhc3NldAAAAQ9hc3NldF9zcGVlZF9rZXkBBWFzc2V0CQCsAgIFBWFzc2V0AgZfc3BlZWQBC2Fzc2V0X3NwZWVkAQVhc3NldAkBC3ZhbHVlT3JFbHNlAgkAmggCBQR0aGlzCQEPYXNzZXRfc3BlZWRfa2V5AQUFYXNzZXQAAAEOYXNzZXRfbGVmdF9rZXkBBWFzc2V0CQCsAgIFBWFzc2V0AgVfbGVmdAEKYXNzZXRfbGVmdAEFYXNzZXQJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwkBDmFzc2V0X2xlZnRfa2V5AQUFYXNzZXQAAAERYXNzZXRfY29udHJvbF9rZXkBBWFzc2V0CQCsAgIFBWFzc2V0AghfY29udHJvbAENYXNzZXRfY29udHJvbAEFYXNzZXQJAQt2YWx1ZU9yRWxzZQIJAJoIAgUEdGhpcwkBEWFzc2V0X2NvbnRyb2xfa2V5AQUFYXNzZXQAAAEMY2hlY2tBZGRyZXNzAQNhNTgEAWEJARFAZXh0ck5hdGl2ZSgxMDYyKQEFA2E1OAkApQgBBQFhAQpjaGVja0Fzc2V0AQdhc3NldDU4AwkAAAIFB2Fzc2V0NTgCBVdBVkVTAgVXQVZFUwQFYXNzZXQJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkA2QQBBQdhc3NldDU4CQCsAgICFndyb25nIGFzc2V0IGVuY29kaW5nOiAFB2Fzc2V0NTgEBGluZm8JARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkA7AcBBQVhc3NldAkArAICAhJ3cm9uZyBhc3NldCBpbmZvOiAFB2Fzc2V0NTgDCQAAAgUEaW5mbwUEaW5mbwUHYXNzZXQ1OAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgEFYXNzZXQBAWEDCQAAAgUBYQIFV0FWRVMFBHVuaXQJANkEAQUBYQEMYXNzZXRfc3RyaW5nAQFhBAckbWF0Y2gwBQFhAwkAAQIFByRtYXRjaDACCkJ5dGVWZWN0b3IEAWIFByRtYXRjaDAJANgEAQUBYgIFV0FWRVMBDWFzc2V0X2JhbGFuY2UBAWEDCQAAAgUBYQIFV0FWRVMICQDvBwEFBHRoaXMJYXZhaWxhYmxlCQDwBwIFBHRoaXMJANkEAQUBYQEMc3RvcF9yZXdhcmRzAAoBBGZvbGQCA2FjYwVhc3NldAkAzggCBQNhY2MJAMwIAgkBDEludGVnZXJFbnRyeQIJAQ9hc3NldF9zcGVlZF9rZXkBBQVhc3NldAAABQNuaWwKAAIkbAUMcmV3YXJkc19saXN0CgACJHMJAJADAQUCJGwKAAUkYWNjMAUDbmlsCgEFJGYwXzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAQRmb2xkAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGYwXzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhNMaXN0IHNpemUgZXhjZWVkcyA1CQEFJGYwXzICCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECBQUkYWNjMAAAAAEAAgADAAQABQEQY2hlY2twb2ludF9hc3NldAIDYWNjBWFzc2V0BA1fYXNzZXRfcmV3YXJkCQEMYXNzZXRfcmV3YXJkAQUFYXNzZXQEDF9hc3NldF9zcGVlZAkBC2Fzc2V0X3NwZWVkAQUFYXNzZXQEC19hc3NldF9sZWZ0CQEKYXNzZXRfbGVmdAEFBWFzc2V0BA9lc3RpbWF0ZV9yZXdhcmQJAGgCCQBlAgUGSEVJR0hUBQtzeW5jX2hlaWdodAUMX2Fzc2V0X3NwZWVkBAtyZWFsX3Jld2FyZAMJAGYCBQ9lc3RpbWF0ZV9yZXdhcmQFC19hc3NldF9sZWZ0BQtfYXNzZXRfbGVmdAUPZXN0aW1hdGVfcmV3YXJkBBJjbGFpbV9hc3NldF9yZXdhcmQJAGQCBQ1fYXNzZXRfcmV3YXJkBQtyZWFsX3Jld2FyZAQQY2xhaW1fYXNzZXRfbGVmdAkAZQIFC19hc3NldF9sZWZ0BQtyZWFsX3Jld2FyZAQRY2xhaW1fYXNzZXRfc3BlZWQDCQBmAgUQY2xhaW1fYXNzZXRfbGVmdAAABQxfYXNzZXRfc3BlZWQAAAQNcmV3YXJkX2FjdGlvbgMJAAACBRJjbGFpbV9hc3NldF9yZXdhcmQFDV9hc3NldF9yZXdhcmQFA25pbAkAzAgCCQEMSW50ZWdlckVudHJ5AgkBEGFzc2V0X3Jld2FyZF9rZXkBBQVhc3NldAUSY2xhaW1fYXNzZXRfcmV3YXJkBQNuaWwEDl9hc3NldF9iYWxhbmNlCQENYXNzZXRfYmFsYW5jZQEFBWFzc2V0BA5fYXNzZXRfY29udHJvbAkBDWFzc2V0X2NvbnRyb2wBBQVhc3NldAMJAGYCBQ5fYXNzZXRfY29udHJvbAUOX2Fzc2V0X2JhbGFuY2UJAAIBCQCsAgIJAKwCAgkArAICCQCsAgIFBWFzc2V0AhsgYmFsYW5jZSBsZWFrYWdlIGRldGVjdGVkOiAJAKQDAQUOX2Fzc2V0X2NvbnRyb2wCAyA+IAkApAMBBQ5fYXNzZXRfYmFsYW5jZQQScGVyaW9kX25ld19iYWxhbmNlCQBlAgUOX2Fzc2V0X2JhbGFuY2UFDl9hc3NldF9jb250cm9sBBRwZXJpb2RfYXNzZXRfYmFsYW5jZQkAZAIFEGNsYWltX2Fzc2V0X2xlZnQFEnBlcmlvZF9uZXdfYmFsYW5jZQQScGVyaW9kX2Fzc2V0X3NwZWVkCQBpAgUUcGVyaW9kX2Fzc2V0X2JhbGFuY2UFBnBlcmlvZAMDCQBnAgURY2xhaW1fYXNzZXRfc3BlZWQFEnBlcmlvZF9hc3NldF9zcGVlZAkAZwIFEGNsYWltX2Fzc2V0X2xlZnQFEnBlcmlvZF9uZXdfYmFsYW5jZQcEDHNwZWVkX2FjdGlvbgMJAAACBRFjbGFpbV9hc3NldF9zcGVlZAUMX2Fzc2V0X3NwZWVkBQNuaWwJAMwIAgkBDEludGVnZXJFbnRyeQIJAQ9hc3NldF9zcGVlZF9rZXkBBQVhc3NldAURY2xhaW1fYXNzZXRfc3BlZWQFA25pbAQLbGVmdF9hY3Rpb24DCQAAAgUQY2xhaW1fYXNzZXRfbGVmdAULX2Fzc2V0X2xlZnQFA25pbAkAzAgCCQEMSW50ZWdlckVudHJ5AgkBDmFzc2V0X2xlZnRfa2V5AQUFYXNzZXQFEGNsYWltX2Fzc2V0X2xlZnQFA25pbAkAzggCCQDOCAIJAM4IAgUDYWNjBQ1yZXdhcmRfYWN0aW9uBQxzcGVlZF9hY3Rpb24FC2xlZnRfYWN0aW9uBBFwZXJpb2RfYXNzZXRfbGVmdAkAaAIFEnBlcmlvZF9hc3NldF9zcGVlZAUGcGVyaW9kBBFwZXJpb2RfYXNzZXRfZHVzdAkAZQIFFHBlcmlvZF9hc3NldF9iYWxhbmNlBRFwZXJpb2RfYXNzZXRfbGVmdAQTcGVyaW9kX2Fzc2V0X2NvbnRvbAkAZQIFDl9hc3NldF9iYWxhbmNlBRFwZXJpb2RfYXNzZXRfZHVzdAkAzggCCQDOCAIFA2FjYwUNcmV3YXJkX2FjdGlvbgkAzAgCCQEMSW50ZWdlckVudHJ5AgkBD2Fzc2V0X3NwZWVkX2tleQEFBWFzc2V0BRJwZXJpb2RfYXNzZXRfc3BlZWQJAMwIAgkBDEludGVnZXJFbnRyeQIJAQ5hc3NldF9sZWZ0X2tleQEFBWFzc2V0BRFwZXJpb2RfYXNzZXRfbGVmdAkAzAgCCQEMSW50ZWdlckVudHJ5AgkBEWFzc2V0X2NvbnRyb2xfa2V5AQUFYXNzZXQFE3BlcmlvZF9hc3NldF9jb250b2wFA25pbAEEc3luYwADBQlpc19raWxsZWQFA25pbAkA/AcEBQR0aGlzAgpjaGVja3BvaW50BQNuaWwFA25pbAESY2hlY2twb2ludF9hY3Rpb25zAAQLc3luY19hY3Rpb24DCQAAAgULc3luY19oZWlnaHQFBkhFSUdIVAUDbmlsCQDMCAIJAQxJbnRlZ2VyRW50cnkCBQ9zeW5jX2hlaWdodF9rZXkFBkhFSUdIVAUDbmlsCQDOCAIFC3N5bmNfYWN0aW9uCgACJGwFDHJld2FyZHNfbGlzdAoAAiRzCQCQAwEFAiRsCgAFJGFjYzAFA25pbAoBBSRmMF8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQEQY2hlY2twb2ludF9hc3NldAIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmMF8yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQITTGlzdCBzaXplIGV4Y2VlZHMgNQkBBSRmMF8yAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgUFJGFjYzAAAAABAAIAAwAEAAUBC3VwZGF0ZV91c2VyAgR1c2VyBmNoYW5nZQQPbmV3X3VzZXJfYW1vdW50CQBkAgkBC3VzZXJfYW1vdW50AQUEdXNlcgUGY2hhbmdlAwkAZgIAAAUPbmV3X3VzZXJfYW1vdW50CQACAQkArAICCQCsAgIJAKwCAgIMYmFkIGFtb3VudDogCQCkAwEFBmNoYW5nZQIULCBhdmFpbGFibGUgYW1vdW50OiAJAKQDAQkBC3VzZXJfYW1vdW50AQUEdXNlcgQQbmV3X3Rva2VuX2Ftb3VudAkAZAIFDHRva2VuX2Ftb3VudAUGY2hhbmdlAwkAZgIFEG5ld190b2tlbl9hbW91bnQJAQ1hc3NldF9iYWxhbmNlAQUFdG9rZW4JAAIBCQCsAgIJAKwCAgkArAICAiB0b2tlbiBiYWxhbmNlIGxlYWthZ2UgZGV0ZWN0ZWQ6IAkApAMBBRBuZXdfdG9rZW5fYW1vdW50AgMgPiAJAKQDAQkBDWFzc2V0X2JhbGFuY2UBBQV0b2tlbgQBcwkBBHN5bmMAAwkAAAIFAXMFAXMKAQRmb2xkAgNhY2MFYXNzZXQJAM4IAgUDYWNjBA1fYXNzZXRfcmV3YXJkCQEMYXNzZXRfcmV3YXJkAQUFYXNzZXQEFF91c2VyX2Fzc2V0X2FkanVzdGVkCQETdXNlcl9hc3NldF9hZGp1c3RlZAIFBHVzZXIFBWFzc2V0BBBuZXdfYXNzZXRfcmV3YXJkAwkAAAIFDHRva2VuX2Ftb3VudAAABQ1fYXNzZXRfcmV3YXJkCQBrAwUNX2Fzc2V0X3Jld2FyZAUQbmV3X3Rva2VuX2Ftb3VudAUMdG9rZW5fYW1vdW50BBduZXdfdXNlcl9hc3NldF9hZGp1c3RlZAkAZAIFFF91c2VyX2Fzc2V0X2FkanVzdGVkAwkAAAIFEG5ld190b2tlbl9hbW91bnQAAAUNX2Fzc2V0X3Jld2FyZAkBAS0BCQBrAwUQbmV3X2Fzc2V0X3Jld2FyZAUGY2hhbmdlBRBuZXdfdG9rZW5fYW1vdW50BA1yZXdhcmRfYWN0aW9uAwkAAAIFDV9hc3NldF9yZXdhcmQFEG5ld19hc3NldF9yZXdhcmQFA25pbAkAzAgCCQEMSW50ZWdlckVudHJ5AgkBEGFzc2V0X3Jld2FyZF9rZXkBBQVhc3NldAUQbmV3X2Fzc2V0X3Jld2FyZAUDbmlsBA1hZGp1c3RfYWN0aW9uAwkAAAIFFF91c2VyX2Fzc2V0X2FkanVzdGVkBRduZXdfdXNlcl9hc3NldF9hZGp1c3RlZAUDbmlsCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEXdXNlcl9hc3NldF9hZGp1c3RlZF9rZXkCBQR1c2VyBQVhc3NldAUXbmV3X3VzZXJfYXNzZXRfYWRqdXN0ZWQFA25pbAkAzggCBQ1yZXdhcmRfYWN0aW9uBQ1hZGp1c3RfYWN0aW9uBAxzdG9wX2FjdGlvbnMDCQAAAgUQbmV3X3Rva2VuX2Ftb3VudAAACQEMc3RvcF9yZXdhcmRzAAUDbmlsCQDOCAIJAM4IAgkAzAgCCQEMSW50ZWdlckVudHJ5AgUQdG9rZW5fYW1vdW50X2tleQUQbmV3X3Rva2VuX2Ftb3VudAkAzAgCCQEMSW50ZWdlckVudHJ5AgkBD3VzZXJfYW1vdW50X2tleQEFBHVzZXIFD25ld191c2VyX2Ftb3VudAUDbmlsCgACJGwFDHJld2FyZHNfbGlzdAoAAiRzCQCQAwEFAiRsCgAFJGFjYzAFA25pbAoBBSRmMF8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQEEZm9sZAIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmMF8yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQITTGlzdCBzaXplIGV4Y2VlZHMgNQkBBSRmMF8yAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgUFJGFjYzAAAAABAAIAAwAEAAUFDHN0b3BfYWN0aW9ucwkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgEQY2hlY2tSZXdhcmRzTGlzdAIIX3Jld2FyZHMGX3Rva2VuBA1fcmV3YXJkc19saXN0CQC1CQIFCF9yZXdhcmRzAgEsAwkAZgIJAJADAQUNX3Jld2FyZHNfbGlzdAULTUFYX1JFV0FSRFMJAAIBAhB0b28gbWFueSByZXdhcmRzCgEEZm9sZAIDYWNjBWFzc2V0AwkAAAIJAQpjaGVja0Fzc2V0AQUFYXNzZXQFBl90b2tlbgkAAgECGnJld2FyZCBjYW5ub3QgYmUgdGhlIHRva2VuAwkBD2NvbnRhaW5zRWxlbWVudAIFA2FjYwUFYXNzZXQJAAIBAhlkdXBsaWNhdGVkIHJld2FyZCBpbiBsaXN0CQDOCAIFA2FjYwkAzAgCBQVhc3NldAUDbmlsCQC5CQIKAAIkbAUNX3Jld2FyZHNfbGlzdAoAAiRzCQCQAwEFAiRsCgAFJGFjYzAFA25pbAoBBSRmMF8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQEEZm9sZAIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmMF8yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQITTGlzdCBzaXplIGV4Y2VlZHMgNQkBBSRmMF8yAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgUFJGFjYzAAAAABAAIAAwAEAAUCASwMA21zZwEHZGVwb3NpdAADCQECIT0CCQCQAwEIBQNtc2cIcGF5bWVudHMAAQkAAgECI3dyb25nIHBheW1lbnRzLCBzaG91bGQgYmUgMSBwYXltZW50BAdwYXltZW50CQCRAwIIBQNtc2cIcGF5bWVudHMAAAMJAQIhPQIJAQxhc3NldF9zdHJpbmcBCAUHcGF5bWVudAdhc3NldElkBQV0b2tlbgkAAgEJAKwCAgkArAICCQCsAgICDXdyb25nIHRva2VuOiAJAQxhc3NldF9zdHJpbmcBCAUHcGF5bWVudAdhc3NldElkAgQgIT0gBQV0b2tlbgMJAGcCAAAIBQdwYXltZW50BmFtb3VudAkAAgECIHdyb25nIGFtb3VudCwgc2hvdWxkIGJlIHBvc2l0aXZlCQELdXBkYXRlX3VzZXICCQClCAEIBQNtc2cGY2FsbGVyCAUHcGF5bWVudAZhbW91bnQDbXNnAQh3aXRoZHJhdwEGYW1vdW50AwkBAiE9AgkAkAMBCAUDbXNnCHBheW1lbnRzAAAJAAIBAh93cm9uZyBwYXltZW50cywgc2hvdWxkIGJlIGVtcHR5AwkAZwIAAAUGYW1vdW50CQACAQIgd3JvbmcgYW1vdW50LCBzaG91bGQgYmUgcG9zaXRpdmUJAM4IAgkBC3VwZGF0ZV91c2VyAgkApQgBCAUDbXNnBmNhbGxlcgkBAS0BBQZhbW91bnQJAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwgFA21zZwZjYWxsZXIFBmFtb3VudAkBBWFzc2V0AQUFdG9rZW4FA25pbANtc2cBBWNsYWltAAMJAQIhPQIJAJADAQgFA21zZwhwYXltZW50cwAACQACAQIfd3JvbmcgcGF5bWVudHMsIHNob3VsZCBiZSBlbXB0eQQBcwMJAGYCBQx0b2tlbl9hbW91bnQAAAkBBHN5bmMABQNuaWwDCQAAAgUBcwUBcwQEdXNlcgkApQgBCAUDbXNnBmNhbGxlcgoBBGZvbGQCA2FjYwVhc3NldAkAzggCBQNhY2MEDV9hc3NldF9yZXdhcmQJAQxhc3NldF9yZXdhcmQBBQVhc3NldAQLYWNjdW11bGF0ZWQJAGQCCQETdXNlcl9hc3NldF9hZGp1c3RlZAIFBHVzZXIFBWFzc2V0AwkAAAIFDHRva2VuX2Ftb3VudAAAAAAJAGsDBQ1fYXNzZXRfcmV3YXJkCQELdXNlcl9hbW91bnQBBQR1c2VyBQx0b2tlbl9hbW91bnQEB2NsYWltZWQJARJ1c2VyX2Fzc2V0X2NsYWltZWQCBQR1c2VyBQVhc3NldAQGYW1vdW50CQBlAgULYWNjdW11bGF0ZWQFB2NsYWltZWQDCQAAAgUGYW1vdW50AAAFA25pbAMJAGYCAAAFBmFtb3VudAkAAgEJAKwCAgkArAICBQVhc3NldAIcIGJhZCBjbGFpbSBhbW91bnQgZGV0ZWN0ZWQ6IAkApAMBBQZhbW91bnQEDl9hc3NldF9jb250cm9sCQENYXNzZXRfY29udHJvbAEFBWFzc2V0CQDMCAIJAQ5TY3JpcHRUcmFuc2ZlcgMIBQNtc2cGY2FsbGVyBQZhbW91bnQJAQVhc3NldAEFBWFzc2V0CQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEWdXNlcl9hc3NldF9jbGFpbWVkX2tleQIFBHVzZXIFBWFzc2V0CQBkAgUHY2xhaW1lZAUGYW1vdW50CQDMCAIJAQxJbnRlZ2VyRW50cnkCCQERYXNzZXRfY29udHJvbF9rZXkBBQVhc3NldAkAZQIFDl9hc3NldF9jb250cm9sBQZhbW91bnQFA25pbAQNY2xhaW1fYWN0aW9ucwoAAiRsBQxyZXdhcmRzX2xpc3QKAAIkcwkAkAMBBQIkbAoABSRhY2MwBQNuaWwKAQUkZjBfMQICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkBBGZvbGQCBQIkYQkAkQMCBQIkbAUCJGkKAQUkZjBfMgICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkAAgECE0xpc3Qgc2l6ZSBleGNlZWRzIDUJAQUkZjBfMgIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIFBSRhY2MwAAAAAQACAAMABAAFAwkAAAIJAJADAQUNY2xhaW1fYWN0aW9ucwAACQACAQIQbm90aGluZyB0byBjbGFpbQUNY2xhaW1fYWN0aW9ucwkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgNtc2cBEGNsYWltYWJsZV90b2tlbnMBBHVzZXIJAJQKAgUDbmlsCQELdXNlcl9hbW91bnQBBQR1c2VyA21zZwEOY2xhaW1lZF9yZXdhcmQCBHVzZXIFYXNzZXQJAJQKAgUDbmlsCQESdXNlcl9hc3NldF9jbGFpbWVkAgUEdXNlcgUFYXNzZXQDbXNnARBjbGFpbWFibGVfcmV3YXJkAgR1c2VyBWFzc2V0BAFzAwkAZgIFDHRva2VuX2Ftb3VudAAACQEEc3luYwAFA25pbAMJAAACBQFzBQFzBA1fYXNzZXRfcmV3YXJkCQEMYXNzZXRfcmV3YXJkAQUFYXNzZXQEC2FjY3VtdWxhdGVkCQBkAgkBE3VzZXJfYXNzZXRfYWRqdXN0ZWQCBQR1c2VyBQVhc3NldAMJAAACBQx0b2tlbl9hbW91bnQAAAAACQBrAwUNX2Fzc2V0X3Jld2FyZAkBC3VzZXJfYW1vdW50AQUEdXNlcgUMdG9rZW5fYW1vdW50BAdjbGFpbWVkCQESdXNlcl9hc3NldF9jbGFpbWVkAgUEdXNlcgUFYXNzZXQEBmFtb3VudAkAZQIFC2FjY3VtdWxhdGVkBQdjbGFpbWVkCQCUCgIFA25pbAUGYW1vdW50CQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuA21zZwEKY2hlY2twb2ludAADBQlpc19raWxsZWQJAAIBAhRjaGVja3BvaW50IGlzIGtpbGxlZAMDCQAAAgUMdG9rZW5fYW1vdW50AAAJAQIhPQIIBQNtc2cGY2FsbGVyBQR0aGlzBwkAAgECFmNoZWNrcG9pbnQgdW5hdmFpbGFibGUJARJjaGVja3BvaW50X2FjdGlvbnMAA21zZwEEaW5pdAQGX293bmVyBl90b2tlbghfcmV3YXJkcwdfcGVyaW9kAwkBCWlzRGVmaW5lZAEJAJ0IAgUEdGhpcwIFdG9rZW4JAAIBAhNhbHJlYWR5IGluaXRpYWxpemVkAwkBAiE9AggFA21zZwZjYWxsZXIFBHRoaXMJAAIBAhhzZWxmIGluaXRpYWxpemF0aW9uIG9ubHkDCQBnAgAABQdfcGVyaW9kCQACAQIKYmFkIHBlcmlvZAkAzAgCCQELU3RyaW5nRW50cnkCAgVvd25lcgkBDGNoZWNrQWRkcmVzcwEFBl9vd25lcgkAzAgCCQELU3RyaW5nRW50cnkCAgV0b2tlbgkBCmNoZWNrQXNzZXQBBQZfdG9rZW4JAMwIAgkBC1N0cmluZ0VudHJ5AgIHcmV3YXJkcwkBEGNoZWNrUmV3YXJkc0xpc3QCBQhfcmV3YXJkcwUGX3Rva2VuCQDMCAIJAQxJbnRlZ2VyRW50cnkCAgZwZXJpb2QFB19wZXJpb2QJAMwIAgkBDEJvb2xlYW5FbnRyeQICCWlzX2tpbGxlZAcFA25pbANtc2cBCmFkZF9yZXdhcmQBBnJld2FyZAMJAQIhPQIIBQNtc2cGY2FsbGVyBQVvd25lcgkAAgECCm9ubHkgb3duZXIJAMwIAgkBC1N0cmluZ0VudHJ5AgIHcmV3YXJkcwkBEGNoZWNrUmV3YXJkc0xpc3QCCQCsAgIJAKwCAgUHcmV3YXJkcwIBLAUGcmV3YXJkBQV0b2tlbgUDbmlsA21zZwEKc2V0X2tpbGxlZAEKX2lzX2tpbGxlZAMJAQIhPQIIBQNtc2cGY2FsbGVyBQVvd25lcgkAAgECCm9ubHkgb3duZXIDCQAAAgUJaXNfa2lsbGVkBQpfaXNfa2lsbGVkCQACAQIKc2FtZSBzdGF0ZQQMc3RvcF9hY3Rpb25zAwUKX2lzX2tpbGxlZAkBDHN0b3BfcmV3YXJkcwAFA25pbAkAzggCCQDMCAIJAQxCb29sZWFuRW50cnkCAglpc19raWxsZWQFCl9pc19raWxsZWQFA25pbAUMc3RvcF9hY3Rpb25zA21zZwESc2V0X2hlaWdodF9hZGRyZXNzAQ5faGVpZ2h0QWRkcmVzcwMJAQIhPQIIBQNtc2cGY2FsbGVyBQVvd25lcgkAAgECCm9ubHkgb3duZXIJAMwIAgkBC1N0cmluZ0VudHJ5AgINaGVpZ2h0QWRkcmVzcwkBDGNoZWNrQWRkcmVzcwEFDl9oZWlnaHRBZGRyZXNzBQNuaWwBaQEMc2V0X3ZlcmlmaWVyAQh2ZXJpZmllcgMJAQIhPQIIBQFpBmNhbGxlcgUEdGhpcwkAAgECDnNlbGYgY2FsbCBvbmx5BAlhZGRyZXNzT0sEByRtYXRjaDAJAKYIAQUIdmVyaWZpZXIDCQABAgUHJG1hdGNoMAIHQWRkcmVzcwQBYQUHJG1hdGNoMAYHAwkBASEBBQlhZGRyZXNzT0sJAAIBCQCsAgICF3ZlcmlmaWVyIHdyb25nIGFkZHJlc3MgBQh2ZXJpZmllcgMJAQlpc0RlZmluZWQBCQCdCAIFBHRoaXMCCHZlcmlmaWVyCQACAQIYdmVyaWZpZXIgYWxyZWFkeSBkZWZpbmVkCQDMCAIJAQtTdHJpbmdFbnRyeQICCHZlcmlmaWVyBQh2ZXJpZmllcgUDbmlsAQJ0eAEGdmVyaWZ5AAQHJG1hdGNoMAkAnQgCBQR0aGlzAgh2ZXJpZmllcgMJAAECBQckbWF0Y2gwAgZTdHJpbmcECHZlcmlmaWVyBQckbWF0Y2gwCQELdmFsdWVPckVsc2UCCQCbCAIJARFAZXh0ck5hdGl2ZSgxMDYyKQEFCHZlcmlmaWVyCQCsAgIJAKwCAgkArAICAgdzdGF0dXNfCQClCAEFBHRoaXMCAV8JANgEAQgFAnR4AmlkBwkA9AMDCAUCdHgJYm9keUJ5dGVzCQCRAwIIBQJ0eAZwcm9vZnMAAAgFAnR4D3NlbmRlclB1YmxpY0tleR7t+gc=", "chainId": 87, "height": 3382311, "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 MAX_REWARDS = 5 | |
5 | + | ||
6 | + | let owner = addressFromStringValue(getStringValue(this, "owner")) | |
7 | + | ||
8 | + | let token = getStringValue(this, "token") | |
9 | + | ||
10 | + | let rewards = getStringValue(this, "rewards") | |
11 | + | ||
12 | + | let rewards_list = split(rewards, ",") | |
13 | + | ||
14 | + | let period = getIntegerValue(this, "period") | |
15 | + | ||
16 | + | let is_killed = getBooleanValue(this, "is_killed") | |
17 | + | ||
18 | + | let heightAddress = valueOrErrorMessage(addressFromString(valueOrErrorMessage(getString(this, "heightAddress"), "no settings defined")), "bad settings address") | |
19 | + | ||
20 | + | let HEIGHT = height | |
21 | + | ||
22 | + | let sync_height_key = "sync_height" | |
23 | + | ||
24 | + | let sync_height = valueOrElse(getInteger(this, sync_height_key), 0) | |
25 | + | ||
26 | + | let token_amount_key = "tokens" | |
27 | + | ||
28 | + | let token_amount = valueOrElse(getInteger(this, token_amount_key), 0) | |
29 | + | ||
30 | + | func user_amount_key (user) = (user + "_amount") | |
31 | + | ||
32 | + | ||
33 | + | func user_amount (user) = valueOrElse(getInteger(this, user_amount_key(user)), 0) | |
34 | + | ||
35 | + | ||
36 | + | func user_asset_adjusted_key (user,asset) = (((user + "_") + asset) + "_adjusted") | |
37 | + | ||
38 | + | ||
39 | + | func user_asset_adjusted (user,asset) = valueOrElse(getInteger(this, user_asset_adjusted_key(user, asset)), 0) | |
40 | + | ||
41 | + | ||
42 | + | func user_asset_claimed_key (user,asset) = (((user + "_") + asset) + "_claimed") | |
43 | + | ||
44 | + | ||
45 | + | func user_asset_claimed (user,asset) = valueOrElse(getInteger(this, user_asset_claimed_key(user, asset)), 0) | |
46 | + | ||
47 | + | ||
48 | + | func asset_reward_key (asset) = (asset + "_reward") | |
49 | + | ||
50 | + | ||
51 | + | func asset_reward (asset) = valueOrElse(getInteger(this, asset_reward_key(asset)), 0) | |
52 | + | ||
53 | + | ||
54 | + | func asset_speed_key (asset) = (asset + "_speed") | |
55 | + | ||
56 | + | ||
57 | + | func asset_speed (asset) = valueOrElse(getInteger(this, asset_speed_key(asset)), 0) | |
58 | + | ||
59 | + | ||
60 | + | func asset_left_key (asset) = (asset + "_left") | |
61 | + | ||
62 | + | ||
63 | + | func asset_left (asset) = valueOrElse(getInteger(this, asset_left_key(asset)), 0) | |
64 | + | ||
65 | + | ||
66 | + | func asset_control_key (asset) = (asset + "_control") | |
67 | + | ||
68 | + | ||
69 | + | func asset_control (asset) = valueOrElse(getInteger(this, asset_control_key(asset)), 0) | |
70 | + | ||
71 | + | ||
72 | + | func checkAddress (a58) = { | |
73 | + | let a = addressFromStringValue(a58) | |
74 | + | toString(a) | |
75 | + | } | |
76 | + | ||
77 | + | ||
78 | + | func checkAsset (asset58) = if ((asset58 == "WAVES")) | |
79 | + | then "WAVES" | |
80 | + | else { | |
81 | + | let asset = valueOrErrorMessage(fromBase58String(asset58), ("wrong asset encoding: " + asset58)) | |
82 | + | let info = valueOrErrorMessage(assetInfo(asset), ("wrong asset info: " + asset58)) | |
83 | + | if ((info == info)) | |
84 | + | then asset58 | |
85 | + | else throw("Strict value is not equal to itself.") | |
86 | + | } | |
87 | + | ||
88 | + | ||
89 | + | func asset (a) = if ((a == "WAVES")) | |
90 | + | then unit | |
91 | + | else fromBase58String(a) | |
92 | + | ||
93 | + | ||
94 | + | func asset_string (a) = match a { | |
95 | + | case b: ByteVector => | |
96 | + | toBase58String(b) | |
97 | + | case _ => | |
98 | + | "WAVES" | |
99 | + | } | |
100 | + | ||
101 | + | ||
102 | + | func asset_balance (a) = if ((a == "WAVES")) | |
103 | + | then wavesBalance(this).available | |
104 | + | else assetBalance(this, fromBase58String(a)) | |
105 | + | ||
106 | + | ||
107 | + | func stop_rewards () = { | |
108 | + | func fold (acc,asset) = (acc ++ [IntegerEntry(asset_speed_key(asset), 0)]) | |
109 | + | ||
110 | + | let $l = rewards_list | |
111 | + | let $s = size($l) | |
112 | + | let $acc0 = nil | |
113 | + | func $f0_1 ($a,$i) = if (($i >= $s)) | |
114 | + | then $a | |
115 | + | else fold($a, $l[$i]) | |
116 | + | ||
117 | + | func $f0_2 ($a,$i) = if (($i >= $s)) | |
118 | + | then $a | |
119 | + | else throw("List size exceeds 5") | |
120 | + | ||
121 | + | $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5) | |
122 | + | } | |
123 | + | ||
124 | + | ||
125 | + | func checkpoint_asset (acc,asset) = { | |
126 | + | let _asset_reward = asset_reward(asset) | |
127 | + | let _asset_speed = asset_speed(asset) | |
128 | + | let _asset_left = asset_left(asset) | |
129 | + | let estimate_reward = ((HEIGHT - sync_height) * _asset_speed) | |
130 | + | let real_reward = if ((estimate_reward > _asset_left)) | |
131 | + | then _asset_left | |
132 | + | else estimate_reward | |
133 | + | let claim_asset_reward = (_asset_reward + real_reward) | |
134 | + | let claim_asset_left = (_asset_left - real_reward) | |
135 | + | let claim_asset_speed = if ((claim_asset_left > 0)) | |
136 | + | then _asset_speed | |
137 | + | else 0 | |
138 | + | let reward_action = if ((claim_asset_reward == _asset_reward)) | |
139 | + | then nil | |
140 | + | else [IntegerEntry(asset_reward_key(asset), claim_asset_reward)] | |
141 | + | let _asset_balance = asset_balance(asset) | |
142 | + | let _asset_control = asset_control(asset) | |
143 | + | if ((_asset_control > _asset_balance)) | |
144 | + | then throw(((((asset + " balance leakage detected: ") + toString(_asset_control)) + " > ") + toString(_asset_balance))) | |
145 | + | else { | |
146 | + | let period_new_balance = (_asset_balance - _asset_control) | |
147 | + | let period_asset_balance = (claim_asset_left + period_new_balance) | |
148 | + | let period_asset_speed = (period_asset_balance / period) | |
149 | + | if (if ((claim_asset_speed >= period_asset_speed)) | |
150 | + | then (claim_asset_left >= period_new_balance) | |
151 | + | else false) | |
152 | + | then { | |
153 | + | let speed_action = if ((claim_asset_speed == _asset_speed)) | |
154 | + | then nil | |
155 | + | else [IntegerEntry(asset_speed_key(asset), claim_asset_speed)] | |
156 | + | let left_action = if ((claim_asset_left == _asset_left)) | |
157 | + | then nil | |
158 | + | else [IntegerEntry(asset_left_key(asset), claim_asset_left)] | |
159 | + | (((acc ++ reward_action) ++ speed_action) ++ left_action) | |
160 | + | } | |
161 | + | else { | |
162 | + | let period_asset_left = (period_asset_speed * period) | |
163 | + | let period_asset_dust = (period_asset_balance - period_asset_left) | |
164 | + | let period_asset_contol = (_asset_balance - period_asset_dust) | |
165 | + | ((acc ++ reward_action) ++ [IntegerEntry(asset_speed_key(asset), period_asset_speed), IntegerEntry(asset_left_key(asset), period_asset_left), IntegerEntry(asset_control_key(asset), period_asset_contol)]) | |
166 | + | } | |
167 | + | } | |
168 | + | } | |
169 | + | ||
170 | + | ||
171 | + | func sync () = if (is_killed) | |
172 | + | then nil | |
173 | + | else invoke(this, "checkpoint", nil, nil) | |
174 | + | ||
175 | + | ||
176 | + | func checkpoint_actions () = { | |
177 | + | let sync_action = if ((sync_height == HEIGHT)) | |
178 | + | then nil | |
179 | + | else [IntegerEntry(sync_height_key, HEIGHT)] | |
180 | + | (sync_action ++ { | |
181 | + | let $l = rewards_list | |
182 | + | let $s = size($l) | |
183 | + | let $acc0 = nil | |
184 | + | func $f0_1 ($a,$i) = if (($i >= $s)) | |
185 | + | then $a | |
186 | + | else checkpoint_asset($a, $l[$i]) | |
187 | + | ||
188 | + | func $f0_2 ($a,$i) = if (($i >= $s)) | |
189 | + | then $a | |
190 | + | else throw("List size exceeds 5") | |
191 | + | ||
192 | + | $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5) | |
193 | + | }) | |
194 | + | } | |
195 | + | ||
196 | + | ||
197 | + | func update_user (user,change) = { | |
198 | + | let new_user_amount = (user_amount(user) + change) | |
199 | + | if ((0 > new_user_amount)) | |
200 | + | then throw(((("bad amount: " + toString(change)) + ", available amount: ") + toString(user_amount(user)))) | |
201 | + | else { | |
202 | + | let new_token_amount = (token_amount + change) | |
203 | + | if ((new_token_amount > asset_balance(token))) | |
204 | + | then throw(((("token balance leakage detected: " + toString(new_token_amount)) + " > ") + toString(asset_balance(token)))) | |
205 | + | else { | |
206 | + | let s = sync() | |
207 | + | if ((s == s)) | |
208 | + | then { | |
209 | + | func fold (acc,asset) = (acc ++ { | |
210 | + | let _asset_reward = asset_reward(asset) | |
211 | + | let _user_asset_adjusted = user_asset_adjusted(user, asset) | |
212 | + | let new_asset_reward = if ((token_amount == 0)) | |
213 | + | then _asset_reward | |
214 | + | else fraction(_asset_reward, new_token_amount, token_amount) | |
215 | + | let new_user_asset_adjusted = (_user_asset_adjusted + (if ((new_token_amount == 0)) | |
216 | + | then _asset_reward | |
217 | + | else -(fraction(new_asset_reward, change, new_token_amount)))) | |
218 | + | let reward_action = if ((_asset_reward == new_asset_reward)) | |
219 | + | then nil | |
220 | + | else [IntegerEntry(asset_reward_key(asset), new_asset_reward)] | |
221 | + | let adjust_action = if ((_user_asset_adjusted == new_user_asset_adjusted)) | |
222 | + | then nil | |
223 | + | else [IntegerEntry(user_asset_adjusted_key(user, asset), new_user_asset_adjusted)] | |
224 | + | (reward_action ++ adjust_action) | |
225 | + | }) | |
226 | + | ||
227 | + | let stop_actions = if ((new_token_amount == 0)) | |
228 | + | then stop_rewards() | |
229 | + | else nil | |
230 | + | (([IntegerEntry(token_amount_key, new_token_amount), IntegerEntry(user_amount_key(user), new_user_amount)] ++ { | |
231 | + | let $l = rewards_list | |
232 | + | let $s = size($l) | |
233 | + | let $acc0 = nil | |
234 | + | func $f0_1 ($a,$i) = if (($i >= $s)) | |
235 | + | then $a | |
236 | + | else fold($a, $l[$i]) | |
237 | + | ||
238 | + | func $f0_2 ($a,$i) = if (($i >= $s)) | |
239 | + | then $a | |
240 | + | else throw("List size exceeds 5") | |
241 | + | ||
242 | + | $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5) | |
243 | + | }) ++ stop_actions) | |
244 | + | } | |
245 | + | else throw("Strict value is not equal to itself.") | |
246 | + | } | |
247 | + | } | |
248 | + | } | |
249 | + | ||
250 | + | ||
251 | + | func checkRewardsList (_rewards,_token) = { | |
252 | + | let _rewards_list = split(_rewards, ",") | |
253 | + | if ((size(_rewards_list) > MAX_REWARDS)) | |
254 | + | then throw("too many rewards") | |
255 | + | else { | |
256 | + | func fold (acc,asset) = if ((checkAsset(asset) == _token)) | |
257 | + | then throw("reward cannot be the token") | |
258 | + | else if (containsElement(acc, asset)) | |
259 | + | then throw("duplicated reward in list") | |
260 | + | else (acc ++ [asset]) | |
261 | + | ||
262 | + | makeString({ | |
263 | + | let $l = _rewards_list | |
264 | + | let $s = size($l) | |
265 | + | let $acc0 = nil | |
266 | + | func $f0_1 ($a,$i) = if (($i >= $s)) | |
267 | + | then $a | |
268 | + | else fold($a, $l[$i]) | |
269 | + | ||
270 | + | func $f0_2 ($a,$i) = if (($i >= $s)) | |
271 | + | then $a | |
272 | + | else throw("List size exceeds 5") | |
273 | + | ||
274 | + | $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5) | |
275 | + | }, ",") | |
276 | + | } | |
277 | + | } | |
278 | + | ||
279 | + | ||
280 | + | @Callable(msg) | |
281 | + | func deposit () = if ((size(msg.payments) != 1)) | |
282 | + | then throw("wrong payments, should be 1 payment") | |
283 | + | else { | |
284 | + | let payment = msg.payments[0] | |
285 | + | if ((asset_string(payment.assetId) != token)) | |
286 | + | then throw(((("wrong token: " + asset_string(payment.assetId)) + " != ") + token)) | |
287 | + | else if ((0 >= payment.amount)) | |
288 | + | then throw("wrong amount, should be positive") | |
289 | + | else update_user(toString(msg.caller), payment.amount) | |
290 | + | } | |
291 | + | ||
292 | + | ||
293 | + | ||
294 | + | @Callable(msg) | |
295 | + | func withdraw (amount) = if ((size(msg.payments) != 0)) | |
296 | + | then throw("wrong payments, should be empty") | |
297 | + | else if ((0 >= amount)) | |
298 | + | then throw("wrong amount, should be positive") | |
299 | + | else (update_user(toString(msg.caller), -(amount)) ++ [ScriptTransfer(msg.caller, amount, asset(token))]) | |
300 | + | ||
301 | + | ||
302 | + | ||
303 | + | @Callable(msg) | |
304 | + | func claim () = if ((size(msg.payments) != 0)) | |
305 | + | then throw("wrong payments, should be empty") | |
306 | + | else { | |
307 | + | let s = if ((token_amount > 0)) | |
308 | + | then sync() | |
309 | + | else nil | |
310 | + | if ((s == s)) | |
311 | + | then { | |
312 | + | let user = toString(msg.caller) | |
313 | + | func fold (acc,asset) = (acc ++ { | |
314 | + | let _asset_reward = asset_reward(asset) | |
315 | + | let accumulated = (user_asset_adjusted(user, asset) + (if ((token_amount == 0)) | |
316 | + | then 0 | |
317 | + | else fraction(_asset_reward, user_amount(user), token_amount))) | |
318 | + | let claimed = user_asset_claimed(user, asset) | |
319 | + | let amount = (accumulated - claimed) | |
320 | + | if ((amount == 0)) | |
321 | + | then nil | |
322 | + | else if ((0 > amount)) | |
323 | + | then throw(((asset + " bad claim amount detected: ") + toString(amount))) | |
324 | + | else { | |
325 | + | let _asset_control = asset_control(asset) | |
326 | + | [ScriptTransfer(msg.caller, amount, asset(asset)), IntegerEntry(user_asset_claimed_key(user, asset), (claimed + amount)), IntegerEntry(asset_control_key(asset), (_asset_control - amount))] | |
327 | + | } | |
328 | + | }) | |
329 | + | ||
330 | + | let claim_actions = { | |
331 | + | let $l = rewards_list | |
332 | + | let $s = size($l) | |
333 | + | let $acc0 = nil | |
334 | + | func $f0_1 ($a,$i) = if (($i >= $s)) | |
335 | + | then $a | |
336 | + | else fold($a, $l[$i]) | |
337 | + | ||
338 | + | func $f0_2 ($a,$i) = if (($i >= $s)) | |
339 | + | then $a | |
340 | + | else throw("List size exceeds 5") | |
341 | + | ||
342 | + | $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5) | |
343 | + | } | |
344 | + | if ((size(claim_actions) == 0)) | |
345 | + | then throw("nothing to claim") | |
346 | + | else claim_actions | |
347 | + | } | |
348 | + | else throw("Strict value is not equal to itself.") | |
349 | + | } | |
350 | + | ||
351 | + | ||
352 | + | ||
353 | + | @Callable(msg) | |
354 | + | func claimable_tokens (user) = $Tuple2(nil, user_amount(user)) | |
355 | + | ||
356 | + | ||
357 | + | ||
358 | + | @Callable(msg) | |
359 | + | func claimed_reward (user,asset) = $Tuple2(nil, user_asset_claimed(user, asset)) | |
360 | + | ||
361 | + | ||
362 | + | ||
363 | + | @Callable(msg) | |
364 | + | func claimable_reward (user,asset) = { | |
365 | + | let s = if ((token_amount > 0)) | |
366 | + | then sync() | |
367 | + | else nil | |
368 | + | if ((s == s)) | |
369 | + | then { | |
370 | + | let _asset_reward = asset_reward(asset) | |
371 | + | let accumulated = (user_asset_adjusted(user, asset) + (if ((token_amount == 0)) | |
372 | + | then 0 | |
373 | + | else fraction(_asset_reward, user_amount(user), token_amount))) | |
374 | + | let claimed = user_asset_claimed(user, asset) | |
375 | + | let amount = (accumulated - claimed) | |
376 | + | $Tuple2(nil, amount) | |
377 | + | } | |
378 | + | else throw("Strict value is not equal to itself.") | |
379 | + | } | |
380 | + | ||
381 | + | ||
382 | + | ||
383 | + | @Callable(msg) | |
384 | + | func checkpoint () = if (is_killed) | |
385 | + | then throw("checkpoint is killed") | |
386 | + | else if (if ((token_amount == 0)) | |
387 | + | then (msg.caller != this) | |
388 | + | else false) | |
389 | + | then throw("checkpoint unavailable") | |
390 | + | else checkpoint_actions() | |
391 | + | ||
392 | + | ||
393 | + | ||
394 | + | @Callable(msg) | |
395 | + | func init (_owner,_token,_rewards,_period) = if (isDefined(getString(this, "token"))) | |
396 | + | then throw("already initialized") | |
397 | + | else if ((msg.caller != this)) | |
398 | + | then throw("self initialization only") | |
399 | + | else if ((0 >= _period)) | |
400 | + | then throw("bad period") | |
401 | + | else [StringEntry("owner", checkAddress(_owner)), StringEntry("token", checkAsset(_token)), StringEntry("rewards", checkRewardsList(_rewards, _token)), IntegerEntry("period", _period), BooleanEntry("is_killed", false)] | |
402 | + | ||
403 | + | ||
404 | + | ||
405 | + | @Callable(msg) | |
406 | + | func add_reward (reward) = if ((msg.caller != owner)) | |
407 | + | then throw("only owner") | |
408 | + | else [StringEntry("rewards", checkRewardsList(((rewards + ",") + reward), token))] | |
409 | + | ||
410 | + | ||
411 | + | ||
412 | + | @Callable(msg) | |
413 | + | func set_killed (_is_killed) = if ((msg.caller != owner)) | |
414 | + | then throw("only owner") | |
415 | + | else if ((is_killed == _is_killed)) | |
416 | + | then throw("same state") | |
417 | + | else { | |
418 | + | let stop_actions = if (_is_killed) | |
419 | + | then stop_rewards() | |
420 | + | else nil | |
421 | + | ([BooleanEntry("is_killed", _is_killed)] ++ stop_actions) | |
422 | + | } | |
423 | + | ||
424 | + | ||
425 | + | ||
426 | + | @Callable(msg) | |
427 | + | func set_height_address (_heightAddress) = if ((msg.caller != owner)) | |
428 | + | then throw("only owner") | |
429 | + | else [StringEntry("heightAddress", checkAddress(_heightAddress))] | |
430 | + | ||
431 | + | ||
432 | + | ||
433 | + | @Callable(i) | |
434 | + | func set_verifier (verifier) = if ((i.caller != this)) | |
435 | + | then throw("self call only") | |
436 | + | else { | |
437 | + | let addressOK = match addressFromString(verifier) { | |
438 | + | case a: Address => | |
439 | + | true | |
440 | + | case _ => | |
441 | + | false | |
442 | + | } | |
443 | + | if (!(addressOK)) | |
444 | + | then throw(("verifier wrong address " + verifier)) | |
445 | + | else if (isDefined(getString(this, "verifier"))) | |
446 | + | then throw("verifier already defined") | |
447 | + | else [StringEntry("verifier", verifier)] | |
448 | + | } | |
449 | + | ||
450 | + | ||
451 | + | @Verifier(tx) | |
452 | + | func verify () = match getString(this, "verifier") { | |
453 | + | case verifier: String => | |
454 | + | valueOrElse(getBoolean(addressFromStringValue(verifier), ((("status_" + toString(this)) + "_") + toBase58String(tx.id))), false) | |
455 | + | case _ => | |
456 | + | sigVerify(tx.bodyBytes, tx.proofs[0], tx.senderPublicKey) | |
457 | + | } | |
458 | + |
github/deemru/w8io/fabc49c 50.84 ms ◑