> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.coinflow.cash/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.coinflow.cash/_mcp/server.

# Settlement to EVM Contracts

> **Warning**
>
> **This page is for advanced / cryptocurrency-native companies.** If that's not you, head back to the [Quickstart](/guides/getting-started/quickstart) for the standard flows.

## Overview

On-chain merchants with custom program logic can choose to settle directly to a smart contract or wallet. Coinflow requires these merchants to pass a transaction to our system. The following section explains how merchants can construct and submit a transaction compatible with their smart contracts.

## Specifying Price

Coinflow supports making purchases in all liquid currencies, you can configure the following properties to select the token and the amount necessary to complete the purchase:

`token` - Address of the token which the purchase is denominated in (if using USDC leave this empty)

`amount` - Amount of that token necessary to complete the purchase

> 📘 If using ETH or MATIC please pass `0x0000000000000000000000000000000000001010`

## Waiting for Transaction Confirmation

By default Coinflow will show the user a success message as soon as the transaction has passed simulation and been submitted to the chain. Because of retry logic + time to confirm we recommend keeping this default behavior as it results in a better user experience.

In the case you want the user to wait until the transaction has confirmed on chain you can add `waitForHash` to the `transaction` object you pass to the Coinflow Purchase Component.

When `waitForHash=true` the onSuccess hook will also include the hash in its return data.

**Example:**

```javascript
<CoinflowPurchase
	...
  transaction={{
  	transaction: ...,
   	waitForHash: true,
  }}
  onSuccess={(userAddress: string, hash: string, {paymentId}: {paymentId: string}) => {
    console.log({paymentId, hash});
  }}
/>
```

## Specifying Transaction

There are multiple different ways of making purchases on EVM compatible blockchains via Coinflow. Each one is specific to what you as a company are selling and how your smart contracts work under the hood. Coinflow is designed for maximum flexibility and provides options so that your company does not need to change their smart contracts.

Ask yourself the following questions to determine which option is the best for you:

1. Are you selling NFTs?
   1. Yes - **Go to question 2**
   2. No - Go to section [Redeem with Custom Receiver Field](#redeem-with-custom-receiver-field)
2. Do you know the ID of the NFT being delivered to the user at the time of transaction creation?
   1. Yes - Go to section [Known Token ID](#known-token-id)
   2. **No - Go to question 3**
3. Does your program use SafeMint to mint the user an NFT?
   1. Yes - Go to section [SafeMint](#safemint)
   2. **No - Go to question 4**
4. Does your program return the NFT token ID in the first 32 bytes of the function call?
   1. Yes - Go to section [Returned Token ID](#returned-token-id)
   2. No - Go to section [Redeem with Custom Receiver Field](#redeem-with-custom-receiver-field)

### Redeem with Custom Receiver Field

> 🚧 Merchant's smart contracts might require changes

**Your Smart Contract needs to implement the following functionality:**

1. The payer for the purchase (ERC-20 token), should be`msg.sender`
2. The smart contract method must support a`receiver` argument, which is the end-user's wallet that is receiving the good or service.

```solidity

function (receiver: address, ...) {
   payer = msg.sender; // Will always be the Coinflow contract.
}
```

When passing the transaction object to the Coinflow SDK or API's please utilize the following format:

```javascript
{
    {
        to: '<YOUR CONTRACT ADDRESS>',
        data: '0x...', // Function call data of the transaction
    }
}
```

### Known Token ID

If during transaction construction, your system knows the contract address and token ID of the NFT, you can specify the NFT Token ID and no changes to your smart contract are required. The Coinflow program will automatically forward the NFT to the customer's wallet.

When passing the transaction object to the Coinflow SDK or API's please utilize the following format:

```javascript
{
	transaction: {
		to: '0x...', // This is your contract's address
		data: '0x...' // This is the data for your contracts function call
	},
	nftContract: '0x...', // This is your NFT's contract address
	nftId: '...' // This is the ID of the NFT
}
```

### SafeMint

If your contract implements [Openzeppelin's SafeMint function](https://docs.openzeppelin.com/contracts/2.x/api/token/erc721), then no changes are required to your contract. The Coinflow contract automatically determines the Token ID, and forwards the NFT to the user.

When passing the transaction object to the Coinflow SDK or API's please utilize the following format:

```javascript
{
	type: "safeMint",
	transaction: {
		to: '0x...', // This is your contract's address
		data: '0x...' // This is the data for your contracts function call
	},
}
```

### Returned Token ID

If your contract returns the Token ID of minted NFT in the first 32 bytes of returnData, then no changes are required to your contract.

When passing the transaction object to the Coinflow SDK or API's please utilize the following format:

```javascript
{
	type: "returned",
	transaction: {
		to: '0x...', // This is your contract's address
		data: '0x...' // This is the data for your contracts function call
	},
}
```