Omniscia Gravita Protocol Audit
StabilityPool Code Style Findings
StabilityPool Code Style Findings
SPL-01C: Inefficient Renunciation of Ownership
Type | Severity | Location |
---|---|---|
Gas Optimization | ![]() | StabilityPool.sol:L267 |
Description:
The StabilityPool::setAddresses
function will invoke the OwnableUpgradeable::renounceOwnership
function which in turn will apply the onlyOwner
modifier redundantly.
Example:
242function setAddresses(243 address _borrowerOperationsAddress,244 address _vesselManagerAddress,245 address _activePoolAddress,246 address _debtTokenAddress,247 address _sortedVesselsAddress,248 address _communityIssuanceAddress,249 address _adminContractAddress250) external initializer override {251 require(!isInitialized, "StabilityPool: Already initialized");252
253 isInitialized = true;254 __Ownable_init();255 __ReentrancyGuard_init();256
257 borrowerOperations = IBorrowerOperations(_borrowerOperationsAddress);258 vesselManager = IVesselManager(_vesselManagerAddress);259 activePool = IActivePool(_activePoolAddress);260 debtToken = IDebtToken(_debtTokenAddress);261 sortedVessels = ISortedVessels(_sortedVesselsAddress);262 communityIssuance = ICommunityIssuance(_communityIssuanceAddress);263 adminContract = IAdminContract(_adminContractAddress);264
265 P = DECIMAL_PRECISION;266
267 renounceOwnership();268}
Recommendation:
We advise the OwnableUpgradeable::_transferOwnership
function to be utilized directly, transferring ownership to the zero address.
Alleviation:
Ownership of the contract is no longer renounced in the latest iteration of the codebase rendering this exhibit inapplicable.
SPL-02C: Inefficient mapping
Lookups
Type | Severity | Location |
---|---|---|
Gas Optimization | ![]() | StabilityPool.sol:L404, L405, L661, L662, L836, L838-L841, L852, L856-L859 |
Description:
The linked statements perform key-based lookup operations on mapping
declarations from storage multiple times for the same key redundantly.
Example:
392function _updateG(uint256 _GRVTIssuance) internal {393 uint256 cachedTotalDebtTokenDeposits = totalDebtTokenDeposits; // cached to save an SLOAD394 /*395 * When total deposits is 0, G is not updated. In this case, the GRVT issued can not be obtained by later396 * depositors - it is missed out on, and remains in the balanceof the CommunityIssuance contract.397 *398 */399 if (cachedTotalDebtTokenDeposits == 0 || _GRVTIssuance == 0) {400 return;401 }402 uint256 GRVTPerUnitStaked = _computeGRVTPerUnitStaked(_GRVTIssuance, cachedTotalDebtTokenDeposits);403 uint256 marginalGRVTGain = GRVTPerUnitStaked.mul(P);404 epochToScaleToG[currentEpoch][currentScale] = epochToScaleToG[currentEpoch][currentScale].add(marginalGRVTGain);405 emit G_Updated(epochToScaleToG[currentEpoch][currentScale], currentEpoch, currentScale);406}
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:
All but the first instance pair have been optimized per our recommendation, rendering this exhibit partially alleviated.
SPL-03C: Inexplicable Contract Member
Type | Severity | Location |
---|---|---|
Gas Optimization | ![]() | StabilityPool.sol:L174, L615-L616, L806-L807 |
Description:
The pendingCollGains
member of the StabilityPool
is utilized in multiple statements within the code, however, it results in a no-op as it remains filled with zero-values throughout its lifetime.
Example:
805// Reset pendingCollGains since those were all sent to the borrower806Colls memory tempPendingCollGains;807pendingCollGains[_to] = tempPendingCollGains;
Recommendation:
We advise it to be re-evaluated and potentially omitted, significantly improving the gas costs of the functions it was utilized in.
Alleviation:
The pendingCollGains
contract member has been safely removed as advised.
SPL-04C: Inexplicable Ownable Pattern
Type | Severity | Location |
---|---|---|
Gas Optimization | ![]() | StabilityPool.sol:L254, L267 |
Description:
The StabilityPool
inherits the OwnableUpgradeable
implementation redundantly as it initializes it within the StabilityPool::setAddresses
function and consequently renounces ownership in the same call.
Example:
242function setAddresses(243 address _borrowerOperationsAddress,244 address _vesselManagerAddress,245 address _activePoolAddress,246 address _debtTokenAddress,247 address _sortedVesselsAddress,248 address _communityIssuanceAddress,249 address _adminContractAddress250) external initializer override {251 require(!isInitialized, "StabilityPool: Already initialized");252
253 isInitialized = true;254 __Ownable_init();255 __ReentrancyGuard_init();256
257 borrowerOperations = IBorrowerOperations(_borrowerOperationsAddress);258 vesselManager = IVesselManager(_vesselManagerAddress);259 activePool = IActivePool(_activePoolAddress);260 debtToken = IDebtToken(_debtTokenAddress);261 sortedVessels = ISortedVessels(_sortedVesselsAddress);262 communityIssuance = ICommunityIssuance(_communityIssuanceAddress);263 adminContract = IAdminContract(_adminContractAddress);264
265 P = DECIMAL_PRECISION;266
267 renounceOwnership();268}
Recommendation:
We advise it to be removed, inheriting the Initializable
implementation of OpenZeppelin instead which is properly put in use within the contract.
Alleviation:
The contract no longer utilizes or inherits the OwnableUpgradeable
implementation, addressing this exhibit in full.
SPL-05C: Loop Iterator Optimizations
Type | Severity | Location |
---|---|---|
Gas Optimization | ![]() | StabilityPool.sol:L635, L794, L835, L849, L896, L924, L934 |
Description:
The linked for
loops increment / decrement their iterator "safely" due to Solidity's built - in safe arithmetics (post-0.8.X
).
Example:
635for (uint256 i = 0; i < assetsLen; ++i) {
Recommendation:
We advise the increment / decrement operations to be performed in an unchecked
code block as the last statement within each for
loop to optimize their execution cost.
Alleviation:
The loop iterator increments have been optimized as advised where applicable, however, their i++
counterpart is utilized instead of ++i
. We advise the latter to be set in use as it is more optimal than the present code.
SPL-06C: Redundant Initialization Paradigm
Type | Severity | Location |
---|---|---|
Gas Optimization | ![]() | StabilityPool.sol:L250-L251, L253 |
Description:
The StabilityPool
contract inherits the OpenZeppelin OwnableUpgradeable
implementation which contains the Initializable
implementation, put in use within the StabilityPool::setAddresses
function. As such, the manual isInitialized
flag is redundant.
Example:
242function setAddresses(243 address _borrowerOperationsAddress,244 address _vesselManagerAddress,245 address _activePoolAddress,246 address _debtTokenAddress,247 address _sortedVesselsAddress,248 address _communityIssuanceAddress,249 address _adminContractAddress250) external initializer override {251 require(!isInitialized, "StabilityPool: Already initialized");252
253 isInitialized = true;254 __Ownable_init();255 __ReentrancyGuard_init();256
257 borrowerOperations = IBorrowerOperations(_borrowerOperationsAddress);258 vesselManager = IVesselManager(_vesselManagerAddress);259 activePool = IActivePool(_activePoolAddress);260 debtToken = IDebtToken(_debtTokenAddress);261 sortedVessels = ISortedVessels(_sortedVesselsAddress);262 communityIssuance = ICommunityIssuance(_communityIssuanceAddress);263 adminContract = IAdminContract(_adminContractAddress);264
265 P = DECIMAL_PRECISION;266
267 renounceOwnership();268}
Recommendation:
We advise it and its validations to be omitted from the codebase as it is ineffectual and duplicates the purpose of the Initializable::initializer
modifier.
Alleviation:
The manual initialization methodology has been removed from the contract as advised.
SPL-07C: Suboptimal Struct Declaration Style
Type | Severity | Location |
---|---|---|
Code Style | ![]() | StabilityPool.sol:L614 |
Description:
The linked declaration style of a struct is using index-based argument initialization.
Example:
614Colls(collateralsFromNewGains, amountsFromNewGains),
Recommendation:
We advise the key-value declaration format to be utilized instead, greatly increasing the legibility of the codebase.
Alleviation:
The referenced declaration of a struct
is no longer present in the codebase, rendering this exhibit no longer applicable.