AddressValidity
Assertion whether a given string represents a valid address on an external blockchain.
Supported chains
BTC
(Bitcoin)DOGE
(Dogecoin)XRP
(XRP Ledger)- Test networks:
testBTC
(Bitcoin Testnet v3),testDOGE
,testXRP
Request
Field | Solidity Type | Description |
---|---|---|
addressStr | string | The address string to verify. |
Response
Field | Solidity Type | Description |
---|---|---|
isValid | bool | Indicates whether the provided address is valid. |
standardAddress | string | The standardized form of the validated address if isValid ; otherwise, an empty string. |
standardAddressHash | bytes32 | The keccak256 hash of the standardAddress if isValid ; otherwise, a zero bytes32 string. |
Verification process
The address is verified against the validity criteria specific to the chain identified by sourceId
. If the address meets all criteria:
isValid
is set totrue
.- The
standardAddress
and itsstandardAddressHash
are computed.
If the address is invalid:
isValid
is set tofalse
.- The
standardAddress
is empty andstandardAddressHash
is zero value.
For the lowestUsedTimestamp
parameter, the value 0xffffffffffffffff
(equivalent to ) in hexadecimal) is used as the default.
Address validity criteria
Bitcoin
An address on Bitcoin is derived from the locking script (pkscript
).
Only standard locking scripts get assigned an address.
There are two formats of the Bitcoin addresses, Base58
and Bech32(m)
.
The format is determined based on the type of locking script.
Base58
Bitcoin's Base58 format uses the following encoding dictionary:
123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz
Address Structure
Decoded addresses have the format:
<leadingByte><hash><checksum>
Components
leadingByte
:- On mainnet:
00
for Pay-to-PubKey (p2pk) and Pay-to-PubKey-Hash (p2pkh)05
for Pay-to-Script-Hash (p2sh)
- On testnet:
6f
for p2pk and p2pkhc4
for p2sh
- On mainnet:
hash
: Represents either the public key, hash of the public key, or hash of a script.checksum
: The first four bytes of the double SHA-256 hash of<leadingByte><hash>
.
Validation Criteria
- Address contains only characters from the Base58 dictionary.
- Decoded hexadecimal form is exactly 25 bytes long (address length varies between 26 to 34 characters).
- Starts with a valid
leadingByte
. - The checksum is valid and matches the first four bytes of the double SHA-256 hash.
Resources
Bech32(m)
Bech32 is a newer address format using the character set:
qpzry9x8gf2tvdw0s3jn54khce6mua7l
Address Structure
A Bech32 address has the following components:
- Human-Readable Part (HRP):
bc
for mainnettb
for testnet
- Separator: Always
1
- Data Part:
- The first character indicates the witness version (0-16).
- The last six characters form a checksum.
The checksum differs based on the witness version:
Validation Criteria
- Address contains only characters from the Bech32 dictionary.
- All non-numeric characters must be either entirely uppercase or lowercase.
- Starts with a valid HRP followed by the separator (
1
). - Length is between 14 to 74 characters, with the length modulo 8 being 0, 3, or 5.
- For witness version
0
, length must be 42 or 62 characters.
- For witness version
- Checksum is validated based on the witness version.
- Addresses with witness versions
2
and above are unsupported and invalid.
Resources
Dogecoin (Base58
)
Dogecoin uses a Base58 dictionary, identical to Bitcoin's:
123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz
Address Structure
Decoded addresses have the format:
<leadingByte><hash><checksum>
Components
leadingByte
:- On mainnet:
1e
for p2pk and p2pkh16
for p2sh
- On testnet:
6f
for p2pk and p2pkh71
for p2sh
- On mainnet:
hash
: Represents either the public key, hash of the public key, or script hash.checksum
: First four bytes of the double SHA-256 hash of<leadingByte><hash>
.
Validation Criteria
- Address contains only characters from the Base58 dictionary.
- Length is 26 to 34 characters. Decoded hex form is 25 bytes.
- Valid leading byte:
- Mainnet: Starts with
D
,A
, or9
. - Testnet: Starts with
n
,m
, or2
.
- Mainnet: Starts with
- The checksum is validated.
XRPL (Base58
)
The XRP Ledger uses a custom Base58 dictionary:
rpshnaf39wBUDNEGHJKLM4PQRST7VWXYZ2bcdeCg65jkm8oFqi1tuvAxyz
Address Structure
Decoded to hexadecimal:
<leadingByte><publicKeyHash><checksum>
Components
leadingByte
:- On mainnet:
00
(addresses start withr
).
- On mainnet:
publicKeyHash
: A 20-byte hash of the public key.checksum
: The first four bytes of the double SHA-256 hash of<leadingByte><publicKeyHash>
.
Validation Criteria
- Address contains only characters from the XRPL Base58 dictionary.
- Length is 25 to 35 characters. Decoded hex form is 25 bytes.
- Address starts with
r
. - The checksum is valid.
Resources
Contract interface
Sourced from IAddressValidity.sol
on GitHub.
// SPDX-License-Identifier: MIT
pragma solidity >=0.7.6 <0.9;
/**
* @custom:name IAddressValidity
* @custom:id 0x05
* @custom:supported BTC, DOGE, XRP
* @author Flare
* @notice An assertion whether a string represents a valid address on an external chain.
* @custom:verification The address is checked against all validity criteria of the chain with `sourceId`.
* Indicator of validity is provided.
* If the address is valid, its standard form and standard hash are computed.
* Validity criteria for each supported chain:
* - [BTC](/specs/attestations/external-chains/address-validity/BTC.md)
* - [DOGE](/specs/attestations/external-chains/address-validity/DOGE.md)
* - [XRPL](/specs/attestations/external-chains/address-validity/XRPL.md)
* @custom:lut `0xffffffffffffffff` ($2^{64}-1$ in hex)
* @custom:lutlimit `0xffffffffffffffff`, `0xffffffffffffffff`, `0xffffffffffffffff`
*/
interface IAddressValidity {
/**
* @notice Toplevel request
* @param attestationType ID of the attestation type.
* @param sourceId Id of the data source.
* @param messageIntegrityCode `MessageIntegrityCode` that is derived from the expected response.
* @param requestBody Data defining the request. Type and interpretation is determined by the `attestationType`.
*/
struct Request {
bytes32 attestationType;
bytes32 sourceId;
bytes32 messageIntegrityCode;
RequestBody requestBody;
}
/**
* @notice Toplevel response
* @param attestationType Extracted from the request.
* @param sourceId Extracted from the request.
* @param votingRound The ID of the State Connector round in which the request was considered.
* @param lowestUsedTimestamp The lowest timestamp used to generate the response.
* @param requestBody Extracted from the request.
* @param responseBody Data defining the response. The verification rules for the construction of the
* response body and the type are defined per specific `attestationType`.
*/
struct Response {
bytes32 attestationType;
bytes32 sourceId;
uint64 votingRound;
uint64 lowestUsedTimestamp;
RequestBody requestBody;
ResponseBody responseBody;
}
/**
* @notice Toplevel proof
* @param merkleProof Merkle proof corresponding to the attestation response.
* @param data Attestation response.
*/
struct Proof {
bytes32[] merkleProof;
Response data;
}
/**
* @notice Request body for IAddressValidity attestation type
* @param addressStr Address to be verified.
*/
struct RequestBody {
string addressStr;
}
/**
* @notice Response body for IAddressValidity attestation type
* @param isValid Boolean indicator of the address validity.
* @param standardAddress If `isValid`, standard form of the validated address. Otherwise an empty string.
* @param standardAddressHash If `isValid`, standard address hash of the validated address.
* Otherwise a zero bytes32 string.
*/
struct ResponseBody {
bool isValid;
string standardAddress;
bytes32 standardAddressHash;
}
}