Eth中气体成本的增加和存储操作成本的增加(参见eip 2929)引发了另一项研究,即寻找更廉价的方法将数据压缩到单个存储槽(32字节)中,同时优化更便宜的负载。
我将在下面的答案中分享我自己的实验,但仍在寻找更好的解决方案。所以这是我的一个悬而未决的问题。
发布于 2020-10-07 12:35:31
参见下面的代码实验,将4个数字压缩到一个槽(int16、int112、int16、int112)。这些功能所使用的技术和气体产生的结果是:
正如你所看到的,对于单个负载+数据转移,气体成本仍然远远不是单一负荷成本(目前EVM为800 gas )。
contract CompressedData {
uint256 constant pow2_16 = 2 ** 16;
uint256 constant pow2_112 = 2 ** 112;
uint256 constant full112 = 2 ** 112 - 1;
uint256 constant full16 = 2 ** 16 - 1;
struct CompData {
int16 x1;
int112 y1;
int16 x2;
int112 y2;
}
mapping(uint => CompData) data;
mapping(uint => bytes32) decData;
constructor() public {
data[0].x1 = 1;
data[0].y1 = -1000;
data[0].x2 = 2;
data[0].y2 = -2000;
decData[0] = encodeData(11, -10, 21, -20);
decData[1] = encodeStepFunctionData(13, -13, 15, -15);
}
function getData (uint256 x) external view returns (int256, int256, int256, int256) {
// gas result according to remix: 1306
CompData storage pData = data[x];
return(pData.x1, pData.y1, pData.x2, pData.y2);
}
function getDataMem (uint256 x) external view returns (int256, int256, int256, int256) {
// gas result according to remix: 1681
CompData memory _data = data[x];
return(_data.x1, _data.y1, _data.x2, _data.y2);
}
function encodeData(int256 x1, int256 x2, int256 x3, int256 x4) public pure returns(bytes32 result) {
uint256 val;
val = uint256(x1) & full16;
val |= (uint256(x2) & full112) * pow2_16;
val |= (uint256(x3) & full16) * pow2_16 * pow2_112;
val |= (uint256(x4) & full112) * pow2_16 * pow2_112 * pow2_16;
return(bytes32(val));
}
function getDecData(uint256 x) external view returns (int256 x1, int256 y1, int256 x2, int256 y2) {
// gas result according to remix: 1298
uint256 val = uint256(decData[x]);
x1 = int256(int16(val));
y1 = int256(int112((val / pow2_16)));
x2 = int256(int16(val / (pow2_16 * pow2_112)));
y2 = int256(int112((val / (pow2_16 * pow2_112 * pow2_16))));
}
function getShiftDecData(uint256 x) external view returns (int256 x1, int256 y1, int256 x2, int256 y2) {
// gas result according to remix: 1258
uint256 val = uint256(decData[x]);
x1 = int256(int16(val));
y1 = int256(int112((val >> 16)));
x2 = int256(int16(val >> (16 + 112)));
y2 = int256(int112((val >> (16 + 112 + 16))));
}
function getDecodedAsm() external view returns (uint112 x1, int16 y1, uint112 x2, int16 y2){
// gas result according to remix: 1346
bytes memory tmp = abi.encodePacked(decData[1]); //assembly decoded data in slot 1
assembly {
x1 := mload(add(tmp, 14))
y1 := mload(add(tmp, 16))
x2 := mload(add(tmp, 30))
y2 := mload(add(tmp, 32))
}
}
function encodeStepFunctionData(uint112 x1, int16 y1, uint112 x2, int16 y2) public pure returns(bytes32 out) {
bytes memory _data = abi.encodePacked(x1, y1, x2, y2);
assembly {
// skip 1 slot for data.length
out := mload(add(_data, 32))
}
}}
https://ethereum.stackexchange.com/questions/88131
复制相似问题