#!/bin/sh # Re-reads BMNR's figures on Robinhood Chain and compares them with what pegproof read # at block 106694507. It only makes eth_calls: read-only, nothing is signed or sent. # Needs curl and bc. To ask another Robinhood Chain node: PEGPROOF_RPC=https://your-node sh verify.sh RPC_URL=https://rpc.mainnet.chain.robinhood.com if [ -n "$PEGPROOF_RPC" ]; then RPC_URL=$PEGPROOF_RPC; fi TOKEN=0x9a7842eded60b0fe1e03eec342c82a397c821ed0 BLOCK=106694507 BLOCK_HEX=0x65c076b DIFFERENT=0 UNCHECKED=0 for tool in curl bc; do if ! command -v "$tool" >/dev/null 2>&1; then echo "This script needs $tool, which is not installed here. Nothing was checked." >&2 exit 2 fi done # eth_call TO DATA: the hex digits of the result, without 0x; nothing on an error. eth_call() { curl -s "$RPC_URL" -H 'content-type: application/json' \ -d "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"eth_call\",\"params\":[{\"to\":\"$1\",\"data\":\"$2\"},\"$BLOCK_HEX\"]}" \ | tr -d ' \r\n' | sed -n 's/.*"result":"0x\([0-9a-fA-F]*\)".*/\1/p' } # word HEX N: the N-th 32-byte word of HEX, counting from 0. word() { printf '%s' "$1" | cut -c "$(($2 * 64 + 1))-$(($2 * 64 + 64))" } # dec HEX: the unsigned decimal value of HEX; nothing for nothing. dec() { if [ -z "$1" ]; then return 0; fi printf 'ibase=16; %s\n' "$(printf '%s' "$1" | tr 'abcdef' 'ABCDEF')" | bc | tr -d '\\\n' } # amount EXPR: EXPR evaluated by bc, on one line, with the leading zero bc leaves out (.5 -> 0.5). amount() { printf '%s\n' "$1" | bc | tr -d '\\\n' | sed 's/^\./0./; s/^-\./-0./' } # compare NAME PEGPROOF CHAIN: no answer from the node is NOT CHECKED, never DIFFERS. compare() { got=$3 if [ -z "$got" ]; then got='(no answer: the call failed, or the node has no state at this block)' verdict='NOT CHECKED'; UNCHECKED=1 elif [ "$2" = "$3" ]; then verdict=MATCH else verdict=DIFFERS; DIFFERENT=1 fi printf '%s\n pegproof read: %s\n chain says: %s\n %s\n\n' "$1" "$2" "$got" "$verdict" } CHAIN=$(curl -s "$RPC_URL" -H 'content-type: application/json' -d '{"jsonrpc":"2.0","id":1,"method":"eth_chainId","params":[]}' | tr -d ' \r\n' | sed -n 's/.*"result":"\(0x[0-9a-fA-F]*\)".*/\1/p') case "$CHAIN" in 0x1237) ;; '') echo "No answer from $RPC_URL to eth_chainId. Nothing was checked." >&2; exit 2 ;; *) echo "$RPC_URL is not Robinhood Chain (chain id $CHAIN, expected 0x1237). Nothing was checked." >&2; exit 2 ;; esac echo "Token $TOKEN at block $BLOCK, asking $RPC_URL" echo SUPPLY=$(dec "$(word "$(eth_call "$TOKEN" 0x18160ddd)" 0)") compare 'totalSupply()' 4193688450000000000000 "$SUPPLY" MULT=$(dec "$(word "$(eth_call "$TOKEN" 0xa60bf13d)" 0)") compare 'uiMultiplier()' 1000000000000000000 "$MULT" if [ -n "$SUPPLY" ] && [ -n "$MULT" ]; then RAW=$(amount "$SUPPLY * $MULT / 10^18") printf '%s %s\n' "Shares outstanding, from the chain's values:" "$(amount "scale=2; $RAW / 10^18")" fi echo if [ "$DIFFERENT" = 1 ]; then echo "Some values differ. Your node returned something other than what pegproof read at block $BLOCK." exit 1 elif [ "$UNCHECKED" = 1 ]; then echo "Some values could not be checked: the node gave no answer. It may be rate-limiting, or have no state at block $BLOCK (older blocks may need an archive node)." exit 2 else echo "All values match what pegproof read at block $BLOCK." fi