I was engaged by LayerZero to do a time bounded security review of a part of the contracts comprising their V2 deployment. The review took place over two weeks and from commit hash 80e93e7. Layerzero is a bridge protocol and my review was focused on the components in the directories: protocol/contracts and messagelib/contracts in the layerzero monorepo. This encompasses the contracts for core message passing component and also libraries related to parsing the messages which are passed. This review does not generally comment on the bridging mechanism itself but rather the fidelity of the scoped contracts to their intended purpose.
Presented in chronological order:
safeCall
and safeStaticCall
silently truncate returndata to prevent against an attack class called a 'returndatabomb', however they do not indicate to the caller of the function that an error has occurred. This can cause corruption of memory as a contract which interacts with the message passing system gets less data than the encoding would indicate, or in the worst case corruption of memory items such as replacing the end of a bytes array with zero when it is copied from returndata.
IMessageLib(_lib).messageLibType()
is not equal to their corresponded expected inverse ie isSendLib checks that the returned value is not MessageLibType.Receive. If a library ever either intentionally uses a 3rd state or unintentionally returns a value besides 1 or 0 the isSendLib and isReceiveLib will both be true breaking assumptions that send/receive is mutually exclusive. I recommend changing the checks to be that the returned enum is equal to the expected value.