Commit 9fbeebda authored by Matthew Slipper's avatar Matthew Slipper

op-chain-ops: Preserve predeploy nonces

Users are unable to use the OptimismMintableERC20Factory contract due to the nonce being reset to zero. This PR updates the predeploy storage wipe function to preserve nonces during the migration. This is fixable on Goerli by incrementing the nonce manually on the factory contract.
parent 1211ba29
...@@ -119,6 +119,11 @@ func PostCheckMigratedDB( ...@@ -119,6 +119,11 @@ func PostCheckMigratedDB(
Preimages: true, Preimages: true,
}) })
prevDB, err := state.New(prevHeader.Root, underlyingDB, nil)
if err != nil {
return fmt.Errorf("cannot open historical StateDB: %w", err)
}
db, err := state.New(header.Root, underlyingDB, nil) db, err := state.New(header.Root, underlyingDB, nil)
if err != nil { if err != nil {
return fmt.Errorf("cannot open StateDB: %w", err) return fmt.Errorf("cannot open StateDB: %w", err)
...@@ -134,7 +139,7 @@ func PostCheckMigratedDB( ...@@ -134,7 +139,7 @@ func PostCheckMigratedDB(
} }
log.Info("checked untouchables") log.Info("checked untouchables")
if err := PostCheckPredeploys(db); err != nil { if err := PostCheckPredeploys(prevDB, db); err != nil {
return err return err
} }
log.Info("checked predeploys") log.Info("checked predeploys")
...@@ -209,13 +214,13 @@ func PostCheckUntouchables(udb state.Database, currDB *state.StateDB, prevRoot c ...@@ -209,13 +214,13 @@ func PostCheckUntouchables(udb state.Database, currDB *state.StateDB, prevRoot c
// PostCheckPredeploys will check that there is code at each predeploy // PostCheckPredeploys will check that there is code at each predeploy
// address // address
func PostCheckPredeploys(db *state.StateDB) error { func PostCheckPredeploys(prevDB, currDB *state.StateDB) error {
for i := uint64(0); i <= 2048; i++ { for i := uint64(0); i <= 2048; i++ {
// Compute the predeploy address // Compute the predeploy address
bigAddr := new(big.Int).Or(bigL2PredeployNamespace, new(big.Int).SetUint64(i)) bigAddr := new(big.Int).Or(bigL2PredeployNamespace, new(big.Int).SetUint64(i))
addr := common.BigToAddress(bigAddr) addr := common.BigToAddress(bigAddr)
// Get the code for the predeploy // Get the code for the predeploy
code := db.GetCode(addr) code := currDB.GetCode(addr)
// There must be code for the predeploy // There must be code for the predeploy
if len(code) == 0 { if len(code) == 0 {
return fmt.Errorf("no code found at predeploy %s", addr) return fmt.Errorf("no code found at predeploy %s", addr)
...@@ -227,11 +232,23 @@ func PostCheckPredeploys(db *state.StateDB) error { ...@@ -227,11 +232,23 @@ func PostCheckPredeploys(db *state.StateDB) error {
} }
// There must be an admin // There must be an admin
admin := db.GetState(addr, AdminSlot) admin := currDB.GetState(addr, AdminSlot)
adminAddr := common.BytesToAddress(admin.Bytes()) adminAddr := common.BytesToAddress(admin.Bytes())
if addr != predeploys.ProxyAdminAddr && addr != predeploys.GovernanceTokenAddr && adminAddr != predeploys.ProxyAdminAddr { if addr != predeploys.ProxyAdminAddr && addr != predeploys.GovernanceTokenAddr && adminAddr != predeploys.ProxyAdminAddr {
return fmt.Errorf("expected admin for %s to be %s but got %s", addr, predeploys.ProxyAdminAddr, adminAddr) return fmt.Errorf("expected admin for %s to be %s but got %s", addr, predeploys.ProxyAdminAddr, adminAddr)
} }
// Balances and nonces should match legacy
oldNonce := prevDB.GetNonce(addr)
oldBalance := prevDB.GetBalance(addr)
newNonce := currDB.GetNonce(addr)
newBalance := currDB.GetBalance(addr)
if oldNonce != newNonce {
return fmt.Errorf("expected nonce for %s to be %d but got %d", addr, oldNonce, newNonce)
}
if oldBalance.Cmp(newBalance) != 0 {
return fmt.Errorf("expected balance for %s to be %d but got %d", addr, oldBalance, newBalance)
}
} }
// For each predeploy, check that we've set the implementation correctly when // For each predeploy, check that we've set the implementation correctly when
...@@ -248,7 +265,7 @@ func PostCheckPredeploys(db *state.StateDB) error { ...@@ -248,7 +265,7 @@ func PostCheckPredeploys(db *state.StateDB) error {
} }
if *proxyAddr == predeploys.ProxyAdminAddr { if *proxyAddr == predeploys.ProxyAdminAddr {
implCode := db.GetCode(*proxyAddr) implCode := currDB.GetCode(*proxyAddr)
if len(implCode) == 0 { if len(implCode) == 0 {
return errors.New("no code found at proxy admin") return errors.New("no code found at proxy admin")
} }
...@@ -260,12 +277,12 @@ func PostCheckPredeploys(db *state.StateDB) error { ...@@ -260,12 +277,12 @@ func PostCheckPredeploys(db *state.StateDB) error {
return fmt.Errorf("error converting to code namespace: %w", err) return fmt.Errorf("error converting to code namespace: %w", err)
} }
implCode := db.GetCode(expImplAddr) implCode := currDB.GetCode(expImplAddr)
if len(implCode) == 0 { if len(implCode) == 0 {
return fmt.Errorf("no code found at predeploy impl %s", *proxyAddr) return fmt.Errorf("no code found at predeploy impl %s", *proxyAddr)
} }
impl := db.GetState(*proxyAddr, ImplementationSlot) impl := currDB.GetState(*proxyAddr, ImplementationSlot)
actImplAddr := common.BytesToAddress(impl.Bytes()) actImplAddr := common.BytesToAddress(impl.Bytes())
if expImplAddr != actImplAddr { if expImplAddr != actImplAddr {
return fmt.Errorf("expected implementation for %s to be at %s, but got %s", *proxyAddr, expImplAddr, actImplAddr) return fmt.Errorf("expected implementation for %s to be at %s, but got %s", *proxyAddr, expImplAddr, actImplAddr)
......
...@@ -92,7 +92,17 @@ func WipePredeployStorage(db vm.StateDB) error { ...@@ -92,7 +92,17 @@ func WipePredeployStorage(db vm.StateDB) error {
} }
log.Info("wiping storage", "name", name, "address", *addr) log.Info("wiping storage", "name", name, "address", *addr)
// We need to make sure that we preserve nonces.
oldNonce := db.GetNonce(*addr)
oldBalance := db.GetBalance(*addr)
db.CreateAccount(*addr) db.CreateAccount(*addr)
if oldNonce > 0 {
db.SetNonce(*addr, oldNonce)
}
if oldBalance.Cmp(common.Big0) != 0 {
db.AddBalance(*addr, oldBalance)
}
} }
return nil return nil
......
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