@@ -6,37 +6,66 @@ package c
66import (
77 "math/big"
88 "strings"
9+ "time"
910
1011 "github.com/ava-labs/coreth/core/types"
1112 "github.com/ava-labs/coreth/params"
13+ "github.com/ava-labs/coreth/plugin/evm/upgrade/acp176"
14+ "github.com/ava-labs/coreth/plugin/evm/upgrade/cortina"
1215 "github.com/ethereum/go-ethereum/accounts/abi"
1316 "github.com/ethereum/go-ethereum/common"
1417 "github.com/onsi/ginkgo/v2"
1518 "github.com/stretchr/testify/require"
1619 "go.uber.org/zap"
1720
21+ "github.com/ava-labs/avalanchego/api/info"
1822 "github.com/ava-labs/avalanchego/tests/fixture/e2e"
1923 "github.com/ava-labs/avalanchego/tests/fixture/tmpnet"
2024)
2125
22- // This test uses the compiled bin for `hashing .sol` as
23- // well as its ABI contained in `hashing_contract .go`.
26+ // This test uses the compiled bytecode for `consume_gas .sol` as well as its ABI
27+ // contained in `consume_gas .go`.
2428
2529var _ = e2e .DescribeCChain ("[Dynamic Fees]" , func () {
2630 tc := e2e .NewTestContext ()
2731 require := require .New (tc )
2832
29- // Need a gas limit much larger than the standard 21_000 to enable
30- // the contract to induce a gas price increase
31- const largeGasLimit = uint64 (8_000_000 )
33+ const (
34+ // maxFeePerGas is the maximum fee that transactions issued by this test
35+ // will be willing to pay. The actual value doesn't really matter, it
36+ // just needs to be higher than the `targetGasPrice` calculated below.
37+ maxFeePerGas = 1000 * params .GWei
38+ // minFeePerGas is the minimum fee that transactions issued by this test
39+ // will pay. The mempool enforces that this value is non-zero.
40+ minFeePerGas = 1 * params .Wei
3241
33- // TODO(marun) What is the significance of this value?
34- gasTip := big .NewInt (1000 * params .GWei )
42+ // expectedGasPriceIncreaseNumerator/expectedGasPriceIncreaseDenominator
43+ // is the multiplier that the gas price is attempted to reach. So if the
44+ // initial gas price is 5 GWei, the test will attempt to increase the
45+ // gas price to 6 GWei.
46+ expectedGasPriceIncreaseNumerator = 6
47+ expectedGasPriceIncreaseDenominator = 5
48+ )
49+ var (
50+ bigExpectedGasPriceIncreaseNumerator = big .NewInt (expectedGasPriceIncreaseNumerator )
51+ bigExpectedGasPriceIncreaseDenominator = big .NewInt (expectedGasPriceIncreaseDenominator )
52+ bigExpectedGasPriceIncreaseDenominatorMinus1 = big .NewInt (expectedGasPriceIncreaseDenominator - 1 )
53+
54+ gasFeeCap = big .NewInt (maxFeePerGas )
55+ gasTipCap = big .NewInt (minFeePerGas )
56+ )
3557
3658 ginkgo .It ("should ensure that the gas price is affected by load" , func () {
3759 tc .By ("creating a new private network to ensure isolation from other tests" )
60+ env := e2e .GetEnv (tc )
61+ publicNetwork := env .GetNetwork ()
62+
3863 privateNetwork := tmpnet .NewDefaultNetwork ("avalanchego-e2e-dynamic-fees" )
39- e2e .GetEnv (tc ).StartPrivateNetwork (privateNetwork )
64+ // Copy over the defaults from the normal test suite to include settings
65+ // like the upgrade config.
66+ privateNetwork .DefaultFlags = tmpnet.FlagsMap {}
67+ privateNetwork .DefaultFlags .SetDefaults (publicNetwork .DefaultFlags )
68+ env .StartPrivateNetwork (privateNetwork )
4069
4170 // Avoid emitting a spec-scoped metrics link for the shared
4271 // network since the link emitted by the start of the private
@@ -60,116 +89,167 @@ var _ = e2e.DescribeCChain("[Dynamic Fees]", func() {
6089 tc .By ("initializing a transaction signer" )
6190 cChainID , err := ethClient .ChainID (tc .DefaultContext ())
6291 require .NoError (err )
63- signer := types .NewEIP155Signer (cChainID )
92+ signer := types .NewLondonSigner (cChainID )
6493 ecdsaKey := key .ToECDSA ()
6594 sign := func (tx * types.Transaction ) * types.Transaction {
6695 signedTx , err := types .SignTx (tx , signer , ecdsaKey )
6796 require .NoError (err )
6897 return signedTx
6998 }
7099
100+ // gasLimit is the maximum amount of gas that can be used in a block.
101+ var gasLimit uint64
102+ tc .By ("checking if Fortuna is activated" , func () {
103+ infoClient := info .NewClient (nodeURI .URI )
104+ upgrades , err := infoClient .Upgrades (tc .DefaultContext ())
105+ require .NoError (err )
106+
107+ now := time .Now ()
108+ if upgrades .IsFUpgradeActivated (now ) {
109+ gasLimit = acp176 .MinMaxCapacity
110+ } else {
111+ gasLimit = cortina .GasLimit
112+ }
113+ })
114+ tc .Log ().Info ("set gas limit" ,
115+ zap .Uint64 ("gasLimit" , gasLimit ),
116+ )
117+
71118 var contractAddress common.Address
72119 tc .By ("deploying an expensive contract" , func () {
73120 // Create transaction
74121 nonce , err := ethClient .AcceptedNonceAt (tc .DefaultContext (), ethAddress )
75122 require .NoError (err )
76- compiledContract := common .Hex2Bytes (hashingCompiledContract )
77- tx := types .NewTx (& types.LegacyTx {
78- Nonce : nonce ,
79- GasPrice : gasTip ,
80- Gas : largeGasLimit ,
81- Value : common .Big0 ,
82- Data : compiledContract ,
123+ compiledContract := common .Hex2Bytes (consumeGasCompiledContract )
124+ tx := types .NewTx (& types.DynamicFeeTx {
125+ ChainID : cChainID ,
126+ Nonce : nonce ,
127+ GasTipCap : gasTipCap ,
128+ GasFeeCap : gasFeeCap ,
129+ Gas : gasLimit ,
130+ To : nil , // contract creation
131+ Data : compiledContract ,
83132 })
84133
85134 // Send the transaction and wait for acceptance
86135 signedTx := sign (tx )
87136 receipt := e2e .SendEthTransaction (tc , ethClient , signedTx )
137+ require .Equal (types .ReceiptStatusSuccessful , receipt .Status )
88138
89139 contractAddress = receipt .ContractAddress
90140 })
91141
92- var gasPrice * big.Int
93- tc .By ("calling the expensive contract repeatedly until a gas price increase is detected" , func () {
142+ latest , err := ethClient .HeaderByNumber (tc .DefaultContext (), nil )
143+ require .NoError (err )
144+
145+ initialGasPrice := latest .BaseFee
146+ targetGasPrice := new (big.Int ).Set (initialGasPrice )
147+ targetGasPrice .Mul (targetGasPrice , bigExpectedGasPriceIncreaseNumerator )
148+ targetGasPrice .Add (targetGasPrice , bigExpectedGasPriceIncreaseDenominatorMinus1 )
149+ targetGasPrice .Div (targetGasPrice , bigExpectedGasPriceIncreaseDenominator )
150+
151+ tc .Log ().Info ("initializing gas prices" ,
152+ zap .Stringer ("initialPrice" , initialGasPrice ),
153+ zap .Stringer ("targetPrice" , targetGasPrice ),
154+ )
155+
156+ tc .By ("calling the contract repeatedly until a sufficient gas price increase is detected" , func () {
94157 // Evaluate the bytes representation of the contract
95- hashingABI , err := abi .JSON (strings .NewReader (hashingABIJson ))
158+ hashingABI , err := abi .JSON (strings .NewReader (consumeGasABIJson ))
96159 require .NoError (err )
97- contractData , err := hashingABI .Pack ("hashIt" )
160+ contractData , err := hashingABI .Pack (consumeGasFunction )
98161 require .NoError (err )
99162
100- var initialGasPrice * big.Int
101163 tc .Eventually (func () bool {
102164 // Check the gas price
103- var err error
104- gasPrice , err = ethClient .SuggestGasPrice (tc .DefaultContext ())
165+ latest , err := ethClient .HeaderByNumber (tc .DefaultContext (), nil )
105166 require .NoError (err )
106- if initialGasPrice == nil {
107- initialGasPrice = gasPrice
108- tc .Log ().Info ("initial gas price" ,
109- zap .Uint64 ("price" , initialGasPrice .Uint64 ()),
110- )
111- } else if gasPrice .Cmp (initialGasPrice ) > 0 {
167+
168+ // If the gas price has increased, stop the loop.
169+ if latest .BaseFee .Cmp (targetGasPrice ) >= 0 {
112170 tc .Log ().Info ("gas price has increased" ,
113- zap .Uint64 ("price" , gasPrice .Uint64 ()),
171+ zap .Stringer ("initialPrice" , initialGasPrice ),
172+ zap .Stringer ("targetPrice" , targetGasPrice ),
173+ zap .Stringer ("newPrice" , latest .BaseFee ),
114174 )
115175 return true
116176 }
117177
178+ tc .Log ().Info ("gas price hasn't sufficiently increased" ,
179+ zap .Stringer ("initialPrice" , initialGasPrice ),
180+ zap .Stringer ("newPrice" , latest .BaseFee ),
181+ zap .Stringer ("targetPrice" , targetGasPrice ),
182+ )
183+
118184 // Create the transaction
119185 nonce , err := ethClient .AcceptedNonceAt (tc .DefaultContext (), ethAddress )
120186 require .NoError (err )
121- tx := types .NewTx (& types.LegacyTx {
122- Nonce : nonce ,
123- GasPrice : gasTip ,
124- Gas : largeGasLimit ,
125- To : & contractAddress ,
126- Value : common .Big0 ,
127- Data : contractData ,
187+ tx := types .NewTx (& types.DynamicFeeTx {
188+ ChainID : cChainID ,
189+ Nonce : nonce ,
190+ GasTipCap : gasTipCap ,
191+ GasFeeCap : gasFeeCap ,
192+ Gas : gasLimit ,
193+ To : & contractAddress ,
194+ Data : contractData ,
128195 })
129196
130197 // Send the transaction and wait for acceptance
131198 signedTx := sign (tx )
132- _ = e2e .SendEthTransaction (tc , ethClient , signedTx )
199+ receipt := e2e .SendEthTransaction (tc , ethClient , signedTx )
200+ // The transaction should have run out of gas
201+ require .Equal (types .ReceiptStatusFailed , receipt .Status )
133202
134203 // The gas price will be checked at the start of the next iteration
135204 return false
136205 }, e2e .DefaultTimeout , e2e .DefaultPollingInterval , "failed to see gas price increase before timeout" )
137206 })
138207
139- tc .By ("waiting for the gas price to decrease..." , func () {
140- initialGasPrice := gasPrice
208+ // Create a recipient address
209+ var (
210+ recipientKey = e2e .NewPrivateKey (tc )
211+ recipientEthAddress = recipientKey .EthAddress ()
212+ )
213+ tc .By ("sending small transactions until a sufficient gas price decrease is detected" , func () {
141214 tc .Eventually (func () bool {
142- var err error
143- gasPrice , err = ethClient .SuggestGasPrice (tc .DefaultContext ())
215+ // Check the gas price
216+ latest , err : = ethClient .HeaderByNumber (tc .DefaultContext (), nil )
144217 require .NoError (err )
145- return initialGasPrice .Cmp (gasPrice ) > 0
146- }, e2e .DefaultTimeout , e2e .DefaultPollingInterval , "failed to see gas price decrease before timeout" )
147- tc .Log ().Info ("gas price has decreased" ,
148- zap .Uint64 ("price" , gasPrice .Uint64 ()),
149- )
150- })
151218
152- tc .By ("sending funds at the current gas price" , func () {
153- // Create a recipient address
154- var (
155- recipientKey = e2e .NewPrivateKey (tc )
156- recipientEthAddress = recipientKey .EthAddress ()
157- )
219+ // If the gas price has decreased, stop the loop.
220+ if latest .BaseFee .Cmp (initialGasPrice ) <= 0 {
221+ tc .Log ().Info ("gas price has decreased" ,
222+ zap .Stringer ("initialPrice" , initialGasPrice ),
223+ zap .Stringer ("newPrice" , latest .BaseFee ),
224+ )
225+ return true
226+ }
227+
228+ tc .Log ().Info ("gas price hasn't sufficiently decreased" ,
229+ zap .Stringer ("initialPrice" , initialGasPrice ),
230+ zap .Stringer ("newPrice" , latest .BaseFee ),
231+ )
158232
159- // Create transaction
160- nonce , err := ethClient .AcceptedNonceAt (tc .DefaultContext (), ethAddress )
161- require .NoError (err )
162- tx := types .NewTx (& types.LegacyTx {
163- Nonce : nonce ,
164- GasPrice : gasPrice ,
165- Gas : e2e .DefaultGasLimit ,
166- To : & recipientEthAddress ,
167- Value : common .Big0 ,
168- })
233+ // Create the transaction
234+ nonce , err := ethClient .AcceptedNonceAt (tc .DefaultContext (), ethAddress )
235+ require .NoError (err )
236+ tx := types .NewTx (& types.DynamicFeeTx {
237+ ChainID : cChainID ,
238+ Nonce : nonce ,
239+ GasTipCap : gasTipCap ,
240+ GasFeeCap : gasFeeCap ,
241+ Gas : e2e .DefaultGasLimit ,
242+ To : & recipientEthAddress ,
243+ })
169244
170- // Send the transaction and wait for acceptance
171- signedTx := sign (tx )
172- _ = e2e .SendEthTransaction (tc , ethClient , signedTx )
245+ // Send the transaction and wait for acceptance
246+ signedTx := sign (tx )
247+ receipt := e2e .SendEthTransaction (tc , ethClient , signedTx )
248+ require .Equal (types .ReceiptStatusSuccessful , receipt .Status )
249+
250+ // The gas price will be checked at the start of the next iteration
251+ return false
252+ }, e2e .DefaultTimeout , e2e .DefaultPollingInterval , "failed to see gas price decrease before timeout" )
173253 })
174254
175255 _ = e2e .CheckBootstrapIsPossible (tc , privateNetwork )
0 commit comments