Getting Started

Learn Ethereum basics - wallets, transactions, testnets, and your first smart contract


Getting Started

In this chapter we will start exploring Ethereum, learning how to use wallets, how to create transactions, and also how to run a basic smart contract.

Ether Currency Units

Ethereum's currency unit is called ether, identified also as "ETH" or with the symbols Ξ (from the Greek letter "Xi" that looks like a stylized capital E) or, less often, ♦: for example, 1 ether, or 1 ETH, or Ξ1, or ♦1.

Use Unicode character U+039E for Ξ and U+2666 for ♦.

Ether is subdivided into smaller units, down to the smallest unit possible, which is named wei. One ether is 1 quintillion wei (1 × 10¹⁸ or 1,000,000,000,000,000,000). You may hear people refer to the currency "Ethereum" too, but this is a common beginner's mistake. Ethereum is the system, ether is the currency.

The value of ether is always represented internally in Ethereum as an unsigned integer value denominated in wei. When you transact 1 ether, the transaction encodes 1000000000000000000 wei as the value.

Ether's various denominations have both a scientific name using the International System of Units (SI) and a colloquial name that pays homage to many of the great minds of computing and cryptography.

Value (in wei)ExponentCommon nameSI name
110⁰weiWei
1,00010³BabbageKilowei or femtoether
1,000,00010⁶LovelaceMegawei or picoether
1,000,000,00010⁹ShannonGigawei or nanoether
1,000,000,000,00010¹²SzaboMicroether or micro
1,000,000,000,000,00010¹⁵FinneyMilliether or milli
1,000,000,000,000,000,00010¹⁸EtherEther
1,000,000,000,000,000,000,00010²¹GrandKiloether
1,000,000,000,000,000,000,000,00010²⁴Megaether

Choosing an Ethereum Wallet

The term "wallet" has come to mean many things, although they are all related and on a day-to-day basis boil down to pretty much the same thing. We will use the term "wallet" to mean a software application that helps you manage your Ethereum account. In short, an Ethereum wallet is your gateway to the Ethereum system. It holds your keys and can create and broadcast transactions on your behalf. Choosing an Ethereum wallet can be difficult because there are many different options with different features and designs. Some are more suitable for beginners and some are more suitable for experts. The Ethereum platform itself is still being improved, and the "best" wallets are often the ones that adapt to the changes that come with the platform upgrades.

But don't worry! If you choose a wallet and don't like how it works—or if you like it at first but later want to try something else—you can change wallets quite easily. All you have to do is make a transaction that sends your funds from the old wallet to the new wallet, or export your private keys and import them into the new one.

We've selected three different types of wallets to use as examples throughout the book: a mobile wallet, a desktop wallet, and a web-based wallet. We've chosen these three wallets because they represent a broad range of complexity and features. However, the selection of these wallets is not an endorsement of their quality or security. They are simply a good starting place for demonstrations and testing.

Remember that for a wallet application to work, it must have access to your private keys, so it is vital that you only download and use wallet applications from sources you trust. Fortunately, in general, the more popular a wallet application is, the more trustworthy it is likely to be. Nevertheless, it is good practice to avoid "putting all your eggs in one basket" and have your Ethereum accounts spread across a couple of wallets.

The following are some good starter wallets:

MetaMask — MetaMask is a browser extension wallet that runs in your browser (Chrome, Firefox, Opera, or Brave Browser). It is easy to use and convenient for testing, as it is able to connect to a variety of Ethereum nodes and test blockchains. MetaMask is a web-based wallet.

Jaxx — Jaxx is a multiplatform and multicurrency wallet that runs on a variety of operating systems, including Android, iOS, Windows, macOS, and Linux. It is often a good choice for new users as it is designed for simplicity and ease of use. Jaxx is either a mobile or a desktop wallet, depending on where you install it.

MyEtherWallet (MEW) — MyEtherWallet is a web-based wallet that runs in any browser. It has multiple sophisticated features we will explore in many of our examples. MyEtherWallet is a web-based wallet.

Emerald Wallet — Emerald Wallet is designed to work with the Ethereum Classic blockchain, but is compatible with other Ethereum-based blockchains. It's an open source desktop application and works under Windows, macOS, and Linux. Emerald Wallet can run a full node or connect to a public remote node, working in a "light" mode. It also has a companion tool to do all operations from the command line.

We'll start by installing MetaMask on a desktop—but first, we'll briefly discuss controlling and managing keys.

Control and Responsibility

Open blockchains like Ethereum are important because they operate as a decentralized system. That means lots of things, but one crucial aspect is that each user of Ethereum can—and should—control their own private keys, which are the things that control access to funds and smart contracts. We sometimes call the combination of access to funds and smart contracts an "account" or "wallet." These terms can get quite complex in their functionality, so we will go into this in more detail later. As a fundamental principle, however, it is as easy as one private key equals one "account." Some users choose to give up control over their private keys by using a third-party custodian, such as an online exchange. In this book, we will teach you how to take control and manage your own private keys.

With control comes a big responsibility. If you lose your private keys, you lose access to your funds and contracts. No one can help you regain access—your funds will be locked forever. Here are a few tips to help you manage this responsibility:

  • Do not improvise security. Use tried-and-tested standard approaches.

  • The more important the account (e.g., the higher the value of the funds controlled, or the more significant the smart contracts accessible), the higher security measures should be taken.

  • The highest security is gained from an air-gapped device, but this level is not required for every account.

  • Never store your private key in plain form, especially digitally. Fortunately, most user interfaces today won't even let you see the raw private key.

  • Private keys can be stored in an encrypted form, as a digital "keystore" file. Being encrypted, they need a password to unlock. When you are prompted to choose a password, make it strong (i.e., long and random), back it up, and don't share it. If you don't have a password manager, write it down and store it in a safe and secret place. To access your account, you need both the keystore file and the password.

  • Do not store any passwords in digital documents, digital photos, screenshots, online drives, encrypted PDFs, etc. Again, do not improvise security. Use a password manager or pen and paper.

  • When you are prompted to back up a key as a mnemonic word sequence, use pen and paper to make a physical backup. Do not leave that task "for later"; you will forget. These backups can be used to rebuild your private key in case you lose all the data saved on your system, or if you forget or lose your password. However, they can also be used by attackers to get your private keys, so never store them digitally, and keep the physical copy stored securely in a locked drawer or safe.

  • Before transferring any large amounts (especially to new addresses), first do a small test transaction (e.g., less than $1 value) and wait for confirmation of receipt.

  • When you create a new account, start by sending only a small test transaction to the new address. Once you receive the test transaction, try sending back again from that account. There are lots of reasons account creation can go wrong, and if it has gone wrong, it is better to find out with a small loss. If the tests work, all is well.

  • Public block explorers are an easy way to independently see whether a transaction has been accepted by the network. However, this convenience has a negative impact on your privacy, because you reveal your addresses to block explorers, which can track you.

  • Do not send money to any of the addresses shown in this book. The private keys are listed in the book and someone will immediately take that money.

Now that we've covered some basic best practices for key management and security, let's get to work using MetaMask!

Getting Started with MetaMask

Open the Google Chrome browser and navigate to the Chrome Web Store extensions page.

Search for "MetaMask" and click on the logo of a fox. You should see the detail page of the MetaMask Chrome extension.

It's important to verify that you are downloading the real MetaMask extension, as sometimes people are able to sneak malicious extensions past Google's filters. The real one:

  • Shows the ID nkbihfbeogaeaoehlefnkodbefgpgknn in the address bar
  • Is offered by https://metamask.io
  • Has more than 1,500 reviews
  • Has more than 1,000,000 users

Once you confirm you are looking at the correct extension, click "Add to Chrome" to install it.

Creating a Wallet

Once MetaMask is installed you should see a new icon (the head of a fox) in your browser's toolbar. Click on it to get started. You will be asked to accept the terms and conditions and then to create your new Ethereum wallet by entering a password.

The password controls access to MetaMask, so that it can't be used by anyone with access to your browser.

Once you've set a password, MetaMask will generate a wallet for you and show you a mnemonic backup consisting of 12 English words. These words can be used in any compatible wallet to recover access to your funds should something happen to MetaMask or your computer. You do not need the password for this recovery; the 12 words are sufficient.

Back up your mnemonic (12 words) on paper, twice. Store the two paper backups in two separate secure locations, such as a fire-resistant safe, a locked drawer, or a safe deposit box. Treat the paper backups like cash of equivalent value to what you store in your Ethereum wallet. Anyone with access to these words can gain access and steal your money.

Once you have confirmed that you have stored the mnemonic securely, you'll be able to see the details of your Ethereum account.

Your account page shows the name of your account ("Account 1" by default), an Ethereum address (0x9E713... in the example), and a colorful icon to help you visually distinguish this account from other accounts. At the top of the account page, you can see which Ethereum network you are currently working on ("Main Network" in the example).

Congratulations! You have set up your first Ethereum wallet.

Switching Networks

As you can see on the MetaMask account page, you can choose between multiple Ethereum networks. By default, MetaMask will try to connect to the main network. The other choices are public testnets, any Ethereum node of your choice, or nodes running private blockchains on your own computer (localhost):

Ethereum Mainnet — The main public Ethereum (PoS) blockchain. Real ETH, real value, and real consequences.

Ethereum Classic Mainnet — The main public Ethereum Classic (PoW) blockchain. Real ETC, real value, and real consequences. You may need to add this network manually (chainId: 61).

Sepolia Test Network — Ethereum (PoS) public test blockchain. ETH on this network has no value. This is the recommended testnet for Ethereum development.

Mordor Test Network — Ethereum Classic (PoW) public test blockchain. METC on this network has no value. This is the recommended testnet for Ethereum Classic development. You'll need to add this network manually (chainId: 63, RPC: https://rpc.mordor.etccooperative.org).

Localhost 8545 — Connects to a node running on the same computer as the browser. The node can be part of any public blockchain (main or testnet), or a private testnet.

Custom RPC — Allows you to connect MetaMask to any node with a Geth-compatible Remote Procedure Call (RPC) interface. The node can be part of any public or private blockchain, including Ethereum Classic networks.

Your MetaMask wallet uses the same private key and Ethereum address on all the networks it connects to. However, your balance on each network will be different. Your keys may control ether and contracts on Sepolia, for example, but not on the main network. The same applies across chains — your ETC balance is separate from your ETH balance, even though the address is identical. To add Ethereum Classic networks to MetaMask, go to Settings → Networks → Add Network and enter:

ETC Mainnet: chainId: 61, RPC: https://etc.rivet.link

Mordor Testnet: chainId: 63, RPC: https://rpc.mordor.etccooperative.org

Getting Some Test Ether

Your first task is to get your wallet funded. You won't be doing that on the main network because real ether costs money and handling it requires a bit more experience. For now, you'll load your wallet with some testnet ether.

You have two main options for testnets:

Option A: Sepolia (Ethereum PoS) — Switch MetaMask to the Sepolia Test Network. Visit the Sepolia faucet at https://sepoliafaucet.com or https://faucet.sepolia.dev to request test ETH. Most faucets require you to paste your wallet address and may have rate limits.

Option B: Mordor (Ethereum Classic PoW) — Add the Mordor network to MetaMask (chainId: 63, RPC: https://rpc.mordor.etccooperative.org). You can either use a faucet at https://faucet.mordortest.net or, for a more educational experience, run a Core Geth node and mine your own METC (see the chapter on Running Ethereum Clients).

For this example, we'll use Sepolia. Switch MetaMask to the Sepolia Test Network and visit a Sepolia faucet. Paste your wallet address and request test ether.

**Why two testnets?** Sepolia runs on Proof of Stake (like Ethereum mainnet), while Mordor runs on Proof of Work (like Ethereum Classic mainnet). Using both helps you understand the differences between the two consensus mechanisms. The smart contracts you write work identically on both!

In a few seconds to minutes (depending on the testnet), your MetaMask wallet will show a balance. Click on the transaction in MetaMask to view it in a block explorer, which is a website that allows you to visualize and explore blocks, addresses, and transactions.

For Sepolia, use https://sepolia.etherscan.io. For Mordor, use https://etc-mordor.blockscout.com.

The transaction has been recorded on the testnet blockchain and can be viewed at any time by anyone, simply by searching for the transaction ID.

Sending Ether from MetaMask

Once you've received your first test ether from a faucet, you can experiment with sending ether. Many faucets allow you to donate test ether back so others can use it. Even though test ether has no value, some people hoard it, making it difficult for everyone else to use the test networks. Hoarding test ether is frowned upon!

Let's send some test ether. In MetaMask, click "Send" and enter a recipient address — you can use a faucet donation address, or create a second account in MetaMask to practice sending to yourself. Enter an amount (e.g., 0.1 ETH) and MetaMask will prepare a transaction and pop up a window with the confirmation.

Oops! You probably noticed you can't complete the transaction—MetaMask says you have an insufficient balance. At first glance this may seem confusing: you have 1 ETH, you want to send 1 ETH, so why is MetaMask saying you have insufficient funds?

The answer is because of the cost of gas. Every EVM transaction requires payment of a fee, which is collected by block producers (miners on PoW chains like Ethereum Classic, validators on PoS chains like Ethereum) to validate the transaction. The fees are charged in a virtual currency called gas. You pay for the gas with ether, as part of the transaction.

Fees are required on the test networks too. Without fees, a test network would behave differently from the main network, making it an inadequate testing platform. Fees also protect the test networks from DoS attacks and poorly constructed contracts (e.g., infinite loops), much like they protect the main network.

When you create a transaction, MetaMask calculates the gas price based on recent network activity. The unit "gwei" stands for gigawei — wei is the smallest subdivision of ether, as we discussed earlier. The gas limit for a basic ether transfer is 21,000 gas units. Therefore, the total fee you'll pay is gas price × gas limit. For example, at 3 gwei: 3 × 21,000 gwei = 63,000 gwei = 0.000063 ETH.

Gas prices vary by network. Ethereum Classic typically has lower gas prices than Ethereum mainnet due to less network congestion. Testnets like Mordor and Sepolia have very low gas prices since test ether has no value.

If you try to send your entire balance, MetaMask will warn you about insufficient funds because you need to reserve some for gas. Reduce the amount slightly to leave room for fees, then click Confirm to submit the transaction. After confirmation, you'll see your updated balance reflecting both the sent amount and the gas fee.

Exploring the Transaction History of an Address

By now you have become an expert in using MetaMask to send and receive test ether. Your wallet has received at least one payment and possibly sent one as well. You can view all these transactions using a block explorer — use https://sepolia.etherscan.io for Sepolia or https://etc-mordor.blockscout.com for Mordor. You can either copy your wallet address and paste it into the block explorer's search box, or have MetaMask open the page for you. Next to your account icon in MetaMask, you will see a button showing three dots. Click on it to show a menu of account-related options.

Select "View account on Etherscan" to open a web page in the block explorer showing your account's transaction history.

Here you can see the entire transaction history of your Ethereum address. It shows all the transactions recorded on the testnet blockchain where your address is the sender or recipient. Click on a few of these transactions to see more details.

You can explore the transaction history of any address. Take a look at the transaction history of a faucet address (hint: it is the "sender" address listed in your oldest incoming payment). You can see all the test ether sent from the faucet to you and to other addresses. Every transaction you see can lead you to more addresses and more transactions. Before long you will be lost in the maze of interconnected data. Public blockchains contain an enormous wealth of information, all of which can be explored programmatically, as we will see in future examples.

Try the same exercise on both Sepolia (Etherscan) and Mordor (Blockscout). Notice how the block explorers look similar because they're displaying the same underlying EVM data structures — addresses, transactions, blocks, and contracts work the same way on both chains.

Introducing the World Computer

You've now created a wallet and sent and received ether. So far, we've treated Ethereum as a cryptocurrency. But Ethereum is much, much more. In fact, the cryptocurrency function is subservient to Ethereum's function as a decentralized world computer. Ether is meant to be used to pay for running smart contracts, which are computer programs that run on an emulated computer called the Ethereum Virtual Machine (EVM).

The EVM is a global singleton, meaning that it operates as if it were a global, single-instance computer, running everywhere. Each node on the Ethereum network runs a local copy of the EVM to validate contract execution, while the Ethereum blockchain records the changing state of this world computer as it processes transactions and smart contracts. We'll discuss this in much greater detail in the chapter on the EVM.

Externally Owned Accounts (EOAs) and Contracts

The type of account you created in the MetaMask wallet is called an externally owned account (EOA). Externally owned accounts are those that have a private key; having the private key means control over access to funds or contracts. Now, you're probably guessing there is another type of account. That other type of account is a contract account. A contract account has smart contract code, which a simple EOA can't have. Furthermore, a contract account does not have a private key. Instead, it is owned (and controlled) by the logic of its smart contract code: the software program recorded on the Ethereum blockchain at the contract account's creation and executed by the EVM.

Contracts have addresses, just like EOAs. Contracts can also send and receive ether, just like EOAs. However, when a transaction destination is a contract address, it causes that contract to run in the EVM, using the transaction, and the transaction's data, as its input. In addition to ether, transactions can contain data indicating which specific function in the contract to run and what parameters to pass to that function. In this way, transactions can call functions within contracts.

Note that because a contract account does not have a private key, it cannot initiate a transaction. Only EOAs can initiate transactions, but contracts can react to transactions by calling other contracts, building complex execution paths. One typical use of this is an EOA sending a request transaction to a multisignature smart contract wallet to send some ETH on to another address. A typical DApp programming pattern is to have Contract A calling Contract B in order to maintain a shared state across users of Contract A.

In the next few sections, we will write our first contract. You will then learn how to create, fund, and use that contract with your MetaMask wallet and test ether on a testnet. The examples work identically on Sepolia (Ethereum) or Mordor (Ethereum Classic) — the EVM doesn't care which chain you're using!

A Simple Contract: A Test Ether Faucet

Ethereum has many different high-level languages, all of which can be used to write a contract and produce EVM bytecode. You can read about many of the most prominent and interesting ones in the chapter on High-Level Languages. One high-level language is by far the dominant choice for smart contract programming: Solidity. Solidity was created by Dr. Gavin Wood, and has become the most widely used language in Ethereum (and beyond). We'll use Solidity to write our first contract.

For our first example, we will write a contract that controls a faucet. You've already used a faucet to get test ether on a test network. A faucet is a relatively simple thing: it gives out ether to any address that asks, and can be refilled periodically. You can implement a faucet as a wallet controlled by a human or a web server.

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
 
// Our first contract is a faucet!
contract Faucet {
    // Give out ether to anyone who asks
    function withdraw(uint withdraw_amount) public {
        // Limit withdrawal amount
        require(withdraw_amount <= 100000000000000000);
 
        // Send the amount to the address that requested it
        payable(msg.sender).transfer(withdraw_amount);
    }
 
    // Accept any incoming amount
    receive() external payable {}
}
You will find all the code samples for this book in the code repository. We'll be using Solidity 0.8.x throughout this book, which includes important safety features like built-in overflow checking.

This is a very simple contract, about as simple as we can make it. It is also a flawed contract, demonstrating a number of bad practices and security vulnerabilities. We will learn by examining all of its flaws in later sections. But for now, let's look at what this contract does and how it works, line by line. You will quickly notice that many elements of Solidity are similar to existing programming languages, such as JavaScript, Java, or C++.

The first line is a comment:

// Our first contract is a faucet!

Comments are for humans to read and are not included in the executable EVM bytecode. We usually put them on the line before the code we are trying to explain, or sometimes on the same line. Comments start with two forward slashes: //. Everything from the first slash until the end of that line is treated the same as a blank line and ignored.

The next line is where our actual contract starts:

contract Faucet {

This line declares a contract object, similar to a class declaration in other object-oriented languages. The contract definition includes all the lines between the curly braces ({}), which define a scope, much like how curly braces are used in many other programming languages.

Next, we declare the first function of the Faucet contract:

function withdraw(uint withdraw_amount) public {

The function is named withdraw, and it takes one unsigned integer (uint) argument named withdraw_amount. It is declared as a public function, meaning it can be called by other contracts. The function definition follows, between curly braces. The first part of the withdraw function sets a limit on withdrawals:

require(withdraw_amount <= 100000000000000000);

It uses the built-in Solidity function require to test a precondition, that the withdraw_amount is less than or equal to 100,000,000,000,000,000 wei, which is the base unit of ether (see the denominations table earlier) and equivalent to 0.1 ether. If the withdraw function is called with a withdraw_amount greater than that amount, the require function here will cause contract execution to stop and fail with an exception. Note that statements need to be terminated with a semicolon in Solidity.

This part of the contract is the main logic of our faucet. It controls the flow of funds out of the contract by placing a limit on withdrawals. It's a very simple control but can give you a glimpse of the power of a programmable blockchain: decentralized software controlling money.

Next comes the actual withdrawal:

payable(msg.sender).transfer(withdraw_amount);

A couple of interesting things are happening here. The msg object is one of the inputs that all contracts can access. It represents the transaction that triggered the execution of this contract. The attribute sender is the sender address of the transaction. The function transfer is a built-in function that transfers ether from the current contract to the address of the sender. Reading it backward, this means transfer to the sender of the msg that triggered this contract execution. The transfer function takes an amount as its only argument. We pass the withdraw_amount value that was the parameter to the withdraw function declared a few lines earlier.

The very next line is the closing curly brace, indicating the end of the definition of our withdraw function.

Next, we declare one more function:

receive() external payable {}

The receive function is called if the transaction that triggered the contract didn't name any of the declared functions in the contract, or didn't contain data and thus was a plain Ether transfer. Contracts can have one such receive function (without a name) and it is used to receive ether. That's why it is defined as an external and payable function, which means it can accept ether into the contract. It doesn't do anything, other than accept the ether, as indicated by the empty definition in the curly braces ({}). If we make a transaction that sends ether to the contract address, as if it were a wallet, this function will handle it.

Right below our default function is the final closing curly brace, which closes the definition of the contract Faucet. That's it!

Compiling the Faucet Contract

Now that we have our first example contract, we need to use a Solidity compiler to convert the Solidity code into EVM bytecode so it can be executed by the EVM on the blockchain itself.

The Solidity compiler comes as a standalone executable, as part of various frameworks, and bundled in Integrated Development Environments (IDEs). To keep things simple, we will use one of the more popular IDEs, called Remix.

Use your Chrome browser (with the MetaMask wallet you installed earlier) to navigate to the Remix IDE at https://remix.ethereum.org.

When you first load Remix, it will start with a sample contract called ballot.sol. We don't need that, so close it by clicking the x on the corner of the tab.

Now, add a new tab by clicking on the circular plus sign in the top-left toolbar. Name the new file Faucet.sol.

Once you have the new tab open, copy and paste the code from our example Faucet.sol.

Once you have loaded the Faucet.sol contract into the Remix IDE, the IDE will automatically compile the code. If all goes well, you will see a green box with "Faucet" in it appear on the right, under the Compile tab, confirming the successful compilation.

If something goes wrong, the most likely problem is that the Remix IDE is using a version of the Solidity compiler that is different from 0.8. In that case, our pragma directive will prevent Faucet.sol from compiling. To change the compiler version, go to the Settings tab, set the version to 0.8.x, and try again.

The Solidity compiler has now compiled our Faucet.sol into EVM bytecode. If you are curious, the bytecode is a series of opcodes like PUSH, MSTORE, CALLDATASIZE, and so on. Aren't you glad you are using a high-level language like Solidity instead of programming directly in EVM bytecode? Me too!

Creating the Contract on the Blockchain

So, we have a contract. We've compiled it into bytecode. Now, we need to "register" the contract on the blockchain. We will be using a testnet to test our contract — either Sepolia (Ethereum) or Mordor (Ethereum Classic). The deployment process is identical on both.

Registering a contract on the blockchain involves creating a special transaction whose destination is the address 0x0000000000000000000000000000000000000000, also known as the zero address. The zero address is a special address that tells the Ethereum blockchain that you want to register a contract. Fortunately, the Remix IDE will handle all of that for you and send the transaction to MetaMask.

First, switch to the Run tab and select Injected Provider - MetaMask in the Environment drop-down selection box. This connects the Remix IDE to your MetaMask wallet, and through MetaMask to whichever network you have selected (Sepolia, Mordor, etc.). Once you do that, you can see the network name under Environment. Also, in the Account selection box it shows the address of your wallet.

Right below the Run settings you just confirmed is the Faucet contract, ready to be created. Click on the Deploy button.

Remix will construct the special "creation" transaction and MetaMask will ask you to approve it. You'll notice the contract creation transaction has no ether in it, but it has data (the compiled contract bytecode) and will consume gas. Click Submit to approve it.

Now you have to wait. It will take a few seconds to a minute for the contract to be included in a block. On Mordor (PoW), the contract is "mined" into a block. On Sepolia (PoS), the contract is "validated" into a block. Either way, the result is the same — your contract is now on the blockchain! Remix won't appear to be doing much, but be patient.

Once the contract is created, it appears at the bottom of the Run tab.

Notice that the Faucet contract now has an address of its own: Remix shows it as "Faucet at 0x72e...c7829" (although your address, the random letters and numbers, will be different). The small clipboard symbol to the right allows you to copy the contract address to your clipboard. We will use that in the next section.

Interacting with the Contract

Let's recap what we've learned so far: Ethereum contracts are programs that control money, which run inside a virtual machine called the EVM. They are created by a special transaction that submits their bytecode to be recorded on the blockchain. Once they are created on the blockchain, they have an Ethereum address, just like wallets. Anytime someone sends a transaction to a contract address it causes the contract to run in the EVM, with the transaction as its input. Transactions sent to contract addresses may have ether or data or both. If they contain ether, it is "deposited" to the contract balance. If they contain data, the data can specify a named function in the contract and call it, passing arguments to the function.

Viewing the Contract Address in a Block Explorer

We now have a contract recorded on the blockchain, and we can see it has an Ethereum address. Let's check it out in a block explorer and see what a contract looks like. In the Remix IDE, copy the address of the contract by clicking the clipboard icon next to its name.

Keep Remix open; we'll come back to it again later. Now, navigate your browser to the appropriate block explorer — https://sepolia.etherscan.io for Sepolia or https://etc-mordor.blockscout.com for Mordor — and paste the address into the search box. You should see the contract's address history.

Funding the Contract

For now, the contract only has one transaction in its history: the contract creation transaction. As you can see, the contract also has no ether (zero balance). That's because we didn't send any ether to the contract in the creation transaction, even though we could have.

Our faucet needs funds! Our first project will be to use MetaMask to send ether to the contract. You should still have the address of the contract in your clipboard (if not, copy it again from Remix). Open MetaMask, and send 1 ether to it, exactly as you would to any other Ethereum address.

In a minute, if you reload the block explorer, it will show another transaction to the contract address and an updated balance of 1 ether (or 1 METC if you're on Mordor).

Remember the unnamed default external payable function in our Faucet.sol code? It looked like this:

receive() external payable {}

When you sent a transaction to the contract address, with no data specifying which function to call, it called this default function. Because we declared it as payable, it accepted and deposited the 1 ether into the contract's account balance. Your transaction caused the contract to run in the EVM, updating its balance. You have funded your faucet!

Withdrawing from Our Contract

Next, let's withdraw some funds from the faucet. To withdraw, we have to construct a transaction that calls the withdraw function and passes a withdraw_amount argument to it. To keep things simple for now, Remix will construct that transaction for us and MetaMask will present it for our approval.

Return to the Remix tab and look at the contract on the Run tab. You should see an orange box labeled withdraw with a field entry labeled uint256 withdraw_amount.

This is the Remix interface to the contract. It allows us to construct transactions that call the functions defined in the contract. We will enter a withdraw_amount and click the withdraw button to generate the transaction.

First, let's figure out the withdraw_amount. We want to try and withdraw 0.1 ether, which is the maximum amount allowed by our contract. Remember that all currency values in Ethereum are denominated in wei internally, and our withdraw function expects the withdraw_amount to be denominated in wei too. The amount we want is 0.1 ether, which is 100,000,000,000,000,000 wei (a 1 followed by 17 zeros).

Due to a limitation in JavaScript, a number as large as 10¹⁷ cannot be processed by Remix. Instead, we enclose it in double quotes, to allow Remix to receive it as a string and manipulate it as a BigNumber. If we don't enclose it in quotes, the Remix IDE will fail to process it and display "Error encoding arguments: Error: Assertion failed."

Type "100000000000000000" (with the quotes) into the withdraw_amount box and click on the withdraw button.

MetaMask will pop up a transaction window for you to approve. Click Confirm to send your withdrawal call to the contract.

Wait a minute and then reload the block explorer to see the transaction reflected in the Faucet contract address history.

We now see a new transaction with the contract address as the destination and a value of 0 ether. The contract balance has changed and is now 0.9 ether because it sent us 0.1 ether as requested. But we don't see an "OUT" transaction in the contract address history.

Where's the outgoing withdrawal? A new tab has appeared on the contract's address history page, named Internal Transactions. Because the 0.1 ether transfer originated from the contract code, it is an internal transaction (also called a message). Click on that tab to see it.

This "internal transaction" was sent by the contract in this line of code (from the withdraw function in Faucet.sol):

payable(msg.sender).transfer(withdraw_amount);

To recap: you sent a transaction from your MetaMask wallet that contained data instructions to call the withdraw function with a withdraw_amount argument of 0.1 ether. That transaction caused the contract to run inside the EVM. As the EVM ran the Faucet contract's withdraw function, first it called the require function and validated that the requested amount was less than or equal to the maximum allowed withdrawal of 0.1 ether. Then it called the transfer function to send you the ether. Running the transfer function generated an internal transaction that deposited 0.1 ether into your wallet address, from the contract's balance. That's the one shown on the Internal Transactions tab in the block explorer.

Conclusions

In this chapter, you set up a wallet using MetaMask and funded it using a faucet on a test network. You received ether into your wallet's Ethereum address, then you sent ether to another address.

Next, you wrote a faucet contract in Solidity. You used the Remix IDE to compile the contract into EVM bytecode, then used Remix to form a transaction and created the Faucet contract on the testnet blockchain. Once created, the Faucet contract had an Ethereum address, and you sent it some ether. Finally, you constructed a transaction to call the withdraw function and successfully asked for 0.1 ether. The contract checked the request and sent you 0.1 ether with an internal transaction.

It may not seem like much, but you've just successfully interacted with software that controls money on a decentralized world computer.

**Cross-chain exercise**: If you deployed your Faucet contract to Sepolia, try deploying the same contract to Mordor (or vice versa). You'll notice the process is identical — same Solidity code, same Remix workflow, same MetaMask interaction. The only difference is the network you're connected to. This demonstrates the core principle of this book: **the EVM is the constant, consensus is the variable**.

We will do a lot more smart contract programming in the Smart Contracts chapter and learn about best practices and security considerations in the Smart Contract Security chapter.