Email: zach@zfadd.is
Social: @zacharius@refactorcamp.org
Git: github.com | git.zfadd.is

ZacharyFaddis

Dec. 20, 2018, 10:08 p.m.

Diving Into Ethereum Smart Contracts

Introduction

Lately I’ve been diving into the world of Ethereum development and creating some toy smart contracts in preparation of a much larger endeavor I have in mind.

I figured I’d make a blog post showcasing the contracts I’ve made and the tools I used to create them. In the hopes of possibly getting others up to speed faster and with less headaches in the future.

The contracts

Here I’m going to describe the contracts I made and show the code for how they are implemented. I’ve also written tests to prove basic functionality that you can see be looking at the source code in my repo.

I am confident that these contracts work as intended but can’t guarantee that they are secure or can’t be cheated in some way by a malicious actor. I think they could be used for small values or in scenarios where you trust all parties to act in good faith but I wouldn’t use them for anything more serious until they’re looked at by someone with more experience.

Payment contract: Invoice

My first foray into smart contracts is a simple invoice contract. It allows someone, the Originator, the issue an invoice to another, the Debtor.

The debtor can make query the contract to see how much he owes and make partial payments until he pays the original amount in full. If he overpays he can collect that money back as a refund.

The Originator can collect however much the debtor has paid so far, until he has collected the original amount.

pragma solidity ^0.4.0;

contract invoice {

  address public originator;
  address public payer;
  uint public og_owed;
  uint public owed;
  string public invoice_name;

  uint public refund = 0;
  uint public collected = 0;

  

  constructor(
              string _invoice_name,
              address _payer,
              uint _amount_owed
              )public {
    originator = msg.sender;
    payer = _payer;
    invoice_name = _invoice_name;
    owed = _amount_owed;
    og_owed = owed;
  }

  function pay() public payable {

    //payment must be from deptor
    require(
            msg.sender == payer,
            'This weight is not yours to bear');


    if(msg.value > owed) {
      refund = msg.value - owed;
      collected = owed;
      owed = 0;
    }else {
      collected += msg.value;
      owed -= msg.value;
    }



   }


  function collect() public {
    if (msg.sender == originator &&
        collected > 0) {
      uint amount = collected;
      collected = 0;
      originator.transfer(amount);
    }

    if (msg.sender == payer &&
        refund > 0) {
      amount = refund;
      refund = 0;
      payer.transfer(amount);
    }
  }

   
}


              
  

Gambling contract: Bet

My most complicated contract by far, and the one I’m most proud of.

This is a contract to allow two people to bet on something and for the outcome of the bet to be determined by a panel of predefined judges.

initation

the contract creator will specify a number of criteria to make the bet.

  • who he is betting against
  • the amount being bet,
  • a short string defining the bet,
  • a list of judges,
  • a future date defining the deadline for judge’s to cast their vote
  • the judge consensus threshold needed to determine a winner

confirmation

the person being challenged to the bet has 24 hours to send an amount equal to the initiating bet. Once this has been done the bet will be considered confirmed and neither party can retract their bet.

The challenged can pay partially, allowing the payment to be split into multiple chunks. If he overpays, he will be refunded the difference.

During the confirmation period, either party can choose to retract their bet. In this event both parties will be refunded however much they have put in so far and the contract will be considered complete.

judgment

After the confirmation period, all judges listed will be able to vote to determine the winner. Judges have 3 choices

  • challenged
  • challenger
  • hung

By default the judges’ vote will be set to hung, which means that neither party should win. They have till the judgment deadline determined in the contract initiation to cast their vote. A judge’s vote can be changed at any time before the deadline

decision

At the judgment deadline all votes will be tallied. If their are enough votes toward either party to cross the specified threshold, all collected money will go towards the winning party. If neither party gets enough votes, the bet will be considered hung and both parties will be able to collect their money back.

source code

pragma solidity >= 0.5.0;


contract Bet {
  address public initiator;
  address public challenged;
  address[] public judges;

  enum Vote { Null, Initiator, Challenged, Hung }
  mapping(address => Vote) public votes;

  string public bet_name;

  uint public bet;
  uint public matched = 0;

  //number between 0 and 100, inclusive
  //decides vote threshold needed to declare winner
  uint public threshold;

  uint public owed_initiator = 0;
  uint public owed_challenged = 0;

  //times expressed as seconds since unix epoch
  uint public creation_time = now;
  uint public judgement_deadline;
  uint public confirmation_deadline = creation_time + 1 days;

  event Voted(address judge, Vote vote);
  event stateChange(State state);
  event Owed(address owed, uint amount);
  event Test(uint t);

  enum State { Confirmation, Judgement, Complete }
  State public state;

  enum Conclusion { Undecided, Initiator, Challenger, Hung }
  Conclusion public winstate = Conclusion.Undecided;

  //check the time to ensure we are in the correct state
  modifier checkState {
    uint time = now;

    if (time > confirmation_deadline && state==State.Confirmation) {
      state = State.Judgement;
      emit stateChange(state);
    }

    if (time > judgement_deadline && state==State.Judgement) {
      state = State.Complete;
      emit stateChange(state);
    }

    _;
      
  }

  constructor (string memory _bet_name,
              address _challenged,
              address[] memory _judges,
              uint _threshold,
              uint _deadline) public payable {

    require(_deadline > confirmation_deadline,
            'deadline must be more than 24 hours into the future');
    
    require(_threshold <= 100,
            'threshold cant be greater than 100');

    require (_judges.length >= 1,
             'There must be atleast 1 judge');
    
    bet_name = _bet_name;
    bet = msg.value;
    challenged = _challenged;
    initiator = msg.sender;
    threshold = _threshold;
    judgement_deadline = _deadline;
    judges = _judges;

    for(uint i=0; i<_judges.length; i++) {
      votes[_judges[i]] = Vote.Hung;
    }

    state = State.Confirmation;
    emit stateChange(state);
  }

  //allow challenged to match bet of initiator
  function matchBet() public payable checkState {

    require(msg.sender == challenged,
            'you have not been challenged');
    require(state == State.Confirmation,
            'We are not in the confirmation stage');

    matched += msg.value;

    if(matched > bet) {
      owed_challenged = matched - bet;
      emit Owed(challenged, owed_challenged);
      matched = bet;
    }

    if(matched == bet) {
      state = State.Judgement;
      emit stateChange(state);
    }
  }

  //allow initiator and challenged to collect any owed amount
  function collect() public checkState {
    uint amount = 0;

    if(msg.sender == challenged &&
       owed_challenged > 0){
      amount = owed_challenged;
      owed_challenged = 0;
      msg.sender.transfer(amount);
    }

    if(msg.sender == initiator &&
       owed_initiator > 0){
      amount = owed_initiator;
      owed_initiator= 0;
      msg.sender.transfer(amount);
    }
  }


  //allow initiator or challenged to retract bet during confirmation
  function retract() public checkState {
    require(msg.sender == initiator || msg.sender == challenged,
            'you cannot retract this bet');
    require(state == State.Confirmation,
            'it is too late to turn back');

    state = State.Complete;
    winstate = Conclusion.Hung;
    emit stateChange(state);

    owed_initiator = bet;
    if(owed_initiator > 0){
      emit Owed(initiator, owed_initiator);
    }

    owed_challenged = matched;
    if(owed_challenged > 0){
      emit Owed(challenged, owed_challenged);
    }
  }

  //allow judges to vote
  function castVote(uint int_vote) public checkState {
    require(votes[msg.sender] != Vote.Null,
            'Only judges can vote');
    require(state == State.Judgement,
            'It is not yet the time of reckoning');

    Vote vote = Vote(int_vote);

    votes[msg.sender] = vote;
    emit Voted(msg.sender, vote);
  }

  function conclude() public checkState {
    require(state == State.Complete,
            'Your fate is still being decided on');
    require(winstate == Conclusion.Undecided,
            'This contract has concluded');
    
    uint init_votes = 0;
    uint chall_votes = 0;

    bool init_threshold = false;
    bool chall_threshold = false;

    for(uint i=0; i<judges.length; i++){
      if(votes[judges[i]] == Vote.Initiator) {
        init_votes += 1;
      }
      else if(votes[judges[i]] == Vote.Challenged){
        chall_votes += 1;
      }
    }

    emit Test(init_votes);
    emit Test(chall_votes);

    if( (init_votes/judges.length) > (threshold/100) ){
      init_threshold = true;
    }

    if( (chall_votes/judges.length) > (threshold/100) ){
      chall_threshold = true;
    }

    if(init_threshold != chall_threshold){
      if(init_threshold == true) {
        winstate = Conclusion.Initiator;
        owed_initiator += bet*2;
      }else if(chall_threshold == true) {
        winstate = Conclusion.Challenger;
        owed_challenged += bet*2;
      }
    }else{
      winstate = Conclusion.Hung;
      owed_initiator += bet;
      owed_challenged += bet;
    }

    state = State.Complete;

    emit Owed(initiator,owed_initiator);
    emit Owed(challenged, owed_challenged);
    emit stateChange(state);

  }

  //force change state, for testing purposes only
  //ensure is commentted out before deploying contract for realsies
  function changeState(State _state) public {
    state = _state;
  }

  

}
   

Judge interface and contract: Simple Judge

I wanted to make it easy to create robo judges to interact with my betting contract so I made an extremely simple judge interface. To implement the interface, all you need is a smart contract with a function, castVote(), which accepts an address to send the vote to. This function should then make its decision and send the vote to the address given.

I made a simple judge that implemented the judge interface. When it receives a castVote request it will check the time and decide who it will side in favor of depending on whether the time is even or odd.

Judge Interface

pragma solidity >= 0.5.0;

import './bet.sol';

interface Judge {

  enum Vote { Null, Initiator, Challenged, Hung }

  function castVote (Bet toContract) external returns (Vote vote);
}   

Simple Judge

pragma solidity 0.5.0;

import './judge_interface.sol' ;
import './bet.sol' ;
import "./oraclizeAPI.sol";


contract Simple_Judge is Judge {


  function castVote(Bet bet_contract) external returns (Vote vote) {
    if (block.timestamp % 2 == 0){
      vote = Vote.Initiator;
    }
    else {
      vote = Vote.Challenged;
    }
    bet_contract.castVote(uint(vote));
    return vote;
  }

}
   

The Tools

My goal here is to provide a roadmap of the quickest route to getting started making things using Blockchain and Smart Contracts. Below is what I found the be the most supported and well documented tools. Things change rapidly in this space and I can only say that this is what I found to be the best tools at the time of this writing.

The Platform: Ethereum

If you are new to the world of blockchain based coins and platforms you have likely only heard of two technologies: Ethereum and Bitcoin.

Bitcoin is strictly a currency. It has a very limited language that allows for basic smart contract functionality, but it really isn’t good for anything more complicated than requiring multiple people’s approval to approve a transaction. It is the first real use of blockchain, is truly revolutionary, and has many use cases, but if your a developer trying to making something complex and interesting with Smart Contracts, I don’t recommend Bitcoin.

Ethereum is a little different. It technically has a currency, Ether, but it basically serves as just a medium of exchange to fuel its true purpose. That being a global computer in which the code of every smart contract is stored and executed on multiple computers across the network, ensuring a consensus is reached before payments are sent. Imagine if all laws and contracts were coded into this network, and all matters decided by the consensus of the network instead of being adjudicated by lawyers and courts. That’s basically the promise of Ethereum. It supports much more complicated smart contracts and allows developers to build some pretty interesting things.

There are several platforms and coins out there that allow you to make smart contracts at various levels of complexity but Ethereum is by far the most mature platform out there and allows the greatest freedom in what you can build with their smart contracts.

Ethereum Foundation

The Contract Language: Solidity

Solidity is the main contract language for Ethereum Smart Contracts and maintained by Ethereum. It was based off JavaScript and has many of the same conventions and syntax.

There is another Smart Contract language developed by Ethereum, Vyper. This one is based off Python. From my understanding it is not nearly as well developed or supported, at least at time of writing.

Solidity Docs

The Ethereum API: Web3.js

Web3.js is the JavaScript API used to interact with an Ethereum network.

While the contracts themselves will be written in Solidity, you will need to interact with them in another language. Web3.js allows you to create and interact with smart contracts and to query information about the network.

There is also a Web3.py library for Python, but there is a larger community around the JS library. Mainly because most people are trying to build something to be used through a browser and for that you’ll need JavaScript.

Web3.js docs

The Framework: Truffle

Truffle seems to be the most mature framework for developing smart contracts and to have the largest community. Has tools to help you develop, test, and deploy your contracts. Also has a library that acts as an abstraction layer on top of Web3.js that makes it simpler to interact with your contracts.

It should be noted that Truffle is not maintained by Ethereum but it is an open source project.

Truffle Docs

The Test Network: Ganache

Built by the same organization that maintains Truffle, Ganache gives you your own private network that you solely control and allows you to test and inspect how your contract will act without having to spend any gas or waiting for transactions to be confirmed.

Ganache Homepage/Download

George Martin Jr

March 4, 2019, 9:01 p.m.

Hello there, My name is George, and I was wondering if you would like to have your website zfadd.is promoted as a resource on my blog georgemartjr.com ? We are updating our broken link resources to include up to date resources for our readers. Our resource links are manually approved as a do follow link. If you are interested in having your site included as a resource on our blog, please let me know. Thanks for your consideration, George

Estelle Milne

March 24, 2019, 6:36 a.m.

Hi I had visited your store last week, and I saw a very nice toy i wanne buy. But I have a question, today I wanted to order it, but can not find the toy anymore in your store. it looks like the first picture on this site http://bit.ly/Picturetoy7225 Mail me if you are going to sell it again. I hope soon so that I can place an order. I'll wait. Sincerely

Belen Minton

April 21, 2019, 12:44 a.m.

Hello I regularly order from your shop, and I love your store. But I have a question, I see a lot of Items on this site http://bit.ly/CheaperProducts that you also sell. but there products are 40% cheaper, well my question is what is the difference between your shop and theirs, is it the quality or something else, I hope you can answer my question. greetings

Osvaldo Berg

April 21, 2019, 1:56 a.m.

Hello I had visited your store last month, and I saw a verry nice item i wanne buy. But I have a question, today I wanted to order it, but can not find the item anymore in your store. it looks like the first picture on this site http://bit.ly/FotoProduct8293 Mail me if you are going to sell it again. I hope soon so that I can place an order. I'll wait. Sincerely

Uta Vanover

May 4, 2019, 8:53 p.m.

Protect Your Loved Ones on the Roads - A Must for Every Car Owner These Roadside Safety Discs can be seen from over 5000 feet by oncoming motorists. Protect yourself and your family in all emergency situations, simply activate each light with a single click. Special Price - http://bit.ly/2LpxYPm

Noble Walthall

May 10, 2019, 9:41 p.m.

How would you like to Upload A SINGLE Video And RANK for 100 LANGUAGES !!! FACT #1 ONLY 25% of the searches made online are in ENGLISH! And yet everybody focuses on trying to rank in ENGLISH! FACT #2 YouTube is the 2nd BIGGEST website in the world… And still you focus all your efforts trying to rank and get traffic ONLY from Google! http://bit.ly/2PVgtFh DO THE MATH: With Over 3 Billion Searches A Month… All the visitors that you will ever need ARE ALREADY ON YOUTUBE! 3 billion searches a month. 75% are not in English… Do the math… 2.2 billion searches each month in foreign languages! Are you getting an idea on how much money you are leaving on the TABLE? http://bit.ly/2PVgtFh

Margarette Glauert

May 21, 2019, 7:23 p.m.

Hello I regularly order from your shop, and I love your store. But I have a question, I see a lot of Items on this site http://bit.ly/CheaperProducts that you also sell. but there products are 40% cheaper, well my question is what is the difference between your shop and theirs, is it the quality or something else, I hope you can answer my question. Sincerely

Aly Chiman

May 26, 2019, 4:31 a.m.

Hello there, My name is Aly and I would like to know if you would have any interest to have your website here at zfadd.is promoted as a resource on our blog alychidesign.com ? We are updating our do-follow broken link resources to include current and up to date resources for our readers. If you may be interested in being included as a resource on our blog, please let me know. Thanks, Aly

Jacques Pruitt

May 27, 2019, 3:10 p.m.

Provably Fair Gaming, 0.5% House Edge https://crashdice.com

Rene Paulk

June 11, 2019, 7:20 a.m.

Hello i like your webshop, But I have a question, I see a lot of Items in this webshop http://bit.ly/CheaperItem19 that you also sell in your store. but there items are 36% cheaper, well my question is what is the difference between your store and theirs, is it the quality or something else, I hope you can answer my question. greetings

Rory Seifert

June 27, 2019, 3:43 a.m.

Hi As I promised at lunch last week, here a photo of the woman you asked for in the office. http://bit.ly/Pictureofficewomen please don't tell anyone that you have the picture of me. Thank you

Denslemo

July 30, 2019, 7:12 a.m.

<a href="https://cafergot1.com/">cafergot internet pharmacy</a>

Denslemo

July 31, 2019, 6:48 p.m.

<a href="https://cafergot1.com/">cafergot</a>

Denslemo

Aug. 2, 2019, 4:28 a.m.

<a href="https://cafergot1.com/">cafergot</a>

Denslemo

Aug. 3, 2019, 2:43 p.m.

<a href="https://cafergot1.com/">cafergot</a>

Denslemo

Aug. 4, 2019, 11:20 p.m.

<a href="https://cafergot1.com/">generic cafergot</a>

Denslemo

Aug. 6, 2019, 7:54 a.m.

<a href="https://cafergot1.com/">cafergot internet pharmacy</a>

Denslemo

Aug. 7, 2019, 11:01 p.m.

<a href="https://cafergot1.com/">cheap cafergot</a>

canadian pharmacies shipping to usa

Aug. 8, 2019, 7:19 p.m.

<a href="http://canadianpharmaciesoffer.com/">online pharmacies canada</a> http://canadianpharmaciesoffer.com/ <a href=http://canadianpharmaciesoffer.com/>canadian online pharmacies</a>

Denslemo

Aug. 9, 2019, 9:57 a.m.

<a href="https://cafergot1.com/">cafergot</a>

Denslemo

Aug. 10, 2019, 6:27 p.m.

<a href="https://cafergot1.com/">cafergot</a>

Denslemo

Aug. 12, 2019, 4:55 a.m.

<a href="https://cafergot1.com/">cafergot internet pharmacy</a>

mipscupt

Aug. 12, 2019, 10:31 p.m.

Cialis online overnight <a href="http://cialisndbrx.com/#">buy cialis online</a> online buy tadalafil <a href="http://cialischmrx.com/#">buy cheap cialis online</a> order generic cialis india <a href="http://cialischbrx.com/#">buy generic cialis online</a> buy cialis online usa <a href="http://cialisdbrx.com/#">buy cheap cialis online</a> viva viagra <a href="http://chviagranrxusa.com/#">buy generic viagra online</a>

Denslemo

Aug. 13, 2019, 1:48 p.m.

<a href="https://cafergot1.com/">cafergot medication</a>

Denslemo

Aug. 14, 2019, 10:47 p.m.

<a href="https://cafergot1.com/">cafergot online</a>

Denslemo

Aug. 16, 2019, 6:58 a.m.

<a href="https://cafergot1.com/">cafergot</a>

Denslemo

Aug. 17, 2019, 4:35 p.m.

<a href="https://cafergot1.com/">cafergot</a>