Summary
verify_smart_contract_based_signature resolves the contract address with Address::parse_checksummed(contract_address, None), which enforces EIP-55 and errors on a plain-lowercase address. Charon resolves it with common.HexToAddress — fully lenient: any casing, optional 0x, never errors.
The address originates from a cluster-definition operator address field, which is commonly stored lowercase. Such a definition verifies in Charon but fails in Pluto with a parse error before the ERC-1271 call ever fires — breaking signature verification for smart-contract (ERC-1271) operators.
Proposed change
Parse leniently (e.g. Address::from_str), accepting any casing. Keep erroring on non-hex or wrong-length input — Go's HexToAddress never errors (it zero-pads/truncates), and matching that exactly would silently accept garbage; document the residual strictness as a deliberate choice. Add a test that a lowercase address reaches the ERC-1271 call, and one that a checksummed mixed-case address still works.
While here, backfill the crate's test surface (a single test today — the empty-address noop): the ERC-1271 MAGIC_VALUE constant and both isValidSignature true/false branches (mirroring Charon's TestMagicValue/TestERC1271Implementation), the CallTimeout path, and EthClient::new with a non-empty endpoint.
Acceptance
A lowercase (non-checksummed) operator address verifies identically to Charon; malformed addresses still error.
Summary
verify_smart_contract_based_signatureresolves the contract address withAddress::parse_checksummed(contract_address, None), which enforces EIP-55 and errors on a plain-lowercase address. Charon resolves it withcommon.HexToAddress— fully lenient: any casing, optional0x, never errors.The address originates from a cluster-definition operator
addressfield, which is commonly stored lowercase. Such a definition verifies in Charon but fails in Pluto with a parse error before the ERC-1271 call ever fires — breaking signature verification for smart-contract (ERC-1271) operators.Proposed change
Parse leniently (e.g.
Address::from_str), accepting any casing. Keep erroring on non-hex or wrong-length input — Go'sHexToAddressnever errors (it zero-pads/truncates), and matching that exactly would silently accept garbage; document the residual strictness as a deliberate choice. Add a test that a lowercase address reaches the ERC-1271 call, and one that a checksummed mixed-case address still works.While here, backfill the crate's test surface (a single test today — the empty-address noop): the ERC-1271
MAGIC_VALUEconstant and bothisValidSignaturetrue/false branches (mirroring Charon'sTestMagicValue/TestERC1271Implementation), theCallTimeoutpath, andEthClient::newwith a non-empty endpoint.Acceptance
A lowercase (non-checksummed) operator address verifies identically to Charon; malformed addresses still error.