Skip to content

fix: EIP-1559 fee display and RLP integer encoding#236

Open
BitHighlander wants to merge 4 commits into
developfrom
fix/eip1559
Open

fix: EIP-1559 fee display and RLP integer encoding#236
BitHighlander wants to merge 4 commits into
developfrom
fix/eip1559

Conversation

@BitHighlander

Copy link
Copy Markdown
Owner

Summary

Two EIP-1559 correctness fixes:

Fee display: formatEthereumFeeEIP1559 was adding max_priority_fee_per_gas on top of max_fee_per_gas before multiplying by gas_limit. The priority fee is a tip contained within max_fee, not additive — displayed fee was overstated.

RLP encoding: Integer fields (nonce, gas, value, fees) must not carry leading zero bytes per the Ethereum yellow paper. hash_rlp_field preserved them verbatim. Added hash_rlp_bytes_stripped() and applied it to all integer fields. The to address field is intentionally unchanged.

Test plan

  • CI green
  • EIP-1559 tx fee displays correctly (max_fee_per_gas × gas_limit)
  • Signed tx recovers correct signer on Base/Arbitrum/Avalanche

…_gas field

Bug 1 (display): formatEthereumFeeEIP1559 computed fee rate as
max_fee_per_gas + max_priority_fee_per_gas before multiplying by
gas_limit. The priority fee is a tip contained within max_fee_per_gas,
not additive — the user's maximum cost is max_fee_per_gas * gas_limit.
This caused the displayed fee to be overstated.

Bug 2 (signing): max_priority_fee_per_gas was only included in the
RLP length calculation and hash when has_max_priority_fee_per_gas was
set. EIP-1559 always requires this field (9-field list). If the host
omitted it, the firmware produced an 8-field RLP list — valid length
header but wrong field count — resulting in a transaction that would
be rejected at broadcast. nanopb zero-initialises unset fields, so
removing the guard is safe: size=0 encodes as 0x80 (integer zero).
…llow paper

RLP-encoded integer fields (nonce, gas, value, fees) must not carry leading
zero bytes. hash_rlp_field preserved them verbatim, producing non-canonical
transactions that are rejected on broadcast for any field whose big-endian
representation has a leading zero (common for small nonces, zero values, etc.).

Added hash_rlp_bytes_stripped() and applied it to nonce, gas_price, gas_limit,
max_fee_per_gas, max_priority_fee_per_gas, and value. The to address field
is intentionally left using hash_rlp_field — addresses are not integers.
hash_rlp_field(..., sizeof(uint8_t)) only hashed the low byte of chain_id
(little-endian uint32). Chain IDs above 255 — Base (8453), Arbitrum (42161),
Avalanche C-Chain (43114) — were all hashed as their low byte only, producing
a signature that recovers the wrong signer on these networks.

Use hash_rlp_number(chain_id) which converts to big-endian and strips
leading zeros, matching the Ethereum yellow paper.
deps/device-protocol → 8ef74da (feat(ripple): memo + THORChain routing)
deps/python-keepkey  → bf870e6 (7.14.2: XRP memo + EVM depositWithExpiry + msg-signing)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant