Key Rotation Has a Data Plane: What Happens to Outstanding Signatures?
Rotating a privileged key feels complete when the old signer disappears from the owner list and the replacement can pass a test transaction. That proves the control plane changed. It does not prove that signed intent created before the change has disappeared.
A relayer may still hold a permit. A market maker may still have an order in an off-chain book. A Safe transaction may already carry several owner signatures. A governance operation may be waiting in a timelock. Each object has its own validator, nonce, deadline and cancellation path. The old key can be gone while one of those objects remains executable.
This is the data plane of key rotation: the inventory of outstanding instructions that can still move assets or change state. A safe cutover has to reconcile that inventory, not merely update an owner set.Owner rotation is complete only after every outstanding action has a disposition.
The first question is not whether the key was removed
Start with a sharper question: what exact verifier will evaluate each outstanding instruction after the cutover?
An EOA signature proves that a specific private key signed a digest. Changing an administrator in another contract does not alter that proof. The action becomes unusable only if the application rejects the recovered address, consumes or invalidates its nonce, reaches its deadline, changes the signing domain or follows another enforced cancellation rule.
A smart contract signature behaves differently. Under ERC-1271, the application asks the signing contract whether a given hash and signature are valid now. That contract can consult current owners, thresholds, time or other state. A signature accepted before an owner change can fail afterward. The reverse is possible too if the wallet's validation logic or configuration changes.
Then there are actions that have crossed the signature boundary already. Once a governance call has been scheduled in a timelock, its future execution is controlled by the timelock state and roles, not by rechecking every signature that helped approve it. Once a permit is submitted and becomes an allowance, rotating the original signer does not erase that allowance. The state transition has already happened.
Those three cases require different remedies. Treating all of them as stale signatures creates a false sense of cancellation.
Four states matter during a rotation
For each signed action, record both the signature state and the action state. A compact four-state vocabulary is enough for most cutovers:
- Unsubmitted. The signed payload exists off-chain, but the verifier has not accepted it.
- Submitted. A transaction carrying the payload is pending or its finality is not yet accepted by the operating policy.
- Materialized. The signed intent has become on-chain state, such as an allowance, queued operation or executed order.
- Disposed. The item is proven expired, invalidated, canceled, executed as intended or replaced under an approved decision.
Do not collapse submitted into materialized. A mempool transaction can be replaced, dropped or included on a different branch. Do not collapse materialized into executed either. A timelock entry is real on-chain state while its target calls remain unexecuted.
The rotation is ready to close only when every item is disposed or assigned to a named owner with a bounded follow-up. Unknown is a valid temporary status. It is safer than declaring an off-chain order canceled because nobody saw it in one interface.
Build the signed-action inventory before the owner change
The inventory is the reusable artifact for this operation. Create one row for every class of signed or queued instruction the retiring key could have influenced. If individual enumeration is practical, record one row per digest. If the population is large, define a provable range such as one nonce lane, one order epoch or one relayer queue snapshot.
Each row should contain:
- Artifact and digest: the human purpose, exact typed data or transaction hash and storage location.
- Signer model: EOA recovery, ERC-1271 contract validation, Safe owner threshold or another explicit scheme.
- Domain: chain ID, verifying contract, application name and version or the exact alternative domain fields.
- Replay boundary: account nonce, keyed nonce, bitmap, order salt, Safe nonce, timelock operation ID or absence of an enforced replay control.
- Time boundary: signed deadline, order expiry, review expiry and the source of time used by the verifier.
- Current action state: unsubmitted, submitted, materialized or disposed, with the observation block or system snapshot.
- Post-rotation validity: expected valid, expected invalid or unknown, plus the function or state read that supports the expectation.
- Cancellation path: exact call, actor, prerequisite and evidence that cancellation took effect.
- Decision: execute before cutover, cancel, let expire, re-sign after cutover or escalate for manual review.
Keep the digest and the decoded meaning together. A hex value alone does not tell an incident responder whether it approves ten tokens, an unlimited allowance, a proxy upgrade or an order with partial fills. A prose description alone cannot prove which bytes were reviewed.
At Pharos Production, the relevant smart-contract engineering scope includes threat modeling, role mapping, testing and deployment runbooks. Applied to key rotation, that service addresses the central problem by binding outstanding signed actions to verifiers and cancellation tests instead of treating an owner-list update as the entire change. This is a mapping to the published service process, not a claim about a specific client cutover.
One address can sit inside several authority systems
Inventory by verifier, not by wallet label. The same retiring address may be a Safe owner on Ethereum, a direct contract administrator on an L2, the signer of an order-domain message and the operator behind a relayer credential. Those are four authority relationships. Completing one replacement says nothing about the other three.
Chain scope must be explicit. Contracts deployed at the same-looking address on two networks have separate state, code and role membership. A typed-data domain may include one chain ID, while an application database associates the signer with several environments. Record each deployment and domain separately. Do not close the row because the block explorer on the primary network shows the new owner.
Contract upgrades add another layer. If the verifier sits behind a proxy, a new implementation can change signature rules while the verifying contract address remains constant. Domain separation by address alone will not reveal that semantic change. The inventory should bind the validation result to an implementation reference or runtime-code observation where that distinction matters. If an upgrade and key rotation share one maintenance window, rehearse both execution orders because the first transition may change how the second is authorized.
Relayer custody creates an off-chain boundary. A service may store signed payloads, schedule submission and retry failed broadcasts. Removing access to the signing key prevents new messages, but it does not delete the service's queue. Snapshot the queue through an authoritative export, stop new enqueue operations and reconcile transaction hashes afterward. A dashboard count is useful only when its pagination, filters and environment are recorded.
Finally, distinguish key compromise from planned retirement. During planned retirement, the team may execute wanted actions before the cutover and let bounded items expire. After suspected compromise, every still-usable signature is potential hostile inventory. Prioritize canceling unlimited allowances, administrative calls and orders with meaningful remaining value. If cancellation consumes a nonce shared with a wanted action, choose the sequence deliberately and capture the losing payloads as disposed.
This verifier-first model prevents a common closure error: the ceremony report lists one old address and one new address, while the operational record never says where either address had power.
EIP-712 defines a digest, not a revocation system
EIP-712 gives structured messages a typed hash and an extensible domain separator. Fields such as chainId, verifyingContract, name and version can prevent a signature intended for one domain from being accepted in another when the verifier uses them correctly.
The specification states the boundary in six words:
"It does not include replay protection."
Remco Bloemen, Leonid Logvinov and Jacob Evans, authors of EIP-712: Typed structured data hashing and signing, Ethereum Improvement Proposals, September 12, 2017. Original specification.
The operational consequence is direct. Rotation cannot rely on the typed-data format to invalidate earlier messages. Replay protection belongs to the application. The inventory must identify where that application stores or derives the control.
Check whether the nonce is global, per signer, per action type or unordered. A global nonce can invalidate many pending messages when one action consumes it. A bitmap may let the application cancel selected messages. An order salt may need a protocol-specific cancellation transaction. A deadline prevents later execution only when the verifier actually enforces it against the relevant clock.
Changing the domain version is a blunt invalidation tool. It may make every signature under the old version fail, but it also affects users and integrations that were expected to remain valid. A domain change should be an explicit migration decision with compatibility tests, not an undocumented side effect of rotating one privileged owner.
EOA signatures usually outlive the private-key ceremony
Suppose an EOA owner signed an administrative meta-transaction, then the team removed that address from an AccessControl role. The cryptographic signature still recovers to the same address. Whether execution fails depends on when and where authorization is checked.
If the receiving contract recovers the signer and checks the current role at execution time, the role removal may invalidate the pending action. Verify the actual call path and run the message against post-rotation state. An interface label that says admin is not evidence about the verifier.
If an intermediary verified the signature once and stored an approved action, later execution may no longer consult the original role. The action has crossed into materialized state. Find the stored approval, queue entry or operation ID and use that system's cancellation path.
Token permits show why the distinction matters. ERC-2612 accepts a permit only when its owner signature, nonce and deadline satisfy the token contract. On acceptance it updates the allowance and increments the owner's nonce. Before submission, the outstanding permit remains usable until its nonce changes or its deadline passes. After submission, the relevant risk is the allowance. A key-rotation runbook that checks only unused permits can miss spending authority already written to state.
Order protocols add partial fills and multiple nonce models. One order may remain valid for its unfilled amount after another order from the same signer executes. Another protocol may invalidate an entire nonce bucket. Query the protocol's canonical order state and cancellation function. Do not infer cancellation from a relayer UI removing a card.
Safe owner rotation invalidates some packages, not every downstream effect
Safe's swapOwner replaces one owner with another, and the change itself must be executed as a Safe transaction. The Safe then verifies owner signatures against its current owner set and threshold when an owner transaction is executed. A package that depends on the removed owner may no longer satisfy that check after rotation.
That useful property still needs testing at the exact boundary. Safe supports several signature forms and separates owner transactions from module transactions. The Safe smart-account concepts describe current owners, threshold checks and the separate module path. A module may authorize an action under its own logic. Removing an owner does not establish that enabled modules, guards, spending limits or other extensions lost authority.
Inspect at least four Safe populations:
- transactions proposed but carrying no confirmations;
- transaction packages with some or all owner signatures collected;
- approved hashes or alternative signature forms supported by the deployed Safe version;
- downstream operations already executed by the Safe, including timelock schedules and role grants.
Record the Safe nonce for every owner transaction. If the rotation uses the next nonce, a previously prepared transaction at a later nonce may become executable after the rotation if its signatures still satisfy the new configuration. A transaction at the same nonce loses the race once another transaction consumes that nonce, but the losing package should still be marked disposed with receipt evidence.
Test signature packages through the deployed Safe contract after the owner change. A local library result without the deployed account state is not enough. Include the chain, Safe address, implementation version, threshold and block reference in the test record.
ERC-1271 makes validity stateful
Contract accounts move the validity decision into code. ERC-1271 requires isValidSignature(hash, signature) to return its magic value when the contract accepts the signature. The standard allows validation to depend on time, owner authorization or another stateful rule.
OpenZeppelin's SignatureChecker documentation makes the practical contrast explicit: an EOA signature is checked by recovery, while a contract signature can return true at one block and false at another. For rotation work, that means a one-time pre-cutover validation result is evidence about one state snapshot, not a promise about future settlement.
This statefulness creates two requirements. First, applications should validate as close as possible to the action that consumes the signature. Caching a successful ERC-1271 result can preserve authority that the wallet later intended to revoke. If a protocol caches validity, identify the cache's invalidation rule and treat the cached approval as materialized state.
Second, the cutover test needs both positive and negative cases. A signature from the new configuration should succeed. A signature package that depends on the removed owner should fail. A signature unrelated to the rotated owner should behave according to the chosen policy. That last result must be decided, not assumed: some teams intend a surgical rotation, while others choose an epoch change that invalidates every prior contract signature.
ERC-5719 is a replacement interface, not universal recovery
ERC-5719 addresses stale smart-contract-wallet signatures by defining a way for a client to request an alternative signature for the same digest. Its motivation includes owner-set and wallet-implementation changes.
The interface does not make existing consumers support replacement. A client first tries ERC-1271, then asks for an alternative only if the wallet implements the ERC-5719 method and the retrieval path succeeds. The replacement must itself pass ERC-1271 validation. The client also needs a retry limit.
Do not write ERC-5719 available in the inventory because the standard exists. Record wallet support, consumer support, URI availability, integrity expectations and failure behavior. If any part is absent, the old signature is invalid for that client and the operator needs another authorized route. Replacement preserves a digest; it does not cancel a bad instruction or revise its terms.
Queued governance survives the signatures that created it
A governance proposal or timelock operation can outlive the accounts that approved or scheduled it. Once the call is in a Pending or Ready state, execution follows the timelock's roles and operation lifecycle.
OpenZeppelin's TimelockController documentation identifies an operation by the hash of its target, value, calldata, predecessor and salt. A proposer can cancel a pending operation. After cancellation, its state returns to unset and a reschedule starts a new timer. That is the cancellation evidence the inventory needs.
Rotating the proposer, Safe owner or governor delegate does not automatically cancel an existing operation. Read the operation ID from the deployed timelock and check whether it is pending, ready or done. Decode every target call. A batch may rotate one role while also changing a proxy implementation or moving assets.
Review the cancellation route before removing old authority. The actor performing the rotation might also be the only practical path to cancel an unsafe queued operation. In a governed setup, roles may require another delayed proposal. An emergency plan that discovers this dependency after the owner change is too late.
The published blockchain delivery process places threat modeling, testing, security review and staged mainnet rollout before operations are treated as complete. For a rotation, the useful application is a fork rehearsal that proves invalidation and cancellation paths against the same inventory operators will use on the live network. The service page supports the process description; it does not prove a result for an unnamed deployment.
Run the cutover as a controlled state transition
Use a six-step runbook. Keep the owner-change transaction and data-plane dispositions in one record.
1. Freeze new signatures
Set a cutoff time and stop systems from requesting new signatures from the retiring key. Disable automated signers through their normal administrative path. Preserve logs needed to identify the last authorized digest. A policy announcement without an enforced signer stop is not a freeze.
2. Snapshot every queue
Export Safe proposals, relayer queues, order books, permit stores, governance proposals, timelock operations and application-specific approvals. Record the query boundary and observation time. If a queue is eventually consistent or paginated, retain that limitation and reconcile again after the change.
3. Assign a disposition
For every row choose execute, cancel, expire, re-sign or investigate. Execution before rotation is valid only when the action is still wanted and its effects are checked. Expiry is valid only when the deadline is enforced and the remaining exposure fits the incident timeline. Re-signing needs a fresh domain and nonce read, not a copied payload with a new signature.
4. Rehearse post-rotation behavior
On a fork or representative test deployment, apply the exact owner change. Test old and new signature packages through their real verifying calls. Submit cancellation transactions where they exist. Inspect queued governance state. Compare expected and observed outcomes, including actions that unexpectedly remain valid.
5. Execute and reconcile
Broadcast the reviewed rotation through the correct authority path. Wait for the confirmation policy appropriate to the chain, then repeat the queue reads. Bind receipts, block hashes and changed state to the inventory rows. Investigate any item whose state differs from rehearsal rather than forcing it into the planned label.
6. Close with negative evidence
Prove the old path fails where failure is intended. Attempt the bounded old-owner signature checks, read invalidated nonces and verify canceled operation IDs. Also prove intended unaffected paths still work. Rotation can fail by leaving old authority alive or by disabling an unrelated recovery route.The same owner change can invalidate one signature, leave another usable and leave a queued operation untouched.
Use stop conditions, not a confidence score
A rotation should stop when the team cannot name the verifier, domain or replay boundary for a high-impact action. It should also stop when a required cancellation route is unavailable, the queue snapshot is incomplete or rehearsal differs from the proposed production state.
Do not average these gaps into a readiness percentage. One unknown unlimited permit can matter more than hundreds of disposed low-value orders. Prioritize by worst credible action, remaining validity window and available containment.
The final cutover record should answer five questions without relying on the operator's memory:
- Which authority changed, on what chain and at which block?
- Which outstanding signed or queued actions existed at the cutoff?
- Why is each action now executable, invalid, canceled, expired or still unknown?
- Which tests prove the old path fails and the new path works?
- Who owns every remaining unknown, and when does its authority end?
Changing an owner is a control-plane event. Closing the outstanding-action inventory is the data-plane completion condition. Until both are evidenced, the key rotation is still in progress.
More insights to read
- Smart Contract Upgrade Authority: Timelocks, Multisigs, and Emergency Controls
- Smart Contract Release Audit: 8 Repository Artifacts
- Upgradeable Solidity Smart Contracts. Part 1: Versioning
- Web3. Smart Contracts. Oracles. Part 1
- Smart Contracts. Their Potential and Real Limitations. Part 1
About the author
Dmytro Nasyrov. Photo supplied by the author.
Written by Dmytro Nasyrov PhD, software architect with 24 years of production experience. Dmytro is the founder and CTO of Pharos Production. He works on production software architecture for FinTech, AI, Web3 and blockchain systems.
