On Nov. 2, the Axion Network launched its new token, known as AXN. The project touted the asset as a new investment vehicle, claiming that it would be the most profitable blockchain of its kind to date. During the interim leadup to AXN’s airdrop, five separate teams allegedly examined the token’s code; industry darlings such as CertiK and Hacken were among those who conducted the audits.
A few short hours after the protocol’s freeclaim event, however, it became clear that something had gone awry. An unauthorized actor unexpectedly minted 79 billion AXN and unloaded them on the market. The price collapsed in excess of 99%, netting the attackers a cool 1300 ETH — worth an estimated $500,000 at time of publication.
In the hours that followed, the team behind the Axion project encouraged participants to stay away from trading or interacting with the asset, stating via the platform’s official Telegram channel:
“Do not buy AXN right now, do not interact with the dashboard,”
The Axion Network’s Twitter account continued to post updates, including that:
Despite these reassurances, CertiK is stepping forward to offer the community a clearer explanation of what they perceive to have gone wrong, and insights into how similar attacks could be prevented in future. Cointelegraph reached out via email to “Jack Durden,” who was described to us as the CEO of the Axion Network, but received no immediate response. No team members are listed in the project’s white paper or on the website, and the name “Jack Durden” is shared with the unseen narrator from the movie Fight Club.
Note that the remainder of this article is reproduced word-for-word, courtesy of CertiK, as a public service to educate readers on the audit team’s understanding of what happened. Cointelegraph has not audited the code and the views stated hereafter are therefore exclusively those of CertiK.
CertiK staff report on the Axion price crash
On the 2nd of November 2020 at approximately 11:00 AM +UTC a hacker managed to mint around ~80 billion AXN tokens by utilizing the unstake function of the Axion Staking contract.
The hacker proceeded to then dump the tokens on the AXN Uniswap exchange for Ether, repeating this process until the Uniswap exchange was drained and the token price was driven to 0.
We were informed of the incident within a few minutes of the attack occuring and our security analysts began assessing the situation immediately.
We have concluded that the attack was likely planned from the inside, involving an injection of malicious code at the time the code was deployed by altering code from OpenZeppelin dependencies.
The exploited function was not part of the audit we conducted as it was added after joining together Axion’s code with OpenZeppelin’s code via “flattening” and injecting it within OpenZeppelin’s code prior to deployment.
The hacker used anonymous funds procured from tornado.cash the day before the hack occured, hinting at a pre-meditated attack. Presumably to save some funds in case the attack fails, 2.1 Ether were re-circulated in tornado.cash right after the account received the funds.
To finalize the attack setup, the hacker purchased around ~700k HEX2T tokens from the Uniswap exchange. However, these funds were ultimately not part of the attack and served as a smokescreen with regards to how the attack unfolded.
The hacker began their way towards actuating their attack by creating an “empty” stake on the Staking contract of the Axion Network by invoking the stake function with a 0 amount and 1 day stake duration at approximately 09:00 AM +UTC. This created a Session entry for the attacker with a 0 amount and 0 shares value at session ID 6.
Afterwards, the attacker pre-approved an unlimited amount of AXN to the Uniswap exchange in anticipation of their attack succeeding. Consequently, they approved the NativeSwap contract of Axion for the amount of funds they intended to convert to AXN tokens.
They invoked the deposit function of the NativeSwap contract at approximately 10:00 AM +UTC, however the hacker never called the withdraw function of the contract to claim his swapped AXN as evident on the NativeSwap contract’s swapTokenBalanceOf function. Afterwards, they made one more failed deposit function call before executing the attack.
These transactions were merely smokescreens for how the unstake attack was actually carried out. As the transactions that the attacker conducted resulted in no change to the sessionDataOf mapping, we concluded that this was a multi-address attack.
We investigated the source code of the contract’s at the GitHub repository that had been shared with us to identify a flaw that would cause the sessionDataOf mapping to be affected.
We were unable to detect any assignments to it or members of it outside the stake functions which prompted us to question whether the deployment of the contracts was conducted properly.
After analyzing the source code of the deployed Staking contract, we pinpointed a code injection in the AccessControl OpenZeppelin library between L665-L671 of the deployed source code of the Staking contract. The linked checkRole function is not part of the OpenZeppelin v3.0.1 implementation, which was listed as a dependency in the project’s GitHub repository.
Within the checkRole function, the following assembly block exists:
This particular function allows a specific address to conduct an arbitrary write to the contract based on the input variables it supplements via low-level calls. Annotated, the assembly block would look like this:
This function was injected at deployment as it does not exist in the OpenZeppelin AccessControl implementation, meaning that the members of the Axion Network that were involved with deploying the token acted maliciously.
The attack utilized code that was deliberately injected prior to the protocol’s deployment. This incident bears no relation to the audits conducted by CertiK and the party responsible for the attack was a person that seemed to be involved with the deployment of the Axion Network contracts.
As an additional degree of security, audit reports should standardise to include deployed smart contract addresses whose source code has been verified to be the same as the one that was audited.
The Security Oracle serves as an on-chain relayer of security intelligence, conducting security checks which include the verification of deployed smart contracts to match the audited versions.