How to customize your Orbit chain's precompiles
Orbit chains are currently a public preview capability. This offering and its supporting documentation may change significantly as we capture feedback from readers like you.
To provide feedback, click the Request an update button at the top of this document, join the Arbitrum Discord, or reach out to our team directly by completing this form.
There are two ways to customize your chain's precompiles:
- Add new methods to to an existing precompile.
- Create a new precompile.
Prerequisites
Clone the Nitro repository before you begin:
git clone --branch v2.1.0-beta.16 <https://github.com/OffchainLabs/nitro.git>
cd nitro
git submodule update --init --recursive --force
Option 1: Add new methods to an existing precompile
Using your favorite code editor, open an existing precompile from the precompiles/ directory. We'll use ArbSys.sol
as an example. Open the the corresponding go
file (ArbSys.go
) and add a simple SayHi
method:
func (con *ArbSys) SayHi(c ctx, evm mech) (string, error) {
return "hi", nil
}
Then, open the corresponding Solidity interface file (ArbSys.sol
) from the contracts/src/precompiles/ directory and add the required interface. Ensure that the method name on the interface matches the name of the function you introduced in the previous step, camelCased
:
function sayHi() external view returns(string memory);
Next, build Nitro by following steps 3-7 of the instructions in How to build Nitro locally. Note that if you've already built the Docker image, you still need run the last step to rebuild.
Run Nitro by following the instructions (Note the instructions in How to run a full node cann't start orbit node):
docker run --rm -it -v /some/local/dir/arbitrum:/home/user/.arbitrum -p 0.0.0.0:8547:8547 -p 0.0.0.0:8548:8548 offchainlabs/nitro-node:v2.1.0-beta.16-ad8cfe5 --parent-chain.connection.url=<YourParentChainUrl> --chain.id=<YourOrbitChainId> --http.api=net,web3,eth,debug --http.corsdomain=* --http.addr=0.0.0.0 --http.vhosts=*
Once your node is running, you can call ArbSys.sol
either directly using curl
, or through Foundry's cast call
.
Call your function directly using curl
curl Your_IP_Address:8547\
-X POST \
-H "Content-Type: application/json" \
--data '{"method":"eth_call","params":[{"from":null,"to":"0x0000000000000000000000000000000000000064","data":"0x0c49c36c"}, "latest"],"id":1,"jsonrpc":"2.0"}'
You should see something like this:
{"jsonrpc":"2.0","id":1,"result":"0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000026869000000000000000000000000000000000000000000000000000000000000"}
0x6869
is the hex-encoded utf8 representation of hi
, which you'll see embedded in the result
hex string.
Call your function using Foundry's cast call
cast call 0x0000000000000000000000000000000000000064 "sayHi()(string)”
You should see something like this:
hi
Option 2: Create a new precompile
First, navigate to the precompiles/
directory and create a new precompile called ArbSys.sol
. We'll define a new method, and we'll give it an address:
package precompiles
// ArbGasInfo provides insight into the cost of using the rollup.
type ArbHi struct {
Address addr // 0x11a, for example
}
func (con *ArbHi) SayHi(c ctx, evm mech) (string, error) {
return "hi", nil
}
Then, update precompile.go to register the new precompile under the Precompiles()
method:
insert(MakePrecompile(templates.ArbHiMetaData, &ArbHi{Address: hex("11a")})) // 0x011a here is an example address
Navigate to contracts/src/precompiles/, create ArbHi.sol
, and add the required interface. Ensure that the method name on the interface matches the name of the function you introduced in the previous step, camelCased
:
pragma solidity >=0.4.21 <0.9.0;
/// @title Say hi.
/// @notice just for test
/// This custom contract will set on 0x000000000000000000000000000000000000011a since we set it in precompile.go.
interface ArbHi {
function sayHi() external view returns(string memory);
}
Next, build Nitro by following the instructions in How to build Nitro locally. Note that if you've already built the Docker image, you still need run the last step to rebuild.
Run Nitro by following the instructions (Note the instructions in How to run a full node cann't start orbit node):
docker run --rm -it -v /some/local/dir/arbitrum:/home/user/.arbitrum -p 0.0.0.0:8547:8547 -p 0.0.0.0:8548:8548 offchainlabs/nitro-node:v2.1.0-beta.16-ad8cfe5 --parent-chain.connection.url=<YourParentChainUrl> --chain.id=<YourOrbitChainId> --http.api=net,web3,eth,debug --http.corsdomain=* --http.addr=0.0.0.0 --http.vhosts=*
Once your node is running, you can call ArbHi.sol
either directly using curl
, or through Foundry's cast call
.
Call your function directly using curl
curl Your_IP_Address:8547 \
-X POST \
-H "Content-Type: application/json" \
--data '{"method":"eth_call","params":[{"from":null,"to":"0x000000000000000000000000000000000000011a","data":"0x0c49c36c"}, "latest"],"id":1,"jsonrpc":"2.0"}'
You should see something like this:
{"jsonrpc":"2.0","id":1,"result":"0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000026869000000000000000000000000000000000000000000000000000000000000"}
Call your function using Foundry's cast call
cast call 0x000000000000000000000000000000000000011a "sayHi()(string)”
You should see something like this:
hi