PenginFinance Token Rug Pull

Reported loss Not disclosed
Rugpull

What happened

PenginToken is a MasterChef-style governance token whose owner can mint without limit and whose transfers are locked until the owner calls unlock(). While isTransferable is false, _beforeTokenTransfer only allows transfers where the sender or the recipient is the owner, so ordinary holders cannot move or sell tokens to a liquidity pair. The same check also covers mints, so before unlock() the owner can mint only to the owner address; the mint function itself has no cap.

De.Fi's REKT database lists PENGIN as an exit scam/rug pull on BNB Smart Chain, citing a BscScan page for the deployer address 0xdCbCc7cC…E0E4c6; the source alone does not show whether the owner minted, kept the lock on, or removed liquidity.

How it happened

  1. The token starts with no supply: constructor() ERC20("PenginFinance Token", "PENGIN") {}. New tokens come only from mint, and the deployer becomes the Ownable owner.
  2. The owner can mint any amount: function mint(address _to, uint256 _amount) public override onlyOwner { _mint(_to, _amount); ... }. No maximum supply is enforced anywhere in the contract. Because _mint calls _beforeTokenTransfer(address(0), account, amount), the lock in step 3 applies to mints too: until unlock() is called, mint can only target the owner address. A code comment says the owner is meant to be the MasterChef (farming) contract, which is a deployment choice the source does not enforce.
  3. Transfers start locked: bool public isTransferable; defaults to false, and _beforeTokenTransfer runs if (isTransferable == false) { require(from == owner() || to == owner(), "locked"); } on every transfer, mint and burn.
  4. While locked, a holder's transfer to a pair or to another holder reverts with "locked" unless the owner is the sender or recipient, and a mint to any other address reverts the same way. Only the owner can end the lock, with function unlock() public override onlyOwner { isTransferable = true; }, and there is no function that re-locks. After unlock(), the owner can mint any amount to any address.
  5. The owner can pass these powers to another address with transferOwnership(address newOwner) or give them up with renounceOwnership(); a read of the contract on 2026-09-30 returns an owner (0x85cd1f59…e04c49) different from the deployer, but the transaction that changed it was not opened.
  6. What the owner actually minted, whether unlock() was called, and whether holders were prevented from selling are not shown by the source; the rug-pull label comes from De.Fi's listing.

Protocol details

Classification Token
Protocol Type Exit Scam/Rugpull
Affected asset / contract PENGIN
Protocol links Website

Build your security review skills

Work through hands-on labs covering real exploit mechanics, review techniques, and defensive patterns.