sherlock-2025-04-burve-m02
[M-02] Simplex ownership cannot be transferred
Summary
BaseAdminFacet.transferOwnership 함수는 2step 으로 구현되었으므로 BaseAdminFacet.acceptOwnership 함수 역시 다이아몬드 프록시에 등록해야 한다. 하지만 이를 등록하지 않으므로 관리자 변경이 불가하다.
Keyword
proxy, multi-facet proxy, diamond proxy
Vulnerability
BaseAdminFacet.transferOwnership 함수는 2step 으로 구현되었다.
따라서 BaseAdminFacet.acceptOwnership 함수 시그니처도 등록되어야 한다.
function transferOwnership(address _newOwner) external override {
AdminLib.reassignOwner(_newOwner);
}
function reassignOwner(address newOwner) internal {
validateOwner();
@> adminStore().pendingOwner = newOwner;
}하지만 Diamond를 초기화할 때, BaseAdminFacet.acceptOwnership 는 등록되지 않는다.
따라서 관리자를 변경하는 기능은 이 함수를 추가하기 전까지는 동작하지 않는다.
{
bytes4[] memory adminSelectors = new bytes4[](3);
@> adminSelectors[0] = BaseAdminFacet.transferOwnership.selector;
adminSelectors[1] = BaseAdminFacet.owner.selector;
adminSelectors[2] = BaseAdminFacet.adminRights.selector;
cuts[2] = FacetCut({
facetAddress: address(new BaseAdminFacet()),
action: FacetCutAction.Add,
functionSelectors: adminSelectors
});
}Impact
관리자를 변경하는 기능은 BaseAdminFacet.acceptOwnership를 다이아몬드 프록시에 등록하기 전까지는 동작하지 않는다.
Mitigation
다이아몬드 프록시 생성자에서 BaseAdminFacet.acceptOwnership 함수를 등록한다.
{
- bytes4[] memory adminSelectors = new bytes4[](3);
+ bytes4[] memory adminSelectors = new bytes4[](4);
adminSelectors[0] = BaseAdminFacet.transferOwnership.selector;
adminSelectors[1] = BaseAdminFacet.owner.selector;
adminSelectors[2] = BaseAdminFacet.adminRights.selector;
+ adminSelectors[3] = BaseAdminFacet.acceptOwnership.selector;
cuts[2] = FacetCut({
facetAddress: address(new BaseAdminFacet()),
action: FacetCutAction.Add,
functionSelectors: adminSelectors
});
}tags: bughunting, burve, smart contract, solidity, severity medium, proxy pattern, multi-facet proxy