Transaction Security
Understand what a transaction will do before the user signs it, then decide whether to allow, warn, or block the request. HashDit simulates the transaction, checks every address and contract it touches against threat intelligence, and returns one recommendation the signing flow can act on.
Networks: all supported EVM chains, plus Tron. See Supported Chains.
Using The Recommendation
recommended_action is the simplest field to integrate into a signing flow:
| Value | Meaning | Suggested UI behavior |
|---|---|---|
ALLOW | No risk worth interrupting the user for was detected. | Continue to the normal confirmation screen. |
WARN | The user should understand one or more risks before signing. | Show every risk_details[].description and require confirmation. |
BLOCK | Strong evidence indicates that the transaction may harm the user. | Advise against signing and stop the default flow. |
| Score | Risk level | Recommendation |
|---|---|---|
0 | No Obvious Risk | ALLOW |
1 | Caution | ALLOW |
2 | Low Risk | WARN |
3 | Medium Risk | WARN |
4 | High Risk | BLOCK |
5 | Significant Risk | BLOCK |
Use name for application logic and description for user-facing copy. Key off name, not description: identifiers are stable, while wording improves over time.
Security Coverage
HashDit combines request context, threat intelligence, contract metadata and simulation evidence. Findings can cover:- Malicious or brand-impersonating dApp URLs
- Risky destination addresses and addresses reached by internal calls
- Unlimited approvals, approvals to wallet addresses, and NFT approval-for-all
- Known-malicious or suspicious function calls
- Unverified destinations, recipients and contract functions
- Tron account-permission changes
risk_details contains only the findings triggered for the submitted transaction. Reverts and the actual balance, approval and ownership effects are reported separately, in the simulation result.
Security Analysis Without Simulation
Setsimulate to false when you only need the verdict:
{
"dapp_url": "https://app.example.com/swap",
"evm_transactions": [
{
"chain_id": 56,
"from": "0x8894E0a0c962CB723c1976a4421c95949bE2D4E3",
"to": "0x55d398326f99059ff775485246999027b3197955",
"data": "0x095ea7b3"
}
],
"simulate": false
}
data.security and omits exec_summary, results and simulation_error. Checks that depend on execution evidence — an approval created inside a nested call, the proportion of a balance transferred — are unavailable in this mode.
Tron Transactions
evm_transactions shape every other chain uses, or the unsigned transaction object tronWeb.transactionBuilder returns, as tron_transactions. The second lets a wallet forward what it already holds; prefer it on Tron.tronWeb.transactionBuilder.* returned, unmodified. Addresses are accepted in either encoding tronWeb emits — 21-byte hex, or the Base58 form you get with visible: true. txID, visible and raw_data_hex are ignored, and the { "method": "tron_sendTransaction", "params": … } provider envelope is unwrapped.
dapp_url, simulate and requested_items work exactly as they do for evm_transactions.
Amounts Are Decimal Here
Numbers inside a Tron transaction are read as decimal only — unlike the Numeric Fields of this API, where0x marks hex.
A 0x-prefixed amount is a 400, as is any amount, threshold or key weight that cannot be read. Nothing is defaulted to zero.
Which Operations Are Simulated
raw_data.contract[0].type decides.
Simulated. TransferContract, TransferAssetContract, TriggerSmartContract, FreezeBalanceV2Contract, UnfreezeBalanceV2Contract, DelegateResourceContract, UnDelegateResourceContract, WithdrawExpireUnfreezeContract.
Assessed, but not simulated. A vote, a reward withdrawal, an account-permission change and a Stake 1.0 freeze are all real transactions with nothing for the simulator to execute: AccountPermissionUpdateContract, VoteWitnessContract, WithdrawBalanceContract, AccountUpdateContract, CancelAllUnfreezeV2Contract, FreezeBalanceContract, UnfreezeBalanceContract, ParticipateAssetIssueContract, CreateSmartContract.
For these, results is empty, simulation_error names the operation, and security is still a full assessment.
Anything else also returns a verdict rather than an error, so a transaction type Tron adds later keeps working.
Account Permission Changes
AccountPermissionUpdateContract is read in full: which permission block each new key lands in, the signature threshold, the key weights, and — for an active permission — the operations it is limited to.
| Finding | When |
|---|---|
tx_tron_permission_transfer | Another account gains a key that can take value out: an owner key, or an active key permitting TransferContract, TransferAssetContract, TriggerSmartContract or AccountPermissionUpdateContract. |
tx_tron_permission_delegated | Another account gains a key that cannot: a witness key, or an active key permitting none of the four above. |
tx_tron_permission_unusable | A permission’s threshold exceeds the total weight of its own keys, so it could never be used again. |
tx_tron_permission_update | The signer changes their own permissions and no other account gains a key. |
results empty. The flat evm_transactions shape cannot express this operation at all.
Input requirement: an active permission must carry its 32-byte operations bitmap, as hex or base64. Its contents decide which of the first two findings applies, so a bitmap that cannot be read is a 400.
tx_tron_permission_transfer prominently. One signature grants a key to the account — TRX, every TRC-20 and TRC-10, staked balances and future deposits at once. It is not an approval, so it will not appear in any approval-review screen, and revoking it needs a further permission change.
Numeric Fields
Everyint | string field in this request — value, gas, gas_price, max_fee_per_gas, max_priority_fee_per_gas, nonce, type, block_height, token_id, token_value, and the amount inside freeze_balance and delegate_resource — accepts all three of:
| Form | Example |
|---|---|
| JSON number | 1000000 |
| Decimal string | "1000000" |
0x-prefixed hex | "0xf4240" |
0x prefix: "f4240" is a 400.
tron_transactions object are decimal only. See Amounts Are Decimal Here.Errors
| HTTP status | Example status | When it happens |
|---|---|---|
400 | invalid request | A required field is missing, a value cannot be read, two aliases of one field disagree, both request shapes were sent, more than one transaction was sent, or the chain is unsupported. |
401 | Authentication error | X-API-KEY is missing or invalid. |
429 | too many requests | The caller exceeded its request limit. |
500 | internal server error | HashDit could not complete the request. |
detail or message explaining the failure:
{
"code": "-1",
"status": "invalid request",
"detail": "send exactly one transaction; batch analysis is not supported"
}
tron_transactions:
{
"code": "-1",
"status": "invalid request",
"detail": "send either 'tron_transactions' or 'evm_transactions', not both: they describe the same request two different ways and only one of them can be the one the user is signing"
}
{
"code": "-1",
"status": "invalid request",
"detail": "tron_transactions[0]: could not read 'amount' as a number: '0xf4240'. Tron writes these in decimal; a 0x-prefixed value is not a Tron amount"
}
Request/Response
camelCase and snake_case. See Request Field Names.Headers
Your HashDit API key.
Body
Send exactly one transaction, in exactly one of evm_transactions or tron_transactions.
Sending both shapes, or more than one transaction, is a 400.
The transaction to analyze. Alias: transactions.
Send this or tron_transactions, not both, and send exactly one item.
1 elementShow child attributes
Show child attributes
[ { "chain_id": "56", "from": "0x000000000000000000000000000000000000dead", "to": "0x6ad549e6312114e646f30cDDde75e15a96d86233", "value": "1000000000000000000", "data": "0x" } ]
On Tron you can skip the flattening entirely: send the object tronWeb.transactionBuilder.* returned, unmodified. See the Tron Unsigned Transaction example in the playground.
Unmodified unsigned Tron transactions. Alias: tronTransactions.
Send this or evm_transactions, not both, and send exactly one item. No chain_id is needed — a Tron transaction identifies its own chain.
See Tron Transactions.
1 elementFull URL of the dApp that initiated the transaction. Alias: dappUrl.
Optional, recommended.
Defaults to true.
Set to false to return the security verdict without simulation output. exec_summary, results and simulation_error are omitted. Checks that depend on execution evidence — an approval created inside a nested call, the proportion of a balance transferred — are unavailable in this mode.
Which simulation sections to include in results.
Show child attributes
Show child attributes
Response
Successful response.
code: "0" means the API request succeeded; it does not mean the transaction would. Check exec_summary.result_code and results[0].revert for the simulation outcome.
A revert is served at HTTP 200. simulation_error is null when execution produced a result — including a revert.
Every successful call uses the standard envelope: code, status, data.
"0" when the API request succeeded.
"0"
"ok" on success; otherwise an error label.
"ok"
Successful payload.
security is always present on success.
exec_summary, results and simulation_error are omitted when simulate is false.
tron_fee_limit is Tron only, and present only when both inputs are available.
Show child attributes
Show child attributes
Was this page helpful?