From 7849b1ec7f4daa83ec7a2997c69732363405b66e Mon Sep 17 00:00:00 2001 From: Grant Wuerker Date: Tue, 13 Jul 2021 16:45:49 -0600 Subject: [PATCH] Move type traits to separate crates. --- crates/abi/src/builder.rs | 3 +- crates/abi/src/elements.rs | 129 +++++- crates/abi/src/utils.rs | 7 +- crates/analyzer/src/lib.rs | 57 --- crates/analyzer/src/namespace/events.rs | 24 +- crates/analyzer/src/namespace/types.rs | 413 +----------------- .../analysis__abi_encoding_stress.snap | 9 +- .../analysis__data_copying_stress.snap | 9 +- .../snapshots/analysis__erc20_token.snap | 22 +- .../tests/snapshots/analysis__events.snap | 30 +- .../analysis__external_contract.snap | 9 +- .../tests/snapshots/analysis__guest_book.snap | 9 +- .../tests/snapshots/analysis__ownable.snap | 12 +- .../analysis__sized_vals_in_sto.snap | 9 +- .../tests/snapshots/analysis__strings.snap | 9 +- .../snapshots/analysis__tuple_stress.snap | 9 +- .../tests/snapshots/analysis__uniswap.snap | 59 +-- crates/test-utils/src/lib.rs | 3 +- crates/yulgen/src/constructor.rs | 5 +- crates/yulgen/src/lib.rs | 1 + crates/yulgen/src/mappers/assignments.rs | 88 ---- crates/yulgen/src/mappers/declarations.rs | 53 +-- crates/yulgen/src/mappers/expressions.rs | 186 +------- crates/yulgen/src/mappers/functions.rs | 61 +-- crates/yulgen/src/names/abi.rs | 14 +- crates/yulgen/src/names/mod.rs | 26 +- crates/yulgen/src/operations/abi.rs | 33 +- crates/yulgen/src/operations/data.rs | 38 +- crates/yulgen/src/operations/mod.rs | 1 + crates/yulgen/src/operations/revert.rs | 21 + crates/yulgen/src/runtime/abi_dispatcher.rs | 18 +- crates/yulgen/src/runtime/functions/abi.rs | 48 +- .../yulgen/src/runtime/functions/contracts.rs | 14 +- crates/yulgen/src/runtime/functions/math.rs | 9 +- crates/yulgen/src/runtime/functions/revert.rs | 72 ++- .../yulgen/src/runtime/functions/structs.rs | 3 +- crates/yulgen/src/runtime/mod.rs | 63 ++- crates/yulgen/src/types.rs | 248 +++++++++++ ...decode_component_address_mem_function.snap | 2 +- ...code_component_bool_calldata_function.snap | 2 +- ...ecode_component_bytes_26_mem_function.snap | 4 +- ...ode_component_int16_calldata_function.snap | 2 +- ...component_string_26_calldata_function.snap | 4 +- ...decode_component_uint256_mem_function.snap | 2 +- ...decode_data_address_bool_mem_function.snap | 6 +- ..._bool_address_bytes_calldata_function.snap | 12 +- .../yulgen__revert_string_error.snap | 8 +- crates/yulgen/tests/yulgen.rs | 43 +- 48 files changed, 738 insertions(+), 1171 deletions(-) create mode 100644 crates/yulgen/src/operations/revert.rs create mode 100644 crates/yulgen/src/types.rs diff --git a/crates/abi/src/builder.rs b/crates/abi/src/builder.rs index d193875d35..dbabd90947 100644 --- a/crates/abi/src/builder.rs +++ b/crates/abi/src/builder.rs @@ -1,7 +1,6 @@ -use crate::elements::{Component, Contract, Event, EventField, ModuleAbis}; +use crate::elements::{AbiEncoding, Component, Contract, Event, EventField, ModuleAbis}; use crate::errors::AbiError; use fe_analyzer::context::Context; -use fe_analyzer::namespace::types::AbiEncoding; use fe_parser::ast as fe; /// Parse a map of contract ABIs from the input `module`. diff --git a/crates/abi/src/elements.rs b/crates/abi/src/elements.rs index 081b4e4fa5..34b0f09634 100644 --- a/crates/abi/src/elements.rs +++ b/crates/abi/src/elements.rs @@ -1,6 +1,6 @@ use crate::errors::AbiError; use fe_analyzer::context::FunctionAttributes; -use fe_analyzer::namespace::types::{AbiComponent, AbiEncoding}; +use fe_analyzer::namespace::types::{Array, Base, FeString, FixedSize, Integer, Struct, Tuple}; use serde::ser::SerializeSeq; use serde::{Serialize, Serializer}; use std::collections::HashMap; @@ -62,6 +62,133 @@ impl Serialize for Contract { } } +/// Single component of a tuple. +#[derive(Clone, Debug, PartialEq, PartialOrd, Ord, Eq)] +pub struct AbiComponent { + pub name: String, + pub typ: String, + /// The subcomponents of the component. + pub components: Vec, +} + +/// Information relevant to ABI encoding. +pub trait AbiEncoding { + /// Name of the type as it appears in the Json ABI. + fn abi_json_name(&self) -> String; + + /// The components of an ABI tuple. + fn abi_components(&self) -> Vec; +} + +impl AbiEncoding for FixedSize { + fn abi_json_name(&self) -> String { + match self { + FixedSize::Array(array) => array.abi_json_name(), + FixedSize::Base(base) => base.abi_json_name(), + FixedSize::Tuple(tuple) => tuple.abi_json_name(), + FixedSize::String(string) => string.abi_json_name(), + FixedSize::Contract(_) => "address".to_string(), + FixedSize::Struct(val) => val.abi_json_name(), + } + } + + fn abi_components(&self) -> Vec { + match self { + FixedSize::Array(array) => array.abi_components(), + FixedSize::Base(base) => base.abi_components(), + FixedSize::Tuple(tuple) => tuple.abi_components(), + FixedSize::String(string) => string.abi_components(), + FixedSize::Contract(_) => vec![], + FixedSize::Struct(val) => val.abi_components(), + } + } +} + +impl AbiEncoding for Base { + fn abi_json_name(&self) -> String { + match self { + Base::Numeric(Integer::U256) => "uint256".to_string(), + Base::Numeric(Integer::U128) => "uint128".to_string(), + Base::Numeric(Integer::U64) => "uint64".to_string(), + Base::Numeric(Integer::U32) => "uint32".to_string(), + Base::Numeric(Integer::U16) => "uint16".to_string(), + Base::Numeric(Integer::U8) => "uint8".to_string(), + Base::Numeric(Integer::I256) => "int256".to_string(), + Base::Numeric(Integer::I128) => "int128".to_string(), + Base::Numeric(Integer::I64) => "int64".to_string(), + Base::Numeric(Integer::I32) => "int32".to_string(), + Base::Numeric(Integer::I16) => "int16".to_string(), + Base::Numeric(Integer::I8) => "int8".to_string(), + Base::Address => "address".to_string(), + Base::Bool => "bool".to_string(), + Base::Unit => panic!("unit type is not abi encodable"), + } + } + + fn abi_components(&self) -> Vec { + vec![] + } +} + +impl AbiEncoding for Array { + fn abi_json_name(&self) -> String { + if self.inner == Base::Numeric(Integer::U8) { + "bytes".to_string() + } else { + format!("{}[{}]", self.inner.abi_json_name(), self.size) + } + } + + fn abi_components(&self) -> Vec { + vec![] + } +} + +impl AbiEncoding for Struct { + fn abi_json_name(&self) -> String { + "tuple".to_string() + } + + fn abi_components(&self) -> Vec { + self.fields + .iter() + .map(|(name, typ)| AbiComponent { + name: name.to_owned(), + typ: typ.abi_json_name(), + components: vec![], + }) + .collect() + } +} + +impl AbiEncoding for Tuple { + fn abi_json_name(&self) -> String { + "tuple".to_string() + } + + fn abi_components(&self) -> Vec { + self.items + .iter() + .enumerate() + .map(|(index, item)| AbiComponent { + name: format!("item{}", index), + typ: item.abi_json_name(), + components: vec![], + }) + .collect() + } +} + +impl AbiEncoding for FeString { + fn abi_json_name(&self) -> String { + "string".to_string() + } + + fn abi_components(&self) -> Vec { + vec![] + } +} + /// An event interface. #[derive(Serialize, Debug, PartialEq, Clone)] pub struct Event { diff --git a/crates/abi/src/utils.rs b/crates/abi/src/utils.rs index 2ad8c72540..e68eea770b 100644 --- a/crates/abi/src/utils.rs +++ b/crates/abi/src/utils.rs @@ -3,15 +3,16 @@ use fe_common::utils::keccak; /// Formats the name and fields and calculates the 32 byte keccak256 value of /// the signature. pub fn event_topic(name: &str, fields: &[String]) -> String { - sign_event_or_func(name, fields, 32) + hash_signature(name, fields, 32) } + /// Formats the name and params and calculates the 4 byte keccak256 value of the /// signature. pub fn func_selector(name: &str, params: &[String]) -> String { - sign_event_or_func(name, params, 4) + hash_signature(name, params, 4) } -fn sign_event_or_func(name: &str, params: &[String], size: usize) -> String { +fn hash_signature(name: &str, params: &[String], size: usize) -> String { let signature = format!("{}({})", name, params.join(",")); keccak::partial(signature.as_bytes(), size) } diff --git a/crates/analyzer/src/lib.rs b/crates/analyzer/src/lib.rs index 37e993587e..1507ef93bb 100644 --- a/crates/analyzer/src/lib.rs +++ b/crates/analyzer/src/lib.rs @@ -39,60 +39,3 @@ pub fn analyze(module: &fe::Module, file_id: SourceFileId) -> Result Self { - ContextHarness { - context: Context::new(), - src: src.to_string(), - } - } - - fn find_span(&self, substr: &str) -> Span { - let start = self - .src - .find(substr) - .unwrap_or_else(|| panic!("unable to find '{}' in '{}'", substr, self.src)); - - Span { - start, - end: start + substr.len(), - } - } - - pub fn add_expression(&mut self, substr: &str, attributes: ExpressionAttributes) { - let span = self.find_span(substr); - let mock_node = Node::new(fe::Expr::Name("foo"), span); - self.context.add_expression(&mock_node, attributes) - } - - pub fn add_expressions(&mut self, substrs: Vec<&str>, attributes: ExpressionAttributes) { - for substr in substrs { - self.add_expression(substr, attributes.clone()) - } - } - - pub fn add_declaration(&mut self, substr: &str, typ: FixedSize) { - let span = self.find_span(substr); - let mock_node = Node::new( - fe::FuncStmt::Expr { - value: fe::Expr::Name("foo"), - }, - span, - ); - self.context.add_declaration(&mock_node, typ) - } - } -} diff --git a/crates/analyzer/src/namespace/events.rs b/crates/analyzer/src/namespace/events.rs index 5bff996b7f..a701661d99 100644 --- a/crates/analyzer/src/namespace/events.rs +++ b/crates/analyzer/src/namespace/events.rs @@ -1,30 +1,29 @@ -use crate::namespace::types::{AbiEncoding, FixedSize}; -use fe_common::utils::keccak; +use crate::namespace::types::FixedSize; #[derive(Clone, Debug, PartialEq, Hash)] pub struct EventDef { pub name: String, - pub topic: String, pub fields: Vec<(String, FixedSize)>, pub indexed_fields: Vec, } impl EventDef { pub fn new(name: &str, fields: Vec<(String, FixedSize)>, indexed_fields: Vec) -> Self { - let abi_fields = fields - .iter() - .map(|(_, typ)| typ.abi_selector_name()) - .collect::>(); - let topic = build_event_topic(name, abi_fields); - Self { name: name.to_string(), - topic, fields, indexed_fields, } } + pub fn all_field_types(&self) -> Vec { + self.fields + .to_owned() + .into_iter() + .map(|(_, typ)| typ) + .collect() + } + /// The event's indexed fields. /// /// These should be logged as additional topics. @@ -67,11 +66,6 @@ impl EventDef { } } -fn build_event_topic(name: &str, fields: Vec) -> String { - let signature = format!("{}({})", name, fields.join(",")); - keccak::full(signature.as_bytes()) -} - #[cfg(test)] mod tests { use crate::namespace::events::EventDef; diff --git a/crates/analyzer/src/namespace/types.rs b/crates/analyzer/src/namespace/types.rs index 2aa103527e..2a3ec184cb 100644 --- a/crates/analyzer/src/namespace/types.rs +++ b/crates/analyzer/src/namespace/types.rs @@ -24,103 +24,6 @@ pub fn i256_min() -> BigInt { BigInt::from(-2).pow(255) } -/// The type has a constant size known to the compiler. -pub trait FeSized { - /// Constant size of the type. - fn size(&self) -> usize; -} - -/// ABI types given in the Solidity specification with some extra information needed to inform -/// generation of encoding/decoding functions. -#[derive(Clone, Debug, PartialEq, PartialOrd, Ord, Eq)] -pub enum AbiType { - StaticArray { inner: Box, size: usize }, - Tuple { components: Vec }, - Uint { size: usize }, - Int { size: usize }, - Bool, - Address, - String { max_size: usize }, - Bytes { size: usize }, -} - -impl AbiType { - /// The number of bytes used to encode the type's head. - pub fn head_size(&self) -> usize { - match self { - AbiType::StaticArray { size, .. } => 32 * size, - AbiType::Tuple { components } => 32 * components.len(), - AbiType::Uint { .. } => 32, - AbiType::Int { .. } => 32, - AbiType::Bool => 32, - AbiType::Address => 32, - AbiType::String { .. } => 32, - AbiType::Bytes { .. } => 32, - } - } - - /// The number of bytes used in Fe's data layout. This is used when packing and unpacking - /// arrays. - pub fn packed_size(&self) -> usize { - match *self { - AbiType::Uint { size } => size, - AbiType::Int { size } => size, - AbiType::Bool => 1, - AbiType::Address => 32, - _ => todo!("recursive encoding"), - } - } - - /// `true` if the encoded value is stored in the data section, `false` if it is not. - pub fn has_data(&self) -> bool { - match self { - AbiType::Uint { .. } => false, - AbiType::StaticArray { .. } => false, - AbiType::Tuple { .. } => false, - AbiType::Int { .. } => false, - AbiType::Bool => false, - AbiType::Address => false, - AbiType::String { .. } => true, - AbiType::Bytes { .. } => true, - } - } -} - -/// Data can be decoded from memory or calldata. -#[derive(Clone, Debug, PartialEq, PartialOrd, Ord, Eq, Copy)] -pub enum AbiDecodeLocation { - Calldata, - Memory, -} - -/// Single component of a tuple. -#[derive(Clone, Debug, PartialEq, PartialOrd, Ord, Eq)] -pub struct AbiComponent { - pub name: String, - pub typ: String, - /// The subcomponents of the component. - pub components: Vec, -} - -/// Information relevant to ABI encoding. -pub trait AbiEncoding { - /// Name of the type as it appears in the Json ABI. - fn abi_json_name(&self) -> String; - - /// Name of the type as it appears in the selector preimage. - fn abi_selector_name(&self) -> String; - - /// The components of an ABI tuple. - fn abi_components(&self) -> Vec; - - /// The ABI type of a Fe type. - fn abi_type(&self) -> AbiType; -} - -pub fn abi_types(types: &[T]) -> Vec { - types.iter().map(|typ| typ.abi_type()).collect() -} - /// Names that can be used to build identifiers without collision. pub trait SafeNames { /// Name in the lower snake format (e.g. lower_snake_case). @@ -264,6 +167,23 @@ impl Integer { ) } + pub fn size(&self) -> usize { + match self { + Integer::U256 => 32, + Integer::U128 => 16, + Integer::U64 => 8, + Integer::U32 => 4, + Integer::U16 => 2, + Integer::U8 => 1, + Integer::I256 => 32, + Integer::I128 => 16, + Integer::I64 => 8, + Integer::I32 => 4, + Integer::I16 => 2, + Integer::I8 => 1, + } + } + /// Returns `true` if the integer is at least the same size (or larger) than /// `other` pub fn can_hold(&self, other: &Integer) -> bool { @@ -464,305 +384,6 @@ impl From for FixedSize { } } -impl FeSized for FixedSize { - fn size(&self) -> usize { - match self { - FixedSize::Base(base) => base.size(), - FixedSize::Array(array) => array.size(), - FixedSize::Tuple(tuple) => tuple.size(), - FixedSize::String(string) => string.size(), - FixedSize::Contract(contract) => contract.size(), - FixedSize::Struct(val) => val.size(), - } - } -} - -impl FeSized for Integer { - fn size(&self) -> usize { - match self { - Integer::U8 => 1, - Integer::U16 => 2, - Integer::U32 => 4, - Integer::U64 => 8, - Integer::U128 => 16, - Integer::U256 => 32, - Integer::I8 => 1, - Integer::I16 => 2, - Integer::I32 => 4, - Integer::I64 => 8, - Integer::I128 => 16, - Integer::I256 => 32, - } - } -} - -impl FeSized for Base { - fn size(&self) -> usize { - match self { - Base::Numeric(integer) => integer.size(), - Base::Bool => 1, - Base::Address => 32, - Base::Unit => 0, - } - } -} - -impl FeSized for Array { - fn size(&self) -> usize { - self.size * self.inner.size() - } -} - -impl FeSized for Tuple { - fn size(&self) -> usize { - self.items.iter().map(|typ| typ.size()).sum() - } -} - -impl FeSized for Struct { - fn size(&self) -> usize { - self.fields.len() * 32 - } -} - -impl FeSized for FeString { - fn size(&self) -> usize { - self.max_size + 32 - } -} - -impl FeSized for Contract { - fn size(&self) -> usize { - 32 - } -} - -impl AbiEncoding for FixedSize { - fn abi_json_name(&self) -> String { - match self { - FixedSize::Array(array) => array.abi_json_name(), - FixedSize::Base(base) => base.abi_json_name(), - FixedSize::Tuple(tuple) => tuple.abi_json_name(), - FixedSize::String(string) => string.abi_json_name(), - FixedSize::Contract(contract) => contract.abi_json_name(), - FixedSize::Struct(val) => val.abi_json_name(), - } - } - - fn abi_selector_name(&self) -> String { - match self { - FixedSize::Array(array) => array.abi_selector_name(), - FixedSize::Base(base) => base.abi_selector_name(), - FixedSize::Tuple(tuple) => tuple.abi_selector_name(), - FixedSize::String(string) => string.abi_selector_name(), - FixedSize::Contract(contract) => contract.abi_selector_name(), - FixedSize::Struct(val) => val.abi_selector_name(), - } - } - - fn abi_components(&self) -> Vec { - match self { - FixedSize::Array(array) => array.abi_components(), - FixedSize::Base(base) => base.abi_components(), - FixedSize::Tuple(tuple) => tuple.abi_components(), - FixedSize::String(string) => string.abi_components(), - FixedSize::Contract(contract) => contract.abi_components(), - FixedSize::Struct(val) => val.abi_components(), - } - } - - fn abi_type(&self) -> AbiType { - match self { - FixedSize::Base(base) => base.abi_type(), - FixedSize::Array(array) => array.abi_type(), - FixedSize::Tuple(tuple) => tuple.abi_type(), - FixedSize::String(string) => string.abi_type(), - FixedSize::Contract(contract) => contract.abi_type(), - FixedSize::Struct(val) => val.abi_type(), - } - } -} - -impl AbiEncoding for Base { - fn abi_json_name(&self) -> String { - match self { - Base::Numeric(Integer::U256) => "uint256".to_string(), - Base::Numeric(Integer::U128) => "uint128".to_string(), - Base::Numeric(Integer::U64) => "uint64".to_string(), - Base::Numeric(Integer::U32) => "uint32".to_string(), - Base::Numeric(Integer::U16) => "uint16".to_string(), - Base::Numeric(Integer::U8) => "uint8".to_string(), - Base::Numeric(Integer::I256) => "int256".to_string(), - Base::Numeric(Integer::I128) => "int128".to_string(), - Base::Numeric(Integer::I64) => "int64".to_string(), - Base::Numeric(Integer::I32) => "int32".to_string(), - Base::Numeric(Integer::I16) => "int16".to_string(), - Base::Numeric(Integer::I8) => "int8".to_string(), - Base::Address => "address".to_string(), - Base::Bool => "bool".to_string(), - Base::Unit => panic!("unit type is not abi encodable"), - } - } - - fn abi_selector_name(&self) -> String { - self.abi_json_name() - } - - fn abi_components(&self) -> Vec { - vec![] - } - - fn abi_type(&self) -> AbiType { - match self { - Base::Numeric(integer) => { - let size = integer.size(); - if integer.is_signed() { - AbiType::Int { size } - } else { - AbiType::Uint { size } - } - } - Base::Address => AbiType::Address, - Base::Bool => AbiType::Bool, - Base::Unit => panic!("unit type is not abi encodable"), - } - } -} - -impl AbiEncoding for Array { - fn abi_json_name(&self) -> String { - if self.inner == Base::Numeric(Integer::U8) { - "bytes".to_string() - } else { - format!("{}[{}]", self.inner.abi_json_name(), self.size) - } - } - - fn abi_selector_name(&self) -> String { - self.abi_json_name() - } - - fn abi_components(&self) -> Vec { - vec![] - } - - fn abi_type(&self) -> AbiType { - if matches!(self.inner, Base::Numeric(Integer::U8)) { - AbiType::Bytes { size: self.size } - } else { - AbiType::StaticArray { - inner: Box::new(self.inner.abi_type()), - size: self.size, - } - } - } -} - -impl AbiEncoding for Struct { - fn abi_json_name(&self) -> String { - "tuple".to_string() - } - - fn abi_selector_name(&self) -> String { - let field_names = self - .fields - .iter() - .map(|(_, typ)| typ.abi_json_name()) - .collect::>(); - let joined_names = field_names.join(","); - format!("({})", joined_names) - } - - fn abi_components(&self) -> Vec { - self.fields - .iter() - .map(|(name, typ)| AbiComponent { - name: name.to_owned(), - typ: typ.abi_json_name(), - components: vec![], - }) - .collect() - } - - fn abi_type(&self) -> AbiType { - AbiType::Tuple { - components: self.fields.iter().map(|(_, typ)| typ.abi_type()).collect(), - } - } -} - -impl AbiEncoding for Tuple { - fn abi_json_name(&self) -> String { - "tuple".to_string() - } - - fn abi_selector_name(&self) -> String { - let field_names = self - .items - .iter() - .map(|typ| typ.abi_json_name()) - .collect::>(); - let joined_names = field_names.join(","); - format!("({})", joined_names) - } - - fn abi_components(&self) -> Vec { - self.items - .iter() - .enumerate() - .map(|(index, item)| AbiComponent { - name: format!("item{}", index), - typ: item.abi_json_name(), - components: vec![], - }) - .collect() - } - - fn abi_type(&self) -> AbiType { - AbiType::Tuple { - components: self.items.iter().map(|typ| typ.abi_type()).collect(), - } - } -} - -impl AbiEncoding for Contract { - fn abi_json_name(&self) -> String { - unimplemented!(); - } - - fn abi_selector_name(&self) -> String { - unimplemented!() - } - - fn abi_components(&self) -> Vec { - unimplemented!() - } - - fn abi_type(&self) -> AbiType { - unimplemented!(); - } -} - -impl AbiEncoding for FeString { - fn abi_json_name(&self) -> String { - "string".to_string() - } - - fn abi_selector_name(&self) -> String { - "string".to_string() - } - - fn abi_components(&self) -> Vec { - vec![] - } - - fn abi_type(&self) -> AbiType { - AbiType::String { - max_size: self.max_size, - } - } -} - impl SafeNames for FixedSize { fn lower_snake(&self) -> String { match self { diff --git a/crates/analyzer/tests/snapshots/analysis__abi_encoding_stress.snap b/crates/analyzer/tests/snapshots/analysis__abi_encoding_stress.snap index be5e21362e..1c9c632c87 100644 --- a/crates/analyzer/tests/snapshots/analysis__abi_encoding_stress.snap +++ b/crates/analyzer/tests/snapshots/analysis__abi_encoding_stress.snap @@ -1559,11 +1559,10 @@ note: · │ 81 │ │ my_bytes=self.my_bytes.to_mem() 82 │ │ ) - │ ╰─────────^ attributes hash: 4513326996750634814 + │ ╰─────────^ attributes hash: 12177163395993072198 │ = EventDef { name: "MyEvent", - topic: "0xcac88c5748a42fc8d9baf196f981a3571f79726e9c579d4268b8b1155eb48f47", fields: [ ( "my_addrs", @@ -2065,7 +2064,7 @@ note: · │ 81 │ │ my_bytes=self.my_bytes.to_mem() 82 │ │ ) - │ ╰─────────^ attributes hash: 6100196207567586091 + │ ╰─────────^ attributes hash: 10470223520467846865 │ = ContractAttributes { public_functions: [ @@ -2373,7 +2372,6 @@ note: events: [ EventDef { name: "MyEvent", - topic: "0xcac88c5748a42fc8d9baf196f981a3571f79726e9c579d4268b8b1155eb48f47", fields: [ ( "my_addrs", @@ -2640,11 +2638,10 @@ note: 19 │ │ my_u16s: u16[255] 20 │ │ my_bool: bool 21 │ │ my_bytes: u8[100] - │ ╰─────────────────────────^ attributes hash: 4513326996750634814 + │ ╰─────────────────────────^ attributes hash: 12177163395993072198 │ = EventDef { name: "MyEvent", - topic: "0xcac88c5748a42fc8d9baf196f981a3571f79726e9c579d4268b8b1155eb48f47", fields: [ ( "my_addrs", diff --git a/crates/analyzer/tests/snapshots/analysis__data_copying_stress.snap b/crates/analyzer/tests/snapshots/analysis__data_copying_stress.snap index fa0d7442a2..cff3bcf487 100644 --- a/crates/analyzer/tests/snapshots/analysis__data_copying_stress.snap +++ b/crates/analyzer/tests/snapshots/analysis__data_copying_stress.snap @@ -2097,11 +2097,10 @@ note: ┌─ stress/data_copying_stress.fe:74:9 │ 74 │ emit MyEvent(my_string=some_string, my_u256=some_u256) - │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attributes hash: 8256047936283544719 + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attributes hash: 2143436862180406659 │ = EventDef { name: "MyEvent", - topic: "0x417b479eab59fa49bedfbbb7cab907b3a81d8375cfca57da274a3d8b6c61a813", fields: [ ( "my_string", @@ -2503,7 +2502,7 @@ note: · │ 79 │ │ pub def get_my_second_addr() -> address: 80 │ │ return self.my_addrs[1] - │ ╰───────────────────────────────^ attributes hash: 13264315667730462853 + │ ╰───────────────────────────────^ attributes hash: 6310860118106615959 │ = ContractAttributes { public_functions: [ @@ -2703,7 +2702,6 @@ note: events: [ EventDef { name: "MyEvent", - topic: "0x417b479eab59fa49bedfbbb7cab907b3a81d8375cfca57da274a3d8b6c61a813", fields: [ ( "my_string", @@ -2785,11 +2783,10 @@ note: 12 │ ╭ event MyEvent: 13 │ │ my_string: String<42> 14 │ │ my_u256: u256 - │ ╰─────────────────────^ attributes hash: 8256047936283544719 + │ ╰─────────────────────^ attributes hash: 2143436862180406659 │ = EventDef { name: "MyEvent", - topic: "0x417b479eab59fa49bedfbbb7cab907b3a81d8375cfca57da274a3d8b6c61a813", fields: [ ( "my_string", diff --git a/crates/analyzer/tests/snapshots/analysis__erc20_token.snap b/crates/analyzer/tests/snapshots/analysis__erc20_token.snap index 08a1d0d28e..8b4c8f9e7f 100644 --- a/crates/analyzer/tests/snapshots/analysis__erc20_token.snap +++ b/crates/analyzer/tests/snapshots/analysis__erc20_token.snap @@ -3229,11 +3229,10 @@ note: ┌─ demos/erc20_token.fe:76:9 │ 76 │ emit Transfer(from=sender, to=recipient, value=value) - │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attributes hash: 7306228411242967775 + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attributes hash: 13133831135344517982 │ = EventDef { name: "Transfer", - topic: "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", fields: [ ( "from", @@ -3266,11 +3265,10 @@ note: ┌─ demos/erc20_token.fe:85:9 │ 85 │ emit Transfer(from=address(0), to=account, value=value) - │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attributes hash: 7306228411242967775 + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attributes hash: 13133831135344517982 │ = EventDef { name: "Transfer", - topic: "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", fields: [ ( "from", @@ -3303,11 +3301,10 @@ note: ┌─ demos/erc20_token.fe:94:9 │ 94 │ emit Transfer(from=account, to=address(0), value) - │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attributes hash: 7306228411242967775 + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attributes hash: 13133831135344517982 │ = EventDef { name: "Transfer", - topic: "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", fields: [ ( "from", @@ -3340,11 +3337,10 @@ note: ┌─ demos/erc20_token.fe:101:9 │ 101 │ emit Approval(owner, spender, value) - │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attributes hash: 1848444562662411933 + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attributes hash: 33203932515406232 │ = EventDef { name: "Approval", - topic: "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925", fields: [ ( "owner", @@ -3933,7 +3929,7 @@ note: · │ 106 │ │ def _before_token_transfer(from: address, to: address, value: u256): 107 │ │ pass - │ ╰────────────^ attributes hash: 9140180386963659551 + │ ╰────────────^ attributes hash: 2383532079953921392 │ = ContractAttributes { public_functions: [ @@ -4169,7 +4165,6 @@ note: events: [ EventDef { name: "Approval", - topic: "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925", fields: [ ( "owner", @@ -4199,7 +4194,6 @@ note: }, EventDef { name: "Transfer", - topic: "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", fields: [ ( "from", @@ -4489,11 +4483,10 @@ note: 12 │ │ idx owner: address 13 │ │ idx spender: address 14 │ │ value: u256 - │ ╰───────────────────^ attributes hash: 1848444562662411933 + │ ╰───────────────────^ attributes hash: 33203932515406232 │ = EventDef { name: "Approval", - topic: "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925", fields: [ ( "owner", @@ -4529,11 +4522,10 @@ note: 17 │ │ idx from: address 18 │ │ idx to: address 19 │ │ value: u256 - │ ╰───────────────────^ attributes hash: 7306228411242967775 + │ ╰───────────────────^ attributes hash: 13133831135344517982 │ = EventDef { name: "Transfer", - topic: "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", fields: [ ( "from", diff --git a/crates/analyzer/tests/snapshots/analysis__events.snap b/crates/analyzer/tests/snapshots/analysis__events.snap index dd63c933ac..ca6eea1fc3 100644 --- a/crates/analyzer/tests/snapshots/analysis__events.snap +++ b/crates/analyzer/tests/snapshots/analysis__events.snap @@ -355,11 +355,10 @@ note: ┌─ features/events.fe:20:9 │ 20 │ emit Nums(num1=26, num2=42) - │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^ attributes hash: 10238921483171311 + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^ attributes hash: 4173083644535479702 │ = EventDef { name: "Nums", - topic: "0x3cc309fb61c8d0d1165018be6f4c8d7f7fd4ef4739dea209201fe9d06f2dc8c3", fields: [ ( "num1", @@ -387,11 +386,10 @@ note: ┌─ features/events.fe:23:9 │ 23 │ emit Bases(num=26, addr) - │ ^^^^^^^^^^^^^^^^^^^^^^^^ attributes hash: 9537689344407037091 + │ ^^^^^^^^^^^^^^^^^^^^^^^^ attributes hash: 5225681472135288954 │ = EventDef { name: "Bases", - topic: "0x6bffe320be20b1367c958a4599064519ff8b5a775856c842306b2549283f977b", fields: [ ( "num", @@ -415,11 +413,10 @@ note: ┌─ features/events.fe:26:9 │ 26 │ emit Mix(num1=26, addr, num2=42, my_bytes) - │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attributes hash: 17802014580178921388 + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attributes hash: 9252761509683604439 │ = EventDef { name: "Mix", - topic: "0xb81cb79c37f55a0aac157707a5d7ce4bd0a2571eea1abfefcc3df86c9e2ac1a4", fields: [ ( "num1", @@ -464,11 +461,10 @@ note: ┌─ features/events.fe:32:9 │ 32 │ emit Addresses(addrs) - │ ^^^^^^^^^^^^^^^^^^^^^ attributes hash: 7515606018431882693 + │ ^^^^^^^^^^^^^^^^^^^^^ attributes hash: 11156221068256331545 │ = EventDef { name: "Addresses", - topic: "0x56000a174d799384dffb63081e5f2a4875fdfb797b50719cf536d42e2aeea37f", fields: [ ( "addrs", @@ -611,7 +607,7 @@ note: · │ 31 │ │ addrs[1] = addr2 32 │ │ emit Addresses(addrs) - │ ╰─────────────────────────────^ attributes hash: 1223784352612324630 + │ ╰─────────────────────────────^ attributes hash: 5589918496276372530 │ = ContractAttributes { public_functions: [ @@ -690,7 +686,6 @@ note: events: [ EventDef { name: "Addresses", - topic: "0x56000a174d799384dffb63081e5f2a4875fdfb797b50719cf536d42e2aeea37f", fields: [ ( "addrs", @@ -706,7 +701,6 @@ note: }, EventDef { name: "Bases", - topic: "0x6bffe320be20b1367c958a4599064519ff8b5a775856c842306b2549283f977b", fields: [ ( "num", @@ -727,7 +721,6 @@ note: }, EventDef { name: "Mix", - topic: "0xb81cb79c37f55a0aac157707a5d7ce4bd0a2571eea1abfefcc3df86c9e2ac1a4", fields: [ ( "num1", @@ -769,7 +762,6 @@ note: }, EventDef { name: "Nums", - topic: "0x3cc309fb61c8d0d1165018be6f4c8d7f7fd4ef4739dea209201fe9d06f2dc8c3", fields: [ ( "num1", @@ -803,11 +795,10 @@ note: 2 │ ╭ event Nums: 3 │ │ idx num1: u256 4 │ │ num2: u256 - │ ╰──────────────────^ attributes hash: 10238921483171311 + │ ╰──────────────────^ attributes hash: 4173083644535479702 │ = EventDef { name: "Nums", - topic: "0x3cc309fb61c8d0d1165018be6f4c8d7f7fd4ef4739dea209201fe9d06f2dc8c3", fields: [ ( "num1", @@ -837,11 +828,10 @@ note: 6 │ ╭ event Bases: 7 │ │ num: u256 8 │ │ addr: address - │ ╰─────────────────────^ attributes hash: 9537689344407037091 + │ ╰─────────────────────^ attributes hash: 5225681472135288954 │ = EventDef { name: "Bases", - topic: "0x6bffe320be20b1367c958a4599064519ff8b5a775856c842306b2549283f977b", fields: [ ( "num", @@ -869,11 +859,10 @@ note: 12 │ │ idx addr: address 13 │ │ num2: u256 14 │ │ my_bytes: u8[100] - │ ╰─────────────────────────^ attributes hash: 17802014580178921388 + │ ╰─────────────────────────^ attributes hash: 9252761509683604439 │ = EventDef { name: "Mix", - topic: "0xb81cb79c37f55a0aac157707a5d7ce4bd0a2571eea1abfefcc3df86c9e2ac1a4", fields: [ ( "num1", @@ -919,11 +908,10 @@ note: │ 16 │ ╭ event Addresses: 17 │ │ addrs: address[2] - │ ╰─────────────────────────^ attributes hash: 7515606018431882693 + │ ╰─────────────────────────^ attributes hash: 11156221068256331545 │ = EventDef { name: "Addresses", - topic: "0x56000a174d799384dffb63081e5f2a4875fdfb797b50719cf536d42e2aeea37f", fields: [ ( "addrs", diff --git a/crates/analyzer/tests/snapshots/analysis__external_contract.snap b/crates/analyzer/tests/snapshots/analysis__external_contract.snap index 9acb4f6b69..f8c1084d6b 100644 --- a/crates/analyzer/tests/snapshots/analysis__external_contract.snap +++ b/crates/analyzer/tests/snapshots/analysis__external_contract.snap @@ -937,11 +937,10 @@ note: ┌─ features/external_contract.fe:8:9 │ 8 │ emit MyEvent(my_num, my_addrs, my_string) - │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attributes hash: 4492871892068261472 + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attributes hash: 3647007368702598913 │ = EventDef { name: "MyEvent", - topic: "0xd67c2bc3a91d2cec185a9b15d2b3c2ab27e058d76493e2442c375b78fc226e7b", fields: [ ( "my_num", @@ -1339,7 +1338,7 @@ note: · │ 14 │ │ my_array[2] = b 15 │ │ return my_array - │ ╰───────────────────────^ attributes hash: 10746953601890129745 + │ ╰───────────────────────^ attributes hash: 15321376917823949382 │ = ContractAttributes { public_functions: [ @@ -1412,7 +1411,6 @@ note: events: [ EventDef { name: "MyEvent", - topic: "0xd67c2bc3a91d2cec185a9b15d2b3c2ab27e058d76493e2442c375b78fc226e7b", fields: [ ( "my_num", @@ -1879,11 +1877,10 @@ note: 3 │ │ my_num: u256 4 │ │ my_addrs: address[5] 5 │ │ my_string: String<11> - │ ╰─────────────────────────────^ attributes hash: 4492871892068261472 + │ ╰─────────────────────────────^ attributes hash: 3647007368702598913 │ = EventDef { name: "MyEvent", - topic: "0xd67c2bc3a91d2cec185a9b15d2b3c2ab27e058d76493e2442c375b78fc226e7b", fields: [ ( "my_num", diff --git a/crates/analyzer/tests/snapshots/analysis__guest_book.snap b/crates/analyzer/tests/snapshots/analysis__guest_book.snap index 524e631913..b254d5627b 100644 --- a/crates/analyzer/tests/snapshots/analysis__guest_book.snap +++ b/crates/analyzer/tests/snapshots/analysis__guest_book.snap @@ -219,11 +219,10 @@ note: ┌─ demos/guest_book.fe:16:9 │ 16 │ emit Signed(book_msg=book_msg) - │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attributes hash: 7183865788821629486 + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attributes hash: 9556729338567466879 │ = EventDef { name: "Signed", - topic: "0xcd5d879305a2503cad08d3e2d007778eec8dc5def7bc74dd20875842b2ff7765", fields: [ ( "book_msg", @@ -303,7 +302,7 @@ note: · │ 20 │ │ # has to be done explicitly via `to_mem()` 21 │ │ return self.messages[addr].to_mem() - │ ╰───────────────────────────────────────────^ attributes hash: 10725603398456560869 + │ ╰───────────────────────────────────────────^ attributes hash: 9853337215152345802 │ = ContractAttributes { public_functions: [ @@ -346,7 +345,6 @@ note: events: [ EventDef { name: "Signed", - topic: "0xcd5d879305a2503cad08d3e2d007778eec8dc5def7bc74dd20875842b2ff7765", fields: [ ( "book_msg", @@ -377,11 +375,10 @@ note: │ 8 │ ╭ event Signed: 9 │ │ book_msg: String<100> - │ ╰─────────────────────────────^ attributes hash: 7183865788821629486 + │ ╰─────────────────────────────^ attributes hash: 9556729338567466879 │ = EventDef { name: "Signed", - topic: "0xcd5d879305a2503cad08d3e2d007778eec8dc5def7bc74dd20875842b2ff7765", fields: [ ( "book_msg", diff --git a/crates/analyzer/tests/snapshots/analysis__ownable.snap b/crates/analyzer/tests/snapshots/analysis__ownable.snap index cd878683a6..1753a6b4e8 100644 --- a/crates/analyzer/tests/snapshots/analysis__ownable.snap +++ b/crates/analyzer/tests/snapshots/analysis__ownable.snap @@ -408,11 +408,10 @@ note: ┌─ features/ownable.fe:17:5 │ 17 │ emit OwnershipTransferred(previousOwner=msg.sender, newOwner=address(0)) - │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attributes hash: 2811860516133209857 + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attributes hash: 9113824683084517456 │ = EventDef { name: "OwnershipTransferred", - topic: "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", fields: [ ( "previousOwner", @@ -437,11 +436,10 @@ note: ┌─ features/ownable.fe:23:5 │ 23 │ emit OwnershipTransferred(previousOwner=msg.sender, newOwner) - │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attributes hash: 2811860516133209857 + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attributes hash: 9113824683084517456 │ = EventDef { name: "OwnershipTransferred", - topic: "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", fields: [ ( "previousOwner", @@ -548,7 +546,7 @@ note: · │ 22 │ │ self._owner = newOwner 23 │ │ emit OwnershipTransferred(previousOwner=msg.sender, newOwner) - │ ╰─────────────────────────────────────────────────────────────────^ attributes hash: 6356425488681343574 + │ ╰─────────────────────────────────────────────────────────────────^ attributes hash: 3105072853312817186 │ = ContractAttributes { public_functions: [ @@ -597,7 +595,6 @@ note: events: [ EventDef { name: "OwnershipTransferred", - topic: "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", fields: [ ( "previousOwner", @@ -664,11 +661,10 @@ note: 4 │ ╭ event OwnershipTransferred: 5 │ │ idx previousOwner: address 6 │ │ idx newOwner: address - │ ╰─────────────────────────^ attributes hash: 2811860516133209857 + │ ╰─────────────────────────^ attributes hash: 9113824683084517456 │ = EventDef { name: "OwnershipTransferred", - topic: "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", fields: [ ( "previousOwner", diff --git a/crates/analyzer/tests/snapshots/analysis__sized_vals_in_sto.snap b/crates/analyzer/tests/snapshots/analysis__sized_vals_in_sto.snap index 6b7497de9f..01ef2a0869 100644 --- a/crates/analyzer/tests/snapshots/analysis__sized_vals_in_sto.snap +++ b/crates/analyzer/tests/snapshots/analysis__sized_vals_in_sto.snap @@ -456,11 +456,10 @@ note: 32 │ │ nums=self.nums.to_mem(), 33 │ │ str=self.str.to_mem() 34 │ │ ) - │ ╰─────────^ attributes hash: 3097665000133065506 + │ ╰─────────^ attributes hash: 12755436388436492077 │ = EventDef { name: "MyEvent", - topic: "0xa1df37e97e04df228bf0d77958ff8e03261b1070a21f3aa7a439f6d234c1dcf2", fields: [ ( "num", @@ -658,7 +657,7 @@ note: · │ 33 │ │ str=self.str.to_mem() 34 │ │ ) - │ ╰─────────^ attributes hash: 6442315895292032331 + │ ╰─────────^ attributes hash: 5920818002125761658 │ = ContractAttributes { public_functions: [ @@ -762,7 +761,6 @@ note: events: [ EventDef { name: "MyEvent", - topic: "0xa1df37e97e04df228bf0d77958ff8e03261b1070a21f3aa7a439f6d234c1dcf2", fields: [ ( "num", @@ -838,11 +836,10 @@ note: 7 │ │ num: u256 8 │ │ nums: u256[42] 9 │ │ str: String<26> - │ ╰───────────────────────^ attributes hash: 3097665000133065506 + │ ╰───────────────────────^ attributes hash: 12755436388436492077 │ = EventDef { name: "MyEvent", - topic: "0xa1df37e97e04df228bf0d77958ff8e03261b1070a21f3aa7a439f6d234c1dcf2", fields: [ ( "num", diff --git a/crates/analyzer/tests/snapshots/analysis__strings.snap b/crates/analyzer/tests/snapshots/analysis__strings.snap index 25ed387d98..cb541638b5 100644 --- a/crates/analyzer/tests/snapshots/analysis__strings.snap +++ b/crates/analyzer/tests/snapshots/analysis__strings.snap @@ -284,11 +284,10 @@ note: ┌─ features/strings.fe:12:9 │ 12 │ emit MyEvent(s2, u, s1, s3, a, s4="static string", s5=String<100>("foo")) - │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attributes hash: 14401346865018949396 + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attributes hash: 2616592871617117419 │ = EventDef { name: "MyEvent", - topic: "0x3c1df123f6496961966c7a4f1c9f9d6931ad63ae890874ecf4470db31dfaed78", fields: [ ( "s2", @@ -503,7 +502,7 @@ note: · │ 24 │ │ return "foo 25 │ │ balu" - │ ╰─────────────^ attributes hash: 8230381975525950566 + │ ╰─────────────^ attributes hash: 5325600778331999631 │ = ContractAttributes { public_functions: [ @@ -617,7 +616,6 @@ note: events: [ EventDef { name: "MyEvent", - topic: "0x3c1df123f6496961966c7a4f1c9f9d6931ad63ae890874ecf4470db31dfaed78", fields: [ ( "s2", @@ -719,11 +717,10 @@ note: · │ 8 │ │ s4: String<13> 9 │ │ s5: String<100> - │ ╰───────────────────────^ attributes hash: 14401346865018949396 + │ ╰───────────────────────^ attributes hash: 2616592871617117419 │ = EventDef { name: "MyEvent", - topic: "0x3c1df123f6496961966c7a4f1c9f9d6931ad63ae890874ecf4470db31dfaed78", fields: [ ( "s2", diff --git a/crates/analyzer/tests/snapshots/analysis__tuple_stress.snap b/crates/analyzer/tests/snapshots/analysis__tuple_stress.snap index b7b9ebf448..4e3350fd18 100644 --- a/crates/analyzer/tests/snapshots/analysis__tuple_stress.snap +++ b/crates/analyzer/tests/snapshots/analysis__tuple_stress.snap @@ -1168,11 +1168,10 @@ note: ┌─ stress/tuple_stress.fe:24:9 │ 24 │ emit MyEvent(my_tuple) - │ ^^^^^^^^^^^^^^^^^^^^^^ attributes hash: 8657778404503886351 + │ ^^^^^^^^^^^^^^^^^^^^^^ attributes hash: 1448730452803770990 │ = EventDef { name: "MyEvent", - topic: "0x61f3dbecaa72e626e43d4d3e9617d7c4f3c6cba20efd487973b991c1d46f3627", fields: [ ( "my_tuple", @@ -1579,7 +1578,7 @@ note: · │ 42 │ │ pub def encode_my_tuple(my_tuple: (u256, bool, address)) -> u8[96]: 43 │ │ return my_tuple.abi_encode() - │ ╰────────────────────────────────────^ attributes hash: 10749101579316714129 + │ ╰────────────────────────────────────^ attributes hash: 13290905967414103606 │ = ContractAttributes { public_functions: [ @@ -1837,7 +1836,6 @@ note: events: [ EventDef { name: "MyEvent", - topic: "0x61f3dbecaa72e626e43d4d3e9617d7c4f3c6cba20efd487973b991c1d46f3627", fields: [ ( "my_tuple", @@ -1938,11 +1936,10 @@ note: │ 4 │ ╭ event MyEvent: 5 │ │ my_tuple: (u256, bool, address) - │ ╰───────────────────────────────────────^ attributes hash: 8657778404503886351 + │ ╰───────────────────────────────────────^ attributes hash: 1448730452803770990 │ = EventDef { name: "MyEvent", - topic: "0x61f3dbecaa72e626e43d4d3e9617d7c4f3c6cba20efd487973b991c1d46f3627", fields: [ ( "my_tuple", diff --git a/crates/analyzer/tests/snapshots/analysis__uniswap.snap b/crates/analyzer/tests/snapshots/analysis__uniswap.snap index f94cdf6d22..60a7c299d9 100644 --- a/crates/analyzer/tests/snapshots/analysis__uniswap.snap +++ b/crates/analyzer/tests/snapshots/analysis__uniswap.snap @@ -13742,11 +13742,10 @@ note: ┌─ demos/uniswap.fe:78:9 │ 78 │ emit Transfer(from=address(0), to, value) - │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attributes hash: 7306228411242967775 + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attributes hash: 13133831135344517982 │ = EventDef { name: "Transfer", - topic: "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", fields: [ ( "from", @@ -13779,11 +13778,10 @@ note: ┌─ demos/uniswap.fe:83:9 │ 83 │ emit Transfer(from, to=address(0), value) - │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attributes hash: 7306228411242967775 + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attributes hash: 13133831135344517982 │ = EventDef { name: "Transfer", - topic: "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", fields: [ ( "from", @@ -13816,11 +13814,10 @@ note: ┌─ demos/uniswap.fe:87:9 │ 87 │ emit Approval(owner, spender, value) - │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attributes hash: 1848444562662411933 + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attributes hash: 33203932515406232 │ = EventDef { name: "Approval", - topic: "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925", fields: [ ( "owner", @@ -13853,11 +13850,10 @@ note: ┌─ demos/uniswap.fe:92:9 │ 92 │ emit Transfer(from, to, value) - │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attributes hash: 7306228411242967775 + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attributes hash: 13133831135344517982 │ = EventDef { name: "Transfer", - topic: "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", fields: [ ( "from", @@ -13890,11 +13886,10 @@ note: ┌─ demos/uniswap.fe:135:9 │ 135 │ emit Sync(reserve0=self.reserve0, reserve1=self.reserve1) - │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attributes hash: 1491363276386853569 + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attributes hash: 13994204795377527353 │ = EventDef { name: "Sync", - topic: "0xcf2aa50876cdfbb541206f89af0ee78d44a2abf8d328e37fa4917f982149848a", fields: [ ( "reserve0", @@ -13920,11 +13915,10 @@ note: ┌─ demos/uniswap.fe:184:9 │ 184 │ emit Mint(sender=msg.sender, amount0, amount1) - │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attributes hash: 16552791640588084768 + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attributes hash: 2843628716761322765 │ = EventDef { name: "Mint", - topic: "0x4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f", fields: [ ( "sender", @@ -13958,11 +13952,10 @@ note: ┌─ demos/uniswap.fe:213:9 │ 213 │ emit Burn(sender=msg.sender, amount0, amount1, to) - │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attributes hash: 13447946108360371057 + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attributes hash: 2179438666396421974 │ = EventDef { name: "Burn", - topic: "0xdccd412f0b1252819cb1fd330b93224ca42612892bb3f4f789976e6d81936496", fields: [ ( "sender", @@ -14003,11 +13996,10 @@ note: ┌─ demos/uniswap.fe:253:9 │ 253 │ emit Swap(sender=msg.sender, amount0_in, amount1_in, amount0_out, amount1_out, to) - │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attributes hash: 16809180625926927400 + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attributes hash: 13230512840943275093 │ = EventDef { name: "Swap", - topic: "0xd78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d822", fields: [ ( "sender", @@ -14064,11 +14056,10 @@ note: ┌─ demos/uniswap.fe:328:9 │ 328 │ emit PairCreated(token0, token1, pair=address(pair), index=self.pair_counter) - │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attributes hash: 15124876836433594590 + │ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attributes hash: 6014823549090347161 │ = EventDef { name: "PairCreated", - topic: "0x0d3648bd0f6ba80134a33ba9275ac585d9d315f0ad8355cddefde31afa28d0e9", fields: [ ( "token0", @@ -16655,7 +16646,7 @@ note: · │ 281 │ │ def min(x: u256, y: u256) -> u256: 282 │ │ return x if x < y else y - │ ╰────────────────────────────────^ attributes hash: 3296488074704541138 + │ ╰────────────────────────────────^ attributes hash: 70790541238228800 │ = ContractAttributes { public_functions: [ @@ -16935,7 +16926,6 @@ note: events: [ EventDef { name: "Approval", - topic: "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925", fields: [ ( "owner", @@ -16965,7 +16955,6 @@ note: }, EventDef { name: "Burn", - topic: "0xdccd412f0b1252819cb1fd330b93224ca42612892bb3f4f789976e6d81936496", fields: [ ( "sender", @@ -17003,7 +16992,6 @@ note: }, EventDef { name: "Mint", - topic: "0x4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f", fields: [ ( "sender", @@ -17034,7 +17022,6 @@ note: }, EventDef { name: "Swap", - topic: "0xd78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d822", fields: [ ( "sender", @@ -17088,7 +17075,6 @@ note: }, EventDef { name: "Sync", - topic: "0xcf2aa50876cdfbb541206f89af0ee78d44a2abf8d328e37fa4917f982149848a", fields: [ ( "reserve0", @@ -17111,7 +17097,6 @@ note: }, EventDef { name: "Transfer", - topic: "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", fields: [ ( "from", @@ -17282,7 +17267,7 @@ note: · │ 336 │ │ assert msg.sender == fee_to_setter, "UniswapV2: FORBIDDEN" 337 │ │ self.fee_to_setter = fee_to_setter - │ ╰──────────────────────────────────────────^ attributes hash: 17828679396369561962 + │ ╰──────────────────────────────────────────^ attributes hash: 15769488941515133797 │ = ContractAttributes { public_functions: [ @@ -17384,7 +17369,6 @@ note: events: [ EventDef { name: "PairCreated", - topic: "0x0d3648bd0f6ba80134a33ba9275ac585d9d315f0ad8355cddefde31afa28d0e9", fields: [ ( "token0", @@ -19179,11 +19163,10 @@ note: 31 │ │ idx owner: address 32 │ │ idx spender: address 33 │ │ value: u256 - │ ╰───────────────────^ attributes hash: 1848444562662411933 + │ ╰───────────────────^ attributes hash: 33203932515406232 │ = EventDef { name: "Approval", - topic: "0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925", fields: [ ( "owner", @@ -19219,11 +19202,10 @@ note: 36 │ │ idx from: address 37 │ │ idx to: address 38 │ │ value: u256 - │ ╰───────────────────^ attributes hash: 7306228411242967775 + │ ╰───────────────────^ attributes hash: 13133831135344517982 │ = EventDef { name: "Transfer", - topic: "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", fields: [ ( "from", @@ -19259,11 +19241,10 @@ note: 41 │ │ idx sender: address 42 │ │ amount0: u256 43 │ │ amount1: u256 - │ ╰─────────────────────^ attributes hash: 16552791640588084768 + │ ╰─────────────────────^ attributes hash: 2843628716761322765 │ = EventDef { name: "Mint", - topic: "0x4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f", fields: [ ( "sender", @@ -19301,11 +19282,10 @@ note: 47 │ │ amount0: u256 48 │ │ amount1: u256 49 │ │ idx to: address - │ ╰───────────────────────^ attributes hash: 13447946108360371057 + │ ╰───────────────────────^ attributes hash: 2179438666396421974 │ = EventDef { name: "Burn", - topic: "0xdccd412f0b1252819cb1fd330b93224ca42612892bb3f4f789976e6d81936496", fields: [ ( "sender", @@ -19352,11 +19332,10 @@ note: 55 │ │ amount0_out: u256 56 │ │ amount1_out: u256 57 │ │ idx to: address - │ ╰───────────────────────^ attributes hash: 16809180625926927400 + │ ╰───────────────────────^ attributes hash: 13230512840943275093 │ = EventDef { name: "Swap", - topic: "0xd78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d822", fields: [ ( "sender", @@ -19415,11 +19394,10 @@ note: 59 │ ╭ event Sync: 60 │ │ reserve0: u256 61 │ │ reserve1: u256 - │ ╰──────────────────────^ attributes hash: 1491363276386853569 + │ ╰──────────────────────^ attributes hash: 13994204795377527353 │ = EventDef { name: "Sync", - topic: "0xcf2aa50876cdfbb541206f89af0ee78d44a2abf8d328e37fa4917f982149848a", fields: [ ( "reserve0", @@ -19449,11 +19427,10 @@ note: 295 │ │ idx token1: address 296 │ │ pair: address 297 │ │ index: u256 - │ ╰───────────────────^ attributes hash: 15124876836433594590 + │ ╰───────────────────^ attributes hash: 6014823549090347161 │ = EventDef { name: "PairCreated", - topic: "0x0d3648bd0f6ba80134a33ba9275ac585d9d315f0ad8355cddefde31afa28d0e9", fields: [ ( "token0", diff --git a/crates/test-utils/src/lib.rs b/crates/test-utils/src/lib.rs index 221330d6f4..5c8ec651fe 100644 --- a/crates/test-utils/src/lib.rs +++ b/crates/test-utils/src/lib.rs @@ -158,8 +158,9 @@ impl ContractHarness { .collect::>(); if !outputs_for_event.iter().any(|v| v == expected_output) { + println!("raw logs dump: {:?}", raw_logs); panic!( - "no {} logs matching: {:?}\nfound: {:?}", + "no \"{}\" logs matching: {:?}\nfound: {:?}", name, expected_output, outputs_for_event ) } diff --git a/crates/yulgen/src/constructor.rs b/crates/yulgen/src/constructor.rs index 3419154a84..de055b1031 100644 --- a/crates/yulgen/src/constructor.rs +++ b/crates/yulgen/src/constructor.rs @@ -1,6 +1,7 @@ use crate::names::abi as abi_names; use crate::operations::abi as abi_operations; -use fe_analyzer::namespace::types::{AbiDecodeLocation, FixedSize}; +use crate::types::{to_abi_types, AbiDecodeLocation}; +use fe_analyzer::namespace::types::FixedSize; use yultsur::*; /// Builds a constructor for a contract with no init function. @@ -31,7 +32,7 @@ pub fn build_with_init( statements! {} } else { let decode_expr = abi_operations::decode_data( - &init_params, + &to_abi_types(&init_params), expression! { params_start_mem }, expression! { params_end_mem }, AbiDecodeLocation::Memory, diff --git a/crates/yulgen/src/lib.rs b/crates/yulgen/src/lib.rs index 5bec652cef..0a109c3583 100644 --- a/crates/yulgen/src/lib.rs +++ b/crates/yulgen/src/lib.rs @@ -12,6 +12,7 @@ mod mappers; pub mod names; pub mod operations; pub mod runtime; +pub mod types; mod utils; pub(crate) use context::Context; diff --git a/crates/yulgen/src/mappers/assignments.rs b/crates/yulgen/src/mappers/assignments.rs index 4c3ae29de1..c16ee4908c 100644 --- a/crates/yulgen/src/mappers/assignments.rs +++ b/crates/yulgen/src/mappers/assignments.rs @@ -70,91 +70,3 @@ fn expr_as_ident(expr: yul::Expression) -> yul::Identifier { panic!("expression is not an identifier"); } } - -#[cfg(test)] -#[cfg(feature = "fix-context-harness")] -mod tests { - use crate::mappers::assignments::assign; - use fe_analyzer::namespace::types::{Array, Type, U256}; - use fe_analyzer::test_utils::ContextHarness; - use fe_analyzer::{Context, ExpressionAttributes, Location}; - use fe_parser as parser; - use rstest::rstest; - - fn map(context: &Context, src: &str) -> String { - let tokens = parser::get_parse_tokens(src).expect("couldn't parse assignment"); - let stmt = parser::parsers::assign_stmt(&tokens[..]) - .expect("couldn't build assignment AST") - .1; - - let assign = assign(context, &stmt).expect("couldn't map assignment AST"); - assign.to_string() - } - - #[test] - fn assign_u256() { - let mut harness = ContextHarness::new("foo = bar"); - harness.add_expressions( - vec!["foo", "bar"], - ExpressionAttributes::new(Type::Base(U256), Location::Value), - ); - - assert_eq!(map(&harness.context, &harness.src), "$foo := $bar") - } - - #[rstest( - assignment, - expected_yul, - case("foo = 1 + 2", "$foo := checked_add_u256(1, 2)"), - case("foo = 1 - 2", "$foo := checked_sub_unsigned(1, 2)"), - case("foo = 1 * 2", "$foo := checked_mul_u256(1, 2)"), - case("foo = 1 / 2", "$foo := checked_div_unsigned(1, 2)"), - case("foo = 1 ** 2", "$foo := checked_exp_u256(1, 2)"), - case("foo = 1 % 2", "$foo := checked_mod_unsigned(1, 2)"), - case("foo = 1 & 2", "$foo := and(1, 2)"), - case("foo = 1 | 2", "$foo := or(1, 2)"), - case("foo = 1 ^ 2", "$foo := xor(1, 2)"), - case("foo = 1 << 2", "$foo := shl(2, 1)"), - case("foo = 1 >> 2", "$foo := shr(2, 1)") - )] - fn assign_arithmetic_expression(assignment: &str, expected_yul: &str) { - let mut harness = ContextHarness::new(assignment); - harness.add_expressions( - vec!["foo", "1", "2", &assignment[6..]], - ExpressionAttributes::new(Type::Base(U256), Location::Value), - ); - - assert_eq!(map(&harness.context, assignment), expected_yul) - } - - #[test] - fn assign_subscript_u256() { - let mut harness = ContextHarness::new("foo[4] = 2"); - - harness.add_expressions( - vec!["2", "4"], - ExpressionAttributes::new(Type::Base(U256), Location::Value), - ); - - harness.add_expression( - "foo[4]", - ExpressionAttributes::new(Type::Base(U256), Location::Memory), - ); - - harness.add_expression( - "foo", - ExpressionAttributes::new( - Type::Array(Array { - size: 10, - inner: U256, - }), - Location::Memory, - ), - ); - - assert_eq!( - map(&harness.context, &harness.src), - "mstoren(add($foo, mul(4, 32)), 32, 2)" - ) - } -} diff --git a/crates/yulgen/src/mappers/declarations.rs b/crates/yulgen/src/mappers/declarations.rs index a7d887fd62..a5c104eae2 100644 --- a/crates/yulgen/src/mappers/declarations.rs +++ b/crates/yulgen/src/mappers/declarations.rs @@ -1,6 +1,7 @@ use crate::mappers::expressions; +use crate::types::EvmSized; use crate::{names, Context}; -use fe_analyzer::namespace::types::{FeSized, FixedSize}; +use fe_analyzer::namespace::types::FixedSize; use fe_parser::ast as fe; use fe_parser::node::Node; use yultsur::*; @@ -39,53 +40,3 @@ fn var_decl_name(target: &fe::VarDeclTarget) -> &str { panic!("complex VarDeclTargets should be lowered to VarDeclTarget::Name") } } - -#[cfg(test)] -#[cfg(feature = "fix-context-harness")] -mod tests { - use crate::mappers::declarations::var_decl; - use fe_analyzer::namespace::types::{Array, Base, FixedSize, Type, U256}; - use fe_analyzer::test_utils::ContextHarness; - use fe_analyzer::{Context, ExpressionAttributes, Location}; - use fe_parser as parser; - - fn map(context: &Context, src: &str) -> String { - let tokens = parser::get_parse_tokens(src).expect("Couldn't parse declaration"); - let stmt = &parser::parsers::vardecl_stmt(&tokens[..]) - .expect("Couldn't build declaration AST") - .1; - - let decl = var_decl(context, &stmt).expect("Couldn't map declaration AST"); - - decl.to_string() - } - - #[test] - fn decl_u256() { - let mut harness = ContextHarness::new("foo: u256 = bar"); - harness.add_declaration("foo: u256 = bar", FixedSize::Base(U256)); - harness.add_expression( - "bar", - ExpressionAttributes::new(Type::Base(U256), Location::Value), - ); - - assert_eq!(map(&harness.context, &harness.src), "let $foo := $bar"); - } - - #[test] - fn decl_array() { - let mut harness = ContextHarness::new("foo: address[10]"); - harness.add_declaration( - "foo: address[10]", - FixedSize::Array(Array { - size: 10, - inner: Base::Address, - }), - ); - - assert_eq!( - map(&harness.context, &harness.src), - "let $foo := alloc(320)" - ); - } -} diff --git a/crates/yulgen/src/mappers/expressions.rs b/crates/yulgen/src/mappers/expressions.rs index f1db736c70..9bf4b4d78a 100644 --- a/crates/yulgen/src/mappers/expressions.rs +++ b/crates/yulgen/src/mappers/expressions.rs @@ -2,12 +2,13 @@ use crate::operations::{ abi as abi_operations, contracts as contract_operations, data as data_operations, structs as struct_operations, }; +use crate::types::{AbiType, EvmSized}; use crate::{names, Context}; use builtins::{BlockField, ChainField, MsgField, Object, TxField}; use fe_analyzer::builtins; use fe_analyzer::builtins::{ContractTypeMethod, GlobalMethod}; use fe_analyzer::context::{CallType, Location}; -use fe_analyzer::namespace::types::{Base, FeSized, FixedSize, Type}; +use fe_analyzer::namespace::types::{Base, FixedSize, Type}; use fe_common::numeric; use fe_common::utils::keccak; use fe_parser::ast as fe; @@ -134,7 +135,7 @@ fn expr_call(context: &mut Context, exp: &Node) -> yul::Expression { builtins::ValueMethod::Clone => expr(context, value), builtins::ValueMethod::AbiEncode => match typ { Type::Struct(struct_) => abi_operations::encode( - &[struct_], + &[AbiType::from(&struct_)], vec![expr(context, value)], ), _ => panic!("invalid attributes"), @@ -472,184 +473,3 @@ fn expr_bool_operation(context: &mut Context, exp: &Node) -> yul::Expr unreachable!() } - -#[cfg(test)] -#[cfg(feature = "fix-context-harness")] -mod tests { - use crate::mappers::expressions::{expr, Location}; - use fe_analyzer::namespace::types::{Array, Base, Map, Type, U256}; - use fe_analyzer::test_utils::ContextHarness; - use fe_analyzer::{Context, ExpressionAttributes}; - use fe_parser as parser; - use rstest::rstest; - - fn map(context: &mut Context, src: &str) -> String { - let tokens = parser::get_parse_tokens(src).expect("Couldn't parse expression"); - let expression = &parser::parsers::expr(&tokens[..]) - .expect("Couldn't build expression AST") - .1; - - expr(context, expression) - .expect("Couldn't map expression AST") - .to_string() - } - - #[test] - fn map_sload_u256() { - let mut harness = ContextHarness::new("self.foo[3]"); - - harness.add_expression( - "3", - ExpressionAttributes::new(Type::Base(U256), Location::Value), - ); - - harness.add_expression( - "self.foo", - ExpressionAttributes::new( - Type::Map(Map { - key: Base::Address, - value: Box::new(Type::Base(U256)), - }), - Location::Storage { nonce: Some(0) }, - ), - ); - - let mut attributes = - ExpressionAttributes::new(Type::Base(U256), Location::Storage { nonce: None }); - attributes.move_location = Some(Location::Value); - harness.add_expression("self.foo[3]", attributes); - - let result = map(&harness.context, &harness.src); - - assert_eq!(result, "bytes_sloadn(map_value_ptr(0, 3), 32)"); - } - - #[test] - fn map_sload_with_array_elem() { - let mut harness = ContextHarness::new("self.foo_map[bar_array[index]]"); - - let foo_key = Base::Address; - let foo_value = Type::Array(Array { - size: 8, - inner: Base::Address, - }); - let bar_value = Type::Base(Base::Address); - - harness.add_expression( - "self.foo_map", - ExpressionAttributes::new( - Type::Map(Map { - key: foo_key, - value: Box::new(foo_value.clone()), - }), - Location::Storage { nonce: Some(0) }, - ), - ); - - harness.add_expression( - "bar_array", - ExpressionAttributes::new( - Type::Array(Array { - size: 100, - inner: Base::Address, - }), - Location::Memory, - ), - ); - - harness.add_expression( - "index", - ExpressionAttributes::new(Type::Base(U256), Location::Value), - ); - - let mut attributes = ExpressionAttributes::new(bar_value, Location::Memory); - attributes.move_location = Some(Location::Value); - harness.add_expression("bar_array[index]", attributes); - - let mut attributes = - ExpressionAttributes::new(foo_value, Location::Storage { nonce: None }); - attributes.move_location = Some(Location::Memory); - harness.add_expression("self.foo_map[bar_array[index]]", attributes); - - let result = map(&harness.context, &harness.src); - - assert_eq!( - result, - "scopym(div(map_value_ptr(0, mloadn(add($bar_array, mul($index, 32)), 32)), 32), 256)" - ); - } - - #[rstest( - expression, - expected_yul, - typ, - case("block.coinbase", "coinbase()", Type::Base(Base::Address)), - case("block.difficulty", "difficulty()", Type::Base(U256)), - case("block.number", "number()", Type::Base(U256)), - case("block.timestamp", "timestamp()", Type::Base(U256)), - case("chain.id", "chainid()", Type::Base(U256)), - case("msg.sender", "caller()", Type::Base(Base::Address)), - case("msg.value", "callvalue()", Type::Base(U256)), - case("tx.origin", "origin()", Type::Base(Base::Address)), - case("tx.gas_price", "gasprice()", Type::Base(U256)) - )] - fn builtin_attribute(expression: &str, expected_yul: &str, typ: Type) { - let mut harness = ContextHarness::new(expression); - harness.add_expression(expression, ExpressionAttributes::new(typ, Location::Value)); - let result = map(&harness.context, expression); - assert_eq!(result, expected_yul); - } - - #[rstest( - expression, - expected_yul, - case("1 + 2", "checked_add_u256(1, 2)"), - case("1 - 2", "checked_sub_unsigned(1, 2)"), - case("1 * 2", "checked_mul_u256(1, 2)"), - case("1 / 2", "checked_div_unsigned(1, 2)"), - case("1 ** 2", "checked_exp_u256(1, 2)"), - case("1 % 2", "checked_mod_unsigned(1, 2)"), - case("1 & 2", "and(1, 2)"), - case("1 | 2", "or(1, 2)"), - case("1 ^ 2", "xor(1, 2)"), - case("1 << 2", "shl(2, 1)"), - case("1 >> 2", "shr(2, 1)") - )] - fn arithmetic_expression(expression: &str, expected_yul: &str) { - let mut harness = ContextHarness::new(expression); - harness.add_expressions( - vec!["1", "2", expression], - ExpressionAttributes::new(Type::Base(U256), Location::Value), - ); - - let result = map(&harness.context, expression); - - assert_eq!(result, expected_yul); - } - - #[rstest( - expression, - expected_yul, - case("1 == 2", "eq(1, 2)"), - case("1 != 2", "iszero(eq(1, 2))"), - case("1 < 2", "lt(1, 2)"), - case("1 <= 2", "iszero(gt(1, 2))"), - case("1 > 2", "gt(1, 2)"), - case("1 >= 2", "iszero(lt(1, 2))") - )] - fn comparison_expression(expression: &str, expected_yul: &str) { - let mut harness = ContextHarness::new(expression); - harness.add_expressions( - vec!["1", "2"], - ExpressionAttributes::new(Type::Base(U256), Location::Value), - ); - harness.add_expression( - expression, - ExpressionAttributes::new(Type::Base(Base::Bool), Location::Value), - ); - - let result = map(&harness.context, expression); - - assert_eq!(result, expected_yul); - } -} diff --git a/crates/yulgen/src/mappers/functions.rs b/crates/yulgen/src/mappers/functions.rs index 66b1fa1e10..bb4a5db9b3 100644 --- a/crates/yulgen/src/mappers/functions.rs +++ b/crates/yulgen/src/mappers/functions.rs @@ -1,11 +1,12 @@ use crate::constants::PANIC_FAILED_ASSERTION; use crate::mappers::{assignments, declarations, expressions}; use crate::names; -use crate::operations::abi as abi_operations; use crate::operations::data as data_operations; +use crate::operations::revert as revert_operations; +use crate::types::{AbiType, EvmSized}; use crate::Context; use fe_analyzer::context::ExpressionAttributes; -use fe_analyzer::namespace::types::{FeSized, FixedSize, Type}; +use fe_analyzer::namespace::types::Type; use fe_parser::ast as fe; use fe_parser::node::Node; use yultsur::*; @@ -128,23 +129,23 @@ fn revert(context: &mut Context, stmt: &Node) -> yul::Statement { .get_expression(error_expr) .expect("missing expression"); - if let Type::Struct(val) = &error_attributes.typ { - context.revert_errors.insert(val.clone()); + if let Type::Struct(_struct) = &error_attributes.typ { + context.revert_errors.insert(_struct.clone()); - let revert_data = expressions::expr(context, error_expr); - let size = abi_operations::encoding_size(&[val.clone()], vec![revert_data.clone()]); - let revert_fn = names::revert_name(&val.name, &val.get_field_types()); - - return statement! { - ([revert_fn]([revert_data], [size])) - }; + revert_operations::revert( + &_struct.name, + &AbiType::from(_struct), + expressions::expr(context, error_expr), + ) + } else { + panic!("trying to revert with non-struct expression") } + } else { + statement! { revert(0, 0) } } - - return statement! { revert(0, 0) }; + } else { + unreachable!() } - - unreachable!() } fn emit(context: &mut Context, stmt: &Node) -> yul::Statement { @@ -168,7 +169,7 @@ fn emit(context: &mut Context, stmt: &Node) -> yul::Statement { fn assert(context: &mut Context, stmt: &Node) -> yul::Statement { if let fe::FuncStmt::Assert { test, msg } = &stmt.kind { let test = expressions::expr(context, test); - return match msg { + match msg { Some(val) => { let msg = expressions::expr(context, val); let msg_attributes = context @@ -176,27 +177,29 @@ fn assert(context: &mut Context, stmt: &Node) -> yul::Statement { .get_expression(val) .expect("missing expression"); - if let Type::String(str) = &msg_attributes.typ { - let size = abi_operations::encoding_size(&[str.clone()], vec![msg.clone()]); - let fixed_size = FixedSize::String(str.clone()); - context.assert_strings.insert(str.clone()); - let revert_fn = names::error_revert_name(&[fixed_size]); + if let Type::String(string) = &msg_attributes.typ { + context.assert_strings.insert(string.to_owned()); - return statement! { + statement! { if (iszero([test])) { - ([revert_fn]([msg], [size])) + [revert_operations::error_revert(&AbiType::from(string), msg)] } - }; + } + } else { + unreachable!() } - unreachable!() } None => { - statement! { if (iszero([test])) { (revert_with_panic([literal_expression! {(PANIC_FAILED_ASSERTION)}])) } } + statement! { + if (iszero([test])) { + [revert_operations::panic_revert(PANIC_FAILED_ASSERTION)] + } + } } - }; + } + } else { + unreachable!() } - - unreachable!() } fn break_statement(_context: &mut Context, stmt: &Node) -> yul::Statement { diff --git a/crates/yulgen/src/names/abi.rs b/crates/yulgen/src/names/abi.rs index a2403007b2..58fb160718 100644 --- a/crates/yulgen/src/names/abi.rs +++ b/crates/yulgen/src/names/abi.rs @@ -1,17 +1,17 @@ -use fe_analyzer::namespace::types::{abi_types, AbiDecodeLocation, AbiEncoding, AbiType}; +use crate::types::{AbiDecodeLocation, AbiType}; use yultsur::*; /// Generates an ABI encoding function name for a given set of types. -pub fn encode(_types: &[T]) -> yul::Identifier { - let name = format!("abi_encode_{}", types(&abi_types(_types))); +pub fn encode(_types: &[AbiType]) -> yul::Identifier { + let name = format!("abi_encode_{}", types(_types)); identifier! { (name) } } -pub fn decode_data(_types: &[T], location: AbiDecodeLocation) -> yul::Identifier { +pub fn decode_data(_types: &[AbiType], location: AbiDecodeLocation) -> yul::Identifier { let name = format!( "abi_decode_data_{}_{}", - types(&abi_types(_types)), + types(_types), decode_location(location) ); @@ -123,7 +123,7 @@ pub fn vals(prefix: &str, n: usize) -> (Vec, Vec String { +pub fn typ(_typ: &AbiType) -> String { match _typ { AbiType::Uint { size } => format!("uint{}", size * 8), AbiType::Int { size } => format!("int{}", size * 8), @@ -136,7 +136,7 @@ fn typ(_typ: &AbiType) -> String { } } -fn types(types: &[AbiType]) -> String { +pub fn types(types: &[AbiType]) -> String { types.iter().map(typ).collect::>().join("_") } diff --git a/crates/yulgen/src/names/mod.rs b/crates/yulgen/src/names/mod.rs index 6b89636ea5..43858d9045 100644 --- a/crates/yulgen/src/names/mod.rs +++ b/crates/yulgen/src/names/mod.rs @@ -1,5 +1,6 @@ -use fe_abi::utils as abi_utils; -use fe_analyzer::namespace::types::{AbiEncoding, Integer, SafeNames}; +use crate::names::abi as abi_names; +use crate::types::AbiType; +use fe_analyzer::namespace::types::Integer; use yultsur::*; pub mod abi; @@ -62,26 +63,9 @@ pub fn var_name(name: &str) -> yul::Identifier { identifier! { (format!("${}", name)) } } -/// Generate a revert function name for the name `Error` and a given set of types -pub fn error_revert_name(types: &[T]) -> yul::Identifier { - revert_name("Error", types) -} - /// Generates a revert function name for a given name and types -pub fn revert_name(name: &str, types: &[T]) -> yul::Identifier { - let type_names = types - .iter() - .map(|param| param.lower_snake()) - .collect::>(); - - let abi_names = types - .iter() - .map(|param| param.abi_selector_name()) - .collect::>(); - - let selector = abi_utils::func_selector(name, &abi_names); - - let name = format!("revert_with_{}_{}", selector, &type_names.join("_")); +pub fn revert(name: &str, typ: &AbiType) -> yul::Identifier { + let name = format!("revert_with_{}_{}", name, abi_names::typ(typ)); identifier! { (name) } } diff --git a/crates/yulgen/src/operations/abi.rs b/crates/yulgen/src/operations/abi.rs index 98db6db1be..695b4c2c65 100644 --- a/crates/yulgen/src/operations/abi.rs +++ b/crates/yulgen/src/operations/abi.rs @@ -1,7 +1,7 @@ use crate::names::abi as abi_names; use crate::operations::data as data_operations; +use crate::types::{AbiDecodeLocation, AbiType}; use crate::utils::ceil_32; -use fe_analyzer::namespace::types::{AbiDecodeLocation, AbiEncoding, AbiType}; use yultsur::*; /// The size of an encoding known at compile-time. @@ -17,7 +17,7 @@ pub enum EncodingSize { /// Returns an expression that encodes the given values and returns a pointer to /// the encoding. -pub fn encode(types: &[T], vals: Vec) -> yul::Expression { +pub fn encode(types: &[AbiType], vals: Vec) -> yul::Expression { let func_name = abi_names::encode(&types); expression! { [func_name]([vals...]) } } @@ -25,7 +25,7 @@ pub fn encode(types: &[T], vals: Vec) -> yul::E /// Returns an expression that gives size of the encoded values. /// /// It will sum up the sizes known at compile-time with the sizes known during runtime. -pub fn encoding_size(types: &[T], vals: Vec) -> yul::Expression { +pub fn encoding_size(types: &[AbiType], vals: Vec) -> yul::Expression { let mut head_size = 0; let mut known_data_size = 0; let mut unknown_data_size = vec![]; @@ -33,14 +33,13 @@ pub fn encoding_size(types: &[T], vals: Vec) -> let typed_vals = types.iter().zip(vals); for (typ, val) in typed_vals { - let abi_type = typ.abi_type(); - head_size += abi_type.head_size(); - match abi_type { + head_size += typ.head_size(); + match typ { AbiType::String { .. } => { known_data_size += 32; unknown_data_size.push(expression! { ceil32((mload([val]))) }) } - AbiType::Bytes { size } => known_data_size += 32 + ceil_32(size), + AbiType::Bytes { size } => known_data_size += 32 + ceil_32(*size), _ => {} } } @@ -50,23 +49,23 @@ pub fn encoding_size(types: &[T], vals: Vec) -> } /// Returns an expression that gives the size of the encoding's head. -pub fn encoding_head_size(types: &[T]) -> yul::Expression { - literal_expression! { (types.iter().map(|typ| typ.abi_type().head_size()).sum::()) } +pub fn encoding_head_size(types: &[AbiType]) -> yul::Expression { + literal_expression! { (types.iter().map(|typ| typ.head_size()).sum::()) } } /// Returns the known-at-compile-time encoding size. -pub fn encoding_known_size(types: &[T]) -> EncodingSize { +pub fn encoding_known_size(types: &[AbiType]) -> EncodingSize { let (min, max) = types.iter().fold((0, 0), |(mut min, mut max), typ| { - min += typ.abi_type().head_size(); - max += typ.abi_type().head_size(); + min += typ.head_size(); + max += typ.head_size(); - match typ.abi_type() { + match typ { AbiType::String { max_size } => { min += 32; - max += ceil_32(max_size) + 32; + max += ceil_32(*max_size) + 32; } AbiType::Bytes { size } => { - let size = ceil_32(size) + 32; + let size = ceil_32(*size) + 32; min += size; max += size; } @@ -87,8 +86,8 @@ pub fn encoding_known_size(types: &[T]) -> EncodingSize { } /// Decode a segment of memory and return each decoded component as separate values. -pub fn decode_data( - types: &[T], +pub fn decode_data( + types: &[AbiType], head_start: yul::Expression, data_end: yul::Expression, location: AbiDecodeLocation, diff --git a/crates/yulgen/src/operations/data.rs b/crates/yulgen/src/operations/data.rs index 7b74c1eb04..8f5fa2f65c 100644 --- a/crates/yulgen/src/operations/data.rs +++ b/crates/yulgen/src/operations/data.rs @@ -1,34 +1,43 @@ use crate::operations::abi as abi_operations; +use crate::types::{to_abi_selector_names, to_abi_types, EvmSized}; use fe_analyzer::namespace::events::EventDef; -use fe_analyzer::namespace::types::{Array, FeSized, FixedSize}; +use fe_analyzer::namespace::types::{Array, FixedSize}; use yultsur::*; /// Loads a value of the given type from storage. -pub fn sload(typ: T, sptr: yul::Expression) -> yul::Expression { +pub fn sload(typ: T, sptr: yul::Expression) -> yul::Expression { let size = literal_expression! { (typ.size()) }; expression! { bytes_sloadn([sptr], [size]) } } /// Stores a value of the given type in storage. -pub fn sstore(typ: T, sptr: yul::Expression, value: yul::Expression) -> yul::Statement { +pub fn sstore( + typ: T, + sptr: yul::Expression, + value: yul::Expression, +) -> yul::Statement { let size = literal_expression! { (typ.size()) }; statement! { bytes_sstoren([sptr], [size], [value]) } } /// Loads a value of the given type from memory. -pub fn mload(typ: T, mptr: yul::Expression) -> yul::Expression { +pub fn mload(typ: T, mptr: yul::Expression) -> yul::Expression { let size = literal_expression! { (typ.size()) }; expression! { mloadn([mptr], [size]) } } /// Stores a value of the given type in memory. -pub fn mstore(typ: T, mptr: yul::Expression, value: yul::Expression) -> yul::Statement { +pub fn mstore( + typ: T, + mptr: yul::Expression, + value: yul::Expression, +) -> yul::Statement { let size = literal_expression! { (typ.size()) }; statement! { mstoren([mptr], [size], [value]) } } /// Copies a segment of memory into storage. -pub fn mcopys(typ: T, sptr: yul::Expression, mptr: yul::Expression) -> yul::Statement { +pub fn mcopys(typ: T, sptr: yul::Expression, mptr: yul::Expression) -> yul::Statement { let size = literal_expression! { (typ.size()) }; let word_ptr = expression! { div([sptr], 32) }; statement! { mcopys([mptr], [word_ptr], [size]) } @@ -37,14 +46,14 @@ pub fn mcopys(typ: T, sptr: yul::Expression, mptr: yul::Expression) /// Copies a segment of storage into memory. /// /// Returns the address of the data in memory. -pub fn scopym(typ: T, sptr: yul::Expression) -> yul::Expression { +pub fn scopym(typ: T, sptr: yul::Expression) -> yul::Expression { let size = literal_expression! { (typ.size()) }; let word_ptr = expression! { div([sptr], 32) }; expression! { scopym([word_ptr], [size]) } } /// Copies a segment of storage to another segment of storage. -pub fn scopys( +pub fn scopys( typ: T, dest_ptr: yul::Expression, origin_ptr: yul::Expression, @@ -56,14 +65,19 @@ pub fn scopys( } /// Copies a segment of memory to another segment of memory. -pub fn mcopym(typ: T, ptr: yul::Expression) -> yul::Expression { +pub fn mcopym(typ: T, ptr: yul::Expression) -> yul::Expression { let size = literal_expression! { (typ.size()) }; expression! { mcopym([ptr], [size]) } } /// Logs an event. pub fn emit_event(event: EventDef, vals: Vec) -> yul::Statement { - let mut topics = vec![literal_expression! { (event.topic) }]; + // the first topic is the hash of the event signature + let topic_0 = fe_abi::utils::event_topic( + &event.name, + &to_abi_selector_names(&event.all_field_types()), + ); + let mut topics = vec![literal_expression! { (topic_0) }]; let (field_vals, field_types): (Vec, Vec) = event .non_indexed_field_types_with_index() @@ -78,8 +92,8 @@ pub fn emit_event(event: EventDef, vals: Vec) -> yul::Statement .map(|(index, typ)| (vals[index].to_owned(), typ)) .unzip(); - let encoding = abi_operations::encode(&field_types, field_vals); - let encoding_size = abi_operations::encoding_size(&field_types, vals); + let encoding = abi_operations::encode(&to_abi_types(&field_types), field_vals); + let encoding_size = abi_operations::encoding_size(&to_abi_types(&field_types), vals); // for now we assume these are all base type values and therefore do not need to // be hashed diff --git a/crates/yulgen/src/operations/mod.rs b/crates/yulgen/src/operations/mod.rs index 68dba84695..2b80b29af2 100644 --- a/crates/yulgen/src/operations/mod.rs +++ b/crates/yulgen/src/operations/mod.rs @@ -1,4 +1,5 @@ pub mod abi; pub mod contracts; pub mod data; +pub mod revert; pub mod structs; diff --git a/crates/yulgen/src/operations/revert.rs b/crates/yulgen/src/operations/revert.rs new file mode 100644 index 0000000000..722600cd1d --- /dev/null +++ b/crates/yulgen/src/operations/revert.rs @@ -0,0 +1,21 @@ +use crate::names; +use crate::types::AbiType; +use yultsur::*; + +// this is more of an assert operation +pub fn error_revert(typ: &AbiType, msg: yul::Expression) -> yul::Statement { + revert("Error", typ, msg) +} + +pub fn panic_revert(val: usize) -> yul::Statement { + revert( + "Panic", + &AbiType::Uint { size: 32 }, + literal_expression! { (val) }, + ) +} + +pub fn revert(name: &str, typ: &AbiType, val: yul::Expression) -> yul::Statement { + let func_name = names::revert(name, typ); + statement! { [func_name]([val]) } +} diff --git a/crates/yulgen/src/runtime/abi_dispatcher.rs b/crates/yulgen/src/runtime/abi_dispatcher.rs index c8fc827abe..35e2efcdb7 100644 --- a/crates/yulgen/src/runtime/abi_dispatcher.rs +++ b/crates/yulgen/src/runtime/abi_dispatcher.rs @@ -1,8 +1,8 @@ use crate::names::abi as abi_names; use crate::operations::abi as abi_operations; +use crate::types::{to_abi_types, AbiDecodeLocation, AbiType}; use fe_abi::utils as abi_utils; use fe_analyzer::context::FunctionAttributes; -use fe_analyzer::namespace::types::{AbiDecodeLocation, AbiEncoding, FixedSize}; use yultsur::*; /// Builds a switch statement that dispatches calls to the contract. @@ -24,7 +24,7 @@ pub fn dispatcher(attributes: &[FunctionAttributes]) -> yul::Statement { } fn dispatch_arm(attributes: FunctionAttributes) -> yul::Case { - let selector = selector(&attributes.name, &attributes.param_types()); + let selector = selector(&attributes.name, &to_abi_types(&attributes.param_types())); let (param_idents, param_exprs) = abi_names::vals("call", attributes.params.len()); @@ -33,7 +33,7 @@ fn dispatch_arm(attributes: FunctionAttributes) -> yul::Case { statements! {} } else { let decode_expr = abi_operations::decode_data( - &attributes.param_types(), + &to_abi_types(&attributes.param_types()), expression! { 4 }, expression! { calldatasize() }, AbiDecodeLocation::Calldata, @@ -53,11 +53,11 @@ fn dispatch_arm(attributes: FunctionAttributes) -> yul::Case { } } else { let encode_expr = abi_operations::encode( - &[attributes.return_type.clone()], + &[AbiType::from(&attributes.return_type)], expressions! { return_val }, ); let encoding_size = abi_operations::encoding_size( - &[attributes.return_type], + &[AbiType::from(&attributes.return_type)], expressions! { return_val }, ); statements! { @@ -77,10 +77,10 @@ fn dispatch_arm(attributes: FunctionAttributes) -> yul::Case { } } -fn selector(name: &str, params: &[FixedSize]) -> yul::Literal { +fn selector(name: &str, params: &[AbiType]) -> yul::Literal { let params = params .iter() - .map(|param| param.abi_selector_name()) + .map(|param| param.selector_name()) .collect::>(); literal! { (abi_utils::func_selector(name, ¶ms)) } @@ -89,7 +89,7 @@ fn selector(name: &str, params: &[FixedSize]) -> yul::Literal { #[cfg(test)] mod tests { use crate::runtime::abi_dispatcher::selector; - use fe_analyzer::namespace::types::{FixedSize, U256}; + use crate::types::AbiType; #[test] fn test_selector_literal_basic() { @@ -99,7 +99,7 @@ mod tests { #[test] fn test_selector_literal() { assert_eq!( - selector("bar", &[FixedSize::Base(U256)]).to_string(), + selector("bar", &[AbiType::Uint { size: 32 }]).to_string(), String::from("0x0423a132"), ) } diff --git a/crates/yulgen/src/runtime/functions/abi.rs b/crates/yulgen/src/runtime/functions/abi.rs index 08868d3686..a59a5c09a4 100644 --- a/crates/yulgen/src/runtime/functions/abi.rs +++ b/crates/yulgen/src/runtime/functions/abi.rs @@ -2,19 +2,25 @@ use crate::constants::PANIC_INVALID_ABI_DATA; use crate::names::abi as abi_names; use crate::operations::abi as abi_operations; use crate::operations::abi::EncodingSize; +use crate::operations::revert as revert_operations; +use crate::types::{AbiDecodeLocation, AbiType}; use crate::utils::ceil_32; -use fe_analyzer::namespace::types::{AbiDecodeLocation, AbiEncoding, AbiType}; use yultsur::*; /// Return all abi runtime functions pub fn all() -> Vec { - vec![unpack(), is_left_padded(), is_right_padded()] + vec![ + unpack(), + is_left_padded(), + is_right_padded(), + encode(vec![AbiType::Uint { size: 32 }]), + ] } /// Creates a batch of encoding function for the given type arrays. /// /// It sorts the functions and removes duplicates. -pub fn batch_encode(batch: Vec>) -> Vec { +pub fn batch_encode(batch: Vec>) -> Vec { let mut yul_functions: Vec<_> = batch.into_iter().map(encode).collect(); yul_functions.sort(); yul_functions.dedup(); @@ -25,9 +31,7 @@ pub fn batch_encode(batch: Vec>) -> Vec { /// locations. /// /// It sorts the functions and removes duplicates. -pub fn batch_decode( - data_batch: Vec<(Vec, AbiDecodeLocation)>, -) -> Vec { +pub fn batch_decode(data_batch: Vec<(Vec, AbiDecodeLocation)>) -> Vec { let component_batch = data_batch .iter() .fold(vec![], |mut accum, (types, location)| { @@ -44,8 +48,9 @@ pub fn batch_decode( let component_functions: Vec<_> = component_batch .into_iter() .map(|(typ, location)| { - let top_function = decode_component(&typ.abi_type(), location); - let inner_functions = match &typ.abi_type() { + let top_function = decode_component(&typ, location); + + let inner_functions = match &typ { AbiType::Tuple { components } => components .iter() .map(|typ| decode_component(typ, location)) @@ -66,7 +71,7 @@ pub fn batch_decode( } /// Creates a function that decodes ABI encoded data. -pub fn decode_data(types: &[T], location: AbiDecodeLocation) -> yul::Statement { +pub fn decode_data(types: &[AbiType], location: AbiDecodeLocation) -> yul::Statement { #[derive(Clone)] struct IdentExpr { ident: yul::Identifier, @@ -103,7 +108,6 @@ pub fn decode_data(types: &[T], location: AbiDecodeLocation) -> .iter() .enumerate() .map(|(i, typ)| { - let typ = typ.abi_type(); let data_offsets = if typ.has_data() { Some(DataOffsets { start: format!("data_start_offset_{}", i).into(), @@ -114,7 +118,7 @@ pub fn decode_data(types: &[T], location: AbiDecodeLocation) -> }; DecodeVal { - typ, + typ: typ.to_owned(), return_val: format!("return_val_{}", i).into(), decoded_val: format!("decoded_val_{}", i).into(), head_offset: format!("head_offset_{}", i).into(), @@ -448,9 +452,7 @@ pub fn is_right_padded() -> yul::Statement { } fn revert_with_invalid_abi_data() -> yul::Statement { - statement!(revert_with_panic([ - literal_expression! { (PANIC_INVALID_ABI_DATA) } - ])) + revert_operations::panic_revert(PANIC_INVALID_ABI_DATA) } /// Reverts if the value is not left padded with the given number of bits. @@ -519,7 +521,7 @@ pub fn unpack() -> yul::Statement { } /// Generates an encoding function for any set of type parameters. -pub fn encode(types: Vec) -> yul::Statement { +pub fn encode(types: Vec) -> yul::Statement { let func_name = abi_names::encode(&types); // Create names for each of the values we're encoding. @@ -530,24 +532,24 @@ pub fn encode(types: Vec) -> yul::Statement { let head_encode_stmts: Vec<_> = typed_params .clone() .into_iter() - .map(|(typ, param)| match typ.abi_type() { - AbiType::StaticArray { inner, size } => encode_static_array(param, *inner, size), + .map(|(typ, param)| match typ { + AbiType::StaticArray { inner, size } => encode_static_array(param, inner, *size), AbiType::Tuple { components } => encode_tuple(param, components), AbiType::Uint { .. } => encode_uint(param), AbiType::Int { .. } => encode_uint(param), AbiType::Bool => encode_uint(param), AbiType::Address => encode_uint(param), AbiType::String { .. } => encode_string_head(param), - AbiType::Bytes { size } => encode_bytes_head(size), + AbiType::Bytes { size } => encode_bytes_head(*size), }) .collect(); // Encode the data section of each component with dynamically-sized data. let data_encode_stmts: Vec<_> = typed_params .into_iter() - .filter_map(|(typ, param)| match typ.abi_type() { + .filter_map(|(typ, param)| match typ { AbiType::String { .. } => Some(encode_string_data(param)), - AbiType::Bytes { size } => Some(encode_bytes_data(size, param)), + AbiType::Bytes { size } => Some(encode_bytes_data(*size, param)), _ => None, }) .collect(); @@ -564,8 +566,8 @@ pub fn encode(types: Vec) -> yul::Statement { } } -fn encode_tuple(val: yul::Expression, elems: Vec) -> yul::Statement { - let tuple_size = elems.len() * 32; +fn encode_tuple(val: yul::Expression, components: &[AbiType]) -> yul::Statement { + let tuple_size = components.len() * 32; let tuple_size = literal_expression! { (tuple_size) }; statement! { pop((mcopym([val], [tuple_size]))) } } @@ -614,7 +616,7 @@ fn encode_bytes_data(size: usize, ptr: yul::Expression) -> yul::Statement { } } -fn encode_static_array(val: yul::Expression, inner: AbiType, size: usize) -> yul::Statement { +fn encode_static_array(val: yul::Expression, inner: &AbiType, size: usize) -> yul::Statement { abi_operations::unpack( val, literal_expression! { (size) }, diff --git a/crates/yulgen/src/runtime/functions/contracts.rs b/crates/yulgen/src/runtime/functions/contracts.rs index 896fa3af2e..cef98ffe1e 100644 --- a/crates/yulgen/src/runtime/functions/contracts.rs +++ b/crates/yulgen/src/runtime/functions/contracts.rs @@ -1,9 +1,9 @@ use crate::names; use crate::names::abi as abi_names; use crate::operations::abi as abi_operations; +use crate::types::{to_abi_types, AbiDecodeLocation}; use fe_abi::utils as abi_utils; use fe_analyzer::namespace::types::Contract; -use fe_analyzer::namespace::types::{AbiDecodeLocation, AbiEncoding}; use yultsur::*; /// Return all contacts runtime functions @@ -21,10 +21,9 @@ pub fn calls(contract: Contract) -> Vec { .map(|function| { // get the name of the call function and its parameters let function_name = names::contract_call(&contract_name, &function.name); - let param_names = function - .param_types() + let param_names = to_abi_types(&function.param_types()) .iter() - .map(|typ| typ.abi_selector_name()) + .map(|typ| typ.selector_name()) .collect::>(); // create a pair of identifiers and expressions for the parameters @@ -36,9 +35,10 @@ pub fn calls(contract: Contract) -> Vec { }; // the operations used to encode the parameters let encoding_operation = - abi_operations::encode(&function.param_types(), param_exprs.clone()); + abi_operations::encode(&to_abi_types(&function.param_types()), param_exprs.clone()); // the size of the encoded data - let encoding_size = abi_operations::encoding_size(&function.param_types(), param_exprs); + let encoding_size = + abi_operations::encoding_size(&to_abi_types(&function.param_types()), param_exprs); if function.return_type.is_unit() { // there is no return data to handle @@ -52,7 +52,7 @@ pub fn calls(contract: Contract) -> Vec { } } else { let decoding_operation = abi_operations::decode_data( - &[function.return_type], + &to_abi_types(&[function.return_type]), expression! { outstart }, expression! { add(outstart, outsize) }, AbiDecodeLocation::Memory, diff --git a/crates/yulgen/src/runtime/functions/math.rs b/crates/yulgen/src/runtime/functions/math.rs index 77e302d627..917279beef 100644 --- a/crates/yulgen/src/runtime/functions/math.rs +++ b/crates/yulgen/src/runtime/functions/math.rs @@ -1,5 +1,6 @@ use crate::constants::{numeric_min_max, PANIC_DIV_OR_MOD_BY_ZERO, PANIC_OVER_OR_UNDERFLOW}; use crate::names; +use crate::operations::revert as revert_operations; use fe_analyzer::namespace::types::Integer; use yultsur::*; @@ -110,15 +111,11 @@ pub fn all() -> Vec { } fn revert_with_over_or_under_flow() -> yul::Statement { - statement!(revert_with_panic([ - literal_expression! {(PANIC_OVER_OR_UNDERFLOW)} - ])) + revert_operations::panic_revert(PANIC_OVER_OR_UNDERFLOW) } fn revert_with_div_or_mod_by_zero() -> yul::Statement { - statement!(revert_with_panic([ - literal_expression! {(PANIC_DIV_OR_MOD_BY_ZERO)} - ])) + revert_operations::panic_revert(PANIC_DIV_OR_MOD_BY_ZERO) } fn checked_mod_unsigned() -> yul::Statement { diff --git a/crates/yulgen/src/runtime/functions/revert.rs b/crates/yulgen/src/runtime/functions/revert.rs index 297e2bb227..ea3cf82f8f 100644 --- a/crates/yulgen/src/runtime/functions/revert.rs +++ b/crates/yulgen/src/runtime/functions/revert.rs @@ -1,67 +1,47 @@ use crate::names; -use crate::names::abi as abi_names; -use fe_abi::utils as abi_utils; -use fe_analyzer::namespace::types::{AbiEncoding, FixedSize, Struct, U256}; +use crate::operations::abi as abi_operations; +use crate::types::{to_abi_selector_names, AbiType}; use yultsur::*; -fn selector(name: &str, params: &[FixedSize]) -> yul::Expression { - let params = params - .iter() - .map(|param| param.abi_selector_name()) - .collect::>(); - - literal_expression! {(abi_utils::func_selector(name, ¶ms))} -} - /// Generate a YUL function to revert with the `Error` signature and the /// given set of params. /// NOTE: This is currently used for `assert False, "message"` statements which are /// encoded as `Error(msg="message")`. This will be removed in the future. -pub fn generate_revert_fn_for_assert(params: &[FixedSize]) -> yul::Statement { - generate_revert_fn("Error", params, params) -} - -/// Generate a YUL function to revert with a specific struct used as error data -pub fn generate_struct_revert(val: &Struct) -> yul::Statement { - let struct_fields = val.get_field_types(); - generate_revert_fn(&val.name, &[FixedSize::Struct(val.clone())], &struct_fields) +pub fn error_revert(typ: &AbiType) -> yul::Statement { + revert("Error", typ) } /// Generate a YUL function to revert with panic codes -pub fn generate_revert_fn_for_panic() -> yul::Statement { - let selector = selector("Panic", &[FixedSize::Base(U256)]); - - return function_definition! { - function revert_with_panic(error_code) { - (let ptr := alloc_mstoren([selector], 4)) - (pop((alloc_mstoren(error_code, 32)))) - (revert(ptr, (add(4, 32)))) - } - }; +pub fn panic_revert() -> yul::Statement { + revert("Panic", &AbiType::Uint { size: 32 }) } /// Generate a YUL function to revert with data -pub fn generate_revert_fn( - name: &str, - encoding_params: &[FixedSize], - selector_params: &[FixedSize], -) -> yul::Statement { - let abi_encode_fn = abi_names::encode(encoding_params); - - let function_name = names::revert_name(name, selector_params); - - let selector = selector(name, &selector_params); +pub fn revert(name: &str, typ: &AbiType) -> yul::Statement { + let func_name = names::revert(name, typ); + // the selector parens around a tuple are removed for the selector preimage + // e.g. we use `MyError(bool, address)` instead of `MyError(bool, address)` + let selector = { + let selector_params = match typ.clone() { + AbiType::Tuple { components } => components, + typ => vec![typ], + }; + let selector = fe_abi::utils::func_selector(name, &to_abi_selector_names(&selector_params)); + literal_expression! { (selector) } + }; + let encode_val = abi_operations::encode(&[typ.to_owned()], vec![expression! { val }]); + let encoding_size = abi_operations::encoding_size(&[typ.to_owned()], vec![expression! { val }]); - return function_definition! { - function [function_name](data_ptr, size) { + function_definition! { + function [func_name](val) { (let ptr := alloc_mstoren([selector], 4)) - (pop(([abi_encode_fn](data_ptr)))) - (revert(ptr, (add(4, size)))) + (pop([encode_val])) + (revert(ptr, (add(4, [encoding_size])))) } - }; + } } /// Return all revert runtime functions pub fn all() -> Vec { - vec![generate_revert_fn_for_panic()] + vec![panic_revert()] } diff --git a/crates/yulgen/src/runtime/functions/structs.rs b/crates/yulgen/src/runtime/functions/structs.rs index 2c6b10eb40..0bbf7e8f34 100644 --- a/crates/yulgen/src/runtime/functions/structs.rs +++ b/crates/yulgen/src/runtime/functions/structs.rs @@ -1,5 +1,6 @@ use crate::names; -use fe_analyzer::namespace::types::{FeSized, Struct}; +use crate::types::EvmSized; +use fe_analyzer::namespace::types::Struct; use yultsur::*; /// Generate a YUL function that can be used to create an instance of diff --git a/crates/yulgen/src/runtime/mod.rs b/crates/yulgen/src/runtime/mod.rs index 9e301af2f8..85da21c0c4 100644 --- a/crates/yulgen/src/runtime/mod.rs +++ b/crates/yulgen/src/runtime/mod.rs @@ -1,8 +1,9 @@ pub mod abi_dispatcher; pub mod functions; +use crate::types::{to_abi_types, AbiDecodeLocation, AbiType}; use crate::Context; use fe_analyzer::context::FunctionAttributes; -use fe_analyzer::namespace::types::{AbiDecodeLocation, Contract, FixedSize}; +use fe_analyzer::namespace::types::Contract; use fe_parser::ast as fe; use fe_parser::node::Node; use yultsur::*; @@ -20,40 +21,40 @@ pub fn build(context: &Context, contract: &Node) -> Vec>(); let events_batch = attributes .events .iter() - .map(|event| event.non_indexed_field_types()) + .map(|event| to_abi_types(&event.non_indexed_field_types())) .collect::>(); let contracts_batch = external_functions .clone() .into_iter() - .map(|function| function.param_types()) + .map(|function| to_abi_types(&function.param_types())) .collect(); let assert_strings_batch = context .assert_strings - .clone() - .into_iter() - .map(|val| vec![val.into()]) + .iter() + .map(|val| vec![AbiType::from(val)]) .collect::>(); let revert_errors_batch = context .revert_errors .clone() .into_iter() - .map(|val| val.get_field_types()) + .map(|val| to_abi_types(&val.get_field_types())) .collect::>(); + let revert_panic_batch = vec![vec![AbiType::Uint { size: 32 }]]; + let structs_batch = attributes .structs - .clone() - .into_iter() - .map(|struct_| vec![FixedSize::Struct(struct_)]) + .iter() + .map(|struct_| vec![AbiType::from(struct_)]) .collect::>>(); let batch = [ @@ -62,6 +63,7 @@ pub fn build(context: &Context, contract: &Node) -> Vec) -> Vec) -> Vec>(); let revert_calls = context .revert_errors - .clone() - .into_iter() - .map(|val| functions::revert::generate_struct_revert(&val)) + .iter() + .map(|_struct| functions::revert::revert(&_struct.name, &AbiType::from(_struct))) .collect::>(); - return [ + let mut funcs = [ std, encoding, decoding, @@ -131,6 +143,9 @@ pub fn build(context: &Context, contract: &Node) -> Vec usize; +} + +impl EvmSized for FixedSize { + fn size(&self) -> usize { + match self { + FixedSize::Base(base) => base.size(), + FixedSize::Array(array) => array.size(), + FixedSize::Tuple(tuple) => tuple.size(), + FixedSize::String(string) => string.size(), + FixedSize::Contract(contract) => contract.size(), + FixedSize::Struct(val) => val.size(), + } + } +} + +impl EvmSized for Integer { + fn size(&self) -> usize { + match self { + Integer::U8 => 1, + Integer::U16 => 2, + Integer::U32 => 4, + Integer::U64 => 8, + Integer::U128 => 16, + Integer::U256 => 32, + Integer::I8 => 1, + Integer::I16 => 2, + Integer::I32 => 4, + Integer::I64 => 8, + Integer::I128 => 16, + Integer::I256 => 32, + } + } +} + +impl EvmSized for Base { + fn size(&self) -> usize { + match self { + Base::Numeric(integer) => integer.size(), + Base::Bool => 1, + Base::Address => 32, + Base::Unit => 0, + } + } +} + +impl EvmSized for Array { + fn size(&self) -> usize { + self.size * self.inner.size() + } +} + +impl EvmSized for Tuple { + fn size(&self) -> usize { + self.items.iter().map(|typ| typ.size()).sum() + } +} + +impl EvmSized for Struct { + fn size(&self) -> usize { + self.fields.len() * 32 + } +} + +impl EvmSized for FeString { + fn size(&self) -> usize { + self.max_size + 32 + } +} + +impl EvmSized for Contract { + fn size(&self) -> usize { + 32 + } +} + +#[derive(Clone, Debug, PartialEq, PartialOrd, Ord, Eq)] +pub enum AbiType { + StaticArray { inner: Box, size: usize }, + Tuple { components: Vec }, + Uint { size: usize }, + Int { size: usize }, + Bool, + Address, + String { max_size: usize }, + Bytes { size: usize }, +} + +#[derive(Clone, Debug, PartialEq, PartialOrd, Ord, Eq, Copy)] +pub enum AbiDecodeLocation { + Calldata, + Memory, +} + +pub fn to_abi_types<'a, T>(types: &'a [T]) -> Vec +where + &'a T: Into, +{ + types.iter().map(|typ| typ.into()).collect() +} + +pub fn to_abi_selector_names<'a, T>(types: &'a [T]) -> Vec +where + &'a T: Into, +{ + types.iter().map(|typ| typ.into().selector_name()).collect() +} + +impl AbiType { + /// The number of bytes used to encode the type's head. + pub fn head_size(&self) -> usize { + match self { + AbiType::StaticArray { size, .. } => 32 * size, + AbiType::Tuple { components } => 32 * components.len(), + AbiType::Uint { .. } => 32, + AbiType::Int { .. } => 32, + AbiType::Bool => 32, + AbiType::Address => 32, + AbiType::String { .. } => 32, + AbiType::Bytes { .. } => 32, + } + } + + /// The number of bytes used in Fe's data layout. This is used when packing and unpacking + /// arrays. + pub fn packed_size(&self) -> usize { + match *self { + AbiType::Uint { size } => size, + AbiType::Int { size } => size, + AbiType::Bool => 1, + AbiType::Address => 32, + _ => todo!("recursive encoding"), + } + } + + /// `true` if the encoded value is stored in the data section, `false` if it is not. + pub fn has_data(&self) -> bool { + match self { + AbiType::Uint { .. } => false, + AbiType::StaticArray { .. } => false, + AbiType::Tuple { .. } => false, + AbiType::Int { .. } => false, + AbiType::Bool => false, + AbiType::Address => false, + AbiType::String { .. } => true, + AbiType::Bytes { .. } => true, + } + } + + pub fn selector_name(&self) -> String { + match self { + AbiType::StaticArray { inner, size } => format!("{}[{}]", inner.selector_name(), size), + AbiType::Tuple { components } => format!( + "({})", + components + .iter() + .map(|component| component.selector_name()) + .collect::>() + .join(",") + ), + AbiType::Uint { size } => format!("uint{}", 8 * size), + AbiType::Int { size } => format!("int{}", 8 * size), + AbiType::Bool => "bool".to_string(), + AbiType::Address => "address".to_string(), + AbiType::String { .. } => "string".to_string(), + AbiType::Bytes { .. } => "bytes".to_string(), + } + } +} + +impl From<&FixedSize> for AbiType { + fn from(typ: &FixedSize) -> Self { + match typ { + FixedSize::Base(base) => base.into(), + FixedSize::Array(array) => array.into(), + FixedSize::Tuple(tuple) => tuple.into(), + FixedSize::String(string) => string.into(), + FixedSize::Contract(_) => AbiType::Address, + FixedSize::Struct(val) => val.into(), + } + } +} + +impl From<&Base> for AbiType { + fn from(typ: &Base) -> Self { + match typ { + Base::Numeric(integer) => { + let size = integer.size(); + if integer.is_signed() { + AbiType::Int { size } + } else { + AbiType::Uint { size } + } + } + Base::Address => AbiType::Address, + Base::Bool => AbiType::Bool, + Base::Unit => panic!("unit type is not abi encodable"), + } + } +} + +impl From<&Array> for AbiType { + fn from(array: &Array) -> Self { + if matches!(array.inner, Base::Numeric(Integer::U8)) { + AbiType::Bytes { size: array.size } + } else { + AbiType::StaticArray { + inner: Box::new(AbiType::from(&array.inner)), + size: array.size, + } + } + } +} + +impl From<&Struct> for AbiType { + fn from(_struct: &Struct) -> Self { + AbiType::Tuple { + components: _struct.fields.iter().map(|(_, typ)| typ.into()).collect(), + } + } +} + +impl From<&Tuple> for AbiType { + fn from(tuple: &Tuple) -> Self { + AbiType::Tuple { + components: tuple.items.iter().map(|typ| typ.into()).collect(), + } + } +} + +impl From<&FeString> for AbiType { + fn from(string: &FeString) -> Self { + AbiType::String { + max_size: string.max_size, + } + } +} + +impl From<&AbiType> for AbiType { + fn from(typ: &AbiType) -> Self { + typ.to_owned() + } +} diff --git a/crates/yulgen/tests/snapshots/yulgen__abi_decode_component_address_mem_function.snap b/crates/yulgen/tests/snapshots/yulgen__abi_decode_component_address_mem_function.snap index 1cc8a30dde..d774106ac9 100644 --- a/crates/yulgen/tests/snapshots/yulgen__abi_decode_component_address_mem_function.snap +++ b/crates/yulgen/tests/snapshots/yulgen__abi_decode_component_address_mem_function.snap @@ -6,5 +6,5 @@ expression: "abi_functions::decode_component_bool(AbiDecodeLocation::Memory)" function abi_decode_component_bool_mem(head_start, offset) -> return_val { let ptr := add(head_start, offset) return_val := mload(ptr) - if iszero(is_left_padded(255, return_val)) { revert_with_panic(153) } + if iszero(is_left_padded(255, return_val)) { revert_with_Panic_uint256(153) } } diff --git a/crates/yulgen/tests/snapshots/yulgen__abi_decode_component_bool_calldata_function.snap b/crates/yulgen/tests/snapshots/yulgen__abi_decode_component_bool_calldata_function.snap index aa7c67083f..82969cf778 100644 --- a/crates/yulgen/tests/snapshots/yulgen__abi_decode_component_bool_calldata_function.snap +++ b/crates/yulgen/tests/snapshots/yulgen__abi_decode_component_bool_calldata_function.snap @@ -6,5 +6,5 @@ expression: "abi_functions::decode_component_bool(AbiDecodeLocation::Calldata)" function abi_decode_component_bool_calldata(head_start, offset) -> return_val { let ptr := add(head_start, offset) return_val := calldataload(ptr) - if iszero(is_left_padded(255, return_val)) { revert_with_panic(153) } + if iszero(is_left_padded(255, return_val)) { revert_with_Panic_uint256(153) } } diff --git a/crates/yulgen/tests/snapshots/yulgen__abi_decode_component_bytes_26_mem_function.snap b/crates/yulgen/tests/snapshots/yulgen__abi_decode_component_bytes_26_mem_function.snap index e1ea3ac6fa..961c2e581e 100644 --- a/crates/yulgen/tests/snapshots/yulgen__abi_decode_component_bytes_26_mem_function.snap +++ b/crates/yulgen/tests/snapshots/yulgen__abi_decode_component_bytes_26_mem_function.snap @@ -8,12 +8,12 @@ function abi_decode_component_bytes_26_mem(head_start, head_offset) -> return_va data_start_offset := mload(head_ptr) let data_start := add(head_start, data_start_offset) let bytes_size := mload(data_start) - if iszero(eq(bytes_size, 26)) { revert_with_panic(153) } + if iszero(eq(bytes_size, 26)) { revert_with_Panic_uint256(153) } let data_size := add(bytes_size, 32) let padded_data_size := ceil32(data_size) data_end_offset := add(data_start_offset, padded_data_size) let end_word := mload(sub(add(head_start, data_end_offset), 32)) let padding_size_bits := mul(sub(padded_data_size, data_size), 8) - if iszero(is_right_padded(padding_size_bits, end_word)) { revert_with_panic(153) } + if iszero(is_right_padded(padding_size_bits, end_word)) { revert_with_Panic_uint256(153) } return_val := mcopym(add(data_start, 32), sub(data_size, 32)) } diff --git a/crates/yulgen/tests/snapshots/yulgen__abi_decode_component_int16_calldata_function.snap b/crates/yulgen/tests/snapshots/yulgen__abi_decode_component_int16_calldata_function.snap index 0c6fa40aaa..3a3cefd3ae 100644 --- a/crates/yulgen/tests/snapshots/yulgen__abi_decode_component_int16_calldata_function.snap +++ b/crates/yulgen/tests/snapshots/yulgen__abi_decode_component_int16_calldata_function.snap @@ -6,5 +6,5 @@ expression: "abi_functions::decode_component_int(2, AbiDecodeLocation::Calldata) function abi_decode_component_int16_calldata(head_start, offset) -> return_val { let ptr := add(head_start, offset) return_val := calldataload(ptr) - if iszero(or(iszero(shr(15, return_val)), iszero(shr(15, not(return_val))))) { revert_with_panic(153) } + if iszero(or(iszero(shr(15, return_val)), iszero(shr(15, not(return_val))))) { revert_with_Panic_uint256(153) } } diff --git a/crates/yulgen/tests/snapshots/yulgen__abi_decode_component_string_26_calldata_function.snap b/crates/yulgen/tests/snapshots/yulgen__abi_decode_component_string_26_calldata_function.snap index ef3f25e45a..8fa971a338 100644 --- a/crates/yulgen/tests/snapshots/yulgen__abi_decode_component_string_26_calldata_function.snap +++ b/crates/yulgen/tests/snapshots/yulgen__abi_decode_component_string_26_calldata_function.snap @@ -8,12 +8,12 @@ function abi_decode_component_bytes_26_calldata(head_start, head_offset) -> retu data_start_offset := calldataload(head_ptr) let data_start := add(head_start, data_start_offset) let bytes_size := calldataload(data_start) - if iszero(eq(bytes_size, 26)) { revert_with_panic(153) } + if iszero(eq(bytes_size, 26)) { revert_with_Panic_uint256(153) } let data_size := add(bytes_size, 32) let padded_data_size := ceil32(data_size) data_end_offset := add(data_start_offset, padded_data_size) let end_word := calldataload(sub(add(head_start, data_end_offset), 32)) let padding_size_bits := mul(sub(padded_data_size, data_size), 8) - if iszero(is_right_padded(padding_size_bits, end_word)) { revert_with_panic(153) } + if iszero(is_right_padded(padding_size_bits, end_word)) { revert_with_Panic_uint256(153) } return_val := ccopym(add(data_start, 32), sub(data_size, 32)) } diff --git a/crates/yulgen/tests/snapshots/yulgen__abi_decode_component_uint256_mem_function.snap b/crates/yulgen/tests/snapshots/yulgen__abi_decode_component_uint256_mem_function.snap index 8ec152c3b8..ada0552d1a 100644 --- a/crates/yulgen/tests/snapshots/yulgen__abi_decode_component_uint256_mem_function.snap +++ b/crates/yulgen/tests/snapshots/yulgen__abi_decode_component_uint256_mem_function.snap @@ -6,5 +6,5 @@ expression: "abi_functions::decode_component_uint(32, AbiDecodeLocation::Memory) function abi_decode_component_uint256_mem(head_start, offset) -> return_val { let ptr := add(head_start, offset) return_val := mload(ptr) - if iszero(is_left_padded(0, return_val)) { revert_with_panic(153) } + if iszero(is_left_padded(0, return_val)) { revert_with_Panic_uint256(153) } } diff --git a/crates/yulgen/tests/snapshots/yulgen__abi_decode_data_address_bool_mem_function.snap b/crates/yulgen/tests/snapshots/yulgen__abi_decode_data_address_bool_mem_function.snap index aeb661ab57..fe51625f57 100644 --- a/crates/yulgen/tests/snapshots/yulgen__abi_decode_data_address_bool_mem_function.snap +++ b/crates/yulgen/tests/snapshots/yulgen__abi_decode_data_address_bool_mem_function.snap @@ -1,16 +1,16 @@ --- source: crates/yulgen/tests/yulgen.rs -expression: "abi_functions::decode_data(&[Base::Bool, Base::Address],\n AbiDecodeLocation::Memory)" +expression: "abi_functions::decode_data(&[AbiType::Bool, AbiType::Address],\n AbiDecodeLocation::Memory)" --- function abi_decode_data_bool_address_mem(head_start, data_end) -> return_val_0, return_val_1 { let encoding_size := sub(data_end, head_start) - if iszero(eq(encoding_size, 64)) { revert_with_panic(153) } + if iszero(eq(encoding_size, 64)) { revert_with_Panic_uint256(153) } let head_offset_0 := 0 let head_offset_1 := 32 let decoded_val_0 := abi_decode_component_bool_mem(head_start, head_offset_0) let decoded_val_1 := abi_decode_component_address_mem(head_start, head_offset_1) - if iszero(eq(encoding_size, 64)) { revert_with_panic(153) } + if iszero(eq(encoding_size, 64)) { revert_with_Panic_uint256(153) } return_val_0 := decoded_val_0 return_val_1 := decoded_val_1 } diff --git a/crates/yulgen/tests/snapshots/yulgen__abi_decode_data_u256_bytes_string_bool_address_bytes_calldata_function.snap b/crates/yulgen/tests/snapshots/yulgen__abi_decode_data_u256_bytes_string_bool_address_bytes_calldata_function.snap index b9d8b9fc4d..ea5b939af9 100644 --- a/crates/yulgen/tests/snapshots/yulgen__abi_decode_data_u256_bytes_string_bool_address_bytes_calldata_function.snap +++ b/crates/yulgen/tests/snapshots/yulgen__abi_decode_data_u256_bytes_string_bool_address_bytes_calldata_function.snap @@ -1,11 +1,11 @@ --- source: crates/yulgen/tests/yulgen.rs -expression: "abi_functions::decode_data(&[FixedSize::u256(),\n FixedSize::Array(Array{inner:\n Base::Numeric(Integer::U8),\n size: 100,}),\n FixedSize::String(FeString{max_size: 42,}),\n FixedSize::bool(), FixedSize::address(),\n FixedSize::Array(Array{inner:\n Base::Numeric(Integer::U8),\n size: 100,})],\n AbiDecodeLocation::Calldata)" +expression: "abi_functions::decode_data(&[AbiType::Uint{size: 32,},\n AbiType::Bytes{size: 100,},\n AbiType::String{max_size: 42,}, AbiType::Bool,\n AbiType::Address, AbiType::Bytes{size: 100,}],\n AbiDecodeLocation::Calldata)" --- function abi_decode_data_uint256_bytes_100_string_42_bool_address_bytes_100_calldata(head_start, data_end) -> return_val_0, return_val_1, return_val_2, return_val_3, return_val_4, return_val_5 { let encoding_size := sub(data_end, head_start) - if or(lt(encoding_size, 544), gt(encoding_size, 608)) { revert_with_panic(153) } + if or(lt(encoding_size, 544), gt(encoding_size, 608)) { revert_with_Panic_uint256(153) } let head_offset_0 := 0 let head_offset_1 := 32 let head_offset_2 := 64 @@ -18,10 +18,10 @@ function abi_decode_data_uint256_bytes_100_string_42_bool_address_bytes_100_call let decoded_val_3 := abi_decode_component_bool_calldata(head_start, head_offset_3) let decoded_val_4 := abi_decode_component_address_calldata(head_start, head_offset_4) let decoded_val_5, data_start_offset_5, data_end_offset_5 := abi_decode_component_bytes_100_calldata(head_start, head_offset_5) - if iszero(eq(data_start_offset_1, 192)) { revert_with_panic(153) } - if iszero(eq(data_start_offset_2, data_end_offset_1)) { revert_with_panic(153) } - if iszero(eq(data_start_offset_5, data_end_offset_2)) { revert_with_panic(153) } - if iszero(eq(encoding_size, data_end_offset_5)) { revert_with_panic(153) } + if iszero(eq(data_start_offset_1, 192)) { revert_with_Panic_uint256(153) } + if iszero(eq(data_start_offset_2, data_end_offset_1)) { revert_with_Panic_uint256(153) } + if iszero(eq(data_start_offset_5, data_end_offset_2)) { revert_with_Panic_uint256(153) } + if iszero(eq(encoding_size, data_end_offset_5)) { revert_with_Panic_uint256(153) } return_val_0 := decoded_val_0 return_val_1 := decoded_val_1 return_val_2 := decoded_val_2 diff --git a/crates/yulgen/tests/snapshots/yulgen__revert_string_error.snap b/crates/yulgen/tests/snapshots/yulgen__revert_string_error.snap index b1c68f0ec1..d75993702d 100644 --- a/crates/yulgen/tests/snapshots/yulgen__revert_string_error.snap +++ b/crates/yulgen/tests/snapshots/yulgen__revert_string_error.snap @@ -1,10 +1,10 @@ --- source: crates/yulgen/tests/yulgen.rs -expression: "revert_functions::generate_revert_fn_for_assert(&[FeString{max_size:\n 3,}.into()])" +expression: "revert_functions::error_revert(&AbiType::String{max_size: 3,})" --- -function revert_with_0x08c379a0_string_3(data_ptr, size) { +function revert_with_Error_string_3(val) { let ptr := alloc_mstoren(0x08c379a0, 4) - pop(abi_encode_string_3(data_ptr)) - revert(ptr, add(4, size)) + pop(abi_encode_string_3(val)) + revert(ptr, add(4, add(64, ceil32(mload(val))))) } diff --git a/crates/yulgen/tests/yulgen.rs b/crates/yulgen/tests/yulgen.rs index 0210139b2a..5ba766365c 100644 --- a/crates/yulgen/tests/yulgen.rs +++ b/crates/yulgen/tests/yulgen.rs @@ -1,8 +1,6 @@ use fe_analyzer::context::FunctionAttributes; use fe_analyzer::namespace::events::EventDef; -use fe_analyzer::namespace::types::{ - AbiDecodeLocation, AbiType, Array, Base, FeString, FixedSize, Integer, Struct, U256, -}; +use fe_analyzer::namespace::types::{Base, FeString, FixedSize, Integer, Struct, U256}; use fe_yulgen::constructor; use fe_yulgen::names::abi as abi_names; use fe_yulgen::operations::{abi as abi_operations, data as data_operations}; @@ -10,6 +8,7 @@ use fe_yulgen::runtime::abi_dispatcher; use fe_yulgen::runtime::functions::{ abi as abi_functions, revert as revert_functions, structs as structs_functions, }; +use fe_yulgen::types::{AbiDecodeLocation, AbiType}; use insta::assert_display_snapshot; use wasm_bindgen_test::wasm_bindgen_test; use yultsur::*; @@ -66,23 +65,23 @@ test_yulgen! { abi_dispatcher, abi_dispatcher::dispatcher(&function_attributes( // ABI encoding functions test_yulgen! { abi_encode_u256_address_function, - abi_functions::encode(vec![U256, Base::Address]) + abi_functions::encode(vec![AbiType::Uint { size: 32 }, AbiType::Address]) } // ABI decoding functions test_yulgen! { abi_decode_data_address_bool_mem_function, - abi_functions::decode_data(&[Base::Bool, Base::Address], AbiDecodeLocation::Memory) + abi_functions::decode_data(&[AbiType::Bool, AbiType::Address], AbiDecodeLocation::Memory) } test_yulgen! { abi_decode_data_u256_bytes_string_bool_address_bytes_calldata_function, abi_functions::decode_data(&[ - FixedSize::u256(), - FixedSize::Array(Array { inner: Base::Numeric(Integer::U8), size: 100 }), - FixedSize::String(FeString { max_size: 42 }), - FixedSize::bool(), - FixedSize::address(), - FixedSize::Array(Array { inner: Base::Numeric(Integer::U8), size: 100 }), + AbiType::Uint { size: 32 }, + AbiType::Bytes { size: 100 }, + AbiType::String { max_size: 42 }, + AbiType::Bool, + AbiType::Address, + AbiType::Bytes { size: 100 }, ], AbiDecodeLocation::Calldata) } test_yulgen! { @@ -185,16 +184,16 @@ test_yulgen! { // ABI operations test_yulgen! { encode_u256_operation, - abi_operations::encode(&[U256], vec![expression! { 42 }]) + abi_operations::encode(&[AbiType::Uint { size: 32 }], vec![expression! { 42 }]) } test_yulgen! { encode_size_u256_operation, - abi_operations::encoding_size(&[U256], vec![expression! { 42 }]) + abi_operations::encoding_size(&[AbiType::Uint { size: 32 }], vec![expression! { 42 }]) } test_yulgen! { decode_string_calldata_operation, abi_operations::decode_data( - &[FeString { max_size: 26 }], + &[AbiType::String { max_size: 26 }], expression! { 42 }, expression! { 10 }, AbiDecodeLocation::Calldata @@ -205,21 +204,21 @@ test_yulgen! { test_yulgen! { encode_name, abi_names::encode(&[ - FixedSize::Base(U256), - FixedSize::Array(Array { - inner: Base::Numeric(Integer::U8), - size: 100 - }) + AbiType::Uint { size: 32 }, + AbiType::Bytes { size: 100 } ]) } test_yulgen! { decode_data_name_u256_calldata_name, - abi_names::decode_data(&[U256], AbiDecodeLocation::Calldata) + abi_names::decode_data(&[AbiType::Uint { size: 32 }], AbiDecodeLocation::Calldata) } test_yulgen! { decode_data_name_string_mem_name, - abi_names::decode_data(&[FeString { max_size: 42 }], AbiDecodeLocation::Memory) + abi_names::decode_data(&[AbiType::String { max_size: 42 }], AbiDecodeLocation::Memory) } // revert functions -test_yulgen! { revert_string_error, revert_functions::generate_revert_fn_for_assert(&[FeString { max_size: 3}.into()]) } +test_yulgen! { + revert_string_error, + revert_functions::error_revert(&AbiType::String { max_size: 3 }) +}