Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

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

10 changes: 5 additions & 5 deletions crates/solidity-v2/outputs/cargo/ast/src/abi/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}

Expand Down
Original file line number Diff line number Diff line change
@@ -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 {
Expand All @@ -25,8 +25,11 @@ impl EventDefinitionStruct {
}))
}

pub fn compute_selector(&self) -> Option<u32> {
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))
}
}
11 changes: 6 additions & 5 deletions crates/solidity-v2/outputs/cargo/semantic/src/built_ins/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is fine for now, but in the future we should maybe still bind but emit a diagnostic (not for this PR).

_ => None,
},
Definition::UserDefinedValueType(_) => match symbol {
Expand Down Expand Up @@ -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()),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,17 +30,25 @@ 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
.find_contract_by_name("Test")
.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);
Expand Down

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

Original file line number Diff line number Diff line change
@@ -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
───╯
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
library Utils {
event Foo(uint x) anonymous;

function test() internal pure {
Foo.selector;
}
}
Loading