> For the complete documentation index, see [llms.txt](https://docs.kpk.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.kpk.io/funds/integration/subscription-request.md).

# Subscription request

Subscribing is a two-step flow, just like a standard deposit:

1. **Approve** the shares contract to spend your subscription asset — a standard ERC-20 `approve` call.
2. **Create the request** with `requestSubscription` on the shares contract:

```solidity
function requestSubscription(
    uint256 assetsIn,         // amount of the asset to deposit
    uint256 minSharesOut,     // slippage protection (see Calculate share price)
    address subscriptionAsset,// must be approved for deposits
    address receiver          // who receives the minted shares
) external returns (uint256 requestId);
```

{% hint style="warning" %}
`minSharesOut` is **slippage protection**. The actual shares are computed by the operator from the share price at settlement time; that result must be `≥ minSharesOut` or the request fails the slippage check. Derive it with `previewSubscription` — see [Calculate share price](/funds/integration/calculate-share-price.md).
{% endhint %}

## Example

Subscribing **1,000 USDC** (6 decimals) into a fund. We derive `minSharesOut` from `previewSubscription(assets, 0, asset)` (the `0` uses the fund's last settled price) and apply a 0.5% slippage tolerance.

{% tabs %}
{% tab title="viem" %}

```typescript
import { createWalletClient, createPublicClient, http, parseAbi, parseUnits } from "viem";
import { privateKeyToAccount } from "viem/accounts";
import { mainnet } from "viem/chains";

const SHARES = "0x...";  // fund shares contract — see the fund's Policies and addresses
const USDC   = "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48";

const sharesAbi = parseAbi([
  "function previewSubscription(uint256 assets, uint256 sharesPrice, address subscriptionAsset) view returns (uint256)",
  "function requestSubscription(uint256 assetsIn, uint256 minSharesOut, address subscriptionAsset, address receiver) returns (uint256)",
]);
const erc20Abi = parseAbi(["function approve(address spender, uint256 amount) returns (bool)"]);

const account = privateKeyToAccount("0x...");
const pub = createPublicClient({ chain: mainnet, transport: http() });
const wallet = createWalletClient({ account, chain: mainnet, transport: http() });

const assetsIn = parseUnits("1000", 6); // 1,000 USDC

// 1. Estimate shares at the last settled price, then apply 0.5% slippage tolerance.
const expectedShares = await pub.readContract({
  address: SHARES, abi: sharesAbi, functionName: "previewSubscription",
  args: [assetsIn, 0n, USDC],
});
const minSharesOut = (expectedShares * 9950n) / 10000n;

// 2. Approve, then request.
await wallet.writeContract({ address: USDC, abi: erc20Abi, functionName: "approve", args: [SHARES, assetsIn] });
const hash = await wallet.writeContract({
  address: SHARES, abi: sharesAbi, functionName: "requestSubscription",
  args: [assetsIn, minSharesOut, USDC, account.address],
});
```

{% endtab %}

{% tab title="ethers.js" %}

```typescript
import { ethers } from "ethers";

const SHARES = "0x...";  // fund shares contract — see the fund's Policies and addresses
const USDC   = "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48";

const sharesAbi = [
  "function previewSubscription(uint256 assets, uint256 sharesPrice, address subscriptionAsset) view returns (uint256)",
  "function requestSubscription(uint256 assetsIn, uint256 minSharesOut, address subscriptionAsset, address receiver) returns (uint256)",
];
const erc20Abi = ["function approve(address spender, uint256 amount) returns (bool)"];

const provider = new ethers.JsonRpcProvider("https://eth.llamarpc.com");
const signer = new ethers.Wallet("0x...", provider);
const shares = new ethers.Contract(SHARES, sharesAbi, signer);
const usdc = new ethers.Contract(USDC, erc20Abi, signer);

const assetsIn = ethers.parseUnits("1000", 6); // 1,000 USDC

const expectedShares = await shares.previewSubscription(assetsIn, 0n, USDC);
const minSharesOut = (expectedShares * 9950n) / 10000n; // 0.5% slippage

await (await usdc.approve(SHARES, assetsIn)).wait();
const tx = await shares.requestSubscription(assetsIn, minSharesOut, USDC, await signer.getAddress());
await tx.wait();
```

{% endtab %}

{% tab title="Python" %}

```python
from web3 import Web3

SHARES = "0x..."  # fund shares contract — see the fund's Policies and addresses
USDC   = "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"

shares_abi = [
    {"name": "previewSubscription", "type": "function", "stateMutability": "view",
     "inputs": [{"name": "assets", "type": "uint256"}, {"name": "sharesPrice", "type": "uint256"},
                {"name": "subscriptionAsset", "type": "address"}],
     "outputs": [{"type": "uint256"}]},
    {"name": "requestSubscription", "type": "function", "stateMutability": "nonpayable",
     "inputs": [{"name": "assetsIn", "type": "uint256"}, {"name": "minSharesOut", "type": "uint256"},
                {"name": "subscriptionAsset", "type": "address"}, {"name": "receiver", "type": "address"}],
     "outputs": [{"type": "uint256"}]},
]
erc20_abi = [{"name": "approve", "type": "function", "stateMutability": "nonpayable",
              "inputs": [{"name": "spender", "type": "address"}, {"name": "amount", "type": "uint256"}],
              "outputs": [{"type": "bool"}]}]

w3 = Web3(Web3.HTTPProvider("https://eth.llamarpc.com"))
acct = w3.eth.account.from_key("0x...")
shares = w3.eth.contract(address=SHARES, abi=shares_abi)
usdc = w3.eth.contract(address=USDC, abi=erc20_abi)

assets_in = 1000 * 10**6  # 1,000 USDC

expected = shares.functions.previewSubscription(assets_in, 0, USDC).call()
min_shares_out = expected * 9950 // 10000  # 0.5% slippage

# Build, sign, and send approve + requestSubscription (nonce/gas handling omitted for brevity).
approve = usdc.functions.approve(SHARES, assets_in).build_transaction({"from": acct.address})
# ... sign & send approve ...
req = shares.functions.requestSubscription(
    assets_in, min_shares_out, USDC, acct.address
).build_transaction({"from": acct.address})
# ... sign & send req ...
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}

## Events

Creating a subscription request emits a `SubscriptionRequest` event containing the `requestId`, `cancelableFrom`, and `expiryAt`. Track it as described in [Monitor a request](/funds/integration/monitor-a-request.md).
{% endhint %}

<figure><picture><source srcset="/files/fMRNxtuXyn7U776YiNmf" media="(prefers-color-scheme: dark)"><img src="/files/NFHGzZEDY6sGZWTioZqh" alt=""></picture><figcaption><p>Subscription flow example, with USDC as subscription token.</p></figcaption></figure>


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## 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, and the optional `goal` query parameter:

```
GET https://docs.kpk.io/funds/integration/subscription-request.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

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.
