Original.finance Rug Pull
What happened
Original.finance is a BNB Smart Chain farm whose MasterChef pays out PhotonToken (Photon) and tracks a referral tree. De.Fi's REKT database lists it as an Exit Scam/Rugpull dated 2021-08-26. The code has two separate freeze switches, each guarded by its own moderator variable: MasterChef.moderator controls updatePaused, which makes every deposit, withdraw and emergencyWithdraw revert, and PhotonToken.moderator controls statusTransfer, which makes every Photon _transfer revert.
The two variables are set by separate constructors, and the source does not show whether one address holds both roles. The MasterChef owner can also set a pool deposit fee up to 100%. The source shows what these keys allow; no transaction showing any of them being used was opened.
How it happened
What the code allows (no transaction showing these calls was opened):
MasterChefstarts locked:bool public paused = true;anddeposit,withdrawandemergencyWithdraweach start withrequire(paused == false, "!paused");. Only theMasterChefmoderator(the address passed as_moderatorto theMasterChefconstructor) can change it:updatePausedrunsrequire(moderator == msg.sender);and thenpaused = _value;.- Once users have staked LP tokens, the
MasterChefmoderatorcan callupdatePaused(true)again. EverywithdrawandemergencyWithdrawthen reverts, so the LP tokens recorded inuser.amountcannot be pulled out through this contract until thatmoderatorunpauses. - Separately,
PhotonTokenhas its ownaddress public moderator;, set from the_modargument of thePhotonTokenconstructor. It overrides_transferwithrequire(!_pausedTokens, "!paused");, andstatusTransfer(bool _value)sets_pausedTokensafterrequire(moderator == msg.sender);. While_pausedTokensis true, everytransferandtransferFromof Photon reverts, including transfers to or from an exchange pair, so held Photon can be neither moved nor sold. Minting is unaffected becausemintcalls the internal_mint, which does not call_transfer. - Each
moderatorcan hand its role to another address with its ownchangeModfunction, and the source does not show which addresses hold the two roles or whether they are the same. - The deposit fee is a further lever:
setandaddaccept_depositFeeBP <= 10000, so an owner (orsetupaddress) can set 100%.depositthen sendsdepositFeetofeeAddressand creditsuser.amount = user.amount.add(_amount).sub(depositFee), which is zero for a 100% fee. addSetuphas no access check beyondrequire(setup == address(0)), so while nosetupaddress is recorded any caller can set it, andonlyOwnerAndSetupthen lets that address calladd,setandupdateEmissionRate.
on 2021-08-26 is not established by the source; De.Fi's REKT database lists the project as an Exit Scam/Rugpull.
Protocol details
Build your security review skills
Work through hands-on labs covering real exploit mechanics, review techniques, and defensive patterns.