How to check Ethereum addresses in PHP

I am using PHP and curled up with json to communicate with my geth server.

I can do whatever I want except for one thing: validating the user-entered address according to the ethereum wallet format.

I've seen a javascript function here , but I'm mostly using PHP, I'm not into JS at all.

Any ideas on how to validate ethereum addresses in PHP?

+3


source to share


2 answers


Here's a PHP implementation for checking Ethereum address versus EIP 55 . For details on how this works, check out the comments.

<?php

use bb\Sha3\Sha3;

class EthereumValidator
{
    public function isAddress(string $address): bool
    {
        // See: https://github.com/ethereum/web3.js/blob/7935e5f/lib/utils/utils.js#L415
        if ($this->matchesPattern($address)) {
            return $this->isAllSameCaps($address) ?: $this->isValidChecksum($address);
        }

        return false;
    }

    protected function matchesPattern(string $address): int
    {
        return preg_match('/^(0x)?[0-9a-f]{40}$/i', $address);
    }

    protected function isAllSameCaps(string $address): bool
    {
        return preg_match('/^(0x)?[0-9a-f]{40}$/', $address) || preg_match('/^(0x)?[0-9A-F]{40}$/', $address);
    }

    protected function isValidChecksum($address)
    {
        $address = str_replace('0x', '', $address);
        // See: https://github.com/ethereum/web3.js/blob/b794007/lib/utils/sha3.js#L35
        $hash = Sha3::hash(strtolower($address), 256);

        // See: https://github.com/web3j/web3j/pull/134/files#diff-db8702981afff54d3de6a913f13b7be4R42
        for ($i = 0; $i < 40; $i++ ) {
            if (ctype_alpha($address{$i})) {
                // Each uppercase letter should correlate with a first bit of 1 in the hash char with the same index,
                // and each lowercase letter with a 0 bit.
                $charInt = intval($hash{$i}, 16);

                if ((ctype_upper($address{$i}) && $charInt <= 7) || (ctype_lower($address{$i}) && $charInt > 7)) {
                    return false;
                }
            }
        }

        return true;
    }
}

      

Dependencies



To verify checksum addresses, we need SHA3 , which is not yet supported by the built-in hash()

. You need to get into this pure PHP implementation to fulfill the above rule. It is not registered with Packagist, register the repo as a composer VCS repository .

There's also a PHP extension implementation that I don't feel right now.

+2


source


Basically, you can convert javascript to PHP completely. Here I was able to convert and test the code for checking the ethereum address in PHP.

/**
 * Checks if the given string is an address
 *
 * @method isAddress
 * @param {String} $address the given HEX adress
 * @return {Boolean}
*/
function isAddress($address) {
    if (!preg_match('/^(0x)?[0-9a-f]{40}$/i',$address)) {
        // check if it has the basic requirements of an address
        return false;
    } elseif (!preg_match('/^(0x)?[0-9a-f]{40}$/',$address) || preg_match('/^(0x)?[0-9A-F]{40}$/',$address)) {
        // If it all small caps or all all caps, return true
        return true;
    } else {
        // Otherwise check each case
        return isChecksumAddress($address);
    }
}

/**
 * Checks if the given string is a checksummed address
 *
 * @method isChecksumAddress
 * @param {String} $address the given HEX adress
 * @return {Boolean}
*/
function isChecksumAddress($address) {
    // Check each case
    $address = str_replace('0x','',$address);
    $addressHash = hash('sha3',strtolower($address));
    $addressArray=str_split($address);
    $addressHashArray=str_split($addressHash);

    for($i = 0; $i < 40; $i++ ) {
        // the nth letter should be uppercase if the nth digit of casemap is 1
        if ((intval($addressHashArray[$i], 16) > 7 && strtoupper($addressArray[$i]) !== $addressArray[$i]) || (intval($addressHashArray[$i], 16) <= 7 && strtolower($addressArray[$i]) !== $addressArray[$i])) {
            return false;
        }
    }
    return true;
}

      



Meanwhile, for those looking for a very simple regex to validate the epheration of an address (for example, to be used as an HTML field template attribute), this regex may suffice.

^(0x)?[0-9a-fA-F]{40}$

      

+6


source







All Articles