zksyncEra在L1有部署智能合约,以实现L1上的修改。部署的合约有:DiamondInit、DiamondProxy、DiamondUpgrade、ExecutorFacet、GettersFacet、MailboxFacet、Verifier、ValidatorTimelock、
zksync Era 在 L1 有部署智能合约,以实现 L1 上的修改。部署的合约有:DiamondInit、DiamondProxy、DiamondUpgrade、ExecutorFacet、GettersFacet、MailboxFacet、Verifier、ValidatorTimelock、AllowList。
通过上述合约,可以看的出来 zksync Era 的链上合约部分采用的是钻石代理方法,同时也有一些其他的合约辅助。
这部分主要是直接贴近Diamond
的部分,充当起了 L1(以太坊)与 L2 (ZK Chain)之间的连接器,负责检查提交的有效性证明(零知识证明)与数据可用性,处理 L1 <-> L2 的通信(存取款等),完成 L2 上的状态转换(zksync 的状态更替)。
L2 部分也部署了一些重要的合约执行一些逻辑行为,这些合约被称为系统合约。
Diamond 部分就是采用了EIP-2535
的钻石代理,将各个功能划分为不同的切面(Facet
)。zksync 的具体实现与参考实现的区别在于访问的冻结能力。每个Facet
都有一个相关的参数,表示能否冻结对该Facet
的访问。特权参与者可以冻结 Diamond(非单独的Facet
),并且在主管(governor
)或管理员(admin
)解冻前,所有标有isFreezable
的Facet
都无法访问。
需要注意的是,钻石代理的升级系统可以被冻结,从而永久冻结该钻石代理(我的理解是解冻需要升级,升级被冻结就死循环了)
单独的Facet
,唯一功能是提供了view
和pure
方法,同时实现了loupe
功能,方便了 Facet 的管理,该 Facet 绝对不能冻结。
loupe
功能就是指获取Diamond
的有关信息(各个Facet
的地址信息、函数选择器信息),进入到合约代码中发现函数的返回值大多数都是address
类型。
该 Facet 处理 L1 <-> L2 通信 ,具有三个功能:
L1 <-> L2 通信:
桥接原生代币:
抵抗审查机制:
L1 -> L2 通信的方法是:在 L1 上发起请求 L2 的交易并在 L2 上执行。这表示用户可以调用 L1 上的函数(如调用depositERC20
函数,即向 L2 存入 ERC20 代币),然后相关交易数据将会保存在某个队列中(如priorityRequests
队列),随后触发事件(让Watcher
能够监听到,交给 L2 上的 zksync 处理)。
L1 上 user 发起的
Deposit
和FullExit
交易都可以独立于 L2 的交易,优先完成。用户在发起从 L1 到 L2 的交易时,需要以原生代币支付交易执行费用。在 L2 上的交易,由于 zksync 支持 AA 账户,所以可以用 ERC20 代币支付交易执行费用
该 Facet 接收来自 L2 的 Batches,强制执行数据的可用性,检查零知识证明(zk-proof)的有效性。状态转换分三个阶段:
commitBatches(提交 Batches)
proveBatches(验证 Batches)
executeBatches(执行 Batches)
对于commitBatches
,我们看看合约中的描述,正确符合上面的描述:
/// @notice Function called by the operator to commit new batches. It is responsible for:
/// - Verifying the correctness of their timestamps.
/// - Processing their L2->L1 logs.
/// - Storing batch commitments.
/// @param _lastCommittedBatchData Stored data of the last committed batch.
/// @param _newBatchesData Data of the new batches to be committed.
function commitBatches(
StoredBatchInfo calldata _lastCommittedBatchData,
CommitBatchInfo[] calldata _newBatchesData
) external;
每当提交一个 Batch 时,就会处理 L2 -> L1 的系统日志,每个 L2 -> L1 的系统日志都有一个 key 包含在下面中(对于源码中的多出的几个值我也不能理解为啥多出来了):
// 对于给定的 Batch ,将会包含 9 到 10 个 系统日志,SystemLogKey 中每个键都会包含一个日志(log)
enum SystemLogKey {
L2_TO_L1_LOGS_TREE_ROOT_KEY, // L2_TO_L1_MESSENGER
TOTAL_L2_TO_L1_PUBDATA_KEY, // L2_TO_L1_MESSENGER
STATE_DIFF_HASH_KEY, // L2_TO_L1_MESSENGER
PACKED_BATCH_AND_L2_BLOCK_TIMESTAMP_KEY, // L2_SYSTEM_CONTEXT_SYSTEM_CONTRACT_ADDR
PREV_BATCH_HASH_KEY, // L2_SYSTEM_CONTEXT_SYSTEM_CONTRACT_ADDR
CHAINED_PRIORITY_TXN_HASH_KEY, // L2_BOOTLOADER_ADDRESS
NUMBER_OF_LAYER_1_TXS_KEY, // L2_BOOTLOADER_ADDRESS
BLOB_ONE_HASH_KEY, // L2_PUBDATA_CHUNK_PUBLISHER_ADDR
BLOB_TWO_HASH_KEY, // L2_PUBDATA_CHUNK_PUBLISHER_ADDR
EXPECTED_SYSTEM_CONTRACT_UPGRADE_TX_HASH_KEY // L2_BOOTLOADER_ADDRESS,仅在升级协议时需要
}
L2_TO_L1_MESSENGER
包含三个 key:
L2_TO_L1_LOGS_TREE_ROOT_KEY
TOTAL_L2_TO_L1_PUBDATA_KEY
STATE_DIFF_HASH_KEY
L2_SYSTEM_CONTEXT_SYSTEM_CONTRACT_ADDR
包含两个 key:
PACKED_BATCH_AND_L2_BLOCK_TIMESTAMP_KEY
PREV_BATCH_HASH_KEY
L2_PUBDATA_CHUNK_PUBLISHER_ADDR
包含两个 key:
BLOB_ONE_HASH_KEY
BLOB_TWO_HASH_KEY
L2_BOOTLOADER_ADDRESS
包含两到三个 key:
CHAINED_PRIORITY_TXN_HASH_KEY
NUMBER_OF_LAYER_1_TXS_KEY
EXPECTED_SYSTEM_CONTRACT_UPGRADE_TX_HASH_KEY
该 Facet 负责配置的设置和升级能力,可以处理一下任务:
特权地址管理:
系统参数配置:
冻结能力:
Diamond
执行冻结与解冻,以在升级期间或对检测到的漏洞响应来保护生态系统。对 AdminFacet 的控制主要有两个实体实现:
STM(状态转换管理器):
Governance.sol
合约和管理员实例控制。换个角度,Governance.sol
由两个多签控制:管理员多签、安全委员会多签。通过协作,这些实例能够执行立刻升级的能力,而 Matter Labs 被限制为执行延时的升级。管理员:
一个单独功能的合约,是钻石代理的初始化逻辑。仅在钻石代理的构造函数中调用以此,不会作为 Facet 保存在钻石中。
函数会返回一个魔术值,如
EIP 1271
的设计,大小为 32 字节/// @notice hyperchain diamond contract initialization /// @return Magic 32 bytes, which indicates that the contract logic is expected to be used as a diamond proxy /// initializer function initialize(InitializeData calldata _initializeData) external reentrancyGuardInitializer returns (bytes32) { require(address(_initializeData.verifier) != address(0), "vt"); /* // ....... */ return Diamond.DIAMOND_INIT_SUCCESS_RETURN_VALUE; } /* 在 Diamond.sol 中的定义 bytes32 internal constant DIAMOND_INIT_SUCCESS_RETURN_VALUE = 0x33774e659306e47509050e97cb651e731180a42d458212294d30751925c551a2; // keccak256("diamond.zksync.init") - 1 */
介于 Validator 的 EOA 账户和 zksync 智能合约之间的智能合约,提供了无需信任的方法来延迟 batch 的执行,而无需修改主要的 zksync 合约。
zksync 主动监控链的活动,并通过冻结链来对任何可疑活动做出应对,使得在恢复正常运营之前有时间进行调查和缓解措施。这种临时方案是为了防止网络处于 Alpha 阶段时验证器的热密钥泄露造成任何重大影响。
该合约包含了四个主要函数:commitBatches
、 proveBatches
、 executeBatches
和 revertBatches
组成,只能由验证者调用。
当 Validator 调用commitBatches
时,相同的calldata
传播到 zksync 合约(DiamondProxy
通过call
,在ExecutorFacet
调用delegatecall
),并且为这些 Batches 分配了一个时间戳,来跟踪 Batches 的提交时间,来强制实行提交与执行 Batches 之间的延迟。然后 Validator 可以证明早已提交的 Bacthes 无论写到的时间戳,并且再次将相同的calldata
(与proveBatches
函数相关)传播到 zksync 合约。在这个延迟过去后,验证者可以调用executeBatches
将相同的calldata
传播到 zksync 合约。
ValidatorTimelock 合约的所有者与管理合约的所有者都是 Matter Labs 多签。
知识异序非交互式论证(PLONK)验证器拉格朗日基置换的修改版本(大概是链上进行零知识证明的验证的合约吧)。
存储在不同合约上调用函数的权限的智能合约。
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!