Skip to content

Instantly share code, notes, and snippets.

@jklepatch
Last active February 28, 2023 20:23
Show Gist options
  • Star 17 You must be signed in to star a gist
  • Fork 7 You must be signed in to fork a gist
  • Save jklepatch/09c8b427df57e4d45cbfe27b7c7c3760 to your computer and use it in GitHub Desktop.
Save jklepatch/09c8b427df57e4d45cbfe27b7c7c3760 to your computer and use it in GitHub Desktop.
Bonus 1: Useful Solidity snippets - Blockchain Masterclass
## Safe division and multiplication to avoid underflow / overflow
import "github.com/OpenZeppelin/zeppelin-solidity/contracts/math/SafeMath.sol";
contract MyContract {
using SafeMath for uint;
uint a;
uint b;
...
//Now you can do:
a.add(b);
a.div(b);
}

Test that string is empty

if(bytes(stringVar).length === 0) {...}

Concatenate 2 strings

bytes memory b;

b = abi.encodePacked("hello");
b = abi.encodePacked(b, " world");

string memory s = string(b);

Alternative method - need to compare which one is more gas efficient:

import "github.com/Arachnid/solidity-stringutils/strings.sol";

contract C {
  using strings for *;
  string public s;

  function foo(string s1, string s2) {
    s = s1.toSlice().concat(s2.toSlice());
  }
}

Represent a collection of data

struct Users {
  uint id;
  string name;
}
User[] users;
uint nextUserId;

Return array

With ABIEncoderV2 (good for production in Solidity 0.6):

pragma experiemental ABIEncoderV2;

struct User {...}
User[] users;

function getUsers() returns (User[] memory) {
  return users;
}

Without ABIEncoderV2:

pragma experiemental ABIEncoderV2;

struct User {
  uint id; 
  string name
}
User[] users;
uint nextUserId;

function getUsers() returns (User[] memory) {
  uint[] memory userIds = new uint[](users.length);
  string[] memory userNames = new string[](users.length);
  for(uint i = 0; i < users.length; i++) {
    userIds[i] = users[i].id;
    userNames[i] = users[i].name;
  }
  return (userIds, userNames);
}

Removing array elements without holes:

pragma solidity ^0.6.0;

contract MyContract {
  string[] public data;

  constructor() public {
    data.push("John");
    data.push("Bruce");
    data.push("Tom");
    data.push("Bart");
    data.push("Cherry");
  }

  function removeNoOrder(uint index) external {
    data[index] = data[data.length - 1];
    data.pop();
  }

  function removeInOrder(uint index) external {
    for(uint i = index; i <  data.length - 1; i++) {
      data[i] = data[i + 1];
    }
    data.pop();
  }
}

Represent a collection of data

//Easier to access a specific element, harder to iterate compared to array method

struct Users {
  uint id;
  string name;
}
mapping(uint => User) users;
uint nextUserId;

2 ways to create a struct

//Method 1

struct User {
  uint id;
  string name;
}
...
User memory user = User(1, "James");

//Method 2

User memory user = User({id: 1, name: "James"}); //parameters can be out-of-order

Struct with nested mapping

How to create a new struct and put it in a mapping of struct?

Struct User {
  uint id;
  string name;
  mapping(uint => true) isOwnerOf;
}
mapping(uint => users);
...
//cannot do this as `memory` mapping are not possible
User memory user = User(..., mapping(1 => true));
users[0] = user;

//Instead, have to leverage the fact that its possible to access any mapping entry, including non-existing one:
users[0].id = 0;
users[0].name = "James";
users[0].isOwnerOf[10] = true;

Generate a Hash:

bytes32 hash = keccak256(abi.encodePacked(varA, varB, varC));

Generate a random number:

uint nonce;
function generateRandom(uint modulo) public returns(uint) {
  uint random = uint(keccak256(abi.encodePacked(now, msg.sender, nonce))) % modulo;
  nonce++;
  return random;
}
@saaqibz
Copy link

saaqibz commented Apr 20, 2021

I don't think the random number generator is necessarily safe. it could be manipulated by malicious miners.

@chrismtai
Copy link

not safe at all, use chainlink to generate random number.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment