Skip to content

Instantly share code, notes, and snippets.

@skozin
Created November 30, 2020 22:23
Show Gist options
  • Save skozin/b3e1f38bb31387ce3b8d023ddb9f7e33 to your computer and use it in GitHub Desktop.
Save skozin/b3e1f38bb31387ce3b8d023ddb9f7e33 to your computer and use it in GitHub Desktop.
Unstructured storage demo (array of value types)
pragma solidity 0.4.24;
contract ValueTypeArrayDemo {
bytes32 internal constant MEMBERS_ARRAY_POSITION = keccak256("org.test.storagedemo.members");
function getMember(uint256 _index) public view returns (address) {
return _getMember(_index, MEMBERS_ARRAY_POSITION);
}
function setMember(uint256 _index, address _address) public {
_setMember(_index, _address, MEMBERS_ARRAY_POSITION);
}
function pushMember(address _address) public {
_pushMember(_address, MEMBERS_ARRAY_POSITION);
}
function popMember() public returns (address member) {
return _popMember(MEMBERS_ARRAY_POSITION);
}
function getTotalMembers() public view returns (uint256 total) {
return _getTotalMembers(MEMBERS_ARRAY_POSITION);
}
function _getTotalMembers(bytes32 _membersSlot) internal view returns (uint256 total) {
assembly {
total := sload(_membersSlot)
}
}
function _getMember(uint256 _index, bytes32 _membersSlot) internal view returns (address member) {
assembly {
let len := sload(_membersSlot)
switch lt(_index, len)
case 1 {
// using scratch space
mstore(0, _membersSlot)
let position := add(keccak256(0, 32), _index)
member := sload(position)
}
case 0 {
member := 0
}
}
}
function _setMember(uint256 _index, address _address, bytes32 _membersSlot) internal {
assembly {
let len := sload(_membersSlot)
switch lt(_index, len)
case 1 {
// using scratch space
mstore(0, _membersSlot)
let position := add(keccak256(0, 32), _index)
sstore(position, _address)
}
case 0 {
revert(0, 0)
}
}
}
function _pushMember(address _address, bytes32 _membersSlot) internal {
uint256 newLen;
assembly {
newLen := add(sload(_membersSlot), 1)
sstore(_membersSlot, newLen)
}
_setMember(newLen - 1, _address, _membersSlot);
}
function _popMember(bytes32 _membersSlot) internal returns (address member) {
assembly {
let len := sload(_membersSlot)
switch lt(0, len)
case 1 {
let newLen := sub(len, 1)
sstore(_membersSlot, newLen)
// using scratch space
mstore(0, _membersSlot)
let position := add(keccak256(0, 32), newLen)
member := sload(position)
sstore(position, 0)
}
case 0 {
revert(0, 0)
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment