Skip to content

Jovay Bridge Developer Reference

This document provides a technical reference for developers who need to interact directly with the Jovay ETH Bridge smart contracts.

INFO

For a simple and secure user experience, we strongly recommend using the official Jovay Bridge DApp Tutorial instead of interacting with the contracts directly.

Contract Addresses & ABIs

L1 ETH Bridge Contract (on Ethereum)

NetworkL1 Bridge Contract Address
Ethereum Mainnet0x922248db4a99bb542539ae7165fb9d7a546fb9f1
Sepolia Testnet0x940eFB877281884699176892B02A3db49f29CDE8
View L1 Bridge ABI
JSON
json
[
	{
		"anonymous": false,
		"inputs": [
			{
				"indexed": true,
				"internalType": "address",
				"name": "from",
				"type": "address"
			},
			{
				"indexed": true,
				"internalType": "address",
				"name": "to",
				"type": "address"
			},
			{
				"indexed": false,
				"internalType": "uint256",
				"name": "amount",
				"type": "uint256"
			},
			{
				"indexed": false,
				"internalType": "bytes",
				"name": "msg",
				"type": "bytes"
			}
		],
		"name": "DepositETH",
		"type": "event"
	},
	{
		"anonymous": false,
		"inputs": [
			{
				"indexed": true,
				"internalType": "address",
				"name": "from",
				"type": "address"
			},
			{
				"indexed": true,
				"internalType": "address",
				"name": "to",
				"type": "address"
			},
			{
				"indexed": false,
				"internalType": "uint256",
				"name": "amount",
				"type": "uint256"
			},
			{
				"indexed": false,
				"internalType": "bytes",
				"name": "msg",
				"type": "bytes"
			}
		],
		"name": "FinalizeWithdrawETH",
		"type": "event"
	},
	{
		"inputs": [
			{
				"internalType": "address",
				"name": "to_",
				"type": "address"
			},
			{
				"internalType": "uint256",
				"name": "amount_",
				"type": "uint256"
			},
			{
				"internalType": "uint256",
				"name": "gasLimit_",
				"type": "uint256"
			},
			{
				"internalType": "bytes",
				"name": "data_",
				"type": "bytes"
			}
		],
		"name": "deposit",
		"outputs": [],
		"stateMutability": "payable",
		"type": "function"
	},
	{
		"inputs": [
			{
				"internalType": "address",
				"name": "sender_",
				"type": "address"
			},
			{
				"internalType": "address",
				"name": "to_",
				"type": "address"
			},
			{
				"internalType": "uint256",
				"name": "value_",
				"type": "uint256"
			},
			{
				"internalType": "bytes",
				"name": "msg_",
				"type": "bytes"
			}
		],
		"name": "finalizeWithdraw",
		"outputs": [],
		"stateMutability": "payable",
		"type": "function"
	}
]

L2 ETH Bridge Contract (on Jovay)

NetworkL2 Bridge Contract Address
Jovay Mainnet0xb220d17a11bd2d11e3f57a305ff5b481c81b1028
Jovay Testnet0xD278bC7189d2ed65c005c345A0e8a387f15b7a3A
View L2 Bridge ABI
JSON
json
[
	{
		"anonymous": false,
		"inputs": [
			{
				"indexed": true,
				"internalType": "address",
				"name": "from",
				"type": "address"
			},
			{
				"indexed": true,
				"internalType": "address",
				"name": "to",
				"type": "address"
			},
			{
				"indexed": false,
				"internalType": "uint256",
				"name": "amount",
				"type": "uint256"
			},
			{
				"indexed": false,
				"internalType": "bytes",
				"name": "msg",
				"type": "bytes"
			}
		],
		"name": "FinalizeDepositETH",
		"type": "event"
	},
	{
		"anonymous": false,
		"inputs": [
			{
				"indexed": true,
				"internalType": "address",
				"name": "from",
				"type": "address"
			},
			{
				"indexed": true,
				"internalType": "address",
				"name": "to",
				"type": "address"
			},
			{
				"indexed": false,
				"internalType": "uint256",
				"name": "amount",
				"type": "uint256"
			},
			{
				"indexed": false,
				"internalType": "bytes",
				"name": "msg",
				"type": "bytes"
			}
		],
		"name": "WithdrawETH",
		"type": "event"
	},
	{
		"inputs": [
			{
				"internalType": "bytes",
				"name": "msg_",
				"type": "bytes"
			}
		],
		"name": "claimDeposit",
		"outputs": [],
		"stateMutability": "nonpayable",
		"type": "function"
	},
	{
		"inputs": [
			{
				"internalType": "bytes",
				"name": "msg_",
				"type": "bytes"
			},
			{
				"internalType": "address",
				"name": "new_refund_address_",
				"type": "address"
			}
		],
		"name": "claimDeposit",
		"outputs": [],
		"stateMutability": "nonpayable",
		"type": "function"
	},
	{
		"inputs": [
			{
				"internalType": "address",
				"name": "sender_",
				"type": "address"
			},
			{
				"internalType": "address",
				"name": "to_",
				"type": "address"
			},
			{
				"internalType": "uint256",
				"name": "amount_",
				"type": "uint256"
			},
			{
				"internalType": "bytes",
				"name": "data_",
				"type": "bytes"
			}
		],
		"name": "finalizeDeposit",
		"outputs": [],
		"stateMutability": "payable",
		"type": "function"
	},
	{
		"inputs": [
			{
				"internalType": "address",
				"name": "to_",
				"type": "address"
			},
			{
				"internalType": "uint256",
				"name": "amount_",
				"type": "uint256"
			},
			{
				"internalType": "uint256",
				"name": "gasLimit_",
				"type": "uint256"
			},
			{
				"internalType": "bytes",
				"name": "data_",
				"type": "bytes"
			}
		],
		"name": "withdraw",
		"outputs": [],
		"stateMutability": "payable",
		"type": "function"
	}
]

Core Workflows

Deposit: L1 to L2

Step 1: Initiate Deposit on L1

To deposit ETH from Layer 1 to Layer 2, call the deposit function on the L1 Bridge Contract.

deposit
solidity
function deposit(
    address to_,
    uint256 amount_,
    uint256 gasLimit_,
    bytes memory data_
) external payable;

Parameters:

NameTypeDescription
to_addressThe recipient address on Jovay (L2).
amount_uint256The amount of ETH (in wei) to deposit.
gasLimit_uint256The gas limit for the corresponding transaction on L2.
data_bytesOptional data to pass with the message. Can be 0x for a standard ETH deposit.
valuepayableThe msg.value of the L1 transaction must be >= amount_ + (gasLimit_ * l2GasPrice).

After the L1 transaction is finalized, the bridge relayer should automatically call finalizeDeposit on L2 to credit the funds to the recipient.

Step 2 (Optional): Manually Claim Deposit on L2

In the rare event that the automated deposit does not arrive in your L2 account after a reasonable time, you can manually trigger the finalization.

To do this, call the claimDeposit function on the L2 Bridge Contract.

claimDeposit
solidity
function claimDeposit(bytes memory msg_) external;

This function allows a user to manually claim their assets on L2 if the automatic deposit relay fails.

Parameters:

NameTypeDescription
msg_bytesThe original message data from the DepositETH event log of your L1 deposit transaction. You can find this in the transaction details on an L1 block explorer.

Withdrawal: L2 to L1

Withdrawing ETH from Layer 2 to Layer 1 is a two-step process that requires two separate transactions.

Step 1: Initiate Withdrawal on L2

First, call the withdraw function on the L2 Bridge Contract.

withdraw
solidity
function withdraw(
    address to_,
    uint256 amount_,
    uint256 gasLimit_,
    bytes memory data_
) external payable;

Parameters:

NameTypeDescription
to_addressThe recipient address on Ethereum (L1).
amount_uint256The amount of ETH (in wei) to withdraw.
gasLimit_uint256The gas limit for the finalization transaction on L1.
data_bytesOptional data. Can be 0x.
valuepayableThe msg.value of the L2 transaction must be >= amount_ + (gasLimit_ * l1GasPrice).

After this L2 transaction is confirmed, you must wait for the transaction batch to be finalized on L1 (up to 1 hour). Once finalized, a proof will be available on the Jovay Explorer page for your transaction.

Step 2: Finalize Withdrawal on L1

Next, call the relayMsgWithProof function on the L1 Bridge Contract to claim your funds on Ethereum.

relayMsgWithProof
solidity
struct L2MsgProof {
    uint256 batchIndex;
    bytes merkleProof;
}
function relayMsgWithProof(
    uint256 value_,
    uint256 nonce_,
    bytes memory msg_,
    L2MsgProof memory proof_
) external payable;

Parameters:

NameTypeDescription
value_uint256The exact amount of ETH you withdrew on L2.
nonce_uint256The nonce of the cross-chain message. Find this in the SentMsg event log on the L2 withdrawal transaction page in the explorer.
msg_bytesThe original message from the SentMsg event log. This is typically in Base64 on the explorer and must be converted to a Hex string (with a 0x prefix) before being passed to the function.
proof_L2MsgProofA struct containing the proof data, passed as a tuple [batchIndex, proof].
batchIndexuint256The index of the batch containing your L2 withdrawal transaction. Find this by clicking the block number on the transaction page in the explorer.
merkleProofbytesThe SPV proof for your L2 message. This is the main hex string labeled "Proof" on the transaction page in the explorer.