Sponsored Tasks: How It Works
This page follows one sponsored reward from an empty vault to tokens in a worker's wallet. For the commands at each step see the CLI reference.
Contents
- Lifecycle at a glance
- 1. Create the vault
- 2. Fund the vault
- 3. Authorize a manager
- 4. Deposit fee credit
- 5. Create a task with a reservation
- 6. The verdict
- 7. Settlement
- 8. Claim
- How the reward is split
- Reward states
- Vault balances
Lifecycle at a glance
| Step | Who | On-chain call | Result |
|---|---|---|---|
| 1 | Sponsor | SponsoredTaskFactory.createVault | Vault clone deployed, registered in the registry, epoch 1, status active. |
| 2 | Anyone | SponsoredTasksVault.fund | Project tokens move into the vault and become available. |
| 3 | Owner | SponsoredTasksVault.configureManager | Manager gets a spend cap and is active. |
| 4 | Manager | SponsoredTaskFeeBank.deposit | Manager holds USDC fee credit. |
| 5 | Manager | Taskmarket task creation with the Sponsored Task hook | Creation fee charged from credit; tokens reserved for the task. |
| 6 | Requester, evaluator or protocol | Taskmarket verdict | The hook commits the awards. |
| 7 | Keeper (or anyone) | SponsoredTaskHook.reconcile, finalizeSettlement or finalizeRelease | Merkle root installed in the vault, or reservation released. |
| 8 | Worker, via a gasless relay | SponsoredTasksVault.claimTo | Net tokens sent to the worker's withdrawal address. |
1. Create the vault
taskmarket sponsored-task create calls the factory's createVault(token, vaultOwner, userSalt)
with a random salt. The factory deploys a minimal clone of the vault implementation, derives the
vaultId, initializes the vault with the hook as its controller and the fee policy, and registers
the vault in the SponsoredTaskRegistry in the same transaction. Vault creation is permissionless:
any address can create a vault for any token. The token must be a deployed contract.
2. Fund the vault
fund(amount) pulls exactly amount tokens from the caller. Anyone can fund an active vault. The
vault checks that the sender's balance fell by exactly amount and its own balance rose by exactly
amount, so fee-on-transfer tokens are rejected at funding time.
3. Authorize a manager
The owner calls configureManager(manager, cap, active). The cap is a lifetime token allowance in
base units, not a per-task limit. See Managing a vault.
4. Deposit fee credit
Every sponsored task pays one flat creation fee in USDC, charged from the manager's credit in the fee bank during task creation. The manager deposits credit ahead of time. See Fees and the fee bank.
5. Create a task with a reservation
The manager runs taskmarket task create ... --sponsored-task <vaultId> --sponsored-task-tokens <amount>. The CLI previews the funding, asks the backend to build the hook's funding request, and
attaches the Sponsored Task hook to the task. Inside the task-creation transaction the hook:
- Checks that the task pays in USDC, the requester is the manager, and the funding request matches the task's terms hash.
- Checks that the vault is registered, active, on this chain, at the stated epoch, and controlled by this hook.
- Charges the creation fee from the manager's fee bank credit.
- Calls the vault's
reserveTask, which checks the manager is active, the spend cap and the vault's available balance both cover the amount, and the fee terms match the fee policy's current terms. The fee rate and recipient are snapshotted onto the reservation.
If any check fails, the whole task creation reverts, including the fee charge. The reward appears
on the task with state reserved. Details are in
Creating sponsored tasks.
6. The verdict
When the task completes, the hook records the verdict type, the awards and the USDC payout pool (the reward less any evaluator fee). It does not move tokens at this point. Three outcomes skip the split entirely:
- Cancelled or expired task. The reservation is released back to the vault's available balance.
- More than 8 awards. The hook releases the reservation and marks the reward
award_count_exceededinstead of reverting, so the USDC settlement is never blocked. - Worker forfeit. A forfeit keeps the reservation in place.
7. Settlement
Nothing in the contracts pays a worker or returns tokens automatically. A Taskmarket backend
keeper checks every 30 seconds for sponsored tasks that are completed, cancelled or expired
but still reserved, and calls the hook's permissionless reconcile for each one. reconcile
reads the task's on-chain status and verdict and either installs the settlement or releases the
reservation. A call that is not actionable yet reverts harmlessly and is retried on a later pass.
Installing a settlement computes each winner's gross, fee and net amounts, builds a Merkle tree of
the net entitlements (one leaf per winner with a non-zero net amount), and calls the vault's
installSettlement. The vault moves the reserved amount out of the manager's reservation, counts
the distributed amount as spent against the manager's cap, makes the distributed amount
claimable, and returns any undistributed remainder to the available balance. The reward's state
becomes credited (or released if nothing was distributed).
A manual split-award verdict that reconcile cannot rebuild by itself is left reserved for an
operator to settle with finalizeSettlement directly. finalizeSettlement, finalizeRelease,
reconcile and refreshOwnerDefault are all permissionless.
8. Claim
The worker runs taskmarket sponsored-task claim <vaultId>. The CLI fetches the worker's unclaimed
entitlements with their Merkle proofs, signs an EIP-712 ClaimTo authorization naming the worker's
registered withdrawal address, and posts it to the backend, which relays claimTo on-chain. The
worker pays no gas. See Claiming rewards.
The fee portion is claimed separately by the snapshotted fee recipient with the vault's
claimFee.
How the reward is split
Settlement uses the verdict's award weights (the USDC amount each winner was awarded):
| Verdict | Gross distributed |
|---|---|
APPROVE | The whole reserved amount, split pro rata by award weight. |
PARTIAL | The reserved amount scaled by min(total awards, payout pool) / payout pool, then split pro rata. The rest returns to the vault. |
REJECT, or no non-zero award | Nothing. The full reservation returns to the vault. |
For each winner, the token fee is winnerGross * feeBps / 10000, and the winner's entitlement is
the remainder. With a fee rate of 750 bps, a 100-token reward pays the worker 92.5 tokens.
Reward states
These are the values of state on a task's sponsoredTaskRewards entry:
| State | Meaning | Worker can claim? |
|---|---|---|
reserved | Task in progress, or finished but not yet settled. Tokens are held in the vault. | No, not yet. |
credited | Settlement installed on-chain. Winners have entitlements. | Yes. |
released | Task cancelled or expired, or the verdict distributed nothing. Tokens returned to the vault's available balance. | No. |
defaulted | The vault owner exited the vault before the reward was settled. | No. |
award_count_exceeded | The verdict had more than 8 awards. USDC settled normally; the sponsored reward was released. | No. |
The state stays credited after a worker claims. Whether a particular entitlement has been paid
is recorded on-chain (isClaimed on the vault), and the
entitlements endpoint only returns
unpaid ones.
On-chain, the vault tracks its own allocation statuses: Reserved, Claimable, Settled (every
entitlement and the fee paid out), Released and DefaultedByOwner.
Vault balances
| Balance | Meaning |
|---|---|
| Funded total | Every token ever funded into the vault. |
| Reserved | Tokens held for tasks that have not settled. |
| Claimable | Settled entitlements and fees not yet claimed. |
| Available | Token balance minus reserved minus claimable. This is what new reservations and owner withdrawals can use. |
taskmarket sponsored-task balance <vaultId> shows fundedTotal, availableBalance and
reservedBalance as indexed by Taskmarket.