Repository: gakonst/ethers-rs
Pull request #740 (2021-12-25 16:17:55)

feat: support abi generated from forge
## Motivation

Binding generated by AbiGen which bind output of `forge build`  throws this error #683 

But it work If I change the format of ABI json to only be the content of `abi`

## Solution



## PR Checklist

- [x] Added Tests
- [ ] Added Documentation
- [ ] Updated the changelog


gakonst: Hey - I think this does not exactly work? A few errors in CI - could you take another look?
thasarito: looks like https://github.com/thasarito/ethers-rs/blob/8c63eef62669e5a13a5adac44166f2348913310d/ethers-contract/ethers-contract-abigen/src/contract.rs#L159 breaks a lot of test.

Can you give me some direction how to fix this? @mattsse @gakonst 
mattsse: > looks like https://github.com/thasarito/ethers-rs/blob/8c63eef62669e5a13a5adac44166f2348913310d/ethers-contract/ethers-contract-abigen/src/contract.rs#L159 breaks a lot of test.
> 
> Can you give me some direction how to fix this? @mattsse @gakonst

abi parsing is a bit horrible rn for several reasons:
* the `ethabi::Contract` type does not really deserialize to the same json object solc spits out, I noticed it omits some fields for the `constructor`.
* it also seems like `ethabi::Contract` can't handle a serde roundtrip? as it fails to deserialize its own serialization apparently...

This is really an `ethabi` issue, we faced something similar in the past, that's why the `RawAbi` was introduced in the first place, which is an as-is representation of solc's `abi`.

Also we currently have a system in place that handles human readable abi differently, instead of the json abi we parse the human readable abi during runtime as well, which is perhaps no longer necessary, I think

So how to mitigate this here:
short term is, update the `abi_str` only is this else branch, and use the `RawAbi` to deserialize it
https://github.com/gakonst/ethers-rs/blob/42647d61f84a9d9f55383d8c6b432d01007434ef/ethers-contract/ethers-contract-abigen/src/contract.rs#L177-L181
long term get this fixed on `ethabi`
gakonst: hey @thasarito - happy new year! any plans to get this over the line?
thasarito: > hey @thasarito - happy new year! any plans to get this over the line?

I'm working on it but it might take a while.
gakonst: word - just checking! no rush.
thasarito: @gakonst 

I checked to change the `abi_str`  in  case that it starts with `{`. 

Patch:
diff --git a/ethers-contract/ethers-contract-abigen/src/contract.rs b/ethers-contract/ethers-contract-abigen/src/contract.rs
index b47c8d50..42c1feba 100644
--- a/ethers-contract/ethers-contract-abigen/src/contract.rs
+++ b/ethers-contract/ethers-contract-abigen/src/contract.rs
@@ -152,7 +152,7 @@ impl Context {
     /// Create a context from the code generation arguments.
     pub fn from_abigen(args: Abigen) -> Result<Self> {
         // get the actual ABI string
-        let abi_str =
+        let mut abi_str =
             args.abi_source.get().map_err(|e| anyhow!("failed to get ABI JSON: {}", e))?;
 
         let (abi, human_readable, abi_parser) = parse_abi(&abi_str)?;
@@ -172,6 +172,13 @@ impl Context {
             internal_structs.outputs = abi_parser.outputs.clone();
 
             internal_structs
+        } else if abi_str.starts_with('{') {
+            abi_str = serde_json::to_string(&abi).context("fail to serialize abi to json")?;
+
+            serde_json::from_str::<RawAbi>(&abi_str)
+                .ok()
+                .map(InternalStructs::new)
+                .unwrap_or_default()
         } else {
             serde_json::from_str::<RawAbi>(&abi_str)
                 .ok()


Test patch:
diff --git a/ethers-contract/tests/abigen.rs b/ethers-contract/tests/abigen.rs
index a4647be7..556879a1 100644
--- a/ethers-contract/tests/abigen.rs
+++ b/ethers-contract/tests/abigen.rs
@@ -25,6 +25,11 @@ fn can_gen_human_readable() {
     assert_eq!("ValueChanged(address,string,string)", ValueChangedFilter::abi_signature());
 }
 
+#[test]
+fn can_gen_not_human_readable() {
+    abigen!(VerifierAbiHardhatContract, "./tests/solidity-contracts/verifier_abi_hardhat.json");
+}
+
 #[test]
 fn can_gen_human_readable_multiple() {
     abigen!(