Omniscia Gnosis Guild Audit
Integrity Code Style Findings
Integrity Code Style Findings
IYT-01C: Content Validation Grouping
Type | Severity | Location |
---|---|---|
Gas Optimization | ![]() | Integrity.sol:L153-L169, L177-L189, L205-L233 |
Description:
The referenced if-else-if
clauses can be grouped into a single conditional as they validate multiple operators of the same family (i.e. logical ones, array-based etc.).
Example:
144function _content(145 ConditionFlat memory condition,146 uint256 index147) private pure {148 Operator operator = condition.operator;149 ParameterType paramType = condition.paramType;150 bytes memory compValue = condition.compValue;151 if (operator == Operator.Pass) {152 return;153 } else if (operator == Operator.And) {154 if (paramType != ParameterType.None) {155 revert UnsuitableParameterType(index);156 }157 } else if (operator == Operator.Or) {158 if (paramType != ParameterType.None) {159 revert UnsuitableParameterType(index);160 }161 } else if (operator == Operator.Nor) {162 if (paramType != ParameterType.None) {163 revert UnsuitableParameterType(index);164 }165 } else if (operator == Operator.Xor) {166 if (paramType != ParameterType.None) {167 revert UnsuitableParameterType(index);168 }169 } else if (operator == Operator.Matches) {170 if (171 paramType != ParameterType.Tuple &&172 paramType != ParameterType.Array &&173 paramType != ParameterType.AbiEncoded174 ) {175 revert UnsuitableParameterType(index);176 }177 } else if (operator == Operator.ArraySome) {178 if (paramType != ParameterType.Array) {179 revert UnsuitableParameterType(index);180 }181 } else if (operator == Operator.ArrayEvery) {182 if (paramType != ParameterType.Array) {183 revert UnsuitableParameterType(index);184 }185 } else if (operator == Operator.ArraySubset) {186 if (paramType != ParameterType.Array) {187 revert UnsuitableParameterType(index);188 }189 } else if (operator == Operator.EqualToAvatar) {190 if (paramType != ParameterType.Static) {191 revert UnsuitableParameterType(index);192 }193 } else if (operator == Operator.EqualTo) {194 if (195 paramType != ParameterType.Static &&196 paramType != ParameterType.Dynamic &&197 paramType != ParameterType.Tuple &&198 paramType != ParameterType.Array199 ) {200 revert UnsuitableParameterType(index);201 }202 if (compValue.length % 32 != 0) {203 revert UnsuitableCompValue(index);204 }205 } else if (operator == Operator.GreaterThan) {206 if (paramType != ParameterType.Static) {207 revert UnsuitableParameterType(index);208 }209 if (compValue.length != 32) {210 revert UnsuitableCompValue(index);211 }212 } else if (operator == Operator.LessThan) {213 if (paramType != ParameterType.Static) {214 revert UnsuitableParameterType(index);215 }216 if (compValue.length != 32) {217 revert UnsuitableCompValue(index);218 }219 } else if (operator == Operator.SignedIntGreaterThan) {220 if (paramType != ParameterType.Static) {221 revert UnsuitableParameterType(index);222 }223 if (compValue.length != 32) {224 revert UnsuitableCompValue(index);225 }226 } else if (operator == Operator.SignedIntLessThan) {227 if (paramType != ParameterType.Static) {228 revert UnsuitableParameterType(index);229 }230 if (compValue.length != 32) {231 revert UnsuitableCompValue(index);232 }233 } else if (operator == Operator.Bitmask) {234 if (235 paramType != ParameterType.Static &&236 paramType != ParameterType.Dynamic237 ) {238 revert UnsuitableParameterType(index);239 }240 if (compValue.length != 32) {241 revert MalformedBitmask(index);242 }243 } else if (operator == Operator.Custom) {244 if (245 paramType != ParameterType.Static &&246 paramType != ParameterType.Dynamic &&247 paramType != ParameterType.Tuple &&248 paramType != ParameterType.Array249 ) {250 revert UnsuitableParameterType(index);251 }252 } else if (operator == Operator.WithinAllowance) {253 if (paramType != ParameterType.Static) {254 revert UnsuitableParameterType(index);255 }256 } else if (operator == Operator.EtherWithinAllowance) {257 if (paramType != ParameterType.None) {258 revert UnsuitableParameterType(index);259 }260 } else if (operator == Operator.CallWithinAllowance) {261 if (paramType != ParameterType.None) {262 revert UnsuitableParameterType(index);263 }264 }265}
Recommendation:
We advise them to be grouped into a single conditional, greatly increasing the legibility of the Integrity::_content
function as well as optimizing its execution cost.
Alleviation:
Operator group types are properly grouped in the validation process within Integrity::_node
, optimizing the codebase's bytecode significantly.
IYT-02C: Loop Iterator Optimizations
Type | Severity | Location |
---|---|---|
Gas Optimization | ![]() | Integrity.sol:L35, L62, L68, L84, L102, L119, L278 |
Description:
The linked for
loops increment / decrement their iterator "safely" due to Solidity's built - in safe arithmetics (post-0.8.X
).
Example:
35for (uint256 i = 0; i < conditions.length; ++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 Gnosis Guild team considered this exhibit but has opted not to apply it to avoid broad usage of the unchecked
paradigm. As such, we consider this exhibit acknowledged.
IYT-03C: Redundant Validation of Sub-Type Tree
Type | Severity | Location |
---|---|---|
Gas Optimization | ![]() | Integrity.sol:L95-L96 |
Description:
The Integrity::compatibleSubTypeTree
is invoked unconditionally for logical expressions (i.e. Operator.And
), however, they may contain a single child in certain cases rendering the validation redundant.
Example:
84for (uint256 i = 0; i < conditions.length; i++) {85 ConditionFlat memory condition = conditions[i];86 if (87 (condition.operator >= Operator.And &&88 condition.operator <= Operator.Xor)89 ) {90 // must have no compValue91 if (condition.compValue.length != 0) {92 revert UnsuitableCompValue(i);93 }94
95 // must have at least one child96 if (childrenBounds[i].length == 0) {97 revert UnsuitableChildrenCount(i);98 }99 }100}101
102for (uint256 i = 0; i < conditions.length; i++) {103 ConditionFlat memory condition = conditions[i];104 if (105 (condition.operator >= Operator.And &&106 condition.operator <= Operator.Xor)107 ) {108 compatibleSubTypeTree(conditions, i, childrenBounds);109 }110
111 if (112 (condition.paramType == ParameterType.Array &&113 childrenBounds[i].length > 1)114 ) {115 compatibleSubTypeTree(conditions, i, childrenBounds);116 }117}
Recommendation:
We advise the same childrenBounds
conditional of the Integrity::compatibleSubTypeTree
invocation for Array
parameter types to be assimilated into the referenced if
clause, ensuring that the Integrity::compatibleSubTypeTree
function is invoked optimally.
Alleviation:
The code of Integrity::_topology
(now renamed to Integrity::_tree
) has been refactored to no longer contain this inefficiency, validating childrenBounds
lengths on a need-to basis and thus optimizing the validation process.