Omniscia Mean Finance Audit

TransformerOracle Code Style Findings

TransformerOracle Code Style Findings

TOE-01C: Potential Quote Code Simplification

Description:

The linked code statements contain a lot of repetition as the joint transformer case is identical in statements to each independent transformer case.

Example:

solidity/contracts/TransformerOracle.sol
89if (address(_transformerTokenIn) != address(0) && address(_transformerTokenOut) != address(0)) {
90 // If both tokens have a transformer, then we need to transform both in and out data
91 ITransformer.UnderlyingAmount[] memory _transformedIn = _transformerTokenIn.calculateTransformToUnderlying(_tokenIn, _amountIn);
92 address[] memory _underlyingOut = _transformerTokenOut.getUnderlying(_tokenOut);
93 uint256 _amountOutUnderlying = UNDERLYING_ORACLE.quote(_transformedIn[0].underlying, _transformedIn[0].amount, _underlyingOut[0], _data);
94 return _transformerTokenOut.calculateTransformToDependent(_tokenOut, _toUnderlyingAmount(_underlyingOut[0], _amountOutUnderlying));
95} else if (address(_transformerTokenIn) != address(0)) {
96 // If token in has a transformer, then calculate how much amount it would be in underlying, and calculate the quote for that
97 ITransformer.UnderlyingAmount[] memory _transformedIn = _transformerTokenIn.calculateTransformToUnderlying(_tokenIn, _amountIn);
98 return UNDERLYING_ORACLE.quote(_transformedIn[0].underlying, _transformedIn[0].amount, _tokenOut, _data);
99} else if (address(_transformerTokenOut) != address(0)) {
100 // If token out has a transformer, then calculate the quote for the underlying and then transform the result
101 address[] memory _underlyingOut = _transformerTokenOut.getUnderlying(_tokenOut);
102 uint256 _amountOutUnderlying = UNDERLYING_ORACLE.quote(_tokenIn, _amountIn, _underlyingOut[0], _data);
103 return _transformerTokenOut.calculateTransformToDependent(_tokenOut, _toUnderlyingAmount(_underlyingOut[0], _amountOutUnderlying));
104} else {
105 // If there are no transformers, then just call the underlying oracle
106 return UNDERLYING_ORACLE.quote(_tokenIn, _amountIn, _tokenOut, _data);
107}

Recommendation:

We advise local variables to be utilized for the final calculation and the code to be simplified by simply performing assignments in each transformer presence case thus greatly increasing the legibility and maintainability of the codebase and achieving a minor gas optimization.

Alleviation:

The code was greatly simplified by applying the recommended optimization and requiring only two if clauses and a total of 8 "complex" statements rather than 11 optimizing the codebase's legibility and gas cost in the process.

TOE-02C: Potential Transformer Code Simplification

Description:

The _getTransformers function can be greatly simplified by querying the transformers function of REGISTRY directly and then zeroing out the entries based on the _avoidMappingA and _avoidMappingB evaluations.

Example:

solidity/contracts/TransformerOracle.sol
150function _getTransformers(address _tokenA, address _tokenB) internal view virtual returns (ITransformer[] memory _transformers) {
151 bool _avoidMappingA = willAvoidMappingToUnderlying[_tokenA];
152 bool _avoidMappingB = willAvoidMappingToUnderlying[_tokenB];
153 if (!_avoidMappingA && !_avoidMappingB) {
154 address[] memory _tokens = new address[](2);
155 _tokens[0] = _tokenA;
156 _tokens[1] = _tokenB;
157 return REGISTRY.transformers(_tokens);
158 } else {
159 _transformers = new ITransformer[](2);
160 if (_avoidMappingA && _avoidMappingB) {
161 _transformers[0] = ITransformer(address(0));
162 _transformers[1] = ITransformer(address(0));
163 } else if (_avoidMappingA) {
164 _transformers[0] = ITransformer(address(0));
165 address[] memory _tokens = new address[](1);
166 _tokens[0] = _tokenB;
167 ITransformer[] memory _returnedTransformers = REGISTRY.transformers(_tokens);
168 _transformers[1] = _returnedTransformers[0];
169 } else {
170 address[] memory _tokens = new address[](1);
171 _tokens[0] = _tokenA;
172 ITransformer[] memory _returnedTransformers = REGISTRY.transformers(_tokens);
173 _transformers[0] = _returnedTransformers[0];
174 _transformers[1] = ITransformer(address(0));
175 }
176 }
177}

Recommendation:

We advise this to be done so greatly optimizing the gas cost of the function and simplifying its execution.

Alleviation:

The code was optimized based on our recommendation and simply overwrites the _transformerTokenA and _transformerTokenB entries (previously _transformers) based on whether their "avoidance" flags have been set, optimizing the code's readability significantly.