3

Im calling a smart contract function that requires addresses, I only have these addresses as strings. How do I convert string to address in solidity?

5 Answers 5

2

In Solidity, an address is represented by a 20-byte value. You can convert a string that represents an Ethereum address to an address type using the address function. Here's an example:

function myFunction(string memory addressString) public {
  address myAddress = address(bytes20(bytes(addressString)));
  // Do something with myAddress
}

In this example, addressString is the string that represents an Ethereum address. The bytes(addressString) converts the string to a byte array, and bytes20 takes the first 20 bytes of that array. Finally, address casts the resulting 20-byte value as an Ethereum address.

Note that the input string must be a valid Ethereum address in order for this conversion to work properly. If the input string is not a valid Ethereum address, this code may result in an error.

Also, be aware that you may need to handle the possibility of invalid input strings in your contract code, either by validating the input before passing it to address, or by adding appropriate error handling code.

1

Answer by PSS does not seem to work for me. I am not getting the correct address back. But I am able to get the address back correctly using the following syntax address(0x33253420549e8E4a2Ea4061505BCFDBd288BA2f7) without any quotes

1

this is working perfectly for me. How to convert string into address.

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;


contract Check {
    
    address public pick;
    
     function toAddress(string calldata s) public  returns (address) {
        bytes memory _bytes = hexStringToAddress(s);
        require(_bytes.length >= 1 + 20, "toAddress_outOfBounds");
        address tempAddress;

        assembly {
            tempAddress := div(mload(add(add(_bytes, 0x20), 1)), 0x1000000000000000000000000)
        }

        pick = tempAddress;
    }
     function hexStringToAddress(string calldata s) public  returns (bytes memory) {
        bytes memory ss = bytes(s);
        require(ss.length%2 == 0); // length must be even
        bytes memory r = new bytes(ss.length/2);
        for (uint i=0; i<ss.length/2; ++i) {
            r[i] = bytes1(fromHexChar(uint8(ss[2*i])) * 16 +
                        fromHexChar(uint8(ss[2*i+1])));
        }

        return r;

    }

     function fromHexChar(uint8 c) public returns (uint8) {
        if (bytes1(c) >= bytes1('0') && bytes1(c) <= bytes1('9')) {
            return c - uint8(bytes1('0'));
        }
        if (bytes1(c) >= bytes1('a') && bytes1(c) <= bytes1('f')) {
            return 10 + c - uint8(bytes1('a'));
        }
        if (bytes1(c) >= bytes1('A') && bytes1(c) <= bytes1('F')) {
            return 10 + c - uint8(bytes1('A'));
        }
        return 0;
    }
}
0

TL;DR I do not have the correct answer, but it is not the accepted o

I was burnt a bit by the accepted answer as it contains an incorrect answer

Let us take a simple ERC20 contract:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";

contract Token is ERC20 {
    constructor(string memory name, string memory symbol) ERC20(name, symbol)  {
        _mint(msg.sender, 10000 * 10 ** decimals());
    }
}

Now we are going to write a test (I am using foundry)

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import "forge-std/Test.sol";
import "forge-std/console2.sol";
import "../src/Token.sol";

contract TokenTest is Test {
    Token public token;

    function setUp() public {
        token = new Token("Token", "TKN");
        console2.log("Token deployed to %s", address(token));
        // Token deployed to 0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f
    }

    function testAddressIsDifferent() public {
        address tokenAddr = address(bytes20(bytes("0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f")));
        assertNotEq(address(token), tokenAddr);
    }

    function testAddressTheSame() public {
        address tokenAddr = address(uint160(0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f));
        assertEq(address(token), tokenAddr);
    }
}

If we replace assertNotEq with assertEq we will get the following error.

[FAIL. Reason: assertion failed: 
0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f != 0x3078353631356445423739384242334534644661]
testAddressIsDifferent()

Luckily I have spent just a few hours and tested it on Sepolia :)

0

ChatGPT helped me get this right after the accepted answer failed. Here's the working solution:

pragma solidity ^0.8.0;

contract StringToAddress {

    function stringToAddress(string memory str) public pure returns (address) {
        bytes memory strBytes = bytes(str);
        require(strBytes.length == 42, "Invalid address length");
        bytes memory addrBytes = new bytes(20);

        for (uint i = 0; i < 20; i++) {
            addrBytes[i] = bytes1(hexCharToByte(strBytes[2 + i * 2]) * 16 + hexCharToByte(strBytes[3 + i * 2]));
        }

        return address(uint160(bytes20(addrBytes)));
    }

    function hexCharToByte(bytes1 char) internal pure returns (uint8) {
        uint8 byteValue = uint8(char);
        if (byteValue >= uint8(bytes1('0')) && byteValue <= uint8(bytes1('9'))) {
            return byteValue - uint8(bytes1('0'));
        } else if (byteValue >= uint8(bytes1('a')) && byteValue <= uint8(bytes1('f'))) {
            return 10 + byteValue - uint8(bytes1('a'));
        } else if (byteValue >= uint8(bytes1('A')) && byteValue <= uint8(bytes1('F'))) {
            return 10 + byteValue - uint8(bytes1('A'));
        }
        revert("Invalid hex character");
    }
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.