-
Notifications
You must be signed in to change notification settings - Fork 21
feat: Added support for custom maxTransactionFee and gas to createContract/callContract
#249
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
192d352
8781e10
6a074cd
7d03712
9d0c577
c548e07
f91dc96
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,8 +1,11 @@ | ||||||||||||||||||||||||||||||||||||
| package org.hiero.base.implementation; | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| import static org.hiero.base.implementation.ProtocolLayerClientImpl.MAX_GAS_LIMIT; | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| import com.hedera.hashgraph.sdk.ContractFunctionResult; | ||||||||||||||||||||||||||||||||||||
| import com.hedera.hashgraph.sdk.ContractId; | ||||||||||||||||||||||||||||||||||||
| import com.hedera.hashgraph.sdk.FileId; | ||||||||||||||||||||||||||||||||||||
| import com.hedera.hashgraph.sdk.Hbar; | ||||||||||||||||||||||||||||||||||||
| import java.nio.file.Files; | ||||||||||||||||||||||||||||||||||||
| import java.nio.file.Path; | ||||||||||||||||||||||||||||||||||||
| import java.util.Arrays; | ||||||||||||||||||||||||||||||||||||
|
|
@@ -39,14 +42,27 @@ public SmartContractClientImpl( | |||||||||||||||||||||||||||||||||||
| @NonNull | ||||||||||||||||||||||||||||||||||||
| @Override | ||||||||||||||||||||||||||||||||||||
| public ContractId createContract( | ||||||||||||||||||||||||||||||||||||
| @NonNull final FileId fileId, @Nullable final ContractParam<?>... constructorParams) | ||||||||||||||||||||||||||||||||||||
| @NonNull final FileId fileId, | ||||||||||||||||||||||||||||||||||||
| @NonNull final Hbar maxTransactionFee, | ||||||||||||||||||||||||||||||||||||
| final int gas, | ||||||||||||||||||||||||||||||||||||
| @Nullable final ContractParam<?>... constructorParams) | ||||||||||||||||||||||||||||||||||||
| throws HieroException { | ||||||||||||||||||||||||||||||||||||
| Objects.requireNonNull(fileId, "fileId must not be null"); | ||||||||||||||||||||||||||||||||||||
| Objects.requireNonNull(maxTransactionFee, "maxTransactionFee must not be null"); | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| if (gas < 0 || gas > MAX_GAS_LIMIT) { | ||||||||||||||||||||||||||||||||||||
| throw new IllegalArgumentException( | ||||||||||||||||||||||||||||||||||||
| "gas must be between 0 and " + MAX_GAS_LIMIT + " inclusive"); | ||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||||||||||||
| final ContractCreateRequest request; | ||||||||||||||||||||||||||||||||||||
| if (constructorParams == null) { | ||||||||||||||||||||||||||||||||||||
| request = ContractCreateRequest.of(fileId); | ||||||||||||||||||||||||||||||||||||
| request = ContractCreateRequest.of(fileId, maxTransactionFee, gas); | ||||||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||||||
| request = ContractCreateRequest.of(fileId, Arrays.asList(constructorParams)); | ||||||||||||||||||||||||||||||||||||
| request = | ||||||||||||||||||||||||||||||||||||
| ContractCreateRequest.of( | ||||||||||||||||||||||||||||||||||||
| fileId, maxTransactionFee, gas, Arrays.asList(constructorParams)); | ||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||
| final ContractCreateResult result = | ||||||||||||||||||||||||||||||||||||
| protocolLayerClient.executeContractCreateTransaction(request); | ||||||||||||||||||||||||||||||||||||
|
|
@@ -59,11 +75,17 @@ public ContractId createContract( | |||||||||||||||||||||||||||||||||||
| @NonNull | ||||||||||||||||||||||||||||||||||||
| @Override | ||||||||||||||||||||||||||||||||||||
| public ContractId createContract( | ||||||||||||||||||||||||||||||||||||
| @NonNull final byte[] contents, @Nullable final ContractParam<?>... constructorParams) | ||||||||||||||||||||||||||||||||||||
| @NonNull final byte[] contents, | ||||||||||||||||||||||||||||||||||||
| @NonNull final Hbar maxTransactionFee, | ||||||||||||||||||||||||||||||||||||
| final int gas, | ||||||||||||||||||||||||||||||||||||
| @Nullable final ContractParam<?>... constructorParams) | ||||||||||||||||||||||||||||||||||||
| throws HieroException { | ||||||||||||||||||||||||||||||||||||
| Objects.requireNonNull(contents, "contents must not be null"); | ||||||||||||||||||||||||||||||||||||
| Objects.requireNonNull(maxTransactionFee, "maxTransactionFee must not be null"); | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||||||||||||
| final FileId fileId = fileClient.createFile(contents); | ||||||||||||||||||||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If createContract(...) throws, is deleteFile() ever called? Should it be
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. that is to matche the existing flow we have, but happy to change the flow in this PR it needed :) |
||||||||||||||||||||||||||||||||||||
| final ContractId contract = createContract(fileId, constructorParams); | ||||||||||||||||||||||||||||||||||||
| final ContractId contract = createContract(fileId, maxTransactionFee, gas, constructorParams); | ||||||||||||||||||||||||||||||||||||
| fileClient.deleteFile(fileId); | ||||||||||||||||||||||||||||||||||||
| return contract; | ||||||||||||||||||||||||||||||||||||
|
Comment on lines
86
to
90
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win Always delete the temporary bytecode file after creation attempts. If delegated gas validation or contract creation fails, Line 89 is skipped, leaving a paid Hedera file orphaned. Validate before upload where possible and delete the file in Proposed cleanup+ FileId fileId = null;
try {
- final FileId fileId = fileClient.createFile(contents);
- final ContractId contract = createContract(fileId, maxTransactionFee, gas, constructorParams);
- fileClient.deleteFile(fileId);
- return contract;
+ fileId = fileClient.createFile(contents);
+ return createContract(fileId, maxTransactionFee, gas, constructorParams);
} catch (Exception e) {
throw new HieroException("Failed to create contract out of byte array", e);
+ } finally {
+ if (fileId != null) {
+ fileClient.deleteFile(fileId);
+ }
}📝 Committable suggestion
Suggested change
|
||||||||||||||||||||||||||||||||||||
| } catch (Exception e) { | ||||||||||||||||||||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would it make sense to catch more specific exceptions (e.g. IOException) here? Catching Exception also wraps programming errors like IllegalArgumentException, which may make debugging harder.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. same with this one too |
||||||||||||||||||||||||||||||||||||
|
|
@@ -74,11 +96,17 @@ public ContractId createContract( | |||||||||||||||||||||||||||||||||||
| @NonNull | ||||||||||||||||||||||||||||||||||||
| @Override | ||||||||||||||||||||||||||||||||||||
| public ContractId createContract( | ||||||||||||||||||||||||||||||||||||
| @NonNull final Path pathToBin, @Nullable final ContractParam<?>... constructorParams) | ||||||||||||||||||||||||||||||||||||
| @NonNull final Path pathToBin, | ||||||||||||||||||||||||||||||||||||
| @NonNull final Hbar maxTransactionFee, | ||||||||||||||||||||||||||||||||||||
| final int gas, | ||||||||||||||||||||||||||||||||||||
| @Nullable final ContractParam<?>... constructorParams) | ||||||||||||||||||||||||||||||||||||
| throws HieroException { | ||||||||||||||||||||||||||||||||||||
| Objects.requireNonNull(pathToBin, "pathToBin must not be null"); | ||||||||||||||||||||||||||||||||||||
| Objects.requireNonNull(maxTransactionFee, "maxTransactionFee must not be null"); | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||||||||||||
| final byte[] bytes = Files.readAllBytes(pathToBin); | ||||||||||||||||||||||||||||||||||||
| return createContract(bytes, constructorParams); | ||||||||||||||||||||||||||||||||||||
| return createContract(bytes, maxTransactionFee, gas, constructorParams); | ||||||||||||||||||||||||||||||||||||
| } catch (Exception e) { | ||||||||||||||||||||||||||||||||||||
| throw new HieroException("Failed to create contract from path " + pathToBin, e); | ||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||
|
|
@@ -89,10 +117,23 @@ public ContractId createContract( | |||||||||||||||||||||||||||||||||||
| public ContractCallResult callContractFunction( | ||||||||||||||||||||||||||||||||||||
| @NonNull final ContractId contractId, | ||||||||||||||||||||||||||||||||||||
| @NonNull final String functionName, | ||||||||||||||||||||||||||||||||||||
| @NonNull final Hbar maxTransactionFee, | ||||||||||||||||||||||||||||||||||||
| final int gas, | ||||||||||||||||||||||||||||||||||||
| @Nullable ContractParam<?>... params) | ||||||||||||||||||||||||||||||||||||
| throws HieroException { | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| Objects.requireNonNull(contractId, "contractId must not be null"); | ||||||||||||||||||||||||||||||||||||
| Objects.requireNonNull(functionName, "functionName must not be null"); | ||||||||||||||||||||||||||||||||||||
| Objects.requireNonNull(maxTransactionFee, "maxTransactionFee must not be null"); | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| if (gas < 0 || gas > MAX_GAS_LIMIT) { | ||||||||||||||||||||||||||||||||||||
| throw new IllegalArgumentException( | ||||||||||||||||||||||||||||||||||||
| "gas must be between 0 and " + MAX_GAS_LIMIT + " inclusive"); | ||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||||||||||||
| final ContractCallRequest request = ContractCallRequest.of(contractId, functionName, params); | ||||||||||||||||||||||||||||||||||||
| final ContractCallRequest request = | ||||||||||||||||||||||||||||||||||||
| ContractCallRequest.of(contractId, functionName, maxTransactionFee, gas, params); | ||||||||||||||||||||||||||||||||||||
| final ContractFunctionResult result = | ||||||||||||||||||||||||||||||||||||
| protocolLayerClient.executeContractCallTransaction(request).contractFunctionResult(); | ||||||||||||||||||||||||||||||||||||
| return new ContractCallResultImpl(result); | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win
Place shared gas policy in a neutral API/domain type. Defining it on
ProtocolLayerClientImplreverses dependencies throughout the request and public API layers.hiero-enterprise-base/src/main/java/org/hiero/base/implementation/ProtocolLayerClientImpl.java#L123-L123: moveMAX_GAS_LIMITandDEFAULT_GASto the neutral type.hiero-enterprise-base/src/main/java/org/hiero/base/protocol/data/ContractCallRequest.java#L3-L4: import the limit from that neutral type.hiero-enterprise-base/src/main/java/org/hiero/base/protocol/data/ContractCreateRequest.java#L3-L4: import the limit from that neutral type.hiero-enterprise-base/src/main/java/org/hiero/base/SmartContractClient.java#L3-L5: import the default gas without depending on an implementation.hiero-enterprise-base/src/main/java/org/hiero/base/implementation/SmartContractClientImpl.java#L3-L3: consume the same neutral policy.📍 Affects 5 files
hiero-enterprise-base/src/main/java/org/hiero/base/implementation/ProtocolLayerClientImpl.java#L123-L123(this comment)hiero-enterprise-base/src/main/java/org/hiero/base/protocol/data/ContractCallRequest.java#L3-L4hiero-enterprise-base/src/main/java/org/hiero/base/protocol/data/ContractCreateRequest.java#L3-L4hiero-enterprise-base/src/main/java/org/hiero/base/SmartContractClient.java#L3-L5hiero-enterprise-base/src/main/java/org/hiero/base/implementation/SmartContractClientImpl.java#L3-L3