👮
Contract Cops
  • Mastering Ethereum Book
    • What is ethereum?
    • Tokens
    • Oracles
    • Decenralized Applications(DApps)
    • The Ethereum virtual machine
    • Ethereum basics
    • Ethereum clients
    • Cryptography
    • Wallets
    • Transactions
    • Chapter 7 - Smart Contracts & Solidity
    • Side Notes
      • Tokens
      • Smart Contracts and Solidity
  • Cryptography
    • Ethereum Cryptography - Cheatsheet
    • Assymetric vs symmetric cryptography
    • ECDSA vs RSA
    • Elliptic curves and ECDSA
    • Sha-256 Example
    • Sha-256
    • What are the different steps in SHA-256?
  • Ethereum Blocks
    • Block Headers
  • Learning Solidity
    • Storage vs memory
    • Upgradeable contracts
      • Proxy pattern in smart contracts
  • PoS
    • Proof of stake
  • PoW
    • PoW
  • Tokens
    • ERC-1155
    • ERC20
  • Cryptonomics
    • Automated market makers
    • Collateral Tokens
    • Collateralized Stablecoin
    • Fiat currency
    • Liquidity pool
    • Open Position: Meaning and Risk in Trading
    • Slippage
    • Spot price
  • Common Attack Vectors
    • Checking access control
    • Access control issues on critical functions
    • Account Existence Check for low level calls
    • Account Existence Check
    • Common attacks with contract/EOA addresses
    • Arithmetic under/overflow
    • Assert Attack
    • Assert require revert
    • Assert Violation
    • Bad Interface DOS
    • Bad pragma and compiler
    • Block Timestamp Manipulation
    • Bypassing contract check
    • Code With No Effects
    • Code size check vulnerability
    • Constructors with Care
    • Default Visibilities
    • Delegatecall
    • Delegatecall
    • Denial of Service (DoS)
    • DoS with block gas limit
    • Entropy Illusion
    • External contract referencing
    • Flash Loan Attack
    • Floating Point and Precision
    • Function selector abuse
    • Function selector abuse
    • Smart contract gas griefing
    • Hash collision parameters
    • Hash Collisions With Multiple Variable Length Arguments
    • Imprecise arithmetic
    • Improper Array Deletion
    • Incorrect array deletion
    • Incorrect interface
    • Insufficient Gas Griefing
    • Loop through long arrays
    • Message call with hardcoded gas amount
    • Not enough gas for ether transfer
    • Precision Loss in Calculations
    • Oracle Manipulation
    • Public Burn Function
    • Read-only reentrancy
    • Race Conditions/Front Running
    • Reentrancy Attacks
    • Reentrancy
    • Requirement Violation
    • Right-To-Left-Override control character (U+202E)
    • Shadowing State Variables
    • Short Address / Parameter attack
    • Signature Malleability
    • Signature Replay
    • Transaction Order Dependence
    • Tx.Origin Authentication
    • Unchecked CALL Return Values
    • Unexpected ether
    • Uninitialized Storage Pointers
    • Unsafe Ownership Transfer
  • EIP's
    • EIP155
    • EIP55
  • PoW
    • Ethash
    • Scrypt - RFC 7914
  • Questions for self evaluation
    • Questions 23/04/2023 (Nr: 84)
    • Usability guide for questions
  • Frequently asked questions
    • What is the difference between transaction and message?
    • What is the use of a interface or function without implementation?
  • UsefulResources
Powered by GitBook
On this page
  • To economize on bytecode size in calling contracts
  • To establish standards and ensure compliance
  • To detect developer errors and oversights
  • Why/How?
  1. Frequently asked questions

What is the use of a interface or function without implementation?

PreviousWhat is the difference between transaction and message?NextUsefulResources

Last updated 2 years ago

Let's observe the example below:

And now see the next example, you may wonder: "What is the difference between first and the second code, why we are using interface and is it actually needed?"

So the answer is multi-layered:

  1. To economize on bytecode size in calling contracts.

  2. To establish standards and ensure compliance.

  3. To detect developer errors and oversights.

Let's see them one by one

To economize on bytecode size in calling contracts

Consider contract Client that will interact with Test(from the examples above). One can create an instance of Test in the client, like this:

This will work but Client will have bytecode size of Test size plus Client size because the compiler will roll up the complete Test implementation into Client.

Client doesn't need all of that code. It only needs the interface for the functions it will call.

It can achieve the same result with a smaller bytecode if uses the interface contract instead - Calculator(as the example above).

As an aside, you can cast the input (will still be an address) as the contract Type:

constructor(Calculator calculator) {
    c = calculator;
}

To establish standards and ensure compliance

Many standards are defined as function interfaces and specifications of precise behaviour.

For example, ERC20 is an interface but without particular implementation as long as the functions work a certain way - that can be confirmed with a test suite. It is common to see something like:

contract MyToken is IERC20 {
    ...
}

where IERC20 is the defined interface for an ERC20 contract.

If MyToken is deployable, then that establishes that there is an implementation for each function required for the IERC20 interface. This is related to ...

To detect developer errors and oversights

Inconsistency can creep into intricate systems in the development stage. It can also be cognitively heavy for reviewers to detect inconsistency. Interfaces can function as a sort of error-detection.

Suppose someone decides that

getResult() 

needs an argument, e.g.

getResult(address user) .... 

That's a non-trivial design change that will affect a lot of things. Since

contract Test is Calculator {...}

Test will not deploy unless the interface is updated.

Why/How?

Function signatures are the first 4 bytes of a hash of the function name and arguments, so getResult() and getResult(uint) are completely different functions at the bytecode level.

In practice, that means Test will compile, but it won't deploy because it will not define one of the mandatory functions defined in the inherited interface.

That is exactly what we want because either:

  1. The interface has been redefined, meaning all clients need to adjust

  2. The implementation is incorrect, meaning adding that argument is unacceptable

  3. There is a missing implementation and the one provided is in addition to the mandatory functions, but not a replacement (both are needed).

For style and consistency, it can be a good habit to define interfaces for implementations on a 1:1 basis.

Alt text
Alt text
Alt text
Alt text