简体   繁体   中英

Ethers how to encode data to bytes parameters

I'm trying to test a piece of generic solidity code, I'm trying to figure out how to encode data properly for bytes parameters.

I have a function in a smart contract which looks like so:

function validateAdditionalCalldata(bytes calldata resolverOptions) external view;
function resolve(uint256 amountIn, bytes calldata resolverOptions) public override returns (uint256 amountOut) {

    // Decode the additional calldata as a SwapResolverOptions struct
    (SwapResolverOptions memory swapResolverOptions) = abi.decode(resolverOptions, (SwapResolverOptions));
    return resolveImplementation(amountIn, swapResolverOptions);
}

This solidity code will generate code which takes in a PromiseOrValue<BytesLike> :

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

I'm wondering how I can encode a specific parameter so I can pass it along to ethers. In typescript I have a set of options that looks like this:

const resolverOptions: SwapResolverOptionsStruct = {
  path: '0x00',
  //This parameter will be removed in the next deployment
  deadline: BigNumber.from(1000),
  amountIn: BigNumber.from(100000000),
  amountOutMinimum: BigNumber.from(0),
  inputTokenAddress: WMATIC_MUMBAI,
  destinationAddress: owner.address,
  targetAddress: ADDRESS_ZERO,
};

I'm trying to encode this parameters in the following way:

import { defaultAbiCoder } from "@ethersproject/abi";

encodedResolverOptions = defaultAbiCoder.encode(
  ['SwapResolverOptionsStruct'],
  [resolverOptions]
);

However when I try to encode it gets and error:

Error: invalid type (argument="type", value="SwapResolverOptionsStruct",

Note: in my paticular use case I cannot just encoded the whole function call.

I would like to pass my data to the validateAdditionalCalldata how ever the parameter is PromiseOrValue<BytesLike>

How can I encoded my resolverOptions so I can pass it as bytes?

I figured out a few way to do this. I'll list each one:

Resolve the type params using ethers and get function. (if there is a function which has your type in it)

const functionFragment = swapResolverInterface.getFunction("resolveImplementation");

encodedResolverOptions = defaultAbiCoder.encode(
    [functionFragment.inputs[1]],
    [resolverOptions]
);

Resolve it from an object and a method signature with parameter names:

encodedResolverOptions = defaultAbiCoder.encode(
  ["(bytes path,uint256 deadline,uint256 amountIn,uint256 amountOutMinimum,address inputTokenAddress,address destinationAddress,address targetAddress)"],
  [resolverOptions]
);

Resolve it as an array from the method signature without names Note: this assumes the object was declared in the same order as the parameters, alternatively you can manually construct the array:

encodedResolverOptions = defaultAbiCoder.encode(
  ["(bytes,uint256,uint256,uint256,address,address,address)"],
  [Object.values(resolverOptions)]
);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM