Skip to content

Live proof ​

Audience: contributors and reviewers who want on-chain evidence that the plugin signs with real KMS keys.

Status: the latest run of the live suite on Sepolia (#44), with the transaction matrix of #144. pnpm run docs:live-proof renders this page from test/live/proof.json, which the run wrote; do not edit it by hand.

Run ​

FieldValue
Date2026-10-16, blocks mined from 06:22:24 to 06:26:36 UTC
Commiteeec83b
Chain id11155111 (Sepolia)
Blocks11925619 to 11925638
CommandHARDHAT_KMS_LIVE_NETWORK=sepolia pnpm run test:live
ProvidersAWS KMS, Google Cloud KMS and Azure Key Vault, in parallel
Gas prices1.00 to 1.00 gwei for types 0 and 1; 0.00 to 1.00 gwei for types 2 and 4

Every transaction below was signed by the provider's KMS key through the plugin, except where a case says another key signed. The suite waited for each receipt and checked its status, its sender and its type against the case table in test/live/matrix.ts. A run that misses a receipt for any live cell fails, and writes no proof.

The personal_sign and eth_signTypedData_v4 signatures are checked with eth_call: LiveCheck rebuilds the EIP-191 and EIP-712 digests on chain and recovers the KMS account with ecrecover. These checks send no transaction, so they have no hash.

Each account ends the run with no code. Its EIP-7702 delegation is cleared by the last case, and the throwaway key whose authorization the account sent is cleared by a second transaction in the same case. Slot 0 of each account's storage keeps the count that the delegated add wrote; clearing a delegation does not reset storage.

Coverage matrix ​

One decision per action and type. Live cells run on Sepolia and on the fork, fork cells only on the fork, unit cells only in the unit or integration tests, and refused cells are refused by the plugin before any request. Each live and fork cell runs once per provider.

ActionType 0 (legacy)Type 1 (EIP-2930)Type 2 (EIP-1559)Type 3 (EIP-4844)Type 4 (EIP-7702)
ETH to another EOALiveLiveLiveRefused (r)Live
ETH to selfFork (a)Fork (a)LiveRefused (r)Live
Contract deployLiveLiveLiveN/A (b)N/A (c)
Contract callLiveLiveLiveRefused (r)Live
Payable contract callLiveLiveLiveRefused (r)Live
Reverting transaction, mined with status 0Fork (d)Fork (d)LiveRefused (r)Fork (d)
Replacement (same nonce, higher fee)Fork (e)Fork (e)Fork (e), unitRefused (r)Fork (e)
EIP-7702 set delegationN/A (f)N/A (f)N/A (f)N/A (f)Live
EIP-7702 clear delegationN/A (f)N/A (f)N/A (f)N/A (f)Live
Sponsored: we send another key's authorizationN/A (f)N/A (f)N/A (f)N/A (f)Live
Sponsored: another account sends our authorizationN/A (g)N/A (g)N/A (g)N/A (g)Fork (h)
SignatureDecision
personal_signLive
eth_signTypedData_v4Live
eth_signLive

Reasons:

  • (a) A self-send of type 0 or 1 takes the same fill and signing path as a send to another EOA of the same type, which runs live. Self-sends of types 2 and 4 run live.
  • (b) EIP-4844: "to … MUST NOT be nil … blob transactions cannot have the form of a create transaction." The plugin refuses blob transactions anyway.
  • (c) EIP-7702 gives destination the semantics of EIP-4844: "this implies a null destination is not valid."
  • (d) The revert path does not depend on the type: the receipt has status 0, and the next transaction whose nonce the plugin fills carries the account's count after the revert, which the type 2 case proves on Sepolia. The type 4 case also checks that the delegation stays applied, since EIP-7702 does not roll back processed authorizations when execution fails.
  • (e) A replacement needs a transaction that stays pending. On Sepolia that means pricing one below the base fee through a load-balanced public RPC, where a backend may refuse it or mine it, and a stuck nonce blocks the account. In fork mode the case turns automine off with evm_setAutomine, sends, sends the replacement with double the fees, mines, and checks that only the replacement was mined.
  • (f) EIP-7702: only a set-code transaction (type 4) carries an authorization_list, and the list must not be empty. The plugin picks type 4 exactly when authorizationList is present and refuses a gasPrice next to it.
  • (g) The other account signs the outer transaction; the plugin signs only the authorization, which only type 4 carries (EIP-7702).
  • (h) On Sepolia the KMS account would first have to fund a second key, and ETH would stay there. In fork mode anvil_setBalance funds a throwaway local sender for free. The KMS key signs the authorization with its current nonce, not nonce + 1, since another account sends it.
  • (r) EIP-4844 blob transactions: the plugin refuses them before any request.

Unit tests:

  • packages/hardhat-kms/test/unit/rpc/transaction-filler.test.ts, "refuses blob transactions before any request": eth-to-eoa/eip4844, eth-to-self/eip4844, call/eip4844, payable-call/eip4844, revert/eip4844, replacement/eip4844
  • packages/hardhat-kms/test/integration/send-lock.test.ts, "keeps an explicit nonce and sends same-nonce replacements with higher fees": replacement/eip1559

Not in the matrix:

  • CREATE2 factory deploy: The plugin sees a call to the factory, which is the contract call row. It never builds the CREATE2 address itself.

Cases:

CaseModeWhat it sends
deploy-live-checklivedeploy LiveCheck
eth-to-eoa-legacylive1 wei to a fresh address
eth-to-eoa-eip2930live1 wei to a fresh address, with an access list
eth-to-eoa-eip1559live1 wei to a fresh address
self-send-legacyfork1 wei to itself
self-send-eip2930fork1 wei to itself, with an access list
self-send-eip1559live1 wei to itself
deploy-minimal-legacylivedeploy a 3-byte contract
deploy-minimal-eip2930livedeploy a 3-byte contract, with an access list
revert-eip1559livean unknown selector to LiveCheck, with a gas limit of 50,000
revert-legacyforkan unknown selector to LiveCheck, with a gas limit of 50,000
revert-eip2930forkan unknown selector to LiveCheck, with an access list and a gas limit of 50,000
call-legacyliveadd(1) with 1 wei
call-eip2930liveadd(1) with 1 wei, with an access list
call-eip1559liveadd(1) with 1 wei
replace-legacyforkreplace a pending 1 wei self-send
replace-eip2930forkreplace a pending 1 wei self-send, with an access list
replace-eip1559forkreplace a pending 1 wei self-send
delegate-and-calllivedelegate to LiveCheck and call add(1) on itself with 1 wei
signaturesliveLiveCheck recovers a personal_sign, an eth_sign and an eth_signTypedData_v4 signature
sponsor-otherlive1 wei to the fresh address, carrying a throwaway key's authorization to LiveCheck; a second transaction clears that delegation
sponsored-by-otherforka funded local account sends our authorization, delegating to the 3-byte contract
revert-eip7702forkdelegate back to LiveCheck and send an unknown selector to itself, with a gas limit of 100,000
replace-eip7702forkreplace a pending self-send that carries an authorization
clear-delegationliveauthorize the zero address and send 1 wei to itself

AWS KMS ​

ActionType 0 (legacy)Type 1 (EIP-2930)Type 2 (EIP-1559)Type 3 (EIP-4844)Type 4 (EIP-7702)
ETH to another EOA0x4332f7450xd620b4e60x51e1fc2cRefused (r)0x393614a0
ETH to selffork onlyfork only0x9dc5f855Refused (r)0x488d0ed7
Contract deploy0x7d40a12c0xeae7ceb70x3d50e4ddN/A (b)N/A (c)
Contract call0xc15345db0x700348560xe39fad17Refused (r)0xcd045bc3
Payable contract call0xc15345db0x700348560xe39fad17Refused (r)0xcd045bc3
Reverting transaction, mined with status 0fork onlyfork only0x230cf20bRefused (r)fork only
Replacement (same nonce, higher fee)fork onlyfork onlyfork onlyRefused (r)fork only
EIP-7702 set delegationN/A (f)N/A (f)N/A (f)N/A (f)0xcd045bc3
EIP-7702 clear delegationN/A (f)N/A (f)N/A (f)N/A (f)0x488d0ed7
Sponsored: we send another key's authorizationN/A (f)N/A (f)N/A (f)N/A (f)0x393614a0
Sponsored: another account sends our authorizationN/A (g)N/A (g)N/A (g)N/A (g)fork only
SignatureProof
personal_signeth_call at block 11925630
eth_signTypedData_v4eth_call at block 11925630
eth_signeth_call at block 11925630
CaseStepTypeStatusBlockTransaction
deploy-live-checkdeploy LiveCheck21119256190x3d50e4dd
eth-to-eoa-legacy1 wei to a fresh address01119256200x4332f745
eth-to-eoa-eip29301 wei to a fresh address11119256210xd620b4e6
eth-to-eoa-eip15591 wei to a fresh address21119256220x51e1fc2c
self-send-eip15591 wei to itself21119256230x9dc5f855
deploy-minimal-legacydeploy a 3-byte contract01119256240x7d40a12c
deploy-minimal-eip2930deploy a 3-byte contract11119256250xeae7ceb7
revert-eip1559an unknown selector to LiveCheck20119256260x230cf20b
call-legacyadd(1) with 1 wei01119256270xc15345db
call-eip2930add(1) with 1 wei11119256280x70034856
call-eip1559add(1) with 1 wei21119256290xe39fad17
call-eip1559add(1) with 1 wei, filled while the first was pending21119256290x99bd397d
delegate-and-calldelegate to LiveCheck and add(1) with 1 wei41119256300xcd045bc3
sponsor-other1 wei to a fresh address, with a throwaway key's authorization41119256330x393614a0
sponsor-otherclear the throwaway key's delegation41119256340x03cfbf62
clear-delegationclear the delegation, with 1 wei to itself41119256350x488d0ed7

Google Cloud KMS ​

ActionType 0 (legacy)Type 1 (EIP-2930)Type 2 (EIP-1559)Type 3 (EIP-4844)Type 4 (EIP-7702)
ETH to another EOA0xd10a41920x8e302c520x990cafa6Refused (r)0x6a4ca6b3
ETH to selffork onlyfork only0xa407484aRefused (r)0x147b3514
Contract deploy0x4b6731b70xd4ea5bc60x906b46b3N/A (b)N/A (c)
Contract call0x4fd85d4e0xae47e40a0x6b14fbf7Refused (r)0xa6f9c688
Payable contract call0x4fd85d4e0xae47e40a0x6b14fbf7Refused (r)0xa6f9c688
Reverting transaction, mined with status 0fork onlyfork only0x221ca29aRefused (r)fork only
Replacement (same nonce, higher fee)fork onlyfork onlyfork onlyRefused (r)fork only
EIP-7702 set delegationN/A (f)N/A (f)N/A (f)N/A (f)0xa6f9c688
EIP-7702 clear delegationN/A (f)N/A (f)N/A (f)N/A (f)0x147b3514
Sponsored: we send another key's authorizationN/A (f)N/A (f)N/A (f)N/A (f)0x6a4ca6b3
Sponsored: another account sends our authorizationN/A (g)N/A (g)N/A (g)N/A (g)fork only
SignatureProof
personal_signeth_call at block 11925630
eth_signTypedData_v4eth_call at block 11925630
eth_signeth_call at block 11925630
CaseStepTypeStatusBlockTransaction
deploy-live-checkdeploy LiveCheck21119256190x906b46b3
eth-to-eoa-legacy1 wei to a fresh address01119256200xd10a4192
eth-to-eoa-eip29301 wei to a fresh address11119256210x8e302c52
eth-to-eoa-eip15591 wei to a fresh address21119256220x990cafa6
self-send-eip15591 wei to itself21119256230xa407484a
deploy-minimal-legacydeploy a 3-byte contract01119256240x4b6731b7
deploy-minimal-eip2930deploy a 3-byte contract11119256250xd4ea5bc6
revert-eip1559an unknown selector to LiveCheck20119256260x221ca29a
call-legacyadd(1) with 1 wei01119256270x4fd85d4e
call-eip2930add(1) with 1 wei11119256280xae47e40a
call-eip1559add(1) with 1 wei21119256290x6b14fbf7
call-eip1559add(1) with 1 wei, filled while the first was pending21119256290xb421daf4
delegate-and-calldelegate to LiveCheck and add(1) with 1 wei41119256300xa6f9c688
sponsor-other1 wei to a fresh address, with a throwaway key's authorization41119256330x6a4ca6b3
sponsor-otherclear the throwaway key's delegation41119256340xbccd1388
clear-delegationclear the delegation, with 1 wei to itself41119256350x147b3514

Azure Key Vault ​

ActionType 0 (legacy)Type 1 (EIP-2930)Type 2 (EIP-1559)Type 3 (EIP-4844)Type 4 (EIP-7702)
ETH to another EOA0x40eee9a80x8dea94880xa5430eb7Refused (r)0x46166a99
ETH to selffork onlyfork only0x9deeef26Refused (r)0x420c8d8b
Contract deploy0xfaab96e70xec8d87c50xb319c000N/A (b)N/A (c)
Contract call0xd5a081230xeb00dadf0xd68b8dc9Refused (r)0x4725b166
Payable contract call0xd5a081230xeb00dadf0xd68b8dc9Refused (r)0x4725b166
Reverting transaction, mined with status 0fork onlyfork only0x81f6e7b1Refused (r)fork only
Replacement (same nonce, higher fee)fork onlyfork onlyfork onlyRefused (r)fork only
EIP-7702 set delegationN/A (f)N/A (f)N/A (f)N/A (f)0x4725b166
EIP-7702 clear delegationN/A (f)N/A (f)N/A (f)N/A (f)0x420c8d8b
Sponsored: we send another key's authorizationN/A (f)N/A (f)N/A (f)N/A (f)0x46166a99
Sponsored: another account sends our authorizationN/A (g)N/A (g)N/A (g)N/A (g)fork only
SignatureProof
personal_signeth_call at block 11925630
eth_signTypedData_v4eth_call at block 11925630
eth_signeth_call at block 11925630
CaseStepTypeStatusBlockTransaction
deploy-live-checkdeploy LiveCheck21119256190xb319c000
eth-to-eoa-legacy1 wei to a fresh address01119256200x40eee9a8
eth-to-eoa-eip29301 wei to a fresh address11119256210x8dea9488
eth-to-eoa-eip15591 wei to a fresh address21119256220xa5430eb7
self-send-eip15591 wei to itself21119256230x9deeef26
deploy-minimal-legacydeploy a 3-byte contract01119256240xfaab96e7
deploy-minimal-eip2930deploy a 3-byte contract11119256250xec8d87c5
revert-eip1559an unknown selector to LiveCheck20119256260x81f6e7b1
call-legacyadd(1) with 1 wei01119256270xd5a08123
call-eip2930add(1) with 1 wei11119256280xeb00dadf
call-eip1559add(1) with 1 wei21119256290xd68b8dc9
call-eip1559add(1) with 1 wei, filled while the first was pending21119256290x3def8c98
delegate-and-calldelegate to LiveCheck and add(1) with 1 wei41119256300x4725b166
sponsor-other1 wei to a fresh address, with a throwaway key's authorization41119256330x46166a99
sponsor-otherclear the throwaway key's delegation41119256350xefb92377
clear-delegationclear the delegation, with 1 wei to itself41119256380x420c8d8b

The providers together spent 0.00276432329841456 ETH.

MIT licensed. A community plugin, not affiliated with or endorsed by Nomic Foundation, Amazon Web Services, Google or Microsoft.