diff --git a/cmd/geth/main.go b/cmd/geth/main.go
index b232b8e807ebb427ae6288a97e8db16dbdd48bd7..f1e8e2421747d989f076dd1f12e7827589054592 100644
--- a/cmd/geth/main.go
+++ b/cmd/geth/main.go
@@ -186,6 +186,7 @@ var (
 		utils.IPCPathFlag,
 		utils.InsecureUnlockAllowedFlag,
 		utils.RPCGlobalGasCap,
+		utils.RPCGlobalTxFeeCap,
 	}
 
 	whisperFlags = []cli.Flag{
diff --git a/cmd/geth/usage.go b/cmd/geth/usage.go
index 5c429056e96b674b9e43197043d7e17e176d1b12..ee97e1a972302a2656fd7cab5184b423820dab3a 100644
--- a/cmd/geth/usage.go
+++ b/cmd/geth/usage.go
@@ -176,6 +176,7 @@ var AppHelpFlagGroups = []flagGroup{
 			utils.GraphQLCORSDomainFlag,
 			utils.GraphQLVirtualHostsFlag,
 			utils.RPCGlobalGasCap,
+			utils.RPCGlobalTxFeeCap,
 			utils.JSpathFlag,
 			utils.ExecFlag,
 			utils.PreloadJSFlag,
diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go
index 19d7e99a43b0f68b11ae12c550d4d809f3d94ef1..dbc1cdad1fd8bc27bd28fc9919a6fcaf1c10bdf4 100644
--- a/cmd/utils/flags.go
+++ b/cmd/utils/flags.go
@@ -478,6 +478,11 @@ var (
 		Name:  "rpc.gascap",
 		Usage: "Sets a cap on gas that can be used in eth_call/estimateGas",
 	}
+	RPCGlobalTxFeeCap = cli.Float64Flag{
+		Name:  "rpc.txfeecap",
+		Usage: "Sets a cap on transaction fee (in ether) that can be sent via the RPC APIs (0 = no cap)",
+		Value: eth.DefaultConfig.RPCTxFeeCap,
+	}
 	// Logging and debug settings
 	EthStatsURLFlag = cli.StringFlag{
 		Name:  "ethstats",
@@ -1560,6 +1565,9 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *eth.Config) {
 	if ctx.GlobalIsSet(RPCGlobalGasCap.Name) {
 		cfg.RPCGasCap = new(big.Int).SetUint64(ctx.GlobalUint64(RPCGlobalGasCap.Name))
 	}
+	if ctx.GlobalIsSet(RPCGlobalTxFeeCap.Name) {
+		cfg.RPCTxFeeCap = ctx.GlobalFloat64(RPCGlobalTxFeeCap.Name)
+	}
 	if ctx.GlobalIsSet(DNSDiscoveryFlag.Name) {
 		urls := ctx.GlobalString(DNSDiscoveryFlag.Name)
 		if urls == "" {
diff --git a/eth/api_backend.go b/eth/api_backend.go
index a82aee4eb79edc618ab6cf18ea9c9bc2219d3f21..b6d727076117e6699a90034f84b9ff761d9e89d7 100644
--- a/eth/api_backend.go
+++ b/eth/api_backend.go
@@ -293,6 +293,10 @@ func (b *EthAPIBackend) RPCGasCap() *big.Int {
 	return b.eth.config.RPCGasCap
 }
 
+func (b *EthAPIBackend) RPCTxFeeCap() float64 {
+	return b.eth.config.RPCTxFeeCap
+}
+
 func (b *EthAPIBackend) BloomStatus() (uint64, uint64) {
 	sections, _, _ := b.eth.bloomIndexer.Sections()
 	return params.BloomBitsBlocks, sections
diff --git a/eth/config.go b/eth/config.go
index 45767810d4ff49dd83395e9ec899ad59cfa4bb80..84a2f140a9490d706f4e6e3215bb6fc82d595397 100644
--- a/eth/config.go
+++ b/eth/config.go
@@ -64,6 +64,7 @@ var DefaultConfig = Config{
 		Blocks:     20,
 		Percentile: 60,
 	},
+	RPCTxFeeCap: 1, // 1 ether
 }
 
 func init() {
@@ -159,6 +160,10 @@ type Config struct {
 	// RPCGasCap is the global gas cap for eth-call variants.
 	RPCGasCap *big.Int `toml:",omitempty"`
 
+	// RPCTxFeeCap is the global transaction fee(price * gaslimit) cap for
+	// send-transction variants. The unit is ether.
+	RPCTxFeeCap float64 `toml:",omitempty"`
+
 	// Checkpoint is a hardcoded checkpoint which can be nil.
 	Checkpoint *params.TrustedCheckpoint `toml:",omitempty"`
 
diff --git a/eth/gen_config.go b/eth/gen_config.go
index 56980bc501615597296302e4603e2d1942ffb235..f3d18918560dc2d556a664bd24c5edfb3797f406 100644
--- a/eth/gen_config.go
+++ b/eth/gen_config.go
@@ -40,6 +40,7 @@ func (c Config) MarshalTOML() (interface{}, error) {
 		TrieCleanCache          int
 		TrieDirtyCache          int
 		TrieTimeout             time.Duration
+		SnapshotCache           int
 		Miner                   miner.Config
 		Ethash                  ethash.Config
 		TxPool                  core.TxPoolConfig
@@ -49,10 +50,9 @@ func (c Config) MarshalTOML() (interface{}, error) {
 		EWASMInterpreter        string
 		EVMInterpreter          string
 		RPCGasCap               *big.Int                       `toml:",omitempty"`
+		RPCTxFeeCap             float64                        `toml:",omitempty"`
 		Checkpoint              *params.TrustedCheckpoint      `toml:",omitempty"`
 		CheckpointOracle        *params.CheckpointOracleConfig `toml:",omitempty"`
-		OverrideIstanbul        *big.Int                       `toml:",omitempty"`
-		OverrideMuirGlacier     *big.Int                       `toml:",omitempty"`
 	}
 	var enc Config
 	enc.Genesis = c.Genesis
@@ -77,6 +77,7 @@ func (c Config) MarshalTOML() (interface{}, error) {
 	enc.TrieCleanCache = c.TrieCleanCache
 	enc.TrieDirtyCache = c.TrieDirtyCache
 	enc.TrieTimeout = c.TrieTimeout
+	enc.SnapshotCache = c.SnapshotCache
 	enc.Miner = c.Miner
 	enc.Ethash = c.Ethash
 	enc.TxPool = c.TxPool
@@ -86,6 +87,7 @@ func (c Config) MarshalTOML() (interface{}, error) {
 	enc.EWASMInterpreter = c.EWASMInterpreter
 	enc.EVMInterpreter = c.EVMInterpreter
 	enc.RPCGasCap = c.RPCGasCap
+	enc.RPCTxFeeCap = c.RPCTxFeeCap
 	enc.Checkpoint = c.Checkpoint
 	enc.CheckpointOracle = c.CheckpointOracle
 	return &enc, nil
@@ -116,6 +118,7 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error {
 		TrieCleanCache          *int
 		TrieDirtyCache          *int
 		TrieTimeout             *time.Duration
+		SnapshotCache           *int
 		Miner                   *miner.Config
 		Ethash                  *ethash.Config
 		TxPool                  *core.TxPoolConfig
@@ -125,10 +128,9 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error {
 		EWASMInterpreter        *string
 		EVMInterpreter          *string
 		RPCGasCap               *big.Int                       `toml:",omitempty"`
+		RPCTxFeeCap             *float64                       `toml:",omitempty"`
 		Checkpoint              *params.TrustedCheckpoint      `toml:",omitempty"`
 		CheckpointOracle        *params.CheckpointOracleConfig `toml:",omitempty"`
-		OverrideIstanbul        *big.Int                       `toml:",omitempty"`
-		OverrideMuirGlacier     *big.Int                       `toml:",omitempty"`
 	}
 	var dec Config
 	if err := unmarshal(&dec); err != nil {
@@ -200,6 +202,9 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error {
 	if dec.TrieTimeout != nil {
 		c.TrieTimeout = *dec.TrieTimeout
 	}
+	if dec.SnapshotCache != nil {
+		c.SnapshotCache = *dec.SnapshotCache
+	}
 	if dec.Miner != nil {
 		c.Miner = *dec.Miner
 	}
@@ -227,6 +232,9 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error {
 	if dec.RPCGasCap != nil {
 		c.RPCGasCap = dec.RPCGasCap
 	}
+	if dec.RPCTxFeeCap != nil {
+		c.RPCTxFeeCap = *dec.RPCTxFeeCap
+	}
 	if dec.Checkpoint != nil {
 		c.Checkpoint = dec.Checkpoint
 	}
diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go
index 7d17c9cd21843aab468f07a2d4bc7df14dbf9ac3..f266917109a3e6dc2e94d2dcfb7123d6d2f1349a 100644
--- a/internal/ethapi/api.go
+++ b/internal/ethapi/api.go
@@ -1520,6 +1520,13 @@ func (args *SendTxArgs) toTransaction() *types.Transaction {
 
 // SubmitTransaction is a helper function that submits tx to txPool and logs a message.
 func SubmitTransaction(ctx context.Context, b Backend, tx *types.Transaction) (common.Hash, error) {
+	// If the transaction fee cap is already specified, ensure the
+	// fee of the given transaction is _reasonable_.
+	feeEth := new(big.Float).Quo(new(big.Float).SetInt(new(big.Int).Mul(tx.GasPrice(), new(big.Int).SetUint64(tx.Gas()))), new(big.Float).SetInt(big.NewInt(params.Ether)))
+	feeFloat, _ := feeEth.Float64()
+	if b.RPCTxFeeCap() != 0 && feeFloat > b.RPCTxFeeCap() {
+		return common.Hash{}, fmt.Errorf("tx fee (%.2f ether) exceeds the configured cap (%.2f ether)", feeFloat, b.RPCTxFeeCap())
+	}
 	if err := b.SendTx(ctx, tx); err != nil {
 		return common.Hash{}, err
 	}
diff --git a/internal/ethapi/backend.go b/internal/ethapi/backend.go
index 245091df35a37af5e358a8d75f782ee570d07dae..5f5f9a6eeff5b7a2db8ac9281c3f7b19019e6af7 100644
--- a/internal/ethapi/backend.go
+++ b/internal/ethapi/backend.go
@@ -45,7 +45,8 @@ type Backend interface {
 	ChainDb() ethdb.Database
 	AccountManager() *accounts.Manager
 	ExtRPCEnabled() bool
-	RPCGasCap() *big.Int // global gas cap for eth_call over rpc: DoS protection
+	RPCGasCap() *big.Int  // global gas cap for eth_call over rpc: DoS protection
+	RPCTxFeeCap() float64 // global tx fee cap for all transaction related APIs
 
 	// Blockchain API
 	SetHead(number uint64)
diff --git a/les/api_backend.go b/les/api_backend.go
index 756beaf6a78d178b0295655a8af141090dd2eb87..75f255cd92df981e2661079a7d3ad37c5dfa3020 100644
--- a/les/api_backend.go
+++ b/les/api_backend.go
@@ -262,6 +262,10 @@ func (b *LesApiBackend) RPCGasCap() *big.Int {
 	return b.eth.config.RPCGasCap
 }
 
+func (b *LesApiBackend) RPCTxFeeCap() float64 {
+	return b.eth.config.RPCTxFeeCap
+}
+
 func (b *LesApiBackend) BloomStatus() (uint64, uint64) {
 	if b.eth.bloomIndexer == nil {
 		return 0, 0