Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(zink-codegen): introduce derive macro for events #298

Merged
merged 24 commits into from
Dec 12, 2024
Merged
20 changes: 20 additions & 0 deletions Cargo.lock

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

26 changes: 3 additions & 23 deletions codegen/src/visitor/log.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,31 +60,11 @@ impl Function {

/// Log a message with topics.
pub fn log(&mut self, count: usize) -> Result<()> {
let mut topics = Vec::<Vec<u8>>::default();
for topic in (1..=count).rev() {
let (offset, size) = self.data()?;
let size = size as usize;
let data = self.env.data.load(offset, size)?;

tracing::debug!("log{count} topic{topic}: {:?}", data);
topics.push(data);
}

let name = {
let (offset, size) = self.data()?;
let size = size as usize;
let data = self.env.data.load(offset, size)?;

tracing::debug!("log1 name: {:?}", data);
data
};

for topic in topics {
self.masm.push(&topic)?;
}
let (offset, size) = self.data()?;
let data = self.env.data.load(offset, size as usize)?;

// 1. write data to memory
let MemoryInfo { offset, size } = self.masm.memory_write_bytes(&name)?;
let MemoryInfo { offset, size } = self.masm.memory_write_bytes(&data)?;

// 3. prepare the offset and size of the data.
self.masm.push(&size.to_ls_bytes())?;
Expand Down
269 changes: 187 additions & 82 deletions examples/log.rs
Original file line number Diff line number Diff line change
@@ -1,99 +1,204 @@
//! Addition example.
#![cfg_attr(target_arch = "wasm32", no_std)]
#![cfg_attr(target_arch = "wasm32", no_main)]

extern crate zink;

use zink::Event;
use zink::{primitives::U256, Event};

/// A `Ping` event.
#[derive(Event)]
struct Ping;

#[zink::external]
pub fn log0() {
Ping.log0();
pub enum MyEvent {
/// Event with no topics
Topic0,
/// Event with one topic
Topic1(U256),
/// Event with two topics
Topic2(U256, U256),
/// Event with three topics
Topic3(U256, U256, U256),
/// Event with four topics
Topic4(U256, U256, U256, U256),
}

#[zink::external]
pub fn log1() {
Ping.log1(b"pong");
pub mod event_tests {

use super::*;

/// Test log0
#[zink::external]
pub fn test_log0() {
unsafe { zink::ffi::evm::log0(b"MyEvent") }
}
malik672 marked this conversation as resolved.
Show resolved Hide resolved

/// Test log1
#[zink::external]
pub fn test_log1(value: U256) {
unsafe {
let topic = value.bytes32();
zink::ffi::evm::log1(topic, b"MyEvent")
}
malik672 marked this conversation as resolved.
Show resolved Hide resolved
}

/// Test log2
#[zink::external]
pub fn test_log2(value1: U256, value2: U256) {
unsafe {
let topic1 = value1.bytes32();
let topic2 = value2.bytes32();
zink::ffi::evm::log2(topic1, topic2, b"MyEvent")
}
malik672 marked this conversation as resolved.
Show resolved Hide resolved
}

/// Test log3
#[zink::external]
pub fn test_log3(value1: U256, value2: U256, value3: U256) {
unsafe {
let topic1 = value1.bytes32();
let topic2 = value2.bytes32();
let topic3 = value3.bytes32();
zink::ffi::evm::log3(topic1, topic2, topic3, b"MyEvent")
}
malik672 marked this conversation as resolved.
Show resolved Hide resolved
}

/// Test log4
#[zink::external]
pub fn test_log4(value1: U256, value2: U256, value3: U256, value4: U256) {
unsafe {
let topic1 = value1.bytes32();
let topic2 = value2.bytes32();
let topic3 = value3.bytes32();
let topic4 = value4.bytes32();

zink::ffi::evm::log4(topic1, topic2, topic3, topic4, b"MyEvent")
}
malik672 marked this conversation as resolved.
Show resolved Hide resolved
}

/// Test multiple event logs in one transaction
#[zink::external]
pub fn test_multiple_logs(value1: U256, value2: U256, value3: U256, value4: U256) {
test_log0();
test_log1(value1);
test_log2(value1, value2);
test_log3(value1, value2, value3);
test_log4(value1, value2, value3, value4);
}
}

#[zink::external]
pub fn log2() {
Ping.log2(b"pong", b"ping");
}
#[cfg(test)]
mod tests {

#[zink::external]
pub fn log3() {
Ping.log3(b"pong", b"ping", b"pong");
}
use zink::Asm;
use zint::{Bytes32, Contract};

#[zink::external]
pub fn log4() {
Ping.log4(b"pong", b"ping", b"pong", b"pong");
#[test]
fn test_events() {
let mut contract = Contract::search("log")
.unwrap()
.compile()
.expect("failed to compile");

let name = b"MyEvent";
let value1: i32 = 1;
let value2: i32 = 2;
let value3: i32 = 3;
let value4: i32 = 4;

{
// Test log0
let info = contract.execute(&[b"test_log0()".to_vec()]).unwrap();
assert!(!info.logs.is_empty());
assert_eq!(
info.logs[0].data.data.to_vec(),
name.to_vec().to_bytes32().to_vec()
);

// Test log1
let info = contract
.execute(&[b"test_log1(uint256)".to_vec(), value1.bytes32().to_vec()])
.expect("failed to execute test_log1");
assert!(!info.logs.is_empty());
assert_eq!(
info.logs[0].data.data.to_vec(),
name.to_vec().to_bytes32().to_vec()
);
assert_eq!(info.logs[0].topics()[0].to_vec(), value1.bytes32().to_vec());

// Test log2
let info = contract
.execute(&[
b"test_log2(uint256,uint256)".to_vec(),
value1.bytes32().to_vec(),
value2.bytes32().to_vec(),
])
.unwrap();
assert!(!info.logs.is_empty());
assert_eq!(info.logs[0].topics()[1].to_vec(), value1.bytes32().to_vec());
assert_eq!(
info.logs[0].topics()[0].to_vec(),
value2.bytes32().to_vec()
);

let info = contract
.execute(&[
b"test_log3(uint256,uint256,uint256)".to_vec(),
value1.bytes32().to_vec(),
value2.bytes32().to_vec(),
value3.bytes32().to_vec(),
])
.unwrap();
assert!(!info.logs.is_empty());
assert_eq!(
info.logs[0].topics()[2].to_vec(),
value1.bytes32().to_vec()
);
assert_eq!(
info.logs[0].topics()[1].to_vec(),
value2.bytes32().to_vec()
);
assert_eq!(
info.logs[0].topics()[0].to_vec(),
value3.bytes32().to_vec()
);

let info = contract
.execute(&[
b"test_log4(uint256,uint256,uint256,uint256)".to_vec(),
value1.bytes32().to_vec(),
value2.bytes32().to_vec(),
value3.bytes32().to_vec(),
value4.bytes32().to_vec(),
])
.unwrap();
assert!(!info.logs.is_empty());
assert_eq!(
info.logs[0].topics()[3].to_vec(),
value1.bytes32().to_vec()
);
assert_eq!(
info.logs[0].topics()[2].to_vec(),
value2.bytes32().to_vec()
);
assert_eq!(
info.logs[0].topics()[1].to_vec(),
value3.bytes32().to_vec()
);
assert_eq!(
info.logs[0].topics()[0].to_vec(),
value4.bytes32().to_vec()
);

let info = contract
.execute(&[
b"test_multiple_logs(uint256,uint256,uint256,uint256)".to_vec(),
value1.bytes32().to_vec(),
value2.bytes32().to_vec(),
value3.bytes32().to_vec(),
value4.bytes32().to_vec(),
])
.unwrap();
assert!(!info.logs.is_empty());
}
}
}

#[cfg(not(target_arch = "wasm32"))]
fn main() {}

#[test]
fn test() -> anyhow::Result<()> {
use zint::{Bytes32, Contract};
let mut contract = Contract::search("log")?.compile()?;

let info = contract.execute(["log0()"])?;
assert_eq!(
info.logs[0].data.data.to_vec(),
b"Ping".to_vec().to_bytes32()
);

let info = contract.execute(["log1()"])?;
assert_eq!(
info.logs[0].data.data.to_vec(),
b"Ping".to_vec().to_bytes32()
);
assert_eq!(info.logs[0].topics(), vec![b"pong".to_vec().to_bytes32()]);

let info = contract.execute(["log2()"])?;
assert_eq!(
info.logs[0].data.data.to_vec(),
b"Ping".to_vec().to_bytes32()
);
assert_eq!(
info.logs[0].topics(),
vec![b"pong".to_vec().to_bytes32(), b"ping".to_vec().to_bytes32()]
);

let info = contract.execute(["log3()"])?;
assert_eq!(
info.logs[0].data.data.to_vec(),
b"Ping".to_vec().to_bytes32()
);
assert_eq!(
info.logs[0].topics(),
vec![
b"pong".to_vec().to_bytes32(),
b"ping".to_vec().to_bytes32(),
b"pong".to_vec().to_bytes32()
]
);

let info = contract.execute(["log4()"])?;
assert_eq!(
info.logs[0].data.data.to_vec(),
b"Ping".to_vec().to_bytes32()
);
assert_eq!(
info.logs[0].topics(),
vec![
b"pong".to_vec().to_bytes32(),
b"ping".to_vec().to_bytes32(),
b"pong".to_vec().to_bytes32(),
b"pong".to_vec().to_bytes32()
]
);

Ok(())
}
Loading
Loading