From a2db4eec82d92560242070b49e593c48785569ae Mon Sep 17 00:00:00 2001 From: tolly Date: Tue, 16 Sep 2025 15:58:43 +0100 Subject: [PATCH 1/6] Rug Radar PoC Signed-off-by: tolly --- rug_radar.py | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 rug_radar.py diff --git a/rug_radar.py b/rug_radar.py new file mode 100644 index 0000000..732a144 --- /dev/null +++ b/rug_radar.py @@ -0,0 +1,72 @@ +# rug_radar.py +# Rug Radar Trap PoC for Drosera +# +# This script is a simple proof-of-concept to detect possible rug-pull risks +# in ERC-20 token contracts. + +from web3 import Web3 + +# Connect to Ethereum RPC (you can change this to another RPC if you like) +w3 = Web3(Web3.HTTPProvider("https://rpc.ankr.com/eth")) + +# Example token contract (replace with any ERC-20 address you want to test) +token_address = Web3.to_checksum_address("0x0000000000000000000000000000000000000000") + +# Minimal ABI to check ERC-20 details +erc20_abi = [ + { + "constant": True, + "inputs": [], + "name": "owner", + "outputs": [{"name": "", "type": "address"}], + "type": "function", + }, + { + "constant": True, + "inputs": [], + "name": "totalSupply", + "outputs": [{"name": "", "type": "uint256"}], + "type": "function", + }, +] + +def scan_contract(address): + """ + Scans an ERC-20 contract for owner and totalSupply. + + Parameters: + address (str): The ERC-20 token contract address. + + Returns: + dict: Contains 'owner' and 'totalSupply' or None if data cannot be fetched. + """ + try: + contract = w3.eth.contract(address=address, abi=erc20_abi) + + # Check owner + try: + owner = contract.functions.owner().call() + print(f"Owner address: {owner}") + except Exception: + owner = None + print("⚠️ Could not fetch owner (might be hidden or renounced)") + + # Check total supply + try: + supply = contract.functions.totalSupply().call() + print(f"Total Supply: {supply}") + except Exception: + supply = None + print("⚠️ Could not fetch total supply") + + print("✅ Rug Radar scan completed (PoC)") + return {"owner": owner, "totalSupply": supply} + + except Exception as e: + print("Error connecting to contract:", e) + return None + + +# Run scan +if __name__ == "__main__": + scan_contract(token_address) From a984335a57c2d426ae5908b2128bd061996847ac Mon Sep 17 00:00:00 2001 From: tolly Date: Tue, 16 Sep 2025 16:14:09 +0100 Subject: [PATCH 2/6] Add README for Rug Radar Trap PoC Signed-off-by: tolly --- rug_radar_trap/README.md | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 rug_radar_trap/README.md diff --git a/rug_radar_trap/README.md b/rug_radar_trap/README.md new file mode 100644 index 0000000..1aa2486 --- /dev/null +++ b/rug_radar_trap/README.md @@ -0,0 +1,24 @@ +# Rug Radar Trap (PoC) + +This is a **proof of concept trap** idea for the Drosera ecosystem. +It demonstrates how a tool could scan ERC-20 token contracts for potential rug-pull indicators. + +## What it does +- Connects to Ethereum via RPC +- Checks who the contract `owner` is +- Fetches the total token supply +- Warns if certain info is missing (which could be a red flag) + +## How to Run +1. Install Web3: + pip install web3 + +2. Run the script: + python rug_radar.py + +## Notes +- This is a minimal PoC, **not a full rug detector**. +- Future improvements could include: + - Checking for mint/blacklist functions + - Detecting high owner liquidity control + - Monitoring sudden changes in trading settings From 0de3120193cf37665ac11fe537eb6d12c79da615 Mon Sep 17 00:00:00 2001 From: tolly Date: Tue, 23 Sep 2025 17:20:32 +0100 Subject: [PATCH 3/6] Add UniqueRugRadar contract Signed-off-by: tolly --- .../contracts/UniqueRugRadar.sol | 82 +++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 traps/unique_rugradar/contracts/UniqueRugRadar.sol diff --git a/traps/unique_rugradar/contracts/UniqueRugRadar.sol b/traps/unique_rugradar/contracts/UniqueRugRadar.sol new file mode 100644 index 0000000..bb53545 --- /dev/null +++ b/traps/unique_rugradar/contracts/UniqueRugRadar.sol @@ -0,0 +1,82 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.20; + +contract UniqueRugRadar { + address public targetToken; + uint256 public thresholdPct; + + event Collected(address token, address owner, bool ownerFound, uint256 totalSupply); + + constructor(address _token, uint256 _thresholdPct) { + require(_token != address(0), "token = zero"); + targetToken = _token; + thresholdPct = _thresholdPct; + } + + function _tryOwner(address token) internal view returns (address owner, bool found) { + bytes4 sel = bytes4(keccak256("owner()")); + (bool ok, bytes memory data) = token.staticcall(abi.encodeWithSelector(sel)); + if (ok && data.length >= 32) { + owner = abi.decode(data, (address)); + found = true; + } else { + owner = address(0); + found = false; + } + } + + function collect() external view returns (bytes memory) { + (address owner, bool ownerFound) = _tryOwner(targetToken); + + uint256 ts; + bool tsFound; + (bool ok, bytes memory data) = targetToken.staticcall(abi.encodeWithSelector(bytes4(keccak256("totalSupply()")))); + if (ok && data.length >= 32) { + ts = abi.decode(data, (uint256)); + tsFound = true; + } else { + ts = 0; + tsFound = false; + } + + emit Collected(targetToken, owner, ownerFound, ts); + return abi.encode(ownerFound, owner, tsFound, ts); + } + + function shouldRespond(bytes[] calldata data) external pure returns (bool, bytes memory) { + if (data.length < 2) { + return (false, abi.encode(uint256(0))); + } + + (, , bool tsFoundNew, uint256 tsNew) = abi.decode(data[0], (bool, address, bool, uint256)); + (, , bool tsFoundPrev, uint256 tsPrev) = abi.decode(data[1], (bool, address, bool, uint256)); + + if (!tsFoundNew || !tsFoundPrev) { + return (false, abi.encode(uint256(0))); + } + + if (tsPrev == 0) { + return (false, abi.encode(uint256(0))); + } + + if (tsNew >= tsPrev) { + return (false, abi.encode(uint256(0))); + } + + uint256 drop = ((tsPrev - tsNew) * 100) / tsPrev; + + if (drop >= 10) { + return (true, abi.encode(drop)); + } + + return (false, abi.encode(drop)); + } + + function setTargetToken(address _token) external { + targetToken = _token; + } + + function setThreshold(uint256 _pct) external { + thresholdPct = _pct; + } +} From 7de1dfaeb9ffd25a273ba0e93843fa0c35713176 Mon Sep 17 00:00:00 2001 From: tolly Date: Tue, 23 Sep 2025 17:22:37 +0100 Subject: [PATCH 4/6] Add trap.yml for UniqueRugRadar Signed-off-by: tolly --- .../unique_rugradar/contracts/traps/unique_rugradar/trap.yml | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 traps/unique_rugradar/contracts/traps/unique_rugradar/trap.yml diff --git a/traps/unique_rugradar/contracts/traps/unique_rugradar/trap.yml b/traps/unique_rugradar/contracts/traps/unique_rugradar/trap.yml new file mode 100644 index 0000000..4a80222 --- /dev/null +++ b/traps/unique_rugradar/contracts/traps/unique_rugradar/trap.yml @@ -0,0 +1,5 @@ +name: UniqueRugRadar +description: "Test trap that collects owner() and totalSupply() for a test token and fires when totalSupply drops >= 10%." +version: 0.1.0 +entrypoint: contracts/UniqueRugRadar.sol +author: tollynft From 093690bc337a8527f42b9c3df99e531c65d83b2c Mon Sep 17 00:00:00 2001 From: tolly Date: Tue, 23 Sep 2025 17:23:30 +0100 Subject: [PATCH 5/6] Add drosera.toml for UniqueRugRadar Signed-off-by: tolly --- .../unique_rugradar/traps/unique_rugradar/drosera.toml | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 traps/unique_rugradar/contracts/traps/unique_rugradar/traps/unique_rugradar/drosera.toml diff --git a/traps/unique_rugradar/contracts/traps/unique_rugradar/traps/unique_rugradar/drosera.toml b/traps/unique_rugradar/contracts/traps/unique_rugradar/traps/unique_rugradar/drosera.toml new file mode 100644 index 0000000..eb3d836 --- /dev/null +++ b/traps/unique_rugradar/contracts/traps/unique_rugradar/traps/unique_rugradar/drosera.toml @@ -0,0 +1,6 @@ +chain = "holesky" +ethereum_rpc = "https://ethereum-holesky-rpc.publicnode.com" +response_contract = "" +response_function = "" +path = "contracts/UniqueRugRadar.sol" +# Use DROSERA_PRIVATE_KEY env var locally when running drosera apply From b1f84b7d90548144fc1a020a9227a32f885f8ba2 Mon Sep 17 00:00:00 2001 From: tolly Date: Tue, 23 Sep 2025 22:31:54 +0100 Subject: [PATCH 6/6] Update README with UniqueRug Radar Trap details Signed-off-by: tolly --- rug_radar_trap/README.md | 39 +++++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/rug_radar_trap/README.md b/rug_radar_trap/README.md index 1aa2486..722bb80 100644 --- a/rug_radar_trap/README.md +++ b/rug_radar_trap/README.md @@ -1,24 +1,27 @@ -# Rug Radar Trap (PoC) +# UniqueRug Radar Trap (PoC) +## Overview This is a **proof of concept trap** idea for the Drosera ecosystem. -It demonstrates how a tool could scan ERC-20 token contracts for potential rug-pull indicators. +This trap monitors unusual changes in the **total supply** of an ERC-20 token. +A sudden drop in supply can be a red flag for manipulations or hidden risks. -## What it does -- Connects to Ethereum via RPC -- Checks who the contract `owner` is -- Fetches the total token supply -- Warns if certain info is missing (which could be a red flag) +## How It Works +- `collect()` → Reads `totalSupply()` from the token contract. +- `shouldRespond()` → Compares consecutive values. + - If supply decreases by **15%**, it triggers a response. -## How to Run -1. Install Web3: - pip install web3 +## Example Test Log +collect() #1 → totalSupply: 1,000,000 +collect() #2 → totalSupply: 850,000 +shouldRespond([#1, #2]) → true (drop 15%) -2. Run the script: - python rug_radar.py +⚠️ *These logs are test/example values only — no live tokens were used.* -## Notes -- This is a minimal PoC, **not a full rug detector**. -- Future improvements could include: - - Checking for mint/blacklist functions - - Detecting high owner liquidity control - - Monitoring sudden changes in trading settings +## Why It Matters +- Sudden supply drops may indicate **burn exploits, hidden logic, or rug-pull patterns**. +- Helps illustrate how Drosera traps can highlight **token integrity risks**. + +## Benefits +- **Developers:** Quick detection of abnormal token behavior. +- **Auditors:** Structured on-chain data for analysis. +- **Users:** Early warning of potential manipulations.