stake.link

stake.link
DeFiHardhatBridge
27,500 USDC
View results
Submission Details
Severity: medium
Invalid

No Error handling mechanism involved for Cross Chain Messaging using CCIP

Summary

Error Handling Defensive Mechanisms should be used to prevent unexpected DOS conditions during Cross Chain Messaging. In stakeLink proper error handling mechanism is not used causing DOS in unexpected situations.

Vulnerability Details

According to the Doc's of CCIP , cross-chain messaging can involve a lot of errors in the process which should be properly checked and action must be taken accordingly. These are some of the known Errors mentioned in their Doc's and there may occur some unexpected ones in future.:

https://docs.chain.link/ccip/api-reference/errors

To be safe from unexpected DOS from both known and unknown errors, proper error handling mechanisms should be taken as shown in the below official CCIP docs:

https://docs.chain.link/ccip/tutorials/programmable-token-transfers-defensive

Some of these include adding a processing message function, checking the return messageId for Errors, retrying Failed Messages etc. But as we can see none of these are involved in the present implementation as shown here in RESDLTokenBridge.sol :

https://github.com/Cyfrin/2023-12-stake-link/blob/main/contracts/core/ccip/RESDLTokenBridge.sol#L113C1-L124C10

if (_payNative) {
if (fees > msg.value) revert InsufficientFee();
messageId = sdlPoolCCIPController.ccipSend{value: fees}(_destinationChainSelector, evm2AnyMessage);
if (fees < msg.value) {
(bool success, ) = msg.sender.call{value: msg.value - fees}("");
if (!success) revert TransferFailed();
}
} else {
if (fees > _maxLINKFee) revert FeeExceedsLimit();
linkToken.safeTransferFrom(msg.sender, address(sdlPoolCCIPController), fees);
messageId = sdlPoolCCIPController.ccipSend(_destinationChainSelector, evm2AnyMessage);
}

and here in SDLPoolCCIPController.sol:

https://github.com/Cyfrin/2023-12-stake-link/blob/main/contracts/core/ccip/base/SDLPoolCCIPController.sol#L102C1-L110C6

function ccipReceive(Client.Any2EVMMessage calldata _message) external override onlyRouter {
_verifyCCIPSender(_message);
if (_message.destTokenAmounts.length == 1 && _message.destTokenAmounts[0].token == address(sdlToken)) {
IRESDLTokenBridge(reSDLTokenBridge).ccipReceive(_message);
} else {
_ccipReceive(_message);
}
}

and here in WrappedTokenBridge.sol:

https://github.com/Cyfrin/2023-12-stake-link/blob/main/contracts/core/ccip/WrappedTokenBridge.sol#L179C1-L190C10

if (_payNative) {
if (fees > msg.value) revert InsufficientFee();
messageId = router.ccipSend{value: fees}(_destinationChainSelector, evm2AnyMessage);
if (fees < msg.value) {
(bool success, ) = _sender.call{value: msg.value - fees}("");
if (!success) revert TransferFailed();
}
} else {
if (fees > _maxLINKFee) revert FeeExceedsLimit();
linkToken.safeTransferFrom(_sender, address(this), fees);
messageId = router.ccipSend(_destinationChainSelector, evm2AnyMessage);
}

Impact

Unexpected DOS due to Errors might be caused which in worst case could lead to Lockage of User Funds as mentioned in CCIP docs as:
Defensive coding is crucial as it enables the recovery of locked tokens and ensures the protection of your users' assets

Tools Used

Manual Review, CCIP Docs

Recommendations

Implement a Proper Error handling mechanism as shown in CCIP's token-transfers-defensive Docs for receiving and sending of cross chain messages.

Updates

Lead Judging Commences

0kage Lead Judge over 1 year ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.