| name | asset-flow-analysis |
| description | Auto-loaded by explorator (Phase 1) and sub-auditors (Phase 2) for asset mapping. Framework: "Where's the money? How does it move? Where can it leak?" Maps asset storage locations, movement paths, leakage points. Answers attacker's first question about protocol funds.
|
| user-invocable | false |
Asset Flow Analysis Framework
Purpose
"Where is the money? How does it move? Where can it leak?"
Systematically map asset storage, movement paths, and potential leakage points within a protocol.
1. Asset Storage Identification
1.1 ETH Storage
// Direct balance
address(this).balance
// Wrapped ETH
WETH.balanceOf(address(this))
1.2 ERC20 Token Storage
// Token balance
IERC20(token).balanceOf(address(this))
// Internal accounting variables
mapping(address => uint256) balances;
uint256 totalDeposited;
1.3 Share/LP Tokens
// Minted amount
uint256 totalSupply;
mapping(address => uint256) shares;
// LP tokens
IUniswapV2Pair(pair).totalSupply();
IUniswapV2Pair(pair).balanceOf(address(this));
1.4 Asset Storage by Protocol Type
| Protocol Type | Asset Storage Pattern | Key Variables |
|---|
| Vault | ERC20 balance + internal shares | totalAssets, totalSupply |
| AMM/DEX | reserve0, reserve1 | Token pair balances |
| Lending | deposits mapping + borrowed funds | totalDeposits, totalBorrowed |
| Staking | staked tokens + reward pool | totalStaked, rewardPool |
| Bridge | locked tokens | lockedAmount, pendingTransfers |
2. Asset Flow Mapping
2.1 Deposit Paths (Inflow)
[User Wallet] ──deposit()──► [Protocol Contract]
│
▼
shares issued
| Function | Description | Risk |
|---|
deposit() | Asset deposit | Entry point |
stake() | Staking | Entry point |
supply() | Supply | Entry point |
mint() | LP mint | Entry point |
2.2 Withdrawal Paths (Outflow)
[Protocol Contract] ──withdraw()──► [User Wallet]
│
▼
shares burned
| Function | Description | Risk |
|---|
withdraw() | Asset withdrawal | Exit point |
unstake() | Unstaking | Exit point |
redeem() | Redemption | Exit point |
burn() | LP burn | Exit point |
2.3 Transfer Paths (Internal)
[Pool A] ──swap()──► [Pool B]
│
▼
price calculation
| Function | Description | Risk |
|---|
swap() | Exchange | Price manipulation |
transfer() | Transfer | Permission verification |
liquidate() | Liquidation | Oracle dependency |
2.4 Privileged Paths
[Admin] ──emergencyWithdraw()──► [Admin Wallet]
⚠️ High risk
| Function | Description | Risk |
|---|
emergencyWithdraw() | Emergency withdrawal | Rug Pull |
skim() | Surplus collection | Asset leakage |
sweep() | Token recovery | Unintended withdrawal |
rescue() | Rescue | Potential abuse |
3. Leakage Path Exploration
3.1 Unvalidated Withdrawal
// DANGER: No access control
function withdraw(uint256 amount) external {
token.transfer(msg.sender, amount); // @audit Anyone can withdraw!
}
3.2 Calculation Error Leakage
// DANGER: Precision loss
function withdraw(uint256 shares) external {
uint256 amount = shares / totalSupply * totalAssets; // @audit Division first!
// Multiple withdrawals accumulate rounding gains
}
3.3 Callback Bypass Leakage
// DANGER: Reentrancy through callback
function withdraw(uint256 amount) external {
token.transfer(msg.sender, amount); // @audit Callback occurs
balances[msg.sender] -= amount; // State update too late
}
3.4 Economic Attack Leakage
// DANGER: Price manipulation
function liquidate(address user) external {
uint256 price = oracle.getPrice(); // @audit Spot price can be manipulated
if (collateral[user] * price < debt[user]) {
// Liquidation with manipulated price
}
}
4. Asset Flow Diagram Template
┌─────────────────────────────────────────────────┐
│ Asset Flow Diagram │
├─────────────────────────────────────────────────┤
│ │
│ [User Wallet] │
│ │ │
│ │ deposit()/stake() │
│ ▼ │
│ ┌─────────────┐ ┌─────────────┐ │
│ │ Protocol │◄────►│ Oracle │ │
│ │ Contract │ │ (Price) │ │
│ └─────────────┘ └─────────────┘ │
│ │ │ │
│ │ │ withdraw()/swap() │
│ │ ▼ │
│ [User Wallet] [Admin] ◄── emergencyWithdraw│
│ │ │
│ ▼ │
│ ⚠️ Leakage Risk │
│ │
└─────────────────────────────────────────────────┘
5. Output Format
## Asset Flow Analysis Results
### Asset Storage
| Contract | Asset Type | Storage Variable | Location |
|----------|------------|------------------|----------|
| Pool | ETH | address(this).balance | Pool.sol:45 |
| Pool | ERC20 | token.balanceOf | Pool.sol:67 |
| Pool | Shares | totalSupply | Pool.sol:23 |
### Flow Paths
#### Deposit (Inflow)
User → deposit() → Pool
├── amount validation
├── token transfer
└── shares issued
#### Withdrawal (Outflow)
Pool → withdraw() → User
├── shares validation
├── shares burned
└── token transfer
### Leakage Risk Points
| Location | Path | Risk Level | Description |
|----------|------|------------|-------------|
| Pool.sol:142 | withdraw() | High | Insufficient access control |
| Pool.sol:200 | skim() | Medium | Admin-only unverified |
### Attack Scenarios
1. **First Depositor Attack**
- Path: deposit → donate → next user deposit
- Leakage: Subsequent depositor funds
- Risk Level: High
6. Search Queries
# Find asset storage
Grep("balanceOf\\(address\\(this\\)\\)|address\\(this\\)\\.balance", glob="**/*.sol")
Grep("totalSupply|totalAssets|totalDeposited", glob="**/*.sol")
# Find deposit functions
Grep("function.*deposit|function.*stake|function.*supply", glob="**/*.sol")
# Find withdrawal functions
Grep("function.*withdraw|function.*redeem|function.*unstake", glob="**/*.sol")
# Find privileged functions
Grep("emergencyWithdraw|sweep|rescue|skim", glob="**/*.sol")
7. Attacker Mindset
- "Where is the money stored?" → Asset storage
- "Who can move the money?" → Access permissions
- "What paths can leak money?" → Leakage points
- "Can I manipulate the flow?" → Price/calculation attacks