Skip to content

Standard Commission Calls

The standard commissionCall is the bread and butter of the protocol. It allows you to wrap a batch of transactions and attach a commission.

WHEN TO USE

Use this for simple, independent actions.

  • Example: "Deposit 100 USDC into Aave"
  • Example: "Buy 1 ETH NFT on OpenSea"

Do not use if you need the output of step 1 to be the input of step 2.

The Flow

  1. Fund: User sends ETH/Tokens to CommissionRoad.
  2. Execute: CommissionRoad executes the calls as msg.sender.
  3. Sweep: CommissionRoad sends the results back to the user.

Implementation

1. Encode your calls (including the Sweep!)

Since CommissionRoad performs the action, it usually receives the output tokens. You must instruct it to send them back to the user.

typescript
import { encodeFunctionData, parseEther } from "viem";

// A. The Action (e.g., Swap on Uniswap)
// Note: 'recipient' in the swap data should be CommissionRoad address (or user if supported)
const swapData = encodeFunctionData({ ... });

// B. The Sweep (Get tokens back to user)
const sweepData = encodeFunctionData({
    abi: commissionRoadAbi,
    functionName: "sweepERC20Token",
    args: [outputTokenAddress, userAddress]
});

const batchCallData = [
  { target: swapRouter, callData: swapData, value: 0n },
  { target: commissionRoadAddress, callData: sweepData, value: 0n } // Critical!
];

2. Calculate Commission and Call

typescript
await commissionRoad.write.commissionCall([
  batchCallData,
  nftId,
  ethAddress,
  commission,
], { value: totalEthNeeded });

Permit2 Integration

CommissionRoad works natively with Permit2, allowing you to pay commissions in any token and handle approvals efficiently.

WHY IT'S NICE

  • Single Approval: Users approve the Permit2 contract once per token.
  • Any Token: Pay commissions in USDC, DAI, or the token being swapped.

To use Permit2, simply include the permitTransferFrom call as the first call in your batchCallData.

typescript
// 1. Sign Permit
const signature = await signPermit2(user, permit, commissionRoadAddress);

// 2. Add as First Call
const permitCall = encodeFunctionData({
  abi: permit2Abi,
  functionName: "permitTransferFrom",
  args: [permit, transferDetails, userAddress, signature]
});

batchCallData.unshift({
    target: permit2Address,
    callData: permitCall,
    value: 0n
});

⚠️ Gotchas

  • Context: The target contract sees CommissionRoad as the msg.sender, not the user.
  • No Chaining: You cannot use the result of Call A in Call B.