Skip to content

Commit

Permalink
Fix address(this) resolution when mirror address is passed in the call (
Browse files Browse the repository at this point in the history
hashgraph#7984)

There is an inconsistency on call address(this) function depending on the **to** parameter in a contract call request.
Address(this) will return whatever is specified as the 'to' parameter in the http request.
If a contract is created via ethereum transaction on hedera it will have a canonical ethereum address. It will also have the long zero address.
So in our contract call request we can put in the **to** parameter either the canonical evm address or the long zero and it should return the same response.
Currently if we call address(this) of a contract that has a canonical evm address but we pass it's long zero address in the contract call request it will return long zero address in the response. But we actually want the evm address returned.

This **PR** adds a check to see if a long zero address in passed in the request and will make the following verification:
If the address is long zero verify that there might be a canonical evm address.
If there exists a canonical evm address use it instead of the long zero.
Otherwise use the long zero.

Services uses similar approach -> 
```
if (relayerId == null) {
            result = evmTxProcessor.execute(
                    sender, receiver.canonicalAddress(), op.getGas(), op.getAmount(), callData, txnCtx.consensusTime());
}
```
 
This PR modifies:
`MirrorEvmTxProcessorImpl` adds a new method to determine the correct **to** address.
Added integration test for address function in `ContractCallDynamicCallsTest`

---------

Signed-off-by: Kristiyan Selveliev <[email protected]>
  • Loading branch information
kselveliev authored Apr 2, 2024
1 parent 9f02648 commit 46f9b03
Show file tree
Hide file tree
Showing 12 changed files with 107 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import com.hedera.node.app.service.evm.contracts.execution.PricesAndFeesProvider;
import com.hedera.node.app.service.evm.store.contracts.AbstractCodeCache;
import com.hedera.node.app.service.evm.store.contracts.HederaEvmMutableWorldState;
import com.hedera.node.app.service.evm.store.tokens.TokenAccessor;
import com.hedera.services.store.models.Account;
import com.hedera.services.utils.EntityIdUtils;
import com.hederahashgraph.api.proto.java.ResponseCodeEnum;
Expand All @@ -55,6 +56,7 @@ public class MirrorEvmTxProcessorImpl extends HederaEvmTxProcessor implements Mi
private final MirrorEvmContractAliases aliasManager;
private final Store store;
private final EntityAddressSequencer entityAddressSequencer;
private final TokenAccessor tokenAccessor;

@SuppressWarnings("java:S107")
public MirrorEvmTxProcessorImpl(
Expand All @@ -69,7 +71,8 @@ public MirrorEvmTxProcessorImpl(
final AbstractCodeCache codeCache,
final MirrorOperationTracer operationTracer,
final Store store,
final EntityAddressSequencer entityAddressSequencer) {
final EntityAddressSequencer entityAddressSequencer,
TokenAccessor tokenAccessor) {
super(
worldState,
pricesAndFeesProvider,
Expand All @@ -84,6 +87,7 @@ public MirrorEvmTxProcessorImpl(
this.codeCache = codeCache;
this.store = store;
this.entityAddressSequencer = entityAddressSequencer;
this.tokenAccessor = tokenAccessor;
}

public HederaEvmTransactionProcessingResult execute(CallServiceParameters params, long estimatedGas) {
Expand All @@ -97,10 +101,10 @@ public HederaEvmTransactionProcessingResult execute(CallServiceParameters params
Account.getDummySenderAccount(params.getSender().canonicalAddress());
store.updateAccount(senderAccount);
}

Address receiverAddress = determineReceiverAddress(params.getReceiver());
return super.execute(
params.getSender(),
params.getReceiver(),
receiverAddress,
gasPrice,
params.isEstimate(),
params.isEstimate() ? estimatedGas : params.getGas(),
Expand Down Expand Up @@ -148,4 +152,17 @@ protected MessageFrame buildInitialFrame(
.build();
}
}

private Address determineReceiverAddress(Address receiver) {
if (receiver == null || receiver.equals(Address.ZERO) || !aliasManager.isMirror(receiver)) {
return receiver;
}

Address canonical = tokenAccessor.canonicalAddress(receiver);
if (canonical == null || Address.ZERO.equals(canonical)) {
return receiver;
} else {
return canonical;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
import com.hedera.node.app.service.evm.store.contracts.AbstractCodeCache;
import com.hedera.node.app.service.evm.store.contracts.HederaEvmEntityAccess;
import com.hedera.node.app.service.evm.store.models.HederaEvmAccount;
import com.hedera.node.app.service.evm.store.tokens.TokenAccessor;
import com.hedera.services.store.models.Account;
import com.hederahashgraph.api.proto.java.ResponseCodeEnum;
import com.swirlds.common.utility.SemanticVersion;
Expand Down Expand Up @@ -131,6 +132,9 @@ class MirrorEvmTxProcessorTest {
@Mock
private StoreImpl store;

@Mock
private TokenAccessor tokenAccessor;

private MirrorEvmTxProcessorImpl mirrorEvmTxProcessor;
private Pair<ResponseCodeEnum, Long> result;

Expand Down Expand Up @@ -180,7 +184,8 @@ void setup() {
new AbstractCodeCache(10, hederaEvmEntityAccess),
mirrorOperationTracer,
store,
new EntityAddressSequencer());
new EntityAddressSequencer(),
tokenAccessor);

Pair<ResponseCodeEnum, Long> result = Pair.of(ResponseCodeEnum.OK, 100L);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import java.math.BigInteger;
import lombok.RequiredArgsConstructor;
import org.assertj.core.data.Percentage;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.EnumSource;

Expand Down Expand Up @@ -77,6 +78,30 @@ void dynamicCallsTestWithAliasSenderForEstimateGas(DynamicCallsContractFunctions
}
}

@Test
void testGetAddressThisWithEvmAliasRecipient() {
String ethCallContractWithout0x =
DYNAMIC_ETH_CALLS_CONTRACT_ALIAS.toString().substring(2);
String successfulResponse = "0x000000000000000000000000" + ethCallContractWithout0x;
final var functionHash = functionEncodeDecoder.functionHashFor("getAddressThis", DYNAMIC_ETH_CALLS_ABI_PATH);
final var serviceParameters = serviceParametersForExecution(
functionHash, DYNAMIC_ETH_CALLS_CONTRACT_ALIAS, ETH_CALL, 0L, BlockType.LATEST);

assertThat(contractCallService.processCall(serviceParameters)).isEqualTo(successfulResponse);
}

@Test
void testGetAddressThisWithLongZeroRecipientThatHasEvmAlias() {
String ethCallContractWithout0x =
DYNAMIC_ETH_CALLS_CONTRACT_ALIAS.toString().substring(2);
String successfulResponse = "0x000000000000000000000000" + ethCallContractWithout0x;
final var functionHash = functionEncodeDecoder.functionHashFor("getAddressThis", DYNAMIC_ETH_CALLS_ABI_PATH);
final var serviceParameters = serviceParametersForExecution(
functionHash, DYNAMIC_ETH_CALLS_CONTRACT_ADDRESS, ETH_CALL, 0L, BlockType.LATEST);

assertThat(contractCallService.processCall(serviceParameters)).isEqualTo(successfulResponse);
}

@RequiredArgsConstructor
enum DynamicCallsContractFunctions {
MINT_FUNGIBLE_TOKEN(
Expand Down Expand Up @@ -245,7 +270,8 @@ enum DynamicCallsContractFunctions {
},
null),
GRANT_KYC_REVOKE_KYC_FUNGIBLE("grantKycRevokeKyc", new Object[] {FUNGIBLE_TOKEN_ADDRESS, SENDER_ALIAS}, null),
GRANT_KYC_REVOKE_KYC_NFT("grantKycRevokeKyc", new Object[] {NFT_ADDRESS, SENDER_ALIAS}, null);
GRANT_KYC_REVOKE_KYC_NFT("grantKycRevokeKyc", new Object[] {NFT_ADDRESS, SENDER_ALIAS}, null),
ADDRESS_THIS("getAddressThis", null, null);
private final String name;
private final Object[] functionParameters;
private final String expectedErrorMessage;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,7 @@ void testNonSystemContractCodeHash(String input, String expectedOutput) {
@Test
void deployAddressThisContract() {
final var serviceParameters = serviceParametersForAddressThis(
Bytes.wrap(functionEncodeDecoder.getContractBytes(ADDRESS_THIS_CONTRACT_BYTES_PATH)));
Bytes.wrap(functionEncodeDecoder.getContractBytes(ADDRESS_THIS_CONTRACT_INIT_BYTES_PATH)));
final var expectedGasUsed = gasUsedAfterExecution(serviceParameters);

assertThat(isWithinExpectedGasRange(
Expand All @@ -278,6 +278,19 @@ void addressThisFromFunction() {
.isTrue();
}

@Test
void addressThisEthCallWithoutEvmAlias() {
String addressThisContractAddressWithout0x =
ADDRESS_THIS_CONTRACT_ADDRESS.toString().substring(2);
String successfulResponse = "0x000000000000000000000000" + addressThisContractAddressWithout0x;
final var functionHash =
functionEncodeDecoder.functionHashFor("getAddressThis", ADDRESS_THIS_CONTRACT_ABI_PATH);
final var serviceParameters = serviceParametersForExecution(
functionHash, ADDRESS_THIS_CONTRACT_ADDRESS, ETH_CALL, 0L, BlockType.LATEST);

assertThat(contractCallService.processCall(serviceParameters)).isEqualTo(successfulResponse);
}

@Test
void deployNestedAddressThisContract() {
final var serviceParameters = serviceParametersForAddressThis(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -576,6 +576,9 @@ public class ContractCallTestSetup extends Web3IntegrationTest {
@Value("classpath:contracts/TestContractAddress/TestAddressThis.bin")
protected Path ADDRESS_THIS_CONTRACT_BYTES_PATH;

@Value("classpath:contracts/TestContractAddress/TestAddressThisInit.bin")
protected Path ADDRESS_THIS_CONTRACT_INIT_BYTES_PATH;

@Value("classpath:contracts/TestContractAddress/TestAddressThis.json")
protected Path ADDRESS_THIS_CONTRACT_ABI_PATH;

Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -554,6 +554,19 @@
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "getAddressThis",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -406,6 +406,10 @@ contract DynamicEthCalls is HederaTokenService {
if (response != HederaResponseCodes.SUCCESS) revert("Is kyc operation failed");
if(isKyc) revert("Kyc status mismatch");
}

function getAddressThis() public view returns(address) {
return address(this);
}
}

contract SpenderContract {
Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1 @@
60806040526000309050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610078576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161006f906100db565b60405180910390fd5b506100fb565b600082825260208201905092915050565b7f5a65726f20616464726573732e00000000000000000000000000000000000000600082015250565b60006100c5600d8361007e565b91506100d08261008f565b602082019050919050565b600060208201905081810360008301526100f4816100b8565b9050919050565b6101648061010a6000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c806341de2c4e14610030575b600080fd5b61003861003a565b005b6000309050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036100ae576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100a59061010e565b60405180910390fd5b50565b600082825260208201905092915050565b7f5a65726f20616464726573732e00000000000000000000000000000000000000600082015250565b60006100f8600d836100b1565b9150610103826100c2565b602082019050919050565b60006020820190508181036000830152610127816100eb565b905091905056fea2646970667358221220cfb72597ca3ad2667cec512e862fc68bba53097afe7258045f34bed0b1f2fc7164736f6c63430008120033
608060405234801561001057600080fd5b50600436106100365760003560e01c80630a83b9a61461003b57806341de2c4e14610059575b600080fd5b610043610063565b6040516100509190610123565b60405180910390f35b61006161006b565b005b600030905090565b6000309050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036100df576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100d69061019b565b60405180910390fd5b50565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061010d826100e2565b9050919050565b61011d81610102565b82525050565b60006020820190506101386000830184610114565b92915050565b600082825260208201905092915050565b7f5a65726f20616464726573732e00000000000000000000000000000000000000600082015250565b6000610185600d8361013e565b91506101908261014f565b602082019050919050565b600060208201905081810360008301526101b481610178565b905091905056fea2646970667358221220d1bf301106861c636eb4ce94ec71f03f9d02995361aa602aafcae9a5521663db64736f6c63430008120033
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,24 @@
"stateMutability": "payable",
"type": "constructor"
},
{
"inputs": [],
"name": "getAddressThis",
"outputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "testAddressThis",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
}
]
]
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,7 @@ contract TestAddressThis {
}
}

function getAddressThis() public view returns(address) {
return address(this);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
60806040526000309050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1603610078576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161006f906100db565b60405180910390fd5b506100fb565b600082825260208201905092915050565b7f5a65726f20616464726573732e00000000000000000000000000000000000000600082015250565b60006100c5600d8361007e565b91506100d08261008f565b602082019050919050565b600060208201905081810360008301526100f4816100b8565b9050919050565b6101f18061010a6000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80630a83b9a61461003b57806341de2c4e14610059575b600080fd5b610043610063565b6040516100509190610123565b60405180910390f35b61006161006b565b005b600030905090565b6000309050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16036100df576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100d69061019b565b60405180910390fd5b50565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061010d826100e2565b9050919050565b61011d81610102565b82525050565b60006020820190506101386000830184610114565b92915050565b600082825260208201905092915050565b7f5a65726f20616464726573732e00000000000000000000000000000000000000600082015250565b6000610185600d8361013e565b91506101908261014f565b602082019050919050565b600060208201905081810360008301526101b481610178565b905091905056fea2646970667358221220d1bf301106861c636eb4ce94ec71f03f9d02995361aa602aafcae9a5521663db64736f6c63430008120033

0 comments on commit 46f9b03

Please sign in to comment.