Omniscia Tangible Audit
Exchange Code Style Findings
Exchange Code Style Findings
EEG-01C: Inefficient mapping
Lookups
Type | Severity | Location |
---|---|---|
Gas Optimization | Exchange.sol:L124, L128 |
Description:
The linked statements perform key-based lookup operations on mapping
declarations from storage multiple times for the same key redundantly.
Example:
123} else {124 amounts = new uint256[](routePaths[tokenized].length);125 amounts = IRouter(_router).swapExactTokensForTokens(126 amountIn,127 minAmountOut,128 routePaths[tokenized],129 msg.sender,130 block.timestamp131 );132}
Recommendation:
As the lookups internally perform an expensive keccak256
operation, we advise the lookups to be cached wherever possible to a single local declaration that either holds the value of the mapping
in case of primitive types or holds a storage
pointer to the struct
contained.
Alleviation (2ad448279d9e8e4b6edd94bcd2eb22129b6f7357):
All referenced inefficient mapping
lookups have been optimized to the greatest extent possible, significantly reducing the gas cost of the functions the statements were located in.
EEG-02C: Sub-Optimal Inverse Route Management
Type | Severity | Location |
---|---|---|
Gas Optimization | Exchange.sol:L75 |
Description:
The overall Exchange
contract and specifically its Exchange::addRouterForTokens
function will inefficiently maintain duplicate data entries for the trade route it wishes to support between two tokens.
Example:
56function addRouterForTokens(57 address tokenInAddress,58 address tokenOutAddress,59 address _router,60 IRouter.Route[] calldata _routes,61 IRouter.Route[] calldata _routesReversed,62 bool _simpleSwap,63 bool _stable64) external onlyFactoryOwner {65 require(_routes.length == _routesReversed.length, "mismatch");66 bytes memory tokenized = abi.encodePacked(tokenInAddress, tokenOutAddress);67 bytes memory tokenizedReverse = abi.encodePacked(tokenOutAddress, tokenInAddress);68 // set routes69 routers[tokenized] = _router;70 routers[tokenizedReverse] = _router;71 // set paths if any72 uint256 length = _routes.length;73 for (uint256 i; i < length; ) {74 routePaths[tokenized].push(_routes[i]);75 routePaths[tokenizedReverse].push(_routesReversed[i]);76 unchecked {77 ++i;78 }79 }80 // set if simple swap or with hops81 simpleSwap[tokenized] = _simpleSwap;82 simpleSwap[tokenizedReverse] = _simpleSwap;83 //set if pool is stable or not84 stable[tokenized] = _stable;85 stable[tokenizedReverse] = _stable;86}
Recommendation:
We advise the Exchange
contract to sort the in and out tokens of a swap similarly to Uniswap and to maintain a single data entry for each.
If the inverse trade path is requested, we advise the canonical trade path to be loaded from storage
and to be reversed using a local memory
variable which will significantly optimize the gas cost of maintaining trade routes.
Alleviation (2ad448279d9e8e4b6edd94bcd2eb22129b6f7357):
The Exchange
contract was revised to integrate with Uniswap V3 like pools, thereby no longer requiring complex router paths in reverse order.
As such, we consider this optimization no longer applicable.