Track 4 · Solidity foundations · lesson 14

Interfaces and external calls

11 min


Everything so far has happened inside one contract. This lesson is where your code starts talking to code you did not write — and where the danger begins.

An interface is a shape, not a contract

interface ICounter {
    function increment() external;
    function count() external view returns (uint256);
}

No bodies, no state, no constructor. It tells the compiler how to encode a call to something at an address that claims to behave this way.

ICounter(someAddress) does not check anything. There is no verification that the address holds a contract, that the contract has those functions, or that they do what the names suggest.

You are asserting a shape. If you are wrong, the call reverts — or worse, silently hits a different function whose selector happens to match.

Driver.solComplete
Loading editor…
Make bumpTwice() call increment() on the counter, twice.
Run the code to see what happens.
Nudge
`counter` is already built and stored. You only have to talk to it.
Show me the approach
An interface variable is called like any object: `counter.increment();`.
Show me the code
Put `counter.increment();` in the body, twice.
Explain the solution
Each of those is a real external call — a separate execution context with its own `msg.sender`, which from Counter's point of view is the Driver contract, not you. That handover is where reentrancy becomes possible, and it is the whole subject of track 7.

What an external call really is

Each counter.increment() is a whole separate execution:

That third point is the important one.

Predict

Your contract sends ETH to an address, then updates its records. The recipient is a contract. What can it do while it has control?

Choose one answer

Assume every external call is hostile

Three habits worth forming now:

  1. Update your state before calling out. Always.
  2. Check return values. A low-level .call() returns false rather than reverting.
  3. Assume the callee can call you back, run out of gas, or revert on purpose to block you.

None of this is paranoia. Every one of these has been used to take real money.

Check

Contract A calls contract B. Inside B, what is `msg.sender`?

Choose one answer

Worth remembering

  • An interface declares a shape; casting an address to it verifies nothing.
  • An external call is a separate execution context, and `msg.sender` becomes the calling contract.
  • Control genuinely leaves your contract — the callee can call you back before you finish.
  • Checks-effects-interactions: validate, update state, then call out.
  • Low-level `.call()` returns false instead of reverting; always check it.