← All articles

Same-Permission-Key Detection: How Permission Rotation Reveals Control Changes on TRON

Part of Who Controls a TRON Wallet? A Complete Guide to TRON Address Attribution

Key takeaways

  • TRON stores control directly in account state, so one wallet/getaccount call answers who can move funds right now — no contract decoding, unlike Ethereum's Safe.
  • The same address showing up in two accounts' key lists means they share an operator. That's a more direct attribution signal than any transaction-graph link.
  • Every permission change is one on-chain transaction that overwrites the whole state, so rotations are dated to the block and diffable key-by-key — readable as a control-handoff timeline.
  • Rotation can mean hardening, a sale, or a hostile takeover. Three diagnostics — key persistence, threshold direction, post-rotation activity — tell them apart.

TRON’s permission system produces two on-chain signals no other major chain offers in the same form. The same signing address can appear in multiple accounts’ permission key lists, which makes operator clustering visible without any cryptographic correlation. And every change to an account’s permission structure is an explicit on-chain transaction with all-or-nothing semantics, so ownership transitions read as precise events with verifiable timestamps.

This is the methodology layer on top of those signals. For the protocol mechanics — what Owner and Active permissions are, how threshold signatures work, what AccountPermissionUpdateContract does, how to read wallet/getaccount — see The TRON Account Model. Here the focus is attribution: what the signals mean, what attacks they expose, what false positives degrade them, and how an investigator weighs them.

Permission state is the cleanest control signal

Every TRON account encodes who can authorize its transactions directly in protocol state. The Owner permission lists the keys that can do anything — including reconfiguring the account itself — at a threshold those keys must collectively meet; Active permissions list keys scoped to specific operation sets. One call, POST /wallet/getaccount, returns the complete current permission state of any account.

EX. 1 TRON account WALLET/GETACCOUNT EX. 2 Owner permission TYPE 0 · ID 0 · CAN RECONFIGURE THE ACCOUNT keys: { address, weight } × up to 5 threshold: min combined weight to authorize KEY EX. 3 Active permission(s) TYPE 2 · ID 2+ · ARRAY UP TO 8 operations bitmask scopes which contract types it can sign EX. 4 Witness permission TYPE 1 · ID 1 · SR ACCOUNTS ONLY controls block production — presence signals SR status, not takeover [ ROOT CONTROL ] [ DEFAULT NEW ACCOUNT — OWN ADDRESS · WEIGHT 1 · THRESHOLD 1 ]
Control lives in the account itself — one call returns the whole structure.

No other major chain exposes this as a first-class protocol feature. Ethereum’s nearest equivalent — Safe (formerly Gnosis Safe) — is a smart contract layered on the account model. The keys controlling a Safe live in the contract’s storage, reachable only by decoding contract state. TRON’s permissions live in the account itself, named in the same response that returns the balance.

Permission state is therefore the most authoritative on-chain answer to who controls a wallet right now. Transaction history tells you who has interacted with the account over time; permission state tells you who has the present right to move funds. A divergence between the two — recent senders who aren’t among the current Owner-permission keys — is a signal worth chasing.

This is why permission state deserves to be read as authority in its own right. Sound attribution is rule-first here: a controlling Owner-permission key holder can be named the controller directly from that evidence, without inferring it from anything else; and when no permission evidence exists, the honest move is to abstain rather than name a controller from behavioral signals alone.

A shared key is a shared operator

A TRON permission key is a TRON address rather than a raw public key: the protocol records each authorized signer as an address-and-weight pair, identical in form to the addresses in transaction histories. Query wallet/getaccount for two unrelated wallets and find the same address in both key arrays, and those accounts share an operator. The shared address is the operator.

Transaction-graph analysis never gets this direct. A funding-flow link between two wallets could be shared control, or it could just be a payment. A shared permission key is unambiguous: someone deliberately granted that specific address the right to sign on both accounts. And the grant is itself an on-chain AccountPermissionUpdateContract, attributable to whoever held Owner permission at the moment of grant.

Not all reuse is equal

Owner-key reuse across accounts is the strongest signal. Owner permission can execute any contract type, including reconfiguring the account, so an address in the Owner key list of two accounts holds the master keys to both, with no scope restriction.

Active-key reuse is weaker, because Active permissions are bounded by an operations bitmask — the protocol’s encoded list of which contract types the permission can authorize. The default bitmask (7fff1fc0033efb07...) is explicitly all contracts except permission updates, so an Active-only signer can’t rotate keys. The signal points to operational sharing rather than root control.

Weakest of the three is the same address showing up as transaction payer on permission updates. The payer broadcast and paid for the update but isn’t necessarily a key holder — anyone with Owner permission could sign an update broadcast from any address with TRX to spare.

A coordinated wallet set usually shows one of two shapes. The personal-operator pattern: every wallet’s Owner permission lists the same key — the operator’s address — at weight ≥ threshold, single-key, with Active permissions adding session keys or hot-wallet delegates that vary across the set. The institutional pattern: every wallet’s Owner permission lists the same multi-sig committee, often 2-of-3 or 3-of-5, with the same key addresses recurring across all the institution’s custody accounts.

One gap to note. For a single wallet, a key holder who has never transacted with it is still fully visible — both the live snapshot and the decoded permission-update history name the current key holders directly, whether or not those addresses ever moved funds. What no on-chain query does for you is enumerate the same key across other wallets as a clustering signal: a wallet/getaccount call sees only the wallet you asked about. Building that cross-wallet view means repeating the query against the suspect key, account by account.

Rotation events as ownership history

AccountPermissionUpdateContract (contract type 46) is the only transaction that modifies an account’s permission structure. It carries a 100 TRX protocol fee, plus an extra 1 TRX multi-signature fee when the current Owner permission needs a quorum to sign — a cost set high enough to make permission updates infrequent by design. Most TRON wallets never run one.

Each update specifies the complete desired state of all permissions. The TRON docs are blunt about it:

“This interface will override the original account permissions, so even if you only want to modify the owner permission, you still need to configure the witness (if it is a witness account) and active permissions.”

So every AccountPermissionUpdateContract in a wallet’s history is a full permission snapshot at that moment. Diff two consecutive updates and you reconstruct exactly which keys were added, removed, reweighted, or re-thresholded. There’s no partial-update mode to muddy the picture. The block-level guarantee sharpens the timestamp: a block containing a permission update excludes any further transactions from that account in the same block, so the change takes effect from the next block. The transaction’s block timestamp is therefore the exact activation moment of the new state — and every outbound transfer after it is attributable to whoever held the new keys.

EX. 1 EX. 2 EX. 3 Permission state A KEYS: ORIGINAL Update tx CONTRACT TYPE 46 Permission state B KEYS: NEW SET KEY [ BEFORE ] [ BLOCK TIMESTAMP ] [ FROM NEXT BLOCK ] Full snapshot each time — diff A → B = exact key changes Every outbound after this point = new key holder
The full-snapshot-each-time rule turns rotation history into a diffable, block-dated handoff timeline.

Rotation, transfer, or takeover?

On its own, a rotation event doesn’t tell you which of the three you’re looking at. What does:

Routine rotation HARDENING · TRANSFER Hostile takeover THE ATTACK PATTERN EX. 1 EX. 2 EX. 3 EX. 4 EX. 5 EX. 6 ORIGINAL KEYS Kept at meaningful weight ORIGINAL KEYS All replaced with unseen addresses THRESHOLD Raised (1-of-1 → 2-of-3) THRESHOLD Cut to 1 (or weight-asymmetric) ACTIVITY AFTER Months of normal use ACTIVITY AFTER Drain within hours / days KEY [ SAME THREE DIAGNOSTICS · READ ACROSS BOTH COLUMNS ]
The same three diagnostics, read across both columns.

The hostile-takeover playbook

Security firms on TRON have documented permission-rotation attacks in three variants. SlowMist’s casework covers the first two; OKX’s wallet-security guidance covers the third.

Variant 1 — add the attacker as a co-signer with a raised threshold. The user’s original key stays in the Owner key list, but the attacker’s address joins as a second key and the threshold rises to 2. The user can still sign yet can’t meet threshold alone, so the account is “jointly controlled” in form. In practice the attacker just refuses to co-sign:

“the hacker has added their own address as an authorized Owner/Active party. The account is now jointly controlled by the user and the hacker, with the threshold set at 2.”

Variant 2 — transfer all permissions to the attacker. The user’s key is removed from the Owner permission entirely; the attacker’s address becomes the sole Owner key at threshold 1. The user is locked out.

“hackers exploit TRON’s permission management system by directly transferring the user’s Owner/Active permissions to the hacker’s address, with the threshold still set at 1.”

Variant 3 — weight-asymmetric multi-sig. OKX documents a configuration where the attacker takes weight 2, the user weight 1, and the threshold is 3. Neither party signs alone. It looks “multi-sig secured”; in practice the user can never reach threshold without the attacker’s cooperation.

A concrete on-chain case

Token Trace’s November 2023 writeup documented the permission-trap pattern in the wild. The victim wallet TPpAzAmpY5PAJ72XtSKVayfCcHfRHevMPu had its Owner permission pre-assigned to scammer-controlled TYgYr17S9Zi1DocuuBCNiPLw6vq8VnEjAU before the victim ever imported the seed phrase the scammer handed them. Holding the seed phrase, the victim still couldn’t move the funds — the Owner permission was no longer his.

Both addresses are verifiable on Tronscan, and the configuration persists on-chain as of May 2026: the victim’s Owner permission still lists the scammer address as sole key at weight 1, threshold 1. The scammer address is uninitialized — no balance, no permission state, no outbound history. The scammer holds the private key but never funds the address; it works purely as a permission-holder. Watch for that shape in permission-trap cases — an Owner permission whose key is an address with no on-chain footprint of its own.

The silent-hijack scale claim

AMLBot, a blockchain-security firm, reported figures in January 2025 — shared with and published by Cointelegraph — putting the pattern’s scale at an estimated 14,545 TRON wallets at risk via the UpdateAccountPermission attack, with 2,130 compromised in Q4 2024 alone, holding roughly $31.5M in assets. AMLBot CTO Mykhailo Tiutin stressed the silent quality: wallet UIs don’t notify users when a new key is added, so a victim usually discovers the takeover only by attempting an outbound transaction.

These figures live in AMLBot’s report as shared with Cointelegraph rather than in a standalone AMLBot publication, and the underlying victim list and methodology aren’t public. Cite them as “AMLBot, via Cointelegraph” rather than as independently verifiable on-chain numbers.

Rotation isn’t the only takeover

A hot-wallet drain on TRON doesn’t have to involve AccountPermissionUpdateContract at all. The November 2023 Poloniex incident — a multi-chain hot-wallet drain that included substantial TRX and TRC-20 outflows from Poloniex’s TRON hot wallets — was a straightforward private-key compromise. The attackers used the stolen keys to broadcast outbound transactions directly; no permission update appears in the affected wallets’ histories. Halborn called it “a classic example of a compromised hot wallet,” and CertiK independently characterized it as a private-key compromise — specifically the second-largest such compromise CertiK detected in 2023.

So the absence of a permission update on a drained wallet carries information too. It separates a private-key compromise, where the attacker uses the keys directly, from a permission takeover, where the attacker rotates keys first and then drains. The two are different attacks, and they call for different incident-response postures and leave different forensic artifacts.

False positives and edge cases

Most TRON wallets carry no AccountPermissionUpdateContract events and use default single-key permissions. The protocol initializes each new account with a single key — the account’s own address — at weight 1, threshold 1, on both Owner and the first Active permission. A rotation is significant precisely because it deviates from that baseline. Several configurations would generate false positives if read naively:

  • MPC custody (Fireblocks-style). MPC providers compute signatures off-chain through multi-party computation, so the on-chain transaction carries a single signature from the address representing the combined key shares. There’s no on-chain permission-key reuse to detect — the same operational team signs across many client wallets, but each footprint is single-signer. MPC-custodied wallets cluster invisibly to permission analysis.
  • Witness permission on SR accounts. The witness_permission field appears only on Super Representative, SR Partner, and SR Candidate accounts, controls block-producing nodes, and is documented at TIP-105. A witness key separate from the Owner key is the documented best practice for SRs — block-production key on the validator node, funds key elsewhere. Its presence signals SR status rather than a takeover.
  • Pseudo multi-sig. Multiple Owner keys can exist while one key alone holds enough weight to meet threshold — visually multi-sig, functionally single-key. It pays to rate a permission configuration by how much its threshold actually constrains signing: strongest when no single key can authorize alone and the threshold demands a supermajority — at least two-thirds — of total key weight; weaker when one key dominates the threshold, or when the threshold clears half the total weight but falls short of two-thirds; weakest for single-key accounts and for genuine multi-sigs whose threshold sits below half the total weight. Pseudo multi-sig shows up often in exchange hot wallets, where backup keys exist but one operational key needs to sign quickly without quorum coordination.
  • Deliberate freeze. A threshold higher than the sum of all key weights renders the account unsignable by any combination of current keys — detectable from wallet/getaccount as threshold > sum(keys[].weight). It can be intentional (a self-imposed lock) or accidental (a config error). Either way the account can’t originate new outbound transactions until the threshold drops via another AccountPermissionUpdateContract, which needs Owner permission — which by definition no current key holder can authorize.
  • Institutional custody key reuse. Custody platforms using native TRON multi-sig (rather than MPC) may legitimately appear as a permission key across many unrelated client accounts. A custody-provided co-signer key is shared infrastructure that carries no ownership information — and without an external catalog of known custody signing keys it’s hard to filter automatically. The workaround is manual annotation of repeatedly-appearing institutional addresses.

Exchange hot wallets deserve their own note. Frequent AccountPermissionUpdateContract events on an exchange-attributed hot wallet may be routine operational rotation. Without external attribution, telling routine from compromise means reading the post-rotation pattern: normal customer-withdrawal volume is operational; a single large outbound to an unfamiliar address is the takeover pattern.

Weighing the permission signals

Permission state answers the control question in two complementary forms — a live snapshot of who holds the keys now, and a history of how those keys changed.

The control-handoff timeline

Permission-update history says nothing about who originated a wallet — a rotation is a control event, not a creation event. Each decoded AccountPermissionUpdateContract instead adds an entry to a dated control-handoff timeline: who gained keys, who lost them, and when. The timeline’s final key state, read together with the live permission snapshot, answers who controls the wallet now — directly, from the permission evidence itself. Key holders that a funding-flow analysis would never surface show up here on the same basis. It’s tempting to treat executing a permission update as “definitive ownership proof,” but that overreaches: on TRON, account creation is the one signal that definitively marks origin, while permission evidence answers the separate question of present control.

Weighing current-control roles

A live snapshot names every key holder, but what each one proves depends on its role:

Permission roleEvidentiary weight
Controlling Owner key (weight ≥ threshold, can authorize alone)Strongest evidence of control
Owner co-signer (cannot authorize alone)Moderate
Active-only permission key holderStrong
Original creator removed from all permission keysStrongest negative — points away

A creator removed from all keys is the strongest negative signal of the set — it points attribution away from whoever made the account. The weight it deserves comes from how often genesis-creator removal tracks a hostile rotation rather than a legitimate handoff; on TRON, that correlation is strong enough to treat full creator removal as a serious flag.

Weight also decays with age: recent updates weigh most, older ones progressively less. A permission update from years back is much weaker evidence of current operational involvement than a recent one.

Most wallets carry default permissions and rotate them never — so the ones that do rotate are signaling something, and the same mechanics that record the rotation record exactly when, by whom, and to what.

The cross-wallet gap

The two patterns worth naming as you read a configuration: the weighted-key-meets-threshold-alone shape (pseudo multi-sig, above), and a key-composition change consistent with control transfer. Both live entirely in the permission evidence — the live snapshot for the first, the control-handoff timeline for the second — so neither needs anything beyond wallet/getaccount and the decoded update history to detect.

The hard limit is cross-wallet, not per-wallet. For one wallet, permission-key holders who have never transacted with it are fully readable — someone holding Owner permission via a single AccountPermissionUpdateContract, or appearing only in the live snapshot, is right there in the account state. What no on-chain query does is cluster the same key across wallets: nothing enumerates the other accounts where a given wallet’s keys also appear. The cross-wallet clustering described earlier therefore stays a manual workflow.

Investigative workflow

Two API surfaces matter for permission-state forensics.

Current state — wallet/getaccount

POST https://api.trongrid.io/wallet/getaccount with body { "address": "T...", "visible": true } returns the full account object including owner_permission, active_permission (array, up to 8), and witness_permission (SR accounts only). Each permission object exposes:

  • type0 Owner, 1 Witness, 2 Active
  • id — Owner always 0, Witness 1, Active starts at 2
  • permission_name — human-readable label
  • threshold — minimum combined weight to authorize
  • keys — array of { address, weight } pairs, up to 5 entries
  • operations (Active only) — 256-bit hex bitmask, little-endian bytes, big-endian bits within each byte (TIP-105 encoding)

This is the canonical query for “who controls this wallet right now” — unauthenticated, free, one round trip.

Historical changes — enumerating permission updates

TronGrid can’t filter an address’s transactions by contract type; v1/accounts/:address/transactions returns everything undifferentiated. Two practical paths to isolate the permission updates:

  1. TronScan API filter. GET https://apilist.tronscanapi.com/api/transaction?sort=-timestamp&limit=50&address=T...&contract_type=46 returns only permission-update transactions. Direct calls now require a TronScan API key sent in the TRON-PRO-API-KEY header — without one the endpoint answers 401 Authorization Required. The contract_type=46 parameter is observably supported and used by their frontend, though not formally documented in the public API reference.
  2. Client-side filtering. Fetch the full history via TronGrid’s v1 endpoint and filter locally on tx.raw_data.contract[0].type === 'AccountPermissionUpdateContract'. More API calls, but keyless and built entirely on documented endpoints — the free path.

Each transaction’s raw_data.contract[0].parameter.value carries the complete new permission state (owner, actives[], optional witness) plus the owner_address of the modified account. Pair the value with a wallet/getaccount snapshot from the moment before the update and you reconstruct the diff — exactly which keys changed and how.

Cross-wallet key reuse

This workflow is manual today — a wallet’s own key holders are readable directly, but nothing on-chain clusters the same key across wallets:

  1. Pull a candidate key from the analyzed wallet’s wallet/getaccount Owner permission.
  2. Search for other accounts where the same address appears as a permission key. There’s no native TRON API for “find all accounts where address X is a permission key”; practical paths are (a) keep your own catalog of the address and let cross-references accumulate as you work through more wallets, (b) query commercial chain-analytics platforms that index permission state across all TRON accounts, or (c) maintain an investigator-side index built by crawling wallet/getaccount.
  3. For each shared-key account, repeat the full attribution. The shared key is the operator; the question is what other signals — delegation, fueling (see Who Pays the Fees?), transaction patterns — confirm or qualify it.

What this means for investigators

Permission state and rotation history together expose the structure of control on TRON in a way no transaction graph can match. A wallet’s keys, and the moments those keys changed, are first-class protocol records — visible, queryable, dated to the block. Records aren’t attribution by themselves, though. Getting from one to the other means ranking shared-key signals by strength, separating rotation types by their accompanying activity, filtering the false positives that institutional custody and MPC introduce, and then interpreting what’s left.

Sources

Primary and authoritative sources used for the facts in this article: