如何使用Ethers将SwapResolverOptions结构体编码为Bytes参数
Solidity结构体编码为Bytes的解决方案
问题描述
我在测试一段Solidity代码,需要为bytes类型参数正确编码数据。合约包含以下函数:
function validateAdditionalCalldata(bytes calldata resolverOptions) external view; function resolve(uint256 amountIn, bytes calldata resolverOptions) public override returns (uint256 amountOut) { // 将额外calldata解码为SwapResolverOptions结构体 (SwapResolverOptions memory swapResolverOptions) = abi.decode(resolverOptions, (SwapResolverOptions)); return resolveImplementation(amountIn, swapResolverOptions); }
对应的TypeScript生成代码中,resolve函数接收PromiseOrValue<BytesLike>类型的resolverOptions参数:
resolve( amountIn: PromiseOrValue<BigNumberish>, resolverOptions: PromiseOrValue<BytesLike>, overrides?: Overrides & { from?: PromiseOrValue<string> } ): Promise<ContractTransaction>; export type SwapResolverOptionsStruct = { path: PromiseOrValue<BytesLike>; deadline: PromiseOrValue<BigNumberish>; amountIn: PromiseOrValue<BigNumberish>; amountOutMinimum: PromiseOrValue<BigNumberish>; inputTokenAddress: PromiseOrValue<string>; targetAddress: PromiseOrValue<string>; destinationAddress: PromiseOrValue<string>; };
我在TypeScript中定义了参数实例:
const resolverOptions: SwapResolverOptionsStruct = { path: '0x00', // 该参数将在下一版本部署中移除 deadline: BigNumber.from(1000), amountIn: BigNumber.from(100000000), amountOutMinimum: BigNumber.from(0), inputTokenAddress: WMATIC_MUMBAI, destinationAddress: owner.address, targetAddress: ADDRESS_ZERO, };
尝试用以下方式编码时触发错误:
import { defaultAbiCoder } from "@ethersproject/abi"; encodedResolverOptions = defaultAbiCoder.encode( ['SwapResolverOptionsStruct'], [resolverOptions] );
错误信息:
Error: invalid type (argument="type", value="SwapResolverOptionsStruct",
注意:我无法直接编码整个函数调用,必须将编码后的数据传给validateAdditionalCalldata函数,其参数类型为PromiseOrValue<BytesLike>。需要明确如何正确将resolverOptions编码为bytes类型。
解决方案
问题核心是defaultAbiCoder不识别TypeScript自定义类型,必须使用Solidity原生类型字符串来描述结构体字段。
步骤1:确认Solidity结构体定义
根据TypeScript类型反推,你的Solidity中SwapResolverOptions结构体应为:
struct SwapResolverOptions { bytes path; uint256 deadline; uint256 amountIn; uint256 amountOutMinimum; address inputTokenAddress; address targetAddress; address destinationAddress; }
步骤2:使用Solidity类型列表编码
在TypeScript中,按结构体字段顺序传入类型列表和对应值即可完成编码:
import { defaultAbiCoder } from "@ethersproject/abi"; // 对应Solidity结构体的原生类型列表 const structTypeList = [ 'bytes', 'uint256', 'uint256', 'uint256', 'address', 'address', 'address' ]; // 按顺序提取结构体实例的字段值 const structValueList = [ resolverOptions.path, resolverOptions.deadline, resolverOptions.amountIn, resolverOptions.amountOutMinimum, resolverOptions.inputTokenAddress, resolverOptions.targetAddress, resolverOptions.destinationAddress ]; // 执行编码 const encodedResolverOptions = defaultAbiCoder.encode(structTypeList, structValueList);
关键注意事项
- 类型列表和值列表的顺序必须严格匹配Solidity结构体的字段顺序,否则解码时会出现数据错乱。
- 编码后的
encodedResolverOptions直接符合BytesLike类型要求,可直接传入validateAdditionalCalldata或resolve函数的参数中。
内容的提问来源于stack exchange,提问作者Ritzy Dev
相关产品推荐
相关产品推荐

