Security and composition · ≈ 10 min

Why the VM takes things away from you

Every restriction in the contract VM traces back to one requirement: every node must compute the identical result, forever.

A block is only valid if every node that re-executes it agrees on the result. Not "usually agrees" — agrees exactly, byte for byte, on hardware that does not exist yet, years from now. Every restriction you have hit follows from that.

No clock. time.time() differs per node. Use abi.block_timestamp(), which is a value agreed by consensus and identical for everyone re-executing that block.

No randomness. random and os.urandom produce a different value every call. Anything that must be unpredictable has to come from a source consensus agrees on — a commit-reveal scheme, or the chain's randomness beacon.

No network, no files. A remote server can be down, or answer differently, or answer differently *to different nodes on purpose*. That is not a chain any more.

No floats. IEEE-754 rounding varies with compiler flags and hardware. Money is integers — 1 ANM = 10^9 nANM, and every amount in the system is an integer count of those base units.

Two things that look deterministic and are not.

set and dict iteration order: Python fixes dict ordering by insertion, but set iteration depends on hash values, and for str and bytes those are randomized per process unless PYTHONHASHSEED is pinned. Iterating a set of strings can genuinely produce different orders on different nodes. Sort before you iterate.

Exception *messages*: catching an error and storing str(e) embeds text that can change between Python versions. Branch on the error type, never on its prose.

Deterministic does not mean implemented. treasury.balance() and treasury.transfer() exist in the VM's stdlib and are, as of 2026-08-20, stubs: balance always returns 0 and transfer is a no-op whose own docstring says *"real implementation would mutate balances"*. The real versions live in the chain runtime.

A contract written against them in a local sandbox appears to work perfectly and moves nothing. Before you rely on any stdlib primitive for value movement, call it and check the result rather than trusting the name — this academy's own lessons were re-scoped after doing exactly that.

The practical test, whenever you are unsure: could two honest nodes running this line get different answers? If yes, it cannot be in a contract — it goes off-chain, and its result comes back in a transaction the contract can verify.

Stuck? Ask

Answered by Animica's own free inference network. It is donated GPU capacity, so give it 20-30 seconds.