rounding-direction-truncation
Use when auditing integer maths in a contract that divides, multiplies with scaling, or converts between decimals. Checks each division rounds in the protocol's favour and guards against truncation to zero.
- License 许可
- MIT
- 最近更新
- 2026-11-12
- Stars
- ★ 81
- Forks
- 17
01 前言 Front Matter
- name
- rounding-direction-truncation
- description
- Use when auditing integer maths in a contract that divides, multiplies with scaling, or converts between decimals. Checks each division rounds in the protocol's favour and guards against truncation to zero.
02 资源文件 3
- 许可证LICENSE1.0 KB
- 参考文档SOURCE.md355 B
- 参考文档TRUST.auto.yaml2.2 KB
03 SKILL.md 正文
Rounding direction and truncation
Solidity integer division truncates toward zero, so every a / b silently favours one party — the review is to decide which party and whether that is the safe one.
Procedure
- Find all divisions and scale conversions:
grep -nE '/ *[0-9a-zA-Z_(]|/ 1e|mulDiv|wadDiv|rayDiv' -r src/. - For each, name the direction that is safe: shares minted to a user round DOWN, assets paid out to a user round DOWN, debt owed by a user rounds UP.
- Confirm the wrap: in OpenZeppelin
Math.mulDiv, passMath.Rounding.Floorwhen the user receives the result andMath.Rounding.Ceilwhen the protocol receives it. - Check the multiply-before-divide rule:
(a * b) / cmust not overflow; usemulDiv, which widens to 512-bit. - Hunt truncation-to-zero: any
amount / ratewhererate > amountreturns 0, letting a user pay zero for a non-zero asset. - Check fee maths:
fee = amount * feeBps / 10_000rounds down, so the protocol under-collects; verify a dust attacker cannot loop withamount = 1and payfee = 0. - Test the boundary with a fuzz test that asserts monotonicity:
function testFuzz_noFreeShares(uint96 assets) public {
uint256 shares = vault.previewDeposit(assets);
if (assets > 0) assertGt(shares + vault.totalSupply(), 0);
}
- Confirm rounding is applied after aggregation, not per-leg, in multi-hop conversion functions.
- Verify a decimal conversion (
1e6USDC to1e18shares) uses10 ** (18 - 6)and cannot be reversed by rounding. - Record each division, its direction, and the party that benefits.
Pitfalls
previewX(view) andX(state-changing) use different rounding; integrators trust the wrong one and over-withdraw.mulDivdefault rounding is Floor; using it for a debt calculation rounds the attacker's debt down every block.- Percentage fee computed on a per-second drip: truncation to zero makes a flash-loan in-out free in the same block.
- Casting
uint256touint128/int128without a bounds check wraps silently. - Combining two truncated values (
a/b + c/d) when(a*d + b*c)/(b*d)was intended.
Verification
forge test --match-test "testFuzz.*[Rr]ound" -vv
Pass: the fuzz run reports 256+ runs with no counterexample. Add fail_on_revert = true under [fuzz] in foundry.toml so a revert is a failure, not a skip.
Report each division site, its rounding direction, and the benefiting party.
04 同仓库更多 Skills
recipe-performance
Diagnose a specific MetaMask user flow's real-app performance and Sentry critical-user-flow telemetry with deterministic mm-harness recipes. Use for CUF boundaries, cold/warm/background-resume behavior, latency regressions, lifecycle tags, duplicate or blocking network requests, long tasks, layout/paint cost, screen redraws, React rerenders, or browser trace analysis where tests alone cannot prove the real app.
mexc-spot-websocket
MEXC Spot WebSocket workflows for public streams, protobuf handling, depth maintenance, listen keys, and private streams without exposing API keys.
mexc-spot-rest
MEXC Spot REST workflows for public data, signed account requests, orders, wallet/admin actions, and secure signing without exposing API keys.
mexc-futures-websocket
MEXC Futures WebSocket workflows for public streams, private account/order/position streams, ping/pong, subscriptions, and depth maintenance.
0xklen-version-and-refresh-sanctions-lists
暂无简介
verify-tests-cover-changed-lines
Use when a PR adds code that the existing suite may not exercise. Measures patch coverage — the share of newly changed lines hit by tests — before approving.