Skip to content

Instantly share code, notes, and snippets.

@sydneyitguy
Created January 8, 2020 16:42
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sydneyitguy/39b85cb9d67b434a0773067c50c9bdaf to your computer and use it in GitHub Desktop.
Save sydneyitguy/39b85cb9d67b434a0773067c50c9bdaf to your computer and use it in GitHub Desktop.
Ethereum address validation and normalization in Ruby
# Extracted from https://github.com/se3000/ruby-eth
#
# Dependencies:
# - gem 'digest-sha3'
# - gem 'rlp'
#
# Usage:
# - Eth::Utils.valid_address?('0x4Db7569F90bd836294B11c8b08B853d2de499Ced')
# => true
# - Eth::Utils.format_address('0x4db7569f90bd836294b11c8b08b853d2de499ced')
# => 0x4Db7569F90bd836294B11c8b08B853d2de499Ced
module Eth
module Utils
extend self
def prefix_hex(hex)
hex.match(/\A0x/) ? hex : "0x#{hex}"
end
def bin_to_hex(string)
RLP::Utils.encode_hex string
end
def remove_hex_prefix(s)
s[0,2].downcase == '0x' ? s[2..-1] : s
end
def keccak256(x)
Digest::SHA3.new(256).digest(x)
end
def valid_address?(address)
Address.new(address).valid?
end
def format_address(address)
Address.new(address).checksummed
end
end
class Address
def initialize(address)
@address = Utils.prefix_hex(address)
end
def valid?
if !matches_any_format?
false
elsif not_checksummed?
true
else
checksum_matches?
end
end
def checksummed
raise "Invalid address: #{address}" unless matches_any_format?
cased = unprefixed.chars.zip(checksum.chars).map do |char, check|
check.match(/[0-7]/) ? char.downcase : char.upcase
end
Utils.prefix_hex(cased.join)
end
private
attr_reader :address
def checksum_matches?
address == checksummed
end
def not_checksummed?
all_uppercase? || all_lowercase?
end
def all_uppercase?
address.match(/(?:0[xX])[A-F0-9]{40}/)
end
def all_lowercase?
address.match(/(?:0[xX])[a-f0-9]{40}/)
end
def matches_any_format?
address.match(/\A(?:0[xX])[a-fA-F0-9]{40}\z/)
end
def checksum
Utils.bin_to_hex(Utils.keccak256 unprefixed.downcase)
end
def unprefixed
Utils.remove_hex_prefix address
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment