所有文章 > 区块链驱动 > 如何使用 Circle 的智能合约平台将 ETH 兑换成 USDC
如何使用 Circle 的智能合约平台将 ETH 兑换成 USDC

如何使用 Circle 的智能合约平台将 ETH 兑换成 USDC

Circle 的智能合约平台允许您通过智能合约将 ETH 无缝兑换为 USDC。了解如何操作。

Circle 的智能合约平台简化了以编程方式部署智能合约并通过包含钱包和 gas 抽象基础设施的 SDK 调用其函数的过程。以下是我们将要完成的工作:

  • 编写一个智能合约,在 Uniswap 上执行从 ETH 到 USDC 的交换。
  • 使用 Remix IDE 编译智能合约并提取 ABI JSON 和字节码。
  • 通过 SDK 部署并调用智能合约函数进行 Token 兑换。

先决条件

在我们开始之前,请确保您拥有以下内容:

  1. Remix IDE:用于编写和编译智能合约。
  2. Circle智能合约:用于管理智能合约交互以执行交换。
  3. 可编程钱包:用于部署智能合约和执行合约功能。

编写智能合约

我们将使用与 Uniswap 交互的预先编写的智能合约来执行代币交换。本指南将向您展示如何将 ETH 兑换成 USDC。当 ETH 存入合约进行交换时,它会转换为 Wrapped ETH (WETH),这是一种 ERC20 代币,可以使用 Uniswap 的协议交换为 USDC。以下是合约代码:

// 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;

// Token contract addresses used for the WETH to USDC swap
address public constant WETH9 = 0x7ceB23fD6bC0adD59E62ac25578270cFf1b9f619;

address public constant USDC = 0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359;

uint24 public constant poolFee = 3000;

constructor(ISwapRouter _swapRouter) {
swapRouter = _swapRouter;
}

// @notice swapExactInputSingle swaps a fixed amount of WETH9 for a maximum possible amount of USDC
// using the WETH9/USDC 0.3% pool by calling `exactInputSingle` in the swap router.
// @dev The calling address must approve this contract to spend at least `amountIn` worth of its WETH9 for this function to succeed.
// @param amountIn The exact amount of WETH9 that will be swapped for USDC.
// @return amountOut The amount of USDC received.
function swapExactInputSingle(uint256 amountIn) external returns (uint256 amountOut) {
// msg.sender must approve this contract

// Transfer the specified amount of WETH9 to this contract.
TransferHelper.safeTransferFrom(WETH9, msg.sender, address(this), amountIn);

// Approve the router to spend WETH9.
TransferHelper.safeApprove(WETH9, address(swapRouter), amountIn);

// Naively set amountOutMinimum to 0. In production, use an oracle or other data source to choose a safer value for amountOutMinimum.
// We also set the sqrtPriceLimitx96 to be 0 to ensure we swap our exact input amount.
ISwapRouter.ExactInputSingleParams memory params =
ISwapRouter.ExactInputSingleParams({
tokenIn: WETH9,
tokenOut: USDC,
fee: poolFee,
recipient: msg.sender,
deadline: block.timestamp,
amountIn: amountIn,
amountOutMinimum: 0,
sqrtPriceLimitX96: 0
});

// The call to `exactInputSingle` executes the swap.
amountOut = swapRouter.exactInputSingle(params);
}

// @notice swapExactOutputSingle swaps a minimum possible amount of WETH9 for a fixed amount of USDC.
// @dev The calling address must approve this contract to spend its WETH9 for this function to succeed. As the amount of input WETH9 is variable,
// the calling address will need to approve for a slightly higher amount, anticipating some variance.
// @param amountOut The exact amount of USDC to receive from the swap.
// @param amountInMaximum The amount of WETH9 we are willing to spend to receive the specified amount of USDC.
// @return amountIn The amount of WETH9 actually spent in the swap.
function swapExactOutputSingle(uint256 amountOut, uint256 amountInMaximum) external returns (uint256 amountIn) {
// Transfer the specified amount of WETH9 to this contract.
TransferHelper.safeTransferFrom(WETH9, msg.sender, address(this), amountInMaximum);

// Approve the router to spend the specified `amountInMaximum` of WETH9.
// In production, you should choose the maximum amount to spend based on oracles or other data sources to achieve a better swap.
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
});

// Executes the swap returning the amountIn needed to spend to receive the desired amountOut.
amountIn = swapRouter.exactOutputSingle(params);

// For exact output swaps, the amountInMaximum may not have all been spent.
// If the actual amount spent (amountIn) is less than the specified maximum amount, we must refund the msg.sender and approve the swapRouter to spend 0.
if (amountIn < amountInMaximum) {
TransferHelper.safeApprove(WETH9, address(swapRouter), 0);
TransferHelper.safeTransfer(WETH9, msg.sender, amountInMaximum - amountIn);
}
}
}

编译智能合约

在部署智能合约之前,我们需要对其进行编译,以获取 ABI(Application Binary Interface)和字节码。为此,我们将使用 Remix IDE。打开 Remix IDE

  • 在 Web 浏览器中导航到 REMIX IDE。

创建新文件

  • 在 Remix IDE 中,创建一个新文件并粘贴上面提供的智能合约代码。

编译合约

  • 从编译器选项卡中选择合适的 Solidity 编译器版本 (0.8.26)。
  • 点击 “Compile” 按钮编译合约。

复制 ABI 和 Bytecode

  • 编译合约后,导航到 “Compilation Details” 部分。
  • 复制 ABI JSON 和字节码。使用 Circle 的 SDK 部署合约时需要这些。

为什么需要此步骤?

编译智能合约会生成 ABI 和字节码,这对于在区块链上部署合约并与之交互至关重要。ABI 定义了合约的接口,允许我们调用其函数,而字节码是部署到区块链的合约的编译版本。

部署智能合约

要使用 Circle 的 SDK 部署编译好的合约,请执行以下步骤:

安装和导入所需的软件包

首先,确保您已安装必要的软件包:

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

这些软件包提供了与 Circle 的智能合约平台交互和处理开发人员控制的钱包所需的工具。

然后,在您的项目中导入所需的包:

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

准备部署参数:

  • name:合约的名称。
  • description:合同的简要描述。
  • walletId:您的 Circle 钱包 ID。
  • 区块链:区块链网络(例如 MATIC-AMOY)
  • fee:费用配置。
  • constructorParameters:要设置为合约初始所有者的地址。在本指南中,它应该是您的钱包地址,但可以是任何地址。
  • entitySecretCiphertext:您的加密实体密钥。
  • abiJSON:您在上述步骤中从 Remix IDE 复制的 JSON 格式合约的 ABI。请注意,ABI JSON 必须字符串化(即引号转义)。要字符串化 JSON,您可以使用 JsonFormatter 的 Stringify 工具。
  • bytecode:您在上述步骤中从 Remix IDE 复制的合约的编译字节码。字节码必须以 0x 为前缀。

部署合约:

 const response = await circleContractSdk.deployContract({
name: 'Swap Contract',
description: 'Contract for swapping WETH9 to USDC using Uniswap',
walletId: '046b6c7f-0b8a-43b9-b35d-6489e6daee91',// Replace with your walletId
blockchain: 'MATIC-AMOY',
fee: {
type: 'level',
config: {
feeLevel: 'MEDIUM'
}
},
constructorParameters: ['0xYourWalletAddress'], // Replace with your wallet address
entitySecretCiphertext: '0NtD3d3+nmgb4GqYQXzAjKF8h5Zq6sHM2k/...', // Replace with your entitySecretCipher text
abiJSON: '[...]', // Replace with actual stringified ABI JSON
bytecode: '0x...' // Replace with actual bytecode prefixed with 0x
});

成功部署智能合约后,您将收到包含 contractId 和 transactionId 的响应。

{ 
"data": {
"contractId": "0189db84-72b7-7fcc-832b-5bf886b9a0ef",
"transactionId": "7b989c65-9678-56d8-a998-d295b8b04535"
}
}

检查部署状态:

const response = await circleContractSdk.getContract({
id: '0189db84-72b7-7fcc-832b-5bf886b9a0ef'
});
{
"data": {
"contract": {
"id": "0189db84-72b7-7fcc-832b-5bf886b9a0ef",
"deploymentTransactionId": "7b989c65-9678-56d8-a998-d295b8b04535",
"name": "Swap Contract",
"description": "Contract for swapping WETH9 to USDC using Uniswap",
"contractInputType": "BYTECODE",
"createDate": "2023-08-09T18:17:17Z",
"updateDate": "2023-08-09T18:17:17Z",
"archived": false,
"contractAddress": "0x1e124d7384cd34448ea5907bd0052a79355ab5eb",
"blockchain": "MATIC-AMOY",
"status": "COMPLETE",
"deployerAddress": "0x1bf9ad0cc2ad298c69a2995aa806ee832788218c",
"txHash": "0x241c4df6f08f9ed2b569c9f9b1cc48fb6074ffffaeee7552e716ce059161a743",
"abiJSON": "[\n\t{\n\t\t\"inputs\": [],\n\t\t\"stateMutability\": \"nonpayable\",\n\t\t\"type\": \"constructor\"\n\t},\n\t{\n\t\t\"anonymous\": false,",
"functions": [
{
"name": "swapExactInputSingle",
"type": "function",
"inputs": [
{
"name": "amountIn",
"type": "uint256"
}
],
"stateMutability": "nonpayable"
}
],
"verificationStatus": "UNVERIFIED"
}
}
}

与已部署的合约交互

部署合约后,您可以与它交互以执行代币交换。下面介绍如何调用 swapExactInputSingle 函数:

准备交互参数:

  • walletId:您的 Circle 钱包 ID。
  • contractAddress:已部署合约的地址。
  • abiFunctionSignature:要调用的函数签名。
  • abiParameters:函数的参数。
  • fee:费用配置。

调用函数:

 const response = await circleDeveloperSdk.createContractExecutionTransaction({
walletId: 'ce714f5b-0d8e-4062-9454-61aa1154869b', // Replace with your wallet ID
contractAddress: '0x2f3A40A3db8a7e3D09B0adfEfbCe4f6F81927557', // Replace with your contract address
abiFunctionSignature: 'swapExactInputSingle(uint256)',
abiParameters: [1000], // Example amountIn value
fee: {
type: 'level',
config: {
feeLevel: 'MEDIUM'
}
}
});

结论

我们展示了如何利用Circle的智能合约平台部署智能合约,并与之交互,以通过Uniswap实现从ETH到USDC的代币转换。借助Circle的SDK,您可以轻松地管理智能合约并执行区块链交易。

#你可能也喜欢这些API文章!