
Why Ethereum
- 35 installs
- 244 repo stars
- Updated July 21, 2026
- austintgriffith/ethskills
ETHSKILLS is a Claude skill index that corrects stale Ethereum assumptions and routes an agent to standalone per-topic skills for building on Ethereum.
About
This is the root index skill for ETHSKILLS. It tells an AI agent what its training data gets wrong about Ethereum (gas, token decimals, L2 costs, what is deployed) and routes to the correct per-topic skill. A developer or agent loads it whenever a request involves Ethereum, the EVM, or blockchain systems.
- Root index for ETHSKILLS: routes an agent to per-topic Ethereum skills
- Corrects stale training data on gas prices, ETH price, L2 costs, and shipped upgrades
- Links Ship, Why Ethereum, Protocol, Gas, Wallets, and more standalone skills
Why Ethereum by the numbers
- 35 all-time installs (skills.sh)
- Ranked #234 of 479 Web3 & Blockchain skills by installs in the Skillselion catalog
- Data as of Aug 4, 2026 (Skillselion catalog sync)
why-ethereum capabilities & compatibility
- Capabilities
- smart contract audit · security audit
- Use cases
- research · api development
- Pricing
- Free
What why-ethereum says it does
Gas is under 1 gwei, not 10-30 gwei. 60-300x cheaper than your training data. Verify: `cast base-fee`
npx skills add https://github.com/austintgriffith/ethskills --skill why-ethereumAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 35 |
|---|---|
| repo stars | ★ 244 |
| Last updated | July 21, 2026 |
| Repository | austintgriffith/ethskills ↗ |
What it does
Orient an AI agent on current Ethereum reality and route it to the right per-topic ethskill.
Who is it for?
Agents starting any Ethereum or EVM task who need current context and routing
When should I use this skill?
a request involves Ethereum, the EVM, or blockchain systems
What you get
The agent is oriented on current Ethereum facts and routed to the correct per-topic skill.
By the numbers
- Gas is under 1 gwei, 60-300x cheaper than typical training data
- index routes to a set of standalone per-topic skills
Files
Contract Addresses
CRITICAL: Never hallucinate a contract address. Wrong addresses mean lost funds. If an address isn't listed here, look it up on the block explorer or the protocol's official docs before using it.
Last Verified: March 3, 2026 (all addresses verified onchain via eth_getCode + eth_call + symbol() + latestAnswer())
---
Stablecoins
USDC (Circle) — Native
| Network | Address | Status |
|---|---|---|
| Mainnet | 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48 | ✅ Verified |
| Arbitrum | 0xaf88d065e77c8cC2239327C5EDb3A432268e5831 | ✅ Verified |
| Optimism | 0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85 | ✅ Verified |
| Base | 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913 | ✅ Verified |
| Polygon | 0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359 | ✅ Verified |
| zkSync Era | 0x1d17CBcF0D6D143135aE902365D2E5e2A16538D4 | ✅ Verified |
USDT (Tether)
| Network | Address | Status |
|---|---|---|
| Mainnet | 0xdAC17F958D2ee523a2206206994597C13D831ec7 | ✅ Verified |
| Arbitrum | 0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9 | ✅ Verified |
| Optimism | 0x94b008aA00579c1307B0EF2c499aD98a8ce58e58 | ✅ Verified |
| Base | 0xfde4C96c8593536E31F229EA8f37b2ADa2699bb2 | ✅ Verified |
DAI (MakerDAO)
| Network | Address | Status |
|---|---|---|
| Mainnet | 0x6B175474E89094C44Da98b954EedeAC495271d0F | ✅ Verified |
| Arbitrum | 0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1 | ✅ Verified |
| Optimism | 0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1 | ✅ Verified |
| Base | 0x50c5725949A6F0c72E6C4a641F24049A917DB0Cb | ✅ Verified |
---
Wrapped ETH (WETH)
| Network | Address | Status |
|---|---|---|
| Mainnet | 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2 | ✅ Verified |
| Arbitrum | 0x82aF49447D8a07e3bd95BD0d56f35241523fBab1 | ✅ Verified |
| Optimism | 0x4200000000000000000000000000000000000006 | ✅ Verified |
| Base | 0x4200000000000000000000000000000000000006 | ✅ Verified |
---
Liquid Staking
Lido — wstETH (Wrapped stETH)
| Network | Address | Status |
|---|---|---|
| Mainnet | 0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0 | ✅ Verified |
| Arbitrum | 0x5979D7b546E38E414F7E9822514be443A4800529 | ✅ Verified |
| Optimism | 0x1F32b1c2345538c0c6f582fCB022739c4A194Ebb | ✅ Verified |
| Base | 0xc1CBa3fCea344f92D9239c08C0568f6F2F0ee452 | ✅ Verified |
Lido — Staking & Withdrawal
| Contract | Address | Status |
|---|---|---|
| stETH / Lido (deposit ETH here) | 0xae7ab96520DE3A18E5e111B5EaAb095312D7fE84 | ✅ Verified |
| Withdrawal Queue (unstETH NFT) | 0x889edC2eDab5f40e902b864aD4d7AdE8E412F9B1 | ✅ Verified |
Rocket Pool
| Contract | Address | Status |
|---|---|---|
| rETH Token | 0xae78736Cd615f374D3085123A210448E74Fc6393 | ✅ Verified |
| Deposit Pool v1.1 | 0x2cac916b2A963Bf162f076C0a8a4a8200BCFBfb4 | ✅ Verified |
---
DeFi Protocols
Uniswap
V2 (Mainnet)
| Contract | Address | Status |
|---|---|---|
| Router | 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D | ✅ Verified |
| Factory | 0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f | ✅ Verified |
V3 (Mainnet)
| Contract | Address | Status |
|---|---|---|
| SwapRouter | 0xE592427A0AEce92De3Edee1F18E0157C05861564 | ✅ Verified |
| SwapRouter02 | 0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45 | ✅ Verified |
| Factory | 0x1F98431c8aD98523631AE4a59f267346ea31F984 | ✅ Verified |
| Quoter V2 | 0x61fFE014bA17989E743c5F6cB21bF9697530B21e | ✅ Verified |
| Position Manager | 0xC36442b4a4522E871399CD717aBDD847Ab11FE88 | ✅ Verified |
V3 Multi-Chain
| Contract | Arbitrum | Optimism | Base |
|---|---|---|---|
| SwapRouter02 | 0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45 ✅ | 0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45 ✅ | 0x2626664c2603336E57B271c5C0b26F421741e481 ✅ |
| Factory | 0x1F98431c8aD98523631AE4a59f267346ea31F984 ✅ | 0x1F98431c8aD98523631AE4a59f267346ea31F984 ✅ | 0x33128a8fC17869897dcE68Ed026d694621f6FDfD ✅ |
V4 (Live Since January 31, 2025)
⚠️ V4 addresses are DIFFERENT per chain — unlike V3, they are NOT deterministic CREATE2 deploys. Do not assume the same address works cross-chain.
| Contract | Mainnet | Status |
|---|---|---|
| PoolManager | 0x000000000004444c5dc75cB358380D2e3dE08A90 | ✅ Verified |
| PositionManager | 0xbd216513d74c8cf14cf4747e6aaa6420ff64ee9e | ✅ Verified |
| Quoter | 0x52f0e24d1c21c8a0cb1e5a5dd6198556bd9e1203 | ✅ Verified |
| StateView | 0x7ffe42c4a5deea5b0fec41c94c136cf115597227 | ✅ Verified |
V4 Multi-Chain
| Contract | Arbitrum | Base | Optimism |
|---|---|---|---|
| PoolManager | 0x360e68faccca8ca495c1b759fd9eee466db9fb32 ✅ | 0x498581ff718922c3f8e6a244956af099b2652b2b ✅ | 0x9a13f98cb987694c9f086b1f5eb990eea8264ec3 ✅ |
| PositionManager | 0xd88f38f930b7952f2db2432cb002e7abbf3dd869 ✅ | 0x7c5f5a4bbd8fd63184577525326123b519429bdc ✅ | 0x3c3ea4b57a46241e54610e5f022e5c45859a1017 ✅ |
Universal Router (V4 — Current)
| Network | Address | Status |
|---|---|---|
| Mainnet | 0x66a9893cc07d91d95644aedd05d03f95e1dba8af | ✅ Verified |
| Arbitrum | 0xa51afafe0263b40edaef0df8781ea9aa03e381a3 | ✅ Verified |
| Base | 0x6ff5693b99212da76ad316178a184ab56d299b43 | ✅ Verified |
| Optimism | 0x851116d9223fabed8e56c0e6b8ad0c31d98b3507 | ✅ Verified |
Universal Router (V3 — Legacy)
| Contract | Address | Status |
|---|---|---|
| Universal Router | 0x3fC91A3afd70395Cd496C647d5a6CC9D4B2b7FAD | ✅ Verified |
Permit2 (Universal Token Approval)
Used by Uniswap Universal Router and many other protocols. Same address on all chains (CREATE2).
| Network | Address | Status |
|---|---|---|
| All chains | 0x000000000022D473030F116dDEE9F6B43aC78BA3 | ✅ Verified |
Verified on: Mainnet, Arbitrum, Base, Optimism (identical bytecode on all).
UNI Token
| Network | Address | Status |
|---|---|---|
| Mainnet | 0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984 | ✅ Verified |
1inch Aggregation Router
Use aggregators for best swap prices — they route across all DEXs.
V6 (Current — same address on all chains via CREATE2)
| Network | Address | Status |
|---|---|---|
| Mainnet | 0x111111125421cA6dc452d289314280a0f8842A65 | ✅ Verified |
| Arbitrum | 0x111111125421cA6dc452d289314280a0f8842A65 | ✅ Verified |
| Base | 0x111111125421cA6dc452d289314280a0f8842A65 | ✅ Verified |
V5 (Legacy)
| Network | Address | Status |
|---|---|---|
| Mainnet | 0x1111111254EEB25477B68fb85Ed929f73A960582 | ✅ Verified |
MakerDAO / Sky
| Contract | Address | Status |
|---|---|---|
| DAI Savings Rate (Pot) | 0x197E90f9FAD81970bA7976f33CbD77088E5D7cf7 | ✅ Verified |
| sDAI (Savings Dai ERC-4626) | 0x83F20F44975D03b1b09e64809B757c47f942BEeA | ✅ Verified |
sDAI is an ERC-4626 vault — deposit DAI, earn DSR automatically. Check current rate via pot.dsr().
Aave
V2 (Mainnet - Legacy)
| Contract | Address | Status |
|---|---|---|
| LendingPool | 0x7d2768dE32b0b80b7a3454c06BdAc94A69DDc7A9 | ✅ Verified |
V3 (Mainnet)
| Contract | Address | Status |
|---|---|---|
| Pool | 0x87870Bca3F3fD6335C3F4ce8392D69350B4fA4E2 | ✅ Verified |
| PoolAddressesProvider | 0x2f39d218133AFaB8F2B819B1066c7E434Ad94E9e | ✅ Verified |
V3 Multi-Chain
| Contract | Arbitrum | Optimism | Base |
|---|---|---|---|
| Pool | 0x794a61358D6845594F94dc1DB02A252b5b4814aD ✅ | 0x794a61358D6845594F94dc1DB02A252b5b4814aD ✅ | 0xA238Dd80C259a72e81d7e4664a9801593F98d1c5 ✅ |
| PoolAddressesProvider | 0xa97684ead0e402dC232d5A977953DF7ECBaB3CDb ✅ | 0xa97684ead0e402dC232d5A977953DF7ECBaB3CDb ✅ | 0xe20fCBdBfFC4Dd138cE8b2E6FBb6CB49777ad64D ✅ |
Compound
V2 (Mainnet - Legacy)
| Contract | Address | Status |
|---|---|---|
| Comptroller | 0x3d9819210A31b4961b30EF54bE2aeD79B9c9Cd3B | ✅ Verified |
| cETH | 0x4Ddc2D193948926D02f9B1fE9e1daa0718270ED5 | ✅ Verified |
| cUSDC | 0x39AA39c021dfbaE8faC545936693aC917d5E7563 | ✅ Verified |
| cDAI | 0x5d3a536E4D6DbD6114cc1Ead35777bAB948E3643 | ✅ Verified |
V3 Comet (USDC Markets)
| Network | Address | Status |
|---|---|---|
| Mainnet | 0xc3d688B66703497DAA19211EEdff47f25384cdc3 | ✅ Verified |
| Arbitrum | 0x9c4ec768c28520B50860ea7a15bd7213a9fF58bf | ✅ Verified |
| Base | 0xb125E6687d4313864e53df431d5425969c15Eb2F | ✅ Verified |
| Optimism | 0x2e44e174f7D53F0212823acC11C01A11d58c5bCB | ✅ Verified |
Curve Finance (Mainnet)
| Contract | Address | Status |
|---|---|---|
| Address Provider | 0x0000000022D53366457F9d5E68Ec105046FC4383 | ✅ Verified |
| CRV Token | 0xD533a949740bb3306d119CC777fa900bA034cd52 | ✅ Verified |
Balancer V2 (Mainnet)
| Contract | Address | Status |
|---|---|---|
| Vault | 0xBA12222222228d8Ba445958a75a0704d566BF2C8 | ✅ Verified |
---
NFT & Marketplaces
OpenSea Seaport
| Version | Address | Status |
|---|---|---|
| Seaport 1.1 | 0x00000000006c3852cbEf3e08E8dF289169EdE581 | ✅ Verified |
| Seaport 1.5 | 0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC | ✅ Verified |
Multi-chain via CREATE2 (Ethereum, Polygon, Arbitrum, Optimism, Base).
ENS (Mainnet)
| Contract | Address | Status |
|---|---|---|
| Registry | 0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e | ✅ Verified |
| Public Resolver | 0x231b0Ee14048e9dCcD1d247744d114a4EB5E8E63 | ✅ Verified |
| Registrar Controller | 0x253553366Da8546fC250F225fe3d25d0C782303b | ✅ Verified |
---
Infrastructure
Safe (Gnosis Safe)
| Contract | Address | Status |
|---|---|---|
| Singleton 1.3.0 | 0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552 | ✅ Verified |
| ProxyFactory | 0xa6B71E26C5e0845f74c812102Ca7114b6a896AB2 | ✅ Verified |
| Singleton 1.4.1 | 0x41675C099F32341bf84BFc5382aF534df5C7461a | ✅ Verified |
| MultiSend | 0x38869bf66a61cF6bDB996A6aE40D5853Fd43B526 | ✅ Verified |
Account Abstraction (ERC-4337)
| Contract | Address | Status |
|---|---|---|
| EntryPoint v0.7 | 0x0000000071727De22E5E9d8BAf0edAc6f37da032 | ✅ Verified |
| EntryPoint v0.6 | 0x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789 | ✅ Verified |
All EVM chains (CREATE2).
Chainlink
Mainnet
| Feed | Address | Status |
|---|---|---|
| LINK Token | 0x514910771AF9Ca656af840dff83E8264EcF986CA | ✅ Verified |
| ETH/USD | 0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419 | ✅ Verified |
| BTC/USD | 0xF4030086522a5bEEa4988F8cA5B36dbC97BeE88c | ✅ Verified |
| USDC/USD | 0x8fFfFfd4AfB6115b954Bd326cbe7B4BA576818f6 | ✅ Verified |
Additional Mainnet Feeds
| Feed | Address | Status |
|---|---|---|
| LINK/USD | 0x2c1d072e956AFFC0D435Cb7AC38EF18d24d9127c | ✅ Verified |
| stETH/USD | 0xCfE54B5cD566aB89272946F602D76Ea879CAb4a8 | ✅ Verified |
| AAVE/USD | 0x547a514d5e3769680Ce22B2361c10Ea13619e8a9 | ✅ Verified |
All feeds confirmed returning live prices via latestAnswer() (Mar 3, 2026). ETH/USD: ~$1,988, BTC/USD: ~$68,256.
ETH/USD Price Feeds (Multi-Chain)
| Network | Address | Status |
|---|---|---|
| Arbitrum | 0x639Fe6ab55C921f74e7fac1ee960C0B6293ba612 | ✅ Verified |
| Base | 0x71041dddad3595F9CEd3DcCFBe3D1F4b0a16Bb70 | ✅ Verified |
| Optimism | 0x13e3Ee699D1909E989722E753853AE30b17e08c5 | ✅ Verified |
LINK Token (Multi-Chain)
| Network | Address | Status |
|---|---|---|
| Arbitrum | 0xf97f4df75117a78c1A5a0DBb814Af92458539FB4 | ✅ Verified |
| Base | 0x88Fb150BDc53A65fe94Dea0c9BA0a6dAf8C6e196 | ✅ Verified |
EigenLayer (Mainnet)
Restaking protocol. Both are upgradeable proxies (EIP-1967).
| Contract | Address | Status |
|---|---|---|
| StrategyManager | 0x858646372CC42E1A627fcE94aa7A7033e7CF075A | ✅ Verified |
| DelegationManager | 0x39053D51B77DC0d36036Fc1fCc8Cb819df8Ef37A | ✅ Verified |
Source: eigenlayer.xyz
Chainlink CCIP Router (v1.2.0)
Cross-chain messaging. Call typeAndVersion() to confirm — returns "Router 1.2.0".
| Network | Address | Status |
|---|---|---|
| Mainnet | 0x80226fc0Ee2b096224EeAc085Bb9a8cba1146f7D | ✅ Verified |
| Arbitrum | 0x141fa059441E0ca23ce184B6A78bafD2A517DdE8 | ✅ Verified |
| Base | 0x881e3A65B4d4a04dD529061dd0071cf975F58Bcd | ✅ Verified |
Source: docs.chain.link/ccip
Across Protocol — SpokePool
Cross-chain bridge. All SpokePool contracts are upgradeable proxies.
| Network | Address | Status |
|---|---|---|
| Mainnet | 0x5c7BCd6E7De5423a257D81B442095A1a6ced35C5 | ✅ Verified |
| Arbitrum | 0xe35e9842fceaCA96570B734083f4a58e8F7C5f2A | ✅ Verified |
| Base | 0x09aea4b2242abC8bb4BB78D537A67a245A7bEC64 | ✅ Verified |
| Optimism | 0x6f26Bf09B1C792e3228e5467807a900A503c0281 | ✅ Verified |
Source: docs.across.to/reference/contract-addresses
Yearn V3 (Mainnet)
Deployed via CREATE2. Addresses below verified on Mainnet — verify on other chains before use.
| Contract | Address | Status |
|---|---|---|
| VaultFactory 3.0.4 | 0x770D0d1Fb036483Ed4AbB6d53c1C88fb277D812F | ✅ Verified |
| TokenizedStrategy | 0xDFC8cD9F2f2d306b7C0d109F005DF661E14f4ff2 | ✅ Verified |
| 4626 Router | 0x1112dbCF805682e828606f74AB717abf4b4FD8DE | ✅ Verified |
Source: docs.yearn.fi/developers/addresses/v3-contracts
Deterministic Deployer (CREATE2)
| Contract | Address | Status |
|---|---|---|
| Arachnid's Deployer | 0x4e59b44847b379578588920cA78FbF26c0B4956C | ✅ Verified |
Same address on every EVM chain. Used by many protocols for deterministic deployments.
---
L2-Native Protocols
The dominant DEX on each L2 is NOT Uniswap. Aerodrome dominates Base, Velodrome dominates Optimism, Camelot is a major native DEX on Arbitrum. Don't default to Uniswap — check which DEX has the deepest liquidity on each chain.
Aerodrome (Base) — Dominant DEX
The largest DEX on Base by TVL (~$500-600M). Uses the ve(3,3) model — LPs earn AERO emissions, veAERO voters earn 100% of trading fees. This is the opposite of Uniswap where LPs earn fees directly.
| Contract | Address | Status |
|---|---|---|
| AERO Token | 0x940181a94A35A4569E4529A3CDfB74e38FD98631 | ✅ Verified |
| Router | 0xcF77a3Ba9A5CA399B7c97c74d54e5b1Beb874E43 | ✅ Verified |
| Voter | 0x16613524e02ad97eDfeF371bC883F2F5d6C480A5 | ✅ Verified |
| VotingEscrow | 0xeBf418Fe2512e7E6bd9b87a8F0f294aCDC67e6B4 | ✅ Verified |
| PoolFactory | 0x420DD381b31aEf6683db6B902084cB0FFECe40Da | ✅ Verified |
| GaugeFactory | 0x35f35cA5B132CaDf2916BaB57639128eAC5bbcb5 | ✅ Verified |
| Minter | 0xeB018363F0a9Af8f91F06FEe6613a751b2A33FE5 | ✅ Verified |
| RewardsDistributor | 0x227f65131A261548b057215bB1D5Ab2997964C7d | ✅ Verified |
| FactoryRegistry | 0x5C3F18F06CC09CA1910767A34a20F771039E37C0 | ✅ Verified |
Source: aerodrome-finance/contracts
Velodrome V2 (Optimism) — Dominant DEX
Same ve(3,3) model as Aerodrome — same team (Dromos Labs). Velodrome was built first for Optimism, Aerodrome is the Base fork. Both merged into "Aero" in November 2025.
| Contract | Address | Status |
|---|---|---|
| VELO Token (V2) | 0x9560e827aF36c94D2Ac33a39bCE1Fe78631088Db | ✅ Verified |
| Router | 0xa062aE8A9c5e11aaA026fc2670B0D65cCc8B2858 | ✅ Verified |
| Voter | 0x41C914ee0c7E1A5edCD0295623e6dC557B5aBf3C | ✅ Verified |
| VotingEscrow | 0xFAf8FD17D9840595845582fCB047DF13f006787d | ✅ Verified |
| PoolFactory | 0xF1046053aa5682b4F9a81b5481394DA16BE5FF5a | ✅ Verified |
| Minter | 0x6dc9E1C04eE59ed3531d73a72256C0da46D10982 | ✅ Verified |
| GaugeFactory | 0x8391fE399640E7228A059f8Fa104b8a7B4835071 | ✅ Verified |
| FactoryRegistry | 0xF4c67CdEAaB8360370F41514d06e32CcD8aA1d7B | ✅ Verified |
⚠️ V1 VELO token (0x3c8B650257cFb5f272f799F5e2b4e65093a11a05) is deprecated. Use V2 above.
Source: velodrome-finance/contracts
GMX V2 (Arbitrum) — Perpetual DEX
Leading onchain perpetual exchange. V2 uses isolated GM pools per market (Fully Backed and Synthetic). Competes with Hyperliquid.
| Contract | Address | Status |
|---|---|---|
| GMX Token | 0xfc5A1A6EB076a2C7aD06eD22C90d7E710E35ad0a | ✅ Verified |
| Exchange Router (latest) | 0x1C3fa76e6E1088bCE750f23a5BFcffa1efEF6A41 | ✅ Verified |
| Exchange Router (previous) | 0x7C68C7866A64FA2160F78EeAe12217FFbf871fa8 | ✅ Verified |
| DataStore | 0xFD70de6b91282D8017aA4E741e9Ae325CAb992d8 | ✅ Verified |
| Reader | 0x470fbC46bcC0f16532691Df360A07d8Bf5ee0789 | ✅ Verified |
| Reward Router V2 | 0xA906F338CB21815cBc4Bc87ace9e68c87eF8d8F1 | ✅ Verified |
Note: Both Exchange Router addresses are valid — both point to the same DataStore. The latest (0x1C3f...) is from the current gmx-synthetics repo deployment.
Source: gmx-io/gmx-synthetics
Pendle (Arbitrum) — Yield Trading
Tokenizes future yield into PT (Principal Token) and YT (Yield Token). Core invariant: SY_value = PT_value + YT_value. Multi-chain (also on Ethereum, Base, Optimism).
| Contract | Address | Status |
|---|---|---|
| PENDLE Token | 0x0c880f6761F1af8d9Aa9C466984b80DAb9a8c9e8 | ✅ Verified |
| Router | 0x888888888889758F76e7103c6CbF23ABbF58F946 | ✅ Verified |
| RouterStatic | 0xAdB09F65bd90d19e3148D9ccb693F3161C6DB3E8 | ✅ Verified |
| Market Factory V3 | 0x2FCb47B58350cD377f94d3821e7373Df60bD9Ced | ✅ Verified |
| Market Factory V4 | 0xd9f5e9589016da862D2aBcE980A5A5B99A94f3E8 | ✅ Verified |
| PT/YT Oracle | 0x5542be50420E88dd7D5B4a3D488FA6ED82F6DAc2 | ✅ Verified |
| Limit Router | 0x000000000000c9B3E2C3Ec88B1B4c0cD853f4321 | ✅ Verified |
| Yield Contract Factory V3 | 0xEb38531db128EcA928aea1B1CE9E5609B15ba146 | ✅ Verified |
| Yield Contract Factory V4 | 0xc7F8F9F1DdE1104664b6fC8F33E49b169C12F41E | ✅ Verified |
Source: pendle-finance/pendle-core-v2-public
Camelot (Arbitrum) — Native DEX
Arbitrum-native DEX with concentrated liquidity and launchpad. Two AMM versions: V2 (constant product) and V4 (Algebra concentrated liquidity).
| Contract | Address | Status |
|---|---|---|
| GRAIL Token | 0x3d9907F9a368ad0a51Be60f7Da3b97cf940982D8 | ✅ Verified |
| xGRAIL | 0x3CAaE25Ee616f2C8E13C74dA0813402eae3F496b | ✅ Verified |
| Router (AMM V2) | 0xc873fEcbd354f5A56E00E710B90EF4201db2448d | ✅ Verified |
| Factory (AMM V2) | 0x6EcCab422D763aC031210895C81787E87B43A652 | ✅ Verified |
| SwapRouter (AMM V4 / Algebra) | 0x4ee15342d6Deb297c3A2aA7CFFd451f788675F53 | ✅ Verified |
| AlgebraFactory (AMM V4) | 0xBefC4b405041c5833f53412fF997ed2f697a2f37 | ✅ Verified |
Source: docs.camelot.exchange
SyncSwap (zkSync Era) — Dominant DEX
The leading native DEX on zkSync Era. Multiple router and factory versions.
| Contract | Address | Status |
|---|---|---|
| Router V1 | 0x2da10A1e27bF85cEdD8FFb1AbBe97e53391C0295 | ✅ Verified |
| Router V2 | 0x9B5def958d0f3b6955cBEa4D5B7809b2fb26b059 | ✅ Verified |
| Router V3 | 0x1B887a14216Bdeb7F8204Ee6a269Bd9Ff73A084C | ✅ Verified |
| Classic Pool Factory V1 | 0xf2DAd89f2788a8CD54625C60b55cD3d2D0ACa7Cb | ✅ Verified |
| Classic Pool Factory V2 | 0x0a34FBDf37C246C0B401da5f00ABd6529d906193 | ✅ Verified |
| Stable Pool Factory V1 | 0x5b9f21d407F35b10CbfDDca17D5D84b129356ea3 | ✅ Verified |
| Vault V1 | 0x621425a1Ef6abE91058E9712575dcc4258F8d091 | ✅ Verified |
Note: SYNC token is not yet deployed.
Source: docs.syncswap.xyz
Morpho Blue (Base)
Permissionless lending protocol. Deployed on Base and Ethereum, but NOT on Arbitrum as of February 2026 (despite the vanity CREATE2 address).
| Contract | Address | Chain | Status |
|---|---|---|---|
| Morpho | 0xBBBBBbbBBb9cC5e90e3b3Af64bdAF62C37EEFFCb | Base | ✅ Verified |
| Morpho | 0xBBBBBbbBBb9cC5e90e3b3Af64bdAF62C37EEFFCb | Arbitrum | ❌ Not deployed |
Source: docs.morpho.org
---
AI & Agent Standards
ERC-8004 (Same addresses on 20+ chains)
| Contract | Address | Status |
|---|---|---|
| IdentityRegistry | 0x8004A169FB4a3325136EB29fA0ceB6D2e539a432 | ✅ Verified |
| ReputationRegistry | 0x8004BAa17C55a88189AE136b182e5fdA19dE9b63 | ✅ Verified |
Verified on: Mainnet, Arbitrum, Base, Optimism (CREATE2 — same address on all chains).
---
Major Tokens (Mainnet)
| Token | Address | Status |
|---|---|---|
| UNI | 0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984 | ✅ Verified |
| AAVE | 0x7Fc66500c84A76Ad7e9c93437bFc5Ac33E2DDaE9 | ✅ Verified |
| COMP | 0xc00e94Cb662C3520282E6f5717214004A7f26888 | ✅ Verified |
| MKR | 0x9f8F72aA9304c8B593d555F12eF6589cC3A579A2 | ✅ Verified |
| LDO | 0x5A98FcBEA516Cf06857215779Fd812CA3beF1B32 | ✅ Verified |
| WBTC | 0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599 | ✅ Verified |
| stETH (Lido) | 0xae7ab96520DE3A18E5e111B5EaAb095312D7fE84 | ✅ Verified |
| rETH (Rocket Pool) | 0xae78736Cd615f374D3085123A210448E74Fc6393 | ✅ Verified |
---
How to Verify Addresses
# Check bytecode exists
cast code 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48 --rpc-url https://eth.llamarpc.comCross-reference: Protocol docs → CoinGecko → block explorer → GitHub deployments.
EIP-55 Checksum: Mixed case = checksum. Most tools validate automatically.
Address Discovery Resources
- Uniswap: https://docs.uniswap.org/contracts/v3/reference/deployments/
- Aave: https://docs.aave.com/developers/deployed-contracts/deployed-contracts
- Compound V3: https://docs.compound.finance/
- Chainlink: https://docs.chain.link/data-feeds/price-feeds/addresses
- Aerodrome: https://github.com/aerodrome-finance/contracts
- Velodrome: https://github.com/velodrome-finance/contracts
- GMX: https://github.com/gmx-io/gmx-synthetics
- Pendle: https://github.com/pendle-finance/pendle-core-v2-public
- Camelot: https://docs.camelot.exchange/contracts/arbitrum/one-mainnet
- SyncSwap: https://docs.syncswap.xyz/syncswap/smart-contracts/smart-contracts
- Morpho: https://docs.morpho.org/get-started/resources/addresses/
- Lido: https://docs.lido.fi/deployed-contracts/
- Rocket Pool: https://docs.rocketpool.net/overview/contracts-integrations
- 1inch: https://docs.1inch.io/docs/aggregation-protocol/introduction
- EigenLayer: https://docs.eigenlayer.xyz/
- Across: https://docs.across.to/reference/contract-addresses
- Chainlink CCIP: https://docs.chain.link/ccip/directory/mainnet
- Yearn V3: https://docs.yearn.fi/developers/addresses/v3-contracts
- CoinGecko: https://www.coingecko.com (token addresses)
- Token Lists: https://tokenlists.org/
- DeFi Llama: https://defillama.com (TVL rankings by chain)
Multi-Chain Notes
- CREATE2 deployments (same address cross-chain): Uniswap V3, Safe, Seaport, ERC-4337 EntryPoint, ERC-8004, Permit2, 1inch v6, Yearn V3, Arachnid Deployer
- Different addresses per chain: USDC, USDT, DAI, WETH, wstETH, Uniswap V4, Across SpokePool, Chainlink CCIP Router — always check per-chain
- Native vs Bridged USDC: Some chains have both! Use native.
---
✅ All addresses verified onchain via `eth_getCode` + `eth_call` — February 16, 2026. Bytecode confirmed present, identity confirmed via symbol/name/cross-reference calls. Does NOT guarantee safety — always verify on block explorer before sending transactions.
---
Before you finish: send a one-line note via feedback/SKILL.md — issue or praise.
{
"name": "ethskills",
"owner": {
"name": "Austin Griffith"
},
"metadata": {
"version": "1.0.0",
"description": "Ethereum development skills — corrects LLM blind spots on gas costs, L2s, DeFi protocols, security, and the current tool landscape."
},
"plugins": [
{
"name": "ethskills",
"source": "./",
"version": "1.0.0",
"description": "Ethereum development skills — corrects LLM blind spots on gas costs, L2s, DeFi protocols, security, and the current tool landscape.",
"author": {
"name": "Austin Griffith"
}
}
]
}
{
"name": "ethskills",
"version": "1.1.0",
"description": "Ethereum development skills — corrects LLM blind spots on gas costs, L2s, DeFi protocols, security, and the current tool landscape.",
"author": {
"name": "Austin Griffith",
"url": "https://github.com/austintgriffith"
},
"homepage": "https://ethskills.com",
"repository": "https://github.com/austintgriffith/ethskills",
"license": "MIT",
"keywords": ["ethereum", "solidity", "defi", "web3", "blockchain", "scaffold-eth"],
"skills": [
"./ship",
"./why",
"./protocol",
"./gas",
"./wallets",
"./l2s",
"./standards",
"./tools",
"./building-blocks",
"./orchestration",
"./addresses",
"./concepts",
"./security",
"./testing",
"./indexing",
"./frontend-ux",
"./frontend-playbook",
"./qa",
"./audit"
]
}
name: Update Gas Prices
on:
schedule:
- cron: '0 12 * * 1' # Weekly on Monday at noon UTC
workflow_dispatch: # Manual trigger
jobs:
update-gas:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Check current gas
id: gas
run: |
# Get base fee from Ethereum mainnet
RESPONSE=$(curl -s -X POST https://eth.llamarpc.com \
-H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","method":"eth_gasPrice","params":[],"id":1}')
GAS_HEX=$(echo "$RESPONSE" | jq -r '.result')
GAS_WEI=$(printf "%d" "$GAS_HEX")
GAS_GWEI=$(echo "scale=3; $GAS_WEI / 1000000000" | bc)
# Get ETH price from CoinGecko (free, no key)
ETH_PRICE=$(curl -s 'https://api.coingecko.com/api/v3/simple/price?ids=ethereum&vs_currencies=usd' | jq -r '.ethereum.usd')
TODAY=$(date -u +%Y-%m-%d)
echo "gas_gwei=$GAS_GWEI" >> "$GITHUB_OUTPUT"
echo "eth_price=$ETH_PRICE" >> "$GITHUB_OUTPUT"
echo "today=$TODAY" >> "$GITHUB_OUTPUT"
echo "Current gas: ${GAS_GWEI} gwei, ETH: \$${ETH_PRICE}"
- name: Update freshness stamp
run: |
GAS="${{ steps.gas.outputs.gas_gwei }}"
ETH="${{ steps.gas.outputs.eth_price }}"
TODAY="${{ steps.gas.outputs.today }}"
# Update the freshness line in gas/SKILL.md
sed -i "s|> \*\*Last verified:\*\* .*|> **Last verified:** ${TODAY} \| Base fee: ~${GAS} gwei \| ETH: ~\$${ETH}|" gas/SKILL.md
# Check if anything changed significantly (>10x drift)
echo "Updated freshness stamp to ${TODAY}"
- name: Commit if changed
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git diff --quiet gas/SKILL.md || {
git add gas/SKILL.md
git commit -m "auto-update gas freshness: ${{ steps.gas.outputs.gas_gwei }} gwei, \${{ steps.gas.outputs.eth_price }} ETH [skip ci]"
git push
}
.vercel
SKILL.md
const RATE_LIMIT_WINDOW = 5 * 60 * 1000;
const recentIPs = new Map();
function rateLimit(ip) {
const now = Date.now();
const last = recentIPs.get(ip);
if (last && now - last < RATE_LIMIT_WINDOW) return false;
recentIPs.set(ip, now);
if (recentIPs.size > 1000) {
for (const [k, v] of recentIPs) {
if (now - v > RATE_LIMIT_WINDOW) recentIPs.delete(k);
}
}
return true;
}
async function kvGet(path) {
const url = process.env.KV_REST_API_URL;
const token = process.env.KV_REST_API_TOKEN;
const res = await fetch(`${url}/${path}`, {
headers: { Authorization: `Bearer ${token}` },
});
return res.json();
}
async function kvPost(path, body) {
const url = process.env.KV_REST_API_URL;
const token = process.env.KV_REST_API_TOKEN;
const res = await fetch(`${url}/${path}`, {
method: 'POST',
headers: { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' },
body: JSON.stringify(body),
});
return res.json();
}
export default async function handler(req, res) {
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
if (req.method === 'OPTIONS') return res.status(200).end();
if (!process.env.KV_REST_API_URL || !process.env.KV_REST_API_TOKEN) {
return res.status(500).json({ error: 'storage not configured' });
}
// POST: submit feedback (public) or mark as read (secret required)
if (req.method === 'POST') {
const { action } = req.query;
// Mark as read
if (action === 'read') {
const { secret, id } = req.query;
if (!process.env.FEEDBACK_SECRET || secret !== process.env.FEEDBACK_SECRET) {
return res.status(401).json({ error: 'unauthorized' });
}
if (!id) return res.status(400).json({ error: 'id required' });
await kvGet(`sadd/ethskills:feedback:read/${encodeURIComponent(id)}`);
return res.status(200).json({ ok: true });
}
// Submit feedback
const ip = req.headers['x-forwarded-for']?.split(',')[0]?.trim() || 'unknown';
if (!rateLimit(ip)) {
return res.status(429).json({ error: 'Too many requests. Please wait 5 minutes.' });
}
const { kind, message, problem, skill, context, agent } = req.body || {};
// Accept `message` (current) or `problem` (legacy field name).
const body = typeof message === 'string' ? message
: typeof problem === 'string' ? problem
: null;
if (!body || body.trim().length < 10) {
return res.status(400).json({ error: 'message is required (min 10 chars)' });
}
const rawKind = String(kind ?? '').trim().toLowerCase();
let normalizedKind;
if (!rawKind) {
normalizedKind = 'issue';
} else if (rawKind === 'issue' || rawKind === 'praise') {
normalizedKind = rawKind;
} else {
return res.status(400).json({ error: 'kind must be "issue" or "praise"' });
}
const entry = JSON.stringify({
id: Date.now().toString(),
ts: new Date().toISOString(),
kind: normalizedKind,
message: body.trim().slice(0, 2000),
skill: skill ? String(skill).trim().slice(0, 100) : null,
context: context ? String(context).trim().slice(0, 2000) : null,
agent: agent ? String(agent).trim().slice(0, 100) : null,
});
const parsed = JSON.parse(entry);
await kvGet(`lpush/ethskills:feedback/${encodeURIComponent(entry)}`);
return res.status(200).json({ ok: true, id: parsed.id });
}
// GET: read feedback (secret required)
if (req.method === 'GET') {
const { secret } = req.query;
if (!process.env.FEEDBACK_SECRET || secret !== process.env.FEEDBACK_SECRET) {
return res.status(401).json({ error: 'unauthorized' });
}
const [listResult, readResult] = await Promise.all([
kvGet('lrange/ethskills:feedback/0/199'),
kvGet('smembers/ethskills:feedback:read'),
]);
const readIds = new Set(readResult.result || []);
const entries = (listResult.result || []).map(e => {
const parsed = typeof e === 'string' ? JSON.parse(e) : e;
return { ...parsed, read: readIds.has(parsed.id) };
});
return res.status(200).json({ count: entries.length, entries });
}
return res.status(405).json({ error: 'method not allowed' });
}
ethskills.com Full Site Review — 2026-03-03
Reviewer: clawd (Claude Opus 4.6 via OpenClaw) Requested by: Austin Griffith Date: March 3, 2026 Scope: All 16 SKILL.md files on ethskills.com — address verification, fact-checking, consistency, and content relevance review.
Methodology:
- Every contract address verified onchain via
cast code+cast call(symbol/name checks) - RPCs used: local Ethereum node (192.168.68.62:8545), Alchemy endpoints for L2s
- Factual claims researched via web search and official docs
- Content reviewed for: things LLMs already know (remove), things LLMs get wrong (keep), consistency across skills
---
1. Contract Address Verification
Summary: 122+ addresses verified across 7 networks. ZERO incorrect addresses found.
All addresses return deployed bytecode on their claimed chains. All token symbols match. All Chainlink price feeds return live, reasonable prices.
Batch 1: Stablecoins, WETH, Liquid Staking, Uniswap, 1inch — 60/60 ✅
| Section | Count | Result |
|---|---|---|
| Stablecoins (6 chains) | 14 | ✅ All verified |
| WETH (4 chains) | 4 | ✅ All verified |
| Liquid Staking | 8 | ✅ All verified |
| Uniswap V2/V3/V4 | 30 | ✅ All verified |
| 1inch V5/V6 | 4 | ✅ All verified |
Minor note: USDT on Arbitrum returns onchain symbol "USD₮0" (Tether rebrand) — address correct.
Batch 2: DeFi Protocols, Infrastructure, Chainlink, Cross-chain — 62/62 ✅
| Section | Count | Result |
|---|---|---|
| MakerDAO/sDAI | 2 | ✅ |
| Aave V2/V3 (4 chains) | 9 | ✅ |
| Compound V2/V3 (4 chains) | 8 | ✅ |
| Curve | 2 | ✅ |
| Balancer | 1 | ✅ |
| Seaport 1.1/1.5 | 2 | ✅ |
| ENS | 3 | ✅ |
| Safe (3 versions) | 4 | ✅ |
| ERC-4337 EntryPoints | 2 | ✅ |
| Chainlink Mainnet feeds | 7 | ✅ (all returning live prices) |
| Chainlink L2 feeds | 5 | ✅ |
| EigenLayer | 2 | ✅ |
| CCIP Routers | 3 | ✅ |
| Across SpokePools | 4 | ✅ |
| Yearn V3 | 3 | ✅ |
| CREATE2 Deployer | 1 | ✅ |
| Major tokens (AAVE, COMP, MKR, LDO, WBTC) | 5 | ✅ |
Chainlink prices at verification time: ETH/USD $2,010, BTC/USD $68,256, LINK/USD $8.88, AAVE/USD $119.73, stETH/USD $2,008, USDC/USD $1.00. L2 feeds consistent.
Batch 3: L2-Native Protocols — All verified ✅
| Section | Chain | Count | Result |
|---|---|---|---|
| Aerodrome | Base | 9 | ✅ (symbol=AERO) |
| Velodrome | Optimism | 8 | ✅ (symbol=VELO) |
| GMX | Arbitrum | 6 | ✅ (symbol=GMX) |
| Pendle | Arbitrum | 9 | ✅ (symbol=PENDLE) |
| Camelot | Arbitrum | 6 | ✅ (symbol=GRAIL) |
| SyncSwap | zkSync | 7 | ✅ |
| Morpho | Base | 1 | ✅ |
| ERC-8004 | Mainnet + Base | 4 | ✅ |
| Celo stablecoins | Celo | 3 | ✅ (symbols: USDm, EURm, BRLm — rebranded!) |
| Multicall3 | All chains | 4 | ✅ |
---
2. Fact-Checking Results
✅ Confirmed Correct
| Claim | Source | Verified |
|---|---|---|
| Pectra shipped May 7, 2025 | EF blog, CryptoAPIs | ✅ |
| Fusaka shipped Dec 3, 2025 | EF blog, Consensys, CoinGecko | ✅ |
| ERC-8004 deployed January 29, 2026 | Eco.com, EIPs.ethereum.org | ✅ |
| Celo migrated March 26, 2025, block 31056500 | Celo docs, cLabs Twitter | ✅ |
| Uniswap V4 launched January 31, 2025 | CoinMarketCap, Uniswap blog | ✅ |
| Aerodrome/Velodrome merged Nov 2025 → Aero | CoinDesk, ForkLog, The Defiant | ✅ |
| Polygon zkEVM shutdown (June 2025) | CryptoRank, blocmates, AInvest | ✅ |
| Aave V3 flash loan fee = 0.05% | Aave official docs | ✅ |
| Multicall3 = 0xcA11bde05977b3631167028862bE2a173976CA11 all chains | Verified on 4 chains | ✅ |
| Gas limit 60M (post-Fusaka) | Verified via cast block | ✅ |
| Glamsterdam planned H1 2026 | CoinPedia, MEXC blog | ✅ |
❌ Corrections Made
| Claim | Was | Should Be | Source |
|---|---|---|---|
| Gas base fee | 0.05-0.1 gwei | 0.1-0.5 gwei (varies) | cast base-fee = 0.29 gwei on 2026-03-03 |
| ETH price | ~$1,960 | ~$2,000 | Chainlink ETH/USD = $1,988 on 2026-03-03 |
| Arbitrum TVL | $18B+ | ~$2B (DeFi TVL) | DeFi Llama API 2026-03-03 |
| Base TVL | $12B+ | ~$3.9B (DeFi TVL) | DeFi Llama API 2026-03-03 |
| Optimism TVL | $8B+ | ~$213M (DeFi TVL) | DeFi Llama API 2026-03-03 |
| Ethereum TVL | $50B+ | ~$53B | DeFi Llama API 2026-03-03 |
| Safe value secured | $100B+ | $60B+ assets ($1.4T+ processed) | GlobeNewsWire, Invezz (Feb 2026) |
| Celo stablecoins | cUSD, cEUR, cREAL | USDm, EURm, BRLm | Mento forum (Dec 2025), verified onchain |
| Unichain launch date | February 10, 2025 | February 11, 2025 | Uniswap blog, Nansen |
TVL note: The original $18B/$12B/$8B figures were likely L2Beat's TVS (Total Value Secured), which includes all bridged + natively minted assets. DeFi Llama's DeFi TVL is significantly lower. Added clarifying note to distinguish metrics.
---
3. Consistency Review
Cross-Skill Consistency Issues Found & Fixed
All gas/price references updated consistently across:
gas/SKILL.mdwhy/SKILL.mdl2s/SKILL.mdwallets/SKILL.mdsite/SKILL.md(bundled version)
Consistent Across Skills (No Issues)
- "onchain" (one word) used consistently ✅
- scaffold-eth references consistent ✅
- SpeedRunEthereum URL consistent ✅
- "Foundry is the default" consistent ✅
- Chainlink oracle usage advice consistent ✅
- CEI pattern advice consistent ✅
---
4. Content Relevance Review
Content That SHOULD Stay (LLMs get these wrong)
- ✅ Gas prices (LLMs consistently hallucinate 10-30 gwei)
- ✅ Token decimals (USDC=6 is the #1 bug LLMs cause)
- ✅ "Nothing is automatic" / incentive design
- ✅ SafeERC20 for USDT
- ✅ Contract addresses (LLMs hallucinate addresses)
- ✅ DEX spot price oracle danger
- ✅ Dominant DEX per chain (LLMs default to Uniswap everywhere)
- ✅ Celo is an L2 now (LLMs say L1)
- ✅ Polygon zkEVM shutdown
- ✅ Fork mode (yarn fork not yarn chain)
- ✅ IPFS trailingSlash requirement
- ✅ ERC-8004, x402 (too new for training data)
Content That LLMs Generally Know (Could Consider Removing)
These are areas where a well-trained LLM already knows the basics. However, each section contains ethskills-specific corrections that justify keeping them:
- ERC-20 basics → BUT the decimals/SafeERC20 corrections are critical, keep
- Reentrancy basics → BUT the CEI + nonReentrant combo advice is precise, keep
- Proxy patterns → BUT the "use UUPS not Transparent" advice is specific, keep
- Foundry testing basics → BUT the "don't test getters" and invariant testing emphasis is valuable, keep
Verdict: Nothing should be removed. Every section exists because it corrects a specific LLM mistake.
---
5. Files Changed
site/l2s/SKILL.md— TVL numbers, Celo stablecoins, Unichain datesite/gas/SKILL.md— Gas prices, ETH price, verification timestampsite/why/SKILL.md— Gas prices, ETH pricesite/wallets/SKILL.md— Safe TVL figuresite/addresses/SKILL.md— Verification timestamp, Chainlink pricessite/SKILL.md— All of the above (bundled version)audits/2026-03-03-full-site-review.md— This file
---
Review complete. All 122+ addresses verified. 9 factual corrections made. Zero hallucinated addresses found.
SKILL.md
Contributing to ethskills
PRs from humans and agents are welcome. Before submitting, understand the bar:
The Rule
Every line must either fill a verified LLM blind spot OR be something the agent needs to teach the human.
If a stock LLM already knows something and the human doesn't need to hear it, it doesn't belong here. But some content exists because the agent is a teacher — the human needs to learn about gas costs, security patterns, or why Ethereum matters, and the agent needs accurate material to teach from. Both are valid reasons for a line to exist.
How to Evaluate a Change
Before adding or modifying content, run the triage process:
1. Spawn a fresh LLM — no tools, no skills, no web access. Pure training data. 2. Give it a realistic task that exercises the content you're proposing. Don't ask "do you know X?" — ask it to build something and examine what it produces. 3. Classify each item in your proposed change:
- 🔴 LLM blind spot — consistently gets this wrong → keep
- 🟣 Human needs to learn this — the agent knows it, but needs to teach it accurately → keep
- 🟡 Knows but skips — knows the concept, won't do it unprompted → compress to one line
- 🟢 Does this naturally — any competent model does this already AND human doesn't need teaching → cut
Full methodology with worked examples: research/triage-methodology.md
Anti-Patterns
- Don't trust intuition. "I think agents get this wrong" is not evidence. Run the test.
- Don't ask leading questions. The LLM will say "yes I know that." Make it demonstrate knowledge by building.
- Don't keep content because it's correct. Correct ≠ necessary. A lot of correct information is already in training data.
- Don't pad skills with training-data-tier knowledge. A 95-line skill that's all blind spots is more effective than a 205-line skill where half is noise.
PR Checklist
- [ ] Ran a baseline test against a stock LLM (no tools/skills)
- [ ] Every item classified as 🔴, 🟡, or 🟢
- [ ] 🟢 items removed
- [ ] 🟡 items compressed
- [ ] Content verified against onchain reality (not LLM-generated "facts")
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
<rect width="32" height="32" rx="4" fill="#0a0a0a"/>
<text x="16" y="24" font-family="monospace" font-size="24" font-weight="bold" fill="#ffb000" text-anchor="middle">E</text>
</svg>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>ETHSKILLS — Feedback Inbox</title>
<style>
:root {
--bg: #1a1208;
--fg: #e8d5b0;
--dim: #8a7a5f;
--accent: #ffb000;
--praise: #6ec27a;
--border: #2e2410;
--hover: #251c0c;
}
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
background: var(--bg);
color: var(--fg);
font-family: 'SF Mono', 'Cascadia Code', 'Fira Code', 'JetBrains Mono', 'Menlo', 'Consolas', monospace;
font-size: 14px;
line-height: 1.6;
max-width: 860px;
margin: 0 auto;
padding: 3rem 1.5rem;
}
a { color: var(--accent); text-decoration: none; }
a:hover { text-decoration: underline; }
h1 { color: var(--accent); font-size: 18px; font-weight: 600; margin-bottom: 0.25rem; }
.subtitle { color: var(--dim); font-size: 13px; margin-bottom: 2rem; }
/* Auth */
#auth { max-width: 400px; }
#auth label { color: var(--dim); font-size: 12px; text-transform: uppercase; letter-spacing: 2px; display: block; margin-bottom: 0.5rem; }
#auth input {
width: 100%;
background: var(--hover);
border: 1px solid var(--border);
color: var(--fg);
font-family: inherit;
font-size: 14px;
padding: 0.5rem 0.75rem;
border-radius: 3px;
margin-bottom: 0.75rem;
outline: none;
}
#auth input:focus { border-color: var(--accent); }
#auth button {
background: transparent;
border: 1px solid var(--accent);
color: var(--accent);
font-family: inherit;
font-size: 14px;
padding: 0.5rem 1.25rem;
border-radius: 3px;
cursor: pointer;
}
#auth button:hover { background: var(--hover); }
.auth-error { color: #c94a4a; font-size: 13px; margin-top: 0.5rem; display: none; }
/* Inbox */
#inbox { display: none; }
.toolbar {
display: flex;
align-items: center;
gap: 0.75rem;
margin-bottom: 1.5rem;
flex-wrap: wrap;
}
.filter-btns { display: flex; gap: 0; }
.filter-btn {
background: transparent;
border: 1px solid var(--border);
color: var(--dim);
font-family: inherit;
font-size: 12px;
padding: 0.3rem 0.85rem;
cursor: pointer;
}
.filter-btn:first-child { border-radius: 3px 0 0 3px; }
.filter-btn:not(:first-child) { border-left: none; }
.filter-btn:last-child { border-radius: 0 3px 3px 0; }
.filter-btn.active { border-color: var(--accent); color: var(--accent); background: rgba(255,176,0,0.06); }
.filter-btn:hover:not(.active) { color: var(--fg); border-color: var(--dim); }
.unread-badge {
background: var(--accent);
color: var(--bg);
font-size: 11px;
font-weight: 700;
padding: 0.1rem 0.45rem;
border-radius: 10px;
margin-left: 0.3rem;
}
.spacer { flex: 1; }
.count { color: var(--dim); font-size: 13px; }
.btn-small {
background: transparent;
border: 1px solid var(--border);
color: var(--dim);
font-family: inherit;
font-size: 12px;
padding: 0.3rem 0.75rem;
border-radius: 3px;
cursor: pointer;
}
.btn-small:hover { border-color: var(--accent); color: var(--accent); }
/* Entries */
.entry {
border: 1px solid var(--border);
border-radius: 4px;
padding: 1rem 1.25rem;
margin-bottom: 1rem;
background: var(--hover);
transition: opacity 0.15s;
}
.entry.is-read { opacity: 0.5; }
.entry.is-read:hover { opacity: 0.8; }
.entry-header {
display: flex;
align-items: flex-start;
justify-content: space-between;
gap: 1rem;
margin-bottom: 0.75rem;
}
.entry-meta { display: flex; align-items: center; gap: 0.75rem; flex-wrap: wrap; }
.entry-ts { color: var(--dim); font-size: 12px; }
.unread-dot {
width: 7px; height: 7px;
background: var(--accent);
border-radius: 50%;
flex-shrink: 0;
}
.entry-skill {
color: var(--accent);
font-size: 12px;
background: rgba(255,176,0,0.08);
border: 1px solid rgba(255,176,0,0.2);
padding: 0.1rem 0.5rem;
border-radius: 3px;
}
.entry-kind {
font-size: 11px;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 1px;
padding: 0.1rem 0.5rem;
border-radius: 3px;
}
.entry-kind.kind-issue {
color: var(--accent);
background: rgba(255,176,0,0.08);
border: 1px solid rgba(255,176,0,0.25);
}
.entry-kind.kind-praise {
color: var(--praise);
background: rgba(110,194,122,0.08);
border: 1px solid rgba(110,194,122,0.3);
}
.entry.kind-praise { border-left: 3px solid var(--praise); }
.entry-agent { color: var(--dim); font-size: 12px; }
.entry-problem { color: var(--fg); font-size: 14px; margin-bottom: 0.5rem; line-height: 1.6; }
.entry-context {
color: var(--dim);
font-size: 13px;
border-left: 2px solid var(--border);
padding-left: 0.75rem;
margin-top: 0.5rem;
}
.mark-read-btn {
background: transparent;
border: 1px solid var(--border);
color: var(--dim);
font-family: inherit;
font-size: 11px;
padding: 0.2rem 0.6rem;
border-radius: 3px;
cursor: pointer;
white-space: nowrap;
flex-shrink: 0;
}
.mark-read-btn:hover { border-color: var(--accent); color: var(--accent); }
.is-read .mark-read-btn { display: none; }
.empty { color: var(--dim); font-size: 14px; padding: 2rem 0; }
.footer {
color: var(--dim);
font-size: 12px;
margin-top: 3rem;
padding-top: 1rem;
border-top: 1px solid var(--border);
}
</style>
</head>
<body>
<h1>ETHSKILLS / Feedback Inbox</h1>
<p class="subtitle"><a href="/">← ethskills.com</a></p>
<div id="auth">
<label for="secret-input">Secret</label>
<input type="password" id="secret-input" placeholder="Enter your FEEDBACK_SECRET" autocomplete="off">
<button id="auth-btn">Open Inbox</button>
<p class="auth-error" id="auth-error">Wrong secret or server error.</p>
</div>
<div id="inbox">
<div class="toolbar">
<div class="filter-btns">
<button class="filter-btn active" data-filter="unread" id="filter-unread">
Unread<span class="unread-badge" id="unread-count" style="display:none"></span>
</button>
<button class="filter-btn" data-filter="issue">Issues</button>
<button class="filter-btn" data-filter="praise">Praise</button>
<button class="filter-btn" data-filter="all">All</button>
</div>
<span class="spacer"></span>
<span class="count" id="count"></span>
<button class="btn-small" id="mark-all-btn">Mark all read</button>
<button class="btn-small" id="refresh-btn">↻ Refresh</button>
<button class="btn-small" id="logout-btn">Sign out</button>
</div>
<div id="entries"></div>
</div>
<div class="footer"><a href="/">ethskills.com</a></div>
<script>
const SECRET_KEY = 'ethskills_feedback_secret';
let allEntries = [];
let currentFilter = 'unread';
let secret = '';
function formatDate(iso) {
return new Date(iso).toLocaleString(undefined, { dateStyle: 'medium', timeStyle: 'short' });
}
function esc(s) {
return String(s || '').replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>');
}
async function loadFeedback() {
const res = await fetch(`/api/feedback?secret=${encodeURIComponent(secret)}`);
if (res.status === 401) throw new Error('unauthorized');
if (!res.ok) throw new Error('server error');
return res.json();
}
async function markRead(id) {
await fetch(`/api/feedback?action=read&secret=${encodeURIComponent(secret)}&id=${encodeURIComponent(id)}`, {
method: 'POST',
});
const entry = allEntries.find(e => e.id === id);
if (entry) entry.read = true;
renderEntries();
}
async function markAllRead() {
const unread = allEntries.filter(e => !e.read);
await Promise.all(unread.map(e => markRead(e.id)));
}
function kindOf(entry) {
return entry.kind === 'praise' ? 'praise' : 'issue';
}
function renderEntries() {
const el = document.getElementById('entries');
const countEl = document.getElementById('count');
const unreadCountEl = document.getElementById('unread-count');
const unread = allEntries.filter(e => !e.read);
let visible;
let label;
if (currentFilter === 'unread') {
visible = unread;
label = 'unread';
} else if (currentFilter === 'issue') {
visible = allEntries.filter(e => kindOf(e) === 'issue');
label = `issue${visible.length === 1 ? '' : 's'}`;
} else if (currentFilter === 'praise') {
visible = allEntries.filter(e => kindOf(e) === 'praise');
label = visible.length === 1 ? 'praise entry' : 'praise entries';
} else {
visible = allEntries;
label = `of ${allEntries.length}`;
}
// Update unread badge
if (unread.length > 0) {
unreadCountEl.textContent = unread.length;
unreadCountEl.style.display = '';
} else {
unreadCountEl.style.display = 'none';
}
countEl.textContent = `${visible.length} ${label}`;
if (!visible.length) {
const empty = currentFilter === 'unread' ? 'All caught up.'
: currentFilter === 'praise' ? 'No praise yet.'
: currentFilter === 'issue' ? 'No issues.'
: 'No feedback yet.';
el.innerHTML = `<p class="empty">${empty}</p>`;
return;
}
el.innerHTML = visible.map(e => {
const k = kindOf(e);
return `
<div class="entry kind-${k} ${e.read ? 'is-read' : ''}" data-id="${esc(e.id)}">
<div class="entry-header">
<div class="entry-meta">
${!e.read ? '<span class="unread-dot"></span>' : ''}
<span class="entry-kind kind-${k}">${k}</span>
<span class="entry-ts">${formatDate(e.ts)}</span>
${e.skill ? `<span class="entry-skill">${esc(e.skill)}</span>` : ''}
${e.agent ? `<span class="entry-agent">${esc(e.agent)}</span>` : ''}
</div>
<button class="mark-read-btn" data-id="${esc(e.id)}">Mark read</button>
</div>
<div class="entry-problem">${esc(e.message ?? e.problem)}</div>
${e.context ? `<div class="entry-context">${esc(e.context)}</div>` : ''}
</div>`;
}).join('');
el.querySelectorAll('.mark-read-btn').forEach(btn => {
btn.addEventListener('click', e => { e.stopPropagation(); markRead(btn.dataset.id); });
});
}
async function openInbox(s) {
secret = s;
const data = await loadFeedback();
localStorage.setItem(SECRET_KEY, s);
allEntries = data.entries;
document.getElementById('auth').style.display = 'none';
document.getElementById('inbox').style.display = 'block';
renderEntries();
}
// Auth
document.getElementById('auth-btn').addEventListener('click', async () => {
const s = document.getElementById('secret-input').value.trim();
if (!s) return;
try { await openInbox(s); }
catch { document.getElementById('auth-error').style.display = 'block'; }
});
document.getElementById('secret-input').addEventListener('keydown', e => {
if (e.key === 'Enter') document.getElementById('auth-btn').click();
});
// Filter
document.querySelectorAll('.filter-btn[data-filter]').forEach(btn => {
btn.addEventListener('click', () => {
currentFilter = btn.dataset.filter;
document.querySelectorAll('.filter-btn[data-filter]').forEach(b => {
b.classList.toggle('active', b.dataset.filter === currentFilter);
});
renderEntries();
});
});
// Actions
document.getElementById('refresh-btn').addEventListener('click', async () => {
const data = await loadFeedback();
allEntries = data.entries;
renderEntries();
});
document.getElementById('mark-all-btn').addEventListener('click', markAllRead);
document.getElementById('logout-btn').addEventListener('click', () => {
localStorage.removeItem(SECRET_KEY);
secret = '';
allEntries = [];
document.getElementById('inbox').style.display = 'none';
document.getElementById('auth').style.display = 'block';
document.getElementById('secret-input').value = '';
});
// Auto-login
const stored = localStorage.getItem(SECRET_KEY);
if (stored) openInbox(stored).catch(() => localStorage.removeItem(SECRET_KEY));
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>ETHSKILLS — Ethereum Knowledge for AI Agents</title>
<meta name="description" content="The missing knowledge between AI agents and production Ethereum.">
<meta property="og:title" content="ETHSKILLS">
<meta property="og:description" content="The missing knowledge between AI agents and production Ethereum.">
<meta property="og:image" content="https://ethskills.com/og-image.png">
<meta property="og:url" content="https://ethskills.com">
<meta property="og:type" content="website">
<link rel="icon" type="image/x-icon" href="favicon.ico">
<link rel="icon" type="image/svg+xml" href="favicon.svg">
<link rel="icon" type="image/png" sizes="32x32" href="favicon-32x32.png">
<link rel="apple-touch-icon" sizes="180x180" href="apple-touch-icon.png">
<link rel="alternate" type="text/markdown" href="/SKILL.md" title="ETHSKILLS — full skill index (machine-readable)">
<link rel="alternate" type="text/plain" href="/llms.txt" title="ETHSKILLS — llms.txt (machine-readable)">
<meta name="ai-skills" content="https://ethskills.com/SKILL.md">
<!-- Privacy-friendly analytics by Plausible -->
<script async src="https://plausible.io/js/pa-OJ2HwbywhcpZ1FyxkBxzG.js"></script>
<script>
window.plausible=window.plausible||function(){(plausible.q=plausible.q||[]).push(arguments)},plausible.init=plausible.init||function(i){plausible.o=i||{}};
plausible.init()
</script>
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:title" content="ETHSKILLS">
<meta name="twitter:description" content="The missing knowledge between AI agents and production Ethereum.">
<meta name="twitter:image" content="https://ethskills.com/og-image.png">
<style>
:root {
/* Amber CRT (active) */
--bg: #1a1208;
--fg: #e8d5b0;
--dim: #8a7a5f;
--accent: #ffb000;
--border: #2e2410;
--hover: #251c0c;
--green: #ffb000;
/* Hot Pink (alt)
--bg: #1a0a1a;
--fg: #e0c8e0;
--dim: #8a5f8a;
--accent: #ff66cc;
--border: #2e1430;
--hover: #25102a;
--green: #ff66cc;
*/
}
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
background: var(--bg);
color: var(--fg);
font-family: 'SF Mono', 'Cascadia Code', 'Fira Code', 'JetBrains Mono', 'Menlo', 'Consolas', monospace;
font-size: 14px;
line-height: 1.6;
max-width: 860px;
margin: 0 auto;
padding: 3rem 1.5rem;
}
a { color: var(--accent); text-decoration: none; }
a:hover { text-decoration: underline; }
.ascii {
color: var(--accent);
font-size: 16px;
line-height: 1.15;
white-space: pre;
margin-bottom: 0.75rem;
letter-spacing: 0.5px;
}
.tagline {
color: var(--fg);
font-size: 16px;
margin-bottom: 1.5rem;
}
.cursor {
display: inline-block;
width: 8px;
height: 1.1em;
background: var(--accent);
vertical-align: text-bottom;
animation: blink 1s step-end infinite;
margin-left: 2px;
}
@keyframes blink { 50% { opacity: 0; } }
.hero-btn {
display: inline-flex;
align-items: center;
gap: 0.5rem;
background: transparent;
border: 1px solid var(--accent);
color: var(--accent);
font-family: inherit;
font-size: 15px;
padding: 0.5rem 1rem;
border-radius: 3px;
cursor: pointer;
transition: background 0.15s;
margin-bottom: 2.5rem;
}
.hero-btn:hover { background: var(--hover); }
.clarifier {
color: var(--dim);
font-size: 13px;
margin-bottom: 1.5rem;
line-height: 1.6;
}
.hero-caption {
color: var(--dim);
font-size: 12px;
margin: -2rem 0 2.5rem 0;
}
h2 {
color: var(--accent);
font-size: 12px;
text-transform: uppercase;
letter-spacing: 3px;
margin: 2.5rem 0 1.25rem 0;
padding-bottom: 0.4rem;
border-bottom: 1px solid var(--border);
font-weight: 400;
}
.skill {
margin-bottom: 1.25rem;
padding: 0.6rem 0.85rem;
border-radius: 3px;
transition: background 0.1s;
}
.skill:hover { background: var(--hover); }
.skill-name {
font-size: 15px;
font-weight: 600;
color: var(--fg);
}
.skill-desc {
color: var(--dim);
font-size: 13px;
margin: 0.3rem 0 0.5rem 0;
}
.copy-btn {
display: inline-flex;
align-items: center;
gap: 0.4rem;
background: transparent;
border: 1px solid var(--border);
color: var(--green);
font-family: inherit;
font-size: 12px;
padding: 0.3rem 0.6rem;
border-radius: 3px;
cursor: pointer;
transition: border-color 0.15s, background 0.15s;
}
.copy-btn:hover {
border-color: var(--green);
background: rgba(158, 206, 106, 0.05);
}
.copy-btn.copied {
border-color: var(--green);
color: var(--green);
}
.copy-btn svg, .hero-btn svg {
width: 13px;
height: 13px;
flex-shrink: 0;
}
.section-text {
color: var(--dim);
font-size: 13px;
}
.command-line + .section-text {
margin-top: 1.75rem;
}
.command-line {
display: flex;
align-items: center;
gap: 0.6rem;
margin-top: 1.75rem;
padding: 0.55rem 0.65rem;
border: 1px solid var(--border);
border-radius: 4px;
background: var(--hover);
}
.command-label {
color: var(--accent);
font-size: 11px;
text-transform: uppercase;
letter-spacing: 1.5px;
flex-shrink: 0;
margin-right: 1.5rem;
}
.command-line code {
flex: 1;
min-width: 0;
color: var(--fg);
font-family: monospace;
font-size: 12px;
line-height: 1.5;
word-break: break-word;
}
.command-line .copy-btn { flex-shrink: 0; }
.setup-list {
margin-top: 1.25rem;
border-top: 1px solid var(--border);
}
.setup-row {
display: grid;
grid-template-columns: 10rem 1.5fr 1fr;
gap: 1.25rem;
align-items: start;
padding: 1rem 0;
border-bottom: 1px solid var(--border);
font-size: 12px;
}
.setup-tool {
color: var(--accent);
font-weight: 600;
font-size: 13px;
letter-spacing: 0.5px;
padding-top: 0.1rem;
}
.setup-artifact { display: flex; flex-direction: column; gap: 0.3rem; min-width: 0; }
.setup-howto {
color: var(--accent);
font-size: 10px;
letter-spacing: 2px;
text-transform: uppercase;
margin-bottom: 0.15rem;
opacity: 0.85;
}
.setup-artifact code {
display: block;
color: var(--fg);
background: var(--hover);
border: 1px solid var(--border);
border-radius: 3px;
padding: 0.35rem 0.55rem;
font-family: monospace;
font-size: 12px;
line-height: 1.5;
word-break: break-word;
white-space: pre-wrap;
}
.setup-artifact code.is-content {
border-style: dashed;
color: var(--fg);
}
.setup-howto + .setup-howto,
.setup-artifact code + .setup-howto {
margin-top: 0.65rem;
}
.setup-note {
color: var(--dim);
line-height: 1.6;
padding-top: 0.5rem;
}
@media (max-width: 620px) {
.command-line {
align-items: stretch;
flex-direction: column;
}
.command-line .copy-btn {
width: fit-content;
}
.setup-row {
grid-template-columns: 1fr;
gap: 0.5rem;
}
.setup-note { padding-top: 0; }
}
.footer {
color: var(--dim);
font-size: 12px;
margin-top: 3rem;
padding-top: 1rem;
border-top: 1px solid var(--border);
}
/* Modal */
.skill { cursor: pointer; }
.modal-backdrop {
display: none;
position: fixed;
inset: 0;
background: rgba(0,0,0,0.75);
z-index: 100;
align-items: center;
justify-content: center;
padding: 2rem;
animation: fadeIn 0.2s ease;
}
.modal-backdrop.open { display: flex; }
@keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }
.modal-box {
background: var(--bg);
border: 1px solid var(--border);
border-radius: 6px;
max-width: 720px;
width: 100%;
max-height: 85vh;
overflow: hidden;
display: flex;
flex-direction: column;
animation: slideUp 0.25s ease;
}
@keyframes slideUp { from { opacity: 0; transform: translateY(12px); } to { opacity: 1; transform: translateY(0); } }
.modal-header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 1rem 1.25rem;
border-bottom: 1px solid var(--border);
flex-shrink: 0;
}
.modal-header-actions { display: flex; align-items: center; gap: 0.75rem; }
.modal-title { color: var(--accent); font-size: 15px; font-weight: 600; }
.modal-close {
background: none;
border: none;
color: var(--dim);
cursor: pointer;
padding: 0.25rem;
line-height: 1;
font-size: 20px;
transition: color 0.15s;
}
.modal-close:hover { color: var(--fg); }
.modal-body {
padding: 1.25rem 1.5rem;
overflow-y: auto;
color: var(--fg);
font-size: 14px;
line-height: 1.65;
}
.modal-body h1, .modal-body h2, .modal-body h3 { color: var(--accent); margin: 1.25em 0 0.5em 0; font-weight: 600; }
.modal-body h1 { font-size: 1.35em; }
.modal-body h2 { font-size: 1.15em; }
.modal-body h3 { font-size: 1.05em; }
.modal-body p { margin: 0.75em 0; }
.modal-body ul, .modal-body ol { margin: 0.75em 0; padding-left: 1.5em; }
.modal-body li { margin: 0.35em 0; }
.modal-body code { background: var(--hover); color: var(--accent); padding: 0.15em 0.4em; border-radius: 3px; font-size: 0.92em; }
.modal-body pre { background: var(--hover); border: 1px solid var(--border); border-radius: 3px; padding: 1rem; overflow-x: auto; margin: 1em 0; }
.modal-body pre code { background: none; padding: 0; color: var(--fg); }
.modal-body blockquote { border-left: 3px solid var(--accent); margin: 1em 0; padding-left: 1em; color: var(--dim); }
.modal-body table { border-collapse: collapse; width: 100%; margin: 1em 0; font-size: 13px; }
.modal-body th, .modal-body td { border: 1px solid var(--border); padding: 0.4rem 0.6rem; text-align: left; }
.modal-body th { background: var(--hover); color: var(--accent); }
.modal-body a { color: var(--accent); }
.modal-body strong { color: var(--fg); font-weight: 600; }
.modal-loading { color: var(--dim); }
.modal-error { color: #c94a4a; }
</style>
</head>
<body>
<!-- Bot-readable skill index: https://ethskills.com/SKILL.md -->
<div aria-hidden="true" style="position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;">
ETHSKILLS — Ethereum Knowledge for AI Agents. Bot-readable. Each skill lives at /topic/SKILL.md — fetch any URL and read it into your context.
All skills: https://ethskills.com/SKILL.md
Individual skills:
https://ethskills.com/ship/SKILL.md — Ship (start here)
https://ethskills.com/why/SKILL.md — Why Ethereum
https://ethskills.com/gas/SKILL.md — Gas & Costs
https://ethskills.com/wallets/SKILL.md — Wallets
https://ethskills.com/l2s/SKILL.md — Layer 2s
https://ethskills.com/standards/SKILL.md — Standards
https://ethskills.com/tools/SKILL.md — Tools
https://ethskills.com/building-blocks/SKILL.md — Money Legos (DeFi)
https://ethskills.com/orchestration/SKILL.md — Orchestration
https://ethskills.com/addresses/SKILL.md — Contract Addresses
https://ethskills.com/concepts/SKILL.md — Concepts
https://ethskills.com/security/SKILL.md — Security
https://ethskills.com/noir/SKILL.md — Noir (ZK Privacy)
https://ethskills.com/testing/SKILL.md — Testing
https://ethskills.com/indexing/SKILL.md — Indexing
https://ethskills.com/frontend-ux/SKILL.md — Frontend UX
https://ethskills.com/frontend-playbook/SKILL.md — Frontend Playbook
https://ethskills.com/qa/SKILL.md — QA (Pre-Ship Audit)
https://ethskills.com/audit/SKILL.md — Audit (Smart Contract Security Audit)
</div>
<div class="ascii" style="font-size:clamp(0.3rem,calc((100vw - 3rem) / 52),1rem);">
███████╗████████╗██╗ ██╗███████╗██╗ ██╗██╗██╗ ██╗ ███████╗
██╔════╝╚══██╔══╝██║ ██║██╔════╝██║ ██╔╝██║██║ ██║ ██╔════╝
█████╗ ██║ ███████║███████╗█████╔╝ ██║██║ ██║ ███████╗
██╔══╝ ██║ ██╔══██║╚════██║██╔═██╗ ██║██║ ██║ ╚════██║
███████╗ ██║ ██║ ██║███████║██║ ██╗██║███████╗███████╗███████║
╚══════╝ ╚═╝ ╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝╚═╝╚══════╝╚══════╝╚══════╝
</div>
<p class="tagline">The missing knowledge between AI agents and production Ethereum.<span class="cursor"></span></p>
<p class="clarifier">Your AI agent is wrong about building on Ethereum. ETHSKILLS fixes that, so anyone can ship onchain, expert or not. Works in Claude, ChatGPT, Cursor, or any agent.</p>
<div class="command-line">
<span class="command-label">Prompt</span>
<code>Read https://ethskills.com/SKILL.md and follow it before writing Solidity or shipping anything onchain.</code>
<button class="copy-btn" data-url="Read https://ethskills.com/SKILL.md and follow it before writing Solidity or shipping anything onchain."><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="9" y="9" width="13" height="13" rx="2"/><path d="M5 15H4a2 2 0 01-2-2V4a2 2 0 012-2h9a2 2 0 012 2v1"/></svg> Copy prompt</button>
</div>
<p class="section-text">Per session. To install it once in Claude Code, Cursor, or Codex, see <a href="#persistent-setup">Persistent Setup</a> below.</p>
<h2>Skills</h2>
<div class="skill">
<div class="skill-name">Ship</div>
<div class="skill-desc">End-to-end guide for AI agents — from a dApp idea to deployed production app. Fetch this FIRST, it routes you through all other skills.</div>
<button class="copy-btn" data-url="https://ethskills.com/ship/SKILL.md"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="9" y="9" width="13" height="13" rx="2"/><path d="M5 15H4a2 2 0 01-2-2V4a2 2 0 012-2h9a2 2 0 012 2v1"/></svg> ethskills.com/ship/SKILL.md</button>
</div>
<div class="skill">
<div class="skill-name">Why Ethereum</div>
<div class="skill-desc">Why build on Ethereum specifically — Pectra/Fusaka upgrades, honest tradeoffs, the AI agent angle, countering stale FUD, matching use cases to strengths.</div>
<button class="copy-btn" data-url="https://ethskills.com/why/SKILL.md"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="9" y="9" width="13" height="13" rx="2"/><path d="M5 15H4a2 2 0 01-2-2V4a2 2 0 012-2h9a2 2 0 012 2v1"/></svg> ethskills.com/why/SKILL.md</button>
</div>
<div class="skill">
<div class="skill-name">Protocol</div>
<div class="skill-desc">How Ethereum evolves — EIP lifecycle, fork process, where decisions happen, and how to verify what's actually planned. Use when asked about upcoming features, Verkle trees, roadmap items, or any protocol-level changes. Prevents confidently wrong answers based on stale training data.</div>
<button class="copy-btn" data-url="https://ethskills.com/protocol/SKILL.md"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="9" y="9" width="13" height="13" rx="2"/><path d="M5 15H4a2 2 0 01-2-2V4a2 2 0 012-2h9a2 2 0 012 2v1"/></svg> ethskills.com/protocol/SKILL.md</button>
</div>
<div class="skill">
<div class="skill-name">Gas & Costs</div>
<div class="skill-desc">Current gas prices, what things actually cost on Ethereum today, mainnet vs L2 honest comparison. Counters the #1 misconception that Ethereum is expensive.</div>
<button class="copy-btn" data-url="https://ethskills.com/gas/SKILL.md"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="9" y="9" width="13" height="13" rx="2"/><path d="M5 15H4a2 2 0 01-2-2V4a2 2 0 012-2h9a2 2 0 012 2v1"/></svg> ethskills.com/gas/SKILL.md</button>
</div>
<div class="skill">
<div class="skill-name">Wallets</div>
<div class="skill-desc">Creating wallets, connecting to dApps, signing transactions, multisig (Gnosis Safe), account abstraction. How an AI agent gets a wallet and uses it safely.</div>
<button class="copy-btn" data-url="https://ethskills.com/wallets/SKILL.md"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="9" y="9" width="13" height="13" rx="2"/><path d="M5 15H4a2 2 0 01-2-2V4a2 2 0 012-2h9a2 2 0 012 2v1"/></svg> ethskills.com/wallets/SKILL.md</button>
</div>
<div class="skill">
<div class="skill-name">Layer 2s</div>
<div class="skill-desc">Current L2 landscape, bridging, deployment differences, when to use which L2. Arbitrum, Optimism, Base, zkSync, and more.</div>
<button class="copy-btn" data-url="https://ethskills.com/l2s/SKILL.md"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="9" y="9" width="13" height="13" rx="2"/><path d="M5 15H4a2 2 0 01-2-2V4a2 2 0 012-2h9a2 2 0 012 2v1"/></svg> ethskills.com/l2s/SKILL.md</button>
</div>
<div class="skill">
<div class="skill-name">Standards</div>
<div class="skill-desc">ERC-20, ERC-721, ERC-1155, ERC-8004 (agent identity), EIP-7702 (smart EOAs), and newer ERCs. Token standards, identity standards, payment standards.</div>
<button class="copy-btn" data-url="https://ethskills.com/standards/SKILL.md"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="9" y="9" width="13" height="13" rx="2"/><path d="M5 15H4a2 2 0 01-2-2V4a2 2 0 012-2h9a2 2 0 012 2v1"/></svg> ethskills.com/standards/SKILL.md</button>
</div>
<div class="skill">
<div class="skill-name">Tools</div>
<div class="skill-desc">Current frameworks, libraries, RPCs, block explorers. x402 (HTTP payments), MCPs, abi.ninja, Foundry, Scaffold-ETH 2. What actually works today.</div>
<button class="copy-btn" data-url="https://ethskills.com/tools/SKILL.md"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="9" y="9" width="13" height="13" rx="2"/><path d="M5 15H4a2 2 0 01-2-2V4a2 2 0 012-2h9a2 2 0 012 2v1"/></svg> ethskills.com/tools/SKILL.md</button>
</div>
<div class="skill">
<div class="skill-name">Money Legos</div>
<div class="skill-desc">DeFi legos and protocol composability. Uniswap, Aave, Compound, MakerDAO, Yearn, Curve — what they do, how to build on them, how to combine them.</div>
<button class="copy-btn" data-url="https://ethskills.com/building-blocks/SKILL.md"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="9" y="9" width="13" height="13" rx="2"/><path d="M5 15H4a2 2 0 01-2-2V4a2 2 0 012-2h9a2 2 0 012 2v1"/></svg> ethskills.com/building-blocks/SKILL.md</button>
</div>
<div class="skill">
<div class="skill-name">Orchestration</div>
<div class="skill-desc">The three-phase build system and dApp orchestration patterns. How an AI agent plans, builds, and deploys a complete Ethereum application.</div>
<button class="copy-btn" data-url="https://ethskills.com/orchestration/SKILL.md"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="9" y="9" width="13" height="13" rx="2"/><path d="M5 15H4a2 2 0 01-2-2V4a2 2 0 012-2h9a2 2 0 012 2v1"/></svg> ethskills.com/orchestration/SKILL.md</button>
</div>
<div class="skill">
<div class="skill-name">Contract Addresses</div>
<div class="skill-desc">Verified contract addresses for major protocols across Ethereum mainnet and L2s. Stop hallucinating addresses — use real ones.</div>
<button class="copy-btn" data-url="https://ethskills.com/addresses/SKILL.md"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="9" y="9" width="13" height="13" rx="2"/><path d="M5 15H4a2 2 0 01-2-2V4a2 2 0 012-2h9a2 2 0 012 2v1"/></svg> ethskills.com/addresses/SKILL.md</button>
</div>
<div class="skill">
<div class="skill-name">Concepts</div>
<div class="skill-desc">The essential mental models for building onchain. "Nothing is automatic" — every function needs a caller and an incentive. Randomness pitfalls, incentive design, the hyperstructure test, and how to teach your human.</div>
<button class="copy-btn" data-url="https://ethskills.com/concepts/SKILL.md"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="9" y="9" width="13" height="13" rx="2"/><path d="M5 15H4a2 2 0 01-2-2V4a2 2 0 012-2h9a2 2 0 012 2v1"/></svg> ethskills.com/concepts/SKILL.md</button>
</div>
<div class="skill">
<div class="skill-name">Security</div>
<div class="skill-desc">Solidity security patterns and common vulnerabilities with defensive code. Token decimals, reentrancy, oracle manipulation, vault inflation attacks, and a pre-deploy checklist. Run through this before every deployment.</div>
<button class="copy-btn" data-url="https://ethskills.com/security/SKILL.md"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="9" y="9" width="13" height="13" rx="2"/><path d="M5 15H4a2 2 0 01-2-2V4a2 2 0 012-2h9a2 2 0 012 2v1"/></svg> ethskills.com/security/SKILL.md</button>
</div>
<div class="skill">
<div class="skill-name">Noir (ZK Privacy)</div>
<div class="skill-desc">Building privacy apps with Noir zero-knowledge circuits — toolchain, commitment-nullifier pattern, Solidity verifiers, NoirJS frontend integration. Use when building anything with zero-knowledge proofs on Ethereum.</div>
<button class="copy-btn" data-url="https://ethskills.com/noir/SKILL.md"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="9" y="9" width="13" height="13" rx="2"/><path d="M5 15H4a2 2 0 01-2-2V4a2 2 0 012-2h9a2 2 0 012 2v1"/></svg> ethskills.com/noir/SKILL.md</button>
</div>
<div class="skill">
<div class="skill-name">Testing</div>
<div class="skill-desc">Smart contract testing with Foundry — unit tests, fuzz testing, fork testing, invariant testing. What to test, what not to test, and what LLMs get wrong.</div>
<button class="copy-btn" data-url="https://ethskills.com/testing/SKILL.md"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="9" y="9" width="13" height="13" rx="2"/><path d="M5 15H4a2 2 0 01-2-2V4a2 2 0 012-2h9a2 2 0 012 2v1"/></svg> ethskills.com/testing/SKILL.md</button>
</div>
<div class="skill">
<div class="skill-name">Indexing</div>
<div class="skill-desc">How to read and query onchain data — events, The Graph, Dune, indexing patterns. Why you cannot just loop through blocks, and what to use instead.</div>
<button class="copy-btn" data-url="https://ethskills.com/indexing/SKILL.md"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="9" y="9" width="13" height="13" rx="2"/><path d="M5 15H4a2 2 0 01-2-2V4a2 2 0 012-2h9a2 2 0 012 2v1"/></svg> ethskills.com/indexing/SKILL.md</button>
</div>
<div class="skill">
<div class="skill-name">Frontend UX</div>
<div class="skill-desc">Mandatory frontend rules for Scaffold-ETH 2 projects. Onchain button loaders, three-button approval flow, Address components, USD values, RPC config, and pre-publish checklist. Prevents the UX mistakes AI agents make on every build.</div>
<button class="copy-btn" data-url="https://ethskills.com/frontend-ux/SKILL.md"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="9" y="9" width="13" height="13" rx="2"/><path d="M5 15H4a2 2 0 01-2-2V4a2 2 0 012-2h9a2 2 0 012 2v1"/></svg> ethskills.com/frontend-ux/SKILL.md</button>
</div>
<div class="skill">
<div class="skill-name">Frontend Playbook</div>
<div class="skill-desc">The complete build-to-production pipeline. Fork mode, IPFS deployment, Vercel monorepo config, ENS subdomain setup, and the full go-to-production checklist with verification steps.</div>
<button class="copy-btn" data-url="https://ethskills.com/frontend-playbook/SKILL.md"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="9" y="9" width="13" height="13" rx="2"/><path d="M5 15H4a2 2 0 01-2-2V4a2 2 0 012-2h9a2 2 0 012 2v1"/></svg> ethskills.com/frontend-playbook/SKILL.md</button>
</div>
<div class="skill">
<div class="skill-name">QA</div>
<div class="skill-desc">Production QA checklist for dApps. Give this to a SEPARATE reviewer agent after the build — it audits the app against every common mistake AI agents make before shipping. Covers approve button double-fire, wallet flow, SE2 branding cleanup, USD values, and more.</div>
<button class="copy-btn" data-url="https://ethskills.com/qa/SKILL.md"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="9" y="9" width="13" height="13" rx="2"/><path d="M5 15H4a2 2 0 01-2-2V4a2 2 0 012-2h9a2 2 0 012 2v1"/></svg> ethskills.com/qa/SKILL.md</button>
</div>
<div class="skill">
<div class="skill-name">Audit</div>
<div class="skill-desc">Deep EVM smart contract audit system. 500+ non-obvious checklist items across 19 domains — AMM, lending, oracles, proxies, signatures, governance, bridges, and more. Runs parallel specialist agents, synthesizes findings, and files GitHub issues. Use when auditing contracts you didn't write.</div>
<button class="copy-btn" data-url="https://ethskills.com/audit/SKILL.md"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="9" y="9" width="13" height="13" rx="2"/><path d="M5 15H4a2 2 0 01-2-2V4a2 2 0 012-2h9a2 2 0 012 2v1"/></svg> ethskills.com/audit/SKILL.md</button>
</div>
<h2 id="persistent-setup">Persistent Setup</h2>
<p class="section-text">Optional. If you'd rather not paste the prompt above every session, configure your tool once below.</p>
<div class="setup-list">
<div class="setup-row">
<span class="setup-tool">Codex</span>
<div class="setup-artifact">
<span class="setup-howto">1. Create this file in your repo root</span>
<code>AGENTS.md</code>
<span class="setup-howto">2. Paste this inside the file</span>
<code class="is-content">Read https://ethskills.com/SKILL.md and follow it before writing Solidity or shipping anything onchain.</code>
</div>
<span class="setup-note">Pointer (per repo). Codex fetches ethskills on each task.</span>
</div>
<div class="setup-row">
<span class="setup-tool">Cursor</span>
<div class="setup-artifact">
<span class="setup-howto">1. Create this Cursor rule file</span>
<code>.cursor/rules/ethskills.mdc</code>
<span class="setup-howto">2. Paste this inside the file</span>
<code class="is-content">---
description: ethskills knowledge pack for building on Ethereum
alwaysApply: true
---
Before writing Solidity, deploying contracts, integrating DeFi, or building a dApp frontend, read https://ethskills.com/SKILL.md and follow it.</code>
</div>
<span class="setup-note">Pointer (per repo). Cursor fetches when the rule fires.</span>
</div>
<div class="setup-row">
<span class="setup-tool">Claude Code</span>
<div class="setup-artifact">
<span class="setup-howto">1. Add the marketplace catalog</span>
<code>/plugin marketplace add austintgriffith/ethskills</code>
<span class="setup-howto">2. Install ethskills (active in every project)</span>
<code>/plugin install ethskills@ethskills</code>
</div>
<span class="setup-note">Install (user-wide). Plugin reads from disk, granular skill loading.</span>
</div>
<div class="setup-row">
<span class="setup-tool">OpenClaw</span>
<div class="setup-artifact">
<span class="setup-howto">Run in your terminal</span>
<code>clawhub install ethskills</code>
</div>
<span class="setup-note">Install (per project). Cloned into ./skills/.</span>
</div>
<div class="setup-row">
<span class="setup-tool">Scripts</span>
<div class="setup-artifact">
<span class="setup-howto">Run in your shell</span>
<code>curl -s https://ethskills.com/SKILL.md</code>
</div>
<span class="setup-note">Fetch + bake (per script). Embed in pipelines or system prompts.</span>
</div>
</div>
<h2>Contributing</h2>
<p class="section-text">Something wrong or missing? Humans and agents alike are welcome to <a href="https://github.com/austintgriffith/ethskills">open a PR</a>.</p>
<h2>Feedback</h2>
<p class="section-text">If something in ethskills confused you, slowed you down, or genuinely helped — issues OR praise — fetch <a href="https://ethskills.com/feedback/SKILL.md">feedback/SKILL.md</a> and send a note. Bias toward sending; weak signals are easy to ignore in the inbox, but missing signals can't be recovered.</p>
<div class="footer">MIT License · <a href="https://github.com/austintgriffith/ethskills">GitHub Repo</a> · <a href="https://github.com/austintgriffith/ethskills-research">Research</a></div>
<div id="modal" class="modal-backdrop" aria-hidden="true">
<div class="modal-box" role="dialog" aria-modal="true">
<div class="modal-header">
<span class="modal-title" id="modal-title">Skill</span>
<div class="modal-header-actions">
<button type="button" class="copy-btn" id="modal-copy-btn" data-url="" title="Copy skill URL"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="9" y="9" width="13" height="13" rx="2"/><path d="M5 15H4a2 2 0 01-2-2V4a2 2 0 012-2h9a2 2 0 012 2v1"/></svg> <span id="modal-copy-label"></span></button>
<a class="copy-btn" id="modal-edit-btn" href="#" target="_blank" rel="noopener" title="Edit on GitHub">Edit</a>
<button type="button" class="modal-close" id="modal-close" aria-label="Close">×</button>
</div>
</div>
<div class="modal-body" id="modal-body"></div>
</div>
</div>
<script>
// Minimal markdown → HTML (no external deps). Escapes HTML in text.
function renderMarkdown(md) {
const esc = s => s.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>').replace(/"/g,'"');
const inline = s => esc(s)
.replace(/\*\*(.+?)\*\*/g, '<strong>$1</strong>')
.replace(/\*(.+?)\*/g, '<em>$1</em>')
.replace(/`([^`]+)`/g, '<code>$1</code>')
.replace(/\[([^\]]+)\]\(([^)]+)\)/g, '<a href="$2" target="_blank" rel="noopener">$1</a>');
let raw = md.replace(/\r\n?/g, '\n');
if (raw.startsWith('---\n')) {
const end = raw.indexOf('\n---', 4);
if (end !== -1) raw = raw.slice(end + 4).replace(/^\n+/, '');
}
let out = '';
const lines = raw.split('\n');
let i = 0;
while (i < lines.length) {
const line = lines[i];
if (/^```(\w*)\s*$/.test(line)) {
let block = '';
for (i++; i < lines.length && !/^```\s*$/.test(lines[i]); i++) block += esc(lines[i]) + '\n';
i++;
out += '<pre><code>' + block + '</code></pre>';
continue;
}
if (/^(#{1,3})\s+(.+)$/.test(line)) {
const l = RegExp.$1.length;
out += '<h' + l + '>' + inline(RegExp.$2) + '</h' + l + '>';
i++;
continue;
}
if (/^\|.+\|$/.test(line)) {
const rows = [];
while (i < lines.length && /^\|.+\|$/.test(lines[i])) {
if (!/^\|[-:\s|]+\|$/.test(lines[i])) {
rows.push(lines[i].split('|').slice(1, -1).map(c => c.trim()));
}
i++;
}
if (rows.length) {
out += '<table><thead><tr>';
rows[0].forEach(c => { out += '<th>' + inline(c) + '</th>'; });
out += '</tr></thead><tbody>';
for (let r = 1; r < rows.length; r++) {
out += '<tr>';
rows[r].forEach(c => { out += '<td>' + inline(c) + '</td>'; });
out += '</tr>';
}
out += '</tbody></table>';
}
continue;
}
if (/^>\s?(.*)$/.test(line)) {
let block = inline(RegExp.$1);
for (i++; i < lines.length && /^>\s?(.*)$/.test(lines[i]); i++) block += '\n' + inline(RegExp.$1);
out += '<blockquote>' + block.replace(/\n/g, '<br>') + '</blockquote>';
continue;
}
if (/^[-*]\s+(.+)$/.test(line)) {
out += '<ul>';
while (i < lines.length && /^[-*]\s+(.+)$/.test(lines[i])) {
out += '<li>' + inline(RegExp.$1) + '</li>';
i++;
}
out += '</ul>';
continue;
}
if (/^\d+\.\s+(.+)$/.test(line)) {
out += '<ol>';
while (i < lines.length && /^\d+\.\s+(.+)$/.test(lines[i])) {
out += '<li>' + inline(RegExp.$1) + '</li>';
i++;
}
out += '</ol>';
continue;
}
if (line.trim() === '') {
i++;
continue;
}
out += '<p>' + inline(line) + '</p>';
i++;
}
return out;
}
// Copy URL on copy button click (stop propagation so card click doesn't fire)
document.querySelectorAll('.copy-btn[data-url]').forEach(btn => {
btn.addEventListener('click', async (e) => {
e.stopPropagation();
const url = btn.dataset.url;
try { await navigator.clipboard.writeText(url); } catch(err) {
const t = document.createElement('textarea'); t.value = url; document.body.appendChild(t); t.select(); document.execCommand('copy'); document.body.removeChild(t);
}
const orig = btn.innerHTML;
btn.classList.add('copied');
btn.innerHTML = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="20 6 9 17 4 12"/></svg> Copied!';
setTimeout(() => { btn.innerHTML = orig; btn.classList.remove('copied'); }, 1500);
});
});
// Hero button now uses copy-btn class — handled by the querySelectorAll above.
// Modal: open on card click, fetch skill and render markdown
const modal = document.getElementById('modal');
const modalTitle = document.getElementById('modal-title');
const modalBody = document.getElementById('modal-body');
const modalClose = document.getElementById('modal-close');
const modalCopyBtn = document.getElementById('modal-copy-btn');
const modalCopyLabel = document.getElementById('modal-copy-label');
const GITHUB_BASE = 'https://github.com/austintgriffith/ethskills/blob/master/';
function openModal(title, path, skillUrl) {
modal.classList.add('open');
modal.setAttribute('aria-hidden', 'false');
modalTitle.textContent = title;
modalCopyBtn.dataset.url = skillUrl;
modalCopyLabel.textContent = skillUrl.replace(/^https?:\/\/[^/]+\//, '');
document.getElementById('modal-edit-btn').href = GITHUB_BASE + path;
modalBody.innerHTML = '<p class="modal-loading">Loading…</p>';
modalBody.classList.remove('modal-error');
fetch(path)
.then(r => { if (!r.ok) throw new Error(r.statusText); return r.text(); })
.then(text => { modalBody.innerHTML = renderMarkdown(text); })
.catch(err => {
modalBody.classList.add('modal-error');
modalBody.innerHTML = '<p>Could not load skill: ' + ('' + err.message).replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>') + '.</p>';
});
}
function closeModal() {
modal.classList.remove('open');
modal.setAttribute('aria-hidden', 'true');
}
document.querySelectorAll('.skill').forEach(card => {
const copyBtn = card.querySelector('.copy-btn[data-url]');
const title = card.querySelector('.skill-name');
if (!copyBtn || !title) return;
card.addEventListener('click', (e) => {
if (e.target.closest('.copy-btn')) return;
const skillUrl = copyBtn.dataset.url;
const path = new URL(skillUrl).pathname.slice(1);
openModal(title.textContent, path, skillUrl);
});
});
modalCopyBtn.addEventListener('click', async (e) => {
e.stopPropagation();
const url = modalCopyBtn.dataset.url;
if (!url) return;
try { await navigator.clipboard.writeText(url); } catch(err) {
const t = document.createElement('textarea'); t.value = url; document.body.appendChild(t); t.select(); document.execCommand('copy'); document.body.removeChild(t);
}
const orig = modalCopyBtn.innerHTML;
modalCopyBtn.classList.add('copied');
modalCopyBtn.innerHTML = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="20 6 9 17 4 12"/></svg> Copied!';
setTimeout(() => { modalCopyBtn.innerHTML = orig; modalCopyBtn.classList.remove('copied'); }, 1500);
});
modalClose.addEventListener('click', closeModal);
modal.addEventListener('click', (e) => { if (e.target === modal) closeModal(); });
document.addEventListener('keydown', (e) => { if (e.key === 'Escape') closeModal(); });
</script>
</body>
</html>
SKILL.mdethskills — OpenClaw Skill
Ethereum development knowledge for AI agents. Fetches real-time docs from ethskills.com so your agent knows how to actually build on Ethereum — not just trade on it.
Install
Copy SKILL.md into your OpenClaw skills directory, or point your agent at:
https://ethskills.com/SKILL.mdNo API keys. No CLI tools. Just curl and read.
What It Does
When your agent encounters any Ethereum/Solidity/dApp task, this skill tells it to fetch the relevant ethskills.com doc. The docs are kept current and correct what LLMs typically get wrong about gas costs, tooling, L2s, and deployment patterns.
Topics Covered
- Scaffold-ETH 2 project setup
- Solidity security patterns
- Gas costs (correcting stale training data)
- Layer 2 deployment
- ERC standards (ERC-20, ERC-721, ERC-8004, x402)
- DeFi composability
- Testing with Foundry
- Frontend UX patterns
- Production deployment & QA
Links
<img width="759" height="198" alt="image" src="https://github.com/user-attachments/assets/19afbd29-29cd-4b9a-bb67-c914cc5d9576" />
LLMs think gas is 30 gwei. It's 0.05. They've never heard of ERC-8004 or x402. They hallucinate contract addresses. This site fixes that.
How It Works
Each skill is a markdown file. Give any URL to your AI agent — it reads it and instantly corrects its Ethereum knowledge.
https://ethskills.com/SKILL.md ← table of contents
https://ethskills.com/gas/SKILL.md ← just gas & costs
https://ethskills.com/why/SKILL.md ← why ethereumAdd the top-level SKILL.md to your agent's context
The agent will look up the specific skills when needed.
Just prompt your agent with this:
Install the https://github.com/austintgriffith/ethskills/blob/master/SKILL.md skillClaude Code Plugin
Install directly from GitHub — no clone required:
/plugin marketplace add austintgriffith/ethskills
/plugin install ethskills@ethskillsTerminology
Say "onchain" not "on-chain." The Ethereum community writes it as one word — no hyphen. LLMs default to "on-chain" but that's not how builders talk. Use "onchain" in all writing, documentation, and generated content.
Skills
| Skill | What LLMs Get Wrong |
|---|---|
| Why Ethereum | Pectra/Fusaka shipped, gas is cheap now, AI agent angle |
| Gas & Costs | Think gas is 10-30 gwei — reality is 0.05-0.3 gwei |
| Wallets | EIP-7702 is live, Safe addresses, agent key safety |
| Layer 2s | Think L2 txs cost $0.01-2.00 — reality is <$0.001 |
| Standards | Don't know ERC-8004, EIP-7702 status, EIP-3009 for x402 |
| Tools | Don't know x402, Blockscout MCP, current tool landscape |
| Money Legos | Stale on current DeFi state, Uniswap V4 status |
| Orchestration | Don't know SE2 three-phase build system |
| Contract Addresses | Hallucinate addresses — these are verified onchain |
| Concepts | Nothing is automatic, incentive design, randomness pitfalls |
| Security | Token decimals, reentrancy, oracle manipulation, vault inflation, pre-deploy checklist |
| Frontend UX | Onchain button rules, three-button approval flow, Address components, USD values |
| Frontend Playbook | Fork mode, IPFS deploy, Vercel config, ENS setup, production checklist |
Security Guardrails
Skills teach restraint, not just capability. Every skill that touches keys, credentials, or funds includes explicit safety rules — because LLMs optimize for speed and will hardcode a private key into git add . if you let them. Coverage includes wallet keys, API keys, RPC URLs, and the common SE2 scaffold.config.ts trap.
Methodology
We test stock LLMs, find what they get wrong, and write corrections. Content is verified against onchain reality. If an LLM already knows something, we don't include it.
Every proposed change goes through [triage](https://github.com/austintgriffith/ethskills-research/blob/master/research/triage-methodology.md): spawn a stock LLM, give it a realistic task, see what it gets wrong. Only verified blind spots survive.
See the research repo for baseline audits, gap analysis, and full methodology.
Contributing
Something wrong or missing? Humans and agents are welcome to open a PR. Read CONTRIBUTING.md first — the bar is "would a stock LLM get this wrong?"
License
MIT
{
"rewrites": [
{ "source": "/l2", "destination": "/l2s/SKILL.md" },
{ "source": "/layer2", "destination": "/l2s/SKILL.md" },
{ "source": "/defi", "destination": "/building-blocks/SKILL.md" },
{ "source": "/inbox", "destination": "/inbox.html" },
{ "source": "/:skill", "destination": "/:skill/SKILL.md" }
],
"headers": [
{
"source": "/(.*)\\.md",
"headers": [
{ "key": "Access-Control-Allow-Origin", "value": "*" },
{ "key": "Content-Type", "value": "text/markdown; charset=utf-8" }
]
}
]
}
Related skills
FAQ
Is Ethereum still expensive?
No. Gas is under 1 gwei, a mainnet transfer is about $0.004 and a swap about $0.04, which is 60-300x cheaper than older training data suggests.
Where should an agent start?
Fetch ship/SKILL.md first for an end-to-end build route, or fetch a specific standalone topic skill by name.