Skip to content

Security Best Practices

This page covers important security considerations when integrating with CommissionRoad.

Always Collect a Commission

Critical Security Pattern

Always set commission to at least 1 wei — even if you intend to offer "free" transactions. A zero commission removes an important safety rail.

The Sweep Attack

When a commissionCall executes, CommissionRoad may hold tokens temporarily between calls in the batch. A malicious target contract could exploit this window:

  1. User submits a commissionCall with commission = 0
  2. Batch includes a call to a malicious contract, followed by a sweepERC20Token call
  3. The malicious contract re-enters or calls sweepERC20Token itself — draining the tokens before the user's sweep runs
  4. With commission = 0, the _collectCommissions step is a no-op — nothing reverts

Why a Nonzero Commission Prevents This

When commission > 0, CommissionRoad calls CommissionVault.depositCommission at the end of the transaction. For ERC20 commissions, the vault calls safeTransferFrom to pull tokens from CommissionRoad. If a malicious contract has already drained those tokens, safeTransferFrom reverts — taking the entire transaction with it.

The minimum commission acts as an implicit guard — it ensures the token balance is still intact at the end of execution.

typescript
// ✅ Safe: Always collect at least dust
const commission = 1n; // 1 wei — negligible cost, maximum protection

await commissionRoad.write.commissionCall([
  batchCallData,
  nftId,
  commissionToken,
  commission,
], { value: totalEthNeeded + commission });
typescript
// ❌ Unsafe: Zero commission removes the safety net
const commission = 0n;

await commissionRoad.write.commissionCall([
  batchCallData,
  nftId,
  commissionToken,
  commission, // No depositCommission call — sweep attacks possible
], { value: totalEthNeeded });

Rule of Thumb

If in doubt, set commission = 1. The cost is negligible (1 wei), but it guarantees that depositCommission runs and validates the contract's token balance before the transaction completes.

Use the Allowlist

The Allowlist is an opt-in feature that lets NFT owners restrict which contracts can be called through their NFT ID. Together with the nonzero commission rule above, the allowlist provides defense in depth:

LayerProtects AgainstHow
Nonzero commissionSweep attacksEnsures depositCommission runs, reverting if tokens were drained
AllowlistUnauthorized targetsBlocks calls to contracts not explicitly approved by the NFT owner

Setup

typescript
// 1. Enable the allowlist
await commissionRoad.write.setAllowlistEnabled([nftId, true]);

// 2. Only allow known good contracts
await commissionRoad.write.setAllowlist([nftId, uniswapRouter, true]);
await commissionRoad.write.setAllowlist([nftId, aaveLending, true]);

TIP

The allowlist also applies to EIP-7702 / Executor flows. You manage it in one place — on the CommissionRoad contract.