Skip to content

Unsafe delegatecall detector#

The unsafe-delegatecall detector reports delegatecall calls to possibly untrusted contracts.

Calls are ignored if they the delegatecall target is trusted (e.g. this) or if the call is protected by an onlyOwner modifier or similar logic.

More precisely, access controls based on msg.sender are checked in the detector. Addresses set in a constructor or in functions protected by onlyOwner (or similar) are considered trusted.

Example#

pragma solidity ^0.8.0;

import "@openzeppelin/contracts/interfaces/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";

contract Storage {
    using SafeERC20 for IERC20;

    mapping(address => uint256) public balances;
    address public computationLogic;

    function setComputationLogic(address _computationLogic) external {
        computationLogic = _computationLogic;
    }

    function deposit(IERC20 token, uint256 amount) external {
        token.safeTransferFrom(msg.sender, address(this), amount);
        balances[msg.sender] += amount;
    }

    function recomputeRewards() external {
        computationLogic.delegatecall(
            abi.encodeWithSignature("recomputeRewards()")
        ); // (1)!
    }
}
  1. The delegatecall call is not protected by any access control condition using msg.sender and owner. The computationLogic variable can be set by anyone, making it possible to call arbitrary code that can modify the storage of the Storage contract.

Parameters#

Command-line name TOML name Type Default value Description
--proxy/--no-proxy proxy bool false Whether to report delegatecall calls in proxy contracts.