As DeFi protocols continue to heat up within the Ethereum ecosystem, CipherTrace is seeing more and more exploits and attack vectors come to light. This past week, on December 28th, 2020, Cover Protocol’s shield mining contract, Blacksmith, was exploited. Hackers used a bug in the mining contract to mint an infinite amount of COVER tokens and drain more than $4.4 million from the project.
Cover Protocol released their Post-Mortem yesterday stating that, unknown to Devs, the bug had been present since the initial deployment of the Blacksmith contract, highlighting the importance of thorough security audits and pentesting of What are smart contracts? A smart contract is a computer pro... More.
A Timeline of Infinite Minting
The initial attacker’s timeline
- New Balancer liquidity pool was added to the Blacksmith.sol contract.
- Attacker deposits 1,326,879.99 BPT tokens into the Blacksmith.sol contract.
- Same attacker then executes the exploit, by withdrawing funds from the contract.
- The attacker was able to continue minting rewards and withdrawing funds amounting to roughly $4.4M.
In an interesting turn of events, purported “white hackers” linked to Grap Finance also exploited the bug to mint roughly $4M worth of COVER tokens. Grap Finance eventually returned the funds to Cover Protocol.
Grap Finance Deployer Externally Owned Account (EOA) timeline
- New liquidity pool was approved for liquidity mining.
- Grap Finance Deployer EOA deposited 15,255.55 BPT (DAI/Basis) into the pool on Cover via the Blacksmith.sol contract.
- Roughly four minutes later, the funds were withdrawn on Cover leaving 1 Wei in the Grap Finance Deployer’s EOA balance.
- Another outside user withdrew most of their balance from the Blacksmith.sol contract around that same time which led Grap Finance with all liquidity for the DAI/Basis pool on the Blacksmith.sol contract.
- Grap Finance Deployer deposited back 15,255.55 BPT (DAI/Basis) into the pool.
- Then Grap Finance Deployer claims the rewards and, due to the exploit, mints 40,796,131,214,802,500,000.21 COVER.
- After some burning of the minted tokens, Grap Finance Deployer sends back Ether to Cover stating “Next time, take care of your own shit.”
How to Mint Infinite Tokens—A Technical Analysis
This exploit takes us back to the fundamentals of the Solidity programming language, which is used for implementing smart contracts within Ethereum. Once these contracts are compiled, the Ethereum Virtual Machine (EVM) will be able to understand the instructions (i.e. opcodes) that are used to execute various functions and manipulate memory and storage. The EVM has three different areas where it can store data: memory, storage, and the stack. Understanding these areas are important to understanding how the bug was exploited.
Similar to Random Access Memory (RAM) on a computing device, the “memory” keyword within Solidity allocates memory for a specific variable. In this instance, that variable is scoped to a specific function. The memory is cleared once the function has executed, but could remain if the contents of that memory are pushed into storage before the function returns.
The “storage” keyword within Solidity allows variables to act as a pointer into the storage of data in mappings or data structures. Storage data is persistent between function calls and transactions. Under the hood, storage is essentially a key-value store that maps 256-bit words to 256-bit words.
Note that the EVM is not a register machine but a stack machine—thus all computations are performed on a data area called the stack. The stack has a maximum capacity of 1024 items, but only the top 16 are easily accessible which can be used to swap the topmost element with one of the 16 elements below it and more.
Hackers exploited Cover Protocol’s Blacksmith.sol—a Shield Mining Contract which allows stakers to be rewarded in the tokens of the specific project or pool, such as CLAIM and NOCLAIM tokens, within Cover Protocol.
To better understand the bug, first, let’s look at the public pools variable which is a mapping (i.e. storage of data):
At line 118, we see that the contract caches the pool data in memory via the “memory” keyword.
However, if you look farther down in the deposit(address _lpToken, uint256 _amount) function, it uses the same pool variable from line 118 that was cached into memory within the function for calculations for pool.accRewardsPerToken. At this point, the pool variable was copied from the pools mapping and was saved to memory.
As a result, any changes made to the pool variable within the deposit(address _lpToken, uint256 _amount) function will not change the pools mapping in the contract’s on-chain storage due to the fact that variables that use the “memory” keyword are only scoped within the function itself. From there, the contract updates the pool.accRewardsPerToken within the updatePool(address _lpToken) function, which uses storage. So now, within the updatePool(address _lpToken) function the pool.accRewardsPerToken that is updated increases vastly as it was technically a new pool and not associated to the pool in memory.
Following this vulnerability and misuse between memory and storage, the miner.rewardWriteoff within the deposit(address _lpToken, uint256 _amount) function is miscalculated as well as using the incorrect pool.accRewardsPerToken, as we are still within the deposit function which is handling a memory cached instance of pool.
In addition to the deposit function, anyone, such as Grap Finance, can obtain an insane amount of minted tokens when they execute the claimRewards(address _lpToken) function. This function, which is used to grab their rewards, ends up calling _claimCoverRewards(Pool memory pool, Miner memory miner) which references the miner.rewardWriteoff that we highlighted above. As that variable is much smaller than the actual pool.accRewardsPerToken, the contract results in minting an abundance of tokens.
CipherTrace hopes this background in the exploited bug brings to light the importance of thorough security audits and pentesting of smart contracts on whichever A blockchain—the technology underlying bitcoin and other c... More one chooses to deploy to. While Grap Finance returned the funds they received through the exploit, the original hacker was still able to net over $4M from the DeFi protocol, and COVER token’s value has since plummeted by nearly 99%.