Skip to content

Commit

Permalink
fix: deserialize missing state mutability as non payable (#488)
Browse files Browse the repository at this point in the history
  • Loading branch information
mattsse authored Jan 20, 2024
1 parent d3f0c69 commit 317951e
Show file tree
Hide file tree
Showing 5 changed files with 41 additions and 1 deletion.
6 changes: 6 additions & 0 deletions crates/json-abi/src/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,20 +66,23 @@ abi_items! {
/// The input types of the constructor. May be empty.
pub inputs: Vec<Param>,
/// The state mutability of the constructor.
#[serde(default)]
pub state_mutability: StateMutability,
}

/// A JSON ABI fallback function.
#[derive(Copy)]
pub struct Fallback: "fallback" {
/// The state mutability of the fallback function.
#[serde(default)]
pub state_mutability: StateMutability,
}

/// A JSON ABI receive function.
#[derive(Copy)]
pub struct Receive: "receive" {
/// The state mutability of the receive function.
#[serde(default)]
pub state_mutability: StateMutability,
}

Expand All @@ -93,6 +96,9 @@ abi_items! {
/// The output types of the function. May be empty.
pub outputs: Vec<Param>,
/// The state mutability of the function.
///
/// By default this is [StateMutability::NonPayable] which is reflected in Solidity by not specifying a state mutability modifier at all. This field was introduced in 0.4.16: <https://github.com/ethereum/solidity/releases/tag/v0.4.16>
#[serde(default)]
pub state_mutability: StateMutability,
}

Expand Down
10 changes: 9 additions & 1 deletion crates/json-abi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,14 +50,22 @@ mod to_sol;
pub(crate) mod utils;

/// A JSON ABI function's state mutability.
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
#[derive(
Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize,
)]
#[serde(rename_all = "lowercase")]
pub enum StateMutability {
/// Pure functions promise not to read from or modify the state.
Pure,
/// View functions promise not to modify the state.
View,
/// Nonpayable functions promise not to receive Ether.
///
/// This is the solidity default: <https://docs.soliditylang.org/en/latest/abi-spec.html#json>
///
/// The state mutability nonpayable is reflected in Solidity by not specifying a state
/// mutability modifier at all.
#[default]
NonPayable,
/// Payable functions make no promises.
Payable,
Expand Down
1 change: 1 addition & 0 deletions crates/json-abi/tests/abi/ZRXToken.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_value","type":"uint256"}],"name":"approve","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transferFrom","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint8"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"}],"name":"balanceOf","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transfer","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"_owner","type":"address"},{"name":"_spender","type":"address"}],"name":"allowance","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"inputs":[],"payable":false,"type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_from","type":"address"},{"indexed":true,"name":"_to","type":"address"},{"indexed":false,"name":"_value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_owner","type":"address"},{"indexed":true,"name":"_spender","type":"address"},{"indexed":false,"name":"_value","type":"uint256"}],"name":"Approval","type":"event"}]
14 changes: 14 additions & 0 deletions crates/json-abi/tests/abi/ZRXToken.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
interface ZRXToken {
event Approval(address indexed _owner, address indexed _spender, uint256 _value);
event Transfer(address indexed _from, address indexed _to, uint256 _value);

function allowance(address _owner, address _spender) external returns (uint256);
function approve(address _spender, uint256 _value) external returns (bool);
function balanceOf(address _owner) external returns (uint256);
function decimals() external returns (uint8);
function name() external returns (string memory);
function symbol() external returns (string memory);
function totalSupply() external returns (uint256);
function transfer(address _to, uint256 _value) external returns (bool);
function transferFrom(address _from, address _to, uint256 _value) external returns (bool);
}
11 changes: 11 additions & 0 deletions crates/sol-types/tests/macros/sol/json.rs
Original file line number Diff line number Diff line change
Expand Up @@ -179,3 +179,14 @@ fn junkyard() {
// https://etherscan.io/address/0x2e4b0f20bdb1caa0886c531256efdaab925dbe72
sol!(Junkyard, "../json-abi/tests/abi/Junkyard.json");
}

// Handle missing state mutability in JSON ABI
// https://github.com/alloy-rs/core/issues/485
#[test]
fn zrx_token() {
// https://etherscan.io/address/0xe41d2489571d322189246dafa5ebde1f4699f498#code
sol!(ZRXToken, "../json-abi/tests/abi/ZRXToken.json");

let _ = ZRXToken::approveCall { _spender: Address::ZERO, _value: U256::ZERO };
assert_eq!(ZRXToken::approveCall::SIGNATURE, "approve(address,uint256)");
}

0 comments on commit 317951e

Please sign in to comment.