feat(contract, abigen): support Hardhat ABI format (#478)
This commit is contained in:
parent
a9157e1543
commit
4036f45f3d
|
@ -205,6 +205,7 @@ mod tests {
|
||||||
let params = vec![Param {
|
let params = vec![Param {
|
||||||
name: "arg_a".to_string(),
|
name: "arg_a".to_string(),
|
||||||
kind: ParamType::Address,
|
kind: ParamType::Address,
|
||||||
|
internal_type: None,
|
||||||
}];
|
}];
|
||||||
let token_stream = expand_inputs_call_arg(¶ms);
|
let token_stream = expand_inputs_call_arg(¶ms);
|
||||||
assert_eq!(token_stream.to_string(), "arg_a");
|
assert_eq!(token_stream.to_string(), "arg_a");
|
||||||
|
@ -214,10 +215,12 @@ mod tests {
|
||||||
Param {
|
Param {
|
||||||
name: "arg_a".to_string(),
|
name: "arg_a".to_string(),
|
||||||
kind: ParamType::Address,
|
kind: ParamType::Address,
|
||||||
|
internal_type: None,
|
||||||
},
|
},
|
||||||
Param {
|
Param {
|
||||||
name: "arg_b".to_string(),
|
name: "arg_b".to_string(),
|
||||||
kind: ParamType::Uint(256usize),
|
kind: ParamType::Uint(256usize),
|
||||||
|
internal_type: None,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
let token_stream = expand_inputs_call_arg(¶ms);
|
let token_stream = expand_inputs_call_arg(¶ms);
|
||||||
|
@ -228,14 +231,17 @@ mod tests {
|
||||||
Param {
|
Param {
|
||||||
name: "arg_a".to_string(),
|
name: "arg_a".to_string(),
|
||||||
kind: ParamType::Address,
|
kind: ParamType::Address,
|
||||||
|
internal_type: None,
|
||||||
},
|
},
|
||||||
Param {
|
Param {
|
||||||
name: "arg_b".to_string(),
|
name: "arg_b".to_string(),
|
||||||
kind: ParamType::Uint(128usize),
|
kind: ParamType::Uint(128usize),
|
||||||
|
internal_type: None,
|
||||||
},
|
},
|
||||||
Param {
|
Param {
|
||||||
name: "arg_c".to_string(),
|
name: "arg_c".to_string(),
|
||||||
kind: ParamType::Bool,
|
kind: ParamType::Bool,
|
||||||
|
internal_type: None,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
let token_stream = expand_inputs_call_arg(¶ms);
|
let token_stream = expand_inputs_call_arg(¶ms);
|
||||||
|
@ -256,10 +262,12 @@ mod tests {
|
||||||
Param {
|
Param {
|
||||||
name: "a".to_string(),
|
name: "a".to_string(),
|
||||||
kind: ParamType::Bool,
|
kind: ParamType::Bool,
|
||||||
|
internal_type: None,
|
||||||
},
|
},
|
||||||
Param {
|
Param {
|
||||||
name: "b".to_string(),
|
name: "b".to_string(),
|
||||||
kind: ParamType::Address,
|
kind: ParamType::Address,
|
||||||
|
internal_type: None,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
@ -279,6 +287,7 @@ mod tests {
|
||||||
expand_fn_outputs(&[Param {
|
expand_fn_outputs(&[Param {
|
||||||
name: "a".to_string(),
|
name: "a".to_string(),
|
||||||
kind: ParamType::Bool,
|
kind: ParamType::Bool,
|
||||||
|
internal_type: None,
|
||||||
}])
|
}])
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
{ bool },
|
{ bool },
|
||||||
|
@ -292,10 +301,12 @@ mod tests {
|
||||||
Param {
|
Param {
|
||||||
name: "a".to_string(),
|
name: "a".to_string(),
|
||||||
kind: ParamType::Bool,
|
kind: ParamType::Bool,
|
||||||
|
internal_type: None,
|
||||||
},
|
},
|
||||||
Param {
|
Param {
|
||||||
name: "b".to_string(),
|
name: "b".to_string(),
|
||||||
kind: ParamType::Address,
|
kind: ParamType::Address,
|
||||||
|
internal_type: None,
|
||||||
},
|
},
|
||||||
],)
|
],)
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
|
|
|
@ -1,10 +1,72 @@
|
||||||
//! This is a basic representation of a contract ABI that does no post processing but contains the raw content of the ABI.
|
//! This is a basic representation of a contract ABI that does no post processing but contains the raw content of the ABI.
|
||||||
|
|
||||||
#![allow(missing_docs)]
|
#![allow(missing_docs)]
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{
|
||||||
|
de::{EnumAccess, Error, MapAccess, SeqAccess, Visitor},
|
||||||
|
Deserialize, Deserializer, Serialize,
|
||||||
|
};
|
||||||
|
|
||||||
/// Contract ABI as a list of items where each item can be a function, constructor or event
|
/// Contract ABI as a list of items where each item can be a function, constructor or event
|
||||||
pub type RawAbi = Vec<Item>;
|
pub struct RawAbi(Vec<Item>);
|
||||||
|
|
||||||
|
impl IntoIterator for RawAbi {
|
||||||
|
type Item = Item;
|
||||||
|
type IntoIter = std::vec::IntoIter<Self::Item>;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn into_iter(self) -> Self::IntoIter {
|
||||||
|
self.0.into_iter()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct RawAbiVisitor;
|
||||||
|
|
||||||
|
impl<'de> Visitor<'de> for RawAbiVisitor {
|
||||||
|
type Value = RawAbi;
|
||||||
|
|
||||||
|
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||||
|
formatter.write_str("a sequence or map with `abi` key")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
|
||||||
|
where
|
||||||
|
A: SeqAccess<'de>,
|
||||||
|
{
|
||||||
|
let mut vec = Vec::new();
|
||||||
|
|
||||||
|
while let Some(element) = seq.next_element()? {
|
||||||
|
vec.push(element);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(RawAbi(vec))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
|
||||||
|
where
|
||||||
|
A: MapAccess<'de>,
|
||||||
|
{
|
||||||
|
let mut vec = None;
|
||||||
|
|
||||||
|
while let Some(key) = map.next_key::<String>()? {
|
||||||
|
if key == "abi" {
|
||||||
|
vec = Some(RawAbi(map.next_value::<Vec<Item>>()?));
|
||||||
|
} else {
|
||||||
|
map.next_value::<serde::de::IgnoredAny>()?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
vec.ok_or_else(|| serde::de::Error::missing_field("abi"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'de> Deserialize<'de> for RawAbi {
|
||||||
|
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||||
|
where
|
||||||
|
D: Deserializer<'de>,
|
||||||
|
{
|
||||||
|
deserializer.deserialize_any(RawAbiVisitor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
|
@ -40,9 +102,17 @@ pub struct Component {
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn can_parse_raw_abi() {
|
fn can_parse_raw_abi() {
|
||||||
const VERIFIER_ABI: &str = include_str!("../../tests/solidity-contracts/verifier_abi.json");
|
const VERIFIER_ABI: &str = include_str!("../../tests/solidity-contracts/verifier_abi.json");
|
||||||
let _ = serde_json::from_str::<RawAbi>(VERIFIER_ABI).unwrap();
|
let _ = serde_json::from_str::<RawAbi>(VERIFIER_ABI).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn can_parse_hardhat_raw_abi() {
|
||||||
|
const VERIFIER_ABI: &str =
|
||||||
|
include_str!("../../tests/solidity-contracts/verifier_abi_hardhat.json");
|
||||||
|
let _ = serde_json::from_str::<RawAbi>(VERIFIER_ABI).unwrap();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,7 +63,7 @@ impl Source {
|
||||||
S: AsRef<str>,
|
S: AsRef<str>,
|
||||||
{
|
{
|
||||||
let source = source.as_ref();
|
let source = source.as_ref();
|
||||||
if source.starts_with('[') {
|
if matches!(source.chars().next(), Some('[' | '{')) {
|
||||||
return Ok(Source::String(source.to_owned()));
|
return Ok(Source::String(source.to_owned()));
|
||||||
}
|
}
|
||||||
let root = env::current_dir()?.canonicalize()?;
|
let root = env::current_dir()?.canonicalize()?;
|
||||||
|
@ -283,5 +283,12 @@ mod tests {
|
||||||
let src = r#"[{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"name","type":"string"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"symbol","type":"string"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"name":"decimals","type":"uint8"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"spender","type":"address"},{"name":"value","type":"uint256"}],"name":"approve","outputs":[{"name":"success","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"totalSupply","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":"success","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"who","type":"address"}],"name":"balanceOf","outputs":[{"name":"balance","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"to","type":"address"},{"name":"value","type":"uint256"}],"name":"transfer","outputs":[{"name":"success","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"owner","type":"address"},{"name":"spender","type":"address"}],"name":"allowance","outputs":[{"name":"remaining","type":"uint256"}],"payable":false,"type":"function"},{"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"},{"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"}]"#;
|
let src = r#"[{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"name","type":"string"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"symbol","type":"string"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"name":"decimals","type":"uint8"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"spender","type":"address"},{"name":"value","type":"uint256"}],"name":"approve","outputs":[{"name":"success","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"totalSupply","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":"success","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"who","type":"address"}],"name":"balanceOf","outputs":[{"name":"balance","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"to","type":"address"},{"name":"value","type":"uint256"}],"name":"transfer","outputs":[{"name":"success","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"owner","type":"address"},{"name":"spender","type":"address"}],"name":"allowance","outputs":[{"name":"remaining","type":"uint256"}],"payable":false,"type":"function"},{"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"},{"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"}]"#;
|
||||||
let parsed = Source::parse(src).unwrap();
|
let parsed = Source::parse(src).unwrap();
|
||||||
assert_eq!(parsed, Source::String(src.to_owned()));
|
assert_eq!(parsed, Source::String(src.to_owned()));
|
||||||
|
|
||||||
|
let hardhat_src = format!(
|
||||||
|
r#"{{"_format": "hh-sol-artifact-1", "contractName": "Verifier", "sourceName": "contracts/verifier.sol", "abi": {}, "bytecode": "0x", "deployedBytecode": "0x", "linkReferences": {{}}, "deployedLinkReferences": {{}}}}"#,
|
||||||
|
src,
|
||||||
|
);
|
||||||
|
let hardhat_parsed = Source::parse(&hardhat_src).unwrap();
|
||||||
|
assert_eq!(hardhat_parsed, Source::String(hardhat_src));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,185 @@
|
||||||
|
{
|
||||||
|
"_format": "hh-sol-artifact-1",
|
||||||
|
"contractName": "Verifier",
|
||||||
|
"sourceName": "contracts/verifier.sol",
|
||||||
|
"abi": [
|
||||||
|
{
|
||||||
|
"inputs": [],
|
||||||
|
"stateMutability": "nonpayable",
|
||||||
|
"type": "constructor"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"internalType": "uint256[]",
|
||||||
|
"name": "input",
|
||||||
|
"type": "uint256[]"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"components": [
|
||||||
|
{
|
||||||
|
"components": [
|
||||||
|
{
|
||||||
|
"internalType": "uint256",
|
||||||
|
"name": "X",
|
||||||
|
"type": "uint256"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"internalType": "uint256",
|
||||||
|
"name": "Y",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"internalType": "struct Pairing.G1Point",
|
||||||
|
"name": "A",
|
||||||
|
"type": "tuple"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"components": [
|
||||||
|
{
|
||||||
|
"internalType": "uint256[2]",
|
||||||
|
"name": "X",
|
||||||
|
"type": "uint256[2]"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"internalType": "uint256[2]",
|
||||||
|
"name": "Y",
|
||||||
|
"type": "uint256[2]"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"internalType": "struct Pairing.G2Point",
|
||||||
|
"name": "B",
|
||||||
|
"type": "tuple"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"components": [
|
||||||
|
{
|
||||||
|
"internalType": "uint256",
|
||||||
|
"name": "X",
|
||||||
|
"type": "uint256"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"internalType": "uint256",
|
||||||
|
"name": "Y",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"internalType": "struct Pairing.G1Point",
|
||||||
|
"name": "C",
|
||||||
|
"type": "tuple"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"internalType": "struct Verifier.Proof",
|
||||||
|
"name": "proof",
|
||||||
|
"type": "tuple"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"components": [
|
||||||
|
{
|
||||||
|
"components": [
|
||||||
|
{
|
||||||
|
"internalType": "uint256",
|
||||||
|
"name": "X",
|
||||||
|
"type": "uint256"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"internalType": "uint256",
|
||||||
|
"name": "Y",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"internalType": "struct Pairing.G1Point",
|
||||||
|
"name": "alfa1",
|
||||||
|
"type": "tuple"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"components": [
|
||||||
|
{
|
||||||
|
"internalType": "uint256[2]",
|
||||||
|
"name": "X",
|
||||||
|
"type": "uint256[2]"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"internalType": "uint256[2]",
|
||||||
|
"name": "Y",
|
||||||
|
"type": "uint256[2]"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"internalType": "struct Pairing.G2Point",
|
||||||
|
"name": "beta2",
|
||||||
|
"type": "tuple"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"components": [
|
||||||
|
{
|
||||||
|
"internalType": "uint256[2]",
|
||||||
|
"name": "X",
|
||||||
|
"type": "uint256[2]"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"internalType": "uint256[2]",
|
||||||
|
"name": "Y",
|
||||||
|
"type": "uint256[2]"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"internalType": "struct Pairing.G2Point",
|
||||||
|
"name": "gamma2",
|
||||||
|
"type": "tuple"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"components": [
|
||||||
|
{
|
||||||
|
"internalType": "uint256[2]",
|
||||||
|
"name": "X",
|
||||||
|
"type": "uint256[2]"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"internalType": "uint256[2]",
|
||||||
|
"name": "Y",
|
||||||
|
"type": "uint256[2]"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"internalType": "struct Pairing.G2Point",
|
||||||
|
"name": "delta2",
|
||||||
|
"type": "tuple"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"components": [
|
||||||
|
{
|
||||||
|
"internalType": "uint256",
|
||||||
|
"name": "X",
|
||||||
|
"type": "uint256"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"internalType": "uint256",
|
||||||
|
"name": "Y",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"internalType": "struct Pairing.G1Point[]",
|
||||||
|
"name": "IC",
|
||||||
|
"type": "tuple[]"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"internalType": "struct Verifier.VerifyingKey",
|
||||||
|
"name": "vk",
|
||||||
|
"type": "tuple"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "verify",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"internalType": "bool",
|
||||||
|
"name": "",
|
||||||
|
"type": "bool"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"bytecode": "0x",
|
||||||
|
"deployedBytecode": "0x",
|
||||||
|
"linkReferences": {},
|
||||||
|
"deployedLinkReferences": {}
|
||||||
|
}
|
Loading…
Reference in New Issue