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

chore(solver/app): approve outbox spend in fulfil #2572

Merged
merged 2 commits into from
Dec 2, 2024
Merged
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
1 change: 1 addition & 0 deletions contracts/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ install-deps: check-pnpm-version ## Install dependencies.
build: version ## Build contracts.
forge build --force --root core
forge build --force --root avs
forge build --force --root solve


.PHONY: all
Expand Down
8 changes: 8 additions & 0 deletions e2e/app/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"github.com/omni-network/omni/e2e/netman"
"github.com/omni-network/omni/e2e/netman/pingpong"
"github.com/omni-network/omni/e2e/solve"
"github.com/omni-network/omni/e2e/solve/devapp"
"github.com/omni-network/omni/e2e/types"
"github.com/omni-network/omni/halo/genutil/evm/predeploys"
"github.com/omni-network/omni/lib/contracts"
Expand Down Expand Up @@ -171,6 +172,13 @@ func E2ETest(ctx context.Context, def Definition, cfg E2ETestConfig) error {
return err
}

if def.Manifest.DeploySolve {
// TODO(corver): Remove this
if err := devapp.TestFlow(ctx, NetworkFromDef(def), ExternalEndpoints(def)); err != nil {
return err
}
}

var eg errgroup.Group
eg.Go(func() error { return testGasPumps(ctx, def) })
eg.Go(func() error { return testBridge(ctx, def) })
Expand Down
6 changes: 5 additions & 1 deletion e2e/solve/deploy.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,11 @@ func DeployContracts(ctx context.Context, network netconf.Network, backends ethb
var eg errgroup.Group

eg.Go(func() error {
return deployBoxes(ctx, network, backends)
if err := deployBoxes(ctx, network, backends); err != nil {
return errors.Wrap(err, "deploy boxes")
}

return devapp.AllowOutboxCalls(ctx, network, backends)
})
eg.Go(func() error {
return devapp.Deploy(ctx, network, backends)
Expand Down
112 changes: 94 additions & 18 deletions e2e/solve/devapp/deploy.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (

"github.com/omni-network/omni/contracts/bindings"
"github.com/omni-network/omni/e2e/app/eoa"
"github.com/omni-network/omni/lib/cast"
"github.com/omni-network/omni/lib/contracts"
"github.com/omni-network/omni/lib/create3"
"github.com/omni-network/omni/lib/errors"
Expand All @@ -13,6 +14,9 @@ import (
"github.com/omni-network/omni/lib/netconf"

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/params"

"cosmossdk.io/math"
)

const (
Expand All @@ -21,47 +25,119 @@ const (
l2TokenSalt = "l2-token"
)

var (
create3Factory = contracts.Create3Factory(netconf.Devnet)
deployer = eoa.MustAddress(netconf.Devnet, eoa.RoleDeployer)
)

// Deploy deploys the mock tokens and vaults to devnet.
func Deploy(ctx context.Context, network netconf.Network, backends ethbackend.Backends) error {
if network.ID != netconf.Devnet {
return errors.New("onl devnet")
}

mockl1, ok := network.Chain(evmchain.IDMockL1)
if !ok {
return errors.New("no mock l1")
l1Backend, err := backends.Backend(static.L1.ChainID)
if err != nil {
return errors.Wrap(err, "backend mock l1")
}

l2Backend, err := backends.Backend(static.L2.ChainID)
if err != nil {
return errors.Wrap(err, "backend mock l2")
}

if err := deployToken(ctx, l1Backend, l1TokenSalt); err != nil {
return errors.Wrap(err, "deploy l1 token")
}

if err := deployVault(ctx, l1Backend, l1VaultSalt, static.L1Token); err != nil {
return errors.Wrap(err, "deploy vault")
}

if err := deployToken(ctx, l2Backend, l2TokenSalt); err != nil {
return errors.Wrap(err, "deploy l2 token")
}

if err := fundSolver(ctx, l1Backend, static.L1Token); err != nil {
return errors.Wrap(err, "fund solver")
}

return nil
}

func fundSolver(ctx context.Context, backend *ethbackend.Backend, tokenAddr common.Address) error {
mngr := eoa.MustAddress(netconf.Devnet, eoa.RoleManager) // we use mngr to mint, but this doesn't matter. could be any dev addr
slvr := eoa.MustAddress(netconf.Devnet, eoa.RoleSolver)

token, err := bindings.NewMockToken(tokenAddr, backend)
if err != nil {
return errors.Wrap(err, "new mock token")
}

txOpts, err := backend.BindOpts(ctx, mngr)
if err != nil {
return errors.Wrap(err, "bind opts")
}

mockl2, ok := network.Chain(evmchain.IDMockL2)
eth1m := math.NewInt(1_000_000).MulRaw(params.Ether).BigInt()
tx, err := token.Mint(txOpts, slvr, eth1m)
if err != nil {
return errors.Wrap(err, "mint")
}

_, err = backend.WaitMined(ctx, tx)
if err != nil {
return errors.Wrap(err, "wait mined")
}

return nil
}

// AllowOutboxCalls allows the outbox to call the L1 vault deposit method.
func AllowOutboxCalls(ctx context.Context, network netconf.Network, backends ethbackend.Backends) error {
if network.ID != netconf.Devnet {
return errors.New("onl devnet")
}

addrs, err := contracts.GetAddresses(ctx, network.ID)
if err != nil {
return errors.Wrap(err, "get addresses")
}

mockl1, ok := network.Chain(evmchain.IDMockL1)
if !ok {
return errors.New("no mock l2")
return errors.New("no mock l1")
}

mockl1Backend, err := backends.Backend(mockl1.ID)
if err != nil {
return errors.Wrap(err, "backend mock l1")
}

mockl2Backend, err := backends.Backend(mockl2.ID)
if err := allowCalls(ctx, mockl1Backend, addrs.SolveOutbox); err != nil {
return errors.Wrap(err, "allow calls")
}

return nil
}

// allowCalls allows the outbox to call the L1 vault deposit method.
func allowCalls(ctx context.Context, backend *ethbackend.Backend, outboxAddr common.Address) error {
outbox, err := bindings.NewSolveOutbox(outboxAddr, backend)
if err != nil {
return errors.Wrap(err, "backend mock l2")
return errors.Wrap(err, "new solve outbox")
}

if err := deployToken(ctx, mockl1Backend, l1TokenSalt); err != nil {
return errors.Wrap(err, "deploy l1 token")
txOpts, err := backend.BindOpts(ctx, manager)
if err != nil {
return errors.Wrap(err, "bind opts")
}

if err := deployVault(ctx, mockl1Backend, l1VaultSalt, static.L1Token); err != nil {
return errors.Wrap(err, "deploy vault")
vaultDepositID, err := cast.Array4(vaultDeposit.ID[:4])
if err != nil {
return err
}

if err := deployToken(ctx, mockl2Backend, l2TokenSalt); err != nil {
return errors.Wrap(err, "deploy l2 token")
tx, err := outbox.SetAllowedCall(txOpts, static.L1Vault, vaultDepositID, true)
if err != nil {
return errors.Wrap(err, "set allowed call")
} else if _, err := backend.WaitMined(ctx, tx); err != nil {
return errors.Wrap(err, "wait mined")
}

return nil
Expand Down
120 changes: 116 additions & 4 deletions e2e/solve/devapp/deposit.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,16 @@ package devapp
import (
"context"
"math/big"
"time"

"github.com/omni-network/omni/contracts/bindings"
"github.com/omni-network/omni/lib/anvil"
"github.com/omni-network/omni/lib/contracts"
"github.com/omni-network/omni/lib/errors"
"github.com/omni-network/omni/lib/ethclient/ethbackend"
"github.com/omni-network/omni/lib/log"
"github.com/omni-network/omni/lib/netconf"
"github.com/omni-network/omni/lib/xchain"

"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
Expand Down Expand Up @@ -78,7 +81,107 @@ func IsDeposited(ctx context.Context, backends ethbackend.Backends, req DepositR

// assumes balance(onBehalfOf) was zero before deposit request
// assumes one deposit per test case onBehalfOf addr
return balance.Cmp(req.Deposit.Amount) != 0, nil
return balance.Cmp(req.Deposit.Amount) == 0, nil
}

// TestFlow submits deposit requests to the solve inbox and waits for them to be processed.
func TestFlow(ctx context.Context, network netconf.Network, endpoints xchain.RPCEndpoints) error {
backends, err := ethbackend.BackendsFromNetwork(network, endpoints)
if err != nil {
return err
}

deposits, err := RequestDeposits(ctx, backends)
if err != nil {
return err
}

timeout, cancel := context.WithTimeout(ctx, time.Minute)
defer cancel()

// Wait for all deposits to be completed on dest chain by solver/outbox
toCheck := toSet(deposits)
for {
if timeout.Err() != nil {
return errors.New("timeout waiting for deposits")
}

for deposit := range toCheck {
ok, err := IsDeposited(ctx, backends, deposit)
if err != nil {
return err
} else if ok {
log.Debug(ctx, "Deposit complete", "remaining", len(toCheck)-1)
delete(toCheck, deposit)
}
}

if len(toCheck) == 0 {
break
}

time.Sleep(time.Second)
}

log.Debug(ctx, "All deposits fulfilled")

// Wait for requests to be claimed by solver
toCheck = toSet(deposits)
for {
if timeout.Err() != nil {
return errors.New("timeout waiting for claims")
}

const statusClaimed = 6

for deposit := range toCheck {
status, err := GetDepositStatus(ctx, backends, deposit)
if err != nil {
return err
} else if status == statusClaimed {
log.Debug(ctx, "Deposit claimed", "remaining", len(toCheck)-1)
delete(toCheck, deposit)
}
}

if len(toCheck) == 0 {
break
}

time.Sleep(time.Second)
}

log.Debug(ctx, "All deposits claimed")

return nil
}

func GetDepositStatus(ctx context.Context, backends ethbackend.Backends, deposit DepositReq) (uint8, error) {
app := GetApp()

backend, err := backends.Backend(app.L2.ChainID)
if err != nil {
return 0, errors.Wrap(err, "backend")
}

addrs, err := contracts.GetAddresses(ctx, netconf.Devnet)
if err != nil {
return 0, errors.Wrap(err, "get addresses")
}

inbox, err := bindings.NewSolveInbox(addrs.SolveInbox, backend)
if err != nil {
return 0, errors.Wrap(err, "new mock vault")
}

callOpts := &bind.CallOpts{Context: ctx}

req, err := inbox.GetRequest(callOpts, deposit.ID)
if err != nil {
return 0, errors.Wrap(err, "get balance")
}

return req.Status, nil
}

// addRandomDepositors adds n random depositors privkeys to the backend.
Expand Down Expand Up @@ -224,10 +327,19 @@ func parseReqID(inbox bindings.SolveInboxFilterer, logs []*types.Log) ([32]byte,
}

func packDeposit(args DepositArgs) ([]byte, error) {
data, err := vaultDeposit.Inputs.Pack(args.OnBehalfOf, args.Amount)
calldata, err := vaultABI.Pack("deposit", args.OnBehalfOf, args.Amount)
if err != nil {
return nil, errors.Wrap(err, "pack data")
return nil, errors.Wrap(err, "pack deposit call data")
}

return calldata, nil
}

func toSet[T comparable](slice []T) map[T]bool {
set := make(map[T]bool)
for _, v := range slice {
set[v] = true
}

return data, nil
return set
}
27 changes: 27 additions & 0 deletions e2e/solve/devapp/deposit_internal_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package devapp

import (
"math/big"
"testing"

"github.com/ethereum/go-ethereum/common"

"github.com/stretchr/testify/require"
)

func TestPackUnpack(t *testing.T) {
t.Parallel()

dep := DepositArgs{
OnBehalfOf: common.Address{},
Amount: big.NewInt(1),
}

packed, err := packDeposit(dep)
require.NoError(t, err)

dep2, err := unpackDeposit(packed)
require.NoError(t, err)

require.Equal(t, dep, dep2)
}
Loading
Loading