技术研报 | 实践与探索,解锁 Starknet 安全之钥

Part 1

Starknet 简介

**Starknet 是建立在以太坊之上的第二层网络,提供高吞吐量和低 Gas 成本,同时保障着以太坊第一层的安全级别。**该系统的高效性源于其能够在链下执行计算,随后生成 ZK 证明。然后在链上验证此证明,允许将多个 L2 交易捆绑到以太坊上的单个交易中。Starknet 上的智能合约使用 Cairo 语言编写,可以无缝部署,使用户能够在这个类似以太坊的网络中进行交易。

Part 2

Cairo

**Starknet 是一个去中心化的 Validity-Rollup。**它利用 Cairo1.0 —— 一种受 Rust 启发的本地智能合约语言,在主网上开发应用程序,如 dYdX、Sorare 和 ImmutableX,从而使开发人员能够更安全、高效地编写合约。

Part 3

账户抽象化(Account Abstraction)

Starknet 的核心在于账户抽象化,其中每个账户本质上都是智能账户,消除了 EOA 的概念。这种独特的方法在所有 L1 和 L2 链中都得到应用,确保所有基础设施,包括钱包和区块浏览器,都适用于这种抽象化。这将 Starknet 定位为智能生态系统的先驱,开发人员可以在构建工具和应用程序时,知道这种抽象化是普遍适用的,而不需要考虑非抽象化账户。这确保了智能账户是用户与应用程序交互的唯一媒介。Starknet 的本地账户抽象化还消除了在 ERC-4337 中出现的由 Bundler 引入的额外复杂性。与其将基础设施和工具调整为与 Bundler 交互,不如通过指定排序器来完成 Bundler 的角色,从而简化了该流程。

下图是 Starknet 交易流程[1],仍然是从 ERC-4337 的设计原则中汲取灵感[2]。

post image

Part 4

Starknet 安全的最佳实践

#1

访问控制

当智能合约没有有效的安全措施时,访问控制就会出现问题,允许未应当有执行特定操作权限的用户访问。这种疏忽可能导致不可预测的智能合约操作,并可能导致资金损失。

例如,考虑一个设计用于创建代币的智能合约。如果缺乏严格的权限检查,这就类似于为潜在的滥用留下了机会。

在这种情况下,mint 函数是开放给任何用户调用的,允许他们 mint 新代币。▶建议: 为了解决与访问控制相关的漏洞,建议采用授权方法,例如基于角色的访问控制(RBAC)或检查所有权。您可以根据需要制定一个解决方案,也可以选择使用 OpenZeppelin 等现有的框架。 参考之前的例子,可以引入一个“所有者”变量。在合约初始化期间,会确定这个所有者的身份。随后,可以在 mint 函数中添加一个验证步骤,确保只有指定的所有者有权 mint 代币。
在这种情况下,mint 函数是开放给任何用户调用的,允许他们 mint 新代币。▶建议: 为了解决与访问控制相关的漏洞,建议采用授权方法,例如基于角色的访问控制(RBAC)或检查所有权。您可以根据需要制定一个解决方案,也可以选择使用 OpenZeppelin 等现有的框架。 参考之前的例子,可以引入一个“所有者”变量。在合约初始化期间,会确定这个所有者的身份。随后,可以在 mint 函数中添加一个验证步骤,确保只有指定的所有者有权 mint 代币。
通过加强访问控制措施,您可以确保只有拥有正确权限的人才能触发您的智能合约函数,从而最大程度地减少不必要的问题。#2Overflow & Underflow溢出,即上溢出(Overflow)和下溢出(Underflow),在合约编程中是关键考虑因素。上溢出发生在数值计算产生的结果超过存储,或者寄存器或存储器的表示能力时。容易受上溢出影响的合约可能在预期计算结果和实际计算结果之间出现明显差异,破坏合约逻辑,可能导致财务损失。在这一部分,我们深入探讨在 Starknet 智能合约中应对这些挑战的策略。 使用“felt252”数据类型可能会带来问题。超过其有效范围的操作可能会产生错误的结果:
通过加强访问控制措施,您可以确保只有拥有正确权限的人才能触发您的智能合约函数,从而最大程度地减少不必要的问题。#2Overflow & Underflow溢出,即上溢出(Overflow)和下溢出(Underflow),在合约编程中是关键考虑因素。上溢出发生在数值计算产生的结果超过存储,或者寄存器或存储器的表示能力时。容易受上溢出影响的合约可能在预期计算结果和实际计算结果之间出现明显差异,破坏合约逻辑,可能导致财务损失。在这一部分,我们深入探讨在 Starknet 智能合约中应对这些挑战的策略。 使用“felt252”数据类型可能会带来问题。超过其有效范围的操作可能会产生错误的结果:
▶建议: 为了避免这种不准确性,选择强化的数据类型:使用像 u128 或 u256 这样的数据类型,它们经过设计能够熟练地处理上溢出和下溢出情况。
▶建议: 为了避免这种不准确性,选择强化的数据类型:使用像 u128 或 u256 这样的数据类型,它们经过设计能够熟练地处理上溢出和下溢出情况。
#3重入(Reentrancy)重入是智能合约中的一个潜在漏洞,使其无意中允许外部且未经验证的代码在其范围内运行。这种风险在智能合约与另一个外部合约进行交互时出现,而后者又调用了初始合约,可能导致无限循环。实质上,重入攻击利用了这个缺陷,使恶意行为者能够不断触发合约函数,引发无休止的循环,从而可能促成未经授权的资金提取。 想象一下,在一个游戏合约中,只有经过批准的地址才有权利创建一把“NFT 剑”。一旦铸造完成,他们可以激活一个 sword_received() 函数来使用这把剑,之后将其归还给合约。然而,NFT 合约还存在一个漏洞,使其容易受到重入漏洞的影响。恶意玩家可以利用这个缺陷不断制造多把“NFT 剑”。
#3重入(Reentrancy)重入是智能合约中的一个潜在漏洞,使其无意中允许外部且未经验证的代码在其范围内运行。这种风险在智能合约与另一个外部合约进行交互时出现,而后者又调用了初始合约,可能导致无限循环。实质上,重入攻击利用了这个缺陷,使恶意行为者能够不断触发合约函数,引发无休止的循环,从而可能促成未经授权的资金提取。 想象一下,在一个游戏合约中,只有经过批准的地址才有权利创建一把“NFT 剑”。一旦铸造完成,他们可以激活一个 sword_received() 函数来使用这把剑,之后将其归还给合约。然而,NFT 合约还存在一个漏洞,使其容易受到重入漏洞的影响。恶意玩家可以利用这个缺陷不断制造多把“NFT 剑”。
恶意操作者的合约可能会以一种利用重入漏洞的方式来构建 sword_received() 函数,使其能够持续铸造一系列的“NFT 剑”。
恶意操作者的合约可能会以一种利用重入漏洞的方式来构建 sword_received() 函数,使其能够持续铸造一系列的“NFT 剑”。
post image

重入经常发生于 callback 函数中。此外,在诸如闪电贷(flash loans)之类的情况下,借贷合约可能会使用 callback 函数,以允许借款合约利用并随后偿还借入的金额。

▶建议:

**为了防范重入威胁,建议遵循“检查-效果-交互”(check-effects-interactions)的范式。**这意味着在启动对外部合约的调用之前,应优先更新合约的内部状态。参考提供的示例,在调用外部函数之前将发送者从白名单中移除是明智之举。

post image