Detailed description of the impact of this finding.
we are not checking any min amount in sendprice function. when we are sending price feed to renzo connext receiver we are keeping the minamount to 0.
Proof of Concept
Provide direct links to all referenced code in GitHub. Add screenshots, logs, or any other relevant proof that illustrates the concept.
function sendPrice(
CCIPDestinationParam[] calldata _destinationParam,
ConnextDestinationParam[] calldata _connextDestinationParam
) external payable onlyPriceFeedSender nonReentrant {
// call getRate() to get the current price of ezETH
uint256 exchangeRate = rateProvider.getRate();
bytes memory _callData = abi.encode(exchangeRate, block.timestamp);
// send price feed to renzo CCIP receivers
for (uint256 i = 0; i < _destinationParam.length; ) {
Client.EVM2AnyMessage memory evm2AnyMessage = Client.EVM2AnyMessage({
receiver: abi.encode(_destinationParam[i]._renzoReceiver), // ABI-encoded xRenzoDepsot contract address
data: _callData, // ABI-encoded ezETH exchange rate with Timestamp
tokenAmounts: new Client.EVMTokenAmount, // Empty array indicating no tokens are being sent
extraArgs: Client._argsToBytes(
// Additional arguments, setting gas limit
Client.EVMExtraArgsV1({ gasLimit: 200_000 })
),
// Set the feeToken address, indicating LINK will be used for fees
feeToken: address(linkToken)
});
// Get the fee required to send the message
uint256 fees = linkRouterClient.getFee(
_destinationParam[i].destinationChainSelector,
evm2AnyMessage
);
if (fees > linkToken.balanceOf(address(this)))
revert NotEnoughBalance(linkToken.balanceOf(address(this)), fees);
// approve the Router to transfer LINK tokens on contract's behalf. It will spend the fees in LINK
linkToken.approve(address(linkRouterClient), fees);
// Send the message through the router and store the returned message ID
bytes32 messageId = linkRouterClient.ccipSend(
_destinationParam[i].destinationChainSelector,
evm2AnyMessage
);
// Emit an event with message details
emit MessageSent(
messageId,
_destinationParam[i].destinationChainSelector,
_destinationParam[i]._renzoReceiver,
exchangeRate,
address(linkToken),
fees
);
unchecked {
++i;
}
}
// send price feed to renzo connext receiver
for (uint256 i = 0; i < _connextDestinationParam.length; ) {
connext.xcall{ value: _connextDestinationParam[i].relayerFee }(
_connextDestinationParam[i].destinationDomainId,
_connextDestinationParam[i]._renzoReceiver,
address(0),
msg.sender,
0,
@>> 0,
_callData
);
Lines of code
https://github.com/code-423n4/2024-04-renzo/blob/main/contracts/Bridge/L1/xRenzoBridge.sol#L271
Vulnerability details
Impact
Detailed description of the impact of this finding. we are not checking any min amount in sendprice function. when we are sending price feed to renzo connext receiver we are keeping the minamount to 0.
Proof of Concept
Provide direct links to all referenced code in GitHub. Add screenshots, logs, or any other relevant proof that illustrates the concept.
function sendPrice( CCIPDestinationParam[] calldata _destinationParam, ConnextDestinationParam[] calldata _connextDestinationParam ) external payable onlyPriceFeedSender nonReentrant { // call getRate() to get the current price of ezETH uint256 exchangeRate = rateProvider.getRate(); bytes memory _callData = abi.encode(exchangeRate, block.timestamp); // send price feed to renzo CCIP receivers for (uint256 i = 0; i < _destinationParam.length; ) { Client.EVM2AnyMessage memory evm2AnyMessage = Client.EVM2AnyMessage({ receiver: abi.encode(_destinationParam[i]._renzoReceiver), // ABI-encoded xRenzoDepsot contract address data: _callData, // ABI-encoded ezETH exchange rate with Timestamp tokenAmounts: new Client.EVMTokenAmount, // Empty array indicating no tokens are being sent extraArgs: Client._argsToBytes( // Additional arguments, setting gas limit Client.EVMExtraArgsV1({ gasLimit: 200_000 }) ), // Set the feeToken address, indicating LINK will be used for fees feeToken: address(linkToken) });
Tools Used
Recommended Mitigation Steps
keep a minamount for slippage
Assessed type
Context