iktok90-design/ai-smart-contract-auditor/fee-on-transfer

Claude Code and agent skill by iktok90-design/ai-smart-contract-auditor

Trust tier 3
  • community
Source check pending

Checking that the SKILL.md file is still in the repository.

Detect fee-on-transfer / deflationary / rebasing token accounting bugs — crediting the *passed amount* instead of the measured balance delta. Activate whenever code calls transfer/transferFrom and then credits, mints shares for, or records the literal amount argument, in deposits, AMM swaps, lending collateral, vaults, staking, or bridges — without measuring balanceAfter - balanceBefore.

Install

npx vskill@latest install iktok90-design/ai-smart-contract-auditor/fee-on-transfer

SKILL.md

Fee-on-transfer token accounting detection

When this applies

Trigger on any of:

  • Deposit/stake/addLiquidity that records the amount argument after transferFrom
  • Vault/ERC-4626 deposit minting shares proportional to the requested assets, not received
  • AMM/router updating reserves with the input amount rather than actual receipt
  • Lending protocols crediting collateral by passed amount
  • Bridges locking/burning amount then minting the same amount on the far side
  • Any flow assuming received == amount for arbitrary ERC-20s

Detection patterns

Credit passed amount, not delta (HIGH)
solidity
function deposit(uint256 amount) external {
token.transferFrom(msg.sender, address(this), amount);
balanceOf[msg.sender] += amount; // ← amount, but FoT token delivered less
totalDeposited += amount;
}

Signal: the contract believes it holds more than it does. On a fee-on-transfer token (USDT with fee switch enabled, PAXG, many meme tokens), totalDeposited exceeds the real balance — last withdrawers are insolvent, or an attacker mints excess shares/LP.

AMM reserve desync (HIGH)

Router records input amountIn into reserves but the pair received amountIn - fee. k invariant is computed on phantom reserves, mispricing the swap and letting an attacker drain the shortfall over time (the Uniswap-V2-style "supports FoT" *SupportingFeeOnTransferTokens functions exist precisely because of this).

Rebasing double-count (MEDIUM / HIGH)
solidity
uint256 shares = amount * totalShares / totalAssets; // totalAssets from stored var

Signal: stored totalAssets vs live token.balanceOf(this) diverge as a positive-rebasing token (stETH, aTokens, OHM) grows. Crediting against the stale stored figure under- or over-mints shares; an attacker times deposits around rebase.

Bridge mint mismatch (CRITICAL)

Lock amount on chain A, emit message, mint amount on chain B — but only amount - fee was locked. Repeated deposits accumulate an unbacked mint surplus that can be withdrawn on A by honest users, draining the lockbox.

Severity rubric

PatternSeverityNotes
Bridge mints unbacked surplusCriticalCross-chain insolvency
Vault/LP shares minted on phantom amountHighDirect over-mint, fund loss
AMM reserve recorded as passed amountHighMispricing, drainable shortfall
Lending collateral over-creditedHighUnder-collateralized borrow
Rebasing stored-vs-live totalAssets driftMediumTiming-dependent
FoT token on a hard whitelist of non-FoT tokensInfoSurface closed by policy

Remediation patterns

  1. Measure the delta: uint256 before = token.balanceOf(address(this)); token.transferFrom(...); uint256 received = token.balanceOf(address(this)) - before; and credit received.
  2. Reject FoT on entry — if received != amount, revert (OpenZeppelin SafeERC20 does not do this for you).
  3. Use live balance, not stored totals, for rebasing tokens, or wrap them (wstETH) so balances are non-rebasing.
  4. Token allowlist for assets known not to take a transfer fee; document the assumption.
  5. On bridges, lock the measured received amount and mint exactly that.

False-positive notes

  • A protocol that only ever handles a fixed, audited, non-FoT token (e.g. a WETH-only vault) is safe — note the assumption rather than flagging High.
  • *SupportingFeeOnTransferTokens router variants already measure deltas — don't flag.
  • Read-only quoting that never credits balances is unaffected.

Related

  • [[token-compatibility]] — broader weird-ERC20 behaviors (no return value, blocklists)
  • [[erc4626-inflation]] — share-mint math interacts with miscounted assets
  • [[cross-chain-messaging]] — bridge mint/lock mismatch surface

Security

  • Security scanPassed, 90 of 100Pattern checks on the skill's files.
  • Model reviewPassed

Quality evaluation

  • Task evaluationNot runNo evaluation yet. Run one in Skill Studio.

Source

Popularity

Repository stars
37
Repository forks
5
7-day trend score
18

Stars and forks are for the whole GitHub repository, not this skill alone. Not refreshed yet.

Works with

Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.

  • Claude Code
  • Cursor
  • GitHub Copilot
  • Windsurf
  • Codex
  • Gemini CLI
  • Cline
  • Amp
  • Roo Code
  • Goose
  • Continue
  • Kilo Code
  • Junie
  • Trae
  • OpenHands
  • Qwen Code
  • AI Agent
  • Tabnine Chat
  • Sourcegraph Cody
  • Amazon Q
  • Firebase Genkit
  • Sweep
  • Devin
  • Phind
  • Mentat
  • Claude Desktop
  • Aider
  • GPT Pilot
  • Plandex
  • bolt.new
  • v0
  • Replit Agent
  • Anse
  • TypingMind
  • BetterChatGPT
  • LibreChat
  • Warp AI
  • Pieces
  • Fig AI
Embed badge
vskill VERIFIED badge
[![vskill VERIFIED](https://verified-skill.com/api/v1/skills/iktok90-design/ai-smart-contract-auditor/fee-on-transfer/badge)](https://verified-skill.com/skills/iktok90-design/ai-smart-contract-auditor/fee-on-transfer)

Something wrong with this skill or its page? Tell us.