CertiK reviewed 4. Ignore Fud (Ignore Fud Bridge) on 16 May 2023: 8 findings, 0 critical; 6 marked fixed, 1 acknowledged, 1 open.
Report hosted on skynet.certik.com.
Trustblock does not review code.
Statuses are the security firm’s own, from its report.
| Severity | Open | Acknowledged | Fixed |
|---|---|---|---|
| Critical | 0 | 0 | 0 |
| High | 1 | 0 | 4 |
| Medium | 0 | 0 | 2 |
| Low | 0 | 1 | 0 |
In the current implementation, there is no input validation for the `setPayloadSizeLimit()` function's `_size` argument. Consequently, if an inappropriately small value, such as 1, is set, it could render the bridge unusable as all user payloads would exceed this limit. ```solidity= function setPayloadSizeLimit(uint16 _dstChainId, uint _size) external onlyOwner { payloadSizeLimitLookup[_dstChainId] = _size; } ``` ```solidity= function _checkPayloadSize(uint16 _dstChainId, uint _payloadSize) internal view virtual { uint payloadSizeLimit = payloadSizeLimitLookup[_dstChainId]; if (payloadSizeLimit == 0) { // use default if not set payloadSizeLimit = DEFAULT_PAYLOAD_SIZE_LIMIT; } require(_payloadSize <= payloadSizeLimit, "LzApp: payload size is too large"); } ```
In the Current implementation, functions `setTrustedRemote` and `setTrustedRemoteAddress` will not check if the input argument `_path` and `_remoteAddress` is valid or not. ```solidity= function setTrustedRemote(uint16 _srcChainId, bytes calldata _path) external onlyOwner { trustedRemoteLookup[_srcChainId] = _path; emit SetTrustedRemote(_srcChainId, _path); } function setTrustedRemoteAddress(uint16 _remoteChainId, bytes calldata _remoteAddress) external onlyOwner { trustedRemoteLookup[_remoteChainId] = abi.encodePacked(_remoteAddress, address(this)); emit SetTrustedRemoteAddress(_remoteChainId, _remoteAddress); } ``` It's important to note that the `TokenBridge` contract trusts the message and payload from the `TrustedRemote`. Any improper configuration of the trustedRemoteLookup can disrupt cross-chain communication among bridge contracts. This disruption could potentially result in tokens becoming permanently locked, posing a significant risk to the overall operation of the system. Furthermore, the implications could be more severe if a malicious contract is designated as the `trustedRemote`. In this scenario, the malicious contract could generate an arbitrary payload and drain the tokens within the original token bridge, posing a severe threat to the security and integrity of the system.
The current implementation displays an issue regarding the `setWithdrawalFeeBps()` function. There is no established upper limit restricting the parameter of this function, potentially enabling up to 100% of fees on bridge transactions. In this case, the contract owner will receive 100% of the bridged amount as fees while the user will lose all of their bridged assets. This lack of constraint could lead to an undue burden on users and possibly deter the utilization of the bridge.
The bridge owner can add arbitrary ERC-20 tokens for bridging through the function `registerToken()`. If the wrapped token is compromised (such as unlimited mint) on the destination chain, it can be used to drain the original token on the source chain. ```solidity= function registerToken(address token, uint8 sharedDecimals) external onlyOwner { require(token != address(0), "OriginalTokenBridge: invalid token address"); require(!supportedTokens[token], "OriginalTokenBridge: token already registered"); uint8 localDecimals = _getTokenDecimals(token); require(localDecimals >= sharedDecimals, "OriginalTokenBridge: shared decimals must be less than or equal to local decimals"); supportedTokens[token] = true; LDtoSDConversionRate[token] = 10**(localDecimals - sharedDecimals); emit RegisterToken(token); } ``` Besides, any misconfiguration of token and its decimals will lead to incorrect briding amounts, thereby posing a risk of fund loss to the users.
Function `setRemoteChainId()` does not check if the input chain Id is valid and supported by the LayerZero Endpoint. An improper setting of the `remoteChainId` can lead to tokens, once bridged out, being irretrievably locked in the bridge contract. ```solidity=1717 function setRemoteChainId(uint16 _remoteChainId) external onlyOwner { remoteChainId = _remoteChainId; emit SetRemoteChainId(_remoteChainId); } ```
The only requirement for the `_minGas` is that it is greater than 0. An insufficient min gas configuration could cause cross chain transactions to fail. Custom adapter parameters and minimum destination gas for each cross-chain path can be used when the default amount of gas (200,000) is not enough. This requires whoever calls the send function to provide the adapter params with a destination gas >= amount set in the minDstGasLookup for that chain. ```solidity= function setMinDstGas(uint16 _dstChainId, uint16 _packetType, uint _minGas) external onlyOwner { require(_minGas > 0, "LzApp: invalid minGas"); minDstGasLookup[_dstChainId][_packetType] = _minGas; emit SetMinDstGas(_dstChainId, _packetType, _minGas); } ``` ```solidity= function _checkGasLimit(uint16 _dstChainId, uint16 _type, bytes memory _adapterParams, uint _extraGas) internal view virtual { uint providedGasLimit = _getGasLimit(_adapterParams); uint minGasLimit = minDstGasLookup[_dstChainId][_type] + _extraGas; require(minGasLimit > 0, "LzApp: minGasLimit not set"); require(providedGasLimit >= minGasLimit, "LzApp: gas limit is too low"); } ```
| Address | Chain | Source code |
|---|---|---|
| 0x04cb…4d7f0x04cbefb3d208172336f74448d529148b429d4d7f | Chain: BNB Chain | Source code: Verified source |
1,044 projects reviewed · 1,375 reports · latest May 2025
See CertiK’s auditsSomething wrong on this page? A missing report, a wrong date, a finding that was fixed since. Tell us and we check it against its source.
Tell us