OpenAI writes ERC20 in Odra

2 min read Original article ↗

use odra::{Variable, types::Address, contract_env, Mapping, execution_error, U256};

#[odra::module]

pub struct ERC20 {

name: Variable<String>,

symbol: Variable<String>,

decimals: Variable<u8>,

total_supply: Variable<U256>,

balances: Mapping<Address, U256>,

allowed: Mapping<(Address, Address), U256>

}

#[odra::module]

impl ERC20 {

#[odra(init)]

pub fn init(&mut self, name: String, symbol: String, decimals: u8, total_supply: U256) {

self.name.set(name);

self.symbol.set(symbol);

self.decimals.set(decimals);

self.total_supply.set(total_supply);

self.balances.set(&contract_env::caller(), total_supply);

}

pub fn total_supply(&self) -> U256 {

self.total_supply.get_or_default()

}

pub fn balance_of(&self, owner: Address) -> U256 {

self.balances.get_or_default(&owner)

}

pub fn transfer(&mut self, to: Address, value: U256) {

let from = contract_env::caller();

let from_balance = self.balances.get_or_default(&from);

let to_balance = self.balances.get_or_default(&to);

if from_balance < value {

contract_env::revert(Error::InsufficientBalance);

}

self.balances.set(&from, from_balance - value);

self.balances.set(&to, to_balance + value);

}

pub fn transfer_from(&mut self, from: Address, to: Address, value: U256) {

let caller = contract_env::caller();

let from_balance = self.balances.get_or_default(&from);

let to_balance = self.balances.get_or_default(&to);

let allowed = self.allowed.get_or_default(&(from, caller));

if from_balance < value {

contract_env::revert(Error::InsufficientBalance);

}

if allowed < value {

contract_env::revert(Error::InsufficientAllowance);

}

self.balances.set(&from, from_balance - value);

self.balances.set(&to, to_balance + value);

self.allowed.set(&(from, caller), allowed - value);

}

pub fn approve(&mut self, spender: Address, value: U256) {

let owner = contract_env::caller();

self.allowed.set(&(owner, spender), value);

}

pub fn allowance(&self, owner: Address, spender: Address) -> U256 {

self.allowed.get_or_default(&(owner, spender))

}

}

execution_error! {

pub enum Error {

InsufficientBalance => 1,

InsufficientAllowance => 2,

}

}