Skip to content

Conversation

sidarth16
Copy link
Contributor

@sidarth16 sidarth16 commented Jul 12, 2025

Summary

This PR introduces a new method is_returning_msg_sender() in the Function class, enabling detection of Solidity functions that return msg.sender, either directly or through variable aliasing.


Motivation

In many smart contract patterns, msg.sender is returned through internal functions, often after assignment to local variables or via wrapper functions like _msgSender(). Detecting such patterns is crucial for accurate static analysis—particularly when assessing function protection or authorization flows.

This utility provides foundational support for enhancing other modules involving msg.sender (in future PRs ).


What’s Covered

The newly added method Function.is_returning_msg_sender() returns True if:

  • The function directly returns msg.sender
  • The function returns a variable that was directly or transitively assigned from msg.sender

Examples:

  • Direct return :
function _msgSender() internal view returns (address) {
    return msg.sender;
}
  • Transitive Aliasing:
function _myMsgSender() internal view returns (address) {
    address a = msg.sender;
    address b = a;
    return b;
}

What's not Covered

  • Returns via internal function calls, even if those functions return msg.sender:
function _getUser() internal view returns (address) {
        return _msgSender();  // _msgSender() returns msg.sender
}

Support for such recursive or wrapper logic will be addressed in a future update.

Closes #2755

@sidarth16 sidarth16 requested a review from smonicas as a code owner July 12, 2025 12:16
@sidarth16
Copy link
Contributor Author

sidarth16 commented Jul 12, 2025

The following Solidity contract was used for local testing of the is_returning_msg_sender() utility:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract TestMsgSender {
    address public owner;

    constructor() {
        owner = msg.sender;
    }

    // ✅ Should be detected
    function directSender() internal view returns (address) {
        return msg.sender;
    }

    // ✅ Should be detected
    function aliasSender() internal view returns (address) {
        address a = msg.sender;
        return a;
    }

    // ✅ Should be detected
    function multiAliasSender() internal view returns (address) {
        address a = msg.sender;
        address b = a;
        address c = b;
        return c;
    }

    // ✅ Should be detected
    function reassignSender() internal view returns (address) {
        address a = msg.sender;
        address b = a;
        a = b;
        return a;
    }

    // ✅ Should be detected
    function _getSender() internal view returns (address) {
        return msg.sender;
    }

    // ❌ Should NOT be detected (msg.sender conversions)
    function conversionSender() internal view returns (address) {
        address a = msg.sender;
        address b = address(uint160(uint256(uint160(a))));
        return b;
    }

    // ❌ Should NOT be detected (nested internal call)
    function returnsViaInternal() internal view returns (address) {
        return _getSender();
    }

    // ❌ Should NOT be detected (returns unrelated var)
    function unrelatedReturn() internal view returns (address) {
        address a = owner;
        return a;
    }

    // ❌ Should NOT be detected (does not return msg.sender)
    function notMsgSender() internal view returns (address) {
        return address(this);
    }

    // ❌ Should NOT be detected (does not return address)
    function notAddress() internal view returns (uint256) {
        address a = msg.sender;
        return 7;
    }
}

Test Code

from slither.slither import Slither

sl = Slither('test_msgsender.sol')
contract = sl.contracts[0]
for func in  contract.functions:
    print(f'{func.canonical_name}    :  {func.is_returning_msg_sender()}' )

Output

TestMsgSender.constructor()       	:  False
TestMsgSender.directSender()       	:  True
TestMsgSender.aliasSender()       	:  True
TestMsgSender.multiAliasSender()       	:  True
TestMsgSender.reassignSender()       	:  True
TestMsgSender._getSender()       	:  True
TestMsgSender.conversionSender()       	:  False
TestMsgSender.returnsViaInternal()     	:  False
TestMsgSender.unrelatedReturn()       	:  False
TestMsgSender.notMsgSender()       	:  False
TestMsgSender.notAddress()       	:  False

@sidarth16 sidarth16 changed the title Add Function module to detect functions returning msg.sender directly or via alias feat: Add Function module to detect functions returning msg.sender directly or via alias Jul 12, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant