Loading…
Loading…
A mintable ANM20 fungible token contract in Animica vm_py, with an offline dapp UI that simulates transfer and owner-only mint. Deployment is prepared for Animica testnet.
Language: Animica vm_py (Python)
Contract deployment is prepared for Animica testnet; live wallet-signed deployment connects in the next phase. Forge never executes contract code on the server.
# Animica vm_py smart contract — ANM20 fungible token
# Runs on the Animica VM. Deployment is prepared for Animica testnet.
class ANM20Token:
"""A standard ANM20 fungible token with owner-only minting.
All persistent data lives in self.state, a dict that the Animica VM
commits between calls. Balances and allowances are keyed by address
string; missing keys read as 0.
"""
def __init__(self, name, symbol, decimals, total_supply, owner):
self.name = name
self.symbol = symbol
self.decimals = int(decimals)
self.total_supply = int(total_supply)
self.owner = owner
# state["balances"][addr] -> int
# state["allowances"][owner][spender] -> int
self.state = {
"balances": {owner: int(total_supply)},
"allowances": {},
}
# ── Views ────────────────────────────────────────────────────────────
def balance_of(self, addr):
return int(self.state["balances"].get(addr, 0))
def allowance(self, owner, spender):
return int(self.state["allowances"].get(owner, {}).get(spender, 0))
# ── Transfers ────────────────────────────────────────────────────────
def transfer(self, caller, to, amount):
amount = int(amount)
if amount < 0:
raise ValueError("amount must be non-negative")
balances = self.state["balances"]
frm = int(balances.get(caller, 0))
if frm < amount:
raise ValueError("insufficient balance")
balances[caller] = frm - amount
balances[to] = int(balances.get(to, 0)) + amount
return True
def approve(self, caller, spender, amount):
amount = int(amount)
if amount < 0:
raise ValueError("amount must be non-negative")
allowances = self.state["allowances"]
if caller not in allowances:
allowances[caller] = {}
allowances[caller][spender] = amount
return True
def transfer_from(self, caller, sender, to, amount):
amount = int(amount)
if amount < 0:
raise ValueError("amount must be non-negative")
allowances = self.state["allowances"]
allowed = int(allowances.get(sender, {}).get(caller, 0))
if allowed < amount:
raise ValueError("allowance exceeded")
balances = self.state["balances"]
frm = int(balances.get(sender, 0))
if frm < amount:
raise ValueError("insufficient balance")
balances[sender] = frm - amount
balances[to] = int(balances.get(to, 0)) + amount
allowances[sender][caller] = allowed - amount
return True
# ── Supply ───────────────────────────────────────────────────────────
def mint(self, caller, to, amount):
if caller != self.owner:
raise PermissionError("only owner can mint")
amount = int(amount)
if amount < 0:
raise ValueError("amount must be non-negative")
balances = self.state["balances"]
balances[to] = int(balances.get(to, 0)) + amount
self.total_supply += amount
return True
An Animica smart-contract tip jar: anyone can tip, only the owner can withdraw. This preview simulates the contract locally — on-chain deploy and settlement are prepared for the next phase.