Verification procedure lacks minimum confirmations check
Description
The _verify
function is an essential component of the ZKBridgeOracleV2 contract. It ensures that the parameters of each particular packet that has been transmitted cross-chain are legitimate, and it determines whether those packets can be forwarded to the Receive Ultra-Light Node (ULN).
function _verify(
bytes32 _blockHash,
bytes32 _receiptHash,
uint32 _srcEid,
address _receiver,
bytes memory _packetHeader,
bytes32 _payloadHash
) internal {
IBlockUpdater blockUpdater = blockUpdaters[_srcEid];
if (address(blockUpdater) == address(0)) revert UnsupportedUpdater(_srcEid);
(bool exist, uint256 blockConfirmation) = blockUpdater.checkBlockConfirmation(_blockHash, _receiptHash);
if (!exist) revert BlockNotSet();
(address receiverLib,) = layerZeroEndpointV2.getReceiveLibrary(_receiver, _srcEid);
IReceiveUlnE2(receiverLib).verify(_packetHeader, _payloadHash, uint64(blockConfirmation));
}
In the current implementation, the function checks whether the given _blockHash
is valid for the _receiptHash
, and if so, it forwards the specific packet on to the Ultra-Light Node.
As per the official LayerZero DVN documentation↗ (point 4) requirements, however, prior to the Ultra-Light Node verification, the _verify
function must ensure that the packet has accrued enough block confirmations.
Impact
Lack of an adequate verification procedure might lead to the exclusion of the DVN from the LayerZero Verification layer, as it might propose to verifications packets that have not yet passed enough block confirmations.
Recommendations
We recommend implementing the following checks that ensure all LayerZero standards are respected adequately:
function _verify(
bytes32 _blockHash,
bytes32 _receiptHash,
uint32 _srcEid,
address _receiver,
bytes memory _packetHeader,
bytes32 _payloadHash
) internal {
// ...
(address receiverLib,) = layerZeroEndpointV2.getReceiveLibrary(_receiver, _srcEid);
+ UlnConfig memory ulnConfig = IReceiveUlnE2(receiverLib).getUlnConfig(
+ _receiver,
+ _srcEid
+ );
+
+ require(
+ blockConfirmations >= ulnConfig.confirmations,
+ "ZkBridgeOracleV2: packet not verified"
+ );
IReceiveUlnE2(receiverLib).verify(_packetHeader, _payloadHash, uint64(blockConfirmation));
}
Remediation
This issue has been acknowledged by Polyhedra Network, and a fix was implemented in commit 17df5bda↗.