Features
- Deterministic JSON-RPC filtering with lowercase method matching and batch rejection.
- Fast proxy built on Axum that forwards permissible payloads untouched to the upstream node.
- TOML + CLI configuration merger with sensible defaults for bind address and upstream URL.
- Structured tracing with INFO/WARN/ERROR logs for start-up, blocked calls, and shutdown events.
Installation
NOTE
vetois not yet published to crates.io. Install from source while we stabilize the interface.
# Install the CLI into your cargo bin from the workspace.
# Or build a release binary in target/release/veto.
veto targets Rust 1.88+ and ships with comprehensive tests. Run cargo test in the workspace to validate a local build.
Configuration
veto reads configuration from a TOML file (defaults to .veto.toml) and merges it with CLI overrides. Defaults resolve to 0.0.0.0:8546 for the bind address and http://127.0.0.1:8545 for the upstream. All method names are normalized to lowercase before being enforced, and duplicate entries collapse automatically.
# .veto.toml
= "0.0.0.0:8546"
= "http://127.0.0.1:8545"
= [
"anvil_setBalance",
"anvil_setNonce",
"evm_increaseTime",
"eth_sendTransaction"
]
TIP
You can provide the same values at runtime with flags such as
--bind-address,--upstream-url, or--blocked-methods eth_sendtransaction,personal_sign. CLI flags always take precedence over file values.
The proxy refuses batch JSON-RPC requests and responds with a JSON-RPC error payload when a blocked method is invoked.
Docker
A multi-stage Dockerfile is included for building slim runtime images.
FROM ghcr.io/refcell/veto-builder:latest AS veto
FROM debian:bookworm-slim
COPY --from=veto /veto /usr/local/bin/veto
ENTRYPOINT ["/usr/local/bin/veto"]
When an official image is published it will live at ghcr.io/refcell/veto/veto-builder. Until then you can produce the builder image locally:
# Build the minimal scratch-based builder image containing /veto.
The resulting veto-builder stage only ships the compiled binary, making it ideal for copy-paste into bespoke runtime images.
Usage
Launch the proxy after you have an upstream Anvil (or any Ethereum JSON-RPC) node running:
# start anvil in another terminal
# run veto in front of it
Send RPC traffic to http://127.0.0.1:8546 (or the bind address you configure). Any blocked method receives a deterministic JSON-RPC error response and the event is logged:
# -> { "jsonrpc":"2.0", "error":{ "code":-32601, "message":"Method 'eth_sendTransaction' blocked by veto proxy" }, "id":1 }
All other payloads are forwarded untouched to the upstream node.
Why?
Smart contract testing frequently requires unsafe JSON-RPC helpers (e.g. anvil_setBalance, evm_setNextBlockTimestamp) that must never leak into higher-stakes environments. veto provides:
- A focused allow/deny layer that sits in front of local Anvil or Hardhat instances.
- Hard default blocking lists you can codify per project to de-risk automation.
- Clear audit trails via structured logging so you know when and why a call was denied.
The proxy keeps development workflows flexible while enforcing the guardrails needed for repeatable evaluation setups, CI pipelines, and shared testing infrastructure.
Contributing
Contributions, bug reports, and feature requests are welcome. Please open an issue or PR on GitHub so we can review the change together.