Skip to content
Prividium

Enabling Bridging

Bridging moves assets between Ethereum L1 and a Prividium™ network. Enabling it requires configuration across three independent layers.

  1. Permissions-API rules: function permissions on the L2 system contracts (and per-token L2 ERC-20 contracts) that the User Panel calls during bridging.
  2. L1 Transaction Filterer: an optional L1 contract that controls which L1→L2 deposits are accepted.
  3. Frontend settings: user-panel environment variables that show or hide the bridge UI.

How bridging uses permissions

Prividium™ applies its deny-by-default permission model to system contracts. After system-contract sync, every bridge function starts as Forbidden. Create the rules below to turn bridging on for a new environment.

Deposits and withdrawals use permissions differently:

  • Deposits move funds in through an L1 transaction. The L2 crediting runs as an automatic priority-queue transaction that bypasses Prividium and needs no L2 write permission. Before it can start a deposit, though, the User Panel reads token metadata from L2NativeTokenVault on L2. If those reads are Forbidden, the User Panel cannot start the deposit. Deposits therefore require L2 read permissions.
  • Withdrawals are user-signed L2 transactions. The User Panel needs both the read permissions (same token metadata) and write permissions on the withdrawal functions.

The three bridge system contracts are registered automatically:

ContractAddress
L2BaseToken0x000000000000000000000000000000000000800A
L2AssetRouter0x0000000000000000000000000000000000010003
L2NativeTokenVault0x0000000000000000000000000000000000010004

Create the permission rules below from each contract's Function Permissions tab in the Admin Dashboard, or through the API.

Token-resolution read permissions

The User Panel reads token metadata from L2 before every deposit and withdrawal, for both ETH and ERC-20. Grant these reads as All Users (public) because they are read-only view calls. You can also gate them by role if your policy requires it.

L2NativeTokenVault at 0x0000000000000000000000000000000000010004 (read access):

FunctionSelectorWhy needed
L1_CHAIN_ID()0x2f90b184Resolve the chain's asset identifiers
BASE_TOKEN_ASSET_ID()0xcb944decDetect whether the asset is the base token
WETH_TOKEN()0x37d277d4Returns the configured wrapped base token address
originChainId(bytes32)0x5f3455b5Determine where the asset originates
l2TokenAddress(address)0xf5f15168Map the L1 token to its L2 address

Withdrawals also read one function on L2AssetRouter at 0x0000000000000000000000000000000000010003 (read access):

FunctionSelectorWhy needed
l1TokenAddress(address)0xf54266a2Map the L2 token back to its L1 address (withdrawal)

The User Panel reads the first four L2NativeTokenVault functions on every deposit and withdrawal, including plain ETH. Any user who lacks full sequencer access needs all four permitted to bridge in either direction.

Enabling deposits

A deposit requires:

  1. The token-resolution read permissions above (the four common functions for ETH; add l2TokenAddress for ERC-20).
  2. The L1 Transaction Filterer to allow the deposit (see Transaction Filterer).

The L2 execution of a deposit is a priority-queue transaction and needs no L2 write permission. The reads above are the only L2-side configuration a deposit needs.

Enabling withdrawals

A withdrawal requires the read permissions above plus the following write permissions. Grant as All Users (public) or Check Role.

ContractFunctionSelectorAsset
L2BaseTokenwithdraw(address)0x51cff8d9ETH / base
L2AssetRouterwithdraw(bytes32,bytes)0x4a2e35baERC-20
L2NativeTokenVaultensureTokenIsRegistered(address)0x19a2a285ERC-20
L2 ERC-20 tokenapprove(address,uint256)0x095ea7b3ERC-20

Withdrawals must also be enabled in the frontend with VITE_WITHDRAWAL_ENABLED=true (see Frontend configuration).

ERC-20 considerations

  • Per-token permissions are required. Each bridgeable ERC-20 has its own L2 address and needs its own rules: approve(address,uint256) (write) for withdrawals, and allowance(address,address) and balanceOf(address) as reads. Add a rule for every token you intend to bridge, because no wildcard covers them.
  • Token registration. ensureTokenIsRegistered(address) registers the token in L2NativeTokenVault and returns its asset id; it must be permitted (write) before an ERC-20 withdrawal can be routed.
  • Frontend token list. Additional ERC-20s shown in the user panel are configured with VITE_BRIDGE_TOKENS (JSON). The L2 token address for each entry must be resolved correctly; see the private user-panel environment variable docs for the schema.

Transaction Filterer

The Transaction Filterer is an optional L1 contract that gates which L1→L2 transactions (including deposits) are queued. It is the deposit-side admission control and is independent of the L2 permission rules above.

Key behaviors:

  • setDepositsAllowed(bool) toggles whether non-whitelisted addresses may deposit.
  • When deposits are allowed, a non-whitelisted EOA may deposit only to its own address.
  • Whitelisted addresses (grantWhitelist / revokeWhitelist) may perform arbitrary L1→L2 transactions.
  • L1 contract addresses are aliased during deposit, so L1 contracts cannot deposit unless explicitly whitelisted.

If deposits are rejected at L1 (no L2 priority transaction appears) even though permissions are correct, check the filterer's depositsAllowed flag and the sender's whitelist status. For deployment and the full method reference, see Transaction Filterer.

Frontend configuration

These user-panel environment variables control the bridge UI only. They do not create permission rules and do not affect the Transaction Filterer.

VariablePurposeDefault
VITE_BRIDGING_ENABLEDShow the bridge UI (deposits)false
VITE_WITHDRAWAL_ENABLEDShow withdrawal features in the UIfalse
VITE_BRIDGE_TOKENSAdditional ERC-20 tokens for bridging[]
VITE_L1_RPC_URLL1 RPC endpoint (required when bridging)

See the private user-panel environment variable docs for the full list.

Verification checklist

Confirm a permission rule exists for each (contract, function) below, that its access type matches, and that its rule is All Users (public) or a Check Role rule the user holds. None should remain Forbidden.

Deposit — ETH

  • L2NativeTokenVault.L1_CHAIN_ID() — read
  • L2NativeTokenVault.BASE_TOKEN_ASSET_ID() — read
  • L2NativeTokenVault.WETH_TOKEN() — read
  • L2NativeTokenVault.originChainId(bytes32) — read
  • Transaction Filterer allows the sender

Deposit — ERC-20 (all of the above, plus)

  • L2NativeTokenVault.l2TokenAddress(address) — read

Withdraw — ETH (the four common reads, plus)

  • L2BaseToken.withdraw(address) — write
  • VITE_WITHDRAWAL_ENABLED=true

Withdraw — ERC-20 (the four common reads, plus)

  • L2AssetRouter.l1TokenAddress(address) — read
  • L2NativeTokenVault.ensureTokenIsRegistered(address) — write
  • <token>.approve(address,uint256) — write
  • <token>.allowance(address,address) — read
  • L2AssetRouter.withdraw(bytes32,bytes) — write
  • VITE_WITHDRAWAL_ENABLED=true

Troubleshooting

SymptomLikely cause
Deposit fails immediately, no L1 transaction is sentA token-resolution read permission on 0x…010004 is Forbidden (e.g. L1_CHAIN_ID). Grant the four common reads.
Deposit rejected at L1 / no L2 priority transaction appearsTransaction Filterer depositsAllowed=false, or the sender is not whitelisted (or is an aliased L1 contract).
Withdrawal "not authorized"A write permission is missing (withdraw, ensureTokenIsRegistered, or the token's approve).