top of page

HIGH - ANKR/Stader - Reward distribution is vulnerable to MEV leading to theft of reward 🚩

ANKR and Stader for BNB are both liquid staking solutions for BSC. They are both vulnerable to the expoit detailed below. They have decided to live with the risk of this attack, which in my opinion is irresponsible for their users which may be affected, while the project itself is not at risk.


Target


Bug Description: Distribution of rewards is done via updateRatio() function with new rewards. It re-calculated the pool value / shares ratio, which is used in conversion from bonds to shares. Attacker may perform sandwich attack (see reference for explanation) by crafting the following transactions:

USER: stake() - send X BNB into the contract, receive (X-relayFee) aBNBb ================================================= Operator: updateRatio(rewards) - increase ratio with rewards ================================================= USER: unstake() - burn aBNBb balance, receive X + REWARD% * ( X / X+POOL ) - relayFee


The receiving of profits does not happen immediately, only after distributeRewards() takes place, several days later. However, users can also realize their profits from increased aBNBb balance instantly via DeFi markets. There is no question that the daily yield is stolen from other pool members.

The root cause is that rewards are distributed collectively but users can partake and take rewards immediately, although their funds were not yet used in staking and as such do not deserve the sent rewards.

Impact Up to full amount of protocol rewards can be taken from pool members, depending on attacker's budget (which affects his share of the total pool). Difficulty to Exploit: Medium

Weakness: MEV

Recommendation Store amount of last reward distribution For each user, store timestamp of last deposit / receive of token. In unstake(), if user did not wait longer than some variable time from deposit / receive to withdraw, he does not receive last reward. This will protect from both MEV methods explained above, exiting with withdraw / exiting with DeFi swap.


Proof of Concept

Assume pool contains 1000 BNB of value, with 800 aBNBc / shares minted (1 share = 1.25 BNB) Attacker sees updateRewards() transaction in mempool:

call deposit - send 1000 BNB, mint 1000 aBNBb (800 shares)

updateRatio(+10BNB) executed - pool now has 2000 BNB + 10BNB new rewards = 2010 BNB -> ratio is 2010 / 1600 = 1.25625 -> attacker aBNBb is 1005

call withdraw - return 1005 aBNBb. attacker must wait for distributeRewards() to be called to receive his profits.


End state: attacker receives 50% of the rewards distributed by matching the total pool value. Attacker can also exit his position with profit immediately using DeFi markets.

Recent Posts

See All

Comments


bottom of page