Access Control List

with Merkle Trees in Solidity

Roman Storm

I manage a consulting company that specializing in Dapp development and security audits of smart contracts.

https://poa.network

https://multisender.app

+
++
=
==

xyz://YourNextDapp.eth

Token Distribution
Strategies in Ethereum

PUSH 

PULL

VS
VSVS

Push Strategy

Step 2. Send tokens to those addresses

Step 1. Create a list of addresses with balances.

[
    "0xcF6Eb81256614C53a062fAB2Fc02Bb2FcC5c2Ffd": "1",
    "0x56A35D36B4B3Ab2F8c9C75a8b37B73C87D330457": "1",
    "0xd1DAb4f3629914d2865d6e45A6d6346C78cF5f94": "1",
    "0x60720BB7388734c8858d92fAb1560D3593525282": "1"
]

Limitations of PUSH:

  • Block gas limit = 8,000,000 on Ethereum mainnet

1 token transfer ~ 40k-150k gas(depends on transfer implementation)


this means we can only send from 50 to 200 ERC20 token transfers per block

10,000 tranfers = 50 transactions

tx cost = 5,000,000 gas * 20 gwei = 0.1 eth

Total: 50 txs * $23 = $1,150.00

USD tx cost @ 20 gwei gasPrice =  $23

1 eth = $230

Limitations of Push strategy

  • have to monitor all transactions to make sure nothing failed.​ 

Possible reasons for failure:

  • Low gas price(very long wait for tx to be mined)
  • Ran out of tokens to send

 

  • Sending a tx very close to block gas limit. Example: 7,999,999
  • out of gas

 

Push method can get the job done, and

1. Expensive

2. Tedious

3. Stressful

 

Lets look at a more efficient strategy:

Pull Strategy

Step 1. Create a list of addresses with balances and write it into smart contract
 

Step 2. Notify users in the permission list to claim their tokens

Simplistic approach

  • Hardcode all addresses and balances to the smart contract.

Choosing HOW you drive your Pull Strategy is critical

This is expensive, since you need to send large amounts of data to the smart contract on ethereum network.

This is not efficient.

Merkle Trees

are our friends

Merkle trees 

allow smart contracts 

to know about large amounts of data 

WITHOUT actually storing the data.

0x0039f22efb07a647557c7c5d17854cfd6d489ef3
10 tokens
0x0039f22efb07a647557c7c5d17854cfd6d489ef3
10 tokens

HASH FUNCTION

hash1

hash2

HASH FUNCTION

root hash

ROOT HASH=Hash( hash(h(S,M),h(A,H)) , hash(Craig Satoshi) )

1. Satoshi

2. Maxwell

3.Anderson

4. Hearn

Generating Proofs

5.Craig Satoshi

Hash (Satoshi)

Hash (Maxwell)

Hash (Anderson)

Hash (Hearn)

Hash (Craig Satoshi)

Hash(Satoshi, Maxwell)

Hash(Anderson, Hearn)

Hash(Hash(Satoshi, Maxwell), hash(Anderson, Hearn))

Proof in Solidity

function verify(
  bytes32[] proof,
  bytes32 root,
  bytes32 leaf
)
  internal
  pure
  returns (bool)
{
  bytes32 computedHash = leaf;

  for (uint256 i = 0; i < proof.length; i++) {
    bytes32 proofElement = proof[i];

    if (computedHash < proofElement) {
      computedHash = keccak256(abi.encodePacked(computedHash, proofElement));
    } else {
      computedHash = keccak256(abi.encodePacked(proofElement, computedHash));
    }
  }

  return computedHash == root;
}

What we learned today

Merkle trees are

https://multisender.app

https://rstormsf.github.io/merkleairdrop/

 

source code:
https://github.com/rstormsf/merkleairdrop

https://github.com/rstormsf/multisender

 

  • Efficient
  • cost optimized
  • easy to use

SAVE MONEY

Buy a trampoline

use merkle trees

have fun