> ## 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.

# Route WETH to USDT over Uniswap V2 and Curve

> One Ethereum transaction that sells WETH for USDC on the Uniswap V2 pair, then that USDC for USDT in Curve's 3pool, with a minimum on each leg.

The program sells `amount` WETH for USDC on the Uniswap V2 WETH/USDC pair, then exactly the USDC that leg delivered for USDT in Curve's 3pool, paid to `recipient`, and returns each leg's output. The cook reverts when the pair is missing, the first leg delivers less than `minUsdc`, the recipient receives less than `minUsdt`, or either leg leaves its input token in the Pot.

**Target chains:** Ethereum. The recorded simulation uses an Ethereum fork.

## Prerequisites

Install the [Sauce CLI](https://docs.eco.com/sauce-sdk/installation.md) to compile and simulate. To send the transaction, configure a wallet with funds for gas and the Kitchen fee, and provide WETH in your Pot once it is deployed, or through [`--fund`](https://docs.eco.com/sauce-sdk/cli/funding).

## Program

`pot` is the Pot the program runs on, available without declaring it ([Names](https://docs.eco.com/sauce/names.md#balances)).

```ts multi-venue-route.sauce.ts theme={null}
// Sells `amount` of the Pot's WETH for USDC on the Uniswap V2 WETH/USDC pair, then that USDC for
// USDT in Curve's 3pool, and pays the USDT to `recipient`. Both venues are paid before they swap,
// so each leg spends its whole input or reverts. The cook reverts, and nothing moves, when the
// pair is missing, the first leg delivers less than `minUsdc`, `recipient` receives less than
// `minUsdt`, or either leg leaves its input token in the Pot.
//
//   sauce simulate multi-venue-route.sauce.ts --chain ethereum --owner <address> \
//     --assume-balance WETH:<amount>n --args <amount> <minUsdc> <minUsdt> <recipient>
//   sauce run multi-venue-route.sauce.ts --chain ethereum --wallet <name> \
//     --fund WETH:<amount>n --args <amount> <minUsdc> <minUsdt> <recipient>
//
//   amount: Uint256      the WETH to sell, in wei (18 decimals): 1000000000000000000 is 1 WETH
//   minUsdc: Uint256     the least USDC the Uniswap V2 leg may deliver, in USDC base units
//                        (6 decimals): 2300000000 is 2,300 USDC
//   minUsdt: Uint256     the least USDT `recipient` may receive, in USDT base units (6 decimals):
//                        2290000000 is 2,290 USDT
//   recipient: Address   receives the USDT
//
// On Ethereum, sell 1 WETH for at least 2,300 USDC, then at least 2,290 USDT for <recipient>:
//
//   sauce run multi-venue-route.sauce.ts --chain ethereum --wallet me --fund WETH:1 \
//     --args 1000000000000000000 2300000000 2290000000 <recipient>
import { curve, uniswapV2 } from "@sauce/router";

function main(
  amount: Uint256,
  minUsdc: Uint256,
  minUsdt: Uint256,
  recipient: Address,
): { usdc: Uint256; usdt: Uint256 } {
  require(amount > 0, "amount is 0");
  require(recipient != 0, "no recipient");
  const wethBefore = pot.WETH;
  require(wethBefore >= amount, "not enough WETH in the Pot");
  const pair = UniswapV2.Factory.getPair(WETH, USDC);
  require(pair != 0, "no WETH/USDC pair");

  // Leg 1: WETH to USDC on the V2 pair (fee 3000, its 0.3%), output kept in the Pot.
  const usdcBefore = pot.USDC;
  uniswapV2(pair, WETH, USDC, amount, 3000, 0, pot);
  const usdc = pot.USDC - usdcBefore;
  require(pot.WETH == wethBefore - amount, "leg 1 left WETH in the Pot");
  require(usdc >= minUsdc, "leg 1 below minUsdc");

  // Leg 2: exactly the USDC leg 1 delivered, to USDT in the 3pool (USDC is coin 1, USDT coin 2),
  // paid to the recipient.
  const usdtBefore = recipient.USDT;
  curve(Curve.ThreePool, USDC, USDT, usdc, 1, 2, false, 0, recipient);
  const usdt = recipient.USDT - usdtBefore;
  require(pot.USDC == usdcBefore, "leg 2 left USDC in the Pot");
  require(usdt >= minUsdt, "leg 2 below minUsdt");

  return { usdc, usdt };
}
```

## How it works

* Both venues are paid before they swap: `uniswapV2` transfers the WETH to the pair and calls its `swap`, and `curve` approves exactly `usdc` for the 3pool to pull in `exchange`. A paid-first swap spends its whole input or reverts, and each leg checks the Pot's input balance afterwards (`leg 1 left WETH in the Pot`, `leg 2 left USDC in the Pot`).
* Each leg's output is a measured balance change, the Pot's USDC and then `recipient.USDT`, compared with `minUsdc` and `minUsdt` under the program's own revert reasons. The library's `minOut` is `0` because the program checks the measured amount in the same cook.
* The second leg sells `usdc`, what the first leg delivered, not the Pot's USDC balance, so USDC the Pot held before the cook is not sold.
* In `curve(Curve.ThreePool, USDC, USDT, usdc, 1, 2, false, ...)`, `1` and `2` are the 3pool's coin indices for USDC and USDT, and `false` selects the `int128` index form of a StableSwap pool.

## Run the example

**1. Compile**

```bash theme={null}
sauce compile multi-venue-route.sauce.ts --chain ethereum
```

**2. Simulate**

```bash theme={null}
sauce simulate multi-venue-route.sauce.ts --chain ethereum --owner <your-address> \
  --assume-balance WETH:1 --args 1000000000000000000 2300000000 2290000000 <recipient>
```

`--assume-balance WETH:1` gives the Pot 1 WETH for this simulation only. The result lists each leg's output and every transfer the cook made.

**3. Send**

```bash theme={null}
sauce run multi-venue-route.sauce.ts --chain ethereum --wallet <name> \
  --fund WETH:1 --args 1000000000000000000 2300000000 2290000000 <recipient>
```

`--fund WETH:1` pulls 1 WETH from the wallet into the Pot in the same cook. `sauce tx` prints the unsigned transaction instead, for your own signer, with the same funding and arguments:

```bash theme={null}
sauce tx multi-venue-route.sauce.ts --chain ethereum --owner <your-address> \
  --fund WETH:1 --args 1000000000000000000 2300000000 2290000000 <recipient>
```

## Simulation result

Simulated on a local fork of Ethereum at block 26278321 with the current contracts. Nothing was signed or sent; values change with the block.

```text theme={null}
The cook succeeds from 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266: gas used 348404 for the cook, after the Pot's deploy (1. below), returns 0x000000000000000000000000000000000000000000000000000000008a3c11c6000000000000000000000000000000000000000000000000000000008a62d467
main returns { usdc: Uint256, usdt: Uint256 }: { usdc: 2319192518, usdt: 2321732711 }
...
What moved, in order:
...
  [3] Pot                -> 0xB4e1…C9Dc                  1 WETH
  [4] 0xB4e1…C9Dc        -> Pot                          2319.192518 USDC
  [5] Pot                -> Curve.ThreePool 0xbEbc…F1C7  2319.192518 USDC
  [6] Curve.ThreePool    -> Pot                          2321.732711 USDT
  [7] Pot                -> 0x7099…79C8                  2321.732711 USDT
Approvals:
  0xDcFCc75A3C9a0EC798CAf81B6C84D4c5d5988c49 (the Pot) lets 0xbEbc44782C7dB0a1A60Cb6fe97d0b483032FF1C7 (Curve.ThreePool) spend 2319.192518 USDC
Net balance changes:
  0xDcFCc75A3C9a0EC798CAf81B6C84D4c5d5988c49 (the Pot): -1 WETH
  0xB4e16d0168e52d35CaCD2c6185b44281Ec28C9Dc: +1 WETH, -2319.192518 USDC
  0xbEbc44782C7dB0a1A60Cb6fe97d0b483032FF1C7 (Curve.ThreePool): +2319.192518 USDC, -2321.732711 USDT
  0x70997970C51812dc3A010C7d01b50e0d17dc79C8: +2321.732711 USDT
  0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 (owner): -0.00003728943124295 ETH
...
```

The first leg sold 1 WETH to the pair (0xB4e1…C9Dc) for 2,319.192518 USDC, and the second sold all of it in the 3pool for 2,321.732711 USDT, paid to the recipient. The Pot's net change is the 1 WETH sold; the 3pool's approval is the exact USDC it pulled.

On the same fork, with `minUsdt` at 2,400 USDT (`2400000000`), the second leg's check reverts the cook, the first leg's swap included:

```bash theme={null}
sauce simulate multi-venue-route.sauce.ts --chain ethereum --owner <your-address> \
  --assume-balance WETH:1 \
  --args 1000000000000000000 2300000000 2400000000 <recipient> \
  --expect-revert "leg 2 below minUsdt"
```

```text theme={null}
As expected, the cook reverts: the program threw "leg 2 below minUsdt"
The cook reverts: the program threw "leg 2 below minUsdt"
...
```

## Next steps

* [Oracle-guarded swap](https://docs.eco.com/quickstarts/sauce/oracle-guarded-swap.md): one leg, gated on Chainlink's price and stopped by a price limit.
* [Distributed swap](https://docs.eco.com/quickstarts/sauce/distributed-swap.md): one order across several price-limited pools.
* [`sauce simulate`](https://docs.eco.com/sauce-sdk/cli/simulate), [`sauce run`](https://docs.eco.com/sauce-sdk/cli/run), [`sauce tx`](https://docs.eco.com/sauce-sdk/cli/tx), [Names](https://docs.eco.com/sauce/names.md)


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