Web3j 继承StaticStruct的类所有属性必须为Public <DynamicArray<StaticStruct>>

Web3j 继承StaticStruct的类所有属性必须为Public,属性的顺序和数量必须和solidity 里面的struct 属性相同,否则属性少了或者多了的时候会出现错位

Web3j 继承StaticStruct的类所有属性不能为private,因为web3j 是通过长度去截取返回值解析成对应的属性进行赋值的。要获取一个list对象时,web3j是按一个类的所有public属性个数去截取总长度的,再进行解析赋值到没一个属性里

StaticStruct类

复制代码
import lombok.Data;
import org.web3j.abi.datatypes.Address;
import org.web3j.abi.datatypes.StaticStruct;
import org.web3j.abi.datatypes.Type;
import org.web3j.abi.datatypes.generated.Uint256;

@Data
public class ChildStaticStruct extends StaticStruct {

    public Uint256 attr1;
    public Uint256 attr2;
    public Address attr3;

    public ChildStaticStruct(Uint256 attr1, Uint256 attr2, Address attr3) {
         super(new Type[]{attr1,attr2,attr3});
    }
}

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.web3j.abi.FunctionEncoder;
import org.web3j.abi.FunctionReturnDecoder;
import org.web3j.abi.TypeReference;
import org.web3j.abi.datatypes.Address;
import org.web3j.abi.datatypes.DynamicArray;
import org.web3j.abi.datatypes.Function;
import org.web3j.abi.datatypes.Type;
import org.web3j.protocol.Web3j;
import org.web3j.protocol.core.DefaultBlockParameterName;
import org.web3j.protocol.core.methods.request.Transaction;
import org.web3j.protocol.core.methods.response.EthCall;

import java.io.IOException;
import java.util.Arrays;
import java.util.List;

public class TestContract {
    private static final Logger logger = LoggerFactory.getLogger(TestContract.class);
    private String address;
    private Web3j web3j;
    public TestContract(String address, Web3j web3j) {
        this.address = address;
        this.web3j = web3j;
    }

    public List<ChildStaticStruct> getStaticStructList(String address) throws IOException {
        List<Type> inputParameters = Arrays.asList( new Address(address));
        List<TypeReference<?>> outputParameters = Arrays.asList(new TypeReference<DynamicArray<ChildStaticStruct>>(){});
        Function function = new Function("getStaticStructList",inputParameters,outputParameters);
        Transaction transaction = Transaction.createEthCallTransaction(null,address, FunctionEncoder.encode(function));
        EthCall response = web3j.ethCall(transaction, DefaultBlockParameterName.LATEST).send();
        List<Type> output = FunctionReturnDecoder.decode(response.getValue(),function.getOutputParameters());
        List<ChildStaticStruct> results = (List<ChildStaticStruct>)output.get(0).getValue();
        return results;
    }
}

web3j的TypeDecoder 里的decodeArrayElements 验证了是否为StructType子类,

在currOffset += getSingleElementLength(input, currOffset, cls) * 64)判断了截取的长度

复制代码
if (StructType.class.isAssignableFrom(cls)) {
                elements = new ArrayList(length);
                currOffset = 0;

                for(currOffset = offset; currOffset < length; currOffset += getSingleElementLength(input, currOffset, cls) * 64) {
                    if (DynamicStruct.class.isAssignableFrom(cls)) {
                        value = decodeDynamicStruct(input, offset + DefaultFunctionReturnDecoder.getDataOffset(input, currOffset, typeReference), TypeReference.create(cls));
                    } else {
                        value = decodeStaticStruct(input, currOffset, TypeReference.create(cls));
                    }

                    elements.add(value);
                    ++currOffset;
                }

                String typeName = Utils.getSimpleTypeName(cls);
                return (Type)consumer.apply(elements, typeName);
            } 

getSingleElementLength 验证了截取长度是根据public属性数量去截取Utils.staticStructNestedPublicFieldsFlatList(type).size(),pirvate计算长度

复制代码
static <T extends Type> int getSingleElementLength(String input, int offset, Class<T> type) {
        if (input.length() == offset) {
            return 0;
        } else if (!DynamicBytes.class.isAssignableFrom(type) && !Utf8String.class.isAssignableFrom(type)) {
            return StaticStruct.class.isAssignableFrom(type) ? Utils.staticStructNestedPublicFieldsFlatList(type).size() : 1;
        } else {
            return decodeUintAsInt(input, offset) / 32 + 2;
        }
    }

staticStructNestedPublicFieldsFlatList方面里面通过Modifier.isPublic(field.getModifiers())过滤了public

复制代码
public static List<Field> staticStructNestedPublicFieldsFlatList(Class<Type> classType) {
        return (List)staticStructsNestedFieldsFlatList(classType).stream().filter((field) -> {
            return Modifier.isPublic(field.getModifiers());
        }).collect(Collectors.toList());
    }

Modifier 里面比较了Public

复制代码
public static boolean isPublic(int mod) {
        return (mod & PUBLIC) != 0;
    }
相关推荐
2603_953527992 天前
WordPress Finale Lite 插件高危漏洞检测与利用工具 (CVE-2024-30485)
前端·python·安全·web3·xss
电报号dapp1197 天前
区块链DApp开发深度解析:概念拆解+技术架构+应用前景
架构·web3·去中心化·区块链·智能合约
电报号dapp1197 天前
公链 + DID,解锁 Web3 数字身份新范式
人工智能·web3·去中心化·区块链·智能合约
木西7 天前
RaveDAO Pro:Web3 票务系统的完整技术实现
web3·智能合约·solidity
电报号dapp1197 天前
交易所开发:构建数字资产交易的安全与高效平台
安全·web3·去中心化·区块链·智能合约
Web3VentureView8 天前
SYNBO 亮相香港 Web3 嘉年华:在 AI+Web3 时代重思链上一级市场基础设施
人工智能·web3·区块链·加密货币·web4·synbo
许强0xq9 天前
订单流战争:AI、区块链与市场透明度的终极博弈
web3·区块链·智能合约·solidity·dapp
潇楠Web3哨兵10 天前
Web3多功能监控软件 V10 :从代码层面深度剖析一款商业级双链监控系统的实现艺术!
web3
迷藏49410 天前
**发散创新:基于Solid协议的Web3.0去中心化身份认证系统实战解析**在Web3.
java·python·web3·去中心化·区块链
AI_Claude_code10 天前
ZLibrary访问困境方案三:Web代理与轻量级转发服务的搭建与优化
爬虫·python·web安全·搜索引擎·网络安全·web3·httpx