Withdrawal
Withdrawal
When it comes to withdrawals there are several notes that needs to be taken into account:
- Withdrawal flow consist of two steps:
- Executing withdrawal transaction on L2 which initiates submission to L1.
- Executing finalize withdrawal after the withdrawal transaction is submitted to L1.
- The duration for submitting a withdrawal transaction to L1 can last up to 24 hours.
- On the testnet, withdrawals are automatically finalized. There is no need to execute finalize withdrawal step, otherwise, an error with code
jj
would occur.
Withdraw ETH
This is an example of how to withdraw ETH from zkSync Era network (L2) to Ethereum network (L1):
package main
import (
"context"
"fmt"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/zksync-sdk/zksync2-go/accounts"
"github.com/zksync-sdk/zksync2-go/clients"
"github.com/zksync-sdk/zksync2-go/utils"
"log"
"math/big"
"os"
)
func main() {
var (
PrivateKey = os.Getenv("PRIVATE_KEY")
ZkSyncEraProvider = "https://testnet.era.zksync.dev"
EthereumProvider = "https://rpc.ankr.com/eth_goerli"
)
// Connect to zkSync network
client, err := clients.Dial(ZkSyncEraProvider)
if err != nil {
log.Panic(err)
}
defer client.Close()
// Connect to Ethereum network
ethClient, err := ethclient.Dial(EthereumProvider)
if err != nil {
log.Panic(err)
}
defer ethClient.Close()
// Create wallet
wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey), &client, ethClient)
if err != nil {
log.Fatal(err)
}
// Perform withdrawal
tx, err := wallet.Withdraw(nil, accounts.WithdrawalTransaction{
To: wallet.Address(),
Amount: big.NewInt(1_000_000_000),
Token: utils.EthAddress,
})
if err != nil {
panic(err)
}
fmt.Println("Withdraw transaction: ", tx.Hash())
// Wait until transaction is finalized
_, err = client.WaitFinalized(context.Background(), tx.Hash())
if err != nil {
log.Panic(err)
}
// Perform finalize withdrawal
finalizeWithdrawTx, err := wallet.FinalizeWithdraw(nil, tx.Hash(), 0)
if err != nil {
log.Panic(err)
}
fmt.Println("Finalize withdraw transaction: ", finalizeWithdrawTx.Hash())
}
Withdraw tokens
This is an example of how to withdraw tokens from zkSync Era network (L2) to Ethereum network (L1):
package main
import (
"fmt"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/zksync-sdk/zksync2-go/accounts"
"github.com/zksync-sdk/zksync2-go/clients"
"github.com/zksync-sdk/zksync2-go/utils"
"log"
"math/big"
"os"
)
func main() {
var (
PrivateKey = os.Getenv("PRIVATE_KEY")
ZkSyncEraProvider = "https://testnet.era.zksync.dev"
EthereumProvider = "https://rpc.ankr.com/eth_goerli"
)
// Connect to zkSync network
client, err := clients.Dial(ZkSyncEraProvider)
if err != nil {
log.Panic(err)
}
defer client.Close()
// Connect to Ethereum network
ethClient, err := ethclient.Dial(EthereumProvider)
if err != nil {
log.Panic(err)
}
defer ethClient.Close()
// Create wallet
wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey), &client, ethClient)
if err != nil {
log.Panic(err)
}
// Perform withdrawal
tx, err := wallet.Withdraw(nil, accounts.WithdrawalTransaction{
To: wallet.Address(),
Amount: big.NewInt(1_000_000_000),
Token: utils.EthAddress,
})
if err != nil {
log.Panic(err)
}
fmt.Println("Withdraw transaction: ", tx.Hash())
}
Finalize withdrawal
package main
import (
"context"
"fmt"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/zksync-sdk/zksync2-go/accounts"
"github.com/zksync-sdk/zksync2-go/clients"
"log"
"os"
)
func main() {
var (
PrivateKey = os.Getenv("PRIVATE_KEY")
ZkSyncEraProvider = "https://testnet.era.zksync.dev"
EthereumProvider = "https://rpc.ankr.com/eth_goerli"
WithdrawTx = common.HexToHash("<Withdraw tx hash>")
)
// Connect to zkSync network
client, err := clients.Dial(ZkSyncEraProvider)
if err != nil {
log.Panic(err)
}
defer client.Close()
// Connect to Ethereum network
ethClient, err := ethclient.Dial(EthereumProvider)
if err != nil {
log.Panic(err)
}
defer ethClient.Close()
// Create wallet
wallet, err := accounts.NewWallet(common.Hex2Bytes(PrivateKey), &client, ethClient)
if err != nil {
log.Panic(err)
}
// Check if the withdrawal is finalized
if isFinalized, errFinalized := wallet.IsWithdrawFinalized(nil, WithdrawTx, 0); errFinalized != nil {
log.Panic(errFinalized)
} else if !isFinalized {
// Perform the finalize withdrawal
finalizeWithdrawTx, errWithdraw := wallet.FinalizeWithdraw(nil, WithdrawTx, 0)
if errWithdraw != nil {
log.Panic(errWithdraw)
}
fmt.Println("Finalize withdraw transaction: ", finalizeWithdrawTx.Hash())
// Wait for finalize withdraw transaction to be finalized on L1 network
fmt.Println("Waiting for finalize withdraw transaction to be finalized on L1 network")
_, err = bind.WaitMined(context.Background(), ethClient, finalizeWithdrawTx)
if err != nil {
log.Panic(err)
}
}
}