> ## Documentation Index
> Fetch the complete documentation index at: https://docs.cryptocheckout.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Gas reimbursement

> How the platform recovers deposit-rail gas from the merchant without ever gaining the ability to withhold funds.

Spec: `docs/superpowers/specs/2026-08-06-deposit-rail-gas-economics.md` §4.

## The problem

The keeper fronts native gas for every deposit-rail sweep. Two things make the shipped recovery model untenable.

**The existing channel is being deleted.** Today the keeper recovers gas via the `distribute()` distributor incentive — a bps fraction of gross, capped by the pool's committed `distributionIncentiveBps`. The plan to zero that incentive and restore a true 1% flat removes *the only mechanism by which deposit-rail gas is recovered at all*. Two issues written independently, in direct conflict.

**The bps model does not track the cost in either direction.** Gas is a fixed cost per invoice; the incentive is a percentage of gross per distribution. At 50 bps on a $20 order — $0.10 recovered:

| Chain    | Real cost per invoice | Recovered | Outcome                                       |
| -------- | --------------------- | --------- | --------------------------------------------- |
| Ethereum | \$0.0097              | \$0.10    | **over-recovers 10×** — merchant overcharged  |
| TRON     | \$1.84                | \$0.10    | **under-recovers 18×** — platform eats \$1.74 |

Worse, the incentive is charged per *distribution*, not per *invoice*. A merchant batching 1,000 small invoices into one distribute pays 50 bps once while the platform paid 1,000 forwarder deploys. TRON needs a \$368 order for 50 bps to cover a single invoice.

## The mechanism

Take the reimbursement at **distribute**, not at sweep, and route it through the existing treasury transfer.

### Final split

```
treasury  0.75% of gross  +  USD gas spent      ← ONE transfer, existing recipient
partner   0.25% of gross                        ← computed on GROSS, unchanged
merchant  gross − treasury − partner
```

Treasury and partner are computed on the **full gross**; the gas is carved from the **merchant share only**. This mirrors how the existing incentive already behaves at `MerchantPool.sol:203`.

<Warning>
  Deducting *off the top, before the split* is wrong. It spreads the cost pro-rata, silently shrinking the partner's 0.25% referral on every deposit-rail order. A regression test must pin that partner and treasury shares are unaffected by deposit-rail gas — partner earnings already display as \$0.00 in the dashboard, so this would go unnoticed.
</Warning>

### bps becomes a ceiling, not a formula

```solidity theme={null}
// today: the contract computes it
incentive = gross * incentiveBps / 10_000;

// after: the caller supplies it, the contract only bounds it
function distribute(IERC20 token, uint256 reimbursement) external {
    require(reimbursement <= cap(gross), "over cap");
    treasuryAmt = gross * treasuryBps / 10_000;   // on GROSS
    partnerAmt  = gross * partnerBps  / 10_000;   // on GROSS
    merchantAmt = gross - treasuryAmt - partnerAmt - reimbursement;
}
```

### The cap must be `min(bps, absolute)`

A bps-only cap recreates the exact mismatch this design exists to fix. TRON's $1.84 needs 200 bps on a $92 order but 500 bps on a $37 one. The cap is immutable at pool deploy while the merchant's tolerance is a mutable setting, so it must be sized for the loosest tolerance they might ever pick — and a 500 bps cap on a $10,000 order authorises a **\$500** claim, which permissionless `distribute()` makes reachable by anyone.

```
cap = min(capBps * gross / 10_000, absoluteMaxTokenUnits)
```

Both immutable in init code, the absolute term set per chain. Self-limiting rather than lossy: excess debt carries forward.

### Recipient is the committed treasury address, never `msg.sender`

<Danger>
  Today's incentive pays `msg.sender` — correct for a permissionless incentive, wrong for a gas reimbursement. Once the merchant presses Claim, **the merchant is `msg.sender`** and would receive their own gas debt. The recipient must be the treasury address fixed in the init code. This is a semantic change from the deployed contract, not a parameter change.
</Danger>

### Why treasury rather than a separate keeper payee

Stablecoin sitting in the keeper address is useless — the keeper needs *native* gas. Whoever receives the reimbursement, treasury must still run sell-stablecoin, buy-native, fund-keeper. A fourth recipient buys nothing operationally while costing 15,000–30,000 gas per distribution, which the merchant pays as part of their Claim transaction.

Accounting stays decomposable: treasury receives `gross × treasuryBps / 10_000 + reimbursement`, and both components are recoverable off-chain because the bps value is committed and known.

## The receipt ledger

The contract never knows about gas. All pricing lives off-chain.

<Steps>
  <Step title="Send">
    Keeper sends the clone-and-sweep transaction.
  </Step>

  <Step title="Read the receipt">
    `gasUsed × effectiveGasPrice` on EVM, `energy_usage_total × sun rate` on TRON.
  </Step>

  <Step title="Snapshot USD at spend time">
    Convert via Chainlink and **store the snapshot**. Do not recompute at distribute — a price move would re-price the debt.
  </Step>

  <Step title="Write the row">
    `(invoice, chain, native_spent, usd_at_spend, token_units)`.
  </Step>

  <Step title="Sum at distribute">
    Total the unreimbursed rows for that pool and token, pass as `reimbursement`, mark them reimbursed.
  </Step>

  <Step title="Carry forward the remainder">
    Anything the cap rejected stays open for the next distribution.
  </Step>
</Steps>

## Carry-forward, never claim-gating

Deduction only works when there is something to deduct from. An underpaid, wrong-token, or never-settled invoice leaves gas spent against a pool with little in it.

The answer is to carry the shortfall to the next distribution, still capped. A merchant who keeps trading always repays; one who stops leaves a small unrecovered balance.

<Danger>
  A carried debt must **never** block or delay `distribute()` or a claim. Blocking a payout is the withholding power described in [Distribution](/settlement/distribution) — it produces the identical merchant net while handing the platform a capability a regulator will treat as custody.
</Danger>

## Second-order effect

Charging the minting merchant for their own invoices' gas largely defuses the self-dealing griefing vector, where an attacker mints invoices at the floor and pays themselves, recovering 99% while the platform eats the gas. The attack stops being economically interesting when the attacker funds it.

## Open commercial decision

Actual-cost billing makes the merchant's effective rate chain-dependent — 1% plus $0.01 on Ethereum, 1% plus $1.84 on TRON. That collides with a single all-in headline number, and the fee disclosure has already needed one correction. A published flat per-chain surcharge may sell better than a true pass-through even though it over- and under-recovers at the margins. See [Open decisions](/economics/open-decisions).
