Withdraw ERC20 (Myria) Tokens
- Learn how to withdraw ERC20 tokens from Myria L2 network to Ethereum L1 network.
- To inspect the function in the SDK with details payload and response format you can reference at SDK Docs.
Prerequisites
- ERC20 Token must be registered to Myria system
- Make sure that you have ERC-20 tokens (such as Myria tokens) in the L2 wallet
- You can deposit ERC20 (ex: MYR tokens) from L1 to L2 wallet, can reference at depositERC20 step.
- Or if your L2 wallet received the ERC-20 tokens from Airdrop / Campaign events.
Withdrawal process
1. Available balance of ERC-20 tokens in the L2 wallet
The balance (funds) of desire tokens must be great than 0 in Myria L2 wallet.
2. Initiate the withdrawal
An off-chain withdrawal transaction will be initiated to request the withdrawal of off-chain funds.
3. Get withdraw balance
Check and verify the on-chain balance to ensure funds are available for claiming. This step is mandatory to confirm the availability of the funds.
4. Complete withdraw
Request an on-chain withdrawal of funds to L1. The funds will be transferred from Myria's dedicated L1 instance to the user's or developer's L1 wallet.
Implementation
- Myria SDK (React)
You can find the full React implementation for ERC20 withdrawals in the Myria React Samples repository.
1. Set up a React project
Withdrawing ERC20 tokens requires client-side interaction with the MetaMask wallet. It's recommended to use React to implement such behavior.
You can create a React app via Create React App. Note, the below project relies on the Web3.js library and needs custom configuration.
2. Create a myria-client.ts
helper
It's recommended to have a separate .ts
file for quick access to the MyriaClient
.
For more details, use the Myria Core SDK overview.
3. Withdraw ERC20 tokens
- withdraw-erc20.ts
- Wallet.tsx
The withdrawErc20()
function has the following parameters:
params
object:
tokenType
- TokenType.ERC20 as an enum TokenTypeamount
- the Wei amount that you'd to withdrawtokenAddress
- The smart contract address of your ERC-20 tokensenderPublicKey
- The Stark Key that you registered in Myria L2senderEthAddress
- Your wallet address in L1receiverPublicKey
- Your wallet address in L1quantum
- Default constants 10^10 as pre-defined value in Myria
sendOptions
object:
from
- public key of your walletconfirmationType
- Recommendation type isConfirmed
as the request is awaiting until transaction is confirmed at on-chain and received transaction receipts
import { ConfirmationType, TokenType, WithdrawOffchainParamsV2, WithdrawalModule, MyriaClient, SendOptions } from "myria-core-sdk";
import Web3 from 'web3';
const QUANTUM = 10000000000; // 10^10 as pre-defined rules in Myria
function convertEthToWei(amount: string): string {
if (!amount || Number(amount) === 0) return '0';
return Web3.utils.toWei(amount.toString()).toString();
}
export async function withdrawERC20(client: MyriaClient, starkKey: string, account: string, contractAddress: string, amount: string) {
const withdrawalModule: WithdrawalModule = new WithdrawalModule(client);
const withdrawErc20Params : WithdrawOffchainParamsV2 = {
tokenType: TokenType.ERC20,
amount: String(convertEthToWei(amount.toString())),
tokenAddress: contractAddress, // Your ERC-20 smart contract of tokens
senderPublicKey: `0x${pKey}`,
senderEthAddress: account,
receiverPublicKey: account,
quantum: QUANTUM.toString(),
};
const sendOptions: SendOptions = {
from: account,
confirmationType: ConfirmationType.Confirmed,
}
const responseWithdraw: TransactionData = await withdrawModule.withdrawalOffchainV2(withdrawErc20Params, sendOptions);
console.log(JSON.stringify(responseWithdraw, null, 2));
}
To withdraw ERC20 tokens, you need to know the contract address of that token. You can find the address using one of the blockchain explorers, such as Etherscan. Here's an example of Myria token on Sepolia network.
import { MyriaClient } from "myria-core-sdk";
import { useState } from "react";
import { withdrawERC20 } from "./withdraw-erc20";
type Props = {
isConnected: boolean,
account: string,
starkKey: string
client: MyriaClient
}
const Wallet = ({ isConnected, account, starkKey, client }: Props) => {
const [contractAddress, setContractAddress] = useState<any>("0x83a795e1e91560aae4207fdae9199d384f11d9d2");
const [amount, setAmount] = useState<any>("5");
const onWithdrawERC20Token = async () => {
return await withdrawErc20(client, starkKey, account, contractAddress, amount);
};
const onContractAddressChange = (event: React.ChangeEvent<HTMLInputElement>) => {
setContractAddress(event.target.value);
};
const onAmountChange = (event: React.ChangeEvent<HTMLInputElement>) => {
setAmount(event.target.value);
};
return (
<div className="container">
<div className="row">
<div className="col-lg-4 list-form py-3 mt-3">
<h4 className="text-white">Withdraw tokens</h4>
<div className="form-row">
<div className="col">
<input type="text" value={contractAddress} onChange={onContractAddressChange} name="contractAddress" className="form-control" placeholder="Erc20 contract address" />
</div>
<div className="col">
<input type="text" value={amount} onChange={onAmountChange} name="amount" className="form-control" placeholder="Amount" />
</div>
<div className="col">
<button onClick={() => onWithdrawERC20Token()} className="btn-mry">Withdraw ERC20 tokens</button>
</div>
</div>
</div>
</div>
</div>
);
}
export default Wallet;
4. Get available withdraw balance
At this stage, the system has tracked your off-chain withdrawal transactions. The availability of your withdrawal balance depends on the internal batch processing by Myria with Starkware.
The estimated processing time for the batch job is 35-48 hours.
Important note: You're only able to Complete The Withdraw as next step (Withdraw On-chain) if the withdraw balance is available and greater > 0 in L1.
- get-withdraw-balance-erc20.ts
The getWithdrawBalance()
function has the following parameters:
params
object:
tokenType
- TokenType.ERC20 as an enum TokenTypeassetId
- The computed hex string with Starkware's algorithm by combination of ERC-20 tokens smart contract and token type + quantumtokenAddress
- The smart contract address of your ERC-20 tokenquantum
- Default constants 10^10 as pre-defined value in Myria
import { ConfirmationType, TokenType, WithdrawalModule, MyriaClient } from "myria-core-sdk";
import Web3 from 'web3';
// Reference at this link: https://github.com/starkware-libs/starkware-crypto-utils
const StarkwareLib = require('@starkware-industries/starkware-crypto-utils');
const { asset } = StarkwareLib;
const QUANTUM = 10000000000; // 10^10 as pre-defined rules in Myria
export async function getWithdrawBalance(client: MyriaClient, account: string, contractAddress: string) {
const withdrawalModule: WithdrawalModule = new WithdrawalModule(client);
// Computed asset type by combination of Smart contract address and tokens type, Quantum
const assetType = asset.getAssetType({
type: 'ERC20',
data: {
quantum: QUANTUM.toString(),
tokenAddress: contractAddress
}
});
const availableWithdrawBalance = await withdrawModule.getWithdrawalBalance(account, assetId);
console.log(JSON.stringify(availableWithdrawBalance, null, 2));
}
4. Complete Withdraw - Withdraw fund to your L1 wallet
- This is the final step of the withdrawal process, transferring your funds from Myria L1 to your L1 wallet (e.g., MetaMask).
- Please note that the on-chain withdrawal process will require a gas fee, which must be available in your L1 wallet (MetaMask).
Important note: Your withdrawal transaction would cost gas fee based on ethereum networks gas and it could be fluctuated in time.
- get-withdraw-balance-erc20.ts
The withdrawOnchainErc20()
function has the following parameters:
params
object:
tokenType
- TokenType.ERC20 as an enum TokenTypeassetId
- The computed hex string with Starkware's algorithm by combination of ERC-20 tokens smart contract and token type + quantumtokenAddress
- The smart contract address of your ERC-20 tokenquantum
- Default constants 10^10 as pre-defined value in Myria
import { ConfirmationType, TokenType, WithdrawalModule, MyriaClient, WithdrawOnchainParams } from "myria-core-sdk";
import Web3 from 'web3';
// Reference at this link: https://github.com/starkware-libs/starkware-crypto-utils
const StarkwareLib = require('@starkware-industries/starkware-crypto-utils');
const { asset } = StarkwareLib;
const QUANTUM = 10000000000; // 10^10 as pre-defined rules in Myria
export async function withdrawOnchainErc20(client: MyriaClient, account: string, contractAddress: string) {
const withdrawalModule: WithdrawalModule = new WithdrawalModule(client);
// Computed asset type by combination of Smart contract address and tokens type, Quantum
const assetType: string = asset.getAssetType({
type: TokenType.ERC20,
data: {
quantum: QUANTUM,
tokenAddress: contractAddress
}
});
const withdrawOnchainErc20Payload: WithdrawOnchainParams = {
starkKey: walletAddress,
assetType
};
const sendOptions = {
from: account,
nonce: new Date().getTime(), // It's optional but it's recommend to pass the unique nonce by get timestamp
confirmationType: ConfirmationType.Confirmed
};
const result = await withdrawModule.withdrawalOnchain(withdrawOnchainErc20Payload, sendOptions);
// If the on-chain withdrawal is successful, the next check of the on-chain balance will show zero.
const withdrawOnchainResult = await withdrawModule.getWithdrawalBalance(account, assetId);
console.log(JSON.stringify(withdrawOnchainResult, null, 2));
}