Skip to content
Last updated: March 11, 2025

SCWE-035: Insecure Delegatecall Usage

Stable Version v0.0.1

This content is in the version-(v0.0.1) and still under active development, so it is subject to change any time (e.g. structure, IDs, content, URLs, etc.).

Send Feedback

Relationships

  • CWE-250: Execution with Unnecessary Privileges
    CWE-250 Link

Description

Insecure delegatecall usage refers to vulnerabilities that arise when using delegatecall to execute code from another contract. This can lead to: - Unauthorized access to sensitive functions. - Exploitation of vulnerabilities in the called contract. - Loss of funds or data.

Remediation

  • Validate targets: Ensure the target contract is trusted and secure.
  • Restrict permissions: Restrict delegatecall usage to trusted addresses.
  • Test thoroughly: Conduct extensive testing to ensure delegatecall is used securely.

Examples

  • Insecure Delegatecall Usage
    pragma solidity ^0.8.0;
    
    contract InsecureDelegatecall {
        function executeDelegatecall(address target, bytes memory data) public {
            (bool success, ) = target.delegatecall(data); // ❌ No validation, attacker-controlled contract can be used
            require(success, "Delegatecall failed");
        }
    }
    
  • Anyone can call executeDelegatecall() with a malicious contract, which will execute arbitrary code within the caller’s context.
  • Can lead to theft of funds, privilege escalation, or state corruption.

  • Secure Delegatecall Usage

    pragma solidity ^0.8.0;
    
    contract SecureDelegatecall {
        address public owner;
        address public trustedTarget;
    
        modifier onlyOwner() {
            require(msg.sender == owner, "Not authorized");
            _;
        }
    
        constructor(address _trustedTarget) {
            owner = msg.sender;
            trustedTarget = _trustedTarget;
        }
    
        function updateTrustedTarget(address _newTarget) public onlyOwner {
            require(isTrusted(_newTarget), "Untrusted target");
            trustedTarget = _newTarget;
        }
    
        function executeDelegatecall(bytes memory data) public onlyOwner {
            require(trustedTarget != address(0), "Invalid target");
            (bool success, ) = trustedTarget.delegatecall(data);
            require(success, "Delegatecall failed");
        }
    
        function isTrusted(address _target) internal pure returns (bool) {
            // Implement further checks if needed
            return _target != address(0);
        }
    }
    

Fixes: - Only the contract owner can update trustedTarget. - Validation of trusted target before executing delegatecall. - Prevents arbitrary execution by restricting calls to trustedTarget.