Signed-off-by: xermicus <cyrill@parity.io>
This commit is contained in:
xermicus
2024-05-14 09:46:18 +02:00
parent 2194aeebd0
commit 83bf9d6041
10 changed files with 194 additions and 72 deletions
+22
View File
@@ -104,6 +104,15 @@ sol!(
}
);
sol!(
contract Events {
event A(uint) anonymous;
event E(uint indexed, uint indexed, uint indexed);
function emitEvent(uint topics) public;
}
);
impl Contract {
/// Execute the contract.
///
@@ -338,6 +347,18 @@ impl Contract {
calldata: MStore8::mStore8Call::new((value,)).abi_encode(),
}
}
pub fn event(topics: U256) -> Self {
let code = include_str!("../contracts/Events.sol");
let name = "Events";
Self {
name,
evm_runtime: crate::compile_evm_bin_runtime(name, code),
pvm_runtime: crate::compile_blob(name, code),
calldata: Events::emitEventCall::new((topics,)).abi_encode(),
}
}
}
#[cfg(test)]
@@ -389,6 +410,7 @@ mod tests {
Contract::erc20 as fn() -> Contract,
(|| Contract::sha1(Vec::new())) as fn() -> Contract,
(|| Contract::division_arithmetics_div(U256::ZERO, U256::ZERO)) as fn() -> Contract,
(|| Contract::event(U256::ZERO)) as fn() -> Contract,
]
.into_par_iter()
.map(extract_code_size)
+21 -2
View File
@@ -1,7 +1,8 @@
use alloy_primitives::{Address, U256};
use cases::Contract;
use mock_runtime::{CallOutput, State};
use crate::mock_runtime::ReturnFlags;
use crate::mock_runtime::{Event, ReturnFlags};
pub mod cases;
pub mod mock_runtime;
@@ -82,7 +83,25 @@ pub fn assert_success(contract: &Contract, differential: bool) -> (State, CallOu
if differential {
let evm =
revive_differential::prepare(contract.evm_runtime.clone(), contract.calldata.clone());
assert_eq!(output.data.clone(), revive_differential::execute(evm));
let (evm_output, evm_log) = revive_differential::execute(evm);
assert_eq!(output.data.clone(), evm_output);
assert_eq!(output.events.len(), evm_log.len());
assert_eq!(
output.events,
evm_log
.iter()
.map(|log| Event {
address: Address::from_slice(log.address.as_bytes()),
data: log.data.clone(),
topics: log
.topics
.iter()
.map(|topic| U256::from_be_bytes(topic.0))
.collect(),
})
.collect::<Vec<_>>()
);
}
(state, output)
+40 -2
View File
@@ -17,8 +17,9 @@ struct Account {
}
/// Emitted event data.
#[derive(Debug, Default, Clone)]
#[derive(Debug, Default, Clone, PartialEq)]
pub struct Event {
pub address: Address,
pub data: Vec<u8>,
pub topics: Vec<U256>,
}
@@ -31,7 +32,7 @@ pub struct CallOutput {
/// The contract call output.
pub data: Vec<u8>,
/// The emitted events.
pub events: Event,
pub events: Vec<Event>,
}
/// The contract blob export to be called.
@@ -570,6 +571,43 @@ fn link_host_functions(engine: &Engine) -> Linker<Transaction> {
)
.unwrap();
linker
.func_wrap(
runtime_api::DEPOSIT_EVENT,
|caller: Caller<Transaction>,
topics_ptr: u32,
topics_len: u32,
data_ptr: u32,
data_len: u32| {
let (caller, transaction) = caller.split();
let address = transaction.top_frame().callee;
let data = if data_len != 0 {
caller.read_memory_into_vec(data_ptr, data_len)?
} else {
Default::default()
};
let topics = if topics_len != 0 {
caller
.read_memory_into_vec(topics_ptr, topics_len)?
.chunks(32)
.map(|chunk| U256::from_be_slice(chunk))
.collect()
} else {
Default::default()
};
transaction.top_frame_mut().output.events.push(Event {
address,
data,
topics,
});
Ok(())
},
)
.unwrap();
linker
}
+6
View File
@@ -415,3 +415,9 @@ fn signed_remainder() {
assert_eq!(received, expected);
}
}
#[test]
fn events() {
assert_success(&Contract::event(U256::ZERO), true);
assert_success(&Contract::event(U256::from(123)), true);
}