fogo-paymaster

Crates.iofogo-paymaster
lib.rsfogo-paymaster
version0.7.2
created_at2025-10-07 23:11:24.406382+00
updated_at2026-01-23 20:06:46.112301+00
descriptionFogo paymaster service and transaction validator CLI
homepage
repositoryhttps://github.com/fogo-foundation/fogo-sessions
max_upload_size
id1872918
size417,390
(fogo-ops)

documentation

README

Paymaster

The Sessions Paymaster service provides apps with a way to fund user transactions on their frontends. This allows users to conduct these transactions without needing to hold native FOGO.

You can view metrics for the service at port 4000.

Constraints

The constraints API enables apps to set up filters for what kinds of transactions they wish to permit their paymasters to pay for. The paymaster filters are intended to regulate what transactions apps pay for, rather than constrain actions on the frontend to a non-exploitable surface. Accordingly, the constraints should be designed to outline appropriate use of the app's funds toward relevant user actions. This will help to ensure that these funds are only spent on legitimate use of the app's relevant frontend functions by retail users.

Thus, rather than avoid exploits, the paymaster filters should focus on constraining the action space to bonafide transactions that would be undertaken on the app's frontend.

The constraints are expressed in terms of TransactionVariation objects. Each TransactionVariation describes constraints on a transaction that must all be passed in order for a transaction to be considered valid. A transaction must pass at least one of an app's configured TransactionVariations in order to gain approval to use the paymaster's funds.

v0: VariationProgramWhitelist

v0 is a simple whitelist-based constraint set. A set of whitelisted programs is specified, and the transaction will pass iff every instruction's program is in the whitelist.

There are no constraints on instruction ordering, accounts, or data.

v1: VariationOrderedInstructionConstraints

v1 is a more fleshed out constraint set. It introduces constraints on each instruction in the transaction as well as a max gas spend (this checks the signature gas cost plus the priority fee). A list of instruction constraints is specified in order, with each instruction constraint containing:

  • a program ID to match against
  • a list of account constraints
    • each of these specifies the account in the instruction to check and a set of accounts to include and exclude from matching against
  • a list of data constraints
    • each of these specifies the location of the data and a type, value(s), and (in)equality to match against
  • a boolean indicating whether this instruction is explicitly required in the transaction.

v1 does not enforce relationships across instructions (e.g. require instruction Y if instruction X is present, constrain data in instruction Y based on the value of data in instruction X). In this way, it is relatively stateless and allows for simple absolute constraints on the instructions.

Running

Prerequisites

  • Provision Postgres (Docker Compose is available via docker-compose.yml).
  • Copy .env.example to .env and adjust the values to match your local setup.

Database

Start the Postgres container (and the optional pgweb UI) with:

docker compose up

Confirm that DATABASE_URL in your environment matches the credentials that the container exposes.

This will:

  • spin up a local postgres 17 database which can be used to connect the paymaster on postgres://paymaster:paymaster@localhost:5432/paymaster
  • run pgweb which exposes a web interface on http://localhost:8080/

Migrations

Migrations are located in: services/paymaster/migrations, and can be run using:

cargo run --bin fogo-paymaster migrate

Seeding

Seeding is optional, but simplifies bootstrapping a local configuration. Provide both a database URL, a path to a TOML config (an example lives at tilt/configs/paymaster.toml), and the network you'd like this config to live in (eg: testnet/mainnet):

cargo run --bin paymaster-config-sync -- --config="./tilt/configs/paymaster.toml" --db-url="postgres://paymaster:paymaster@localhost:5432/paymaster" --network-environment testnet

note that running the paymaster-config-sync multiple times will act as an upsert command where it will create variations if they don't exist or update them if they're already present in the db.

Running the paymaster

Launch the service with either environment variables or explicit flags. The minimum inputs are the database URL, HTTP RPC endpoint, network (eg. testnet/mainnet) and a mnemonic file path for the sponsor wallet. Example:

cargo run --bin fogo-paymaster run \
  --db-url "postgres://paymaster:paymaster@localhost:5432/paymaster" \
  --rpc-url-http https://testnet-alt.fogo.io \
  --mnemonic-file ./tilt/secrets/mnemonic
  --network-environment testnet

Optional flags:

  • --rpc-url-ws (defaults to replacing http with ws on the HTTP URL)
  • --listen-address (default 0.0.0.0:4000)
  • --otlp-endpoint for exporting OpenTelemetry traces (default http://localhost:4317)
  • --db-refresh-interval-seconds for how frequently domain config is refreshed (default 10 secs)
  • --valiant-api-key to enable swapping of accrued fee tokens into FOGO as per specifications in the config
  • --valiant-override-url to override the default Valiant endpoint used by the paymaster. The default behavior is determined according to the --network-environment flag; this override flag is handy particularly in the case of localnet testing.

You can also rely on the .env(see .env.example) values and simply run cargo run --bin fogo-paymaster run.

Metrics and Logs

The paymaster service records some metrics via Prometheus and some spans for timing of the transaction validation/submission/confirmation flow via OpenTelemetry. The service exports these OpenTelemetry spans to localhost:4317 by default. You can configure sending these to a different destination by setting the OTEL_EXPORTER_OTLP_ENDPOINT environment variable, or by providing the otlp_endpoint CLI arg.

You can run a local all in one jaeger instance to collect and visualize these spans by running:

docker run --name jaeger \
  -e COLLECTOR_OTLP_ENABLED=true \
  -p 16686:16686 \
  -p 4317:4317 \
  jaegertracing/all-in-one:1.63.0

Transaction Validator Tool

The crate also exposes a cli tool to validate arbitrary transactions against a specified config. You can run this via the following command:

cargo run --bin paymaster-tx-validator validate -c <CONFIG_PATH> --network <testnet|mainnet> --transaction-hash <ONCHAIN_TRANSACTION_HASH> (--rpc-url-http <RPC_URL_HTTP>)

Alternatively, you can provide a serialized transaction as a base64 string via the --transaction argument in place of the hash. Additionally, you could ask the tool to validate a specified number of the most recent transactions that interacted with this domain's sponsor pubkey via:

cargo run --bin paymaster-tx-validator validate -c <CONFIG_PATH> --network <testnet|mainnet> --domain <DOMAIN> --recent-sponsor-txs <NUMBER_OF_RECENT_TXS> (--rpc-url-http <RPC_URL_HTTP>)

Note that in this case, you must specify the domain you wish to match against and pull recent transactions for, unless your config only has 1 domain.

You can optionally provide the name of the domain you wish to match against via --domain. The tool will print out the set of transaction variations that the provided transaction matches against. If --domain is provided, you can optionally provide the name of a particular variation you wish to match against via --variation. The tool will then print out additional logging showing the exact errors in each case that a transaction does not match against this domain and variation combination.

Commit count: 545

cargo fmt