Skip to content

cow-venue: use alloy primitives instead of byte-array aliases #546

Description

@mfw78

From a question raised on #461: why does order.rs declare pub type U256? Target: cow-venue (L3). Wire format is free to change: nothing has been released to production.

Problem

cow-venue/src/order.rs declares two aliases that shadow well-known alloy primitives with raw byte arrays:

pub type Address = [u8; 20];
pub type U256 = [u8; 32];

U256 in an Ethereum Rust codebase means alloy_primitives::U256, a numeric type with arithmetic, ordering and parsing. This one is a byte array with none of that, so sell_amount: U256 reads as a number that can be operated on and is not. The collision is live inside this same crate: assembly.rs's doctest writes sellAmount: U256::from(1_000u64), which is alloy's U256 in that scope, so one identifier names two different types in two files. Address shadows alloy_primitives::Address identically.

Why the apparent justifications do not hold

  • no_std. Self-imposed rather than required: every target here is wasm32-wasip2, which has full std, and nexum-sdk is already a std crate. It is also hollow, because the default body slice pulls videre-sdk then nexum-sdk, which is std, so the linked artefact carries std regardless. #![no_std] constrains only this crate's own source.
  • borsh. alloy_primitives::U256 is ruint::Uint<256, 4>, and ruint (1.18.0 in the lock) ships a borsh feature. alloy-primitives exposes no passthrough for it, so enable it by declaring ruint directly with features = ["borsh"] and letting cargo unify.
  • A dependency-light body slice. Illusory. nexum-sdk depends on alloy-primitives and alloy-provider non-optionally, and body = ["dep:borsh", "dep:videre-sdk"] reaches nexum-sdk through videre-sdk. alloy-primitives is therefore already unconditionally in the body slice's graph, so marking it optional = true in this crate's manifest saves nothing.

Proposal

  • Replace pub type Address and pub type U256 with alloy_primitives::{Address, U256} in order.rs and its dependents.
  • Enable borsh for ruint with a direct ruint = { version = "1", default-features = false, features = ["borsh"] } dependency.
  • Drop the to_be_bytes / from_be_bytes hops in assembly.rs that exist only to cross the alias boundary.
  • Regenerate tests/vectors/cow-header-goldens.json if the encoding moves. No body-version bump and no #[borsh(with = ...)] byte-preserving adapter is needed: nothing is released, so the wire format may change freely. Doing this before a release is what makes it cheap.

While here

Two things this exposes, worth settling rather than carrying:

  • alloy-primitives being optional = true in this crate is meaningless given the transitive path above. Either drop the optionality or document what it actually gates.
  • #![cfg_attr(not(any(test, feature = "adapter")), no_std)] buys nothing while the crate's own dependencies are std. Decide whether cow-venue is genuinely meant to be no_std-portable, in which case the std dependency chain is the defect, or drop the attribute.

Acceptance criteria

  • No type alias in cow-venue shadows an alloy primitive name.
  • Amounts and addresses are alloy_primitives::U256 and alloy_primitives::Address, borsh-encodable through ruint's feature.
  • Goldens regenerated and the codec round-trips.

Metadata

Metadata

Assignees

No one assigned

    Labels

    component/cow-integrationshepherd:cow / cow-api order submissiondebtCode works but makes future work harder.effort/hoursFew hours. Single PR.p2-annoyingNot broken, but annoying enough to matter.

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions