Skip to content

GitLab

  • Projects
  • Groups
  • Snippets
  • Help
    • Loading...
  • Sign in
issue
issue
  • Project overview
    • Project overview
    • Details
    • Activity
    • Releases
  • Repository
    • Repository
    • Files
    • Commits
    • Branches
    • Tags
    • Contributors
    • Graph
    • Compare
  • Issues 23
    • Issues 23
    • List
    • Boards
    • Labels
    • Service Desk
    • Milestones
  • Wiki
    • Wiki
  • Snippets
    • Snippets
  • Members
    • Members
  • Activity
  • Graph
  • Create a new issue
  • Commits
  • Issue Boards
Collapse sidebar

新注册的用户请输入邮箱并保存,随后登录邮箱激活账号。后续可直接使用邮箱登录!

  • chainmaker
  • issueissue
  • Issues
  • #801

Closed
Open
Opened Aug 23, 2023 by jian wang@yanshu1 of 18 tasks completed1/18 tasks

在evm中,使用solidity合约调用其他solidity合约返回值问题

【问题分类】

  • [] bug
  • P2P网络相关(包含libp2p,liquid)
  • 链账户身份与权限相关(证书问题、public、多签投票问题)
  • 核心交易引擎相关(交易池、DAG)
  • 共识相关
  • 智能合约相关
  • 存储相关
  • SDK相关
  • 长安链CMC工具
  • 长安链管理台
  • 长安链浏览器
  • 长安链合约IDE
  • 长安链web签名插件
  • 跨链相关
  • 轻节点相关
  • 隐私计算相关
  • 密码学相关
  • 环境依赖
  • 其他补充:

【问题描述】(请对问题进行描述,方便定位问题)

在issue-789中,使用docker部署,合约内部调用其他合约会报jump out of range异常,考虑可能是版本问题后,采用脚本直接部署,chainmaker分支代码为2.3.2,使用当前分支可以直接调用跨链,但是使用过程中有2个问题。 其一:智能合约地址如果是以0x开头的哈希字符串,自己本身调用是没有问题的,如果作为方法参数,以0x开头会出现contract name not found的异常,如果去掉0x则不会出现这个问题。 其二:返回值中含有特殊字符,无法正常解析返回参数

具体的现象,操作步骤,前置条件等,尽可能描述清楚,有截图说明更佳

pragma solidity >=0.5.0 <0.6.0;

contract HelloWorld {
    string name = "HelloWorld!";

    constructor(string memory n) public {
        name = n;
    }

    function get() public view returns (string memory) {
        return name;
    }

    function set(string memory n) public {
        name = n;
    }

    function get1(string memory s) public pure returns (string memory) {
        return s;
    }

    function get2(string memory s1, string memory s2) public pure returns (string memory) {
        return string(abi.encodePacked(s1, s2));
    }
}

pragma solidity >=0.4.22 <0.6.0;

contract  Test {

    function callOtherContract(address contractAddress,string memory method,string memory n)public  returns(bytes memory result)
    {
        bool success;
        (success, result) = contractAddress.call( abi.encodeWithSignature(method, n));
        return result;
    }
    function get() public view returns(string memory){
        return "1111";
    }

}

###部署hellword合约

    public static String deployHelloWorld(ChainClient chainClient) throws Exception {
        ResultOuterClass.TxResponse responseInfo = null;
        //这里的合约地址和evm有点差异,不能以0x开头,否则在下文作为参数调用时会提示contract name not found
        String contractAddress = CryptoUtils.nameToAddrStr("HelloWorld", ChainConfigOuterClass.AddrType.ETHEREUM);
        try {
                 byte[] byteCode = FileUtils.getResourceFileBytes("HelloWorld.bin");
            String deployFunction = FunctionEncoder.encodeConstructor(Arrays.asList(new Utf8String("HelloWorld2023")));
            Map<String, byte[]> queryParamMap = new HashMap<>();
            queryParamMap.put("data", deployFunction.getBytes());
            System.out.println("hello word contract address:" + contractAddress);
            Request.Payload payload = chainClient.createContractCreatePayload(contractAddress, "1", byteCode,
                    ContractOuterClass.RuntimeType.EVM, null);
            Request.EndorsementEntry[] endorsementEntries = SdkUtils
                    .getEndorsers(payload, new User[]{chainClient.getClientUser()});
            responseInfo = chainClient.sendContractManageRequest(payload, endorsementEntries, 10000, 10000);
            System.out.println("response:" + responseInfo.toString());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return contractAddress;
    }

###部署test合约

    public static void deployTest(ChainClient chainClient,String contractAddress) throws Exception {
       ResultOuterClass.TxResponse responseInfo = null;
        String testAddress = CryptoUtils.nameToAddrStr("Test", ChainConfigOuterClass.AddrType.ETHEREUM);
        try {
            byte[] byteCode = FileUtils.getResourceFileBytes("Test.bin");
            Request.Payload payload = chainClient.createContractCreatePayload(testAddress, "1", byteCode,
                    ContractOuterClass.RuntimeType.EVM, null);
            Request.EndorsementEntry[] endorsementEntries = SdkUtils
                    .getEndorsers(payload, new User[]{chainClient.getClientUser()});
            responseInfo = chainClient.sendContractManageRequest(payload, endorsementEntries, 10000, 10000);
            System.out.println("response:" + responseInfo.toString());
        } catch (Exception e) {
            e.printStackTrace();
        }
        callOtherContract(chainClient,contractAddress,testAddress);
    }

###test调用helloworld合约

    private static void callOtherContract(ChainClient chainClient, String contractAddress, String testAddress) throws ChainMakerCryptoSuiteException, ChainClientException {
        Function callFunction = new Function("callOtherContract", Arrays.asList(new Address(contractAddress),new Utf8String("get1(string)"),new Utf8String("12333")),
                Arrays.<TypeReference<?>>asList(new TypeReference<DynamicBytes>() {
                }));
        String callMethod = FunctionEncoder.encode(callFunction);
        HashMap<String, byte[]> callParams = new HashMap<>();
        String callMethodId = callMethod.substring(0, 10);
        callParams.put("data", callMethod.getBytes());
        ResultOuterClass.TxResponse callResult = chainClient.invokeContract(testAddress, callMethodId, null, callParams, 3000, 3000);
        byte[] byteArray = callResult.getContractResult().getResult().toByteArray();
        String callHex = Hex.toHexString(byteArray);
        List<Type> decode = FunctionReturnDecoder.decode(callHex, callFunction.getOutputParameters());
        DynamicBytes type = (DynamicBytes)decode.get(0);
        System.out.println("before:"+new String(type.getValue()));
        boolean flag32 = false;
        boolean flag96 = false;
        for (int i = 0; i < byteArray.length; i++) {
            if (flag32 && flag96) {
                break;
            }
            if (byteArray[i] == 32 && !flag32)  {
                byteArray[i] = 0;
                flag32 = true;
            }
            if (byteArray[i] == 96 && !flag96) {
                byteArray[i] = 0;
                flag96 = true;
            }
        }
        System.out.println("after:"+new String(byteArray).replaceAll("\\p{C}", "").trim());

    }

###返回结果 image

如果返回结果不特殊处理,是没有办法正确解析出来,目前只有合约调合约会出现这种情况

【相关日志文件】(如果有报错日志请贴图,或者上传附件)

chainmaker-go 的 log/system.log & bin/panic.log file *

SDK 的 sdk.log file

【系统信息】(请填写系统信息,方便定位问题)

  • chainmaker-go version * : [v2.3.2]
  • OS & version * :
  • docker镜像 version:
  • 管理台 version:
    • 如果是管理台的相关问题,请附带管理台版本,如果不是可忽略。
  • 区块浏览器 version:
    • 如果是浏览器的相关问题,请附带浏览器版本,如果不是可忽略。
  • 合约IDE version:
    • 如果是合约IDE的相关问题,请附带合约IDE版本,如果不是可忽略。
  • web签名插件 version:
    • 如果是web签名插件的相关问题,请附带web签名插件版本,如果不是可忽略。
Edited Aug 23, 2023 by jian wang
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information
Assignee
Assign to
None
Milestone
None
Assign milestone
Time tracking
None
Due date
None
Reference: chainmaker/issue#801

Copyright © 2021 ChainMaker Org. All Rights Reserved. 长安链 版权所有。