feat: support parsing bytecode from evm object (#2024)
This commit is contained in:
parent
2aa7bc3b99
commit
01d3e4310f
|
@ -117,6 +117,26 @@ pub enum JsonAbi {
|
||||||
Array(RawAbi),
|
Array(RawAbi),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// === impl JsonAbi ===
|
||||||
|
|
||||||
|
impl JsonAbi {
|
||||||
|
/// Returns the bytecode object
|
||||||
|
pub fn bytecode(&self) -> Option<Bytes> {
|
||||||
|
match self {
|
||||||
|
JsonAbi::Object(abi) => abi.bytecode.clone(),
|
||||||
|
JsonAbi::Array(_) => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the deployed bytecode object
|
||||||
|
pub fn deployed_bytecode(&self) -> Option<Bytes> {
|
||||||
|
match self {
|
||||||
|
JsonAbi::Object(abi) => abi.deployed_bytecode.clone(),
|
||||||
|
JsonAbi::Array(_) => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn deserialize_abi_array<'de, D>(deserializer: D) -> Result<RawAbi, D::Error>
|
fn deserialize_abi_array<'de, D>(deserializer: D) -> Result<RawAbi, D::Error>
|
||||||
where
|
where
|
||||||
D: Deserializer<'de>,
|
D: Deserializer<'de>,
|
||||||
|
@ -128,6 +148,7 @@ where
|
||||||
pub struct AbiObject {
|
pub struct AbiObject {
|
||||||
pub abi: RawAbi,
|
pub abi: RawAbi,
|
||||||
pub bytecode: Option<Bytes>,
|
pub bytecode: Option<Bytes>,
|
||||||
|
pub deployed_bytecode: Option<Bytes>,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct AbiObjectVisitor;
|
struct AbiObjectVisitor;
|
||||||
|
@ -145,6 +166,7 @@ impl<'de> Visitor<'de> for AbiObjectVisitor {
|
||||||
{
|
{
|
||||||
let mut abi = None;
|
let mut abi = None;
|
||||||
let mut bytecode = None;
|
let mut bytecode = None;
|
||||||
|
let mut deployed_bytecode = None;
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
#[serde(untagged)]
|
#[serde(untagged)]
|
||||||
|
@ -153,6 +175,28 @@ impl<'de> Visitor<'de> for AbiObjectVisitor {
|
||||||
Bytes(Bytes),
|
Bytes(Bytes),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Bytecode {
|
||||||
|
fn into_bytes(self) -> Option<Bytes> {
|
||||||
|
let bytecode = match self {
|
||||||
|
Bytecode::Object { object } => object,
|
||||||
|
Bytecode::Bytes(bytes) => bytes,
|
||||||
|
};
|
||||||
|
if bytecode.is_empty() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(bytecode)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// represents nested bytecode objects of the `evm` value
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
struct EvmObj {
|
||||||
|
bytecode: Option<Bytecode>,
|
||||||
|
#[serde(rename = "deployedBytecode")]
|
||||||
|
deployed_bytecode: Option<Bytecode>,
|
||||||
|
}
|
||||||
|
|
||||||
struct DeserializeBytes(Bytes);
|
struct DeserializeBytes(Bytes);
|
||||||
|
|
||||||
impl<'de> Deserialize<'de> for DeserializeBytes {
|
impl<'de> Deserialize<'de> for DeserializeBytes {
|
||||||
|
@ -169,15 +213,18 @@ impl<'de> Visitor<'de> for AbiObjectVisitor {
|
||||||
"abi" => {
|
"abi" => {
|
||||||
abi = Some(RawAbi(map.next_value::<Vec<Item>>()?));
|
abi = Some(RawAbi(map.next_value::<Vec<Item>>()?));
|
||||||
}
|
}
|
||||||
|
"evm" => {
|
||||||
|
if let Ok(evm) = map.next_value::<EvmObj>() {
|
||||||
|
bytecode = evm.bytecode.and_then(|b| b.into_bytes());
|
||||||
|
deployed_bytecode = evm.deployed_bytecode.and_then(|b| b.into_bytes())
|
||||||
|
}
|
||||||
|
}
|
||||||
"bytecode" | "byteCode" => {
|
"bytecode" | "byteCode" => {
|
||||||
bytecode = map
|
bytecode = map.next_value::<Bytecode>().ok().and_then(|b| b.into_bytes());
|
||||||
.next_value::<Bytecode>()
|
}
|
||||||
.ok()
|
"deployedbytecode" | "deployedBytecode" => {
|
||||||
.map(|obj| match obj {
|
deployed_bytecode =
|
||||||
Bytecode::Object { object } => object,
|
map.next_value::<Bytecode>().ok().and_then(|b| b.into_bytes());
|
||||||
Bytecode::Bytes(bytes) => bytes,
|
|
||||||
})
|
|
||||||
.filter(|bytecode| !bytecode.0.is_empty());
|
|
||||||
}
|
}
|
||||||
"bin" => {
|
"bin" => {
|
||||||
bytecode = map
|
bytecode = map
|
||||||
|
@ -186,6 +233,13 @@ impl<'de> Visitor<'de> for AbiObjectVisitor {
|
||||||
.map(|b| b.0)
|
.map(|b| b.0)
|
||||||
.filter(|b| !b.0.is_empty());
|
.filter(|b| !b.0.is_empty());
|
||||||
}
|
}
|
||||||
|
"runtimebin" | "runtimeBin" => {
|
||||||
|
deployed_bytecode = map
|
||||||
|
.next_value::<DeserializeBytes>()
|
||||||
|
.ok()
|
||||||
|
.map(|b| b.0)
|
||||||
|
.filter(|b| !b.0.is_empty());
|
||||||
|
}
|
||||||
_ => {
|
_ => {
|
||||||
map.next_value::<serde::de::IgnoredAny>()?;
|
map.next_value::<serde::de::IgnoredAny>()?;
|
||||||
}
|
}
|
||||||
|
@ -193,7 +247,7 @@ impl<'de> Visitor<'de> for AbiObjectVisitor {
|
||||||
}
|
}
|
||||||
|
|
||||||
let abi = abi.ok_or_else(|| serde::de::Error::missing_field("abi"))?;
|
let abi = abi.ok_or_else(|| serde::de::Error::missing_field("abi"))?;
|
||||||
Ok(AbiObject { abi, bytecode })
|
Ok(AbiObject { abi, bytecode, deployed_bytecode })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -316,4 +370,18 @@ mod tests {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn can_parse_deployed_bytecode() {
|
||||||
|
let artifact = include_str!("../../testdata/solc-obj.json");
|
||||||
|
match serde_json::from_str::<JsonAbi>(artifact).unwrap() {
|
||||||
|
JsonAbi::Object(abi) => {
|
||||||
|
assert!(abi.bytecode.is_some());
|
||||||
|
assert!(abi.deployed_bytecode.is_some());
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
panic!("expected abi object")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue