syrupUSDC Native Mint/Redeem
Enable syrupUSDC deposits and withdrawals in your app via CCIP on chains other than Ethereum. For wallets, apps, DEXes, custody solutions etc.
Deposits & withdrawals for Solana & EVM chains are only available for syrupUSDC. syrupUSDT support is coming in Q2 2026.
Overview
Maple's receiver contract processes programmable token transfers via CCIP messages. The receiver contract handles two types of operations:
Deposits: When USDC is sent to the receiver, it processes a deposit operation
Withdrawals: When SyrupUSDC is sent to the receiver, it processes a withdrawal operation
This guide covers sending messages from Solana to Ethereum (testnet), but the same principles apply to EVM-to-EVM transfers with appropriate token address changes.
Step By Step Guide
1. Prerequisites
This guide uses
@chainlink/ccip-sdkv0.95. The stable v1.0 release will be available shortly.
Node.js 20 or higher
@chainlink/ccip-sdk^0.95.0 - install via npm@solana/web3.js^1.98.4@solana/wallet-adapter-react(for wallet integration)ethers^6.13.4 (for EVM address conversion)viem^2.43.5 (for EVM chain interactions)
Installation
2. Receiver Contract Details
Testnet Deployment (Ethereum Sepolia)
Receiver Address:
0x02b6a75c5d1f430f0614dc5ac8ad5f9d35fba2c4Receiver Address (bytes32):
0x00000000000000000000000002b6a75c5d1f430f0614dc5ac8ad5f9d35fba2c4Pool Address:
0x3EB612858EE843eBb14Df37b9Ec2c7c82B23eE2BDestination Chain: Ethereum Sepolia
Chain Selector:
16015286601757825753
⚠ These addresses are for testnet only. When deploying to mainnet, you must update all addresses to be mainnet from Asset Integration.
Token Addresses
Solana (Devnet):
USDC Mint:
4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDUPool Token Mint:
6Sn78bdY12h6j5wVzeXqYrTZboKPqBtqjB4p5xsRNFaX
Ethereum (Sepolia Testnet):
USDC: Different from Solana - use the USDC contract address on Ethereum Sepolia
syrupUSDC: Use the syrupUSDC contract address on Ethereum Sepolia
⚠ For EVM-to-EVM deposits and withdrawals, use the appropriate USDC or syrupUSDC addresses for the destination chain from Asset Integration.
3. Message Structure
The Maple receiver contract expects a UniversalMessage struct encoded as ABI-encoded bytes:
Field Descriptions
universalSenderAddress (
bytes32): The Solana sender's public key converted to bytes32 formatExample:
2hVTZGxQZTpPjarHQsnQfnRSGSy8LPy85szn8Wy4sj5V→0x193b18c1b4280b6fcb542dc733cfccc3b4e56b287e04647317bdb129685854ac
pool (
address): The Maple pool contract address on EthereumTestnet:
0x3EB612858EE843eBb14Df37b9Ec2c7c82B23eE2B
metaData (
bytes32): Used to identify the source of deposits/withdrawals. Used for incentive campaigns and support. Use0:[your protocol name]encoded as bytes32E.g.
0:mapleas bytes32Default:
0x0000000000000000000000000000000000000000000000000000000000000000
4. Building the Message
Step 1: Convert Solana Address to bytes32
Step 2: Encode the Struct
Step 3: Convert Receiver Address to bytes32
5. Gas Estimation
⚠ Always use
estimateReceiveExecutionto estimate gas limits. Never hardcode gas values as they vary based on message data, token amounts, and receiver contract complexity.
Gas estimation determines how much gas is needed for the receiver contract to execute the message on the destination chain. The CCIP SDK provides accurate gas estimation through the estimateReceiveExecution function, which should be used for every message.
Using estimateReceiveExecution
Always Estimate Gas
Critical: Always use
estimateReceiveExecutionto estimate gas limits. Never hardcode gas values as they vary based on message data, token amounts, and receiver contract complexity.
Gas estimation may fail in rare cases (network issues, contract not deployed, etc.). If estimation fails:
Retry the estimation - Most failures are transient network issues
Check receiver contract - Ensure the receiver contract is deployed and accessible
Verify parameters - Ensure sender, receiver, and data are correctly formatted
Use minimum safety value - Only as a last resort, use a minimum value that ensures the transaction won't fail
Important Notes:
SDK gas estimation is strongly preferred - it calculates the exact gas needed for your specific message
Fallback values are emergency-only and may be too high or too low
If estimation consistently fails, there may be an issue with your setup
The fallback 700,000 gas is a conservative safety value, not a recommended value
Always investigate why estimation failed before using fallback values
6. Fee Estimation
Fee estimation calculates the CCIP fee required to send the message across chains.
7. Executing the Transaction
Step 1: Generate Unsigned Transaction
Step 2: Convert to Solana Transaction
Step 3: Sign and Send
Complete Code Example
Here's a complete example integrating all the steps:
Message Monitoring via API
After sending CCIP messages, you'll want to monitor their status and display message history to users. The CCIP API provides REST endpoints for querying message transactions by sender address, receiver address, or both.
Note: This is a pre-release version of the CCIP API (v2). The public release will be published soon. The Base URL of the production API will be: https://api.ccip.cldev.cloud/v2/
API Base URL (Staging)
https://api.ccip.cldev.cloud/v2/
Querying Messages
The API supports querying messages with the following filters:
By Receiver Address: Find all messages sent to the Maple receiver contract
By Sender Address: Find all messages sent by a specific user
By Both: Find messages matching both sender and receiver
Basic Query Function
Understanding Message Statuses
The API returns messages with the following status values:
SENT: Transaction submitted and waiting for source chain confirmationSOURCE_FINALIZED: Transaction confirmed on source chain and ready for CCIP processingCOMMITTED: Message committed to destination chain's commit store (CCIP v1.6 and below)BLESSED: Message approved by CCIP network (CCIP v1.6 and below)VERIFYING: Message is being verified by the CCIP network (CCIP v1.7+)VERIFIED: Message has been verified by the CCIP network (CCIP v1.7+)SUCCESS: Message successfully executed on destination chainFAILED: Message execution failed but can be manually retried
Status Display Helpers
Best Practices
Cache Results: Cache message queries to reduce API calls
Debounce Search: Debounce user input when searching by address
Handle Pagination: Always check
hasNextPagebefore loading moreError Recovery: Implement retry logic for transient failures
Status Polling: Only poll for messages that aren't in final states (SUCCESS/FAILED)
Rate Limiting: Be mindful of API rate limits in production
Message Information via API
The CCIP API provides endpoints to query detailed message information by message ID, sender address, or receiver address. This is useful for building monitoring dashboards, transaction history, and status tracking in your application.
API Base URL
Note: This is a pre-release version of the CCIP API (v2). The public release will be published soon.
Get Message by Message ID
Query a specific message using its message ID:
Query Messages by Receiver Address
Get all messages sent to the Maple receiver contract:
Query Messages by Sender Address
Get all messages sent by a specific Solana address:
Polling for Message Status Updates
Poll the API to check when a message status changes:
Complete Example: Message Monitoring Hook
A React hook for monitoring messages:
Best Practices (Same as Monitoring)
Rate Limiting: Be mindful of API rate limits. Implement exponential backoff for retries
Caching: Cache message data to reduce API calls, especially for completed messages
Polling Strategy: Only poll messages that aren't in final states (SUCCESS/FAILED)
Error Handling: Implement retry logic for transient failures
Pagination: Use cursors for pagination when querying multiple messages
Address Format: Ensure addresses are in the correct format (lowercase for EVM, base58 for Solana)
Important Notes
Minimum Transfer Amounts
⚠ Deposits and redemptions must exceed the configured fee for that token. Transactions with amounts below the fee will require manual recovery (handled by Maple).
Before sending a crosschain deposit or redemption:
Query the receiver contract for the current fee configuration
Validate the user's amount exceeds the fee
Display a clear error if the amount is too low
Fee amounts are configured per-token on the receiver contract. For fee queries and recovery procedures, see Failed Deposit/Redemption Retry and Recovery. Maple handles these edge cases with a 24h SLA, but you can as well for faster resolution.
Address Format Differences
Gas Estimation: Use standard EVM address format (20 bytes, 42 characters with
0x)Example:
0x02b6a75c5d1f430f0614dc5ac8ad5f9d35fba2c4
Message Construction: Use bytes32-padded address format (32 bytes, 66 characters with
0x)Example:
0x00000000000000000000000002b6a75c5d1f430f0614dc5ac8ad5f9d35fba2c4
Token Transfer Behavior
USDC Transfer: When USDC is sent to the receiver, it processes a deposit operation
SyrupUSDC Transfer: When SyrupUSDC is sent to the receiver, it processes a redemption operation
Ensure you're sending the correct token type based on the operation you want to perform.
Mainnet Deployment
All addresses in this guide are for testnet only. Before deploying to mainnet:
Update receiver contract address
Update pool contract address
Update token addresses (USDC, SyrupUSDC) for mainnet
Update destination chain selector if using a different chain
Verify all addresses on mainnet explorer
All addresses are available in Asset Integration.
Gas Estimation Best Practices
Always use estimateReceiveExecution to estimate gas limits. Never hardcode gas values.
Key Points:
Always estimate: Use
estimateReceiveExecutionfor every messageSender required: Include the sender address for accurate Solana-to-EVM estimation
API signature: Use
estimateReceiveExecution({ source, dest, routerOrRamp, message })Validate estimates: Check that estimates are reasonable (not zero, not extremely high)
Handle failures: If estimation fails, retry before using fallback values
Fallback value: 700,000 gas is a conservative fallback for emergency cases, not a recommended value
Why estimation is important:
Gas requirements vary based on message data size
SyrupUSDC Contract state can cause variable gas usage
Other conditions can influence gas requirements
If estimation fails:
Check network connectivity
Verify receiver contract is deployed and accessible
Ensure all parameters (sender, receiver, data) are correct
Retry the estimation (most failures are transient)
Only use fallback values as a last resort
Out-of-Order Execution
Always set allowOutOfOrderExecution: true
Error Handling
Implement comprehensive error handling for:
User transaction rejection
Insufficient funds (SOL for fees, tokens for transfer)
Network errors
Gas estimation failures
Transaction confirmation failures
Message Tracking
After sending, track your message using the CCIP Explorer:
URL:
https://ccip.chain.link/msg/{messageId}The message ID is extracted from the transaction logs after confirmation
Resources & Contact
Partnerships & queries: [email protected]
Last updated
Was this helpful?