Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ public void shouldReturnErrorWithInvalidChainId() {
.withChainId(BLOCKCHAIN.getChainId().add(BigInteger.ONE))
.withFrom(Address.fromHexString("0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b"))
.withTo(Address.fromHexString("0x8888f1f195afa192cfee860698584c030f4c9db1"))
.withMaxFeePerGas(Wei.ONE)
.withValue(Wei.ONE)
.build();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -296,9 +296,6 @@ public Optional<TransactionSimulatorResult> processWithWorldUpdater(
final long simulationGasCap =
calculateSimulationGasCap(callParams.getGasLimit(), blockHeaderToProcess.getGasLimit());

final Wei value = callParams.getValue() != null ? callParams.getValue() : Wei.ZERO;
final Bytes payload = callParams.getPayload() != null ? callParams.getPayload() : Bytes.EMPTY;

final MainnetTransactionProcessor transactionProcessor =
protocolSchedule.getByBlockHeader(blockHeaderToProcess).getTransactionProcessor();

Expand All @@ -322,8 +319,6 @@ public Optional<TransactionSimulatorResult> processWithWorldUpdater(
senderAddress,
nonce,
simulationGasCap,
value,
payload,
blobGasPrice);
if (maybeTransaction.isEmpty()) {
return Optional.empty();
Expand Down Expand Up @@ -404,9 +399,11 @@ private Optional<Transaction> buildTransaction(
final Address senderAddress,
final long nonce,
final long gasLimit,
final Wei value,
final Bytes payload,
final Wei blobGasPrice) {

final Wei value = callParams.getValue() != null ? callParams.getValue() : Wei.ZERO;
final Bytes payload = callParams.getPayload() != null ? callParams.getPayload() : Bytes.EMPTY;

final Transaction.Builder transactionBuilder =
Transaction.builder()
.nonce(nonce)
Expand Down Expand Up @@ -437,18 +434,21 @@ private Optional<Transaction> buildTransaction(
maxPriorityFeePerGas = callParams.getMaxPriorityFeePerGas().orElse(gasPrice);
maxFeePerBlobGas = callParams.getMaxFeePerBlobGas().orElse(blobGasPrice);
}
if (header.getBaseFee().isEmpty()) {

if (shouldSetGasPrice(callParams, header)) {
transactionBuilder.gasPrice(gasPrice);
} else if (protocolSchedule.getChainId().isPresent()) {
}

if (shouldSetMaxFeePerGas(callParams, header)) {
transactionBuilder.maxFeePerGas(maxFeePerGas).maxPriorityFeePerGas(maxPriorityFeePerGas);
} else {
return Optional.empty();
}

transactionBuilder.guessType();
if (transactionBuilder.getTransactionType().supportsBlob()) {
if (shouldSetBlobGasPrice(callParams)) {
transactionBuilder.maxFeePerBlobGas(maxFeePerBlobGas);
}

transactionBuilder.guessType();

if (transactionBuilder.getTransactionType().requiresChainId()) {
callParams
.getChainId()
Expand Down Expand Up @@ -489,4 +489,39 @@ public Optional<Boolean> doesAddressExist(

return Optional.of(worldState.get(address) != null);
}

private boolean shouldSetGasPrice(final CallParameter callParams, final BlockHeader header) {
if (header.getBaseFee().isEmpty()) {
return true;
}

// if maxPriorityFeePerGas and maxFeePerGas are not set, use gasPrice
return callParams.getMaxPriorityFeePerGas().isEmpty() && callParams.getMaxFeePerGas().isEmpty();
}

private boolean shouldSetMaxFeePerGas(final CallParameter callParams, final BlockHeader header) {
if (protocolSchedule.getChainId().isEmpty()) {
return false;
}

if (header.getBaseFee().isEmpty()) {
return false;
}

if (shouldSetBlobGasPrice(callParams)) {
return true;
}

// only set maxFeePerGas and maxPriorityFeePerGas if they are present, otherwise transaction
// will be considered EIP-1559 transaction even if the simulation is for a legacy transaction
return callParams.getMaxPriorityFeePerGas().isPresent()
|| callParams.getMaxFeePerGas().isPresent();
}

private boolean shouldSetBlobGasPrice(final CallParameter callParams) {
if (protocolSchedule.getChainId().isEmpty()) {
return false;
}
return callParams.getBlobVersionedHashes().isPresent();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -912,4 +912,43 @@ private CallParameter blobTransactionCallParameter(
Optional.of(maxFeePerBlobGas),
Optional.of(bwc.getVersionedHashes()));
}

@Test
public void shouldSimulateLegacyTransactionWhenBaseFeeNotZero() {
// tests that the transaction simulator will simulate a legacy transaction when the base fee is
// not zero
// and the transaction is a legacy transaction

final CallParameter callParameter = legacyTransactionCallParameter();

final BlockHeader blockHeader =
blockHeaderTestFixture
.number(1L)
.stateRoot(Hash.ZERO)
.baseFeePerGas(Wei.of(7))
.buildHeader();

mockBlockchainForBlockHeader(blockHeader);
mockWorldStateForAccount(blockHeader, callParameter.getFrom(), 1L);

final Transaction expectedTransaction =
Transaction.builder()
.type(TransactionType.FRONTIER)
.nonce(1L)
.gasPrice(callParameter.getGasPrice())
.gasLimit(blockHeader.getGasLimit())
.to(callParameter.getTo())
.sender(callParameter.getFrom())
.value(callParameter.getValue())
.payload(callParameter.getPayload())
.signature(FAKE_SIGNATURE)
.build();
mockProcessorStatusForTransaction(expectedTransaction, Status.SUCCESSFUL);

final Optional<TransactionSimulatorResult> result =
transactionSimulator.process(callParameter, 1L);

verifyTransactionWasProcessed(expectedTransaction);
assertThat(result.get().isSuccessful()).isTrue();
}
}