# Deploying a Vault

A vault is created in a single transaction against the Vault Deployer for the asset you want to hold. The deployer pulls your initial deposit and mints shares to your wallet in the same call.

### Pick the right deployer

One deployer per asset:

| Asset | Deployer                                                                                                                     |
| ----- | ---------------------------------------------------------------------------------------------------------------------------- |
| USDC  | [`0xe4D85722dB649d3890f9DBA4510F1A16AD942FD9`](https://etherscan.io/address/0xe4D85722dB649d3890f9DBA4510F1A16AD942FD9#code) |
| WBTC  | [`0x55073cdF0b0E42C8B807A265EADff69973274a8d`](https://etherscan.io/address/0x55073cdF0b0E42C8B807A265EADff69973274a8d#code) |
| WETH  | [`0x6701241e65d4baFC399Ca4358E95960aF3C041C4`](https://etherscan.io/address/0x6701241e65d4baFC399Ca4358E95960aF3C041C4#code) |

### Read the current minimum initial deposit

Before deploying, read the minimum initial deposit from the deployer — it's configured per asset and can change, so read it on-chain rather than hard-coding.

```ts
const deployerAbi = [
  {type: 'function', stateMutability: 'view', name: 'minInitialDeposit',
   inputs: [], outputs: [{type: 'uint256'}]},
] as const

const minDeposit = await client.readContract({
  address: deployer, abi: deployerAbi, functionName: 'minInitialDeposit',
})
```

### Approve the initial deposit

The deployer needs to be able to pull `initialDeposit` of the underlying asset from your wallet:

```ts
const assetAbi = [{
  type: 'function', stateMutability: 'nonpayable', name: 'approve',
  inputs: [{type: 'address'}, {type: 'uint256'}],
  outputs: [{type: 'bool'}],
}] as const

await walletClient.writeContract({
  address: underlyingToken,
  abi: assetAbi, functionName: 'approve',
  args: [deployer, initialDeposit],
})
```

If the underlying token supports [EIP‑2612 permit](https://eips.ethereum.org/EIPS/eip-2612) (USDC does), you can skip the separate approval transaction by using `deployVaultWithPermit` instead — see below.

### Call `deployVault`

```ts
const deployAbi = [{
  type: 'function', stateMutability: 'nonpayable', name: 'deployVault',
  inputs: [
    {name: 'initialDeposit',    type: 'uint256'},
    {name: 'maxManagementFee',  type: 'uint256'},
    {name: 'maxPerformanceFee', type: 'uint256'},
  ],
  outputs: [/* FusionInstance struct — read from the event instead */],
}] as const

// Fees are in basis points (100 bps = 1%). Default DCV terms are
// 0.25% management (25 bps) and 30% performance (3000 bps) — pass those
// as the slippage caps, unless you've agreed different terms with Tesseract.
const MAX_MGMT_FEE = 25n      // 0.25%
const MAX_PERF_FEE = 3000n    // 30%

const hash = await walletClient.writeContract({
  address: deployer,
  abi: deployAbi,
  functionName: 'deployVault',
  args: [initialDeposit, MAX_MGMT_FEE, MAX_PERF_FEE],
})

const receipt = await client.waitForTransactionReceipt({hash})
```

`maxManagementFee` and `maxPerformanceFee` are slippage guards — the transaction reverts if the deployer's currently configured fees exceed them. Use the agreed contractual values so an accidental on-chain fee bump can't deploy a vault with fees higher than what you signed up for.

### Extract the vault address

The deployer emits a `VaultDeployed` event. Parse it from the receipt:

```ts
import {parseAbiItem, decodeEventLog} from 'viem'

const vaultDeployedEvent = parseAbiItem(
  'event VaultDeployed(address indexed plasmaVault, address indexed owner, address accessManager, address feeManager, address rewardsManager, address withdrawManager, address contextManager, address priceManager)'
)

const log = receipt.logs.find(l => l.address.toLowerCase() === deployer.toLowerCase())
const decoded = decodeEventLog({abi: [vaultDeployedEvent], data: log.data, topics: log.topics})

const vault = decoded.args.plasmaVault
const withdrawManager = decoded.args.withdrawManager
```

Save `plasmaVault` (the vault address you'll interact with for deposits / withdrawals) and `withdrawManager` (per-vault manager for scheduled withdrawals). Both are also discoverable later via the [Public API](/dedicated-client-vaults/reference/public-api.md).

### Using permit (one transaction)

For underlying tokens that support EIP‑2612, you can skip the separate approval and deploy in a single transaction:

```ts
// 1. Generate a permit signature for `initialDeposit` to `deployer`
const {v, r, s, deadline} = await signPermit({...})

// 2. Call the permit variant
await walletClient.writeContract({
  address: deployer,
  abi: /* deployVaultWithPermit ABI */,
  functionName: 'deployVaultWithPermit',
  args: [initialDeposit, mgmtFee, perfFee, deadline, v, r, s],
})
```

***

Once your vault exists, continue to [**Strategy Assignment**](/dedicated-client-vaults/integration-guide/scenario-a/strategy-assignment.md) to start managing it, or [**Deposits**](/dedicated-client-vaults/integration-guide/scenario-a/deposits.md) if you want to add more capital first.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.tesseract.fi/dedicated-client-vaults/integration-guide/scenario-a/deploying-a-vault.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
