Security and money safety
A device that holds a persistent key and will sign on request is a target. BoAT MER refuses first, and this chapter covers the part that is yours to get right.
What the buyer refuses to sign#
Before any signature is produced, the buyer engine rejects a slice with:
- a zero payee address
- a slice ID that does not increase
- a rate that does not match the accepted offer
- a zero amount
- reported power below the billing floor
- a validity window that is too short
- a cumulative session cap that would be exceeded
- a nonce it has already seen — the replay guard rolls over when full, and the session cap keeps counting across the rollover
Rate ceilings and thresholds are your configuration, not library policy. Set them to the smallest values your application can work with, not the largest it can tolerate.
Integration rules#
Approval in your process is not a technical control
A human click or a review queue sits above the transport. If the transport that carries signing commands is open, a request can reach the device without passing through it. The control has to be at or below the layer the request arrives on.
Do not blind-sign a bare digest
Signing any 32 bytes you are handed makes the device a signing oracle. Sign structured, parseable intent instead — EIP-712 with a domain, as the boat_nano_* path does — so a signature made in one context cannot be reinterpreted in another.
Authenticate the command channel
Whatever carries signing requests — MQTT, HTTP, BLE — should require credentials, and only the one service that drives the device should be able to publish to its signing command. Devices publish telemetry and subscribe to commands; they do not publish commands.
Let each party sign its own intent
In the slice flow the buyer signs its own authorization and the seller signs nothing — there is no oracle to abuse. A design where one device signs a digest computed by someone else is oracle-prone by nature.
Custody stops theft, not trickery
Keeping the key on the chip means it cannot be taken. It does not stop the device being asked to sign the wrong thing. Those are different threats and need different controls.
Bound what a compromise can cost
Use the session cap, rate ceiling, minimum validity window and monotonic slice counter, and keep them tight.
The EIP-712 domain trap#
Most "the signature verifies locally but settlement rejects it" bugs are a wrong domain — for example signing under the USDC token domain when the verifier expects the Circle Gateway domain. The signature is valid; it is valid for something else. eip712-domain-trap.md lists the mistakes that produce valid-looking signatures.