Project

One World
NFTDeFi
15,000 USDC
View results
Submission Details
Severity: medium
Invalid

Inefficient Use of EnumerableSet.AddressSet for View Functions

Summary

The viewWhitelistedCurrencies function inefficiently uses the EnumerableSet.AddressSet for iterating over the set, which could result in high gas costs when the set grows large.

Finding Description

In the current implementation, the viewWhitelistedCurrencies function returns a list of whitelisted currencies by directly iterating through the EnumerableSet.AddressSet via a for loop. This method can be inefficient, especially when the set grows large, since it involves multiple storage reads and copying data into memory.

The gas cost for reading the set in this manner could increase, leading to unnecessary expenses for users interacting with the contract. In addition, iterating directly over a set stored in EnumerableSet does not leverage the potential efficiency of storing the currencies in an array, which could have a lower gas cost for view functions.

While this issue may not directly break security guarantees, it could lead to performance degradation and higher costs for users.

Vulnerability Details

  • Vulnerability Type: Gas inefficiency

  • Location: viewWhitelistedCurrencies function in CurrencyManager.sol

  • Line of Impact: The iteration through the EnumerableSet when fetching whitelisted currencies.

Impact

The impact of this issue is primarily related to gas inefficiency:

  1. User Costs: Users will face higher transaction costs when calling viewWhitelistedCurrencies as the size of the EnumerableSet grows.

  2. Contract Interaction: Frequent calls to this function on large sets can result in prohibitively high gas fees, which might discourage users from interacting with the contract.

Given that this is a view function, the impact is not immediate in terms of security but it affects usability and cost-effectiveness. If left unaddressed, it could affect the overall user experience and cause performance degradation over time.

Proof of Concept

Here is the relevant code in the viewWhitelistedCurrencies function:

function viewWhitelistedCurrencies(
uint256 cursor,
uint256 size
) external view override returns (address[] memory, uint256) {
uint256 length = size;
if (length > _whitelistedCurrencies.length() - cursor) {
length = _whitelistedCurrencies.length() - cursor;
}
address[] memory whitelistedCurrencies = new address[]();
for (uint256 i = 0; i < length; i++) {
whitelistedCurrencies[i] = _whitelistedCurrencies.at(cursor + i);
}
return (whitelistedCurrencies, cursor + length);
}

The iteration through _whitelistedCurrencies using at(cursor + i) may result in higher gas costs as the set grows, especially for large numbers of whitelisted currencies.

Recommendations

The issue can be addressed by storing the addresses in an array rather than directly relying on the EnumerableSet for iteration in the view function. This would reduce gas costs by avoiding unnecessary access to the set.

Suggested Fix

  1. Store the whitelisted currencies in an array when adding them to the set, or

  2. Create a mapping from addresses to booleans and iterate over the keys in the mapping instead of using EnumerableSet.

Here’s a possible fix for the viewWhitelistedCurrencies function:

// Assuming an array of whitelisted currencies is stored
address[] private whitelistedCurrenciesArray;
function viewWhitelistedCurrencies(
uint256 cursor,
uint256 size
) external view override returns (address[] memory, uint256) {
uint256 length = size;
if (length > whitelistedCurrenciesArray.length - cursor) {
length = whitelistedCurrenciesArray.length - cursor;
}
address[] memory currencies = new address[]();
for (uint256 i = 0; i < length; i++) {
currencies[i] = whitelistedCurrenciesArray[cursor + i];
}
return (currencies, cursor + length);
}

In this implementation, the whitelistedCurrenciesArray would be populated when currencies are added to the system, and no direct iteration of EnumerableSet would be necessary, leading to more efficient gas usage.

Updates

Lead Judging Commences

0xbrivan2 Lead Judge 7 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.