Understanding The Web

Ethereum Bootcamp: Advanced Concepts

Posted

Mastering Solidity empowers developers with the tools to create advanced smart contracts.  Week 7 of Alchemy University’s Ethereum Bootcamp explores advanced concepts in the Solidity programming language.  Leading up to this week, each week of the bootcamp introduced foundational topics.  Putting it all together, students learn how to create useful smart contracts with more complex ideas.  To introduce the topic of proxy contracts, students learn about smart contract storage.  Understanding storage is essential to understanding proxy contracts.  Following proxy contracts, students learn about upgradable contracts.  The bootcamp lessons are completed with the topics of libraries and governance.  With the information in week 7, students have all the tools to create advanced smart contracts.

Smart Contract Storage

Understanding contract storage is important for multiple reasons.  A strong understanding of storage will produce gas efficient contracts.  Smart contract security auditing requires a strong grasp of smart contract storage.  The underlying functionality of proxy contracts requires knowledge of smart contract storage. It is valuable information that can be applied to a variety of modalities in the blockchain ecosystem.

What is contract storage?

The rules that govern how contract storage variables are laid out in long term memory are referred to as contract storage layout.  Smart contracts will generally have state variables that are stored in long term memory.  As public functions and variables are externally available, so to are state variables.  This external interface of variables is controlled by the Solidity compiler and not the developer. 

How is memory used in the EVM?

In basic terms, a smart contract is a computer program that runs on a blockchain.  Programs consist of functions and the variables that interact with functions.  The data that functions use need to be stored somewhere in a computer’s memory.  In the case of Solidity and Ethereum, the computer is the Ethereum Virtual Machine.

Solidity Memory types

Developers can instruct Solidity where to store variables by declaring one of three keywords: memory, calldata, or storage.  Each of these memory types have rules dictating how long a variable’s memory location will be valid as well as how the variable can be used.

Memory

The memory keyword is used for variables and parameters that are used within a function.  After a function is executed, these variables and parameters no longer exist in memory.  Memory variables only exist during the lifetime of a function. 

Calldata

Calldata is very similar to memory.  Both exist only during the lifetime of a function, and they are not stored on the blockchain. Unlike memory, calldata is limited in size and cannot be modified directly.  Calldata is also read-only. 

Storage

The storage keyword allocates variables and functions into long-term memory.  In other programming environments, long-term storage is generally off loaded to filesystems or databases.  In a blockchain environment, smart contract code and data both persist together long-term. 

What is storage memory?

Each smart contract gets its own storage area which is persistent, and a read-write memory area.  Contracts can only read and write from their own storage.  Storage is broken down into slots which are contiguous and referenced by indexes starting at 0 and ending at 2256.  This gives contracts an immense storage size, and they can be considered virtual.  All slots are initialized to a value of 0.  However, the EVM doesn’t store every single slot.  It only keeps track of which slots are in use and which slots are not.  If an unused slot is accessed, the EVM will know and return 0. 

Understanding storage slots provides developers with a low-level view essential to creating efficient smart contracts and utilizing advanced methods.  The memory keyword is used for temporary variables that are only needed during the execution of the function.  The calldata keyword is used for function arguments that are passed from external callers and they can not be modified.  The storage keyword is used to permanently store data on that blockchain which can be accessed and modified by any function within the contract.  These concepts are fundamental towards understanding proxy contracts.

Proxy Contracts

Delegatecall

Smart contracts live on the blockchain in the form of bytecode.  When an externally owned account (EOA) interacts with a smart contract, it goes through steps such as signing a transaction and sending calldata. When interacting with a contract, a “message context” is created which involves the sender, the value, and storage. 

Often times, an EOA will interact with a contract (Contract A).  This contract will then interact with another contract (Contract B). One way this contract-to-contract communication can be facilitated is through the call keyword.

In the scenario above, the EOA uses calldata with a signed transaction. This is sent to contract A.  At this point, the message sender is the EOA, the value is the same as it was initially at 1.0, and the storage being used is contract A’s.  Then, the call method is used to interact with contact B.  At contract B, the message sender is contract A, the value is 2.0, and the storage in use is contract B’s.

Instead of using the call method, an alternative is delegatecall

When contract A uses delegatecall to interact with contract B, the sender is the EOA throughout the transaction chain.  Unlike the call method, delegatecall uses contract A’s storage when contract B is invoked.  The value sent is the same value throughout the transaction.

The dynamic of delegatecall using the original contract’s storage is an important concept.  The delegatecall method is a common way to utilize proxy contracts. 

What is a proxy contract?

A proxy contract is a contract that delegates calls to another contract.  The proxy contract acts as an intermediary between EOAs and the target contract.  Instead of directly interacting with the target contract, the proxy contract forwards function calls and data to the target contract while also handling the storage. 

Use Cases

Proxy contracts can be used for a variety of reasons.  They can provide an access control layer by restricting certain functions.  Proxy contracts can be used to save on gas by deploying one implementation and delegating to it.  The most common use case is for smart contract upgradability.

Upgrading Contracts

Why upgrade?

Modern technology allows developers to upgrade their applications.  If a bug is found or a desirable new feature is requested, applications can easily be upgraded.  The nature of blockchain technology dictates that smart contracts are immutable.  Once a smart contract is deployed, it is set in stone.  While this is a key feature of the blockchain, developers may desire the ability to upgrade their decentralized applications (dapps).  Proxy contracts allow developers to create smart contracts with a more iterative approach.    

How upgrading smart contracts works

Upgradable smart contracts are a pattern composed of three contracts.

Proxy Contract

The proxy contract is the contract the user interacts with directly.  This contract holds the contract state.  The proxy contract forwards transactions to the implementation contract. 

Implementation Contract

The implementation contract provides the skeleton logic and data.  This contract instantiates variables.  Using delegatecall, the proxy contract gives the implementation contract these values. 

ProxyAdmin Contract

The proxyadmin contract links the proxy contract and the implementation contract.  Alongside the proxy contract, the proxyadmin acts as a manager to the upgrade process.  The proxyadmin contract is responsible for deploying and maintaining the implementation contracts that the proxy contract points to.

Libraries

What are libraries?

Developers will find that code is often reusable, and there is no need to constantly duplicate the code.  Like other programming languages, Solidity supports libraries.  Libraries are reusable pieces of code that can be deployed by multiple contracts.  When a library is deployed on its own, it cannot store storage variables or receive ether.  Libraries are generally pulled into smart contracts by the compiler.   

The snippet above is an example of a pure math library used by Uniswap.  Searching Uniswap’s repository shows several libraries in use.  Using libraries is standard practice in large smart contracts.

How libraries are used

There are two ways to use libraries.

Deployed Inline

The most common use of libraries is when they are deployed inline.  When functions from a library are marked as internal, they are pulled directly into the smart contract.  When the Solidity compiler produces bytecode, the functions from libraries are included in the smart contract bytecode.

Deployed Separately

When deployed separately, the library must be linked with the contract being deployed.  Deploying libraries separately can be useful in reducing the amount of space the smart contract requires.  Separately deployed libraries can also be shared with other contracts.  In order to use a function from a library, an external call must be made. Under the hood, a delegatecall will be made.  This is the same functionality as seen with proxy contracts.

Governance

Governance Standard

The concept of governance is the decentralized implementation of decision making.  As with many other features, governance on the blockchain is moving towards standardization.  Governance implemented by Compound protocol has set the foundation for other protocols.  A governance system can be created with the combination of smart contracts and ERC-20 tokens. The process of governance can take place both on and off chain.     

Off-chain

Off chain governance relies on traditional models.  The decision making occurs off the blockchain.  Off-chain governance is defined by informal discussion and improvement proposals.  However, voting can also occur off-chain.  Snapshots occur to provide voting power based on token balances at certain block heights.  After the snapshot, an off-chain vote takes place giving voting weight to token holders based on the snapshot.

On-chain

On-chain governance is the decision making that takes place on the blockchain. Following the Compound protocol standard, there is a set process for each proposal.  With enough tokens locked, anyone can create a proposal.  A 2-day review period establishes voting weights based on tokens held.  After review, the voting period lasts for 3 days. If the vote passes, there is a 2-day time lock period.  After the timelock period, the proposal can then be implemented.  Regardless of what the proposal is, it will always take at least 7 days to resolve.

Conclusion

The final week of Alchemy University’s Ethereum Bootcamp expands on the previous lessons and explores advanced concepts.  Students learn about proxy contracts which have a variety of applications.  In order to understand proxy contracts, students first learn about smart contract storage.  Smart contract storage is essential to understanding proxy contracts, but it also provides developers with a much clearer image of how smart contracts work in general.  The idea of proxy contracts is followed by upgradable contracts. Upgradable contracts can utilize proxy contracts allowing decentralized applications to break free of their immutable nature.  Next, students learn about the usefulness of libraries.  Libraries give developers access to reusable code. Finally, the bootcamp is completed highlighting the topic of governance.  Governance is an important dynamic that can be an addition to any blockchain project.  Completing Alchemy University’s Ethereum Bootcamp will provide developers with strong smart-contract fundamentals.