Skip to content

AxLabs/neox-bridge-devnet

Repository files navigation

Bridge DevNet

This repository contains a Docker Compose–based Bridge Devnet for local development and testing of the Neo N3 ↔ Neo X bridge.

It spins up a complete, reproducible environment including a Neo N3 chain, a Neo X chain (based on the go-ethereum fork maintained by the bane-labs organization), pre-funded accounts, automatic deployment of bridge-related smart contracts, and supporting infrastructure such as RabbitMQ, Prometheus, and Grafana.

The Devnet is designed to enable end-to-end testing, realistic debugging, and operational visibility during bridge development by allowing the full system to be run locally with minimal setup.

Table of Contents

Overview

This project provides a complete development stack with:

  • NeoX Node: Ethereum-compatible blockchain node with dBFT consensus
  • NeoN3 Node: Neo N3 blockchain node for cross-chain operations
  • RabbitMQ: Message broker for inter-service communication

Prerequisites

  • Docker & Docker Compose

Clone the repository (with submodules)

  1. First-time clone:

    git clone --recurse-submodules https://github.com/AxLabs/neox-bridge-devnet.git
    cd neox-bridge-devnet
  2. If you already cloned without submodules:

    git submodule update --init --recursive

Warning

If you update the ./go-ethereum submodule to a different commit, make sure to also run the following command to build the required binaries:

docker compose build neox-node

Quick Start

  1. Navigate to the project directory:

    cd neox-bridge-devnet
  2. Start all services:

    docker compose up
  3. Access the services:

  4. Stop all services:

    docker compose down

    To remove volumes (reset blockchain data):

    docker compose down -v

Funding Accounts

NeoX:

To fund accounts on NeoX, you can use the tools/funding/neox-funding.csv to add addresses and amounts. The funding will be processed automatically after the NeoX node starts, by the neox-funding service.

Important

Create an EVM keystore with cd bridge-evm-contracts && npm run ops -- accounts create-keystore --path ../tools/neox-funding/neox-wallets/personal.json. Use an empty password for the default devnet flow, or set the matching OPS_PERSONAL_PASSWORD value when running ops commands. When this keystore exists during deployment, the bridge funding step also funds the personal wallet with the NEO token on NeoX. If you create it after deployment, run ./tools/neox-funding/fund-personal-neo-token.sh while the devnet is running.

Optionally, you can invoke again the funding script manually if needed:

 docker compose up -d neox-funding

Note

Running the funding script multiple times will fund all the addresses in tools/funding/neox-funding.csv as well as the default accounts only if they have less balance than the GAS_AMOUNT env variable.

NeoN3:

To fund accounts on NeoN3, you must now specify both the GAS_AMOUNT and the NEO_AMOUNT environment variables for the neon3-funding service. The funding will be processed automatically after the NeoN3 node starts, and it will also fund all the wallets in the /tools/neon3-funding/neon3-wallets directory.

  • Both GAS and NEO tokens are funded.
  • The NEO amount is now a required parameter.
  • The script will only fund a wallet if its GAS balance is below the GAS_AMOUNT or its NEO balance is below the NEO_AMOUNT.
  • The docker-compose command for neon3-funding now explicitly sets the NEO amount as the third parameter.
  • If you run the funding service multiple times, it will only top up wallets that are below the specified thresholds for either token.

Optionally, you can invoke the funding script manually if needed:

docker compose up -d neon3-funding

Note:

  • Both GAS_AMOUNT and NEO_AMOUNT must be set and must be valid numbers.
  • The script will validate these parameters and fail early if they are missing or invalid.
  • The script now provides clear error messages and debug output if there are issues with the funding process.

Check Node Availability

To verify that the nodes are up and responding via RPC:

Neo X:

curl -X POST --json '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}' http://localhost:8562

Neo N3:

curl -s -X POST --json '{"jsonrpc" : "2.0", "id": 1, "method": "getblockcount", "params":[] }' http://localhost:40332

Deployment of EVM Message Bridge Contracts

Initial Setup

NeoX EVM Contracts Deployment

The EVM contracts are deployed automatically when the neox-contracts service starts. It uses the Foundry deployment scripts from bridge-evm-contracts/script/deploy and the wallets in the tools/neox-funding/neox-wallets folder to deploy the bridge stack. The deployment logs can be found in the neox-contracts service logs.

The same service also deploys the devnet NEO token with forge create and registers it through the bridge-evm-contracts ops CLI. The devnet owns this token deployment and registration orchestration; the contracts repo only provides the bridge deployment scripts and ops commands.

The deployment service writes:

  • bridge addresses to tools/addresses/neox-addresses.json
  • the Foundry deployment manifest to bridge-evm-contracts/deployments/foundry/neox-devnet.json
  • local ops config to bridge-evm-contracts/config/*.local.json and bridge-evm-contracts/config/accounts/neox-devnet.json

The service can also be run manually if it did not start automatically. This service depends on the NeoX node being operational and the deployer wallet having sufficient funds:

docker compose up -d neox-contracts

NeoN3 Contracts Deployment

The NeoN3 contracts are deployed automatically when the neon3-contracts service starts. It uses the wallets in the tools/neon3-funding/neon3-wallets folder to deploy the contracts. The deployment logs can be found in the neon3-contracts service logs.

The service can also be run manually if it did not start automatically. This service depends on the NeoN3 node being operational and the deployer wallet having sufficient funds:

docker compose up -d neon3-contracts

Changing Contracts And Deploying Again

If you make changes to the contracts and want to deploy them again, you can follow these steps:

  1. Stop all the services:

    docker compose down -v
  2. Checkout the desired branch or make changes to the contracts repos.

  3. Update the service definitions and commands

    Make sure that the correct deployment script is invoked by the neox-contracts and neon3-contracts services. Ensure that all expected environment variables are correctly set and any required volumes are correctly mounted.

    The scripts used for deployment are located as follows:

  4. Start the services again:

    docker compose up -d

Additional Tools

Sending Messages from NEOX to NEON3

To send messages from NeoX to NeoN3, use scripts in tools/send-from-evm. The default wallet is deployer, override with PERSONAL_WALLET_FILENAME. The scripts use the EVM contracts ops CLI and read wallets from tools/neox-funding/neox-wallets.

If the wallet has insufficient funds, the script will fail. Fund the wallet beforehand (see Funding Accounts).

1. Sending a String Message

./tools/send-from-evm/send-string.sh <message> [network]
  • <message>: String message to send (required).
  • [network]: Target NeoN3 network (optional, default: neoxDevnet).

Environment Variables:

  • PERSONAL_WALLET_FILENAME: Wallet name (default: deployer)

2. Sending an N3 Scripthash Message

./tools/send-from-evm/send-n3-script.sh <script_hex> [store_result] [network]
  • <script_hex>: Hex-encoded NeoN3 script (required).
  • [store_result]: Store result (true or false, default: true).
  • [network]: Target NeoN3 network (optional, default: neoxDevnet).

N3 scripts are always sent as executable messages.

Environment Variables:

  • Same as above.

3. Sending a Custom Message

./tools/send-from-evm/send-message.sh [OPTIONS]

Options:

  • -a, --address ADDRESS: MessageBridge contract address override (default: messageBridge from tools/addresses/neox-addresses.json)
  • -t, --type TYPE: Message type (executable or store-only, default: store-only)
  • -d, --data DATA: Raw hex message data, string message, or NeoN3 script bytes
  • -s, --store-result BOOL: Store result for executable messages (default: true)
  • -n, --network NETWORK: Ops network (default: neox-devnet; neoxDevnet is accepted)
  • -h, --help: Show help

Environment Variables:

  • PERSONAL_WALLET_FILENAME

Notes:

  • MessageBridge address defaults to messageBridge from tools/addresses/neox-addresses.json if not provided.
  • The deployment service generates local ops config in bridge-evm-contracts/config/*.local.json and bridge-evm-contracts/config/accounts/neox-devnet.json.
  • If you encounter issues, check script output and verify wallet balances and environment variables.

Sending Messages from NEON3 to NEOX

Use scripts in tools/send-from-neo. The default wallet is deployer, override with SENDER_WALLET. Wallets must exist in bridge-neo-contracts/wallets (auto-copied from tools/neon3-funding/neon3-wallets if missing).

If the wallet has insufficient funds, the script will fail. Fund the wallet beforehand (see Funding Accounts).

1. Sending a String Message

./tools/send-from-neo/send-string.sh <message> [node_url]
  • <message>: String message to send (required).
  • [node_url]: NeoN3 RPC endpoint URL (optional, default: http://127.0.0.1:40332).

Environment Variables:

  • SENDER_WALLET: User wallet JSON file (default: deployer it refers to wallets/deployer.json)
  • SENDER_WALLET_PASSWORD: Wallet password

2. Sending an EVM Contract Call

./tools/send-from-neo/send-evm-call.sh <evm_data_hex> [store_result] [node_url]
  • <evm_data_hex>: Hex-encoded EVM contract call data (required).
  • [store_result]: Store result (true or false, default: true).
  • [node_url]: NeoN3 RPC endpoint URL (optional, default: http://127.0.0.1:40332).

Environment Variables:

  • Same as above.

3. Sending a Custom Message

./tools/send-from-neo/send-message.sh [OPTIONS]

Options:

  • -a, --address ADDRESS: MessageBridge contract hash override (default: messageBridge from tools/addresses/n3-addresses.json)
  • -t, --type TYPE: Message type (executable or store-only, default: store-only)
  • -d, --data DATA: Raw hex message data, string message, or EVM contract call data
  • -f, --fee-sponsor HASH160: Fee sponsor hash160 (optional)
  • -s, --store-result BOOL: Store result for executable messages (default: true)
  • -n, --node URL: NeoN3 RPC endpoint URL (default: http://127.0.0.1:40332)
  • -h, --help: Show help

Environment Variables:

  • Same as above.

Notes:

  • MessageBridge hash defaults to messageBridge from tools/addresses/n3-addresses.json if not provided.
  • The deployment service generates local ops config in bridge-evm-contracts/config/*.local.json and bridge-evm-contracts/config/accounts/neox-devnet.json.
  • If you encounter issues, check script output and verify your environment variables and wallet balances.

Token Bridge Asset Movement

Use scripts in tools/token-bridge to move assets through the TokenBridge. By default, the scripts read the Bridge contract from tools/addresses/n3-addresses.json or tools/addresses/neox-addresses.json, depending on the direction. Pass --bridge only when you want to override that devnet default.

Native asset movement has two sides:

  • On NeoN3, deposits use the representative NEP-17 token configured as the native bridge token.
  • On NeoX, withdrawals use the native EVM coin.

Token movement uses registered token pairs:

  • NeoN3 deposits use the neoToken hash from tools/addresses/n3-addresses.json by default.
  • NeoX withdrawals use an ERC20 token alias from bridge-evm-contracts/config/deployments/<network>.local.json or a direct ERC20 address.

If a wallet has insufficient funds or token allowance, the script will fail with the underlying bridge/ops error. Fund the wallet beforehand (see Funding Accounts).

Deposit Native from NeoN3 to NeoX

./tools/token-bridge/deposit-native.sh --to <evm_recipient_hash160> --amount <raw_amount>

Example:

./tools/token-bridge/deposit-native.sh \
  --to 0x1111111111111111111111111111111111111111 \
  --amount 100000000

Options:

  • -a, --bridge HASH: Bridge contract hash override (default: bridge from tools/addresses/n3-addresses.json)
  • -t, --to HASH160: EVM recipient as 20-byte hex/hash160
  • -m, --amount RAW_AMOUNT: Raw integer amount to deposit
  • -w, --wallet WALLET: Sender wallet name without .json (default: deployer)
  • -n, --node URL: NeoN3 RPC endpoint (default: http://127.0.0.1:40332)

Environment variables:

  • SENDER_WALLET: Sender wallet name without .json (default: deployer)
  • SENDER_WALLET_PASSWORD: Sender wallet password

Deposit Token from NeoN3 to NeoX

./tools/token-bridge/deposit-token.sh --to <evm_recipient_hash160> --amount <raw_amount>

Example:

./tools/token-bridge/deposit-token.sh \
  --to 0x1111111111111111111111111111111111111111 \
  --amount 100000000

Options:

  • -a, --bridge HASH: Bridge contract hash override (default: bridge from tools/addresses/n3-addresses.json)
  • -k, --token HASH: NEP-17 token hash override (default: neoToken from tools/addresses/n3-addresses.json)
  • -t, --to HASH160: EVM recipient as 20-byte hex/hash160
  • -m, --amount RAW_AMOUNT: Raw integer token amount to deposit
  • -w, --wallet WALLET: Sender wallet name without .json (default: deployer)
  • -n, --node URL: NeoN3 RPC endpoint (default: http://127.0.0.1:40332)

Environment variables:

  • SENDER_WALLET: Sender wallet name without .json (default: deployer)
  • SENDER_WALLET_PASSWORD: Sender wallet password

Withdraw Native from NeoX to NeoN3

./tools/token-bridge/withdraw-native.sh --to <neo_n3_recipient_hash160> --amount <amount>

Example:

./tools/token-bridge/withdraw-native.sh \
  --to 0x1111111111111111111111111111111111111111 \
  --amount 0.1

Options:

  • -a, --bridge ADDRESS: Bridge contract address override (default: bridge from tools/addresses/neox-addresses.json)
  • -t, --to ADDRESS: NeoN3 recipient represented as 20-byte hex/address
  • -m, --amount AMOUNT: Amount in native decimal units
  • --account ACCOUNT: EVM ops account alias (default from PERSONAL_WALLET_FILENAME, or deployer)
  • -n, --network NETWORK: Ops network (default: neox-devnet; neoxDevnet is accepted)
  • --dry-run [BOOL]: Print the transaction without sending it
  • --yes: Confirm mainnet write guard

Environment variables:

  • PERSONAL_WALLET_FILENAME: Wallet file name without .json used for the personal account
  • OPS_*_PASSWORD: Passwords consumed by the EVM ops account config

Withdraw Token from NeoX to NeoN3

./tools/token-bridge/withdraw-token.sh --token <alias_or_erc20_address> --to <neo_n3_recipient_hash160> --amount <amount> --approve

Example:

./tools/token-bridge/withdraw-token.sh \
  --token neo \
  --to 0x1111111111111111111111111111111111111111 \
  --amount 1 \
  --approve

Options:

  • -a, --bridge ADDRESS: Bridge contract address override (default: bridge from tools/addresses/neox-addresses.json)
  • -k, --token TOKEN: Token alias or ERC20 address (default: neo)
  • -t, --to ADDRESS: NeoN3 recipient represented as 20-byte hex/address
  • -m, --amount AMOUNT: Amount in token decimal units
  • --account ACCOUNT: EVM ops account alias (default from PERSONAL_WALLET_FILENAME, or deployer)
  • -n, --network NETWORK: Ops network (default: neox-devnet; neoxDevnet is accepted)
  • --approve: Approve bridge spending before withdrawing if needed
  • --dry-run [BOOL]: Print the transaction without sending it
  • --yes: Confirm mainnet write guard

Environment variables:

  • PERSONAL_WALLET_FILENAME: Wallet file name without .json used for the personal account
  • OPS_*_PASSWORD: Passwords consumed by the EVM ops account config

For the full script-local reference, see tools/token-bridge/README.md.

TypeScript Bridge Examples

The tools/bridge-examples-ts directory provides TypeScript scripts for interacting with the MessageBridge contract. These examples use the bridge-sdk-ts library and cover common operations such as sending messages, executing contract calls, and querying contract state.

For setup and usage instructions, see the bridge-examples-ts README.

About

Private Network of Neo X and Neo N3, including the native bridge smart contracts

Resources

License

Stars

3 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors