Recommended format
One strict CSV, one exact-byte hash, and one weighted ticket selection. Luckotto records the hash but does not interpret the file or enforce the reseller’s customer payout.
Make the CSV
Start with the two required case-sensitive columns. Any uniquely named partner columns may follow.
ticket_id,weight_wei
LKT-7M4Q-K2PF,1000000000000000
LKT-9C8W-X5NR,1000000000000000Use valid UTF-8 without a byte-order mark; LF or CRLF records; no blank lines, quotes, escaping, control characters, or surrounding field whitespace. Ticket IDs are nonempty and unique. Weights are positive decimal integers.
Hash the bytes
Do not normalize or reserialize the file.
positionCommitment = keccak256(exactCsvBytes)
sum(row.weight_wei) = position stakeChanging any character, newline, column, or row order changes the commitment. Publish the exact file when placing the position and give each customer their ticket ID on a signed receipt.
Select the ticket
First verify that the reseller’s Luckotto position was selected.
localPoint = candidatePoint - position.rangeStart
for row in file order:
next = cursor + row.weight_wei
if localPoint < next: select row
cursor = nextThe winning position guarantees 0 ≤ localPoint < position stake, so exactly one weighted row is selected. The Luckotto candidate already combines Ethereum and Quicknet randomness; using the target block hash alone would create a weaker, separate draw.
Availability: Luckotto still resolves if the CSV is unavailable. Withholding it only makes the reseller’s customer allocation unverifiable.