This sentence uses \` and \` delimiters to show math inline:
On April 12 2025, an unverified contract, 0x623c, was exploited, leading to the loss of approximately $28,000 due to a lack of access control. The exploit was the fourth incident linked to this same attacker, who had already conducted exploits on Gemcy, OPC, and AIRWA, gaining around $181,000. On April 23, the attacker conducted a fifth attack on ACB.
Here, we break down how the Sola Token was exploited from the event flow, then decompile the unverified contract in order to confirm the root cause of the incident.
Exploit Transaction:
https://bscscan.com/tx/0x9371eb4b0da7dedc95568d508a7fc97298a27bb44947c82dc4542fe3a4e5e3c9
Addresses
Attack wallet: 0x70f0406e0A50C53304194B2668Ec853D664a3D9C
Attack contract: 0xD306C1f4506C89929820a10163206E337658E2b4
Victim contract: 0x623c1c6693e1425a7E691a0FF5C256Cb276522CA
Step by Step Event Flow
If we take a closer look at the data field, we can see that there were three bits of information passed:
Once the USDT was transferred, the withdrawToken() function was called in order to transfer the owed SOLA tokens from the victim contract.
Analyzing unverified contracts
The event flow indicates that, for an unconfirmed reason, the attacker was allowed to transfer tokens from SOLA contract 0x623c1c6693e1425a7E691a0FF5C256Cb276522CA when conducting a swap. This could either be that they have permission via a privileged wallet address or it’s a publicly accessible function with no permission checks. In order to confirm, we need to decompile the contract and look at the withdrawToken() function.
The decompiled code can look quite unreadable until it is converted into its original format. Typically, this would involve recognition of common lines of code and replacing known variables. For example, in this code, v0 is true or false and v1 is token balance. We can use AI to speed up this process:
Now, the code is more readable. We can confirm that the withdrawToken() function has no modifiers, such as onlyOwner, nor does it have any 'require' statement which limits who can access this public function.
The attacker’s address 0x70f0406e0A50C53304194B2668Ec853D664a3D9C was funded on March 29 by address 0x326f75EA9C85337f88087155bf6220Fa8DE81324 with both addresses having already been used in a number of other exploits before this incident.
In total, the attacker has sent 498 BNB to Tornado Cash from across the five incidents listed.
Since the beginning of 2025, incidents related to code issues remain one of the most common attack vectors. The number of incidents due to code vulnerabilities has remained fairly consistent in the last four years, though losses have decreased year on year.
So far in 2025, we have recorded 93 incidents linked to code vulnerabilities for a total loss of around $52.5 million. This makes it the second most common cause of losses by number of incidents, just behind phishing.
To keep up to date on the latest incident alerts and statistics, follow @certikalert on X or read our latest analysis on certik.com.