Daughter Doge Revenge Token Rug Pull

Reported loss Not disclosed
Rugpull

What happened

DDR is a BEP20 token whose verified source gives the owner a function that sets any holder's allowance, with no consent from that holder. De.Fi's REKT database lists it as an exit scam / rug pull, describing "hard rug code that can steal staked tokens at any time". The code lets the owner approve itself to spend any address's balance (including a contract that holds staked DDR) and then pull it out with transferFrom, burn any balance, and a minter role can mint without a cap.

No transaction, loss amount or attacker address is established by the sources opened for this record.

How it happened

  1. The contract DDR extends BEP20 and adds an owner-only overload of approve with three parameters: function approve(address owner, address spender, uint256 amount) public onlyOwner { _approve(owner, spender, amount); }. Unlike the standard approve(spender, amount), which sets an allowance from _msgSender(), this one lets the owner write _allowances[owner][spender] for any owner address it names.
  2. With an allowance written over a holder's address (or over a contract that holds staked DDR, which is the case De.Fi's listing describes), the owner as spender can call the standard transferFrom(sender, recipient, amount). That function runs _transfer(sender, recipient, amount) and then reduces _allowances[sender][_msgSender()] by amount, so the holder's balance is debited with no action from the holder.
  3. The transfer tax does not stop this. In DDR._transfer, a recipient other than FEE_ADDRESS with a non-zero transferTaxRate (default 500, i.e. 5%, capped at MAXIMUM_TRANSFER_TAX_RATE 1000) gets amount - taxAmount, and taxAmount goes to FEE_ADDRESS; the full amount leaves the holder either way.
  4. Two further owner-or-minter powers sit beside this: function burn(address _from, uint256 _amount) public onlyOwner { _burn(_from, _amount); } destroys any address's tokens, and function mint(address _to, uint256 _amount) public onlyMinter { _mint(_to, _amount); } has no supply cap. MinterRole's constructor calls _addMinter(msg.sender), so the deployer holds the minter role.
  5. What the code allows is separate from what happened. The code contains renounceOwnership() and renounceMinter(), so these powers could be given up, and no opened source shows whether any holder's allowance was written or any balance moved. The contract currently reports owner 0x949adc6e…c5c283, which differs from the deployer 0x4a94ee3A…80E198; the ownership transfer transaction was not examined. De.Fi's REKT database lists the token as an exit scam / rug pull dated 2021-10-12.

Protocol details

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

Build your security review skills

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