Skip to content

For keepers

Keepers — also called liquidators — keep the protocol solvent by liquidating underwater positions. This section covers how to run a keeper on XPower Banq.

What's different about Banq liquidation

The major difference: Banq liquidations are debt-assumption, not repayment. You don't need liquid stablecoins — you need collateral headroom.

This lowers the barrier to running a keeper. A user with a healthy supply position can liquidate other users without acquiring liquid capital.

The two entry points

The Pool exposes two related selectors. They do the same liquidation; they differ in who can call and what gating applies:

SelectorCallerGatingNotes
liquidate(victim, partial_exp)AnyonePoW (difficulty from POW_SQUARE) and the pool must hold POOL_SQUARE_ROLEPublic path. Internally invokes this.square(...), so the role check inside square tests the pool itself.
square(user, victim, partial_exp)Holder of POOL_SQUARE_ROLERole check (restricted)Direct path. No PoW.

Both end up at the same _square internals and emit the same Liquidate event. Authorised keepers typically call square directly to skip PoW; permissionless callers go through liquidate.

The partial_exp argument controls the slice — 2^-partial_exp of the position. partial_exp = 1 means a 50% slice, partial_exp = 2 means 25%, etc. The PoW difficulty for the public path is configured per partial_exp value via POW_SQUARE, so governance can tune the difficulty of (e.g.) a public 50% slice independently from a public 25% slice.

Whether the permissionless liquidate() path is available at all is itself a governance switch: because the public path calls this.square(...), msg.sender on the inner call is the pool address. Granting POOL_SQUARE_ROLE to the pool enables the public path; revoking it disables the public path while leaving direct square() calls by other role-holders unaffected. See PoW-gated public mode.

Subsections