Skip to content

Instantly share code, notes, and snippets.

@brockelmore
Created January 19, 2022 23:20
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save brockelmore/9fb8a3350b096b26e2e5d4952cbac515 to your computer and use it in GitHub Desktop.
Save brockelmore/9fb8a3350b096b26e2e5d4952cbac515 to your computer and use it in GitHub Desktop.
Pushable array datatype for solidity
// SPDX-License-Identifier: UNLICENSE
pragma solidity >=0.8.0 <0.9.0;
// NOT TESTED - USE AT YOUR OWN RISK
// Supports 32 byte word types. Could be easily extended to multiword types by
// passing in the size of the elements as well though
struct PushableArray {
bytes self;
}
library PushArray {
function newArray(uint8 len) internal pure returns (PushableArray memory s) {
assembly {
// grab free mem ptr
s := mload(0x40)
// update free mem ptr to 32*(len+2)+curr_free_memptr
mstore(0x40, add(s, mul(add(0x02, len), 0x20)))
mstore(add(0x20, s), len)
}
}
function push(PushableArray memory self, uint256 elem) internal pure {
assembly {
if eq(mload(self), mload(add(0x20, self))) {
revert (0,0)
}
mstore(
add(
self, // self + (2+curr_len)*32
mul(
add(0x02, mload(self)), // 2 + curr len * 32
0x20
)
), elem
)
mstore(self, add(0x01, mload(self)))
}
}
function push_unsafe(PushableArray memory self, uint256 elem) internal pure {
assembly {
mstore(add(self, mul(add(0x02, mload(self)), 0x20)), elem)
mstore(self, add(0x01, mload(self)))
}
}
function get(PushableArray memory self, uint8 i) internal pure returns (uint256 s) {
assembly {
s := mload(add(self, mul(0x20, add(0x02, i))))
}
}
}
contract Push {
using PushArray for PushableArray;
function t2() public returns (uint256){
PushableArray memory pa = PushArray.newArray(5);
// unsafe pushes
pa.push_unsafe(125);
pa.push_unsafe(126);
pa.push_unsafe(127);
pa.push_unsafe(128);
pa.push_unsafe(129);
// one more push *would not* revert
uint256 last = pa.get(4);
assert(last == 129);
return last;
}
function t() public returns (uint256){
PushableArray memory pa = PushArray.newArray(5);
// safe pushes
pa.push(125);
pa.push(126);
pa.push(127);
pa.push(128);
pa.push(129);
// one more push would revert
uint256 last = pa.get(4);
assert(last == 129);
return last;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment