Skip to content

Instantly share code, notes, and snippets.

@a2468834
Last active April 16, 2022 13:40
Show Gist options
  • Save a2468834/f6ed659a4727f40e570fdc13941b45b2 to your computer and use it in GitHub Desktop.
Save a2468834/f6ed659a4727f40e570fdc13941b45b2 to your computer and use it in GitHub Desktop.
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.1;
// The compiler does not reserve a storage slot for these variables.
uint256 constant dim1 = 36;
uint256 constant dim2 = 36;
uint256 constant dim = dim1 * dim2;
// Use the original "struct Cell"
contract CanvasV1 {
struct Cell {
address _user; // 20 bytes
string _color; // 32, 64,... bytes
uint256 _draw_time; // 32 bytes
}
Cell [dim2][dim1] private _canvas;
// getCanvas(0, 2): 110,416 gas
function getCanvas(uint8 start, uint8 end) public view returns (Cell [dim2][] memory) {
// The following two expressions also imply (start>=0) and (start<=end)
require(start < dim1);
require(end <= dim1);
uint8 size = end - start; // The size of slicing the first dimension
if(size == 0) {
return new Cell[dim2][](0);
}
else {
Cell[dim2][] memory output = new Cell[dim2][](size);
for(uint8 i; i < size; i++)
for(uint8 j; j < dim2; j++)
output[i][j] = _canvas[start + i][j];
return output;
}
}
}
// Use the storage layout efficiency "struct Cell"
contract CanvasV2A {
struct Cell {
address _user; // 20 B
bytes3 _color; // 3 B
uint72 _draw_time; // 9 B
}
Cell [dim2][dim1] private _canvas;
// getCanvas(0, 2): 64,465 gas
function getCanvas(uint8 start, uint8 end) public view returns (Cell [dim2][] memory) {
// The following two expressions also imply (start>=0) and (start<=end)
require(start < dim1);
require(end <= dim1);
uint8 size = end - start; // The size of slicing the first dimension
if(size == 0) {
return new Cell[dim2][](0);
}
else {
Cell[dim2][] memory output = new Cell[dim2][](size);
for(uint8 i; i < size; i++)
for(uint8 j; j < dim2; j++)
output[i][j] = _canvas[start + i][j];
return output;
}
}
}
// Use 1D array
contract CanvasV2B {
struct Cell {
address _user; // 20 B
bytes3 _color; // 3 B
uint72 _draw_time; // 9 B
}
Cell [dim] private _canvas;
// getCanvas(0, 2): 70,960 gas
function getCanvas(uint8 start, uint8 end) public view returns (Cell [] memory) {
// The following two expressions also imply (start>=0) and (start<=end)
require(start < dim1);
require(end <= dim1);
uint8 size = end - start; // The size of slicing the first dimension
if(size == 0) {
return new Cell[](0);
}
else {
Cell[] memory output = new Cell[](dim2 * size);
for(uint8 i; i < size; i++)
for(uint8 j; j < dim2; j++)
output[(dim2 * i) + j] = _canvas[dim2 * (start + i) + j];
return output;
}
}
}
contract CanvasV3 {
struct Cell {
address _user; // 20 B
bytes3 _color; // 3 B
uint72 _draw_time; // 9 B
}
uint64[dim2][dim1] private _canvas; // A 2D array of draw_id
mapping(uint64 => Cell) private _draw_info; // A mapping of (draw_id -> Cell)
function getDrawInfo(uint64 draw_id) public view returns (Cell memory) {
return _draw_info[draw_id];
}
function getCanvas() public view returns (uint64[dim2][dim1] memory) {
return _canvas;
}
function getCanvasSlice(uint8 start, uint8 end) public view returns (uint64[dim2][] memory) {
// The following two expressions also imply (start>=0) and (start<=end)
require(end <= dim1);
uint8 size = end - start; // The size of slicing the first dimension
if(size == 0) {
return new uint64[dim2][](0);
}
else {
uint64[dim2][] memory output = new uint64[dim2][](size);
for(uint8 i; i < size; i++)
for(uint8 j; j < dim2; j++)
output[i][j] = _canvas[start + i][j];
return output;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment