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 21
    • Issues 21
    • 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
  • #1363

Closed
Open
Opened May 24, 2025 by z hb@zhaohongbo0 of 17 tasks completed0/17 tasks

Solidity合约异构调用Go合约失败

【问题分类】

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

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

在长安链部署了CMNFA合约,CMC调用正常,Java调用Go合约正常,Solidity合约异构调用Go合约失败,报错信息:message: "parse cross vm param length failed"

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

以下是solidity合约代码

// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.0;

// 导入 OpenZeppelin 的 Strings 库 (请确保路径正确)
import "@openzeppelin/contracts/utils/Strings.sol";


contract SolidityToGOMint {
    // 在合约内部启用 Strings 库对 uint256 的方法
    using Strings for uint256;

    // 参数缓冲区大小不变,但修改变量名称以匹配 ChainMaker 文档示例
    string[10] public params; // <--- 修改点: 将 paramsBuffer 改为 params

    /**
     * @notice 调用指定地址的 Go 合约的 Mint 方法,接收 uint256 tokenId
     * @param goContractAddress 目标 Go 合约的地址
     * @param to 接收 token 的地址 (对应 Go 的 to)
     * @param tokenIdUint256 要铸造的 token 的 ID (uint256 类型)
     * @param categoryName token 的类别名称 (对应 Go 的 categoryName)
     * @param metadataString token 的元数据 (对应 Go 的 metadata []byte),需要预先编码为字符串
     * @return success      指示低级调用是否成功 (EVM -> Go VM 通信层面)
     * @return data         从 Go 合约返回的原始数据 (通常是 protogo.Response 的 bytes)
     */
    function callGoMint(
        address goContractAddress,
        string calldata to,
        uint256 tokenIdUint256,
        string calldata categoryName,
        string calldata metadataString
    ) public returns (bool success, bytes memory data) {
        // 1. 填充参数缓冲区 (现在填充的是 params 状态变量)

        params[0] = "CrossVMCall"; // 固定标识符
        params[1] = "Mint";        // 目标 Go 方法名

        // 参数 1: to
        params[2] = "to";
        params[3] = to;

        // 参数 2: tokenId
        params[4] = "tokenId";
        params[5] = tokenIdUint256.toString(); // 将 uint256 转换为 string

        // 参数 3: categoryName
        params[6] = "categoryName";
        params[7] = categoryName;

        // 参数 4: metadata
        params[8] = "metadata";
        params[9] = metadataString; // 预编码的字符串

        // 2. 发起异构调用
        // 使用 goContractAddress.call("")
        // EVM 会自动读取名为 'params' 的状态变量,并根据其内容构建发送给 Go VM 的实际参数。
        (success, data) = goContractAddress.call("");

        // 检查低级调用是否成功 (EVM 成功与 Go VM 通信)
        require(success, "Heterogeneous call to Go Mint failed at EVM level");

        // 'data' 将包含 Go 合约方法 (mintCore) 的完整 protogo.Response 编码。
        // 你可以在链下解析这个 'data' 来查看 Go 合约的实际 ContractResult.code 和 message。
        // 例如,如果 Go 合约返回 "only admin can mint tokens",这个信息会在 data 中。

        return (success, data); // 返回低级调用结果和 Go 合约返回数据
    }
}

传递给solidity合约的参数信息

image

尝试过将meta替换为普通的字符串也依然报错

Go合约代码为CMNFA合约,调用的函数如下

func (c *CMNFAContract) InvokeContract(method string) protogo.Response {
	if len(method) == 0 {
		return sdk.Error("method of param should not be empty")
	}
	switch method {
	case "Standards":
		return c.standardsCore()
	case "SupportStandard":
		return c.supportStandardCore()
	case "Mint":
		return c.mintCore()

func (c *CMNFAContract) mintCore() protogo.Response {
	args := sdk.Instance.GetArgs()
	to := string(args[paramTo])
	tokenId := string(args[paramTokenId])
	categoryName := string(args[paramCategoryName])
	metadata := args[paramMetadata]
	err := c.verifyToken(to, tokenId, categoryName)
	if err != nil {
		return sdk.Error(err.Error())
	}
	sender, err := sdk.Instance.Sender()
	if err != nil {
		return sdk.Error(fmt.Sprintf("get sender failed, err:%s", err))
	}
	admin, _, err := sdk.Instance.GetStateFromKeyWithExists(adminStoreKey)
	if err != nil {
		return sdk.Error(fmt.Sprintf("get admin failed, err:%s", err))
	}
	if sender != admin {
		return sdk.Error("only admin can mint tokens")
	}
	err = c.Mint(to, tokenId, categoryName, metadata)
	if err != nil {
		return sdk.Error(err.Error())
	}
	//time.Sleep(time.Second * 2)
	return sdk.Success([]byte("Mint success"))
}

image image 命令行正常执行 image

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

  • chainmaker-go version * : [v2.3.5]
  • OS & version * :

Linux version 5.15.0-124-generic (buildd@lcy02-amd64-092) (gcc (Ubuntu 9.4.0-1ubuntu1~20.04.2) 9.4.0, GNU ld (GNU Binutils for Ubuntu) 2.34) #134~20.04.1-Ubuntu SMP Tue Oct 1 15:27:33 UTC 2024
  • docker镜像 version:
docker version
Client: Docker Engine - Community
 Version:           28.0.2
 API version:       1.48
 Go version:        go1.23.7
 Git commit:        0442a73
 Built:             Wed Mar 19 14:36:56 2025
 OS/Arch:           linux/amd64
 Context:           default

Server: Docker Engine - Community
 Engine:
  Version:          28.0.2
  API version:      1.48 (minimum version 1.24)
  Go version:       go1.23.7
  Git commit:       bea4de2
  Built:            Wed Mar 19 14:36:56 2025
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          1.7.26
  GitCommit:        753481ec61c7c8955a23d6ff7bc8e4daed455734
 runc:
  Version:          1.2.5
  GitCommit:        v1.2.5-0-g59923ef
 docker-init:
  Version:          0.19.0
  GitCommit:        de40ad0
  • 管理台 version:
    • 如果是管理台的相关问题,请附带管理台版本,如果不是可忽略。
  • 区块浏览器 version:
    • 如果是浏览器的相关问题,请附带浏览器版本,如果不是可忽略。
  • 合约IDE version:
    • 如果是合约IDE的相关问题,请附带合约IDE版本,如果不是可忽略。
  • web签名插件 version:
    • 如果是web签名插件的相关问题,请附带web签名插件版本,如果不是可忽略。
Edited May 24, 2025 by z hb
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#1363

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