Skip to content

Commit 7c8e021

Browse files
authored
Create README.md for InvCon results documentation
Add README.md for InvCon invariant mining results detailing directory structure, execution outcomes, and known limitations.
1 parent 8fc93ec commit 7c8e021

1 file changed

Lines changed: 152 additions & 0 deletions

File tree

results/README.md

Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
# InvCon — Invariant Mining Results
2+
3+
This directory contains the invariant files (`.inv`) produced by running [InvCon](https://github.com/ASSERT-KTH/InvCon-Tool) against a curated dataset of real-world vulnerable Ethereum smart contracts.
4+
5+
---
6+
7+
## Directory Structure
8+
9+
Each subdirectory corresponds to one contract run and is named after the incident identifier from the dfhl-invariants database:
10+
11+
```
12+
results/
13+
├── 201804_BEC/
14+
│ ├── <contract_address>.inv # Daikon invariant file
15+
├── 201804_SmartMesh/
16+
│ └── ...
17+
├── 202102_Yearn_ydai/
18+
│ └── ...
19+
└── ...
20+
```
21+
22+
---
23+
24+
## How These Results Were Generated
25+
26+
### Environment
27+
28+
All runs were performed inside a Docker container built from the `Dockerfile` at the root of this repository. The image is based on `ubuntu:22.04` and pins the following key dependencies:
29+
30+
| Dependency | Version |
31+
|---|---|
32+
| Python | 3.10 (system) |
33+
| Slither | 0.10.0 |
34+
| Daikon | 5.8.6 |
35+
| Node.js | system (apt) |
36+
| web3.py | bundled with Slither |
37+
38+
### Running a Single Contract
39+
40+
```bash
41+
# Build the image
42+
docker build -t invcon .
43+
44+
# Run against a contract address
45+
docker run --rm \
46+
-e ETHERSCAN_API_KEY=$ETHERSCAN_API_KEY \
47+
-v $(pwd)/results/<incident_name>:/home/realworldcontracts/ \
48+
invcon \
49+
--eth_address <0x_contract_address> \
50+
--workspace /home/realworldcontracts/
51+
```
52+
53+
The `ETHERSCAN_API_KEY` environment variable must be set to a valid [Etherscan V2 API key](https://docs.etherscan.io/getting-started/viewing-api-usage-statistics). The tool fetches source code, ABI, and transaction histories live from Etherscan.
54+
55+
### Running the Full Batch
56+
57+
The full batch was executed using the following script on a WSL (Ubuntu) host:
58+
59+
```bash
60+
#!/bin/bash
61+
mkdir -p ~/invcon-results
62+
63+
# Parse contract addresses from the dfhl-invariants database JSON
64+
python3 -c "
65+
import json
66+
db = json.load(open('database.json'))
67+
for name, entry in db.items():
68+
if entry.get('blockchain') == 'Ethereum' and entry.get('vulnerable_contract_address'):
69+
print(f\"{name},{entry['vulnerable_contract_address']}\")
70+
" > /tmp/contracts.csv
71+
72+
while IFS=, read -r name address; do
73+
echo "=== Running $name ($address) ==="
74+
mkdir -p ~/invcon-results/$name
75+
docker run --rm \
76+
-e ETHERSCAN_API_KEY=$ETHERSCAN_API_KEY \
77+
-v ~/invcon-results/$name:/home/realworldcontracts/ \
78+
invcon \
79+
--eth_address "$address" \
80+
--workspace /home/realworldcontracts/ \
81+
> ~/invcon-results/$name/run.log 2>&1 || true
82+
echo "Done."
83+
done < /tmp/contracts.csv
84+
```
85+
86+
### Committing Results to This Repository
87+
88+
Results were pushed to this repository as follows:
89+
90+
```bash
91+
# From the repo root (after running the batch)
92+
cp -r ~/invcon-results/* results/
93+
94+
# Stage and commit
95+
git add results/
96+
git commit -m "feat(results): add InvCon invariant mining output for dfhl-invariants dataset
97+
98+
- 26 contracts attempted from the ASSERT-KTH dfhl-invariants database
99+
- 12 clean successful runs, 3 partial (no Daikon samples), 9 hard failures
100+
- See results/README.md for full execution outcome table and root cause analysis"
101+
102+
git push origin main
103+
```
104+
105+
---
106+
107+
## Execution Outcomes
108+
109+
| Incident ID | Contract | Status | `.inv` File | Notes |
110+
|---|---|:---:|:---:|---|
111+
| 201804_BEC | `0xC5d...` || `BecToken.inv` | ERC20 token; fallback IndexErrors non-fatal |
112+
| 201804_SmartMesh | `0x55f...` || `SMT.inv` | ERC20 token; 3000 txs in ~18 min |
113+
| 202008_Opyn | `0x951...` ||| `Web3.soliditySha3` deprecated API crash |
114+
| 202102_Yearn_ydai | `0xACd...` || `yVault.inv` | Vault contract; 2000 txs |
115+
| 202109_Nimbus | `0xc0A...` ||| `uint112` not supported in storage layout parser |
116+
| 202201_Anyswap | `0x6b7...` || `AnyswapV4Router.inv` | Cross-chain router; 3000 txs |
117+
| 202202_TecraSpace | `0x...` ||| Crawler `SystemExit(-1)` — Etherscan data unavailable |
118+
| 202206_InverseFinance | `0xE8b...` | ⚠️ | `YVCrv3CryptoFeed.inv` (empty) | 0 transactions crawled — likely proxy contract |
119+
| 202209_BadGuysbyRPF | `0xB84...` ||| Unsupported NFT parameter types (URI strings, bytes) |
120+
| 202210_N00d | `0x356...` || `SushiBar.inv` | 97 txs; clean run |
121+
| 202210_Uerii | `0x418...` || `Token.inv` | 491 txs; clean run |
122+
| 202212_JAY | `0xf29...` | ⚠️ | `JAY.inv` (partial) | Malformed dtrace at line 5520 (string escaping) |
123+
| 202301_QTN | `0xC9f...` || `QUATERNION.inv` | 387 txs; clean run |
124+
| 202305_ERC20TokenBank | `0x765...` | ⚠️ | `ExchangeBetweenPools.inv` (empty) | 0 tx — proxy/router pattern |
125+
| 202306_VINU | `0xF7e...` || `VINU.in` | 14 txs; clean run |
126+
| 202308_Uwerx | `0x430...` || `Uwerx.inv` | 75 txs; clean run |
127+
| 202309_uniclyNFT | `0xd3c...` ||| `bytes4` not supported in storage layout parser |
128+
| 202310_PseudoETH | `0x203...` ||| `uint112` not supported (Uniswap V2 pattern) |
129+
| 202311_grok | `0x839...` || `GROK.inv` | 3000 txs; ~35 min crawl |
130+
| 202404_HoppyFrogERC | `0xe5c...` || `Hoppy.inv` | ERC721; 2000 txs; non-fatal NFT param errors |
131+
| 202406_APEMAGA | `0x56f...` || `Tonken.inv` | 20 txs; clean run |
132+
| 202406_JokInTheBox | `0xA64...` ||| Source is Handlebars template `{{` — Slither compile fail |
133+
| 202406_WIFCOIN_ETH | `0xA1c...` ||| Same `{{` template source issue |
134+
| 202408_OMPxContract | `0x203...` ||| `Unknown Error` in `Contract.__init__` |
135+
| 202409_Bedrock_DeFi | `0x702...` || `Vault.inv` | 2 txs; clean run |
136+
| 202409_OnyxDAO | `0x...` ||| `Unknown Error` in `Contract.__init__` |
137+
138+
**Legend:** ✅ Full success — `.inv` file produced with Daikon output · ⚠️ Tool completed but no usable invariants · ❌ Hard failure — no output produced
139+
140+
---
141+
142+
## Known Limitations
143+
144+
1. **Transaction cap:** InvCon fetches at most 2,000 transactions per contract (configurable via `--txs_limit`). Invariants derived from fewer transactions have lower statistical confidence.
145+
2. **Etherscan dependency:** Results require a live Etherscan connection. API rate limits may cause partial crawls. The API key used during this study has been revoked after use.
146+
3. **Unsupported Solidity types:** InvCon's storage layout parser (`parsing/storageLayout.py`) does not handle sub-32-byte integer types (`uint112`, `uint96`, etc.) or fixed-size byte arrays (`bytes4`, `bytes8`). Contracts using these types (e.g., Uniswap V2 forks using `uint112` for reserves) will fail.
147+
4. **Proxy contracts:** InvCon queries only the specified address. Proxy contracts that delegate all logic to an implementation contract will return 0 transactions and produce empty invariant files.
148+
5. **No ERC721 support:** NFT-specific parameter types (`tokenId` + `bytes data` in `safeTransferFrom`) cause non-fatal decoding errors. Some invariants may be absent for ERC721 contracts.
149+
150+
---
151+
152+
*Generated April 2026 · InvCon commit: ASSERT-KTH/InvCon-Tool `main`*

0 commit comments

Comments
 (0)