Mantle

Set up your Mantle RPC node

Requirements

Prerequisites

Install docker

sudo apt update
sudo apt install snapd
sudo apt-get install jq -y
snap install docker
curl -L https://foundry.paradigm.xyz | bash && source /root/.bashrc && foundryup

Download configs

git clone https://github.com/mantlenetworkio/networks.git mantlenetworks
cd mantlenetworks

Generate JWT secret and p2p node key

mkdir -p mainnet/secret
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))" > mainnet/secret/jwt_secret_txt
cast w n |grep -i "Private Key" |awk -F ": " '{print $2}' |sed 's/0x//' > mainnet/secret/p2p_node_key_txt
mkdir sepolia/secret
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))" > sepolia/secret/jwt_secret_txt
cast w n |grep -i "Private Key" |awk -F ": " '{print $2}' |sed 's/0x//' > sepolia/secret/p2p_node_key_txt

Update node config

⚠️

Make sure to set ETH1_HTTP to your own Ethereum RPC node for security.

Set the following config option in mainnet/envs/geth.env:

ETH1_HTTP=your_ethereum_mainnet_l1_node
GCMODE=full # or archive

Set the following config option in docker-compose-sepolia.yml

OP_NODE_L1_ETH_RPC=your_ethereum_sepolia_l1_node

Download latest snapshot

Download the latest snapshot for a quicker sync: Mainnet | Testnet

mkdir -p ./data/mainnet-geth
tarball="[latest snapshot].tar"
wget https://s3.ap-southeast-1.amazonaws.com/snapshot.mantle.xyz/${tarball}
tar vxf ${tarball} -C ./data/mainnet-geth
mkdir -p ./data/geth
tarball="[latest snapshot].tar"
wget https://s3.ap-southeast-1.amazonaws.com/static.testnet.mantle.xyz/${tarball}
tar vxf ${tarball} -C ./data/geth

Start the node

docker compose -f docker-compose-mainnetv2.yml up -d
docker compose -f docker-compose-sepolia.yml up -d

An output similar to the following will be shown:

[+] Running 6/6
 ✔ replica 5 layers [⣿⣿⣿⣿⣿]      0B/0B      Pulled
   ✔ 0cdfa0c98ed7 Pull complete
   ✔ da01580fbcc6 Pull complete
[+] Running 1/1
 ✔ Container mantlenetworks-replica-1  Started

After it is done, verify by listing the services and their status

docker compose -f docker-compose-mainnetv2.yml ps
docker compose -f docker-compose-sepolia.yml ps

You should see these 2 services running

NAME                       IMAGE                                  COMMAND             SERVICE             CREATED             STATUS              PORTS
NAME                       IMAGE                                    COMMAND                  SERVICE             CREATED             STATUS                          PORTS
mantlenetworks-op-geth-1   mantlenetworkio/op-geth:v1.0.0-alpha.1   "geth --datadir=/db …"   op-geth             7 minutes ago       Up 7 minutes                    0.0.0.0:8545-8546->8545-8546/tcp, :::8545-8546->8545-8546/tcp, 0.0.0.0:8551->8551/tcp, :::8551->8551/tcp, 30303/tcp, 30303/udp
mantlenetworks-op-node-1   mantlenetworkio/op-node:v1.0.0-alpha.1   "op-node"                op-node             7 minutes ago       Up 7 minutes

Check logs

Verify mantle geth logs

docker compose logs op-geth --since 2m -f
mantlenetworks-op-geth-1  | INFO [04-01|11:02:21.459] Starting peer-to-peer node               instance=Geth/v0.1.0-unstable-e1c72d53-20240312/linux-amd64/go1.20.14
mantlenetworks-op-geth-1  | INFO [04-01|11:02:21.502] New local node record                    seq=1,711,969,341,501 id=d90665a63ea4440a ip=127.0.0.1 udp=30300 tcp=30300
mantlenetworks-op-geth-1  | INFO [04-01|11:02:21.502] Started P2P networking                   self=enode://904642693e46d2f64234e635d4b3777e23d9227920ea27eaf62d76387eee2ecfe3a1c8881f2cc71b1c68b2e148a6215fc9e4c361b285f1bec9c5f0e92978e408@127.0.0.1:30300
mantlenetworks-op-geth-1  | INFO [04-01|11:02:21.503] IPC endpoint opened                      url=/db/geth.ipc
mantlenetworks-op-geth-1  | INFO [04-01|11:02:21.503] Loaded JWT secret file                   path=/secret/jwt_secret_txt crc32=0x61dfbe40
mantlenetworks-op-geth-1  | INFO [04-01|11:02:21.503] HTTP server started                      endpoint=[::]:8545 auth=false prefix= cors=* vhosts=*
mantlenetworks-op-geth-1  | INFO [04-01|11:02:21.503] WebSocket enabled                        url=ws://[::]:8546
mantlenetworks-op-geth-1  | INFO [04-01|11:02:21.503] WebSocket enabled                        url=ws://[::]:8551
mantlenetworks-op-geth-1  | INFO [04-01|11:02:21.503] HTTP server started                      endpoint=[::]:8551 auth=true  prefix= cors=localhost vhosts=*
mantlenetworks-op-geth-1  | INFO [04-01|11:02:23.907] New local node record                    seq=1,711,969,341,502 id=d90665a63ea4440a ip=65.108.239.113 udp=30300 tcp=30300

It will not import new headers until your op-node is synced, once your op-node is synced, your blast-geth logs should look like this

mantlenetworks-op-geth-1  | INFO [02-29|08:08:15.219] Starting work on payload                 id=0x48323feb74b0d35a
mantlenetworks-op-geth-1  | INFO [02-29|08:08:15.237] Imported new potential chain segment     number=3083 hash=96c535..584bd5 blocks=1 txs=1 mgas=0.047 elapsed=16.962ms    mgasps=2.768 age=1mo3w1d snapdiffs=606.60KiB triedirty=0.00B
mantlenetworks-op-geth-1  | INFO [02-29|08:08:15.243] Chain head was updated                   number=3083 hash=96c535..584bd5 root=52730a..6a9c02 elapsed=5.42431ms   age=1mo3w1d
mantlenetworks-op-geth-1  | INFO [02-29|08:08:15.256] Starting work on payload                 id=0x180234ae531457a1
mantlenetworks-op-geth-1  | INFO [02-29|08:08:15.274] Imported new potential chain segment     number=3084 hash=9687bc..de7e94 blocks=1 txs=1 mgas=0.047 elapsed=16.911ms    mgasps=2.776 age=1mo3w1d snapdiffs=606.78KiB triedirty=0.00B
mantlenetworks-op-geth-1  | INFO [02-29|08:08:15.285] Chain head was updated                   number=3084 hash=9687bc..de7e94 root=8081fb..43e327 elapsed=10.075637ms age=1mo3w1d
mantlenetworks-op-geth-1  | INFO [02-29|08:08:15.307] Starting work on payload                 id=0x44c95802c3652dbd

Verify OP node logs

docker compose logs op-node --since 2m -f

You should see logs like

mantlenetworks-op-node-1  | t=2024-02-27T07:43:46+0000 lvl=info msg="Starting JSON-RPC server"
mantlenetworks-op-node-1  | t=2024-02-27T07:43:46+0000 lvl=info msg="metrics disabled"
mantlenetworks-op-node-1  | t=2024-02-27T07:43:46+0000 lvl=info msg="Starting execution engine driver"
mantlenetworks-op-node-1  | t=2024-02-27T07:43:46+0000 lvl=info msg="Starting driver"                   sequencerEnabled=false sequencerStopped=false
mantlenetworks-op-node-1  | t=2024-02-27T07:43:46+0000 lvl=info msg="Rollup node started"
mantlenetworks-op-node-1  | t=2024-02-27T07:43:46+0000 lvl=info msg="State loop started"
mantlenetworks-op-node-1  | t=2024-02-27T07:43:46+0000 lvl=info msg="Loaded current L2 heads"           unsafe=0x26a1c0faad7b041f34569a1bb383f00ab74b335883a44bed53e9f41ced5fd906:0 safe=0x26a1c0faad7b041f34569a1bb383f00ab74b335883a44bed53e9f41ced5fd906:0 finalized=0x26a1c0faad7b041f34569a1bb383f00ab74b335883a44bed53e9f41ced5fd906:0 unsafe_origin=0x17728cf4d8e0b4f292d2390a869fd7c632d39e72efb00ca3462b4387c6aa2437:5044255 safe_origin=0x17728cf4d8e0b4f292d2390a869fd7c632d39e72efb00ca3462b4387c6aa2437:5044255
mantlenetworks-op-node-1  | t=2024-02-27T07:43:47+0000 lvl=info msg="Walking back L1Block by number"    curr=0x17728cf4d8e0b4f292d2390a869fd7c632d39e72efb00ca3462b4387c6aa2437:5044255 next=0x17728cf4d8e0b4f292d2390a869fd7c632d39e72efb00ca3462b4387c6aa2437:5044255 l2block=0x26a1c0faad7b041f34569a1bb383f00ab74b335883a44bed53e9f41ced5fd906:0
mantlenetworks-op-node-1  | t=2024-02-27T07:43:47+0000 lvl=info msg="Hit finalized L2 head, returning immediately" unsafe=0x26a1c0faad7b041f34569a1bb383f00ab74b335883a44bed53e9f41ced5fd906:0 safe=0x26a1c0faad7b041f34569a1bb383f00ab74b335883a44bed53e9f41ced5fd906:0 finalized=0x26a1c0faad7b041f34569a1bb383f00ab74b335883a44bed53e9f41ced5fd906:0 unsafe_origin=0x17728cf4d8e0b4f292d2390a869fd7c632d39e72efb00ca3462b4387c6aa2437:5044255 safe_origin=0x17728cf4d8e0b4f292d2390a869fd7c632d39e72efb00ca3462b4387c6aa2437:5044255
mantlenetworks-op-node-1  | t=2024-02-27T07:43:47+0000 lvl=info msg="Sync progress"                     reason="reset derivation work" l2_finalized=0x26a1c0faad7b041f34569a1bb383f00ab74b335883a44bed53e9f41ced5fd906:0 l2_safe=0x26a1c0faad7b041f34569a1bb383f00ab74b335883a44bed53e9f41ced5fd906:0 l2_unsafe=0x26a1c0faad7b041f34569a1bb383f00ab74b335883a44bed53e9f41ced5fd906:0 l2_engineSyncTarget=0x26a1c0faad7b041f34569a1bb383f00ab74b335883a44bed53e9f41ced5fd906:0 l2_time=1,704,686,688 l1_derived=0x17728cf4d8e0b4f292d2390a869fd7c632d39e72efb00ca3462b4387c6aa2437:5044255

Verify node sync status

RPC Endpoint

echo "$(curl -4 ifconfig.co):8545"

Method 1:

curl -X POST [rpc] -H "Content-Type: application/json" --data '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}' | jq

If you get something like this in response to the above rpc call, your node is setup correctly

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": "0x4e4c"
}

You can use a hex to number convertor to get the block height

Method 2:

You can also check your status by connecting to geth console

docker exec -it mantlenetworks-op-geth-1 geth attach http://localhost:8545
> eth.blockNumber
1209 # it will show you the latest block - number here is just an example

You can compare the block height on your node with explorer (mainnet or testnet), use your RPC node only when it has caught up with the latest block height.

Configure vald

In order for vald to connect to your mantle node, your rpc_addr should be exposed in vald’s config.toml

[[QP_bridge_evm]]
name = "mantle"
rpc_addr = "http://IP:PORT"
start-with-bridge = true
[[QP_bridge_evm]]
name = "mantle"
rpc_addr = "http://IP:PORT"
start-with-bridge = true
Edit this page