Migrate the deposit_contract crate to alloy (#8139)

https://github.com/sigp/lighthouse/issues/6022


  Switches the `deposit_contract` crate to use the `alloy` ecosystem and removes the dependency on `ethabi`


Co-Authored-By: Mac L <mjladson@pm.me>
This commit is contained in:
Mac L
2025-11-11 10:52:46 +04:00
committed by GitHub
parent b3df0d1985
commit 11d1f60753
4 changed files with 148 additions and 262 deletions

View File

@@ -1,23 +1,44 @@
use ethabi::{Contract, Token};
use alloy_dyn_abi::{DynSolValue, JsonAbiExt};
use alloy_json_abi::JsonAbi;
use alloy_primitives::FixedBytes;
use ssz::{Decode, DecodeError as SszDecodeError, Encode};
use tree_hash::TreeHash;
use types::{DepositData, Hash256, PublicKeyBytes, SignatureBytes};
pub use ethabi::Error;
#[derive(Debug)]
pub enum DecodeError {
EthabiError(ethabi::Error),
pub enum Error {
AlloyCoreError(alloy_json_abi::Error),
SerdeJsonError(serde_json::Error),
DynAbiError(alloy_dyn_abi::Error),
SszDecodeError(SszDecodeError),
FunctionNotFound,
MissingField,
UnableToGetBytes,
MissingToken,
InadequateBytes,
}
impl From<ethabi::Error> for DecodeError {
fn from(e: ethabi::Error) -> DecodeError {
DecodeError::EthabiError(e)
impl From<alloy_json_abi::Error> for Error {
fn from(e: alloy_json_abi::Error) -> Error {
Error::AlloyCoreError(e)
}
}
impl From<serde_json::Error> for Error {
fn from(e: serde_json::Error) -> Error {
Error::SerdeJsonError(e)
}
}
impl From<alloy_dyn_abi::Error> for Error {
fn from(e: alloy_dyn_abi::Error) -> Error {
Error::DynAbiError(e)
}
}
impl From<SszDecodeError> for Error {
fn from(e: SszDecodeError) -> Error {
Error::SszDecodeError(e)
}
}
@@ -36,47 +57,57 @@ pub mod testnet {
pub fn encode_eth1_tx_data(deposit_data: &DepositData) -> Result<Vec<u8>, Error> {
let params = vec![
Token::Bytes(deposit_data.pubkey.as_ssz_bytes()),
Token::Bytes(deposit_data.withdrawal_credentials.as_ssz_bytes()),
Token::Bytes(deposit_data.signature.as_ssz_bytes()),
Token::FixedBytes(deposit_data.tree_hash_root().as_ssz_bytes()),
DynSolValue::Bytes(deposit_data.pubkey.as_ssz_bytes()),
DynSolValue::Bytes(deposit_data.withdrawal_credentials.as_ssz_bytes()),
DynSolValue::Bytes(deposit_data.signature.as_ssz_bytes()),
DynSolValue::FixedBytes(
FixedBytes::<32>::from_slice(&deposit_data.tree_hash_root().as_ssz_bytes()),
32,
),
];
// Here we make an assumption that the `crate::testnet::ABI` has a superset of the features of
// the crate::ABI`.
let abi = Contract::load(ABI)?;
let function = abi.function("deposit")?;
function.encode_input(&params)
let abi: JsonAbi = serde_json::from_slice(ABI)?;
let function = abi
.function("deposit")
.and_then(|functions| functions.first())
.ok_or(Error::FunctionNotFound)?;
function
.abi_encode_input(&params)
.map_err(Error::DynAbiError)
}
pub fn decode_eth1_tx_data(
bytes: &[u8],
amount: u64,
) -> Result<(DepositData, Hash256), DecodeError> {
let abi = Contract::load(ABI)?;
let function = abi.function("deposit")?;
let mut tokens = function.decode_input(bytes.get(4..).ok_or(DecodeError::InadequateBytes)?)?;
pub fn decode_eth1_tx_data(bytes: &[u8], amount: u64) -> Result<(DepositData, Hash256), Error> {
let abi: JsonAbi = serde_json::from_slice(ABI)?;
let function = abi
.function("deposit")
.and_then(|functions| functions.first())
.ok_or(Error::FunctionNotFound)?;
let input_data = bytes.get(4..).ok_or(Error::InadequateBytes)?;
let mut tokens = function.abi_decode_input(input_data)?;
macro_rules! decode_token {
($type: ty, $to_fn: ident) => {
<$type>::from_ssz_bytes(
&tokens
.pop()
.ok_or_else(|| DecodeError::MissingToken)?
.$to_fn()
.ok_or_else(|| DecodeError::UnableToGetBytes)?,
)
.map_err(DecodeError::SszDecodeError)?
};
($type: ty) => {{
let token = tokens.pop().ok_or(Error::MissingToken)?;
let bytes_data = match token {
DynSolValue::Bytes(b) => b,
DynSolValue::FixedBytes(b, _) => b.to_vec(),
_ => return Err(Error::UnableToGetBytes),
};
<$type>::from_ssz_bytes(&bytes_data)?
}};
}
let root = decode_token!(Hash256, into_fixed_bytes);
let root = decode_token!(Hash256);
let deposit_data = DepositData {
amount,
signature: decode_token!(SignatureBytes, into_bytes),
withdrawal_credentials: decode_token!(Hash256, into_bytes),
pubkey: decode_token!(PublicKeyBytes, into_bytes),
signature: decode_token!(SignatureBytes),
withdrawal_credentials: decode_token!(Hash256),
pubkey: decode_token!(PublicKeyBytes),
};
Ok((deposit_data, root))