1use alloy_primitives::{keccak256, Address};
4use elliptic_curve::sec1::ToEncodedPoint;
5use k256::ecdsa::{SigningKey, VerifyingKey};
6
7#[inline]
9pub fn secret_key_to_address(secret_key: &SigningKey) -> Address {
10 public_key_to_address(secret_key.verifying_key())
11}
12
13#[inline]
15pub fn public_key_to_address(pubkey: &VerifyingKey) -> Address {
16 let affine = pubkey.as_ref();
17 let encoded = affine.to_encoded_point(false);
18 raw_public_key_to_address(&encoded.as_bytes()[1..])
19}
20
21#[inline]
33#[track_caller]
34pub fn raw_public_key_to_address(pubkey: &[u8]) -> Address {
35 assert_eq!(pubkey.len(), 64, "raw public key must be 64 bytes");
36 let digest = keccak256(pubkey);
37 Address::from_slice(&digest[12..])
38}
39
40#[cfg(test)]
41mod tests {
42 use super::*;
43 use alloy_primitives::hex;
44
45 #[test]
47 fn test_public_key_to_address() {
48 let addr = "0Ac1dF02185025F65202660F8167210A80dD5086".parse::<Address>().unwrap();
49
50 let pubkey = VerifyingKey::from_sec1_bytes(
52 &hex::decode("0376698beebe8ee5c74d8cc50ab84ac301ee8f10af6f28d0ffd6adf4d6d3b9b762")
53 .unwrap(),
54 )
55 .unwrap();
56 assert_eq!(public_key_to_address(&pubkey), addr);
57
58 let pubkey= VerifyingKey::from_sec1_bytes(&hex::decode("0476698beebe8ee5c74d8cc50ab84ac301ee8f10af6f28d0ffd6adf4d6d3b9b762d46ca56d3dad2ce13213a6f42278dabbb53259f2d92681ea6a0b98197a719be3").unwrap()).unwrap();
60 assert_eq!(public_key_to_address(&pubkey), addr);
61 }
62
63 #[test]
64 fn test_raw_public_key_to_address() {
65 let addr = "0Ac1dF02185025F65202660F8167210A80dD5086".parse::<Address>().unwrap();
66
67 let pubkey_bytes = hex::decode("76698beebe8ee5c74d8cc50ab84ac301ee8f10af6f28d0ffd6adf4d6d3b9b762d46ca56d3dad2ce13213a6f42278dabbb53259f2d92681ea6a0b98197a719be3").unwrap();
68
69 assert_eq!(raw_public_key_to_address(&pubkey_bytes), addr);
70 }
71
72 #[test]
73 #[should_panic]
74 fn test_raw_public_key_to_address_panics() {
75 raw_public_key_to_address(&[]);
76 }
77}