2

My code

for ( uint256 index = 0; index < 5; index++) {
              string memory name = GetName_v1();
            }

GetName_v1 is a method name and it should be actually a dynamic method name like

GeName_v${index}

Is there a way in solidity to achieve such? Or what is the proper way of doing it?

2

I think that Mikko's way is the only way even if you want to call other methods of the same contract.

pragma solidity ^0.8.4;


contract Test {
    uint value;
    
    function set(uint n) external{
        value = n;
    }
    
    function get() external view returns(uint) {
        return value;
    }
    
    function callByName(string calldata functionSignature, bytes calldata parameters) external returns(bytes memory) {
        (bool success, bytes memory data) = address(this).delegatecall(
            abi.encodeWithSelector(
                bytes4(
                    keccak256(bytes(functionSignature))
                ),
                parameters
            )
        );
        require(success, 'Call failed');
        return data;
    }
}

Here for example you can call get() dynamically calling callByName('get()', '0x') instead. Note that the functionSignature parameter must include the paramters types e.g. for set() it should be set(uint256). Using this method you must provide the parameters encoding and return data decoding.

I used delegatecall since in this case it should be equivalent to call but I have seen that this way it needs slightly less gas.

However this solution isn't great for at least two reasons:

  • All the functions you want to call dynamically must be public or external, you could make a bad work around adding a modifier like this:
modifier isPrivate() {
    require(msg.sender == address(this), 'This method is private');
    _;
}
  • The compiler manages really differently externally callable methods (public/external) from internally callable (private/internal) and if you want to use this "trick" you must declare your methods externally callable. Internally callable methods are managed using the JUMP opcode, indeed my first idea was to write an inline assembly snippet to simply jump but unfortunately this is not possible using YUL. For this reason calling methods in this way will make your contract spend more gas since it needs an additional internal transaction.
1

Yes. You can manually construct calldata which contains the input function selector (4 bytes) and then arguments to the function.

Here is a post that covers the topic.

6
  • Thanks but that is not actually the solution I am looking for. Infact the dynamic methods all exists within the same contract.
    – NinjaMAN
    Jul 15 at 9:02
  • AFAIK you can call your own contract in similar manner. Jul 15 at 9:48
  • But I dont see function name being dynamic there. Because Test is the function name and its static in the code as bytes memory payload = abi.encodeWithSignature("Test(uint, uint)", 12, 35); (bool success, bytes memory returnData) = address(addr).call(payload); require(success);
    – NinjaMAN
    Jul 15 at 10:47
  • You can generate strings dynamically in Solidity. How to do this please read Solidity documentation or open another question, as it is out of scope. Jul 15 at 10:48
  • my intention is not to generate strings dynamically. I already have 10 method names as method1,method2 .... method10. The only dynamic in method name is the integer appended at last i.e method${integer}
    – NinjaMAN
    Jul 15 at 11:01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.