Skip to main content
added 89 characters in body
Source Link
BonisTech
  • 672
  • 5
  • 17
/// @use-src 0:"src/Foo.sol"
object "Foo_28" {
    code {
        {
           /// here goes the constructor code
        }
    }
    /// @use-src 0:"src/Foo.sol"
    object "Foo_28_deployed" {
        code {
            {
                // figure out where to which function signature hash to direct the call
                /// @src 0:65:376  "contract Foo {..."
                mstore(64, memoryguard(0x80))
                if iszero(lt(calldatasize(), 4))
                {
                    switch shr(224, calldataload(0))
                    case 0x0714c622 { // function signature of anotherFunction()
                        external_fun_anotherFunction() // call to private function
                    }
                    case 0x35b09a6e { // function signature of someFunction()
                        external_fun_anotherFunction() // call to private function
                    }
                }
                revert(0, 0)
            }
            function external_fun_anotherFunction() // the function privateFunction() 
            {
                if callvalue() { revert(0, 0) }
                if slt(add(calldatasize(), not(3)), 0) { revert(0, 0) }
                let memPos := mload(64)
                mstore(memPos, /** @src 0:158:160  "42" */ 0x2a)
                /// @src 0:65:376  "contract Foo {..."
                return(memPos, 32)
            }
        }
        data // here goes the meta data
    }
}

/// @use-src 0:"src/Foo.sol"
object "Foo_28" {
    code {
        {
           /// here goes the constructor code
        }
    }
    /// @use-src 0:"src/Foo.sol"
    object "Foo_28_deployed" {
        code {
            {
                /// @src 0:65:376  "contract Foo {..."
                mstore(64, memoryguard(0x80))
                if iszero(lt(calldatasize(), 4))
                {
                    switch shr(224, calldataload(0))
                    case 0x0714c622 { // function signature of anotherFunction()
                        external_fun_anotherFunction() // call to private function
                    }
                    case 0x35b09a6e { // function signature of someFunction()
                        external_fun_anotherFunction() // call to private function
                    }
                }
                revert(0, 0)
            }
            function external_fun_anotherFunction() // the function privateFunction() 
            {
                if callvalue() { revert(0, 0) }
                if slt(add(calldatasize(), not(3)), 0) { revert(0, 0) }
                let memPos := mload(64)
                mstore(memPos, /** @src 0:158:160  "42" */ 0x2a)
                /// @src 0:65:376  "contract Foo {..."
                return(memPos, 32)
            }
        }
        data // here goes the meta data
    }
}

/// @use-src 0:"src/Foo.sol"
object "Foo_28" {
    code {
        {
           /// here goes the constructor code
        }
    }
    /// @use-src 0:"src/Foo.sol"
    object "Foo_28_deployed" {
        code {
            {
                // figure out where to which function signature hash to direct the call
                /// @src 0:65:376  "contract Foo {..."
                mstore(64, memoryguard(0x80))
                if iszero(lt(calldatasize(), 4))
                {
                    switch shr(224, calldataload(0))
                    case 0x0714c622 { // function signature of anotherFunction()
                        external_fun_anotherFunction() // call to private function
                    }
                    case 0x35b09a6e { // function signature of someFunction()
                        external_fun_anotherFunction() // call to private function
                    }
                }
                revert(0, 0)
            }
            function external_fun_anotherFunction() // the function privateFunction() 
            {
                if callvalue() { revert(0, 0) }
                if slt(add(calldatasize(), not(3)), 0) { revert(0, 0) }
                let memPos := mload(64)
                mstore(memPos, /** @src 0:158:160  "42" */ 0x2a)
                /// @src 0:65:376  "contract Foo {..."
                return(memPos, 32)
            }
        }
        data // here goes the meta data
    }
}

Bounty Ended with 50 reputation awarded by Ismael
added 298 characters in body
Source Link
BonisTech
  • 672
  • 5
  • 17

tl;dr, to answer your question:

Is there any way at all to call private functions using inline assembly?

Yes, it is possible, but not with the call() instruction.

Long answer + extras:

If you're purely trying to use the call() instruction, this will not work because there is no selector created for private functions as explained by the others. However, it is actually possible to call a private function from within a contract.

If you're purely trying to use the call() instruction, this will not work. However, it is actually possible to call a private function from within a contract.

tl;dr, to answer your question:

Is there any way at all to call private functions using inline assembly?

Yes, it is possible, but not with the call() instruction.

Long answer + extras:

If you're purely trying to use the call() instruction, this will not work because there is no selector created for private functions as explained by the others. However, it is actually possible to call a private function from within a contract.

Source Link
BonisTech
  • 672
  • 5
  • 17

If you're purely trying to use the call() instruction, this will not work. However, it is actually possible to call a private function from within a contract.

Since you're playing around with Yul, what I like to do is write a simple contract in Solidity and compile it using the IR optimizer and look at the output to understand it more. Here's an example:

  1. Write a contract Foo.sol:
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.20;

contract Foo {
    function privateFunction() private pure returns(uint256) {
        return 42;
    }

    function someFunction() external pure returns(uint256) {
        return privateFunction();
    }

    function anotherFunction() external pure returns(uint256) {
        return privateFunction();
    }
}
  1. Compile it using the following command:

solc --optimize --ir-optimized -o out ./Foo.sol --overwrite

  1. Look at the output file in ./out/Foo_opt.sol. The output should look like this:
/// @use-src 0:"src/Foo.sol"
object "Foo_28" {
    code {
        {
           /// here goes the constructor code
        }
    }
    /// @use-src 0:"src/Foo.sol"
    object "Foo_28_deployed" {
        code {
            {
                /// @src 0:65:376  "contract Foo {..."
                mstore(64, memoryguard(0x80))
                if iszero(lt(calldatasize(), 4))
                {
                    switch shr(224, calldataload(0))
                    case 0x0714c622 { // function signature of anotherFunction()
                        external_fun_anotherFunction() // call to private function
                    }
                    case 0x35b09a6e { // function signature of someFunction()
                        external_fun_anotherFunction() // call to private function
                    }
                }
                revert(0, 0)
            }
            function external_fun_anotherFunction() // the function privateFunction() 
            {
                if callvalue() { revert(0, 0) }
                if slt(add(calldatasize(), not(3)), 0) { revert(0, 0) }
                let memPos := mload(64)
                mstore(memPos, /** @src 0:158:160  "42" */ 0x2a)
                /// @src 0:65:376  "contract Foo {..."
                return(memPos, 32)
            }
        }
        data // here goes the meta data
    }
}

Explanation: The compiler writes an internal/private external_fun_anotherFunction function, which is called by the other two functions. You can go through the code line by line, and hopefully learn a bit more :)