Open howlbot-integration[bot] opened 6 months ago
alcueca marked the issue as satisfactory
alcueca marked the issue as selected for report
Mitigation of #372 is good as well.
Hey @alcueca,
I think this issue should be of low severity because we can see that xRenzoBridge has functions to retrieve the funds that are "stuck", which is exactly what the first paragraph of the provided Connext documentation advises - https://docs.connext.network/developers/guides/handling-failures#reverts-on-receiver-contract. In all matters, manually distributing failed transactions funds is not an optimal solution, but in the end, funds are not really stuck, since the admin can still process them from the Connext directly:
Thanks!
Hey @alcueca
https://github.com/code-423n4/2024-04-renzo-findings/issues/287 should be marked as a duplicate of this as well.
@blckhv I'm afraid this is factually incorrect. Connext allows you to re-submit / retry a failed TX only if it failed due to insufficient relayer fee (which is what the sponsor said in the screenshot).
In the case it failed due to the xReceive()
on the destination chain reverting, then the funds will be stuck. Not to mention that this failure is silent. Meaning that admins may be notified that this call failed on the destination chain very late.
That's why the Connext docs says that the IXReceiver contract should be implemented defensively.
If the call on the receiver contract (also referred to as "target" contract) reverts, funds sent in with the call will end up on the receiver contract. To avoid situations where user funds get stuck on the receivers, developers should build any contract implementing IXReceive defensively.
Ultimately, the goal should be to handle any revert-susceptible code and ensure that the logical owner of funds always maintains agency over them.
Bridging silently failing + admins having to manually recover funds and manually redistribute to other parts of the system is surely Medium severity worthy.
Hey @alcueca
287 should be marked as a duplicate of this as well.
@blckhv I'm afraid this is factually incorrect. Connext allows you to re-submit / retry a failed TX only if it failed due to insufficient relayer fee (which is what the sponsor said in the screenshot).
In the case it failed due to the
xReceive()
on the destination chain reverting, then the funds will be stuck. Not to mention that this failure is silent. Meaning that admins may be notified that this call failed on the destination chain very late.That's why the Connext docs says that the IXReceiver contract should be implemented defensively.
If the call on the receiver contract (also referred to as "target" contract) reverts, funds sent in with the call will end up on the receiver contract. To avoid situations where user funds get stuck on the receivers, developers should build any contract implementing IXReceive defensively.
Ultimately, the goal should be to handle any revert-susceptible code and ensure that the logical owner of funds always maintains agency over them.
Bridging silently failing + admins having to manually recover funds and manually redistribute to other parts of the system is surely Medium severity worthy.
Agree with this comments
my submission explains that there are several revert conditions
https://github.com/code-423n4/2024-04-renzo-findings/issues/374
Lines of code
https://github.com/code-423n4/2024-04-renzo/blob/main/contracts/Bridge/L1/xRenzoBridge.sol#L175
Vulnerability details
Impact
If the
xReceive
function fails to handle reverts properly, it could result in funds getting stuck. This can happen for example when:ezETH
rate on L1 and L2 could be different.Proof of Concept
Failure to handle errors in the
xReceive
function as outlined by Connext can lead to funds becoming inaccessible. https://docs.connext.network/developers/guides/handling-failures#reverts-on-receiver-contractThis can happen in several scenarios within the
xRenzoBridge
contract:If the deposited amount on L2 exceeds the
maxDepositTVL
limit set on L1, the deposit will fail when bridged to L1. This could occur if an attacker uses a large flash loan ofWETH
to deposit on L2 and then swaps the mintedxezETH
to repay the flash loan.https://github.com/code-423n4/2024-04-renzo/blob/main/contracts/Bridge/L1/xRenzoBridge.sol#L175
https://github.com/code-423n4/2024-04-renzo/blob/main/contracts/RestakeManager.sol#L510
If the protocol on L1 is paused, the deposit made on L2 will be successful and equivalent
xezETH
will be minted, but when it is bridged to L1, it will fail. This is because no pausing mechanism is defined on L2 to be aligned with L1.https://github.com/code-423n4/2024-04-renzo/blob/main/contracts/Bridge/L2/xRenzoDeposit.sol#L168
https://github.com/code-423n4/2024-04-renzo/blob/main/contracts/Bridge/L2/xRenzoDeposit.sol#L204
If the deposited amount on L2 is too low so that when it is bridged to L1, minted amount of
ezETH
becomes zero, it will fail. This can happen if between the deposit on L2 and bridging to L1, the TVL increases while total supply ofezETH
does not change. By doing so, eachezETH
is worth more than before. So, when that small amount ofWETH
is going to be deposited into the protocol on L1, it mints lessezETH
than the amount ofxezETH
minted on L2. If it is zero, it will revert.https://github.com/code-423n4/2024-04-renzo/blob/main/contracts/Bridge/L1/xRenzoBridge.sol#L175
https://github.com/code-423n4/2024-04-renzo/blob/main/contracts/RestakeManager.sol#L565
https://github.com/code-423n4/2024-04-renzo/blob/main/contracts/Oracle/RenzoOracle.sol#L146
Tools Used
Recommended Mitigation Steps
To address these potential failures, it is suggested to:
implement error handling in the
xReceive
function. Specifically, placing thedepositETH
function call within a try/catch block could help manage these failures. Additionally, only authenticated addresses should be allowed to handle these errors.enforce the deposited amount on L2 to be less than
maxDepositTVL
.define the pausing mechanism on L2.
allow the
BrdigeSweepr
to define the amount of token to be bridged to L1. By doing so, it can handle the situations where a large amount is deposited on L2.https://github.com/code-423n4/2024-04-renzo/blob/main/contracts/Bridge/L2/xRenzoDeposit.sol#L414
Assessed type
Context