Skip to content

Commit aa77c59

Browse files
authored
feat(op-acceptance-tests): base; deposit flow (#15979)
* feat(op-acceptance-tests): base; deposit flow * feat(op-acceptance-tests): do not expose private key * feat(op-acceptance-tests): unused finality check
1 parent 18594ce commit aa77c59

File tree

7 files changed

+128
-11
lines changed

7 files changed

+128
-11
lines changed
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
package deposit
2+
3+
import (
4+
"math/big"
5+
"testing"
6+
"time"
7+
8+
"github.com/stretchr/testify/require"
9+
10+
"github.com/ethereum-optimism/optimism/op-devstack/devtest"
11+
"github.com/ethereum-optimism/optimism/op-devstack/presets"
12+
"github.com/ethereum-optimism/optimism/op-service/eth"
13+
"github.com/ethereum-optimism/optimism/op-service/txplan"
14+
supervisorTypes "github.com/ethereum-optimism/optimism/op-supervisor/supervisor/types"
15+
"github.com/lmittmann/w3"
16+
)
17+
18+
func TestMain(m *testing.M) {
19+
presets.DoMain(m, presets.WithMinimal())
20+
}
21+
22+
func TestL1ToL2Deposit(gt *testing.T) {
23+
// Create a test environment using op-devstack
24+
t := devtest.SerialT(gt)
25+
sys := presets.NewMinimal(t)
26+
27+
// Wait for L1 node to be responsive
28+
sys.L1Network.WaitForOnline()
29+
30+
// Fund Alice on L1
31+
fundingAmount := eth.ThousandEther
32+
alice := sys.FunderL1.NewFundedEOA(fundingAmount)
33+
alice.VerifyBalanceExact(fundingAmount)
34+
35+
alicel2 := alice.AsEL(sys.L2EL)
36+
37+
// Get the optimism portal address
38+
rollupConfig := sys.L2Chain.Escape().RollupConfig()
39+
portalAddr := rollupConfig.DepositContractAddress
40+
41+
depositAmount := eth.OneEther
42+
43+
// Define the deposit function and encode arguments
44+
// TODO: Redo this when the new DSL (#16079) is merged
45+
funcDeposit := w3.MustNewFunc(`depositTransaction(address,uint256,uint64,bool,bytes)`, "")
46+
args, err := funcDeposit.EncodeArgs(
47+
alice.Address(), // _to
48+
depositAmount.ToBig(), // _value
49+
uint64(300_000), // _gasLimit
50+
false, // _isCreation
51+
[]byte{}, // _data
52+
)
53+
require.NoError(t, err)
54+
55+
// Create and confirm the transaction (awaits tx inclusion and checks success status)
56+
tx := alice.Transact(
57+
alice.Plan(),
58+
txplan.WithGasLimit(500_000),
59+
txplan.WithTo(&portalAddr),
60+
txplan.WithData(args),
61+
txplan.WithValue(depositAmount.ToBig()))
62+
63+
receipt := tx.Included.Value()
64+
gasPrice := receipt.EffectiveGasPrice // bugfix: use the exact price that was charged
65+
66+
// Verify the deposit was successful
67+
gasCost := new(big.Int).Mul(new(big.Int).SetUint64(receipt.GasUsed), gasPrice)
68+
expectedFinalL1 := new(big.Int).Sub(fundingAmount.ToBig(), depositAmount.ToBig())
69+
expectedFinalL1.Sub(expectedFinalL1, gasCost)
70+
71+
alice.VerifyBalanceExact(eth.WeiBig(expectedFinalL1))
72+
73+
// Wait for the sequencer to process the deposit
74+
t.Require().Eventually(func() bool {
75+
head := sys.L2CL.HeadBlockRef(supervisorTypes.LocalUnsafe)
76+
return head.L1Origin.Number >= receipt.BlockNumber.Uint64()
77+
}, time.Second*10, time.Second, "awaiting deposit to be processed by L2")
78+
alicel2.VerifyBalanceExact(depositAmount)
79+
}

op-acceptance-tests/tests/base/init_test.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,4 @@ import (
99
// TestMain creates the test-setups against the shared backend
1010
func TestMain(m *testing.M) {
1111
presets.DoMain(m, presets.WithMinimal())
12-
1312
}

op-devstack/dsl/el.go

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,26 +33,46 @@ func (el *elNode) ChainID() eth.ChainID {
3333
}
3434

3535
func (el *elNode) WaitForBlock() eth.BlockRef {
36+
return el.waitForNextBlock(1)
37+
}
38+
39+
func (el *elNode) WaitForOnline() {
40+
el.require.Eventually(func() bool {
41+
el.log.Info("Waiting for online")
42+
_, err := el.inner.EthClient().InfoByLabel(el.ctx, eth.Unsafe)
43+
return err == nil
44+
}, 10*time.Second, 500*time.Millisecond, "Expected to be online")
45+
}
46+
47+
// waitForNextBlockWithTimeout waits until the specified block number is present
48+
func (el *elNode) waitForNextBlock(blocksFromNow uint64) eth.BlockRef {
3649
initial, err := el.inner.EthClient().InfoByLabel(el.ctx, eth.Unsafe)
3750
el.require.NoError(err, "Expected to get latest block from execution client")
51+
targetBlock := initial.NumberU64() + blocksFromNow
3852
initialRef := eth.InfoToL1BlockRef(initial)
3953
var newRef eth.BlockRef
54+
4055
err = wait.For(el.ctx, 500*time.Millisecond, func() (bool, error) {
4156
newBlock, err := el.inner.EthClient().InfoByLabel(el.ctx, eth.Unsafe)
4257
if err != nil {
4358
return false, err
4459
}
4560

4661
newRef = eth.InfoToL1BlockRef(newBlock)
62+
if newBlock.NumberU64() >= targetBlock {
63+
el.log.Info("Target block reached", "block", newRef)
64+
return true, nil
65+
}
66+
4767
if initialRef == newRef {
4868
el.log.Info("Still same block detected as initial", "block", initialRef)
4969
return false, nil
70+
} else {
71+
el.log.Info("New block detected", "new_block", newRef, "prev_block", initialRef)
5072
}
51-
52-
el.log.Info("New block detected", "new_block", newRef, "prev_block", initialRef)
53-
return true, nil
73+
return false, nil
5474
})
55-
el.require.NoError(err, "Expected to get latest block from execution client for comparison")
75+
el.require.NoError(err, "Expected to reach target block")
5676
return newRef
5777
}
5878

op-devstack/dsl/eoa.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@ func NewEOA(key *Key, el ELNode) *EOA {
3636
}
3737
}
3838

39+
func (u *EOA) AsEL(el ELNode) *EOA {
40+
return NewEOA(u.key, el)
41+
}
42+
3943
func (u *EOA) String() string {
4044
return fmt.Sprintf("EOA(%s @ %s)", u.key.Address(), u.el.ChainID())
4145
}

op-devstack/dsl/l1_network.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,3 +59,7 @@ func (n *L1Network) PrintChain() {
5959
n.log.Info("Printing block hashes and parent hashes", "network", n.String(), "chain", n.ChainID())
6060
spew.Dump(entries)
6161
}
62+
63+
func (n *L1Network) WaitForOnline() {
64+
NewL1ELNode(n.inner.L1ELNode(match.FirstL1EL)).WaitForOnline()
65+
}

op-devstack/presets/interop.go

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,13 @@ type SimpleInterop struct {
4040

4141
Wallet *dsl.HDWallet
4242

43-
FaucetA *dsl.Faucet
44-
FaucetB *dsl.Faucet
43+
FaucetA *dsl.Faucet
44+
FaucetB *dsl.Faucet
45+
FaucetL1 *dsl.Faucet
4546

46-
FunderA *dsl.Funder
47-
FunderB *dsl.Funder
47+
FunderL1 *dsl.Funder
48+
FunderA *dsl.Funder
49+
FunderB *dsl.Funder
4850
}
4951

5052
func (s *SimpleInterop) L2Networks() []*dsl.L2Network {
@@ -94,6 +96,8 @@ func NewSimpleInterop(t devtest.T) *SimpleInterop {
9496
L2BatcherA: dsl.NewL2Batcher(l2A.L2Batcher(match.Assume(t, match.FirstL2Batcher))),
9597
L2BatcherB: dsl.NewL2Batcher(l2B.L2Batcher(match.Assume(t, match.FirstL2Batcher))),
9698
}
99+
out.FaucetL1 = dsl.NewFaucet(out.L1Network.Escape().Faucet(match.Assume(t, match.FirstFaucet)))
100+
out.FunderL1 = dsl.NewFunder(out.Wallet, out.FaucetL1, out.L1EL)
97101
out.FunderA = dsl.NewFunder(out.Wallet, out.FaucetA, out.L2ELA)
98102
out.FunderB = dsl.NewFunder(out.Wallet, out.FaucetB, out.L2ELB)
99103
return out

op-devstack/presets/minimal.go

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ type Minimal struct {
1818
ControlPlane stack.ControlPlane
1919

2020
L1Network *dsl.L1Network
21+
L1EL *dsl.L1ELNode
2122

2223
L2Chain *dsl.L2Network
2324
L2Batcher *dsl.L2Batcher
@@ -28,8 +29,10 @@ type Minimal struct {
2829

2930
Wallet *dsl.HDWallet
3031

31-
Faucet *dsl.Faucet
32-
Funder *dsl.Funder
32+
FaucetL1 *dsl.Faucet
33+
Faucet *dsl.Faucet
34+
FunderL1 *dsl.Funder
35+
Funder *dsl.Funder
3336
}
3437

3538
func (m *Minimal) L2Networks() []*dsl.L2Network {
@@ -49,12 +52,14 @@ func NewMinimal(t devtest.T) *Minimal {
4952

5053
t.Gate().Equal(len(system.TestSequencers()), 1, "expected exactly one test sequencer")
5154

55+
l1Net := system.L1Network(match.FirstL1Network)
5256
l2 := system.L2Network(match.Assume(t, match.L2ChainA))
5357
out := &Minimal{
5458
Log: t.Logger(),
5559
T: t,
5660
ControlPlane: orch.ControlPlane(),
5761
L1Network: dsl.NewL1Network(system.L1Network(match.FirstL1Network)),
62+
L1EL: dsl.NewL1ELNode(l1Net.L1ELNode(match.Assume(t, match.FirstL1EL))),
5863
L2Chain: dsl.NewL2Network(l2),
5964
L2Batcher: dsl.NewL2Batcher(l2.L2Batcher(match.Assume(t, match.FirstL2Batcher))),
6065
L2EL: dsl.NewL2ELNode(l2.L2ELNode(match.Assume(t, match.FirstL2EL))),
@@ -63,6 +68,8 @@ func NewMinimal(t devtest.T) *Minimal {
6368
Wallet: dsl.NewHDWallet(t, devkeys.TestMnemonic, 30),
6469
Faucet: dsl.NewFaucet(l2.Faucet(match.Assume(t, match.FirstFaucet))),
6570
}
71+
out.FaucetL1 = dsl.NewFaucet(out.L1Network.Escape().Faucet(match.Assume(t, match.FirstFaucet)))
72+
out.FunderL1 = dsl.NewFunder(out.Wallet, out.FaucetL1, out.L1EL)
6673
out.Funder = dsl.NewFunder(out.Wallet, out.Faucet, out.L2EL)
6774
return out
6875
}

0 commit comments

Comments
 (0)