Staff / expert · Blockchain infrastructure
A signing service can sign the wrong valid transaction
An external signer securely stores the key, but a caller can submit any chain, destination and amount. Is key custody enough?
Try explaining this aloud before opening the answer. State your assumptions and trace a boundary case.
package main
import (
"fmt"
"math/big"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
)
func main() {
to := common.HexToAddress("0x0000000000000000000000000000000000000001")
tx := types.NewTx(&types.DynamicFeeTx{ChainID: big.NewInt(1337), Nonce: 7, GasTipCap: big.NewInt(1), GasFeeCap: big.NewInt(2), Gas: 21000, To: &to, Value: big.NewInt(1)})
// Unsigned local teaching intent; no key, signer or broadcast is used.
fmt.Println(tx.ChainId(), tx.Nonce(), tx.Value())
}Reveal a strong answer
A signing key is authority, not an ordinary configuration string. An RPC URL, ABI helper or generic retry function should not automatically receive it. Separate construction and policy validation from key custody, bind transactions to the intended chain, and record what was approved without logging private keys or seed material. Read-only blockchain work does not require a signer at all.
Use reviewed protocol signing libraries and choose custody appropriate to the threat model, such as a tightly scoped external signer, keystore or hardware-backed process. Plan key rotation, backup, access control and audit records. Off-chain signed messages need domain separation, intended action, expiry and replay protection too; an address recovered from a signature does not automatically prove authorization for every action. The unsigned intent carries a chain ID, nonce, destination, value and distinct fee fields. Constructing it does not authorize or broadcast anything, and the tiny fee values are illustration only. A signer boundary must validate the actual chain, destination, function arguments, amount and fee ceilings against an explicit policy before signing.
Do not invent cryptographic signing or log seed phrases for debugging. Ethereum’s historical Keccak-256 and standardized SHA3-256 are different functions; substituting one silently changes hashes. Chain-bound transaction signatures do not solve every cross-contract or off-chain replay. Test rejection of wrong chain, modified destination, excessive fees, duplicate intent and an unavailable signer without sending real funds.
Common trap
A correctly signed transaction can still be the wrong transaction for the business and network.
Try it
Define an intent-validation policy, audit record, chain/domain binding, limits and rejection cases without embedding any production key.
Worked solution
Secure custody reduces key exposure but does not validate business intent. The signer boundary or an equally trusted approval boundary must enforce the intended chain, destination/function, amount, nonce identity and fee ceilings. Off-chain messages also need action/domain, expiry and replay policy. Use reviewed protocol primitives, keep key material out of logs and plan rotation and recovery. Signature recovery alone does not grant permission to every action.
Change the constraint
Which audit fields prove what was approved without exposing the signing key or seed?
How did you do?
Self-assessment, not a compiler pass or interview score. Explain the reasoning unaided before marking understood.
Not marked. Progress stays on this browser, separate from course completion.
Primary references
Checked 2026-10-28. Use documentation for your pinned runtime, driver and tool version.