1

I wrote a small contract that is supposed to generate an address from a given publicKey.

pragma solidity ^0.8.0;

contract GenerateAddress { bytes public publicKey = "6d7bac197da6e91f506db699a1844efc93b9bf5508bacb6870a98fc2137c4330741f94af61aa635a44f9059ff2082737d43cfb376124ae8772250b85f656aa1d";

function generateAddress() public view returns (address addr) {
    bytes32 publicKeyHash = keccak256(publicKey);
    addr = address(bytes20(publicKeyHash));
    return addr;
}

}

The public key in question was generated from this page: Ethereum Address Generator (Been using it for years to get some test addresses etc.)

Generate ETH address

So I hard-coded the publicKey I got from there to test my simple contract.

However the address I got is 0x70191eCc889463533ea48C3A666e7eE0692a0087 while the Ethereum Address Generator returns 0xdf92c554c0078eec90937d7a5944976ef31d602c as valid address (For the same public key)

Basically, I get different address for identical publicKey and I would like to understand what am I doing wrong.

Sky
  • 2,282
  • 2
  • 7
  • 26

2 Answers2

2

In your smart contract there are some issues:

  • When you're calculating the account hash you must pass your public key like hexedecimal value. In your case, you're executing this operation with the literal value.
  • For calculating account address, you must take the 20 bytes == 40 characters from the ending of hash public key value (in your case publicKeyHash). With this statement, address(bytes20(publicKeyHash)); you're taking 40 characters from the variable beginning.

To fix this issues, I modified your smart contract in this way and put some notes:

pragma solidity ^0.8.0;

contract GenerateAddress { // NOTE: With hex before the value, Solidity compiler takes this value in hexadecimal value bytes public publicKey = hex"6d7bac197da6e91f506db699a1844efc93b9bf5508bacb6870a98fc2137c4330741f94af61aa635a44f9059ff2082737d43cfb376124ae8772250b85f656aa1d";

function generateAddress() public view returns (address addr) {
    bytes32 publicKeyHash = keccak256(publicKey);
    // NOTE: I take the last 40 characters from the end of publicKeyHash variable 
    //       and convert them into address.
    addr = address(uint160(uint256(publicKeyHash)));
    return addr;
}

}

Sky
  • 2,282
  • 2
  • 7
  • 26
Antonio Carito
  • 2,445
  • 3
  • 10
  • 23
  • Thanks, I already solved this issue, but I got caught up on something else, so I forgot to answer to accept an answer. Your explanation is good, but some details/numbers are off, so I will edit your answer to fix it. Hope that is ok with you. – Sky Jan 11 '23 at 13:42
  • 1
    Sure, we should always improve answers to make them helpful to other users that they have the same issue or doubt – Antonio Carito Jan 11 '23 at 15:10
  • hex"" != bytes("") – liquan.eth Apr 17 '23 at 13:36
1

addr = address(bytes20(publicKeyHash)); is taking the first 20 bytes - for an address you need the last 20

also, solidity is taking publicKey as a string and converting it to bytes (using utf-8 encoding). you need to save it as a hexadecimal number (or convert it to bytes first, then hardcode it)

Edit: the answer here explains it in full - Compute address of public key string in Solidity