Network

Posts (Buzz)

A post is called a buzz. Posting is intentionally the cheapest thing the network does: there is no per-post storage — a buzz is one increment of a global counter (bidCounter, first bid = 1) plus a single event. Ownership, threading, and content are all reconstructed by indexers from the log. Deleting a post that isn't yours is a no-op that indexers ignore.

Everything is an event

buzz(uid, BuzzInput[]) emits one Buzzed event per item and returns the created bids, so an integrating contract can compose on the result. There is no bidOwner slot, no reply table, and no reaction counter in state — dropping ~20k gas of storage per post is exactly why this is affordable.

Buzzed(uint256 indexed uid, uint256 indexed bid, uint256 indexed parentBid,
       bytes32 postType, bytes32[] content, uint256[] taggedUsers, bytes32[] settings)
BuzzDeleted(uint256 indexed uid, uint256 indexed bid)

The API is batch-only: you always pass an array of BuzzInput. A dedicated single-post function would save only ~1k gas, not worth a second code path.

Every action takes the acting uid explicitly, and the contract checks permissions[uid][actor]. Passing a uid you don't hold POST for simply reverts — an address acts for a uid, it never implicitly owns one.

Post types

postType is a bytes32 that is self-describing — it carries its own meaning as right-padded ASCII, with no registry and no numeric IDs:

  • The empty word (0x0) is a plaintext post: parentBid == 0 is an original, any other parentBid is a reply.
  • Every other value is an ASCII tag — bytes32("repost"), bytes32("quote"), bytes32("poll"), bytes32("article"), and so on.

The contract does not validate postType or parentBid; clients decide what to render and what to filter. New post types are therefore a client convention, never a contract change — this is how a single immutable contract supports an open-ended and growing catalog of content formats.

Content

content is an opaque bytes32[]. It can be raw text chunks packed into words, an IPFS CID, an Arweave id, an encrypted envelope, or anything else. How to decode it is signalled by the settings word, so a client reads settings first and interprets content accordingly. taggedUsers is a parallel list of uids mentioned in the post.

Content settings

settings is a bytes32[] of self-describing flags travelling with the post — encoding scheme, content type, visibility hints, and other client conventions. Like post types, these bits are meaning agreed between clients, not interpreted by the contract. Keeping encoding out of the contract is what lets content formats evolve without redeploying.

Reactions

Reactions are not stored on-chain either — react emits an event and, optionally, moves an ERC-20 tip in the same call. It is batch-only and requires the REACT permission.

Reacted(uint256 indexed uid, uint256 indexed bid, uint256 reactionType,
        address token, uint256 amount, uint256 toUid, address to)
  • reactionType 0–15 are the reserved core set (0 = none / remove); values ≥ 1024 are client-defined. Not validated.
  • A tip is the reactor's own money and carries no protocol cut — the full amount is sent to the recipient's payout address via transferFrom. The recipient uid and resolved address are in the event so indexers can attribute tips without trusting the client.
  • The token must be a real contract (codeless addresses revert), so a Reacted event can never fabricate a tip against an EOA. A malicious token can still lie, so indexers should verify tip amounts against the token's own Transfer logs before displaying them.
  • If the recipient's payout resolves to address(0) the tip reverts — tokens are never burned or partially moved.

Media

Buzzes reference media by a fileId registered separately, so images and files are not inlined into post content. See Media for the file registry.