Commit 5279572c authored by mergify[bot]'s avatar mergify[bot] Committed by GitHub

Merge branch 'develop' into 08-03-bridge_transaction/transfer_schema_models

parents d9ed92d7 86914a57
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -9,7 +9,7 @@ import (
"github.com/ethereum-optimism/optimism/op-bindings/solc"
)
const StandardBridgeStorageLayoutJSON = "{\"storage\":[{\"astId\":1000,\"contract\":\"src/universal/StandardBridge.sol:StandardBridge\",\"label\":\"spacer_0_0_20\",\"offset\":0,\"slot\":\"0\",\"type\":\"t_address\"},{\"astId\":1001,\"contract\":\"src/universal/StandardBridge.sol:StandardBridge\",\"label\":\"spacer_1_0_20\",\"offset\":0,\"slot\":\"1\",\"type\":\"t_address\"},{\"astId\":1002,\"contract\":\"src/universal/StandardBridge.sol:StandardBridge\",\"label\":\"deposits\",\"offset\":0,\"slot\":\"2\",\"type\":\"t_mapping(t_address,t_mapping(t_address,t_uint256))\"},{\"astId\":1003,\"contract\":\"src/universal/StandardBridge.sol:StandardBridge\",\"label\":\"__gap\",\"offset\":0,\"slot\":\"3\",\"type\":\"t_array(t_uint256)47_storage\"}],\"types\":{\"t_address\":{\"encoding\":\"inplace\",\"label\":\"address\",\"numberOfBytes\":\"20\"},\"t_array(t_uint256)47_storage\":{\"encoding\":\"inplace\",\"label\":\"uint256[47]\",\"numberOfBytes\":\"1504\",\"base\":\"t_uint256\"},\"t_mapping(t_address,t_mapping(t_address,t_uint256))\":{\"encoding\":\"mapping\",\"label\":\"mapping(address =\u003e mapping(address =\u003e uint256))\",\"numberOfBytes\":\"32\",\"key\":\"t_address\",\"value\":\"t_mapping(t_address,t_uint256)\"},\"t_mapping(t_address,t_uint256)\":{\"encoding\":\"mapping\",\"label\":\"mapping(address =\u003e uint256)\",\"numberOfBytes\":\"32\",\"key\":\"t_address\",\"value\":\"t_uint256\"},\"t_uint256\":{\"encoding\":\"inplace\",\"label\":\"uint256\",\"numberOfBytes\":\"32\"}}}"
const StandardBridgeStorageLayoutJSON = "{\"storage\":[{\"astId\":1000,\"contract\":\"src/universal/StandardBridge.sol:StandardBridge\",\"label\":\"_initialized\",\"offset\":0,\"slot\":\"0\",\"type\":\"t_uint8\"},{\"astId\":1001,\"contract\":\"src/universal/StandardBridge.sol:StandardBridge\",\"label\":\"_initializing\",\"offset\":1,\"slot\":\"0\",\"type\":\"t_bool\"},{\"astId\":1002,\"contract\":\"src/universal/StandardBridge.sol:StandardBridge\",\"label\":\"spacer_0_2_20\",\"offset\":2,\"slot\":\"0\",\"type\":\"t_address\"},{\"astId\":1003,\"contract\":\"src/universal/StandardBridge.sol:StandardBridge\",\"label\":\"spacer_1_0_20\",\"offset\":0,\"slot\":\"1\",\"type\":\"t_address\"},{\"astId\":1004,\"contract\":\"src/universal/StandardBridge.sol:StandardBridge\",\"label\":\"deposits\",\"offset\":0,\"slot\":\"2\",\"type\":\"t_mapping(t_address,t_mapping(t_address,t_uint256))\"},{\"astId\":1005,\"contract\":\"src/universal/StandardBridge.sol:StandardBridge\",\"label\":\"messenger\",\"offset\":0,\"slot\":\"3\",\"type\":\"t_contract(CrossDomainMessenger)1007\"},{\"astId\":1006,\"contract\":\"src/universal/StandardBridge.sol:StandardBridge\",\"label\":\"__gap\",\"offset\":0,\"slot\":\"4\",\"type\":\"t_array(t_uint256)46_storage\"}],\"types\":{\"t_address\":{\"encoding\":\"inplace\",\"label\":\"address\",\"numberOfBytes\":\"20\"},\"t_array(t_uint256)46_storage\":{\"encoding\":\"inplace\",\"label\":\"uint256[46]\",\"numberOfBytes\":\"1472\",\"base\":\"t_uint256\"},\"t_bool\":{\"encoding\":\"inplace\",\"label\":\"bool\",\"numberOfBytes\":\"1\"},\"t_contract(CrossDomainMessenger)1007\":{\"encoding\":\"inplace\",\"label\":\"contract CrossDomainMessenger\",\"numberOfBytes\":\"20\"},\"t_mapping(t_address,t_mapping(t_address,t_uint256))\":{\"encoding\":\"mapping\",\"label\":\"mapping(address =\u003e mapping(address =\u003e uint256))\",\"numberOfBytes\":\"32\",\"key\":\"t_address\",\"value\":\"t_mapping(t_address,t_uint256)\"},\"t_mapping(t_address,t_uint256)\":{\"encoding\":\"mapping\",\"label\":\"mapping(address =\u003e uint256)\",\"numberOfBytes\":\"32\",\"key\":\"t_address\",\"value\":\"t_uint256\"},\"t_uint256\":{\"encoding\":\"inplace\",\"label\":\"uint256\",\"numberOfBytes\":\"32\"},\"t_uint8\":{\"encoding\":\"inplace\",\"label\":\"uint8\",\"numberOfBytes\":\"1\"}}}"
var StandardBridgeStorageLayout = new(solc.StorageLayout)
......
......@@ -64,6 +64,15 @@ func (s *StorageLayout) GetStorageLayoutEntry(name string) (StorageLayoutEntry,
return StorageLayoutEntry{}, fmt.Errorf("%s not found", name)
}
// GetStorageLayoutType returns the StorageLayoutType where the label matches
// the provided name.
func (s *StorageLayout) GetStorageLayoutType(name string) (StorageLayoutType, error) {
if ty, ok := s.Types[name]; ok {
return ty, nil
}
return StorageLayoutType{}, fmt.Errorf("%s not found", name)
}
type StorageLayoutEntry struct {
AstId uint `json:"astId"`
Contract string `json:"contract"`
......
......@@ -37,13 +37,13 @@ func main() {
Flags: []cli.Flag{
&cli.StringFlag{
Name: "l1-rpc-url",
Required: true,
Value: "http://127.0.0.1:8545",
Usage: "L1 RPC URL",
EnvVars: []string{"L1_RPC_URL"},
},
&cli.StringFlag{
Name: "l2-rpc-url",
Required: true,
Value: "http://127.0.0.1:9545",
Usage: "L2 RPC URL",
EnvVars: []string{"L2_RPC_URL"},
},
......@@ -603,11 +603,17 @@ func checkL2StandardBridge(addr common.Address, client *ethclient.Client) error
if messenger != predeploys.L2CrossDomainMessengerAddr {
return fmt.Errorf("L2StandardBridge MESSENGER should be %s, got %s", predeploys.L2CrossDomainMessengerAddr, messenger)
}
version, err := contract.Version(&bind.CallOpts{})
if err != nil {
return err
}
initialized, err := getInitialized("L2StandardBridge", addr, client)
if err != nil {
return err
}
log.Info("L2StandardBridge", "_initialized", initialized)
log.Info("L2StandardBridge version", "version", version)
return nil
}
......@@ -714,6 +720,13 @@ func checkL2CrossDomainMessenger(addr common.Address, client *ethclient.Client)
if err != nil {
return err
}
initialized, err := getInitialized("L2CrossDomainMessenger", addr, client)
if err != nil {
return err
}
log.Info("L2CrossDomainMessenger", "_initialized", initialized)
log.Info("L2CrossDomainMessenger version", "version", version)
return nil
}
......@@ -805,3 +818,36 @@ func getEIP1967ImplementationAddress(client *ethclient.Client, addr common.Addre
impl := common.BytesToAddress(slot)
return impl, nil
}
// getInitialized will get the initialized value in storage of a contract.
// This is an incrementing number that starts at 1 and increments each time that
// the contract is upgraded.
func getInitialized(name string, addr common.Address, client *ethclient.Client) (*big.Int, error) {
layout, err := bindings.GetStorageLayout(name)
if err != nil {
return nil, err
}
entry, err := layout.GetStorageLayoutEntry("_initialized")
if err != nil {
return nil, err
}
typ, err := layout.GetStorageLayoutType(entry.Type)
if err != nil {
return nil, err
}
slot := common.BigToHash(big.NewInt(int64(entry.Slot)))
value, err := client.StorageAt(context.Background(), addr, slot, nil)
if err != nil {
return nil, err
}
if entry.Offset+typ.NumberOfBytes > uint(len(value)) {
return nil, fmt.Errorf("value length is too short")
}
// Swap the endianness
slice := common.CopyBytes(value)
for i, j := 0, len(slice)-1; i < j; i, j = i+1, j-1 {
slice[i], slice[j] = slice[j], slice[i]
}
initialized := new(big.Int).SetBytes(slice[entry.Offset : entry.Offset+typ.NumberOfBytes])
return initialized, nil
}
......@@ -656,6 +656,11 @@ func NewL2StorageConfig(config *DeployConfig, block *types.Block) (state.Storage
"xDomainMsgSender": "0x000000000000000000000000000000000000dEaD",
"msgNonce": 0,
}
storage["L2StandardBridge"] = state.StorageValues{
"_initialized": 2,
"_initializing": false,
"messenger": predeploys.L2CrossDomainMessengerAddr,
}
storage["L1Block"] = state.StorageValues{
"number": block.Number(),
"timestamp": block.Time(),
......
......@@ -3,6 +3,7 @@ package challenger
import (
"context"
"errors"
"os"
"testing"
"time"
......@@ -40,6 +41,19 @@ func NewChallenger(t *testing.T, ctx context.Context, l1Endpoint string, name st
require.NotEmpty(t, cfg.TxMgrConfig.PrivateKey, "Missing private key for TxMgrConfig")
require.NoError(t, cfg.Check(), "op-challenger config should be valid")
if cfg.CannonBin != "" {
_, err := os.Stat(cfg.CannonBin)
require.NoError(t, err, "cannon should be built. Make sure you've run make cannon-prestate")
}
if cfg.CannonServer != "" {
_, err := os.Stat(cfg.CannonServer)
require.NoError(t, err, "op-program should be built. Make sure you've run make cannon-prestate")
}
if cfg.CannonAbsolutePreState != "" {
_, err := os.Stat(cfg.CannonAbsolutePreState)
require.NoError(t, err, "cannon pre-state should be built. Make sure you've run make cannon-prestate")
}
errCh := make(chan error, 1)
ctx, cancel := context.WithCancel(ctx)
go func() {
......
package disputegame
import (
"context"
"github.com/ethereum-optimism/optimism/op-challenger/config"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils/challenger"
)
type AlphabetGameHelper struct {
FaultGameHelper
claimedAlphabet string
}
func (g *AlphabetGameHelper) StartChallenger(ctx context.Context, l1Endpoint string, name string, options ...challenger.Option) *challenger.Helper {
opts := []challenger.Option{
func(c *config.Config) {
c.GameAddress = g.addr
c.GameDepth = alphabetGameDepth
c.TraceType = config.TraceTypeAlphabet
// By default the challenger agrees with the root claim (thus disagrees with the proposed output)
// This can be overridden by passing in options
c.AlphabetTrace = g.claimedAlphabet
c.AgreeWithProposedOutput = false
},
}
opts = append(opts, options...)
c := challenger.NewChallenger(g.t, ctx, l1Endpoint, name, opts...)
g.t.Cleanup(func() {
_ = c.Close()
})
return c
}
package disputegame
import (
"context"
"github.com/ethereum-optimism/optimism/op-challenger/config"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils/challenger"
)
type CannonGameHelper struct {
FaultGameHelper
}
func (g *CannonGameHelper) StartChallenger(ctx context.Context, l1Endpoint string, l2Endpoint string, name string, options ...challenger.Option) *challenger.Helper {
opts := []challenger.Option{
func(c *config.Config) {
c.GameAddress = g.addr
c.GameDepth = cannonGameDepth
c.TraceType = config.TraceTypeCannon
c.AgreeWithProposedOutput = false
c.CannonL2 = l2Endpoint
c.CannonBin = "../cannon/bin/cannon"
c.CannonDatadir = g.t.TempDir()
c.CannonServer = "../op-program/bin/op-program"
c.CannonAbsolutePreState = "../op-program/bin/prestate.json"
c.CannonSnapshotFreq = config.DefaultCannonSnapshotFreq
},
}
opts = append(opts, options...)
c := challenger.NewChallenger(g.t, ctx, l1Endpoint, name, opts...)
g.t.Cleanup(func() {
_ = c.Close()
})
return c
}
package disputegame
import (
"context"
"fmt"
"math/big"
"testing"
"time"
"github.com/ethereum-optimism/optimism/op-bindings/bindings"
"github.com/ethereum-optimism/optimism/op-challenger/fault/types"
"github.com/ethereum-optimism/optimism/op-service/client/utils"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/stretchr/testify/require"
)
type FaultGameHelper struct {
t *testing.T
require *require.Assertions
client *ethclient.Client
opts *bind.TransactOpts
game *bindings.FaultDisputeGame
maxDepth int
addr common.Address
}
func (g *FaultGameHelper) GameDuration(ctx context.Context) time.Duration {
duration, err := g.game.GAMEDURATION(&bind.CallOpts{Context: ctx})
g.require.NoError(err, "failed to get game duration")
return time.Duration(duration) * time.Second
}
func (g *FaultGameHelper) WaitForClaimCount(ctx context.Context, count int64) {
ctx, cancel := context.WithTimeout(ctx, time.Minute)
defer cancel()
err := utils.WaitFor(ctx, time.Second, func() (bool, error) {
actual, err := g.game.ClaimDataLen(&bind.CallOpts{Context: ctx})
if err != nil {
return false, err
}
g.t.Log("Waiting for claim count", "current", actual, "expected", count, "game", g.addr)
return actual.Cmp(big.NewInt(count)) == 0, nil
})
g.require.NoError(err)
}
type ContractClaim struct {
ParentIndex uint32
Countered bool
Claim [32]byte
Position *big.Int
Clock *big.Int
}
func (g *FaultGameHelper) WaitForClaim(ctx context.Context, predicate func(claim ContractClaim) bool) {
ctx, cancel := context.WithTimeout(ctx, time.Minute)
defer cancel()
err := utils.WaitFor(ctx, time.Second, func() (bool, error) {
count, err := g.game.ClaimDataLen(&bind.CallOpts{Context: ctx})
if err != nil {
return false, fmt.Errorf("retrieve number of claims: %w", err)
}
// Search backwards because the new claims are at the end and more likely the ones we want.
for i := count.Int64() - 1; i >= 0; i-- {
claimData, err := g.game.ClaimData(&bind.CallOpts{Context: ctx}, big.NewInt(i))
if err != nil {
return false, fmt.Errorf("retrieve claim %v: %w", i, err)
}
if predicate(claimData) {
return true, nil
}
}
return false, nil
})
g.require.NoError(err)
}
func (g *FaultGameHelper) WaitForClaimAtMaxDepth(ctx context.Context, countered bool) {
g.WaitForClaim(ctx, func(claim ContractClaim) bool {
pos := types.NewPositionFromGIndex(claim.Position.Uint64())
return pos.Depth() == g.maxDepth && claim.Countered == countered
})
}
func (g *FaultGameHelper) Resolve(ctx context.Context) {
ctx, cancel := context.WithTimeout(ctx, time.Minute)
defer cancel()
tx, err := g.game.Resolve(g.opts)
g.require.NoError(err)
_, err = utils.WaitReceiptOK(ctx, g.client, tx.Hash())
g.require.NoError(err)
}
func (g *FaultGameHelper) WaitForGameStatus(ctx context.Context, expected Status) {
g.t.Logf("Waiting for game %v to have status %v", g.addr, expected)
ctx, cancel := context.WithTimeout(ctx, time.Minute)
defer cancel()
err := utils.WaitFor(ctx, time.Second, func() (bool, error) {
ctx, cancel := context.WithTimeout(ctx, 30*time.Second)
defer cancel()
status, err := g.game.Status(&bind.CallOpts{Context: ctx})
if err != nil {
return false, fmt.Errorf("game status unavailable: %w", err)
}
g.t.Logf("Game %v has state %v, waiting for state %v", g.addr, Status(status), expected)
return expected == Status(status), nil
})
g.require.NoError(err, "wait for game status")
}
This diff is collapsed.
......@@ -8,6 +8,7 @@ import (
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils/disputegame"
"github.com/ethereum-optimism/optimism/op-service/client/utils"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/stretchr/testify/require"
)
......@@ -143,6 +144,32 @@ func TestChallengerCompleteDisputeGame(t *testing.T) {
}
}
func TestCannonDisputeGame(t *testing.T) {
t.Skip("CLI-4290: op-challenger doesn't handle trace extension correctly for cannon")
InitParallel(t)
ctx := context.Background()
sys, l1Client := startFaultDisputeSystem(t)
t.Cleanup(sys.Close)
disputeGameFactory := disputegame.NewFactoryHelper(t, ctx, sys.cfg.L1Deployments, l1Client)
game := disputeGameFactory.StartCannonGame(ctx, common.Hash{0xaa})
require.NotNil(t, game)
game.StartChallenger(ctx, sys.NodeEndpoint("l1"), sys.NodeEndpoint("sequencer"), "Challenger", func(c *config.Config) {
c.AgreeWithProposedOutput = true // Agree with the proposed output, so disagree with the root claim
c.TxMgrConfig.PrivateKey = e2eutils.EncodePrivKeyToString(sys.cfg.Secrets.Alice)
})
// Challenger should counter the root claim
game.WaitForClaimCount(ctx, 2)
sys.TimeTravelClock.AdvanceTime(game.GameDuration(ctx))
require.NoError(t, utils.WaitNextBlock(ctx, l1Client))
game.WaitForGameStatus(ctx, disputegame.StatusChallengerWins)
}
func startFaultDisputeSystem(t *testing.T) (*System, *ethclient.Client) {
cfg := DefaultSystemConfig(t)
delete(cfg.Nodes, "verifier")
......
......@@ -13,7 +13,6 @@ import (
"github.com/ethereum-optimism/optimism/op-bindings/bindings"
"github.com/ethereum-optimism/optimism/op-bindings/predeploys"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils"
"github.com/ethereum-optimism/optimism/op-node/rollup/derive"
"github.com/ethereum-optimism/optimism/op-node/testutils/fuzzerutils"
"github.com/ethereum-optimism/optimism/op-node/withdrawals"
"github.com/ethereum/go-ethereum/accounts"
......@@ -246,10 +245,6 @@ func TestMixedDepositValidity(t *testing.T) {
// Define our L1 transaction timeout duration.
txTimeoutDuration := 10 * time.Duration(cfg.DeployConfig.L1BlockTime) * time.Second
// Bind to the deposit contract
depositContract, err := bindings.NewOptimismPortal(cfg.L1Deployments.OptimismPortalProxy, l1Client)
require.NoError(t, err)
// Create a struct used to track our transactors and their transactions sent.
type TestAccountState struct {
Account *TestAccount
......@@ -320,27 +315,18 @@ func TestMixedDepositValidity(t *testing.T) {
} else {
transferValue = new(big.Int).Mul(common.Big2, transactor.ExpectedL2Balance) // trigger a revert by trying to transfer our current balance * 2
}
tx, err := depositContract.DepositTransaction(transactor.Account.L1Opts, toAddr, transferValue, 100_000, false, nil)
require.Nil(t, err, "with deposit tx")
// Wait for the deposit tx to appear in L1.
receipt, err := waitForTransaction(tx.Hash(), l1Client, txTimeoutDuration)
require.Nil(t, err, "Waiting for deposit tx on L1")
require.Equal(t, receipt.Status, types.ReceiptStatusSuccessful)
// Reconstruct the L2 tx hash to wait for the deposit in L2.
reconstructedDep, err := derive.UnmarshalDepositLogEvent(receipt.Logs[0])
require.NoError(t, err, "Could not reconstruct L2 Deposit")
tx = types.NewTx(reconstructedDep)
receipt, err = waitForTransaction(tx.Hash(), l2Verif, txTimeoutDuration)
require.NoError(t, err)
// Verify the result of the L2 tx receipt. Based on how much we transferred it should be successful/failed.
SendDepositTx(t, cfg, l1Client, l2Verif, transactor.Account.L1Opts, func(l2Opts *DepositTxOpts) {
l2Opts.GasLimit = 100_000
l2Opts.IsCreation = false
l2Opts.Data = nil
l2Opts.ToAddr = toAddr
l2Opts.Value = transferValue
if validTransfer {
require.Equal(t, types.ReceiptStatusSuccessful, receipt.Status, "Transaction should have succeeded")
l2Opts.ExpectedStatus = types.ReceiptStatusSuccessful
} else {
require.Equal(t, types.ReceiptStatusFailed, receipt.Status, "Transaction should have failed")
l2Opts.ExpectedStatus = types.ReceiptStatusFailed
}
})
// Update our expected balances.
if validTransfer && transactor != receiver {
......
This diff is collapsed.
......@@ -33,11 +33,8 @@ func setupL2OutputOracle() (common.Address, *bind.TransactOpts, *backends.Simula
backend,
big.NewInt(10),
big.NewInt(2),
big.NewInt(0),
big.NewInt(0),
from,
common.Address{0xdd},
big.NewInt(100))
big.NewInt(100),
)
if err != nil {
return common.Address{}, nil, nil, nil, err
}
......
This diff is collapsed.
This diff is collapsed.
......@@ -94,9 +94,9 @@
}
},
"L1StandardBridge": {
"spacer_0_0_20": {
"spacer_0_2_20": {
"slot": 0,
"offset": 0,
"offset": 2,
"length": 20
},
"spacer_1_0_20": {
......
This diff is collapsed.
......@@ -14,18 +14,18 @@ import { L2ToL1MessagePasser } from "./L2ToL1MessagePasser.sol";
/// L2 on the L2 side. Users are generally encouraged to use this contract instead of lower
/// level message passing contracts.
contract L2CrossDomainMessenger is CrossDomainMessenger, Semver {
/// @custom:semver 1.4.1
/// @custom:semver 1.5.0
/// @notice Constructs the L2CrossDomainMessenger contract.
/// @param _l1CrossDomainMessenger Address of the L1CrossDomainMessenger contract.
constructor(address _l1CrossDomainMessenger)
Semver(1, 4, 1)
Semver(1, 5, 0)
CrossDomainMessenger(_l1CrossDomainMessenger)
{
initialize();
}
/// @notice Initializer.
function initialize() public initializer {
function initialize() public reinitializer(2) {
__CrossDomainMessenger_init();
}
......
......@@ -5,6 +5,7 @@ import { Predeploys } from "../libraries/Predeploys.sol";
import { StandardBridge } from "../universal/StandardBridge.sol";
import { Semver } from "../universal/Semver.sol";
import { OptimismMintableERC20 } from "../universal/OptimismMintableERC20.sol";
import { CrossDomainMessenger } from "../universal/CrossDomainMessenger.sol";
/// @custom:proxied
/// @custom:predeploy 0x4200000000000000000000000000000000000010
......@@ -50,13 +51,19 @@ contract L2StandardBridge is StandardBridge, Semver {
bytes extraData
);
/// @custom:semver 1.1.1
/// @custom:semver 1.2.0
/// @notice Constructs the L2StandardBridge contract.
/// @param _otherBridge Address of the L1StandardBridge.
constructor(address payable _otherBridge)
Semver(1, 1, 1)
StandardBridge(payable(Predeploys.L2_CROSS_DOMAIN_MESSENGER), _otherBridge)
{}
constructor(StandardBridge _otherBridge) Semver(1, 2, 0) StandardBridge(_otherBridge) {
initialize();
}
/// @notice Initializer
function initialize() public reinitializer(2) {
__StandardBridge_init({
_messenger: CrossDomainMessenger(Predeploys.L2_CROSS_DOMAIN_MESSENGER)
});
}
/// @notice Allows EOAs to bridge ETH by sending directly to the bridge.
receive() external payable override onlyEOA {
......
......@@ -35,6 +35,13 @@ contract L1StandardBridge_Initialize_Test is Bridge_Initializer {
assertEq(address(L1Bridge.OTHER_BRIDGE()), Predeploys.L2_STANDARD_BRIDGE);
assertEq(address(L2Bridge), Predeploys.L2_STANDARD_BRIDGE);
}
function test_initialize_fix_succeeds() external {
bytes32 slot0 = vm.load(address(L1Bridge), bytes32(uint256(0)));
// The first storage slot should only have its first byte set to 0x02.
// This covers the `clearLegacySlot` fix.
assertEq(slot0, bytes32(uint256(2)));
}
}
contract L1StandardBridge_Initialize_TestFail is Bridge_Initializer {}
......
......@@ -11,7 +11,7 @@ contract MIPS_Test is Test {
function setUp() public {
oracle = new PreimageOracle();
mips = new MIPS();
mips = new MIPS(oracle);
vm.store(address(mips), 0x0, bytes32(abi.encode(address(oracle))));
vm.label(address(oracle), "PreimageOracle");
vm.label(address(mips), "MIPS");
......
......@@ -14,7 +14,7 @@ import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
/// internal functions so they can be more easily tested directly.
contract StandardBridgeTester is StandardBridge {
constructor(address payable _messenger, address payable _otherBridge)
StandardBridge(_messenger, _otherBridge)
StandardBridge(StandardBridge(_otherBridge))
{}
function isOptimismMintableERC20(address _token) external view returns (bool) {
......
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment