RWT attack on BNB Smart Chain led to about $118,000 in losses
Blockchain security firm ZeroShadow said it detected an exploit targeting the RWT project on BNB Smart Chain on July 19, 2026. The incident caused losses of about $118,000.

The attack transaction was:
https://bscscan.com/tx/0x22300140e7c44899c2602382a6e7a4a34a70f47f9736721744bc6434c07171dc
The attacker address was:
https://bscscan.com/address/0x84dd3a5d4de44c8ad0ce032beab8bc3f01d1dcf7
The attack contract address was:
https://bscscan.com/address/0x7ed953ff42509568f620aa340a33a9373447f4ce
The affected RWT/USDT pair address was:
https://bscscan.com/address/0xc1c2ef25372f12ce18d35044446064b720c4aa27
How the attack started
ZeroShadow said the attacker first took out a flash loan of 1,000,000 USDT from Lista DAO: Moolah.
The attacker then called the buy function on the RWT trading contract at 0x8812bB5fB89D69D35Ac84D2C37B55769395b9f90 and spent 93,612.061013797236332471 USDT to buy RWT.
Of that amount, 14,041.809152069585449870 USDT was transferred out as a fee. The amount that actually entered the RWT/USDT pair was 79,570.251861727650882601 USDT, calculated as 93,612.061013797236332471 minus 14,041.809152069585449870.
The attacker received 36,718,733.010848105074881558 RWT.
Next, the attacker transferred 238,910.179775312595883090 USDT into the RWT/USDT pair and withdrew about 36,718,733 RWT from the pair. ZeroShadow said this increased the pair’s USDT balance while reducing its RWT balance, which pushed up RWT’s price on PancakeSwap V2.
The critical step came after the sell
After lifting the price, the attacker sold 35,984,358.350631142973383908 RWT through the project’s trading contract sell function and received 235,902.720974496353639994 USDT from the pair.

Under normal conditions, ZeroShadow wrote, trading fees and AMM slippage would make it difficult to profit directly from a buy-and-sell sequence like this.
But the transaction logs showed something else. After the attacker sold RWT, the RWT contract burned an additional 71,968,716.701262285946767816 RWT from the RWT/USDT pair.
ZeroShadow compared the two amounts:
- RWT sold by the attacker: 35,984,358.350631142973383908
- RWT burned from the pair: 71,968,716.701262285946767816
- Relationship: 35,984,358.350631142973383908 × 2 = 71,968,716.701262285946767816
That meant the trading contract executed an extra burn from the PancakeSwap pair after each sell, with the burn amount equal to twice the amount sold.
Why the attacker could trigger the burn
ZeroShadow pointed to the RWT token contract’s burn function:
function burn(address _From, uint256 _amount) external onlyOwner { _burn(_From, _amount);}
This function allowed an authorized address to specify any _From address and burn RWT from that address. In the report’s words, an authorized address could directly execute:
RWT.burn(pancakeSwapPair, amount);
That would burn RWT held by the PancakeSwap pair itself.
The report also cited the onlyOwner check in the RWT contract:
mapping(address => bool) internal role;modifier onlyOwner() { require( hasRole(_msgSender()), "Ownable: caller is not the owner" ); _;}
ZeroShadow said this onlyOwner modifier did not restrict calls to the owner() address alone. Instead, it checked whether role[msg.sender] == true. Any address assigned role = true by the project could call high-privilege functions such as burn, mint, and setRole.
According to the report, the project granted that privilege to the trading contract at 0x8812bB5fB89D69D35Ac84D2C37B55769395b9f90, while the contract’s buy and sell functions remained callable by ordinary users. The attacker therefore did not need direct access to the RWT owner role. By calling the public sell function, the attacker could indirectly cause the privileged trading contract to burn RWT from the pair.
ZeroShadow summarized the call path like this:
attacker → public sell function → privileged RWT trading contract → RWT.burn(pair, amount)

Reconstructed contract logic
ZeroShadow said the trading contract at 0x8812...9f90 did not publish complete source code. Based on runtime bytecode, function selectors, transaction logs, and event parameters, the firm reconstructed the core logic approximately as follows:
function sell(uint256 amount, uint256 minOut) external { // collect and sell user RWT _sellRWT(amount, minOut); // burn RWT from the PancakeSwap pair uint256 burnAmount = amount * 2; RWT.burn(pancakePair, burnAmount); // write updated balances into reserves IPancakePair(pancakePair).sync();}
Once the trading contract burned RWT from the pair, the pair’s actual RWT balance fell, while its USDT balance did not drop in the same proportion. The contract then called sync(), and the PancakeSwap V2 pair wrote current balances back into reserves:
reserveRWT = RWT.balanceOf(pair);reserveUSDT = USDT.balanceOf(pair);
The report simplified the pool pricing relationship as:
RWT Price = USDT Reserve / RWT Reserve
So if the RWT reserve is sharply reduced while the USDT reserve stays largely unchanged, the pool price of RWT rises quickly.
- RWT reserve down
- USDT reserve largely unchanged
- RWT price up
ZeroShadow said the attacker repeated this process several times. After each sell, the contract burned about twice the sold amount from the pair and then called sync() to update reserves. As the pair’s RWT reserves kept shrinking, the token’s price kept rising, allowing the attacker to withdraw more USDT by selling smaller amounts of RWT later in the sequence.
The report outlined the flow as:
buy RWT with USDT → sell part of the RWT → trading contract burns RWT from the pair → call sync() to update reserves → RWT price rises → sell RWT again for USDT
Project revoked the contract role about six minutes later
ZeroShadow said that about six minutes after the exploit, the RWT project sent two setRole transactions to change the trading contract’s permission at 0x8812...9f90 to false.
The related transactions were:
https://bscscan.com/tx/0xa7220206910794024452293b80cbbb77389f847c12c53b81528e628b4c3d9d73
https://bscscan.com/tx/0x18f2b31770c152242d85cfbe711f28d5ae985a0f4950a17a7e9558712a9d082d

Both transactions used the same parameter:
setRole( 0x8812bb5fb89d69d35ac84d2c37b55769395b9f90, false);
ZeroShadow said this supported its conclusion that the burn authority used in the exploit came from the RWT project’s trading contract, not from the attacker directly obtaining the RWT owner privilege.
Final outcome and code-level issues
At the end of the attack, the attacker repaid the 1,000,000 USDT flash loan to Moolah and transferred the remaining 118,069.281571404198479027 USDT to the attacker address. ZeroShadow estimated the final profit at about $118,000.
The report identified two contract-level security issues.
First, the RWT burn function could burn tokens from any address, and it did not restrict _From from being the PancakeSwap pair. That meant an authorized contract could directly alter the pair’s RWT balance.
Second, the project granted that authority to a public trading contract, and that contract calculated the amount to burn from the pair during the sell flow based on user input. That let the attacker control:
- how much RWT to sell
- how much RWT would be burned from the pair
- the pair’s updated RWT reserve
- the pool price of RWT
ZeroShadow stressed that this was not simply a case of a burn function lacking access control. In its view, the project gave high-privilege arbitrary-burn capability to a public business contract, and that contract allowed outside users to destroy assets in an AMM pair through controllable parameters and then manipulate reserves with sync().
Recommendations from ZeroShadow
ZeroShadow concluded that the exploit was rooted in RWT’s design of a trading mechanism that could directly burn RWT from a PancakeSwap pair, combined with assigning burn permissions to a public trading contract.
The attacker used a flash loan for 1,000,000 USDT, bought a large amount of RWT, changed the reserve ratio in the RWT/USDT pair, and then called the trading contract’s sell function. After each sale, the contract burned roughly twice the sold amount from the pair and called sync(), which kept pushing the pool price higher. By repeating the process, the attacker gradually reduced the pair’s RWT reserves and extracted USDT from the pool. After repaying the flash loan, the attacker ended with about $118,000 in profit.
The firm said projects should not allow any contract to execute burn or forced transfer operations against an AMM pair address. Token burns should apply only to tokens actually held by the protocol itself and should not directly modify assets held at an LP address.
It also recommended separating powers such as mint, burn, blacklist management, trading switches, and role management, so that a single external business contract does not hold multiple administrator privileges at once.
When designing token burn logic, automatic liquidity additions, automatic buybacks, and price calculation logic, the report said teams should closely review the combined risks of operations such as burn(pair), transferFrom(pair), skim(), and sync(). Before deployment, contracts should go through cross-audits by multiple audit teams and be tested against flash-loan and economic-model attacks in a mainnet fork environment.
Disclaimer: The market carries risk, and investors should act with caution. This article does not constitute investment advice. Users should consider whether any opinions, views, or conclusions in the article fit their own circumstances. Any investment decisions made on that basis are the user’s own responsibility.

