Account Permission Management
How TRON accounts support multi-party control through weighted permissions and signature thresholds.
A TRON account does not need to be controlled by a single private key. Through Account Permission Management (TIP-16), an account can be jointly operated by multiple parties — each holding their own keys, each with a configurable weight, and each transaction authorized only when the sum of signatures meets a threshold.
This page covers the three permission types, the threshold-and-weight model, the structure of the permission update contract, the operations bitmap that restricts active permissions to specific contract types, and the fees charged for permission updates and multi-signed transactions.
Prerequisites
Permission types
Each TRON account has three permission slots:
| Permission | Default purpose | Notes |
|---|---|---|
| Owner | Full control — can execute any contract type and modify the account's own permissions | Created by default for new accounts with ID 0 |
| Witness | Used by Super Representative (SR) accounts to sign block production | Must contain exactly 1 key; cannot authorize normal contract transactions |
| Active | Custom-scoped permissions for delegated operation | One is created by default with ID 2; up to 8 per account |
The proto-level name witness_permission is the same as what TRON prose calls "Super Representative (SR) permission". This page uses Witness when referring to the permission type (matching the code), and SR when discussing the role. For the broader witness-vs-SR convention, see Consensus and DPoS.
Threshold and weight
A permission is authorized when the sum of signing weights meets or exceeds the threshold. Each permission is configured with:
- A threshold — a positive integer
- A list of keys, each with a base58 address and a weight (
int64)
When a transaction is signed, the network recovers the signing addresses, looks them up in the relevant permission's keys list, sums the weights of the recognized signers, and checks the sum against the threshold.
The configuration must satisfy these constraints (enforced at AccountPermissionUpdateContract validation):
| Rule | Detail |
|---|---|
| Max keys per permission | Fixed at 5 |
| Distinct addresses | A keys list cannot contain the same address twice |
| Positive weights | Each key's weight > 0 |
| Sum ≥ threshold | The sum of all key weights must be at least the threshold (otherwise threshold is unreachable) |
permission_name length | At most 32 bytes |
parent_id | Must be 0 |
| Witness permission single-key | Witness type permissions must contain exactly 1 key |
Single-signer (default)
A new account starts with one owner permission and one active permission. Both have a threshold of 1 and a key list containing only the account's own address with weight 1. The default active permission also contains the network-defined operations bitmap. The initial owner permission is:
threshold: 1
keys:
- address: <account's own address>, weight: 1For either default permission, the account's private key contributes weight 1 and meets the threshold. A transaction using the active permission must also have its contract type enabled in the permission's operations bitmap.
Multi-party
A 2-of-3 owner permission across three parties:
threshold: 2
keys:
- address: TKey1...AA, weight: 1
- address: TKey2...BB, weight: 1
- address: TKey3...CC, weight: 1Any two of the three signers can authorize a transaction.
Weighted
Different parties can hold different authority levels:
threshold: 3
keys:
- address: TFounder...A, weight: 2
- address: TCofnd1...B, weight: 1
- address: TCofnd2...C, weight: 1A founder (weight 2) plus any one cofounder (weight 1) reaches threshold 3. Either cofounder alone (weight 1) does not. Both cofounders working without the founder (1 + 1 = 2) does not.
Active permissions and contract restrictions
Active permissions go beyond simple multi-sig: each active permission carries an operations field that restricts which contract types it may execute. This lets you grant a delegate the authority to perform specific actions without exposing the full owner permission.
The operations field is a 32-byte (256-bit) bitmap encoded little-endian. Each bit corresponds to a ContractType value from Tron.proto. Contract type ID n is bit (n & 7) of byte n / 8:
- ID
0→ byte 0, bit 0 (least-significant bit of first byte) - ID
7→ byte 0, bit 7 - ID
8→ byte 1, bit 0 - ID
59→ byte 7, bit 3
A bit set to 1 means "this permission can execute this contract type". A bit set to 0 means "this contract type is forbidden under this permission".
Contract type IDs
Every TRON contract type has a numeric ID from the Transaction.Contract.ContractType proto enum. The table below lists popular transaction supported on mainnet:
| ID | ContractType | Description |
|---|---|---|
| 0 | AccountCreateContract | Create an account |
| 1 | TransferContract | Transfer TRX |
| 2 | TransferAssetContract | Transfer a TRC-10 token |
| 4 | VoteWitnessContract | Vote for a Super Representative |
| 5 | WitnessCreateContract | Apply to become an SR candidate |
| 11 | FreezeBalanceContract | Stake 1.0 — stake TRX |
| 12 | UnfreezeBalanceContract | Stake 1.0 — unstake TRX |
| 13 | WithdrawBalanceContract | Withdraw voting rewards |
| 16 | ProposalCreateContract | Create a governance proposal |
| 17 | ProposalApproveContract | Approve a proposal |
| 30 | CreateSmartContract | Deploy a smart contract |
| 31 | TriggerSmartContract | Call a smart contract |
| 33 | UpdateSettingContract | Update consume_user_resource_percent |
| 45 | UpdateEnergyLimitContract | Adjust the Energy limit a deployer subsidizes |
| 46 | AccountPermissionUpdateContract | Update account permissions |
| 48 | ClearABIContract | Clear a contract's ABI |
| 49 | UpdateBrokerageContract | Update SR brokerage rate |
| 54 | FreezeBalanceV2Contract | Stake 2.0 — stake TRX |
| 55 | UnfreezeBalanceV2Contract | Stake 2.0 — unstake TRX |
| 56 | WithdrawExpireUnfreezeContract | Withdraw unstaked TRX after the cooldown |
| 57 | DelegateResourceContract | Delegate Bandwidth or Energy |
| 58 | UnDelegateResourceContract | Cancel resource delegation |
| 59 | CancelAllUnfreezeV2Contract | Cancel all pending unstake operations |
Source:
protocol/src/main/protos/core/Tron.protoenum ContractType. The list reflects the protocol as of java-tron v4.8+. For the source-of-truth enum, also see Details of supported transaction types.
Computing the operations bitmap
To allow a permission to execute, say, TRX transfers (ID 1), SR voting (ID 4), and Stake 2.0 staking (ID 54), compute the bitmap by setting bits 1, 4, and 54:
import org.bouncycastle.util.encoders.Hex;
int[] contractIds = { 1, 4, 54 }; // TransferContract, VoteWitnessContract, FreezeBalanceV2Contract
byte[] operations = new byte[32];
for (int id : contractIds) {
operations[id / 8] |= (byte) (1 << (id % 8));
}
System.out.println(Hex.toHexString(operations));
// "1200000000004000000000000000000000000000000000000000000000000000"Decode in the reverse direction:
public static List<Integer> decodeOperations(String operationsHex) {
byte[] ops = Hex.decode(operationsHex);
List<Integer> ids = new ArrayList<>();
for (int i = 0; i < ops.length; i++) {
for (int bit = 0; bit < 8; bit++) {
if ((ops[i] >> bit & 0x1) == 1) {
ids.add(i * 8 + bit);
}
}
}
return ids;
}Worked encoding examples
| Operations allowed | Binary (big-endian by byte, low bit first within each byte) | Hex (little-endian byte order) |
|---|---|---|
| TransferContract (ID 1) + VoteWitnessContract (ID 4) | 00010010 00000000 00000000 … | 12 00 00 … |
| TransferContract (ID 1) + UpdateAssetContract (ID 15) | 00000010 10000000 00000000 … | 02 80 00 … |
| All system contracts (per Mainnet defaults) | 01111111 11111111 00011111 … | 7F FF 1F … |
Decoding a hex string by eye: read each byte as a binary nibble pair, with the least-significant bit being the lowest contract ID for that byte. Byte 0's bit 0 = contract type ID 0; byte 0's bit 7 = ID 7; byte 1's bit 0 = ID 8; and so on.
Use case: a hot key for transfers only
A treasury account's owner permission is held by a multi-sig group. To pay routine vendor invoices without convening the multi-sig every time, the treasury creates an active permission with:
- A single-signer threshold (e.g.,
threshold: 1, one delegate key withweight: 1) - An
operationsbitmap that allows onlyTransferContract(ID 1) — hex02 00 00 … - All other contract types disabled — the delegate cannot stake, vote, deploy contracts, or modify permissions
The delegate's hot key can sign vendor transfers, but cannot perform any other operation. The owner permission remains in cold storage.
Updating permissions
To modify any permission, the account submits an AccountPermissionUpdateContract transaction. The contract replaces the complete permission configuration: even if you only want to change one active permission, you must submit the new owner permission and the complete active-permission list. An SR account must also submit its new Witness permission; a non-SR account must not submit a Witness permission.
message AccountPermissionUpdateContract {
bytes owner_address = 1;
Permission owner = 2;
Permission witness = 3;
repeated Permission actives = 4;
}| Field | Description |
|---|---|
owner_address | The account being modified |
owner | The new owner permission (required, not optional) |
witness | The new Witness permission (only meaningful for SR accounts; otherwise null) |
actives | The new list of active permissions (1–8 required) |
The transaction is normally authorized by the account's current owner permission. An active permission can also authorize it when the transaction selects that permission and its operations bitmap enables AccountPermissionUpdateContract (ID 46).
A misconfigured update can make permissions unrecoverableThe node validates structural constraints such as permission types, address formats, key count, weights, thresholds, and active-permission bitmaps. It cannot verify that the operator actually controls the private keys for the addresses in
keys. If the owner permission cannot meet its threshold and no usable active permission enables ID 46, the account's permissions cannot be changed again. Access to assets and operations then depends on the remaining active permissions and theiroperationsbitmaps; an SR's Witness permission can still authorize block signing independently. Before submitting:
- Rehearse the same payload on Shasta or Nile, and verify that the intended signer combinations can meet the threshold and complete a transaction.
- Check every Base58Check address character by character and confirm that its private key is currently usable.
- For each planned key-loss scenario, confirm that the remaining usable weight can still meet the threshold.
- For a staged migration, you may temporarily retain the current owner key in the new
keyslist if it remains trusted, then remove it after validating the other keys. Do not retain a key that may be compromised.- Create a threshold-1 active permission only when the application explicitly needs a single-key emergency path. It becomes a single-key authorization path for every operation enabled in its bitmap, so restrict
operationsand leave ID 46 disabled unless that key is intentionally allowed to change account permissions.See Reverting the owner permission to single-signature below.
Permission_id in transactions
Every transaction declares which permission level it is signed under via Permission_id in the contract body:
| Permission_id | Permission |
|---|---|
| 0 | Owner permission (default if omitted) |
| 1 | Witness permission — reserved for SR block production; cannot authorize normal contract transactions |
| 2–9 | Active permissions, in the order they were added to the account |
The id of an active permission is automatically assigned by the network in sequence starting at 2. For any Permission_id != 0, the permission's type must equal Active and the requested contract type must be allowed by the operations bitmap; otherwise the transaction is rejected with Permission type is wrong! or Permission denied!.
Fees
Permission management on TRON charges two kinds of fees. Both are dynamic chain parameters and can be adjusted by governance proposal — query the live values via wallet/getchainparameters rather than hard-coding them.
| Fee | Chain parameter | Current Mainnet value (query-time snapshot) | When charged |
|---|---|---|---|
| Update account permissions | #22 getUpdateAccountPermissionFee | 100 TRX (100,000,000 sun) | Every AccountPermissionUpdateContract transaction |
| Multi-signature surcharge | #23 getMultiSignFee | 1 TRX (1,000,000 sun) | Charged once when a transaction carries two or more signatures |
Both fees are added on top of the normal Bandwidth or Energy cost of the transaction.
Worked example: 2-of-3 multi-sig setup
The payload below configures a 2-of-3 owner permission and creates one active permission. It assumes that all three owner keys have been verified as usable. owner_address identifies the account being modified; that address does not also have to appear in owner.keys.
{
"owner_address": "TYourAccount...XX",
"owner": {
"type": 0,
"id": 0,
"permission_name": "owner",
"threshold": 2,
"keys": [
{ "address": "TKey1...AA", "weight": 1 },
{ "address": "TKey2...BB", "weight": 1 },
{ "address": "TKey3...CC", "weight": 1 }
]
},
"witness": null,
"actives": [
{
"type": 2,
"id": 2,
"permission_name": "active0",
"threshold": 1,
"operations": "120000000000c00f000000000000000000000000000000000000000000000000",
"keys": [
{ "address": "TKey2...BB", "weight": 1 }
]
}
]
}After this transaction confirms, all owner-level operations on the account require any two of the three keys. The active0 permission (id 2) lets TKey2 execute the operations enabled by the operations bitmap on its own. The bitmap here enables TRX transfers, SR voting and the Stake 2.0 contracts (IDs 1, 4, 54–59), computed with the method under "Computing the operations bitmap" above; it does not enable permission updates (ID 46). This active permission is a single-key path for the enabled operations and should be configured only when it matches the account's security policy.
For the end-to-end transaction flow with multi-party signing, see Account Permission Management transaction example.
Reverting the owner permission to single-signature
The owner permission can be changed back to single-signature as long as a current permission can authorize AccountPermissionUpdateContract: normally an owner permission that meets its threshold, or a usable active permission whose bitmap enables ID 46. Submit another permission update with one key in owner.keys and threshold: 1, together with the complete list of 1–8 active permissions. An SR account must also submit its Witness permission; a non-SR account omits it or passes null. The update fee applies again (100 TRX on Mainnet at the time of writing).
This changes only the owner permission. Existing active permissions can still authorize the operations enabled in their respective operations bitmaps. To place the entire account under the same single key, also set the keys and threshold of every active permission to that single-key configuration, while retaining only the required operations. Witness is a separate single-key permission used by an SR for block production and should be changed only when its signing address also needs to change.
If the owner permission cannot meet its threshold and no usable active permission enables ID 46, the permission update cannot be authorized and the owner permission cannot be changed back to single-signature.
Limits
| Limit | Value |
|---|---|
| Maximum keys per permission | Fixed at 5 |
| Active permissions per account | 1–8 |
permission_name length | 32 bytes |
Permission_id range | 0–9 (0 = owner, 1 = Witness, 2–9 = active) |
| Witness permission key count | Must be exactly 1 |
Active permission parent_id | Must be 0 |
APIs
| API | Description |
|---|---|
wallet/accountpermissionupdate | Update account permissions |
wallet/getsignweight | Inspect collected signature weight on a partial transaction |
wallet/getapprovedlist | List addresses that have signed |
wallet/broadcasttransaction | Submit a fully-signed transaction |
Related resources
- Account Permission Management transaction example — End-to-end multi-sig walkthrough
- Signature validation — How signatures are checked
- Accounts and keys — Account basics
- Details of supported transaction types — Full
ContractTypereference - TIP-16 — The original specification
Updated 5 days ago