triggerSmartContract <src>
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.
options.funcABIV2 + options.parametersV2Use 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
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. Defaults: feeLimit = tronWeb.feeLimit, callValue = 0. | 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:
options.rawParameter— already-encoded hex calldata (with or without0xprefix).options.shieldedParameter— alias ofrawParameterfor shielded-pool flows.options.funcABIV2+options.parametersV2— recommended default. Encoded viaencodeParamsV2ByABI; supportstuple, nestedtuple[], dynamic arrays, etc.- Positional
parameters— legacy ABI v1 encoder. Works for flat signatures only; does not support tuples. options.input— used as rawdatawhenfunctionSelectoris omitted entirely.
Notes on parameter encoding
addressandaddress[]values are normalized to the EVM0x…form before encoding; you may pass base58 (T…), hex (41…), or0x…strings.trcTokenis internally treated asuint256when ABI-encoded.- When
options.txLocalistrue, the transaction is constructed entirely on the client (the function selector + parameters are hashed locally withkeccak256) and no network request is made; otherwise the node'swallet/triggersmartcontractendpoint is called. options.permissionIdmay be supplied for multi-signature transactions.
Validation
The following constraints are enforced before the request is issued; violations throw synchronously:
feeLimitmust be a positive integer.callValuemust be a non-negative integer.parametersmust be an array.contractAddressmust be a valid TRON address.issuerAddress,tokenId, andtokenValueare validated when provided.
Returns
A wrapper which contains the unsigned transaction object.
interface TransactionWrapper {
result: {
result: boolean;
};
/**
* The unsigned transaction object created by calling the contract function.
*/
transaction: Transaction;
}
Example
Recommended: funcABIV2 + parametersV2
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"
);
{
"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"
}
}
Example with a tuple input (struct):
// 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)
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:
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:
const signedTx = await tronWeb.trx.sign(transactionWrapper.transaction);
const result = await tronWeb.trx.sendRawTransaction(signedTx);