Skip to main content
International payments require burning a source currency, applying an exchange rate, and minting the destination currency to the receiver, coordinating multiple actors (bank, sender, FX provider) across each step. This solution blueprint shows how to orchestrate that flow on-chain with DFNS wallets handling the key management and transaction signing.

Get the code

Clone the repository to follow along.
The system involves three main actors:

Bank

Deploys contracts, mints tokens, manages roles, and sets the FX rate for each payment

Sender

Initiates payments in the source currency (e.g., iEUR)

Receiver

Receives funds in the destination currency (e.g., iAUD)
Setup: The Bank deploys two stablecoins (iEUR and iAUD) and the CrossBorderPayment contract. Payment flow:
  1. The Sender initiates a payment, specifying the receiver and amount in iEUR
  2. The Bank sets the conversion rate (how much iAUD the receiver gets)
  3. The Sender executes the payment. iEUR is burned from the sender and iAUD is minted to the receiver

Prerequisites

  1. Clone the cross-border-payments solution
  2. Create a DFNS organization if you don’t have one already, and note the organization id
  3. Create a service account for API access (see the service account guide)
  4. Create 3 wallets: Bank, Sender and Receiver on an EVM-compatible network (e.g.: Ethereum Sepolia)
  5. Fund the Bank and Sender wallets with Testnet ETH for gas fees (see using testnets)
  6. Make sure you have installed Node.js v18+

Project Structure

Configuration

1

Clone and install

2

Set up environment variables

Copy the example environment file and fill in your values:
.env
3

Compile contracts

Deploy the System

This script:
  1. Deploys iEUR (source stablecoin)
  2. Deploys iAUD (destination stablecoin)
  3. Deploys the CrossBorderPayment contract
  4. Transfers iAUD ownership to the payment contract (so it can mint on settlement)
  5. Mints 1000 iEUR to the Sender wallet
Save the three contract addresses from the output.

End-to-End Payment Flow

1

Grant the MINTER_ROLE to the CrossBorderPayment contract

The payment contract needs permission to mint iAUD when settling payments:
2

Initiate a payment (Sender)

The sender initiates a 100 iEUR payment to the receiver. This approves the token transfer and calls initPayment in one step:
Note the Payment ID from the output.
3

Set the FX rate (FX Provider)

The FX provider sets how much iAUD the receiver will get. For example, 150 iAUD for 100 iEUR (1.5x rate):
4

Execute the payment (Sender)

The sender confirms and executes the payment. This burns iEUR from the sender and mints iAUD to the receiver:
5

Verify balances

  • Sender: 900 iEUR (100 burned)
  • Receiver: 150 iAUD (150 minted)

Run the Test Suite

The test suite verifies the full payment flow on a local Hardhat network (no DFNS credentials needed):

Settle to fiat with Payouts

If your cross-border flow ends in fiat bank deposits rather than on-chain tokens, use Payouts to convert stablecoins (USDC, USDT, EURC) to local currency across 94 countries and 63 currencies. See the usage guide or developer guide.
Last modified on July 8, 2026