From 677c35af61dd93e4b653b0c0c037a6fca2540a00 Mon Sep 17 00:00:00 2001 From: clearloop Date: Mon, 26 Feb 2024 22:35:52 +0800 Subject: [PATCH] feat(evm): add dyn types in sol-abi --- codegen/src/codegen/dispatcher.rs | 16 ++++++++++++++++ codegen/src/visitor/local.rs | 2 ++ evm/abi/README.md | 6 +++++- evm/abi/src/arg.rs | 23 +++++++++++++++++++---- zink/src/lib.rs | 3 +++ 5 files changed, 45 insertions(+), 5 deletions(-) diff --git a/codegen/src/codegen/dispatcher.rs b/codegen/src/codegen/dispatcher.rs index 3f4c5cce6..c5eccb867 100644 --- a/codegen/src/codegen/dispatcher.rs +++ b/codegen/src/codegen/dispatcher.rs @@ -130,6 +130,8 @@ impl Dispatcher { // 1. drop selector. // 2. load calldata to stack. // 3. jump to the callee function. + // + // TODO: Parse bytes from the selector. fn process(&mut self, len: usize, last: bool) -> Result { let len = len as u8; if last && len == 0 { @@ -151,6 +153,20 @@ impl Dispatcher { } if len > 0 { + // FIXME: Using the length of parameters here + // is incorrect once we have params have length + // over than 4 bytes. + // + // 1. decode the abi from signature, if contains + // bytes type, use `calldatacopy` to load the data + // on stack. + // + // 2. if the present param is a 4 bytes value, use + // `calldataload[n]` directly. + // + // Actually 1. is more closed to the common cases, + // what 4 bytes for in EVM? + // [ ret, callee ] -> [ param * len, ret, callee ] for p in (0..len).rev() { let offset = 4 + p * 32; diff --git a/codegen/src/visitor/local.rs b/codegen/src/visitor/local.rs index e02ede6c8..0724d2fc1 100644 --- a/codegen/src/visitor/local.rs +++ b/codegen/src/visitor/local.rs @@ -7,8 +7,10 @@ impl Function { pub fn _local_get(&mut self, local_index: u32) -> Result<()> { let local_index = local_index as usize; if self.is_main && local_index < self.ty.params().len() { + // Parsing data from selector. self._local_get_calldata(local_index) } else { + // Passing data between local functions. self._local_get_var(local_index) } } diff --git a/evm/abi/README.md b/evm/abi/README.md index 63246d06f..15784e074 100644 --- a/evm/abi/README.md +++ b/evm/abi/README.md @@ -1,10 +1,14 @@ # Solidity ABI -An implementation of solidity ABI in rust. +An straightforward solidity ABI implementation in rust. Currently only used by the zink language, so the provided features is syncing with the development of zink. +If you are looking for a complete implementation of solidity ABI +in rust, plz check [alloy-core](https://github.com/alloy-rs/core). + + ## LICENSE GPL-3.0 diff --git a/evm/abi/src/arg.rs b/evm/abi/src/arg.rs index 7d3969a9c..e6ff2a582 100644 --- a/evm/abi/src/arg.rs +++ b/evm/abi/src/arg.rs @@ -29,9 +29,17 @@ pub enum Param { UInt32, /// A 64-bit unsigned integer. UInt64, - /// An unknown type. + /// An EVM address. + Address, + /// A boolean type. + Bool, + /// A byte array. #[default] - Unknown, + Bytes, + /// A string type. + String, + /// An unknown type. + Unknown(String), } impl From<&str> for Param { @@ -41,7 +49,10 @@ impl From<&str> for Param { "i64" | "int64" => Param::Int64, "u32" | "uint32" => Param::UInt32, "usize" | "u64" | "uint64" => Param::UInt64, - _ => Param::Unknown, + "Address" => Param::Address, + "Bytes" | "Vec" => Param::Bytes, + "String" => Param::String, + _ => Param::Unknown(s.to_string()), } } } @@ -61,7 +72,11 @@ impl AsRef for Param { Param::Int64 => "int64", Param::UInt32 => "uint32", Param::UInt64 => "uint64", - Param::Unknown => "unknown", + Param::Address => "address", + Param::Bool => "bool", + Param::Bytes => "bytes", + Param::String => "string", + Param::Unknown(ty) => ty.as_ref(), } } } diff --git a/zink/src/lib.rs b/zink/src/lib.rs index a1fd75fba..19b59f627 100644 --- a/zink/src/lib.rs +++ b/zink/src/lib.rs @@ -10,6 +10,9 @@ mod storage; pub use self::{asm::Asm, event::Event, storage::Storage}; pub use zink_codegen::{constructor, external, storage, Event}; +/// EVM address in rust. +pub type Address = [u8; 20]; + // Panic hook implementation #[cfg(target_arch = "wasm32")] #[panic_handler]