Rug pull protection system development

We design and develop full-cycle blockchain solutions: from smart contract architecture to launching DeFi protocols, NFT marketplaces and crypto exchanges. Security audits, tokenomics, integration with existing infrastructure.
Showing 1 of 1 servicesAll 1306 services
Rug pull protection system development
Complex
~3-5 business days
FAQ
Blockchain Development Services
Blockchain Development Stages
Latest works
  • image_website-b2b-advance_0.png
    B2B ADVANCE company website development
    1214
  • image_web-applications_feedme_466_0.webp
    Development of a web application for FEEDME
    1161
  • image_websites_belfingroup_462_0.webp
    Website development for BELFINGROUP
    852
  • image_ecommerce_furnoro_435_0.webp
    Development of an online store for the company FURNORO
    1041
  • image_logo-advance_0.png
    B2B Advance company logo design
    561
  • image_crm_enviok_479_0.webp
    Development of a web application for Enviok
    823

Development of Anti-Rug-Pull Protection System

Rug pull — when project team intentionally withdraws liquidity and/or ETH/tokens from contract, leaving holders with worthless tokens. Not technical bug — intentional. But technique enabling rug pull is concrete and predictable. Protection builds on two levels: on-chain mechanics preventing team from withdrawing liquidity, and off-chain monitoring alerting before execution.

Classification of rug pull vectors

Liquidity removal

Most common vector. Team adds liquidity to Uniswap/PancakeSwap, launches marketing, price rises → team withdraws liquidity. LP tokens owned by team, no restrictions.

Unrestricted mint

Team deploys token with mint(address, amount) accessible to owner. Anytime can mint billions and sell on market.

// DANGEROUS PATTERN
contract HoneypotToken is ERC20, Ownable {
    function mint(address to, uint256 amount) external onlyOwner {
        _mint(to, amount);  // Unrestricted mint for owner
    }
}

Hidden transfer restrictions

Contract allows only certain addresses to sell (sell restriction), blocking regular holders from selling. Owner can add/remove addresses from blacklist or whitelist.

Fee manipulation

Standard deflationary token with fee. Team can change fee to 99% — any sale returns almost everything to team.

uint256 public sellFee = 3;  // 3% — seems reasonable

// Later:
function setSellFee(uint256 fee) external onlyOwner {
    sellFee = fee;  // Can become 99%
}

On-chain protective mechanics

Locked liquidity via Unicrypt / PinkLock

Simplest protection: LP tokens locked in smart contract with timelock. Team can't physically withdraw liquidity until expiry.

// Unicrypt Liquidity Locker interface
interface IUnicryptLocker {
    function lockLPToken(
        address lpToken,
        uint256 amount,
        uint256 unlockDate,   // UNIX timestamp
        address payable referral,
        bool feeInEth,
        address payable withdrawer
    ) external payable;
}

// On launch: lock LP for minimum 1 year
function lockInitialLiquidity(address lpToken, uint256 amount) external onlyOwner {
    IERC20(lpToken).approve(address(unicryptLocker), amount);
    
    unicryptLocker.lockLPToken{value: lockFee}(
        lpToken,
        amount,
        block.timestamp + 365 days,
        payable(address(0)),
        true,
        payable(msg.sender)
    );
}

Check for users: on Unicrypt or Team.Finance can check lock by token or LP token address.

Renounced ownership and Ownable2Step

If team renounces ownership — no one can call onlyOwner functions. Maximum protection but makes contract immutable completely, including useful functions.

Compromise — limited owner via Ownable2Step with restricted powers:

contract ProtectedToken is ERC20, Ownable2Step {
    // Owner can ONLY change marketing wallet and fee parameters
    // within predefined limits
    
    uint256 public constant MAX_SELL_FEE = 500;  // max 5% — hardcoded, immutable
    uint256 public sellFee = 300;  // current 3%
    
    function setSellFee(uint256 newFee) external onlyOwner {
        require(newFee <= MAX_SELL_FEE, "Fee exceeds maximum");
        sellFee = newFee;
    }
    
    // No mint function
    // No blacklist/whitelist
    // No transfer restrictions function
}

Mint cap and fixed supply

Limit maximum supply hardcoded — not via variable but via constant:

uint256 public constant MAX_SUPPLY = 1_000_000_000 * 1e18;  // 1 billion, immutable

function mint(address to, uint256 amount) external onlyMinter {
    require(totalSupply() + amount <= MAX_SUPPLY, "Exceeds max supply");
    _mint(to, amount);
}

// After TGE — minter role revoked
function renounceMinterRole() external onlyOwner {
    minter = address(0);
}

Timelock for critical functions

Any critical parameter changes must go through timelock — delay with public announcement:

contract TimelockProtectedToken is ERC20 {
    uint256 public constant TIMELOCK_DURATION = 48 hours;
    
    function proposeFeeChange(uint256 newFee) external onlyOwner {
        require(newFee <= 500, "Too high");
        
        bytes32 changeId = keccak256(abi.encodePacked("fee", newFee, block.timestamp));
        pendingChanges[changeId] = PendingChange({
            changeType: "fee",
            newValue: newFee,
            executableAt: block.timestamp + TIMELOCK_DURATION,
            executed: false
        });
        
        emit FeeChangeProposed(changeId, newFee, block.timestamp + TIMELOCK_DURATION);
    }
    
    function executeFeeChange(bytes32 changeId) external onlyOwner {
        PendingChange storage change = pendingChanges[changeId];
        require(!change.executed, "Already executed");
        require(block.timestamp >= change.executableAt, "Timelock not passed");
        
        change.executed = true;
        sellFee = change.newValue;
        
        emit FeeChanged(change.newValue);
    }
}

Timelock gives community 48 hours to see change and exit before it applies.

Off-chain monitoring: early detection

Contract analysis before purchase

Automatic scanner checks contract before interaction:

interface ContractRiskAssessment {
  address: string;
  risks: RiskItem[];
  score: number;  // 0 (safe) to 100 (high risk)
}

async function analyzeToken(tokenAddress: string): Promise<ContractRiskAssessment> {
  const risks: RiskItem[] = [];
  
  // 1. Check for mint function
  const hasMintFunction = await checkFunctionExists(tokenAddress, 'mint(address,uint256)');
  if (hasMintFunction) {
    const mintRestricted = await checkMintHasSupplyCap(tokenAddress);
    if (!mintRestricted) {
      risks.push({
        severity: 'critical',
        type: 'UNLIMITED_MINT',
        description: 'Owner can mint unlimited tokens'
      });
    }
  }
  
  // 2. Check owner
  const owner = await getContractOwner(tokenAddress);
  const ownerRenounced = owner === ZERO_ADDRESS;
  if (!ownerRenounced) {
    const ownerCapabilities = await getOwnerCapabilities(tokenAddress);
    if (ownerCapabilities.canChangeTransferRestrictions) {
      risks.push({
        severity: 'high',
        type: 'TRANSFER_RESTRICTION',
        description: 'Owner can restrict token transfers (potential honeypot)'
      });
    }
  }
  
  // 3. LP lock status
  const lpToken = await getUniswapLPToken(tokenAddress);
  if (lpToken) {
    const lockStatus = await checkLiquidityLock(lpToken);
    if (!lockStatus.isLocked) {
      risks.push({
        severity: 'high',
        type: 'UNLOCKED_LIQUIDITY',
        description: 'Liquidity is not locked'
      });
    }
  }
  
  // 4. Proxy check
  const isProxy = await isProxyContract(tokenAddress);
  if (isProxy) {
    const proxyAdmin = await getProxyAdmin(tokenAddress);
    const proxyAdminIsTimelocked = await isTimelocked(proxyAdmin);
    if (!proxyAdminIsTimelocked) {
      risks.push({
        severity: 'high',
        type: 'UPGRADEABLE_NO_TIMELOCK',
        description: 'Upgradeable contract without timelock on admin'
      });
    }
  }
  
  const score = calculateRiskScore(risks);
  return { address: tokenAddress, risks, score };
}

Honeypot detection: simulation of sale

Best way to check honeypot — simulate sell transaction via fork:

async function simulateSell(
  tokenAddress: string,
  amount: bigint,
  holderAddress: string
): Promise<{ canSell: boolean; receivedAmount: bigint; errorReason?: string }> {
  
  // Fork mainnet locally
  const anvil = await startAnvil({ forkUrl: MAINNET_RPC, forkBlockNumber: 'latest' });
  
  try {
    // Impersonate holder address
    await anvil.impersonateAccount(holderAddress);
    
    const router = getContract({ address: UNISWAP_V2_ROUTER, abi: ROUTER_ABI });
    const token = getContract({ address: tokenAddress, abi: ERC20_ABI });
    
    // Approve
    await token.write.approve([UNISWAP_V2_ROUTER, amount], { account: holderAddress });
    
    // Simulate sell
    const ethBalanceBefore = await anvil.getBalance(holderAddress);
    
    await router.write.swapExactTokensForETHSupportingFeeOnTransferTokens(
      [amount, 0n, [tokenAddress, WETH], holderAddress, BigInt(Date.now()) + 1000n],
      { account: holderAddress }
    );
    
    const ethBalanceAfter = await anvil.getBalance(holderAddress);
    const receivedETH = ethBalanceAfter - ethBalanceBefore;
    
    return { canSell: true, receivedAmount: receivedETH };
    
  } catch (error) {
    return { canSell: false, receivedAmount: 0n, errorReason: error.message };
  } finally {
    await anvil.close();
  }
}

This catches honeypot allowing transaction to pass but with 99% transfer fee.

Integration into product

System can be:

  1. Browser extension — warning on risky token approve or swap
  2. DEX frontend middleware — check before swap confirmation
  3. Portfolio tracker — monitor already purchased tokens
  4. Telegram/Discord bot — alerts for watchlist tokens

No automatic tool gives 100% protection — experienced scammer can create contract passing all checks. But raising effort barrier makes attacks less profitable and filters most opportunistic rug pulls.

Components and timeline

Component Description Timeline
Contract analyzer Static bytecode + ABI analysis 3–4 weeks
Honeypot simulator Anvil fork + sale simulation 2–3 weeks
Real-time monitor WebSocket event listener + alerts 2–3 weeks
LP lock checker Unicrypt, PinkLock, Team.Finance integration 1–2 weeks
3rd party integration GoPlus, Token Sniffer API 1 week
Frontend/bot UI or Telegram bot for alerts 2–4 weeks
Database Check history, caching 1–2 weeks