Compare commits

..

3 Commits

Author SHA1 Message Date
Omar Abdulla d8017b4ddf Support linking at compile time 2025-07-25 09:37:24 +03:00
Omar Abdulla eacc09fe4f Create a unified way to access deployed contracts 2025-07-24 20:16:07 +03:00
Omar Abdulla 7ef76bb470 Use wrappers for libraries in metadata. 2025-07-24 19:07:06 +03:00
4 changed files with 14 additions and 110 deletions
-4
View File
@@ -10,10 +10,6 @@ use crate::{CompilerInput, CompilerOutput, SolidityCompiler};
use revive_dt_config::Arguments;
use revive_solc_json_interface::SolcStandardJsonOutput;
// TODO: I believe that we need to also pass the solc compiler to resolc so that resolc uses the
// specified solc compiler. I believe that currently we completely ignore the specified solc binary
// when invoking resolc which doesn't seem right if we're using solc as a compiler frontend.
/// A wrapper around the `resolc` binary, emitting PVM-compatible bytecode.
#[derive(Debug)]
pub struct Resolc {
+12 -55
View File
@@ -3,7 +3,6 @@
use std::collections::HashMap;
use std::fmt::Debug;
use std::marker::PhantomData;
use std::str::FromStr;
use alloy::json_abi::JsonAbi;
use alloy::network::{Ethereum, TransactionBuilder};
@@ -101,30 +100,12 @@ where
anyhow::bail!("unsupported solc version: {:?}", &mode.solc_version);
};
// Note: if the metadata is contained within a solidity file then this is the only file that
// we wish to compile since this is a self-contained test. Otherwise, if it's a JSON file
// then we need to compile all of the contracts that are in the directory since imports are
// allowed in there.
let Some(ref metadata_file_path) = metadata.file_path else {
anyhow::bail!("The metadata file path is not defined");
};
let mut files_to_compile = if metadata_file_path
.extension()
.is_some_and(|extension| extension.eq_ignore_ascii_case("sol"))
{
Box::new(std::iter::once(metadata_file_path.clone())) as Box<dyn Iterator<Item = _>>
} else {
Box::new(
FilesWithExtensionIterator::new(metadata.directory()?)
.with_allowed_extension("sol"),
)
};
let compiler = Compiler::<T::Compiler>::new()
.allow_path(metadata.directory()?)
.solc_optimizer(mode.solc_optimize());
let mut compiler =
files_to_compile.try_fold(compiler, |compiler, path| compiler.with_source(&path))?;
let mut compiler = FilesWithExtensionIterator::new(metadata.directory()?)
.with_allowed_extension("sol")
.try_fold(compiler, |compiler, path| compiler.with_source(&path))?;
for (library_instance, (library_address, _)) in self.deployed_libraries.iter() {
let library_ident = &metadata
.contracts
@@ -219,13 +200,12 @@ where
case_idx: CaseIdx,
input: &Input,
node: &T::Blockchain,
mode: &SolcMode,
) -> anyhow::Result<(TransactionReceipt, GethTrace, DiffMode)> {
let deployment_receipts =
self.handle_contract_deployment(metadata, case_idx, input, node)?;
let execution_receipt =
self.handle_input_execution(case_idx, input, deployment_receipts, node)?;
self.handle_input_expectations(case_idx, input, &execution_receipt, node, mode)?;
self.handle_input_expectations(case_idx, input, &execution_receipt, node)?;
self.handle_input_diff(case_idx, execution_receipt, node)
}
@@ -332,7 +312,6 @@ where
input: &Input,
execution_receipt: &TransactionReceipt,
node: &T::Blockchain,
mode: &SolcMode,
) -> anyhow::Result<()> {
let span = tracing::info_span!("Handling input expectations");
let _guard = span.enter();
@@ -388,7 +367,6 @@ where
node,
expectation,
&tracing_result,
mode,
)?;
}
@@ -402,16 +380,11 @@ where
node: &T::Blockchain,
expectation: &ExpectedOutput,
tracing_result: &CallFrame,
mode: &SolcMode,
) -> anyhow::Result<()> {
if let Some(ref version_requirement) = expectation.compiler_version {
let Some(compiler_version) = mode.last_patch_version(&self.config.solc) else {
anyhow::bail!("unsupported solc version: {:?}", &mode.solc_version);
};
if !version_requirement.matches(&compiler_version) {
return Ok(());
}
}
// TODO: We want to respect the compiler version filter on the expected output but would
// require some changes to the interfaces of the compiler and such. So, we add it later.
// Additionally, what happens if the compiler filter doesn't match? Do we consider that the
// transaction should succeed? Do we just ignore the expectation?
let deployed_contracts = self.deployed_contracts(case_idx);
let chain_state_provider = node;
@@ -458,18 +431,8 @@ where
expected_events.iter().zip(execution_receipt.logs())
{
// Handling the emitter assertion.
if let Some(ref expected_address) = expected_event.address {
let expected = if let Some(contract_instance) = expected_address
.strip_suffix(".address")
.map(ContractInstance::new)
{
deployed_contracts
.get(&contract_instance)
.map(|(address, _)| *address)
} else {
Address::from_str(expected_address).ok()
}
.context("Failed to get the address of the event")?;
if let Some(expected_address) = expected_event.address {
let expected = expected_address;
let actual = actual_event.address();
if actual != expected {
tracing::error!(
@@ -902,13 +865,8 @@ where
tracing::info_span!("Executing input", contract_name = ?input.instance)
.in_scope(|| {
let (leader_receipt, _, leader_diff) = match leader_state
.handle_input(
self.metadata,
case_idx,
&input,
self.leader_node,
&mode,
) {
.handle_input(self.metadata, case_idx, &input, self.leader_node)
{
Ok(result) => result,
Err(error) => {
tracing::error!(
@@ -937,7 +895,6 @@ where
case_idx,
&input,
self.follower_node,
&mode,
) {
Ok(result) => result,
Err(error) => {
+1 -50
View File
@@ -51,7 +51,7 @@ pub struct ExpectedOutput {
#[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq)]
pub struct Event {
pub address: Option<String>,
pub address: Option<Address>,
pub topics: Vec<String>,
pub values: Calldata,
}
@@ -1010,53 +1010,4 @@ mod tests {
// Assert
assert!(resolved.is_err())
}
#[test]
fn expected_json_can_be_deserialized1() {
// Arrange
let str = r#"
{
"return_data": [
"1"
],
"events": [
{
"topics": [],
"values": []
}
]
}
"#;
// Act
let expected = serde_json::from_str::<Expected>(str);
// Assert
expected.expect("Failed to deserialize");
}
#[test]
fn expected_json_can_be_deserialized2() {
// Arrange
let str = r#"
{
"return_data": [
"1"
],
"events": [
{
"address": "Main.address",
"topics": [],
"values": []
}
]
}
"#;
// Act
let expected = serde_json::from_str::<Expected>(str);
// Assert
expected.expect("Failed to deserialize");
}
}
+1 -1
View File
@@ -193,7 +193,7 @@ impl Metadata {
metadata.file_path = Some(path.to_path_buf());
metadata.contracts = Some(
[(
ContractInstance::new("Test"),
ContractInstance::new("test"),
ContractPathAndIdent {
contract_source_path: path.to_path_buf(),
contract_ident: ContractIdent::new("Test"),