Omniscia Dapp Radar Audit

LzApp Manual Review Findings

LzApp Manual Review Findings

LAP-01M: Potentially Undesirable Blockchain Flexibility

TypeSeverityLocation
Logical FaultLzApp.sol:L12, L19

Description:

One of the requirements for a proper LayerZero receiver implementation is the validation that the caller of the lzReceive function is the known LayerZero endpoint, a trait that is not upheld by the contract.

Impact:

An improperly specified endpoint will cause issues in messages being relayed in a trustless manner.

Example:

contracts/LZ/LzApp.sol
18constructor(address _endpoint) {
19 lzEndpoint = ILayerZeroEndpoint(_endpoint);
20}

Recommendation:

Given that the deployment of the protocol is expected to happen on Polygon, Binance, and Ethereum, we advise the usage of dedicated implementations with each endpoint hard-coded as a contract-level constant.

Alleviation:

The Dapp Radar team opted to retain the current implementation in the codebase as it permits flexibility when rapidly deploying across multiple environments. While we still advise a dedicated contract with a contract-level constant to be coded for each intended chain (and potentially a flexible test version) as advised by the LayerZero documentation itself, the Dapp Radar stated that they will gracefully handle any misconfiguration in live deployments and as such we consider this exhibit acknowledged.

LAP-02M: Outdated LayerZero Receiver Implementation

Description:

The LzApp implementation is meant to be a copy of the basic LzReceiver example that the LayerZero labs themselves have developed, however, there is a notable discrepancy between the two implementations that relates to an external call that may no longer exist in the code as well as a getter function difference. In detail, the _lzSend implementation of the official LayerZero examples repository transmits the full msg.value amount and contains no external calls to the endpoint and the getConfig function makes use of the first uint16 variable instead of invoking the endpoint's getter function for the send version.

Impact:

Improper integration of LayerZero can lead to inexecutable code and deployments.

Example:

contracts/LZ/LzApp.sol
34function _lzSend(uint16 _dstChainId, bytes memory _payload, address payable _refundAddress, address _zroPaymentAddress, bytes memory _adapterParam) internal {
35 require(trustedRemoteLookup[_dstChainId].length != 0, "LzSend: destination chain is not a trusted source.");
36
37 (uint256 messageFee, ) = lzEndpoint.estimateFees(_dstChainId, address(this), _payload, false, _adapterParam);
38 lzEndpoint.send{value: messageFee}(_dstChainId, trustedRemoteLookup[_dstChainId], _payload, _refundAddress, _zroPaymentAddress, _adapterParam);
39}

Recommendation:

We advise this discrepancy to be investigated as the Dapp Radar codebase may contain outdated code no longer compatible with the latest LayerZero implementation.

Alleviation:

The code was updated to reflect the latest LayerZero example implementation as based off their repository, thereby alleviating this exhibit.