tx · HGJR8N2MDLZaQrUQfp2oBwp4cfBvWhaCk8SGopNKcPAy 3PG97Sf8BXwoF7HonG1VZQCPmHVVgyJbeaV: -0.02600000 Waves 2023.05.02 13:02 [3625607] smart account 3PG97Sf8BXwoF7HonG1VZQCPmHVVgyJbeaV > SELF 0.00000000 Waves
{ "type": 13, "id": "HGJR8N2MDLZaQrUQfp2oBwp4cfBvWhaCk8SGopNKcPAy", "fee": 2600000, "feeAssetId": null, "timestamp": 1683021718545, "version": 2, "chainId": 87, "sender": "3PG97Sf8BXwoF7HonG1VZQCPmHVVgyJbeaV", "senderPublicKey": "HKWPeXmpjsweG16UvKf7Dxh5AFCnRzJipvP8a8Qf5rM9", "proofs": [ "2YqLjSMZRhCLBwbcxKQjAwhF3255Q4T6iVHM3sSVSsks8S4xsU417t5kjxMWdTRapjtHgpFFbfqZwyRhiFzbcNs3" ], "script": "base64:BgI5CAISABIAEgMKAQESABIDCgEBEgASABIAEgASABIAEggKBgEBAQEBAhIAEgsKCQEBAQEBAQEBAhIAPAADU0VQAgJfXwAJbWluQW1vdW50AMCEPQAFTVVMVDYAwIQ9AAVNVUxUOACAwtcvAAx3YXZlc0Fzc2V0SWQJANkEAQIFV0FWRVMACXd4QXNzZXRJZAEgkwEcq6nHbiVXzmaecba9qmv4POhYCyru2aBOuzzcFLEAC3N1cmZBc3NldElkASCS0fRK4hEBK/R+6t4hjj3F+8nyfc6Hsu1SGfA6TiRY9QAKeHRuQXNzZXRJZAEgtiYpwwT1zlORpA5LdSQvZIxRsfrfr1QpvUjSHSqyqtEADHZpcmVzQXNzZXRJZAEguNriNwFicF+aqFuyGQy9D8Nlr3UGtlgt3QeTVqndqZcAC2RleENvbnRyYWN0ARoBV8pr/J/Xy7o1PTtmmh6OsIpSpzSimkOUggAYd2F2ZXNFeGNoYW5nZURleENvbnRyYWN0ARoBVy4qNTWxDbfxeT7ht0bQnnRSTXsx0IOuBgAXbmV1dHJpbm9Db250cmFjdEFkZHJlc3MBGgFXcARipkeb6a1WaJTL74WMMIIgKJoIFJayABZuZXV0cmlub1N0YWtpbmdBZGRyZXNzARoBV2toOOED1JqMnxIbxiy8Iwc5C83tEtcKXwAZbmV1dHJpbm9QcmljZUluZGV4QWRkcmVzcwEaAVcjs60SXJOkyuw5/k9G1s1WTS37EPtjmHoAFGNhc2VYdG5Td2FwU3RhdGVJZGxlAAAAHGNhc2VYdG5Td2FwU3RhdGVYdG5Ub1Jld2FyZHMAAQAkY2FzZVh0blN3YXBTdGF0ZUV4Y2hhbmdlUmV3YXJkc09uRGV4AAIADmNvbnN0cnVjdGVkS2V5Agtjb25zdHJ1Y3RlZAATeHRuU3dhcFN0YXRlRW51bUtleQIQeHRuU3dhcFN0YXRlRW51bQASdG90YWxTdXJmU3Rha2VkS2V5Ag90b3RhbFN1cmZTdGFrZWQAJXBlbmRpbmdUb3RhbFN1cmZBbW91bnRUb1dpdGhkcmF3YWxLZXkCInBlbmRpbmdUb3RhbFN1ZnRBbW91bnRUb1dpdGhkcmF3YWwAEmRldnNXYXZlc0Ftb3VudEtleQIPZGV2c1dhdmVzQW1vdW50ABFkZXZzU3VyZkFtb3VudEtleQIOZGV2c1N1cmZBbW91bnQAD2RldnNXeEFtb3VudEtleQIMZGV2c1d4QW1vdW50ABBkZXZzWHRuQW1vdW50S2V5AhBkZXZzWHRuQW1vdW50S2V5ABF4dG5Td2FwQmxvY2tJZEtleQIOeHRuU3dhcEJsb2NrSWQAF3h0blN3YXBUcmFuc2FjdGlvbklkS2V5AhR4dG5Td2FwVHJhbnNhY3Rpb25JZAAUeHRuU3dhcFByaWNlSW5kZXhLZXkCEXh0blN3YXBQcmljZUluZGV4ABp4dG5Td2FwWHRuU3dhcHBlZEFtb3VudEtleQIXeHRuU3dhcFh0blN3YXBwZWRBbW91bnQAHHh0blN3YXBXYXZlc0JhbGFuY2VBdFN3YXBLZXkCGXh0blN3YXBXYXZlc0JhbGFuY2VBdFN3YXAAGXh0blN3YXBXeEJhbGFuY2VBdFN3YXBLZXkCFnh0blN3YXBXeEJhbGFuY2VBdFN3YXAAHHh0blN3YXBWaXJlc0JhbGFuY2VBdFN3YXBLZXkCGXh0blN3YXBWaXJlc0JhbGFuY2VBdFN3YXAAHnh0blN3YXBYdG5CYWxhbmNlQXRFeGNoYW5nZUtleQIbeHRuU3dhcFh0bkJhbGFuY2VBdEV4Y2hhbmdlABl4dG5Td2FwRXhjaGFuZ2VCbG9ja0lkS2V5AhZ4dG5Td2FwRXhjaGFuZ2VCbG9ja0lkABpsYXN0U3VjY2Vzc1N3YXBCbG9ja0hlaWdodAIabGFzdFN1Y2Nlc3NTd2FwQmxvY2tIZWlnaHQAHGN1cnJlbnRXaXRoZHJhd2FsUGVyaW9kSWRLZXkCGWN1cnJlbnRXaXRoZHJhd2FsUGVyaW9kSWQAGWN1cnJlbnRYVE5Td2FwUGVyaW9kSWRLZXkCFmN1cnJlbnRYVE5Td2FwUGVyaW9kSWQAJGN1cnJlbnRTdXJmU3Rha2luZ1Jld2FyZHNQZXJpb2RJZEtleQIkY3VycmVudFN1cmZTdGFraW5nUmV3YXJkc1BlcmlvZElkS2V5ASprZXlDdXJyZW50WHRuU3dhcFBlcmlvZFh0bkFtb3VudEZvck9uZVN1cmYBCHBlcmlvZElkCQCsAgIJAKwCAgInY3VycmVudFhUTlN3YXBQZXJpb2RYdG5BbW91bnRGb3JPbmVTdXJmBQNTRVAJAKQDAQUIcGVyaW9kSWQBNmtleUN1cnJlbnRTdXJmU3Rha2luZ1Jld2FyZFBlcmlvZFdhdmVzQW1vdW50Rm9yT25lU3VyZgEIcGVyaW9kSWQJAKwCAgkArAICAjNjdXJyZW50U3VyZlN0YWtpbmdSZXdhcmRQZXJpb2RXYXZlc0Ftb3VudEZvck9uZVN1cmYFA1NFUAkApAMBBQhwZXJpb2RJZAEza2V5Q3VycmVudFN1cmZTdGFraW5nUmV3YXJkUGVyaW9kV3hBbW91bnRGb3JPbmVTdXJmAQhwZXJpb2RJZAkArAICCQCsAgICMGN1cnJlbnRTdXJmU3Rha2luZ1Jld2FyZFBlcmlvZFd3QW1vdW50Rm9yT25lU3VyZgUDU0VQCQCkAwEFCHBlcmlvZElkATRrZXlDdXJyZW50U3VyZlN0YWtpbmdSZXdhcmRQZXJpb2RYdG5BbW91bnRGb3JPbmVTdXJmAQhwZXJpb2RJZAkArAICCQCsAgICMWN1cnJlbnRTdXJmU3Rha2luZ1Jld2FyZFBlcmlvZFh0bkFtb3VudEZvck9uZVN1cmYFA1NFUAkApAMBBQhwZXJpb2RJZAE2a2V5Q3VycmVudFN1cmZTdGFraW5nUmV3YXJkUGVyaW9kVmlyZXNBbW91bnRGb3JPbmVTdXJmAQhwZXJpb2RJZAkArAICCQCsAgICM2N1cnJlbnRTdXJmU3Rha2luZ1Jld2FyZFBlcmlvZFZpcmVzQW1vdW50Rm9yT25lU3VyZgUDU0VQCQCkAwEFCHBlcmlvZElkAR1rZXlDdXJyZW50VXNlclRvdGFsU3VyZlN0YWtlZAEHYWRkcmVzcwkArAICCQCsAgICGmN1cnJlbnRVc2VyVG90YWxTdXJmU3Rha2VkBQNTRVAFB2FkZHJlc3MBLGtleUN1cnJlbnRVc2VyVW5jbGFpbWVkWHRuU3dhcFJld2FyZFBlcmlvZElkAQdhZGRyZXNzCQCsAgIJAKwCAgIpY3VycmVudFVzZXJVbmNsYWltZWRYdG5Td2FwUmV3YXJkUGVyaW9kSWQFA1NFUAUHYWRkcmVzcwEwa2V5Q3VycmVudFVzZXJVbmNsYWltZWRTdXJmU3Rha2luZ1Jld2FyZFBlcmlvZElkAQdhZGRyZXNzCQCsAgIJAKwCAgItY3VycmVudFVzZXJVbmNsYWltZWRTdXJmU3Rha2luZ1Jld2FyZFBlcmlvZElkBQNTRVAFB2FkZHJlc3MBJ2tleUN1cnJlbnRVc2VyUGVuZGluZ1dpdGhkcmF3YWxQZXJpb2RJZAEHYWRkcmVzcwkArAICCQCsAgICJGN1cnJlbnRVc2VyUGVuZGluZ1dpdGhkcmF3YWxQZXJpb2RJZAUDU0VQBQdhZGRyZXNzAStrZXlDdXJyZW50VXNlclRvdGFsU3VyZlBlbmRpbmdGb3JXaXRoZHJhd2FsAQdhZGRyZXNzCQCsAgIJAKwCAgIoY3VycmVudFVzZXJUb3RhbFN1cmZQZW5kaW5nRm9yV2l0aGRyYXdhbAUDU0VQBQdhZGRyZXNzAQlhc1BheW1lbnQBAXYEByRtYXRjaDAFAXYDCQABAgUHJG1hdGNoMAIPQXR0YWNoZWRQYXltZW50BAFwBQckbWF0Y2gwBQFwCQACAQIhZmFpbCB0byBjYXN0IGludG8gQXR0YWNoZWRQYXltZW50AQVhc0ludAEDdmFsBAckbWF0Y2gwBQN2YWwDCQABAgUHJG1hdGNoMAIDSW50BAZ2YWxJbnQFByRtYXRjaDAFBnZhbEludAkAAgECFWZhaWwgdG8gY2FzdCBpbnRvIEludAEMYXNJbnRPclRocm93AgN2YWwHbWVzc2FnZQQHJG1hdGNoMAUDdmFsAwkAAQIFByRtYXRjaDACA0ludAQGdmFsSW50BQckbWF0Y2gwBQZ2YWxJbnQJAAIBBQdtZXNzYWdlAQphc0ludE9yRGVmAgN2YWwHZGVmYXVsdAQHJG1hdGNoMAUDdmFsAwkAAQIFByRtYXRjaDACA0ludAQGdmFsSW50BQckbWF0Y2gwBQZ2YWxJbnQFB2RlZmF1bHQBCGFzU3RyaW5nAQN2YWwEByRtYXRjaDAFA3ZhbAMJAAECBQckbWF0Y2gwAgZTdHJpbmcECXZhbFN0cmluZwUHJG1hdGNoMAUJdmFsU3RyaW5nCQACAQIYZmFpbCB0byBjYXN0IGludG8gU3RyaW5nAQ1hc1N0cmluZ09yRGVmAgN2YWwHZGVmYXVsdAQHJG1hdGNoMAUDdmFsAwkAAQIFByRtYXRjaDACBlN0cmluZwQJdmFsU3RyaW5nBQckbWF0Y2gwBQl2YWxTdHJpbmcFB2RlZmF1bHQBCWFzQm9vbGVhbgEDdmFsBAckbWF0Y2gwBQN2YWwDCQABAgUHJG1hdGNoMAIHQm9vbGVhbgQHdmFsQm9vbAUHJG1hdGNoMAUHdmFsQm9vbAkAAgECGWZhaWwgdG8gY2FzdCBpbnRvIEJvb2xlYW4BDmFzQm9vbGVhbk9yRGVmAgN2YWwHZGVmYXVsdAQHJG1hdGNoMAUDdmFsAwkAAQIFByRtYXRjaDACB0Jvb2xlYW4EB3ZhbEJvb2wFByRtYXRjaDAFB3ZhbEJvb2wFB2RlZmF1bHQBEWN1cnJlbnRQcm9wb3J0aW9uAQ94dG5Td2FwTGltaXRNYXgED3RvdGFsU3VyZlN0YWtlZAkBEUBleHRyTmF0aXZlKDEwNTUpAQUSdG90YWxTdXJmU3Rha2VkS2V5CQC9AgQJALYCAQUPdG90YWxTdXJmU3Rha2VkCQC2AgEFBU1VTFQ2CQC2AgEFD3h0blN3YXBMaW1pdE1heAUGSEFMRlVQAQ9jaGVja1Byb3BvcnRpb24DD3h0blN3YXBMaW1pdE1heApzdXJmQW1vdW50CXhudEFtb3VudAQKcHJvcG9ydGlvbgkBEWN1cnJlbnRQcm9wb3J0aW9uAQUPeHRuU3dhcExpbWl0TWF4BBJleHBlY3RlZFN1cmZBbW91bnQJAKADAQkAvQIEBQpwcm9wb3J0aW9uCQC2AgEFCXhudEFtb3VudAkAtgIBBQVNVUxUNgUGSEFMRlVQAwkAAAIFEmV4cGVjdGVkU3VyZkFtb3VudAUKc3VyZkFtb3VudAYJAAIBCQCsAgIJAKwCAgkArAICCQCsAgICBVdpdGggCQCkAwEFD3h0blN3YXBMaW1pdE1heAIfIFhOVCBhbW91bnQgeW91IHNob3VsZCBwcm92aWRlIAkApAMBBRJleHBlY3RlZFN1cmZBbW91bnQCFSBTVVJGIGFtb3VudCB0byBzdGFrZQEcaW50ZXJhY3RXaXRoU3dhcFBhcmFtc0J5VXNlcgAEBnJlc3VsdAkA/AcECQEHQWRkcmVzcwEFFm5ldXRyaW5vU3Rha2luZ0FkZHJlc3MCG3N3YXBQYXJhbXNCeVVzZXJTWVNSRUFET05MWQkAzAgCBQR0aGlzCQDMCAIAAAUDbmlsBQNuaWwDCQAAAgUGcmVzdWx0BQZyZXN1bHQEByRtYXRjaDAFBnJlc3VsdAMJAAECBQckbWF0Y2gwAiMoSW50LCBJbnQsIEludCwgSW50LCBJbnQsIEludCwgSW50KQQFdHVwbGUFByRtYXRjaDAJAMwIAggFBXR1cGxlAl8xCQDMCAIIBQV0dXBsZQJfMgkAzAgCCAUFdHVwbGUCXzMJAMwIAggFBXR1cGxlAl80CQDMCAIIBQV0dXBsZQJfNQkAzAgCCAUFdHVwbGUCXzYJAMwIAggFBXR1cGxlAl83BQNuaWwJAAIBAi5GQVRBTDogQ2FuJ3QgZmV0Y2ggZGF0YSBmcm9tIG5ldXRyaW5vIGNvbnRyYWN0CQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuASppc1VzZXJIYXNVbmNsYWltZWRSZXdhcmRzSW5QcmV2aW91c1BlcmlvZHMBB2FkZHJlc3MEInVzZXJVbmNsYWltZWRYdG5Td2FwUmV3YXJkUGVyaW9kSWQJAQphc0ludE9yRGVmAgkAnwgBCQEsa2V5Q3VycmVudFVzZXJVbmNsYWltZWRYdG5Td2FwUmV3YXJkUGVyaW9kSWQBBQdhZGRyZXNzAP///////////wEEJ3VzZXJVbmNsYWltZWRTdXJmU3Rha2luZ1Jld2FyZHNQZXJpb2RJZAkBCmFzSW50T3JEZWYCCQCfCAEJATBrZXlDdXJyZW50VXNlclVuY2xhaW1lZFN1cmZTdGFraW5nUmV3YXJkUGVyaW9kSWQBBQdhZGRyZXNzAP///////////wEEFGN1cnJlbnRYVE5Td2FwUGVyaW9kCQEKYXNJbnRPckRlZgIJAJ8IAQUZY3VycmVudFhUTlN3YXBQZXJpb2RJZEtleQAABB9jdXJyZW50U3VyZlN0YWtpbmdSZXdhcmRzUGVyaW9kCQEKYXNJbnRPckRlZgIJAJ8IAQUkY3VycmVudFN1cmZTdGFraW5nUmV3YXJkc1BlcmlvZElkS2V5AAADAwkAZgIFInVzZXJVbmNsYWltZWRYdG5Td2FwUmV3YXJkUGVyaW9kSWQA////////////AQkAZgIFFGN1cnJlbnRYVE5Td2FwUGVyaW9kBSJ1c2VyVW5jbGFpbWVkWHRuU3dhcFJld2FyZFBlcmlvZElkBwYDAwkAZgIFJ3VzZXJVbmNsYWltZWRTdXJmU3Rha2luZ1Jld2FyZHNQZXJpb2RJZAD///////////8BCQBmAgUfY3VycmVudFN1cmZTdGFraW5nUmV3YXJkc1BlcmlvZAUndXNlclVuY2xhaW1lZFN1cmZTdGFraW5nUmV3YXJkc1BlcmlvZElkBwYHDwFpAQtjb25zdHJ1Y3RvcgAEByRtYXRjaDAJAKAIAQUOY29uc3RydWN0ZWRLZXkDCQABAgUHJG1hdGNoMAIHQm9vbGVhbgkAAgECI0NvbnN0cnVjdG9yIGNhbiBiZSBjYWxsZWQganVzdCBvbmNlCQDMCAIJAQxCb29sZWFuRW50cnkCBQ5jb25zdHJ1Y3RlZEtleQYJAMwIAgkBDEludGVnZXJFbnRyeQIFHGN1cnJlbnRXaXRoZHJhd2FsUGVyaW9kSWRLZXkAAAkAzAgCCQEMSW50ZWdlckVudHJ5AgUZY3VycmVudFhUTlN3YXBQZXJpb2RJZEtleQAACQDMCAIJAQxJbnRlZ2VyRW50cnkCBSRjdXJyZW50U3VyZlN0YWtpbmdSZXdhcmRzUGVyaW9kSWRLZXkAAAkAzAgCCQEMSW50ZWdlckVudHJ5AgUlcGVuZGluZ1RvdGFsU3VyZkFtb3VudFRvV2l0aGRyYXdhbEtleQAACQDMCAIJAQxJbnRlZ2VyRW50cnkCBRJkZXZzV2F2ZXNBbW91bnRLZXkAAAkAzAgCCQEMSW50ZWdlckVudHJ5AgURZGV2c1N1cmZBbW91bnRLZXkAAAkAzAgCCQEMSW50ZWdlckVudHJ5AgUPZGV2c1d4QW1vdW50S2V5AAAJAMwIAgkBDEludGVnZXJFbnRyeQIFEGRldnNYdG5BbW91bnRLZXkAAAkAzAgCCQEMSW50ZWdlckVudHJ5AgUabGFzdFN1Y2Nlc3NTd2FwQmxvY2tIZWlnaHQAAAkAzAgCCQEMSW50ZWdlckVudHJ5AgUTeHRuU3dhcFN0YXRlRW51bUtleQUUY2FzZVh0blN3YXBTdGF0ZUlkbGUFA25pbAFpARdleHRlbmRQcmljZUluZGV4QnlPbmVVcAAEDnN3YXBQcmljZUluZGV4CQERQGV4dHJOYXRpdmUoMTA1NSkBBRR4dG5Td2FwUHJpY2VJbmRleEtleQkAzAgCCQEMSW50ZWdlckVudHJ5AgUUeHRuU3dhcFByaWNlSW5kZXhLZXkJAGQCBQ5zd2FwUHJpY2VJbmRleAABBQNuaWwBaQEPd3JpdGVQcmljZUluZGV4AQpwcmljZUluZGV4CQDMCAIJAQxJbnRlZ2VyRW50cnkCBRR4dG5Td2FwUHJpY2VJbmRleEtleQUKcHJpY2VJbmRleAUDbmlsAWkBBXN0YWtlAAMJAQIhPQIJARFAZXh0ck5hdGl2ZSgxMDU1KQEFE3h0blN3YXBTdGF0ZUVudW1LZXkFFGNhc2VYdG5Td2FwU3RhdGVJZGxlCQACAQIzWFROIHN3YXAgaW4gcHJvZ3Jlc3MsIHdhaXQgYXBwcm94aW1hdGVsbHkgMyBtaW51dGVzAwkBAiE9AgkAkAMBCAUBaQhwYXltZW50cwABCQACAQIzWW91IG11c3QgaW5jbHVkZSBleGFjdGx5IG9uZSBwYXltZW50IGluIHRyYW5zYWN0aW9uBAdwYXltZW50CQEJYXNQYXltZW50AQkAkQMCCAUBaQhwYXltZW50cwAAAwMJAQIhPQIIBQdwYXltZW50B2Fzc2V0SWQFC3N1cmZBc3NldElkBgkAZgIFCW1pbkFtb3VudAgFB3BheW1lbnQGYW1vdW50CQACAQIXV3JvbmcgYXNzZXRJZCBvciBhbW91bnQEE2NhbGxlckFkZHJlc3NTdHJpbmcJANgEAQgIBQFpBmNhbGxlcgVieXRlcwMJASppc1VzZXJIYXNVbmNsYWltZWRSZXdhcmRzSW5QcmV2aW91c1BlcmlvZHMBBRNjYWxsZXJBZGRyZXNzU3RyaW5nCQACAQI+WW91IGhhdmUgdW5jbGFpbWVkIHJld2FyZHMsIGNsYWltIHRoZW0gZmlyc3QsIHRoZW4gc3Rha2UgYWdhaW4EBnJlc3VsdAkA/AcECQEHQWRkcmVzcwEFFm5ldXRyaW5vU3Rha2luZ0FkZHJlc3MCBXN0YWtlBQNuaWwJAMwIAgUHcGF5bWVudAUDbmlsAwkAAAIFBnJlc3VsdAUGcmVzdWx0BBJuZXdUb3RhbFN1cmZTdGFrZWQEByRtYXRjaDAJAJ8IAQUSdG90YWxTdXJmU3Rha2VkS2V5AwkAAQIFByRtYXRjaDACA0ludAQBdgUHJG1hdGNoMAkAZAIFAXYIBQdwYXltZW50BmFtb3VudAgFB3BheW1lbnQGYW1vdW50BBhjYWxsZXJUb3RhbFN1cmZTdGFrZWRLZXkJAR1rZXlDdXJyZW50VXNlclRvdGFsU3VyZlN0YWtlZAEFE2NhbGxlckFkZHJlc3NTdHJpbmcEGG5ld0NhbGxlclRvdGFsU3VyZlN0YWtlZAQHJG1hdGNoMAkAnwgBBRhjYWxsZXJUb3RhbFN1cmZTdGFrZWRLZXkDCQABAgUHJG1hdGNoMAIDSW50BAF2BQckbWF0Y2gwCQBkAgUBdggFB3BheW1lbnQGYW1vdW50CAUHcGF5bWVudAZhbW91bnQEFGN1cnJlbnRYVE5Td2FwUGVyaW9kCQEKYXNJbnRPckRlZgIJAJ8IAQUZY3VycmVudFhUTlN3YXBQZXJpb2RJZEtleQAABB9jdXJyZW50U3VyZlN0YWtpbmdSZXdhcmRzUGVyaW9kCQEKYXNJbnRPckRlZgIJAJ8IAQUkY3VycmVudFN1cmZTdGFraW5nUmV3YXJkc1BlcmlvZElkS2V5AAAJAMwIAgkBDEludGVnZXJFbnRyeQIFEnRvdGFsU3VyZlN0YWtlZEtleQUSbmV3VG90YWxTdXJmU3Rha2VkCQDMCAIJAQxJbnRlZ2VyRW50cnkCBRhjYWxsZXJUb3RhbFN1cmZTdGFrZWRLZXkFGG5ld0NhbGxlclRvdGFsU3VyZlN0YWtlZAkAzAgCCQEMSW50ZWdlckVudHJ5AgkBLGtleUN1cnJlbnRVc2VyVW5jbGFpbWVkWHRuU3dhcFJld2FyZFBlcmlvZElkAQUTY2FsbGVyQWRkcmVzc1N0cmluZwUUY3VycmVudFhUTlN3YXBQZXJpb2QJAMwIAgkBDEludGVnZXJFbnRyeQIJATBrZXlDdXJyZW50VXNlclVuY2xhaW1lZFN1cmZTdGFraW5nUmV3YXJkUGVyaW9kSWQBBRNjYWxsZXJBZGRyZXNzU3RyaW5nBR9jdXJyZW50U3VyZlN0YWtpbmdSZXdhcmRzUGVyaW9kBQNuaWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQEXYXBwbHlGb3JQZW5kaW5nV2l0aGRyYXcBBmFtb3VudAMJAQIhPQIJARFAZXh0ck5hdGl2ZSgxMDU1KQEFE3h0blN3YXBTdGF0ZUVudW1LZXkFFGNhc2VYdG5Td2FwU3RhdGVJZGxlCQACAQIzWFROIHN3YXAgaW4gcHJvZ3Jlc3MsIHdhaXQgYXBwcm94aW1hdGVsbHkgMyBtaW51dGVzAwkAZgIJAJADAQgFAWkIcGF5bWVudHMAAAkAAgECJlRoaXMgZnVuY3Rpb24gZG9lcyBub3QgYWNjZXB0IHBheW1lbnRzAwkAZwIAAAUGYW1vdW50CQACAQIXQW1vdW50IG11c3QgYmUgcG9zaXRpdmUEE2NhbGxlckFkZHJlc3NTdHJpbmcJANgEAQgIBQFpBmNhbGxlcgVieXRlcwQVY2FsbGVyVG90YWxTdXJmU3Rha2VkCQERQGV4dHJOYXRpdmUoMTA1NSkBCQEda2V5Q3VycmVudFVzZXJUb3RhbFN1cmZTdGFrZWQBBRNjYWxsZXJBZGRyZXNzU3RyaW5nAwkAZgIFBmFtb3VudAUVY2FsbGVyVG90YWxTdXJmU3Rha2VkCQACAQIgSW5zdWZmaWNpZW50IGJhbGFuY2UgdG8gd2l0aGRyYXcDCQEqaXNVc2VySGFzVW5jbGFpbWVkUmV3YXJkc0luUHJldmlvdXNQZXJpb2RzAQUTY2FsbGVyQWRkcmVzc1N0cmluZwkAAgECPFlvdSBoYXZlIHVuY2xhaW1lZCByZXdhcmRzLCBjbGFpbSB0aGVtIGZpcnN0LCB0aGVuIHRyeSBhZ2FpbgQTY3VycmVudFdpdGhkcmF3YWxJZAkBEUBleHRyTmF0aXZlKDEwNTUpAQUcY3VycmVudFdpdGhkcmF3YWxQZXJpb2RJZEtleQQlcGVuZGluZ1RvdGFsU3VyZlRvVW5zdGFrZUZyb21OZXV0cmlubwkBEUBleHRyTmF0aXZlKDEwNTUpAQUlcGVuZGluZ1RvdGFsU3VyZkFtb3VudFRvV2l0aGRyYXdhbEtleQQddXNlclBlbmRpbmdXaXRoZHJhd2FsUGVyaW9kSWQJAQphc0ludE9yRGVmAgkAnwgBCQEna2V5Q3VycmVudFVzZXJQZW5kaW5nV2l0aGRyYXdhbFBlcmlvZElkAQUTY2FsbGVyQWRkcmVzc1N0cmluZwD///////////8BBCF1c2VyVG90YWxTdXJmUGVuZGluZ0ZvcldpdGhkcmF3YWwJAQphc0ludE9yRGVmAgkAnwgBCQEra2V5Q3VycmVudFVzZXJUb3RhbFN1cmZQZW5kaW5nRm9yV2l0aGRyYXdhbAEFE2NhbGxlckFkZHJlc3NTdHJpbmcAAAMDCQBmAgUddXNlclBlbmRpbmdXaXRoZHJhd2FsUGVyaW9kSWQA////////////AQkAZgIFE2N1cnJlbnRXaXRoZHJhd2FsSWQFHXVzZXJQZW5kaW5nV2l0aGRyYXdhbFBlcmlvZElkBwkAAgECP1lvdSBoYXZlIHVuY2xhaW1lZCBzdWZ0IG9uIGNvbnRyYWN0LCBwbGVhc2UgcGVyZm9ybSBjbGFpbSBmaXJzdAQcdXNlck5ld1RvdGFsU3VyZlN0YWtlZEFtb3VudAkAZQIFFWNhbGxlclRvdGFsU3VyZlN0YWtlZAUGYW1vdW50BCR1c2VyTmV3VG90YWxTdXJmUGVuZGluZ0ZvcldpdGhkcmF3YWwJAGQCBSF1c2VyVG90YWxTdXJmUGVuZGluZ0ZvcldpdGhkcmF3YWwFBmFtb3VudAQobmV3UGVuZGluZ1RvdGFsU3VyZlRvVW5zdGFrZUZyb21OZXV0cmlubwkAZAIFJXBlbmRpbmdUb3RhbFN1cmZUb1Vuc3Rha2VGcm9tTmV1dHJpbm8FBmFtb3VudAQYbmV3VG90YWxTdXJmU3Rha2VkQW1vdW50CQBlAgkBEUBleHRyTmF0aXZlKDEwNTUpAQUSdG90YWxTdXJmU3Rha2VkS2V5BQZhbW91bnQJAMwIAgkBDEludGVnZXJFbnRyeQIJAR1rZXlDdXJyZW50VXNlclRvdGFsU3VyZlN0YWtlZAEFE2NhbGxlckFkZHJlc3NTdHJpbmcFHHVzZXJOZXdUb3RhbFN1cmZTdGFrZWRBbW91bnQJAMwIAgkBDEludGVnZXJFbnRyeQIJASdrZXlDdXJyZW50VXNlclBlbmRpbmdXaXRoZHJhd2FsUGVyaW9kSWQBBRNjYWxsZXJBZGRyZXNzU3RyaW5nBRNjdXJyZW50V2l0aGRyYXdhbElkCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEra2V5Q3VycmVudFVzZXJUb3RhbFN1cmZQZW5kaW5nRm9yV2l0aGRyYXdhbAEFE2NhbGxlckFkZHJlc3NTdHJpbmcFJHVzZXJOZXdUb3RhbFN1cmZQZW5kaW5nRm9yV2l0aGRyYXdhbAkAzAgCCQEMSW50ZWdlckVudHJ5AgUlcGVuZGluZ1RvdGFsU3VyZkFtb3VudFRvV2l0aGRyYXdhbEtleQUobmV3UGVuZGluZ1RvdGFsU3VyZlRvVW5zdGFrZUZyb21OZXV0cmlubwkAzAgCCQEMSW50ZWdlckVudHJ5AgUSdG90YWxTdXJmU3Rha2VkS2V5BRhuZXdUb3RhbFN1cmZTdGFrZWRBbW91bnQFA25pbAFpARpwZXJmb3JtRGlzdHJpYnV0ZWRXaXRoZHJhdwADCQBmAgkAkAMBCAUBaQhwYXltZW50cwAACQACAQImVGhpcyBmdW5jdGlvbiBkb2VzIG5vdCBhY2NlcHQgcGF5bWVudHMEE2N1cnJlbnRXaXRoZHJhd2FsSWQJARFAZXh0ck5hdGl2ZSgxMDU1KQEFHGN1cnJlbnRXaXRoZHJhd2FsUGVyaW9kSWRLZXkEJXBlbmRpbmdUb3RhbFN1cmZUb1Vuc3Rha2VGcm9tTmV1dHJpbm8JARFAZXh0ck5hdGl2ZSgxMDU1KQEFJXBlbmRpbmdUb3RhbFN1cmZBbW91bnRUb1dpdGhkcmF3YWxLZXkDCQBnAgAABSVwZW5kaW5nVG90YWxTdXJmVG9VbnN0YWtlRnJvbU5ldXRyaW5vBQNuaWwEBnJlc3VsdAkA/AcECQEHQWRkcmVzcwEFFm5ldXRyaW5vU3Rha2luZ0FkZHJlc3MCB3Vuc3Rha2UJAMwIAgUlcGVuZGluZ1RvdGFsU3VyZlRvVW5zdGFrZUZyb21OZXV0cmlubwUDbmlsBQNuaWwDCQAAAgUGcmVzdWx0BQZyZXN1bHQJAMwIAgkBDEludGVnZXJFbnRyeQIFHGN1cnJlbnRXaXRoZHJhd2FsUGVyaW9kSWRLZXkJAGQCBRNjdXJyZW50V2l0aGRyYXdhbElkAAEJAMwIAgkBDEludGVnZXJFbnRyeQIFJXBlbmRpbmdUb3RhbFN1cmZBbW91bnRUb1dpdGhkcmF3YWxLZXkAAAUDbmlsCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBCWNsYWltU3VyZgADCQBmAgkAkAMBCAUBaQhwYXltZW50cwAACQACAQImVGhpcyBmdW5jdGlvbiBkb2VzIG5vdCBhY2NlcHQgcGF5bWVudHMEE2NhbGxlckFkZHJlc3NTdHJpbmcJANgEAQgIBQFpBmNhbGxlcgVieXRlcwQZY3VycmVudFdpdGhkcmF3YWxQZXJpb2RJZAkBEUBleHRyTmF0aXZlKDEwNTUpAQUcY3VycmVudFdpdGhkcmF3YWxQZXJpb2RJZEtleQQWdXNlcldpdGhkcmF3YWxQZXJpb2RJZAkBCmFzSW50T3JEZWYCCQCfCAEJASdrZXlDdXJyZW50VXNlclBlbmRpbmdXaXRoZHJhd2FsUGVyaW9kSWQBBRNjYWxsZXJBZGRyZXNzU3RyaW5nAP///////////wEEIXVzZXJUb3RhbFN1cmZQZW5kaW5nRm9yV2l0aGRyYXdhbAkBCmFzSW50T3JEZWYCCQCfCAEJAStrZXlDdXJyZW50VXNlclRvdGFsU3VyZlBlbmRpbmdGb3JXaXRoZHJhd2FsAQUTY2FsbGVyQWRkcmVzc1N0cmluZwAAAwMJAAACBRZ1c2VyV2l0aGRyYXdhbFBlcmlvZElkAP///////////wEGCQAAAgUhdXNlclRvdGFsU3VyZlBlbmRpbmdGb3JXaXRoZHJhd2FsAAAJAAIBAhNOb3RoaW5nIHRvIHdpdGhkcmF3AwkAAAIFFnVzZXJXaXRoZHJhd2FsUGVyaW9kSWQFGWN1cnJlbnRXaXRoZHJhd2FsUGVyaW9kSWQJAAIBAiRZb3UgbXVzdCB3YWl0IGZvciBwZXJpb2QgdG8gY29tcGxldGUJAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwgFAWkGY2FsbGVyBSF1c2VyVG90YWxTdXJmUGVuZGluZ0ZvcldpdGhkcmF3YWwFC3N1cmZBc3NldElkCQDMCAIJAQtEZWxldGVFbnRyeQEJASdrZXlDdXJyZW50VXNlclBlbmRpbmdXaXRoZHJhd2FsUGVyaW9kSWQBBRNjYWxsZXJBZGRyZXNzU3RyaW5nCQDMCAIJAQtEZWxldGVFbnRyeQEJAStrZXlDdXJyZW50VXNlclRvdGFsU3VyZlBlbmRpbmdGb3JXaXRoZHJhd2FsAQUTY2FsbGVyQWRkcmVzc1N0cmluZwUDbmlsAWkBH3h0blN3YXBQYXJ0MXN3YXBYVE5Gcm9tTmV1dHJpbm8AAwkBAiE9AgkBEUBleHRyTmF0aXZlKDEwNTUpAQUTeHRuU3dhcFN0YXRlRW51bUtleQUUY2FzZVh0blN3YXBTdGF0ZUlkbGUJAAIBAhlXcm9uZyBzdGF0ZSwgbXVzdCBiZSBJZGxlBA53aXRoZHJhd1Jlc3VsdAkA/AcEBQR0aGlzAhpwZXJmb3JtRGlzdHJpYnV0ZWRXaXRoZHJhdwUDbmlsBQNuaWwDCQAAAgUOd2l0aGRyYXdSZXN1bHQFDndpdGhkcmF3UmVzdWx0BBJzdXJmU3Rha2luZ1Jld2FyZHMJAPwHBAUEdGhpcwIjc3VyZlN0YWtpbmdSZXdhcmRzQ2xhaW1Gcm9tTmV1dHJpbm8FA25pbAUDbmlsAwkAAAIFEnN1cmZTdGFraW5nUmV3YXJkcwUSc3VyZlN0YWtpbmdSZXdhcmRzBAZyZXN1bHQJAPwHBAkBB0FkZHJlc3MBBRduZXV0cmlub0NvbnRyYWN0QWRkcmVzcwIbc3dhcFBhcmFtc0J5VXNlclNZU1JFQURPTkxZCQDMCAIJAKUIAQUEdGhpcwkAzAgCAAAFA25pbAUDbmlsAwkAAAIFBnJlc3VsdAUGcmVzdWx0BAckbWF0Y2gwBQZyZXN1bHQDCQABAgUHJG1hdGNoMAIjKEludCwgSW50LCBJbnQsIEludCwgSW50LCBJbnQsIEludCkEBXR1cGxlBQckbWF0Y2gwAwkAZgIIBQV0dXBsZQJfMwAACQACAQkArAICCQCsAgICJ1RpbWUgaXMgbm90IGNvbWUgeWV0LCB5b3UgbmVlZCB0byB3YWl0IAkApAMBCAUFdHVwbGUCXzMCByBibG9ja3MEDW1heFN3YXBBbW91bnQIBQV0dXBsZQJfNwMJAGYCAMCEPQUNbWF4U3dhcEFtb3VudAkAAgECLE1pbiBYVE4gYW1vdW50IHRvIHN3YXAgaXMgMSwgc3Rha2UgbW9yZSBTVVJGAwkAZgIFDW1heFN3YXBBbW91bnQJAPAHAgUEdGhpcwUKeHRuQXNzZXRJZAkAAgECVlhUTiBCYWxhbmNlIG9uIGNvbnRyYWN0IGlzIHNtYWxsZXIgdGhhbiBtYXggc3dhcCBhbW91bnQsIGluY3JlYXNlIFhUTiBjb250cmFjdCBiYWxhbmNlBBNjdXJyZW50V2F2ZXNCYWxhbmNlCQDvBwEFBHRoaXMEEGN1cnJlbnRXWEJhbGFuY2UJAPAHAgUEdGhpcwUJd3hBc3NldElkBBNjdXJyZW50VmlyZXNCYWxhbmNlCQDwBwIFBHRoaXMFDHZpcmVzQXNzZXRJZAQUc3dhcE5ldXRyaW5vVG9Bc3NldHMJAPwHBAkBB0FkZHJlc3MBBRduZXV0cmlub0NvbnRyYWN0QWRkcmVzcwIUc3dhcE5ldXRyaW5vVG9CYXNrZXQFA25pbAkAzAgCCQEPQXR0YWNoZWRQYXltZW50AgUKeHRuQXNzZXRJZAUNbWF4U3dhcEFtb3VudAUDbmlsAwkAAAIFFHN3YXBOZXV0cmlub1RvQXNzZXRzBRRzd2FwTmV1dHJpbm9Ub0Fzc2V0cwQKcHJpY2VJbmRleAkAZAIJARFAZXh0ck5hdGl2ZSgxMDUwKQIJAQdBZGRyZXNzAQUZbmV1dHJpbm9QcmljZUluZGV4QWRkcmVzcwILcHJpY2VfaW5kZXgAAQkAzAgCCQEMSW50ZWdlckVudHJ5AgUReHRuU3dhcEJsb2NrSWRLZXkFBmhlaWdodAkAzAgCCQELU3RyaW5nRW50cnkCBRd4dG5Td2FwVHJhbnNhY3Rpb25JZEtleQkA2AQBCAUBaQ10cmFuc2FjdGlvbklkCQDMCAIJAQxJbnRlZ2VyRW50cnkCBRR4dG5Td2FwUHJpY2VJbmRleEtleQUKcHJpY2VJbmRleAkAzAgCCQEMSW50ZWdlckVudHJ5AgUaeHRuU3dhcFh0blN3YXBwZWRBbW91bnRLZXkFDW1heFN3YXBBbW91bnQJAMwIAgkBDEludGVnZXJFbnRyeQIFHHh0blN3YXBXYXZlc0JhbGFuY2VBdFN3YXBLZXkIBRNjdXJyZW50V2F2ZXNCYWxhbmNlCWF2YWlsYWJsZQkAzAgCCQEMSW50ZWdlckVudHJ5AgUZeHRuU3dhcFd4QmFsYW5jZUF0U3dhcEtleQUQY3VycmVudFdYQmFsYW5jZQkAzAgCCQEMSW50ZWdlckVudHJ5AgUceHRuU3dhcFZpcmVzQmFsYW5jZUF0U3dhcEtleQUTY3VycmVudFZpcmVzQmFsYW5jZQkAzAgCCQEMSW50ZWdlckVudHJ5AgUTeHRuU3dhcFN0YXRlRW51bUtleQUcY2FzZVh0blN3YXBTdGF0ZVh0blRvUmV3YXJkcwUDbmlsCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIrSW5jb3JyZWN0IGRhdGEgZnJvbSBuZXV0cmlubyBzbWFydCBjb250cmFjdAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpASd4dG5Td2FwUGFydDJleGNoYW5nZVh0blN3YXBSZXdhcmRzT25EZXgAAwkBAiE9AgkBEUBleHRyTmF0aXZlKDEwNTUpAQUTeHRuU3dhcFN0YXRlRW51bUtleQUcY2FzZVh0blN3YXBTdGF0ZVh0blRvUmV3YXJkcwkAAgECIVdyb25nIHN0YXRlLCBtdXN0IGJlIFh0blRvUmV3YXJkcwMJAGcCCQERQGV4dHJOYXRpdmUoMTA1NSkBBRF4dG5Td2FwQmxvY2tJZEtleQUGaGVpZ2h0CQACAQIVTXVzdCB3YWl0IGZvciAxIGJsb2NrBBBzd2FwVHJhbnNhdGlvbklkCQERQGV4dHJOYXRpdmUoMTA1OCkBBRd4dG5Td2FwVHJhbnNhY3Rpb25JZEtleQQOc3dhcFByaWNlSW5kZXgJARFAZXh0ck5hdGl2ZSgxMDU1KQEFFHh0blN3YXBQcmljZUluZGV4S2V5BAx3aXRoZHJhd19yZXMJAPwHBAkBB0FkZHJlc3MBBRduZXV0cmlub0NvbnRyYWN0QWRkcmVzcwIId2l0aGRyYXcJAMwIAgkApQgBBQR0aGlzCQDMCAIFDnN3YXBQcmljZUluZGV4CQDMCAIFEHN3YXBUcmFuc2F0aW9uSWQFA25pbAUDbmlsAwkAAAIFDHdpdGhkcmF3X3JlcwUMd2l0aGRyYXdfcmVzBBJ3YXZlc0JhbGFuY2VBdFN3YXAJARFAZXh0ck5hdGl2ZSgxMDU1KQEFHHh0blN3YXBXYXZlc0JhbGFuY2VBdFN3YXBLZXkED3d4QmFsYW5jZUF0U3dhcAkBEUBleHRyTmF0aXZlKDEwNTUpAQUZeHRuU3dhcFd4QmFsYW5jZUF0U3dhcEtleQQSdmlyZXNCYWxhbmNlQXRTd2FwCQERQGV4dHJOYXRpdmUoMTA1NSkBBRx4dG5Td2FwVmlyZXNCYWxhbmNlQXRTd2FwS2V5BBNjdXJyZW50V2F2ZXNCYWxhbmNlCQDvBwEFBHRoaXMEEGN1cnJlbnRXWEJhbGFuY2UJAPAHAgUEdGhpcwUJd3hBc3NldElkBBNjdXJyZW50VmlyZXNCYWxhbmNlCQDwBwIFBHRoaXMFDHZpcmVzQXNzZXRJZAQMd2F2ZXNSZXdhcmRzCQBlAggFE2N1cnJlbnRXYXZlc0JhbGFuY2UJYXZhaWxhYmxlBRJ3YXZlc0JhbGFuY2VBdFN3YXADCQAAAgUMd2F2ZXNSZXdhcmRzBQx3YXZlc1Jld2FyZHMECXd4UmV3YXJkcwkAZQIFEGN1cnJlbnRXWEJhbGFuY2UFD3d4QmFsYW5jZUF0U3dhcAMJAAACBQl3eFJld2FyZHMFCXd4UmV3YXJkcwQMdmlyZXNSZXdhcmRzCQBlAgUTY3VycmVudFZpcmVzQmFsYW5jZQUSdmlyZXNCYWxhbmNlQXRTd2FwAwkAAAIFDHZpcmVzUmV3YXJkcwUMdmlyZXNSZXdhcmRzBBd4dG5BbW91bnRCZWZvcmVFeGNoYW5nZQkA8AcCBQR0aGlzBQp4dG5Bc3NldElkAwkAAAIFF3h0bkFtb3VudEJlZm9yZUV4Y2hhbmdlBRd4dG5BbW91bnRCZWZvcmVFeGNoYW5nZQQKeHRuU3dhcHBlZAkBEUBleHRyTmF0aXZlKDEwNTUpAQUaeHRuU3dhcFh0blN3YXBwZWRBbW91bnRLZXkEDWV4Y2hhbmdlV2F2ZXMDCQBnAgAABQx3YXZlc1Jld2FyZHMFA25pbAQJd2F2ZXNTd2FwCQD8BwQJAQdBZGRyZXNzAQUYd2F2ZXNFeGNoYW5nZURleENvbnRyYWN0AgRzd2FwCQDMCAIAAAkAzAgCCQClCAEJAQdBZGRyZXNzAQUKeHRuQXNzZXRJZAkAzAgCCQClCAEFBHRoaXMFA25pbAkAzAgCCQEPQXR0YWNoZWRQYXltZW50AgUEdW5pdAUMd2F2ZXNSZXdhcmRzBQNuaWwDCQAAAgUJd2F2ZXNTd2FwBQl3YXZlc1N3YXAFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgMJAAACBQ1leGNoYW5nZVdhdmVzBQ1leGNoYW5nZVdhdmVzBA1leGNoYW5nZVZpcmVzAwkAZwIAAAUMdmlyZXNSZXdhcmRzBQNuaWwECXZpcmVzU3dhcAkA/AcECQEHQWRkcmVzcwEFGHdhdmVzRXhjaGFuZ2VEZXhDb250cmFjdAIEc3dhcAkAzAgCAAAJAMwIAgkApQgBCQEHQWRkcmVzcwEFCnh0bkFzc2V0SWQJAMwIAgkApQgBBQR0aGlzBQNuaWwJAMwIAgkBD0F0dGFjaGVkUGF5bWVudAIFBHVuaXQFDHZpcmVzUmV3YXJkcwUDbmlsAwkAAAIFCXZpcmVzU3dhcAUJdmlyZXNTd2FwBQNuaWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4DCQAAAgUNZXhjaGFuZ2VWaXJlcwUNZXhjaGFuZ2VWaXJlcwQKZXhjaGFuZ2VXWAMJAGcCAAAFCXd4UmV3YXJkcwUDbmlsBAZ3eFN3YXAJAPwHBAkBB0FkZHJlc3MBBRh3YXZlc0V4Y2hhbmdlRGV4Q29udHJhY3QCBHN3YXAJAMwIAgAACQDMCAIJAKUIAQkBB0FkZHJlc3MBBQp4dG5Bc3NldElkCQDMCAIJAKUIAQUEdGhpcwUDbmlsCQDMCAIJAQ9BdHRhY2hlZFBheW1lbnQCBQl3eEFzc2V0SWQFCXd4UmV3YXJkcwUDbmlsAwkAAAIFBnd4U3dhcAUGd3hTd2FwBQNuaWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4DCQAAAgUKZXhjaGFuZ2VXWAUKZXhjaGFuZ2VXWAQQY3VycmVudFh0bkFtb3VudAkA8AcCBQR0aGlzBQp4dG5Bc3NldElkBBZjdXJyZW50WHRuU3dhcFBlcmlvZElkCQERQGV4dHJOYXRpdmUoMTA1NSkBBRljdXJyZW50WFROU3dhcFBlcmlvZElkS2V5BA90b3RhbFN1cmZTdGFrZWQJARFAZXh0ck5hdGl2ZSgxMDU1KQEFEnRvdGFsU3VyZlN0YWtlZEtleQQYeHRuUmV3YXJkQW1vdW50Rm9yUGVyaW9kCQBlAgUQY3VycmVudFh0bkFtb3VudAkAZAIFF3h0bkFtb3VudEJlZm9yZUV4Y2hhbmdlBQp4dG5Td2FwcGVkBBx4dG5SZXdhcmRQZXJPbmVTdXJmRm9yUGVyaW9kAwkAZwIAAAUYeHRuUmV3YXJkQW1vdW50Rm9yUGVyaW9kAAAJAG4EBRh4dG5SZXdhcmRBbW91bnRGb3JQZXJpb2QFBU1VTFQ2BQ90b3RhbFN1cmZTdGFrZWQFBkhBTEZVUAkAzAgCCQEMSW50ZWdlckVudHJ5AgIVWFROX1JFV0FSRF9GT1JfUEVSSU9EBRh4dG5SZXdhcmRBbW91bnRGb3JQZXJpb2QJAMwIAgkBDEludGVnZXJFbnRyeQICFldBVkVTX1JFV0FSRFNfRk9SX1NXQVAFDHdhdmVzUmV3YXJkcwkAzAgCCQEMSW50ZWdlckVudHJ5AgITV1hfUkVXQVJEU19GT1JfU1dBUAUJd3hSZXdhcmRzCQDMCAIJAQxJbnRlZ2VyRW50cnkCAhZWSVJFU19SRVdBUkRTX0ZPUl9TV0FQBQx2aXJlc1Jld2FyZHMJAMwIAgkBDEludGVnZXJFbnRyeQIFHnh0blN3YXBYdG5CYWxhbmNlQXRFeGNoYW5nZUtleQkA8AcCBQR0aGlzBQp4dG5Bc3NldElkCQDMCAIJAQxJbnRlZ2VyRW50cnkCBRl4dG5Td2FwRXhjaGFuZ2VCbG9ja0lkS2V5BQZoZWlnaHQJAMwIAgkBDEludGVnZXJFbnRyeQIJASprZXlDdXJyZW50WHRuU3dhcFBlcmlvZFh0bkFtb3VudEZvck9uZVN1cmYBBRZjdXJyZW50WHRuU3dhcFBlcmlvZElkBRx4dG5SZXdhcmRQZXJPbmVTdXJmRm9yUGVyaW9kCQDMCAIJAQxJbnRlZ2VyRW50cnkCBRljdXJyZW50WFROU3dhcFBlcmlvZElkS2V5CQBkAgUWY3VycmVudFh0blN3YXBQZXJpb2RJZAABCQDMCAIJAQxJbnRlZ2VyRW50cnkCBRN4dG5Td2FwU3RhdGVFbnVtS2V5BRRjYXNlWHRuU3dhcFN0YXRlSWRsZQUDbmlsCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBBWNsYWltAAQJeHRuUmVzdWx0CQD8BwQFBHRoaXMCE2NsYWltWHRuU3dhcFJld2FyZHMFA25pbAUDbmlsAwkAAAIFCXh0blJlc3VsdAUJeHRuUmVzdWx0BQNuaWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BaQETY2xhaW1YdG5Td2FwUmV3YXJkcwADCQBmAgkAkAMBCAUBaQhwYXltZW50cwAACQACAQImVGhpcyBmdW5jdGlvbiBkb2VzIG5vdCBhY2NlcHQgcGF5bWVudHMEE2NhbGxlckFkZHJlc3NTdHJpbmcJANgEAQgIBQFpDG9yaWdpbkNhbGxlcgVieXRlcwQWY3VycmVudFh0blN3YXBQZXJpb2RJZAkBCmFzSW50T3JEZWYCCQCfCAEFGWN1cnJlbnRYVE5Td2FwUGVyaW9kSWRLZXkAAAQpY3VycmVudFVzZXJVbmNsYWltZWRYdG5Td2FwUmV3YXJkUGVyaW9kSWQJAQphc0ludE9yRGVmAgkAnwgBCQEsa2V5Q3VycmVudFVzZXJVbmNsYWltZWRYdG5Td2FwUmV3YXJkUGVyaW9kSWQBBRNjYWxsZXJBZGRyZXNzU3RyaW5nAP///////////wEDCQAAAgUpY3VycmVudFVzZXJVbmNsYWltZWRYdG5Td2FwUmV3YXJkUGVyaW9kSWQA////////////AQkAlAoCCQDMCAIJAQtTdHJpbmdFbnRyeQICBWRlYnVnCQEsa2V5Q3VycmVudFVzZXJVbmNsYWltZWRYdG5Td2FwUmV3YXJkUGVyaW9kSWQBBRNjYWxsZXJBZGRyZXNzU3RyaW5nBQNuaWwA////////////AQMJAAACBSljdXJyZW50VXNlclVuY2xhaW1lZFh0blN3YXBSZXdhcmRQZXJpb2RJZAUWY3VycmVudFh0blN3YXBQZXJpb2RJZAkAAgECMllvdSBuZWVkIHRvIHdhaXQgZm9yIGN1cnJlbnQgc3dhcCBwZXJpb2QgdG8gZmluaXNoBBZ1bmNsYWltZWRYdG5Td2Fwc0NvdW50CQBlAgUWY3VycmVudFh0blN3YXBQZXJpb2RJZAUpY3VycmVudFVzZXJVbmNsYWltZWRYdG5Td2FwUmV3YXJkUGVyaW9kSWQEE3VzZXJUb3RhbFN1cmZTdGFrZWQJARFAZXh0ck5hdGl2ZSgxMDU1KQEJAR1rZXlDdXJyZW50VXNlclRvdGFsU3VyZlN0YWtlZAEFE2NhbGxlckFkZHJlc3NTdHJpbmcELG5ld0N1cnJlbnRVc2VyVW5jbGFpbWVkWHRuU3dhcFJld2FyZFBlcmlvZElkAwkAZgIFFnVuY2xhaW1lZFh0blN3YXBzQ291bnQAHgkAZAIFKWN1cnJlbnRVc2VyVW5jbGFpbWVkWHRuU3dhcFJld2FyZFBlcmlvZElkAB4FFmN1cnJlbnRYdG5Td2FwUGVyaW9kSWQECml0ZXJhdGlvbnMDCQBmAgAeBRZ1bmNsYWltZWRYdG5Td2Fwc0NvdW50BRZ1bmNsYWltZWRYdG5Td2Fwc0NvdW50AB4EBnJlc3VsdAkA/AcEBQR0aGlzAiBpbnRlcm5hbEFjY3VtdWxhdGVYdG5Td2FwUmV3YXJkcwkAzAgCBQppdGVyYXRpb25zCQDMCAIAAAkAzAgCBSljdXJyZW50VXNlclVuY2xhaW1lZFh0blN3YXBSZXdhcmRQZXJpb2RJZAkAzAgCAAAJAMwIAgUTdXNlclRvdGFsU3VyZlN0YWtlZAkAzAgCCAgFAWkMb3JpZ2luQ2FsbGVyBWJ5dGVzBQNuaWwFA25pbAMJAAACBQZyZXN1bHQFBnJlc3VsdAkAzAgCCQEMSW50ZWdlckVudHJ5AgkBLGtleUN1cnJlbnRVc2VyVW5jbGFpbWVkWHRuU3dhcFJld2FyZFBlcmlvZElkAQUTY2FsbGVyQWRkcmVzc1N0cmluZwUsbmV3Q3VycmVudFVzZXJVbmNsYWltZWRYdG5Td2FwUmV3YXJkUGVyaW9kSWQFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpASBpbnRlcm5hbEFjY3VtdWxhdGVYdG5Td2FwUmV3YXJkcwYKaXRlcmF0aW9ucwdjdXJyZW50FHN0YXJ0WHRuU3dhcFBlcmlvZElkFGFjY3VtdWxhdGVkUmV3YXJkWHRuDnVzZXJTdXJmQW1vdW50B2FkZHJlc3MDCQECIT0CBQR0aGlzCAUBaQZjYWxsZXIJAAIBAhFJbnRlcm5hbCBmdW5jdGlvbgMJAGcCBQdjdXJyZW50BQppdGVyYXRpb25zAwkAZgIFFGFjY3VtdWxhdGVkUmV3YXJkWHRuAAAJAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwkBB0FkZHJlc3MBBQdhZGRyZXNzBRRhY2N1bXVsYXRlZFJld2FyZFh0bgUKeHRuQXNzZXRJZAUDbmlsBQNuaWwEEHh0bkFtb3VudFBlclN1cmYJAQphc0ludE9yRGVmAgkAnwgBCQEqa2V5Q3VycmVudFh0blN3YXBQZXJpb2RYdG5BbW91bnRGb3JPbmVTdXJmAQkAZAIFFHN0YXJ0WHRuU3dhcFBlcmlvZElkBQdjdXJyZW50AAAEBnJld2FyZAMJAAACBRB4dG5BbW91bnRQZXJTdXJmAAAAAAkAbgQFEHh0bkFtb3VudFBlclN1cmYFDnVzZXJTdXJmQW1vdW50BQVNVUxUNgUGSEFMRlVQBAZyZXN1bHQJAPwHBAUEdGhpcwIgaW50ZXJuYWxBY2N1bXVsYXRlWHRuU3dhcFJld2FyZHMJAMwIAgUKaXRlcmF0aW9ucwkAzAgCCQBkAgUHY3VycmVudAABCQDMCAIJAGQCBRRzdGFydFh0blN3YXBQZXJpb2RJZAUHY3VycmVudAkAzAgCCQBkAgUUYWNjdW11bGF0ZWRSZXdhcmRYdG4FBnJld2FyZAkAzAgCBQ51c2VyU3VyZkFtb3VudAkAzAgCBQdhZGRyZXNzBQNuaWwFA25pbAMJAAACBQZyZXN1bHQFBnJlc3VsdAUDbmlsCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBF2NsYWltU3VyZlN0YWtpbmdSZXdhcmRzAAMJAGYCCQCQAwEIBQFpCHBheW1lbnRzAAAJAAIBAiZUaGlzIGZ1bmN0aW9uIGRvZXMgbm90IGFjY2VwdCBwYXltZW50cwQTY2FsbGVyQWRkcmVzc1N0cmluZwkA2AQBCAgFAWkGY2FsbGVyBWJ5dGVzBCFjdXJyZW50U3VyZlN0YWtpbmdSZXdhcmRzUGVyaW9kSWQJAQphc0ludE9yRGVmAgkAnwgBBSRjdXJyZW50U3VyZlN0YWtpbmdSZXdhcmRzUGVyaW9kSWRLZXkAAAQtY3VycmVudFVzZXJVbmNsYWltZWRTdXJmU3Rha2luZ1Jld2FyZFBlcmlvZElkCQEKYXNJbnRPckRlZgIJAJ8IAQkBMGtleUN1cnJlbnRVc2VyVW5jbGFpbWVkU3VyZlN0YWtpbmdSZXdhcmRQZXJpb2RJZAEFE2NhbGxlckFkZHJlc3NTdHJpbmcA////////////AQMJAAACBS1jdXJyZW50VXNlclVuY2xhaW1lZFN1cmZTdGFraW5nUmV3YXJkUGVyaW9kSWQA////////////AQkAlAoCBQNuaWwA////////////AQMJAAACBS1jdXJyZW50VXNlclVuY2xhaW1lZFN1cmZTdGFraW5nUmV3YXJkUGVyaW9kSWQFIWN1cnJlbnRTdXJmU3Rha2luZ1Jld2FyZHNQZXJpb2RJZAkAAgECMllvdSBuZWVkIHRvIHdhaXQgZm9yIGN1cnJlbnQgc3dhcCBwZXJpb2QgdG8gZmluaXNoBBp1bmNsYWltZWRTdXJmU3Rha2luZ3NDb3VudAkAZQIFIWN1cnJlbnRTdXJmU3Rha2luZ1Jld2FyZHNQZXJpb2RJZAUtY3VycmVudFVzZXJVbmNsYWltZWRTdXJmU3Rha2luZ1Jld2FyZFBlcmlvZElkBBN1c2VyVG90YWxTdXJmU3Rha2VkCQERQGV4dHJOYXRpdmUoMTA1NSkBCQEda2V5Q3VycmVudFVzZXJUb3RhbFN1cmZTdGFrZWQBBRNjYWxsZXJBZGRyZXNzU3RyaW5nBDBuZXdDdXJyZW50VXNlclVuY2xhaW1lZFN1cmZTdGFraW5nUmV3YXJkUGVyaW9kSWQDCQBmAgUadW5jbGFpbWVkU3VyZlN0YWtpbmdzQ291bnQALQkAZAIFLWN1cnJlbnRVc2VyVW5jbGFpbWVkU3VyZlN0YWtpbmdSZXdhcmRQZXJpb2RJZAAtBSFjdXJyZW50U3VyZlN0YWtpbmdSZXdhcmRzUGVyaW9kSWQECml0ZXJhdGlvbnMDCQBmAgAtBRp1bmNsYWltZWRTdXJmU3Rha2luZ3NDb3VudAUadW5jbGFpbWVkU3VyZlN0YWtpbmdzQ291bnQALQQGcmVzdWx0CQD8BwQFBHRoaXMCJGludGVybmFsQWNjdW11bGF0ZVN1cmZTdGFraW5nUmV3YXJkcwkAzAgCBQppdGVyYXRpb25zCQDMCAIAAAkAzAgCBS1jdXJyZW50VXNlclVuY2xhaW1lZFN1cmZTdGFraW5nUmV3YXJkUGVyaW9kSWQJAMwIAgAACQDMCAIAAAkAzAgCAAAJAMwIAgAACQDMCAIFE3VzZXJUb3RhbFN1cmZTdGFrZWQJAMwIAggIBQFpBmNhbGxlcgVieXRlcwUDbmlsBQNuaWwDCQAAAgUGcmVzdWx0BQZyZXN1bHQJAMwIAgkBDEludGVnZXJFbnRyeQIJATBrZXlDdXJyZW50VXNlclVuY2xhaW1lZFN1cmZTdGFraW5nUmV3YXJkUGVyaW9kSWQBBRNjYWxsZXJBZGRyZXNzU3RyaW5nBTBuZXdDdXJyZW50VXNlclVuY2xhaW1lZFN1cmZTdGFraW5nUmV3YXJkUGVyaW9kSWQFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgFpASRpbnRlcm5hbEFjY3VtdWxhdGVTdXJmU3Rha2luZ1Jld2FyZHMJCml0ZXJhdGlvbnMHY3VycmVudBVzdGFydFN1cmZTd2FwUGVyaW9kSWQWYWNjdW11bGF0ZWRSZXdhcmRXYXZlcxNhY2N1bXVsYXRlZFJld2FyZFd4FGFjY3VtdWxhdGVkUmV3YXJkWHRuFmFjY3VtdWxhdGVkUmV3YXJkVmlyZXMOdXNlclN1cmZBbW91bnQHYWRkcmVzcwMJAQIhPQIFBHRoaXMIBQFpBmNhbGxlcgkAAgECEUludGVybmFsIGZ1bmN0aW9uAwkAZwIFB2N1cnJlbnQFCml0ZXJhdGlvbnMDAwMDCQBmAgUUYWNjdW11bGF0ZWRSZXdhcmRYdG4AAAYJAGYCBRZhY2N1bXVsYXRlZFJld2FyZFdhdmVzAAAGCQBmAgUTYWNjdW11bGF0ZWRSZXdhcmRXeAAABgkAZgIFFmFjY3VtdWxhdGVkUmV3YXJkVmlyZXMAAAkAzAgCCQEOU2NyaXB0VHJhbnNmZXIDCQEHQWRkcmVzcwEFB2FkZHJlc3MFFGFjY3VtdWxhdGVkUmV3YXJkWHRuBQp4dG5Bc3NldElkCQDMCAIJAQ5TY3JpcHRUcmFuc2ZlcgMJAQdBZGRyZXNzAQUHYWRkcmVzcwUWYWNjdW11bGF0ZWRSZXdhcmRXYXZlcwUMd2F2ZXNBc3NldElkCQDMCAIJAQ5TY3JpcHRUcmFuc2ZlcgMJAQdBZGRyZXNzAQUHYWRkcmVzcwUTYWNjdW11bGF0ZWRSZXdhcmRXeAUJd3hBc3NldElkCQDMCAIJAQ5TY3JpcHRUcmFuc2ZlcgMJAQdBZGRyZXNzAQUHYWRkcmVzcwUWYWNjdW11bGF0ZWRSZXdhcmRWaXJlcwUMdmlyZXNBc3NldElkBQNuaWwFA25pbAQQeHRuQW1vdW50UGVyU3VyZgkBCmFzSW50T3JEZWYCCQCfCAEJATRrZXlDdXJyZW50U3VyZlN0YWtpbmdSZXdhcmRQZXJpb2RYdG5BbW91bnRGb3JPbmVTdXJmAQkAZAIFFXN0YXJ0U3VyZlN3YXBQZXJpb2RJZAUHY3VycmVudAAABBJ3YXZlc0Ftb3VudFBlclN1cmYJAQphc0ludE9yRGVmAgkAnwgBCQE2a2V5Q3VycmVudFN1cmZTdGFraW5nUmV3YXJkUGVyaW9kV2F2ZXNBbW91bnRGb3JPbmVTdXJmAQkAZAIFFXN0YXJ0U3VyZlN3YXBQZXJpb2RJZAUHY3VycmVudAAABA93eEFtb3VudFBlclN1cmYJAQphc0ludE9yRGVmAgkAnwgBCQEza2V5Q3VycmVudFN1cmZTdGFraW5nUmV3YXJkUGVyaW9kV3hBbW91bnRGb3JPbmVTdXJmAQkAZAIFFXN0YXJ0U3VyZlN3YXBQZXJpb2RJZAUHY3VycmVudAAABBJ2aXJlc0Ftb3VudFBlclN1cmYJAQphc0ludE9yRGVmAgkAnwgBCQE2a2V5Q3VycmVudFN1cmZTdGFraW5nUmV3YXJkUGVyaW9kVmlyZXNBbW91bnRGb3JPbmVTdXJmAQkAZAIFFXN0YXJ0U3VyZlN3YXBQZXJpb2RJZAUHY3VycmVudAAABAl4dG5SZXdhcmQDCQAAAgUQeHRuQW1vdW50UGVyU3VyZgAAAAAJAG4EBRB4dG5BbW91bnRQZXJTdXJmBQ51c2VyU3VyZkFtb3VudAUFTVVMVDgFBkhBTEZVUAQLd2F2ZXNSZXdhcmQDCQAAAgUSd2F2ZXNBbW91bnRQZXJTdXJmAAAAAAkAbgQFEndhdmVzQW1vdW50UGVyU3VyZgUOdXNlclN1cmZBbW91bnQFBU1VTFQ4BQZIQUxGVVAECHd4UmV3YXJkAwkAAAIFD3d4QW1vdW50UGVyU3VyZgAAAAAJAG4EBQ93eEFtb3VudFBlclN1cmYFDnVzZXJTdXJmQW1vdW50BQVNVUxUOAUGSEFMRlVQBAt2aXJlc1Jld2FyZAMJAAACBRJ2aXJlc0Ftb3VudFBlclN1cmYAAAAACQBuBAUSdmlyZXNBbW91bnRQZXJTdXJmBQ51c2VyU3VyZkFtb3VudAUFTVVMVDgFBkhBTEZVUAQGcmVzdWx0CQD8BwQFBHRoaXMCJGludGVybmFsQWNjdW11bGF0ZVN1cmZTdGFraW5nUmV3YXJkcwkAzAgCBQppdGVyYXRpb25zCQDMCAIJAGQCBQdjdXJyZW50AAEJAMwIAgkAZAIFFXN0YXJ0U3VyZlN3YXBQZXJpb2RJZAUHY3VycmVudAkAzAgCCQBkAgUWYWNjdW11bGF0ZWRSZXdhcmRXYXZlcwULd2F2ZXNSZXdhcmQJAMwIAgkAZAIFE2FjY3VtdWxhdGVkUmV3YXJkV3gFCHd4UmV3YXJkCQDMCAIJAGQCBRRhY2N1bXVsYXRlZFJld2FyZFh0bgUJeHRuUmV3YXJkCQDMCAIJAGQCBRZhY2N1bXVsYXRlZFJld2FyZFZpcmVzBQt2aXJlc1Jld2FyZAkAzAgCBQ51c2VyU3VyZkFtb3VudAkAzAgCBQdhZGRyZXNzBQNuaWwFA25pbAMJAAACBQZyZXN1bHQFBnJlc3VsdAUDbmlsCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBI3N1cmZTdGFraW5nUmV3YXJkc0NsYWltRnJvbU5ldXRyaW5vAAMJAGYCCQCQAwEIBQFpCHBheW1lbnRzAAAJAAIBAiZUaGlzIGZ1bmN0aW9uIGRvZXMgbm90IGFjY2VwdCBwYXltZW50cwQWY3VycmVudFdhdmVzT25Db250cmFjdAkA7wcBBQR0aGlzAwkAAAIFFmN1cnJlbnRXYXZlc09uQ29udHJhY3QFFmN1cnJlbnRXYXZlc09uQ29udHJhY3QEE2N1cnJlbnRXeE9uQ29udHJhY3QJAPAHAgUEdGhpcwUJd3hBc3NldElkAwkAAAIFE2N1cnJlbnRXeE9uQ29udHJhY3QFE2N1cnJlbnRXeE9uQ29udHJhY3QEFGN1cnJlbnRYdG5PbkNvbnRyYWN0CQDwBwIFBHRoaXMFCnh0bkFzc2V0SWQDCQAAAgUUY3VycmVudFh0bk9uQ29udHJhY3QFFGN1cnJlbnRYdG5PbkNvbnRyYWN0BBZjdXJyZW50VmlyZXNPbkNvbnRyYWN0CQDwBwIFBHRoaXMFDHZpcmVzQXNzZXRJZAMJAAACBRZjdXJyZW50VmlyZXNPbkNvbnRyYWN0BRZjdXJyZW50VmlyZXNPbkNvbnRyYWN0BAZyZXN1bHQJAPwHBAkBB0FkZHJlc3MBBRZuZXV0cmlub1N0YWtpbmdBZGRyZXNzAgxjbGFpbVJld2FyZHMFA25pbAUDbmlsAwkAAAIFBnJlc3VsdAUGcmVzdWx0BBJuZXdXYXZlc09uQ29udHJhY3QJAO8HAQUEdGhpcwQPbmV3V3hPbkNvbnRyYWN0CQDwBwIFBHRoaXMFCXd4QXNzZXRJZAQQbmV3WHRuT25Db250cmFjdAkA8AcCBQR0aGlzBQp4dG5Bc3NldElkBBJuZXdWaXJlc09uQ29udHJhY3QJAPAHAgUEdGhpcwUMdmlyZXNBc3NldElkBBp3YXZlc1Jld2FyZEFtb3VudEZvclBlcmlvZAkAZQIIBRJuZXdXYXZlc09uQ29udHJhY3QJYXZhaWxhYmxlCAUWY3VycmVudFdhdmVzT25Db250cmFjdAlhdmFpbGFibGUEF3d4UmV3YXJkQW1vdW50Rm9yUGVyaW9kCQBlAgUPbmV3V3hPbkNvbnRyYWN0BRNjdXJyZW50V3hPbkNvbnRyYWN0BBh4dG5SZXdhcmRBbW91bnRGb3JQZXJpb2QJAGUCBRBuZXdYdG5PbkNvbnRyYWN0BRRjdXJyZW50WHRuT25Db250cmFjdAQadmlyZXNSZXdhcmRBbW91bnRGb3JQZXJpb2QJAGUCBRJuZXdWaXJlc09uQ29udHJhY3QFFmN1cnJlbnRWaXJlc09uQ29udHJhY3QEIWN1cnJlbnRTdXJmU3Rha2luZ1Jld2FyZHNQZXJpb2RJZAkBEUBleHRyTmF0aXZlKDEwNTUpAQUkY3VycmVudFN1cmZTdGFraW5nUmV3YXJkc1BlcmlvZElkS2V5BA90b3RhbFN1cmZTdGFrZWQJAQphc0ludE9yRGVmAgkAnwgBBRJ0b3RhbFN1cmZTdGFrZWRLZXkAAAMJAAACBQ90b3RhbFN1cmZTdGFrZWQAAAUDbmlsBB53YXZlc1Jld2FyZFBlck9uZVN1cmZGb3JQZXJpb2QDCQAAAgUad2F2ZXNSZXdhcmRBbW91bnRGb3JQZXJpb2QAAAAACQBuBAUad2F2ZXNSZXdhcmRBbW91bnRGb3JQZXJpb2QFBU1VTFQ4CQBoAgUPdG90YWxTdXJmU3Rha2VkAGQFBkhBTEZVUAQbd3hSZXdhcmRQZXJPbmVTdXJmRm9yUGVyaW9kAwkAAAIFF3d4UmV3YXJkQW1vdW50Rm9yUGVyaW9kAAAAAAkAbgQFF3d4UmV3YXJkQW1vdW50Rm9yUGVyaW9kBQVNVUxUOAUPdG90YWxTdXJmU3Rha2VkBQZIQUxGVVAEHHh0blJld2FyZFBlck9uZVN1cmZGb3JQZXJpb2QDCQAAAgUYeHRuUmV3YXJkQW1vdW50Rm9yUGVyaW9kAAAAAAkAbgQFGHh0blJld2FyZEFtb3VudEZvclBlcmlvZAUFTVVMVDgFD3RvdGFsU3VyZlN0YWtlZAUGSEFMRlVQBB52aXJlc1Jld2FyZFBlck9uZVN1cmZGb3JQZXJpb2QDCQAAAgUadmlyZXNSZXdhcmRBbW91bnRGb3JQZXJpb2QAAAAACQBuBAUadmlyZXNSZXdhcmRBbW91bnRGb3JQZXJpb2QFBU1VTFQ4BQ90b3RhbFN1cmZTdGFrZWQFBkhBTEZVUAkAzAgCCQEMSW50ZWdlckVudHJ5AgkBNmtleUN1cnJlbnRTdXJmU3Rha2luZ1Jld2FyZFBlcmlvZFdhdmVzQW1vdW50Rm9yT25lU3VyZgEFIWN1cnJlbnRTdXJmU3Rha2luZ1Jld2FyZHNQZXJpb2RJZAUed2F2ZXNSZXdhcmRQZXJPbmVTdXJmRm9yUGVyaW9kCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEza2V5Q3VycmVudFN1cmZTdGFraW5nUmV3YXJkUGVyaW9kV3hBbW91bnRGb3JPbmVTdXJmAQUhY3VycmVudFN1cmZTdGFraW5nUmV3YXJkc1BlcmlvZElkBRt3eFJld2FyZFBlck9uZVN1cmZGb3JQZXJpb2QJAMwIAgkBDEludGVnZXJFbnRyeQIJATRrZXlDdXJyZW50U3VyZlN0YWtpbmdSZXdhcmRQZXJpb2RYdG5BbW91bnRGb3JPbmVTdXJmAQUhY3VycmVudFN1cmZTdGFraW5nUmV3YXJkc1BlcmlvZElkBRx4dG5SZXdhcmRQZXJPbmVTdXJmRm9yUGVyaW9kCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQE2a2V5Q3VycmVudFN1cmZTdGFraW5nUmV3YXJkUGVyaW9kVmlyZXNBbW91bnRGb3JPbmVTdXJmAQUhY3VycmVudFN1cmZTdGFraW5nUmV3YXJkc1BlcmlvZElkBR52aXJlc1Jld2FyZFBlck9uZVN1cmZGb3JQZXJpb2QJAMwIAgkBDEludGVnZXJFbnRyeQIFJGN1cnJlbnRTdXJmU3Rha2luZ1Jld2FyZHNQZXJpb2RJZEtleQkAZAIFIWN1cnJlbnRTdXJmU3Rha2luZ1Jld2FyZHNQZXJpb2RJZAABBQNuaWwJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4BAnR4AQZ2ZXJpZnkACQD0AwMIBQJ0eAlib2R5Qnl0ZXMJAJEDAggFAnR4BnByb29mcwAACAUCdHgPc2VuZGVyUHVibGljS2V5xOwKTA==", "height": 3625607, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: DzwD4an6arqjiG4i3CVj6tjZ1LLAaXHYbQDEmiPUexeJ Next: BeghE9JRyXF9tv6BgRU16eP8y4CCC8kLwEoWahKCinwh Diff:
Old | New | Differences | |
---|---|---|---|
519 | 519 | let iterations = if ((30 > unclaimedXtnSwapsCount)) | |
520 | 520 | then unclaimedXtnSwapsCount | |
521 | 521 | else 30 | |
522 | - | let result = invoke(this, "internalAccumulateXtnSwapRewards", [iterations, 0, currentUserUnclaimedXtnSwapRewardPeriodId, 0, userTotalSurfStaked, i. | |
522 | + | let result = invoke(this, "internalAccumulateXtnSwapRewards", [iterations, 0, currentUserUnclaimedXtnSwapRewardPeriodId, 0, userTotalSurfStaked, i.originCaller.bytes], nil) | |
523 | 523 | if ((result == result)) | |
524 | 524 | then [IntegerEntry(keyCurrentUserUnclaimedXtnSwapRewardPeriodId(callerAddressString), newCurrentUserUnclaimedXtnSwapRewardPeriodId)] | |
525 | 525 | else throw("Strict value is not equal to itself.") |
Old | New | Differences | |
---|---|---|---|
1 | 1 | {-# STDLIB_VERSION 6 #-} | |
2 | 2 | {-# SCRIPT_TYPE ACCOUNT #-} | |
3 | 3 | {-# CONTENT_TYPE DAPP #-} | |
4 | 4 | let SEP = "__" | |
5 | 5 | ||
6 | 6 | let minAmount = 1000000 | |
7 | 7 | ||
8 | 8 | let MULT6 = 1000000 | |
9 | 9 | ||
10 | 10 | let MULT8 = 100000000 | |
11 | 11 | ||
12 | 12 | let wavesAssetId = fromBase58String("WAVES") | |
13 | 13 | ||
14 | 14 | let wxAssetId = base58'Atqv59EYzjFGuitKVnMRk6H8FukjoV3ktPorbEys25on' | |
15 | 15 | ||
16 | 16 | let surfAssetId = base58'At8D6NFFpheCbvKVnjVoeLL84Eo8NZn6ovManxfLaFWL' | |
17 | 17 | ||
18 | 18 | let xtnAssetId = base58'DG2xFkPdDwKUoBkzGAhQtLpSGzfXLiCYPEzeKH2Ad24p' | |
19 | 19 | ||
20 | 20 | let viresAssetId = base58'DSbbhLsSTeDg5Lsiufk2Aneh3DjVqJuPr2M9uU1gwy5p' | |
21 | 21 | ||
22 | 22 | let dexContract = base58'3PLPCb3wF2H2gtzohoAjeWcGaMKEiJvtE5X' | |
23 | 23 | ||
24 | 24 | let wavesExchangeDexContract = base58'3P68zNiufsu1viZpu1aY3cdahRRKcvV5N93' | |
25 | 25 | ||
26 | 26 | let neutrinoContractAddress = base58'3PC9BfRwJWWiw9AREE2B3eWzCks3CYtg4yo' | |
27 | 27 | ||
28 | 28 | let neutrinoStakingAddress = base58'3PBiotFpqjRMkkeFBccnQNUXUopy7KFez5C' | |
29 | 29 | ||
30 | 30 | let neutrinoPriceIndexAddress = base58'3P5Bfd58PPfNvBM2Hy8QfbcDqMeNtzg7KfP' | |
31 | 31 | ||
32 | 32 | let caseXtnSwapStateIdle = 0 | |
33 | 33 | ||
34 | 34 | let caseXtnSwapStateXtnToRewards = 1 | |
35 | 35 | ||
36 | 36 | let caseXtnSwapStateExchangeRewardsOnDex = 2 | |
37 | 37 | ||
38 | 38 | let constructedKey = "constructed" | |
39 | 39 | ||
40 | 40 | let xtnSwapStateEnumKey = "xtnSwapStateEnum" | |
41 | 41 | ||
42 | 42 | let totalSurfStakedKey = "totalSurfStaked" | |
43 | 43 | ||
44 | 44 | let pendingTotalSurfAmountToWithdrawalKey = "pendingTotalSuftAmountToWithdrawal" | |
45 | 45 | ||
46 | 46 | let devsWavesAmountKey = "devsWavesAmount" | |
47 | 47 | ||
48 | 48 | let devsSurfAmountKey = "devsSurfAmount" | |
49 | 49 | ||
50 | 50 | let devsWxAmountKey = "devsWxAmount" | |
51 | 51 | ||
52 | 52 | let devsXtnAmountKey = "devsXtnAmountKey" | |
53 | 53 | ||
54 | 54 | let xtnSwapBlockIdKey = "xtnSwapBlockId" | |
55 | 55 | ||
56 | 56 | let xtnSwapTransactionIdKey = "xtnSwapTransactionId" | |
57 | 57 | ||
58 | 58 | let xtnSwapPriceIndexKey = "xtnSwapPriceIndex" | |
59 | 59 | ||
60 | 60 | let xtnSwapXtnSwappedAmountKey = "xtnSwapXtnSwappedAmount" | |
61 | 61 | ||
62 | 62 | let xtnSwapWavesBalanceAtSwapKey = "xtnSwapWavesBalanceAtSwap" | |
63 | 63 | ||
64 | 64 | let xtnSwapWxBalanceAtSwapKey = "xtnSwapWxBalanceAtSwap" | |
65 | 65 | ||
66 | 66 | let xtnSwapViresBalanceAtSwapKey = "xtnSwapViresBalanceAtSwap" | |
67 | 67 | ||
68 | 68 | let xtnSwapXtnBalanceAtExchangeKey = "xtnSwapXtnBalanceAtExchange" | |
69 | 69 | ||
70 | 70 | let xtnSwapExchangeBlockIdKey = "xtnSwapExchangeBlockId" | |
71 | 71 | ||
72 | 72 | let lastSuccessSwapBlockHeight = "lastSuccessSwapBlockHeight" | |
73 | 73 | ||
74 | 74 | let currentWithdrawalPeriodIdKey = "currentWithdrawalPeriodId" | |
75 | 75 | ||
76 | 76 | let currentXTNSwapPeriodIdKey = "currentXTNSwapPeriodId" | |
77 | 77 | ||
78 | 78 | let currentSurfStakingRewardsPeriodIdKey = "currentSurfStakingRewardsPeriodIdKey" | |
79 | 79 | ||
80 | 80 | func keyCurrentXtnSwapPeriodXtnAmountForOneSurf (periodId) = (("currentXTNSwapPeriodXtnAmountForOneSurf" + SEP) + toString(periodId)) | |
81 | 81 | ||
82 | 82 | ||
83 | 83 | func keyCurrentSurfStakingRewardPeriodWavesAmountForOneSurf (periodId) = (("currentSurfStakingRewardPeriodWavesAmountForOneSurf" + SEP) + toString(periodId)) | |
84 | 84 | ||
85 | 85 | ||
86 | 86 | func keyCurrentSurfStakingRewardPeriodWxAmountForOneSurf (periodId) = (("currentSurfStakingRewardPeriodWwAmountForOneSurf" + SEP) + toString(periodId)) | |
87 | 87 | ||
88 | 88 | ||
89 | 89 | func keyCurrentSurfStakingRewardPeriodXtnAmountForOneSurf (periodId) = (("currentSurfStakingRewardPeriodXtnAmountForOneSurf" + SEP) + toString(periodId)) | |
90 | 90 | ||
91 | 91 | ||
92 | 92 | func keyCurrentSurfStakingRewardPeriodViresAmountForOneSurf (periodId) = (("currentSurfStakingRewardPeriodViresAmountForOneSurf" + SEP) + toString(periodId)) | |
93 | 93 | ||
94 | 94 | ||
95 | 95 | func keyCurrentUserTotalSurfStaked (address) = (("currentUserTotalSurfStaked" + SEP) + address) | |
96 | 96 | ||
97 | 97 | ||
98 | 98 | func keyCurrentUserUnclaimedXtnSwapRewardPeriodId (address) = (("currentUserUnclaimedXtnSwapRewardPeriodId" + SEP) + address) | |
99 | 99 | ||
100 | 100 | ||
101 | 101 | func keyCurrentUserUnclaimedSurfStakingRewardPeriodId (address) = (("currentUserUnclaimedSurfStakingRewardPeriodId" + SEP) + address) | |
102 | 102 | ||
103 | 103 | ||
104 | 104 | func keyCurrentUserPendingWithdrawalPeriodId (address) = (("currentUserPendingWithdrawalPeriodId" + SEP) + address) | |
105 | 105 | ||
106 | 106 | ||
107 | 107 | func keyCurrentUserTotalSurfPendingForWithdrawal (address) = (("currentUserTotalSurfPendingForWithdrawal" + SEP) + address) | |
108 | 108 | ||
109 | 109 | ||
110 | 110 | func asPayment (v) = match v { | |
111 | 111 | case p: AttachedPayment => | |
112 | 112 | p | |
113 | 113 | case _ => | |
114 | 114 | throw("fail to cast into AttachedPayment") | |
115 | 115 | } | |
116 | 116 | ||
117 | 117 | ||
118 | 118 | func asInt (val) = match val { | |
119 | 119 | case valInt: Int => | |
120 | 120 | valInt | |
121 | 121 | case _ => | |
122 | 122 | throw("fail to cast into Int") | |
123 | 123 | } | |
124 | 124 | ||
125 | 125 | ||
126 | 126 | func asIntOrThrow (val,message) = match val { | |
127 | 127 | case valInt: Int => | |
128 | 128 | valInt | |
129 | 129 | case _ => | |
130 | 130 | throw(message) | |
131 | 131 | } | |
132 | 132 | ||
133 | 133 | ||
134 | 134 | func asIntOrDef (val,default) = match val { | |
135 | 135 | case valInt: Int => | |
136 | 136 | valInt | |
137 | 137 | case _ => | |
138 | 138 | default | |
139 | 139 | } | |
140 | 140 | ||
141 | 141 | ||
142 | 142 | func asString (val) = match val { | |
143 | 143 | case valString: String => | |
144 | 144 | valString | |
145 | 145 | case _ => | |
146 | 146 | throw("fail to cast into String") | |
147 | 147 | } | |
148 | 148 | ||
149 | 149 | ||
150 | 150 | func asStringOrDef (val,default) = match val { | |
151 | 151 | case valString: String => | |
152 | 152 | valString | |
153 | 153 | case _ => | |
154 | 154 | default | |
155 | 155 | } | |
156 | 156 | ||
157 | 157 | ||
158 | 158 | func asBoolean (val) = match val { | |
159 | 159 | case valBool: Boolean => | |
160 | 160 | valBool | |
161 | 161 | case _ => | |
162 | 162 | throw("fail to cast into Boolean") | |
163 | 163 | } | |
164 | 164 | ||
165 | 165 | ||
166 | 166 | func asBooleanOrDef (val,default) = match val { | |
167 | 167 | case valBool: Boolean => | |
168 | 168 | valBool | |
169 | 169 | case _ => | |
170 | 170 | default | |
171 | 171 | } | |
172 | 172 | ||
173 | 173 | ||
174 | 174 | func currentProportion (xtnSwapLimitMax) = { | |
175 | 175 | let totalSurfStaked = getIntegerValue(totalSurfStakedKey) | |
176 | 176 | fraction(toBigInt(totalSurfStaked), toBigInt(MULT6), toBigInt(xtnSwapLimitMax), HALFUP) | |
177 | 177 | } | |
178 | 178 | ||
179 | 179 | ||
180 | 180 | func checkProportion (xtnSwapLimitMax,surfAmount,xntAmount) = { | |
181 | 181 | let proportion = currentProportion(xtnSwapLimitMax) | |
182 | 182 | let expectedSurfAmount = toInt(fraction(proportion, toBigInt(xntAmount), toBigInt(MULT6), HALFUP)) | |
183 | 183 | if ((expectedSurfAmount == surfAmount)) | |
184 | 184 | then true | |
185 | 185 | else throw((((("With " + toString(xtnSwapLimitMax)) + " XNT amount you should provide ") + toString(expectedSurfAmount)) + " SURF amount to stake")) | |
186 | 186 | } | |
187 | 187 | ||
188 | 188 | ||
189 | 189 | func interactWithSwapParamsByUser () = { | |
190 | 190 | let result = invoke(Address(neutrinoStakingAddress), "swapParamsByUserSYSREADONLY", [this, 0], nil) | |
191 | 191 | if ((result == result)) | |
192 | 192 | then match result { | |
193 | 193 | case tuple: (Int, Int, Int, Int, Int, Int, Int) => | |
194 | 194 | [tuple._1, tuple._2, tuple._3, tuple._4, tuple._5, tuple._6, tuple._7] | |
195 | 195 | case _ => | |
196 | 196 | throw("FATAL: Can't fetch data from neutrino contract") | |
197 | 197 | } | |
198 | 198 | else throw("Strict value is not equal to itself.") | |
199 | 199 | } | |
200 | 200 | ||
201 | 201 | ||
202 | 202 | func isUserHasUnclaimedRewardsInPreviousPeriods (address) = { | |
203 | 203 | let userUnclaimedXtnSwapRewardPeriodId = asIntOrDef(getInteger(keyCurrentUserUnclaimedXtnSwapRewardPeriodId(address)), -1) | |
204 | 204 | let userUnclaimedSurfStakingRewardsPeriodId = asIntOrDef(getInteger(keyCurrentUserUnclaimedSurfStakingRewardPeriodId(address)), -1) | |
205 | 205 | let currentXTNSwapPeriod = asIntOrDef(getInteger(currentXTNSwapPeriodIdKey), 0) | |
206 | 206 | let currentSurfStakingRewardsPeriod = asIntOrDef(getInteger(currentSurfStakingRewardsPeriodIdKey), 0) | |
207 | 207 | if (if ((userUnclaimedXtnSwapRewardPeriodId > -1)) | |
208 | 208 | then (currentXTNSwapPeriod > userUnclaimedXtnSwapRewardPeriodId) | |
209 | 209 | else false) | |
210 | 210 | then true | |
211 | 211 | else if (if ((userUnclaimedSurfStakingRewardsPeriodId > -1)) | |
212 | 212 | then (currentSurfStakingRewardsPeriod > userUnclaimedSurfStakingRewardsPeriodId) | |
213 | 213 | else false) | |
214 | 214 | then true | |
215 | 215 | else false | |
216 | 216 | } | |
217 | 217 | ||
218 | 218 | ||
219 | 219 | @Callable(i) | |
220 | 220 | func constructor () = match getBoolean(constructedKey) { | |
221 | 221 | case _: Boolean => | |
222 | 222 | throw("Constructor can be called just once") | |
223 | 223 | case _ => | |
224 | 224 | [BooleanEntry(constructedKey, true), IntegerEntry(currentWithdrawalPeriodIdKey, 0), IntegerEntry(currentXTNSwapPeriodIdKey, 0), IntegerEntry(currentSurfStakingRewardsPeriodIdKey, 0), IntegerEntry(pendingTotalSurfAmountToWithdrawalKey, 0), IntegerEntry(devsWavesAmountKey, 0), IntegerEntry(devsSurfAmountKey, 0), IntegerEntry(devsWxAmountKey, 0), IntegerEntry(devsXtnAmountKey, 0), IntegerEntry(lastSuccessSwapBlockHeight, 0), IntegerEntry(xtnSwapStateEnumKey, caseXtnSwapStateIdle)] | |
225 | 225 | } | |
226 | 226 | ||
227 | 227 | ||
228 | 228 | ||
229 | 229 | @Callable(i) | |
230 | 230 | func extendPriceIndexByOneUp () = { | |
231 | 231 | let swapPriceIndex = getIntegerValue(xtnSwapPriceIndexKey) | |
232 | 232 | [IntegerEntry(xtnSwapPriceIndexKey, (swapPriceIndex + 1))] | |
233 | 233 | } | |
234 | 234 | ||
235 | 235 | ||
236 | 236 | ||
237 | 237 | @Callable(i) | |
238 | 238 | func writePriceIndex (priceIndex) = [IntegerEntry(xtnSwapPriceIndexKey, priceIndex)] | |
239 | 239 | ||
240 | 240 | ||
241 | 241 | ||
242 | 242 | @Callable(i) | |
243 | 243 | func stake () = if ((getIntegerValue(xtnSwapStateEnumKey) != caseXtnSwapStateIdle)) | |
244 | 244 | then throw("XTN swap in progress, wait approximatelly 3 minutes") | |
245 | 245 | else if ((size(i.payments) != 1)) | |
246 | 246 | then throw("You must include exactly one payment in transaction") | |
247 | 247 | else { | |
248 | 248 | let payment = asPayment(i.payments[0]) | |
249 | 249 | if (if ((payment.assetId != surfAssetId)) | |
250 | 250 | then true | |
251 | 251 | else (minAmount > payment.amount)) | |
252 | 252 | then throw("Wrong assetId or amount") | |
253 | 253 | else { | |
254 | 254 | let callerAddressString = toBase58String(i.caller.bytes) | |
255 | 255 | if (isUserHasUnclaimedRewardsInPreviousPeriods(callerAddressString)) | |
256 | 256 | then throw("You have unclaimed rewards, claim them first, then stake again") | |
257 | 257 | else { | |
258 | 258 | let result = invoke(Address(neutrinoStakingAddress), "stake", nil, [payment]) | |
259 | 259 | if ((result == result)) | |
260 | 260 | then { | |
261 | 261 | let newTotalSurfStaked = match getInteger(totalSurfStakedKey) { | |
262 | 262 | case v: Int => | |
263 | 263 | (v + payment.amount) | |
264 | 264 | case _ => | |
265 | 265 | payment.amount | |
266 | 266 | } | |
267 | 267 | let callerTotalSurfStakedKey = keyCurrentUserTotalSurfStaked(callerAddressString) | |
268 | 268 | let newCallerTotalSurfStaked = match getInteger(callerTotalSurfStakedKey) { | |
269 | 269 | case v: Int => | |
270 | 270 | (v + payment.amount) | |
271 | 271 | case _ => | |
272 | 272 | payment.amount | |
273 | 273 | } | |
274 | 274 | let currentXTNSwapPeriod = asIntOrDef(getInteger(currentXTNSwapPeriodIdKey), 0) | |
275 | 275 | let currentSurfStakingRewardsPeriod = asIntOrDef(getInteger(currentSurfStakingRewardsPeriodIdKey), 0) | |
276 | 276 | [IntegerEntry(totalSurfStakedKey, newTotalSurfStaked), IntegerEntry(callerTotalSurfStakedKey, newCallerTotalSurfStaked), IntegerEntry(keyCurrentUserUnclaimedXtnSwapRewardPeriodId(callerAddressString), currentXTNSwapPeriod), IntegerEntry(keyCurrentUserUnclaimedSurfStakingRewardPeriodId(callerAddressString), currentSurfStakingRewardsPeriod)] | |
277 | 277 | } | |
278 | 278 | else throw("Strict value is not equal to itself.") | |
279 | 279 | } | |
280 | 280 | } | |
281 | 281 | } | |
282 | 282 | ||
283 | 283 | ||
284 | 284 | ||
285 | 285 | @Callable(i) | |
286 | 286 | func applyForPendingWithdraw (amount) = if ((getIntegerValue(xtnSwapStateEnumKey) != caseXtnSwapStateIdle)) | |
287 | 287 | then throw("XTN swap in progress, wait approximatelly 3 minutes") | |
288 | 288 | else if ((size(i.payments) > 0)) | |
289 | 289 | then throw("This function does not accept payments") | |
290 | 290 | else if ((0 >= amount)) | |
291 | 291 | then throw("Amount must be positive") | |
292 | 292 | else { | |
293 | 293 | let callerAddressString = toBase58String(i.caller.bytes) | |
294 | 294 | let callerTotalSurfStaked = getIntegerValue(keyCurrentUserTotalSurfStaked(callerAddressString)) | |
295 | 295 | if ((amount > callerTotalSurfStaked)) | |
296 | 296 | then throw("Insufficient balance to withdraw") | |
297 | 297 | else if (isUserHasUnclaimedRewardsInPreviousPeriods(callerAddressString)) | |
298 | 298 | then throw("You have unclaimed rewards, claim them first, then try again") | |
299 | 299 | else { | |
300 | 300 | let currentWithdrawalId = getIntegerValue(currentWithdrawalPeriodIdKey) | |
301 | 301 | let pendingTotalSurfToUnstakeFromNeutrino = getIntegerValue(pendingTotalSurfAmountToWithdrawalKey) | |
302 | 302 | let userPendingWithdrawalPeriodId = asIntOrDef(getInteger(keyCurrentUserPendingWithdrawalPeriodId(callerAddressString)), -1) | |
303 | 303 | let userTotalSurfPendingForWithdrawal = asIntOrDef(getInteger(keyCurrentUserTotalSurfPendingForWithdrawal(callerAddressString)), 0) | |
304 | 304 | if (if ((userPendingWithdrawalPeriodId > -1)) | |
305 | 305 | then (currentWithdrawalId > userPendingWithdrawalPeriodId) | |
306 | 306 | else false) | |
307 | 307 | then throw("You have unclaimed suft on contract, please perform claim first") | |
308 | 308 | else { | |
309 | 309 | let userNewTotalSurfStakedAmount = (callerTotalSurfStaked - amount) | |
310 | 310 | let userNewTotalSurfPendingForWithdrawal = (userTotalSurfPendingForWithdrawal + amount) | |
311 | 311 | let newPendingTotalSurfToUnstakeFromNeutrino = (pendingTotalSurfToUnstakeFromNeutrino + amount) | |
312 | 312 | let newTotalSurfStakedAmount = (getIntegerValue(totalSurfStakedKey) - amount) | |
313 | 313 | [IntegerEntry(keyCurrentUserTotalSurfStaked(callerAddressString), userNewTotalSurfStakedAmount), IntegerEntry(keyCurrentUserPendingWithdrawalPeriodId(callerAddressString), currentWithdrawalId), IntegerEntry(keyCurrentUserTotalSurfPendingForWithdrawal(callerAddressString), userNewTotalSurfPendingForWithdrawal), IntegerEntry(pendingTotalSurfAmountToWithdrawalKey, newPendingTotalSurfToUnstakeFromNeutrino), IntegerEntry(totalSurfStakedKey, newTotalSurfStakedAmount)] | |
314 | 314 | } | |
315 | 315 | } | |
316 | 316 | } | |
317 | 317 | ||
318 | 318 | ||
319 | 319 | ||
320 | 320 | @Callable(i) | |
321 | 321 | func performDistributedWithdraw () = if ((size(i.payments) > 0)) | |
322 | 322 | then throw("This function does not accept payments") | |
323 | 323 | else { | |
324 | 324 | let currentWithdrawalId = getIntegerValue(currentWithdrawalPeriodIdKey) | |
325 | 325 | let pendingTotalSurfToUnstakeFromNeutrino = getIntegerValue(pendingTotalSurfAmountToWithdrawalKey) | |
326 | 326 | if ((0 >= pendingTotalSurfToUnstakeFromNeutrino)) | |
327 | 327 | then nil | |
328 | 328 | else { | |
329 | 329 | let result = invoke(Address(neutrinoStakingAddress), "unstake", [pendingTotalSurfToUnstakeFromNeutrino], nil) | |
330 | 330 | if ((result == result)) | |
331 | 331 | then [IntegerEntry(currentWithdrawalPeriodIdKey, (currentWithdrawalId + 1)), IntegerEntry(pendingTotalSurfAmountToWithdrawalKey, 0)] | |
332 | 332 | else throw("Strict value is not equal to itself.") | |
333 | 333 | } | |
334 | 334 | } | |
335 | 335 | ||
336 | 336 | ||
337 | 337 | ||
338 | 338 | @Callable(i) | |
339 | 339 | func claimSurf () = if ((size(i.payments) > 0)) | |
340 | 340 | then throw("This function does not accept payments") | |
341 | 341 | else { | |
342 | 342 | let callerAddressString = toBase58String(i.caller.bytes) | |
343 | 343 | let currentWithdrawalPeriodId = getIntegerValue(currentWithdrawalPeriodIdKey) | |
344 | 344 | let userWithdrawalPeriodId = asIntOrDef(getInteger(keyCurrentUserPendingWithdrawalPeriodId(callerAddressString)), -1) | |
345 | 345 | let userTotalSurfPendingForWithdrawal = asIntOrDef(getInteger(keyCurrentUserTotalSurfPendingForWithdrawal(callerAddressString)), 0) | |
346 | 346 | if (if ((userWithdrawalPeriodId == -1)) | |
347 | 347 | then true | |
348 | 348 | else (userTotalSurfPendingForWithdrawal == 0)) | |
349 | 349 | then throw("Nothing to withdraw") | |
350 | 350 | else if ((userWithdrawalPeriodId == currentWithdrawalPeriodId)) | |
351 | 351 | then throw("You must wait for period to complete") | |
352 | 352 | else [ScriptTransfer(i.caller, userTotalSurfPendingForWithdrawal, surfAssetId), DeleteEntry(keyCurrentUserPendingWithdrawalPeriodId(callerAddressString)), DeleteEntry(keyCurrentUserTotalSurfPendingForWithdrawal(callerAddressString))] | |
353 | 353 | } | |
354 | 354 | ||
355 | 355 | ||
356 | 356 | ||
357 | 357 | @Callable(i) | |
358 | 358 | func xtnSwapPart1swapXTNFromNeutrino () = if ((getIntegerValue(xtnSwapStateEnumKey) != caseXtnSwapStateIdle)) | |
359 | 359 | then throw("Wrong state, must be Idle") | |
360 | 360 | else { | |
361 | 361 | let withdrawResult = invoke(this, "performDistributedWithdraw", nil, nil) | |
362 | 362 | if ((withdrawResult == withdrawResult)) | |
363 | 363 | then { | |
364 | 364 | let surfStakingRewards = invoke(this, "surfStakingRewardsClaimFromNeutrino", nil, nil) | |
365 | 365 | if ((surfStakingRewards == surfStakingRewards)) | |
366 | 366 | then { | |
367 | 367 | let result = invoke(Address(neutrinoContractAddress), "swapParamsByUserSYSREADONLY", [toString(this), 0], nil) | |
368 | 368 | if ((result == result)) | |
369 | 369 | then match result { | |
370 | 370 | case tuple: (Int, Int, Int, Int, Int, Int, Int) => | |
371 | 371 | if ((tuple._3 > 0)) | |
372 | 372 | then throw((("Time is not come yet, you need to wait " + toString(tuple._3)) + " blocks")) | |
373 | 373 | else { | |
374 | 374 | let maxSwapAmount = tuple._7 | |
375 | 375 | if ((1000000 > maxSwapAmount)) | |
376 | 376 | then throw("Min XTN amount to swap is 1, stake more SURF") | |
377 | 377 | else if ((maxSwapAmount > assetBalance(this, xtnAssetId))) | |
378 | 378 | then throw("XTN Balance on contract is smaller than max swap amount, increase XTN contract balance") | |
379 | 379 | else { | |
380 | 380 | let currentWavesBalance = wavesBalance(this) | |
381 | 381 | let currentWXBalance = assetBalance(this, wxAssetId) | |
382 | 382 | let currentViresBalance = assetBalance(this, viresAssetId) | |
383 | 383 | let swapNeutrinoToAssets = invoke(Address(neutrinoContractAddress), "swapNeutrinoToBasket", nil, [AttachedPayment(xtnAssetId, maxSwapAmount)]) | |
384 | 384 | if ((swapNeutrinoToAssets == swapNeutrinoToAssets)) | |
385 | 385 | then { | |
386 | 386 | let priceIndex = (getIntegerValue(Address(neutrinoPriceIndexAddress), "price_index") + 1) | |
387 | 387 | [IntegerEntry(xtnSwapBlockIdKey, height), StringEntry(xtnSwapTransactionIdKey, toBase58String(i.transactionId)), IntegerEntry(xtnSwapPriceIndexKey, priceIndex), IntegerEntry(xtnSwapXtnSwappedAmountKey, maxSwapAmount), IntegerEntry(xtnSwapWavesBalanceAtSwapKey, currentWavesBalance.available), IntegerEntry(xtnSwapWxBalanceAtSwapKey, currentWXBalance), IntegerEntry(xtnSwapViresBalanceAtSwapKey, currentViresBalance), IntegerEntry(xtnSwapStateEnumKey, caseXtnSwapStateXtnToRewards)] | |
388 | 388 | } | |
389 | 389 | else throw("Strict value is not equal to itself.") | |
390 | 390 | } | |
391 | 391 | } | |
392 | 392 | case _ => | |
393 | 393 | throw("Incorrect data from neutrino smart contract") | |
394 | 394 | } | |
395 | 395 | else throw("Strict value is not equal to itself.") | |
396 | 396 | } | |
397 | 397 | else throw("Strict value is not equal to itself.") | |
398 | 398 | } | |
399 | 399 | else throw("Strict value is not equal to itself.") | |
400 | 400 | } | |
401 | 401 | ||
402 | 402 | ||
403 | 403 | ||
404 | 404 | @Callable(i) | |
405 | 405 | func xtnSwapPart2exchangeXtnSwapRewardsOnDex () = if ((getIntegerValue(xtnSwapStateEnumKey) != caseXtnSwapStateXtnToRewards)) | |
406 | 406 | then throw("Wrong state, must be XtnToRewards") | |
407 | 407 | else if ((getIntegerValue(xtnSwapBlockIdKey) >= height)) | |
408 | 408 | then throw("Must wait for 1 block") | |
409 | 409 | else { | |
410 | 410 | let swapTransationId = getStringValue(xtnSwapTransactionIdKey) | |
411 | 411 | let swapPriceIndex = getIntegerValue(xtnSwapPriceIndexKey) | |
412 | 412 | let withdraw_res = invoke(Address(neutrinoContractAddress), "withdraw", [toString(this), swapPriceIndex, swapTransationId], nil) | |
413 | 413 | if ((withdraw_res == withdraw_res)) | |
414 | 414 | then { | |
415 | 415 | let wavesBalanceAtSwap = getIntegerValue(xtnSwapWavesBalanceAtSwapKey) | |
416 | 416 | let wxBalanceAtSwap = getIntegerValue(xtnSwapWxBalanceAtSwapKey) | |
417 | 417 | let viresBalanceAtSwap = getIntegerValue(xtnSwapViresBalanceAtSwapKey) | |
418 | 418 | let currentWavesBalance = wavesBalance(this) | |
419 | 419 | let currentWXBalance = assetBalance(this, wxAssetId) | |
420 | 420 | let currentViresBalance = assetBalance(this, viresAssetId) | |
421 | 421 | let wavesRewards = (currentWavesBalance.available - wavesBalanceAtSwap) | |
422 | 422 | if ((wavesRewards == wavesRewards)) | |
423 | 423 | then { | |
424 | 424 | let wxRewards = (currentWXBalance - wxBalanceAtSwap) | |
425 | 425 | if ((wxRewards == wxRewards)) | |
426 | 426 | then { | |
427 | 427 | let viresRewards = (currentViresBalance - viresBalanceAtSwap) | |
428 | 428 | if ((viresRewards == viresRewards)) | |
429 | 429 | then { | |
430 | 430 | let xtnAmountBeforeExchange = assetBalance(this, xtnAssetId) | |
431 | 431 | if ((xtnAmountBeforeExchange == xtnAmountBeforeExchange)) | |
432 | 432 | then { | |
433 | 433 | let xtnSwapped = getIntegerValue(xtnSwapXtnSwappedAmountKey) | |
434 | 434 | let exchangeWaves = if ((0 >= wavesRewards)) | |
435 | 435 | then nil | |
436 | 436 | else { | |
437 | 437 | let wavesSwap = invoke(Address(wavesExchangeDexContract), "swap", [0, toString(Address(xtnAssetId)), toString(this)], [AttachedPayment(unit, wavesRewards)]) | |
438 | 438 | if ((wavesSwap == wavesSwap)) | |
439 | 439 | then nil | |
440 | 440 | else throw("Strict value is not equal to itself.") | |
441 | 441 | } | |
442 | 442 | if ((exchangeWaves == exchangeWaves)) | |
443 | 443 | then { | |
444 | 444 | let exchangeVires = if ((0 >= viresRewards)) | |
445 | 445 | then nil | |
446 | 446 | else { | |
447 | 447 | let viresSwap = invoke(Address(wavesExchangeDexContract), "swap", [0, toString(Address(xtnAssetId)), toString(this)], [AttachedPayment(unit, viresRewards)]) | |
448 | 448 | if ((viresSwap == viresSwap)) | |
449 | 449 | then nil | |
450 | 450 | else throw("Strict value is not equal to itself.") | |
451 | 451 | } | |
452 | 452 | if ((exchangeVires == exchangeVires)) | |
453 | 453 | then { | |
454 | 454 | let exchangeWX = if ((0 >= wxRewards)) | |
455 | 455 | then nil | |
456 | 456 | else { | |
457 | 457 | let wxSwap = invoke(Address(wavesExchangeDexContract), "swap", [0, toString(Address(xtnAssetId)), toString(this)], [AttachedPayment(wxAssetId, wxRewards)]) | |
458 | 458 | if ((wxSwap == wxSwap)) | |
459 | 459 | then nil | |
460 | 460 | else throw("Strict value is not equal to itself.") | |
461 | 461 | } | |
462 | 462 | if ((exchangeWX == exchangeWX)) | |
463 | 463 | then { | |
464 | 464 | let currentXtnAmount = assetBalance(this, xtnAssetId) | |
465 | 465 | let currentXtnSwapPeriodId = getIntegerValue(currentXTNSwapPeriodIdKey) | |
466 | 466 | let totalSurfStaked = getIntegerValue(totalSurfStakedKey) | |
467 | 467 | let xtnRewardAmountForPeriod = (currentXtnAmount - (xtnAmountBeforeExchange + xtnSwapped)) | |
468 | 468 | let xtnRewardPerOneSurfForPeriod = if ((0 >= xtnRewardAmountForPeriod)) | |
469 | 469 | then 0 | |
470 | 470 | else fraction(xtnRewardAmountForPeriod, MULT6, totalSurfStaked, HALFUP) | |
471 | 471 | [IntegerEntry("XTN_REWARD_FOR_PERIOD", xtnRewardAmountForPeriod), IntegerEntry("WAVES_REWARDS_FOR_SWAP", wavesRewards), IntegerEntry("WX_REWARDS_FOR_SWAP", wxRewards), IntegerEntry("VIRES_REWARDS_FOR_SWAP", viresRewards), IntegerEntry(xtnSwapXtnBalanceAtExchangeKey, assetBalance(this, xtnAssetId)), IntegerEntry(xtnSwapExchangeBlockIdKey, height), IntegerEntry(keyCurrentXtnSwapPeriodXtnAmountForOneSurf(currentXtnSwapPeriodId), xtnRewardPerOneSurfForPeriod), IntegerEntry(currentXTNSwapPeriodIdKey, (currentXtnSwapPeriodId + 1)), IntegerEntry(xtnSwapStateEnumKey, caseXtnSwapStateIdle)] | |
472 | 472 | } | |
473 | 473 | else throw("Strict value is not equal to itself.") | |
474 | 474 | } | |
475 | 475 | else throw("Strict value is not equal to itself.") | |
476 | 476 | } | |
477 | 477 | else throw("Strict value is not equal to itself.") | |
478 | 478 | } | |
479 | 479 | else throw("Strict value is not equal to itself.") | |
480 | 480 | } | |
481 | 481 | else throw("Strict value is not equal to itself.") | |
482 | 482 | } | |
483 | 483 | else throw("Strict value is not equal to itself.") | |
484 | 484 | } | |
485 | 485 | else throw("Strict value is not equal to itself.") | |
486 | 486 | } | |
487 | 487 | else throw("Strict value is not equal to itself.") | |
488 | 488 | } | |
489 | 489 | ||
490 | 490 | ||
491 | 491 | ||
492 | 492 | @Callable(i) | |
493 | 493 | func claim () = { | |
494 | 494 | let xtnResult = invoke(this, "claimXtnSwapRewards", nil, nil) | |
495 | 495 | if ((xtnResult == xtnResult)) | |
496 | 496 | then nil | |
497 | 497 | else throw("Strict value is not equal to itself.") | |
498 | 498 | } | |
499 | 499 | ||
500 | 500 | ||
501 | 501 | ||
502 | 502 | @Callable(i) | |
503 | 503 | func claimXtnSwapRewards () = if ((size(i.payments) > 0)) | |
504 | 504 | then throw("This function does not accept payments") | |
505 | 505 | else { | |
506 | 506 | let callerAddressString = toBase58String(i.originCaller.bytes) | |
507 | 507 | let currentXtnSwapPeriodId = asIntOrDef(getInteger(currentXTNSwapPeriodIdKey), 0) | |
508 | 508 | let currentUserUnclaimedXtnSwapRewardPeriodId = asIntOrDef(getInteger(keyCurrentUserUnclaimedXtnSwapRewardPeriodId(callerAddressString)), -1) | |
509 | 509 | if ((currentUserUnclaimedXtnSwapRewardPeriodId == -1)) | |
510 | 510 | then $Tuple2([StringEntry("debug", keyCurrentUserUnclaimedXtnSwapRewardPeriodId(callerAddressString))], -1) | |
511 | 511 | else if ((currentUserUnclaimedXtnSwapRewardPeriodId == currentXtnSwapPeriodId)) | |
512 | 512 | then throw("You need to wait for current swap period to finish") | |
513 | 513 | else { | |
514 | 514 | let unclaimedXtnSwapsCount = (currentXtnSwapPeriodId - currentUserUnclaimedXtnSwapRewardPeriodId) | |
515 | 515 | let userTotalSurfStaked = getIntegerValue(keyCurrentUserTotalSurfStaked(callerAddressString)) | |
516 | 516 | let newCurrentUserUnclaimedXtnSwapRewardPeriodId = if ((unclaimedXtnSwapsCount > 30)) | |
517 | 517 | then (currentUserUnclaimedXtnSwapRewardPeriodId + 30) | |
518 | 518 | else currentXtnSwapPeriodId | |
519 | 519 | let iterations = if ((30 > unclaimedXtnSwapsCount)) | |
520 | 520 | then unclaimedXtnSwapsCount | |
521 | 521 | else 30 | |
522 | - | let result = invoke(this, "internalAccumulateXtnSwapRewards", [iterations, 0, currentUserUnclaimedXtnSwapRewardPeriodId, 0, userTotalSurfStaked, i. | |
522 | + | let result = invoke(this, "internalAccumulateXtnSwapRewards", [iterations, 0, currentUserUnclaimedXtnSwapRewardPeriodId, 0, userTotalSurfStaked, i.originCaller.bytes], nil) | |
523 | 523 | if ((result == result)) | |
524 | 524 | then [IntegerEntry(keyCurrentUserUnclaimedXtnSwapRewardPeriodId(callerAddressString), newCurrentUserUnclaimedXtnSwapRewardPeriodId)] | |
525 | 525 | else throw("Strict value is not equal to itself.") | |
526 | 526 | } | |
527 | 527 | } | |
528 | 528 | ||
529 | 529 | ||
530 | 530 | ||
531 | 531 | @Callable(i) | |
532 | 532 | func internalAccumulateXtnSwapRewards (iterations,current,startXtnSwapPeriodId,accumulatedRewardXtn,userSurfAmount,address) = if ((this != i.caller)) | |
533 | 533 | then throw("Internal function") | |
534 | 534 | else if ((current >= iterations)) | |
535 | 535 | then if ((accumulatedRewardXtn > 0)) | |
536 | 536 | then [ScriptTransfer(Address(address), accumulatedRewardXtn, xtnAssetId)] | |
537 | 537 | else nil | |
538 | 538 | else { | |
539 | 539 | let xtnAmountPerSurf = asIntOrDef(getInteger(keyCurrentXtnSwapPeriodXtnAmountForOneSurf((startXtnSwapPeriodId + current))), 0) | |
540 | 540 | let reward = if ((xtnAmountPerSurf == 0)) | |
541 | 541 | then 0 | |
542 | 542 | else fraction(xtnAmountPerSurf, userSurfAmount, MULT6, HALFUP) | |
543 | 543 | let result = invoke(this, "internalAccumulateXtnSwapRewards", [iterations, (current + 1), (startXtnSwapPeriodId + current), (accumulatedRewardXtn + reward), userSurfAmount, address], nil) | |
544 | 544 | if ((result == result)) | |
545 | 545 | then nil | |
546 | 546 | else throw("Strict value is not equal to itself.") | |
547 | 547 | } | |
548 | 548 | ||
549 | 549 | ||
550 | 550 | ||
551 | 551 | @Callable(i) | |
552 | 552 | func claimSurfStakingRewards () = if ((size(i.payments) > 0)) | |
553 | 553 | then throw("This function does not accept payments") | |
554 | 554 | else { | |
555 | 555 | let callerAddressString = toBase58String(i.caller.bytes) | |
556 | 556 | let currentSurfStakingRewardsPeriodId = asIntOrDef(getInteger(currentSurfStakingRewardsPeriodIdKey), 0) | |
557 | 557 | let currentUserUnclaimedSurfStakingRewardPeriodId = asIntOrDef(getInteger(keyCurrentUserUnclaimedSurfStakingRewardPeriodId(callerAddressString)), -1) | |
558 | 558 | if ((currentUserUnclaimedSurfStakingRewardPeriodId == -1)) | |
559 | 559 | then $Tuple2(nil, -1) | |
560 | 560 | else if ((currentUserUnclaimedSurfStakingRewardPeriodId == currentSurfStakingRewardsPeriodId)) | |
561 | 561 | then throw("You need to wait for current swap period to finish") | |
562 | 562 | else { | |
563 | 563 | let unclaimedSurfStakingsCount = (currentSurfStakingRewardsPeriodId - currentUserUnclaimedSurfStakingRewardPeriodId) | |
564 | 564 | let userTotalSurfStaked = getIntegerValue(keyCurrentUserTotalSurfStaked(callerAddressString)) | |
565 | 565 | let newCurrentUserUnclaimedSurfStakingRewardPeriodId = if ((unclaimedSurfStakingsCount > 45)) | |
566 | 566 | then (currentUserUnclaimedSurfStakingRewardPeriodId + 45) | |
567 | 567 | else currentSurfStakingRewardsPeriodId | |
568 | 568 | let iterations = if ((45 > unclaimedSurfStakingsCount)) | |
569 | 569 | then unclaimedSurfStakingsCount | |
570 | 570 | else 45 | |
571 | 571 | let result = invoke(this, "internalAccumulateSurfStakingRewards", [iterations, 0, currentUserUnclaimedSurfStakingRewardPeriodId, 0, 0, 0, 0, userTotalSurfStaked, i.caller.bytes], nil) | |
572 | 572 | if ((result == result)) | |
573 | 573 | then [IntegerEntry(keyCurrentUserUnclaimedSurfStakingRewardPeriodId(callerAddressString), newCurrentUserUnclaimedSurfStakingRewardPeriodId)] | |
574 | 574 | else throw("Strict value is not equal to itself.") | |
575 | 575 | } | |
576 | 576 | } | |
577 | 577 | ||
578 | 578 | ||
579 | 579 | ||
580 | 580 | @Callable(i) | |
581 | 581 | func internalAccumulateSurfStakingRewards (iterations,current,startSurfSwapPeriodId,accumulatedRewardWaves,accumulatedRewardWx,accumulatedRewardXtn,accumulatedRewardVires,userSurfAmount,address) = if ((this != i.caller)) | |
582 | 582 | then throw("Internal function") | |
583 | 583 | else if ((current >= iterations)) | |
584 | 584 | then if (if (if (if ((accumulatedRewardXtn > 0)) | |
585 | 585 | then true | |
586 | 586 | else (accumulatedRewardWaves > 0)) | |
587 | 587 | then true | |
588 | 588 | else (accumulatedRewardWx > 0)) | |
589 | 589 | then true | |
590 | 590 | else (accumulatedRewardVires > 0)) | |
591 | 591 | then [ScriptTransfer(Address(address), accumulatedRewardXtn, xtnAssetId), ScriptTransfer(Address(address), accumulatedRewardWaves, wavesAssetId), ScriptTransfer(Address(address), accumulatedRewardWx, wxAssetId), ScriptTransfer(Address(address), accumulatedRewardVires, viresAssetId)] | |
592 | 592 | else nil | |
593 | 593 | else { | |
594 | 594 | let xtnAmountPerSurf = asIntOrDef(getInteger(keyCurrentSurfStakingRewardPeriodXtnAmountForOneSurf((startSurfSwapPeriodId + current))), 0) | |
595 | 595 | let wavesAmountPerSurf = asIntOrDef(getInteger(keyCurrentSurfStakingRewardPeriodWavesAmountForOneSurf((startSurfSwapPeriodId + current))), 0) | |
596 | 596 | let wxAmountPerSurf = asIntOrDef(getInteger(keyCurrentSurfStakingRewardPeriodWxAmountForOneSurf((startSurfSwapPeriodId + current))), 0) | |
597 | 597 | let viresAmountPerSurf = asIntOrDef(getInteger(keyCurrentSurfStakingRewardPeriodViresAmountForOneSurf((startSurfSwapPeriodId + current))), 0) | |
598 | 598 | let xtnReward = if ((xtnAmountPerSurf == 0)) | |
599 | 599 | then 0 | |
600 | 600 | else fraction(xtnAmountPerSurf, userSurfAmount, MULT8, HALFUP) | |
601 | 601 | let wavesReward = if ((wavesAmountPerSurf == 0)) | |
602 | 602 | then 0 | |
603 | 603 | else fraction(wavesAmountPerSurf, userSurfAmount, MULT8, HALFUP) | |
604 | 604 | let wxReward = if ((wxAmountPerSurf == 0)) | |
605 | 605 | then 0 | |
606 | 606 | else fraction(wxAmountPerSurf, userSurfAmount, MULT8, HALFUP) | |
607 | 607 | let viresReward = if ((viresAmountPerSurf == 0)) | |
608 | 608 | then 0 | |
609 | 609 | else fraction(viresAmountPerSurf, userSurfAmount, MULT8, HALFUP) | |
610 | 610 | let result = invoke(this, "internalAccumulateSurfStakingRewards", [iterations, (current + 1), (startSurfSwapPeriodId + current), (accumulatedRewardWaves + wavesReward), (accumulatedRewardWx + wxReward), (accumulatedRewardXtn + xtnReward), (accumulatedRewardVires + viresReward), userSurfAmount, address], nil) | |
611 | 611 | if ((result == result)) | |
612 | 612 | then nil | |
613 | 613 | else throw("Strict value is not equal to itself.") | |
614 | 614 | } | |
615 | 615 | ||
616 | 616 | ||
617 | 617 | ||
618 | 618 | @Callable(i) | |
619 | 619 | func surfStakingRewardsClaimFromNeutrino () = if ((size(i.payments) > 0)) | |
620 | 620 | then throw("This function does not accept payments") | |
621 | 621 | else { | |
622 | 622 | let currentWavesOnContract = wavesBalance(this) | |
623 | 623 | if ((currentWavesOnContract == currentWavesOnContract)) | |
624 | 624 | then { | |
625 | 625 | let currentWxOnContract = assetBalance(this, wxAssetId) | |
626 | 626 | if ((currentWxOnContract == currentWxOnContract)) | |
627 | 627 | then { | |
628 | 628 | let currentXtnOnContract = assetBalance(this, xtnAssetId) | |
629 | 629 | if ((currentXtnOnContract == currentXtnOnContract)) | |
630 | 630 | then { | |
631 | 631 | let currentViresOnContract = assetBalance(this, viresAssetId) | |
632 | 632 | if ((currentViresOnContract == currentViresOnContract)) | |
633 | 633 | then { | |
634 | 634 | let result = invoke(Address(neutrinoStakingAddress), "claimRewards", nil, nil) | |
635 | 635 | if ((result == result)) | |
636 | 636 | then { | |
637 | 637 | let newWavesOnContract = wavesBalance(this) | |
638 | 638 | let newWxOnContract = assetBalance(this, wxAssetId) | |
639 | 639 | let newXtnOnContract = assetBalance(this, xtnAssetId) | |
640 | 640 | let newViresOnContract = assetBalance(this, viresAssetId) | |
641 | 641 | let wavesRewardAmountForPeriod = (newWavesOnContract.available - currentWavesOnContract.available) | |
642 | 642 | let wxRewardAmountForPeriod = (newWxOnContract - currentWxOnContract) | |
643 | 643 | let xtnRewardAmountForPeriod = (newXtnOnContract - currentXtnOnContract) | |
644 | 644 | let viresRewardAmountForPeriod = (newViresOnContract - currentViresOnContract) | |
645 | 645 | let currentSurfStakingRewardsPeriodId = getIntegerValue(currentSurfStakingRewardsPeriodIdKey) | |
646 | 646 | let totalSurfStaked = asIntOrDef(getInteger(totalSurfStakedKey), 0) | |
647 | 647 | if ((totalSurfStaked == 0)) | |
648 | 648 | then nil | |
649 | 649 | else { | |
650 | 650 | let wavesRewardPerOneSurfForPeriod = if ((wavesRewardAmountForPeriod == 0)) | |
651 | 651 | then 0 | |
652 | 652 | else fraction(wavesRewardAmountForPeriod, MULT8, (totalSurfStaked * 100), HALFUP) | |
653 | 653 | let wxRewardPerOneSurfForPeriod = if ((wxRewardAmountForPeriod == 0)) | |
654 | 654 | then 0 | |
655 | 655 | else fraction(wxRewardAmountForPeriod, MULT8, totalSurfStaked, HALFUP) | |
656 | 656 | let xtnRewardPerOneSurfForPeriod = if ((xtnRewardAmountForPeriod == 0)) | |
657 | 657 | then 0 | |
658 | 658 | else fraction(xtnRewardAmountForPeriod, MULT8, totalSurfStaked, HALFUP) | |
659 | 659 | let viresRewardPerOneSurfForPeriod = if ((viresRewardAmountForPeriod == 0)) | |
660 | 660 | then 0 | |
661 | 661 | else fraction(viresRewardAmountForPeriod, MULT8, totalSurfStaked, HALFUP) | |
662 | 662 | [IntegerEntry(keyCurrentSurfStakingRewardPeriodWavesAmountForOneSurf(currentSurfStakingRewardsPeriodId), wavesRewardPerOneSurfForPeriod), IntegerEntry(keyCurrentSurfStakingRewardPeriodWxAmountForOneSurf(currentSurfStakingRewardsPeriodId), wxRewardPerOneSurfForPeriod), IntegerEntry(keyCurrentSurfStakingRewardPeriodXtnAmountForOneSurf(currentSurfStakingRewardsPeriodId), xtnRewardPerOneSurfForPeriod), IntegerEntry(keyCurrentSurfStakingRewardPeriodViresAmountForOneSurf(currentSurfStakingRewardsPeriodId), viresRewardPerOneSurfForPeriod), IntegerEntry(currentSurfStakingRewardsPeriodIdKey, (currentSurfStakingRewardsPeriodId + 1))] | |
663 | 663 | } | |
664 | 664 | } | |
665 | 665 | else throw("Strict value is not equal to itself.") | |
666 | 666 | } | |
667 | 667 | else throw("Strict value is not equal to itself.") | |
668 | 668 | } | |
669 | 669 | else throw("Strict value is not equal to itself.") | |
670 | 670 | } | |
671 | 671 | else throw("Strict value is not equal to itself.") | |
672 | 672 | } | |
673 | 673 | else throw("Strict value is not equal to itself.") | |
674 | 674 | } | |
675 | 675 | ||
676 | 676 | ||
677 | 677 | @Verifier(tx) | |
678 | 678 | func verify () = sigVerify(tx.bodyBytes, tx.proofs[0], tx.senderPublicKey) | |
679 | 679 |
github/deemru/w8io/3ef1775 350.00 ms ◑