diff --git a/crates/solidity-v2/outputs/cargo/ast/generated/public_api.txt b/crates/solidity-v2/outputs/cargo/ast/generated/public_api.txt index f37ca8289b..6efb1a103d 100644 --- a/crates/solidity-v2/outputs/cargo/ast/generated/public_api.txt +++ b/crates/solidity-v2/outputs/cargo/ast/generated/public_api.txt @@ -187,6 +187,7 @@ pub fn slang_solidity_v2_ast::abi::TupleComponent::fmt(&self, &mut core::fmt::Fo impl core::hash::Hash for slang_solidity_v2_ast::abi::TupleComponent pub fn slang_solidity_v2_ast::abi::TupleComponent::hash<__H: core::hash::Hasher>(&self, &mut __H) impl core::marker::StructuralPartialEq for slang_solidity_v2_ast::abi::TupleComponent +pub fn slang_solidity_v2_ast::abi::hash_from_signature(&str) -> [u8; 32] pub fn slang_solidity_v2_ast::abi::selector_from_signature(&str) -> u32 pub type slang_solidity_v2_ast::abi::AbiMutability = slang_solidity_v2_semantic::types::FunctionTypeMutability pub mod slang_solidity_v2_ast::ast @@ -1858,7 +1859,7 @@ impl slang_solidity_v2_ast::ast::EventDefinitionStruct pub fn slang_solidity_v2_ast::ast::EventDefinitionStruct::compute_abi_entry(&self) -> core::option::Option pub fn slang_solidity_v2_ast::ast::EventDefinitionStruct::compute_canonical_signature(&self) -> core::option::Option pub fn slang_solidity_v2_ast::ast::EventDefinitionStruct::compute_internal_signature(&self) -> core::option::Option -pub fn slang_solidity_v2_ast::ast::EventDefinitionStruct::compute_selector(&self) -> core::option::Option +pub fn slang_solidity_v2_ast::ast::EventDefinitionStruct::compute_topic0(&self) -> core::option::Option<[u8; 32]> impl slang_solidity_v2_ast::ast::EventDefinitionStruct pub fn slang_solidity_v2_ast::ast::EventDefinitionStruct::enclosing_definition(&self) -> core::option::Option impl slang_solidity_v2_ast::ast::EventDefinitionStruct diff --git a/crates/solidity-v2/outputs/cargo/ast/src/abi/mod.rs b/crates/solidity-v2/outputs/cargo/ast/src/abi/mod.rs index 6a9cf9fd0d..7801bccbc4 100644 --- a/crates/solidity-v2/outputs/cargo/ast/src/abi/mod.rs +++ b/crates/solidity-v2/outputs/cargo/ast/src/abi/mod.rs @@ -330,12 +330,12 @@ impl StorageItem { } } -pub fn selector_from_signature(signature: &str) -> u32 { - let mut hasher = Keccak256::new(); - hasher.update(signature.as_bytes()); - let result = hasher.finalize(); +pub fn hash_from_signature(signature: &str) -> [u8; 32] { + Keccak256::digest(signature).into() +} - let selector_bytes: [u8; 4] = result[0..4].try_into().unwrap(); +pub fn selector_from_signature(signature: &str) -> u32 { + let selector_bytes: [u8; 4] = hash_from_signature(signature)[0..4].try_into().unwrap(); u32::from_be_bytes(selector_bytes) } diff --git a/crates/solidity-v2/outputs/cargo/ast/src/abi/node_extensions/event_definition.rs b/crates/solidity-v2/outputs/cargo/ast/src/abi/node_extensions/event_definition.rs index 71d06cb531..da8988f6cb 100644 --- a/crates/solidity-v2/outputs/cargo/ast/src/abi/node_extensions/event_definition.rs +++ b/crates/solidity-v2/outputs/cargo/ast/src/abi/node_extensions/event_definition.rs @@ -1,4 +1,4 @@ -use crate::abi::{AbiEntry, AbiEvent, selector_from_signature}; +use crate::abi::{AbiEntry, AbiEvent, hash_from_signature}; use crate::ast::EventDefinitionStruct; impl EventDefinitionStruct { @@ -25,8 +25,11 @@ impl EventDefinitionStruct { })) } - pub fn compute_selector(&self) -> Option { + pub fn compute_topic0(&self) -> Option<[u8; 32]> { + if self.ir_node.is_anonymous { + return None; + } self.compute_canonical_signature() - .map(|sig| selector_from_signature(&sig)) + .map(|sig| hash_from_signature(&sig)) } } diff --git a/crates/solidity-v2/outputs/cargo/semantic/src/built_ins/mod.rs b/crates/solidity-v2/outputs/cargo/semantic/src/built_ins/mod.rs index 20ac06ffb6..0a8f8a6753 100644 --- a/crates/solidity-v2/outputs/cargo/semantic/src/built_ins/mod.rs +++ b/crates/solidity-v2/outputs/cargo/semantic/src/built_ins/mod.rs @@ -209,8 +209,8 @@ impl<'a> BuiltInsResolver<'a> { "selector" => Some(InternalBuiltIn::ErrorSelector), _ => None, }, - Definition::Event(_) => match symbol { - "selector" => Some(InternalBuiltIn::EventSelector), + Definition::Event(event) => match symbol { + "selector" if !event.ir_node.is_anonymous => Some(InternalBuiltIn::EventSelector), _ => None, }, Definition::UserDefinedValueType(_) => match symbol { @@ -381,9 +381,10 @@ impl<'a> BuiltInsResolver<'a> { InternalBuiltIn::MsgSender => Typing::Resolved(self.types.address()), InternalBuiltIn::MsgSig => Typing::Resolved(self.types.bytes4()), InternalBuiltIn::MsgValue => Typing::Resolved(self.types.uint256()), - InternalBuiltIn::ErrorSelector - | InternalBuiltIn::EventSelector - | InternalBuiltIn::FunctionSelector => Typing::Resolved(self.types.bytes4()), + InternalBuiltIn::ErrorSelector | InternalBuiltIn::FunctionSelector => { + Typing::Resolved(self.types.bytes4()) + } + InternalBuiltIn::EventSelector => Typing::Resolved(self.types.bytes32()), InternalBuiltIn::TxGasPrice => Typing::Resolved(self.types.uint256()), InternalBuiltIn::TxOrigin => Typing::Resolved(self.types.address()), InternalBuiltIn::TypeName => Typing::Resolved(self.types.string_memory()), diff --git a/crates/solidity-v2/outputs/cargo/semantic/src/passes/tests/typing.rs b/crates/solidity-v2/outputs/cargo/semantic/src/passes/tests/typing.rs index 5e4c54433c..6665a21578 100644 --- a/crates/solidity-v2/outputs/cargo/semantic/src/passes/tests/typing.rs +++ b/crates/solidity-v2/outputs/cargo/semantic/src/passes/tests/typing.rs @@ -1922,17 +1922,21 @@ fn test_storage_base_slot_evaluation() { #[test] fn test_event_selector() { - // `.selector` on an event name types as `bytes4`. + // `.selector` on an event name types as `bytes32`: the event's `topics[0]`. let (type_, _) = type_of_expression_in_context("event E(uint a);", "E.selector"); - assert_eq!(type_, Type::ByteArray(ByteArrayType { width: 4 })); + assert_eq!(type_, Type::ByteArray(ByteArrayType { width: 32 })); // With *overloaded* events the name is ambiguous; we currently resolve the // member against the first candidate (both candidates expose `selector`, - // so the typing is still `bytes4`). solc reports an ambiguity error here — + // so the typing is still `bytes32`). solc reports an ambiguity error here — // that diagnostic is part of the SDR[37] validation backlog. let (type_, _) = type_of_expression_in_context("event E(uint a); event E(bool b);", "E.selector"); - assert_eq!(type_, Type::ByteArray(ByteArrayType { width: 4 })); + assert_eq!(type_, Type::ByteArray(ByteArrayType { width: 32 })); + + // An anonymous event emits no `topics[0]`, so it exposes no `selector`. + let (type_, _) = try_type_of_expression_in_context("event E(uint a) anonymous;", "E.selector"); + assert_eq!(None, type_); } #[test] diff --git a/crates/solidity-v2/outputs/cargo/slang_solidity/src/tests/abi/selectors.rs b/crates/solidity-v2/outputs/cargo/slang_solidity/src/tests/abi/selectors.rs index 0cba5d7877..59dbf0fb2b 100644 --- a/crates/solidity-v2/outputs/cargo/slang_solidity/src/tests/abi/selectors.rs +++ b/crates/solidity-v2/outputs/cargo/slang_solidity/src/tests/abi/selectors.rs @@ -30,7 +30,7 @@ fn test_function_selector() { } #[test] -fn test_events_and_errors_selectors() { +fn test_event_topics_and_error_selectors() { let unit = super::FullAbi::build_compilation_unit(); let test_contract = unit @@ -38,9 +38,17 @@ fn test_events_and_errors_selectors() { .next() .expect("Test contract can be found"); - let events = test_contract.events(); - assert_eq!(events.len(), 1); - assert_eq!(events[0].compute_selector(), Some(0xb9b1_0fa6)); // Event(uint256,bytes) + let events = test_contract.linearised_events(); + assert_eq!(events.len(), 2); + assert_eq!(events[0].compute_topic0(), None); // BaseEvent(uint256,string) anonymous + assert_eq!( + events[1].compute_topic0(), // Event(uint256,bytes32) + Some([ + 0xb9, 0xb1, 0x0f, 0xa6, 0x33, 0x03, 0x36, 0xbe, 0xe8, 0x83, 0x55, 0x7e, 0x90, 0x6a, + 0xb0, 0xd5, 0xe9, 0x8e, 0xe5, 0x03, 0x06, 0x9e, 0x9c, 0x49, 0x68, 0x9f, 0x95, 0x02, + 0x2d, 0xb8, 0x13, 0x99, + ]) + ); let errors = test_contract.errors(); assert_eq!(errors.len(), 1); diff --git a/crates/solidity-v2/outputs/cargo/tests/src/binder_output/snapshots.generated.rs b/crates/solidity-v2/outputs/cargo/tests/src/binder_output/snapshots.generated.rs index 6afad98258..774b4cacbd 100644 --- a/crates/solidity-v2/outputs/cargo/tests/src/binder_output/snapshots.generated.rs +++ b/crates/solidity-v2/outputs/cargo/tests/src/binder_output/snapshots.generated.rs @@ -585,6 +585,11 @@ mod errors { mod events { use super::*; + #[test] + fn anonymous_selector() -> Result<()> { + run("events", "anonymous_selector") + } + #[test] fn custom_types() -> Result<()> { run("events", "custom_types") diff --git a/crates/solidity-v2/testing/snapshots/binder_output/events/anonymous_selector/generated/0.8.0-failure.txt b/crates/solidity-v2/testing/snapshots/binder_output/events/anonymous_selector/generated/0.8.0-failure.txt new file mode 100644 index 0000000000..34ee1241e4 --- /dev/null +++ b/crates/solidity-v2/testing/snapshots/binder_output/events/anonymous_selector/generated/0.8.0-failure.txt @@ -0,0 +1,41 @@ +# This file is generated automatically by infrastructure scripts. Please don't edit by hand. + +Definitions (4): +- Def: #1 ["Utils" @ input.sol:1:9] (library) +- Def: #2 ["Foo" @ input.sol:2:11] (event) +- Def: #3 ["x" @ input.sol:2:20] (parameter, type: uint256) +- Def: #4 ["test" @ input.sol:4:14] (function, type: function () returns void) + +------------------------------------------------------------------------ + +References (2): +- Ref: ["Foo" @ input.sol:5:9] -> #2 +- Ref: ["selector" @ input.sol:5:13] -> unresolved + +------------------------------------------------------------------------ + +Unbound identifiers (0): + +------------------------------------------------------------------------ + +Bindings: + ╭─[input.sol:1:1] + │ + 1 │ library Utils { + │ ──┬── + │ ╰──── name: 1 + 2 │ event Foo(uint x) anonymous; + │ ─┬─ ┬ + │ ╰────────── name: 2 + │ │ + │ ╰── name: 3 + │ + 4 │ function test() internal pure { + │ ──┬─ + │ ╰─── name: 4 + 5 │ Foo.selector; + │ ─┬─ ────┬─── + │ ╰──────────── ref: 2 + │ │ + │ ╰───── unresolved +───╯ diff --git a/crates/solidity-v2/testing/snapshots/binder_output/events/anonymous_selector/input.sol b/crates/solidity-v2/testing/snapshots/binder_output/events/anonymous_selector/input.sol new file mode 100644 index 0000000000..77d2b82088 --- /dev/null +++ b/crates/solidity-v2/testing/snapshots/binder_output/events/anonymous_selector/input.sol @@ -0,0 +1,7 @@ +library Utils { + event Foo(uint x) anonymous; + + function test() internal pure { + Foo.selector; + } +}