Dispatcher is a contract that is intended to be inherited by the Router contract. The Dispatcher's __Dispatcher_init() function should not use the initializer modifier, instead, it should use onlyInitializing modifier.
In the Dispatcher.sol:71 contract, the __Dispatcher_init() function uses the initializer modifier. This is incorrect for an abstract contract like Dispatcher, which is meant to be inherited by other contracts, such as Router.sol.
In this inheritance model, the Router contract also has its own initialize() function, which includes the initializer modifier and calls the __Dispatcher_init() function of the Dispatcher. The problem here is that both the parent contract and the child contract are using the initializer modifier, which limits initialization to only one call.
According to the OpenZeppelin documentation, the onlyInitializing modifier should be used to allow initialization in both the parent and child contracts. The onlyInitializing modifier ensures that when the initialize function is called, any contracts in its inheritance chain can still complete their own initialization. This results in a denial of service (DoS) vulnerability, as the initialization can never be completed successfully.
A modifier that defines a protected initializer function that can be invoked at most once. In its scope, onlyInitializing functions can be used to initialize parent contracts.
Attack Scenario\
Describe how the vulnerability can be exploited.
Contracts have already been deployed and initialized as such. To be noted: Initializer takes into account nested calls and do not revert in such situations.
Github username: @MatinR1 Twitter username: MatinRezaii1 Submission hash (on-chain): 0x1b6aa672fde9499ae6b1e3947dab3f6425dd58800fcbdd5ab97b020425f84adf Severity: high
Description: Description\
Dispatcher is a contract that is intended to be inherited by the Router contract. The Dispatcher's
__Dispatcher_init()
function should not use theinitializer
modifier, instead, it should useonlyInitializing
modifier.In the Dispatcher.sol:71 contract, the
__Dispatcher_init()
function uses theinitializer
modifier. This is incorrect for an abstract contract like Dispatcher, which is meant to be inherited by other contracts, such as Router.sol.In this inheritance model, the Router contract also has its own
initialize()
function, which includes theinitializer
modifier and calls the__Dispatcher_init()
function of the Dispatcher. The problem here is that both the parent contract and the child contract are using theinitializer
modifier, which limits initialization to only one call.According to the OpenZeppelin documentation, the
onlyInitializing
modifier should be used to allow initialization in both the parent and child contracts. TheonlyInitializing
modifier ensures that when the initialize function is called, any contracts in its inheritance chain can still complete their own initialization. This results in a denial of service (DoS) vulnerability, as the initialization can never be completed successfully.For further information, you can check the OpenZeppelin's documents: https://docs.openzeppelin.com/contracts/4.x/api/proxy#Initializable-initializer--
Attack Scenario\ Describe how the vulnerability can be exploited.
Attachments
https://github.com/perspectivefi/core-v2-hats/blob/d245fd66e864670457c3d5652ddc1bcd0e6068eb/src/router/Dispatcher.sol#L71-L82