Skip to content
Merged
Show file tree
Hide file tree
Changes from 20 commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
f49f53b
forge install: devtools
gfournierPro May 9, 2025
06c09ee
forge install: layerzero-v2
gfournierPro May 9, 2025
8bb6a85
forge install: rlc-faucet-contract
gfournierPro May 9, 2025
91c7a70
forge install: openzeppelin-contracts
gfournierPro May 9, 2025
fcb4ee0
feat: Implement RLCAdapter and RLCOFT contracts with deployment scripts
gfournierPro May 13, 2025
0fd43c7
refactor: Clean up whitespace and formatting in contract scripts
gfournierPro May 13, 2025
5ff3398
feat: Implement cross-chain transfer scripts for RLC tokens between A…
gfournierPro May 14, 2025
c400115
feat: Update deployment scripts to use environment variables for addr…
gfournierPro May 14, 2025
dfd6e42
Refactor Ethereum to Arbitrum transfer scripts and update transaction…
gfournierPro May 14, 2025
1d2795a
feat: Add .env.template for Ethereum and Arbitrum Sepolia configurations
gfournierPro May 15, 2025
6eefe3a
refactor: Remove Foundry section and enhance README with detailed bri…
gfournierPro May 15, 2025
7a713a6
feat: Add detailed transaction data for cross-chain transfers from Ar…
gfournierPro May 15, 2025
dcc2ef6
feat: Add transaction details and receipts for Ethereum to Arbitrum t…
gfournierPro May 15, 2025
52e5b76
refactor: Clean up Makefile by removing unused targets and help section
gfournierPro May 15, 2025
3b71cff
refactor: Simplify README by removing detailed .env configuration sec…
gfournierPro May 15, 2025
22d9aea
feat: Implement EnvUtils library for updating environment variables i…
gfournierPro May 15, 2025
6ef8db5
Refactor code structure for improved readability and maintainability
gfournierPro May 15, 2025
e4d5e19
fix: Update RPC URLs for Ethereum and Arbitrum Sepolia configurations
gfournierPro May 15, 2025
db42713
feat(rlcoft.sol): Override decimals function to return 9 for the token
gfournierPro May 15, 2025
09b05f3
fix: Correct API key variable name for Blockscan to ETHERSCAN_API_KEY
gfournierPro May 15, 2025
f1b607f
feat(Makefile): Add verification targets for RLCAdapter and RLCOFT on…
gfournierPro May 15, 2025
5f6a184
fix(.gitignore): Update ignore rules for Foundry broadcast files
gfournierPro May 15, 2025
70d212d
add run latest
gfournierPro May 15, 2025
822f69e
clean up unnecessary transaction data.
gfournierPro May 15, 2025
f5c1400
feat: Add initial changelog for RLC OFT bridge system implementation
gfournierPro May 15, 2025
bf41432
refactor: Update environment variable names for LayerZero configuration
gfournierPro May 16, 2025
87e205c
refactor: Rename environment variables for RLC adapter and OFT addresses
gfournierPro May 16, 2025
f1a0a3d
fix: Update Arbitrum Sepolia RPC URL to the correct endpoint
gfournierPro May 16, 2025
1d74f14
refactor: Rename token configuration variables for RLC OFT
gfournierPro May 16, 2025
0a71ee3
fix: add EOF blank line
gfournierPro May 16, 2025
a4351e8
refactor(MakeFile): Move test and clean targets to the top
gfournierPro May 16, 2025
c15e285
fix(README): Update repository clone URL in
gfournierPro May 16, 2025
6212a9c
docs(README): Add instructions for creating and editing .env file
gfournierPro May 16, 2025
78e7521
refactor(Makefile): Rename configuration and token transfer targets f…
gfournierPro May 16, 2025
e932c70
fix: Correct constructor order in RLCAdapter and RLCOFT contracts
gfournierPro May 16, 2025
e1cf4ca
fix: Update SPDX license identifiers from UNLICENSED to Apache-2.0 in…
gfournierPro May 16, 2025
20b2a14
docs(RLCOFT): Improve comment clarity for approveAndCall function
gfournierPro May 16, 2025
9c6eccc
feat: Introduce ITokenSpender interface and update RLCOFT to use it
gfournierPro May 16, 2025
84f348b
refactor: Simplify contract names in deployment and configuration scr…
gfournierPro May 16, 2025
67af7c0
fix: Rename DELEGATE_ADDRESS and RECEIVER_ADDRESS to SENDER_ADDRESS i…
gfournierPro May 16, 2025
d50588c
refactor: Change variable declarations for RLCAdapter and RLCOFT to l…
gfournierPro May 16, 2025
e046bcb
fix(Makefile): Remove unnecessary source command in send-tokens-to-se…
gfournierPro May 16, 2025
f9c877f
docs: Update README for clarity and add contract overview section
gfournierPro May 16, 2025
47297f4
docs: Update usage section in README for clarity on bridging RLC tokens
gfournierPro May 16, 2025
72cf079
chore: Comment out test step in CI workflow for future implementation
gfournierPro May 16, 2025
b3c2972
fix(Makefile): Remove unused .PHONY target for send-tokens-to-arbitru…
gfournierPro May 16, 2025
07144df
style: Clean up whitespace in multiple Solidity scripts for consistency
gfournierPro May 16, 2025
feadf9b
fix: Rename environment variable for Arbitrum Sepolia RLC OFT address…
gfournierPro May 16, 2025
a1238c1
fix: Rename scripts and Makefile targets for clarity and consistency
gfournierPro May 16, 2025
cabe6da
style: Add TODO comment to extract and document gas estimation function
gfournierPro May 16, 2025
fac839e
fix: Change behavior on missing .env file to revert instead of returning
gfournierPro May 16, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 10 additions & 11 deletions .env.template
Original file line number Diff line number Diff line change
@@ -1,23 +1,22 @@
# Ethereum Sepolia Configuration
SEPOLIA_RPC_URL="https://gateway.tenderly.co/public/sepolia"
SEPOLIA_ENDPOINT_ADDRESS=0x<layerzero-endpoint-address-on-sepolia>
SEPOLIA_CHAIN_ID=SEPOLIA_CHAIN_ID=40161 # LayerZero chain ID for Ethereum Sepolia
SEPOLIA_ADAPTER_ADDRESS=0x<deployed-rlc-adapter-address-on-sepolia>
LAYER_ZERO_SEPOLIA_ENDPOINT_ADDRESS=0x6EDCE65403992e310A62460808c4b910D972f10f
LAYER_ZERO_SEPOLIA_CHAIN_ID=40161 # LayerZero chain ID for Ethereum Sepolia
RLC_SEPOLIA_ADAPTER_ADDRESS=0x<deployed-rlc-adapter-address-on-sepolia>
RLC_SEPOLIA_ADDRESS=0x<rlc-token-address-on-sepolia>

# Arbitrum Sepolia Configuration
ARBITRUM_SEPOLIA_RPC_URL="https://arbitrum-sepolia-rpc.publicnode.com"
ARBITRUM_SEPOLIA_ENDPOINT_ADDRESS=0x<layerzero-endpoint-address-on-arbitrum-sepolia>
ARBITRUM_SEPOLIA_CHAIN_ID=40231 # LayerZero chain ID for Arbitrum Sepolia
ARBITRUM_SEPOLIA_OFT_ADDRESS=0x<deployed-rlcoft-address-on-arbitrum-sepolia>
ARBITRUM_SEPOLIA_RPC_URL="https://arbitrum-sepolia.gateway.tenderly.co"
LAYER_ZERO_ARBITRUM_SEPOLIA_ENDPOINT_ADDRESS=0x6EDCE65403992e310A62460808c4b910D972f10f
LAYER_ZERO_ARBITRUM_SEPOLIA_CHAIN_ID=40231 # LayerZero chain ID for Arbitrum Sepolia
ARBITRUM_SEPOLIA_RLC_OFT_ADDRESS=0x<deployed-rlcoft-address-on-arbitrum-sepolia>

# Token Configuration for OFT
TOKEN_NAME="RLC OFT"
TOKEN_SYMBOL="RLC"
RLC_OFT_TOKEN_NAME="RLC OFT"
RLC_TOKEN_SYMBOL="RLC"

# Transaction Settings
DELEGATE_ADDRESS=0x<delegate-wallet-address>
RECEIVER_ADDRESS=0x<receiver-wallet-address>
SENDER_ADDRESS=0x<delegate-wallet-address>

# API Keys
ETHERSCAN_API_KEY=<your-etherscan-api-key>
Expand Down
10 changes: 5 additions & 5 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ jobs:
run: |
forge build --sizes
id: build

- name: Run Forge tests
run: |
forge test -vvv
id: test
#TDO: Uncomment when tests are available
# - name: Run Forge tests
# run: |
# forge test -vvv
# id: test
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,4 @@ docs/

# Dotenv file
.env
.last_deploy.json
.last_deploy.json
44 changes: 23 additions & 21 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,38 +1,48 @@
# Makefile for RLC OFT Project
-include .env

# Test and utility targets
test:
@echo "Running tests..."
forge test -vvv

clean:
@echo "Cleaning artifacts..."
forge clean

# Deployment targets
deploy-adapter:
@echo "Deploying RLCAdapter on SEPOLIA..."
forge script script/RLCAdapter.s.sol:DeployRLCAdapter \
forge script script/RLCAdapter.s.sol:Deploy \
--rpc-url $(SEPOLIA_RPC_URL) \
--account $(ACCOUNT) \
--broadcast \
-vvv

deploy-oft:
@echo "Deploying RLCOFT on Arbitrum SEPOLIA..."
forge script script/RLCOFT.s.sol:DeployRLCOFT \
forge script script/RLCOFT.s.sol:Deploy \
--rpc-url $(ARBITRUM_SEPOLIA_RPC_URL) \
--account $(ACCOUNT) \
--broadcast \
-vvv \

conf-adapter:
configure-adapter:
@echo "Configuring RLCAdapter on SEPOLIA..."
forge script script/ConfigureRLCAdapter.s.sol:ConfigureRLCAdapter \
forge script script/ConfigureRLCAdapter.s.sol:Configure \
--rpc-url $(SEPOLIA_RPC_URL) \
--account $(ACCOUNT) \
--broadcast \
-vvv
conf-oft:
configure-oft:
@echo "Configuring RLCOFT on Arbitrum SEPOLIA..."
forge script script/ConfigureRLCOFT.s.sol:ConfigureRLCOFT \
forge script script/ConfigureRLCOFT.s.sol:Configure \
--rpc-url $(ARBITRUM_SEPOLIA_RPC_URL) \
--account $(ACCOUNT) \
--broadcast \
-vvv

send-tokens:
send-tokens-to-arbitrum-sepolia:
@echo "Sending tokens cross-chain... from SEPOLIA to Arbitrum SEPOLIA"
forge script script/SendEthereumToArbitrum.s.sol:SendEthereumToArbitrum \
--rpc-url $(SEPOLIA_RPC_URL) \
Expand All @@ -41,9 +51,9 @@ send-tokens:
-vvv

.PHONY: send-tokens-arbitrum-sepolia
send-tokens-arbitrum-sepolia:
send-tokens-to-sepolia:
@echo "Sending tokens cross-chain... from Arbitrum SEPOLIA to SEPOLIA"
@source .env && forge script script/SendArbitrumToEthereum.s.sol:SendArbitrumToEthereum \
forge script script/SendArbitrumToEthereum.s.sol:SendArbitrumToEthereum \
--rpc-url $(ARBITRUM_SEPOLIA_RPC_URL) \
--account $(ACCOUNT) \
--broadcast \
Expand All @@ -55,29 +65,21 @@ verify-adapter:
forge verify-contract \
--chain-id 11155111 \
--watch \
--constructor-args $(shell cast abi-encode "constructor(address,address,address)" $(RLC_SEPOLIA_ADDRESS) $(SEPOLIA_ENDPOINT_ADDRESS) $(DELEGATE_ADDRESS)) \
--constructor-args $(shell cast abi-encode "constructor(address,address,address)" $(RLC_SEPOLIA_ADDRESS) $(LAYER_ZERO_SEPOLIA_ENDPOINT_ADDRESS) $(SENDER_ADDRESS)) \
--etherscan-api-key $(ETHERSCAN_API_KEY) \
$(SEPOLIA_ADAPTER_ADDRESS) \
$(RLC_SEPOLIA_ADAPTER_ADDRESS) \
src/RLCAdapter.sol:RLCAdapter

verify-oft:
@echo "Verifying RLCOFT on Arbitrum Sepolia Etherscan..."
forge verify-contract \
--chain-id 421614 \
--watch \
--constructor-args $(shell cast abi-encode "constructor(string,string,address,address)" $(TOKEN_NAME) $(TOKEN_SYMBOL) $(ARBITRUM_SEPOLIA_ENDPOINT_ADDRESS) $(DELEGATE_ADDRESS)) \
--constructor-args $(shell cast abi-encode "constructor(string,string,address,address)" $(RLC_OFT_TOKEN_NAME) $(RLC_TOKEN_SYMBOL) $(LAYER_ZERO_ARBITRUM_SEPOLIA_ENDPOINT_ADDRESS) $(SENDER_ADDRESS)) \
--etherscan-api-key $(ARBISCAN_API_KEY) \
$(ARBITRUM_SEPOLIA_OFT_ADDRESS) \
$(ARBITRUM_SEPOLIA_RLC_OFT_ADDRESS) \
src/RLCOFT.sol:RLCOFT

# Combined verification target
verify-all: verify-adapter verify-oft

# Test and utility targets
test:
@echo "Running tests..."
forge test -vvv

clean:
@echo "Cleaning artifacts..."
forge clean
94 changes: 23 additions & 71 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,23 +6,23 @@ This project implements a cross-chain token bridge for the RLC token between Eth

The system consists of two main components:

1. **RLCAdapter (on Ethereum **Sepolia**)**: Wraps the existing RLC ERC-20 token to make it compatible with LayerZero's cross-chain messaging.
1. **RLCAdapter (on Ethereum Sepolia)**: Wraps the existing RLC ERC-20 token to make it compatible with LayerZero's cross-chain messaging.
2. **RLCOFT (on Arbitrum Sepolia)**: A new token that's minted when RLC tokens are locked in the adapter on Ethereum, and burned when tokens are sent back.

[![Architecture Diagram](https://mermaid.ink/img/pako:eNqNVNtO4zAQ_RXLvAY2F3JpQEhpLrsPRUhQXqBoZRKXRjh2ZCdouf372nHSEhrYddV2MjnHZ-ZM4leYswLDED5wVG_AMllRIJdo73ViBdNmgzluK3CFa0ZKtIIaotblIr6VX7Bkj5ju0qflWXoZ2-bpj_LsbpeOClQ3mCtGH44oF9myT3_iLW5-p8tftwv0jPkN5gyktKhZSZseg2mhg73aI35fNny6dimnKpF_E-XL7H4R0eX8v4u4Fph3VasAMAoGG-_A4eHZmwWiuubsCQvQKHHxBkaWDPQObIMYESKAkBqfcP1FB3PAguWPuw1lc_ugY2kFLQSosBDoAb_15mqgjjucC2LOhDjMN6ikI7R0YYuWcYf2QIJJ-YT5h42lhRqnHFYgH5xLu3b1dT0qTweLhmnd7Rk56EQjJ_YU5mDecrpT2APEE91P9ZN82f2UV-lE919OKQPXlPx7Tj_BkiMq1mrTkWHbAvRvTpAQCV4DPLym65KQ8CD24izzDdFwSQ4PnMQ1576RM8J4eE9Q_njyiY-GV0Xz51bqZNmWb0eBnQXf8Vs1RM3NssSOzC03y4LANL_jkpeembjqs6u6WxPMD3xlnzE4N5jwUaAb_tDd6Mbgp7F9xlQTI4iestE_GuTlBBqwwrxCZSHPzFcFXUEpWuEVDGVY4DVqSaPOmXcJRW3Drp5pDkMpjg3Y1gVqcFIieUBVMFwjImS2RvSGsWoAyUsYvsI_MAysI8_yfNuZeY7tuUFgwGcYWjP3yLdN1_Jl5PiBab8b8KXbwDyaufbMOnYs27OsIPA8A3LWPmy2WrgoG8bP9ZnfHf2GPPpVN1qcy_cD85i1tJFKlj3UnHY8jXr_C5RA8AI?type=png)](https://mermaid.live/edit#pako:eNqNVNtO4zAQ_RXLvAY2F3JpQEhpLrsPRUhQXqBoZRKXRjh2ZCdouf372nHSEhrYddV2MjnHZ-ZM4leYswLDED5wVG_AMllRIJdo73ViBdNmgzluK3CFa0ZKtIIaotblIr6VX7Bkj5ju0qflWXoZ2-bpj_LsbpeOClQ3mCtGH44oF9myT3_iLW5-p8tftwv0jPkN5gyktKhZSZseg2mhg73aI35fNny6dimnKpF_E-XL7H4R0eX8v4u4Fph3VasAMAoGG-_A4eHZmwWiuubsCQvQKHHxBkaWDPQObIMYESKAkBqfcP1FB3PAguWPuw1lc_ugY2kFLQSosBDoAb_15mqgjjucC2LOhDjMN6ikI7R0YYuWcYf2QIJJ-YT5h42lhRqnHFYgH5xLu3b1dT0qTweLhmnd7Rk56EQjJ_YU5mDecrpT2APEE91P9ZN82f2UV-lE919OKQPXlPx7Tj_BkiMq1mrTkWHbAvRvTpAQCV4DPLym65KQ8CD24izzDdFwSQ4PnMQ1576RM8J4eE9Q_njyiY-GV0Xz51bqZNmWb0eBnQXf8Vs1RM3NssSOzC03y4LANL_jkpeembjqs6u6WxPMD3xlnzE4N5jwUaAb_tDd6Mbgp7F9xlQTI4iestE_GuTlBBqwwrxCZSHPzFcFXUEpWuEVDGVY4DVqSaPOmXcJRW3Drp5pDkMpjg3Y1gVqcFIieUBVMFwjImS2RvSGsWoAyUsYvsI_MAysI8_yfNuZeY7tuUFgwGcYWjP3yLdN1_Jl5PiBab8b8KXbwDyaufbMOnYs27OsIPA8A3LWPmy2WrgoG8bP9ZnfHf2GPPpVN1qcy_cD85i1tJFKlj3UnHY8jXr_C5RA8AI)
[![Architecture Diagram](https://mermaid.ink/img/pako:eNqNVNtO4zAQ_RXLvAY2F3JpQEhpLrsPRUhQXqBoZRKXRjh2ZCdouf372nHSEhrYddV2MjnHZ-ZM4leYswLDED5wVG_AMllRIJdo73ViBdNmgzluK3CFa0ZKtIIaotblIr6VX7Bkj5ju0qflWXoZ2-bpj_LsbpeOClQ3mCtGH44oF9myT3_iLW5-p8tftwv0jPkN5gyktKhZSZseg2mhg73aI35fNny6dimnKpF_E-XL7H4R0eX8v4u4Fph3VasAMAoGG-_A4eHZmwWiuubsCQvQKHHxBkaWDPQObIMYESKAkBqfcP1FB3PAguWPuw1lc_ugY2kFLQSosBDoAb_15mqgjjucC2LOhDjMN6ikI7R0YYuWcYf2QIJJ-YT5h42lhRqnHFYgH5xLu3b1dT0qTweLhmnd7Rk56EQjJ_YU5mDecrpT2APEE91P9ZN82f2UV-lE919OKQPXlPx7Tj_BkiMq1mrTkWHbAvRvTpAQCV4DPLym65KQ8CD24izzDdFwSQ4PnMQ1576RM8J4eE9Q_njyiY-GV0Xz51bqZNmWb0eBnQXf8Vs1RM3NssSOzC03y4LANL_jkpeembjqs6u6WxPMD3xlnzE4N5jwUaAb_tDd6Mbgp7F9xlQTI4iestE_GuTlBBqwwrxCZSHPzFcFXUEpWuEVDGVY4DVqSaPOmXcJRW3Drp5pDkMpjg3Y1gVqcFIieUBVMFwjImS2RvSGsWoAyUsYvsI_MAysI8_yfNuZeY7tuUFgwGcYWjP3yLdN1_Jl5PiBab8b8KXbwDyaufbMOnYs27OsIPA8A3LWPmy2WrgoG8bP9ZnfHf2GPPpVN1qcy_cD85i1tJFKlj3UnHY8jXr_C5RA8AI)](https://mermaid.live/edit#pako:eNqNVNtO4zAQ_RXLvAY2F3JpQEhpLrsPRUhQXqBoZRKXRjh2ZCdouf372nHSEhrYddV2MjnHZ-ZM4leYswLDED5wVG_AMllRIJdo73ViBdNmgzluK3CFa0ZKtIIaotblIr6VX7Bkj5ju0qflWXoZ2-bpj_LsbpeOClQ3mCtGH44oF9myT3_iLW5-p8tftwv0jPkN5gyktKhZSZseg2mhg73aI35fNny6dimnKpF_E-XL7H4R0eX8v4u4Fph3VasAMAoGG-_A4eHZmwWiuubsCQvQKHHxBkaWDPQObIMYESKAkBqfcP1FB3PAguWPuw1lc_ugY2kFLQSosBDoAb_15mqgjjucC2LOhDjMN6ikI7R0YYuWcYf2QIJJ-YT5h42lhRqnHFYgH5xLu3b1dT0qTweLhmnd7Rk56EQjJ_YU5mDecrpT2APEE91P9ZN82f2UV-lE919OKQPXlPx7Tj_BkiMq1mrTkWHbAvRvTpAQCV4DPLym65KQ8CD24iyyDdFwSQ4PnMQ1576RM8J4eE9Q_njyiY-GV0Xz51bqZNmWb0eBnQXf8Vs1RM3NssSOzC03y4LANL_jkpeembjqs6u6WxPMD3xlnzE4N5jwUaAb_tDd6Mbgp7F9xlQTI4iestE_GuTlBBqwwrxCZSHPzFcFXUEpWuEVDGVY4DVqSaPOmXcJRW3Drp5pDkMpjg3Y1gVqcFIieUBVMFwjImS2RvSGsWoAyUsYvsI_MAysI8_yfNuZeY7tuUFgwGcYWjP3yLdN1_Jl5PiBab8b8KXbwDyaufbMOnYs27OsIPA8A3LWPmy2WrgoG8bP9ZnfHf2GPPpVN1qcy_cD85i1tJFKlj3UnHY8jXr_C5RA8AI)

## Prerequisites

- [Foundry](https://book.getfoundry.sh/getting-started/installation.html) for contract compilation and deployment
- Ethereum wallet with Sepolia ETH and Arbitrum Sepolia ETH for gas
- RLC tokens on Sepolia testnet for bridge testing

## Setup
## Installation

1. Clone the repository
```bash
git clone https://github.com/yourusername/rlc-layerzero-bridge.git
cd rlc-layerzero-bridge
git clone https://github.com/iExecBlockchainComputing/rlc-multichain.git
cd rlc-multichain
```

2. Install dependencies
Expand All @@ -31,6 +31,16 @@ The system consists of two main components:
```

3. Create a `.env` file
```sh
cp .env.template .env # and edit .env content
```

## Contract Overview

Instead of duplicating code that may become outdated, here are links to the key contracts in the repository:

- [RLCAdapter.sol](https://github.com/iExecBlockchainComputing/rlc-multichain/blob/main/src/RLCAdapter.sol) - Ethereum-side adapter that wraps the existing RLC token
- [RLCOFT.sol](https://github.com/iExecBlockchainComputing/rlc-multichain/blob/main/src/RLCOFT.sol) - Arbitrum-side token that implements the OFT standard

## Deployment

Expand Down Expand Up @@ -60,78 +70,30 @@ After deployment, update your `.env` file with the deployed contract addresses.

## Usage

### Bridge RLC from Ethereum to Arbitrum
### Bridge RLC

To send RLC tokens from Ethereum Sepolia to Arbitrum Sepolia:
A. To send RLC tokens from Ethereum Sepolia to Arbitrum Sepolia:

```bash
make send-tokens
make send-tokens-to-arbitrum-sepolia
```

This will:
1. Approve the RLCAdapter to spend your RLC tokens
2. Initiate the cross-chain transfer through LayerZero
3. Lock tokens in the adapter and mint equivalent tokens on Arbitrum

### Bridge RLC from Arbitrum to Ethereum

To send RLC tokens from Arbitrum Sepolia back to Ethereum Sepolia:
B. To send RLC tokens from Arbitrum Sepolia back to Ethereum Sepolia:

```bash
make send-tokens-arbitrum-sepolia
make send-tokens-to-sepolia
```

This will:
1. Burn RLCOFT tokens on Arbitrum
2. Send a cross-chain message to the adapter
3. Release the original RLC tokens on Ethereum

## Contract Architecture

### RLCAdapter.sol

An adapter that wraps the existing RLC token to make it compatible with LayerZero's OFT protocol. It extends:
- `OFTAdapter`: Handles the OFT cross-chain logic
- `Ownable`: Provides ownership control for administrative functions

```solidity
contract RLCAdapter is Ownable, OFTAdapter {
constructor(address _token, address _lzEndpoint, address _owner)
OFTAdapter(_token, _lzEndpoint, _owner)
Ownable(_owner)
{}
}
```

### RLCOFT.sol

A new token on the destination chain (Arbitrum) that's minted when RLC tokens are locked in the adapter. It extends:
- `OFT`: Implements the OFT cross-chain logic
- `Ownable`: Provides ownership control for administrative functions

```solidity
contract RLCOFT is Ownable, OFT {
constructor(string memory _name, string memory _symbol, address _lzEndpoint, address _delegate)
OFT(_name, _symbol, _lzEndpoint, _delegate)
Ownable(_delegate)
{}

function burn(uint256 _value) external returns (bool) {
_burn(msg.sender, _value);
return true;
}

function approveAndCall(address _spender, uint256 _value, bytes calldata _extraData) public returns (bool) {
TokenSpender spender = TokenSpender(_spender);
if (approve(_spender, _value)) {
spender.receiveApproval(msg.sender, _value, address(this), _extraData);
return true;
}
return false;
}
}
```

## How It Works

1. **Ethereum → Arbitrum:**
Expand All @@ -151,6 +113,7 @@ contract RLCOFT is Ownable, OFT {
- The bridge security relies on LayerZero's security model
- Administrative functions are protected by the Ownable pattern
- Use caution when setting trusted remotes to prevent unauthorized cross-chain interactions
- Always test thoroughly on testnets before deploying to mainnet

## Gas Costs and Fees

Expand All @@ -161,22 +124,11 @@ LayerZero transactions require fees to cover:

The scripts automatically calculate these fees and include them in the transaction.

## Testing

Testing with Foundry tests is recommended before mainnet deployments.

```bash
forge test
```

## Troubleshooting

Common issues:
- Insufficient gas: Ensure you have enough ETH on both networks
- Missing environment variables: Check your .env file is properly loaded
- Chain ID mismatch: Verify LayerZero chain IDs are correct

## References

- [LayerZero Documentation](https://layerzero.gitbook.io/docs/)
- [OFT Contracts](https://github.com/LayerZero-Labs/solidity-examples/tree/main/contracts/token/oft)
- [OFT Contracts](https://github.com/LayerZero-Labs/solidity-examples/tree/main/contracts/token/oft)
- [iExec Platform Documentation](https://docs.iex.ec/)
12 changes: 6 additions & 6 deletions script/ConfigureRLCAdapter.s.sol
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
// script/ConfigureRLCAdapter.s.sol
// SPDX-License-Identifier: UNLICENSED
// SPDX-FileCopyrightText: 2025 IEXEC BLOCKCHAIN TECH <[email protected]>
// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.22;

import {Script, console} from "forge-std/Script.sol";
import {RLCAdapter} from "../src/RLCAdapter.sol";

contract ConfigureRLCAdapter is Script {
contract Configure is Script {
function run() external {
vm.startBroadcast();

// RLCAdapter on Ethereum Sepolia
address adapterAddress = vm.envAddress("SEPOLIA_ADAPTER_ADDRESS"); // Add your RLCAdapter address here
address adapterAddress = vm.envAddress("RLC_SEPOLIA_ADAPTER_ADDRESS"); // Add your RLCAdapter address here
RLCAdapter adapter = RLCAdapter(adapterAddress);

// RLCOFT on Arbitrum Sepolia
address oftAddress = vm.envAddress("ARBITRUM_SEPOLIA_OFT_ADDRESS");
uint16 arbitrumSepoliaChainId = uint16(vm.envUint("ARBITRUM_SEPOLIA_CHAIN_ID"));
address oftAddress = vm.envAddress("ARBITRUM_SEPOLIA_RLC_OFT_ADDRESS");
uint16 arbitrumSepoliaChainId = uint16(vm.envUint("LAYER_ZERO_ARBITRUM_SEPOLIA_CHAIN_ID"));

// Set trusted remote
adapter.setPeer(arbitrumSepoliaChainId, bytes32(uint256(uint160(oftAddress))));
Expand Down
12 changes: 6 additions & 6 deletions script/ConfigureRLCOFT.s.sol
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
// script/ConfigureRLCOFT.s.sol
// SPDX-License-Identifier: UNLICENSED
// SPDX-FileCopyrightText: 2025 IEXEC BLOCKCHAIN TECH <[email protected]>
// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.22;

import {Script, console} from "forge-std/Script.sol";
import {RLCOFT} from "../src/RLCOFT.sol";

contract ConfigureRLCOFT is Script {
contract Configure is Script {
function run() external {
vm.startBroadcast();

// RLCOFT on Arbitrum Sepolia
address oftAddress = vm.envAddress("ARBITRUM_SEPOLIA_OFT_ADDRESS");
address oftAddress = vm.envAddress("ARBITRUM_SEPOLIA_RLC_OFT_ADDRESS");
RLCOFT oft = RLCOFT(oftAddress);

// RLCAdapter on Ethereum Sepolia
address adapterAddress = vm.envAddress("SEPOLIA_ADAPTER_ADDRESS");// Add your RLCAdapter address here
uint16 ethereumSepoliaChainId = uint16(vm.envUint("SEPOLIA_CHAIN_ID")); // LayerZero chain ID for Ethereum Sepolia
address adapterAddress = vm.envAddress("RLC_SEPOLIA_ADAPTER_ADDRESS");// Add your RLCAdapter address here
uint16 ethereumSepoliaChainId = uint16(vm.envUint("LAYER_ZERO_SEPOLIA_CHAIN_ID")); // LayerZero chain ID for Ethereum Sepolia

// Set trusted remote
oft.setPeer(ethereumSepoliaChainId, bytes32(uint256(uint160(adapterAddress))));
Expand Down
Loading
Loading