Coinmonks
Published in

Coinmonks

Photo by Florian Olivo on Unsplash

Implement a Pseudo-Random Number Generator in 26 bytes smart contract

Immortal := keccak256(Immortal XOR blockhash(block.number - 32))

What is the point here?

How could this proposal help?

Randomness := RPNGResult XOR OracleResult

Implementation

; EVM Assembly The Divine by Chiro Hiro <chiro8x@gmail.com>PUSH1 0x20
RETURNDATASIZE
CALLER
ORIGIN
XOR
PUSH1 0x0a
JUMPI
REVERT
JUMPDEST
DUP2
DUP2
DUP1
SLOAD
DUP3
NUMBER
SUB
BLOCKHASH
XOR
DUP2
MSTORE
SHA3
DUP2
SSTORE
RETURN
  • PUSH1 0x20 push 0x20 to the top of the stack
  • RETURNDATASIZE push 0x00 to stack, because we didn’t perform any call then its result is 0x00 . It’s cheaper thanPUSH1 0x00
  • CALLER push msg.sender to sack
  • ORIGIN push tx.origin to stack
  • XOR consume two items on the top of the stack and pushing the result msg.sender xor tx.origin to stack
  • PUSH1 0x0a push JUMPDEST to stack
  • JUMPI consume two items on the top of the stack, if msg.sender == tx.origin do REVERT otherwise, jump to JUMPDEST
  • DUP2 duplicate the 2nd item in the stack
  • DUP2 duplicate the 2nd item in the stack
  • DUP1 duplicate the item on the top stack, our stack would look like this [0x00,0x00,0x20,0x00,0x20], we assume that the top of the stack in the left.
  • SLOAD load storage at index 0x00 return immortal on the top of the stack
  • DUP3 we used DUP3 to duplicate 0x20 since BLOCKHASH can’t perform with current block, the idea is we perform it on 32nd older block.
  • NUMBER return current block height block.number to stack
  • SUB consume two value on the top of the stack then push block.number - 32 to stack
  • BLOCKHASH get block hash of block.number - 32 push to stack, blockhash and immortal are on the top of the stack
  • XOR EVM has wordsize is of 256 bits so we better use XOR to combine two 256 bits values instead of performing con cat in the memory. After this step blockhash xor imomrtal will be on the top of the stack.
  • DUP2 will duplicate 0x00 , now 0x00 is on top of the stack
  • MSTORE assign memory memory[0, 32] = blockhash xor imomrtal , stack right now[0x00,0x20,0x00,0x20]
  • SHA3 compute the digest of value in the memory at[0x00:0x20] then push the result to the stack
  • DUP2 duplicate 0x00 value in stack, the stack is [0x00,keccak256(blockhash xor immortal),0x00,0x20]
  • SSTORE consume two items on the top of the stack and overwrite immortal at 0x00
  • RETURN consume two last items in the stack and leave.
Output:
60203d333218600a57fd5b8181805482430340188152208155f3
Tx deploy data:
601a803d90600a8239f360203d333218600a57fd5b8181805482430340188152208155f3

Conclusion

  • We prevent normal address to trigger PRNG
  • Code was optimized to minimal gas consumption
  • Each call cost around 5190 gas, mostly from SLOAD andSSTORE
  • This code work on any EVM
  • The more the other contracts use this PRNG the less chance for an adversary to predict or manipulate the result

--

--

Coinmonks (http://coinmonks.io/) is a non-profit Crypto Educational Publication. Follow us on Twitter @coinmonks and Our other project —  https://coincodecap.com, Email  — gaurav@coincodecap.com

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store