solid如何验证对特定结构的calldata解码



我在solid中有一个接口,看起来像这样,如果传递的calldata不是特定类型,我希望我的调用恢复

// Resolver interface
interface IResolver {
// Pass payment info as calldata only the manager should have the right to update it
function resolve(uint256 amount, ResolverOptions calldata resolverOptions) external returns (uint256);
// Reverts if the calldata passes is not a proper struct
function validateAdditionalCalldata(bytes calldata additionalCalldata) external view;
}

我已经创建了一个类来实现这个:

struct fooResolverOptions {
address[] fooAddresses; 
uint256[] fooAmounts; 
}
contract FooResolver is IResolver {
// Validate the additional calldata passed to the resolver contract
function validateAdditionalCalldata(bytes calldata additionalCalldata) view external {
// Convert the additional calldata to bytes memory
bytes memory additionalCalldataMemory = additionalCalldata;
// Decode the additional calldata as a FooResolverOptions struct
FooResolverOptions memory fooOptions;
bool success = abi.decode(additionalCalldataMemory, fooOptions);

// Check if the decode was successful
require(success, "Invalid additional calldata");
}
}

None of the Way's I've tried decode work:

bool success = abi.decode(additionalCalldataMemory, fooOptions);

这种方式声明decode没有返回值。

FooResolverOptions memory fooOptions;
abi.decode(additionalCalldata, fooOptions);

This way声明它需要一个类型元组。我如何解码结构数据,并验证它成功吗?

Solidity目前(v0.8)不支持abi.decode()中的动态参数,因此您需要编写逻辑来验证预定义的类型集。


bytes calldata additionalCalldata在您的示例中是一个字节数组,因此abi.decode(additionalCalldataMemory, <types>);试图将二进制解码为您传递的任何<types>。如果输入符合类型长度,它将简单地将值解码为该类型。

同时适合booladdress类型的示例,因此两个操作都成功:

function validateAdditionalCalldata() pure external returns (bool, address) {
bytes memory additionalCalldataMemory = hex"0000000000000000000000000000000000000000000000000000000000000001";
bool decoded1 = abi.decode(additionalCalldataMemory, (bool));
address decoded2 = abi.decode(additionalCalldataMemory, (address));
return (decoded1, decoded2);
}

当值不适合类型时,抛出异常。未捕获异常有效地恢复事务或调用。但是,您可以使用try/catch来捕获异常。

pragma solidity ^0.8;
contract FooResolver {
function validateAdditionalCalldata() external view returns (bool, address) {
// does not fit `bool` but still fits `address`
bytes memory additionalCalldataMemory = hex"0000000000000000000000000000000000000000000000000000000000000002";
bool decoded1;
try this.decodeToBool(additionalCalldataMemory) returns (bool decodedValue) {
decoded1 = decodedValue;
} catch {
decoded1 = false;
}
address decoded2 = abi.decode(additionalCalldataMemory, (address));
return (decoded1, decoded2);
}
// workaround - try/catch can be currently (v0.8) used on external function calls - but not on native function calls
function decodeToBool(bytes memory data) external pure returns (bool) {
return abi.decode(data, (bool));
}
}

最新更新