This codelab will walk you through how to create and deploy a smart contract via Remix and how to interact with it from both within Remix or a web-based tool such as MyCrypto. If you'd like more information about what is going on, I would recommend visiting https://github.com/ethereumbook/ethereumbook/blob/develop/02intro.asciidoc or viewing the associated screencast lectures available from class.

What you'll learn

What you'll need

  1. Log into your Metamask account and ensure you are using Ropsten

  1. Visit the Remix IDE at https://remix.ethereum.org
  2. Click "Solidity" for your environment

  1. Hover over the icons on the left to see what they correspond to (File explorer, Solidity compiler, Deploy & run)

  1. Click the icon to bring up the file explorer

  1. Click on the "+" to add a new file and name the file "MyContract.sol"

For this lab, we will be deploying a simple contract called MyContract that takes in ETH (the cryptocurrency used for Ethereum transactions). Anyone can send ETH to this contract and anyone can destroy it. Upon destruction, all ETH from the contract is sent to its owner (the wallet that has deployed the contract).

Walk-through the source code

pragma solidity 0.4.24;
contract MyContract {
        address public owner;

        constructor () public {
                owner = msg.sender;
        }

        function getBalance() external view returns(uint) {
                return address(this).balance;
        }

        function cashOut() external {
                selfdestruct(owner);
        }

        function () public payable {
        }
}

Use selfdestruct() at your own peril (if you like keeping your $)

  1. Go back to the Remix file explorer where you have created MyContract.sol and paste it into the file. The Remix IDE (integrated development environment) uses local HTML5 storage to hold your contract code.
  2. Click on the Solidity compiler icon to bring up the compiler

  1. In the compile tab, select the compiler version specified in code (e.g. 0.4.24), then click "Compile"

  1. Look for green check on the compiler icon for success

  1. Then locate clipboard icons that allow you to copy the contract ABI (Application Binary Interface) and EVM bytecode to the clipboard

  1. The ABI is needed for external tools outside of Remix (such as MyCrypto) to interact with the contract.

(For CS students) A contract's ABI is a specification of its binary interface. This allows one to interact with the contract appropriately. The ABI consists of all of the variables in the contract including their types, the functions the contract implements including the parameters and their types. It also specifies any modifiers associated with the variables and functions.

Examine the different parts of MyContract's ABI, by copying it and pasting it into a text document.

  1. Specify a gettr for the public storage variable address owner. Gettrs for public variables are automatically implemented by the Solidity compiler. They have no inputs, are not payable, and are view-only
     {
                "constant": true,
                "inputs": [],
                "name": "owner",
                "outputs": [
                        {
                                "name": "",
                                "type": "address"
                        }
                ],
                "payable": false,
                "stateMutability": "view",
                "type": "function"
        },
  1. Specify the getBalance() function that returns the balance of the contract as a uint256.
        {
                "constant": true,
                "inputs": [],
                "name": "getBalance",
                "outputs": [
                        {
                                "name": "",
                                "type": "uint256"
                        }
                ],
                "payable": false,
                "stateMutability": "view",
                "type": "function"
        },
  1. Specify the cashOut() function. Note that it is non-payable in that the function can not be used to receive payment when called. (It can and does send payment)
        {
                "constant": false,
                "inputs": [],
                "name": "cashOut",
                "outputs": [],
                "payable": false,
                "stateMutability": "nonpayable",
                "type": "function"
        },
  1. Specify the non-payable constructor. Constructors that are payable can receive ETH when deployed by their creator. Constructors for SI CTF levels, for example, are payable. MyContract must be send funds via the fallback function (the only payable function that it has)
        {
                "inputs": [],
                "payable": false,
                "stateMutability": "nonpayable",
                "type": "constructor"
        },
  1. Specify the payable fallback function
        {
                "payable": true,
                "stateMutability": "payable",
                "type": "fallback"
        }
  1. Click on the "Deploy & run transactions" tab

  1. Use the "Injected Web3" environment. This uses Web3.js to communicate directly with Ethereum blockchain nodes (running a client such as geth). Note that Remix includes a fully functional Ethereum Virtual Machine written in Javascript that allows you to run and test contracts within the browser only.

  1. Ensure you are connected to the Ropsten network after selecting. If you are not on Ropsten, go back to Metamask and ensure Ropsten is selected.

  1. Click "Deploy". Note that if the constructor were declared "payable", you could have specified an amount of ETH to send the contract via the "Value" field before clicking "Deploy"
  2. A window will pop up asking you to specify "Gas". This is a nominal amount of ETH needed to give miners on Ethereum the incentive to include your transaction onto the blockchain. Use the default settings that Metamask has suggested. Note: if you are unhappy with the time it is taking for your transactions to process, you may "EDIT" the transaction to increase the "GAS FEE" you're willing to pay, but beware of running out of gas (which will cause your transaction to fail)

  1. Wait for the transaction to complete and for the contract's address to show up in Remix

  1. At the bottom, a clipboard icon appears next to the deployed contract that allows you to copy its address onto the clipboard for use in other tools. Take a screenshot of the above UI in Remix to include in your lab notebook. Ensure that you show both your wallet address and the address of MyContract that you deployed.

On a public blockchain like Ethereum, all transactions are publicly accessible. To view the contract deployment transaction you have just initiated, return to Metamask.

  1. Click on the most recent transaction in the UI

  1. In the details of the transaction, you will find the amount of gas used to deploy the contract and the price of gas you paid. Finally, you will see the total amount of ETH this represents. From this UI, there is an arrow which is a link that will allow you to view the transaction on Etherscan (a web site that provides a web interface to the Ethereum blockchains). Click on it.

  1. Etherscan shows the hash of the transaction included in the block. It also shows the block depth (confirmations), the wallet address that created it, and the address of the contract itself (which should be the same as what shows up on Remix)
  2. Take a screenshot of your Etherscan transaction as shown above to include in your lab notebook

Back in Remix, you can access and interact with the contract, by clicking on the contract under the "Deployed contracts" section. Public gettrs (blue) and contract functions (orange) allow you to interact with the contract

  1. In the example below, both the contract-defined getBalance() function and the automatically instantiated gettr for the public owner address can be clicked on to reveal their values. Click on both.

  1. We will now interact with the contract via a web-based wallet. Go to https://mycrypto.com (an open-source web interface for interacting with contracts) to do the same as above.
  2. In the upper right corner, click dropdown set to "ETHEREUM (AUTO)"

  1. Select the Ropsten network and "AUTO"

  1. Then click "MetaMask" for the wallet to use to access the Blockchain with through MyCrypto

  1. Under "TOOLS", select "Interact with Contracts"

  1. Go to the "Deploy & run transactions" tab of your Remix session to copy the MyContract address onto the clipboard. Paste it into the MyCrypto page above

  1. Go to the "Compile" tab of your Remix session to copy the MyContract ABI onto the clipboard and also paste it into the MyCrypto interface

  1. You should have something like below

  1. Click "Access", then under "Read/Write" Contract, view the options for interacting with the contract. Click on the owner gettr, then click "READ". Take a screenshot to include in your lab notebook.

We will now send the contract funds via our Metamask wallet, which will be processed by the payable fallback function.

  1. Click on Metamask and login if necessary
  2. Take a screenshot of your wallet to include for your lab notebook to show the amount of ETH you have to start with, then click on "SEND"

  1. Copy the contract address from previously into the "To" field. Specify 0.5 ETH as the amount to send. If the transaction fails, set the "Transaction Fee" to slow and try again

  1. Click "Next", then when a confirmation appears, see that the transaction total includes both the amount of ETH we are sending along with the gas fee for the transaction. When the transaction completes, see the update to your wallet balance.

  1. Bring up the transaction on Metamask and on Etherscan. Note that it shows the transfer from your wallet to the contract.

  1. Bring the contract itself up on Etherscan by copying and pasting its address into the search window on Etherscan or clicking on the contract address in the above UI.
  2. Take a screenshot of the contract's transactions to include for your lab notebook that includes its creation transaction.

  1. Note that you can copy your contract's address to the clipboard by clicking on the icon next to its address. You will need this for the next step of this codelab.
  2. Congratulations. You've deployed and funded a smart contract using Ethereum. Your code and transactions will live forever (or until the heat death of the universe), whichever comes first.

MyContract has an external function call named cashOut() that can be called by anyone. The function will simply destroy the contract and send the funds that it holds to the owner of the contract. While we could use MyCrypto to directly call the cashOut() function, to show how contracts can call other contracts, we will create a second contract in Remix to call cashOut().

Back in Remix, use the same process for creating MyContract, to create another contract to kill it called "KillMyContract"

pragma solidity 0.4.24;

interface MyContract {
        function cashOut() external payable;
}

contract KillMyContract {
        address myContractAddr = <YourContractAddressForMyContract>;
        // (e.g. address myContractAddr = 0x5D22a10ab401601219dc9d8A3Ffe48B6EC937954;
        function kill() external {
                MyContract mc = MyContract(myContractAddr);
                mc.cashOut();
        }
        function () public payable {
        }
}

Note that this code must be modified to include the contract address it is intended to call. From the previous step in the lab, copy the address of your version of MyContract that has been deployed and replace the value of <YourContractAddressforMyContract> in the code with it.

Read the code to find the following in the contract code

Repeat the above steps from MyContract for KillMyContract

We will now see what shows up on the blockchain for this transaction.

  1. Go back to Etherscan to locate your original MyContract contract.
  2. Click on the "Internal Txns" tab. These are transactions that have come from within the blockchain (rather than from a wallet outside of the blockchain)
  3. Take a screenshot that shows the two internal transactions that have occured to include in your lab notebook. The bottom one is the call from KillMyContract's address to MyContract that invokes cashOut() while the top one is the result of MyContract's invocation of selfdestruct()to send the contract's balance over to the owner wallet.

  1. Next, click on the Contract tab and take a screenshot of the transaction hash that contains the self-destruct() call for MyContract.

  1. Click on the hash to bring up its internal transactions. In this trace, notice the call from your wallet address to the address of your KillMyContract contract address has "Produced 2 Contract Internal Transactions". The first is the call_0 transaction representing KillMyContract's call to cashOut() while the second is the suicide_0_0 representing the selfdestruct() call sending the remaining contract balance to the owner wallet (e.g. your wallet address)

  1. Click on the Overview tab which summarizes this transaction hash. Take a screenshot and include it in your lab notebook.

You have now funded a contract and received the funds back from it upon its self-destruction. However, these transactions are not free. To keep the network operating, miners and full-nodes must be paid for their operation. Transaction fees are an often-overlooked fact of life on any blockchain and the myriad of blockchains compete to provide similar functionality at a cheaper price while still ensuring security from tampering.

Determine the amount of ETH you have spent from the beginning of this lab.

  1. Click on Metamask
  2. Take a screenshot of your wallet to include for your lab notebook and show the difference in balance from before and after this lab

  1. Convert the difference on Google to show how much $ you would have spent if you had done this lab on the main Ethereum blockchain using today's exchange rate.

You've completed the "Hello World" of smart contracts and their deployments on Ethereum. While simple contracts such as the ones shown here might make it seem like smart contracts with Solidity are a good idea, subsequent labs and assignments will show you otherwise. Much like we teach C at Portland State in order to show how easy it is to create security problems with it, we teach Solidity to do the same. If you can avoid using Solidity to implement smart contracts, we would recommend doing so.