solidity-argus 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (131) hide show
  1. package/AGENTS.md +37 -0
  2. package/LICENSE +21 -0
  3. package/README.md +249 -0
  4. package/package.json +43 -0
  5. package/skills/INVENTORY.md +79 -0
  6. package/skills/README.md +56 -0
  7. package/skills/checklists/cyfrin-best-practices-runtime/SKILL.md +424 -0
  8. package/skills/checklists/cyfrin-best-practices-upgrades/SKILL.md +157 -0
  9. package/skills/checklists/cyfrin-defi-core/SKILL.md +373 -0
  10. package/skills/checklists/cyfrin-defi-integrations/SKILL.md +412 -0
  11. package/skills/checklists/cyfrin-gas/SKILL.md +55 -0
  12. package/skills/checklists/general-audit/SKILL.md +433 -0
  13. package/skills/methodology/audit-workflow/SKILL.md +129 -0
  14. package/skills/methodology/report-template/SKILL.md +190 -0
  15. package/skills/methodology/severity-classification/SKILL.md +179 -0
  16. package/skills/protocol-patterns/amm-dex/SKILL.md +229 -0
  17. package/skills/protocol-patterns/bridges-cross-chain/SKILL.md +317 -0
  18. package/skills/protocol-patterns/dao-governance/SKILL.md +281 -0
  19. package/skills/protocol-patterns/lending-borrowing/SKILL.md +221 -0
  20. package/skills/protocol-patterns/staking-vesting/SKILL.md +247 -0
  21. package/skills/references/exploit-reference/SKILL.md +259 -0
  22. package/skills/references/smartbugs-examples/SKILL.md +296 -0
  23. package/skills/vulnerability-patterns/access-control/SKILL.md +298 -0
  24. package/skills/vulnerability-patterns/arbitrary-storage-location/SKILL.md +59 -0
  25. package/skills/vulnerability-patterns/assert-violation/SKILL.md +59 -0
  26. package/skills/vulnerability-patterns/asserting-contract-from-code-size/SKILL.md +61 -0
  27. package/skills/vulnerability-patterns/authorization-txorigin/SKILL.md +55 -0
  28. package/skills/vulnerability-patterns/default-visibility/SKILL.md +62 -0
  29. package/skills/vulnerability-patterns/delegatecall-untrusted-callee/SKILL.md +60 -0
  30. package/skills/vulnerability-patterns/dos-gas-limit/SKILL.md +59 -0
  31. package/skills/vulnerability-patterns/dos-revert/SKILL.md +72 -0
  32. package/skills/vulnerability-patterns/flash-loan-attacks/SKILL.md +249 -0
  33. package/skills/vulnerability-patterns/floating-pragma/SKILL.md +51 -0
  34. package/skills/vulnerability-patterns/hash-collision/SKILL.md +52 -0
  35. package/skills/vulnerability-patterns/inadherence-to-standards/SKILL.md +61 -0
  36. package/skills/vulnerability-patterns/incorrect-constructor/SKILL.md +60 -0
  37. package/skills/vulnerability-patterns/incorrect-inheritance-order/SKILL.md +59 -0
  38. package/skills/vulnerability-patterns/insufficient-gas-griefing/SKILL.md +61 -0
  39. package/skills/vulnerability-patterns/lack-of-precision/SKILL.md +61 -0
  40. package/skills/vulnerability-patterns/logic-errors/SKILL.md +333 -0
  41. package/skills/vulnerability-patterns/missing-protection-signature-replay/SKILL.md +60 -0
  42. package/skills/vulnerability-patterns/msgvalue-loop/SKILL.md +66 -0
  43. package/skills/vulnerability-patterns/off-by-one/SKILL.md +67 -0
  44. package/skills/vulnerability-patterns/oracle-manipulation/SKILL.md +252 -0
  45. package/skills/vulnerability-patterns/outdated-compiler-version/SKILL.md +65 -0
  46. package/skills/vulnerability-patterns/overflow-underflow/SKILL.md +61 -0
  47. package/skills/vulnerability-patterns/reentrancy/SKILL.md +266 -0
  48. package/skills/vulnerability-patterns/shadowing-state-variables/SKILL.md +72 -0
  49. package/skills/vulnerability-patterns/signature-malleability/SKILL.md +59 -0
  50. package/skills/vulnerability-patterns/unbounded-return-data/SKILL.md +63 -0
  51. package/skills/vulnerability-patterns/unchecked-return-values/SKILL.md +52 -0
  52. package/skills/vulnerability-patterns/unencrypted-private-data-on-chain/SKILL.md +65 -0
  53. package/skills/vulnerability-patterns/unexpected-ecrecover-null-address/SKILL.md +61 -0
  54. package/skills/vulnerability-patterns/uninitialized-storage-pointer/SKILL.md +63 -0
  55. package/skills/vulnerability-patterns/unsafe-low-level-call/SKILL.md +56 -0
  56. package/skills/vulnerability-patterns/unsecure-signatures/SKILL.md +80 -0
  57. package/skills/vulnerability-patterns/unsupported-opcodes/SKILL.md +69 -0
  58. package/skills/vulnerability-patterns/unused-variables/SKILL.md +70 -0
  59. package/skills/vulnerability-patterns/use-of-deprecated-functions/SKILL.md +81 -0
  60. package/skills/vulnerability-patterns/weak-sources-randomness/SKILL.md +77 -0
  61. package/skills/vulnerability-patterns/weird-tokens/SKILL.md +294 -0
  62. package/src/agents/argus-prompt.ts +407 -0
  63. package/src/agents/pythia-prompt.ts +134 -0
  64. package/src/agents/scribe-prompt.ts +87 -0
  65. package/src/agents/sentinel-prompt.ts +133 -0
  66. package/src/cli/cli-program.ts +67 -0
  67. package/src/cli/commands/doctor.ts +83 -0
  68. package/src/cli/commands/init.ts +46 -0
  69. package/src/cli/commands/install.ts +55 -0
  70. package/src/cli/index.ts +13 -0
  71. package/src/cli/tui-prompts.ts +75 -0
  72. package/src/cli/types.ts +9 -0
  73. package/src/config/index.ts +3 -0
  74. package/src/config/loader.ts +36 -0
  75. package/src/config/schema.ts +82 -0
  76. package/src/config/types.ts +4 -0
  77. package/src/constants/defaults.ts +6 -0
  78. package/src/create-hooks.ts +84 -0
  79. package/src/create-managers.ts +26 -0
  80. package/src/create-tools.ts +30 -0
  81. package/src/features/audit-enforcer/audit-enforcer.ts +34 -0
  82. package/src/features/audit-enforcer/index.ts +1 -0
  83. package/src/features/background-agent/background-manager.ts +200 -0
  84. package/src/features/background-agent/index.ts +1 -0
  85. package/src/features/context-monitor/context-monitor.ts +48 -0
  86. package/src/features/context-monitor/index.ts +4 -0
  87. package/src/features/context-monitor/tool-output-truncator.ts +17 -0
  88. package/src/features/error-recovery/index.ts +2 -0
  89. package/src/features/error-recovery/session-recovery.ts +27 -0
  90. package/src/features/error-recovery/tool-error-recovery.ts +35 -0
  91. package/src/features/index.ts +5 -0
  92. package/src/features/persistent-state/audit-state-manager.ts +121 -0
  93. package/src/features/persistent-state/index.ts +1 -0
  94. package/src/hooks/compaction-hook.ts +50 -0
  95. package/src/hooks/config-handler.ts +116 -0
  96. package/src/hooks/event-hook-v2.ts +93 -0
  97. package/src/hooks/event-hook.ts +74 -0
  98. package/src/hooks/hook-system.ts +9 -0
  99. package/src/hooks/index.ts +5 -0
  100. package/src/hooks/knowledge-sync-hook.ts +57 -0
  101. package/src/hooks/safe-create-hook.ts +15 -0
  102. package/src/hooks/system-prompt-hook.ts +126 -0
  103. package/src/hooks/tool-tracking-hook.ts +234 -0
  104. package/src/hooks/types.ts +16 -0
  105. package/src/index.ts +36 -0
  106. package/src/knowledge/scvd-client.ts +242 -0
  107. package/src/knowledge/scvd-index.ts +183 -0
  108. package/src/knowledge/scvd-sync.ts +85 -0
  109. package/src/managers/index.ts +1 -0
  110. package/src/managers/types.ts +85 -0
  111. package/src/plugin-interface.ts +38 -0
  112. package/src/shared/binary-utils.ts +63 -0
  113. package/src/shared/deep-merge.ts +71 -0
  114. package/src/shared/file-utils.ts +56 -0
  115. package/src/shared/index.ts +5 -0
  116. package/src/shared/jsonc-parser.ts +39 -0
  117. package/src/shared/logger.ts +36 -0
  118. package/src/state/audit-state.ts +27 -0
  119. package/src/state/finding-store.ts +126 -0
  120. package/src/state/plugin-state.ts +14 -0
  121. package/src/state/types.ts +61 -0
  122. package/src/tools/contract-analyzer-tool.ts +184 -0
  123. package/src/tools/forge-fuzz-tool.ts +311 -0
  124. package/src/tools/forge-test-tool.ts +397 -0
  125. package/src/tools/pattern-checker-tool.ts +337 -0
  126. package/src/tools/report-generator-tool.ts +308 -0
  127. package/src/tools/slither-tool.ts +465 -0
  128. package/src/tools/solodit-search-tool.ts +131 -0
  129. package/src/tools/sync-knowledge-tool.ts +116 -0
  130. package/src/utils/project-detector.ts +133 -0
  131. package/src/utils/solidity-parser.ts +174 -0
@@ -0,0 +1,70 @@
1
+ ---
2
+ name: unused-variables
3
+ description: - Contract declares state variables, local variables, function parameters, or imports that are never referenced
4
+ ---
5
+ <!-- Source: kadenzipfel/smart-contract-vulnerabilities (MIT) -->
6
+
7
+ # Presence of Unused Variables
8
+
9
+ ## Preconditions
10
+ - Contract declares state variables, local variables, function parameters, or imports that are never referenced
11
+ - OR: return values from function calls are silently discarded
12
+
13
+ ## Vulnerable Pattern
14
+ ```solidity
15
+ contract Vault {
16
+ uint256 public totalDeposits;
17
+ uint256 public unusedCounter; // Declared but never read or written
18
+
19
+ function deposit(uint256 amount, bytes memory data) external {
20
+ // `data` parameter never used — possible missing validation
21
+ totalDeposits += amount;
22
+ }
23
+
24
+ function process() external {
25
+ // Return value from transfer silently discarded
26
+ // This may indicate missing success check
27
+ IERC20(token).transfer(recipient, amount);
28
+
29
+ uint256 result = _calculate();
30
+ // `result` computed but never used — missing logic?
31
+ }
32
+ }
33
+ ```
34
+
35
+ ## Detection Heuristics
36
+ 1. Search for state variables that are never referenced in any function (only declared)
37
+ 2. Search for function parameters that are never used in the function body
38
+ 3. Search for local variables that are assigned but never read
39
+ 4. Check for return values from external calls that are not captured or checked
40
+ 5. For each unused variable, determine: is it dead code (safe to remove) or does it indicate missing logic (a bug)?
41
+ 6. Check compiler warnings for unused variable alerts
42
+
43
+ ## False Positives
44
+ - The variable is part of an interface implementation and must be declared for signature compatibility even if unused
45
+ - The variable is used in a commented-out or conditional compilation path
46
+ - The variable is reserved for future use and documented as such
47
+ - Function parameters prefixed with `_` to explicitly mark as unused (e.g., `function hook(uint256 /* _amount */)`)
48
+
49
+ ## Remediation
50
+ - For dead code: remove the unused variable entirely
51
+ - For missing logic: implement the intended use (e.g., check the return value, use the parameter for validation)
52
+ - For interface-required but unused parameters: use the unnamed parameter syntax
53
+ ```solidity
54
+ // Remove dead state variables
55
+ // uint256 public unusedCounter; — DELETE
56
+
57
+ // Unnamed parameters for interface compliance
58
+ function onERC721Received(
59
+ address, // operator — unused
60
+ address, // from — unused
61
+ uint256, // tokenId — unused
62
+ bytes memory // data — unused
63
+ ) external pure returns (bytes4) {
64
+ return this.onERC721Received.selector;
65
+ }
66
+
67
+ // Check return values — use SafeERC20 for non-compliant tokens
68
+ bool success = IERC20(token).transfer(recipient, amount);
69
+ require(success);
70
+ ```
@@ -0,0 +1,81 @@
1
+ ---
2
+ name: use-of-deprecated-functions
3
+ description: - Contract uses Solidity functions, keywords, or language features that have been deprecated or removed
4
+ ---
5
+ <!-- Source: kadenzipfel/smart-contract-vulnerabilities (MIT) -->
6
+
7
+ # Use of Deprecated Functions
8
+
9
+ ## Preconditions
10
+ - Contract uses Solidity functions, keywords, or language features that have been deprecated or removed
11
+ - The deprecated feature may behave differently than expected or may not compile on newer Solidity versions
12
+
13
+ ## Vulnerable Pattern
14
+ ```solidity
15
+ pragma solidity ^0.4.24;
16
+
17
+ contract Legacy {
18
+ function destroy() external {
19
+ // suicide is deprecated — renamed to selfdestruct
20
+ // selfdestruct itself is now deprecated post-Dencun
21
+ suicide(msg.sender);
22
+ }
23
+
24
+ function getHash(bytes memory data) external view returns (bytes32) {
25
+ return sha3(data); // Deprecated — use keccak256
26
+ }
27
+
28
+ function getBlockHash(uint256 n) external view returns (bytes32) {
29
+ return block.blockhash(n); // Deprecated — use blockhash(n)
30
+ }
31
+
32
+ function getRemainingGas() external view returns (uint256) {
33
+ return msg.gas; // Deprecated — use gasleft()
34
+ }
35
+ }
36
+ ```
37
+
38
+ | Deprecated | Replacement |
39
+ |---|---|
40
+ | `suicide(address)` | `selfdestruct(address)` (also deprecated) |
41
+ | `block.blockhash(uint)` | `blockhash(uint)` |
42
+ | `sha3(...)` | `keccak256(...)` |
43
+ | `callcode(...)` | `delegatecall(...)` |
44
+ | `throw` | `revert()` |
45
+ | `msg.gas` | `gasleft()` |
46
+ | `constant` (function modifier) | `view` |
47
+ | `var` | Explicit type name |
48
+
49
+ ## Detection Heuristics
50
+ 1. Search for each deprecated keyword: `suicide`, `sha3`, `block.blockhash`, `callcode`, `throw`, `msg.gas`, `constant` (as function modifier), `var`
51
+ 2. Search for `selfdestruct` — while it's the replacement for `suicide`, it is itself deprecated post-Dencun and non-functional on some chains
52
+ 3. Check compiler warnings for deprecation notices
53
+ 4. Flag any usage and recommend the modern replacement
54
+
55
+ ## False Positives
56
+ - The deprecated function appears in comments or documentation, not in executable code
57
+ - The contract is intentionally targeting an old Solidity version where the deprecated feature is still standard
58
+ - Interface definitions that reference deprecated patterns for backward compatibility
59
+
60
+ ## Remediation
61
+ - Replace each deprecated function with its modern equivalent (see table above)
62
+ - For `selfdestruct`: remove reliance entirely, as it is deprecated and non-functional on some chains post-Dencun
63
+ - Upgrade the Solidity version to benefit from compiler enforcement of modern syntax
64
+ ```solidity
65
+ // Modern equivalents
66
+ pragma solidity 0.8.24;
67
+
68
+ contract Modern {
69
+ function getHash(bytes memory data) external pure returns (bytes32) {
70
+ return keccak256(data);
71
+ }
72
+
73
+ function getBlockHash(uint256 n) external view returns (bytes32) {
74
+ return blockhash(n);
75
+ }
76
+
77
+ function getRemainingGas() external view returns (uint256) {
78
+ return gasleft();
79
+ }
80
+ }
81
+ ```
@@ -0,0 +1,77 @@
1
+ ---
2
+ name: weak-sources-randomness
3
+ description: - Contract generates \"random\" values using on-chain data: `block.timestamp`, `blockhash`, `block.difficulty` / `block.prevrandao`, `block.number`, or combinations thereof
4
+ ---
5
+ <!-- Source: kadenzipfel/smart-contract-vulnerabilities (MIT) -->
6
+
7
+ # Weak Sources of Randomness from Chain Attributes
8
+
9
+ ## Preconditions
10
+ - Contract generates "random" values using on-chain data: `block.timestamp`, `blockhash`, `block.difficulty` / `block.prevrandao`, `block.number`, or combinations thereof
11
+ - The random value determines outcomes with economic value (lotteries, games, minting, distributions)
12
+
13
+ ## Vulnerable Pattern
14
+ ```solidity
15
+ function drawLottery() external {
16
+ // All inputs are deterministic and publicly visible
17
+ // Another contract can compute the same value in the same tx
18
+ uint256 random = uint256(keccak256(abi.encodePacked(
19
+ block.timestamp,
20
+ block.prevrandao,
21
+ msg.sender
22
+ ))) % 100;
23
+
24
+ if (random < 5) {
25
+ _payWinner(msg.sender);
26
+ }
27
+ }
28
+
29
+ // Attacker contract
30
+ contract Exploit {
31
+ function attack(Lottery target) external {
32
+ // Compute the same "random" value before calling
33
+ uint256 random = uint256(keccak256(abi.encodePacked(
34
+ block.timestamp,
35
+ block.prevrandao,
36
+ address(this)
37
+ ))) % 100;
38
+
39
+ // Only call if we'll win
40
+ if (random < 5) {
41
+ target.drawLottery();
42
+ }
43
+ }
44
+ }
45
+ ```
46
+
47
+ ## Detection Heuristics
48
+ 1. Search for `block.timestamp`, `block.prevrandao`, `block.difficulty`, `blockhash`, `block.number` used as inputs to `keccak256` or arithmetic operations producing a "random" value
49
+ 2. Check if the resulting value determines an outcome with economic impact (winner selection, token distribution, NFT rarity, game outcome)
50
+ 3. If randomness is derived exclusively from on-chain data, flag it — a contract in the same transaction can compute the identical value
51
+ 4. Check if `blockhash` is used for a future block (returns 0 for blocks not yet mined) or a block older than 256 blocks (also returns 0)
52
+ 5. Check if validators/miners can influence the inputs to bias the outcome
53
+
54
+ ## False Positives
55
+ - Chainlink VRF or another verifiable randomness oracle is used
56
+ - On-chain data is combined with an off-chain commit-reveal scheme (the on-chain part alone doesn't determine the outcome)
57
+ - The randomness doesn't determine anything with economic value
58
+ - `block.prevrandao` on PoS Ethereum provides sufficient entropy for the specific use case (not for high-value outcomes)
59
+
60
+ ## Remediation
61
+ - Use Chainlink VRF (Verifiable Random Function) for provably fair randomness
62
+ - Implement a commit-reveal scheme: users commit hashed choices, reveal in a later block
63
+ - Never use `block.timestamp`, `blockhash`, or `block.prevrandao` alone for randomness in high-value contexts
64
+ ```solidity
65
+ import {VRFConsumerBaseV2} from "@chainlink/contracts/src/v0.8/vrf/VRFConsumerBaseV2.sol";
66
+
67
+ contract FairLottery is VRFConsumerBaseV2 {
68
+ function requestRandom() external {
69
+ requestRandomWords(keyHash, subId, confirmations, gasLimit, 1);
70
+ }
71
+
72
+ function fulfillRandomWords(uint256, uint256[] memory randomWords) internal override {
73
+ uint256 winner = randomWords[0] % participants.length;
74
+ _payWinner(participants[winner]);
75
+ }
76
+ }
77
+ ```
@@ -0,0 +1,294 @@
1
+ ---
2
+ name: weird-tokens
3
+ description: Non-standard ERC20 behaviors, integration pitfalls, and token-handling safeguards.
4
+ ---
5
+ <!-- Source: DeFiFoFum/fofum-solidity-skills (MIT) -->
6
+
7
+ # Weird ERC20 Tokens Reference
8
+
9
+ Tokens that don't behave like standard ERC20. Integrating with these requires special handling.
10
+
11
+ ## Quick Reference Table
12
+
13
+ | Pattern | Example Tokens | Risk | Mitigation |
14
+ |---------|---------------|------|------------|
15
+ | Missing return values | USDT, BNB, OMG | Silent failures | SafeERC20 |
16
+ | Fee on transfer | STA, PAXG, SAFEMOON | Balance mismatch | Measure before/after |
17
+ | Rebasing | AMPL, stETH, OHM | Cached balance wrong | Don't cache balances |
18
+ | Pausable | BNB, ZIL | DOS | Handle gracefully |
19
+ | Blocklist | USDC, USDT | User funds frozen | Document risk |
20
+ | Upgradeable | USDC, USDT | Behavior can change | Monitor upgrades |
21
+ | Flash mintable | DAI | Infinite supply attacks | Check total supply |
22
+ | Multiple addresses | TUSD | Accounting errors | Verify canonical address |
23
+ | Low decimals | USDC (6), GUSD (2) | Precision loss | Handle decimals explicitly |
24
+ | High decimals | YAM-V2 (24) | Overflow risk | Check bounds |
25
+ | Approval race | USDT, KNC | Front-running | Set to 0 first |
26
+ | Revert on zero | LEND | Unexpected reverts | Check amount > 0 |
27
+ | Non-string metadata | MKR | Type errors | Handle bytes32 |
28
+ | ERC777 hooks | imBTC | Reentrancy | Treat as untrusted |
29
+
30
+ ---
31
+
32
+ ## Detailed Patterns
33
+
34
+ ### 1. Missing Return Values
35
+
36
+ **Tokens:** USDT, BNB, OMG, BADGER
37
+
38
+ **Problem:**
39
+ ```solidity
40
+ // Returns nothing, but ERC20 interface expects bool
41
+ function transfer(address to, uint value) public {
42
+ // ... no return statement
43
+ }
44
+ ```
45
+
46
+ **Exploit:**
47
+ ```solidity
48
+ // This compiles but fails at runtime for USDT
49
+ IERC20(usdt).transfer(to, amount); // Reverts: expected return data
50
+ ```
51
+
52
+ **Fix:**
53
+ ```solidity
54
+ import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
55
+ using SafeERC20 for IERC20;
56
+
57
+ IERC20(usdt).safeTransfer(to, amount); // Works
58
+ ```
59
+
60
+ ---
61
+
62
+ ### 2. Fee on Transfer
63
+
64
+ **Tokens:** STA, PAXG, SAFEMOON, most "reflection" tokens
65
+
66
+ **Problem:**
67
+ ```solidity
68
+ function transfer(address to, uint value) public returns (bool) {
69
+ uint fee = value * feePercent / 100;
70
+ _transfer(msg.sender, feeCollector, fee);
71
+ _transfer(msg.sender, to, value - fee);
72
+ return true;
73
+ }
74
+ ```
75
+
76
+ **Exploit:**
77
+ ```solidity
78
+ // User deposits 100, protocol credits 100
79
+ // But only 98 actually arrived (2% fee)
80
+ // User can withdraw 100, stealing 2 from protocol
81
+ function deposit(uint amount) external {
82
+ token.transferFrom(msg.sender, address(this), amount);
83
+ balances[msg.sender] += amount; // WRONG!
84
+ }
85
+ ```
86
+
87
+ **Fix:**
88
+ ```solidity
89
+ function deposit(uint amount) external {
90
+ uint balanceBefore = token.balanceOf(address(this));
91
+ token.transferFrom(msg.sender, address(this), amount);
92
+ uint received = token.balanceOf(address(this)) - balanceBefore;
93
+ balances[msg.sender] += received; // Credit actual amount
94
+ }
95
+ ```
96
+
97
+ ---
98
+
99
+ ### 3. Rebasing Tokens
100
+
101
+ **Tokens:** AMPL, stETH (rebases), OHM, AAVE aTokens
102
+
103
+ **Problem:**
104
+ ```solidity
105
+ // Balance changes without any transfers
106
+ function rebase(int supplyDelta) external {
107
+ totalSupply = totalSupply + supplyDelta;
108
+ // All balances scale proportionally
109
+ }
110
+ ```
111
+
112
+ **Exploit:**
113
+ ```solidity
114
+ // Protocol caches balance
115
+ uint cachedBalance = steth.balanceOf(address(this));
116
+
117
+ // ... time passes, rebase happens ...
118
+
119
+ // Cached balance is now wrong
120
+ // Can lead to accounting errors, insolvency
121
+ ```
122
+
123
+ **Fix:**
124
+ - Don't cache balances
125
+ - Use wrapper tokens (wstETH instead of stETH)
126
+ - Track shares, not absolute amounts
127
+
128
+ ---
129
+
130
+ ### 4. Pausable Tokens
131
+
132
+ **Tokens:** BNB, ZIL, USDC (admin can pause)
133
+
134
+ **Problem:**
135
+ ```solidity
136
+ modifier whenNotPaused() {
137
+ require(!paused, "Paused");
138
+ _;
139
+ }
140
+
141
+ function transfer(address to, uint value) public whenNotPaused {
142
+ // ...
143
+ }
144
+ ```
145
+
146
+ **Impact:**
147
+ - Protocol can be DOS'd if token pauses
148
+ - User funds stuck
149
+ - Liquidations fail
150
+
151
+ **Fix:**
152
+ - Have emergency withdrawal that doesn't rely on transfers
153
+ - Document risk to users
154
+ - Consider timelock on protocol side
155
+
156
+ ---
157
+
158
+ ### 5. Blocklist/Blacklist Tokens
159
+
160
+ **Tokens:** USDC, USDT (compliance blacklists)
161
+
162
+ **Problem:**
163
+ ```solidity
164
+ function transfer(address to, uint value) public {
165
+ require(!blacklisted[msg.sender], "Blacklisted");
166
+ require(!blacklisted[to], "Blacklisted");
167
+ // ...
168
+ }
169
+ ```
170
+
171
+ **Impact:**
172
+ - Blacklisted users can't withdraw
173
+ - Protocol holding funds for blacklisted user is stuck
174
+
175
+ **Fix:**
176
+ - Document risk
177
+ - Consider allowing admin rescue to different address
178
+ - Use wrapper tokens where possible
179
+
180
+ ---
181
+
182
+ ### 6. Upgradeable Tokens
183
+
184
+ **Tokens:** USDC, USDT, many newer tokens
185
+
186
+ **Problem:**
187
+ - Token logic can change after integration
188
+ - New fee mechanisms could be added
189
+ - Pausability could be added
190
+
191
+ **Impact:**
192
+ - Your integration assumptions may break post-upgrade
193
+
194
+ **Fix:**
195
+ - Monitor token upgrades
196
+ - Have upgrade handlers in your protocol
197
+ - Test against upgraded implementations
198
+
199
+ ---
200
+
201
+ ### 7. Flash Mintable Tokens
202
+
203
+ **Tokens:** DAI (flash mint), some wrapped tokens
204
+
205
+ **Problem:**
206
+ ```solidity
207
+ function flashLoan(uint amount) external {
208
+ _mint(msg.sender, amount);
209
+ IFlashBorrower(msg.sender).onFlashLoan(amount);
210
+ _burn(msg.sender, amount);
211
+ }
212
+ ```
213
+
214
+ **Impact:**
215
+ - Attacker can temporarily have infinite tokens
216
+ - Breaks governance (voting with flash minted tokens)
217
+ - Price manipulation
218
+
219
+ **Fix:**
220
+ - Use TWAP for prices
221
+ - Snapshot voting tokens before proposals
222
+ - Check totalSupply before/after for sanity
223
+
224
+ ---
225
+
226
+ ### 8. Approval Race Condition
227
+
228
+ **Tokens:** USDT requires setting to 0 first
229
+
230
+ **Problem:**
231
+ ```solidity
232
+ // USDT's approve reverts if allowance > 0 and newValue > 0
233
+ function approve(address spender, uint value) public {
234
+ require(value == 0 || allowance[msg.sender][spender] == 0);
235
+ // ...
236
+ }
237
+ ```
238
+
239
+ **Fix:**
240
+ ```solidity
241
+ // Always set to 0 first
242
+ token.approve(spender, 0);
243
+ token.approve(spender, newAmount);
244
+
245
+ // Or use SafeERC20
246
+ token.safeIncreaseAllowance(spender, amount);
247
+ ```
248
+
249
+ ---
250
+
251
+ ### 9. ERC777 Hooks (Reentrancy)
252
+
253
+ **Tokens:** imBTC, any ERC777
254
+
255
+ **Problem:**
256
+ ```solidity
257
+ // ERC777 calls hooks on sender and receiver
258
+ function _send(address from, address to, uint256 amount) internal {
259
+ _callTokensToSend(from, to, amount); // HOOK - reentrancy!
260
+ _transfer(from, to, amount);
261
+ _callTokensReceived(from, to, amount); // HOOK - reentrancy!
262
+ }
263
+ ```
264
+
265
+ **Impact:**
266
+ - Reentrancy even without ETH transfers
267
+ - imBTC was exploited via this
268
+
269
+ **Fix:**
270
+ - Treat ERC777 transfers as untrusted external calls
271
+ - Apply CEI pattern
272
+ - Use ReentrancyGuard
273
+
274
+ ---
275
+
276
+ ## Integration Checklist
277
+
278
+ When integrating any token:
279
+
280
+ - [ ] Check for missing return values (SafeERC20)
281
+ - [ ] Check for fee-on-transfer (measure actual received)
282
+ - [ ] Check for rebasing (don't cache balances)
283
+ - [ ] Check for pausability (emergency paths)
284
+ - [ ] Check for blocklists (document risk)
285
+ - [ ] Check for upgradeability (monitor changes)
286
+ - [ ] Check for flash minting (use TWAP)
287
+ - [ ] Check for ERC777 hooks (reentrancy guard)
288
+ - [ ] Check decimals (6, 8, 18, 24 all exist)
289
+ - [ ] Check approval behavior (set to 0 first for USDT)
290
+
291
+ ## Resources
292
+
293
+ - **weird-erc20:** <https://github.com/d-xo/weird-erc20>
294
+ - **Token Integration Checklist:** <https://github.com/crytic/building-secure-contracts/blob/master/development-guidelines/token_integration.md>