vUSD

On this page, you can find the contracts and their interactions involved when bridging to and from Ethereum (L1 - $DAI/$USDC/$USDT) and Cronos zkEVM (L2 - $vUSD ), it includes:

[L1 -> L2] Minting $vUSD with $DAI/$USDC/$USDT

[L2 -> L1] Withdrawing $DAI from $vUSD

The following instructions cover bridging and minting $vUSD with $DAI, $USDC, or $USDT deposits on L1.

Note that the contracts are based on $DAI. $USDC or $USDT deposits will be swapped to $DAI during the deposit process. Check Step 2) Minting And Bridging $ybUSD for details and parameters.


[L1 -> L2] Minting $vUSD with $DAI/$USDC/$USDT

From Ethereum mainnet (L1) to Cronos zkEVM mainnet (L2)

For bridging $DAI/$USDC/$USDT (Ethereum Mainnet) to $vUSD (Cronos zkEVM Mainnet), we would need to:

  1. Mint and bridge $ybUSD from Ethereum to Cronos zkEVM Mainnet with $DAI/$USDC/$USDT;

  2. Mint $vUSD with $ybUSD on Cronos zkEVM Mainnet.

To bridge $DAI/$USDC/$USDT from Ethereum mainnet -> Cronos zkEVM mainnet, and obtain $vUSD we would need to interact with:

Step 1) Calculating the amount of $ybUSD to Bridge

On Ethereum, use ybUSD token contract to call the convertToShares function:

ybUSD.convertToShares(daiAmount)
ParametersComments

daiAmount

The amount of $DAI (with 18 decimals) to be used to mint $ybUSD.

Keep this amount for later steps.

Step 2) Minting And Bridging $ybUSD

On Ethereum, call the mintAndBridge function on the ybUSDBridgecontract:

function mintAndBridge(
        address _l2Receiver,
        uint256 _amount,
        uint128 _stableCoinType,
        uint256 _minAmountAccepted,
        uint256 _l2GasLimit,
        uint256 _l2GasPerPubdataByteLimit,
        address _refundRecipient
        )
ParametersComments

_l2Receiver

The address on Cronos zkEVM that will receive $ybUSD

_amount

The amount of DAI/(USDC/USDT will be swapped to DAI) to deposit into the $ybUSD contract, in their corresponding decimals ( 18 for $DAI, 6 for $USDC and USDT )

_stableCoinType

Set 0 for $DAI, 1 for $USDC, 2 for $USDT

_minAmountAccepted

Minimum amount accepted when swapping USDC/USDT to DAI

_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 $ybUSD on Ethereum and bridge it to the _l2Receiver address on L2.

Step 3) Approving $ybUSD to be spend by $vUSD contract

On Cronos zkEVM, call approve on the ybUSD contract to approve $vUSD contract to spend $ybUSD with appropriate amount.

Step 4) Minting of $vUSD

On Cronos zkEVM, call mint on $vUSD contract , to mint $vUSD

function mint(
        address _receiver, 
        uint256 _ybUsdAmount
        )
ParametersComments

_receiver

Address to receive the minted $vUSD tokens

_ybUsdAmount

Amount of $ybUSD to be used to mint $vUSD

This will mint $vUSD into the _receiver address.


[L2 -> L1] Withdrawing $DAI from $vUSD

From Cronos zkEVM mainnet (L2) -> Ethereum mainnet (L1)

For withdrawing $vUSD (Cronos zkEVM Mainnet) and get $DAI (Ethereum Mainnet) , we would need to:

  1. [On Cronos zkEVM] Use $vUSD to redeem $ybUSD;

  2. [On Cronos zkEVM] Bridge $ybUSD to Ethereum;

  3. [On Ethereum] Redeem $ybUSD for $DAI

To redeem $vUSD from Cronos zkEVM mainnet -> Ethereum mainnet, and withdraw $DAI we would need to interact with the following contracts:

Step 1) Approving $vUSD to be spend by vUSD contract

On Cronos zkEVM, call approve on the $vUSD contract to approve $vUSD spend with appropriate amount.

Step 2) Redeeming $vUSD for $ybUSD

On Cronos zkEVM, call redeem on the vUSD contract, to burn $vUSD and redeem $ybUSD

function redeem(
        address _receiver,
        uint256 _vUsdAmount
        )
ParametersComments

_receiver

Address to receive $ybUSD on Cronos zkEVM

_vUsdAmount

Amount of vUSD that will be burned to redeem $ybUSD

Once done, corresponding $ybUSD will be transfer to the _reciever address

Step 3) Approving $ybUSD to be spend by the L2Bridge

On Cronos zkEVM, call approve on the ybUSD contract, to approve L2Bridge contract to spend $ybUSD.

Step 4) Withdrawing $ybUSD and store withdrawal hash

On Cronos zkEVM, call withdraw on the L2Bridge contract

function withdraw(
        address _l1Receiver, 
        address _l2Token, 
        uint256 _amount
        )
ParametersComments

_l1Receiver

Address on Ethereum to receive the token

_l2Token

The token to be withdrawn, the Cronos zkEVM contract address $ybUSD in this case.

_amount

amount of tokens to be withdrawn, note $ybUSD has 18 decimals

Keep the transaction hash for later use in Step 5. This withdraws $ybUSD from Cronos zkEVM to Ethereum. It takes 24 hours before the withdrawal can be finalized on Ethereum. Store the transaction hash from the withdrawal transaction; it will be needed to finalize the withdrawal.

Step 5) Gathering information for $ybUSD withdrawal on L1

Extra information for the L2 -> L1 transaction is required for the next step in claiming the $ybUSD. 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 $ybUSD on L1

Once the transaction in Step 4 has been finalized, we can claim the withdrawn $ybUSD from the L2Bridge 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
        )
ParametersComments

_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 $ybUSD will go into the receiver's wallet on Ethereum.

We can use zksync-ethers package isWithdrawalFinalized call to whether the withdrawal transaction is finalized on the L1 network.

isWithdrawalFinalized(withdrawalHash)
ParametersComments

withdrawalHash

The transaction hash of the L2 transaction includes the withdrawal transaction from Step 4

Step 7) Approving $ybUSD to be spend by ybUSD contract

On Ethereum, call approve on the $ybUSD contract, to approve the contract to spend $ybUSD

Step 8) Redeem $ybUSD for $DAI

On Ethereum, call redeem on the the $ybUSD contract

function redeem(
        uint256 _amount
        )
ParametersComments

_amount

The amount of $ybUSD tokens to redeem for $DAI

Once redeem is completed, the withdrawn amount of $DAI will go into the receiver's wallet on Ethereum.

Last updated