The need for secure and efficient payment gateways is crucial, especially for businesses operating in volatile economic environments. In this tutorial we will be building a non-custodial payment gateway for stablecoins, allowing merchants to accept payments without centralized intermediaries holding their funds.
🎥 Watch the Video Overview: For a visual walkthrough of the implementation, check out our YouTube video: Building a Non-Custodial Stablecoin Payment Gateway on Moonbeam.
Example Use Case
Imagine a merchant selling online products who wishes to accept payments in USDC. Using our gateway, the customer pays in USDC, which is securely routed to the merchant’s wallet, ensuring no third party takes custody of the funds. Our Moonbeam-based implementation showcases one approach to achieving this.
The Moonbeam Solution
This implementation is part of KwickBit’s project funded by the Decentralized Futures Grant from the Web3 Foundation, showcasing innovative solutions for non-custodial payment gateways.
User Flow Logic:
1. Teleport USDC:
- The user teleports USDC from the Asset Hub to Moonbeam, where it is represented as xUSDC.
2. Call the Payment Smart Contract:
- The user interacts with the payment smart contract on Moonbeam, providing payment details such as the amount and a unique payment ID.
3. Process the Payment:
- The smart contract processes the payment, transferring funds to the merchant’s address.
Implementation Logic with Indexer
- The Moonbeam implementation relies on an off-chain indexer that monitors smart contract events.
- The indexer listens for specific payment-related events, such as successful fund transfers, and logs them for further processing.
- Business Logic:Â The indexer can push these events to a queue system like RabbitMQ or Kafka, where another process can handle notifying the merchant and updating their system.
Key Steps:
1. Deploy the smart contract to Moonbeam.
2. Use an indexer to process payment events and update merchant systems with the status.

Smart Contract Highlights (Solidity)
The core logic of the Moonbeam smart contract handles payment verification, processing royalties, and transferring funds. Here’s the key source code:
require(!processedPayments[request.paymentId], "Payment already processed");
// Generate the EIP-712 typed data hash
bytes32 structHash = keccak256(
abi.encode(
keccak256("PaymentRequest(string paymentId,uint256 amount,address payer,address merchantAddress)"),
keccak256(bytes(request.paymentId)),
request.amount,
request.payer,
request.merchantAddress
)
);
bytes32 hash = _hashTypedDataV4(structHash);
// Recover the signer and verify their role
address signer = ECDSA.recover(hash, signature);
require(hasRole(APPROVER_ROLE, signer), "Invalid approver signature");
// Calculate the royalty fee and the amount to be sent to the destination
uint256 royaltyAmount = (request.amount * royaltyPercentage) / 10000;
uint256 amountToTransfer = request.amount - royaltyAmount;
// Transfer royalty to multisig wallet directly from the payer
require(token.transferFrom(request.payer, multisigWallet, royaltyAmount), "ERC20 royalty transfer failed");
require(
token.transferFrom(request.payer, request.merchantAddress, amountToTransfer), "ERC20 transfer to destination failed"
);
// Mark the paymentId as processed
processedPayments[request.paymentId] = true;
// Emit the event
emit ERC20PaymentReceived(
address(token), request.payer, request.amount, request.paymentId, request.merchantAddress, royaltyAmount
);
Explanation of Key Components:
1. Duplicate Payment Prevention: Ensures each paymentId is processed only once.
2. EIP-712 Typed Data: Used for securely hashing and signing the payment details.
3. Royalty Calculation: Deducts a percentage of the payment as royalties, transferring it to a multisig wallet.
4. Event Emission: Emits an ERC20PaymentReceived event, which the indexer uses to notify business systems.
Links
- Learn more about:Â Moonbeam
- Github Repository
- Youtube tutorial:Â Building a Non-Custodial Stablecoin Payment Gateway on Moonbeam
- Check out the second part of this series for our implementation on the Pop network.
Check our article on Medium: https://medium.com/kwickbit/building-a-non-custodial-payment-gateway-on-moonbeam-b7499d426ad9