Omniscia vfat Audit
FlashloanStrategy Code Style Findings
FlashloanStrategy Code Style Findings
FSG-01C: Illegible Selector Extraction
Type | Severity | Location |
---|---|---|
Code Style | ![]() | FlashloanStrategy.sol:L709-L722 |
Description:
The FlashloanStrategy::extractSelector
function represents an assembly
block that extracts the function selector of a bytes
payload.
Example:
709function extractSelector(bytes memory params)710 public711 pure712 returns (bytes4 selector)713{714 assembly {715 // 1. Load 4 bytes from `params`716 // 2. Shift the bytes left by 224 bits/28 bytes so that they're at717 // the beginning of the 32-byte memory slot as required by718 // Solidity ABI spec719 // 3. Store the result in `selector`720 selector := shl(224, mload(add(params, 4)))721 }722}
Recommendation:
We advise this to be achieved via Solidity's built-in syntax and namely slices by assigning the value of params[:4]
to the selector
variable after casting to the bytes4
data type.
Alleviation (6ab7af3bb4):
The vfat team evaluated this exhibit and stated that the optimization is inapplicable due to the input argument’s memory
data location.
In this case, we advise the bytes4
cast to be performed directly on the params
argument thus increasing the legibility of the codebase whilst minimizing usage of assembly
blocks and achieving the same end result.
Alleviation (986c6b0a71):
The code was updated per our recommendation, optimizing its syntax whilst retaining the same computational result.
FSG-02C: Inexecutable Code
Type | Severity | Location |
---|---|---|
Gas Optimization | ![]() | FlashloanStrategy.sol:L318-L320 |
Description:
The FlashloanStrategy::initiateFlashloan
function contains an else
branch that will never be executed as the decoding process of an enum
will prevent non-explicit values from being stored in it.
Example:
235if (providerType == FlashloanProvider.AAVEV2) {236 uint256[] memory modes = new uint256[](assets.length);237 // mode 0 = no debt incurred, everything repaid at end of flashloan238 bytes memory aaveV2params = abi.encode(sickleAddress, params);239 // storing the hash of the callback data for safety checks240 flashloanDataHash = keccak256(aaveV2params);241 ILendingPoolV2(aaveV2LendingPool).flashLoan(242 address(this), // flashloan receiver243 assets,244 amounts,245 modes,246 address(0), // onBehalfOf variable247 aaveV2params,248 0 // referral code249 );250} else if (providerType == FlashloanProvider.AAVEV3) {251 bytes memory aaveV3params = abi.encode(sickleAddress, params);252 // storing the hash of the callback data for safety checks253 flashloanDataHash = keccak256(aaveV3params);254 if (assets.length == 1) {255 IPoolV3(aaveV3LendingPool).flashLoanSimple(256 address(this), // flashloan receiver257 assets[0],258 amounts[0],259 aaveV3params,260 0 // referral code261 );262 } else {263 uint256[] memory modes = new uint256[](assets.length);264 // mode 0 = no debt incurred, everything repaid at end of265 // flashloan266 IPoolV3(aaveV3LendingPool).flashLoan(267 address(this), // flashloan receiver268 assets,269 amounts,270 modes,271 address(0),272 aaveV3params,273 0 // referral code274 );275 }276} else if (providerType == FlashloanProvider.BALANCER) {277 bytes memory balancerParams = abi.encode(sickleAddress, params);278 // storing the hash of the callback data for safety checks279 flashloanDataHash = keccak256(balancerParams);280 IBalancerVault(balancerVault).flashLoan(281 this, assets, amounts, balancerParams282 );283} else if (providerType == FlashloanProvider.UNIV2) {284 if (assets.length != 2) revert NotAnAssetPair();285 address poolAddress = IUniswapV2Factory(quickswapFactoryAddr)286 .getPair(assets[0], assets[1]);287 (,, uint256[] memory premiums,) =288 abi.decode(params[4:], (address[], uint256[], uint256[], bytes));289 bytes memory uniswapFlashParams = abi.encode(290 sickleAddress, poolAddress, assets, amounts, premiums, params291 );292 // storing the hash of the callback data for safety checks293 flashloanDataHash = keccak256(uniswapFlashParams);294 IUniswapV2Pair(poolAddress).swap(295 amounts[0], amounts[1], address(this), uniswapFlashParams296 );297} else if (providerType == FlashloanProvider.UNIV3) {298 if (assets.length != 2) revert NotAnAssetPair();299 address poolAddress = IUniswapV3Factory(uniswapV3FactoryAddr)300 .getPool(assets[0], assets[1], providerFee);301 (,, uint256[] memory premiums,) =302 abi.decode(params[4:], (address[], uint256[], uint256[], bytes));303 bytes memory uniswapFlashParams = abi.encode(304 sickleAddress, poolAddress, assets, amounts, premiums, params305 );306 // storing the hash of the callback data for safety checks307 flashloanDataHash = keccak256(uniswapFlashParams);308 IUniswapV3Pool(poolAddress).flash(309 address(this), amounts[0], amounts[1], uniswapFlashParams310 );311} else if (providerType == FlashloanProvider.MORPHO) {312 if (assets.length != 1) revert NotSingleAsset();313 bytes memory morphoParams =314 abi.encode(sickleAddress, assets[0], params);315 // storing the hash of the callback data for safety checks316 flashloanDataHash = keccak256(morphoParams);317 IMorpho(morpho).flashLoan(assets[0], amounts[0], morphoParams);318} else {319 revert UnauthorizedOperation();320}
Recommendation:
We advise the else
branch to be omitted, and the last else-if
branch to be converted to an else
branch optimizing the code's gas cost.
Alleviation (6ab7af3bb495b817ffec469255ea679b1813eecb):
The inexecutable else
branch has been omitted from the codebase and the else if
branch of the MORPHO
provider type has been optimized per our recommendations.
FSG-03C: Redundant Zero-Value Assignments
Type | Severity | Location |
---|---|---|
Gas Optimization | ![]() | FlashloanStrategy.sol: • I-1: L624 • I-2: L642 • I-3: L658 • I-4: L675 • I-5: L690 |
Description:
All values of the premiums
array on initialization are zero rendering assignments of zero to be inefficient.
Example:
684for (uint256 i; i < length;) {685 if (amounts[i] > 0) {686 premiums[i] =687 ((amounts[i] * providerFee) / 10_000 / 100) + 1; // hundredths688 // of basis points689 } else {690 premiums[i] = 0;691 }692
693 unchecked {694 ++i;695 }696}
Recommendation:
We advise all referenced assignments to be omitted, optimizing the code's gas cost and legibility.
Alleviation (6ab7af3bb495b817ffec469255ea679b1813eecb):
All redundant zero-value assignments have been omitted as advised.
FSG-04C: Repetitive Value Literal
Type | Severity | Location |
---|---|---|
Code Style | ![]() | FlashloanStrategy.sol:L621, L639, L687 |
Description:
The linked value literal is repeated across the codebase multiple times.
Example:
621/ 10_000
Recommendation:
We advise it to be set to a constant
variable instead, optimizing the legibility of the codebase.
In case the constant
has already been declared, we advise it to be properly re-used across the code.
Alleviation (6ab7af3bb495b817ffec469255ea679b1813eecb):
The referenced value literal 10_000
has been properly relocated to a contract-level constant
declaration labelled BPS_BASIS
, optimizing the code's legibility.