← Contract Hero · WorkLearnPlugins
acc-evm-wal
Lesson 01 · Foundry

Anchor a Walrus blob ID per EVM address, in 50 lines of Solidity.

Write a Solidity contract that stores one Walrus blob ID per caller, then verify it with a Foundry test suite. The contract is small enough to fit on one screen; the goal is to nail the three load-bearing choices — bytes32 storage, msg.sender-keyed mapping, and a plain read path that hands off URL construction to the off-chain client.

Slug: 01-walrus-solidity-basics Stack: Foundry · Solidity 0.8.20 Sections: 3 Final gate: forge test · 4 tests

What you'll write

Three sections, all editing one file: src/WalrusAnchor.sol. Each section's key moment is the one decision that makes the rest of the section fall into place.

  • s01 · anchor state

    Anchor state — the on-chain footprint

    Picking bytes32 for the blob ID. Walrus blob IDs are exactly 32 bytes (a BLAKE2b-256 hash of the content), so they slot into a single storage word — one SSTORE per anchor regardless of underlying blob size. Using string or bytes would double the cost and break the constant-gas property.

  • s02 · write path

    The write path — anchor(bytes32 blobId)

    Using msg.sender as the mapping key (rather than taking an address owner parameter). This makes the on-chain authentication implicit — the EVM has already proven who the caller is by the time we reach this line, so we don't need any explicit require(msg.sender == owner) check.

  • s03 · read path

    The read path — blobOf(address) and the equivalence gate

    The read path is a plain mapping lookup with no decoding, no aggregation, and no events — the off-chain client uses the returned bytes32 to build a URL like https://aggregator.walrus-testnet.walrus.space/v1/blobs/<blobId-as-base64url> and fetches the actual content from there. The contract's job ends at returning the pointer.

Verification

The reference-app's Foundry suite is the equivalence gate. Run it inside the workspace:

forge test

All 4 tests should pass: storesBlobIdForCaller · emitsEvent · overwritesPrevious · blobOf returns zero for unknown.

Sources

Read the reference-app on GitHub, or jump to the parent showcase for the full design context.