使用 Circle 智能合约平台将 ETH 兑换 USDC:完整实战指南

·

当你想在 DeFi 世界里把 ETH 兑换成 USDC 时,如果既要快速放心、又要支持后端自动化,Circle 的智能合约平台会是你手中的利器。本文带你一步步解锁「从智能合约编写到链上调用」的全部环节,并穿插 关键词:以太坊、USDC、智能合约、Remix IDE、Circle SDK、Uniswap、WETH、 Polygon 测试网、代币兑换、智能合约部署。


准备工作:让你事半功倍的三件套

在正式开始前,先准备好 三件核心装备

  1. Remix IDE(在线版即可):用来编写、编译 Solidity 代码。
  2. Circle 智能合约平台:负责把合约部署到链上,并给你一把 SDK 万能钥匙
  3. 可编程钱包:既是钱包负责 Gas,又能在后台自动签名,省去繁琐手工操作。

👉 一键直达安全快捷的新手钱包创建教程


代码剖析:最小可运行的兑换合约

与 Uniswap 交互的合约其实比你想象中简单。下面这份精简合约实现了两个功能:

之所以先提到 WETH,是因为 Uniswap 内部用 WETH 计价,存入的 ETH 会自动转成 WETH(关键词:WETH、以太坊原生代币)。
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.20;
pragma abicoder v2;

import "@uniswap/v3-periphery/contracts/libraries/TransferHelper.sol";
import "@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.sol";

contract SwapExamples {
    ISwapRouter public immutable swapRouter;

    address public constant WETH9 = 0x7ceB23fD6bC0adD59E62ac25578270cFf1b9f619;
    address public constant USDC  = 0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359;
    uint24  public constant poolFee = 3000; // 0.3%

    constructor(ISwapRouter _swapRouter) {
        swapRouter = _swapRouter;
    }

    // 功能 1:固定 WETH 输入,求最大 USDC 输出
    function swapExactInputSingle(uint256 amountIn) external returns (uint256 amountOut) {
        TransferHelper.safeTransferFrom(WETH9, msg.sender, address(this), amountIn);
        TransferHelper.safeApprove(WETH9, address(swapRouter), amountIn);

        ISwapRouter.ExactInputSingleParams memory params = ISwapRouter.ExactInputSingleParams({
            tokenIn: WETH9,
            tokenOut: USDC,
            fee: poolFee,
            recipient: msg.sender,
            deadline: block.timestamp,
            amountIn: amountIn,
            amountOutMinimum: 0,
            sqrtPriceLimitX96: 0
        });
        amountOut = swapRouter.exactInputSingle(params);
    }

    // 功能 2:固定 USDC 输出,求最少 WETH 输入
    function swapExactOutputSingle(uint256 amountOut, uint256 amountInMaximum) external returns (uint256 amountIn) {
        TransferHelper.safeTransferFrom(WETH9, msg.sender, address(this), amountInMaximum);
        TransferHelper.safeApprove(WETH9, address(swapRouter), amountInMaximum);

        ISwapRouter.ExactOutputSingleParams memory params = ISwapRouter.ExactOutputSingleParams({
            tokenIn: WETH9,
            tokenOut: USDC,
            fee: poolFee,
            recipient: msg.sender,
            deadline: block.timestamp,
            amountOut: amountOut,
            amountInMaximum: amountInMaximum,
            sqrtPriceLimitX96: 0
        });

        amountIn = swapRouter.exactOutputSingle(params);

        if (amountIn < amountInMaximum) {
            TransferHelper.safeApprove(WETH9, address(swapRouter), 0);
            TransferHelper.safeTransfer(WETH9, msg.sender, amountInMaximum - amountIn);
        }
    }
}

步骤一:在 Remix 中编译并提取合约数据

关键词:Remix IDE、编译、ABI、字节码
  1. 打开 Remix:在浏览器输入 remix.ethereum.org。
  2. 新建 SwapExamples.sol,将上面代码原样贴入
  3. Compiler 页签 → 选择 Solidity 0.8.20Compile SwapExamples.sol
  4. 点击 Compilation Details → 复制 ABIJSON.stringify
    例:将 [{"inputs":[... 变成字符串 '[{"inputs":[...}]'
  5. 再复制 Bytecode,前面自带 0x 无需再手动添加。

步骤二:将合约塞进 Circle SDK「自动发射器」

关键词:Circle SDK、部署智能合约、钱包 ID、Polygon 测试网、Gas 抽象层

确保机器已装 Node,再敲两行命令:

npm install @circle-fin/smart-contract-platform \
            @circle-fin/developer-controlled-wallets --save

接着,在你的 .js 文件顶部:

const circleContractSdk      = require('@circle-fin/smart-contract-platform');
const developerControlledWallets = require('@circle-fin/developer-controlled-wallets');

核心参数清单(注意保密)

参数示例说明
name"Swap Contract"展示用
walletId"046b6c7f-..."您在 Circle 控制台生成的钱包
blockchain"MATIC-AMOY"本文演示 Polygon Amoy 测试网
constructorParameters["0xYourWalletAddress"]通常是钱包地址
entitySecretCiphertext"0NtD3..."用 Circle CLI 加密后的实体密钥
abiJSON'[{"inputs":[...}]'字符串化 JSON
bytecode"0x6080..."Remix 获得的 Bytecode

完整调用代码:

const response = await circleContractSdk.deployContract({
  name: 'Swap Contract',
  description: '合约:WETH 换 USDC',
  walletId: '把你的 walletId 填进来',
  blockchain: 'MATIC-AMOY',
  fee: { type: 'level', config: { feeLevel: 'MEDIUM' } },
  constructorParameters: ['0xYourWalletAddress'],
  entitySecretCiphertext: '把你的加密实体密钥填进来',
  abiJSON: JSON.stringify([{"inputs":[...}]), // 字符串化
  bytecode: '0x6080...yourBytecode'
});

console.log(response.data);
// 输出示例:
// { "data": { "contractId": "0189db84-...", "transactionId": "7b989c65-..." } }

部署成功后,获得 contractId + transactionId,用下面的代码查询 实时状态

const check = await circleContractSdk.getContract({ id: '0189db84-...' });
console.log(check.data.contract.status); // 期待 "COMPLETE"

步骤三:真正发起兑换交易

关键词:代币兑换、调用函数、gas 抽象

当合约状态 COMPLETE 后,你会看到 contractAddress: 0x1e124d...,接下来用它执行 swapExactInputSingle

精简版代码(替换关键变量):

const executeRes = await developerControlledWallets.createContractExecutionTransaction({
  walletId:           'ce714f5b-...',
  contractAddress:    '0x2f3A40A3db8a7...',
  abiFunctionSignature: 'swapExactInputSingle(uint256)',
  abiParameters:      [1000], // 换 1000 wei 为单位的 WETH
  fee: { type: 'level', config: { feeLevel: 'MEDIUM' } }
});
console.log(executeRes.data); // 包含 transactionId 与链上 txHash

👉 立即体验更低滑点、实时价格的链上闪电交易


常见问题(FAQ)

  1. Q:为什么部署到 Polygon Amoy 而不是主网?
    A:初学者先用测试网练手,打领水就能免 gas 费,待操作无误后可 一键改链 到主网。
  2. Q:需不需要手动把 ETH 换成 WETH?
    A:不必。合约内部会自动把 ETH 存成 WETH,但主网调用需给足 ETH。
  3. Q:amountOutMinimum 设为 0 安全吗?
    A:测试网随意,主网务必用预言机或滑点保护,否则会被 MEV 机器人 三明治攻击。
  4. Q:能否在同合约再加 ERC20 互换?
    A:绝对可以,把新 Token 地址、新池费率填进去,再复用现有架构即可。
  5. Q:Circle 的 SDK 支持 Solana 或 BNB Chain 了吗?
    A:截至目前仅支持 EVM 系链(如 Polygon、Avalanche C-Chain、Ethereum 主网等)。 未来列表将持续扩张

写在最后

借助 Circle 提供的 gas 抽象化一站式 SDK,你把原本需要 5 篇教程才能讲清楚的全流程,压缩到了 3 个核心步骤:
编译 → 部署 → 调用。
下一步,你可以把这套脚本嵌入 DApp 后端,每天自动把 以太坊收益换成 USDC;或者做成 Telegram Bot,一键帮朋友换汇。
圈重点:关键词:智能合约、Circle SDK、USDC 兑换、代币自动化、DeFi 进阶——抓住它们,你就能占领搜索高地。祝编码愉快,链上冲浪!