Deposit tokens to Arbitrum
This guide shows you how to deposit ERC-20 tokens from a parent chain (like Ethereum) to an Arbitrum child chain. This assumes your token is already configured for bridging. If you need to set up bridging for a new token, see Configure token bridging.
Prerequisites
- Your token must already be bridgeable (registered with a gateway)
- A wallet with the tokens you want to deposit on the parent chain
- ETH on the parent chain to pay for gas fees
- Familiarity with Arbitrum's token bridge architecture
Depositing tokens using the Arbitrum SDK
The simplest way to deposit tokens is using the Arbitrum SDK:
Step 1: Set up the SDK
import { getArbitrumNetwork, Erc20Bridger } from '@arbitrum/sdk';
import { providers, Wallet } from 'ethers';
// Set up providers and wallet
const parentProvider = new providers.JsonRpcProvider(process.env.PARENT_RPC);
const childProvider = new providers.JsonRpcProvider(process.env.CHILD_RPC);
const wallet = new Wallet(process.env.PRIVATE_KEY, parentProvider);
// Initialize the bridge
const childNetwork = await getArbitrumNetwork(childProvider);
const erc20Bridge = new Erc20Bridger(childNetwork);
Step 2: Approve the gateway
The gateway contract needs permission to transfer your tokens:
const approveTx = await erc20Bridge.approveToken({
parentSigner: wallet,
erc20ParentAddress: tokenAddress,
});
const approveReceipt = await approveTx.wait();
console.log(`Approved gateway: ${approveReceipt.transactionHash}`);
Step 3: Deposit tokens
const depositTx = await erc20Bridge.deposit({
amount: ethers.utils.parseUnits('100', 18), // Amount to deposit
erc20ParentAddress: tokenAddress,
parentSigner: wallet,
childProvider: childProvider,
});
const depositReceipt = await depositTx.wait();
console.log(`Deposit initiated: ${depositReceipt.transactionHash}`);
Step 4: Wait for child chain execution
// Wait for the deposit to be processed on the child chain
const childResult = await depositReceipt.waitForChildTransactionReceipt(childProvider);
if (childResult.complete) {
console.log('Deposit successful!');
console.log(`Child chain transaction: ${childResult.message.childTxReceipt.transactionHash}`);
} else {
console.log('Deposit failed or pending');
}
Depositing tokens manually
If you prefer to interact with the contracts directly:
Step 1: Get contract addresses
Find the router and gateway addresses for your network on the contract addresses page.
Step 2: Approve the gateway
First, find which gateway will handle your token:
// Call on L1GatewayRouter
address gateway = l1GatewayRouter.getGateway(tokenAddress);
Then approve it:
// Call on your ERC-20 token contract
token.approve(gateway, amountToDeposit);
Step 3: Initiate deposit
Call the router contract's outboundTransferCustomRefund method:
function outboundTransferCustomRefund(
address _token,
address _refundTo,
address _to,
uint256 _amount,
uint256 _maxGas,
uint256 _gasPriceBid,
bytes calldata _data
) external payable returns (bytes memory)
Parameters:
_token: Parent chain address of the token to deposit_refundTo: Address to receive excess gas refund on the child chain_to: Address to receive tokens on the child chain_amount: Amount of tokens to deposit_maxGas: Max gas for child chain execution_gasPriceBid: Gas price for child chain execution_data: Encoded data containingmaxSubmissionCostand extra data
Example:
const router = new ethers.Contract(routerAddress, routerABI, wallet);
// Encode the data parameter
const data = ethers.utils.defaultAbiCoder.encode(['uint256', 'bytes'], [maxSubmissionCost, '0x']);
const tx = await router.outboundTransferCustomRefund(
tokenAddress,
refundAddress,
destinationAddress,
amount,
maxGas,
gasPriceBid,
data,
{ value: maxSubmissionCost + maxGas * gasPriceBid },
);
await tx.wait();
How deposits work
When you deposit tokens:
- Parent chain: Your tokens are escrowed in the gateway contract (for standard tokens) or burned (for custom tokens)
- Message sent: A retryable ticket is created to mint/release tokens on the child chain
- Child chain: After a few minutes, tokens are minted/released to your address
For more details on the underlying protocol, see Token bridging overview.
Troubleshooting
Deposit not appearing on child chain
If your deposit doesn't appear after 10-15 minutes:
- Check the transaction status on the Retryables Dashboard
- If the retryable ticket failed, you may need to manually redeem it
- Check that you provided sufficient gas fees for child chain execution
"Insufficient allowance" error
Make sure you approved the correct gateway contract (not the router). Use getGateway() to find the right gateway address.
Next steps
- Withdraw tokens back to parent chain
- Understand token bridge architecture
- Configure bridging for a new token