# Clarity

<div data-with-frame="true"><figure><img src="https://629346125-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FH74xqoobupBWwBsVMJhK%2Fuploads%2FhNoJj4p1Tn1ICZ3RHBqb%2Fclarity-cover.png?alt=media&#x26;token=bfe03cb2-6bc9-4bd7-840c-bd5a5b3d6e84" alt=""><figcaption></figcaption></figure></div>

{% hint style="info" %}
前往 [Clarity 快速入门课程](https://app.gitbook.com/s/Zz9BLmTU9oydDpL3qiUh/get-started/clarity-crash-course) 来构建你的第一个 Clarity 智能合约。
{% endhint %}

Clarity 是一种 **可判定的** 智能合约语言，专为 Stacks 区块链设计，侧重于可预测性和安全性优化。它从一开始就是为了让开发者更容易编写安全、可靠的智能合约而构建的。Clarity 具有多项独特特性，使其成为编写智能合约的理想选择。

Clarity 背后的设计决策在很大程度上借鉴了对常见 Solidity 漏洞的经验教训，并创造出一种从一开始就将安全性和可靠性作为核心目标的语言。

### Clarity 有何不同

以下部分摘自 [Clarity 书籍](https://book.clarity-lang.org/ch00-00-introduction.html):

智能合约语言的数量逐年增加。选择第一门语言可能颇具挑战，尤其对初学者而言。选择在很大程度上取决于你感兴趣的生态系统，尽管有些语言不止适用于一个平台。每种语言都有各自的优缺点，逐一探讨它们超出了本书的范围。相反，我们将重点介绍 Clarity 的独特之处，以及为什么如果你需要最高级别的安全性和透明度，它会是首选。

Clarity 的核心原则之一是其设计即安全。其设计过程受到对整个智能合约工程领域中常见陷阱、错误和漏洞的审视所指导。现实世界中有无数例子表明，开发者的失误导致了大量代币的损失或被盗。举两个大例子：一个后来被称为 Parity 漏洞的问题导致了价值数百万美元的以太坊不可挽回地损失。其次，对 The DAO（一个“去中心化自治组织”）的黑客攻击造成了极其严重的经济损失，以至于以太坊基金会决定进行一次有争议的硬分叉来撤销这次盗窃。这些以及许多其他错误，本可以在语言本身的设计中被预防。

#### Clarity 是解释型的，不是编译型的

Clarity 代码会被解释执行，并按原样提交到链上。Solidity 和其他语言在提交到链上之前会被编译成字节码。编译型智能合约语言的危险有两方面：首先，编译器会增加一层复杂性。编译器中的错误可能导致生成与预期不同的字节码，从而带来引入漏洞的风险。其次，字节码不可被人直接阅读，这使得验证智能合约实际上在做什么变得非常困难。问问你自己：你会签署一份你读不懂的合同吗？如果你的答案是否定的，那么为什么智能合约就应该不同呢？在 Clarity 中，所见即所得。

#### Clarity 是可判定的

可判定语言的特性在于：从代码本身，你可以确定程序将会做什么。这避免了诸如停机问题之类的问题。使用 Clarity，你可以确切知道，给定任何输入，程序都会在有限步数内停止。简单来说：程序执行一定会结束。可判定性还允许对调用图进行完整的静态分析，因此你可以在执行前准确了解精确成本。Clarity 调用不可能在调用过程中“耗尽 gas”。我们在关于可判定性的安全深度解析中，会进一步探讨这一想法，以及图灵完备性的讨论。

#### Clarity 不允许重入

重入是指一个智能合约调用另一个合约，而后者又回调到第一个合约——这次调用“重新进入”了同一逻辑。它可能让攻击者在合约尚未更新其内部余额表之前，多次触发代币提现。Clarity 的设计将重入视为一种反特性，并在语言层面禁止它。

#### Clarity 可防止溢出和下溢

当一次计算得到的数值过大或过小，以致分别无法存储时，就会发生溢出和下溢。这些事件会使智能合约陷入混乱，并可能被攻击者在编写不佳的合约中故意触发。通常这会导致合约被冻结或代币被清空。任何类型的溢出和下溢都会在 Clarity 中自动导致交易中止。

#### 对自定义代币的支持是内置的

发行自定义的同质和非同质代币是智能合约的常见用例。自定义代币功能已内置于 Clarity 语言中。开发者无需担心创建内部余额表、管理供应量以及发出代币事件。后面的章节会深入介绍如何创建自定义代币。

#### 在 Stacks 上，交易通过后置条件得到保护

为了进一步保护用户代币，可以为交易附加后置条件，以声明交易完成后链上状态已按某种方式发生变化。例如，调用智能合约的用户可以附加一个后置条件，说明调用完成后，必须恰好有 500 STX 从一个地址转移到另一个地址。如果后置条件检查失败，则整个交易会被回滚。由于自定义代币支持已直接内置于 Clarity 中，后置条件也可以以同样的方式用于保护任何其他代币。

#### 返回响应不能被置之不理

公开的合约调用必须返回所谓的响应，用于指示成功或失败。任何调用另一个合约的合约都必须正确处理该响应。未能这样做的 Clarity 合约是无效的，无法部署到网络上。像 Solidity 这样的其他语言允许使用底层调用，而不要求检查返回值。例如，如果开发者忘记检查结果，代币转账可能会静默失败。在 Clarity 中，不可能忽略错误，尽管这显然会限制开发者在错误处理上的疏忽。关于函数和控制流的章节会全面介绍响应和错误处理。

#### 组合优于继承

Clarity 采用组合优于继承的设计。这意味着 Clarity 智能合约不会像 Solidity 等语言中那样彼此继承。开发者转而定义 trait，然后由不同的智能合约去实现这些 trait。这使合约能够以更大的灵活性适配不同的接口。无需担心复杂的类树以及具有隐式继承行为的合约。

#### 访问底层链：比特币

Clarity 智能合约可以读取比特币底层链的状态。这意味着你可以将比特币交易用作智能合约的触发器！Clarity 还内置了若干函数，用于验证 secp256k1 签名和恢复密钥。
