├── .gitignore ├── README.md └── images ├── 1544.jpeg ├── 2554.jpeg ├── 319.jpeg └── 3316.jpeg /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | pip-wheel-metadata/ 24 | share/python-wheels/ 25 | *.egg-info/ 26 | .installed.cfg 27 | *.egg 28 | MANIFEST 29 | 30 | # PyInstaller 31 | # Usually these files are written by a python script from a template 32 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 33 | *.manifest 34 | *.spec 35 | 36 | # Installer logs 37 | pip-log.txt 38 | pip-delete-this-directory.txt 39 | 40 | # Unit test / coverage reports 41 | htmlcov/ 42 | .tox/ 43 | .nox/ 44 | .coverage 45 | .coverage.* 46 | .cache 47 | nosetests.xml 48 | coverage.xml 49 | *.cover 50 | *.py,cover 51 | .hypothesis/ 52 | .pytest_cache/ 53 | 54 | # Translations 55 | *.mo 56 | *.pot 57 | 58 | # Django stuff: 59 | *.log 60 | local_settings.py 61 | db.sqlite3 62 | db.sqlite3-journal 63 | 64 | # Flask stuff: 65 | instance/ 66 | .webassets-cache 67 | 68 | # Scrapy stuff: 69 | .scrapy 70 | 71 | # Sphinx documentation 72 | docs/_build/ 73 | 74 | # PyBuilder 75 | target/ 76 | 77 | # Jupyter Notebook 78 | .ipynb_checkpoints 79 | 80 | # IPython 81 | profile_default/ 82 | ipython_config.py 83 | 84 | # pyenv 85 | .python-version 86 | 87 | # pipenv 88 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 89 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 90 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 91 | # install all needed dependencies. 92 | #Pipfile.lock 93 | 94 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 95 | __pypackages__/ 96 | 97 | # Celery stuff 98 | celerybeat-schedule 99 | celerybeat.pid 100 | 101 | # SageMath parsed files 102 | *.sage.py 103 | 104 | # Environments 105 | .env 106 | .venv 107 | env/ 108 | venv/ 109 | ENV/ 110 | env.bak/ 111 | venv.bak/ 112 | 113 | # Spyder project settings 114 | .spyderproject 115 | .spyproject 116 | 117 | # Rope project settings 118 | .ropeproject 119 | 120 | # mkdocs documentation 121 | /site 122 | 123 | # mypy 124 | .mypy_cache/ 125 | .dmypy.json 126 | dmypy.json 127 | 128 | # Pyre type checker 129 | .pyre/ 130 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Arbitrum Sybil Detection 2 | 3 | This project aims to remove Sybil addresses from the Arbitrum airdrop, ensuring that only legitimate users receive the airdrop tokens. 4 | 5 | --- 6 | 7 | ## Methodology 8 | 9 | We use on-chain data to identify related addresses owned by the same user and remove entity addresses such as bridges, exchanges, and smart contracts using data from Nansen, Hop, and OffChain Labs. There are also some addresses being removed by manual inspection, such as donation addresses, l2 alias, etc. 10 | 11 | With those cleaned up, 2 graphs are generated for this study: 12 | 13 | Graph 1: In this graph, each transaction with msg.value is treated as an edge with their (from_address, to_address) 14 | 15 | Graph 2: In this graph, each funder/sweep transaction is treated as an edge with their (from_address, to_address) 16 | 17 | - **funder transaction** is the first ether transfer to an account 18 | - **sweep transaction** is the last ether transfer from an account 19 | 20 | --- 21 | 22 | ## Sybil Cluster Identification 23 | 24 | Clusters are generated by partitioning the above graphs into strongly connected and weakly connected subgraphs. Large subgraphs are broken down using the Louvain Community Detection Algorithm, providing more refined results and eliminating Sybil addresses more accurately. 25 | 26 | We identify Sybil clusters based on known patterns, here are some examples 27 | 28 | - Addresses transferring funds in a cluster of more than 20 addresses 29 | - Addresses that are funded from the same source 30 | - Addresses with similar activity 31 | 32 | --- 33 | 34 | ## Examples 35 | 36 | ### Cluster 319 with 110 eligible addresses 37 | ![ alt text for screen readers](/images/319.jpeg "cluster 319") 38 | Sample address: 0x1ddbf60792aac896aed180eaa6810fccd7839ada 39 | 40 | ### Cluster 1544 with 56 eligible addresses 41 | ![ alt text for screen readers](/images/1544.jpeg "cluster 1544") 42 | Sample address: 0xc7bb9b943fd2a04f651cc513c17eb5671b90912d 43 | 44 | ### Cluster 2554 with 121 eligible addresses 45 | ![ alt text for screen readers](/images/2554.jpeg "cluster 2554") 46 | Sample address: 0x3fb4c01b5ceecf307010f84c9a858aeaeab0b9fa 47 | 48 | ### Cluster 3316 with 65 eligible addresses 49 | ![ alt text for screen readers](/images/3316.jpeg "cluster 3316") 50 | Sample address: 0x15bc18bb8c378c94c04795d72621957497130400 51 | 52 | --- 53 | 54 | ## Inputs Used 55 | 56 | 1. Raw Eligibility List (from Nansen) 57 | 58 | 2. Excluded Entities (from Nansen) 59 | 60 | 3. CEX Deposit Addresses (from Nansen) 61 | 62 | 4. CEX Deposit Addresses (traced from CEXs hot wallets) 63 | 64 | 5. Unique transaction and traces (from,to) Arbitrum 65 | 66 | 6. Unique transaction and traces (from,to) Ethereum 67 | 68 | 7. Internal Address list from OffChain Labs 69 | 70 | 8. [Hop Blacklist](https://github.com/hop-protocol/hop-airdrop/blob/master/src/data/blacklists/blacklist.ts) 71 | 72 | 9. [Hop eliminatedSybilAttackers](https://github.com/hop-protocol/hop-airdrop/blob/master/src/data/eliminatedSybilAttackers.csv) 73 | 74 | 10. Nansen address tags 75 | 76 | 11. Other active addresses tagged manually 77 | -------------------------------------------------------------------------------- /images/1544.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArbitrumFoundation/sybil-detection/ceda238929057c2ff40484aaed3eee096e7ed120/images/1544.jpeg -------------------------------------------------------------------------------- /images/2554.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArbitrumFoundation/sybil-detection/ceda238929057c2ff40484aaed3eee096e7ed120/images/2554.jpeg -------------------------------------------------------------------------------- /images/319.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArbitrumFoundation/sybil-detection/ceda238929057c2ff40484aaed3eee096e7ed120/images/319.jpeg -------------------------------------------------------------------------------- /images/3316.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ArbitrumFoundation/sybil-detection/ceda238929057c2ff40484aaed3eee096e7ed120/images/3316.jpeg --------------------------------------------------------------------------------