Repository: hiero-ledger/hiero-mirror-node
Pull request #11101: Add web3 integration tests for get schedule info
Author: login: nickeynikolovv
Labels: name: enhancement
description: Type: New feature
name: test
description: Test infrastructure, automated tests required, etc
name: web3
description: Area: Web3 API
name: modularized evm
Created: 2025-05-05T11:43:02Z | Merged: 2025-05-19T14:51:59Z

This PR adds tests for get schedule info for token create scheduled transactions

**Related issue(s)**:

Fixes #10928

**Notes for reviewer**:
IMPORTANT: This PR is based on and should be merged after the changes from #10927 because there will be the main implementation for ScheduleRepository and ScheduleReadableKVState

**Checklist**

- [ ] Documented (Code comments, README, etc.)
- [x] Tested (unit, integration, etc.)


Linked issue #10928: Add integration tests for GetScheduledInfoTest
### Problem

Currently our code does not have any HederaScheduleService tests so we need to add them.

### Solution

The class you can check in hiero-consensus-node is `GetScheduledInfoTest`, located in package `com.hedera.services.bdd.suites.contract.precompile.schedule` of test-clients module. We need to add tests similar to those.

### Alternatives

_No response_

Diff:
diff --git a/hedera-mirror-web3/src/test/java/com/hedera/mirror/web3/service/ContractCallGetScheduleInfoTest.java b/hedera-mirror-web3/src/test/java/com/hedera/mirror/web3/service/ContractCallGetScheduleInfoTest.java
new file mode 100644
index 00000000000..e9f79165089
--- /dev/null
+++ b/hedera-mirror-web3/src/test/java/com/hedera/mirror/web3/service/ContractCallGetScheduleInfoTest.java
@@ -0,0 +1,182 @@
+// SPDX-License-Identifier: Apache-2.0
+
+package com.hedera.mirror.web3.service;
+
+import static com.hedera.hapi.node.base.ResponseCodeEnum.CONTRACT_REVERT_EXECUTED;
+import static com.hedera.mirror.web3.evm.utils.EvmTokenUtils.toAddress;
+import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+import com.hedera.hapi.node.base.AccountID;
+import com.hedera.hapi.node.base.Timestamp;
+import com.hedera.hapi.node.base.TokenSupplyType;
+import com.hedera.hapi.node.base.TokenType;
+import com.hedera.hapi.node.scheduled.SchedulableTransactionBody;
+import com.hedera.hapi.node.token.TokenCreateTransactionBody;
+import com.hedera.mirror.common.domain.entity.EntityId;
+import com.hedera.mirror.common.domain.entity.EntityType;
+import com.hedera.mirror.web3.exception.MirrorEvmTransactionException;
+import com.hedera.mirror.web3.web3j.generated.GetScheduleInfo;
+import com.hedera.node.app.hapi.utils.CommonPbjConverters;
+import com.hederahashgraph.api.proto.java.ResponseCodeEnum;
+import java.math.BigInteger;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ValueSource;
+
+/**
+ * This test class validates the correct results for getting schedule info for a token create transaction via smart contract calls .
+ */
+class ContractCallGetScheduleInfoTest extends AbstractContractCallServiceHistoricalTest {
+    @ParameterizedTest
+    @ValueSource(booleans = {true, false})
+    void getFungibleCreateScheduleInfoNonExisting(final Boolean isFungible) {
+        // Cannot get schedule info for non-existing schedule
+        // Given
+        final var entity = domainBuilder.entityId();
+        final var nonExistingAddress = toAddress(entity).toHexString();
+        final var contract = testWeb3jService.deploy(GetScheduleInfo::deploy);
+        // When
+        final var functionCall = isFungible
+                ? contract.call_getFungibleCreateTokenInfo(nonExistingAddress)
+                : contract.call_getNonFungibleCreateTokenInfo(nonExistingAddress);
+
+        final var exception = assertThrows(MirrorEvmTransactionException.class, functionCall::send);
+        // Then
+        assertThat(exception.getMessage()).isEqualTo(CONTRACT_REVERT_EXECUTED.protoName());
+    }
+
+    @Test
+    void getFungibleCreateScheduleInfo() throws Exception {
+        // Given
+        final var contract = testWeb3jService.deploy(GetScheduleInfo::deploy);
+        final var payerAccount = accountEntityPersist();
+        final var treasuryAccount = accountEntityPersist();
+        final var scheduleEntity = domainBuilder
+                .entity()
+                .customize(e -> e.type(EntityType.SCHEDULE))
+                .persist();
+        final var tokenName = "Fungible-Token";
+        final var tokenSymbol = "FUNG";
+        final var maxSupply = 1000L;
+        // Build Schedule Token create transaction body in bytes
+        final var scheduleTokenCreateTransactionBodyBytes = buildScheduledTokenCreateTransactionBody(
+                treasuryAccount, tokenName, tokenSymbol, TokenType.FUNGIBLE_COMMON, 500L, maxSupply);
+        // Persist schedule
+        final var schedule = domainBuilder
+                .schedule()
+                .customize(e -> e.scheduleId(scheduleEntity.toEntityId().getId())
+                        .transactionBody(scheduleTokenCreateTransactionBodyBytes)
+                        .payerAccountId(payerAccount.toEntityId())
+                        .creatorAccountId(payerAccount.toEntityId()))
+                .persist();
+
+        // When
+        final var entityId = EntityId.of(schedule.getScheduleId());
+        final var functionCall = contract.call_getFungibleCreateTokenInfo(getAddressFromEntityId(entityId));
+        // Then
+        if (mirrorNodeEvmProperties.isModularizedServices()) {
+            final var functionCallResult = functionCall.send();
+            assertThat(functionCallResult.component1())
+                    .isEqualTo(BigInteger.valueOf(ResponseCodeEnum.SUCCESS.getNumber()));
+            assertThat(functionCallResult.component2().tokenInfo.token.name).isEqualTo(tokenName);
+            assertThat(functionCallResult.component2().tokenInfo.token.symbol).isEqualTo(tokenSymbol);
+            assertThat(functionCallResult.component2().tokenInfo.token.treasury)
+                    .isEqualTo(getAddressFromEntityId(treasuryAccount.toEntityId()));
+            assertThat(functionCallResult.component2().tokenInfo.token.maxSupply)
+                    .isEqualTo(BigInteger.valueOf(maxSupply));
+
+        } else {
+            assertThrows(MirrorEvmTransactionException.class, functionCall::send);
+        }
+    }
+
+    @Test
+    void getNonFungibleCreateScheduleInfo() throws Exception {
+        // Given
+        final var contract = testWeb3jService.deploy(GetScheduleInfo::deploy);
+        final var payerAccount = accountEntityPersist();
+        final var treasuryAccount = accountEntityPersist();
+        final var scheduleEntity = domainBuilder
+                .entity()
+                .customize(e -> e.type(EntityType.SCHEDULE))
+                .persist();
+        final var tokenName = "Non-Fungible-Token";
+        final var tokenSymbol = "NFT";
+        final var maxSupply = 1000L;
+        // Build Schedule Token create transaction body in bytes
+        final var scheduleTokenCreateTransactionBodyBytes = buildScheduledTokenCreateTransactionBody(
+                treasuryAccount, tokenName, tokenSymbol, TokenType.NON_FUNGIBLE_UNIQUE, 0L, maxSupply);
+        // Persist schedule
+        final var schedule = domainBuilder
+                .schedule()
+                .customize(e -> e.scheduleId(scheduleEntity.toEntityId().getId())
+                        .transactionBody(scheduleTokenCreateTransactionBodyBytes)
+                        .payerAccountId(payerAccount.toEntityId())
+                        .creatorAccountId(payerAccount.toEntityId()))
+                .persist();
+        // When
+        final var entityId = EntityId.of(schedule.getScheduleId());
+        final var functionCall = contract.call_getNonFungibleCreateTokenInfo(getAddressFromEntityId(entityId));
+        // Then
+        if (mirrorNodeEvmProperties.isModularizedServices()) {
+            final var functionCallResult = functionCall.send();
+            assertThat(functionCallResult.component1())
+                    .isEqualTo(BigInteger.valueOf(ResponseCodeEnum.SUCCESS.getNumber()));
+            assertThat(functionCallResult.component2().tokenInfo.token.name).isEqualTo(tokenName);
+            assertThat(functionCallResult.component2().tokenInfo.token.symbol).isEqualTo(tokenSymbol);
+            assertThat(functionCallResult.component2().tokenInfo.token.treasury)
+                    .isEqualTo(getAddressFromEntityId(treasuryAccount.toEntityId()));
+            assertThat(functionCallResult.component2().tokenInfo.token.maxSupply)
+                    .isEqualTo(BigInteger.valueOf(maxSupply));
+        } else {
+            assertThrows(MirrorEvmTransactionException.class, functionCall::send);
+        }
+    }
+
+    /**
+     * Build Scheduled Token Create transaction body in bytes
+     *
+     * @param treasuryAccount The treasury account of the token
+     * @param name The name of the token
+     * @param symbol The symbol of the token
+     * @param tokenType Token type, either Fungible or Non-Fungible
+     * @param initialSupply The initial supply of the token
+     * @param maxSupply the max supply of the token
+     * @return The schedule transaction body for token create transaction in bytes
+     */
+    private byte[] buildScheduledTokenCreateTransactionBody(
+            com.hedera.mirror.common.domain.entity.Entity treasuryAccount,
+            String name,
+            String symbol,
+            TokenType tokenType,
+            long initialSupply,
+            long maxSupply) {
+
+        final var treasuryAccountId = AccountID.newBuilder()
+                .shardNum(treasuryAccount.getShard())
+                .realmNum(treasuryAccount.getRealm())
+                .accountNum(treasuryAccount.getNum())
+                .build();
+
+        final var tokenCreateTransactionBody = TokenCreateTransactionBody.newBuilder()
+                .tokenType(tokenType)
+                .name(name)
+                .symbol(symbol)
+                .supplyType(TokenSupplyType.FINITE)
+                .expiry(Timestamp.newBuilder().seconds(10L).build())
+                .treasury(treasuryAccountId)
+                .autoRenewAccount(AccountID.newBuilder()
+                        .accountNum(treasuryAccount.getNum())
+                        .build())
+                .initialSupply(initialSupply)
+                .maxSupply(maxSupply)
+                .build();
+
+        final var scheduleTransactionBody = SchedulableTransactionBody.newBuilder()
+                .tokenCreation(tokenCreateTransactionBody)
+                .build();
+
+        return CommonPbjConverters.asBytes(SchedulableTransactionBody.PROTOBUF, scheduleTransactionBody);
+    }
+}
diff --git a/hedera-mirror-web3/src/test/solidity/GetScheduleInfo.sol b/hedera-mirror-web3/src/test/solidity/GetScheduleInfo.sol
new file mode 100644
index 00000000000..074a71656d2
--- /dev/null
+++ b/hedera-mirror-web3/src/test/solidity/GetScheduleInfo.sol
@@ -0,0 +1,25 @@
+// SPDX-License-Identifier: Apache-2.0
+pragma solidity >=0.4.9 <0.9.0;
+
+import "./HederaScheduleService.sol";
+import "./HederaResponseCodes.sol";
+pragma experimental ABIEncoderV2;
+
+contract GetScheduleInfo is HederaScheduleService {
+
+    function getFungibleCreateTokenInfo(address scheduleAddress) external returns (int64 responseCode, IHederaTokenService.FungibleTokenInfo memory fungibleTokenInfo) {
+        (responseCode, fungibleTokenInfo) = getScheduledCreateFungibleTokenInfo(scheduleAddress);
+        if (responseCode != HederaResponseCodes.SUCCESS) {
+            revert();
+        }
+        return (responseCode, fungibleTokenInfo);
+    }
+
+    function getNonFungibleCreateTokenInfo(address scheduleAddress) external returns (int64 responseCode, IHederaTokenService.NonFungibleTokenInfo memory nonFungibleTokenInfo) {
+        (responseCode, nonFungibleTokenInfo) = getScheduledCreateNonFungibleTokenInfo(scheduleAddress);
+        if (responseCode != HederaResponseCodes.SUCCESS) {
+            revert();
+        }
+        return (responseCode, nonFungibleTokenInfo);
+    }
+}


Reviews:
user: login: sdimitrov9
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-05T12:11:00Z
user: login: sdimitrov9
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-05T12:17:30Z
user: login: sdimitrov9
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-05T12:23:04Z
user: login: nickeynikolovv
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-07T07:44:32Z
user: login: nickeynikolovv
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-07T07:44:45Z
user: login: nickeynikolovv
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-07T07:44:51Z
user: login: sdimitrov9
state: DISMISSED
author_association: CONTRIBUTOR
submitted_at: 2025-05-09T08:45:39Z
user: login: kselveliev
state: DISMISSED
author_association: CONTRIBUTOR
submitted_at: 2025-05-09T14:14:19Z
user: login: bilyana-gospodinova
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-13T12:39:52Z
user: login: bilyana-gospodinova
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-13T12:40:36Z
user: login: nickeynikolovv
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-14T12:55:51Z
user: login: nickeynikolovv
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-14T13:00:00Z
user: login: bilyana-gospodinova
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-14T13:03:06Z
user: login: bilyana-gospodinova
state: DISMISSED
author_association: CONTRIBUTOR
submitted_at: 2025-05-14T13:04:09Z
user: login: kselveliev
body: LGTM
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-19T14:20:54Z
user: login: kselveliev
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-05-19T14:21:27Z
user: login: steven-sheehy
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-05-19T14:29:08Z

Review comments:
diff_hunk: @@ -0,0 +1,185 @@
+// SPDX-License-Identifier: Apache-2.0
+
+package com.hedera.mirror.web3.service;
+
+import static com.hedera.hapi.node.base.ResponseCodeEnum.CONTRACT_REVERT_EXECUTED;
+import static com.hedera.mirror.web3.evm.utils.EvmTokenUtils.toAddress;
+import static com.hedera.node.app.service.contract.impl.utils.ConversionUtils.asEvmAddress;
+import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+import com.hedera.hapi.node.base.AccountID;
+import com.hedera.hapi.node.base.Timestamp;
+import com.hedera.hapi.node.base.TokenSupplyType;
+import com.hedera.hapi.node.base.TokenType;
+import com.hedera.hapi.node.scheduled.SchedulableTransactionBody;
+import com.hedera.hapi.node.token.TokenCreateTransactionBody;
+import com.hedera.mirror.common.domain.entity.EntityId;
+import com.hedera.mirror.common.domain.entity.EntityType;
+import com.hedera.mirror.web3.exception.MirrorEvmTransactionException;
+import com.hedera.mirror.web3.web3j.generated.GetScheduleInfo;
+import com.hedera.node.app.hapi.utils.CommonPbjConverters;
+import com.hederahashgraph.api.proto.java.ResponseCodeEnum;
+import java.math.BigInteger;
+import org.junit.jupiter.api.Test;
+
+class ContractCallGetScheduleInfoTest extends AbstractContractCallServiceHistoricalTest {
+
+    @Test
+    void getFungibleCreateScheduleInfoNonExisting() throws Exception {
+        // Cannot get schedule info for non-existing schedule
+        // Given
+        final var entity = domainBuilder.entityId();
+        final var nonExistingAddress = toAddress(entity).toHexString();
+        final var contract = testWeb3jService.deploy(GetScheduleInfo::deploy);
+        // When
+        final var functionCall = contract.call_getFungibleCreateTokenInfo(nonExistingAddress);
+        final var exception = assertThrows(MirrorEvmTransactionException.class, functionCall::send);
+        // Then
+        assertThat(exception.getMessage()).isEqualTo(CONTRACT_REVERT_EXECUTED.protoName());
+    }
+
+    @Test
+    void getNFTCreateScheduleInfoNonExisting() throws Exception {
+        // Cannot get schedule info for non-existing schedule
+        // Given
+        final var entity = domainBuilder.entityId();
+        final var nonExistingAddress = toAddress(entity).toHexString();
+        final var contract = testWeb3jService.deploy(GetScheduleInfo::deploy);
+        // When
+        final var functionCall = contract.call_getNonFungibleCreateTokenInfo(nonExistingAddress);
+        final var exception = assertThrows(MirrorEvmTransactionException.class, functionCall::send);
+        // Then
+        assertThat(exception.getMessage()).isEqualTo(CONTRACT_REVERT_EXECUTED.protoName());
+    }
+
+    @Test
+    void getFungibleCreateScheduleInfo() throws Exception {
+        // Given
+        final var contract = testWeb3jService.deploy(GetScheduleInfo::deploy);
+        final var payerAccount = accountEntityPersist();
+        final var treasuryAccount = accountEntityPersist();
+        final var scheduleEntity = domainBuilder
+                .entity()
+                .customize(e -> e.type(EntityType.SCHEDULE))
+                .persist();
+        final var tokenName = "Fungible-Token";
+        final var tokenSymbol = "FUNG";
+        final var maxSupply = 1000;
+        // Create Token create transaction body
+        final var expiry = Timestamp.newBuilder().seconds(10L).build();
+        final var tokenCreateTransactionBody = TokenCreateTransactionBody.newBuilder()
path: hedera-mirror-web3/src/test/java/com/hedera/mirror/web3/service/ContractCallGetScheduleInfoTest.java
user: login: sdimitrov9
body: Consider extracting repeated code, like:

     ```
      private byte[] buildScheduledTokenCreateTransactionBody(
                  com.hedera.mirror.common.domain.entity.Entity treasuryAccount,
                  String name,
                  String symbol,
                  TokenType tokenType,
                  long initialSupply,
                  long maxSupply
          ) {

          final var treasuryAccountId = AccountID.newBuilder()
                  .shardNum(treasuryAccount.getShard())
                  .realmNum(treasuryAccount.getRealm())
                  .accountNum(treasuryAccount.getNum())
                  .build();
  
          final var tokenCreateTransactionBody = TokenCreateTransactionBody.newBuilder()
                  .tokenType(tokenType)
                  .name(name)
                  .symbol(symbol)
                  .supplyType(TokenSupplyType.FINITE)
                  .expiry(Timestamp.newBuilder().seconds(10L).build())
                  .treasury(treasuryAccountId)
                  .autoRenewAccount(AccountID.newBuilder().accountNum(treasuryAccount.getNum()).build())
                  .initialSupply(initialSupply)
                  .maxSupply(maxSupply)
                  .build();
  
          final var scheduleTransactionBody = SchedulableTransactionBody.newBuilder()
                  .tokenCreation(tokenCreateTransactionBody)
                  .build();
  
          return CommonPbjConverters.asBytes(SchedulableTransactionBody.PROTOBUF, scheduleTransactionBody);
      }
```
created_at: 2025-05-05T12:11:00Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,185 @@
+// SPDX-License-Identifier: Apache-2.0
+
+package com.hedera.mirror.web3.service;
+
+import static com.hedera.hapi.node.base.ResponseCodeEnum.CONTRACT_REVERT_EXECUTED;
+import static com.hedera.mirror.web3.evm.utils.EvmTokenUtils.toAddress;
+import static com.hedera.node.app.service.contract.impl.utils.ConversionUtils.asEvmAddress;
path: hedera-mirror-web3/src/test/java/com/hedera/mirror/web3/service/ContractCallGetScheduleInfoTest.java
user: login: sdimitrov9
body: Remove unused import.
created_at: 2025-05-05T12:17:30Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,185 @@
+// SPDX-License-Identifier: Apache-2.0
+
+package com.hedera.mirror.web3.service;
+
+import static com.hedera.hapi.node.base.ResponseCodeEnum.CONTRACT_REVERT_EXECUTED;
+import static com.hedera.mirror.web3.evm.utils.EvmTokenUtils.toAddress;
+import static com.hedera.node.app.service.contract.impl.utils.ConversionUtils.asEvmAddress;
+import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+import com.hedera.hapi.node.base.AccountID;
+import com.hedera.hapi.node.base.Timestamp;
+import com.hedera.hapi.node.base.TokenSupplyType;
+import com.hedera.hapi.node.base.TokenType;
+import com.hedera.hapi.node.scheduled.SchedulableTransactionBody;
+import com.hedera.hapi.node.token.TokenCreateTransactionBody;
+import com.hedera.mirror.common.domain.entity.EntityId;
+import com.hedera.mirror.common.domain.entity.EntityType;
+import com.hedera.mirror.web3.exception.MirrorEvmTransactionException;
+import com.hedera.mirror.web3.web3j.generated.GetScheduleInfo;
+import com.hedera.node.app.hapi.utils.CommonPbjConverters;
+import com.hederahashgraph.api.proto.java.ResponseCodeEnum;
+import java.math.BigInteger;
+import org.junit.jupiter.api.Test;
+
path: hedera-mirror-web3/src/test/java/com/hedera/mirror/web3/service/ContractCallGetScheduleInfoTest.java
user: login: sdimitrov9
body: I would add javadoc with some information about the business logic tested by the class, but as of this moment this is more of a personal preference rather than something we necessarily stick up to.
created_at: 2025-05-05T12:23:04Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,185 @@
+// SPDX-License-Identifier: Apache-2.0
+
+package com.hedera.mirror.web3.service;
+
+import static com.hedera.hapi.node.base.ResponseCodeEnum.CONTRACT_REVERT_EXECUTED;
+import static com.hedera.mirror.web3.evm.utils.EvmTokenUtils.toAddress;
+import static com.hedera.node.app.service.contract.impl.utils.ConversionUtils.asEvmAddress;
+import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+import com.hedera.hapi.node.base.AccountID;
+import com.hedera.hapi.node.base.Timestamp;
+import com.hedera.hapi.node.base.TokenSupplyType;
+import com.hedera.hapi.node.base.TokenType;
+import com.hedera.hapi.node.scheduled.SchedulableTransactionBody;
+import com.hedera.hapi.node.token.TokenCreateTransactionBody;
+import com.hedera.mirror.common.domain.entity.EntityId;
+import com.hedera.mirror.common.domain.entity.EntityType;
+import com.hedera.mirror.web3.exception.MirrorEvmTransactionException;
+import com.hedera.mirror.web3.web3j.generated.GetScheduleInfo;
+import com.hedera.node.app.hapi.utils.CommonPbjConverters;
+import com.hederahashgraph.api.proto.java.ResponseCodeEnum;
+import java.math.BigInteger;
+import org.junit.jupiter.api.Test;
+
path: hedera-mirror-web3/src/test/java/com/hedera/mirror/web3/service/ContractCallGetScheduleInfoTest.java
user: login: nickeynikolovv
body: Added
created_at: 2025-05-07T07:44:32Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,185 @@
+// SPDX-License-Identifier: Apache-2.0
+
+package com.hedera.mirror.web3.service;
+
+import static com.hedera.hapi.node.base.ResponseCodeEnum.CONTRACT_REVERT_EXECUTED;
+import static com.hedera.mirror.web3.evm.utils.EvmTokenUtils.toAddress;
+import static com.hedera.node.app.service.contract.impl.utils.ConversionUtils.asEvmAddress;
path: hedera-mirror-web3/src/test/java/com/hedera/mirror/web3/service/ContractCallGetScheduleInfoTest.java
user: login: nickeynikolovv
body: Done
created_at: 2025-05-07T07:44:45Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,185 @@
+// SPDX-License-Identifier: Apache-2.0
+
+package com.hedera.mirror.web3.service;
+
+import static com.hedera.hapi.node.base.ResponseCodeEnum.CONTRACT_REVERT_EXECUTED;
+import static com.hedera.mirror.web3.evm.utils.EvmTokenUtils.toAddress;
+import static com.hedera.node.app.service.contract.impl.utils.ConversionUtils.asEvmAddress;
+import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+import com.hedera.hapi.node.base.AccountID;
+import com.hedera.hapi.node.base.Timestamp;
+import com.hedera.hapi.node.base.TokenSupplyType;
+import com.hedera.hapi.node.base.TokenType;
+import com.hedera.hapi.node.scheduled.SchedulableTransactionBody;
+import com.hedera.hapi.node.token.TokenCreateTransactionBody;
+import com.hedera.mirror.common.domain.entity.EntityId;
+import com.hedera.mirror.common.domain.entity.EntityType;
+import com.hedera.mirror.web3.exception.MirrorEvmTransactionException;
+import com.hedera.mirror.web3.web3j.generated.GetScheduleInfo;
+import com.hedera.node.app.hapi.utils.CommonPbjConverters;
+import com.hederahashgraph.api.proto.java.ResponseCodeEnum;
+import java.math.BigInteger;
+import org.junit.jupiter.api.Test;
+
+class ContractCallGetScheduleInfoTest extends AbstractContractCallServiceHistoricalTest {
+
+    @Test
+    void getFungibleCreateScheduleInfoNonExisting() throws Exception {
+        // Cannot get schedule info for non-existing schedule
+        // Given
+        final var entity = domainBuilder.entityId();
+        final var nonExistingAddress = toAddress(entity).toHexString();
+        final var contract = testWeb3jService.deploy(GetScheduleInfo::deploy);
+        // When
+        final var functionCall = contract.call_getFungibleCreateTokenInfo(nonExistingAddress);
+        final var exception = assertThrows(MirrorEvmTransactionException.class, functionCall::send);
+        // Then
+        assertThat(exception.getMessage()).isEqualTo(CONTRACT_REVERT_EXECUTED.protoName());
+    }
+
+    @Test
+    void getNFTCreateScheduleInfoNonExisting() throws Exception {
+        // Cannot get schedule info for non-existing schedule
+        // Given
+        final var entity = domainBuilder.entityId();
+        final var nonExistingAddress = toAddress(entity).toHexString();
+        final var contract = testWeb3jService.deploy(GetScheduleInfo::deploy);
+        // When
+        final var functionCall = contract.call_getNonFungibleCreateTokenInfo(nonExistingAddress);
+        final var exception = assertThrows(MirrorEvmTransactionException.class, functionCall::send);
+        // Then
+        assertThat(exception.getMessage()).isEqualTo(CONTRACT_REVERT_EXECUTED.protoName());
+    }
+
+    @Test
+    void getFungibleCreateScheduleInfo() throws Exception {
+        // Given
+        final var contract = testWeb3jService.deploy(GetScheduleInfo::deploy);
+        final var payerAccount = accountEntityPersist();
+        final var treasuryAccount = accountEntityPersist();
+        final var scheduleEntity = domainBuilder
+                .entity()
+                .customize(e -> e.type(EntityType.SCHEDULE))
+                .persist();
+        final var tokenName = "Fungible-Token";
+        final var tokenSymbol = "FUNG";
+        final var maxSupply = 1000;
+        // Create Token create transaction body
+        final var expiry = Timestamp.newBuilder().seconds(10L).build();
+        final var tokenCreateTransactionBody = TokenCreateTransactionBody.newBuilder()
path: hedera-mirror-web3/src/test/java/com/hedera/mirror/web3/service/ContractCallGetScheduleInfoTest.java
user: login: nickeynikolovv
body: Done
created_at: 2025-05-07T07:44:51Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,191 @@
+// SPDX-License-Identifier: Apache-2.0
+
+package com.hedera.mirror.web3.service;
+
+import static com.hedera.hapi.node.base.ResponseCodeEnum.CONTRACT_REVERT_EXECUTED;
+import static com.hedera.mirror.web3.evm.utils.EvmTokenUtils.toAddress;
+import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+import com.hedera.hapi.node.base.AccountID;
+import com.hedera.hapi.node.base.Timestamp;
+import com.hedera.hapi.node.base.TokenSupplyType;
+import com.hedera.hapi.node.base.TokenType;
+import com.hedera.hapi.node.scheduled.SchedulableTransactionBody;
+import com.hedera.hapi.node.token.TokenCreateTransactionBody;
+import com.hedera.mirror.common.domain.entity.EntityId;
+import com.hedera.mirror.common.domain.entity.EntityType;
+import com.hedera.mirror.web3.exception.MirrorEvmTransactionException;
+import com.hedera.mirror.web3.web3j.generated.GetScheduleInfo;
+import com.hedera.node.app.hapi.utils.CommonPbjConverters;
+import com.hederahashgraph.api.proto.java.ResponseCodeEnum;
+import java.math.BigInteger;
+import org.junit.jupiter.api.Test;
+
+/**
+ * This test class validates the correct results for getting schedule info for a token create transaction via smart contract calls .
+ */
+class ContractCallGetScheduleInfoTest extends AbstractContractCallServiceHistoricalTest {
+
+    @Test
+    void getFungibleCreateScheduleInfoNonExisting() {
+        // Cannot get schedule info for non-existing schedule
+        // Given
+        final var entity = domainBuilder.entityId();
+        final var nonExistingAddress = toAddress(entity).toHexString();
+        final var contract = testWeb3jService.deploy(GetScheduleInfo::deploy);
+        // When
+        final var functionCall = contract.call_getFungibleCreateTokenInfo(nonExistingAddress);
+        final var exception = assertThrows(MirrorEvmTransactionException.class, functionCall::send);
+        // Then
+        assertThat(exception.getMessage()).isEqualTo(CONTRACT_REVERT_EXECUTED.protoName());
+    }
+
+    @Test
+    void getNFTCreateScheduleInfoNonExisting() {
+        // Cannot get schedule info for non-existing schedule
+        // Given
+        final var entity = domainBuilder.entityId();
+        final var nonExistingAddress = toAddress(entity).toHexString();
+        final var contract = testWeb3jService.deploy(GetScheduleInfo::deploy);
+        // When
+        final var functionCall = contract.call_getNonFungibleCreateTokenInfo(nonExistingAddress);
+        final var exception = assertThrows(MirrorEvmTransactionException.class, functionCall::send);
+        // Then
+        assertThat(exception.getMessage()).isEqualTo(CONTRACT_REVERT_EXECUTED.protoName());
+    }
+
+    @Test
+    void getFungibleCreateScheduleInfo() throws Exception {
path: hedera-mirror-web3/src/test/java/com/hedera/mirror/web3/service/ContractCallGetScheduleInfoTest.java
user: login: bilyana-gospodinova
body: This test is identical to `getNonFungibleCreateScheduleInfo()` and can be parameterized.
created_at: 2025-05-13T12:39:52Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,191 @@
+// SPDX-License-Identifier: Apache-2.0
+
+package com.hedera.mirror.web3.service;
+
+import static com.hedera.hapi.node.base.ResponseCodeEnum.CONTRACT_REVERT_EXECUTED;
+import static com.hedera.mirror.web3.evm.utils.EvmTokenUtils.toAddress;
+import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+import com.hedera.hapi.node.base.AccountID;
+import com.hedera.hapi.node.base.Timestamp;
+import com.hedera.hapi.node.base.TokenSupplyType;
+import com.hedera.hapi.node.base.TokenType;
+import com.hedera.hapi.node.scheduled.SchedulableTransactionBody;
+import com.hedera.hapi.node.token.TokenCreateTransactionBody;
+import com.hedera.mirror.common.domain.entity.EntityId;
+import com.hedera.mirror.common.domain.entity.EntityType;
+import com.hedera.mirror.web3.exception.MirrorEvmTransactionException;
+import com.hedera.mirror.web3.web3j.generated.GetScheduleInfo;
+import com.hedera.node.app.hapi.utils.CommonPbjConverters;
+import com.hederahashgraph.api.proto.java.ResponseCodeEnum;
+import java.math.BigInteger;
+import org.junit.jupiter.api.Test;
+
+/**
+ * This test class validates the correct results for getting schedule info for a token create transaction via smart contract calls .
+ */
+class ContractCallGetScheduleInfoTest extends AbstractContractCallServiceHistoricalTest {
+
+    @Test
+    void getFungibleCreateScheduleInfoNonExisting() {
path: hedera-mirror-web3/src/test/java/com/hedera/mirror/web3/service/ContractCallGetScheduleInfoTest.java
user: login: bilyana-gospodinova
body: This test is identical to `getNFTCreateScheduleInfoNonExisting()` and can be parameterized.
created_at: 2025-05-13T12:40:36Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,191 @@
+// SPDX-License-Identifier: Apache-2.0
+
+package com.hedera.mirror.web3.service;
+
+import static com.hedera.hapi.node.base.ResponseCodeEnum.CONTRACT_REVERT_EXECUTED;
+import static com.hedera.mirror.web3.evm.utils.EvmTokenUtils.toAddress;
+import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+import com.hedera.hapi.node.base.AccountID;
+import com.hedera.hapi.node.base.Timestamp;
+import com.hedera.hapi.node.base.TokenSupplyType;
+import com.hedera.hapi.node.base.TokenType;
+import com.hedera.hapi.node.scheduled.SchedulableTransactionBody;
+import com.hedera.hapi.node.token.TokenCreateTransactionBody;
+import com.hedera.mirror.common.domain.entity.EntityId;
+import com.hedera.mirror.common.domain.entity.EntityType;
+import com.hedera.mirror.web3.exception.MirrorEvmTransactionException;
+import com.hedera.mirror.web3.web3j.generated.GetScheduleInfo;
+import com.hedera.node.app.hapi.utils.CommonPbjConverters;
+import com.hederahashgraph.api.proto.java.ResponseCodeEnum;
+import java.math.BigInteger;
+import org.junit.jupiter.api.Test;
+
+/**
+ * This test class validates the correct results for getting schedule info for a token create transaction via smart contract calls .
+ */
+class ContractCallGetScheduleInfoTest extends AbstractContractCallServiceHistoricalTest {
+
+    @Test
+    void getFungibleCreateScheduleInfoNonExisting() {
path: hedera-mirror-web3/src/test/java/com/hedera/mirror/web3/service/ContractCallGetScheduleInfoTest.java
user: login: nickeynikolovv
body: Addressed
created_at: 2025-05-14T12:55:51Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,191 @@
+// SPDX-License-Identifier: Apache-2.0
+
+package com.hedera.mirror.web3.service;
+
+import static com.hedera.hapi.node.base.ResponseCodeEnum.CONTRACT_REVERT_EXECUTED;
+import static com.hedera.mirror.web3.evm.utils.EvmTokenUtils.toAddress;
+import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+import com.hedera.hapi.node.base.AccountID;
+import com.hedera.hapi.node.base.Timestamp;
+import com.hedera.hapi.node.base.TokenSupplyType;
+import com.hedera.hapi.node.base.TokenType;
+import com.hedera.hapi.node.scheduled.SchedulableTransactionBody;
+import com.hedera.hapi.node.token.TokenCreateTransactionBody;
+import com.hedera.mirror.common.domain.entity.EntityId;
+import com.hedera.mirror.common.domain.entity.EntityType;
+import com.hedera.mirror.web3.exception.MirrorEvmTransactionException;
+import com.hedera.mirror.web3.web3j.generated.GetScheduleInfo;
+import com.hedera.node.app.hapi.utils.CommonPbjConverters;
+import com.hederahashgraph.api.proto.java.ResponseCodeEnum;
+import java.math.BigInteger;
+import org.junit.jupiter.api.Test;
+
+/**
+ * This test class validates the correct results for getting schedule info for a token create transaction via smart contract calls .
+ */
+class ContractCallGetScheduleInfoTest extends AbstractContractCallServiceHistoricalTest {
+
+    @Test
+    void getFungibleCreateScheduleInfoNonExisting() {
+        // Cannot get schedule info for non-existing schedule
+        // Given
+        final var entity = domainBuilder.entityId();
+        final var nonExistingAddress = toAddress(entity).toHexString();
+        final var contract = testWeb3jService.deploy(GetScheduleInfo::deploy);
+        // When
+        final var functionCall = contract.call_getFungibleCreateTokenInfo(nonExistingAddress);
+        final var exception = assertThrows(MirrorEvmTransactionException.class, functionCall::send);
+        // Then
+        assertThat(exception.getMessage()).isEqualTo(CONTRACT_REVERT_EXECUTED.protoName());
+    }
+
+    @Test
+    void getNFTCreateScheduleInfoNonExisting() {
+        // Cannot get schedule info for non-existing schedule
+        // Given
+        final var entity = domainBuilder.entityId();
+        final var nonExistingAddress = toAddress(entity).toHexString();
+        final var contract = testWeb3jService.deploy(GetScheduleInfo::deploy);
+        // When
+        final var functionCall = contract.call_getNonFungibleCreateTokenInfo(nonExistingAddress);
+        final var exception = assertThrows(MirrorEvmTransactionException.class, functionCall::send);
+        // Then
+        assertThat(exception.getMessage()).isEqualTo(CONTRACT_REVERT_EXECUTED.protoName());
+    }
+
+    @Test
+    void getFungibleCreateScheduleInfo() throws Exception {
path: hedera-mirror-web3/src/test/java/com/hedera/mirror/web3/service/ContractCallGetScheduleInfoTest.java
user: login: nickeynikolovv
body: The results that we get from the call_getFungibleCreateTokenInfo and call_getNonFungibleCreateTokenInfo are from different classes, therefore we cannot use the same assertions at the end of the tests. The results from the fungible one is from GetScheduleInfo->TokenInfo  and for the NFT is from GetScheduleInfo->NonFungibleTokenInfo and in order to make the test parameterized we will need to add two different sets of assertions one for fungible and one for NFT which is probably not the best solution. Cleaner and more readable in my opinion will be to be 2 separate tests. Wdyt?
created_at: 2025-05-14T13:00:00Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,191 @@
+// SPDX-License-Identifier: Apache-2.0
+
+package com.hedera.mirror.web3.service;
+
+import static com.hedera.hapi.node.base.ResponseCodeEnum.CONTRACT_REVERT_EXECUTED;
+import static com.hedera.mirror.web3.evm.utils.EvmTokenUtils.toAddress;
+import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+import com.hedera.hapi.node.base.AccountID;
+import com.hedera.hapi.node.base.Timestamp;
+import com.hedera.hapi.node.base.TokenSupplyType;
+import com.hedera.hapi.node.base.TokenType;
+import com.hedera.hapi.node.scheduled.SchedulableTransactionBody;
+import com.hedera.hapi.node.token.TokenCreateTransactionBody;
+import com.hedera.mirror.common.domain.entity.EntityId;
+import com.hedera.mirror.common.domain.entity.EntityType;
+import com.hedera.mirror.web3.exception.MirrorEvmTransactionException;
+import com.hedera.mirror.web3.web3j.generated.GetScheduleInfo;
+import com.hedera.node.app.hapi.utils.CommonPbjConverters;
+import com.hederahashgraph.api.proto.java.ResponseCodeEnum;
+import java.math.BigInteger;
+import org.junit.jupiter.api.Test;
+
+/**
+ * This test class validates the correct results for getting schedule info for a token create transaction via smart contract calls .
+ */
+class ContractCallGetScheduleInfoTest extends AbstractContractCallServiceHistoricalTest {
+
+    @Test
+    void getFungibleCreateScheduleInfoNonExisting() {
+        // Cannot get schedule info for non-existing schedule
+        // Given
+        final var entity = domainBuilder.entityId();
+        final var nonExistingAddress = toAddress(entity).toHexString();
+        final var contract = testWeb3jService.deploy(GetScheduleInfo::deploy);
+        // When
+        final var functionCall = contract.call_getFungibleCreateTokenInfo(nonExistingAddress);
+        final var exception = assertThrows(MirrorEvmTransactionException.class, functionCall::send);
+        // Then
+        assertThat(exception.getMessage()).isEqualTo(CONTRACT_REVERT_EXECUTED.protoName());
+    }
+
+    @Test
+    void getNFTCreateScheduleInfoNonExisting() {
+        // Cannot get schedule info for non-existing schedule
+        // Given
+        final var entity = domainBuilder.entityId();
+        final var nonExistingAddress = toAddress(entity).toHexString();
+        final var contract = testWeb3jService.deploy(GetScheduleInfo::deploy);
+        // When
+        final var functionCall = contract.call_getNonFungibleCreateTokenInfo(nonExistingAddress);
+        final var exception = assertThrows(MirrorEvmTransactionException.class, functionCall::send);
+        // Then
+        assertThat(exception.getMessage()).isEqualTo(CONTRACT_REVERT_EXECUTED.protoName());
+    }
+
+    @Test
+    void getFungibleCreateScheduleInfo() throws Exception {
path: hedera-mirror-web3/src/test/java/com/hedera/mirror/web3/service/ContractCallGetScheduleInfoTest.java
user: login: bilyana-gospodinova
body: I see. In this case it can remain as it is.
created_at: 2025-05-14T13:03:06Z
author_association: CONTRIBUTOR

PR comments:
user: login: lfdt-bot
created_at: 2025-05-05T11:44:11Z
body: ![](https://res.cloudinary.com/snyk/image/upload/r-d/scm-platform/snyk-pull-requests/pr-banner-default.svg)

### :tada: **Snyk checks have passed. No issues have been found so far.**

:white_check_mark: **security/snyk** check is complete. No issues have been found. [(View Details)](https://app.snyk.io/org/hiero-mirror-node/pr-checks/5729f48e-1b8c-4aa7-93ee-c97698ffd95a?refs=4fad102fd0163c5e92a6f7f021fac939adb10093&source=prChecksComment)

:white_check_mark: **license/snyk** check is complete. No issues have been found. [(View Details)](https://app.snyk.io/org/hiero-mirror-node/pr-checks/5729f48e-1b8c-4aa7-93ee-c97698ffd95a/license?refs=4fad102fd0163c5e92a6f7f021fac939adb10093&source=prChecksComment)

:white_check_mark: **code/snyk** check is complete. No issues have been found. [(View Details)](https://app.snyk.io/org/hiero-mirror-node/project/a07f98b0-76e6-4105-83b5-61050e93da72/pr-check/e8a19714-fa08-41df-b38d-fd7ceb89ae89?refs=4fad102fd0163c5e92a6f7f021fac939adb10093&source=prChecksComment)



author_association: NONE
user: login: codacy-production[bot]
created_at: 2025-05-19T14:46:02Z
body: ## Coverage summary from Codacy
### [See diff coverage on Codacy](https://app.codacy.com/gh/hiero-ledger/hiero-mirror-node/pull-requests/11101/coverage?utm_source=github.com&utm_medium=coverageSummary&utm_campaign=coverageSummaryPullRequest)

 | Coverage variation | Diff coverage | 
 | ------------- | ------------- |
 | :x: **-23.52%** (target: -1.00%) | :white_check_mark: **∅** |

<details>
<summary>Coverage variation details</summary>

| | Coverable lines | Covered lines | Coverage |
| ------------- | ------------- | ------------- | ------------- |
| Common ancestor commit (fef0791aee00963ee986ef65a89f058a312b5c74) | 35270 | 33392 | 94.68% | |
| Head commit (4fad102fd0163c5e92a6f7f021fac939adb10093) | 49848 (+14578) | 35470 (+2078) | 71.16% (**-23.52%**) |

**Coverage variation** is the difference between the coverage for the head and common ancestor commits of the pull request branch: `<coverage of head commit> - <coverage of common ancestor commit>`
</details>

<details>
<summary>Diff coverage details</summary>

| | Coverable lines | Covered lines | Diff coverage |
| ------------- | ------------- | ------------- | ------------- |
| Pull request (#11101) | 0 | 0 | **∅ (not applicable)** |

**Diff coverage** is the percentage of lines that are covered by tests out of the coverable lines that the pull request added or modified: `<covered lines added or modified>/<coverable lines added or modified> * 100%`
</details>

#### [See your quality gate settings](https://app.codacy.com/gh/hiero-ledger/hiero-mirror-node/settings/quality?utm_source=github.com&utm_medium=coverageSummary&utm_campaign=coverageSummaryGates)&nbsp;&nbsp;&nbsp;&nbsp;[Change summary preferences](https://app.codacy.com/gh/hiero-ledger/hiero-mirror-node/settings/integrations?utm_source=github.com&utm_medium=coverageSummary&utm_campaign=coverageSummarySettings)

<!-- 108f945d-e553-4918-8ccf-027c6d4acc2c -->
author_association: NONE