Ethereum Address


Ethereum addresses are composed of the prefix "0x", a common identifier for hexadecimal, concatenated with the rightmost 20 bytes of the Keccak-256 hash (big endian) of the ECDSA public key (the curve used is the so-called secp256k1, the same as Bitcoin)

There are 2 types of account in ETH network, externally owned account (EOA) and contract account. Remember account just simply mean an address.

Externally owned account (EOA)

  • Controlled by private key.
  • Has ETH balance state

Contract account

  • No private key, controlled by codes written in contract.
  • Has ETH balance state
  • Has associated code and state of variables declared in contract.
  • Learn more about Smart Contract.


EOA Address Generator

<?php 
use kornrunner\Keccak;
use BitWasp\Bitcoin\Key\Factory\PrivateKeyFactory;
use BitWasp\Bitcoin\Crypto\Random\Random;

include_once "../libraries/vendor/autoload.php";
include_once("html_iframe_header.php");

function toChecksumAddress($address) 
{
	
	$address = strtolower(str_replace('0x', '', $address));
	$hash = Keccak::hash(strtolower($address), 256);
	$checksumAddress = '0x';
	
	for($i=0;$i<strlen($address);$i++) {
		
		if (intval($hash{$i}, 16) > 7) {
			$checksumAddress .= strtoupper($address{$i});
		} else {
			$checksumAddress .= $address{$i};
		}
	}
	
	return $checksumAddress;
	
}

if ($_SERVER['REQUEST_METHOD'] == 'POST') {
    try {
       
        $privKeyFactory = new PrivateKeyFactory();

        if (!$_POST['input'] OR ctype_xdigit($_POST['input'])) 
        {
            if (!$_POST['input']) 
            { 
                $rbg = new Random();
                $privateKey = $privKeyFactory->generateUncompressed($rbg);
                
            } else {
                
                $privateKey = $privKeyFactory->fromHexUncompressed($_POST['input']);
            }
        } 
       
		$publicKey = $privateKey->getPublicKey();
		$publicKey = substr($publicKey->getHex(), 2);
		$madeUpEthAddress = $publicKey;
		
		$hash = Keccak::hash(hex2bin($madeUpEthAddress), 256);
		// Ethereum address has 20 bytes length. (40 hex characters long)
		// We only need the last 20 bytes as Ethereum address
		$ethAddress = toChecksumAddress('0x' . substr($hash, -40));
		
    ?>
        <div class="table-responsive">
            <table border=0 class='table'>
                <tr style='background-color:#f0f0f0'><td>Address</td><td><?php echo $ethAddress?></td></tr>
                <tr><td>Private Key Hex</td><td><?php echo $privateKey->getHex()?></td></tr>               
                <tr style='background-color:#f0f0f0'><td>Public Key Hex</td><td><?php echo $publicKey?></td></tr>
            </table>
        </div>
<?php 
    } catch (Exception $e) {
        $errmsg .= "Problem found. " . $e->getMessage();

    }
} 

if ($errmsg) {
?>
    <div class="alert alert-danger">
        <strong>Error!</strong> <?php echo $errmsg?>
    </div>
<?php
}
?>
<form action='' method='post'>
    <div class="form-group">
        <label for="input">Private Key (Hex):</label>
        <input class="form-control" type='text' name='input' id='input' value='<?php echo $_POST['input']?>'>
        <small>Put empty if you want system assign you a random private key.</small>
    </div>
   
    <input type='submit' class="btn btn-success btn-block"/>
</form>
<?php
include_once("html_iframe_footer.php");
go/eth_address_form.go

package main

import (
	"errors"
	"github.com/ethereum/go-ethereum/crypto"
	"github.com/ethereum/go-ethereum/common/hexutil"
	"github.com/ethereum/go-ethereum/crypto/secp256k1"
	"crypto/ecdsa"
	"math/big"
)

func generateKeyAndAddress(privateKeyHex string) (map[string]string,  error) {
	var thisError error 
	response := make(map[string]string)
	var privateKey *ecdsa.PrivateKey
	
	
	if len(privateKeyHex) == 0 {
		
		if retPrivateKey, retError := crypto.GenerateKey(); retError != nil {
			thisError = errors.New("Key generation fail")
		} else {
			privateKey = retPrivateKey
		}
	} else {
		var pri ecdsa.PrivateKey
		var retBool bool
		if pri.D, retBool = new(big.Int).SetString(privateKeyHex,16); retBool == true {
			
			pri.PublicKey.Curve = secp256k1.S256()
			pri.PublicKey.X, pri.PublicKey.Y = pri.PublicKey.Curve.ScalarBaseMult(pri.D.Bytes())
			
			privateKey = &pri
		} else {
			thisError = errors.New("Hex input not valid")
		}
	}
	
	if (thisError == nil) {
		privateKeyBytes := crypto.FromECDSA(privateKey)	
		publicKey := privateKey.Public()
		
		if publicKeyECDSA, isPublicKeyType := publicKey.(*ecdsa.PublicKey); isPublicKeyType == true {
			
			address := crypto.PubkeyToAddress(*publicKeyECDSA).Hex()
			
			publicKeyBytes := crypto.FromECDSAPub(publicKeyECDSA)
			
			response["publicKey"] = hexutil.Encode(publicKeyBytes)[4:]
			response["privateKey"] = hexutil.Encode(privateKeyBytes)[2:]
			response["address"] = address
		} else {
			thisError = errors.New("Public key generation fail");
		}
	}
	
	return response, thisError
}

go/templates/eth_address_form.html

{{ template "html_iframe_header.html" .}}

{{if .error}}
	<div class="alert alert-danger">
        <strong>Error!</strong> {{ .error }}
    </div>
{{else if .address}}
	<div class="table-responsive">
		<table border=0 class='table'>
			<tr style='background-color:#f0f0f0'><td>Address</td><td>{{ .address }}</td></tr>
			<tr><td>Private Key Hex</td><td>{{ .privateKey }}</td></tr>               
			<tr style='background-color:#f0f0f0'><td>Public Key Hex</td><td>{{ .publicKey }}</td></tr>
		</table>
	</div>
{{end}}
 
<form action='' method='post'>
    <div class="form-group">
        <label for="input">Private Key (Hex):</label>
        <input class="form-control" type='text' name='input' id='input' value='{{ .input }}'>
        <small>Put empty if you want system assign you a random private key.</small>
    </div>
   
    <input type='submit' class="btn btn-success btn-block"/>
</form>

{{ template "html_iframe_footer.html" .}}

Address Validator

Address checksum was described in EIP-55.

<?php 
use kornrunner\Keccak;

include_once "../libraries/vendor/autoload.php";
include_once("html_iframe_header.php");

class EthAddressValidator
{
	private $addressValid = false;
	private $address = "";
	
	function __construct(string $address) 
	{
		$this->address = $address;
		if ($this->isPatternMatched()) {
			if (!$this->isAllSameCaps()) {
				$this->addressValid = $this->isValidChecksum();	
			} else {
				$this->addressValid = true;
			}
        }
	}
	
    public function isValidAddress(): bool
    {	
        return $this->addressValid;
    }
	
    protected function isPatternMatched(): int
    {
        return preg_match('/^(0x)?[0-9a-f]{40}$/i', $this->address);
    }

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

    protected function isValidChecksum(): bool
    {
        $address = str_replace('0x', '', $this->address);
        $hash = Keccak::hash(strtolower($address), 256);

        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;
    }
}

if ($_SERVER['REQUEST_METHOD'] == 'POST') {
   
    $validator = new EthAddressValidator($_POST['address']);
	
	if ($validator->isAllSameCaps() === true) {
	?>
		<div class="alert alert-info">
			<strong>Notice!</strong> Address pattern valid but checksum cannot be verified.
		</div>
	<?php 
	} else if ($validator->isValidAddress() === true) {
?>
		<div class="alert alert-success">
			<strong>Success!</strong> Checksum validation was passed.
		</div>
<?php
	} else {
?>
		<div class="alert alert-danger">
			<strong>Error!</strong> Invalid address.
		</div>	
<?php	
	}
}
?>
<form action='' method='post'>
    <div class="form-group">
        <label for="address">Address:</label>
        <input class="form-control" type='text' name='address' id='address' value='<?php echo $_POST['address']?>'>
    </div>
   
    <input type='submit' class="btn btn-success btn-block"/>
</form>
<?php
include_once("html_iframe_footer.php");
go/eth_address_validator.go

package main

import (
	"github.com/ethereum/go-ethereum/common"
)

func isValidAddress(address string) (map[string]string,  error) {
	
	response := make(map[string]string)
	addressObj, thisError := common.NewMixedcaseAddressFromString(address);
	response["checkSum"] = "na"
	if thisError == nil {
		if addressObj.ValidChecksum() {
			response["checkSum"] = "valid"
		} else {
			response["checkSum"] = "invalid"
		}
	}
	
	return response, thisError
}

go/templates/eth_address_validator.html

{{ template "html_iframe_header.html" .}}

{{if .error}}
	<div class="alert alert-danger">
        <strong>Error!</strong> {{ .error }}
    </div>
{{end}}

{{if .checkSum }}
	{{if eq .checkSum "valid"}}
		<div class="alert alert-success">
			<strong>Success!</strong> Checksum validation was passed.
		</div>
	{{else if eq .checkSum "invalid"}}
		<div class="alert alert-info">
			<strong>Notice!</strong> Address pattern valid but checksum cannot be verified.
		</div>
	{{end}}
{{end}}
 
<form action='' method='post'>
    <div class="form-group">
        <label for="address">Address:</label>
        <input class="form-control" type='text' name='address' id='address' value='{{ .address }}'>
    </div>
   
    <input type='submit' class="btn btn-success btn-block"/>
</form>

{{ template "html_iframe_footer.html" .}}

Contract Address Generator

Contract address will be auto generated (without private key) when contract-type tx publish to ETH network.

<?php 
use kornrunner\Keccak;
use Web3p\RLP\RLP;

include_once "../libraries/vendor/autoload.php";
include_once("html_iframe_header.php");

if ($_SERVER['REQUEST_METHOD'] == 'POST') {
    try {
       
        $rlp = new RLP;
		$normalizedAddress = "0x" . ltrim($_POST['address'], "0x");
		
		$encoded = $rlp->encode([$normalizedAddress, (int)$_POST['nonce']]);
		$hash = Keccak::hash(hex2bin($encoded->toString('hex')), 256);
		$ethAddress = '0x' . substr($hash, -40);
		
    ?>
       
		<div class="alert alert-success">
			<strong>Success!</strong> <?php echo $ethAddress?>
		</div>
<?php 
    } catch (Exception $e) {
        $errmsg .= "Problem found. " . $e->getMessage();

    }
} 

if ($errmsg) {
?>
    <div class="alert alert-danger">
        <strong>Error!</strong> <?php echo $errmsg?>
    </div>
<?php
}
?>
<form action='' method='post'>
    <div class="form-group">
        <label for="address">Sender Address:</label>
        <input class="form-control" type='text' name='address' id='address' value='<?php echo $_POST['address']?>'>
    </div>
	
	<div class="form-group">
        <label for="nonce">Nonce:</label>
        <input class="form-control" type='text' name='nonce' id='nonce' value='<?php echo $_POST['nonce']?>'>
    </div>
   
    <input type='submit' class="btn btn-success btn-block"/>
</form>
<?php
include_once("html_iframe_footer.php");	
go/eth_contract_address_form.go

package main

import(
	"github.com/ethereum/go-ethereum/rlp"
	"strconv"
	"github.com/ethereum/go-ethereum/common"
	"github.com/ethereum/go-ethereum/common/hexutil"
	"github.com/ethereum/go-ethereum/crypto"
)

func genContractAddress(addressHex string, nonceStr string) (map[string]string, error) {
	var thisError error 
	
	response := make(map[string]string)
	
	if nonce, err1 := strconv.ParseUint(nonceStr, 10, 64 /*uint64*/); err1 == nil {
		address := common.HexToAddress(addressHex)
	
		if rlpBytes, err2 := rlp.EncodeToBytes([]interface{}{address, nonce}); err2 == nil {
			hashBytes := crypto.Keccak256Hash(rlpBytes)
			response["ethAddress"] = hexutil.Encode(hashBytes[12:])
			
		} else {
			thisError = err2
		}
	} else {
		thisError = err1
	}
	 
	return response, thisError
}

go/templates/eth_contract_address_form.html

{{ template "html_iframe_header.html" .}}


{{if .error}}
	<div class="alert alert-danger">
        <strong>Error!</strong> {{ .error }}
    </div>
{{else if .ethAddress}}
	<div class="alert alert-success">
		<strong>Success!</strong> {{.ethAddress}}
	</div>
{{end}}

<form action='' method='post'>
    <div class="form-group">
        <label for="address">Sender Address:</label>
        <input class="form-control" type='text' name='address' id='address' value='{{.address}}'>
    </div>
	
	<div class="form-group">
        <label for="nonce">Nonce:</label>
        <input class="form-control" type='text' name='nonce' id='nonce' value='{{.nonce}}'>
    </div>
   
    <input type='submit' class="btn btn-success btn-block"/>
</form>

{{ template "html_iframe_footer.html" .}}

How To Determine Address Type?

You can call JSON-RPC with getcode method. if the address is representing an EOA you will get 0x as response otherwise you will get the contract's bytecode.

<?php 

include_once "../libraries/vendor/autoload.php";
$hosts = ["https://mainnet.infura.io"=>"https://mainnet.infura.io","https://ropsten.infura.io"=>"https://ropsten.infura.io", "https://cloudflare-eth.com"=>"https://cloudflare-eth.com"];
$blockParams = ['pending'=>'Pending','latest'=>'Latest', 'earliest'=>'Earliest'];

include_once("html_iframe_header.php");
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
	try {
		
		if (!in_array($_POST['host'], array_keys($hosts))) {
			throw new Exception("Please provide valid host.");
		}
		
		$url = $_POST['host'] . "/" . $_POST['path'];
		
		$ch = curl_init();
		$requestId = time();
		
		$params = [];
		$params['jsonrpc']= "2.0";
		$params['method'] = 'eth_getCode';
		$params['params'] = [$_POST['address'],$_POST['blockparam']];
		$params['id'] = $requestId;
	
		curl_setopt($ch, CURLOPT_URL,$url);
		curl_setopt($ch, CURLOPT_POST, 1);
		curl_setopt($ch, CURLOPT_POSTFIELDS,$req = json_encode($params));
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
		curl_setopt($ch, CURLOPT_HTTPHEADER, ["Content-Type: application/json"]);

		$resp = curl_exec($ch);
		
		if ($resp === false) {
			throw new Exception("curl_exec return false");
		}
		
		if (strlen($err = @curl_error($ch)) > 0) {
			$errno = @curl_errno($ch);
			throw new Exception( "{$err} ({$errno})" );
		}
		
		$result = json_decode($resp,true); 
		if ($result['id'] != $requestId) {
			throw new Exception("Invalid request id.");
		}
		$result = $result['result'];
		
		curl_close ($ch);
		
		?>
		<div class="alert alert-success">
			<h6 class="mt-3">Host</h6>
			<textarea class="form-control" rows="1" readonly><?php echo $url;?></textarea>
			
			<h6 class="mt-3">JSON-RPC Request</h6>
			<textarea class="form-control" rows="5" id="comment" readonly><?php echo $req;?></textarea>
			
			<h6 class="mt-3">JSON-RPC Response</h6>
			<textarea class="form-control" rows="1" id="comment" readonly><?php echo $resp;?></textarea>
			
			
			
			<?Php
			if ($result) {
			?>
			<h6 class="mt-3">Result</h6>
			<?php			
				if ($result == '0x' or $result == '0x0') {
					echo "{$_POST['address']} is EOA address.";
				} else if (substr($result,0,2) == '0x' AND strlen($result) >= 3) {
					echo "{$_POST['address']} is contract address.";
				}
			}
			?>
		</div>
		<?php
	} catch (Exception $e) {
		$errmsg .= "Problem found. " . $e->getMessage();
	}
} 

if ($errmsg) {
?>
    <div class="alert alert-danger">
        <strong>Error!</strong> <?php echo $errmsg?>
    </div>
<?php
}

?>
<form id='this_form' action='?action=submit' method='post'>

	<div class="form-group">
		<label for="host">Host To Receive RPC:</label>
		
		<div class="input-group mb-3">
			<select id="host" name="host" class="form-control" >
			<?php
			foreach($hosts as $k=>$v) {
				echo "<option value='{$k}'".($k == $_POST['host'] ? " selected": "").">{$v}</option>";
			}
			?>
			</select>
			<div class="input-group-append">
				<span class="input-group-text">
					/
				</span>
			</div>
			
			<input class="form-control" type='text' name='path' id='path' value='<?php echo $_POST['path']?>' placeholder="Put extra path or blank if it does not.">
			
		</div>
	</div>
	
	<div class="form-group">
		<label for="blockparam">Block Parameter:</label>
		<select id="blockparam" name="blockparam" class="form-control" >
			<?php
			foreach($blockParams as $k=>$v) {
				echo "<option value='{$k}'".($k == $_POST['blockparam'] ? " selected": "").">{$v}</option>";
			}
			?>
		</select>
	</div>
	
	<div class="form-group">
        <label for="address">Address:</label>
        <input class="form-control" type='text' name='address' id='address' value='<?php echo $_POST['address']?>'>
    </div>
		
    <input type='submit' class="btn btn-success btn-block"/>
</form>
<?php
include_once("html_iframe_footer.php");








Tutorials
About Us
Contents have been open source in GITHUB. Please give me a ⭐ if you found this helpful :)
Community
Problem? Raise me a new issue.
Support Us
Buy me a coffee. so i can spend more nights for this :)

BTCSCHOOLS would like to present you with more pratical but little theory throughout our tutorials. Pages' content are constantly keep reviewed to avoid mistakes, but we cannot warrant correctness of all contents. While using this site, you agree to accept our terms of use, cookie & privacy policy. Copyright 2019 by BTCSCHOOLS. All Rights Reserved.