Skip to content

Commit

Permalink
Fix tests in ContractCallSeviceTest class (#10432)
Browse files Browse the repository at this point in the history
Fixing tests in ContractCallSeviceTest class, a payer was not set in
some of the scenarios.

---------

Signed-off-by: sdimitrov9 <[email protected]>
  • Loading branch information
sdimitrov9 authored Feb 21, 2025
1 parent 0f8009a commit 7b3c84c
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@

package com.hedera.mirror.web3.service;

import static com.hedera.mirror.web3.service.model.CallServiceParameters.CallType.ETH_CALL;
import static com.hedera.mirror.web3.service.model.CallServiceParameters.CallType.ETH_ESTIMATE_GAS;
import static com.hedera.mirror.web3.utils.ContractCallTestUtil.ESTIMATE_GAS_ERROR_MESSAGE;
import static com.hedera.mirror.web3.utils.ContractCallTestUtil.TRANSACTION_GAS_LIMIT;
import static com.hedera.mirror.web3.utils.ContractCallTestUtil.isWithinExpectedGasRange;
Expand Down Expand Up @@ -211,15 +213,24 @@ protected ContractExecutionParameters getContractExecutionParameters(

protected ContractExecutionParameters getContractExecutionParameters(
final Bytes data, final Address receiver, final Address payerAddress, final long value) {
return getContractExecutionParameters(data, receiver, payerAddress, value, ETH_CALL);
}

protected ContractExecutionParameters getContractExecutionParameters(
final Bytes data,
final Address receiverAddress,
final Address senderAddress,
final long value,
final CallType callType) {
return ContractExecutionParameters.builder()
.block(BlockType.LATEST)
.callData(data)
.callType(CallType.ETH_CALL)
.callType(callType)
.gas(TRANSACTION_GAS_LIMIT)
.isEstimate(false)
.isEstimate(callType == ETH_ESTIMATE_GAS)
.isStatic(false)
.receiver(receiver)
.sender(new HederaEvmAccount(payerAddress))
.receiver(receiverAddress)
.sender(new HederaEvmAccount(senderAddress))
.value(value)
.build();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

package com.hedera.mirror.web3.service;

import static com.hedera.hapi.node.base.ResponseCodeEnum.PAYER_ACCOUNT_NOT_FOUND;
import static com.hedera.mirror.common.util.DomainUtils.toEvmAddress;
import static com.hedera.mirror.web3.evm.utils.EvmTokenUtils.toAddress;
import static com.hedera.mirror.web3.exception.BlockNumberNotFoundException.UNKNOWN_BLOCK_NUMBER;
Expand Down Expand Up @@ -337,14 +338,29 @@ void estimateGasForPureCall() {
verifyEthCallAndEstimateGas(functionCall, contract);
}

/**
* If we make a contract call with the zero address (0x0) set as the recipient in the contractExecutionParameters,
* Hedera treats this as a contract creation request rather than a function call.
* The contract is then initialized using the contractCallData, which should contain the compiled bytecode of the
* contract. If contractCallData is empty (0x0), the contract will be deployed without any functions(no fallback
* function as well, which is called when the contract is called without specifying a function or when non-existent
* function is specified.) in its bytecode. Respectively, any call to the contract will fail with
* CONTRACT_BYTECODE_EMPTY, indicating that the contract exists, but does not have any executable logic.
*/
@Test
void estimateGasWithoutReceiver() {
// Given
final var serviceParametersEthCall =
getContractExecutionParameters(Bytes.fromHexString(HEX_PREFIX), Address.ZERO, ETH_CALL);
final var payer = accountEntityPersist();
final var receiverAddress = Address.ZERO;

final var contract = testWeb3jService.deployWithoutPersist(ERCTestContract::deploy);
final var contractCallData = Bytes.fromHexString(contract.getContractBinary());

final var serviceParametersEthCall = getContractExecutionParameters(
contractCallData, toAddress(payer.toEntityId()), receiverAddress, 0L, ETH_CALL);

final var actualGasUsed = gasUsedAfterExecution(serviceParametersEthCall);
final var serviceParametersEstimateGas =
getContractExecutionParameters(Bytes.fromHexString(HEX_PREFIX), Address.ZERO, ETH_ESTIMATE_GAS);
final var serviceParametersEstimateGas = getContractExecutionParameters(
contractCallData, toAddress(payer.toEntityId()), receiverAddress, 0L, ETH_ESTIMATE_GAS);

// When
final var result = contractExecutionService.processCall(serviceParametersEstimateGas);
Expand Down Expand Up @@ -561,13 +577,14 @@ void nonExistingFunctionCallWithFallback() {
}

@Test
void ethCallWithValueAndNotExistingSenderAlias() {
void ethCallWithValueAndSenderWithoutAlias() {
// Given
final var receiver = accountEntityWithEvmAddressPersist();
final var receiverAddress = getAliasAddressFromEntity(receiver);
final var notExistingSenderAlias = Address.fromHexString("0x6b175474e89094c44da98b954eedeac495271d0f");
final var serviceParameters =
getContractExecutionParametersWithValue(Bytes.EMPTY, notExistingSenderAlias, receiverAddress, 10L);
final var receiverEntity = accountEntityWithEvmAddressPersist();
final var receiverAddress = getAliasAddressFromEntity(receiverEntity);
final var payer = accountEntityPersist(); // Account without alias

final var serviceParameters = getContractExecutionParametersWithValue(
Bytes.EMPTY, toAddress(payer.toEntityId()), receiverAddress, 10L);

// When
final var result = contractExecutionService.processCall(serviceParameters);
Expand All @@ -577,6 +594,27 @@ void ethCallWithValueAndNotExistingSenderAlias() {
assertGasLimit(serviceParameters);
}

@Test
void ethCallWithValueAndNotExistingSenderAddress() {
final var receiverEntity = accountEntityWithEvmAddressPersist();
final var receiverAddress = getAliasAddressFromEntity(receiverEntity);
final var notExistingAccountAddress = toAddress(EntityId.of(4325));

final var serviceParameters =
getContractExecutionParametersWithValue(Bytes.EMPTY, notExistingAccountAddress, receiverAddress, 10L);

if (mirrorNodeEvmProperties.isModularizedServices()) {
assertThatThrownBy(() -> contractExecutionService.processCall(serviceParameters))
.isInstanceOf(MirrorEvmTransactionException.class)
.hasMessage(PAYER_ACCOUNT_NOT_FOUND.name());
} else {
final var result = contractExecutionService.processCall(serviceParameters);
assertThat(result).isEqualTo(HEX_PREFIX);
}

assertGasLimit(serviceParameters);
}

@Test
void invalidFunctionSig() {
// Given
Expand Down Expand Up @@ -1100,7 +1138,8 @@ private Entity systemAccountEntityWithEvmAddressPersist() {
@Nested
class EVM46Validation {

private static final Address NON_EXISTING_ADDRESS = toAddress(123456789);
private static final Address NON_EXISTING_ADDRESS =
Address.fromHexString("0xa7d9ddbe1f17865597fbd27ec712455208b6b76d");

@Test
void callToNonExistingContract() {
Expand All @@ -1118,8 +1157,12 @@ void callToNonExistingContract() {
@Test
void transferToNonExistingContract() {
// Given
final var serviceParameters =
getContractExecutionParametersWithValue(Bytes.EMPTY, NON_EXISTING_ADDRESS, 1L);
final var payer = accountEntityWithEvmAddressPersist();

// The NON_EXISTING_ADDRESS should be a valid EVM alias key(Ethereum-style address derived from an ECDSA
// public key), otherwise INVALID_ALIAS_KEY could be thrown
final var serviceParameters = getContractExecutionParametersWithValue(
Bytes.EMPTY, getAliasAddressFromEntity(payer), NON_EXISTING_ADDRESS, 1L);

// When
final var result = contractExecutionService.processCall(serviceParameters);
Expand Down

0 comments on commit 7b3c84c

Please sign in to comment.