Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

init #1

Closed
wants to merge 17 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
41 changes: 41 additions & 0 deletions .github/workflows/build.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
name: Build

on:
push:
# branches: [ main ]
# pull_request:
# branches: [ main ]

jobs:

'build-go':
name: make build-go
runs-on: ubuntu-latest
steps:

- name: Set up Go 1.x
uses: actions/setup-go@v2
with:
go-version: ^1.21

- name: Check out
uses: actions/checkout@v3

- name: Make build-go
run: make build-go

'build-test-solidity':
name: make build-solidity
runs-on: ubuntu-latest
steps:

- name: Check out
uses: actions/checkout@v3
with:
submodules: recursive

- name: Install Foundry
uses: foundry-rs/foundry-toolchain@v1

- name: Make build-solidity
run: cd contracts && forge build && forge test
57 changes: 57 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
.DS_Store
node_modules
results
temp
.nyc_output
coverage.json
*.tsbuildinfo
**/lcov.info

yarn-error.log
.yarn/*
!.yarn/releases
!.yarn/plugins
.pnp.*

dist
artifacts
cache

packages/contracts-bedrock/deployments/devnetL1
packages/contracts-bedrock/deployments/anvil

# vim
*.sw*

# jetbrains
.idea/

.secrets
.env
.env*
!.env.example
*.log

.devnet

# Ignore local fuzzing results
**/testdata/fuzz/

coverage.out

# Ignore bedrock go bindings local output files
op-bindings/bin
op-exporter


__pycache__

# Ignore echidna artifacts
crytic-export

# Ignore building artifacts
build/
bot

# Ignore the configuration files
bot.toml
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[submodule "contracts/lib/openzeppelin-contracts"]
path = contracts/lib/openzeppelin-contracts
url = https://github.com/OpenZeppelin/openzeppelin-contracts
28 changes: 28 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
FROM --platform=$BUILDPLATFORM golang:1.21.1-alpine3.18 as builder

RUN apk add --no-cache make ca-certificates gcc musl-dev linux-headers git jq bash

COPY ./go.mod /app/go.mod
COPY ./go.sum /app/go.sum

WORKDIR /app

RUN go mod download

COPY ./core /app/core
COPY ./cmd /app/cmd
COPY ./Makefile /app/Makefile
COPY ./bot.toml /app/bot.toml

WORKDIR /app/

RUN make build-go

FROM alpine:3.18

COPY --from=builder /app/bot /usr/local/bin
COPY --from=builder /app/bot.toml /app/bot.toml

WORKDIR /app

CMD ["bot", "run", "--config", "/app/bot.toml"]
19 changes: 19 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
GITCOMMIT := $(shell git rev-parse HEAD)
GITDATE := $(shell git show -s --format='%ct')

LDFLAGSSTRING +=-X main.GitCommit=$(GITCOMMIT)
LDFLAGSSTRING +=-X main.GitDate=$(GITDATE)
LDFLAGS := -ldflags "$(LDFLAGSSTRING)"

build-go:
env GO111MODULE=on go build -v $(LDFLAGS) ./cmd/bot

build-solidity:
pushd contracts; \
forge build; \
popd;

.PHONY: \
bot \
build-go \
build-solidity
102 changes: 102 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
# opbnb-bridge-bot

## Description

The opbnb-bridge-bot project primarily maintains a Layer2 contract named `L2StandardBridgeBot`. This contract, when called, initiates withdrawal transactions and collects a fixed fee for every withdrawals. The project promises that after the withdrawal transaction has can be proven and finalized after the required time window, a third-party account would complete the corresponding L1 proven withdrawal transactions and L1 finalized withdrawal transactions, thus completing the entire withdrawal process.

## Motivation

![image](./assets/optimism-withdraw-flow.png)

A withdrawal request must be completed in three steps:

1. Send a L2 initiating transaction
2. Send the L1 proven transaction after the proposer submits the next L2 output root
3. Send L1 finalized transaction after the challenge window has passed

Completing these three steps might not be a good user experience. Firstly, users need to send 3 transactions; secondly, they need to wait 2 periods before sending the next transaction.

### See also

- opBNB testnet bridge: https://opbnb-testnet-bridge.bnbchain.org

- withdrawal example: https://testnet.opbnbscan.com/tx/0xadb6b8d8bffb4dc7177ef1e27e202035f0861a71521c3cdff66a4aeb4464e501

## Design Principle and Working Mechanism

This project consists of an on-chain contract [`contracts/src/L2StandardBridgeBot.sol`](contracts/src/L2StandardBridgeBot.sol) and [an off-chain bot](./cmd/bot/run.go#L67-L68).

The `L2StandardBridgeBot` contract provides a `withdrawTo` function, which charges a fixed fee for every execution and then forwards the call to the `L2StandardBridge.withdraw`.

The off-chain bot watches the `L2StandardBridgeBot.WithdrawTo` events and based on these events, re-constructs the corresponding withdrawals. We name these withdrawals as **bot-delegated withdrawals**. As time go out of the bot-delegated withdrawal's proven and finalized time window, our bot will send proven and finalized transactions to complete the entire withdrawal process.

references
- contracts
- [L2StandardBridge.sol](https://github.com/bnb-chain/opbnb/blob/v0.2.2/packages/contracts-bedrock/contracts/L2/L2StandardBridge.sol#L105-L129) which concludes the `withdrawTo` function.
- opBNB Mainnet [address](https://opbnbscan.com/address/0x4200000000000000000000000000000000000010).
- opBNB Testnet [address](https://testnet.opbnbscan.com/address/0x4200000000000000000000000000000000000010)
- [OptimismPortal.sol](https://github.com/bnb-chain/opbnb/blob/v0.2.2/packages/contracts-bedrock/contracts/L1/OptimismPortal.sol) which concludes the `proveWithdrawalTransaction` and `finalizeWithdrawalTransaction` functions.
- BSC Mainnet [address](https://bscscan.com/address/0x1876EA7702C0ad0C6A2ae6036DE7733edfBca519).
- BSC Testnet [address](https://testnet.bscscan.com/address/0x4386c8abf2009ac0c263462da568dd9d46e52a31)
- [opbnb bridge](https://opbnb-bridge.bnbchain.org)
- [tutorial](https://github.com/ethereum-optimism/optimism-tutorial/blob/main/cross-dom-bridge-erc20/README.md) of interacting with bridge with js-sdk.

## User Guide

### Getting Started at opBNB testnet

1. Prepare a PostgreSQL database

```
docker-compose up -d
```

2. Compile the off-chain bot and output the artifact to `./bot`

```
make build-go
```

3. Run the off-chain bot

```
OPBNB_BRIDGE_BOT_PRIVKEY=<bot privkey> ./bot --config ./bot.toml
```

### Deploy and Use Contracts

1. Compile the contract using `forge`

```
make build-solidity
```

2. Deploy contract

```
cd contracts

export DELEGATE_FEE=1000000000000000
forge create \
--rpc-url $OPBNB_TESTNET \
--private-key $OP_DEPLOYER_PRIVKEY \
src/L2StandardBridgeBot.sol:L2StandardBridgeBot --constructor-args $OP_DEPLOYER_ADDRESS $DELEGATE_FEE
```

3. Withdraw via the deployed contract

```
export DELEGATE_FEE=1000000000000000
export amount=2000000000000001
export contract_addr=<deployed contract address>

cast send --rpc-url $OPBNB_TESTNET \
--private-key $OP_DEPLOYER_PRIVKEY \
--value $(($DELEGATE_FEE + $amount)) \
$contract_addr \
$(cast calldata 'withdrawTo( address _l2Token, address _to, uint256 _amount, uint32 _minGasLimit, bytes calldata _extraData)' 0xDeadDeAddeAddEAddeadDEaDDEAdDeaDDeAD0000 $OP_DEPLOYER_ADDRESS $amount 150469 "")
```

## License

MIT
Binary file added assets/optimism-withdraw-flow.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
25 changes: 25 additions & 0 deletions bot.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
[rpcs]
l1-rpc =
l2-rpc =

[db]
host = "0.0.0.0"
port = 5434
user = "db_username"
password = "db_password"
name = "db_name"

[l1-contracts]
address-manager = "0x1111111111111111111111111111111111111111"
Copy link
Collaborator

Choose a reason for hiding this comment

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

It's determined for both testnet and mainnet.

  1. Remove unnecessary configurations.
  2. List both testnet and mainnet configurations here. Use testnet as the default and comment out the mainnet configuration.

system-config = "0x406ac857817708eaf4ca3a82317ef4ae3d1ea23b"
optimism-portal = "0x4386c8abf2009ac0c263462da568dd9d46e52a31"
l2-output-oracle = "0xff2394bb843012562f4349c6632a0ecb92fc8810"
l1-cross-domain-messenger = "0xd506952e78eecd5d4424b1990a0c99b1568e7c2c"
l1-standard-bridge = "0x1111111111111111111111111111111111111111"
# l1-erc721-bridge = "0x17e1454015bfb3377c75be7b6d47b236fd2ddbe7"
l1-erc721-bridge = "0x1111111111111111111111111111111111111111"

[misc]
l2-standard-bridge-bot = "0x4c3171982cd7f62690f4d6e086b91f434b97332f"
propose-time-window = 60
challenge-time-window = 60
71 changes: 71 additions & 0 deletions cmd/bot/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package main

import (
"context"
"os"

oplog "github.com/ethereum-optimism/optimism/op-service/log"
"github.com/ethereum-optimism/optimism/op-service/opio"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params"
"github.com/urfave/cli/v2"
)

var (
ConfigFlag = &cli.StringFlag{
Name: "config",
Value: "./bot.toml",
Aliases: []string{"c"},
Usage: "path to config file",
EnvVars: []string{"BOT_CONFIG"},
}
)

var (
GitCommit = ""
GitDate = ""
)

func main() {
// This is the most root context, used to propagate
// cancellations to all spawned application-level goroutines
ctx, cancel := context.WithCancel(context.Background())
go func() {
opio.BlockOnInterrupts()
cancel()
}()

oplog.SetupDefaults()
app := newCli(GitCommit, GitDate)
if err := app.RunContext(ctx, os.Args); err != nil {
log.Error("application failed", "err", err)
os.Exit(1)
}
}

func newCli(GitCommit string, GitDate string) *cli.App {
flags := []cli.Flag{ConfigFlag}
flags = append(flags, oplog.CLIFlags("OPBNB_BRIDGE_BOT")...)
return &cli.App{
Name: "opbnb-bridge-bot",
Version: params.VersionWithCommit(GitCommit, GitDate),
Description: "opbnb-bridge-bot",
EnableBashCompletion: true,
Commands: []*cli.Command{
{
Name: "run",
Flags: flags,
Description: "Runs the indexing service",
Action: runCommand,
},
{
Name: "version",
Description: "print version",
Action: func(ctx *cli.Context) error {
cli.ShowVersion(ctx)
return nil
},
},
},
}
}
Loading
Loading