Skip to content

Latest commit

 

History

History
62 lines (40 loc) · 2.41 KB

L-05.md

File metadata and controls

62 lines (40 loc) · 2.41 KB

Calling _distribute can throw a false positive.

Summary

In the _distribute function, the call to the proxy address can throw a false positive if the proxy is not deployed.

Vulnerability Details

If the bytecode of the proxy address is empty the call to that address will not revert. In the case a contest is expired, the address of the proxy holds tokens and the proxy has never been deployed, the call to the proxy address will not revert, givin the executor the false impression that the distribution process has been completed.

Proof of Concept

The distributionByOwner function is used to distribute tokens to the winner of a contest. The function calls the _distribute function, which calls the proxy address. If the proxy address has never been deployed, the call will not revert. And the executor will assume it has been distributed.

Note: the snippet shows only the relevant code for the test. Full test file can be found here.

    function test_PoC_L05() public {
        bytes32 contestId = keccak256("a contest id");
        uint256 closeTime = block.timestamp + 1 weeks;
        bytes memory data = createData();
        address empty = makeAddr("empty");

        vm.startPrank(owner);
        address implementation = address(new Distributor(address(factory), stadium));

        factory.setContest(organizer, contestId, closeTime, implementation);

        uint256 expiration = closeTime + 1 weeks;

        vm.warp(expiration);

        tokenA.mint(empty, 1000e18);

        //Distribution does not revert.
        factory.distributeByOwner(empty, organizer, contestId, implementation, data);

        // Empty address has 1000e18 tokens.
        assertEq(tokenA.balanceOf(empty), 1000e18);
    }

Impact

Low. The issue can be fixed by using the deployProxyAndDistributeByOwner function.

Tools Used

None.

Recommendations

Verify that the proxy address bytecode is not empty before calling it.

    function _distribute(address proxy, bytes calldata data) internal {
+       if (proxy.code.length == 0) revert ProxyFactory__ProxyNotDeployed();
        (bool success,) = proxy.call(data);
        if (!success) revert ProxyFactory__DelegateCallFailed();
        emit Distributed(proxy, data);
    }