尝试在 Solidity 中将地址字符串转换为类型地址

问题描述 投票:0回答:2

我正在尝试将地址字符串转换为实体地址类型,但是当我这样做时

    function StringToBytes(string memory _str) public pure returns (bytes memory) {
        return bytes(_str);
        
    }
    function StringToBytesLength(string memory _str) public pure returns (uint256) {
        return bytes(_str).length;
        
    }

StringToBytes 的结果给了我 42 ,理想情况下应该给我 20 。如果我在 python 中尝试同样的事情,即将 string 转换为 bytes ,它会给我 20 个字节,这是以太坊地址的长度(以字节为单位)。我找到了几种将地址字符串转换为地址类型的解决方案,但它们都不适用于 Solidity 0.7 版本。 请帮忙。

ethereum solidity
2个回答
0
投票

我想要一个解决方案,但它不是最优的,我正在寻找一个gas费更便宜的解决方案,它现在消耗77492。


    function fromHexChar(uint8 c) public pure 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;
    }
    
    function hexStringToAddress(string calldata s) public pure 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 toAddress(string calldata s) public pure 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)
        }

        return tempAddress;
    }

0
投票
pragma solidity ^0.8.0;

contract StringToAddress {

function stringToAddress(string memory _address) public pure returns (address) {
    string memory cleanAddress = remove0xPrefix(_address);
    bytes20 _addressBytes = parseHexStringToBytes20(cleanAddress);
    return address(_addressBytes);
}

function remove0xPrefix(string memory _hexString) internal pure returns (string memory) {
    if (bytes(_hexString).length >= 2 && bytes(_hexString)[0] == '0' && (bytes(_hexString)[1] == 'x' || bytes(_hexString)[1] == 'X')) {
        return substring(_hexString, 2, bytes(_hexString).length);
    }
    return _hexString;
}

function substring(string memory _str, uint256 _start, uint256 _end) internal pure returns (string memory) {
    bytes memory _strBytes = bytes(_str);
    bytes memory _result = new bytes(_end - _start);
    for (uint256 i = _start; i < _end; i++) {
        _result[i - _start] = _strBytes[i];
    }
    return string(_result);
}

function parseHexStringToBytes20(string memory _hexString) internal pure returns (bytes20) {
    bytes memory _bytesString = bytes(_hexString);
    uint160 _parsedBytes = 0;
    for (uint256 i = 0; i < _bytesString.length; i += 2) {
        _parsedBytes *= 256;
        uint8 _byteValue = parseByteToUint8(_bytesString[i]);
        _byteValue *= 16;
        _byteValue += parseByteToUint8(_bytesString[i + 1]);
        _parsedBytes += _byteValue;
    }
    return bytes20(_parsedBytes);
}

function parseByteToUint8(bytes1 _byte) internal pure returns (uint8) {
    if (uint8(_byte) >= 48 && uint8(_byte) <= 57) {
        return uint8(_byte) - 48;
    } else if (uint8(_byte) >= 65 && uint8(_byte) <= 70) {
        return uint8(_byte) - 55;
    } else if (uint8(_byte) >= 97 && uint8(_byte) <= 102) {
        return uint8(_byte) - 87;
    } else {
        revert(string(abi.encodePacked("Invalid byte value: ", _byte)));
    }
}
}
© www.soinside.com 2019 - 2024. All rights reserved.