Skip to content

Add Support for Compiling and Deploying First Class Functions #15621

Open
@cre-mer

Description

@cre-mer

Abstract

Solidity currently doesn’t support deploying standalone functions as contracts. While Solidity is object-oriented by design, there are valid use cases for pure, stateless functions that could be deployed directly without the overhead of a full contract or library structure. Examples include cryptographic hash computations, verifier functions, or any single-purpose computational logic.

Motivation

The ability to deploy standalone functions would provide several benefits:

  • Cheaper deployment for single-purpose computational logic
  • Reduced gas costs by eliminating overhead such as function dispatcher and smaller calldata
  • Cleaner abstraction for purely functional operations

This would be particularly useful for:

  • ZK proof verifiers
  • Cryptographic operations
  • Pure computational functions
  • Stateless verification logic

Specification

Standalone functions would have the following characteristics:

  • Cannot have state variables
  • Cannot receive ETH
  • Cannot be destroyed
  • Must be pure or view
  • Can only have one function per deployment
  • Must be external

Compilation would generate bytecode that:

  • Skips function selector matching
  • Directly executes the function logic
  • Validate input parameters
  • Returns output

Additional Considerations

While this is currently semi-possible, using a contract that only includes a fallback function, i.e, skipping the function dispatcher, fallback functions are limited in how they can be declared: fallback () external [payable] or fallback (bytes calldata input) external [payable] returns (bytes memory output). The latter declaration allows us even to add custom input and return custom output, however:

  • This adds overhead for developers, who will have to manually encode the input, which is also an error-prone process
  • The return bytes will have to be manually decoded, too, as well as automatically copied into memory, which could add extra costs.

The proposed solution will allow optionally custom input and output parameters and types.

Example

sample-project
├── verifyProof.sol
└── Verifier.sol

verifyProof.sol

function verifyProof(bytes calldata proof) external pure returns (bool) {
    // verification logic
    return true;
}

Verifier.sol

// import the function from a file
import { verifyProof } from "./verifyProof.sol";

contract Verifier {    
    // @param verifyProof the address of the deployed standalone function
    function isValidProof(verifyProof _verifyProof, bytes memory proof) external view returns(bool) {
        return _verifyProof(proof);
    }
}

This gist has an extended example, including a compiled verifyProof.yul file, showing how the function object could look like.

Backwards Compatibility

This feature would be semi-backward compatible. Calling a standalone function, as shown in the example, would not be possible in Solidity. However, this is feasible using low-level calls.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions