--- title: triggerSmartContract --- # triggerSmartContract Triggers a state-changing (non `pure` / non `view`) contract method and returns a `TransactionWrapper` containing the **unsigned** transaction. The transaction still needs to be signed via `tronWeb.trx.sign` and broadcast via `tronWeb.trx.sendRawTransaction`. See more about [Trigger Smart Contract](../../Interact%20with%20contract#triggersmartcontract). :::tip Recommended: pass arguments via `options.funcABIV2` + `options.parametersV2` **Use `options.funcABIV2` + `options.parametersV2` uniformly in all new code, and migrate existing code to this approach over time.** This path encodes arguments through ABI v2 (`encodeParamsV2ByABI`); it not only handles `tuple`, nested `tuple[]`, and other ABI v2 types correctly, but is also fully compatible with the simple flat types that ABI v1 supports — so it can serve as the single unified entry point for passing arguments. The legacy positional `parameters` argument is retained only for backward compatibility with simple flat signatures and is not recommended for new code. When `options.funcABIV2` is present, the positional `parameters` argument is ignored — pass `[]` (or omit it). ::: ## Usage ```javascript const transactionWrapper = await tronWeb.transactionBuilder.triggerSmartContract( contractAddress, functionSelector, options, parameters, issuerAddress ); ``` ## Parameters | Argument | Description | Type | Required | | ---------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------- | -------- | | contractAddress | The smart contract address (base58 or hex). | String | Yes | | functionSelector | Function signature to invoke, e.g. `transfer(address,uint256)`. Whitespace is automatically stripped. Can be omitted only when `options.input` is provided to supply raw call data. | String | Yes \* | | options | Trigger options. **Pass `funcABIV2` + `parametersV2` here to encode arguments (recommended).** See [`TriggerSmartContractOptions`](../../Interact%20with%20contract#triggersmartcontractoptions). Defaults: `feeLimit = tronWeb.feeLimit`, `callValue = 0`. | [`TriggerSmartContractOptions`](../../Interact%20with%20contract#triggersmartcontractoptions) | No | | parameters | Legacy positional arguments. Use only for flat signatures (no `tuple`). Ignored when `options.funcABIV2`, `options.shieldedParameter`, or `options.rawParameter` is supplied. | `Array<{ type: string; value: unknown }>` | No | | issuerAddress | Sender (caller) address. Falls back to `tronWeb.defaultAddress.hex`. | String | No | \* `functionSelector` can be left empty if `options.input` provides raw hex call data. ### Argument-encoding paths (priority, highest first) The trigger builder picks exactly one source for the function arguments, in this order: 1. **`options.rawParameter`** — already-encoded hex calldata (with or without `0x` prefix). 2. **`options.shieldedParameter`** — alias of `rawParameter` for shielded-pool flows. 3. **`options.funcABIV2` + `options.parametersV2`** — **recommended default.** Encoded via `encodeParamsV2ByABI`; supports `tuple`, nested `tuple[]`, dynamic arrays, etc. 4. **Positional `parameters`** — legacy ABI v1 encoder. Works for flat signatures only; does **not** support tuples. 5. **`options.input`** — used as raw `data` when `functionSelector` is omitted entirely. ### Notes on parameter encoding - `address` and `address[]` values are normalized to the EVM `0x…` form before encoding; you may pass base58 (`T…`), hex (`41…`), or `0x…` strings. - `trcToken` is internally treated as `uint256` when ABI-encoded. - When `options.txLocal` is `true`, the transaction is constructed entirely on the client (the function selector + parameters are hashed locally with `keccak256`) and no network request is made; otherwise the node's `wallet/triggersmartcontract` endpoint is called. - `options.permissionId` may be supplied for multi-signature transactions. ### Validation The following constraints are enforced before the request is issued; violations throw synchronously: - `feeLimit` must be a positive integer. - `callValue` must be a non-negative integer. - `parameters` must be an array. - `contractAddress` must be a valid TRON address. - `issuerAddress`, `tokenId`, and `tokenValue` are validated when provided. ## Returns A wrapper which contains the unsigned transaction object. ```typescript interface TransactionWrapper { result: { result: boolean; }; /** * The unsigned transaction object created by calling the contract function. */ transaction: Transaction; } ``` ## Example ### Recommended: `funcABIV2` + `parametersV2` ```javascript const funcABIV2 = { name: 'transfer', type: 'function', inputs: [ { name: '_to', type: 'address' }, { name: '_value', type: 'uint256' } ], outputs: [{ type: 'bool' }], stateMutability: 'nonpayable' }; const options = { feeLimit: 100_000_000, callValue: 0, tokenValue: 10, tokenId: '1000001', txLocal: true, funcABIV2, parametersV2: ['TV3nb5HYFe2xBEmyb3ETe93UGkjAhWyzrs', 100] }; const transactionWrapper = await tronWeb.transactionBuilder.triggerSmartContract( "TQQg4EL8o1BSeKJY4MJ8TB8XK7xufxFBvK", "transfer(address,uint256)", options, [], // positional parameters ignored when funcABIV2 is set "TM2TmqauSEiRf16CyFgzHV2BVxBejY9iyR" ); // output-start { "result": { "result": true }, "transaction": { "visible": false, "txID": "482b1a3b61894f75ea25bd10b14335a4db86c7e2c642ae07abc5a8ae45fb0027", "raw_data": { "contract": [ { "parameter": { "value": { "data": "a9059cbb000000000000000000000000d148171f1ceeeb40d668c47d70e7e94e679775590000000000000000000000000000000000000000000000000000000000000064", "token_id": 1000001, "owner_address": "417946f66d0fc67924da0ac9936183ab3b07c81126", "call_token_value": 10, "contract_address": "419e62be7f4f103c36507cb2a753418791b1cdc182" }, "type_url": "type.googleapis.com/protocol.TriggerSmartContract" }, "type": "TriggerSmartContract" } ], "ref_block_bytes": "3a27", "ref_block_hash": "83ca272ba6030b83", "expiration": 1581935001000, "fee_limit": 100000000, "timestamp": 1581934943649 }, "raw_data_hex": "0a023a27220883ca272ba6030b8340a8fbb195852e5ab401081f12af010a31747970652e676f6f676c65617069732e636f6d2f70726f746f636f6c2e54726967676572536d617274436f6e7472616374127a0a15417946f66d0fc67924da0ac9936183ab3b07c811261215419e62be7f4f103c36507cb2a753418791b1cdc1822244a9059cbb000000000000000000000000d148171f1ceeeb40d668c47d70e7e94e679775590000000000000000000000000000000000000000000000000000000000000064280a30c1843d70a1bbae95852e900180c2d72f" } } // output-end ``` Example with a `tuple` input (struct): ```javascript // solidity: function setStruct((address a, trcToken b, address c) _s) const funcABIV2 = { name: 'setStruct', type: 'function', inputs: [ { name: '_s', type: 'tuple', components: [ { name: 'a', type: 'address' }, { name: 'b', type: 'trcToken' }, { name: 'c', type: 'address' } ] } ], outputs: [] }; const transactionWrapper = await tronWeb.transactionBuilder.triggerSmartContract( 'TQQg4EL8o1BSeKJY4MJ8TB8XK7xufxFBvK', 'setStruct((address,trcToken,address))', { feeLimit: 100_000_000, funcABIV2, parametersV2: [['TPL66VK2gCXNCD7EJg9pgJRfqcRazjhUZY', 1000100, 'TPL66VK2gCXNCD7EJg9pgJRfqcRazjhUZY']] } ); ``` ### Legacy: positional `parameters` (flat signatures only) ```javascript const parameter = [ { type: 'address', value: 'TV3nb5HYFe2xBEmyb3ETe93UGkjAhWyzrs' }, { type: 'uint256', value: 100 } ]; const transactionWrapper = await tronWeb.transactionBuilder.triggerSmartContract( 'TQQg4EL8o1BSeKJY4MJ8TB8XK7xufxFBvK', 'transfer(address,uint256)', { feeLimit: 100_000_000, callValue: 0 }, parameter ); ``` ### Pre-encoded calldata: `options.rawParameter` Use this when you already have ABI-encoded argument bytes (e.g. cached from a previous call or produced by an external signer). Supply only the **arguments** portion — the 4-byte function selector is still derived from `functionSelector` by the builder. The `0x` prefix is optional. You can produce the encoded bytes with the same encoder TronWeb uses internally — `tronWeb.utils.abi.encodeParamsV2ByABI` — so the result is guaranteed to match what `funcABIV2` would have produced: ```javascript const funcABIV2 = { name: 'transfer', type: 'function', inputs: [ { name: '_to', type: 'address' }, { name: '_value', type: 'uint256' } ], outputs: [{ type: 'bool' }], stateMutability: 'nonpayable' }; const rawParameter = tronWeb.utils.abi.encodeParamsV2ByABI(funcABIV2, ['TV3nb5HYFe2xBEmyb3ETe93UGkjAhWyzrs', 100]); // rawParameter is now (0x prefix is optional): // 0x000000000000000000000000d148171f1ceeeb40d668c47d70e7e94e67977559 // 0000000000000000000000000000000000000000000000000000000000000064 const transactionWrapper = await tronWeb.transactionBuilder.triggerSmartContract( 'TQQg4EL8o1BSeKJY4MJ8TB8XK7xufxFBvK', 'transfer(address,uint256)', { feeLimit: 100_000_000, callValue: 0, rawParameter // overrides funcABIV2 / parametersV2 / positional parameters }, [], 'TM2TmqauSEiRf16CyFgzHV2BVxBejY9iyR' ); ``` To bypass the `functionSelector` step entirely and provide the **full** calldata (selector + arguments) as a single hex string, omit `functionSelector` and use `options.input` instead. ### Sign and broadcast After obtaining the wrapper: ```javascript const signedTx = await tronWeb.trx.sign(transactionWrapper.transaction); const result = await tronWeb.trx.sendRawTransaction(signedTx); ```