I read the source code of go-ethereum and confused about how does the EVM find the entry of a called function. As the specification said, the data field in a transaction specifies the function and the arguments. So, in my comprehension, the specific function should be executed in the EVM with related input data rather than the whole contract code. However, I can't find the related code. In the execution loop, PC starts from 0:

pc = uint64(0) // program counter
for ; ; instrCount++ {

    // Get the memory location of pc
    op = contract.GetOp(pc)
    // calculate the new memory size and gas price for the current executing opcode
    newMemSize, cost, err = calculateGasAndSize(evm.env, contract, caller, op, statedb, mem, stack)
    if err != nil {
        return nil, err

    // Use the calculated gas. When insufficient gas is present, use all gas and return an
    // Out Of Gas error
    if !contract.UseGas(cost) {
        return nil, OutOfGasError

    // Resize the memory calculated previously
    // Add a log message
    if evm.cfg.Debug {
        evm.logger.captureState(pc, op, contract.Gas, cost, mem, stack, contract, evm.env.Depth(), nil)

    if opPtr := evm.jumpTable[op]; opPtr.valid {
        if opPtr.fn != nil {
            opPtr.fn(instruction{}, &pc, evm.env, contract, mem, stack)
        } else {
            switch op {
            case PC:
                opPc(instruction{data: new(big.Int).SetUint64(pc)}, &pc, evm.env, contract, mem, stack)
            case JUMP:
                if err := jump(pc, stack.pop()); err != nil {
                    return nil, err

            case JUMPI:
                pos, cond := stack.pop(), stack.pop()

                if cond.Cmp(common.BigTrue) >= 0 {
                    if err := jump(pc, pos); err != nil {
                        return nil, err

            case RETURN:
                offset, size := stack.pop(), stack.pop()
                ret := mem.GetPtr(offset.Int64(), size.Int64())

                return ret, nil
            case SUICIDE:
                opSuicide(instruction{}, nil, evm.env, contract, mem, stack)

            case STOP: // Stop the contract
                return nil, nil
    } else {
        return nil, fmt.Errorf("Invalid opcode %x", op)



So how does the EVM execute the specific function?


the specific function should be executed in EVM with related input data rather than the whole contract code

  1. The EVM will execute the contract code. The EVM just executes the bytecode and does not know anything about functions. Solidity, Serpent and web3.js implement the same Application Binary Interface, which is how functions and data are encoded: What is an ABI and why is it needed to interact with contracts?

As noted here, the ABI is an abstraction on top of the Ethereum protocol and the EVM.

  1. An EVM compiler produces contract code that simulates functions according to the ABI. Here's an example.


For functions that adhere to the ABI, it's the job of the compiler to produce correct EVM bytecode.

A very rough example, for conceptual purposes only, of the bytecode that an EVM compiler would produce:

method_id = first 4 bytes of msg.data
if method_id == 0x25d8dcf2 jump to 0x11
if method_id == 0xaabbccdd jump to 0x22
if method_id == 0xffaaccee jump to 0x33
other code <- Solidity fallback function code could be here
code for function with method id 0x25d8dcf2
code for function with method id 0xaabbccdd
code for function with method id 0xffaaccee

You can see that the first 4 bytes of msg.data (Method ID is the term given by the ABI) is used to check which function to jump to and execute.

From the example, you can also see that you can have your own compiler generate bytecode with different logic (maybe you want to use the first 8 bytes of msg.data), but callers would then have to follow those conventions instead of simply using a library like web3.js.

Example is from:

When does the fallback function get called?

How is an ABI stored in bytecode?

| improve this answer | |
  • So EVM just run the bytecodes. for example, i call a contract function func, and the opCalldataLoad function will load the input data and may jump to the related location using the function signature in input data and then finish the evm execution when RETURN opcode be met. – rong jialei Aug 1 '16 at 3:22
  • Yes, that sounds reasonable. – eth Aug 1 '16 at 4:55
  • @eth how about private functions? I can't find any hash for them in the bytecode – Kennet Celeste Nov 21 '19 at 18:35

I'm using the modified example code from Syntax for calling contract state changing methods, saving it in C.sol:

contract C {
    uint[] public numbers;

    function initNumbers() {

    function stateChanger(uint a) {

Following is the compiled binary code in hex format, formatted into 80 character columns. You can see the 3 function signatures within the binary code marked with '<' and '>'.

user@Kumquat:~$ solc --abi --hashes --bin C.sol

======= C =======

Function signatures:
5a7dc897: initNumbers()
65060775: stateChanger(uint256)
d39fa233: numbers(uint256)

Contract JSON ABI

Here's how the function signatures are computed in geth:

> web3.sha3('initNumbers()').substr(0,10)
> web3.sha3('stateChanger(uint256)').substr(0,10)
> web3.sha3('numbers(uint256)').substr(0,10)
| improve this answer | |
  • If i want to detect the balance change in contract, How can i do that. Should a start a new question to ask that? – rong jialei Aug 1 '16 at 3:26
  • Yup. New question is the best way. – The Officious BokkyPooBah Aug 1 '16 at 4:19

As BokkyPooBah points out, the function signature is used to find the place in the bytecode that contains the code for the called method. The Ethereum ABI defines how the arguments are passed. The first four bytes of the provided argument string is the function signature, encoded using Keccak (SHA3). A switch-like statement is used to compare the first four bytes of the provided argument string to the methods available for this contract. If no match is found, the contracts throws an exception (by calling a non-existing opcode) and the method call then fails. If a match is found, the program counter is moved to that method by using the JUMPI opcode.

See also What is the program counter at the start of an Ethereum method execution?

| improve this answer | |

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.