diff --git a/Cargo.lock b/Cargo.lock index 88000ee4de..877531836c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -610,6 +610,7 @@ dependencies = [ "frame-benchmarking", "frame-support", "frame-system", + "hex", "pallet-evm", "pallet-liquidity-pools-gateway", "parity-scale-codec 3.6.4", diff --git a/pallets/liquidity-pools-gateway/axelar-gateway-precompile/Cargo.toml b/pallets/liquidity-pools-gateway/axelar-gateway-precompile/Cargo.toml index 63a59815c0..52dacaed9b 100644 --- a/pallets/liquidity-pools-gateway/axelar-gateway-precompile/Cargo.toml +++ b/pallets/liquidity-pools-gateway/axelar-gateway-precompile/Cargo.toml @@ -6,6 +6,7 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +hex = { version = "0.4.3", default-features = false } codec = { package = "parity-scale-codec", version = "3.0.0", features = ["derive"], default-features = false } frame-support = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.38" } frame-system = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.38" } diff --git a/pallets/liquidity-pools-gateway/axelar-gateway-precompile/src/lib.rs b/pallets/liquidity-pools-gateway/axelar-gateway-precompile/src/lib.rs index 1468d434b3..f1ce23e93a 100644 --- a/pallets/liquidity-pools-gateway/axelar-gateway-precompile/src/lib.rs +++ b/pallets/liquidity-pools-gateway/axelar-gateway-precompile/src/lib.rs @@ -26,7 +26,8 @@ use sp_std::vec::Vec; pub use crate::weights::WeightInfo; pub const MAX_SOURCE_CHAIN_BYTES: u32 = 128; -pub const MAX_SOURCE_ADDRESS_BYTES: u32 = 32; +// Ensure we allow enough to support a hex encoded address with the `0x` prefix. +pub const MAX_SOURCE_ADDRESS_BYTES: u32 = 42; pub const MAX_TOKEN_SYMBOL_BYTES: u32 = 32; pub const MAX_PAYLOAD_BYTES: u32 = 1024; pub const PREFIX_CONTRACT_CALL_APPROVED: [u8; 32] = keccak256!("contract-call-approved"); @@ -273,8 +274,13 @@ where exit_status: ExitError::Other("converter for source not found".into()), })?; + let source_address_bytes = + get_source_address_bytes(source_address).ok_or(PrecompileFailure::Error { + exit_status: ExitError::Other("invalid source address".into()), + })?; + let domain_address = domain_converter - .try_convert(source_address.as_bytes()) + .try_convert(source_address_bytes.as_slice()) .ok_or(PrecompileFailure::Error { exit_status: ExitError::Other("account bytes mismatch for domain".into()), })?; @@ -320,3 +326,55 @@ where Ok(()) } } + +const EXPECTED_SOURCE_ADDRESS_SIZE: usize = 20; +const HEX_PREFIX: &str = "0x"; + +pub(crate) fn get_source_address_bytes( + source_address: String, +) -> Option> { + if source_address.as_bytes().len() == EXPECTED_SOURCE_ADDRESS_SIZE { + return Some(source_address.as_bytes().to_vec()); + } + + let str = source_address.as_str().ok()?; + + // Attempt to hex decode source address. + return match hex::decode(str.clone()) { + Ok(res) => Some(res), + Err(_) => { + // Strip 0x prefix. + let res = str.strip_prefix(HEX_PREFIX)?; + + hex::decode(res).ok() + } + }; +} + +#[cfg(test)] +mod tests { + use sp_core::H160; + + use super::*; + + #[test] + fn get_source_address_bytes_works() { + let hash = H160::from_low_u64_be(1); + + let str = String::::from(hash.as_fixed_bytes().to_vec()); + + get_source_address_bytes(str).expect("address bytes from H160 works"); + + let str = String::::from( + "d47ed02acbbb66ee8a3fe0275bd98add0aa607c3".to_string(), + ); + + get_source_address_bytes(str).expect("address bytes from un-prefixed hex works"); + + let str = String::::from( + "0xd47ed02acbbb66ee8a3fe0275bd98add0aa607c3".to_string(), + ); + + get_source_address_bytes(str).expect("address bytes from prefixed hex works"); + } +}