Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
156 changes: 156 additions & 0 deletions contracts/src/contract/erc20.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
#[starknet::contract]
pub mod TimelyCapsuleToken {
use core::num::traits::Zero;
use core::starknet::storage::{
Map, StoragePathEntry, StoragePointerReadAccess, StoragePointerWriteAccess,
};
use starknet::event::EventEmitter;
use starknet::{ContractAddress, get_caller_address};
use crate::interfaces::IERC20;

#[storage]
pub struct Storage {
balances: Map<ContractAddress, u256>,
allowances: Map<(ContractAddress, ContractAddress), u256>,
token_name: ByteArray,
symbol: ByteArray,
decimal: u8,
total_supply: u256,
owner: ContractAddress,
}

#[event]
#[derive(Drop, starknet::Event)]
pub enum Event {
Transfer: Transfer,
Approval: Approval,
}

#[derive(Drop, starknet::Event)]
pub struct Transfer {
#[key]
from: ContractAddress,
#[key]
to: ContractAddress,
amount: u256,
}

#[derive(Drop, starknet::Event)]
pub struct Approval {
#[key]
owner: ContractAddress,
#[key]
spender: ContractAddress,
value: u256,
}

#[constructor]
fn constructor(ref self: ContractState, owner: ContractAddress) {
self.token_name.write("TimelyCapsule");
self.symbol.write("DWT");
self.decimal.write(18);
self.owner.write(owner);
}

#[abi(embed_v0)]
impl TimelyCapsuleTokenImpl of IERC20<ContractState> {
fn total_supply(self: @ContractState) -> u256 {
self.total_supply.read()
}

fn balance_of(self: @ContractState, account: ContractAddress) -> u256 {
let balance = self.balances.entry(account).read();

balance
}

fn allowance(
self: @ContractState, owner: ContractAddress, spender: ContractAddress,
) -> u256 {
let allowance = self.allowances.entry((owner, spender)).read();

allowance
}

fn transfer(ref self: ContractState, recipient: ContractAddress, amount: u256) -> bool {
let sender = get_caller_address();

let sender_prev_balance = self.balances.entry(sender).read();
let recipient_prev_balance = self.balances.entry(recipient).read();

assert(sender_prev_balance >= amount, 'Insufficient amount');

self.balances.entry(sender).write(sender_prev_balance - amount);
self.balances.entry(recipient).write(recipient_prev_balance + amount);

assert(
self.balances.entry(recipient).read() > recipient_prev_balance,
'Transaction failed',
);

self.emit(Transfer { from: sender, to: recipient, amount });

true
}

fn transfer_from(
ref self: ContractState,
sender: ContractAddress,
recipient: ContractAddress,
amount: u256,
) -> bool {
let spender = get_caller_address();

let spender_allowance = self.allowances.entry((sender, spender)).read();
let sender_balance = self.balances.entry(sender).read();
let recipient_balance = self.balances.entry(recipient).read();

assert(amount <= spender_allowance, 'amount exceeds allowance');
assert(amount <= sender_balance, 'amount exceeds balance');

self.allowances.entry((sender, spender)).write(spender_allowance - amount);
self.balances.entry(sender).write(sender_balance - amount);
self.balances.entry(recipient).write(recipient_balance + amount);

self.emit(Transfer { from: sender, to: recipient, amount });

true
}

fn approve(ref self: ContractState, spender: ContractAddress, amount: u256) -> bool {
let caller = get_caller_address();

self.allowances.entry((caller, spender)).write(amount);

self.emit(Approval { owner: caller, spender, value: amount });

true
}

fn name(self: @ContractState) -> ByteArray {
self.token_name.read()
}

fn symbol(self: @ContractState) -> ByteArray {
self.symbol.read()
}

fn decimals(self: @ContractState) -> u8 {
self.decimal.read()
}

fn mint(ref self: ContractState, recipient: ContractAddress, amount: u256) -> bool {
let previous_total_supply = self.total_supply.read();
let previous_balance = self.balances.entry(recipient).read();

self.total_supply.write(previous_total_supply + amount);
self.balances.entry(recipient).write(previous_balance + amount);

let zero_address = Zero::zero();

self.emit(Transfer { from: zero_address, to: recipient, amount });

true
}
}
}
Loading