记录一下个人学习笔记,参考网上资料,本文主要是我个人学习笔记,内容出处均在文末注明。部分内容源自ChatGPT,如文中有错误还请不吝赐教。【文本】标识的内容文本为作者个人观点,仅供参考。上一篇文章提到了zkSync原生支持账户抽象,本文对账户抽象进行详细说明。传统的以太坊网络中,主要存
记录一下个人学习笔记,参考网上资料,本文主要是我个人学习笔记,内容出处均在文末注明。部分内容源自 ChatGPT,如文中有错误还请不吝赐教。【文本】标识的内容文本为作者个人观点,仅供参考。
上一篇文章提到了 zkSync 原生支持账户抽象,本文对账户抽象进行详细说明。
传统的以太坊网络中,主要存在两类账户:
尽管这两类账户都能持有和转移资产,它们的功能和限制各不相同: EOA:1)免费创建。2)能够直接发起交易。3)主要进行 ETH 和代币转移。4)由一对密钥控制。
合约账户:1)部署需消耗 gas。2)仅在接收到交易时能发起交易。【意思就是合约交互也需要EOA触发】3)可以执行多样化的逻辑,如多签钱包,社交恢复,代付 gas 费用等。4)无私钥,完全由代码逻辑控制。
账户抽象(AA)将 EOA 和合约账户的特性统一,允许账户既能自主发起交易,又能承载复杂的逻辑。这极大地扩展了区块链账户的应用范围,使得例如智能合约钱包等应用成为可能,同时简化了用户的操作流程和为用户的资金安全提供了更安全的保障。
zkSync 上的帐户抽象协议与 EIP4337 非常相似,而 zkSync 期望在其链中有着更高的效率和用户体验,zkSync 实现了原生的账户抽象,在关键部分做了不一样的处理:【关于ERC4337协议的内容后续我会在其他文章详细阐述】
【也就是说 zkSync 协议层面支持,不用维护专门的 mempool 和 打包者,以太坊之后可能也会采用这种方案,在未来的分叉中支持】
每个智能合约账户按照官方建议遵从 IAccount 接口实现【这个和ERC4337差不多捏】,包含以下 5 个关键方法:
validateTransaction
(必须):确认交易逻辑是否满足账户规则,如果错误应回滚,若是成功则继续执行交易流程
executeTransaction
(必须):收取手续费后调用,执行交易内容
payForTransaction
(可选):不使用 Paymaster 将会直接采用正常手续费扣除方案(tx.gasprice * tx.gasLimit)
prepareForPaymaster
(可选):设置支付的方案,如:ERC-20 代币替代 Gas 支付(参考 官方案例)
executeTransactionFromOutside
(可选):该函数处理是否从外部发起交易,不是强制实现的,但官方鼓励这样做,因为在优先模式的情况下(例如,如果 Operator 没有响应),则可以考虑从 EOA 帐户开始交易。
// SPDX-License-Identifier: MIT
pragma solidity 0.8.20;
import "../libraries/TransactionHelper.sol";
bytes4 constant ACCOUNT_VALIDATION_SUCCESS_MAGIC = IAccount.validateTransaction.selector;
interface IAccount {
function validateTransaction(
bytes32 _txHash,
bytes32 _suggestedSignedHash,
Transaction calldata _transaction
) external payable returns (bytes4 magic);
function executeTransaction(
bytes32 _txHash,
bytes32 _suggestedSignedHash,
Transaction calldata _transaction
) external payable;
function executeTransactionFromOutside(Transaction calldata _transaction) external payable;
function payForTransaction(
bytes32 _txHash,
bytes32 _suggestedSignedHash,
Transaction calldata _transaction
) external payable;
function prepareForPaymaster(
bytes32 _txHash,
bytes32 _possibleSignedHash,
Transaction calldata _transaction
) external payable;
}
Paymaster:zkSync 中的支付中继
在 zkSync 的账户抽象化框架内,Paymaster
作为中心角色,使得交易发起者可以通过第三方支付交易费用,或使用非原生代币(如 ERC-20 代币)支付费用。
Paymaster
合约来负责支付交易费用。Paymaster
合约在接到支付请求后,会根据内部逻辑验证请求的有效性,并决定是否支付交易费用。Paymaster
同意支付,它会向网络支付所需的费用,使用户交易得以执行。validateAndPayForPaymasterTransaction
(必须):由引导程序调用,以验证支付方是否同意支付交易的费用。如果支付人愿意为交易付款,则此它必须至少发送 tx.gasprice * tx.gasLimit
给 Operator。若验证成功,则返回 magic 值 PAYMASTER_VALIDATION_SUCCESS_MAGIC
和交易上下文 context
(最多 1024 字节长度的字节数组,将传递给 postTransaction
方法)。
postTransaction
(可选):在事务执行后调用。请注意,与 EIP4337 不同,zkSync 抽象账户不能保证一定会调用此方法:比如事务因 out of gas 错误而失败,则不会调用此方法。它的参数分别为:的上下文 _context
、交易对象 _transaction
、交易哈希 _txHash
,由 EOAs 签名的交易哈希 _suggestedSignedHash
,交易执行的结果 _txResult
,以及付款人可能收到 Gas 退款的最大值 _maxRefundedGas
。
contract MyPaymaster is IPaymaster {
uint256 constant PRICE_FOR_PAYING_FEES = 1;
address public allowedToken;
modifier onlyBootloader() {
require(msg.sender == BOOTLOADER_FORMAL_ADDRESS, "Only bootloader can call this method");
// Continue execution if called from the bootloader.
_;
}
constructor(address _erc20) {
allowedToken = _erc20;
}
function validateAndPayForPaymasterTransaction (
bytes32,
bytes32,
Transaction calldata _transaction
) external payable onlyBootloader returns (bytes4 magic, bytes memory context) {
// 自定义处理GAS支付逻辑
}
function postTransaction (
bytes calldata _context,
Transaction calldata _transaction,
bytes32,
bytes32,
ExecutionResult _txResult,
uint256 _maxRefundedGas
) external payable onlyBootloader override {
}
receive() external payable {}
}
Paymaster
负责将这些代币转换成网络接受的费用形式。Paymaster
,为其用户群体支付交易费用,降低用户参与门槛。【Gas代付,但要注意DoS攻击】如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!