Created
January 19, 2022 23:20
-
-
Save brockelmore/9fb8a3350b096b26e2e5d4952cbac515 to your computer and use it in GitHub Desktop.
Pushable array datatype for solidity
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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