Closed masaun closed 1 year ago
Wontdo: The team made an aware decision to manage most roles globally at the Chief.sol contract level. Both roles can be assigned at a later time by the timelock. The timelock control can be granted to a governance contract in the future.
Title
Lack of validation to check whether or not the
REBALANCER_ROLE
andLIQUIDATOR_ROLE
would be granted before the YieldVault/BorrowingVault is deployed, which results in losing the health of this protocol and decreased-performance of vaults due to failing to rebalance and liquidation.Affected smart contract
Description
Within the CoreRoles,
REBALANCER_ROLE
andLIQUIDATOR_ROLE
are defined like this: https://github.com/Fujicracy/fuji-v2/blob/6231dd1161602cc4b081fd2bab621fa6a3cb9394/packages/protocol/src/access/CoreRoles.sol#L13-L20Then, within the Chief#
constructor()
, some roles would be assigned via the_grantRole()
like this: On the other hands, some roles like such asREBALANCER_ROLE
andLIQUIDATOR_ROLE
would not be granted here. https://github.com/Fujicracy/fuji-v2/blob/6231dd1161602cc4b081fd2bab621fa6a3cb9394/packages/protocol/src/Chief.sol#L119-L122Within the SystemAccessControl, the
hasRole()
modifier would be defined in order to check whether or not specified-address has proper role to call a function like this: https://github.com/Fujicracy/fuji-v2/blob/6231dd1161602cc4b081fd2bab621fa6a3cb9394/packages/protocol/src/access/SystemAccessControl.sol#L27-L32By being checked by the
hasRole(msg.sender, REBALANCER_ROLE)
modifier, both the YieldVault#rebalance()
and the BorrowingVault#rebalance()
can be called by only caller who has aREBALANCER_ROLE
like this: https://github.com/Fujicracy/fuji-v2/blob/6231dd1161602cc4b081fd2bab621fa6a3cb9394/packages/protocol/src/vaults/borrowing/BorrowingVault.sol#L526 https://github.com/Fujicracy/fuji-v2/blob/6231dd1161602cc4b081fd2bab621fa6a3cb9394/packages/protocol/src/vaults/yield/YieldVault.sol#L179Also, by being checked by the
hasRole(msg.sender, LIQUIDATOR_ROLE)
modifier, both the BorrowingVault#liquidate()
can be called by only caller who has aLIQUIDATOR_ROLE
like this: https://github.com/Fujicracy/fuji-v2/blob/6231dd1161602cc4b081fd2bab621fa6a3cb9394/packages/protocol/src/vaults/borrowing/BorrowingVault.sol#L589Based on above, when both vaults (YieldVault and BorrowingVault) would be deployed via the vault factory (YieldVaultFactory and BorrowingVaultFactory), both the
REBALANCER_ROLE
and theLIQUIDATOR_ROLE
must be granted to the proper addresses before the both vaults would be deployed.However, within the
constructor()
of the YieldVault#constructor()
and the BorrowingVault#constructor()
, there is no validation to check whether or not both theREBALANCER_ROLE
and theLIQUIDATOR_ROLE
would be granted to the proper addresses.If the owner forget or miss to grant both roles above to the proper address before both vaults above would be deployed, three functions defined in the both vaults below will always fail unless the owner realize it and grant each roles (
REBALANCER_ROLE
andLIQUIDATOR_ROLE
) to the proper addresses.rebalance()
rebalance()
liquidate()
This lead to a bad situation that
rebalance()
andliquidate()
above that was supposed to be occurred would fail repeatedly unless the owner realize it and grant each roles (REBALANCER_ROLE
andLIQUIDATOR_ROLE
) to the proper addresses. This results in losing the health of this protocol and decreased-performance of vaults due to failing to rebalance and liquidation.Attack scenario
See the "Description" part above.
Recommendation
Consider adding a validation in order to check whether or not both roles (
REBALANCER_ROLE
andLIQUIDATOR_ROLE
) would be granted to the proper addresses to the BorrowingVault#constructor()
like this:Also, consider adding a validation in order to check whether or not the
REBALANCER_ROLE
would be granted to the proper addresses to the YieldVault#constructor()
like this: