diff --git a/core/forkid/forkid_test.go b/core/forkid/forkid_test.go
index 1fc1b4ee1c432a7841c12650b42510bb40b11394..cc22b6313ca35f8f15d6e5c2f8622fe398e6d0c5 100644
--- a/core/forkid/forkid_test.go
+++ b/core/forkid/forkid_test.go
@@ -61,8 +61,10 @@ func TestCreation(t *testing.T) {
 				{9199999, ID{Hash: checksumToBytes(0x879d6e30), Next: 9200000}},   // Last Istanbul and first Muir Glacier block
 				{9200000, ID{Hash: checksumToBytes(0xe029e991), Next: 12244000}},  // First Muir Glacier block
 				{12243999, ID{Hash: checksumToBytes(0xe029e991), Next: 12244000}}, // Last Muir Glacier block
-				{12244000, ID{Hash: checksumToBytes(0x0eb440f6), Next: 0}},        // First Berlin block
-				{20000000, ID{Hash: checksumToBytes(0x0eb440f6), Next: 0}},        // Future Berlin block
+				{12244000, ID{Hash: checksumToBytes(0x0eb440f6), Next: 12965000}}, // First Berlin block
+				{12964999, ID{Hash: checksumToBytes(0x0eb440f6), Next: 12965000}}, // Last Berlin block
+				{12965000, ID{Hash: checksumToBytes(0xb715077d), Next: 0}},        // First London block
+				{20000000, ID{Hash: checksumToBytes(0xb715077d), Next: 0}},        // Future London block
 			},
 		},
 		// Ropsten test cases
@@ -199,11 +201,11 @@ func TestValidation(t *testing.T) {
 		// Local is mainnet Petersburg, remote is Rinkeby Petersburg.
 		{7987396, ID{Hash: checksumToBytes(0xafec6b27), Next: 0}, ErrLocalIncompatibleOrStale},
 
-		// Local is mainnet Berlin, far in the future. Remote announces Gopherium (non existing fork)
+		// Local is mainnet London, far in the future. Remote announces Gopherium (non existing fork)
 		// at some future block 88888888, for itself, but past block for local. Local is incompatible.
 		//
 		// This case detects non-upgraded nodes with majority hash power (typical Ropsten mess).
-		{88888888, ID{Hash: checksumToBytes(0x0eb440f6), Next: 88888888}, ErrLocalIncompatibleOrStale},
+		{88888888, ID{Hash: checksumToBytes(0xb715077d), Next: 88888888}, ErrLocalIncompatibleOrStale},
 
 		// Local is mainnet Byzantium. Remote is also in Byzantium, but announces Gopherium (non existing
 		// fork) at block 7279999, before Petersburg. Local is incompatible.
diff --git a/core/types/block.go b/core/types/block.go
index e556fc75f7f07af15c3441a4dd6d7e678fa92731..b8879f011735b14c285b8aa43778eb440e4b8348 100644
--- a/core/types/block.go
+++ b/core/types/block.go
@@ -569,6 +569,11 @@ func (h *Header) SanityCheck() error {
 	if eLen := len(h.Extra); eLen > 100*1024 {
 		return fmt.Errorf("too large block extradata: size %d", eLen)
 	}
+	if h.BaseFee != nil {
+		if bfLen := h.BaseFee.BitLen(); bfLen > 256 {
+			return fmt.Errorf("too large base fee: bitlen %d", bfLen)
+		}
+	}
 	return nil
 }
 
diff --git a/core/vm/runtime/env.go b/core/vm/runtime/env.go
index 7a0a74a588eaf792300b1d91297578cddcb22c96..fdd2fb31d2996e2209b50e70f887c40e5b647a0e 100644
--- a/core/vm/runtime/env.go
+++ b/core/vm/runtime/env.go
@@ -36,6 +36,7 @@ func NewEnv(cfg *Config) *vm.EVM {
 		Time:        cfg.Time.Uint64(),
 		Difficulty:  cfg.Difficulty,
 		GasLimit:    cfg.GasLimit,
+		BaseFee:     cfg.BaseFee,
 	}
 
 	return vm.NewEVM(blockContext, txContext, cfg.State, cfg.ChainConfig, cfg.EVMConfig)
diff --git a/core/vm/runtime/runtime.go b/core/vm/runtime/runtime.go
index ef5edf2d7e7ab2691231c7dd92daefcc9351127e..32079dbecfa3bcd9ead9fc41cda1502be613fd41 100644
--- a/core/vm/runtime/runtime.go
+++ b/core/vm/runtime/runtime.go
@@ -45,6 +45,7 @@ type Config struct {
 	Value       *uint256.Int
 	Debug       bool
 	EVMConfig   vm.Config
+	BaseFee     *uint256.Int
 
 	State     *state.IntraBlockState
 	r         state.StateReader
@@ -71,6 +72,7 @@ func setDefaults(cfg *Config) {
 			IstanbulBlock:       new(big.Int),
 			MuirGlacierBlock:    new(big.Int),
 			BerlinBlock:         new(big.Int),
+			LondonBlock:         new(big.Int),
 		}
 	}
 
diff --git a/crypto/signature_cgo.go b/crypto/signature_cgo.go
index 89c55c3f73542ef8d3a37d97f13bcc24278d999a..d7d895e49834be0dd536e6b72354004e73ac272d 100644
--- a/crypto/signature_cgo.go
+++ b/crypto/signature_cgo.go
@@ -14,7 +14,7 @@
 // You should have received a copy of the GNU Lesser General Public License
 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
 
-// +build !nacl,!js,cgo
+// +build !nacl,!js,cgo,!gofuzz
 
 package crypto
 
diff --git a/crypto/signature_nocgo.go b/crypto/signature_nocgo.go
index 9516aff783bcc0568964aaa8d16947f726a3e1d3..8d38fd8d5d0d4cc1dcf7ef2daca57f35321e37b4 100644
--- a/crypto/signature_nocgo.go
+++ b/crypto/signature_nocgo.go
@@ -14,7 +14,7 @@
 // You should have received a copy of the GNU Lesser General Public License
 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
 
-// +build nacl js !cgo
+// +build nacl js !cgo gofuzz
 
 package crypto
 
diff --git a/go.mod b/go.mod
index 48b80d7a2cd1fe3231b1027a393aee1683ef174c..2074fa82d566a8068cd8a8811a432ec6208e1e43 100644
--- a/go.mod
+++ b/go.mod
@@ -35,7 +35,7 @@ require (
 	github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0
 	github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d
 	github.com/holiman/uint256 v1.2.0
-	github.com/huin/goupnp v1.0.1-0.20200620063722-49508fba0031
+	github.com/huin/goupnp v1.0.1-0.20210626160114-33cdcbb30dda
 	github.com/jackpal/go-nat-pmp v1.0.2
 	github.com/jedisct1/go-minisign v0.0.0-20190909160543-45766022959e
 	github.com/json-iterator/go v1.1.11
diff --git a/go.sum b/go.sum
index 586ddc62674ddc0fc4b8b1447d5f89c24a72e107..99c1e90c08c9f67c4ae0952362decf79daf04ec6 100644
--- a/go.sum
+++ b/go.sum
@@ -536,8 +536,8 @@ github.com/huandu/xstrings v1.3.2 h1:L18LIDzqlW6xN2rEkpdV8+oL/IXWJ1APd+vsdYy4Wdw
 github.com/huandu/xstrings v1.3.2/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
 github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg=
 github.com/huin/goupnp v1.0.0/go.mod h1:n9v9KO1tAxYH82qOn+UTIFQDmx5n1Zxd/ClZDMX7Bnc=
-github.com/huin/goupnp v1.0.1-0.20200620063722-49508fba0031 h1:HarGZ5h9HD9LgEg1yRVMXyfiw4wlXiLiYM2oMjeA/SE=
-github.com/huin/goupnp v1.0.1-0.20200620063722-49508fba0031/go.mod h1:nNs7wvRfN1eKaMknBydLNQU6146XQim8t4h+q90biWo=
+github.com/huin/goupnp v1.0.1-0.20210626160114-33cdcbb30dda h1:Vofqyy/Ysqit++X33unU0Gr08b6P35hKm3juytDrBVI=
+github.com/huin/goupnp v1.0.1-0.20210626160114-33cdcbb30dda/go.mod h1:0dxJBVBHqTMjIUMkESDTNgOOx/Mw5wYIfyFmdzSamkM=
 github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3iZrZfqZzyLl6l7F3c6L1oWn7OICBi6o=
 github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
 github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
diff --git a/p2p/peer_error.go b/p2p/peer_error.go
index ab61bfef062d5be26fd48f90285a207ecbbef558..393cc86b0970909fd8312eb229bc1b6b318f66da 100644
--- a/p2p/peer_error.go
+++ b/p2p/peer_error.go
@@ -89,7 +89,7 @@ var discReasonToString = [...]string{
 }
 
 func (d DiscReason) String() string {
-	if len(discReasonToString) < int(d) {
+	if len(discReasonToString) <= int(d) {
 		return fmt.Sprintf("unknown disconnect reason %d", d)
 	}
 	return discReasonToString[d]
diff --git a/params/config.go b/params/config.go
index 6854d3acfbb96f93ab0ffc53ab6b95284a078b55..e6ad99e2602e48c9645176a72ad72ecb434d855f 100644
--- a/params/config.go
+++ b/params/config.go
@@ -93,6 +93,7 @@ var (
 		IstanbulBlock:       big.NewInt(9_069_000),
 		MuirGlacierBlock:    big.NewInt(9_200_000),
 		BerlinBlock:         big.NewInt(12_244_000),
+		LondonBlock:         big.NewInt(12_965_000),
 		Ethash:              new(EthashConfig),
 	}