Transaction7702.createTransaction() ignores accessList parameter - the field remains null in constructed object
Transaction7702.createTransaction() accepts an accessList parameter but does NOT actually set it to the constructed object. The accessList field (inherited from Transaction2930) remains null, causing incorrect RLP encoding when the transaction is serialized.
Steps To Reproduce
- Create a Transaction7702 using
Transaction7702.createTransaction() with a non-empty accessList
- Call
transaction.getAccessList() on the returned object
- Observe that it returns
null instead of the provided access list
Sample code
import org.web3j.crypto.transaction.type.Transaction7702;
import org.web3j.crypto.AccessListObject;
import java.math.BigInteger;
import java.util.Collections;
import java.util.List;
public class ReproduceIssue {
public static void main(String[] args) {
List<AccessListObject> accessList = Collections.singletonList(
new AccessListObject(
"0xde0b295669a9fd93d5f28d9ec85e40f4cb697bae",
Collections.singletonList("0x0000000000000000000000000000000000000000000000000000000000000003")
)
);
Transaction7702 tx = Transaction7702.createTransaction(
42L, // chainId
BigInteger.valueOf(123), // nonce
BigInteger.valueOf(5_000_000_000L), // maxPriorityFeePerGas
BigInteger.valueOf(30_000_000_000L), // maxFeePerGas
BigInteger.valueOf(1_000_000), // gasLimit
"0x627306090abab3a6e1400e9345bc60c78a8bef57", // to
BigInteger.ZERO, // value
"0xdeadbeef", // data
accessList, // <-- This is ignored!
Collections.emptyList() // authorizationList
);
// This returns null, but should return the accessList provided above
List<AccessListObject> actualAccessList = tx.getAccessList();
System.out.println("Access list is null: " + (actualAccessList == null)); // prints "true"
}
}
Expected behavior
The accessList field should be set to the provided value, and tx.getAccessList() should return the non-empty access list passed to createTransaction().
Actual behavior
The accessList parameter is accepted but silently ignored. The field remains null because Transaction7702.createTransaction() doesn't set the inherited accessList field from Transaction2930.
Root cause: Looking at the source code, Transaction7702.createTransaction() constructs the object but never calls setAccessList() on the parent class.
Environment
- Web3j version: 5.0.2 (latest)
- Java version: 21
- Operating System: macOS / Linux
Additional context
Related code in Transaction2930
Transaction7702 extends Transaction2930, and the accessList field is defined in the parent class. The Transaction2930.createTransaction() method correctly sets this field, but Transaction7702.createTransaction() appears to have missed it.
Impact
This causes incorrect RLP encoding when encoding EIP-7702 transactions that should include an access list, potentially leading to:
- Wrong transaction hash calculation
- Failed transaction validation
- Incorrect gas estimation
Suggested fix
Fix the Transaction7702 constructor to pass accessList to the parent class Transaction1559:
protected Transaction7702(
long chainId,
BigInteger nonce,
BigInteger maxPriorityFeePerGas,
BigInteger maxFeePerGas,
BigInteger gasLimit,
String to,
BigInteger value,
String data,
List<AccessListObject> accessList,
List<AuthorizationTuple> authorizationList) {
// Pass accessList to Transaction1559 constructor (9-parameter version)
super(chainId, nonce, gasLimit, to, value, data, maxPriorityFeePerGas, maxFeePerGas, accessList);
this.authorizationList = authorizationList;
}
Root cause: The current code calls super(chainId, nonce, gasLimit, to, value, data, maxPriorityFeePerGas, maxFeePerGas) which invokes the 8-parameter constructor of Transaction1559 that internally passes Collections.emptyList() to the grandparent class. It should instead call the 9-parameter constructor that accepts and passes the accessList parameter.
Transaction7702.createTransaction() ignores accessList parameter - the field remains null in constructed object
Transaction7702.createTransaction() accepts an
accessListparameter but does NOT actually set it to the constructed object. TheaccessListfield (inherited fromTransaction2930) remainsnull, causing incorrect RLP encoding when the transaction is serialized.Steps To Reproduce
Transaction7702.createTransaction()with a non-empty accessListtransaction.getAccessList()on the returned objectnullinstead of the provided access listSample code
Expected behavior
The
accessListfield should be set to the provided value, andtx.getAccessList()should return the non-empty access list passed tocreateTransaction().Actual behavior
The
accessListparameter is accepted but silently ignored. The field remainsnullbecauseTransaction7702.createTransaction()doesn't set the inheritedaccessListfield fromTransaction2930.Root cause: Looking at the source code,
Transaction7702.createTransaction()constructs the object but never callssetAccessList()on the parent class.Environment
Additional context
Related code in Transaction2930
Transaction7702extendsTransaction2930, and theaccessListfield is defined in the parent class. TheTransaction2930.createTransaction()method correctly sets this field, butTransaction7702.createTransaction()appears to have missed it.Impact
This causes incorrect RLP encoding when encoding EIP-7702 transactions that should include an access list, potentially leading to:
Suggested fix
Fix the
Transaction7702constructor to passaccessListto the parent classTransaction1559:Root cause: The current code calls
super(chainId, nonce, gasLimit, to, value, data, maxPriorityFeePerGas, maxFeePerGas)which invokes the 8-parameter constructor ofTransaction1559that internally passesCollections.emptyList()to the grandparent class. It should instead call the 9-parameter constructor that accepts and passes theaccessListparameter.