How it works
Payment link
The sender's browser creates a fresh Arc-compatible wallet and encrypts its private key with a 28-character, high-entropy recovery code.
Instant payment
The sender calls the router. It forwards native USDC to that new wallet in the same transaction and retains nothing.
Wallet delivery
The recipient opens the private link and enters the recovery code. Decryption happens locally, revealing their funded wallet, private key and encrypted backup.
ArcPay does not collect recipient contact details. After payment, the sender can open WhatsApp or their email app with the claim link prefilled. The recovery code should be shared separately.
Security model
- No ArcPay custody
- No contract owner
- No withdrawal function
- No contact collection
- Local wallet generation
- Local key decryption
What appears on-chain
The sender address, generated recipient address, amount, transaction data and a random payment identifier are public on Arc. The note, recovery code and private key are not written to the blockchain.
Who controls the money?
Once the routing transaction succeeds, only the holder of the generated wallet's private key controls its funds. ArcPay cannot recover or move them.
Open-source contract
The live ArcPay router at 0x7Df1eb198f8bd4EdEDd91D0C1Cf9c5e9Eb90107F is released under the permissive MIT license. It receives native USDC and forwards it immediately to the supplied recipient address. Direct transfers to the contract are rejected.
ArcPayRouter.sol
Download Solidity source// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
contract ArcPayRouter {
error InvalidRecipient();
error ZeroAmount();
error TransferFailed();
event PaymentRouted(
bytes32 indexed paymentId,
address indexed sender,
address indexed recipient,
uint256 amount
);
function route(bytes32 paymentId, address payable recipient)
external payable
{
if (recipient == address(0)) revert InvalidRecipient();
if (msg.value == 0) revert ZeroAmount();
(bool sent, ) = recipient.call{value: msg.value}("");
if (!sent) revert TransferFailed();
emit PaymentRouted(paymentId, msg.sender, recipient, msg.value);
}
receive() external payable { revert TransferFailed(); }
fallback() external payable { revert TransferFailed(); }
}Wallet recovery
New claim links contain a compact AES-GCM encrypted private key, never a readable private key. The 28-character recovery code decrypts it inside the recipient's browser. Older encrypted-keystore links remain supported. After unlocking, the recipient sees a confirmation tick, can copy the wallet address, reveal the private key, and download a standard encrypted backup.
The first successful unlock sends a zero-value marker transaction from the generated wallet to itself. This provides an on-chain claimed state without giving ArcPay custody. Later unlocks detect the wallet's outgoing nonce and show “Already claimed on Arc.” The marker uses a small Arc network fee.
The transaction page reads Arc Mainnet directly and shows funding status, amount, sender, generated recipient wallet, block, confirmations and the Arc Explorer record.
The link and recovery code together control the wallet. Treat the message like cash and never forward it.
Important limits
ArcPay is software, not a bank or custodian. Blockchain transactions are irreversible. If the private link and recovery code are lost, ArcPay cannot restore the wallet. Verify the deployed router address before relying on it: 0x7Df1eb198f8bd4EdEDd91D0C1Cf9c5e9Eb90107F.
ArcPay contract address: 0x6d73b37e277E6e69956F261C5d215DfCBD7DDce1.