[Ethereum] How to concatenate uint to address in solidity

go-ethereumremixsoliditystring

I would like to concatenate an Ethereum address to an uint in Solidity. How can I do that?

Best Answer

You have not specified which base you want each operand represented by (for example, decimal base for the uint operand and hexadecimal base for the address operand), so here are the likely options:

pragma solidity 0.6.12;

contract MyContract {
    function concatDecDec(uint256 x, address y) external pure returns (string memory) {
        return string(abi.encodePacked(itod(x), itod(uint256(y))));
    }

    function concatDecHex(uint256 x, address y) external pure returns (string memory) {
        return string(abi.encodePacked(itod(x), itoh(uint256(y))));
    }

    function concatHexDec(uint256 x, address y) external pure returns (string memory) {
        return string(abi.encodePacked(itoh(x), itod(uint256(y))));
    }

    function concatHexHex(uint256 x, address y) external pure returns (string memory) {
        return string(abi.encodePacked(itoh(x), itoh(uint256(y))));
    }

    function itod(uint256 x) private pure returns (string memory) {
        if (x > 0) {
            string memory str;
            while (x > 0) {
                str = string(abi.encodePacked(uint8(x % 10 + 48), str));
                x /= 10;
            }
            return str;
        }
        return "0";
    }

    function itoh(uint256 x) private pure returns (string memory) {
        if (x > 0) {
            string memory str;
            while (x > 0) {
                str = string(abi.encodePacked(uint8(x % 16 + (x % 16 < 10 ? 48 : 87)), str));
                x /= 16;
            }
            return str;
        }
        return "0";
    }
}

Note that when executed in a transaction (i.e., from a non-constant contract function), each one of these functions may yield a relatively high gas-cost.


Here is a Truffle test of the contract above:

const MyContract = artifacts.require('MyContract');

const UINT256 = '99999999';
const ADDRESS = '0x1234567812345678123456781234567812345678';

contract('test', () => {
    it('test', async () => {
        const myContract = await MyContract.new();
        const resultDecDec = await myContract.concatDecDec(UINT256, ADDRESS);
        const resultDecHex = await myContract.concatDecHex(UINT256, ADDRESS);
        const resultHexDec = await myContract.concatHexDec(UINT256, ADDRESS);
        const resultHexHex = await myContract.concatHexHex(UINT256, ADDRESS);
        assert.equal(resultDecDec, web3.utils.toBN(UINT256).toString(10) + web3.utils.toBN(ADDRESS).toString(10));
        assert.equal(resultDecHex, web3.utils.toBN(UINT256).toString(10) + web3.utils.toBN(ADDRESS).toString(16));
        assert.equal(resultHexDec, web3.utils.toBN(UINT256).toString(16) + web3.utils.toBN(ADDRESS).toString(10));
        assert.equal(resultHexHex, web3.utils.toBN(UINT256).toString(16) + web3.utils.toBN(ADDRESS).toString(16));
    });
});