Skip to content

Commit

Permalink
Add new abi crate
Browse files Browse the repository at this point in the history
  • Loading branch information
Y-Nak committed Mar 5, 2022
1 parent afd19c3 commit 1a7009c
Show file tree
Hide file tree
Showing 14 changed files with 722 additions and 15 deletions.
21 changes: 18 additions & 3 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion crates/abi/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ repository = "https://github.com/ethereum/fe"

[dependencies]
fe-common = {path = "../common", version = "^0.14.0-alpha"}
fe-parser = {path = "../parser", version = "^0.14.0-alpha"}
fe-analyzer = {path = "../analyzer", version = "^0.14.0-alpha"}
serde_json = "1.0"
serde = "1.0"
2 changes: 1 addition & 1 deletion crates/abi/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,5 @@ pub fn func_selector(name: &str, params: &[String]) -> String {

fn hash_signature(name: &str, params: &[String], size: usize) -> String {
let signature = format!("{}({})", name, params.join(","));
keccak::partial(signature.as_bytes(), size)
format!("0x{}", keccak::partial(signature.as_bytes(), size))
}
4 changes: 1 addition & 3 deletions crates/codegen/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,4 @@ authors = ["The Fe Developers <[email protected]>"]
edition = "2021"

[dependencies]
fe-mir = { path = "../mir", version = "^0.14.0-alpha" }
fe-common = { path = "../common", version = "^0.14.0-alpha" }
fe-abi= { path = "../abi", version = "^0.14.0-alpha" }
fe-mir = { path = "../mir", version = "^0.14.0-alpha" }
3 changes: 0 additions & 3 deletions crates/codegen/src/abi.rs

This file was deleted.

1 change: 0 additions & 1 deletion crates/codegen/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
pub mod abi;
pub mod yul;
4 changes: 2 additions & 2 deletions crates/common/src/utils/keccak.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,13 @@ pub fn partial_right_padded(content: &[u8], size: usize) -> String {
.map(|(index, byte)| if index >= size { 0 } else { *byte })
.collect();

format!("0x{}", hex::encode(&padded_output))
hex::encode(&padded_output)
}

/// Take the first `size` number of bytes of the hash with no padding.
pub fn partial(content: &[u8], size: usize) -> String {
let result = full_as_bytes(content);
format!("0x{}", hex::encode(&result[0..size]))
hex::encode(&result[0..size])
}

/// Get the full 32 byte hash of the content as a byte array.
Expand Down
14 changes: 14 additions & 0 deletions crates/new_abi/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
[package]
name = "fe-new_abi"
version = "0.14.0-alpha"
authors = ["The Fe Developers <[email protected]>"]
edition = "2021"
license = "Apache-2.0"
repository = "https://github.com/ethereum/fe"

[dependencies]
fe-common = { path = "../common", version = "^0.14.0-alpha" }
serde = { version = "1.0", features = ["derive"] }

[dev-dependencies]
serde_test = "1.0"
33 changes: 33 additions & 0 deletions crates/new_abi/src/contract.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
use super::{event::AbiEvent, function::AbiFunction};

use serde::{ser::SerializeSeq, Serialize, Serializer};

#[derive(Debug, Clone)]
pub struct AbiContract {
/// Public functions in the contract.
funcs: Vec<AbiFunction>,

/// Events emitted from the contract.
events: Vec<AbiEvent>,
}

impl Serialize for AbiContract {
fn serialize<S: Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
let mut seq = s.serialize_seq(Some(self.funcs.len() + self.events.len()))?;
for func in &self.funcs {
seq.serialize_element(func)?;
}

for event in &self.events {
seq.serialize_element(event)?;
}

seq.end()
}
}

impl AbiContract {
pub fn new(funcs: Vec<AbiFunction>, events: Vec<AbiEvent>) -> Self {
Self { funcs, events }
}
}
148 changes: 148 additions & 0 deletions crates/new_abi/src/event.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
use super::types::AbiType;

use fe_common::utils::keccak;
use serde::Serialize;

#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
pub struct AbiEvent {
#[serde(rename = "type")]
ty: &'static str,
name: String,
inputs: Vec<AbiEventField>,
anonymous: bool,
}

impl AbiEvent {
pub fn new(name: String, fields: Vec<AbiEventField>, anonymous: bool) -> Self {
Self {
ty: "event",
name,
inputs: fields,
anonymous,
}
}

pub fn signature(&self) -> AbiEventSignature {
AbiEventSignature::new(self)
}
}

pub struct AbiEventSignature {
sig: String,
}

impl AbiEventSignature {
pub fn signature(&self) -> &str {
&self.sig
}

pub fn hash_hex(&self) -> String {
keccak::full(self.sig.as_bytes())
}

pub fn hash_raw(&self) -> [u8; 32] {
keccak::full_as_bytes(self.sig.as_bytes())
}

fn new(event: &AbiEvent) -> Self {
let sig = format!(
"{}({})",
event.name,
event
.inputs
.iter()
.map(|input| input.ty.selector_type_name())
.collect::<Vec<_>>()
.join(",")
);

Self { sig }
}
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
pub struct AbiEventField {
name: String,
#[serde(flatten)]
ty: AbiType,
indexed: bool,
}

impl AbiEventField {
pub fn new(name: String, ty: impl Into<AbiType>, indexed: bool) -> Self {
Self {
name,
ty: ty.into(),
indexed,
}
}
}

#[cfg(test)]
mod tests {
use super::*;

use serde_test::{assert_ser_tokens, Token};

fn test_event() -> AbiEvent {
let i32_ty = AbiType::Int(32);
let u32_ty = AbiType::UInt(32);
let field1 = AbiEventField::new("x".into(), i32_ty, true);
let field2 = AbiEventField::new("y".into(), u32_ty, false);

AbiEvent::new("MyEvent".into(), vec![field1, field2], false)
}

#[test]
fn serialize_event() {
let event = test_event();

assert_ser_tokens(
&event,
&[
Token::Struct {
name: "AbiEvent",
len: 4,
},
Token::Str("type"),
Token::Str("event"),
Token::String("name"),
Token::String("MyEvent"),
Token::Str("inputs"),
Token::Seq { len: Some(2) },
Token::Map { len: None },
Token::String("name"),
Token::String("x"),
Token::String("type"),
Token::String("int32"),
Token::Str("indexed"),
Token::Bool(true),
Token::MapEnd,
Token::Map { len: None },
Token::String("name"),
Token::String("y"),
Token::String("type"),
Token::String("uint32"),
Token::Str("indexed"),
Token::Bool(false),
Token::MapEnd,
Token::SeqEnd,
Token::Str("anonymous"),
Token::Bool(false),
Token::StructEnd,
],
)
}

#[test]
fn event_signature() {
let event = test_event();

let sig = event.signature();
debug_assert_eq!(sig.signature(), "MyEvent(int32,uint32)");
debug_assert_eq!(
sig.hash_hex(),
"ec835d5150565cb216f72ba07d715e875b0738b1ac3f412e103839e5157b7ee6"
);
}
}
Loading

0 comments on commit 1a7009c

Please sign in to comment.