Testing before you deploy
Deployed code is permanent and public. Everything you can find locally costs nothing to fix.
A contract is immutable once deployed and its storage is public forever. There is no hotfix, and a mistake is visible to everyone who looks. The asymmetry is extreme: a bug found locally costs a minute, and the same bug found after deployment may cost everything the contract holds.
The VM runs as a normal Python library, so a contract is testable as a normal Python module — no chain, no node, no waiting for blocks:
from vm_py.stdlib import abi, storage
def test_transfer_rejects_overdraft():
ctx = abi.CallContext(
sender=b"\x11" * 32,
origin=b"\x11" * 32,
contract=b"\x22" * 32,
chain_id=1,
block_height=100,
block_timestamp=1_700_000_000,
)
with abi.runtime_context(ctx):
contract.mint(b"\x11" * 32, 100)
try:
contract.transfer(b"\xbb" * 32, 500)
assert False, "overdraft should have reverted"
except Exception as e:
assert b"insufficient" in getattr(e, "reason", b"")
Call storage.reset_backend() between tests, or state leaks from one test into the next and you get passes that depend on execution order.
Test behaviour, not source text. This academy grades your exercises by *calling your functions and checking what happened* — return values, revert reasons, emitted events — never by looking for a keyword in your code. That is deliberate: a check that greps for abi.require passes for a comment mentioning it and fails for a correct solution written differently.
Write your own tests the same way. Assert on outcomes.
What to cover, in priority order:
1. The failure paths. Overdrafts, wrong caller, zero amounts, an allowance that is one unit short. Bugs live here, not in the happy path. 2. State after a failed call. A revert must leave storage untouched. Assert the balance is unchanged *after* the failure — several exercises here check exactly that, because "it reverted" and "it changed nothing" are different claims. 3. Boundaries. Exactly at the cap, exactly zero, exactly the full balance. 4. Ordering. Call things in an order you did not intend. Can accept run before nominate? Can init be called twice?
Then rehearse the deployment itself, on a devnet. animica network set devnet gives you a chain where ANM is free and mistakes are free with it. Deploy there, call every method, and confirm the receipt says what you expect.
And remember what the deployment track showed: inclusion is not execution. A transaction can be safely in a block with status: 0 because your constructor reverted. Always read the receipt status — on devnet and on mainnet.
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.