This repo contains a set of smart contracts meant for enabling XERC20 token bridging through the Arbitrum canonical bridge, using two different approaches:
An example use case for this approach would be ezETH. ezETH is an ERC20 on L1 with an XERC20 representation on both L1 and L2. In order for Renzo to enable bridging the ezETH token it would need to:
- Deploy both
L1LockboxGatewayandL1LockboxGateway - Set the previously deployed
L1LockboxGatewayas abridgeon the XERC20 ezETH - Make a proposal to Arbitrum DAO for registering the
ezETH on Arbitrum's router to be used with
the
L1LockboxGateway, which should include:- Registering the ezETH on the router
- Remove from UI block-list
- Add L2 ezETH to L2ApprovalUtils
There are a few prerequisites to keep in mind for registering a token in the router associating it to a specific gateway.
First of all, the L1 counterpart of the token must conform to the ICustomToken interface. This means that:
- It must have a isArbitrumEnabled method that returns 0xb1
- It must have a method that makes an external call to L1CustomGateway.registerCustomL2Token specifying the address of the L2 contract, and to L1GatewayRouter.setGateway specifying the address of the custom gateway. These calls should be made only once to configure the gateway.
These methods are needed to register the token via the gateway contract. If the L1 contract does not include these methods and it is not upgradeable, registration could alternatively be performed in one of these ways:
- As a chain-owner registration via an Arbitrum DAO proposal.
- By wrapping your L1 token and registering the wrapped version of your token.
This approach uses an Adapter contract which is used for being able to permissionlessly register a non Arbitrum compatible token on the Arbitrum Router to be used with a Custom Gateway
In order to be able to use this approach it would be required to:
UI
- BootNode's UI PR to be merged (TODO add PR link)
Some trusted entity
- Deploy both
L1XERC20GatewayandL1XERC20Gateway
XERC20 Token Issuer
- Deploy an
L1XERC20Adapterif the XERC20 token - Call the
registerTokenOnL2function on the deployedL1XERC20Adapter - Set the
L1XERC20Gatewayas abridgeon the XERC20 token. WARNING: Token issuer must ensure the previous step was properly executed before this one. - Make a PR to Arbitrum's UI repository adding the L2 XERC20 token to L2ApprovalUtils
Deployment script documentation can be found here.
Foundry typically uses git submodules to manage dependencies, but this template uses Node.js packages because submodules don't scale.
This is how to install dependencies:
- Install the dependency using your preferred package manager, e.g.
bun install dependency-name- Use this syntax to install from GitHub:
bun install github:username/repo-name
- Use this syntax to install from GitHub:
- Add a remapping for the dependency in remappings.txt, e.g.
dependency-name=node_modules/dependency-name
Note that OpenZeppelin Contracts is pre-installed, so you can follow that as an example.
This is a list of the most frequently needed commands.
Build the contracts:
$ forge buildDelete the build artifacts and cache directories:
$ forge cleanCompile the contracts:
$ forge buildGet a test coverage report:
$ forge coverageFormat the contracts:
$ forge fmtGet a gas report:
$ forge test --gas-reportLint the contracts:
$ bun run lintRun the tests:
$ forge testGenerate test coverage and output result to the terminal:
$ bun run test:coverageGenerate test coverage with lcov report (you'll have to open the ./coverage/index.html file in your browser, to do so
simply copy paste the path):
$ bun run test:coverage:reportThis project is licensed under MIT.

