Skip to content

Commit

Permalink
feat(sol-macro): add return value names to simple getters
Browse files Browse the repository at this point in the history
  • Loading branch information
DaniPopes committed Jun 4, 2024
1 parent 9d5c39f commit 715ef63
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 11 deletions.
31 changes: 30 additions & 1 deletion crates/sol-types/tests/macros/sol/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use alloy_primitives::{b256, bytes, hex, keccak256, Address, I256, U256};
use alloy_primitives::{b256, bytes, hex, keccak256, Address, B256, I256, U256};
use alloy_sol_types::{sol, SolCall, SolError, SolEvent, SolStruct, SolType};
use serde::Serialize;
use serde_json::Value;
Expand Down Expand Up @@ -238,6 +238,35 @@ fn getters() {
let _ = nestedMapArrayReturn { _0: U256::ZERO };
}

#[test]
fn getter_names() {
sol! {
contract Getters {
string public value;
string[] public array;
mapping(bytes32 => string) public map;
mapping(bytes32 k => string v) public mapWithNames;

mapping(bytes32 k1 => mapping(uint256 k2 => string v2) v1) public nestedMapWithNames;
}
}

let _ = Getters::valueCall {};
let _ = Getters::valueReturn { value: String::new() };

let _ = Getters::arrayCall { _0: U256::ZERO };
let _ = Getters::arrayReturn { _0: String::new() };

let _ = Getters::mapCall { _0: B256::ZERO };
let _ = Getters::mapReturn { _0: String::new() };

let _ = Getters::mapWithNamesCall { k: B256::ZERO };
let _ = Getters::mapWithNamesReturn { v: String::new() };

let _ = Getters::nestedMapWithNamesCall { k1: B256::ZERO, k2: U256::ZERO };
let _ = Getters::nestedMapWithNamesReturn { v2: String::new() };
}

#[test]
fn abigen_sol_multicall() {
sol!("../syn-solidity/tests/contracts/Multicall.sol");
Expand Down
31 changes: 21 additions & 10 deletions crates/syn-solidity/src/item/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -145,17 +145,19 @@ impl ItemFunction {
pub fn new_getter(name: SolIdent, ty: Type) -> Self {
let span = name.span();
let kind = FunctionKind::new_function(span);
let mut function = Self::new(kind, Some(name));
let mut function = Self::new(kind, Some(name.clone()));

// `public view`
function.attributes.0 = vec![
FunctionAttribute::Visibility(Visibility::new_public(span)),
FunctionAttribute::Mutability(Mutability::new_view(span)),
];

// Recurse into mappings and arrays to generate arguments and the return type
// Recurse into mappings and arrays to generate arguments and the return type.
// If the return type is simple, the return value name is set to the variable name.
let mut ty = ty;
let mut return_name = None;
let mut first = true;
loop {
match ty {
// mapping(k => v) -> arguments += k, ty = v
Expand All @@ -171,8 +173,14 @@ impl ItemFunction {
function.parameters.push(VariableDeclaration::new(uint256));
ty = *array.ty;
}
_ => break,
_ => {
if first {
return_name = Some(name);
}
break;
}
}
first = false;
}
let mut returns = ParameterList::new();
returns.push(VariableDeclaration::new_with(ty, None, return_name));
Expand Down Expand Up @@ -446,10 +454,10 @@ mod tests {
}

test_getters! {
"bool public getter;"
=> "function getter() public view returns (bool);",
"bool public constant publicConstantAttr = false;"
=> "function publicConstantAttr() public view returns (bool);",
"bool public simple;"
=> "function simple() public view returns (bool simple);",
"bool public constant simpleConstant = false;"
=> "function simpleConstant() public view returns (bool simpleConstant);",

"mapping(address => bool) public map;"
=> "function map(address) public view returns (bool);",
Expand All @@ -473,9 +481,12 @@ mod tests {
let var = syn::parse_str::<VariableDefinition>(var_s).unwrap();
let getter = ItemFunction::from_variable_definition(var);
let f = syn::parse_str::<ItemFunction>(fn_s).unwrap();
assert_eq!(format!("{getter:#?}"), format!("{f:#?}"));
// test that the ABIs are the same
if run_solc {
assert_eq!(format!("{getter:#?}"), format!("{f:#?}"), "{var_s}");

// Test that the ABIs are the same.
// Skip `simple` getters since the return type will have a different ABI because Solc
// doesn't populate the field.
if run_solc && !var_s.contains("simple") {
match (wrap_and_compile(var_s, true), wrap_and_compile(fn_s, false)) {
(Ok(a), Ok(b)) => {
assert_eq!(a.trim(), b.trim(), "\nleft: {var_s:?}\nright: {fn_s:?}")
Expand Down

0 comments on commit 715ef63

Please sign in to comment.