Skip to main content

What is Redelegation?

Redelegation is the process of updating an existing wallet delegation with new parameters. This replaces the previous delegation for that wallet address with a new one.
Redelegation follows the exact same 3-step process as initial delegation. The new delegation completely replaces the previous one for the same wallet address.

When to Redelegate

1. Allowance Adjustment

Scenario: User needs to increase or decrease spending limit
When: User’s current allowance is running low or depletedExample:
  • Current allowance: 5,000 USDC
  • Remaining: 500 USDC
  • Want to increase to: 10,000 USDC
Action: Redelegate with new amount (10,000 USDC)

2. Contract Upgrades

Scenario: Platform upgrades smart contracts with new features or security improvements
Platform will notify users when contract upgrades require redelegation. This is the most critical redelegation scenario.
When It Happens:
  • Platform deploys new smart contract versions
  • Security patches or improvements implemented
  • New features added to delegation contracts
  • Network-specific contract updates
What You Need to Do:
  1. Monitor platform notifications for upgrade announcements
  2. Inform users of the upgrade and its benefits
  3. Guide users through redelegation process
  4. Set reasonable deadline for migration
  5. Provide fallback for users who don’t migrate promptly
Example Notification Flow:
interface ContractUpgradeNotification {
  upgradeId: string;
  effectiveDate: string;
  deadline: string;
  affectedNetworks: string[];
  reason: string;
  changes: string[];
}

async function notifyUsersOfContractUpgrade(
  upgrade: ContractUpgradeNotification
) {
  // Send email/push notification to all users with delegated wallets
  // on affected networks

  const affectedUsers = await getUsersWithWalletsOnNetworks(
    upgrade.affectedNetworks
  );

  for (const user of affectedUsers) {
    await sendNotification(user, {
      title: 'Action Required: Wallet Redelegation Needed',
      message: `Our smart contracts have been upgraded. Please redelegate your wallets by ${upgrade.deadline}.`,
      action: {
        label: 'Redelegate Now',
        url: '/settings/wallets/redelegate'
      }
    });
  }
}

3. Network Migration

Scenario: User wants to move delegation to a different blockchain Example Use Cases:
  • Switch from Ethereum to Linea for lower gas fees
  • Move from Linea to Solana for faster transactions
  • Consolidate multiple network wallets to single network
Process:
  1. Delegate new wallet on target network
  2. Update priority to prefer new network
  3. Optionally revoke old delegation (by setting allowance to 0)
async function migrateToLinea(
  userId: string,
  ethereumWalletAddress: string,
  lineaWalletAddress: string
) {
  console.log('Step 1: Delegate new Linea wallet');
  await completeDelegationFlow(
    userId,
    'linea',
    'usdc',
    '10000',
    lineaWalletAddress
  );

  console.log('Step 2: Update priority to prefer Linea');
  const wallets = await getCurrentPriority(userId);

  const lineaWallet = wallets.find(w => w.address === lineaWalletAddress);
  const ethereumWallet = wallets.find(w => w.address === ethereumWalletAddress);

  if (lineaWallet && ethereumWallet) {
    await updatePriority(userId, [
      { id: lineaWallet.id, priority: 1 },
      { id: ethereumWallet.id, priority: 2 }
    ]);
  }

  console.log('Step 3: Optional - Revoke Ethereum delegation');
  // User can manually revoke in their wallet or leave as backup
}

4. Wallet Address Change

Scenario: User wants to use a different wallet address for the same network Common Reasons:
  • Upgraded to hardware wallet
  • Changed wallet provider
  • Security concerns with old wallet
  • Using different wallet for organizational reasons
Process:
  1. Delegate new wallet address
  2. Verify new wallet works
  3. Remove or deprioritize old wallet
You can have multiple wallets on the same network with different addresses. Use priority to control which is used first.

5. Security Events

Scenario: Wallet potentially compromised or security best practices When to Redelegate Immediately:
  • Private key exposure suspected
  • Wallet used on untrusted device
  • Suspicious transaction activity
  • Periodic security rotation (best practice)
Emergency Redelegation Process:
1

Revoke Current Delegation

Set allowance to 0 on potentially compromised wallet using user’s wallet interface (not API)
2

Delegate New Wallet

Complete delegation flow with new, secure wallet
3

Verify Security

Ensure old wallet has zero allowance and new wallet is functioning
4

Monitor

Watch for any unauthorized transactions on old wallet

Redelegation Process

Redelegation uses the exact same 3-step workflow as initial delegation:

Step-by-Step Redelegation

1

Request New Delegation Token

Call GET /v1/delegation/token to generate a new single-use token
2

Frontend Wallet Interaction

User approves new blockchain transaction with updated parameters:
  • Same wallet address (for allowance update)
  • New spending limit (if changing allowance)
  • New spender address (if contract upgraded)
3

Submit New Proof

Submit proof with new transaction data using POST /v1/delegation/evm/post-approval for EVM or POST /v1/delegation/solana/post-approval for Solana
4

Verify Update

Call GET /v1/wallet/external to confirm new allowance is reflected
The new delegation completely replaces the previous one. There is no “additive” mode - you must specify the full new allowance, not just the additional amount.

Implementation Examples

Increase Allowance

async function increaseAllowance(
  userId: string,
  walletAddress: string,
  currentAllowance: number,
  additionalAmount: number
): Promise<void> {
  const newAllowance = currentAllowance + additionalAmount;

  console.log(`Increasing allowance from ${currentAllowance} to ${newAllowance}`);

  const wallet = await getExternalWallets(userId);
  const targetWallet = wallet.find(w => w.address === walletAddress);

  if (!targetWallet) {
    throw new Error('Wallet not found');
  }

  await completeDelegationFlow(
    userId,
    targetWallet.network as any,
    targetWallet.currency as any,
    newAllowance.toString(),
    walletAddress
  );

  console.log('✅ Allowance increased successfully');
}

Contract Upgrade Migration

interface ContractUpgrade {
  network: 'linea' | 'ethereum' | 'solana';
  newSpenderAddress: string;
  newTokenAddress?: string;
  effectiveDate: Date;
}

async function migrateToNewContract(
  userId: string,
  walletAddress: string,
  upgrade: ContractUpgrade
): Promise<void> {
  const wallets = await getExternalWallets(userId);
  const wallet = wallets.find(w =>
    w.address === walletAddress && w.network === upgrade.network
  );

  if (!wallet) {
    throw new Error('Wallet not found for migration');
  }

  console.log('Starting contract upgrade migration...');
  console.log(`Network: ${upgrade.network}`);
  console.log(`New spender: ${upgrade.newSpenderAddress}`);

  await completeDelegationFlow(
    userId,
    wallet.network as any,
    wallet.currency as any,
    wallet.allowance,
    walletAddress,
    {
      spenderAddress: upgrade.newSpenderAddress,
      tokenAddress: upgrade.newTokenAddress
    }
  );

  console.log('✅ Migration to new contract complete');

  const updated = await getExternalWallets(userId);
  const updatedWallet = updated.find(w => w.address === walletAddress);

  console.log('Updated wallet:', updatedWallet);
}

Batch Redelegation

For users with multiple wallets needing updates:
async function batchRedelegate(
  userId: string,
  updates: Array<{
    address: string;
    newAllowance: string;
  }>
): Promise<{
  successful: string[];
  failed: Array<{ address: string; error: string }>;
}> {
  const results = {
    successful: [] as string[],
    failed: [] as Array<{ address: string; error: string }>
  };

  const wallets = await getExternalWallets(userId);

  for (const update of updates) {
    try {
      const wallet = wallets.find(w => w.address === update.address);

      if (!wallet) {
        throw new Error('Wallet not found');
      }

      await completeDelegationFlow(
        userId,
        wallet.network as any,
        wallet.currency as any,
        update.newAllowance,
        update.address
      );

      results.successful.push(update.address);
      console.log(`✅ Redelegated ${update.address}`);

    } catch (error: any) {
      results.failed.push({
        address: update.address,
        error: error.message
      });
      console.error(`❌ Failed to redelegate ${update.address}:`, error);
    }

    await new Promise(resolve => setTimeout(resolve, 1000));
  }

  return results;
}

UI/UX Considerations

Informing Users About Redelegation

Prompt users when allowance is running low:
function AllowanceWarning({ wallet }: { wallet: ExternalWallet }) {
  const remaining = parseFloat(wallet.allowance);
  const original = parseFloat(wallet.balance);
  const percentRemaining = (remaining / original) * 100;

  if (percentRemaining > 20) return null;

  return (
    <div className="warning">
      <AlertIcon />
      <div>
        <h4>Low Allowance Warning</h4>
        <p>
          Only {remaining} {wallet.currency.toUpperCase()} remaining.
          Redelegate to increase your spending limit.
        </p>
        <button onClick={() => startRedelegation(wallet)}>
          Increase Allowance
        </button>
      </div>
    </div>
  );
}

Best Practices

Proactive Redelegation

Set up automated monitoring to alert users before allowance runs out:
async function checkAllowanceStatus(userId: string) {
  const wallets = await getExternalWallets(userId);

  for (const wallet of wallets) {
    const percentRemaining =
      (parseFloat(wallet.balance) / parseFloat(wallet.allowance)) * 100;

    if (percentRemaining < 20) {
      await sendNotification(userId, {
        type: 'low_allowance',
        wallet: wallet.address,
        remaining: wallet.balance,
        currency: wallet.currency
      });
    }
  }
}
Regularly check for contract upgrades:
async function checkForContractUpgrades(): Promise<ContractUpgrade[]> {
  const response = await fetch('/api/platform/contract-upgrades');
  return await response.json();
}

// Run daily
setInterval(async () => {
  const upgrades = await checkForContractUpgrades();
  if (upgrades.length > 0) {
    await notifyAffectedUsers(upgrades);
  }
}, 24 * 60 * 60 * 1000);
Educate users about when and why to redelegate:
  • Include redelegation info in onboarding
  • Provide in-app tooltips and guides
  • Send periodic reminders about allowance status
  • Explain benefits of proactive management
Handle scenarios where redelegation hasn’t occurred:
  • Maintain multiple wallet support for failover
  • Prompt users at checkout if allowance insufficient
  • Provide clear error messages with actionable steps
  • Allow alternative payment methods during migration periods

Testing Redelegation

Always test redelegation flows before production:
describe('Redelegation', () => {
  it('should increase allowance successfully', async () => {
    const initialAllowance = 5000;
    const additionalAmount = 5000;
    const expectedNew = 10000;

    await increaseAllowance(
      userId,
      walletAddress,
      initialAllowance,
      additionalAmount
    );

    const wallets = await getExternalWallets(userId);
    const wallet = wallets.find(w => w.address === walletAddress);

    expect(wallet?.allowance).toBe(expectedNew.toString());
  });

  it('should handle contract upgrade migration', async () => {
    const upgrade: ContractUpgrade = {
      network: 'linea',
      newSpenderAddress: '0xNewSpender...',
      effectiveDate: new Date()
    };

    await migrateToNewContract(userId, walletAddress, upgrade);

    // Verify new contract is being used
    const wallets = await getExternalWallets(userId);
    const wallet = wallets.find(w => w.address === walletAddress);

    expect(wallet).toBeDefined();
    // Additional verification that new spender is active
  });

  it('should batch redelegate multiple wallets', async () => {
    const updates = [
      { address: wallet1, newAllowance: '10000' },
      { address: wallet2, newAllowance: '5000' }
    ];

    const results = await batchRedelegate(userId, updates);

    expect(results.successful).toHaveLength(2);
    expect(results.failed).toHaveLength(0);
  });
});

Troubleshooting

Symptom: API shows old allowance after redelegationCauses:
  • Blockchain transaction not confirmed
  • Wrong transaction hash submitted
  • Cached data in API
Solutions:
  • Wait for blockchain confirmation (check block explorer)
  • Verify transaction hash is correct
  • Retry fetching wallet data after 30 seconds
Symptom: Transaction fails during Step 2Causes:
  • Insufficient gas/SOL for transaction
  • Wrong network selected in wallet
  • Wallet connection lost
Solutions:
  • Ensure user has gas funds (ETH/SOL)
  • Verify correct network selected
  • Reconnect wallet and retry
Symptom: Old delegation still working after supposed upgradeCauses:
  • Upgrade not yet effective
  • Gradual rollout in progress
  • Network-specific timing
Solutions:
  • Check upgrade effective date
  • Contact platform support for rollout status
  • Complete redelegation proactively regardless

Monitoring & Analytics

Track redelegation metrics for your application:
interface RedelegationMetrics {
  totalRedelegations: number;
  redelegationsByReason: {
    allowanceIncrease: number;
    allowanceDecrease: number;
    contractUpgrade: number;
    networkMigration: number;
    security: number;
  };
  averageNewAllowance: number;
  redelegationSuccessRate: number;
}

async function trackRedelegation(
  userId: string,
  reason: string,
  oldAllowance: number,
  newAllowance: number,
  success: boolean
) {
  await analytics.track('wallet_redelegation', {
    userId,
    reason,
    oldAllowance,
    newAllowance,
    change: newAllowance - oldAllowance,
    changePercent: ((newAllowance - oldAllowance) / oldAllowance) * 100,
    success,
    timestamp: new Date()
  });
}

Next Steps