Closed sherlock-admin2 closed 10 months ago
1 comment(s) were left on this issue during the judging contest.
auditsea commented:
Gas
1 comment(s) were left on this issue during the judging contest.
auditsea commented:
Gas
Invalid, all informational/gas optimization finding
eta
medium
Unhandled Return Data in
Delegatecall
, Memory Optimization, Unused Parameter and Unsafe Code CastSummary
This code review highlights four issues for improvement: 1)Unhandled Return Data in
Diamond:: fallback
: The Diamond::fallback function's external call doesn't handle return data ofdelegatecall
, potentially exposing it to gas griefing attacks. 2)Optimize Logic in Setter Function: To enhance change tracking and potentially reduce memory usage, record both old and new values for critical parameter changes within setter functions inLibDiamond.sol and LibUbiquityPool.sol
, avoiding unnecessary caching. 3)Unused Parameter inLibDiamond::removeFunctions
: TheLibDiamond::removeFunctions
function has an unnecessary parameter,_facetAddress
, which is unused in its logic to check for address(0), with a notice to checkif function does not exist then do nothing and return
which is more relevant to the_functionSelectors
requirement. 4)Code Cast from Unit256 to Uint112 and back to Uint256: The code casts a uint256 value fromIMetaPool::balances
to a smaller uint112 type and then immediately to the uint256 type inLibTWAPOracle::setPool
.Vulnerability Detail
1.Unhandled Return Data in
Diamond:: fallback
EVM Return Data Handling: When a contract calls another contract (external calls), the EVM allocates memory to store the called contract's return data, including a boolean success value indicating the call outcome.
Unhandled Return Data: In the code snippet,
let result := delegatecall(gas(), facet, 0, calldatasize(), 0, 0)
performs an external call without specifying any output buffer (out) or its size (outsize). This means the return data is discarded, including the success value.Potential Gas Griefing: Malicious external contracts could exploit this by intentionally returning large amounts of data, consuming more gas than expected. This could lead to unexpected gas costs for the calling contract or even prevent it from completing the transaction, potentially disrupting its functionality.
Diamond::fallback
2.Improve Logic in Setter Function in
LibDiamond.sol and LibUbiquityPool.sol
Record both old and new values: Directly within setter functions, it is recommended to record both its previous and updated values of critical parameters. This creates a detailed change history, enabling accurate tracking of parameter modifications, informed analysis of change patterns and potential rollback to a previous state if required.
Eliminate unnecessary caching: If the old value is only needed for immediate actions (e.g., event emission), access it directly within the setter to streamline code and potentially reduce memory overhead. This streamlines code, potentially reduces memory overhead, and improve code readability.
LibDiamond::setContractOwner
All other instances entailed:
LibUbiquityPool::updateChainLinkCollateralPrice
LibUbiquityPool::setFees
LibUbiquityPool::setPoolCeiling
LibUbiquityPool::setPriceThresholds
LibUbiquityPool::setRedemptionDelayBlocks
3.Unused Parameter in
LibDiamond::removeFunctions
The
removeFunctions
function has an unused parameter,_facetAddress
, which is passed to it but never utilized within the logic of both theremoveFunctions
and theremoveFunction
functions.This parameter is only checked in a require statement that ensures its value is address(0) as mentioned by a notice. However, this notice of
// if function does not exist then do nothing and return
is more logically relevant to the_functionSelectors
requirement.LibDiamond::removeFunctions
4.Consider to Use SafeCast for Casting
Casting from larger types to smaller ones can potentially lead to overflows and thus unexpected behavior. When the uint256 value in the
IMetaPool::balances
gets cast to uint112 in theLibTWAPOracle::setPool
, it could end up as an entirely different, much smaller number due to the reduction in bits.OpenZeppelin's SafeCast library provides functions for safe type conversions, throwing an error whenever an overflow would occur. It is generally recommended to use SafeCast or similar protective measures when performing type conversions to ensure the accuracy of your computations and the security of your contracts.
LibTWAPOracle::setPool
IMetaPool::balances
Impact
Unhandled Return Data and Potential Gas Griefing: By ignoring the return data from external calls, this code opens the door to gas griefing, so that malicious contracts can force high gas usage, potentially preventing completion or causing unexpected financial losses.
Inaccurate Tracing and Analysis: Without capturing both old and new values, precise tracking of parameter changesis impossible, hindering trend analysis and issue diagnosis.
Unused Parameter: The presence of an unused parameter introduces unnecessary complexity and opens potential security vulnerabilities for malicious actors to exploit.
Overflow Risk in Type Casting: Overflows can result in unexpected and incorrect calculations, potentially leading to financial losses, contract malfunctions, or security vulnerabilities.
Code Snippet
1) Diamond::fallback
2) LibDiamond::setContractOwner LibUbiquityPool::updateChainLinkCollateralPrice LibUbiquityPool::setFees LibUbiquityPool::setPoolCeiling LibUbiquityPool::setPriceThresholds LibUbiquityPool::setRedemptionDelayBlocks
3) LibDiamond::removeFunctions
4) LibTWAPOracle::setPool IMetaPool::balances
Tool used
Manual Review
Recommendation
Use Safe Delecatecall Pattern: Employ the delegatecall function with appropriate out and outsize parameters to capture the return data. This allows for proper handling of the success value and prevents unexpected gas consumption.
Prioritize Change Tracking and Memory Efficiency: Capture both old and new values directly within setter functions for critical parameters to establish a detailed change history. Avoid unnecessary caching by directly accessing old values within the functions when feasible, which potentially reduces memory overhead and enhances code readability.
Remove
_facetAddress
Parameter: Eliminate the_facetAddress
parameter from theremoveFunctions
function to eliminate potential confusion, and reduces the risk of unintended vulnerabilities related to unused parameters.Use Safe Casting Libraries: Employ OpenZeppelin's SafeCast library or similar tools for safe type conversions. If possible, use larger data types (e.g., uint256) throughout the contract to avoid the need for casting and reduce the risk of overflows.