How to convert a uint to bytes in Solidity?

Is there an easy way to convert a uint to bytes in Solidity?

The alternative to @eth's answer is to use assembly:

function toBytes(uint256 x) returns (bytes b) {
b = new bytes(32);
assembly { mstore(add(b, 32), x) }
}

This is significantly more gas-efficient, but depends on the internal memory layout used by the Solidity compiler. In theory, this can change in future, but in practice it should be fairly stable.

Here's a comparison of the gas used in the three methods by @NickJohnson, @Eth and @k26dr. I've added a constant to the function modifiers as these functions do not alter the blockchain:

pragma solidity ^0.4.2;

contract Test {
function toBytesNickJohnson(uint256 x) constant returns (bytes b) {
b = new bytes(32);
assembly { mstore(add(b, 32), x) }
}

function toBytesEth(uint256 x) constant returns (bytes b) {
b = new bytes(32);
for (uint i = 0; i < 32; i++) {
b[i] = byte(uint8(x / (2**(8*(31 - i)))));
}
}

function toBytesNicolasMassart(uint256 x) constant returns (bytes c) {
bytes32 b = bytes32(x);
c = new bytes(32);
for (uint i=0; i < 32; i++) {
c[i] = b[i];
}
}
}

You can see the gas cost of running these functions in Remix (Solidity Browser): There are no easy ways to convert anything to bytes. Here's a function:

function toBytes(uint256 x) returns (bytes b) {
b = new bytes(32);
for (uint i = 0; i < 32; i++) {
b[i] = byte(uint8(x / (2**(8*(31 - i)))));
}
}

Based on Solidity Gitter chat.

If you're overly concerned about gas we can improve on @NickJohnson answer too.

function toBytes(uint _num) returns (bytes _ret) {
assembly {
mstore(_ret, 0x20)
}
}

This will shave approximately a further 15% off the gas cost, just be careful that you're not using that memory for something else as 0x10 is a direct reference to memory.

Also, if you want to copy an 8bit int to byte here's an alternative which only uses half the gas cost:

function toByte(uint8 _num) returns (byte _ret) {
assembly {
mstore8(0x20, _num)
}
}

Again, be mindful that 0x20 is another direct memory reference and in all honesty with this one I would stick with

function toByte(uint8 _num) returns (byte _ret) {
return byte(_num);
}

The gas price between the two was almost identical, but the functional ASM was undercutting it by about 70 wei

Edit: If you're concerned about overwriting memory you could use:

let m_alloc := add(msize(),0x1)

Instead of referencing memory yourself

• I didn't know msize() can be used to increase the memory allocation by adding to it. The solidity assembly document (solidity.readthedocs.io/en/v0.4.24/…) is very brief. Is there a better reference document out there? – Thomas Jul 20 '18 at 23:04
• msize doesn't, it returns the highest point in memory and you simply state that you want to write to msize() plus 1. Here's another stack page where I explain it in more detail ethereum.stackexchange.com/questions/9537/… – James Lockhart Jul 23 '18 at 16:20

You can convert to bytes32 then convert to bytes:

uint u = 200;
bytes32 b = bytes32(u);
bytes memory c = new bytes(32);
for (uint i=0; i < 32; i++) {
c[i] = b[i];
}

You can avoid padding the bytes array with 0's with the toBytes implementations by determining the scriptNumSize

function scriptNumSize(uint256 i) public view returns (uint256) {
if      (i > 0x7fffffff) { return 5; }
else if (i > 0x7fffff  ) { return 4; }
else if (i > 0x7fff    ) { return 3; }
else if (i > 0x7f      ) { return 2; }
else if (i > 0x00      ) { return 1; }
else                     { return 0; }
}

function toBytes(uint256 x) public view returns (bytes memory b) {
uint a = scriptNumSize(x);
b = new bytes(a);
for (uint i = 0; i < a; i++) {
b[i] = byte(uint8(x / (2**(8*(a - 1 - i)))));
}
}

For example uint 1563384765 would return 0x5d2f5bbd not 0x000000000000000000000000000000000000000000000000000000005d2f5bbd

This was written specifically for timestamps. If you want larger numbers you can add more if cases.