Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to validate an Ethereum address PHP / Laravel?

How can I check if the Ethereum address from Laravel input is valid in terms of format?

like image 282
Hitesh Patel Avatar asked Oct 20 '25 08:10

Hitesh Patel


1 Answers

Here's a Laravel custom validation rule for validating Ethereum addresses against the EIP 55 specification. For details of how it works, please go through the comments.

<?php

namespace App\Rules;

use kornrunner\Keccak; // composer require greensea/keccak
use Illuminate\Contracts\Validation\Rule;

class ValidEthereumAddress implements Rule
{
    /**
     * @var Keccak
     */
    protected $hasher;

    public function __construct(Keccak $hasher)
    {
        $this->keccak = $hasher;
    }

    public function passes($attribute, $value)
    {
        // See: https://github.com/ethereum/web3.js/blob/7935e5f/lib/utils/utils.js#L415
        if ($this->matchesPattern($value)) {
            return $this->isAllSameCaps($value) ?: $this->isValidChecksum($value);
        }

        return false;
    }

    public function message()
    {
        return 'The :attribute must be a valid Ethereum address.';
    }

    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);
        $hash = $this->keccak->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 validate checksum addresses, we need a Keccac implementation in place which is not supported by the built-in hash() function. You need to require this pure PHP implementation for the above rule to work.

like image 69
sepehr Avatar answered Oct 21 '25 22:10

sepehr



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!