Block Magnates

The New Crypto Publication on The Block

Follow publication

EVM: Smart Contract Calls (Part 2)

--

In our EVM article, we mentioned that smart contracts can call each other. This time, we’re focusing on another case: smart contracts can also call functions within the same contract, and we refer to this as an “internal call.” On the other hand, when one smart contract calls another, like Contract A calling Contract B, it’s called an “external call.” In this section, we’ll talk about both internal and external calls, explore the differences, and explain how they work with the EVM.

Internal Call

funcA() might call funcB() within the same smart contract. The modifier can be internal, public, or view, but it can't be external because smart contracts can't call an external function within the same contract. So, for an internal call, it must (1) happen within the same contract, (2) be one function calling another, and (3) the memory and stack stay the same.

External Call

Unlike internal calls, we also have external calls. This happens when one smart contract calls another. In this case, the memory and stack are cleared and reset, and the next contract will fill them. When we talk about external calls, there are three types: (1) call, which is the basic, simple call; (2) staticCall; and (3) delegateCall.

Call

A “call” is the simplest way for one smart contract to call another.

When you call a smart contract, you specify how much ETH you’re sending and what data you’re including. Remember, once the EOA (Externally Owned Account) sends a transaction to your smart contract, it carries some message data. But when you call another contract, the message sender, value, and message data all change.

So, how do they change? In the context of Contract B, the message sender is Contract A, not the EOA that triggered the transaction.

Another important thing to note about a regular call is that when we call another contract, a new EVM instance is created for Contract B. Essentially, we’re jumping from one contract to another, so the node has to initialize a new EVM instance. The response might or might not contain data. At this point, Contract B’s code and storage are changed, and we have a new stack, memory, and program counter, but the remaining gas is still the same.

Once everything is done, the new EVM instance terminates, and the original EVM continues. We then go back to executing Contract A, which means we return to the same storage, stack, memory, and program counter. The machine state changes accordingly. This is basically how a call works with the EVM.

staticCall

Now, staticCall is the next type of call. It’s very similar to a regular call, but with one key requirement: when you use a static call, the function you're calling cannot change its state. That’s why it’s called a static call — it can’t modify anything at all.

delegateCal

This is the type of call that everyone worries about, and they have a good reason. (1) It’s because delegateCall is different from a normal call, and it’s mainly used with smart contract proxies.

The context of the call will be from Contract A. What does this mean? Let’s break it down. Imagine an EOA account wallet triggers funcA() in Contract A and sends 0 ETH. Now, funcA() has a delegateCall opcode that calls funcB() in Contract B. The context here is that the message sender will still be the EOA account, and the value sent will still be 0 ETH, just like the original transaction. Why? Because Contract B is running funcB() within the context of Contract A.

Confusing? Let’s simplify it. The key point is that the code in Contract B doesn’t change the state or storage of Contract B. Instead, Contract B updates the storage and state of Contract A.

So, basically, Contract B is running with Contract A’s context. There will be a new EVM instance with new memory, stack, and program counter, but the difference is the storage will belong to Contract A. This is why delegateCall is usually considered dangerous. If you can control a delegateCall to another contract you control, it can change the storage of Contract A.

The message sender and value stay the same. This can be thought of as a chain of calls: EOA → smart contract → smart contract → delegate call. Finally, once the new EVM instance terminates, we go back to the original execution.

So, these are the basics. We’ll dive deeper into this next time.

Sign up to discover human stories that deepen your understanding of the world.

--

--

No responses yet

Write a response