Omniscia Tangible Audit

Exchange Manual Review Findings

Exchange Manual Review Findings

EEG-01M: Incorrect Output Amount Measurement

TypeSeverityLocation
Logical FaultExchange.sol:L156

Description:

The Exchange::quoteOut function will incorrectly assess the output amount of a swap via the IRouter::getAmountOut as the function's stable boolean result is not mandated to match the stable configuration of the tokenized trade path.

Impact:

The output amount yielded by Exchange::quoteOut may be higher than the actual output of a trade via the stable configuration, causing reliance on the function's outputs for setting minimum outputs to be incorrect.

Example:

contracts/Exchange.sol
144function quoteOut(
145 address tokenIn,
146 address tokenOut,
147 uint256 amountIn
148) external view returns (uint256) {
149 uint256[] memory amounts = new uint256[](2);
150
151 bytes memory tokenized = abi.encodePacked(tokenIn, tokenOut);
152 address _router = routers[tokenized];
153 require(address(0) != _router, "router 0 qo");
154
155 if (simpleSwap[tokenized]) {
156 (amounts[1], ) = IRouter(_router).getAmountOut(amountIn, tokenIn, tokenOut);
157 } else {
158 amounts = new uint256[](routePaths[tokenized].length);
159 amounts = IRouter(_router).getAmountsOut(amountIn, routePaths[tokenized]);
160 }
161
162 return amounts[amounts.length - 1];
163}

Recommendation:

We advise the code to ensure that the stable boolean result of the IRouter::getAmountOut function call matches the stable configuration of the trade path and to handle the failure case accordingly.

Alleviation (2ad448279d9e8e4b6edd94bcd2eb22129b6f7357):

The Exchange::quoteOut function was revised to integrate with Uniswap V3 like pools, thereby no longer being susceptible to the same vulnerability.

As such, we consider this exhibit to be no longer applicable.

EEG-02M: Inexistent Sanitization of Trade Routes

Description:

The Exchange::addRouterForTokens function permits explicit trade routes to be added for a particular token pair, however, these trade routes are not validated in their outputs.

Impact:

A misconfigured trade route may lead to the minimum output values passed into Exchange::exchange to be incorrectly consumed and may cause smart-contract integrators of the Exchange::exchange function to lose funds.

Example:

contracts/Exchange.sol
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 _stable
64) 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 routes
69 routers[tokenized] = _router;
70 routers[tokenizedReverse] = _router;
71 // set paths if any
72 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 hops
81 simpleSwap[tokenized] = _simpleSwap;
82 simpleSwap[tokenizedReverse] = _simpleSwap;
83 //set if pool is stable or not
84 stable[tokenized] = _stable;
85 stable[tokenizedReverse] = _stable;
86}

Recommendation:

As they are passed in as-is in the Exchange::exchange function, we advise the code to ensure that the input and, more importantly, the output tokens of the trade route match the desired outcome.

Alleviation (2ad448279d9e8e4b6edd94bcd2eb22129b6f7357):

The Exchange contract was revised to integrate with Uniswap V3 like pools, thereby no longer requiring interim path definitions and only the input and output tokens from which the tokenized and tokenizedReverse variables are calculated from.

As such, we consider this exhibit no longer applicable.