-
solidity 智能合约之间的调用
2019-07-30 15:43:34智能合约之间的调用 在区块链上,有些功能往往无法通过一个智能合约完成,此时便会用到智能合约之间的调用。本篇文章带大家通过具体示例来了解一下智能合约之间的调用。 在智能合约的编译过程中,有两种情况:调用者...智能合约之间的调用
在区块链上,有些功能往往无法通过一个智能合约完成,此时便会用到智能合约之间的调用。本篇文章带大家通过具体示例来了解一下智能合约之间的调用。
在智能合约的编译过程中,有两种情况:调用者和被调用者在一个sol文件中和分别在不同的文件中。
同sol文件的智能合约调用
在下面的智能合约中,Demo1和Demo在同一个文件中,可进行同时编译,然后逐个发布。
pragma solidity ^0.5.10; contract Demo1{ uint public data; function setData(uint _data) public { data = _data; } } contract Demo2{ function toSetData(Demo1 demo1,uint _data) public { demo1.setData(_data); } }
当发布完成,可通过第Demo2的toSetData方法进行Demo1方法的调用。传递的第一个参数为Demo1的智能合约地址,第二个参数为要设置的值。
不同sol文件的智能合约调用
在大多数情况下,两个智能合约不存在于同一个sol文件中,那么就需要使用另外一种形式来进行调用。还拿调用Demo1方法来举例,用另外一个sol文件中的Demo3来调用Demo1。
首先需要声明接口,然后在Demo3中直接调用对应的接口。
pragma solidity ^0.5.10; contract Demo1{ function setData(uint _data) public; } contract Demo3{ function toSetData(Demo1 demo1,uint _data) public { demo1.setData(_data); } }
调用接口是传递的参数依旧同第一种情况。
原文链接:https://www.choupangxia.com/2019/07/30/solidity-智能合约之间的调用/
程序新视界
关注程序员的职场生涯,大量优质学习资源、技术文章分享
-
以太坊智能合约之间的调用
2019-06-22 19:11:10已经有一个代币合约如C,需要实现一个合约,在这个合约中调用代币合约C中的transfer函数,即转代币的函数。 要在一个合约中调用另一个合约,可用用以下三种方式调用。 CALL:最常用调用,内置变量msg的值会被修改为...最近有个新的需求
已经有一个代币合约如C,需要实现一个合约,在这个合约中调用代币合约C中的transfer函数,即转代币的函数。要在一个合约中调用另一个合约,可用用以下三种方式调用。
- CALL:最常用调用,内置变量msg的值会被修改为调用者,执行环境为被调用者的运行环境。
- DELEGATECALL:调用后内置变量msg的值不会修改为调用者,但执行环境为调用者的运行环境。
- CALLCODE和DELEGATECALL: 是在调用者的上下文中执行, 可以修改调用者的storage; CALLCODE 阻止msg.sender和msg.value传递;
而DELEGATECALL不阻止;
在A的合约中,B.callcode(c的函数): c看到msg.sender是B;
在A的合约中,B.delegatecall(c的函数): c看到msg.sender是A;可以看到,这三种方式都并不符合我们的需求。
方法只有,先让用户调用代币合约C中的approve方法,再调用下面实现的合约中的depositToken方法。
pragma solidity ^0.4.25;contract Deposit { bool public stopped = false; uint256 public totalDeposit=0; uint256 minDepositValue; address owner; address cTokenAddr=0x01c2ce7bd1bc34eed8a99d0ea0abee305362c143; uint256 minBlockGap; mapping(address => mapping(string=>uint256)) depositRecords; mapping(address=>mapping(string=>uint256)) withdrawRecords; uint256 public account=0; uint256 public blocknum ; constructor(uint256 _minValue,uint256 _minBlockGap) public { owner=msg.sender; minDepositValue=_minValue; minBlockGap=_minBlockGap; } event Withdraw(address indexed _from, string indexed _pk, uint indexed _value); event DepositToken(address indexed _from,address indexed _to,uint256 indexed _value); function depositToken(address _to,uint256 _value,string pk) public isRunning validAddress returns (bool sucess) { require(_value>minDepositValue); bytes4 transferFromMethodId = bytes4(keccak256("transferFrom(address,address,uint256)")); if(cTokenAddr.call(transferFromMethodId,msg.sender,_to, _value)){ depositRecords[msg.sender][pk]+=_value; totalDeposit+=_value; emit DepositToken(msg.sender,_to,_value); return true; } return false; } function setMinBlockGap(uint256 _blockGap) public onlyOwner { minBlockGap=_blockGap; } function withdraw(uint256 _value,string _pk) public onlyOwner isRunning validAddress returns (bool sucess) { require(depositRecords[msg.sender][_pk]>_value); uint256 blockNumGap=getBlockNumGap(_pk); if(blockNumGap<minBlockGap) return false; bytes4 transferMethodId = bytes4(keccak256("transfer(address,uint256)")); if(cTokenAddr.call(transferMethodId,msg.sender, _value)){ depositRecords[msg.sender][_pk]-=_value; withdrawRecords[msg.sender][_pk]=0; totalDeposit-=_value; emit Withdraw(msg.sender,_pk,_value); return true; } return false; } function getDeposit(string pk) public view returns (uint256){ return depositRecords[msg.sender][pk]; } function getDepositByAddr(address addr,string pk) public onlyOwner view returns(uint256){ return depositRecords[addr][pk]; } function RequestWithdraw(string pk) public returns (bool){ getBlockNumGap(pk); } function getwithdrawRecords(string pk) public view returns (uint256){ return withdrawRecords[msg.sender][pk]; } function getBlockNum() private view returns (uint256){ return block.number; } function getBlockNumGap(string pk) private returns (uint256){ uint256 number=getBlockNum(); if (withdrawRecords[msg.sender][pk]==0){ withdrawRecords[msg.sender][pk]=number; return 0; }else{ return number-withdrawRecords[msg.sender][pk]; } } function getTotalDeposit() public onlyOwner view returns (uint256){ return totalDeposit; } function stop(address _to,bool ifTransfer) public onlyOwner returns (bool sucess) { stopped=true; if(!ifTransfer){ return true; } bytes4 methodId = bytes4(keccak256("transfer(address,uint256)")); if(cTokenAddr.call(methodId,_to,totalDeposit)){ totalDeposit=0; return true; } return false; } function () payable public { revert(); } function start() public onlyOwner { stopped = false; } modifier onlyOwner { require(msg.sender == owner); _; } modifier isRunning { require(!stopped); _; } modifier validAddress { require(address(0) != msg.sender); _; } }
-
智能合约之间调用msg.sender解析
2020-05-14 10:49:55msg.sender在构造函数中: //构造函数 constructor() public { owner = msg.sender; } function increse(address receiver, uint amount) public{ ...在构造函数中,msg.sender等于部署该合约的地址; ...msg.sender在构造函数中:
//构造函数 constructor() public { owner = msg.sender; } function increse(address receiver, uint amount) public{ require( owner == receiver); balances[receiver] += amount; }
在构造函数中,msg.sender等于部署该合约的地址;
-
区块链笔记:智能合约之合约调用方式,RPC/IPC调用,常用RPC调用框架,关于web3对象,基于Nodejs示例
2020-03-20 13:11:26合约调用方式 合约调用的三种方式 ...主要是进程之间的一个调用方式 HTTP的方式 这个是比较常见的一些方式 通常是使用JSON格式来做数据的序列化与反序列化 也就是HTTP的JSON RPC的方式 websocke...合约调用方式
- 合约调用的三种方式
IPC方式
- 通常是通过控制台的方式
- 以太网的节点在运行之后,可以打开一个控制台
- 在控制台里面呢通过输入命令的方式,可以来调取一些智能合约的方法
- IPC的方式也成为管道通信
- 主要是进程之间的一个调用方式
HTTP的方式
- 这个是比较常见的一些方式
- 通常是使用JSON格式来做数据的序列化与反序列化
- 也就是HTTP的JSON RPC的方式
websocket的方式
- 以太坊内部支持使用websocket协议直接对节点内部一些合约接口来进行调用
- 在这三种方式中,我们通过客户端来调的话是后两种,HTTP的JSON RPC的方式以及websocket方式
- 而第一种IPC的方式更多的是在本机本节点来做一些访问调试,是进程之间的一种管道通信方式
RPC/IPC调用
- 上面是Go语言版本的以太坊全节点程序
- 也是以太坊官方维护的一个优先级最高的一个节点程序的版本叫geth,也就是Go语言的eth节点
- 它运行之后,可以通过这个命令 $
geth console
,带上这么一个子命令,这样来运行全节点以后,就会进入到一个控制台,就能进入到控制台 - 在控制台里面它会打印出一些与连接相关的信息,我们可以在这里看到它有
IPC endpoint
,也就是IPC的一个连接地址 - 这里是使用MAC系统来运行的,它是在这个
/Users/mac/Library/Ethereum/geth.ipc
默认的位置生成一个这样一个文件geth.ipc
- 这个IPC的连接通信方式就是通过这个共享的一个文件来进行连接的
- 也可以来打开另外一个控制台,只要来指向这个ipc文件就可以
- 另外就是HTTP的链接地址, 我们是在本地,所以它是127.0.0.1, 端口号是8545
- 进入控制台以后可以通过很多的命令来访问以太的节点
- 控制台中输入exit命令可以退出
常用RPC调用框架
- 对于以太节点来讲,它是支持一个节点内部的RPC服务端
- 对于客户端来讲的,目前已经支持了很多种语言的版本,比如支持Javascript的语言版本叫web3.js,这个版本也是最常用的版本
- 除此以外,有面向Java语言的web3j
- 面向C#的Nethereum
- 支持Ruby语言的ethereum-ruby
- 以及随着发展可能也会去支持其他语言的版本
- 当然也可以自己来封装,这可能是因为以太RPC的支持的接口都是开源的,我们也可以自己来根据需要来来做自己的封装
Library Language Project Page web3.js JavaScript https://github.com/ethereum/web3.js web3j Java https://github.com/web3j/web3j Nethereum C# .NET https://github.com/Nethereum/Nethereum ethereum-ruby Ruby https://github.com/DigixGlobal/ethereum-ruby 关于web3对象
- web3.js对象
- 以太坊JavaScript API
- 在web3这个github仓库中可以看到, https://github.com/ethereum/web3.js/tree/1.x/packages 这个目录
- 是包含了一组已经封装好的客户端的调用库, 它是以太坊的Js版本的SDK
- 导入后,有个类叫Web3, 在web3这个库里调用了上面的各个子库,来实现了这么一个封装,可查看官网示例
- 普通 JSON RPC
- 参数和返回值都是通过json来序列化和反序列化的
- 需要配合以太坊节点使用
- 可以是正式主网节点,也可是测试部署私有或模拟节点
- 以太坊JavaScript API
- web3对象的调用测试代码
var Web3 = require('web3'); if(typeof web3 !== 'undefined') { web3 = new Web3(web3.currentProvider); } else { // set the provider you want from Web3.providers web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")); } var Version = web3.version; console.log("client version: " + version);
基于Nodejs示例
var Web3 = require('web3'); if(typeof web3 !== 'undefined') { web3 = new Web3(web3.currentProvider); } else { // set the provider you want from Web3.providers web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")); } web3.eth.getAccounts(console.log);
输出10个生成的地址
null [ '0x437615686191efF890C7cCa136cfbf21Cb6451E6', '0xe4a56746DAfDf247BF125d5809B2D6168722Eb37', '0x23604b6563d63D5f3b4C9a09ADe681F5f2811DB6', '0x4900AEeA7CC7F76E473805c50E8F0e49c1F99D8E', '0x1A32509bC3DAA2AC5493AE212064e59ebeaED34c', '0x7c0c971814dBA35D5c53E5650b71E91ecb8C31fa', '0x2DB7594e84DC79EE782f3962C1ea9cC2912c3EF1', '0x9D86096d38B4460Be319dA56265499D863ccB5c4', '0xD03cbC188201EB3AB61aC465Dc1e3A2fa517245C', '0x77238F0407aF96Fd26Fe22A9996B2349F1ebb91f' ]
- 合约调用的三种方式
-
【问链-EOS公开课】第十一课 EOS 智能合约相互调用
2018-10-12 22:46:03EOS中合约之间是可以相互调用的,主要通过inline action完成合约之间的调用。 譬如在掷骰子游戏中,存在两个玩家先下注资金,然后比较骰子大小后决定胜负,赢的那一方将获得所有的下注资金。在eosio源代码eos/build/... -
以太坊知识教程------智能合约(2)调用
2021-01-09 21:08:54合约之间通过调用或发送消息的方式进行交互 。当一个合约接收到一条消息时,它可以回复一些数据,这样消息的原发送者就能立即使用 。采用这种方法,发送一条消息就像调用一次函数。 一个智能合约能够给其他智能... -
在geth客户端调用已部署的智能合约
2018-01-31 14:51:56什么是合约? 合约是代码(它的功能)和数据(它的状态)的集合,存在于以太坊区块链的特定地址。 合约账户能够在彼此之间传递信息,进行图灵完备的...也有其他语言可以用于编写智能合约如Serpent和LLL,在下一节会 -
图文并茂详细介绍Solidity的三种合约间的调用方式 call、delegatecall 和 callcode
2021-01-20 13:15:25最近开始学习以太坊智能合约编程,其中涉及到智能合约之间的函数调用。 Solidity的三种合约间的调用方式有call、delegatecall 和 callcode这3种方式。参考了下面的文章: ...对于文章中提到的三种调用方式的异同点 ... -
调用wasm_PDX Utopia区块链协议栈支持WASM合约与Solidity之间互相调用
2021-01-14 14:23:56Ewasm智能合约在区块链的价值性能高效:WASM采用二进制编码,在程序执行过程中的性能优越;存储成本低:相对于文本格式,二进制编码的文本占用的存储空间更小;多语言支持:用户可以使用 C/C++/RUST/Go等多种语言编.... -
ETH——智能合约
2020-10-07 02:35:04智能合约是以太坊的精髓,也是以太坊和比特币最大的一个区别。 什么是智能合约 智能合约是运行在区块链上的一段代码, 代码的逻辑定义了合约的内容。 智能合约的账户保存了合约当前的运行状态 balance:当前... -
python智能合约编程_python与以太坊智能合约交互
2021-01-14 05:37:54交易必备的方法和对象w3节点对象发送交易方法封装swapContract.pymain.pypython与以太坊智能合约交互需要做一个轮询脚本之前写了基于DYDX闪电贷在Cofix和Uniswap之间套利,只要解释了套利合约中的逻辑以及怎么调用... -
第三章:版权交易系统智能合约开发
2018-10-25 16:51:311.erc20的标准和实现 2.erc721的标准和实现 3.erc721标准的改造 4.合约之间的调用和功能调试 -
学习笔记(3):第三章:版权交易系统智能合约开发-ERC20合约介绍
2021-02-21 16:58:541.erc20的标准和实现 2.erc721的标准和实现 3.erc721标准的改造 4.合约之间的调用和功能调试 -
用形式化验证缓解智能合约漏洞
2020-06-18 19:26:02Solidity已经支持对未调用其他合同的某些智能合约进行正式验证。当然,这不包括任何转让代币的合约。 下面的Solidity合同模拟了一个原始的众筹合约,该合约可以持有Token,某些人可以根据其股份提取Token。它缺少... -
2.4 部署智能合约到通道上
2020-05-21 10:12:09智能合约是介于区块链与业务系统之间,它是业务系统与区块链数据进行交互(设置,更新,获取数据)的工具。 正常情况下区块链开发分为区块链底层开发和DAPP应用开发两大类,本节之前的部署甚至定制开发都是链的底层... -
solidity 以太坊智能合约语言(三)
2018-09-05 19:00:03ABI是以太坊合约间相互调用的一种消息格式,包括从链外部调用链,或者合约之间的相互调用,类似于常见的rpc协议一样,也就是定义操作函数签名,参数编码,返回结果编码等。 1、函数 使用ABI协议的时候,必须要求在... -
hyperledger fabric2.0关键概念--智能合约--中文介绍
2020-10-24 12:08:42智能合约在可执行代码中定义不同组织之间的规则。应用程序调用一个art contract来生成记录在分类帐上的事务。 我们可以使用区块链合同将这些程序转化为可执行的网络合同智能合约–开拓各种新的可能性。这是因为智能... -
EOS系列七:智能合约通信模型、transaction、action、限制
2018-12-14 15:26:541、智能合约间的调用通信模型有内联调用和延迟调用。 2、action之间的执行完全独立,无法直接通信,如需在action间交互状态数据,则必须由一个action将数据写入EOSIO database(多索引表),再由另一个action从... -
第三章:版权交易系统智能合约开发-CSDN就业班-专题视频课程
2018-10-25 16:52:361.erc20的标准和实现 2.erc721的标准和实现 3.erc721标准的改造 4.合约之间的调用和功能调试 -
以太坊智能合约开发,Web3.js API 中文文档 ethereum web3.js入门说明
2018-05-03 05:04:00以太坊智能合约开发,Web3.js API 中文文档 ethereum web3.js入门说明 为了让你的Ðapp运行上以太坊,一种选择是使用web3.js library提供的web3。对象。底层实现上,它通过RPC 调用与本地节点通信。web3.js可以与... -
区块链安全————DAO攻击事件解析
2018-06-18 14:00:35跨合约调用智能合约之间的调用本质上是外部调用,可以使用message call或者创建智能合约对象的形式进行调用。(1)使用message call比如合约1调用合约2的某个方法:bytes4 methodId = bytes4(keccak... -
区块链 以太坊 虚拟机 EVM 详解
2021-01-22 11:07:58智能合约之间的调用有四种方式 以太坊虚拟机 以太坊虚拟机,简称 EVM,是用来执行以太坊上的交易的。业务流程如下图: 输入一笔交易,内部会转换成一个 Message 对象,传入 EVM 执行。 如果是一笔普通转账交易,... -
区块链安全 - DAO攻击事件解析
2018-03-05 19:52:48跨合约调用智能合约之间的调用本质上是外部调用,可以使用message call或者创建智能合约对象的形式进行调用。(1)使用message call比如合约1调用合约2的某个方法:bytes4 methodId = bytes4(keccak... -
Solidity委托调用时插槽顺序问题
2021-02-16 18:30:01在使用Solidity编写智能合约, 有时调用外部合约会使用委托调用,因为委托调用将执行逻辑交给了外部...但是需要注意的是,委托调用时需要考虑委托合约和被委托合约之间状态变量的对应关系,其底层就是插槽的对应关系。
收藏数
74
精华内容
29
-
Android安全之IntentSchemeUrl攻击
-
华工信号与系统真题与详解.zip
-
龙芯生态应用开发基础:C语言精要
-
非线性Tavis-Cummings模型的Berry相位
-
一个带下拉刷新列表的日历demo.zip
-
numpy-1.16.5-cp36-cp36m-win_amd64.whl
-
2021-02-25
-
MySQL 高可用(DRBD + heartbeat)
-
理解Object.defineProperty
-
自主机器人软件技术
-
MySQL Router 实现高可用、负载均衡、读写分离
-
激光等离子体X射线偏振度探测
-
MySQL 高可用工具 DRBD 实战部署详解
-
脉冲激光强化点阵光斑强度分布反求算法
-
ELF视频教程
-
OTL用于多目标优化的比较研究
-
Odoo Tree视图颜色组件,各行不同颜色
-
基于衍射叠栅信号的超精密定位系统
-
生活不易
-
centos查看当前用户