Omniscia Euler Finance Audit
ESynth Code Style Findings
ESynth Code Style Findings
ESH-01C: Ineffectual Usage of Safe Arithmetics
Type | Severity | Location |
---|---|---|
Language Specific | ESynth.sol:L73 |
Description:
The linked mathematical operation is guaranteed to be performed safely by surrounding conditionals evaluated in either require
checks or if-else
constructs.
Example:
73minterCache.minted = minterCache.minted > amount ? minterCache.minted - uint128(amount) : 0; // down-casting is safe because amount < minted <= max uint128
Recommendation:
Given that safe arithmetics are toggled on by default in pragma
versions of 0.8.X
, we advise the linked statement to be wrapped in an unchecked
code block thereby optimizing its execution cost.
Alleviation (fb2dd77a6ff9b7f710edb48e7eb5437e0db4fc1a):
The referenced subtraction has been wrapped in an unchecked
code block safely, optimizing its gas cost.
ESH-02C: Inefficient Loop Limit Evaluation
Type | Severity | Location |
---|---|---|
Gas Optimization | ESynth.sol:L138 |
Description:
The linked for
loop evaluates its limit inefficiently on each iteration.
Example:
138for (uint256 i = 0; i < ignoredForTotalSupply.length(); i++) {
Recommendation:
We advise the statements within the for
loop limit to be relocated outside to a local variable declaration that is consequently utilized for the evaluation to significantly reduce the codebase's gas cost. We should note the same optimization is applicable for storage reads present in such limits as they are newly read on each iteration (i.e. length
members of arrays in storage).
Alleviation (fb2dd77a6ff9b7f710edb48e7eb5437e0db4fc1a):
The referenced loop limit evaluation (ignoredForTotalSupply.length()
) has been properly cached outside the for
loop to a dedicated local variable ignoredLength
that is consequently utilized, optimizing the loop's gas cost significantly.
ESH-03C: Inefficient Structure Mutability Specifiers
Type | Severity | Location |
---|---|---|
Gas Optimization | ESynth.sol:L45, L55, L65, L74 |
Description:
The MinterData
structures that are loaded in the ESynth::mint
and ESynth::burn
functions are declared as storage
yet they are re-written to their respective mapping
slot after being mutated.
Example:
40/// @notice Mints a certain amount of tokens to the account.41/// @param account The account to mint the tokens to.42/// @param amount The amount of tokens to mint.43function mint(address account, uint256 amount) external nonReentrant {44 address sender = _msgSender();45 MinterData storage minterCache = minters[sender];46
47 if (48 amount > type(uint128).max - minterCache.minted49 || minterCache.capacity < uint256(minterCache.minted) + amount50 ) {51 revert E_CapacityReached();52 }53
54 minterCache.minted += uint128(amount); // safe to down-cast because amount <= capacity <= max uint12855 minters[sender] = minterCache;56
57 _mint(account, amount);58}59
60/// @notice Burns a certain amount of tokens from the accounts balance. Requires the account, except the owner to have an allowance for the sender.61/// @param account The account to burn the tokens from.62/// @param amount The amount of tokens to burn.63function burn(address account, uint256 amount) external nonReentrant {64 address sender = _msgSender();65 MinterData storage minterCache = minters[sender];66
67 // The allowance check should be performed if the spender is not the account with the exception of the owner burning from this contract.68 if (account != sender && !(account == address(this) && sender == owner())) {69 _spendAllowance(account, sender, amount);70 }71
72 // If burning more than minted, reset minted to 073 minterCache.minted = minterCache.minted > amount ? minterCache.minted - uint128(amount) : 0; // down-casting is safe because amount < minted <= max uint12874 minters[sender] = minterCache;75
76 _burn(account, amount);77}
Recommendation:
We advise both variables to be set as memory
, optimizing the gas cost of each function to one SLOAD
and one SSTORE
operation.
Alleviation (fb2dd77a6ff9b7f710edb48e7eb5437e0db4fc1a):
The data locations of the two referenced local MinterData
declarations have been properly updated to memory
, optimizing each function's gas cost.
ESH-04C: Loop Iterator Optimization
Type | Severity | Location |
---|---|---|
Gas Optimization | ESynth.sol:L138 |
Description:
The linked for
loop increments / decrements the iterator "safely" due to Solidity's built-in safe arithmetics (post-0.8.X
).
Example:
138for (uint256 i = 0; i < ignoredForTotalSupply.length(); i++) {
Recommendation:
We advise the increment / decrement operation to be performed in an unchecked
code block as the last statement within the for
loop to optimize its execution cost.
Alleviation (fb2dd77a6f):
The recommendation has been indirectly addressed due to the alleviation of exhibit ESH-02C
and thus the optimizer's application.
To note, the original loop iterator was not optimized as the ignoredForTotalSupply.length()
statement was considered dynamic and thus the optimizer did not assume the increment would be securely performed.
Alleviation (0f2192ac81):
After further testing of the proposed optimization, we concluded that the built-in optimizations of the Solidity compiler the project uses (0.8.23
) would have covered the iterator case described in the exhibit per the official requirements of the optimization.
As such, we consider the optimization nullified as it would not have resulted in a gas reduction in its original form.