Blockchain Development Workflow and Pet Adoption dApp Tutorial – Learning Note 3

### Development Workflow

### beginning of development with a private blockchain
>> geth –dev console –ipcdisable

To revisit 5.1

### node, npm and nvm

often you will encounter incompatible version of node and npm, or you need different version of npm/node for different projects. nvm is the solution.
Mac/Linux
https://github.com/nvm-sh/nvm

Nvm doesn’t support Window. Below is a alternative to nvm in window
https://github.com/coreybutler/nvm-windows

Note:. Before installing the nvm-window, remember to remove the existing node installation

Uninstall Node.js and npm

Uninstall node.js and npm installed using Windows Installer (msi)

To uninstall node.js and npm, Open Windows “Control Panel” -> “Uninstall a program”, select Node.js and click on uninstall to uninstaill both node.js and npm

Cleanup directories

After the uninstall, look for the following folders and delete them if exists
* Nodejs installed directory
* npm and npm-cache directories from %appdata% directory

* npmrc directory from user home directory ( C:Users{User} )

>> nvm
### Install other version of node
>> nvm install 10.22.1
>> nvm list
>> nvm use 10.22.1

Note: to run npm in powershell, make sure you open the powershell in “administrative mode”

### Ganache

>> npm install -g ganache-cli

>>ganache-cli

Available Accounts
==================
(0) 0xa8b4D5578e74922473D43bd9B1BA2005C1697522 (100 ETH)
(1) 0xb5367e2d47Ec97eE54dAd67aE2665245441A2383 (100 ETH)
(2) 0x651411ABdD83Cd610Cd7C44f4C2F87D85107b9b6 (100 ETH)
(3) 0xF93806c963D8A2D751672E15B306bF90Bf20e586 (100 ETH)
(4) 0x113015caA33D0c32AD160F8bC2336f33F25f69bA (100 ETH)
(5) 0x885E2EC9ae39EEE506040525320139250bb6C6ab (100 ETH)
(6) 0x50561D6728B238a64dEe47ac3E701cC546CB2a7A (100 ETH)
(7) 0x1383c4848882A4d3c7681935Aed6d3cA2CC597aC (100 ETH)
(8) 0x751bf220aCF7A0A23a1c8106d5FF7bDdc1B75097 (100 ETH)
(9) 0x33A11A50f0fCA2f46283AAf870EFEF9C2d5ddc3d (100 ETH)

Private Keys
==================
(0) 0x3b1dca2f486d5b7b1c22ac08921fc2d5596e61efaab93561310b0aa0770850b0
(1) 0x17844954e498fa51d6be9dca83f19c6538514fe75439a8ebb8559e37436eb60a
(2) 0x3cab334e964b2e66daf013e60d29d7473702141eddf553aa88afc1c9698ed5ed
(3) 0x39cdf82ca0916a4e1bb4ef21838e88579cff75b6333065d7a4e38535fb8e594e
(4) 0x07e371aac4eb57c66fa3c6d4f861678332d0eaf2aeb7fb24afa92d3480c781db
(5) 0x839525ce112385f7e421b58614d4d2af3a77e860c8c9b35d86caa1d53cd69f9e
(6) 0xa280a67e15816ef6eef8d1ec1c47347902275c6ea57f26703ff3ff5f8716b585
(7) 0xa4953932cee5cf185bf670d888c447e1ed9abd258a2076c074d892db4e8a132a
(8) 0x5856942dbd530d4779c25532b0b21226bb109a832e9018668102e2f59970ce06
(9) 0xc369545eff1c03c9d5becd318519d9ef0dbdee79863e5bbde67aa77b75a5a736

HD Wallet
==================
Mnemonic: artwork visa parrot ethics obvious awkward embody slice stomach wrong kind print
Base HD Path: m/44’/60’/0’/0/{account_index}

Gas Price
==================
20000000000

Gas Limit
==================
6721975

Call Gas Limit
==================
9007199254740991

Listening on 127.0.0.1:8545

Note: you may encounter disabled running script issue in Window Powershell

Solution: In an administrative mode powershell,
>> set-executionpolicy remotesigned

Reference: https://www.faqforge.com/windows/windows-powershell-running-scripts-is-disabled-on-this-systeadm/

### Connect localhost with Remix.ethereum.org

### import accounts to Metamask and check if all 10 accounts have a balance of 100 ETH

Note: Import accounts with private key. Make sure your network is localhost

### Truffle Suite
documentation: http://truffleframework.com/

### Installing Truffle
>>npm install -g truffle

# should revisit 5.1 and 5.5

### Solidity Fundamentals
### Data Types and Variables
Statically typed

Elementary Types

  • Boolean
     
  • Integer
     
  • Address
     
  • Byte Arrays
     
  • Enums
     

Complex Types

  • Arrays

Structs

Mappings

### Functions

### The difference between storage and memory
### Contract Structure
### How to read smart contract
### Smart Contract Application Binary Interfaces (ABIs)
### Events and logs in Ethereum
Reference: https://solidity.readthedocs.io/en/latest/contracts.html#events

The common uses for events can be broken down into three main use cases:

  1. Events can provide smart contract return values for the User Interface
  2. They can act as asynchronous triggers with data and
  3. They can act a cheaper form of storage.

Events as Data Storage

Logs, which are essentially the same as events (the context dictates which term is more appropriate) can also be used as a cheaper form of storage. Logs cost 8 gas per byte whereas contract storage costs 20,000 per 32 bytes, or 625 gas per byte. Logs are cheaper, but also cannot be accessed from any contracts so their use case as storage objects is much more limited. Even still, logs can be useful for aggregating historical reference data.

### Factory Contracts
### A deep dive into the Remix IDE

Should revisit the entire chapter 6

### Truffle Pet Shop Tutorial
This tutorial will take you through the process of building your first dapp—an adoption tracking system for a pet shop!

ensure you have the development environment setup
>> truffle -v

### use truffle box (boiler plates) to create the project structure with user interface code
>> truffle unbox pet-shop

Note: understand more about Truffle Box boiler plates https://www.trufflesuite.com/boxes

Directory structure
The default Truffle directory structure contains the following:

  • contracts/: Contains the Solidity source files for our smart contracts. There is an important contract in here called Migrations.sol, which we’ll talk about later.
  • migrations/: Truffle uses a migration system to handle smart contract deployments. A migration is an additional special smart contract that keeps track of changes.
  • test/: Contains both JavaScript and Solidity tests for our smart contracts
  • truffle-config.js: Truffle configuration file

### Create a new contract name “Adoption.sol”

pragma solidity ^0.5.0;

contract Adoption {
address[16] public adopter;

// adopting a pet
function adopt(uint petId) public returns (uint) {
require(petId >= 0 && petId <= 15);

adopters[petId] = msg.sender;

return petId;
}

// retrieving the adopters
function getAdopters() public view returns (address[16] memory){
return adopters;
}

}

### compile contract
>> truffle compile

### Migrate the contract to blockchain
A migration is a deployment script meant to alter the state of your application’s contracts, moving it from one state to the next. For the first migration, you might just be deploying new code, but over time, other migrations might move data around or replace a contract with a new one.

### Create a new file name “2_deploy_contracts.js” under the “migration” folder
var Adoption = artifacts.require(“Adoption”);

module.exports = function(deployer){
deployer.deploy(Adoption);
};

### Launch ganache and migrate the contract to ganache private blockchain

>> truffle migrate

### Testing the smart contract using solidity
We start the contract off with 3 imports:

  • Assert.sol: Gives us various assertions to use in our tests. In testing, an assertion checks for things like equality, inequality or emptiness to return a pass/fail from our test. Here’s a full list of the assertions included with Truffle.
  • DeployedAddresses.sol: When running tests, Truffle will deploy a fresh instance of the contract being tested to the blockchain. This smart contract gets the address of the deployed contract.
  • Adoption: The smart contract we want to test.

Then we define three contract-wide variables:

  • First, one containing the smart contract to be tested, calling the DeployedAddresses smart contract to get its address.
  • Second, the id of the pet that will be used to test the adoption functions.
  • Third, since the TestAdoption contract will be sending the transaction, we set the expected adopter address to this, a contract-wide variable that gets the current contract’s address.

### Create a new file name “TestAdoption.sol” under “test” folder
pragma solidity ^0.5.0;

import “truffle/Assert.sol”;
import “truffle/DeployedAddresses.sol”;
import “../contracts/Adoption.sol”;

contract TestAdoption{
// The address of the adoption contract to be tested
Adoption adoption = Adoption(DeployedAddresses.Adoption());

// The id of the pet that will be used for testing
uint expectedPetId = 8;

//The expected owner of adopted pet is this contract
address expectedAdopter = address(this);

// Testing the adopt() function
function testUserCanAdoptPet() public {
uint returnedId = adoption.adopt(expectedPetId);

Assert.equal(returnedId, expectedPetId, “Adoption of the expected pet should match what is returned.”);
}

// Testing retrieval of a single pet’s owner
function testGetAdopterAddressByPetId() public {
address adopter = adoption.adopters(expectedPetId);

Assert.equal(adopter, expectedAdopter, “Owner of the expected pet should be this contract”);
}

// Testing retrieval of all pet owners
function testGetAdopterAddressByPetIdInArray() public {
// Store adopters in memory rather than contract’s storage
address[16] memory adopters = adoption.getAdopters();

Assert.equal(adopters[expectedPetId], expectedAdopter, “Owner of the expected pet should be this contract”);
}
}

### Run the test
>> truffle test

### Creating UI with smart contract
Modify the “app.js” file in the “/src/js” folder as below:
App = {
web3Provider: null,
contracts: {},

init: async function() {
// Load pets.
$.getJSON(‘../pets.json’, function(data) {
var petsRow = $(‘#petsRow’);
var petTemplate = $(‘#petTemplate’);

for (i = 0; i < data.length; i ++) {
petTemplate.find(‘.panel-title’).text(data[i].name);
petTemplate.find(‘img’).attr(‘src’, data[i].picture);
petTemplate.find(‘.pet-breed’).text(data[i].breed);
petTemplate.find(‘.pet-age’).text(data[i].age);
petTemplate.find(‘.pet-location’).text(data[i].location);
petTemplate.find(‘.btn-adopt’).attr(‘data-id’, data[i].id);

petsRow.append(petTemplate.html());
}
});

return await App.initWeb3();
},

initWeb3: async function() {
// Modern dapp browsers…
if (window.ethereum) {
App.web3Provider = window.ethereum;
try {
// Request account access
await window.ethereum.enable();
} catch (error) {
// User denied account access…
console.error(“User denied account access”)
}
}
// Legacy dapp browsers…
else if (window.web3) {
App.web3Provider = window.web3.currentProvider;
}
// If no injected web3 instance is detected, fall back to Ganache
else {
App.web3Provider = new Web3.providers.HttpProvider(‘http://localhost:7545‘);
}
web3 = new Web3(App.web3Provider);

return App.initContract();
},

initContract: function() {
$.getJSON(‘Adoption.json’, function(data) {
// Get the necessary contract artifact file and instantiate it with @truffle/contract
var AdoptionArtifact = data;
App.contracts.Adoption = TruffleContract(AdoptionArtifact);

// Set the provider for our contract
App.contracts.Adoption.setProvider(App.web3Provider);

// Use our contract to retrieve and mark the adopted pets
return App.markAdopted();
});

return App.bindEvents();
},

bindEvents: function() {
$(document).on(‘click’, ‘.btn-adopt’, App.handleAdopt);
},

markAdopted: function() {
var adoptionInstance;

App.contracts.Adoption.deployed().then(function(instance) {
adoptionInstance = instance;

return adoptionInstance.getAdopters.call();
}).then(function(adopters) {
for (i = 0; i < adopters.length; i++) {
if (adopters[i] !== ‘0x0000000000000000000000000000000000000000’) {
$(‘.panel-pet’).eq(i).find(‘button’).text(‘Success’).attr(‘disabled’, true);
}
}
}).catch(function(err) {
console.log(err.message);
});
},

handleAdopt: function(event) {
event.preventDefault();

var petId = parseInt($(event.target).data(‘id’));

var adoptionInstance;

web3.eth.getAccounts(function(error, accounts) {
if (error) {
console.log(error);
}

var account = accounts[0];

App.contracts.Adoption.deployed().then(function(instance) {
adoptionInstance = instance;

// Execute adopt as a transaction by sending account
return adoptionInstance.adopt(petId, {from: account});
}).then(function(result) {
return App.markAdopted();
}).catch(function(err) {
console.log(err.message);
});
});
}

};

$(function() {
$(window).load(function() {
App.init();
});
});

Note: Initiate Web3, Instantiating contract, getting the adopted pets and updating the UI, handling the adopt function,

### Interact with the dapp in browser

  1. Get the private key from Ganache
     
  2. Import ganache test account to MetaMask
  1. Add LocalHost 7545 Network to MetaMask

### Installing and configuring lite-server
Examine “bs-config.json” and “package.json” files
{
“server”: {
“baseDir”: [“./src”, “./build/contracts”]
}}

“scripts”: {
“dev”: “lite-server”,
“test”: “echo “Error: no test specified” && exit 1″},

### Starting the local web server
>> npm run dev

Pet Shop Dapp launched:


### try to adopt a pet and play around with the dapp

### Introductory Contracts
reference: https://sunnya97.gitbooks.io/a-beginner-s-guide-to-ethereum-and-dapp-developme/content/writing-smart-contracts/introductory-contracts.html

### Inter-contract Execution
=> calling the value/code from another contract base on contract address

### Inheritance
### Libraries
Libraries are contracts that do not have storage, they cannot hold ether and they cannot inherit or be inherited by other contracts. Libraries can be seen as implicit base contracts of the contracts that use them.

They exist for the purpose of code reuse.

Reference: https://www.trufflesuite.com/docs/truffle/getting-started/package-management-via-npm

EthPM and Truffle
Library and contract package management can be simplified by using EthPM. EthPM is essentially npm for Ethereum contracts. Truffle has support for EthPM so you can install a package with truffle install and the package name.
Available packages: https://docs.ethpm.com/

>> truffle install <package name>

Truffle comes with an option for migrating contracts that enables you to only deploy contracts if there isn’t already a deployed instance. For example, MyContract requires an instance of the Ethereum Name Service contract. The following deployment script will only deploy an instance of the ENS (Ethereum Name Service) contract if there is not one on the detected network.
var ENS = artifacts.require(“ens/ENS”);
var MyContract = artifacts.require(“MyContract”);

module.exports = function(deployer) {
// Only deploy ENS if there’s not already an address already.
// i.e., don’t deploy if we’re using the canonical ENS address,
// but do deploy it if we’re on a test network and ENS doesn’t exist.
deployer.deploy(ENS, {overwrite: false}).then(function() {
return deployer.deploy(MyContract, ENS.address);
});
};

Like NPM, configuration options for EthPM go in a separate JSON file called ethpm.json. This file sits alongside your Truffle configuration and gives Truffle all the information it needs to publish your package.

Additional Resources:

  1. Library Driven Development in Solidity
  2. Libraries in the Solidity Docs
  3. Linking to deployed libraries with Truffle migrations
  4. What are the steps to compile and deploy a library in solidity?
  5. Package Management with EthPM in Truffle
  6. EthPM: Reusable Smart Contract Packages

### Smart Contract System Design

  • Voting system

### Proof Existence
Start ganache-ccli
>>ganache-cli

v
init proof of existence project
>> mkdir proof-of-existence
>> cd proof-of-existence
>> truffle init

migration
>> truffle migrate

>> truffle create contract ProofOfExistence1

pragma solidity ^0.5.0;

contract ProofOfExistence1 {

// state

bytes32 public proof;

// calculate and store the proof for a document

// *transactional function*

function notarize(string memory document) public {

proof = proofFor(document);

}

// helper function to get a document’s sha256

// *read-only function*

function proofFor(string memory document) public pure returns (bytes32) {

return sha256(abi.encodePacked(document));

}

}

### Create a new migration file in the migrations directory “2_deploy_contracts.js”

var ProofOfExistence1 = artifacts.require(‘./ProofOfExistence1.sol’);

module.exports = function(deployer) {
deployer.deploy(ProofOfExistence1);
};

### Migration

Migrations are JavaScript files that help you deploy contracts to the Ethereum network. These files are responsible for staging your deployment tasks, and they’re written under the assumption that your deployment needs will change over time.

Reference: https://www.trufflesuite.com/docs/truffle/getting-started/running-migrations

>> truffle migrate

### Interact with smart contract
>> truffle console

truffle(development) >>var poe = await ProofOfExistence1.at(ProofOfExistence1.address)
truffle(development) >>poe.address

### to call a notarize function
truffle(development) >> poe.notarize(“Hello World!”)

This function causes a state change, so it is a transactional function. Transactional functions return a Promise that resolves to a transaction object.
We can get the proof for the string with

truffle(development) >> poe.proofFor(“Hello World!”)

And check that the contract’s state was correctly changed

truffle(development)> poe.proof()

Note: make sure the hashes match

### exit truffle console
truffle(development)> .exit

### Iterating the code
>> truffle create contract ProofOfExistence2

pragma solidity ^0.5.0;

contract ProofOfExistence2 {

// state

bytes32[] private proofs;

// store a proof of existence in the contract state
// *transactional function*

function storeProof(bytes32 proof) public

{

proofs.push(proof);

}

// calculate and store the proof for a document

// *transactional function*

function notarize(string calldata document) external

{

bytes32 proof = proofFor(document);

storeProof(proof);

}

// helper function to get a document’s sha256

// *read-only function*

function proofFor(string memory document)

pure public returns (bytes32)

{

return sha256(abi.encodePacked(document));

}

// check if a document has been notarized

// *read-only function*

function checkDocument(string memory document)

public

view

returns (bool)

{

bytes32 proof = proofFor(document);

return hasProof(proof);

}

// returns true if proof is stored

// *read-only function*

function hasProof(bytes32 proof)

internal view returns (bool)

{

for (uint256 i = 0; i < proofs.length; i++) {

if (proofs[i] == proof) {

return true;

}

}
return false;

}
}

### Update 2_deploy_contract.js
var ProofOfExistence2 = artifacts.require(‘./ProofOfExistence2.sol’);

module.exports = function(deployer) {
deployer.deploy(ProofOfExistence2);
};

>> truffle migrate –reset

>> truffle console
>>>>var poe = await ProofOfExistence2.at(ProofOfExistence2.address)
>>>> poe.checkDocument(“Hello World!”)
>>>> poe.notarize(“Hello World!”)
>>>> poe.checkDocument(“Hello World!”)

### test if multiple proofs can be stored in smart contract
>>>> poe.notarize(“Hello Consensys!”)
>>>> poe.checkDocument(“Hello Consensys!”)

Note: Looping over arrays in smart contracts can get expensive as arrays get longer. Using a mapping is a better solution.
>>>>.exit

### Using mapping for the smart contract instead of array

>>truffle create contract ProofOfExistence3
pragma solidity ^0.5.0;

contract ProofOfExistence3 {

mapping (bytes32 => bool) private proofs;

// store a proof of existence in the contract state
function storeProof(bytes32 proof)
internal
{
proofs[proof] = true;
}

// calculate and store the proof for a document
function notarize(string calldata document)
external
{
bytes32 proof = proofFor(document);
storeProof(proof);
}

// helper function to get a document’s sha256
function proofFor(string memory document)
pure
public
returns (bytes32)
{
return keccak256(bytes(document));
}

// check if a document has been notarized
function checkDocument(string memory document)
public
view
returns (bool)
{
bytes32 proof = proofFor(document);
return hasProof(proof);
}

// returns true if proof is stored
function hasProof(bytes32 proof)
internal
view
returns(bool)
{
return proofs[proof];
}
}

### Modify the deployment script 2_deploy_contract.js
var ProofOfExistence3 = artifacts.require(‘./ProofOfExistence3.sol’);

module.exports = function(deployer) {
deployer.deploy(ProofOfExistence3);
};

>> truffle migrate –reset

### Test to ensure all behave the same as in ProofOfExistence2.sol
>> truffle console
>>>>var poe = await ProofOfExistence2.at(ProofOfExistence2.address)
>>>> poe.checkDocument(“Hello World!”)
>>>> poe.notarize(“Hello World!”)
>>>> poe.checkDocument(“Hello World!”)

### test if multiple proofs can be stored in smart contract
>>>> poe.notarize(“Hello Consensys!”)
>>>> poe.checkDocument(“Hello Consensys!”)

### Deployment to the Tesnet

Uncomment below in truffle-config.js

const HDWalletProvider = require(‘@truffle/hdwallet-provider’);
const infuraKey = “fj4jll3k…..”;
//
const fs = require(‘fs’);
const mnemonic = fs.readFileSync(“.secret”).toString().trim();

Note:
line 1 => will import the tool to derive a private key and address from a mnemonic.
lline 2 => for your infura API key
line 3 and liine 4 => will import your seed phrase (from the .secret file) into the file. Truffle will use these words to access your wallet and deploy the contract.

Metamask password: 12345678
get Rinkeby Test Ether from: https://faucet.rinkeby.io/

### save the seed phrase into a file “.secret” in project folder

Infura Rinkeby Test Network API End points:
https://rinkeby.infura.io/v3/b2682c3cc9834ae5a310c8eae5ae35a8

input the above to truffle-config.js “const infuraKey =”

###Make sure hdwallet-provider is installed
> npm install @truffle/hdwallet-provider

### Modify truffle-config.js module.export as below:

networks: {
development: {
host: ‘localhost’,
port: 8545,
network_id: ‘*’
},

rinkeby: {
provider: () => new HDWalletProvider(mnemonic, infuraURL),
network_id: 4, // Rinkeby’s network id
gas: 5500000,
},
}

Where the “mnemonic” variable is the 12 word seed phrase that you saved from metamask and the “infuraKey” variable is your Infura Project ID.

### deploy the contract to Rinkeby Test Network
>> truffle migrate –network rinkeby

The terminal prints the addresses of the deployed contracts as well as the transaction hashes of the deployment transactions. This information can also be referenced in the contract artifacts, which are stored in proof-of-existence/build/contracts/. Deployment information is found at the bottom of each JSON file.

You can now interact with the deployed contract on the Rinkeby test network!

### Multi-Signature Wallet Exercise
reference:
https://github.com/ConsenSys-Academy/multisig-wallet-exercise/blob/master/Multisig_wallet_info.md
https://github.com/ConsenSys/MultiSigWallet
https://github.com/ConsenSys-Academy/multisig-wallet-exercise

A multisignature wallet is an account that requires some m-of-n quorum of approved private keys to approve a transaction before it is executed.

In Ethereum, multisignature wallets are implemented as a smart contract, that each of the approved external accounts sends a transaction to in order to “sign” a group transaction.

Following this project spec designed by the UPenn Blockchain Club, you will now create your own multisignature wallet contract.

Note: It is not suggested that you use this multisignature wallet with any real funds, but rather use a far more deeply audited one such as the Gnosis multisignature wallet.

Objectives:
1. To learn how to handle complex interactions between multiple users on one contract
2. Learn how to avoid loops and implement voting
3. To learn to assess possible attacks on contracts.

>> git clone https://github.com/ConsenSysMesh/MultiSigWallet.git

### Implementing the Contract via Remix

To revisit 7.7

### Debugging Truffle Tests
reference: https://github.com/ConsenSys-Academy/truffle-test-debugging

>> git clone https://github.com/ConsenSys-Academy/truffle-test-debugging.git

>> ganache-cli
>>truffle test

### find out the transaction hash causing the test error

### debug the error
>> truffle debug 0x8299aacba164f10c871c6bee2e610bc2c9a97fd07ce3ae66992637f41de0a37a

### Navigating through the transaction
>> o
>> v

Error:

### Go go SimpleStorage.sol and remove “+1” from the file and save
>> truffle test

### In the next few sections, you will practice writing smart contracts. We are using Test Driven Development (TDD) to help you think about the development process for Solidity.

Note: Solidity Cheatsheets https://manojpramesh.github.io/solidity-cheatsheet/#mapping

### Simple Bank Exercise
reference: https://github.com/CA-bootcamp-s19/simple-bank-exercise-farmountain
git: https://github.com/CA-bootcamp-s19/simple-bank-exercise-farmountain.git

Commonly used git commands
git clone https://github.com/CA-bootcamp-s19/simple-bank-exercise-farmountain.git
git init
git pull

git remote -v
git checkout -b NJD-55
git checkout NJD-55
git status

git add .

git commit -m “NJD-55 enhance corporate registry generator fields”

git push https://github.com/CA-bootcamp-s19/simple-bank-exercise-farmountain.git

git pull
git checkout master

### To resolve conflicts in the master
git pull
git rebase origin/master
git push -f

contract test verification: https://travis-ci.com/github/CA-bootcamp-s19/simple-bank-exercise-farmountain

>> git clone https://github.com/CA-bootcamp-s19/simple-bank-exercise-farmountain.git

// SPDX-License-Identifier: MIT
/*
This exercise has been updated to use Solidity version 0.6.12
Breaking changes from 0.5 to 0.6 can be found here:
https://solidity.readthedocs.io/en/v0.6.12/060-breaking-changes.html
*/

pragma solidity ^0.6.12;

contract SimpleBank {

//
// State variables
//
/* Fill in the keyword. Hint: We want to protect our users balance from other contracts*/
mapping (address => uint) private balances;

/* Fill in the keyword. We want to create a getter function and allow contracts to be able to see if a user is enrolled. */
mapping (address => bool) public enrolled;

/* Let’s make sure everyone knows who owns the bank. Use the appropriate keyword for this*/
address public owner;

//
// Events – publicize actions to external listeners
//

/* Add an argument for this event, an accountAddress */
event LogEnrolled(address accountAddress);

/* Add 2 arguments for this event, an accountAddress and an amount */
event LogDepositMade(address accountAddress, uint amount);

/* Create an event called LogWithdrawal */
/* Add 3 arguments for this event, an accountAddress, withdrawAmount and a newBalance */
event LogWithdrawal(address accountAddress, uint withdrawAmount, uint newBalance);

//
// Functions
//

/* Use the appropriate global variable to get the sender of the transaction */
constructor() public payable {
/* Set the owner to the creator of this contract */
owner = msg.sender;
}

// Fallback function – Called if other functions don’t match call or
// sent ether without data
// Typically, called when invalid data is sent
// Added so ether sent to this contract is reverted if the contract fails
// otherwise, the sender’s money is transferred to contract
receive() external payable {
require(msg.data.length==0);
revert(“send ether without data”);
}

/// @notice Get balance
/// @return The balance of the user
// A SPECIAL KEYWORD prevents function from editing state variables;
// allows function to run locally/off blockchain
function getBalance() public view returns (uint) {
/* Get the balance of the sender of this transaction */
return balances[msg.sender];
}

/// @notice Enroll a customer with the bank
/// @return The users enrolled status
// Emit the appropriate event
function enroll() public returns (bool){
enrolled[msg.sender] = true;
emit LogEnrolled(msg.sender);
return enrolled[msg.sender];
}

/// @notice Deposit ether into bank
/// @return The balance of the user after the deposit is made
// Add the appropriate keyword so that this function can receive ether
// Use the appropriate global variables to get the transaction sender and value
// Emit the appropriate event
// Users should be enrolled before they can make deposits
function deposit() public payable returns (uint) {
/* Add the amount to the user’s balance, call the event associated with a deposit,
then return the balance of the user */
balances[msg.sender] += msg.value;
emit LogDepositMade(msg.sender, msg.value);
return balances[msg.sender];
}

/// @notice Withdraw ether from bank
/// @dev This does not return any excess ether sent to it
/// @param withdrawAmount amount you want to withdraw
/// @return The balance remaining for the user
// Emit the appropriate event
function withdraw(uint withdrawAmount) public payable returns (uint) {
/* If the sender’s balance is at least the amount they want to withdraw,
Subtract the amount from the sender’s balance, and try to send that amount of ether
to the user attempting to withdraw.
return the user’s balance.*/
require(withdrawAmount <= balances[msg.sender]);
balances[msg.sender] -= withdrawAmount;
msg.sender.transfer(withdrawAmount);
emit LogWithdrawal(msg.sender, withdrawAmount, balances[msg.sender]);
return balances[msg.sender];
}

}

### Supply Chain Exercise
reference: https://github.com/CA-bootcamp-s19/supply-chain-exercise-farmountain
git: https://github.com/CA-bootcamp-s19/supply-chain-exercise-farmountain.git

contract test validation: https://travis-ci.com/github/CA-bootcamp-s19/supply-chain-exercise-farmountain

>>git clone https://github.com/CA-bootcamp-s19/supply-chain-exercise-farmountain
// SPDX-License-Identifier: MIT
/*
This exercise has been updated to use Solidity version 0.6
Breaking changes from 0.5 to 0.6 can be found here:
https://solidity.readthedocs.io/en/v0.6.12/060-breaking-changes.html
*/

pragma solidity >=0.6.0 <0.7.0;

contract SupplyChain {

/* set owner */
address owner;

/* Add a variable called skuCount to track the most recent sku # */
uint skuCount;

/* Add a line that creates a public mapping that maps the SKU (a number) to an Item.
Call this mappings items
*/
mapping (uint => Item) public items;

/* Add a line that creates an enum called State. This should have 4 states
ForSale
Sold
Shipped
Received
(declaring them in this order is important for testing)
*/
enum State {
ForSale,
Sold,
Shipped,
Received
}

/* Create a struct named Item.
Here, add a name, sku, price, state, seller, and buyer
We’ve left you to figure out what the appropriate types are,
if you need help you can ask around 🙂
Be sure to add “payable” to addresses that will be handling value transfer
*/
struct Item {
string name;
uint sku;
uint price;
State state;
address payable seller;
address payable buyer;
}

/* Create 4 events with the same name as each possible State (see above)
Prefix each event with “Log” for clarity, so the forSale event will be called “LogForSale”
Each event should accept one argument, the sku */

event LogForSale(uint sku);
event LogSold(uint sku);
event LogShipped(uint sku);
event LogReceived(uint sku);

/* Create a modifer that checks if the msg.sender is the owner of the contract */
modifier checkOwner{ msg.sender == owner; _;}

modifier verifyCaller (address _address) { require (msg.sender == _address); _;}

modifier paidEnough(uint _price) { require(msg.value >= _price); _;}
modifier checkValue(uint _sku) {
//refund them after pay for item (why it is before, _ checks for logic before func)
_;
uint _price = items[_sku].price;
uint amountToRefund = msg.value – _price;
items[_sku].buyer.transfer(amountToRefund);
}

/* For each of the following modifiers, use what you learned about modifiers
to give them functionality. For example, the forSale modifier should require
that the item with the given sku has the state ForSale.
Note that the uninitialized Item.State is 0, which is also the index of the ForSale value,
so checking that Item.State == ForSale is not sufficient to check that an Item is for sale.
Hint: What item properties will be non-zero when an Item has been added?

PS: Uncomment the modifier but keep the name for testing purposes!
*/

modifier forSale(uint sku) { items[sku].state == State.ForSale && items[sku].price > 0; _;}
modifier sold(uint sku) { items[sku].state == State.Sold; _;}
modifier shipped(uint sku) {items[sku].state == State.Shipped; _;}
modifier received(uint sku) {items[sku].state == State.Received; _;}

constructor() public {
/* Here, set the owner as the person who instantiated the contract
and set your skuCount to 0. */
owner = msg.sender;
skuCount = 0;
}

function addItem(string memory _name, uint _price) public returns(bool){
emit LogForSale(skuCount);
items[skuCount] = Item({name: _name, sku: skuCount, price: _price, state: State.ForSale, seller: msg.sender, buyer: address(0)});
skuCount = skuCount + 1;
return true;
}

/* Add a keyword so the function can be paid. This function should transfer money
to the seller, set the buyer as the person who called this transaction, and set the state
to Sold. Be careful, this function should use 3 modifiers to check if the item is for sale,
if the buyer paid enough, and check the value after the function is called to make sure the buyer is
refunded any excess ether sent. Remember to call the event associated with this function!*/

function buyItem(uint sku)
public payable
forSale(sku)
paidEnough(items[sku].price)
checkValue(sku)

{
items[sku].seller.transfer(items[sku].price);
items[sku].buyer = msg.sender;
items[sku].state = State.Sold;
emit LogSold(sku);
}

/* Add 2 modifiers to check if the item is sold already, and that the person calling this function
is the seller. Change the state of the item to shipped. Remember to call the event associated with this function!*/
function shipItem(uint sku)
public
sold(sku)
verifyCaller(items[sku].seller)
{
items[sku].state = State.Shipped;
emit LogShipped(sku);
}

/* Add 2 modifiers to check if the item is shipped already, and that the person calling this function
is the buyer. Change the state of the item to received. Remember to call the event associated with this function!*/
function receiveItem(uint sku)
public
shipped(sku)
verifyCaller(items[sku].buyer)
{
items[sku].state = State.Received;
emit LogReceived(sku);
}

/* We have these functions completed so we can run tests, just ignore it 🙂 */

function fetchItem(uint _sku) public view returns (string memory name, uint sku, uint price, uint state, address seller, address buyer) {
name = items[_sku].name;
sku = items[_sku].sku;
price = items[_sku].price;
state = uint(items[_sku].state);
seller = items[_sku].seller;
buyer = items[_sku].buyer;
return (name, sku, price, state, seller, buyer);
}

}

### push code to github for validation
>> git status
>> git add .
>> git commit -m “Supply Chain Exercise with answer”
>> git push

### Validate the answer https://travis-ci.com/github/CA-bootcamp-s19/supply-chain-exercise-farmountain

### Writing tests in solidity

reference: https://www.trufflesuite.com/docs/truffle/testing/writing-tests-in-solidity

revisit below:

  1. To understand the inheritance relationship of

a. Base Contract (Parent Contract)
b. Derived Contract (Child Contract)
c. Abstract contract
d. Interface
e. Libraries

  1. Components and elements of Smart Contracts

Solidity Cheatsheet and Best practices

### Web3

Additional Resources:

  1. A Warm Welcome to Web3 and the Future of the Internet
  2. Latest stable Javascript JSON-RPC API documentation (v 0.2x.x)
  3. Ethereum Web3.js library documentation v1.0

truffle
web3.js
ether.js

Revisit 8.1.1 & 8.1.2

### Truffle for Web

Revisit 8.2

### Integrating Web3 with React

Additional Resources:

  1. Truffle box React
  2. If React isn’t your thing – Truffle maintains a list of boxes that make getting started with Truffle and your favorite framework super easy. If you don’t see one that suits your needs, feel free to create you own!
  3. React & Ethereum: Getting Started with the minimum tool set Required: Part 1 of 4
  4. Free Webinar on Web3-react with Uniswap’s Ian Lapham

Revisit 8.3 & 8.3.1
Rimble UI

Rimble is a React component library that makes creating Web3 applications in react much easier. The library is under active development by the ConsenSys Design team.

This library is only useful if you choose to develop an application using React.
>> npm install –save rimble-ui styled-components

### To include a button
import React, { Component } from ‘react’
import { Button } from ‘rimble-ui’
class Example extends Component {
render () {
return (
<Button size={‘medium’}>
Click me!
</Button>
)
}
}

### Include a Metamask button
reference: https://rimble.consensys.design/compownents/rimble-ui/metamaskbutton/

### Display an address with a “copy” Button
reference: https://rimble.consensys.design/components/rimble-ui/EthAddress

### Add a ToastMessage
reference: https://rimble.consensys.design/components/rimble-ui/ToastMessage

### Programatically creating Ethereum addresses in Javascript
To revisit to find out the content

### Smart Contracts Pitfalls, Testing, and Debugging

  • Writing tests for Solidity smart contracts in Javascript and Solidity using the Truffle framework
  • Smart contract best practices
  • Smart contract exploits and dangers
  • Optimizing Gas
  • Go over a safety checklist of things to consider before deploying your contracts

Tests:

  • Unit Testing

Additional Resources:

  1. Writing Solidity tests in Truffle
  2. Writing Javascript tests in Truffle
  3. Testing for throws in Truffle Solidity tests
  4. How to catch Solidity errors in Truffle Javascript tests

Additional Resources:

  1. Original post on Ethereum stack exchange
  2. Easily add it to your project with Open Zeppelin Test Helpers

Additional Resources:

  1. Smart contract best practices
  2. Recommendations for Smart Contract Security in Solidity
  3. Common bugs, attacks and best practices
  4. Front-running
  5. Ethereum is a Dark Forest: A descriptive essay on frontrunning

### Exploits and Dangers

Re-entrancy (SWC-107) attacks can be problematic because calling external contracts passes control flow to them. The called contract may take over the control flow and end up calling the smart contract function again in a recursive manner.

// INSECURE
mapping (address => uint) private userBalances;

function withdrawBalance() public {
uint amountToWithdraw = userBalances[msg.sender];
require(msg.sender.call.value(amountToWithdraw)()); // At this point, the caller’s code is executed, and can call withdrawBalance again
userBalances[msg.sender] = 0;
}

Additional Resources:

  1. Known Attacks
  2. A survey of attacks on Ethereum smart contracts
  3. A list of known bugs from the Solidity docs
  4. Smart contract weaknesses
  5. Learn about these vulnerabilities by exploiting deployed test net contracts yourself with Ethernaut
  6. Solve challenges by exploiting vulnerabilities at the CaptureTheEther CTF
  7. An overview of known vulnerabilities with samples and how to fix them

Additional Resources:

SWC Registry

For a comprehensive, maintained list of smart contract weaknesses, along with test cases and examples of vulnerable smart contracts, check out the SWC Registry. This is a community maintained project and includes most, if not all of the well known vulnerabilities and hacks, with contract samples and suggestions for how to address weaknesses.

Additional Resources:

  1. Smart contract safety checklist
  2. Cross chain replay attacks
  3. Solidity Attack Vectors

A quick and easy way to check your Solidity code for common bugs is to use security analysis tools. Static analysis tools will parse your code and highlight potential security vulnerabilities.

Tools like SmartCheck will do static analysis on your code right in the browser. You can upload a Solidity (or Vyper) file from your computer, paste the code or import your GitHub repository.

Please note that all issues raised are not necessarily security vulnerabilities and static analysis tools will not catch every possible vulnerability.

Mythx

MythX is the premier security analysis API for Ethereum smart contracts. It detects many common Solidity and EVM bytecode vulnerabilities. This makes it attractive for developers and auditors alike. It can be used right away with integrations for Remix or Brownie, or from the system CLI. There are also libraries (https://docs.mythx.io/en/latest/building-security-tools/index.html#language-bindings) available as a starting point for building custom security tools such as IDE extensions and CI scripts.

Promo code = LEIzfJcp

Note: Truffle Plugin is being deprecated, although the steps below still work on some machines. For the authoritative “Getting Started” with MythX, please follow steps for MythX CLI here.

Steps to Get Started

  1. Go to https://mythx.io/
  2. Click the “sign up”button
  3. Complete the registration form.
  4. You will then have an option to choose a plan. Please select “Try MythX & Buy Scans” This will allow you to set up a MythX account with no charge.
  5. Go to the dashboard Billing tab click “Buy a pack of 3 scans today for $9.99
  6. Enter your promo code LEIzfJcp in the box provided and proceed through check with no charge

In this lesson we are going to use the MythX security plugin for Truffle Framework. Follow this link to see installation instructions for your machine. Be sure to add the correct configuration information to take full advantage of the free MythX features. MythX also requires that solc (the Solidity compiler) is installed. Reference the Solidity documentation for solc installation instructions.

Download this Truffle project containing a simple Coin.sol contract.

pragma solidity ^0.5.0;

contract Coin {
// The keyword “public” makes those variables
// readable from outside.
address public minter;
mapping (address => uint) public balances;

// Events allow light clients to react on
// changes efficiently.
event Sent(address from, address to, uint amount);

// This is the constructor whose code is
// run only when the contract is created.
constructor() public {
minter = msg.sender;
}

function mint(address receiver, uint amount) public {
require(msg.sender == minter, “Must be minter.”);
balances[receiver] += amount;
}

function send(address receiver, uint amount) public {
// require(balances[msg.sender] >= amount, “Insufficient funds”);
balances[msg.sender] -= amount;
balances[receiver] += amount;
emit Sent(msg.sender, receiver, amount);
}
}

Navigate to the project directory in the terminal and compile the contracts with truffle compile. Once the contracts have compiled, run truffle run verify to analyze the project contracts.

In this case, the output of MythX will be something like this:

mythxrelog.png

MythX is letting us know that there are 3 arithmetic operations in the contract that could potentially overflow/underflow in certain contract states and a warning. MythX points out the contract, the function where the potential vulnerability is, the line number of the file and the expression on that line.

Now, if we un-comment the require() statement in line 25 of Coin.sol and recompile the contract and run truffle run verify, our output will look something like this:

mythxrelog.png

Notice that the underflow error in line 26 is no longer present.

Alternatively MythX can also be used online, as a plugin in the new Remix editor as an additional plugin.

The process of developing and securing smart contracts is an incremental one. MythX will not catch every vulnerability, but it is definitely worth adding to your developer toolbox.

MythX vs Mythril

Mythril is a security analysis tool for EVM bytecode. The main difference between the two is that MythX is optimized for usability and covers a wider range of security issues while Mythril isn’t.

Along with several other tools that were developed in-house, Mythril is one of the analysis tools used the MythX project to deliver security reports.

** A special thanks to Ovidiu Voicu for helping update this lesson!**

Additional Resources

  1. MythX website
  2. Mythril
  3. Practical Smart Contract Security Analysis and Exploitation
  4. Slither, a Solidity source code analyzer
  5. Smart Check
  6. All Ethereum Security Tools Built by ConsenSys Diligence
  7. Awesome MythX Smart Contract Security Tools
  8. MythX Security Analysis Plugin for Truffle Framework

TxOrigin Attack (SWC-115)

In this lesson we are going to cover a tx.origin attack. The global variable tx.origin in Solidity always references the address of the original sender of the transaction, of the full call chain. See the reference in the docs here. This is different than message.sender in that message.sender references the address of the sender of the current call.

You should never use tx.origin in Solidity for authorization (SWC-115). The following smart contract shows you why. It is susceptible to attack.

pragma solidity >0.5.0;
// Example Tx.Origin Authentication Attack
contract VulnerableContract {
address payable owner = msg.sender;

function withdraw(address payable _recipient) public {
require(tx.origin == owner);
_recipient.transfer(address(this).balance);
}

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

function() external payable {}
}
contract MaliciousContract {
VulnerableContract vulnerableContract = VulnerableContract(0x08970FEd061E7747CD9a38d680A601510CB659FB);
address payable attackerAddress = 0xdD870fA1b7C4700F2BD7f44238821C26f7392148;

function() external payable {
vulnerableContract.withdraw(attackerAddress);
}
}

In this contract, if the creator of the VulnerableContract is tricked into calling the MaliciousContract, the Malicious contract will be able to drain the VulnerableContract of all funds.

Additional Resources:

  1. Solidity documentation on the security considerations of tx.origin
  2. The SWC Registry entry for Authorization through tx.origin

This set of contracts shows what a reentrancy attack (https://swcregistry.io/docs/SWC-107) looks like.

pragma solidity 0.5.2;
// Example Reentrancy Attack
contract VulnerableContract {
mapping(address => uint) public balances;

function deposit() public payable {
require(msg.value > 1);
balances[msg.sender] += msg.value;
}

function withdraw(uint _amount) public {
require(balances[msg.sender] >= _amount, “Not enough balance!”);
msg.sender.call.value(_amount)(“”);
balances[msg.sender] -= _amount;
}

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

function() payable external {}
}
contract MaliciousContract {
VulnerableContract vulnerableContract = VulnerableContract(0x08970FEd061E7747CD9a38d680A601510CB659FB);

function deposit() public payable {
vulnerableContract.deposit.value(msg.value)();
}

function withdraw() public {
vulnerableContract.withdraw(1 ether);
}

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

function () payable external {
if(address(vulnerableContract).balance > 1 ether) {
vulnerableContract.withdraw(1 ether);
}
}
}

This contract shows what an integer overflow vulnerability (https://swcregistry.io/docs/SWC-101) looks like.

In this VulnerableContract the lockTime is manipulable by the currentInvestor. The maximum value for the lockTime is 4294967295 because it is declared type uint32 (and 2^32 = 4294967296). If the currentInvestor attempts to set the value above 4294967295, it will overflow and start counting back at 0.

pragma solidity ^0.5.0;
// Example Integer Overflow and Underflow
contract VulnerableContract {
uint MINIMUM_INVESTMENT = 50 ether;
uint32 INITIAL_LOCK_TIME = 2592000; // 30 days in seconds
address payable currentInvestor;
uint investmentTimestamp;
uint32 public lockTime = INITIAL_LOCK_TIME;
function increaseLockTime(uint32 _seconds) public {
require(msg.sender == currentInvestor);
lockTime += _seconds; // uint32 max is 4294967295 seconds. Attack passing 4292375295
}

function invest() public payable {
require(currentInvestor == address(0));
require(msg.value >= MINIMUM_INVESTMENT);
currentInvestor = msg.sender;
investmentTimestamp = now;
}

function withdrawWithProfit() public {
require(msg.sender == currentInvestor);
require(now – investmentTimestamp >= lockTime);
uint profit = 1 ether + lockTime * 1 wei;
currentInvestor.transfer(MINIMUM_INVESTMENT + profit);
currentInvestor = address(0);
lockTime = INITIAL_LOCK_TIME;
}

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

function() external payable {}
}

This type of attack is easily avoidable by using a SafeMath library such as this, that provides safety checks and will revert on error.

MythX is a smart contract security service for Ethereum. As part of the bootcamp, we have gotten a free pack of three scans for every student from the ConsenSys MythX team.

Promo code = LEIzfJcp

Steps to Get Started

  1. Go to https://mythx.io/
  2. Click the “sign up”button
  3. Complete the registration form.
  4. You will then have an option to choose a plan. Please select “Try MythX & Buy Scans” This will allow you to set up a MythX account with no charge.
  5. Go to the dashboard Billing tab click “Buy a pack of 3 scans today for $9.99
  6. Enter your promo code LEIzfJcp in the box provided and proceed through check with no charge

Welcome to Module 10: Ethereum Advanced Topics

In this module we will cover:

  • Common Smart contract design patterns
  • Designing upgradable smart contract systems
  • What are Oracles, and how do you use one?
  • Using the Ethereum Name Service
  • An introduction to IPFS
  • Formal Verification and smart contracts

In this lesson we will go over some of the most common design patterns that developers use when writing smart contracts.

Fail early and fail loud

//Bad code, do not emulate

function silentFailIfZero(uint num) public view returns (uint){
if(num != 0){
return num;
}
}
This function will fail without throwing an exception. This is a bad practice because it is not immediately clear whether the function executed properly or not.
function throwsErrorIfZero(uint num) public view returns (uint){
require(num != 0);
return num;
}

This function checks the condition required for execution as early as possible in the function body and throws an exception if the condition is not met. This is a good practice to reduce unnecessary code execution in the event that an exception will be thrown.

Restricting Access

You cannot prevent people or computer programs from reading your contracts’ state. The state is publicly available information for anyone with access to the blockchain.

However, you can restrict other contracts’ access to the state by making state variables private.

contract C1 {

uint private internalNum;

}

You can restrict function access so that only specific addresses are permitted to execute functions.

This is useful for allowing only designated users, or other contracts to access administrative methods, such as changing ownership of a contract, implementing an upgrade or stopping the contract.

contract Admin {

mapping(address => bool) admins;

modifier onlyAdmin {
require(admins[msg.sender] == true);
_;
}

function addAdmin(address _a)
public
onlyAdmin
returns(bool)
{
admins[_a] = true;
return true;
}

}

It can be useful to restrict function access to owners, a more general admin class or to any stakeholder in the system.

Here is an overview of access control on OpenZeppelin.

Auto Deprecation

The auto deprecation design pattern is a useful strategy for closing contracts that should expire after a certain amount of time.

This can be useful when running alpha or beta testing for your smart contracts.

Remember that using timestamps such as the now keyword are subject to manipulation by the block miners in a 30-second window.

pragma solidity ^0.4.25;

contract Autodeprecate {
uint contract_expired;

modifier is_active {
if(!expired()) _;
}

modifier when_deprecated {
if(expired()) _;
}

constructor(uint duration) {
contract_expired = now + duration;
}

function expired()
view
public
returns(bool)
{
return now > contract_expired ? true : false;
}
}

Mortal

Link to Ownable.sol.

pragma solidity ^0.5.0;

import “./Ownable.sol”;

contract Mortal is Ownable {

function kill()
{
if(msg.sender == owner()) selfdestruct(address(uint160(owner()))); // cast owner to address payable
}

}

Implementing the mortal design pattern means including the ability to destroy the contract and remove it from the blockchain.

You can destroy a contract using the selfdestruct keyword. The function to do it is often called kill.

It takes one parameter which is the address that will receive all of the funds that the contract currently holds.

As an irreversible action, restricting access to this function is important.

Pull over Push Payments (also known as the Withdrawal Pattern)

Navigate to this fund splitter contract on Github.

There are a few key takeaways from this contract.

First, There is a separation of function logic. The split() function handles the accounting and divides the msg.value sent with the transaction. Another function, withdraw(), allows accounts to transfer their balance from the contract to their account.

This pattern is also called the withdrawal pattern. It protects against re-entrancy and denial of service attacks that we will cover in the next lesson.

Circuit Breaker

Circuit Breakers are design patterns that allow contract functionality to be stopped. This would be desirable in situations where there is a live contract where a bug has been detected. Freezing the contract would be beneficial for reducing harm before a fix can be implemented.

Circuit breaker contracts can be set up to permit certain functions in certain situations. For example, if you are implementing a withdrawal pattern, you might want to stop people from depositing funds into the contract if a bug has been detected, while still allowing accounts with balances to withdraw their funds.

contract CircuitBreaker {

bool public stopped = false;

modifier stopInEmergency { require(!stopped); _; }
modifier onlyInEmergency { require(stopped); _; }

function deposit() stopInEmergency public { … }
function withdraw() onlyInEmergency public { … }
}

In a situation such as this, you would also want to restrict access to the accounts that can modify the stopped state variable, maybe to the contract owner (such as multisig wallet) or a set of admins.

State Machine

Contracts often act as a state machine, where the contract has certain states in which it behaves differently and different functions can and should be called. A function call often ends a stage and moves the contract to the next stage (especially if the contract models interaction). It is also common that some stages are automatically reached at a certain point in time.

The Colony token weighted voting protocol implemented this design pattern to manage the poll state.

Admins can only add poll options in the poll creation stage. Votes can only be submitted when the poll was active. The poll can only be resolved after the poll close time has been reached.

Speed Bump

Speed bumps slow down actions so that if malicious actions occur, there is time to recover.

pragma solidity ^0.4.25;

contract SpeedBump {

uint allowedTime;

modifier allowed_every(uint _time){
if(now > allowedTime){
_;
allowedTime = now + _time;
}
}

constructor(uint duration){
allowedTime = 0;
}

function setAllowedTime(uint _time)
public
returns(bool)
{
allowedTime = now + _time;
return true;
}

}

For example, “The DAO” contract required 27 days between a successful request to split the DAO and the ability to do so. This ensured the funds were kept within the contract, increasing the likelihood of recovery.

Additional Resources:

Additional Resources:

  1. ENS website
  2. ENS documentation
  3. Top level domain .luxe will resolve Etheruem addresses
  4. ENS Migration Feb 2020
  5. ENS Migration V1 > V2 Post-Mortem (upgrade from LLL to Solidity)
  6. ENS + Emoji Combo (fun project) 2019

Key points:

  • IPFS stand for the Inter-planetary file system
  • Hashes in IPFS start with “Qm…”
  • The js-ipfs library allows you to use IPFS without having to run a local IPFS node
  • It aims to replace HTTP by addressing file content (with hashes) rather than file locations
  • It uses p2p protocols, making it a decentralized network
  • It complements blockchain nicely, as it allows immutable, off-chain data storage
  • Other benefits include bandwidth saving for servers, potential content availability improvements, censorship and deletion resistance and data deduplication

Additional Resources:

  1. IPFS
  2. IPFS Demo
  3. IPFS Docs
  4. How IPFS Works

Additional Resources:

  1. Software Engineering techniques – ConsenSys
  2. Upgradability in an Immutable World
  3. Summary of Ethereum Upgradeable Smart Contract R&D
  4. Diamond Contracts — interesting variation on upgradability patterns

Additional Resources:

  1. Provable Things Walkthrough
  2. Provable Things Documentation
  3. Provable Things Examples

What are Oracles? A Beginner’s Guide

Back in ancient times, an oracle was someone who offered advice or a prophecy thought to have come directly from a divine source. In the context of blockchain, oracles are an industry term for an information source that delivers real world data to smart contracts on a blockchain.

Blockchains have numerous incredible and powerful features, but they are inherently a separate system not connected to the real world. Blockchains keep a ledger of the transactions of its nodes, while data in the real world can be posted by anyone, at anytime. This is problematic as almost everything we want to do with blockchains will require interfacing with the real world, and the oracle often provides the information that triggers smart contract execution.

For example, suppose Alice and Bob bet $10 on a basketball game. Alice thinks team A will win and Bob bets on team B. They decide to do this bet on a blockchain to use its security and immutability benefits to ensure the losing side pays up. Both deposit their money into a smart contract, and code logic is written to payout the winner. On the day of the game, team A wins but the smart contract has no way of knowing this. An oracle must inform the smart contract of this result for Alice to be paid. Here, the smart contract required information on the outcome of a basketball game, and this information triggered the payout.

Oracles are extremely important as they must be a source of truth for the smart contract. The delivery of false information could have drastic consequences. In our example, if the oracle is not secure and Bob is able to tamper with the oracle, he can instead have the oracle deliver data saying team B won instead. This failure from the security of the oracle would result in Alice losing the bet, despite all the security promises provided by a blockchain system.

Thus, oracle providers must ensure truthfulness of the data provided. First off, the real world data must be obtained from a trusted place. There is no blockchain system to guarantee data accuracy, so this data is often obtained from a trusted and verified source. For example, the oracle could obtain the basketball match results from the NBA website. This is usually cross checked with additional sources, such as verified news networks. Finally, the oracle should also provide proof that the data has not been tampered with, either by external parties, or the oracle service provider itself.

As oracles are a crucial component of most dapps, it is important for developers to keep potential oracle failures in mind – the consequences, and how to prevent them.

This in depth tutorial is designed to walk you through the process of building your first dapp using a Rhombus oracle. It will guide you step by step on how to incorporate real world data into your smart contracts with the Rhombus Lighthouse Delivery method. You will learn how to interact with existing Lighthouses on Rinkeby in your smart contracts, and how to perform local testing of Lighthouses using Truffle and a local Ganache chain.

GitHub

You can view the project tutorial here.

There is a dire need for more secure methods of smart contract development within the blockchain community.

There have been hundreds of millions of dollars worth of crypto assets lost or stolen due to insecure smart contracts, and there are thousands of smart contracts on the blockchain with known vulnerabilities.

Part of the problem is due to the current state of developer tools and programming languages such as Solidity.

The goal is to make writing secure smart contracts as easy and accessible as possible. One route to this goal is via formal verification.

From Wikipedia, formal verification is the act of proving or disproving the correctness of intended algorithms underlying a system with respect to a certain formal specification or property, using formal methods of mathematics.

Said another way, it is a way to prove that a program is correct for all inputs. This can ensure that a hacker cannot modify the contract to an unintended state.

Using formal verification, smart contract proofs can be checked by machines. Efficient formal verification requires specific programming languages and features that are not currently present in the Ethereum ecosystem. Due to the nature of its analysis tools, MythX is also able to formally verify smart contracts. This guide gives more details on how to formally verify a smart contract in Remix using the MythX analysis API.

Read more about formal verification as it applies to computer science more generally on Wikipedia.

Related Posts