Skip to content

feat(vm): add ABI semantic validation for /wallet/deploycontract#6703

Open
yanghang8612 wants to merge 2 commits intotronprotocol:developfrom
yanghang8612:feat/issue-6674-abi-validation
Open

feat(vm): add ABI semantic validation for /wallet/deploycontract#6703
yanghang8612 wants to merge 2 commits intotronprotocol:developfrom
yanghang8612:feat/issue-6674-abi-validation

Conversation

@yanghang8612
Copy link
Copy Markdown
Collaborator

@yanghang8612 yanghang8612 commented Apr 24, 2026

Closes #6674.

Add a dedicated AbiValidator and invoke it inside the existing CreateSmartContract branch of Wallet.createTransactionCapsule, so both the HTTP /wallet/deploycontract path and the gRPC deployContract path fail fast on malformed ABI input with a field-path-anchored error.

Scope: validation runs only at the API entry point (transaction construction). Block replay and re-validation of already-persisted contracts are unaffected — no consensus-layer behaviour change.

Rules align with go-ethereum's accounts/abi parser:

  • reject uint / int shorthand and out-of-range uintN / intN widths
  • reject bytesN with N outside [1, 32]
  • reject the entire fixed / ufixed family
  • reject malformed array suffixes
  • reject leading / trailing whitespace in any type string (so persisted bytes equal the validated bytes)
  • reject duplicate constructor / fallback / receive
  • require receive to be payable (legacy payable flag honoured)
  • reject fallback / receive carrying inputs or outputs
  • reject UnknownEntryType
  • require a name for function; require a name for event only when not anonymous; require a name for error
  • keep tuple / tuple[] / tuple[N] permissive, since the proto schema cannot represent components

Also reuse the validator in PublicMethod.jsonStr2Abi and TvmTestUtils.jsonStr2Abi so test/util ABI parsing and request-handling share the same rule set; both helpers now also map "receive" and "error" so receive-/error-entry test ABIs reach the proper validator branch instead of falling to UNRECOGNIZED.

Tests

  • AbiValidatorTest — covers each rejection branch (widths, bytesN bounds, fixed/ufixed, array suffixes, whitespace, duplicates, payable/inputs/outputs constraints, UnknownEntryType, missing-name).
  • DeployContractServletTest — end-to-end HTTP /wallet/deploycontract rejection.
  • TvmTestUtilsTest, PublicMethodTest — confirm receive / error entry mapping reaches the validator.

@github-actions github-actions Bot requested a review from CodeNinjaEvan April 24, 2026 01:36
@yanghang8612 yanghang8612 changed the title feat(vm): add ABI semantic validation for /wallet/deploycontract (#6674) feat(vm): add ABI semantic validation for /wallet/deploycontract Apr 24, 2026
if (raw == null || raw.isEmpty()) {
return "type must not be empty";
}
String t = raw.trim();
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Really nice helper layout — checkType returning either null or a short reason makes the call site read very cleanly, and isolating the regex/base-type tables at the top is great for future tweaking. ✨

One subtle gap: t = raw.trim() lets a type like " uint256 " pass validation, but the validator never normalizes the proto — the on-chain Param.type keeps the original whitespace. Per the linked issue's "fewer inconsistencies in stored ABI metadata" goal, would it make sense to reject whitespace-padded types upfront, e.g.:

if (!raw.equals(raw.trim())) {
  return "type must not contain leading/trailing whitespace";
}

That way the validator's "this passed" implies "what gets persisted is exactly what got checked", which matches the stated goal of strict-matching tooling compatibility.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @alan-eth — that lands. The whole point of this validator is that "passed validation" should match "what gets persisted"; accepting " uint256 " breaks the invariant silently and the proto write never normalizes it back. Adding the upfront whitespace reject is a cleaner contract than threading a trim() through the write path.

Going in the next commit.

case "fallback":
return SmartContract.ABI.Entry.EntryType.Fallback;
case "error":
return SmartContract.ABI.Entry.EntryType.Error;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great call adding case "error" here — without it any test ABI carrying an error entry would fall into UNRECOGNIZED and now hit the new "unknown entry type" rejection. Nice symmetry with PublicMethod.getEntryType which already had it. 🎯

Minor follow-up: both this helper and PublicMethod.getEntryType still omit case "receive", even though the new validator has dedicated handling for Receive (payability + IO checks). Any test that wants to exercise a receive entry through these helpers will still get UNRECOGNIZED and bounce off the new rejection. Worth adding the one-line case in both files while you're here, so the validator's full surface is reachable from test utilities?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch. Adding case "receive" to both TvmTestUtils.getEntryType and PublicMethod.getEntryType so the validator's Receive handling (payability + IO checks) is actually reachable from test helpers — otherwise any test that exercises a receive entry bounces off "unknown entry type" before it hits the rules the validator is there to enforce. Folds into the same commit as the whitespace fix above.

@halibobo1205 halibobo1205 added this to the GreatVoyage-v4.8.2 milestone Apr 24, 2026
@halibobo1205 halibobo1205 added topic:vm VM, smart contract topic:api rpc/http related issue labels Apr 24, 2026
private AbiValidator() {
}

public static void validate(ABI abi) throws ContractValidateException {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is validate(ABI abi) too strict? It may reject legitimate ABIs generated by older or non-standard compilers.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looked into this carefully — checked solc v0.4.0 source (Sep 2016, predates TRON mainnet by ~2 years):

  • IntegerType::toString (Types.cpp:323-328) returns prefix + bits unconditionally, so ABIs always carry "uint256"/"int128" etc., never bare "uint"/"int".
  • FixedBytesType::toString (Types.h:455) returns "bytes" + N unconditionally — the byte keyword is source-language only, never reaches ABI JSON.
  • Fallback gets its own ABI entry (InterfaceHandler.cpp:78-86 in v0.4.0): method["type"] = "fallback". Never emitted as type=function with empty name.

Combined with TRON's solc fork being 0.4.x-based, every contract ever deployed on TRON mainnet has gone through canonical-emitting solc. The strict validator does not reject any solc-produced ABI, modern or historical.

Hand-written ABIs that use shorthand can canonicalize client-side; storing non-canonical types on-chain would actively work against #6674's "fewer inconsistencies in stored ABI metadata" goal.

Keeping the strict rules.

@yanghang8612 yanghang8612 force-pushed the feat/issue-6674-abi-validation branch from a1368ac to ed66c1e Compare April 29, 2026 15:28
…nprotocol#6674)

AbiValidator runs in CreateSmartContract path of
Wallet.createTransactionCapsule (HTTP and gRPC), with rules aligned
to go-ethereum's accounts/abi parser. Reused in test ABI helpers.
…elpers

AbiValidator now rejects leading/trailing whitespace upfront;
PublicMethod / TvmTestUtils helpers map "receive" so receive-entry
test ABIs reach the validator's Receive branch.
@yanghang8612 yanghang8612 force-pushed the feat/issue-6674-abi-validation branch from ed66c1e to 3a5e561 Compare May 6, 2026 03:28
@github-actions github-actions Bot requested a review from CodeNinjaEvan May 6, 2026 03:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

topic:api rpc/http related issue topic:vm VM, smart contract

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

[Feature] Add ABI semantic validation for /wallet/deploycontract

5 participants