-
Notifications
You must be signed in to change notification settings - Fork 2
/
ERC5018.sol
164 lines (143 loc) · 5.86 KB
/
ERC5018.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./IERC5018.sol";
import "./LargeStorageManager.sol";
import "./BlobStorageManager.sol";
contract ERC5018 is IERC5018, LargeStorageManager, BlobStorageManager {
enum StorageMode {
Uninitialized,
OnChain,
Blob
}
mapping(bytes32 => StorageMode) storageModes;
constructor(
uint8 slotLimit,
uint32 maxChunkSize,
address storageAddress
) LargeStorageManager(slotLimit) BlobStorageManager(maxChunkSize, storageAddress) {}
function getStorageMode(bytes memory name) public view returns (StorageMode) {
return storageModes[keccak256(name)];
}
function _setStorageMode(bytes memory name, StorageMode mode) internal {
storageModes[keccak256(name)] = mode;
}
// Large storage methods
function write(bytes memory name, bytes calldata data) public onlyOwner payable virtual override {
// TODO: support multiple chunks
return writeChunk(name, 0, data);
}
function read(bytes memory name) public view virtual override returns (bytes memory, bool) {
StorageMode mode = getStorageMode(name);
if (mode == StorageMode.Blob) {
return _getFromBlob(keccak256(name));
} else if (mode == StorageMode.OnChain) {
return _get(keccak256(name));
}
return (new bytes(0), false);
}
function size(bytes memory name) public view virtual override returns (uint256, uint256) {
StorageMode mode = getStorageMode(name);
if (mode == StorageMode.Blob) {
return _sizeFromBlob(keccak256(name));
} else if (mode == StorageMode.OnChain) {
return _size(keccak256(name));
}
return (0, 0);
}
function remove(bytes memory name) public virtual override onlyOwner returns (uint256) {
StorageMode mode = getStorageMode(name);
if (mode == StorageMode.Blob) {
return _removeFromBlob(keccak256(name), 0);
} else if (mode == StorageMode.OnChain) {
return _remove(keccak256(name), 0);
}
return 0;
}
function countChunks(bytes memory name) public view virtual override returns (uint256) {
StorageMode mode = getStorageMode(name);
if (mode == StorageMode.Blob) {
return _countChunksFromBlob(keccak256(name));
} else if (mode == StorageMode.OnChain) {
return _countChunks(keccak256(name));
}
return 0;
}
// Chunk-based large storage methods
function writeChunk(
bytes memory name,
uint256 chunkId,
bytes calldata data
) public payable onlyOwner virtual override {
StorageMode mode = getStorageMode(name);
require(mode == StorageMode.Uninitialized || mode == StorageMode.OnChain, "Invalid storage mode");
if (mode == StorageMode.Uninitialized) {
_setStorageMode(name, StorageMode.OnChain);
}
_putChunkFromCalldata(keccak256(name), chunkId, data, msg.value);
}
function writeChunks(
bytes memory name,
uint256[] memory chunkIds,
uint256[] memory sizes
) public onlyOwner override payable {
require(isSupportBlob(), "The current network does not support blob upload");
StorageMode mode = getStorageMode(name);
require(mode == StorageMode.Uninitialized || mode == StorageMode.Blob, "Invalid storage mode");
if (mode == StorageMode.Uninitialized) {
_setStorageMode(name, StorageMode.Blob);
}
_putChunks(keccak256(name), chunkIds, sizes);
}
function readChunk(bytes memory name, uint256 chunkId) public view virtual override returns (bytes memory, bool) {
StorageMode mode = getStorageMode(name);
if (mode == StorageMode.Blob) {
return _getChunkFromBlob(keccak256(name), chunkId);
} else if (mode == StorageMode.OnChain) {
return _getChunk(keccak256(name), chunkId);
}
return (new bytes(0), false);
}
function chunkSize(bytes memory name, uint256 chunkId) public view virtual override returns (uint256, bool) {
StorageMode mode = getStorageMode(name);
if (mode == StorageMode.Blob) {
return _chunkSizeFromBlob(keccak256(name), chunkId);
} else if (mode == StorageMode.OnChain) {
return _chunkSize(keccak256(name), chunkId);
}
return (0, false);
}
function removeChunk(bytes memory name, uint256 chunkId) public virtual onlyOwner override returns (bool) {
StorageMode mode = getStorageMode(name);
if (mode == StorageMode.Blob) {
return _removeChunkFromBlob(keccak256(name), chunkId);
} else if (mode == StorageMode.OnChain) {
return _removeChunk(keccak256(name), chunkId);
}
return false;
}
function truncate(bytes memory name, uint256 chunkId) public virtual onlyOwner override returns (uint256) {
StorageMode mode = getStorageMode(name);
if (mode == StorageMode.Blob) {
return _removeFromBlob(keccak256(name), chunkId);
} else if (mode == StorageMode.OnChain) {
return _remove(keccak256(name), chunkId);
}
return 0;
}
function refund() public onlyOwner override {
payable(owner()).transfer(address(this).balance);
}
function destruct() public onlyOwner override {
selfdestruct(payable(owner()));
}
function getChunkHash(bytes memory name, uint256 chunkId) public override view returns (bytes32) {
StorageMode mode = getStorageMode(name);
if (mode == StorageMode.Blob) {
return _getChunkHashFromBlob(keccak256(name), chunkId);
} else if (mode == StorageMode.OnChain) {
(bytes memory localData,) = readChunk(name, chunkId);
return keccak256(localData);
}
return 0;
}
}