Skip to content

Commit

Permalink
Fix event signature encoding (#72)
Browse files Browse the repository at this point in the history
Fixes two errors with event signature encoding:

1. The byte string resulting from the keccak hash was reversed;
2. The textual event signature mixed Rust and Solidity naming conventions and erroneously used `u256` instead of `uint256`
  • Loading branch information
virgil-serbanuta authored Feb 7, 2025
1 parent 3c87fb5 commit 15ccc63
Show file tree
Hide file tree
Showing 6 changed files with 66 additions and 13 deletions.
2 changes: 1 addition & 1 deletion tests/ulm/counter/rust/src/ulm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,7 @@ pub fn keccak_hash(api: &dyn Ulm, value: &Bytes) -> [u8; 32] {

pub fn keccak_hash_int(api: &dyn Ulm, value: &Bytes) -> U256 {
let fingerprint = keccak_hash(api, value);
U256::from_array_le(fingerprint)
U256::from_array_be(fingerprint)
}

pub fn endpoint_fingerprint(api: &dyn Ulm, value: &str) -> [u8; 4] {
Expand Down
2 changes: 1 addition & 1 deletion tests/ulm/erc20/erc20_test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ function test_name {

name=$(erc20_name $k1 $contract)
echo -n "."
assert_eq "Doge Coin" "$name" "Name"
assert_eq "Dogecoin" "$name" "Name"

echo -e " ${GREEN}passed${NC}"
}
Expand Down
10 changes: 5 additions & 5 deletions tests/ulm/erc20/rust/src/erc20.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ impl Erc20 {
let mut encoder = Encoder::new();
encoder.add(value);
log3(
&*self.api.borrow(),
"Transfer(address,address,u256)",
&mut *self.api.borrow_mut(),
"Transfer(address,address,uint256)",
&from.into(), &to.into(),
encoder.encode()
)
Expand All @@ -55,8 +55,8 @@ impl Erc20 {
let mut encoder = Encoder::new();
encoder.add(value);
log3(
&*self.api.borrow(),
"Approval(address,address,u256)",
&mut *self.api.borrow_mut(),
"Approval(address,address,uint256)",
&owner.into(), &spender.into(),
encoder.encode()
)
Expand All @@ -67,7 +67,7 @@ impl Erc20 {
pub fn init(&self) {}

pub fn name(&self) -> &str {
"Doge Coin"
"Dogecoin"
}

pub fn symbol(&self) -> &str {
Expand Down
37 changes: 36 additions & 1 deletion tests/ulm/erc20/rust/src/erc20_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ mod erc20_tests {

let erc20 = Erc20::new(api);

assert_eq!("Doge Coin", erc20.name());
assert_eq!("Dogecoin", erc20.name());
}

#[test]
Expand Down Expand Up @@ -92,6 +92,41 @@ mod erc20_tests {
assert_eq!(balance(800), erc20.balance_of(&account1));
assert_eq!(balance(200), erc20.balance_of(&account2));
assert_eq!(balance(1000), erc20.total_supply());

let api_result = api.borrow();
assert_eq!(1, api_result.log.len());
assert_eq!(3, api_result.log[0].indexed_fields.len());
assert_eq!(
vec![
18 , 77 , 182, 52 , 90 , 145, 127, 172,
177, 59 , 159, 146, 140, 132, 227, 44 ,
17 , 91 , 63 , 82 , 12 , 4 , 3 , 40 ,
230, 157, 210, 99 , 154, 105, 86 , 253,
],
api_result.log[0].indexed_fields[0]
);
assert_eq!(
vec![
123_u8, 0_u8, 0_u8, 0_u8, 0_u8, 0_u8, 0_u8, 0_u8,
0_u8, 0_u8, 0_u8, 0_u8, 0_u8, 0_u8, 0_u8, 0_u8,
0_u8, 0_u8, 0_u8, 0_u8, 0_u8, 0_u8, 0_u8, 0_u8,
0_u8, 0_u8, 0_u8, 0_u8, 0_u8, 0_u8, 0_u8, 0_u8,
],
api_result.log[0].indexed_fields[1]
);
assert_eq!(
vec![
200_u8, 1_u8, 0_u8, 0_u8, 0_u8, 0_u8, 0_u8, 0_u8,
0_u8, 0_u8, 0_u8, 0_u8, 0_u8, 0_u8, 0_u8, 0_u8,
0_u8, 0_u8, 0_u8, 0_u8, 0_u8, 0_u8, 0_u8, 0_u8,
0_u8, 0_u8, 0_u8, 0_u8, 0_u8, 0_u8, 0_u8, 0_u8,
],
api_result.log[0].indexed_fields[2]
);
let data = api_result.log[0].data.clone();
let b = data.slice(0..data.len());
let expected = b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc8";
assert_eq!(expected, &b[..])
}

#[test]
Expand Down
22 changes: 17 additions & 5 deletions tests/ulm/erc20/rust/src/ulm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ pub use mock::failWrapper;
pub use impl_::failWrapper;

pub trait Ulm {
fn log3(&self, data1: &[u8; 32], data2: &[u8; 32], data3: &[u8; 32], bytes: &[u8]);
fn log3(&mut self, data1: &[u8; 32], data2: &[u8; 32], data3: &[u8; 32], bytes: &[u8]);
fn caller(&self, result: &mut [u8; 20]);

fn call_data_length(&self) -> u32;
Expand Down Expand Up @@ -88,7 +88,7 @@ pub mod impl_ {
}

impl Ulm for UlmImpl {
fn log3(&self, data1: &[u8; 32], data2: &[u8; 32], data3: &[u8; 32], bytes: &[u8]) {
fn log3(&mut self, data1: &[u8; 32], data2: &[u8; 32], data3: &[u8; 32], bytes: &[u8]) {
unsafe { Log3(data1.as_ptr(), data2.as_ptr(), data3.as_ptr(), bytes.as_ptr(), bytes.len()); }
}
fn caller(&self, result: &mut [u8; 20]) {
Expand Down Expand Up @@ -142,10 +142,16 @@ pub mod mock {
panic!("{}", msg);
}

pub struct UlmLogEntry {
pub indexed_fields: Vec<[u8; 32]>,
pub data: Bytes,
}

pub struct UlmMock {
storage: HashMap<Bytes, Bytes>,
caller: [u8; 20],
call_data: Bytes,
pub log: Vec<UlmLogEntry>,
}

impl UlmMock {
Expand All @@ -154,6 +160,7 @@ pub mod mock {
storage: HashMap::new(),
caller: [0_u8; 20],
call_data: Bytes::new(),
log: Vec::new()
}))
}
pub fn set_caller(&mut self, caller: Address) {
Expand All @@ -163,7 +170,12 @@ pub mod mock {
}

impl Ulm for UlmMock {
fn log3(&self, _data1: &[u8; 32], _data2: &[u8; 32], _data3: &[u8; 32], _bytes: &[u8]) {}
fn log3(&mut self, data1: &[u8; 32], data2: &[u8; 32], data3: &[u8; 32], bytes: &[u8]) {
self.log.push(UlmLogEntry{
indexed_fields: vec![data1.clone(), data2.clone(), data3.clone()],
data: Bytes::copy_from_slice(bytes),
});
}

fn caller(&self, result: &mut [u8; 20]) {
*result = self.caller;
Expand Down Expand Up @@ -219,7 +231,7 @@ pub mod mock {
}
}

pub fn log3(api: &dyn Ulm, signature: &str, data2: &U256, data3: &U256, bytes: Bytes) {
pub fn log3(api: &mut dyn Ulm, signature: &str, data2: &U256, data3: &U256, bytes: Bytes) {
let signature_fingerprint = keccak_hash_int(api, &Bytes::copy_from_slice(signature.as_bytes()));
let mut data1_bytes = [0_u8; 32];
signature_fingerprint.copy_to_array_le(&mut data1_bytes);
Expand Down Expand Up @@ -278,7 +290,7 @@ pub fn keccak_hash(api: &dyn Ulm, value: &Bytes) -> [u8; 32] {

pub fn keccak_hash_int(api: &dyn Ulm, value: &Bytes) -> U256 {
let fingerprint = keccak_hash(api, value);
U256::from_array_le(fingerprint)
U256::from_array_be(fingerprint)
}

pub fn endpoint_fingerprint(api: &dyn Ulm, value: &str) -> [u8; 4] {
Expand Down
6 changes: 6 additions & 0 deletions tests/ulm/erc20/rust/src/unsigned.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,12 @@ impl<const N: usize> Unsigned<N> {
Unsigned { chunks }
}

pub fn from_array_be(chunks: [u8; N]) -> Unsigned<N> {
let r_c_v : Vec<u8> = chunks.into_iter().rev().collect();
let reverse_chunks: [u8; N] = r_c_v.try_into().unwrap();
Unsigned { chunks: reverse_chunks }
}

pub fn from_u64(value: u64) -> Unsigned<N> {
if 8 <= N {
let mut chunks = [0_u8; N];
Expand Down

0 comments on commit 15ccc63

Please sign in to comment.