vETH
On this page, you can find the contracts and their interactions involved when bridging to and from Ethereum (L1 - $ETH) and Cronos zkEVM (L2 - $vETH ), it includes:
[L1 -> L2] Minting $vETH with $ETH
[L2 -> L1] Withdrawing $ETH from $vETH
[L1 -> L2] Minting $vETH with $ETH
From Ethereum mainnet (L1) to Cronos zkEVM mainnet (L2)
To bridge $ETH from Ethereum mainnet -> Cronos zkEVM mainnet
, and obtain $vETH, we would need to interact with:
ybETHBridge
$ybETH token contract
Cronos zkEVM:
0xf226a595b83056ff3D26b827e3d5b0896E4392a9
$vETH token contract
Cronos zkEVM:
0x271602A97027ee1dd03b1E6e5dB153eB659A80b1
Step 1) Calculating the amount of $ybETH to Bridge
On Ethereum, use ybETH contract to call the convertToShare
function:
ybETH.convertToShare(ethAmount)
ethAmount
The amount of $ETH (with 18 decimals) to be used to mint $ybETH.
Keep this amount for later steps.
Step 2) Minting And Bridging $ybETH
On Ethereum, call the mintAndBridge
function on the ybETHBridge contract:
function mintAndBridge(
address _l2Receiver,
uint256 _amount,
uint256 _l2GasLimit,
uint256 _l2GasPerPubdataByteLimit,
address _refundRecipient
)
_l2Receiver
The address on Cronos zkEVM that will receive $ybETH
_amount
The amount of $ETH to mint and bridge $ybETH, as calculate in Step 1
_l2Gaslimit
Maximum amount of L2 gas that transaction can consume during execution on L2. Reference value: 500,000
_l2GasPerPubdataByteLimit
The maximum amount of L2 gas that the operator may charge the user for a single byte of pubdata. Reference value: 800
_refundRecipient
Address to collect refund, if bridging is unsuccessful.
This will mint $ybETH on Ethereum and bridge it to the _l2Receiver
address.
Step 3) Approving $ybETH to be spend by $vETH contract
On Cronos zkEVM, call approve
on the $ybETH contract to approve $vETH to spend $ybETH with appropriate amount.
Step 4) Minting of $vETH
On Cronos zkEVM, call mint
on $vETH contract , to mint $vETH
function mint(
address _receiver,
uint256 _ybEthAmount
)
_receiver
Address to receive the minted $vETH tokens
_ybEthAmount
Amount of $ybETH to be used to mint $vETH
This will mint $vETH into the _receiver
address.
[L2 -> L1] Withdrawing $ETH from $vETH
From Cronos zkEVM mainnet (L2) -> Ethereum mainnet (L1)
To redeem $vETH from Cronos zkEVM mainnet
, and withdraw $ETH on Ethereum mainnet
we would need to interact with the following contracts:
vETH
Cronos zkEVM:
0x271602A97027ee1dd03b1E6e5dB153eB659A80b1
l2Bridge
Cronos zkEVM: 0x309429DE3621992Cb0ab8982A448c9Cc5c38405b
zk Chain Shared Bridge
ybETH
Cronos zkEVM:
0xf226a595b83056ff3D26b827e3d5b0896E4392a9
vnoNFT
Step 1) Approving $vETH to be spend by vETH contract
On Cronos zkEVM, call approve
on the $vETH contract to approve $vETH spend with appropriate amount.
Step 2) Redeeming $vETH for $ybETH
On Cronos zkEVM, call redeem
on the vETH contract, to burn $vETH and redeem $ybETH
function redeem(
address _receiver,
uint256 _vethAmount
)
_receiver
Address to receive $ybETH on Cronos zkEVM
_vethAmount
Amount of vETH that will be burned to redeem ybETH
Once done, corresponding $ybETH will be transfer to the _reciever
address
Step 3) Approving $ybETH to be spend by the L2Bridge
On Cronos zkEVM, call approve
on the ybETH contract, to approve L2Bridge
to spend $ybETH.
Step 4) Withdrawing $ybETH and store withdrawal hash
On Cronos zkEVM, call withdraw on the L2Bridge contract
function withdraw(
address _l1Receiver,
address _l2Token,
uint256 _amount)
_l1Receiver
Address on Ethereum to receive the token
_l2Token
The token to be withdrawn, the Cronos zkEVM contract address $ybETH in this case.
_amount
amount of tokens to be withdrawn, note $ybETH has 18
decimals
Keep the transaction hash for later use in Step 5. This withdraws $ybETH from Cronos zkEVM to Ethereum. It takes at least 24 hours before the withdrawal can be finalized on Ethereum. Store the transaction hash from the withdrawal transaction; you will need it to finalize the withdrawal.
Step 5) Gathering information for $ybETH withdrawal on L1
Extra information for the L2 -> L1 transaction is required for the next step in claiming the $ybETH on L1. This information can be gathered by finalizeWithdrawalParams, using zksync-ethers
package
finalizeWithdrawalParams(withdrawalHash)
This takes the L2 withdrawal hash as parameters and returns the parameters required for finalizing a withdrawal in the next step.
Example outputs:
{
l1BatchNumber: 18,
l2MessageIndex: 59,
l2TxNumberInBlock: 2919,
message: '0x6c0960f935f448644c86dbda241ecb57f18a15c80f35a066000000000000000000000000000000000000000000000a2a15d09519be000000',
sender: '0x000000000000000000000000000000000000800a',
proof: [
'0x23ff0fb003a6a6e111f87cff02afc8680944c711abbe792f07ab4206e9efb9a3',
'0x09fece9c46307f2a0976a3a9b57873e453cf0f4773c2377dcd19f054166aef22',
'0x33c106ae5601983b53c751129d1921c17e40b69aa3fdbfaf07b7a0e0750d35e4',
'0x952ffa5de22d99815d9513dd7454949edb2a1cbcf86008f6fa8b169ffe9b4aee',
'0x8f10560a0b5412ca2e0578fb9266f55411f357d52c8fc3b2cad43b9877a559a6',
'0x8e70b93d3c90798df26473a3ad32a86170e8d52023a4044cf1d4c2d645471b14',
'0xdfaacb39891bbbf4509af408239b97a6f5ef715a5c299ba1f3625c20aec4ef8f',
'0xb04e5ee349086985f74b73971ce9dfe76bbed95c84906c5dffd96504e1e5396c',
'0xac506ecb5465659b3a927143f6d724f91d8d9c4bdb2463aee111d9aa869874db',
'0x124b05ec272cecd7538fdafe53b6628d31188ffb6f345139aac3c3c1fd2e470f',
'0xc3be9cbd19304d84cca3d045e06b8db3acd68c304fc9cd4cbffe6d18036cb13f',
'0xfef7bd9f889811e59e4076a0174087135f080177302763019adaf531257e3a87',
'0xa707d1c62d8be699d34cb74804fdd7b4c568b6c1a821066f126c680d4b83e00b',
'0xf6e093070e0389d2e529d60fadb855fdded54976ec50ac709e3a36ceaa64c291'
]
}
Step 6) Claiming the $ybETH on L1
Once the transaction in Step 4 has been finalized on L1, we can claim the withdrawn $ybETH from the Shared Bridge contract by calling its finalizeWithdrawal
function. The inputs can be found in Step 5,
function finalizeWithdrawal(
uint256 _chainId,
uint256 _l2BatchNumber,
uint256 _l2MessageIndex,
uint16 _l2TxNumberInBatch,
bytes calldata _message,
bytes32 calldata _merkleProof
)
_chainId
Chain id for Cronos zkEVM, which is 388
_l2BatchNumber
The L2 batch number where the withdrawal was processed, obtained in Step 5.
_l2MessageIndex
The position in the L2 logs Merkle tree of the l2Log that was sent with the message, obtained in Step 5.
_l2TxNumberInBatch
The L2 transaction number in the batch, in which the log was sent, obtained in Step 5.
_message
The L2 withdraw data, stored in an L2 -> L1 message, obtained in Step 5.
_merkleProof
The Merkle Proof, obtained in Step 5.
Once finalizeWithdrawal
is completed, the withdrawn amount of $ybETH will go into the receiver's wallet on Ethereum.
We can use zksync-ethers
package isWithdrawalFinalized
call to confirm whether the withdrawal transaction is finalized on the L1 network.
isWithdrawalFinalized(withdrawalHash)
withdrawalHash
The transaction hash of the L2 transaction includes the withdrawal transaction from Step 4
Step 7) Approving $ybETH to be spend by ybETH contract
On Ethereum, call approve
on the $ybETH contract, to approve the contract to spend $ybETH.
Step 8) Requesting $ETH withdrawal
On Ethereum, call requestUnbond
to request a unbonding of the staked $ETH.
function requestUnbond(
uint256 _shareAmount,
address _receiver
)
_shareAmount
The amount of $ybETH that is to be burned to unbond $ETH
_receiver
The wallet address on ethereum to receive the receipt NFT. This NFT is needed to withdraw the $ETH once the unbond period has ended
This will burn $ybETH and mint a receipt NFT - Veno Unstaked ETH (vnoNFT) to the _receiver
address. The unbonding procress takes 1~10 days, hold on to the NFT to claim the $ETH once it's ready. Store the tokenId of the received NFT; it is needed to withdraw the $ETH in the next steps.
Step 9) Approving NFT to be spend by ybETH contract
On Ethereum, call setApprovalForAll
on the vnoNFT contract, to approve $ybETH to transfer your vnoNFT obtained in Step 8).
setApprovalForAll(address operator, bool _approved)
operator
$ybETH contract address on Ethereum
_approved
Set to "True" to grant approval.
Step 10) Withdrawing $ETH
On Ethereum, call unbond
function on the ybETH contract to burn the receipt NFT and receive the underlying unstaked $ETH.
function unbond(
uint256 _tokenId,
address _receiver
)
_tokenId
The tokenId of the receipt NFT, recieved in Step 7
_receiver
The address on Ethereum to receive $ETH
This transaction burns the receipt NFT and sends the unstaked $ETH to the specified receiver.
Last updated