Skip to content

Commit

Permalink
Merge pull request #5 from Renzo-Protocol/ez-withdraw
Browse files Browse the repository at this point in the history
Ez withdraw
  • Loading branch information
pooleja authored Jun 12, 2024
2 parents 639db77 + 3e54a3e commit 36777a1
Show file tree
Hide file tree
Showing 47 changed files with 4,468 additions and 258 deletions.
Binary file not shown.
Binary file not shown.
1 change: 1 addition & 0 deletions Audit/code4rena_Audit.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Code4Rena Audit Link - https://code4rena.com/reports/2024-04-renzo
4 changes: 2 additions & 2 deletions contracts/Bridge/Connext/integration/LockboxAdapterBlast.sol
Original file line number Diff line number Diff line change
Expand Up @@ -81,9 +81,9 @@ contract LockboxAdapterBlast {
}

SafeERC20.safeTransferFrom(IERC20(_erc20), msg.sender, address(this), _amount);
SafeERC20.safeApprove(IERC20(_erc20), lockbox, _amount);
SafeERC20.safeIncreaseAllowance(IERC20(_erc20), lockbox, _amount);
IXERC20Lockbox(lockbox).deposit(_amount);
SafeERC20.safeApprove(IERC20(xerc20), blastStandardBridge, _amount);
SafeERC20.safeIncreaseAllowance(IERC20(xerc20), blastStandardBridge, _amount);
L1StandardBridge(blastStandardBridge).bridgeERC20To(
xerc20,
_remoteToken,
Expand Down
13 changes: 9 additions & 4 deletions contracts/Bridge/L1/xRenzoBridge.sol
Original file line number Diff line number Diff line change
Expand Up @@ -144,8 +144,8 @@ contract xRenzoBridge is
uint32 _origin,
bytes memory
) external nonReentrant returns (bytes memory) {
// Only allow incoming messages from the Connext contract
if (msg.sender != address(connext)) {
// Only allow incoming messages from the Connext contract or bridge admin role
if (msg.sender != address(connext) && !roleManager.isBridgeAdmin(msg.sender)) {
revert InvalidSender(address(connext), msg.sender);
}

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

// Approve the lockbox to spend the ezETH
ezETH.safeApprove(address(xezETHLockbox), ezETHAmount);
ezETH.safeIncreaseAllowance(address(xezETHLockbox), ezETHAmount);

// Get the xezETH balance before the deposit
uint256 xezETHBalanceBeforeDeposit = xezETH.balanceOf(address(this));
Expand Down Expand Up @@ -213,6 +213,10 @@ contract xRenzoBridge is
) external payable onlyPriceFeedSender nonReentrant {
// call getRate() to get the current price of ezETH
uint256 exchangeRate = rateProvider.getRate();

// check revert if price fetched by rate provider is undercollateralized
if (exchangeRate < 1 ether) revert InvalidOraclePrice();

bytes memory _callData = abi.encode(exchangeRate, block.timestamp);
// send price feed to renzo CCIP receivers
for (uint256 i = 0; i < _destinationParam.length; ) {
Expand Down Expand Up @@ -292,7 +296,8 @@ contract xRenzoBridge is
* @param _to destination address
*/
function recoverNative(uint256 _amount, address _to) external onlyBridgeAdmin {
payable(_to).transfer(_amount);
(bool success, ) = payable(_to).call{ value: _amount }("");
if (!success) revert TransferFailed();
}

/**
Expand Down
57 changes: 40 additions & 17 deletions contracts/Bridge/L2/xRenzoDeposit.sol
Original file line number Diff line number Diff line change
Expand Up @@ -328,15 +328,30 @@ contract xRenzoDeposit is
* @param _timestamp The timestamp of the price update
*/
function _updatePrice(uint256 _price, uint256 _timestamp) internal {
_beforeUpdatePrice(_price, _timestamp);

// Update values and emit event
lastPrice = _price;
lastPriceTimestamp = _timestamp;

emit PriceUpdated(_price, _timestamp);
}

function _beforeUpdatePrice(uint256 _price, uint256 _timestamp) internal view {
// Check for 0
if (_price == 0) {
revert InvalidZeroInput();
}

// Check for price divergence - more than 10%
// check for undercollateralized price - < 1
if (_price < 1 ether) {
revert InvalidOraclePrice();
}

// Check for price divergence - more than 1%
if (
(_price > lastPrice && (_price - lastPrice) > (lastPrice / 10)) ||
(_price < lastPrice && (lastPrice - _price) > (lastPrice / 10))
(_price > lastPrice && (_price - lastPrice) > (lastPrice / 100)) ||
(_price < lastPrice && (lastPrice - _price) > (lastPrice / 100))
) {
revert InvalidOraclePrice();
}
Expand All @@ -350,12 +365,6 @@ contract xRenzoDeposit is
if (_timestamp > block.timestamp) {
revert InvalidTimestamp(_timestamp);
}

// Update values and emit event
lastPrice = _price;
lastPriceTimestamp = _timestamp;

emit PriceUpdated(_price, _timestamp);
}

/**
Expand All @@ -366,7 +375,7 @@ contract xRenzoDeposit is
*/
function _trade(uint256 _amountIn, uint256 _deadline) internal returns (uint256) {
// Approve the deposit asset to the connext contract
depositToken.safeApprove(address(connext), _amountIn);
depositToken.safeIncreaseAllowance(address(connext), _amountIn);

// We will accept any amount of tokens out here... The caller of this function should verify the amount meets minimums
uint256 minOut = 0;
Expand Down Expand Up @@ -397,11 +406,21 @@ contract xRenzoDeposit is
uint256 feeCollected = bridgeFeeCollected;
bridgeFeeCollected = 0;
// transfer collected fee to bridgeSweeper
uint256 balanceBefore = address(this).balance;
IWeth(address(depositToken)).withdraw(feeCollected);
feeCollected = address(this).balance - balanceBefore;
(bool success, ) = payable(msg.sender).call{ value: feeCollected }("");
if (!success) revert TransferFailed();
uint256 chainId;
assembly {
chainId := chainid()
}
// If executing chain is BSC or XLayer then transfer WETH to bridgeSweeper
if (chainId == 56 || chainId == 196) {
IERC20(address(depositToken)).safeTransfer(msg.sender, feeCollected);
} else {
// transfer collected fee in ETH to bridgeSweeper
uint256 balanceBefore = address(this).balance;
IWeth(address(depositToken)).withdraw(feeCollected);
feeCollected = address(this).balance - balanceBefore;
bool success = payable(msg.sender).send(feeCollected);
if (!success) revert TransferFailed();
}
emit SweeperBridgeFeeCollected(msg.sender, feeCollected);
}

Expand All @@ -426,7 +445,7 @@ contract xRenzoDeposit is
}

// Approve it to the connext contract
collateralToken.safeApprove(address(connext), balance);
collateralToken.safeIncreaseAllowance(address(connext), balance);

// Need to send some calldata so it triggers xReceive on the target
bytes memory bridgeCallData = abi.encode(balance);
Expand Down Expand Up @@ -454,7 +473,11 @@ contract xRenzoDeposit is
* @return uint256 .
*/
function getRate() external view override returns (uint256) {
return lastPrice;
(uint256 _lastPrice, uint256 _lastPriceTimestamp) = getMintRate();
if (block.timestamp > _lastPriceTimestamp + 1 days) {
revert OraclePriceExpired();
}
return _lastPrice;
}

/**
Expand Down
17 changes: 10 additions & 7 deletions contracts/Delegation/IOperatorDelegator.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,15 @@ interface IOperatorDelegator {

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

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

function completeWithdrawal(
IStrategyManager.QueuedWithdrawal calldata _withdrawal,
IERC20 _token,
uint256 _middlewareTimesIndex,
address _sendToAddress
) external;
// function completeWithdrawal(
// IStrategyManager.DeprecatedStruct_QueuedWithdrawal calldata _withdrawal,
// IERC20 _token,
// uint256 _middlewareTimesIndex,
// address _sendToAddress
// ) external;

function getStakedETHBalance() external view returns (uint256);

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

function pendingUnstakedDelayedWithdrawalAmount() external view returns (uint256);

function delegateAddress() external view returns (address);
}
Loading

0 comments on commit 36777a1

Please sign in to comment.