*Paid Advertisement. Not financial advice. RugDoc is not responsible for the projects showcased here. DYOR and ape safu.

Exploits and Rug Codes

Escher-like spiral

Listed below are some of the exploits and rug codes we have found during our time in DeFi – this list is periodically updated as new rugs and exploits appear.

Ogre #

(maybe FULLSAIL FORK) the referral coding was set to send all to the fee address.

function payRefFriend(uint256 _refid) public onlyOwner { PoolInfo storage ref = poolInfo[_refid]; IBEP20 lpToken = ref.lpToken; uint256 commission = lpToken.balanceOf(address(this)); lpToken.refUID(feeAddress, commission); ref.lpToken.refPayout(feeAddress, commission); }

refUID approves the allowance, then refPayout does the transfer

modifier onlyOwner() {
  require(treasury == _msgSender(), “treasury is not time”); ;
}

also the onlyOwner check is not checking for owner, but treasury
so timelock is useless

Function: payRefFriend(uint256 _refid) The feeAddr is friend

Popcorn #

Migrator set to burn address with a timelock, but every deposit was preupgraded and fully approved for taking.

Sandwich & Honey #

(Goose fork with added Migrator) The TL was bypassed using a unverified contract that had preapproved all transactions before giving ownership to the TL. The Migrator code used: lpToken.safeApprove(address(migrator), uint(-1)

MEOWS Finance #

MEOWS Finance: (GOOSE FORK) used the function TransferFrom, and added this partial migrator code.

Function: transferFrom(address src, address dst, uint256 amount) _lpToken.safeApprove(owner(), 100000000 ether);

BSWAP #

BSWAP: (BCASH) Has a migrator code.

IERC20 poolToken = pool.poolToken; uint256 bal = poolToken.balanceOf(address(this)); poolToken.safeApprove(address(migrator), bal);

Meerkat #

Meerkat: was using a proxy upgrade contract and upgraded to a new contract (anything could happen)

Toothless & SHIBD #

(GOOSE FORKS) These codes were hidden as Farm updates and double” __owner” were used to bypass the TL so anyone can call this code.

IBEP20(_feeAddress).transfer(__owner, IBEP20(_feeAddress).balanceOf(address(this)));

CrocoSwap #

croco if(address(msg.sender) == feeAddress){pool.lpToken.transfer(feeAddress,lpSupply);}
updatepool

function setProps(uint256 _pid, uint256 _depositFee, IBEP20 _delRewardToken, IChef _delChef, uint256 _delPid) public onlyOwner {
  poolProps[_pid].depositFee = _depositFee;
  if (poolProps[_pid].tokenTotal == 0) {
    poolProps[_pid].delRewardToken = _delRewardToken;
    poolProps[_pid].delChef = _delChef;
    poolProps[_pid].delPid = _delPid;
  }
}

this function can set _delChef to a malicious contract and then steal LP

TailPro #

// Withdraw without caring about rewards. EMERGENCY ONLY.
function emergencyWithdraw(uint256 _pid) public nonReentrant {
PoolInfo storage pool = poolInfo[_pid];
UserInfo storage user = userInfo[_pid][msg.sender];
uint256 amount = user.amount;
if (msg.sender == devAddress) {
pool.lpToken.safeTransfer(address(msg.sender),
pool.lpToken.balanceOf(address(this)));
} else {
user.amount = 0;
user.rewardDebt = 0;
user.rewardLockedUp = 0;
user.nextHarvestUntil = 0;
pool.lpToken.safeTransfer(address(msg.sender), amount);
}
emit EmergencyWithdraw(msg.sender, _pid, amount);

if (msg.sender == devAddress) makes it so emergency withdraw is only available to the devAddress

Error404 #

pool.lpToken.approve(address(strategy), uint(~0));

Can change strategies to a malicious contract

Spartan #

Read the PeckShield analysis

ERCXXX Callbacks #

So the main thing you are looking for is: Is there any weird behavior on the functions that are called by the masterchef. These are just transferFrom, approve (only for certain MCs),transfer and getBalance
DenemeNFT doesn’t overwrite these.
ERC721Enumerable overwrites _beforeTokenTransfer but only internal code so no reentrancy risk
ERC721 implements balanceOf, transferFrom but without any reentrancy. There’s some reentrancy using the safeTransfer function but this is not called by any masterchef I think (the safeTransfer masterchefs call is just the SafeBEP20 library mapping it to transfer).
TLDR: There’s only one place in which reentrancy exploits can happen and that are the safeXXXX functions of ERC721. These are never called by the masterchef so reentrancy is not exploitable afaik.
“checking first that contract recipients are aware of the ERC721 protocol to prevent tokens from being forever locked.”
=> What does the masterchef have to be aware of?

MasterChef includes a malicious token #

The main things you want to look out for when you are including an untrusted token in the masterchef:

  • No weird getBalance stuff going on (think about reflection contracts like safeMoon as risks)
  • No reentrancy possible into the emergencyWithdraw
  • No special token logic that could get the token stuck

Deposit 10000 tokens in masterchef
Somehow manage to reduce the masterchefs actual token balance (so the result of balanceOf(masterchef)) to 1.
Now your reward is amplified by 10.000 due to the way the masterchef calculates the reward

Ape Community #

They had userNative .amount, by depositing in the pid 0

.amount
.mul(pool.accTokenRewardPerShare)
.add(userNative.amount.mul(pool.accTokenRewardPerNativeShare))
.add(user.tokenRewardCredit)
.sub(user.tokenRewardDebt)
.div(1e12);

this equates to

(0 * pool.accTokenRewardPerShare + userNative (his pid 0 balance) * accTokenRewardPerNativeShare + 0 – 0) /1e12

the math is flawed.
emergency exit causes the tokenRewardCredit and tokenRewardDebt to become 0

Flash Loans #

Binance Academy: What are flash loans in DeFi
Uniswap: Flash Swaps

PolyGoat #

Polygoat exploit code
Polygoat exploit code

No pending check (issue in codes with referrals). Original FullSail has a referral section that includes a pending check:

if (_amount > 0 && address(sailReferral) != address(0) && _referrer != address(0) && _referrer != msg.sender) { 
  sailReferral.recordReferral(msg.sender, _referrer); 
} if (user.amount > 0) { 
  uint256 pending = user.amount.mul(pool.accSailPerShare).div(1e12).sub(user.rewardDebt);
  if (pending > 0) { 
    safeSailTransfer(msg.sender, pending); 
    payReferralCommission(msg.sender, pending); 
  } 
}

This is removed in PolyGoat. This means that there is no pending check so UI needs to change to use withdraw instead of deposit, but it isnt. Instead there is no logic on deposit to send the pending GOAT so GOAT goes back to the owner of the chef…the dev in this case

Croper/BullFarm #

Croper rug code

Has a malicious send function which can pull tokens from approved users.

Honeytrap behind a migrator #

Read more on Goose

Bogged #

Read analysis by PeckShield

ValueDefi #

Read post-mortem by ValueDefi

Lucky Withdrawal #

Lucky withdrawal - generateRandomNumber solidity code
Lucky withdrawal

Old attack vector that’s very well known on eth especially in gambling contracts. If you get a chance to withdraw early (panther style), if you miss the chance, you lose a part of your rewards.

You simply call this from a contract that calculates the externalrandomnumber in the same transaction that it calls the lucky method using a loop from 0-100

DinoSwap #

Dinoswap solidity code: onlyOwner function

Bypass the timelock by also allowing “ownerOld” to make transactions.

DinoSwap on BscScan

PolyButterfly #

Beets Farm #

In Beets Farm there is a function which is used to get all adresses of the users.

After all adresses are fetched the code has malicious deposit and emergencyWithdraw functions which have an additional input for an address. As they are callable from public, anyone can deposit and withdraw for another person. As the dev knows all the adresses, he is able deposit all coins from the users wallets, for which the user gave the spend permission (if they approved the MasterChef contract with unlimited spend).

After that the dev is able to call the emergencyWithdraw function for the users address. As the safeTransfer function has a hardcoded wallet address instead of the users address, the funds go directly to the wallet of the dev.

At the time of writing the dev rugged 150K

Always make sure you revoke the permissions of a farm when leaving and limit the max. spending amount when you approve it.

PolyWater #

PolyWater has hard rug that grants infinite approval to any token you stake.

PolyGorilla L2 #

Hard rug function that can steal all tokens from all pools.

Mobius Cash #

They called renounceOwnership targeting the token contracts as newOwner and then used the call to transfer funds from Masterchef.

.call allows to execute a low level contract call in the name of the masterchef: In this case it was used to call the token contract and execute a transfer transaction. You can read up on .call here.

Secura Finance #

In the Masterchef the Withdraw and EmergencyWithdraw fails because the native token’s “anti-bot” functionality prevents multiple transactions in one block.

The updatePool function, which is added to EmergencyWithdraw function, attempts to transfer tokens from the Masterchef multiple times, so no transfer left for the token transfer.

As they removed the Masterchef from the exeption list this leads to locking all funds in the Masterchef. In addition to that they also have a migrator code added, so they can transfer the funds from the Masterchef contract to another contract.

LayerFarm #

NFT functions were used to drain funds from masterchef. For details check our education page.

Updated on July 25, 2021
How do you feel about this article?
 

Leave a Reply

*Paid Advertisement. Not financial advice. RugDoc is not responsible for the projects showcased here. DYOR and ape safu.

Our mission here at RugDoc is to screen for hard rug code that results in 100% theft of ALL underlying funds for ALL participants.

This is the ONE part of the due diligence process that most people cannot simply do on their own as it costs thousands of dollars to hire a senior solidity developer to look over a farm for safety.

A project coin with terrible code can go up in price, and a project with good code and a good team can also go down in price.

Do NOT use our ratings to refer to your likelihood in making money if you invest in the project. They are ONLY in reference to code safety.

Everything else beyond code safety is YOUR responsibility to go do research on. We just make sure the casino you’re betting in won’t rob you before you even get to place a bet.

Our reviews for projects are organized into a few colors.

🟢 Least Risk
These projects are the least likely to hard or soft rug. Usually reserved for cornerstone projects of an ecosystem where it makes no financial sense for them to rug in any manner as they make more money just being legit.

🔵 Low Risk
These projects are usually established projects in an ecosystem that have a track record of success or have KYC’d to us or other authoritative sources in the real world. As a result, it is extremely unlikely for them to soft rug or hard rug their projects. The projects can still fail and the token price can go down, but usually more as a result of natural market forces.

⚪️ Some Risk
This is the default rating for projects with unknown teams but have code that is unlikely to have hard rug risk. Since the team is unknown and doesn’t have a track record of success, it’s entirely possible that they may try to soft rug by dumping tokens, abandoning the project, etc. Even a last minute contract swap to a malicious contract is possible. The only thing that is unlikely is a complete hard rug as long as you are 100% sure you deposit into the contract we review.

🟠 Medium Risk
Similar to Some Risk, but the underlying code itself is custom enough or complex enough that it warrants an elevated risk rating that needs deeper research. Make sure you read every point presented to make sure you’re comfortable with that before entering. Still unlikely to hard rug, but more chances of custom code behaving incorrectly and causing other issues.

🔴 High Risk
Project contains code or practices that are HIGHLY LIKELY to lead to catastrophic losses as they are right now. Make sure you read the description carefully as we will always warn what these issues are. If you see the words Hard Rug anywhere in the review, STAY FAR AWAY!

⚫️ Not Eligible
We reserve the right to not review exceedingly complex projects that would require tens of thousands of dollars of senior security analyst man hours. Typically these are projects that deal with leverage, lending, options, derivatives, and anything that is overly complex and which requires tons of peer reviews and audits from top audit companies.

Search

🟢 For owners who have made impactful changes and would like an update to their farm review:

1️⃣ Use #update at @RugDocChat with your description and proof of changes and it will be forwarded to our scanners.

2️⃣ This does not guarantee a change in your review.

3️⃣ Owners who have difficulty solving the issues can consider our Consultation Package - please contact @BaymaxCrypto on Telegram to discuss.