4

When a method in a deployed contract is called (either by an externally controlled account or by another smart contract), what will the program counter be at the beginning of the method call? In other words: Where will code execution start and how does the Ethereum client and the other contracts know where the different methods are located in the EVM?

6

The program counter is always 0 at the beginning of an execution. The contract sets the program counter to match the correct method call through a switch statement (a jump table) at the beginning of the execution of a contract. The CALLDATALOAD (with argument 0x00 (on the stack)) gets the input data for the method call onto the stack. The first input data for a method call is the method signature which is the first four bytes of SHA3(<methodname>(methodArgumentType)).

For a method called "transfer" which takes a uint8 as argument, this would be the first four bytes (big endian, left-most bytes, of SHA3('transfer(uint8)') which is "0x865645aa". The text string of the input to the SHA3 function is encoded as ASCII.

The function signature is compared to the function signature of the available methods in this contract, and control is then given to that method through a conditional jump instruction (JUMPI).

The calling convention for invoking contract methods is defined in the Ethereum Contract ABI. https://github.com/ethereum/wiki/wiki/Ethereum-Contract-ABI

A switch-like statement at the beginning of the contract is how the Solidity compiler gives control to the correct method. If you write your own compiler or your own EVM, the important thing is to follow the ABI Contract definition (if you want it to be easy for other people, programs, and contracts to interact with your code).

2

Illustrating more of @Thorkil's answer.

Example

A very rough example, for conceptual purposes only, of the "switch-like statement at the beginning of the contract".

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
0x11:
code for function with method id 0x25d8dcf2
0x22:
code for another function
0x33:
code for another function

One 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.

Ethereum Contract ABI is a convention outside of the EVM

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. It is very helpful that everyone follows the same ABI, but for example, you can write your own bytecode and tools that could make it difficult for anyone else to call your contract. (But security by obscurity may not offer much since reverse engineering is possible with all data on the blockchain being public.)

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.