code4rena-2023-11-party-dao-h02

[H-02] Single host can unfairly skip veto period for proposal that does not have full host support

보고서

Summary

모든 호스트(관리자)가 동의하면 제안을 거절할 수 있는 대기 기간을 가지지 않고 바로 제안을 실행할 수 있다. 하지만 취약점으로 인해 한 명의 호스트가 호스트 만장일치 상황을 만들어 대기 시간을 우회할 수 있다.

Keyword

51% attack, dao, timelock

Vulnerability

PartyGovernance.abdicateHost 함수는 한 호스트(관리자)가 자신의 호스트 권한을 다른 이에게 넘기거나 삭제하는 함수이다.

    function abdicateHost(address newPartyHost) external {
        _assertHost();
        // 0 is a special case burn address.
        if (newPartyHost != address(0)) {
            // Cannot transfer host status to an existing host.
            if (isHost[newPartyHost]) {
                revert InvalidNewHostError();
            }
@>          isHost[newPartyHost] = true;
        } else {
@>          // Burned the host status
            --numHosts;
        }
        isHost[msg.sender] = false;
        emit HostStatusTransferred(msg.sender, newPartyHost);
    }

abdicateHost 는 제안의 어느 라이프사이클 단계에서든 가능하다. 즉, 호스트가 제안에 투표하여 numHostsAccepted 값을 늘린 후 호스트 권한을 다른 지갑으로 옮겨 호스트 권한으로 다시 투표할 수 있다.

즉, 한 명의 호스트가 호스트 권한을 여러 계정에 돌려가며 투표하면 호스트 만장일치 상황을 만들 수 있다. 호스트 만장일치가 되면 해당 제안은 대기 시간 없이 바로 실행될 수 있다.

function accept(uint256 proposalId, uint256 snapIndex) public returns (uint256 totalVotes) {
    ...
 
@>  if (isHost[msg.sender]) {
@>      ++values.numHostsAccepted;
    }
    info.values = values;

Impact

한 명의 호스트가 호스트 만장일치 상황을 만들어 대기 시간 없이 제안을 바로 실행할 수 있다.

Mitigation

현재 투표권을 처리하는 것과 유사한 방식으로 호스트에 대한 스냅샷을 작성해 사용한다.


tags: bughunting, party dao, smart contract, solidity, dao, 51% attack, timelock, severity high