Skip to content

Commit 36777a1

Browse files
authored
Merge pull request #5 from Renzo-Protocol/ez-withdraw
Ez withdraw
2 parents 639db77 + 3e54a3e commit 36777a1

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+4468
-258
lines changed
Binary file not shown.
Binary file not shown.

Audit/code4rena_Audit.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Code4Rena Audit Link - https://code4rena.com/reports/2024-04-renzo

contracts/Bridge/Connext/integration/LockboxAdapterBlast.sol

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,9 +81,9 @@ contract LockboxAdapterBlast {
8181
}
8282

8383
SafeERC20.safeTransferFrom(IERC20(_erc20), msg.sender, address(this), _amount);
84-
SafeERC20.safeApprove(IERC20(_erc20), lockbox, _amount);
84+
SafeERC20.safeIncreaseAllowance(IERC20(_erc20), lockbox, _amount);
8585
IXERC20Lockbox(lockbox).deposit(_amount);
86-
SafeERC20.safeApprove(IERC20(xerc20), blastStandardBridge, _amount);
86+
SafeERC20.safeIncreaseAllowance(IERC20(xerc20), blastStandardBridge, _amount);
8787
L1StandardBridge(blastStandardBridge).bridgeERC20To(
8888
xerc20,
8989
_remoteToken,

contracts/Bridge/L1/xRenzoBridge.sol

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -144,8 +144,8 @@ contract xRenzoBridge is
144144
uint32 _origin,
145145
bytes memory
146146
) external nonReentrant returns (bytes memory) {
147-
// Only allow incoming messages from the Connext contract
148-
if (msg.sender != address(connext)) {
147+
// Only allow incoming messages from the Connext contract or bridge admin role
148+
if (msg.sender != address(connext) && !roleManager.isBridgeAdmin(msg.sender)) {
149149
revert InvalidSender(address(connext), msg.sender);
150150
}
151151

@@ -178,7 +178,7 @@ contract xRenzoBridge is
178178
uint256 ezETHAmount = ezETH.balanceOf(address(this)) - ezETHBalanceBeforeDeposit;
179179

180180
// Approve the lockbox to spend the ezETH
181-
ezETH.safeApprove(address(xezETHLockbox), ezETHAmount);
181+
ezETH.safeIncreaseAllowance(address(xezETHLockbox), ezETHAmount);
182182

183183
// Get the xezETH balance before the deposit
184184
uint256 xezETHBalanceBeforeDeposit = xezETH.balanceOf(address(this));
@@ -213,6 +213,10 @@ contract xRenzoBridge is
213213
) external payable onlyPriceFeedSender nonReentrant {
214214
// call getRate() to get the current price of ezETH
215215
uint256 exchangeRate = rateProvider.getRate();
216+
217+
// check revert if price fetched by rate provider is undercollateralized
218+
if (exchangeRate < 1 ether) revert InvalidOraclePrice();
219+
216220
bytes memory _callData = abi.encode(exchangeRate, block.timestamp);
217221
// send price feed to renzo CCIP receivers
218222
for (uint256 i = 0; i < _destinationParam.length; ) {
@@ -292,7 +296,8 @@ contract xRenzoBridge is
292296
* @param _to destination address
293297
*/
294298
function recoverNative(uint256 _amount, address _to) external onlyBridgeAdmin {
295-
payable(_to).transfer(_amount);
299+
(bool success, ) = payable(_to).call{ value: _amount }("");
300+
if (!success) revert TransferFailed();
296301
}
297302

298303
/**

contracts/Bridge/L2/xRenzoDeposit.sol

Lines changed: 40 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -328,15 +328,30 @@ contract xRenzoDeposit is
328328
* @param _timestamp The timestamp of the price update
329329
*/
330330
function _updatePrice(uint256 _price, uint256 _timestamp) internal {
331+
_beforeUpdatePrice(_price, _timestamp);
332+
333+
// Update values and emit event
334+
lastPrice = _price;
335+
lastPriceTimestamp = _timestamp;
336+
337+
emit PriceUpdated(_price, _timestamp);
338+
}
339+
340+
function _beforeUpdatePrice(uint256 _price, uint256 _timestamp) internal view {
331341
// Check for 0
332342
if (_price == 0) {
333343
revert InvalidZeroInput();
334344
}
335345

336-
// Check for price divergence - more than 10%
346+
// check for undercollateralized price - < 1
347+
if (_price < 1 ether) {
348+
revert InvalidOraclePrice();
349+
}
350+
351+
// Check for price divergence - more than 1%
337352
if (
338-
(_price > lastPrice && (_price - lastPrice) > (lastPrice / 10)) ||
339-
(_price < lastPrice && (lastPrice - _price) > (lastPrice / 10))
353+
(_price > lastPrice && (_price - lastPrice) > (lastPrice / 100)) ||
354+
(_price < lastPrice && (lastPrice - _price) > (lastPrice / 100))
340355
) {
341356
revert InvalidOraclePrice();
342357
}
@@ -350,12 +365,6 @@ contract xRenzoDeposit is
350365
if (_timestamp > block.timestamp) {
351366
revert InvalidTimestamp(_timestamp);
352367
}
353-
354-
// Update values and emit event
355-
lastPrice = _price;
356-
lastPriceTimestamp = _timestamp;
357-
358-
emit PriceUpdated(_price, _timestamp);
359368
}
360369

361370
/**
@@ -366,7 +375,7 @@ contract xRenzoDeposit is
366375
*/
367376
function _trade(uint256 _amountIn, uint256 _deadline) internal returns (uint256) {
368377
// Approve the deposit asset to the connext contract
369-
depositToken.safeApprove(address(connext), _amountIn);
378+
depositToken.safeIncreaseAllowance(address(connext), _amountIn);
370379

371380
// We will accept any amount of tokens out here... The caller of this function should verify the amount meets minimums
372381
uint256 minOut = 0;
@@ -397,11 +406,21 @@ contract xRenzoDeposit is
397406
uint256 feeCollected = bridgeFeeCollected;
398407
bridgeFeeCollected = 0;
399408
// transfer collected fee to bridgeSweeper
400-
uint256 balanceBefore = address(this).balance;
401-
IWeth(address(depositToken)).withdraw(feeCollected);
402-
feeCollected = address(this).balance - balanceBefore;
403-
(bool success, ) = payable(msg.sender).call{ value: feeCollected }("");
404-
if (!success) revert TransferFailed();
409+
uint256 chainId;
410+
assembly {
411+
chainId := chainid()
412+
}
413+
// If executing chain is BSC or XLayer then transfer WETH to bridgeSweeper
414+
if (chainId == 56 || chainId == 196) {
415+
IERC20(address(depositToken)).safeTransfer(msg.sender, feeCollected);
416+
} else {
417+
// transfer collected fee in ETH to bridgeSweeper
418+
uint256 balanceBefore = address(this).balance;
419+
IWeth(address(depositToken)).withdraw(feeCollected);
420+
feeCollected = address(this).balance - balanceBefore;
421+
bool success = payable(msg.sender).send(feeCollected);
422+
if (!success) revert TransferFailed();
423+
}
405424
emit SweeperBridgeFeeCollected(msg.sender, feeCollected);
406425
}
407426

@@ -426,7 +445,7 @@ contract xRenzoDeposit is
426445
}
427446

428447
// Approve it to the connext contract
429-
collateralToken.safeApprove(address(connext), balance);
448+
collateralToken.safeIncreaseAllowance(address(connext), balance);
430449

431450
// Need to send some calldata so it triggers xReceive on the target
432451
bytes memory bridgeCallData = abi.encode(balance);
@@ -454,7 +473,11 @@ contract xRenzoDeposit is
454473
* @return uint256 .
455474
*/
456475
function getRate() external view override returns (uint256) {
457-
return lastPrice;
476+
(uint256 _lastPrice, uint256 _lastPriceTimestamp) = getMintRate();
477+
if (block.timestamp > _lastPriceTimestamp + 1 days) {
478+
revert OraclePriceExpired();
479+
}
480+
return _lastPrice;
458481
}
459482

460483
/**

contracts/Delegation/IOperatorDelegator.sol

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,15 @@ interface IOperatorDelegator {
1010

1111
function deposit(IERC20 _token, uint256 _tokenAmount) external returns (uint256 shares);
1212

13-
function startWithdrawal(IERC20 _token, uint256 _tokenAmount) external returns (bytes32);
13+
// Note: Withdraws disabled for this release
14+
// function startWithdrawal(IERC20 _token, uint256 _tokenAmount) external returns (bytes32);
1415

15-
function completeWithdrawal(
16-
IStrategyManager.QueuedWithdrawal calldata _withdrawal,
17-
IERC20 _token,
18-
uint256 _middlewareTimesIndex,
19-
address _sendToAddress
20-
) external;
16+
// function completeWithdrawal(
17+
// IStrategyManager.DeprecatedStruct_QueuedWithdrawal calldata _withdrawal,
18+
// IERC20 _token,
19+
// uint256 _middlewareTimesIndex,
20+
// address _sendToAddress
21+
// ) external;
2122

2223
function getStakedETHBalance() external view returns (uint256);
2324

@@ -30,4 +31,6 @@ interface IOperatorDelegator {
3031
function eigenPod() external view returns (IEigenPod);
3132

3233
function pendingUnstakedDelayedWithdrawalAmount() external view returns (uint256);
34+
35+
function delegateAddress() external view returns (address);
3336
}

0 commit comments

Comments
 (0)