BytesLib.sol 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506
  1. // SPDX-License-Identifier: Unlicense
  2. /*
  3. * @title Solidity Bytes Arrays Utils
  4. * @author Gonçalo Sá <goncalo.sa@consensys.net>
  5. *
  6. * @dev Bytes tightly packed arrays utility library for ethereum contracts written in Solidity.
  7. * The library lets you concatenate, slice and type cast bytes arrays both in memory and storage.
  8. */
  9. pragma solidity >=0.5.0 <0.7.0;
  10. library BytesLib {
  11. function concat(
  12. bytes memory _preBytes,
  13. bytes memory _postBytes
  14. )
  15. internal
  16. pure
  17. returns (bytes memory)
  18. {
  19. bytes memory tempBytes;
  20. assembly {
  21. // Get a location of some free memory and store it in tempBytes as
  22. // Solidity does for memory variables.
  23. tempBytes := mload(0x40)
  24. // Store the length of the first bytes array at the beginning of
  25. // the memory for tempBytes.
  26. let length := mload(_preBytes)
  27. mstore(tempBytes, length)
  28. // Maintain a memory counter for the current write location in the
  29. // temp bytes array by adding the 32 bytes for the array length to
  30. // the starting location.
  31. let mc := add(tempBytes, 0x20)
  32. // Stop copying when the memory counter reaches the length of the
  33. // first bytes array.
  34. let end := add(mc, length)
  35. for {
  36. // Initialize a copy counter to the start of the _preBytes data,
  37. // 32 bytes into its memory.
  38. let cc := add(_preBytes, 0x20)
  39. } lt(mc, end) {
  40. // Increase both counters by 32 bytes each iteration.
  41. mc := add(mc, 0x20)
  42. cc := add(cc, 0x20)
  43. } {
  44. // Write the _preBytes data into the tempBytes memory 32 bytes
  45. // at a time.
  46. mstore(mc, mload(cc))
  47. }
  48. // Add the length of _postBytes to the current length of tempBytes
  49. // and store it as the new length in the first 32 bytes of the
  50. // tempBytes memory.
  51. length := mload(_postBytes)
  52. mstore(tempBytes, add(length, mload(tempBytes)))
  53. // Move the memory counter back from a multiple of 0x20 to the
  54. // actual end of the _preBytes data.
  55. mc := end
  56. // Stop copying when the memory counter reaches the new combined
  57. // length of the arrays.
  58. end := add(mc, length)
  59. for {
  60. let cc := add(_postBytes, 0x20)
  61. } lt(mc, end) {
  62. mc := add(mc, 0x20)
  63. cc := add(cc, 0x20)
  64. } {
  65. mstore(mc, mload(cc))
  66. }
  67. // Update the free-memory pointer by padding our last write location
  68. // to 32 bytes: add 31 bytes to the end of tempBytes to move to the
  69. // next 32 byte block, then round down to the nearest multiple of
  70. // 32. If the sum of the length of the two arrays is zero then add
  71. // one before rounding down to leave a blank 32 bytes (the length block with 0).
  72. mstore(0x40, and(
  73. add(add(end, iszero(add(length, mload(_preBytes)))), 31),
  74. not(31) // Round down to the nearest 32 bytes.
  75. ))
  76. }
  77. return tempBytes;
  78. }
  79. function concatStorage(bytes storage _preBytes, bytes memory _postBytes) internal {
  80. assembly {
  81. // Read the first 32 bytes of _preBytes storage, which is the length
  82. // of the array. (We don't need to use the offset into the slot
  83. // because arrays use the entire slot.)
  84. let fslot := sload(_preBytes_slot)
  85. // Arrays of 31 bytes or less have an even value in their slot,
  86. // while longer arrays have an odd value. The actual length is
  87. // the slot divided by two for odd values, and the lowest order
  88. // byte divided by two for even values.
  89. // If the slot is even, bitwise and the slot with 255 and divide by
  90. // two to get the length. If the slot is odd, bitwise and the slot
  91. // with -1 and divide by two.
  92. let slength := div(and(fslot, sub(mul(0x100, iszero(and(fslot, 1))), 1)), 2)
  93. let mlength := mload(_postBytes)
  94. let newlength := add(slength, mlength)
  95. // slength can contain both the length and contents of the array
  96. // if length < 32 bytes so let's prepare for that
  97. // v. http://solidity.readthedocs.io/en/latest/miscellaneous.html#layout-of-state-variables-in-storage
  98. switch add(lt(slength, 32), lt(newlength, 32))
  99. case 2 {
  100. // Since the new array still fits in the slot, we just need to
  101. // update the contents of the slot.
  102. // uint256(bytes_storage) = uint256(bytes_storage) + uint256(bytes_memory) + new_length
  103. sstore(
  104. _preBytes_slot,
  105. // all the modifications to the slot are inside this
  106. // next block
  107. add(
  108. // we can just add to the slot contents because the
  109. // bytes we want to change are the LSBs
  110. fslot,
  111. add(
  112. mul(
  113. div(
  114. // load the bytes from memory
  115. mload(add(_postBytes, 0x20)),
  116. // zero all bytes to the right
  117. exp(0x100, sub(32, mlength))
  118. ),
  119. // and now shift left the number of bytes to
  120. // leave space for the length in the slot
  121. exp(0x100, sub(32, newlength))
  122. ),
  123. // increase length by the double of the memory
  124. // bytes length
  125. mul(mlength, 2)
  126. )
  127. )
  128. )
  129. }
  130. case 1 {
  131. // The stored value fits in the slot, but the combined value
  132. // will exceed it.
  133. // get the keccak hash to get the contents of the array
  134. mstore(0x0, _preBytes_slot)
  135. let sc := add(keccak256(0x0, 0x20), div(slength, 32))
  136. // save new length
  137. sstore(_preBytes_slot, add(mul(newlength, 2), 1))
  138. // The contents of the _postBytes array start 32 bytes into
  139. // the structure. Our first read should obtain the `submod`
  140. // bytes that can fit into the unused space in the last word
  141. // of the stored array. To get this, we read 32 bytes starting
  142. // from `submod`, so the data we read overlaps with the array
  143. // contents by `submod` bytes. Masking the lowest-order
  144. // `submod` bytes allows us to add that value directly to the
  145. // stored value.
  146. let submod := sub(32, slength)
  147. let mc := add(_postBytes, submod)
  148. let end := add(_postBytes, mlength)
  149. let mask := sub(exp(0x100, submod), 1)
  150. sstore(
  151. sc,
  152. add(
  153. and(
  154. fslot,
  155. 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00
  156. ),
  157. and(mload(mc), mask)
  158. )
  159. )
  160. for {
  161. mc := add(mc, 0x20)
  162. sc := add(sc, 1)
  163. } lt(mc, end) {
  164. sc := add(sc, 1)
  165. mc := add(mc, 0x20)
  166. } {
  167. sstore(sc, mload(mc))
  168. }
  169. mask := exp(0x100, sub(mc, end))
  170. sstore(sc, mul(div(mload(mc), mask), mask))
  171. }
  172. default {
  173. // get the keccak hash to get the contents of the array
  174. mstore(0x0, _preBytes_slot)
  175. // Start copying to the last used word of the stored array.
  176. let sc := add(keccak256(0x0, 0x20), div(slength, 32))
  177. // save new length
  178. sstore(_preBytes_slot, add(mul(newlength, 2), 1))
  179. // Copy over the first `submod` bytes of the new data as in
  180. // case 1 above.
  181. let slengthmod := mod(slength, 32)
  182. let mlengthmod := mod(mlength, 32)
  183. let submod := sub(32, slengthmod)
  184. let mc := add(_postBytes, submod)
  185. let end := add(_postBytes, mlength)
  186. let mask := sub(exp(0x100, submod), 1)
  187. sstore(sc, add(sload(sc), and(mload(mc), mask)))
  188. for {
  189. sc := add(sc, 1)
  190. mc := add(mc, 0x20)
  191. } lt(mc, end) {
  192. sc := add(sc, 1)
  193. mc := add(mc, 0x20)
  194. } {
  195. sstore(sc, mload(mc))
  196. }
  197. mask := exp(0x100, sub(mc, end))
  198. sstore(sc, mul(div(mload(mc), mask), mask))
  199. }
  200. }
  201. }
  202. function slice(
  203. bytes memory _bytes,
  204. uint256 _start,
  205. uint256 _length
  206. )
  207. internal
  208. pure
  209. returns (bytes memory)
  210. {
  211. require(_bytes.length >= (_start + _length), "Read out of bounds");
  212. bytes memory tempBytes;
  213. assembly {
  214. switch iszero(_length)
  215. case 0 {
  216. // Get a location of some free memory and store it in tempBytes as
  217. // Solidity does for memory variables.
  218. tempBytes := mload(0x40)
  219. // The first word of the slice result is potentially a partial
  220. // word read from the original array. To read it, we calculate
  221. // the length of that partial word and start copying that many
  222. // bytes into the array. The first word we copy will start with
  223. // data we don't care about, but the last `lengthmod` bytes will
  224. // land at the beginning of the contents of the new array. When
  225. // we're done copying, we overwrite the full first word with
  226. // the actual length of the slice.
  227. let lengthmod := and(_length, 31)
  228. // The multiplication in the next line is necessary
  229. // because when slicing multiples of 32 bytes (lengthmod == 0)
  230. // the following copy loop was copying the origin's length
  231. // and then ending prematurely not copying everything it should.
  232. let mc := add(add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod)))
  233. let end := add(mc, _length)
  234. for {
  235. // The multiplication in the next line has the same exact purpose
  236. // as the one above.
  237. let cc := add(add(add(_bytes, lengthmod), mul(0x20, iszero(lengthmod))), _start)
  238. } lt(mc, end) {
  239. mc := add(mc, 0x20)
  240. cc := add(cc, 0x20)
  241. } {
  242. mstore(mc, mload(cc))
  243. }
  244. mstore(tempBytes, _length)
  245. //update free-memory pointer
  246. //allocating the array padded to 32 bytes like the compiler does now
  247. mstore(0x40, and(add(mc, 31), not(31)))
  248. }
  249. //if we want a zero-length slice let's just return a zero-length array
  250. default {
  251. tempBytes := mload(0x40)
  252. mstore(0x40, add(tempBytes, 0x20))
  253. }
  254. }
  255. return tempBytes;
  256. }
  257. function toAddress(bytes memory _bytes, uint256 _start) internal pure returns (address) {
  258. require(_bytes.length >= (_start + 20), "Read out of bounds");
  259. address tempAddress;
  260. assembly {
  261. tempAddress := div(mload(add(add(_bytes, 0x20), _start)), 0x1000000000000000000000000)
  262. }
  263. return tempAddress;
  264. }
  265. function toUint8(bytes memory _bytes, uint256 _start) internal pure returns (uint8) {
  266. require(_bytes.length >= (_start + 1), "Read out of bounds");
  267. uint8 tempUint;
  268. assembly {
  269. tempUint := mload(add(add(_bytes, 0x1), _start))
  270. }
  271. return tempUint;
  272. }
  273. function toUint16(bytes memory _bytes, uint256 _start) internal pure returns (uint16) {
  274. require(_bytes.length >= (_start + 2), "Read out of bounds");
  275. uint16 tempUint;
  276. assembly {
  277. tempUint := mload(add(add(_bytes, 0x2), _start))
  278. }
  279. return tempUint;
  280. }
  281. function toUint32(bytes memory _bytes, uint256 _start) internal pure returns (uint32) {
  282. require(_bytes.length >= (_start + 4), "Read out of bounds");
  283. uint32 tempUint;
  284. assembly {
  285. tempUint := mload(add(add(_bytes, 0x4), _start))
  286. }
  287. return tempUint;
  288. }
  289. function toUint64(bytes memory _bytes, uint256 _start) internal pure returns (uint64) {
  290. require(_bytes.length >= (_start + 8), "Read out of bounds");
  291. uint64 tempUint;
  292. assembly {
  293. tempUint := mload(add(add(_bytes, 0x8), _start))
  294. }
  295. return tempUint;
  296. }
  297. function toUint96(bytes memory _bytes, uint256 _start) internal pure returns (uint96) {
  298. require(_bytes.length >= (_start + 12), "Read out of bounds");
  299. uint96 tempUint;
  300. assembly {
  301. tempUint := mload(add(add(_bytes, 0xc), _start))
  302. }
  303. return tempUint;
  304. }
  305. function toUint128(bytes memory _bytes, uint256 _start) internal pure returns (uint128) {
  306. require(_bytes.length >= (_start + 16), "Read out of bounds");
  307. uint128 tempUint;
  308. assembly {
  309. tempUint := mload(add(add(_bytes, 0x10), _start))
  310. }
  311. return tempUint;
  312. }
  313. function toUint256(bytes memory _bytes, uint256 _start) internal pure returns (uint256) {
  314. require(_bytes.length >= (_start + 32), "Read out of bounds");
  315. uint256 tempUint;
  316. assembly {
  317. tempUint := mload(add(add(_bytes, 0x20), _start))
  318. }
  319. return tempUint;
  320. }
  321. function toBytes32(bytes memory _bytes, uint256 _start) internal pure returns (bytes32) {
  322. require(_bytes.length >= (_start + 32), "Read out of bounds");
  323. bytes32 tempBytes32;
  324. assembly {
  325. tempBytes32 := mload(add(add(_bytes, 0x20), _start))
  326. }
  327. return tempBytes32;
  328. }
  329. function equal(bytes memory _preBytes, bytes memory _postBytes) internal pure returns (bool) {
  330. bool success = true;
  331. assembly {
  332. let length := mload(_preBytes)
  333. // if lengths don't match the arrays are not equal
  334. switch eq(length, mload(_postBytes))
  335. case 1 {
  336. // cb is a circuit breaker in the for loop since there's
  337. // no said feature for inline assembly loops
  338. // cb = 1 - don't breaker
  339. // cb = 0 - break
  340. let cb := 1
  341. let mc := add(_preBytes, 0x20)
  342. let end := add(mc, length)
  343. for {
  344. let cc := add(_postBytes, 0x20)
  345. // the next line is the loop condition:
  346. // while(uint256(mc < end) + cb == 2)
  347. } eq(add(lt(mc, end), cb), 2) {
  348. mc := add(mc, 0x20)
  349. cc := add(cc, 0x20)
  350. } {
  351. // if any of these checks fails then arrays are not equal
  352. if iszero(eq(mload(mc), mload(cc))) {
  353. // unsuccess:
  354. success := 0
  355. cb := 0
  356. }
  357. }
  358. }
  359. default {
  360. // unsuccess:
  361. success := 0
  362. }
  363. }
  364. return success;
  365. }
  366. function equalStorage(
  367. bytes storage _preBytes,
  368. bytes memory _postBytes
  369. )
  370. internal
  371. view
  372. returns (bool)
  373. {
  374. bool success = true;
  375. assembly {
  376. // we know _preBytes_offset is 0
  377. let fslot := sload(_preBytes_slot)
  378. // Decode the length of the stored array like in concatStorage().
  379. let slength := div(and(fslot, sub(mul(0x100, iszero(and(fslot, 1))), 1)), 2)
  380. let mlength := mload(_postBytes)
  381. // if lengths don't match the arrays are not equal
  382. switch eq(slength, mlength)
  383. case 1 {
  384. // slength can contain both the length and contents of the array
  385. // if length < 32 bytes so let's prepare for that
  386. // v. http://solidity.readthedocs.io/en/latest/miscellaneous.html#layout-of-state-variables-in-storage
  387. if iszero(iszero(slength)) {
  388. switch lt(slength, 32)
  389. case 1 {
  390. // blank the last byte which is the length
  391. fslot := mul(div(fslot, 0x100), 0x100)
  392. if iszero(eq(fslot, mload(add(_postBytes, 0x20)))) {
  393. // unsuccess:
  394. success := 0
  395. }
  396. }
  397. default {
  398. // cb is a circuit breaker in the for loop since there's
  399. // no said feature for inline assembly loops
  400. // cb = 1 - don't breaker
  401. // cb = 0 - break
  402. let cb := 1
  403. // get the keccak hash to get the contents of the array
  404. mstore(0x0, _preBytes_slot)
  405. let sc := keccak256(0x0, 0x20)
  406. let mc := add(_postBytes, 0x20)
  407. let end := add(mc, mlength)
  408. // the next line is the loop condition:
  409. // while(uint256(mc < end) + cb == 2)
  410. for {} eq(add(lt(mc, end), cb), 2) {
  411. sc := add(sc, 1)
  412. mc := add(mc, 0x20)
  413. } {
  414. if iszero(eq(sload(sc), mload(mc))) {
  415. // unsuccess:
  416. success := 0
  417. cb := 0
  418. }
  419. }
  420. }
  421. }
  422. }
  423. default {
  424. // unsuccess:
  425. success := 0
  426. }
  427. }
  428. return success;
  429. }
  430. }