乐趣区

关于区块链:如何在智能合约中调用另一个合约的函数

智能合约是在区块链中被执行的一段程序,因为它们在区块链上执行,所以不依赖于任何的中心化服务器。目前最支流的智能合约编程语言是 Solidity。

在以太坊区块链中,智能合约能够和其余曾经部署的智能合约进行交互。除了以太坊,其余 EVM 兼容的区块链(应用以太坊虚拟机执行智能合约的区块链)也都有这个特点。

以下是须要在一个智能合约中调用其余合约的一些场景:

  • 通证的铸造者和发行人,通过一个合约来调用通证的智能合约来发行它。
  • 去中心化交易所(DEX)在进行通证交易的时候,始终都须要和其余智能合约相交互。
  • 当你想通过 Chainlink Data Feed 取得一个通证价格的时候,你的智能合约也须要和资产的 aggregator 相交互,这里的 aggregator 也是一个智能合约。
  • 当你应用 Chainlink VRF 的时候,你的合约须要给 VRF Coordinator 发送一个申请,Coordinator 才能够将随机数发送回你的智能合约。
  • 在通过 Chainlink Keepers 自动化执行智能合约的时候,你须要创立 Keepers Upkeep,而 Upkeep 须要通过一个合约来查看和执行你部署的用户合约。

    为什么要在一个合约中调用另外一个合约的函数?

    有的时候,一个利用是由多个合约组成的。比方,我已经创立过一个利用,它是由三个合约组成的并且彼此之间须要交互,然而我没法将它部署在以太坊的主网上,因为它们占的空间太大了,超出了区块限度。我不得不将这个利用重构为 5 个更小的智能合约,这样这个利用才能够被公布。

另一个乏味的利用场景是可降级的合约。区块链是不可更改的,这就意味着在智能合约部署当前,代码就不能被批改了。然而能够通过代理函数来指向其余合约来实现“降级”。

如果你想要扭转逻辑,你能够给代理合约提供一个不同的指标合约地址,比方一个更新过的合约。还能够把逻辑和数据分到不同的智能合约中。这样,逻辑合约能够被代理合约降级或者替换,然而所有的数据还是存储在数据合约之中。

这个个性十分有用,因为它容许代码被反复利用,部署的合约能够被当成一个库来应用。因而,它还能够缩小部署时的耗费,因为当合约能够被重复使用的时候,每次新的利用须要部署的合约就可能变少。

Solidity 中调用另一个智能合约

让咱们应用 Remix 这个在线 IDE 来进行一些尝试。

创立你的第一个智能合约

创立一个文件,用来存储智能合约,你能够将多个智能合约存储在一个文件中!

  • 在 Remix 中,点击右边工具栏的“File Explorers”。
  • 点击“Create a new file”按钮。
  • 给你的文件命名为 Contracts.sol

你将要在这个文件中编写并且部署两个合约。
首先,定义 SPDX license 信息和编译器版本。复制并且粘贴这部分代码:

// SPDX-License-Identifier: MIT

pragma solidity 0.8.16;

Counter 合约

第一个合约是“Counter”,合约中只有一个数字自增的函数。
复制并且粘贴这个例子:

contract Counter {
    uint public number;
    function increment() external {number += 1;}
}

Counter 合约有:

  • 一个公共的变量 number,是一个无符号整型变量,这个变量会做自增。
  • 一个函数 increment 给整型变量减少 1。它是一个 external 函数,所以它能够被其余合约发送的交易调用。

编译 Counter 合约

  1. 在右边工具栏中找到“Solidity compiler”按钮。
  2. 点击“Compile Contracts.sol”按钮
  3. Enable 主动编译(auto-compile)选项
  4. 看下有没有绿色的标记,如果有的话就阐明编译胜利了

部署 Counter 合约

  1. 在右边的工具栏,点击按钮“Deploy and run transactions”。
  2. 当初,咱们只有一个智能合约,所以“Counter”在“Contracts”下拉菜单中会被主动抉择。
  3. 点击“Deploy”按钮

在下方找到部署好的合约,而后复制它的地址。就像上面这个地址:

0xd9145CCE52D386f254917e481eB44e9943F39138
你会看到如下图所示:

在右边工具栏的下方能够找到部署好的合约

与 Counter 合约交互

关上 Counter 合约而后:

  1. 点击“number”按钮,而后查看它的值是不是 0。
  2. 点击“increment”按钮,发送一个交易来给数字减少 1。
  3. 再次点击“number”按钮,查看当初的值是不是 1。

这个是最终后果:

counter 合约的最终后果

CounterCaller 合约

当初咱们第一个合约 Counter 曾经部署了,让咱们创立另一个合约来应用 Counter 合约中的 increment 函数。这个机制就像是依赖注入(Dependency Injection),调用者能够通过合约函数的签名和变量来初始化一个合约。

在 Contract.sol 文件的底部复制和粘贴以下的代码:

contract CounterCaller {
    Counter public myCounter;

    constructor(address counterAddress) {myCounter = Counter(counterAddress);
    }

    function counterIncrement() external {myCounter.increment();
    }
}

CounterCaller 合约有:

  • 一个叫 myCounter 的变量,数据类型就是 Counter。这意味着咱们曾经将行将调用的合约作为一个数据类型,以便咱们能够通过这个变量来取得合约的函数和变量。
  • 构造函数,构造函数只有在部署的过程中才会被调用,它会应用之前部署的 Counter 合约的地址初始化 myCounter。
  • counterIncrement 函数会通过 myCounter 调用 increment 函数,这里的 myCounter 就像是指向 Counter 智能合约的“指针”。

请看残缺的 Contracts.sol 文件:

// SPDX-License-Identifier: MIT
pragma solidity 0.8.16;

contract Counter {
    uint public number;

    function increment() external {number += 1;}
}

contract CounterCaller {
    Counter public myCounter;

    constructor(address counterAddress) {myCounter = Counter(counterAddress);
    }

    function counterIncrement() external {myCounter.increment();
    }
}

编译 CounterCaller 合约

  1. 如果你曾经 enable 来 auto-compile 选项,它就曾经实现了编译。
  2. 查看按钮旁边的绿色按钮,已确定是否曾经编译胜利。
  3. 或者,依据之前的步骤去编译 Counter 合约。

当初,让咱们来部署 CounterCaller 合约。在右边的工具栏中,点击按钮“Deploy and run transactions”。

  1. 在合约的下拉菜单中,抉择 CounterCaller。
  2. 在 Deploy 按钮旁边粘贴 Counter 合约的地址。
  3. 点击“Deploy”按钮。

部署 ContractCaller 合约。

与 CounterCaller 合约交互

在右边工具栏中找到 CounterCaller 合约,而后开展。

  • 点击“myCounter”按钮而后查看 Counter 的地址。
  • 点击“counterIncrement”按钮,发送交易来调用 Counter 合约中的 increment 函数。
  • 在 Counter 合约中点击 number 按钮,验证数字是否减少了 1,当初应该曾经是 2 了。
    这是最终的后果:
  • 与 CounterCaller 合约交互。*

这个根底的例子演示了如何从在一个合约中调用另一个合约。

还有一些别的形式在不同的合约之间相互调用,只有你晓得部署好的合约的地址,函数和公共变量,另一个合约就能够调用它。

在你晓得了合约中可能调用另一个合约之后,你就能够:

  • 将一个合约分成多个合约
  • 设计简单的 dApp 的架构
  • 实现代码的复用
  • 创立工厂合约(一个能够创立别的合约的合约)

您能够关注 Chainlink 预言机并且私信退出开发者社区,有大量对于智能合约的学习材料以及对于区块链的话题!

退出移动版