This guide covers writing, deploying, and interacting with smart contracts on Vernachain.
Vernachain smart contracts are written in Python and executed in a secure virtual machine. The system provides:
class MyContract:
def __init__(self):
"""Constructor - called when contract is deployed."""
self.owner = globals()['sender']
self.value = 0
def set_value(self, new_value: int):
"""Update the stored value."""
# Access execution context
sender = globals()['sender']
gas_counter = globals()['gas_counter']
# Charge gas for storage operation
gas_counter.charge(10)
# Only owner can update
assert sender == self.owner, "Not authorized"
self.value = new_value
def get_value(self) -> int:
"""Read the stored value."""
# Read operations are free
return self.value
globals()['sender']
: Transaction sender addressglobals()['value']
: Amount of VERNA sent with callglobals()['gas_counter']
: Gas tracking objectglobals()['block']
: Current block information# Gas costs for operations
gas_counter.charge(10) # Basic operation
gas_counter.charge_storage(32) # Storage operation
gas_counter.charge_compute(100) # Heavy computation
Here’s a complete ERC20-like token contract:
class Token:
def __init__(self, name: str, symbol: str, total_supply: int):
"""Initialize the token contract."""
self.name = name
self.symbol = symbol
self.decimals = 18
self.total_supply = total_supply
# Storage
self.balances = {globals()['sender']: total_supply}
self.allowances = {}
# Events
self.Transfer = Event('Transfer')
self.Approval = Event('Approval')
def balance_of(self, account: str) -> int:
"""Get the token balance of an account."""
return self.balances.get(account, 0)
def transfer(self, to: str, amount: int) -> bool:
"""Transfer tokens to another address."""
sender = globals()['sender']
gas_counter = globals()['gas_counter']
# Charge gas
gas_counter.charge(100)
# Check balance
assert self.balances.get(sender, 0) >= amount, "Insufficient balance"
# Update balances
self.balances[sender] = self.balances.get(sender, 0) - amount
self.balances[to] = self.balances.get(to, 0) + amount
# Emit event
self.Transfer.emit(sender, to, amount)
return True
def approve(self, spender: str, amount: int) -> bool:
"""Approve spender to spend tokens."""
sender = globals()['sender']
gas_counter = globals()['gas_counter']
gas_counter.charge(50)
if sender not in self.allowances:
self.allowances[sender] = {}
self.allowances[sender][spender] = amount
self.Approval.emit(sender, spender, amount)
return True
def transfer_from(self, from_addr: str, to: str, amount: int) -> bool:
"""Transfer tokens on behalf of another address."""
sender = globals()['sender']
gas_counter = globals()['gas_counter']
gas_counter.charge(150)
# Check allowance
allowed = self.allowances.get(from_addr, {}).get(sender, 0)
assert allowed >= amount, "Insufficient allowance"
# Check balance
assert self.balances.get(from_addr, 0) >= amount, "Insufficient balance"
# Update balances
self.balances[from_addr] -= amount
self.balances[to] = self.balances.get(to, 0) + amount
# Update allowance
self.allowances[from_addr][sender] -= amount
self.Transfer.emit(from_addr, to, amount)
return True
Using CLI:
python -m src.cli deploy 0xsender...addr token.py \
--args '{"name": "MyToken", "symbol": "MTK", "total_supply": 1000000}'
Using SDK:
from src.sdk.vernachain import VernaChainSDK
sdk = VernaChainSDK()
await sdk.connect()
# Deploy contract
contract_addr = await sdk.deploy_contract(
from_address="0xsender...addr",
code=open("token.py").read(),
constructor_args=["MyToken", "MTK", 1000000]
)
Using CLI:
# Transfer tokens
python -m src.cli call 0xsender...addr 0xcontract...addr transfer \
--args '{"to": "0xrecipient...addr", "amount": 100}'
# Check balance
python -m src.cli call 0xsender...addr 0xcontract...addr balance_of \
--args '{"account": "0xrecipient...addr"}'
Using SDK:
# Transfer tokens
result = await sdk.call_contract(
contract_address="0xcontract...addr",
from_address="0xsender...addr",
function_name="transfer",
args=["0xrecipient...addr", 100]
)
# Check balance
balance = await sdk.call_contract(
contract_address="0xcontract...addr",
from_address="0xsender...addr",
function_name="balance_of",
args=["0xrecipient...addr"]
)