部署 & 运行 (第 2 部分)

已部署的合约

这部分包含了已部署的合约列表,可以通过自动生成的 UI 与之进行交互(也叫 udapp)。

已部署的合约如下图展示,默认处于折叠状态。

单击左侧的小图标可以把它打开。

打开后您就可以看到合约中的方法。每一个方法按钮可能会有不同的颜色。

  • Solidity 中标识为 constantpure 的方法会有一个蓝色按钮。单击此类按钮不会创建新交易。所以点击不会导致状态改变 — 它只会返回一个存储在合约中的值 — 所以它不会消耗你 gas 费用。

  • 那些会更改合约状态且不接受以太币的方法称为 non-payable 方法,这种方法会有一个橙色按钮。 点击它们会创建一个交易,因此会产生 gas 费用。

  • 带有红色按钮的方法是 Solidity 中的 payable 方法。单击这种按钮会创建一个新交易,并且该交易可以接受一个 value。这个 value 可以在 Gas Limit 字段下面的 Value 字段中指定。

在 Solidity 文档中查看更多关于 Solidity 修饰符的信息

如果一个方法需要输入参数,那么… 你必须填写。

输入参数

在折叠视图中输入参数

(在一个输入框中输入所有参数)

  • 输入框会告诉您每个参数是什么类型。

  • 数字和地址不需要用双引号括起来。

  • 字符串不需要用双引号括起来。

  • 参数用逗号分隔。

在上面的例子中,”delegate” 方法有 3 个参数。

在展开视图中输入参数

单击 ‘down’ 图标会展开多参数交互界面 - 您可以一次只输入一个参数。少了很多混乱!

在展开的视图中,字符串不需要用双引号括起来。

单击剪贴板图标会对输入参数进行编码并复制。 只有一组有效的输入参数可以被编码。

因此,如果您错将一个 uint8 的值输入到本该是 address 类型的输入框中,单击此处的剪贴板图标会给您返回一个错误。

低级交互

低级交互可以通过 recieve()fallback() 方法,向合约发送资金或 calldata 或者资金和 calldata 。 通常,您只有在遵循升级或代理模式时,才需要实现 fallback 方法。

低级交互在每个已部署合约的方法的下方。

请注意以下事项:

  • 如果你只是单纯地想往一个合约转账以太币,那么这个合约需要有 receive() 方法。 如果你的合约已部署,并且你想给它转账以太币,你可以输入以太币的数量(见下图中的 A),单位可以是 Ether 或 Wei 或其他,然后在低级交互的 calldata 字段中什么都不需要输入(见下图中的 B),直接单击 Transact 按钮即可(参见下图中的 C)。

  • 如果您想往您的合约发送 calldata 的同时转账以太币,那么您需要使用 fallback() 方法,并且标识方法的状态可变性为 payable

  • 如果你没有向合约转账以太币,只是发送 calldata,那么你需要使用 fallback() 方法。

  • 如果您在使用低级交互时违反规则,您将受到警告。

更多有关使用 fallbackreceive 方法的细节,请参阅solidity 文档

将元组或结构体传给一个合约方法

要传入一个元组,您需要把元素放到一个数组 [] 里面。

类似地,要将一个结构体作为方法的参数传入,属性值需要放到数组 [] 里面 。 注意,这行 pragma experimental ABIEncoderV2; 代码需要放在 solidity 文件的顶部。

将嵌套结构体传递给方法的示例

假定一个嵌套结构体是这样定义:

struct Garden {
    uint slugCount;  
    uint wormCount;
    Flower[] theFlowers;
}
struct Flower {
    uint flowerNum;
    string color;
}

如果方法签名是 fertilizer(Garden memory gardenPlot),那么输入参数的正确语法就是:

[1,2,[[3,"Petunia"]]]

为了延伸一下这个例子,这里有一个示例合约:

pragma solidity >=0.4.22 <0.7.0;
pragma experimental ABIEncoderV2;

contract Sunshine {
    struct Garden {
      uint slugCount;  
      uint wormCount;
      Flower[] theFlowers;
    }
    struct Flower {
        uint flowerNum;
        string color;
    }
      
    function fertilizer(Garden memory gardenPlot) public {
        uint a = gardenPlot.slugCount;
        uint b = gardenPlot.wormCount;
        Flower[] memory cFlowers = gardenPlot.theFlowers;
        uint d = gardenPlot.theFlowers[0].flowerNum;
        string memory e = gardenPlot.theFlowers[0].color;
    }
}

在编译、部署合约并打开部署的实例后,我们可以将下面的输入参数添加到名为 fertilizer 的方法中:

[1,2,[[3,"Black-eyed Susan"],[4,"Pansy"]]]

fertilizer 方法只接受一个 Garden 类型的参数。 Garden 类型是一个结构体。 结构体用方括号括起来。 Garden 内部有一个叫 theFlowers 数组,这个数组的元素也是结构体。 theFlowers 数组本来就有一对括号,里面的结构体元素又有另一对括号。 所以,这里出现了两个方括号。