People often ask me "How did you learn how to hack?" The answer: by reading. This page is a collection of the blog posts and other articles that I have accumulated over the years of my journey. Enjoy!
stakeLP(): Allows a user to stake BUSD-sDAO LP tokens directly in the contract.getReward(): Collect sDAO tokens from the staked LP tokens.withdrawTeam(): Transfers all LP tokens to a preset TEAM address.tranferFrom(): Added functionality for calculating the total staking reward of the tokens accumulated when sDAO tokens are transfered from the BUSD-sDAO token contract.transferFrom() math for the tokens is incorrect. When executing the code for staking, the functionality only checks to see if the address we're trying to transfer to is the BUSD-sDAO LP token. If it is, then 7% of that is added directly to the totalStakeReward. totalStakeReward is used directly in the rewards per token calculation AND is directly accessible to any user. Within the transfer() function, only msg.sender must be the owner, indicating this is a flaw in the contract.withdrawTeam() can be called externally by anybody to send funds to the TEAM address, which is owned by the SportsDAO. By pairing this functionality of transferring with the direct control over some of the fields for rewards, we come across a vulnerability! LPInstance can be removed by the second issue mentioned above. Since this is the denominator of the math, controlling this is a HUGE deal.
newPerTokenReward = (totalStakeReward - lastTotalStakeReward) * 1e18
/ LPInstance.balanceOf(address(this));
LPInstance be extremely small; this can be done first by removing all of the funds via the withdrawTeam() then adding in a tiny amount via the bug in transferFrom(). Once the denominator is tiny, the math for the rewards is completely busted. The amount of rewards per token will be extremely high, since it believes it has very little of the token!