From 387999b2bc60975ea393b6a62d2d65e34a67c088 Mon Sep 17 00:00:00 2001 From: clearloop <26088946+clearloop@users.noreply.github.com> Date: Sat, 16 Dec 2023 14:55:35 +0800 Subject: [PATCH] feat(abi): introduce solidity compatible function ABI (#179) * feat(abi): introduce macro impl_codec for encoding ABIs * chore(deps): upgrade dependencies * feat(evm): introduce solidity abi * feat(abi): conditonal compilation * chore(abi): rename evm-abi to sol-abi * ci(dep): review dep only on PR * chore(RELEASES): append RELEASES note --- .github/workflows/main.yml | 1 + Cargo.lock | 57 +++++------- Cargo.toml | 48 +++++----- RELEASES.md | 8 ++ abi/Cargo.toml | 23 +++-- abi/src/lib.rs | 106 ++++++++++++----------- abi/src/result.rs | 1 + abi/src/selector.rs | 39 +++++++++ codegen/src/dispatcher.rs | 5 +- codegen/src/result.rs | 2 +- evm/README.md | 4 + evm/abi/Cargo.toml | 17 ++++ evm/abi/README.md | 6 ++ evm/abi/src/abi.rs | 61 +++++++++++++ evm/abi/src/input.rs | 61 +++++++++++++ evm/abi/src/lib.rs | 12 +++ {codegen => evm}/opcodes/Cargo.toml | 0 {codegen => evm}/opcodes/README.md | 0 {codegen => evm}/opcodes/src/lib.rs | 0 {codegen => evm}/opcodes/src/shanghai.rs | 0 examples/addition.rs | 2 +- examples/fibonacci.rs | 2 +- examples/storage.rs | 4 +- zink/codegen/src/selector.rs | 24 +---- zint/src/contract.rs | 2 +- 25 files changed, 342 insertions(+), 143 deletions(-) create mode 100644 abi/src/selector.rs create mode 100644 evm/README.md create mode 100644 evm/abi/Cargo.toml create mode 100644 evm/abi/README.md create mode 100644 evm/abi/src/abi.rs create mode 100644 evm/abi/src/input.rs create mode 100644 evm/abi/src/lib.rs rename {codegen => evm}/opcodes/Cargo.toml (100%) rename {codegen => evm}/opcodes/README.md (100%) rename {codegen => evm}/opcodes/src/lib.rs (100%) rename {codegen => evm}/opcodes/src/shanghai.rs (100%) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 340ed86fb..229cf36c6 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -46,6 +46,7 @@ jobs: dep: name: Review runs-on: ubuntu-latest + if: github.event_name == 'pull_request' steps: - name: Checkout Repository uses: actions/checkout@v4 diff --git a/Cargo.lock b/Cargo.lock index 4d4cd481f..0f2458440 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -433,20 +433,6 @@ dependencies = [ "serde", ] -[[package]] -name = "cargo_metadata" -version = "0.15.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eee4243f1f26fc7a42710e7439c149e2b10b05472f88090acce52632f231a73a" -dependencies = [ - "camino", - "cargo-platform", - "semver", - "serde", - "serde_json", - "thiserror", -] - [[package]] name = "cargo_metadata" version = "0.18.1" @@ -697,13 +683,13 @@ name = "conta" version = "0.0.0" dependencies = [ "anyhow", - "cargo_metadata 0.15.4", + "cargo_metadata", "clap", "crates-io", "curl", "semver", "serde", - "toml 0.7.8", + "toml", ] [[package]] @@ -1032,14 +1018,14 @@ name = "elko" version = "0.1.7" dependencies = [ "anyhow", - "cargo_metadata 0.15.4", + "cargo_metadata", "clap", "colored", "etc", "semver", "serde", "thiserror", - "toml 0.7.8", + "toml", "tracing", "wasm-opt", "zinkc", @@ -1276,7 +1262,7 @@ dependencies = [ "serde", "serde_json", "syn 2.0.41", - "toml 0.8.8", + "toml", "walkdir", ] @@ -1304,7 +1290,7 @@ checksum = "2f03e0bdc216eeb9e355b90cf610ef6c5bb8aca631f97b5ae9980ce34ea7878d" dependencies = [ "arrayvec", "bytes", - "cargo_metadata 0.18.1", + "cargo_metadata", "chrono", "const-hex", "elliptic-curve", @@ -3548,6 +3534,15 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "sol-abi" +version = "0.0.1" +dependencies = [ + "quote", + "serde", + "syn 2.0.41", +] + [[package]] name = "solang-parser" version = "0.3.3" @@ -3930,18 +3925,6 @@ dependencies = [ "tracing", ] -[[package]] -name = "toml" -version = "0.7.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd79e69d3b627db300ff956027cc6c3798cef26d22526befdfcd12feeb6d2257" -dependencies = [ - "serde", - "serde_spanned", - "toml_datetime", - "toml_edit 0.19.15", -] - [[package]] name = "toml" version = "0.8.8" @@ -3970,8 +3953,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" dependencies = [ "indexmap 2.1.0", - "serde", - "serde_spanned", "toml_datetime", "winnow", ] @@ -4656,6 +4637,8 @@ dependencies = [ "postcard", "serde", "sha3", + "sol-abi", + "syn 2.0.41", "thiserror", ] @@ -4758,7 +4741,7 @@ name = "zinkc-filetests" version = "0.1.7" dependencies = [ "anyhow", - "cargo_metadata 0.15.4", + "cargo_metadata", "proc-macro2", "quote", "syn 2.0.41", @@ -4787,14 +4770,14 @@ name = "zint" version = "0.1.7" dependencies = [ "anyhow", - "cargo_metadata 0.15.4", + "cargo_metadata", "etc", "ethers", "hex", "revm", "serde", "thiserror", - "toml 0.7.8", + "toml", "tracing", "tracing-subscriber", "url", diff --git a/Cargo.toml b/Cargo.toml index f1820b8a5..90cda50b9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,9 +5,10 @@ members = [ "cli/conta", "cli/elko", "codegen", - "codegen/opcodes", "compiler", "compiler/filetests", + "evm/opcodes", + "evm/abi", "zink/codegen", "zint", ] @@ -22,42 +23,43 @@ homepage = "https://github.com/clearloop/zink" repository = "https://github.com/clearloop/zink.git" [workspace.dependencies] -anyhow = "1.0.71" -cargo_metadata = "0.15.4" -clap = "4.3.10" +anyhow = "1.0.75" +cargo_metadata = "0.18.1" +clap = "4.4.11" curl = "0.4.44" color-eyre = "0.6.2" -colored = "2.0.4" +colored = "2.1.0" crates-io = "0.37.0" etc = "0.1.16" ethers = "2.0.11" hex = "0.4.3" -indexmap = "2.0.0" -once_cell = "1.18.0" +indexmap = "2.1.0" +once_cell = "1.19.0" parking_lot = "0.12.1" -paste = "1.0.13" +paste = "1.0.14" postcard = { version = "1.0.8", default-features = false } -proc-macro2 = "1.0.69" +proc-macro2 = "1.0.70" quote = "1.0.33" revm = "3.5.0" -semver = "1.0.18" -serde = "1.0.171" -sha3 = "0.10.6" -smallvec = "1.11.0" -syn = { version = "2.0.38", features = [ "full" ] } -target-lexicon = "0.12.8" -thiserror = "1.0.40" -tokio = "1.34.0" -toml = "0.7.6" -tracing = "0.1.37" -tracing-subscriber = "0.3.17" -url = "2.4.1" +semver = "1.0.20" +serde = "1.0.193" +sha3 = "0.10.8" +smallvec = "1.11.2" +syn = { version = "2.0.41", features = [ "full" ] } +target-lexicon = "0.12.12" +thiserror = "1.0.50" +tokio = "1.35.0" +toml = "0.8.8" +tracing = "0.1.40" +tracing-subscriber = "0.3.18" +url = "2.5.0" wasm-opt = "0.113.0" wasmparser = "0.107.0" -wat = "1.0.75" +wat = "1.0.82" elko = { path = "cli/elko", version = "=0.1.7" } -opcodes = { package = "evm-opcodes", path = "codegen/opcodes", version = "=0.0.3", features = ["data"] } +opcodes = { package = "evm-opcodes", path = "evm/opcodes", version = "=0.0.3", features = ["data"] } +sol-abi = { path = "evm/abi", version = "=0.0.1" } zabi = { path = "abi", version = "=0.1.7" } zinkup = { path = "cli", version = "=0.1.7" } zingen = { path = "codegen", version = "=0.1.7" } diff --git a/RELEASES.md b/RELEASES.md index c064fd225..23d068f0b 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -1,3 +1,11 @@ +## v0.1.8 + +### Changes + +- Solidity compatible ABI +- Refactor `zabi` a wrapper a `sol-abi` +- Conditional compilation for abi related crates + ## v0.1.7 ### Added diff --git a/abi/Cargo.toml b/abi/Cargo.toml index c52b34bba..f8b6cab79 100644 --- a/abi/Cargo.toml +++ b/abi/Cargo.toml @@ -10,8 +10,21 @@ license.workspace = true repository.workspace = true [dependencies] -hex.workspace = true -postcard = { workspace = true, default-features = false, features = [ "use-std" ] } -serde = { workspace = true, features = [ "derive" ] } -sha3.workspace = true -thiserror.workspace = true +sol-abi.workspace = true + +# optional features +hex = { workspace = true, optional = true } +postcard = { workspace = true, default-features = false, features = [ "use-std" ], optional = true } +serde = { workspace = true, features = [ "derive" ], optional = true } +sha3 = { workspace = true, optional = true } +syn = { workspace = true, optional = true } +thiserror = { workspace = true, optional = true } + +# TODO: introduce feature alloc. +[features] +default = [ "hex", "selector", "syn" ] +bytes = [ "postcard", "serde" ] +hex = [ "dep:hex", "thiserror", "bytes" ] +selector = [ "sha3" ] +serde = [ "dep:serde", "sol-abi/serde" ] +syn = [ "dep:syn", "sol-abi/syn" ] diff --git a/abi/src/lib.rs b/abi/src/lib.rs index bbbc48521..c814aa687 100644 --- a/abi/src/lib.rs +++ b/abi/src/lib.rs @@ -1,71 +1,79 @@ -//! Utils for generating of zink ABI -pub use self::result::{Error, Result}; -use serde::{Deserialize, Serialize}; -use sha3::{Digest, Keccak256}; +//! Zink ABI implementation +//! +//! Currently just a wrapper of solidity ABI. -mod result; +pub mod result; +pub mod selector; -/// Generate a keccak hash of the input (sha3) -pub fn keccak256(input: &[u8]) -> [u8; 32] { - let mut hasher = Keccak256::new(); - hasher.update(input); - hasher.finalize().into() -} +use core::ops::{Deref, DerefMut}; + +/// Function ABI. +#[derive(Debug, Clone)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Abi(sol_abi::Abi); -/// Get function selector from function signature. -pub fn selector(input: &[u8]) -> [u8; 4] { - let mut selector = [0u8; 4]; - selector.copy_from_slice(&keccak256(input)[..4]); +impl Deref for Abi { + type Target = sol_abi::Abi; - selector + fn deref(&self) -> &Self::Target { + &self.0 + } } -/// Function ABI. -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct Abi { - /// Function name. - pub name: String, - /// Function inputs. - pub inputs: Vec, +impl DerefMut for Abi { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } } +#[cfg(feature = "bytes")] impl Abi { - /// Get function signature. - pub fn signature(&self) -> String { - self.name.clone() + "(" + &self.inputs.join(",") + ")" + /// Convert [`Abi`] to bytes. + pub fn to_bytes(&self) -> postcard::Result> { + postcard::to_stdvec(self).map_err(Into::into) } - /// Get function selector. - pub fn selector(&self) -> [u8; 4] { - let sig = self.signature(); - let mut selector = [0u8; 4]; - selector.copy_from_slice(&keccak256(sig.as_bytes())[..4]); - - selector + /// Convert bytes to [`Abi`]. + pub fn from_bytes(bytes: impl AsRef<[u8]>) -> postcard::Result { + postcard::from_bytes(bytes.as_ref()).map_err(Into::into) } +} - /// Parse ABI from bytes. - pub fn from_bytes(bytes: &[u8]) -> Result { - postcard::from_bytes(bytes).map_err(Into::into) - } +#[cfg(feature = "hex")] +mod hex_impl { + use crate::{result::Result, Abi}; - /// Decode ABI form hex string. - pub fn from_hex(hex: &str) -> Result { - Self::from_bytes(&hex::decode(hex)?) + impl Abi { + /// Convert [`Abi`] to hex string. + pub fn to_hex(&self) -> Result { + Ok("0x".to_string() + &hex::encode(self.to_bytes()?)) + } + + /// Convert hex string to [`Abi`]. + pub fn from_hex(hex: impl AsRef) -> Result { + Self::from_bytes(hex::decode(hex.as_ref().trim_start_matches("0x"))?) + .map_err(Into::into) + } } - /// Decode ABI form hex string. - pub fn from_hex_bytes(bytes: &[u8]) -> Result { - Self::from_hex(&String::from_utf8_lossy(bytes)) + impl ToString for Abi { + fn to_string(&self) -> String { + self.to_hex().unwrap_or_default() + } } - /// Convert ABI to hex string. - pub fn to_hex(&self) -> Result { - self.to_bytes().map(hex::encode) + impl core::str::FromStr for Abi { + type Err = crate::result::Error; + + fn from_str(hex: &str) -> Result { + Self::from_hex(hex) + } } +} - /// Convert ABI to bytes. - pub fn to_bytes(&self) -> Result> { - postcard::to_stdvec(&self).map_err(Into::into) +#[cfg(feature = "syn")] +impl From<&syn::Signature> for Abi { + fn from(sig: &syn::Signature) -> Self { + Self(sol_abi::Abi::from(sig)) } } diff --git a/abi/src/result.rs b/abi/src/result.rs index 41e579feb..cf0fb19ac 100644 --- a/abi/src/result.rs +++ b/abi/src/result.rs @@ -1,4 +1,5 @@ //! Abi results +#![cfg(feature = "hex")] /// ABI error #[derive(Debug, thiserror::Error)] diff --git a/abi/src/selector.rs b/abi/src/selector.rs new file mode 100644 index 000000000..387d4fc1f --- /dev/null +++ b/abi/src/selector.rs @@ -0,0 +1,39 @@ +//! Zink ABI utils +#![cfg(feature = "selector")] + +use crate::Abi; +use sha3::{Digest, Keccak256}; + +/// Generate a keccak hash of the input (sha3) +pub fn keccak256(input: &[u8]) -> [u8; 32] { + let mut hasher = Keccak256::new(); + hasher.update(input); + hasher.finalize().into() +} + +/// Parse selector from bytes. +pub fn parse(bytes: &[u8]) -> [u8; 4] { + let mut selector = [0u8; 4]; + selector.copy_from_slice(&keccak256(bytes)[..4]); + selector +} + +impl Abi { + /// Get function signature. + pub fn signature(&self) -> String { + self.name.clone() + + "(" + + &self + .inputs + .iter() + .map(|i| i.ty.as_ref()) + .collect::>() + .join(",") + + ")" + } + + /// Get function selector. + pub fn selector(&self) -> [u8; 4] { + parse(self.signature().as_bytes()) + } +} diff --git a/codegen/src/dispatcher.rs b/codegen/src/dispatcher.rs index 4d9a24331..7ff62fdb5 100644 --- a/codegen/src/dispatcher.rs +++ b/codegen/src/dispatcher.rs @@ -88,7 +88,8 @@ impl<'d> Dispatcher<'d> { return Err(Error::FuncNotImported("emit_abi".into())); } - Abi::from_hex_bytes(&self.data.load(offset, length as usize)?).map_err(Into::into) + let abi = self.data.load(offset, length as usize)?; + Abi::from_hex(String::from_utf8_lossy(&abi)).map_err(Into::into) } /// Emit return of ext function. @@ -183,7 +184,7 @@ impl<'d> Dispatcher<'d> { tracing::trace!( "Emitting selector {:?} for function: {}", selector_bytes, - abi.signature() + abi.signature(), ); let func = self.query_func(&abi.name)?; diff --git a/codegen/src/result.rs b/codegen/src/result.rs index 81bc7c16a..335e1adb8 100644 --- a/codegen/src/result.rs +++ b/codegen/src/result.rs @@ -5,7 +5,7 @@ pub enum Error { /// Failed to parse function ABI. #[error(transparent)] - Abi(#[from] zabi::Error), + Abi(#[from] zabi::result::Error), /// Failed to parse WASM with binary reader. #[error(transparent)] BinaryReader(#[from] wasmparser::BinaryReaderError), diff --git a/evm/README.md b/evm/README.md new file mode 100644 index 000000000..ea636161a --- /dev/null +++ b/evm/README.md @@ -0,0 +1,4 @@ +# EVM Primitives + +- [evm-opcodes](./opcodes) +- [evm-abi](./abi) diff --git a/evm/abi/Cargo.toml b/evm/abi/Cargo.toml new file mode 100644 index 000000000..18d5a11d2 --- /dev/null +++ b/evm/abi/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "sol-abi" +version = "0.0.1" +authors.workspace = true +edition.workspace = true +license.workspace = true +homepage.workspace = true +repository.workspace = true + +[dependencies] +serde = { workspace = true, optional = true } +syn = { workspace = true, optional = true } +quote = { workspace = true, optional = true } + +[features] +default = [ "serde", "syn" ] +syn = [ "dep:syn", "quote" ] diff --git a/evm/abi/README.md b/evm/abi/README.md new file mode 100644 index 000000000..ecd4eae49 --- /dev/null +++ b/evm/abi/README.md @@ -0,0 +1,6 @@ +# Solidity ABI + +An implementation of solidity ABI in rust. + +Currently only used by the zink language, so the provided features +is syncing with the development of zink. diff --git a/evm/abi/src/abi.rs b/evm/abi/src/abi.rs new file mode 100644 index 000000000..d3befa47b --- /dev/null +++ b/evm/abi/src/abi.rs @@ -0,0 +1,61 @@ +//! Solidity ABI abstraction. +use crate::Input; + +/// Solidity ABI abstraction. +#[derive(Debug, Clone)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Abi { + /// ABI name. + pub name: String, + /// ABI type. + pub ty: Type, + /// ABI inputs. + pub inputs: Vec, +} + +#[cfg(feature = "syn")] +impl From<&syn::Signature> for Abi { + fn from(sig: &syn::Signature) -> Self { + let args = sig.inputs.iter().filter_map(|arg| { + if let syn::FnArg::Typed(syn::PatType { ty, .. }) = arg { + Some(Input { + name: sig.ident.to_string(), + ty: crate::Param::from(ty), + }) + } else { + None + } + }); + + Abi { + name: sig.ident.to_string(), + inputs: args.collect(), + ty: Type::Function, + } + } +} + +/// Solidity ABI type. +#[derive(Debug, Clone)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub enum Type { + /// Constructor ABI. + Constructor, + /// Function ABI. + Function, +} + +impl AsRef for Type { + fn as_ref(&self) -> &str { + match self { + Type::Constructor => "constructor", + Type::Function => "function", + } + } +} + +impl ToString for Type { + fn to_string(&self) -> String { + self.as_ref().to_string() + } +} diff --git a/evm/abi/src/input.rs b/evm/abi/src/input.rs new file mode 100644 index 000000000..e16636424 --- /dev/null +++ b/evm/abi/src/input.rs @@ -0,0 +1,61 @@ +//! Input of solidity ABI. + +/// Input of solidity ABI. +#[derive(Debug, Clone)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Input { + /// Name of the input. + pub name: String, + /// Type of the input. + pub ty: Param, +} + +/// The canonical type of the parameter. +#[derive(Debug, Clone)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub enum Param { + /// A 32-bit integer. + Int32, + /// A 64-bit integer. + Int64, + /// A 32-bit unsigned integer. + UInt32, + /// A 64-bit unsigned integer. + UInt64, + /// An unknown type. + Unknown, +} + +impl From<&str> for Param { + fn from(s: &str) -> Self { + match s { + "i32" | "int32" => Param::Int32, + "i64" | "int64" => Param::Int64, + "u32" | "uint32" => Param::UInt32, + "usize" | "u64" | "uint64" => Param::UInt64, + _ => Param::Unknown, + } + } +} + +impl AsRef for Param { + fn as_ref(&self) -> &str { + match self { + Param::Int32 => "int32", + Param::Int64 => "int64", + Param::UInt32 => "uint32", + Param::UInt64 => "uint64", + Param::Unknown => "unknown", + } + } +} + +#[cfg(feature = "syn")] +impl From<&Box> for Param { + fn from(ty: &Box) -> Self { + use quote::ToTokens; + + let ident = ty.into_token_stream().to_string(); + Self::from(ident.as_str()) + } +} diff --git a/evm/abi/src/lib.rs b/evm/abi/src/lib.rs new file mode 100644 index 000000000..1b314d950 --- /dev/null +++ b/evm/abi/src/lib.rs @@ -0,0 +1,12 @@ +//! Solidity ABI implementation +//! +//! https://docs.soliditylang.org/en/latest/abi-spec.html#json +#![deny(missing_docs)] + +mod abi; +mod input; + +pub use self::{ + abi::Abi, + input::{Input, Param}, +}; diff --git a/codegen/opcodes/Cargo.toml b/evm/opcodes/Cargo.toml similarity index 100% rename from codegen/opcodes/Cargo.toml rename to evm/opcodes/Cargo.toml diff --git a/codegen/opcodes/README.md b/evm/opcodes/README.md similarity index 100% rename from codegen/opcodes/README.md rename to evm/opcodes/README.md diff --git a/codegen/opcodes/src/lib.rs b/evm/opcodes/src/lib.rs similarity index 100% rename from codegen/opcodes/src/lib.rs rename to evm/opcodes/src/lib.rs diff --git a/codegen/opcodes/src/shanghai.rs b/evm/opcodes/src/shanghai.rs similarity index 100% rename from codegen/opcodes/src/shanghai.rs rename to evm/opcodes/src/shanghai.rs diff --git a/examples/addition.rs b/examples/addition.rs index 284137bb3..ee618a2fe 100644 --- a/examples/addition.rs +++ b/examples/addition.rs @@ -18,7 +18,7 @@ fn test() -> anyhow::Result<()> { let mut contract = Contract::search("addition")?.compile()?; let info = contract.execute([ - "addition(u64,u64)".as_bytes(), + "addition(uint64,uint64)".as_bytes(), &1u64.to_bytes32(), &2u64.to_bytes32(), ])?; diff --git a/examples/fibonacci.rs b/examples/fibonacci.rs index 3f7325eaa..511bdcaf4 100644 --- a/examples/fibonacci.rs +++ b/examples/fibonacci.rs @@ -22,7 +22,7 @@ fn main() {} fn test() -> anyhow::Result<()> { use zint::{Bytes32, Contract}; let mut contract = Contract::search("fibonacci")?.compile()?; - let selector = "fib(usize)".as_bytes(); + let selector = "fib(uint64)".as_bytes(); // x = 0 let info = contract.execute([selector, &0usize.to_bytes32()])?; diff --git a/examples/storage.rs b/examples/storage.rs index 18a3b9fb6..57585d08a 100644 --- a/examples/storage.rs +++ b/examples/storage.rs @@ -47,7 +47,7 @@ fn selector() -> anyhow::Result<()> { { let key = 0; let value: i32 = 42; - let info = contract.execute(&[b"set(i32)".to_vec(), value.to_bytes32().to_vec()])?; + let info = contract.execute(&[b"set(int32)".to_vec(), value.to_bytes32().to_vec()])?; assert!(info.ret.is_empty()); assert_eq!(info.instr, InstructionResult::Return); assert_eq!(info.storage.get(&U256::from(key)), Some(&U256::from(value))); @@ -63,7 +63,7 @@ fn selector() -> anyhow::Result<()> { let key = 0; let value = 42; let info = - contract.execute(&[b"set_and_get(i32)".to_vec(), value.to_bytes32().to_vec()])?; + contract.execute(&[b"set_and_get(int32)".to_vec(), value.to_bytes32().to_vec()])?; assert_eq!(info.instr, InstructionResult::Return); assert_eq!(info.ret, value.to_bytes32()); assert_eq!(info.storage.get(&U256::from(key)), Some(&U256::from(value))); diff --git a/zink/codegen/src/selector.rs b/zink/codegen/src/selector.rs index 75164b717..8e358caae 100644 --- a/zink/codegen/src/selector.rs +++ b/zink/codegen/src/selector.rs @@ -2,8 +2,8 @@ use proc_macro::TokenStream; use proc_macro2::{Ident, Span}; -use quote::{quote, ToTokens}; -use syn::{parse_quote, FnArg, ItemFn, Signature}; +use quote::quote; +use syn::{parse_quote, ItemFn}; use zabi::Abi; /// Mark the function as external. @@ -16,7 +16,7 @@ pub fn external(mut item: ItemFn) -> TokenStream { let selector: ItemFn = { let func = item.sig.ident.clone().to_string(); let ident = Ident::new(&(func.clone() + "_selector"), Span::call_site()); - let selector = parse_selector(&item.sig); + let selector = Abi::from(&item.sig).to_hex().expect("ABI is not supported"); let selector_len = selector.len() as u32; let doc = " EVM selector for the function `".to_string() + &func + "`"; @@ -39,21 +39,3 @@ pub fn external(mut item: ItemFn) -> TokenStream { } .into() } - -/// Hash function signature to EVM selector. -fn parse_selector(sig: &Signature) -> String { - let args = sig.inputs.iter().map(|arg| match arg { - FnArg::Typed(pat) => pat.ty.clone().into_token_stream().to_string(), - _ => panic!( - "Unsupported function argument: {:?}", - arg.into_token_stream().to_string() - ), - }); - - Abi { - name: sig.ident.to_string(), - inputs: args.collect(), - } - .to_hex() - .expect("Failed to serialize ABI") -} diff --git a/zint/src/contract.rs b/zint/src/contract.rs index 7ce04c5fe..06aeb63fa 100644 --- a/zint/src/contract.rs +++ b/zint/src/contract.rs @@ -148,7 +148,7 @@ impl Contract { return Err(anyhow!("no selector provided")); } - calldata.extend_from_slice(&zabi::selector(&inputs[0].to_vec())); + calldata.extend_from_slice(&zabi::selector::parse(&inputs[0].to_vec())); inputs = &inputs[1..]; }