Crypto Project Penetration Testing
Penetration test of crypto project is not standard web application pentest plus Slither. It is multi-level work: smart contracts, infrastructure, frontend, bridges, backend API and social engineering. Ronin Bridge lost $625M not from contract vulnerability — from compromising 5 of 9 validator keys through spear phishing. Effective pentest covers all attack vectors.
Scope and methodology
Before starting, clearly define scope. Typical crypto project components:
| Component | Attack vectors |
|---|---|
| Smart contracts | Reentrancy, flash loan, overflow, access control |
| Frontend dApp | XSS, wallet drainer injection, clipboard hijacking |
| Backend API | Auth bypass, IDOR, rate limiting, key exposure |
| Infrastructure | Node RPC exposure, private key management, admin panels |
| Bridge / relayer | Replay attacks, signature malleability, validator compromise |
| Discord/Telegram | Bot manipulation, invite phishing, admin account takeover |
Smart contract analysis
Static analysis
Start of any contract pentest — automated tools:
# Slither — static analyzer from Trail of Bits
slither . --print human-summary
slither . --detect reentrancy-eth,reentrancy-no-eth,arbitrary-send-eth
# Mythril — symbolic execution
myth analyze contracts/Vault.sol --solv 0.8.20
# Aderyn — Rust-based analyzer, faster than Slither on large codebases
aderyn .
# 4naly3er — specialized in gas and security patterns
Automated tools find low-hanging fruit: wrong operation order, unused return values, obvious reentrancy. Critical vulnerabilities rarely found automatically.
Manual contract analysis
Focused areas for manual review:
Access control: who can call privileged functions? Is onlyOwner / AccessControl implemented correctly? No backdoors through constructor or initializer?
// Classic mistake: initializer can be called twice
contract VulnerableProxy {
bool private initialized;
function initialize(address _admin) external {
// VULNERABILITY: no !initialized check
admin = _admin;
}
}
// Correct:
function initialize(address _admin) external {
require(!initialized, "Already initialized");
initialized = true;
admin = _admin;
}
Price oracle manipulation: spot prices instead of TWAP? Possible flash loan attack on oracle?
Signature validation: correct EIP-712 signature checks? Replay attack protection via nonce or chainId?
Economic attacks
Flash loan attacks on AMM protocols require understanding pool mechanics:
// Simulate flash loan attack via Foundry
// forge test --match-test testFlashLoanAttack -vvv
function testFlashLoanAttack() public {
// 1. Take 1000 ETH flash loan
uint256 flashAmount = 1000 ether;
vm.deal(address(attacker), flashAmount);
uint256 priceBefore = target.getPrice();
// 2. Manipulate pool — sharply buy token
attacker.manipulatePool(flashAmount);
uint256 priceAfter = target.getPrice();
console.log("Price manipulation:", priceBefore, "->", priceAfter);
// 3. Exploit protocol with manipulated price
uint256 profit = attacker.exploit();
// 4. Repay flash loan
attacker.repayFlash(flashAmount);
assertGt(profit, 0, "Attack should be profitable");
}
Frontend security
Wallet drainer injection
Most common attack on dApp users — compromised frontend injecting malicious approve transactions:
Supply chain attack: attacker compromises npm package (web3-utils, ethers fork) or CDN from which frontend loads. Injected script replaces recipient address in transactions or injects setApprovalForAll for NFT contract.
Check in pentest:
- Subresource Integrity (SRI) hashes for external scripts
- Content Security Policy headers
- Lockfile (
package-lock.json,yarn.lock) with integrity hashes - Used CDNs and their trust chain
Clipboard hijacking: script replaces address in clipboard on copy. Simple DOM injection via XSS.
Infrastructure audit
RPC endpoint security
Many protocols maintain own Ethereum nodes. Check:
# Is RPC open publicly?
curl -X POST http://node-ip:8545 \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","method":"eth_accounts","id":1}'
# If returns accounts — critical vulnerability
# Check methods whitelist
curl -X POST http://node-ip:8545 \
-d '{"method":"admin_nodeInfo","id":1}' # should be blocked
Private keys and secrets
Audit key management:
- Where are deploy keys stored? (HSM, AWS KMS, local file?)
- Who has multisig access? Hardware wallet used?
- Are there .env files with keys in repository (git history)?
- Were keys rotated after employee termination?
# Search for secrets in git history
git log -p --all | grep -E "(private_key|PRIVATE_KEY|mnemonic|MNEMONIC)" | head -20
# TruffleHog — specialized tool
trufflehog git file://. --only-verified
# GitLeaks
gitleaks detect --source . -v
Bridge and cross-chain specifics
Bridge contracts are highest-risk component. Specific checks:
Replay attack: same signed message can be used on multiple chains. Signature must include chainId and unique nonce.
Validator key management: how many validator keys need compromise for attack? Ronin Bridge had 9 validators, 5 controlled by one organization (Axie Infinity / Sky Mavis). Effective threshold was 2/2, not 5/9.
Finality assumptions: bridge must wait for block finality before minting on destination chain. For Ethereum — 12+ blocks (PoS finality). For BSC — more due to different consensus.
Pentest report
Final report structure:
Critical: direct fund loss, possible immediate exploitation
High: significant risk under certain conditions
Medium: logical errors, potential DoS vectors
Low/Informational: best practice violations, improvements
For each finding:
- Vulnerability description
- Proof of Concept (code or reproduction steps)
- Potential impact
- Remediation recommendations
- Status after remediation
Pentest is snapshot. Protocol changes, new code requires new audit. Best protocols (Uniswap, Aave) audit each major update and maintain bug bounty programs via Immunefi for continuous coverage.







