Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(example): basic implementation of ERC20 #228

Merged
merged 22 commits into from
Nov 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
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
4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -110,3 +110,7 @@ opcodes = { workspace = true, features = ["data"] }
tracing.workspace = true
zint.workspace = true
hex.workspace = true

# [features]
# default = [ "evm" ]
# evm = [ ]
4 changes: 2 additions & 2 deletions codegen/src/asm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ impl Assembler {
return Ok(());
}

tracing::debug!(
tracing::trace!(
"increment stack pointer {}.add({items}) -> {}",
self.sp,
self.sp + items
Expand All @@ -67,7 +67,7 @@ impl Assembler {
return Ok(());
}

tracing::debug!(
tracing::trace!(
"decrement stack pointer {}.sub({items}) -> {}",
self.sp,
self.sp - items
Expand Down
6 changes: 6 additions & 0 deletions codegen/src/codegen/constructor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ pub struct Constructor {
impl Constructor {
/// preset storage for the contract
pub fn storage(&mut self, mapping: InitStorage) -> Result<()> {
tracing::debug!("Building storage in constructor ...");
for (key, value) in mapping.into_iter() {
self.masm.push(&value)?;
self.masm.push(&key)?;
Expand All @@ -38,6 +39,11 @@ impl Constructor {
let runtime_bytecode_offset =
Self::runtime_bytcode_offset(init_code_len, runtime_bytecode_size.len());

tracing::trace!("length of bytecode: {:?}", runtime_bytecode_len);
tracing::trace!(
"length of bytecode in hex: {:?}",
hex::encode(&runtime_bytecode_size)
);
let mut masm = self.masm.clone();

// 1. copy runtime bytecode to memory
Expand Down
2 changes: 1 addition & 1 deletion codegen/src/codegen/dispatcher.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ impl Dispatcher {
self.abi.push(abi.clone());

let selector_bytes = abi.selector();
tracing::trace!(
tracing::debug!(
"Emitting selector {:?} for function: {}",
selector_bytes,
abi.signature(),
Expand Down
10 changes: 5 additions & 5 deletions codegen/src/local.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,11 +87,11 @@ impl Locals {
let offset = if local.ty() == &LocalSlotType::Parameter {
self.inner[..index].iter().fold(0, |acc, x| acc + x.align())
} else {
panic!("This should never be reached");
// self.inner[..index]
// .iter()
// .filter(|x| x.ty() == &LocalSlotType::Variable)
// .fold(0, |acc, x| acc + x.align())
// panic!("This should never be reached");
self.inner[..index]
.iter()
.filter(|x| x.ty() == &LocalSlotType::Variable)
.fold(0, |acc, x| acc + x.align())
}
.to_ls_bytes()
.to_vec()
Expand Down
2 changes: 1 addition & 1 deletion codegen/src/masm/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ impl MacroAssembler {

/// Place n bytes on stack.
pub fn push(&mut self, bytes: &[u8]) -> Result<()> {
tracing::trace!("push bytes: 0x{:x?}", bytes);
tracing::trace!("push bytes: 0x{}", hex::encode(bytes));

// TODO: support PUSH0 #247
//
Expand Down
1 change: 1 addition & 0 deletions codegen/src/visitor/call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ impl Function {
HostFunc::Evm(OpCode::LOG3) => self.log(3),
HostFunc::Evm(OpCode::LOG4) => self.log(4),
HostFunc::Evm(op) => self.masm.emit_op(op),
HostFunc::U256MAX => self.masm.push(&[255; 32]),
HostFunc::Revert(count) => self.revert(count),
HostFunc::NoOp | HostFunc::Label(_) => Ok(()),
_ => {
Expand Down
3 changes: 2 additions & 1 deletion codegen/src/visitor/control.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,8 @@ impl Function {
///
/// Performs an unconditional branch.
pub fn _br(&mut self, _depth: u32) -> Result<()> {
todo!()
// TODO: do sth here?
Ok(())
}

/// Performs a conditional branch if i32 is non-zero.
Expand Down
5 changes: 4 additions & 1 deletion codegen/src/visitor/log.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,11 @@ impl Function {
}

let offset_len = (data[0] - 0x5f) as usize;
tracing::trace!("offset len: {offset_len}");
let offset = {
let mut bytes = [0; 4];
bytes[..offset_len].copy_from_slice(&data[1..(1 + offset_len)]);
bytes[(4 - offset_len)..].copy_from_slice(&data[1..(offset_len + 1)]);
bytes.reverse();
i32::from_le_bytes(bytes)
};
tracing::debug!("log offset: {:?}", offset);
Expand All @@ -45,6 +47,7 @@ impl Function {
return Err(Error::InvalidDataOffset(data[offset_len + 1].into()));
}
let size = {
// TODO: from ls bytes as offset
let mut bytes = [0; 4];
let size_bytes = &data[(offset_len + 2)..];
bytes[..size_bytes.len()].copy_from_slice(size_bytes);
Expand Down
9 changes: 6 additions & 3 deletions codegen/src/wasm/abi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,6 @@ macro_rules! offset {
.rev()
.skip_while(|b| *b == 0)
.collect::<Vec<_>>()
.into_iter()
.rev()
.collect::<Vec<_>>()
.into()
}
}
Expand Down Expand Up @@ -131,3 +128,9 @@ impl ToLSBytes for &[ValType] {
.to_ls_bytes()
}
}

#[test]
fn test_usize_to_ls_bytes() {
assert_eq!(363usize.to_ls_bytes().to_vec(), vec![0x01, 0x6b]);
assert_eq!(255usize.to_ls_bytes().to_vec(), vec![0xff]);
}
6 changes: 6 additions & 0 deletions codegen/src/wasm/host.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ pub enum HostFunc {
EmitABI,
/// check equal of two addresses
AddressEq,
/// Push u256 max to stack
U256MAX,
/// Revert messages with length of slots
Revert(usize),
/// Compiler labels
Expand Down Expand Up @@ -66,6 +68,10 @@ impl TryFrom<(&str, &str)> for HostFunc {
})?)),
("zinkc", "emit_abi") => Ok(Self::EmitABI),
("zinkc", "address_eq") => Ok(Self::Evm(OpCode::EQ)),
("zinkc", "u256_add") => Ok(Self::Evm(OpCode::ADD)),
("zinkc", "u256_sub") => Ok(Self::Evm(OpCode::SUB)),
("zinkc", "u256_lt") => Ok(Self::Evm(OpCode::LT)),
("zinkc", "u256_max") => Ok(Self::U256MAX),
("zinkc", "label_reserve_mem_32") => Ok(Self::Label(CompilerLabel::ReserveMemory32)),
("zinkc", "label_reserve_mem_64") => Ok(Self::Label(CompilerLabel::ReserveMemory64)),
_ => {
Expand Down
8 changes: 7 additions & 1 deletion evm/abi/src/arg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ pub enum Param {
UInt32,
/// A 64-bit unsigned integer.
UInt64,
/// A 256-bit unsigned integer.
UInt256,
// /// A 256-bit unsigned integer.
// UInt256,
/// A boolean type.
Bool,
/// An EVM address.
Expand All @@ -60,10 +64,11 @@ impl From<&str> for Param {
"u16" | "uint16" => Param::UInt16,
"u32" | "uint32" => Param::UInt32,
"u64" | "uint64" => Param::UInt64,
"U256" | "u256" | "uint256" => Param::UInt256,
"bool" => Param::Bool,
"address" | "Address" => Param::Address,
"Bytes" | "Vec<u8>" => Param::Bytes,
"String" => Param::String,
"String" | "String32" => Param::String,
_ => Param::Unknown(s.to_string()),
}
}
Expand All @@ -88,6 +93,7 @@ impl AsRef<str> for Param {
Param::UInt16 => "uint16",
Param::UInt32 => "uint32",
Param::UInt64 => "uint64",
Param::UInt256 => "uint256",
Param::Address => "address",
Param::Bool => "boolean",
Param::Bytes => "bytes",
Expand Down
26 changes: 26 additions & 0 deletions examples/constfn.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
//! Storage example.
#![cfg_attr(target_arch = "wasm32", no_std)]
#![cfg_attr(target_arch = "wasm32", no_main)]

extern crate zink;

/// set value to the storage.
#[zink::external]
pub fn decimals() -> i32 {
8
}

#[cfg(not(target_arch = "wasm32"))]
fn main() {}

#[test]
fn value() -> anyhow::Result<()> {
use zint::{Bytes32, Contract};

let mut contract = Contract::search("constfn")?.compile()?;

let decimals = 8.to_bytes32().to_vec();
let info = contract.execute(&[b"decimals()".to_vec(), decimals.clone()])?;
assert_eq!(info.ret, decimals);
Ok(())
}
Loading