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.
