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_KEYTOTAL_L2_TO_L1_PUBDATA_KEYSTATE_DIFF_HASH_KEYL2_SYSTEM_CONTEXT_SYSTEM_CONTRACT_ADDR包含两个 key:
PACKED_BATCH_AND_L2_BLOCK_TIMESTAMP_KEYPREV_BATCH_HASH_KEYL2_PUBDATA_CHUNK_PUBLISHER_ADDR包含两个 key:
BLOB_ONE_HASH_KEYBLOB_TWO_HASH_KEYL2_BOOTLOADER_ADDRESS包含两到三个 key:
CHAINED_PRIORITY_TXN_HASH_KEYNUMBER_OF_LAYER_1_TXS_KEYEXPECTED_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)验证器拉格朗日基置换的修改版本(大概是链上进行零知识证明的验证的合约吧)。
存储在不同合约上调用函数的权限的智能合约。
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!