Compare commits

..

3 Commits

Author SHA1 Message Date
Omar Abdulla 7836461763 Add test 2025-07-21 12:15:27 +03:00
Omar Abdulla 0e473e1633 Merge remote-tracking branch 'origin/main' into bugfix/function-signature 2025-07-21 12:13:24 +03:00
Omar Abdulla c8cef4834f Allow for the use of function signatures 2025-07-18 16:37:15 +03:00
2 changed files with 60 additions and 64 deletions
+44 -60
View File
@@ -23,8 +23,7 @@ pub struct Input {
#[serde(default = "default_instance")]
pub instance: ContractInstance,
pub method: Method,
#[serde(default)]
pub calldata: Calldata,
pub calldata: Option<Calldata>,
pub expected: Option<Expected>,
pub value: Option<String>,
pub storage: Option<HashMap<String, Calldata>>,
@@ -74,12 +73,6 @@ pub enum Method {
FunctionName(String),
}
impl Default for Calldata {
fn default() -> Self {
Self::Compound(Default::default())
}
}
impl Calldata {
pub fn find_all_contract_instances(&self, vec: &mut Vec<ContractInstance>) {
if let Calldata::Compound(compound) = self {
@@ -90,40 +83,6 @@ impl Calldata {
}
}
}
pub fn construct_call_data(
&self,
buffer: &mut Vec<u8>,
deployed_contracts: &HashMap<ContractInstance, (Address, JsonAbi)>,
chain_state_provider: &impl EthereumNode,
) -> anyhow::Result<()> {
match self {
Calldata::Single(string) => {
alloy::hex::decode_to_slice(string, buffer)?;
}
Calldata::Compound(items) => {
for (arg_idx, arg) in items.iter().enumerate() {
match resolve_argument(arg, deployed_contracts, chain_state_provider) {
Ok(resolved) => {
buffer.extend(resolved.to_be_bytes::<32>());
}
Err(error) => {
tracing::error!(arg, arg_idx, ?error, "Failed to resolve argument");
return Err(error);
}
};
}
}
};
Ok(())
}
pub fn size_requirement(&self) -> usize {
match self {
Calldata::Single(single) => (single.len() - 2) / 2,
Calldata::Compound(items) => items.len() * 32,
}
}
}
impl ExpectedOutput {
@@ -153,12 +112,23 @@ impl Input {
) -> anyhow::Result<Bytes> {
match self.method {
Method::Deployer | Method::Fallback => {
let mut calldata = Vec::<u8>::with_capacity(self.calldata.size_requirement());
self.calldata.construct_call_data(
&mut calldata,
deployed_contracts,
chain_state_provider,
)?;
let calldata_args = match &self.calldata {
Some(Calldata::Compound(args)) => args,
_ => anyhow::bail!("Expected compound calldata for function call"),
};
let mut calldata = Vec::<u8>::with_capacity(calldata_args.len() * 32);
for (arg_idx, arg) in calldata_args.iter().enumerate() {
match resolve_argument(arg, deployed_contracts, chain_state_provider) {
Ok(resolved) => {
calldata.extend(resolved.to_be_bytes::<32>());
}
Err(error) => {
tracing::error!(arg, arg_idx, ?error, "Failed to resolve argument");
return Err(error);
}
};
}
Ok(calldata.into())
}
@@ -191,6 +161,11 @@ impl Input {
tracing::trace!("Functions found for instance: {}", self.instance.as_ref());
let calldata_args = match &self.calldata {
Some(Calldata::Compound(args)) => args,
_ => anyhow::bail!("Expected compound calldata for function call"),
};
tracing::trace!(
"Starting encoding ABI's parameters for instance: {}",
self.instance.as_ref()
@@ -202,13 +177,20 @@ impl Input {
//
// We're using indices in the following code in order to avoid the need for us to allocate
// a new buffer for each one of the resolved arguments.
let mut calldata = Vec::<u8>::with_capacity(4 + self.calldata.size_requirement());
let mut calldata = Vec::<u8>::with_capacity(4 + calldata_args.len() * 32);
calldata.extend(function.selector().0);
self.calldata.construct_call_data(
&mut calldata,
deployed_contracts,
chain_state_provider,
)?;
for (arg_idx, arg) in calldata_args.iter().enumerate() {
match resolve_argument(arg, deployed_contracts, chain_state_provider) {
Ok(resolved) => {
calldata.extend(resolved.to_be_bytes::<32>());
}
Err(error) => {
tracing::error!(arg, arg_idx, ?error, "Failed to resolve argument");
return Err(error);
}
};
}
Ok(calldata.into())
}
@@ -235,7 +217,9 @@ impl Input {
let mut vec = Vec::new();
vec.push(self.instance.clone());
self.calldata.find_all_contract_instances(&mut vec);
if let Some(ref cd) = self.calldata {
cd.find_all_contract_instances(&mut vec);
}
match &self.expected {
Some(Expected::Calldata(cd)) => {
cd.find_all_contract_instances(&mut vec);
@@ -432,7 +416,7 @@ mod tests {
let input = Input {
instance: ContractInstance::new_from("Contract"),
method: Method::FunctionName("store".to_owned()),
calldata: Calldata::Compound(vec!["42".into()]),
calldata: Some(Calldata::Compound(vec!["42".into()])),
..Default::default()
};
@@ -474,9 +458,9 @@ mod tests {
let input: Input = Input {
instance: "Contract".to_owned().into(),
method: Method::FunctionName("send(address)".to_owned()),
calldata: Calldata::Compound(vec![
calldata: Some(Calldata::Compound(vec![
"0x1000000000000000000000000000000000000001".to_string(),
]),
])),
..Default::default()
};
@@ -521,9 +505,9 @@ mod tests {
let input: Input = Input {
instance: ContractInstance::new_from("Contract"),
method: Method::FunctionName("send".to_owned()),
calldata: Calldata::Compound(vec![
calldata: Some(Calldata::Compound(vec![
"0x1000000000000000000000000000000000000001".to_string(),
]),
])),
..Default::default()
};
+16 -4
View File
@@ -110,25 +110,37 @@ mod tests {
#[test]
fn try_get_windows() {
let version = List::download(List::WINDOWS_URL).unwrap().latest_release;
let version = List::download(List::WINDOWS_URL)
.unwrap()
.latest_release
.into();
GHDownloader::windows(version).download().unwrap();
}
#[test]
fn try_get_macosx() {
let version = List::download(List::MACOSX_URL).unwrap().latest_release;
let version = List::download(List::MACOSX_URL)
.unwrap()
.latest_release
.into();
GHDownloader::macosx(version).download().unwrap();
}
#[test]
fn try_get_linux() {
let version = List::download(List::LINUX_URL).unwrap().latest_release;
let version = List::download(List::LINUX_URL)
.unwrap()
.latest_release
.into();
GHDownloader::linux(version).download().unwrap();
}
#[test]
fn try_get_wasm() {
let version = List::download(List::WASM_URL).unwrap().latest_release;
let version = List::download(List::WASM_URL)
.unwrap()
.latest_release
.into();
GHDownloader::wasm(version).download().unwrap();
}
}