solidity进阶第二课——import和调用其他合约

import(引用)的引用方法

1.通过源文件相对位置导入,在solidity中,当你有多个文件并且想把一个文件导入文件时可以用import。

import'./someothercontract.sol';
//  ./表示同一目录
contract newContract is SomeOtherContract{
}

这样当我们合约contract目录下有一名为.someothercontract.sol的文件它会被编译器导入

2.通过源文件网址导入网上的合约。

// 通过网址引用
import 'https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/Address.sol';

3.通过npm的目录导入

import '@openzeppelin/contracts/access/Ownable.sol';

4.通过全局符号导入特定合约

import {NewContract} from './SomeOtherContract.sol';

5.引用(import)在代码中的位置为:在声明版本号之后,在其余代码之前。

 以简单合约OtherContract来调用

contract OtherContract {
    uint256 private _x = 0; // 状态变量_x
    // 收到eth的事件,记录amount和gas
    event Log(uint amount, uint gas);
    
    // 返回合约ETH余额
    function getBalance() view public returns(uint) {
        return address(this).balance;
    }

    // 可以调整状态变量_x的函数,并且可以往合约转ETH (payable)
    function setX(uint256 x) external payable{
        _x = x;
        // 如果转入ETH,则释放Log事件
        if(msg.value > 0){
            emit Log(msg.value, gasleft());
        }
    }

    // 读取_x
    function getX() external view returns(uint x){
        x = _x;
    }
}

调用OtherContract合约

我们可以利用合约的地址和合约代码(或接口)来创建合约的引用:_Name(_Address),其中_Name是合约名,_Address是合约地址。然后用合约的引用来调用它的函数:_Name(_Address).f(),其中f()是要调用的函数。

1.传入合约地址

我们可以在函数里传入目标合约地址,生成目标合约的引用,然后调用目标函数。以调用OtherContract合约的setX函数为例,我们在新合约中写一个callSetX函数,传入已部署好的OtherContract合约地址_AddresssetX的参数x

    function callSetX(address _Address, uint256 x) external{
        OtherContract(_Address).setX(x);
    }

2.传入合约变量

我们可以直接在函数里传入合约的引用,只需要把上面参数的address类型改为目标合约名,比如OtherContract。下面例子实现了调用目标合约的getX()函数。注意该函数参数OtherContract _Address底层类型仍然是address,生成的ABI中、调用callGetX时传入的参数都是address类型

    function callGetX(OtherContract _Address) external view returns(uint x){
        x = _Address.getX();
    }

复制OtherContract合约的地址,填入callGetX函数的参数中,调用后成功获取x的值

3.创建合约变量

我们可以创建合约变量,然后通过它来调用目标函数。下面例子,我们给变量oc存储了OtherContract合约的引用:

    function callGetX2(address _Address) external view returns(uint x){
        OtherContract oc = OtherContract(_Address);
        x = oc.getX();
    }

复制OtherContract合约的地址,填入callGetX2函数的参数中,调用后成功获取x的值

4.调用合约并发送ETH

如果目标合约的函数是payable的,那么我们可以通过调用它来给合约转账:_Name(_Address).f{value: _Value}(),其中_Name是合约名,_Address是合约地址,f是目标函数名,_Value是要转的ETH数额(以wei为单位)。OtherContract合约的setX函数是payable的,在下面这个例子中我们通过调用setX来往目标合约转账。

    function setXTransferETH(address otherContract, uint256 x) payable external{
        OtherContract(otherContract).setX{value: msg.value}(x);
    }

 复制OtherContract合约的地址,填入setXTransferETH函数的参数中,并转入10ETH

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
根据区块链网络中心化程度的不同,分化出3种不同应用场景下的区块链:(1)全网公开,无用户授权机制的区块链,称为公有链;(2)允许授权的节点加入网络,可根据权限查看信息,往往被用于机构间的区块链,称为联盟链或行业链;(3)所有网络中的节点都掌握在一家机构手中,称为私有链。联盟链和私有链也统称为许可链,公有链称为非许可链。  公有区块链系统 公有链中,任何节点无须任何许可便可随时加入或脱离网络。从最早的比特币系统人手介绍公有链系统的发展现状。 点对点电子现金系统:比特币与传统分布式系统的C/S , B/S或三层架构不同,比特币系统基于P2P网络,所有节点对等,且都运行同样的节点程序。节点程序总体上分为两部分:一部分是前台程序,包括钱包或图形化界面;另一部分是后台程序,包括挖矿、区块链管理、脚本引擎及网络管理等。区块链管理:涉及初始区块链下载、连接区块、断开区块、校验区块和保存区块,以及发现最长链条的顶区块。内存池管理:即交易池管理。节点将通过验证的交易放在一个交易池中,并准备好将其放入下一步挖到的区块中。邻接点管理:当一个新比特币节点初始启动时,它需要发现网络中的其他节点,并与至少一个节点连接。共识管理:比特币中的共识管理包括挖矿、区块验证和交易验证规则。比特币采用PoW共识机制,依赖机器进行哈希运算来获取记账权,同时每次达成共识需要全网共同参与运算,允许全网50%节点出错。密码模块:比特币采用RIMEMD和SHA-256算法及Base-58编码生成比特币地址。签名模块:比特币采用椭圆曲线secp256k1及数字签名算法ECDSA来实现数字签名并生成公钥。脚本引擎:比特币的脚本语言是一种基于堆栈的编程脚本,共有256个指令,是非图灵完备的运算平台,没有能力计算任意带复杂功能的任务。本课程从零到一带领你实践一个小型公链。 智能合约,Smart Contract,是一种旨在以信息化方式传播、验证或执行合同的计算机协议。 区块链领域的智能合约有以下特点:规则公开透明,合约内的规则以及数据对外部可见;所有交易公开可见,不会存在任何虚假或者隐藏的交易。 所以我们常说区块链技术具有“公开透明”“不可篡改”的特点,这些其实都是智能合约赋予区块链的。 程序员的世界里一致有个认知:相较于程序和机器,人更加不可控。人会作恶,但是代码并不会主观主动作恶。 而传统的契约行为,都是由人来制定规则,由人去执行。当然,遇到边界问题或者异常,也是由人去做界定。 但有了智能合约之后,这些就变得不一样了。 开发者通过智能合约去制定一套规则,然后发布到线上,人与智能合约进行交互,由机器去完成业务的部分,这样就规避了由人来做执行时可能造成的作弊行为。 静态类型的编程语言——Solidity,是以太坊的智能合约实现的编程语言,运行在以太坊的虚拟机 Ethereum Virtual Machine(EVM)上。 借由 Solidity,开发人员能够编写出可自我执行的应用程序,该程式可被视为一份具权威性且永不可悔改的交易合约,对已具备程式编辑能力的人而言,编写 Solidity 的难易度就如同编写一般的编程语言。 关于智能合约的应用,大名鼎鼎的 ICO 就是其中之一。除了 ICO 之外,与物联网结合赋能智能家居、投票等等,都是智能合约的应用场景。换言之,能够用机器去实现既定的规则、提高效率,且能够规避人类的作弊行为的场景,基本都是智能合约的应用场景。
Solidity 中,合约调用可以通过合约地址进行实现。合约调用的语法如下: ``` contract ContractA { function foo(uint256 x) public returns (uint256) { // do something } } contract ContractB { ContractA contractA = ContractA(0x1234567890123456789012345678901234567890); function bar() public { uint256 result = contractA.foo(123); // do something with result } } ``` 在上面的示例中,合约 B 调用合约 A 中的函数 `foo`,并将值 `123` 作为参数传递给了该函数。需要注意的是,调用 `foo` 函数会消耗 Gas,因此需要确保调用合约有足够的 Gas 储备。 在合约调用时,还需要注意传递参数的类型和顺序。Solidity 支持多种数据类型,包括整数、布尔值、字符串、地址等等。在传递参数时,需要确保参数类型和数量与被调用函数的参数类型和数量相匹配,否则会导致编译错误。 另外,如果被调用的函数是视图函数(即不修改状态的函数),则可以使用 `call` 方法进行调用。例如: ``` contract ContractA { function foo(uint256 x) public view returns (uint256) { // do something } } contract ContractB { ContractA contractA = ContractA(0x1234567890123456789012345678901234567890); function bar() public { (bool success, uint256 result) = contractA.call(abi.encodeWithSignature("foo(uint256)", 123)); require(success, "failed to call ContractA.foo"); // do something with result } } ``` 在上面的示例中,`ContractB` 调用了 `ContractA` 中的函数 `foo`,并使用 `call` 方法进行调用。需要注意的是,使用 `call` 方法时需要手动编码参数,因此需要使用 `abi.encodeWithSignature` 函数将参数编码为字节数组。另外,如果调用失败,需要使用 `require` 断言确保调用成功。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值