Watch & respond

Auto-pause

A pause-only on-chain circuit breaker: Sentinelleai holds a dedicated pauser role and watches for unambiguous compromise signals, and can send exactly one kind of transaction — pause().

Pause only, never unpause
The service's transaction list contains exactly one function, pause(), and it refuses to start if that list is ever widened. Reopening a paused contract always stays with your own owner or multisig — disarming the watch never unpauses anything, and there is no code path here that could. Sentinelleai holds a pauser role on your contract, never ownership or admin rights.
A pause-only circuit breaker: reads must agree, one signal, one function, reopening stays with you.Every two minutes two independent RPCs are read. If they disagree, nothing happens. If they agree and show a compromise signal — owner changed, bytecode changed on a non-upgradeable contract, or the proxy implementation changed — the service calls pause(), the only function it can send. The contract stays paused until the owner or multisig reopens it; the service never calls unpause().Every ~2 minutesRPC ARPC BBoth agree?No — reads disagreeno action, recheck in ~2 minCompromise signal?• Owner changed• Bytecode changed (non-upgradeable)• Proxy implementation changedNo compromise signalno action, recheck in ~2 minpause()the only function the service can sendContract pausedYou investigate.Your owner / multisig reopens it.unpause()— nevernoyesnoyes
A pause-only circuit breaker: reads must agree, one signal, one function, reopening stays with you.

What you need before enrolling

  1. 1

    Your contract exposes pause() and paused()

    The target must be a Pausable contract (or equivalent): a readable paused() boolean and apause() function present in the deployed bytecode.
  2. 2

    Grant the pause role to the address Sentinelleai shows you

    Enrolling generates a dedicated key for that one protocol. Its private key never leaves the platform and is never displayed; only its address is shown, for you to copy and grant the pause role to (isPauser or an OpenZeppelin PAUSER_ROLE grant).
  3. 3

    Fund the pauser address

    It needs enough native token on the target chain to cover a handful of pause() calls — enrolment checks the balance against the current gas price and tells you if it is short.
  4. 4

    Keep the pauser separate from your owner and admin

    Enrolment refuses a pauser address that is also the contract's owner, or that holds the default admin role — either would let the same key that pauses also unpause, which defeats the whole design.

The six verification checks

Before a protocol can be armed, six read-only checks (V1–V6) must all pass. Every read goes through a live RPC call against the chain you enrolled on; any read that cannot be resolved makes its check "unknown", never rounded up to a pass.

CheckQuestionPasses whenFails when
V1Is this a Pausable contract?paused() returns a valid booleanpaused() does not return a bool
V2Is pause() exposed?The deployed bytecode contains the pause() selectorThe selector is absent from the bytecode
V3Does the pauser hold pause authority?isPauser() or the pauser role check returns true for the pauser addressEither check answers false — the role has not been granted yet
V4Is the pauser separated from unpause authority?The pauser is not the owner and does not hold the default admin roleThe pauser is the owner, or holds the default admin role — it could unpause or grant itself the ability to
V5Is the pauser funded?Its balance covers at least a few pause() calls at the current gas priceBalance is below that floor
V6Was a baseline recorded?A code hash (or EIP-1967 implementation address, for a proxy) was read and stored for every watched addressA baseline could not be read for one or more watched addresses

A protocol can only be armed once every check reads pass. You can re-run verification at any time from the Auto-pause page.

What triggers a pause, and what does not

Once armed, the engine polls your enrolled contracts roughly every two minutes, reading each check through at least two independent RPC endpoints and only acting when they agree — an endpoint that cannot be reached, or that disagrees with the others, blocks a trigger rather than causing one. A confirmed, agreed signal on any of the following sends pause():

  • Ownership escape — owner() no longer returns the owner recorded when the protocol was enrolled and verified.
  • Bytecode mutation — the runtime bytecode hash of a watched contract enrolled as immutable code no longer matches its recorded baseline (including the contract's code being destroyed entirely).
  • Proxy implementation drift — the EIP-1967 implementation slot of a watched proxy no longer points at the implementation recorded at enrolment.
Say plainly what this does not catch
A compromise that drains funds without changing the owner, the code, or the proxy implementation — a logic bug exploited through the contract's own normal functions, for example — produces none of these three signals and will not trigger a pause. A chain reorganisation or a disagreement between your RPC endpoints never triggers a pause either: it withholds one. There is also a cooldown per contract after a pause fires, and a cap on how many pauses one polling cycle can send, both meant to stop a flapping condition from sending repeated transactions.

After a pause

A pause buys time, nothing more. You investigate what happened, and you decide when and how to unpause — Sentinelleai never does either. Every check, trigger, and transaction attempt is recorded as an event, and delivery of the pause transaction itself is tracked the same way any other protective action is: see the evidence ledger for how these events are chained and reported.

A pause also triggers the customer report flow: you get a short email notice as soon as pause() lands, then the full signed report after a hold window, with the consent you signed for Auto-pause attached to it. See Reports sent to you for the notice, the hold, and how an operator can add a note or skip a delivery.

Testnet rehearsal

The enrolment form groups chains into mainnet and testnet. Enrolling a throwaway contract on a testnet first lets you see the full enrol → verify → arm flow, and a real pause, before committing a production contract to the service.

The Auto-pause page showing an enrolled protocol, its verification checks, and its event history
Enrol, verify, arm — each protocol's events are listed underneath it.

Pricing structure

Auto-pause is billed per protocol per month. One pausable contract, plus the contracts watched around it, on one chain, counts as one protocol — the same protocol deployed on a second chain counts as a second protocol. It is sold as a standalone add-on and is not included in the general bundle, because it is the one function here that can move a money-bearing contract on your behalf, so enrolling it is always an explicit, deliberate choice. See pricing for current figures.

Subscribing requires signing a consent the first time: a phrase you type verbatim confirming you read this page, recorded against your identity in the evidence ledger before checkout proceeds. See Plans & billing for what exactly is recorded.

What it stops short of

  • It detects three specific, unambiguous signals — ownership change, bytecode mutation, proxy re-pointing — not exploitation in general.
  • It cannot read your contract's business logic and will not stop a hack that operates entirely within it.
  • It withholds action rather than guess whenever RPCs disagree or cannot be reached, which trades some missed detections for never pausing on bad information.
  • It never unpauses. Reopening is always a decision made by your own owner or multisig.