03 · Documentation
Shard
The proposal that names the addresses to exile, posts the bond, and fixes the snapshot.
A Shard is the proposal. It names who should leave, fixes the moment that counts, and puts a bond at stake. Every exile starts here.
In Athens, the ostrakon was the shard of pottery a citizen wrote a name on. On Elysium, it is one transaction.
Proposing
A Shard is created with a single call: propose(token, exiles[], balanceRoot).
It takes three things. The token. The list of addresses to exile. The Merkle root of every holder's balance at that block.
Who can propose
The proposer must hold at least 0.5 % of the token's total supply at the moment of proposing. This is checked against the live balance in that block.
The threshold keeps the door narrow. Anyone with a real stake can knock. Not everyone can.
Who can be named
A Shard names between 1 and 10 addresses. Each named address must hold at least 1 % of total supply at that moment. The same address cannot be named twice. The proposer cannot name itself.
Naming is per address. A wallet below 1 % cannot be named, whoever owns it.
The bond
Every Shard carries a bond in $OSTRA. On testnet the bond is a constant of 1,000 OSTRA, readable from bondAmount(). On mainnet the bond is pegged to a HYPE value. It is still paid in $OSTRA. No other token is accepted.
Proposing takes two steps. First approve the bond. Then propose.
The bond has three possible fates:
| Outcome | What happens to the bond |
|---|---|
| A challenge succeeds | Paid in full to the challenger |
| The vote misses quorum | Burned |
| The vote reaches quorum | Returned to the proposer, whatever the result |
A careless root costs the bond. A proposal no one cares about costs the bond. A proposal the holders take seriously costs nothing.
One Shard at a time
A token can have only one active Shard. A Shard is active while it is in challenge or in vote. A Shard that is cancelled by a challenge or fails its vote frees the token for a new one.
The snapshot
The snapshot block is the block that includes the proposal. Everything that follows is measured against it.
At proposal time, Shard records the total supply and the balance of each named address. These numbers set the quorum and the size of the new token later.
Votes and claims both use snapshot balances. What happens after the snapshot does not count.
The balance root
The proposer supplies a Merkle root. It commits to one leaf per holder with a nonzero balance at the snapshot block. Each leaf is an address and its balance.
Why the proposer supplies it
An arbitrary token cannot list its own holders. Reading every balance on-chain in one transaction is impossible.
So the chain does not compute the root. It verifies it. The proposer does the work off-chain. Anyone can check it during the challenge window. Every vote and every claim is then proven against it.
How the tree is built
The tree is canonical. Anyone can rebuild it from the token's public Transfer events and get the same root.
- Each leaf is the double keccak of the ABI-encoded address and balance.
- Leaves are sorted.
- Pairs are hashed in sorted order.
This matches the OpenZeppelin Merkle tree format, so standard libraries can build proofs for it.
bytes32 leaf = keccak256(bytes.concat(keccak256(abi.encode(holder, balance))));
The Ostrakon site rebuilds the root for every Shard and checks it against the one on-chain. If they differ, it says so.
Token requirement
The token must keep ERC20Votes-style checkpoints. The challenge reads the token's own historical record of balances at the snapshot block. Without checkpoints, there is nothing to check against.
The demo tokens on testnet use ERC20Votes with self-delegation locked. Votes always equal balances. The checkpointed record is the balance record.
The challenge
The challenge window lasts 24 hours from the proposal.
During that time, anyone can call challenge(shardId, holder, statedBalance, proof). The challenger shows one leaf that is in the root and proves it with a Merkle proof. If the balance in that leaf differs from the token's own checkpointed balance for that holder at the snapshot block, the Shard is cancelled.
The challenger receives the whole bond.
One wrong leaf is enough. A root is either exact or it is worthless.
Opening the vote
After 24 hours, anyone can call open(shardId). The Shard moves to the Ekklesia and the vote begins.
No one has to wait for the proposer. No one has to wait for a team.
Parameters
| Parameter | Value |
|---|---|
| Proposer minimum | 0.5 % of total supply |
| Named address minimum | 1 % of total supply |
| Addresses per Shard | 1 to 10 |
| Bond | 1,000 OSTRA on testnet |
| Challenge period | 24 hours |
| Active Shards per token | 1 |