0

Can a function call itself...specifically, I am looking at this code and I can't figure out how this could work properly...the parameter vault would be the first parameter in the line that calls updateYield() so I don't see how this could work. I know you can have two functions with the same name but they have to have different parameters.

function updateYield(uint256 vault) external nonReentrant {
        vault.updateYield();
        emit Events.UpdateYield(vault);
    }
2
  • 1
    Can you add the entire contract code and/or a link to the code on a block explorer if possible?
    – Rohan Nero
    Sep 15, 2023 at 2:20
  • seems like you're essentially asking about recursive functions, at least if vault is address(this), can you update your question with a code example?
    – MShakeG
    Sep 16, 2023 at 10:29

2 Answers 2

0

You can create a function that calls itself, the issue is ensuring that you don't get stuck in an endless loop that drains all your gas.

Take these contracts as an example:

Assume we will always pass 1 as the input to the only() function.

contract CallOneself {


    function only(uint x) public {
        if(x < 7) {
            only(x + 1);
        }
        
    }
}

This function call used around 26533 gas.

 function only(uint x) public {
        if(x < 77) {
            only(x + 1);
        }
        
    }

This function call used around 46095 gas.

 function only(uint x) public {
        if(x < 777) {
            only(x + 1);
        }
        
    }

And this function call used up the entire default amount of gas on Remix and then reverted.

2
  • Thank you that makes sense but in this case the function (see below) takes a vault as a parameter (vault is an address) and then calls itself with vault as a parameter. I wonder if the developer intended to call a private function called _yieldUpdate since I know that is a common structure to use. I am pretty new to solidity and I wish I could write better tests but I can't really test it myself yet. Code: function updateYield(uint256 vault) external nonReentrant { vault.updateYield(); emit Events.UpdateYield(vault); } Sep 15, 2023 at 16:55
  • @auditor_chick can you add the entire contract code in your question body? As well as a link to it on a block explorer if possible. Without the entire context it's hard to tell what the developer's intentions were, but you may be correct that the developer intended to call _yieldUpdate() but made a mistake.
    – Rohan Nero
    Sep 15, 2023 at 22:57
0

This concept is called method overriding polymorphism in OOP programming, it is achieved by making more than one function with the same name but with different parameters.

It's used to change the logic of the function when different parameters are passed.

Here is an example of a function that prints a number.

contract PrintNumber {
    event NumberPrint(uint256 number);

    function printNumber() public {
        printNumber(0);
    }

    function printNumber(uint256 number) public {
        emit NumberPrint(number);
    }
}

You can see this approach used by the Openzeppelin contract.

Here is a snipped code of the approve function from the ERC20 contract, which uses polymorphism.

contract ERC20 {
    function _approve(address owner, address spender, uint256 value) internal {
        _approve(owner, spender, value, true);
    }

    function _approve(address owner, address spender, uint256 value, bool emitEvent) internal virtual {
        if (owner == address(0)) {
            revert ERC20InvalidApprover(address(0));
        }
        if (spender == address(0)) {
            revert ERC20InvalidSpender(address(0));
        }
        _allowances[owner][spender] = value;
        if (emitEvent) {
            emit Approval(owner, spender, value);
        }
    }
}
2
  • Hey I have heard of what you are talking about (although I didn't know the name of it before so thank you for that). But in this case the function has the same name and it takes the exact same parameters as well. I'm pretty sure the dev was intending to put _updateYield to call an internal function out of the corresponding library. But I was wondering what would happen if you tried to call a function that just called itself (same parameters). And it sounds like it is a lot more complicated than I thought Sep 18, 2023 at 15:33
  • This is probably the case. When the function calls itself (recursion) it should have a condition to stop executing to not running forever. In solidity, if you made a function calling itself without any stopping conditions it will give an error when firing this function.
    – Al-Qa'qa'
    Sep 19, 2023 at 8:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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