Omniscia vfat Audit

ConnectorRegistry Manual Review Findings

ConnectorRegistry Manual Review Findings

CRY-01M: Potential Failure of Graceful Function

Description:

The ConnectorRegistry::hasConnector function, in contrast to the ConnectorRegistry::connectorOf function, will gracefully handle the absence of a connector by yielding false instead of reverting.

A case exists whereby the function may inadvertently revert instead of yielding false; in case the customRegistries implementation satisfies the ICustomConnectorRegistry::connectorOf function selector but does not yield an argument, the overall transaction will revert due to an uncaught decoding error.

Impact:

The ConnectorRegistry::hasConnector function may ultimately revert even though its implementation approach indicates that it should not.

Example:

contracts/ConnectorRegistry.sol
124function hasConnector(address target) external view returns (bool) {
125 if (connectors_[target] != address(0)) {
126 return true;
127 }
128
129 uint256 length = customRegistries.length;
130 for (uint256 i; i != length;) {
131 if (address(customRegistries[i]) != address(0)) {
132 try customRegistries[i].connectorOf(target) returns (
133 address _connector
134 ) {
135 if (_connector != address(0)) {
136 return true;
137 }
138 } catch {
139 // Ignore
140 }
141
142 unchecked {
143 ++i;
144 }
145 }
146 }
147
148 return false;
149}

Recommendation:

We advise the system to either acknowledge this risk or perform a safer call to the ICustomConnectorRegistry::connectorOf function by evaluating whether the returned payload is 32 bytes in length and thus permits the decoding of the associated address argument.

Alleviation (6ab7af3bb495b817ffec469255ea679b1813eecb):

The code was updated per the latter of our two recommendations, introducing a low-level staticcall whose result is manually handled by evaluating whether the call is successful and the yielded payload is 32 bytes in length. As such, we consider this exhibit fully alleviated.