Mappings: many values, one namespace
There is no dict in storage. You build one by composing keys — and the prefix you choose is a security boundary.
Storage is flat: bytes to bytes. A mapping is just a key-building function:
def _k_bal(addr: bytes) -> bytes:
return b"anm20:bal:" + addr
def _k_allow(owner: bytes, spender: bytes) -> bytes:
return b"anm20:allow:" + owner + b":" + spender
That is exactly how the Animica token standard does it. Every key is prefixed with the contract's own namespace so two different mappings can never collide.
Composite keys need a separator you control. prefix + a + b is unsafe if a can vary in length: for two-byte pieces, a=b"xy", b=b"z" and a=b"x", b=b"yz" both build prefix + b"xyz" — one user's allowance becomes another's. Animica addresses are fixed 32-byte values so concatenation is safe *there*, but the moment a key part is variable-length you need a separator or a length prefix. The token standard uses b":" between parts for exactly this reason.
Your turn
Implement a two-level mapping: set_score(game, player, points) and score(game, player). Different games must keep separate scores for the same player.
Hints
One way to do it
from stdlib import storage
def _k(game: bytes, player: bytes) -> bytes:
# A separator between the variable-length parts keeps
# ("ab","c") and ("a","bc") from colliding.
return b"demo:score:" + game + b":" + player
def _uget(key: bytes) -> int:
raw = storage.get(key, b"")
return 0 if raw == b"" else int.from_bytes(raw, "big")
def _uset(key: bytes, value: int) -> None:
v = int(value)
if v == 0:
storage.delete(key)
return
storage.set(key, v.to_bytes(max(1, (v.bit_length() + 7) // 8), "big"))
def set_score(game: bytes, player: bytes, points: int) -> None:
_uset(_k(bytes(game), bytes(player)), int(points))
def score(game: bytes, player: bytes) -> int:
return _uget(_k(bytes(game), bytes(player)))
Claim your 10 ANM
Finish this lesson and claim 10 ANM, once per address. Paid from the Animica treasury in batches — allow a few minutes.
Stuck? Ask
Answered by Animica's own free inference network. It is donated GPU capacity, so give it 20-30 seconds.