Skip to content

Commit

Permalink
MezoAllocator Withdrawals Improvements (#717)
Browse files Browse the repository at this point in the history
Depends on: #716

In this PR we introduce a couple of improvements to the MezoAllocator
contract related to withdrawals from the Mezo Portal.

### Check if the withdrawal amount exceeds the deposit balance
(1b95419)

Here we improve the withdrawal function to check if the withdrawal
amount exceeds the deposit balance.
If the withdrawal amount exceeds the deposit balance, the function will
revert with a custom error message.
Before these changes, since the Portal contract changed the handling of
partial and full withdrawals the withdrawal function reverted on
`depositBalance -= uint96(amount);` with:
```
panic code 0x11 (Arithmetic operation overflowed outside of an unchecked block)
```

### Include unallocated MezoAllocator balance in `withdraw` and
`releaseDeposit` (1b9ba17,
0440580)

In bb42bce we included the current
balance of the MezoAllocator contract in the `totalAssets` function
result. The balance can come from a rewards transfer or any donation.

We haven't considered this balance in the `withdraw` function, which
could lead to blocking the last user withdrawing the funds, as the
balance of assets owned by them calculated based on `totalAssets`
function, couldn't be fully withdraw due to unallocated balance being
stuck in the `MezoAllocator` contract. In
1b9ba17 we introduce possibility to
withdraw funds from the unallocated contract balance.

For the `releaseDeposit` function we could face a problem when the Mezo
Portal deposit is already released but some tokens were donated to the
MezoAllocator contract, since the `Porta.withdraw` function would be
reverting as there is no deposit, we won't be able to transfer the
unallocated funds in the same call. We fixed it in
0440580.

> [!IMPORTANT]  
> Please ignore failing integration tests, as these will be fixed in
#718
  • Loading branch information
r-czajkowski authored Sep 3, 2024
2 parents c3790ef + 6151a38 commit db074d5
Show file tree
Hide file tree
Showing 2 changed files with 486 additions and 111 deletions.
60 changes: 46 additions & 14 deletions solidity/contracts/MezoAllocator.sol
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,15 @@ contract MezoAllocator is IDispatcher, Ownable2StepUpgradeable {
uint256 newDepositAmount
);
/// @notice Emitted when tBTC is withdrawn from MezoPortal.
event DepositWithdrawn(uint256 indexed depositId, uint256 amount);
/// If MezoAllocator has a positive balance part of the requested amount
/// is withdrawn from MezoAllocator and the rest from MezoPortal.
event WithdrawFromMezoPortal(
uint256 indexed depositId,
uint256 requestedAmount,
uint256 amountWithdrawnFromPortal
);
/// @notice Emitted when tBTC is withdrawn from MezoAllocator.
event WithdrawFromMezoAllocator(uint256 amount);
/// @notice Emitted when the maintainer address is updated.
event MaintainerAdded(address indexed maintainer);
/// @notice Emitted when the maintainer address is updated.
Expand All @@ -142,6 +150,12 @@ contract MezoAllocator is IDispatcher, Ownable2StepUpgradeable {
error MaintainerNotRegistered();
/// @notice Reverts if the maintainer has been already registered.
error MaintainerAlreadyRegistered();
/// @notice Reverts if the requested amount to withdraw exceeds the amount
/// deposited in the Mezo Portal.
error WithdrawalAmountExceedsDepositBalance(
uint256 requestedAmount,
uint256 depositAmount
);

modifier onlyMaintainer() {
if (!isMaintainer[msg.sender]) {
Expand Down Expand Up @@ -225,20 +239,35 @@ contract MezoAllocator is IDispatcher, Ownable2StepUpgradeable {
function withdraw(uint256 amount) external {
if (msg.sender != address(stbtc)) revert CallerNotStbtc();

emit DepositWithdrawn(depositId, amount);
uint256 unallocatedBalance = tbtc.balanceOf(address(this));

if (amount > unallocatedBalance) {
uint256 amountToWithdraw = amount - unallocatedBalance;

emit WithdrawFromMezoPortal(depositId, amount, amountToWithdraw);

if (amountToWithdraw < depositBalance) {
mezoPortal.withdrawPartially(
address(tbtc),
depositId,
uint96(amountToWithdraw)
);
// slither-disable-next-line incorrect-equality
} else if (amountToWithdraw == depositBalance) {
mezoPortal.withdraw(address(tbtc), depositId);
} else {
revert WithdrawalAmountExceedsDepositBalance(
amountToWithdraw,
depositBalance
);
}

if (amount < depositBalance) {
mezoPortal.withdrawPartially(
address(tbtc),
depositId,
uint96(amount)
);
// slither-disable-next-line reentrancy-no-eth
depositBalance -= uint96(amountToWithdraw);
} else {
mezoPortal.withdraw(address(tbtc), depositId);
emit WithdrawFromMezoAllocator(amount);
}

// slither-disable-next-line reentrancy-no-eth
depositBalance -= uint96(amount);
tbtc.safeTransfer(address(stbtc), amount);
}

Expand All @@ -250,9 +279,12 @@ contract MezoAllocator is IDispatcher, Ownable2StepUpgradeable {
.getDeposit(address(this), address(tbtc), depositId)
.balance;

emit DepositReleased(depositId, amount);
depositBalance = 0;
mezoPortal.withdraw(address(tbtc), depositId);
if (amount > 0) {
emit DepositReleased(depositId, amount);
depositBalance = 0;
mezoPortal.withdraw(address(tbtc), depositId);
}

tbtc.safeTransfer(address(stbtc), tbtc.balanceOf(address(this)));
}

Expand Down
Loading

0 comments on commit db074d5

Please sign in to comment.