Skip to content

[SEC-131] Enforce local Ethereum transaction expenditure policy#531

Draft
huangminghuang wants to merge 6 commits into
masterfrom
fix/sec-131
Draft

[SEC-131] Enforce local Ethereum transaction expenditure policy#531
huangminghuang wants to merge 6 commits into
masterfrom
fix/sec-131

Conversation

@huangminghuang

@huangminghuang huangminghuang commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Summary

  • enforce a per-client Ethereum transaction policy at the final signing boundary, covering chain id, EIP-1559 priority/max fees, buffered gas limit, and checked gas_limit * max_fee_per_gas + value
  • make the preferred --outpost-ethereum-client-config-file a strict, versioned JSON document that keeps client id, signature-provider id, RPC URL, authoritative chain id, and optional nested policy together
  • apply maximum-uint256 defaults to all four policy caps when transaction_policy is omitted, preserving pre-policy transaction behavior for existing deployments
  • retain --outpost-ethereum-client compatibility; four-field clients use the local chain id, while the original three-field form resolves eth_chainId under one aggregate five-second startup deadline
  • remove the superseded --outpost-ethereum-transaction-policy-file option and replace its example with the unified client configuration
  • use non-truncating uint32 chain ids, canonical uint256 decimal/RPC quantities, checked fee/gas derivations, and full-width EIP-1559 RLP encoding
  • emit structured, sanitized reason/field/observed/allowed diagnostics without exposing RPC credentials, key material, calldata, or signatures

Configuration

Preferred configuration:

{
  "version": 1,
  "clients": [
    {
      "client_id": "eth-mainnet",
      "signature_provider_id": "eth-01",
      "rpc_url": "https://rpc.example.invalid",
      "chain_id": "1",
      "transaction_policy": {
        "max_priority_fee_per_gas_wei": "2000000000",
        "max_fee_per_gas_wei": "100000000000",
        "max_gas_limit": "2000000",
        "max_total_native_cost_wei": "250000000000000000"
      }
    }
  ]
}

transaction_policy is optional. Omitting it sets each cap to 2^256 - 1. Production operators should configure finite caps appropriate to their chain and workload.

Multiple clients are supported for distinct EVM outposts, endpoints, or signers. Same-chain clients are not automatic failover: chain-id lookup fails closed when more than one client matches and the caller does not select a client id.

Enforcement details

  • configured chain ids are canonical decimal strings in 1..UINT32_MAX and are authoritative for replay protection
  • policy limits are positive canonical decimal strings up to uint256
  • rejected transactions are not clamped, signed, or broadcast
  • maxFeePerGas is derived as 2 * baseFeePerGas + maxPriorityFeePerGas; insufficient dynamic headroom reports the formula operands and configured cap
  • multiplication and addition overflow are rejected before total-cost comparison
  • the legacy three-field client form performs bounded startup RPC resolution; unavailable endpoints fail startup without an unbounded wait

Validation

  • complete test_fc: 512 tests passed
  • complete test_outpost_ethereum_client_plugin: 22 tests passed
  • full incremental Release build completed, including nodeop
  • git diff --check clean
  • current-head combined flow-swap-with-underwriting with wire-tools-ts#36: SUCCESS (40 phases, 127 steps, 935.1s); generated config omitted transaction_policy, all four operator daemons used only the unified config option, both ETH→SOL and SOL→ETH settlements completed, and no policy rejection diagnostics were emitted
  • current-head GitHub CI is pending

Dependency

The paired cluster-tool change is Wire-Network/wire-tools-ts#36.

Jira: SEC-131 / WSA-225

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