Omniscia Badai Tech Audit
IndexPool Code Style Findings
IndexPool Code Style Findings
IPL-01C: Deprecated Revert Pattern
Type | Severity | Location |
---|---|---|
Code Style | ![]() | IndexPool.sol:L82 |
Description:
The referenced revert
statement is deprecated as it yields a textual literal.
Example:
81if (heldTokens[i] == _tokenAddress) {82 revert("IndexPool: Token has already been added");83}
Recommendation:
We advise a proper error
declaration to be introduced, or the if-revert
pattern to be updated with the require
pattern.
Alleviation (d639d227f8b8d90dbd9813ab9d7a5cbee34dd9b1):
A custom TokenCanNotBeAddedTwice
error declaration was introduced for the relevant if-revert
pattern addressing this exhibit.
IPL-02C: Inefficient Iterator Types
Type | Severity | Location |
---|---|---|
Gas Optimization | ![]() | IndexPool.sol: • I-1: L48 • I-2: L51 • I-3: L80 • I-4: L95 |
Description:
The referenced for
loop iterators are defined as unit8
data types inefficiently.
Example:
95for (uint8 i = 0; i < _tokens.length; i++) {
Recommendation:
The EVM is built to operate on 256-bit data types, and any types that utilize less bits involve masking operations that increase the gas cost involved on all operations.
We advise the relevant data types to be set to the uint256
data type, optimizing all instances that the variables are utilized in.
Alleviation (d639d227f8b8d90dbd9813ab9d7a5cbee34dd9b1):
All applicable iterator types have been updated to uint256
as advised, optimizing the code's gas cost.
IPL-03C: Inefficient Token Skipping Mechanism
Type | Severity | Location |
---|---|---|
Gas Optimization | ![]() | IndexPool.sol:L44, L51-L56 |
Description:
The current token skipping mechanism is inefficient as it will perform an iteration of the _skipTokens
array for each iteration of the heldTokens
array.
Example:
42function burnIndexTokenAndSkipSomeTokens(43 uint256 _amount,44 address[] memory _skipTokens45) public nonReentrant {46 uint256 amountOfPoolBalance;47 indexToken.burnFrom(msg.sender, _amount);48 for (uint8 i = 0; i < heldTokens.length; i++) {49 // Skip tokens that are in the skipTokens array50 bool skipToken = false;51 for (uint8 j = 0; j < _skipTokens.length; j++) {52 if (heldTokens[i] == _skipTokens[j]) {53 skipToken = true;54 break;55 }56 }57 if (skipToken) {58 continue;59 }60
61 amountOfPoolBalance =62 ((IERC20(heldTokens[i])).balanceOf(address(this)) * _amount) /63 indexToken.totalSupply();64 if (amountOfPoolBalance > 0) {65 (IERC20(heldTokens[i])).safeTransfer(66 msg.sender,67 amountOfPoolBalance68 );69 }70 }71 emit IndexTokenBurned(msg.sender, _amount);72}
Recommendation:
We advise the approach to be revised, mandating that callers configure the _skipTokens
array in the same order that the tokens are identified in the heldTokens
array.
This will permit the code to solely check the uppermost entry of the _skipTokens
array, incrementing its index solely when a token has been skipped and thus greatly optimizing the function's gas cost and scalability.
Alleviation (d639d227f8b8d90dbd9813ab9d7a5cbee34dd9b1):
The optimization has been implemented as advised, greatly reducing the gas cost associated with skipping a particular token.
IPL-04C: Redundant Application of Modifier
Type | Severity | Location |
---|---|---|
Gas Optimization | ![]() | IndexPool.sol:L78, L94 |
Description:
The IndexPool::addTokenBatch
function will re-apply the Ownable::onlyOwner
modifier once at the top-level call and once on each inner IndexPool::addToken
call.
Example:
74/**75 * @notice Adds a token to the index pool.76 * @param _tokenAddress The address of the token to add.77 */78function addToken(address _tokenAddress) public onlyOwner {79 // Check if the token is already in the pool, to prevent distributing it multiple times80 for (uint8 i = 0; i < heldTokens.length; i++) {81 if (heldTokens[i] == _tokenAddress) {82 revert("IndexPool: Token has already been added");83 }84 }85
86 heldTokens.push(_tokenAddress);87 emit TokenAdded();88}89
90/**91 * @notice Adds a batch of tokens to the index pool.92 * @param _tokens The addresses of the tokens to add.93 */94function addTokenBatch(address[] calldata _tokens) external onlyOwner {95 for (uint8 i = 0; i < _tokens.length; i++) {96 addToken(_tokens[i]);97 }98}
Recommendation:
We advise the contents of the IndexPool::addToken
function to be refactored to an internal
function that does not apply the modifier, permitting the same function to be invoked across both implementations optimally.
Alleviation (d639d227f8):
This optimization has not been applied rendering it to be considered acknowledged. To note, both functions can remain public and the internalization of the IndexPool::addToken
function's statements would not functionally affect either function.
Alleviation (2ef12e6885):
The optimization has been applied per our recommendation, greatly optimizing the gas cost of the batch function's operation.
IPL-05C: Redundant Parenthesis Statements
Type | Severity | Location |
---|---|---|
Code Style | ![]() | IndexPool.sol: • I-1: L62 • I-2: L65 |
Description:
The referenced statements are redundantly wrapped in parenthesis' (()
).
Example:
62((IERC20(heldTokens[i])).balanceOf(address(this)) * _amount) /
Recommendation:
We advise them to be safely omitted, increasing the legibility of the codebase.
Alleviation (d639d227f8b8d90dbd9813ab9d7a5cbee34dd9b1):
The redundant parenthesis in the referenced statements have been safely omitted.
IPL-06C: Variable Mutability Specifier (Immutable)
Type | Severity | Location |
---|---|---|
Gas Optimization | ![]() | IndexPool.sol:L17 |
Description:
The linked variable is assigned to only once during the contract's constructor
.
Example:
23constructor(address _indexToken) Ownable(msg.sender) {24 indexToken = IERC20Burnable(_indexToken);25}
Recommendation:
We advise it to be set as immutable
greatly optimizing its read-access gas cost.
Alleviation (d639d227f8b8d90dbd9813ab9d7a5cbee34dd9b1):
The indexToken
contract-level variable of the contract has been set as immutable
, optimizing its read-access gas cost significantly.