Gas Killer Docs
Solidity Reference

Reference

GasKillerSDK API surface, state update types, and revert selectors.

API surface of GasKillerSDK (BLS scheme). Inheriting it gives your contract everything on this page.

abstract contract GasKillerSDK is StateTracker, TransitionGuard, IGasKillerSDK

Constants

ConstantValueMeaning
QUORUM_THRESHOLD66Minimum share of each quorum's stake that must sign
THRESHOLD_DENOMINATOR100Denominator for the above — so 66%
300Default blockStaleMeasure, in blocks, when unset
ERC-165 id0x93de4531type(IGasKillerSDK).interfaceId; the router requires it

The threshold is checked per quorum, not across their union: every quorum in quorumNumbers must independently clear 66%.

verifyAndUpdate

The settlement entrypoint. The router builds this call for you (you never encode it by hand), but its parameters explain every failure mode.

function verifyAndUpdate(
    bytes32 msgHash,
    bytes calldata quorumNumbers,
    uint32 referenceBlockNumber,
    bytes calldata storageUpdates,
    uint256 transitionIndex,
    bytes4 targetFunction,
    IBLSSignatureCheckerTypes.NonSignerStakesAndSignature calldata nonSignerStakesAndSignature
) external payable guardTransition trackState;
ParameterPurpose
msgHashThe signed digest; recomputed on-chain and compared
quorumNumbersWhich quorums must clear the threshold
referenceBlockNumberBlock the operator set was snapshotted at
storageUpdatesABI-encoded (StateUpdateType[], bytes[]) — the diff to apply
transitionIndexCounter value this payload was computed against
targetFunctionSelector of the tracked function that was simulated
nonSignerStakesAndSignatureAggregate signature plus per-non-signer stake proofs

It executes in this order, so an earlier check masks any later one:

  1. referenceBlockNumber < block.number → else FutureBlockNumber
  2. referenceBlockNumber + blockStaleMeasure >= block.number → else StaleBlockNumber
  3. transitionIndex + 1 == stateTransitionCount() → else InvalidTransitionIndex
  4. Digest matches msgHash → else InvalidSignature
  5. checkSignatures on the configured checker, then the 66% test per quorum
  6. Apply the updates

The signed digest

sha256(abi.encode(transitionIndex, address(this), targetFunction, storageUpdates))

Available as a view for off-chain cross-checking:

function getMessageHash(
    uint256 transitionIndex,
    bytes4 targetFunction,
    bytes calldata storageUpdates
) external view returns (bytes32);

Binding address(this) means a payload cannot be replayed against a different contract, and binding transitionIndex means it cannot be replayed against a different state of the same one.

State update types

storageUpdates decodes to a list of operations applied in order.

TypeEffect
STOREWrite a 32-byte value to a storage slot
CALLExternal call, optionally with ETH value
LOG0LOG4Emit a log with 0–4 indexed topics
CREATEDeploy a contract, nonce-derived address
CREATE2Deploy a contract, salt-derived address

Most integrations only ever produce STORE and LOG*. See Tracked functions for the funding rules that apply to the value-bearing types.

Inherited members

From StateTracker:

MemberDescription
trackStateModifier; increments the transition counter before the body
stateTransitionCount()Transitions applied so far

From TransitionGuard:

MemberDescription
guardTransitionModifier; reverts re-entry, holds the in-transition latch
inTransition()True while a transition is applying

Both use fixed hashed slots, and TransitionGuard uses EIP-1153 transient storage, so a Cancun-or-later EVM is required.

Revert selectors

What a failed settlement means. Reverts from the SDK:

SelectorErrorCauseFix
0x252f8a0eFutureBlockNumberReference block is not yet minedRetry; usually a node lagging behind head
0x305c3e93StaleBlockNumberPayload older than blockStaleMeasureSubmit a new task — the payload expired
0x7376e0a2InvalidTransitionIndexContract state advanced since signingSubmit a new task; another transition landed first
0x8baa579fInvalidSignatureRecomputed digest ≠ msgHashPayload was altered, or the target's ABI differs from the router's
0x6d8605dbInsufficientQuorumThresholdSigners hold under 66% of a quorumTransient: too many operators missed the round
0xfbbb7b2bInvalidStorageUpdatesUpdates could not be decodedReport it — malformed payload
0x398d4d32InvalidOperationUnrecognised update typeReport it — version mismatch
0x287cdcedReentrantTransitionverifyAndUpdate re-entered mid-transitionA CALL update re-entered the contract; see inTransition()
0x493f09c4RevertingContextA CALL update revertedOften under-funded msg.value; carries the inner revert data
0x30116425DeploymentFailedA CREATE/CREATE2 update failedUsually under-funded msg.value
0x5f6f132cInvalidArgumentsUpdate arguments malformedReport it
0x25773e13MalformedLogPayloadLog update malformedReport it

Reverts that come from the restaking middleware's signature checker, not the SDK:

SelectorErrorWhat it usually means
0xe1310aedInvalidQuorumApkHashYour blsSignatureChecker is bound to a different operator set than the router signs with. See Configuration
0x4b874f45InvalidReferenceBlocknumberReference block outside the checker's usable range
0xaffc5edbStaleStakesForbiddenStake snapshot too old for the checker's policy
0x43714afdInputArrayLengthMismatchMalformed non-signer arrays — report it

Decode an unknown selector with cast 4byte <selector>, or recover a revert locally by replaying the payload at a block inside its validity window:

cast call "$TO" "$DATA" --from "$FROM" --block <n> --rpc-url "$RPC_URL"

A payload that reverts at every block in its window is not a timing problem: it is a configuration problem.

Source

On this page