TecraCoin TcrToken burnFrom Allowance Bug Exploits
Exploit Transactions
0x81e9918e248d14d78ff7b697355fd9f456c6d7881486ed14fdfb69db16631154Victim Addresses
0x420725a69e79eeffb000f98ccd78a52369b6c5d4Ethereum0xe38b72d6595fd3885d1d2f770aa23e94757f91a1EthereumLoss Breakdown
Similar Incidents
SchnoodleV9 reflection allowance bug drains SNOOD/WETH liquidity
36%GPv2Settlement allowance leak lets router drain WETH and USDC
35%Dexible selfSwap allowance drain
34%Access-control bug draining 5 ETH from token contract
33%SilicaPools decimal-manipulation bug drains WBTC flashloan collateral
32%WBTC Drain via Insecure Router transferFrom Path
32%Root Cause Analysis
TecraCoin TcrToken burnFrom Allowance Bug Exploits
1. Incident Overview TL;DR
On Ethereum mainnet block 14139082, an unprivileged attacker used a single contract-creation transaction to exploit a bug in TecraCoin's TcrToken contract. The exploit destroyed the TCR balance of a TCR/USDT liquidity pool and swapped that exposure into USDT via Uniswap, delivering 639,222.253258 USDT to the attacker's externally owned account (EOA).
The root cause is a mis-indexed allowance check in TcrToken.burnFrom. Instead of checking the victim's allowance to the spender, the implementation checks and updates _allowances[msg.sender][from]. This allows any caller that self-approves a victim address to burn tokens from that victim without the victim's consent. The attacker packaged this bug into a constructor that approves and then calls the vulnerable burn path against the TCR/USDT pool, followed by swaps to drain USDT.
2. Key Background
TecraCoin's TcrToken contract at 0xe38b72d6595fd3885d1d2f770aa23e94757f91a1 is an ERC20-style token with standard _balances and _allowances mappings, owner and pauser roles, blacklist functionality, and burn/burnFrom helpers implemented in Contract.sol. The token uses 8 decimals, a fixed maxSupply, and exposes the typical transfer, transferFrom, and approve interfaces, plus additional bulk transfer and upgrade hooks.
The principal victim of this incident is a TCR/USDT liquidity pool at 0x420725a69e79eeffb000f98ccd78a52369b6c5d4. This pool holds reserves of TCR and USDT and is serviced by the canonical UniswapV2 router at 0x7a250d5630b4cf539739df2c5dacb4c659f2488d. The exploit contract uses the router to route swaps through this pool, converting the destroyed TCR exposure into USDT and sending the proceeds to the attacker EOA.
In a correct ERC20 design, a burnFrom(from, amount) helper uses the allowance mapping as _allowances[from][msg.sender]. The spender (caller) can only burn tokens from from that from has explicitly allowed. This enforces the invariant that destructive operations on a holder's balance are gated by that holder's approvals.
3. Vulnerability Analysis & Root Cause Summary
The vulnerability is an authorization bug in TcrToken.burnFrom(address from, uint256 amount). The function checks allowance by reading _allowances[msg.sender][from] and then calls _approve(msg.sender, from, ...) before burning from's balance. This reverses the indices in the allowance mapping.
As a result, any caller can:
- Call
approve(victim, amount)from their own address, which writes to_allowances[msg.sender][victim]. - Immediately call
burnFrom(victim, amount)(directly or via a contract).
Because the function consults _allowances[msg.sender][victim], the call passes the allowance check and burns the victim's tokens even though the victim never consented. The exploit contract deploys with constructor logic that performs large self-approvals and then calls the vulnerable burn path against the TCR/USDT pool address, followed by swaps through UniswapV2Router02 to pull USDT out of the same pool.
This is an ACT (anyone-can-take) opportunity: any unprivileged EOA that can pay gas and deploy an equivalent exploit contract can reproduce the same sequence against the same vulnerable TcrToken deployment and a TCR-funded pool.
4. Detailed Root Cause Analysis
4.1 Vulnerable token implementation
The TecraCoin TcrToken contract implements burn and burnFrom as follows (excerpt from the verified source):
function burn(uint256 amount) external {
require(_balances[msg.sender] >= amount, ERROR_BTL);
_burn(msg.sender, amount);
}
function burnFrom(address from, uint256 amount) external {
require(_allowances[msg.sender][from] >= amount, ERROR_ATL);
require(_balances[from] >= amount, ERROR_BTL);
_approve(msg.sender, from, _allowances[msg.sender][from] - amount);
_burn(from, amount);
}
The allowance mapping is declared as:
mapping(address => mapping(address => uint256)) private _allowances;
Everywhere else, allowance-related operations treat the mapping as _allowances[owner][spender]. However, in burnFrom, the check and subsequent _approve call both use _allowances[msg.sender][from], effectively treating msg.sender as the owner and from as the spender. This breaks the standard invariant:
For any holder
Hand spenderS, a destructive burn ofH's balance viaburnFrom(H, amount)must only succeed if_allowances[H][S] >= amountandHhas explicitly granted that allowance toS.
With the indices reversed, an attacker can:
- Call
approve(victim, amount)from their EOA, which sets_allowances[attacker][victim] = amount. - Use an attacker-controlled contract as
msg.senderto callburnFrom(victim, amount), relying on the mis-indexed lookup to see a large allowance and then burn the victim’s balance.
4.2 Pre-state and pool balances
The ACT pre-state σ_B is Ethereum mainnet state just before inclusion of the exploit transaction 0x81e9918e248d14d78ff7b697355fd9f456c6d7881486ed14fdfb69db16631154 in block 14139082. The collected prestate balance diff shows the TCR/USDT pool’s TCR balance:
{
"token": "0xe38b72d6595fd3885d1d2f770aa23e94757f91a1",
"holder": "0x420725a69e79eeffb000f98ccd78a52369b6c5d4",
"before": "58027283904946",
"after": "10214462474",
"delta": "-58017069442472",
"contract_name": "TcrToken"
}
This shows that, over the course of the exploit transaction, the pool loses exactly 58,017,069,442,472 raw TCR units, matching the amount burned in the constructor path described below.
4.3 Exploit constructor and burn sequence
The seed transaction is a type‑2 contract-creation transaction from EOA 0xb19b7f59c08ea447f82b587c058ecbf5fde9c299 with hash:
0x81e9918e248d14d78ff7b697355fd9f456c6d7881486ed14fdfb69db16631154
The receipt confirms deployment of contract 0x6653d9bcbc28fc5a2f5fb5650af8f2b2e1695a15 and significant interactions with WETH9, USDT, TcrToken, the TCR/USDT pool, and UniswapV2Router02. The trace (trace.cast.log) and decoded calldata show the constructor performing the following high-level steps:
- Approve UniswapV2Router02 (
0x7a250d5630b4cf539739df2c5dacb4c659f2488d) to spend unlimited USDT and TCR on behalf of the exploit contract. - Approve the TCR/USDT pool address
0x420725a69e79eeffb000f98ccd78a52369b6c5d4for a very large TCR allowance using TcrToken’sapprove. - Call the vulnerable
burnFrom-style function on TcrToken withfrom = 0x420725a69e79eeffb000f98ccd78a52369b6c5d4andamount = 58017069442472TCR units, relying on the mis-indexed_allowances[msg.sender][from]mapping to satisfy the allowance check based on the earlier self-approval. - Route swaps through UniswapV2Router02 and the TCR/USDT pool so that the destroyed TCR exposure results in a large USDT transfer from the pool to the exploit contract, and then onward to the attacker EOA.
USDT Transfer logs in the exploit receipt show:
{
"address": "0xdac17f958d2ee523a2206206994597c13d831ec7",
"data": "0x0000000000000000000000000000000000000000000000000000000006ba2816",
"topics": [
"Transfer(...)",
"0x0000000000000000000000000d4a11d5eeaac28ec3f61d100daf4d40471f1852",
"0x000000000000000000000000420725a69e79eeffb000f98ccd78a52369b6c5d4"
]
}
and a subsequent Transfer from the exploit contract to the attacker EOA, confirming that 639222253258 raw USDT units (639,222.253258 USDT with 6 decimals) are ultimately delivered to 0xb19b7f59c08ea447f82b587c058ecbf5fde9c299.
4.4 Profit calculation and ACT success predicate
The native balance diff for the exploit transaction shows:
- The attacker EOA loses
101095144261776538wei. - WETH9 gains
40000000000000000wei. - The miner’s fee-recipient address gains
1230886000000000wei.
From the receipt, gasUsed = 0x12c826 and effectiveGasPrice = 0xb8e7b741f. Multiplying these yields an exact gas fee of 61095144261776538 wei (0.061095144261776538 ETH). The remaining ETH delta corresponds to the 0.04 ETH value sent in the contract-creation transaction.
The USDT inflow is completely determined by the USDT Transfer logs: the attacker EOA receives exactly 639222253258 USDT units (639,222.253258 USDT). Valuing ETH at approximately 3,000 USDT around the 2022‑02‑04 block timestamp, the gas fee corresponds to about 183.29 USDT. Treating the attacker’s pre‑tx USDT balance as 0 in the reference portfolio, the exploit yields:
value_before≈ 0 USDT,value_after≈ 639,222.253258 USDT,value_delta≈ +639,038.97 USDT net of gas.
This fulfills the ACT profit predicate: the adversary’s portfolio value in the USDT reference asset strictly increases after fees.
4.5 Conditions for exploitation
For this ACT opportunity to exist, the following conditions must hold:
- The deployed TcrToken contract must contain the mis-indexed
burnFromallowance check (_allowances[msg.sender][from]). - A TCR holder such as the TCR/USDT pool must hold a substantial TCR balance and not be blacklisted or otherwise protected from
burnFrom. - An unprivileged EOA must be able to deploy and fund an exploit contract, send a single constructor transaction that self-approves and then calls
burnFromagainst the victim, and route swaps through a DEX router to extract USDT. - Gas costs for the deployment and swaps must be small relative to the USDT value unlocked by destroying the victim’s TCR reserve, ensuring positive net profit.
All of these conditions are satisfied in the observed attack, and they remain reproducible for any adversary that can deploy an equivalent constructor against the same vulnerable TcrToken deployment.
5. Adversary Flow Analysis
5.1 Adversary-related accounts
The adversary-related cluster consists of:
- EOA
0xb19b7f59c08ea447f82b587c058ecbf5fde9c299: sender of the exploit transaction and final recipient of 639,222.253258 USDT. - Exploit contract
0x6653d9bcbc28fc5a2f5fb5650af8f2b2e1695a15: deployed by the EOA; its constructor performs the TcrToken approvals, the abusiveburnFromcall, and the swaps via UniswapV2Router02 that move USDT from the pool to the EOA.
Victim-related contracts are:
- TecraCoin TcrToken at
0xe38b72d6595fd3885d1d2f770aa23e94757f91a1(verified source available). - TCR/USDT liquidity pool at
0x420725a69e79eeffb000f98ccd78a52369b6c5d4(pair contract used as the TCR holder and USDT source).
5.2 Lifecycle stages
-
Initial funding
- Internal transfers deliver ETH to the attacker EOA in the following transactions:
0xfaf32d4a7eb2b17857d8d17b6aaa457cbc68b73ed84c8a4a3b23aa959380a2d5(block 14138961),0x91946c20c99d3d3837244f23f0406f82ca3482ac95ae4e6c017984d1125994c7(block 14139280),0xee1e24d077f96393d1439f6bf20e48a3122ec9c252de69eb69154f7cf4a14f7e(block 14139320).
- These internal transfers, visible in the address-level trace data, accumulate sufficient ETH for the contract deployment and gas.
- Internal transfers deliver ETH to the attacker EOA in the following transactions:
-
Exploit contract deployment
- The attacker sends a single normal transaction with nonce 0 and hash
0x81e9918e248d14d78ff7b697355fd9f456c6d7881486ed14fdfb69db16631154, deploying the exploit contract0x6653d9bcbc28fc5a2f5fb5650af8f2b2e1695a15. - The transaction includes 0.04 ETH value and consumes 0.061095144261776538 ETH in gas, as shown by the receipt and prestate balance diff.
- The attacker sends a single normal transaction with nonce 0 and hash
-
Constructor exploit and payout
- During the constructor execution, the exploit contract:
- Calls TcrToken
approveto set large allowances from the contract to UniswapV2Router02 and to the TCR/USDT pool address. - Invokes the vulnerable
burnFrompath withfrom = 0x420725a69e79eeffb000f98ccd78a52369b6c5d4and an amount of58017069442472TCR units, relying on the mis-indexed_allowances[msg.sender][from]check. - Routes swaps through UniswapV2Router02 that cause USDT to move from the TCR/USDT pool to the exploit contract and then to the attacker EOA.
- Calls TcrToken
- USDT Transfer logs confirm that the attacker EOA receives 639,222.253258 USDT in this single transaction.
- The exploit completes entirely within the constructor; there are no follow-up attacker-crafted transactions required to realize the profit.
- During the constructor execution, the exploit contract:
Because all of these steps are driven by a single public transaction from an unprivileged EOA and rely only on publicly deployed contracts and on-chain state, the strategy is an ACT opportunity.
6. Impact & Losses
On-chain balances and logs quantify the impact as follows:
- The TCR/USDT pool loses
58,017,069,442,472raw TCR units. With 8 decimals, this corresponds to 580,170,694.42472 TCR in economic exposure. - The same pool’s USDT reserve is reduced by
639,222.253258USDT, as shown by TetherToken Transfer logs routing USDT from the pool to the exploit contract and then to the attacker EOA. - The attacker EOA pays exactly 0.061095144261776538 ETH in gas for the exploit transaction, equivalent to about 183.29 USDT when valued at approximately 3,000 USDT/ETH at the block timestamp.
- The attacker’s net profit in the USDT reference asset is approximately +639,038.97 USDT, computed as the USDT inflow minus the gas cost converted into USDT.
The direct victims are liquidity providers in the TCR/USDT pool, whose TCR and USDT positions are depleted. The TcrToken contract itself remains deployed with the same vulnerable logic, so the same pattern can be applied to any other TCR holder that is not otherwise protected.
7. References
-
Seed exploit transaction and trace
Ethereum mainnet tx0x81e9918e248d14d78ff7b697355fd9f456c6d7881486ed14fdfb69db16631154(block 14139082), including RPC metadata, receipt, trace, and prestate balance diff (local artifacts:tx.rpc.json,receipt.rpc.json,trace.cast.log,balance_diff.prestate.json). -
TecraCoin TcrToken contract source
Verified source for TcrToken at0xe38b72d6595fd3885d1d2f770aa23e94757f91a1, including the vulnerableburnFromimplementation (local artifact:Contract.sol). -
Attacker EOA funding history
Address-level txlists for0xb19b7f59c08ea447f82b587c058ecbf5fde9c299, showing internal ETH funding transactions and the single exploit transaction with nonce 0. -
TCR/USDT pool behavior
Prestate ERC20 balance diff and USDT Transfer logs demonstrating the TCR burn and USDT outflow from0x420725a69e79eeffb000f98ccd78a52369b6c5d4to the exploit contract and then to the attacker EOA. -
ACT opportunity characterization
Root cause and ACT opportunity definitions as encoded in the analysis artifacts, tying the mis-indexedburnFromallowance check to an anyone-can-take, single-tx profit strategy.