开发者可以通过遵循以上安全实践,避免常见的错误和漏洞,有效提升其合约的安全性。
原用标题:热度暴涨的 SOL 为何狂飙 4 倍?开发者构建 Solana 项目需要注意哪些安全问题?
封面:Solana
自今年年初以来,Solana 的生态一直处于快速发展的状态,尤其是 SOL 在过去几周内大幅上涨,让大家将目光再次转移到这个老牌项目。Marinade Finance、Lido 和 Jito 等流动性质押项目的推出让 Solana 的 TVL 相比年初增长了 1 倍。Solana 与 Visa、Shopify 等实体的合作让用户和投资者看到了 Solana 生态与现实消费者结合的巨大潜力。
目前,越来越多的开发者参与到 Solana 的生态构建中。10 月,Beosin 受邀成为 Solana Hackerhouse Shanghai 的合作伙伴,为开发者分享安全开发经验。本文 Beosin 将为大家讲解开发 Solana 智能合约的安全实践,加强项目方智能合约的安全性。
![](https://web3caff.com/wp-content/uploads/2023/11/image-285.png)
Solana 账户特点及风险
在 Solana 的设计中,所有的信息都存储在账户(Account)对象中,而账户类型分为三类:
1. 数据账户,用于存储数据。数据账户又分为系统所有账户和程序派生账户(Program Derived Address)
2. 程序账户,用于存储可执行程序,即用户/Solana 官方开发并部署的智能合约。值得注意的是,Solana 的智能合约是可以被更新/销毁的。
3. 原生账户,指 Solana 上的原生程序,它们是由节点在部署时生成的智能合约,普通用户无法更新/销毁,但和其它智能合约一样,可以被合约/RPC 调用。
注:Solana 的程序(Program)本质上和其它区块链的智能合约(Contract)类似,下文的程序等同于智能合约。
以下是 Solana 账户与以太坊账户的对比:
![](https://web3caff.com/wp-content/uploads/2023/11/image-284.png)
从上图可以看到,Solana 独特的账户模型将数据资源和执行程序分离,使其可以快速处理并发交易,但同时开发者如何处理好账户之间的关系成为了一项安全挑战。开发者需要注意以下有关账户的风险:
1. 账户依赖校验缺失
对于一个 Solana 项目来说,不同的业务场景会有不同的分层架构,并且分层架构之间的数据账户存在依赖关系。开发者需要非常清楚合约与数据账户之间的依赖关系并加入约束,避免攻击者通过伪造数据进行攻击。
![](https://web3caff.com/wp-content/uploads/2023/11/image-283.png)
2. 账户数据校验缺失
当执行某些 Instructions 时,需要对账户进行校验,以确定交互的数据对象/程序是正确的。Solana 的合约开发者可能会忽略对交互的数据/程序地址进行一致性检查。
![](https://web3caff.com/wp-content/uploads/2023/11/image-282.png)
如上图所示,主程序在调用外部程序前应验证外部程序的地址是否正确。否则黑客可以提供恶意的外部程序进行攻击。
Solana 智能合约安全实践
开发者除了避免围绕 Solana 账户产生的风险,遵循以下安全实践可以提高在开发智能合约、运行项目时的安全性:
1. 设置紧急模式
任何智能合约都可能存在未被发现的漏洞,因此,项目的开发团队应在合约中设置紧急模式并制定风险应对方案,以便在风险出现时能强制暂停合约业务并修复漏洞。
impl Mode{
pub fn transform(&mut self, desired_mode: Mode) -> Result<()>{
let new_mode = match self{
Mode::Normal => match desired_mode {
Mode::Normal => None,
Mode::Paused => Some(Mode::Paused),
Mode::Terminated => Some(Mode::Terminated),
},
Mode::Paused => match desired_mode {
Mode::Normal => Some(Mode::Normal),
Mode::Paused => None,
Mode::Terminated => None,
},
Mode::Terminated => None,
};
if let Some(mode) = new_mode{
*self = mode;
Ok(())
}else{
Err(StakingError::IllegalModeTransformation.into())
}
}
}
2. 尽量使用 Anchor 开发框架
Anchor 框架已有许多成熟的代码模版,并支持对 Solana 的大部分特性进行检查,可以避免很多易忽略的细节错误,比如跨程序调用时使用 Program<'info, T> 类型,Anchor 会帮助开发者检查调用的外部程序的地址。因此,对于 Solana 的合约开发者来说,我们建议在大部分的情况下考虑使用 Anchor 框架进行合约开发。
3. 注意数学相关问题
由于 Rust 在处理整数除法时会约去小数部分,因此在做复杂计算时开发者需要留意结果的精度问题。开发者应结合实际场景对计算结果向上/向下取整,或者对计算的数据做特别处理。对于整形溢出问题,建议开发者使用 SafeMath 或者在 Cargo.toml 中添加发布模式的溢出检查。
4. 重入检查
Solana 支持跨程序调用,但深度目前限制为 4。此限制可以防止程序可能从中间状态调用另一程序而忽略其自身可能会被回调到的情况。因此 Solana 的智能合约难以被重入攻击,但还是建议开发者应当进行重入检查。
5. Solana cli 关闭程序账户
开发者如果使用 Solana cli 关闭程序,那么需注意后续将无法通过升级或重新部署的方式还原该程序账户。
6. 注意区分类型
在 Solana 合约开发中,账户数据本质上只是一个字节数组,程序将其反序列化为自定义的账户类型。如果没有实现明确区分账户类型的方法,程序可能会使用到预期之外的账户数据。
#[program]
pub mod type_cosplay_insecure {
use super::*;
pub fn admin_instruction(ctx: Context<AdminInstruction>) -> Result<()> {
...
}
}
#[derive(Accounts)]
pub struct AdminInstruction<'info> {
admin_config: UncheckedAccount<'info>,
admin: Signer<'info>,
}
#[derive(BorshSerialize, BorshDeserialize)]
pub struct AdminConfig {
admin: Pubkey,
}
#[derive(BorshSerialize, BorshDeserialize)]
pub struct UserConfig {
user: Pubkey,
}
在上面的案例中,AdminConfig 和 UserConfig 类型具有相同的数据结构。这意味着 UserConfig 类型可以作为 AdminConfig 传入。只要存储在账户数据中的公钥与签署交易的管理员匹配, admin_instruction 指令就会继续执行,即使签名者实际上不是 Admin。
对此,开发者应该进行鉴权然后使用 Account<'info, AdminConfig> 指定 admin_config 类型为 AdminConfig,然后使用 #[account(has_one=xxx)],检查交易上下文的账户权限依赖,如下所示:
...
#[derive(Accounts)]
pub struct AdminInstruction<'info> {
#[account(has_one = admin)]
admin_config: Account<'info, AdminConfig>,
admin: Signer<'info>,
}
...
7. 对智能合约进行审计
智能合约审计是通过对智能合约代码进行系统的测试和审查,尽可能发现代码中的潜在安全漏洞,排除安全风险,确保代码没有业务逻辑漏洞,符合预期运行流程和结果。此前 Beosin 已完成对 Solana 生态 NFT 项目 Space Runners 的安全审计,保障项目安全运行。
![](https://web3caff.com/wp-content/uploads/2023/11/image-281.png)
总结
Solana 的开发者社区正在不断壮大,Beosin 之前支持的 Solana Hyperdrive 全球线上黑客松已经顺利开展,Beosin 也为整个 Solana 生态提供安全帮助。由于 Solana 独特的账户设计和采用 Rust 作为开发语言,开发者在进行相关智能合约开发时,有关代码安全方面可能存在疏漏之处。开发者可以通过遵循以上安全实践,避免常见的错误和漏洞,有效提升其合约的安全性。此前 Beosin 也对 Solana 生态相关项目被攻击事件进行分析:用一千万撬动上亿资金?Solana 生态 Mango 协议遭受黑客攻击事件分析。
免责声明:作为区块链信息平台,本站所发布文章仅代表作者及嘉宾个人观点,与 Web3Caff 立场无关。 文章内的信息仅供参考,均不构成任何投资建议及要约,并请您遵守所在国家或地区的相关法律法规。