From e2f08024db2f75ee0c13bb56c552bbc8f0d71ec9 Mon Sep 17 00:00:00 2001 From: Stanimir Stoyanov Date: Wed, 5 Mar 2025 15:50:07 +0200 Subject: [PATCH] feat: HIP-1028 apply versioning to Update Token and Update Token Keys System Contracts (#17994) Signed-off-by: Lyuben Ivanov Signed-off-by: Stanimir Stoyanov Co-authored-by: Lyuben Ivanov --- .../processors/Hts0x167TranslatorsModule.java | 19 + .../processors/Hts0x16cTranslatorsModule.java | 29 ++ .../exec/processors/HtsTranslatorsModule.java | 46 --- .../ScheduleNativeTranslator.java | 4 +- .../hts/update/UpdateCommonDecoder.java | 225 +++++++++++ .../hts/update/UpdateCommons.java | 40 ++ .../hts/update/UpdateDecoder.java | 371 ------------------ .../hts/update/UpdateExpiryTranslator.java | 24 +- .../update/UpdateKeysCommonTranslator.java | 32 ++ .../hts/update/UpdateKeysTranslator.java | 78 ---- .../update/UpdateTokenCommonTranslator.java | 49 +++ .../hts/update/UpdateTranslator.java | 125 ------ .../update/address_0x167/UpdateDecoder.java | 122 ++++++ .../address_0x167/UpdateKeysTranslator.java | 46 +++ .../address_0x167/UpdateTranslator.java | 63 +++ .../update/address_0x16c/UpdateDecoder.java | 116 ++++++ .../address_0x16c/UpdateKeysTranslator.java | 46 +++ .../UpdateNFTsMetadataTranslator.java | 8 +- .../address_0x16c/UpdateTranslator.java | 43 ++ .../allowance/GetAllowanceTranslatorTest.java | 2 +- .../hts/burn/BurnTranslatorTest.java | 2 +- .../update/UpdateExpiryTranslatorTest.java | 8 +- .../UpdateNFTsMetadataTranslatorTest.java | 11 +- .../UpdateDecoderTest.java | 51 +-- .../UpdateKeysTranslatorTest.java | 6 +- .../UpdateTranslatorTest.java | 50 +-- .../address_0x16c/UpdateDecoderTest.java | 89 +++++ .../UpdateKeysTranslatorTest.java | 82 ++++ .../address_0x16c/UpdateTranslatorTest.java | 81 ++++ .../address_16c/NumericValidation16c.java | 53 +++ .../token/NumericValidationTest.java | 54 +-- .../precompile/token/TokenMetadataTest.java | 8 +- .../token/UpdateTokenMetadataTest.java | 3 +- .../UpdateTokenMetadata.bin | 1 - .../HederaTokenService/HederaTokenService.sol | 9 +- .../IHederaTokenService.sol | 3 + .../NumericContract16c/NumericContract16c.bin | 1 + .../NumericContract16c.json | 38 ++ .../NumericContract16c/NumericContract16c.sol | 20 + .../UpdateTokenMetadata.bin | 1 + .../UpdateTokenMetadata.json | 29 ++ .../UpdateTokenMetadata.sol | 5 +- 42 files changed, 1311 insertions(+), 782 deletions(-) create mode 100644 hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/exec/systemcontracts/hts/update/UpdateCommonDecoder.java create mode 100644 hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/exec/systemcontracts/hts/update/UpdateCommons.java delete mode 100644 hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/exec/systemcontracts/hts/update/UpdateDecoder.java create mode 100644 hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/exec/systemcontracts/hts/update/UpdateKeysCommonTranslator.java delete mode 100644 hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/exec/systemcontracts/hts/update/UpdateKeysTranslator.java create mode 100644 hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/exec/systemcontracts/hts/update/UpdateTokenCommonTranslator.java delete mode 100644 hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/exec/systemcontracts/hts/update/UpdateTranslator.java create mode 100644 hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/exec/systemcontracts/hts/update/address_0x167/UpdateDecoder.java create mode 100644 hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/exec/systemcontracts/hts/update/address_0x167/UpdateKeysTranslator.java create mode 100644 hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/exec/systemcontracts/hts/update/address_0x167/UpdateTranslator.java create mode 100644 hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/exec/systemcontracts/hts/update/address_0x16c/UpdateDecoder.java create mode 100644 hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/exec/systemcontracts/hts/update/address_0x16c/UpdateKeysTranslator.java rename hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/exec/systemcontracts/hts/update/{ => address_0x16c}/UpdateNFTsMetadataTranslator.java (93%) create mode 100644 hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/exec/systemcontracts/hts/update/address_0x16c/UpdateTranslator.java rename hedera-node/hedera-smart-contract-service-impl/src/test/java/com/hedera/node/app/service/contract/impl/test/exec/systemcontracts/hts/update/{ => address_0x167}/UpdateDecoderTest.java (73%) rename hedera-node/hedera-smart-contract-service-impl/src/test/java/com/hedera/node/app/service/contract/impl/test/exec/systemcontracts/hts/update/{ => address_0x167}/UpdateKeysTranslatorTest.java (95%) rename hedera-node/hedera-smart-contract-service-impl/src/test/java/com/hedera/node/app/service/contract/impl/test/exec/systemcontracts/hts/update/{ => address_0x167}/UpdateTranslatorTest.java (90%) create mode 100644 hedera-node/hedera-smart-contract-service-impl/src/test/java/com/hedera/node/app/service/contract/impl/test/exec/systemcontracts/hts/update/address_0x16c/UpdateDecoderTest.java create mode 100644 hedera-node/hedera-smart-contract-service-impl/src/test/java/com/hedera/node/app/service/contract/impl/test/exec/systemcontracts/hts/update/address_0x16c/UpdateKeysTranslatorTest.java create mode 100644 hedera-node/hedera-smart-contract-service-impl/src/test/java/com/hedera/node/app/service/contract/impl/test/exec/systemcontracts/hts/update/address_0x16c/UpdateTranslatorTest.java create mode 100644 hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/address_16c/NumericValidation16c.java delete mode 100644 hedera-node/test-clients/src/main/resources/contract/contracts/UpdateTokenMetadata/UpdateTokenMetadata.bin create mode 100644 hedera-node/test-clients/src/main/resources/contract/contracts_16c/NumericContract16c/NumericContract16c.bin create mode 100644 hedera-node/test-clients/src/main/resources/contract/contracts_16c/NumericContract16c/NumericContract16c.json create mode 100644 hedera-node/test-clients/src/main/resources/contract/contracts_16c/NumericContract16c/NumericContract16c.sol create mode 100644 hedera-node/test-clients/src/main/resources/contract/contracts_16c/UpdateTokenMetadata/UpdateTokenMetadata.bin rename hedera-node/test-clients/src/main/resources/contract/{contracts => contracts_16c}/UpdateTokenMetadata/UpdateTokenMetadata.json (83%) rename hedera-node/test-clients/src/main/resources/contract/{contracts => contracts_16c}/UpdateTokenMetadata/UpdateTokenMetadata.sol (77%) diff --git a/hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/exec/processors/Hts0x167TranslatorsModule.java b/hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/exec/processors/Hts0x167TranslatorsModule.java index fee6ac75b2b..5b6e0fda5c9 100644 --- a/hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/exec/processors/Hts0x167TranslatorsModule.java +++ b/hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/exec/processors/Hts0x167TranslatorsModule.java @@ -5,6 +5,8 @@ import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.HtsCallAttempt; import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.create.address_0x167.CreateTranslator; import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.tokentype.address_0x167.TokenTypeTranslator; +import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.update.address_0x167.UpdateKeysTranslator; +import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.update.address_0x167.UpdateTranslator; import dagger.Module; import dagger.Provides; import dagger.multibindings.IntoSet; @@ -33,4 +35,21 @@ static CallTranslator provideTokenTypeTranslator(@NonNull final static CallTranslator provideCreateTranslator(@NonNull final CreateTranslator translator) { return translator; } + + @Provides + @Singleton + @IntoSet + @Named("HtsTranslators") + static CallTranslator provideUpdateKeysTranslator(@NonNull final UpdateKeysTranslator translator) { + return translator; + } + + @Provides + @Singleton + @IntoSet + @Named("HtsTranslators") + static CallTranslator provideUpdateTokenCommonTranslator( + @NonNull final UpdateTranslator translator) { + return translator; + } } diff --git a/hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/exec/processors/Hts0x16cTranslatorsModule.java b/hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/exec/processors/Hts0x16cTranslatorsModule.java index 46c01a807fc..b9e02f7823d 100644 --- a/hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/exec/processors/Hts0x16cTranslatorsModule.java +++ b/hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/exec/processors/Hts0x16cTranslatorsModule.java @@ -5,6 +5,9 @@ import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.HtsCallAttempt; import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.create.address_0x16c.CreateTranslator; import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.tokentype.address_0x16c.TokenTypeTranslator; +import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.update.address_0x16c.UpdateKeysTranslator; +import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.update.address_0x16c.UpdateNFTsMetadataTranslator; +import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.update.address_0x16c.UpdateTranslator; import dagger.Module; import dagger.Provides; import dagger.multibindings.IntoSet; @@ -33,4 +36,30 @@ static CallTranslator provideTokenTypeTranslator(@NonNull final static CallTranslator provideCreateTranslator(@NonNull final CreateTranslator translator) { return translator; } + + @Provides + @Singleton + @IntoSet + @Named("HtsTranslators") + static CallTranslator provideUpdateKeysTranslator(@NonNull final UpdateKeysTranslator translator) { + return translator; + } + + @Provides + @Singleton + @IntoSet + @Named("HtsTranslators") + static CallTranslator provideUpdateTokenCommonTranslator( + @NonNull final UpdateTranslator translator) { + return translator; + } + + @Provides + @Singleton + @IntoSet + @Named("HtsTranslators") + static CallTranslator provideUpdateNFTsMetadataTranslator( + @NonNull final UpdateNFTsMetadataTranslator translator) { + return translator; + } } diff --git a/hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/exec/processors/HtsTranslatorsModule.java b/hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/exec/processors/HtsTranslatorsModule.java index e7a9d0c3082..61e196462a5 100644 --- a/hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/exec/processors/HtsTranslatorsModule.java +++ b/hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/exec/processors/HtsTranslatorsModule.java @@ -10,7 +10,6 @@ import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.burn.BurnTranslator; import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.cancelairdrops.TokenCancelAirdropTranslator; import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.claimairdrops.TokenClaimAirdropTranslator; -import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.create.address_0x167.CreateTranslator; import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.customfees.TokenCustomFeesTranslator; import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.decimals.DecimalsTranslator; import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.defaultfreezestatus.DefaultFreezeStatusTranslator; @@ -37,16 +36,12 @@ import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.tokenexpiry.TokenExpiryTranslator; import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.tokeninfo.TokenInfoTranslator; import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.tokenkey.TokenKeyTranslator; -import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.tokentype.address_0x167.TokenTypeTranslator; import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.tokenuri.TokenUriTranslator; import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.totalsupply.TotalSupplyTranslator; import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.transfer.ClassicTransfersTranslator; import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.transfer.Erc20TransfersTranslator; import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.transfer.Erc721TransferFromTranslator; import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.update.UpdateExpiryTranslator; -import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.update.UpdateKeysTranslator; -import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.update.UpdateNFTsMetadataTranslator; -import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.update.UpdateTranslator; import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.updatetokencustomfees.UpdateTokenCustomFeesTranslator; import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.wipe.WipeTranslator; import dagger.Module; @@ -132,14 +127,6 @@ static CallTranslator provideBurnTranslator(@NonNull final BurnT return translator; } - @Provides - @Singleton - @IntoSet - @Named("HtsTranslators") - static CallTranslator provideCreateTranslator(@NonNull final CreateTranslator translator) { - return translator; - } - @Provides @Singleton @IntoSet @@ -290,14 +277,6 @@ static CallTranslator provideIsTokenTranslator(@NonNull final Is return translator; } - @Provides - @Singleton - @IntoSet - @Named("HtsTranslators") - static CallTranslator provideTokenTypeTranslator(@NonNull final TokenTypeTranslator translator) { - return translator; - } - @Provides @Singleton @IntoSet @@ -350,14 +329,6 @@ static CallTranslator provideTokenKeyTranslator(@NonNull final T return translator; } - @Provides - @Singleton - @IntoSet - @Named("HtsTranslators") - static CallTranslator provideUpdateTranslator(@NonNull final UpdateTranslator translator) { - return translator; - } - @Provides @Singleton @IntoSet @@ -402,14 +373,6 @@ static CallTranslator provideNonFungibleTokenInfoTranslator( return translator; } - @Provides - @Singleton - @IntoSet - @Named("HtsTranslators") - static CallTranslator provideUpdateKeysTranslator(@NonNull final UpdateKeysTranslator translator) { - return translator; - } - @Provides @Singleton @IntoSet @@ -419,15 +382,6 @@ static CallTranslator provideUpdateTokenCustomFeesTranslator( return translator; } - @Provides - @Singleton - @IntoSet - @Named("HtsTranslators") - static CallTranslator provideUpdateNFTsMetadataTranslator( - @NonNull final UpdateNFTsMetadataTranslator translator) { - return translator; - } - @Provides @Singleton @IntoSet diff --git a/hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/exec/systemcontracts/hss/schedulenative/ScheduleNativeTranslator.java b/hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/exec/systemcontracts/hss/schedulenative/ScheduleNativeTranslator.java index 636d1feb316..86e3ba57ff0 100644 --- a/hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/exec/systemcontracts/hss/schedulenative/ScheduleNativeTranslator.java +++ b/hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/exec/systemcontracts/hss/schedulenative/ScheduleNativeTranslator.java @@ -3,7 +3,7 @@ import static com.hedera.node.app.service.contract.impl.exec.systemcontracts.HtsSystemContract.HTS_167_EVM_ADDRESS; import static com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.create.CreateCommons.createMethodsSet; -import static com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.update.UpdateTranslator.updateMethodsMap; +import static com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.update.UpdateCommons.updateMethodsSet; import static com.hedera.node.app.spi.workflows.HandleException.validateTrue; import static java.util.Objects.requireNonNull; import static org.hyperledger.besu.datatypes.Address.fromHexString; @@ -120,7 +120,7 @@ private boolean innerCallValidation(@NonNull final HssCallAttempt attempt) { final var canBeCreateToken = createMethodsSet.stream().anyMatch(s -> Arrays.equals(s.selector(), innerCallSelector)); final var canBeUpdateToken = - updateMethodsMap.keySet().stream().anyMatch(s -> Arrays.equals(s.selector(), innerCallSelector)); + updateMethodsSet.stream().anyMatch(s -> Arrays.equals(s.selector(), innerCallSelector)); return canBeCreateToken || canBeUpdateToken; } diff --git a/hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/exec/systemcontracts/hts/update/UpdateCommonDecoder.java b/hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/exec/systemcontracts/hts/update/UpdateCommonDecoder.java new file mode 100644 index 00000000000..46bbcd38d7f --- /dev/null +++ b/hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/exec/systemcontracts/hts/update/UpdateCommonDecoder.java @@ -0,0 +1,225 @@ +// SPDX-License-Identifier: Apache-2.0 +package com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.update; + +import static com.hedera.hapi.node.base.ResponseCodeEnum.INVALID_ACCOUNT_ID; +import static com.hedera.hapi.node.base.ResponseCodeEnum.INVALID_SIGNATURE; +import static com.hedera.hapi.node.base.ResponseCodeEnum.INVALID_TREASURY_ACCOUNT_FOR_TOKEN; +import static com.hedera.hapi.node.base.ResponseCodeEnum.TOKEN_IS_IMMUTABLE; +import static com.hedera.node.app.service.contract.impl.utils.ConversionUtils.asNumericContractId; +import static com.hedera.node.app.spi.key.KeyUtils.IMMUTABILITY_SENTINEL_KEY; + +import com.esaulpaugh.headlong.abi.Tuple; +import com.hedera.hapi.node.base.Duration; +import com.hedera.hapi.node.base.Key; +import com.hedera.hapi.node.base.Timestamp; +import com.hedera.hapi.node.base.TokenID; +import com.hedera.hapi.node.state.token.Token; +import com.hedera.hapi.node.token.TokenUpdateTransactionBody; +import com.hedera.hapi.node.transaction.TransactionBody; +import com.hedera.node.app.service.contract.impl.exec.scope.HederaNativeOperations; +import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.AddressIdConverter; +import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.DispatchForResponseCodeHtsCall; +import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.HtsCallAttempt; +import com.hedera.node.app.service.contract.impl.exec.utils.KeyValueWrapper; +import com.hedera.node.app.service.contract.impl.exec.utils.TokenExpiryWrapper; +import com.hedera.node.app.service.contract.impl.exec.utils.TokenKeyWrapper; +import com.hedera.node.app.service.contract.impl.utils.ConversionUtils; +import edu.umd.cs.findbugs.annotations.NonNull; +import edu.umd.cs.findbugs.annotations.Nullable; +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.List; + +public abstract class UpdateCommonDecoder { + + /** + * A customizer that refines {@link com.hedera.hapi.node.base.ResponseCodeEnum#INVALID_ACCOUNT_ID} and + * {@link com.hedera.hapi.node.base.ResponseCodeEnum#INVALID_SIGNATURE} response codes. + */ + public static final DispatchForResponseCodeHtsCall.FailureCustomizer FAILURE_CUSTOMIZER = + (body, code, enhancement) -> { + if (code == INVALID_ACCOUNT_ID) { + final var op = body.tokenUpdateOrThrow(); + if (op.hasTreasury()) { + final var accountStore = enhancement.nativeOperations().readableAccountStore(); + final var maybeTreasury = accountStore.getAccountById(op.treasuryOrThrow()); + if (maybeTreasury == null) { + return INVALID_TREASURY_ACCOUNT_FOR_TOKEN; + } + } + } else if (code == INVALID_SIGNATURE) { + final var op = body.tokenUpdateOrThrow(); + final var tokenStore = enhancement.nativeOperations().readableTokenStore(); + if (isKnownImmutable(tokenStore.get(op.tokenOrElse(TokenID.DEFAULT)))) { + return TOKEN_IS_IMMUTABLE; + } + } + return code; + }; + + // below values correspond to tuples' indexes + protected static final int TOKEN_ADDRESS = 0; + protected static final int HEDERA_TOKEN = 1; + + protected static final int EXPIRY = 1; + protected static final int TOKEN_KEYS = 1; + + protected static final int KEY_TYPE = 0; + protected static final int KEY_VALUE = 1; + protected static final int SERIAL_NUMBERS = 1; + protected static final int METADATA = 2; + + protected static final int INHERIT_ACCOUNT_KEY = 0; + protected static final int CONTRACT_ID = 1; + protected static final int ED25519 = 2; + protected static final int ECDSA_SECP_256K1 = 3; + protected static final int DELEGATABLE_CONTRACT_ID = 4; + + private static boolean isKnownImmutable(@Nullable final Token token) { + return token != null && IMMUTABILITY_SENTINEL_KEY.equals(token.adminKeyOrElse(IMMUTABILITY_SENTINEL_KEY)); + } + + protected TokenUpdateTransactionBody.Builder decodeTokenUpdate( + @NonNull final Tuple call, + @NonNull final AddressIdConverter addressIdConverter, + @NonNull final HederaNativeOperations nativeOperation) { + final var tokenId = ConversionUtils.asTokenId(call.get(TOKEN_ADDRESS)); + final var hederaToken = (Tuple) call.get(HEDERA_TOKEN); + + final var tokenName = (String) hederaToken.get(0); + final var tokenSymbol = (String) hederaToken.get(1); + final var tokenTreasury = addressIdConverter.convert(hederaToken.get(2)); + final var memo = (String) hederaToken.get(3); + final List tokenKeys = + decodeTokenKeys(hederaToken.get(7), addressIdConverter, nativeOperation); + final var tokenExpiry = decodeTokenExpiry(hederaToken.get(8), addressIdConverter); + + // Build the transaction body + final var txnBodyBuilder = TokenUpdateTransactionBody.newBuilder(); + txnBodyBuilder.token(tokenId); + + if (tokenName != null) { + txnBodyBuilder.name(tokenName); + } + if (tokenSymbol != null) { + txnBodyBuilder.symbol(tokenSymbol); + } + if (memo != null) { + txnBodyBuilder.memo(memo); + } + + txnBodyBuilder.treasury(tokenTreasury); + + if (tokenExpiry.second() != 0) { + txnBodyBuilder.expiry( + Timestamp.newBuilder().seconds(tokenExpiry.second()).build()); + } + if (tokenExpiry.autoRenewAccount() != null) { + txnBodyBuilder.autoRenewAccount(tokenExpiry.autoRenewAccount()); + } + if (tokenExpiry.autoRenewPeriod() != null + && tokenExpiry.autoRenewPeriod().seconds() != 0) { + txnBodyBuilder.autoRenewPeriod(tokenExpiry.autoRenewPeriod()); + } + addKeys(tokenKeys, txnBodyBuilder); + return txnBodyBuilder; + } + + protected List decodeTokenKeys( + @NonNull final Tuple[] tokenKeysTuples, + @NonNull final AddressIdConverter addressIdConverter, + @NonNull final HederaNativeOperations nativeOperation) { + final List tokenKeys = new ArrayList<>(tokenKeysTuples.length); + for (final var tokenKeyTuple : tokenKeysTuples) { + final var keyType = ((BigInteger) tokenKeyTuple.get(KEY_TYPE)).intValue(); + final Tuple keyValueTuple = tokenKeyTuple.get(KEY_VALUE); + final var inheritAccountKey = (Boolean) keyValueTuple.get(INHERIT_ACCOUNT_KEY); + final byte[] ed25519 = keyValueTuple.get(ED25519); + final byte[] ecdsaSecp256K1 = keyValueTuple.get(ECDSA_SECP_256K1); + final var entityIdFactory = nativeOperation.entityIdFactory(); + final var contractId = + asNumericContractId(entityIdFactory, addressIdConverter.convert(keyValueTuple.get(CONTRACT_ID))); + final var delegatableContractId = asNumericContractId( + entityIdFactory, addressIdConverter.convert(keyValueTuple.get(DELEGATABLE_CONTRACT_ID))); + + tokenKeys.add(new TokenKeyWrapper( + keyType, + new KeyValueWrapper( + inheritAccountKey, + contractId.contractNumOrThrow() != 0 ? contractId : null, + ed25519, + ecdsaSecp256K1, + delegatableContractId.contractNumOrThrow() != 0 ? delegatableContractId : null))); + } + + return tokenKeys; + } + + @Nullable + public TransactionBody decodeTokenUpdateKeys(@NonNull final HtsCallAttempt attempt) { + + final var call = decodeCall(attempt); + + final var tokenId = ConversionUtils.asTokenId(call.get(TOKEN_ADDRESS)); + final var tokenKeys = + decodeTokenKeys(call.get(TOKEN_KEYS), attempt.addressIdConverter(), attempt.nativeOperations()); + + // Build the transaction body + final var txnBodyBuilder = TokenUpdateTransactionBody.newBuilder(); + txnBodyBuilder.token(tokenId); + addKeys(tokenKeys, txnBodyBuilder); + + try { + return TransactionBody.newBuilder().tokenUpdate(txnBodyBuilder).build(); + } catch (final IllegalArgumentException ignore) { + return null; + } + } + + protected abstract Tuple decodeCall(@NonNull final HtsCallAttempt attempt); + + protected void addKeys(final List tokenKeys, final TokenUpdateTransactionBody.Builder builder) { + tokenKeys.forEach(tokenKeyWrapper -> { + final var key = tokenKeyWrapper.key().asGrpc(); + if (key == Key.DEFAULT) { + throw new IllegalArgumentException(); + } + setUsedKeys(builder, tokenKeyWrapper, key); + }); + } + + private void setUsedKeys( + final TokenUpdateTransactionBody.Builder builder, final TokenKeyWrapper tokenKeyWrapper, final Key key) { + if (tokenKeyWrapper.isUsedForAdminKey()) { + builder.adminKey(key); + } + if (tokenKeyWrapper.isUsedForKycKey()) { + builder.kycKey(key); + } + if (tokenKeyWrapper.isUsedForFreezeKey()) { + builder.freezeKey(key); + } + if (tokenKeyWrapper.isUsedForWipeKey()) { + builder.wipeKey(key); + } + if (tokenKeyWrapper.isUsedForSupplyKey()) { + builder.supplyKey(key); + } + if (tokenKeyWrapper.isUsedForFeeScheduleKey()) { + builder.feeScheduleKey(key); + } + if (tokenKeyWrapper.isUsedForPauseKey()) { + builder.pauseKey(key); + } + } + + protected TokenExpiryWrapper decodeTokenExpiry( + @NonNull final Tuple expiryTuple, @NonNull final AddressIdConverter addressIdConverter) { + final var second = (long) expiryTuple.get(0); + final var autoRenewAccount = addressIdConverter.convert(expiryTuple.get(1)); + final var autoRenewPeriod = + Duration.newBuilder().seconds(expiryTuple.get(2)).build(); + return new TokenExpiryWrapper( + second, autoRenewAccount.accountNumOrElse(0L) == 0 ? null : autoRenewAccount, autoRenewPeriod); + } +} diff --git a/hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/exec/systemcontracts/hts/update/UpdateCommons.java b/hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/exec/systemcontracts/hts/update/UpdateCommons.java new file mode 100644 index 00000000000..fb7aa13ff8c --- /dev/null +++ b/hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/exec/systemcontracts/hts/update/UpdateCommons.java @@ -0,0 +1,40 @@ +// SPDX-License-Identifier: Apache-2.0 +package com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.update; + +import com.hedera.hapi.node.base.AccountID; +import com.hedera.hapi.node.transaction.TransactionBody; +import com.hedera.node.app.service.contract.impl.exec.gas.DispatchType; +import com.hedera.node.app.service.contract.impl.exec.gas.SystemContractGasCalculator; +import com.hedera.node.app.service.contract.impl.exec.utils.SystemContractMethod; +import com.hedera.node.app.service.contract.impl.hevm.HederaWorldUpdater; +import edu.umd.cs.findbugs.annotations.NonNull; +import java.util.HashSet; +import java.util.Set; +import javax.inject.Singleton; + +/** + * Provides common functionality for the update related system contracts. + */ +@Singleton +public final class UpdateCommons { + + // The set of all update system contract methods + public static final Set updateMethodsSet = new HashSet<>(); + + /** + * @param body the transaction body to be dispatched + * @param systemContractGasCalculator the gas calculator for the system contract + * @param enhancement the enhancement to use + * @param payerId the payer of the transaction + * @return the required gas + */ + public static long gasRequirement( + @NonNull final TransactionBody body, + @NonNull final SystemContractGasCalculator systemContractGasCalculator, + @NonNull final HederaWorldUpdater.Enhancement enhancement, + @NonNull final AccountID payerId) { + return systemContractGasCalculator.gasRequirement(body, DispatchType.UPDATE, payerId); + } + + private UpdateCommons() {} +} diff --git a/hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/exec/systemcontracts/hts/update/UpdateDecoder.java b/hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/exec/systemcontracts/hts/update/UpdateDecoder.java deleted file mode 100644 index f05f49612af..00000000000 --- a/hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/exec/systemcontracts/hts/update/UpdateDecoder.java +++ /dev/null @@ -1,371 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -package com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.update; - -import static com.hedera.hapi.node.base.ResponseCodeEnum.INVALID_ACCOUNT_ID; -import static com.hedera.hapi.node.base.ResponseCodeEnum.INVALID_SIGNATURE; -import static com.hedera.hapi.node.base.ResponseCodeEnum.INVALID_TREASURY_ACCOUNT_FOR_TOKEN; -import static com.hedera.hapi.node.base.ResponseCodeEnum.TOKEN_IS_IMMUTABLE; -import static com.hedera.node.app.service.contract.impl.utils.ConversionUtils.asNumericContractId; -import static com.hedera.node.app.spi.key.KeyUtils.IMMUTABILITY_SENTINEL_KEY; - -import com.esaulpaugh.headlong.abi.Address; -import com.esaulpaugh.headlong.abi.Tuple; -import com.google.common.primitives.Longs; -import com.hedera.hapi.node.base.Duration; -import com.hedera.hapi.node.base.Key; -import com.hedera.hapi.node.base.Timestamp; -import com.hedera.hapi.node.base.TokenID; -import com.hedera.hapi.node.state.token.Token; -import com.hedera.hapi.node.token.TokenUpdateNftsTransactionBody; -import com.hedera.hapi.node.token.TokenUpdateTransactionBody; -import com.hedera.hapi.node.token.TokenUpdateTransactionBody.Builder; -import com.hedera.hapi.node.transaction.TransactionBody; -import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.AddressIdConverter; -import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.DispatchForResponseCodeHtsCall; -import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.HtsCallAttempt; -import com.hedera.node.app.service.contract.impl.exec.utils.KeyValueWrapper; -import com.hedera.node.app.service.contract.impl.exec.utils.TokenExpiryWrapper; -import com.hedera.node.app.service.contract.impl.exec.utils.TokenKeyWrapper; -import com.hedera.node.app.service.contract.impl.utils.ConversionUtils; -import com.hedera.node.config.data.ContractsConfig; -import com.hedera.pbj.runtime.io.buffer.Bytes; -import edu.umd.cs.findbugs.annotations.NonNull; -import edu.umd.cs.findbugs.annotations.Nullable; -import java.math.BigInteger; -import java.util.ArrayList; -import java.util.List; -import javax.inject.Inject; -import javax.inject.Singleton; - -@Singleton -public class UpdateDecoder { - /** - * A customizer that refines {@link com.hedera.hapi.node.base.ResponseCodeEnum#INVALID_ACCOUNT_ID} and - * {@link com.hedera.hapi.node.base.ResponseCodeEnum#INVALID_SIGNATURE} response codes. - */ - public static final DispatchForResponseCodeHtsCall.FailureCustomizer FAILURE_CUSTOMIZER = - (body, code, enhancement) -> { - if (code == INVALID_ACCOUNT_ID) { - final var op = body.tokenUpdateOrThrow(); - if (op.hasTreasury()) { - final var accountStore = enhancement.nativeOperations().readableAccountStore(); - final var maybeTreasury = accountStore.getAccountById(op.treasuryOrThrow()); - if (maybeTreasury == null) { - return INVALID_TREASURY_ACCOUNT_FOR_TOKEN; - } - } - } else if (code == INVALID_SIGNATURE) { - final var op = body.tokenUpdateOrThrow(); - final var tokenStore = enhancement.nativeOperations().readableTokenStore(); - if (isKnownImmutable(tokenStore.get(op.tokenOrElse(TokenID.DEFAULT)))) { - return TOKEN_IS_IMMUTABLE; - } - } - return code; - }; - // below values correspond to tuples' indexes - private static final int TOKEN_ADDRESS = 0; - private static final int HEDERA_TOKEN = 1; - - private static final int EXPIRY = 1; - private static final int TOKEN_KEYS = 1; - - private static final int KEY_TYPE = 0; - private static final int KEY_VALUE = 1; - private static final int SERIAL_NUMBERS = 1; - private static final int METADATA = 2; - - private static final int INHERIT_ACCOUNT_KEY = 0; - private static final int CONTRACT_ID = 1; - private static final int ED25519 = 2; - private static final int ECDSA_SECP_256K1 = 3; - private static final int DELEGATABLE_CONTRACT_ID = 4; - - @Inject - public UpdateDecoder() { - // Dagger2 - } - - private static boolean isKnownImmutable(@Nullable final Token token) { - return token != null && IMMUTABILITY_SENTINEL_KEY.equals(token.adminKeyOrElse(IMMUTABILITY_SENTINEL_KEY)); - } - - /** - * Decodes a call to {@link UpdateTranslator#TOKEN_UPDATE_INFO_FUNCTION_V1} into a synthetic {@link TransactionBody}. - * - * @param attempt the attempt - * @return the synthetic transaction body - */ - public @Nullable TransactionBody decodeTokenUpdateV1(@NonNull final HtsCallAttempt attempt) { - final var call = UpdateTranslator.TOKEN_UPDATE_INFO_FUNCTION_V1.decodeCall( - attempt.input().toArrayUnsafe()); - final var decoded = decodeTokenUpdate(call, attempt); - return TransactionBody.newBuilder().tokenUpdate(decoded).build(); - } - - /** - * Decodes a call to {@link UpdateTranslator#TOKEN_UPDATE_INFO_FUNCTION_V2} into a synthetic {@link TransactionBody}. - * - * @param attempt the attempt - * @return the synthetic transaction body - */ - public @Nullable TransactionBody decodeTokenUpdateV2(@NonNull final HtsCallAttempt attempt) { - final var call = UpdateTranslator.TOKEN_UPDATE_INFO_FUNCTION_V2.decodeCall( - attempt.input().toArrayUnsafe()); - final var decoded = decodeTokenUpdate(call, attempt); - return TransactionBody.newBuilder().tokenUpdate(decoded).build(); - } - - /** - * Decodes a call to {@link UpdateTranslator#TOKEN_UPDATE_INFO_FUNCTION_WITH_METADATA} into a synthetic {@link TransactionBody}. - * - * @param attempt the attempt - * @return the synthetic transaction body - */ - public TransactionBody decodeTokenUpdateWithMetadata(@NonNull final HtsCallAttempt attempt) { - final var call = UpdateTranslator.TOKEN_UPDATE_INFO_FUNCTION_WITH_METADATA.decodeCall( - attempt.input().toArrayUnsafe()); - final var decoded = decodeUpdateWithMeta(call, attempt); - return TransactionBody.newBuilder().tokenUpdate(decoded).build(); - } - - /** - * Decodes a call to {@link UpdateTranslator#TOKEN_UPDATE_INFO_FUNCTION_V3} into a synthetic {@link TransactionBody}. - * - * @param attempt the attempt - * @return the synthetic transaction body - */ - public @Nullable TransactionBody decodeTokenUpdateV3(@NonNull final HtsCallAttempt attempt) { - final var call = UpdateTranslator.TOKEN_UPDATE_INFO_FUNCTION_V3.decodeCall( - attempt.input().toArrayUnsafe()); - final var decoded = decodeTokenUpdate(call, attempt); - return TransactionBody.newBuilder().tokenUpdate(decoded).build(); - } - - /** - * Decodes a call to {@link UpdateExpiryTranslator#UPDATE_TOKEN_EXPIRY_INFO_V1} into a synthetic {@link TransactionBody}. - * - * @param attempt the attempt - * @return the synthetic transaction body - */ - public TransactionBody decodeTokenUpdateExpiryV1(@NonNull final HtsCallAttempt attempt) { - final var call = UpdateExpiryTranslator.UPDATE_TOKEN_EXPIRY_INFO_V1.decodeCall( - attempt.input().toArrayUnsafe()); - return decodeTokenUpdateExpiry(call, attempt.addressIdConverter()); - } - - /** - * Decodes a call to {@link UpdateExpiryTranslator#UPDATE_TOKEN_EXPIRY_INFO_V2} into a synthetic {@link TransactionBody}. - * - * @param attempt the attempt - * @return the synthetic transaction body - */ - public TransactionBody decodeTokenUpdateExpiryV2(@NonNull final HtsCallAttempt attempt) { - final var call = UpdateExpiryTranslator.UPDATE_TOKEN_EXPIRY_INFO_V2.decodeCall( - attempt.input().toArrayUnsafe()); - return decodeTokenUpdateExpiry(call, attempt.addressIdConverter()); - } - - private TokenUpdateTransactionBody.Builder decodeTokenUpdate( - @NonNull final Tuple call, @NonNull final HtsCallAttempt attempt) { - final var tokenId = ConversionUtils.asTokenId(call.get(TOKEN_ADDRESS)); - final var hederaToken = (Tuple) call.get(HEDERA_TOKEN); - - final var tokenName = (String) hederaToken.get(0); - final var tokenSymbol = (String) hederaToken.get(1); - final var tokenTreasury = attempt.addressIdConverter().convert(hederaToken.get(2)); - final var memo = (String) hederaToken.get(3); - final List tokenKeys = decodeTokenKeys(hederaToken.get(7), attempt); - final var tokenExpiry = decodeTokenExpiry(hederaToken.get(8), attempt.addressIdConverter()); - - // Build the transaction body - final var txnBodyBuilder = TokenUpdateTransactionBody.newBuilder(); - txnBodyBuilder.token(tokenId); - - if (tokenName != null) { - txnBodyBuilder.name(tokenName); - } - if (tokenSymbol != null) { - txnBodyBuilder.symbol(tokenSymbol); - } - if (memo != null) { - txnBodyBuilder.memo(memo); - } - - txnBodyBuilder.treasury(tokenTreasury); - - if (tokenExpiry.second() != 0) { - txnBodyBuilder.expiry( - Timestamp.newBuilder().seconds(tokenExpiry.second()).build()); - } - if (tokenExpiry.autoRenewAccount() != null) { - txnBodyBuilder.autoRenewAccount(tokenExpiry.autoRenewAccount()); - } - if (tokenExpiry.autoRenewPeriod() != null - && tokenExpiry.autoRenewPeriod().seconds() != 0) { - txnBodyBuilder.autoRenewPeriod(tokenExpiry.autoRenewPeriod()); - } - addKeys(tokenKeys, txnBodyBuilder); - return txnBodyBuilder; - } - - public TokenUpdateTransactionBody.Builder decodeUpdateWithMeta( - @NonNull final Tuple call, @NonNull final HtsCallAttempt attempt) { - final var tokenUpdateTransactionBody = decodeTokenUpdate(call, attempt); - final var hederaToken = (Tuple) call.get(HEDERA_TOKEN); - final Bytes tokenMetadata = hederaToken.size() > 9 ? Bytes.wrap((byte[]) hederaToken.get(9)) : null; - if (tokenMetadata != null && tokenMetadata.length() > 0) { - tokenUpdateTransactionBody.metadata(tokenMetadata); - } - final List tokenKeys = decodeTokenKeys(hederaToken.get(7), attempt); - addKeys(tokenKeys, tokenUpdateTransactionBody); - addMetaKey(tokenKeys, tokenUpdateTransactionBody); - return tokenUpdateTransactionBody; - } - - @Nullable - public TransactionBody decodeTokenUpdateKeys(@NonNull final HtsCallAttempt attempt) { - final boolean metadataSupport = - attempt.configuration().getConfigData(ContractsConfig.class).metadataKeyAndFieldEnabled(); - final var call = UpdateKeysTranslator.TOKEN_UPDATE_KEYS_FUNCTION.decodeCall( - attempt.input().toArrayUnsafe()); - - final var tokenId = ConversionUtils.asTokenId(call.get(TOKEN_ADDRESS)); - final var tokenKeys = decodeTokenKeys(call.get(TOKEN_KEYS), attempt); - - // Build the transaction body - final var txnBodyBuilder = TokenUpdateTransactionBody.newBuilder(); - txnBodyBuilder.token(tokenId); - addKeys(tokenKeys, txnBodyBuilder); - if (metadataSupport) { - addMetaKey(tokenKeys, txnBodyBuilder); - } - try { - return TransactionBody.newBuilder().tokenUpdate(txnBodyBuilder).build(); - } catch (IllegalArgumentException ignore) { - return null; - } - } - - public TransactionBody decodeUpdateNFTsMetadata(@NonNull final HtsCallAttempt attempt) { - final var call = UpdateNFTsMetadataTranslator.UPDATE_NFTs_METADATA.decodeCall( - attempt.input().toArrayUnsafe()); - - final var tokenId = ConversionUtils.asTokenId(call.get(TOKEN_ADDRESS)); - final List serialNumbers = Longs.asList(call.get(SERIAL_NUMBERS)); - final byte[] metadata = call.get(METADATA); - - final var txnBodyBuilder = TokenUpdateNftsTransactionBody.newBuilder() - .token(tokenId) - .serialNumbers(serialNumbers) - .metadata(Bytes.wrap(metadata)); - - return TransactionBody.newBuilder().tokenUpdateNfts(txnBodyBuilder).build(); - } - - private void addKeys(final List tokenKeys, final TokenUpdateTransactionBody.Builder builder) { - tokenKeys.forEach(tokenKeyWrapper -> { - final var key = tokenKeyWrapper.key().asGrpc(); - if (key == Key.DEFAULT) { - throw new IllegalArgumentException(); - } - setUsedKeys(builder, tokenKeyWrapper, key); - }); - } - - private void setUsedKeys(Builder builder, TokenKeyWrapper tokenKeyWrapper, Key key) { - if (tokenKeyWrapper.isUsedForAdminKey()) { - builder.adminKey(key); - } - if (tokenKeyWrapper.isUsedForKycKey()) { - builder.kycKey(key); - } - if (tokenKeyWrapper.isUsedForFreezeKey()) { - builder.freezeKey(key); - } - if (tokenKeyWrapper.isUsedForWipeKey()) { - builder.wipeKey(key); - } - if (tokenKeyWrapper.isUsedForSupplyKey()) { - builder.supplyKey(key); - } - if (tokenKeyWrapper.isUsedForFeeScheduleKey()) { - builder.feeScheduleKey(key); - } - if (tokenKeyWrapper.isUsedForPauseKey()) { - builder.pauseKey(key); - } - } - - private void addMetaKey(final List tokenKeys, final TokenUpdateTransactionBody.Builder builder) { - tokenKeys.forEach(tokenKeyWrapper -> { - final var key = tokenKeyWrapper.key().asGrpc(); - if (tokenKeyWrapper.isUsedForMetadataKey()) { - builder.metadataKey(key); - } - }); - } - - private TransactionBody decodeTokenUpdateExpiry( - @NonNull final Tuple call, @NonNull final AddressIdConverter addressIdConverter) { - final var tokenId = (Address) call.get(TOKEN_ADDRESS); - final var expiryTuple = (Tuple) call.get(EXPIRY); - final var txnBodyBuilder = TokenUpdateTransactionBody.newBuilder(); - - txnBodyBuilder.token(ConversionUtils.asTokenId(tokenId)); - final var tokenExpiry = decodeTokenExpiry(expiryTuple, addressIdConverter); - - if (tokenExpiry.second() != 0) { - txnBodyBuilder.expiry( - Timestamp.newBuilder().seconds(tokenExpiry.second()).build()); - } - if (tokenExpiry.autoRenewAccount() != null) { - txnBodyBuilder.autoRenewAccount(tokenExpiry.autoRenewAccount()); - } - if (tokenExpiry.autoRenewPeriod() != null - && tokenExpiry.autoRenewPeriod().seconds() != 0) { - txnBodyBuilder.autoRenewPeriod(tokenExpiry.autoRenewPeriod()); - } - - return TransactionBody.newBuilder().tokenUpdate(txnBodyBuilder).build(); - } - - private List decodeTokenKeys( - @NonNull final Tuple[] tokenKeysTuples, @NonNull final HtsCallAttempt attempt) { - final List tokenKeys = new ArrayList<>(tokenKeysTuples.length); - for (final var tokenKeyTuple : tokenKeysTuples) { - final var keyType = ((BigInteger) tokenKeyTuple.get(KEY_TYPE)).intValue(); - final Tuple keyValueTuple = tokenKeyTuple.get(KEY_VALUE); - final var inheritAccountKey = (Boolean) keyValueTuple.get(INHERIT_ACCOUNT_KEY); - final byte[] ed25519 = keyValueTuple.get(ED25519); - final byte[] ecdsaSecp256K1 = keyValueTuple.get(ECDSA_SECP_256K1); - final var contractId = asNumericContractId( - attempt.nativeOperations().entityIdFactory(), - attempt.addressIdConverter().convert(keyValueTuple.get(CONTRACT_ID))); - final var delegatableContractId = asNumericContractId( - attempt.nativeOperations().entityIdFactory(), - attempt.addressIdConverter().convert(keyValueTuple.get(DELEGATABLE_CONTRACT_ID))); - - tokenKeys.add(new TokenKeyWrapper( - keyType, - new KeyValueWrapper( - inheritAccountKey, - contractId.contractNumOrThrow() != 0 ? contractId : null, - ed25519, - ecdsaSecp256K1, - delegatableContractId.contractNumOrThrow() != 0 ? delegatableContractId : null))); - } - - return tokenKeys; - } - - private TokenExpiryWrapper decodeTokenExpiry( - @NonNull final Tuple expiryTuple, @NonNull final AddressIdConverter addressIdConverter) { - final var second = (long) expiryTuple.get(0); - final var autoRenewAccount = addressIdConverter.convert(expiryTuple.get(1)); - final var autoRenewPeriod = - Duration.newBuilder().seconds(expiryTuple.get(2)).build(); - return new TokenExpiryWrapper( - second, autoRenewAccount.accountNumOrElse(0L) == 0 ? null : autoRenewAccount, autoRenewPeriod); - } -} diff --git a/hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/exec/systemcontracts/hts/update/UpdateExpiryTranslator.java b/hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/exec/systemcontracts/hts/update/UpdateExpiryTranslator.java index 426d2fd6642..3575810d0f1 100644 --- a/hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/exec/systemcontracts/hts/update/UpdateExpiryTranslator.java +++ b/hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/exec/systemcontracts/hts/update/UpdateExpiryTranslator.java @@ -3,23 +3,20 @@ import static com.hedera.node.app.hapi.utils.contracts.ParsingConstants.EXPIRY; import static com.hedera.node.app.hapi.utils.contracts.ParsingConstants.EXPIRY_V2; -import static com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.update.UpdateDecoder.FAILURE_CUSTOMIZER; +import static com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.update.UpdateCommonDecoder.FAILURE_CUSTOMIZER; -import com.hedera.hapi.node.base.AccountID; import com.hedera.hapi.node.transaction.TransactionBody; -import com.hedera.node.app.service.contract.impl.exec.gas.DispatchType; -import com.hedera.node.app.service.contract.impl.exec.gas.SystemContractGasCalculator; import com.hedera.node.app.service.contract.impl.exec.metrics.ContractMetrics; import com.hedera.node.app.service.contract.impl.exec.systemcontracts.common.AbstractCallTranslator; import com.hedera.node.app.service.contract.impl.exec.systemcontracts.common.Call; import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.DispatchForResponseCodeHtsCall; import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.HtsCallAttempt; import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.ReturnTypes; +import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.update.address_0x167.UpdateDecoder; import com.hedera.node.app.service.contract.impl.exec.utils.SystemContractMethod; import com.hedera.node.app.service.contract.impl.exec.utils.SystemContractMethod.Category; import com.hedera.node.app.service.contract.impl.exec.utils.SystemContractMethod.Variant; import com.hedera.node.app.service.contract.impl.exec.utils.SystemContractMethodRegistry; -import com.hedera.node.app.service.contract.impl.hevm.HederaWorldUpdater; import edu.umd.cs.findbugs.annotations.NonNull; import java.util.Arrays; import java.util.Optional; @@ -70,22 +67,7 @@ public UpdateExpiryTranslator( @Override public Call callFrom(@NonNull HtsCallAttempt attempt) { return new DispatchForResponseCodeHtsCall( - attempt, nominalBodyFor(attempt), UpdateTranslator::gasRequirement, FAILURE_CUSTOMIZER); - } - - /** - * @param body the transaction body to be dispatched - * @param systemContractGasCalculator the gas calculator for the system contract - * @param enhancement the enhancement to use - * @param payerId the payer of the transaction - * @return the required gas - */ - public static long gasRequirement( - @NonNull final TransactionBody body, - @NonNull final SystemContractGasCalculator systemContractGasCalculator, - @NonNull final HederaWorldUpdater.Enhancement enhancement, - @NonNull final AccountID payerId) { - return systemContractGasCalculator.gasRequirement(body, DispatchType.UPDATE, payerId); + attempt, nominalBodyFor(attempt), UpdateCommons::gasRequirement, FAILURE_CUSTOMIZER); } private TransactionBody nominalBodyFor(@NonNull final HtsCallAttempt attempt) { diff --git a/hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/exec/systemcontracts/hts/update/UpdateKeysCommonTranslator.java b/hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/exec/systemcontracts/hts/update/UpdateKeysCommonTranslator.java new file mode 100644 index 00000000000..b548a62c38b --- /dev/null +++ b/hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/exec/systemcontracts/hts/update/UpdateKeysCommonTranslator.java @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: Apache-2.0 +package com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.update; + +import static com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.update.UpdateCommonDecoder.FAILURE_CUSTOMIZER; + +import com.hedera.node.app.service.contract.impl.exec.metrics.ContractMetrics; +import com.hedera.node.app.service.contract.impl.exec.systemcontracts.common.AbstractCallTranslator; +import com.hedera.node.app.service.contract.impl.exec.systemcontracts.common.Call; +import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.DispatchForResponseCodeHtsCall; +import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.HtsCallAttempt; +import com.hedera.node.app.service.contract.impl.exec.utils.SystemContractMethod; +import com.hedera.node.app.service.contract.impl.exec.utils.SystemContractMethodRegistry; +import edu.umd.cs.findbugs.annotations.NonNull; + +public abstract class UpdateKeysCommonTranslator extends AbstractCallTranslator { + + private final UpdateCommonDecoder decoder; + + public UpdateKeysCommonTranslator( + @NonNull final UpdateCommonDecoder decoder, + @NonNull final SystemContractMethodRegistry systemContractMethodRegistry, + @NonNull final ContractMetrics contractMetrics) { + super(SystemContractMethod.SystemContract.HTS, systemContractMethodRegistry, contractMetrics); + this.decoder = decoder; + } + + @Override + public Call callFrom(@NonNull final HtsCallAttempt attempt) { + return new DispatchForResponseCodeHtsCall( + attempt, decoder.decodeTokenUpdateKeys(attempt), UpdateCommons::gasRequirement, FAILURE_CUSTOMIZER); + } +} diff --git a/hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/exec/systemcontracts/hts/update/UpdateKeysTranslator.java b/hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/exec/systemcontracts/hts/update/UpdateKeysTranslator.java deleted file mode 100644 index 70727e172d1..00000000000 --- a/hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/exec/systemcontracts/hts/update/UpdateKeysTranslator.java +++ /dev/null @@ -1,78 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -package com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.update; - -import static com.hedera.node.app.hapi.utils.contracts.ParsingConstants.ARRAY_BRACKETS; -import static com.hedera.node.app.hapi.utils.contracts.ParsingConstants.TOKEN_KEY; -import static com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.update.UpdateDecoder.FAILURE_CUSTOMIZER; - -import com.hedera.hapi.node.base.AccountID; -import com.hedera.hapi.node.transaction.TransactionBody; -import com.hedera.node.app.service.contract.impl.exec.gas.DispatchType; -import com.hedera.node.app.service.contract.impl.exec.gas.SystemContractGasCalculator; -import com.hedera.node.app.service.contract.impl.exec.metrics.ContractMetrics; -import com.hedera.node.app.service.contract.impl.exec.systemcontracts.common.AbstractCallTranslator; -import com.hedera.node.app.service.contract.impl.exec.systemcontracts.common.Call; -import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.DispatchForResponseCodeHtsCall; -import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.HtsCallAttempt; -import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.ReturnTypes; -import com.hedera.node.app.service.contract.impl.exec.utils.SystemContractMethod; -import com.hedera.node.app.service.contract.impl.exec.utils.SystemContractMethod.Category; -import com.hedera.node.app.service.contract.impl.exec.utils.SystemContractMethodRegistry; -import com.hedera.node.app.service.contract.impl.hevm.HederaWorldUpdater; -import edu.umd.cs.findbugs.annotations.NonNull; -import java.util.Optional; -import javax.inject.Inject; -import javax.inject.Singleton; - -@Singleton -public class UpdateKeysTranslator extends AbstractCallTranslator { - /** Selector for updateTokenKeys(address, TOKEN_KEY[]) method. */ - public static final SystemContractMethod TOKEN_UPDATE_KEYS_FUNCTION = SystemContractMethod.declare( - "updateTokenKeys(address," + TOKEN_KEY + ARRAY_BRACKETS + ")", ReturnTypes.INT) - .withCategories(Category.UPDATE); - - private final UpdateDecoder decoder; - - /** - * @param decoder the decoder to use for token update keys calls - */ - @Inject - public UpdateKeysTranslator( - @NonNull final UpdateDecoder decoder, - @NonNull final SystemContractMethodRegistry systemContractMethodRegistry, - @NonNull final ContractMetrics contractMetrics) { - super(SystemContractMethod.SystemContract.HTS, systemContractMethodRegistry, contractMetrics); - this.decoder = decoder; - - registerMethods(TOKEN_UPDATE_KEYS_FUNCTION); - } - - @Override - public @NonNull Optional identifyMethod(@NonNull final HtsCallAttempt attempt) { - return attempt.isMethod(TOKEN_UPDATE_KEYS_FUNCTION); - } - - @Override - public Call callFrom(@NonNull HtsCallAttempt attempt) { - return new DispatchForResponseCodeHtsCall( - attempt, - decoder.decodeTokenUpdateKeys(attempt), - UpdateKeysTranslator::gasRequirement, - FAILURE_CUSTOMIZER); - } - - /** - * @param body the transaction body to be dispatched - * @param systemContractGasCalculator the gas calculator for the system contract - * @param enhancement the enhancement to use - * @param payerId the payer of the transaction - * @return the required gas - */ - public static long gasRequirement( - @NonNull final TransactionBody body, - @NonNull final SystemContractGasCalculator systemContractGasCalculator, - @NonNull final HederaWorldUpdater.Enhancement enhancement, - @NonNull final AccountID payerId) { - return systemContractGasCalculator.gasRequirement(body, DispatchType.UPDATE, payerId); - } -} diff --git a/hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/exec/systemcontracts/hts/update/UpdateTokenCommonTranslator.java b/hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/exec/systemcontracts/hts/update/UpdateTokenCommonTranslator.java new file mode 100644 index 00000000000..734ac59cded --- /dev/null +++ b/hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/exec/systemcontracts/hts/update/UpdateTokenCommonTranslator.java @@ -0,0 +1,49 @@ +// SPDX-License-Identifier: Apache-2.0 +package com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.update; + +import static com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.update.UpdateCommonDecoder.FAILURE_CUSTOMIZER; + +import com.hedera.hapi.node.transaction.TransactionBody; +import com.hedera.node.app.service.contract.impl.exec.metrics.ContractMetrics; +import com.hedera.node.app.service.contract.impl.exec.systemcontracts.common.AbstractCallTranslator; +import com.hedera.node.app.service.contract.impl.exec.systemcontracts.common.Call; +import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.DispatchForResponseCodeHtsCall; +import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.HtsCallAttempt; +import com.hedera.node.app.service.contract.impl.exec.utils.SystemContractMethod; +import com.hedera.node.app.service.contract.impl.exec.utils.SystemContractMethodRegistry; +import edu.umd.cs.findbugs.annotations.NonNull; +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; + +public class UpdateTokenCommonTranslator extends AbstractCallTranslator { + + protected static final String UPDATE_TOKEN_INFO_STRING = "updateTokenInfo(address,"; + + protected final Map updateMethodsMap = new HashMap<>(); + + public UpdateTokenCommonTranslator( + @NonNull final SystemContractMethodRegistry systemContractMethodRegistry, + @NonNull final ContractMetrics contractMetrics) { + super(SystemContractMethod.SystemContract.HTS, systemContractMethodRegistry, contractMetrics); + } + + @Override + public @NonNull Optional identifyMethod(@NonNull final HtsCallAttempt attempt) { + return updateMethodsMap.keySet().stream().filter(attempt::isSelector).findFirst(); + } + + @Override + public Call callFrom(@NonNull HtsCallAttempt attempt) { + return new DispatchForResponseCodeHtsCall( + attempt, nominalBodyFor(attempt), UpdateCommons::gasRequirement, FAILURE_CUSTOMIZER); + } + + private TransactionBody nominalBodyFor(@NonNull final HtsCallAttempt attempt) { + return updateMethodsMap.entrySet().stream() + .filter(entry -> attempt.isSelector(entry.getKey())) + .map(entry -> entry.getValue().decode(attempt)) + .findFirst() + .orElse(null); + } +} diff --git a/hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/exec/systemcontracts/hts/update/UpdateTranslator.java b/hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/exec/systemcontracts/hts/update/UpdateTranslator.java deleted file mode 100644 index 9b83aad2646..00000000000 --- a/hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/exec/systemcontracts/hts/update/UpdateTranslator.java +++ /dev/null @@ -1,125 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -package com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.update; - -import static com.hedera.node.app.hapi.utils.contracts.ParsingConstants.ARRAY_BRACKETS; -import static com.hedera.node.app.hapi.utils.contracts.ParsingConstants.EXPIRY; -import static com.hedera.node.app.hapi.utils.contracts.ParsingConstants.EXPIRY_V2; -import static com.hedera.node.app.hapi.utils.contracts.ParsingConstants.HEDERA_TOKEN_WITH_METADATA; -import static com.hedera.node.app.hapi.utils.contracts.ParsingConstants.TOKEN_KEY; - -import com.hedera.hapi.node.base.AccountID; -import com.hedera.hapi.node.transaction.TransactionBody; -import com.hedera.node.app.service.contract.impl.exec.gas.DispatchType; -import com.hedera.node.app.service.contract.impl.exec.gas.SystemContractGasCalculator; -import com.hedera.node.app.service.contract.impl.exec.metrics.ContractMetrics; -import com.hedera.node.app.service.contract.impl.exec.systemcontracts.common.AbstractCallTranslator; -import com.hedera.node.app.service.contract.impl.exec.systemcontracts.common.Call; -import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.DispatchForResponseCodeHtsCall; -import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.HtsCallAttempt; -import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.ReturnTypes; -import com.hedera.node.app.service.contract.impl.exec.utils.SystemContractMethod; -import com.hedera.node.app.service.contract.impl.exec.utils.SystemContractMethod.Category; -import com.hedera.node.app.service.contract.impl.exec.utils.SystemContractMethod.Variant; -import com.hedera.node.app.service.contract.impl.exec.utils.SystemContractMethodRegistry; -import com.hedera.node.app.service.contract.impl.hevm.HederaWorldUpdater; -import com.hedera.node.config.data.ContractsConfig; -import edu.umd.cs.findbugs.annotations.NonNull; -import java.util.HashMap; -import java.util.Map; -import java.util.Optional; -import javax.inject.Inject; -import javax.inject.Singleton; - -@Singleton -public class UpdateTranslator extends AbstractCallTranslator { - private static final String UPDATE_TOKEN_INFO_STRING = "updateTokenInfo(address,"; - private static final String HEDERA_TOKEN_STRUCT = - "(string,string,address,string,bool,uint32,bool," + TOKEN_KEY + ARRAY_BRACKETS + "," + EXPIRY + ")"; - private static final String HEDERA_TOKEN_STRUCT_V2 = - "(string,string,address,string,bool,int64,bool," + TOKEN_KEY + ARRAY_BRACKETS + "," + EXPIRY + ")"; - private static final String HEDERA_TOKEN_STRUCT_V3 = - "(string,string,address,string,bool,int64,bool," + TOKEN_KEY + ARRAY_BRACKETS + "," + EXPIRY_V2 + ")"; - /** Selector for updateTokenInfo(address, HEDERA_TOKEN_STRUCT) method. */ - public static final SystemContractMethod TOKEN_UPDATE_INFO_FUNCTION_V1 = SystemContractMethod.declare( - UPDATE_TOKEN_INFO_STRING + HEDERA_TOKEN_STRUCT + ")", ReturnTypes.INT) - .withVariant(Variant.V1) - .withCategories(Category.UPDATE); - /** Selector for updateTokenInfo(address, HEDERA_TOKEN_STRUCT_V2) method. */ - public static final SystemContractMethod TOKEN_UPDATE_INFO_FUNCTION_V2 = SystemContractMethod.declare( - UPDATE_TOKEN_INFO_STRING + HEDERA_TOKEN_STRUCT_V2 + ")", ReturnTypes.INT) - .withVariant(Variant.V2) - .withCategories(Category.UPDATE); - /** Selector for updateTokenInfo(address, HEDERA_TOKEN_STRUCT_V3) method. */ - public static final SystemContractMethod TOKEN_UPDATE_INFO_FUNCTION_V3 = SystemContractMethod.declare( - UPDATE_TOKEN_INFO_STRING + HEDERA_TOKEN_STRUCT_V3 + ")", ReturnTypes.INT) - .withVariant(Variant.V3) - .withCategories(Category.UPDATE); - /** Selector for updateTokenInfo(address, HEDERA_TOKEN_WITH_METADATA) method. */ - public static final SystemContractMethod TOKEN_UPDATE_INFO_FUNCTION_WITH_METADATA = SystemContractMethod.declare( - UPDATE_TOKEN_INFO_STRING + HEDERA_TOKEN_WITH_METADATA + ")", ReturnTypes.INT) - .withVariant(Variant.WITH_METADATA) - .withCategories(Category.UPDATE); - - public static final Map updateMethodsMap = new HashMap<>(); - - /** - * @param decoder the decoder to use for token update info calls - */ - @Inject - public UpdateTranslator( - final UpdateDecoder decoder, - @NonNull final SystemContractMethodRegistry systemContractMethodRegistry, - @NonNull final ContractMetrics contractMetrics) { - super(SystemContractMethod.SystemContract.HTS, systemContractMethodRegistry, contractMetrics); - - registerMethods( - TOKEN_UPDATE_INFO_FUNCTION_V1, - TOKEN_UPDATE_INFO_FUNCTION_V2, - TOKEN_UPDATE_INFO_FUNCTION_V3, - TOKEN_UPDATE_INFO_FUNCTION_WITH_METADATA); - - updateMethodsMap.put(TOKEN_UPDATE_INFO_FUNCTION_V1, decoder::decodeTokenUpdateV1); - updateMethodsMap.put(TOKEN_UPDATE_INFO_FUNCTION_V2, decoder::decodeTokenUpdateV2); - updateMethodsMap.put(TOKEN_UPDATE_INFO_FUNCTION_V3, decoder::decodeTokenUpdateV3); - updateMethodsMap.put(TOKEN_UPDATE_INFO_FUNCTION_WITH_METADATA, decoder::decodeTokenUpdateWithMetadata); - } - - @Override - public @NonNull Optional identifyMethod(@NonNull final HtsCallAttempt attempt) { - final boolean metadataSupport = - attempt.configuration().getConfigData(ContractsConfig.class).metadataKeyAndFieldEnabled(); - - if (attempt.isSelectorIfConfigEnabled(metadataSupport, TOKEN_UPDATE_INFO_FUNCTION_WITH_METADATA)) - return Optional.of(TOKEN_UPDATE_INFO_FUNCTION_WITH_METADATA); - return updateMethodsMap.keySet().stream().filter(attempt::isSelector).findFirst(); - } - - @Override - public Call callFrom(@NonNull HtsCallAttempt attempt) { - return new DispatchForResponseCodeHtsCall( - attempt, nominalBodyFor(attempt), UpdateTranslator::gasRequirement, UpdateDecoder.FAILURE_CUSTOMIZER); - } - - /** - * @param body the transaction body to be dispatched - * @param systemContractGasCalculator the gas calculator for the system contract - * @param enhancement the enhancement to use - * @param payerId the payer of the transaction - * @return the required gas - */ - public static long gasRequirement( - @NonNull final TransactionBody body, - @NonNull final SystemContractGasCalculator systemContractGasCalculator, - @NonNull final HederaWorldUpdater.Enhancement enhancement, - @NonNull final AccountID payerId) { - return systemContractGasCalculator.gasRequirement(body, DispatchType.UPDATE, payerId); - } - - private TransactionBody nominalBodyFor(@NonNull final HtsCallAttempt attempt) { - return updateMethodsMap.entrySet().stream() - .filter(entry -> attempt.isSelector(entry.getKey())) - .map(entry -> entry.getValue().decode(attempt)) - .findFirst() - .orElse(null); - } -} diff --git a/hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/exec/systemcontracts/hts/update/address_0x167/UpdateDecoder.java b/hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/exec/systemcontracts/hts/update/address_0x167/UpdateDecoder.java new file mode 100644 index 00000000000..e5c4e04b536 --- /dev/null +++ b/hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/exec/systemcontracts/hts/update/address_0x167/UpdateDecoder.java @@ -0,0 +1,122 @@ +// SPDX-License-Identifier: Apache-2.0 +package com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.update.address_0x167; + +import com.esaulpaugh.headlong.abi.Address; +import com.esaulpaugh.headlong.abi.Tuple; +import com.hedera.hapi.node.base.Timestamp; +import com.hedera.hapi.node.token.TokenUpdateTransactionBody; +import com.hedera.hapi.node.transaction.TransactionBody; +import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.AddressIdConverter; +import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.HtsCallAttempt; +import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.update.UpdateCommonDecoder; +import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.update.UpdateExpiryTranslator; +import com.hedera.node.app.service.contract.impl.utils.ConversionUtils; +import edu.umd.cs.findbugs.annotations.NonNull; +import edu.umd.cs.findbugs.annotations.Nullable; +import javax.inject.Inject; +import javax.inject.Singleton; + +@Singleton +public class UpdateDecoder extends UpdateCommonDecoder { + + /** + * Default constructor for injection. + */ + @Inject + public UpdateDecoder() { + // Dagger2 + } + + /** + * Decodes a call to {@link UpdateTranslator#TOKEN_UPDATE_INFO_FUNCTION_V1} into a synthetic {@link TransactionBody}. + * + * @param attempt the attempt + * @return the synthetic transaction body + */ + public @Nullable TransactionBody decodeTokenUpdateV1(@NonNull final HtsCallAttempt attempt) { + final var call = UpdateTranslator.TOKEN_UPDATE_INFO_FUNCTION_V1.decodeCall( + attempt.input().toArrayUnsafe()); + final var decoded = decodeTokenUpdate(call, attempt.addressIdConverter(), attempt.nativeOperations()); + return TransactionBody.newBuilder().tokenUpdate(decoded).build(); + } + + /** + * Decodes a call to {@link UpdateTranslator#TOKEN_UPDATE_INFO_FUNCTION_V2} into a synthetic {@link TransactionBody}. + * + * @param attempt the attempt + * @return the synthetic transaction body + */ + public @Nullable TransactionBody decodeTokenUpdateV2(@NonNull final HtsCallAttempt attempt) { + final var call = UpdateTranslator.TOKEN_UPDATE_INFO_FUNCTION_V2.decodeCall( + attempt.input().toArrayUnsafe()); + final var decoded = decodeTokenUpdate(call, attempt.addressIdConverter(), attempt.nativeOperations()); + return TransactionBody.newBuilder().tokenUpdate(decoded).build(); + } + + /** + * Decodes a call to {@link UpdateTranslator#TOKEN_UPDATE_INFO_FUNCTION_V3} into a synthetic {@link TransactionBody}. + * + * @param attempt the attempt + * @return the synthetic transaction body + */ + public @Nullable TransactionBody decodeTokenUpdateV3(@NonNull final HtsCallAttempt attempt) { + final var call = UpdateTranslator.TOKEN_UPDATE_INFO_FUNCTION_V3.decodeCall( + attempt.input().toArrayUnsafe()); + final var decoded = decodeTokenUpdate(call, attempt.addressIdConverter(), attempt.nativeOperations()); + return TransactionBody.newBuilder().tokenUpdate(decoded).build(); + } + + /** + * Decodes a call to {@link UpdateExpiryTranslator#UPDATE_TOKEN_EXPIRY_INFO_V1} into a synthetic {@link TransactionBody}. + * + * @param attempt the attempt + * @return the synthetic transaction body + */ + public TransactionBody decodeTokenUpdateExpiryV1(@NonNull final HtsCallAttempt attempt) { + final var call = UpdateExpiryTranslator.UPDATE_TOKEN_EXPIRY_INFO_V1.decodeCall( + attempt.input().toArrayUnsafe()); + return decodeTokenUpdateExpiry(call, attempt.addressIdConverter()); + } + + /** + * Decodes a call to {@link UpdateExpiryTranslator#UPDATE_TOKEN_EXPIRY_INFO_V2} into a synthetic {@link TransactionBody}. + * + * @param attempt the attempt + * @return the synthetic transaction body + */ + public TransactionBody decodeTokenUpdateExpiryV2(@NonNull final HtsCallAttempt attempt) { + final var call = UpdateExpiryTranslator.UPDATE_TOKEN_EXPIRY_INFO_V2.decodeCall( + attempt.input().toArrayUnsafe()); + return decodeTokenUpdateExpiry(call, attempt.addressIdConverter()); + } + + @Override + protected Tuple decodeCall(@NonNull final HtsCallAttempt attempt) { + return UpdateKeysTranslator.TOKEN_UPDATE_KEYS_FUNCTION.decodeCall( + attempt.input().toArrayUnsafe()); + } + + private TransactionBody decodeTokenUpdateExpiry( + @NonNull final Tuple call, @NonNull final AddressIdConverter addressIdConverter) { + final var tokenId = (Address) call.get(TOKEN_ADDRESS); + final var expiryTuple = (Tuple) call.get(EXPIRY); + final var txnBodyBuilder = TokenUpdateTransactionBody.newBuilder(); + + txnBodyBuilder.token(ConversionUtils.asTokenId(tokenId)); + final var tokenExpiry = decodeTokenExpiry(expiryTuple, addressIdConverter); + + if (tokenExpiry.second() != 0) { + txnBodyBuilder.expiry( + Timestamp.newBuilder().seconds(tokenExpiry.second()).build()); + } + if (tokenExpiry.autoRenewAccount() != null) { + txnBodyBuilder.autoRenewAccount(tokenExpiry.autoRenewAccount()); + } + if (tokenExpiry.autoRenewPeriod() != null + && tokenExpiry.autoRenewPeriod().seconds() != 0) { + txnBodyBuilder.autoRenewPeriod(tokenExpiry.autoRenewPeriod()); + } + + return TransactionBody.newBuilder().tokenUpdate(txnBodyBuilder).build(); + } +} diff --git a/hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/exec/systemcontracts/hts/update/address_0x167/UpdateKeysTranslator.java b/hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/exec/systemcontracts/hts/update/address_0x167/UpdateKeysTranslator.java new file mode 100644 index 00000000000..5959145a2e3 --- /dev/null +++ b/hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/exec/systemcontracts/hts/update/address_0x167/UpdateKeysTranslator.java @@ -0,0 +1,46 @@ +// SPDX-License-Identifier: Apache-2.0 +package com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.update.address_0x167; + +import static com.hedera.node.app.hapi.utils.contracts.ParsingConstants.ARRAY_BRACKETS; +import static com.hedera.node.app.hapi.utils.contracts.ParsingConstants.TOKEN_KEY; +import static com.hedera.node.app.service.contract.impl.exec.systemcontracts.HtsSystemContract.HTS_167_CONTRACT_ID; + +import com.hedera.node.app.service.contract.impl.exec.metrics.ContractMetrics; +import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.HtsCallAttempt; +import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.ReturnTypes; +import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.update.UpdateKeysCommonTranslator; +import com.hedera.node.app.service.contract.impl.exec.utils.SystemContractMethod; +import com.hedera.node.app.service.contract.impl.exec.utils.SystemContractMethodRegistry; +import edu.umd.cs.findbugs.annotations.NonNull; +import java.util.Optional; +import javax.inject.Inject; +import javax.inject.Singleton; + +@Singleton +public class UpdateKeysTranslator extends UpdateKeysCommonTranslator { + /** + * Selector for updateTokenKeys(address, TOKEN_KEY[]) method. + */ + public static final SystemContractMethod TOKEN_UPDATE_KEYS_FUNCTION = SystemContractMethod.declare( + "updateTokenKeys(address," + TOKEN_KEY + ARRAY_BRACKETS + ")", ReturnTypes.INT) + .withCategories(SystemContractMethod.Category.UPDATE) + .withSupportedAddress(HTS_167_CONTRACT_ID); + + /** + * @param decoder the decoder to use for token update keys calls + */ + @Inject + public UpdateKeysTranslator( + @NonNull final UpdateDecoder decoder, + @NonNull final SystemContractMethodRegistry systemContractMethodRegistry, + @NonNull final ContractMetrics contractMetrics) { + super(decoder, systemContractMethodRegistry, contractMetrics); + + registerMethods(TOKEN_UPDATE_KEYS_FUNCTION); + } + + @Override + public @NonNull Optional identifyMethod(@NonNull final HtsCallAttempt attempt) { + return attempt.isMethod(TOKEN_UPDATE_KEYS_FUNCTION); + } +} diff --git a/hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/exec/systemcontracts/hts/update/address_0x167/UpdateTranslator.java b/hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/exec/systemcontracts/hts/update/address_0x167/UpdateTranslator.java new file mode 100644 index 00000000000..9096ca5eed1 --- /dev/null +++ b/hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/exec/systemcontracts/hts/update/address_0x167/UpdateTranslator.java @@ -0,0 +1,63 @@ +// SPDX-License-Identifier: Apache-2.0 +package com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.update.address_0x167; + +import static com.hedera.node.app.hapi.utils.contracts.ParsingConstants.ARRAY_BRACKETS; +import static com.hedera.node.app.hapi.utils.contracts.ParsingConstants.EXPIRY; +import static com.hedera.node.app.hapi.utils.contracts.ParsingConstants.EXPIRY_V2; +import static com.hedera.node.app.hapi.utils.contracts.ParsingConstants.TOKEN_KEY; +import static com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.update.UpdateCommons.updateMethodsSet; + +import com.hedera.node.app.service.contract.impl.exec.metrics.ContractMetrics; +import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.ReturnTypes; +import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.update.UpdateTokenCommonTranslator; +import com.hedera.node.app.service.contract.impl.exec.utils.SystemContractMethod; +import com.hedera.node.app.service.contract.impl.exec.utils.SystemContractMethod.Category; +import com.hedera.node.app.service.contract.impl.exec.utils.SystemContractMethod.Variant; +import com.hedera.node.app.service.contract.impl.exec.utils.SystemContractMethodRegistry; +import edu.umd.cs.findbugs.annotations.NonNull; +import javax.inject.Inject; +import javax.inject.Singleton; + +@Singleton +public class UpdateTranslator extends UpdateTokenCommonTranslator { + private static final String HEDERA_TOKEN_STRUCT = + "(string,string,address,string,bool,uint32,bool," + TOKEN_KEY + ARRAY_BRACKETS + "," + EXPIRY + ")"; + private static final String HEDERA_TOKEN_STRUCT_V2 = + "(string,string,address,string,bool,int64,bool," + TOKEN_KEY + ARRAY_BRACKETS + "," + EXPIRY + ")"; + private static final String HEDERA_TOKEN_STRUCT_V3 = + "(string,string,address,string,bool,int64,bool," + TOKEN_KEY + ARRAY_BRACKETS + "," + EXPIRY_V2 + ")"; + /** Selector for updateTokenInfo(address, HEDERA_TOKEN_STRUCT) method. */ + public static final SystemContractMethod TOKEN_UPDATE_INFO_FUNCTION_V1 = SystemContractMethod.declare( + UPDATE_TOKEN_INFO_STRING + HEDERA_TOKEN_STRUCT + ")", ReturnTypes.INT) + .withVariant(Variant.V1) + .withCategories(Category.UPDATE); + /** Selector for updateTokenInfo(address, HEDERA_TOKEN_STRUCT_V2) method. */ + public static final SystemContractMethod TOKEN_UPDATE_INFO_FUNCTION_V2 = SystemContractMethod.declare( + UPDATE_TOKEN_INFO_STRING + HEDERA_TOKEN_STRUCT_V2 + ")", ReturnTypes.INT) + .withVariant(Variant.V2) + .withCategories(Category.UPDATE); + /** Selector for updateTokenInfo(address, HEDERA_TOKEN_STRUCT_V3) method. */ + public static final SystemContractMethod TOKEN_UPDATE_INFO_FUNCTION_V3 = SystemContractMethod.declare( + UPDATE_TOKEN_INFO_STRING + HEDERA_TOKEN_STRUCT_V3 + ")", ReturnTypes.INT) + .withVariant(Variant.V3) + .withCategories(Category.UPDATE); + + /** + * @param decoder the decoder to use for token update info calls + */ + @Inject + public UpdateTranslator( + final UpdateDecoder decoder, + @NonNull final SystemContractMethodRegistry systemContractMethodRegistry, + @NonNull final ContractMetrics contractMetrics) { + super(systemContractMethodRegistry, contractMetrics); + + registerMethods(TOKEN_UPDATE_INFO_FUNCTION_V1, TOKEN_UPDATE_INFO_FUNCTION_V2, TOKEN_UPDATE_INFO_FUNCTION_V3); + + updateMethodsMap.put(TOKEN_UPDATE_INFO_FUNCTION_V1, decoder::decodeTokenUpdateV1); + updateMethodsMap.put(TOKEN_UPDATE_INFO_FUNCTION_V2, decoder::decodeTokenUpdateV2); + updateMethodsMap.put(TOKEN_UPDATE_INFO_FUNCTION_V3, decoder::decodeTokenUpdateV3); + + updateMethodsSet.addAll(updateMethodsMap.keySet()); + } +} diff --git a/hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/exec/systemcontracts/hts/update/address_0x16c/UpdateDecoder.java b/hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/exec/systemcontracts/hts/update/address_0x16c/UpdateDecoder.java new file mode 100644 index 00000000000..f2ea9685292 --- /dev/null +++ b/hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/exec/systemcontracts/hts/update/address_0x16c/UpdateDecoder.java @@ -0,0 +1,116 @@ +// SPDX-License-Identifier: Apache-2.0 +package com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.update.address_0x16c; + +import com.esaulpaugh.headlong.abi.Tuple; +import com.google.common.primitives.Longs; +import com.hedera.hapi.node.token.TokenUpdateNftsTransactionBody; +import com.hedera.hapi.node.token.TokenUpdateTransactionBody; +import com.hedera.hapi.node.transaction.TransactionBody; +import com.hedera.node.app.service.contract.impl.exec.scope.HederaNativeOperations; +import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.AddressIdConverter; +import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.HtsCallAttempt; +import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.update.UpdateCommonDecoder; +import com.hedera.node.app.service.contract.impl.exec.utils.TokenKeyWrapper; +import com.hedera.node.app.service.contract.impl.utils.ConversionUtils; +import com.hedera.pbj.runtime.io.buffer.Bytes; +import edu.umd.cs.findbugs.annotations.NonNull; +import edu.umd.cs.findbugs.annotations.Nullable; +import java.util.List; +import javax.inject.Inject; +import javax.inject.Singleton; + +@Singleton +public class UpdateDecoder extends UpdateCommonDecoder { + + /** + * Default constructor for injection. + */ + @Inject + public UpdateDecoder() { + // Dagger2 + } + + /** + * Decodes a call to {@link UpdateTranslator#TOKEN_UPDATE_INFO_FUNCTION_WITH_METADATA} into a synthetic {@link TransactionBody}. + * + * @param attempt the attempt + * @return the synthetic transaction body + */ + public TransactionBody decodeTokenUpdateWithMetadata(@NonNull final HtsCallAttempt attempt) { + final var call = UpdateTranslator.TOKEN_UPDATE_INFO_FUNCTION_WITH_METADATA.decodeCall( + attempt.input().toArrayUnsafe()); + final var decoded = decodeUpdateWithMeta(call, attempt.addressIdConverter(), attempt.nativeOperations()); + return TransactionBody.newBuilder().tokenUpdate(decoded).build(); + } + + @Override + protected Tuple decodeCall(@NonNull final HtsCallAttempt attempt) { + return UpdateKeysTranslator.TOKEN_UPDATE_KEYS_16C.decodeCall( + attempt.input().toArrayUnsafe()); + } + + public TokenUpdateTransactionBody.Builder decodeUpdateWithMeta( + @NonNull final Tuple call, + @NonNull final AddressIdConverter addressIdConverter, + @NonNull final HederaNativeOperations nativeOperation) { + final var tokenUpdateTransactionBody = decodeTokenUpdate(call, addressIdConverter, nativeOperation); + final var hederaToken = (Tuple) call.get(HEDERA_TOKEN); + final Bytes tokenMetadata = hederaToken.size() > 9 ? Bytes.wrap((byte[]) hederaToken.get(9)) : null; + if (tokenMetadata != null && tokenMetadata.length() > 0) { + tokenUpdateTransactionBody.metadata(tokenMetadata); + } + final List tokenKeys = + decodeTokenKeys(hederaToken.get(7), addressIdConverter, nativeOperation); + addKeys(tokenKeys, tokenUpdateTransactionBody); + addMetaKey(tokenKeys, tokenUpdateTransactionBody); + return tokenUpdateTransactionBody; + } + + public TransactionBody decodeUpdateNFTsMetadata(@NonNull final HtsCallAttempt attempt) { + final var call = UpdateNFTsMetadataTranslator.UPDATE_NFTs_METADATA.decodeCall( + attempt.input().toArrayUnsafe()); + + final var tokenId = ConversionUtils.asTokenId(call.get(TOKEN_ADDRESS)); + final List serialNumbers = Longs.asList(call.get(SERIAL_NUMBERS)); + final byte[] metadata = call.get(METADATA); + + final var txnBodyBuilder = TokenUpdateNftsTransactionBody.newBuilder() + .token(tokenId) + .serialNumbers(serialNumbers) + .metadata(Bytes.wrap(metadata)); + + return TransactionBody.newBuilder().tokenUpdateNfts(txnBodyBuilder).build(); + } + + @Override + @Nullable + public TransactionBody decodeTokenUpdateKeys(@NonNull final HtsCallAttempt attempt) { + + final var call = decodeCall(attempt); + + final var tokenId = ConversionUtils.asTokenId(call.get(TOKEN_ADDRESS)); + final var tokenKeys = + decodeTokenKeys(call.get(TOKEN_KEYS), attempt.addressIdConverter(), attempt.nativeOperations()); + + // Build the transaction body + final var txnBodyBuilder = TokenUpdateTransactionBody.newBuilder(); + txnBodyBuilder.token(tokenId); + addKeys(tokenKeys, txnBodyBuilder); + addMetaKey(tokenKeys, txnBodyBuilder); + + try { + return TransactionBody.newBuilder().tokenUpdate(txnBodyBuilder).build(); + } catch (final IllegalArgumentException ignore) { + return null; + } + } + + private void addMetaKey(final List tokenKeys, final TokenUpdateTransactionBody.Builder builder) { + tokenKeys.forEach(tokenKeyWrapper -> { + final var key = tokenKeyWrapper.key().asGrpc(); + if (tokenKeyWrapper.isUsedForMetadataKey()) { + builder.metadataKey(key); + } + }); + } +} diff --git a/hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/exec/systemcontracts/hts/update/address_0x16c/UpdateKeysTranslator.java b/hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/exec/systemcontracts/hts/update/address_0x16c/UpdateKeysTranslator.java new file mode 100644 index 00000000000..0dfee7484c2 --- /dev/null +++ b/hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/exec/systemcontracts/hts/update/address_0x16c/UpdateKeysTranslator.java @@ -0,0 +1,46 @@ +// SPDX-License-Identifier: Apache-2.0 +package com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.update.address_0x16c; + +import static com.hedera.node.app.hapi.utils.contracts.ParsingConstants.ARRAY_BRACKETS; +import static com.hedera.node.app.hapi.utils.contracts.ParsingConstants.TOKEN_KEY; +import static com.hedera.node.app.service.contract.impl.exec.systemcontracts.HtsSystemContract.HTS_16C_CONTRACT_ID; + +import com.hedera.node.app.service.contract.impl.exec.metrics.ContractMetrics; +import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.HtsCallAttempt; +import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.ReturnTypes; +import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.update.UpdateKeysCommonTranslator; +import com.hedera.node.app.service.contract.impl.exec.utils.SystemContractMethod; +import com.hedera.node.app.service.contract.impl.exec.utils.SystemContractMethodRegistry; +import edu.umd.cs.findbugs.annotations.NonNull; +import java.util.Optional; +import javax.inject.Inject; +import javax.inject.Singleton; + +@Singleton +public class UpdateKeysTranslator extends UpdateKeysCommonTranslator { + /** + * Selector for updateTokenKeys(address, TOKEN_KEY[]) method. + */ + public static final SystemContractMethod TOKEN_UPDATE_KEYS_16C = SystemContractMethod.declare( + "updateTokenKeys(address," + TOKEN_KEY + ARRAY_BRACKETS + ")", ReturnTypes.INT) + .withCategories(SystemContractMethod.Category.UPDATE) + .withSupportedAddress(HTS_16C_CONTRACT_ID); + + /** + * @param decoder the decoder to use for token update keys calls + */ + @Inject + public UpdateKeysTranslator( + @NonNull final UpdateDecoder decoder, + @NonNull final SystemContractMethodRegistry systemContractMethodRegistry, + @NonNull final ContractMetrics contractMetrics) { + super(decoder, systemContractMethodRegistry, contractMetrics); + + registerMethods(TOKEN_UPDATE_KEYS_16C); + } + + @Override + public @NonNull Optional identifyMethod(@NonNull final HtsCallAttempt attempt) { + return attempt.isMethod(TOKEN_UPDATE_KEYS_16C); + } +} diff --git a/hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/exec/systemcontracts/hts/update/UpdateNFTsMetadataTranslator.java b/hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/exec/systemcontracts/hts/update/address_0x16c/UpdateNFTsMetadataTranslator.java similarity index 93% rename from hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/exec/systemcontracts/hts/update/UpdateNFTsMetadataTranslator.java rename to hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/exec/systemcontracts/hts/update/address_0x16c/UpdateNFTsMetadataTranslator.java index 04d60b04f3a..c152d1ed16c 100644 --- a/hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/exec/systemcontracts/hts/update/UpdateNFTsMetadataTranslator.java +++ b/hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/exec/systemcontracts/hts/update/address_0x16c/UpdateNFTsMetadataTranslator.java @@ -1,5 +1,7 @@ // SPDX-License-Identifier: Apache-2.0 -package com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.update; +package com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.update.address_0x16c; + +import static com.hedera.node.app.service.contract.impl.exec.systemcontracts.HtsSystemContract.HTS_16C_CONTRACT_ID; import com.hedera.hapi.node.base.AccountID; import com.hedera.hapi.node.transaction.TransactionBody; @@ -16,7 +18,6 @@ import com.hedera.node.app.service.contract.impl.exec.utils.SystemContractMethod.Variant; import com.hedera.node.app.service.contract.impl.exec.utils.SystemContractMethodRegistry; import com.hedera.node.app.service.contract.impl.hevm.HederaWorldUpdater; -import com.hedera.node.config.data.ContractsConfig; import edu.umd.cs.findbugs.annotations.NonNull; import java.util.Optional; import javax.inject.Inject; @@ -28,6 +29,7 @@ public class UpdateNFTsMetadataTranslator extends AbstractCallTranslator identifyMethod(@NonNull final HtsCallAttempt attempt) { - if (!attempt.configuration().getConfigData(ContractsConfig.class).systemContractUpdateNFTsMetadataEnabled()) - return Optional.empty(); return attempt.isMethod(UPDATE_NFTs_METADATA); } diff --git a/hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/exec/systemcontracts/hts/update/address_0x16c/UpdateTranslator.java b/hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/exec/systemcontracts/hts/update/address_0x16c/UpdateTranslator.java new file mode 100644 index 00000000000..e53c7c43caf --- /dev/null +++ b/hedera-node/hedera-smart-contract-service-impl/src/main/java/com/hedera/node/app/service/contract/impl/exec/systemcontracts/hts/update/address_0x16c/UpdateTranslator.java @@ -0,0 +1,43 @@ +// SPDX-License-Identifier: Apache-2.0 +package com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.update.address_0x16c; + +import static com.hedera.node.app.hapi.utils.contracts.ParsingConstants.HEDERA_TOKEN_WITH_METADATA; +import static com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.update.UpdateCommons.updateMethodsSet; + +import com.hedera.node.app.service.contract.impl.exec.metrics.ContractMetrics; +import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.ReturnTypes; +import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.update.UpdateTokenCommonTranslator; +import com.hedera.node.app.service.contract.impl.exec.utils.SystemContractMethod; +import com.hedera.node.app.service.contract.impl.exec.utils.SystemContractMethod.Category; +import com.hedera.node.app.service.contract.impl.exec.utils.SystemContractMethod.Variant; +import com.hedera.node.app.service.contract.impl.exec.utils.SystemContractMethodRegistry; +import edu.umd.cs.findbugs.annotations.NonNull; +import javax.inject.Inject; +import javax.inject.Singleton; + +@Singleton +public class UpdateTranslator extends UpdateTokenCommonTranslator { + + /** Selector for updateTokenInfo(address, HEDERA_TOKEN_WITH_METADATA) method. */ + public static final SystemContractMethod TOKEN_UPDATE_INFO_FUNCTION_WITH_METADATA = SystemContractMethod.declare( + UPDATE_TOKEN_INFO_STRING + HEDERA_TOKEN_WITH_METADATA + ")", ReturnTypes.INT) + .withVariant(Variant.WITH_METADATA) + .withCategories(Category.UPDATE); + + /** + * @param decoder the decoder to use for token update info calls + */ + @Inject + public UpdateTranslator( + final UpdateDecoder decoder, + @NonNull final SystemContractMethodRegistry systemContractMethodRegistry, + @NonNull final ContractMetrics contractMetrics) { + super(systemContractMethodRegistry, contractMetrics); + + registerMethods(TOKEN_UPDATE_INFO_FUNCTION_WITH_METADATA); + + updateMethodsMap.put(TOKEN_UPDATE_INFO_FUNCTION_WITH_METADATA, decoder::decodeTokenUpdateWithMetadata); + + updateMethodsSet.add(TOKEN_UPDATE_INFO_FUNCTION_WITH_METADATA); + } +} diff --git a/hedera-node/hedera-smart-contract-service-impl/src/test/java/com/hedera/node/app/service/contract/impl/test/exec/systemcontracts/hts/allowance/GetAllowanceTranslatorTest.java b/hedera-node/hedera-smart-contract-service-impl/src/test/java/com/hedera/node/app/service/contract/impl/test/exec/systemcontracts/hts/allowance/GetAllowanceTranslatorTest.java index 1b23e6dcf66..f135bafe15a 100644 --- a/hedera-node/hedera-smart-contract-service-impl/src/test/java/com/hedera/node/app/service/contract/impl/test/exec/systemcontracts/hts/allowance/GetAllowanceTranslatorTest.java +++ b/hedera-node/hedera-smart-contract-service-impl/src/test/java/com/hedera/node/app/service/contract/impl/test/exec/systemcontracts/hts/allowance/GetAllowanceTranslatorTest.java @@ -3,7 +3,7 @@ import static com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.allowance.GetAllowanceTranslator.ERC_GET_ALLOWANCE; import static com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.allowance.GetAllowanceTranslator.GET_ALLOWANCE; -import static com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.update.UpdateTranslator.TOKEN_UPDATE_INFO_FUNCTION_V3; +import static com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.update.address_0x167.UpdateTranslator.TOKEN_UPDATE_INFO_FUNCTION_V3; import static com.hedera.node.app.service.contract.impl.test.TestHelpers.APPROVED_HEADLONG_ADDRESS; import static com.hedera.node.app.service.contract.impl.test.TestHelpers.FUNGIBLE_TOKEN_HEADLONG_ADDRESS; import static com.hedera.node.app.service.contract.impl.test.TestHelpers.OWNER_HEADLONG_ADDRESS; diff --git a/hedera-node/hedera-smart-contract-service-impl/src/test/java/com/hedera/node/app/service/contract/impl/test/exec/systemcontracts/hts/burn/BurnTranslatorTest.java b/hedera-node/hedera-smart-contract-service-impl/src/test/java/com/hedera/node/app/service/contract/impl/test/exec/systemcontracts/hts/burn/BurnTranslatorTest.java index 3987b655fdf..68ee182c5b3 100644 --- a/hedera-node/hedera-smart-contract-service-impl/src/test/java/com/hedera/node/app/service/contract/impl/test/exec/systemcontracts/hts/burn/BurnTranslatorTest.java +++ b/hedera-node/hedera-smart-contract-service-impl/src/test/java/com/hedera/node/app/service/contract/impl/test/exec/systemcontracts/hts/burn/BurnTranslatorTest.java @@ -3,7 +3,7 @@ import static com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.burn.BurnTranslator.BURN_TOKEN_V1; import static com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.burn.BurnTranslator.BURN_TOKEN_V2; -import static com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.update.UpdateTranslator.TOKEN_UPDATE_INFO_FUNCTION_V3; +import static com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.update.address_0x167.UpdateTranslator.TOKEN_UPDATE_INFO_FUNCTION_V3; import static com.hedera.node.app.service.contract.impl.test.exec.systemcontracts.CallAttemptHelpers.prepareHtsAttemptWithSelector; import static org.assertj.core.api.Assertions.assertThat; diff --git a/hedera-node/hedera-smart-contract-service-impl/src/test/java/com/hedera/node/app/service/contract/impl/test/exec/systemcontracts/hts/update/UpdateExpiryTranslatorTest.java b/hedera-node/hedera-smart-contract-service-impl/src/test/java/com/hedera/node/app/service/contract/impl/test/exec/systemcontracts/hts/update/UpdateExpiryTranslatorTest.java index 7273ed1770a..56896ac76f7 100644 --- a/hedera-node/hedera-smart-contract-service-impl/src/test/java/com/hedera/node/app/service/contract/impl/test/exec/systemcontracts/hts/update/UpdateExpiryTranslatorTest.java +++ b/hedera-node/hedera-smart-contract-service-impl/src/test/java/com/hedera/node/app/service/contract/impl/test/exec/systemcontracts/hts/update/UpdateExpiryTranslatorTest.java @@ -3,7 +3,7 @@ import static com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.update.UpdateExpiryTranslator.UPDATE_TOKEN_EXPIRY_INFO_V1; import static com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.update.UpdateExpiryTranslator.UPDATE_TOKEN_EXPIRY_INFO_V2; -import static com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.update.UpdateKeysTranslator.TOKEN_UPDATE_KEYS_FUNCTION; +import static com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.update.address_0x167.UpdateKeysTranslator.TOKEN_UPDATE_KEYS_FUNCTION; import static com.hedera.node.app.service.contract.impl.test.TestHelpers.NON_FUNGIBLE_TOKEN_HEADLONG_ADDRESS; import static com.hedera.node.app.service.contract.impl.test.TestHelpers.NON_SYSTEM_ACCOUNT_ID; import static com.hedera.node.app.service.contract.impl.test.TestHelpers.OWNER_HEADLONG_ADDRESS; @@ -20,8 +20,8 @@ import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.AddressIdConverter; import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.DispatchForResponseCodeHtsCall; import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.HtsCallAttempt; -import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.update.UpdateDecoder; import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.update.UpdateExpiryTranslator; +import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.update.address_0x167.UpdateDecoder; import com.hedera.node.app.service.contract.impl.exec.utils.SystemContractMethodRegistry; import com.hedera.node.app.service.contract.impl.hevm.HederaWorldUpdater; import java.time.Instant; @@ -111,8 +111,8 @@ void matchesFailsIfIncorrectSelectorTest() { @Test void callFromUpdateTest() { - Tuple tuple = Tuple.of(NON_FUNGIBLE_TOKEN_HEADLONG_ADDRESS, expiry); - Bytes inputBytes = Bytes.wrapByteBuffer(UPDATE_TOKEN_EXPIRY_INFO_V1.encodeCall(tuple)); + final Tuple tuple = Tuple.of(NON_FUNGIBLE_TOKEN_HEADLONG_ADDRESS, expiry); + final Bytes inputBytes = Bytes.wrapByteBuffer(UPDATE_TOKEN_EXPIRY_INFO_V1.encodeCall(tuple)); given(attempt.input()).willReturn(inputBytes); given(attempt.selector()).willReturn(UPDATE_TOKEN_EXPIRY_INFO_V1.selector()); given(attempt.enhancement()).willReturn(enhancement); diff --git a/hedera-node/hedera-smart-contract-service-impl/src/test/java/com/hedera/node/app/service/contract/impl/test/exec/systemcontracts/hts/update/UpdateNFTsMetadataTranslatorTest.java b/hedera-node/hedera-smart-contract-service-impl/src/test/java/com/hedera/node/app/service/contract/impl/test/exec/systemcontracts/hts/update/UpdateNFTsMetadataTranslatorTest.java index 055136436e0..8c29b5618be 100644 --- a/hedera-node/hedera-smart-contract-service-impl/src/test/java/com/hedera/node/app/service/contract/impl/test/exec/systemcontracts/hts/update/UpdateNFTsMetadataTranslatorTest.java +++ b/hedera-node/hedera-smart-contract-service-impl/src/test/java/com/hedera/node/app/service/contract/impl/test/exec/systemcontracts/hts/update/UpdateNFTsMetadataTranslatorTest.java @@ -14,8 +14,8 @@ import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.AddressIdConverter; import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.DispatchForResponseCodeHtsCall; import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.HtsCallAttempt; -import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.update.UpdateDecoder; -import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.update.UpdateNFTsMetadataTranslator; +import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.update.address_0x16c.UpdateDecoder; +import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.update.address_0x16c.UpdateNFTsMetadataTranslator; import com.hedera.node.app.service.contract.impl.exec.utils.SystemContractMethodRegistry; import com.hedera.node.app.service.contract.impl.hevm.HederaWorldUpdater; import com.hedera.node.config.testfixtures.HederaTestConfigBuilder; @@ -61,18 +61,11 @@ void setUp() { @Test void matchesUpdateNFTsMetadataTest() { - given(attempt.configuration()).willReturn(getTestConfiguration(true)); given(attempt.isMethod(UpdateNFTsMetadataTranslator.UPDATE_NFTs_METADATA)) .willReturn(Optional.of(UpdateNFTsMetadataTranslator.UPDATE_NFTs_METADATA)); assertThat(subject.identifyMethod(attempt)).isPresent(); } - @Test - void doesNotMatchUpdateNFTsMetadataWhenDisabled() { - given(attempt.configuration()).willReturn(getTestConfiguration(false)); - assertThat(subject.identifyMethod(attempt)).isEmpty(); - } - @Test void callFromUpdateTest() { final var tuple = Tuple.of(NON_FUNGIBLE_TOKEN_HEADLONG_ADDRESS, new long[] {1}, "P. Griffin".getBytes()); diff --git a/hedera-node/hedera-smart-contract-service-impl/src/test/java/com/hedera/node/app/service/contract/impl/test/exec/systemcontracts/hts/update/UpdateDecoderTest.java b/hedera-node/hedera-smart-contract-service-impl/src/test/java/com/hedera/node/app/service/contract/impl/test/exec/systemcontracts/hts/update/address_0x167/UpdateDecoderTest.java similarity index 73% rename from hedera-node/hedera-smart-contract-service-impl/src/test/java/com/hedera/node/app/service/contract/impl/test/exec/systemcontracts/hts/update/UpdateDecoderTest.java rename to hedera-node/hedera-smart-contract-service-impl/src/test/java/com/hedera/node/app/service/contract/impl/test/exec/systemcontracts/hts/update/address_0x167/UpdateDecoderTest.java index fafc8b8953b..82e1f6838c5 100644 --- a/hedera-node/hedera-smart-contract-service-impl/src/test/java/com/hedera/node/app/service/contract/impl/test/exec/systemcontracts/hts/update/UpdateDecoderTest.java +++ b/hedera-node/hedera-smart-contract-service-impl/src/test/java/com/hedera/node/app/service/contract/impl/test/exec/systemcontracts/hts/update/address_0x167/UpdateDecoderTest.java @@ -1,11 +1,9 @@ // SPDX-License-Identifier: Apache-2.0 -package com.hedera.node.app.service.contract.impl.test.exec.systemcontracts.hts.update; +package com.hedera.node.app.service.contract.impl.test.exec.systemcontracts.hts.update.address_0x167; import static com.hedera.node.app.service.contract.impl.test.TestHelpers.FUNGIBLE_TOKEN_HEADLONG_ADDRESS; -import static com.hedera.node.app.service.contract.impl.test.TestHelpers.NON_FUNGIBLE_TOKEN_HEADLONG_ADDRESS; import static com.hedera.node.app.service.contract.impl.test.TestHelpers.OWNER_HEADLONG_ADDRESS; import static com.hedera.node.app.service.contract.impl.test.TestHelpers.OWNER_ID; -import static java.util.Objects.requireNonNull; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.mockito.BDDMockito.given; @@ -13,10 +11,9 @@ import com.esaulpaugh.headlong.abi.Tuple; import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.AddressIdConverter; import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.HtsCallAttempt; -import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.update.UpdateDecoder; import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.update.UpdateExpiryTranslator; -import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.update.UpdateNFTsMetadataTranslator; -import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.update.UpdateTranslator; +import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.update.address_0x167.UpdateDecoder; +import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.update.address_0x167.UpdateTranslator; import java.time.Instant; import org.apache.tuweni.bytes.Bytes; import org.junit.jupiter.api.BeforeEach; @@ -36,7 +33,6 @@ class UpdateDecoderTest { private final UpdateDecoder subject = new UpdateDecoder(); private final String newName = "NEW NAME"; - private final String metadata = "LionTigerBear"; private static final long EXPIRY_TIMESTAMP = Instant.now().plusSeconds(3600).toEpochMilli() / 1000; private static final long AUTO_RENEW_PERIOD = 8_000_000L; private final Tuple expiry = Tuple.of(EXPIRY_TIMESTAMP, OWNER_HEADLONG_ADDRESS, AUTO_RENEW_PERIOD); @@ -53,21 +49,6 @@ class UpdateDecoderTest { // Expiry expiry); - private final Tuple hederaTokenWithMetadata = Tuple.from( - newName, - "symbol", - OWNER_HEADLONG_ADDRESS, - "memo", - true, - 1000L, - false, - // TokenKey - new Tuple[] {}, - // Expiry - expiry, - // Metadata, - metadata.getBytes()); - @Nested class UpdateTokenInfoAndExpiry { @BeforeEach @@ -109,18 +90,6 @@ void updateV3Works() { assertEquals(tokenUpdate.name(), newName); } - @Test - void updateWithMetadataWorks() { - final var encoded = - Bytes.wrapByteBuffer(UpdateTranslator.TOKEN_UPDATE_INFO_FUNCTION_WITH_METADATA.encodeCallWithArgs( - FUNGIBLE_TOKEN_HEADLONG_ADDRESS, hederaTokenWithMetadata)); - given(attempt.input()).willReturn(encoded); - - final var body = subject.decodeTokenUpdateWithMetadata(attempt); - final var tokenUpdate = body.tokenUpdateOrThrow(); - assertEquals(tokenUpdate.metadata().asUtf8String(), metadata); - } - @Test void updateExpiryV1Works() { final var encoded = @@ -157,18 +126,4 @@ void updateExpiryV2Works() { assertEquals(OWNER_ID, tokenUpdate.autoRenewAccount()); } } - - @Test - void updateNFTsMetadataWorks() { - final var encoded = Bytes.wrapByteBuffer(UpdateNFTsMetadataTranslator.UPDATE_NFTs_METADATA.encodeCallWithArgs( - NON_FUNGIBLE_TOKEN_HEADLONG_ADDRESS, new long[] {1, 2, 3}, "Jerry".getBytes())); - given(attempt.input()).willReturn(encoded); - - final var body = subject.decodeUpdateNFTsMetadata(attempt); - final var tokenUpdate = requireNonNull(body).tokenUpdateNftsOrThrow(); - - assertNotNull(tokenUpdate.metadata()); - assertEquals("Jerry", tokenUpdate.metadata().asUtf8String()); - assertEquals(3, tokenUpdate.serialNumbers().size()); - } } diff --git a/hedera-node/hedera-smart-contract-service-impl/src/test/java/com/hedera/node/app/service/contract/impl/test/exec/systemcontracts/hts/update/UpdateKeysTranslatorTest.java b/hedera-node/hedera-smart-contract-service-impl/src/test/java/com/hedera/node/app/service/contract/impl/test/exec/systemcontracts/hts/update/address_0x167/UpdateKeysTranslatorTest.java similarity index 95% rename from hedera-node/hedera-smart-contract-service-impl/src/test/java/com/hedera/node/app/service/contract/impl/test/exec/systemcontracts/hts/update/UpdateKeysTranslatorTest.java rename to hedera-node/hedera-smart-contract-service-impl/src/test/java/com/hedera/node/app/service/contract/impl/test/exec/systemcontracts/hts/update/address_0x167/UpdateKeysTranslatorTest.java index 5edd05a760a..c156e3d2e6b 100644 --- a/hedera-node/hedera-smart-contract-service-impl/src/test/java/com/hedera/node/app/service/contract/impl/test/exec/systemcontracts/hts/update/UpdateKeysTranslatorTest.java +++ b/hedera-node/hedera-smart-contract-service-impl/src/test/java/com/hedera/node/app/service/contract/impl/test/exec/systemcontracts/hts/update/address_0x167/UpdateKeysTranslatorTest.java @@ -1,5 +1,5 @@ // SPDX-License-Identifier: Apache-2.0 -package com.hedera.node.app.service.contract.impl.test.exec.systemcontracts.hts.update; +package com.hedera.node.app.service.contract.impl.test.exec.systemcontracts.hts.update.address_0x167; import static com.hedera.node.app.service.contract.impl.test.exec.systemcontracts.CallAttemptHelpers.prepareHtsAttemptWithSelector; import static org.assertj.core.api.Assertions.assertThat; @@ -10,8 +10,8 @@ import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.AddressIdConverter; import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.HtsCallAttempt; import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.freeze.FreezeUnfreezeTranslator; -import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.update.UpdateDecoder; -import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.update.UpdateKeysTranslator; +import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.update.address_0x167.UpdateDecoder; +import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.update.address_0x167.UpdateKeysTranslator; import com.hedera.node.app.service.contract.impl.exec.utils.SystemContractMethodRegistry; import com.hedera.node.app.service.contract.impl.hevm.HederaWorldUpdater; import org.junit.jupiter.api.BeforeEach; diff --git a/hedera-node/hedera-smart-contract-service-impl/src/test/java/com/hedera/node/app/service/contract/impl/test/exec/systemcontracts/hts/update/UpdateTranslatorTest.java b/hedera-node/hedera-smart-contract-service-impl/src/test/java/com/hedera/node/app/service/contract/impl/test/exec/systemcontracts/hts/update/address_0x167/UpdateTranslatorTest.java similarity index 90% rename from hedera-node/hedera-smart-contract-service-impl/src/test/java/com/hedera/node/app/service/contract/impl/test/exec/systemcontracts/hts/update/UpdateTranslatorTest.java rename to hedera-node/hedera-smart-contract-service-impl/src/test/java/com/hedera/node/app/service/contract/impl/test/exec/systemcontracts/hts/update/address_0x167/UpdateTranslatorTest.java index 44503a3c79a..14dd9f73ea9 100644 --- a/hedera-node/hedera-smart-contract-service-impl/src/test/java/com/hedera/node/app/service/contract/impl/test/exec/systemcontracts/hts/update/UpdateTranslatorTest.java +++ b/hedera-node/hedera-smart-contract-service-impl/src/test/java/com/hedera/node/app/service/contract/impl/test/exec/systemcontracts/hts/update/address_0x167/UpdateTranslatorTest.java @@ -1,16 +1,17 @@ // SPDX-License-Identifier: Apache-2.0 -package com.hedera.node.app.service.contract.impl.test.exec.systemcontracts.hts.update; +package com.hedera.node.app.service.contract.impl.test.exec.systemcontracts.hts.update.address_0x167; import static com.hedera.hapi.node.base.ResponseCodeEnum.INVALID_ACCOUNT_ID; import static com.hedera.hapi.node.base.ResponseCodeEnum.INVALID_SIGNATURE; import static com.hedera.hapi.node.base.ResponseCodeEnum.INVALID_TOKEN_ID; import static com.hedera.hapi.node.base.ResponseCodeEnum.INVALID_TREASURY_ACCOUNT_FOR_TOKEN; import static com.hedera.hapi.node.base.ResponseCodeEnum.TOKEN_IS_IMMUTABLE; -import static com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.update.UpdateDecoder.FAILURE_CUSTOMIZER; -import static com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.update.UpdateTranslator.TOKEN_UPDATE_INFO_FUNCTION_V1; -import static com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.update.UpdateTranslator.TOKEN_UPDATE_INFO_FUNCTION_V2; -import static com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.update.UpdateTranslator.TOKEN_UPDATE_INFO_FUNCTION_V3; -import static com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.update.UpdateTranslator.TOKEN_UPDATE_INFO_FUNCTION_WITH_METADATA; +import static com.hedera.node.app.service.contract.impl.exec.systemcontracts.HtsSystemContract.HTS_167_CONTRACT_ID; +import static com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.update.UpdateCommonDecoder.FAILURE_CUSTOMIZER; +import static com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.update.address_0x167.UpdateTranslator.TOKEN_UPDATE_INFO_FUNCTION_V1; +import static com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.update.address_0x167.UpdateTranslator.TOKEN_UPDATE_INFO_FUNCTION_V2; +import static com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.update.address_0x167.UpdateTranslator.TOKEN_UPDATE_INFO_FUNCTION_V3; +import static com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.update.address_0x16c.UpdateTranslator.TOKEN_UPDATE_INFO_FUNCTION_WITH_METADATA; import static com.hedera.node.app.service.contract.impl.test.TestHelpers.EXPLICITLY_IMMUTABLE_FUNGIBLE_TOKEN; import static com.hedera.node.app.service.contract.impl.test.TestHelpers.FUNGIBLE_TOKEN; import static com.hedera.node.app.service.contract.impl.test.TestHelpers.FUNGIBLE_TOKEN_ID; @@ -18,7 +19,7 @@ import static com.hedera.node.app.service.contract.impl.test.TestHelpers.NON_FUNGIBLE_TOKEN_HEADLONG_ADDRESS; import static com.hedera.node.app.service.contract.impl.test.TestHelpers.NON_SYSTEM_ACCOUNT_ID; import static com.hedera.node.app.service.contract.impl.test.exec.systemcontracts.CallAttemptHelpers.prepareHtsAttemptWithSelector; -import static com.hedera.node.app.service.contract.impl.test.exec.systemcontracts.CallAttemptHelpers.prepareHtsAttemptWithSelectorAndCustomConfig; +import static com.hedera.node.app.service.contract.impl.test.exec.systemcontracts.CallAttemptHelpers.prepareHtsAttemptWithSelectorWithContractID; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.mockito.ArgumentMatchers.any; @@ -36,15 +37,13 @@ import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.DispatchForResponseCodeHtsCall; import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.HtsCallAttempt; import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.freeze.FreezeUnfreezeTranslator; -import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.update.UpdateDecoder; -import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.update.UpdateTranslator; +import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.update.address_0x167.UpdateDecoder; +import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.update.address_0x167.UpdateTranslator; import com.hedera.node.app.service.contract.impl.exec.utils.SystemContractMethodRegistry; import com.hedera.node.app.service.contract.impl.hevm.HederaWorldUpdater; import com.hedera.node.app.service.contract.impl.test.exec.systemcontracts.common.CallTestBase; import com.hedera.node.app.service.token.ReadableAccountStore; import com.hedera.node.app.service.token.ReadableTokenStore; -import com.hedera.node.config.data.ContractsConfig; -import com.swirlds.config.api.Configuration; import org.apache.tuweni.bytes.Bytes; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -75,12 +74,6 @@ class UpdateTranslatorTest extends CallTestBase { @Mock private ReadableAccountStore readableAccountStore; - @Mock - private ContractsConfig contractsConfig; - - @Mock - Configuration configuration; - @Mock private ContractMetrics contractMetrics; @@ -209,25 +202,23 @@ void matchesUpdateV3Test() { } @Test - void matchesUpdateMetadataTest() { - given(configuration.getConfigData(ContractsConfig.class)).willReturn(contractsConfig); - given(contractsConfig.metadataKeyAndFieldEnabled()).willReturn(true); - attempt = prepareHtsAttemptWithSelectorAndCustomConfig( - TOKEN_UPDATE_INFO_FUNCTION_WITH_METADATA, + void matchesFailsOnIncorrectSelector() { + attempt = prepareHtsAttemptWithSelector( + FreezeUnfreezeTranslator.FREEZE, subject, enhancement, addressIdConverter, verificationStrategies, gasCalculator, - systemContractMethodRegistry, - configuration); - assertThat(subject.identifyMethod(attempt)).isPresent(); + systemContractMethodRegistry); + assertThat(subject.identifyMethod(attempt)).isEmpty(); } @Test - void matchesFailsOnIncorrectSelector() { - attempt = prepareHtsAttemptWithSelector( - FreezeUnfreezeTranslator.FREEZE, + void matchesFailsOnUpdateMetadataTest() { + attempt = prepareHtsAttemptWithSelectorWithContractID( + HTS_167_CONTRACT_ID, + TOKEN_UPDATE_INFO_FUNCTION_WITH_METADATA, subject, enhancement, addressIdConverter, @@ -243,9 +234,6 @@ void callFromUpdateTest() { Bytes inputBytes = Bytes.wrapByteBuffer(TOKEN_UPDATE_INFO_FUNCTION_V1.encodeCall(tuple)); given(attempt.input()).willReturn(inputBytes); given(attempt.isSelector(TOKEN_UPDATE_INFO_FUNCTION_V1)).willReturn(true); - lenient() - .when(attempt.isSelector(TOKEN_UPDATE_INFO_FUNCTION_WITH_METADATA)) - .thenReturn(false); lenient().when(attempt.isSelector(TOKEN_UPDATE_INFO_FUNCTION_V2)).thenReturn(false); lenient().when(attempt.isSelector(TOKEN_UPDATE_INFO_FUNCTION_V3)).thenReturn(false); given(attempt.enhancement()).willReturn(mockEnhancement()); diff --git a/hedera-node/hedera-smart-contract-service-impl/src/test/java/com/hedera/node/app/service/contract/impl/test/exec/systemcontracts/hts/update/address_0x16c/UpdateDecoderTest.java b/hedera-node/hedera-smart-contract-service-impl/src/test/java/com/hedera/node/app/service/contract/impl/test/exec/systemcontracts/hts/update/address_0x16c/UpdateDecoderTest.java new file mode 100644 index 00000000000..214b6a31360 --- /dev/null +++ b/hedera-node/hedera-smart-contract-service-impl/src/test/java/com/hedera/node/app/service/contract/impl/test/exec/systemcontracts/hts/update/address_0x16c/UpdateDecoderTest.java @@ -0,0 +1,89 @@ +// SPDX-License-Identifier: Apache-2.0 +package com.hedera.node.app.service.contract.impl.test.exec.systemcontracts.hts.update.address_0x16c; + +import static com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.update.address_0x16c.UpdateTranslator.TOKEN_UPDATE_INFO_FUNCTION_WITH_METADATA; +import static com.hedera.node.app.service.contract.impl.test.TestHelpers.FUNGIBLE_TOKEN_HEADLONG_ADDRESS; +import static com.hedera.node.app.service.contract.impl.test.TestHelpers.NON_FUNGIBLE_TOKEN_HEADLONG_ADDRESS; +import static com.hedera.node.app.service.contract.impl.test.TestHelpers.OWNER_HEADLONG_ADDRESS; +import static com.hedera.node.app.service.contract.impl.test.TestHelpers.OWNER_ID; +import static java.util.Objects.requireNonNull; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.lenient; + +import com.esaulpaugh.headlong.abi.Tuple; +import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.AddressIdConverter; +import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.HtsCallAttempt; +import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.update.address_0x16c.UpdateDecoder; +import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.update.address_0x16c.UpdateNFTsMetadataTranslator; +import java.time.Instant; +import org.apache.tuweni.bytes.Bytes; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +@ExtendWith(MockitoExtension.class) +class UpdateDecoderTest { + + @Mock + private HtsCallAttempt attempt; + + private UpdateDecoder subject = new UpdateDecoder(); + + @Mock + private AddressIdConverter addressIdConverter; + + private final String newName = "NEW NAME"; + private final String metadata = "LionTigerBear"; + private static final long EXPIRY_TIMESTAMP = Instant.now().plusSeconds(3600).toEpochMilli() / 1000; + private static final long AUTO_RENEW_PERIOD = 8_000_000L; + private final Tuple expiry = Tuple.of(EXPIRY_TIMESTAMP, OWNER_HEADLONG_ADDRESS, AUTO_RENEW_PERIOD); + private final Tuple hederaTokenWithMetadata = Tuple.from( + newName, + "symbol", + OWNER_HEADLONG_ADDRESS, + "memo", + true, + 1000L, + false, + // TokenKey + new Tuple[] {}, + // Expiry + expiry, + // Metadata, + metadata.getBytes()); + + @BeforeEach + void setUp() { + lenient().when(attempt.addressIdConverter()).thenReturn(addressIdConverter); + lenient().when(addressIdConverter.convert(OWNER_HEADLONG_ADDRESS)).thenReturn(OWNER_ID); + } + + @Test + void updateWithMetadataWorks() { + final var encoded = Bytes.wrapByteBuffer(TOKEN_UPDATE_INFO_FUNCTION_WITH_METADATA.encodeCallWithArgs( + FUNGIBLE_TOKEN_HEADLONG_ADDRESS, hederaTokenWithMetadata)); + given(attempt.input()).willReturn(encoded); + + final var body = subject.decodeTokenUpdateWithMetadata(attempt); + final var tokenUpdate = body.tokenUpdateOrThrow(); + assertEquals(tokenUpdate.metadata().asUtf8String(), metadata); + } + + @Test + void updateNFTsMetadataWorks() { + final var encoded = Bytes.wrapByteBuffer(UpdateNFTsMetadataTranslator.UPDATE_NFTs_METADATA.encodeCallWithArgs( + NON_FUNGIBLE_TOKEN_HEADLONG_ADDRESS, new long[] {1, 2, 3}, "Jerry".getBytes())); + given(attempt.input()).willReturn(encoded); + + final var body = subject.decodeUpdateNFTsMetadata(attempt); + final var tokenUpdate = requireNonNull(body).tokenUpdateNftsOrThrow(); + + assertNotNull(tokenUpdate.metadata()); + assertEquals("Jerry", tokenUpdate.metadata().asUtf8String()); + assertEquals(3, tokenUpdate.serialNumbers().size()); + } +} diff --git a/hedera-node/hedera-smart-contract-service-impl/src/test/java/com/hedera/node/app/service/contract/impl/test/exec/systemcontracts/hts/update/address_0x16c/UpdateKeysTranslatorTest.java b/hedera-node/hedera-smart-contract-service-impl/src/test/java/com/hedera/node/app/service/contract/impl/test/exec/systemcontracts/hts/update/address_0x16c/UpdateKeysTranslatorTest.java new file mode 100644 index 00000000000..276b1eb64d3 --- /dev/null +++ b/hedera-node/hedera-smart-contract-service-impl/src/test/java/com/hedera/node/app/service/contract/impl/test/exec/systemcontracts/hts/update/address_0x16c/UpdateKeysTranslatorTest.java @@ -0,0 +1,82 @@ +// SPDX-License-Identifier: Apache-2.0 +package com.hedera.node.app.service.contract.impl.test.exec.systemcontracts.hts.update.address_0x16c; + +import static com.hedera.node.app.service.contract.impl.exec.systemcontracts.HtsSystemContract.HTS_16C_CONTRACT_ID; +import static com.hedera.node.app.service.contract.impl.test.exec.systemcontracts.CallAttemptHelpers.prepareHtsAttemptWithSelectorWithContractID; +import static org.assertj.core.api.Assertions.assertThat; + +import com.hedera.node.app.service.contract.impl.exec.gas.SystemContractGasCalculator; +import com.hedera.node.app.service.contract.impl.exec.metrics.ContractMetrics; +import com.hedera.node.app.service.contract.impl.exec.scope.VerificationStrategies; +import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.AddressIdConverter; +import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.HtsCallAttempt; +import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.freeze.FreezeUnfreezeTranslator; +import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.update.address_0x16c.UpdateDecoder; +import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.update.address_0x16c.UpdateKeysTranslator; +import com.hedera.node.app.service.contract.impl.exec.utils.SystemContractMethodRegistry; +import com.hedera.node.app.service.contract.impl.hevm.HederaWorldUpdater; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +@ExtendWith(MockitoExtension.class) +class UpdateKeysTranslatorTest { + @Mock + private HtsCallAttempt attempt; + + @Mock + private SystemContractGasCalculator gasCalculator; + + @Mock + private HederaWorldUpdater.Enhancement enhancement; + + @Mock + private AddressIdConverter addressIdConverter; + + @Mock + private VerificationStrategies verificationStrategies; + + @Mock + private ContractMetrics contractMetrics; + + private final SystemContractMethodRegistry systemContractMethodRegistry = new SystemContractMethodRegistry(); + + private UpdateKeysTranslator subject; + + private final UpdateDecoder decoder = new UpdateDecoder(); + + @BeforeEach + void setUp() { + subject = new UpdateKeysTranslator(decoder, systemContractMethodRegistry, contractMetrics); + } + + @Test + void matchesUpdateKeysTest() { + attempt = prepareHtsAttemptWithSelectorWithContractID( + HTS_16C_CONTRACT_ID, + UpdateKeysTranslator.TOKEN_UPDATE_KEYS_16C, + subject, + enhancement, + addressIdConverter, + verificationStrategies, + gasCalculator, + systemContractMethodRegistry); + assertThat(subject.identifyMethod(attempt)).isPresent(); + } + + @Test + void matchesIncorrectSelectorFailsTest() { + attempt = prepareHtsAttemptWithSelectorWithContractID( + HTS_16C_CONTRACT_ID, + FreezeUnfreezeTranslator.FREEZE, + subject, + enhancement, + addressIdConverter, + verificationStrategies, + gasCalculator, + systemContractMethodRegistry); + assertThat(subject.identifyMethod(attempt)).isEmpty(); + } +} diff --git a/hedera-node/hedera-smart-contract-service-impl/src/test/java/com/hedera/node/app/service/contract/impl/test/exec/systemcontracts/hts/update/address_0x16c/UpdateTranslatorTest.java b/hedera-node/hedera-smart-contract-service-impl/src/test/java/com/hedera/node/app/service/contract/impl/test/exec/systemcontracts/hts/update/address_0x16c/UpdateTranslatorTest.java new file mode 100644 index 00000000000..6274533e401 --- /dev/null +++ b/hedera-node/hedera-smart-contract-service-impl/src/test/java/com/hedera/node/app/service/contract/impl/test/exec/systemcontracts/hts/update/address_0x16c/UpdateTranslatorTest.java @@ -0,0 +1,81 @@ +// SPDX-License-Identifier: Apache-2.0 +package com.hedera.node.app.service.contract.impl.test.exec.systemcontracts.hts.update.address_0x16c; + +import static com.hedera.node.app.service.contract.impl.exec.systemcontracts.HtsSystemContract.HTS_16C_CONTRACT_ID; +import static com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.update.address_0x16c.UpdateTranslator.TOKEN_UPDATE_INFO_FUNCTION_WITH_METADATA; +import static com.hedera.node.app.service.contract.impl.test.exec.systemcontracts.CallAttemptHelpers.prepareHtsAttemptWithSelectorWithContractID; +import static org.assertj.core.api.Assertions.assertThat; + +import com.hedera.node.app.service.contract.impl.exec.metrics.ContractMetrics; +import com.hedera.node.app.service.contract.impl.exec.scope.VerificationStrategies; +import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.AddressIdConverter; +import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.HtsCallAttempt; +import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.freeze.FreezeUnfreezeTranslator; +import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.update.address_0x16c.UpdateDecoder; +import com.hedera.node.app.service.contract.impl.exec.systemcontracts.hts.update.address_0x16c.UpdateTranslator; +import com.hedera.node.app.service.contract.impl.exec.utils.SystemContractMethodRegistry; +import com.hedera.node.app.service.contract.impl.hevm.HederaWorldUpdater; +import com.hedera.node.app.service.contract.impl.test.exec.systemcontracts.common.CallTestBase; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +@ExtendWith(MockitoExtension.class) +class UpdateTranslatorTest extends CallTestBase { + + @Mock + private HtsCallAttempt attempt; + + @Mock + private AddressIdConverter addressIdConverter; + + @Mock + private VerificationStrategies verificationStrategies; + + @Mock + private HederaWorldUpdater.Enhancement enhancement; + + @Mock + private ContractMetrics contractMetrics; + + private final SystemContractMethodRegistry systemContractMethodRegistry = new SystemContractMethodRegistry(); + + private UpdateTranslator subject; + + private final UpdateDecoder decoder = new UpdateDecoder(); + + @BeforeEach + void setUp() { + subject = new UpdateTranslator(decoder, systemContractMethodRegistry, contractMetrics); + } + + @Test + void matchesUpdateMetadataTest() { + attempt = prepareHtsAttemptWithSelectorWithContractID( + HTS_16C_CONTRACT_ID, + TOKEN_UPDATE_INFO_FUNCTION_WITH_METADATA, + subject, + enhancement, + addressIdConverter, + verificationStrategies, + gasCalculator, + systemContractMethodRegistry); + assertThat(subject.identifyMethod(attempt)).isPresent(); + } + + @Test + void matchesFailsOnIncorrectSelector() { + attempt = prepareHtsAttemptWithSelectorWithContractID( + HTS_16C_CONTRACT_ID, + FreezeUnfreezeTranslator.FREEZE, + subject, + enhancement, + addressIdConverter, + verificationStrategies, + gasCalculator, + systemContractMethodRegistry); + assertThat(subject.identifyMethod(attempt)).isEmpty(); + } +} diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/address_16c/NumericValidation16c.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/address_16c/NumericValidation16c.java new file mode 100644 index 00000000000..e85dfd69d9c --- /dev/null +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/address_16c/NumericValidation16c.java @@ -0,0 +1,53 @@ +// SPDX-License-Identifier: Apache-2.0 +package com.hedera.services.bdd.suites.contract.precompile.address_16c; + +import static com.hedera.services.bdd.junit.RepeatableReason.NEEDS_VIRTUAL_TIME_FOR_FAST_EXECUTION; +import static com.hedera.services.bdd.spec.HapiSpec.hapiTest; +import static com.hedera.services.bdd.spec.dsl.entities.SpecContract.VARIANT_16C; +import static com.hedera.services.bdd.spec.dsl.entities.SpecTokenKey.ADMIN_KEY; +import static com.hedera.services.bdd.spec.dsl.entities.SpecTokenKey.METADATA_KEY; +import static com.hedera.services.bdd.spec.dsl.entities.SpecTokenKey.PAUSE_KEY; +import static com.hedera.services.bdd.spec.dsl.entities.SpecTokenKey.SUPPLY_KEY; +import static com.hederahashgraph.api.proto.java.ResponseCodeEnum.CONTRACT_REVERT_EXECUTED; +import static com.hederahashgraph.api.proto.java.ResponseCodeEnum.INVALID_NFT_ID; +import static com.hederahashgraph.api.proto.java.ResponseCodeEnum.MISSING_SERIAL_NUMBERS; + +import com.hedera.services.bdd.junit.HapiTest; +import com.hedera.services.bdd.junit.RepeatableHapiTest; +import com.hedera.services.bdd.spec.dsl.annotations.Contract; +import com.hedera.services.bdd.spec.dsl.annotations.NonFungibleToken; +import com.hedera.services.bdd.spec.dsl.entities.SpecContract; +import com.hedera.services.bdd.spec.dsl.entities.SpecNonFungibleToken; +import java.util.stream.Stream; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.DynamicTest; + +public class NumericValidation16c { + + @Contract(contract = "NumericContract16c", creationGas = 1_000_000L, variant = VARIANT_16C) + static SpecContract numericContract; + + @NonFungibleToken( + numPreMints = 5, + keys = {SUPPLY_KEY, PAUSE_KEY, ADMIN_KEY, METADATA_KEY}) + static SpecNonFungibleToken nft; + + @RepeatableHapiTest(NEEDS_VIRTUAL_TIME_FOR_FAST_EXECUTION) + @DisplayName("when using updateNFTsMetadata for specific NFT from NFT collection with invalid serial number") + public Stream failToUpdateNFTsMetadata() { + return Stream.of(new long[] {Long.MAX_VALUE}, new long[] {0}, new long[] {-1, 1}, new long[] {-1}) + .flatMap(invalidSerialNumbers -> hapiTest(numericContract + .call("updateNFTsMetadata", nft, invalidSerialNumbers, "tiger".getBytes()) + .gas(1_000_000L) + .andAssert(txn -> txn.hasKnownStatuses(CONTRACT_REVERT_EXECUTED, INVALID_NFT_ID)))); + } + + @HapiTest + @DisplayName("when using updateNFTsMetadata for specific NFT from NFT collection with empty serial numbers") + public Stream failToUpdateNFTsMetadataWithEmptySerialNumbers() { + return hapiTest(numericContract + .call("updateNFTsMetadata", nft, new long[] {}, "zebra".getBytes()) + .gas(1_000_000L) + .andAssert(txn -> txn.hasKnownStatuses(CONTRACT_REVERT_EXECUTED, MISSING_SERIAL_NUMBERS))); + } +} diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/token/NumericValidationTest.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/token/NumericValidationTest.java index 0b28c24bd3f..9e8fac50986 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/token/NumericValidationTest.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/token/NumericValidationTest.java @@ -1,6 +1,7 @@ // SPDX-License-Identifier: Apache-2.0 package com.hedera.services.bdd.suites.contract.precompile.token; +import static com.hedera.services.bdd.junit.RepeatableReason.NEEDS_VIRTUAL_TIME_FOR_FAST_EXECUTION; import static com.hedera.services.bdd.junit.TestTags.SMART_CONTRACT; import static com.hedera.services.bdd.spec.HapiSpec.hapiTest; import static com.hedera.services.bdd.spec.dsl.entities.SpecTokenKey.ADMIN_KEY; @@ -11,13 +12,12 @@ import static com.hedera.services.bdd.suites.HapiSuite.ONE_HUNDRED_HBARS; import static com.hedera.services.bdd.suites.HapiSuite.ONE_MILLION_HBARS; import static com.hederahashgraph.api.proto.java.ResponseCodeEnum.CONTRACT_REVERT_EXECUTED; -import static com.hederahashgraph.api.proto.java.ResponseCodeEnum.INVALID_NFT_ID; -import static com.hederahashgraph.api.proto.java.ResponseCodeEnum.MISSING_SERIAL_NUMBERS; import static com.hederahashgraph.api.proto.java.ResponseCodeEnum.SUCCESS; import com.hedera.pbj.runtime.io.buffer.Bytes; import com.hedera.services.bdd.junit.HapiTest; import com.hedera.services.bdd.junit.HapiTestLifecycle; +import com.hedera.services.bdd.junit.RepeatableHapiTest; import com.hedera.services.bdd.junit.support.TestLifecycle; import com.hedera.services.bdd.spec.dsl.annotations.Account; import com.hedera.services.bdd.spec.dsl.annotations.Contract; @@ -90,7 +90,7 @@ private record BigIntegerTestCase(BigInteger amount, ResponseCodeEnum status) {} @Nested @DisplayName("calls fail to approve functions with invalid amounts") class ApproveTests { - @HapiTest + @RepeatableHapiTest(NEEDS_VIRTUAL_TIME_FOR_FAST_EXECUTION) @DisplayName("when using fungible token via redirect proxy contract") public Stream failToApproveViaProxyFungibleToken() { return zeroNegativeAndGreaterThanLong.stream() @@ -100,7 +100,7 @@ public Stream failToApproveViaProxyFungibleToken() { .andAssert(txn -> txn.hasKnownStatus(testCase.status)))); } - @HapiTest + @RepeatableHapiTest(NEEDS_VIRTUAL_TIME_FOR_FAST_EXECUTION) @DisplayName("when using nft via redirect proxy contract") public Stream failToApproveViaProxyNft() { return zeroNegativeAndGreaterThanLong.stream() @@ -110,7 +110,7 @@ public Stream failToApproveViaProxyNft() { .andAssert(txn -> txn.hasKnownStatus(testCase.status)))); } - @HapiTest + @RepeatableHapiTest(NEEDS_VIRTUAL_TIME_FOR_FAST_EXECUTION) @DisplayName("when using fungible token hts system contract") public Stream failToApproveFungibleToken() { return zeroNegativeAndGreaterThanLong.stream() @@ -120,7 +120,7 @@ public Stream failToApproveFungibleToken() { .andAssert(txn -> txn.hasKnownStatus(testCase.status)))); } - @HapiTest + @RepeatableHapiTest(NEEDS_VIRTUAL_TIME_FOR_FAST_EXECUTION) @DisplayName("when using nft hts system contract") public Stream failToApproveNft() { return zeroNegativeAndGreaterThanLong.stream() @@ -264,7 +264,7 @@ public Stream failToWipeNft() { @DisplayName("calls fail to static functions with invalid amounts") class StaticFunctionsTests { - @HapiTest + @RepeatableHapiTest(NEEDS_VIRTUAL_TIME_FOR_FAST_EXECUTION) @DisplayName("when using tokenURI") public Stream failTokenURI() { return zeroNegativeAndGreaterThanLong.stream() @@ -273,7 +273,7 @@ public Stream failTokenURI() { .andAssert(txn -> txn.hasKnownStatus(testCase.status)))); } - @HapiTest + @RepeatableHapiTest(NEEDS_VIRTUAL_TIME_FOR_FAST_EXECUTION) @DisplayName("when using getTokenKey for NFT") public Stream failToGetTokenKeyNFT() { return zeroNegativeAndGreaterThanLong.stream() @@ -282,7 +282,7 @@ public Stream failToGetTokenKeyNFT() { .andAssert(txn -> txn.hasKnownStatus(testCase.status)))); } - @HapiTest + @RepeatableHapiTest(NEEDS_VIRTUAL_TIME_FOR_FAST_EXECUTION) @DisplayName("when using getTokenKey for Fungible Token") public Stream failToGetTokenKeyFT() { return zeroNegativeAndGreaterThanLong.stream() @@ -299,7 +299,7 @@ public Stream failToGetNonFungibleTokenInfo() { .andAssert(txn -> txn.hasKnownStatus(CONTRACT_REVERT_EXECUTED))); } - @HapiTest + @RepeatableHapiTest(NEEDS_VIRTUAL_TIME_FOR_FAST_EXECUTION) @DisplayName("when using getApproved") public Stream failToGetApproved() { return zeroNegativeAndGreaterThanLong.stream() @@ -308,7 +308,7 @@ public Stream failToGetApproved() { .andAssert(txn -> txn.hasKnownStatus(testCase.status)))); } - @HapiTest + @RepeatableHapiTest(NEEDS_VIRTUAL_TIME_FOR_FAST_EXECUTION) @DisplayName("when using getApprovedERC") public Stream failToGetApprovedERC() { return zeroNegativeAndGreaterThanLong.stream() @@ -317,7 +317,7 @@ public Stream failToGetApprovedERC() { .andAssert(txn -> txn.hasKnownStatus(testCase.status)))); } - @HapiTest + @RepeatableHapiTest(NEEDS_VIRTUAL_TIME_FOR_FAST_EXECUTION) @DisplayName("when using ownerOf") public Stream failToOwnerOf() { return zeroNegativeAndGreaterThanLong.stream() @@ -337,7 +337,7 @@ class HASFunctionsTests { @Account(name = "spender") static SpecAccount spender; - @HapiTest + @RepeatableHapiTest(NEEDS_VIRTUAL_TIME_FOR_FAST_EXECUTION) @DisplayName("when using hbarAllowance") public Stream failToApproveHbar() { return zeroNegativeAndGreaterThanLong.stream() @@ -346,7 +346,7 @@ public Stream failToApproveHbar() { .andAssert(txn -> txn.hasKnownStatus(testCase.status())))); } - @HapiTest + @RepeatableHapiTest(NEEDS_VIRTUAL_TIME_FOR_FAST_EXECUTION) @DisplayName("when using hbarApprove") public Stream failToHbarApprove() { return zeroNegativeAndGreaterThanLong.stream() @@ -360,7 +360,7 @@ public Stream failToHbarApprove() { @DisplayName("fail to call Exchange Rate System contract functions") class ExchangeRateSystemContractTests { - @HapiTest + @RepeatableHapiTest(NEEDS_VIRTUAL_TIME_FOR_FAST_EXECUTION) @DisplayName("when converting tinycents to tinybars") public Stream convertTinycentsToTinybars() { return zeroNegativeAndGreaterThanLong.stream() @@ -369,7 +369,7 @@ public Stream convertTinycentsToTinybars() { .andAssert(txn -> txn.hasKnownStatus(testCase.status())))); } - @HapiTest + @RepeatableHapiTest(NEEDS_VIRTUAL_TIME_FOR_FAST_EXECUTION) @DisplayName("when converting tinybars to tinycents") public Stream convertTinybarsToTinycents() { return zeroNegativeAndGreaterThanLong.stream() @@ -433,7 +433,7 @@ public Stream failToUseCreateFungibleTokenWithCustomFeesV3Fractiona .andAssert(txn -> txn.hasKnownStatus(CONTRACT_REVERT_EXECUTED))); } - @HapiTest + @RepeatableHapiTest(NEEDS_VIRTUAL_TIME_FOR_FAST_EXECUTION) @DisplayName("when using createFungibleTokenWithCustomFeesV3 with fractionalFee where denominator is < 0") public Stream failToUseCreateFungibleTokenWithCustomFeesV3FractionalFeeNegativeDenominator() { final long nominator = 1; @@ -445,7 +445,7 @@ public Stream failToUseCreateFungibleTokenWithCustomFeesV3Fractiona .andAssert(txn -> txn.hasKnownStatus(CONTRACT_REVERT_EXECUTED)))); } - @HapiTest + @RepeatableHapiTest(NEEDS_VIRTUAL_TIME_FOR_FAST_EXECUTION) @DisplayName("when using createNonFungibleTokenWithCustomFeesV3 with fractionalFee where denominator is bad") public Stream failToUseCreateNonFungibleTokenWithCustomRoyaltyFeesV3WithBadDenominator() { return Stream.of(-1L, 0L) @@ -499,7 +499,7 @@ public Stream failToUseCreateFungible() { .andAssert(txn -> txn.logged().hasKnownStatus(CONTRACT_REVERT_EXECUTED))); } - @HapiTest + @RepeatableHapiTest(NEEDS_VIRTUAL_TIME_FOR_FAST_EXECUTION) @DisplayName("when using createFungibleTokenV2 with negative initial supply") public Stream failToUseCreateFungibleTokenV2() { return hapiTest(numericContractComplex @@ -561,7 +561,7 @@ public Stream failToUseCreateNonFungibleTokenV3WithNegativeExpiry() .andAssert(txn -> txn.hasKnownStatus(CONTRACT_REVERT_EXECUTED))); } - @HapiTest + @RepeatableHapiTest(NEEDS_VIRTUAL_TIME_FOR_FAST_EXECUTION) @DisplayName("when using updateTokenInfoV2 for fungible token with new maxSupply") public Stream failToUpdateTokenInfoV2FungibleMaxSupply() { // maxSupply cannot be updated using updateTokenInfo. @@ -574,7 +574,7 @@ public Stream failToUpdateTokenInfoV2FungibleMaxSupply() { fungibleToken.getInfo().andAssert(info -> info.hasMaxSupply(1200)))); } - @HapiTest + @RepeatableHapiTest(NEEDS_VIRTUAL_TIME_FOR_FAST_EXECUTION) @DisplayName("when using updateTokenInfoV3 for both fungible and nonFungible token") public Stream failToUpdateTokenInfoV3FungibleAndNft() { return Stream.of(fungibleToken, nft) @@ -583,14 +583,14 @@ public Stream failToUpdateTokenInfoV3FungibleAndNft() { .andAssert(txn -> txn.hasKnownStatus(CONTRACT_REVERT_EXECUTED)))); } - @HapiTest + @RepeatableHapiTest(NEEDS_VIRTUAL_TIME_FOR_FAST_EXECUTION) @DisplayName("when using updateNFTsMetadata for specific NFT from NFT collection with invalid serial number") public Stream failToUpdateNFTsMetadata() { return Stream.of(new long[] {Long.MAX_VALUE}, new long[] {0}, new long[] {-1, 1}, new long[] {-1}) .flatMap(invalidSerialNumbers -> hapiTest(numericContract .call("updateNFTsMetadata", nft, invalidSerialNumbers, "tiger".getBytes()) .gas(1_000_000L) - .andAssert(txn -> txn.hasKnownStatuses(CONTRACT_REVERT_EXECUTED, INVALID_NFT_ID)))); + .andAssert(txn -> txn.hasKnownStatus(CONTRACT_REVERT_EXECUTED)))); } @HapiTest @@ -599,7 +599,7 @@ public Stream failToUpdateNFTsMetadataWithEmptySerialNumbers() { return hapiTest(numericContract .call("updateNFTsMetadata", nft, new long[] {}, "zebra".getBytes()) .gas(1_000_000L) - .andAssert(txn -> txn.hasKnownStatuses(CONTRACT_REVERT_EXECUTED, MISSING_SERIAL_NUMBERS))); + .andAssert(txn -> txn.hasKnownStatus(CONTRACT_REVERT_EXECUTED))); } } @@ -660,7 +660,7 @@ public Stream failToUseTransferToken() { .andAssert(txn -> txn.hasKnownStatus(CONTRACT_REVERT_EXECUTED))); } - @HapiTest + @RepeatableHapiTest(NEEDS_VIRTUAL_TIME_FOR_FAST_EXECUTION) @DisplayName("when using transferTokenERC") public Stream failToUseTransferTokenERC() { return zeroNegativeAndGreaterThanLong.stream() @@ -689,7 +689,7 @@ public Stream failToUseTransferFrom() { .andAssert(txn -> txn.hasKnownStatus(CONTRACT_REVERT_EXECUTED))); } - @HapiTest + @RepeatableHapiTest(NEEDS_VIRTUAL_TIME_FOR_FAST_EXECUTION) @DisplayName("when using transferFromERC") public Stream failToUseTransferFromERC() { return Stream.of(NEGATIVE_ONE_BIG_INT, MAX_LONG_PLUS_1_BIG_INT) @@ -699,7 +699,7 @@ public Stream failToUseTransferFromERC() { .andAssert(txn -> txn.hasKnownStatus(CONTRACT_REVERT_EXECUTED)))); } - @HapiTest + @RepeatableHapiTest(NEEDS_VIRTUAL_TIME_FOR_FAST_EXECUTION) @DisplayName("when using transferFromNFT") public Stream failToUseTransferNFTFrom() { return zeroNegativeAndGreaterThanLong.stream() diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/token/TokenMetadataTest.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/token/TokenMetadataTest.java index e71b90644e2..1188ecd8aab 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/token/TokenMetadataTest.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/token/TokenMetadataTest.java @@ -1,6 +1,7 @@ // SPDX-License-Identifier: Apache-2.0 package com.hedera.services.bdd.suites.contract.precompile.token; +import static com.hedera.services.bdd.junit.RepeatableReason.NEEDS_VIRTUAL_TIME_FOR_FAST_EXECUTION; import static com.hedera.services.bdd.junit.TestTags.SMART_CONTRACT; import static com.hedera.services.bdd.spec.HapiSpec.hapiTest; import static com.hedera.services.bdd.spec.assertions.ContractFnResultAsserts.resultWith; @@ -28,6 +29,7 @@ import com.hedera.node.app.hapi.utils.contracts.ParsingConstants.FunctionType; import com.hedera.services.bdd.junit.HapiTest; import com.hedera.services.bdd.junit.HapiTestLifecycle; +import com.hedera.services.bdd.junit.RepeatableHapiTest; import com.hedera.services.bdd.junit.support.TestLifecycle; import com.hedera.services.bdd.spec.HapiSpec; import com.hedera.services.bdd.spec.dsl.annotations.Account; @@ -51,7 +53,6 @@ import java.util.concurrent.atomic.AtomicReference; import java.util.stream.Stream; import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.DynamicTest; import org.junit.jupiter.api.Tag; @@ -92,8 +93,7 @@ static void beforeAll(final TestLifecycle testLifecycle) { fungibleToken.authorizeContracts(contractTarget)); } - @Disabled - @HapiTest + @RepeatableHapiTest(NEEDS_VIRTUAL_TIME_FOR_FAST_EXECUTION) public Stream testUpdateMetadata() { return Stream.of(nft, fungibleToken) .flatMap(token -> hapiTest( @@ -104,8 +104,6 @@ public Stream testUpdateMetadata() { token.getInfo().andAssert(info -> info.hasMetadata("randomMetaNew777")))); } - // Disabled until update keys is implemented - @Disabled @HapiTest public Stream testUpdateTokenKeys() { return hapiTest(contractTarget diff --git a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/token/UpdateTokenMetadataTest.java b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/token/UpdateTokenMetadataTest.java index 8b5f2dbb13b..124d91d85e1 100644 --- a/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/token/UpdateTokenMetadataTest.java +++ b/hedera-node/test-clients/src/main/java/com/hedera/services/bdd/suites/contract/precompile/token/UpdateTokenMetadataTest.java @@ -3,6 +3,7 @@ import static com.hedera.services.bdd.junit.TestTags.SMART_CONTRACT; import static com.hedera.services.bdd.spec.HapiSpec.hapiTest; +import static com.hedera.services.bdd.spec.dsl.entities.SpecContract.VARIANT_16C; import static com.hedera.services.bdd.spec.dsl.entities.SpecTokenKey.ADMIN_KEY; import static com.hedera.services.bdd.spec.dsl.entities.SpecTokenKey.METADATA_KEY; import static com.hedera.services.bdd.spec.dsl.entities.SpecTokenKey.PAUSE_KEY; @@ -38,7 +39,7 @@ @HapiTestLifecycle public class UpdateTokenMetadataTest { - @Contract(contract = "UpdateTokenMetadata", creationGas = 4_000_000L) + @Contract(contract = "UpdateTokenMetadata", creationGas = 4_000_000L, variant = VARIANT_16C) static SpecContract updateTokenMetadata; @NonFungibleToken( diff --git a/hedera-node/test-clients/src/main/resources/contract/contracts/UpdateTokenMetadata/UpdateTokenMetadata.bin b/hedera-node/test-clients/src/main/resources/contract/contracts/UpdateTokenMetadata/UpdateTokenMetadata.bin deleted file mode 100644 index 14ab25d1499..00000000000 --- a/hedera-node/test-clients/src/main/resources/contract/contracts/UpdateTokenMetadata/UpdateTokenMetadata.bin +++ /dev/null @@ -1 +0,0 @@ -608060405234801561000f575f80fd5b50610e4a8061001d5f395ff3fe608060405234801561000f575f80fd5b506004361061004a575f3560e01c80631262ec561461004e57806315dacbea1461006a578063618dc65e1461009a5780639b23d3d9146100cb575b5f80fd5b61006860048036038101906100639190610893565b6100fb565b005b610084600480360381019061007f919061094e565b610158565b60405161009191906109c1565b60405180910390f35b6100b460048036038101906100af91906109da565b610270565b6040516100c2929190610ac6565b60405180910390f35b6100e560048036038101906100e0919061094e565b6103c5565b6040516100f291906109c1565b60405180910390f35b5f6101078484846104dd565b9050601660030b8160070b14610152576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161014990610b74565b60405180910390fd5b50505050565b5f805f61016773ffffffffffffffffffffffffffffffffffffffff166315dacbea60e01b888888886040516024016101939493929190610bb0565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506040516101fd9190610c2d565b5f604051808303815f865af19150503d805f8114610236576040519150601f19603f3d011682016040523d82523d5f602084013e61023b565b606091505b50915091508161024c576015610261565b808060200190518101906102609190610c79565b5b60030b92505050949350505050565b5f60605f8061016773ffffffffffffffffffffffffffffffffffffffff1663618dc65e60e01b87876040516024016102a9929190610ca4565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506040516103139190610c2d565b5f604051808303815f865af19150503d805f811461034c576040519150601f19603f3d011682016040523d82523d5f602084013e610351565b606091505b50915091507f4af4780e06fe8cb9df64b0794fa6f01399af979175bb988e35e0e57e594567bc8282604051610387929190610cec565b60405180910390a1816103aa57601560405180602001604052805f8152506103ae565b6016815b8160030b9150809450819550505050509250929050565b5f805f61016773ffffffffffffffffffffffffffffffffffffffff16639b23d3d960e01b888888886040516024016104009493929190610bb0565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505060405161046a9190610c2d565b5f604051808303815f865af19150503d805f81146104a3576040519150601f19603f3d011682016040523d82523d5f602084013e6104a8565b606091505b5091509150816104b95760156104ce565b808060200190518101906104cd9190610c79565b5b60030b92505050949350505050565b5f805f61016773ffffffffffffffffffffffffffffffffffffffff16630fcaca1f60e01b87878760405160240161051693929190610dd1565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506040516105809190610c2d565b5f604051808303815f865af19150503d805f81146105b9576040519150601f19603f3d011682016040523d82523d5f602084013e6105be565b606091505b5091509150816105cf5760156105e4565b808060200190518101906105e39190610c79565b5b60030b925050509392505050565b5f604051905090565b5f80fd5b5f80fd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f61062c82610603565b9050919050565b61063c81610622565b8114610646575f80fd5b50565b5f8135905061065781610633565b92915050565b5f80fd5b5f601f19601f8301169050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b6106a782610661565b810181811067ffffffffffffffff821117156106c6576106c5610671565b5b80604052505050565b5f6106d86105f2565b90506106e4828261069e565b919050565b5f67ffffffffffffffff82111561070357610702610671565b5b602082029050602081019050919050565b5f80fd5b5f8160070b9050919050565b61072d81610718565b8114610737575f80fd5b50565b5f8135905061074881610724565b92915050565b5f61076061075b846106e9565b6106cf565b9050808382526020820190506020840283018581111561078357610782610714565b5b835b818110156107ac5780610798888261073a565b845260208401935050602081019050610785565b5050509392505050565b5f82601f8301126107ca576107c961065d565b5b81356107da84826020860161074e565b91505092915050565b5f80fd5b5f67ffffffffffffffff82111561080157610800610671565b5b61080a82610661565b9050602081019050919050565b828183375f83830152505050565b5f610837610832846107e7565b6106cf565b905082815260208101848484011115610853576108526107e3565b5b61085e848285610817565b509392505050565b5f82601f83011261087a5761087961065d565b5b813561088a848260208601610825565b91505092915050565b5f805f606084860312156108aa576108a96105fb565b5b5f6108b786828701610649565b935050602084013567ffffffffffffffff8111156108d8576108d76105ff565b5b6108e4868287016107b6565b925050604084013567ffffffffffffffff811115610905576109046105ff565b5b61091186828701610866565b9150509250925092565b5f819050919050565b61092d8161091b565b8114610937575f80fd5b50565b5f8135905061094881610924565b92915050565b5f805f8060808587031215610966576109656105fb565b5b5f61097387828801610649565b945050602061098487828801610649565b935050604061099587828801610649565b92505060606109a68782880161093a565b91505092959194509250565b6109bb81610718565b82525050565b5f6020820190506109d45f8301846109b2565b92915050565b5f80604083850312156109f0576109ef6105fb565b5b5f6109fd85828601610649565b925050602083013567ffffffffffffffff811115610a1e57610a1d6105ff565b5b610a2a85828601610866565b9150509250929050565b5f819050919050565b610a4681610a34565b82525050565b5f81519050919050565b5f82825260208201905092915050565b5f5b83811015610a83578082015181840152602081019050610a68565b5f8484015250505050565b5f610a9882610a4c565b610aa28185610a56565b9350610ab2818560208601610a66565b610abb81610661565b840191505092915050565b5f604082019050610ad95f830185610a3d565b8181036020830152610aeb8184610a8e565b90509392505050565b5f82825260208201905092915050565b7f4661696c656420746f20757064617465206d6574616461746120666f72204e465f8201527f5473000000000000000000000000000000000000000000000000000000000000602082015250565b5f610b5e602283610af4565b9150610b6982610b04565b604082019050919050565b5f6020820190508181035f830152610b8b81610b52565b9050919050565b610b9b81610622565b82525050565b610baa8161091b565b82525050565b5f608082019050610bc35f830187610b92565b610bd06020830186610b92565b610bdd6040830185610b92565b610bea6060830184610ba1565b95945050505050565b5f81905092915050565b5f610c0782610a4c565b610c118185610bf3565b9350610c21818560208601610a66565b80840191505092915050565b5f610c388284610bfd565b915081905092915050565b5f8160030b9050919050565b610c5881610c43565b8114610c62575f80fd5b50565b5f81519050610c7381610c4f565b92915050565b5f60208284031215610c8e57610c8d6105fb565b5b5f610c9b84828501610c65565b91505092915050565b5f604082019050610cb75f830185610b92565b8181036020830152610cc98184610a8e565b90509392505050565b5f8115159050919050565b610ce681610cd2565b82525050565b5f604082019050610cff5f830185610cdd565b8181036020830152610d118184610a8e565b90509392505050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b610d4c81610718565b82525050565b5f610d5d8383610d43565b60208301905092915050565b5f602082019050919050565b5f610d7f82610d1a565b610d898185610d24565b9350610d9483610d34565b805f5b83811015610dc4578151610dab8882610d52565b9750610db683610d69565b925050600181019050610d97565b5085935050505092915050565b5f606082019050610de45f830186610b92565b8181036020830152610df68185610d75565b90508181036040830152610e0a8184610a8e565b905094935050505056fea2646970667358221220378cc85004d47606644b5671cbfe73da96a3f3563cc3fb44b3819bd6b60153fe64736f6c63430008180033 \ No newline at end of file diff --git a/hedera-node/test-clients/src/main/resources/contract/contracts_16c/HederaTokenService/HederaTokenService.sol b/hedera-node/test-clients/src/main/resources/contract/contracts_16c/HederaTokenService/HederaTokenService.sol index 01eb8fabe1b..484823a119e 100644 --- a/hedera-node/test-clients/src/main/resources/contract/contracts_16c/HederaTokenService/HederaTokenService.sol +++ b/hedera-node/test-clients/src/main/resources/contract/contracts_16c/HederaTokenService/HederaTokenService.sol @@ -2,7 +2,7 @@ pragma solidity >=0.5.0 <0.9.0; pragma experimental ABIEncoderV2; -import "../HederaResponseCodes.sol"; +import "./HederaResponseCodes.sol"; import "./IHederaTokenService.sol"; abstract contract HederaTokenService { @@ -746,4 +746,11 @@ abstract contract HederaTokenService { ); (responseCode) = success ? abi.decode(result, (int32)) : HederaResponseCodes.UNKNOWN; } + + function updateNFTsMetadata(address nftToken, int64[] memory serialNumbers, bytes memory metadata) external returns (int64 responseCode) { + (bool success, bytes memory result) = precompileAddress.call( + abi.encodeWithSelector(IHederaTokenService.updateNFTsMetadata.selector, nftToken, serialNumbers, metadata) + ); + (responseCode) = success ? abi.decode(result, (int32)) : HederaResponseCodes.UNKNOWN; + } } diff --git a/hedera-node/test-clients/src/main/resources/contract/contracts_16c/HederaTokenService/IHederaTokenService.sol b/hedera-node/test-clients/src/main/resources/contract/contracts_16c/HederaTokenService/IHederaTokenService.sol index b0db8f274c6..945402183d7 100644 --- a/hedera-node/test-clients/src/main/resources/contract/contracts_16c/HederaTokenService/IHederaTokenService.sol +++ b/hedera-node/test-clients/src/main/resources/contract/contracts_16c/HederaTokenService/IHederaTokenService.sol @@ -869,4 +869,7 @@ interface IHederaTokenService { /// @param nftIDs Array of NFT IDs to reject /// @return responseCode The response code for the status of the request. SUCCESS is 22. function rejectTokens(address rejectingAddress, address[] memory ftAddresses, NftID[] memory nftIDs) external returns (int64 responseCode); + + + function updateNFTsMetadata(address nftToken, int64[] memory serialNumbers, bytes memory metadata) external returns (int64 responseCode); } \ No newline at end of file diff --git a/hedera-node/test-clients/src/main/resources/contract/contracts_16c/NumericContract16c/NumericContract16c.bin b/hedera-node/test-clients/src/main/resources/contract/contracts_16c/NumericContract16c/NumericContract16c.bin new file mode 100644 index 00000000000..6ff9ccab1aa --- /dev/null +++ b/hedera-node/test-clients/src/main/resources/contract/contracts_16c/NumericContract16c/NumericContract16c.bin @@ -0,0 +1 @@ +608060405234801561001057600080fd5b5061079d806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80630e969a051461003b5780630fcaca1f14610059575b600080fd5b610043610075565b60405161005091906101cb565b60405180910390f35b610073600480360381019061006e919061049f565b61007a565b005b601681565b60008061016c73ffffffffffffffffffffffffffffffffffffffff168585856040516024016100ab93929190610676565b6040516020818303038152906040527f0fcaca1f000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505060405161013591906106f7565b6000604051808303816000865af19150503d8060008114610172576040519150601f19603f3d011682016040523d82523d6000602084013e610177565b606091505b5091509150600081806020019051810190610192919061073a565b9050601660030b8160030b146101a757600080fd5b505050505050565b60008160030b9050919050565b6101c5816101af565b82525050565b60006020820190506101e060008301846101bc565b92915050565b6000604051905090565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000610225826101fa565b9050919050565b6102358161021a565b811461024057600080fd5b50565b6000813590506102528161022c565b92915050565b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6102a68261025d565b810181811067ffffffffffffffff821117156102c5576102c461026e565b5b80604052505050565b60006102d86101e6565b90506102e4828261029d565b919050565b600067ffffffffffffffff8211156103045761030361026e565b5b602082029050602081019050919050565b600080fd5b60008160070b9050919050565b6103308161031a565b811461033b57600080fd5b50565b60008135905061034d81610327565b92915050565b6000610366610361846102e9565b6102ce565b9050808382526020820190506020840283018581111561038957610388610315565b5b835b818110156103b2578061039e888261033e565b84526020840193505060208101905061038b565b5050509392505050565b600082601f8301126103d1576103d0610258565b5b81356103e1848260208601610353565b91505092915050565b600080fd5b600067ffffffffffffffff82111561040a5761040961026e565b5b6104138261025d565b9050602081019050919050565b82818337600083830152505050565b600061044261043d846103ef565b6102ce565b90508281526020810184848401111561045e5761045d6103ea565b5b610469848285610420565b509392505050565b600082601f83011261048657610485610258565b5b813561049684826020860161042f565b91505092915050565b6000806000606084860312156104b8576104b76101f0565b5b60006104c686828701610243565b935050602084013567ffffffffffffffff8111156104e7576104e66101f5565b5b6104f3868287016103bc565b925050604084013567ffffffffffffffff811115610514576105136101f5565b5b61052086828701610471565b9150509250925092565b6105338161021a565b82525050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b61056e8161031a565b82525050565b60006105808383610565565b60208301905092915050565b6000602082019050919050565b60006105a482610539565b6105ae8185610544565b93506105b983610555565b8060005b838110156105ea5781516105d18882610574565b97506105dc8361058c565b9250506001810190506105bd565b5085935050505092915050565b600081519050919050565b600082825260208201905092915050565b60005b83811015610631578082015181840152602081019050610616565b60008484015250505050565b6000610648826105f7565b6106528185610602565b9350610662818560208601610613565b61066b8161025d565b840191505092915050565b600060608201905061068b600083018661052a565b818103602083015261069d8185610599565b905081810360408301526106b1818461063d565b9050949350505050565b600081905092915050565b60006106d1826105f7565b6106db81856106bb565b93506106eb818560208601610613565b80840191505092915050565b600061070382846106c6565b915081905092915050565b610717816101af565b811461072257600080fd5b50565b6000815190506107348161070e565b92915050565b6000602082840312156107505761074f6101f0565b5b600061075e84828501610725565b9150509291505056fea26469706673582212208bd06e578ed3364f6ad15b6ca54aa3b7964fc2a6c4e7c3d9cc5ab33622cdd28564736f6c63430008120033 \ No newline at end of file diff --git a/hedera-node/test-clients/src/main/resources/contract/contracts_16c/NumericContract16c/NumericContract16c.json b/hedera-node/test-clients/src/main/resources/contract/contracts_16c/NumericContract16c/NumericContract16c.json new file mode 100644 index 00000000000..75aa85acb90 --- /dev/null +++ b/hedera-node/test-clients/src/main/resources/contract/contracts_16c/NumericContract16c/NumericContract16c.json @@ -0,0 +1,38 @@ +[ + { + "inputs": [], + "name": "SUCCESS_CODE", + "outputs": [ + { + "internalType": "int32", + "name": "", + "type": "int32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "nftToken", + "type": "address" + }, + { + "internalType": "int64[]", + "name": "serialNumbers", + "type": "int64[]" + }, + { + "internalType": "bytes", + "name": "_newMetadata", + "type": "bytes" + } + ], + "name": "updateNFTsMetadata", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] \ No newline at end of file diff --git a/hedera-node/test-clients/src/main/resources/contract/contracts_16c/NumericContract16c/NumericContract16c.sol b/hedera-node/test-clients/src/main/resources/contract/contracts_16c/NumericContract16c/NumericContract16c.sol new file mode 100644 index 00000000000..fbd0a47f649 --- /dev/null +++ b/hedera-node/test-clients/src/main/resources/contract/contracts_16c/NumericContract16c/NumericContract16c.sol @@ -0,0 +1,20 @@ +// SPDX-Licence-Identifier: Apache02.0 +pragma solidity >=0.5.9 < 0.9.0; +pragma experimental ABIEncoderV2; + +contract NumericContract16c { + + int32 public constant SUCCESS_CODE = 22; + + /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/ + /* Non-static Simple HTS functions */ + /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/ + function updateNFTsMetadata(address nftToken, int64[] memory serialNumbers, bytes memory _newMetadata) public { + (bool success, bytes memory result) = address(0x16c) + .call(abi.encodeWithSignature("updateNFTsMetadata(address,int64[],bytes)", nftToken, serialNumbers, _newMetadata)); + + int32 responseCode = abi.decode(result, (int32)); + require(responseCode == SUCCESS_CODE); + } + +} \ No newline at end of file diff --git a/hedera-node/test-clients/src/main/resources/contract/contracts_16c/UpdateTokenMetadata/UpdateTokenMetadata.bin b/hedera-node/test-clients/src/main/resources/contract/contracts_16c/UpdateTokenMetadata/UpdateTokenMetadata.bin new file mode 100644 index 00000000000..59239ece8e1 --- /dev/null +++ b/hedera-node/test-clients/src/main/resources/contract/contracts_16c/UpdateTokenMetadata/UpdateTokenMetadata.bin @@ -0,0 +1 @@ +6080604052348015600e575f80fd5b50610f1c8061001c5f395ff3fe608060405234801561000f575f80fd5b5060043610610055575f3560e01c80630fcaca1f146100595780631262ec561461008957806315dacbea146100a5578063618dc65e146100d55780639b23d3d914610106575b5f80fd5b610073600480360381019061006e9190610940565b610136565b60405161008091906109d7565b60405180910390f35b6100a3600480360381019061009e9190610940565b61024b565b005b6100bf60048036038101906100ba9190610a23565b61031a565b6040516100cc91906109d7565b60405180910390f35b6100ef60048036038101906100ea9190610a87565b610432565b6040516100fd929190610b59565b60405180910390f35b610120600480360381019061011b9190610a23565b610587565b60405161012d91906109d7565b60405180910390f35b5f805f61016c73ffffffffffffffffffffffffffffffffffffffff16630fcaca1f60e01b87878760405160240161016f93929190610c4d565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506040516101d99190610cca565b5f604051808303815f865af19150503d805f8114610212576040519150601f19603f3d011682016040523d82523d5f602084013e610217565b606091505b50915091508161022857601561023d565b8080602001905181019061023c9190610d16565b5b60030b925050509392505050565b5f3073ffffffffffffffffffffffffffffffffffffffff16630fcaca1f8585856040518463ffffffff1660e01b815260040161028993929190610c4d565b6020604051808303815f875af11580156102a5573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906102c99190610d55565b9050601660030b8160070b14610314576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161030b90610e00565b60405180910390fd5b50505050565b5f805f61016c73ffffffffffffffffffffffffffffffffffffffff166315dacbea60e01b888888886040516024016103559493929190610e2d565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506040516103bf9190610cca565b5f604051808303815f865af19150503d805f81146103f8576040519150601f19603f3d011682016040523d82523d5f602084013e6103fd565b606091505b50915091508161040e576015610423565b808060200190518101906104229190610d16565b5b60030b92505050949350505050565b5f60605f8061016c73ffffffffffffffffffffffffffffffffffffffff1663618dc65e60e01b878760405160240161046b929190610e70565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506040516104d59190610cca565b5f604051808303815f865af19150503d805f811461050e576040519150601f19603f3d011682016040523d82523d5f602084013e610513565b606091505b50915091507f4af4780e06fe8cb9df64b0794fa6f01399af979175bb988e35e0e57e594567bc8282604051610549929190610eb8565b60405180910390a18161056c57601560405180602001604052805f815250610570565b6016815b8160030b9150809450819550505050509250929050565b5f805f61016c73ffffffffffffffffffffffffffffffffffffffff16639b23d3d960e01b888888886040516024016105c29493929190610e2d565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505060405161062c9190610cca565b5f604051808303815f865af19150503d805f8114610665576040519150601f19603f3d011682016040523d82523d5f602084013e61066a565b606091505b50915091508161067b576015610690565b8080602001905181019061068f9190610d16565b5b60030b92505050949350505050565b5f604051905090565b5f80fd5b5f80fd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6106d9826106b0565b9050919050565b6106e9816106cf565b81146106f3575f80fd5b50565b5f81359050610704816106e0565b92915050565b5f80fd5b5f601f19601f8301169050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b6107548261070e565b810181811067ffffffffffffffff821117156107735761077261071e565b5b80604052505050565b5f61078561069f565b9050610791828261074b565b919050565b5f67ffffffffffffffff8211156107b0576107af61071e565b5b602082029050602081019050919050565b5f80fd5b5f8160070b9050919050565b6107da816107c5565b81146107e4575f80fd5b50565b5f813590506107f5816107d1565b92915050565b5f61080d61080884610796565b61077c565b905080838252602082019050602084028301858111156108305761082f6107c1565b5b835b81811015610859578061084588826107e7565b845260208401935050602081019050610832565b5050509392505050565b5f82601f8301126108775761087661070a565b5b81356108878482602086016107fb565b91505092915050565b5f80fd5b5f67ffffffffffffffff8211156108ae576108ad61071e565b5b6108b78261070e565b9050602081019050919050565b828183375f83830152505050565b5f6108e46108df84610894565b61077c565b905082815260208101848484011115610900576108ff610890565b5b61090b8482856108c4565b509392505050565b5f82601f8301126109275761092661070a565b5b81356109378482602086016108d2565b91505092915050565b5f805f60608486031215610957576109566106a8565b5b5f610964868287016106f6565b935050602084013567ffffffffffffffff811115610985576109846106ac565b5b61099186828701610863565b925050604084013567ffffffffffffffff8111156109b2576109b16106ac565b5b6109be86828701610913565b9150509250925092565b6109d1816107c5565b82525050565b5f6020820190506109ea5f8301846109c8565b92915050565b5f819050919050565b610a02816109f0565b8114610a0c575f80fd5b50565b5f81359050610a1d816109f9565b92915050565b5f805f8060808587031215610a3b57610a3a6106a8565b5b5f610a48878288016106f6565b9450506020610a59878288016106f6565b9350506040610a6a878288016106f6565b9250506060610a7b87828801610a0f565b91505092959194509250565b5f8060408385031215610a9d57610a9c6106a8565b5b5f610aaa858286016106f6565b925050602083013567ffffffffffffffff811115610acb57610aca6106ac565b5b610ad785828601610913565b9150509250929050565b5f819050919050565b610af381610ae1565b82525050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f610b2b82610af9565b610b358185610b03565b9350610b45818560208601610b13565b610b4e8161070e565b840191505092915050565b5f604082019050610b6c5f830185610aea565b8181036020830152610b7e8184610b21565b90509392505050565b610b90816106cf565b82525050565b5f81519050919050565b5f82825260208201905092915050565b5f819050602082019050919050565b610bc8816107c5565b82525050565b5f610bd98383610bbf565b60208301905092915050565b5f602082019050919050565b5f610bfb82610b96565b610c058185610ba0565b9350610c1083610bb0565b805f5b83811015610c40578151610c278882610bce565b9750610c3283610be5565b925050600181019050610c13565b5085935050505092915050565b5f606082019050610c605f830186610b87565b8181036020830152610c728185610bf1565b90508181036040830152610c868184610b21565b9050949350505050565b5f81905092915050565b5f610ca482610af9565b610cae8185610c90565b9350610cbe818560208601610b13565b80840191505092915050565b5f610cd58284610c9a565b915081905092915050565b5f8160030b9050919050565b610cf581610ce0565b8114610cff575f80fd5b50565b5f81519050610d1081610cec565b92915050565b5f60208284031215610d2b57610d2a6106a8565b5b5f610d3884828501610d02565b91505092915050565b5f81519050610d4f816107d1565b92915050565b5f60208284031215610d6a57610d696106a8565b5b5f610d7784828501610d41565b91505092915050565b5f82825260208201905092915050565b7f4661696c656420746f20757064617465206d6574616461746120666f72204e465f8201527f5473000000000000000000000000000000000000000000000000000000000000602082015250565b5f610dea602283610d80565b9150610df582610d90565b604082019050919050565b5f6020820190508181035f830152610e1781610dde565b9050919050565b610e27816109f0565b82525050565b5f608082019050610e405f830187610b87565b610e4d6020830186610b87565b610e5a6040830185610b87565b610e676060830184610e1e565b95945050505050565b5f604082019050610e835f830185610b87565b8181036020830152610e958184610b21565b90509392505050565b5f8115159050919050565b610eb281610e9e565b82525050565b5f604082019050610ecb5f830185610ea9565b8181036020830152610edd8184610b21565b9050939250505056fea26469706673582212209157f781a4d63754f73dec487d95446b0d80d3aefb7e1093ff3817426630a6c764736f6c634300081a0033 \ No newline at end of file diff --git a/hedera-node/test-clients/src/main/resources/contract/contracts/UpdateTokenMetadata/UpdateTokenMetadata.json b/hedera-node/test-clients/src/main/resources/contract/contracts_16c/UpdateTokenMetadata/UpdateTokenMetadata.json similarity index 83% rename from hedera-node/test-clients/src/main/resources/contract/contracts/UpdateTokenMetadata/UpdateTokenMetadata.json rename to hedera-node/test-clients/src/main/resources/contract/contracts_16c/UpdateTokenMetadata/UpdateTokenMetadata.json index 47aae423dc3..eac91eb5ed4 100644 --- a/hedera-node/test-clients/src/main/resources/contract/contracts/UpdateTokenMetadata/UpdateTokenMetadata.json +++ b/hedera-node/test-clients/src/main/resources/contract/contracts_16c/UpdateTokenMetadata/UpdateTokenMetadata.json @@ -142,5 +142,34 @@ ], "stateMutability": "nonpayable", "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "nftToken", + "type": "address" + }, + { + "internalType": "int64[]", + "name": "serialNumbers", + "type": "int64[]" + }, + { + "internalType": "bytes", + "name": "metadata", + "type": "bytes" + } + ], + "name": "updateNFTsMetadata", + "outputs": [ + { + "internalType": "int64", + "name": "responseCode", + "type": "int64" + } + ], + "stateMutability": "nonpayable", + "type": "function" } ] \ No newline at end of file diff --git a/hedera-node/test-clients/src/main/resources/contract/contracts/UpdateTokenMetadata/UpdateTokenMetadata.sol b/hedera-node/test-clients/src/main/resources/contract/contracts_16c/UpdateTokenMetadata/UpdateTokenMetadata.sol similarity index 77% rename from hedera-node/test-clients/src/main/resources/contract/contracts/UpdateTokenMetadata/UpdateTokenMetadata.sol rename to hedera-node/test-clients/src/main/resources/contract/contracts_16c/UpdateTokenMetadata/UpdateTokenMetadata.sol index c115f33eb19..b34ce692635 100644 --- a/hedera-node/test-clients/src/main/resources/contract/contracts/UpdateTokenMetadata/UpdateTokenMetadata.sol +++ b/hedera-node/test-clients/src/main/resources/contract/contracts_16c/UpdateTokenMetadata/UpdateTokenMetadata.sol @@ -1,6 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.24; - +pragma solidity >=0.5.0 <0.9.0; import {HederaTokenService} from "./HederaTokenService.sol"; import {HederaResponseCodes} from "./HederaResponseCodes.sol"; @@ -9,7 +8,7 @@ contract UpdateTokenMetadata is HederaTokenService { } function callUpdateNFTsMetadata(address nftToken, int64[] memory serialNumbers, bytes memory _newMetadata) public { - (int64 responseCode) = HederaTokenService.updateNFTsMetadata(nftToken, serialNumbers, _newMetadata); + (int64 responseCode) = this.updateNFTsMetadata(nftToken, serialNumbers, _newMetadata); require(responseCode == HederaResponseCodes.SUCCESS, "Failed to update metadata for NFTs"); } }