# 合约修饰符

By [jambestwick](https://paragraph.com/@vatalikbuterin) · 2022-02-09

---

第1章: 可支付
========

截至目前，我们只接触到很少的 **_函数修饰符_**。 要记住所有的东西很难，所以我们来个概览：

1.  我们有决定函数何时和被谁调用的可见性修饰符: `private` 意味着它只能被合约内部调用； `internal` 就像 `private` 但是也能被继承的合约调用； `external` 只能从合约外部调用；最后 `public` 可以在任何地方调用，不管是内部还是外部。
    
2.  我们也有状态修饰符， 告诉我们函数如何和区块链交互: `view` 告诉我们运行这个函数不会更改和保存任何数据； `pure` 告诉我们这个函数不但不会往区块链写数据，它甚至不从区块链读取数据。这两种在被从合约外部调用的时候都不花费任何gas（但是它们在被内部其他函数调用的时候将会耗费gas）。
    
3.  然后我们有了自定义的 `modifiers`，例如在第三课学习的: `onlyOwner` 和 `aboveLevel`。 对于这些修饰符我们可以自定义其对函数的约束逻辑。
    

这些修饰符可以同时作用于一个函数定义上：

    function test() external view onlyOwner anotherModifier { /* ... */ }
    

在这一章，我们来学习一个新的修饰符 `payable`.

payable 修饰符
-----------

`payable` 方法是让 Solidity 和以太坊变得如此酷的一部分 —— 它们是一种可以接收以太的特殊函数。

先放一下。当你在调用一个普通网站服务器上的API函数的时候，你无法用你的函数传送美元——你也不能传送比特币。

但是在以太坊中， 因为钱 (_以太_), 数据 (_事务负载_)， 以及合约代码本身都存在于以太坊。你可以在同时调用函数 **并**付钱给另外一个合约。

这就允许出现很多有趣的逻辑， 比如向一个合约要求支付一定的钱来运行一个函数。

来看个例子
-----

    contract OnlineStore {
      function buySomething() external payable {
        // 检查以确定0.001以太发送出去来运行函数:
        require(msg.value == 0.001 ether);
        // 如果为真，一些用来向函数调用者发送数字内容的逻辑
        transferThing(msg.sender);
      }
    }
    

在这里，`msg.value` 是一种可以查看向合约发送了多少以太的方法，另外 `ether` 是一个內建单元。

这里发生的事是，一些人会从 web3.js 调用这个函数 (从DApp的前端)， 像这样 :

    // 假设 `OnlineStore` 在以太坊上指向你的合约:
    OnlineStore.buySomething().send(from: web3.eth.defaultAccount, value: web3.utils.toWei(0.001))
    

注意这个 `value` 字段， JavaScript 调用来指定发送多少(0.001)`以太`。如果把事务想象成一个信封，你发送到函数的参数就是信的内容。 添加一个 `value` 很像在信封里面放钱 —— 信件内容和钱同时发送给了接收者。

> _注意： 如果一个函数没标记为_`payable`， 而你尝试利用上面的方法发送以太，函数将拒绝你的事务。

---

*Originally published on [jambestwick](https://paragraph.com/@vatalikbuterin/548FRiw5UcO3Bg53nGWP)*
