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

# Deployment

> Deploy Flash-Loan Router contracts to Ethereum networks

export const InlineResource = ({value, copyValue, href, chain, explorerHref, explorerType = "address", explorerSuffix = "", showCopy = true, showExplorer = false, openInNewTab}) => {
  const explorerBases = {
    arbitrum: "https://arbiscan.io",
    arbitrum_one: "https://arbiscan.io",
    avalanche: "https://snowscan.xyz",
    base: "https://basescan.org",
    bnb: "https://bscscan.com",
    ethereum: "https://etherscan.io",
    gnosis: "https://gnosisscan.io",
    ink: "https://explorer.inkonchain.com",
    linea: "https://lineascan.build",
    mainnet: "https://etherscan.io",
    optimism: "https://optimistic.etherscan.io",
    plasma: "https://plasmascan.to",
    polygon: "https://polygonscan.com",
    sepolia: "https://sepolia.etherscan.io",
    xdai: "https://gnosisscan.io"
  };
  const isExternalUrl = (candidate = "") => (/^https?:\/\//i).test(candidate);
  const isHexAddress = (candidate = "") => (/^0x[a-fA-F0-9]{40}$/).test(candidate);
  const normalizeUrl = (candidate = "") => {
    if (!candidate) {
      return "";
    }
    if (candidate.startsWith("/") || candidate.startsWith("#") || isExternalUrl(candidate)) {
      return candidate;
    }
    return `https://${candidate}`;
  };
  const compactUrl = (candidate = "") => {
    const withoutProtocol = candidate.replace(/^https?:\/\//i, "");
    if (withoutProtocol.length <= 40) {
      return withoutProtocol;
    }
    const [host, ...segments] = withoutProtocol.split("/");
    if (!segments.length) {
      return `${withoutProtocol.slice(0, 20)}...${withoutProtocol.slice(-12)}`;
    }
    const tail = segments.length >= 2 ? `${segments[segments.length - 2]}/${segments[segments.length - 1]}` : segments[segments.length - 1];
    return `${host}/.../${tail}`;
  };
  const resolvedExplorerHref = (() => {
    if (explorerHref) {
      return explorerHref;
    }
    if (!chain || !value) {
      return "";
    }
    const base = explorerBases[chain];
    if (!base) {
      return "";
    }
    return `${base}/${explorerType}/${value}${explorerSuffix}`;
  })();
  const resolvedHref = normalizeUrl(href || "");
  const primaryHref = resolvedHref || (showExplorer ? resolvedExplorerHref : "");
  const primaryTarget = openInNewTab ?? (primaryHref ? isExternalUrl(primaryHref) : false);
  const shouldCompactValue = isExternalUrl(value || "") || isExternalUrl(primaryHref);
  const displayValue = shouldCompactValue ? compactUrl(value) : value;
  const contentClassName = ["inline-resource__value", shouldCompactValue ? "inline-resource__value--compact" : "", isHexAddress(value || "") ? "inline-resource__value--address" : ""].filter(Boolean).join(" ");
  const setButtonState = (button, state, label) => {
    if (!button) {
      return;
    }
    button.dataset.state = state;
    button.setAttribute("aria-label", label);
    button.title = label;
    if (button.__copyTimer) {
      window.clearTimeout(button.__copyTimer);
      button.__copyTimer = null;
    }
    if (state === "idle") {
      return;
    }
    button.__copyTimer = window.setTimeout(() => {
      button.dataset.state = "idle";
      button.setAttribute("aria-label", "Copy value");
      button.title = "Copy value";
    }, 1200);
  };
  const fallbackCopy = text => {
    if (typeof document === "undefined") {
      return false;
    }
    const input = document.createElement("textarea");
    input.value = text;
    input.setAttribute("readonly", "");
    input.style.left = "-9999px";
    input.style.position = "absolute";
    document.body.appendChild(input);
    input.select();
    let copied = false;
    try {
      copied = document.execCommand("copy");
    } catch {
      copied = false;
    }
    document.body.removeChild(input);
    return copied;
  };
  const copyText = async (text, button) => {
    if (!text) {
      setButtonState(button, "copied", "Nothing to copy");
      return;
    }
    try {
      if (typeof navigator !== "undefined" && navigator.clipboard?.writeText) {
        await navigator.clipboard.writeText(text);
        setButtonState(button, "copied", "Copied");
        return;
      }
    } catch {}
    const copied = fallbackCopy(text);
    setButtonState(button, copied ? "copied" : "idle", copied ? "Copied" : "Copy failed");
  };
  const content = <code className={contentClassName} title={value}>
      {displayValue}
    </code>;
  return <span className="inline-resource">
      {primaryHref ? <a className="inline-resource__link" href={primaryHref} rel={primaryTarget ? "noreferrer noopener" : undefined} target={primaryTarget ? "_blank" : undefined} title={value}>
          {content}
        </a> : content}

      {showCopy || showExplorer && resolvedExplorerHref && resolvedExplorerHref !== primaryHref ? <span className="inline-resource__actions">
          {showCopy ? <button aria-label="Copy value" className="inline-resource__action" data-state="idle" onClick={event => copyText(copyValue || value, event.currentTarget)} title="Copy value" type="button">
              <span className="inline-resource__icon inline-resource__icon--copy">
                <CopyIcon />
              </span>
              <span className="inline-resource__icon inline-resource__icon--check">
                <CheckIcon />
              </span>
            </button> : null}

          {showExplorer && resolvedExplorerHref && resolvedExplorerHref !== primaryHref ? <a aria-label="Open in explorer" className="inline-resource__action" href={resolvedExplorerHref} rel="noreferrer noopener" target="_blank" title="Open in explorer">
              <span className="inline-resource__icon">
                <ExternalLinkIcon />
              </span>
            </a> : null}
        </span> : null}
    </span>;
};

## Overview

This guide covers the basic deployment process for the Flash-Loan Router contracts. The contracts are deployed using Foundry's scripting system and support deterministic deployment via CREATE2, ensuring the same addresses across all networks.

<Note>
  For detailed deployment operations, monitoring, and advanced configuration, see the [Operations](/flash-loan-router/operations/deployment-guide) section.
</Note>

## Deployed Addresses

All contracts are deployed deterministically with CREATE2 and share the same addresses across supported networks:

* `FlashLoanRouter`: <InlineResource value="0x9da8B48441583a2b93e2eF8213aAD0EC0b392C69" chain="ethereum" showExplorer />
* `AaveBorrower`: <InlineResource value="0x7d9C4DeE56933151Bc5C909cfe09DEf0d315CB4A" chain="ethereum" showExplorer />
* `ERC3156Borrower`: <InlineResource value="0x47d71b4B3336AB2729436186C216955F3C27cD04" chain="ethereum" showExplorer />

See [`networks.json`](https://github.com/cowprotocol/flash-loan-router/blob/main/networks.json) for complete deployment details by chain ID.

## Prerequisites

Before deploying, ensure you have:

<Steps>
  <Step title="Environment setup">
    Configure your `.env` file with the required variables:

    ```bash theme={null}
    # Required for deployment
    CHAIN_ID=1
    ETH_RPC_URL=https://eth-mainnet.g.alchemy.com/v2/YOUR_API_KEY
    PRIVATE_KEY=your_private_key_here

    # Optional: for contract verification
    ETHERSCAN_API_KEY=your_etherscan_api_key
    ```

    Load the environment variables:

    ```bash theme={null}
    source .env
    ```

    <Warning>
      Ensure your deployer account has sufficient ETH for gas fees on the target network.
    </Warning>
  </Step>

  <Step title="Verify compilation">
    Build the contracts to ensure they compile successfully:

    ```bash theme={null}
    forge build
    ```
  </Step>
</Steps>

## Deployment Options

### Deploy All Contracts

To deploy all contracts (FlashLoanRouter, AaveBorrower, and ERC3156Borrower) in a single transaction:

<Steps>
  <Step title="Dry-run the deployment">
    Simulate the deployment without broadcasting:

    ```bash theme={null}
    forge script script/DeployAllContracts.s.sol:DeployAllContracts \
      --rpc-url $ETH_RPC_URL \
      --private-key $PRIVATE_KEY
    ```

    Review the output to verify:

    * Gas estimates
    * Contract addresses
    * Constructor arguments
  </Step>

  <Step title="Broadcast the deployment">
    Execute the deployment on the network:

    ```bash theme={null}
    forge script script/DeployAllContracts.s.sol:DeployAllContracts \
      --rpc-url $ETH_RPC_URL \
      --private-key $PRIVATE_KEY \
      --broadcast
    ```
  </Step>

  <Step title="Verify contracts (optional)">
    Add the `--verify` flag to automatically verify contracts on Etherscan:

    ```bash theme={null}
    forge script script/DeployAllContracts.s.sol:DeployAllContracts \
      --rpc-url $ETH_RPC_URL \
      --private-key $PRIVATE_KEY \
      --broadcast \
      --verify
    ```

    <Note>
      Ensure `ETHERSCAN_API_KEY` is set in your `.env` file for verification to work.
    </Note>
  </Step>
</Steps>

### Deploy a Single Contract

For deploying individual contracts, use the scripts in `script/single-deployment/`:

<Tabs>
  <Tab title="FlashLoanRouter">
    ```bash theme={null}
    forge script script/single-deployment/DeployFlashLoanRouter.s.sol:DeployFlashLoanRouter \
      --rpc-url $ETH_RPC_URL \
      --private-key $PRIVATE_KEY \
      --broadcast
    ```
  </Tab>

  <Tab title="AaveBorrower">
    ```bash theme={null}
    # Set the FlashLoanRouter address first
    export FLASHLOAN_ROUTER_ADDRESS=0x9da8B48441583a2b93e2eF8213aAD0EC0b392C69

    forge script script/single-deployment/DeployAAVEBorrower.s.sol:DeployAAVEBorrower \
      --rpc-url $ETH_RPC_URL \
      --private-key $PRIVATE_KEY \
      --broadcast
    ```
  </Tab>

  <Tab title="ERC3156Borrower">
    ```bash theme={null}
    # Set the FlashLoanRouter address first
    export FLASHLOAN_ROUTER_ADDRESS=0x9da8B48441583a2b93e2eF8213aAD0EC0b392C69

    forge script script/single-deployment/DeployERC3156Borrower.s.sol:DeployERC3156Borrower \
      --rpc-url $ETH_RPC_URL \
      --private-key $PRIVATE_KEY \
      --broadcast
    ```
  </Tab>
</Tabs>

## Contract Verification

If you need to verify already deployed contracts manually:

<CodeGroup>
  ```bash FlashLoanRouter theme={null}
  forge verify-contract \
    0x9da8B48441583a2b93e2eF8213aAD0EC0b392C69 \
    src/FlashLoanRouter.sol:FlashLoanRouter \
    --chain-id $CHAIN_ID \
    --etherscan-api-key $ETHERSCAN_API_KEY \
    --constructor-args $(cast abi-encode "constructor(address)" 0x9008D19f58AAbD9eD0D60971565AA8510560ab41)
  ```

  ```bash AaveBorrower theme={null}
  forge verify-contract \
    0x7d9C4DeE56933151Bc5C909cfe09DEf0d315CB4A \
    src/AaveBorrower.sol:AaveBorrower \
    --chain-id $CHAIN_ID \
    --etherscan-api-key $ETHERSCAN_API_KEY \
    --constructor-args $(cast abi-encode "constructor(address)" 0x9da8B48441583a2b93e2eF8213aAD0EC0b392C69)
  ```

  ```bash ERC3156Borrower theme={null}
  forge verify-contract \
    0x47d71b4B3336AB2729436186C216955F3C27cD04 \
    src/ERC3156Borrower.sol:ERC3156Borrower \
    --chain-id $CHAIN_ID \
    --etherscan-api-key $ETHERSCAN_API_KEY \
    --constructor-args $(cast abi-encode "constructor(address)" 0x9da8B48441583a2b93e2eF8213aAD0EC0b392C69)
  ```
</CodeGroup>

## Deployment Flow

The `DeployAllContracts` script follows this sequence:

1. **Deploy FlashLoanRouter** - The main router contract that coordinates flash loans and settlements
2. **Deploy AaveBorrower** - Adapter for Aave flash-loan protocol (requires FlashLoanRouter address)
3. **Deploy ERC3156Borrower** - Adapter for ERC-3156 compatible lenders (requires FlashLoanRouter address)

Each borrower contract needs the FlashLoanRouter address as a constructor argument.

## Updating Deployment Records

After deployment, update the `networks.json` file to track your deployment:

<Steps>
  <Step title="Generate networks file">
    The `networks.json` file is generated automatically from broadcast files:

    ```bash theme={null}
    bash script/generate-networks-file.sh > networks.json
    ```
  </Step>

  <Step title="Manual deployments">
    For deployments done outside of Forge scripts, manually update:

    ```bash theme={null}
    # Edit the manual networks file
    vim broadcast/networks-manual.json
    ```

    Then regenerate:

    ```bash theme={null}
    bash script/generate-networks-file.sh > networks.json
    ```
  </Step>
</Steps>

## Network Support

The Flash-Loan Router supports deployment to all networks where CoW Protocol is deployed and flash-loan lenders (Aave, Maker, etc.) are available.

CoW Protocol is deployed on the following networks:

| Network           | Chain ID | Type      |
| ----------------- | -------- | --------- |
| Ethereum          | 1        | Mainnet   |
| Gnosis Chain      | 100      | Mainnet   |
| Arbitrum One      | 42161    | Layer 2   |
| Base              | 8453     | Layer 2   |
| Polygon           | 137      | Sidechain |
| Avalanche C-Chain | 43114    | Sidechain |
| BNB Smart Chain   | 56       | Sidechain |
| Optimism          | 10       | Layer 2   |
| Linea             | 59144    | Layer 2   |
| Plasma            | 9745     | Layer 2   |
| Ink               | 57073    | Layer 2   |
| Sepolia           | 11155111 | Testnet   |

For the complete list of deployment addresses per network, see the [networks.json](https://github.com/cowprotocol/flash-loan-router/blob/main/networks.json) file.

## Deployment Checklist

Before deploying to production:

* [ ] Verify all environment variables are set correctly
* [ ] Run a dry-run deployment on the target network
* [ ] Ensure deployer account has sufficient ETH for gas
* [ ] Review gas estimates and contract addresses
* [ ] Test deployment on a testnet first
* [ ] Verify contracts on block explorer
* [ ] Update `networks.json` with new deployment addresses
* [ ] Document any network-specific configuration

## Next Steps

<CardGroup cols={2}>
  <Card title="Operations Guide" icon="gears" href="/flash-loan-router/operations/deployment-guide">
    Learn advanced deployment operations and monitoring
  </Card>

  <Card title="Router Design" icon="plug" href="/flash-loan-router/concepts/router-design">
    Integrate flash loans into your CoW Protocol settlements
  </Card>

  <Card title="Security" icon="shield" href="/flash-loan-router/concepts/security-model">
    Understand the security model and best practices
  </Card>

  <Card title="Networks" icon="globe" href="/flash-loan-router/operations/networks">
    View all deployment addresses by network
  </Card>
</CardGroup>
