Summary
Wrong parameter is emitted in StakingRewardsPool::_transferShares()'s Transfer event, which will give provide false information to protocol owners.
Vulnerability Details
Here is the internal _transferShares():
function _transferShares(address _sender, address _recipient, uint256 _sharesAmount) internal {
require(_sender != address(0), "Transfer from the zero address");
require(_recipient != address(0), "Transfer to the zero address");
require(shares[_sender] >= _sharesAmount, "Transfer amount exceeds balance");
shares[_sender] -= _sharesAmount;
shares[_recipient] += _sharesAmount;
@> emit Transfer(_sender, _recipient, getStakeByShares(_sharesAmount));
}
if we look at the IERC20Upgradeable::Transfer() event:
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
It states that the value amount should be the transfered tokens. Notice that the in _transferShares() the shares amount is deducted from sender and added to recipient's account, so the moved amount is _sharesAmount. For example StakingRewardsPool::_transfer(), _mint(), _burn() are using this pattern:
function _transfer(address _sender, address _recipient, uint256 _amount) internal override {
uint256 sharesToTransfer = getSharesByStake(_amount);
...
shares[_sender] -= sharesToTransfer;
shares[_recipient] += sharesToTransfer;
!!!!!!!!
emit Transfer(_sender, _recipient, _amount);
}
function _mint(address _recipient, uint256 _amount) internal override {
uint256 sharesToMint = getSharesByStake(_amount);
_mintShares(_recipient, sharesToMint);
!!!!!!!!
emit Transfer(address(0), _recipient, _amount);
}
function _burn(address _account, uint256 _amount) internal override {
uint256 sharesToBurn = getSharesByStake(_amount);
...
totalShares -= sharesToBurn;
shares[_account] -= sharesToBurn;
!!!!!!!
emit Transfer(_account, address(0), _amount);
}
Tools Used
Manual Review
Recommendations
function _transferShares(address _sender, address _recipient, uint256 _sharesAmount) internal {
require(_sender != address(0), "Transfer from the zero address");
require(_recipient != address(0), "Transfer to the zero address");
require(shares[_sender] >= _sharesAmount, "Transfer amount exceeds balance");
shares[_sender] -= _sharesAmount;
shares[_recipient] += _sharesAmount;
- emit Transfer(_sender, _recipient, getStakeByShares(_sharesAmount));
+ emit Transfer(_sender, _recipient, _sharesAmount);
}