
Viem Sweep
- 16 installs
- Updated January 24, 2026
- melonask/viem-sweep-skills
Helps with ai & agent building tasks.
About
viem-sweep is a Claude Code skill for ai & agent building. It helps solo builders move faster with AI-assisted coding.
- viem-sweep
- AI & Agent Building
- AI-coding skill
Viem Sweep by the numbers
- 16 all-time installs (skills.sh)
- Ranked #11,068 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
- Data as of Aug 4, 2026 (Skillselion catalog sync)
npx skills add https://github.com/melonask/viem-sweep-skills --skill viem-sweepAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 16 |
|---|---|
| Last updated | January 24, 2026 |
| Repository | melonask/viem-sweep-skills ↗ |
What it does
Helps with ai & agent building tasks.
Files
Viem Sweep
Overview
This skill provides implementation patterns for advanced transaction strategies using viem v2. It covers methods for moving assets from multiple sources to a destination, ranging from simple private key transfers to advanced gas-optimized and signature-based patterns.
Strategy Selection Guide
Choose the appropriate strategy based on your requirements and infrastructure:
1. Legacy Strategy (Direct Transfer)
Best for: General use case with private keys.
- Pros: Works with any ERC20 token; simple logic.
- Cons: High gas cost (requires ETH on every source account); management of dust ETH.
- Mechanism: Admin funds source -> Source sends token.
2. Factory Strategy (CREATE2)
Best for: High-volume deposit addresses (e.g., exchanges).
- Pros: Lowest gas cost; clean address management; no private keys needed (just salt).
- Cons: Requires initial setup (factory contract); addresses must be generated by factory.
- Mechanism: Predict address -> Deploy (if needed) & Flush in one tx.
3. Permit Strategy (EIP-2612)
Best for: Gasless user experiences with compatible tokens (e.g., UNI, DAI).
- Pros: Gasless for user (relayer pays); single batch transaction.
- Cons: Token MUST support EIP-2612; requires private key signature.
- Mechanism: User signs Permit -> Admin submits batch.
4. Auth Strategy (EIP-3009)
Best for: USDC and other tokens supporting TransferWithAuthorization.
- Pros: Gasless for user; single batch transaction; handles non-sequential nonces (USDC).
- Cons: Token MUST support EIP-3009.
- Mechanism: User signs Authorization -> Admin submits batch.
5. EIP-7702 Strategy (Delegation)
Best for: Future-proofing and "upgrading" EOAs to smart contracts temporarily.
- Pros: Allows EOAs to act as contracts (batching, recovery, sponsored gas) without permanent migration.
- Cons: Requires chain support (Prague hardfork+).
- Mechanism: User signs delegation -> Admin executes tx with auth list.
Implementation Details
For detailed code examples, ABI snippets, and deep-dive explanations of each strategy, refer to the Strategies Reference. The underlying Solidity contract logic can be found in the Contracts Reference.
Usage
When implementing these strategies, ensure you have: 1. Viem v2 installed. 2. Access to a PublicClient (for reads/simulation) and WalletClient (for signing/sending). 3. Relevant ABI definitions (standard ERC20, or your specific Factory/Sweeper contracts).
To request specific implementation details, ask:
- "How do I implement a factory sweep with viem?"
- "Show me the EIP-7702 signing flow."
- "What is the difference between Permit and Auth strategies?"
Viem Sweep Skills
This skills provides comprehensive guidance and reference implementations for advanced token sweeping and transaction strategies using viem v2. It is designed to help developers implement efficient, secure, and modern asset transfer patterns on Ethereum and EVM-compatible chains.
Features
The skill covers five core strategies, ranging from basic transfers to cutting-edge EIP implementations:
1. Legacy Strategy: Standard direct transfers (funds ETH for gas if needed). 2. Factory Strategy: Gas-efficient deterministic deposit addresses using CREATE2 and minimal proxies. 3. Permit Strategy (EIP-2612): Gasless transfers using signed permits. 4. Auth Strategy (EIP-3009): Specialized gasless transfers for tokens like USDC. 5. EIP-7702 Strategy: Account delegation for "upgrading" EOAs to smart contracts during a transaction.
Installation
To add this skill to your project, run:
npx skills add melonask/viem-sweep-skillsContents
- `SKILL.md`: The main entry point containing the strategy selection guide and high-level overview.
- `references/strategies.md`: Detailed TypeScript/JavaScript implementation patterns using
viem. - `references/contracts.md`: Reference Solidity implementations for the supporting smart contracts (Factories, Sweepers, Delegates).
Usage
You can trigger this skill by asking the agent for help with:
- "How do I sweep tokens using viem?"
- "Implement a wallet factory with CREATE2."
- "Show me how to use EIP-7702 with viem."
- "Explain the difference between Permit and Auth transfer strategies."
Requirements
- Viem: v2.x or higher
- Solidity: v0.8.x (for the contract implementations)
Strategy Smart Contracts
These Solidity contracts provide the on-chain logic for the sweeping strategies.
1. Wallet Factory (Strategy 2)
Uses CREATE2 to deploy minimal proxies and flush tokens/ETH in batches.
contract WalletFactory is Ownable {
address public immutable IMPLEMENTATION;
function predictAddress(bytes32 salt) external view returns (address) {
return Clones.predictDeterministicAddress(IMPLEMENTATION, salt, address(this));
}
function batchSweep(bytes32[] calldata salts, address token, address recipient) external onlyOwner {
for (uint256 i; i < salts.length; ) {
address proxy = Clones.predictDeterministicAddress(IMPLEMENTATION, salts[i], address(this));
if (proxy.code.length == 0) Clones.cloneDeterministic(IMPLEMENTATION, salts[i]);
WalletImplementation(payable(proxy)).flush(token, recipient);
unchecked { ++i; }
}
}
}2. Sweeper Delegate (Strategy 5 / EIP-7702)
Target code for EIP-7702 delegation.
contract SweeperDelegate {
function executeSweep(address token, address recipient) external {
uint256 balance = IERC20(token).balanceOf(address(this));
if (balance != 0) SafeERC20.safeTransfer(IERC20(token), recipient, balance);
}
}3. Permit Sweeper (Strategy 3 & 4)
Handles batch execution of EIP-2612 Permits and EIP-3009 Authorizations.
contract PermitSweeper is Ownable {
struct PermitBatch {
address token;
address owner;
uint256 amount;
uint256 deadline;
uint8 v;
bytes32 r;
bytes32 s;
}
function executeBatchPermitSweep(PermitBatch[] calldata batches, address recipient) external onlyOwner {
for (uint256 i; i < batches.length; ) {
PermitBatch calldata b = batches[i];
IERC20Permit(b.token).permit(b.owner, address(this), b.amount, b.deadline, b.v, b.r, b.s);
SafeERC20.safeTransferFrom(IERC20(b.token), b.owner, recipient, b.amount);
unchecked { ++i; }
}
}
}Viem V2 Transaction Strategies
This reference details implementation patterns for various transaction sweeping strategies using viem v2.
1. Legacy Strategy (Direct Transfer)
When to use:
- You have the private keys for source addresses.
- Token does not support advanced features (Permit/Auth/Delegation).
- Gas cost is not the primary concern, or simplicity is preferred.
How it works:
1. Check if source has ETH for gas. 2. Fund source with ETH if needed (from admin wallet). 3. Execute erc20.transfer from source.
Code Example:
import {
createWalletClient,
http,
type PublicClient,
type WalletClient,
type Hex,
parseEther,
} from "viem";
import { privateKeyToAccount } from "viem/accounts";
import { mainnet } from "viem/chains";
export async function executeLegacySweep(
publicClient: PublicClient,
adminWallet: WalletClient,
privateKey: Hex,
tokenAddress: Hex,
recipient: Hex
) {
const account = privateKeyToAccount(privateKey);
const userWallet = createWalletClient({
account,
chain: mainnet,
transport: http(),
});
// 1. Check ETH balance for gas
const balance = await publicClient.getBalance({ address: account.address });
const gasPrice = await publicClient.getGasPrice();
const estimatedGasCost = gasPrice * 60000n; // ~60k gas buffer
// 2. Fund if necessary
if (balance < estimatedGasCost) {
const hash = await adminWallet.sendTransaction({
to: account.address,
value: estimatedGasCost - balance + parseEther("0.001"), // Buffer
});
await publicClient.waitForTransactionReceipt({ hash });
}
// 3. Execute Transfer
const { request } = await publicClient.simulateContract({
account,
address: tokenAddress,
abi: [
{
/* ERC20 Transfer ABI */ name: "transfer",
type: "function",
inputs: [
{ name: "to", type: "address" },
{ name: "value", type: "uint256" },
],
outputs: [],
stateMutability: "nonpayable",
},
],
functionName: "transfer",
args: [
recipient,
await getTokenBalance(publicClient, tokenAddress, account.address),
], // Assume helper exists
});
return await userWallet.writeContract(request);
}2. Factory Strategy (CREATE2 Clones)
When to use:
- You want to generate deposit addresses deterministically without deploying contracts upfront.
- You want to sweep multiple addresses in a single transaction (gas efficient).
- You are using a factory contract that deploys minimal proxies (EIP-1167).
How it works:
1. Predict address using Clones.predictDeterministicAddress (off-chain or on-chain view). 2. Send tokens to predicted address. 3. Call batchSweep on factory:
- Deploys proxy if code size is 0.
- Calls
flushon proxy to send tokens to recipient.
Code Example:
import { type PublicClient, type WalletClient, type Hex } from "viem";
export async function executeFactorySweep(
publicClient: PublicClient,
walletClient: WalletClient, // Admin executes this
factoryAddress: Hex,
salts: Hex[],
tokenAddress: Hex,
recipient: Hex
) {
// Batch sweep deploys (if needed) and flushes in one go
const { request } = await publicClient.simulateContract({
account: walletClient.account!,
address: factoryAddress,
abi: [
{
/* WalletFactory ABI */
name: "batchSweep",
type: "function",
inputs: [
{ name: "salts", type: "bytes32[]" },
{ name: "token", type: "address" },
{ name: "recipient", type: "address" },
],
outputs: [],
},
],
functionName: "batchSweep",
args: [salts, tokenAddress, recipient],
});
return await walletClient.writeContract(request);
}3. Permit Strategy (EIP-2612)
When to use:
- Token supports EIP-2612
permitfunction. - You have private keys but want to pay gas from a central "admin" account (gasless for users).
How it works:
1. User signs a typed data (EIP-712) Permit message. 2. Admin submits batch of permits + transferFrom calls to a sweeper contract. 3. Sweeper contract calls permit (updating allowance) then transferFrom.
Code Example:
import {
type PublicClient,
type WalletClient,
type Hex,
parseSignature,
} from "viem";
import { privateKeyToAccount } from "viem/accounts";
export async function generatePermitSignature(
client: PublicClient,
token: Hex,
ownerPk: Hex,
spender: Hex,
value: bigint,
deadline: bigint
) {
const account = privateKeyToAccount(ownerPk);
const nonce = (await client.readContract({
address: token,
abi: [
{
/* ERC20Permit ABI */
name: "nonces",
inputs: [{ name: "owner", type: "address" }],
outputs: [{ name: "", type: "uint256" }],
type: "function",
},
],
functionName: "nonces",
args: [account.address],
})) as bigint;
const domain = {
name: await getTokenName(client, token),
version: "1",
chainId: await client.getChainId(),
verifyingContract: token,
};
const signature = await account.signTypedData({
domain,
types: {
Permit: [
{ name: "owner", type: "address" },
{ name: "spender", type: "address" },
{ name: "value", type: "uint256" },
{ name: "nonce", type: "uint256" },
{ name: "deadline", type: "uint256" },
],
},
primaryType: "Permit",
message: { owner: account.address, spender, value, nonce, deadline },
});
return {
...parseSignature(signature),
owner: account.address,
value,
deadline,
};
}4. Auth Strategy (EIP-3009)
When to use:
- Token supports EIP-3009
transferWithAuthorization(e.g., USDC). - Similar to Permit, allows gasless transfers via signature.
How it works:
1. User signs TransferWithAuthorization typed data. 2. Admin submits batch to sweeper contract. 3. Sweeper calls transferWithAuthorization on token.
Code Example:
// Similar to Permit, but types are:
/*
types: {
TransferWithAuthorization: [
{ name: "from", type: "address" },
{ name: "to", type: "address" },
{ name: "value", type: "uint256" },
{ name: "validAfter", type: "uint256" },
{ name: "validBefore", type: "uint256" },
{ name: "nonce", type: "bytes32" },
],
}
*/
// Note: Nonce is usually random bytes32, not sequential.5. EIP-7702 Strategy (Delegation)
When to use:
- Chain supports EIP-7702 (e.g., Prague hardfork).
- You want to temporarily upgrade an EOA to a smart contract to execute batch operations.
How it works:
1. User signs an "Authorization" to delegate code to a SweeperDelegate contract. 2. Admin submits transaction with authorizationList. 3. During transaction, User account _becomes_ the Delegate contract. 4. Admin calls function on User (which is now a contract) to sweep tokens.
Code Example:
import { type PublicClient, type WalletClient, type Hex } from "viem";
import { privateKeyToAccount } from "viem/accounts";
export async function executeEip7702Sweep(
publicClient: PublicClient,
walletClient: WalletClient,
sweeperDelegate: Hex, // The code we want to set
batchInvoker: Hex, // Contract that calls the users
privateKey: Hex,
token: Hex,
recipient: Hex
) {
const account = privateKeyToAccount(privateKey);
const chainId = await publicClient.getChainId();
const nonce = await publicClient.getTransactionCount({
address: account.address,
});
// 1. Sign Authorization
const authorization = await walletClient.signAuthorization({
account,
contractAddress: sweeperDelegate,
chainId,
nonce,
});
// 2. Submit Transaction with Authorization List
// The BatchInvoker will call `account.executeSweep(token, recipient)`
const { request } = await publicClient.simulateContract({
account: walletClient.account!,
address: batchInvoker,
abi: [
{
/* BatchInvoker ABI */
},
],
functionName: "batchCall7702",
args: [[account.address], token, recipient],
});
return await walletClient.writeContract({
...request,
authorizationList: [authorization],
});
}