Encoding
Within Gameday a market is associated with an oracle event and is deployed as separate contract. Markets may have more than two outcomes, so this flexibility is supported with distinct market types and associated encoding rules.
ERC-6909
Market contracts mint and burn ERC-6909 outcome tokens. The token ID is an encoded outcome for the associated event. On settlement, market contract allows winning tokens IDs to be claimed as rewards.
We have included an example python encoding module, which allows for manual encoding. Client order builder integrates this encoding. Market type and number of outcomes is available as part of Market object from REST API.
Bit layout (256 bits, big-endian)
| 255 - 252 | 251 - 246 | 245 – 241 | 240 | 239 - 0 |
|---|---|---|---|---|
market type uint4 | empty | n_outcomes uint5 | yes/no 1 bit | payload 240 bits |
Payload per market type:
BINARY- 0: empty (no payload), only yes/noRANKED- 1: N outcome indices packed as uint8 (up to 30 outcomes)TOP- 2: outcomes represented as bits set in payload (up to 30 outcomes)OVERUNDER- 3: outcome_val as int64 (two's complement) in lowest 64 bitsEXACT- 4: outcome_val as int64 (two's complement) in lowest 64 bitsRANGE- 5: low_bound (int64) in bits 127–64, high_bound (int64) in bits 63-0
Examples
BINARY market type
| 255 - 252 | 251 - 246 | 245 – 241 | 240 | 239 - 0 |
|---|---|---|---|---|
market type uint4 | empty | n_outcomes uint5 | yes/no 1 bit | payload 240 bits |
| 0000 | 000000 | 00001 | 1 | 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 |
# uint256
5300541194335152988749892502228755547482451690626856874364818603877859328
RANKED market type
- Yes/No:
YES, - Single outcome
- Index
2of candidate outcomes
| 255 - 252 | 251 - 246 | 245 – 241 | 240 | 239 - 0 |
|---|---|---|---|---|
market type uint4 | empty | n_outcomes uint5 | yes/no 1 bit | payload 240 bits |
| 0001 | 000000 | 00001 | 1 | 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010 |
7240539271461818982632353158044480077861029009396286490382342212897155842050
- Yes/No:
YES, - 3 outcomes
- Indices
2, 0, 3
| 255 - 252 | 251 - 246 | 245 – 241 | 240 | 239 - 0 |
|---|---|---|---|---|
market type uint4 | empty | n_outcomes uint5 | yes/no 1 bit | payload 240 bits |
| 0001 | 000000 | 00011 | 1 | 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000011 |
7247606659720932519950686348047451751924338944983788966214828637702326452227
Packing Ranked indices
for index, outcome_idx in enumerate(outcome_indices):
payload |= outcome_idx << (8 * (n_outcomes - 1 - index))
Decoding Ranked payload
for index in range(n_outcomes -1, -1, -1):
decoded_payload.append((payload >> (8 * index)) & 0xFF)
>>> [2, 0, 3]
TOP market type
- Yes/No:
YES, - 3 outcomes
- Indices
0, 2, 3of candidate outcomes
| 255 - 252 | 251 - 246 | 245 – 241 | 240 | 239 - 0 |
|---|---|---|---|---|
market type uint4 | empty | n_outcomes uint5 | yes/no 1 bit | payload 240 bits |
| 0010 | 000000 | 00011 | 1 | 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001101 |
14484612237053194733923872911090445992753712986586324218680927638196896923661
Packing TOP indices
for outcome_idx in outcome_indices:
payload |= 1 << outcome_idx
Decoding TOP payload
diff = 0 ^ payload
while diff:
idx = (diff & -diff).bit_length() - 1
indices.append(idx)
diff &= diff - 1
>>> [0, 2, 3]
Or simple scan:
for i in range(payload.bit_length()):
if (payload & 1 << 1):
indices.append(i)
Scalar markets
- Market type:
OVERUNDER - Yes/No:
NO, - 1 outcome
- Outcome value:
74500
| 255 - 252 | 251 - 246 | 245 – 241 | 240 | 239 - 0 |
|---|---|---|---|---|
market type uint4 | empty | n_outcomes uint5 | yes/no 1 bit | payload 240 bits |
| 0011 | 000000 | 00001 | 0 | 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010010001100000100 |
21714550426126343410578726284130468559519777092601356995314540213886297121540
Decoding scalar types
_UINT64_MASK = (1 << 64) - 1
raw_value = payload & _UINT64_MASK
outcome_value = raw_value if raw_value < (1 << 63) else raw_value - (1 << 64)
RANGE markets
- Market type:
RANGE - Yes/No:
YES, - 1 outcome
- Low bound:
65000 - High bound:
75000
| 255 - 252 | 251 - 246 | 245 – 241 | 240 | 239 - 0 |
|---|---|---|---|---|
market type uint4 | empty | n_outcomes uint5 | yes/no 1 bit | payload 240 bits |
| 0101 | 000000 | 00001 | 1 | 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011111101111010000000000000000000000000000000000000000000000000010010010011111000 |
36190328427855646222854682707717199959694352659703304318243224612197585986808
Decoding RANGE
low_bound_raw = (payload >> 64) & _UINT64_MASK
high_bound_raw = payload & _UINT64_MASK
low_bound = low_bound_raw if low_bound_raw < (1 << 63) else low_bound_raw - (1 << 64)
high_bound = high_bound_raw if high_bound_raw < (1 << 63) else high_bound_raw - (1 << 64)