Skip to content

Commit d5db2c5

Browse files
teddavEvalir
andauthored
feat(chisel): display return value on function call (foundry-rs#5584)
* feat(chisel): display return value on function call * styling * add lifetime to avoid unwrapping * chore: clippy * chore: match instead of destructure for clarity --------- Co-authored-by: Enrique Ortiz <[email protected]>
1 parent dffdfde commit d5db2c5

File tree

1 file changed

+50
-5
lines changed

1 file changed

+50
-5
lines changed

crates/chisel/src/executor.rs

Lines changed: 50 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -176,12 +176,22 @@ impl SessionSource {
176176
.get(input)
177177
.or_else(|| source.infer_inner_expr_type());
178178

179-
let (contract_expr, ty) = match contract_expr
180-
.and_then(|e| Type::ethabi(e, Some(&generated_output.intermediate)).map(|ty| (e, ty)))
179+
// If the current action is a function call, we get its return type
180+
// otherwise it returns None
181+
let function_call_return_type =
182+
Type::get_function_return_type(contract_expr, &generated_output.intermediate);
183+
184+
let (contract_expr, ty) = if let Some(function_call_return_type) = function_call_return_type
181185
{
182-
Some(res) => res,
183-
// this type was denied for inspection, continue
184-
None => return Ok((true, None)),
186+
(function_call_return_type.0, function_call_return_type.1)
187+
} else {
188+
match contract_expr.and_then(|e| {
189+
Type::ethabi(e, Some(&generated_output.intermediate)).map(|ty| (e, ty))
190+
}) {
191+
Some(res) => res,
192+
// this type was denied for inspection, continue
193+
None => return Ok((true, None)),
194+
}
185195
};
186196

187197
// the file compiled correctly, thus the last stack item must be the memory offset of
@@ -988,6 +998,41 @@ impl Type {
988998
.and_then(|ty| ty.try_as_ethabi(intermediate))
989999
}
9901000

1001+
/// Get the return type of a function call expression.
1002+
fn get_function_return_type<'a>(
1003+
contract_expr: Option<&'a pt::Expression>,
1004+
intermediate: &IntermediateOutput,
1005+
) -> Option<(&'a pt::Expression, ParamType)> {
1006+
let function_call = match contract_expr? {
1007+
pt::Expression::FunctionCall(_, function_call, _) => function_call,
1008+
_ => return None,
1009+
};
1010+
let (contract_name, function_name) = match function_call.as_ref() {
1011+
pt::Expression::MemberAccess(_, contract_name, function_name) => {
1012+
(contract_name, function_name)
1013+
}
1014+
_ => return None,
1015+
};
1016+
let contract_name = match contract_name.as_ref() {
1017+
pt::Expression::Variable(contract_name) => contract_name.to_owned(),
1018+
_ => return None,
1019+
};
1020+
1021+
let pt::Expression::Variable(contract_name) =
1022+
intermediate.repl_contract_expressions.get(&contract_name.name)?
1023+
else {
1024+
return None
1025+
};
1026+
1027+
let contract = intermediate
1028+
.intermediate_contracts
1029+
.get(&contract_name.name)?
1030+
.function_definitions
1031+
.get(&function_name.name)?;
1032+
let return_parameter = contract.as_ref().returns.first()?.to_owned().1?;
1033+
Type::ethabi(&return_parameter.ty, Some(intermediate)).map(|p| (contract_expr.unwrap(), p))
1034+
}
1035+
9911036
/// Inverts Int to Uint and viceversa.
9921037
fn invert_int(self) -> Self {
9931038
match self {

0 commit comments

Comments
 (0)