Summary
MarketMakingEngineConfigurationBranch.sol#configureFeeRecipient()
checks if result total share will not exceed maximum shares as wrong way.
Vulnerability Details
MarketMakingEngineConfigurationBranch.sol#configureFeeRecipient()
function is as follows.
function configureFeeRecipient(address feeRecipient, uint256 share) external onlyOwner {
if (feeRecipient == address(0)) revert Errors.ZeroInput("feeRecipient");
MarketMakingEngineConfiguration.Data storage marketMakingEngineConfiguration =
MarketMakingEngineConfiguration.load();
if (share > 0) {
@> UD60x18 totalFeeRecipientsSharesX18 = ud60x18(marketMakingEngineConfiguration.totalFeeRecipientsShares);
if (
@> totalFeeRecipientsSharesX18.add(ud60x18(share)).gt(
@> ud60x18(Constants.MAX_CONFIGURABLE_PROTOCOL_FEE_SHARES)
)
) {
revert Errors.FeeRecipientShareExceedsLimit();
}
}
(, uint256 oldFeeRecipientShares) = marketMakingEngineConfiguration.protocolFeeRecipients.tryGet(feeRecipient);
if (oldFeeRecipientShares > 0) {
if (oldFeeRecipientShares > share) {
@> marketMakingEngineConfiguration.totalFeeRecipientsShares -=
@> (oldFeeRecipientShares - share).toUint128();
} else {
@> marketMakingEngineConfiguration.totalFeeRecipientsShares +=
@> (share - oldFeeRecipientShares).toUint128();
}
} else {
marketMakingEngineConfiguration.totalFeeRecipientsShares += share.toUint128();
}
marketMakingEngineConfiguration.protocolFeeRecipients.set(feeRecipient, share);
emit LogConfigureFeeRecipient(feeRecipient, share);
}
As we can see above, the check of maximum share does not consider oldFeeRecipientShares.
Impact
This vulnerability will cause that owner cannot configure share even if total share does not exceed maximum share.
Tools Used
Manual review
Recommendations
Modify MarketMakingEngineConfigurationBranch.sol#configureFeeRecipient()
as follows.
function configureFeeRecipient(address feeRecipient, uint256 share) external onlyOwner {
if (feeRecipient == address(0)) revert Errors.ZeroInput("feeRecipient");
MarketMakingEngineConfiguration.Data storage marketMakingEngineConfiguration =
MarketMakingEngineConfiguration.load();
--
-- if (share > 0) {
-- UD60x18 totalFeeRecipientsSharesX18 = ud60x18(marketMakingEngineConfiguration.totalFeeRecipientsShares);
--
-- if (
-- totalFeeRecipientsSharesX18.add(ud60x18(share)).gt(
-- ud60x18(Constants.MAX_CONFIGURABLE_PROTOCOL_FEE_SHARES)
-- )
-- ) {
-- revert Errors.FeeRecipientShareExceedsLimit();
-- }
-- }
(, uint256 oldFeeRecipientShares) = marketMakingEngineConfiguration.protocolFeeRecipients.tryGet(feeRecipient);
if (oldFeeRecipientShares > 0) {
if (oldFeeRecipientShares > share) {
marketMakingEngineConfiguration.totalFeeRecipientsShares -=
(oldFeeRecipientShares - share).toUint128();
} else {
marketMakingEngineConfiguration.totalFeeRecipientsShares +=
(share - oldFeeRecipientShares).toUint128();
}
} else {
marketMakingEngineConfiguration.totalFeeRecipientsShares += share.toUint128();
}
++
++ if (share > oldFeeRecipientShares) {
++ UD60x18 totalFeeRecipientsSharesX18 = ud60x18(marketMakingEngineConfiguration.totalFeeRecipientsShares);
++
++ if (
++ totalFeeRecipientsSharesX18.gt(
++ ud60x18(Constants.MAX_CONFIGURABLE_PROTOCOL_FEE_SHARES)
++ )
++ ) {
++ revert Errors.FeeRecipientShareExceedsLimit();
++ }
++ }
marketMakingEngineConfiguration.protocolFeeRecipients.set(feeRecipient, share);
emit LogConfigureFeeRecipient(feeRecipient, share);
}