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

# Pay USDC and a tokenized stock from a Pot on Solana

> A Solana cook that pays USDC and Backed's TSLAx, a Token-2022 mint, from the Pot to one recipient and returns what arrived of each.

The program pays `recipient` `cash` of USDC and `shares` of TSLAx from the Pot and returns what arrived in the recipient's two token accounts. The cook reverts when the Pot holds less than either amount or the recipient's USDC account receives less than `cash`.

**Target chains:** Solana. Use `--chain solana`; the recorded simulation is described below.

## Prerequisites

You need the `sauce` command (`npm install -g @eco-incorp/sauce`), a Solana key to send from (a keypair file, or `sauce wallet new <name> --solana`), and the USDC and TSLAx in the Pot's token accounts. `--fund` is EVM only: transfer each token to its token account owned by the Pot before running the cook, not to the Pot's address. `sauce pot --chain solana --owner <your-pubkey>` prints the Pot's address; use it as the token accounts' owner. See [Installation](https://docs.eco.com/sauce-sdk/installation.md).

## Program

`pot` is the Pot the program runs on, available without declaring it; `pot.USDC` and `pot.TSLAx` read its token accounts ([Names](https://docs.eco.com/sauce/names.md#balances)).

```ts solana-payment.sauce.ts theme={null}
// Pays `recipient` `cash` of USDC and `shares` of TSLAx (Backed's tokenized Tesla) from the Pot,
// in one cook, and returns what arrived of each, read from the recipient's token accounts before
// and after. USDC is an SPL Token mint; TSLAx is a Token-2022 mint, moved by the checked write
// with its decimals. The cook reverts, and nothing moves, when the Pot holds less than either
// amount or the recipient's USDC account receives less than `cash`.
//
//   sauce simulate solana-payment.sauce.ts --chain solana --owner <pubkey> \
//     --assume-balance USDC:<cash>n --assume-balance TSLAx:<shares>n \
//     --args <recipient> <cash> <shares>
//   sauce run solana-payment.sauce.ts --chain solana --keypair <keypair> \
//     --args <recipient> <cash> <shares>
//
//   recipient: Address  who is paid: a wallet's base58 public key
//   cash: Uint256       the USDC to pay, in USDC's base units (6 decimals): 1000000 is 1 USDC
//   shares: Uint256     the TSLAx to pay, in TSLAx's base units (8 decimals): 50000000 is half a
//                       TSLAx
//
// Pay 1 USDC and half a TSLAx:
//
//   sauce run solana-payment.sauce.ts --chain solana --keypair <keypair> \
//     --args <recipient> 1000000 50000000
function main(
  recipient: Address,
  cash: Uint256,
  shares: Uint256,
): { cashReceived: Uint256; sharesReceived: Uint256 } {
  require(pot.USDC >= cash, "not enough USDC in the Pot");
  require(pot.TSLAx >= shares, "not enough TSLAx in the Pot");

  const usdcBefore = recipient.USDC;
  USDC.transfer(recipient, cash);
  const cashReceived = recipient.USDC - usdcBefore;
  require(cashReceived == cash, "recipient received less USDC than cash");

  // A Token-2022 mint may withhold a transfer fee, so the shares are measured, not assumed.
  const sharesBefore = recipient.TSLAx;
  TSLAx.transfer(recipient, shares);
  const sharesReceived = recipient.TSLAx - sharesBefore;

  return { cashReceived, sharesReceived };
}
```

## How it works

* Both payments are token methods written as on an EVM chain. Compiling adds eight accounts to `main`, each derived when the cook is built: the Pot, its USDC and TSLAx accounts, the recipient's two, SPL Token, Token-2022 and TSLAx's mint. USDC moves by SPL Token's transfer; TSLAx, a Token-2022 mint, by the checked transfer with its 8 decimals and the mint as one more account.
* `recipient.USDC` and `recipient.TSLAx` read the recipient's associated token account for each mint. Each is read before and after its transfer: USDC is required to arrive in full, and `sharesReceived` is returned as measured, because a Token-2022 mint with a transfer fee delivers the amount less the fee.
* After each transfer the token method checks that the account it paid belongs to `recipient`, and reverts with `wrong recipient account` otherwise.
* `sauce compile --json` measures the cook at 2,292 bytes against the 1,232-byte limit, so `sauce run` stages the 1,653-byte payload in a code buffer. The recipient had no TSLAx account: the simulation made it empty, and `sauce run` creates it before the cook, the owner paying its rent.

## Run the example

**1. Compile**

```bash theme={null}
sauce compile solana-payment.sauce.ts --chain solana
sauce compile solana-payment.sauce.ts --chain solana --json --args <recipient> 1000000 50000000
```

`--json` lists the eight accounts in `manifest`, each with its `derive`, and `cook`: 2,292 bytes against the 1,232-byte limit, `"fits": false`.

**2. Simulate**

```bash theme={null}
sauce simulate solana-payment.sauce.ts --chain solana --owner <your-pubkey> \
  --assume-balance USDC:1 --assume-balance TSLAx:1 --args <recipient> 1000000 50000000
```

The two `--assume-balance` flags give the Pot 1 USDC and 1 TSLAx in a local LiteSVM copy of the cook's accounts, read from the cluster. `--owner` must be a wallet's address.

**3. Send**

```bash theme={null}
sauce run solana-payment.sauce.ts --chain solana --keypair <keypair> \
  --args <recipient> 1000000 50000000
```

`sauce run` creates the Pot and the missing token accounts the cook names (asking first, or with `--yes`), stages the program, sends the cook and closes the buffer. `--wallet <name>` signs with a Solana wallet instead. `sauce tx` with `--owner <your-pubkey>` in place of `--keypair <keypair>` prints the run as a plan of unsigned transactions for another signer.

> [!WARNING]
>
> `recipient` is a wallet's public key. A token account given there is taken as a wallet, and the cook pays an associated token account it holds, which no one can spend from.

## Simulation result

Simulated on Solana at slot 460260738 with the command above, in a local LiteSVM copy. Nothing was signed or sent; values change with the slot. Lines that name the owner are left out.

```text theme={null}
...
main returns { cashReceived: Uint256, sharesReceived: Uint256 }: { cashReceived: 1000000, sharesReceived: 50000000 }
Left in the Pot, not in the owner's wallet:
  0.5 TSLAx, in EU1oJiwsneH5XHpzir6JSGAdTf5jAExUedcRTbNeHS1g (it held 1 TSLAx before)
  Only another cook moves it out. To end in a wallet, the program must send it there, or name the wallet as the recipient of the call that produces it.
Simulated in a local copy (LiteSVM) of the 8 accounts the cook names, read from solana at slot 460260738, with the released engine and Kitchen: the cook does not fit one transaction, and no cluster can stage a program without sending. Nothing was signed or sent:
  Kitchen create_pot: Pot BjFSkVpfmbX19SuADFxTsfzWdTErjdELMyd4Nd4iXo9T is not created on solana yet, so the copy creates it first
  the 1653-byte program staged into a code buffer in 4 transactions, as `sauce run` stages it
...
Token balance changes:
  6Cz6ZMnQAE4D9UFUyxpsdWYHtkJ5h315eBAFvq8gRSGs (potUSDC, the Pot's USDC account), owned by BjFSkVpfmbX19SuADFxTsfzWdTErjdELMyd4Nd4iXo9T (the Pot): -1 USDC
  EU1oJiwsneH5XHpzir6JSGAdTf5jAExUedcRTbNeHS1g (potTSLAx, the Pot's TSLAx account), owned by BjFSkVpfmbX19SuADFxTsfzWdTErjdELMyd4Nd4iXo9T (the Pot): -0.5 TSLAx
  7dQmths1cyCQ4xaC5KcVfXz4BvVWtnHc3hcgnfnE1PBx (recipientUSDC, main's argument recipient's USDC account), owned by H8sMJSCQxfKiFTCfDR3DUMLPwcRbM61LGFJ8N4dK3WjS: +1 USDC
  DkAm371NA8pvGLRZXpMjvbw6Pu5xQL1FjPmognKEPVUN (recipientTSLAx, main's argument recipient's TSLAx account), owned by H8sMJSCQxfKiFTCfDR3DUMLPwcRbM61LGFJ8N4dK3WjS: +0.5 TSLAx
...
```

Both amounts arrived in full: 1 USDC and 0.5 TSLAx, so TSLAx withheld no transfer fee. The other 0.5 TSLAx the simulation assumed stays in the Pot.

Asking for 2 TSLAx (`200000000`) with 1 in the Pot, and `--expect-revert "not enough TSLAx in the Pot"`:

```text theme={null}
As expected, the cook reverts: the program threw "not enough TSLAx in the Pot"
The cook reverts: the program threw "not enough TSLAx in the Pot"
Simulated in a local copy (LiteSVM) of the 8 accounts the cook names, read from solana at slot 460260760, with the released engine and Kitchen: the cook does not fit one transaction, and no cluster can stage a program without sending. Nothing was signed or sent:
...
```

## Next steps

* [Pay](https://docs.eco.com/quickstarts/sauce/pay.md): one USDC payment from the Pot on Base, Ethereum or Arc
* [Buy a tokenized stock](https://docs.eco.com/quickstarts/sauce/buy-tokenized-stock.md): buying a stock token on Ethereum
* [Wrap SOL](https://docs.eco.com/quickstarts/sauce/solana-wrap-sol.md): calls into the System Program and SPL Token with the accounts written out
* [Tokens](https://docs.eco.com/sauce-sdk/reference/tokens.md), [`sauce pot`](https://docs.eco.com/sauce-sdk/cli/pot), [`sauce simulate`](https://docs.eco.com/sauce-sdk/cli/simulate)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.