泰山众筹系统丨泰山众筹系统开发(详细及案例)丨泰山众筹源码案例开发

简介: solidity合约内调用合约ChainMaker evm虚拟机支持solidity合约动态调用solidity合约,solidity合约动态调用solidity合约,以及solidity合约动态调用其他类型合约。

solidity合约内调用合约
ChainMaker evm虚拟机支持solidity合约动态调用solidity合约,solidity合约动态调用solidity合约,以及solidity合约动态调用其他类型合约。

8.2.1. 静态调用
静态调用,是指在调用之前,调用者必须知道被调用者合约的接口。即,必须将被调用者的接口和调用者合约一同编译。在实际执行使,调用者不能调用接口以外的方法。

静态调用示例

合约callee.sol为被调用者合约,实现了一个简单的加法功能。

// SPDX-License-Identifier: GPL-3.0

pragma solidity > 0.5.21;

//被调用者合约
contract Callee {

function Adder(uint256 x, uint256 y) public returns(uint256) {
    return x + y;
}

}
合约caller.sol为调用者合约,可以调用callee.sol合约的方法。

// SPDX-License-Identifier: GPL-3.0

pragma solidity >=0.5.21;

//被调用合约Callee的接口
abstract contract ICallee {

    //Callee.Adder的方法签名
function Adder(uint256 x, uint256 y) public virtual returns(uint256);

}

//调用者合约
contract Caller {

function crossCall(address addr, uint256 x, uint256 y) public returns(uint256) {
    ICallee callee = ICallee(addr); //将被调用合约的地址转化为ICalle接口
    return callee.Adder(x, y);      //根据接口和方法签名调用
}

}
如示例所示,调用者合约Caller所在文件内,声明了一个被调用者合约Callee的接口ICallee,接口内有Callee合约的方法签名。调用者合约获得被调用合约的地址后,即可根据实现声明的接口,调用该地址的方法了。注意,在调用者合约调用被调用者之前,必须确保被调用者合约已经部署完成。

8.2.2. 动态调用
所谓动态调用,是指调用者合约不需要提前知道被调用合约的接口,只需要在调用时,告诉调用者被调合约的方法签名即可。调用者合约不需要事前绑定被调者的接口,可以在调用时,指定任意被调用合约及其方法,更加灵活。

动态调用示例

合约dynamic_call.sol。部署Caller合约后,可以调用任意solidity合约及其方法,不限定接口。

// SPDX-License-Identifier: GPL-3.0

pragma solidity >= 0.8.0;

contract Caller {

string[10] x;
string[8] params;

function cross_call(address callee, string calldata method, string calldata key, int256 value) public {
        //注意,method必须为方法签名格式,且方法签名的参数间不能有空格,例如"save(string,int256)"
    callee.call((abi.encodeWithSignature(method, key, value));
}

}
如示例所示,调用者合约Caller可以调用任意合约的任意方法,只需要将被调用合约的地址、方法签名和参数传给调用者合约即可。

注意,被调合约的方法必须是方法签名样式,且方法签名的参数间不能有空格,如示例中注释所示,否则无法编译为准确的ABI类型的calldata,evm将无法识别。

8.2.3. 异构调用
异构调用是指,solidity合约调用其他虚拟机类型的合约,比如wasm、docker-go等,只要在ChainMaker支持范围内,都可以异构调用。

solidity执行跨合约调用时,会将参数编码为ABI格式的calldata。但,对其他虚拟机合约来说,它们的参数并不需要ABI编码,也没有ABI文件,所以无法解析从调用者solidity合约那里传递来的参数。针对这种情况,ChainMaker单独实现了一套异构调用逻辑。

​ 1 作为调用者的solidity合约需要在合约内声明一个string数组类型的状态变量,用做异构调用的参数缓冲区;

​ 2 在异构调用之前,需要将带传递的参数按顺序写入参数缓冲区;

​ 3 参数缓冲区的第一个元素(下标为0)必须是”CrossVMCall”字符串,用于让ChainMaker evm识别这是跨虚拟机的异构合约调用;

​ 4 参数缓冲区的第二个元素必须是待调用的方法名(此方法名不需要方法签名格式);

​ 5 从第三个参数开始,每两个元素一组,标识一个待传递参数,前一个元素为参数的类型或key(视被调合约而定),后一个元素为参数的值。

关于进一步理解异构调用的内容,可以参考接下来的异构调用示例。

异构调用示例

合约cross_vm_call.sol。部署CrossCall合约后,可以通过cross_call方法调用其他虚拟机类型的合约。。

// SPDX-License-Identifier: GPL-3.0

pragma solidity >= 0.8.0;

contract CrossCall {

string[10] x;
string[8] params;  //参数缓冲区

    //address类型的参数callee为被调用合约地址
function cross_call(address callee, string calldata method, string calldata time, string calldata name, string calldata hash) public {
    
//CrossVMCall is reserved key word
    params[0] = "CrossVMCall";//CrossVMCall为固定值,第一个参数必须是此值
    params[1] = method;       //方法名,例如"save"
    params[2] = "time";       //参数1的类型或key
    params[3] = time;         //参数1的value
    params[4] = "file_name";  //参数2的类型或key
    params[5] = name;         //参数2的value
    params[6] = "file_hash";  //参数3的类型或key
    params[7] = hash;         //参数2的value

      callee.call("");//跨虚拟机调用callee合约,callee.call的参数为空,evm虚拟机会从参数缓冲区读取对应的参数
}

}
如示例所示,solidity跨虚拟机异构调用时,必须提供被调合约的地址,而不能是方法名,因为合约调用方法call是solidity语法中,地址类型的成员方法,使用合约名则无法识别。

8.3. 其他虚拟机跨合约调用
相比于solidity,ChainMaker的其他虚拟机类型合约,都不支持合约创建合约,只支持合约调用合约。但同构异构都支持,且相比solidity也更加简单,只需要调用该类型合约所提供的跨合约调用接口即可。

调用示例

合约go_cross_call_evm.go 为go语言合约跨虚拟机调用soldity合约示例。

/*
SPDX-License-Identifier: Apache-2.0
*/

package main

//export init_contract
func initContract() {}

//export upgrade
func upgrade() {}

//export crossCallEvmContract
func crossCallEvmContract() {

ctx := NewSimContext()

// 获取参数
name, _ := ctx.ArgString("name")
method, _ := ctx.ArgString("method")
calldata, _ := ctx.Arg("calldata")
params := make(map[string][]byte, 1)
params["data"] = calldata

//执行跨虚拟机低啊用
if result, resultCode := ctx.CallContract(name, method, params); resultCode != SUCCESS {
    // 返回结果
    ctx.ErrorResult("failed to cross call evm contract: " + name)
} else {
    // 返回结果
    ctx.SuccessResultByte(result)
    // 记录日志
    ctx.Log("cross call evm contract result:" + string(result))
}

}

func main() {

}

相关文章
泰山众筹系统开发|解析泰山众筹模式火爆原因
最近也有不少读者私信问我这个模式,今天就在这里分析一下,泰山众筹模式的优势也就是它在市场爆火的原因。
|
JSON 区块链 数据格式
阿凡达泰山众筹系统开发(详细及程序)丨泰山众筹阿凡达系统开发(4.0运营版)
 We decided on reward and punishment measures,and then entered the agreement into the blockchain in the form of code.Once the agreed conditions are triggered,a program will automatically execute it,which is smart contract
|
新零售 人工智能 缓存
泰山众筹(阿凡达4.0)系统开发详细及方案丨泰山众筹(阿凡达4.0)开发源码及平台
新零售是指个人、企业以互联网为依托,通过运用大数据、人工智能等先进技术手段并运用心理学知识,对商品的生产、流通与销售过程进行升级改造,进而重塑业态结构与生态圈,并对线上服务、线下体验以及现代物流进行深度融合的零售新模式。
|
新零售 存储 缓存
区块链阿凡达泰山众筹商城系统开发(正式版)丨区块链阿凡达泰山众筹商城开发源码系统
“新零售”的核心要义在于推动线上与线下的一体化进程,其关键在于使线上的互联网力量和线下的实体店终端形成真正意义上的合力,从而完成电商平台和实体零售店面在商业维度上的优化升级。同时,促成价格消费时代向价值消费时代的全面转型。
阿凡达(泰山众筹)开发原理丨阿凡达(泰山众筹)系统开发(详情开发)丨阿凡达及泰山众筹源码案例部署
交易是否能够结束的关键计算在SwapMath.computeSwapStep中完成,这里计算了交易是否能在目标价格范围内结束,以及消耗的tokenIn和得到的tokenOut.这里摘取此函数部分代码进行分析
|
缓存
阿凡达泰山众筹商城开发详情丨阿凡达泰山众筹商城系统开发(开发模板)丨阿凡达泰山众筹商城源码及功能系统
 如果当前word中没有记录其他tick index,那么取这个word的最小/最大tick index,这么做的目的是,让单步交易中tick的跨度不至于太大,以减少计算中溢出的可能性
|
新零售 人工智能 前端开发
泰山众筹4.0阿凡达系统丨泰山众筹4.0阿凡达系统开发(上线版)丨泰山众筹4.0阿凡达开发源码平台
了解了线上电商和线下购物的短板,线上线下结合是新的销售通路,而这个新的销售通路就是新零售模式。在互联网工具快速发展的时期,要以互联网为依托,通过运用大数据、人工智能等先进技术手段,对商品的生产、流通与销售过程进行升级改造,进而重塑业态结构与生态圈,并对线上服务、线下体验以及现代物流进行深度融合,一是让商家生产消费者喜欢的商品,二是让消费者更容易找到自己喜欢的商品,实现线上考察、线下体验,线上线下购买。商家和消费者更有效的链接就是新零售模式。
|
存储 编译器 区块链
泰山众筹阿凡达开发(升级版)丨泰山众筹阿凡达系统开发(案例及开发)丨泰山众筹阿凡达开发源码及部署
 The blockchain social new retail system is a decentralized platform to create a new trading model.Blockchain technology is a marketing system that can decentralize sales.Through it,an open marketing ecosystem is built for businesses to promote the sales ecological cycle.Through the blockchain mall
|
数据格式 JSON
泰山众筹4.0开发案例源码丨泰山众筹4.0系统开发(详细规则及功能)丨泰山众筹4.0系统源码模式
contract ERC721 { function balanceOf(address _owner) external view returns (uint256); function ownerOf(uint256 _tokenId) external view returns (address); function safeTransferFrom(address _from, address _to, uint256 _tokenId, bytes data) external payable;