Skip to content

Latest commit

 

History

History
201 lines (140 loc) · 15.8 KB

remix_2.md

File metadata and controls

201 lines (140 loc) · 15.8 KB

Remix Part II - Wallets

Remix Part I looked at using the IDE to compile and deploy smart contracts; Remix comes with some stock-standard contracts for storage, ownership, & voting.

Contents

  1. Environment
  2. MetaMask
  3. Hierarchical Deterministic (HD) Wallets
  4. BIP39
  5. Security
  6. Remix Integration
  7. Testnet ETH
  8. Prepare a Transaction to Send Some ETH
  9. Exercises

Video

There's a screencast of this tutorial on YouTube.

Environment

These contracts get compiled within the virtual machine (VM) environment that runs within your browser instance. This is a simulated blockchain; there are no real blocks, or miners, or validators here. From the docs: For connecting to a sandbox blockchain in the browser. The Remix VM (previously called JavaScript VM) is its own “blockchain” and on each reload the old chain will be cleared and a new blockchain will be started. The old one will not be saved. The London refers to the London fork of Ethereum.

remix environment options

The default is London which includes support for the London fork which changed how fees are handled. As it stands now we have access to 10 dummy test accounts that are preloaded with 100 ETH. These accounts are ephemeral and transaction history will not be saved--or mined to the blockchain for that matter. Injected Provider will allow communication with MetaMask and Brave's native crypto wallet.

MetaMask

Metamask is a Chrome extension. It can run with Chrome/Firefox/Brave/Edge and acts as a middleman between blockchains (mainnets, testnets, custom interfaces, etc.) and applications. The 'wallet' part will store your private keys and sign messages and transactions as well as manage multiple accounts.

various crypto extensions

Examples of crypto extensions running in Brave. Crypto Wallets is Brave's native wallet extension. Best practise for security is to disable extensions when they are not in use. See here for a list of recommended MetaMask security settings and some of the common scams in play.

After installing the extension, you have the option to import a previous wallet using a recovery phrase or create a new one.

MetaMask create screen

MetaMask will provide you with a Secret Recovery Phrase (often called a seed phrase), and ask you to securely store the words and then submit them back in the correct order. It is very important to keep this recovery phrase of 12 words private and secure. (Even if only using for testnet activity it is wise crypto behaviour to become comfortable with self custody.)

MetaMask Secret Recovery Phrase

After creating a password, watching the video, writing down your phrase, and re-entering your phrase, you'll be at the interface ready to use your new account address (the one shown here is 0x99A95d4d7DDe6B9E663509a41CF3A9eeAfC07Ad9) in any of the chains that accept Ethereum based addresses.

MetaMask interface

Hierarchical Deterministic (HD) Wallets

Each instance of MetaMask that has a recovery phrase is called a hierarchical deterministic wallet. Within this hierarchy you can generate multiple accounts, each having their own public/private key pair and each being able to be regenerated with the recovery phrase. This allows many addresses to be generated from the same seed entropy1, so you can always invoice with a fresh address. The new accounts generated under this regime are ordered, with one 'leading' to the next, and deterministic such that when recovering a wallet the child accounts generated will be the same and in the same order.

HD key generation tree

BIP39

The seed phrase is a mapping of common English (& some other) language words to numbers that when assembled in the correct order represent the master private key. BIP392 is a standard that was developed for Bitcoin and now used in many cryptocurrency projects. The total list is 2048 words and contains words as short as mom and as long as mosquito. From the master key many branches and children can be derived as per the algorithm below. To generate a seed phrase, you first need some entropy, then run it through SHA256, append the bit difference to the entropy, and split the output into the required number of words (12, 18, 24, etc.). These individual pieces then map to one of the 2048 words.

extending parent public key

Key diagram sources: Antonopolous, Mastering Bitcoin. 2nd ed. 2018. https://github.com/bitcoinbook/bitcoinbook.

Security

In order to guess someone's private key you need to guess a sequence of 12, or 24 words from the list. Since there are 2048 possibilities for each guess, you have a one-in-2048 chance of guessing the first word correctly. At this point it may seem feesible for a computer to run this search fairly easily. Keeping in mind there is no progress indicator like making it past the first tumbler in a lock, so the probability to find the first two words is now $p= {1 \over 2048}{1 \over 2048}={1 \over 4,194,304} $. Extending this to a twelve word seed phrase: $p={1 \over 2048^{12}}$ and inverting to represent the number of possibilities we get $5.44E10^{39}$. On average it might take half the time to correctly guess a seed, so this is $2.72E10^{39}$ attemps. This is roughly the same size as the theoretical maximum number of Internet addresses that can be allocated under the IPv6 addressing ( $10^{36}$ ); or the estimated number of atoms in Earth ( $10^{50}$ ).

Exercise: How much harder is it to guess a 24-word phrase? How long would it take your computer to guess every possible key?

Remix Integration

In MetaMask, the Ethereum mainnet is the default selection. Mainnet Ethereum requires gas fees to be paid in real ETH and so we'll want to click Show/hide test networks and then select Goerli.

MM_show_hide
MM_test_networks

Goerli is a fully operational ethereum test network that activated the proof-of-stake merge in August 2022 and should be supported into the merge and subsequent updates. Update: Goerli is deprecated, so you may want to try Sepolia instead.

Back at remix.ethereum.org select the Deploy tab and Injected Provider environment. MetaMask should open and ask you to connect.

remix injected provider MetaMask

Click Next and Connect. Remix now shows your MetaMask address 0x99A..C07Ad9 along with its balance.

remix MetaMask account balance

Testnet ETH

We now have access to Goerli and an IDE that can compile contracts and send transactions through a wallet. But to do we always need to pay gas fees. Yes, even on testnets, as they must mimic the mainnet as closely as possible. A few options to acquire some goerliETH:

Claiming the GoerliETH will actually be verified onchain, as opposed to a virtual machine in the browser.

faucet eth

Sepolia

Goerli is deprecated and Sepolia is the primary testnet. Try the sepolia/alchemy faucet here: https://sepoliafaucet.com/

Lets use some ETH (finally)

  1. In the File explorer tab open the 2_Owner.sol contract template
  2. In the Solidity compiler tab click the button that says Compile 2_Owner.sol
  3. In the Deploy & run transactions tab click the deploy button
  4. Here, a MetaMask notifcation pops up asking you to confirm deployment and showing the gas required.
remix gas fee warning
  1. You have to wait for these transactions to be confirmed. Once the contract has been deployed you will see an update in the console and a link to the transaction on etherscan.
remix_etherscan link
  1. Check our your remaining balance. Any difference?

Prepare a Transaction to Send Some ETH

For this section you can switch back to the Javascript VM or continue using MetaMask connected to Goerli. I will use Goerli as we are already connected to it.

Copy the following solidity code into a new file. Name it send_Receive.sol.

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.16;

contract ReceiveEther {
    /*
    Which function is called, fallback() or receive()?

           send Ether
               |
         msg.data is empty?
              / \
            yes  no
            /     \
receive() exists?  fallback()
         /   \
        yes   no
        /      \
    receive()   fallback()
    */

    // Function to receive Ether. msg.data must be empty
    receive() external payable {}

    // Fallback function is called when msg.data is not empty
    fallback() external payable {}

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

contract SendEther {
    function sendViaTransfer(address payable _to) public payable {
        // This function is no longer recommended for sending Ether.
        _to.transfer(msg.value);
    }

    function sendViaSend(address payable _to) public payable {
        // Send returns a boolean value indicating success or failure.
        // This function is not recommended for sending Ether.
        bool sent = _to.send(msg.value);
        require(sent, "Failed to send Ether");
    }

    function sendViaCall(address payable _to) public payable {
        // Call returns a boolean value indicating success or failure.
        // This is the current recommended method to use.
        (bool sent, bytes memory data) = _to.call{value: msg.value}("");
        require(sent, "Failed to send Ether");
    }
}

In Remix, in the Solidity compiler tab, click compile. (Its a good idea to leave auto compile turned on.) You should get a warning about an unused local variable and a status update in the terminal window.

Switch to the Deploy & run transactions tab. Clicking on the CONTRACT box shows there are actually two contracts in the code above: ReceiveEther & SendEther.

image

Deploy both contracts & pay the gas fees using MetaMask (not not if using the VM).

image

You should see all of your available contracts in the IDE.

image

Interacting with a contract or sending coins involves preparing and posting a transaction. Key information is the GAS LIMIT or how much gas you are willing to pay to get the transaction to post--once your gas runs out the transaction will cancel, VALUE which can be ether denominated in smaller units--Wei is shown in Remix3, and the address_to field which is the recipient. This is all usually done by the wallet software. Remix will prepare and broadcast our transaction.

In MetaMask I will switch to Account 2 to get a fresh address: 0xd2b2A1F06B05f9880577B2d0e7083e8ABbeC3dBb. Set up your transaction as follows.

image

Did it Work?

Check your other account in MetaMask to see.

image

Exercises

  1. The ReceiveEther contract currently has a balance of zero. Send some ether to this contract.
  2. Why would you want to send ETH to a contract and not to someone's wallet?
  3. Are your gas fees different than mine? Why?
  4. From the section on security, how much harder is it to guess a 24-word phrase than a 12-word phrase? For a (modest) 12-word seed, how long would it take your computer to guess every possible key?

Choose #5 or #6 as a coding exercise
5. Hierarchical Deterministic (HD) Wallet Creation: Implement a basic Hierarchical Deterministic (HD) Wallet using an existing library. Experiment with creating child keys from a master seed.
6. Multisignature (Multisig) Transaction Simulation: Simulate a multisig transaction that requires signatures from at least two out of three parties. You could create three key pairs and write a function that verifies multiple signatures.

Footnotes

  1. Seed entropy refers to the orignal source of randomness used to generate the seed phrase. In the case of browser generation such as with MetaMask this comes from the OS random function and is the safest way to do so online. Good ways to generate your own entropy include dice and lava-lamps.

  2. Bitcoin improvement proposal number 39. See also BIP32 and BIP44

  3. 10 million gwei is 0.01 ether, see https://eth-converter.com/