Skip to content

Commit

Permalink
Merge pull request #683 from OffchainLabs/add-custom-events
Browse files Browse the repository at this point in the history
Add custom events
  • Loading branch information
symbolpunk committed Oct 19, 2023
2 parents ddd0d4f + ee2a6e2 commit f7f23c4
Showing 1 changed file with 107 additions and 1 deletion.
108 changes: 107 additions & 1 deletion arbitrum-docs/launch-orbit-chain/how-tos/customize-precompile.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,11 @@ To support these additional use-cases, follow the instructions described in [How

:::

There are two ways to customize your chain's precompiles:
There are three primary ways to customize your chain's precompiles:

1. Add new methods to an existing [precompile][precompile_impl_dir_link].
2. Create a new precompile.
3. Define a new event.

### Prerequisites

Expand Down Expand Up @@ -162,6 +163,111 @@ You should see something like this:
hi
```

## Option 3: Define a new event

We'll reuse the `Arbsys` precompile from Option 1 above to demonstrate how to emit a simple `Hi` event from the `SayHi` method in `ArbSys.sol`.

First, go to the [precompiles implementation][precompile_impl_dir_link] directory, find `ArbSys.go`, and edit the `ArbSys` struct:

```go
// ArbSys provides system-level functionality for interacting with L1 and understanding the call stack.
type ArbSys struct {
Address addr // 0x64
L2ToL1Tx func(ctx, mech, addr, addr, huge, huge, huge, huge, huge, huge, []byte) error
L2ToL1TxGasCost func(addr, addr, huge, huge, huge, huge, huge, huge, []byte) (uint64, error)
SendMerkleUpdate func(ctx, mech, huge, bytes32, huge) error
SendMerkleUpdateGasCost func(huge, bytes32, huge) (uint64, error)
InvalidBlockNumberError func(huge, huge) error

// deprecated event
L2ToL1Transaction func(ctx, mech, addr, addr, huge, huge, huge, huge, huge, huge, huge, []byte) error
L2ToL1TransactionGasCost func(addr, addr, huge, huge, huge, huge, huge, huge, huge, []byte) (uint64, error)

// Add your customize event here:
Hi func(ctx, mech, addr) error
// This is needed and will tell you how much gas it will cost, the param is the same as your event but without the first two (ctx, mech), the return param is always (uint64, error)
HiGasCost func(addr) (uint64, error)
}
```

Then add the event to the `SayHi` method:

```go
func (con *ArbSys) SayHi(c ctx, evm mech) (string, error) {
err := con.Hi(c, evm, c.caller)
return "hi", err
}
```

Now navigate to the [precompiles interface][precompile_interface_dir_link] directory, open `Arbsys.sol`, and add the required interface. Ensure that the event name on the interface matches the name of the function you introduced in `ArbSys` struct in the previous step:

```solidity
event Hi(address caller);
```

If you want to [index the parameter](https://docs.soliditylang.org/en/latest/contracts.html#events) of the event (if you want to filter by that parameter in the future, for example), just add `indexed` to the Solidity interface:

```solidity
event Hi(address indexed caller);
```

Our function now emits an event, which means that when calling it, the state will change and a gas cost will be incurred. So we have to remove the `view` function behavior:

```solidity
function sayHi() external returns(string memory);
```

Next, build Nitro by following the instructions in [How to build Nitro locally](/node-running/how-tos/build-nitro-locally). Note that if you've already built the Docker image, you still need run the last step to rebuild.

Run Nitro with the following command:

```shell
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 @latestNitroNodeImage@ --parent-chain.connection.url=<YourParentChainUrl> --chain.id=<YourOrbitChainId> --http.api=net,web3,eth,debug --http.corsdomain=* --http.addr=0.0.0.0 --http.vhosts=*
```

:::info

Note that the instructions provided in [How to run a full node](/node-running/how-tos/running-a-full-node) **will not** work with your Orbit node. See [Command-line options (Orbit)](/launch-orbit-chain/reference/command-line-options) for Orbit-specific CLI flags.

:::

### Send the transaction and get the transaction receipt

To send a transaction to `ArbSys`, we need to include a gas cost, because the function is no longer a view/pure function:

```
cast send 0x0000000000000000000000000000000000000064 "sayHi()(string)"
```

Call `eth_getTransactionReceipt` with the returned transaction hash result. You should see something like this:

```
{"jsonrpc":"2.0","id":1,"result":{"blockHash":"Your_blockHash","blockNumber":"Your_blockNumber","contractAddress":null,"cumulativeGasUsed":"0x680b","effectiveGasPrice":"0x5f5e100","from":"Your_address","gasUsed":"0x680b","gasUsedForL1":"0xe35","l1BlockNumber":"l1_blockNumber","logs":[{"address":"0x0000000000000000000000000000000000000064","topics":["0xa9378d5bd800fae4d5b8d4c6712b2b64e8ecc86fdc831cb51944000fc7c8ecfa","0x000000000000000000000000{Your_address}"],"data":"0x","blockNumber":"Your_blockNumber","transactionHash":"Your_txHash","transactionIndex":"0x1","blockHash":"Your_blockHash","logIndex":"0x0","removed":false}],"logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000100000000000000040000000000000080004000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000004000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000","status":"0x1","to":"0x0000000000000000000000000000000000000064","transactionHash":"Your_txHash","transactionIndex":"0x1","type":"0x2"}}
```

Note the `logs` field within the transaction receipt:

```
"logs":[
{
"address":"0x0000000000000000000000000000000000000064",
"topics":[
"0xa9378d5bd800fae4d5b8d4c6712b2b64e8ecc86fdc831cb51944000fc7c8ecfa",
"0x000000000000000000000000{Your_address}"
],
"data":"0x",
"blockNumber":"0x40",
"transactionHash":"{Your_txHash}",
"transactionIndex":"0x1",
"blockHash":"0x0b367d705002b3575db99354a0964c033f929f26f4442ed347e47ae43a8f28e4",
"logIndex":"0x0",
"removed":false
}
]
```

From the `logs` field, we can see the `topics[0]` is `0xa937..cfa`, which is the event signature of `Hi(address)`. You can verify this using [4 byte directory](https://www.4byte.directory/event-signatures/?bytes_signature=0xa9378d5bd800fae4d5b8d4c6712b2b64e8ecc86fdc831cb51944000fc7c8ecfa) - `topics[1]` is `Your_address`, which is exactly what we defined above!

<!-- For clarity in the code, we add here all links to github, using "link references" (First the interfaces, and below the implementations) -->
<!--
Note that nitro-contracts repository is hardcoded because atm we use the "nitro" repository for referencing precompiles for the current released nitro version (for Arb chains),
Expand Down

1 comment on commit f7f23c4

@vercel
Copy link

@vercel vercel bot commented on f7f23c4 Oct 19, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.