Skip to content

Conversation

hanzel98
Copy link
Contributor

What?

  • Adds integration tests for the liquid staking feature of MetaMask using delegations.
  • Adds a new adapter that can be used to save the approval step as a separate action.

Why?

  • Shows the ability to use the delegation with the MetaMask liquid staking feature.

@hanzel98 hanzel98 requested a review from a team as a code owner June 27, 2025 21:16
@hanzel98 hanzel98 marked this pull request as draft June 27, 2025 21:16
@hanzel98 hanzel98 self-assigned this Jul 2, 2025
@hanzel98 hanzel98 requested review from McOso and MoMannn July 2, 2025 20:56
@hanzel98 hanzel98 marked this pull request as ready for review July 2, 2025 20:56
Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: Infinite Allowance Overflow Bug

The _ensureAllowance function attempts to set an infinite allowance for the withdrawalQueue using stETH.safeIncreaseAllowance(address(withdrawalQueue), type(uint256).max). However, safeIncreaseAllowance adds the specified amount to the existing allowance. If the current allowance is already greater than zero, this operation will cause an arithmetic overflow and revert, as currentAllowance + type(uint256).max exceeds type(uint256).max. The intended behavior was likely to set the allowance to type(uint256).max, which should be achieved using safeApprove.

src/helpers/LiquidStakingAdapter.sol#L175-L181

/// @param _amount Amount needed for the operation
function _ensureAllowance(uint256 _amount) private {
uint256 allowance_ = stETH.allowance(address(this), address(withdrawalQueue));
if (allowance_ < _amount) {
stETH.safeIncreaseAllowance(address(withdrawalQueue), type(uint256).max);
}
}

Fix in Cursor


Bug: Permit Value Mismatch Causes Transfer Failures

In the requestWithdrawalsWithPermit function, the permit call uses _permit.value while the subsequent safeTransferFrom uses totalAmount_ (calculated as the sum of _amounts). If _permit.value does not exactly match totalAmount_, the transfer will either fail due to insufficient allowance or grant excessive allowance.

src/helpers/LiquidStakingAdapter.sol#L115-L135

/// @return requestIds_ Array of withdrawal request IDs
function requestWithdrawalsWithPermit(
uint256[] memory _amounts,
IWithdrawalQueue.PermitInput memory _permit
)
external
returns (uint256[] memory requestIds_)
{
uint256 totalAmount_ = _calculateTotalAmount(_amounts);
// Use permit to approve stETH transfer
IERC20Permit(address(stETH)).permit(
msg.sender, address(this), _permit.value, _permit.deadline, _permit.v, _permit.r, _permit.s
);
// Transfer stETH from sender to this contract
stETH.safeTransferFrom(msg.sender, address(this), totalAmount_);
// Execute common withdrawal logic
requestIds_ = _requestWithdrawals(_amounts, totalAmount_, msg.sender);
}

Fix in Cursor


BugBot free trial expires on July 22, 2025
You have used $0.00 of your $50.00 spend limit so far. Manage your spend limit in the Cursor dashboard.

Was this report helpful? Give feedback by reacting with 👍 or 👎

@hanzel98 hanzel98 added the new release This PR goes to the next release label Jul 22, 2025
@hanzel98
Copy link
Contributor Author

hanzel98 commented Sep 3, 2025

This PR needs an RPC URL secret on github to work

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

new release This PR goes to the next release

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant