title: 29. 账户抽象 tags: cairo starknet wtfacademy accountabstratction WTF Cairo极简教程: 29. 账户抽象 我最近在学 ,巩固一下细节,也写一个 ,供小白们使用。教程基于 版本。 推特:@0xAAScience|@WTFAcademy WTF Academy 社群:Discord|微信群|官网 wtf.academy 所有代码和教程开源在 github: github.com/WTFAcademy/WTF-Cairo 在这节中,我们将会讲一下账户抽象(Account Abstraction,简称AA),并实现一个账户合约。
title: 29. 账户抽象 tags: - cairo - starknet - wtfacademy - accountabstratction
我最近在学cairo-lang,巩固一下细节,也写一个WTF Cairo极简教程,供小白们使用。教程基于cairo 2.2.0版本。
WTF Academy 社群:Discord|微信群|官网 wtf.academy
所有代码和教程开源在 github: github.com/WTFAcademy/WTF-Cairo
在这节中,我们将会讲一下账户抽象(Account Abstraction,简称AA),并实现一个账户合约。
在传统的以太坊中,有两种账户类型:
外部所有账户(EOA):由拥有私钥的任何人控制,例如MetaMask等钱包管理的账户。
合约账户(CA):由只能合约控制
在Starknet中,原生支持账户抽象(AA),所有的账户是智能合约,使用合约验证交易,使用的钱包主要是ArgentX和Braavos。
账户抽象代表了一种在区块链网络中管理账户和交易的方法。主要涉及两个关键概念:
智能合约验证其交易,摆脱了通用验证模型。
好处包括智能合约支付燃料费,支持一个账户多个签名者,以及使用替代加密签名。
2.用户体验优化
账户抽象使开发者能够设计灵活的安全模型,如对常规和高价值交易使用不同的密钥。
它提供了种子短语用于账户恢复的替代方案,简化了用户体验。
具体可以参考StarkNet Account Abstraction Model
账户抽象统一了合约账号和外部账号,它使得用户的账号具有编程性,用户可以将不同的需求适配到不同的账号,例如:
当您需要一个不同于ECDSA的签名机制时,您可以创建一个账号来实现它。
当您想要使用多个密钥来授权交易时,您可以创建一个账号来实现它。
如果您想要每周更换您账号的私钥时,您可以创建一个账号来实现它。
接下来,我们来实现一个账户合约。当智能合约遵循SNIP-6(Starknet改进提案6:标准账户接口)
中的接口时,它就变成了账户合约。
struct Call { to: ContractAddress, selector: felt252, calldata: Array<felt252> } trait ISRC6 { fn __execute__(calls: Array<Call>) -> Array<Span<felt252>>; fn __validate__(calls: Array<Call>) -> felt252; fn is_valid_signature(hash: felt252, signature: Array<felt252>) -> felt252; }
该接口总共有三个函数:
__execute__():通过账户执行一个交易。
__validate__():验证交易是否有效的执行。
is_valid_signature():确认交易签名的真实性。
接下来我们实现该账户合约。
#[starknet::contract] mod HelloAccount { use starknet::VALIDATED; use starknet::get_caller_address; use starknet::ContractAddress; use super::Call; #[storage] struct Storage {} #[abi(embed_v0)] impl SRC6Impl of super::ISRC6<ContractState> { fn is_valid_signature( self: @ContractState, hash: felt252, signature: Array<felt252> ) -> felt252 { VALIDATED } fn validate(self: @ContractState, calls: Array<Call>) -> felt252 { let hash = 0; let mut signature: Array<felt252> = ArrayTrait::new(); signature.append(0); self.is_valid_signature(hash, signature) } fn execute(self: @ContractState, calls: Array<Call>) -> Array<Span<felt252>> { let sender = get_caller_address(); assert(sender.is_zero(), 'Account: invalid caller'); let Call{to, selector, calldata } = calls.at(0); let _res = starknet::call_contract_syscall(*to, *selector, calldata.span()).unwrap(); let mut res = ArrayTrait::new(); res.append(_res); res } } }
本章我们学习了账户抽象,并实现了一个简易的账户合约。