diff --git a/hapi-utils/src/main/java/com/hedera/services/contracts/ParsingConstants.java b/hapi-utils/src/main/java/com/hedera/services/contracts/ParsingConstants.java index 9a9582198977..7780c17f202e 100644 --- a/hapi-utils/src/main/java/com/hedera/services/contracts/ParsingConstants.java +++ b/hapi-utils/src/main/java/com/hedera/services/contracts/ParsingConstants.java @@ -41,10 +41,14 @@ private ParsingConstants() { // struct types public static final String EXPIRY = "(uint32,address,uint32)"; + public static final String EXPIRY_V2 = "(int32,address,int32)"; public static final String FIXED_FEE = "(uint32,address,bool,bool,address)"; + public static final String FIXED_FEE_V2 = "(int64,address,bool,bool,address)"; public static final String FRACTIONAL_FEE = "(uint32,uint32,uint32,uint32,bool,address)"; + public static final String FRACTIONAL_FEE_V2 = "(int64,int64,int64,int64,bool,address)"; public static final String KEY_VALUE = "(bool,address,bytes,bytes,address)"; public static final String ROYALTY_FEE = "(uint32,uint32,uint32,address,bool,address)"; + public static final String ROYALTY_FEE_V2 = "(int64,int64,int64,address,bool,address)"; public static final String TOKEN_KEY = "(uint256," + KEY_VALUE + ")"; public static final String HEDERA_TOKEN = diff --git a/hedera-node/hedera-mono-service/src/main/java/com/hedera/services/store/contracts/precompile/AbiConstants.java b/hedera-node/hedera-mono-service/src/main/java/com/hedera/services/store/contracts/precompile/AbiConstants.java index 69a4f14fd4bc..b8064c2a9a2d 100644 --- a/hedera-node/hedera-mono-service/src/main/java/com/hedera/services/store/contracts/precompile/AbiConstants.java +++ b/hedera-node/hedera-mono-service/src/main/java/com/hedera/services/store/contracts/precompile/AbiConstants.java @@ -40,8 +40,12 @@ private AbiConstants() { public static final int ABI_ID_TRANSFER_NFT = 0x5cfc9011; // mintToken(address token, uint64 amount, bytes[] memory metadata) public static final int ABI_ID_MINT_TOKEN = 0x278e0b88; + // mintToken(address token, int64 amount, bytes[] memory metadata) + public static final int ABI_ID_MINT_TOKEN_V2 = 0xe0f4059a; // burnToken(address token, uint64 amount, int64[] memory serialNumbers) public static final int ABI_ID_BURN_TOKEN = 0xacb9cff9; + // burnToken(address token, int64 amount, int64[] memory serialNumbers) + public static final int ABI_ID_BURN_TOKEN_V2 = 0xd6910d06; // deleteToken(address token) public static final int ABI_ID_DELETE_TOKEN = 0xf069f712; // associateTokens(address account, address[] memory tokens) @@ -108,6 +112,8 @@ private AbiConstants() { public static final int ABI_ID_ERC_TOKEN_URI_NFT = 0xc87b56dd; // wipeTokenAccount(address, address, uint32) public static final int ABI_WIPE_TOKEN_ACCOUNT_FUNGIBLE = 0x9790686d; + // wipeTokenAccount(address, address, int32) + public static final int ABI_WIPE_TOKEN_ACCOUNT_FUNGIBLE_V2 = 0x2d279ec6; // wipeTokenAccountNFT(address, address, int64[]) public static final int ABI_WIPE_TOKEN_ACCOUNT_NFT = 0xf7f38e26; // isFrozen(address token, address account) @@ -118,8 +124,10 @@ private AbiConstants() { public static final int ABI_ID_UNFREEZE = 0x52f91387; // updateTokenInfo(address token, HederaToken tokenInfo) public static final int ABI_ID_UPDATE_TOKEN_INFO = 0x2cccc36f; - // updateTokenKeys(address token, TokenKey []) + // updateTokenInfo(address token, HederaToken tokenInfo) public static final int ABI_ID_UPDATE_TOKEN_INFO_V2 = 0x18370d34; + // updateTokenInfo(address token, HederaToken tokenInfo) + public static final int ABI_ID_UPDATE_TOKEN_INFO_V3 = 0x1d6d6529; // updateTokenKeys(address token, TokenKey []) public static final int ABI_ID_UPDATE_TOKEN_KEYS = 0x6fc3cbaf; // getTokenKey(address token, uint tokenType) @@ -141,6 +149,8 @@ private AbiConstants() { public static final int ABI_ID_CREATE_FUNGIBLE_TOKEN = 0x7812a04b; // createFungibleToken(HederaToken memory token, uint64 initialTotalSupply, uint32 decimals) public static final int ABI_ID_CREATE_FUNGIBLE_TOKEN_V2 = 0xc23baeb6; + // createFungibleToken(HederaToken memory token, int64 initialTotalSupply, int32 decimals) + public static final int ABI_ID_CREATE_FUNGIBLE_TOKEN_V3 = 0x2c1e9423; // createFungibleTokenWithCustomFees( // HederaToken memory token, // uint initialTotalSupply, @@ -155,11 +165,20 @@ private AbiConstants() { // FixedFee[] memory fixedFees, // FractionalFee[] memory fractionalFees) public static final int ABI_ID_CREATE_FUNGIBLE_TOKEN_WITH_FEES_V2 = 0xb937581a; + // createFungibleTokenWithCustomFees( + // HederaToken memory token, + // int64 initialTotalSupply, + // int32 decimals, + // FixedFee[] memory fixedFees, + // FractionalFee[] memory fractionalFees) + public static final int ABI_ID_CREATE_FUNGIBLE_TOKEN_WITH_FEES_V3 = 0x6daa94d8; // createNonFungibleToken(HederaToken memory token) public static final int ABI_ID_CREATE_NON_FUNGIBLE_TOKEN = 0x9dc711e0; // createNonFungibleToken(HederaToken memory token) // HederaToken field maxSupply updated to int64 public static final int ABI_ID_CREATE_NON_FUNGIBLE_TOKEN_V2 = 0x9c89bb35; + // createNonFungibleToken(HederaToken memory token) + public static final int ABI_ID_CREATE_NON_FUNGIBLE_TOKEN_V3 = 0xa4bcba95; // createNonFungibleTokenWithCustomFees( // HederaToken memory token, // FixedFee[] memory fixedFees, @@ -171,6 +190,11 @@ private AbiConstants() { // RoyaltyFee[] memory royaltyFees) // HederaToken field maxSupply updated to int64 public static final int ABI_ID_CREATE_NON_FUNGIBLE_TOKEN_WITH_FEES_V2 = 0x45733969; + // createNonFungibleTokenWithCustomFees( + // HederaToken memory token, + // FixedFee[] memory fixedFees, + // RoyaltyFee[] memory royaltyFees) + public static final int ABI_ID_CREATE_NON_FUNGIBLE_TOKEN_WITH_FEES_V3 = 0xaddb7110; // **** HIP-514 function selectors **** // getFungibleTokenInfo(address token) @@ -199,4 +223,6 @@ private AbiConstants() { public static final int ABI_ID_GET_TOKEN_EXPIRY_INFO = 0xd614cdb8; // updateTokenExpiryInfo(address token, Expiry expiryInfoStruct) public static final int ABI_ID_UPDATE_TOKEN_EXPIRY_INFO = 0x593d6e82; + // updateTokenExpiryInfo(address token, Expiry expiryInfoStruct) + public static final int ABI_ID_UPDATE_TOKEN_EXPIRY_INFO_V2 = 0x4a089f09; } diff --git a/hedera-node/hedera-mono-service/src/main/java/com/hedera/services/store/contracts/precompile/HTSPrecompiledContract.java b/hedera-node/hedera-mono-service/src/main/java/com/hedera/services/store/contracts/precompile/HTSPrecompiledContract.java index 2df69c63222c..f0a4912c9564 100644 --- a/hedera-node/hedera-mono-service/src/main/java/com/hedera/services/store/contracts/precompile/HTSPrecompiledContract.java +++ b/hedera-node/hedera-mono-service/src/main/java/com/hedera/services/store/contracts/precompile/HTSPrecompiledContract.java @@ -293,7 +293,8 @@ void prepareComputation(final Bytes input, final UnaryOperator aliasReso functionId, senderAddress, impliedTransfersMarshal)); - case AbiConstants.ABI_ID_MINT_TOKEN -> new MintPrecompile( + case AbiConstants.ABI_ID_MINT_TOKEN, + AbiConstants.ABI_ID_MINT_TOKEN_V2-> new MintPrecompile( ledgers, encoder, updater.aliases(), @@ -302,8 +303,10 @@ void prepareComputation(final Bytes input, final UnaryOperator aliasReso sideEffectsTracker, syntheticTxnFactory, infrastructureFactory, - precompilePricingUtils); - case AbiConstants.ABI_ID_BURN_TOKEN -> new BurnPrecompile( + precompilePricingUtils, + functionId); + case AbiConstants.ABI_ID_BURN_TOKEN, + AbiConstants.ABI_ID_BURN_TOKEN_V2 -> new BurnPrecompile( ledgers, encoder, updater.aliases(), @@ -311,7 +314,8 @@ void prepareComputation(final Bytes input, final UnaryOperator aliasReso sideEffectsTracker, syntheticTxnFactory, infrastructureFactory, - precompilePricingUtils); + precompilePricingUtils, + functionId); case AbiConstants.ABI_ID_ASSOCIATE_TOKENS -> new MultiAssociatePrecompile( ledgers, updater.aliases(), @@ -453,14 +457,16 @@ void prepareComputation(final Bytes input, final UnaryOperator aliasReso syntheticTxnFactory, infrastructureFactory, precompilePricingUtils); - case AbiConstants.ABI_WIPE_TOKEN_ACCOUNT_FUNGIBLE -> new WipeFungiblePrecompile( + case AbiConstants.ABI_WIPE_TOKEN_ACCOUNT_FUNGIBLE, + AbiConstants.ABI_WIPE_TOKEN_ACCOUNT_FUNGIBLE_V2-> new WipeFungiblePrecompile( ledgers, updater.aliases(), sigsVerifier, sideEffectsTracker, syntheticTxnFactory, infrastructureFactory, - precompilePricingUtils); + precompilePricingUtils, + functionId); case AbiConstants.ABI_WIPE_TOKEN_ACCOUNT_NFT -> new WipeNonFungiblePrecompile( ledgers, updater.aliases(), @@ -498,7 +504,8 @@ void prepareComputation(final Bytes input, final UnaryOperator aliasReso infrastructureFactory, precompilePricingUtils); case AbiConstants.ABI_ID_UPDATE_TOKEN_INFO, - AbiConstants.ABI_ID_UPDATE_TOKEN_INFO_V2 -> new TokenUpdatePrecompile( + AbiConstants.ABI_ID_UPDATE_TOKEN_INFO_V2, + AbiConstants.ABI_ID_UPDATE_TOKEN_INFO_V3-> new TokenUpdatePrecompile( ledgers, updater.aliases(), sigsVerifier, @@ -675,8 +682,11 @@ yield switch (nestedFunctionSelector) { AbiConstants.ABI_ID_CREATE_FUNGIBLE_TOKEN_V2, AbiConstants.ABI_ID_CREATE_FUNGIBLE_TOKEN_WITH_FEES_V2, AbiConstants.ABI_ID_CREATE_NON_FUNGIBLE_TOKEN_V2, - AbiConstants - .ABI_ID_CREATE_NON_FUNGIBLE_TOKEN_WITH_FEES_V2 -> (dynamicProperties + AbiConstants.ABI_ID_CREATE_NON_FUNGIBLE_TOKEN_WITH_FEES_V2, + AbiConstants.ABI_ID_CREATE_FUNGIBLE_TOKEN_V3, + AbiConstants.ABI_ID_CREATE_FUNGIBLE_TOKEN_WITH_FEES_V3, + AbiConstants.ABI_ID_CREATE_NON_FUNGIBLE_TOKEN_V3, + AbiConstants.ABI_ID_CREATE_NON_FUNGIBLE_TOKEN_WITH_FEES_V3 -> (dynamicProperties .isHTSPrecompileCreateEnabled()) ? new TokenCreatePrecompile( ledgers, @@ -747,14 +757,17 @@ yield switch (nestedFunctionSelector) { precompilePricingUtils, currentView); case AbiConstants - .ABI_ID_UPDATE_TOKEN_EXPIRY_INFO -> new UpdateTokenExpiryInfoPrecompile( + .ABI_ID_UPDATE_TOKEN_EXPIRY_INFO, + AbiConstants + .ABI_ID_UPDATE_TOKEN_EXPIRY_INFO_V2-> new UpdateTokenExpiryInfoPrecompile( ledgers, updater.aliases(), sigsVerifier, sideEffectsTracker, syntheticTxnFactory, infrastructureFactory, - precompilePricingUtils); + precompilePricingUtils, + functionId); case AbiConstants.ABI_ID_TRANSFER_FROM -> checkFeatureFlag( dynamicProperties.areAllowancesEnabled(), () -> diff --git a/hedera-node/hedera-mono-service/src/main/java/com/hedera/services/store/contracts/precompile/codec/DecodingFacade.java b/hedera-node/hedera-mono-service/src/main/java/com/hedera/services/store/contracts/precompile/codec/DecodingFacade.java index 3923e7e1edd2..2a25a6c7b08a 100644 --- a/hedera-node/hedera-mono-service/src/main/java/com/hedera/services/store/contracts/precompile/codec/DecodingFacade.java +++ b/hedera-node/hedera-mono-service/src/main/java/com/hedera/services/store/contracts/precompile/codec/DecodingFacade.java @@ -17,6 +17,7 @@ import static com.hedera.services.contracts.ParsingConstants.ARRAY_BRACKETS; import static com.hedera.services.contracts.ParsingConstants.EXPIRY; +import static com.hedera.services.contracts.ParsingConstants.EXPIRY_V2; import static com.hedera.services.contracts.ParsingConstants.TOKEN_KEY; import static com.hedera.services.utils.EntityIdUtils.accountIdFromEvmAddress; @@ -52,7 +53,7 @@ public class DecodingFacade { private static final String KEY_VALUE_DECODER = "(bool,bytes32,bytes,bytes,bytes32)"; public static final String TOKEN_KEY_DECODER = "(int32," + KEY_VALUE_DECODER + ")"; public static final String EXPIRY_DECODER = "(int64,bytes32,int64)"; - + public static final String EXPIRY_DECODER_V2 = "(int32,bytes32,int32)"; public static final String FIXED_FEE_DECODER = "(int64,bytes32,bool,bool,bytes32)"; public static final String FRACTIONAL_FEE_DECODER = "(int64,int64,int64,int64,bool,bytes32)"; public static final String ROYALTY_FEE_DECODER = "(int64,int64,int64,bytes32,bool,bytes32)"; @@ -71,6 +72,13 @@ public class DecodingFacade { + "," + EXPIRY + ")"; + public static final String HEDERA_TOKEN_STRUCT_V3 = + "(string,string,address,string,bool,int64,bool," + + TOKEN_KEY + + ARRAY_BRACKETS + + "," + + EXPIRY_V2 + + ")"; public static final String HEDERA_TOKEN_STRUCT_DECODER = "(string,string,bytes32,string,bool,int64,bool," + TOKEN_KEY_DECODER @@ -78,6 +86,13 @@ public class DecodingFacade { + "," + EXPIRY_DECODER + ")"; + public static final String HEDERA_TOKEN_STRUCT_DECODER_V2 = + "(string,string,bytes32,string,bool,int64,bool," + + TOKEN_KEY_DECODER + + ARRAY_BRACKETS + + "," + + EXPIRY_DECODER_V2 + + ")"; private DecodingFacade() { throw new UnsupportedOperationException("Utility Class"); @@ -127,6 +142,18 @@ public static TokenExpiryWrapper decodeTokenExpiry( autoRenewPeriod); } + public static TokenExpiryWrapper decodeTokenExpiryV2( + @NotNull final Tuple expiryTuple, final UnaryOperator aliasResolver) { + final var second = (int) expiryTuple.get(0); + final var autoRenewAccount = + convertLeftPaddedAddressToAccountId(expiryTuple.get(1), aliasResolver); + final var autoRenewPeriod = (int) expiryTuple.get(2); + return new TokenExpiryWrapper( + second, + autoRenewAccount.getAccountNum() == 0 ? null : autoRenewAccount, + autoRenewPeriod); + } + public static Tuple decodeFunctionCall( @NotNull final Bytes input, final Bytes selector, final ABIType decoder) { if (!selector.equals(input.slice(0, FUNCTION_SELECTOR_BYTES_LENGTH))) { diff --git a/hedera-node/hedera-mono-service/src/main/java/com/hedera/services/store/contracts/precompile/impl/BurnPrecompile.java b/hedera-node/hedera-mono-service/src/main/java/com/hedera/services/store/contracts/precompile/impl/BurnPrecompile.java index 471da6614d0b..16c9cebd8427 100644 --- a/hedera-node/hedera-mono-service/src/main/java/com/hedera/services/store/contracts/precompile/impl/BurnPrecompile.java +++ b/hedera-node/hedera-mono-service/src/main/java/com/hedera/services/store/contracts/precompile/impl/BurnPrecompile.java @@ -33,6 +33,7 @@ import com.hedera.services.ledger.accounts.ContractAliases; import com.hedera.services.state.submerkle.ExpirableTxnRecord; import com.hedera.services.store.contracts.WorldLedgers; +import com.hedera.services.store.contracts.precompile.AbiConstants; import com.hedera.services.store.contracts.precompile.InfrastructureFactory; import com.hedera.services.store.contracts.precompile.SyntheticTxnFactory; import com.hedera.services.store.contracts.precompile.codec.BurnWrapper; @@ -43,6 +44,7 @@ import com.hederahashgraph.api.proto.java.ResponseCodeEnum; import com.hederahashgraph.api.proto.java.Timestamp; import com.hederahashgraph.api.proto.java.TransactionBody; + import java.util.Arrays; import java.util.Collections; import java.util.List; @@ -52,11 +54,15 @@ import org.hyperledger.besu.evm.frame.MessageFrame; public class BurnPrecompile extends AbstractWritePrecompile { + private final int functionId; private static final List NO_SERIAL_NOS = Collections.emptyList(); private static final String BURN = String.format(FAILURE_MESSAGE, "burn"); private static final Function BURN_TOKEN_FUNCTION = new Function("burnToken(address,uint64,int64[])", INT); + private static final Function BURN_TOKEN_FUNCTION_V2 = + new Function("burnToken(address,int64,int64[])", INT); private static final Bytes BURN_TOKEN_SELECTOR = Bytes.wrap(BURN_TOKEN_FUNCTION.selector()); + private static final Bytes BURN_TOKEN_SELECTOR_V2 = Bytes.wrap(BURN_TOKEN_FUNCTION_V2.selector()); private static final ABIType BURN_TOKEN_DECODER = TypeFactory.create("(bytes32,int64,int64[])"); private final EncodingFacade encoder; @@ -72,17 +78,24 @@ public BurnPrecompile( final SideEffectsTracker sideEffects, final SyntheticTxnFactory syntheticTxnFactory, final InfrastructureFactory infrastructureFactory, - final PrecompilePricingUtils pricingUtils) { + final PrecompilePricingUtils pricingUtils, + final int functionId) { super(ledgers, sideEffects, syntheticTxnFactory, infrastructureFactory, pricingUtils); this.encoder = encoder; this.aliases = aliases; this.sigsVerifier = sigsVerifier; + this.functionId = functionId; } @Override public TransactionBody.Builder body( final Bytes input, final UnaryOperator aliasResolver) { - burnOp = decodeBurn(input); + burnOp = + switch (functionId) { + case AbiConstants.ABI_ID_BURN_TOKEN -> decodeBurn(input); + case AbiConstants.ABI_ID_BURN_TOKEN_V2 -> decodeBurnV2(input); + default -> null; + }; transactionBody = syntheticTxnFactory.createBurn(burnOp); return transactionBody; } @@ -159,4 +172,20 @@ public static BurnWrapper decodeBurn(final Bytes input) { tokenID, Arrays.stream(serialNumbers).boxed().toList()); } } + + public static BurnWrapper decodeBurnV2(final Bytes input) { + final Tuple decodedArguments = + decodeFunctionCall(input, BURN_TOKEN_SELECTOR_V2, BURN_TOKEN_DECODER); + + final var tokenID = convertAddressBytesToTokenID(decodedArguments.get(0)); + final var fungibleAmount = (long) decodedArguments.get(1); + final var serialNumbers = (long[]) decodedArguments.get(2); + + if (fungibleAmount > 0) { + return BurnWrapper.forFungible(tokenID, fungibleAmount); + } else { + return BurnWrapper.forNonFungible( + tokenID, Arrays.stream(serialNumbers).boxed().toList()); + } + } } diff --git a/hedera-node/hedera-mono-service/src/main/java/com/hedera/services/store/contracts/precompile/impl/MintPrecompile.java b/hedera-node/hedera-mono-service/src/main/java/com/hedera/services/store/contracts/precompile/impl/MintPrecompile.java index a42a56dddb66..bf4bcf1cb69e 100644 --- a/hedera-node/hedera-mono-service/src/main/java/com/hedera/services/store/contracts/precompile/impl/MintPrecompile.java +++ b/hedera-node/hedera-mono-service/src/main/java/com/hedera/services/store/contracts/precompile/impl/MintPrecompile.java @@ -21,7 +21,9 @@ import static com.hedera.services.store.contracts.precompile.codec.DecodingFacade.decodeFunctionCall; import static com.hedera.services.store.contracts.precompile.utils.PrecompilePricingUtils.GasCostType.MINT_FUNGIBLE; import static com.hedera.services.store.contracts.precompile.utils.PrecompilePricingUtils.GasCostType.MINT_NFT; -import static com.hederahashgraph.api.proto.java.ResponseCodeEnum.*; +import static com.hederahashgraph.api.proto.java.ResponseCodeEnum.FAIL_INVALID; +import static com.hederahashgraph.api.proto.java.ResponseCodeEnum.INVALID_FULL_PREFIX_SIGNATURE_FOR_PRECOMPILE; +import static com.hederahashgraph.api.proto.java.ResponseCodeEnum.OK; import static com.hederahashgraph.api.proto.java.TokenType.NON_FUNGIBLE_UNIQUE; import com.esaulpaugh.headlong.abi.ABIType; @@ -36,6 +38,7 @@ import com.hedera.services.records.RecordsHistorian; import com.hedera.services.state.submerkle.ExpirableTxnRecord; import com.hedera.services.store.contracts.WorldLedgers; +import com.hedera.services.store.contracts.precompile.AbiConstants; import com.hedera.services.store.contracts.precompile.InfrastructureFactory; import com.hedera.services.store.contracts.precompile.SyntheticTxnFactory; import com.hedera.services.store.contracts.precompile.codec.EncodingFacade; @@ -56,11 +59,15 @@ import org.hyperledger.besu.evm.frame.MessageFrame; public class MintPrecompile extends AbstractWritePrecompile { + private final int functionId; private static final List NO_METADATA = Collections.emptyList(); private static final String MINT = String.format(FAILURE_MESSAGE, "mint"); private static final Function MINT_TOKEN_FUNCTION = new Function("mintToken(address,uint64,bytes[])", INT); - private static final Bytes MINT_TOKEN_SELECTOR = Bytes.wrap(MINT_TOKEN_FUNCTION.selector()); + private static final Function MINT_TOKEN_FUNCTION_V2 = + new Function("mintToken(address,int64,bytes[])", INT); + public static final Bytes MINT_TOKEN_SELECTOR = Bytes.wrap(MINT_TOKEN_FUNCTION.selector()); + private static final Bytes MINT_TOKEN_SELECTOR_V2 = Bytes.wrap(MINT_TOKEN_FUNCTION_V2.selector()); private static final ABIType MINT_TOKEN_DECODER = TypeFactory.create("(bytes32,int64,bytes[])"); private final EncodingFacade encoder; @@ -79,19 +86,26 @@ public MintPrecompile( final SideEffectsTracker sideEffects, final SyntheticTxnFactory syntheticTxnFactory, final InfrastructureFactory infrastructureFactory, - final PrecompilePricingUtils pricingUtils) { + final PrecompilePricingUtils pricingUtils, + final int functionId) { super(ledgers, sideEffects, syntheticTxnFactory, infrastructureFactory, pricingUtils); this.encoder = encoder; this.aliases = aliases; this.sigsVerifier = sigsVerifier; this.recordsHistorian = recordsHistorian; + this.functionId = functionId; } @Override public TransactionBody.Builder body( final Bytes input, final UnaryOperator aliasResolver) { this.transactionBody = null; - mintOp = decodeMint(input); + mintOp = + switch (functionId) { + case AbiConstants.ABI_ID_MINT_TOKEN -> decodeMint(input); + case AbiConstants.ABI_ID_MINT_TOKEN_V2 -> decodeMintV2(input); + default -> null; + }; transactionBody = syntheticTxnFactory.createMint(mintOp); return transactionBody; } @@ -173,4 +187,22 @@ public static MintWrapper decodeMint(final Bytes input) { return MintWrapper.forNonFungible(tokenID, wrappedMetadata); } } + + public static MintWrapper decodeMintV2(final Bytes input) { + final Tuple decodedArguments = + decodeFunctionCall(input, MINT_TOKEN_SELECTOR_V2, MINT_TOKEN_DECODER); + + final var tokenID = convertAddressBytesToTokenID(decodedArguments.get(0)); + final var fungibleAmount = (long) decodedArguments.get(1); + final var metadataList = (byte[][]) decodedArguments.get(2); + final List wrappedMetadata = new ArrayList<>(); + for (final var meta : metadataList) { + wrappedMetadata.add(ByteStringUtils.wrapUnsafely(meta)); + } + if (fungibleAmount > 0) { + return MintWrapper.forFungible(tokenID, fungibleAmount); + } else { + return MintWrapper.forNonFungible(tokenID, wrappedMetadata); + } + } } diff --git a/hedera-node/hedera-mono-service/src/main/java/com/hedera/services/store/contracts/precompile/impl/TokenCreatePrecompile.java b/hedera-node/hedera-mono-service/src/main/java/com/hedera/services/store/contracts/precompile/impl/TokenCreatePrecompile.java index 57d13458ed2a..2fbb2fba9d9f 100644 --- a/hedera-node/hedera-mono-service/src/main/java/com/hedera/services/store/contracts/precompile/impl/TokenCreatePrecompile.java +++ b/hedera-node/hedera-mono-service/src/main/java/com/hedera/services/store/contracts/precompile/impl/TokenCreatePrecompile.java @@ -17,8 +17,11 @@ import static com.hedera.services.contracts.ParsingConstants.ARRAY_BRACKETS; import static com.hedera.services.contracts.ParsingConstants.FIXED_FEE; +import static com.hedera.services.contracts.ParsingConstants.FIXED_FEE_V2; import static com.hedera.services.contracts.ParsingConstants.FRACTIONAL_FEE; +import static com.hedera.services.contracts.ParsingConstants.FRACTIONAL_FEE_V2; import static com.hedera.services.contracts.ParsingConstants.ROYALTY_FEE; +import static com.hedera.services.contracts.ParsingConstants.ROYALTY_FEE_V2; import static com.hedera.services.exceptions.ValidationUtils.validateTrue; import static com.hedera.services.ledger.properties.AccountProperty.AUTO_RENEW_ACCOUNT_ID; import static com.hedera.services.state.submerkle.EntityId.MISSING_ENTITY_ID; @@ -26,12 +29,15 @@ import static com.hedera.services.store.contracts.precompile.codec.DecodingFacade.FRACTIONAL_FEE_DECODER; import static com.hedera.services.store.contracts.precompile.codec.DecodingFacade.HEDERA_TOKEN_STRUCT; import static com.hedera.services.store.contracts.precompile.codec.DecodingFacade.HEDERA_TOKEN_STRUCT_DECODER; +import static com.hedera.services.store.contracts.precompile.codec.DecodingFacade.HEDERA_TOKEN_STRUCT_DECODER_V2; import static com.hedera.services.store.contracts.precompile.codec.DecodingFacade.HEDERA_TOKEN_STRUCT_V2; +import static com.hedera.services.store.contracts.precompile.codec.DecodingFacade.HEDERA_TOKEN_STRUCT_V3; import static com.hedera.services.store.contracts.precompile.codec.DecodingFacade.ROYALTY_FEE_DECODER; import static com.hedera.services.store.contracts.precompile.codec.DecodingFacade.convertAddressBytesToTokenID; import static com.hedera.services.store.contracts.precompile.codec.DecodingFacade.convertLeftPaddedAddressToAccountId; import static com.hedera.services.store.contracts.precompile.codec.DecodingFacade.decodeFunctionCall; import static com.hedera.services.store.contracts.precompile.codec.DecodingFacade.decodeTokenExpiry; +import static com.hedera.services.store.contracts.precompile.codec.DecodingFacade.decodeTokenExpiryV2; import static com.hedera.services.store.contracts.precompile.codec.DecodingFacade.decodeTokenKeys; import static com.hedera.services.store.contracts.precompile.codec.KeyValueWrapper.KeyValueType.INVALID_KEY; import static com.hedera.services.store.contracts.precompile.codec.TokenCreateWrapper.FixedFeeWrapper.FixedFeePayment.INVALID_PAYMENT; @@ -157,10 +163,16 @@ public class TokenCreatePrecompile extends AbstractWritePrecompile { Bytes.wrap(TOKEN_CREATE_FUNGIBLE_FUNCTION.selector()); public static final ABIType TOKEN_CREATE_FUNGIBLE_DECODER = TypeFactory.create("(" + HEDERA_TOKEN_STRUCT_DECODER + ",uint256,uint256)"); + public static final ABIType TOKEN_CREATE_FUNGIBLE_DECODER_V2 = + TypeFactory.create("(" + HEDERA_TOKEN_STRUCT_DECODER_V2 + ",uint256,uint256)"); private static final Function TOKEN_CREATE_FUNGIBLE_FUNCTION_V2 = new Function("createFungibleToken(" + HEDERA_TOKEN_STRUCT_V2 + ",uint64,uint32)"); public static final Bytes TOKEN_CREATE_FUNGIBLE_SELECTOR_V2 = Bytes.wrap(TOKEN_CREATE_FUNGIBLE_FUNCTION_V2.selector()); + private static final Function TOKEN_CREATE_FUNGIBLE_FUNCTION_V3 = + new Function("createFungibleToken(" + HEDERA_TOKEN_STRUCT_V3 + ",int64,int32)"); + public static final Bytes TOKEN_CREATE_FUNGIBLE_SELECTOR_V3 = + Bytes.wrap(TOKEN_CREATE_FUNGIBLE_FUNCTION_V3.selector()); private static final Function TOKEN_CREATE_FUNGIBLE_WITH_FEES_FUNCTION = new Function( "createFungibleTokenWithCustomFees(" @@ -198,6 +210,20 @@ public class TokenCreatePrecompile extends AbstractWritePrecompile { + FRACTIONAL_FEE_DECODER + ARRAY_BRACKETS + ")"); + + private static final Function TOKEN_CREATE_FUNGIBLE_WITH_FEES_FUNCTION_V3 = + new Function( + "createFungibleTokenWithCustomFees(" + + HEDERA_TOKEN_STRUCT_V3 + + ",int64,int32," + + FIXED_FEE_V2 + + ARRAY_BRACKETS + + "," + + FRACTIONAL_FEE_V2 + + ARRAY_BRACKETS + + ")"); + public static final Bytes TOKEN_CREATE_FUNGIBLE_WITH_FEES_SELECTOR_V3 = + Bytes.wrap(TOKEN_CREATE_FUNGIBLE_WITH_FEES_FUNCTION_V3.selector()); private static final Function TOKEN_CREATE_NON_FUNGIBLE_FUNCTION = new Function("createNonFungibleToken(" + HEDERA_TOKEN_STRUCT + ")"); public static final Bytes TOKEN_CREATE_NON_FUNGIBLE_SELECTOR = @@ -208,6 +234,12 @@ public class TokenCreatePrecompile extends AbstractWritePrecompile { Bytes.wrap(TOKEN_CREATE_NON_FUNGIBLE_FUNCTION_V2.selector()); public static final ABIType TOKEN_CREATE_NON_FUNGIBLE_DECODER = TypeFactory.create("(" + HEDERA_TOKEN_STRUCT_DECODER + ")"); + private static final Function TOKEN_CREATE_NON_FUNGIBLE_FUNCTION_V3 = + new Function("createNonFungibleToken(" + HEDERA_TOKEN_STRUCT_V3 + ")"); + public static final Bytes TOKEN_CREATE_NON_FUNGIBLE_SELECTOR_V3 = + Bytes.wrap(TOKEN_CREATE_NON_FUNGIBLE_FUNCTION_V3.selector()); + public static final ABIType TOKEN_CREATE_NON_FUNGIBLE_DECODER_V2 = + TypeFactory.create("(" + HEDERA_TOKEN_STRUCT_DECODER_V2 + ")"); private static final Function TOKEN_CREATE_NON_FUNGIBLE_WITH_FEES_FUNCTION = new Function( "createNonFungibleTokenWithCustomFees(" @@ -245,6 +277,30 @@ public class TokenCreatePrecompile extends AbstractWritePrecompile { + ROYALTY_FEE_DECODER + ARRAY_BRACKETS + ")"); + private static final Function TOKEN_CREATE_NON_FUNGIBLE_WITH_FEES_FUNCTION_V3 = + new Function( + "createNonFungibleTokenWithCustomFees(" + + HEDERA_TOKEN_STRUCT_V3 + + "," + + FIXED_FEE_V2 + + ARRAY_BRACKETS + + "," + + ROYALTY_FEE_V2 + + ARRAY_BRACKETS + + ")"); + public static final Bytes TOKEN_CREATE_NON_FUNGIBLE_WITH_FEES_SELECTOR_V3 = + Bytes.wrap(TOKEN_CREATE_NON_FUNGIBLE_WITH_FEES_FUNCTION_V3.selector()); + public static final ABIType TOKEN_CREATE_NON_FUNGIBLE_WITH_FEES_DECODER_V2 = + TypeFactory.create( + "(" + + HEDERA_TOKEN_STRUCT_DECODER_V2 + + "," + + FIXED_FEE_DECODER + + ARRAY_BRACKETS + + "," + + ROYALTY_FEE_DECODER + + ARRAY_BRACKETS + + ")"); private final EncodingFacade encoder; private final HederaStackedWorldStateUpdater updater; private final EvmSigsVerifier sigsVerifier; @@ -306,6 +362,17 @@ public TransactionBody.Builder body( case AbiConstants .ABI_ID_CREATE_NON_FUNGIBLE_TOKEN_WITH_FEES_V2 -> decodeNonFungibleCreateWithFeesV2( input, aliasResolver); + case AbiConstants.ABI_ID_CREATE_FUNGIBLE_TOKEN_V3 -> decodeFungibleCreateV3( + input, aliasResolver); + case AbiConstants + .ABI_ID_CREATE_FUNGIBLE_TOKEN_WITH_FEES_V3 -> decodeFungibleCreateWithFeesV3( + input, aliasResolver); + case AbiConstants + .ABI_ID_CREATE_NON_FUNGIBLE_TOKEN_V3 -> decodeNonFungibleCreateV3( + input, aliasResolver); + case AbiConstants + .ABI_ID_CREATE_NON_FUNGIBLE_TOKEN_WITH_FEES_V3 -> decodeNonFungibleCreateWithFeesV3( + input, aliasResolver); default -> null; }; @@ -607,6 +674,38 @@ public static TokenCreateWrapper decodeTokenCreateWithoutFees( tokenExpiry); } + public static TokenCreateWrapper decodeTokenCreateWithoutFeesV2( + @NotNull final Tuple tokenCreateStruct, + final boolean isFungible, + final BigInteger initSupply, + final BigInteger decimals, + final UnaryOperator aliasResolver) { + final var tokenName = (String) tokenCreateStruct.get(0); + final var tokenSymbol = (String) tokenCreateStruct.get(1); + final var tokenTreasury = + convertLeftPaddedAddressToAccountId(tokenCreateStruct.get(2), aliasResolver); + final var memo = (String) tokenCreateStruct.get(3); + final var isSupplyTypeFinite = (Boolean) tokenCreateStruct.get(4); + final var maxSupply = (long) tokenCreateStruct.get(5); + final var isFreezeDefault = (Boolean) tokenCreateStruct.get(6); + final var tokenKeys = decodeTokenKeys(tokenCreateStruct.get(7), aliasResolver); + final var tokenExpiry = decodeTokenExpiryV2(tokenCreateStruct.get(8), aliasResolver); + + return new TokenCreateWrapper( + isFungible, + tokenName, + tokenSymbol, + tokenTreasury.getAccountNum() != 0 ? tokenTreasury : null, + memo, + isSupplyTypeFinite, + initSupply, + decimals, + maxSupply, + isFreezeDefault, + tokenKeys, + tokenExpiry); + } + /** * Decodes the given bytes of the fungible token. * @@ -788,6 +887,20 @@ public static TokenCreateWrapper decodeFungibleCreateV2( aliasResolver); } + public static TokenCreateWrapper decodeFungibleCreateV3( + final Bytes input, final UnaryOperator aliasResolver) { + final Tuple decodedArguments = + decodeFunctionCall( + input, TOKEN_CREATE_FUNGIBLE_SELECTOR_V3, TOKEN_CREATE_FUNGIBLE_DECODER_V2); + + return decodeTokenCreateWithoutFeesV2( + decodedArguments.get(0), + true, + decodedArguments.get(1), + decodedArguments.get(2), + aliasResolver); + } + /** * Decodes the given bytes of the fungible token. * @@ -824,6 +937,29 @@ public static TokenCreateWrapper decodeFungibleCreateWithFeesV2( return tokenCreateWrapper; } + public static TokenCreateWrapper decodeFungibleCreateWithFeesV3( + final Bytes input, final UnaryOperator aliasResolver) { + final Tuple decodedArguments = + decodeFunctionCall( + input, + TOKEN_CREATE_FUNGIBLE_WITH_FEES_SELECTOR_V3, + TOKEN_CREATE_FUNGIBLE_WITH_FEES_DECODER); + + final var tokenCreateWrapper = + decodeTokenCreateWithoutFees( + decodedArguments.get(0), + true, + decodedArguments.get(1), + decodedArguments.get(2), + aliasResolver); + final var fixedFees = decodeFixedFees(decodedArguments.get(3), aliasResolver); + final var fractionalFees = decodeFractionalFees(decodedArguments.get(4), aliasResolver); + tokenCreateWrapper.setFixedFees(fixedFees); + tokenCreateWrapper.setFractionalFees(fractionalFees); + + return tokenCreateWrapper; + } + /** * Decodes the given bytes of the non-fungible token. * @@ -848,6 +984,18 @@ public static TokenCreateWrapper decodeNonFungibleCreateV2( decodedArguments.get(0), false, BigInteger.ZERO, BigInteger.ZERO, aliasResolver); } + public static TokenCreateWrapper decodeNonFungibleCreateV3( + final Bytes input, final UnaryOperator aliasResolver) { + final Tuple decodedArguments = + decodeFunctionCall( + input, + TOKEN_CREATE_NON_FUNGIBLE_SELECTOR_V3, + TOKEN_CREATE_NON_FUNGIBLE_DECODER_V2); + + return decodeTokenCreateWithoutFees( + decodedArguments.get(0), false, BigInteger.ZERO, BigInteger.ZERO, aliasResolver); + } + /** * Decodes the given bytes of the non-fungible token. * @@ -883,4 +1031,27 @@ public static TokenCreateWrapper decodeNonFungibleCreateWithFeesV2( return tokenCreateWrapper; } + + public static TokenCreateWrapper decodeNonFungibleCreateWithFeesV3( + final Bytes input, final UnaryOperator aliasResolver) { + final Tuple decodedArguments = + decodeFunctionCall( + input, + TOKEN_CREATE_NON_FUNGIBLE_WITH_FEES_SELECTOR_V3, + TOKEN_CREATE_NON_FUNGIBLE_WITH_FEES_DECODER_V2); + + final var tokenCreateWrapper = + decodeTokenCreateWithoutFees( + decodedArguments.get(0), + false, + BigInteger.ZERO, + BigInteger.ZERO, + aliasResolver); + final var fixedFees = decodeFixedFees(decodedArguments.get(1), aliasResolver); + final var royaltyFees = decodeRoyaltyFees(decodedArguments.get(2), aliasResolver); + tokenCreateWrapper.setFixedFees(fixedFees); + tokenCreateWrapper.setRoyaltyFees(royaltyFees); + + return tokenCreateWrapper; + } } diff --git a/hedera-node/hedera-mono-service/src/main/java/com/hedera/services/store/contracts/precompile/impl/TokenUpdatePrecompile.java b/hedera-node/hedera-mono-service/src/main/java/com/hedera/services/store/contracts/precompile/impl/TokenUpdatePrecompile.java index 433ebebe192b..f68d48fe8df4 100644 --- a/hedera-node/hedera-mono-service/src/main/java/com/hedera/services/store/contracts/precompile/impl/TokenUpdatePrecompile.java +++ b/hedera-node/hedera-mono-service/src/main/java/com/hedera/services/store/contracts/precompile/impl/TokenUpdatePrecompile.java @@ -19,11 +19,14 @@ import static com.hedera.services.exceptions.ValidationUtils.validateTrue; import static com.hedera.services.store.contracts.precompile.codec.DecodingFacade.HEDERA_TOKEN_STRUCT; import static com.hedera.services.store.contracts.precompile.codec.DecodingFacade.HEDERA_TOKEN_STRUCT_DECODER; +import static com.hedera.services.store.contracts.precompile.codec.DecodingFacade.HEDERA_TOKEN_STRUCT_DECODER_V2; import static com.hedera.services.store.contracts.precompile.codec.DecodingFacade.HEDERA_TOKEN_STRUCT_V2; +import static com.hedera.services.store.contracts.precompile.codec.DecodingFacade.HEDERA_TOKEN_STRUCT_V3; import static com.hedera.services.store.contracts.precompile.codec.DecodingFacade.convertAddressBytesToTokenID; import static com.hedera.services.store.contracts.precompile.codec.DecodingFacade.convertLeftPaddedAddressToAccountId; import static com.hedera.services.store.contracts.precompile.codec.DecodingFacade.decodeFunctionCall; import static com.hedera.services.store.contracts.precompile.codec.DecodingFacade.decodeTokenExpiry; +import static com.hedera.services.store.contracts.precompile.codec.DecodingFacade.decodeTokenExpiryV2; import static com.hedera.services.store.contracts.precompile.codec.DecodingFacade.decodeTokenKeys; import static com.hedera.services.store.contracts.precompile.codec.DecodingFacade.removeBrackets; import static com.hedera.services.store.contracts.precompile.impl.AbstractTokenUpdatePrecompile.UpdateType.UPDATE_TOKEN_INFO; @@ -61,6 +64,13 @@ public class TokenUpdatePrecompile extends AbstractTokenUpdatePrecompile { new Function("updateTokenInfo(address," + HEDERA_TOKEN_STRUCT_V2 + ")"); private static final Bytes TOKEN_UPDATE_INFO_SELECTOR_V2 = Bytes.wrap(TOKEN_UPDATE_INFO_FUNCTION_V2.selector()); + private static final Function TOKEN_UPDATE_INFO_FUNCTION_V3 = + new Function("updateTokenInfo(address," + HEDERA_TOKEN_STRUCT_V3 + ")"); + private static final Bytes TOKEN_UPDATE_INFO_SELECTOR_V3 = + Bytes.wrap(TOKEN_UPDATE_INFO_FUNCTION_V3.selector()); + private static final ABIType TOKEN_UPDATE_INFO_DECODER_V2 = + TypeFactory.create( + "(" + removeBrackets(BYTES32) + "," + HEDERA_TOKEN_STRUCT_DECODER_V2 + ")"); private TokenUpdateWrapper updateOp; private final int functionId; @@ -93,6 +103,8 @@ public TransactionBody.Builder body(Bytes input, UnaryOperator aliasReso input, aliasResolver); case AbiConstants.ABI_ID_UPDATE_TOKEN_INFO_V2 -> decodeUpdateTokenInfoV2( input, aliasResolver); + case AbiConstants.ABI_ID_UPDATE_TOKEN_INFO_V3 -> decodeUpdateTokenInfoV3( + input, aliasResolver); default -> null; }; transactionBody = syntheticTxnFactory.createTokenUpdate(updateOp); @@ -165,4 +177,22 @@ public static TokenUpdateWrapper decodeUpdateTokenInfoV2( return new TokenUpdateWrapper( tokenID, tokenName, tokenSymbol, tokenTreasury, tokenMemo, tokenKeys, tokenExpiry); } + + public static TokenUpdateWrapper decodeUpdateTokenInfoV3( + Bytes input, UnaryOperator aliasResolver) { + final Tuple decodedArguments = + decodeFunctionCall(input, TOKEN_UPDATE_INFO_SELECTOR_V3, TOKEN_UPDATE_INFO_DECODER_V2); + final var tokenID = convertAddressBytesToTokenID(decodedArguments.get(0)); + + final Tuple hederaTokenStruct = decodedArguments.get(1); + final var tokenName = (String) hederaTokenStruct.get(0); + final var tokenSymbol = (String) hederaTokenStruct.get(1); + final var tokenTreasury = + convertLeftPaddedAddressToAccountId(hederaTokenStruct.get(2), aliasResolver); + final var tokenMemo = (String) hederaTokenStruct.get(3); + final var tokenKeys = decodeTokenKeys(hederaTokenStruct.get(7), aliasResolver); + final var tokenExpiry = decodeTokenExpiryV2(hederaTokenStruct.get(8), aliasResolver); + return new TokenUpdateWrapper( + tokenID, tokenName, tokenSymbol, tokenTreasury, tokenMemo, tokenKeys, tokenExpiry); + } } diff --git a/hedera-node/hedera-mono-service/src/main/java/com/hedera/services/store/contracts/precompile/impl/TransferPrecompile.java b/hedera-node/hedera-mono-service/src/main/java/com/hedera/services/store/contracts/precompile/impl/TransferPrecompile.java index 6ce62de58a0c..e7d6f16f6dc3 100644 --- a/hedera-node/hedera-mono-service/src/main/java/com/hedera/services/store/contracts/precompile/impl/TransferPrecompile.java +++ b/hedera-node/hedera-mono-service/src/main/java/com/hedera/services/store/contracts/precompile/impl/TransferPrecompile.java @@ -72,19 +72,17 @@ public class TransferPrecompile extends AbstractWritePrecompile { private static final Function CRYPTO_TRANSFER_FUNCTION = new Function( "cryptoTransfer((address,(address,int64)[],(address,address,int64)[])[])", INT); - private static final Bytes CRYPTO_TRANSFER_SELECTOR = - Bytes.wrap(CRYPTO_TRANSFER_FUNCTION.selector()); - private static final ABIType CRYPTO_TRANSFER_DECODER = - TypeFactory.create("((bytes32,(bytes32,int64)[],(bytes32,bytes32,int64)[])[])"); private static final Function CRYPTO_TRANSFER_FUNCTION_V2 = new Function( - "cryptoTransfer(((address,int64,bool)[]),(address,(address,int64,bool)[],(address,address,int64,bool)[])[])", - INT); + "cryptoTransfer(((address,int64,bool)[]),(address,(address,int64,bool)[],(address,address,int64,bool)[])[])", INT); + private static final Bytes CRYPTO_TRANSFER_SELECTOR = + Bytes.wrap(CRYPTO_TRANSFER_FUNCTION.selector()); private static final Bytes CRYPTO_TRANSFER_SELECTOR_V2 = Bytes.wrap(CRYPTO_TRANSFER_FUNCTION_V2.selector()); + private static final ABIType CRYPTO_TRANSFER_DECODER = + TypeFactory.create("((bytes32,(bytes32,int64)[],(bytes32,bytes32,int64)[])[])"); private static final ABIType CRYPTO_TRANSFER_DECODER_V2 = - TypeFactory.create( - "(((bytes32,int64,bool)[]),(bytes32,(bytes32,int64,bool)[],(bytes32,bytes32,int64,bool)[])[])"); + TypeFactory.create("(((bytes32,int64,bool)[]),(bytes32,(bytes32,int64,bool)[],(bytes32,bytes32,int64,bool)[])[])"); private static final Function TRANSFER_TOKENS_FUNCTION = new Function("transferTokens(address,address[],int64[])", INT); private static final Bytes TRANSFER_TOKENS_SELECTOR = diff --git a/hedera-node/hedera-mono-service/src/main/java/com/hedera/services/store/contracts/precompile/impl/UpdateTokenExpiryInfoPrecompile.java b/hedera-node/hedera-mono-service/src/main/java/com/hedera/services/store/contracts/precompile/impl/UpdateTokenExpiryInfoPrecompile.java index 546290c8caf4..4ccb38ec905d 100644 --- a/hedera-node/hedera-mono-service/src/main/java/com/hedera/services/store/contracts/precompile/impl/UpdateTokenExpiryInfoPrecompile.java +++ b/hedera-node/hedera-mono-service/src/main/java/com/hedera/services/store/contracts/precompile/impl/UpdateTokenExpiryInfoPrecompile.java @@ -17,11 +17,14 @@ import static com.hedera.services.contracts.ParsingConstants.BYTES32; import static com.hedera.services.contracts.ParsingConstants.EXPIRY; +import static com.hedera.services.contracts.ParsingConstants.EXPIRY_V2; import static com.hedera.services.exceptions.ValidationUtils.validateTrue; import static com.hedera.services.store.contracts.precompile.codec.DecodingFacade.EXPIRY_DECODER; +import static com.hedera.services.store.contracts.precompile.codec.DecodingFacade.EXPIRY_DECODER_V2; import static com.hedera.services.store.contracts.precompile.codec.DecodingFacade.convertAddressBytesToTokenID; import static com.hedera.services.store.contracts.precompile.codec.DecodingFacade.decodeFunctionCall; import static com.hedera.services.store.contracts.precompile.codec.DecodingFacade.decodeTokenExpiry; +import static com.hedera.services.store.contracts.precompile.codec.DecodingFacade.decodeTokenExpiryV2; import static com.hedera.services.store.contracts.precompile.codec.DecodingFacade.removeBrackets; import static com.hedera.services.store.contracts.precompile.impl.AbstractTokenUpdatePrecompile.UpdateType.UPDATE_TOKEN_EXPIRY; import static com.hederahashgraph.api.proto.java.ResponseCodeEnum.INVALID_TOKEN_ID; @@ -34,6 +37,7 @@ import com.hedera.services.contracts.sources.EvmSigsVerifier; import com.hedera.services.ledger.accounts.ContractAliases; import com.hedera.services.store.contracts.WorldLedgers; +import com.hedera.services.store.contracts.precompile.AbiConstants; import com.hedera.services.store.contracts.precompile.InfrastructureFactory; import com.hedera.services.store.contracts.precompile.SyntheticTxnFactory; import com.hedera.services.store.contracts.precompile.codec.TokenUpdateExpiryInfoWrapper; @@ -46,12 +50,19 @@ import org.hyperledger.besu.evm.frame.MessageFrame; public class UpdateTokenExpiryInfoPrecompile extends AbstractTokenUpdatePrecompile { + private final int functionId; private static final Function TOKEN_UPDATE_EXPIRY_INFO_FUNCTION = new Function("updateTokenExpiryInfo(address," + EXPIRY + ")"); private static final Bytes TOKEN_UPDATE_EXPIRY_INFO_SELECTOR = Bytes.wrap(TOKEN_UPDATE_EXPIRY_INFO_FUNCTION.selector()); private static final ABIType TOKEN_UPDATE_EXPIRY_INFO_DECODER = TypeFactory.create("(" + removeBrackets(BYTES32) + "," + EXPIRY_DECODER + ")"); + private static final Function TOKEN_UPDATE_EXPIRY_INFO_FUNCTION_V2 = + new Function("updateTokenExpiryInfo(address," + EXPIRY_V2 + ")"); + private static final Bytes TOKEN_UPDATE_EXPIRY_INFO_SELECTOR_V2 = + Bytes.wrap(TOKEN_UPDATE_EXPIRY_INFO_FUNCTION_V2.selector()); + private static final ABIType TOKEN_UPDATE_EXPIRY_INFO_DECODER_V2 = + TypeFactory.create("(" + removeBrackets(BYTES32) + "," + EXPIRY_DECODER_V2 + ")"); private TokenUpdateExpiryInfoWrapper updateExpiryInfoOp; public UpdateTokenExpiryInfoPrecompile( @@ -61,7 +72,8 @@ public UpdateTokenExpiryInfoPrecompile( SideEffectsTracker sideEffectsTracker, SyntheticTxnFactory syntheticTxnFactory, InfrastructureFactory infrastructureFactory, - PrecompilePricingUtils precompilePricingUtils) { + PrecompilePricingUtils precompilePricingUtils, + final int functionId) { super( ledgers, aliases, @@ -70,11 +82,18 @@ public UpdateTokenExpiryInfoPrecompile( syntheticTxnFactory, infrastructureFactory, precompilePricingUtils); + this.functionId = functionId; } @Override public Builder body(Bytes input, UnaryOperator aliasResolver) { - updateExpiryInfoOp = decodeUpdateTokenExpiryInfo(input, aliasResolver); + updateExpiryInfoOp = + switch (functionId) { + case AbiConstants.ABI_ID_UPDATE_TOKEN_EXPIRY_INFO -> decodeUpdateTokenExpiryInfo(input, aliasResolver); + case AbiConstants.ABI_ID_UPDATE_TOKEN_EXPIRY_INFO_V2 -> decodeUpdateTokenExpiryInfoV2(input, aliasResolver); + default -> null; + }; + transactionBody = syntheticTxnFactory.createTokenUpdateExpiryInfo(updateExpiryInfoOp); return transactionBody; } @@ -99,4 +118,16 @@ public static TokenUpdateExpiryInfoWrapper decodeUpdateTokenExpiryInfo( final var tokenExpiry = decodeTokenExpiry(tokenExpiryStruct, aliasResolver); return new TokenUpdateExpiryInfoWrapper(tokenID, tokenExpiry); } + + public static TokenUpdateExpiryInfoWrapper decodeUpdateTokenExpiryInfoV2( + final Bytes input, final UnaryOperator aliasResolver) { + final Tuple decodedArguments = + decodeFunctionCall( + input, TOKEN_UPDATE_EXPIRY_INFO_SELECTOR_V2, TOKEN_UPDATE_EXPIRY_INFO_DECODER_V2); + + final var tokenID = convertAddressBytesToTokenID(decodedArguments.get(0)); + final Tuple tokenExpiryStruct = decodedArguments.get(1); + final var tokenExpiry = decodeTokenExpiryV2(tokenExpiryStruct, aliasResolver); + return new TokenUpdateExpiryInfoWrapper(tokenID, tokenExpiry); + } } diff --git a/hedera-node/hedera-mono-service/src/main/java/com/hedera/services/store/contracts/precompile/impl/WipeFungiblePrecompile.java b/hedera-node/hedera-mono-service/src/main/java/com/hedera/services/store/contracts/precompile/impl/WipeFungiblePrecompile.java index 1eacc7b063cf..18c1e0a773f1 100644 --- a/hedera-node/hedera-mono-service/src/main/java/com/hedera/services/store/contracts/precompile/impl/WipeFungiblePrecompile.java +++ b/hedera-node/hedera-mono-service/src/main/java/com/hedera/services/store/contracts/precompile/impl/WipeFungiblePrecompile.java @@ -29,6 +29,7 @@ import com.hedera.services.contracts.sources.EvmSigsVerifier; import com.hedera.services.ledger.accounts.ContractAliases; import com.hedera.services.store.contracts.WorldLedgers; +import com.hedera.services.store.contracts.precompile.AbiConstants; import com.hedera.services.store.contracts.precompile.InfrastructureFactory; import com.hedera.services.store.contracts.precompile.SyntheticTxnFactory; import com.hedera.services.store.contracts.precompile.codec.WipeWrapper; @@ -40,12 +41,19 @@ import org.apache.tuweni.bytes.Bytes; public class WipeFungiblePrecompile extends AbstractWipePrecompile { + private final int functionId; private static final Function WIPE_TOKEN_ACCOUNT_FUNCTION = new Function("wipeTokenAccount(address,address,uint32)", INT); + private static final Function WIPE_TOKEN_ACCOUNT_FUNCTION_V2 = + new Function("wipeTokenAccount(address,address,int32)", INT); private static final Bytes WIPE_TOKEN_ACCOUNT_SELECTOR = Bytes.wrap(WIPE_TOKEN_ACCOUNT_FUNCTION.selector()); + private static final Bytes WIPE_TOKEN_ACCOUNT_SELECTOR_V2 = + Bytes.wrap(WIPE_TOKEN_ACCOUNT_FUNCTION_V2.selector()); private static final ABIType WIPE_TOKEN_ACCOUNT_DECODER = TypeFactory.create("(bytes32,bytes32,uint32)"); + private static final ABIType WIPE_TOKEN_ACCOUNT_DECODER_V2 = + TypeFactory.create("(bytes32,bytes32,int32)"); public WipeFungiblePrecompile( WorldLedgers ledgers, @@ -54,7 +62,8 @@ public WipeFungiblePrecompile( SideEffectsTracker sideEffects, SyntheticTxnFactory syntheticTxnFactory, InfrastructureFactory infrastructureFactory, - PrecompilePricingUtils pricingUtils) { + PrecompilePricingUtils pricingUtils, + final int functionId) { super( ledgers, aliases, @@ -63,11 +72,17 @@ public WipeFungiblePrecompile( syntheticTxnFactory, infrastructureFactory, pricingUtils); + this.functionId = functionId; } @Override public TransactionBody.Builder body(Bytes input, UnaryOperator aliasResolver) { - wipeOp = decodeWipe(input, aliasResolver); + wipeOp = + switch (functionId) { + case AbiConstants.ABI_WIPE_TOKEN_ACCOUNT_FUNGIBLE -> decodeWipe(input, aliasResolver); + case AbiConstants.ABI_WIPE_TOKEN_ACCOUNT_FUNGIBLE_V2 -> decodeWipeV2(input, aliasResolver); + default -> null; + }; transactionBody = syntheticTxnFactory.createWipe(wipeOp); return transactionBody; } @@ -83,7 +98,6 @@ public static WipeWrapper decodeWipe( final Bytes input, final UnaryOperator aliasResolver) { final Tuple decodedArguments = decodeFunctionCall(input, WIPE_TOKEN_ACCOUNT_SELECTOR, WIPE_TOKEN_ACCOUNT_DECODER); - final var tokenID = convertAddressBytesToTokenID(decodedArguments.get(0)); final var accountID = convertLeftPaddedAddressToAccountId(decodedArguments.get(1), aliasResolver); @@ -91,4 +105,17 @@ public static WipeWrapper decodeWipe( return WipeWrapper.forFungible(tokenID, accountID, fungibleAmount); } + + public static WipeWrapper decodeWipeV2( + final Bytes input, final UnaryOperator aliasResolver) { + final Tuple decodedArguments = + decodeFunctionCall(input, WIPE_TOKEN_ACCOUNT_SELECTOR_V2, WIPE_TOKEN_ACCOUNT_DECODER_V2); + + final var tokenID = convertAddressBytesToTokenID(decodedArguments.get(0)); + final var accountID = + convertLeftPaddedAddressToAccountId(decodedArguments.get(1), aliasResolver); + final var fungibleAmount = (int) decodedArguments.get(2); + + return WipeWrapper.forFungible(tokenID, accountID, fungibleAmount); + } } diff --git a/hedera-node/hedera-mono-service/src/test/java/com/hedera/services/store/contracts/precompile/BurnPrecompilesTest.java b/hedera-node/hedera-mono-service/src/test/java/com/hedera/services/store/contracts/precompile/BurnPrecompilesTest.java index cdf2e084c448..243e709b4029 100644 --- a/hedera-node/hedera-mono-service/src/test/java/com/hedera/services/store/contracts/precompile/BurnPrecompilesTest.java +++ b/hedera-node/hedera-mono-service/src/test/java/com/hedera/services/store/contracts/precompile/BurnPrecompilesTest.java @@ -40,6 +40,7 @@ import static com.hedera.services.store.contracts.precompile.HTSTestsUtil.targetSerialNos; import static com.hedera.services.store.contracts.precompile.HTSTestsUtil.timestamp; import static com.hedera.services.store.contracts.precompile.impl.BurnPrecompile.decodeBurn; +import static com.hedera.services.store.contracts.precompile.impl.BurnPrecompile.decodeBurnV2; import static com.hederahashgraph.api.proto.java.ResponseCodeEnum.FAIL_INVALID; import static com.hederahashgraph.api.proto.java.ResponseCodeEnum.INVALID_SIGNATURE; import static com.hederahashgraph.api.proto.java.ResponseCodeEnum.INVALID_TOKEN_ID; @@ -173,6 +174,9 @@ class BurnPrecompilesTest { private static final Bytes FUNGIBLE_BURN_INPUT = Bytes.fromHexString( "0xacb9cff90000000000000000000000000000000000000000000000000000000000000498000000000000000000000000000000000000000000000000000000000000002100000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000"); + private static final Bytes FUNGIBLE_BURN_INPUT_V2 = + Bytes.fromHexString( + "0xd6910d060000000000000000000000000000000000000000000000000000000000000498000000000000000000000000000000000000000000000000000000000000002100000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000"); private static final Bytes NON_FUNGIBLE_BURN_INPUT = Bytes.fromHexString( "0xacb9cff9000000000000000000000000000000000000000000000000000000000000049e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000007b00000000000000000000000000000000000000000000000000000000000000ea"); @@ -543,6 +547,17 @@ void decodeFungibleBurnInput() { assertEquals(FUNGIBLE_COMMON, decodedInput.type()); } + @Test + void decodeFungibleBurnInputV2() { + burnPrecompile.when(() -> decodeBurnV2(FUNGIBLE_BURN_INPUT_V2)).thenCallRealMethod(); + final var decodedInput = decodeBurnV2(FUNGIBLE_BURN_INPUT_V2); + + assertTrue(decodedInput.tokenType().getTokenNum() > 0); + assertEquals(33, decodedInput.amount()); + assertEquals(0, decodedInput.serialNos().size()); + assertEquals(FUNGIBLE_COMMON, decodedInput.type()); + } + @Test void decodeNonFungibleBurnInput() { burnPrecompile.when(() -> decodeBurn(NON_FUNGIBLE_BURN_INPUT)).thenCallRealMethod(); diff --git a/hedera-node/hedera-mono-service/src/test/java/com/hedera/services/store/contracts/precompile/CreatePrecompileTest.java b/hedera-node/hedera-mono-service/src/test/java/com/hedera/services/store/contracts/precompile/CreatePrecompileTest.java index 9b6020be2920..0d425848a39f 100644 --- a/hedera-node/hedera-mono-service/src/test/java/com/hedera/services/store/contracts/precompile/CreatePrecompileTest.java +++ b/hedera-node/hedera-mono-service/src/test/java/com/hedera/services/store/contracts/precompile/CreatePrecompileTest.java @@ -20,12 +20,16 @@ import static com.hedera.services.state.EntityCreator.EMPTY_MEMO; import static com.hedera.services.store.contracts.precompile.AbiConstants.ABI_ID_CREATE_FUNGIBLE_TOKEN; import static com.hedera.services.store.contracts.precompile.AbiConstants.ABI_ID_CREATE_FUNGIBLE_TOKEN_V2; +import static com.hedera.services.store.contracts.precompile.AbiConstants.ABI_ID_CREATE_FUNGIBLE_TOKEN_V3; import static com.hedera.services.store.contracts.precompile.AbiConstants.ABI_ID_CREATE_FUNGIBLE_TOKEN_WITH_FEES; import static com.hedera.services.store.contracts.precompile.AbiConstants.ABI_ID_CREATE_FUNGIBLE_TOKEN_WITH_FEES_V2; +import static com.hedera.services.store.contracts.precompile.AbiConstants.ABI_ID_CREATE_FUNGIBLE_TOKEN_WITH_FEES_V3; import static com.hedera.services.store.contracts.precompile.AbiConstants.ABI_ID_CREATE_NON_FUNGIBLE_TOKEN; import static com.hedera.services.store.contracts.precompile.AbiConstants.ABI_ID_CREATE_NON_FUNGIBLE_TOKEN_V2; +import static com.hedera.services.store.contracts.precompile.AbiConstants.ABI_ID_CREATE_NON_FUNGIBLE_TOKEN_V3; import static com.hedera.services.store.contracts.precompile.AbiConstants.ABI_ID_CREATE_NON_FUNGIBLE_TOKEN_WITH_FEES; import static com.hedera.services.store.contracts.precompile.AbiConstants.ABI_ID_CREATE_NON_FUNGIBLE_TOKEN_WITH_FEES_V2; +import static com.hedera.services.store.contracts.precompile.AbiConstants.ABI_ID_CREATE_NON_FUNGIBLE_TOKEN_WITH_FEES_V3; import static com.hedera.services.store.contracts.precompile.HTSTestsUtil.account; import static com.hedera.services.store.contracts.precompile.HTSTestsUtil.contractAddr; import static com.hedera.services.store.contracts.precompile.HTSTestsUtil.contractAddress; @@ -43,29 +47,39 @@ import static com.hedera.services.store.contracts.precompile.codec.TokenCreateWrapper.FixedFeeWrapper.FixedFeePayment.USE_CURRENTLY_CREATED_TOKEN; import static com.hedera.services.store.contracts.precompile.codec.TokenCreateWrapper.FixedFeeWrapper.FixedFeePayment.USE_EXISTING_FUNGIBLE_TOKEN; import static com.hedera.services.store.contracts.precompile.impl.TokenCreatePrecompile.TOKEN_CREATE_FUNGIBLE_DECODER; +import static com.hedera.services.store.contracts.precompile.impl.TokenCreatePrecompile.TOKEN_CREATE_FUNGIBLE_DECODER_V2; import static com.hedera.services.store.contracts.precompile.impl.TokenCreatePrecompile.TOKEN_CREATE_FUNGIBLE_SELECTOR; import static com.hedera.services.store.contracts.precompile.impl.TokenCreatePrecompile.TOKEN_CREATE_FUNGIBLE_SELECTOR_V2; +import static com.hedera.services.store.contracts.precompile.impl.TokenCreatePrecompile.TOKEN_CREATE_FUNGIBLE_SELECTOR_V3; import static com.hedera.services.store.contracts.precompile.impl.TokenCreatePrecompile.TOKEN_CREATE_FUNGIBLE_WITH_FEES_DECODER; import static com.hedera.services.store.contracts.precompile.impl.TokenCreatePrecompile.TOKEN_CREATE_FUNGIBLE_WITH_FEES_SELECTOR; import static com.hedera.services.store.contracts.precompile.impl.TokenCreatePrecompile.TOKEN_CREATE_FUNGIBLE_WITH_FEES_SELECTOR_V2; +import static com.hedera.services.store.contracts.precompile.impl.TokenCreatePrecompile.TOKEN_CREATE_FUNGIBLE_WITH_FEES_SELECTOR_V3; import static com.hedera.services.store.contracts.precompile.impl.TokenCreatePrecompile.TOKEN_CREATE_NON_FUNGIBLE_DECODER; import static com.hedera.services.store.contracts.precompile.impl.TokenCreatePrecompile.TOKEN_CREATE_NON_FUNGIBLE_SELECTOR; import static com.hedera.services.store.contracts.precompile.impl.TokenCreatePrecompile.TOKEN_CREATE_NON_FUNGIBLE_SELECTOR_V2; import static com.hedera.services.store.contracts.precompile.impl.TokenCreatePrecompile.TOKEN_CREATE_NON_FUNGIBLE_WITH_FEES_DECODER; +import static com.hedera.services.store.contracts.precompile.impl.TokenCreatePrecompile.TOKEN_CREATE_NON_FUNGIBLE_WITH_FEES_DECODER_V2; import static com.hedera.services.store.contracts.precompile.impl.TokenCreatePrecompile.TOKEN_CREATE_NON_FUNGIBLE_WITH_FEES_SELECTOR; import static com.hedera.services.store.contracts.precompile.impl.TokenCreatePrecompile.TOKEN_CREATE_NON_FUNGIBLE_WITH_FEES_SELECTOR_V2; +import static com.hedera.services.store.contracts.precompile.impl.TokenCreatePrecompile.TOKEN_CREATE_NON_FUNGIBLE_WITH_FEES_SELECTOR_V3; import static com.hedera.services.store.contracts.precompile.impl.TokenCreatePrecompile.decodeFixedFees; import static com.hedera.services.store.contracts.precompile.impl.TokenCreatePrecompile.decodeFractionalFees; import static com.hedera.services.store.contracts.precompile.impl.TokenCreatePrecompile.decodeFungibleCreate; import static com.hedera.services.store.contracts.precompile.impl.TokenCreatePrecompile.decodeFungibleCreateV2; +import static com.hedera.services.store.contracts.precompile.impl.TokenCreatePrecompile.decodeFungibleCreateV3; import static com.hedera.services.store.contracts.precompile.impl.TokenCreatePrecompile.decodeFungibleCreateWithFees; import static com.hedera.services.store.contracts.precompile.impl.TokenCreatePrecompile.decodeFungibleCreateWithFeesV2; +import static com.hedera.services.store.contracts.precompile.impl.TokenCreatePrecompile.decodeFungibleCreateWithFeesV3; import static com.hedera.services.store.contracts.precompile.impl.TokenCreatePrecompile.decodeNonFungibleCreate; import static com.hedera.services.store.contracts.precompile.impl.TokenCreatePrecompile.decodeNonFungibleCreateV2; +import static com.hedera.services.store.contracts.precompile.impl.TokenCreatePrecompile.decodeNonFungibleCreateV3; import static com.hedera.services.store.contracts.precompile.impl.TokenCreatePrecompile.decodeNonFungibleCreateWithFees; import static com.hedera.services.store.contracts.precompile.impl.TokenCreatePrecompile.decodeNonFungibleCreateWithFeesV2; +import static com.hedera.services.store.contracts.precompile.impl.TokenCreatePrecompile.decodeNonFungibleCreateWithFeesV3; import static com.hedera.services.store.contracts.precompile.impl.TokenCreatePrecompile.decodeRoyaltyFees; import static com.hedera.services.store.contracts.precompile.impl.TokenCreatePrecompile.decodeTokenCreateWithoutFees; +import static com.hedera.services.store.contracts.precompile.impl.TokenCreatePrecompile.decodeTokenCreateWithoutFeesV2; import static com.hederahashgraph.api.proto.java.ResponseCodeEnum.INVALID_FULL_PREFIX_SIGNATURE_FOR_PRECOMPILE; import static com.hederahashgraph.api.proto.java.ResponseCodeEnum.INVALID_SIGNATURE; import static java.util.function.UnaryOperator.identity; @@ -222,6 +236,10 @@ class CreatePrecompileTest { Bytes.fromHexString( "c23baeb600000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000007fffffffffffffff0000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001a0000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007fffffffffffffff000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000007a120000000000000000000000000000000000000000000000000000000000000000094d79546f6b656e5632000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000054d544b563200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000066d656d6f56320000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000160000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"); + private static final Bytes CREATE_FUNGIBLE_NO_FEES_INPUT_V3 = + Bytes.fromHexString( + "0x2c1e942300000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000007fffffffffffffff0000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001a0000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007fffffffffffffff000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000007a120000000000000000000000000000000000000000000000000000000000000000094d79546f6b656e5632000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000054d544b563200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000066d656d6f56320000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000160000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"); + private static final Bytes CREATE_FUNGIBLE_WITH_FEES_INPUT = Bytes.fromHexString( "0x4c381ae700000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000c8000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000005600000000000000000000000000000000000000000000000000000000000000620000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001a0000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000015b200000000000000000000000000000000000000000000000000000000000000074d79546f6b656e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000034d544b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000046d656d6f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000160000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000037000000000000000000000000000000000000000000000000000000000000006400000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000003"); @@ -230,6 +248,10 @@ class CreatePrecompileTest { Bytes.fromHexString( "0xb937581a00000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000007fffffffffffffff000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000005600000000000000000000000000000000000000000000000000000000000000620000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001a0000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007fffffffffffffff000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000007a120000000000000000000000000000000000000000000000000000000000000000094d79546f6b656e5632000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000054d544b563200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000066d656d6f56320000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000160000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001"); + private static final Bytes CREATE_FUNGIBLE_WITH_FEES_INPUT_V3 = + Bytes.fromHexString( + "0x6daa94d800000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000007fffffffffffffff000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000005600000000000000000000000000000000000000000000000000000000000000620000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001a0000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007fffffffffffffff000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000007a120000000000000000000000000000000000000000000000000000000000000000094d79546f6b656e5632000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000054d544b563200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000066d656d6f56320000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000160000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001"); + private static final Bytes CREATE_NON_FUNGIBLE_NO_FEES_INPUT = Bytes.fromHexString( "0x9dc711e00000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001a0000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000037000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000004071b890000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000054d794e465400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000034e4654000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000076e66744d656d6f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"); @@ -246,6 +268,10 @@ class CreatePrecompileTest { Bytes.fromHexString( "0x457339690000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000052000000000000000000000000000000000000000000000000000000000000005e0000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001a0000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000007fffffffffffffff000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000007a120000000000000000000000000000000000000000000000000000000000000000074d794e465456320000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000054e4654563200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000096e66744d656d6f56320000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000160000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002"); + private static final Bytes CREATE_NON_FUNGIBLE_WITH_FEES_INPUT_V3 = + Bytes.fromHexString( + "0x3eed0a290000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000052000000000000000000000000000000000000000000000000000000000000005e0000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001a0000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000007fffffffffffffff000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000007a120000000000000000000000000000000000000000000000000000000000000000074d794e465456320000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000054e4654563200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000096e66744d656d6f56320000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000160000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002"); + private static final Bytes CREATE_FUNGIBLE_WITH_FEES_INPUT_NULL_ACCOUNTS = Bytes.fromHexString( "0x4c381ae700000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000c8000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000005600000000000000000000000000000000000000000000000000000000000000620000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000001a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000015b200000000000000000000000000000000000000000000000000000000000000074d79546f6b656e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000034d544b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000046d656d6f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000160000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000037000000000000000000000000000000000000000000000000000000000000006400000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000"); @@ -541,6 +567,41 @@ void createFungibleV2HappyPathWorks() { prepareAndAssertCreateHappyPathSucceeds(tokenCreateWrapper, pretendArguments); } + @Test + void createFungibleV3HappyPathWorks() { + // test-specific preparations + given(infrastructureFactory.newSideEffects()).willReturn(sideEffects); + given(worldUpdater.permissivelyUnaliased(any())) + .willAnswer(invocationOnMock -> invocationOnMock.getArgument(0)); + final var tokenCreateWrapper = + createTokenCreateWrapperWithKeys( + List.of( + new TokenKeyWrapper( + 1, + new KeyValueWrapper( + false, + EntityIdUtils.contractIdFromEvmAddress( + contractAddress), + new byte[] {}, + new byte[] {}, + null)), + new TokenKeyWrapper( + 8, + new KeyValueWrapper( + false, + null, + new byte[] {}, + new byte[] {}, + EntityIdUtils.contractIdFromEvmAddress( + contractAddress))))); + Bytes pretendArguments = Bytes.of(Integers.toBytes(ABI_ID_CREATE_FUNGIBLE_TOKEN_V3)); + tokenCreatePrecompile + .when(() -> decodeFungibleCreateV3(eq(pretendArguments), any())) + .thenReturn(tokenCreateWrapper); + + prepareAndAssertCreateHappyPathSucceeds(tokenCreateWrapper, pretendArguments); + } + @Test void createFungibleWithFeesV2HappyPathWorks() { // test-specific preparations @@ -570,6 +631,35 @@ void createFungibleWithFeesV2HappyPathWorks() { prepareAndAssertCreateHappyPathSucceeds(tokenCreateWrapper, pretendArguments); } + @Test + void createFungibleWithFeesV3HappyPathWorks() { + // test-specific preparations + given(infrastructureFactory.newSideEffects()).willReturn(sideEffects); + given(worldUpdater.permissivelyUnaliased(any())) + .willAnswer(invocationOnMock -> invocationOnMock.getArgument(0)); + final var tokenCreateWrapper = + createTokenCreateWrapperWithKeys( + List.of( + new TokenKeyWrapper( + 1, + new KeyValueWrapper( + false, + null, + new byte[] {}, + new byte[] {}, + EntityIdUtils.contractIdFromEvmAddress( + contractAddress))))); + tokenCreateWrapper.setFixedFees(List.of(fixedFee)); + tokenCreateWrapper.setFractionalFees(List.of(HTSTestsUtil.fractionalFee)); + Bytes pretendArguments = + Bytes.of(Integers.toBytes(ABI_ID_CREATE_FUNGIBLE_TOKEN_WITH_FEES_V3)); + tokenCreatePrecompile + .when(() -> decodeFungibleCreateWithFeesV3(eq(pretendArguments), any())) + .thenReturn(tokenCreateWrapper); + + prepareAndAssertCreateHappyPathSucceeds(tokenCreateWrapper, pretendArguments); + } + @Test void createNonFungibleV2HappyPathWorks() { // test-specific preparations @@ -601,6 +691,37 @@ void createNonFungibleV2HappyPathWorks() { prepareAndAssertCreateHappyPathSucceeds(tokenCreateWrapper, pretendArguments); } + @Test + void createNonFungibleV3HappyPathWorks() { + // test-specific preparations + given(infrastructureFactory.newSideEffects()).willReturn(sideEffects); + given(worldUpdater.permissivelyUnaliased(any())) + .willAnswer(invocationOnMock -> invocationOnMock.getArgument(0)); + final var tokenCreateWrapper = + createNonFungibleTokenCreateWrapperWithKeys( + List.of( + new TokenKeyWrapper( + 1, + new KeyValueWrapper( + false, + null, + new byte[] {}, + new byte + [JECDSASecp256k1Key + .ECDSA_SECP256K1_COMPRESSED_KEY_LENGTH], + null)))); + Bytes pretendArguments = Bytes.of(Integers.toBytes(ABI_ID_CREATE_NON_FUNGIBLE_TOKEN_V3)); + tokenCreatePrecompile + .when(() -> decodeNonFungibleCreateV3(eq(pretendArguments), any())) + .thenReturn(tokenCreateWrapper); + given(wrappedLedgers.accounts()).willReturn(accounts); + given(accounts.get(any(), eq(AUTO_RENEW_ACCOUNT_ID))) + .willReturn(EntityId.fromGrpcAccountId(account)); + given(sigsVerifier.cryptoKeyIsActive(any())).willReturn(true); + + prepareAndAssertCreateHappyPathSucceeds(tokenCreateWrapper, pretendArguments); + } + @Test void createNonFungibleV2WithFeesHappyPathWorks() { // test-specific preparations @@ -632,6 +753,37 @@ void createNonFungibleV2WithFeesHappyPathWorks() { prepareAndAssertCreateHappyPathSucceeds(tokenCreateWrapper, pretendArguments); } + @Test + void createNonFungibleV3WithFeesHappyPathWorks() { + // test-specific preparations + given(infrastructureFactory.newSideEffects()).willReturn(sideEffects); + given(worldUpdater.permissivelyUnaliased(any())) + .willAnswer(invocationOnMock -> invocationOnMock.getArgument(0)); + final var tokenCreateWrapper = + createNonFungibleTokenCreateWrapperWithKeys( + List.of( + new TokenKeyWrapper( + 1, + new KeyValueWrapper( + true, null, new byte[] {}, new byte[] {}, null)))); + tokenCreateWrapper.setFixedFees(List.of(fixedFee)); + tokenCreateWrapper.setRoyaltyFees(List.of(HTSTestsUtil.royaltyFee)); + Bytes pretendArguments = + Bytes.of(Integers.toBytes(ABI_ID_CREATE_NON_FUNGIBLE_TOKEN_WITH_FEES_V3)); + given(wrappedLedgers.accounts()).willReturn(accounts); + given(accounts.get(any(), eq(AUTO_RENEW_ACCOUNT_ID))) + .willReturn(EntityId.fromGrpcAccountId(account)); + tokenCreatePrecompile + .when(() -> decodeNonFungibleCreateWithFeesV3(eq(pretendArguments), any())) + .thenReturn(tokenCreateWrapper); + given(accounts.get(any(), eq(KEY))) + .willReturn( + new JContractIDKey( + EntityIdUtils.contractIdFromEvmAddress(contractAddress))); + + prepareAndAssertCreateHappyPathSucceeds(tokenCreateWrapper, pretendArguments); + } + @Test void createFailurePath() { given(infrastructureFactory.newSideEffects()).willReturn(sideEffects); @@ -1353,6 +1505,36 @@ void decodeFungibleCreateNoFeesInputV2() { assertExpectedFungibleTokenCreateStructV2(decodedInput); } + @Test + void decodeFungibleCreateNoFeesInputV3() { + final Tuple decodedArguments = + decodeFunctionCall( + CREATE_FUNGIBLE_NO_FEES_INPUT_V3, + TOKEN_CREATE_FUNGIBLE_SELECTOR_V3, + TOKEN_CREATE_FUNGIBLE_DECODER_V2); + tokenCreatePrecompile + .when(() -> decodeFungibleCreateV3(CREATE_FUNGIBLE_NO_FEES_INPUT_V3, identity())) + .thenCallRealMethod(); + tokenCreatePrecompile + .when( + () -> + decodeTokenCreateWithoutFeesV2( + decodedArguments.get(0), + true, + decodedArguments.get(1), + decodedArguments.get(2), + identity())) + .thenCallRealMethod(); + final var decodedInput = + decodeFungibleCreateV3(CREATE_FUNGIBLE_NO_FEES_INPUT_V3, identity()); + + assertEquals(BigInteger.valueOf(9223372036854775807L), decodedInput.getInitSupply()); + assertEquals(BigInteger.valueOf(4), decodedInput.getDecimals()); + assertExpectedKeys(decodedInput); + + assertExpectedFungibleTokenCreateStructV2(decodedInput); + } + @Test void decodeFungibleCreateWithFeesInputV2() { final Tuple decodedArguments = @@ -1417,6 +1599,70 @@ CREATE_FUNGIBLE_WITH_FEES_INPUT_V2, identity())) fractionalFeeWrapper.feeCollector()); } + @Test + void decodeFungibleCreateWithFeesInputV3() { + final Tuple decodedArguments = + decodeFunctionCall( + CREATE_FUNGIBLE_WITH_FEES_INPUT_V3, + TOKEN_CREATE_FUNGIBLE_WITH_FEES_SELECTOR_V3, + TOKEN_CREATE_FUNGIBLE_WITH_FEES_DECODER); + tokenCreatePrecompile + .when( + () -> + decodeFungibleCreateWithFeesV3( + CREATE_FUNGIBLE_WITH_FEES_INPUT_V3, identity())) + .thenCallRealMethod(); + tokenCreatePrecompile + .when( + () -> + decodeTokenCreateWithoutFees( + decodedArguments.get(0), + true, + decodedArguments.get(1), + decodedArguments.get(2), + identity())) + .thenCallRealMethod(); + tokenCreatePrecompile + .when(() -> decodeFixedFees(decodedArguments.get(3), identity())) + .thenCallRealMethod(); + tokenCreatePrecompile + .when(() -> decodeFractionalFees(decodedArguments.get(4), identity())) + .thenCallRealMethod(); + final var decodedInput = + decodeFungibleCreateWithFeesV3(CREATE_FUNGIBLE_WITH_FEES_INPUT_V3, identity()); + + assertExpectedFungibleTokenCreateStructV2(decodedInput); + + assertEquals(decodedInput.getInitSupply(), BigInteger.valueOf(9223372036854775807L)); + assertEquals(decodedInput.getDecimals(), BigInteger.valueOf(4)); + assertExpectedKeys(decodedInput); + + final var fixedFees = decodedInput.getFixedFees(); + assertEquals(1, fixedFees.size()); + final var fixedFeeWrapper = fixedFees.get(0); + assertEquals(USE_EXISTING_FUNGIBLE_TOKEN, fixedFeeWrapper.getFixedFeePayment()); + final var customFee = fixedFeeWrapper.asGrpc(); + assertEquals(0, customFee.getFixedFee().getAmount()); + assertEquals( + TokenID.newBuilder().setTokenNum(1).setRealmNum(0).setShardNum(0).build(), + customFee.getFixedFee().getDenominatingTokenId()); + assertEquals( + AccountID.newBuilder().setAccountNum(1).build(), + customFee.getFeeCollectorAccountId()); + + final var fractionalFees = decodedInput.getFractionalFees(); + assertEquals(1, fractionalFees.size()); + final var fractionalFeeWrapper = fractionalFees.get(0); + assertEquals(1, fractionalFeeWrapper.numerator()); + assertEquals(1, fractionalFeeWrapper.denominator()); + assertEquals(1, fractionalFeeWrapper.minimumAmount()); + assertEquals(1, fractionalFeeWrapper.maximumAmount()); + assertFalse(fractionalFeeWrapper.netOfTransfers()); + assertEquals( + AccountID.newBuilder().setAccountNum(1).build(), + fractionalFeeWrapper.feeCollector()); + } + @Test void decodeNonFungibleCreateNoFeesInputV2() { final Tuple decodedArguments = @@ -1536,6 +1782,81 @@ CREATE_NON_FUNGIBLE_WITH_FEES_INPUT_V2, identity())) AccountID.newBuilder().setAccountNum(2).build(), royaltyFeeWrapper.feeCollector()); } + @Test + void decodeNonFungibleCreateWithFeesInputV3() { + final Tuple decodedArguments = + decodeFunctionCall( + CREATE_NON_FUNGIBLE_WITH_FEES_INPUT_V3, + TOKEN_CREATE_NON_FUNGIBLE_WITH_FEES_SELECTOR_V3, + TOKEN_CREATE_NON_FUNGIBLE_WITH_FEES_DECODER_V2); + tokenCreatePrecompile + .when( + () -> + decodeNonFungibleCreateWithFeesV3( + CREATE_NON_FUNGIBLE_WITH_FEES_INPUT_V3, identity())) + .thenCallRealMethod(); + tokenCreatePrecompile + .when( + () -> + decodeTokenCreateWithoutFees( + decodedArguments.get(0), + false, + BigInteger.ZERO, + BigInteger.ZERO, + identity())) + .thenCallRealMethod(); + tokenCreatePrecompile + .when(() -> decodeFixedFees(decodedArguments.get(1), identity())) + .thenCallRealMethod(); + tokenCreatePrecompile + .when(() -> decodeRoyaltyFees(decodedArguments.get(2), identity())) + .thenCallRealMethod(); + final var decodedInput = + decodeNonFungibleCreateWithFeesV3( + CREATE_NON_FUNGIBLE_WITH_FEES_INPUT_V3, identity()); + + assertFalse(decodedInput.isFungible()); + assertEquals("MyNFTV2", decodedInput.getName()); + assertEquals("NFTV2", decodedInput.getSymbol()); + assertEquals(AccountID.newBuilder().setAccountNum(1L).build(), decodedInput.getTreasury()); + assertEquals("nftMemoV2", decodedInput.getMemo()); + assertTrue(decodedInput.isSupplyTypeFinite()); + assertEquals(9223372036854775807L, decodedInput.getMaxSupply()); + assertFalse(decodedInput.isFreezeDefault()); + assertEquals(0L, decodedInput.getExpiry().second()); + assertEquals(8000000L, decodedInput.getExpiry().autoRenewPeriod()); + assertEquals( + AccountID.newBuilder().setAccountNum(4L).build(), + decodedInput.getExpiry().autoRenewAccount()); + assertEquals(BigInteger.valueOf(0), decodedInput.getInitSupply()); + assertEquals(BigInteger.valueOf(0), decodedInput.getDecimals()); + assertExpectedKeys(decodedInput); + + final var fixedFees = decodedInput.getFixedFees(); + assertEquals(1, fixedFees.size()); + final var fixedFeeWrapper = fixedFees.get(0); + assertEquals(USE_EXISTING_FUNGIBLE_TOKEN, fixedFeeWrapper.getFixedFeePayment()); + final var customFee = fixedFeeWrapper.asGrpc(); + assertEquals(0, customFee.getFixedFee().getAmount()); + assertEquals( + TokenID.newBuilder().setTokenNum(1).build(), + customFee.getFixedFee().getDenominatingTokenId()); + assertEquals( + AccountID.newBuilder().setAccountNum(1).build(), + customFee.getFeeCollectorAccountId()); + + final var royaltyFees = decodedInput.getRoyaltyFees(); + assertEquals(1, royaltyFees.size()); + final var royaltyFeeWrapper = royaltyFees.get(0); + assertEquals(1, royaltyFeeWrapper.numerator()); + assertEquals(2, royaltyFeeWrapper.denominator()); + final var actualFallbackFee = royaltyFeeWrapper.fallbackFixedFee().asGrpc(); + assertEquals(3, actualFallbackFee.getFixedFee().getAmount()); + assertTrue(actualFallbackFee.getFixedFee().hasDenominatingTokenId()); + assertEquals( + AccountID.newBuilder().setAccountNum(2).build(), royaltyFeeWrapper.feeCollector()); + } + private void assertExpectedFungibleTokenCreateStructV2(final TokenCreateWrapper decodedInput) { assertTrue(decodedInput.isFungible()); assertEquals("MyTokenV2", decodedInput.getName()); diff --git a/hedera-node/hedera-mono-service/src/test/java/com/hedera/services/store/contracts/precompile/HTSPrecompiledContractTest.java b/hedera-node/hedera-mono-service/src/test/java/com/hedera/services/store/contracts/precompile/HTSPrecompiledContractTest.java index 46561ef1de8c..12b56d9c400d 100644 --- a/hedera-node/hedera-mono-service/src/test/java/com/hedera/services/store/contracts/precompile/HTSPrecompiledContractTest.java +++ b/hedera-node/hedera-mono-service/src/test/java/com/hedera/services/store/contracts/precompile/HTSPrecompiledContractTest.java @@ -16,9 +16,48 @@ package com.hedera.services.store.contracts.precompile; import static com.hedera.services.contracts.execution.HederaMessageCallProcessor.INVALID_TRANSFER; -import static com.hedera.services.store.contracts.precompile.AbiConstants.*; import static com.hedera.services.store.contracts.precompile.ERC20PrecompilesTest.CRYPTO_TRANSFER_TOKEN_FROM_NFT_WRAPPER; import static com.hedera.services.store.contracts.precompile.ERC20PrecompilesTest.CRYPTO_TRANSFER_TOKEN_FROM_WRAPPER; +import static com.hedera.services.store.contracts.precompile.AbiConstants.ABI_ID_ASSOCIATE_TOKEN; +import static com.hedera.services.store.contracts.precompile.AbiConstants.ABI_ID_ASSOCIATE_TOKENS; +import static com.hedera.services.store.contracts.precompile.AbiConstants.ABI_ID_BURN_TOKEN; +import static com.hedera.services.store.contracts.precompile.AbiConstants.ABI_ID_BURN_TOKEN_V2; +import static com.hedera.services.store.contracts.precompile.AbiConstants.ABI_ID_CREATE_FUNGIBLE_TOKEN; +import static com.hedera.services.store.contracts.precompile.AbiConstants.ABI_ID_CREATE_FUNGIBLE_TOKEN_V2; +import static com.hedera.services.store.contracts.precompile.AbiConstants.ABI_ID_CREATE_FUNGIBLE_TOKEN_V3; +import static com.hedera.services.store.contracts.precompile.AbiConstants.ABI_ID_CREATE_FUNGIBLE_TOKEN_WITH_FEES; +import static com.hedera.services.store.contracts.precompile.AbiConstants.ABI_ID_CREATE_FUNGIBLE_TOKEN_WITH_FEES_V2; +import static com.hedera.services.store.contracts.precompile.AbiConstants.ABI_ID_CREATE_FUNGIBLE_TOKEN_WITH_FEES_V3; +import static com.hedera.services.store.contracts.precompile.AbiConstants.ABI_ID_CREATE_NON_FUNGIBLE_TOKEN; +import static com.hedera.services.store.contracts.precompile.AbiConstants.ABI_ID_CREATE_NON_FUNGIBLE_TOKEN_V2; +import static com.hedera.services.store.contracts.precompile.AbiConstants.ABI_ID_CREATE_NON_FUNGIBLE_TOKEN_V3; +import static com.hedera.services.store.contracts.precompile.AbiConstants.ABI_ID_CREATE_NON_FUNGIBLE_TOKEN_WITH_FEES; +import static com.hedera.services.store.contracts.precompile.AbiConstants.ABI_ID_CREATE_NON_FUNGIBLE_TOKEN_WITH_FEES_V2; +import static com.hedera.services.store.contracts.precompile.AbiConstants.ABI_ID_CREATE_NON_FUNGIBLE_TOKEN_WITH_FEES_V3; +import static com.hedera.services.store.contracts.precompile.AbiConstants.ABI_ID_CRYPTO_TRANSFER; +import static com.hedera.services.store.contracts.precompile.AbiConstants.ABI_ID_CRYPTO_TRANSFER_V2; +import static com.hedera.services.store.contracts.precompile.AbiConstants.ABI_ID_DISSOCIATE_TOKEN; +import static com.hedera.services.store.contracts.precompile.AbiConstants.ABI_ID_DISSOCIATE_TOKENS; +import static com.hedera.services.store.contracts.precompile.AbiConstants.ABI_ID_ERC_NAME; +import static com.hedera.services.store.contracts.precompile.AbiConstants.ABI_ID_GET_TOKEN_CUSTOM_FEES; +import static com.hedera.services.store.contracts.precompile.AbiConstants.ABI_ID_GET_TOKEN_EXPIRY_INFO; +import static com.hedera.services.store.contracts.precompile.AbiConstants.ABI_ID_GET_TOKEN_INFO; +import static com.hedera.services.store.contracts.precompile.AbiConstants.ABI_ID_MINT_TOKEN; +import static com.hedera.services.store.contracts.precompile.AbiConstants.ABI_ID_MINT_TOKEN_V2; +import static com.hedera.services.store.contracts.precompile.AbiConstants.ABI_ID_PAUSE_TOKEN; +import static com.hedera.services.store.contracts.precompile.AbiConstants.ABI_ID_REDIRECT_FOR_TOKEN; +import static com.hedera.services.store.contracts.precompile.AbiConstants.ABI_ID_TRANSFER_FROM; +import static com.hedera.services.store.contracts.precompile.AbiConstants.ABI_ID_TRANSFER_FROM_NFT; +import static com.hedera.services.store.contracts.precompile.AbiConstants.ABI_ID_TRANSFER_NFT; +import static com.hedera.services.store.contracts.precompile.AbiConstants.ABI_ID_TRANSFER_NFTS; +import static com.hedera.services.store.contracts.precompile.AbiConstants.ABI_ID_TRANSFER_TOKEN; +import static com.hedera.services.store.contracts.precompile.AbiConstants.ABI_ID_TRANSFER_TOKENS; +import static com.hedera.services.store.contracts.precompile.AbiConstants.ABI_ID_UNPAUSE_TOKEN; +import static com.hedera.services.store.contracts.precompile.AbiConstants.ABI_ID_UPDATE_TOKEN_EXPIRY_INFO; +import static com.hedera.services.store.contracts.precompile.AbiConstants.ABI_ID_UPDATE_TOKEN_EXPIRY_INFO_V2; +import static com.hedera.services.store.contracts.precompile.AbiConstants.ABI_WIPE_TOKEN_ACCOUNT_FUNGIBLE; +import static com.hedera.services.store.contracts.precompile.AbiConstants.ABI_WIPE_TOKEN_ACCOUNT_FUNGIBLE_V2; +import static com.hedera.services.store.contracts.precompile.AbiConstants.ABI_WIPE_TOKEN_ACCOUNT_NFT; import static com.hedera.services.store.contracts.precompile.HTSTestsUtil.TEST_CONSENSUS_TIME; import static com.hedera.services.store.contracts.precompile.HTSTestsUtil.associateOp; import static com.hedera.services.store.contracts.precompile.HTSTestsUtil.contractAddress; @@ -39,9 +78,13 @@ import static com.hedera.services.store.contracts.precompile.HTSTestsUtil.timestamp; import static com.hedera.services.store.contracts.precompile.HTSTestsUtil.tokenUpdateExpiryInfoWrapper; import static com.hedera.services.store.contracts.precompile.impl.TokenCreatePrecompile.decodeFungibleCreateV2; +import static com.hedera.services.store.contracts.precompile.impl.TokenCreatePrecompile.decodeFungibleCreateV3; import static com.hedera.services.store.contracts.precompile.impl.TokenCreatePrecompile.decodeFungibleCreateWithFeesV2; +import static com.hedera.services.store.contracts.precompile.impl.TokenCreatePrecompile.decodeFungibleCreateWithFeesV3; import static com.hedera.services.store.contracts.precompile.impl.TokenCreatePrecompile.decodeNonFungibleCreateV2; +import static com.hedera.services.store.contracts.precompile.impl.TokenCreatePrecompile.decodeNonFungibleCreateV3; import static com.hedera.services.store.contracts.precompile.impl.TokenCreatePrecompile.decodeNonFungibleCreateWithFeesV2; +import static com.hedera.services.store.contracts.precompile.impl.TokenCreatePrecompile.decodeNonFungibleCreateWithFeesV3; import static org.hyperledger.besu.evm.frame.MessageFrame.State.REVERT; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNull; @@ -498,12 +541,44 @@ void computeCallsCorrectImplementationForMintToken() { assertTrue(subject.getPrecompile() instanceof MintPrecompile); } + @Test + void computeCallsCorrectImplementationForMintTokenV2() { + // given + givenFrameContext(); + Bytes input = Bytes.of(Integers.toBytes(ABI_ID_MINT_TOKEN_V2)); + mintPrecompile.when(() -> MintPrecompile.decodeMintV2(any())).thenReturn(fungibleMint); + given(worldUpdater.permissivelyUnaliased(any())) + .willAnswer(invocationOnMock -> invocationOnMock.getArgument(0)); + + // when + subject.prepareFields(messageFrame); + subject.prepareComputation(input, a -> a); + + // then + assertTrue(subject.getPrecompile() instanceof MintPrecompile); + } + @Test void computeCallsCorrectImplementationForBurnToken() { // given givenFrameContext(); Bytes input = Bytes.of(Integers.toBytes(ABI_ID_BURN_TOKEN)); - // given(decoder.decodeBurn(any())).willReturn(fungibleBurn); + given(worldUpdater.permissivelyUnaliased(any())) + .willAnswer(invocationOnMock -> invocationOnMock.getArgument(0)); + + // when + subject.prepareFields(messageFrame); + subject.prepareComputation(input, a -> a); + + // then + assertTrue(subject.getPrecompile() instanceof BurnPrecompile); + } + + @Test + void computeCallsCorrectImplementationForBurnTokenV2() { + // given + givenFrameContext(); + Bytes input = Bytes.of(Integers.toBytes(ABI_ID_BURN_TOKEN_V2)); given(worldUpdater.permissivelyUnaliased(any())) .willAnswer(invocationOnMock -> invocationOnMock.getArgument(0)); @@ -645,6 +720,19 @@ void computeCallsCorrectImplementationForCreateFungibleTokenWithFeesV2() { prepareAndAssertCorrectInstantiationOfTokenCreatePrecompile(input); } + @Test + void computeCallsCorrectImplementationForCreateFungibleTokenWithFeesV3() { + // given + Bytes input = Bytes.of(Integers.toBytes(ABI_ID_CREATE_FUNGIBLE_TOKEN_WITH_FEES_V3)); + tokenCreatePrecompile + .when(() -> decodeFungibleCreateWithFeesV3(any(), any())) + .thenReturn(createTokenCreateWrapperWithKeys(Collections.emptyList())); + given(worldUpdater.permissivelyUnaliased(any())) + .willAnswer(invocationOnMock -> invocationOnMock.getArgument(0)); + + prepareAndAssertCorrectInstantiationOfTokenCreatePrecompile(input); + } + @Test void computeCallsCorrectImplementationForCreateNonFungibleTokenWithFeesV2() { // given @@ -658,6 +746,19 @@ void computeCallsCorrectImplementationForCreateNonFungibleTokenWithFeesV2() { prepareAndAssertCorrectInstantiationOfTokenCreatePrecompile(input); } + @Test + void computeCallsCorrectImplementationForCreateNonFungibleTokenWithFeesV3() { + // given + Bytes input = Bytes.of(Integers.toBytes(ABI_ID_CREATE_NON_FUNGIBLE_TOKEN_WITH_FEES_V3)); + tokenCreatePrecompile + .when(() -> decodeNonFungibleCreateWithFeesV3(any(), any())) + .thenReturn(createTokenCreateWrapperWithKeys(Collections.emptyList())); + given(worldUpdater.permissivelyUnaliased(any())) + .willAnswer(invocationOnMock -> invocationOnMock.getArgument(0)); + + prepareAndAssertCorrectInstantiationOfTokenCreatePrecompile(input); + } + @Test void computeCallsCorrectImplementationForCreateFungibleTokenV2() { // given @@ -671,6 +772,19 @@ void computeCallsCorrectImplementationForCreateFungibleTokenV2() { prepareAndAssertCorrectInstantiationOfTokenCreatePrecompile(input); } + @Test + void computeCallsCorrectImplementationForCreateFungibleTokenV3() { + // given + Bytes input = Bytes.of(Integers.toBytes(ABI_ID_CREATE_FUNGIBLE_TOKEN_V3)); + tokenCreatePrecompile + .when(() -> decodeFungibleCreateV3(any(), any())) + .thenReturn(createTokenCreateWrapperWithKeys(Collections.emptyList())); + given(worldUpdater.permissivelyUnaliased(any())) + .willAnswer(invocationOnMock -> invocationOnMock.getArgument(0)); + + prepareAndAssertCorrectInstantiationOfTokenCreatePrecompile(input); + } + @Test void computeCallsCorrectImplementationForCreateNonFungibleTokenV2() { // given @@ -684,6 +798,19 @@ void computeCallsCorrectImplementationForCreateNonFungibleTokenV2() { prepareAndAssertCorrectInstantiationOfTokenCreatePrecompile(input); } + @Test + void computeCallsCorrectImplementationForCreateNonFungibleTokenV3() { + // given + Bytes input = Bytes.of(Integers.toBytes(ABI_ID_CREATE_NON_FUNGIBLE_TOKEN_V3)); + tokenCreatePrecompile + .when(() -> decodeNonFungibleCreateV3(any(), any())) + .thenReturn(createTokenCreateWrapperWithKeys(Collections.emptyList())); + given(worldUpdater.permissivelyUnaliased(any())) + .willAnswer(invocationOnMock -> invocationOnMock.getArgument(0)); + + prepareAndAssertCorrectInstantiationOfTokenCreatePrecompile(input); + } + @Test void computeCallsCorrectImplementationForCreateFungibleTokenWithFees() { // given @@ -1051,6 +1178,25 @@ void computeCallsCorrectImplementationForWipeFungibleToken() { assertTrue(subject.getPrecompile() instanceof WipeFungiblePrecompile); } + @Test + void computeCallsCorrectImplementationForWipeFungibleTokenV2() { + // given + givenFrameContext(); + Bytes input = Bytes.of(Integers.toBytes(ABI_WIPE_TOKEN_ACCOUNT_FUNGIBLE_V2)); + wipeFungiblePrecompile + .when(() -> WipeFungiblePrecompile.decodeWipeV2(any(), any())) + .thenReturn(fungibleWipe); + given(worldUpdater.permissivelyUnaliased(any())) + .willAnswer(invocationOnMock -> invocationOnMock.getArgument(0)); + + // when + subject.prepareFields(messageFrame); + subject.prepareComputation(input, a -> a); + + // then + assertTrue(subject.getPrecompile() instanceof WipeFungiblePrecompile); + } + @Test void computeCallsCorrectImplementationForWipeNonFungibleToken() { // given @@ -1130,6 +1276,28 @@ void computeCallsCorrectImplementationForUpdateExpiryInfoForToken() { assertTrue(subject.getPrecompile() instanceof UpdateTokenExpiryInfoPrecompile); } + @Test + void computeCallsCorrectImplementationForUpdateExpiryInfoV2() { + // given + givenFrameContext(); + Bytes input = Bytes.of(Integers.toBytes(ABI_ID_UPDATE_TOKEN_EXPIRY_INFO_V2)); + updateTokenExpiryInfoPrecompile + .when( + () -> + UpdateTokenExpiryInfoPrecompile.decodeUpdateTokenExpiryInfoV2( + any(), any())) + .thenReturn(tokenUpdateExpiryInfoWrapper); + given(worldUpdater.permissivelyUnaliased(any())) + .willAnswer(invocationOnMock -> invocationOnMock.getArgument(0)); + + // when + subject.prepareFields(messageFrame); + subject.prepareComputation(input, a -> a); + + // then + assertTrue(subject.getPrecompile() instanceof UpdateTokenExpiryInfoPrecompile); + } + private void givenFrameContext() { given(messageFrame.getSenderAddress()).willReturn(contractAddress); given(messageFrame.getWorldUpdater()).willReturn(worldUpdater); diff --git a/hedera-node/hedera-mono-service/src/test/java/com/hedera/services/store/contracts/precompile/MintPrecompilesTest.java b/hedera-node/hedera-mono-service/src/test/java/com/hedera/services/store/contracts/precompile/MintPrecompilesTest.java index 1d3d77442184..2bd4b2129738 100644 --- a/hedera-node/hedera-mono-service/src/test/java/com/hedera/services/store/contracts/precompile/MintPrecompilesTest.java +++ b/hedera-node/hedera-mono-service/src/test/java/com/hedera/services/store/contracts/precompile/MintPrecompilesTest.java @@ -41,6 +41,7 @@ import static com.hedera.services.store.contracts.precompile.HTSTestsUtil.successResult; import static com.hedera.services.store.contracts.precompile.HTSTestsUtil.timestamp; import static com.hedera.services.store.contracts.precompile.impl.MintPrecompile.decodeMint; +import static com.hedera.services.store.contracts.precompile.impl.MintPrecompile.decodeMintV2; import static com.hedera.test.utils.TxnUtils.assertFailsWith; import static com.hederahashgraph.api.proto.java.ResponseCodeEnum.FAIL_INVALID; import static com.hederahashgraph.api.proto.java.ResponseCodeEnum.INVALID_SIGNATURE; @@ -175,6 +176,9 @@ class MintPrecompilesTest { private static final Bytes FUNGIBLE_MINT_INPUT = Bytes.fromHexString( "0x278e0b88000000000000000000000000000000000000000000000000000000000000043e000000000000000000000000000000000000000000000000000000000000000f00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000"); + private static final Bytes FUNGIBLE_MINT_INPUT_V2 = + Bytes.fromHexString( + "0xe0f4059a000000000000000000000000000000000000000000000000000000000000043e000000000000000000000000000000000000000000000000000000000000000f00000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000000"); private static final Bytes NON_FUNGIBLE_MINT_INPUT = Bytes.fromHexString( "0x278e0b88000000000000000000000000000000000000000000000000000000000000042e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000124e4654206d65746164617461207465737431000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000124e4654206d657461646174612074657374320000000000000000000000000000"); @@ -581,6 +585,16 @@ void decodeFungibleMintInput() { assertEquals(FUNGIBLE_COMMON, decodedInput.type()); } + @Test + void decodeFungibleMintInputV2() { + mintPrecompile.when(() -> decodeMintV2(FUNGIBLE_MINT_INPUT_V2)).thenCallRealMethod(); + final var decodedInput = decodeMintV2(FUNGIBLE_MINT_INPUT_V2); + + assertTrue(decodedInput.tokenType().getTokenNum() > 0); + assertEquals(15, decodedInput.amount()); + assertEquals(FUNGIBLE_COMMON, decodedInput.type()); + } + @Test void decodeNonFungibleMintInput() { mintPrecompile.when(() -> decodeMint(NON_FUNGIBLE_MINT_INPUT)).thenCallRealMethod(); diff --git a/hedera-node/hedera-mono-service/src/test/java/com/hedera/services/store/contracts/precompile/TokenUpdatePrecompileTest.java b/hedera-node/hedera-mono-service/src/test/java/com/hedera/services/store/contracts/precompile/TokenUpdatePrecompileTest.java index 0a3c1d97a011..9c542568ef2c 100644 --- a/hedera-node/hedera-mono-service/src/test/java/com/hedera/services/store/contracts/precompile/TokenUpdatePrecompileTest.java +++ b/hedera-node/hedera-mono-service/src/test/java/com/hedera/services/store/contracts/precompile/TokenUpdatePrecompileTest.java @@ -18,6 +18,7 @@ import static com.hedera.services.state.EntityCreator.EMPTY_MEMO; import static com.hedera.services.store.contracts.precompile.AbiConstants.ABI_ID_UPDATE_TOKEN_INFO; import static com.hedera.services.store.contracts.precompile.AbiConstants.ABI_ID_UPDATE_TOKEN_INFO_V2; +import static com.hedera.services.store.contracts.precompile.AbiConstants.ABI_ID_UPDATE_TOKEN_INFO_V3; import static com.hedera.services.store.contracts.precompile.HTSTestsUtil.contractAddr; import static com.hedera.services.store.contracts.precompile.HTSTestsUtil.contractAddress; import static com.hedera.services.store.contracts.precompile.HTSTestsUtil.createFungibleTokenUpdateWrapperWithKeys; @@ -26,6 +27,7 @@ import static com.hedera.services.store.contracts.precompile.HTSTestsUtil.successResult; import static com.hedera.services.store.contracts.precompile.impl.TokenUpdatePrecompile.decodeUpdateTokenInfo; import static com.hedera.services.store.contracts.precompile.impl.TokenUpdatePrecompile.decodeUpdateTokenInfoV2; +import static com.hedera.services.store.contracts.precompile.impl.TokenUpdatePrecompile.decodeUpdateTokenInfoV3; import static com.hederahashgraph.api.proto.java.ResponseCodeEnum.FAIL_INVALID; import static com.hederahashgraph.api.proto.java.ResponseCodeEnum.OK; import static java.util.function.UnaryOperator.identity; @@ -222,6 +224,31 @@ void computeCallsSuccessfullyForUpdateFungibleTokenV2() { assertEquals(successResult, result); } + @Test + void computeCallsSuccessfullyForUpdateFungibleTokenV3() { + // given + final var input = Bytes.of(Integers.toBytes(ABI_ID_UPDATE_TOKEN_INFO_V3)); + given(infrastructureFactory.newSideEffects()).willReturn(sideEffects); + given(worldUpdater.permissivelyUnaliased(any())) + .willAnswer(invocationOnMock -> invocationOnMock.getArgument(0)); + givenFrameContext(); + given(frame.getBlockValues()) + .willReturn(new HederaBlockValues(10L, 123L, Instant.ofEpochSecond(123L))); + givenLedgers(); + givenMinimalContextForSuccessfulCall(); + givenMinimalRecordStructureForSuccessfulCall(); + givenUpdateTokenContextV3(); + givenPricingUtilsContext(); + given(updateLogic.validate(any())).willReturn(OK); + // when + subject.prepareFields(frame); + subject.prepareComputation(input, a -> a); + subject.getPrecompile().getMinimumFeeInTinybars(Timestamp.getDefaultInstance()); + final var result = subject.computeInternal(frame); + // then + assertEquals(successResult, result); + } + @Test void failsWithWrongValidityForUpdateFungibleToken() { // given @@ -357,6 +384,26 @@ private void givenUpdateTokenContextV2() { .setTokenUpdate(TokenUpdateTransactionBody.newBuilder())); } + private void givenUpdateTokenContextV3() { + given( + sigsVerifier.hasActiveAdminKey( + true, fungibleTokenAddr, fungibleTokenAddr, wrappedLedgers)) + .willReturn(true); + given(infrastructureFactory.newHederaTokenStore(sideEffects, tokens, nfts, tokenRels)) + .willReturn(hederaTokenStore); + given( + infrastructureFactory.newTokenUpdateLogic( + hederaTokenStore, wrappedLedgers, sideEffects)) + .willReturn(updateLogic); + tokenUpdatePrecompile + .when(() -> decodeUpdateTokenInfoV3(any(), any())) + .thenReturn(updateWrapper); + given(syntheticTxnFactory.createTokenUpdate(updateWrapper)) + .willReturn( + TransactionBody.newBuilder() + .setTokenUpdate(TokenUpdateTransactionBody.newBuilder())); + } + private void givenMinimalRecordStructureForSuccessfulCall() { given( creator.createSuccessfulSyntheticRecord( diff --git a/hedera-node/hedera-mono-service/src/test/java/com/hedera/services/store/contracts/precompile/TransferPrecompilesTest.java b/hedera-node/hedera-mono-service/src/test/java/com/hedera/services/store/contracts/precompile/TransferPrecompilesTest.java index 95962f8b86d2..f6096199a5fb 100644 --- a/hedera-node/hedera-mono-service/src/test/java/com/hedera/services/store/contracts/precompile/TransferPrecompilesTest.java +++ b/hedera-node/hedera-mono-service/src/test/java/com/hedera/services/store/contracts/precompile/TransferPrecompilesTest.java @@ -222,6 +222,9 @@ class TransferPrecompilesTest { private static final Bytes POSITIVE_FUNGIBLE_AMOUNT_AND_NFT_TRANSFER_CRYPTO_TRANSFER_INPUT = Bytes.fromHexString( "0x189a554c00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004a4000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000004a1000000000000000000000000000000000000000000000000000000000000002b000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000004a100000000000000000000000000000000000000000000000000000000000004a10000000000000000000000000000000000000000000000000000000000000048"); + private static final Bytes POSITIVE_FUNGIBLE_AMOUNT_AND_NFT_TRANSFER_CRYPTO_TRANSFER_INPUT_V2 = + Bytes.fromHexString( + "0x0e71804f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004a4000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000004a1000000000000000000000000000000000000000000000000000000000000002b000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000004a100000000000000000000000000000000000000000000000000000000000004a10000000000000000000000000000000000000000000000000000000000000048"); private static final Bytes NEGATIVE_FUNGIBLE_AMOUNT_CRYPTO_TRANSFER_INPUT = Bytes.fromHexString( "0x189a554c00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004c0000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000004bdffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffce0000000000000000000000000000000000000000000000000000000000000000"); diff --git a/hedera-node/hedera-mono-service/src/test/java/com/hedera/services/store/contracts/precompile/UpdateTokenExpiryInfoPrecompileTest.java b/hedera-node/hedera-mono-service/src/test/java/com/hedera/services/store/contracts/precompile/UpdateTokenExpiryInfoPrecompileTest.java index 8df46e8d127f..168d41c1fb08 100644 --- a/hedera-node/hedera-mono-service/src/test/java/com/hedera/services/store/contracts/precompile/UpdateTokenExpiryInfoPrecompileTest.java +++ b/hedera-node/hedera-mono-service/src/test/java/com/hedera/services/store/contracts/precompile/UpdateTokenExpiryInfoPrecompileTest.java @@ -17,6 +17,7 @@ import static com.hedera.services.state.EntityCreator.EMPTY_MEMO; import static com.hedera.services.store.contracts.precompile.AbiConstants.ABI_ID_UPDATE_TOKEN_EXPIRY_INFO; +import static com.hedera.services.store.contracts.precompile.AbiConstants.ABI_ID_UPDATE_TOKEN_EXPIRY_INFO_V2; import static com.hedera.services.store.contracts.precompile.HTSTestsUtil.contractAddr; import static com.hedera.services.store.contracts.precompile.HTSTestsUtil.contractAddress; import static com.hedera.services.store.contracts.precompile.HTSTestsUtil.fungibleTokenAddr; @@ -26,6 +27,7 @@ import static com.hedera.services.store.contracts.precompile.HTSTestsUtil.tokenUpdateExpiryInfoWrapper; import static com.hedera.services.store.contracts.precompile.HTSTestsUtil.tokenUpdateExpiryInfoWrapperWithInvalidTokenID; import static com.hedera.services.store.contracts.precompile.impl.UpdateTokenExpiryInfoPrecompile.decodeUpdateTokenExpiryInfo; +import static com.hedera.services.store.contracts.precompile.impl.UpdateTokenExpiryInfoPrecompile.decodeUpdateTokenExpiryInfoV2; import static java.util.function.UnaryOperator.identity; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -127,6 +129,9 @@ class UpdateTokenExpiryInfoPrecompileTest { public static final Bytes UPDATE_EXPIRY_INFO_FOR_TOKEN_INPUT = Bytes.fromHexString( "0x593d6e8200000000000000000000000000000000000000000000000000000000000008d300000000000000000000000000000000000000000000000000000000bbf7edc700000000000000000000000000000000000000000000000000000000000008d000000000000000000000000000000000000000000000000000000000002820a8"); + public static final Bytes UPDATE_EXPIRY_INFO_FOR_TOKEN_INPUT_V2 = + Bytes.fromHexString( + "0x4a089f0900000000000000000000000000000000000000000000000000000000000008d3000000000000000000000000000000000000000000000000000000000bf7edc700000000000000000000000000000000000000000000000000000000000008d00000000000000000000000000000000000000000000000000000000000000008"); private HTSPrecompiledContract subject; private MockedStatic updateTokenExpiryInfoPrecompile; @@ -186,6 +191,28 @@ void updateTokenExpiryInfoHappyPath() { assertEquals(successResult, result); } + @Test + void updateTokenExpiryInfoV2HappyPath() { + // given + final var input = Bytes.of(Integers.toBytes(ABI_ID_UPDATE_TOKEN_EXPIRY_INFO_V2)); + given(infrastructureFactory.newSideEffects()).willReturn(sideEffects); + given(worldUpdater.permissivelyUnaliased(any())) + .willAnswer(invocationOnMock -> invocationOnMock.getArgument(0)); + givenFrameContext(); + givenLedgers(); + givenMinimalContextForSuccessfulCall(); + givenMinimalRecordStructureForSuccessfulCall(); + givenUpdateTokenContextV2(); + givenPricingUtilsContext(); + // when + subject.prepareFields(frame); + subject.prepareComputation(input, a -> a); + subject.getPrecompile().getMinimumFeeInTinybars(Timestamp.getDefaultInstance()); + final var result = subject.computeInternal(frame); + // then + assertEquals(successResult, result); + } + @Test void updateTokenExpiryInfoFailsWithInvalidTokenID() { // given @@ -233,6 +260,23 @@ UPDATE_EXPIRY_INFO_FOR_TOKEN_INPUT, identity())) assertTrue(decodedInput.expiry().autoRenewPeriod() > 0); } + @Test + void decodeUpdateExpiryInfoV2ForTokenInput() { + updateTokenExpiryInfoPrecompile + .when( + () -> + decodeUpdateTokenExpiryInfoV2( + UPDATE_EXPIRY_INFO_FOR_TOKEN_INPUT_V2, identity())) + .thenCallRealMethod(); + final var decodedInput = + decodeUpdateTokenExpiryInfoV2(UPDATE_EXPIRY_INFO_FOR_TOKEN_INPUT_V2, identity()); + + assertTrue(decodedInput.tokenID().getTokenNum() > 0); + assertTrue(decodedInput.expiry().second() > 0); + assertTrue(decodedInput.expiry().autoRenewAccount().getAccountNum() > 0); + assertTrue(decodedInput.expiry().autoRenewPeriod() > 0); + } + private void givenFrameContext() { given(frame.getSenderAddress()).willReturn(contractAddress); given(frame.getWorldUpdater()).willReturn(worldUpdater); @@ -271,6 +315,25 @@ private void givenUpdateTokenContext() { .setTokenUpdate(TokenUpdateTransactionBody.newBuilder())); } + private void givenUpdateTokenContextV2() { + given(sigsVerifier.hasActiveAdminKey(true, tokenAddress, fungibleTokenAddr, wrappedLedgers)) + .willReturn(true); + given(infrastructureFactory.newHederaTokenStore(sideEffects, tokens, nfts, tokenRels)) + .willReturn(hederaTokenStore); + given( + infrastructureFactory.newTokenUpdateLogic( + hederaTokenStore, wrappedLedgers, sideEffects)) + .willReturn(updateLogic); + given(updateLogic.validate(any())).willReturn(ResponseCodeEnum.OK); + updateTokenExpiryInfoPrecompile + .when(() -> decodeUpdateTokenExpiryInfoV2(any(), any())) + .thenReturn(tokenUpdateExpiryInfoWrapper); + given(syntheticTxnFactory.createTokenUpdateExpiryInfo(tokenUpdateExpiryInfoWrapper)) + .willReturn( + TransactionBody.newBuilder() + .setTokenUpdate(TokenUpdateTransactionBody.newBuilder())); + } + private void givenMinimalRecordStructureForSuccessfulCall() { given( creator.createSuccessfulSyntheticRecord( diff --git a/hedera-node/hedera-mono-service/src/test/java/com/hedera/services/store/contracts/precompile/WipeFungiblePrecompileTest.java b/hedera-node/hedera-mono-service/src/test/java/com/hedera/services/store/contracts/precompile/WipeFungiblePrecompileTest.java index b9987366bfdc..1cc4a9c298de 100644 --- a/hedera-node/hedera-mono-service/src/test/java/com/hedera/services/store/contracts/precompile/WipeFungiblePrecompileTest.java +++ b/hedera-node/hedera-mono-service/src/test/java/com/hedera/services/store/contracts/precompile/WipeFungiblePrecompileTest.java @@ -32,6 +32,7 @@ import static com.hedera.services.store.contracts.precompile.HTSTestsUtil.successResult; import static com.hedera.services.store.contracts.precompile.HTSTestsUtil.timestamp; import static com.hedera.services.store.contracts.precompile.impl.WipeFungiblePrecompile.decodeWipe; +import static com.hedera.services.store.contracts.precompile.impl.WipeFungiblePrecompile.decodeWipeV2; import static com.hederahashgraph.api.proto.java.ResponseCodeEnum.OK; import static com.hederahashgraph.api.proto.java.TokenType.FUNGIBLE_COMMON; import static java.util.function.UnaryOperator.identity; @@ -165,7 +166,9 @@ class WipeFungiblePrecompileTest { private static final Bytes FUNGIBLE_WIPE_INPUT = Bytes.fromHexString( "0x9790686d00000000000000000000000000000000000000000000000000000000000006aa00000000000000000000000000000000000000000000000000000000000006a8000000000000000000000000000000000000000000000000000000000000000a"); - + private static final Bytes FUNGIBLE_WIPE_INPUT_V2 = + Bytes.fromHexString( + "0x2d279ec600000000000000000000000000000000000000000000000000000000000006aa00000000000000000000000000000000000000000000000000000000000006a8000000000000000000000000000000000000000000000000000000000000000a"); private HTSPrecompiledContract subject; private MockedStatic wipeFungiblePrecompile; @@ -409,6 +412,20 @@ void decodeFungibleWipeInput() { assertEquals(FUNGIBLE_COMMON, decodedInput.type()); } + @Test + void decodeFungibleWipeInputV2() { + wipeFungiblePrecompile + .when(() -> decodeWipeV2(FUNGIBLE_WIPE_INPUT_V2, identity())) + .thenCallRealMethod(); + final var decodedInput = decodeWipeV2(FUNGIBLE_WIPE_INPUT_V2, identity()); + + assertTrue(decodedInput.token().getTokenNum() > 0); + assertTrue(decodedInput.account().getAccountNum() > 0); + assertEquals(10, decodedInput.amount()); + assertEquals(0, decodedInput.serialNumbers().size()); + assertEquals(FUNGIBLE_COMMON, decodedInput.type()); + } + private void givenFungibleFrameContext() { givenFrameContext(); wipeFungiblePrecompile diff --git a/test-clients/src/main/java/com/hedera/services/bdd/spec/transactions/token/HapiTokenMint.java b/test-clients/src/main/java/com/hedera/services/bdd/spec/transactions/token/HapiTokenMint.java index 53eedc74d109..7822c100ae66 100644 --- a/test-clients/src/main/java/com/hedera/services/bdd/spec/transactions/token/HapiTokenMint.java +++ b/test-clients/src/main/java/com/hedera/services/bdd/spec/transactions/token/HapiTokenMint.java @@ -114,7 +114,7 @@ protected long feeFor(HapiApiSpec spec, Transaction txn, int numPayerKeys) throw numPayerKeys); } - private FeeData usageEstimate(TransactionBody txn, SigValueObj svo) throws Throwable { + private FeeData usageEstimate(TransactionBody txn, SigValueObj svo) { UsageAccumulator accumulator = new UsageAccumulator(); long lifetime = 0L; @@ -123,10 +123,10 @@ private FeeData usageEstimate(TransactionBody txn, SigValueObj svo) throws Throw info.getExpiry().getSeconds() - txn.getTransactionID().getTransactionValidStart().getSeconds(); } - final var tokenBurnMeta = TOKEN_OPS_USAGE_UTILS.tokenMintUsageFrom(txn, subType, lifetime); + final var tokenMintMeta = TOKEN_OPS_USAGE_UTILS.tokenMintUsageFrom(txn, subType, lifetime); final var baseTransactionMeta = new BaseTransactionMeta(txn.getMemoBytes().size(), 0); TokenOpsUsage tokenOpsUsage = new TokenOpsUsage(); - tokenOpsUsage.tokenMintUsage(suFrom(svo), baseTransactionMeta, tokenBurnMeta, accumulator); + tokenOpsUsage.tokenMintUsage(suFrom(svo), baseTransactionMeta, tokenMintMeta, accumulator); return AdapterUtils.feeDataFrom(accumulator); }