Solidity中如何将参数编码为bytes类型传递后解码调用函数
完整实现方案
1. 合约端代码实现
直接用Solidity内置的abi.decode完成bytes解码,无需手动实现解析逻辑,完整合约示例如下:
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; contract TestContract { // 你的目标函数foo2 function foo2(address param1, uint256 param2) internal pure returns (address, uint256) { // 此处写你的业务逻辑,示例直接返回参数验证 return (param1, param2); } // 对外暴露的foo1,接收bytes类型参数 function foo1(bytes calldata params) external pure returns (address, uint256) { // 直接解码bytes为对应的address和uint256类型 // 解码顺序要和前端编码的参数顺序、类型完全对应 (address param1, uint256 param2) = abi.decode(params, (address, uint256)); // 调用foo2 return foo2(param1, param2); } }
如果需要单独封装解码函数,可以按如下方式实现:
function decode(bytes calldata params) private pure returns (address param1, uint256 param2) { (param1, param2) = abi.decode(params, (address, uint256)); } // foo1就可以改成 function foo1(bytes calldata params) external pure returns (address, uint256) { (address param1, uint256 param2) = decode(params); return foo2(param1, param2); }
2. 前端编码实现
前端按照Solidity ABI编码规则把参数序列化为bytes即可,以常用的ethers.js库为例:
ethers.js v5/v6 实现
import { ethers } from "ethers"; // 1. 构造参数 const param1 = "0xAddRess"; // 替换为实际地址 const param2 = 1; // 2. 编码为bytes,类型数组顺序要和合约解码顺序完全一致 const params = ethers.utils.defaultAbiCoder.encode( ["address", "uint256"], [param1, param2] ); // 3. 调用合约foo1方法 const tx = await myContract.foo1(params); await tx.wait();
web3.js 实现
如果用web3.js,编码方式如下:
const Web3 = require('web3'); const web3 = new Web3(); const param1 = "0xAddRess"; const param2 = 1; const params = web3.eth.abi.encodeParameters(["address", "uint256"], [param1, param2]); const tx = await myContract.methods.foo1(params).send();
注意事项
- 编码时的类型顺序、类型定义必须和合约解码时的参数完全一致,否则会出现解码错误或者数据错乱
- 地址类型参数需要传入合法的以太坊地址,否则编码阶段就会报错
- 数值类型要匹配范围,uint256不要传入负数或者超出2^256-1的数值
内容的提问来源于stack exchange,提问作者Edgaras Karka
相关产品推荐
相关产品推荐

