sherlock-2023-08-cooler-m01

[M-01] emergency_shutdown role is not enough for emergency shutdown

보고서

Summary

emergencyShutdown()의 내부에서 호출되는 함수에는 또다른 권한이 필요하므로 emergency_shutdown 권한만 가진 관리자로는 긴급 중지를 할 수 없다.

Keyword

access control, modifier

Vulnerability

프로토콜에서 관리자 역할로는 emergency_shutdown, cooler_overseer 두 가지가 있다. emergency_shutdown 에게는 Clearinghouse 를 중지할 수 있는 emergencyShutdown()를 호출할 권한이 있다.

하지만 이 권한만으로는 부족하다. emergencyShutdown() 에서는 defund()를 호출하는데, defund()를 호출하기 위해서는 cooler_overseer 권한이 필요하다.

@>  function emergencyShutdown() external onlyRole("emergency_shutdown") {
        active = false;
 
        // If necessary, defund sDAI.
        uint256 sdaiBalance = sdai.balanceOf(address(this));
@>      if (sdaiBalance != 0) defund(sdai, sdaiBalance);
 
        // If necessary, defund DAI.
        uint256 daiBalance = dai.balanceOf(address(this));
@>      if (daiBalance != 0) defund(dai, daiBalance);
 
        emit Deactivated();
    }
 
@>  function defund(ERC20 token_, uint256 amount_) public onlyRole("cooler_overseer") {
        ...
    }

프로토콜 팀에게 질문하여 두 역할은 서로 다른 두 개의 멀티시그에 의해 유지될 것이며, emergency_shutdown 멀티시그는 임계값(threshold)이 낮고 보유자가 더 많다는 것을 확인했다. 따라서 거버넌스는 의도했던 것보다 긴급 상황에 신속하게 대처할 수 없을 것이다.

Impact

emergency_shutdown 역할만으로는 프로토콜을 긴급 중지할 수 없다.

Mitigation

긴급 종료 시 defund를 호출하지 않고 중단 후 별도로 호출하게 변경한다. 또는 defund 함수를 internal 함수로 분리하여 이용한다.


tags: bughunting, olympus dao, smart contract, solidity, lending protocol, access control vulnerability, severity medium