Fierce Coral Turkey
High
withdraw
function is invoked whenever a user wants to withdraw his staking, this function will invoke _msgRemoveStakers
.
Inside _msgRemoveStakers
sendMessage
is called, note that there is no option to specify the refundAddress
.
function _msgRemoveStakers(address[] memory remove) internal {
=> MESSENGER.sendMessage(
address(OTHER_STAKING),
0,
abi.encodeCall(IL2Staking.removeStakers, (remove)),
gasLimitRemoveStakers
);
}
This triggers the sendMessage
function in the L1CrossDomainMessenger
contract:
function sendMessage(
address _to,
uint256 _value,
bytes memory _message,
uint256 _gasLimit
) external payable override whenNotPaused {
_sendMessage(_to, _value, _message, _gasLimit, _msgSender());
}
The sendMessage
function invokes _sendMessage
, assigning the refundAddress
as the msg.sender
. The msg.sender
will always be the L1CrossDomainMessenger
contract itself.
function _sendMessage(
address _to,
uint256 _value,
bytes memory _message,
uint256 _gasLimit,
address _refundAddress
) internal nonReentrant {
//...Omitted code
// Refund any remaining fee to the `_refundAddress`
unchecked {
uint256 _refund = msg.value - _fee - _value;
if (_refund > 0) {
(bool _success, ) = _refundAddress.call{value: _refund}("");
require(_success, "Failed to refund the fee");
}
}
}
If a refund is required, any leftover fee is returned to the _refundAddress
, which will always be the L1CrossDomainMessenger
contract itself.
This means that users that might have any remaining fee will not get it back. Instead, the contract will receive it.
Ultimately users lose a part of their funds.
Use the other sendMessage
function which allows to specify your own _refundAddress