Omniscia Dapp Radar Audit
LzApp Manual Review Findings
LzApp Manual Review Findings
LAP-01M: Potentially Undesirable Blockchain Flexibility
Type | Severity | Location |
---|---|---|
Logical Fault | LzApp.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:
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
Type | Severity | Location |
---|---|---|
External Call Validation | LzApp.sol:L34-L39, L42-L44 |
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:
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.