Skip to main content

Solidity - Passing functions as parameters

· 2 min read
Rahul Saxena

Function Types

For official documentations follow this link.

So, in Solidity, you can pass functions themselves as parameters to other functions. These type of parameters are called function types.

These function types can be used to pass and return functions from function calls.

Example

1. Format of function types is the following:

function (<parameter types>) {internal | external} [pure | view | payable] [returns(<return types>)]

Note : Function types can only be internal or external. Also, the return types cannot be empty if the function in question does not return anything, in this case, completely omit the returns keyword.

2. Conversions

function A can be converted to function B if they identical parameter types, identical return types, identical internal/external propery, and state mutability of A is more restrictive than B.

Since view says that no state will be changed whereas pure says no state variable will be changed or read. Therefore, pure is more restrictive than view

Also, rememeber that all non-payable functions are payable (accepting 0 Ether), but no non-payable is payable. Therefore non-payable is more restrictive.

So,

2.1 pure can be converted to view and non-payable

2.2 view can be converted to non-payable

2.3 non-payable can be converted to payable

3. A short mock implementation of this concept


// SPDX-License-Identifier: MIT

pragma solidity ^0.8.11;

contract FunctionParameter {

uint256 public currentSupply = 100;

function increaseSupply(uint256 _newSupply) public returns(uint256) {
uint256 _currentSupply = currentSupply;
_changeSupply(_currentSupply, _newSupply, _add);
return currentSupply;
}

function decreaseSupply(uint256 _decreaseSupplyBy) public returns(uint256) {
uint256 _currentSupply = currentSupply;
_changeSupply(_currentSupply, _decreaseSupplyBy, _sub);
return currentSupply;
}

function fundMe() external payable{}

////////////////////////
// Internal functions
////////////////////////

function _changeSupply(uint256 a, uint256 b, function(uint256, uint256) internal pure returns(uint256) foo) internal returns(uint256) {
currentSupply = foo(a, b);
return currentSupply;
}

function _add(uint256 a, uint256 b) internal pure returns (uint256) {
return (a + b);
}

function _sub(uint256 a, uint256 b) internal pure returns(uint256) {
return (a > b ? (a - b) : 0 );
}
}

Similarly as this was done for internal function calls, you can use this concept for external function calls.

Note: One obvious but important thing to note here is that the internal functions can only be called inside the current contract (including library functions and inherited functions) because they cannot be executed outside of the context of the current contract.