transaction_args_test.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342
  1. // Copyright 2022 The go-ethereum Authors
  2. // This file is part of the go-ethereum library.
  3. //
  4. // The go-ethereum library is free software: you can redistribute it and/or modify
  5. // it under the terms of the GNU Lesser General Public License as published by
  6. // the Free Software Foundation, either version 3 of the License, or
  7. // (at your option) any later version.
  8. //
  9. // The go-ethereum library is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU Lesser General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU Lesser General Public License
  15. // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
  16. package ethapi
  17. import (
  18. "context"
  19. "fmt"
  20. "math/big"
  21. "reflect"
  22. "testing"
  23. "time"
  24. "github.com/ethereum/go-ethereum"
  25. "github.com/ethereum/go-ethereum/accounts"
  26. "github.com/ethereum/go-ethereum/common"
  27. "github.com/ethereum/go-ethereum/common/hexutil"
  28. "github.com/ethereum/go-ethereum/consensus"
  29. "github.com/ethereum/go-ethereum/core"
  30. "github.com/ethereum/go-ethereum/core/bloombits"
  31. "github.com/ethereum/go-ethereum/core/state"
  32. "github.com/ethereum/go-ethereum/core/types"
  33. "github.com/ethereum/go-ethereum/core/vm"
  34. "github.com/ethereum/go-ethereum/ethdb"
  35. "github.com/ethereum/go-ethereum/event"
  36. "github.com/ethereum/go-ethereum/params"
  37. "github.com/ethereum/go-ethereum/rpc"
  38. )
  39. // TestSetFeeDefaults tests the logic for filling in default fee values works as expected.
  40. func TestSetFeeDefaults(t *testing.T) {
  41. type test struct {
  42. name string
  43. isLondon bool
  44. in *TransactionArgs
  45. want *TransactionArgs
  46. err error
  47. }
  48. var (
  49. b = newBackendMock()
  50. fortytwo = (*hexutil.Big)(big.NewInt(42))
  51. maxFee = (*hexutil.Big)(new(big.Int).Add(new(big.Int).Mul(b.current.BaseFee, big.NewInt(2)), fortytwo.ToInt()))
  52. al = &types.AccessList{types.AccessTuple{Address: common.Address{0xaa}, StorageKeys: []common.Hash{{0x01}}}}
  53. )
  54. tests := []test{
  55. // Legacy txs
  56. {
  57. "legacy tx pre-London",
  58. false,
  59. &TransactionArgs{},
  60. &TransactionArgs{GasPrice: fortytwo},
  61. nil,
  62. },
  63. {
  64. "legacy tx post-London, explicit gas price",
  65. true,
  66. &TransactionArgs{GasPrice: fortytwo},
  67. &TransactionArgs{GasPrice: fortytwo},
  68. nil,
  69. },
  70. // Access list txs
  71. {
  72. "access list tx pre-London",
  73. false,
  74. &TransactionArgs{AccessList: al},
  75. &TransactionArgs{AccessList: al, GasPrice: fortytwo},
  76. nil,
  77. },
  78. {
  79. "access list tx post-London, explicit gas price",
  80. false,
  81. &TransactionArgs{AccessList: al, GasPrice: fortytwo},
  82. &TransactionArgs{AccessList: al, GasPrice: fortytwo},
  83. nil,
  84. },
  85. {
  86. "access list tx post-London",
  87. true,
  88. &TransactionArgs{AccessList: al},
  89. &TransactionArgs{AccessList: al, MaxFeePerGas: maxFee, MaxPriorityFeePerGas: fortytwo},
  90. nil,
  91. },
  92. {
  93. "access list tx post-London, only max fee",
  94. true,
  95. &TransactionArgs{AccessList: al, MaxFeePerGas: maxFee},
  96. &TransactionArgs{AccessList: al, MaxFeePerGas: maxFee, MaxPriorityFeePerGas: fortytwo},
  97. nil,
  98. },
  99. {
  100. "access list tx post-London, only priority fee",
  101. true,
  102. &TransactionArgs{AccessList: al, MaxFeePerGas: maxFee},
  103. &TransactionArgs{AccessList: al, MaxFeePerGas: maxFee, MaxPriorityFeePerGas: fortytwo},
  104. nil,
  105. },
  106. // Dynamic fee txs
  107. {
  108. "dynamic tx post-London",
  109. true,
  110. &TransactionArgs{},
  111. &TransactionArgs{MaxFeePerGas: maxFee, MaxPriorityFeePerGas: fortytwo},
  112. nil,
  113. },
  114. {
  115. "dynamic tx post-London, only max fee",
  116. true,
  117. &TransactionArgs{MaxFeePerGas: maxFee},
  118. &TransactionArgs{MaxFeePerGas: maxFee, MaxPriorityFeePerGas: fortytwo},
  119. nil,
  120. },
  121. {
  122. "dynamic tx post-London, only priority fee",
  123. true,
  124. &TransactionArgs{MaxFeePerGas: maxFee},
  125. &TransactionArgs{MaxFeePerGas: maxFee, MaxPriorityFeePerGas: fortytwo},
  126. nil,
  127. },
  128. {
  129. "dynamic fee tx pre-London, maxFee set",
  130. false,
  131. &TransactionArgs{MaxFeePerGas: maxFee},
  132. nil,
  133. fmt.Errorf("maxFeePerGas and maxPriorityFeePerGas are not valid before London is active"),
  134. },
  135. {
  136. "dynamic fee tx pre-London, priorityFee set",
  137. false,
  138. &TransactionArgs{MaxPriorityFeePerGas: fortytwo},
  139. nil,
  140. fmt.Errorf("maxFeePerGas and maxPriorityFeePerGas are not valid before London is active"),
  141. },
  142. {
  143. "dynamic fee tx, maxFee < priorityFee",
  144. true,
  145. &TransactionArgs{MaxFeePerGas: maxFee, MaxPriorityFeePerGas: (*hexutil.Big)(big.NewInt(1000))},
  146. nil,
  147. fmt.Errorf("maxFeePerGas (0x3e) < maxPriorityFeePerGas (0x3e8)"),
  148. },
  149. {
  150. "dynamic fee tx, maxFee < priorityFee while setting default",
  151. true,
  152. &TransactionArgs{MaxFeePerGas: (*hexutil.Big)(big.NewInt(7))},
  153. nil,
  154. fmt.Errorf("maxFeePerGas (0x7) < maxPriorityFeePerGas (0x2a)"),
  155. },
  156. // Misc
  157. {
  158. "set all fee parameters",
  159. false,
  160. &TransactionArgs{GasPrice: fortytwo, MaxFeePerGas: maxFee, MaxPriorityFeePerGas: fortytwo},
  161. nil,
  162. fmt.Errorf("both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified"),
  163. },
  164. {
  165. "set gas price and maxPriorityFee",
  166. false,
  167. &TransactionArgs{GasPrice: fortytwo, MaxPriorityFeePerGas: fortytwo},
  168. nil,
  169. fmt.Errorf("both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified"),
  170. },
  171. {
  172. "set gas price and maxFee",
  173. true,
  174. &TransactionArgs{GasPrice: fortytwo, MaxFeePerGas: maxFee},
  175. nil,
  176. fmt.Errorf("both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified"),
  177. },
  178. }
  179. ctx := context.Background()
  180. for i, test := range tests {
  181. if test.isLondon {
  182. b.activateLondon()
  183. } else {
  184. b.deactivateLondon()
  185. }
  186. got := test.in
  187. err := got.setFeeDefaults(ctx, b)
  188. if err != nil && err.Error() == test.err.Error() {
  189. // Test threw expected error.
  190. continue
  191. } else if err != nil {
  192. t.Fatalf("test %d (%s): unexpected error: %s", i, test.name, err)
  193. }
  194. if !reflect.DeepEqual(got, test.want) {
  195. t.Fatalf("test %d (%s): did not fill defaults as expected: (got: %v, want: %v)", i, test.name, got, test.want)
  196. }
  197. }
  198. }
  199. type backendMock struct {
  200. current *types.Header
  201. config *params.ChainConfig
  202. }
  203. func newBackendMock() *backendMock {
  204. config := &params.ChainConfig{
  205. ChainID: big.NewInt(42),
  206. HomesteadBlock: big.NewInt(0),
  207. DAOForkBlock: nil,
  208. DAOForkSupport: true,
  209. EIP150Block: big.NewInt(0),
  210. EIP155Block: big.NewInt(0),
  211. EIP158Block: big.NewInt(0),
  212. ByzantiumBlock: big.NewInt(0),
  213. ConstantinopleBlock: big.NewInt(0),
  214. PetersburgBlock: big.NewInt(0),
  215. IstanbulBlock: big.NewInt(0),
  216. MuirGlacierBlock: big.NewInt(0),
  217. BerlinBlock: big.NewInt(0),
  218. LondonBlock: big.NewInt(1000),
  219. }
  220. return &backendMock{
  221. current: &types.Header{
  222. Difficulty: big.NewInt(10000000000),
  223. Number: big.NewInt(1100),
  224. GasLimit: 8_000_000,
  225. GasUsed: 8_000_000,
  226. Time: 555,
  227. Extra: make([]byte, 32),
  228. BaseFee: big.NewInt(10),
  229. },
  230. config: config,
  231. }
  232. }
  233. func (b *backendMock) activateLondon() {
  234. b.current.Number = big.NewInt(1100)
  235. }
  236. func (b *backendMock) deactivateLondon() {
  237. b.current.Number = big.NewInt(900)
  238. }
  239. func (b *backendMock) SuggestGasTipCap(ctx context.Context) (*big.Int, error) {
  240. return big.NewInt(42), nil
  241. }
  242. func (b *backendMock) CurrentHeader() *types.Header { return b.current }
  243. func (b *backendMock) ChainConfig() *params.ChainConfig { return b.config }
  244. // Other methods needed to implement Backend interface.
  245. func (b *backendMock) SyncProgress() ethereum.SyncProgress { return ethereum.SyncProgress{} }
  246. func (b *backendMock) FeeHistory(ctx context.Context, blockCount int, lastBlock rpc.BlockNumber, rewardPercentiles []float64) (*big.Int, [][]*big.Int, []*big.Int, []float64, error) {
  247. return nil, nil, nil, nil, nil
  248. }
  249. func (b *backendMock) ChainDb() ethdb.Database { return nil }
  250. func (b *backendMock) AccountManager() *accounts.Manager { return nil }
  251. func (b *backendMock) ExtRPCEnabled() bool { return false }
  252. func (b *backendMock) RPCGasCap() uint64 { return 0 }
  253. func (b *backendMock) RPCEVMTimeout() time.Duration { return time.Second }
  254. func (b *backendMock) RPCTxFeeCap() float64 { return 0 }
  255. func (b *backendMock) UnprotectedAllowed() bool { return false }
  256. func (b *backendMock) SetHead(number uint64) {}
  257. func (b *backendMock) HeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Header, error) {
  258. return nil, nil
  259. }
  260. func (b *backendMock) HeaderByHash(ctx context.Context, hash common.Hash) (*types.Header, error) {
  261. return nil, nil
  262. }
  263. func (b *backendMock) HeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*types.Header, error) {
  264. return nil, nil
  265. }
  266. func (b *backendMock) CurrentBlock() *types.Block { return nil }
  267. func (b *backendMock) BlockByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Block, error) {
  268. return nil, nil
  269. }
  270. func (b *backendMock) BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) {
  271. return nil, nil
  272. }
  273. func (b *backendMock) BlockByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*types.Block, error) {
  274. return nil, nil
  275. }
  276. func (b *backendMock) StateAndHeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*state.StateDB, *types.Header, error) {
  277. return nil, nil, nil
  278. }
  279. func (b *backendMock) StateAndHeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*state.StateDB, *types.Header, error) {
  280. return nil, nil, nil
  281. }
  282. func (b *backendMock) PendingBlockAndReceipts() (*types.Block, types.Receipts) { return nil, nil }
  283. func (b *backendMock) GetReceipts(ctx context.Context, hash common.Hash) (types.Receipts, error) {
  284. return nil, nil
  285. }
  286. func (b *backendMock) GetLogs(ctx context.Context, blockHash common.Hash, number uint64) ([][]*types.Log, error) {
  287. return nil, nil
  288. }
  289. func (b *backendMock) GetTd(ctx context.Context, hash common.Hash) *big.Int { return nil }
  290. func (b *backendMock) GetEVM(ctx context.Context, msg core.Message, state *state.StateDB, header *types.Header, vmConfig *vm.Config, blockContext *vm.BlockContext) (*vm.EVM, func() error, error) {
  291. return nil, nil, nil
  292. }
  293. func (b *backendMock) SubscribeChainEvent(ch chan<- core.ChainEvent) event.Subscription { return nil }
  294. func (b *backendMock) SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) event.Subscription {
  295. return nil
  296. }
  297. func (b *backendMock) SubscribeChainSideEvent(ch chan<- core.ChainSideEvent) event.Subscription {
  298. return nil
  299. }
  300. func (b *backendMock) SendTx(ctx context.Context, signedTx *types.Transaction) error { return nil }
  301. func (b *backendMock) GetTransaction(ctx context.Context, txHash common.Hash) (*types.Transaction, common.Hash, uint64, uint64, error) {
  302. return nil, [32]byte{}, 0, 0, nil
  303. }
  304. func (b *backendMock) GetPoolTransactions() (types.Transactions, error) { return nil, nil }
  305. func (b *backendMock) GetPoolTransaction(txHash common.Hash) *types.Transaction { return nil }
  306. func (b *backendMock) GetPoolNonce(ctx context.Context, addr common.Address) (uint64, error) {
  307. return 0, nil
  308. }
  309. func (b *backendMock) Stats() (pending int, queued int) { return 0, 0 }
  310. func (b *backendMock) TxPoolContent() (map[common.Address]types.Transactions, map[common.Address]types.Transactions) {
  311. return nil, nil
  312. }
  313. func (b *backendMock) TxPoolContentFrom(addr common.Address) (types.Transactions, types.Transactions) {
  314. return nil, nil
  315. }
  316. func (b *backendMock) SubscribeNewTxsEvent(chan<- core.NewTxsEvent) event.Subscription { return nil }
  317. func (b *backendMock) BloomStatus() (uint64, uint64) { return 0, 0 }
  318. func (b *backendMock) ServiceFilter(ctx context.Context, session *bloombits.MatcherSession) {}
  319. func (b *backendMock) SubscribeLogsEvent(ch chan<- []*types.Log) event.Subscription { return nil }
  320. func (b *backendMock) SubscribePendingLogsEvent(ch chan<- []*types.Log) event.Subscription {
  321. return nil
  322. }
  323. func (b *backendMock) SubscribeRemovedLogsEvent(ch chan<- core.RemovedLogsEvent) event.Subscription {
  324. return nil
  325. }
  326. func (b *backendMock) Engine() consensus.Engine { return nil }