|
1 | 1 | //! The test driver handles the compilation and execution of the test cases. |
2 | 2 |
|
3 | 3 | use alloy::{ |
4 | | - primitives::{Address, map::HashMap}, |
5 | | - rpc::types::trace::geth::{AccountState, DiffMode, GethTrace}, |
| 4 | + network::TransactionBuilder, |
| 5 | + primitives::{Address, bytes::Bytes, map::HashMap}, |
| 6 | + rpc::types::{ |
| 7 | + TransactionRequest, |
| 8 | + trace::geth::{AccountState, DiffMode, GethTrace}, |
| 9 | + }, |
6 | 10 | }; |
7 | 11 | use revive_dt_compiler::{Compiler, CompilerInput, SolidityCompiler}; |
8 | 12 | use revive_dt_config::Arguments; |
@@ -109,6 +113,56 @@ where |
109 | 113 |
|
110 | 114 | Ok((trace, diff)) |
111 | 115 | } |
| 116 | + |
| 117 | + pub fn deploy_contracts(&mut self, input: &Input, node: &T::Blockchain) -> anyhow::Result<()> { |
| 118 | + for output in self.contracts.values() { |
| 119 | + let Some(contract_map) = &output.contracts else { |
| 120 | + log::debug!("No contracts in output — skipping deployment for this input."); |
| 121 | + continue; |
| 122 | + }; |
| 123 | + |
| 124 | + for contracts in contract_map.values() { |
| 125 | + for (contract_name, contract) in contracts { |
| 126 | + if contract_name != &input.instance { |
| 127 | + continue; |
| 128 | + } |
| 129 | + |
| 130 | + let bytecode = contract |
| 131 | + .evm |
| 132 | + .as_ref() |
| 133 | + .and_then(|evm| evm.bytecode.as_ref()) |
| 134 | + .map(|b| b.object.clone()); |
| 135 | + |
| 136 | + let Some(code) = bytecode else { |
| 137 | + anyhow::bail!("no bytecode for contract `{}`", contract_name); |
| 138 | + }; |
| 139 | + |
| 140 | + let tx = TransactionRequest::default() |
| 141 | + .with_from(input.caller) |
| 142 | + .with_to(Address::ZERO) |
| 143 | + .with_input(Bytes::from(code.clone())) |
| 144 | + .with_gas_price(20_000_000_000) |
| 145 | + .with_gas_limit(20_000_000_000) |
| 146 | + .with_chain_id(self.config.network_id) |
| 147 | + .with_nonce(0); |
| 148 | + |
| 149 | + let receipt = node.execute_transaction(tx)?; |
| 150 | + let Some(address) = receipt.contract_address else { |
| 151 | + anyhow::bail!( |
| 152 | + "contract `{}` deployment did not return an address", |
| 153 | + contract_name |
| 154 | + ); |
| 155 | + }; |
| 156 | + |
| 157 | + self.deployed_contracts |
| 158 | + .insert(contract_name.clone(), address); |
| 159 | + log::info!("deployed contract `{}` at {:?}", contract_name, address); |
| 160 | + } |
| 161 | + } |
| 162 | + } |
| 163 | + |
| 164 | + Ok(()) |
| 165 | + } |
112 | 166 | } |
113 | 167 |
|
114 | 168 | pub struct Driver<'a, Leader: Platform, Follower: Platform> { |
@@ -173,6 +227,9 @@ where |
173 | 227 |
|
174 | 228 | for case in &self.metadata.cases { |
175 | 229 | for input in &case.inputs { |
| 230 | + leader_state.deploy_contracts(input, self.leader_node)?; |
| 231 | + follower_state.deploy_contracts(input, self.follower_node)?; |
| 232 | + |
176 | 233 | let (_, leader_diff) = leader_state.execute_input(input, self.leader_node)?; |
177 | 234 | let (_, follower_diff) = |
178 | 235 | follower_state.execute_input(input, self.follower_node)?; |
|
0 commit comments